From 6d423cbba26d22476675b481afa11c588792ebf7 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Sebastian=20Dr=C3=B6ge?= Date: Tue, 26 May 2020 22:45:41 +0300 Subject: [PATCH] audioresample: Drain the resampler and reset timestamp tracking on caps changes Especially when changing the sample rate our timestamp tracking will be completely off, but even otherwise we would usually lose the last few samples if we don't drain here as the resampler gets reset if anything but the sample rate changes. This is usually not a problem as the first buffer after a caps event usually has the discont flag set, but can cause problems if - the caps event is followed by a segment event, which then causes draining according to the new sample rate - the caps were changed because of rengotiation due to a reconfigure event and there is not discontinuity from upstream In both cases we would output buffers with completely wrong timestamps. Part-of: --- gst/audioresample/gstaudioresample.c | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/gst/audioresample/gstaudioresample.c b/gst/audioresample/gstaudioresample.c index a56bcdf..74e8db9 100644 --- a/gst/audioresample/gstaudioresample.c +++ b/gst/audioresample/gstaudioresample.c @@ -127,6 +127,9 @@ static gboolean gst_audio_resample_stop (GstBaseTransform * base); static gboolean gst_audio_resample_query (GstPad * pad, GstObject * parent, GstQuery * query); +static void gst_audio_resample_push_drain (GstAudioResample * resample, + guint history_len); + #define gst_audio_resample_parent_class parent_class G_DEFINE_TYPE (GstAudioResample, gst_audio_resample, GST_TYPE_BASE_TRANSFORM); @@ -497,7 +500,27 @@ gst_audio_resample_set_caps (GstBaseTransform * base, GstCaps * incaps, if (!gst_audio_info_from_caps (&out, outcaps)) goto invalid_outcaps; - /* FIXME do some checks */ + /* Reset timestamp tracking and drain the resampler if the audio format is + * changing. Especially when changing the sample rate our timestamp tracking + * will be completely off, but even otherwise we would usually lose the last + * few samples if we don't drain here */ + if (!gst_audio_info_is_equal (&in, &resample->in) || + !gst_audio_info_is_equal (&out, &resample->out)) { + if (resample->converter) { + gsize latency = gst_audio_converter_get_max_latency (resample->converter); + gst_audio_resample_push_drain (resample, latency); + } + gst_audio_resample_reset_state (resample); + resample->num_gap_samples = 0; + resample->num_nongap_samples = 0; + resample->t0 = GST_CLOCK_TIME_NONE; + resample->in_offset0 = GST_BUFFER_OFFSET_NONE; + resample->out_offset0 = GST_BUFFER_OFFSET_NONE; + resample->samples_in = 0; + resample->samples_out = 0; + resample->need_discont = TRUE; + } + gst_audio_resample_update_state (resample, &in, &out); resample->in = in; -- 2.7.4