encodebin: refactor tests
[platform/upstream/gstreamer.git] / tests / check / elements / encodebin.c
1 /* GStreamer unit test for gstprofile
2  *
3  * Copyright (C) <2009> Edward Hervey <edward.hervey@collabora.co.uk>
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
18  * Boston, MA 02110-1301, USA.
19  */
20
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24
25 #include <gst/pbutils/encoding-profile.h>
26 #include <gst/pbutils/missing-plugins.h>
27 #include <gst/check/gstcheck.h>
28
29 /* Helper functions to create profiles */
30
31 static GstEncodingProfile *
32 create_ogg_profile ()
33 {
34   GstEncodingContainerProfile *prof;
35   GstCaps *ogg;
36
37   ogg = gst_caps_new_empty_simple ("application/ogg");
38   prof = gst_encoding_container_profile_new ((gchar *) "myprofile", NULL, ogg,
39       NULL);
40   gst_caps_unref (ogg);
41   return (GstEncodingProfile *) prof;
42 }
43
44 static GstEncodingProfile *
45 create_ogg_vorbis_profile (guint presence, gchar * preset)
46 {
47   GstEncodingContainerProfile *cprof;
48   GstCaps *ogg, *vorbis;
49
50   ogg = gst_caps_new_empty_simple ("application/ogg");
51   cprof =
52       gst_encoding_container_profile_new ((gchar *) "myprofile", NULL, ogg,
53       NULL);
54   gst_caps_unref (ogg);
55
56   vorbis = gst_caps_new_empty_simple ("audio/x-vorbis");
57   fail_unless (gst_encoding_container_profile_add_profile (cprof,
58           (GstEncodingProfile *) gst_encoding_audio_profile_new (vorbis, preset,
59               NULL, presence)));
60   gst_caps_unref (vorbis);
61
62   return (GstEncodingProfile *) cprof;
63 }
64
65 static GstEncodingProfile *
66 create_ogg_theora_vorbis_profile (guint theorapresence, guint vorbispresence)
67 {
68   GstEncodingContainerProfile *prof;
69   GstCaps *ogg, *vorbis, *theora;
70
71   ogg = gst_caps_new_empty_simple ("application/ogg");
72   prof =
73       gst_encoding_container_profile_new ((gchar *) "myprofile", NULL, ogg,
74       NULL);
75   gst_caps_unref (ogg);
76
77   vorbis = gst_caps_new_empty_simple ("audio/x-vorbis");
78   fail_unless (gst_encoding_container_profile_add_profile (prof,
79           (GstEncodingProfile *) gst_encoding_audio_profile_new (vorbis, NULL,
80               NULL, vorbispresence)));
81   gst_caps_unref (vorbis);
82
83   theora = gst_caps_new_empty_simple ("video/x-theora");
84   fail_unless (gst_encoding_container_profile_add_profile (prof,
85           (GstEncodingProfile *) gst_encoding_video_profile_new (theora, NULL,
86               NULL, theorapresence)));
87   gst_caps_unref (theora);
88
89   return (GstEncodingProfile *) prof;
90 }
91
92 static GstEncodingProfile *
93 create_vorbis_only_profile (void)
94 {
95   GstEncodingProfile *prof;
96   GstCaps *vorbis;
97
98   vorbis = gst_caps_new_empty_simple ("audio/x-vorbis");
99   prof =
100       (GstEncodingProfile *) gst_encoding_audio_profile_new (vorbis, NULL, NULL,
101       0);
102   gst_caps_unref (vorbis);
103
104   return prof;
105 }
106
107 static GstEncodingProfile *
108 create_unsupported_profile (void)
109 {
110   GstEncodingProfile *prof;
111   GstCaps *caps;
112
113   caps = gst_caps_new_empty_simple ("audio/x-bogus");
114   prof =
115       (GstEncodingProfile *) gst_encoding_audio_profile_new (caps, NULL, NULL,
116       0);
117   gst_caps_unref (caps);
118
119   return prof;
120 }
121
122 static void
123 _caps_match (GstPad * sinkpad, const gchar * capsname)
124 {
125   GstCaps *caps, *sinkcaps;
126   gchar *name;
127
128   caps = gst_caps_from_string (capsname);
129   sinkcaps = gst_pad_query_caps (sinkpad, NULL);
130   fail_unless (sinkcaps != NULL);
131   name = gst_caps_to_string (sinkcaps);
132   fail_unless (gst_caps_is_subset (sinkcaps, caps),
133       "caps ('%s') are not a subset of ('%s')", name, capsname);
134   g_free (name);
135   gst_caps_unref (sinkcaps);
136   gst_caps_unref (caps);
137 }
138
139 static void
140 set_profile (GstElement * ebin, GstEncodingProfile * prof)
141 {
142   g_object_set (ebin, "profile", prof, NULL);
143   gst_encoding_profile_unref (prof);
144 }
145
146 /* Tests */
147
148 GST_START_TEST (test_encodebin_set_profile)
149 {
150   GstElement *ebin;
151   GstEncodingProfile *prof, *prof2;
152
153   /* Create an encodebin and check that it correctly changes states
154    * according to whether a profile is set or not */
155
156   ebin = gst_element_factory_make ("encodebin", NULL);
157
158   /* Set a profile on encodebin... */
159   prof = create_ogg_profile ();
160   g_object_set (ebin, "profile", prof, NULL);
161
162   /* ... and check the profile has been properly set */
163   g_object_get (ebin, "profile", &prof2, NULL);
164
165   fail_unless (gst_encoding_profile_is_equal (prof, prof2));
166
167   gst_encoding_profile_unref (prof);
168   gst_encoding_profile_unref (prof2);
169
170   gst_object_unref (ebin);
171 };
172
173 GST_END_TEST;
174
175
176 GST_START_TEST (test_encodebin_can_go_to_ready_without_profile)
177 {
178   GstElement *ebin;
179   GstPad *srcpad;
180   GstPad *target;
181
182   /* Create an encodebin and check that it correctly changes states
183    * according to whether a profile is set or not */
184
185   ebin = gst_element_factory_make ("encodebin", NULL);
186
187   /* Check if the source pad was properly created */
188   srcpad = gst_element_get_static_pad (ebin, "src");
189   fail_unless (srcpad != NULL);
190
191   /* At this point, the ghostpad has *NO* target */
192   target = gst_ghost_pad_get_target (GST_GHOST_PAD (srcpad));
193   fail_unless (target == NULL);
194   gst_object_unref (srcpad);
195
196   /* No profile,
197    * switching to READY should succeed,
198    * but switching to PAUSED should fail
199    */
200   fail_unless_equals_int (gst_element_set_state (ebin, GST_STATE_READY),
201       GST_STATE_CHANGE_SUCCESS);
202   fail_unless_equals_int (gst_element_set_state (ebin, GST_STATE_PAUSED),
203       GST_STATE_CHANGE_FAILURE);
204
205   /* Set back to NULL */
206   fail_unless_equals_int (gst_element_set_state (ebin, GST_STATE_NULL),
207       GST_STATE_CHANGE_SUCCESS);
208
209   gst_object_unref (ebin);
210 };
211
212 GST_END_TEST;
213
214 GST_START_TEST (test_encodebin_can_go_to_paused_with_profile)
215 {
216   GstElement *ebin;
217   GstPad *srcpad;
218   GstPad *target;
219
220   /* Create an encodebin and check that it correctly changes states
221    * according to whether a profile is set or not */
222
223   ebin = gst_element_factory_make ("encodebin", NULL);
224
225   /* Set a profile on encodebin... */
226   set_profile (ebin, create_ogg_profile ());
227
228   /* Make sure we can go to PAUSED */
229   fail_unless_equals_int (gst_element_set_state (ebin, GST_STATE_PAUSED),
230       GST_STATE_CHANGE_SUCCESS);
231
232   /* At this point, the source pad *HAS* a target */
233   srcpad = gst_element_get_static_pad (ebin, "src");
234   fail_unless (srcpad != NULL);
235   target = gst_ghost_pad_get_target (GST_GHOST_PAD (srcpad));
236   fail_unless (target != NULL);
237   gst_object_unref (target);
238   gst_object_unref (srcpad);
239
240
241   /* Set back to NULL */
242   fail_unless_equals_int (gst_element_set_state (ebin, GST_STATE_NULL),
243       GST_STATE_CHANGE_SUCCESS);
244
245   gst_object_unref (ebin);
246 };
247
248 GST_END_TEST;
249
250
251 GST_START_TEST (test_encodebin_sink_pads_static)
252 {
253   GstElement *ebin;
254   GstPad *srcpad, *sinkpad;
255
256   /* Create an encodebin and check that it properly creates the sink pads
257    * for a single-stream profile with fixed presence */
258
259   ebin = gst_element_factory_make ("encodebin", NULL);
260
261   /* streamprofile that has a forced presence of 1 */
262   set_profile (ebin, create_ogg_vorbis_profile (1, NULL));
263
264   fail_unless_equals_int (gst_element_set_state (ebin, GST_STATE_PAUSED),
265       GST_STATE_CHANGE_SUCCESS);
266
267   /* Check if the source pad was properly created */
268   srcpad = gst_element_get_static_pad (ebin, "src");
269   fail_unless (srcpad != NULL);
270   gst_object_unref (srcpad);
271
272   /* Check if the audio sink pad was properly created */
273   sinkpad = gst_element_get_static_pad (ebin, "audio_0");
274   fail_unless (sinkpad != NULL);
275   /* Check caps match */
276   _caps_match (sinkpad, "audio/x-raw;audio/x-vorbis");
277   gst_object_unref (sinkpad);
278
279   /* Set back to NULL */
280   fail_unless_equals_int (gst_element_set_state (ebin, GST_STATE_NULL),
281       GST_STATE_CHANGE_SUCCESS);
282
283   gst_object_unref (ebin);
284 };
285
286 GST_END_TEST;
287
288 GST_START_TEST (test_encodebin_preset)
289 {
290   GstElement *ebin;
291   GstEncodingProfile *prof;
292   guint64 max_delay = 0;
293   GstPreset *oggmuxpreset;
294
295   /* Create an encodebin with a bogus preset and check it fails switching states */
296
297   ebin = gst_element_factory_make ("encodebin", NULL);
298   oggmuxpreset = GST_PRESET (gst_element_factory_make ("oggmux", NULL));
299
300   /* We also set the name as the load_preset call will reset the element name to
301    * what is described in the preset... which might not be very smart tbh */
302   g_object_set (oggmuxpreset, "max-delay", (guint64) 12, "name",
303       "testingoggmux", NULL);
304
305   /* Give a name someone should never use outside of that test */
306   gst_preset_save_preset (oggmuxpreset, "test_encodebin_preset");
307
308   /* streamprofile that has a forced presence of 1 */
309   prof = create_ogg_vorbis_profile (1, NULL);
310
311   gst_encoding_profile_set_preset (prof, "test_encodebin_preset");
312   gst_encoding_profile_set_preset_name (prof, "oggmux");
313
314   set_profile (ebin, prof);
315
316   /* It will go to READY... */
317   fail_unless_equals_int (gst_element_set_state (ebin, GST_STATE_READY),
318       GST_STATE_CHANGE_SUCCESS);
319   /* ... and to PAUSED */
320   fail_unless (gst_element_set_state (ebin, GST_STATE_PAUSED) !=
321       GST_STATE_CHANGE_FAILURE);
322
323   gst_child_proxy_get (GST_CHILD_PROXY (ebin), "testingoggmux::max-delay",
324       &max_delay, NULL);
325   fail_unless_equals_uint64 (max_delay, 12);
326
327   gst_element_set_state (ebin, GST_STATE_NULL);
328   gst_preset_delete_preset (oggmuxpreset, "test_encodebin_preset");
329
330   gst_object_unref (ebin);
331 };
332
333 GST_END_TEST;
334
335 GST_START_TEST (test_encodebin_sink_pads_nopreset_static)
336 {
337   GstElement *ebin;
338
339   /* Create an encodebin with a bogus preset and check it fails switching states */
340
341   ebin = gst_element_factory_make ("encodebin", NULL);
342
343   /* streamprofile that has a forced presence of 1 */
344   set_profile (ebin,
345       create_ogg_vorbis_profile (1, (gchar *) "nowaythispresetexists"));
346
347   /* It will go to READY... */
348   fail_unless_equals_int (gst_element_set_state (ebin, GST_STATE_READY),
349       GST_STATE_CHANGE_SUCCESS);
350   /* ... but to not PAUSED */
351   fail_unless_equals_int (gst_element_set_state (ebin, GST_STATE_PAUSED),
352       GST_STATE_CHANGE_FAILURE);
353
354   gst_element_set_state (ebin, GST_STATE_NULL);
355
356   gst_object_unref (ebin);
357 };
358
359 GST_END_TEST;
360
361 GST_START_TEST (test_encodebin_sink_pads_dynamic)
362 {
363   GstElement *ebin;
364   GstPad *srcpad, *sinkpad;
365   GstCaps *sinkcaps;
366
367   /* Create an encodebin and check that it properly creates the sink pads
368    * for a single-stream profile with a unfixed presence */
369
370   ebin = gst_element_factory_make ("encodebin", NULL);
371
372   /* streamprofile that has non-forced presence */
373   set_profile (ebin, create_ogg_vorbis_profile (0, NULL));
374
375   /* Check if the source pad was properly created */
376   srcpad = gst_element_get_static_pad (ebin, "src");
377   fail_unless (srcpad != NULL);
378   gst_object_unref (srcpad);
379
380   /* Check if the audio sink pad can be requested */
381   sinkpad = gst_element_get_request_pad (ebin, "audio_0");
382   fail_unless (sinkpad != NULL);
383   _caps_match (sinkpad, "audio/x-raw;audio/x-vorbis");
384   gst_element_release_request_pad (ebin, sinkpad);
385   gst_object_unref (sinkpad);
386   sinkpad = NULL;
387
388   /* Check again with the 'request-pad' signal */
389   sinkcaps = gst_caps_new_empty_simple ("audio/x-raw");
390   g_signal_emit_by_name (ebin, "request-pad", sinkcaps, &sinkpad);
391   gst_caps_unref (sinkcaps);
392   fail_unless (sinkpad != NULL);
393   _caps_match (sinkpad, "audio/x-raw;audio/x-vorbis");
394   gst_element_release_request_pad (ebin, sinkpad);
395   gst_object_unref (sinkpad);
396   sinkpad = NULL;
397
398   fail_unless_equals_int (gst_element_set_state (ebin, GST_STATE_PAUSED),
399       GST_STATE_CHANGE_SUCCESS);
400
401   /* Set back to NULL */
402   fail_unless_equals_int (gst_element_set_state (ebin, GST_STATE_NULL),
403       GST_STATE_CHANGE_SUCCESS);
404
405   gst_object_unref (ebin);
406 };
407
408 GST_END_TEST;
409
410 GST_START_TEST (test_encodebin_sink_pads_multiple_static)
411 {
412   GstElement *ebin;
413   GstPad *srcpad, *sinkpadvorbis, *sinkpadtheora;
414
415   /* Create an encodebin and check that it properly creates the sink pads */
416
417   ebin = gst_element_factory_make ("encodebin", NULL);
418
419   /* First try is with a streamprofile that has a forced presence of 1 */
420   set_profile (ebin, create_ogg_theora_vorbis_profile (1, 1));
421
422   fail_unless_equals_int (gst_element_set_state (ebin, GST_STATE_PAUSED),
423       GST_STATE_CHANGE_SUCCESS);
424
425   /* Check if the source pad was properly created */
426   srcpad = gst_element_get_static_pad (ebin, "src");
427   fail_unless (srcpad != NULL);
428   gst_object_unref (srcpad);
429
430   /* Check if the audio sink pad was properly created */
431   sinkpadvorbis = gst_element_get_static_pad (ebin, "audio_0");
432   fail_unless (sinkpadvorbis != NULL);
433   _caps_match (sinkpadvorbis, "audio/x-raw;audio/x-vorbis");
434   gst_object_unref (sinkpadvorbis);
435
436   /* Check if the video sink pad was properly created */
437   sinkpadtheora = gst_element_get_static_pad (ebin, "video_1");
438   fail_unless (sinkpadtheora != NULL);
439   _caps_match (sinkpadtheora, "video/x-raw;video/x-theora");
440   gst_object_unref (sinkpadtheora);
441
442   /* Set back to NULL */
443   fail_unless_equals_int (gst_element_set_state (ebin, GST_STATE_NULL),
444       GST_STATE_CHANGE_SUCCESS);
445
446   gst_object_unref (ebin);
447 };
448
449 GST_END_TEST;
450
451 GST_START_TEST (test_encodebin_sink_pads_multiple_dynamic)
452 {
453   GstElement *ebin;
454   GstPad *srcpad, *sinkpadvorbis, *sinkpadtheora;
455
456   /* Create an encodebin and check that it properly creates the sink pads
457    * for a multiple-stream with unfixed presence */
458
459   ebin = gst_element_factory_make ("encodebin", NULL);
460
461   /* multi-stream profile that has non-forced presence */
462   set_profile (ebin, create_ogg_theora_vorbis_profile (0, 0));
463
464   /* Check if the source pad was properly created */
465   srcpad = gst_element_get_static_pad (ebin, "src");
466   fail_unless (srcpad != NULL);
467   gst_object_unref (srcpad);
468
469   /* Check if the audio sink pad was properly created */
470   sinkpadvorbis = gst_element_get_request_pad (ebin, "audio_0");
471   _caps_match (sinkpadvorbis, "audio/x-raw;audio/x-vorbis");
472   fail_unless (sinkpadvorbis != NULL);
473
474   /* Check if the video sink pad was properly created */
475   sinkpadtheora = gst_element_get_request_pad (ebin, "video_1");
476   _caps_match (sinkpadtheora, "video/x-raw;video/x-theora");
477   fail_unless (sinkpadtheora != NULL);
478
479   fail_unless_equals_int (gst_element_set_state (ebin, GST_STATE_PAUSED),
480       GST_STATE_CHANGE_SUCCESS);
481
482   /* Set back to NULL */
483   fail_unless_equals_int (gst_element_set_state (ebin, GST_STATE_NULL),
484       GST_STATE_CHANGE_SUCCESS);
485
486   gst_element_release_request_pad (GST_ELEMENT (ebin), sinkpadvorbis);
487   gst_object_unref (sinkpadvorbis);
488   gst_element_release_request_pad (GST_ELEMENT (ebin), sinkpadtheora);
489   gst_object_unref (sinkpadtheora);
490
491   gst_object_unref (ebin);
492 };
493
494 GST_END_TEST;
495
496 GST_START_TEST (test_encodebin_sink_pads_dynamic_encoder)
497 {
498   GstElement *ebin;
499   GstPad *srcpad, *sinkpad = NULL;
500   GstCaps *vorbiscaps;
501
502   /* Create an encodebin and check that it properly creates the sink pads
503    * for a single-stream profile with a unfixed presence */
504
505   ebin = gst_element_factory_make ("encodebin", NULL);
506
507   /* streamprofile that has non-forced presence */
508   set_profile (ebin, create_ogg_vorbis_profile (0, NULL));
509
510   /* Check if the source pad was properly created */
511   srcpad = gst_element_get_static_pad (ebin, "src");
512   fail_unless (srcpad != NULL);
513   gst_object_unref (srcpad);
514
515   /* Check if the audio sink pad was properly created */
516   vorbiscaps = gst_caps_from_string ("audio/x-vorbis,channels=2,rate=44100");
517   g_signal_emit_by_name (ebin, "request-pad", vorbiscaps, &sinkpad);
518   gst_caps_unref (vorbiscaps);
519   fail_unless (sinkpad != NULL);
520   _caps_match (sinkpad, "audio/x-raw;audio/x-vorbis");
521   gst_element_release_request_pad (ebin, sinkpad);
522   gst_object_unref (sinkpad);
523
524   fail_unless_equals_int (gst_element_set_state (ebin, GST_STATE_PAUSED),
525       GST_STATE_CHANGE_SUCCESS);
526
527   /* Set back to NULL */
528   fail_unless_equals_int (gst_element_set_state (ebin, GST_STATE_NULL),
529       GST_STATE_CHANGE_SUCCESS);
530
531   gst_object_unref (ebin);
532 };
533
534 GST_END_TEST;
535
536 GST_START_TEST (test_encodebin_render_audio_static)
537 {
538   GstElement *ebin, *pipeline, *audiotestsrc, *fakesink;
539   GstBus *bus;
540   gboolean done = FALSE;
541
542   /* Create an encodebin and render 5s of vorbis/ogg */
543
544   pipeline = gst_pipeline_new ("encodebin-pipeline");
545   bus = gst_pipeline_get_bus ((GstPipeline *) pipeline);
546   audiotestsrc = gst_element_factory_make ("audiotestsrc", NULL);
547   g_object_set (audiotestsrc, "num-buffers", 10, NULL);
548   fakesink = gst_element_factory_make ("fakesink", NULL);
549
550   ebin = gst_element_factory_make ("encodebin", NULL);
551   set_profile (ebin, create_ogg_vorbis_profile (1, NULL));
552
553   gst_bin_add_many ((GstBin *) pipeline, audiotestsrc, ebin, fakesink, NULL);
554
555   fail_unless (gst_element_link_many (audiotestsrc, ebin, fakesink, NULL));
556
557   fail_unless_equals_int (gst_element_set_state (pipeline, GST_STATE_PLAYING),
558       GST_STATE_CHANGE_ASYNC);
559
560   while (!done) {
561     GstMessage *msg;
562
563     /* poll the bus until we get EOS without any errors */
564     msg = gst_bus_timed_pop (bus, GST_SECOND / 10);
565     if (msg) {
566       switch (GST_MESSAGE_TYPE (msg)) {
567         case GST_MESSAGE_ERROR:
568           fail ("GST_MESSAGE_ERROR");
569           break;
570         case GST_MESSAGE_EOS:
571           done = TRUE;
572           break;
573         default:
574           break;
575       }
576       gst_message_unref (msg);
577     }
578   }
579
580   /* Set back to NULL */
581   fail_unless_equals_int (gst_element_set_state (pipeline, GST_STATE_NULL),
582       GST_STATE_CHANGE_SUCCESS);
583
584   gst_object_unref (bus);
585
586   gst_object_unref (pipeline);
587 }
588
589 GST_END_TEST;
590
591 GST_START_TEST (test_encodebin_render_audio_only_static)
592 {
593   GstElement *ebin, *pipeline, *audiotestsrc, *fakesink;
594   GstBus *bus;
595   gboolean done = FALSE;
596   GstPad *sinkpad;
597   GstCaps *sinkcaps;
598
599   /* Create an encodebin and render 5s of vorbis only */
600   pipeline = gst_pipeline_new ("encodebin-pipeline");
601   bus = gst_pipeline_get_bus ((GstPipeline *) pipeline);
602   audiotestsrc = gst_element_factory_make ("audiotestsrc", NULL);
603   g_object_set (audiotestsrc, "num-buffers", 10, NULL);
604   fakesink = gst_element_factory_make ("fakesink", NULL);
605
606   ebin = gst_element_factory_make ("encodebin", NULL);
607   set_profile (ebin, create_vorbis_only_profile ());
608
609   gst_bin_add_many (GST_BIN (pipeline), audiotestsrc, ebin, fakesink, NULL);
610
611   GST_DEBUG ("linking encodebin");
612   fail_unless (gst_element_link_many (audiotestsrc, ebin, fakesink, NULL));
613
614   /* Requesting a new pad should fail */
615   ASSERT_CRITICAL (gst_element_get_request_pad (ebin, "audio_0"));
616
617   sinkcaps = gst_caps_new_empty_simple ("audio/x-raw");
618   g_signal_emit_by_name (ebin, "request-pad", sinkcaps, &sinkpad);
619   gst_caps_unref (sinkcaps);
620   fail_if (sinkpad != NULL);
621
622   fail_unless_equals_int (gst_element_set_state (pipeline, GST_STATE_PLAYING),
623       GST_STATE_CHANGE_ASYNC);
624
625   while (!done) {
626     GstMessage *msg;
627
628     /* poll the bus until we get EOS without any errors */
629     msg = gst_bus_timed_pop (bus, GST_SECOND / 10);
630     if (msg) {
631       switch (GST_MESSAGE_TYPE (msg)) {
632         case GST_MESSAGE_ERROR:
633           fail ("GST_MESSAGE_ERROR");
634           break;
635         case GST_MESSAGE_EOS:
636           done = TRUE;
637           break;
638         default:
639           break;
640       }
641       gst_message_unref (msg);
642     }
643   }
644
645   /* Set back to NULL */
646   fail_unless_equals_int (gst_element_set_state (pipeline, GST_STATE_NULL),
647       GST_STATE_CHANGE_SUCCESS);
648
649   gst_object_unref (bus);
650
651   gst_object_unref (pipeline);
652 }
653
654 GST_END_TEST;
655
656 GST_START_TEST (test_encodebin_render_audio_dynamic)
657 {
658   GstElement *ebin, *pipeline, *audiotestsrc, *fakesink;
659   GstBus *bus;
660   GstPad *sinkpad, *srcpad;
661   gboolean done = FALSE;
662
663   /* Create an encodebin and render 5s of vorbis/ogg */
664
665   pipeline = gst_pipeline_new ("encodebin-pipeline");
666   bus = gst_pipeline_get_bus ((GstPipeline *) pipeline);
667   audiotestsrc = gst_element_factory_make ("audiotestsrc", NULL);
668   g_object_set (audiotestsrc, "num-buffers", 10, NULL);
669   fakesink = gst_element_factory_make ("fakesink", NULL);
670
671   ebin = gst_element_factory_make ("encodebin", NULL);
672   set_profile (ebin, create_ogg_vorbis_profile (0, NULL));
673
674   gst_bin_add_many ((GstBin *) pipeline, audiotestsrc, ebin, fakesink, NULL);
675
676   srcpad = gst_element_get_static_pad (audiotestsrc, "src");
677   fail_unless (srcpad != NULL);
678
679   sinkpad = gst_element_get_request_pad (ebin, "audio_0");
680   fail_unless (sinkpad != NULL);
681   _caps_match (sinkpad, "audio/x-raw;audio/x-vorbis");
682
683   fail_unless_equals_int (gst_pad_link (srcpad, sinkpad), GST_PAD_LINK_OK);
684
685   gst_object_unref (srcpad);
686
687   fail_unless (gst_element_link (ebin, fakesink));
688
689   fail_unless_equals_int (gst_element_set_state (pipeline, GST_STATE_PLAYING),
690       GST_STATE_CHANGE_ASYNC);
691
692   while (!done) {
693     GstMessage *msg;
694
695     /* poll the bus until we get EOS without any errors */
696     msg = gst_bus_timed_pop (bus, GST_SECOND / 10);
697     if (msg) {
698       switch (GST_MESSAGE_TYPE (msg)) {
699         case GST_MESSAGE_ERROR:
700           fail ("GST_MESSAGE_ERROR");
701           break;
702         case GST_MESSAGE_EOS:
703           done = TRUE;
704           break;
705         default:
706           break;
707       }
708       gst_message_unref (msg);
709     }
710   }
711
712   /* Set back to NULL */
713   fail_unless_equals_int (gst_element_set_state (pipeline, GST_STATE_NULL),
714       GST_STATE_CHANGE_SUCCESS);
715
716   gst_element_release_request_pad (GST_ELEMENT (ebin), sinkpad);
717   gst_object_unref (sinkpad);
718
719   gst_object_unref (bus);
720
721   gst_object_unref (pipeline);
722 }
723
724 GST_END_TEST;
725
726 GST_START_TEST (test_encodebin_render_audio_video_static)
727 {
728   GstElement *ebin, *pipeline, *audiotestsrc, *videotestsrc, *fakesink;
729   GstBus *bus;
730   gboolean done = FALSE;
731
732   /* Create an encodebin and render 5s of vorbis/ogg */
733
734   pipeline = gst_pipeline_new ("encodebin-pipeline");
735   bus = gst_pipeline_get_bus ((GstPipeline *) pipeline);
736   audiotestsrc = gst_element_factory_make ("audiotestsrc", NULL);
737   g_object_set (audiotestsrc, "num-buffers", 10, NULL);
738   videotestsrc = gst_element_factory_make ("videotestsrc", NULL);
739   g_object_set (videotestsrc, "num-buffers", 5, NULL);
740   fakesink = gst_element_factory_make ("fakesink", NULL);
741
742   ebin = gst_element_factory_make ("encodebin", NULL);
743   set_profile (ebin, create_ogg_theora_vorbis_profile (1, 1));
744
745   gst_bin_add_many ((GstBin *) pipeline, audiotestsrc, videotestsrc, ebin,
746       fakesink, NULL);
747
748   fail_unless (gst_element_link (videotestsrc, ebin));
749   fail_unless (gst_element_link_many (audiotestsrc, ebin, fakesink, NULL));
750
751   fail_unless_equals_int (gst_element_set_state (pipeline, GST_STATE_PLAYING),
752       GST_STATE_CHANGE_ASYNC);
753
754   while (!done) {
755     GstMessage *msg;
756
757     /* poll the bus until we get EOS without any errors */
758     msg = gst_bus_timed_pop (bus, GST_SECOND / 10);
759     if (msg) {
760       switch (GST_MESSAGE_TYPE (msg)) {
761         case GST_MESSAGE_ERROR:
762           fail ("GST_MESSAGE_ERROR");
763           break;
764         case GST_MESSAGE_EOS:
765           done = TRUE;
766           break;
767         default:
768           break;
769       }
770       gst_message_unref (msg);
771     }
772   }
773
774   /* Set back to NULL */
775   fail_unless_equals_int (gst_element_set_state (pipeline, GST_STATE_NULL),
776       GST_STATE_CHANGE_SUCCESS);
777
778   gst_object_unref (bus);
779
780   gst_object_unref (pipeline);
781 }
782
783 GST_END_TEST;
784
785 GST_START_TEST (test_encodebin_render_audio_video_dynamic)
786 {
787   GstElement *ebin, *pipeline, *audiotestsrc, *videotestsrc, *fakesink;
788   GstBus *bus;
789   gboolean done = FALSE;
790   GstPad *sinkpad1, *sinkpad2, *srcpad;
791
792   /* Create an encodebin and render 5s of vorbis/ogg */
793
794   pipeline = gst_pipeline_new ("encodebin-pipeline");
795   bus = gst_pipeline_get_bus ((GstPipeline *) pipeline);
796   audiotestsrc = gst_element_factory_make ("audiotestsrc", NULL);
797   g_object_set (audiotestsrc, "num-buffers", 10, NULL);
798   videotestsrc = gst_element_factory_make ("videotestsrc", NULL);
799   g_object_set (videotestsrc, "num-buffers", 5, NULL);
800   fakesink = gst_element_factory_make ("fakesink", NULL);
801
802   ebin = gst_element_factory_make ("encodebin", NULL);
803   set_profile (ebin, create_ogg_theora_vorbis_profile (0, 0));
804
805   gst_bin_add_many ((GstBin *) pipeline, audiotestsrc, videotestsrc, ebin,
806       fakesink, NULL);
807
808   fail_unless (gst_element_link (ebin, fakesink));
809
810   srcpad = gst_element_get_static_pad (audiotestsrc, "src");
811   sinkpad1 = gst_element_get_request_pad (ebin, "audio_0");
812   fail_unless (srcpad != NULL);
813   fail_unless (sinkpad1 != NULL);
814   _caps_match (sinkpad1, "audio/x-raw;audio/x-vorbis");
815   fail_unless_equals_int (gst_pad_link (srcpad, sinkpad1), GST_PAD_LINK_OK);
816   gst_object_unref (srcpad);
817
818   srcpad = gst_element_get_static_pad (videotestsrc, "src");
819   sinkpad2 = gst_element_get_request_pad (ebin, "video_1");
820   _caps_match (sinkpad2, "video/x-raw;video/x-theora");
821   fail_unless_equals_int (gst_pad_link (srcpad, sinkpad2), GST_PAD_LINK_OK);
822   gst_object_unref (srcpad);
823
824   fail_unless_equals_int (gst_element_set_state (pipeline, GST_STATE_PLAYING),
825       GST_STATE_CHANGE_ASYNC);
826
827   while (!done) {
828     GstMessage *msg;
829
830     /* poll the bus until we get EOS without any errors */
831     msg = gst_bus_timed_pop (bus, GST_SECOND / 10);
832     if (msg) {
833       switch (GST_MESSAGE_TYPE (msg)) {
834         case GST_MESSAGE_ERROR:
835           fail ("GST_MESSAGE_ERROR");
836           break;
837         case GST_MESSAGE_EOS:
838           done = TRUE;
839           break;
840         default:
841           break;
842       }
843       gst_message_unref (msg);
844     }
845   }
846
847   /* Set back to NULL */
848   fail_unless_equals_int (gst_element_set_state (pipeline, GST_STATE_NULL),
849       GST_STATE_CHANGE_SUCCESS);
850
851   gst_element_release_request_pad (GST_ELEMENT (ebin), sinkpad1);
852   gst_object_unref (sinkpad1);
853   gst_element_release_request_pad (GST_ELEMENT (ebin), sinkpad2);
854   gst_object_unref (sinkpad2);
855
856   gst_object_unref (bus);
857
858   gst_object_unref (pipeline);
859 }
860
861 GST_END_TEST;
862
863 GST_START_TEST (test_encodebin_impossible_element_combination)
864 {
865   GstElement *ebin;
866   GstEncodingProfile *prof;
867   GstCaps *ogg, *x264;
868
869   ebin = gst_element_factory_make ("x264enc", NULL);
870   if (ebin == NULL) {
871     GST_DEBUG ("No available h264 encoder, skipping test");
872     return;
873   }
874   gst_object_unref (ebin);
875
876   /* Make sure that impossible combinations of encoders and muxer
877    * properly fail. In this case we try putting h264 in ogg.
878    *
879    * To properly test we abort early, we use a presence of zero for the
880    * h264 stream profile. */
881
882   ebin = gst_element_factory_make ("encodebin", NULL);
883
884   ogg = gst_caps_new_empty_simple ("application/ogg");
885   prof = (GstEncodingProfile *) gst_encoding_container_profile_new ((gchar *)
886       "myprofile", NULL, ogg, NULL);
887   gst_caps_unref (ogg);
888
889   x264 = gst_caps_new_empty_simple ("video/x-h264");
890   fail_unless (gst_encoding_container_profile_add_profile
891       (GST_ENCODING_CONTAINER_PROFILE (prof),
892           (GstEncodingProfile *) gst_encoding_video_profile_new (x264, NULL,
893               NULL, 0)));
894   gst_caps_unref (x264);
895
896   g_object_set (ebin, "profile", prof, NULL);
897   gst_encoding_profile_unref (prof);
898
899   /* It will go to READY... */
900   fail_unless_equals_int (gst_element_set_state (ebin, GST_STATE_READY),
901       GST_STATE_CHANGE_SUCCESS);
902   /* ... but to not PAUSED */
903   fail_unless_equals_int (gst_element_set_state (ebin, GST_STATE_PAUSED),
904       GST_STATE_CHANGE_FAILURE);
905
906   gst_element_set_state (ebin, GST_STATE_NULL);
907
908   gst_object_unref (ebin);
909 };
910
911 GST_END_TEST;
912
913 static void
914 _test_encodebin_reuse (GstEncodingProfile * prof1, GstEncodingProfile * prof2)
915 {
916   GstElement *ebin;
917
918   ebin = gst_element_factory_make ("encodebin", NULL);
919
920   /* Set a profile on encodebin... */
921   if (prof1)
922     g_object_set (ebin, "profile", prof1, NULL);
923
924   /* Make sure we can go to PAUSED */
925   fail_unless_equals_int (gst_element_set_state (ebin, GST_STATE_PAUSED),
926       GST_STATE_CHANGE_SUCCESS);
927
928   /* Set back to NULL */
929   fail_unless_equals_int (gst_element_set_state (ebin, GST_STATE_NULL),
930       GST_STATE_CHANGE_SUCCESS);
931
932   if (prof2)
933     g_object_set (ebin, "profile", prof2, NULL);
934
935   /* Make sure we can go to PLAYING */
936   fail_unless_equals_int (gst_element_set_state (ebin, GST_STATE_PAUSED),
937       GST_STATE_CHANGE_SUCCESS);
938
939   /* Set back to NULL */
940   fail_unless_equals_int (gst_element_set_state (ebin, GST_STATE_NULL),
941       GST_STATE_CHANGE_SUCCESS);
942
943   gst_object_unref (ebin);
944 }
945
946 GST_START_TEST (test_encodebin_reuse)
947 {
948   GstEncodingProfile *prof1;
949   GstEncodingProfile *prof2;
950   GstEncodingProfile *prof3;
951   GstCaps *caps;
952
953   caps = gst_caps_new_empty_simple ("application/ogg");
954   prof1 = (GstEncodingProfile *) gst_encoding_container_profile_new ((gchar *)
955       "myprofile", NULL, caps, NULL);
956   gst_caps_unref (caps);
957
958   prof2 = create_ogg_theora_vorbis_profile (1, 1);
959   prof3 = create_vorbis_only_profile ();
960
961   _test_encodebin_reuse (prof1, NULL);
962   _test_encodebin_reuse (prof1, prof1);
963
964   _test_encodebin_reuse (prof1, prof2);
965
966   _test_encodebin_reuse (prof2, prof3);
967
968   gst_encoding_profile_unref (prof1);
969   gst_encoding_profile_unref (prof2);
970   gst_encoding_profile_unref (prof3);
971 };
972
973 GST_END_TEST;
974
975 GST_START_TEST (test_encodebin_named_requests)
976 {
977   GstElement *ebin;
978   GstEncodingContainerProfile *cprof;
979   GstCaps *ogg, *vorbis, *theora;
980   GstEncodingProfile *vorbisprof, *theoraprof;
981   GstPad *srcpad, *sinkpadvorbis, *sinkpadtheora;
982
983   /* Create a profile with vorbis/theora named profile */
984   ogg = gst_caps_new_empty_simple ("application/ogg");
985   cprof =
986       gst_encoding_container_profile_new ((gchar *) "myprofile", NULL, ogg,
987       NULL);
988   gst_caps_unref (ogg);
989
990   vorbis = gst_caps_new_empty_simple ("audio/x-vorbis");
991   vorbisprof =
992       (GstEncodingProfile *) gst_encoding_audio_profile_new (vorbis, NULL, NULL,
993       0);
994   gst_encoding_profile_set_name (vorbisprof, "vorbisprofile");
995   fail_unless (gst_encoding_container_profile_add_profile (cprof, vorbisprof));
996   gst_caps_unref (vorbis);
997
998   theora = gst_caps_new_empty_simple ("video/x-theora");
999   theoraprof =
1000       (GstEncodingProfile *) gst_encoding_video_profile_new (theora, NULL, NULL,
1001       0);
1002   gst_encoding_profile_set_name (theoraprof, "theoraprofile");
1003   fail_unless (gst_encoding_container_profile_add_profile (cprof, theoraprof));
1004   gst_caps_unref (theora);
1005
1006   ebin = gst_element_factory_make ("encodebin", NULL);
1007
1008   /* First try is with a streamprofile that has a forced presence of 1 */
1009   g_object_set (ebin, "profile", cprof, NULL);
1010
1011   gst_encoding_profile_unref (cprof);
1012
1013   /* Check if the source pad was properly created */
1014   srcpad = gst_element_get_static_pad (ebin, "src");
1015   fail_unless (srcpad != NULL);
1016   gst_object_unref (srcpad);
1017
1018   /* Request a vorbis profile pad */
1019   g_signal_emit_by_name (ebin, "request-profile-pad", "vorbisprofile",
1020       &sinkpadvorbis);
1021   fail_unless (sinkpadvorbis != NULL);
1022   _caps_match (sinkpadvorbis, "audio/x-raw;audio/x-vorbis");
1023   gst_object_unref (sinkpadvorbis);
1024
1025   /* Request a theora profile pad */
1026   g_signal_emit_by_name (ebin, "request-profile-pad", "theoraprofile",
1027       &sinkpadtheora);
1028   fail_unless (sinkpadtheora != NULL);
1029   _caps_match (sinkpadtheora, "video/x-raw;video/x-theora");
1030   gst_object_unref (sinkpadtheora);
1031
1032   fail_unless_equals_int (gst_element_set_state (ebin, GST_STATE_PAUSED),
1033       GST_STATE_CHANGE_SUCCESS);
1034
1035   /* Set back to NULL */
1036   fail_unless_equals_int (gst_element_set_state (ebin, GST_STATE_NULL),
1037       GST_STATE_CHANGE_SUCCESS);
1038
1039   gst_object_unref (ebin);
1040
1041 }
1042
1043 GST_END_TEST;
1044
1045 GST_START_TEST (test_encodebin_missing_plugin_messages)
1046 {
1047   GstElement *pipeline = gst_pipeline_new ("test");
1048   GstBus *bus = gst_pipeline_get_bus ((GstPipeline *) pipeline);
1049   GstElement *ebin = gst_element_factory_make ("encodebin", NULL);
1050   GstMessage *message;
1051
1052   /* first add to bin, then set profile */
1053   gst_bin_add ((GstBin *) pipeline, ebin);
1054   set_profile (ebin, create_unsupported_profile ());
1055
1056   gst_element_set_state (pipeline, GST_STATE_READY);
1057
1058   message = gst_bus_pop_filtered (bus, GST_MESSAGE_ELEMENT);
1059   fail_if (message == NULL);
1060   fail_if (!gst_is_missing_plugin_message (message));
1061   gst_message_unref (message);
1062
1063   gst_element_set_state (pipeline, GST_STATE_NULL);
1064   gst_object_unref (bus);
1065   gst_object_unref (pipeline);
1066 }
1067
1068 GST_END_TEST;
1069
1070 static Suite *
1071 encodebin_suite (void)
1072 {
1073   Suite *s = suite_create ("encodebin element");
1074   TCase *tc_chain = tcase_create ("general");
1075
1076   suite_add_tcase (s, tc_chain);
1077   tcase_add_test (tc_chain, test_encodebin_set_profile);
1078   tcase_add_test (tc_chain, test_encodebin_can_go_to_ready_without_profile);
1079   tcase_add_test (tc_chain, test_encodebin_can_go_to_paused_with_profile);
1080   tcase_add_test (tc_chain, test_encodebin_sink_pads_static);
1081   tcase_add_test (tc_chain, test_encodebin_sink_pads_nopreset_static);
1082   tcase_add_test (tc_chain, test_encodebin_preset);
1083   tcase_add_test (tc_chain, test_encodebin_sink_pads_dynamic);
1084   tcase_add_test (tc_chain, test_encodebin_sink_pads_multiple_static);
1085   tcase_add_test (tc_chain, test_encodebin_sink_pads_multiple_dynamic);
1086   tcase_add_test (tc_chain, test_encodebin_sink_pads_dynamic_encoder);
1087   tcase_add_test (tc_chain, test_encodebin_render_audio_static);
1088   tcase_add_test (tc_chain, test_encodebin_render_audio_only_static);
1089   tcase_add_test (tc_chain, test_encodebin_render_audio_dynamic);
1090   tcase_add_test (tc_chain, test_encodebin_render_audio_video_static);
1091   tcase_add_test (tc_chain, test_encodebin_render_audio_video_dynamic);
1092   tcase_add_test (tc_chain, test_encodebin_impossible_element_combination);
1093   tcase_add_test (tc_chain, test_encodebin_reuse);
1094   tcase_add_test (tc_chain, test_encodebin_named_requests);
1095   tcase_add_test (tc_chain, test_encodebin_missing_plugin_messages);
1096
1097   return s;
1098 }
1099
1100 GST_CHECK_MAIN (encodebin);