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