mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-06 13:30:01 -05:00
link: add feedback links
Check if a link is a feedback loop. For feedback loops we want to schedule the consumer before the provider.
This commit is contained in:
parent
0701428aec
commit
9b2a051daf
2 changed files with 46 additions and 7 deletions
|
|
@ -804,6 +804,7 @@ do_activate_link(struct spa_loop *loop,
|
||||||
{
|
{
|
||||||
struct pw_link *this = user_data;
|
struct pw_link *this = user_data;
|
||||||
struct spa_graph_port *in, *out;
|
struct spa_graph_port *in, *out;
|
||||||
|
struct pw_node *inode, *onode;
|
||||||
|
|
||||||
pw_log_trace("link %p: activate", this);
|
pw_log_trace("link %p: activate", this);
|
||||||
|
|
||||||
|
|
@ -813,11 +814,20 @@ do_activate_link(struct spa_loop *loop,
|
||||||
spa_graph_port_add(&this->output->rt.mix_node, out);
|
spa_graph_port_add(&this->output->rt.mix_node, out);
|
||||||
spa_graph_port_add(&this->input->rt.mix_node, in);
|
spa_graph_port_add(&this->input->rt.mix_node, in);
|
||||||
spa_graph_port_link(out, in);
|
spa_graph_port_link(out, in);
|
||||||
this->rt.link.signal_data = &this->input->node->rt.root;
|
if (this->feedback) {
|
||||||
spa_graph_link_add(&this->output->node->rt.root,
|
inode = this->output->node;
|
||||||
this->input->node->rt.root.state,
|
onode = this->input->node;
|
||||||
&this->rt.link);
|
}
|
||||||
|
else {
|
||||||
|
onode = this->output->node;
|
||||||
|
inode = this->input->node;
|
||||||
|
}
|
||||||
|
if (inode != onode) {
|
||||||
|
this->rt.link.signal_data = &inode->rt.root;
|
||||||
|
spa_graph_link_add(&onode->rt.root,
|
||||||
|
inode->rt.root.state,
|
||||||
|
&this->rt.link);
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1034,7 +1044,8 @@ do_deactivate_link(struct spa_loop *loop,
|
||||||
spa_graph_port_unlink(out);
|
spa_graph_port_unlink(out);
|
||||||
spa_graph_port_remove(out);
|
spa_graph_port_remove(out);
|
||||||
spa_graph_port_remove(in);
|
spa_graph_port_remove(in);
|
||||||
spa_graph_link_remove(&this->rt.link);
|
if (this->input->node != this->output->node)
|
||||||
|
spa_graph_link_remove(&this->rt.link);
|
||||||
this->rt.link.signal_data = NULL;
|
this->rt.link.signal_data = NULL;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -1185,6 +1196,32 @@ static int find_driver(struct pw_link *this)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool pw_link_is_feedback(struct pw_node *output, struct pw_node *input)
|
||||||
|
{
|
||||||
|
struct pw_port *p;
|
||||||
|
|
||||||
|
if (output == input)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
spa_list_for_each(p, &output->output_ports, link) {
|
||||||
|
struct pw_link *l;
|
||||||
|
|
||||||
|
spa_list_for_each(l, &p->links, output_link) {
|
||||||
|
if (l->feedback)
|
||||||
|
continue;
|
||||||
|
if (l->input->node == input)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
spa_list_for_each(l, &p->links, output_link) {
|
||||||
|
if (l->feedback)
|
||||||
|
continue;
|
||||||
|
if (pw_link_is_feedback(l->input->node, input))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
struct pw_link *pw_link_new(struct pw_core *core,
|
struct pw_link *pw_link_new(struct pw_core *core,
|
||||||
struct pw_port *output,
|
struct pw_port *output,
|
||||||
struct pw_port *input,
|
struct pw_port *input,
|
||||||
|
|
@ -1215,7 +1252,8 @@ struct pw_link *pw_link_new(struct pw_core *core,
|
||||||
goto no_mem;
|
goto no_mem;
|
||||||
|
|
||||||
this = &impl->this;
|
this = &impl->this;
|
||||||
pw_log_debug("link %p: new", this);
|
this->feedback = pw_link_is_feedback(input_node, output_node);
|
||||||
|
pw_log_debug("link %p: new feedback %d", this, this->feedback);
|
||||||
|
|
||||||
if (user_data_size > 0)
|
if (user_data_size > 0)
|
||||||
this->user_data = SPA_MEMBER(impl, sizeof(struct impl), void);
|
this->user_data = SPA_MEMBER(impl, sizeof(struct impl), void);
|
||||||
|
|
|
||||||
|
|
@ -456,6 +456,7 @@ struct pw_link {
|
||||||
|
|
||||||
struct pw_link_info info; /**< introspectable link info */
|
struct pw_link_info info; /**< introspectable link info */
|
||||||
struct pw_properties *properties; /**< extra link properties */
|
struct pw_properties *properties; /**< extra link properties */
|
||||||
|
bool feedback;
|
||||||
|
|
||||||
enum pw_link_state state; /**< link state */
|
enum pw_link_state state; /**< link state */
|
||||||
char *error; /**< error message when state error */
|
char *error; /**< error message when state error */
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue