gst/playback/gstdecodebin2.c: Make decodebin2 autoplug depayloaders too.
[platform/upstream/gstreamer.git] / gst / playback / gstdecodebin2.c
1 /* GStreamer
2  * Copyright (C) <2006> Edward Hervey <edward@fluendo.com>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 /**
21  * SECTION:element-decodebin2
22  * @short_description: Next-generation automatic decoding bin
23  *
24  * #GstBin that auto-magically constructs a decoding pipeline using available
25  * decoders and demuxers via auto-plugging.
26  *
27  * At this stage, decodebin2 is considered UNSTABLE. The API provided in the
28  * signals is expected to change in the near future. 
29  *
30  * To try out decodebin2, you can set the USE_DECODEBIN2 environment 
31  * variable (USE_DECODEBIN2=1 for example). This will cause playbin to use
32  * decodebin2 instead of the older decodebin for its internal auto-plugging.
33  */
34
35 #ifdef HAVE_CONFIG_H
36 #include "config.h"
37 #endif
38
39 #include <gst/gst-i18n-plugin.h>
40
41 #include <string.h>
42 #include <gst/gst.h>
43 #include <gst/pbutils/pbutils.h>
44
45 #include "gstplay-marshal.h"
46
47 /* generic templates */
48 static GstStaticPadTemplate decoder_bin_sink_template =
49 GST_STATIC_PAD_TEMPLATE ("sink",
50     GST_PAD_SINK,
51     GST_PAD_ALWAYS,
52     GST_STATIC_CAPS_ANY);
53
54 static GstStaticPadTemplate decoder_bin_src_template =
55 GST_STATIC_PAD_TEMPLATE ("src%d",
56     GST_PAD_SRC,
57     GST_PAD_SOMETIMES,
58     GST_STATIC_CAPS_ANY);
59
60 GST_DEBUG_CATEGORY_STATIC (gst_decode_bin_debug);
61 #define GST_CAT_DEFAULT gst_decode_bin_debug
62
63 typedef struct _GstDecodeGroup GstDecodeGroup;
64 typedef struct _GstDecodePad GstDecodePad;
65 typedef struct _GstDecodeBin GstDecodeBin;
66 typedef struct _GstDecodeBin GstDecodeBin2;
67 typedef struct _GstDecodeBinClass GstDecodeBinClass;
68
69 #define GST_TYPE_DECODE_BIN             (gst_decode_bin_get_type())
70 #define GST_DECODE_BIN_CAST(obj)        ((GstDecodeBin*)(obj))
71 #define GST_DECODE_BIN(obj)             (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_DECODE_BIN,GstDecodeBin))
72 #define GST_DECODE_BIN_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_DECODE_BIN,GstDecodeBinClass))
73 #define GST_IS_DECODE_BIN(obj)          (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_DECODE_BIN))
74 #define GST_IS_DECODE_BIN_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_DECODE_BIN))
75
76 /**
77  *  GstDecodeBin2:
78  *
79  *  The opaque #DecodeBin2 data structure
80  */
81 struct _GstDecodeBin
82 {
83   GstBin bin;                   /* we extend GstBin */
84
85   GstElement *typefind;         /* this holds the typefind object */
86   GstElement *fakesink;
87
88   GMutex *lock;                 /* Protects activegroup and groups */
89   GstDecodeGroup *activegroup;  /* group currently active */
90   GList *groups;                /* List of non-active GstDecodeGroups, sorted in
91                                  * order of creation. */
92   GList *oldgroups;             /* List of no-longer-used GstDecodeGroups. 
93                                  * Should be freed in dispose */
94   gint nbpads;                  /* unique identifier for source pads */
95   GstCaps *caps;                /* caps on which to stop decoding */
96
97   GList *factories;             /* factories we can use for selecting elements */
98 };
99
100 struct _GstDecodeBinClass
101 {
102   GstBinClass parent_class;
103
104   /* signal we fire when a new pad has been decoded into raw audio/video */
105   void (*new_decoded_pad) (GstElement * element, GstPad * pad, gboolean last);
106   /* signal we fire when a pad has been removed */
107   void (*removed_decoded_pad) (GstElement * element, GstPad * pad);
108   /* signal fired when we found a pad that we cannot decode */
109   void (*unknown_type) (GstElement * element, GstPad * pad, GstCaps * caps);
110   /* signal fired to know if we continue trying to decode the given caps */
111     gboolean (*autoplug_continue) (GstElement * element, GstCaps * caps);
112   /* signal fired to reorder the proposed list of factories */
113     gboolean (*autoplug_sort) (GstElement * element, GstCaps * caps,
114       GList ** list);
115 };
116
117 /* signals */
118 enum
119 {
120   SIGNAL_NEW_DECODED_PAD,
121   SIGNAL_REMOVED_DECODED_PAD,
122   SIGNAL_UNKNOWN_TYPE,
123   SIGNAL_AUTOPLUG_CONTINUE,
124   SIGNAL_AUTOPLUG_SORT,
125   LAST_SIGNAL
126 };
127
128 /* Properties */
129 enum
130 {
131   PROP_0,
132   PROP_CAPS,
133 };
134
135 static GstBinClass *parent_class;
136 static guint gst_decode_bin_signals[LAST_SIGNAL] = { 0 };
137
138 static const GstElementDetails gst_decode_bin_details =
139 GST_ELEMENT_DETAILS ("Decoder Bin",
140     "Generic/Bin/Decoder",
141     "Autoplug and decode to raw media",
142     "Edward Hervey <edward@fluendo.com>");
143
144
145 static gboolean add_fakesink (GstDecodeBin * decode_bin);
146 static void remove_fakesink (GstDecodeBin * decode_bin);
147
148 static void type_found (GstElement * typefind, guint probability,
149     GstCaps * caps, GstDecodeBin * decode_bin);
150
151 static gboolean gst_decode_bin_autoplug_continue (GstElement * element,
152     GstCaps * caps);
153 static gboolean gst_decode_bin_autoplug_sort (GstElement * element,
154     GstCaps * caps, GList ** list);
155 static void gst_decode_bin_set_property (GObject * object, guint prop_id,
156     const GValue * value, GParamSpec * pspec);
157 static void gst_decode_bin_get_property (GObject * object, guint prop_id,
158     GValue * value, GParamSpec * pspec);
159 static void gst_decode_bin_set_caps (GstDecodeBin * dbin, GstCaps * caps);
160 static GstCaps *gst_decode_bin_get_caps (GstDecodeBin * dbin);
161
162 static GstPad *find_sink_pad (GstElement * element);
163 static GstStateChangeReturn gst_decode_bin_change_state (GstElement * element,
164     GstStateChange transition);
165
166 #define DECODE_BIN_LOCK(dbin) G_STMT_START {                            \
167     GST_LOG_OBJECT (dbin,                                               \
168                     "locking from thread %p",                           \
169                     g_thread_self ());                                  \
170     g_mutex_lock (GST_DECODE_BIN_CAST(dbin)->lock);                     \
171     GST_LOG_OBJECT (dbin,                                               \
172                     "locked from thread %p",                            \
173                     g_thread_self ());                                  \
174 } G_STMT_END
175
176 #define DECODE_BIN_UNLOCK(dbin) G_STMT_START {                          \
177     GST_LOG_OBJECT (dbin,                                               \
178                     "unlocking from thread %p",                         \
179                     g_thread_self ());                                  \
180     g_mutex_unlock (GST_DECODE_BIN_CAST(dbin)->lock);                   \
181 } G_STMT_END
182
183 /* GstDecodeGroup
184  *
185  * Streams belonging to the same group/chain of a media file
186  *
187  */
188
189 struct _GstDecodeGroup
190 {
191   GstDecodeBin *dbin;
192   GMutex *lock;
193   GstElement *multiqueue;
194   gboolean exposed;             /* TRUE if this group is exposed */
195   gboolean drained;             /* TRUE if EOS went throug all endpads */
196   gboolean blocked;             /* TRUE if all endpads are blocked */
197   gboolean complete;            /* TRUE if we are not expecting anymore streams 
198                                  * on this group */
199   gulong overrunsig;
200   gulong underrunsig;
201   guint nbdynamic;              /* number of dynamic pads in the group. */
202
203   GList *endpads;               /* List of GstDecodePad of source pads to be exposed */
204   GList *ghosts;                /* List of GstGhostPad for the endpads */
205 };
206
207 #define GROUP_MUTEX_LOCK(group) G_STMT_START {                          \
208     GST_LOG_OBJECT (group->dbin,                                        \
209                     "locking group %p from thread %p",                  \
210                     group, g_thread_self ());                           \
211     g_mutex_lock (group->lock);                                         \
212     GST_LOG_OBJECT (group->dbin,                                        \
213                     "locked group %p from thread %p",                   \
214                     group, g_thread_self ());                           \
215 } G_STMT_END
216
217 #define GROUP_MUTEX_UNLOCK(group) G_STMT_START {                        \
218     GST_LOG_OBJECT (group->dbin,                                        \
219                     "unlocking group %p from thread %p",                \
220                     group, g_thread_self ());                           \
221     g_mutex_unlock (group->lock);                                       \
222 } G_STMT_END
223
224
225 static GstDecodeGroup *gst_decode_group_new (GstDecodeBin * decode_bin);
226 static GstPad *gst_decode_group_control_demuxer_pad (GstDecodeGroup * group,
227     GstPad * pad);
228 static gboolean gst_decode_group_control_source_pad (GstDecodeGroup * group,
229     GstPad * pad);
230 static gboolean gst_decode_group_expose (GstDecodeGroup * group);
231 static void gst_decode_group_check_if_blocked (GstDecodeGroup * group);
232 static void gst_decode_group_set_complete (GstDecodeGroup * group);
233 static void gst_decode_group_hide (GstDecodeGroup * group);
234 static void gst_decode_group_free (GstDecodeGroup * group);
235
236 /* GstDecodePad
237  *
238  * GstPad private used for source pads of groups
239  */
240
241 struct _GstDecodePad
242 {
243   GstPad *pad;
244   GstDecodeGroup *group;
245   gboolean blocked;
246   gboolean drained;
247 };
248
249 static GstDecodePad *gst_decode_pad_new (GstDecodeGroup * group, GstPad * pad,
250     gboolean block);
251 static void source_pad_blocked_cb (GstPad * pad, gboolean blocked,
252     GstDecodePad * dpad);
253
254 /* TempPadStruct
255  * Internal structure used for pads which have more than one structure.
256  */
257 typedef struct _TempPadStruct
258 {
259   GstDecodeBin *dbin;
260   GstDecodeGroup *group;
261 } TempPadStruct;
262
263 /********************************
264  * Standard GObject boilerplate *
265  ********************************/
266
267 static void gst_decode_bin_class_init (GstDecodeBinClass * klass);
268 static void gst_decode_bin_init (GstDecodeBin * decode_bin);
269 static void gst_decode_bin_dispose (GObject * object);
270 static void gst_decode_bin_finalize (GObject * object);
271
272 static GType
273 gst_decode_bin_get_type (void)
274 {
275   static GType gst_decode_bin_type = 0;
276
277   if (!gst_decode_bin_type) {
278     static const GTypeInfo gst_decode_bin_info = {
279       sizeof (GstDecodeBinClass),
280       NULL,
281       NULL,
282       (GClassInitFunc) gst_decode_bin_class_init,
283       NULL,
284       NULL,
285       sizeof (GstDecodeBin),
286       0,
287       (GInstanceInitFunc) gst_decode_bin_init,
288       NULL
289     };
290
291     gst_decode_bin_type =
292         g_type_register_static (GST_TYPE_BIN, "GstDecodeBin2",
293         &gst_decode_bin_info, 0);
294   }
295
296   return gst_decode_bin_type;
297 }
298
299 static gboolean
300 _gst_boolean_accumulator (GSignalInvocationHint * ihint,
301     GValue * return_accu, const GValue * handler_return, gpointer dummy)
302 {
303   gboolean myboolean;
304
305   myboolean = g_value_get_boolean (handler_return);
306   if (!(ihint->run_type & G_SIGNAL_RUN_CLEANUP))
307     g_value_set_boolean (return_accu, myboolean);
308
309   /* stop emission if FALSE */
310   return myboolean;
311 }
312
313 static void
314 gst_decode_bin_class_init (GstDecodeBinClass * klass)
315 {
316   GObjectClass *gobject_klass;
317   GstElementClass *gstelement_klass;
318   GstBinClass *gstbin_klass;
319
320   gobject_klass = (GObjectClass *) klass;
321   gstelement_klass = (GstElementClass *) klass;
322   gstbin_klass = (GstBinClass *) klass;
323
324   parent_class = g_type_class_peek_parent (klass);
325
326   gobject_klass->dispose = GST_DEBUG_FUNCPTR (gst_decode_bin_dispose);
327   gobject_klass->finalize = GST_DEBUG_FUNCPTR (gst_decode_bin_finalize);
328   gobject_klass->set_property = GST_DEBUG_FUNCPTR (gst_decode_bin_set_property);
329   gobject_klass->get_property = GST_DEBUG_FUNCPTR (gst_decode_bin_get_property);
330
331   /**
332    * GstDecodeBin2::new-decoded-pad:
333    * @pad: the newly created pad
334    * @islast: #TRUE if this is the last pad to be added. Deprecated.
335    *
336    * This signal gets emitted as soon as a new pad of the same type as one of
337    * the valid 'raw' types is added.
338    */
339
340   gst_decode_bin_signals[SIGNAL_NEW_DECODED_PAD] =
341       g_signal_new ("new-decoded-pad", G_TYPE_FROM_CLASS (klass),
342       G_SIGNAL_RUN_LAST,
343       G_STRUCT_OFFSET (GstDecodeBinClass, new_decoded_pad), NULL, NULL,
344       gst_play_marshal_VOID__OBJECT_BOOLEAN, G_TYPE_NONE, 2, GST_TYPE_PAD,
345       G_TYPE_BOOLEAN);
346
347   /**
348    * GstDecodeBin2::removed-decoded-pad:
349    * @pad: the pad that was removed
350    *
351    * This signal is emitted when a 'final' caps pad has been removed.
352    */
353
354   gst_decode_bin_signals[SIGNAL_REMOVED_DECODED_PAD] =
355       g_signal_new ("removed-decoded-pad", G_TYPE_FROM_CLASS (klass),
356       G_SIGNAL_RUN_LAST,
357       G_STRUCT_OFFSET (GstDecodeBinClass, removed_decoded_pad), NULL, NULL,
358       gst_marshal_VOID__OBJECT, G_TYPE_NONE, 1, GST_TYPE_PAD);
359
360   /**
361    * GstDecodeBin2::unknown-type:
362    * @pad: the new pad containing caps that cannot be resolved to a 'final' stream type.
363    * @caps: the #GstCaps of the pad that cannot be resolved.
364    *
365    * This signal is emitted when a pad for which there is no further possible
366    * decoding is added to the decodebin.
367    */
368
369   gst_decode_bin_signals[SIGNAL_UNKNOWN_TYPE] =
370       g_signal_new ("unknown-type", G_TYPE_FROM_CLASS (klass),
371       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstDecodeBinClass, unknown_type),
372       NULL, NULL, gst_marshal_VOID__OBJECT_OBJECT, G_TYPE_NONE, 2,
373       GST_TYPE_PAD, GST_TYPE_CAPS);
374
375   /**
376    * GstDecodeBin2::autoplug-continue:
377    * @caps: The #GstCaps found.
378    *
379    * This signal is emitted whenever decodebin2 finds a new stream. It is
380    * emitted before looking for any elements that can handle that stream.
381    *
382    * Returns: #TRUE if you wish decodebin2 to look for elements that can
383    * handle the given @caps. If #FALSE, those caps will be considered as
384    * final and the pad will be exposed as such (see 'new-decoded-pad'
385    * signal).
386    */
387
388   gst_decode_bin_signals[SIGNAL_AUTOPLUG_CONTINUE] =
389       g_signal_new ("autoplug-continue", G_TYPE_FROM_CLASS (klass),
390       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstDecodeBinClass, autoplug_continue),
391       _gst_boolean_accumulator, NULL, gst_play_marshal_BOOLEAN__OBJECT,
392       G_TYPE_BOOLEAN, 1, GST_TYPE_CAPS);
393
394   /**
395    * GstDecodeBin2::autoplug-sort:
396    * @caps: The #GstCaps.
397    * @factories: A #GList of possible #GstElementFactory to use.
398    *
399    * This signal is emitted once decodebin2 has found all the possible
400    * #GstElementFactory that can be used to handle the given @caps.
401    *
402    * UNSTABLE API. Will change soon.
403    *
404    * Returns: #TRUE if you wish decodebin2 to start trying to decode
405    * the given @caps with the list of factories. #FALSE if you do not want
406    * these #GstCaps, if so the pad will be exposed as unknown (see
407    * 'unknown-type' signal).
408    */
409
410   gst_decode_bin_signals[SIGNAL_AUTOPLUG_SORT] =
411       g_signal_new ("autoplug-sort", G_TYPE_FROM_CLASS (klass),
412       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstDecodeBinClass, autoplug_sort),
413       _gst_boolean_accumulator, NULL, gst_play_marshal_BOOLEAN__OBJECT_POINTER,
414       G_TYPE_BOOLEAN, 2, GST_TYPE_CAPS, G_TYPE_POINTER);
415
416   g_object_class_install_property (gobject_klass, PROP_CAPS,
417       g_param_spec_boxed ("caps", "Caps", "The caps on which to stop decoding.",
418           GST_TYPE_CAPS, G_PARAM_READWRITE));
419
420   klass->autoplug_continue =
421       GST_DEBUG_FUNCPTR (gst_decode_bin_autoplug_continue);
422   klass->autoplug_sort = GST_DEBUG_FUNCPTR (gst_decode_bin_autoplug_sort);
423
424   gst_element_class_add_pad_template (gstelement_klass,
425       gst_static_pad_template_get (&decoder_bin_sink_template));
426   gst_element_class_add_pad_template (gstelement_klass,
427       gst_static_pad_template_get (&decoder_bin_src_template));
428
429   gst_element_class_set_details (gstelement_klass, &gst_decode_bin_details);
430
431   gstelement_klass->change_state =
432       GST_DEBUG_FUNCPTR (gst_decode_bin_change_state);
433 }
434
435 /* the filter function for selecting the elements we can use in
436  * autoplugging */
437 static gboolean
438 gst_decode_bin_factory_filter (GstPluginFeature * feature,
439     GstDecodeBin * decode_bin)
440 {
441   guint rank;
442   const gchar *klass;
443
444   /* we only care about element factories */
445   if (!GST_IS_ELEMENT_FACTORY (feature))
446     return FALSE;
447
448   klass = gst_element_factory_get_klass (GST_ELEMENT_FACTORY (feature));
449   /* only demuxers, decoders and parsers can play */
450   if (strstr (klass, "Demux") == NULL &&
451       strstr (klass, "Decoder") == NULL && strstr (klass, "Parse") == NULL &&
452       strstr (klass, "Depayloader") == NULL) {
453     return FALSE;
454   }
455
456   /* only select elements with autoplugging rank */
457   rank = gst_plugin_feature_get_rank (feature);
458   if (rank < GST_RANK_MARGINAL)
459     return FALSE;
460
461   return TRUE;
462 }
463
464 /* function used to sort element features */
465 static gint
466 compare_ranks (GstPluginFeature * f1, GstPluginFeature * f2)
467 {
468   gint diff;
469   const gchar *rname1, *rname2;
470
471   diff = gst_plugin_feature_get_rank (f2) - gst_plugin_feature_get_rank (f1);
472   if (diff != 0)
473     return diff;
474
475   rname1 = gst_plugin_feature_get_name (f1);
476   rname2 = gst_plugin_feature_get_name (f2);
477
478   diff = strcmp (rname2, rname1);
479
480   return diff;
481 }
482
483 static void
484 print_feature (GstPluginFeature * feature)
485 {
486   const gchar *rname;
487
488   rname = gst_plugin_feature_get_name (feature);
489
490   GST_DEBUG ("%s", rname);
491 }
492
493 static void
494 gst_decode_bin_init (GstDecodeBin * decode_bin)
495 {
496   GList *factories;
497
498   /* first filter out the interesting element factories */
499   factories = gst_default_registry_feature_filter (
500       (GstPluginFeatureFilter) gst_decode_bin_factory_filter,
501       FALSE, decode_bin);
502
503   /* sort them according to their ranks */
504   decode_bin->factories = g_list_sort (factories, (GCompareFunc) compare_ranks);
505   /* do some debugging */
506   g_list_foreach (decode_bin->factories, (GFunc) print_feature, NULL);
507
508
509   /* we create the typefind element only once */
510   decode_bin->typefind = gst_element_factory_make ("typefind", "typefind");
511   if (!decode_bin->typefind) {
512     g_warning ("can't find typefind element, decodebin will not work");
513   } else {
514     GstPad *pad;
515     GstPad *gpad;
516
517     /* add the typefind element */
518     if (!gst_bin_add (GST_BIN (decode_bin), decode_bin->typefind)) {
519       g_warning ("Could not add typefind element, decodebin will not work");
520       gst_object_unref (decode_bin->typefind);
521       decode_bin->typefind = NULL;
522     }
523
524     /* get the sinkpad */
525     pad = gst_element_get_pad (decode_bin->typefind, "sink");
526
527     /* ghost the sink pad to ourself */
528     gpad = gst_ghost_pad_new ("sink", pad);
529     gst_pad_set_active (gpad, TRUE);
530     gst_element_add_pad (GST_ELEMENT (decode_bin), gpad);
531
532     gst_object_unref (pad);
533
534     /* connect a signal to find out when the typefind element found
535      * a type */
536     g_signal_connect (G_OBJECT (decode_bin->typefind), "have_type",
537         G_CALLBACK (type_found), decode_bin);
538   }
539
540   decode_bin->lock = g_mutex_new ();
541   decode_bin->activegroup = NULL;
542   decode_bin->groups = NULL;
543
544   decode_bin->caps =
545       gst_caps_from_string ("video/x-raw-yuv;video/x-raw-rgb;video/x-raw-gray;"
546       "audio/x-raw-int;audio/x-raw-float;" "text/plain;text/x-pango-markup");
547
548   add_fakesink (decode_bin);
549
550   /* FILLME */
551 }
552
553 static void
554 gst_decode_bin_dispose (GObject * object)
555 {
556   GstDecodeBin *decode_bin;
557   GList *tmp;
558
559   decode_bin = GST_DECODE_BIN (object);
560
561   if (decode_bin->factories)
562     gst_plugin_feature_list_free (decode_bin->factories);
563   decode_bin->factories = NULL;
564
565   if (decode_bin->activegroup) {
566     gst_decode_group_free (decode_bin->activegroup);
567     decode_bin->activegroup = NULL;
568   }
569
570   /* remove groups */
571   for (tmp = decode_bin->groups; tmp; tmp = g_list_next (tmp)) {
572     GstDecodeGroup *group = (GstDecodeGroup *) tmp->data;
573
574     gst_decode_group_free (group);
575   }
576   g_list_free (decode_bin->groups);
577   decode_bin->groups = NULL;
578
579   for (tmp = decode_bin->oldgroups; tmp; tmp = g_list_next (tmp)) {
580     GstDecodeGroup *group = (GstDecodeGroup *) tmp->data;
581
582     gst_decode_group_free (group);
583   }
584   g_list_free (decode_bin->oldgroups);
585   decode_bin->oldgroups = NULL;
586
587   if (decode_bin->caps)
588     gst_caps_unref (decode_bin->caps);
589   decode_bin->caps = NULL;
590   remove_fakesink (decode_bin);
591
592   G_OBJECT_CLASS (parent_class)->dispose (object);
593 }
594
595 static void
596 gst_decode_bin_finalize (GObject * object)
597 {
598   GstDecodeBin *decode_bin;
599
600   decode_bin = GST_DECODE_BIN (object);
601
602   if (decode_bin->lock) {
603     g_mutex_free (decode_bin->lock);
604     decode_bin->lock = NULL;
605   }
606
607   G_OBJECT_CLASS (parent_class)->finalize (object);
608 }
609
610 static void
611 gst_decode_bin_set_property (GObject * object, guint prop_id,
612     const GValue * value, GParamSpec * pspec)
613 {
614   GstDecodeBin *dbin;
615
616   dbin = GST_DECODE_BIN (object);
617
618   switch (prop_id) {
619     case PROP_CAPS:
620       gst_decode_bin_set_caps (dbin, (GstCaps *) g_value_dup_boxed (value));
621       break;
622     default:
623       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
624       break;
625   }
626 }
627
628 static void
629 gst_decode_bin_get_property (GObject * object, guint prop_id,
630     GValue * value, GParamSpec * pspec)
631 {
632   GstDecodeBin *dbin;
633
634   dbin = GST_DECODE_BIN (object);
635   switch (prop_id) {
636     case PROP_CAPS:{
637       g_value_take_boxed (value, gst_decode_bin_get_caps (dbin));
638       break;
639     }
640     default:
641       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
642       break;
643   }
644
645 }
646
647 /* _set_caps
648  * Changes the caps on which decodebin will stop decoding.
649  * Will unref the previously set one. The refcount of the given caps will be
650  * taken.
651  * @caps can be NULL.
652  *
653  * MT-safe
654  */
655
656 static void
657 gst_decode_bin_set_caps (GstDecodeBin * dbin, GstCaps * caps)
658 {
659   GST_DEBUG_OBJECT (dbin, "Setting new caps: %" GST_PTR_FORMAT, caps);
660
661   DECODE_BIN_LOCK (dbin);
662   if (dbin->caps)
663     gst_caps_unref (dbin->caps);
664   dbin->caps = caps;
665   DECODE_BIN_UNLOCK (dbin);
666 }
667
668 /* _get_caps
669  * Returns the currently configured caps on which decodebin will stop decoding.
670  * The returned caps (if not NULL), will have its refcount incremented.
671  *
672  * MT-safe
673  */
674
675 static GstCaps *
676 gst_decode_bin_get_caps (GstDecodeBin * dbin)
677 {
678   GstCaps *caps;
679
680   GST_DEBUG_OBJECT (dbin, "Getting currently set caps");
681
682   DECODE_BIN_LOCK (dbin);
683   caps = dbin->caps;
684   if (caps)
685     gst_caps_ref (caps);
686   DECODE_BIN_UNLOCK (dbin);
687
688   return caps;
689 }
690
691 /*****
692  * Default autoplug signal handlers
693  *****/
694
695 static gboolean
696 gst_decode_bin_autoplug_continue (GstElement * element, GstCaps * caps)
697 {
698   return TRUE;
699 }
700
701 static gboolean
702 gst_decode_bin_autoplug_sort (GstElement * element, GstCaps * caps,
703     GList ** list)
704 {
705   return TRUE;
706 }
707
708
709
710 /********
711  * Discovery methods
712  *****/
713
714 static gboolean are_raw_caps (GstDecodeBin * dbin, GstCaps * caps);
715 static gboolean is_demuxer_element (GstElement * srcelement);
716 static GList *find_compatibles (GstDecodeBin * decode_bin,
717     const GstCaps * caps);
718
719 static gboolean connect_pad (GstDecodeBin * dbin, GstElement * src,
720     GstPad * pad, GList * factories, GstDecodeGroup * group);
721 static gboolean connect_element (GstDecodeBin * dbin, GstElement * element,
722     GstDecodeGroup * group);
723 static void expose_pad (GstDecodeBin * dbin, GstElement * src, GstPad * pad,
724     GstDecodeGroup * group);
725
726 static void pad_added_group_cb (GstElement * element, GstPad * pad,
727     GstDecodeGroup * group);
728 static void pad_removed_group_cb (GstElement * element, GstPad * pad,
729     GstDecodeGroup * group);
730 static void no_more_pads_group_cb (GstElement * element,
731     GstDecodeGroup * group);
732 static void pad_added_cb (GstElement * element, GstPad * pad,
733     GstDecodeBin * dbin);
734 static void pad_removed_cb (GstElement * element, GstPad * pad,
735     GstDecodeBin * dbin);
736 static void no_more_pads_cb (GstElement * element, GstDecodeBin * dbin);
737
738 static GstDecodeGroup *get_current_group (GstDecodeBin * dbin);
739
740 static void
741 analyze_new_pad (GstDecodeBin * dbin, GstElement * src, GstPad * pad,
742     GstCaps * caps, GstDecodeGroup * group)
743 {
744   gboolean apcontinue = TRUE;
745   GList *factories = NULL;
746   gboolean apsort = TRUE;
747
748   GST_DEBUG_OBJECT (dbin, "Pad %s:%s caps:%" GST_PTR_FORMAT,
749       GST_DEBUG_PAD_NAME (pad), caps);
750
751   if ((caps == NULL) || gst_caps_is_empty (caps))
752     goto unknown_type;
753
754   if (gst_caps_is_any (caps))
755     goto any_caps;
756
757   /* 1. Emit 'autoplug-continue' */
758   g_signal_emit (G_OBJECT (dbin),
759       gst_decode_bin_signals[SIGNAL_AUTOPLUG_CONTINUE], 0, caps, &apcontinue);
760
761   /* 1.a if autoplug-continue is FALSE or caps is a raw format, goto pad_is_final */
762   if ((!apcontinue) || are_raw_caps (dbin, caps))
763     goto expose_pad;
764
765   /* 1.b else if there's no compatible factory or 'autoplug-sort' returned FALSE, goto pad_not_used */
766   if ((factories = find_compatibles (dbin, caps))) {
767     /* emit autoplug-sort */
768     g_signal_emit (G_OBJECT (dbin),
769         gst_decode_bin_signals[SIGNAL_AUTOPLUG_SORT],
770         0, caps, &factories, &apsort);
771     if (!apsort) {
772       g_list_free (factories);
773       /* User doesn't want that pad */
774       goto pad_not_wanted;
775     }
776   } else {
777     /* no compatible factories */
778     goto unknown_type;
779   }
780
781   /* 1.c else goto pad_is_valid */
782   GST_LOG_OBJECT (pad, "Let's continue discovery on this pad");
783
784   connect_pad (dbin, src, pad, factories, group);
785   g_list_free (factories);
786
787   return;
788
789 expose_pad:
790   {
791     GST_LOG_OBJECT (dbin, "Pad is final. autoplug-continue:%d", apcontinue);
792     expose_pad (dbin, src, pad, group);
793     return;
794   }
795
796 pad_not_wanted:
797   {
798     GST_LOG_OBJECT (pad, "User doesn't want this pad, stopping discovery");
799     return;
800   }
801
802 unknown_type:
803   {
804     GST_LOG_OBJECT (pad, "Unknown type, firing signal");
805     g_signal_emit (G_OBJECT (dbin),
806         gst_decode_bin_signals[SIGNAL_UNKNOWN_TYPE], 0, pad, caps);
807
808     /* Check if there are no pending groups, if so, remove fakesink */
809     if (dbin->groups == NULL)
810       remove_fakesink (dbin);
811
812     gst_element_post_message (GST_ELEMENT_CAST (dbin),
813         gst_missing_decoder_message_new (GST_ELEMENT_CAST (dbin), caps));
814     return;
815   }
816
817 any_caps:
818   {
819     GST_WARNING_OBJECT (pad,
820         "pad has ANY caps, not able to autoplug to anything");
821     /* FIXME : connect to caps notification */
822     return;
823   }
824 }
825
826
827 /* connect_pad:
828  *
829  * Try to connect the given pad to an element created from one of the factories,
830  * and recursively.
831  *
832  * Returns TRUE if an element was properly created and linked
833  */
834
835 static gboolean
836 connect_pad (GstDecodeBin * dbin, GstElement * src, GstPad * pad,
837     GList * factories, GstDecodeGroup * group)
838 {
839   gboolean res = FALSE;
840   GList *tmp;
841   GstPad *mqpad = NULL;
842
843   g_return_val_if_fail (factories != NULL, FALSE);
844   GST_DEBUG_OBJECT (dbin, "pad %s:%s , group:%p",
845       GST_DEBUG_PAD_NAME (pad), group);
846
847   /* 1. is element demuxer or parser */
848   if (is_demuxer_element (src)) {
849     GST_LOG_OBJECT (src, "is a demuxer, connecting the pad through multiqueue");
850
851     if (!group)
852       if (!(group = get_current_group (dbin))) {
853         group = gst_decode_group_new (dbin);
854         DECODE_BIN_LOCK (dbin);
855         dbin->groups = g_list_append (dbin->groups, group);
856         DECODE_BIN_UNLOCK (dbin);
857       }
858
859     if (!(mqpad = gst_decode_group_control_demuxer_pad (group, pad)))
860       goto beach;
861     pad = mqpad;
862   }
863
864   /* 2. Try to create an element and link to it */
865   for (tmp = factories; tmp; tmp = g_list_next (tmp)) {
866     GstElementFactory *factory = (GstElementFactory *) tmp->data;
867     GstElement *element;
868     GstPad *sinkpad;
869
870     /* 2.1. Try to create an element */
871     if ((element = gst_element_factory_create (factory, NULL)) == NULL) {
872       GST_WARNING_OBJECT (dbin, "Could not create an element from %s",
873           gst_plugin_feature_get_name (GST_PLUGIN_FEATURE (factory)));
874       continue;
875     }
876
877     /* 2.3. Find its sink pad */
878     if (!(sinkpad = find_sink_pad (element))) {
879       GST_WARNING_OBJECT (dbin, "Element %s doesn't have a sink pad",
880           GST_ELEMENT_NAME (element));
881       gst_object_unref (element);
882       continue;
883     }
884
885     /* 2.4 add it ... */
886     if (!(gst_bin_add (GST_BIN (dbin), element))) {
887       GST_WARNING_OBJECT (dbin, "Couldn't add %s to the bin",
888           GST_ELEMENT_NAME (element));
889       gst_object_unref (sinkpad);
890       gst_object_unref (element);
891       continue;
892     }
893
894     /* ... activate it ... */
895     if ((gst_element_set_state (element,
896                 GST_STATE_READY)) == GST_STATE_CHANGE_FAILURE) {
897       GST_WARNING_OBJECT (dbin, "Couldn't set %s to READY",
898           GST_ELEMENT_NAME (element));
899       gst_object_unref (sinkpad);
900       gst_bin_remove (GST_BIN (dbin), element);
901       continue;
902     }
903
904     /* 2.5 ...and try to link */
905     if ((gst_pad_link (pad, sinkpad)) != GST_PAD_LINK_OK) {
906       GST_WARNING_OBJECT (dbin, "Link failed on pad %s:%s",
907           GST_DEBUG_PAD_NAME (sinkpad));
908       gst_element_set_state (element, GST_STATE_NULL);
909       gst_object_unref (sinkpad);
910       gst_bin_remove (GST_BIN (dbin), element);
911       continue;
912     }
913     gst_object_unref (sinkpad);
914     GST_LOG_OBJECT (dbin, "linked on pad %s:%s", GST_DEBUG_PAD_NAME (pad));
915
916     /* link this element further */
917     connect_element (dbin, element, group);
918
919     /* Bring the element to the state of the parent */
920     if ((gst_element_set_state (element,
921                 GST_STATE_PAUSED)) == GST_STATE_CHANGE_FAILURE) {
922       GST_WARNING_OBJECT (dbin, "Couldn't set %s to PAUSED",
923           GST_ELEMENT_NAME (element));
924       gst_element_set_state (element, GST_STATE_NULL);
925       gst_bin_remove (GST_BIN (dbin), element);
926       continue;
927     }
928
929     res = TRUE;
930     break;
931   }
932
933   if (mqpad)
934     gst_object_unref (mqpad);
935
936 beach:
937   return res;
938 }
939
940 static gboolean
941 connect_element (GstDecodeBin * dbin, GstElement * element,
942     GstDecodeGroup * group)
943 {
944   GList *pads;
945   gboolean res = TRUE;
946   gboolean dynamic = FALSE;
947   GList *to_connect = NULL;
948
949   GST_DEBUG_OBJECT (dbin, "Attempting to connect element %s [group:%p] further",
950       GST_ELEMENT_NAME (element), group);
951
952   /* 1. Loop over pad templates, grabbing existing pads along the way */
953   for (pads = GST_ELEMENT_GET_CLASS (element)->padtemplates; pads;
954       pads = g_list_next (pads)) {
955     GstPadTemplate *templ = GST_PAD_TEMPLATE (pads->data);
956     const gchar *templ_name;
957
958     /* we are only interested in source pads */
959     if (GST_PAD_TEMPLATE_DIRECTION (templ) != GST_PAD_SRC)
960       continue;
961
962     templ_name = GST_PAD_TEMPLATE_NAME_TEMPLATE (templ);
963     GST_DEBUG_OBJECT (dbin, "got a source pad template %s", templ_name);
964
965     /* figure out what kind of pad this is */
966     switch (GST_PAD_TEMPLATE_PRESENCE (templ)) {
967       case GST_PAD_ALWAYS:
968       {
969         /* get the pad that we need to autoplug */
970         GstPad *pad = gst_element_get_pad (element, templ_name);
971
972         if (pad) {
973           GST_DEBUG_OBJECT (dbin, "got the pad for always template %s",
974               templ_name);
975           /* here is the pad, we need to autoplug it */
976           to_connect = g_list_prepend (to_connect, pad);
977         } else {
978           /* strange, pad is marked as always but it's not
979            * there. Fix the element */
980           GST_WARNING_OBJECT (dbin,
981               "could not get the pad for always template %s", templ_name);
982         }
983         break;
984       }
985       case GST_PAD_SOMETIMES:
986       {
987         /* try to get the pad to see if it is already created or
988          * not */
989         GstPad *pad = gst_element_get_pad (element, templ_name);
990
991         if (pad) {
992           GST_DEBUG_OBJECT (dbin, "got the pad for sometimes template %s",
993               templ_name);
994           /* the pad is created, we need to autoplug it */
995           to_connect = g_list_prepend (to_connect, pad);
996         } else {
997           GST_DEBUG_OBJECT (dbin,
998               "did not get the sometimes pad of template %s", templ_name);
999           /* we have an element that will create dynamic pads */
1000           dynamic = TRUE;
1001         }
1002         break;
1003       }
1004       case GST_PAD_REQUEST:
1005         /* ignore request pads */
1006         GST_DEBUG_OBJECT (dbin, "ignoring request padtemplate %s", templ_name);
1007         break;
1008     }
1009   }
1010
1011   /* 2. if there are more potential pads, connect to relevent signals */
1012   if (dynamic) {
1013     if (group) {
1014       GST_LOG ("Adding signals to element %s in group %p",
1015           GST_ELEMENT_NAME (element), group);
1016       GROUP_MUTEX_LOCK (group);
1017       group->nbdynamic++;
1018       GST_LOG ("Group %p has now %d dynamic elements", group, group->nbdynamic);
1019       GROUP_MUTEX_UNLOCK (group);
1020       g_signal_connect (G_OBJECT (element), "pad-added",
1021           G_CALLBACK (pad_added_group_cb), group);
1022       g_signal_connect (G_OBJECT (element), "pad-removed",
1023           G_CALLBACK (pad_removed_group_cb), group);
1024       g_signal_connect (G_OBJECT (element), "no-more-pads",
1025           G_CALLBACK (no_more_pads_group_cb), group);
1026     } else {
1027       /* This is a non-grouped element, the handlers are different */
1028       g_signal_connect (G_OBJECT (element), "pad-added",
1029           G_CALLBACK (pad_added_cb), dbin);
1030       g_signal_connect (G_OBJECT (element), "pad-removed",
1031           G_CALLBACK (pad_removed_cb), dbin);
1032       g_signal_connect (G_OBJECT (element), "no-more-pads",
1033           G_CALLBACK (no_more_pads_cb), dbin);
1034     }
1035   }
1036
1037   /* 3. for every available pad, connect it */
1038   for (pads = to_connect; pads; pads = g_list_next (pads)) {
1039     GstPad *pad = GST_PAD_CAST (pads->data);
1040     GstCaps *caps;
1041
1042     caps = gst_pad_get_caps (pad);
1043     analyze_new_pad (dbin, element, pad, caps, group);
1044     if (caps)
1045       gst_caps_unref (caps);
1046
1047     gst_object_unref (pad);
1048   }
1049   g_list_free (to_connect);
1050
1051   return res;
1052 }
1053
1054 /* expose_pad:
1055  *
1056  * Expose the given pad on the group as a decoded pad.
1057  * If group is NULL, a GstDecodeGroup will be created and setup properly.
1058  */
1059 static void
1060 expose_pad (GstDecodeBin * dbin, GstElement * src, GstPad * pad,
1061     GstDecodeGroup * group)
1062 {
1063   gboolean newgroup = FALSE;
1064   gboolean isdemux;
1065   GstPad *mqpad = NULL;
1066
1067   GST_DEBUG_OBJECT (dbin, "pad %s:%s, group:%p",
1068       GST_DEBUG_PAD_NAME (pad), group);
1069
1070   if (!group)
1071     if (!(group = get_current_group (dbin))) {
1072       group = gst_decode_group_new (dbin);
1073       DECODE_BIN_LOCK (dbin);
1074       dbin->groups = g_list_append (dbin->groups, group);
1075       DECODE_BIN_UNLOCK (dbin);
1076       newgroup = TRUE;
1077     }
1078
1079   isdemux = is_demuxer_element (src);
1080
1081   if (isdemux || newgroup) {
1082     GST_LOG_OBJECT (src, "is a demuxer, connecting the pad through multiqueue");
1083
1084     if (!(mqpad = gst_decode_group_control_demuxer_pad (group, pad)))
1085       goto beach;
1086     pad = mqpad;
1087   }
1088
1089   gst_decode_group_control_source_pad (group, pad);
1090
1091   if (newgroup && !isdemux) {
1092     /* If we have discovered a raw pad and it doesn't belong to any group,
1093      * that means there wasn't any demuxer. In that case, we consider the
1094      * group as being complete. */
1095     gst_decode_group_set_complete (group);
1096   }
1097   if (mqpad)
1098     gst_object_unref (mqpad);
1099
1100 beach:
1101   return;
1102 }
1103
1104 static void
1105 type_found (GstElement * typefind, guint probability,
1106     GstCaps * caps, GstDecodeBin * decode_bin)
1107 {
1108   GstPad *pad;
1109
1110   GST_STATE_LOCK (decode_bin);
1111
1112   GST_DEBUG_OBJECT (decode_bin, "typefind found caps %" GST_PTR_FORMAT, caps);
1113
1114   pad = gst_element_get_pad (typefind, "src");
1115
1116   analyze_new_pad (decode_bin, typefind, pad, caps, NULL);
1117
1118   gst_object_unref (pad);
1119
1120   GST_STATE_UNLOCK (decode_bin);
1121   return;
1122 }
1123
1124 static void
1125 pad_added_group_cb (GstElement * element, GstPad * pad, GstDecodeGroup * group)
1126 {
1127   GstCaps *caps;
1128   gboolean expose = FALSE;
1129
1130   GST_LOG_OBJECT (pad, "pad added, group:%p", group);
1131
1132   caps = gst_pad_get_caps (pad);
1133   analyze_new_pad (group->dbin, element, pad, caps, group);
1134   if (caps)
1135     gst_caps_unref (caps);
1136
1137   GROUP_MUTEX_LOCK (group);
1138   group->nbdynamic--;
1139   GST_LOG ("Group %p has now %d dynamic objects", group, group->nbdynamic);
1140   if (group->nbdynamic == 0)
1141     expose = TRUE;
1142   GROUP_MUTEX_UNLOCK (group);
1143   if (expose) {
1144     GST_LOG
1145         ("That was the last dynamic object, now attempting to expose the group");
1146     DECODE_BIN_LOCK (group->dbin);
1147     gst_decode_group_expose (group);
1148     DECODE_BIN_UNLOCK (group->dbin);
1149   }
1150 }
1151
1152 static void
1153 pad_removed_group_cb (GstElement * element, GstPad * pad,
1154     GstDecodeGroup * group)
1155 {
1156   GST_LOG_OBJECT (pad, "pad removed, group:%p", group);
1157
1158   /* In fact, we don't have to do anything here, the active group will be
1159    * removed when the group's multiqueue is drained */
1160 }
1161
1162 static void
1163 no_more_pads_group_cb (GstElement * element, GstDecodeGroup * group)
1164 {
1165   GST_LOG_OBJECT (element, "no more pads, setting group %p to complete", group);
1166
1167   /* FIXME : FILLME */
1168   gst_decode_group_set_complete (group);
1169 }
1170
1171 static void
1172 pad_added_cb (GstElement * element, GstPad * pad, GstDecodeBin * dbin)
1173 {
1174   GstCaps *caps;
1175
1176   GST_LOG_OBJECT (pad, "Pad added to non-grouped element");
1177
1178   caps = gst_pad_get_caps (pad);
1179   analyze_new_pad (dbin, element, pad, caps, NULL);
1180   if (caps)
1181     gst_caps_unref (caps);
1182 }
1183
1184 static void
1185 pad_removed_cb (GstElement * element, GstPad * pad, GstDecodeBin * dbin)
1186 {
1187   GST_LOG_OBJECT (pad, "Pad removed from non-grouped element");
1188 }
1189
1190 static void
1191 no_more_pads_cb (GstElement * element, GstDecodeBin * dbin)
1192 {
1193   GstDecodeGroup *group;
1194
1195   GST_LOG_OBJECT (element, "No more pads, setting current group to complete");
1196
1197   /* Find the non-complete group, there should only be one */
1198   if (!(group = get_current_group (dbin)))
1199     goto no_group;
1200
1201   gst_decode_group_set_complete (group);
1202   return;
1203
1204 no_group:
1205   {
1206     GST_WARNING_OBJECT (dbin, "We couldn't find a non-completed group !!");
1207     return;
1208   }
1209 }
1210
1211 /* this function runs through the element factories and returns a list
1212  * of all elements that are able to sink the given caps 
1213  */
1214 static GList *
1215 find_compatibles (GstDecodeBin * decode_bin, const GstCaps * caps)
1216 {
1217   GList *factories;
1218   GList *to_try = NULL;
1219
1220   /* loop over all the factories */
1221   for (factories = decode_bin->factories; factories;
1222       factories = g_list_next (factories)) {
1223     GstElementFactory *factory = GST_ELEMENT_FACTORY (factories->data);
1224     const GList *templates;
1225     GList *walk;
1226
1227     /* get the templates from the element factory */
1228     templates = gst_element_factory_get_static_pad_templates (factory);
1229     for (walk = (GList *) templates; walk; walk = g_list_next (walk)) {
1230       GstStaticPadTemplate *templ = walk->data;
1231
1232       /* we only care about the sink templates */
1233       if (templ->direction == GST_PAD_SINK) {
1234         GstCaps *intersect;
1235         GstCaps *tmpl_caps;
1236
1237         /* try to intersect the caps with the caps of the template */
1238         tmpl_caps = gst_static_caps_get (&templ->static_caps);
1239
1240         intersect = gst_caps_intersect (caps, tmpl_caps);
1241         gst_caps_unref (tmpl_caps);
1242
1243         /* check if the intersection is empty */
1244         if (!gst_caps_is_empty (intersect)) {
1245           /* non empty intersection, we can use this element */
1246           to_try = g_list_prepend (to_try, factory);
1247           gst_caps_unref (intersect);
1248           break;
1249         }
1250         gst_caps_unref (intersect);
1251       }
1252     }
1253   }
1254   to_try = g_list_reverse (to_try);
1255
1256   return to_try;
1257 }
1258
1259 /* Decide whether an element is a demuxer based on the 
1260  * klass and number/type of src pad templates it has */
1261 static gboolean
1262 is_demuxer_element (GstElement * srcelement)
1263 {
1264   GstElementFactory *srcfactory;
1265   GstElementClass *elemclass;
1266   GList *templates, *walk;
1267   const gchar *klass;
1268   gint potential_src_pads = 0;
1269
1270   srcfactory = gst_element_get_factory (srcelement);
1271   klass = gst_element_factory_get_klass (srcfactory);
1272
1273   /* Can't be a demuxer unless it has Demux in the klass name */
1274   if (!strstr (klass, "Demux"))
1275     return FALSE;
1276
1277   /* Walk the src pad templates and count how many the element
1278    * might produce */
1279   elemclass = GST_ELEMENT_GET_CLASS (srcelement);
1280
1281   walk = templates = gst_element_class_get_pad_template_list (elemclass);
1282   while (walk != NULL) {
1283     GstPadTemplate *templ;
1284
1285     templ = (GstPadTemplate *) walk->data;
1286     if (GST_PAD_TEMPLATE_DIRECTION (templ) == GST_PAD_SRC) {
1287       switch (GST_PAD_TEMPLATE_PRESENCE (templ)) {
1288         case GST_PAD_ALWAYS:
1289         case GST_PAD_SOMETIMES:
1290           if (strstr (GST_PAD_TEMPLATE_NAME_TEMPLATE (templ), "%"))
1291             potential_src_pads += 2;    /* Might make multiple pads */
1292           else
1293             potential_src_pads += 1;
1294           break;
1295         case GST_PAD_REQUEST:
1296           potential_src_pads += 2;
1297           break;
1298       }
1299     }
1300     walk = g_list_next (walk);
1301   }
1302
1303   if (potential_src_pads < 2)
1304     return FALSE;
1305
1306   return TRUE;
1307 }
1308
1309 /* Returns TRUE if the caps are raw, or if they are compatible with the caps 
1310  * specified in the 'caps' property 
1311  * 
1312  * The decodebin_lock should be taken !
1313  */
1314 static gboolean
1315 are_raw_caps (GstDecodeBin * dbin, GstCaps * caps)
1316 {
1317   GstCaps *intersection;
1318   gboolean res;
1319
1320   GST_LOG_OBJECT (dbin, "Checking with caps %" GST_PTR_FORMAT, caps);
1321
1322   intersection = gst_caps_intersect (dbin->caps, caps);
1323
1324   res = (!(gst_caps_is_empty (intersection)));
1325
1326   gst_caps_unref (intersection);
1327
1328   GST_LOG_OBJECT (dbin, "Caps are %sfinal caps", res ? "" : "not ");
1329
1330   return res;
1331 }
1332
1333
1334 /****
1335  * GstDecodeGroup functions
1336  ****/
1337
1338 static void
1339 multi_queue_overrun_cb (GstElement * queue, GstDecodeGroup * group)
1340 {
1341   GST_LOG_OBJECT (group->dbin, "multiqueue is full");
1342
1343   /* if we haven't exposed the group, do it */
1344   DECODE_BIN_LOCK (group->dbin);
1345   gst_decode_group_expose (group);
1346   DECODE_BIN_UNLOCK (group->dbin);
1347 }
1348
1349 static void
1350 multi_queue_underrun_cb (GstElement * queue, GstDecodeGroup * group)
1351 {
1352   GstDecodeBin *dbin = group->dbin;
1353
1354   GST_LOG_OBJECT (dbin, "multiqueue is empty for group %p", group);
1355
1356   /* Check if we need to activate another group */
1357   DECODE_BIN_LOCK (dbin);
1358   if ((group == dbin->activegroup) && dbin->groups) {
1359     GST_DEBUG_OBJECT (dbin, "Switching to new group");
1360     /* unexpose current active */
1361     gst_decode_group_hide (group);
1362
1363     /* expose first group of groups */
1364     gst_decode_group_expose ((GstDecodeGroup *) dbin->groups->data);
1365   }
1366   DECODE_BIN_UNLOCK (dbin);
1367 }
1368
1369 /* gst_decode_group_new
1370  *
1371  * Creates a new GstDecodeGroup. It is up to the caller to add it to the list
1372  * of groups.
1373  */
1374 static GstDecodeGroup *
1375 gst_decode_group_new (GstDecodeBin * dbin)
1376 {
1377   GstDecodeGroup *group;
1378   GstElement *mq;
1379
1380   GST_LOG_OBJECT (dbin, "Creating new group");
1381
1382   if (!(mq = gst_element_factory_make ("multiqueue", NULL))) {
1383     GST_WARNING ("Couldn't create multiqueue element");
1384     return NULL;
1385   }
1386
1387   g_object_set (G_OBJECT (mq),
1388       "max-size-bytes", 2 * 1024 * 1024,
1389       "max-size-time", 5 * GST_SECOND, "max-size-buffers", 0, NULL);
1390
1391   group = g_new0 (GstDecodeGroup, 1);
1392   group->lock = g_mutex_new ();
1393   group->dbin = dbin;
1394   group->multiqueue = mq;
1395   group->exposed = FALSE;
1396   group->drained = FALSE;
1397   group->blocked = FALSE;
1398   group->complete = FALSE;
1399   group->endpads = NULL;
1400
1401   group->overrunsig = g_signal_connect (G_OBJECT (mq), "overrun",
1402       G_CALLBACK (multi_queue_overrun_cb), group);
1403   group->underrunsig = g_signal_connect (G_OBJECT (mq), "underrun",
1404       G_CALLBACK (multi_queue_underrun_cb), group);
1405
1406   gst_bin_add (GST_BIN (dbin), group->multiqueue);
1407   gst_element_set_state (group->multiqueue, GST_STATE_PAUSED);
1408
1409   GST_LOG_OBJECT (dbin, "Returning new group %p", group);
1410
1411   return group;
1412 }
1413
1414 /** get_current_group:
1415  *
1416  * Returns the current non-completed group.
1417  *
1418  * Returns NULL if no groups are available, or all groups are completed.
1419  */
1420 static GstDecodeGroup *
1421 get_current_group (GstDecodeBin * dbin)
1422 {
1423   GList *tmp;
1424   GstDecodeGroup *group = NULL;
1425
1426   DECODE_BIN_LOCK (dbin);
1427   for (tmp = dbin->groups; tmp; tmp = g_list_next (tmp)) {
1428     GstDecodeGroup *this = (GstDecodeGroup *) tmp->data;
1429
1430     GST_LOG_OBJECT (dbin, "group %p, complete:%d", this, this->complete);
1431
1432     if (!this->complete) {
1433       group = this;
1434       break;
1435     }
1436   }
1437   DECODE_BIN_UNLOCK (dbin);
1438
1439   GST_LOG_OBJECT (dbin, "Returning group %p", group);
1440
1441   return group;
1442 }
1443
1444 static gboolean
1445 group_demuxer_event_probe (GstPad * pad, GstEvent * event,
1446     GstDecodeGroup * group)
1447 {
1448   if (GST_EVENT_TYPE (event) == GST_EVENT_EOS) {
1449     GST_DEBUG_OBJECT (group->dbin,
1450         "Got EOS on group input pads, exposing group if it wasn't before");
1451     DECODE_BIN_LOCK (group->dbin);
1452     gst_decode_group_expose (group);
1453     DECODE_BIN_UNLOCK (group->dbin);
1454   }
1455   return TRUE;
1456 }
1457
1458 /* gst_decode_group_control_demuxer_pad
1459  *
1460  * Adds a new demuxer srcpad to the given group.
1461  *
1462  * Returns the srcpad of the multiqueue corresponding the given pad.
1463  * Returns NULL if there was an error.
1464  */
1465 static GstPad *
1466 gst_decode_group_control_demuxer_pad (GstDecodeGroup * group, GstPad * pad)
1467 {
1468   GstPad *srcpad, *sinkpad;
1469   gchar *nb, *sinkname, *srcname;
1470
1471   GST_LOG ("group:%p pad %s:%s", group, GST_DEBUG_PAD_NAME (pad));
1472
1473   srcpad = NULL;
1474
1475   if (!(sinkpad = gst_element_get_pad (group->multiqueue, "sink%d"))) {
1476     GST_ERROR ("Couldn't get sinkpad from multiqueue");
1477     return NULL;
1478   }
1479
1480   if ((gst_pad_link (pad, sinkpad) != GST_PAD_LINK_OK)) {
1481     GST_ERROR ("Couldn't link demuxer and multiqueue");
1482     goto beach;
1483   }
1484
1485   sinkname = gst_pad_get_name (sinkpad);
1486   nb = sinkname + 4;
1487   srcname = g_strdup_printf ("src%s", nb);
1488   g_free (sinkname);
1489
1490   GROUP_MUTEX_LOCK (group);
1491
1492   if (!(srcpad = gst_element_get_pad (group->multiqueue, srcname))) {
1493     GST_ERROR ("Couldn't get srcpad %s from multiqueue", srcname);
1494     goto chiringuito;
1495   }
1496
1497   /* connect event handler on pad to intercept EOS events */
1498   gst_pad_add_event_probe (pad, G_CALLBACK (group_demuxer_event_probe), group);
1499
1500 chiringuito:
1501   g_free (srcname);
1502   GROUP_MUTEX_UNLOCK (group);
1503
1504 beach:
1505   gst_object_unref (sinkpad);
1506   return srcpad;
1507 }
1508
1509 static gboolean
1510 gst_decode_group_control_source_pad (GstDecodeGroup * group, GstPad * pad)
1511 {
1512   GstDecodePad *dpad;
1513
1514   g_return_val_if_fail (group != NULL, FALSE);
1515
1516   GST_LOG ("group:%p , pad %s:%s", group, GST_DEBUG_PAD_NAME (pad));
1517
1518   /* FIXME : check if pad is already controlled */
1519
1520   GROUP_MUTEX_LOCK (group);
1521
1522   /* Create GstDecodePad for the pad */
1523   dpad = gst_decode_pad_new (group, pad, TRUE);
1524
1525   group->endpads = g_list_append (group->endpads, dpad);
1526
1527   GROUP_MUTEX_UNLOCK (group);
1528
1529   return TRUE;
1530 }
1531
1532 /* gst_decode_group_check_if_blocked:
1533  *
1534  * Call this when one of the pads blocked status has changed.
1535  * If the group is complete and blocked, the group will be marked as blocked
1536  * and will ghost/expose all pads on decodebin if the group is the current one.
1537  *
1538  * Call with the group lock taken ! MT safe
1539  */
1540 static void
1541 gst_decode_group_check_if_blocked (GstDecodeGroup * group)
1542 {
1543   GList *tmp;
1544   gboolean blocked = TRUE;
1545
1546   GST_LOG ("group : %p , ->complete:%d , ->nbdynamic:%d",
1547       group, group->complete, group->nbdynamic);
1548
1549   /* 1. don't do anything if group is not complete */
1550   if (!group->complete || group->nbdynamic) {
1551     GST_DEBUG_OBJECT (group->dbin, "Group isn't complete yet");
1552     return;
1553   }
1554
1555   for (tmp = group->endpads; tmp; tmp = g_list_next (tmp)) {
1556     GstDecodePad *dpad = (GstDecodePad *) tmp->data;
1557
1558     if (!dpad->blocked) {
1559       blocked = FALSE;
1560       break;
1561     }
1562   }
1563
1564   /* 2. Update status of group */
1565   group->blocked = blocked;
1566   GST_LOG ("group is blocked:%d", blocked);
1567
1568   /* 3. don't do anything if not blocked completely */
1569   if (!blocked)
1570     return;
1571
1572   /* 4. if we're the current group, expose pads */
1573   DECODE_BIN_LOCK (group->dbin);
1574   if (!gst_decode_group_expose (group))
1575     GST_WARNING_OBJECT (group->dbin, "Couldn't expose group");
1576   DECODE_BIN_UNLOCK (group->dbin);
1577 }
1578
1579 static void
1580 gst_decode_group_check_if_drained (GstDecodeGroup * group)
1581 {
1582   GList *tmp;
1583   GstDecodeBin *dbin = group->dbin;
1584   gboolean drained = TRUE;
1585
1586   GST_LOG ("group : %p", group);
1587
1588   for (tmp = group->endpads; tmp; tmp = g_list_next (tmp)) {
1589     GstDecodePad *dpad = (GstDecodePad *) tmp->data;
1590
1591     GST_LOG ("testing dpad %p", dpad);
1592
1593     if (!dpad->drained) {
1594       drained = FALSE;
1595       break;
1596     }
1597   }
1598
1599   group->drained = drained;
1600   GST_LOG ("group is drained");
1601
1602   if (!drained)
1603     return;
1604
1605   DECODE_BIN_LOCK (dbin);
1606   if ((group == dbin->activegroup) && dbin->groups) {
1607     GST_DEBUG_OBJECT (dbin, "Switching to new group");
1608
1609     gst_decode_group_hide (group);
1610
1611     gst_decode_group_expose ((GstDecodeGroup *) dbin->groups->data);
1612   }
1613   DECODE_BIN_UNLOCK (dbin);
1614 }
1615
1616 /* sort_end_pads:
1617  * GCompareFunc to use with lists of GstPad.
1618  * Sorts pads by mime type.
1619  * First video (raw, then non-raw), then audio (raw, then non-raw),
1620  * then others.
1621  *
1622  * Return: negative if a<b, 0 if a==b, positive if a>b
1623  */
1624
1625 static gint
1626 sort_end_pads (GstDecodePad * da, GstDecodePad * db)
1627 {
1628   GstPad *a, *b;
1629   gint va, vb;
1630   GstCaps *capsa, *capsb;
1631   GstStructure *sa, *sb;
1632   const gchar *namea, *nameb;
1633
1634   a = da->pad;
1635   b = db->pad;
1636
1637   capsa = gst_pad_get_caps (a);
1638   capsb = gst_pad_get_caps (b);
1639
1640   sa = gst_caps_get_structure ((const GstCaps *) capsa, 0);
1641   sb = gst_caps_get_structure ((const GstCaps *) capsb, 0);
1642
1643   namea = gst_structure_get_name (sa);
1644   nameb = gst_structure_get_name (sb);
1645
1646   if (g_strrstr (namea, "video/x-raw-"))
1647     va = 0;
1648   else if (g_strrstr (namea, "video/"))
1649     va = 1;
1650   else if (g_strrstr (namea, "audio/x-raw"))
1651     va = 2;
1652   else if (g_strrstr (namea, "audio/"))
1653     va = 3;
1654   else
1655     va = 4;
1656
1657   if (g_strrstr (nameb, "video/x-raw-"))
1658     vb = 0;
1659   else if (g_strrstr (nameb, "video/"))
1660     vb = 1;
1661   else if (g_strrstr (nameb, "audio/x-raw"))
1662     vb = 2;
1663   else if (g_strrstr (nameb, "audio/"))
1664     vb = 3;
1665   else
1666     vb = 4;
1667
1668   gst_caps_unref (capsa);
1669   gst_caps_unref (capsb);
1670
1671   return va - vb;
1672 }
1673
1674 /* gst_decode_group_expose:
1675  *
1676  * Expose this group's pads.
1677  *
1678  * Not MT safe, please take the group lock
1679  */
1680
1681 static gboolean
1682 gst_decode_group_expose (GstDecodeGroup * group)
1683 {
1684   GList *tmp;
1685   GList *next = NULL;
1686
1687   if (group->dbin->activegroup) {
1688     GST_DEBUG_OBJECT (group->dbin, "A group is already active and exposed");
1689     return TRUE;
1690   }
1691
1692   if (group->dbin->activegroup == group) {
1693     GST_WARNING ("Group %p is already exposed", group);
1694     return TRUE;
1695   }
1696
1697   if (!group->dbin->groups
1698       || (group != (GstDecodeGroup *) group->dbin->groups->data)) {
1699     GST_WARNING ("Group %p is not the first group to expose", group);
1700     return FALSE;
1701   }
1702
1703   if (group->nbdynamic) {
1704     GST_WARNING ("Group %p still has %d dynamic objects, not exposing yet",
1705         group, group->nbdynamic);
1706     return FALSE;
1707   }
1708
1709   GST_LOG ("Exposing group %p", group);
1710
1711   /* re-order pads : video, then audio, then others */
1712   group->endpads = g_list_sort (group->endpads, (GCompareFunc) sort_end_pads);
1713
1714   /* Expose pads */
1715
1716   for (tmp = group->endpads; tmp; tmp = next) {
1717     GstDecodePad *dpad = (GstDecodePad *) tmp->data;
1718     gchar *padname;
1719     GstPad *ghost;
1720
1721     next = g_list_next (tmp);
1722
1723     /* 1. ghost pad */
1724     padname = g_strdup_printf ("src%d", group->dbin->nbpads);
1725     group->dbin->nbpads++;
1726
1727     GST_LOG_OBJECT (group->dbin, "About to expose pad %s:%s",
1728         GST_DEBUG_PAD_NAME (dpad->pad));
1729
1730     ghost = gst_ghost_pad_new (padname, dpad->pad);
1731     gst_pad_set_active (ghost, TRUE);
1732     gst_element_add_pad (GST_ELEMENT (group->dbin), ghost);
1733     group->ghosts = g_list_append (group->ghosts, ghost);
1734
1735     g_free (padname);
1736
1737     /* 2. emit signal */
1738     GST_DEBUG_OBJECT (group->dbin, "emitting new-decoded-pad");
1739     g_signal_emit (G_OBJECT (group->dbin),
1740         gst_decode_bin_signals[SIGNAL_NEW_DECODED_PAD], 0, ghost,
1741         (next == NULL));
1742     GST_DEBUG_OBJECT (group->dbin, "emitted new-decoded-pad");
1743
1744     /* 3. Unblock internal  pad */
1745     GST_DEBUG_OBJECT (dpad->pad, "unblocking");
1746     gst_pad_set_blocked_async (dpad->pad, FALSE,
1747         (GstPadBlockCallback) source_pad_blocked_cb, dpad);
1748     GST_DEBUG_OBJECT (dpad->pad, "unblocked");
1749
1750   }
1751
1752   group->dbin->activegroup = group;
1753
1754   /* pop off the first group */
1755   group->dbin->groups =
1756       g_list_delete_link (group->dbin->groups, group->dbin->groups);
1757
1758   remove_fakesink (group->dbin);
1759
1760   group->exposed = TRUE;
1761
1762   GST_LOG_OBJECT (group->dbin, "signalling no-more-pads");
1763   gst_element_no_more_pads (GST_ELEMENT (group->dbin));
1764
1765   GST_LOG_OBJECT (group->dbin, "Group %p exposed", group);
1766   return TRUE;
1767 }
1768
1769 static void
1770 gst_decode_group_hide (GstDecodeGroup * group)
1771 {
1772   GList *tmp;
1773
1774   GST_LOG ("Hiding group %p", group);
1775
1776   if (group != group->dbin->activegroup) {
1777     GST_WARNING ("This group is not the active one, aborting");
1778     return;
1779   }
1780
1781   GROUP_MUTEX_LOCK (group);
1782
1783   /* Remove ghost pads */
1784   for (tmp = group->ghosts; tmp; tmp = g_list_next (tmp))
1785     gst_element_remove_pad (GST_ELEMENT (group->dbin), (GstPad *) tmp->data);
1786
1787   g_list_free (group->ghosts);
1788   group->ghosts = NULL;
1789
1790   group->exposed = FALSE;
1791
1792   GROUP_MUTEX_UNLOCK (group);
1793
1794   group->dbin->activegroup = NULL;
1795   group->dbin->oldgroups = g_list_append (group->dbin->oldgroups, group);
1796 }
1797
1798 static void
1799 deactivate_free_recursive (GstDecodeGroup * group, GstElement * element)
1800 {
1801   GstIterator *it;
1802   GstIteratorResult res;
1803   gpointer point;
1804
1805   GST_LOG ("element:%s", GST_ELEMENT_NAME (element));
1806
1807   /* call on downstream elements */
1808   it = gst_element_iterate_src_pads (element);
1809
1810 restart:
1811
1812   while (1) {
1813     res = gst_iterator_next (it, &point);
1814     switch (res) {
1815       case GST_ITERATOR_DONE:
1816         goto done;
1817       case GST_ITERATOR_RESYNC:
1818         gst_iterator_resync (it);
1819         goto restart;
1820       case GST_ITERATOR_ERROR:
1821       {
1822         GST_WARNING ("Had an error while iterating source pads of element: %s",
1823             GST_ELEMENT_NAME (element));
1824         goto beach;
1825       }
1826       case GST_ITERATOR_OK:
1827       {
1828         GstPad *pad = GST_PAD (point);
1829         GstPad *peerpad = NULL;
1830
1831         if ((peerpad = gst_pad_get_peer (pad))) {
1832           GstObject *parent;
1833
1834           parent = gst_pad_get_parent (peerpad);
1835           gst_object_unref (peerpad);
1836
1837           if (parent && GST_IS_ELEMENT (parent))
1838             deactivate_free_recursive (group, GST_ELEMENT (parent));
1839           if (parent)
1840             gst_object_unref (parent);
1841         }
1842       }
1843         break;
1844       default:
1845         break;
1846     }
1847   }
1848
1849 done:
1850   gst_element_set_state (element, GST_STATE_NULL);
1851   gst_bin_remove (GST_BIN (group->dbin), element);
1852
1853 beach:
1854   gst_iterator_free (it);
1855
1856   return;
1857 }
1858
1859 static void
1860 gst_decode_group_free (GstDecodeGroup * group)
1861 {
1862   GList *tmp;
1863
1864   GST_LOG ("group %p", group);
1865
1866   GROUP_MUTEX_LOCK (group);
1867   /* Clear all GstDecodePad */
1868   for (tmp = group->endpads; tmp; tmp = g_list_next (tmp)) {
1869     GstDecodePad *dpad = (GstDecodePad *) tmp->data;
1870
1871     g_free (dpad);
1872   }
1873   g_list_free (group->endpads);
1874   group->endpads = NULL;
1875
1876   /* disconnect signal handlers on multiqueue */
1877   g_signal_handler_disconnect (group->multiqueue, group->underrunsig);
1878   g_signal_handler_disconnect (group->multiqueue, group->overrunsig);
1879
1880   /* remove all elements */
1881   deactivate_free_recursive (group, group->multiqueue);
1882
1883   GROUP_MUTEX_UNLOCK (group);
1884
1885   g_mutex_free (group->lock);
1886   g_free (group);
1887 }
1888
1889 /* gst_decode_group_set_complete:
1890  *
1891  * Mark the group as complete. This means no more streams will be controlled
1892  * through this group.
1893  *
1894  * MT safe
1895  */
1896 static void
1897 gst_decode_group_set_complete (GstDecodeGroup * group)
1898 {
1899   GST_LOG_OBJECT (group->dbin, "Setting group %p to COMPLETE", group);
1900
1901   GROUP_MUTEX_LOCK (group);
1902   group->complete = TRUE;
1903   gst_decode_group_check_if_blocked (group);
1904   GROUP_MUTEX_UNLOCK (group);
1905 }
1906
1907
1908
1909 /*************************
1910  * GstDecodePad functions
1911  *************************/
1912
1913 static void
1914 source_pad_blocked_cb (GstPad * pad, gboolean blocked, GstDecodePad * dpad)
1915 {
1916   GST_LOG_OBJECT (pad, "blocked:%d , dpad:%p, dpad->group:%p",
1917       blocked, dpad, dpad->group);
1918
1919   /* Update this GstDecodePad status */
1920   dpad->blocked = blocked;
1921
1922   if (blocked) {
1923     GROUP_MUTEX_LOCK (dpad->group);
1924     gst_decode_group_check_if_blocked (dpad->group);
1925     GROUP_MUTEX_UNLOCK (dpad->group);
1926   }
1927 }
1928
1929 static gboolean
1930 source_pad_event_probe (GstPad * pad, GstEvent * event, GstDecodePad * dpad)
1931 {
1932   GST_LOG_OBJECT (pad, "%s dpad:%p", GST_EVENT_TYPE_NAME (event), dpad);
1933
1934   if (GST_EVENT_TYPE (event) == GST_EVENT_EOS) {
1935     /* Set our pad as drained */
1936     dpad->drained = TRUE;
1937
1938     /* Check if all pads are drained */
1939     gst_decode_group_check_if_drained (dpad->group);
1940   }
1941
1942   return TRUE;
1943 }
1944
1945 /*gst_decode_pad_new:
1946  *
1947  * Creates a new GstDecodePad for the given pad.
1948  * If block is TRUE, Sets the pad blocking asynchronously
1949  */
1950
1951 static GstDecodePad *
1952 gst_decode_pad_new (GstDecodeGroup * group, GstPad * pad, gboolean block)
1953 {
1954   GstDecodePad *dpad;
1955
1956   dpad = g_new0 (GstDecodePad, 1);
1957   dpad->pad = pad;
1958   dpad->group = group;
1959   dpad->blocked = FALSE;
1960   dpad->drained = TRUE;
1961
1962   if (block)
1963     gst_pad_set_blocked_async (pad, TRUE,
1964         (GstPadBlockCallback) source_pad_blocked_cb, dpad);
1965   gst_pad_add_event_probe (pad, G_CALLBACK (source_pad_event_probe), dpad);
1966   return dpad;
1967 }
1968
1969
1970 /*****
1971  * Element add/remove
1972  *****/
1973
1974 /*
1975  * add_fakesink / remove_fakesink
1976  *
1977  * We use a sink so that the parent ::change_state returns GST_STATE_CHANGE_ASYNC
1978  * when that sink is present (since it's not connected to anything it will 
1979  * always return GST_STATE_CHANGE_ASYNC).
1980  *
1981  * But this is an ugly way of achieving this goal.
1982  * Ideally, we shouldn't use a sink and just return GST_STATE_CHANGE_ASYNC in
1983  * our ::change_state if we have not exposed the active group.
1984  * We also need to override ::get_state to fake the asynchronous behaviour.
1985  * Once the active group is exposed, we would then post a
1986  * GST_MESSAGE_STATE_DIRTY and return GST_STATE_CHANGE_SUCCESS (which will call
1987  * ::get_state .
1988  */
1989
1990 static gboolean
1991 add_fakesink (GstDecodeBin * decode_bin)
1992 {
1993   GST_DEBUG_OBJECT (decode_bin, "Adding the fakesink");
1994
1995   if (decode_bin->fakesink)
1996     return TRUE;
1997
1998   decode_bin->fakesink =
1999       gst_element_factory_make ("fakesink", "async-fakesink");
2000   if (!decode_bin->fakesink)
2001     goto no_fakesink;
2002
2003   /* hacky, remove sink flag, we don't want our decodebin to become a sink
2004    * just because we add a fakesink element to make us ASYNC */
2005   GST_OBJECT_FLAG_UNSET (decode_bin->fakesink, GST_ELEMENT_IS_SINK);
2006
2007   if (!gst_bin_add (GST_BIN (decode_bin), decode_bin->fakesink))
2008     goto could_not_add;
2009
2010   return TRUE;
2011
2012   /* ERRORS */
2013 no_fakesink:
2014   {
2015     g_warning ("can't find fakesink element, decodebin will not work");
2016     return FALSE;
2017   }
2018 could_not_add:
2019   {
2020     g_warning ("Could not add fakesink to decodebin, decodebin will not work");
2021     gst_object_unref (decode_bin->fakesink);
2022     decode_bin->fakesink = NULL;
2023     return FALSE;
2024   }
2025 }
2026
2027 static void
2028 remove_fakesink (GstDecodeBin * decode_bin)
2029 {
2030   if (decode_bin->fakesink == NULL)
2031     return;
2032
2033   GST_DEBUG_OBJECT (decode_bin, "Removing the fakesink");
2034
2035   gst_element_set_state (decode_bin->fakesink, GST_STATE_NULL);
2036   gst_bin_remove (GST_BIN (decode_bin), decode_bin->fakesink);
2037   decode_bin->fakesink = NULL;
2038
2039   gst_element_post_message (GST_ELEMENT_CAST (decode_bin),
2040       gst_message_new_state_dirty (GST_OBJECT_CAST (decode_bin)));
2041 }
2042
2043 /*****
2044  * convenience functions
2045  *****/
2046
2047 /* find_sink_pad
2048  *
2049  * Returns the first sink pad of the given element, or NULL if it doesn't have
2050  * any.
2051  */
2052
2053 static GstPad *
2054 find_sink_pad (GstElement * element)
2055 {
2056   GstIterator *it;
2057   GstPad *pad = NULL;
2058   gpointer point;
2059
2060   it = gst_element_iterate_sink_pads (element);
2061
2062   if ((gst_iterator_next (it, &point)) == GST_ITERATOR_OK)
2063     pad = (GstPad *) point;
2064
2065   gst_iterator_free (it);
2066
2067   return pad;
2068 }
2069
2070 static GstStateChangeReturn
2071 gst_decode_bin_change_state (GstElement * element, GstStateChange transition)
2072 {
2073   GstStateChangeReturn ret;
2074   GstDecodeBin *dbin = GST_DECODE_BIN (element);
2075
2076   switch (transition) {
2077     case GST_STATE_CHANGE_NULL_TO_READY:
2078       if (dbin->typefind == NULL)
2079         goto missing_typefind;
2080       break;
2081     case GST_STATE_CHANGE_READY_TO_PAUSED:{
2082       if (!add_fakesink (dbin))
2083         goto missing_fakesink;
2084       break;
2085     }
2086     default:
2087       break;
2088   }
2089
2090   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
2091
2092   /* FIXME : put some cleanup functions here.. if needed */
2093
2094   return ret;
2095
2096 /* ERRORS */
2097 missing_typefind:
2098   {
2099     gst_element_post_message (element,
2100         gst_missing_element_message_new (element, "typefind"));
2101     GST_ELEMENT_ERROR (dbin, CORE, MISSING_PLUGIN, (NULL), ("no typefind!"));
2102     return GST_STATE_CHANGE_FAILURE;
2103   }
2104 missing_fakesink:
2105   {
2106     gst_element_post_message (element,
2107         gst_missing_element_message_new (element, "fakesink"));
2108     GST_ELEMENT_ERROR (dbin, CORE, MISSING_PLUGIN, (NULL), ("no fakesink!"));
2109     return GST_STATE_CHANGE_FAILURE;
2110   }
2111 }
2112
2113 static gboolean
2114 plugin_init (GstPlugin * plugin)
2115 {
2116   GST_DEBUG_CATEGORY_INIT (gst_decode_bin_debug, "decodebin2", 0,
2117       "decoder bin");
2118
2119 #ifdef ENABLE_NLS
2120   GST_DEBUG ("binding text domain %s to locale dir %s", GETTEXT_PACKAGE,
2121       LOCALEDIR);
2122   bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
2123 #endif /* ENABLE_NLS */
2124
2125   return gst_element_register (plugin, "decodebin2", GST_RANK_NONE,
2126       GST_TYPE_DECODE_BIN);
2127 }
2128
2129 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
2130     GST_VERSION_MINOR,
2131     "decodebin2",
2132     "decoder bin newer version", plugin_init, VERSION, GST_LICENSE,
2133     GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)