modules: improve latency handling

Now that the stream remembers the latency for us, we can only care
about the other latency.

So, if we get (output) latency on an input port/stream, we add our
own latency and then set it on the output port/stream. We do the
same for input ports.
This commit is contained in:
Wim Taymans 2025-06-12 15:20:18 +02:00
parent 92243038c1
commit 046fdad4ee
3 changed files with 39 additions and 57 deletions

View file

@ -237,30 +237,20 @@ static void playback_process(void *d)
pw_stream_queue_buffer(impl->playback, out); pw_stream_queue_buffer(impl->playback, out);
} }
static void update_latencies(struct impl *impl) static void update_latency(struct impl *impl, enum spa_direction direction)
{ {
struct spa_latency_info latency; struct spa_latency_info latency;
uint8_t buffer[1024]; uint8_t buffer[1024];
struct spa_pod_builder b; struct spa_pod_builder b;
const struct spa_pod *play_params[2], *capt_params[2]; const struct spa_pod *params[1];
uint32_t n_params = 0; struct pw_stream *s = direction == SPA_DIRECTION_OUTPUT ?
impl->playback : impl->capture;
spa_pod_builder_init(&b, buffer, sizeof(buffer)); spa_pod_builder_init(&b, buffer, sizeof(buffer));
latency = impl->latency[direction];
latency = impl->latency[SPA_DIRECTION_INPUT];
play_params[n_params] = spa_latency_build(&b, SPA_PARAM_Latency, &latency);
spa_process_latency_info_add(&impl->process_latency, &latency); spa_process_latency_info_add(&impl->process_latency, &latency);
capt_params[n_params++] = spa_latency_build(&b, SPA_PARAM_Latency, &latency); params[0] = spa_latency_build(&b, SPA_PARAM_Latency, &latency);
pw_stream_update_params(s, params, 1);
latency = impl->latency[SPA_DIRECTION_OUTPUT];
capt_params[n_params] = spa_latency_build(&b, SPA_PARAM_Latency, &latency);
spa_process_latency_info_add(&impl->process_latency, &latency);
play_params[n_params++] = spa_latency_build(&b, SPA_PARAM_Latency, &latency);
if (impl->playback)
pw_stream_update_params(impl->playback, play_params, n_params);
if (impl->capture)
pw_stream_update_params(impl->capture, capt_params, n_params);
} }
static void param_latency_changed(struct impl *impl, const struct spa_pod *param) static void param_latency_changed(struct impl *impl, const struct spa_pod *param)
@ -271,7 +261,7 @@ static void param_latency_changed(struct impl *impl, const struct spa_pod *param
return; return;
impl->latency[latency.direction] = latency; impl->latency[latency.direction] = latency;
update_latencies(impl); update_latency(impl, latency.direction);
} }
static void stream_state_changed(void *data, enum pw_stream_state old, static void stream_state_changed(void *data, enum pw_stream_state old,

View file

@ -1198,29 +1198,26 @@ static int reset_graph(struct impl *impl)
return res; return res;
} }
static void update_latencies(struct impl *impl) static void update_latency(struct impl *impl, enum spa_direction direction)
{ {
struct spa_latency_info latency; struct spa_latency_info latency;
uint8_t buffer[1024]; uint8_t buffer[1024];
struct spa_pod_builder b; struct spa_pod_builder b;
const struct spa_pod *play_params[2], *capt_params[2]; const struct spa_pod *params[1];
struct pw_stream *s = direction == SPA_DIRECTION_OUTPUT ?
impl->playback : impl->capture;
spa_pod_builder_init(&b, buffer, sizeof(buffer)); spa_pod_builder_init(&b, buffer, sizeof(buffer));
latency = impl->latency[direction];
latency = impl->latency[SPA_DIRECTION_INPUT];
play_params[0] = spa_latency_build(&b, SPA_PARAM_Latency, &latency);
spa_process_latency_info_add(&impl->process_latency, &latency); spa_process_latency_info_add(&impl->process_latency, &latency);
capt_params[0] = spa_latency_build(&b, SPA_PARAM_Latency, &latency); params[0] = spa_latency_build(&b, SPA_PARAM_Latency, &latency);
pw_stream_update_params(s, params, 1);
}
latency = impl->latency[SPA_DIRECTION_OUTPUT]; static void update_latencies(struct impl *impl)
capt_params[1] = spa_latency_build(&b, SPA_PARAM_Latency, &latency); {
spa_process_latency_info_add(&impl->process_latency, &latency); update_latency(impl, SPA_DIRECTION_INPUT);
play_params[1] = spa_latency_build(&b, SPA_PARAM_Latency, &latency); update_latency(impl, SPA_DIRECTION_OUTPUT);
if (impl->playback)
pw_stream_update_params(impl->playback, play_params, 2);
if (impl->capture)
pw_stream_update_params(impl->capture, capt_params, 2);
} }
static void param_latency_changed(struct impl *impl, const struct spa_pod *param, static void param_latency_changed(struct impl *impl, const struct spa_pod *param,
@ -1232,7 +1229,7 @@ static void param_latency_changed(struct impl *impl, const struct spa_pod *param
return; return;
impl->latency[latency.direction] = latency; impl->latency[latency.direction] = latency;
update_latencies(impl); update_latency(impl, latency.direction);
} }
static void param_process_latency_changed(struct impl *impl, const struct spa_pod *param, static void param_process_latency_changed(struct impl *impl, const struct spa_pod *param,

View file

@ -441,46 +441,41 @@ static void playback_process(void *d)
pw_stream_queue_buffer(impl->playback, out); pw_stream_queue_buffer(impl->playback, out);
} }
static void update_latencies(struct impl *impl, bool props, bool process) static void update_latency(struct impl *impl, enum spa_direction direction, bool props, bool process)
{ {
struct spa_latency_info latency; struct spa_latency_info latency;
uint8_t buffer[1024]; uint8_t buffer[1024];
struct spa_pod_builder b; struct spa_pod_builder b;
const struct spa_pod *play_params[4], *capt_params[4]; const struct spa_pod *params[3];
uint32_t n_params = 0; uint32_t n_params = 0;
struct pw_stream *s = direction == SPA_DIRECTION_OUTPUT ?
impl->playback : impl->capture;
if (s == NULL)
return;
spa_pod_builder_init(&b, buffer, sizeof(buffer)); spa_pod_builder_init(&b, buffer, sizeof(buffer));
latency = impl->latency[direction];
latency = impl->latency[SPA_DIRECTION_INPUT];
play_params[n_params] = spa_latency_build(&b, SPA_PARAM_Latency, &latency);
spa_process_latency_info_add(&impl->process_latency, &latency); spa_process_latency_info_add(&impl->process_latency, &latency);
capt_params[n_params++] = spa_latency_build(&b, SPA_PARAM_Latency, &latency); params[n_params++] = spa_latency_build(&b, SPA_PARAM_Latency, &latency);
latency = impl->latency[SPA_DIRECTION_OUTPUT];
capt_params[n_params] = spa_latency_build(&b, SPA_PARAM_Latency, &latency);
spa_process_latency_info_add(&impl->process_latency, &latency);
play_params[n_params++] = spa_latency_build(&b, SPA_PARAM_Latency, &latency);
if (props) { if (props) {
int64_t nsec = impl->process_latency.ns; int64_t nsec = impl->process_latency.ns;
play_params[n_params] = spa_pod_builder_add_object(&b, params[n_params++] = spa_pod_builder_add_object(&b,
SPA_TYPE_OBJECT_Props, SPA_PARAM_Props,
SPA_PROP_latencyOffsetNsec, SPA_POD_Long(nsec));
capt_params[n_params++] = spa_pod_builder_add_object(&b,
SPA_TYPE_OBJECT_Props, SPA_PARAM_Props, SPA_TYPE_OBJECT_Props, SPA_PARAM_Props,
SPA_PROP_latencyOffsetNsec, SPA_POD_Long(nsec)); SPA_PROP_latencyOffsetNsec, SPA_POD_Long(nsec));
} }
if (process) { if (process) {
play_params[n_params] = spa_process_latency_build(&b, params[n_params++] = spa_process_latency_build(&b,
SPA_PARAM_ProcessLatency, &impl->process_latency);
capt_params[n_params++] = spa_process_latency_build(&b,
SPA_PARAM_ProcessLatency, &impl->process_latency); SPA_PARAM_ProcessLatency, &impl->process_latency);
} }
pw_stream_update_params(s, params, n_params);
}
if (impl->playback) static void update_latencies(struct impl *impl, bool props, bool process)
pw_stream_update_params(impl->playback, play_params, n_params); {
if (impl->capture) update_latency(impl, SPA_DIRECTION_INPUT, props, process);
pw_stream_update_params(impl->capture, capt_params, n_params); update_latency(impl, SPA_DIRECTION_OUTPUT, props, process);
} }
static void param_latency_changed(struct impl *impl, const struct spa_pod *param) static void param_latency_changed(struct impl *impl, const struct spa_pod *param)
@ -491,7 +486,7 @@ static void param_latency_changed(struct impl *impl, const struct spa_pod *param
return; return;
impl->latency[latency.direction] = latency; impl->latency[latency.direction] = latency;
update_latencies(impl, false, false); update_latency(impl, latency.direction, false, false);
} }
static void param_process_latency_changed(struct impl *impl, const struct spa_pod *param) static void param_process_latency_changed(struct impl *impl, const struct spa_pod *param)