+typedef enum
+{
+ MODE_NONE = 0,
+ MODE_SUBFRAMES = 1,
+ MODE_PACKETIZED = 1 << 1,
+ MODE_META_ROI = 1 << 2,
+} SubframeMode;
+
+static void
+videodecoder_playback_subframe_mode (SubframeMode mode)
+{
+ GstSegment segment;
+ GstBuffer *buffer;
+ guint i;
+ GList *iter;
+ gint num_buffers = NUM_BUFFERS;
+ gint num_subframes = 1;
+ GList *list;
+ gint num_roi_metas = 0;
+
+ setup_videodecodertester (NULL, NULL);
+
+ /* Allow to test combination of subframes and packetized configuration
+ * 0-0: no subframes not packetized.
+ * 0-1: subframes not packetized.
+ * 1-0: no subframes packetized.
+ * 1-1: subframes and packetized.
+ */
+ if (mode & MODE_SUBFRAMES) {
+ gst_video_decoder_set_subframe_mode (GST_VIDEO_DECODER (dec), TRUE);
+ num_subframes = NUM_SUB_BUFFERS;
+ } else {
+ gst_video_decoder_set_subframe_mode (GST_VIDEO_DECODER (dec), FALSE);
+ num_subframes = 1;
+ }
+ gst_video_decoder_set_packetized (GST_VIDEO_DECODER (dec),
+ mode & MODE_PACKETIZED ? TRUE : FALSE);
+
+ 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);
+ fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_segment (&segment)));
+
+ /* push header only in packetized subframe mode */
+ if (mode == (MODE_PACKETIZED | MODE_SUBFRAMES)) {
+ buffer = gst_buffer_new_and_alloc (0);
+ GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_HEADER);
+ fail_unless (gst_pad_push (mysrcpad, buffer) == GST_FLOW_OK);
+ }
+
+ /* 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 / num_subframes);
+ if ((i + 1) % num_subframes == 0)
+ GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_MARKER);
+ if (mode & MODE_META_ROI)
+ gst_buffer_add_video_region_of_interest_meta (buffer, "face", 0, 0, 10,
+ 10);
+
+ fail_unless (gst_pad_push (mysrcpad, buffer) == GST_FLOW_OK);
+ fail_unless (gst_pad_push_event (mysrcpad,
+ gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM,
+ gst_structure_new_empty ("custom1"))));
+ }
+ /* Send EOS */
+ fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_eos ()));
+
+ /* Test that no frames or pending events are remaining in the base class */
+ list = gst_video_decoder_get_frames (GST_VIDEO_DECODER (dec));
+ fail_unless (g_list_length (list) == 0);
+ g_list_free_full (list, (GDestroyNotify) gst_video_codec_frame_unref);
+
+ /* check that all buffers were received by our source pad 1 output buffer for 4 input buffer */
+ fail_unless (g_list_length (buffers) == num_buffers / num_subframes);
+
+ i = 0;
+ for (iter = buffers; iter; iter = g_list_next (iter)) {
+ GstMapInfo map;
+ guint num;
+ GstMeta *meta;
+ gpointer state = NULL;
+
+ buffer = iter->data;
+ while ((meta = gst_buffer_iterate_meta (buffer, &state))) {
+ if (meta->info->api == GST_VIDEO_REGION_OF_INTEREST_META_API_TYPE)
+ num_roi_metas++;
+ }
+ gst_buffer_map (buffer, &map, GST_MAP_READ);
+ /* Test that the buffer is carrying the expected value 'num' */
+ num = *(guint64 *) map.data;
+
+ fail_unless (i == num);
+ /* Test that the buffer metadata are correct */
+ 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++;
+ }
+
+ if (mode &= MODE_META_ROI)
+ fail_unless (num_roi_metas == num_buffers);
+
+ g_list_free_full (buffers, (GDestroyNotify) gst_buffer_unref);
+ buffers = NULL;
+
+ cleanup_videodecodertest ();
+}
+
+static void
+videodecoder_playback_invalid_ts_subframe_mode (SubframeMode mode)
+{
+ GstSegment segment;
+ GstBuffer *buffer;
+ guint i;
+ gint num_buffers = NUM_BUFFERS;
+ gint num_subframes = 1;
+ GList *list;
+
+ setup_videodecodertester (NULL, NULL);
+
+ /* Allow to test combination of subframes and packetized configuration
+ * 0-0: no subframes not packetized.
+ * 0-1: subframes not packetized.
+ * 1-0: no subframes packetized.
+ * 1-1: subframes and packetized.
+ */
+ if (mode & MODE_SUBFRAMES) {
+ gst_video_decoder_set_subframe_mode (GST_VIDEO_DECODER (dec), TRUE);
+ num_subframes = NUM_SUB_BUFFERS;
+ }
+
+ gst_video_decoder_set_packetized (GST_VIDEO_DECODER (dec),
+ mode & MODE_PACKETIZED ? TRUE : FALSE);
+
+ 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);
+
+ fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_segment (&segment)));
+
+ /* push header only in packetized subframe mode */
+ if (mode == (MODE_PACKETIZED | MODE_SUBFRAMES)) {
+ buffer = gst_buffer_new_and_alloc (0);
+ GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_HEADER);
+ fail_unless (gst_pad_push (mysrcpad, buffer) == GST_FLOW_OK);
+ }
+
+ /* 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 / num_subframes);
+ GST_BUFFER_PTS (buffer) = GST_CLOCK_TIME_NONE;
+ if ((i + 1) % num_subframes == 0)
+ GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_MARKER);
+
+ fail_unless (gst_pad_push (mysrcpad, buffer) == GST_FLOW_OK);
+ fail_unless (gst_pad_push_event (mysrcpad,
+ gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM,
+ gst_structure_new_empty ("custom1"))));
+ }
+ /* Send EOS */
+ fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_eos ()));
+
+ /* Test that no frames or pending events are remaining in the base class */
+ list = gst_video_decoder_get_frames (GST_VIDEO_DECODER (dec));
+ fail_unless (g_list_length (list) == 0);
+ g_list_free_full (list, (GDestroyNotify) gst_video_codec_frame_unref);
+
+ /* check that all buffers were received by our source pad 1 output buffer for 4 input buffer */
+ fail_unless (g_list_length (buffers) == 0);
+
+
+ cleanup_videodecodertest ();
+}
+
+GST_START_TEST (videodecoder_playback_parsed)
+{
+ videodecoder_playback_subframe_mode (MODE_NONE);
+}
+
+GST_END_TEST;
+
+GST_START_TEST (videodecoder_playback_packetized)
+{
+ videodecoder_playback_subframe_mode (MODE_PACKETIZED);
+}
+
+GST_END_TEST;
+
+GST_START_TEST (videodecoder_playback_parsed_subframes)
+{
+ videodecoder_playback_subframe_mode (MODE_SUBFRAMES);
+}
+
+GST_END_TEST;
+
+GST_START_TEST (videodecoder_playback_packetized_subframes)
+{
+ videodecoder_playback_subframe_mode (MODE_SUBFRAMES | MODE_PACKETIZED);
+}
+
+GST_END_TEST;
+
+GST_START_TEST (videodecoder_playback_packetized_subframes_metadata)
+{
+ videodecoder_playback_subframe_mode (MODE_SUBFRAMES |
+ MODE_PACKETIZED | MODE_META_ROI);
+}
+
+GST_END_TEST;
+
+GST_START_TEST (videodecoder_playback_invalid_ts_packetized)
+{
+ videodecoder_playback_invalid_ts_subframe_mode (MODE_PACKETIZED);
+}
+
+GST_END_TEST;
+
+GST_START_TEST (videodecoder_playback_invalid_ts_packetized_subframes)
+{
+ videodecoder_playback_invalid_ts_subframe_mode (MODE_SUBFRAMES |
+ MODE_PACKETIZED);
+}
+
+GST_END_TEST;
+
+
+