3 * Copyright (C) 2014 Samsung Electronics. All rights reserved.
4 * Author: Thiago Santos <ts.santos@sisa.samsung.com>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
16 * You should have received a copy of the GNU Library General Public
17 * License along with this library; if not, write to the
18 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
26 #include <gst/check/gstcheck.h>
27 #include <gst/check/gstharness.h>
28 #include <gst/video/video.h>
29 #include <gst/app/app.h>
31 static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
34 GST_STATIC_CAPS ("video/x-raw")
37 #define RESTRICTED_CAPS_WIDTH 800
38 #define RESTRICTED_CAPS_HEIGHT 600
39 #define RESTRICTED_CAPS_FPS_N 30
40 #define RESTRICTED_CAPS_FPS_D 1
41 static GstStaticPadTemplate sinktemplate_restricted =
42 GST_STATIC_PAD_TEMPLATE ("sink",
45 GST_STATIC_CAPS ("video/x-raw, width=(int)800, height=(int)600,"
46 " framerate=(fraction)30/1")
49 static GstStaticPadTemplate sinktemplate_with_range =
50 GST_STATIC_PAD_TEMPLATE ("sink",
53 GST_STATIC_CAPS ("video/x-raw, width=(int)[1,800], height=(int)[1,600],"
54 " framerate=(fraction)[1/1, 30/1]")
57 static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
60 GST_STATIC_CAPS ("video/x-test-custom")
63 static GstPad *mysrcpad, *mysinkpad;
64 static GstElement *dec;
65 static GList *events = NULL;
67 #define TEST_VIDEO_WIDTH 640
68 #define TEST_VIDEO_HEIGHT 480
69 #define TEST_VIDEO_FPS_N 30
70 #define TEST_VIDEO_FPS_D 1
72 #define GST_VIDEO_DECODER_TESTER_TYPE gst_video_decoder_tester_get_type()
73 static GType gst_video_decoder_tester_get_type (void);
75 typedef struct _GstVideoDecoderTester GstVideoDecoderTester;
76 typedef struct _GstVideoDecoderTesterClass GstVideoDecoderTesterClass;
78 struct _GstVideoDecoderTester
80 GstVideoDecoder parent;
84 gboolean set_output_state;
87 struct _GstVideoDecoderTesterClass
89 GstVideoDecoderClass parent_class;
92 G_DEFINE_TYPE (GstVideoDecoderTester, gst_video_decoder_tester,
93 GST_TYPE_VIDEO_DECODER);
96 gst_video_decoder_tester_start (GstVideoDecoder * dec)
98 GstVideoDecoderTester *dectester = (GstVideoDecoderTester *) dec;
100 dectester->last_buf_num = -1;
101 dectester->last_kf_num = -1;
102 dectester->set_output_state = TRUE;
108 gst_video_decoder_tester_stop (GstVideoDecoder * dec)
114 gst_video_decoder_tester_flush (GstVideoDecoder * dec)
116 GstVideoDecoderTester *dectester = (GstVideoDecoderTester *) dec;
118 dectester->last_buf_num = -1;
119 dectester->last_kf_num = -1;
125 gst_video_decoder_tester_set_format (GstVideoDecoder * dec,
126 GstVideoCodecState * state)
128 GstVideoDecoderTester *dectester = (GstVideoDecoderTester *) dec;
130 if (dectester->set_output_state) {
131 GstVideoCodecState *res = gst_video_decoder_set_output_state (dec,
132 GST_VIDEO_FORMAT_GRAY8, TEST_VIDEO_WIDTH, TEST_VIDEO_HEIGHT, NULL);
133 gst_video_codec_state_unref (res);
140 gst_video_decoder_tester_handle_frame (GstVideoDecoder * dec,
141 GstVideoCodecFrame * frame)
143 GstVideoDecoderTester *dectester = (GstVideoDecoderTester *) dec;
149 gst_buffer_map (frame->input_buffer, &map, GST_MAP_READ);
151 input_num = *((guint64 *) map.data);
153 if ((input_num == dectester->last_buf_num + 1
154 && dectester->last_buf_num != -1)
155 || !GST_BUFFER_FLAG_IS_SET (frame->input_buffer,
156 GST_BUFFER_FLAG_DELTA_UNIT)) {
158 /* the output is gray8 */
159 size = TEST_VIDEO_WIDTH * TEST_VIDEO_HEIGHT;
160 data = g_malloc0 (size);
162 memcpy (data, map.data, sizeof (guint64));
164 frame->output_buffer = gst_buffer_new_wrapped (data, size);
165 frame->pts = GST_BUFFER_PTS (frame->input_buffer);
166 frame->duration = GST_BUFFER_DURATION (frame->input_buffer);
167 dectester->last_buf_num = input_num;
168 if (!GST_BUFFER_FLAG_IS_SET (frame->input_buffer,
169 GST_BUFFER_FLAG_DELTA_UNIT))
170 dectester->last_kf_num = input_num;
173 gst_buffer_unmap (frame->input_buffer, &map);
175 if (frame->output_buffer)
176 return gst_video_decoder_finish_frame (dec, frame);
177 gst_video_codec_frame_unref (frame);
182 gst_video_decoder_tester_class_init (GstVideoDecoderTesterClass * klass)
184 GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
185 GstVideoDecoderClass *videodecoder_class = GST_VIDEO_DECODER_CLASS (klass);
187 static GstStaticPadTemplate sink_templ = GST_STATIC_PAD_TEMPLATE ("sink",
188 GST_PAD_SINK, GST_PAD_ALWAYS,
189 GST_STATIC_CAPS ("video/x-test-custom"));
191 static GstStaticPadTemplate src_templ = GST_STATIC_PAD_TEMPLATE ("src",
192 GST_PAD_SRC, GST_PAD_ALWAYS,
193 GST_STATIC_CAPS ("video/x-raw"));
195 gst_element_class_add_static_pad_template (element_class, &sink_templ);
196 gst_element_class_add_static_pad_template (element_class, &src_templ);
198 gst_element_class_set_metadata (element_class,
199 "VideoDecoderTester", "Decoder/Video", "yep", "me");
201 videodecoder_class->start = gst_video_decoder_tester_start;
202 videodecoder_class->stop = gst_video_decoder_tester_stop;
203 videodecoder_class->flush = gst_video_decoder_tester_flush;
204 videodecoder_class->handle_frame = gst_video_decoder_tester_handle_frame;
205 videodecoder_class->set_format = gst_video_decoder_tester_set_format;
209 gst_video_decoder_tester_init (GstVideoDecoderTester * tester)
214 _mysinkpad_event (GstPad * pad, GstObject * parent, GstEvent * event)
216 events = g_list_append (events, event);
221 setup_videodecodertester (GstStaticPadTemplate * sinktmpl,
222 GstStaticPadTemplate * srctmpl)
224 if (sinktmpl == NULL)
225 sinktmpl = &sinktemplate;
227 srctmpl = &srctemplate;
229 dec = g_object_new (GST_VIDEO_DECODER_TESTER_TYPE, NULL);
230 mysrcpad = gst_check_setup_src_pad (dec, srctmpl);
231 mysinkpad = gst_check_setup_sink_pad (dec, sinktmpl);
233 gst_pad_set_event_function (mysinkpad, _mysinkpad_event);
237 cleanup_videodecodertest (void)
239 gst_pad_set_active (mysrcpad, FALSE);
240 gst_pad_set_active (mysinkpad, FALSE);
241 gst_check_teardown_src_pad (dec);
242 gst_check_teardown_sink_pad (dec);
243 gst_check_teardown_element (dec);
245 g_list_free_full (events, (GDestroyNotify) gst_event_unref);
250 create_test_buffer (guint64 num)
253 guint64 *data = g_malloc (sizeof (guint64));
257 buffer = gst_buffer_new_wrapped (data, sizeof (guint64));
259 GST_BUFFER_PTS (buffer) =
260 gst_util_uint64_scale_round (num, GST_SECOND * TEST_VIDEO_FPS_D,
262 GST_BUFFER_DURATION (buffer) =
263 gst_util_uint64_scale_round (GST_SECOND, TEST_VIDEO_FPS_D,
270 send_startup_events (void)
274 fail_unless (gst_pad_push_event (mysrcpad,
275 gst_event_new_stream_start ("randomvalue")));
279 gst_caps_new_simple ("video/x-test-custom", "width", G_TYPE_INT,
280 TEST_VIDEO_WIDTH, "height", G_TYPE_INT, TEST_VIDEO_HEIGHT, "framerate",
281 GST_TYPE_FRACTION, TEST_VIDEO_FPS_N, TEST_VIDEO_FPS_D, NULL);
282 fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_caps (caps)));
283 gst_caps_unref (caps);
286 #define NUM_BUFFERS 1000
287 GST_START_TEST (videodecoder_playback)
294 setup_videodecodertester (NULL, NULL);
296 gst_pad_set_active (mysrcpad, TRUE);
297 gst_element_set_state (dec, GST_STATE_PLAYING);
298 gst_pad_set_active (mysinkpad, TRUE);
300 send_startup_events ();
302 /* push a new segment */
303 gst_segment_init (&segment, GST_FORMAT_TIME);
304 fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_segment (&segment)));
306 /* push buffers, the data is actually a number so we can track them */
307 for (i = 0; i < NUM_BUFFERS; i++) {
308 buffer = create_test_buffer (i);
310 fail_unless (gst_pad_push (mysrcpad, buffer) == GST_FLOW_OK);
313 fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_eos ()));
315 /* check that all buffers were received by our source pad */
316 fail_unless (g_list_length (buffers) == NUM_BUFFERS);
318 for (iter = buffers; iter; iter = g_list_next (iter)) {
324 gst_buffer_map (buffer, &map, GST_MAP_READ);
327 num = *(guint64 *) map.data;
328 fail_unless (i == num);
329 fail_unless (GST_BUFFER_PTS (buffer) == gst_util_uint64_scale_round (i,
330 GST_SECOND * TEST_VIDEO_FPS_D, TEST_VIDEO_FPS_N));
331 fail_unless (GST_BUFFER_DURATION (buffer) ==
332 gst_util_uint64_scale_round (GST_SECOND, TEST_VIDEO_FPS_D,
335 gst_buffer_unmap (buffer, &map);
339 g_list_free_full (buffers, (GDestroyNotify) gst_buffer_unref);
342 cleanup_videodecodertest ();
348 GST_START_TEST (videodecoder_playback_with_events)
356 setup_videodecodertester (NULL, NULL);
358 gst_pad_set_active (mysrcpad, TRUE);
359 gst_element_set_state (dec, GST_STATE_PLAYING);
360 gst_pad_set_active (mysinkpad, TRUE);
362 send_startup_events ();
364 /* push a new segment */
365 gst_segment_init (&segment, GST_FORMAT_TIME);
366 fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_segment (&segment)));
368 /* push buffers, the data is actually a number so we can track them */
369 for (i = 0; i < NUM_BUFFERS; i++) {
373 tags = gst_tag_list_new (GST_TAG_TRACK_NUMBER, i, NULL);
374 fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_tag (tags)));
376 buffer = create_test_buffer (i);
378 fail_unless (gst_pad_push (mysrcpad, buffer) == GST_FLOW_OK);
382 fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_eos ()));
384 events_iter = events;
385 /* make sure the usual events have been received */
387 GstEvent *sstart = events_iter->data;
388 fail_unless (GST_EVENT_TYPE (sstart) == GST_EVENT_STREAM_START);
389 events_iter = g_list_next (events_iter);
392 GstEvent *caps_event = events_iter->data;
393 fail_unless (GST_EVENT_TYPE (caps_event) == GST_EVENT_CAPS);
394 events_iter = g_list_next (events_iter);
397 GstEvent *segment_event = events_iter->data;
398 fail_unless (GST_EVENT_TYPE (segment_event) == GST_EVENT_SEGMENT);
399 events_iter = g_list_next (events_iter);
402 /* check that all buffers were received by our source pad */
404 for (i = 0; i < NUM_BUFFERS; i++) {
407 GstEvent *tag_event = events_iter->data;
408 GstTagList *taglist = NULL;
410 gst_event_parse_tag (tag_event, &taglist);
412 fail_unless (gst_tag_list_get_uint (taglist, GST_TAG_TRACK_NUMBER,
414 fail_unless (tag_v == i);
416 events_iter = g_list_next (events_iter);
423 gst_buffer_map (buffer, &map, GST_MAP_READ);
425 num = *(guint64 *) map.data;
426 fail_unless (i == num);
427 fail_unless (GST_BUFFER_PTS (buffer) == gst_util_uint64_scale_round (i,
428 GST_SECOND * TEST_VIDEO_FPS_D, TEST_VIDEO_FPS_N));
429 fail_unless (GST_BUFFER_DURATION (buffer) ==
430 gst_util_uint64_scale_round (GST_SECOND, TEST_VIDEO_FPS_D,
433 gst_buffer_unmap (buffer, &map);
434 iter = g_list_next (iter);
437 fail_unless (iter == NULL);
439 /* check that EOS was received */
441 GstEvent *eos = events_iter->data;
443 fail_unless (GST_EVENT_TYPE (eos) == GST_EVENT_EOS);
444 events_iter = g_list_next (events_iter);
447 fail_unless (events_iter == NULL);
449 g_list_free_full (buffers, (GDestroyNotify) gst_buffer_unref);
452 cleanup_videodecodertest ();
457 GST_START_TEST (videodecoder_flush_events)
464 setup_videodecodertester (NULL, NULL);
466 gst_pad_set_active (mysrcpad, TRUE);
467 gst_element_set_state (dec, GST_STATE_PLAYING);
468 gst_pad_set_active (mysinkpad, TRUE);
470 send_startup_events ();
472 /* push a new segment */
473 gst_segment_init (&segment, GST_FORMAT_TIME);
474 fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_segment (&segment)));
476 /* push buffers, the data is actually a number so we can track them */
477 for (i = 0; i < NUM_BUFFERS; i++) {
481 tags = gst_tag_list_new (GST_TAG_TRACK_NUMBER, i, NULL);
482 fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_tag (tags)));
484 buffer = create_test_buffer (i);
486 fail_unless (gst_pad_push (mysrcpad, buffer) == GST_FLOW_OK);
490 fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_eos ()));
492 events_iter = events;
493 /* make sure the usual events have been received */
495 GstEvent *sstart = events_iter->data;
496 fail_unless (GST_EVENT_TYPE (sstart) == GST_EVENT_STREAM_START);
497 events_iter = g_list_next (events_iter);
500 GstEvent *caps_event = events_iter->data;
501 fail_unless (GST_EVENT_TYPE (caps_event) == GST_EVENT_CAPS);
502 events_iter = g_list_next (events_iter);
505 GstEvent *segment_event = events_iter->data;
506 fail_unless (GST_EVENT_TYPE (segment_event) == GST_EVENT_SEGMENT);
507 events_iter = g_list_next (events_iter);
510 /* check that EOS was received */
511 fail_unless (GST_PAD_IS_EOS (mysrcpad));
512 fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_flush_start ()));
513 fail_unless (GST_PAD_IS_EOS (mysrcpad));
515 /* Check that we have tags */
517 GstEvent *tags = gst_pad_get_sticky_event (mysrcpad, GST_EVENT_TAG, 0);
519 fail_unless (tags != NULL);
520 gst_event_unref (tags);
523 /* Check that we still have a segment set */
526 gst_pad_get_sticky_event (mysrcpad, GST_EVENT_SEGMENT, 0);
528 fail_unless (segment != NULL);
529 gst_event_unref (segment);
532 fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_flush_stop (TRUE)));
533 fail_if (GST_PAD_IS_EOS (mysrcpad));
535 /* Check that the segment was flushed on FLUSH_STOP */
538 gst_pad_get_sticky_event (mysrcpad, GST_EVENT_SEGMENT, 0);
540 fail_unless (segment == NULL);
543 /* Check the tags were not lost on FLUSH_STOP */
545 GstEvent *tags = gst_pad_get_sticky_event (mysrcpad, GST_EVENT_TAG, 0);
547 fail_unless (tags != NULL);
548 gst_event_unref (tags);
552 g_list_free_full (buffers, (GDestroyNotify) gst_buffer_unref);
555 cleanup_videodecodertest ();
561 /* Check https://bugzilla.gnome.org/show_bug.cgi?id=721835 */
562 GST_START_TEST (videodecoder_playback_first_frames_not_decoded)
568 setup_videodecodertester (NULL, NULL);
570 gst_pad_set_active (mysrcpad, TRUE);
571 gst_element_set_state (dec, GST_STATE_PLAYING);
572 gst_pad_set_active (mysinkpad, TRUE);
574 send_startup_events ();
576 /* push a new segment */
577 gst_segment_init (&segment, GST_FORMAT_TIME);
578 fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_segment (&segment)));
580 /* push a buffer, to have the segment attached to it.
581 * unfortunately this buffer can't be decoded as it isn't a keyframe */
582 buffer = create_test_buffer (i++);
583 GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT);
584 fail_unless (gst_pad_push (mysrcpad, buffer) == GST_FLOW_OK);
586 /* now be evil and ask this frame to be released
587 * this frame has the segment event attached to it, and the
588 * segment shouldn't disappear with it */
592 ol = l = gst_video_decoder_get_frames (GST_VIDEO_DECODER (dec));
593 fail_unless (g_list_length (l) == 1);
595 GstVideoCodecFrame *tmp = l->data;
597 gst_video_decoder_release_frame (GST_VIDEO_DECODER (dec), tmp);
604 buffer = create_test_buffer (i++);
605 fail_unless (gst_pad_push (mysrcpad, buffer) == GST_FLOW_OK);
607 fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_eos ()));
609 fail_unless (g_list_length (buffers) == 1);
611 g_list_free_full (buffers, (GDestroyNotify) gst_buffer_unref);
614 cleanup_videodecodertest ();
619 GST_START_TEST (videodecoder_buffer_after_segment)
627 setup_videodecodertester (NULL, NULL);
629 gst_pad_set_active (mysrcpad, TRUE);
630 gst_element_set_state (dec, GST_STATE_PLAYING);
631 gst_pad_set_active (mysinkpad, TRUE);
633 send_startup_events ();
635 /* push a new segment */
636 gst_segment_init (&segment, GST_FORMAT_TIME);
637 segment.stop = GST_SECOND;
638 fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_segment (&segment)));
640 /* push buffers until we fill our segment */
643 while (pos < GST_SECOND) {
644 buffer = create_test_buffer (i++);
646 pos = GST_BUFFER_TIMESTAMP (buffer) + GST_BUFFER_DURATION (buffer);
647 fail_unless (gst_pad_push (mysrcpad, buffer) == GST_FLOW_OK);
650 /* pushing the next buffer should result in EOS */
651 buffer = create_test_buffer (i);
652 fail_unless (gst_pad_push (mysrcpad, buffer) == GST_FLOW_EOS);
654 fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_eos ()));
656 /* check that all buffers were received by our source pad */
657 fail_unless (g_list_length (buffers) == i);
659 for (iter = buffers; iter; iter = g_list_next (iter)) {
665 gst_buffer_map (buffer, &map, GST_MAP_READ);
668 num = *(guint64 *) map.data;
669 fail_unless (i == num);
670 fail_unless (GST_BUFFER_PTS (buffer) == gst_util_uint64_scale_round (i,
671 GST_SECOND * TEST_VIDEO_FPS_D, TEST_VIDEO_FPS_N));
672 fail_unless (GST_BUFFER_DURATION (buffer) ==
673 gst_util_uint64_scale_round (GST_SECOND, TEST_VIDEO_FPS_D,
676 gst_buffer_unmap (buffer, &map);
680 g_list_free_full (buffers, (GDestroyNotify) gst_buffer_unref);
683 cleanup_videodecodertest ();
688 /* make sure that the segment event is pushed before the gap */
689 GST_START_TEST (videodecoder_first_data_is_gap)
694 setup_videodecodertester (NULL, NULL);
696 gst_pad_set_active (mysrcpad, TRUE);
697 gst_element_set_state (dec, GST_STATE_PLAYING);
698 gst_pad_set_active (mysinkpad, TRUE);
700 send_startup_events ();
702 /* push a new segment */
703 gst_segment_init (&segment, GST_FORMAT_TIME);
704 fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_segment (&segment)));
707 fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_gap (0,
709 events_iter = events;
710 /* make sure the usual events have been received */
712 GstEvent *sstart = events_iter->data;
713 fail_unless (GST_EVENT_TYPE (sstart) == GST_EVENT_STREAM_START);
714 events_iter = g_list_next (events_iter);
717 GstEvent *caps_event = events_iter->data;
718 fail_unless (GST_EVENT_TYPE (caps_event) == GST_EVENT_CAPS);
719 events_iter = g_list_next (events_iter);
722 GstEvent *segment_event = events_iter->data;
723 fail_unless (GST_EVENT_TYPE (segment_event) == GST_EVENT_SEGMENT);
724 events_iter = g_list_next (events_iter);
727 /* Make sure the gap was pushed */
729 GstEvent *gap = events_iter->data;
730 fail_unless (GST_EVENT_TYPE (gap) == GST_EVENT_GAP);
731 events_iter = g_list_next (events_iter);
733 fail_unless (events_iter == NULL);
735 cleanup_videodecodertest ();
740 GST_START_TEST (videodecoder_backwards_playback)
747 setup_videodecodertester (NULL, NULL);
749 gst_pad_set_active (mysrcpad, TRUE);
750 gst_element_set_state (dec, GST_STATE_PLAYING);
751 gst_pad_set_active (mysinkpad, TRUE);
753 send_startup_events ();
755 /* push a new segment with -1 rate */
756 gst_segment_init (&segment, GST_FORMAT_TIME);
758 segment.stop = (NUM_BUFFERS + 1) * gst_util_uint64_scale_round (GST_SECOND,
759 TEST_VIDEO_FPS_D, TEST_VIDEO_FPS_N);
760 fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_segment (&segment)));
762 /* push buffers, the data is actually a number so we can track them */
768 /* push groups of 10 buffers
769 * every number that is divisible by 10 is set as a discont,
770 * if it is divisible by 20 it is also a keyframe
772 * The logic here is that the current i is the target, and then
773 * it pushes buffers from 'target - 10' up to target.
775 for (j = MAX (target - 10, 0); j < target; j++) {
776 GstBuffer *buffer = create_test_buffer (j);
779 GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
781 GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT);
783 fail_unless (gst_pad_push (mysrcpad, buffer) == GST_FLOW_OK);
788 fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_eos ()));
790 /* check that all buffers were received by our source pad */
791 fail_unless (g_list_length (buffers) == NUM_BUFFERS);
793 for (iter = buffers; iter; iter = g_list_next (iter)) {
799 gst_buffer_map (buffer, &map, GST_MAP_READ);
802 num = *(guint64 *) map.data;
803 fail_unless (i == num);
804 fail_unless (GST_BUFFER_PTS (buffer) == gst_util_uint64_scale_round (i,
805 GST_SECOND * TEST_VIDEO_FPS_D, TEST_VIDEO_FPS_N));
806 fail_unless (GST_BUFFER_DURATION (buffer) ==
807 gst_util_uint64_scale_round (GST_SECOND, TEST_VIDEO_FPS_D,
810 gst_buffer_unmap (buffer, &map);
814 g_list_free_full (buffers, (GDestroyNotify) gst_buffer_unref);
817 cleanup_videodecodertest ();
823 GST_START_TEST (videodecoder_backwards_buffer_after_segment)
830 setup_videodecodertester (NULL, NULL);
832 gst_pad_set_active (mysrcpad, TRUE);
833 gst_element_set_state (dec, GST_STATE_PLAYING);
834 gst_pad_set_active (mysinkpad, TRUE);
836 send_startup_events ();
838 /* push a new segment with -1 rate */
839 gst_segment_init (&segment, GST_FORMAT_TIME);
841 segment.start = GST_SECOND;
842 segment.stop = (NUM_BUFFERS + 1) * gst_util_uint64_scale_round (GST_SECOND,
843 TEST_VIDEO_FPS_D, TEST_VIDEO_FPS_N);
844 fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_segment (&segment)));
846 /* push buffers, the data is actually a number so we can track them */
849 while (pos >= GST_SECOND) {
855 /* push groups of 10 buffers
856 * every number that is divisible by 10 is set as a discont,
857 * if it is divisible by 20 it is also a keyframe
859 * The logic here is that the current i is the target, and then
860 * it pushes buffers from 'target - 10' up to target.
862 for (j = MAX (target - 10, 0); j < target; j++) {
863 buffer = create_test_buffer (j);
865 pos = MIN (GST_BUFFER_TIMESTAMP (buffer), pos);
867 GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
869 GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT);
871 fail_unless (gst_pad_push (mysrcpad, buffer) == GST_FLOW_OK);
876 /* push a discont buffer so it flushes the decoding */
877 buffer = create_test_buffer (i - 10);
878 GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
879 GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT);
880 fail_unless (gst_pad_push (mysrcpad, buffer) == GST_FLOW_EOS);
882 /* check that the last received buffer doesn't contain a
883 * timestamp before the segment */
884 buffer = g_list_last (buffers)->data;
885 fail_unless (GST_BUFFER_TIMESTAMP (buffer) <= segment.start
886 && GST_BUFFER_TIMESTAMP (buffer) + GST_BUFFER_DURATION (buffer) >
889 /* flush our decoded data queue */
890 g_list_free_full (buffers, (GDestroyNotify) gst_buffer_unref);
893 fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_eos ()));
895 fail_unless (buffers == NULL);
897 cleanup_videodecodertest ();
903 GST_START_TEST (videodecoder_query_caps_with_fixed_caps_peer)
907 GstStructure *structure;
908 gint width, height, fps_n, fps_d;
910 setup_videodecodertester (&sinktemplate_restricted, NULL);
912 gst_pad_set_active (mysrcpad, TRUE);
913 gst_element_set_state (dec, GST_STATE_PLAYING);
914 gst_pad_set_active (mysinkpad, TRUE);
916 caps = gst_pad_peer_query_caps (mysrcpad, NULL);
917 fail_unless (caps != NULL);
919 structure = gst_caps_get_structure (caps, 0);
920 fail_unless (gst_structure_get_int (structure, "width", &width));
921 fail_unless (gst_structure_get_int (structure, "height", &height));
922 fail_unless (gst_structure_get_fraction (structure, "framerate", &fps_n,
924 /* match our restricted caps values */
925 fail_unless (width == RESTRICTED_CAPS_WIDTH);
926 fail_unless (height == RESTRICTED_CAPS_HEIGHT);
927 fail_unless (fps_n == RESTRICTED_CAPS_FPS_N);
928 fail_unless (fps_d == RESTRICTED_CAPS_FPS_D);
929 gst_caps_unref (caps);
931 filter = gst_caps_new_simple ("video/x-custom-test", "width", G_TYPE_INT,
932 1000, "height", G_TYPE_INT, 1000, "framerate", GST_TYPE_FRACTION,
934 caps = gst_pad_peer_query_caps (mysrcpad, filter);
935 fail_unless (caps != NULL);
936 fail_unless (gst_caps_is_empty (caps));
937 gst_caps_unref (caps);
938 gst_caps_unref (filter);
940 cleanup_videodecodertest ();
946 _get_int_range (GstStructure * s, const gchar * field, gint * min_v,
951 value = gst_structure_get_value (s, field);
952 fail_unless (value != NULL);
953 fail_unless (GST_VALUE_HOLDS_INT_RANGE (value));
955 *min_v = gst_value_get_int_range_min (value);
956 *max_v = gst_value_get_int_range_max (value);
960 _get_fraction_range (GstStructure * s, const gchar * field, gint * fps_n_min,
961 gint * fps_d_min, gint * fps_n_max, gint * fps_d_max)
964 const GValue *min_v, *max_v;
966 value = gst_structure_get_value (s, field);
967 fail_unless (value != NULL);
968 fail_unless (GST_VALUE_HOLDS_FRACTION_RANGE (value));
970 min_v = gst_value_get_fraction_range_min (value);
971 fail_unless (GST_VALUE_HOLDS_FRACTION (min_v));
972 *fps_n_min = gst_value_get_fraction_numerator (min_v);
973 *fps_d_min = gst_value_get_fraction_denominator (min_v);
975 max_v = gst_value_get_fraction_range_max (value);
976 fail_unless (GST_VALUE_HOLDS_FRACTION (max_v));
977 *fps_n_max = gst_value_get_fraction_numerator (max_v);
978 *fps_d_max = gst_value_get_fraction_denominator (max_v);
981 GST_START_TEST (videodecoder_query_caps_with_range_caps_peer)
985 GstStructure *structure;
986 gint width, height, fps_n, fps_d;
987 gint width_min, height_min, fps_n_min, fps_d_min;
988 gint width_max, height_max, fps_n_max, fps_d_max;
990 setup_videodecodertester (&sinktemplate_with_range, NULL);
992 gst_pad_set_active (mysrcpad, TRUE);
993 gst_element_set_state (dec, GST_STATE_PLAYING);
994 gst_pad_set_active (mysinkpad, TRUE);
996 caps = gst_pad_peer_query_caps (mysrcpad, NULL);
997 fail_unless (caps != NULL);
999 structure = gst_caps_get_structure (caps, 0);
1000 _get_int_range (structure, "width", &width_min, &width_max);
1001 _get_int_range (structure, "height", &height_min, &height_max);
1002 _get_fraction_range (structure, "framerate", &fps_n_min, &fps_d_min,
1003 &fps_n_max, &fps_d_max);
1004 fail_unless (width_min == 1);
1005 fail_unless (width_max == RESTRICTED_CAPS_WIDTH);
1006 fail_unless (height_min == 1);
1007 fail_unless (height_max == RESTRICTED_CAPS_HEIGHT);
1008 fail_unless (fps_n_min == 1);
1009 fail_unless (fps_d_min == 1);
1010 fail_unless (fps_n_max == RESTRICTED_CAPS_FPS_N);
1011 fail_unless (fps_d_max == RESTRICTED_CAPS_FPS_D);
1012 gst_caps_unref (caps);
1014 /* query with a fixed filter */
1015 filter = gst_caps_new_simple ("video/x-test-custom", "width", G_TYPE_INT,
1016 RESTRICTED_CAPS_WIDTH, "height", G_TYPE_INT, RESTRICTED_CAPS_HEIGHT,
1017 "framerate", GST_TYPE_FRACTION, RESTRICTED_CAPS_FPS_N,
1018 RESTRICTED_CAPS_FPS_D, NULL);
1019 caps = gst_pad_peer_query_caps (mysrcpad, filter);
1020 fail_unless (caps != NULL);
1021 structure = gst_caps_get_structure (caps, 0);
1022 fail_unless (gst_structure_get_int (structure, "width", &width));
1023 fail_unless (gst_structure_get_int (structure, "height", &height));
1024 fail_unless (gst_structure_get_fraction (structure, "framerate", &fps_n,
1026 fail_unless (width == RESTRICTED_CAPS_WIDTH);
1027 fail_unless (height == RESTRICTED_CAPS_HEIGHT);
1028 fail_unless (fps_n == RESTRICTED_CAPS_FPS_N);
1029 fail_unless (fps_d == RESTRICTED_CAPS_FPS_D);
1030 gst_caps_unref (caps);
1031 gst_caps_unref (filter);
1033 /* query with a fixed filter that will lead to empty result */
1034 filter = gst_caps_new_simple ("video/x-test-custom", "width", G_TYPE_INT,
1035 1000, "height", G_TYPE_INT, 1000, "framerate", GST_TYPE_FRACTION,
1037 caps = gst_pad_peer_query_caps (mysrcpad, filter);
1038 fail_unless (caps != NULL);
1039 fail_unless (gst_caps_is_empty (caps));
1040 gst_caps_unref (caps);
1041 gst_caps_unref (filter);
1043 cleanup_videodecodertest ();
1048 #define GETCAPS_CAPS_STR "video/x-test-custom, somefield=(string)getcaps"
1050 _custom_video_decoder_getcaps (GstVideoDecoder * dec, GstCaps * filter)
1052 return gst_caps_from_string (GETCAPS_CAPS_STR);
1055 GST_START_TEST (videodecoder_query_caps_with_custom_getcaps)
1058 GstVideoDecoderClass *klass;
1059 GstCaps *expected_caps;
1061 setup_videodecodertester (&sinktemplate_restricted, NULL);
1063 klass = GST_VIDEO_DECODER_CLASS (GST_VIDEO_DECODER_GET_CLASS (dec));
1064 klass->getcaps = _custom_video_decoder_getcaps;
1066 gst_pad_set_active (mysrcpad, TRUE);
1067 gst_element_set_state (dec, GST_STATE_PLAYING);
1068 gst_pad_set_active (mysinkpad, TRUE);
1070 caps = gst_pad_peer_query_caps (mysrcpad, NULL);
1071 fail_unless (caps != NULL);
1073 expected_caps = gst_caps_from_string (GETCAPS_CAPS_STR);
1074 fail_unless (gst_caps_is_equal (expected_caps, caps));
1075 gst_caps_unref (expected_caps);
1076 gst_caps_unref (caps);
1078 cleanup_videodecodertest ();
1083 static const gchar *test_default_caps[][2] = {
1085 "video/x-test-custom",
1086 "video/x-raw, format=I420, width=1280, height=720, framerate=0/1, multiview-mode=mono"}, {
1087 "video/x-test-custom, width=1000",
1088 "video/x-raw, format=I420, width=1000, height=720, framerate=0/1, multiview-mode=mono"}, {
1089 "video/x-test-custom, height=500",
1090 "video/x-raw, format=I420, width=1280, height=500, framerate=0/1, multiview-mode=mono"}, {
1091 "video/x-test-custom, framerate=10/1",
1092 "video/x-raw, format=I420, width=1280, height=720, framerate=10/1, multiview-mode=mono"}, {
1093 "video/x-test-custom, pixel-aspect-ratio=2/1",
1094 "video/x-raw, format=I420, width=1280, height=720, framerate=0/1,"
1095 "pixel-aspect-ratio=2/1, multiview-mode=mono"}
1098 GST_START_TEST (videodecoder_default_caps_on_gap_before_buffer)
1100 GstVideoDecoderTester *dec =
1101 g_object_new (GST_VIDEO_DECODER_TESTER_TYPE, NULL);
1103 gst_harness_new_with_element (GST_ELEMENT (dec), "sink", "src");
1105 GstCaps *caps1, *caps2;
1106 GstVideoInfo info1, info2;
1108 /* Don't set output state since we want trigger the default output caps */
1109 dec->set_output_state = FALSE;
1110 gst_harness_set_src_caps_str (h, test_default_caps[__i__][0]);
1112 fail_unless (gst_harness_push_event (h, gst_event_new_gap (0, GST_SECOND)));
1114 fail_unless_equals_int (gst_harness_events_received (h), 4);
1116 event = gst_harness_pull_event (h);
1117 fail_unless (GST_EVENT_TYPE (event) == GST_EVENT_STREAM_START);
1118 gst_event_unref (event);
1120 event = gst_harness_pull_event (h);
1121 fail_unless (GST_EVENT_TYPE (event) == GST_EVENT_CAPS);
1122 gst_event_unref (event);
1124 event = gst_harness_pull_event (h);
1125 fail_unless (GST_EVENT_TYPE (event) == GST_EVENT_SEGMENT);
1126 gst_event_unref (event);
1128 event = gst_harness_pull_event (h);
1129 fail_unless (GST_EVENT_TYPE (event) == GST_EVENT_GAP);
1130 gst_event_unref (event);
1132 caps1 = gst_pad_get_current_caps (h->sinkpad);
1133 caps2 = gst_caps_from_string (test_default_caps[__i__][1]);
1134 gst_video_info_from_caps (&info1, caps1);
1135 gst_video_info_from_caps (&info2, caps2);
1137 gst_caps_unref (caps1);
1138 gst_caps_unref (caps2);
1140 fail_unless (gst_video_info_is_equal (&info1, &info2));
1142 gst_harness_teardown (h);
1143 gst_object_unref (dec);
1148 GST_START_TEST (videodecoder_playback_event_order)
1155 setup_videodecodertester (NULL, NULL);
1157 gst_pad_set_active (mysrcpad, TRUE);
1158 gst_element_set_state (dec, GST_STATE_PLAYING);
1159 gst_pad_set_active (mysinkpad, TRUE);
1161 send_startup_events ();
1163 /* push a new segment */
1164 gst_segment_init (&segment, GST_FORMAT_TIME);
1165 fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_segment (&segment)));
1167 /* push 5 buffer with one event each. All buffers except the last
1168 * one are dropped in some way, so the events are collected in various
1169 * places. The order must be preserved.
1170 * With the first buffer the segment event is added to the pending event
1171 * list to ensure that incorrect ordering can be detected for later
1174 for (i = 0; i < 9; i++) {
1176 buffer = create_test_buffer (i);
1178 GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT);
1179 fail_unless (gst_pad_push (mysrcpad, buffer) == GST_FLOW_OK);
1183 ol = l = gst_video_decoder_get_frames (GST_VIDEO_DECODER (dec));
1184 fail_unless (g_list_length (l) == 1);
1186 GstVideoCodecFrame *tmp = l->data;
1189 gst_video_decoder_release_frame (GST_VIDEO_DECODER (dec), tmp);
1191 gst_video_decoder_drop_frame (GST_VIDEO_DECODER (dec), tmp);
1193 l = g_list_next (l);
1199 tags = gst_tag_list_new (GST_TAG_TRACK_NUMBER, i, NULL);
1200 fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_tag (tags)));
1204 fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_eos ()));
1206 events_iter = events;
1207 /* make sure the usual events have been received */
1209 GstEvent *sstart = events_iter->data;
1210 fail_unless (GST_EVENT_TYPE (sstart) == GST_EVENT_STREAM_START);
1211 events_iter = g_list_next (events_iter);
1214 GstEvent *caps_event = events_iter->data;
1215 fail_unless (GST_EVENT_TYPE (caps_event) == GST_EVENT_CAPS);
1216 events_iter = g_list_next (events_iter);
1219 GstEvent *segment_event = events_iter->data;
1220 fail_unless (GST_EVENT_TYPE (segment_event) == GST_EVENT_SEGMENT);
1221 events_iter = g_list_next (events_iter);
1224 /* Check the order of the tag events */
1225 for (i = 1; i < 9; i += 2) {
1227 GstEvent *tag_event = events_iter->data;
1228 GstTagList *taglist = NULL;
1230 fail_unless (GST_EVENT_TYPE (tag_event) == GST_EVENT_TAG);
1231 gst_event_parse_tag (tag_event, &taglist);
1233 fail_unless (gst_tag_list_get_uint (taglist, GST_TAG_TRACK_NUMBER, &tag_v));
1234 fail_unless (tag_v == i);
1236 events_iter = g_list_next (events_iter);
1239 /* check that EOS was received */
1241 GstEvent *eos = events_iter->data;
1243 fail_unless (GST_EVENT_TYPE (eos) == GST_EVENT_EOS);
1244 events_iter = g_list_next (events_iter);
1247 fail_unless (events_iter == NULL);
1249 g_list_free_full (buffers, (GDestroyNotify) gst_buffer_unref);
1252 cleanup_videodecodertest ();
1258 gst_videodecoder_suite (void)
1260 Suite *s = suite_create ("GstVideoDecoder");
1261 TCase *tc = tcase_create ("general");
1263 suite_add_tcase (s, tc);
1265 tcase_add_test (tc, videodecoder_query_caps_with_fixed_caps_peer);
1266 tcase_add_test (tc, videodecoder_query_caps_with_range_caps_peer);
1267 tcase_add_test (tc, videodecoder_query_caps_with_custom_getcaps);
1269 tcase_add_test (tc, videodecoder_playback);
1270 tcase_add_test (tc, videodecoder_playback_with_events);
1271 tcase_add_test (tc, videodecoder_playback_first_frames_not_decoded);
1272 tcase_add_test (tc, videodecoder_buffer_after_segment);
1273 tcase_add_test (tc, videodecoder_first_data_is_gap);
1275 tcase_add_test (tc, videodecoder_backwards_playback);
1276 tcase_add_test (tc, videodecoder_backwards_buffer_after_segment);
1277 tcase_add_test (tc, videodecoder_flush_events);
1279 tcase_add_loop_test (tc, videodecoder_default_caps_on_gap_before_buffer, 0,
1280 G_N_ELEMENTS (test_default_caps));
1282 tcase_add_test (tc, videodecoder_playback_event_order);
1287 GST_CHECK_MAIN (gst_videodecoder);