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: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5759>
This commit is contained in:
Sebastian Dröge 2023-12-04 18:45:49 +02:00 committed by GStreamer Marge Bot
parent 35390de50d
commit c4789e6de5
4 changed files with 90 additions and 62 deletions

View file

@ -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

View file

@ -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)
{

View file

@ -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)

View file

@ -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);
}
}