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 *
create_ogg_profile()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 *
create_ogg_vorbis_profile(guint presence,gchar * preset)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 *
create_ogg_theora_vorbis_profile(guint theorapresence,guint vorbispresence)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 *
create_vorbis_only_profile(void)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 GstCaps *
create_unsupported_caps(void)108 create_unsupported_caps (void)
109 {
110 return gst_caps_new_empty_simple ("audio/x-bogus");
111 }
112
113 static GstEncodingProfile *
create_unsupported_profile(void)114 create_unsupported_profile (void)
115 {
116 GstEncodingProfile *prof;
117 GstCaps *caps;
118
119 caps = create_unsupported_caps ();
120 prof =
121 (GstEncodingProfile *) gst_encoding_audio_profile_new (caps, NULL, NULL,
122 0);
123 gst_caps_unref (caps);
124
125 return prof;
126 }
127
128 static void
_caps_match(GstPad * sinkpad,const gchar * capsname)129 _caps_match (GstPad * sinkpad, const gchar * capsname)
130 {
131 GstCaps *caps, *sinkcaps;
132 gchar *name;
133
134 caps = gst_caps_from_string (capsname);
135 sinkcaps = gst_pad_query_caps (sinkpad, NULL);
136 fail_unless (sinkcaps != NULL);
137 name = gst_caps_to_string (sinkcaps);
138 fail_unless (gst_caps_is_subset (sinkcaps, caps),
139 "caps ('%s') are not a subset of ('%s')", name, capsname);
140 g_free (name);
141 gst_caps_unref (sinkcaps);
142 gst_caps_unref (caps);
143 }
144
145 static void
set_profile(GstElement * ebin,GstEncodingProfile * prof)146 set_profile (GstElement * ebin, GstEncodingProfile * prof)
147 {
148 g_object_set (ebin, "profile", prof, NULL);
149 gst_encoding_profile_unref (prof);
150 }
151
152 /* Tests */
153
GST_START_TEST(test_encodebin_set_profile)154 GST_START_TEST (test_encodebin_set_profile)
155 {
156 GstElement *ebin;
157 GstEncodingProfile *prof, *prof2;
158
159 /* Create an encodebin and check that it correctly changes states
160 * according to whether a profile is set or not */
161
162 ebin = gst_element_factory_make ("encodebin", NULL);
163
164 /* Set a profile on encodebin... */
165 prof = create_ogg_profile ();
166 g_object_set (ebin, "profile", prof, NULL);
167
168 /* ... and check the profile has been properly set */
169 g_object_get (ebin, "profile", &prof2, NULL);
170
171 fail_unless (gst_encoding_profile_is_equal (prof, prof2));
172
173 gst_encoding_profile_unref (prof);
174 gst_encoding_profile_unref (prof2);
175
176 gst_object_unref (ebin);
177 };
178
179 GST_END_TEST;
180
181
GST_START_TEST(test_encodebin_can_go_to_ready_without_profile)182 GST_START_TEST (test_encodebin_can_go_to_ready_without_profile)
183 {
184 GstElement *ebin;
185 GstPad *srcpad;
186 GstPad *target;
187
188 /* Create an encodebin and check that it correctly changes states
189 * according to whether a profile is set or not */
190
191 ebin = gst_element_factory_make ("encodebin", NULL);
192
193 /* Check if the source pad was properly created */
194 srcpad = gst_element_get_static_pad (ebin, "src");
195 fail_unless (srcpad != NULL);
196
197 /* At this point, the ghostpad has *NO* target */
198 target = gst_ghost_pad_get_target (GST_GHOST_PAD (srcpad));
199 fail_unless (target == NULL);
200 gst_object_unref (srcpad);
201
202 /* No profile,
203 * switching to READY should succeed,
204 * but switching to PAUSED should fail
205 */
206 fail_unless_equals_int (gst_element_set_state (ebin, GST_STATE_READY),
207 GST_STATE_CHANGE_SUCCESS);
208 fail_unless_equals_int (gst_element_set_state (ebin, GST_STATE_PAUSED),
209 GST_STATE_CHANGE_FAILURE);
210
211 /* Set back to NULL */
212 fail_unless_equals_int (gst_element_set_state (ebin, GST_STATE_NULL),
213 GST_STATE_CHANGE_SUCCESS);
214
215 gst_object_unref (ebin);
216 };
217
218 GST_END_TEST;
219
GST_START_TEST(test_encodebin_can_go_to_paused_with_profile)220 GST_START_TEST (test_encodebin_can_go_to_paused_with_profile)
221 {
222 GstElement *ebin;
223 GstPad *srcpad;
224 GstPad *target;
225
226 /* Create an encodebin and check that it correctly changes states
227 * according to whether a profile is set or not */
228
229 ebin = gst_element_factory_make ("encodebin", NULL);
230
231 /* Set a profile on encodebin... */
232 set_profile (ebin, create_ogg_profile ());
233
234 /* Make sure we can go to PAUSED */
235 fail_unless_equals_int (gst_element_set_state (ebin, GST_STATE_PAUSED),
236 GST_STATE_CHANGE_SUCCESS);
237
238 /* At this point, the source pad *HAS* a target */
239 srcpad = gst_element_get_static_pad (ebin, "src");
240 fail_unless (srcpad != NULL);
241 target = gst_ghost_pad_get_target (GST_GHOST_PAD (srcpad));
242 fail_unless (target != NULL);
243 gst_object_unref (target);
244 gst_object_unref (srcpad);
245
246
247 /* Set back to NULL */
248 fail_unless_equals_int (gst_element_set_state (ebin, GST_STATE_NULL),
249 GST_STATE_CHANGE_SUCCESS);
250
251 gst_object_unref (ebin);
252 };
253
254 GST_END_TEST;
255
256
GST_START_TEST(test_encodebin_sink_pads_static)257 GST_START_TEST (test_encodebin_sink_pads_static)
258 {
259 GstElement *ebin;
260 GstPad *srcpad, *sinkpad;
261
262 /* Create an encodebin and check that it properly creates the sink pads
263 * for a single-stream profile with fixed presence */
264
265 ebin = gst_element_factory_make ("encodebin", NULL);
266
267 /* streamprofile that has a forced presence of 1 */
268 set_profile (ebin, create_ogg_vorbis_profile (1, NULL));
269
270 fail_unless_equals_int (gst_element_set_state (ebin, GST_STATE_PAUSED),
271 GST_STATE_CHANGE_SUCCESS);
272
273 /* Check if the source pad was properly created */
274 srcpad = gst_element_get_static_pad (ebin, "src");
275 fail_unless (srcpad != NULL);
276 gst_object_unref (srcpad);
277
278 /* Check if the audio sink pad was properly created */
279 sinkpad = gst_element_get_static_pad (ebin, "audio_0");
280 fail_unless (sinkpad != NULL);
281 /* Check caps match */
282 _caps_match (sinkpad, "audio/x-raw;audio/x-vorbis");
283 gst_object_unref (sinkpad);
284
285 /* Set back to NULL */
286 fail_unless_equals_int (gst_element_set_state (ebin, GST_STATE_NULL),
287 GST_STATE_CHANGE_SUCCESS);
288
289 gst_object_unref (ebin);
290 };
291
292 GST_END_TEST;
293
GST_START_TEST(test_encodebin_preset)294 GST_START_TEST (test_encodebin_preset)
295 {
296 GstElement *ebin;
297 GstEncodingProfile *prof;
298 guint64 max_delay = 0;
299 GstPreset *oggmuxpreset;
300
301 /* Create an encodebin with a bogus preset and check it fails switching states */
302
303 ebin = gst_element_factory_make ("encodebin", NULL);
304 oggmuxpreset = GST_PRESET (gst_element_factory_make ("oggmux", NULL));
305
306 /* We also set the name as the load_preset call will reset the element name to
307 * what is described in the preset... which might not be very smart tbh */
308 g_object_set (oggmuxpreset, "max-delay", (guint64) 12, "name",
309 "testingoggmux", NULL);
310
311 /* Give a name someone should never use outside of that test */
312 gst_preset_save_preset (oggmuxpreset, "test_encodebin_preset");
313
314 /* streamprofile that has a forced presence of 1 */
315 prof = create_ogg_vorbis_profile (1, NULL);
316
317 gst_encoding_profile_set_preset (prof, "test_encodebin_preset");
318 gst_encoding_profile_set_preset_name (prof, "oggmux");
319
320 set_profile (ebin, prof);
321
322 /* It will go to READY... */
323 fail_unless_equals_int (gst_element_set_state (ebin, GST_STATE_READY),
324 GST_STATE_CHANGE_SUCCESS);
325 /* ... and to PAUSED */
326 fail_unless (gst_element_set_state (ebin, GST_STATE_PAUSED) !=
327 GST_STATE_CHANGE_FAILURE);
328
329 gst_child_proxy_get (GST_CHILD_PROXY (ebin), "testingoggmux::max-delay",
330 &max_delay, NULL);
331 fail_unless_equals_uint64 (max_delay, 12);
332
333 gst_element_set_state (ebin, GST_STATE_NULL);
334 gst_preset_delete_preset (oggmuxpreset, "test_encodebin_preset");
335
336 gst_object_unref (oggmuxpreset);
337 gst_object_unref (ebin);
338 };
339
340 GST_END_TEST;
341
GST_START_TEST(test_encodebin_sink_pads_nopreset_static)342 GST_START_TEST (test_encodebin_sink_pads_nopreset_static)
343 {
344 GstElement *ebin;
345
346 /* Create an encodebin with a bogus preset and check it fails switching states */
347
348 ebin = gst_element_factory_make ("encodebin", NULL);
349
350 /* streamprofile that has a forced presence of 1 */
351 set_profile (ebin,
352 create_ogg_vorbis_profile (1, (gchar *) "nowaythispresetexists"));
353
354 /* It will go to READY... */
355 fail_unless_equals_int (gst_element_set_state (ebin, GST_STATE_READY),
356 GST_STATE_CHANGE_SUCCESS);
357 /* ... but to not PAUSED */
358 fail_unless_equals_int (gst_element_set_state (ebin, GST_STATE_PAUSED),
359 GST_STATE_CHANGE_FAILURE);
360
361 gst_element_set_state (ebin, GST_STATE_NULL);
362
363 gst_object_unref (ebin);
364 };
365
366 GST_END_TEST;
367
GST_START_TEST(test_encodebin_sink_pads_dynamic)368 GST_START_TEST (test_encodebin_sink_pads_dynamic)
369 {
370 GstElement *ebin;
371 GstPad *srcpad, *sinkpad;
372 GstCaps *sinkcaps;
373
374 /* Create an encodebin and check that it properly creates the sink pads
375 * for a single-stream profile with a unfixed presence */
376
377 ebin = gst_element_factory_make ("encodebin", NULL);
378
379 /* streamprofile that has non-forced presence */
380 set_profile (ebin, create_ogg_vorbis_profile (0, NULL));
381
382 /* Check if the source pad was properly created */
383 srcpad = gst_element_get_static_pad (ebin, "src");
384 fail_unless (srcpad != NULL);
385 gst_object_unref (srcpad);
386
387 /* Check if the audio sink pad can be requested */
388 sinkpad = gst_element_request_pad_simple (ebin, "audio_0");
389 fail_unless (sinkpad != NULL);
390 _caps_match (sinkpad, "audio/x-raw;audio/x-vorbis");
391 gst_element_release_request_pad (ebin, sinkpad);
392 gst_object_unref (sinkpad);
393 sinkpad = NULL;
394
395 /* Check again with the 'request-pad' signal */
396 sinkcaps = gst_caps_new_empty_simple ("audio/x-raw");
397 g_signal_emit_by_name (ebin, "request-pad", sinkcaps, &sinkpad);
398 gst_caps_unref (sinkcaps);
399 fail_unless (sinkpad != NULL);
400 _caps_match (sinkpad, "audio/x-raw;audio/x-vorbis");
401 gst_element_release_request_pad (ebin, sinkpad);
402 gst_object_unref (sinkpad);
403 sinkpad = NULL;
404
405 fail_unless_equals_int (gst_element_set_state (ebin, GST_STATE_PAUSED),
406 GST_STATE_CHANGE_SUCCESS);
407
408 /* Set back to NULL */
409 fail_unless_equals_int (gst_element_set_state (ebin, GST_STATE_NULL),
410 GST_STATE_CHANGE_SUCCESS);
411
412 gst_object_unref (ebin);
413 };
414
415 GST_END_TEST;
416
GST_START_TEST(test_encodebin_sink_pads_multiple_static)417 GST_START_TEST (test_encodebin_sink_pads_multiple_static)
418 {
419 GstElement *ebin;
420 GstPad *srcpad, *sinkpadvorbis, *sinkpadtheora;
421
422 /* Create an encodebin and check that it properly creates the sink pads */
423
424 ebin = gst_element_factory_make ("encodebin", NULL);
425
426 /* First try is with a streamprofile that has a forced presence of 1 */
427 set_profile (ebin, create_ogg_theora_vorbis_profile (1, 1));
428
429 fail_unless_equals_int (gst_element_set_state (ebin, GST_STATE_PAUSED),
430 GST_STATE_CHANGE_SUCCESS);
431
432 /* Check if the source pad was properly created */
433 srcpad = gst_element_get_static_pad (ebin, "src");
434 fail_unless (srcpad != NULL);
435 gst_object_unref (srcpad);
436
437 /* Check if the audio sink pad was properly created */
438 sinkpadvorbis = gst_element_get_static_pad (ebin, "audio_0");
439 fail_unless (sinkpadvorbis != NULL);
440 _caps_match (sinkpadvorbis, "audio/x-raw;audio/x-vorbis");
441 gst_object_unref (sinkpadvorbis);
442
443 /* Check if the video sink pad was properly created */
444 sinkpadtheora = gst_element_get_static_pad (ebin, "video_1");
445 fail_unless (sinkpadtheora != NULL);
446 _caps_match (sinkpadtheora, "video/x-raw;video/x-theora");
447 gst_object_unref (sinkpadtheora);
448
449 /* Set back to NULL */
450 fail_unless_equals_int (gst_element_set_state (ebin, GST_STATE_NULL),
451 GST_STATE_CHANGE_SUCCESS);
452
453 gst_object_unref (ebin);
454 };
455
456 GST_END_TEST;
457
GST_START_TEST(test_encodebin_sink_pads_multiple_dynamic)458 GST_START_TEST (test_encodebin_sink_pads_multiple_dynamic)
459 {
460 GstElement *ebin;
461 GstPad *srcpad, *sinkpadvorbis, *sinkpadtheora;
462
463 /* Create an encodebin and check that it properly creates the sink pads
464 * for a multiple-stream with unfixed presence */
465
466 ebin = gst_element_factory_make ("encodebin", NULL);
467
468 /* multi-stream profile that has non-forced presence */
469 set_profile (ebin, create_ogg_theora_vorbis_profile (0, 0));
470
471 /* Check if the source pad was properly created */
472 srcpad = gst_element_get_static_pad (ebin, "src");
473 fail_unless (srcpad != NULL);
474 gst_object_unref (srcpad);
475
476 /* Check if the audio sink pad was properly created */
477 sinkpadvorbis = gst_element_request_pad_simple (ebin, "audio_0");
478 _caps_match (sinkpadvorbis, "audio/x-raw;audio/x-vorbis");
479 fail_unless (sinkpadvorbis != NULL);
480
481 /* Check if the video sink pad was properly created */
482 sinkpadtheora = gst_element_request_pad_simple (ebin, "video_1");
483 _caps_match (sinkpadtheora, "video/x-raw;video/x-theora");
484 fail_unless (sinkpadtheora != NULL);
485
486 fail_unless_equals_int (gst_element_set_state (ebin, GST_STATE_PAUSED),
487 GST_STATE_CHANGE_SUCCESS);
488
489 /* Set back to NULL */
490 fail_unless_equals_int (gst_element_set_state (ebin, GST_STATE_NULL),
491 GST_STATE_CHANGE_SUCCESS);
492
493 gst_element_release_request_pad (GST_ELEMENT (ebin), sinkpadvorbis);
494 gst_object_unref (sinkpadvorbis);
495 gst_element_release_request_pad (GST_ELEMENT (ebin), sinkpadtheora);
496 gst_object_unref (sinkpadtheora);
497
498 gst_object_unref (ebin);
499 };
500
501 GST_END_TEST;
502
GST_START_TEST(test_encodebin_sink_pads_dynamic_encoder)503 GST_START_TEST (test_encodebin_sink_pads_dynamic_encoder)
504 {
505 GstElement *ebin;
506 GstPad *srcpad, *sinkpad = NULL;
507 GstCaps *vorbiscaps;
508
509 /* Create an encodebin and check that it properly creates the sink pads
510 * for a single-stream profile with a unfixed presence */
511
512 ebin = gst_element_factory_make ("encodebin", NULL);
513
514 /* streamprofile that has non-forced presence */
515 set_profile (ebin, create_ogg_vorbis_profile (0, NULL));
516
517 /* Check if the source pad was properly created */
518 srcpad = gst_element_get_static_pad (ebin, "src");
519 fail_unless (srcpad != NULL);
520 gst_object_unref (srcpad);
521
522 /* Check if the audio sink pad was properly created */
523 vorbiscaps = gst_caps_from_string ("audio/x-vorbis,channels=2,rate=44100");
524 g_signal_emit_by_name (ebin, "request-pad", vorbiscaps, &sinkpad);
525 gst_caps_unref (vorbiscaps);
526 fail_unless (sinkpad != NULL);
527 _caps_match (sinkpad, "audio/x-raw;audio/x-vorbis");
528 gst_element_release_request_pad (ebin, sinkpad);
529 gst_object_unref (sinkpad);
530
531 fail_unless_equals_int (gst_element_set_state (ebin, GST_STATE_PAUSED),
532 GST_STATE_CHANGE_SUCCESS);
533
534 /* Set back to NULL */
535 fail_unless_equals_int (gst_element_set_state (ebin, GST_STATE_NULL),
536 GST_STATE_CHANGE_SUCCESS);
537
538 gst_object_unref (ebin);
539 };
540
541 GST_END_TEST;
542
GST_START_TEST(test_encodebin_render_audio_static)543 GST_START_TEST (test_encodebin_render_audio_static)
544 {
545 GstElement *ebin, *pipeline, *audiotestsrc, *fakesink;
546 GstBus *bus;
547 gboolean done = FALSE;
548
549 /* Create an encodebin and render 5s of vorbis/ogg */
550
551 pipeline = gst_pipeline_new ("encodebin-pipeline");
552 bus = gst_pipeline_get_bus ((GstPipeline *) pipeline);
553 audiotestsrc = gst_element_factory_make ("audiotestsrc", NULL);
554 g_object_set (audiotestsrc, "num-buffers", 10, NULL);
555 fakesink = gst_element_factory_make ("fakesink", NULL);
556
557 ebin = gst_element_factory_make ("encodebin", NULL);
558 set_profile (ebin, create_ogg_vorbis_profile (1, NULL));
559
560 gst_bin_add_many ((GstBin *) pipeline, audiotestsrc, ebin, fakesink, NULL);
561
562 fail_unless (gst_element_link_many (audiotestsrc, ebin, fakesink, NULL));
563
564 fail_unless_equals_int (gst_element_set_state (pipeline, GST_STATE_PLAYING),
565 GST_STATE_CHANGE_ASYNC);
566
567 while (!done) {
568 GstMessage *msg;
569
570 /* poll the bus until we get EOS without any errors */
571 msg = gst_bus_timed_pop (bus, GST_SECOND / 10);
572 if (msg) {
573 switch (GST_MESSAGE_TYPE (msg)) {
574 case GST_MESSAGE_ERROR:
575 fail ("GST_MESSAGE_ERROR");
576 break;
577 case GST_MESSAGE_EOS:
578 done = TRUE;
579 break;
580 default:
581 break;
582 }
583 gst_message_unref (msg);
584 }
585 }
586
587 /* Set back to NULL */
588 fail_unless_equals_int (gst_element_set_state (pipeline, GST_STATE_NULL),
589 GST_STATE_CHANGE_SUCCESS);
590
591 gst_object_unref (bus);
592
593 gst_object_unref (pipeline);
594 }
595
596 GST_END_TEST;
597
GST_START_TEST(test_encodebin_render_audio_only_static)598 GST_START_TEST (test_encodebin_render_audio_only_static)
599 {
600 GstElement *ebin, *pipeline, *audiotestsrc, *fakesink;
601 GstBus *bus;
602 gboolean done = FALSE;
603 GstPad *sinkpad;
604 GstCaps *sinkcaps;
605
606 /* Create an encodebin and render 5s of vorbis only */
607 pipeline = gst_pipeline_new ("encodebin-pipeline");
608 bus = gst_pipeline_get_bus ((GstPipeline *) pipeline);
609 audiotestsrc = gst_element_factory_make ("audiotestsrc", NULL);
610 g_object_set (audiotestsrc, "num-buffers", 10, NULL);
611 fakesink = gst_element_factory_make ("fakesink", NULL);
612
613 ebin = gst_element_factory_make ("encodebin", NULL);
614 set_profile (ebin, create_vorbis_only_profile ());
615
616 gst_bin_add_many (GST_BIN (pipeline), audiotestsrc, ebin, fakesink, NULL);
617
618 GST_DEBUG ("linking encodebin");
619 fail_unless (gst_element_link_many (audiotestsrc, ebin, fakesink, NULL));
620
621 /* Requesting a new pad should fail */
622 ASSERT_CRITICAL (gst_element_request_pad_simple (ebin, "audio_0"));
623
624 sinkcaps = gst_caps_new_empty_simple ("audio/x-raw");
625 g_signal_emit_by_name (ebin, "request-pad", sinkcaps, &sinkpad);
626 gst_caps_unref (sinkcaps);
627 fail_if (sinkpad != NULL);
628
629 fail_unless_equals_int (gst_element_set_state (pipeline, GST_STATE_PLAYING),
630 GST_STATE_CHANGE_ASYNC);
631
632 while (!done) {
633 GstMessage *msg;
634
635 /* poll the bus until we get EOS without any errors */
636 msg = gst_bus_timed_pop (bus, GST_SECOND / 10);
637 if (msg) {
638 switch (GST_MESSAGE_TYPE (msg)) {
639 case GST_MESSAGE_ERROR:
640 fail ("GST_MESSAGE_ERROR");
641 break;
642 case GST_MESSAGE_EOS:
643 done = TRUE;
644 break;
645 default:
646 break;
647 }
648 gst_message_unref (msg);
649 }
650 }
651
652 /* Set back to NULL */
653 fail_unless_equals_int (gst_element_set_state (pipeline, GST_STATE_NULL),
654 GST_STATE_CHANGE_SUCCESS);
655
656 gst_object_unref (bus);
657
658 gst_object_unref (pipeline);
659 }
660
661 GST_END_TEST;
662
GST_START_TEST(test_encodebin_render_audio_dynamic)663 GST_START_TEST (test_encodebin_render_audio_dynamic)
664 {
665 GstElement *ebin, *pipeline, *audiotestsrc, *fakesink;
666 GstBus *bus;
667 GstPad *sinkpad, *srcpad;
668 gboolean done = FALSE;
669
670 /* Create an encodebin and render 5s of vorbis/ogg */
671
672 pipeline = gst_pipeline_new ("encodebin-pipeline");
673 bus = gst_pipeline_get_bus ((GstPipeline *) pipeline);
674 audiotestsrc = gst_element_factory_make ("audiotestsrc", NULL);
675 g_object_set (audiotestsrc, "num-buffers", 10, NULL);
676 fakesink = gst_element_factory_make ("fakesink", NULL);
677
678 ebin = gst_element_factory_make ("encodebin", NULL);
679 set_profile (ebin, create_ogg_vorbis_profile (0, NULL));
680
681 gst_bin_add_many ((GstBin *) pipeline, audiotestsrc, ebin, fakesink, NULL);
682
683 srcpad = gst_element_get_static_pad (audiotestsrc, "src");
684 fail_unless (srcpad != NULL);
685
686 sinkpad = gst_element_request_pad_simple (ebin, "audio_0");
687 fail_unless (sinkpad != NULL);
688 _caps_match (sinkpad, "audio/x-raw;audio/x-vorbis");
689
690 fail_unless_equals_int (gst_pad_link (srcpad, sinkpad), GST_PAD_LINK_OK);
691
692 gst_object_unref (srcpad);
693
694 fail_unless (gst_element_link (ebin, fakesink));
695
696 fail_unless_equals_int (gst_element_set_state (pipeline, GST_STATE_PLAYING),
697 GST_STATE_CHANGE_ASYNC);
698
699 while (!done) {
700 GstMessage *msg;
701
702 /* poll the bus until we get EOS without any errors */
703 msg = gst_bus_timed_pop (bus, GST_SECOND / 10);
704 if (msg) {
705 switch (GST_MESSAGE_TYPE (msg)) {
706 case GST_MESSAGE_ERROR:
707 fail ("GST_MESSAGE_ERROR");
708 break;
709 case GST_MESSAGE_EOS:
710 done = TRUE;
711 break;
712 default:
713 break;
714 }
715 gst_message_unref (msg);
716 }
717 }
718
719 /* Set back to NULL */
720 fail_unless_equals_int (gst_element_set_state (pipeline, GST_STATE_NULL),
721 GST_STATE_CHANGE_SUCCESS);
722
723 gst_element_release_request_pad (GST_ELEMENT (ebin), sinkpad);
724 gst_object_unref (sinkpad);
725
726 gst_object_unref (bus);
727
728 gst_object_unref (pipeline);
729 }
730
731 GST_END_TEST;
732
GST_START_TEST(test_encodebin_render_audio_video_static)733 GST_START_TEST (test_encodebin_render_audio_video_static)
734 {
735 GstElement *ebin, *pipeline, *audiotestsrc, *videotestsrc, *fakesink;
736 GstBus *bus;
737 gboolean done = FALSE;
738
739 /* Create an encodebin and render 5s of vorbis/ogg */
740
741 pipeline = gst_pipeline_new ("encodebin-pipeline");
742 bus = gst_pipeline_get_bus ((GstPipeline *) pipeline);
743 audiotestsrc = gst_element_factory_make ("audiotestsrc", NULL);
744 g_object_set (audiotestsrc, "num-buffers", 10, NULL);
745 videotestsrc = gst_element_factory_make ("videotestsrc", NULL);
746 g_object_set (videotestsrc, "num-buffers", 5, NULL);
747 fakesink = gst_element_factory_make ("fakesink", NULL);
748
749 ebin = gst_element_factory_make ("encodebin", NULL);
750 set_profile (ebin, create_ogg_theora_vorbis_profile (1, 1));
751
752 gst_bin_add_many ((GstBin *) pipeline, audiotestsrc, videotestsrc, ebin,
753 fakesink, NULL);
754
755 fail_unless (gst_element_link (videotestsrc, ebin));
756 fail_unless (gst_element_link_many (audiotestsrc, ebin, fakesink, NULL));
757
758 fail_unless_equals_int (gst_element_set_state (pipeline, GST_STATE_PLAYING),
759 GST_STATE_CHANGE_ASYNC);
760
761 while (!done) {
762 GstMessage *msg;
763
764 /* poll the bus until we get EOS without any errors */
765 msg = gst_bus_timed_pop (bus, GST_SECOND / 10);
766 if (msg) {
767 switch (GST_MESSAGE_TYPE (msg)) {
768 case GST_MESSAGE_ERROR:
769 fail ("GST_MESSAGE_ERROR");
770 break;
771 case GST_MESSAGE_EOS:
772 done = TRUE;
773 break;
774 default:
775 break;
776 }
777 gst_message_unref (msg);
778 }
779 }
780
781 /* Set back to NULL */
782 fail_unless_equals_int (gst_element_set_state (pipeline, GST_STATE_NULL),
783 GST_STATE_CHANGE_SUCCESS);
784
785 gst_object_unref (bus);
786
787 gst_object_unref (pipeline);
788 }
789
790 GST_END_TEST;
791
GST_START_TEST(test_encodebin_render_audio_video_dynamic)792 GST_START_TEST (test_encodebin_render_audio_video_dynamic)
793 {
794 GstElement *ebin, *pipeline, *audiotestsrc, *videotestsrc, *fakesink;
795 GstBus *bus;
796 gboolean done = FALSE;
797 GstPad *sinkpad1, *sinkpad2, *srcpad;
798
799 /* Create an encodebin and render 5s of vorbis/ogg */
800
801 pipeline = gst_pipeline_new ("encodebin-pipeline");
802 bus = gst_pipeline_get_bus ((GstPipeline *) pipeline);
803 audiotestsrc = gst_element_factory_make ("audiotestsrc", NULL);
804 g_object_set (audiotestsrc, "num-buffers", 10, NULL);
805 videotestsrc = gst_element_factory_make ("videotestsrc", NULL);
806 g_object_set (videotestsrc, "num-buffers", 5, NULL);
807 fakesink = gst_element_factory_make ("fakesink", NULL);
808
809 ebin = gst_element_factory_make ("encodebin", NULL);
810 set_profile (ebin, create_ogg_theora_vorbis_profile (0, 0));
811
812 gst_bin_add_many ((GstBin *) pipeline, audiotestsrc, videotestsrc, ebin,
813 fakesink, NULL);
814
815 fail_unless (gst_element_link (ebin, fakesink));
816
817 srcpad = gst_element_get_static_pad (audiotestsrc, "src");
818 sinkpad1 = gst_element_request_pad_simple (ebin, "audio_0");
819 fail_unless (srcpad != NULL);
820 fail_unless (sinkpad1 != NULL);
821 _caps_match (sinkpad1, "audio/x-raw;audio/x-vorbis");
822 fail_unless_equals_int (gst_pad_link (srcpad, sinkpad1), GST_PAD_LINK_OK);
823 gst_object_unref (srcpad);
824
825 srcpad = gst_element_get_static_pad (videotestsrc, "src");
826 sinkpad2 = gst_element_request_pad_simple (ebin, "video_1");
827 _caps_match (sinkpad2, "video/x-raw;video/x-theora");
828 fail_unless_equals_int (gst_pad_link (srcpad, sinkpad2), GST_PAD_LINK_OK);
829 gst_object_unref (srcpad);
830
831 fail_unless_equals_int (gst_element_set_state (pipeline, GST_STATE_PLAYING),
832 GST_STATE_CHANGE_ASYNC);
833
834 while (!done) {
835 GstMessage *msg;
836
837 /* poll the bus until we get EOS without any errors */
838 msg = gst_bus_timed_pop (bus, GST_SECOND / 10);
839 if (msg) {
840 switch (GST_MESSAGE_TYPE (msg)) {
841 case GST_MESSAGE_ERROR:
842 fail ("GST_MESSAGE_ERROR");
843 break;
844 case GST_MESSAGE_EOS:
845 done = TRUE;
846 break;
847 default:
848 break;
849 }
850 gst_message_unref (msg);
851 }
852 }
853
854 /* Set back to NULL */
855 fail_unless_equals_int (gst_element_set_state (pipeline, GST_STATE_NULL),
856 GST_STATE_CHANGE_SUCCESS);
857
858 gst_element_release_request_pad (GST_ELEMENT (ebin), sinkpad1);
859 gst_object_unref (sinkpad1);
860 gst_element_release_request_pad (GST_ELEMENT (ebin), sinkpad2);
861 gst_object_unref (sinkpad2);
862
863 gst_object_unref (bus);
864
865 gst_object_unref (pipeline);
866 }
867
868 GST_END_TEST;
869
GST_START_TEST(test_encodebin_impossible_element_combination)870 GST_START_TEST (test_encodebin_impossible_element_combination)
871 {
872 GstElement *ebin;
873 GstEncodingProfile *prof;
874 GstCaps *ogg, *x264;
875
876 ebin = gst_element_factory_make ("x264enc", NULL);
877 if (ebin == NULL) {
878 GST_DEBUG ("No available h264 encoder, skipping test");
879 return;
880 }
881 gst_object_unref (ebin);
882
883 /* Make sure that impossible combinations of encoders and muxer
884 * properly fail. In this case we try putting h264 in ogg.
885 *
886 * To properly test we abort early, we use a presence of zero for the
887 * h264 stream profile. */
888
889 ebin = gst_element_factory_make ("encodebin", NULL);
890
891 ogg = gst_caps_new_empty_simple ("application/ogg");
892 prof = (GstEncodingProfile *) gst_encoding_container_profile_new ((gchar *)
893 "myprofile", NULL, ogg, NULL);
894 gst_caps_unref (ogg);
895
896 x264 = gst_caps_new_empty_simple ("video/x-h264");
897 fail_unless (gst_encoding_container_profile_add_profile
898 (GST_ENCODING_CONTAINER_PROFILE (prof),
899 (GstEncodingProfile *) gst_encoding_video_profile_new (x264, NULL,
900 NULL, 0)));
901 gst_caps_unref (x264);
902
903 g_object_set (ebin, "profile", prof, NULL);
904 gst_encoding_profile_unref (prof);
905
906 /* It will go to READY... */
907 fail_unless_equals_int (gst_element_set_state (ebin, GST_STATE_READY),
908 GST_STATE_CHANGE_SUCCESS);
909 /* ... but to not PAUSED */
910 fail_unless_equals_int (gst_element_set_state (ebin, GST_STATE_PAUSED),
911 GST_STATE_CHANGE_FAILURE);
912
913 gst_element_set_state (ebin, GST_STATE_NULL);
914
915 gst_object_unref (ebin);
916 };
917
918 GST_END_TEST;
919
920 static void
_test_encodebin_reuse(GstEncodingProfile * prof1,GstEncodingProfile * prof2)921 _test_encodebin_reuse (GstEncodingProfile * prof1, GstEncodingProfile * prof2)
922 {
923 GstElement *ebin;
924
925 ebin = gst_element_factory_make ("encodebin", NULL);
926
927 /* Set a profile on encodebin... */
928 if (prof1)
929 g_object_set (ebin, "profile", prof1, NULL);
930
931 /* Make sure we can go to PAUSED */
932 fail_unless_equals_int (gst_element_set_state (ebin, GST_STATE_PAUSED),
933 GST_STATE_CHANGE_SUCCESS);
934
935 /* Set back to NULL */
936 fail_unless_equals_int (gst_element_set_state (ebin, GST_STATE_NULL),
937 GST_STATE_CHANGE_SUCCESS);
938
939 if (prof2)
940 g_object_set (ebin, "profile", prof2, NULL);
941
942 /* Make sure we can go to PLAYING */
943 fail_unless_equals_int (gst_element_set_state (ebin, GST_STATE_PAUSED),
944 GST_STATE_CHANGE_SUCCESS);
945
946 /* Set back to NULL */
947 fail_unless_equals_int (gst_element_set_state (ebin, GST_STATE_NULL),
948 GST_STATE_CHANGE_SUCCESS);
949
950 gst_object_unref (ebin);
951 }
952
GST_START_TEST(test_encodebin_reuse)953 GST_START_TEST (test_encodebin_reuse)
954 {
955 GstEncodingProfile *prof1;
956 GstEncodingProfile *prof2;
957 GstEncodingProfile *prof3;
958
959 prof1 = create_ogg_profile ();
960 prof2 = create_ogg_theora_vorbis_profile (1, 1);
961 prof3 = create_vorbis_only_profile ();
962
963 _test_encodebin_reuse (prof1, NULL);
964 _test_encodebin_reuse (prof1, prof1);
965 _test_encodebin_reuse (prof1, prof2);
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
GST_START_TEST(test_encodebin_named_requests)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
GST_START_TEST(test_encodebin_missing_plugin_messages)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 GstElement *audiotestsrc;
1052 GstPad *sinkpad, *srcpad;
1053
1054 audiotestsrc = gst_element_factory_make ("audiotestsrc", NULL);
1055 g_object_set (audiotestsrc, "num-buffers", 1, NULL);
1056 gst_bin_add ((GstBin *) pipeline, audiotestsrc);
1057
1058 /* first add to bin, then set profile */
1059 gst_bin_add ((GstBin *) pipeline, ebin);
1060 set_profile (ebin, create_unsupported_profile ());
1061
1062 srcpad = gst_element_get_static_pad (audiotestsrc, "src");
1063 sinkpad = gst_element_get_static_pad (ebin, "audio_0");
1064 fail_unless (gst_pad_link (srcpad, sinkpad) == GST_PAD_LINK_OK);
1065 gst_object_unref (srcpad);
1066 gst_object_unref (sinkpad);
1067
1068 gst_element_set_state (pipeline, GST_STATE_PLAYING);
1069
1070 message =
1071 gst_bus_timed_pop_filtered (bus, GST_CLOCK_TIME_NONE,
1072 GST_MESSAGE_ELEMENT);
1073 fail_if (message == NULL);
1074 fail_if (!gst_is_missing_plugin_message (message));
1075 gst_message_unref (message);
1076
1077 gst_element_set_state (pipeline, GST_STATE_NULL);
1078 gst_object_unref (bus);
1079 gst_object_unref (pipeline);
1080 }
1081
1082 GST_END_TEST;
1083
GST_START_TEST(test_encodebin_fallback_profiles_on_failure)1084 GST_START_TEST (test_encodebin_fallback_profiles_on_failure)
1085 {
1086 GstElement *ebin;
1087 GstPad *sinkpad = NULL;
1088 GstCaps *vorbiscaps;
1089 GstEncodingProfile *profile, *vorbis_profile;
1090
1091 ebin = gst_element_factory_make ("encodebin", NULL);
1092
1093 /* Create a ogg profile with a vorbis sub profile
1094 * that can't be 'instanciated' because its preset is set
1095 * to nowaythispresetexists. */
1096 profile = create_ogg_vorbis_profile (0, (gchar *) "nowaythispresetexists");
1097 vorbis_profile = create_vorbis_only_profile ();
1098 gst_encoding_container_profile_add_profile (GST_ENCODING_CONTAINER_PROFILE
1099 (profile), vorbis_profile);
1100 set_profile (ebin, profile);
1101
1102 /* Check if the audio sink pad can be created, meaning
1103 * that the first profile with a 'nowaythispresetexists'
1104 * preset has been skipped. */
1105 vorbiscaps = gst_caps_from_string ("audio/x-vorbis");
1106 g_signal_emit_by_name (ebin, "request-pad", vorbiscaps, &sinkpad);
1107 _caps_match (sinkpad, "audio/x-raw;audio/x-vorbis");
1108 gst_element_release_request_pad (ebin, sinkpad);
1109 gst_object_unref (sinkpad);
1110 gst_caps_unref (vorbiscaps);
1111
1112 gst_object_unref (ebin);
1113 };
1114
1115 GST_END_TEST;
1116
1117 static Suite *
encodebin_suite(void)1118 encodebin_suite (void)
1119 {
1120 Suite *s = suite_create ("encodebin element");
1121 TCase *tc_chain = tcase_create ("general");
1122
1123 suite_add_tcase (s, tc_chain);
1124 tcase_add_test (tc_chain, test_encodebin_set_profile);
1125 tcase_add_test (tc_chain, test_encodebin_can_go_to_ready_without_profile);
1126 tcase_add_test (tc_chain, test_encodebin_can_go_to_paused_with_profile);
1127 tcase_add_test (tc_chain, test_encodebin_sink_pads_static);
1128 tcase_add_test (tc_chain, test_encodebin_sink_pads_nopreset_static);
1129 tcase_add_test (tc_chain, test_encodebin_preset);
1130 tcase_add_test (tc_chain, test_encodebin_sink_pads_dynamic);
1131 tcase_add_test (tc_chain, test_encodebin_sink_pads_multiple_static);
1132 tcase_add_test (tc_chain, test_encodebin_sink_pads_multiple_dynamic);
1133 tcase_add_test (tc_chain, test_encodebin_sink_pads_dynamic_encoder);
1134 tcase_add_test (tc_chain, test_encodebin_render_audio_static);
1135 tcase_add_test (tc_chain, test_encodebin_render_audio_only_static);
1136 tcase_add_test (tc_chain, test_encodebin_render_audio_dynamic);
1137 tcase_add_test (tc_chain, test_encodebin_render_audio_video_static);
1138 tcase_add_test (tc_chain, test_encodebin_render_audio_video_dynamic);
1139 tcase_add_test (tc_chain, test_encodebin_impossible_element_combination);
1140 tcase_add_test (tc_chain, test_encodebin_reuse);
1141 tcase_add_test (tc_chain, test_encodebin_named_requests);
1142 tcase_add_test (tc_chain, test_encodebin_missing_plugin_messages);
1143 tcase_add_test (tc_chain, test_encodebin_fallback_profiles_on_failure);
1144
1145 return s;
1146 }
1147
1148 GST_CHECK_MAIN (encodebin);
1149