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