scheduler: prepare link before usage

A link might become unprepared because a node suspended. When we want
to make the nodes runnable, make sure the link is prepared again.
This commit is contained in:
Wim Taymans 2026-02-21 17:25:54 +01:00
parent 476220c18b
commit 846096d435
3 changed files with 22 additions and 17 deletions

View file

@ -204,27 +204,28 @@ static void check_runnable(struct pw_context *context, struct pw_impl_node *node
spa_list_for_each(p, &node->output_ports, link) { spa_list_for_each(p, &node->output_ports, link) {
spa_list_for_each(l, &p->links, output_link) { spa_list_for_each(l, &p->links, output_link) {
n = l->input->node; n = l->input->node;
/* we can only check the peer when the link is ready and /* the peer needs to be active and we are linked to it
* the peer is active */ * with a non-passive link */
if (!l->prepared || !n->active) if (!n->active || p->passive)
continue; continue;
/* explicitly prepare the link in case it was suspended */
if (!p->passive) { pw_impl_link_prepare(l);
make_runnable(context, node); if (!l->prepared)
make_runnable(context, n); continue;
} make_runnable(context, node);
make_runnable(context, n);
} }
} }
spa_list_for_each(p, &node->input_ports, link) { spa_list_for_each(p, &node->input_ports, link) {
spa_list_for_each(l, &p->links, input_link) { spa_list_for_each(l, &p->links, input_link) {
n = l->output->node; n = l->output->node;
if (!l->prepared || !n->active) if (!n->active || p->passive)
continue; continue;
pw_impl_link_prepare(l);
if (!p->passive) { if (!l->prepared)
make_runnable(context, node); continue;
make_runnable(context, n); make_runnable(context, node);
} make_runnable(context, n);
} }
} }
} }

View file

@ -969,7 +969,8 @@ static void output_remove(struct pw_impl_link *this)
this->output = NULL; this->output = NULL;
} }
static int link_prepare(struct pw_impl_link *this) SPA_EXPORT
int pw_impl_link_prepare(struct pw_impl_link *this)
{ {
struct impl *impl = SPA_CONTAINER_OF(this, struct impl, this); struct impl *impl = SPA_CONTAINER_OF(this, struct impl, this);
@ -1088,7 +1089,7 @@ static void port_param_changed(struct pw_impl_link *this, uint32_t id,
pw_log_info("%p: format changed", this); pw_log_info("%p: format changed", this);
this->preparing = this->prepared = false; this->preparing = this->prepared = false;
link_update_state(this, PW_LINK_STATE_INIT, 0, NULL); link_update_state(this, PW_LINK_STATE_INIT, 0, NULL);
link_prepare(this); pw_impl_link_prepare(this);
} }
static void input_port_param_changed(void *data, uint32_t id) static void input_port_param_changed(void *data, uint32_t id)
@ -1708,7 +1709,7 @@ int pw_impl_link_register(struct pw_impl_link *link,
pw_global_add_listener(link->global, &link->global_listener, &global_events, link); pw_global_add_listener(link->global, &link->global_listener, &global_events, link);
pw_global_register(link->global); pw_global_register(link->global);
link_prepare(link); pw_impl_link_prepare(link);
return 0; return 0;

View file

@ -1358,6 +1358,9 @@ int pw_impl_node_set_io(struct pw_impl_node *node, uint32_t id, void *data, size
int pw_impl_node_add_target(struct pw_impl_node *node, struct pw_node_target *t); int pw_impl_node_add_target(struct pw_impl_node *node, struct pw_node_target *t);
int pw_impl_node_remove_target(struct pw_impl_node *node, struct pw_node_target *t); int pw_impl_node_remove_target(struct pw_impl_node *node, struct pw_node_target *t);
/** Prepare a link
* Starts the negotiation of formats and buffers on \a link */
int pw_impl_link_prepare(struct pw_impl_link *link);
/** starts streaming on a link */ /** starts streaming on a link */
int pw_impl_link_activate(struct pw_impl_link *link); int pw_impl_link_activate(struct pw_impl_link *link);