mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-10-29 05:40:27 -04:00
audioconvert: improve latency handling
When setting the Latency parameter on one side of the converter, set it also on the other size. We should actually implement propagating the latency through all the elements of the converter later. Implement latency handling on fmtconvert. merger and splitter change latency on all ports when on port changes. All this makes the configured and exposed latencies visible on all ports from adapter.
This commit is contained in:
parent
22fe0b293a
commit
48e6e41d95
4 changed files with 91 additions and 45 deletions
|
|
@ -1047,10 +1047,6 @@ impl_node_port_set_param(void *object,
|
|||
this, id, direction, port_id, param);
|
||||
|
||||
switch (id) {
|
||||
case SPA_PARAM_Latency:
|
||||
target = this->fmt[SPA_DIRECTION_REVERSE(direction)];
|
||||
port_id = 0;
|
||||
break;
|
||||
default:
|
||||
is_monitor = IS_MONITOR_PORT(this, direction, port_id);
|
||||
if (is_monitor)
|
||||
|
|
@ -1064,6 +1060,16 @@ impl_node_port_set_param(void *object,
|
|||
direction, port_id, id, flags, param)) < 0)
|
||||
return res;
|
||||
|
||||
switch (id) {
|
||||
case SPA_PARAM_Latency:
|
||||
target = this->fmt[SPA_DIRECTION_REVERSE(direction)];
|
||||
port_id = 0;
|
||||
if ((res = spa_node_port_set_param(target,
|
||||
direction, port_id, id, flags, param)) < 0)
|
||||
return res;
|
||||
break;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@
|
|||
#include <spa/node/io.h>
|
||||
#include <spa/node/utils.h>
|
||||
#include <spa/param/audio/format-utils.h>
|
||||
#include <spa/param/latency-utils.h>
|
||||
#include <spa/param/param.h>
|
||||
#include <spa/pod/filter.h>
|
||||
#include <spa/debug/types.h>
|
||||
|
|
@ -88,7 +89,14 @@ struct port {
|
|||
|
||||
uint64_t info_all;
|
||||
struct spa_port_info info;
|
||||
struct spa_param_info params[8];
|
||||
#define PORT_EnumFormat 0
|
||||
#define PORT_Meta 1
|
||||
#define PORT_IO 2
|
||||
#define PORT_Format 3
|
||||
#define PORT_Buffers 4
|
||||
#define PORT_Latency 5
|
||||
#define N_PORT_PARAMS 6
|
||||
struct spa_param_info params[N_PORT_PARAMS];
|
||||
|
||||
struct spa_audio_info format;
|
||||
uint32_t stride;
|
||||
|
|
@ -114,7 +122,8 @@ struct impl {
|
|||
uint64_t info_all;
|
||||
struct spa_node_info info;
|
||||
struct props props;
|
||||
struct spa_param_info params[8];
|
||||
#define N_NODE_PARAMS 0
|
||||
struct spa_param_info params[1];
|
||||
|
||||
struct spa_hook_list hooks;
|
||||
|
||||
|
|
@ -123,6 +132,8 @@ struct impl {
|
|||
uint32_t src_remap[SPA_AUDIO_MAX_CHANNELS];
|
||||
uint32_t dst_remap[SPA_AUDIO_MAX_CHANNELS];
|
||||
|
||||
struct spa_latency_info latency[2];
|
||||
|
||||
uint32_t cpu_flags;
|
||||
struct convert conv;
|
||||
unsigned int started:1;
|
||||
|
|
@ -553,6 +564,16 @@ impl_node_port_enum_params(void *object, int seq,
|
|||
}
|
||||
break;
|
||||
|
||||
case SPA_PARAM_Latency:
|
||||
switch (result.index) {
|
||||
case 0: case 1:
|
||||
param = spa_latency_build(&b, id, &this->latency[result.index]);
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return -ENOENT;
|
||||
}
|
||||
|
|
@ -660,12 +681,13 @@ static int port_set_format(void *object,
|
|||
this, direction, port_id, res, port->stride);
|
||||
}
|
||||
if (port->have_format) {
|
||||
port->params[3] = SPA_PARAM_INFO(SPA_PARAM_Format, SPA_PARAM_INFO_READWRITE);
|
||||
port->params[4] = SPA_PARAM_INFO(SPA_PARAM_Buffers, SPA_PARAM_INFO_READ);
|
||||
port->params[PORT_Format] = SPA_PARAM_INFO(SPA_PARAM_Format, SPA_PARAM_INFO_READWRITE);
|
||||
port->params[PORT_Buffers] = SPA_PARAM_INFO(SPA_PARAM_Buffers, SPA_PARAM_INFO_READ);
|
||||
} else {
|
||||
port->params[3] = SPA_PARAM_INFO(SPA_PARAM_Format, SPA_PARAM_INFO_WRITE);
|
||||
port->params[4] = SPA_PARAM_INFO(SPA_PARAM_Buffers, 0);
|
||||
port->params[PORT_Format] = SPA_PARAM_INFO(SPA_PARAM_Format, SPA_PARAM_INFO_WRITE);
|
||||
port->params[PORT_Buffers] = SPA_PARAM_INFO(SPA_PARAM_Buffers, 0);
|
||||
}
|
||||
emit_port_info(this, port, false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -676,21 +698,39 @@ impl_node_port_set_param(void *object,
|
|||
const struct spa_pod *param)
|
||||
{
|
||||
struct impl *this = object;
|
||||
struct port *port;
|
||||
int res;
|
||||
|
||||
spa_return_val_if_fail(object != NULL, -EINVAL);
|
||||
spa_return_val_if_fail(CHECK_PORT(object, direction, port_id), -EINVAL);
|
||||
|
||||
port = GET_PORT(this, direction, port_id);
|
||||
|
||||
spa_log_debug(this->log, NAME " %p: set param %u on port %d:%d %p",
|
||||
this, id, direction, port_id, param);
|
||||
|
||||
switch (id) {
|
||||
case SPA_PARAM_Latency:
|
||||
return 0;
|
||||
case SPA_PARAM_Format:
|
||||
return port_set_format(object, direction, port_id, flags, param);
|
||||
default:
|
||||
return -ENOENT;
|
||||
{
|
||||
struct spa_latency_info info;
|
||||
if ((res = spa_latency_parse(param, &info)) < 0)
|
||||
return res;
|
||||
if (direction == info.direction)
|
||||
return -EINVAL;
|
||||
|
||||
this->latency[info.direction] = info;
|
||||
port->info.change_mask |= SPA_PORT_CHANGE_MASK_PARAMS;
|
||||
port->params[PORT_Latency].flags ^= SPA_PARAM_INFO_SERIAL;
|
||||
emit_port_info(this, port, false);
|
||||
break;
|
||||
}
|
||||
case SPA_PARAM_Format:
|
||||
res = port_set_format(object, direction, port_id, flags, param);
|
||||
break;
|
||||
default:
|
||||
res = -ENOENT;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static int
|
||||
|
|
@ -984,13 +1024,14 @@ static int init_port(struct impl *this, enum spa_direction direction, uint32_t p
|
|||
port->info = SPA_PORT_INFO_INIT();
|
||||
port->info.flags = SPA_PORT_FLAG_NO_REF |
|
||||
SPA_PORT_FLAG_DYNAMIC_DATA;
|
||||
port->params[0] = SPA_PARAM_INFO(SPA_PARAM_EnumFormat, SPA_PARAM_INFO_READ);
|
||||
port->params[1] = SPA_PARAM_INFO(SPA_PARAM_Meta, SPA_PARAM_INFO_READ);
|
||||
port->params[2] = SPA_PARAM_INFO(SPA_PARAM_IO, SPA_PARAM_INFO_READ);
|
||||
port->params[3] = SPA_PARAM_INFO(SPA_PARAM_Format, SPA_PARAM_INFO_WRITE);
|
||||
port->params[4] = SPA_PARAM_INFO(SPA_PARAM_Buffers, 0);
|
||||
port->params[PORT_EnumFormat] = SPA_PARAM_INFO(SPA_PARAM_EnumFormat, SPA_PARAM_INFO_READ);
|
||||
port->params[PORT_Meta] = SPA_PARAM_INFO(SPA_PARAM_Meta, SPA_PARAM_INFO_READ);
|
||||
port->params[PORT_IO] = SPA_PARAM_INFO(SPA_PARAM_IO, SPA_PARAM_INFO_READ);
|
||||
port->params[PORT_Format] = SPA_PARAM_INFO(SPA_PARAM_Format, SPA_PARAM_INFO_WRITE);
|
||||
port->params[PORT_Buffers] = SPA_PARAM_INFO(SPA_PARAM_Buffers, 0);
|
||||
port->params[PORT_Latency] = SPA_PARAM_INFO(SPA_PARAM_Latency, SPA_PARAM_INFO_READWRITE);
|
||||
port->info.params = port->params;
|
||||
port->info.n_params = 5;
|
||||
port->info.n_params = N_PORT_PARAMS;
|
||||
port->have_format = false;
|
||||
|
||||
return 0;
|
||||
|
|
@ -1036,9 +1077,12 @@ impl_init(const struct spa_handle_factory *factory,
|
|||
this->info = SPA_NODE_INFO_INIT();
|
||||
this->info.flags = SPA_NODE_FLAG_RT;
|
||||
this->info.params = this->params;
|
||||
this->info.n_params = 0;
|
||||
this->info.n_params = N_NODE_PARAMS;
|
||||
props_reset(&this->props);
|
||||
|
||||
this->latency[SPA_DIRECTION_INPUT] = SPA_LATENCY_INFO(SPA_DIRECTION_INPUT);
|
||||
this->latency[SPA_DIRECTION_OUTPUT] = SPA_LATENCY_INFO(SPA_DIRECTION_OUTPUT);
|
||||
|
||||
init_port(this, SPA_DIRECTION_OUTPUT, 0);
|
||||
init_port(this, SPA_DIRECTION_INPUT, 0);
|
||||
|
||||
|
|
|
|||
|
|
@ -817,8 +817,8 @@ impl_node_port_enum_params(void *object, int seq,
|
|||
break;
|
||||
case SPA_PARAM_Latency:
|
||||
switch (result.index) {
|
||||
case 0:
|
||||
param = spa_latency_build(&b, id, &this->latency[direction]);
|
||||
case 0: case 1:
|
||||
param = spa_latency_build(&b, id, &this->latency[result.index]);
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
|
|
@ -946,19 +946,16 @@ static int port_set_latency(void *object,
|
|||
return -EINVAL;
|
||||
this->latency[other] = info;
|
||||
}
|
||||
if (direction == SPA_DIRECTION_OUTPUT) {
|
||||
for (i = 0; i < this->port_count; i++) {
|
||||
port = GET_IN_PORT(this, i);
|
||||
port->info.change_mask |= SPA_PORT_CHANGE_MASK_PARAMS;
|
||||
port->params[IDX_Latency].flags ^= SPA_PARAM_INFO_SERIAL;
|
||||
emit_port_info(this, port, false);
|
||||
}
|
||||
} else {
|
||||
port = GET_OUT_PORT(this, 0);
|
||||
for (i = 0; i < this->port_count; i++) {
|
||||
port = GET_IN_PORT(this, i);
|
||||
port->info.change_mask |= SPA_PORT_CHANGE_MASK_PARAMS;
|
||||
port->params[IDX_Latency].flags ^= SPA_PARAM_INFO_SERIAL;
|
||||
emit_port_info(this, port, false);
|
||||
}
|
||||
port = GET_OUT_PORT(this, 0);
|
||||
port->info.change_mask |= SPA_PORT_CHANGE_MASK_PARAMS;
|
||||
port->params[IDX_Latency].flags ^= SPA_PARAM_INFO_SERIAL;
|
||||
emit_port_info(this, port, false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -1462,6 +1459,9 @@ impl_init(const struct spa_handle_factory *factory,
|
|||
this->monitor_channel_volumes = spa_atob(str);
|
||||
}
|
||||
|
||||
this->latency[SPA_DIRECTION_INPUT] = SPA_LATENCY_INFO(SPA_DIRECTION_INPUT);
|
||||
this->latency[SPA_DIRECTION_OUTPUT] = SPA_LATENCY_INFO(SPA_DIRECTION_OUTPUT);
|
||||
|
||||
this->node.iface = SPA_INTERFACE_INIT(
|
||||
SPA_TYPE_INTERFACE_Node,
|
||||
SPA_VERSION_NODE,
|
||||
|
|
|
|||
|
|
@ -572,8 +572,8 @@ impl_node_port_enum_params(void *object, int seq,
|
|||
break;
|
||||
case SPA_PARAM_Latency:
|
||||
switch (result.index) {
|
||||
case 0:
|
||||
param = spa_latency_build(&b, id, &this->latency[direction]);
|
||||
case 0: case 1:
|
||||
param = spa_latency_build(&b, id, &this->latency[result.index]);
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
|
|
@ -705,19 +705,16 @@ static int port_set_latency(void *object,
|
|||
return -EINVAL;
|
||||
this->latency[other] = info;
|
||||
}
|
||||
if (direction == SPA_DIRECTION_INPUT) {
|
||||
for (i = 0; i < this->port_count; i++) {
|
||||
port = GET_OUT_PORT(this, i);
|
||||
port->info.change_mask |= SPA_PORT_CHANGE_MASK_PARAMS;
|
||||
port->params[IDX_Latency].flags ^= SPA_PARAM_INFO_SERIAL;
|
||||
emit_port_info(this, port, false);
|
||||
}
|
||||
} else {
|
||||
port = GET_IN_PORT(this, 0);
|
||||
for (i = 0; i < this->port_count; i++) {
|
||||
port = GET_OUT_PORT(this, i);
|
||||
port->info.change_mask |= SPA_PORT_CHANGE_MASK_PARAMS;
|
||||
port->params[IDX_Latency].flags ^= SPA_PARAM_INFO_SERIAL;
|
||||
emit_port_info(this, port, false);
|
||||
}
|
||||
port = GET_IN_PORT(this, 0);
|
||||
port->info.change_mask |= SPA_PORT_CHANGE_MASK_PARAMS;
|
||||
port->params[IDX_Latency].flags ^= SPA_PARAM_INFO_SERIAL;
|
||||
emit_port_info(this, port, false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -793,7 +790,6 @@ static int port_set_format(void *object,
|
|||
if (port->have_format) {
|
||||
port->params[IDX_Format] = SPA_PARAM_INFO(SPA_PARAM_Format, SPA_PARAM_INFO_READWRITE);
|
||||
port->params[IDX_Buffers] = SPA_PARAM_INFO(SPA_PARAM_Buffers, SPA_PARAM_INFO_READ);
|
||||
port->params[IDX_Latency].flags ^= SPA_PARAM_INFO_SERIAL;
|
||||
} else {
|
||||
port->params[IDX_Format] = SPA_PARAM_INFO(SPA_PARAM_Format, SPA_PARAM_INFO_WRITE);
|
||||
port->params[IDX_Buffers] = SPA_PARAM_INFO(SPA_PARAM_Buffers, 0);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue