diff --git a/tests/check/libs/audiodecoder.c b/tests/check/libs/audiodecoder.c index 5d2e1828ff..52b6b12588 100644 --- a/tests/check/libs/audiodecoder.c +++ b/tests/check/libs/audiodecoder.c @@ -416,6 +416,69 @@ GST_START_TEST (audiodecoder_delayed_negotiation_with_gap_event) GST_END_TEST; +GST_START_TEST (audiodecoder_buffer_after_segment) +{ + GstSegment segment; + GstBuffer *buffer; + guint64 i; + GstClockTime pos; + + setup_audiodecodertester (); + + gst_pad_set_active (mysrcpad, TRUE); + gst_element_set_state (dec, GST_STATE_PLAYING); + gst_pad_set_active (mysinkpad, TRUE); + + send_startup_events (); + + /* push a new segment */ + gst_segment_init (&segment, GST_FORMAT_TIME); + segment.stop = GST_SECOND; + fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_segment (&segment))); + + /* push buffers, the data is actually a number so we can track them */ + i = 0; + pos = 0; + while (pos < GST_SECOND) { + GstMapInfo map; + guint64 num; + + buffer = create_test_buffer (i); + pos = GST_BUFFER_TIMESTAMP (buffer) + GST_BUFFER_DURATION (buffer); + + fail_unless (gst_pad_push (mysrcpad, buffer) == GST_FLOW_OK); + + /* check that buffer was received by our source pad */ + buffer = buffers->data; + + gst_buffer_map (buffer, &map, GST_MAP_READ); + + num = *(guint64 *) map.data; + fail_unless_equals_uint64 (i, num); + fail_unless_equals_uint64 (GST_BUFFER_PTS (buffer), + gst_util_uint64_scale_round (i, GST_SECOND, TEST_MSECS_PER_SAMPLE)); + fail_unless_equals_uint64 (GST_BUFFER_DURATION (buffer), + gst_util_uint64_scale_round (1, GST_SECOND, TEST_MSECS_PER_SAMPLE)); + + gst_buffer_unmap (buffer, &map); + + gst_buffer_unref (buffer); + buffers = g_list_delete_link (buffers, buffers); + i++; + } + + /* this buffer is after the segment */ + buffer = create_test_buffer (i++); + fail_unless (gst_pad_push (mysrcpad, buffer) == GST_FLOW_EOS); + + fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_eos ())); + + fail_unless (buffers == NULL); + + cleanup_audiodecodertest (); +} + +GST_END_TEST; static Suite * gst_audiodecoder_suite (void) { @@ -427,6 +490,7 @@ gst_audiodecoder_suite (void) tcase_add_test (tc, audiodecoder_negotiation_with_buffer); tcase_add_test (tc, audiodecoder_negotiation_with_gap_event); tcase_add_test (tc, audiodecoder_delayed_negotiation_with_gap_event); + tcase_add_test (tc, audiodecoder_buffer_after_segment); return s; } diff --git a/tests/check/libs/videodecoder.c b/tests/check/libs/videodecoder.c index 628a48bf3c..b8a2c49459 100644 --- a/tests/check/libs/videodecoder.c +++ b/tests/check/libs/videodecoder.c @@ -481,6 +481,74 @@ GST_START_TEST (videodecoder_playback_first_frames_not_decoded) GST_END_TEST; +GST_START_TEST (videodecoder_buffer_after_segment) +{ + GstSegment segment; + GstBuffer *buffer; + guint64 i; + GstClockTime pos; + GList *iter; + + setup_videodecodertester (); + + gst_pad_set_active (mysrcpad, TRUE); + gst_element_set_state (dec, GST_STATE_PLAYING); + gst_pad_set_active (mysinkpad, TRUE); + + send_startup_events (); + + /* push a new segment */ + gst_segment_init (&segment, GST_FORMAT_TIME); + segment.stop = GST_SECOND; + fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_segment (&segment))); + + /* push buffers until we fill our segment */ + i = 0; + while (pos < GST_SECOND) { + buffer = create_test_buffer (i++); + + pos = GST_BUFFER_TIMESTAMP (buffer) + GST_BUFFER_DURATION (buffer); + fail_unless (gst_pad_push (mysrcpad, buffer) == GST_FLOW_OK); + } + + /* pushing the next buffer should result in EOS */ + buffer = create_test_buffer (i); + fail_unless (gst_pad_push (mysrcpad, buffer) == GST_FLOW_EOS); + + fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_eos ())); + + /* check that all buffers were received by our source pad */ + fail_unless (g_list_length (buffers) == i); + i = 0; + for (iter = buffers; iter; iter = g_list_next (iter)) { + GstMapInfo map; + guint64 num; + + buffer = iter->data; + + gst_buffer_map (buffer, &map, GST_MAP_READ); + + + num = *(guint64 *) map.data; + fail_unless (i == num); + fail_unless (GST_BUFFER_PTS (buffer) == gst_util_uint64_scale_round (i, + GST_SECOND * TEST_VIDEO_FPS_D, TEST_VIDEO_FPS_N)); + fail_unless (GST_BUFFER_DURATION (buffer) == + gst_util_uint64_scale_round (GST_SECOND, TEST_VIDEO_FPS_D, + TEST_VIDEO_FPS_N)); + + gst_buffer_unmap (buffer, &map); + i++; + } + + g_list_free_full (buffers, (GDestroyNotify) gst_buffer_unref); + buffers = NULL; + + cleanup_videodecodertest (); +} + +GST_END_TEST; + GST_START_TEST (videodecoder_backwards_playback) { @@ -563,6 +631,88 @@ GST_START_TEST (videodecoder_backwards_playback) } GST_END_TEST; + + +GST_START_TEST (videodecoder_backwards_buffer_after_segment) +{ + GstSegment segment; + GstBuffer *buffer; + guint64 i; + GstClockTime pos; + + setup_videodecodertester (); + + gst_pad_set_active (mysrcpad, TRUE); + gst_element_set_state (dec, GST_STATE_PLAYING); + gst_pad_set_active (mysinkpad, TRUE); + + send_startup_events (); + + /* push a new segment with -1 rate */ + gst_segment_init (&segment, GST_FORMAT_TIME); + segment.rate = -1.0; + segment.start = GST_SECOND; + segment.stop = (NUM_BUFFERS + 1) * gst_util_uint64_scale_round (GST_SECOND, + TEST_VIDEO_FPS_D, TEST_VIDEO_FPS_N); + fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_segment (&segment))); + + /* push buffers, the data is actually a number so we can track them */ + i = NUM_BUFFERS; + pos = segment.stop; + while (pos >= GST_SECOND) { + gint target = i; + gint j; + + g_assert (i > 0); + + /* push groups of 10 buffers + * every number that is divisible by 10 is set as a discont, + * if it is divisible by 20 it is also a keyframe + * + * The logic here is that hte current i is the target, and then + * it pushes buffers from 'target - 10' up to target. + */ + for (j = MAX (target - 10, 0); j < target; j++) { + buffer = create_test_buffer (j); + + pos = MIN (GST_BUFFER_TIMESTAMP (buffer), pos); + if (j % 10 == 0) + GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT); + if (j % 20 != 0) + GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT); + + fail_unless (gst_pad_push (mysrcpad, buffer) == GST_FLOW_OK); + i--; + } + } + + /* push a discont buffer so it flushes the decoding */ + buffer = create_test_buffer (i - 10); + GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT); + GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT); + fail_unless (gst_pad_push (mysrcpad, buffer) == GST_FLOW_EOS); + + /* check that the last received buffer doesn't contain a + * timestamp before the segment */ + buffer = g_list_last (buffers)->data; + fail_unless (GST_BUFFER_TIMESTAMP (buffer) <= segment.start + && GST_BUFFER_TIMESTAMP (buffer) + GST_BUFFER_DURATION (buffer) > + segment.start); + + /* flush our decoded data queue */ + g_list_free_full (buffers, (GDestroyNotify) gst_buffer_unref); + buffers = NULL; + + fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_eos ())); + + fail_unless (buffers == NULL); + + cleanup_videodecodertest (); +} + +GST_END_TEST; + + static Suite * gst_videodecoder_suite (void) { @@ -573,8 +723,10 @@ gst_videodecoder_suite (void) tcase_add_test (tc, videodecoder_playback); tcase_add_test (tc, videodecoder_playback_with_events); tcase_add_test (tc, videodecoder_playback_first_frames_not_decoded); + tcase_add_test (tc, videodecoder_buffer_after_segment); tcase_add_test (tc, videodecoder_backwards_playback); + tcase_add_test (tc, videodecoder_backwards_buffer_after_segment); return s; }