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