From ac95f796bf74ba945ef85fd3187a3332fc16d9dd Mon Sep 17 00:00:00 2001 From: Pauli Virtanen Date: Fri, 19 Apr 2024 00:29:08 +0300 Subject: [PATCH] combine-stream: fix latency-compensate with resample.disabled=true When resample.disabled=true, which is now the default, Format has zero rate, so latency buffers get zero size. The rate in this case is the graph rate. Fix by just using the delay in samples, as all streams must in any case run at same rate for the combining to work. Fixes: bff252ce60f7 ("combine-stream: actually make use of resample.disable") --- src/modules/module-combine-stream.c | 41 +++++++++-------------------- 1 file changed, 13 insertions(+), 28 deletions(-) diff --git a/src/modules/module-combine-stream.c b/src/modules/module-combine-stream.c index c5bc00796..8f9ff0593 100644 --- a/src/modules/module-combine-stream.c +++ b/src/modules/module-combine-stream.c @@ -305,13 +305,12 @@ struct stream { struct spa_audio_info_raw info; uint32_t remap[SPA_AUDIO_MAX_CHANNELS]; - uint32_t rate; void *delaybuf; struct ringbuffer delay[SPA_AUDIO_MAX_CHANNELS]; - int64_t delay_nsec; /* for main loop */ - int64_t data_delay_nsec; /* for data loop */ + int64_t delay_samples; /* for main loop */ + int64_t data_delay_samples; /* for data loop */ unsigned int ready:1; unsigned int added:1; @@ -441,11 +440,10 @@ static int64_t get_stream_delay(struct stream *s) { struct pw_time t; - if (pw_stream_get_time_n(s->stream, &t, sizeof(t)) < 0 || - t.rate.denom == 0) + if (pw_stream_get_time_n(s->stream, &t, sizeof(t)) < 0) return INT64_MIN; - return t.delay * SPA_NSEC_PER_SEC * t.rate.num / t.rate.denom; + return t.delay; /* samples at graph rate */ } static void update_latency(struct impl *impl) @@ -558,20 +556,19 @@ static void update_delay(struct impl *impl) spa_list_for_each(s, &impl->streams, link) { int64_t delay = get_stream_delay(s); - if (delay != s->delay_nsec && delay != INT64_MIN) - pw_log_debug("stream %d delay:%"PRIi64" ns", s->id, delay); + if (delay != s->delay_samples && delay != INT64_MIN) + pw_log_debug("stream %d delay:%"PRIi64" samples", s->id, delay); max_delay = SPA_MAX(max_delay, delay); - s->delay_nsec = delay; + s->delay_samples = delay; } spa_list_for_each(s, &impl->streams, link) { uint32_t size = 0; - if (s->delay_nsec != INT64_MIN) { - int64_t delay = max_delay - s->delay_nsec; - size = delay * s->rate / SPA_NSEC_PER_SEC; - size *= sizeof(float); + if (s->delay_samples != INT64_MIN) { + int64_t delay = max_delay - s->delay_samples; + size = delay * sizeof(float); } resize_delay(s, size); @@ -708,22 +705,9 @@ static void stream_param_changed(void *d, uint32_t id, const struct spa_pod *par { struct stream *s = d; struct spa_latency_info latency; - struct spa_audio_info format = { 0 }; switch (id) { case SPA_PARAM_Format: - if (!param) { - s->rate = 0; - } else { - if (spa_format_parse(param, &format.media_type, &format.media_subtype) < 0) - break; - if (format.media_type != SPA_MEDIA_TYPE_audio || - format.media_subtype != SPA_MEDIA_SUBTYPE_raw) - break; - if (spa_format_audio_raw_parse(param, &format.info.raw) < 0) - break; - s->rate = format.info.raw.rate; - } update_delay(s->impl); break; case SPA_PARAM_Latency: @@ -735,6 +719,7 @@ static void stream_param_changed(void *d, uint32_t id, const struct spa_pod *par s->latency = latency; } update_latency(s->impl); + update_delay(s->impl); break; default: break; @@ -1075,10 +1060,10 @@ static bool check_stream_delay(struct stream *s) return false; delay = get_stream_delay(s); - if (delay == INT64_MIN || delay == s->data_delay_nsec) + if (delay == INT64_MIN || delay == s->data_delay_samples) return false; - s->data_delay_nsec = delay; + s->data_delay_samples = delay; return true; }