impl-port: query all params through the mixer

Go through the mixers of the port to get the params.

This makes it possible to let the mixer decide on formats, buffers and
io areas.

Currently, the format is the same on all mixer input and output ports
and the buffers are shared on the output port but the idea is to make it
possible to have different formats and buffers per link.
This commit is contained in:
Wim Taymans 2024-04-17 15:39:51 +02:00
parent abb28e5255
commit 84ed9c0fe9
5 changed files with 58 additions and 35 deletions

View file

@ -317,9 +317,9 @@ static int add_port_update(struct node_data *data, struct pw_impl_port *port, ui
for (idx = 0;;) {
spa_pod_dynamic_builder_init(&b, buf, sizeof(buf), 4096);
res = spa_node_port_enum_params_sync(port->node->node,
port->direction, port->port_id,
id, &idx, NULL, &param, &b.b);
res = spa_node_port_enum_params_sync(port->mix,
port->direction, SPA_ID_INVALID,
id, &idx, NULL, &param, &b.b);
if (res == 1) {
void *p;
p = pw_reallocarray(params, n_params + 1, sizeof(struct spa_pod*));

View file

@ -670,7 +670,9 @@ SPA_PRINTF_FUNC(7, 8) int pw_context_debug_port_params(struct pw_context *this,
*/
int pw_context_find_format(struct pw_context *context,
struct pw_impl_port *output,
uint32_t output_mix,
struct pw_impl_port *input,
uint32_t input_mix,
struct pw_properties *props,
uint32_t n_format_filters,
struct spa_pod **format_filters,
@ -684,10 +686,27 @@ int pw_context_find_format(struct pw_context *context,
struct spa_pod_builder fb = { 0 };
uint8_t fbuf[4096];
struct spa_pod *filter;
struct spa_node *in_node, *out_node;
uint32_t in_port, out_port;
out_state = output->state;
in_state = input->state;
if (output_mix == SPA_ID_INVALID) {
out_node = output->node->node;
out_port = output->port_id;
} else {
out_node = output->mix;
out_port = output_mix;
}
if (input_mix == SPA_ID_INVALID) {
in_node = input->node->node;
in_port = input->port_id;
} else {
in_node = input->mix;
in_port = input_mix;
}
pw_log_debug("%p: finding best format %d %d", context, out_state, in_state);
/* when a port is configured but the node is idle, we can reconfigure with a different format */
@ -701,8 +720,8 @@ int pw_context_find_format(struct pw_context *context,
if (in_state == PW_IMPL_PORT_STATE_CONFIGURE && out_state > PW_IMPL_PORT_STATE_CONFIGURE) {
/* only input needs format */
spa_pod_builder_init(&fb, fbuf, sizeof(fbuf));
if ((res = spa_node_port_enum_params_sync(output->node->node,
output->direction, output->port_id,
if ((res = spa_node_port_enum_params_sync(out_node,
output->direction, out_port,
SPA_PARAM_Format, &oidx,
NULL, &filter, &fb)) != 1) {
if (res < 0)
@ -714,8 +733,8 @@ int pw_context_find_format(struct pw_context *context,
pw_log_debug("%p: Got output format:", context);
pw_log_format(SPA_LOG_LEVEL_DEBUG, filter);
if ((res = spa_node_port_enum_params_sync(input->node->node,
input->direction, input->port_id,
if ((res = spa_node_port_enum_params_sync(in_node,
input->direction, in_port,
SPA_PARAM_EnumFormat, &iidx,
filter, format, builder)) <= 0) {
if (res == -ENOENT || res == 0) {
@ -730,8 +749,8 @@ int pw_context_find_format(struct pw_context *context,
} else if (out_state >= PW_IMPL_PORT_STATE_CONFIGURE && in_state > PW_IMPL_PORT_STATE_CONFIGURE) {
/* only output needs format */
spa_pod_builder_init(&fb, fbuf, sizeof(fbuf));
if ((res = spa_node_port_enum_params_sync(input->node->node,
input->direction, input->port_id,
if ((res = spa_node_port_enum_params_sync(in_node,
input->direction, in_port,
SPA_PARAM_Format, &iidx,
NULL, &filter, &fb)) != 1) {
if (res < 0)
@ -743,8 +762,8 @@ int pw_context_find_format(struct pw_context *context,
pw_log_debug("%p: Got input format:", context);
pw_log_format(SPA_LOG_LEVEL_DEBUG, filter);
if ((res = spa_node_port_enum_params_sync(output->node->node,
output->direction, output->port_id,
if ((res = spa_node_port_enum_params_sync(out_node,
output->direction, out_port,
SPA_PARAM_EnumFormat, &oidx,
filter, format, builder)) <= 0) {
if (res == -ENOENT || res == 0) {
@ -761,8 +780,8 @@ int pw_context_find_format(struct pw_context *context,
/* both ports need a format */
pw_log_debug("%p: do enum input %d", context, iidx);
spa_pod_builder_init(&fb, fbuf, sizeof(fbuf));
if ((res = spa_node_port_enum_params_sync(input->node->node,
input->direction, input->port_id,
if ((res = spa_node_port_enum_params_sync(in_node,
input->direction, in_port,
SPA_PARAM_EnumFormat, &iidx,
NULL, &filter, &fb)) != 1) {
if (res == -ENOENT) {
@ -779,8 +798,8 @@ int pw_context_find_format(struct pw_context *context,
pw_log_debug("%p: enum output %d with filter: %p", context, oidx, filter);
pw_log_format(SPA_LOG_LEVEL_DEBUG, filter);
if ((res = spa_node_port_enum_params_sync(output->node->node,
output->direction, output->port_id,
if ((res = spa_node_port_enum_params_sync(out_node,
output->direction, out_port,
SPA_PARAM_EnumFormat, &oidx,
filter, format, builder)) != 1) {
if (res == 0 && filter != NULL) {

View file

@ -355,7 +355,9 @@ static int do_negotiate(struct pw_impl_link *this)
/* find a common format for the ports */
if ((res = pw_context_find_format(context,
output, input, NULL, 0, NULL,
output, this->rt.out_mix.port.port_id,
input, this->rt.in_mix.port.port_id,
NULL, 0, NULL,
&format, &b, &error)) < 0) {
format = NULL;
goto error;
@ -369,8 +371,8 @@ static int do_negotiate(struct pw_impl_link *this)
/* if output port had format and is idle, check if it changed. If so, renegotiate */
if (out_state > PW_IMPL_PORT_STATE_CONFIGURE && output->node->info.state == PW_NODE_STATE_IDLE) {
index = 0;
res = spa_node_port_enum_params_sync(output->node->node,
output->direction, output->port_id,
res = spa_node_port_enum_params_sync(output->mix,
this->rt.out_mix.port.direction, this->rt.out_mix.port.port_id,
SPA_PARAM_Format, &index,
NULL, &current, &b);
switch (res) {
@ -403,8 +405,8 @@ static int do_negotiate(struct pw_impl_link *this)
/* if input port had format and is idle, check if it changed. If so, renegotiate */
if (in_state > PW_IMPL_PORT_STATE_CONFIGURE && input->node->info.state == PW_NODE_STATE_IDLE) {
index = 0;
res = spa_node_port_enum_params_sync(input->node->node,
input->direction, input->port_id,
res = spa_node_port_enum_params_sync(input->mix,
this->rt.in_mix.port.direction, this->rt.in_mix.port.port_id,
SPA_PARAM_Format, &index,
NULL, &current, &b);
switch (res) {
@ -492,12 +494,12 @@ static int do_negotiate(struct pw_impl_link *this)
return res;
error:
pw_context_debug_port_params(context, input->node->node, input->direction,
input->port_id, SPA_PARAM_EnumFormat, res,
"input format (%s)", error);
pw_context_debug_port_params(context, output->node->node, output->direction,
output->port_id, SPA_PARAM_EnumFormat, res,
"output format (%s)", error);
pw_context_debug_port_params(context, input->mix,
this->rt.in_mix.port.direction, this->rt.in_mix.port.port_id,
SPA_PARAM_EnumFormat, res, "input format (%s)", error);
pw_context_debug_port_params(context, output->mix,
this->rt.out_mix.port.direction, this->rt.out_mix.port.port_id,
SPA_PARAM_EnumFormat, res, "output format (%s)", error);
link_update_state(this, PW_LINK_STATE_ERROR, res, error);
free(format);
return res;
@ -604,8 +606,8 @@ static int do_allocation(struct pw_impl_link *this)
}
if ((res = pw_buffers_negotiate(this->context, alloc_flags,
output->node->node, output->port_id,
input->node->node, input->port_id,
output->mix, this->rt.out_mix.port.port_id,
input->mix, this->rt.in_mix.port.port_id,
&output->buffers)) < 0) {
error = spa_aprintf("error alloc buffers: %s", spa_strerror(res));
goto error;

View file

@ -853,11 +853,13 @@ int pw_impl_port_set_mix(struct pw_impl_port *port, struct spa_node *node, uint3
SPA_IO_Buffers,
&port->rt.io, sizeof(port->rt.io));
if (port->node && port->node->rt.position)
if (port->node && port->node->rt.position) {
spa_node_set_io(port->mix,
SPA_IO_Position,
port->node->rt.position,
sizeof(struct spa_io_position));
}
check_params(port);
}
return 0;
}
@ -1530,7 +1532,6 @@ int pw_impl_port_for_each_param(struct pw_impl_port *port,
{
int res;
struct impl *impl = SPA_CONTAINER_OF(port, struct impl, this);
struct pw_impl_node *node = port->node;
struct result_port_params_data user_data = { impl, data, callback, seq, false };
struct spa_hook listener;
struct spa_param_info *pi;
@ -1589,11 +1590,10 @@ int pw_impl_port_for_each_param(struct pw_impl_port *port,
pw_param_add(&impl->pending_list, seq, param_id, NULL);
spa_zero(listener);
spa_node_add_listener(node->node, &listener, &node_events, &user_data);
res = spa_node_port_enum_params(node->node, seq,
port->direction, port->port_id,
param_id, index, max,
filter);
spa_node_add_listener(port->mix, &listener, &node_events, &user_data);
res = spa_node_port_enum_params(port->mix, seq,
port->direction, SPA_ID_INVALID,
param_id, index, max, filter);
spa_hook_remove(&listener);
if (user_data.cache) {

View file

@ -1158,7 +1158,9 @@ struct pw_control {
/** Find a good format between 2 ports */
int pw_context_find_format(struct pw_context *context,
struct pw_impl_port *output,
uint32_t output_mix,
struct pw_impl_port *input,
uint32_t input_mix,
struct pw_properties *props,
uint32_t n_format_filters,
struct spa_pod **format_filters,