update for metadata API changes
[platform/upstream/gst-plugins-base.git] / tests / check / elements / playbin.c
1 /* GStreamer unit tests for playbin
2  *
3  * Copyright (C) 2006 Tim-Philipp Müller <tim centricular net>
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., 59 Temple Place - Suite 330,
18  * Boston, MA 02111-1307, USA.
19  */
20
21 #ifdef HAVE_CONFIG_H
22 # include <config.h>
23 #endif
24
25 #include <gst/check/gstcheck.h>
26 #include <gst/base/gstpushsrc.h>
27 #include <unistd.h>
28
29 #ifndef GST_DISABLE_REGISTRY
30
31 static GType gst_red_video_src_get_type (void);
32 static GType gst_codec_src_get_type (void);
33
34 /* make sure the audio sink is not touched for video-only streams */
35 GST_START_TEST (test_sink_usage_video_only_stream)
36 {
37   GstElement *playbin, *fakevideosink, *fakeaudiosink;
38   GstState cur_state, pending_state;
39   GstElement *source;
40   GstSample *last_sample;
41   gint nstreams;
42
43   fail_unless (gst_element_register (NULL, "redvideosrc", GST_RANK_PRIMARY,
44           gst_red_video_src_get_type ()));
45
46   playbin = gst_element_factory_make ("playbin", "playbin");
47   fail_unless (playbin != NULL, "Failed to create playbin element");
48
49   fakevideosink = gst_element_factory_make ("fakesink", "fakevideosink");
50   fail_unless (fakevideosink != NULL, "Failed to create fakevideosink element");
51
52   fakeaudiosink = gst_element_factory_make ("fakesink", "fakeaudiosink");
53   fail_unless (fakeaudiosink != NULL, "Failed to create fakeaudiosink element");
54
55   /* video-only stream, audiosink will error out in null => ready if used */
56   g_object_set (fakeaudiosink, "state-error", 1, NULL);
57
58   g_object_set (playbin, "video-sink", fakevideosink, NULL);
59   g_object_set (playbin, "audio-sink", fakeaudiosink, NULL);
60
61   g_object_set (playbin, "uri", "redvideo://", NULL);
62
63   fail_unless_equals_int (gst_element_set_state (playbin, GST_STATE_READY),
64       GST_STATE_CHANGE_SUCCESS);
65   fail_unless_equals_int (gst_element_set_state (playbin, GST_STATE_PAUSED),
66       GST_STATE_CHANGE_ASYNC);
67   fail_unless_equals_int (gst_element_get_state (playbin, NULL, NULL, -1),
68       GST_STATE_CHANGE_SUCCESS);
69
70   fail_unless_equals_int (gst_element_get_state (fakeaudiosink, &cur_state,
71           &pending_state, 0), GST_STATE_CHANGE_SUCCESS);
72   fail_unless_equals_int (cur_state, GST_STATE_NULL);
73   fail_unless_equals_int (pending_state, GST_STATE_VOID_PENDING);
74
75   g_object_get (playbin, "n-video", &nstreams, NULL);
76   fail_unless_equals_int (nstreams, 1);
77
78   g_object_get (playbin, "n-audio", &nstreams, NULL);
79   fail_unless_equals_int (nstreams, 0);
80
81   g_object_get (playbin, "n-text", &nstreams, NULL);
82   fail_unless_equals_int (nstreams, 0);
83
84   g_object_get (playbin, "source", &source, NULL);
85   fail_unless (G_TYPE_FROM_INSTANCE (source) == gst_red_video_src_get_type ());
86   gst_object_unref (source);
87
88   g_object_get (playbin, "sample", &last_sample, NULL);
89   fail_unless (GST_IS_SAMPLE (last_sample));
90   gst_sample_unref (last_sample);
91
92   gst_element_set_state (playbin, GST_STATE_NULL);
93   gst_object_unref (playbin);
94 }
95
96 GST_END_TEST;
97
98 /* this tests async error handling when setting up the subbin */
99 GST_START_TEST (test_suburi_error_unknowntype)
100 {
101   GstElement *playbin, *fakesink;
102
103   fail_unless (gst_element_register (NULL, "redvideosrc", GST_RANK_PRIMARY,
104           gst_red_video_src_get_type ()));
105
106   playbin = gst_element_factory_make ("playbin", "playbin");
107   fail_unless (playbin != NULL, "Failed to create playbin element");
108
109   fakesink = gst_element_factory_make ("fakesink", "fakesink");
110   fail_unless (fakesink != NULL, "Failed to create fakesink element");
111   ASSERT_OBJECT_REFCOUNT (fakesink, "fakesink after creation", 1);
112
113   g_object_set (playbin, "video-sink", fakesink, NULL);
114
115   /* suburi file format unknown: playbin should just ignore the suburi and
116    * preroll normally (if /dev/zero does not exist, this test should behave
117    * the same as test_suburi_error_invalidfile() */
118   g_object_set (playbin, "uri", "redvideo://", NULL);
119   g_object_set (playbin, "suburi", "file:///dev/zero", NULL);
120   fail_unless_equals_int (gst_element_set_state (playbin, GST_STATE_READY),
121       GST_STATE_CHANGE_SUCCESS);
122   fail_unless_equals_int (gst_element_set_state (playbin, GST_STATE_PAUSED),
123       GST_STATE_CHANGE_ASYNC);
124   fail_unless_equals_int (gst_element_get_state (playbin, NULL, NULL, -1),
125       GST_STATE_CHANGE_SUCCESS);
126
127   gst_element_set_state (playbin, GST_STATE_NULL);
128   gst_object_unref (playbin);
129 }
130
131 GST_END_TEST;
132
133 GST_START_TEST (test_suburi_error_invalidfile)
134 {
135   GstElement *playbin, *fakesink;
136
137   fail_unless (gst_element_register (NULL, "redvideosrc", GST_RANK_PRIMARY,
138           gst_red_video_src_get_type ()));
139
140   playbin = gst_element_factory_make ("playbin", "playbin");
141   fail_unless (playbin != NULL, "Failed to create playbin element");
142
143   fakesink = gst_element_factory_make ("fakesink", "fakesink");
144   fail_unless (fakesink != NULL, "Failed to create fakesink element");
145   ASSERT_OBJECT_REFCOUNT (fakesink, "fakesink after creation", 1);
146
147   g_object_set (playbin, "video-sink", fakesink, NULL);
148
149   /* suburi file does not exist: playbin should just ignore the suburi and
150    * preroll normally */
151   g_object_set (playbin, "uri", "redvideo://", NULL);
152   g_object_set (playbin, "suburi", "file:///foo/bar/803129999/32x9ax1", NULL);
153   fail_unless_equals_int (gst_element_set_state (playbin, GST_STATE_READY),
154       GST_STATE_CHANGE_SUCCESS);
155   fail_unless_equals_int (gst_element_set_state (playbin, GST_STATE_PAUSED),
156       GST_STATE_CHANGE_ASYNC);
157   fail_unless_equals_int (gst_element_get_state (playbin, NULL, NULL, -1),
158       GST_STATE_CHANGE_SUCCESS);
159
160   gst_element_set_state (playbin, GST_STATE_NULL);
161   gst_object_unref (playbin);
162 }
163
164 GST_END_TEST;
165
166 GST_START_TEST (test_suburi_error_wrongproto)
167 {
168   GstElement *playbin, *fakesink;
169
170   fail_unless (gst_element_register (NULL, "redvideosrc", GST_RANK_PRIMARY,
171           gst_red_video_src_get_type ()));
172
173   playbin = gst_element_factory_make ("playbin", "playbin");
174   fail_unless (playbin != NULL, "Failed to create playbin element");
175
176   fakesink = gst_element_factory_make ("fakesink", "fakesink");
177   fail_unless (fakesink != NULL, "Failed to create fakesink element");
178   ASSERT_OBJECT_REFCOUNT (fakesink, "fakesink after creation", 1);
179
180   g_object_set (playbin, "video-sink", fakesink, NULL);
181
182   /* wrong protocol for suburi: playbin should just ignore the suburi and
183    * preroll normally */
184   g_object_set (playbin, "uri", "redvideo://", NULL);
185   g_object_set (playbin, "suburi", "nosuchproto://foo.bar:80", NULL);
186   fail_unless_equals_int (gst_element_set_state (playbin, GST_STATE_READY),
187       GST_STATE_CHANGE_SUCCESS);
188   fail_unless_equals_int (gst_element_set_state (playbin, GST_STATE_PAUSED),
189       GST_STATE_CHANGE_ASYNC);
190   fail_unless_equals_int (gst_element_get_state (playbin, NULL, NULL, -1),
191       GST_STATE_CHANGE_SUCCESS);
192
193   gst_element_set_state (playbin, GST_STATE_NULL);
194   gst_object_unref (playbin);
195 }
196
197 GST_END_TEST;
198
199 static GstElement *
200 create_playbin (const gchar * uri)
201 {
202   GstElement *playbin, *fakesink1, *fakesink2;
203
204   playbin = gst_element_factory_make ("playbin", "playbin");
205   fail_unless (playbin != NULL, "Failed to create playbin element");
206
207   fakesink1 = gst_element_factory_make ("fakesink", NULL);
208   fail_unless (fakesink1 != NULL, "Failed to create fakesink element #1");
209
210   fakesink2 = gst_element_factory_make ("fakesink", NULL);
211   fail_unless (fakesink2 != NULL, "Failed to create fakesink element #2");
212
213   /* make them behave like normal sinks, even if not needed for the test */
214   g_object_set (fakesink1, "sync", TRUE, NULL);
215   g_object_set (fakesink2, "sync", TRUE, NULL);
216
217   g_object_set (playbin, "video-sink", fakesink1, NULL);
218   g_object_set (playbin, "audio-sink", fakesink2, NULL);
219
220   g_object_set (playbin, "uri", uri, NULL);
221
222   return playbin;
223 }
224
225 GST_START_TEST (test_missing_urisource_handler)
226 {
227   GstStructure *s;
228   GstMessage *msg;
229   GstElement *playbin;
230   GError *err = NULL;
231   GstBus *bus;
232
233   playbin = create_playbin ("chocchipcookie://withahint.of/cinnamon");
234
235   fail_unless_equals_int (gst_element_set_state (playbin, GST_STATE_READY),
236       GST_STATE_CHANGE_SUCCESS);
237   fail_unless_equals_int (gst_element_set_state (playbin, GST_STATE_PAUSED),
238       GST_STATE_CHANGE_FAILURE);
239
240   /* there should be at least a missing-plugin message on the bus now and an
241    * error message; the missing-plugin message should be first */
242   bus = gst_element_get_bus (playbin);
243
244   msg = gst_bus_poll (bus, GST_MESSAGE_ELEMENT | GST_MESSAGE_ERROR, -1);
245   fail_unless_equals_int (GST_MESSAGE_TYPE (msg), GST_MESSAGE_ELEMENT);
246   s = (GstStructure *) gst_message_get_structure (msg);
247   fail_unless (s != NULL);
248   fail_unless (gst_structure_has_name (s, "missing-plugin"));
249   fail_unless (gst_structure_has_field_typed (s, "detail", G_TYPE_STRING));
250   fail_unless_equals_string (gst_structure_get_string (s, "detail"),
251       "chocchipcookie");
252   fail_unless (gst_structure_has_field_typed (s, "type", G_TYPE_STRING));
253   fail_unless_equals_string (gst_structure_get_string (s, "type"), "urisource");
254   gst_message_unref (msg);
255
256   msg = gst_bus_poll (bus, GST_MESSAGE_ERROR, -1);
257   fail_unless_equals_int (GST_MESSAGE_TYPE (msg), GST_MESSAGE_ERROR);
258
259   /* make sure the error is a CORE MISSING_PLUGIN one */
260   gst_message_parse_error (msg, &err, NULL);
261   fail_unless (err != NULL);
262   fail_unless (err->domain == GST_CORE_ERROR, "error has wrong error domain "
263       "%s instead of core-error-quark", g_quark_to_string (err->domain));
264   fail_unless (err->code == GST_CORE_ERROR_MISSING_PLUGIN, "error has wrong "
265       "code %u instead of GST_CORE_ERROR_MISSING_PLUGIN", err->code);
266   g_error_free (err);
267   gst_message_unref (msg);
268   gst_object_unref (bus);
269
270   gst_element_set_state (playbin, GST_STATE_NULL);
271   gst_object_unref (playbin);
272 }
273
274 GST_END_TEST;
275
276 GST_START_TEST (test_missing_suburisource_handler)
277 {
278   GstStructure *s;
279   GstMessage *msg;
280   GstElement *playbin;
281   GError *err = NULL;
282   GstBus *bus;
283
284   playbin = create_playbin ("file:///does/not/exis.t");
285
286   g_object_set (playbin, "suburi", "cookie://withahint.of/cinnamon", NULL);
287
288   fail_unless_equals_int (gst_element_set_state (playbin, GST_STATE_READY),
289       GST_STATE_CHANGE_SUCCESS);
290   fail_unless_equals_int (gst_element_set_state (playbin, GST_STATE_PAUSED),
291       GST_STATE_CHANGE_FAILURE);
292
293   /* there should be at least a missing-plugin message on the bus now and an
294    * error message; the missing-plugin message should be first */
295   bus = gst_element_get_bus (playbin);
296
297   msg = gst_bus_poll (bus, GST_MESSAGE_ELEMENT | GST_MESSAGE_ERROR, -1);
298   fail_unless_equals_int (GST_MESSAGE_TYPE (msg), GST_MESSAGE_ELEMENT);
299   s = (GstStructure *) gst_message_get_structure (msg);
300   fail_unless (s != NULL);
301   fail_unless (gst_structure_has_name (s, "missing-plugin"));
302   fail_unless (gst_structure_has_field_typed (s, "detail", G_TYPE_STRING));
303   fail_unless_equals_string (gst_structure_get_string (s, "detail"), "cookie");
304   fail_unless (gst_structure_has_field_typed (s, "type", G_TYPE_STRING));
305   fail_unless_equals_string (gst_structure_get_string (s, "type"), "urisource");
306   gst_message_unref (msg);
307
308   msg = gst_bus_poll (bus, GST_MESSAGE_WARNING, -1);
309   fail_unless_equals_int (GST_MESSAGE_TYPE (msg), GST_MESSAGE_WARNING);
310
311   /* make sure the *warning* is a CORE MISSING_PLUGIN one */
312   gst_message_parse_warning (msg, &err, NULL);
313   fail_unless (err != NULL);
314   fail_unless (err->domain == GST_CORE_ERROR, "error has wrong error domain "
315       "%s instead of core-error-quark", g_quark_to_string (err->domain));
316   fail_unless (err->code == GST_CORE_ERROR_MISSING_PLUGIN, "error has wrong "
317       "code %u instead of GST_CORE_ERROR_MISSING_PLUGIN", err->code);
318   g_error_free (err);
319   gst_message_unref (msg);
320
321   msg = gst_bus_poll (bus, GST_MESSAGE_ERROR, -1);
322   fail_unless_equals_int (GST_MESSAGE_TYPE (msg), GST_MESSAGE_ERROR);
323
324   /* make sure the error is a RESOURCE NOT_FOUND one */
325   gst_message_parse_error (msg, &err, NULL);
326   fail_unless (err != NULL);
327   fail_unless (err->domain == GST_RESOURCE_ERROR,
328       "error has wrong error domain " "%s instead of resource-error-quark",
329       g_quark_to_string (err->domain));
330   fail_unless (err->code == GST_RESOURCE_ERROR_NOT_FOUND,
331       "error has wrong " "code %u instead of GST_RESOURCE_ERROR_NOT_FOUND",
332       err->code);
333   g_error_free (err);
334   gst_message_unref (msg);
335
336   gst_object_unref (bus);
337
338   gst_element_set_state (playbin, GST_STATE_NULL);
339   gst_object_unref (playbin);
340 }
341
342 GST_END_TEST;
343
344 GST_START_TEST (test_missing_primary_decoder)
345 {
346   GstStructure *s;
347   GstMessage *msg;
348   GstElement *playbin;
349   GError *err = NULL;
350   GstBus *bus;
351
352   fail_unless (gst_element_register (NULL, "codecsrc", GST_RANK_PRIMARY,
353           gst_codec_src_get_type ()));
354
355   playbin = create_playbin ("codec://");
356
357   fail_unless_equals_int (gst_element_set_state (playbin, GST_STATE_READY),
358       GST_STATE_CHANGE_SUCCESS);
359   fail_unless_equals_int (gst_element_set_state (playbin, GST_STATE_PAUSED),
360       GST_STATE_CHANGE_ASYNC);
361
362   /* there should soon be at least a missing-plugin message on the bus and an
363    * error message; the missing-plugin message should be first */
364   bus = gst_element_get_bus (playbin);
365
366   msg = gst_bus_poll (bus, GST_MESSAGE_ELEMENT | GST_MESSAGE_ERROR, -1);
367   fail_unless_equals_int (GST_MESSAGE_TYPE (msg), GST_MESSAGE_ELEMENT);
368   s = (GstStructure *) gst_message_get_structure (msg);
369   fail_unless (s != NULL);
370   fail_unless (gst_structure_has_name (s, "missing-plugin"));
371   fail_unless (gst_structure_has_field_typed (s, "type", G_TYPE_STRING));
372   fail_unless_equals_string (gst_structure_get_string (s, "type"), "decoder");
373   fail_unless (gst_structure_has_field_typed (s, "detail", GST_TYPE_CAPS));
374   gst_message_unref (msg);
375
376   msg = gst_bus_poll (bus, GST_MESSAGE_WARNING, -1);
377   fail_unless_equals_int (GST_MESSAGE_TYPE (msg), GST_MESSAGE_WARNING);
378
379   /* make sure the *warning* is a STREAM CODEC_NOT_FOUND one */
380   gst_message_parse_warning (msg, &err, NULL);
381   fail_unless (err != NULL);
382   fail_unless (err->domain == GST_STREAM_ERROR, "error has wrong error domain "
383       "%s instead of stream-error-quark", g_quark_to_string (err->domain));
384   fail_unless (err->code == GST_STREAM_ERROR_CODEC_NOT_FOUND, "error has wrong "
385       "code %u instead of GST_STREAM_ERROR_CODEC_NOT_FOUND", err->code);
386   g_error_free (err);
387   gst_message_unref (msg);
388
389   msg = gst_bus_poll (bus, GST_MESSAGE_ERROR, -1);
390   fail_unless_equals_int (GST_MESSAGE_TYPE (msg), GST_MESSAGE_ERROR);
391
392   /* make sure the error is a CORE MISSING_PLUGIN one */
393   gst_message_parse_error (msg, &err, NULL);
394   fail_unless (err != NULL);
395   fail_unless (err->domain == GST_CORE_ERROR, "error has wrong error domain "
396       "%s instead of core-error-quark", g_quark_to_string (err->domain));
397   fail_unless (err->code == GST_CORE_ERROR_MISSING_PLUGIN, "error has wrong "
398       "code %u instead of GST_CORE_ERROR_MISSING_PLUGIN", err->code);
399   g_error_free (err);
400   gst_message_unref (msg);
401
402   gst_object_unref (bus);
403
404   gst_element_set_state (playbin, GST_STATE_NULL);
405   gst_object_unref (playbin);
406 }
407
408 GST_END_TEST;
409
410 GST_START_TEST (test_refcount)
411 {
412   GstElement *playbin, *audiosink, *videosink, *vis;
413
414   fail_unless (gst_element_register (NULL, "redvideosrc", GST_RANK_PRIMARY,
415           gst_red_video_src_get_type ()));
416
417   playbin = gst_element_factory_make ("playbin", NULL);
418   audiosink = gst_element_factory_make ("fakesink", "myaudiosink");
419   videosink = gst_element_factory_make ("fakesink", "myvideosink");
420   vis = gst_element_factory_make ("identity", "myvis");
421
422   /* ref because we need them after we unref playbin */
423   gst_object_ref (audiosink);
424   gst_object_ref (videosink);
425   gst_object_ref (vis);
426
427   /* Sinks have floating ref only, setting the properties takes ownership. */
428   g_object_set (playbin,
429       "audio-sink", audiosink,
430       "video-sink", videosink,
431       "vis-plugin", vis, "flags", 0x01 | 0x02 | 0x08, NULL);
432
433   g_object_set (playbin, "uri", "redvideo://", NULL);
434   //"uri", "file:///home/wim/data/cdda.ogg", NULL);
435
436   ASSERT_OBJECT_REFCOUNT (playbin, "playbin", 1);
437
438   /* we have two refs now, one from ourselves and one from playbin */
439   ASSERT_OBJECT_REFCOUNT (audiosink, "myaudiosink", 2);
440   ASSERT_OBJECT_REFCOUNT (videosink, "myvideosink", 2);
441   ASSERT_OBJECT_REFCOUNT (vis, "myvis", 2);
442
443   fail_unless_equals_int (gst_element_set_state (playbin, GST_STATE_PAUSED),
444       GST_STATE_CHANGE_ASYNC);
445   fail_unless_equals_int (gst_element_get_state (playbin, NULL, NULL,
446           GST_CLOCK_TIME_NONE), GST_STATE_CHANGE_SUCCESS);
447   fail_unless_equals_int (gst_element_set_state (playbin, GST_STATE_NULL),
448       GST_STATE_CHANGE_SUCCESS);
449
450   ASSERT_OBJECT_REFCOUNT (playbin, "playbin", 1);
451   /* refcount of our elements is undefined, playbin might keep additional refs
452    * because it cached the elements in bins */
453   gst_object_unref (playbin);
454
455   /* now we are back to our refs */
456   ASSERT_OBJECT_REFCOUNT (audiosink, "myaudiosink", 1);
457   ASSERT_OBJECT_REFCOUNT (videosink, "myvideosink", 1);
458   ASSERT_OBJECT_REFCOUNT (vis, "myvis", 1);
459
460   gst_object_unref (audiosink);
461   gst_object_unref (videosink);
462   gst_object_unref (vis);
463 }
464
465 GST_END_TEST;
466
467 static void
468 source_setup (GstElement * playbin, GstElement * source, GstElement ** p_src)
469 {
470   GST_LOG ("source-setup called, source = %s", G_OBJECT_TYPE_NAME (source));
471   *p_src = gst_object_ref (source);
472   GST_LOG ("here");
473 }
474
475 GST_START_TEST (test_source_setup)
476 {
477   GstElement *playbin, *videosink;
478   GstElement *src = NULL;
479
480   if (!gst_registry_check_feature_version (gst_registry_get (), "redvideosrc",
481           0, 10, 0)) {
482     fail_unless (gst_element_register (NULL, "redvideosrc", GST_RANK_PRIMARY,
483             gst_red_video_src_get_type ()));
484   }
485
486   playbin = gst_element_factory_make ("playbin", NULL);
487   g_object_set (playbin, "uri", "redvideo://", NULL);
488
489   videosink = gst_element_factory_make ("fakesink", "myvideosink");
490   g_object_set (playbin, "video-sink", videosink, NULL);
491
492   g_signal_connect (playbin, "source-setup", G_CALLBACK (source_setup), &src);
493
494   fail_unless_equals_int (gst_element_set_state (playbin, GST_STATE_PAUSED),
495       GST_STATE_CHANGE_ASYNC);
496   fail_unless_equals_int (gst_element_get_state (playbin, NULL, NULL,
497           GST_CLOCK_TIME_NONE), GST_STATE_CHANGE_SUCCESS);
498
499   fail_unless (src != NULL);
500   fail_unless (G_OBJECT_TYPE (src) == gst_red_video_src_get_type ());
501
502   fail_unless_equals_int (gst_element_set_state (playbin, GST_STATE_NULL),
503       GST_STATE_CHANGE_SUCCESS);
504
505   gst_object_unref (playbin);
506   gst_object_unref (src);
507 }
508
509 GST_END_TEST;
510
511 /*** redvideo:// source ***/
512
513 static GstURIType
514 gst_red_video_src_uri_get_type (GType type)
515 {
516   return GST_URI_SRC;
517 }
518
519 static const gchar *const *
520 gst_red_video_src_uri_get_protocols (GType type)
521 {
522   static const gchar *protocols[] = { "redvideo", NULL };
523
524   return protocols;
525 }
526
527 static gchar *
528 gst_red_video_src_uri_get_uri (GstURIHandler * handler)
529 {
530   return g_strdup ("redvideo://");
531 }
532
533 static gboolean
534 gst_red_video_src_uri_set_uri (GstURIHandler * handler, const gchar * uri,
535     GError ** error)
536 {
537   return (uri != NULL && g_str_has_prefix (uri, "redvideo:"));
538 }
539
540 static void
541 gst_red_video_src_uri_handler_init (gpointer g_iface, gpointer iface_data)
542 {
543   GstURIHandlerInterface *iface = (GstURIHandlerInterface *) g_iface;
544
545   iface->get_type = gst_red_video_src_uri_get_type;
546   iface->get_protocols = gst_red_video_src_uri_get_protocols;
547   iface->get_uri = gst_red_video_src_uri_get_uri;
548   iface->set_uri = gst_red_video_src_uri_set_uri;
549 }
550
551 static void
552 gst_red_video_src_init_type (GType type)
553 {
554   static const GInterfaceInfo uri_hdlr_info = {
555     gst_red_video_src_uri_handler_init, NULL, NULL
556   };
557
558   g_type_add_interface_static (type, GST_TYPE_URI_HANDLER, &uri_hdlr_info);
559 }
560
561 typedef GstPushSrc GstRedVideoSrc;
562 typedef GstPushSrcClass GstRedVideoSrcClass;
563
564 G_DEFINE_TYPE_WITH_CODE (GstRedVideoSrc, gst_red_video_src,
565     GST_TYPE_PUSH_SRC, gst_red_video_src_init_type (g_define_type_id));
566
567 static GstFlowReturn
568 gst_red_video_src_create (GstPushSrc * src, GstBuffer ** p_buf)
569 {
570   GstBuffer *buf;
571   GstMapInfo map;
572   guint w = 64, h = 64;
573   guint size;
574
575   size = w * h * 3 / 2;
576   buf = gst_buffer_new_and_alloc (size);
577   gst_buffer_map (buf, &map, GST_MAP_WRITE);
578   memset (map.data, 76, w * h);
579   memset (map.data + (w * h), 85, (w * h) / 4);
580   memset (map.data + (w * h) + ((w * h) / 4), 255, (w * h) / 4);
581   gst_buffer_unmap (buf, &map);
582
583   *p_buf = buf;
584   return GST_FLOW_OK;
585 }
586
587 static GstCaps *
588 gst_red_video_src_get_caps (GstBaseSrc * src, GstCaps * filter)
589 {
590   guint w = 64, h = 64;
591   return gst_caps_new_simple ("video/x-raw", "format", G_TYPE_STRING,
592       "I420", "width", G_TYPE_INT, w, "height",
593       G_TYPE_INT, h, "framerate", GST_TYPE_FRACTION, 1, 1, NULL);
594 }
595
596 static void
597 gst_red_video_src_class_init (GstRedVideoSrcClass * klass)
598 {
599   GstPushSrcClass *pushsrc_class = GST_PUSH_SRC_CLASS (klass);
600   GstBaseSrcClass *basesrc_class = GST_BASE_SRC_CLASS (klass);
601   static GstStaticPadTemplate src_templ = GST_STATIC_PAD_TEMPLATE ("src",
602       GST_PAD_SRC, GST_PAD_ALWAYS,
603       GST_STATIC_CAPS ("video/x-raw, format=(string)I420")
604       );
605   GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
606
607   gst_element_class_add_pad_template (element_class,
608       gst_static_pad_template_get (&src_templ));
609   gst_element_class_set_details_simple (element_class,
610       "Red Video Src", "Source/Video", "yep", "me");
611
612   pushsrc_class->create = gst_red_video_src_create;
613   basesrc_class->get_caps = gst_red_video_src_get_caps;
614 }
615
616 static void
617 gst_red_video_src_init (GstRedVideoSrc * src)
618 {
619 }
620
621 /*** codec:// source ***/
622
623 static GstURIType
624 gst_codec_src_uri_get_type (GType type)
625 {
626   return GST_URI_SRC;
627 }
628
629 static const gchar *const *
630 gst_codec_src_uri_get_protocols (GType type)
631 {
632   static const gchar *protocols[] = { (char *) "codec", NULL };
633
634   return protocols;
635 }
636
637 static gchar *
638 gst_codec_src_uri_get_uri (GstURIHandler * handler)
639 {
640   return g_strdup ("codec://");
641 }
642
643 static gboolean
644 gst_codec_src_uri_set_uri (GstURIHandler * handler, const gchar * uri,
645     GError ** error)
646 {
647   return (uri != NULL && g_str_has_prefix (uri, "codec:"));
648 }
649
650 static void
651 gst_codec_src_uri_handler_init (gpointer g_iface, gpointer iface_data)
652 {
653   GstURIHandlerInterface *iface = (GstURIHandlerInterface *) g_iface;
654
655   iface->get_type = gst_codec_src_uri_get_type;
656   iface->get_protocols = gst_codec_src_uri_get_protocols;
657   iface->get_uri = gst_codec_src_uri_get_uri;
658   iface->set_uri = gst_codec_src_uri_set_uri;
659 }
660
661 static void
662 gst_codec_src_init_type (GType type)
663 {
664   static const GInterfaceInfo uri_hdlr_info = {
665     gst_codec_src_uri_handler_init, NULL, NULL
666   };
667
668   g_type_add_interface_static (type, GST_TYPE_URI_HANDLER, &uri_hdlr_info);
669 }
670
671 #undef parent_class
672 #define parent_class codec_src_parent_class
673
674 typedef GstPushSrc GstCodecSrc;
675 typedef GstPushSrcClass GstCodecSrcClass;
676
677 G_DEFINE_TYPE_WITH_CODE (GstCodecSrc, gst_codec_src,
678     GST_TYPE_PUSH_SRC, gst_codec_src_init_type (g_define_type_id));
679
680 static GstFlowReturn
681 gst_codec_src_create (GstPushSrc * src, GstBuffer ** p_buf)
682 {
683   GstBuffer *buf;
684
685   buf = gst_buffer_new_and_alloc (20);
686   gst_buffer_memset (buf, 0, 0, 20);
687
688   *p_buf = buf;
689   return GST_FLOW_OK;
690 }
691
692 static GstCaps *
693 gst_codec_src_get_caps (GstBaseSrc * src, GstCaps * filter)
694 {
695   return gst_caps_new_empty_simple ("application/x-codec");
696 }
697
698 static void
699 gst_codec_src_class_init (GstCodecSrcClass * klass)
700 {
701   GstPushSrcClass *pushsrc_class = GST_PUSH_SRC_CLASS (klass);
702   GstBaseSrcClass *basesrc_class = GST_BASE_SRC_CLASS (klass);
703   static GstStaticPadTemplate src_templ = GST_STATIC_PAD_TEMPLATE ("src",
704       GST_PAD_SRC, GST_PAD_ALWAYS,
705       GST_STATIC_CAPS ("application/x-codec")
706       );
707   GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
708
709   gst_element_class_add_pad_template (element_class,
710       gst_static_pad_template_get (&src_templ));
711   gst_element_class_set_details_simple (element_class,
712       "Codec Src", "Source/Video", "yep", "me");
713
714   pushsrc_class->create = gst_codec_src_create;
715   basesrc_class->get_caps = gst_codec_src_get_caps;
716 }
717
718 static void
719 gst_codec_src_init (GstCodecSrc * src)
720 {
721 }
722
723 #endif /* GST_DISABLE_REGISTRY */
724
725
726 static Suite *
727 playbin_suite (void)
728 {
729   Suite *s = suite_create ("playbin");
730   TCase *tc_chain = tcase_create ("general");
731
732   suite_add_tcase (s, tc_chain);
733
734 #ifndef GST_DISABLE_REGISTRY
735   tcase_add_test (tc_chain, test_sink_usage_video_only_stream);
736   tcase_add_test (tc_chain, test_suburi_error_wrongproto);
737   tcase_add_test (tc_chain, test_suburi_error_invalidfile);
738   tcase_add_test (tc_chain, test_suburi_error_unknowntype);
739   tcase_add_test (tc_chain, test_missing_urisource_handler);
740   tcase_add_test (tc_chain, test_missing_suburisource_handler);
741   tcase_add_test (tc_chain, test_missing_primary_decoder);
742   tcase_add_test (tc_chain, test_refcount);
743   tcase_add_test (tc_chain, test_source_setup);
744
745   /* one day we might also want to have the following checks:
746    * tcase_add_test (tc_chain, test_missing_secondary_decoder_one_fatal);
747    * tcase_add_test (tc_chain, test_missing_secondary_decoder_two_fatal);
748    * tcase_add_test (tc_chain, test_missing_secondary_decoder_two_with_preroll);
749    */
750 #endif
751
752   return s;
753 }
754
755 GST_CHECK_MAIN (playbin);