• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* GStreamer
2  * Copyright (C) <2006> Edward Hervey <edward@fluendo.com>
3  * Copyright (C) <2009> Sebastian Dröge <sebastian.droege@collabora.co.uk>
4  * Copyright (C) <2011> Hewlett-Packard Development Company, L.P.
5  *   Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>, Collabora Ltd.
6  * Copyright (C) <2013> Collabora Ltd.
7  *   Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>
8  * Copyright (C) <2015-2016> Centricular Ltd
9  *  @author: Edward Hervey <edward@centricular.com>
10  *  @author: Jan Schmidt <jan@centricular.com>
11  *
12  * This library is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU Library General Public
14  * License as published by the Free Software Foundation; either
15  * version 2 of the License, or (at your option) any later version.
16  *
17  * This library is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
20  * Library General Public License for more details.
21  *
22  * You should have received a copy of the GNU Library General Public
23  * License along with this library; if not, write to the
24  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
25  * Boston, MA 02110-1301, USA.
26  */
27 
28 /**
29  * SECTION:element-parsebin
30  * @title: parsebin
31  *
32  * #GstBin that auto-magically constructs a parsing pipeline
33  * using available parsers and demuxers via auto-plugging.
34  *
35  * parsebin unpacks the contents of the input stream to the
36  * level of parsed elementary streams, but unlike decodebin
37  * it doesn't connect decoder elements. The output pads
38  * produce packetised encoded data with timestamps where possible,
39  * or send missing-element messages where not.
40  *
41  * > parsebin is still experimental API and a technology preview.
42  * > Its behaviour and exposed API is subject to change.
43  */
44 
45 /* Implementation notes:
46  *
47  * The following section describes how ParseBin works internally.
48  *
49  * The first part of ParseBin is its typefind element, which tries
50  * to determine the media type of the input stream. If the type is found
51  * autoplugging starts.
52  *
53  * ParseBin internally organizes the elements it autoplugged into
54  * GstParseChains and GstParseGroups. A parse chain is a single chain
55  * of parsing, this
56  * means that if ParseBin ever autoplugs an element with two+ srcpads
57  * (e.g. a demuxer) this will end the chain and everything following this
58  * demuxer will be put into parse groups below the chain. Otherwise,
59  * if an element has a single srcpad that outputs raw data the parse chain
60  * is ended too and a GstParsePad is stored and blocked.
61  *
62  * A parse group combines a number of chains that are created by a
63  * demuxer element.
64  *
65  * This continues until the top-level parse chain is complete. A parse
66  * chain is complete if it either ends with a blocked elementary stream,
67  * if autoplugging stopped because no suitable plugins could be found
68  * or if the active group is complete. A parse group on the other hand
69  * is complete if all child chains are complete.
70  *
71  * If this happens at some point, all end pads of all active groups are exposed.
72  * For this ParseBin adds the end pads, and then unblocks them. Now playback starts.
73  *
74  * If one of the chains that end on a endpad receives EOS ParseBin checks
75  * if all chains and groups are drained. In that case everything goes into EOS.
76  * If there is a chain where the active group is drained but there exist next
77  * groups, the active group is hidden (endpads are removed) and the next group
78  * is exposed. This means that in some cases more pads may be created even
79  * after the initial no-more-pads signal. This happens for example with
80  * so-called "chained oggs", most commonly found among ogg/vorbis internet
81  * radio streams.
82  *
83  * Note 1: If we're talking about blocked endpads this really means that the
84  * *target* pads of the endpads are blocked. Pads that are exposed to the outside
85  * should never ever be blocked!
86  *
87  * Note 2: If a group is complete and the parent's chain demuxer adds new pads
88  * but never signaled no-more-pads this additional pads will be ignored!
89  *
90  */
91 
92 /* FIXME 0.11: suppress warnings for deprecated API such as GValueArray
93  * with newer GLib versions (>= 2.31.0) */
94 #define GLIB_DISABLE_DEPRECATION_WARNINGS
95 
96 #ifdef HAVE_CONFIG_H
97 #include "config.h"
98 #endif
99 
100 #include <gst/gst-i18n-plugin.h>
101 
102 #include <string.h>
103 #include <gst/gst.h>
104 #include <gst/pbutils/pbutils.h>
105 
106 #include "gstplay-enum.h"
107 #include "gstplaybackelements.h"
108 #include "gstplaybackutils.h"
109 #include "gstrawcaps.h"
110 
111 /* generic templates */
112 static GstStaticPadTemplate parse_bin_sink_template =
113 GST_STATIC_PAD_TEMPLATE ("sink",
114     GST_PAD_SINK,
115     GST_PAD_ALWAYS,
116     GST_STATIC_CAPS_ANY);
117 
118 static GstStaticPadTemplate parse_bin_src_template =
119 GST_STATIC_PAD_TEMPLATE ("src_%u",
120     GST_PAD_SRC,
121     GST_PAD_SOMETIMES,
122     GST_STATIC_CAPS_ANY);
123 
124 GST_DEBUG_CATEGORY_STATIC (gst_parse_bin_debug);
125 #define GST_CAT_DEFAULT gst_parse_bin_debug
126 
127 typedef struct _GstPendingPad GstPendingPad;
128 typedef struct _GstParseElement GstParseElement;
129 typedef struct _GstParseChain GstParseChain;
130 typedef struct _GstParseGroup GstParseGroup;
131 typedef struct _GstParsePad GstParsePad;
132 typedef GstGhostPadClass GstParsePadClass;
133 typedef struct _GstParseBin GstParseBin;
134 typedef struct _GstParseBinClass GstParseBinClass;
135 
136 #define GST_TYPE_PARSE_BIN             (gst_parse_bin_get_type())
137 #define GST_PARSE_BIN_CAST(obj)        ((GstParseBin*)(obj))
138 #define GST_PARSE_BIN(obj)             (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_PARSE_BIN,GstParseBin))
139 #define GST_PARSE_BIN_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_PARSE_BIN,GstParseBinClass))
140 #define GST_IS_parse_bin(obj)          (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_PARSE_BIN))
141 #define GST_IS_parse_bin_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_PARSE_BIN))
142 
143 /**
144  *  GstParseBin:
145  *
146  *  The opaque #GstParseBin data structure
147  */
148 struct _GstParseBin
149 {
150   GstBin bin;                   /* we extend GstBin */
151 
152   /* properties */
153   gchar *encoding;              /* encoding of subtitles */
154   guint64 connection_speed;
155 
156   GstElement *typefind;         /* this holds the typefind object */
157 
158   GMutex expose_lock;           /* Protects exposal and removal of groups */
159   GstParseChain *parse_chain;   /* Top level parse chain */
160   guint nbpads;                 /* unique identifier for source pads */
161 
162   GMutex factories_lock;
163   guint32 factories_cookie;     /* Cookie from last time when factories was updated */
164   GList *factories;             /* factories we can use for selecting elements */
165 
166   GMutex subtitle_lock;         /* Protects changes to subtitles and encoding */
167   GList *subtitles;             /* List of elements with subtitle-encoding,
168                                  * protected by above mutex! */
169 
170   gboolean have_type;           /* if we received the have_type signal */
171   guint have_type_id;           /* signal id for have-type from typefind */
172 
173   GMutex dyn_lock;              /* lock protecting pad blocking */
174   gboolean shutdown;            /* if we are shutting down */
175   GList *blocked_pads;          /* pads that have set to block */
176 
177   gboolean expose_allstreams;   /* Whether to expose unknown type streams or not */
178 
179   GList *filtered;              /* elements for which error messages are filtered */
180   GList *filtered_errors;       /* filtered error messages */
181 
182   GMutex cleanup_lock;          /* Mutex used to protect the cleanup thread */
183   GThread *cleanup_thread;      /* thread used to free chains asynchronously.
184                                  * We store it to make sure we end up joining it
185                                  * before stopping the element.
186                                  * Protected by the object lock */
187 
188 };
189 
190 struct _GstParseBinClass
191 {
192   GstBinClass parent_class;
193 
194   /* signal fired when we found a pad that we cannot parse */
195   void (*unknown_type) (GstElement * element, GstPad * pad, GstCaps * caps);
196 
197   /* signal fired to know if we continue trying to parse the given caps */
198     gboolean (*autoplug_continue) (GstElement * element, GstPad * pad,
199       GstCaps * caps);
200   /* signal fired to get a list of factories to try to autoplug */
201   GValueArray *(*autoplug_factories) (GstElement * element, GstPad * pad,
202       GstCaps * caps);
203   /* signal fired to sort the factories */
204   GValueArray *(*autoplug_sort) (GstElement * element, GstPad * pad,
205       GstCaps * caps, GValueArray * factories);
206   /* signal fired to select from the proposed list of factories */
207     GstAutoplugSelectResult (*autoplug_select) (GstElement * element,
208       GstPad * pad, GstCaps * caps, GstElementFactory * factory);
209   /* signal fired when a autoplugged element that is not linked downstream
210    * or exposed wants to query something */
211     gboolean (*autoplug_query) (GstElement * element, GstPad * pad,
212       GstQuery * query);
213 
214   /* fired when the last group is drained */
215   void (*drained) (GstElement * element);
216 };
217 
218 /* signals */
219 enum
220 {
221   SIGNAL_UNKNOWN_TYPE,
222   SIGNAL_AUTOPLUG_CONTINUE,
223   SIGNAL_AUTOPLUG_FACTORIES,
224   SIGNAL_AUTOPLUG_SELECT,
225   SIGNAL_AUTOPLUG_SORT,
226   SIGNAL_AUTOPLUG_QUERY,
227   SIGNAL_DRAINED,
228   LAST_SIGNAL
229 };
230 
231 #define DEFAULT_SUBTITLE_ENCODING NULL
232 /* by default we use the automatic values above */
233 #define DEFAULT_EXPOSE_ALL_STREAMS  TRUE
234 #define DEFAULT_CONNECTION_SPEED    0
235 
236 /* Properties */
237 enum
238 {
239   PROP_0,
240   PROP_SUBTITLE_ENCODING,
241   PROP_SINK_CAPS,
242   PROP_EXPOSE_ALL_STREAMS,
243   PROP_CONNECTION_SPEED
244 };
245 
246 static GstBinClass *parent_class;
247 static guint gst_parse_bin_signals[LAST_SIGNAL] = { 0 };
248 
249 static void type_found (GstElement * typefind, guint probability,
250     GstCaps * caps, GstParseBin * parse_bin);
251 
252 static gboolean gst_parse_bin_autoplug_continue (GstElement * element,
253     GstPad * pad, GstCaps * caps);
254 static GValueArray *gst_parse_bin_autoplug_factories (GstElement *
255     element, GstPad * pad, GstCaps * caps);
256 static GValueArray *gst_parse_bin_autoplug_sort (GstElement * element,
257     GstPad * pad, GstCaps * caps, GValueArray * factories);
258 static GstAutoplugSelectResult gst_parse_bin_autoplug_select (GstElement *
259     element, GstPad * pad, GstCaps * caps, GstElementFactory * factory);
260 static gboolean gst_parse_bin_autoplug_query (GstElement * element,
261     GstPad * pad, GstQuery * query);
262 
263 static void gst_parse_bin_set_property (GObject * object, guint prop_id,
264     const GValue * value, GParamSpec * pspec);
265 static void gst_parse_bin_get_property (GObject * object, guint prop_id,
266     GValue * value, GParamSpec * pspec);
267 static void caps_notify_cb (GstPad * pad, GParamSpec * unused,
268     GstParseChain * chain);
269 
270 static GstStateChangeReturn gst_parse_bin_change_state (GstElement * element,
271     GstStateChange transition);
272 static void gst_parse_bin_handle_message (GstBin * bin, GstMessage * message);
273 static void gst_parse_pad_update_caps (GstParsePad * parsepad, GstCaps * caps);
274 static void gst_parse_pad_update_tags (GstParsePad * parsepad,
275     GstTagList * tags);
276 static GstEvent *gst_parse_pad_stream_start_event (GstParsePad * parsepad,
277     GstEvent * event);
278 static void gst_parse_pad_update_stream_collection (GstParsePad * parsepad,
279     GstStreamCollection * collection);
280 
281 static GstCaps *get_pad_caps (GstPad * pad);
282 static GstStreamType guess_stream_type_from_caps (GstCaps * caps);
283 
284 #define EXPOSE_LOCK(parsebin) G_STMT_START {				\
285     GST_LOG_OBJECT (parsebin,						\
286 		    "expose locking from thread %p",			\
287 		    g_thread_self ());					\
288     g_mutex_lock (&GST_PARSE_BIN_CAST(parsebin)->expose_lock);		\
289     GST_LOG_OBJECT (parsebin,						\
290 		    "expose locked from thread %p",			\
291 		    g_thread_self ());					\
292 } G_STMT_END
293 
294 #define EXPOSE_UNLOCK(parsebin) G_STMT_START {				\
295     GST_LOG_OBJECT (parsebin,						\
296 		    "expose unlocking from thread %p",			\
297 		    g_thread_self ());					\
298     g_mutex_unlock (&GST_PARSE_BIN_CAST(parsebin)->expose_lock);		\
299 } G_STMT_END
300 
301 #define DYN_LOCK(parsebin) G_STMT_START {			\
302     GST_LOG_OBJECT (parsebin,						\
303 		    "dynlocking from thread %p",			\
304 		    g_thread_self ());					\
305     g_mutex_lock (&GST_PARSE_BIN_CAST(parsebin)->dyn_lock);			\
306     GST_LOG_OBJECT (parsebin,						\
307 		    "dynlocked from thread %p",				\
308 		    g_thread_self ());					\
309 } G_STMT_END
310 
311 #define DYN_UNLOCK(parsebin) G_STMT_START {			\
312     GST_LOG_OBJECT (parsebin,						\
313 		    "dynunlocking from thread %p",			\
314 		    g_thread_self ());					\
315     g_mutex_unlock (&GST_PARSE_BIN_CAST(parsebin)->dyn_lock);		\
316 } G_STMT_END
317 
318 #define SUBTITLE_LOCK(parsebin) G_STMT_START {				\
319     GST_LOG_OBJECT (parsebin,						\
320 		    "subtitle locking from thread %p",			\
321 		    g_thread_self ());					\
322     g_mutex_lock (&GST_PARSE_BIN_CAST(parsebin)->subtitle_lock);		\
323     GST_LOG_OBJECT (parsebin,						\
324 		    "subtitle lock from thread %p",			\
325 		    g_thread_self ());					\
326 } G_STMT_END
327 
328 #define SUBTITLE_UNLOCK(parsebin) G_STMT_START {				\
329     GST_LOG_OBJECT (parsebin,						\
330 		    "subtitle unlocking from thread %p",		\
331 		    g_thread_self ());					\
332     g_mutex_unlock (&GST_PARSE_BIN_CAST(parsebin)->subtitle_lock);		\
333 } G_STMT_END
334 
335 struct _GstPendingPad
336 {
337   GstPad *pad;
338   GstParseChain *chain;
339   gulong event_probe_id;
340   gulong notify_caps_id;
341 };
342 
343 struct _GstParseElement
344 {
345   GstElement *element;
346   GstElement *capsfilter;       /* Optional capsfilter for Parser/Convert */
347   gulong pad_added_id;
348   gulong pad_removed_id;
349   gulong no_more_pads_id;
350 };
351 
352 /* GstParseGroup
353  *
354  * Streams belonging to the same group/chain of a media file
355  *
356  * When changing something here lock the parent chain!
357  */
358 struct _GstParseGroup
359 {
360   GstParseBin *parsebin;
361   GstParseChain *parent;
362 
363   gboolean no_more_pads;        /* TRUE if the demuxer signaled no-more-pads */
364   gboolean drained;             /* TRUE if the all children are drained */
365 
366   GList *children;              /* List of GstParseChains in this group */
367 };
368 
369 struct _GstParseChain
370 {
371   GstParseGroup *parent;
372   GstParseBin *parsebin;
373 
374   GMutex lock;                  /* Protects this chain and its groups */
375 
376   GstPad *pad;                  /* srcpad that caused creation of this chain */
377   GstCaps *start_caps;          /* The initial caps of this chain */
378 
379   gboolean drained;             /* TRUE if the all children are drained */
380   gboolean demuxer;             /* TRUE if elements->data is a demuxer */
381   gboolean parsed;              /* TRUE if any elements are a parser */
382   GList *elements;              /* All elements in this group, first
383                                    is the latest and most downstream element */
384 
385   /* Note: there are only groups if the last element of this chain
386    * is a demuxer, otherwise the chain will end with an endpad.
387    * The other way around this means, that endpad only exists if this
388    * chain doesn't end with a demuxer! */
389 
390   GstParseGroup *active_group;  /* Currently active group */
391   GList *next_groups;           /* head is newest group, tail is next group.
392                                    a new group will be created only if the head
393                                    group had no-more-pads. If it's only exposed
394                                    all new pads will be ignored! */
395   GList *pending_pads;          /* Pads that have no fixed caps yet */
396 
397   GstParsePad *current_pad;     /* Current ending pad of the chain that can't
398                                  * be exposed yet but would be the same as endpad
399                                  * once it can be exposed */
400   GstParsePad *endpad;          /* Pad of this chain that could be exposed */
401   gboolean deadend;             /* This chain is incomplete and can't be completed,
402                                    e.g. no suitable parser could be found
403                                    e.g. stream got EOS without buffers
404                                  */
405   gchar *deadend_details;
406   GstCaps *endcaps;             /* Caps that were used when linking to the endpad
407                                    or that resulted in the deadend
408                                  */
409 
410   /* FIXME: This should be done directly via a thread! */
411   GList *old_groups;            /* Groups that should be freed later */
412 };
413 
414 static void gst_parse_chain_free (GstParseChain * chain);
415 static GstParseChain *gst_parse_chain_new (GstParseBin * parsebin,
416     GstParseGroup * group, GstPad * pad, GstCaps * start_caps);
417 static void gst_parse_group_hide (GstParseGroup * group);
418 static void gst_parse_group_free (GstParseGroup * group);
419 static GstParseGroup *gst_parse_group_new (GstParseBin * parsebin,
420     GstParseChain * chain);
421 static gboolean gst_parse_chain_is_complete (GstParseChain * chain);
422 static gboolean gst_parse_chain_expose (GstParseChain * chain,
423     GList ** endpads, gboolean * missing_plugin,
424     GString * missing_plugin_details, gboolean * last_group,
425     gboolean * uncollected_streams);
426 static void build_fallback_collection (GstParseChain * chain,
427     GstStreamCollection * collection);
428 static gboolean gst_parse_chain_is_drained (GstParseChain * chain);
429 static gboolean gst_parse_group_is_complete (GstParseGroup * group);
430 static gboolean gst_parse_group_is_drained (GstParseGroup * group);
431 
432 static gboolean gst_parse_bin_expose (GstParseBin * parsebin);
433 
434 #define CHAIN_MUTEX_LOCK(chain) G_STMT_START {				\
435     GST_LOG_OBJECT (chain->parsebin,					\
436 		    "locking chain %p from thread %p",			\
437 		    chain, g_thread_self ());				\
438     g_mutex_lock (&chain->lock);						\
439     GST_LOG_OBJECT (chain->parsebin,					\
440 		    "locked chain %p from thread %p",			\
441 		    chain, g_thread_self ());				\
442 } G_STMT_END
443 
444 #define CHAIN_MUTEX_UNLOCK(chain) G_STMT_START {                        \
445     GST_LOG_OBJECT (chain->parsebin,					\
446 		    "unlocking chain %p from thread %p",		\
447 		    chain, g_thread_self ());				\
448     g_mutex_unlock (&chain->lock);					\
449 } G_STMT_END
450 
451 /* GstParsePad
452  *
453  * GstPad private used for source pads of chains
454  */
455 struct _GstParsePad
456 {
457   GstGhostPad parent;
458   GstParseBin *parsebin;
459   GstParseChain *chain;
460 
461   gboolean blocked;             /* the *target* pad is blocked */
462   gboolean exposed;             /* the pad is exposed */
463   gboolean drained;             /* an EOS has been seen on the pad */
464 
465   gulong block_id;
466 
467   gboolean in_a_fallback_collection;
468   GstStreamCollection *active_collection;
469   GstStream *active_stream;
470 };
471 
472 GType gst_parse_pad_get_type (void);
473 G_DEFINE_TYPE (GstParsePad, gst_parse_pad, GST_TYPE_GHOST_PAD);
474 #define GST_TYPE_PARSE_PAD (gst_parse_pad_get_type ())
475 #define GST_PARSE_PAD(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_PARSE_PAD,GstParsePad))
476 
477 static GstParsePad *gst_parse_pad_new (GstParseBin * parsebin,
478     GstParseChain * chain);
479 static void gst_parse_pad_activate (GstParsePad * parsepad,
480     GstParseChain * chain);
481 static void gst_parse_pad_unblock (GstParsePad * parsepad);
482 static void gst_parse_pad_set_blocked (GstParsePad * parsepad,
483     gboolean blocked);
484 static gboolean gst_parse_pad_query (GstPad * pad, GstObject * parent,
485     GstQuery * query);
486 static GstPadProbeReturn
487 gst_parse_pad_event (GstPad * pad, GstPadProbeInfo * info, gpointer user_data);
488 
489 
490 static void gst_pending_pad_free (GstPendingPad * ppad);
491 static GstPadProbeReturn pad_event_cb (GstPad * pad, GstPadProbeInfo * info,
492     gpointer data);
493 
494 /********************************
495  * Standard GObject boilerplate *
496  ********************************/
497 
498 static void gst_parse_bin_dispose (GObject * object);
499 static void gst_parse_bin_finalize (GObject * object);
500 static GType gst_parse_bin_get_type (void);
501 
502 G_DEFINE_TYPE (GstParseBin, gst_parse_bin, GST_TYPE_BIN);
503 #define _do_init \
504     GST_DEBUG_CATEGORY_INIT (gst_parse_bin_debug, "parsebin", 0, "parser bin");\
505     playback_element_init (plugin);
506 GST_ELEMENT_REGISTER_DEFINE_WITH_CODE (parsebin, "parsebin", GST_RANK_NONE,
507     GST_TYPE_PARSE_BIN, _do_init);
508 
509 static gboolean
_gst_boolean_accumulator(GSignalInvocationHint * ihint,GValue * return_accu,const GValue * handler_return,gpointer dummy)510 _gst_boolean_accumulator (GSignalInvocationHint * ihint,
511     GValue * return_accu, const GValue * handler_return, gpointer dummy)
512 {
513   gboolean myboolean;
514 
515   myboolean = g_value_get_boolean (handler_return);
516   g_value_set_boolean (return_accu, myboolean);
517 
518   /* stop emission if FALSE */
519   return myboolean;
520 }
521 
522 static gboolean
_gst_boolean_or_accumulator(GSignalInvocationHint * ihint,GValue * return_accu,const GValue * handler_return,gpointer dummy)523 _gst_boolean_or_accumulator (GSignalInvocationHint * ihint,
524     GValue * return_accu, const GValue * handler_return, gpointer dummy)
525 {
526   gboolean myboolean;
527   gboolean retboolean;
528 
529   myboolean = g_value_get_boolean (handler_return);
530   retboolean = g_value_get_boolean (return_accu);
531 
532   g_value_set_boolean (return_accu, myboolean || retboolean);
533 
534   return TRUE;
535 }
536 
537 /* we collect the first result */
538 static gboolean
_gst_array_accumulator(GSignalInvocationHint * ihint,GValue * return_accu,const GValue * handler_return,gpointer dummy)539 _gst_array_accumulator (GSignalInvocationHint * ihint,
540     GValue * return_accu, const GValue * handler_return, gpointer dummy)
541 {
542   gpointer array;
543 
544   array = g_value_get_boxed (handler_return);
545   g_value_set_boxed (return_accu, array);
546 
547   return FALSE;
548 }
549 
550 static gboolean
_gst_select_accumulator(GSignalInvocationHint * ihint,GValue * return_accu,const GValue * handler_return,gpointer dummy)551 _gst_select_accumulator (GSignalInvocationHint * ihint,
552     GValue * return_accu, const GValue * handler_return, gpointer dummy)
553 {
554   GstAutoplugSelectResult res;
555 
556   res = g_value_get_enum (handler_return);
557   g_value_set_enum (return_accu, res);
558 
559   /* Call the next handler in the chain (if any) when the current callback
560    * returns TRY. This makes it possible to register separate autoplug-select
561    * handlers that implement different TRY/EXPOSE/SKIP strategies.
562    */
563   if (res == GST_AUTOPLUG_SELECT_TRY)
564     return TRUE;
565 
566   return FALSE;
567 }
568 
569 static gboolean
_gst_array_hasvalue_accumulator(GSignalInvocationHint * ihint,GValue * return_accu,const GValue * handler_return,gpointer dummy)570 _gst_array_hasvalue_accumulator (GSignalInvocationHint * ihint,
571     GValue * return_accu, const GValue * handler_return, gpointer dummy)
572 {
573   gpointer array;
574 
575   array = g_value_get_boxed (handler_return);
576   g_value_set_boxed (return_accu, array);
577 
578   if (array != NULL)
579     return FALSE;
580 
581   return TRUE;
582 }
583 
584 static void
gst_parse_bin_class_init(GstParseBinClass * klass)585 gst_parse_bin_class_init (GstParseBinClass * klass)
586 {
587   GObjectClass *gobject_klass;
588   GstElementClass *gstelement_klass;
589   GstBinClass *gstbin_klass;
590 
591   gobject_klass = (GObjectClass *) klass;
592   gstelement_klass = (GstElementClass *) klass;
593   gstbin_klass = (GstBinClass *) klass;
594 
595   parent_class = g_type_class_peek_parent (klass);
596 
597   gobject_klass->dispose = gst_parse_bin_dispose;
598   gobject_klass->finalize = gst_parse_bin_finalize;
599   gobject_klass->set_property = gst_parse_bin_set_property;
600   gobject_klass->get_property = gst_parse_bin_get_property;
601 
602   /**
603    * GstParseBin::unknown-type:
604    * @bin: The ParseBin.
605    * @pad: The new pad containing caps that cannot be resolved to a 'final'
606    *       stream type.
607    * @caps: The #GstCaps of the pad that cannot be resolved.
608    *
609    * This signal is emitted when a pad for which there is no further possible
610    * parsing is added to the ParseBin.
611    */
612   gst_parse_bin_signals[SIGNAL_UNKNOWN_TYPE] =
613       g_signal_new ("unknown-type", G_TYPE_FROM_CLASS (klass),
614       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstParseBinClass, unknown_type),
615       NULL, NULL, NULL, G_TYPE_NONE, 2, GST_TYPE_PAD, GST_TYPE_CAPS);
616 
617   /**
618    * GstParseBin::autoplug-continue:
619    * @bin: The ParseBin.
620    * @pad: The #GstPad.
621    * @caps: The #GstCaps found.
622    *
623    * This signal is emitted whenever ParseBin finds a new stream. It is
624    * emitted before looking for any elements that can handle that stream.
625    *
626    * >   Invocation of signal handlers stops after the first signal handler
627    * >   returns %FALSE. Signal handlers are invoked in the order they were
628    * >   connected in.
629    *
630    * Returns: %TRUE if you wish ParseBin to look for elements that can
631    * handle the given @caps. If %FALSE, those caps will be considered as
632    * final and the pad will be exposed as such (see 'pad-added' signal of
633    * #GstElement).
634    */
635   gst_parse_bin_signals[SIGNAL_AUTOPLUG_CONTINUE] =
636       g_signal_new ("autoplug-continue", G_TYPE_FROM_CLASS (klass),
637       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstParseBinClass, autoplug_continue),
638       _gst_boolean_accumulator, NULL, NULL, G_TYPE_BOOLEAN, 2, GST_TYPE_PAD,
639       GST_TYPE_CAPS);
640 
641   /**
642    * GstParseBin::autoplug-factories:
643    * @bin: The ParseBin.
644    * @pad: The #GstPad.
645    * @caps: The #GstCaps found.
646    *
647    * This function is emitted when an array of possible factories for @caps on
648    * @pad is needed. ParseBin will by default return an array with all
649    * compatible factories, sorted by rank.
650    *
651    * If this function returns NULL, @pad will be exposed as a final caps.
652    *
653    * If this function returns an empty array, the pad will be considered as
654    * having an unhandled type media type.
655    *
656    * >   Only the signal handler that is connected first will ever by invoked.
657    * >   Don't connect signal handlers with the #G_CONNECT_AFTER flag to this
658    * >   signal, they will never be invoked!
659    *
660    * Returns: a #GValueArray* with a list of factories to try. The factories are
661    * by default tried in the returned order or based on the index returned by
662    * "autoplug-select".
663    */
664   gst_parse_bin_signals[SIGNAL_AUTOPLUG_FACTORIES] =
665       g_signal_new ("autoplug-factories", G_TYPE_FROM_CLASS (klass),
666       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstParseBinClass,
667           autoplug_factories), _gst_array_accumulator, NULL,
668       NULL, G_TYPE_VALUE_ARRAY, 2, GST_TYPE_PAD, GST_TYPE_CAPS);
669 
670   /**
671    * GstParseBin::autoplug-sort:
672    * @bin: The ParseBin.
673    * @pad: The #GstPad.
674    * @caps: The #GstCaps.
675    * @factories: A #GValueArray of possible #GstElementFactory to use.
676    *
677    * Once ParseBin has found the possible #GstElementFactory objects to try
678    * for @caps on @pad, this signal is emitted. The purpose of the signal is for
679    * the application to perform additional sorting or filtering on the element
680    * factory array.
681    *
682    * The callee should copy and modify @factories or return %NULL if the
683    * order should not change.
684    *
685    * >   Invocation of signal handlers stops after one signal handler has
686    * >   returned something else than %NULL. Signal handlers are invoked in
687    * >   the order they were connected in.
688    * >   Don't connect signal handlers with the #G_CONNECT_AFTER flag to this
689    * >   signal, they will never be invoked!
690    *
691    * Returns: A new sorted array of #GstElementFactory objects.
692    */
693   gst_parse_bin_signals[SIGNAL_AUTOPLUG_SORT] =
694       g_signal_new ("autoplug-sort", G_TYPE_FROM_CLASS (klass),
695       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstParseBinClass, autoplug_sort),
696       _gst_array_hasvalue_accumulator, NULL,
697       NULL, G_TYPE_VALUE_ARRAY, 3, GST_TYPE_PAD, GST_TYPE_CAPS,
698       G_TYPE_VALUE_ARRAY | G_SIGNAL_TYPE_STATIC_SCOPE);
699 
700   /**
701    * GstParseBin::autoplug-select:
702    * @bin: The ParseBin.
703    * @pad: The #GstPad.
704    * @caps: The #GstCaps.
705    * @factory: A #GstElementFactory to use.
706    *
707    * This signal is emitted once ParseBin has found all the possible
708    * #GstElementFactory that can be used to handle the given @caps. For each of
709    * those factories, this signal is emitted.
710    *
711    * The signal handler should return a #GstAutoplugSelectResult enum
712    * value indicating what ParseBin should do next.
713    *
714    * A value of #GstAutoplugSelectResult::try will try to autoplug an element from
715    * @factory.
716    *
717    * A value of #GstAutoplugSelectResult::expose will expose @pad without plugging
718    * any element to it.
719    *
720    * A value of #GstAutoplugSelectResult::skip will skip @factory and move to the
721    * next factory.
722    *
723    * >   The signal handler will not be invoked if any of the previously
724    * >   registered signal handlers (if any) return a value other than
725    * >   GST_AUTOPLUG_SELECT_TRY. Which also means that if you return
726    * >   GST_AUTOPLUG_SELECT_TRY from one signal handler, handlers that get
727    * >   registered next (again, if any) can override that decision.
728    *
729    * Returns: a #GstAutoplugSelectResult that indicates the required
730    * operation. the default handler will always return
731    * #GstAutoplugSelectResult::try.
732    */
733   gst_parse_bin_signals[SIGNAL_AUTOPLUG_SELECT] =
734       g_signal_new ("autoplug-select", G_TYPE_FROM_CLASS (klass),
735       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstParseBinClass, autoplug_select),
736       _gst_select_accumulator, NULL, NULL, GST_TYPE_AUTOPLUG_SELECT_RESULT, 3,
737       GST_TYPE_PAD, GST_TYPE_CAPS, GST_TYPE_ELEMENT_FACTORY);
738 
739   /**
740    * GstParseBin::autoplug-query:
741    * @bin: The ParseBin.
742    * @child: The child element doing the query
743    * @pad: The #GstPad.
744    * @element: The #GstElement.
745    * @query: The #GstQuery.
746    *
747    * This signal is emitted whenever an autoplugged element that is
748    * not linked downstream yet and not exposed does a query. It can
749    * be used to tell the element about the downstream supported caps
750    * for example.
751    *
752    * Returns: %TRUE if the query was handled, %FALSE otherwise.
753    */
754   gst_parse_bin_signals[SIGNAL_AUTOPLUG_QUERY] =
755       g_signal_new ("autoplug-query", G_TYPE_FROM_CLASS (klass),
756       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstParseBinClass, autoplug_query),
757       _gst_boolean_or_accumulator, NULL, NULL, G_TYPE_BOOLEAN, 3, GST_TYPE_PAD,
758       GST_TYPE_ELEMENT, GST_TYPE_QUERY | G_SIGNAL_TYPE_STATIC_SCOPE);
759 
760   /**
761    * GstParseBin::drained:
762    * @bin: The ParseBin
763    *
764    * This signal is emitted once ParseBin has finished parsing all the data.
765    */
766   gst_parse_bin_signals[SIGNAL_DRAINED] =
767       g_signal_new ("drained", G_TYPE_FROM_CLASS (klass),
768       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstParseBinClass, drained),
769       NULL, NULL, NULL, G_TYPE_NONE, 0, G_TYPE_NONE);
770 
771   g_object_class_install_property (gobject_klass, PROP_SUBTITLE_ENCODING,
772       g_param_spec_string ("subtitle-encoding", "subtitle encoding",
773           "Encoding to assume if input subtitles are not in UTF-8 encoding. "
774           "If not set, the GST_SUBTITLE_ENCODING environment variable will "
775           "be checked for an encoding to use. If that is not set either, "
776           "ISO-8859-15 will be assumed.", NULL,
777           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
778 
779   g_object_class_install_property (gobject_klass, PROP_SINK_CAPS,
780       g_param_spec_boxed ("sink-caps", "Sink Caps",
781           "The caps of the input data. (NULL = use typefind element)",
782           GST_TYPE_CAPS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
783 
784   /**
785    * GstParseBin::expose-all-streams:
786    *
787    * Expose streams of unknown type.
788    *
789    * If set to %FALSE, then only the streams that can be parsed to the final
790    * caps (see 'caps' property) will have a pad exposed. Streams that do not
791    * match those caps but could have been parsed will not have parser plugged
792    * in internally and will not have a pad exposed.
793    */
794   g_object_class_install_property (gobject_klass, PROP_EXPOSE_ALL_STREAMS,
795       g_param_spec_boolean ("expose-all-streams", "Expose All Streams",
796           "Expose all streams, including those of unknown type or that don't match the 'caps' property",
797           DEFAULT_EXPOSE_ALL_STREAMS,
798           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
799 
800   /**
801    * GstParseBin2::connection-speed:
802    *
803    * Network connection speed in kbps (0 = unknownw)
804    */
805   g_object_class_install_property (gobject_klass, PROP_CONNECTION_SPEED,
806       g_param_spec_uint64 ("connection-speed", "Connection Speed",
807           "Network connection speed in kbps (0 = unknown)",
808           0, G_MAXUINT64 / 1000, DEFAULT_CONNECTION_SPEED,
809           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
810 
811   klass->autoplug_continue =
812       GST_DEBUG_FUNCPTR (gst_parse_bin_autoplug_continue);
813   klass->autoplug_factories =
814       GST_DEBUG_FUNCPTR (gst_parse_bin_autoplug_factories);
815   klass->autoplug_sort = GST_DEBUG_FUNCPTR (gst_parse_bin_autoplug_sort);
816   klass->autoplug_select = GST_DEBUG_FUNCPTR (gst_parse_bin_autoplug_select);
817   klass->autoplug_query = GST_DEBUG_FUNCPTR (gst_parse_bin_autoplug_query);
818 
819   gst_element_class_add_pad_template (gstelement_klass,
820       gst_static_pad_template_get (&parse_bin_sink_template));
821   gst_element_class_add_pad_template (gstelement_klass,
822       gst_static_pad_template_get (&parse_bin_src_template));
823 
824   gst_element_class_set_static_metadata (gstelement_klass,
825       "Parse Bin", "Generic/Bin/Parser",
826       "Parse and de-multiplex to elementary stream",
827       "Jan Schmidt <jan@centricular.com>, "
828       "Edward Hervey <edward@centricular.com>");
829 
830   gstelement_klass->change_state =
831       GST_DEBUG_FUNCPTR (gst_parse_bin_change_state);
832 
833   gstbin_klass->handle_message =
834       GST_DEBUG_FUNCPTR (gst_parse_bin_handle_message);
835 
836   g_type_class_ref (GST_TYPE_PARSE_PAD);
837 }
838 
839 static void
gst_parse_bin_update_factories_list(GstParseBin * parsebin)840 gst_parse_bin_update_factories_list (GstParseBin * parsebin)
841 {
842   guint cookie;
843 
844   cookie = gst_registry_get_feature_list_cookie (gst_registry_get ());
845   if (!parsebin->factories || parsebin->factories_cookie != cookie) {
846     if (parsebin->factories)
847       gst_plugin_feature_list_free (parsebin->factories);
848     parsebin->factories =
849         gst_element_factory_list_get_elements
850         (GST_ELEMENT_FACTORY_TYPE_DECODABLE, GST_RANK_MARGINAL);
851     parsebin->factories =
852         g_list_sort (parsebin->factories,
853         gst_playback_utils_compare_factories_func);
854     parsebin->factories_cookie = cookie;
855   }
856 }
857 
858 static void
gst_parse_bin_init(GstParseBin * parse_bin)859 gst_parse_bin_init (GstParseBin * parse_bin)
860 {
861   /* first filter out the interesting element factories */
862   g_mutex_init (&parse_bin->factories_lock);
863 
864   /* we create the typefind element only once */
865   parse_bin->typefind = gst_element_factory_make ("typefind", "typefind");
866   if (!parse_bin->typefind) {
867     g_warning ("can't find typefind element, ParseBin will not work");
868   } else {
869     GstPad *pad;
870     GstPad *gpad;
871     GstPadTemplate *pad_tmpl;
872 
873     /* add the typefind element */
874     if (!gst_bin_add (GST_BIN (parse_bin), parse_bin->typefind)) {
875       g_warning ("Could not add typefind element, ParseBin will not work");
876       gst_object_unref (parse_bin->typefind);
877       parse_bin->typefind = NULL;
878     }
879 
880     /* get the sinkpad */
881     pad = gst_element_get_static_pad (parse_bin->typefind, "sink");
882 
883     /* get the pad template */
884     pad_tmpl = gst_static_pad_template_get (&parse_bin_sink_template);
885 
886     /* ghost the sink pad to ourself */
887     gpad = gst_ghost_pad_new_from_template ("sink", pad, pad_tmpl);
888     gst_pad_set_active (gpad, TRUE);
889     gst_element_add_pad (GST_ELEMENT (parse_bin), gpad);
890 
891     gst_object_unref (pad_tmpl);
892     gst_object_unref (pad);
893   }
894 
895   g_mutex_init (&parse_bin->expose_lock);
896   parse_bin->parse_chain = NULL;
897 
898   g_mutex_init (&parse_bin->dyn_lock);
899   parse_bin->shutdown = FALSE;
900   parse_bin->blocked_pads = NULL;
901 
902   g_mutex_init (&parse_bin->subtitle_lock);
903 
904   parse_bin->encoding = g_strdup (DEFAULT_SUBTITLE_ENCODING);
905 
906   parse_bin->expose_allstreams = DEFAULT_EXPOSE_ALL_STREAMS;
907   parse_bin->connection_speed = DEFAULT_CONNECTION_SPEED;
908 
909   g_mutex_init (&parse_bin->cleanup_lock);
910   parse_bin->cleanup_thread = NULL;
911 
912   GST_OBJECT_FLAG_SET (parse_bin, GST_BIN_FLAG_STREAMS_AWARE);
913 }
914 
915 static void
gst_parse_bin_dispose(GObject * object)916 gst_parse_bin_dispose (GObject * object)
917 {
918   GstParseBin *parse_bin;
919 
920   parse_bin = GST_PARSE_BIN (object);
921 
922   if (parse_bin->factories)
923     gst_plugin_feature_list_free (parse_bin->factories);
924   parse_bin->factories = NULL;
925 
926   if (parse_bin->parse_chain)
927     gst_parse_chain_free (parse_bin->parse_chain);
928   parse_bin->parse_chain = NULL;
929 
930   g_free (parse_bin->encoding);
931   parse_bin->encoding = NULL;
932 
933   g_list_free (parse_bin->subtitles);
934   parse_bin->subtitles = NULL;
935 
936   G_OBJECT_CLASS (parent_class)->dispose (object);
937 }
938 
939 static void
gst_parse_bin_finalize(GObject * object)940 gst_parse_bin_finalize (GObject * object)
941 {
942   GstParseBin *parse_bin;
943 
944   parse_bin = GST_PARSE_BIN (object);
945 
946   g_mutex_clear (&parse_bin->expose_lock);
947   g_mutex_clear (&parse_bin->dyn_lock);
948   g_mutex_clear (&parse_bin->subtitle_lock);
949   g_mutex_clear (&parse_bin->factories_lock);
950   g_mutex_clear (&parse_bin->cleanup_lock);
951 
952   G_OBJECT_CLASS (parent_class)->finalize (object);
953 }
954 
955 static void
gst_parse_bin_set_sink_caps(GstParseBin * parsebin,GstCaps * caps)956 gst_parse_bin_set_sink_caps (GstParseBin * parsebin, GstCaps * caps)
957 {
958   GST_DEBUG_OBJECT (parsebin, "Setting new caps: %" GST_PTR_FORMAT, caps);
959 
960   g_object_set (parsebin->typefind, "force-caps", caps, NULL);
961 }
962 
963 static GstCaps *
gst_parse_bin_get_sink_caps(GstParseBin * parsebin)964 gst_parse_bin_get_sink_caps (GstParseBin * parsebin)
965 {
966   GstCaps *caps;
967 
968   GST_DEBUG_OBJECT (parsebin, "Getting currently set caps");
969 
970   g_object_get (parsebin->typefind, "force-caps", &caps, NULL);
971 
972   return caps;
973 }
974 
975 static void
gst_parse_bin_set_subs_encoding(GstParseBin * parsebin,const gchar * encoding)976 gst_parse_bin_set_subs_encoding (GstParseBin * parsebin, const gchar * encoding)
977 {
978   GList *walk;
979 
980   GST_DEBUG_OBJECT (parsebin, "Setting new encoding: %s",
981       GST_STR_NULL (encoding));
982 
983   SUBTITLE_LOCK (parsebin);
984   g_free (parsebin->encoding);
985   parsebin->encoding = g_strdup (encoding);
986 
987   /* set the subtitle encoding on all added elements */
988   for (walk = parsebin->subtitles; walk; walk = g_list_next (walk)) {
989     g_object_set (G_OBJECT (walk->data), "subtitle-encoding",
990         parsebin->encoding, NULL);
991   }
992   SUBTITLE_UNLOCK (parsebin);
993 }
994 
995 static gchar *
gst_parse_bin_get_subs_encoding(GstParseBin * parsebin)996 gst_parse_bin_get_subs_encoding (GstParseBin * parsebin)
997 {
998   gchar *encoding;
999 
1000   GST_DEBUG_OBJECT (parsebin, "Getting currently set encoding");
1001 
1002   SUBTITLE_LOCK (parsebin);
1003   encoding = g_strdup (parsebin->encoding);
1004   SUBTITLE_UNLOCK (parsebin);
1005 
1006   return encoding;
1007 }
1008 
1009 static void
gst_parse_bin_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)1010 gst_parse_bin_set_property (GObject * object, guint prop_id,
1011     const GValue * value, GParamSpec * pspec)
1012 {
1013   GstParseBin *parsebin;
1014 
1015   parsebin = GST_PARSE_BIN (object);
1016 
1017   switch (prop_id) {
1018     case PROP_SUBTITLE_ENCODING:
1019       gst_parse_bin_set_subs_encoding (parsebin, g_value_get_string (value));
1020       break;
1021     case PROP_SINK_CAPS:
1022       gst_parse_bin_set_sink_caps (parsebin, g_value_get_boxed (value));
1023       break;
1024     case PROP_EXPOSE_ALL_STREAMS:
1025       parsebin->expose_allstreams = g_value_get_boolean (value);
1026       break;
1027     case PROP_CONNECTION_SPEED:
1028       GST_OBJECT_LOCK (parsebin);
1029       parsebin->connection_speed = g_value_get_uint64 (value) * 1000;
1030       GST_OBJECT_UNLOCK (parsebin);
1031       break;
1032     default:
1033       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1034       break;
1035   }
1036 }
1037 
1038 static void
gst_parse_bin_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)1039 gst_parse_bin_get_property (GObject * object, guint prop_id,
1040     GValue * value, GParamSpec * pspec)
1041 {
1042   GstParseBin *parsebin;
1043 
1044   parsebin = GST_PARSE_BIN (object);
1045   switch (prop_id) {
1046     case PROP_SUBTITLE_ENCODING:
1047       g_value_take_string (value, gst_parse_bin_get_subs_encoding (parsebin));
1048       break;
1049     case PROP_SINK_CAPS:
1050       g_value_take_boxed (value, gst_parse_bin_get_sink_caps (parsebin));
1051       break;
1052     case PROP_EXPOSE_ALL_STREAMS:
1053       g_value_set_boolean (value, parsebin->expose_allstreams);
1054       break;
1055     case PROP_CONNECTION_SPEED:
1056       GST_OBJECT_LOCK (parsebin);
1057       g_value_set_uint64 (value, parsebin->connection_speed / 1000);
1058       GST_OBJECT_UNLOCK (parsebin);
1059       break;
1060     default:
1061       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1062       break;
1063   }
1064 }
1065 
1066 
1067 /*****
1068  * Default autoplug signal handlers
1069  *****/
1070 static gboolean
gst_parse_bin_autoplug_continue(GstElement * element,GstPad * pad,GstCaps * caps)1071 gst_parse_bin_autoplug_continue (GstElement * element, GstPad * pad,
1072     GstCaps * caps)
1073 {
1074   static GstStaticCaps raw_caps = GST_STATIC_CAPS (DEFAULT_RAW_CAPS);
1075 
1076   GST_DEBUG_OBJECT (element, "caps %" GST_PTR_FORMAT, caps);
1077 
1078   /* If it matches our target caps, expose it */
1079   if (gst_caps_can_intersect (caps, gst_static_caps_get (&raw_caps))) {
1080     GST_DEBUG_OBJECT (element, "autoplug-continue returns FALSE");
1081     return FALSE;
1082   }
1083 
1084   GST_DEBUG_OBJECT (element, "autoplug-continue returns TRUE");
1085 
1086   return TRUE;
1087 }
1088 
1089 static GValueArray *
gst_parse_bin_autoplug_factories(GstElement * element,GstPad * pad,GstCaps * caps)1090 gst_parse_bin_autoplug_factories (GstElement * element, GstPad * pad,
1091     GstCaps * caps)
1092 {
1093   GList *list, *tmp;
1094   GValueArray *result;
1095   GstParseBin *parsebin = GST_PARSE_BIN_CAST (element);
1096 
1097   GST_DEBUG_OBJECT (element, "finding factories");
1098 
1099   /* return all compatible factories for caps */
1100   g_mutex_lock (&parsebin->factories_lock);
1101   gst_parse_bin_update_factories_list (parsebin);
1102   list =
1103       gst_element_factory_list_filter (parsebin->factories, caps, GST_PAD_SINK,
1104       gst_caps_is_fixed (caps));
1105   g_mutex_unlock (&parsebin->factories_lock);
1106 
1107   result = g_value_array_new (g_list_length (list));
1108   for (tmp = list; tmp; tmp = tmp->next) {
1109     GstElementFactory *factory = GST_ELEMENT_FACTORY_CAST (tmp->data);
1110     GValue val = { 0, };
1111 
1112     g_value_init (&val, G_TYPE_OBJECT);
1113     g_value_set_object (&val, factory);
1114     g_value_array_append (result, &val);
1115     g_value_unset (&val);
1116   }
1117   gst_plugin_feature_list_free (list);
1118 
1119   GST_DEBUG_OBJECT (element, "autoplug-factories returns %p", result);
1120 
1121   return result;
1122 }
1123 
1124 static GValueArray *
gst_parse_bin_autoplug_sort(GstElement * element,GstPad * pad,GstCaps * caps,GValueArray * factories)1125 gst_parse_bin_autoplug_sort (GstElement * element, GstPad * pad,
1126     GstCaps * caps, GValueArray * factories)
1127 {
1128   return NULL;
1129 }
1130 
1131 static GstAutoplugSelectResult
gst_parse_bin_autoplug_select(GstElement * element,GstPad * pad,GstCaps * caps,GstElementFactory * factory)1132 gst_parse_bin_autoplug_select (GstElement * element, GstPad * pad,
1133     GstCaps * caps, GstElementFactory * factory)
1134 {
1135   /* Try factory. */
1136   return GST_AUTOPLUG_SELECT_TRY;
1137 }
1138 
1139 static gboolean
gst_parse_bin_autoplug_query(GstElement * element,GstPad * pad,GstQuery * query)1140 gst_parse_bin_autoplug_query (GstElement * element, GstPad * pad,
1141     GstQuery * query)
1142 {
1143   /* No query handled here */
1144   return FALSE;
1145 }
1146 
1147 /********
1148  * Discovery methods
1149  *****/
1150 
1151 static gboolean is_demuxer_element (GstElement * srcelement);
1152 
1153 static gboolean connect_pad (GstParseBin * parsebin, GstElement * src,
1154     GstParsePad * parsepad, GstPad * pad, GstCaps * caps,
1155     GValueArray * factories, GstParseChain * chain, gchar ** deadend_details);
1156 static GList *connect_element (GstParseBin * parsebin, GstParseElement * pelem,
1157     GstParseChain * chain);
1158 static void expose_pad (GstParseBin * parsebin, GstElement * src,
1159     GstParsePad * parsepad, GstPad * pad, GstCaps * caps,
1160     GstParseChain * chain);
1161 
1162 static void pad_added_cb (GstElement * element, GstPad * pad,
1163     GstParseChain * chain);
1164 static void pad_removed_cb (GstElement * element, GstPad * pad,
1165     GstParseChain * chain);
1166 static void no_more_pads_cb (GstElement * element, GstParseChain * chain);
1167 
1168 static GstParseGroup *gst_parse_chain_get_current_group (GstParseChain * chain);
1169 
1170 static gboolean
clear_sticky_events(GstPad * pad,GstEvent ** event,gpointer user_data)1171 clear_sticky_events (GstPad * pad, GstEvent ** event, gpointer user_data)
1172 {
1173   GST_DEBUG_OBJECT (pad, "clearing sticky event %" GST_PTR_FORMAT, *event);
1174   gst_event_unref (*event);
1175   *event = NULL;
1176   return TRUE;
1177 }
1178 
1179 static gboolean
copy_sticky_events(GstPad * pad,GstEvent ** eventptr,gpointer user_data)1180 copy_sticky_events (GstPad * pad, GstEvent ** eventptr, gpointer user_data)
1181 {
1182   GstParsePad *ppad = GST_PARSE_PAD (user_data);
1183   GstEvent *event = gst_event_ref (*eventptr);
1184 
1185   switch (GST_EVENT_TYPE (event)) {
1186     case GST_EVENT_CAPS:{
1187       GstCaps *caps = NULL;
1188       gst_event_parse_caps (event, &caps);
1189       gst_parse_pad_update_caps (ppad, caps);
1190       break;
1191     }
1192     case GST_EVENT_STREAM_START:{
1193       event = gst_parse_pad_stream_start_event (ppad, event);
1194       break;
1195     }
1196     case GST_EVENT_STREAM_COLLECTION:{
1197       GstStreamCollection *collection = NULL;
1198       gst_event_parse_stream_collection (event, &collection);
1199       gst_parse_pad_update_stream_collection (ppad, collection);
1200       break;
1201     }
1202     default:
1203       break;
1204   }
1205 
1206   GST_DEBUG_OBJECT (ppad, "store sticky event %" GST_PTR_FORMAT, event);
1207   gst_pad_store_sticky_event (GST_PAD_CAST (ppad), event);
1208   gst_event_unref (event);
1209 
1210   return TRUE;
1211 }
1212 
1213 static void
parse_pad_set_target(GstParsePad * parsepad,GstPad * target)1214 parse_pad_set_target (GstParsePad * parsepad, GstPad * target)
1215 {
1216   GstPad *old_target = gst_ghost_pad_get_target (GST_GHOST_PAD_CAST (parsepad));
1217   if (old_target)
1218     gst_object_unref (old_target);
1219 
1220   if (old_target == target)
1221     return;
1222 
1223   gst_pad_sticky_events_foreach (GST_PAD_CAST (parsepad),
1224       clear_sticky_events, NULL);
1225   gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (parsepad), target);
1226 
1227   if (target == NULL) {
1228     GST_LOG_OBJECT (parsepad->parsebin, "Setting pad %" GST_PTR_FORMAT
1229         " target to NULL", parsepad);
1230   } else {
1231     GST_LOG_OBJECT (parsepad->parsebin, "Setting pad %" GST_PTR_FORMAT
1232         " target to %" GST_PTR_FORMAT, parsepad, target);
1233     gst_pad_sticky_events_foreach (target, copy_sticky_events, parsepad);
1234   }
1235 }
1236 
1237 /* called when a new pad is discovered. It will perform some basic actions
1238  * before trying to link something to it.
1239  *
1240  *  - Check the caps, don't do anything when there are no caps or when they have
1241  *    no good type.
1242  *  - signal AUTOPLUG_CONTINUE to check if we need to continue autoplugging this
1243  *    pad.
1244  *  - if the caps are non-fixed, setup a handler to continue autoplugging when
1245  *    the caps become fixed (connect to notify::caps).
1246  *  - get list of factories to autoplug.
1247  *  - continue autoplugging to one of the factories.
1248  */
1249 static void
analyze_new_pad(GstParseBin * parsebin,GstElement * src,GstPad * pad,GstCaps * caps,GstParseChain * chain)1250 analyze_new_pad (GstParseBin * parsebin, GstElement * src, GstPad * pad,
1251     GstCaps * caps, GstParseChain * chain)
1252 {
1253   gboolean apcontinue = TRUE;
1254   GValueArray *factories = NULL, *result = NULL;
1255   GstParsePad *parsepad;
1256   GstElementFactory *factory;
1257   const gchar *classification;
1258   gboolean is_parser_converter = FALSE;
1259   gboolean res;
1260   gchar *deadend_details = NULL;
1261 
1262   GST_DEBUG_OBJECT (parsebin, "Pad %s:%s caps:%" GST_PTR_FORMAT,
1263       GST_DEBUG_PAD_NAME (pad), caps);
1264 
1265   if (chain->elements
1266       && src != ((GstParseElement *) chain->elements->data)->element
1267       && src != ((GstParseElement *) chain->elements->data)->capsfilter) {
1268     GST_ERROR_OBJECT (parsebin,
1269         "New pad from not the last element in this chain");
1270     return;
1271   }
1272 
1273   if (chain->demuxer) {
1274     GstParseGroup *group;
1275     GstParseChain *oldchain = chain;
1276     GstParseElement *demux = (chain->elements ? chain->elements->data : NULL);
1277 
1278     if (chain->current_pad)
1279       gst_object_unref (chain->current_pad);
1280     chain->current_pad = NULL;
1281 
1282     /* we are adding a new pad for a demuxer (see is_demuxer_element(),
1283      * start a new chain for it */
1284     CHAIN_MUTEX_LOCK (oldchain);
1285     group = gst_parse_chain_get_current_group (chain);
1286     if (group && !g_list_find (group->children, chain)) {
1287       chain = gst_parse_chain_new (parsebin, group, pad, caps);
1288       group->children = g_list_prepend (group->children, chain);
1289     }
1290     CHAIN_MUTEX_UNLOCK (oldchain);
1291     if (!group) {
1292       GST_WARNING_OBJECT (parsebin, "No current group");
1293       return;
1294     }
1295 
1296     /* If this is not a dynamic pad demuxer, we're no-more-pads
1297      * already before anything else happens
1298      */
1299     if (demux == NULL || !demux->no_more_pads_id)
1300       group->no_more_pads = TRUE;
1301   }
1302 
1303   /* From here on we own a reference to the caps as
1304    * we might create new caps below and would need
1305    * to unref them later */
1306   if (caps)
1307     gst_caps_ref (caps);
1308 
1309   if ((caps == NULL) || gst_caps_is_empty (caps))
1310     goto unknown_type;
1311 
1312   if (gst_caps_is_any (caps))
1313     goto any_caps;
1314 
1315   if (!chain->current_pad)
1316     chain->current_pad = gst_parse_pad_new (parsebin, chain);
1317 
1318   parsepad = gst_object_ref (chain->current_pad);
1319   gst_pad_set_active (GST_PAD_CAST (parsepad), TRUE);
1320   parse_pad_set_target (parsepad, pad);
1321 
1322   /* 1. Emit 'autoplug-continue' the result will tell us if this pads needs
1323    * further autoplugging. Only do this for fixed caps, for unfixed caps
1324    * we will later come here again from the notify::caps handler. The
1325    * problem with unfixed caps is that, we can't reliably tell if the output
1326    * is e.g. accepted by a sink because only parts of the possible final
1327    * caps might be accepted by the sink. */
1328   if (gst_caps_is_fixed (caps))
1329     g_signal_emit (G_OBJECT (parsebin),
1330         gst_parse_bin_signals[SIGNAL_AUTOPLUG_CONTINUE], 0, parsepad, caps,
1331         &apcontinue);
1332   else
1333     apcontinue = TRUE;
1334 
1335   /* 1.a if autoplug-continue is FALSE or caps is a raw format, goto pad_is_final */
1336   if (!apcontinue)
1337     goto expose_pad;
1338 
1339   /* 1.b For Parser/Converter that can output different stream formats
1340    * we insert a capsfilter with the sorted caps of all possible next
1341    * elements and continue with the capsfilter srcpad */
1342   factory = gst_element_get_factory (src);
1343   classification =
1344       gst_element_factory_get_metadata (factory, GST_ELEMENT_METADATA_KLASS);
1345   is_parser_converter = (strstr (classification, "Parser")
1346       && strstr (classification, "Converter"));
1347 
1348   /* FIXME: We just need to be sure that the next element is not a parser */
1349   /* 1.c when the caps are not fixed yet, we can't be sure what element to
1350    * connect. We delay autoplugging until the caps are fixed */
1351   if (!is_parser_converter && !gst_caps_is_fixed (caps)) {
1352     goto non_fixed;
1353   } else if (!is_parser_converter) {
1354     gst_caps_unref (caps);
1355     caps = gst_pad_get_current_caps (pad);
1356     if (!caps) {
1357       GST_DEBUG_OBJECT (parsebin,
1358           "No final caps set yet, delaying autoplugging");
1359       gst_object_unref (parsepad);
1360       goto setup_caps_delay;
1361     }
1362   }
1363 
1364   /* 1.d else get the factories and if there's no compatible factory goto
1365    * unknown_type */
1366   g_signal_emit (G_OBJECT (parsebin),
1367       gst_parse_bin_signals[SIGNAL_AUTOPLUG_FACTORIES], 0, parsepad, caps,
1368       &factories);
1369 
1370   /* NULL means that we can expose the pad */
1371   if (factories == NULL)
1372     goto expose_pad;
1373 
1374   /* if the array is empty, we have a type for which we have no handler */
1375   if (factories->n_values == 0) {
1376     g_value_array_free (factories);
1377 
1378     if (parsebin->expose_allstreams) {
1379       /* If we expose all streams, we only need to inform the application about
1380        * a missing handler but still expose it. We also make sure the stream
1381        * type is unknown. */
1382       if (parsepad->in_a_fallback_collection) {
1383         GstStream *newstream;
1384         GST_LOG_OBJECT (parsepad, "Existing GstStream %" GST_PTR_FORMAT,
1385             parsepad->active_stream);
1386         g_assert (parsepad->active_stream);
1387         newstream =
1388             gst_stream_new (gst_stream_get_stream_id (parsepad->active_stream),
1389             caps, GST_STREAM_TYPE_UNKNOWN,
1390             gst_stream_get_stream_flags (parsepad->active_stream));
1391         gst_object_replace ((GstObject **) & parsepad->active_stream,
1392             (GstObject *) newstream);
1393         GST_LOG_OBJECT (parsepad, "New GstStream %" GST_PTR_FORMAT,
1394             parsepad->active_stream);
1395       }
1396       gst_element_post_message (GST_ELEMENT_CAST (parsebin),
1397           gst_missing_decoder_message_new (GST_ELEMENT_CAST (parsebin), caps));
1398       goto expose_pad;
1399     }
1400     /* Else we will bail out */
1401     gst_object_unref (parsepad);
1402     goto unknown_type;
1403   }
1404 
1405   /* 1.e sort some more. */
1406   g_signal_emit (G_OBJECT (parsebin),
1407       gst_parse_bin_signals[SIGNAL_AUTOPLUG_SORT], 0, parsepad, caps, factories,
1408       &result);
1409   if (result) {
1410     g_value_array_free (factories);
1411     factories = result;
1412   }
1413 
1414   /* 1.g now get the factory template caps and insert the capsfilter if this
1415    * is a parser/converter
1416    */
1417   if (is_parser_converter) {
1418     GstCaps *filter_caps;
1419     gint i;
1420     GstPad *p;
1421     GstParseElement *pelem;
1422 
1423     g_assert (chain->elements != NULL);
1424     pelem = (GstParseElement *) chain->elements->data;
1425 
1426     filter_caps = gst_caps_new_empty ();
1427     for (i = 0; i < factories->n_values; i++) {
1428       GstElementFactory *factory =
1429           g_value_get_object (g_value_array_get_nth (factories, i));
1430       GstCaps *tcaps, *intersection;
1431       const GList *tmps;
1432 
1433       GST_DEBUG ("Trying factory %s",
1434           gst_plugin_feature_get_name (GST_PLUGIN_FEATURE (factory)));
1435 
1436       if (gst_element_get_factory (src) == factory ||
1437           gst_element_factory_list_is_type (factory,
1438               GST_ELEMENT_FACTORY_TYPE_PARSER)) {
1439         GST_DEBUG ("Skipping factory");
1440         continue;
1441       }
1442 
1443       for (tmps = gst_element_factory_get_static_pad_templates (factory); tmps;
1444           tmps = tmps->next) {
1445         GstStaticPadTemplate *st = (GstStaticPadTemplate *) tmps->data;
1446         if (st->direction != GST_PAD_SINK || st->presence != GST_PAD_ALWAYS)
1447           continue;
1448         tcaps = gst_static_pad_template_get_caps (st);
1449         intersection =
1450             gst_caps_intersect_full (tcaps, caps, GST_CAPS_INTERSECT_FIRST);
1451         filter_caps = gst_caps_merge (filter_caps, intersection);
1452         gst_caps_unref (tcaps);
1453       }
1454     }
1455 
1456     /* Append the parser caps to prevent any not-negotiated errors */
1457     filter_caps = gst_caps_merge (filter_caps, gst_caps_ref (caps));
1458 
1459     pelem->capsfilter = gst_element_factory_make ("capsfilter", NULL);
1460     g_object_set (G_OBJECT (pelem->capsfilter), "caps", filter_caps, NULL);
1461     gst_caps_unref (filter_caps);
1462     gst_element_set_state (pelem->capsfilter, GST_STATE_PAUSED);
1463     gst_bin_add (GST_BIN_CAST (parsebin), gst_object_ref (pelem->capsfilter));
1464 
1465     parse_pad_set_target (parsepad, NULL);
1466     p = gst_element_get_static_pad (pelem->capsfilter, "sink");
1467     gst_pad_link_full (pad, p, GST_PAD_LINK_CHECK_NOTHING);
1468     gst_object_unref (p);
1469     p = gst_element_get_static_pad (pelem->capsfilter, "src");
1470     parse_pad_set_target (parsepad, p);
1471     pad = p;
1472 
1473     gst_caps_unref (caps);
1474 
1475     caps = gst_pad_get_current_caps (pad);
1476     if (!caps) {
1477       GST_DEBUG_OBJECT (parsebin,
1478           "No final caps set yet, delaying autoplugging");
1479       gst_object_unref (parsepad);
1480       g_value_array_free (factories);
1481       goto setup_caps_delay;
1482     }
1483   }
1484 
1485   /* 1.h else continue autoplugging something from the list. */
1486   GST_LOG_OBJECT (pad, "Let's continue discovery on this pad");
1487   res =
1488       connect_pad (parsebin, src, parsepad, pad, caps, factories, chain,
1489       &deadend_details);
1490 
1491   /* Need to unref the capsfilter srcpad here if
1492    * we inserted a capsfilter */
1493   if (is_parser_converter)
1494     gst_object_unref (pad);
1495 
1496   gst_object_unref (parsepad);
1497   g_value_array_free (factories);
1498 
1499   if (!res)
1500     goto unknown_type;
1501 
1502   gst_caps_unref (caps);
1503 
1504   return;
1505 
1506 expose_pad:
1507   {
1508     GST_LOG_OBJECT (parsebin, "Pad is final. autoplug-continue:%d", apcontinue);
1509     expose_pad (parsebin, src, parsepad, pad, caps, chain);
1510     gst_object_unref (parsepad);
1511     gst_caps_unref (caps);
1512     return;
1513   }
1514 
1515 unknown_type:
1516   {
1517     GST_LOG_OBJECT (pad, "Unknown type, posting message and firing signal");
1518 
1519     chain->deadend_details = deadend_details;
1520     chain->deadend = TRUE;
1521     chain->drained = TRUE;
1522     chain->endcaps = caps;
1523     gst_object_replace ((GstObject **) & chain->current_pad, NULL);
1524 
1525     gst_element_post_message (GST_ELEMENT_CAST (parsebin),
1526         gst_missing_decoder_message_new (GST_ELEMENT_CAST (parsebin), caps));
1527 
1528     g_signal_emit (G_OBJECT (parsebin),
1529         gst_parse_bin_signals[SIGNAL_UNKNOWN_TYPE], 0, pad, caps);
1530 
1531     /* Try to expose anything */
1532     EXPOSE_LOCK (parsebin);
1533     if (parsebin->parse_chain) {
1534       if (gst_parse_chain_is_complete (parsebin->parse_chain)) {
1535         gst_parse_bin_expose (parsebin);
1536       }
1537     }
1538     EXPOSE_UNLOCK (parsebin);
1539 
1540     if (src == parsebin->typefind) {
1541       if (!caps || gst_caps_is_empty (caps)) {
1542         GST_ELEMENT_ERROR (parsebin, STREAM, TYPE_NOT_FOUND,
1543             (_("Could not determine type of stream")), (NULL));
1544       }
1545     }
1546     return;
1547   }
1548 #if 1
1549 non_fixed:
1550   {
1551     GST_DEBUG_OBJECT (pad, "pad has non-fixed caps delay autoplugging");
1552     gst_object_unref (parsepad);
1553     goto setup_caps_delay;
1554   }
1555 #endif
1556 any_caps:
1557   {
1558     GST_DEBUG_OBJECT (pad, "pad has ANY caps, delaying auto-plugging");
1559     goto setup_caps_delay;
1560   }
1561 setup_caps_delay:
1562   {
1563     GstPendingPad *ppad;
1564 
1565     /* connect to caps notification */
1566     CHAIN_MUTEX_LOCK (chain);
1567     GST_LOG_OBJECT (parsebin, "Chain %p has now %d dynamic pads", chain,
1568         g_list_length (chain->pending_pads));
1569     ppad = g_slice_new0 (GstPendingPad);
1570     ppad->pad = gst_object_ref (pad);
1571     ppad->chain = chain;
1572     ppad->event_probe_id =
1573         gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM,
1574         pad_event_cb, ppad, NULL);
1575     chain->pending_pads = g_list_prepend (chain->pending_pads, ppad);
1576     ppad->notify_caps_id = g_signal_connect (pad, "notify::caps",
1577         G_CALLBACK (caps_notify_cb), chain);
1578     CHAIN_MUTEX_UNLOCK (chain);
1579 
1580     /* If we're here because we have a Parser/Converter
1581      * we have to unref the pad */
1582     if (is_parser_converter)
1583       gst_object_unref (pad);
1584     if (caps)
1585       gst_caps_unref (caps);
1586 
1587     return;
1588   }
1589 }
1590 
1591 static void
add_error_filter(GstParseBin * parsebin,GstElement * element)1592 add_error_filter (GstParseBin * parsebin, GstElement * element)
1593 {
1594   GST_OBJECT_LOCK (parsebin);
1595   parsebin->filtered = g_list_prepend (parsebin->filtered, element);
1596   GST_OBJECT_UNLOCK (parsebin);
1597 }
1598 
1599 static void
remove_error_filter(GstParseBin * parsebin,GstElement * element,GstMessage ** error)1600 remove_error_filter (GstParseBin * parsebin, GstElement * element,
1601     GstMessage ** error)
1602 {
1603   GList *l;
1604 
1605   GST_OBJECT_LOCK (parsebin);
1606   parsebin->filtered = g_list_remove (parsebin->filtered, element);
1607 
1608   if (error)
1609     *error = NULL;
1610 
1611   l = parsebin->filtered_errors;
1612   while (l) {
1613     GstMessage *msg = l->data;
1614 
1615     if (GST_MESSAGE_SRC (msg) == GST_OBJECT_CAST (element)) {
1616       /* Get the last error of this element, i.e. the earliest */
1617       if (error)
1618         gst_message_replace (error, msg);
1619       gst_message_unref (msg);
1620       l = parsebin->filtered_errors =
1621           g_list_delete_link (parsebin->filtered_errors, l);
1622     } else {
1623       l = l->next;
1624     }
1625   }
1626   GST_OBJECT_UNLOCK (parsebin);
1627 }
1628 
1629 typedef struct
1630 {
1631   gboolean ret;
1632   GstPad *peer;
1633 } SendStickyEventsData;
1634 
1635 static gboolean
send_sticky_event(GstPad * pad,GstEvent ** event,gpointer user_data)1636 send_sticky_event (GstPad * pad, GstEvent ** event, gpointer user_data)
1637 {
1638   SendStickyEventsData *data = user_data;
1639   gboolean ret;
1640 
1641   ret = gst_pad_send_event (data->peer, gst_event_ref (*event));
1642   if (!ret)
1643     data->ret = FALSE;
1644 
1645   return data->ret;
1646 }
1647 
1648 static gboolean
send_sticky_events(GstParseBin * parsebin,GstPad * pad)1649 send_sticky_events (GstParseBin * parsebin, GstPad * pad)
1650 {
1651   SendStickyEventsData data;
1652 
1653   data.ret = TRUE;
1654   data.peer = gst_pad_get_peer (pad);
1655 
1656   gst_pad_sticky_events_foreach (pad, send_sticky_event, &data);
1657 
1658   gst_object_unref (data.peer);
1659 
1660   return data.ret;
1661 }
1662 
1663 static gchar *
error_message_to_string(GstMessage * msg)1664 error_message_to_string (GstMessage * msg)
1665 {
1666   GError *err;
1667   gchar *debug, *message, *full_message;
1668 
1669   gst_message_parse_error (msg, &err, &debug);
1670 
1671   message = gst_error_get_message (err->domain, err->code);
1672 
1673   if (debug)
1674     full_message = g_strdup_printf ("%s\n%s\n%s", message, err->message, debug);
1675   else
1676     full_message = g_strdup_printf ("%s\n%s", message, err->message);
1677 
1678   g_free (message);
1679   g_free (debug);
1680   g_clear_error (&err);
1681 
1682   return full_message;
1683 }
1684 
1685 /* We consider elements as "simple demuxer" when they are a demuxer
1686  * with one and only one ALWAYS source pad.
1687  */
1688 static gboolean
is_simple_demuxer_factory(GstElementFactory * factory)1689 is_simple_demuxer_factory (GstElementFactory * factory)
1690 {
1691   if (strstr (gst_element_factory_get_metadata (factory,
1692               GST_ELEMENT_METADATA_KLASS), "Demuxer")) {
1693     const GList *tmp;
1694     gint num_alway_srcpads = 0;
1695 
1696     for (tmp = gst_element_factory_get_static_pad_templates (factory);
1697         tmp; tmp = tmp->next) {
1698       GstStaticPadTemplate *template = tmp->data;
1699 
1700       if (template->direction == GST_PAD_SRC) {
1701         if (template->presence == GST_PAD_ALWAYS) {
1702           if (num_alway_srcpads >= 0)
1703             num_alway_srcpads++;
1704         } else {
1705           num_alway_srcpads = -1;
1706         }
1707       }
1708 
1709     }
1710 
1711     if (num_alway_srcpads == 1)
1712       return TRUE;
1713   }
1714 
1715   return FALSE;
1716 }
1717 
1718 /* connect_pad:
1719  *
1720  * Try to connect the given pad to an element created from one of the factories,
1721  * and recursively.
1722  *
1723  * Note that parsepad is ghosting pad, and so pad is linked; be sure to unset parsepad's
1724  * target before trying to link pad.
1725  *
1726  * Returns TRUE if an element was properly created and linked
1727  */
1728 static gboolean
connect_pad(GstParseBin * parsebin,GstElement * src,GstParsePad * parsepad,GstPad * pad,GstCaps * caps,GValueArray * factories,GstParseChain * chain,gchar ** deadend_details)1729 connect_pad (GstParseBin * parsebin, GstElement * src, GstParsePad * parsepad,
1730     GstPad * pad, GstCaps * caps, GValueArray * factories,
1731     GstParseChain * chain, gchar ** deadend_details)
1732 {
1733   gboolean res = FALSE;
1734   GString *error_details = NULL;
1735 
1736   g_return_val_if_fail (factories != NULL, FALSE);
1737   g_return_val_if_fail (factories->n_values > 0, FALSE);
1738 
1739   GST_DEBUG_OBJECT (parsebin,
1740       "pad %s:%s , chain:%p, %d factories, caps %" GST_PTR_FORMAT,
1741       GST_DEBUG_PAD_NAME (pad), chain, factories->n_values, caps);
1742 
1743   error_details = g_string_new ("");
1744 
1745   /* 2. Try to create an element and link to it */
1746   while (factories->n_values > 0) {
1747     GstAutoplugSelectResult ret;
1748     GstElementFactory *factory;
1749     GstParseElement *pelem;
1750     GstElement *element;
1751     GstPad *sinkpad;
1752     GParamSpec *pspec;
1753     gboolean subtitle;
1754     GList *to_connect = NULL;
1755     gboolean is_parser_converter = FALSE, is_simple_demuxer = FALSE;
1756 
1757     /* Set parsepad target to pad again, it might've been unset
1758      * below but we came back here because something failed
1759      */
1760     parse_pad_set_target (parsepad, pad);
1761 
1762     /* take first factory */
1763     factory = g_value_get_object (g_value_array_get_nth (factories, 0));
1764     /* Remove selected factory from the list. */
1765     g_value_array_remove (factories, 0);
1766 
1767     GST_LOG_OBJECT (src, "trying factory %" GST_PTR_FORMAT, factory);
1768 
1769     /* Check if the caps are really supported by the factory. The
1770      * factory list is non-empty-subset filtered while caps
1771      * are only accepted by a pad if they are a subset of the
1772      * pad caps.
1773      *
1774      * FIXME: Only do this for fixed caps here. Non-fixed caps
1775      * can happen if a Parser/Converter was autoplugged before
1776      * this. We then assume that it will be able to convert to
1777      * everything that the parser would want.
1778      *
1779      * A subset check will fail here because the parser caps
1780      * will be generic and while the parser will only
1781      * support a subset of the parser caps.
1782      */
1783     if (gst_caps_is_fixed (caps)) {
1784       const GList *templs;
1785       gboolean skip = FALSE;
1786 
1787       templs = gst_element_factory_get_static_pad_templates (factory);
1788 
1789       while (templs) {
1790         GstStaticPadTemplate *templ = (GstStaticPadTemplate *) templs->data;
1791 
1792         if (templ->direction == GST_PAD_SINK) {
1793           GstCaps *templcaps = gst_static_caps_get (&templ->static_caps);
1794 
1795           if (!gst_caps_is_subset (caps, templcaps)) {
1796             GST_DEBUG_OBJECT (src,
1797                 "caps %" GST_PTR_FORMAT " not subset of %" GST_PTR_FORMAT, caps,
1798                 templcaps);
1799             gst_caps_unref (templcaps);
1800             skip = TRUE;
1801             break;
1802           }
1803 
1804           gst_caps_unref (templcaps);
1805         }
1806         templs = g_list_next (templs);
1807       }
1808       if (skip)
1809         continue;
1810     }
1811 
1812     /* If the factory is for a parser we first check if the factory
1813      * was already used for the current chain. If it was used already
1814      * we would otherwise create an infinite loop here because the
1815      * parser apparently accepts its own output as input.
1816      * This is only done for parsers because it's perfectly valid
1817      * to have other element classes after each other because a
1818      * parser is the only one that does not change the data. A
1819      * valid example for this would be multiple id3demux in a row.
1820      */
1821     is_parser_converter = strstr (gst_element_factory_get_metadata (factory,
1822             GST_ELEMENT_METADATA_KLASS), "Parser") != NULL;
1823     is_simple_demuxer = is_simple_demuxer_factory (factory);
1824 
1825     if (is_parser_converter) {
1826       gboolean skip = FALSE;
1827       GList *l;
1828 
1829       CHAIN_MUTEX_LOCK (chain);
1830       for (l = chain->elements; l; l = l->next) {
1831         GstParseElement *pelem = (GstParseElement *) l->data;
1832         GstElement *otherelement = pelem->element;
1833 
1834         if (gst_element_get_factory (otherelement) == factory) {
1835           skip = TRUE;
1836           break;
1837         }
1838       }
1839 
1840       if (!skip && chain->parent && chain->parent->parent) {
1841         GstParseChain *parent_chain = chain->parent->parent;
1842         GstParseElement *pelem =
1843             parent_chain->elements ? parent_chain->elements->data : NULL;
1844 
1845         if (pelem && gst_element_get_factory (pelem->element) == factory)
1846           skip = TRUE;
1847       }
1848       CHAIN_MUTEX_UNLOCK (chain);
1849       if (skip) {
1850         GST_DEBUG_OBJECT (parsebin,
1851             "Skipping factory '%s' because it was already used in this chain",
1852             gst_plugin_feature_get_name (GST_PLUGIN_FEATURE_CAST (factory)));
1853         continue;
1854       }
1855 
1856     }
1857 
1858     /* Expose pads if the next factory is a decoder */
1859     if (gst_element_factory_list_is_type (factory,
1860             GST_ELEMENT_FACTORY_TYPE_DECODER)) {
1861       ret = GST_AUTOPLUG_SELECT_EXPOSE;
1862     } else {
1863       /* emit autoplug-select to see what we should do with it. */
1864       g_signal_emit (G_OBJECT (parsebin),
1865           gst_parse_bin_signals[SIGNAL_AUTOPLUG_SELECT],
1866           0, parsepad, caps, factory, &ret);
1867     }
1868 
1869     switch (ret) {
1870       case GST_AUTOPLUG_SELECT_TRY:
1871         GST_DEBUG_OBJECT (parsebin, "autoplug select requested try");
1872         break;
1873       case GST_AUTOPLUG_SELECT_EXPOSE:
1874         GST_DEBUG_OBJECT (parsebin, "autoplug select requested expose");
1875         /* expose the pad, we don't have the source element */
1876         expose_pad (parsebin, src, parsepad, pad, caps, chain);
1877         res = TRUE;
1878         goto beach;
1879       case GST_AUTOPLUG_SELECT_SKIP:
1880         GST_DEBUG_OBJECT (parsebin, "autoplug select requested skip");
1881         continue;
1882       default:
1883         GST_WARNING_OBJECT (parsebin, "autoplug select returned unhandled %d",
1884             ret);
1885         break;
1886     }
1887 
1888     /* 2.0. Unlink pad */
1889     parse_pad_set_target (parsepad, NULL);
1890 
1891     /* 2.1. Try to create an element */
1892     if ((element = gst_element_factory_create (factory, NULL)) == NULL) {
1893       GST_WARNING_OBJECT (parsebin, "Could not create an element from %s",
1894           gst_plugin_feature_get_name (GST_PLUGIN_FEATURE (factory)));
1895       g_string_append_printf (error_details,
1896           "Could not create an element from %s\n",
1897           gst_plugin_feature_get_name (GST_PLUGIN_FEATURE (factory)));
1898       continue;
1899     }
1900 
1901     /* Filter errors, this will prevent the element from causing the pipeline
1902      * to error while we test it using READY state. */
1903     add_error_filter (parsebin, element);
1904 
1905     /* We don't yet want the bin to control the element's state */
1906     gst_element_set_locked_state (element, TRUE);
1907 
1908     /* ... add it ... */
1909     if (!(gst_bin_add (GST_BIN_CAST (parsebin), element))) {
1910       GST_WARNING_OBJECT (parsebin, "Couldn't add %s to the bin",
1911           GST_ELEMENT_NAME (element));
1912       remove_error_filter (parsebin, element, NULL);
1913       g_string_append_printf (error_details, "Couldn't add %s to the bin\n",
1914           GST_ELEMENT_NAME (element));
1915       gst_object_unref (element);
1916       continue;
1917     }
1918 
1919     /* Find its sink pad. */
1920     sinkpad = NULL;
1921     GST_OBJECT_LOCK (element);
1922     if (element->sinkpads != NULL)
1923       sinkpad = gst_object_ref (element->sinkpads->data);
1924     GST_OBJECT_UNLOCK (element);
1925 
1926     if (sinkpad == NULL) {
1927       GST_WARNING_OBJECT (parsebin, "Element %s doesn't have a sink pad",
1928           GST_ELEMENT_NAME (element));
1929       remove_error_filter (parsebin, element, NULL);
1930       g_string_append_printf (error_details,
1931           "Element %s doesn't have a sink pad", GST_ELEMENT_NAME (element));
1932       gst_bin_remove (GST_BIN (parsebin), element);
1933       continue;
1934     }
1935 
1936     /* ... and try to link */
1937     if ((gst_pad_link_full (pad, sinkpad,
1938                 GST_PAD_LINK_CHECK_NOTHING)) != GST_PAD_LINK_OK) {
1939       GST_WARNING_OBJECT (parsebin, "Link failed on pad %s:%s",
1940           GST_DEBUG_PAD_NAME (sinkpad));
1941       remove_error_filter (parsebin, element, NULL);
1942       g_string_append_printf (error_details, "Link failed on pad %s:%s",
1943           GST_DEBUG_PAD_NAME (sinkpad));
1944       gst_object_unref (sinkpad);
1945       gst_bin_remove (GST_BIN (parsebin), element);
1946       continue;
1947     }
1948 
1949     /* ... activate it ... */
1950     if ((gst_element_set_state (element,
1951                 GST_STATE_READY)) == GST_STATE_CHANGE_FAILURE) {
1952       GstMessage *error_msg;
1953 
1954       GST_WARNING_OBJECT (parsebin, "Couldn't set %s to READY",
1955           GST_ELEMENT_NAME (element));
1956       remove_error_filter (parsebin, element, &error_msg);
1957 
1958       if (error_msg) {
1959         gchar *error_string = error_message_to_string (error_msg);
1960         g_string_append_printf (error_details, "Couldn't set %s to READY:\n%s",
1961             GST_ELEMENT_NAME (element), error_string);
1962         gst_message_unref (error_msg);
1963         g_free (error_string);
1964       } else {
1965         g_string_append_printf (error_details, "Couldn't set %s to READY",
1966             GST_ELEMENT_NAME (element));
1967       }
1968       gst_object_unref (sinkpad);
1969       gst_bin_remove (GST_BIN (parsebin), element);
1970       continue;
1971     }
1972 
1973     /* check if we still accept the caps on the pad after setting
1974      * the element to READY */
1975     if (!gst_pad_query_accept_caps (sinkpad, caps)) {
1976       GstMessage *error_msg;
1977 
1978       GST_WARNING_OBJECT (parsebin, "Element %s does not accept caps",
1979           GST_ELEMENT_NAME (element));
1980 
1981       remove_error_filter (parsebin, element, &error_msg);
1982 
1983       if (error_msg) {
1984         gchar *error_string = error_message_to_string (error_msg);
1985         g_string_append_printf (error_details,
1986             "Element %s does not accept caps:\n%s", GST_ELEMENT_NAME (element),
1987             error_string);
1988         gst_message_unref (error_msg);
1989         g_free (error_string);
1990       } else {
1991         g_string_append_printf (error_details,
1992             "Element %s does not accept caps", GST_ELEMENT_NAME (element));
1993       }
1994 
1995       gst_element_set_state (element, GST_STATE_NULL);
1996       gst_object_unref (sinkpad);
1997       gst_bin_remove (GST_BIN (parsebin), element);
1998       continue;
1999     }
2000 
2001     gst_object_unref (sinkpad);
2002     GST_LOG_OBJECT (parsebin, "linked on pad %s:%s", GST_DEBUG_PAD_NAME (pad));
2003 
2004     CHAIN_MUTEX_LOCK (chain);
2005     pelem = g_slice_new0 (GstParseElement);
2006     pelem->element = gst_object_ref (element);
2007     pelem->capsfilter = NULL;
2008     chain->elements = g_list_prepend (chain->elements, pelem);
2009     chain->demuxer = is_demuxer_element (element);
2010 
2011     /* If we plugging a parser, mark the chain as parsed */
2012     chain->parsed |= is_parser_converter;
2013 
2014     CHAIN_MUTEX_UNLOCK (chain);
2015 
2016     /* Set connection-speed property if needed */
2017     if (chain->demuxer) {
2018       GParamSpec *pspec;
2019 
2020       if ((pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (element),
2021                   "connection-speed"))) {
2022         guint64 speed = parsebin->connection_speed / 1000;
2023         gboolean wrong_type = FALSE;
2024 
2025         if (G_PARAM_SPEC_TYPE (pspec) == G_TYPE_PARAM_UINT) {
2026           GParamSpecUInt *pspecuint = G_PARAM_SPEC_UINT (pspec);
2027 
2028           speed = CLAMP (speed, pspecuint->minimum, pspecuint->maximum);
2029         } else if (G_PARAM_SPEC_TYPE (pspec) == G_TYPE_PARAM_INT) {
2030           GParamSpecInt *pspecint = G_PARAM_SPEC_INT (pspec);
2031 
2032           speed = CLAMP (speed, pspecint->minimum, pspecint->maximum);
2033         } else if (G_PARAM_SPEC_TYPE (pspec) == G_TYPE_PARAM_UINT64) {
2034           GParamSpecUInt64 *pspecuint = G_PARAM_SPEC_UINT64 (pspec);
2035 
2036           speed = CLAMP (speed, pspecuint->minimum, pspecuint->maximum);
2037         } else if (G_PARAM_SPEC_TYPE (pspec) == G_TYPE_PARAM_INT64) {
2038           GParamSpecInt64 *pspecint = G_PARAM_SPEC_INT64 (pspec);
2039 
2040           speed = CLAMP (speed, pspecint->minimum, pspecint->maximum);
2041         } else {
2042           GST_WARNING_OBJECT (parsebin,
2043               "The connection speed property %" G_GUINT64_FORMAT " of type %s"
2044               " is not useful not setting it", speed,
2045               g_type_name (G_PARAM_SPEC_TYPE (pspec)));
2046           wrong_type = TRUE;
2047         }
2048 
2049         if (!wrong_type) {
2050           GST_DEBUG_OBJECT (parsebin,
2051               "setting connection-speed=%" G_GUINT64_FORMAT
2052               " to demuxer element", speed);
2053 
2054           g_object_set (element, "connection-speed", speed, NULL);
2055         }
2056       }
2057     }
2058 
2059     /* try to configure the subtitle encoding property when we can */
2060     pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (element),
2061         "subtitle-encoding");
2062     if (pspec && G_PARAM_SPEC_VALUE_TYPE (pspec) == G_TYPE_STRING) {
2063       SUBTITLE_LOCK (parsebin);
2064       GST_DEBUG_OBJECT (parsebin,
2065           "setting subtitle-encoding=%s to element", parsebin->encoding);
2066       g_object_set (G_OBJECT (element), "subtitle-encoding", parsebin->encoding,
2067           NULL);
2068       SUBTITLE_UNLOCK (parsebin);
2069       subtitle = TRUE;
2070     } else {
2071       subtitle = FALSE;
2072     }
2073 
2074     /* link this element further */
2075     to_connect = connect_element (parsebin, pelem, chain);
2076 
2077     if ((is_simple_demuxer || is_parser_converter) && to_connect) {
2078       GList *l;
2079       for (l = to_connect; l; l = g_list_next (l)) {
2080         GstPad *opad = GST_PAD_CAST (l->data);
2081         GstCaps *ocaps;
2082 
2083         ocaps = get_pad_caps (opad);
2084         analyze_new_pad (parsebin, pelem->element, opad, ocaps, chain);
2085         if (ocaps)
2086           gst_caps_unref (ocaps);
2087 
2088         gst_object_unref (opad);
2089       }
2090       g_list_free (to_connect);
2091       to_connect = NULL;
2092     }
2093 
2094     /* Bring the element to the state of the parent */
2095 
2096     /* First lock element's sinkpad stream lock so no data reaches
2097      * the possible new element added when caps are sent by element
2098      * while we're still sending sticky events */
2099     GST_PAD_STREAM_LOCK (sinkpad);
2100 
2101     if ((gst_element_set_state (element,
2102                 GST_STATE_PAUSED)) == GST_STATE_CHANGE_FAILURE) {
2103       GstParseElement *dtmp = NULL;
2104       GstElement *tmp = NULL;
2105       GstMessage *error_msg;
2106 
2107       GST_PAD_STREAM_UNLOCK (sinkpad);
2108 
2109       GST_WARNING_OBJECT (parsebin, "Couldn't set %s to PAUSED",
2110           GST_ELEMENT_NAME (element));
2111 
2112       g_list_free_full (to_connect, (GDestroyNotify) gst_object_unref);
2113       to_connect = NULL;
2114 
2115       remove_error_filter (parsebin, element, &error_msg);
2116 
2117       if (error_msg) {
2118         gchar *error_string = error_message_to_string (error_msg);
2119         g_string_append_printf (error_details, "Couldn't set %s to PAUSED:\n%s",
2120             GST_ELEMENT_NAME (element), error_string);
2121         gst_message_unref (error_msg);
2122         g_free (error_string);
2123       } else {
2124         g_string_append_printf (error_details, "Couldn't set %s to PAUSED",
2125             GST_ELEMENT_NAME (element));
2126       }
2127 
2128       /* Remove all elements in this chain that were just added. No
2129        * other thread could've added elements in the meantime */
2130       CHAIN_MUTEX_LOCK (chain);
2131       do {
2132         GList *l;
2133 
2134         dtmp = chain->elements->data;
2135         tmp = dtmp->element;
2136 
2137         /* Disconnect any signal handlers that might be connected
2138          * in connect_element() or analyze_pad() */
2139         if (dtmp->pad_added_id)
2140           g_signal_handler_disconnect (tmp, dtmp->pad_added_id);
2141         if (dtmp->pad_removed_id)
2142           g_signal_handler_disconnect (tmp, dtmp->pad_removed_id);
2143         if (dtmp->no_more_pads_id)
2144           g_signal_handler_disconnect (tmp, dtmp->no_more_pads_id);
2145 
2146         for (l = chain->pending_pads; l;) {
2147           GstPendingPad *pp = l->data;
2148           GList *n;
2149 
2150           if (GST_PAD_PARENT (pp->pad) != tmp) {
2151             l = l->next;
2152             continue;
2153           }
2154 
2155           gst_pending_pad_free (pp);
2156 
2157           /* Remove element from the list, update list head and go to the
2158            * next element in the list */
2159           n = l->next;
2160           chain->pending_pads = g_list_delete_link (chain->pending_pads, l);
2161           l = n;
2162         }
2163 
2164         if (dtmp->capsfilter) {
2165           gst_bin_remove (GST_BIN (parsebin), dtmp->capsfilter);
2166           gst_element_set_state (dtmp->capsfilter, GST_STATE_NULL);
2167           gst_object_unref (dtmp->capsfilter);
2168         }
2169 
2170         gst_bin_remove (GST_BIN (parsebin), tmp);
2171         gst_element_set_state (tmp, GST_STATE_NULL);
2172 
2173         gst_object_unref (tmp);
2174         g_slice_free (GstParseElement, dtmp);
2175 
2176         chain->elements = g_list_delete_link (chain->elements, chain->elements);
2177       } while (tmp != element);
2178       CHAIN_MUTEX_UNLOCK (chain);
2179 
2180       continue;
2181     } else {
2182       send_sticky_events (parsebin, pad);
2183       /* Everything went well, the spice must flow now */
2184       GST_PAD_STREAM_UNLOCK (sinkpad);
2185     }
2186 
2187     /* Remove error filter now, from now on we can't gracefully
2188      * handle errors of the element anymore */
2189     remove_error_filter (parsebin, element, NULL);
2190 
2191     /* Now let the bin handle the state */
2192     gst_element_set_locked_state (element, FALSE);
2193 
2194     if (subtitle) {
2195       SUBTITLE_LOCK (parsebin);
2196       /* we added the element now, add it to the list of subtitle-encoding
2197        * elements when we can set the property */
2198       parsebin->subtitles = g_list_prepend (parsebin->subtitles, element);
2199       SUBTITLE_UNLOCK (parsebin);
2200     }
2201 
2202     if (to_connect) {
2203       GList *l;
2204       for (l = to_connect; l; l = g_list_next (l)) {
2205         GstPad *opad = GST_PAD_CAST (l->data);
2206         GstCaps *ocaps;
2207 
2208         ocaps = get_pad_caps (opad);
2209         analyze_new_pad (parsebin, pelem->element, opad, ocaps, chain);
2210         if (ocaps)
2211           gst_caps_unref (ocaps);
2212 
2213         gst_object_unref (opad);
2214       }
2215       g_list_free (to_connect);
2216       to_connect = NULL;
2217     }
2218 
2219     res = TRUE;
2220     break;
2221   }
2222 
2223 beach:
2224   if (error_details)
2225     *deadend_details = g_string_free (error_details, (error_details->len == 0
2226             || res));
2227   else
2228     *deadend_details = NULL;
2229 
2230   return res;
2231 }
2232 
2233 static GstCaps *
get_pad_caps(GstPad * pad)2234 get_pad_caps (GstPad * pad)
2235 {
2236   GstCaps *caps;
2237 
2238   /* first check the pad caps, if this is set, we are positively sure it is
2239    * fixed and exactly what the element will produce. */
2240   caps = gst_pad_get_current_caps (pad);
2241 
2242   /* then use the getcaps function if we don't have caps. These caps might not
2243    * be fixed in some cases, in which case analyze_new_pad will set up a
2244    * notify::caps signal to continue autoplugging. */
2245   if (caps == NULL)
2246     caps = gst_pad_query_caps (pad, NULL);
2247 
2248   return caps;
2249 }
2250 
2251 /* Returns a list of pads that can be connected to already and
2252  * connects to pad-added and related signals */
2253 static GList *
connect_element(GstParseBin * parsebin,GstParseElement * pelem,GstParseChain * chain)2254 connect_element (GstParseBin * parsebin, GstParseElement * pelem,
2255     GstParseChain * chain)
2256 {
2257   GstElement *element = pelem->element;
2258   GList *pads;
2259   gboolean dynamic = FALSE;
2260   GList *to_connect = NULL;
2261 
2262   GST_DEBUG_OBJECT (parsebin,
2263       "Attempting to connect element %s [chain:%p] further",
2264       GST_ELEMENT_NAME (element), chain);
2265 
2266   /* 1. Loop over pad templates, grabbing existing pads along the way */
2267   for (pads = GST_ELEMENT_GET_CLASS (element)->padtemplates; pads;
2268       pads = g_list_next (pads)) {
2269     GstPadTemplate *templ = GST_PAD_TEMPLATE (pads->data);
2270     const gchar *templ_name;
2271 
2272     /* we are only interested in source pads */
2273     if (GST_PAD_TEMPLATE_DIRECTION (templ) != GST_PAD_SRC)
2274       continue;
2275 
2276     templ_name = GST_PAD_TEMPLATE_NAME_TEMPLATE (templ);
2277     GST_DEBUG_OBJECT (parsebin, "got a source pad template %s", templ_name);
2278 
2279     /* figure out what kind of pad this is */
2280     switch (GST_PAD_TEMPLATE_PRESENCE (templ)) {
2281       case GST_PAD_ALWAYS:
2282       {
2283         /* get the pad that we need to autoplug */
2284         GstPad *pad = gst_element_get_static_pad (element, templ_name);
2285 
2286         if (pad) {
2287           GST_DEBUG_OBJECT (parsebin, "got the pad for always template %s",
2288               templ_name);
2289           /* here is the pad, we need to autoplug it */
2290           to_connect = g_list_prepend (to_connect, pad);
2291         } else {
2292           /* strange, pad is marked as always but it's not
2293            * there. Fix the element */
2294           GST_WARNING_OBJECT (parsebin,
2295               "could not get the pad for always template %s", templ_name);
2296         }
2297         break;
2298       }
2299       case GST_PAD_SOMETIMES:
2300       {
2301         /* try to get the pad to see if it is already created or
2302          * not */
2303         GstPad *pad = gst_element_get_static_pad (element, templ_name);
2304 
2305         if (pad) {
2306           GST_DEBUG_OBJECT (parsebin, "got the pad for sometimes template %s",
2307               templ_name);
2308           /* the pad is created, we need to autoplug it */
2309           to_connect = g_list_prepend (to_connect, pad);
2310         } else {
2311           GST_DEBUG_OBJECT (parsebin,
2312               "did not get the sometimes pad of template %s", templ_name);
2313           /* we have an element that will create dynamic pads */
2314           dynamic = TRUE;
2315         }
2316         break;
2317       }
2318       case GST_PAD_REQUEST:
2319         /* ignore request pads */
2320         GST_DEBUG_OBJECT (parsebin, "ignoring request padtemplate %s",
2321             templ_name);
2322         break;
2323     }
2324   }
2325 
2326   /* 2. if there are more potential pads, connect to relevant signals */
2327   if (dynamic) {
2328     GST_LOG_OBJECT (parsebin, "Adding signals to element %s in chain %p",
2329         GST_ELEMENT_NAME (element), chain);
2330     pelem->pad_added_id = g_signal_connect (element, "pad-added",
2331         G_CALLBACK (pad_added_cb), chain);
2332     pelem->pad_removed_id = g_signal_connect (element, "pad-removed",
2333         G_CALLBACK (pad_removed_cb), chain);
2334     pelem->no_more_pads_id = g_signal_connect (element, "no-more-pads",
2335         G_CALLBACK (no_more_pads_cb), chain);
2336   }
2337 
2338   /* 3. return all pads that can be connected to already */
2339 
2340   return to_connect;
2341 }
2342 
2343 /* expose_pad:
2344  *
2345  * Expose the given pad on the chain as a parsed pad.
2346  */
2347 static void
expose_pad(GstParseBin * parsebin,GstElement * src,GstParsePad * parsepad,GstPad * pad,GstCaps * caps,GstParseChain * chain)2348 expose_pad (GstParseBin * parsebin, GstElement * src, GstParsePad * parsepad,
2349     GstPad * pad, GstCaps * caps, GstParseChain * chain)
2350 {
2351   GST_DEBUG_OBJECT (parsebin, "pad %s:%s, chain:%p",
2352       GST_DEBUG_PAD_NAME (pad), chain);
2353 
2354   gst_parse_pad_activate (parsepad, chain);
2355   chain->endpad = gst_object_ref (parsepad);
2356   if (caps)
2357     chain->endcaps = gst_caps_ref (caps);
2358   else
2359     chain->endcaps = NULL;
2360 }
2361 
2362 static void
type_found(GstElement * typefind,guint probability,GstCaps * caps,GstParseBin * parse_bin)2363 type_found (GstElement * typefind, guint probability,
2364     GstCaps * caps, GstParseBin * parse_bin)
2365 {
2366   GstPad *pad, *sink_pad;
2367 
2368   GST_DEBUG_OBJECT (parse_bin, "typefind found caps %" GST_PTR_FORMAT, caps);
2369 
2370   /* If the typefinder (but not something else) finds text/plain - i.e. that's
2371    * the top-level type of the file - then error out.
2372    */
2373   if (gst_structure_has_name (gst_caps_get_structure (caps, 0), "text/plain")) {
2374     GST_ELEMENT_ERROR (parse_bin, STREAM, WRONG_TYPE,
2375         (_("This appears to be a text file")),
2376         ("ParseBin cannot parse plain text files"));
2377     goto exit;
2378   }
2379 
2380   /* FIXME: we can only deal with one type, we don't yet support dynamically changing
2381    * caps from the typefind element */
2382   if (parse_bin->have_type || parse_bin->parse_chain)
2383     goto exit;
2384 
2385   parse_bin->have_type = TRUE;
2386 
2387   pad = gst_element_get_static_pad (typefind, "src");
2388   sink_pad = gst_element_get_static_pad (typefind, "sink");
2389 
2390   /* need some lock here to prevent race with shutdown state change
2391    * which might yank away e.g. parse_chain while building stuff here.
2392    * In typical cases, STREAM_LOCK is held and handles that, it need not
2393    * be held (if called from a proxied setcaps), so grab it anyway */
2394   GST_PAD_STREAM_LOCK (sink_pad);
2395   parse_bin->parse_chain = gst_parse_chain_new (parse_bin, NULL, pad, caps);
2396   analyze_new_pad (parse_bin, typefind, pad, caps, parse_bin->parse_chain);
2397   GST_PAD_STREAM_UNLOCK (sink_pad);
2398 
2399   gst_object_unref (sink_pad);
2400   gst_object_unref (pad);
2401 
2402 exit:
2403   return;
2404 }
2405 
2406 static GstPadProbeReturn
pad_event_cb(GstPad * pad,GstPadProbeInfo * info,gpointer data)2407 pad_event_cb (GstPad * pad, GstPadProbeInfo * info, gpointer data)
2408 {
2409   GstEvent *event = GST_PAD_PROBE_INFO_EVENT (info);
2410   GstPendingPad *ppad = (GstPendingPad *) data;
2411   GstParseChain *chain = ppad->chain;
2412   GstParseBin *parsebin = chain->parsebin;
2413 
2414   g_assert (ppad);
2415   g_assert (chain);
2416   g_assert (parsebin);
2417   switch (GST_EVENT_TYPE (event)) {
2418     case GST_EVENT_EOS:
2419       GST_DEBUG_OBJECT (pad, "Received EOS on a non final pad, this stream "
2420           "ended too early");
2421       chain->deadend = TRUE;
2422       chain->drained = TRUE;
2423       gst_object_replace ((GstObject **) & chain->current_pad, NULL);
2424       /* we don't set the endcaps because NULL endcaps means early EOS */
2425 
2426       EXPOSE_LOCK (parsebin);
2427       if (parsebin->parse_chain)
2428         if (gst_parse_chain_is_complete (parsebin->parse_chain))
2429           gst_parse_bin_expose (parsebin);
2430       EXPOSE_UNLOCK (parsebin);
2431       break;
2432     default:
2433       break;
2434   }
2435   return GST_PAD_PROBE_OK;
2436 }
2437 
2438 static void
pad_added_cb(GstElement * element,GstPad * pad,GstParseChain * chain)2439 pad_added_cb (GstElement * element, GstPad * pad, GstParseChain * chain)
2440 {
2441   GstCaps *caps;
2442   GstParseBin *parsebin;
2443 
2444   parsebin = chain->parsebin;
2445 
2446   GST_DEBUG_OBJECT (pad, "pad added, chain:%p", chain);
2447 
2448   caps = get_pad_caps (pad);
2449   analyze_new_pad (parsebin, element, pad, caps, chain);
2450   if (caps)
2451     gst_caps_unref (caps);
2452 
2453   EXPOSE_LOCK (parsebin);
2454   if (parsebin->parse_chain) {
2455     if (gst_parse_chain_is_complete (parsebin->parse_chain)) {
2456       GST_LOG_OBJECT (parsebin,
2457           "That was the last dynamic object, now attempting to expose the group");
2458       if (!gst_parse_bin_expose (parsebin))
2459         GST_WARNING_OBJECT (parsebin, "Couldn't expose group");
2460     }
2461   } else {
2462     GST_DEBUG_OBJECT (parsebin, "No parse chain, new pad ignored");
2463   }
2464   EXPOSE_UNLOCK (parsebin);
2465 }
2466 
2467 static void
pad_removed_cb(GstElement * element,GstPad * pad,GstParseChain * chain)2468 pad_removed_cb (GstElement * element, GstPad * pad, GstParseChain * chain)
2469 {
2470   GList *l;
2471 
2472   GST_LOG_OBJECT (pad, "pad removed, chain:%p", chain);
2473 
2474   /* In fact, we don't have to do anything here, the active group will be
2475    * removed when the group's multiqueue is drained */
2476   CHAIN_MUTEX_LOCK (chain);
2477   for (l = chain->pending_pads; l; l = l->next) {
2478     GstPendingPad *ppad = l->data;
2479     GstPad *opad = ppad->pad;
2480 
2481     if (pad == opad) {
2482       gst_pending_pad_free (ppad);
2483       chain->pending_pads = g_list_delete_link (chain->pending_pads, l);
2484       break;
2485     }
2486   }
2487   CHAIN_MUTEX_UNLOCK (chain);
2488 }
2489 
2490 static void
no_more_pads_cb(GstElement * element,GstParseChain * chain)2491 no_more_pads_cb (GstElement * element, GstParseChain * chain)
2492 {
2493   GstParseGroup *group = NULL;
2494 
2495   GST_LOG_OBJECT (element, "got no more pads");
2496 
2497   CHAIN_MUTEX_LOCK (chain);
2498   if (!chain->elements
2499       || ((GstParseElement *) chain->elements->data)->element != element) {
2500     GST_LOG_OBJECT (chain->parsebin, "no-more-pads from old chain element '%s'",
2501         GST_OBJECT_NAME (element));
2502     CHAIN_MUTEX_UNLOCK (chain);
2503     return;
2504   } else if (!chain->demuxer) {
2505     GST_LOG_OBJECT (chain->parsebin,
2506         "no-more-pads from a non-demuxer element '%s'",
2507         GST_OBJECT_NAME (element));
2508     CHAIN_MUTEX_UNLOCK (chain);
2509     return;
2510   }
2511 
2512   /* when we received no_more_pads, we can complete the pads of the chain */
2513   if (!chain->next_groups && chain->active_group) {
2514     group = chain->active_group;
2515   } else if (chain->next_groups) {
2516     GList *iter;
2517     for (iter = chain->next_groups; iter; iter = g_list_next (iter)) {
2518       group = iter->data;
2519       if (!group->no_more_pads)
2520         break;
2521     }
2522   }
2523   if (!group) {
2524     GST_ERROR_OBJECT (chain->parsebin, "can't find group for element");
2525     CHAIN_MUTEX_UNLOCK (chain);
2526     return;
2527   }
2528 
2529   GST_DEBUG_OBJECT (element, "Setting group %p to complete", group);
2530 
2531   group->no_more_pads = TRUE;
2532   CHAIN_MUTEX_UNLOCK (chain);
2533 
2534   EXPOSE_LOCK (chain->parsebin);
2535   if (chain->parsebin->parse_chain) {
2536     if (gst_parse_chain_is_complete (chain->parsebin->parse_chain)) {
2537       gst_parse_bin_expose (chain->parsebin);
2538     }
2539   }
2540   EXPOSE_UNLOCK (chain->parsebin);
2541 }
2542 
2543 static void
caps_notify_cb(GstPad * pad,GParamSpec * unused,GstParseChain * chain)2544 caps_notify_cb (GstPad * pad, GParamSpec * unused, GstParseChain * chain)
2545 {
2546   GstElement *element;
2547   GList *l;
2548 
2549   GST_LOG_OBJECT (pad, "Notified caps for pad %s:%s", GST_DEBUG_PAD_NAME (pad));
2550 
2551   /* Disconnect this; if we still need it, we'll reconnect to this in
2552    * analyze_new_pad */
2553   element = GST_ELEMENT_CAST (gst_pad_get_parent (pad));
2554 
2555   CHAIN_MUTEX_LOCK (chain);
2556   for (l = chain->pending_pads; l; l = l->next) {
2557     GstPendingPad *ppad = l->data;
2558     if (ppad->pad == pad) {
2559       gst_pending_pad_free (ppad);
2560       chain->pending_pads = g_list_delete_link (chain->pending_pads, l);
2561       break;
2562     }
2563   }
2564   CHAIN_MUTEX_UNLOCK (chain);
2565 
2566   pad_added_cb (element, pad, chain);
2567 
2568   gst_object_unref (element);
2569 }
2570 
2571 /* Decide whether an element is a demuxer based on the
2572  * klass and number/type of src pad templates it has */
2573 static gboolean
is_demuxer_element(GstElement * srcelement)2574 is_demuxer_element (GstElement * srcelement)
2575 {
2576   GstElementFactory *srcfactory;
2577   GstElementClass *elemclass;
2578   GList *walk;
2579   const gchar *klass;
2580   gint potential_src_pads = 0;
2581 
2582   srcfactory = gst_element_get_factory (srcelement);
2583   klass =
2584       gst_element_factory_get_metadata (srcfactory, GST_ELEMENT_METADATA_KLASS);
2585 
2586   /* Can't be a demuxer unless it has Demux in the klass name */
2587   if (!strstr (klass, "Demux"))
2588     return FALSE;
2589 
2590   /* Walk the src pad templates and count how many the element
2591    * might produce */
2592   elemclass = GST_ELEMENT_GET_CLASS (srcelement);
2593 
2594   walk = gst_element_class_get_pad_template_list (elemclass);
2595   while (walk != NULL) {
2596     GstPadTemplate *templ;
2597 
2598     templ = (GstPadTemplate *) walk->data;
2599     if (GST_PAD_TEMPLATE_DIRECTION (templ) == GST_PAD_SRC) {
2600       switch (GST_PAD_TEMPLATE_PRESENCE (templ)) {
2601         case GST_PAD_ALWAYS:
2602         case GST_PAD_SOMETIMES:
2603           if (strstr (GST_PAD_TEMPLATE_NAME_TEMPLATE (templ), "%"))
2604             potential_src_pads += 2;    /* Might make multiple pads */
2605           else
2606             potential_src_pads += 1;
2607           break;
2608         case GST_PAD_REQUEST:
2609           potential_src_pads += 2;
2610           break;
2611       }
2612     }
2613     walk = g_list_next (walk);
2614   }
2615 
2616   if (potential_src_pads < 2)
2617     return FALSE;
2618 
2619   return TRUE;
2620 }
2621 
2622 /* gst_parse_chain_get_current_group:
2623  *
2624  * Returns the current group of this chain, to which
2625  * new chains should be attached or NULL if the last
2626  * group didn't have no-more-pads.
2627  *
2628  * Not MT-safe: Call with parent chain lock!
2629  */
2630 static GstParseGroup *
gst_parse_chain_get_current_group(GstParseChain * chain)2631 gst_parse_chain_get_current_group (GstParseChain * chain)
2632 {
2633   GstParseGroup *group;
2634 
2635   /* Now we know that we can really return something useful */
2636   if (!chain->active_group) {
2637     chain->active_group = group = gst_parse_group_new (chain->parsebin, chain);
2638   } else if (!chain->active_group->no_more_pads) {
2639     group = chain->active_group;
2640   } else {
2641     GList *iter;
2642     group = NULL;
2643     for (iter = chain->next_groups; iter; iter = g_list_next (iter)) {
2644       GstParseGroup *next_group = iter->data;
2645 
2646       if (!next_group->no_more_pads) {
2647         group = next_group;
2648         break;
2649       }
2650     }
2651   }
2652   if (!group) {
2653     group = gst_parse_group_new (chain->parsebin, chain);
2654     chain->next_groups = g_list_append (chain->next_groups, group);
2655   }
2656 
2657   return group;
2658 }
2659 
2660 static void gst_parse_group_free_internal (GstParseGroup * group,
2661     gboolean hide);
2662 
2663 static void
gst_parse_chain_free_internal(GstParseChain * chain,gboolean hide)2664 gst_parse_chain_free_internal (GstParseChain * chain, gboolean hide)
2665 {
2666   GList *l, *set_to_null = NULL;
2667 
2668   CHAIN_MUTEX_LOCK (chain);
2669 
2670   GST_DEBUG_OBJECT (chain->parsebin, "%s chain %p",
2671       (hide ? "Hiding" : "Freeing"), chain);
2672 
2673   if (chain->active_group) {
2674     gst_parse_group_free_internal (chain->active_group, hide);
2675     if (!hide)
2676       chain->active_group = NULL;
2677   }
2678 
2679   for (l = chain->next_groups; l; l = l->next) {
2680     gst_parse_group_free_internal ((GstParseGroup *) l->data, hide);
2681     if (!hide)
2682       l->data = NULL;
2683   }
2684   if (!hide) {
2685     g_list_free (chain->next_groups);
2686     chain->next_groups = NULL;
2687   }
2688 
2689   if (!hide) {
2690     for (l = chain->old_groups; l; l = l->next) {
2691       GstParseGroup *group = l->data;
2692 
2693       gst_parse_group_free (group);
2694     }
2695     g_list_free (chain->old_groups);
2696     chain->old_groups = NULL;
2697   }
2698 
2699   gst_object_replace ((GstObject **) & chain->current_pad, NULL);
2700 
2701   for (l = chain->pending_pads; l; l = l->next) {
2702     GstPendingPad *ppad = l->data;
2703     gst_pending_pad_free (ppad);
2704     l->data = NULL;
2705   }
2706   g_list_free (chain->pending_pads);
2707   chain->pending_pads = NULL;
2708 
2709   for (l = chain->elements; l; l = l->next) {
2710     GstParseElement *pelem = l->data;
2711     GstElement *element = pelem->element;
2712 
2713     if (pelem->pad_added_id)
2714       g_signal_handler_disconnect (element, pelem->pad_added_id);
2715     pelem->pad_added_id = 0;
2716     if (pelem->pad_removed_id)
2717       g_signal_handler_disconnect (element, pelem->pad_removed_id);
2718     pelem->pad_removed_id = 0;
2719     if (pelem->no_more_pads_id)
2720       g_signal_handler_disconnect (element, pelem->no_more_pads_id);
2721     pelem->no_more_pads_id = 0;
2722 
2723     if (pelem->capsfilter) {
2724       if (GST_OBJECT_PARENT (pelem->capsfilter) ==
2725           GST_OBJECT_CAST (chain->parsebin))
2726         gst_bin_remove (GST_BIN_CAST (chain->parsebin), pelem->capsfilter);
2727       if (!hide) {
2728         set_to_null =
2729             g_list_append (set_to_null, gst_object_ref (pelem->capsfilter));
2730       }
2731     }
2732 
2733     if (GST_OBJECT_PARENT (element) == GST_OBJECT_CAST (chain->parsebin))
2734       gst_bin_remove (GST_BIN_CAST (chain->parsebin), element);
2735     if (!hide) {
2736       set_to_null = g_list_append (set_to_null, gst_object_ref (element));
2737     }
2738 
2739     SUBTITLE_LOCK (chain->parsebin);
2740     /* remove possible subtitle element */
2741     chain->parsebin->subtitles =
2742         g_list_remove (chain->parsebin->subtitles, element);
2743     SUBTITLE_UNLOCK (chain->parsebin);
2744 
2745     if (!hide) {
2746       if (pelem->capsfilter) {
2747         gst_object_unref (pelem->capsfilter);
2748         pelem->capsfilter = NULL;
2749       }
2750 
2751       gst_object_unref (element);
2752       l->data = NULL;
2753 
2754       g_slice_free (GstParseElement, pelem);
2755     }
2756   }
2757   if (!hide) {
2758     g_list_free (chain->elements);
2759     chain->elements = NULL;
2760   }
2761 
2762   if (chain->endpad) {
2763     if (chain->endpad->exposed) {
2764       GstPad *endpad = GST_PAD_CAST (chain->endpad);
2765       GST_DEBUG_OBJECT (chain->parsebin, "Removing pad %s:%s",
2766           GST_DEBUG_PAD_NAME (endpad));
2767       gst_pad_push_event (endpad, gst_event_new_eos ());
2768       gst_element_remove_pad (GST_ELEMENT_CAST (chain->parsebin), endpad);
2769     }
2770 
2771     parse_pad_set_target (chain->endpad, NULL);
2772     chain->endpad->exposed = FALSE;
2773     if (!hide) {
2774       gst_object_unref (chain->endpad);
2775       chain->endpad = NULL;
2776     }
2777   }
2778 
2779   if (!hide && chain->current_pad) {
2780     gst_object_unref (chain->current_pad);
2781     chain->current_pad = NULL;
2782   }
2783 
2784   if (chain->pad) {
2785     gst_object_unref (chain->pad);
2786     chain->pad = NULL;
2787   }
2788   if (chain->start_caps) {
2789     gst_caps_unref (chain->start_caps);
2790     chain->start_caps = NULL;
2791   }
2792 
2793   if (chain->endcaps) {
2794     gst_caps_unref (chain->endcaps);
2795     chain->endcaps = NULL;
2796   }
2797   g_free (chain->deadend_details);
2798   chain->deadend_details = NULL;
2799 
2800   GST_DEBUG_OBJECT (chain->parsebin, "%s chain %p", (hide ? "Hidden" : "Freed"),
2801       chain);
2802   CHAIN_MUTEX_UNLOCK (chain);
2803 
2804   while (set_to_null) {
2805     GstElement *element = set_to_null->data;
2806     set_to_null = g_list_delete_link (set_to_null, set_to_null);
2807     gst_element_set_state (element, GST_STATE_NULL);
2808     gst_object_unref (element);
2809   }
2810 
2811   if (!hide) {
2812     g_mutex_clear (&chain->lock);
2813     g_slice_free (GstParseChain, chain);
2814   }
2815 }
2816 
2817 /* gst_parse_chain_free:
2818  *
2819  * Completely frees and removes the chain and all
2820  * child groups from ParseBin.
2821  *
2822  * MT-safe, don't hold the chain lock or any child chain's lock
2823  * when calling this!
2824  */
2825 static void
gst_parse_chain_free(GstParseChain * chain)2826 gst_parse_chain_free (GstParseChain * chain)
2827 {
2828   gst_parse_chain_free_internal (chain, FALSE);
2829 }
2830 
2831 /* gst_parse_chain_new:
2832  *
2833  * Creates a new parse chain and initializes it.
2834  *
2835  * It's up to the caller to add it to the list of child chains of
2836  * a group!
2837  */
2838 static GstParseChain *
gst_parse_chain_new(GstParseBin * parsebin,GstParseGroup * parent,GstPad * pad,GstCaps * start_caps)2839 gst_parse_chain_new (GstParseBin * parsebin, GstParseGroup * parent,
2840     GstPad * pad, GstCaps * start_caps)
2841 {
2842   GstParseChain *chain = g_slice_new0 (GstParseChain);
2843 
2844   GST_DEBUG_OBJECT (parsebin, "Creating new chain %p with parent group %p",
2845       chain, parent);
2846 
2847   chain->parsebin = parsebin;
2848   chain->parent = parent;
2849   g_mutex_init (&chain->lock);
2850   chain->pad = gst_object_ref (pad);
2851   if (start_caps)
2852     chain->start_caps = gst_caps_ref (start_caps);
2853 
2854   return chain;
2855 }
2856 
2857 /****
2858  * GstParseGroup functions
2859  ****/
2860 
2861 static void
gst_parse_group_free_internal(GstParseGroup * group,gboolean hide)2862 gst_parse_group_free_internal (GstParseGroup * group, gboolean hide)
2863 {
2864   GList *l;
2865 
2866   GST_DEBUG_OBJECT (group->parsebin, "%s group %p",
2867       (hide ? "Hiding" : "Freeing"), group);
2868   for (l = group->children; l; l = l->next) {
2869     GstParseChain *chain = (GstParseChain *) l->data;
2870 
2871     gst_parse_chain_free_internal (chain, hide);
2872     if (!hide)
2873       l->data = NULL;
2874   }
2875   if (!hide) {
2876     g_list_free (group->children);
2877     group->children = NULL;
2878   }
2879 
2880   GST_DEBUG_OBJECT (group->parsebin, "%s group %p", (hide ? "Hid" : "Freed"),
2881       group);
2882   if (!hide)
2883     g_slice_free (GstParseGroup, group);
2884 }
2885 
2886 /* gst_parse_group_free:
2887  *
2888  * Completely frees and removes the parse group and all
2889  * it's children.
2890  *
2891  * Never call this from any streaming thread!
2892  *
2893  * Not MT-safe, call with parent's chain lock!
2894  */
2895 static void
gst_parse_group_free(GstParseGroup * group)2896 gst_parse_group_free (GstParseGroup * group)
2897 {
2898   gst_parse_group_free_internal (group, FALSE);
2899 }
2900 
2901 /* gst_parse_group_hide:
2902  *
2903  * Hide the parse group only, this means that
2904  * all child endpads are removed from ParseBin
2905  * and all signals are unconnected.
2906  *
2907  * No element is set to NULL state and completely
2908  * unrefed here.
2909  *
2910  * Can be called from streaming threads.
2911  *
2912  * Not MT-safe, call with parent's chain lock!
2913  */
2914 static void
gst_parse_group_hide(GstParseGroup * group)2915 gst_parse_group_hide (GstParseGroup * group)
2916 {
2917   gst_parse_group_free_internal (group, TRUE);
2918 }
2919 
2920 /* gst_parse_chain_free_hidden_groups:
2921  *
2922  * Frees any parse groups that were hidden previously.
2923  * This allows keeping memory use from ballooning when
2924  * switching chains repeatedly.
2925  *
2926  * A new throwaway thread will be created to free the
2927  * groups, so any delay does not block the setup of a
2928  * new group.
2929  *
2930  * Not MT-safe, call with parent's chain lock!
2931  */
2932 static void
gst_parse_chain_free_hidden_groups(GList * old_groups)2933 gst_parse_chain_free_hidden_groups (GList * old_groups)
2934 {
2935   GList *l;
2936 
2937   for (l = old_groups; l; l = l->next) {
2938     GstParseGroup *group = l->data;
2939 
2940     gst_parse_group_free (group);
2941   }
2942   g_list_free (old_groups);
2943 }
2944 
2945 static void
gst_parse_chain_start_free_hidden_groups_thread(GstParseChain * chain)2946 gst_parse_chain_start_free_hidden_groups_thread (GstParseChain * chain)
2947 {
2948   GThread *thread;
2949   GError *error = NULL;
2950   GList *old_groups;
2951   GstParseBin *parsebin = chain->parsebin;
2952 
2953   old_groups = chain->old_groups;
2954   if (!old_groups)
2955     return;
2956 
2957   /* If we already have a thread running, wait for it to finish */
2958   g_mutex_lock (&parsebin->cleanup_lock);
2959   if (parsebin->cleanup_thread) {
2960     g_thread_join (parsebin->cleanup_thread);
2961     parsebin->cleanup_thread = NULL;
2962   }
2963 
2964   chain->old_groups = NULL;
2965   thread = g_thread_try_new ("free-hidden-groups",
2966       (GThreadFunc) gst_parse_chain_free_hidden_groups, old_groups, &error);
2967   if (!thread || error) {
2968     GST_ERROR ("Failed to start free-hidden-groups thread: %s",
2969         error ? error->message : "unknown reason");
2970     g_clear_error (&error);
2971     chain->old_groups = old_groups;
2972     g_mutex_unlock (&parsebin->cleanup_lock);
2973     return;
2974   }
2975 
2976   parsebin->cleanup_thread = thread;
2977   g_mutex_unlock (&parsebin->cleanup_lock);
2978 
2979   GST_DEBUG_OBJECT (chain->parsebin, "Started free-hidden-groups thread");
2980 }
2981 
2982 /* gst_parse_group_new:
2983  * @parsebin: Parent ParseBin
2984  * @parent: Parent chain or %NULL
2985  *
2986  * Creates a new GstParseGroup. It is up to the caller to add it to the list
2987  * of groups.
2988  */
2989 static GstParseGroup *
gst_parse_group_new(GstParseBin * parsebin,GstParseChain * parent)2990 gst_parse_group_new (GstParseBin * parsebin, GstParseChain * parent)
2991 {
2992   GstParseGroup *group = g_slice_new0 (GstParseGroup);
2993 
2994   GST_DEBUG_OBJECT (parsebin, "Creating new group %p with parent chain %p",
2995       group, parent);
2996 
2997   group->parsebin = parsebin;
2998   group->parent = parent;
2999 
3000   return group;
3001 }
3002 
3003 /* gst_parse_group_is_complete:
3004  *
3005  * Checks if the group is complete, this means that
3006  * a) no-more-pads happened
3007  * b) all child chains are complete
3008  *
3009  * Not MT-safe, always call with ParseBin expose lock
3010  */
3011 static gboolean
gst_parse_group_is_complete(GstParseGroup * group)3012 gst_parse_group_is_complete (GstParseGroup * group)
3013 {
3014   GList *l;
3015   gboolean complete = TRUE;
3016 
3017   if (!group->no_more_pads) {
3018     complete = FALSE;
3019     goto out;
3020   }
3021 
3022   for (l = group->children; l; l = l->next) {
3023     GstParseChain *chain = l->data;
3024 
3025     /* Any blocked chain requires we complete this group
3026      * since everything is synchronous, we can't proceed otherwise */
3027     if (chain->endpad && chain->endpad->blocked)
3028       goto out;
3029 
3030     if (!gst_parse_chain_is_complete (chain)) {
3031       complete = FALSE;
3032       goto out;
3033     }
3034   }
3035 
3036 out:
3037   GST_DEBUG_OBJECT (group->parsebin, "Group %p is complete: %d", group,
3038       complete);
3039   return complete;
3040 }
3041 
3042 /* gst_parse_chain_is_complete:
3043  *
3044  * Returns TRUE if the chain is complete, this means either
3045  * a) This chain is a dead end, i.e. we have no suitable plugins
3046  * b) This chain ends in an endpad and this is blocked or exposed
3047  * c) The chain has gotten far enough to have plugged 1 parser at least.
3048  *
3049  * Not MT-safe, always call with ParseBin expose lock
3050  */
3051 static gboolean
gst_parse_chain_is_complete(GstParseChain * chain)3052 gst_parse_chain_is_complete (GstParseChain * chain)
3053 {
3054   gboolean complete = FALSE;
3055 
3056   CHAIN_MUTEX_LOCK (chain);
3057   if (chain->parsebin->shutdown)
3058     goto out;
3059 
3060   if (chain->deadend) {
3061     complete = TRUE;
3062     goto out;
3063   }
3064 
3065   if (chain->endpad && (chain->endpad->blocked || chain->endpad->exposed)) {
3066     complete = TRUE;
3067     goto out;
3068   }
3069 
3070   if (chain->demuxer) {
3071     if (chain->active_group
3072         && gst_parse_group_is_complete (chain->active_group)) {
3073       complete = TRUE;
3074       goto out;
3075     }
3076   }
3077 
3078   if (chain->parsed) {
3079     complete = TRUE;
3080     goto out;
3081   }
3082 
3083 out:
3084   CHAIN_MUTEX_UNLOCK (chain);
3085   GST_DEBUG_OBJECT (chain->parsebin, "Chain %p is complete: %d", chain,
3086       complete);
3087   return complete;
3088 }
3089 
3090 static void
chain_remove_old_groups(GstParseChain * chain)3091 chain_remove_old_groups (GstParseChain * chain)
3092 {
3093   GList *tmp;
3094 
3095   /* First go in child */
3096   if (chain->active_group) {
3097     for (tmp = chain->active_group->children; tmp; tmp = tmp->next) {
3098       GstParseChain *child = (GstParseChain *) tmp->data;
3099       chain_remove_old_groups (child);
3100     }
3101   }
3102 
3103   if (chain->old_groups) {
3104     gst_parse_group_hide (chain->old_groups->data);
3105     gst_parse_chain_start_free_hidden_groups_thread (chain);
3106   }
3107 }
3108 
3109 static gboolean
3110 drain_and_switch_chains (GstParseChain * chain, GstParsePad * drainpad,
3111     gboolean * last_group, gboolean * drained, gboolean * switched);
3112 /* drain_and_switch_chains/groups:
3113  *
3114  * CALL WITH CHAIN LOCK (or group parent) TAKEN !
3115  *
3116  * Goes down the chains/groups until it finds the chain
3117  * to which the drainpad belongs.
3118  *
3119  * It marks that pad/chain as drained and then will figure
3120  * out which group to switch to or not.
3121  *
3122  * last_chain will be set to TRUE if the group to which the
3123  * pad belongs is the last one.
3124  *
3125  * drained will be set to TRUE if the chain/group is drained.
3126  *
3127  * Returns: TRUE if the chain contained the target pad */
3128 static gboolean
drain_and_switch_group(GstParseGroup * group,GstParsePad * drainpad,gboolean * last_group,gboolean * drained,gboolean * switched)3129 drain_and_switch_group (GstParseGroup * group, GstParsePad * drainpad,
3130     gboolean * last_group, gboolean * drained, gboolean * switched)
3131 {
3132   gboolean handled = FALSE;
3133   GList *tmp;
3134 
3135   GST_DEBUG ("Checking group %p (target pad %s:%s)",
3136       group, GST_DEBUG_PAD_NAME (drainpad));
3137 
3138   /* Definitely can't be in drained groups */
3139   if (G_UNLIKELY (group->drained)) {
3140     goto beach;
3141   }
3142 
3143   /* Figure out if all our chains are drained with the
3144    * new information */
3145   group->drained = TRUE;
3146   for (tmp = group->children; tmp; tmp = tmp->next) {
3147     GstParseChain *chain = (GstParseChain *) tmp->data;
3148     gboolean subdrained = FALSE;
3149 
3150     handled |=
3151         drain_and_switch_chains (chain, drainpad, last_group, &subdrained,
3152         switched);
3153     if (!subdrained)
3154       group->drained = FALSE;
3155   }
3156 
3157 beach:
3158   GST_DEBUG ("group %p (last_group:%d, drained:%d, switched:%d, handled:%d)",
3159       group, *last_group, group->drained, *switched, handled);
3160   *drained = group->drained;
3161   return handled;
3162 }
3163 
3164 static gboolean
drain_and_switch_chains(GstParseChain * chain,GstParsePad * drainpad,gboolean * last_group,gboolean * drained,gboolean * switched)3165 drain_and_switch_chains (GstParseChain * chain, GstParsePad * drainpad,
3166     gboolean * last_group, gboolean * drained, gboolean * switched)
3167 {
3168   gboolean handled = FALSE;
3169   GstParseBin *parsebin = chain->parsebin;
3170 
3171   GST_DEBUG ("Checking chain %p %s:%s (target pad %s:%s)",
3172       chain, GST_DEBUG_PAD_NAME (chain->pad), GST_DEBUG_PAD_NAME (drainpad));
3173 
3174   CHAIN_MUTEX_LOCK (chain);
3175 
3176   /* Definitely can't be in drained chains */
3177   if (G_UNLIKELY (chain->drained)) {
3178     goto beach;
3179   }
3180 
3181   if (chain->endpad) {
3182     /* Check if we're reached the target endchain */
3183     if (drainpad != NULL && chain == drainpad->chain) {
3184       GST_DEBUG ("Found the target chain");
3185       drainpad->drained = TRUE;
3186       handled = TRUE;
3187     }
3188 
3189     chain->drained = chain->endpad->drained;
3190     goto beach;
3191   }
3192 
3193   /* We known there are groups to switch to */
3194   if (chain->next_groups)
3195     *last_group = FALSE;
3196 
3197   /* Check the active group */
3198   if (chain->active_group) {
3199     gboolean subdrained = FALSE;
3200     handled = drain_and_switch_group (chain->active_group, drainpad,
3201         last_group, &subdrained, switched);
3202 
3203     /* The group is drained, see if we can switch to another */
3204     if ((handled || drainpad == NULL) && subdrained && !*switched) {
3205       if (chain->next_groups) {
3206         /* Switch to next group, the actual removal of the current group will
3207          * be done when the next one is activated */
3208         GST_DEBUG_OBJECT (parsebin, "Moving current group %p to old groups",
3209             chain->active_group);
3210         chain->old_groups =
3211             g_list_prepend (chain->old_groups, chain->active_group);
3212         GST_DEBUG_OBJECT (parsebin, "Switching to next group %p",
3213             chain->next_groups->data);
3214         chain->active_group = chain->next_groups->data;
3215         chain->next_groups =
3216             g_list_delete_link (chain->next_groups, chain->next_groups);
3217         *switched = TRUE;
3218         chain->drained = FALSE;
3219       } else {
3220         GST_DEBUG ("Group %p was the last in chain %p", chain->active_group,
3221             chain);
3222         chain->drained = TRUE;
3223         /* We're drained ! */
3224       }
3225     } else {
3226       if (subdrained && !chain->next_groups)
3227         *drained = TRUE;
3228     }
3229   }
3230 
3231 beach:
3232   CHAIN_MUTEX_UNLOCK (chain);
3233 
3234   GST_DEBUG
3235       ("Chain %p (%s:%s handled:%d, last_group:%d, drained:%d, switched:%d, deadend:%d)",
3236       chain, GST_DEBUG_PAD_NAME (chain->pad), handled, *last_group,
3237       chain->drained, *switched, chain->deadend);
3238 
3239   *drained = chain->drained;
3240 
3241   return handled;
3242 }
3243 
3244 /* check if the group is drained, meaning all pads have seen an EOS
3245  * event.  */
3246 static gboolean
gst_parse_pad_handle_eos(GstParsePad * pad)3247 gst_parse_pad_handle_eos (GstParsePad * pad)
3248 {
3249   gboolean last_group = TRUE;
3250   gboolean switched = FALSE;
3251   gboolean drained = FALSE;
3252   GstParseChain *chain = pad->chain;
3253   GstParseBin *parsebin = chain->parsebin;
3254 
3255   GST_LOG_OBJECT (parsebin, "pad %p", pad);
3256   EXPOSE_LOCK (parsebin);
3257   if (parsebin->parse_chain) {
3258     drain_and_switch_chains (parsebin->parse_chain, pad, &last_group, &drained,
3259         &switched);
3260 
3261     GST_LOG_OBJECT (parsebin, "drained:%d switched:%d", drained, switched);
3262     if (switched) {
3263       /* If we resulted in a group switch, expose what's needed */
3264       if (gst_parse_chain_is_complete (parsebin->parse_chain))
3265         gst_parse_bin_expose (parsebin);
3266     }
3267 
3268     if (drained) {
3269       GST_DEBUG_OBJECT (parsebin, "We are fully drained, emitting signal");
3270       g_signal_emit (parsebin, gst_parse_bin_signals[SIGNAL_DRAINED], 0, NULL);
3271     }
3272 
3273   }
3274   EXPOSE_UNLOCK (parsebin);
3275 
3276   return last_group;
3277 }
3278 
3279 /* gst_parse_group_is_drained:
3280  *
3281  * Check is this group is drained and cache this result.
3282  * The group is drained if all child chains are drained.
3283  *
3284  * Not MT-safe, call with group->parent's lock */
3285 static gboolean
gst_parse_group_is_drained(GstParseGroup * group)3286 gst_parse_group_is_drained (GstParseGroup * group)
3287 {
3288   GList *l;
3289   gboolean drained = TRUE;
3290 
3291   if (group->drained) {
3292     drained = TRUE;
3293     goto out;
3294   }
3295 
3296   for (l = group->children; l; l = l->next) {
3297     GstParseChain *chain = l->data;
3298 
3299     CHAIN_MUTEX_LOCK (chain);
3300     if (!gst_parse_chain_is_drained (chain))
3301       drained = FALSE;
3302     CHAIN_MUTEX_UNLOCK (chain);
3303     if (!drained)
3304       goto out;
3305   }
3306   group->drained = drained;
3307 
3308 out:
3309   GST_DEBUG_OBJECT (group->parsebin, "Group %p is drained: %d", group, drained);
3310   return drained;
3311 }
3312 
3313 /* gst_parse_chain_is_drained:
3314  *
3315  * Check is the chain is drained, which means that
3316  * either
3317  *
3318  * a) it's endpad is drained
3319  * b) there are no pending pads, the active group is drained
3320  *    and there are no next groups
3321  *
3322  * Not MT-safe, call with chain lock
3323  */
3324 static gboolean
gst_parse_chain_is_drained(GstParseChain * chain)3325 gst_parse_chain_is_drained (GstParseChain * chain)
3326 {
3327   gboolean drained = FALSE;
3328 
3329   if (chain->endpad) {
3330     drained = chain->endpad->drained;
3331     goto out;
3332   }
3333 
3334   if (chain->pending_pads) {
3335     drained = FALSE;
3336     goto out;
3337   }
3338 
3339   if (chain->active_group && gst_parse_group_is_drained (chain->active_group)
3340       && !chain->next_groups) {
3341     drained = TRUE;
3342     goto out;
3343   }
3344 
3345 out:
3346   GST_DEBUG_OBJECT (chain->parsebin, "Chain %p is drained: %d", chain, drained);
3347   return drained;
3348 }
3349 
3350 /* sort_end_pads:
3351  * GCompareFunc to use with lists of GstPad.
3352  * Sorts pads by mime type.
3353  * First video (raw, then non-raw), then audio (raw, then non-raw),
3354  * then others.
3355  *
3356  * Return: negative if a<b, 0 if a==b, positive if a>b
3357  */
3358 static gint
sort_end_pads(GstParsePad * da,GstParsePad * db)3359 sort_end_pads (GstParsePad * da, GstParsePad * db)
3360 {
3361   gint va, vb;
3362   const gchar *namea, *nameb;
3363   gchar *ida, *idb;
3364   gint ret;
3365   GstCaps *capsa, *capsb;
3366 
3367   capsa = get_pad_caps (GST_PAD_CAST (da));
3368   capsb = get_pad_caps (GST_PAD_CAST (db));
3369 
3370   if (gst_caps_get_size (capsa) == 0 || gst_caps_get_size (capsb) == 0) {
3371     if (gst_caps_is_any (capsa))
3372       va = 6;
3373     if (gst_caps_is_empty (capsa))
3374       va = 7;
3375     else
3376       va = 0;
3377 
3378     if (gst_caps_is_any (capsb))
3379       vb = 6;
3380     if (gst_caps_is_empty (capsb))
3381       vb = 7;
3382     else
3383       vb = 0;
3384   } else {
3385     GstStructure *sa, *sb;
3386 
3387     sa = gst_caps_get_structure ((const GstCaps *) capsa, 0);
3388     sb = gst_caps_get_structure ((const GstCaps *) capsb, 0);
3389 
3390     namea = gst_structure_get_name (sa);
3391     nameb = gst_structure_get_name (sb);
3392 
3393     if (g_strrstr (namea, "video/x-raw"))
3394       va = 0;
3395     else if (g_strrstr (namea, "video/"))
3396       va = 1;
3397     else if (g_strrstr (namea, "image/"))
3398       va = 2;
3399     else if (g_strrstr (namea, "audio/x-raw"))
3400       va = 3;
3401     else if (g_strrstr (namea, "audio/"))
3402       va = 4;
3403     else
3404       va = 5;
3405 
3406     if (g_strrstr (nameb, "video/x-raw"))
3407       vb = 0;
3408     else if (g_strrstr (nameb, "video/"))
3409       vb = 1;
3410     else if (g_strrstr (nameb, "image/"))
3411       vb = 2;
3412     else if (g_strrstr (nameb, "audio/x-raw"))
3413       vb = 3;
3414     else if (g_strrstr (nameb, "audio/"))
3415       vb = 4;
3416     else
3417       vb = 5;
3418   }
3419 
3420   gst_caps_unref (capsa);
3421   gst_caps_unref (capsb);
3422 
3423   if (va != vb)
3424     return va - vb;
3425 
3426   /* if otherwise the same, sort by stream-id */
3427   ida = gst_pad_get_stream_id (GST_PAD_CAST (da));
3428   idb = gst_pad_get_stream_id (GST_PAD_CAST (db));
3429   ret = (ida) ? ((idb) ? strcmp (ida, idb) : -1) : 1;
3430   g_free (ida);
3431   g_free (idb);
3432 
3433   return ret;
3434 }
3435 
3436 static gboolean
debug_sticky_event(GstPad * pad,GstEvent ** event,gpointer user_data)3437 debug_sticky_event (GstPad * pad, GstEvent ** event, gpointer user_data)
3438 {
3439   GST_DEBUG_OBJECT (pad, "sticky event %s (%p)", GST_EVENT_TYPE_NAME (*event),
3440       *event);
3441   return TRUE;
3442 }
3443 
3444 /* Must only be called if the toplevel chain is complete and blocked! */
3445 /* Not MT-safe, call with ParseBin expose lock! */
3446 static gboolean
gst_parse_bin_expose(GstParseBin * parsebin)3447 gst_parse_bin_expose (GstParseBin * parsebin)
3448 {
3449   GList *tmp, *endpads;
3450   gboolean missing_plugin;
3451   GString *missing_plugin_details;
3452   gboolean already_exposed;
3453   gboolean last_group;
3454   gboolean uncollected_streams;
3455   GstStreamCollection *fallback_collection = NULL;
3456 
3457 retry:
3458   endpads = NULL;
3459   missing_plugin = FALSE;
3460   already_exposed = TRUE;
3461   last_group = TRUE;
3462 
3463   missing_plugin_details = g_string_new ("");
3464 
3465   GST_DEBUG_OBJECT (parsebin, "Exposing currently active chains/groups");
3466 
3467   /* Don't expose if we're currently shutting down */
3468   DYN_LOCK (parsebin);
3469   if (G_UNLIKELY (parsebin->shutdown)) {
3470     GST_WARNING_OBJECT (parsebin,
3471         "Currently, shutting down, aborting exposing");
3472     DYN_UNLOCK (parsebin);
3473     return FALSE;
3474   }
3475   DYN_UNLOCK (parsebin);
3476 
3477   /* Get the pads that we're going to expose and mark things as exposed */
3478   uncollected_streams = FALSE;
3479   CHAIN_MUTEX_LOCK (parsebin->parse_chain);
3480   if (!gst_parse_chain_expose (parsebin->parse_chain, &endpads, &missing_plugin,
3481           missing_plugin_details, &last_group, &uncollected_streams)) {
3482     g_list_free_full (endpads, (GDestroyNotify) gst_object_unref);
3483     g_string_free (missing_plugin_details, TRUE);
3484     GST_ERROR_OBJECT (parsebin, "Broken chain/group tree");
3485     CHAIN_MUTEX_UNLOCK (parsebin->parse_chain);
3486     return FALSE;
3487   }
3488   CHAIN_MUTEX_UNLOCK (parsebin->parse_chain);
3489   if (endpads == NULL) {
3490     if (missing_plugin) {
3491       if (missing_plugin_details->len > 0) {
3492         gchar *details = g_string_free (missing_plugin_details, FALSE);
3493         GST_ELEMENT_ERROR (parsebin, CORE, MISSING_PLUGIN, (NULL),
3494             ("no suitable plugins found:\n%s", details));
3495         g_free (details);
3496       } else {
3497         g_string_free (missing_plugin_details, TRUE);
3498         GST_ELEMENT_ERROR (parsebin, CORE, MISSING_PLUGIN, (NULL),
3499             ("no suitable plugins found"));
3500       }
3501     } else {
3502       /* in this case, the stream ended without buffers,
3503        * just post a warning */
3504       g_string_free (missing_plugin_details, TRUE);
3505 
3506       GST_WARNING_OBJECT (parsebin, "All streams finished without buffers. "
3507           "Last group: %d", last_group);
3508       if (last_group) {
3509         GST_ELEMENT_ERROR (parsebin, STREAM, FAILED, (NULL),
3510             ("all streams without buffers"));
3511       } else {
3512         gboolean switched = FALSE;
3513         gboolean drained = FALSE;
3514 
3515         drain_and_switch_chains (parsebin->parse_chain, NULL, &last_group,
3516             &drained, &switched);
3517         GST_ELEMENT_WARNING (parsebin, STREAM, FAILED, (NULL),
3518             ("all streams without buffers"));
3519         if (switched) {
3520           if (gst_parse_chain_is_complete (parsebin->parse_chain))
3521             goto retry;
3522           else
3523             return FALSE;
3524         }
3525       }
3526     }
3527 
3528     return FALSE;
3529   }
3530 
3531   if (uncollected_streams) {
3532     /* FIXME: Collect and use a stream id from the top chain as
3533      * upstream ID? */
3534     fallback_collection = gst_stream_collection_new (NULL);
3535 
3536     build_fallback_collection (parsebin->parse_chain, fallback_collection);
3537 
3538     gst_element_post_message (GST_ELEMENT (parsebin),
3539         gst_message_new_stream_collection (GST_OBJECT (parsebin),
3540             fallback_collection));
3541   }
3542 
3543   g_string_free (missing_plugin_details, TRUE);
3544 
3545   /* Check if this was called when everything was exposed already,
3546    * and see if we need to post a new fallback collection */
3547   for (tmp = endpads; tmp && already_exposed; tmp = tmp->next) {
3548     GstParsePad *parsepad = tmp->data;
3549 
3550     already_exposed &= parsepad->exposed;
3551   }
3552   if (already_exposed) {
3553     GST_DEBUG_OBJECT (parsebin, "Everything was exposed already!");
3554     if (fallback_collection)
3555       gst_object_unref (fallback_collection);
3556     g_list_free_full (endpads, (GDestroyNotify) gst_object_unref);
3557     return TRUE;
3558   }
3559 
3560   /* Set all already exposed pads to blocked */
3561   for (tmp = endpads; tmp; tmp = tmp->next) {
3562     GstParsePad *parsepad = tmp->data;
3563 
3564     if (parsepad->exposed) {
3565       GST_DEBUG_OBJECT (parsepad, "blocking exposed pad");
3566       gst_parse_pad_set_blocked (parsepad, TRUE);
3567     }
3568   }
3569 
3570   /* re-order pads : video, then audio, then others */
3571   endpads = g_list_sort (endpads, (GCompareFunc) sort_end_pads);
3572 
3573   /* Don't expose if we're currently shutting down */
3574   DYN_LOCK (parsebin);
3575   if (G_UNLIKELY (parsebin->shutdown)) {
3576     GST_WARNING_OBJECT (parsebin,
3577         "Currently, shutting down, aborting exposing");
3578     DYN_UNLOCK (parsebin);
3579     return FALSE;
3580   }
3581 
3582   /* Expose pads */
3583   for (tmp = endpads; tmp; tmp = tmp->next) {
3584     GstParsePad *parsepad = (GstParsePad *) tmp->data;
3585     gchar *padname;
3586 
3587     //if (!parsepad->blocked)
3588     //continue;
3589 
3590     /* 1. rewrite name */
3591     padname = g_strdup_printf ("src_%u", parsebin->nbpads);
3592     parsebin->nbpads++;
3593     GST_DEBUG_OBJECT (parsebin, "About to expose parsepad %s as %s",
3594         GST_OBJECT_NAME (parsepad), padname);
3595     gst_object_set_name (GST_OBJECT (parsepad), padname);
3596     g_free (padname);
3597 
3598     gst_pad_sticky_events_foreach (GST_PAD_CAST (parsepad), debug_sticky_event,
3599         parsepad);
3600 
3601     /* 2. activate and add */
3602     if (!parsepad->exposed) {
3603       parsepad->exposed = TRUE;
3604       if (!gst_element_add_pad (GST_ELEMENT (parsebin),
3605               GST_PAD_CAST (parsepad))) {
3606         /* not really fatal, we can try to add the other pads */
3607         g_warning ("error adding pad to ParseBin");
3608         parsepad->exposed = FALSE;
3609         continue;
3610       }
3611 #if 0
3612       /* HACK: Send an empty gap event to push sticky events */
3613       gst_pad_push_event (GST_PAD (parsepad),
3614           gst_event_new_gap (0, GST_CLOCK_TIME_NONE));
3615 #endif
3616     }
3617 
3618     GST_INFO_OBJECT (parsepad, "added new parsed pad");
3619   }
3620 
3621   DYN_UNLOCK (parsebin);
3622 
3623   /* Unblock internal pads. The application should have connected stuff now
3624    * so that streaming can continue. */
3625   for (tmp = endpads; tmp; tmp = tmp->next) {
3626     GstParsePad *parsepad = (GstParsePad *) tmp->data;
3627 
3628     if (parsepad->exposed) {
3629       GST_DEBUG_OBJECT (parsepad, "unblocking");
3630       gst_parse_pad_unblock (parsepad);
3631       GST_DEBUG_OBJECT (parsepad, "unblocked");
3632     }
3633 
3634     /* Send stream-collection events for any pads that don't have them,
3635      * and post a stream-collection onto the bus */
3636     if (parsepad->active_collection == NULL && fallback_collection) {
3637       gst_pad_push_event (GST_PAD (parsepad),
3638           gst_event_new_stream_collection (fallback_collection));
3639     }
3640     gst_object_unref (parsepad);
3641   }
3642   g_list_free (endpads);
3643 
3644   if (fallback_collection)
3645     gst_object_unref (fallback_collection);
3646 
3647   /* Remove old groups */
3648   chain_remove_old_groups (parsebin->parse_chain);
3649 
3650   GST_DEBUG_OBJECT (parsebin, "Exposed everything");
3651   return TRUE;
3652 }
3653 
3654 /* gst_parse_chain_expose:
3655  *
3656  * Check if the chain can be exposed and add all endpads
3657  * to the endpads list.
3658  *
3659  * Not MT-safe, call with ParseBin expose lock! *
3660  */
3661 static gboolean
gst_parse_chain_expose(GstParseChain * chain,GList ** endpads,gboolean * missing_plugin,GString * missing_plugin_details,gboolean * last_group,gboolean * uncollected_streams)3662 gst_parse_chain_expose (GstParseChain * chain, GList ** endpads,
3663     gboolean * missing_plugin, GString * missing_plugin_details,
3664     gboolean * last_group, gboolean * uncollected_streams)
3665 {
3666   GstParseGroup *group;
3667   GList *l;
3668   gboolean ret = FALSE;
3669 
3670   if (chain->deadend) {
3671     if (chain->endcaps) {
3672       if (chain->deadend_details) {
3673         g_string_append (missing_plugin_details, chain->deadend_details);
3674         g_string_append_c (missing_plugin_details, '\n');
3675       } else {
3676         gchar *desc = gst_pb_utils_get_codec_description (chain->endcaps);
3677         gchar *caps_str = gst_caps_to_string (chain->endcaps);
3678         g_string_append_printf (missing_plugin_details,
3679             "Missing parser: %s (%s)\n", desc, caps_str);
3680         g_free (caps_str);
3681         g_free (desc);
3682       }
3683       *missing_plugin = TRUE;
3684     }
3685     return TRUE;
3686   }
3687 
3688   if (chain->endpad == NULL && chain->parsed && chain->pending_pads) {
3689     /* The chain has a pending pad from a parser, let's just
3690      * expose that now as the endpad */
3691     GList *cur = chain->pending_pads;
3692     GstPendingPad *ppad = (GstPendingPad *) (cur->data);
3693     GstPad *endpad = gst_object_ref (ppad->pad);
3694     GstElement *elem =
3695         GST_ELEMENT (gst_object_get_parent (GST_OBJECT (endpad)));
3696 
3697     chain->pending_pads = g_list_remove (chain->pending_pads, ppad);
3698 
3699     gst_pending_pad_free (ppad);
3700 
3701     GST_DEBUG_OBJECT (chain->parsebin,
3702         "Exposing pad %" GST_PTR_FORMAT " with incomplete caps "
3703         "because it's parsed", endpad);
3704 
3705     expose_pad (chain->parsebin, elem, chain->current_pad, endpad, NULL, chain);
3706     gst_object_unref (endpad);
3707     gst_object_unref (elem);
3708   }
3709 
3710   if (chain->endpad) {
3711     GstParsePad *p = chain->endpad;
3712 
3713     if (p->active_stream && p->active_collection == NULL
3714         && !p->in_a_fallback_collection)
3715       *uncollected_streams = TRUE;
3716 
3717     *endpads = g_list_prepend (*endpads, gst_object_ref (p));
3718     return TRUE;
3719   }
3720 
3721   if (chain->next_groups)
3722     *last_group = FALSE;
3723 
3724   group = chain->active_group;
3725   if (!group) {
3726     GstParsePad *p = chain->current_pad;
3727 
3728     if (p->active_stream && p->active_collection == NULL
3729         && !p->in_a_fallback_collection)
3730       *uncollected_streams = TRUE;
3731 
3732     return FALSE;
3733   }
3734 
3735   for (l = group->children; l; l = l->next) {
3736     GstParseChain *childchain = l->data;
3737 
3738     CHAIN_MUTEX_LOCK (childchain);
3739     ret |= gst_parse_chain_expose (childchain, endpads, missing_plugin,
3740         missing_plugin_details, last_group, uncollected_streams);
3741     CHAIN_MUTEX_UNLOCK (childchain);
3742   }
3743 
3744   return ret;
3745 }
3746 
3747 static void
build_fallback_collection(GstParseChain * chain,GstStreamCollection * collection)3748 build_fallback_collection (GstParseChain * chain,
3749     GstStreamCollection * collection)
3750 {
3751   GstParseGroup *group = chain->active_group;
3752   GList *l;
3753 
3754   /* If it's an end pad, or a not-finished chain that's
3755    * not a group, put it in the collection */
3756   if (chain->endpad || (chain->current_pad && group == NULL)) {
3757     GstParsePad *p = chain->current_pad;
3758 
3759     if (p->active_stream != NULL && p->active_collection == NULL) {
3760       GST_DEBUG_OBJECT (p, "Adding stream to fallback collection");
3761       if (G_UNLIKELY (gst_stream_get_stream_type (p->active_stream) ==
3762               GST_STREAM_TYPE_UNKNOWN)) {
3763         GstCaps *caps;
3764         caps = get_pad_caps (GST_PAD_CAST (p));
3765 
3766         if (caps) {
3767           GstStreamType type = guess_stream_type_from_caps (caps);
3768           if (type != GST_STREAM_TYPE_UNKNOWN) {
3769             gst_stream_set_stream_type (p->active_stream, type);
3770             gst_stream_set_caps (p->active_stream, caps);
3771           }
3772           gst_caps_unref (caps);
3773         }
3774       }
3775       gst_stream_collection_add_stream (collection,
3776           gst_object_ref (p->active_stream));
3777       p->in_a_fallback_collection = TRUE;
3778     }
3779     return;
3780   }
3781 
3782   if (!group)
3783     return;
3784 
3785   /* we used g_list_prepend when adding children, so iterate from last
3786    * to first to maintain the original order they were added in */
3787   for (l = g_list_last (group->children); l != NULL; l = l->prev) {
3788     GstParseChain *childchain = l->data;
3789 
3790     build_fallback_collection (childchain, collection);
3791   }
3792 }
3793 
3794 /*************************
3795  * GstParsePad functions
3796  *************************/
3797 
3798 static void gst_parse_pad_dispose (GObject * object);
3799 
3800 static void
gst_parse_pad_class_init(GstParsePadClass * klass)3801 gst_parse_pad_class_init (GstParsePadClass * klass)
3802 {
3803   GObjectClass *gobject_klass;
3804 
3805   gobject_klass = (GObjectClass *) klass;
3806 
3807   gobject_klass->dispose = gst_parse_pad_dispose;
3808 }
3809 
3810 static void
gst_parse_pad_init(GstParsePad * pad)3811 gst_parse_pad_init (GstParsePad * pad)
3812 {
3813   pad->chain = NULL;
3814   pad->blocked = FALSE;
3815   pad->exposed = FALSE;
3816   pad->drained = FALSE;
3817   gst_object_ref_sink (pad);
3818 }
3819 
3820 static void
gst_parse_pad_dispose(GObject * object)3821 gst_parse_pad_dispose (GObject * object)
3822 {
3823   GstParsePad *parsepad = (GstParsePad *) (object);
3824   parse_pad_set_target (parsepad, NULL);
3825 
3826   gst_object_replace ((GstObject **) & parsepad->active_collection, NULL);
3827   gst_object_replace ((GstObject **) & parsepad->active_stream, NULL);
3828 
3829   G_OBJECT_CLASS (gst_parse_pad_parent_class)->dispose (object);
3830 }
3831 
3832 static GstPadProbeReturn
source_pad_blocked_cb(GstPad * pad,GstPadProbeInfo * info,gpointer user_data)3833 source_pad_blocked_cb (GstPad * pad, GstPadProbeInfo * info, gpointer user_data)
3834 {
3835   GstParsePad *parsepad = user_data;
3836   GstParseChain *chain;
3837   GstParseBin *parsebin;
3838   GstPadProbeReturn ret = GST_PAD_PROBE_OK;
3839 
3840   if (GST_PAD_PROBE_INFO_TYPE (info) & GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM) {
3841     GstEvent *event = GST_PAD_PROBE_INFO_EVENT (info);
3842 
3843     GST_LOG_OBJECT (pad, "Seeing event '%s'", GST_EVENT_TYPE_NAME (event));
3844 
3845     if (!GST_EVENT_IS_SERIALIZED (event)) {
3846       /* do not block on sticky or out of band events otherwise the allocation query
3847          from demuxer might block the loop thread */
3848       GST_LOG_OBJECT (pad, "Letting OOB event through");
3849       return GST_PAD_PROBE_PASS;
3850     }
3851 
3852     if (GST_EVENT_IS_STICKY (event) && GST_EVENT_TYPE (event) != GST_EVENT_EOS) {
3853       GstPad *peer;
3854 
3855       /* manually push sticky events to ghost pad to avoid exposing pads
3856        * that don't have the sticky events. Handle EOS separately as we
3857        * want to block the pad on it if we didn't get any buffers before
3858        * EOS and expose the pad then. */
3859       peer = gst_pad_get_peer (pad);
3860       gst_pad_send_event (peer, event);
3861       gst_object_unref (peer);
3862       GST_LOG_OBJECT (pad, "Manually pushed sticky event through");
3863       ret = GST_PAD_PROBE_HANDLED;
3864       goto done;
3865     }
3866   } else if (GST_PAD_PROBE_INFO_TYPE (info) &
3867       GST_PAD_PROBE_TYPE_QUERY_DOWNSTREAM) {
3868     GstQuery *query = GST_PAD_PROBE_INFO_QUERY (info);
3869 
3870     if (!GST_QUERY_IS_SERIALIZED (query)) {
3871       /* do not block on non-serialized queries */
3872       GST_LOG_OBJECT (pad, "Letting non-serialized query through");
3873       return GST_PAD_PROBE_PASS;
3874     }
3875     if (!gst_pad_has_current_caps (pad)) {
3876       /* do not block on allocation queries before we have caps,
3877        * this would deadlock because we are doing no autoplugging
3878        * without caps.
3879        * TODO: Try to do autoplugging based on the query caps
3880        */
3881       GST_LOG_OBJECT (pad, "Letting serialized query before caps through");
3882       return GST_PAD_PROBE_PASS;
3883     }
3884   }
3885   chain = parsepad->chain;
3886   parsebin = chain->parsebin;
3887 
3888   GST_LOG_OBJECT (parsepad, "blocked: parsepad->chain:%p", chain);
3889 
3890   parsepad->blocked = TRUE;
3891 
3892   EXPOSE_LOCK (parsebin);
3893   if (parsebin->parse_chain) {
3894     if (!gst_parse_bin_expose (parsebin))
3895       GST_WARNING_OBJECT (parsebin, "Couldn't expose group");
3896   }
3897   EXPOSE_UNLOCK (parsebin);
3898 
3899 done:
3900   return ret;
3901 }
3902 
3903 /* FIXME: We can probably do some cleverer things, and maybe move this into
3904  * pbutils. Ideas:
3905  *    if there are tags look if it's got an AUDIO_CODEC VIDEO_CODEC CONTAINER_FORMAT tag
3906  *    Look at the factory klass designation of parsers in the chain
3907  *    Consider demuxer pad names as well, sometimes they give the type away
3908  */
3909 static GstStreamType
guess_stream_type_from_caps(GstCaps * caps)3910 guess_stream_type_from_caps (GstCaps * caps)
3911 {
3912   GstStructure *s;
3913   const gchar *name;
3914 
3915   if (gst_caps_get_size (caps) < 1)
3916     return GST_STREAM_TYPE_UNKNOWN;
3917 
3918   s = gst_caps_get_structure (caps, 0);
3919   name = gst_structure_get_name (s);
3920 
3921   if (g_str_has_prefix (name, "video/") || g_str_has_prefix (name, "image/"))
3922     return GST_STREAM_TYPE_VIDEO;
3923   if (g_str_has_prefix (name, "audio/"))
3924     return GST_STREAM_TYPE_AUDIO;
3925   if (g_str_has_prefix (name, "text/") ||
3926       g_str_has_prefix (name, "subpicture/") ||
3927       g_str_has_prefix (name, "subtitle/") ||
3928       g_str_has_prefix (name, "closedcaption/"))
3929     return GST_STREAM_TYPE_TEXT;
3930 
3931   return GST_STREAM_TYPE_UNKNOWN;
3932 }
3933 
3934 static void
gst_parse_pad_update_caps(GstParsePad * parsepad,GstCaps * caps)3935 gst_parse_pad_update_caps (GstParsePad * parsepad, GstCaps * caps)
3936 {
3937   if (caps && parsepad->active_stream) {
3938     GST_DEBUG_OBJECT (parsepad, "Storing caps %" GST_PTR_FORMAT
3939         " on stream %" GST_PTR_FORMAT, caps, parsepad->active_stream);
3940 
3941     if (gst_caps_is_fixed (caps))
3942       gst_stream_set_caps (parsepad->active_stream, caps);
3943     /* intuit a type */
3944     if (gst_stream_get_stream_type (parsepad->active_stream) ==
3945         GST_STREAM_TYPE_UNKNOWN) {
3946       GstStreamType new_type = guess_stream_type_from_caps (caps);
3947       if (new_type != GST_STREAM_TYPE_UNKNOWN)
3948         gst_stream_set_stream_type (parsepad->active_stream, new_type);
3949     }
3950   }
3951 }
3952 
3953 static void
gst_parse_pad_update_tags(GstParsePad * parsepad,GstTagList * tags)3954 gst_parse_pad_update_tags (GstParsePad * parsepad, GstTagList * tags)
3955 {
3956   if (tags && gst_tag_list_get_scope (tags) == GST_TAG_SCOPE_STREAM
3957       && parsepad->active_stream) {
3958     GST_DEBUG_OBJECT (parsepad,
3959         "Storing new tags %" GST_PTR_FORMAT " on stream %" GST_PTR_FORMAT, tags,
3960         parsepad->active_stream);
3961     gst_stream_set_tags (parsepad->active_stream, tags);
3962   }
3963 }
3964 
3965 static GstEvent *
gst_parse_pad_stream_start_event(GstParsePad * parsepad,GstEvent * event)3966 gst_parse_pad_stream_start_event (GstParsePad * parsepad, GstEvent * event)
3967 {
3968   GstStream *stream = NULL;
3969   const gchar *stream_id = NULL;
3970   gboolean repeat_event = FALSE;
3971   GstStreamFlags streamflags;
3972 
3973   gst_event_parse_stream_start (event, &stream_id);
3974   gst_event_parse_stream_flags (event, &streamflags);
3975 
3976   if (parsepad->active_stream != NULL &&
3977       g_str_equal (parsepad->active_stream->stream_id, stream_id))
3978     repeat_event = TRUE;
3979   else {
3980     /* A new stream requires a new collection event, or else
3981      * we'll place it in a fallback collection later */
3982     gst_object_replace ((GstObject **) & parsepad->active_collection, NULL);
3983     parsepad->in_a_fallback_collection = FALSE;
3984   }
3985 
3986   gst_event_parse_stream (event, &stream);
3987   if (stream == NULL) {
3988     GstCaps *caps = gst_pad_get_current_caps (GST_PAD_CAST (parsepad));
3989     if (caps == NULL) {
3990       /* Try and get caps from the parsepad peer */
3991       GstPad *peer = gst_ghost_pad_get_target (GST_GHOST_PAD (parsepad));
3992       caps = gst_pad_get_current_caps (peer);
3993       gst_object_unref (peer);
3994     }
3995     if (caps == NULL && parsepad->chain && parsepad->chain->start_caps) {
3996       /* Still no caps, use the chain start caps */
3997       caps = gst_caps_ref (parsepad->chain->start_caps);
3998     }
3999 
4000     GST_DEBUG_OBJECT (parsepad,
4001         "Saw stream_start with no GstStream. Adding one. Caps %"
4002         GST_PTR_FORMAT, caps);
4003 
4004     if (repeat_event) {
4005       GST_LOG_OBJECT (parsepad, "Using previously created GstStream");
4006       stream = gst_object_ref (parsepad->active_stream);
4007     } else {
4008       GST_LOG_OBJECT (parsepad, "Creating unknown GstStream");
4009       stream =
4010           gst_stream_new (stream_id, NULL, GST_STREAM_TYPE_UNKNOWN,
4011           streamflags);
4012       gst_object_replace ((GstObject **) & parsepad->active_stream,
4013           (GstObject *) stream);
4014     }
4015     if (caps) {
4016       gst_parse_pad_update_caps (parsepad, caps);
4017       gst_caps_unref (caps);
4018     }
4019 
4020     event = gst_event_make_writable (event);
4021     gst_event_set_stream (event, stream);
4022   }
4023   gst_object_unref (stream);
4024   GST_LOG_OBJECT (parsepad, "Saw stream %s (GstStream %p)",
4025       stream->stream_id, stream);
4026 
4027   return event;
4028 }
4029 
4030 static void
gst_parse_pad_update_stream_collection(GstParsePad * parsepad,GstStreamCollection * collection)4031 gst_parse_pad_update_stream_collection (GstParsePad * parsepad,
4032     GstStreamCollection * collection)
4033 {
4034   GST_LOG_OBJECT (parsepad, "Got new stream collection %p", collection);
4035   gst_object_replace ((GstObject **) & parsepad->active_collection,
4036       (GstObject *) collection);
4037   parsepad->in_a_fallback_collection = FALSE;
4038 }
4039 
4040 static GstPadProbeReturn
gst_parse_pad_event(GstPad * pad,GstPadProbeInfo * info,gpointer user_data)4041 gst_parse_pad_event (GstPad * pad, GstPadProbeInfo * info, gpointer user_data)
4042 {
4043   GstEvent *event = GST_PAD_PROBE_INFO_EVENT (info);
4044   GstObject *parent = gst_pad_get_parent (pad);
4045   GstParsePad *parsepad = GST_PARSE_PAD (parent);
4046   gboolean forwardit = TRUE;
4047 
4048   GST_LOG_OBJECT (pad, "%s parsepad:%p", GST_EVENT_TYPE_NAME (event), parsepad);
4049 
4050   switch (GST_EVENT_TYPE (event)) {
4051     case GST_EVENT_CAPS:{
4052       GstCaps *caps = NULL;
4053       gst_event_parse_caps (event, &caps);
4054       gst_parse_pad_update_caps (parsepad, caps);
4055       break;
4056     }
4057     case GST_EVENT_TAG:{
4058       GstTagList *tags;
4059       gst_event_parse_tag (event, &tags);
4060       gst_parse_pad_update_tags (parsepad, tags);
4061       break;
4062     }
4063     case GST_EVENT_STREAM_START:{
4064       GST_PAD_PROBE_INFO_DATA (info) =
4065           gst_parse_pad_stream_start_event (parsepad, event);
4066       break;
4067     }
4068     case GST_EVENT_STREAM_COLLECTION:{
4069       GstStreamCollection *collection = NULL;
4070       gst_event_parse_stream_collection (event, &collection);
4071       gst_parse_pad_update_stream_collection (parsepad, collection);
4072       gst_element_post_message (GST_ELEMENT (parsepad->parsebin),
4073           gst_message_new_stream_collection (GST_OBJECT (parsepad->parsebin),
4074               collection));
4075       break;
4076     }
4077     case GST_EVENT_EOS:{
4078       GST_DEBUG_OBJECT (pad, "we received EOS");
4079 
4080       /* Check if all pads are drained.
4081        * * If there is no next group, we will let the EOS go through.
4082        * * If there is a next group but the current group isn't completely
4083        *   drained, we will drop the EOS event.
4084        * * If there is a next group to expose and this was the last non-drained
4085        *   pad for that group, we will remove the ghostpad of the current group
4086        *   first, which unlinks the peer and so drops the EOS. */
4087       forwardit = gst_parse_pad_handle_eos (parsepad);
4088     }
4089     default:
4090       break;
4091   }
4092   gst_object_unref (parent);
4093   if (forwardit)
4094     return GST_PAD_PROBE_OK;
4095   else
4096     return GST_PAD_PROBE_DROP;
4097 }
4098 
4099 static void
gst_parse_pad_set_blocked(GstParsePad * parsepad,gboolean blocked)4100 gst_parse_pad_set_blocked (GstParsePad * parsepad, gboolean blocked)
4101 {
4102   GstParseBin *parsebin = parsepad->parsebin;
4103   GstPad *opad;
4104 
4105   DYN_LOCK (parsebin);
4106 
4107   GST_DEBUG_OBJECT (parsepad, "blocking pad: %d", blocked);
4108 
4109   opad = gst_ghost_pad_get_target (GST_GHOST_PAD_CAST (parsepad));
4110   if (!opad)
4111     goto out;
4112 
4113   /* do not block if shutting down.
4114    * we do not consider/expect it blocked further below, but use other trick */
4115   if (!blocked || !parsebin->shutdown) {
4116     if (blocked) {
4117       if (parsepad->block_id == 0)
4118         parsepad->block_id =
4119             gst_pad_add_probe (opad,
4120             GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM |
4121             GST_PAD_PROBE_TYPE_QUERY_DOWNSTREAM, source_pad_blocked_cb,
4122             gst_object_ref (parsepad), (GDestroyNotify) gst_object_unref);
4123     } else {
4124       if (parsepad->block_id != 0) {
4125         gst_pad_remove_probe (opad, parsepad->block_id);
4126         parsepad->block_id = 0;
4127       }
4128       parsepad->blocked = FALSE;
4129     }
4130   }
4131 
4132   if (blocked) {
4133     if (parsebin->shutdown) {
4134       /* deactivate to force flushing state to prevent NOT_LINKED errors */
4135       gst_pad_set_active (GST_PAD_CAST (parsepad), FALSE);
4136       /* note that deactivating the target pad would have no effect here,
4137        * since elements are typically connected first (and pads exposed),
4138        * and only then brought to PAUSED state (so pads activated) */
4139     } else {
4140       gst_object_ref (parsepad);
4141       parsebin->blocked_pads =
4142           g_list_prepend (parsebin->blocked_pads, parsepad);
4143     }
4144   } else {
4145     GList *l;
4146 
4147     if ((l = g_list_find (parsebin->blocked_pads, parsepad))) {
4148       gst_object_unref (parsepad);
4149       parsebin->blocked_pads = g_list_delete_link (parsebin->blocked_pads, l);
4150     }
4151   }
4152   gst_object_unref (opad);
4153 out:
4154   DYN_UNLOCK (parsebin);
4155 }
4156 
4157 static void
gst_parse_pad_activate(GstParsePad * parsepad,GstParseChain * chain)4158 gst_parse_pad_activate (GstParsePad * parsepad, GstParseChain * chain)
4159 {
4160   g_return_if_fail (chain != NULL);
4161 
4162   parsepad->chain = chain;
4163   gst_pad_set_active (GST_PAD_CAST (parsepad), TRUE);
4164   gst_parse_pad_set_blocked (parsepad, TRUE);
4165 }
4166 
4167 static void
gst_parse_pad_unblock(GstParsePad * parsepad)4168 gst_parse_pad_unblock (GstParsePad * parsepad)
4169 {
4170   gst_parse_pad_set_blocked (parsepad, FALSE);
4171 }
4172 
4173 static gboolean
gst_parse_pad_query(GstPad * pad,GstObject * parent,GstQuery * query)4174 gst_parse_pad_query (GstPad * pad, GstObject * parent, GstQuery * query)
4175 {
4176   GstParsePad *parsepad = GST_PARSE_PAD (parent);
4177   gboolean ret = FALSE;
4178 
4179   CHAIN_MUTEX_LOCK (parsepad->chain);
4180   if (!parsepad->exposed && !parsepad->parsebin->shutdown
4181       && !parsepad->chain->deadend && parsepad->chain->elements) {
4182     GstParseElement *pelem = parsepad->chain->elements->data;
4183 
4184     ret = FALSE;
4185     GST_DEBUG_OBJECT (parsepad->parsebin,
4186         "calling autoplug-query for %s (element %s): %" GST_PTR_FORMAT,
4187         GST_PAD_NAME (parsepad), GST_ELEMENT_NAME (pelem->element), query);
4188     g_signal_emit (G_OBJECT (parsepad->parsebin),
4189         gst_parse_bin_signals[SIGNAL_AUTOPLUG_QUERY], 0, parsepad,
4190         pelem->element, query, &ret);
4191 
4192     if (ret)
4193       GST_DEBUG_OBJECT (parsepad->parsebin,
4194           "autoplug-query returned %d: %" GST_PTR_FORMAT, ret, query);
4195     else
4196       GST_DEBUG_OBJECT (parsepad->parsebin, "autoplug-query returned %d", ret);
4197   }
4198   CHAIN_MUTEX_UNLOCK (parsepad->chain);
4199 
4200   /* If exposed or nothing handled the query use the default handler */
4201   if (!ret)
4202     ret = gst_pad_query_default (pad, parent, query);
4203 
4204   return ret;
4205 }
4206 
4207 /*gst_parse_pad_new:
4208  *
4209  * Creates a new GstParsePad for the given pad.
4210  */
4211 static GstParsePad *
gst_parse_pad_new(GstParseBin * parsebin,GstParseChain * chain)4212 gst_parse_pad_new (GstParseBin * parsebin, GstParseChain * chain)
4213 {
4214   GstParsePad *parsepad;
4215   GstProxyPad *ppad;
4216   GstPadTemplate *pad_tmpl;
4217 
4218   GST_DEBUG_OBJECT (parsebin, "making new parsepad");
4219   pad_tmpl = gst_static_pad_template_get (&parse_bin_src_template);
4220   parsepad =
4221       g_object_new (GST_TYPE_PARSE_PAD, "direction", GST_PAD_SRC,
4222       "template", pad_tmpl, NULL);
4223   parsepad->chain = chain;
4224   parsepad->parsebin = parsebin;
4225   gst_object_unref (pad_tmpl);
4226 
4227   ppad = gst_proxy_pad_get_internal (GST_PROXY_PAD (parsepad));
4228   gst_pad_set_query_function (GST_PAD_CAST (ppad), gst_parse_pad_query);
4229 
4230   /* Add downstream event probe */
4231   GST_LOG_OBJECT (parsepad, "Adding event probe on internal pad %"
4232       GST_PTR_FORMAT, ppad);
4233   gst_pad_add_probe (GST_PAD_CAST (ppad),
4234       GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM, gst_parse_pad_event, parsepad, NULL);
4235   gst_object_unref (ppad);
4236 
4237   return parsepad;
4238 }
4239 
4240 static void
gst_pending_pad_free(GstPendingPad * ppad)4241 gst_pending_pad_free (GstPendingPad * ppad)
4242 {
4243   g_assert (ppad);
4244   g_assert (ppad->pad);
4245 
4246   if (ppad->event_probe_id != 0)
4247     gst_pad_remove_probe (ppad->pad, ppad->event_probe_id);
4248   if (ppad->notify_caps_id)
4249     g_signal_handler_disconnect (ppad->pad, ppad->notify_caps_id);
4250   gst_object_unref (ppad->pad);
4251   g_slice_free (GstPendingPad, ppad);
4252 }
4253 
4254 /*****
4255  * Element add/remove
4256  *****/
4257 
4258 /* call with dyn_lock held */
4259 static void
unblock_pads(GstParseBin * parsebin)4260 unblock_pads (GstParseBin * parsebin)
4261 {
4262   GList *tmp;
4263 
4264   GST_LOG_OBJECT (parsebin, "unblocking pads");
4265 
4266   for (tmp = parsebin->blocked_pads; tmp; tmp = tmp->next) {
4267     GstParsePad *parsepad = (GstParsePad *) tmp->data;
4268     GstPad *opad;
4269 
4270     opad = gst_ghost_pad_get_target (GST_GHOST_PAD_CAST (parsepad));
4271     if (!opad)
4272       continue;
4273 
4274     GST_DEBUG_OBJECT (parsepad, "unblocking");
4275     if (parsepad->block_id != 0) {
4276       gst_pad_remove_probe (opad, parsepad->block_id);
4277       parsepad->block_id = 0;
4278     }
4279     parsepad->blocked = FALSE;
4280     /* make flushing, prevent NOT_LINKED */
4281     gst_pad_set_active (GST_PAD_CAST (parsepad), FALSE);
4282     gst_object_unref (parsepad);
4283     gst_object_unref (opad);
4284     GST_DEBUG_OBJECT (parsepad, "unblocked");
4285   }
4286 
4287   /* clear, no more blocked pads */
4288   g_list_free (parsebin->blocked_pads);
4289   parsebin->blocked_pads = NULL;
4290 }
4291 
4292 static GstStateChangeReturn
gst_parse_bin_change_state(GstElement * element,GstStateChange transition)4293 gst_parse_bin_change_state (GstElement * element, GstStateChange transition)
4294 {
4295   GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
4296   GstParseBin *parsebin = GST_PARSE_BIN (element);
4297   GstParseChain *chain_to_free = NULL;
4298 
4299   switch (transition) {
4300     case GST_STATE_CHANGE_NULL_TO_READY:
4301       if (parsebin->typefind == NULL)
4302         goto missing_typefind;
4303       break;
4304     case GST_STATE_CHANGE_READY_TO_PAUSED:
4305       /* Make sure we've cleared all existing chains */
4306       EXPOSE_LOCK (parsebin);
4307       if (parsebin->parse_chain) {
4308         gst_parse_chain_free (parsebin->parse_chain);
4309         parsebin->parse_chain = NULL;
4310       }
4311       EXPOSE_UNLOCK (parsebin);
4312       DYN_LOCK (parsebin);
4313       GST_LOG_OBJECT (parsebin, "clearing shutdown flag");
4314       parsebin->shutdown = FALSE;
4315       DYN_UNLOCK (parsebin);
4316       parsebin->have_type = FALSE;
4317 
4318 
4319       /* connect a signal to find out when the typefind element found
4320        * a type */
4321       parsebin->have_type_id =
4322           g_signal_connect (parsebin->typefind, "have-type",
4323           G_CALLBACK (type_found), parsebin);
4324       break;
4325     case GST_STATE_CHANGE_PAUSED_TO_READY:
4326       if (parsebin->have_type_id)
4327         g_signal_handler_disconnect (parsebin->typefind,
4328             parsebin->have_type_id);
4329       parsebin->have_type_id = 0;
4330       DYN_LOCK (parsebin);
4331       GST_LOG_OBJECT (parsebin, "setting shutdown flag");
4332       parsebin->shutdown = TRUE;
4333       unblock_pads (parsebin);
4334       DYN_UNLOCK (parsebin);
4335     default:
4336       break;
4337   }
4338 
4339   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
4340   if (G_UNLIKELY (ret == GST_STATE_CHANGE_FAILURE))
4341     goto activate_failed;
4342 
4343   switch (transition) {
4344     case GST_STATE_CHANGE_PAUSED_TO_READY:
4345       EXPOSE_LOCK (parsebin);
4346       if (parsebin->parse_chain) {
4347         chain_to_free = parsebin->parse_chain;
4348         gst_parse_chain_free_internal (parsebin->parse_chain, TRUE);
4349         parsebin->parse_chain = NULL;
4350       }
4351       EXPOSE_UNLOCK (parsebin);
4352       if (chain_to_free)
4353         gst_parse_chain_free (chain_to_free);
4354       break;
4355     case GST_STATE_CHANGE_READY_TO_NULL:
4356       g_mutex_lock (&parsebin->cleanup_lock);
4357       if (parsebin->cleanup_thread) {
4358         g_thread_join (parsebin->cleanup_thread);
4359         parsebin->cleanup_thread = NULL;
4360       }
4361       g_mutex_unlock (&parsebin->cleanup_lock);
4362     default:
4363       break;
4364   }
4365 
4366   return ret;
4367 
4368 /* ERRORS */
4369 missing_typefind:
4370   {
4371     gst_element_post_message (element,
4372         gst_missing_element_message_new (element, "typefind"));
4373     GST_ELEMENT_ERROR (parsebin, CORE, MISSING_PLUGIN, (NULL),
4374         ("no typefind!"));
4375     return GST_STATE_CHANGE_FAILURE;
4376   }
4377 activate_failed:
4378   {
4379     GST_DEBUG_OBJECT (element,
4380         "element failed to change states -- activation problem?");
4381     return GST_STATE_CHANGE_FAILURE;
4382   }
4383 }
4384 
4385 static void
gst_parse_bin_handle_message(GstBin * bin,GstMessage * msg)4386 gst_parse_bin_handle_message (GstBin * bin, GstMessage * msg)
4387 {
4388   GstParseBin *parsebin = GST_PARSE_BIN (bin);
4389   gboolean drop = FALSE;
4390 
4391   switch (GST_MESSAGE_TYPE (msg)) {
4392     case GST_MESSAGE_ERROR:{
4393       /* Don't pass errors when shutting down. Sometimes,
4394        * elements can generate spurious errors because we set the
4395        * output pads to flushing, and they can't detect that if they
4396        * send an event at exactly the wrong moment */
4397       DYN_LOCK (parsebin);
4398       drop = parsebin->shutdown;
4399       DYN_UNLOCK (parsebin);
4400 
4401       if (!drop) {
4402         GST_OBJECT_LOCK (parsebin);
4403         drop =
4404             (g_list_find (parsebin->filtered, GST_MESSAGE_SRC (msg)) != NULL);
4405         if (drop)
4406           parsebin->filtered_errors =
4407               g_list_prepend (parsebin->filtered_errors, gst_message_ref (msg));
4408         GST_OBJECT_UNLOCK (parsebin);
4409       }
4410       break;
4411     }
4412     default:
4413       break;
4414   }
4415 
4416   if (drop)
4417     gst_message_unref (msg);
4418   else
4419     GST_BIN_CLASS (parent_class)->handle_message (bin, msg);
4420 }
4421