From 62def0399f68abb2a302b506cbed42a185de8a5e Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Wed, 10 Mar 2021 13:06:02 +0100 Subject: [PATCH] impl-node: rework link activation Only activate the links when the node is added to a driver. Otherwise the driver will expect us to decrement the activation counters for the links but that won't happen because the node will not be processed yet. Instead we activate the links that were not activated yet when the node is activated. This improves scheduling for newly added links and nodes. --- src/pipewire/impl-link.c | 10 ++++++-- src/pipewire/impl-node.c | 51 +++++++++++++++++++++++++++------------- src/pipewire/private.h | 1 + 3 files changed, 44 insertions(+), 18 deletions(-) diff --git a/src/pipewire/impl-link.c b/src/pipewire/impl-link.c index 358b5747e..f426d69a4 100644 --- a/src/pipewire/impl-link.c +++ b/src/pipewire/impl-link.c @@ -519,7 +519,10 @@ do_activate_link(struct spa_loop *loop, spa_list_append(&impl->onode->rt.target_list, &this->rt.target.link); state = &this->rt.target.activation->state[0]; - state->required++; + if (!this->rt.target.active && impl->onode->rt.driver_target.node != NULL) { + state->required++; + this->rt.target.active = true; + } pw_log_trace(NAME" %p: node:%p state:%p pending:%d/%d", this, impl->inode, state, state->pending, state->required); @@ -693,7 +696,10 @@ do_deactivate_link(struct spa_loop *loop, spa_list_remove(&this->rt.target.link); state = &this->rt.target.activation->state[0]; - state->required--; + if (this->rt.target.active) { + state->required--; + this->rt.target.active = false; + } pw_log_trace(NAME" %p: node:%p state:%p pending:%d/%d", this, impl->inode, state, state->pending, state->required); diff --git a/src/pipewire/impl-node.c b/src/pipewire/impl-node.c index 37f9d23f7..25e470275 100644 --- a/src/pipewire/impl-node.c +++ b/src/pipewire/impl-node.c @@ -101,6 +101,7 @@ static void node_deactivate(struct pw_impl_node *this) static void add_node(struct pw_impl_node *this, struct pw_impl_node *driver) { struct pw_node_activation_state *dstate, *nstate; + struct pw_node_target *t; if (this->exported) return; @@ -114,21 +115,29 @@ static void add_node(struct pw_impl_node *this, struct pw_impl_node *driver) this->rt.driver_target.data = driver; spa_list_append(&this->rt.target_list, &this->rt.driver_target.link); - dstate = &this->rt.driver_target.activation->state[0]; - dstate->required++; - spa_list_append(&driver->rt.target_list, &this->rt.target.link); nstate = &this->rt.activation->state[0]; - nstate->required++; + if (!this->rt.target.active) { + nstate->required++; + this->rt.target.active = true; + } - pw_log_trace(NAME" %p: driver state:%p pending:%d/%d, node state:%p pending:%d/%d", - this, dstate, dstate->pending, dstate->required, - nstate, nstate->pending, nstate->required); + spa_list_for_each(t, &this->rt.target_list, link) { + dstate = &t->activation->state[0]; + if (!t->active) { + dstate->required++; + t->active = true; + } + pw_log_trace(NAME" %p: driver state:%p pending:%d/%d, node state:%p pending:%d/%d", + this, dstate, dstate->pending, dstate->required, + nstate, nstate->pending, nstate->required); + } } static void remove_node(struct pw_impl_node *this) { struct pw_node_activation_state *dstate, *nstate; + struct pw_node_target *t; if (this->exported) return; @@ -137,17 +146,27 @@ static void remove_node(struct pw_impl_node *this) this, this->rt.driver_target.data, this->rt.driver_target.activation, this->rt.activation); - spa_list_remove(&this->rt.driver_target.link); - dstate = &this->rt.driver_target.activation->state[0]; - dstate->required--; - spa_list_remove(&this->rt.target.link); - nstate = &this->rt.activation->state[0]; - nstate->required--; - pw_log_trace(NAME" %p: driver state:%p pending:%d/%d, node state:%p pending:%d/%d", - this, dstate, dstate->pending, dstate->required, - nstate, nstate->pending, nstate->required); + nstate = &this->rt.activation->state[0]; + if (this->rt.target.active) { + nstate->required--; + this->rt.target.active = false; + } + + spa_list_for_each(t, &this->rt.target_list, link) { + dstate = &t->activation->state[0]; + if (t->active) { + dstate->required--; + t->active = false; + } + pw_log_trace(NAME" %p: driver state:%p pending:%d/%d, node state:%p pending:%d/%d", + this, dstate, dstate->pending, dstate->required, + nstate, nstate->pending, nstate->required); + } + spa_list_remove(&this->rt.driver_target.link); + + this->rt.driver_target.node = NULL; } static int diff --git a/src/pipewire/private.h b/src/pipewire/private.h index 3bb5d0a75..7ec3bf578 100644 --- a/src/pipewire/private.h +++ b/src/pipewire/private.h @@ -513,6 +513,7 @@ struct pw_node_target { struct pw_node_activation *activation; int (*signal) (void *data); void *data; + unsigned int active:1; }; struct pw_node_activation {