audioconvert: add monitor.passthrough option

Add a monitor.passthrough option. This will pass all latency information
directly between the port and its monitor ports.

This is interesting when the adapter (and audioconvert) is used with a
null-audio-sink that simply forwards the data to a real sink/souce. In
that case, we want the sink/source latency to be passed unmodified.

Set the monitor.passthrough on the pulseaudio null-sink because
a passthrough virtual sink is the most likely use case for this.

Add some monitor.passthrough default config where it makes sense.

Fixes #3888
This commit is contained in:
Wim Taymans 2024-03-11 16:16:51 +01:00
parent 10830ab9f8
commit ea524b158c
4 changed files with 46 additions and 26 deletions

View file

@ -238,6 +238,7 @@ struct impl {
unsigned int drained:1;
unsigned int rate_adjust:1;
unsigned int port_ignore_latency:1;
unsigned int monitor_passthrough:1;
uint32_t scratch_size;
uint32_t scratch_ports;
@ -2250,8 +2251,6 @@ impl_node_port_enum_params(void *object, int seq,
case 0: case 1:
{
uint32_t idx = result.index;
if (port->is_monitor)
idx = idx ^ 1;
param = spa_latency_build(&b, id, &port->latency[idx]);
break;
}
@ -2317,9 +2316,6 @@ static int port_set_latency(void *object,
this, direction, port_id, latency);
port = GET_PORT(this, direction, port_id);
if (port->is_monitor)
return 0;
if (latency == NULL) {
info = SPA_LATENCY_INFO(other);
have_latency = false;
@ -2341,32 +2337,50 @@ static int port_set_latency(void *object,
info.min_rate, info.max_rate,
info.min_ns, info.max_ns);
spa_latency_info_combine_start(&info, other);
for (i = 0; i < this->dir[direction].n_ports; i++) {
oport = GET_PORT(this, direction, i);
if (oport->is_monitor || !oport->have_latency)
continue;
spa_log_debug(this->log, "%p: combine %d", this, i);
spa_latency_info_combine(&info, &oport->latency[other]);
}
spa_latency_info_combine_finish(&info);
if (this->monitor_passthrough) {
if (port->is_monitor)
oport = GET_PORT(this, other, port_id-1);
else if (this->monitor && direction == SPA_DIRECTION_INPUT)
oport = GET_PORT(this, other, port_id+1);
else
return 0;
spa_log_debug(this->log, "%p: combined %s latency %f-%f %d-%d %"PRIu64"-%"PRIu64, this,
info.direction == SPA_DIRECTION_INPUT ? "input" : "output",
info.min_quantum, info.max_quantum,
info.min_rate, info.max_rate,
info.min_ns, info.max_ns);
for (i = 0; i < this->dir[other].n_ports; i++) {
oport = GET_PORT(this, other, i);
spa_log_debug(this->log, "%p: change %d", this, i);
if (spa_latency_info_compare(&info, &oport->latency[other]) != 0) {
if (oport != NULL &&
spa_latency_info_compare(&info, &oport->latency[other]) != 0) {
oport->latency[other] = info;
oport->info.change_mask |= SPA_PORT_CHANGE_MASK_PARAMS;
oport->params[IDX_Latency].user++;
emit_port_info(this, oport, false);
}
} else {
spa_latency_info_combine_start(&info, other);
for (i = 0; i < this->dir[direction].n_ports; i++) {
oport = GET_PORT(this, direction, i);
if ((oport->is_monitor) || !oport->have_latency)
continue;
spa_log_debug(this->log, "%p: combine %d", this, i);
spa_latency_info_combine(&info, &oport->latency[other]);
}
spa_latency_info_combine_finish(&info);
spa_log_debug(this->log, "%p: combined %s latency %f-%f %d-%d %"PRIu64"-%"PRIu64, this,
info.direction == SPA_DIRECTION_INPUT ? "input" : "output",
info.min_quantum, info.max_quantum,
info.min_rate, info.max_rate,
info.min_ns, info.max_ns);
for (i = 0; i < this->dir[other].n_ports; i++) {
oport = GET_PORT(this, other, i);
if (oport->is_monitor)
continue;
spa_log_debug(this->log, "%p: change %d", this, i);
if (spa_latency_info_compare(&info, &oport->latency[other]) != 0) {
oport->latency[other] = info;
oport->info.change_mask |= SPA_PORT_CHANGE_MASK_PARAMS;
oport->params[IDX_Latency].user++;
emit_port_info(this, oport, false);
}
}
}
if (emit) {
port->info.change_mask |= SPA_PORT_CHANGE_MASK_PARAMS;
@ -2391,7 +2405,7 @@ static int port_set_tag(void *object,
this, direction, port_id, tag);
port = GET_PORT(this, direction, port_id);
if (port->is_monitor)
if (port->is_monitor && !this->monitor_passthrough)
return 0;
if (tag != NULL) {
@ -3448,6 +3462,8 @@ impl_init(const struct spa_handle_factory *factory,
}
else if (spa_streq(k, SPA_KEY_PORT_IGNORE_LATENCY))
this->port_ignore_latency = spa_atob(s);
else if (spa_streq(k, "monitor.passthrough"))
this->monitor_passthrough = spa_atob(s);
else
audioconvert_set_param(this, k, s);
}