Improve negotiation

Try to link ports based on compatible formats
Add methods to filter formats.
This commit is contained in:
Wim Taymans 2017-02-10 10:17:07 +01:00
parent 1370fafd5b
commit df86fcec10
12 changed files with 229 additions and 95 deletions

View file

@ -482,6 +482,7 @@ pinos_core_find_port (PinosCore *core,
PinosPort *other_port,
uint32_t id,
PinosProperties *props,
unsigned int n_format_filters,
SpaFormat **format_filters,
char **error)
{
@ -508,6 +509,30 @@ pinos_core_find_port (PinosCore *core,
break;
}
} else {
PinosPort *p, *pin, *pout;
p = pinos_node_get_free_port (n, pinos_direction_reverse (other_port->direction));
if (p == NULL)
continue;
if (p->direction == PINOS_DIRECTION_OUTPUT) {
pin = other_port;
pout = p;
} else {
pin = p;
pout = other_port;
}
if (pinos_core_find_format (core,
pout,
pin,
props,
n_format_filters,
format_filters,
error) == NULL)
continue;
best = p;
}
}
if (best == NULL) {
@ -516,6 +541,89 @@ pinos_core_find_port (PinosCore *core,
return best;
}
SpaFormat *
pinos_core_find_format (PinosCore *core,
PinosPort *output,
PinosPort *input,
PinosProperties *props,
unsigned int n_format_filters,
SpaFormat **format_filterss,
char **error)
{
SpaNodeState out_state, in_state;
SpaResult res;
SpaFormat *filter = NULL, *format;
unsigned int iidx = 0, oidx = 0;
out_state = output->node->node->state;
in_state = input->node->node->state;
if (in_state == SPA_NODE_STATE_CONFIGURE && out_state > SPA_NODE_STATE_CONFIGURE) {
/* only input needs format */
if ((res = spa_node_port_get_format (output->node->node,
SPA_DIRECTION_OUTPUT,
output->port_id,
(const SpaFormat **)&format)) < 0) {
asprintf (error, "error get output format: %d", res);
goto error;
}
} else if (out_state == SPA_NODE_STATE_CONFIGURE && in_state > SPA_NODE_STATE_CONFIGURE) {
/* only output needs format */
if ((res = spa_node_port_get_format (input->node->node,
SPA_DIRECTION_INPUT,
input->port_id,
(const SpaFormat **)&format)) < 0) {
asprintf (error, "error get input format: %d", res);
goto error;
}
} else if (in_state == SPA_NODE_STATE_CONFIGURE && out_state == SPA_NODE_STATE_CONFIGURE) {
again:
/* both ports need a format */
pinos_log_debug ("core %p: finding best format", core);
if ((res = spa_node_port_enum_formats (input->node->node,
SPA_DIRECTION_INPUT,
input->port_id,
&filter,
NULL,
iidx)) < 0) {
if (res == SPA_RESULT_ENUM_END && iidx != 0) {
asprintf (error, "error input enum formats: %d", res);
goto error;
}
}
pinos_log_debug ("Try filter: %p", filter);
if (pinos_log_level_enabled (SPA_LOG_LEVEL_DEBUG))
spa_debug_format (filter);
if ((res = spa_node_port_enum_formats (output->node->node,
SPA_DIRECTION_OUTPUT,
output->port_id,
&format,
filter,
oidx)) < 0) {
if (res == SPA_RESULT_ENUM_END) {
oidx = 0;
iidx++;
goto again;
}
asprintf (error, "error output enum formats: %d", res);
goto error;
}
pinos_log_debug ("Got filtered:");
if (pinos_log_level_enabled (SPA_LOG_LEVEL_DEBUG))
spa_debug_format (format);
spa_format_fixate (format);
} else {
asprintf (error, "error node state");
goto error;
}
return format;
error:
return NULL;
}
PinosNodeFactory *
pinos_core_find_node_factory (PinosCore *core,
const char *name)

View file

@ -116,12 +116,20 @@ SpaResult pinos_global_bind (PinosGlobal *global,
uint32_t id);
void pinos_global_destroy (PinosGlobal *global);
SpaFormat * pinos_core_find_format (PinosCore *core,
PinosPort *output,
PinosPort *input,
PinosProperties *props,
unsigned int n_format_filters,
SpaFormat **format_filters,
char **error);
PinosPort * pinos_core_find_port (PinosCore *core,
PinosPort *other_port,
uint32_t id,
PinosProperties *props,
SpaFormat **format_filter,
unsigned int n_format_filters,
SpaFormat **format_filters,
char **error);
PinosNodeFactory * pinos_core_find_node_factory (PinosCore *core,

View file

@ -76,9 +76,8 @@ static SpaResult
do_negotiate (PinosLink *this, SpaNodeState in_state, SpaNodeState out_state)
{
PinosLinkImpl *impl = SPA_CONTAINER_OF (this, PinosLinkImpl, this);
SpaResult res;
SpaFormat *filter = NULL, *format;
unsigned int iidx = 0, oidx = 0;
SpaResult res = SPA_RESULT_ERROR;
SpaFormat *format;
char *error = NULL;
if (in_state != SPA_NODE_STATE_CONFIGURE && out_state != SPA_NODE_STATE_CONFIGURE)
@ -91,64 +90,15 @@ do_negotiate (PinosLink *this, SpaNodeState in_state, SpaNodeState out_state)
out_state = SPA_NODE_STATE_CONFIGURE;
}
/* both ports need a format */
if (in_state == SPA_NODE_STATE_CONFIGURE && out_state == SPA_NODE_STATE_CONFIGURE) {
pinos_log_debug ("link %p: doing negotiate format", this);
again:
if ((res = spa_node_port_enum_formats (this->input->node->node,
SPA_DIRECTION_INPUT,
this->input->port_id,
&filter,
NULL,
iidx)) < 0) {
if (res == SPA_RESULT_ENUM_END && iidx != 0) {
asprintf (&error, "error input enum formats: %d", res);
goto error;
}
}
pinos_log_debug ("Try filter: %p", filter);
if (pinos_log_level_enabled (SPA_LOG_LEVEL_DEBUG))
spa_debug_format (filter);
if ((res = spa_node_port_enum_formats (this->output->node->node,
SPA_DIRECTION_OUTPUT,
this->output->port_id,
&format,
filter,
oidx)) < 0) {
if (res == SPA_RESULT_ENUM_END) {
oidx = 0;
iidx++;
goto again;
}
asprintf (&error, "error output enum formats: %d", res);
goto error;
}
pinos_log_debug ("Got filtered:");
if (pinos_log_level_enabled (SPA_LOG_LEVEL_DEBUG))
spa_debug_format (format);
spa_format_fixate (format);
} else if (in_state == SPA_NODE_STATE_CONFIGURE && out_state > SPA_NODE_STATE_CONFIGURE) {
/* only input needs format */
if ((res = spa_node_port_get_format (this->output->node->node,
SPA_DIRECTION_OUTPUT,
this->output->port_id,
(const SpaFormat **)&format)) < 0) {
asprintf (&error, "error get output format: %d", res);
goto error;
}
} else if (out_state == SPA_NODE_STATE_CONFIGURE && in_state > SPA_NODE_STATE_CONFIGURE) {
/* only output needs format */
if ((res = spa_node_port_get_format (this->input->node->node,
SPA_DIRECTION_INPUT,
this->input->port_id,
(const SpaFormat **)&format)) < 0) {
asprintf (&error, "error get input format: %d", res);
goto error;
}
} else
return SPA_RESULT_OK;
format = pinos_core_find_format (this->core,
this->output,
this->input,
NULL,
0,
NULL,
&error);
if (format == NULL)
goto error;
pinos_log_debug ("link %p: doing set format", this);
if (pinos_log_level_enabled (SPA_LOG_LEVEL_DEBUG))