diff --git a/tests/check/libs/videoencoder.c b/tests/check/libs/videoencoder.c index 6fbd8b9722..04ebac5a83 100644 --- a/tests/check/libs/videoencoder.c +++ b/tests/check/libs/videoencoder.c @@ -917,6 +917,177 @@ GST_START_TEST (videoencoder_playback_events_subframes) GST_END_TEST; +GST_START_TEST (videoencoder_force_keyunit_handling) +{ + GstSegment segment; + GstBuffer *buffer; + GList *l; + gint i; + + setup_videoencodertester (); + + gst_pad_set_active (mysrcpad, TRUE); + gst_element_set_state (enc, GST_STATE_PLAYING); + gst_pad_set_active (mysinkpad, TRUE); + + send_startup_events (); + + /* push a new segment */ + gst_segment_init (&segment, GST_FORMAT_TIME); + fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_segment (&segment))); + + /* push the first buffer */ + buffer = create_test_buffer (0); + fail_unless (gst_pad_push (mysrcpad, buffer) == GST_FLOW_OK); + buffer = NULL; + + fail_unless_equals_int (g_list_length (buffers), 1); + + buffer = create_test_buffer (1); + fail_unless (gst_pad_push (mysrcpad, buffer) == GST_FLOW_OK); + buffer = NULL; + + fail_unless_equals_int (g_list_length (buffers), 2); + + /* send a force-keyunit event, the next buffer should be a keyframe now */ + fail_unless (gst_pad_push_event (mysinkpad, + gst_video_event_new_upstream_force_key_unit (GST_CLOCK_TIME_NONE, + TRUE, 1))); + + buffer = create_test_buffer (2); + fail_unless (gst_pad_push (mysrcpad, buffer) == GST_FLOW_OK); + buffer = NULL; + + fail_unless_equals_int (g_list_length (buffers), 3); + + buffer = create_test_buffer (3); + fail_unless (gst_pad_push (mysrcpad, buffer) == GST_FLOW_OK); + buffer = NULL; + + fail_unless_equals_int (g_list_length (buffers), 4); + + /* send multiple force-keyunit events now, this should still only cause a + * single keyframe */ + fail_unless (gst_pad_push_event (mysinkpad, + gst_video_event_new_upstream_force_key_unit (GST_CLOCK_TIME_NONE, + TRUE, 1))); + fail_unless (gst_pad_push_event (mysinkpad, + gst_video_event_new_upstream_force_key_unit (GST_CLOCK_TIME_NONE, + TRUE, 1))); + + buffer = create_test_buffer (4); + fail_unless (gst_pad_push (mysrcpad, buffer) == GST_FLOW_OK); + buffer = NULL; + + fail_unless_equals_int (g_list_length (buffers), 5); + + buffer = create_test_buffer (5); + fail_unless (gst_pad_push (mysrcpad, buffer) == GST_FLOW_OK); + buffer = NULL; + + fail_unless_equals_int (g_list_length (buffers), 6); + + /* send a force-keyunit event for the running time of the next buffer */ + fail_unless (gst_pad_push_event (mysinkpad, + gst_video_event_new_upstream_force_key_unit + (gst_util_uint64_scale_round (6, GST_SECOND * TEST_VIDEO_FPS_D, + TEST_VIDEO_FPS_N), TRUE, 1))); + + buffer = create_test_buffer (6); + fail_unless (gst_pad_push (mysrcpad, buffer) == GST_FLOW_OK); + buffer = NULL; + + fail_unless_equals_int (g_list_length (buffers), 7); + + buffer = create_test_buffer (7); + fail_unless (gst_pad_push (mysrcpad, buffer) == GST_FLOW_OK); + buffer = NULL; + + fail_unless_equals_int (g_list_length (buffers), 8); + + /* send a force-keyunit event for the running time of the next buffer + * and another one right before. This should only cause a single keyframe + * again */ + fail_unless (gst_pad_push_event (mysinkpad, + gst_video_event_new_upstream_force_key_unit + (gst_util_uint64_scale_round (8, GST_SECOND * TEST_VIDEO_FPS_D, + TEST_VIDEO_FPS_N), TRUE, 1))); + fail_unless (gst_pad_push_event (mysinkpad, + gst_video_event_new_upstream_force_key_unit + (gst_util_uint64_scale_round (8, GST_SECOND * TEST_VIDEO_FPS_D, + TEST_VIDEO_FPS_N) - 10 * GST_MSECOND, TRUE, 1))); + + buffer = create_test_buffer (8); + fail_unless (gst_pad_push (mysrcpad, buffer) == GST_FLOW_OK); + buffer = NULL; + + fail_unless_equals_int (g_list_length (buffers), 9); + + buffer = create_test_buffer (9); + fail_unless (gst_pad_push (mysrcpad, buffer) == GST_FLOW_OK); + buffer = NULL; + + fail_unless_equals_int (g_list_length (buffers), 10); + + /* send a force-keyunit event for the 12th buffer, see below */ + fail_unless (gst_pad_push_event (mysinkpad, + gst_video_event_new_upstream_force_key_unit + (gst_util_uint64_scale_round (12, GST_SECOND * TEST_VIDEO_FPS_D, + TEST_VIDEO_FPS_N), TRUE, 1))); + + /* send two force-keyunit events. This should only cause a single keyframe + * again */ + fail_unless (gst_pad_push_event (mysinkpad, + gst_video_event_new_upstream_force_key_unit + (gst_util_uint64_scale_round (10, GST_SECOND * TEST_VIDEO_FPS_D, + TEST_VIDEO_FPS_N), TRUE, 1))); + fail_unless (gst_pad_push_event (mysinkpad, + gst_video_event_new_upstream_force_key_unit + (gst_util_uint64_scale_round (10, GST_SECOND * TEST_VIDEO_FPS_D, + TEST_VIDEO_FPS_N) - 10 * GST_MSECOND, TRUE, 1))); + + buffer = create_test_buffer (10); + fail_unless (gst_pad_push (mysrcpad, buffer) == GST_FLOW_OK); + buffer = NULL; + + fail_unless_equals_int (g_list_length (buffers), 11); + + buffer = create_test_buffer (11); + fail_unless (gst_pad_push (mysrcpad, buffer) == GST_FLOW_OK); + buffer = NULL; + + fail_unless_equals_int (g_list_length (buffers), 12); + + /* we already sent a force-keyunit event for the 12th buffer long ago */ + buffer = create_test_buffer (12); + fail_unless (gst_pad_push (mysrcpad, buffer) == GST_FLOW_OK); + buffer = NULL; + + fail_unless_equals_int (g_list_length (buffers), 13); + + buffer = create_test_buffer (13); + fail_unless (gst_pad_push (mysrcpad, buffer) == GST_FLOW_OK); + buffer = NULL; + + fail_unless_equals_int (g_list_length (buffers), 14); + + /* every second buffer should be a keyframe */ + for (l = buffers, i = 0; l; l = l->next, i++) { + if (i % 2 == 0) + fail_if (GST_BUFFER_FLAG_IS_SET (l->data, GST_BUFFER_FLAG_DELTA_UNIT)); + else + fail_unless (GST_BUFFER_FLAG_IS_SET (l->data, + GST_BUFFER_FLAG_DELTA_UNIT)); + } + + g_list_free_full (buffers, (GDestroyNotify) gst_buffer_unref); + buffers = NULL; + + cleanup_videoencodertest (); +} + +GST_END_TEST; + static Suite * gst_videoencoder_suite (void) { @@ -933,6 +1104,7 @@ gst_videoencoder_suite (void) tcase_add_test (tc, videoencoder_qos); tcase_add_test (tc, videoencoder_playback_subframes); tcase_add_test (tc, videoencoder_playback_events_subframes); + tcase_add_test (tc, videoencoder_force_keyunit_handling); return s; }