From 6f7922b4dbba5ed780e7b0988669a81848a9e333 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olivier=20Cr=C3=AAte?= Date: Fri, 24 Jul 2020 17:41:57 -0400 Subject: videorate: Only "close" the segment if it is discontinous Otherwise, it will drop valid buffers on a simple segment update Part-of: --- gst/videorate/gstvideorate.c | 94 +++++++++++++++++++++++----------------- tests/check/elements/videorate.c | 6 +++ 2 files changed, 60 insertions(+), 40 deletions(-) diff --git a/gst/videorate/gstvideorate.c b/gst/videorate/gstvideorate.c index d00f102a8..e12fe391c 100644 --- a/gst/videorate/gstvideorate.c +++ b/gst/videorate/gstvideorate.c @@ -794,48 +794,14 @@ gst_video_rate_sink_event (GstBaseTransform * trans, GstEvent * event) { GstSegment segment; gint seqnum; + GstClockTime base_ts, next_ts; + gboolean reset_base_ts = FALSE; gst_event_copy_segment (event, &segment); if (segment.format != GST_FORMAT_TIME) goto format_error; - GST_DEBUG_OBJECT (videorate, "handle NEWSEGMENT"); - - /* close up the previous segment, if appropriate */ - if (videorate->prevbuf) { - gint count = 0; - GstFlowReturn res; - - res = GST_FLOW_OK; - /* fill up to the end of current segment, - * or only send out the stored buffer if there is no specific stop. - * regardless, prevent going loopy in strange cases */ - while (res == GST_FLOW_OK && count <= MAGIC_LIMIT - && !videorate->drop_only - && ((videorate->segment.rate > 0.0 - && GST_CLOCK_TIME_IS_VALID (videorate->segment.stop) - && GST_CLOCK_TIME_IS_VALID (videorate->next_ts) - && videorate->next_ts - videorate->segment.base < - videorate->segment.stop) || (videorate->segment.rate < 0.0 - && GST_CLOCK_TIME_IS_VALID (videorate->segment.start) - && GST_CLOCK_TIME_IS_VALID (videorate->next_ts) - && videorate->next_ts - videorate->segment.base >= - videorate->segment.start) - || count < 1)) { - res = - gst_video_rate_flush_prev (videorate, count > 0, - GST_CLOCK_TIME_NONE); - count++; - } - if (count > 1) { - videorate->dup += count - 1; - if (!videorate->silent) - gst_video_rate_notify_duplicate (videorate); - } - /* clean up for the new one; _chain will resume from the new start */ - gst_video_rate_swap_prev (videorate, NULL, 0); - } - + GST_DEBUG_OBJECT (videorate, "handle SEGMENT event"); /* We just want to update the accumulated stream_time */ @@ -845,20 +811,68 @@ gst_video_rate_sink_event (GstBaseTransform * trans, GstEvent * event) segment.stop = (gint64) (segment.stop / videorate->rate); segment.time = (gint64) (segment.time / videorate->rate); - videorate->base_ts = gst_segment_position_from_running_time (&segment, + base_ts = gst_segment_position_from_running_time (&segment, GST_FORMAT_TIME, gst_segment_to_running_time (&videorate->segment, GST_FORMAT_TIME, videorate->base_ts)); - videorate->next_ts = gst_segment_position_from_running_time (&segment, + next_ts = gst_segment_position_from_running_time (&segment, GST_FORMAT_TIME, gst_segment_to_running_time (&videorate->segment, GST_FORMAT_TIME, videorate->next_ts)); + /* Reset if the segment is discontinuous */ + if (next_ts == GST_CLOCK_TIME_NONE) { + reset_base_ts = TRUE; + + /* close up the previous segment, if appropriate */ + if (videorate->prevbuf) { + gint count = 0; + GstFlowReturn res; + + res = GST_FLOW_OK; + /* fill up to the end of current segment, + * or only send out the stored buffer if there is no specific stop. + * regardless, prevent going loopy in strange cases */ + while (res == GST_FLOW_OK && count <= MAGIC_LIMIT + && !videorate->drop_only + && ((videorate->segment.rate > 0.0 + && GST_CLOCK_TIME_IS_VALID (videorate->segment.stop) + && GST_CLOCK_TIME_IS_VALID (videorate->next_ts) + && videorate->next_ts - videorate->segment.base < + videorate->segment.stop) || (videorate->segment.rate < 0.0 + && GST_CLOCK_TIME_IS_VALID (videorate->segment.start) + && GST_CLOCK_TIME_IS_VALID (videorate->next_ts) + && videorate->next_ts - videorate->segment.base >= + videorate->segment.start) + || count < 1)) { + res = + gst_video_rate_flush_prev (videorate, count > 0, + GST_CLOCK_TIME_NONE); + count++; + } + if (count > 1) { + videorate->dup += count - 1; + if (!videorate->silent) + gst_video_rate_notify_duplicate (videorate); + } + /* clean up for the new one; _chain will resume from the new start */ + gst_video_rate_swap_prev (videorate, NULL, 0); + } + } else if (base_ts == GST_CLOCK_TIME_NONE) { + reset_base_ts = TRUE; + } + + if (reset_base_ts) { + base_ts = 0; + videorate->out_frame_count = 0; + } + videorate->next_ts = next_ts; + videorate->base_ts = base_ts; + gst_segment_copy_into (&segment, &videorate->segment); GST_DEBUG_OBJECT (videorate, "updated segment: %" GST_SEGMENT_FORMAT, &videorate->segment); - seqnum = gst_event_get_seqnum (event); gst_event_unref (event); event = gst_event_new_segment (&segment); diff --git a/tests/check/elements/videorate.c b/tests/check/elements/videorate.c index a12393599..d3782155c 100644 --- a/tests/check/elements/videorate.c +++ b/tests/check/elements/videorate.c @@ -1645,12 +1645,17 @@ GST_START_TEST (test_segment_update) next_ts += GST_SECOND / 25; } gst_check_drop_buffers (); + fail_unless_equals_uint64 (next_ts, 1 * GST_SECOND + (GST_SECOND / 25)); /* Send a pointless segment update, shouldn't change anything */ gst_segment_init (&segment, GST_FORMAT_TIME); segment.position = 5 * GST_SECOND; fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_segment (&segment))); + /* Shouldnt push anything, rest is same as above */ + fail_unless_equals_int (g_list_length (buffers), 0); + assert_videorate_stats (videorate, "second", 2, 26, 0, 25); + /* third buffer */ third = gst_buffer_new_and_alloc (4); GST_BUFFER_TIMESTAMP (third) = 3 * GST_SECOND; @@ -1671,6 +1676,7 @@ GST_START_TEST (test_segment_update) next_ts += GST_SECOND / 25; } + fail_unless_equals_uint64 (next_ts, (25 + 25 + 13) * (GST_SECOND / 25)); /* cleanup */ gst_buffer_unref (first); -- cgit v1.2.1