+#define NUM_BUFFERS 100
+GST_START_TEST (videoencoder_playback_subframes)
+{
+ GstSegment segment;
+ GstBuffer *buffer;
+ guint64 i;
+ GList *iter;
+ int subframes = 4;
+
+ setup_videoencodertester_with_subframes (subframes);
+
+ 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 buffers, the data is actually a number so we can track them */
+ for (i = 0; i < NUM_BUFFERS; i++) {
+ buffer = create_test_buffer (i);
+
+ fail_unless (gst_pad_push (mysrcpad, buffer) == GST_FLOW_OK);
+ }
+
+ fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_eos ()));
+
+ /* check that all buffers (plus one header buffer) were received by our source pad */
+ fail_unless (g_list_length (buffers) == NUM_BUFFERS * subframes + 1);
+ /* check that first buffer is an header */
+ buffer = buffers->data;
+ fail_unless (GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_HEADER));
+ /* check the other buffers */
+ i = 0;
+ for (iter = g_list_next (buffers); iter; iter = g_list_next (iter)) {
+ /* first buffer should be the header */
+ GstMapInfo map;
+ guint64 num;
+ buffer = iter->data;
+ fail_unless (!GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_HEADER));
+ gst_buffer_map (buffer, &map, GST_MAP_READ);
+
+ num = *(guint64 *) map.data;
+ fail_unless (i / subframes == num);
+
+ if (i % subframes)
+ fail_unless (GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT));
+
+ fail_unless (GST_BUFFER_PTS (buffer) ==
+ gst_util_uint64_scale_round (i / subframes,
+ 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_videoencodertest ();
+}
+
+GST_END_TEST;
+
+GST_START_TEST (videoencoder_playback_events_subframes)
+{
+ GstSegment segment;
+ GstBuffer *buffer;
+ GList *iter;
+ gint subframes = 4;
+ gint i, header_found;
+ GstVideoEncoderTester *enc_tester;
+
+ setup_videoencodertester_with_subframes (subframes);
+
+ enc_tester = GST_VIDEO_ENCODER_TESTER (enc);
+ enc_tester->send_headers = TRUE;
+ enc_tester->enable_step_by_step = TRUE;
+
+ 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 -> no new buffer and no new events (still pending two custom events) */
+ gst_segment_init (&segment, GST_FORMAT_TIME);
+ fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_segment (&segment)));
+ fail_unless (g_list_length (buffers) == 0 && g_list_length (events) == 0);
+
+ /* push a first buffer -> no new buffer and no new events (still pending two custom events) */
+ buffer = create_test_buffer (0);
+ fail_unless (gst_pad_push (mysrcpad, buffer) == GST_FLOW_OK);
+ fail_unless (g_list_length (buffers) == 0 && g_list_length (events) == 0);
+
+ /* ouput only one subframe -> 2 buffers(header + subframe) and 3 events (stream-start, caps, segment) */
+ gst_video_encoder_tester_output_step_by_step (GST_VIDEO_ENCODER (enc),
+ enc_tester->last_frame, 1);
+ fail_unless (g_list_length (buffers) == 2 && g_list_length (events) == 3);
+ fail_unless (GST_BUFFER_FLAG_IS_SET ((GstBuffer *) buffers->data,
+ GST_BUFFER_FLAG_HEADER));
+ fail_unless (GST_EVENT_TYPE ((GstEvent *) (g_list_nth (events,
+ 0)->data)) == GST_EVENT_STREAM_START);
+ fail_unless (GST_EVENT_TYPE ((GstEvent *) (g_list_nth (events,
+ 1)->data)) == GST_EVENT_CAPS);
+ fail_unless (GST_EVENT_TYPE ((GstEvent *) (g_list_nth (events,
+ 2)->data)) == GST_EVENT_SEGMENT);
+
+ /* output 3 last subframes -> 2 more buffers and no new events */
+ gst_video_encoder_tester_output_step_by_step (GST_VIDEO_ENCODER (enc),
+ enc_tester->last_frame, 3);
+ fail_unless (g_list_length (buffers) == 5 && g_list_length (events) == 3);
+
+ /* push a new buffer -> no new buffer and no new events */
+ buffer = create_test_buffer (1);
+ fail_unless (gst_pad_push (mysrcpad, buffer) == GST_FLOW_OK);
+ fail_unless (g_list_length (buffers) == 5 && g_list_length (events) == 3);
+
+ /* push an event in between -> no new buffer and no new event */
+ fail_unless (gst_pad_push_event (mysrcpad,
+ gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM,
+ gst_structure_new_empty ("custom1"))));
+ fail_unless (g_list_length (buffers) == 5 && g_list_length (events) == 3);
+
+ /* output 1 subframe -> one new buffer and no new events */
+ gst_video_encoder_tester_output_step_by_step (GST_VIDEO_ENCODER (enc),
+ enc_tester->last_frame, 1);
+ fail_unless (g_list_length (buffers) == 6 && g_list_length (events) == 3);
+
+ /* push another custom event in between , no new event should appear until the next frame is handled */
+ fail_unless (gst_pad_push_event (mysrcpad,
+ gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM,
+ gst_structure_new_empty ("custom2"))));
+ fail_unless (g_list_length (buffers) == 6 && g_list_length (events) == 3);
+
+ /* output 2 subframes -> 2 new buffers and no new events */
+ gst_video_encoder_tester_output_step_by_step (GST_VIDEO_ENCODER (enc),
+ enc_tester->last_frame, 2);
+ fail_unless (g_list_length (buffers) == 8 && g_list_length (events) == 3);
+
+ /* output 1 last subframe -> 1 new buffers and no new events */
+ gst_video_encoder_tester_output_step_by_step (GST_VIDEO_ENCODER (enc),
+ enc_tester->last_frame, 1);
+ fail_unless (g_list_length (buffers) == 9 && g_list_length (events) == 3);
+
+ /* push a third buffer -> no new buffer and no new events (still pending two custom events) */
+ buffer = create_test_buffer (2);
+ fail_unless (gst_pad_push (mysrcpad, buffer) == GST_FLOW_OK);
+ fail_unless (g_list_length (buffers) == 9 && g_list_length (events) == 3);
+
+ /* output 1 subframes -> 1 new buffer and 2 custom events from the last input frame */
+ gst_video_encoder_tester_output_step_by_step (GST_VIDEO_ENCODER (enc),
+ enc_tester->last_frame, 1);
+ fail_unless (g_list_length (buffers) == 10 && g_list_length (events) == 5);
+ fail_unless (GST_EVENT_TYPE ((GstEvent *) (g_list_nth (events,
+ 3)->data)) == GST_EVENT_CUSTOM_DOWNSTREAM);
+ fail_unless (GST_EVENT_TYPE ((GstEvent *) (g_list_nth (events,
+ 4)->data)) == GST_EVENT_CUSTOM_DOWNSTREAM);
+
+ /* push another custom event in between , no new event should appear until eos */
+ fail_unless (gst_pad_push_event (mysrcpad,
+ gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM,
+ gst_structure_new_empty ("custom3"))));
+ fail_unless (g_list_length (buffers) == 10 && g_list_length (events) == 5);
+
+ /* output 3 subframes -> 3 new buffer and no new events */
+ gst_video_encoder_tester_output_step_by_step (GST_VIDEO_ENCODER (enc),
+ enc_tester->last_frame, 3);
+ fail_unless (g_list_length (buffers) == 13 && g_list_length (events) == 5);
+
+ /* push a force key-unit event */
+ enc_tester->key_frame_sent = FALSE;
+ fail_unless (gst_pad_push_event (mysrcpad,
+ gst_video_event_new_downstream_force_key_unit (GST_CLOCK_TIME_NONE,
+ GST_CLOCK_TIME_NONE, GST_CLOCK_TIME_NONE, TRUE, 1)));
+
+ /* Create a new buffer which should be a key unit -> no new buffer and no new event */
+ buffer = create_test_buffer (3);
+ fail_unless (gst_pad_push (mysrcpad, buffer) == GST_FLOW_OK);
+ fail_unless (g_list_length (buffers) == 13 && g_list_length (events) == 5);
+
+ /* output 2 subframes -> 3 new buffer(one header and two subframes and two events key-unit and custom3 */
+ gst_video_encoder_tester_output_step_by_step (GST_VIDEO_ENCODER (enc),
+ enc_tester->last_frame, 2);
+ fail_unless (g_list_length (buffers) == 16 && g_list_length (events) == 7);
+
+ /* output 2 subframes -> 2 new buffer correspong the two last subframes */
+ gst_video_encoder_tester_output_step_by_step (GST_VIDEO_ENCODER (enc),
+ enc_tester->last_frame, 2);
+ fail_unless (g_list_length (buffers) == 18 && g_list_length (events) == 7);
+
+ /* push eos event -> 1 new event ( eos) */
+ fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_eos ()));
+ fail_unless (g_list_length (buffers) == 18 && g_list_length (events) == 8);
+
+ /* check the order of the last events received */
+ fail_unless (GST_EVENT_TYPE ((GstEvent *) (g_list_nth (events,
+ 6)->data)) == GST_EVENT_CUSTOM_DOWNSTREAM);
+ fail_unless (GST_EVENT_TYPE ((GstEvent *) (g_list_nth (events,
+ 7)->data)) == GST_EVENT_EOS);
+
+ /* check that only last subframe owns the GST_VIDEO_BUFFER_FLAG_MARKER flag */
+ i = 0;
+ header_found = 0;
+ for (iter = g_list_next (buffers); iter; iter = g_list_next (iter)) {
+ buffer = (GstBuffer *) (iter->data);
+ if (!GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_HEADER)) {
+ if ((i - header_found) % subframes == (subframes - 1))
+ fail_unless (GST_BUFFER_FLAG_IS_SET (buffer,
+ GST_VIDEO_BUFFER_FLAG_MARKER));
+ else
+ fail_unless (!GST_BUFFER_FLAG_IS_SET (buffer,
+ GST_VIDEO_BUFFER_FLAG_MARKER));
+ } else {
+ fail_unless (!GST_BUFFER_FLAG_IS_SET (buffer,
+ GST_VIDEO_BUFFER_FLAG_MARKER));
+ header_found++;
+ }
+ i++;
+ }
+
+ g_list_free_full (buffers, (GDestroyNotify) gst_buffer_unref);
+ buffers = NULL;
+
+ cleanup_videoencodertest ();
+}
+
+GST_END_TEST;
+