videorate: Reset last_ts when a new segment is received

This fix all buffers being droped when a new segment is received and
average-period property is set.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6522>
This commit is contained in:
Xavier Claessens 2024-04-01 18:00:53 -04:00 committed by Tim-Philipp Müller
parent 3fe9a6dc8c
commit e47f9e8f87
2 changed files with 52 additions and 0 deletions

View file

@ -1039,6 +1039,7 @@ gst_video_rate_sink_event (GstBaseTransform * trans, GstEvent * event)
videorate->base_ts = segment.start;
videorate->out_frame_count = 0;
videorate->next_ts = GST_CLOCK_TIME_NONE;
videorate->last_ts = GST_CLOCK_TIME_NONE;
gst_buffer_replace (&videorate->prevbuf, NULL);
}

View file

@ -2018,6 +2018,56 @@ GST_START_TEST (test_segment_update_same)
}
GST_END_TEST;
GST_START_TEST (test_segment_update_average_period)
{
GstElement *videorate;
GstBuffer *buf;
GstCaps *caps;
GstSegment segment;
/* Create a videorate that outputs at most 1 frame per second. */
videorate = setup_videorate_full (&srctemplate, &downstreamsinktemplate);
g_object_set (videorate, "drop-only", TRUE, "average-period", GST_SECOND,
NULL);
fail_unless (gst_element_set_state (videorate,
GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
"could not set to playing");
caps = gst_caps_from_string (VIDEO_CAPS_STRING);
gst_check_setup_events (mysrcpad, videorate, caps, GST_FORMAT_TIME);
gst_caps_unref (caps);
/* Segment starts at 0 */
gst_segment_init (&segment, GST_FORMAT_TIME);
fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_segment (&segment)));
/* First buffer at t=30s (pts=30s + segment.base=0s). */
buf = gst_buffer_new_and_alloc (4);
GST_BUFFER_PTS (buf) = 30 * GST_SECOND;
fail_unless (gst_pad_push (mysrcpad, buf) == GST_FLOW_OK);
fail_unless_equals_int (g_list_length (buffers), 1);
assert_videorate_stats (videorate, "first", 1, 1, 0, 0);
/* Simulate a pad offset of 30s */
segment.base = 30 * GST_SECOND;
fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_segment (&segment)));
/* Second buffer at t=32s (pts=2s + segment.base=30s). Videorate used to do
* current PTS (2s) - previous PTS (30s) = -28s, negative value being always
* smaller than the target average, the buffer was droped. This verify that it
* now correctly reset average computation when receiving a new segment. */
buf = gst_buffer_new_and_alloc (4);
GST_BUFFER_PTS (buf) = 2 * GST_SECOND;
fail_unless (gst_pad_push (mysrcpad, buf) == GST_FLOW_OK);
fail_unless_equals_int (g_list_length (buffers), 2);
assert_videorate_stats (videorate, "second", 2, 2, 0, 0);
/* cleanup */
cleanup_videorate (videorate);
}
GST_END_TEST;
static Suite *
videorate_suite (void)
{
@ -2047,6 +2097,7 @@ videorate_suite (void)
tcase_add_test (tc_chain, test_segment_base_nonzero);
tcase_add_test (tc_chain, test_segment_update_start_advance);
tcase_add_test (tc_chain, test_segment_update_same);
tcase_add_test (tc_chain, test_segment_update_average_period);
return s;
}