Browse Source

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.
lines
Wim Taymans 1 year ago
parent
commit
48e6e41d95
4 changed files with 89 additions and 43 deletions
  1. +10
    -4
      spa/plugins/audioconvert/audioconvert.c
  2. +60
    -16
      spa/plugins/audioconvert/fmtconvert.c
  3. +11
    -11
      spa/plugins/audioconvert/merger.c
  4. +8
    -12
      spa/plugins/audioconvert/splitter.c

+ 10
- 4
spa/plugins/audioconvert/audioconvert.c View File

@ -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;
}


+ 60
- 16
spa/plugins/audioconvert/fmtconvert.c View File

@ -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;
{
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:
return port_set_format(object, direction, port_id, flags, param);
res = port_set_format(object, direction, port_id, flags, param);
break;
default:
return -ENOENT;
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);


+ 11
- 11
spa/plugins/audioconvert/merger.c View File

@ -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,


+ 8
- 12
spa/plugins/audioconvert/splitter.c View File

@ -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…
Cancel
Save