From c4789e6de59f934dbc24f043a67be0a85b2ca95c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Mon, 4 Dec 2023 18:45:49 +0200 Subject: [PATCH] audio: Consider the expected timestamp for discont-wait handling Otherwise if there is a huge gap it will only be considered a discontinuity after another discont-time amount of buffers has passed. Like this it will be immediately a discontinuity if the gap between the expected and received time becomes bigger than the discont-time. The last part of the test was actually testing for this behaviour and expected the previous behaviour. Most other tests also had to be adjusted because discont will now happen at slightly different times than before. Part-of: --- .../gst-libs/gst/audio/gstaudioaggregator.c | 19 +++- .../gst-libs/gst/audio/gstaudiobasesink.c | 15 ++- .../gst-libs/gst/audio/gstaudiostreamalign.c | 14 ++- .../gst-plugins-base/tests/check/libs/audio.c | 104 +++++++++--------- 4 files changed, 90 insertions(+), 62 deletions(-) diff --git a/subprojects/gst-plugins-base/gst-libs/gst/audio/gstaudioaggregator.c b/subprojects/gst-plugins-base/gst-libs/gst/audio/gstaudioaggregator.c index d967a3295d..123cc78951 100644 --- a/subprojects/gst-plugins-base/gst-libs/gst/audio/gstaudioaggregator.c +++ b/subprojects/gst-plugins-base/gst-libs/gst/audio/gstaudioaggregator.c @@ -1806,6 +1806,7 @@ gst_audio_aggregator_post_messages (GstAudioAggregator * aagg) * Replace the current buffer with input and update GstAudioAggregatorPadPrivate * values. */ +#define ABSDIFF(a, b) ((a) > (b) ? (a) - (b) : (b) - (a)) static gboolean gst_audio_aggregator_fill_buffer (GstAudioAggregator * aagg, GstAudioAggregatorPad * pad) @@ -1873,12 +1874,13 @@ gst_audio_aggregator_fill_buffer (GstAudioAggregator * aagg, pad->priv->new_segment = FALSE; } else { guint64 diff, max_sample_diff; + GstClockTime expected_time; /* Check discont, based on audiobasesink */ - if (start_offset <= pad->priv->next_offset) - diff = pad->priv->next_offset - start_offset; - else - diff = start_offset - pad->priv->next_offset; + diff = ABSDIFF (pad->priv->next_offset, start_offset); + + expected_time = + gst_util_uint64_scale (pad->priv->next_offset, GST_SECOND, rate); max_sample_diff = gst_util_uint64_scale_int (aagg->priv->alignment_threshold, rate, @@ -1888,8 +1890,11 @@ gst_audio_aggregator_fill_buffer (GstAudioAggregator * aagg, if (G_UNLIKELY (diff >= max_sample_diff)) { if (aagg->priv->discont_wait > 0) { if (pad->priv->discont_time == GST_CLOCK_TIME_NONE) { - pad->priv->discont_time = start_time; - } else if (start_time - pad->priv->discont_time >= + if (ABSDIFF (expected_time, start_time) >= aagg->priv->discont_wait) + discont = TRUE; + else + pad->priv->discont_time = expected_time; + } else if (ABSDIFF (start_time, pad->priv->discont_time) >= aagg->priv->discont_wait) { discont = TRUE; pad->priv->discont_time = GST_CLOCK_TIME_NONE; @@ -2046,6 +2051,8 @@ done: return TRUE; } +#undef ABSDIFF + /* Called with pad object lock held */ static gboolean diff --git a/subprojects/gst-plugins-base/gst-libs/gst/audio/gstaudiobasesink.c b/subprojects/gst-plugins-base/gst-libs/gst/audio/gstaudiobasesink.c index 1f843acf44..bc0b7c881f 100644 --- a/subprojects/gst-plugins-base/gst-libs/gst/audio/gstaudiobasesink.c +++ b/subprojects/gst-plugins-base/gst-libs/gst/audio/gstaudiobasesink.c @@ -1728,6 +1728,7 @@ flushing: } } +#define ABSDIFF(a, b) ((a) > (b) ? (a) - (b) : (b) - (a)) static gint64 gst_audio_base_sink_get_alignment (GstAudioBaseSink * sink, GstClockTime sample_offset) @@ -1764,10 +1765,16 @@ gst_audio_base_sink_get_alignment (GstAudioBaseSink * sink, if (sink->priv->discont_wait > 0) { GstClockTime time = gst_util_uint64_scale_int (sample_offset, GST_SECOND, rate); + GstClockTime expected_time = gst_util_uint64_scale_int (sink->next_sample, + GST_SECOND, rate); + if (sink->priv->discont_time == -1) { - /* discont candidate */ - sink->priv->discont_time = time; - } else if (time - sink->priv->discont_time >= sink->priv->discont_wait) { + if (ABSDIFF (expected_time, time) >= sink->priv->discont_wait) + discont = TRUE; + else + sink->priv->discont_time = expected_time; + } else if (ABSDIFF (time, + sink->priv->discont_time) >= sink->priv->discont_wait) { /* discont_wait expired, discontinuity detected */ discont = TRUE; sink->priv->discont_time = -1; @@ -1805,6 +1812,8 @@ gst_audio_base_sink_get_alignment (GstAudioBaseSink * sink, return align; } +#undef ABSDIFF + static GstFlowReturn gst_audio_base_sink_render (GstBaseSink * bsink, GstBuffer * buf) { diff --git a/subprojects/gst-plugins-base/gst-libs/gst/audio/gstaudiostreamalign.c b/subprojects/gst-plugins-base/gst-libs/gst/audio/gstaudiostreamalign.c index caabc842ed..89d9881069 100644 --- a/subprojects/gst-plugins-base/gst-libs/gst/audio/gstaudiostreamalign.c +++ b/subprojects/gst-plugins-base/gst-libs/gst/audio/gstaudiostreamalign.c @@ -370,6 +370,7 @@ gst_audio_stream_align_process (GstAudioStreamAlign * align, discont = TRUE; } else { guint64 diff, max_sample_diff; + GstClockTime expected_time; /* Check discont */ if (align->rate > 0) { @@ -378,6 +379,10 @@ gst_audio_stream_align_process (GstAudioStreamAlign * align, diff = ABSDIFF (end_offset, align->next_offset); } + expected_time = + gst_util_uint64_scale (align->next_offset, GST_SECOND, + ABS (align->rate)); + max_sample_diff = gst_util_uint64_scale_int (align->alignment_threshold, ABS (align->rate), GST_SECOND); @@ -386,7 +391,14 @@ gst_audio_stream_align_process (GstAudioStreamAlign * align, if (G_UNLIKELY (diff >= max_sample_diff)) { if (align->discont_wait > 0) { if (align->discont_time == GST_CLOCK_TIME_NONE) { - align->discont_time = align->rate > 0 ? start_time : end_time; + if (align->rate > 0 + && ABSDIFF (expected_time, start_time) >= align->discont_wait) + discont = TRUE; + else if (align->rate < 0 + && ABSDIFF (expected_time, end_time) >= align->discont_wait) + discont = TRUE; + else + align->discont_time = expected_time; } else if ((align->rate > 0 && ABSDIFF (start_time, align->discont_time) >= align->discont_wait) diff --git a/subprojects/gst-plugins-base/tests/check/libs/audio.c b/subprojects/gst-plugins-base/tests/check/libs/audio.c index 7a01995e2d..1d570073f3 100644 --- a/subprojects/gst-plugins-base/tests/check/libs/audio.c +++ b/subprojects/gst-plugins-base/tests/check/libs/audio.c @@ -1005,17 +1005,17 @@ GST_START_TEST (test_stream_align) gst_audio_stream_align_process (align, discont, timestamp, 10, &out_timestamp, &out_duration, NULL); - fail_unless_equals_uint64 (out_timestamp, 10 * GST_MSECOND * i); - fail_unless_equals_uint64 (out_duration, 10 * GST_MSECOND); if (i == 0) fail_unless (discont); else fail_unless (!discont); + fail_unless_equals_uint64 (out_timestamp, 10 * GST_MSECOND * i); + fail_unless_equals_uint64 (out_duration, 10 * GST_MSECOND); } /* Drift forwards by 1ms per 10ms buffer for the first 40 buffers. * - after 40 buffers we're above alignment threshold - * - after 40 + 100 buffers we're at discont wait + * - after 40 + 96 buffers we're at discont wait */ for (i = 0; i < 500; i++) { timestamp = 10 * GST_MSECOND * i; @@ -1027,15 +1027,15 @@ GST_START_TEST (test_stream_align) gst_audio_stream_align_process (align, discont, timestamp, 10, &out_timestamp, &out_duration, NULL); - if (i < 140) { - fail_unless_equals_uint64 (out_timestamp, 10 * GST_MSECOND * i); - fail_unless_equals_uint64 (out_duration, 10 * GST_MSECOND); + if (i < 136) { if (i == 0) fail_unless (discont); else fail_unless (!discont); + fail_unless_equals_uint64 (out_timestamp, 10 * GST_MSECOND * i); + fail_unless_equals_uint64 (out_duration, 10 * GST_MSECOND); } else { - if (i == 140) + if (i == 136) fail_unless (discont); else fail_unless (!discont); @@ -1047,7 +1047,7 @@ GST_START_TEST (test_stream_align) /* Drift backwards by 1ms per 10ms buffer for the first 40 buffers. * - after 40 buffers we're above alignment threshold - * - after 40 + 100 buffers we're at discont wait + * - after 40 + 104 buffers we're at discont wait */ for (i = 0; i < 500; i++) { timestamp = 10 * GST_MSECOND * i; @@ -1059,15 +1059,15 @@ GST_START_TEST (test_stream_align) gst_audio_stream_align_process (align, discont, timestamp, 10, &out_timestamp, &out_duration, NULL); - if (i < 140) { - fail_unless_equals_uint64 (out_timestamp, 10 * GST_MSECOND * i); - fail_unless_equals_uint64 (out_duration, 10 * GST_MSECOND); + if (i < 144) { if (i == 0) fail_unless (discont); else fail_unless (!discont); + fail_unless_equals_uint64 (out_timestamp, 10 * GST_MSECOND * i); + fail_unless_equals_uint64 (out_duration, 10 * GST_MSECOND); } else { - if (i == 140) + if (i == 144) fail_unless (discont); else fail_unless (!discont); @@ -1080,7 +1080,7 @@ GST_START_TEST (test_stream_align) /* Shift all buffers but the first by 40ms * - after 1 buffers we're above alignment threshold - * - after 101 buffers we're at discont wait + * - after 97 buffers we're at discont wait */ for (i = 0; i < 500; i++) { timestamp = 10 * GST_MSECOND * i; @@ -1092,15 +1092,15 @@ GST_START_TEST (test_stream_align) gst_audio_stream_align_process (align, discont, timestamp, 10, &out_timestamp, &out_duration, NULL); - if (i < 101) { - fail_unless_equals_uint64 (out_timestamp, 10 * GST_MSECOND * i); - fail_unless_equals_uint64 (out_duration, 10 * GST_MSECOND); + if (i < 97) { if (i == 0) fail_unless (discont); else fail_unless (!discont); + fail_unless_equals_uint64 (out_timestamp, 10 * GST_MSECOND * i); + fail_unless_equals_uint64 (out_duration, 10 * GST_MSECOND); } else { - if (i == 101) + if (i == 97) fail_unless (discont); else fail_unless (!discont); @@ -1124,15 +1124,15 @@ GST_START_TEST (test_stream_align) gst_audio_stream_align_process (align, discont, timestamp, 10, &out_timestamp, &out_duration, NULL); - fail_unless_equals_uint64 (out_timestamp, 10 * GST_MSECOND * i); - fail_unless_equals_uint64 (out_duration, 10 * GST_MSECOND); if (i == 0) fail_unless (discont); else fail_unless (!discont); + fail_unless_equals_uint64 (out_timestamp, 10 * GST_MSECOND * i); + fail_unless_equals_uint64 (out_duration, 10 * GST_MSECOND); } - /* Shift every buffer 100 by 2: discont at buffer 200 + /* Shift every buffer after 100 by 2s: discont at buffer 100 */ for (i = 0; i < 500; i++) { timestamp = 10 * GST_MSECOND * i; @@ -1144,21 +1144,21 @@ GST_START_TEST (test_stream_align) gst_audio_stream_align_process (align, discont, timestamp, 10, &out_timestamp, &out_duration, NULL); - if (i < 200) { - fail_unless_equals_uint64 (out_timestamp, 10 * GST_MSECOND * i); - fail_unless_equals_uint64 (out_duration, 10 * GST_MSECOND); + if (i < 100) { if (i == 0) fail_unless (discont); else fail_unless (!discont); - } else { - fail_unless_equals_uint64 (out_timestamp, - 10 * GST_MSECOND * i + 2 * GST_SECOND); + fail_unless_equals_uint64 (out_timestamp, 10 * GST_MSECOND * i); fail_unless_equals_uint64 (out_duration, 10 * GST_MSECOND); - if (i == 200) + } else { + if (i == 100) fail_unless (discont); else fail_unless (!discont); + fail_unless_equals_uint64 (out_timestamp, + 10 * GST_MSECOND * i + 2 * GST_SECOND); + fail_unless_equals_uint64 (out_duration, 10 * GST_MSECOND); } } @@ -1185,12 +1185,12 @@ GST_START_TEST (test_stream_align_reverse) gst_audio_stream_align_process (align, discont, timestamp, 10, &out_timestamp, &out_duration, NULL); - fail_unless_equals_uint64 (out_timestamp, 10 * GST_MSECOND * i); - fail_unless_equals_uint64 (out_duration, 10 * GST_MSECOND); if (i == 499) fail_unless (discont); else fail_unless (!discont); + fail_unless_equals_uint64 (out_timestamp, 10 * GST_MSECOND * i); + fail_unless_equals_uint64 (out_duration, 10 * GST_MSECOND); } /* Drift forwards by 1ms per 10ms buffer for the first 40 buffers. @@ -1207,15 +1207,15 @@ GST_START_TEST (test_stream_align_reverse) gst_audio_stream_align_process (align, discont, timestamp, 10, &out_timestamp, &out_duration, NULL); - if (i >= 500 - 140) { - fail_unless_equals_uint64 (out_timestamp, 10 * GST_MSECOND * i); - fail_unless_equals_uint64 (out_duration, 10 * GST_MSECOND); + if (i >= 500 - 144) { if (i == 499) fail_unless (discont); else fail_unless (!discont); + fail_unless_equals_uint64 (out_timestamp, 10 * GST_MSECOND * i); + fail_unless_equals_uint64 (out_duration, 10 * GST_MSECOND); } else { - if (i == 499 - 140) + if (i == 499 - 144) fail_unless (discont); else fail_unless (!discont); @@ -1239,15 +1239,15 @@ GST_START_TEST (test_stream_align_reverse) gst_audio_stream_align_process (align, discont, timestamp, 10, &out_timestamp, &out_duration, NULL); - if (i >= 500 - 140) { - fail_unless_equals_uint64 (out_timestamp, 10 * GST_MSECOND * i); - fail_unless_equals_uint64 (out_duration, 10 * GST_MSECOND); + if (i >= 500 - 136) { if (i == 499) fail_unless (discont); else fail_unless (!discont); + fail_unless_equals_uint64 (out_timestamp, 10 * GST_MSECOND * i); + fail_unless_equals_uint64 (out_duration, 10 * GST_MSECOND); } else { - if (i == 499 - 140) + if (i == 499 - 136) fail_unless (discont); else fail_unless (!discont); @@ -1260,7 +1260,7 @@ GST_START_TEST (test_stream_align_reverse) /* Shift all buffers but the first by 40ms * - after 1 buffers we're above alignment threshold - * - after 101 buffers we're at discont wait + * - after 106 buffers we're at discont wait */ for (i = 499; i >= 0; i--) { timestamp = 10 * GST_MSECOND * i; @@ -1272,15 +1272,15 @@ GST_START_TEST (test_stream_align_reverse) gst_audio_stream_align_process (align, discont, timestamp, 10, &out_timestamp, &out_duration, NULL); - if (i >= 500 - 101) { - fail_unless_equals_uint64 (out_timestamp, 10 * GST_MSECOND * i); - fail_unless_equals_uint64 (out_duration, 10 * GST_MSECOND); + if (i >= 500 - 105) { if (i == 499) fail_unless (discont); else fail_unless (!discont); + fail_unless_equals_uint64 (out_timestamp, 10 * GST_MSECOND * i); + fail_unless_equals_uint64 (out_duration, 10 * GST_MSECOND); } else { - if (i == 499 - 101) + if (i == 499 - 105) fail_unless (discont); else fail_unless (!discont); @@ -1304,15 +1304,15 @@ GST_START_TEST (test_stream_align_reverse) gst_audio_stream_align_process (align, discont, timestamp, 10, &out_timestamp, &out_duration, NULL); - fail_unless_equals_uint64 (out_timestamp, 10 * GST_MSECOND * i); - fail_unless_equals_uint64 (out_duration, 10 * GST_MSECOND); if (i == 499) fail_unless (discont); else fail_unless (!discont); + fail_unless_equals_uint64 (out_timestamp, 10 * GST_MSECOND * i); + fail_unless_equals_uint64 (out_duration, 10 * GST_MSECOND); } - /* Shift buffer 100 by 2: discont at buffer 200 + /* Shift every buffer after 100 by 2s: discont at buffer 100 */ for (i = 499; i >= 0; i--) { timestamp = 10 * GST_MSECOND * i; @@ -1324,21 +1324,21 @@ GST_START_TEST (test_stream_align_reverse) gst_audio_stream_align_process (align, discont, timestamp, 10, &out_timestamp, &out_duration, NULL); - if (i >= 500 - 200) { - fail_unless_equals_uint64 (out_timestamp, 10 * GST_MSECOND * i); - fail_unless_equals_uint64 (out_duration, 10 * GST_MSECOND); + if (i >= 500 - 100) { if (i == 499) fail_unless (discont); else fail_unless (!discont); - } else { - fail_unless_equals_uint64 (out_timestamp, - 10 * GST_MSECOND * i + 2 * GST_SECOND); + fail_unless_equals_uint64 (out_timestamp, 10 * GST_MSECOND * i); fail_unless_equals_uint64 (out_duration, 10 * GST_MSECOND); - if (i == 499 - 200) + } else { + if (i == 499 - 100) fail_unless (discont); else fail_unless (!discont); + fail_unless_equals_uint64 (out_timestamp, + 10 * GST_MSECOND * i + 2 * GST_SECOND); + fail_unless_equals_uint64 (out_duration, 10 * GST_MSECOND); } }