mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-18 14:26:43 +00:00
videorate: Only "close" the segment if it is discontinous
Otherwise, it will drop valid buffers on a simple segment update Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-base/-/merge_requests/767>
This commit is contained in:
parent
a76f38b2c7
commit
6f7922b4db
2 changed files with 60 additions and 40 deletions
|
@ -794,48 +794,14 @@ gst_video_rate_sink_event (GstBaseTransform * trans, GstEvent * event)
|
||||||
{
|
{
|
||||||
GstSegment segment;
|
GstSegment segment;
|
||||||
gint seqnum;
|
gint seqnum;
|
||||||
|
GstClockTime base_ts, next_ts;
|
||||||
|
gboolean reset_base_ts = FALSE;
|
||||||
|
|
||||||
gst_event_copy_segment (event, &segment);
|
gst_event_copy_segment (event, &segment);
|
||||||
if (segment.format != GST_FORMAT_TIME)
|
if (segment.format != GST_FORMAT_TIME)
|
||||||
goto format_error;
|
goto format_error;
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (videorate, "handle NEWSEGMENT");
|
GST_DEBUG_OBJECT (videorate, "handle SEGMENT event");
|
||||||
|
|
||||||
/* 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* We just want to update the accumulated stream_time */
|
/* 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.stop = (gint64) (segment.stop / videorate->rate);
|
||||||
segment.time = (gint64) (segment.time / 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_FORMAT_TIME,
|
||||||
gst_segment_to_running_time (&videorate->segment, GST_FORMAT_TIME,
|
gst_segment_to_running_time (&videorate->segment, GST_FORMAT_TIME,
|
||||||
videorate->base_ts));
|
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_FORMAT_TIME,
|
||||||
gst_segment_to_running_time (&videorate->segment, GST_FORMAT_TIME,
|
gst_segment_to_running_time (&videorate->segment, GST_FORMAT_TIME,
|
||||||
videorate->next_ts));
|
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_segment_copy_into (&segment, &videorate->segment);
|
||||||
GST_DEBUG_OBJECT (videorate, "updated segment: %" GST_SEGMENT_FORMAT,
|
GST_DEBUG_OBJECT (videorate, "updated segment: %" GST_SEGMENT_FORMAT,
|
||||||
&videorate->segment);
|
&videorate->segment);
|
||||||
|
|
||||||
|
|
||||||
seqnum = gst_event_get_seqnum (event);
|
seqnum = gst_event_get_seqnum (event);
|
||||||
gst_event_unref (event);
|
gst_event_unref (event);
|
||||||
event = gst_event_new_segment (&segment);
|
event = gst_event_new_segment (&segment);
|
||||||
|
|
|
@ -1645,12 +1645,17 @@ GST_START_TEST (test_segment_update)
|
||||||
next_ts += GST_SECOND / 25;
|
next_ts += GST_SECOND / 25;
|
||||||
}
|
}
|
||||||
gst_check_drop_buffers ();
|
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 */
|
/* Send a pointless segment update, shouldn't change anything */
|
||||||
gst_segment_init (&segment, GST_FORMAT_TIME);
|
gst_segment_init (&segment, GST_FORMAT_TIME);
|
||||||
segment.position = 5 * GST_SECOND;
|
segment.position = 5 * GST_SECOND;
|
||||||
fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_segment (&segment)));
|
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 buffer */
|
||||||
third = gst_buffer_new_and_alloc (4);
|
third = gst_buffer_new_and_alloc (4);
|
||||||
GST_BUFFER_TIMESTAMP (third) = 3 * GST_SECOND;
|
GST_BUFFER_TIMESTAMP (third) = 3 * GST_SECOND;
|
||||||
|
@ -1671,6 +1676,7 @@ GST_START_TEST (test_segment_update)
|
||||||
|
|
||||||
next_ts += GST_SECOND / 25;
|
next_ts += GST_SECOND / 25;
|
||||||
}
|
}
|
||||||
|
fail_unless_equals_uint64 (next_ts, (25 + 25 + 13) * (GST_SECOND / 25));
|
||||||
|
|
||||||
/* cleanup */
|
/* cleanup */
|
||||||
gst_buffer_unref (first);
|
gst_buffer_unref (first);
|
||||||
|
|
Loading…
Reference in a new issue