From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from lists.gentoo.org (pigeon.gentoo.org [208.92.234.80]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by finch.gentoo.org (Postfix) with ESMTPS id ABEA71581C1 for ; Sat, 6 Jul 2024 05:41:49 +0000 (UTC) Received: from pigeon.gentoo.org (localhost [127.0.0.1]) by pigeon.gentoo.org (Postfix) with SMTP id D3B8B2BC0A5; Sat, 6 Jul 2024 05:41:48 +0000 (UTC) Received: from smtp.gentoo.org (woodpecker.gentoo.org [140.211.166.183]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by pigeon.gentoo.org (Postfix) with ESMTPS id A2E012BC0A5 for ; Sat, 6 Jul 2024 05:41:48 +0000 (UTC) Received: from oystercatcher.gentoo.org (oystercatcher.gentoo.org [148.251.78.52]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by smtp.gentoo.org (Postfix) with ESMTPS id 69BBB335D72 for ; Sat, 6 Jul 2024 05:41:47 +0000 (UTC) Received: from localhost.localdomain (localhost [IPv6:::1]) by oystercatcher.gentoo.org (Postfix) with ESMTP id C10253A1 for ; Sat, 6 Jul 2024 05:41:45 +0000 (UTC) From: "Sam James" To: gentoo-commits@lists.gentoo.org Content-Transfer-Encoding: 8bit Content-type: text/plain; charset=UTF-8 Reply-To: gentoo-dev@lists.gentoo.org, "Sam James" Message-ID: <1720244472.a58e3aa65a34cf2f8be43eaeb9c1414308b1a347.sam@gentoo> Subject: [gentoo-commits] repo/gentoo:master commit in: media-video/pipewire/files/1.2.0/, media-video/pipewire/ X-VCS-Repository: repo/gentoo X-VCS-Files: media-video/pipewire/files/1.2.0/0001-impl-node-fix-required-state-for-async-driver-nodes.patch media-video/pipewire/files/1.2.0/0002-module-raop-only-set-softVolume-when-valid.patch media-video/pipewire/files/1.2.0/0003-context-Fix-node-collect-with-groups-and-sync-enable.patch media-video/pipewire/files/1.2.0/0004-impl-node-disable-async-for-driver-nodes.patch media-video/pipewire/files/1.2.0/0005-impl-node-set-INACTIVE-state-on-server.patch media-video/pipewire/pipewire-1.2.0-r1.ebuild media-video/pipewire/pipewire-1.2.0-r2.ebuild X-VCS-Directories: media-video/pipewire/ media-video/pipewire/files/1.2.0/ X-VCS-Committer: sam X-VCS-Committer-Name: Sam James X-VCS-Revision: a58e3aa65a34cf2f8be43eaeb9c1414308b1a347 X-VCS-Branch: master Date: Sat, 6 Jul 2024 05:41:45 +0000 (UTC) Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-Id: Gentoo Linux mail X-BeenThere: gentoo-commits@lists.gentoo.org X-Auto-Response-Suppress: DR, RN, NRN, OOF, AutoReply X-Archives-Salt: 910a0433-64b5-4c84-881f-bf5e8d044ef4 X-Archives-Hash: f51418b857f0f3352181c6060e8e6beb commit: a58e3aa65a34cf2f8be43eaeb9c1414308b1a347 Author: Sam James gentoo org> AuthorDate: Sat Jul 6 05:40:51 2024 +0000 Commit: Sam James gentoo org> CommitDate: Sat Jul 6 05:41:12 2024 +0000 URL: https://gitweb.gentoo.org/repo/gentoo.git/commit/?id=a58e3aa6 media-video/pipewire: backport recommended 1.2.x fixes Upstream recommend: """ b8d07e40 fix KODI no sound e6c0014f fix ardour export 525360d7 fix plasma thumbnail """ Take some other fixes on the 1.2 branch from 1.2.0..HEAD too. Signed-off-by: Sam James gentoo.org> ...fix-required-state-for-async-driver-nodes.patch | 82 ++++++++++++ ...odule-raop-only-set-softVolume-when-valid.patch | 30 +++++ ...-node-collect-with-groups-and-sync-enable.patch | 149 +++++++++++++++++++++ ...-impl-node-disable-async-for-driver-nodes.patch | 112 ++++++++++++++++ ...05-impl-node-set-INACTIVE-state-on-server.patch | 30 +++++ ...re-1.2.0-r1.ebuild => pipewire-1.2.0-r2.ebuild} | 0 6 files changed, 403 insertions(+) diff --git a/media-video/pipewire/files/1.2.0/0001-impl-node-fix-required-state-for-async-driver-nodes.patch b/media-video/pipewire/files/1.2.0/0001-impl-node-fix-required-state-for-async-driver-nodes.patch new file mode 100644 index 000000000000..105c8dd1676a --- /dev/null +++ b/media-video/pipewire/files/1.2.0/0001-impl-node-fix-required-state-for-async-driver-nodes.patch @@ -0,0 +1,82 @@ +From b8d07e40d66f12ac28aab710cfeb181bf25bc59a Mon Sep 17 00:00:00 2001 +From: Wim Taymans +Date: Mon, 1 Jul 2024 10:36:09 +0200 +Subject: [PATCH 1/5] impl-node: fix required state for async driver nodes + +When the node activation.required was incremented because it was a +driver, only decrement it in that case, regardless of the current driver +state of the node. + +This fixes the case of KODI where the required field gets out of sync +and things become unschedulable. + +Fixes #4087 +--- + src/pipewire/impl-node.c | 22 ++++++++++++++-------- + src/pipewire/private.h | 1 + + 2 files changed, 15 insertions(+), 8 deletions(-) + +diff --git a/src/pipewire/impl-node.c b/src/pipewire/impl-node.c +index 12629ee64..4def52897 100644 +--- a/src/pipewire/impl-node.c ++++ b/src/pipewire/impl-node.c +@@ -112,13 +112,17 @@ static inline void activate_target(struct pw_impl_node *node, struct pw_node_tar + { + struct pw_node_activation_state *state = &t->activation->state[0]; + if (!t->active) { +- if ((!node->async || node->driving) && !node->exported) { +- SPA_ATOMIC_INC(state->required); +- SPA_ATOMIC_INC(state->pending); ++ if (!node->async || node->driving) { ++ if (!node->exported) { ++ SPA_ATOMIC_INC(state->required); ++ SPA_ATOMIC_INC(state->pending); ++ } + } ++ t->active_driving = node->driving; + t->active = true; +- pw_log_debug("%p: target state:%p id:%d pending:%d/%d", +- node, state, t->id, state->pending, state->required); ++ pw_log_debug("%p: target state:%p id:%d pending:%d/%d %d:%d:%d", ++ node, state, t->id, state->pending, state->required, ++ node->async, node->driving, node->exported); + } + } + +@@ -126,7 +130,7 @@ static inline void deactivate_target(struct pw_impl_node *node, struct pw_node_t + { + if (t->active) { + struct pw_node_activation_state *state = &t->activation->state[0]; +- if (!node->async || node->driving) { ++ if (!node->async || t->active_driving) { + /* the driver copies the required to the pending state + * so first try to resume the node and then decrement the + * required state. This way we either resume with the old value +@@ -137,8 +141,10 @@ static inline void deactivate_target(struct pw_impl_node *node, struct pw_node_t + SPA_ATOMIC_DEC(state->required); + } + t->active = false; +- pw_log_debug("%p: target state:%p id:%d pending:%d/%d trigger:%"PRIu64, +- node, state, t->id, state->pending, state->required, trigger); ++ t->active_driving = false; ++ pw_log_debug("%p: target state:%p id:%d pending:%d/%d %d:%d:%d trigger:%"PRIu64, ++ node, state, t->id, state->pending, state->required, ++ node->async, node->driving, node->exported, trigger); + } + } + +diff --git a/src/pipewire/private.h b/src/pipewire/private.h +index 8c01fe8d5..25af677ac 100644 +--- a/src/pipewire/private.h ++++ b/src/pipewire/private.h +@@ -541,6 +541,7 @@ struct pw_node_target { + int fd; + void (*trigger)(struct pw_node_target *t, uint64_t nsec); + unsigned int active:1; ++ unsigned int active_driving:1; + unsigned int added:1; + }; + +-- +2.45.2 + diff --git a/media-video/pipewire/files/1.2.0/0002-module-raop-only-set-softVolume-when-valid.patch b/media-video/pipewire/files/1.2.0/0002-module-raop-only-set-softVolume-when-valid.patch new file mode 100644 index 000000000000..343b42dfdc8a --- /dev/null +++ b/media-video/pipewire/files/1.2.0/0002-module-raop-only-set-softVolume-when-valid.patch @@ -0,0 +1,30 @@ +From 82b9fa118f2fa009b5eb2891378fe003e2573bbe Mon Sep 17 00:00:00 2001 +From: Wim Taymans +Date: Mon, 1 Jul 2024 11:27:17 +0200 +Subject: [PATCH 2/5] module-raop: only set softVolume when valid + +--- + src/modules/module-raop-sink.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/src/modules/module-raop-sink.c b/src/modules/module-raop-sink.c +index 05e467d24..8ad28693f 100644 +--- a/src/modules/module-raop-sink.c ++++ b/src/modules/module-raop-sink.c +@@ -1643,10 +1643,10 @@ static void stream_props_changed(struct impl *impl, uint32_t id, const struct sp + impl->volume = volume; + + rtsp_send_volume(impl); ++ spa_pod_builder_prop(&b, SPA_PROP_softVolumes, 0); ++ spa_pod_builder_array(&b, sizeof(float), SPA_TYPE_Float, ++ n_vols, soft_vols); + } +- spa_pod_builder_prop(&b, SPA_PROP_softVolumes, 0); +- spa_pod_builder_array(&b, sizeof(float), SPA_TYPE_Float, +- n_vols, soft_vols); + spa_pod_builder_raw_padded(&b, prop, SPA_POD_PROP_SIZE(prop)); + break; + } +-- +2.45.2 + diff --git a/media-video/pipewire/files/1.2.0/0003-context-Fix-node-collect-with-groups-and-sync-enable.patch b/media-video/pipewire/files/1.2.0/0003-context-Fix-node-collect-with-groups-and-sync-enable.patch new file mode 100644 index 000000000000..5e18550bf193 --- /dev/null +++ b/media-video/pipewire/files/1.2.0/0003-context-Fix-node-collect-with-groups-and-sync-enable.patch @@ -0,0 +1,149 @@ +From e6c0014f94e995e49b72bea7ae56b960416e6b29 Mon Sep 17 00:00:00 2001 +From: Wim Taymans +Date: Mon, 1 Jul 2024 14:50:34 +0200 +Subject: [PATCH 3/5] context: Fix node collect with groups and sync enabled + +Keep track of the sync nodes we added to a driver and bring in the other +nodes from the same sync group, group or link groups. This makes it +possible to have disjoint sync groups each with their own driver. + +Fixes export in ardour8 + +Fixes #4083 +--- + src/pipewire/context.c | 49 +++++++++++++++++++++--------------------- + 1 file changed, 25 insertions(+), 24 deletions(-) + +diff --git a/src/pipewire/context.c b/src/pipewire/context.c +index 686dd5eee..f3e1b4d76 100644 +--- a/src/pipewire/context.c ++++ b/src/pipewire/context.c +@@ -1163,13 +1163,14 @@ static inline int run_nodes(struct pw_context *context, struct pw_impl_node *nod + * This ensures that we only activate the paths from the runnable nodes to the + * driver nodes and leave the other nodes idle. + */ +-static int collect_nodes(struct pw_context *context, struct pw_impl_node *node, struct spa_list *collect, +- char **sync) ++static int collect_nodes(struct pw_context *context, struct pw_impl_node *node, struct spa_list *collect) + { + struct spa_list queue; + struct pw_impl_node *n, *t; + struct pw_impl_port *p; + struct pw_impl_link *l; ++ uint32_t n_sync; ++ char *sync[MAX_SYNC+1]; + + pw_log_debug("node %p: '%s'", node, node->name); + +@@ -1178,20 +1179,30 @@ static int collect_nodes(struct pw_context *context, struct pw_impl_node *node, + spa_list_append(&queue, &node->sort_link); + node->visited = true; + ++ n_sync = 0; ++ sync[0] = NULL; ++ + /* now follow all the links from the nodes in the queue + * and add the peers to the queue. */ + spa_list_consume(n, &queue, sort_link) { + spa_list_remove(&n->sort_link); + spa_list_append(collect, &n->sort_link); + +- pw_log_debug(" next node %p: '%s' runnable:%u", n, n->name, n->runnable); ++ pw_log_debug(" next node %p: '%s' runnable:%u active:%d", ++ n, n->name, n->runnable, n->active); + + if (!n->active) + continue; + +- if (sync[0] != NULL) { +- if (pw_strv_find_common(n->sync_groups, sync) < 0) +- continue; ++ if (n->sync) { ++ for (uint32_t i = 0; n->sync_groups[i]; i++) { ++ if (n_sync >= MAX_SYNC) ++ break; ++ if (pw_strv_find(sync, n->sync_groups[i]) >= 0) ++ continue; ++ sync[n_sync++] = n->sync_groups[i]; ++ sync[n_sync] = NULL; ++ } + } + + spa_list_for_each(p, &n->input_ports, link) { +@@ -1242,6 +1253,8 @@ static int collect_nodes(struct pw_context *context, struct pw_impl_node *node, + spa_list_for_each(t, &context->node_list, link) { + if (t->exported || !t->active || t->visited) + continue; ++ /* the other node will be scheduled with this one if it's in ++ * the same group or link group */ + if (pw_strv_find_common(t->groups, n->groups) < 0 && + pw_strv_find_common(t->link_groups, n->link_groups) < 0 && + pw_strv_find_common(t->sync_groups, sync) < 0) +@@ -1253,7 +1266,8 @@ static int collect_nodes(struct pw_context *context, struct pw_impl_node *node, + spa_list_append(&queue, &t->sort_link); + } + } +- pw_log_debug(" next node %p: '%s' runnable:%u", n, n->name, n->runnable); ++ pw_log_debug(" next node %p: '%s' runnable:%u %p %p %p", n, n->name, n->runnable, ++ n->groups, n->link_groups, sync); + } + spa_list_for_each(n, collect, sort_link) + if (!n->driving && n->runnable) { +@@ -1497,10 +1511,9 @@ int pw_context_recalc_graph(struct pw_context *context, const char *reason) + struct pw_impl_node *n, *s, *target, *fallback; + const uint32_t *rates; + uint32_t max_quantum, min_quantum, def_quantum, rate_quantum, floor_quantum, ceil_quantum; +- uint32_t n_rates, def_rate, n_sync; ++ uint32_t n_rates, def_rate; + bool freewheel, global_force_rate, global_force_quantum, transport_start; + struct spa_list collect; +- char *sync[MAX_SYNC+1]; + + pw_log_info("%p: busy:%d reason:%s", context, impl->recalc, reason); + +@@ -1514,23 +1527,11 @@ again: + freewheel = false; + transport_start = false; + +- /* clean up the flags first and collect sync */ +- n_sync = 0; +- sync[0] = NULL; ++ /* clean up the flags first */ + spa_list_for_each(n, &context->node_list, link) { + n->visited = false; + n->checked = 0; + n->runnable = n->always_process && n->active; +- if (n->sync) { +- for (uint32_t i = 0; n->sync_groups[i]; i++) { +- if (n_sync >= MAX_SYNC) +- break; +- if (pw_strv_find(sync, n->sync_groups[i]) >= 0) +- continue; +- sync[n_sync++] = n->sync_groups[i]; +- sync[n_sync] = NULL; +- } +- } + } + + get_quantums(context, &def_quantum, &min_quantum, &max_quantum, &rate_quantum, +@@ -1551,7 +1552,7 @@ again: + + if (!n->visited) { + spa_list_init(&collect); +- collect_nodes(context, n, &collect, sync); ++ collect_nodes(context, n, &collect); + move_to_driver(context, &collect, n); + } + /* from now on we are only interested in active driving nodes +@@ -1605,7 +1606,7 @@ again: + + /* collect all nodes in this group */ + spa_list_init(&collect); +- collect_nodes(context, n, &collect, sync); ++ collect_nodes(context, n, &collect); + + driver = NULL; + spa_list_for_each(t, &collect, sort_link) { +-- +2.45.2 + diff --git a/media-video/pipewire/files/1.2.0/0004-impl-node-disable-async-for-driver-nodes.patch b/media-video/pipewire/files/1.2.0/0004-impl-node-disable-async-for-driver-nodes.patch new file mode 100644 index 000000000000..a7528249f1e3 --- /dev/null +++ b/media-video/pipewire/files/1.2.0/0004-impl-node-disable-async-for-driver-nodes.patch @@ -0,0 +1,112 @@ +From 525360d70ab1698afaaaf20f7e58002b8756353f Mon Sep 17 00:00:00 2001 +From: Wim Taymans +Date: Wed, 3 Jul 2024 13:31:24 +0200 +Subject: [PATCH 4/5] impl-node: disable async for driver nodes + +Make it so that a driver node can never be scheduled async. It could +possibly make sense when the driver node is not currently driving the +graph but when it drives the graph it always needs to be sync. This +also simplifies the target activation because we can simply check the +async state and ignore if the node is driving or not. + +Also make sure that we never make an async link with a driver output port. +This does not make sense because the driver node will always be +triggered sync first and before the async node so we can simply make +a sync link. + +This fixes the modified (only generate 1 buffer) video-src -> video-play +case where the buffer never arrives in video-play because of the +useless async link. + +Fixes #4092 +--- + src/pipewire/impl-link.c | 8 +++++--- + src/pipewire/impl-node.c | 7 +++---- + src/pipewire/private.h | 1 - + 3 files changed, 8 insertions(+), 8 deletions(-) + +diff --git a/src/pipewire/impl-link.c b/src/pipewire/impl-link.c +index 39e9bd17d..6dc2e1a59 100644 +--- a/src/pipewire/impl-link.c ++++ b/src/pipewire/impl-link.c +@@ -1321,7 +1321,8 @@ struct pw_impl_link *pw_context_create_link(struct pw_context *context, + if (this->passive && str == NULL) + pw_properties_set(properties, PW_KEY_LINK_PASSIVE, "true"); + +- impl->async = (output_node->async || input_node->async) && ++ impl->async = !output_node->driver && ++ (output_node->async || input_node->async) && + SPA_FLAG_IS_SET(output->flags, PW_IMPL_PORT_FLAG_ASYNC) && + SPA_FLAG_IS_SET(input->flags, PW_IMPL_PORT_FLAG_ASYNC); + +@@ -1375,8 +1376,9 @@ struct pw_impl_link *pw_context_create_link(struct pw_context *context, + this->name = spa_aprintf("%d.%d.%d -> %d.%d.%d", + output_node->info.id, output->port_id, this->rt.out_mix.port.port_id, + input_node->info.id, input->port_id, this->rt.in_mix.port.port_id); +- pw_log_info("(%s) (%s) -> (%s) async:%04x:%04x:%d", this->name, output_node->name, +- input_node->name, output->flags, input->flags, impl->async); ++ pw_log_info("(%s) (%s) -> (%s) async:%d:%04x:%04x:%d", this->name, output_node->name, ++ input_node->name, output_node->driving, ++ output->flags, input->flags, impl->async); + + pw_impl_port_emit_link_added(output, this); + pw_impl_port_emit_link_added(input, this); +diff --git a/src/pipewire/impl-node.c b/src/pipewire/impl-node.c +index 4def52897..c75e5793e 100644 +--- a/src/pipewire/impl-node.c ++++ b/src/pipewire/impl-node.c +@@ -112,13 +112,12 @@ static inline void activate_target(struct pw_impl_node *node, struct pw_node_tar + { + struct pw_node_activation_state *state = &t->activation->state[0]; + if (!t->active) { +- if (!node->async || node->driving) { ++ if (!node->async) { + if (!node->exported) { + SPA_ATOMIC_INC(state->required); + SPA_ATOMIC_INC(state->pending); + } + } +- t->active_driving = node->driving; + t->active = true; + pw_log_debug("%p: target state:%p id:%d pending:%d/%d %d:%d:%d", + node, state, t->id, state->pending, state->required, +@@ -130,7 +129,7 @@ static inline void deactivate_target(struct pw_impl_node *node, struct pw_node_t + { + if (t->active) { + struct pw_node_activation_state *state = &t->activation->state[0]; +- if (!node->async || t->active_driving) { ++ if (!node->async) { + /* the driver copies the required to the pending state + * so first try to resume the node and then decrement the + * required state. This way we either resume with the old value +@@ -141,7 +140,6 @@ static inline void deactivate_target(struct pw_impl_node *node, struct pw_node_t + SPA_ATOMIC_DEC(state->required); + } + t->active = false; +- t->active_driving = false; + pw_log_debug("%p: target state:%p id:%d pending:%d/%d %d:%d:%d trigger:%"PRIu64, + node, state, t->id, state->pending, state->required, + node->async, node->driving, node->exported, trigger); +@@ -1202,6 +1200,7 @@ static void check_properties(struct pw_impl_node *node) + recalc_reason = "transport changed"; + } + async = pw_properties_get_bool(node->properties, PW_KEY_NODE_ASYNC, false); ++ async &= !node->driver; + if (async != node->async) { + pw_log_info("%p: async %d -> %d", node, node->async, async); + node->async = async; +diff --git a/src/pipewire/private.h b/src/pipewire/private.h +index 25af677ac..8c01fe8d5 100644 +--- a/src/pipewire/private.h ++++ b/src/pipewire/private.h +@@ -541,7 +541,6 @@ struct pw_node_target { + int fd; + void (*trigger)(struct pw_node_target *t, uint64_t nsec); + unsigned int active:1; +- unsigned int active_driving:1; + unsigned int added:1; + }; + +-- +2.45.2 + diff --git a/media-video/pipewire/files/1.2.0/0005-impl-node-set-INACTIVE-state-on-server.patch b/media-video/pipewire/files/1.2.0/0005-impl-node-set-INACTIVE-state-on-server.patch new file mode 100644 index 000000000000..9821c151c97b --- /dev/null +++ b/media-video/pipewire/files/1.2.0/0005-impl-node-set-INACTIVE-state-on-server.patch @@ -0,0 +1,30 @@ +From d08df293a95ce976df1cc8c3ec367a8d5d84db35 Mon Sep 17 00:00:00 2001 +From: Wim Taymans +Date: Wed, 3 Jul 2024 17:42:39 +0200 +Subject: [PATCH 5/5] impl-node: set INACTIVE state on server + +Don't wait for the client to set the INACTIVE state, do it on the +server. We already decremented the target required so we don't want to +schedule the node anymore. + +Fixes some xruns when removing nodes in a stress test. +--- + src/pipewire/impl-node.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/pipewire/impl-node.c b/src/pipewire/impl-node.c +index c75e5793e..be25aa83e 100644 +--- a/src/pipewire/impl-node.c ++++ b/src/pipewire/impl-node.c +@@ -221,7 +221,7 @@ do_node_unprepare(struct spa_loop *loop, bool async, uint32_t seq, + if (!this->rt.prepared) + return 0; + +- if (!this->remote || this->rt.target.activation->client_version < 1) { ++ if (!this->exported) { + /* We mark ourself as finished now, this will avoid going further into the process loop + * in case our fd was ready (removing ourselfs from the loop should avoid that as well). + * If we were supposed to be scheduled make sure we continue the graph for the peers we +-- +2.45.2 + diff --git a/media-video/pipewire/pipewire-1.2.0-r1.ebuild b/media-video/pipewire/pipewire-1.2.0-r2.ebuild similarity index 100% rename from media-video/pipewire/pipewire-1.2.0-r1.ebuild rename to media-video/pipewire/pipewire-1.2.0-r2.ebuild