5 * Copyright (C) <2008> Mark Nauwelaerts <mnauw@users.sf.net>
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
17 * You should have received a copy of the GNU Library General Public
18 * License along with this library; if not, write to the
19 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 * Boston, MA 02111-1307, USA.
31 #include <gst/check/gstcheck.h>
32 #include <gst/pbutils/encoding-profile.h>
34 /* For ease of programming we use globals to keep refs for our floating
35 * src and sink pads we create; otherwise we always have to do get_pad,
36 * get_peer, and then remove references in every test function */
37 static GstPad *mysrcpad, *mysinkpad;
39 #define AUDIO_CAPS_STRING "audio/mpeg, " \
40 "mpegversion = (int) 1, " \
42 "channels = (int) 2, " \
45 #define AUDIO_AAC_CAPS_STRING "audio/mpeg, " \
46 "mpegversion=(int)4, " \
49 "stream-format=(string)raw, " \
51 "base-profile=(string)lc, " \
52 "profile=(string)lc, " \
53 "codec_data=(buffer)1208"
55 #define VIDEO_CAPS_STRING "video/mpeg, " \
56 "mpegversion = (int) 4, " \
57 "systemstream = (boolean) false, " \
58 "width = (int) 384, " \
59 "height = (int) 288, " \
60 "framerate = (fraction) 25/1"
62 #define VIDEO_CAPS_H264_STRING "video/x-h264, " \
65 "framerate=(fraction)30/1, " \
66 "pixel-aspect-ratio=(fraction)1/1, " \
67 "codec_data=(buffer)01640014ffe1001867640014a" \
68 "cd94141fb0110000003001773594000f14299600" \
70 "stream-format=(string)avc, " \
71 "alignment=(string)au, " \
73 "profile=(string)high"
75 static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
78 GST_STATIC_CAPS ("video/quicktime"));
79 static GstStaticPadTemplate srcvideotemplate = GST_STATIC_PAD_TEMPLATE ("src",
82 GST_STATIC_CAPS (VIDEO_CAPS_STRING));
84 static GstStaticPadTemplate srcvideoh264template =
85 GST_STATIC_PAD_TEMPLATE ("src",
88 GST_STATIC_CAPS (VIDEO_CAPS_H264_STRING));
90 static GstStaticPadTemplate srcaudiotemplate = GST_STATIC_PAD_TEMPLATE ("src",
93 GST_STATIC_CAPS (AUDIO_CAPS_STRING));
95 static GstStaticPadTemplate srcaudioaactemplate =
96 GST_STATIC_PAD_TEMPLATE ("src",
99 GST_STATIC_CAPS (AUDIO_AAC_CAPS_STRING));
101 /* setup and teardown needs some special handling for muxer */
103 setup_src_pad (GstElement * element,
104 GstStaticPadTemplate * template, GstCaps * caps, const gchar * sinkname)
106 GstPad *srcpad, *sinkpad;
108 GST_DEBUG_OBJECT (element, "setting up sending pad");
110 srcpad = gst_pad_new_from_static_template (template, "src");
111 fail_if (srcpad == NULL, "Could not create a srcpad");
112 ASSERT_OBJECT_REFCOUNT (srcpad, "srcpad", 1);
114 if (!(sinkpad = gst_element_get_static_pad (element, sinkname)))
115 sinkpad = gst_element_get_request_pad (element, sinkname);
116 fail_if (sinkpad == NULL, "Could not get sink pad from %s",
117 GST_ELEMENT_NAME (element));
118 /* references are owned by: 1) us, 2) qtmux, 3) collect pads */
119 ASSERT_OBJECT_REFCOUNT (sinkpad, "sinkpad", 3);
121 fail_unless (gst_pad_set_caps (srcpad, caps));
122 fail_unless (gst_pad_link (srcpad, sinkpad) == GST_PAD_LINK_OK,
123 "Could not link source and %s sink pads", GST_ELEMENT_NAME (element));
124 gst_object_unref (sinkpad); /* because we got it higher up */
126 /* references are owned by: 1) qtmux, 2) collect pads */
127 ASSERT_OBJECT_REFCOUNT (sinkpad, "sinkpad", 2);
133 teardown_src_pad (GstPad * srcpad)
137 /* clean up floating src pad */
138 sinkpad = gst_pad_get_peer (srcpad);
139 fail_if (sinkpad == NULL);
140 /* pad refs held by 1) qtmux 2) collectpads and 3) us (through _get_peer) */
141 ASSERT_OBJECT_REFCOUNT (sinkpad, "sinkpad", 3);
143 gst_pad_unlink (srcpad, sinkpad);
145 /* after unlinking, pad refs still held by
146 * 1) qtmux and 2) collectpads and 3) us (through _get_peer) */
147 ASSERT_OBJECT_REFCOUNT (sinkpad, "sinkpad", 3);
148 gst_object_unref (sinkpad);
149 /* one more ref is held by element itself */
151 /* pad refs held by creator */
152 ASSERT_OBJECT_REFCOUNT (srcpad, "srcpad", 1);
153 gst_object_unref (srcpad);
157 setup_qtmux (GstStaticPadTemplate * srctemplate, const gchar * sinkname)
161 GST_DEBUG ("setup_qtmux");
162 qtmux = gst_check_setup_element ("qtmux");
163 mysrcpad = setup_src_pad (qtmux, srctemplate, NULL, sinkname);
164 mysinkpad = gst_check_setup_sink_pad (qtmux, &sinktemplate, NULL);
165 gst_pad_set_active (mysrcpad, TRUE);
166 gst_pad_set_active (mysinkpad, TRUE);
172 cleanup_qtmux (GstElement * qtmux, const gchar * sinkname)
174 GST_DEBUG ("cleanup_qtmux");
175 gst_element_set_state (qtmux, GST_STATE_NULL);
177 gst_pad_set_active (mysrcpad, FALSE);
178 gst_pad_set_active (mysinkpad, FALSE);
179 teardown_src_pad (mysrcpad);
180 gst_check_teardown_sink_pad (qtmux);
181 gst_check_teardown_element (qtmux);
185 check_qtmux_pad (GstStaticPadTemplate * srctemplate, const gchar * sinkname,
189 GstBuffer *inbuffer, *outbuffer;
193 guint8 data0[12] = "\000\000\000\024ftypqt ";
194 guint8 data1[8] = "\000\000\000\001mdat";
195 guint8 data2[4] = "moov";
197 qtmux = setup_qtmux (srctemplate, sinkname);
198 g_object_set (qtmux, "dts-method", dts_method, NULL);
199 fail_unless (gst_element_set_state (qtmux,
200 GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
201 "could not set to playing");
203 inbuffer = gst_buffer_new_and_alloc (1);
204 caps = gst_caps_copy (gst_pad_get_pad_template_caps (mysrcpad));
205 gst_buffer_set_caps (inbuffer, caps);
206 gst_caps_unref (caps);
207 GST_BUFFER_TIMESTAMP (inbuffer) = 0;
208 GST_BUFFER_DURATION (inbuffer) = 40 * GST_MSECOND;
209 ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
210 fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
212 /* send eos to have moov written */
213 fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_eos ()) == TRUE);
215 num_buffers = g_list_length (buffers);
216 /* at least expect ftyp, mdat header, buffer chunk and moov */
217 fail_unless (num_buffers >= 4);
219 for (i = 0; i < num_buffers; ++i) {
220 outbuffer = GST_BUFFER (buffers->data);
221 fail_if (outbuffer == NULL);
222 buffers = g_list_remove (buffers, outbuffer);
228 guint8 *data = GST_BUFFER_DATA (outbuffer);
230 fail_unless (GST_BUFFER_SIZE (outbuffer) >= 20);
231 fail_unless (memcmp (data, data0, sizeof (data0)) == 0);
232 fail_unless (memcmp (data + 16, data0 + 8, 4) == 0);
235 case 1: /* mdat header */
236 fail_unless (GST_BUFFER_SIZE (outbuffer) == 16);
237 fail_unless (memcmp (GST_BUFFER_DATA (outbuffer), data1, sizeof (data1))
240 case 2: /* buffer we put in */
241 fail_unless (GST_BUFFER_SIZE (outbuffer) == 1);
244 fail_unless (GST_BUFFER_SIZE (outbuffer) > 8);
245 fail_unless (memcmp (GST_BUFFER_DATA (outbuffer) + 4, data2,
246 sizeof (data2)) == 0);
252 ASSERT_BUFFER_REFCOUNT (outbuffer, "outbuffer", 1);
253 gst_buffer_unref (outbuffer);
257 g_list_free (buffers);
260 cleanup_qtmux (qtmux, sinkname);
264 check_qtmux_pad_fragmented (GstStaticPadTemplate * srctemplate,
265 const gchar * sinkname, guint32 dts_method, gboolean streamable)
268 GstBuffer *inbuffer, *outbuffer;
272 guint8 data0[12] = "\000\000\000\024ftypqt ";
273 guint8 data1[4] = "mdat";
274 guint8 data2[4] = "moov";
275 guint8 data3[4] = "moof";
276 guint8 data4[4] = "mfra";
278 qtmux = setup_qtmux (srctemplate, sinkname);
279 g_object_set (qtmux, "dts-method", dts_method, NULL);
280 g_object_set (qtmux, "fragment-duration", 2000, NULL);
281 g_object_set (qtmux, "streamable", streamable, NULL);
282 fail_unless (gst_element_set_state (qtmux,
283 GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
284 "could not set to playing");
286 inbuffer = gst_buffer_new_and_alloc (1);
287 caps = gst_caps_copy (gst_pad_get_pad_template_caps (mysrcpad));
288 gst_buffer_set_caps (inbuffer, caps);
289 gst_caps_unref (caps);
290 GST_BUFFER_TIMESTAMP (inbuffer) = 0;
291 GST_BUFFER_DURATION (inbuffer) = 40 * GST_MSECOND;
292 ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
293 fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
295 /* send eos to have all written */
296 fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_eos ()) == TRUE);
298 num_buffers = g_list_length (buffers);
299 /* at least expect ftyp, moov, moof, mdat header, buffer chunk
300 * and optionally mfra */
301 fail_unless (num_buffers >= 5);
303 for (i = 0; i < num_buffers; ++i) {
304 outbuffer = GST_BUFFER (buffers->data);
305 fail_if (outbuffer == NULL);
306 buffers = g_list_remove (buffers, outbuffer);
312 guint8 *data = GST_BUFFER_DATA (outbuffer);
314 fail_unless (GST_BUFFER_SIZE (outbuffer) >= 20);
315 fail_unless (memcmp (data, data0, sizeof (data0)) == 0);
316 fail_unless (memcmp (data + 16, data0 + 8, 4) == 0);
320 fail_unless (GST_BUFFER_SIZE (outbuffer) > 8);
321 fail_unless (memcmp (GST_BUFFER_DATA (outbuffer) + 4, data2,
322 sizeof (data2)) == 0);
325 fail_unless (GST_BUFFER_SIZE (outbuffer) > 8);
326 fail_unless (memcmp (GST_BUFFER_DATA (outbuffer) + 4, data3,
327 sizeof (data3)) == 0);
329 case 3: /* mdat header */
330 fail_unless (GST_BUFFER_SIZE (outbuffer) == 8);
331 fail_unless (memcmp (GST_BUFFER_DATA (outbuffer) + 4, data1,
332 sizeof (data1)) == 0);
334 case 4: /* buffer we put in */
335 fail_unless (GST_BUFFER_SIZE (outbuffer) == 1);
338 fail_unless (GST_BUFFER_SIZE (outbuffer) > 8);
339 fail_unless (memcmp (GST_BUFFER_DATA (outbuffer) + 4, data4,
340 sizeof (data4)) == 0);
346 ASSERT_BUFFER_REFCOUNT (outbuffer, "outbuffer", 1);
347 gst_buffer_unref (outbuffer);
351 g_list_free (buffers);
354 cleanup_qtmux (qtmux, sinkname);
359 GST_START_TEST (test_video_pad_dd)
361 check_qtmux_pad (&srcvideotemplate, "video_%d", 0);
366 GST_START_TEST (test_audio_pad_dd)
368 check_qtmux_pad (&srcaudiotemplate, "audio_%d", 0);
374 GST_START_TEST (test_video_pad_frag_dd)
376 check_qtmux_pad_fragmented (&srcvideotemplate, "video_%d", 0, FALSE);
381 GST_START_TEST (test_audio_pad_frag_dd)
383 check_qtmux_pad_fragmented (&srcaudiotemplate, "audio_%d", 0, FALSE);
389 GST_START_TEST (test_video_pad_frag_dd_streamable)
391 check_qtmux_pad_fragmented (&srcvideotemplate, "video_%d", 0, TRUE);
397 GST_START_TEST (test_audio_pad_frag_dd_streamable)
399 check_qtmux_pad_fragmented (&srcaudiotemplate, "audio_%d", 0, TRUE);
404 /* dts-method reorder */
406 GST_START_TEST (test_video_pad_reorder)
408 check_qtmux_pad (&srcvideotemplate, "video_%d", 1);
413 GST_START_TEST (test_audio_pad_reorder)
415 check_qtmux_pad (&srcaudiotemplate, "audio_%d", 1);
421 GST_START_TEST (test_video_pad_frag_reorder)
423 check_qtmux_pad_fragmented (&srcvideotemplate, "video_%d", 1, FALSE);
428 GST_START_TEST (test_audio_pad_frag_reorder)
430 check_qtmux_pad_fragmented (&srcaudiotemplate, "audio_%d", 1, FALSE);
436 GST_START_TEST (test_video_pad_frag_reorder_streamable)
438 check_qtmux_pad_fragmented (&srcvideotemplate, "video_%d", 1, TRUE);
444 GST_START_TEST (test_audio_pad_frag_reorder_streamable)
446 check_qtmux_pad_fragmented (&srcaudiotemplate, "audio_%d", 1, TRUE);
453 GST_START_TEST (test_video_pad_asc)
455 check_qtmux_pad (&srcvideotemplate, "video_%d", 2);
460 GST_START_TEST (test_audio_pad_asc)
462 check_qtmux_pad (&srcaudiotemplate, "audio_%d", 2);
468 GST_START_TEST (test_video_pad_frag_asc)
470 check_qtmux_pad_fragmented (&srcvideotemplate, "video_%d", 2, FALSE);
475 GST_START_TEST (test_audio_pad_frag_asc)
477 check_qtmux_pad_fragmented (&srcaudiotemplate, "audio_%d", 2, FALSE);
483 GST_START_TEST (test_video_pad_frag_asc_streamable)
485 check_qtmux_pad_fragmented (&srcvideotemplate, "video_%d", 2, TRUE);
491 GST_START_TEST (test_audio_pad_frag_asc_streamable)
493 check_qtmux_pad_fragmented (&srcaudiotemplate, "audio_%d", 2, TRUE);
498 GST_START_TEST (test_reuse)
500 GstElement *qtmux = setup_qtmux (&srcvideotemplate, "video_%d");
504 gst_element_set_state (qtmux, GST_STATE_PLAYING);
505 gst_element_set_state (qtmux, GST_STATE_NULL);
506 gst_element_set_state (qtmux, GST_STATE_PLAYING);
507 gst_pad_set_active (mysrcpad, TRUE);
508 gst_pad_set_active (mysinkpad, TRUE);
510 inbuffer = gst_buffer_new_and_alloc (1);
511 fail_unless (inbuffer != NULL);
512 caps = gst_caps_copy (gst_pad_get_pad_template_caps (mysrcpad));
513 gst_buffer_set_caps (inbuffer, caps);
514 gst_caps_unref (caps);
515 GST_BUFFER_TIMESTAMP (inbuffer) = 0;
516 GST_BUFFER_DURATION (inbuffer) = 40 * GST_MSECOND;
517 ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
518 fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
520 /* send eos to have all written */
521 fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_eos ()) == TRUE);
523 cleanup_qtmux (qtmux, "video_%d");
528 static GstEncodingContainerProfile *
529 create_qtmux_profile (const gchar * variant)
531 GstEncodingContainerProfile *cprof;
534 if (variant == NULL) {
535 caps = gst_caps_new_simple ("video/quicktime", NULL);
537 caps = gst_caps_new_simple ("video/quicktime",
538 "variant", G_TYPE_STRING, variant, NULL);
541 cprof = gst_encoding_container_profile_new ("Name", "blah", caps, NULL);
542 gst_caps_unref (caps);
544 caps = gst_caps_new_simple ("audio/x-raw-int", "width", G_TYPE_INT, 16,
545 "depth", G_TYPE_INT, 16, "endianness", G_TYPE_INT, 4321,
546 "channels", G_TYPE_INT, 2, "rate", G_TYPE_INT, 44100,
547 "signed", G_TYPE_BOOLEAN, TRUE, NULL);
548 gst_encoding_container_profile_add_profile (cprof,
549 GST_ENCODING_PROFILE (gst_encoding_audio_profile_new (caps, NULL, NULL,
551 gst_caps_unref (caps);
556 GST_START_TEST (test_encodebin_qtmux)
558 GstEncodingContainerProfile *cprof;
562 enc = gst_element_factory_make ("encodebin", NULL);
566 /* Make sure encodebin finds a muxer for a profile with a variant field .. */
567 cprof = create_qtmux_profile ("apple");
568 g_object_set (enc, "profile", cprof, NULL);
569 gst_encoding_profile_unref (cprof);
571 /* should have created a pad after setting the profile */
572 pad = gst_element_get_static_pad (enc, "audio_0");
573 fail_unless (pad != NULL);
574 gst_object_unref (pad);
575 gst_object_unref (enc);
577 /* ... and for a profile without a variant field */
578 enc = gst_element_factory_make ("encodebin", NULL);
579 cprof = create_qtmux_profile (NULL);
580 g_object_set (enc, "profile", cprof, NULL);
581 gst_encoding_profile_unref (cprof);
583 /* should have created a pad after setting the profile */
584 pad = gst_element_get_static_pad (enc, "audio_0");
585 fail_unless (pad != NULL);
586 gst_object_unref (pad);
587 gst_object_unref (enc);
592 /* Fake mp3 encoder for test */
593 typedef GstElement TestMp3Enc;
594 typedef GstElementClass TestMp3EncClass;
596 static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src",
599 GST_STATIC_CAPS ("audio/mpeg, mpegversion=1, layer=[1,3]")
602 static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
605 GST_STATIC_CAPS ("audio/x-raw-int")
608 static GType test_mp3_enc_get_type (void);
610 GST_BOILERPLATE (TestMp3Enc, test_mp3_enc, GstElement, GST_TYPE_ELEMENT);
613 test_mp3_enc_base_init (gpointer klass)
615 GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
617 gst_element_class_add_static_pad_template (element_class,
619 gst_element_class_add_static_pad_template (element_class, &src_template);
621 gst_element_class_set_details_simple (element_class, "MPEG1 Audio Encoder",
622 "Codec/Encoder/Audio", "Pretends to encode mp3", "Foo Bar <foo@bar.com>");
626 test_mp3_enc_class_init (TestMp3EncClass * klass)
628 /* doesn't actually need to do anything for this test */
632 test_mp3_enc_init (TestMp3Enc * mp3enc, TestMp3EncClass * klass)
636 pad = gst_pad_new_from_static_template (&sink_template, "sink");
637 gst_element_add_pad (mp3enc, pad);
639 pad = gst_pad_new_from_static_template (&src_template, "src");
640 gst_element_add_pad (mp3enc, pad);
644 plugin_init (GstPlugin * plugin)
646 return gst_element_register (plugin, "testmp3enc", GST_RANK_NONE,
647 test_mp3_enc_get_type ());
650 static GstEncodingContainerProfile *
651 create_mp4mux_profile (void)
653 GstEncodingContainerProfile *cprof;
656 caps = gst_caps_new_simple ("video/quicktime",
657 "variant", G_TYPE_STRING, "iso", NULL);
659 cprof = gst_encoding_container_profile_new ("Name", "blah", caps, NULL);
660 gst_caps_unref (caps);
662 caps = gst_caps_new_simple ("audio/mpeg", "mpegversion", G_TYPE_INT, 1,
663 "layer", G_TYPE_INT, 3, "channels", G_TYPE_INT, 2, "rate", G_TYPE_INT,
665 gst_encoding_container_profile_add_profile (cprof,
666 GST_ENCODING_PROFILE (gst_encoding_audio_profile_new (caps, NULL, NULL,
668 gst_caps_unref (caps);
673 GST_START_TEST (test_encodebin_mp4mux)
675 GstEncodingContainerProfile *cprof;
676 GstPluginFeature *feature;
677 GstElement *enc, *mux;
680 /* need a fake mp3 encoder because mp4 only accepts encoded formats */
681 gst_plugin_register_static (GST_VERSION_MAJOR, GST_VERSION_MINOR,
682 "fakemp3enc", "fakemp3enc", plugin_init, VERSION, "LGPL",
683 "gst-plugins-good", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN);
685 feature = gst_default_registry_find_feature ("testmp3enc",
686 GST_TYPE_ELEMENT_FACTORY);
687 gst_plugin_feature_set_rank (feature, GST_RANK_PRIMARY + 100);
689 enc = gst_element_factory_make ("encodebin", NULL);
693 /* Make sure encodebin finds mp4mux even though qtmux outputs a superset */
694 cprof = create_mp4mux_profile ();
695 g_object_set (enc, "profile", cprof, NULL);
696 gst_encoding_profile_unref (cprof);
698 /* should have created a pad after setting the profile */
699 pad = gst_element_get_static_pad (enc, "audio_0");
700 fail_unless (pad != NULL);
701 gst_object_unref (pad);
703 mux = gst_bin_get_by_interface (GST_BIN (enc), GST_TYPE_TAG_SETTER);
704 fail_unless (mux != NULL);
706 GstElementFactory *f = gst_element_get_factory (mux);
708 /* make sure we got mp4mux for variant=iso */
709 GST_INFO ("muxer: %s", G_OBJECT_TYPE_NAME (mux));
710 fail_unless_equals_string (GST_PLUGIN_FEATURE_NAME (f), "mp4mux");
712 gst_object_unref (mux);
713 gst_object_unref (enc);
715 gst_plugin_feature_set_rank (feature, GST_RANK_NONE);
716 gst_object_unref (feature);
722 extract_tags (const gchar * location, GstTagList ** taglist)
727 GstElement *pipeline =
728 gst_parse_launch ("filesrc name=src ! qtdemux ! fakesink", NULL);
730 src = gst_bin_get_by_name (GST_BIN (pipeline), "src");
731 g_object_set (src, "location", location, NULL);
733 bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
734 fail_unless (gst_element_set_state (pipeline, GST_STATE_PLAYING)
735 != GST_STATE_CHANGE_FAILURE);
737 if (*taglist == NULL) {
738 *taglist = gst_tag_list_new ();
742 GstMessage *msg = gst_bus_timed_pop_filtered (bus, GST_CLOCK_TIME_NONE,
743 GST_MESSAGE_TAG | GST_MESSAGE_ERROR | GST_MESSAGE_EOS);
745 if (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_EOS) {
746 gst_message_unref (msg);
748 } else if (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_ERROR) {
750 gst_message_unref (msg);
752 } else if (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_TAG) {
755 gst_message_parse_tag (msg, &tags);
756 gst_tag_list_insert (*taglist, tags, GST_TAG_MERGE_REPLACE);
757 gst_tag_list_free (tags);
759 gst_message_unref (msg);
762 gst_object_unref (bus);
763 gst_element_set_state (pipeline, GST_STATE_NULL);
764 gst_object_unref (src);
765 gst_object_unref (pipeline);
770 test_average_bitrate_custom (const gchar * elementname,
771 GstStaticPadTemplate * tmpl, const gchar * sinkpadname)
775 GstElement *filesink;
779 gint bytes[] = { 16, 22, 12 };
780 gint64 durations[] = { GST_SECOND * 3, GST_SECOND * 5, GST_SECOND * 2 };
781 gint64 total_bytes = 0;
782 GstClockTime total_duration = 0;
784 location = g_strdup_printf ("%s/%s-%d", g_get_tmp_dir (), "qtmuxtest",
786 GST_INFO ("Using location %s for bitrate test", location);
787 qtmux = gst_check_setup_element (elementname);
788 filesink = gst_element_factory_make ("filesink", NULL);
789 g_object_set (filesink, "location", location, NULL);
790 gst_element_link (qtmux, filesink);
791 mysrcpad = setup_src_pad (qtmux, tmpl, NULL, sinkpadname);
792 fail_unless (mysrcpad != NULL);
793 gst_pad_set_active (mysrcpad, TRUE);
795 fail_unless (gst_element_set_state (filesink,
796 GST_STATE_PLAYING) != GST_STATE_CHANGE_FAILURE,
797 "could not set filesink to playing");
798 fail_unless (gst_element_set_state (qtmux,
799 GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
800 "could not set to playing");
802 for (i = 0; i < 3; i++) {
803 inbuffer = gst_buffer_new_and_alloc (bytes[i]);
804 caps = gst_caps_copy (gst_pad_get_pad_template_caps (mysrcpad));
805 gst_buffer_set_caps (inbuffer, caps);
806 gst_caps_unref (caps);
807 GST_BUFFER_TIMESTAMP (inbuffer) = total_duration;
808 GST_BUFFER_DURATION (inbuffer) = (GstClockTime) durations[i];
809 ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
811 total_bytes += GST_BUFFER_SIZE (inbuffer);
812 total_duration += GST_BUFFER_DURATION (inbuffer);
813 fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
816 /* send eos to have moov written */
817 fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_eos ()) == TRUE);
819 gst_element_set_state (qtmux, GST_STATE_NULL);
820 gst_element_set_state (filesink, GST_STATE_NULL);
822 gst_pad_set_active (mysrcpad, FALSE);
823 teardown_src_pad (mysrcpad);
824 gst_object_unref (filesink);
825 gst_check_teardown_element (qtmux);
827 /* check the bitrate tag */
829 GstTagList *taglist = NULL;
833 fail_unless (extract_tags (location, &taglist));
835 fail_unless (gst_tag_list_get_uint (taglist, GST_TAG_BITRATE, &bitrate));
838 (guint) gst_util_uint64_scale_round ((guint64) total_bytes,
839 (guint64) 8 * GST_SECOND, (guint64) total_duration);
840 fail_unless (bitrate == expected);
844 GST_START_TEST (test_average_bitrate)
846 test_average_bitrate_custom ("mp4mux", &srcaudioaactemplate, "audio_%d");
847 test_average_bitrate_custom ("mp4mux", &srcvideoh264template, "video_%d");
849 test_average_bitrate_custom ("qtmux", &srcaudioaactemplate, "audio_%d");
850 test_average_bitrate_custom ("qtmux", &srcvideoh264template, "video_%d");
859 Suite *s = suite_create ("qtmux");
860 TCase *tc_chain = tcase_create ("general");
862 suite_add_tcase (s, tc_chain);
863 tcase_add_test (tc_chain, test_video_pad_dd);
864 tcase_add_test (tc_chain, test_audio_pad_dd);
865 tcase_add_test (tc_chain, test_video_pad_frag_dd);
866 tcase_add_test (tc_chain, test_audio_pad_frag_dd);
867 tcase_add_test (tc_chain, test_video_pad_frag_dd_streamable);
868 tcase_add_test (tc_chain, test_audio_pad_frag_dd_streamable);
870 tcase_add_test (tc_chain, test_video_pad_reorder);
871 tcase_add_test (tc_chain, test_audio_pad_reorder);
872 tcase_add_test (tc_chain, test_video_pad_frag_reorder);
873 tcase_add_test (tc_chain, test_audio_pad_frag_reorder);
874 tcase_add_test (tc_chain, test_video_pad_frag_reorder_streamable);
875 tcase_add_test (tc_chain, test_audio_pad_frag_reorder_streamable);
877 tcase_add_test (tc_chain, test_video_pad_asc);
878 tcase_add_test (tc_chain, test_audio_pad_asc);
879 tcase_add_test (tc_chain, test_video_pad_frag_asc);
880 tcase_add_test (tc_chain, test_audio_pad_frag_asc);
881 tcase_add_test (tc_chain, test_video_pad_frag_asc_streamable);
882 tcase_add_test (tc_chain, test_audio_pad_frag_asc_streamable);
884 tcase_add_test (tc_chain, test_average_bitrate);
886 tcase_add_test (tc_chain, test_reuse);
887 tcase_add_test (tc_chain, test_encodebin_qtmux);
888 tcase_add_test (tc_chain, test_encodebin_mp4mux);
893 GST_CHECK_MAIN (qtmux)