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