• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* GStreamer
2  * Copyright (C) <2006> Edward Hervey <edward@fluendo.com>
3  * Copyright (C) <2009> Sebastian Dröge <sebastian.droege@collabora.co.uk>
4  * Copyright (C) <2011> Hewlett-Packard Development Company, L.P.
5  *   Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>, Collabora Ltd.
6  * Copyright (C) <2013> Collabora Ltd.
7  *   Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Library General Public
11  * License as published by the Free Software Foundation; either
12  * version 2 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Library General Public License for more details.
18  *
19  * You should have received a copy of the GNU Library General Public
20  * License along with this library; if not, write to the
21  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
22  * Boston, MA 02110-1301, USA.
23  */
24 
25 /**
26  * SECTION:element-decodebin
27  * @title: decodebin
28  *
29  * #GstBin that auto-magically constructs a decoding pipeline using available
30  * decoders and demuxers via auto-plugging.
31  *
32  * decodebin is considered stable now and replaces the old #decodebin element.
33  * #uridecodebin uses decodebin internally and is often more convenient to
34  * use, as it creates a suitable source element as well.
35  */
36 
37 /* Implementation notes:
38  *
39  * The following section describes how decodebin works internally.
40  *
41  * The first part of decodebin is its typefind element, which tries
42  * to determine the media type of the input stream. If the type is found
43  * autoplugging starts.
44  *
45  * decodebin internally organizes the elements it autoplugged into GstDecodeChains
46  * and GstDecodeGroups. A decode chain is a single chain of decoding, this
47  * means that if decodebin every autoplugs an element with two+ srcpads
48  * (e.g. a demuxer) this will end the chain and everything following this
49  * demuxer will be put into decode groups below the chain. Otherwise,
50  * if an element has a single srcpad that outputs raw data the decode chain
51  * is ended too and a GstDecodePad is stored and blocked.
52  *
53  * A decode group combines a number of chains that are created by a
54  * demuxer element. All those chains are connected through a multiqueue to
55  * the demuxer. A new group for the same demuxer is only created if the
56  * demuxer has signaled no-more-pads, in which case all following pads
57  * create a new chain in the new group.
58  *
59  * This continues until the top-level decode chain is complete. A decode
60  * chain is complete if it either ends with a blocked endpad, if autoplugging
61  * stopped because no suitable plugins could be found or if the active group
62  * is complete. A decode group on the other hand is complete if all child
63  * chains are complete.
64  *
65  * If this happens at some point, all endpads of all active groups are exposed.
66  * For this decodebin adds the endpads, signals no-more-pads and then unblocks
67  * them. Now playback starts.
68  *
69  * If one of the chains that end on a endpad receives EOS decodebin checks
70  * if all chains and groups are drained. In that case everything goes into EOS.
71  * If there is a chain where the active group is drained but there exist next
72  * groups, the active group is hidden (endpads are removed) and the next group
73  * is exposed. This means that in some cases more pads may be created even
74  * after the initial no-more-pads signal. This happens for example with
75  * so-called "chained oggs", most commonly found among ogg/vorbis internet
76  * radio streams.
77  *
78  * Note 1: If we're talking about blocked endpads this really means that the
79  * *target* pads of the endpads are blocked. Pads that are exposed to the outside
80  * should never ever be blocked!
81  *
82  * Note 2: If a group is complete and the parent's chain demuxer adds new pads
83  * but never signaled no-more-pads this additional pads will be ignored!
84  *
85  */
86 
87 /* FIXME 0.11: suppress warnings for deprecated API such as GValueArray
88  * with newer GLib versions (>= 2.31.0) */
89 #define GLIB_DISABLE_DEPRECATION_WARNINGS
90 
91 #ifdef HAVE_CONFIG_H
92 #include "config.h"
93 #endif
94 
95 #include <gst/gst-i18n-plugin.h>
96 
97 #include <string.h>
98 #include <gst/gst.h>
99 #include <gst/pbutils/pbutils.h>
100 
101 #include "gstplay-enum.h"
102 #include "gstplaybackelements.h"
103 #include "gstrawcaps.h"
104 #include "gstplaybackutils.h"
105 
106 /* generic templates */
107 static GstStaticPadTemplate decoder_bin_sink_template =
108 GST_STATIC_PAD_TEMPLATE ("sink",
109     GST_PAD_SINK,
110     GST_PAD_ALWAYS,
111     GST_STATIC_CAPS_ANY);
112 
113 static GstStaticPadTemplate decoder_bin_src_template =
114 GST_STATIC_PAD_TEMPLATE ("src_%u",
115     GST_PAD_SRC,
116     GST_PAD_SOMETIMES,
117     GST_STATIC_CAPS_ANY);
118 
119 GST_DEBUG_CATEGORY_STATIC (gst_decode_bin_debug);
120 #define GST_CAT_DEFAULT gst_decode_bin_debug
121 
122 typedef struct _GstPendingPad GstPendingPad;
123 typedef struct _GstDecodeElement GstDecodeElement;
124 typedef struct _GstDemuxerPad GstDemuxerPad;
125 typedef struct _GstDecodeChain GstDecodeChain;
126 typedef struct _GstDecodeGroup GstDecodeGroup;
127 typedef struct _GstDecodePad GstDecodePad;
128 typedef GstGhostPadClass GstDecodePadClass;
129 typedef struct _GstDecodeBin GstDecodeBin;
130 typedef struct _GstDecodeBinClass GstDecodeBinClass;
131 
132 #define GST_TYPE_DECODE_BIN             (gst_decode_bin_get_type())
133 #define GST_DECODE_BIN_CAST(obj)        ((GstDecodeBin*)(obj))
134 #define GST_DECODE_BIN(obj)             (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_DECODE_BIN,GstDecodeBin))
135 #define GST_DECODE_BIN_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_DECODE_BIN,GstDecodeBinClass))
136 #define GST_IS_DECODE_BIN(obj)          (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_DECODE_BIN))
137 #define GST_IS_DECODE_BIN_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_DECODE_BIN))
138 
139 /**
140  *  GstDecodeBin:
141  *
142  *  The opaque #GstDecodeBin data structure
143  */
144 struct _GstDecodeBin
145 {
146   GstBin bin;                   /* we extend GstBin */
147 
148   /* properties */
149   GstCaps *caps;                /* caps on which to stop decoding */
150   gchar *encoding;              /* encoding of subtitles */
151   gboolean use_buffering;       /* configure buffering on multiqueues */
152   gboolean force_sw_decoders;
153   gint low_percent;
154   gint high_percent;
155   guint max_size_bytes;
156   guint max_size_buffers;
157   guint64 max_size_time;
158   gboolean post_stream_topology;
159   guint64 connection_speed;
160 
161   GstElement *typefind;         /* this holds the typefind object */
162 
163   GMutex expose_lock;           /* Protects exposal and removal of groups */
164   GstDecodeChain *decode_chain; /* Top level decode chain */
165   guint nbpads;                 /* unique identifier for source pads */
166 
167   GMutex factories_lock;
168   guint32 factories_cookie;     /* Cookie from last time when factories was updated */
169   GList *factories;             /* factories we can use for selecting elements */
170 
171   GMutex subtitle_lock;         /* Protects changes to subtitles and encoding */
172   GList *subtitles;             /* List of elements with subtitle-encoding,
173                                  * protected by above mutex! */
174 
175   gboolean have_type;           /* if we received the have_type signal */
176   guint have_type_id;           /* signal id for have-type from typefind */
177 
178   gboolean async_pending;       /* async-start has been emitted */
179 
180   GMutex dyn_lock;              /* lock protecting pad blocking */
181   gboolean shutdown;            /* if we are shutting down */
182   GList *blocked_pads;          /* pads that have set to block */
183 
184   gboolean expose_allstreams;   /* Whether to expose unknown type streams or not */
185 
186   GList *filtered;              /* elements for which error messages are filtered */
187   GList *filtered_errors;       /* filtered error messages */
188 
189   GList *buffering_status;      /* element currently buffering messages */
190   GMutex buffering_lock;
191   GMutex buffering_post_lock;
192 
193   GMutex cleanup_lock;          /* Mutex used to protect the cleanup thread */
194   GThread *cleanup_thread;      /* thread used to free chains asynchronously.
195                                  * We store it to make sure we end up joining it
196                                  * before stopping the element.
197                                  * Protected by the object lock */
198   GList *cleanup_groups;        /* List of groups to free  */
199 
200 #ifdef OHOS_EXT_FUNC
201   // ohos.ext.func.0013
202   guint mq_num_use_buffering;
203 #endif
204 };
205 
206 struct _GstDecodeBinClass
207 {
208   GstBinClass parent_class;
209 
210   /* signal fired when we found a pad that we cannot decode */
211   void (*unknown_type) (GstElement * element, GstPad * pad, GstCaps * caps);
212 
213   /* signal fired to know if we continue trying to decode the given caps */
214     gboolean (*autoplug_continue) (GstElement * element, GstPad * pad,
215       GstCaps * caps);
216   /* signal fired to get a list of factories to try to autoplug */
217   GValueArray *(*autoplug_factories) (GstElement * element, GstPad * pad,
218       GstCaps * caps);
219   /* signal fired to sort the factories */
220   GValueArray *(*autoplug_sort) (GstElement * element, GstPad * pad,
221       GstCaps * caps, GValueArray * factories);
222   /* signal fired to select from the proposed list of factories */
223     GstAutoplugSelectResult (*autoplug_select) (GstElement * element,
224       GstPad * pad, GstCaps * caps, GstElementFactory * factory);
225   /* signal fired when a autoplugged element that is not linked downstream
226    * or exposed wants to query something */
227     gboolean (*autoplug_query) (GstElement * element, GstPad * pad,
228       GstQuery * query);
229 
230   /* fired when the last group is drained */
231   void (*drained) (GstElement * element);
232 };
233 
234 /* signals */
235 enum
236 {
237   SIGNAL_UNKNOWN_TYPE,
238   SIGNAL_AUTOPLUG_CONTINUE,
239   SIGNAL_AUTOPLUG_FACTORIES,
240   SIGNAL_AUTOPLUG_SELECT,
241   SIGNAL_AUTOPLUG_SORT,
242   SIGNAL_AUTOPLUG_QUERY,
243   SIGNAL_DRAINED,
244 #ifdef OHOS_EXT_FUNC
245   // ohos.ext.func.0028
246   SIGNAL_BITRATE_PARSE_COMPLETE,
247 #endif
248   LAST_SIGNAL
249 };
250 
251 /* automatic sizes, while prerolling we buffer up to 8MB, we ignore time
252  * and buffers in this case. */
253 #define AUTO_PREROLL_SIZE_BYTES                  8 * 1024 * 1024
254 #define AUTO_PREROLL_SIZE_BUFFERS                0
255 #define AUTO_PREROLL_NOT_SEEKABLE_SIZE_TIME      10 * GST_SECOND
256 #define AUTO_PREROLL_SEEKABLE_SIZE_TIME          0
257 
258 /* when playing, keep a max of 8MB of data but try to keep the number of buffers
259  * as low as possible (try to aim for 5 buffers) */
260 #define AUTO_PLAY_SIZE_BYTES        8 * 1024 * 1024
261 #define AUTO_PLAY_SIZE_BUFFERS      5
262 #define AUTO_PLAY_SIZE_TIME         0
263 
264 #define DEFAULT_SUBTITLE_ENCODING NULL
265 #define DEFAULT_USE_BUFFERING     FALSE
266 #define DEFAULT_FORCE_SW_DECODERS FALSE
267 #define DEFAULT_LOW_PERCENT       10
268 #define DEFAULT_HIGH_PERCENT      99
269 /* by default we use the automatic values above */
270 #define DEFAULT_MAX_SIZE_BYTES    0
271 #define DEFAULT_MAX_SIZE_BUFFERS  0
272 #define DEFAULT_MAX_SIZE_TIME     0
273 #define DEFAULT_POST_STREAM_TOPOLOGY FALSE
274 #define DEFAULT_EXPOSE_ALL_STREAMS  TRUE
275 #define DEFAULT_CONNECTION_SPEED    0
276 
277 #ifdef OHOS_EXT_FUNC
278 // ohos.ext.func.0013
279 #define DEFAULT_TIMEOUT              15
280 #endif
281 
282 /* Properties */
283 enum
284 {
285   PROP_0,
286   PROP_CAPS,
287   PROP_SUBTITLE_ENCODING,
288   PROP_SINK_CAPS,
289   PROP_USE_BUFFERING,
290   PROP_FORCE_SW_DECODERS,
291   PROP_LOW_PERCENT,
292   PROP_HIGH_PERCENT,
293   PROP_MAX_SIZE_BYTES,
294   PROP_MAX_SIZE_BUFFERS,
295   PROP_MAX_SIZE_TIME,
296   PROP_POST_STREAM_TOPOLOGY,
297   PROP_EXPOSE_ALL_STREAMS,
298 #ifdef OHOS_EXT_FUNC
299   // ohos.ext.func.0013
300   PROP_MQ_NUM_USE_BUFFRING,
301   PROP_TIMEOUT,
302   PROP_STATE_CHANGE,
303   PROP_EXIT_BLOCK,
304 #endif
305   PROP_CONNECTION_SPEED
306 };
307 
308 static GstBinClass *parent_class;
309 static guint gst_decode_bin_signals[LAST_SIGNAL] = { 0 };
310 
311 static GstStaticCaps default_raw_caps = GST_STATIC_CAPS (DEFAULT_RAW_CAPS);
312 
313 static void do_async_start (GstDecodeBin * dbin);
314 static void do_async_done (GstDecodeBin * dbin);
315 
316 static void type_found (GstElement * typefind, guint probability,
317     GstCaps * caps, GstDecodeBin * decode_bin);
318 
319 static void decodebin_set_queue_size (GstDecodeBin * dbin,
320     GstElement * multiqueue, gboolean preroll, gboolean seekable);
321 static void decodebin_set_queue_size_full (GstDecodeBin * dbin,
322     GstElement * multiqueue, gboolean use_buffering, gboolean preroll,
323     gboolean seekable);
324 
325 static gboolean gst_decode_bin_autoplug_continue (GstElement * element,
326     GstPad * pad, GstCaps * caps);
327 static GValueArray *gst_decode_bin_autoplug_factories (GstElement *
328     element, GstPad * pad, GstCaps * caps);
329 static GValueArray *gst_decode_bin_autoplug_sort (GstElement * element,
330     GstPad * pad, GstCaps * caps, GValueArray * factories);
331 static GstAutoplugSelectResult gst_decode_bin_autoplug_select (GstElement *
332     element, GstPad * pad, GstCaps * caps, GstElementFactory * factory);
333 static gboolean gst_decode_bin_autoplug_query (GstElement * element,
334     GstPad * pad, GstQuery * query);
335 
336 static void gst_decode_bin_set_property (GObject * object, guint prop_id,
337     const GValue * value, GParamSpec * pspec);
338 static void gst_decode_bin_get_property (GObject * object, guint prop_id,
339     GValue * value, GParamSpec * pspec);
340 static void gst_decode_bin_set_caps (GstDecodeBin * dbin, GstCaps * caps);
341 static GstCaps *gst_decode_bin_get_caps (GstDecodeBin * dbin);
342 static void caps_notify_cb (GstPad * pad, GParamSpec * unused,
343     GstDecodeChain * chain);
344 
345 static void flush_chain (GstDecodeChain * chain, gboolean flushing);
346 static void flush_group (GstDecodeGroup * group, gboolean flushing);
347 static GstPad *find_sink_pad (GstElement * element);
348 static GstStateChangeReturn gst_decode_bin_change_state (GstElement * element,
349     GstStateChange transition);
350 static void gst_decode_bin_handle_message (GstBin * bin, GstMessage * message);
351 static gboolean gst_decode_bin_remove_element (GstBin * bin,
352     GstElement * element);
353 
354 static gboolean check_upstream_seekable (GstDecodeBin * dbin, GstPad * pad);
355 
356 static GstCaps *get_pad_caps (GstPad * pad);
357 static void unblock_pads (GstDecodeBin * dbin);
358 
359 #define EXPOSE_LOCK(dbin) G_STMT_START {				\
360     GST_LOG_OBJECT (dbin,						\
361 		    "expose locking from thread %p",			\
362 		    g_thread_self ());					\
363     g_mutex_lock (&GST_DECODE_BIN_CAST(dbin)->expose_lock);		\
364     GST_LOG_OBJECT (dbin,						\
365 		    "expose locked from thread %p",			\
366 		    g_thread_self ());					\
367 } G_STMT_END
368 
369 #define EXPOSE_UNLOCK(dbin) G_STMT_START {				\
370     GST_LOG_OBJECT (dbin,						\
371 		    "expose unlocking from thread %p",			\
372 		    g_thread_self ());					\
373     g_mutex_unlock (&GST_DECODE_BIN_CAST(dbin)->expose_lock);		\
374 } G_STMT_END
375 
376 #define DYN_LOCK(dbin) G_STMT_START {			\
377     GST_LOG_OBJECT (dbin,						\
378 		    "dynlocking from thread %p",			\
379 		    g_thread_self ());					\
380     g_mutex_lock (&GST_DECODE_BIN_CAST(dbin)->dyn_lock);			\
381     GST_LOG_OBJECT (dbin,						\
382 		    "dynlocked from thread %p",				\
383 		    g_thread_self ());					\
384 } G_STMT_END
385 
386 #define DYN_UNLOCK(dbin) G_STMT_START {			\
387     GST_LOG_OBJECT (dbin,						\
388 		    "dynunlocking from thread %p",			\
389 		    g_thread_self ());					\
390     g_mutex_unlock (&GST_DECODE_BIN_CAST(dbin)->dyn_lock);		\
391 } G_STMT_END
392 
393 #define SUBTITLE_LOCK(dbin) G_STMT_START {				\
394     GST_LOG_OBJECT (dbin,						\
395 		    "subtitle locking from thread %p",			\
396 		    g_thread_self ());					\
397     g_mutex_lock (&GST_DECODE_BIN_CAST(dbin)->subtitle_lock);		\
398     GST_LOG_OBJECT (dbin,						\
399 		    "subtitle lock from thread %p",			\
400 		    g_thread_self ());					\
401 } G_STMT_END
402 
403 #define SUBTITLE_UNLOCK(dbin) G_STMT_START {				\
404     GST_LOG_OBJECT (dbin,						\
405 		    "subtitle unlocking from thread %p",		\
406 		    g_thread_self ());					\
407     g_mutex_unlock (&GST_DECODE_BIN_CAST(dbin)->subtitle_lock);		\
408 } G_STMT_END
409 
410 #define BUFFERING_LOCK(dbin) G_STMT_START {				\
411     GST_LOG_OBJECT (dbin,						\
412 		    "buffering locking from thread %p",			\
413 		    g_thread_self ());					\
414     g_mutex_lock (&GST_DECODE_BIN_CAST(dbin)->buffering_lock);		\
415     GST_LOG_OBJECT (dbin,						\
416 		    "buffering lock from thread %p",			\
417 		    g_thread_self ());					\
418 } G_STMT_END
419 
420 #define BUFFERING_UNLOCK(dbin) G_STMT_START {				\
421     GST_LOG_OBJECT (dbin,						\
422 		    "buffering unlocking from thread %p",		\
423 		    g_thread_self ());					\
424     g_mutex_unlock (&GST_DECODE_BIN_CAST(dbin)->buffering_lock);		\
425 } G_STMT_END
426 
427 #ifdef OHOS_EXT_FUNC
428 // ohos.ext.func.0028
429 #define GET_ELEMENT_FAC(ele) gst_element_get_factory (ele)
430 
431 #define GET_ELEMENT_DEMUX(ele) \
432   gst_plugin_feature_get_name (GST_PLUGIN_FEATURE_CAST (GET_ELEMENT_FAC (ele)))
433 
434 #define IS_ADAPTIVE_DEMUX(ele) \
435   ((GET_ELEMENT_DEMUX (ele)) && (!strcasecmp ((GET_ELEMENT_DEMUX (ele)), "hlsdemux")))
436 #endif
437 
438 struct _GstPendingPad
439 {
440   GstPad *pad;
441   GstDecodeChain *chain;
442   gulong event_probe_id;
443   gulong notify_caps_id;
444 };
445 
446 struct _GstDecodeElement
447 {
448   GstElement *element;
449   GstElement *capsfilter;       /* Optional capsfilter for Parser/Convert */
450   gulong pad_added_id;
451   gulong pad_removed_id;
452   gulong no_more_pads_id;
453 };
454 
455 struct _GstDemuxerPad
456 {
457   GWeakRef weakPad;
458   gulong event_probe_id;
459   gulong query_probe_id;
460 };
461 
462 
463 /* GstDecodeGroup
464  *
465  * Streams belonging to the same group/chain of a media file
466  *
467  * When changing something here lock the parent chain!
468  */
469 struct _GstDecodeGroup
470 {
471   GstDecodeBin *dbin;
472   GstDecodeChain *parent;
473 
474   GstElement *multiqueue;       /* Used for linking all child chains */
475   gulong overrunsig;            /* the overrun signal for multiqueue */
476 
477   gboolean overrun;             /* TRUE if the multiqueue signaled overrun. This
478                                  * means that we should really expose the group */
479 
480   gboolean no_more_pads;        /* TRUE if the demuxer signaled no-more-pads */
481   gboolean drained;             /* TRUE if the all children are drained */
482 
483   GList *children;              /* List of GstDecodeChains in this group */
484   GList *demuxer_pad_probe_ids;
485 
486   GList *reqpads;               /* List of RequestPads for multiqueue, there is
487                                  * exactly one RequestPad per child chain */
488 };
489 
490 struct _GstDecodeChain
491 {
492   GstDecodeGroup *parent;
493   GstDecodeBin *dbin;
494 
495   gint refs;                    /* Number of references to this object */
496 
497   GMutex lock;                  /* Protects this chain and its groups */
498 
499   GstPad *pad;                  /* srcpad that caused creation of this chain */
500   gulong pad_probe_id;          /* id for the demuxer_source_pad_probe probe */
501 
502   gboolean drained;             /* TRUE if the all children are drained */
503   gboolean demuxer;             /* TRUE if elements->data is a demuxer */
504   gboolean adaptive_demuxer;    /* TRUE if elements->data is an adaptive streaming demuxer */
505   gboolean seekable;            /* TRUE if this chain ends on a demuxer and is seekable */
506   GList *elements;              /* All elements in this group, first
507                                    is the latest and most downstream element */
508 
509   /* Note: there are only groups if the last element of this chain
510    * is a demuxer, otherwise the chain will end with an endpad.
511    * The other way around this means, that endpad only exists if this
512    * chain doesn't end with a demuxer! */
513 
514   GstDecodeGroup *active_group; /* Currently active group */
515   GList *next_groups;           /* head is newest group, tail is next group.
516                                    a new group will be created only if the head
517                                    group had no-more-pads. If it's only exposed
518                                    all new pads will be ignored! */
519   GList *pending_pads;          /* Pads that have no fixed caps yet */
520 
521   GstDecodePad *current_pad;    /* Current ending pad of the chain that can't
522                                  * be exposed yet but would be the same as endpad
523                                  * once it can be exposed */
524   GstDecodePad *endpad;         /* Pad of this chain that could be exposed */
525   gboolean deadend;             /* This chain is incomplete and can't be completed,
526                                    e.g. no suitable decoder could be found
527                                    e.g. stream got EOS without buffers
528                                  */
529   gchar *deadend_details;
530   GstCaps *endcaps;             /* Caps that were used when linking to the endpad
531                                    or that resulted in the deadend
532                                  */
533 
534   /* FIXME: This should be done directly via a thread! */
535   GList *old_groups;            /* Groups that should be freed later */
536 };
537 
538 static GstDecodeChain *gst_decode_chain_ref (GstDecodeChain * chain);
539 static void gst_decode_chain_unref (GstDecodeChain * chain);
540 static void gst_decode_chain_free (GstDecodeChain * chain);
541 static GstDecodeChain *gst_decode_chain_new (GstDecodeBin * dbin,
542     GstDecodeGroup * group, GstPad * pad);
543 static void gst_decode_group_hide (GstDecodeGroup * group);
544 static void gst_decode_group_free (GstDecodeGroup * group);
545 static GstDecodeGroup *gst_decode_group_new (GstDecodeBin * dbin,
546     GstDecodeChain * chain);
547 static gboolean gst_decode_chain_is_complete (GstDecodeChain * chain);
548 static gboolean gst_decode_chain_expose (GstDecodeChain * chain,
549     GList ** endpads, gboolean * missing_plugin,
550     GString * missing_plugin_details, gboolean * last_group);
551 static gboolean gst_decode_chain_is_drained (GstDecodeChain * chain);
552 static gboolean gst_decode_chain_reset_buffering (GstDecodeChain * chain);
553 static gboolean gst_decode_group_is_complete (GstDecodeGroup * group);
554 static GstPad *gst_decode_group_control_demuxer_pad (GstDecodeGroup * group,
555     GstPad * pad);
556 static gboolean gst_decode_group_is_drained (GstDecodeGroup * group);
557 static gboolean gst_decode_group_reset_buffering (GstDecodeGroup * group);
558 
559 static gboolean gst_decode_bin_expose (GstDecodeBin * dbin);
560 static void gst_decode_bin_reset_buffering (GstDecodeBin * dbin);
561 
562 #define CHAIN_MUTEX_LOCK(chain) G_STMT_START {				\
563     GST_LOG_OBJECT (chain->dbin,					\
564 		    "locking chain %p from thread %p",			\
565 		    chain, g_thread_self ());				\
566     g_mutex_lock (&chain->lock);						\
567     GST_LOG_OBJECT (chain->dbin,					\
568 		    "locked chain %p from thread %p",			\
569 		    chain, g_thread_self ());				\
570 } G_STMT_END
571 
572 #define CHAIN_MUTEX_UNLOCK(chain) G_STMT_START {                        \
573     GST_LOG_OBJECT (chain->dbin,					\
574 		    "unlocking chain %p from thread %p",		\
575 		    chain, g_thread_self ());				\
576     g_mutex_unlock (&chain->lock);					\
577 } G_STMT_END
578 
579 /* GstDecodePad
580  *
581  * GstPad private used for source pads of chains
582  */
583 struct _GstDecodePad
584 {
585   GstGhostPad parent;
586   GstDecodeBin *dbin;
587   GstDecodeChain *chain;
588 
589   gboolean blocked;             /* the *target* pad is blocked */
590   gboolean exposed;             /* the pad is exposed */
591   gboolean drained;             /* an EOS has been seen on the pad */
592 
593   gulong block_id;
594 };
595 
596 GType gst_decode_pad_get_type (void);
597 G_DEFINE_TYPE (GstDecodePad, gst_decode_pad, GST_TYPE_GHOST_PAD);
598 #define GST_TYPE_DECODE_PAD (gst_decode_pad_get_type ())
599 #define GST_DECODE_PAD(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_DECODE_PAD,GstDecodePad))
600 
601 static GstDecodePad *gst_decode_pad_new (GstDecodeBin * dbin,
602     GstDecodeChain * chain);
603 static void gst_decode_pad_activate (GstDecodePad * dpad,
604     GstDecodeChain * chain);
605 static void gst_decode_pad_unblock (GstDecodePad * dpad);
606 static void gst_decode_pad_set_blocked (GstDecodePad * dpad, gboolean blocked);
607 static gboolean gst_decode_pad_query (GstPad * pad, GstObject * parent,
608     GstQuery * query);
609 static gboolean gst_decode_pad_is_exposable (GstDecodePad * endpad);
610 
611 static void gst_pending_pad_free (GstPendingPad * ppad);
612 static GstPadProbeReturn pad_event_cb (GstPad * pad, GstPadProbeInfo * info,
613     gpointer data);
614 
615 /********************************
616  * Standard GObject boilerplate *
617  ********************************/
618 
619 static void gst_decode_bin_dispose (GObject * object);
620 static void gst_decode_bin_finalize (GObject * object);
621 
622 /* Register some quarks here for the stream topology message */
623 static GQuark topology_structure_name = 0;
624 static GQuark topology_caps = 0;
625 static GQuark topology_next = 0;
626 static GQuark topology_pad = 0;
627 static GQuark topology_element_srcpad = 0;
628 
629 GType gst_decode_bin_get_type (void);
630 G_DEFINE_TYPE (GstDecodeBin, gst_decode_bin, GST_TYPE_BIN);
631 #define _do_init \
632     GST_DEBUG_CATEGORY_INIT (gst_decode_bin_debug, "decodebin", 0, "decoder bin");\
633     topology_structure_name = g_quark_from_static_string ("stream-topology"); \
634     topology_caps = g_quark_from_static_string ("caps");\
635     topology_next = g_quark_from_static_string ("next");\
636     topology_pad = g_quark_from_static_string ("pad");\
637     topology_element_srcpad = g_quark_from_static_string ("element-srcpad");\
638     playback_element_init (plugin);\
639 
640 GST_ELEMENT_REGISTER_DEFINE_WITH_CODE (decodebin, "decodebin", GST_RANK_NONE,
641     GST_TYPE_DECODE_BIN, _do_init);
642 
643 static gboolean
_gst_boolean_accumulator(GSignalInvocationHint * ihint,GValue * return_accu,const GValue * handler_return,gpointer dummy)644 _gst_boolean_accumulator (GSignalInvocationHint * ihint,
645     GValue * return_accu, const GValue * handler_return, gpointer dummy)
646 {
647   gboolean myboolean;
648 
649   myboolean = g_value_get_boolean (handler_return);
650   g_value_set_boolean (return_accu, myboolean);
651 
652   /* stop emission if FALSE */
653   return myboolean;
654 }
655 
656 static gboolean
_gst_boolean_or_accumulator(GSignalInvocationHint * ihint,GValue * return_accu,const GValue * handler_return,gpointer dummy)657 _gst_boolean_or_accumulator (GSignalInvocationHint * ihint,
658     GValue * return_accu, const GValue * handler_return, gpointer dummy)
659 {
660   gboolean myboolean;
661   gboolean retboolean;
662 
663   myboolean = g_value_get_boolean (handler_return);
664   retboolean = g_value_get_boolean (return_accu);
665 
666   g_value_set_boolean (return_accu, myboolean || retboolean);
667 
668   return TRUE;
669 }
670 
671 /* we collect the first result */
672 static gboolean
_gst_array_accumulator(GSignalInvocationHint * ihint,GValue * return_accu,const GValue * handler_return,gpointer dummy)673 _gst_array_accumulator (GSignalInvocationHint * ihint,
674     GValue * return_accu, const GValue * handler_return, gpointer dummy)
675 {
676   gpointer array;
677 
678   array = g_value_get_boxed (handler_return);
679   g_value_set_boxed (return_accu, array);
680 
681   return FALSE;
682 }
683 
684 static gboolean
_gst_select_accumulator(GSignalInvocationHint * ihint,GValue * return_accu,const GValue * handler_return,gpointer dummy)685 _gst_select_accumulator (GSignalInvocationHint * ihint,
686     GValue * return_accu, const GValue * handler_return, gpointer dummy)
687 {
688   GstAutoplugSelectResult res;
689 
690   res = g_value_get_enum (handler_return);
691   g_value_set_enum (return_accu, res);
692 
693   /* Call the next handler in the chain (if any) when the current callback
694    * returns TRY. This makes it possible to register separate autoplug-select
695    * handlers that implement different TRY/EXPOSE/SKIP strategies.
696    */
697   if (res == GST_AUTOPLUG_SELECT_TRY)
698     return TRUE;
699 
700   return FALSE;
701 }
702 
703 static gboolean
_gst_array_hasvalue_accumulator(GSignalInvocationHint * ihint,GValue * return_accu,const GValue * handler_return,gpointer dummy)704 _gst_array_hasvalue_accumulator (GSignalInvocationHint * ihint,
705     GValue * return_accu, const GValue * handler_return, gpointer dummy)
706 {
707   gpointer array;
708 
709   array = g_value_get_boxed (handler_return);
710   g_value_set_boxed (return_accu, array);
711 
712   if (array != NULL)
713     return FALSE;
714 
715   return TRUE;
716 }
717 
718 static void
gst_decode_bin_class_init(GstDecodeBinClass * klass)719 gst_decode_bin_class_init (GstDecodeBinClass * klass)
720 {
721   GObjectClass *gobject_klass;
722   GstElementClass *gstelement_klass;
723   GstBinClass *gstbin_klass;
724 
725   gobject_klass = (GObjectClass *) klass;
726   gstelement_klass = (GstElementClass *) klass;
727   gstbin_klass = (GstBinClass *) klass;
728 
729   parent_class = g_type_class_peek_parent (klass);
730 
731   gobject_klass->dispose = gst_decode_bin_dispose;
732   gobject_klass->finalize = gst_decode_bin_finalize;
733   gobject_klass->set_property = gst_decode_bin_set_property;
734   gobject_klass->get_property = gst_decode_bin_get_property;
735 
736   /**
737    * GstDecodeBin::unknown-type:
738    * @bin: The decodebin.
739    * @pad: The new pad containing caps that cannot be resolved to a 'final'
740    *       stream type.
741    * @caps: The #GstCaps of the pad that cannot be resolved.
742    *
743    * This signal is emitted when a pad for which there is no further possible
744    * decoding is added to the decodebin.
745    */
746   gst_decode_bin_signals[SIGNAL_UNKNOWN_TYPE] =
747       g_signal_new ("unknown-type", G_TYPE_FROM_CLASS (klass),
748       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstDecodeBinClass, unknown_type),
749       NULL, NULL, NULL, G_TYPE_NONE, 2, GST_TYPE_PAD, GST_TYPE_CAPS);
750 
751   /**
752    * GstDecodeBin::autoplug-continue:
753    * @bin: The decodebin.
754    * @pad: The #GstPad.
755    * @caps: The #GstCaps found.
756    *
757    * This signal is emitted whenever decodebin finds a new stream. It is
758    * emitted before looking for any elements that can handle that stream.
759    *
760    * >   Invocation of signal handlers stops after the first signal handler
761    * >   returns %FALSE. Signal handlers are invoked in the order they were
762    * >   connected in.
763    *
764    * Returns: %TRUE if you wish decodebin to look for elements that can
765    * handle the given @caps. If %FALSE, those caps will be considered as
766    * final and the pad will be exposed as such (see 'pad-added' signal of
767    * #GstElement).
768    */
769   gst_decode_bin_signals[SIGNAL_AUTOPLUG_CONTINUE] =
770       g_signal_new ("autoplug-continue", G_TYPE_FROM_CLASS (klass),
771       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstDecodeBinClass, autoplug_continue),
772       _gst_boolean_accumulator, NULL, NULL, G_TYPE_BOOLEAN, 2, GST_TYPE_PAD,
773       GST_TYPE_CAPS);
774 
775   /**
776    * GstDecodeBin::autoplug-factories:
777    * @bin: The decodebin.
778    * @pad: The #GstPad.
779    * @caps: The #GstCaps found.
780    *
781    * This signal is emitted when an array of possible factories for @caps on
782    * @pad is needed. Decodebin will by default return an array with all
783    * compatible factories, sorted by rank.
784    *
785    * If this function returns NULL, @pad will be exposed as a final caps.
786    *
787    * If this function returns an empty array, the pad will be considered as
788    * having an unhandled type media type.
789    *
790    * >   Only the signal handler that is connected first will ever by invoked.
791    * >   Don't connect signal handlers with the #G_CONNECT_AFTER flag to this
792    * >   signal, they will never be invoked!
793    *
794    * Returns: a #GValueArray* with a list of factories to try. The factories are
795    * by default tried in the returned order or based on the index returned by
796    * "autoplug-select".
797    */
798   gst_decode_bin_signals[SIGNAL_AUTOPLUG_FACTORIES] =
799       g_signal_new ("autoplug-factories", G_TYPE_FROM_CLASS (klass),
800       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstDecodeBinClass,
801           autoplug_factories), _gst_array_accumulator, NULL,
802       NULL, G_TYPE_VALUE_ARRAY, 2, GST_TYPE_PAD, GST_TYPE_CAPS);
803 
804   /**
805    * GstDecodeBin::autoplug-sort:
806    * @bin: The decodebin.
807    * @pad: The #GstPad.
808    * @caps: The #GstCaps.
809    * @factories: A #GValueArray of possible #GstElementFactory to use.
810    *
811    * Once decodebin has found the possible #GstElementFactory objects to try
812    * for @caps on @pad, this signal is emitted. The purpose of the signal is for
813    * the application to perform additional sorting or filtering on the element
814    * factory array.
815    *
816    * The callee should copy and modify @factories or return %NULL if the
817    * order should not change.
818    *
819    * >   Invocation of signal handlers stops after one signal handler has
820    * >   returned something else than %NULL. Signal handlers are invoked in
821    * >   the order they were connected in.
822    * >   Don't connect signal handlers with the #G_CONNECT_AFTER flag to this
823    * >   signal, they will never be invoked!
824    *
825    * Returns: A new sorted array of #GstElementFactory objects.
826    */
827   gst_decode_bin_signals[SIGNAL_AUTOPLUG_SORT] =
828       g_signal_new ("autoplug-sort", G_TYPE_FROM_CLASS (klass),
829       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstDecodeBinClass, autoplug_sort),
830       _gst_array_hasvalue_accumulator, NULL,
831       NULL, G_TYPE_VALUE_ARRAY, 3, GST_TYPE_PAD, GST_TYPE_CAPS,
832       G_TYPE_VALUE_ARRAY | G_SIGNAL_TYPE_STATIC_SCOPE);
833 
834   /**
835    * GstDecodeBin::autoplug-select:
836    * @bin: The decodebin.
837    * @pad: The #GstPad.
838    * @caps: The #GstCaps.
839    * @factory: A #GstElementFactory to use.
840    *
841    * This signal is emitted once decodebin has found all the possible
842    * #GstElementFactory that can be used to handle the given @caps. For each of
843    * those factories, this signal is emitted.
844    *
845    * The signal handler should return a #GstAutoplugSelectResult enum
846    * value indicating what decodebin should do next.
847    *
848    * A value of #GstAutoplugSelectResult::try will try to autoplug an element from
849    * @factory.
850    *
851    * A value of #GstAutoplugSelectResult::expose will expose @pad without plugging
852    * any element to it.
853    *
854    * A value of #GstAutoplugSelectResult::skip will skip @factory and move to the
855    * next factory.
856    *
857    * >   The signal handler will not be invoked if any of the previously
858    * >   registered signal handlers (if any) return a value other than
859    * >   GST_AUTOPLUG_SELECT_TRY. Which also means that if you return
860    * >   GST_AUTOPLUG_SELECT_TRY from one signal handler, handlers that get
861    * >   registered next (again, if any) can override that decision.
862    *
863    * Returns: a #GstAutoplugSelectResult that indicates the required
864    * operation. the default handler will always return
865    * #GstAutoplugSelectResult::try.
866    */
867   gst_decode_bin_signals[SIGNAL_AUTOPLUG_SELECT] =
868       g_signal_new ("autoplug-select", G_TYPE_FROM_CLASS (klass),
869       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstDecodeBinClass, autoplug_select),
870       _gst_select_accumulator, NULL,
871       NULL, GST_TYPE_AUTOPLUG_SELECT_RESULT, 3, GST_TYPE_PAD, GST_TYPE_CAPS,
872       GST_TYPE_ELEMENT_FACTORY);
873 
874   /**
875    * GstDecodeBin::autoplug-query:
876    * @bin: The decodebin.
877    * @pad: The #GstPad.
878    * @child: The child element doing the query
879    * @query: The #GstQuery.
880    *
881    * This signal is emitted whenever an autoplugged element that is
882    * not linked downstream yet and not exposed does a query. It can
883    * be used to tell the element about the downstream supported caps
884    * for example.
885    *
886    * Returns: %TRUE if the query was handled, %FALSE otherwise.
887    */
888   gst_decode_bin_signals[SIGNAL_AUTOPLUG_QUERY] =
889       g_signal_new ("autoplug-query", G_TYPE_FROM_CLASS (klass),
890       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstDecodeBinClass, autoplug_query),
891       _gst_boolean_or_accumulator, NULL, NULL, G_TYPE_BOOLEAN, 3, GST_TYPE_PAD,
892       GST_TYPE_ELEMENT, GST_TYPE_QUERY | G_SIGNAL_TYPE_STATIC_SCOPE);
893 
894   /**
895    * GstDecodeBin::drained
896    * @bin: The decodebin
897    *
898    * This signal is emitted once decodebin has finished decoding all the data.
899    */
900   gst_decode_bin_signals[SIGNAL_DRAINED] =
901       g_signal_new ("drained", G_TYPE_FROM_CLASS (klass),
902       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstDecodeBinClass, drained),
903       NULL, NULL, NULL, G_TYPE_NONE, 0, G_TYPE_NONE);
904 
905 #ifdef OHOS_EXT_FUNC
906   // ohos.ext.func.0028
907   gst_decode_bin_signals[SIGNAL_BITRATE_PARSE_COMPLETE] =
908         g_signal_new("bitrate-parse-complete",
909             G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST,
910             0, NULL, NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 2, G_TYPE_POINTER, G_TYPE_UINT);
911 #endif
912 
913   g_object_class_install_property (gobject_klass, PROP_CAPS,
914       g_param_spec_boxed ("caps", "Caps", "The caps on which to stop decoding.",
915           GST_TYPE_CAPS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
916 
917   g_object_class_install_property (gobject_klass, PROP_SUBTITLE_ENCODING,
918       g_param_spec_string ("subtitle-encoding", "subtitle encoding",
919           "Encoding to assume if input subtitles are not in UTF-8 encoding. "
920           "If not set, the GST_SUBTITLE_ENCODING environment variable will "
921           "be checked for an encoding to use. If that is not set either, "
922           "ISO-8859-15 will be assumed.", NULL,
923           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
924 
925   g_object_class_install_property (gobject_klass, PROP_SINK_CAPS,
926       g_param_spec_boxed ("sink-caps", "Sink Caps",
927           "The caps of the input data. (NULL = use typefind element)",
928           GST_TYPE_CAPS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
929 
930   /**
931    * GstDecodeBin::use-buffering
932    *
933    * Activate buffering in decodebin. This will instruct the multiqueues behind
934    * decoders to emit BUFFERING messages.
935    */
936   g_object_class_install_property (gobject_klass, PROP_USE_BUFFERING,
937       g_param_spec_boolean ("use-buffering", "Use Buffering",
938           "Emit GST_MESSAGE_BUFFERING based on low-/high-percent thresholds",
939           DEFAULT_USE_BUFFERING, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
940 
941   /**
942    * GstDecodeBin::force-sw-decoders:
943    *
944    * While auto-plugging, if set to %TRUE, those decoders within
945    * "Hardware" klass will be ignored. Otherwise they will be tried.
946    *
947    * Since: 1.18
948    */
949   g_object_class_install_property (gobject_klass, PROP_FORCE_SW_DECODERS,
950       g_param_spec_boolean ("force-sw-decoders", "Software Docoders Only",
951           "Use only sofware decoders to process streams",
952           DEFAULT_FORCE_SW_DECODERS,
953           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
954 
955   /**
956    * GstDecodeBin:low-percent
957    *
958    * Low threshold percent for buffering to start.
959    */
960   g_object_class_install_property (gobject_klass, PROP_LOW_PERCENT,
961       g_param_spec_int ("low-percent", "Low percent",
962           "Low threshold for buffering to start", 0, 100,
963           DEFAULT_LOW_PERCENT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
964   /**
965    * GstDecodeBin:high-percent
966    *
967    * High threshold percent for buffering to finish.
968    */
969   g_object_class_install_property (gobject_klass, PROP_HIGH_PERCENT,
970       g_param_spec_int ("high-percent", "High percent",
971           "High threshold for buffering to finish", 0, 100,
972           DEFAULT_HIGH_PERCENT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
973 
974   /**
975    * GstDecodeBin:max-size-bytes
976    *
977    * Max amount of bytes in the queue (0=automatic).
978    */
979   g_object_class_install_property (gobject_klass, PROP_MAX_SIZE_BYTES,
980       g_param_spec_uint ("max-size-bytes", "Max. size (bytes)",
981           "Max. amount of bytes in the queue (0=automatic)",
982           0, G_MAXUINT, DEFAULT_MAX_SIZE_BYTES,
983           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
984   /**
985    * GstDecodeBin:max-size-buffers
986    *
987    * Max amount of buffers in the queue (0=automatic).
988    */
989   g_object_class_install_property (gobject_klass, PROP_MAX_SIZE_BUFFERS,
990       g_param_spec_uint ("max-size-buffers", "Max. size (buffers)",
991           "Max. number of buffers in the queue (0=automatic)",
992           0, G_MAXUINT, DEFAULT_MAX_SIZE_BUFFERS,
993           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
994   /**
995    * GstDecodeBin:max-size-time
996    *
997    * Max amount of time in the queue (in ns, 0=automatic).
998    */
999   g_object_class_install_property (gobject_klass, PROP_MAX_SIZE_TIME,
1000       g_param_spec_uint64 ("max-size-time", "Max. size (ns)",
1001           "Max. amount of data in the queue (in ns, 0=automatic)",
1002           0, G_MAXUINT64,
1003           DEFAULT_MAX_SIZE_TIME, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
1004 
1005   /**
1006    * GstDecodeBin::post-stream-topology
1007    *
1008    * Post stream-topology messages on the bus every time the topology changes.
1009    */
1010   g_object_class_install_property (gobject_klass, PROP_POST_STREAM_TOPOLOGY,
1011       g_param_spec_boolean ("post-stream-topology", "Post Stream Topology",
1012           "Post stream-topology messages",
1013           DEFAULT_POST_STREAM_TOPOLOGY,
1014           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
1015 
1016   /**
1017    * GstDecodeBin::expose-all-streams
1018    *
1019    * Expose streams of unknown type.
1020    *
1021    * If set to %FALSE, then only the streams that can be decoded to the final
1022    * caps (see 'caps' property) will have a pad exposed. Streams that do not
1023    * match those caps but could have been decoded will not have decoder plugged
1024    * in internally and will not have a pad exposed.
1025    */
1026   g_object_class_install_property (gobject_klass, PROP_EXPOSE_ALL_STREAMS,
1027       g_param_spec_boolean ("expose-all-streams", "Expose All Streams",
1028           "Expose all streams, including those of unknown type or that don't match the 'caps' property",
1029           DEFAULT_EXPOSE_ALL_STREAMS,
1030           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
1031 
1032   /**
1033    * GstDecodeBin2::connection-speed
1034    *
1035    * Network connection speed in kbps (0 = unknownw)
1036    */
1037   g_object_class_install_property (gobject_klass, PROP_CONNECTION_SPEED,
1038       g_param_spec_uint64 ("connection-speed", "Connection Speed",
1039           "Network connection speed in kbps (0 = unknown)",
1040           0, G_MAXUINT64 / 1000, DEFAULT_CONNECTION_SPEED,
1041           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
1042 
1043 #ifdef OHOS_EXT_FUNC
1044   // ohos.ext.func.0012
1045   g_object_class_install_property (gobject_klass, PROP_MQ_NUM_USE_BUFFRING,
1046       g_param_spec_uint ("mq-num-use-buffering", "Mq num use buffering",
1047           "multiqueue number of use buffering", 0, 100,
1048           0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
1049 
1050   g_object_class_install_property (gobject_klass, PROP_TIMEOUT,
1051       g_param_spec_uint ("timeout", "timeout",
1052           "Value in seconds to timeout a blocking I/O (0 = No timeout).", 0,
1053           3600, DEFAULT_TIMEOUT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
1054 
1055   g_object_class_install_property (gobject_klass, PROP_STATE_CHANGE,
1056     g_param_spec_int ("state-change", "state-change from adaptive-demux",
1057         "state-change from adaptive-demux", 0, (gint) (G_MAXINT32), 0,
1058         G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
1059 
1060   g_object_class_install_property (gobject_klass, PROP_EXIT_BLOCK,
1061       g_param_spec_int ("exit-block", "EXIT BLOCK",
1062           "souphttpsrc exit block", 0, (gint) (G_MAXINT32), 0,
1063           G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS));
1064 #endif
1065 
1066   klass->autoplug_continue =
1067       GST_DEBUG_FUNCPTR (gst_decode_bin_autoplug_continue);
1068   klass->autoplug_factories =
1069       GST_DEBUG_FUNCPTR (gst_decode_bin_autoplug_factories);
1070   klass->autoplug_sort = GST_DEBUG_FUNCPTR (gst_decode_bin_autoplug_sort);
1071   klass->autoplug_select = GST_DEBUG_FUNCPTR (gst_decode_bin_autoplug_select);
1072   klass->autoplug_query = GST_DEBUG_FUNCPTR (gst_decode_bin_autoplug_query);
1073 
1074   gst_element_class_add_static_pad_template (gstelement_klass,
1075       &decoder_bin_sink_template);
1076   gst_element_class_add_static_pad_template (gstelement_klass,
1077       &decoder_bin_src_template);
1078 
1079   gst_element_class_set_static_metadata (gstelement_klass,
1080       "Decoder Bin", "Generic/Bin/Decoder",
1081       "Autoplug and decode to raw media",
1082       "Edward Hervey <edward.hervey@collabora.co.uk>, "
1083       "Sebastian Dröge <sebastian.droege@collabora.co.uk>");
1084 
1085   gstelement_klass->change_state =
1086       GST_DEBUG_FUNCPTR (gst_decode_bin_change_state);
1087 
1088   gstbin_klass->handle_message =
1089       GST_DEBUG_FUNCPTR (gst_decode_bin_handle_message);
1090 
1091   gstbin_klass->remove_element =
1092       GST_DEBUG_FUNCPTR (gst_decode_bin_remove_element);
1093 
1094   g_type_class_ref (GST_TYPE_DECODE_PAD);
1095 
1096   gst_type_mark_as_plugin_api (GST_TYPE_AUTOPLUG_SELECT_RESULT, 0);
1097 }
1098 
1099 /* Must be called with factories lock! */
1100 static void
gst_decode_bin_update_factories_list(GstDecodeBin * dbin)1101 gst_decode_bin_update_factories_list (GstDecodeBin * dbin)
1102 {
1103   guint cookie;
1104   GList *factories, *tmp;
1105 
1106   cookie = gst_registry_get_feature_list_cookie (gst_registry_get ());
1107   if (!dbin->factories || dbin->factories_cookie != cookie) {
1108     if (dbin->factories)
1109       gst_plugin_feature_list_free (dbin->factories);
1110     factories =
1111         gst_element_factory_list_get_elements
1112         (GST_ELEMENT_FACTORY_TYPE_DECODABLE, GST_RANK_MARGINAL);
1113 
1114     if (dbin->force_sw_decoders) {
1115       /* filter out Hardware class elements */
1116       dbin->factories = NULL;
1117       for (tmp = factories; tmp; tmp = g_list_next (tmp)) {
1118         GstElementFactory *factory = GST_ELEMENT_FACTORY_CAST (tmp->data);
1119         if (!gst_element_factory_list_is_type (factory,
1120                 GST_ELEMENT_FACTORY_TYPE_HARDWARE)) {
1121           dbin->factories = g_list_prepend (dbin->factories, factory);
1122         } else {
1123           gst_object_unref (factory);
1124         }
1125       }
1126       g_list_free (factories);
1127     } else {
1128       dbin->factories = factories;
1129     }
1130 
1131     dbin->factories =
1132         g_list_sort (dbin->factories,
1133         gst_playback_utils_compare_factories_func);
1134     dbin->factories_cookie = cookie;
1135   }
1136 }
1137 
1138 static void
gst_decode_bin_init(GstDecodeBin * decode_bin)1139 gst_decode_bin_init (GstDecodeBin * decode_bin)
1140 {
1141   /* first filter out the interesting element factories */
1142   g_mutex_init (&decode_bin->factories_lock);
1143 
1144   /* we create the typefind element only once */
1145   decode_bin->typefind = gst_element_factory_make ("typefind", "typefind");
1146   if (!decode_bin->typefind) {
1147     g_warning ("can't find typefind element, decodebin will not work");
1148   } else {
1149     GstPad *pad;
1150     GstPad *gpad;
1151     GstPadTemplate *pad_tmpl;
1152 
1153     /* add the typefind element */
1154     if (!gst_bin_add (GST_BIN (decode_bin), decode_bin->typefind)) {
1155       g_warning ("Could not add typefind element, decodebin will not work");
1156       gst_object_unref (decode_bin->typefind);
1157       decode_bin->typefind = NULL;
1158     }
1159 
1160     /* get the sinkpad */
1161     pad = gst_element_get_static_pad (decode_bin->typefind, "sink");
1162 
1163     /* get the pad template */
1164     pad_tmpl = gst_static_pad_template_get (&decoder_bin_sink_template);
1165 
1166     /* ghost the sink pad to ourself */
1167     gpad = gst_ghost_pad_new_from_template ("sink", pad, pad_tmpl);
1168     gst_pad_set_active (gpad, TRUE);
1169     gst_element_add_pad (GST_ELEMENT (decode_bin), gpad);
1170 
1171     gst_object_unref (pad_tmpl);
1172     gst_object_unref (pad);
1173   }
1174 
1175   g_mutex_init (&decode_bin->expose_lock);
1176   decode_bin->decode_chain = NULL;
1177 
1178   g_mutex_init (&decode_bin->dyn_lock);
1179   decode_bin->shutdown = FALSE;
1180   decode_bin->blocked_pads = NULL;
1181 
1182   g_mutex_init (&decode_bin->subtitle_lock);
1183   g_mutex_init (&decode_bin->buffering_lock);
1184   g_mutex_init (&decode_bin->buffering_post_lock);
1185 
1186   g_mutex_init (&decode_bin->cleanup_lock);
1187   decode_bin->cleanup_thread = NULL;
1188 
1189   decode_bin->encoding = g_strdup (DEFAULT_SUBTITLE_ENCODING);
1190   decode_bin->caps = gst_static_caps_get (&default_raw_caps);
1191   decode_bin->use_buffering = DEFAULT_USE_BUFFERING;
1192   decode_bin->force_sw_decoders = DEFAULT_FORCE_SW_DECODERS;
1193   decode_bin->low_percent = DEFAULT_LOW_PERCENT;
1194   decode_bin->high_percent = DEFAULT_HIGH_PERCENT;
1195 
1196   decode_bin->max_size_bytes = DEFAULT_MAX_SIZE_BYTES;
1197   decode_bin->max_size_buffers = DEFAULT_MAX_SIZE_BUFFERS;
1198   decode_bin->max_size_time = DEFAULT_MAX_SIZE_TIME;
1199 
1200   decode_bin->expose_allstreams = DEFAULT_EXPOSE_ALL_STREAMS;
1201   decode_bin->connection_speed = DEFAULT_CONNECTION_SPEED;
1202 #ifdef OHOS_EXT_FUNC
1203   // ohos.ext.func.0013
1204   decode_bin->mq_num_use_buffering = 0;
1205 #endif
1206 }
1207 
1208 static void
gst_decode_bin_dispose(GObject * object)1209 gst_decode_bin_dispose (GObject * object)
1210 {
1211   GstDecodeBin *decode_bin;
1212 
1213   decode_bin = GST_DECODE_BIN (object);
1214 
1215   if (decode_bin->factories)
1216     gst_plugin_feature_list_free (decode_bin->factories);
1217   decode_bin->factories = NULL;
1218 
1219   if (decode_bin->decode_chain)
1220     gst_decode_chain_free (decode_bin->decode_chain);
1221   decode_bin->decode_chain = NULL;
1222 
1223   if (decode_bin->caps)
1224     gst_caps_unref (decode_bin->caps);
1225   decode_bin->caps = NULL;
1226 
1227   g_free (decode_bin->encoding);
1228   decode_bin->encoding = NULL;
1229 
1230   g_list_free (decode_bin->subtitles);
1231   decode_bin->subtitles = NULL;
1232 
1233   unblock_pads (decode_bin);
1234 
1235   G_OBJECT_CLASS (parent_class)->dispose (object);
1236 }
1237 
1238 static void
gst_decode_bin_finalize(GObject * object)1239 gst_decode_bin_finalize (GObject * object)
1240 {
1241   GstDecodeBin *decode_bin;
1242 
1243   decode_bin = GST_DECODE_BIN (object);
1244 
1245   g_mutex_clear (&decode_bin->expose_lock);
1246   g_mutex_clear (&decode_bin->dyn_lock);
1247   g_mutex_clear (&decode_bin->subtitle_lock);
1248   g_mutex_clear (&decode_bin->buffering_lock);
1249   g_mutex_clear (&decode_bin->buffering_post_lock);
1250   g_mutex_clear (&decode_bin->factories_lock);
1251   g_mutex_clear (&decode_bin->cleanup_lock);
1252 
1253   G_OBJECT_CLASS (parent_class)->finalize (object);
1254 }
1255 
1256 /* _set_caps
1257  * Changes the caps on which decodebin will stop decoding.
1258  * Will unref the previously set one. The refcount of the given caps will be
1259  * increased.
1260  * @caps can be NULL.
1261  *
1262  * MT-safe
1263  */
1264 static void
gst_decode_bin_set_caps(GstDecodeBin * dbin,GstCaps * caps)1265 gst_decode_bin_set_caps (GstDecodeBin * dbin, GstCaps * caps)
1266 {
1267   GST_DEBUG_OBJECT (dbin, "Setting new caps: %" GST_PTR_FORMAT, caps);
1268 
1269   GST_OBJECT_LOCK (dbin);
1270   gst_caps_replace (&dbin->caps, caps);
1271   GST_OBJECT_UNLOCK (dbin);
1272 }
1273 
1274 /* _get_caps
1275  * Returns the currently configured caps on which decodebin will stop decoding.
1276  * The returned caps (if not NULL), will have its refcount incremented.
1277  *
1278  * MT-safe
1279  */
1280 static GstCaps *
gst_decode_bin_get_caps(GstDecodeBin * dbin)1281 gst_decode_bin_get_caps (GstDecodeBin * dbin)
1282 {
1283   GstCaps *caps;
1284 
1285   GST_DEBUG_OBJECT (dbin, "Getting currently set caps");
1286 
1287   GST_OBJECT_LOCK (dbin);
1288   caps = dbin->caps;
1289   if (caps)
1290     gst_caps_ref (caps);
1291   GST_OBJECT_UNLOCK (dbin);
1292 
1293   return caps;
1294 }
1295 
1296 static void
gst_decode_bin_set_sink_caps(GstDecodeBin * dbin,GstCaps * caps)1297 gst_decode_bin_set_sink_caps (GstDecodeBin * dbin, GstCaps * caps)
1298 {
1299   GST_DEBUG_OBJECT (dbin, "Setting new caps: %" GST_PTR_FORMAT, caps);
1300 
1301   g_object_set (dbin->typefind, "force-caps", caps, NULL);
1302 }
1303 
1304 static GstCaps *
gst_decode_bin_get_sink_caps(GstDecodeBin * dbin)1305 gst_decode_bin_get_sink_caps (GstDecodeBin * dbin)
1306 {
1307   GstCaps *caps;
1308 
1309   GST_DEBUG_OBJECT (dbin, "Getting currently set caps");
1310 
1311   g_object_get (dbin->typefind, "force-caps", &caps, NULL);
1312 
1313   return caps;
1314 }
1315 
1316 static void
gst_decode_bin_set_subs_encoding(GstDecodeBin * dbin,const gchar * encoding)1317 gst_decode_bin_set_subs_encoding (GstDecodeBin * dbin, const gchar * encoding)
1318 {
1319   GList *walk;
1320 
1321   GST_DEBUG_OBJECT (dbin, "Setting new encoding: %s", GST_STR_NULL (encoding));
1322 
1323   SUBTITLE_LOCK (dbin);
1324   g_free (dbin->encoding);
1325   dbin->encoding = g_strdup (encoding);
1326 
1327   /* set the subtitle encoding on all added elements */
1328   for (walk = dbin->subtitles; walk; walk = g_list_next (walk)) {
1329     g_object_set (G_OBJECT (walk->data), "subtitle-encoding", dbin->encoding,
1330         NULL);
1331   }
1332   SUBTITLE_UNLOCK (dbin);
1333 }
1334 
1335 static gchar *
gst_decode_bin_get_subs_encoding(GstDecodeBin * dbin)1336 gst_decode_bin_get_subs_encoding (GstDecodeBin * dbin)
1337 {
1338   gchar *encoding;
1339 
1340   GST_DEBUG_OBJECT (dbin, "Getting currently set encoding");
1341 
1342   SUBTITLE_LOCK (dbin);
1343   encoding = g_strdup (dbin->encoding);
1344   SUBTITLE_UNLOCK (dbin);
1345 
1346   return encoding;
1347 }
1348 
1349 #ifdef OHOS_EXT_FUNC
1350 // ohos.ext.func.0012
1351 static void
set_property_handle_to_element(GstDecodeBin * dbin,guint property_id,const void * property_value)1352 set_property_handle_to_element (GstDecodeBin *dbin, guint property_id, const void *property_value)
1353 {
1354   GList *walk = NULL;
1355   GstBin *bin = (GstBin *) dbin;
1356 
1357   for (walk = bin->children; walk != NULL; walk = g_list_next (walk)) {
1358     GObject *element = G_OBJECT (walk->data);
1359     if ((element == NULL) || !GST_IS_ELEMENT (element)) {
1360       continue;
1361     }
1362 
1363     GstElementFactory *fac = gst_element_get_factory ((GstElement *)element);
1364     if (fac == NULL) {
1365       continue;
1366     }
1367     gboolean is_demux = gst_element_factory_list_is_type (fac, GST_ELEMENT_FACTORY_TYPE_DEMUXER);
1368     if (!is_demux) {
1369       continue;
1370     }
1371     GObjectClass *theclass = g_type_class_peek (gst_element_factory_get_element_type (fac));
1372     if (property_id == PROP_TIMEOUT) {
1373       const guint *timeout = (const guint *) property_value;
1374       if ((theclass != NULL) && g_object_class_find_property (theclass, "timeout")) {
1375         g_object_set (element, "timeout", *timeout, NULL);
1376       }
1377     } else if (property_id == PROP_STATE_CHANGE) {
1378       const gint *state = (const gint *) property_value;
1379       if ((theclass != NULL) && g_object_class_find_property (theclass, "state-change")) {
1380         g_object_set (element, "state-change", *state, NULL);
1381       }
1382     } else if (property_id == PROP_EXIT_BLOCK) {
1383       const gint *exit_block = (const gint *) property_value;
1384       if ((theclass != NULL) && g_object_class_find_property (theclass, "exit-block")) {
1385         g_object_set (element, "exit-block", *exit_block, NULL);
1386       }
1387     } else if (property_id == PROP_CONNECTION_SPEED) {
1388       const guint64 *con_speed = (const guint64 *) property_value;
1389       if ((theclass != NULL) && g_object_class_find_property (theclass, "connection-speed")) {
1390         g_object_set (element, "connection-speed", *con_speed, NULL);
1391       }
1392     }
1393   }
1394   return;
1395 }
1396 #endif
1397 
1398 static void
gst_decode_bin_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)1399 gst_decode_bin_set_property (GObject * object, guint prop_id,
1400     const GValue * value, GParamSpec * pspec)
1401 {
1402   GstDecodeBin *dbin;
1403 
1404   dbin = GST_DECODE_BIN (object);
1405 
1406   switch (prop_id) {
1407     case PROP_CAPS:
1408       gst_decode_bin_set_caps (dbin, g_value_get_boxed (value));
1409       break;
1410     case PROP_SUBTITLE_ENCODING:
1411       gst_decode_bin_set_subs_encoding (dbin, g_value_get_string (value));
1412       break;
1413     case PROP_SINK_CAPS:
1414       gst_decode_bin_set_sink_caps (dbin, g_value_get_boxed (value));
1415       break;
1416     case PROP_USE_BUFFERING:
1417       dbin->use_buffering = g_value_get_boolean (value);
1418       break;
1419     case PROP_FORCE_SW_DECODERS:
1420       dbin->force_sw_decoders = g_value_get_boolean (value);
1421       break;
1422     case PROP_LOW_PERCENT:
1423       dbin->low_percent = g_value_get_int (value);
1424       break;
1425     case PROP_HIGH_PERCENT:
1426       dbin->high_percent = g_value_get_int (value);
1427       break;
1428     case PROP_MAX_SIZE_BYTES:
1429       dbin->max_size_bytes = g_value_get_uint (value);
1430       break;
1431     case PROP_MAX_SIZE_BUFFERS:
1432       dbin->max_size_buffers = g_value_get_uint (value);
1433       break;
1434     case PROP_MAX_SIZE_TIME:
1435       dbin->max_size_time = g_value_get_uint64 (value);
1436       break;
1437     case PROP_POST_STREAM_TOPOLOGY:
1438       dbin->post_stream_topology = g_value_get_boolean (value);
1439       break;
1440     case PROP_EXPOSE_ALL_STREAMS:
1441       dbin->expose_allstreams = g_value_get_boolean (value);
1442       break;
1443     case PROP_CONNECTION_SPEED:
1444       GST_OBJECT_LOCK (dbin);
1445       dbin->connection_speed = g_value_get_uint64 (value) * 1000;
1446       GST_OBJECT_UNLOCK (dbin);
1447 #ifdef OHOS_EXT_FUNC
1448     // ohos.ext.func.0028
1449       guint64 con_speed = g_value_get_uint64 (value);
1450       set_property_handle_to_element (dbin, prop_id, (void *)&con_speed);
1451 #endif
1452       break;
1453 #ifdef OHOS_EXT_FUNC
1454     // ohos.ext.func.0013
1455     case PROP_TIMEOUT: {
1456       guint timeout = g_value_get_uint (value);
1457       set_property_handle_to_element (dbin, prop_id, (void *)&timeout);
1458       break;
1459     }
1460     case PROP_STATE_CHANGE: {
1461       gint state = g_value_get_int (value);
1462       set_property_handle_to_element (dbin, prop_id, (void *)&state);
1463       break;
1464     }
1465     case PROP_EXIT_BLOCK: {
1466       gint exit_block = g_value_get_int (value);
1467       set_property_handle_to_element (dbin, prop_id, (void *)&exit_block);
1468       break;
1469     }
1470 #endif
1471     default:
1472       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1473       break;
1474   }
1475 }
1476 
1477 static void
gst_decode_bin_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)1478 gst_decode_bin_get_property (GObject * object, guint prop_id,
1479     GValue * value, GParamSpec * pspec)
1480 {
1481   GstDecodeBin *dbin;
1482 
1483   dbin = GST_DECODE_BIN (object);
1484   switch (prop_id) {
1485     case PROP_CAPS:
1486       g_value_take_boxed (value, gst_decode_bin_get_caps (dbin));
1487       break;
1488     case PROP_SUBTITLE_ENCODING:
1489       g_value_take_string (value, gst_decode_bin_get_subs_encoding (dbin));
1490       break;
1491     case PROP_SINK_CAPS:
1492       g_value_take_boxed (value, gst_decode_bin_get_sink_caps (dbin));
1493       break;
1494     case PROP_USE_BUFFERING:
1495       g_value_set_boolean (value, dbin->use_buffering);
1496       break;
1497     case PROP_FORCE_SW_DECODERS:
1498       g_value_set_boolean (value, dbin->force_sw_decoders);
1499       break;
1500     case PROP_LOW_PERCENT:
1501       g_value_set_int (value, dbin->low_percent);
1502       break;
1503     case PROP_HIGH_PERCENT:
1504       g_value_set_int (value, dbin->high_percent);
1505       break;
1506     case PROP_MAX_SIZE_BYTES:
1507       g_value_set_uint (value, dbin->max_size_bytes);
1508       break;
1509     case PROP_MAX_SIZE_BUFFERS:
1510       g_value_set_uint (value, dbin->max_size_buffers);
1511       break;
1512     case PROP_MAX_SIZE_TIME:
1513       g_value_set_uint64 (value, dbin->max_size_time);
1514       break;
1515     case PROP_POST_STREAM_TOPOLOGY:
1516       g_value_set_boolean (value, dbin->post_stream_topology);
1517       break;
1518     case PROP_EXPOSE_ALL_STREAMS:
1519       g_value_set_boolean (value, dbin->expose_allstreams);
1520       break;
1521     case PROP_CONNECTION_SPEED:
1522       GST_OBJECT_LOCK (dbin);
1523       g_value_set_uint64 (value, dbin->connection_speed / 1000);
1524       GST_OBJECT_UNLOCK (dbin);
1525       break;
1526 #ifdef OHOS_EXT_FUNC
1527     // ohos.ext.func.0013
1528     case PROP_MQ_NUM_USE_BUFFRING:
1529       if (dbin->decode_chain) {
1530         CHAIN_MUTEX_LOCK (dbin->decode_chain);
1531         g_value_set_uint64 (value, dbin->mq_num_use_buffering);
1532         CHAIN_MUTEX_UNLOCK (dbin->decode_chain);
1533       }
1534       break;
1535 #endif
1536     default:
1537       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1538       break;
1539   }
1540 }
1541 
1542 
1543 /*****
1544  * Default autoplug signal handlers
1545  *****/
1546 static gboolean
gst_decode_bin_autoplug_continue(GstElement * element,GstPad * pad,GstCaps * caps)1547 gst_decode_bin_autoplug_continue (GstElement * element, GstPad * pad,
1548     GstCaps * caps)
1549 {
1550   GST_DEBUG_OBJECT (element, "autoplug-continue returns TRUE");
1551 
1552   /* by default we always continue */
1553   return TRUE;
1554 }
1555 
1556 static GValueArray *
gst_decode_bin_autoplug_factories(GstElement * element,GstPad * pad,GstCaps * caps)1557 gst_decode_bin_autoplug_factories (GstElement * element, GstPad * pad,
1558     GstCaps * caps)
1559 {
1560   GList *list, *tmp;
1561   GValueArray *result;
1562   GstDecodeBin *dbin = GST_DECODE_BIN_CAST (element);
1563 
1564   GST_DEBUG_OBJECT (element, "finding factories");
1565 
1566   /* return all compatible factories for caps */
1567   g_mutex_lock (&dbin->factories_lock);
1568   gst_decode_bin_update_factories_list (dbin);
1569   list =
1570       gst_element_factory_list_filter (dbin->factories, caps, GST_PAD_SINK,
1571       gst_caps_is_fixed (caps));
1572   g_mutex_unlock (&dbin->factories_lock);
1573 
1574   result = g_value_array_new (g_list_length (list));
1575   for (tmp = list; tmp; tmp = tmp->next) {
1576     GstElementFactory *factory = GST_ELEMENT_FACTORY_CAST (tmp->data);
1577     GValue val = { 0, };
1578 
1579     g_value_init (&val, G_TYPE_OBJECT);
1580     g_value_set_object (&val, factory);
1581     g_value_array_append (result, &val);
1582     g_value_unset (&val);
1583   }
1584   gst_plugin_feature_list_free (list);
1585 
1586   GST_DEBUG_OBJECT (element, "autoplug-factories returns %p", result);
1587 
1588   return result;
1589 }
1590 
1591 static GValueArray *
gst_decode_bin_autoplug_sort(GstElement * element,GstPad * pad,GstCaps * caps,GValueArray * factories)1592 gst_decode_bin_autoplug_sort (GstElement * element, GstPad * pad,
1593     GstCaps * caps, GValueArray * factories)
1594 {
1595   return NULL;
1596 }
1597 
1598 static GstAutoplugSelectResult
gst_decode_bin_autoplug_select(GstElement * element,GstPad * pad,GstCaps * caps,GstElementFactory * factory)1599 gst_decode_bin_autoplug_select (GstElement * element, GstPad * pad,
1600     GstCaps * caps, GstElementFactory * factory)
1601 {
1602   GST_DEBUG_OBJECT (element, "default autoplug-select returns TRY");
1603 
1604   /* Try factory. */
1605   return GST_AUTOPLUG_SELECT_TRY;
1606 }
1607 
1608 static gboolean
gst_decode_bin_autoplug_query(GstElement * element,GstPad * pad,GstQuery * query)1609 gst_decode_bin_autoplug_query (GstElement * element, GstPad * pad,
1610     GstQuery * query)
1611 {
1612   /* No query handled here */
1613   return FALSE;
1614 }
1615 
1616 /********
1617  * Discovery methods
1618  *****/
1619 
1620 static gboolean are_final_caps (GstDecodeBin * dbin, GstCaps * caps);
1621 static gboolean is_demuxer_element (GstElement * srcelement);
1622 static gboolean is_adaptive_demuxer_element (GstElement * srcelement);
1623 
1624 static gboolean connect_pad (GstDecodeBin * dbin, GstElement * src,
1625     GstDecodePad * dpad, GstPad * pad, GstCaps * caps, GValueArray * factories,
1626     GstDecodeChain * chain, gchar ** deadend_details);
1627 static GList *connect_element (GstDecodeBin * dbin, GstDecodeElement * delem,
1628     GstDecodeChain * chain);
1629 static void expose_pad (GstDecodeBin * dbin, GstElement * src,
1630     GstDecodePad * dpad, GstPad * pad, GstCaps * caps, GstDecodeChain * chain);
1631 
1632 static void pad_added_cb (GstElement * element, GstPad * pad,
1633     GstDecodeChain * chain);
1634 static void pad_removed_cb (GstElement * element, GstPad * pad,
1635     GstDecodeChain * chain);
1636 static void no_more_pads_cb (GstElement * element, GstDecodeChain * chain);
1637 
1638 static GstDecodeGroup *gst_decode_chain_get_current_group (GstDecodeChain *
1639     chain);
1640 
1641 static gboolean
clear_sticky_events(GstPad * pad,GstEvent ** event,gpointer user_data)1642 clear_sticky_events (GstPad * pad, GstEvent ** event, gpointer user_data)
1643 {
1644   GST_DEBUG_OBJECT (pad, "clearing sticky event %" GST_PTR_FORMAT, *event);
1645   gst_event_unref (*event);
1646   *event = NULL;
1647   return TRUE;
1648 }
1649 
1650 static gboolean
copy_sticky_events(GstPad * pad,GstEvent ** event,gpointer user_data)1651 copy_sticky_events (GstPad * pad, GstEvent ** event, gpointer user_data)
1652 {
1653   GstPad *gpad = GST_PAD_CAST (user_data);
1654 
1655   GST_DEBUG_OBJECT (gpad, "store sticky event %" GST_PTR_FORMAT, *event);
1656   gst_pad_store_sticky_event (gpad, *event);
1657 
1658   return TRUE;
1659 }
1660 
1661 static void
decode_pad_set_target(GstDecodePad * dpad,GstPad * target)1662 decode_pad_set_target (GstDecodePad * dpad, GstPad * target)
1663 {
1664   gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (dpad), target);
1665   if (target == NULL)
1666     gst_pad_sticky_events_foreach (GST_PAD_CAST (dpad), clear_sticky_events,
1667         NULL);
1668   else
1669     gst_pad_sticky_events_foreach (target, copy_sticky_events, dpad);
1670 }
1671 
1672 /* called when a new pad is discovered. It will perform some basic actions
1673  * before trying to link something to it.
1674  *
1675  *  - Check the caps, don't do anything when there are no caps or when they have
1676  *    no good type.
1677  *  - signal AUTOPLUG_CONTINUE to check if we need to continue autoplugging this
1678  *    pad.
1679  *  - if the caps are non-fixed, setup a handler to continue autoplugging when
1680  *    the caps become fixed (connect to notify::caps).
1681  *  - get list of factories to autoplug.
1682  *  - continue autoplugging to one of the factories.
1683  */
1684 /* returns whether to expose the pad */
1685 static gboolean
analyze_new_pad(GstDecodeBin * dbin,GstElement * src,GstPad * pad,GstCaps * caps,GstDecodeChain * chain,GstDecodeChain ** new_chain)1686 analyze_new_pad (GstDecodeBin * dbin, GstElement * src, GstPad * pad,
1687     GstCaps * caps, GstDecodeChain * chain, GstDecodeChain ** new_chain)
1688 {
1689   gboolean apcontinue = TRUE;
1690   GValueArray *factories = NULL, *result = NULL;
1691   GstDecodePad *dpad;
1692   GstElementFactory *factory;
1693   const gchar *classification;
1694   gboolean is_parser_converter = FALSE;
1695   gboolean res;
1696   gchar *deadend_details = NULL;
1697 
1698   GST_DEBUG_OBJECT (dbin, "Pad %s:%s caps:%" GST_PTR_FORMAT,
1699       GST_DEBUG_PAD_NAME (pad), caps);
1700 
1701   if (new_chain)
1702     *new_chain = chain;
1703 
1704   if (chain->elements
1705       && src != ((GstDecodeElement *) chain->elements->data)->element
1706       && src != ((GstDecodeElement *) chain->elements->data)->capsfilter) {
1707     GST_ERROR_OBJECT (dbin, "New pad from not the last element in this chain");
1708     return FALSE;
1709   }
1710 
1711   if (chain->endpad) {
1712     GST_ERROR_OBJECT (dbin, "New pad in a chain that is already complete");
1713     return FALSE;
1714   }
1715 
1716   if (chain->demuxer) {
1717     GstDecodeGroup *group;
1718     GstDecodeChain *oldchain = chain;
1719     GstDecodeElement *demux = (chain->elements ? chain->elements->data : NULL);
1720 
1721     if (chain->current_pad)
1722       gst_object_unref (chain->current_pad);
1723     chain->current_pad = NULL;
1724 
1725     /* we are adding a new pad for a demuxer (see is_demuxer_element(),
1726      * start a new chain for it */
1727     CHAIN_MUTEX_LOCK (oldchain);
1728     group = gst_decode_chain_get_current_group (chain);
1729     if (group && !g_list_find (group->children, chain)) {
1730       g_assert (new_chain != NULL);
1731       *new_chain = chain = gst_decode_chain_new (dbin, group, pad);
1732       group->children = g_list_prepend (group->children, chain);
1733     }
1734     CHAIN_MUTEX_UNLOCK (oldchain);
1735     if (!group) {
1736       GST_WARNING_OBJECT (dbin, "No current group");
1737       return FALSE;
1738     }
1739 
1740     /* If this is not a dynamic pad demuxer, we're no-more-pads
1741      * already before anything else happens
1742      */
1743     if (demux == NULL || !demux->no_more_pads_id)
1744       group->no_more_pads = TRUE;
1745   }
1746 
1747   /* From here on we own a reference to the caps as
1748    * we might create new caps below and would need
1749    * to unref them later */
1750   if (caps)
1751     gst_caps_ref (caps);
1752 
1753   if ((caps == NULL) || gst_caps_is_empty (caps))
1754     goto unknown_type;
1755 
1756   if (gst_caps_is_any (caps))
1757     goto any_caps;
1758 
1759   if (!chain->current_pad)
1760     chain->current_pad = gst_decode_pad_new (dbin, chain);
1761 
1762   dpad = gst_object_ref (chain->current_pad);
1763   gst_pad_set_active (GST_PAD_CAST (dpad), TRUE);
1764   decode_pad_set_target (dpad, pad);
1765 
1766   /* 1. Emit 'autoplug-continue' the result will tell us if this pads needs
1767    * further autoplugging. Only do this for fixed caps, for unfixed caps
1768    * we will later come here again from the notify::caps handler. The
1769    * problem with unfixed caps is that, we can't reliably tell if the output
1770    * is e.g. accepted by a sink because only parts of the possible final
1771    * caps might be accepted by the sink. */
1772   if (gst_caps_is_fixed (caps))
1773     g_signal_emit (G_OBJECT (dbin),
1774         gst_decode_bin_signals[SIGNAL_AUTOPLUG_CONTINUE], 0, dpad, caps,
1775         &apcontinue);
1776   else
1777     apcontinue = TRUE;
1778 
1779   /* 1.a if autoplug-continue is FALSE or caps is a raw format, goto pad_is_final */
1780   if ((!apcontinue) || are_final_caps (dbin, caps))
1781     goto expose_pad;
1782 
1783   /* 1.b For Parser/Converter that can output different stream formats
1784    * we insert a capsfilter with the sorted caps of all possible next
1785    * elements and continue with the capsfilter srcpad */
1786   factory = gst_element_get_factory (src);
1787   classification =
1788       gst_element_factory_get_metadata (factory, GST_ELEMENT_METADATA_KLASS);
1789   is_parser_converter = (strstr (classification, "Parser")
1790       && strstr (classification, "Converter"));
1791 
1792   /* 1.c when the caps are not fixed yet, we can't be sure what element to
1793    * connect. We delay autoplugging until the caps are fixed */
1794   if (!is_parser_converter && !gst_caps_is_fixed (caps)) {
1795     goto non_fixed;
1796   } else if (!is_parser_converter) {
1797     gst_caps_unref (caps);
1798     caps = gst_pad_get_current_caps (pad);
1799     if (!caps) {
1800       GST_DEBUG_OBJECT (dbin, "No final caps set yet, delaying autoplugging");
1801       gst_object_unref (dpad);
1802       goto setup_caps_delay;
1803     }
1804   }
1805 
1806   /* 1.d else get the factories and if there's no compatible factory goto
1807    * unknown_type */
1808   g_signal_emit (G_OBJECT (dbin),
1809       gst_decode_bin_signals[SIGNAL_AUTOPLUG_FACTORIES], 0, dpad, caps,
1810       &factories);
1811 
1812   /* NULL means that we can expose the pad */
1813   if (factories == NULL)
1814     goto expose_pad;
1815 
1816   /* if the array is empty, we have a type for which we have no decoder */
1817   if (factories->n_values == 0) {
1818     if (!dbin->expose_allstreams) {
1819       GstCaps *raw = gst_static_caps_get (&default_raw_caps);
1820 
1821       /* If the caps are raw, this just means we don't want to expose them */
1822       if (gst_caps_is_subset (caps, raw)) {
1823         g_value_array_free (factories);
1824         gst_caps_unref (raw);
1825         gst_object_unref (dpad);
1826         goto discarded_type;
1827       }
1828       gst_caps_unref (raw);
1829     }
1830 
1831     /* if not we have a unhandled type with no compatible factories */
1832     g_value_array_free (factories);
1833     gst_object_unref (dpad);
1834     goto unknown_type;
1835   }
1836 
1837   /* 1.e sort some more. */
1838   g_signal_emit (G_OBJECT (dbin),
1839       gst_decode_bin_signals[SIGNAL_AUTOPLUG_SORT], 0, dpad, caps, factories,
1840       &result);
1841   if (result) {
1842     g_value_array_free (factories);
1843     factories = result;
1844   }
1845 
1846   /* At this point we have a potential decoder, but we might not need it
1847    * if it doesn't match the output caps  */
1848   if (!dbin->expose_allstreams && gst_caps_is_fixed (caps)) {
1849     guint i;
1850     const GList *tmps;
1851     gboolean dontuse = FALSE;
1852 
1853     GST_DEBUG ("Checking if we can abort early");
1854 
1855     /* 1.f Do an early check to see if the candidates are potential decoders, but
1856      * due to the fact that they decode to a mediatype that is not final we don't
1857      * need them */
1858 
1859     for (i = 0; i < factories->n_values && !dontuse; i++) {
1860       GstElementFactory *factory =
1861           g_value_get_object (g_value_array_get_nth (factories, i));
1862       GstCaps *tcaps;
1863 
1864       /* We are only interested in skipping decoders */
1865       if (strstr (gst_element_factory_get_metadata (factory,
1866                   GST_ELEMENT_METADATA_KLASS), "Decoder")) {
1867 
1868         GST_DEBUG ("Trying factory %s",
1869             gst_plugin_feature_get_name (GST_PLUGIN_FEATURE (factory)));
1870 
1871         /* Check the source pad template caps to see if they match raw caps but don't match
1872          * our final caps*/
1873         for (tmps = gst_element_factory_get_static_pad_templates (factory);
1874             tmps && !dontuse; tmps = tmps->next) {
1875           GstStaticPadTemplate *st = (GstStaticPadTemplate *) tmps->data;
1876           if (st->direction != GST_PAD_SRC)
1877             continue;
1878           tcaps = gst_static_pad_template_get_caps (st);
1879 
1880           apcontinue = TRUE;
1881 
1882           /* Emit autoplug-continue to see if the caps are considered to be raw caps */
1883           g_signal_emit (G_OBJECT (dbin),
1884               gst_decode_bin_signals[SIGNAL_AUTOPLUG_CONTINUE], 0, dpad, tcaps,
1885               &apcontinue);
1886 
1887           /* If autoplug-continue returns TRUE and the caps are not final, don't use them */
1888           if (apcontinue && !are_final_caps (dbin, tcaps))
1889             dontuse = TRUE;
1890           gst_caps_unref (tcaps);
1891         }
1892       }
1893     }
1894 
1895     if (dontuse) {
1896       gst_object_unref (dpad);
1897       g_value_array_free (factories);
1898       goto discarded_type;
1899     }
1900   }
1901 
1902   /* 1.g now get the factory template caps and insert the capsfilter if this
1903    * is a parser/converter
1904    */
1905   if (is_parser_converter) {
1906     GstCaps *filter_caps;
1907     gint i;
1908     GstElement *capsfilter;
1909     GstPad *p;
1910     GstDecodeElement *delem;
1911 
1912     filter_caps = gst_caps_new_empty ();
1913     for (i = 0; i < factories->n_values; i++) {
1914       GstElementFactory *factory =
1915           g_value_get_object (g_value_array_get_nth (factories, i));
1916       GstCaps *tcaps, *intersection;
1917       const GList *tmps;
1918 
1919       GST_DEBUG ("Trying factory %s",
1920           gst_plugin_feature_get_name (GST_PLUGIN_FEATURE (factory)));
1921 
1922       if (gst_element_get_factory (src) == factory ||
1923           gst_element_factory_list_is_type (factory,
1924               GST_ELEMENT_FACTORY_TYPE_PARSER)) {
1925         GST_DEBUG ("Skipping factory");
1926         continue;
1927       }
1928 
1929       for (tmps = gst_element_factory_get_static_pad_templates (factory); tmps;
1930           tmps = tmps->next) {
1931         GstStaticPadTemplate *st = (GstStaticPadTemplate *) tmps->data;
1932         if (st->direction != GST_PAD_SINK || st->presence != GST_PAD_ALWAYS)
1933           continue;
1934         tcaps = gst_static_pad_template_get_caps (st);
1935         intersection =
1936             gst_caps_intersect_full (tcaps, caps, GST_CAPS_INTERSECT_FIRST);
1937         filter_caps = gst_caps_merge (filter_caps, intersection);
1938         gst_caps_unref (tcaps);
1939       }
1940     }
1941 
1942     /* Append the parser caps to prevent any not-negotiated errors */
1943     filter_caps = gst_caps_merge (filter_caps, gst_caps_ref (caps));
1944 
1945     if (chain->elements) {
1946       delem = (GstDecodeElement *) chain->elements->data;
1947       capsfilter = delem->capsfilter =
1948           gst_element_factory_make ("capsfilter", NULL);
1949     } else {
1950       delem = g_slice_new0 (GstDecodeElement);
1951       capsfilter = delem->element =
1952           gst_element_factory_make ("capsfilter", NULL);
1953       delem->capsfilter = NULL;
1954       chain->elements = g_list_prepend (chain->elements, delem);
1955     }
1956 
1957     g_object_set (G_OBJECT (capsfilter), "caps", filter_caps, NULL);
1958     gst_caps_unref (filter_caps);
1959     gst_element_set_state (capsfilter, GST_STATE_PAUSED);
1960     gst_bin_add (GST_BIN_CAST (dbin), gst_object_ref (capsfilter));
1961 
1962     decode_pad_set_target (dpad, NULL);
1963     p = gst_element_get_static_pad (capsfilter, "sink");
1964     gst_pad_link_full (pad, p, GST_PAD_LINK_CHECK_NOTHING);
1965     gst_object_unref (p);
1966     p = gst_element_get_static_pad (capsfilter, "src");
1967     decode_pad_set_target (dpad, p);
1968     pad = p;
1969 
1970     gst_caps_unref (caps);
1971 
1972     caps = gst_pad_get_current_caps (pad);
1973     if (!caps) {
1974       GST_DEBUG_OBJECT (dbin, "No final caps set yet, delaying autoplugging");
1975       gst_object_unref (dpad);
1976       g_value_array_free (factories);
1977       goto setup_caps_delay;
1978     }
1979   }
1980 
1981   /* 1.h else continue autoplugging something from the list. */
1982   GST_LOG_OBJECT (pad, "Let's continue discovery on this pad");
1983   res =
1984       connect_pad (dbin, src, dpad, pad, caps, factories, chain,
1985       &deadend_details);
1986 
1987   /* Need to unref the capsfilter srcpad here if
1988    * we inserted a capsfilter */
1989   if (is_parser_converter)
1990     gst_object_unref (pad);
1991 
1992   gst_object_unref (dpad);
1993   g_value_array_free (factories);
1994 
1995   if (!res)
1996     goto unknown_type;
1997 
1998   gst_caps_unref (caps);
1999 
2000   return FALSE;
2001 
2002 expose_pad:
2003   {
2004     GST_LOG_OBJECT (dbin, "Pad is final and should expose the pad. "
2005         "autoplug-continue:%d", apcontinue);
2006     gst_object_unref (dpad);
2007     gst_caps_unref (caps);
2008     return TRUE;
2009   }
2010 
2011 discarded_type:
2012   {
2013     GST_LOG_OBJECT (pad, "Known type, but discarded because not final caps");
2014     chain->deadend = TRUE;
2015     chain->endcaps = caps;
2016     gst_object_replace ((GstObject **) & chain->current_pad, NULL);
2017 
2018     /* Try to expose anything */
2019     EXPOSE_LOCK (dbin);
2020     if (dbin->decode_chain) {
2021       if (gst_decode_chain_is_complete (dbin->decode_chain)) {
2022         gst_decode_bin_expose (dbin);
2023       }
2024     }
2025     EXPOSE_UNLOCK (dbin);
2026     do_async_done (dbin);
2027 
2028     return FALSE;
2029   }
2030 
2031 unknown_type:
2032   {
2033     GST_LOG_OBJECT (pad, "Unknown type, posting message and firing signal");
2034 
2035     chain->deadend_details = deadend_details;
2036     chain->deadend = TRUE;
2037     chain->endcaps = caps;
2038     gst_object_replace ((GstObject **) & chain->current_pad, NULL);
2039 
2040     gst_element_post_message (GST_ELEMENT_CAST (dbin),
2041         gst_missing_decoder_message_new (GST_ELEMENT_CAST (dbin), caps));
2042 
2043     g_signal_emit (G_OBJECT (dbin),
2044         gst_decode_bin_signals[SIGNAL_UNKNOWN_TYPE], 0, pad, caps);
2045 
2046     /* Try to expose anything */
2047     EXPOSE_LOCK (dbin);
2048     if (dbin->decode_chain) {
2049       if (gst_decode_chain_is_complete (dbin->decode_chain)) {
2050         gst_decode_bin_expose (dbin);
2051       }
2052     }
2053     EXPOSE_UNLOCK (dbin);
2054 
2055     if (src == dbin->typefind) {
2056       if (!caps || gst_caps_is_empty (caps)) {
2057         GST_ELEMENT_ERROR (dbin, STREAM, TYPE_NOT_FOUND,
2058             (_("Could not determine type of stream")), (NULL));
2059       }
2060       do_async_done (dbin);
2061     }
2062     return FALSE;
2063   }
2064 non_fixed:
2065   {
2066     GST_DEBUG_OBJECT (pad, "pad has non-fixed caps delay autoplugging");
2067     gst_object_unref (dpad);
2068     goto setup_caps_delay;
2069   }
2070 any_caps:
2071   {
2072     GST_DEBUG_OBJECT (pad, "pad has ANY caps, delaying auto-pluggin");
2073     goto setup_caps_delay;
2074   }
2075 setup_caps_delay:
2076   {
2077     GstPendingPad *ppad;
2078 
2079     /* connect to caps notification */
2080     CHAIN_MUTEX_LOCK (chain);
2081     GST_LOG_OBJECT (dbin, "Chain %p has now %d dynamic pads", chain,
2082         g_list_length (chain->pending_pads));
2083     ppad = g_slice_new0 (GstPendingPad);
2084     ppad->pad = gst_object_ref (pad);
2085     ppad->chain = chain;
2086     ppad->event_probe_id =
2087         gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM,
2088         pad_event_cb, ppad, NULL);
2089     chain->pending_pads = g_list_prepend (chain->pending_pads, ppad);
2090     ppad->notify_caps_id = g_signal_connect (pad, "notify::caps",
2091         G_CALLBACK (caps_notify_cb), chain);
2092     CHAIN_MUTEX_UNLOCK (chain);
2093 
2094     /* If we're here because we have a Parser/Converter
2095      * we have to unref the pad */
2096     if (is_parser_converter)
2097       gst_object_unref (pad);
2098     if (caps)
2099       gst_caps_unref (caps);
2100 
2101     return FALSE;
2102   }
2103 }
2104 
2105 static void
add_error_filter(GstDecodeBin * dbin,GstElement * element)2106 add_error_filter (GstDecodeBin * dbin, GstElement * element)
2107 {
2108   GST_OBJECT_LOCK (dbin);
2109   dbin->filtered = g_list_prepend (dbin->filtered, element);
2110   GST_OBJECT_UNLOCK (dbin);
2111 }
2112 
2113 static void
remove_error_filter(GstDecodeBin * dbin,GstElement * element,GstMessage ** error)2114 remove_error_filter (GstDecodeBin * dbin, GstElement * element,
2115     GstMessage ** error)
2116 {
2117   GList *l;
2118 
2119   GST_OBJECT_LOCK (dbin);
2120   dbin->filtered = g_list_remove (dbin->filtered, element);
2121 
2122   if (error)
2123     *error = NULL;
2124 
2125   l = dbin->filtered_errors;
2126   while (l) {
2127     GstMessage *msg = l->data;
2128 
2129     if (GST_MESSAGE_SRC (msg) == GST_OBJECT_CAST (element)) {
2130       /* Get the last error of this element, i.e. the earliest */
2131       if (error)
2132         gst_message_replace (error, msg);
2133       gst_message_unref (msg);
2134       l = dbin->filtered_errors = g_list_delete_link (dbin->filtered_errors, l);
2135     } else {
2136       l = l->next;
2137     }
2138   }
2139   GST_OBJECT_UNLOCK (dbin);
2140 }
2141 
2142 typedef struct
2143 {
2144   gboolean ret;
2145   GstPad *peer;
2146 } SendStickyEventsData;
2147 
2148 static gboolean
send_sticky_event(GstPad * pad,GstEvent ** event,gpointer user_data)2149 send_sticky_event (GstPad * pad, GstEvent ** event, gpointer user_data)
2150 {
2151   SendStickyEventsData *data = user_data;
2152   gboolean ret;
2153 
2154   ret = gst_pad_send_event (data->peer, gst_event_ref (*event));
2155   if (!ret)
2156     data->ret = FALSE;
2157 
2158   return data->ret;
2159 }
2160 
2161 static gboolean
send_sticky_events(GstDecodeBin * dbin,GstPad * pad)2162 send_sticky_events (GstDecodeBin * dbin, GstPad * pad)
2163 {
2164   SendStickyEventsData data;
2165 
2166   data.ret = TRUE;
2167   data.peer = gst_pad_get_peer (pad);
2168 
2169   gst_pad_sticky_events_foreach (pad, send_sticky_event, &data);
2170 
2171   gst_object_unref (data.peer);
2172 
2173   return data.ret;
2174 }
2175 
2176 static gchar *
error_message_to_string(GstMessage * msg)2177 error_message_to_string (GstMessage * msg)
2178 {
2179   GError *err;
2180   gchar *debug, *message, *full_message;
2181 
2182   gst_message_parse_error (msg, &err, &debug);
2183 
2184   message = gst_error_get_message (err->domain, err->code);
2185 
2186   if (debug)
2187     full_message = g_strdup_printf ("%s\n%s\n%s", message, err->message, debug);
2188   else
2189     full_message = g_strdup_printf ("%s\n%s", message, err->message);
2190 
2191   g_free (message);
2192   g_free (debug);
2193   g_clear_error (&err);
2194 
2195   return full_message;
2196 }
2197 
2198 static GstPadProbeReturn
demuxer_source_pad_probe(GstPad * pad,GstPadProbeInfo * info,gpointer user_data)2199 demuxer_source_pad_probe (GstPad * pad, GstPadProbeInfo * info,
2200     gpointer user_data)
2201 {
2202   GstEvent *event = GST_PAD_PROBE_INFO_EVENT (info);
2203   GstDecodeGroup *group = (GstDecodeGroup *) user_data;
2204   GstDecodeChain *parent_chain = group->parent;
2205 
2206   GST_DEBUG_OBJECT (pad, "Saw event %s", GST_EVENT_TYPE_NAME (event));
2207   /* Check if we are the active group, if not we need to proxy the flush
2208    * events to the other groups (of which at least one is exposed, ensuring
2209    * flushing properly propagates downstream of decodebin */
2210   if (parent_chain->active_group == group)
2211     return GST_PAD_PROBE_OK;
2212 
2213   switch (GST_EVENT_TYPE (event)) {
2214     case GST_EVENT_FLUSH_START:
2215     case GST_EVENT_FLUSH_STOP:
2216     {
2217       GList *tmp;
2218       GST_DEBUG_OBJECT (pad, "Proxying flush events to inactive groups");
2219       /* Proxy to active group */
2220       for (tmp = parent_chain->active_group->reqpads; tmp; tmp = tmp->next) {
2221         GstPad *reqpad = (GstPad *) tmp->data;
2222         gst_pad_send_event (reqpad, gst_event_ref (event));
2223       }
2224       /* Proxy to other non-active groups (except ourself) */
2225       for (tmp = parent_chain->next_groups; tmp; tmp = tmp->next) {
2226         GList *tmp2;
2227         GstDecodeGroup *tmpgroup = (GstDecodeGroup *) tmp->data;
2228         if (tmpgroup != group) {
2229           for (tmp2 = tmpgroup->reqpads; tmp2; tmp2 = tmp2->next) {
2230             GstPad *reqpad = (GstPad *) tmp2->data;
2231             gst_pad_send_event (reqpad, gst_event_ref (event));
2232           }
2233         }
2234       }
2235       flush_chain (parent_chain,
2236           GST_EVENT_TYPE (event) == GST_EVENT_FLUSH_START);
2237     }
2238       break;
2239     default:
2240       break;
2241   }
2242 
2243   return GST_PAD_PROBE_OK;
2244 }
2245 
2246 typedef struct
2247 {
2248   GstDecodeChain *chain;
2249   GstPad *pad;
2250 } PadExposeData;
2251 
2252 #ifdef OHOS_EXT_FUNC
2253 // ohos.ext.func.0028
2254 static void
bitrate_parse_complete_cb(GstElement * element,gpointer input,guint num,GstDecodeChain * chain)2255 bitrate_parse_complete_cb (GstElement * element, gpointer input, guint num, GstDecodeChain * chain)
2256 {
2257   if ((element == NULL) || (chain == NULL) || (chain->dbin == NULL)) {
2258     return;
2259   }
2260 
2261   GstDecodeBin *dbin = chain->dbin;
2262   GST_INFO_OBJECT (dbin, "in manifest parse complete");
2263   g_signal_emit (dbin, gst_decode_bin_signals[SIGNAL_BITRATE_PARSE_COMPLETE], 0, input, num);
2264   GST_INFO_OBJECT (dbin, "out manifest parse complete");
2265 
2266 }
2267 #endif
2268 
2269 /* connect_pad:
2270  *
2271  * Try to connect the given pad to an element created from one of the factories,
2272  * and recursively.
2273  *
2274  * Note that dpad is ghosting pad, and so pad is linked; be sure to unset dpad's
2275  * target before trying to link pad.
2276  *
2277  * Returns TRUE if an element was properly created and linked
2278  */
2279 static gboolean
connect_pad(GstDecodeBin * dbin,GstElement * src,GstDecodePad * dpad,GstPad * pad,GstCaps * caps,GValueArray * factories,GstDecodeChain * chain,gchar ** deadend_details)2280 connect_pad (GstDecodeBin * dbin, GstElement * src, GstDecodePad * dpad,
2281     GstPad * pad, GstCaps * caps, GValueArray * factories,
2282     GstDecodeChain * chain, gchar ** deadend_details)
2283 {
2284   gboolean res = FALSE;
2285   GstPad *mqpad = NULL;
2286   gboolean is_demuxer = chain->parent && !chain->elements;      /* First pad after the demuxer */
2287   GString *error_details = NULL;
2288 
2289   g_return_val_if_fail (factories != NULL, FALSE);
2290   g_return_val_if_fail (factories->n_values > 0, FALSE);
2291 
2292   GST_DEBUG_OBJECT (dbin,
2293       "pad %s:%s , chain:%p, %d factories, caps %" GST_PTR_FORMAT,
2294       GST_DEBUG_PAD_NAME (pad), chain, factories->n_values, caps);
2295 
2296   /* 1. is element demuxer or parser */
2297   if (is_demuxer) {
2298     GST_LOG_OBJECT (src,
2299         "is a demuxer, connecting the pad through multiqueue '%s'",
2300         GST_OBJECT_NAME (chain->parent->multiqueue));
2301 
2302     /* Set a flush-start/-stop probe on the downstream events */
2303     chain->pad_probe_id =
2304         gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_EVENT_FLUSH,
2305         demuxer_source_pad_probe, chain->parent, NULL);
2306 
2307     decode_pad_set_target (dpad, NULL);
2308     if (!(mqpad = gst_decode_group_control_demuxer_pad (chain->parent, pad)))
2309       goto beach;
2310     src = chain->parent->multiqueue;
2311     /* Forward sticky events to mq src pad to allow factory initialization */
2312     gst_pad_sticky_events_foreach (pad, copy_sticky_events, mqpad);
2313     pad = mqpad;
2314     decode_pad_set_target (dpad, pad);
2315   }
2316 
2317   error_details = g_string_new ("");
2318 
2319   /* 2. Try to create an element and link to it */
2320   while (factories->n_values > 0) {
2321     GstAutoplugSelectResult ret;
2322     GstElementFactory *factory;
2323     GstDecodeElement *delem;
2324     GstElement *element;
2325     GstPad *sinkpad;
2326     GParamSpec *pspec;
2327     gboolean subtitle;
2328     GList *to_connect = NULL;
2329     GList *to_expose = NULL;
2330     gboolean is_parser = FALSE;
2331     gboolean is_decoder = FALSE;
2332 
2333     /* Set dpad target to pad again, it might've been unset
2334      * below but we came back here because something failed
2335      */
2336     decode_pad_set_target (dpad, pad);
2337 
2338     /* take first factory */
2339     factory = g_value_get_object (g_value_array_get_nth (factories, 0));
2340     /* Remove selected factory from the list. */
2341     g_value_array_remove (factories, 0);
2342 
2343     GST_LOG_OBJECT (src, "trying factory %" GST_PTR_FORMAT, factory);
2344 
2345     /* Check if the caps are really supported by the factory. The
2346      * factory list is non-empty-subset filtered while caps
2347      * are only accepted by a pad if they are a subset of the
2348      * pad caps.
2349      *
2350      * FIXME: Only do this for fixed caps here. Non-fixed caps
2351      * can happen if a Parser/Converter was autoplugged before
2352      * this. We then assume that it will be able to convert to
2353      * everything that the decoder would want.
2354      *
2355      * A subset check will fail here because the parser caps
2356      * will be generic and while the decoder will only
2357      * support a subset of the parser caps.
2358      */
2359     if (gst_caps_is_fixed (caps)) {
2360       const GList *templs;
2361       gboolean skip = FALSE;
2362 
2363       templs = gst_element_factory_get_static_pad_templates (factory);
2364 
2365       while (templs) {
2366         GstStaticPadTemplate *templ = (GstStaticPadTemplate *) templs->data;
2367 
2368         if (templ->direction == GST_PAD_SINK) {
2369           GstCaps *templcaps = gst_static_caps_get (&templ->static_caps);
2370 
2371           if (!gst_caps_is_subset (caps, templcaps)) {
2372             GST_DEBUG_OBJECT (src,
2373                 "caps %" GST_PTR_FORMAT " not subset of %" GST_PTR_FORMAT, caps,
2374                 templcaps);
2375             gst_caps_unref (templcaps);
2376             skip = TRUE;
2377             break;
2378           }
2379 
2380           gst_caps_unref (templcaps);
2381         }
2382         templs = g_list_next (templs);
2383       }
2384       if (skip)
2385         continue;
2386     }
2387 
2388     /* If the factory is for a parser we first check if the factory
2389      * was already used for the current chain. If it was used already
2390      * we would otherwise create an infinite loop here because the
2391      * parser apparently accepts its own output as input.
2392      * This is only done for parsers because it's perfectly valid
2393      * to have other element classes after each other because a
2394      * parser is the only one that does not change the data. A
2395      * valid example for this would be multiple id3demux in a row.
2396      */
2397     is_parser = strstr (gst_element_factory_get_metadata (factory,
2398             GST_ELEMENT_METADATA_KLASS), "Parser") != NULL;
2399 
2400     if (is_parser) {
2401       gboolean skip = FALSE;
2402       GList *l;
2403 
2404       CHAIN_MUTEX_LOCK (chain);
2405       for (l = chain->elements; l; l = l->next) {
2406         GstDecodeElement *delem = (GstDecodeElement *) l->data;
2407         GstElement *otherelement = delem->element;
2408 
2409         if (gst_element_get_factory (otherelement) == factory) {
2410           skip = TRUE;
2411           break;
2412         }
2413       }
2414 
2415       if (!skip && chain->parent && chain->parent->parent) {
2416         GstDecodeChain *parent_chain = chain->parent->parent;
2417         GstDecodeElement *pelem =
2418             parent_chain->elements ? parent_chain->elements->data : NULL;
2419 
2420         if (pelem && gst_element_get_factory (pelem->element) == factory)
2421           skip = TRUE;
2422       }
2423       CHAIN_MUTEX_UNLOCK (chain);
2424       if (skip) {
2425         GST_DEBUG_OBJECT (dbin,
2426             "Skipping factory '%s' because it was already used in this chain",
2427             gst_plugin_feature_get_name (GST_PLUGIN_FEATURE_CAST (factory)));
2428         continue;
2429       }
2430 
2431     }
2432 
2433     /* emit autoplug-select to see what we should do with it. */
2434     g_signal_emit (G_OBJECT (dbin),
2435         gst_decode_bin_signals[SIGNAL_AUTOPLUG_SELECT],
2436         0, dpad, caps, factory, &ret);
2437 
2438     switch (ret) {
2439       case GST_AUTOPLUG_SELECT_TRY:
2440         GST_DEBUG_OBJECT (dbin, "autoplug select requested try");
2441         break;
2442       case GST_AUTOPLUG_SELECT_EXPOSE:
2443         GST_DEBUG_OBJECT (dbin, "autoplug select requested expose");
2444         /* expose the pad, we don't have the source element */
2445         expose_pad (dbin, src, dpad, pad, caps, chain);
2446         res = TRUE;
2447         goto beach;
2448       case GST_AUTOPLUG_SELECT_SKIP:
2449         GST_DEBUG_OBJECT (dbin, "autoplug select requested skip");
2450         continue;
2451       default:
2452         GST_WARNING_OBJECT (dbin, "autoplug select returned unhandled %d", ret);
2453         break;
2454     }
2455 
2456     /* 2.0. Unlink pad */
2457     decode_pad_set_target (dpad, NULL);
2458 
2459     /* 2.1. Try to create an element */
2460     if ((element = gst_element_factory_create (factory, NULL)) == NULL) {
2461       GST_WARNING_OBJECT (dbin, "Could not create an element from %s",
2462           gst_plugin_feature_get_name (GST_PLUGIN_FEATURE (factory)));
2463       g_string_append_printf (error_details,
2464           "Could not create an element from %s\n",
2465           gst_plugin_feature_get_name (GST_PLUGIN_FEATURE (factory)));
2466       continue;
2467     }
2468 
2469     /* Filter errors, this will prevent the element from causing the pipeline
2470      * to error while we test it using READY state. */
2471     add_error_filter (dbin, element);
2472 
2473     /* We don't yet want the bin to control the element's state */
2474     gst_element_set_locked_state (element, TRUE);
2475 
2476     /* ... add it ... */
2477     if (!(gst_bin_add (GST_BIN_CAST (dbin), element))) {
2478       GST_WARNING_OBJECT (dbin, "Couldn't add %s to the bin",
2479           GST_ELEMENT_NAME (element));
2480       remove_error_filter (dbin, element, NULL);
2481       g_string_append_printf (error_details, "Couldn't add %s to the bin\n",
2482           GST_ELEMENT_NAME (element));
2483       gst_object_unref (element);
2484       continue;
2485     }
2486 
2487     /* Find its sink pad. */
2488     if (!(sinkpad = find_sink_pad (element))) {
2489       GST_WARNING_OBJECT (dbin, "Element %s doesn't have a sink pad",
2490           GST_ELEMENT_NAME (element));
2491       remove_error_filter (dbin, element, NULL);
2492       g_string_append_printf (error_details,
2493           "Element %s doesn't have a sink pad", GST_ELEMENT_NAME (element));
2494       gst_bin_remove (GST_BIN (dbin), element);
2495       continue;
2496     }
2497 
2498     /* ... and try to link */
2499     if ((gst_pad_link_full (pad, sinkpad,
2500                 GST_PAD_LINK_CHECK_NOTHING)) != GST_PAD_LINK_OK) {
2501       GST_WARNING_OBJECT (dbin, "Link failed on pad %s:%s",
2502           GST_DEBUG_PAD_NAME (sinkpad));
2503       remove_error_filter (dbin, element, NULL);
2504       g_string_append_printf (error_details, "Link failed on pad %s:%s",
2505           GST_DEBUG_PAD_NAME (sinkpad));
2506       gst_object_unref (sinkpad);
2507       gst_bin_remove (GST_BIN (dbin), element);
2508       continue;
2509     }
2510 
2511     /* ... activate it ... */
2512     if ((gst_element_set_state (element,
2513                 GST_STATE_READY)) == GST_STATE_CHANGE_FAILURE) {
2514       GstMessage *error_msg;
2515 
2516       GST_WARNING_OBJECT (dbin, "Couldn't set %s to READY",
2517           GST_ELEMENT_NAME (element));
2518       remove_error_filter (dbin, element, &error_msg);
2519 
2520       if (error_msg) {
2521         gchar *error_string = error_message_to_string (error_msg);
2522         g_string_append_printf (error_details, "Couldn't set %s to READY:\n%s",
2523             GST_ELEMENT_NAME (element), error_string);
2524         gst_message_unref (error_msg);
2525         g_free (error_string);
2526       } else {
2527         g_string_append_printf (error_details, "Couldn't set %s to READY",
2528             GST_ELEMENT_NAME (element));
2529       }
2530       gst_object_unref (sinkpad);
2531       gst_bin_remove (GST_BIN (dbin), element);
2532       continue;
2533     }
2534 
2535     /* check if we still accept the caps on the pad after setting
2536      * the element to READY */
2537     if (!gst_pad_query_accept_caps (sinkpad, caps)) {
2538       GstMessage *error_msg;
2539 
2540       GST_WARNING_OBJECT (dbin, "Element %s does not accept caps",
2541           GST_ELEMENT_NAME (element));
2542 
2543       remove_error_filter (dbin, element, &error_msg);
2544 
2545       if (error_msg) {
2546         gchar *error_string = error_message_to_string (error_msg);
2547         g_string_append_printf (error_details,
2548             "Element %s does not accept caps:\n%s", GST_ELEMENT_NAME (element),
2549             error_string);
2550         gst_message_unref (error_msg);
2551         g_free (error_string);
2552       } else {
2553         g_string_append_printf (error_details,
2554             "Element %s does not accept caps", GST_ELEMENT_NAME (element));
2555       }
2556 
2557       gst_element_set_state (element, GST_STATE_NULL);
2558       gst_object_unref (sinkpad);
2559       gst_bin_remove (GST_BIN (dbin), element);
2560       continue;
2561     }
2562 
2563     gst_object_unref (sinkpad);
2564     GST_LOG_OBJECT (dbin, "linked on pad %s:%s", GST_DEBUG_PAD_NAME (pad));
2565 
2566     CHAIN_MUTEX_LOCK (chain);
2567     delem = g_slice_new0 (GstDecodeElement);
2568     delem->element = gst_object_ref (element);
2569     delem->capsfilter = NULL;
2570     chain->elements = g_list_prepend (chain->elements, delem);
2571     chain->demuxer = is_demuxer_element (element);
2572     chain->adaptive_demuxer = is_adaptive_demuxer_element (element);
2573 
2574     is_decoder = strstr (gst_element_factory_get_metadata (factory,
2575             GST_ELEMENT_METADATA_KLASS), "Decoder") != NULL;
2576 
2577     /* For adaptive streaming demuxer we insert a multiqueue after
2578      * this demuxer.
2579      * Now for the case where we have a container stream inside these
2580      * buffers, another demuxer will be plugged and after this second
2581      * demuxer there will be a second multiqueue. This second multiqueue
2582      * will get smaller buffers and will be the one emitting buffering
2583      * messages.
2584      * If we don't have a container stream inside the fragment buffers,
2585      * we'll insert a multiqueue below right after the next element after
2586      * the adaptive streaming demuxer. This is going to be a parser or
2587      * decoder, and will output smaller buffers.
2588      */
2589     if (chain->parent && chain->parent->parent) {
2590       GstDecodeChain *parent_chain = chain->parent->parent;
2591 
2592       if (parent_chain->adaptive_demuxer && (is_parser || is_decoder))
2593         chain->demuxer = TRUE;
2594     }
2595 
2596     /* If we are configured to use buffering and there is no demuxer in the
2597      * chain, we still want a multiqueue, otherwise we will ignore the
2598      * use-buffering property. In that case, we will insert a multiqueue after
2599      * the parser or decoder - not elsewhere, otherwise we won't have
2600      * timestamps.
2601      */
2602 
2603     if (!chain->parent && (is_parser || is_decoder) && dbin->use_buffering) {
2604       chain->demuxer = TRUE;
2605       if (is_decoder) {
2606         GST_WARNING_OBJECT (dbin,
2607             "Buffering messages used for decoded and non-parsed data");
2608       }
2609     }
2610 
2611     CHAIN_MUTEX_UNLOCK (chain);
2612 
2613     /* Set connection-speed property if needed */
2614     if (chain->demuxer) {
2615       GParamSpec *pspec;
2616 
2617       if ((pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (element),
2618                   "connection-speed"))) {
2619         guint64 speed = dbin->connection_speed / 1000;
2620         gboolean wrong_type = FALSE;
2621 
2622         if (G_PARAM_SPEC_TYPE (pspec) == G_TYPE_PARAM_UINT) {
2623           GParamSpecUInt *pspecuint = G_PARAM_SPEC_UINT (pspec);
2624 
2625           speed = CLAMP (speed, pspecuint->minimum, pspecuint->maximum);
2626         } else if (G_PARAM_SPEC_TYPE (pspec) == G_TYPE_PARAM_INT) {
2627           GParamSpecInt *pspecint = G_PARAM_SPEC_INT (pspec);
2628 
2629           speed = CLAMP (speed, pspecint->minimum, pspecint->maximum);
2630         } else if (G_PARAM_SPEC_TYPE (pspec) == G_TYPE_PARAM_UINT64) {
2631           GParamSpecUInt64 *pspecuint = G_PARAM_SPEC_UINT64 (pspec);
2632 
2633           speed = CLAMP (speed, pspecuint->minimum, pspecuint->maximum);
2634         } else if (G_PARAM_SPEC_TYPE (pspec) == G_TYPE_PARAM_INT64) {
2635           GParamSpecInt64 *pspecint = G_PARAM_SPEC_INT64 (pspec);
2636 
2637           speed = CLAMP (speed, pspecint->minimum, pspecint->maximum);
2638         } else {
2639           GST_WARNING_OBJECT (dbin,
2640               "The connection speed property %" G_GUINT64_FORMAT " of type %s"
2641               " is not useful not setting it", speed,
2642               g_type_name (G_PARAM_SPEC_TYPE (pspec)));
2643           wrong_type = TRUE;
2644         }
2645 
2646         if (!wrong_type) {
2647           GST_DEBUG_OBJECT (dbin, "setting connection-speed=%" G_GUINT64_FORMAT
2648               " to demuxer element", speed);
2649 
2650           g_object_set (element, "connection-speed", speed, NULL);
2651         }
2652       }
2653     }
2654 
2655 #ifdef OHOS_EXT_FUNC
2656     // ohos.ext.func.0028
2657     if (IS_ADAPTIVE_DEMUX(element)) {
2658         g_signal_connect (element, "bitrate-parse-complete", G_CALLBACK (bitrate_parse_complete_cb), chain);
2659     }
2660 #endif
2661 
2662     /* try to configure the subtitle encoding property when we can */
2663     pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (element),
2664         "subtitle-encoding");
2665     if (pspec && G_PARAM_SPEC_VALUE_TYPE (pspec) == G_TYPE_STRING) {
2666       SUBTITLE_LOCK (dbin);
2667       GST_DEBUG_OBJECT (dbin,
2668           "setting subtitle-encoding=%s to element", dbin->encoding);
2669       g_object_set (G_OBJECT (element), "subtitle-encoding", dbin->encoding,
2670           NULL);
2671       SUBTITLE_UNLOCK (dbin);
2672       subtitle = TRUE;
2673     } else {
2674       subtitle = FALSE;
2675     }
2676 
2677     /* link this element further */
2678     to_connect = connect_element (dbin, delem, chain);
2679 
2680     while (to_connect) {
2681       GstPad *opad = to_connect->data;
2682       gboolean expose_pad = FALSE;
2683       GstDecodeChain *new_chain;
2684       GstCaps *ocaps;
2685 
2686       ocaps = get_pad_caps (opad);
2687       expose_pad =
2688           analyze_new_pad (dbin, delem->element, opad, ocaps, chain,
2689           &new_chain);
2690 
2691       if (ocaps)
2692         gst_caps_unref (ocaps);
2693 
2694       if (expose_pad) {
2695         PadExposeData *expose_data = g_new0 (PadExposeData, 1);
2696         expose_data->chain = new_chain;
2697         expose_data->pad = gst_object_ref (opad);
2698         to_expose = g_list_prepend (to_expose, expose_data);
2699       }
2700 
2701       gst_object_unref (opad);
2702       to_connect = g_list_delete_link (to_connect, to_connect);
2703     }
2704     /* any pads left in to_expose are to be exposed */
2705 
2706     /* Bring the element to the state of the parent */
2707 
2708     /* First lock element's sinkpad stream lock so no data reaches
2709      * the possible new element added when caps are sent by element
2710      * while we're still sending sticky events */
2711     GST_PAD_STREAM_LOCK (sinkpad);
2712 
2713     if ((gst_element_set_state (element,
2714                 GST_STATE_PAUSED)) == GST_STATE_CHANGE_FAILURE ||
2715         !send_sticky_events (dbin, pad)) {
2716       GstDecodeElement *dtmp = NULL;
2717       GstElement *tmp = NULL;
2718       GstMessage *error_msg;
2719 
2720       GST_PAD_STREAM_UNLOCK (sinkpad);
2721 
2722       GST_WARNING_OBJECT (dbin, "Couldn't set %s to PAUSED",
2723           GST_ELEMENT_NAME (element));
2724 
2725       while (to_expose) {
2726         PadExposeData *expose_data = to_expose->data;
2727         gst_object_unref (expose_data->pad);
2728         g_free (expose_data);
2729         to_expose = g_list_delete_link (to_expose, to_expose);
2730       }
2731 
2732       remove_error_filter (dbin, element, &error_msg);
2733 
2734       if (error_msg) {
2735         gchar *error_string = error_message_to_string (error_msg);
2736         g_string_append_printf (error_details, "Couldn't set %s to PAUSED:\n%s",
2737             GST_ELEMENT_NAME (element), error_string);
2738         gst_message_unref (error_msg);
2739         g_free (error_string);
2740       } else {
2741         g_string_append_printf (error_details, "Couldn't set %s to PAUSED",
2742             GST_ELEMENT_NAME (element));
2743       }
2744 
2745       /* Remove all elements in this chain that were just added. No
2746        * other thread could've added elements in the meantime */
2747       CHAIN_MUTEX_LOCK (chain);
2748       do {
2749         GList *l;
2750 
2751         dtmp = chain->elements->data;
2752         tmp = dtmp->element;
2753 
2754         /* Disconnect any signal handlers that might be connected
2755          * in connect_element() or analyze_pad() */
2756         if (dtmp->pad_added_id)
2757           g_signal_handler_disconnect (tmp, dtmp->pad_added_id);
2758         if (dtmp->pad_removed_id)
2759           g_signal_handler_disconnect (tmp, dtmp->pad_removed_id);
2760         if (dtmp->no_more_pads_id)
2761           g_signal_handler_disconnect (tmp, dtmp->no_more_pads_id);
2762 
2763         for (l = chain->pending_pads; l;) {
2764           GstPendingPad *pp = l->data;
2765           GList *n;
2766 
2767           if (GST_PAD_PARENT (pp->pad) != tmp) {
2768             l = l->next;
2769             continue;
2770           }
2771 
2772           gst_pending_pad_free (pp);
2773 
2774           /* Remove element from the list, update list head and go to the
2775            * next element in the list */
2776           n = l->next;
2777           chain->pending_pads = g_list_delete_link (chain->pending_pads, l);
2778           l = n;
2779         }
2780 
2781         if (dtmp->capsfilter) {
2782           gst_bin_remove (GST_BIN (dbin), dtmp->capsfilter);
2783           gst_element_set_state (dtmp->capsfilter, GST_STATE_NULL);
2784           gst_object_unref (dtmp->capsfilter);
2785         }
2786 
2787         gst_bin_remove (GST_BIN (dbin), tmp);
2788         gst_element_set_state (tmp, GST_STATE_NULL);
2789 
2790         gst_object_unref (tmp);
2791         g_slice_free (GstDecodeElement, dtmp);
2792 
2793         chain->elements = g_list_delete_link (chain->elements, chain->elements);
2794       } while (tmp != element);
2795       CHAIN_MUTEX_UNLOCK (chain);
2796 
2797       continue;
2798     } else {
2799       /* Everything went well, the spice must flow now */
2800       GST_PAD_STREAM_UNLOCK (sinkpad);
2801     }
2802 
2803     /* Remove error filter now, from now on we can't gracefully
2804      * handle errors of the element anymore */
2805     remove_error_filter (dbin, element, NULL);
2806 
2807     /* Now let the bin handle the state */
2808     gst_element_set_locked_state (element, FALSE);
2809 
2810     if (subtitle) {
2811       SUBTITLE_LOCK (dbin);
2812       /* we added the element now, add it to the list of subtitle-encoding
2813        * elements when we can set the property */
2814       dbin->subtitles = g_list_prepend (dbin->subtitles, element);
2815       SUBTITLE_UNLOCK (dbin);
2816     }
2817 
2818     while (to_expose) {
2819       PadExposeData *expose_data = to_expose->data;
2820       GstCaps *ocaps;
2821 
2822       ocaps = get_pad_caps (expose_data->pad);
2823       expose_pad (dbin, delem->element, expose_data->chain->current_pad,
2824           expose_data->pad, ocaps, expose_data->chain);
2825 
2826       if (ocaps)
2827         gst_caps_unref (ocaps);
2828 
2829       gst_object_unref (expose_data->pad);
2830       g_free (expose_data);
2831       to_expose = g_list_delete_link (to_expose, to_expose);
2832     }
2833 
2834     res = TRUE;
2835     break;
2836   }
2837 
2838 beach:
2839   if (mqpad)
2840     gst_object_unref (mqpad);
2841 
2842   if (error_details)
2843     *deadend_details = g_string_free (error_details, (error_details->len == 0
2844             || res));
2845   else
2846     *deadend_details = NULL;
2847 
2848   return res;
2849 }
2850 
2851 static GstCaps *
get_pad_caps(GstPad * pad)2852 get_pad_caps (GstPad * pad)
2853 {
2854   GstCaps *caps;
2855 
2856   /* first check the pad caps, if this is set, we are positively sure it is
2857    * fixed and exactly what the element will produce. */
2858   caps = gst_pad_get_current_caps (pad);
2859 
2860   /* then use the getcaps function if we don't have caps. These caps might not
2861    * be fixed in some cases, in which case analyze_new_pad will set up a
2862    * notify::caps signal to continue autoplugging. */
2863   if (caps == NULL)
2864     caps = gst_pad_query_caps (pad, NULL);
2865 
2866   return caps;
2867 }
2868 
2869 /* Returns a list of pads that can be connected to already and
2870  * connects to pad-added and related signals */
2871 static GList *
connect_element(GstDecodeBin * dbin,GstDecodeElement * delem,GstDecodeChain * chain)2872 connect_element (GstDecodeBin * dbin, GstDecodeElement * delem,
2873     GstDecodeChain * chain)
2874 {
2875   GstElement *element = delem->element;
2876   GList *pads;
2877   gboolean dynamic = FALSE;
2878   GList *to_connect = NULL;
2879 
2880   GST_DEBUG_OBJECT (dbin, "Attempting to connect element %s [chain:%p] further",
2881       GST_ELEMENT_NAME (element), chain);
2882 
2883   /* 1. Loop over pad templates, grabbing existing pads along the way */
2884   for (pads = GST_ELEMENT_GET_CLASS (element)->padtemplates; pads;
2885       pads = g_list_next (pads)) {
2886     GstPadTemplate *templ = GST_PAD_TEMPLATE (pads->data);
2887     const gchar *templ_name;
2888 
2889     /* we are only interested in source pads */
2890     if (GST_PAD_TEMPLATE_DIRECTION (templ) != GST_PAD_SRC)
2891       continue;
2892 
2893     templ_name = GST_PAD_TEMPLATE_NAME_TEMPLATE (templ);
2894     GST_DEBUG_OBJECT (dbin, "got a source pad template %s", templ_name);
2895 
2896     /* figure out what kind of pad this is */
2897     switch (GST_PAD_TEMPLATE_PRESENCE (templ)) {
2898       case GST_PAD_ALWAYS:
2899       {
2900         /* get the pad that we need to autoplug */
2901         GstPad *pad = gst_element_get_static_pad (element, templ_name);
2902 
2903         if (pad) {
2904           GST_DEBUG_OBJECT (dbin, "got the pad for always template %s",
2905               templ_name);
2906           /* here is the pad, we need to autoplug it */
2907           to_connect = g_list_prepend (to_connect, pad);
2908         } else {
2909           /* strange, pad is marked as always but it's not
2910            * there. Fix the element */
2911           GST_WARNING_OBJECT (dbin,
2912               "could not get the pad for always template %s", templ_name);
2913         }
2914         break;
2915       }
2916       case GST_PAD_SOMETIMES:
2917       {
2918         /* try to get the pad to see if it is already created or
2919          * not */
2920         GstPad *pad = gst_element_get_static_pad (element, templ_name);
2921 
2922         if (pad) {
2923           GST_DEBUG_OBJECT (dbin, "got the pad for sometimes template %s",
2924               templ_name);
2925           /* the pad is created, we need to autoplug it */
2926           to_connect = g_list_prepend (to_connect, pad);
2927         } else {
2928           GST_DEBUG_OBJECT (dbin,
2929               "did not get the sometimes pad of template %s", templ_name);
2930           /* we have an element that will create dynamic pads */
2931           dynamic = TRUE;
2932         }
2933         break;
2934       }
2935       case GST_PAD_REQUEST:
2936         /* ignore request pads */
2937         GST_DEBUG_OBJECT (dbin, "ignoring request padtemplate %s", templ_name);
2938         break;
2939     }
2940   }
2941 
2942   /* 2. if there are more potential pads, connect to relevant signals */
2943   if (dynamic) {
2944     GST_LOG_OBJECT (dbin, "Adding signals to element %s in chain %p",
2945         GST_ELEMENT_NAME (element), chain);
2946     delem->pad_added_id = g_signal_connect (element, "pad-added",
2947         G_CALLBACK (pad_added_cb), chain);
2948     delem->pad_removed_id = g_signal_connect (element, "pad-removed",
2949         G_CALLBACK (pad_removed_cb), chain);
2950     delem->no_more_pads_id = g_signal_connect (element, "no-more-pads",
2951         G_CALLBACK (no_more_pads_cb), chain);
2952   }
2953 
2954   /* 3. return all pads that can be connected to already */
2955 
2956   return to_connect;
2957 }
2958 
2959 /* expose_pad:
2960  *
2961  * Expose the given pad on the chain as a decoded pad.
2962  */
2963 static void
expose_pad(GstDecodeBin * dbin,GstElement * src,GstDecodePad * dpad,GstPad * pad,GstCaps * caps,GstDecodeChain * chain)2964 expose_pad (GstDecodeBin * dbin, GstElement * src, GstDecodePad * dpad,
2965     GstPad * pad, GstCaps * caps, GstDecodeChain * chain)
2966 {
2967   GstPad *mqpad = NULL;
2968 
2969   GST_DEBUG_OBJECT (dbin, "pad %s:%s, chain:%p",
2970       GST_DEBUG_PAD_NAME (pad), chain);
2971 
2972   /* If this is the first pad for this chain, there are no other elements
2973    * and the source element is not the multiqueue we must link through the
2974    * multiqueue.
2975    *
2976    * This is the case if a demuxer directly exposed a raw pad.
2977    */
2978   if (chain->parent && !chain->elements && src != chain->parent->multiqueue) {
2979     GST_LOG_OBJECT (src, "connecting the pad through multiqueue");
2980 
2981     decode_pad_set_target (dpad, NULL);
2982     if (!(mqpad = gst_decode_group_control_demuxer_pad (chain->parent, pad)))
2983       goto beach;
2984     pad = mqpad;
2985     decode_pad_set_target (dpad, pad);
2986   }
2987 
2988   gst_decode_pad_activate (dpad, chain);
2989   chain->endpad = gst_object_ref (dpad);
2990   chain->endcaps = gst_caps_ref (caps);
2991 
2992   EXPOSE_LOCK (dbin);
2993   if (dbin->decode_chain) {
2994     if (gst_decode_chain_is_complete (dbin->decode_chain)) {
2995       gst_decode_bin_expose (dbin);
2996     }
2997   }
2998   EXPOSE_UNLOCK (dbin);
2999 
3000   if (mqpad)
3001     gst_object_unref (mqpad);
3002 
3003 beach:
3004   return;
3005 }
3006 
3007 /* check_upstream_seekable:
3008  *
3009  * Check if upstream is seekable.
3010  */
3011 static gboolean
check_upstream_seekable(GstDecodeBin * dbin,GstPad * pad)3012 check_upstream_seekable (GstDecodeBin * dbin, GstPad * pad)
3013 {
3014   GstQuery *query;
3015   gint64 start = -1, stop = -1;
3016   gboolean seekable = FALSE;
3017 
3018   query = gst_query_new_seeking (GST_FORMAT_BYTES);
3019   if (!gst_pad_peer_query (pad, query)) {
3020     GST_DEBUG_OBJECT (dbin, "seeking query failed");
3021     goto done;
3022   }
3023 
3024   gst_query_parse_seeking (query, NULL, &seekable, &start, &stop);
3025 
3026   /* try harder to query upstream size if we didn't get it the first time */
3027   if (seekable && stop == -1) {
3028     GST_DEBUG_OBJECT (dbin, "doing duration query to fix up unset stop");
3029     gst_pad_peer_query_duration (pad, GST_FORMAT_BYTES, &stop);
3030   }
3031 
3032   /* if upstream doesn't know the size, it's likely that it's not seekable in
3033    * practice even if it technically may be seekable */
3034   if (seekable && (start != 0 || stop <= start)) {
3035     GST_DEBUG_OBJECT (dbin, "seekable but unknown start/stop -> disable");
3036     seekable = FALSE;
3037   } else {
3038     GST_DEBUG_OBJECT (dbin, "upstream seekable: %d", seekable);
3039   }
3040 
3041 done:
3042   gst_query_unref (query);
3043   return seekable;
3044 }
3045 
3046 static void
type_found(GstElement * typefind,guint probability,GstCaps * caps,GstDecodeBin * decode_bin)3047 type_found (GstElement * typefind, guint probability,
3048     GstCaps * caps, GstDecodeBin * decode_bin)
3049 {
3050   GstPad *pad, *sink_pad;
3051   GstDecodeChain *chain;
3052 
3053   GST_DEBUG_OBJECT (decode_bin, "typefind found caps %" GST_PTR_FORMAT, caps);
3054 
3055   /* If the typefinder (but not something else) finds text/plain - i.e. that's
3056    * the top-level type of the file - then error out.
3057    */
3058   if (gst_structure_has_name (gst_caps_get_structure (caps, 0), "text/plain")) {
3059     GST_ELEMENT_ERROR (decode_bin, STREAM, WRONG_TYPE,
3060         (_("This appears to be a text file")),
3061         ("decodebin cannot decode plain text files"));
3062     goto exit;
3063   }
3064 
3065   pad = gst_element_get_static_pad (typefind, "src");
3066   sink_pad = gst_element_get_static_pad (typefind, "sink");
3067 
3068   /* need some lock here to prevent race with shutdown state change
3069    * which might yank away e.g. decode_chain while building stuff here.
3070    * In typical cases, STREAM_LOCK is held and handles that, it need not
3071    * be held (if called from a proxied setcaps), so grab it anyway */
3072   GST_PAD_STREAM_LOCK (sink_pad);
3073   /* FIXME: we can only deal with one type, we don't yet support dynamically changing
3074    * caps from the typefind element */
3075   if (decode_bin->have_type || decode_bin->decode_chain) {
3076   } else {
3077     decode_bin->have_type = TRUE;
3078 
3079     decode_bin->decode_chain = gst_decode_chain_new (decode_bin, NULL, pad);
3080     chain = gst_decode_chain_ref (decode_bin->decode_chain);
3081 
3082     if (analyze_new_pad (decode_bin, typefind, pad, caps,
3083             decode_bin->decode_chain, NULL))
3084       expose_pad (decode_bin, typefind, decode_bin->decode_chain->current_pad,
3085           pad, caps, decode_bin->decode_chain);
3086 
3087     gst_decode_chain_unref (chain);
3088   }
3089 
3090   GST_PAD_STREAM_UNLOCK (sink_pad);
3091   gst_object_unref (sink_pad);
3092   gst_object_unref (pad);
3093 
3094 exit:
3095   return;
3096 }
3097 
3098 static GstPadProbeReturn
pad_event_cb(GstPad * pad,GstPadProbeInfo * info,gpointer data)3099 pad_event_cb (GstPad * pad, GstPadProbeInfo * info, gpointer data)
3100 {
3101   GstEvent *event = GST_PAD_PROBE_INFO_EVENT (info);
3102   GstPendingPad *ppad = (GstPendingPad *) data;
3103   GstDecodeChain *chain = ppad->chain;
3104   GstDecodeBin *dbin = chain->dbin;
3105 
3106   g_assert (ppad);
3107   g_assert (chain);
3108   g_assert (dbin);
3109   switch (GST_EVENT_TYPE (event)) {
3110     case GST_EVENT_EOS:
3111       GST_DEBUG_OBJECT (pad, "Received EOS on a non final pad, this stream "
3112           "ended too early");
3113       chain->deadend = TRUE;
3114       chain->drained = TRUE;
3115       gst_object_replace ((GstObject **) & chain->current_pad, NULL);
3116       /* we don't set the endcaps because NULL endcaps means early EOS */
3117 
3118       EXPOSE_LOCK (dbin);
3119       if (dbin->decode_chain)
3120         if (gst_decode_chain_is_complete (dbin->decode_chain))
3121           gst_decode_bin_expose (dbin);
3122       EXPOSE_UNLOCK (dbin);
3123       break;
3124     default:
3125       break;
3126   }
3127   return GST_PAD_PROBE_OK;
3128 }
3129 
3130 static void
pad_added_cb(GstElement * element,GstPad * pad,GstDecodeChain * chain)3131 pad_added_cb (GstElement * element, GstPad * pad, GstDecodeChain * chain)
3132 {
3133   GstCaps *caps;
3134   GstDecodeBin *dbin;
3135   GstDecodeChain *new_chain;
3136 
3137   dbin = chain->dbin;
3138 
3139   GST_DEBUG_OBJECT (pad, "pad added, chain:%p", chain);
3140   GST_PAD_STREAM_LOCK (pad);
3141   if (!gst_pad_is_active (pad)) {
3142     GST_PAD_STREAM_UNLOCK (pad);
3143     GST_DEBUG_OBJECT (pad, "Ignoring pad-added from a deactivated pad");
3144     return;
3145   }
3146 
3147   caps = get_pad_caps (pad);
3148   if (analyze_new_pad (dbin, element, pad, caps, chain, &new_chain))
3149     expose_pad (dbin, element, new_chain->current_pad, pad, caps, new_chain);
3150   if (caps)
3151     gst_caps_unref (caps);
3152 
3153   GST_PAD_STREAM_UNLOCK (pad);
3154 }
3155 
3156 static GstPadProbeReturn
sink_pad_event_probe(GstPad * pad,GstPadProbeInfo * info,gpointer user_data)3157 sink_pad_event_probe (GstPad * pad, GstPadProbeInfo * info, gpointer user_data)
3158 {
3159   GstDecodeGroup *group = (GstDecodeGroup *) user_data;
3160   GstEvent *event = GST_PAD_PROBE_INFO_EVENT (info);
3161   GstPad *peer = gst_pad_get_peer (pad);
3162   GstPadProbeReturn proberet = GST_PAD_PROBE_OK;
3163 
3164   GST_DEBUG_OBJECT (pad, "Got upstream event %s", GST_EVENT_TYPE_NAME (event));
3165 
3166   if (peer == NULL) {
3167     GST_DEBUG_OBJECT (pad, "We are unlinked !");
3168     if (group->parent && group->parent->next_groups) {
3169       GstDecodeGroup *last_group =
3170           g_list_last (group->parent->next_groups)->data;
3171       GST_DEBUG_OBJECT (pad, "We could send the event to another group (%p)",
3172           last_group);
3173       /* Grab another sinkpad for that last group through which we will forward this event */
3174       if (last_group->reqpads) {
3175         GstPad *sinkpad = (GstPad *) last_group->reqpads->data;
3176         GstPad *otherpeer = gst_pad_get_peer (sinkpad);
3177         if (otherpeer) {
3178           GST_DEBUG_OBJECT (otherpeer, "Attempting to forward event");
3179           if (gst_pad_send_event (otherpeer, gst_event_ref (event))) {
3180             gst_event_unref (event);
3181             proberet = GST_PAD_PROBE_HANDLED;
3182           }
3183           gst_object_unref (otherpeer);
3184         }
3185       } else {
3186         GST_DEBUG_OBJECT (pad, "No request pads, can't forward event");
3187       }
3188     }
3189   } else {
3190     gst_object_unref (peer);
3191   }
3192 
3193   return proberet;
3194 }
3195 
3196 static GstPadProbeReturn
sink_pad_query_probe(GstPad * pad,GstPadProbeInfo * info,gpointer user_data)3197 sink_pad_query_probe (GstPad * pad, GstPadProbeInfo * info, gpointer user_data)
3198 {
3199   GstDecodeGroup *group = (GstDecodeGroup *) user_data;
3200   GstPad *peer = gst_pad_get_peer (pad);
3201   GstQuery *query = GST_PAD_PROBE_INFO_QUERY (info);
3202   GstPadProbeReturn proberet = GST_PAD_PROBE_OK;
3203 
3204   GST_DEBUG_OBJECT (pad, "Got upstream query %s", GST_QUERY_TYPE_NAME (query));
3205 
3206   if (peer == NULL) {
3207     GST_DEBUG_OBJECT (pad, "We are unlinked !");
3208     if (group->parent && group->parent->next_groups) {
3209       GstDecodeGroup *last_group =
3210           g_list_last (group->parent->next_groups)->data;
3211       GST_DEBUG_OBJECT (pad, "We could send the query to another group");
3212       /* Grab another sinkpad for that last group through which we will forward this event */
3213       if (last_group->reqpads) {
3214         GstPad *sinkpad = (GstPad *) last_group->reqpads->data;
3215         GstPad *otherpeer = gst_pad_get_peer (sinkpad);
3216         if (otherpeer) {
3217           GST_DEBUG_OBJECT (otherpeer, "Attempting to forward query");
3218           if (gst_pad_query (otherpeer, query)) {
3219             proberet = GST_PAD_PROBE_HANDLED;
3220           } else
3221             GST_DEBUG ("FAILURE");
3222           gst_object_unref (otherpeer);
3223         } else
3224           GST_DEBUG_OBJECT (sinkpad, "request pad not connected ??");
3225       } else
3226         GST_DEBUG_OBJECT (pad, "No request pads ???");
3227     }
3228   } else
3229     gst_object_unref (peer);
3230 
3231   return proberet;
3232 }
3233 
3234 static void
pad_removed_cb(GstElement * element,GstPad * pad,GstDecodeChain * chain)3235 pad_removed_cb (GstElement * element, GstPad * pad, GstDecodeChain * chain)
3236 {
3237   GList *l;
3238 
3239   GST_LOG_OBJECT (pad, "pad removed, chain:%p", chain);
3240 
3241   /* In fact, we don't have to do anything here, the active group will be
3242    * removed when the group's multiqueue is drained */
3243   CHAIN_MUTEX_LOCK (chain);
3244   for (l = chain->pending_pads; l; l = l->next) {
3245     GstPendingPad *ppad = l->data;
3246     GstPad *opad = ppad->pad;
3247 
3248     if (pad == opad) {
3249       gst_pending_pad_free (ppad);
3250       chain->pending_pads = g_list_delete_link (chain->pending_pads, l);
3251       break;
3252     }
3253   }
3254   CHAIN_MUTEX_UNLOCK (chain);
3255 }
3256 
3257 static void
no_more_pads_cb(GstElement * element,GstDecodeChain * chain)3258 no_more_pads_cb (GstElement * element, GstDecodeChain * chain)
3259 {
3260   GstDecodeGroup *group = NULL;
3261 
3262   GST_LOG_OBJECT (element, "got no more pads");
3263 
3264   CHAIN_MUTEX_LOCK (chain);
3265   if (!chain->elements
3266       || ((GstDecodeElement *) chain->elements->data)->element != element) {
3267     GST_LOG_OBJECT (chain->dbin, "no-more-pads from old chain element '%s'",
3268         GST_OBJECT_NAME (element));
3269     CHAIN_MUTEX_UNLOCK (chain);
3270     return;
3271   } else if (!chain->demuxer) {
3272     GST_LOG_OBJECT (chain->dbin, "no-more-pads from a non-demuxer element '%s'",
3273         GST_OBJECT_NAME (element));
3274     CHAIN_MUTEX_UNLOCK (chain);
3275     return;
3276   }
3277 
3278   /* when we received no_more_pads, we can complete the pads of the chain */
3279   if (!chain->next_groups && chain->active_group) {
3280     group = chain->active_group;
3281   } else if (chain->next_groups) {
3282     GList *iter;
3283     for (iter = chain->next_groups; iter; iter = g_list_next (iter)) {
3284       group = iter->data;
3285       if (!group->no_more_pads)
3286         break;
3287     }
3288   }
3289   if (!group) {
3290     GST_ERROR_OBJECT (chain->dbin, "can't find group for element");
3291     CHAIN_MUTEX_UNLOCK (chain);
3292     return;
3293   }
3294 
3295   GST_DEBUG_OBJECT (element, "Setting group %p to complete", group);
3296 
3297   group->no_more_pads = TRUE;
3298   /* this group has prerolled enough to not need more pads,
3299    * we can probably set its buffering state to playing now */
3300   GST_DEBUG_OBJECT (group->dbin, "Setting group %p multiqueue to "
3301       "'playing' buffering mode", group);
3302   decodebin_set_queue_size (group->dbin, group->multiqueue, FALSE,
3303       (group->parent ? group->parent->seekable : TRUE));
3304   CHAIN_MUTEX_UNLOCK (chain);
3305 
3306   EXPOSE_LOCK (chain->dbin);
3307   if (chain->dbin->decode_chain) {
3308     if (gst_decode_chain_is_complete (chain->dbin->decode_chain)) {
3309       gst_decode_bin_expose (chain->dbin);
3310     }
3311   }
3312   EXPOSE_UNLOCK (chain->dbin);
3313 }
3314 
3315 static void
caps_notify_cb(GstPad * pad,GParamSpec * unused,GstDecodeChain * chain)3316 caps_notify_cb (GstPad * pad, GParamSpec * unused, GstDecodeChain * chain)
3317 {
3318   GstElement *element;
3319   GList *l;
3320 
3321   GST_LOG_OBJECT (pad, "Notified caps for pad %s:%s", GST_DEBUG_PAD_NAME (pad));
3322 
3323   /* Disconnect this; if we still need it, we'll reconnect to this in
3324    * analyze_new_pad */
3325   element = GST_ELEMENT_CAST (gst_pad_get_parent (pad));
3326 
3327   CHAIN_MUTEX_LOCK (chain);
3328   for (l = chain->pending_pads; l; l = l->next) {
3329     GstPendingPad *ppad = l->data;
3330     if (ppad->pad == pad) {
3331       gst_pending_pad_free (ppad);
3332       chain->pending_pads = g_list_delete_link (chain->pending_pads, l);
3333       break;
3334     }
3335   }
3336   CHAIN_MUTEX_UNLOCK (chain);
3337 
3338   pad_added_cb (element, pad, chain);
3339 
3340   gst_object_unref (element);
3341 }
3342 
3343 /* Decide whether an element is a demuxer based on the
3344  * klass and number/type of src pad templates it has */
3345 static gboolean
is_demuxer_element(GstElement * srcelement)3346 is_demuxer_element (GstElement * srcelement)
3347 {
3348   GstElementFactory *srcfactory;
3349   GstElementClass *elemclass;
3350   GList *walk;
3351   const gchar *klass;
3352   gint potential_src_pads = 0;
3353 
3354   srcfactory = gst_element_get_factory (srcelement);
3355   klass =
3356       gst_element_factory_get_metadata (srcfactory, GST_ELEMENT_METADATA_KLASS);
3357 
3358   /* Can't be a demuxer unless it has Demux in the klass name */
3359   if (!strstr (klass, "Demux"))
3360     return FALSE;
3361 
3362   /* Walk the src pad templates and count how many the element
3363    * might produce */
3364   elemclass = GST_ELEMENT_GET_CLASS (srcelement);
3365 
3366   walk = gst_element_class_get_pad_template_list (elemclass);
3367   while (walk != NULL) {
3368     GstPadTemplate *templ;
3369 
3370     templ = (GstPadTemplate *) walk->data;
3371     if (GST_PAD_TEMPLATE_DIRECTION (templ) == GST_PAD_SRC) {
3372       switch (GST_PAD_TEMPLATE_PRESENCE (templ)) {
3373         case GST_PAD_ALWAYS:
3374         case GST_PAD_SOMETIMES:
3375           if (strstr (GST_PAD_TEMPLATE_NAME_TEMPLATE (templ), "%"))
3376             potential_src_pads += 2;    /* Might make multiple pads */
3377           else
3378             potential_src_pads += 1;
3379           break;
3380         case GST_PAD_REQUEST:
3381           potential_src_pads += 2;
3382           break;
3383       }
3384     }
3385     walk = g_list_next (walk);
3386   }
3387 
3388   if (potential_src_pads < 2)
3389     return FALSE;
3390 
3391   return TRUE;
3392 }
3393 
3394 static gboolean
is_adaptive_demuxer_element(GstElement * srcelement)3395 is_adaptive_demuxer_element (GstElement * srcelement)
3396 {
3397   GstElementFactory *srcfactory;
3398   const gchar *klass;
3399 
3400   srcfactory = gst_element_get_factory (srcelement);
3401   klass =
3402       gst_element_factory_get_metadata (srcfactory, GST_ELEMENT_METADATA_KLASS);
3403 
3404   /* Can't be a demuxer unless it has Demux in the klass name */
3405   if (!strstr (klass, "Demux") || !strstr (klass, "Adaptive"))
3406     return FALSE;
3407 
3408   return TRUE;
3409 }
3410 
3411 /* Returns TRUE if the caps are compatible with the caps specified in the 'caps'
3412  * property (which by default are the raw caps)
3413  *
3414  * The decodebin_lock should be taken !
3415  */
3416 static gboolean
are_final_caps(GstDecodeBin * dbin,GstCaps * caps)3417 are_final_caps (GstDecodeBin * dbin, GstCaps * caps)
3418 {
3419   gboolean res;
3420 
3421   GST_LOG_OBJECT (dbin, "Checking with caps %" GST_PTR_FORMAT, caps);
3422 
3423   /* lock for getting the caps */
3424   GST_OBJECT_LOCK (dbin);
3425   res = gst_caps_is_subset (caps, dbin->caps);
3426   GST_OBJECT_UNLOCK (dbin);
3427 
3428   GST_LOG_OBJECT (dbin, "Caps are %sfinal caps", res ? "" : "not ");
3429 
3430   return res;
3431 }
3432 
3433 /* gst_decode_bin_reset_buffering:
3434  *
3435  * Enables buffering on the last multiqueue of each group only,
3436  * disabling the rest
3437  *
3438  */
3439 static void
gst_decode_bin_reset_buffering(GstDecodeBin * dbin)3440 gst_decode_bin_reset_buffering (GstDecodeBin * dbin)
3441 {
3442   if (!dbin->use_buffering)
3443     return;
3444 
3445   GST_DEBUG_OBJECT (dbin, "Resetting multiqueues buffering");
3446   if (dbin->decode_chain) {
3447     CHAIN_MUTEX_LOCK (dbin->decode_chain);
3448     gst_decode_chain_reset_buffering (dbin->decode_chain);
3449 
3450 #ifdef OHOS_EXT_FUNC
3451     // ohos.ext.func.0013
3452     GstMessage *msg_mq_num_use_buffering =
3453       gst_message_new_mq_num_use_buffering (GST_OBJECT_CAST (dbin), dbin->mq_num_use_buffering);
3454     if (msg_mq_num_use_buffering != NULL) {
3455       gst_element_post_message (GST_ELEMENT_CAST (dbin), msg_mq_num_use_buffering);
3456     }
3457 #endif
3458     CHAIN_MUTEX_UNLOCK (dbin->decode_chain);
3459   }
3460 }
3461 
3462 /****
3463  * GstDecodeChain functions
3464  ****/
3465 
3466 static gboolean
gst_decode_chain_reset_buffering(GstDecodeChain * chain)3467 gst_decode_chain_reset_buffering (GstDecodeChain * chain)
3468 {
3469   GstDecodeGroup *group;
3470 
3471   group = chain->active_group;
3472   GST_LOG_OBJECT (chain->dbin, "Resetting chain %p buffering, active group: %p",
3473       chain, group);
3474   if (group) {
3475     return gst_decode_group_reset_buffering (group);
3476   }
3477   return FALSE;
3478 }
3479 
3480 /* gst_decode_chain_get_current_group:
3481  *
3482  * Returns the current group of this chain, to which
3483  * new chains should be attached or NULL if the last
3484  * group didn't have no-more-pads.
3485  *
3486  * Not MT-safe: Call with parent chain lock!
3487  */
3488 static GstDecodeGroup *
gst_decode_chain_get_current_group(GstDecodeChain * chain)3489 gst_decode_chain_get_current_group (GstDecodeChain * chain)
3490 {
3491   GstDecodeGroup *group;
3492 
3493   if (!chain->next_groups && chain->active_group
3494       && chain->active_group->overrun && !chain->active_group->no_more_pads) {
3495     GST_WARNING_OBJECT (chain->dbin,
3496         "Currently active group %p is exposed"
3497         " and wants to add a new pad without having signaled no-more-pads",
3498         chain->active_group);
3499     return NULL;
3500   }
3501 
3502   if (chain->next_groups && (group = chain->next_groups->data) && group->overrun
3503       && !group->no_more_pads) {
3504     GST_WARNING_OBJECT (chain->dbin,
3505         "Currently newest pending group %p "
3506         "had overflow but didn't signal no-more-pads", group);
3507     return NULL;
3508   }
3509 
3510   /* Now we know that we can really return something useful */
3511   if (!chain->active_group) {
3512     chain->active_group = group = gst_decode_group_new (chain->dbin, chain);
3513   } else if (!chain->active_group->overrun
3514       && !chain->active_group->no_more_pads) {
3515     group = chain->active_group;
3516   } else {
3517     GList *iter;
3518     group = NULL;
3519     for (iter = chain->next_groups; iter; iter = g_list_next (iter)) {
3520       GstDecodeGroup *next_group = iter->data;
3521 
3522       if (!next_group->overrun && !next_group->no_more_pads) {
3523         group = next_group;
3524         break;
3525       }
3526     }
3527   }
3528   if (!group) {
3529     group = gst_decode_group_new (chain->dbin, chain);
3530     chain->next_groups = g_list_append (chain->next_groups, group);
3531   }
3532 
3533   return group;
3534 }
3535 
3536 static void gst_decode_group_free_internal (GstDecodeGroup * group,
3537     gboolean hide);
3538 
3539 static void
gst_decode_chain_unref(GstDecodeChain * chain)3540 gst_decode_chain_unref (GstDecodeChain * chain)
3541 {
3542   if (g_atomic_int_dec_and_test (&chain->refs)) {
3543     g_mutex_clear (&chain->lock);
3544     g_slice_free (GstDecodeChain, chain);
3545   }
3546 }
3547 
3548 static GstDecodeChain *
gst_decode_chain_ref(GstDecodeChain * chain)3549 gst_decode_chain_ref (GstDecodeChain * chain)
3550 {
3551   g_atomic_int_inc (&chain->refs);
3552   return chain;
3553 }
3554 
3555 static void
gst_decode_chain_free_internal(GstDecodeChain * chain,gboolean hide)3556 gst_decode_chain_free_internal (GstDecodeChain * chain, gboolean hide)
3557 {
3558   GList *l, *set_to_null = NULL;
3559 
3560   CHAIN_MUTEX_LOCK (chain);
3561 
3562   GST_DEBUG_OBJECT (chain->dbin, "%s chain %p", (hide ? "Hiding" : "Freeing"),
3563       chain);
3564 
3565   if (chain->active_group) {
3566     gst_decode_group_free_internal (chain->active_group, hide);
3567     if (!hide)
3568       chain->active_group = NULL;
3569   }
3570 
3571   for (l = chain->next_groups; l; l = l->next) {
3572     gst_decode_group_free_internal ((GstDecodeGroup *) l->data, hide);
3573     if (!hide)
3574       l->data = NULL;
3575   }
3576   if (!hide) {
3577     g_list_free (chain->next_groups);
3578     chain->next_groups = NULL;
3579   }
3580 
3581   if (!hide) {
3582     for (l = chain->old_groups; l; l = l->next) {
3583       GstDecodeGroup *group = l->data;
3584 
3585       gst_decode_group_free (group);
3586     }
3587     g_list_free (chain->old_groups);
3588     chain->old_groups = NULL;
3589   }
3590 
3591   for (l = chain->pending_pads; l; l = l->next) {
3592     GstPendingPad *ppad = l->data;
3593     gst_pending_pad_free (ppad);
3594     l->data = NULL;
3595   }
3596   g_list_free (chain->pending_pads);
3597   chain->pending_pads = NULL;
3598 
3599   for (l = chain->elements; l; l = l->next) {
3600     GstDecodeElement *delem = l->data;
3601     GstElement *element = delem->element;
3602 
3603     if (delem->pad_added_id)
3604       g_signal_handler_disconnect (element, delem->pad_added_id);
3605     delem->pad_added_id = 0;
3606     if (delem->pad_removed_id)
3607       g_signal_handler_disconnect (element, delem->pad_removed_id);
3608     delem->pad_removed_id = 0;
3609     if (delem->no_more_pads_id)
3610       g_signal_handler_disconnect (element, delem->no_more_pads_id);
3611     delem->no_more_pads_id = 0;
3612 
3613     if (delem->capsfilter) {
3614       if (GST_OBJECT_PARENT (delem->capsfilter) ==
3615           GST_OBJECT_CAST (chain->dbin))
3616         gst_bin_remove (GST_BIN_CAST (chain->dbin), delem->capsfilter);
3617       if (!hide) {
3618         set_to_null =
3619             g_list_append (set_to_null, gst_object_ref (delem->capsfilter));
3620       }
3621     }
3622 
3623 #ifdef OHOS_OPT_COMPAT
3624     /* ohos.opt.compat.0024
3625       When changing the codec, the hardware plug-in is removed but does not stop,
3626       which will cause the newly created hardware plug-in to report that there is still a buffer outside
3627       when negotiating the pool with the surfacesink, resulting in the failure of the negotiation pool */
3628     if (GST_OBJECT_PARENT (element) == GST_OBJECT_CAST (chain->dbin)) {
3629       gst_element_set_state (element, GST_STATE_NULL);
3630       gst_bin_remove (GST_BIN_CAST (chain->dbin), element);
3631     }
3632 #else
3633     if (GST_OBJECT_PARENT (element) == GST_OBJECT_CAST (chain->dbin))
3634       gst_bin_remove (GST_BIN_CAST (chain->dbin), element);
3635 #endif
3636 
3637     if (!hide) {
3638       set_to_null = g_list_append (set_to_null, gst_object_ref (element));
3639     }
3640 
3641     SUBTITLE_LOCK (chain->dbin);
3642     /* remove possible subtitle element */
3643     chain->dbin->subtitles = g_list_remove (chain->dbin->subtitles, element);
3644     SUBTITLE_UNLOCK (chain->dbin);
3645 
3646     if (!hide) {
3647       if (delem->capsfilter) {
3648         gst_object_unref (delem->capsfilter);
3649         delem->capsfilter = NULL;
3650       }
3651 
3652       gst_object_unref (element);
3653       l->data = NULL;
3654 
3655       g_slice_free (GstDecodeElement, delem);
3656     }
3657   }
3658   if (!hide) {
3659     g_list_free (chain->elements);
3660     chain->elements = NULL;
3661   }
3662 
3663   if (chain->endpad) {
3664     if (chain->endpad->exposed) {
3665       gst_element_remove_pad (GST_ELEMENT_CAST (chain->dbin),
3666           GST_PAD_CAST (chain->endpad));
3667     }
3668 
3669     decode_pad_set_target (chain->endpad, NULL);
3670     chain->endpad->exposed = FALSE;
3671     if (!hide) {
3672       gst_object_unref (chain->endpad);
3673       chain->endpad = NULL;
3674     }
3675   }
3676 
3677   if (!hide && chain->current_pad) {
3678     gst_object_unref (chain->current_pad);
3679     chain->current_pad = NULL;
3680   }
3681 
3682   if (chain->pad) {
3683     gst_object_unref (chain->pad);
3684     chain->pad = NULL;
3685   }
3686 
3687   if (chain->endcaps) {
3688     gst_caps_unref (chain->endcaps);
3689     chain->endcaps = NULL;
3690   }
3691   g_free (chain->deadend_details);
3692   chain->deadend_details = NULL;
3693 
3694   GST_DEBUG_OBJECT (chain->dbin, "%s chain %p", (hide ? "Hidden" : "Freed"),
3695       chain);
3696   CHAIN_MUTEX_UNLOCK (chain);
3697 
3698   while (set_to_null) {
3699     GstElement *element = set_to_null->data;
3700     set_to_null = g_list_delete_link (set_to_null, set_to_null);
3701     gst_element_set_state (element, GST_STATE_NULL);
3702     gst_object_unref (element);
3703   }
3704 
3705   if (!hide)
3706     gst_decode_chain_unref (chain);
3707 }
3708 
3709 /* gst_decode_chain_free:
3710  *
3711  * Completely frees and removes the chain and all
3712  * child groups from decodebin.
3713  *
3714  * MT-safe, don't hold the chain lock or any child chain's lock
3715  * when calling this!
3716  */
3717 static void
gst_decode_chain_free(GstDecodeChain * chain)3718 gst_decode_chain_free (GstDecodeChain * chain)
3719 {
3720   gst_decode_chain_free_internal (chain, FALSE);
3721 }
3722 
3723 /* gst_decode_chain_new:
3724  *
3725  * Creates a new decode chain and initializes it.
3726  *
3727  * It's up to the caller to add it to the list of child chains of
3728  * a group!
3729  */
3730 static GstDecodeChain *
gst_decode_chain_new(GstDecodeBin * dbin,GstDecodeGroup * parent,GstPad * pad)3731 gst_decode_chain_new (GstDecodeBin * dbin, GstDecodeGroup * parent,
3732     GstPad * pad)
3733 {
3734   GstDecodeChain *chain = g_slice_new0 (GstDecodeChain);
3735 
3736   GST_DEBUG_OBJECT (dbin, "Creating new chain %p with parent group %p", chain,
3737       parent);
3738 
3739   chain->dbin = dbin;
3740   chain->parent = parent;
3741   chain->refs = 1;
3742   g_mutex_init (&chain->lock);
3743   chain->pad = gst_object_ref (pad);
3744 
3745   return chain;
3746 }
3747 
3748 /****
3749  * GstDecodeGroup functions
3750  ****/
3751 
3752 /* The overrun callback is used to expose groups that have not yet had their
3753  * no_more_pads called while the (large) multiqueue overflowed. When this
3754  * happens we must assume that the no_more_pads will not arrive anymore and we
3755  * must expose the pads that we have.
3756  */
3757 static void
multi_queue_overrun_cb(GstElement * queue,GstDecodeGroup * group)3758 multi_queue_overrun_cb (GstElement * queue, GstDecodeGroup * group)
3759 {
3760   GstDecodeBin *dbin;
3761 
3762   dbin = group->dbin;
3763 
3764   GST_LOG_OBJECT (dbin, "multiqueue '%s' (%p) is full", GST_OBJECT_NAME (queue),
3765       queue);
3766 
3767   group->overrun = TRUE;
3768   /* this group has prerolled enough to not need more pads,
3769    * we can probably set its buffering state to playing now */
3770   GST_DEBUG_OBJECT (group->dbin, "Setting group %p multiqueue to "
3771       "'playing' buffering mode", group);
3772   decodebin_set_queue_size (group->dbin, group->multiqueue, FALSE,
3773       (group->parent ? group->parent->seekable : TRUE));
3774 
3775   /* FIXME: We should make sure that everything gets exposed now
3776    * even if child chains are not complete because the will never
3777    * be complete! Ignore any non-complete chains when exposing
3778    * and never expose them later
3779    */
3780 
3781   EXPOSE_LOCK (dbin);
3782   if (dbin->decode_chain) {
3783     if (gst_decode_chain_is_complete (dbin->decode_chain)) {
3784       if (!gst_decode_bin_expose (dbin))
3785         GST_WARNING_OBJECT (dbin, "Couldn't expose group");
3786     }
3787   }
3788   EXPOSE_UNLOCK (dbin);
3789 }
3790 
3791 static void
gst_decode_group_free_internal(GstDecodeGroup * group,gboolean hide)3792 gst_decode_group_free_internal (GstDecodeGroup * group, gboolean hide)
3793 {
3794   GList *l;
3795 
3796   GST_DEBUG_OBJECT (group->dbin, "%s group %p", (hide ? "Hiding" : "Freeing"),
3797       group);
3798 
3799   if (!hide) {
3800     for (l = group->demuxer_pad_probe_ids; l != NULL; l = l->next) {
3801       GstDemuxerPad *demuxer_pad = l->data;
3802       GstPad *sinkpad = g_weak_ref_get (&demuxer_pad->weakPad);
3803 
3804       if (sinkpad != NULL) {
3805         gst_pad_remove_probe (sinkpad, demuxer_pad->event_probe_id);
3806         gst_pad_remove_probe (sinkpad, demuxer_pad->query_probe_id);
3807         g_weak_ref_clear (&demuxer_pad->weakPad);
3808         gst_object_unref (sinkpad);
3809       }
3810       g_free (demuxer_pad);
3811     }
3812     g_list_free (group->demuxer_pad_probe_ids);
3813     group->demuxer_pad_probe_ids = NULL;
3814   }
3815 
3816   for (l = group->children; l; l = l->next) {
3817     GstDecodeChain *chain = (GstDecodeChain *) l->data;
3818 
3819     gst_decode_chain_free_internal (chain, hide);
3820     if (!hide)
3821       l->data = NULL;
3822   }
3823   if (!hide) {
3824     g_list_free (group->children);
3825     group->children = NULL;
3826   }
3827 
3828   if (!hide) {
3829     for (l = group->reqpads; l; l = l->next) {
3830       GstPad *pad = l->data;
3831 
3832       gst_element_release_request_pad (group->multiqueue, pad);
3833       gst_object_unref (pad);
3834       l->data = NULL;
3835     }
3836     g_list_free (group->reqpads);
3837     group->reqpads = NULL;
3838   }
3839 
3840   if (group->multiqueue) {
3841     if (group->overrunsig) {
3842       g_signal_handler_disconnect (group->multiqueue, group->overrunsig);
3843       group->overrunsig = 0;
3844     }
3845 
3846     if (GST_OBJECT_PARENT (group->multiqueue) == GST_OBJECT_CAST (group->dbin))
3847       gst_bin_remove (GST_BIN_CAST (group->dbin), group->multiqueue);
3848     if (!hide) {
3849       gst_element_set_state (group->multiqueue, GST_STATE_NULL);
3850       gst_object_unref (group->multiqueue);
3851       group->multiqueue = NULL;
3852     }
3853   }
3854 
3855   GST_DEBUG_OBJECT (group->dbin, "%s group %p", (hide ? "Hid" : "Freed"),
3856       group);
3857   if (!hide)
3858     g_slice_free (GstDecodeGroup, group);
3859 }
3860 
3861 /* gst_decode_group_free:
3862  *
3863  * Completely frees and removes the decode group and all
3864  * it's children.
3865  *
3866  * Never call this from any streaming thread!
3867  *
3868  * Not MT-safe, call with parent's chain lock!
3869  */
3870 static void
gst_decode_group_free(GstDecodeGroup * group)3871 gst_decode_group_free (GstDecodeGroup * group)
3872 {
3873   gst_decode_group_free_internal (group, FALSE);
3874 }
3875 
3876 /* gst_decode_group_hide:
3877  *
3878  * Hide the decode group only, this means that
3879  * all child endpads are removed from decodebin
3880  * and all signals are unconnected.
3881  *
3882  * No element is set to NULL state and completely
3883  * unrefed here.
3884  *
3885  * Can be called from streaming threads.
3886  *
3887  * Not MT-safe, call with parent's chain lock!
3888  */
3889 static void
gst_decode_group_hide(GstDecodeGroup * group)3890 gst_decode_group_hide (GstDecodeGroup * group)
3891 {
3892   gst_decode_group_free_internal (group, TRUE);
3893 }
3894 
3895 /* gst_decode_chain_free_hidden_groups:
3896  *
3897  * Frees any decode groups that were hidden previously.
3898  * This allows keeping memory use from ballooning when
3899  * switching chains repeatedly.
3900  *
3901  * A new throwaway thread will be created to free the
3902  * groups, so any delay does not block the setup of a
3903  * new group.
3904  *
3905  * Not MT-safe, call with parent's chain lock!
3906  */
3907 static void
gst_decode_chain_free_hidden_groups(GList * old_groups)3908 gst_decode_chain_free_hidden_groups (GList * old_groups)
3909 {
3910   GList *l;
3911 
3912   for (l = old_groups; l; l = l->next) {
3913     GstDecodeGroup *group = l->data;
3914 
3915     gst_decode_group_free (group);
3916   }
3917   g_list_free (old_groups);
3918 }
3919 
3920 static void
gst_decode_chain_start_free_hidden_groups_thread(GstDecodeChain * chain)3921 gst_decode_chain_start_free_hidden_groups_thread (GstDecodeChain * chain)
3922 {
3923   GThread *thread;
3924   GError *error = NULL;
3925   GList *old_groups;
3926   GstDecodeBin *dbin = chain->dbin;
3927 
3928   old_groups = chain->old_groups;
3929   if (!old_groups)
3930     return;
3931 
3932   /* If we already have a thread running, wait for it to finish */
3933   g_mutex_lock (&dbin->cleanup_lock);
3934   if (dbin->cleanup_thread) {
3935     g_thread_join (dbin->cleanup_thread);
3936     dbin->cleanup_thread = NULL;
3937   }
3938 
3939   chain->old_groups = NULL;
3940 
3941   if (dbin->shutdown) {
3942     /* If we're shutting down, add the groups to be cleaned up in the
3943      * state change handler (which *is* another thread). Also avoids
3944      * playing racy games with the state change handler */
3945     dbin->cleanup_groups = g_list_concat (dbin->cleanup_groups, old_groups);
3946     g_mutex_unlock (&dbin->cleanup_lock);
3947     return;
3948   }
3949 
3950   thread = g_thread_try_new ("free-hidden-groups",
3951       (GThreadFunc) gst_decode_chain_free_hidden_groups, old_groups, &error);
3952   if (!thread || error) {
3953     GST_ERROR ("Failed to start free-hidden-groups thread: %s",
3954         error ? error->message : "unknown reason");
3955     g_clear_error (&error);
3956     chain->old_groups = old_groups;
3957     g_mutex_unlock (&dbin->cleanup_lock);
3958     return;
3959   }
3960 
3961   dbin->cleanup_thread = thread;
3962   g_mutex_unlock (&dbin->cleanup_lock);
3963 
3964   GST_DEBUG_OBJECT (chain->dbin, "Started free-hidden-groups thread");
3965 }
3966 
3967 static void
decodebin_set_queue_size(GstDecodeBin * dbin,GstElement * multiqueue,gboolean preroll,gboolean seekable)3968 decodebin_set_queue_size (GstDecodeBin * dbin, GstElement * multiqueue,
3969     gboolean preroll, gboolean seekable)
3970 {
3971   gboolean use_buffering;
3972 
3973   /* get the current config from the multiqueue */
3974   g_object_get (multiqueue, "use-buffering", &use_buffering, NULL);
3975 
3976   decodebin_set_queue_size_full (dbin, multiqueue, use_buffering, preroll,
3977       seekable);
3978 }
3979 
3980 /* configure queue sizes, this depends on the buffering method and if we are
3981  * playing or prerolling. */
3982 static void
decodebin_set_queue_size_full(GstDecodeBin * dbin,GstElement * multiqueue,gboolean use_buffering,gboolean preroll,gboolean seekable)3983 decodebin_set_queue_size_full (GstDecodeBin * dbin, GstElement * multiqueue,
3984     gboolean use_buffering, gboolean preroll, gboolean seekable)
3985 {
3986   guint max_bytes, max_buffers;
3987   guint64 max_time;
3988 
3989   GST_DEBUG_OBJECT (multiqueue, "use buffering %d", use_buffering);
3990 
3991   if (preroll || use_buffering) {
3992     /* takes queue limits, initially we only queue up up to the max bytes limit,
3993      * with a default of 2MB. we use the same values for buffering mode. */
3994     if (preroll || (max_bytes = dbin->max_size_bytes) == 0)
3995       max_bytes = AUTO_PREROLL_SIZE_BYTES;
3996     if (preroll || (max_buffers = dbin->max_size_buffers) == 0)
3997       max_buffers = AUTO_PREROLL_SIZE_BUFFERS;
3998     if (preroll || (max_time = dbin->max_size_time) == 0) {
3999       if (dbin->use_buffering && !preroll)
4000         max_time = 5 * GST_SECOND;
4001       else
4002         max_time = seekable ? AUTO_PREROLL_SEEKABLE_SIZE_TIME :
4003             AUTO_PREROLL_NOT_SEEKABLE_SIZE_TIME;
4004     }
4005   } else {
4006     /* update runtime limits. At runtime, we try to keep the amount of buffers
4007      * in the queues as low as possible (but at least 5 buffers). */
4008     if (dbin->use_buffering)
4009       max_bytes = 0;
4010     else if ((max_bytes = dbin->max_size_bytes) == 0)
4011       max_bytes = AUTO_PLAY_SIZE_BYTES;
4012     if ((max_buffers = dbin->max_size_buffers) == 0)
4013       max_buffers = AUTO_PLAY_SIZE_BUFFERS;
4014     /* this is a multiqueue with disabled buffering, don't limit max_time */
4015     if (dbin->use_buffering)
4016       max_time = 0;
4017     else if ((max_time = dbin->max_size_time) == 0)
4018       max_time = AUTO_PLAY_SIZE_TIME;
4019   }
4020 
4021   GST_DEBUG_OBJECT (multiqueue, "setting limits %u bytes, %u buffers, "
4022       "%" G_GUINT64_FORMAT " time", max_bytes, max_buffers, max_time);
4023   g_object_set (multiqueue,
4024       "max-size-bytes", max_bytes, "max-size-time", max_time,
4025       "max-size-buffers", max_buffers, NULL);
4026 }
4027 
4028 /* gst_decode_group_new:
4029  * @dbin: Parent decodebin
4030  * @parent: Parent chain or %NULL
4031  *
4032  * Creates a new GstDecodeGroup. It is up to the caller to add it to the list
4033  * of groups.
4034  */
4035 static GstDecodeGroup *
gst_decode_group_new(GstDecodeBin * dbin,GstDecodeChain * parent)4036 gst_decode_group_new (GstDecodeBin * dbin, GstDecodeChain * parent)
4037 {
4038   GstDecodeGroup *group = g_slice_new0 (GstDecodeGroup);
4039   GstElement *mq;
4040   gboolean seekable;
4041 
4042   GST_DEBUG_OBJECT (dbin, "Creating new group %p with parent chain %p", group,
4043       parent);
4044 
4045   group->dbin = dbin;
4046   group->parent = parent;
4047 
4048   mq = group->multiqueue = gst_element_factory_make ("multiqueue", NULL);
4049   if (G_UNLIKELY (!group->multiqueue))
4050     goto missing_multiqueue;
4051 
4052   /* configure queue sizes for preroll */
4053   seekable = FALSE;
4054   if (parent && parent->demuxer) {
4055     GstElement *element =
4056         ((GstDecodeElement *) parent->elements->data)->element;
4057     GstPad *pad = gst_element_get_static_pad (element, "sink");
4058     if (pad) {
4059       seekable = parent->seekable = check_upstream_seekable (dbin, pad);
4060       gst_object_unref (pad);
4061     }
4062   }
4063   decodebin_set_queue_size_full (dbin, mq, FALSE, TRUE, seekable);
4064 
4065   group->overrunsig = g_signal_connect (mq, "overrun",
4066       G_CALLBACK (multi_queue_overrun_cb), group);
4067   group->demuxer_pad_probe_ids = NULL;
4068 
4069   gst_element_set_state (mq, GST_STATE_PAUSED);
4070   gst_bin_add (GST_BIN (dbin), gst_object_ref (mq));
4071 
4072   return group;
4073 
4074   /* ERRORS */
4075 missing_multiqueue:
4076   {
4077     gst_element_post_message (GST_ELEMENT_CAST (dbin),
4078         gst_missing_element_message_new (GST_ELEMENT_CAST (dbin),
4079             "multiqueue"));
4080     GST_ELEMENT_ERROR (dbin, CORE, MISSING_PLUGIN, (NULL), ("no multiqueue!"));
4081     g_slice_free (GstDecodeGroup, group);
4082     return NULL;
4083   }
4084 }
4085 
4086 /* gst_decode_group_control_demuxer_pad
4087  *
4088  * Adds a new demuxer srcpad to the given group.
4089  *
4090  * Returns the srcpad of the multiqueue corresponding the given pad.
4091  * Returns NULL if there was an error.
4092  */
4093 static GstPad *
gst_decode_group_control_demuxer_pad(GstDecodeGroup * group,GstPad * pad)4094 gst_decode_group_control_demuxer_pad (GstDecodeGroup * group, GstPad * pad)
4095 {
4096   GstDecodeBin *dbin;
4097   GstDemuxerPad *demuxer_pad;
4098   GstPad *srcpad, *sinkpad;
4099   GstIterator *it = NULL;
4100   GValue item = { 0, };
4101 
4102   dbin = group->dbin;
4103 
4104   GST_LOG_OBJECT (dbin, "group:%p pad %s:%s", group, GST_DEBUG_PAD_NAME (pad));
4105 
4106   srcpad = NULL;
4107 
4108   if (G_UNLIKELY (!group->multiqueue))
4109     return NULL;
4110 
4111   if (!(sinkpad =
4112           gst_element_request_pad_simple (group->multiqueue, "sink_%u"))) {
4113     GST_ERROR_OBJECT (dbin, "Couldn't get sinkpad from multiqueue");
4114     return NULL;
4115   }
4116 
4117   if ((gst_pad_link_full (pad, sinkpad,
4118               GST_PAD_LINK_CHECK_NOTHING) != GST_PAD_LINK_OK)) {
4119     GST_ERROR_OBJECT (dbin, "Couldn't link demuxer and multiqueue");
4120     goto error;
4121   }
4122 
4123   it = gst_pad_iterate_internal_links (sinkpad);
4124 
4125   if (!it || (gst_iterator_next (it, &item)) != GST_ITERATOR_OK
4126       || ((srcpad = g_value_dup_object (&item)) == NULL)) {
4127     GST_ERROR_OBJECT (dbin,
4128         "Couldn't get srcpad from multiqueue for sinkpad %" GST_PTR_FORMAT,
4129         sinkpad);
4130     goto error;
4131   }
4132 
4133   CHAIN_MUTEX_LOCK (group->parent);
4134 
4135   /* Note: GWeakRefs can't be moved in memory once they're in use, so do a
4136    * dedicated alloc for the GstDemuxerPad struct that contains it */
4137   demuxer_pad = g_new0 (GstDemuxerPad, 1);
4138   demuxer_pad->event_probe_id = gst_pad_add_probe (sinkpad,
4139       GST_PAD_PROBE_TYPE_EVENT_UPSTREAM, sink_pad_event_probe, group, NULL);
4140   demuxer_pad->query_probe_id = gst_pad_add_probe (sinkpad,
4141       GST_PAD_PROBE_TYPE_QUERY_UPSTREAM, sink_pad_query_probe, group, NULL);
4142 
4143   g_weak_ref_set (&demuxer_pad->weakPad, sinkpad);
4144   group->demuxer_pad_probe_ids =
4145       g_list_prepend (group->demuxer_pad_probe_ids, demuxer_pad);
4146 
4147   group->reqpads = g_list_prepend (group->reqpads, gst_object_ref (sinkpad));
4148   CHAIN_MUTEX_UNLOCK (group->parent);
4149 
4150 beach:
4151   if (G_IS_VALUE (&item))
4152     g_value_unset (&item);
4153   if (it)
4154     gst_iterator_free (it);
4155   gst_object_unref (sinkpad);
4156   return srcpad;
4157 
4158 error:
4159   gst_element_release_request_pad (group->multiqueue, sinkpad);
4160   goto beach;
4161 }
4162 
4163 /* gst_decode_group_is_complete:
4164  *
4165  * Checks if the group is complete, this means that
4166  * a) overrun of the multiqueue or no-more-pads happened
4167  * b) all child chains are complete
4168  *
4169  * Not MT-safe, always call with decodebin expose lock
4170  */
4171 static gboolean
gst_decode_group_is_complete(GstDecodeGroup * group)4172 gst_decode_group_is_complete (GstDecodeGroup * group)
4173 {
4174   GList *l;
4175   gboolean complete = TRUE;
4176 
4177   if (!group->overrun && !group->no_more_pads) {
4178     complete = FALSE;
4179     goto out;
4180   }
4181 
4182   for (l = group->children; l; l = l->next) {
4183     GstDecodeChain *chain = l->data;
4184 
4185     if (!gst_decode_chain_is_complete (chain)) {
4186       complete = FALSE;
4187       goto out;
4188     }
4189   }
4190 
4191 out:
4192   GST_DEBUG_OBJECT (group->dbin, "Group %p is complete: %d", group, complete);
4193   return complete;
4194 }
4195 
4196 /* gst_decode_chain_is_complete:
4197  *
4198  * Returns TRUE if the chain is complete, this means either
4199  * a) This chain is a dead end, i.e. we have no suitable plugins
4200  * b) This chain ends in an endpad and this is blocked or exposed
4201  *
4202  * Not MT-safe, always call with decodebin expose lock
4203  */
4204 static gboolean
gst_decode_chain_is_complete(GstDecodeChain * chain)4205 gst_decode_chain_is_complete (GstDecodeChain * chain)
4206 {
4207   gboolean complete = FALSE;
4208 
4209   CHAIN_MUTEX_LOCK (chain);
4210   if (chain->dbin->shutdown)
4211     goto out;
4212 
4213   if (chain->deadend) {
4214     complete = TRUE;
4215     goto out;
4216   }
4217 
4218   if (chain->endpad && gst_decode_pad_is_exposable (chain->endpad)) {
4219     complete = TRUE;
4220     goto out;
4221   }
4222 
4223   if (chain->demuxer) {
4224     if (chain->active_group
4225         && gst_decode_group_is_complete (chain->active_group)) {
4226       complete = TRUE;
4227       goto out;
4228     }
4229   }
4230 
4231 out:
4232   CHAIN_MUTEX_UNLOCK (chain);
4233   GST_DEBUG_OBJECT (chain->dbin, "Chain %p is complete: %d", chain, complete);
4234   return complete;
4235 }
4236 
4237 /* Flushing group/chains */
4238 static void
flush_group(GstDecodeGroup * group,gboolean flushing)4239 flush_group (GstDecodeGroup * group, gboolean flushing)
4240 {
4241   GList *tmp;
4242 
4243   GST_DEBUG ("group %p flushing:%d", group, flushing);
4244 
4245   if (group->drained == flushing)
4246     return;
4247   for (tmp = group->children; tmp; tmp = tmp->next) {
4248     GstDecodeChain *chain = (GstDecodeChain *) tmp->data;
4249     flush_chain (chain, flushing);
4250   }
4251   GST_DEBUG ("Setting group %p to drained:%d", group, flushing);
4252   group->drained = flushing;
4253 }
4254 
4255 static void
flush_chain(GstDecodeChain * chain,gboolean flushing)4256 flush_chain (GstDecodeChain * chain, gboolean flushing)
4257 {
4258   GList *tmp;
4259   GstDecodeBin *dbin = chain->dbin;
4260 
4261   GST_DEBUG_OBJECT (dbin, "chain %p (pad %s:%s) flushing:%d", chain,
4262       GST_DEBUG_PAD_NAME (chain->pad), flushing);
4263   if (chain->drained == flushing)
4264     return;
4265   /* if unflushing, check if we should switch to last group */
4266   if (flushing == FALSE && chain->next_groups) {
4267     GstDecodeGroup *target_group =
4268         (GstDecodeGroup *) g_list_last (chain->next_groups)->data;
4269     gst_decode_chain_start_free_hidden_groups_thread (chain);
4270     /* Hide active group (we're sure it's not that one we'll be using) */
4271     GST_DEBUG_OBJECT (dbin, "Switching from active group %p to group %p",
4272         chain->active_group, target_group);
4273     gst_decode_group_hide (chain->active_group);
4274     chain->old_groups = g_list_prepend (chain->old_groups, chain->active_group);
4275     chain->active_group = target_group;
4276     /* Hide all groups but the target_group */
4277     for (tmp = chain->next_groups; tmp; tmp = tmp->next) {
4278       GstDecodeGroup *group = (GstDecodeGroup *) tmp->data;
4279       if (group != target_group) {
4280         gst_decode_group_hide (group);
4281         chain->old_groups = g_list_prepend (chain->old_groups, group);
4282       }
4283     }
4284     /* Clear next groups */
4285     g_list_free (chain->next_groups);
4286     chain->next_groups = NULL;
4287   }
4288   /* Mark all groups as flushing */
4289   if (chain->active_group)
4290     flush_group (chain->active_group, flushing);
4291   for (tmp = chain->next_groups; tmp; tmp = tmp->next) {
4292     GstDecodeGroup *group = (GstDecodeGroup *) tmp->data;
4293     flush_group (group, flushing);
4294   }
4295   GST_DEBUG ("Setting chain %p to drained:%d", chain, flushing);
4296   chain->drained = flushing;
4297 }
4298 
4299 static gboolean
4300 drain_and_switch_chains (GstDecodeChain * chain, GstDecodePad * drainpad,
4301     gboolean * last_group, gboolean * drained, gboolean * switched);
4302 /* drain_and_switch_chains/groups:
4303  *
4304  * CALL WITH CHAIN LOCK (or group parent) TAKEN !
4305  *
4306  * Goes down the chains/groups until it finds the chain
4307  * to which the drainpad belongs.
4308  *
4309  * It marks that pad/chain as drained and then will figure
4310  * out which group to switch to or not.
4311  *
4312  * last_chain will be set to TRUE if the group to which the
4313  * pad belongs is the last one.
4314  *
4315  * drained will be set to TRUE if the chain/group is drained.
4316  *
4317  * Returns: TRUE if the chain contained the target pad */
4318 static gboolean
drain_and_switch_group(GstDecodeGroup * group,GstDecodePad * drainpad,gboolean * last_group,gboolean * drained,gboolean * switched)4319 drain_and_switch_group (GstDecodeGroup * group, GstDecodePad * drainpad,
4320     gboolean * last_group, gboolean * drained, gboolean * switched)
4321 {
4322   gboolean handled = FALSE;
4323   GList *tmp;
4324 
4325   GST_DEBUG ("Checking group %p (target pad %s:%s)",
4326       group, GST_DEBUG_PAD_NAME (drainpad));
4327 
4328   /* Definitely can't be in drained groups */
4329   if (G_UNLIKELY (group->drained)) {
4330     goto beach;
4331   }
4332 
4333   /* Figure out if all our chains are drained with the
4334    * new information */
4335   group->drained = TRUE;
4336   for (tmp = group->children; tmp; tmp = tmp->next) {
4337     GstDecodeChain *chain = (GstDecodeChain *) tmp->data;
4338     gboolean subdrained = FALSE;
4339 
4340     handled |=
4341         drain_and_switch_chains (chain, drainpad, last_group, &subdrained,
4342         switched);
4343     if (!subdrained)
4344       group->drained = FALSE;
4345   }
4346 
4347 beach:
4348   GST_DEBUG ("group %p (last_group:%d, drained:%d, switched:%d, handled:%d)",
4349       group, *last_group, group->drained, *switched, handled);
4350   *drained = group->drained;
4351   return handled;
4352 }
4353 
4354 static gboolean
drain_and_switch_chains(GstDecodeChain * chain,GstDecodePad * drainpad,gboolean * last_group,gboolean * drained,gboolean * switched)4355 drain_and_switch_chains (GstDecodeChain * chain, GstDecodePad * drainpad,
4356     gboolean * last_group, gboolean * drained, gboolean * switched)
4357 {
4358   gboolean handled = FALSE;
4359   GstDecodeBin *dbin = chain->dbin;
4360 
4361   GST_DEBUG ("Checking chain %p %s:%s (target pad %s:%s)",
4362       chain, GST_DEBUG_PAD_NAME (chain->pad), GST_DEBUG_PAD_NAME (drainpad));
4363 
4364   CHAIN_MUTEX_LOCK (chain);
4365 
4366   if (chain->pad_probe_id) {
4367     gst_pad_remove_probe (chain->pad, chain->pad_probe_id);
4368     chain->pad_probe_id = 0;
4369   }
4370 
4371   /* Definitely can't be in drained chains */
4372   if (G_UNLIKELY (chain->drained)) {
4373     goto beach;
4374   }
4375 
4376   if (chain->endpad) {
4377     /* Check if we're reached the target endchain */
4378     if (drainpad != NULL && chain == drainpad->chain) {
4379       GST_DEBUG ("Found the target chain");
4380       drainpad->drained = TRUE;
4381       handled = TRUE;
4382     }
4383 
4384     chain->drained = chain->endpad->drained;
4385     goto beach;
4386   }
4387 
4388   /* We known there are groups to switch to */
4389   if (chain->next_groups)
4390     *last_group = FALSE;
4391 
4392   /* Check the active group */
4393   if (chain->active_group) {
4394     gboolean subdrained = FALSE;
4395     handled = drain_and_switch_group (chain->active_group, drainpad,
4396         last_group, &subdrained, switched);
4397 
4398     /* The group is drained, see if we can switch to another */
4399     if ((handled || drainpad == NULL) && subdrained && !*switched) {
4400       if (chain->next_groups) {
4401         /* Switch to next group */
4402         GST_DEBUG_OBJECT (dbin, "Hiding current group %p", chain->active_group);
4403         gst_decode_group_hide (chain->active_group);
4404         chain->old_groups =
4405             g_list_prepend (chain->old_groups, chain->active_group);
4406         GST_DEBUG_OBJECT (dbin, "Switching to next group %p",
4407             chain->next_groups->data);
4408         chain->active_group = chain->next_groups->data;
4409         chain->next_groups =
4410             g_list_delete_link (chain->next_groups, chain->next_groups);
4411         gst_decode_chain_start_free_hidden_groups_thread (chain);
4412         *switched = TRUE;
4413         chain->drained = FALSE;
4414       } else {
4415         GST_DEBUG ("Group %p was the last in chain %p", chain->active_group,
4416             chain);
4417         chain->drained = TRUE;
4418         /* We're drained ! */
4419       }
4420     } else {
4421       if (subdrained && !chain->next_groups)
4422         *drained = TRUE;
4423     }
4424   }
4425 
4426 beach:
4427   CHAIN_MUTEX_UNLOCK (chain);
4428 
4429   GST_DEBUG ("Chain %p (handled:%d, last_group:%d, drained:%d, switched:%d)",
4430       chain, handled, *last_group, chain->drained, *switched);
4431 
4432   *drained = chain->drained;
4433 
4434   if (*drained && !chain->parent)       /* only emit signal from top chain */
4435     g_signal_emit (dbin, gst_decode_bin_signals[SIGNAL_DRAINED], 0, NULL);
4436 
4437   return handled;
4438 }
4439 
4440 /* check if the group is drained, meaning all pads have seen an EOS
4441  * event.  */
4442 static gboolean
gst_decode_pad_handle_eos(GstDecodePad * pad)4443 gst_decode_pad_handle_eos (GstDecodePad * pad)
4444 {
4445   gboolean last_group = TRUE;
4446   gboolean switched = FALSE;
4447   gboolean drained = FALSE;
4448   GstDecodeChain *chain = pad->chain;
4449   GstDecodeBin *dbin = chain->dbin;
4450   GstEvent *tmp;
4451 
4452   GST_LOG_OBJECT (dbin, "pad %p", pad);
4453 
4454   /* Send a stream-group-done event in case downstream needs
4455    * to unblock before we can drain */
4456   tmp = gst_pad_get_sticky_event (GST_PAD (pad), GST_EVENT_STREAM_START, 0);
4457   if (tmp) {
4458     guint group_id;
4459     if (gst_event_parse_group_id (tmp, &group_id)) {
4460       GstPad *peer = gst_pad_get_peer (GST_PAD (pad));
4461 
4462       if (peer) {
4463         GST_DEBUG_OBJECT (dbin,
4464             "Sending stream-group-done for group %u to pad %"
4465             GST_PTR_FORMAT, group_id, pad);
4466         gst_pad_send_event (peer, gst_event_new_stream_group_done (group_id));
4467         gst_object_unref (peer);
4468       }
4469     } else {
4470       GST_DEBUG_OBJECT (dbin,
4471           "No group ID to send stream-group-done on pad %" GST_PTR_FORMAT, pad);
4472     }
4473     gst_event_unref (tmp);
4474   }
4475 
4476   EXPOSE_LOCK (dbin);
4477   if (dbin->decode_chain) {
4478     drain_and_switch_chains (dbin->decode_chain, pad, &last_group, &drained,
4479         &switched);
4480 
4481     if (switched) {
4482       /* If we resulted in a group switch, expose what's needed */
4483       if (gst_decode_chain_is_complete (dbin->decode_chain))
4484         gst_decode_bin_expose (dbin);
4485     }
4486   }
4487   EXPOSE_UNLOCK (dbin);
4488 
4489   return last_group;
4490 }
4491 
4492 /* gst_decode_group_is_drained:
4493  *
4494  * Check is this group is drained and cache this result.
4495  * The group is drained if all child chains are drained.
4496  *
4497  * Not MT-safe, call with group->parent's lock */
4498 static gboolean
gst_decode_group_is_drained(GstDecodeGroup * group)4499 gst_decode_group_is_drained (GstDecodeGroup * group)
4500 {
4501   GList *l;
4502   gboolean drained = TRUE;
4503 
4504   if (group->drained) {
4505     drained = TRUE;
4506     goto out;
4507   }
4508 
4509   for (l = group->children; l; l = l->next) {
4510     GstDecodeChain *chain = l->data;
4511 
4512     CHAIN_MUTEX_LOCK (chain);
4513     if (!gst_decode_chain_is_drained (chain))
4514       drained = FALSE;
4515     CHAIN_MUTEX_UNLOCK (chain);
4516     if (!drained)
4517       goto out;
4518   }
4519   group->drained = drained;
4520 
4521 out:
4522   GST_DEBUG_OBJECT (group->dbin, "Group %p is drained: %d", group, drained);
4523   return drained;
4524 }
4525 
4526 /* gst_decode_chain_is_drained:
4527  *
4528  * Check is the chain is drained, which means that
4529  * either
4530  *
4531  * a) it's endpad is drained
4532  * b) there are no pending pads, the active group is drained
4533  *    and there are no next groups
4534  *
4535  * Not MT-safe, call with chain lock
4536  */
4537 static gboolean
gst_decode_chain_is_drained(GstDecodeChain * chain)4538 gst_decode_chain_is_drained (GstDecodeChain * chain)
4539 {
4540   gboolean drained = FALSE;
4541 
4542   if (chain->endpad) {
4543     drained = chain->endpad->drained;
4544     goto out;
4545   }
4546 
4547   if (chain->pending_pads) {
4548     drained = FALSE;
4549     goto out;
4550   }
4551 
4552   if (chain->active_group && gst_decode_group_is_drained (chain->active_group)
4553       && !chain->next_groups) {
4554     drained = TRUE;
4555     goto out;
4556   }
4557 
4558 out:
4559   GST_DEBUG_OBJECT (chain->dbin, "Chain %p is drained: %d", chain, drained);
4560   return drained;
4561 }
4562 
4563 static gboolean
gst_decode_group_reset_buffering(GstDecodeGroup * group)4564 gst_decode_group_reset_buffering (GstDecodeGroup * group)
4565 {
4566   GList *l;
4567   gboolean ret = TRUE;
4568 
4569   GST_DEBUG_OBJECT (group->dbin, "Group reset buffering %p %s", group,
4570       GST_ELEMENT_NAME (group->multiqueue));
4571   for (l = group->children; l; l = l->next) {
4572     GstDecodeChain *chain = l->data;
4573 
4574     CHAIN_MUTEX_LOCK (chain);
4575     if (!gst_decode_chain_reset_buffering (chain)) {
4576       ret = FALSE;
4577     }
4578     CHAIN_MUTEX_UNLOCK (chain);
4579   }
4580 
4581   decodebin_set_queue_size_full (group->dbin, group->multiqueue, !ret,
4582       FALSE, (group->parent ? group->parent->seekable : TRUE));
4583 
4584   if (ret) {
4585     /* all chains are buffering already, no need to do it here */
4586     g_object_set (group->multiqueue, "use-buffering", FALSE, NULL);
4587   } else {
4588 #ifdef OHOS_EXT_FUNC
4589     // ohos.ext.func.0013
4590     g_object_set (group->multiqueue, "use-buffering", TRUE,
4591         "low-percent", group->dbin->low_percent,
4592         "high-percent", group->dbin->high_percent,
4593         "mq-num-id", group->dbin->mq_num_use_buffering, NULL);
4594 
4595 	  group->dbin->mq_num_use_buffering++;
4596 #else
4597     g_object_set (group->multiqueue, "use-buffering", TRUE,
4598         "low-percent", group->dbin->low_percent,
4599         "high-percent", group->dbin->high_percent, NULL);
4600 #endif
4601   }
4602 
4603   GST_DEBUG_OBJECT (group->dbin, "Setting %s buffering to %d",
4604       GST_ELEMENT_NAME (group->multiqueue), !ret);
4605   return TRUE;
4606 }
4607 
4608 
4609 /* sort_end_pads:
4610  * GCompareFunc to use with lists of GstPad.
4611  * Sorts pads by mime type.
4612  * First video (raw, then non-raw), then audio (raw, then non-raw),
4613  * then others.
4614  *
4615  * Return: negative if a<b, 0 if a==b, positive if a>b
4616  */
4617 static gint
sort_end_pads(GstDecodePad * da,GstDecodePad * db)4618 sort_end_pads (GstDecodePad * da, GstDecodePad * db)
4619 {
4620   gint va, vb;
4621   GstCaps *capsa, *capsb;
4622   GstStructure *sa, *sb;
4623   const gchar *namea, *nameb;
4624   gchar *ida, *idb;
4625   gint ret;
4626 
4627   capsa = get_pad_caps (GST_PAD_CAST (da));
4628   capsb = get_pad_caps (GST_PAD_CAST (db));
4629 
4630   sa = gst_caps_get_structure ((const GstCaps *) capsa, 0);
4631   sb = gst_caps_get_structure ((const GstCaps *) capsb, 0);
4632 
4633   namea = gst_structure_get_name (sa);
4634   nameb = gst_structure_get_name (sb);
4635 
4636   if (g_strrstr (namea, "video/x-raw"))
4637     va = 0;
4638   else if (g_strrstr (namea, "video/"))
4639     va = 1;
4640   else if (g_strrstr (namea, "audio/x-raw"))
4641     va = 2;
4642   else if (g_strrstr (namea, "audio/"))
4643     va = 3;
4644   else
4645     va = 4;
4646 
4647   if (g_strrstr (nameb, "video/x-raw"))
4648     vb = 0;
4649   else if (g_strrstr (nameb, "video/"))
4650     vb = 1;
4651   else if (g_strrstr (nameb, "audio/x-raw"))
4652     vb = 2;
4653   else if (g_strrstr (nameb, "audio/"))
4654     vb = 3;
4655   else
4656     vb = 4;
4657 
4658   gst_caps_unref (capsa);
4659   gst_caps_unref (capsb);
4660 
4661   if (va != vb)
4662     return va - vb;
4663 
4664   /* if otherwise the same, sort by stream-id */
4665   ida = gst_pad_get_stream_id (GST_PAD_CAST (da));
4666   idb = gst_pad_get_stream_id (GST_PAD_CAST (db));
4667   ret = (ida) ? ((idb) ? strcmp (ida, idb) : -1) : 1;
4668   g_free (ida);
4669   g_free (idb);
4670 
4671   return ret;
4672 }
4673 
4674 static GstCaps *
_gst_element_get_linked_caps(GstElement * src,GstElement * sink,GstElement * capsfilter,GstPad ** srcpad)4675 _gst_element_get_linked_caps (GstElement * src, GstElement * sink,
4676     GstElement * capsfilter, GstPad ** srcpad)
4677 {
4678   GstIterator *it;
4679   GstElement *parent;
4680   GstPad *pad, *peer;
4681   gboolean done = FALSE;
4682   GstCaps *caps = NULL;
4683   GValue item = { 0, };
4684 
4685   it = gst_element_iterate_src_pads (src);
4686   while (!done) {
4687     switch (gst_iterator_next (it, &item)) {
4688       case GST_ITERATOR_OK:
4689         pad = g_value_get_object (&item);
4690         peer = gst_pad_get_peer (pad);
4691         if (peer) {
4692           parent = gst_pad_get_parent_element (peer);
4693           if (parent == sink || (capsfilter != NULL && parent == capsfilter)) {
4694             caps = gst_pad_get_current_caps (pad);
4695             *srcpad = gst_object_ref (pad);
4696             done = TRUE;
4697           }
4698 
4699           if (parent)
4700             gst_object_unref (parent);
4701           gst_object_unref (peer);
4702         }
4703         g_value_reset (&item);
4704         break;
4705       case GST_ITERATOR_RESYNC:
4706         gst_iterator_resync (it);
4707         break;
4708       case GST_ITERATOR_ERROR:
4709       case GST_ITERATOR_DONE:
4710         done = TRUE;
4711         break;
4712     }
4713   }
4714   g_value_unset (&item);
4715   gst_iterator_free (it);
4716 
4717   return caps;
4718 }
4719 
4720 /* FIXME: Invent gst_structure_take_structure() to prevent all the
4721  * structure copying for nothing
4722  */
4723 static GstStructure *
gst_decode_chain_get_topology(GstDecodeChain * chain)4724 gst_decode_chain_get_topology (GstDecodeChain * chain)
4725 {
4726   GstStructure *s, *u;
4727   GList *l;
4728   GstCaps *caps;
4729 
4730   if (G_UNLIKELY ((chain->endpad || chain->deadend)
4731           && (chain->endcaps == NULL))) {
4732     GST_WARNING ("End chain without valid caps !");
4733     return NULL;
4734   }
4735 
4736   u = gst_structure_new_id_empty (topology_structure_name);
4737 
4738   /* Now at the last element */
4739   if ((chain->elements || !chain->active_group) &&
4740       (chain->endpad || chain->deadend)) {
4741     GstPad *srcpad;
4742 
4743     s = gst_structure_new_id_empty (topology_structure_name);
4744     gst_structure_id_set (u, topology_caps, GST_TYPE_CAPS, chain->endcaps,
4745         NULL);
4746 
4747     if (chain->endpad) {
4748       gst_structure_id_set (u, topology_pad, GST_TYPE_PAD, chain->endpad, NULL);
4749 
4750       srcpad = gst_ghost_pad_get_target (GST_GHOST_PAD_CAST (chain->endpad));
4751       gst_structure_id_set (u, topology_element_srcpad, GST_TYPE_PAD,
4752           srcpad, NULL);
4753 
4754       gst_object_unref (srcpad);
4755     }
4756 
4757     gst_structure_id_set (s, topology_next, GST_TYPE_STRUCTURE, u, NULL);
4758     gst_structure_free (u);
4759     u = s;
4760   } else if (chain->active_group) {
4761     GValue list = { 0, };
4762     GValue item = { 0, };
4763 
4764     g_value_init (&list, GST_TYPE_LIST);
4765     g_value_init (&item, GST_TYPE_STRUCTURE);
4766     for (l = chain->active_group->children; l; l = l->next) {
4767       s = gst_decode_chain_get_topology (l->data);
4768       if (s) {
4769         gst_value_set_structure (&item, s);
4770         gst_value_list_append_value (&list, &item);
4771         g_value_reset (&item);
4772         gst_structure_free (s);
4773       }
4774     }
4775     gst_structure_id_set_value (u, topology_next, &list);
4776     g_value_unset (&list);
4777     g_value_unset (&item);
4778   }
4779 
4780   /* Get caps between all elements in this chain */
4781   l = (chain->elements && chain->elements->next) ? chain->elements : NULL;
4782   for (; l && l->next; l = l->next) {
4783     GstDecodeElement *delem, *delem_next;
4784     GstElement *elem, *capsfilter, *elem_next;
4785     GstCaps *caps;
4786     GstPad *srcpad;
4787 
4788     delem = l->data;
4789     elem = delem->element;
4790     delem_next = l->next->data;
4791     elem_next = delem_next->element;
4792     capsfilter = delem_next->capsfilter;
4793     srcpad = NULL;
4794 
4795     caps = _gst_element_get_linked_caps (elem_next, elem, capsfilter, &srcpad);
4796 
4797     if (caps) {
4798       s = gst_structure_new_id_empty (topology_structure_name);
4799       gst_structure_id_set (u, topology_caps, GST_TYPE_CAPS, caps, NULL);
4800       gst_caps_unref (caps);
4801 
4802       gst_structure_id_set (s, topology_next, GST_TYPE_STRUCTURE, u, NULL);
4803       gst_structure_free (u);
4804       u = s;
4805     }
4806 
4807     if (srcpad) {
4808       gst_structure_id_set (u, topology_element_srcpad, GST_TYPE_PAD, srcpad,
4809           NULL);
4810       gst_object_unref (srcpad);
4811     }
4812   }
4813 
4814   /* Caps that resulted in this chain */
4815   caps = get_pad_caps (chain->pad);
4816   if (G_UNLIKELY (!caps)) {
4817     GST_WARNING_OBJECT (chain->pad, "Couldn't get the caps of decode chain");
4818     return u;
4819   }
4820   gst_structure_id_set (u, topology_caps, GST_TYPE_CAPS, caps, NULL);
4821   gst_structure_id_set (u, topology_element_srcpad, GST_TYPE_PAD, chain->pad,
4822       NULL);
4823   gst_caps_unref (caps);
4824 
4825   return u;
4826 }
4827 
4828 static void
gst_decode_bin_post_topology_message(GstDecodeBin * dbin)4829 gst_decode_bin_post_topology_message (GstDecodeBin * dbin)
4830 {
4831   GstStructure *s;
4832   GstMessage *msg;
4833 
4834   s = gst_decode_chain_get_topology (dbin->decode_chain);
4835 
4836   if (G_UNLIKELY (s == NULL))
4837     return;
4838   msg = gst_message_new_element (GST_OBJECT (dbin), s);
4839   gst_element_post_message (GST_ELEMENT (dbin), msg);
4840 }
4841 
4842 static gboolean
debug_sticky_event(GstPad * pad,GstEvent ** event,gpointer user_data)4843 debug_sticky_event (GstPad * pad, GstEvent ** event, gpointer user_data)
4844 {
4845   GST_DEBUG_OBJECT (pad, "sticky event %s (%p)", GST_EVENT_TYPE_NAME (*event),
4846       *event);
4847   return TRUE;
4848 }
4849 
4850 
4851 /* Must only be called if the toplevel chain is complete and blocked! */
4852 /* Not MT-safe, call with decodebin expose lock! */
4853 static gboolean
gst_decode_bin_expose(GstDecodeBin * dbin)4854 gst_decode_bin_expose (GstDecodeBin * dbin)
4855 {
4856   GList *tmp, *endpads;
4857   gboolean missing_plugin;
4858   GString *missing_plugin_details;
4859   gboolean already_exposed;
4860   gboolean last_group;
4861 
4862 retry:
4863   endpads = NULL;
4864   missing_plugin = FALSE;
4865   already_exposed = TRUE;
4866   last_group = TRUE;
4867 
4868   missing_plugin_details = g_string_new ("");
4869 
4870   GST_DEBUG_OBJECT (dbin, "Exposing currently active chains/groups");
4871 
4872   /* Don't expose if we're currently shutting down */
4873   DYN_LOCK (dbin);
4874   if (G_UNLIKELY (dbin->shutdown)) {
4875     GST_WARNING_OBJECT (dbin, "Currently, shutting down, aborting exposing");
4876     DYN_UNLOCK (dbin);
4877     return FALSE;
4878   }
4879   DYN_UNLOCK (dbin);
4880 
4881   /* Get the pads that we're going to expose and mark things as exposed */
4882   if (!gst_decode_chain_expose (dbin->decode_chain, &endpads, &missing_plugin,
4883           missing_plugin_details, &last_group)) {
4884     g_list_foreach (endpads, (GFunc) gst_object_unref, NULL);
4885     g_list_free (endpads);
4886     g_string_free (missing_plugin_details, TRUE);
4887     /* Failures could be due to the fact that we are currently shutting down (recheck) */
4888     DYN_LOCK (dbin);
4889     if (G_UNLIKELY (dbin->shutdown)) {
4890       GST_WARNING_OBJECT (dbin, "Currently, shutting down, aborting exposing");
4891       DYN_UNLOCK (dbin);
4892       return FALSE;
4893     }
4894     DYN_UNLOCK (dbin);
4895     GST_ERROR_OBJECT (dbin, "Broken chain/group tree");
4896     g_return_val_if_reached (FALSE);
4897     return FALSE;
4898   }
4899   if (endpads == NULL) {
4900     if (missing_plugin) {
4901       if (missing_plugin_details->len > 0) {
4902         gchar *details = g_string_free (missing_plugin_details, FALSE);
4903         GST_ELEMENT_ERROR (dbin, CORE, MISSING_PLUGIN, (NULL),
4904             ("no suitable plugins found:\n%s", details));
4905         g_free (details);
4906       } else {
4907         g_string_free (missing_plugin_details, TRUE);
4908         GST_ELEMENT_ERROR (dbin, CORE, MISSING_PLUGIN, (NULL),
4909             ("no suitable plugins found"));
4910       }
4911     } else {
4912       /* in this case, the stream ended without buffers,
4913        * just post a warning */
4914       g_string_free (missing_plugin_details, TRUE);
4915 
4916       GST_WARNING_OBJECT (dbin, "All streams finished without buffers. "
4917           "Last group: %d", last_group);
4918       if (last_group) {
4919         GST_ELEMENT_ERROR (dbin, STREAM, FAILED, (NULL),
4920             ("all streams without buffers"));
4921       } else {
4922         gboolean switched = FALSE;
4923         gboolean drained = FALSE;
4924 
4925         drain_and_switch_chains (dbin->decode_chain, NULL, &last_group,
4926             &drained, &switched);
4927         GST_ELEMENT_WARNING (dbin, STREAM, FAILED, (NULL),
4928             ("all streams without buffers"));
4929         if (switched) {
4930           if (gst_decode_chain_is_complete (dbin->decode_chain))
4931             goto retry;
4932           else
4933             return FALSE;
4934         }
4935       }
4936     }
4937 
4938     do_async_done (dbin);
4939     return FALSE;
4940   }
4941 
4942   g_string_free (missing_plugin_details, TRUE);
4943 
4944   /* Check if this was called when everything was exposed already */
4945   for (tmp = endpads; tmp && already_exposed; tmp = tmp->next) {
4946     GstDecodePad *dpad = tmp->data;
4947 
4948     already_exposed &= dpad->exposed;
4949     if (!already_exposed)
4950       break;
4951   }
4952   if (already_exposed) {
4953     GST_DEBUG_OBJECT (dbin, "Everything was exposed already!");
4954     g_list_foreach (endpads, (GFunc) gst_object_unref, NULL);
4955     g_list_free (endpads);
4956     return TRUE;
4957   }
4958 
4959   /* going to expose something, reset buffering */
4960   gst_decode_bin_reset_buffering (dbin);
4961 
4962   /* Set all already exposed pads to blocked */
4963   for (tmp = endpads; tmp; tmp = tmp->next) {
4964     GstDecodePad *dpad = tmp->data;
4965 
4966     if (dpad->exposed) {
4967       GST_DEBUG_OBJECT (dpad, "blocking exposed pad");
4968       gst_decode_pad_set_blocked (dpad, TRUE);
4969     }
4970   }
4971 
4972   /* re-order pads : video, then audio, then others */
4973   endpads = g_list_sort (endpads, (GCompareFunc) sort_end_pads);
4974 
4975   /* Don't add pads if we are shutting down */
4976   DYN_LOCK (dbin);
4977   if (G_UNLIKELY (dbin->shutdown)) {
4978     GST_WARNING_OBJECT (dbin, "Currently, shutting down, aborting exposing");
4979     DYN_UNLOCK (dbin);
4980     return FALSE;
4981   }
4982 
4983   /* Expose pads */
4984   for (tmp = endpads; tmp; tmp = tmp->next) {
4985     GstDecodePad *dpad = (GstDecodePad *) tmp->data;
4986     gchar *padname;
4987 
4988     /* 1. rewrite name */
4989     padname = g_strdup_printf ("src_%u", dbin->nbpads);
4990     dbin->nbpads++;
4991     GST_DEBUG_OBJECT (dbin, "About to expose dpad %s as %s",
4992         GST_OBJECT_NAME (dpad), padname);
4993     gst_object_set_name (GST_OBJECT (dpad), padname);
4994     g_free (padname);
4995 
4996     gst_pad_sticky_events_foreach (GST_PAD_CAST (dpad), debug_sticky_event,
4997         dpad);
4998 
4999     /* 2. activate and add */
5000     if (!dpad->exposed) {
5001       dpad->exposed = TRUE;
5002       if (!gst_element_add_pad (GST_ELEMENT (dbin), GST_PAD_CAST (dpad))) {
5003         /* not really fatal, we can try to add the other pads */
5004         g_warning ("error adding pad to decodebin");
5005         dpad->exposed = FALSE;
5006         continue;
5007       }
5008     }
5009 
5010     /* 3. emit signal */
5011     GST_INFO_OBJECT (dpad, "added new decoded pad");
5012   }
5013   DYN_UNLOCK (dbin);
5014 
5015   /* 4. Signal no-more-pads. This allows the application to hook stuff to the
5016    * exposed pads */
5017   GST_LOG_OBJECT (dbin, "signaling no-more-pads");
5018   gst_element_no_more_pads (GST_ELEMENT (dbin));
5019 
5020   /* 5. Send a custom element message with the stream topology */
5021   if (dbin->post_stream_topology)
5022     gst_decode_bin_post_topology_message (dbin);
5023 
5024   /* 6. Unblock internal pads. The application should have connected stuff now
5025    * so that streaming can continue. */
5026   for (tmp = endpads; tmp; tmp = tmp->next) {
5027     GstDecodePad *dpad = (GstDecodePad *) tmp->data;
5028 
5029     GST_DEBUG_OBJECT (dpad, "unblocking");
5030     gst_decode_pad_unblock (dpad);
5031     GST_DEBUG_OBJECT (dpad, "unblocked");
5032     gst_object_unref (dpad);
5033   }
5034   g_list_free (endpads);
5035 
5036   do_async_done (dbin);
5037   GST_DEBUG_OBJECT (dbin, "Exposed everything");
5038   return TRUE;
5039 }
5040 
5041 /* gst_decode_chain_expose:
5042  *
5043  * Check if the chain can be exposed and add all endpads
5044  * to the endpads list.
5045  *
5046  * Also update the active group's multiqueue to the
5047  * runtime limits.
5048  *
5049  * Not MT-safe, call with decodebin expose lock! *
5050  */
5051 static gboolean
gst_decode_chain_expose(GstDecodeChain * chain,GList ** endpads,gboolean * missing_plugin,GString * missing_plugin_details,gboolean * last_group)5052 gst_decode_chain_expose (GstDecodeChain * chain, GList ** endpads,
5053     gboolean * missing_plugin, GString * missing_plugin_details,
5054     gboolean * last_group)
5055 {
5056   GstDecodeGroup *group;
5057   GList *l;
5058   GstDecodeBin *dbin;
5059 
5060   if (chain->deadend) {
5061     if (chain->endcaps) {
5062       if (chain->deadend_details) {
5063         g_string_append (missing_plugin_details, chain->deadend_details);
5064         g_string_append_c (missing_plugin_details, '\n');
5065       } else {
5066         gchar *desc = gst_pb_utils_get_codec_description (chain->endcaps);
5067         gchar *caps_str = gst_caps_to_string (chain->endcaps);
5068         g_string_append_printf (missing_plugin_details,
5069             "Missing decoder: %s (%s)\n", desc, caps_str);
5070         g_free (caps_str);
5071         g_free (desc);
5072       }
5073       *missing_plugin = TRUE;
5074     }
5075     return TRUE;
5076   }
5077 
5078   if (chain->endpad) {
5079     if (!gst_decode_pad_is_exposable (chain->endpad) && !chain->endpad->exposed)
5080       return FALSE;
5081     *endpads = g_list_prepend (*endpads, gst_object_ref (chain->endpad));
5082     return TRUE;
5083   }
5084 
5085   if (chain->next_groups)
5086     *last_group = FALSE;
5087 
5088   group = chain->active_group;
5089   if (!group)
5090     return FALSE;
5091   if (!group->no_more_pads && !group->overrun)
5092     return FALSE;
5093 
5094   dbin = group->dbin;
5095 
5096   /* we can now disconnect any overrun signal, which is used to expose the
5097    * group. */
5098   if (group->overrunsig) {
5099     GST_LOG_OBJECT (dbin, "Disconnecting overrun");
5100     g_signal_handler_disconnect (group->multiqueue, group->overrunsig);
5101     group->overrunsig = 0;
5102   }
5103 
5104   for (l = group->children; l; l = l->next) {
5105     GstDecodeChain *childchain = l->data;
5106 
5107     if (!gst_decode_chain_expose (childchain, endpads, missing_plugin,
5108             missing_plugin_details, last_group))
5109       return FALSE;
5110   }
5111 
5112   return TRUE;
5113 }
5114 
5115 /*************************
5116  * GstDecodePad functions
5117  *************************/
5118 
5119 static void
gst_decode_pad_class_init(GstDecodePadClass * klass)5120 gst_decode_pad_class_init (GstDecodePadClass * klass)
5121 {
5122 }
5123 
5124 static void
gst_decode_pad_init(GstDecodePad * pad)5125 gst_decode_pad_init (GstDecodePad * pad)
5126 {
5127   pad->chain = NULL;
5128   pad->blocked = FALSE;
5129   pad->exposed = FALSE;
5130   pad->drained = FALSE;
5131   gst_object_ref_sink (pad);
5132 }
5133 
5134 static GstPadProbeReturn
source_pad_blocked_cb(GstPad * pad,GstPadProbeInfo * info,gpointer user_data)5135 source_pad_blocked_cb (GstPad * pad, GstPadProbeInfo * info, gpointer user_data)
5136 {
5137   GstDecodePad *dpad = user_data;
5138   GstDecodeChain *chain;
5139   GstDecodeBin *dbin;
5140   GstPadProbeReturn ret = GST_PAD_PROBE_OK;
5141 
5142   if (GST_PAD_PROBE_INFO_TYPE (info) & GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM) {
5143     GstEvent *event = GST_PAD_PROBE_INFO_EVENT (info);
5144 
5145     GST_LOG_OBJECT (pad, "Seeing event '%s'", GST_EVENT_TYPE_NAME (event));
5146 
5147     if (!GST_EVENT_IS_SERIALIZED (event)) {
5148       /* do not block on sticky or out of band events otherwise the allocation query
5149          from demuxer might block the loop thread */
5150       GST_LOG_OBJECT (pad, "Letting OOB event through");
5151       return GST_PAD_PROBE_PASS;
5152     }
5153 
5154     if (GST_EVENT_IS_STICKY (event) && GST_EVENT_TYPE (event) != GST_EVENT_EOS) {
5155       /* manually push sticky events to ghost pad to avoid exposing pads
5156        * that don't have the sticky events. Handle EOS separately as we
5157        * want to block the pad on it if we didn't get any buffers before
5158        * EOS and expose the pad then. */
5159       gst_pad_push_event (GST_PAD_CAST (dpad), gst_event_ref (event));
5160 
5161       /* let the sticky events pass */
5162       ret = GST_PAD_PROBE_PASS;
5163 
5164       /* we only want to try to expose on CAPS events */
5165       if (GST_EVENT_TYPE (event) != GST_EVENT_CAPS) {
5166         GST_LOG_OBJECT (pad, "Letting sticky non-CAPS event through");
5167         goto done;
5168       }
5169     }
5170   } else if (GST_PAD_PROBE_INFO_TYPE (info) &
5171       GST_PAD_PROBE_TYPE_QUERY_DOWNSTREAM) {
5172     GstQuery *query = GST_PAD_PROBE_INFO_QUERY (info);
5173 
5174     if (!GST_QUERY_IS_SERIALIZED (query)) {
5175       /* do not block on non-serialized queries */
5176       GST_LOG_OBJECT (pad, "Letting non-serialized query through");
5177       return GST_PAD_PROBE_PASS;
5178     }
5179     if (!gst_pad_has_current_caps (pad)) {
5180       /* do not block on allocation queries before we have caps,
5181        * this would deadlock because we are doing no autoplugging
5182        * without caps.
5183        * TODO: Try to do autoplugging based on the query caps
5184        */
5185       GST_LOG_OBJECT (pad, "Letting serialized query before caps through");
5186       return GST_PAD_PROBE_PASS;
5187     }
5188   }
5189   chain = dpad->chain;
5190   dbin = chain->dbin;
5191 
5192   GST_LOG_OBJECT (dpad, "blocked: dpad->chain:%p", chain);
5193 
5194   dpad->blocked = TRUE;
5195 
5196   EXPOSE_LOCK (dbin);
5197   if (dbin->decode_chain) {
5198     if (gst_decode_chain_is_complete (dbin->decode_chain)) {
5199       if (!gst_decode_bin_expose (dbin))
5200         GST_WARNING_OBJECT (dbin, "Couldn't expose group");
5201     }
5202   }
5203   EXPOSE_UNLOCK (dbin);
5204 
5205 done:
5206   return ret;
5207 }
5208 
5209 static GstPadProbeReturn
source_pad_event_probe(GstPad * pad,GstPadProbeInfo * info,gpointer user_data)5210 source_pad_event_probe (GstPad * pad, GstPadProbeInfo * info,
5211     gpointer user_data)
5212 {
5213   GstEvent *event = GST_PAD_PROBE_INFO_EVENT (info);
5214   GstDecodePad *dpad = user_data;
5215   gboolean res = TRUE;
5216 
5217   GST_LOG_OBJECT (pad, "%s dpad:%p", GST_EVENT_TYPE_NAME (event), dpad);
5218 
5219   if (GST_EVENT_TYPE (event) == GST_EVENT_EOS) {
5220     GST_DEBUG_OBJECT (pad, "we received EOS");
5221 
5222     /* Check if all pads are drained.
5223      * * If there is no next group, we will let the EOS go through.
5224      * * If there is a next group but the current group isn't completely
5225      *   drained, we will drop the EOS event.
5226      * * If there is a next group to expose and this was the last non-drained
5227      *   pad for that group, we will remove the ghostpad of the current group
5228      *   first, which unlinks the peer and so drops the EOS. */
5229     res = gst_decode_pad_handle_eos (dpad);
5230   }
5231   if (res)
5232     return GST_PAD_PROBE_OK;
5233   else
5234     return GST_PAD_PROBE_DROP;
5235 }
5236 
5237 static void
gst_decode_pad_set_blocked(GstDecodePad * dpad,gboolean blocked)5238 gst_decode_pad_set_blocked (GstDecodePad * dpad, gboolean blocked)
5239 {
5240   GstDecodeBin *dbin = dpad->dbin;
5241   GstPad *opad;
5242 
5243   DYN_LOCK (dbin);
5244 
5245   GST_DEBUG_OBJECT (dpad, "blocking pad: %d", blocked);
5246 
5247   opad = gst_ghost_pad_get_target (GST_GHOST_PAD_CAST (dpad));
5248   if (!opad)
5249     goto out;
5250 
5251   /* do not block if shutting down.
5252    * we do not consider/expect it blocked further below, but use other trick */
5253   if (!blocked || !dbin->shutdown) {
5254     if (blocked) {
5255       if (dpad->block_id == 0)
5256         dpad->block_id =
5257             gst_pad_add_probe (opad,
5258             GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM |
5259             GST_PAD_PROBE_TYPE_QUERY_DOWNSTREAM, source_pad_blocked_cb,
5260             gst_object_ref (dpad), (GDestroyNotify) gst_object_unref);
5261     } else {
5262       if (dpad->block_id != 0) {
5263         gst_pad_remove_probe (opad, dpad->block_id);
5264         dpad->block_id = 0;
5265       }
5266       dpad->blocked = FALSE;
5267     }
5268   }
5269 
5270   if (blocked) {
5271     if (dbin->shutdown) {
5272       /* deactivate to force flushing state to prevent NOT_LINKED errors */
5273       gst_pad_set_active (GST_PAD_CAST (dpad), FALSE);
5274       /* note that deactivating the target pad would have no effect here,
5275        * since elements are typically connected first (and pads exposed),
5276        * and only then brought to PAUSED state (so pads activated) */
5277     } else {
5278       gst_object_ref (dpad);
5279       dbin->blocked_pads = g_list_prepend (dbin->blocked_pads, dpad);
5280     }
5281   } else {
5282     GList *l;
5283 
5284     if ((l = g_list_find (dbin->blocked_pads, dpad))) {
5285       gst_object_unref (dpad);
5286       dbin->blocked_pads = g_list_delete_link (dbin->blocked_pads, l);
5287     }
5288   }
5289   gst_object_unref (opad);
5290 out:
5291   DYN_UNLOCK (dbin);
5292 }
5293 
5294 static void
gst_decode_pad_add_drained_check(GstDecodePad * dpad)5295 gst_decode_pad_add_drained_check (GstDecodePad * dpad)
5296 {
5297   gst_pad_add_probe (GST_PAD_CAST (dpad), GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM,
5298       source_pad_event_probe, dpad, NULL);
5299 }
5300 
5301 static void
gst_decode_pad_activate(GstDecodePad * dpad,GstDecodeChain * chain)5302 gst_decode_pad_activate (GstDecodePad * dpad, GstDecodeChain * chain)
5303 {
5304   g_return_if_fail (chain != NULL);
5305 
5306   dpad->chain = chain;
5307   gst_pad_set_active (GST_PAD_CAST (dpad), TRUE);
5308   gst_decode_pad_set_blocked (dpad, TRUE);
5309   gst_decode_pad_add_drained_check (dpad);
5310 }
5311 
5312 static void
gst_decode_pad_unblock(GstDecodePad * dpad)5313 gst_decode_pad_unblock (GstDecodePad * dpad)
5314 {
5315   gst_decode_pad_set_blocked (dpad, FALSE);
5316 }
5317 
5318 static gboolean
gst_decode_pad_event(GstPad * pad,GstObject * parent,GstEvent * event)5319 gst_decode_pad_event (GstPad * pad, GstObject * parent, GstEvent * event)
5320 {
5321   GstDecodeBin *dbin = GST_DECODE_BIN (parent);
5322 
5323   if (GST_EVENT_TYPE (event) == GST_EVENT_SEEK && dbin && dbin->decode_chain) {
5324     GstElement *demuxer = NULL;
5325 
5326     /* For adaptive demuxers we send the seek event directly to the demuxer.
5327      * See https://bugzilla.gnome.org/show_bug.cgi?id=606382
5328      */
5329     CHAIN_MUTEX_LOCK (dbin->decode_chain);
5330     if (dbin->decode_chain->adaptive_demuxer) {
5331       GstDecodeElement *delem = dbin->decode_chain->elements->data;
5332       demuxer = gst_object_ref (delem->element);
5333     }
5334     CHAIN_MUTEX_UNLOCK (dbin->decode_chain);
5335 
5336     if (demuxer) {
5337       gboolean ret;
5338 
5339       GST_DEBUG_OBJECT (dbin,
5340           "Sending SEEK event directly to adaptive streaming demuxer %s",
5341           GST_OBJECT_NAME (demuxer));
5342       ret = gst_element_send_event (demuxer, event);
5343       gst_object_unref (demuxer);
5344       return ret;
5345     }
5346   }
5347 
5348   return gst_pad_event_default (pad, parent, event);
5349 }
5350 
5351 static gboolean
gst_decode_pad_query(GstPad * pad,GstObject * parent,GstQuery * query)5352 gst_decode_pad_query (GstPad * pad, GstObject * parent, GstQuery * query)
5353 {
5354   GstDecodePad *dpad = GST_DECODE_PAD (parent);
5355   gboolean ret = FALSE;
5356 
5357   CHAIN_MUTEX_LOCK (dpad->chain);
5358   if (!dpad->exposed && !dpad->dbin->shutdown && !dpad->chain->deadend
5359       && dpad->chain->elements) {
5360     GstDecodeElement *delem = dpad->chain->elements->data;
5361 
5362     ret = FALSE;
5363     GST_DEBUG_OBJECT (dpad->dbin,
5364         "calling autoplug-query for %s (element %s): %" GST_PTR_FORMAT,
5365         GST_PAD_NAME (dpad), GST_ELEMENT_NAME (delem->element), query);
5366     g_signal_emit (G_OBJECT (dpad->dbin),
5367         gst_decode_bin_signals[SIGNAL_AUTOPLUG_QUERY], 0, dpad, delem->element,
5368         query, &ret);
5369 
5370     if (ret)
5371       GST_DEBUG_OBJECT (dpad->dbin,
5372           "autoplug-query returned %d: %" GST_PTR_FORMAT, ret, query);
5373     else
5374       GST_DEBUG_OBJECT (dpad->dbin, "autoplug-query returned %d", ret);
5375   }
5376   CHAIN_MUTEX_UNLOCK (dpad->chain);
5377 
5378   /* If exposed or nothing handled the query use the default handler */
5379   if (!ret)
5380     ret = gst_pad_query_default (pad, parent, query);
5381 
5382   return ret;
5383 }
5384 
5385 static gboolean
gst_decode_pad_is_exposable(GstDecodePad * endpad)5386 gst_decode_pad_is_exposable (GstDecodePad * endpad)
5387 {
5388   if (endpad->blocked || endpad->exposed)
5389     return TRUE;
5390 
5391   return gst_pad_has_current_caps (GST_PAD_CAST (endpad));
5392 }
5393 
5394 /*gst_decode_pad_new:
5395  *
5396  * Creates a new GstDecodePad for the given pad.
5397  */
5398 static GstDecodePad *
gst_decode_pad_new(GstDecodeBin * dbin,GstDecodeChain * chain)5399 gst_decode_pad_new (GstDecodeBin * dbin, GstDecodeChain * chain)
5400 {
5401   GstDecodePad *dpad;
5402   GstProxyPad *ppad;
5403   GstPadTemplate *pad_tmpl;
5404 
5405   GST_DEBUG_OBJECT (dbin, "making new decodepad");
5406   pad_tmpl = gst_static_pad_template_get (&decoder_bin_src_template);
5407   dpad =
5408       g_object_new (GST_TYPE_DECODE_PAD, "direction", GST_PAD_SRC,
5409       "template", pad_tmpl, NULL);
5410   dpad->chain = chain;
5411   dpad->dbin = dbin;
5412   gst_object_unref (pad_tmpl);
5413 
5414   ppad = gst_proxy_pad_get_internal (GST_PROXY_PAD (dpad));
5415   gst_pad_set_query_function (GST_PAD_CAST (ppad), gst_decode_pad_query);
5416   gst_pad_set_event_function (GST_PAD_CAST (dpad), gst_decode_pad_event);
5417   gst_object_unref (ppad);
5418 
5419   return dpad;
5420 }
5421 
5422 static void
gst_pending_pad_free(GstPendingPad * ppad)5423 gst_pending_pad_free (GstPendingPad * ppad)
5424 {
5425   g_assert (ppad);
5426   g_assert (ppad->pad);
5427 
5428   if (ppad->event_probe_id != 0)
5429     gst_pad_remove_probe (ppad->pad, ppad->event_probe_id);
5430   if (ppad->notify_caps_id)
5431     g_signal_handler_disconnect (ppad->pad, ppad->notify_caps_id);
5432   gst_object_unref (ppad->pad);
5433   g_slice_free (GstPendingPad, ppad);
5434 }
5435 
5436 /*****
5437  * Element add/remove
5438  *****/
5439 
5440 static void
do_async_start(GstDecodeBin * dbin)5441 do_async_start (GstDecodeBin * dbin)
5442 {
5443   GstMessage *message;
5444 
5445   dbin->async_pending = TRUE;
5446 
5447   message = gst_message_new_async_start (GST_OBJECT_CAST (dbin));
5448   parent_class->handle_message (GST_BIN_CAST (dbin), message);
5449 }
5450 
5451 static void
do_async_done(GstDecodeBin * dbin)5452 do_async_done (GstDecodeBin * dbin)
5453 {
5454   GstMessage *message;
5455 
5456   if (dbin->async_pending) {
5457     message =
5458         gst_message_new_async_done (GST_OBJECT_CAST (dbin),
5459         GST_CLOCK_TIME_NONE);
5460     parent_class->handle_message (GST_BIN_CAST (dbin), message);
5461 
5462     dbin->async_pending = FALSE;
5463   }
5464 }
5465 
5466 /*****
5467  * convenience functions
5468  *****/
5469 
5470 /* find_sink_pad
5471  *
5472  * Returns the first sink pad of the given element, or NULL if it doesn't have
5473  * any.
5474  */
5475 
5476 static GstPad *
find_sink_pad(GstElement * element)5477 find_sink_pad (GstElement * element)
5478 {
5479   GstIterator *it;
5480   GstPad *pad = NULL;
5481   GValue item = { 0, };
5482 
5483   it = gst_element_iterate_sink_pads (element);
5484 
5485   if ((gst_iterator_next (it, &item)) == GST_ITERATOR_OK)
5486     pad = g_value_dup_object (&item);
5487   g_value_unset (&item);
5488   gst_iterator_free (it);
5489 
5490   return pad;
5491 }
5492 
5493 /* call with dyn_lock held */
5494 static void
unblock_pads(GstDecodeBin * dbin)5495 unblock_pads (GstDecodeBin * dbin)
5496 {
5497   GST_LOG_OBJECT (dbin, "unblocking pads");
5498 
5499   while (dbin->blocked_pads) {
5500     GList *tmp = dbin->blocked_pads;
5501     GstDecodePad *dpad = (GstDecodePad *) tmp->data;
5502     GstPad *opad;
5503 
5504     dbin->blocked_pads = g_list_delete_link (dbin->blocked_pads, tmp);
5505     opad = gst_ghost_pad_get_target (GST_GHOST_PAD_CAST (dpad));
5506     if (opad) {
5507 
5508       GST_DEBUG_OBJECT (dpad, "unblocking");
5509       if (dpad->block_id != 0) {
5510         gst_pad_remove_probe (opad, dpad->block_id);
5511         dpad->block_id = 0;
5512       }
5513       gst_object_unref (opad);
5514     }
5515 
5516     dpad->blocked = FALSE;
5517 
5518     /* We release the dyn lock since we want to allow the streaming threads
5519      * to properly stop and not be blocked in our various probes */
5520     DYN_UNLOCK (dbin);
5521     /* make flushing, prevent NOT_LINKED */
5522     gst_pad_set_active (GST_PAD_CAST (dpad), FALSE);
5523     DYN_LOCK (dbin);
5524 
5525     GST_DEBUG_OBJECT (dpad, "unblocked");
5526     gst_object_unref (dpad);
5527   }
5528 }
5529 
5530 static void
gst_decode_chain_stop(GstDecodeBin * dbin,GstDecodeChain * chain,GQueue * elements)5531 gst_decode_chain_stop (GstDecodeBin * dbin, GstDecodeChain * chain,
5532     GQueue * elements)
5533 {
5534   GQueue *internal_elements, internal_elements_ = G_QUEUE_INIT;
5535   GList *l;
5536 
5537   CHAIN_MUTEX_LOCK (chain);
5538   if (elements) {
5539     internal_elements = elements;
5540   } else {
5541     internal_elements = &internal_elements_;
5542   }
5543 
5544   for (l = chain->next_groups; l; l = l->next) {
5545     GstDecodeGroup *group = l->data;
5546     GList *m;
5547 
5548     for (m = group->children; m; m = m->next) {
5549       GstDecodeChain *chain2 = m->data;
5550       gst_decode_chain_stop (dbin, chain2, internal_elements);
5551     }
5552     if (group->multiqueue)
5553       g_queue_push_head (internal_elements, gst_object_ref (group->multiqueue));
5554   }
5555 
5556   if (chain->active_group) {
5557     for (l = chain->active_group->children; l; l = l->next) {
5558       GstDecodeChain *chain2 = l->data;
5559       gst_decode_chain_stop (dbin, chain2, internal_elements);
5560     }
5561     if (chain->active_group->multiqueue)
5562       g_queue_push_head (internal_elements,
5563           gst_object_ref (chain->active_group->multiqueue));
5564   }
5565 
5566   for (l = chain->old_groups; l; l = l->next) {
5567     GstDecodeGroup *group = l->data;
5568     GList *m;
5569 
5570     for (m = group->children; m; m = m->next) {
5571       GstDecodeChain *chain2 = m->data;
5572       gst_decode_chain_stop (dbin, chain2, internal_elements);
5573     }
5574     if (group->multiqueue)
5575       g_queue_push_head (internal_elements, gst_object_ref (group->multiqueue));
5576   }
5577 
5578   for (l = chain->elements; l; l = l->next) {
5579     GstDecodeElement *delem = l->data;
5580 
5581     if (delem->capsfilter)
5582       g_queue_push_head (internal_elements, gst_object_ref (delem->capsfilter));
5583     g_queue_push_head (internal_elements, gst_object_ref (delem->element));
5584   }
5585 
5586   CHAIN_MUTEX_UNLOCK (chain);
5587 
5588   if (!elements) {
5589     GstElement *element;
5590 
5591     EXPOSE_UNLOCK (dbin);
5592     /* Shut down from bottom to top */
5593     while ((element = g_queue_pop_tail (internal_elements))) {
5594       /* The bin must never ever change the state of this element anymore */
5595       gst_element_set_locked_state (element, TRUE);
5596       gst_element_set_state (element, GST_STATE_NULL);
5597       gst_object_unref (element);
5598     }
5599     g_queue_clear (internal_elements);
5600     EXPOSE_LOCK (dbin);
5601   }
5602 }
5603 
5604 static GstStateChangeReturn
gst_decode_bin_change_state(GstElement * element,GstStateChange transition)5605 gst_decode_bin_change_state (GstElement * element, GstStateChange transition)
5606 {
5607   GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
5608   GstDecodeBin *dbin = GST_DECODE_BIN (element);
5609   GstDecodeChain *chain_to_free = NULL;
5610 
5611   switch (transition) {
5612     case GST_STATE_CHANGE_NULL_TO_READY:
5613       if (dbin->typefind == NULL)
5614         goto missing_typefind;
5615       break;
5616     case GST_STATE_CHANGE_READY_TO_PAUSED:
5617       /* Make sure we've cleared all existing chains */
5618       EXPOSE_LOCK (dbin);
5619       if (dbin->decode_chain) {
5620         gst_decode_chain_free (dbin->decode_chain);
5621         dbin->decode_chain = NULL;
5622       }
5623       EXPOSE_UNLOCK (dbin);
5624       DYN_LOCK (dbin);
5625       GST_LOG_OBJECT (dbin, "clearing shutdown flag");
5626       dbin->shutdown = FALSE;
5627       DYN_UNLOCK (dbin);
5628       dbin->have_type = FALSE;
5629       ret = GST_STATE_CHANGE_ASYNC;
5630       do_async_start (dbin);
5631 
5632 
5633       /* connect a signal to find out when the typefind element found
5634        * a type */
5635       dbin->have_type_id =
5636           g_signal_connect (dbin->typefind, "have-type",
5637           G_CALLBACK (type_found), dbin);
5638       break;
5639     case GST_STATE_CHANGE_PAUSED_TO_READY:
5640     case GST_STATE_CHANGE_READY_TO_NULL:
5641       if (dbin->have_type_id)
5642         g_signal_handler_disconnect (dbin->typefind, dbin->have_type_id);
5643       dbin->have_type_id = 0;
5644       DYN_LOCK (dbin);
5645       GST_LOG_OBJECT (dbin, "setting shutdown flag");
5646       dbin->shutdown = TRUE;
5647       unblock_pads (dbin);
5648       DYN_UNLOCK (dbin);
5649 
5650       /* Make sure we don't have cleanup races where
5651        * we might be trying to deactivate pads (in the cleanup thread)
5652        * at the same time as the default element deactivation
5653        * (in PAUSED=>READY)  */
5654       g_mutex_lock (&dbin->cleanup_lock);
5655       if (dbin->cleanup_thread) {
5656         g_thread_join (dbin->cleanup_thread);
5657         dbin->cleanup_thread = NULL;
5658       }
5659       g_mutex_unlock (&dbin->cleanup_lock);
5660     default:
5661       break;
5662   }
5663 
5664   {
5665     GstStateChangeReturn bret;
5666 
5667     bret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
5668     if (G_UNLIKELY (bret == GST_STATE_CHANGE_FAILURE))
5669       goto activate_failed;
5670     else if (G_UNLIKELY (bret == GST_STATE_CHANGE_NO_PREROLL)) {
5671       do_async_done (dbin);
5672       ret = bret;
5673     }
5674   }
5675   switch (transition) {
5676     case GST_STATE_CHANGE_PAUSED_TO_READY:
5677       do_async_done (dbin);
5678       EXPOSE_LOCK (dbin);
5679       if (dbin->decode_chain) {
5680         gst_decode_chain_stop (dbin, dbin->decode_chain, NULL);
5681         chain_to_free = dbin->decode_chain;
5682         gst_decode_chain_free_internal (dbin->decode_chain, TRUE);
5683         dbin->decode_chain = NULL;
5684       }
5685       EXPOSE_UNLOCK (dbin);
5686       if (chain_to_free)
5687         gst_decode_chain_free (chain_to_free);
5688       g_list_free_full (dbin->buffering_status,
5689           (GDestroyNotify) gst_message_unref);
5690       dbin->buffering_status = NULL;
5691       /* Let's do a final check of leftover groups to free */
5692       g_mutex_lock (&dbin->cleanup_lock);
5693       if (dbin->cleanup_groups) {
5694         gst_decode_chain_free_hidden_groups (dbin->cleanup_groups);
5695         dbin->cleanup_groups = NULL;
5696       }
5697       g_mutex_unlock (&dbin->cleanup_lock);
5698       break;
5699     case GST_STATE_CHANGE_READY_TO_NULL:
5700       /* Let's do a final check of leftover groups to free */
5701       g_mutex_lock (&dbin->cleanup_lock);
5702       if (dbin->cleanup_groups) {
5703         gst_decode_chain_free_hidden_groups (dbin->cleanup_groups);
5704         dbin->cleanup_groups = NULL;
5705       }
5706       g_mutex_unlock (&dbin->cleanup_lock);
5707       break;
5708     default:
5709       break;
5710   }
5711 
5712   return ret;
5713 
5714 /* ERRORS */
5715 missing_typefind:
5716   {
5717     gst_element_post_message (element,
5718         gst_missing_element_message_new (element, "typefind"));
5719     GST_ELEMENT_ERROR (dbin, CORE, MISSING_PLUGIN, (NULL), ("no typefind!"));
5720     return GST_STATE_CHANGE_FAILURE;
5721   }
5722 activate_failed:
5723   {
5724     GST_DEBUG_OBJECT (element,
5725         "element failed to change states -- activation problem?");
5726     do_async_done (dbin);
5727     return GST_STATE_CHANGE_FAILURE;
5728   }
5729 }
5730 
5731 static void
gst_decode_bin_handle_message(GstBin * bin,GstMessage * msg)5732 gst_decode_bin_handle_message (GstBin * bin, GstMessage * msg)
5733 {
5734   GstDecodeBin *dbin = GST_DECODE_BIN (bin);
5735   gboolean drop = FALSE;
5736 
5737   if (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_ERROR) {
5738     /* Don't pass errors when shutting down. Sometimes,
5739      * elements can generate spurious errors because we set the
5740      * output pads to flushing, and they can't detect that if they
5741      * send an event at exactly the wrong moment */
5742     DYN_LOCK (dbin);
5743     drop = dbin->shutdown;
5744     DYN_UNLOCK (dbin);
5745 
5746     if (!drop) {
5747       GST_OBJECT_LOCK (dbin);
5748       drop = (g_list_find (dbin->filtered, GST_MESSAGE_SRC (msg)) != NULL);
5749       if (drop)
5750         dbin->filtered_errors =
5751             g_list_prepend (dbin->filtered_errors, gst_message_ref (msg));
5752       GST_OBJECT_UNLOCK (dbin);
5753     }
5754   } else if (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_BUFFERING) {
5755     gint perc, msg_perc;
5756     gint smaller_perc = 100;
5757     GstMessage *smaller = NULL;
5758     GList *found = NULL;
5759     GList *iter;
5760 
5761     /* buffering messages must be aggregated as there might be multiple
5762      * multiqueue in the pipeline and their independent buffering messages
5763      * will confuse the application
5764      *
5765      * decodebin keeps a list of messages received from elements that are
5766      * buffering.
5767      * Rules are:
5768      * 1) Always post the smaller buffering %
5769      * 2) If an element posts a 100% buffering message, remove it from the list
5770      * 3) When there are no more messages on the list, post 100% message
5771      * 4) When an element posts a new buffering message, update the one
5772      *    on the list to this new value
5773      */
5774 
5775     BUFFERING_LOCK (dbin);
5776     gst_message_parse_buffering (msg, &msg_perc);
5777 
5778     GST_DEBUG_OBJECT (dbin, "Got buffering msg %" GST_PTR_FORMAT, msg);
5779 
5780     g_mutex_lock (&dbin->buffering_post_lock);
5781 
5782     /*
5783      * Single loop for 2 things:
5784      * 1) Look for a message with the same source
5785      *   1.1) If the received message is 100%, remove it from the list
5786      * 2) Find the minimum buffering from the list
5787      */
5788     for (iter = dbin->buffering_status; iter;) {
5789       GstMessage *bufstats = iter->data;
5790       if (GST_MESSAGE_SRC (bufstats) == GST_MESSAGE_SRC (msg)) {
5791         found = iter;
5792         if (msg_perc < 100) {
5793           GST_DEBUG_OBJECT (dbin, "Replacing old buffering msg %"
5794               GST_PTR_FORMAT, iter->data);
5795           gst_message_unref (iter->data);
5796           bufstats = iter->data = gst_message_ref (msg);
5797         } else {
5798           GList *current = iter;
5799 
5800           /* remove the element here and avoid confusing the loop */
5801           iter = g_list_next (iter);
5802 
5803           GST_DEBUG_OBJECT (dbin, "Deleting old buffering msg %"
5804               GST_PTR_FORMAT, current->data);
5805 
5806           gst_message_unref (current->data);
5807           dbin->buffering_status =
5808               g_list_delete_link (dbin->buffering_status, current);
5809 
5810           continue;
5811         }
5812       }
5813 
5814       gst_message_parse_buffering (bufstats, &perc);
5815       if (perc < smaller_perc) {
5816         smaller_perc = perc;
5817         smaller = bufstats;
5818       }
5819       iter = g_list_next (iter);
5820     }
5821 
5822     if (found == NULL && msg_perc < 100) {
5823       if (msg_perc < smaller_perc) {
5824         smaller_perc = msg_perc;
5825         smaller = msg;
5826       }
5827       GST_DEBUG_OBJECT (dbin, "Storing buffering msg %" GST_PTR_FORMAT, msg);
5828       dbin->buffering_status =
5829           g_list_prepend (dbin->buffering_status, gst_message_ref (msg));
5830     }
5831 
5832     /* now compute the buffering message that should be posted */
5833     if (smaller_perc == 100) {
5834       g_assert (dbin->buffering_status == NULL);
5835       /* we are posting the original received msg */
5836     } else {
5837       gst_message_replace (&msg, smaller);
5838     }
5839     BUFFERING_UNLOCK (dbin);
5840 
5841     GST_DEBUG_OBJECT (dbin, "Forwarding buffering msg %" GST_PTR_FORMAT, msg);
5842     GST_BIN_CLASS (parent_class)->handle_message (bin, msg);
5843 
5844     g_mutex_unlock (&dbin->buffering_post_lock);
5845     return;
5846   }
5847 
5848   if (drop) {
5849     gst_message_unref (msg);
5850   } else {
5851     GST_DEBUG_OBJECT (dbin, "Forwarding msg %" GST_PTR_FORMAT, msg);
5852     GST_BIN_CLASS (parent_class)->handle_message (bin, msg);
5853   }
5854 }
5855 
5856 static gboolean
gst_decode_bin_remove_element(GstBin * bin,GstElement * element)5857 gst_decode_bin_remove_element (GstBin * bin, GstElement * element)
5858 {
5859   GstDecodeBin *dbin = GST_DECODE_BIN (bin);
5860   gboolean removed = FALSE, post = FALSE;
5861   GList *iter;
5862 
5863   BUFFERING_LOCK (bin);
5864   g_mutex_lock (&dbin->buffering_post_lock);
5865   for (iter = dbin->buffering_status; iter; iter = iter->next) {
5866     GstMessage *bufstats = iter->data;
5867 
5868     if (GST_MESSAGE_SRC (bufstats) == GST_OBJECT_CAST (element) ||
5869         gst_object_has_as_ancestor (GST_MESSAGE_SRC (bufstats),
5870             GST_OBJECT_CAST (element))) {
5871       gst_message_unref (bufstats);
5872       dbin->buffering_status =
5873           g_list_delete_link (dbin->buffering_status, iter);
5874       removed = TRUE;
5875       break;
5876     }
5877   }
5878 
5879   if (removed && dbin->buffering_status == NULL)
5880     post = TRUE;
5881   BUFFERING_UNLOCK (bin);
5882 
5883   if (post) {
5884     gst_element_post_message (GST_ELEMENT_CAST (bin),
5885         gst_message_new_buffering (GST_OBJECT_CAST (dbin), 100));
5886   }
5887   g_mutex_unlock (&dbin->buffering_post_lock);
5888 
5889   return GST_BIN_CLASS (parent_class)->remove_element (bin, element);
5890 }
5891