|
1 /* GStreamer |
|
2 * Copyright (C) <2006> Edward Hervey <edward@fluendo.com> |
|
3 * |
|
4 * This library is free software; you can redistribute it and/or |
|
5 * modify it under the terms of the GNU Library General Public |
|
6 * License as published by the Free Software Foundation; either |
|
7 * version 2 of the License, or (at your option) any later version. |
|
8 * |
|
9 * This library is distributed in the hope that it will be useful, |
|
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
12 * Library General Public License for more details. |
|
13 * |
|
14 * You should have received a copy of the GNU Library General Public |
|
15 * License along with this library; if not, write to the |
|
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
|
17 * Boston, MA 02111-1307, USA. |
|
18 */ |
|
19 |
|
20 /** |
|
21 * SECTION:element-decodebin2 |
|
22 * @short_description: Next-generation automatic decoding bin |
|
23 * |
|
24 * #GstBin that auto-magically constructs a decoding pipeline using available |
|
25 * decoders and demuxers via auto-plugging. |
|
26 * |
|
27 * At this stage, decodebin2 is considered UNSTABLE. The API provided in the |
|
28 * signals is expected to change in the near future. |
|
29 * |
|
30 * To try out decodebin2, you can set the USE_DECODEBIN2 environment |
|
31 * variable (USE_DECODEBIN2=1 for example). This will cause playbin to use |
|
32 * decodebin2 instead of the older decodebin for its internal auto-plugging. |
|
33 */ |
|
34 |
|
35 #ifdef HAVE_CONFIG_H |
|
36 #include "config.h" |
|
37 #endif |
|
38 |
|
39 #include <gst/gst-i18n-plugin.h> |
|
40 |
|
41 #include <string.h> |
|
42 #include <gst/gst.h> |
|
43 #include <gst/pbutils/pbutils.h> |
|
44 |
|
45 #include "gstplay-marshal.h" |
|
46 #include "gstplay-enum.h" |
|
47 #include "gstfactorylists.h" |
|
48 |
|
49 #ifdef __SYMBIAN32__ |
|
50 #include <glib_global.h> |
|
51 #endif |
|
52 /* generic templates */ |
|
53 static GstStaticPadTemplate decoder_bin_sink_template = |
|
54 GST_STATIC_PAD_TEMPLATE ("sink", |
|
55 GST_PAD_SINK, |
|
56 GST_PAD_ALWAYS, |
|
57 GST_STATIC_CAPS_ANY); |
|
58 |
|
59 static GstStaticPadTemplate decoder_bin_src_template = |
|
60 GST_STATIC_PAD_TEMPLATE ("src%d", |
|
61 GST_PAD_SRC, |
|
62 GST_PAD_SOMETIMES, |
|
63 GST_STATIC_CAPS_ANY); |
|
64 |
|
65 GST_DEBUG_CATEGORY_STATIC (gst_decode_bin_debug); |
|
66 #define GST_CAT_DEFAULT gst_decode_bin_debug |
|
67 |
|
68 typedef struct _GstDecodeGroup GstDecodeGroup; |
|
69 typedef struct _GstDecodePad GstDecodePad; |
|
70 typedef struct _GstDecodeBin GstDecodeBin; |
|
71 typedef struct _GstDecodeBin GstDecodeBin2; |
|
72 typedef struct _GstDecodeBinClass GstDecodeBinClass; |
|
73 |
|
74 #define GST_TYPE_DECODE_BIN (gst_decode_bin_get_type()) |
|
75 #define GST_DECODE_BIN_CAST(obj) ((GstDecodeBin*)(obj)) |
|
76 #define GST_DECODE_BIN(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_DECODE_BIN,GstDecodeBin)) |
|
77 #define GST_DECODE_BIN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_DECODE_BIN,GstDecodeBinClass)) |
|
78 #define GST_IS_DECODE_BIN(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_DECODE_BIN)) |
|
79 #define GST_IS_DECODE_BIN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_DECODE_BIN)) |
|
80 |
|
81 /** |
|
82 * GstDecodeBin2: |
|
83 * |
|
84 * The opaque #DecodeBin2 data structure |
|
85 */ |
|
86 struct _GstDecodeBin |
|
87 { |
|
88 GstBin bin; /* we extend GstBin */ |
|
89 |
|
90 /* properties */ |
|
91 GstCaps *caps; /* caps on which to stop decoding */ |
|
92 gchar *encoding; /* encoding of subtitles */ |
|
93 |
|
94 GstElement *typefind; /* this holds the typefind object */ |
|
95 GstElement *fakesink; |
|
96 |
|
97 GMutex *lock; /* Protects activegroup and groups */ |
|
98 GstDecodeGroup *activegroup; /* group currently active */ |
|
99 GList *groups; /* List of non-active GstDecodeGroups, sorted in |
|
100 * order of creation. */ |
|
101 GList *oldgroups; /* List of no-longer-used GstDecodeGroups. |
|
102 * Should be freed in dispose */ |
|
103 gint nbpads; /* unique identifier for source pads */ |
|
104 |
|
105 GValueArray *factories; /* factories we can use for selecting elements */ |
|
106 |
|
107 gboolean have_type; /* if we received the have_type signal */ |
|
108 guint have_type_id; /* signal id for have-type from typefind */ |
|
109 }; |
|
110 |
|
111 struct _GstDecodeBinClass |
|
112 { |
|
113 GstBinClass parent_class; |
|
114 |
|
115 /* signal we fire when a new pad has been decoded into raw audio/video */ |
|
116 void (*new_decoded_pad) (GstElement * element, GstPad * pad, gboolean last); |
|
117 /* signal we fire when a pad has been removed */ |
|
118 void (*removed_decoded_pad) (GstElement * element, GstPad * pad); |
|
119 /* signal fired when we found a pad that we cannot decode */ |
|
120 void (*unknown_type) (GstElement * element, GstPad * pad, GstCaps * caps); |
|
121 |
|
122 /* signal fired to know if we continue trying to decode the given caps */ |
|
123 gboolean (*autoplug_continue) (GstElement * element, GstPad * pad, |
|
124 GstCaps * caps); |
|
125 /* signal fired to get a list of factories to try to autoplug */ |
|
126 GValueArray *(*autoplug_factories) (GstElement * element, GstPad * pad, |
|
127 GstCaps * caps); |
|
128 /* signal fired to sort the factories */ |
|
129 GValueArray *(*autoplug_sort) (GstElement * element, GstPad * pad, |
|
130 GstCaps * caps, GValueArray * factories); |
|
131 /* signal fired to select from the proposed list of factories */ |
|
132 GstAutoplugSelectResult (*autoplug_select) (GstElement * element, |
|
133 GstPad * pad, GstCaps * caps, GstElementFactory * factory); |
|
134 |
|
135 /* fired when the last group is drained */ |
|
136 void (*drained) (GstElement * element); |
|
137 }; |
|
138 |
|
139 /* signals */ |
|
140 enum |
|
141 { |
|
142 SIGNAL_NEW_DECODED_PAD, |
|
143 SIGNAL_REMOVED_DECODED_PAD, |
|
144 SIGNAL_UNKNOWN_TYPE, |
|
145 SIGNAL_AUTOPLUG_CONTINUE, |
|
146 SIGNAL_AUTOPLUG_FACTORIES, |
|
147 SIGNAL_AUTOPLUG_SELECT, |
|
148 SIGNAL_AUTOPLUG_SORT, |
|
149 SIGNAL_DRAINED, |
|
150 LAST_SIGNAL |
|
151 }; |
|
152 |
|
153 /* Properties */ |
|
154 enum |
|
155 { |
|
156 PROP_0, |
|
157 PROP_CAPS, |
|
158 PROP_SUBTITLE_ENCODING |
|
159 }; |
|
160 |
|
161 static GstBinClass *parent_class; |
|
162 static guint gst_decode_bin_signals[LAST_SIGNAL] = { 0 }; |
|
163 |
|
164 static const GstElementDetails gst_decode_bin_details = |
|
165 GST_ELEMENT_DETAILS ("Decoder Bin", |
|
166 "Generic/Bin/Decoder", |
|
167 "Autoplug and decode to raw media", |
|
168 "Edward Hervey <edward@fluendo.com>"); |
|
169 |
|
170 |
|
171 static gboolean add_fakesink (GstDecodeBin * decode_bin); |
|
172 static void remove_fakesink (GstDecodeBin * decode_bin); |
|
173 |
|
174 static void type_found (GstElement * typefind, guint probability, |
|
175 GstCaps * caps, GstDecodeBin * decode_bin); |
|
176 |
|
177 static gboolean gst_decode_bin_autoplug_continue (GstElement * element, |
|
178 GstPad * pad, GstCaps * caps); |
|
179 static GValueArray *gst_decode_bin_autoplug_factories (GstElement * |
|
180 element, GstPad * pad, GstCaps * caps); |
|
181 static GValueArray *gst_decode_bin_autoplug_sort (GstElement * element, |
|
182 GstPad * pad, GstCaps * caps, GValueArray * factories); |
|
183 static GstAutoplugSelectResult gst_decode_bin_autoplug_select (GstElement * |
|
184 element, GstPad * pad, GstCaps * caps, GstElementFactory * factory); |
|
185 |
|
186 static void gst_decode_bin_set_property (GObject * object, guint prop_id, |
|
187 const GValue * value, GParamSpec * pspec); |
|
188 static void gst_decode_bin_get_property (GObject * object, guint prop_id, |
|
189 GValue * value, GParamSpec * pspec); |
|
190 static void gst_decode_bin_set_caps (GstDecodeBin * dbin, GstCaps * caps); |
|
191 static GstCaps *gst_decode_bin_get_caps (GstDecodeBin * dbin); |
|
192 static void caps_notify_group_cb (GstPad * pad, GParamSpec * unused, |
|
193 GstDecodeGroup * group); |
|
194 static void caps_notify_cb (GstPad * pad, GParamSpec * unused, |
|
195 GstDecodeBin * dbin); |
|
196 |
|
197 static GstPad *find_sink_pad (GstElement * element); |
|
198 static GstStateChangeReturn gst_decode_bin_change_state (GstElement * element, |
|
199 GstStateChange transition); |
|
200 |
|
201 #define DECODE_BIN_LOCK(dbin) G_STMT_START { \ |
|
202 GST_LOG_OBJECT (dbin, \ |
|
203 "locking from thread %p", \ |
|
204 g_thread_self ()); \ |
|
205 g_mutex_lock (GST_DECODE_BIN_CAST(dbin)->lock); \ |
|
206 GST_LOG_OBJECT (dbin, \ |
|
207 "locked from thread %p", \ |
|
208 g_thread_self ()); \ |
|
209 } G_STMT_END |
|
210 |
|
211 #define DECODE_BIN_UNLOCK(dbin) G_STMT_START { \ |
|
212 GST_LOG_OBJECT (dbin, \ |
|
213 "unlocking from thread %p", \ |
|
214 g_thread_self ()); \ |
|
215 g_mutex_unlock (GST_DECODE_BIN_CAST(dbin)->lock); \ |
|
216 } G_STMT_END |
|
217 |
|
218 /* GstDecodeGroup |
|
219 * |
|
220 * Streams belonging to the same group/chain of a media file |
|
221 * |
|
222 */ |
|
223 struct _GstDecodeGroup |
|
224 { |
|
225 GstDecodeBin *dbin; |
|
226 GMutex *lock; |
|
227 GstElement *multiqueue; |
|
228 gboolean exposed; /* TRUE if this group is exposed */ |
|
229 gboolean drained; /* TRUE if EOS went throug all endpads */ |
|
230 gboolean blocked; /* TRUE if all endpads are blocked */ |
|
231 gboolean complete; /* TRUE if we are not expecting anymore streams |
|
232 * on this group */ |
|
233 gulong overrunsig; |
|
234 gulong underrunsig; |
|
235 guint nbdynamic; /* number of dynamic pads in the group. */ |
|
236 |
|
237 GList *endpads; /* List of GstDecodePad of source pads to be exposed */ |
|
238 GList *ghosts; /* List of GstGhostPad for the endpads */ |
|
239 GList *reqpads; /* List of RequestPads for multiqueue. */ |
|
240 }; |
|
241 |
|
242 #define GROUP_MUTEX_LOCK(group) G_STMT_START { \ |
|
243 GST_LOG_OBJECT (group->dbin, \ |
|
244 "locking group %p from thread %p", \ |
|
245 group, g_thread_self ()); \ |
|
246 g_mutex_lock (group->lock); \ |
|
247 GST_LOG_OBJECT (group->dbin, \ |
|
248 "locked group %p from thread %p", \ |
|
249 group, g_thread_self ()); \ |
|
250 } G_STMT_END |
|
251 |
|
252 #define GROUP_MUTEX_UNLOCK(group) G_STMT_START { \ |
|
253 GST_LOG_OBJECT (group->dbin, \ |
|
254 "unlocking group %p from thread %p", \ |
|
255 group, g_thread_self ()); \ |
|
256 g_mutex_unlock (group->lock); \ |
|
257 } G_STMT_END |
|
258 |
|
259 |
|
260 static GstDecodeGroup *gst_decode_group_new (GstDecodeBin * decode_bin, |
|
261 gboolean use_queue); |
|
262 static GstPad *gst_decode_group_control_demuxer_pad (GstDecodeGroup * group, |
|
263 GstPad * pad); |
|
264 static gboolean gst_decode_group_control_source_pad (GstDecodeGroup * group, |
|
265 GstPad * pad); |
|
266 static gboolean gst_decode_group_expose (GstDecodeGroup * group); |
|
267 static void gst_decode_group_check_if_blocked (GstDecodeGroup * group); |
|
268 static void gst_decode_group_set_complete (GstDecodeGroup * group); |
|
269 static void gst_decode_group_hide (GstDecodeGroup * group); |
|
270 static void gst_decode_group_free (GstDecodeGroup * group); |
|
271 |
|
272 /* GstDecodePad |
|
273 * |
|
274 * GstPad private used for source pads of groups |
|
275 */ |
|
276 |
|
277 struct _GstDecodePad |
|
278 { |
|
279 GstPad *pad; |
|
280 GstDecodeGroup *group; |
|
281 gboolean blocked; |
|
282 gboolean drained; |
|
283 }; |
|
284 |
|
285 static GstDecodePad *gst_decode_pad_new (GstDecodeGroup * group, GstPad * pad, |
|
286 gboolean block); |
|
287 static void source_pad_blocked_cb (GstPad * pad, gboolean blocked, |
|
288 GstDecodePad * dpad); |
|
289 |
|
290 /* TempPadStruct |
|
291 * Internal structure used for pads which have more than one structure. |
|
292 */ |
|
293 typedef struct _TempPadStruct |
|
294 { |
|
295 GstDecodeBin *dbin; |
|
296 GstDecodeGroup *group; |
|
297 } TempPadStruct; |
|
298 |
|
299 /******************************** |
|
300 * Standard GObject boilerplate * |
|
301 ********************************/ |
|
302 |
|
303 static void gst_decode_bin_class_init (GstDecodeBinClass * klass); |
|
304 static void gst_decode_bin_init (GstDecodeBin * decode_bin); |
|
305 static void gst_decode_bin_dispose (GObject * object); |
|
306 static void gst_decode_bin_finalize (GObject * object); |
|
307 |
|
308 static GType |
|
309 gst_decode_bin_get_type (void) |
|
310 { |
|
311 static GType gst_decode_bin_type = 0; |
|
312 |
|
313 if (!gst_decode_bin_type) { |
|
314 static const GTypeInfo gst_decode_bin_info = { |
|
315 sizeof (GstDecodeBinClass), |
|
316 NULL, |
|
317 NULL, |
|
318 (GClassInitFunc) gst_decode_bin_class_init, |
|
319 NULL, |
|
320 NULL, |
|
321 sizeof (GstDecodeBin), |
|
322 0, |
|
323 (GInstanceInitFunc) gst_decode_bin_init, |
|
324 NULL |
|
325 }; |
|
326 |
|
327 gst_decode_bin_type = |
|
328 g_type_register_static (GST_TYPE_BIN, "GstDecodeBin2", |
|
329 &gst_decode_bin_info, 0); |
|
330 } |
|
331 |
|
332 return gst_decode_bin_type; |
|
333 } |
|
334 |
|
335 static gboolean |
|
336 _gst_boolean_accumulator (GSignalInvocationHint * ihint, |
|
337 GValue * return_accu, const GValue * handler_return, gpointer dummy) |
|
338 { |
|
339 gboolean myboolean; |
|
340 |
|
341 myboolean = g_value_get_boolean (handler_return); |
|
342 if (!(ihint->run_type & G_SIGNAL_RUN_CLEANUP)) |
|
343 g_value_set_boolean (return_accu, myboolean); |
|
344 |
|
345 /* stop emission if FALSE */ |
|
346 return myboolean; |
|
347 } |
|
348 |
|
349 /* we collect the first result */ |
|
350 static gboolean |
|
351 _gst_array_accumulator (GSignalInvocationHint * ihint, |
|
352 GValue * return_accu, const GValue * handler_return, gpointer dummy) |
|
353 { |
|
354 gpointer array; |
|
355 |
|
356 array = g_value_get_boxed (handler_return); |
|
357 if (!(ihint->run_type & G_SIGNAL_RUN_CLEANUP)) |
|
358 g_value_set_boxed (return_accu, array); |
|
359 |
|
360 return FALSE; |
|
361 } |
|
362 |
|
363 static gboolean |
|
364 _gst_select_accumulator (GSignalInvocationHint * ihint, |
|
365 GValue * return_accu, const GValue * handler_return, gpointer dummy) |
|
366 { |
|
367 GstAutoplugSelectResult res; |
|
368 |
|
369 res = g_value_get_enum (handler_return); |
|
370 if (!(ihint->run_type & G_SIGNAL_RUN_CLEANUP)) |
|
371 g_value_set_enum (return_accu, res); |
|
372 |
|
373 return FALSE; |
|
374 } |
|
375 |
|
376 static void |
|
377 gst_decode_bin_class_init (GstDecodeBinClass * klass) |
|
378 { |
|
379 GObjectClass *gobject_klass; |
|
380 GstElementClass *gstelement_klass; |
|
381 GstBinClass *gstbin_klass; |
|
382 |
|
383 gobject_klass = (GObjectClass *) klass; |
|
384 gstelement_klass = (GstElementClass *) klass; |
|
385 gstbin_klass = (GstBinClass *) klass; |
|
386 |
|
387 parent_class = g_type_class_peek_parent (klass); |
|
388 |
|
389 gobject_klass->dispose = GST_DEBUG_FUNCPTR (gst_decode_bin_dispose); |
|
390 gobject_klass->finalize = GST_DEBUG_FUNCPTR (gst_decode_bin_finalize); |
|
391 gobject_klass->set_property = GST_DEBUG_FUNCPTR (gst_decode_bin_set_property); |
|
392 gobject_klass->get_property = GST_DEBUG_FUNCPTR (gst_decode_bin_get_property); |
|
393 |
|
394 /** |
|
395 * GstDecodeBin2::new-decoded-pad: |
|
396 * @pad: the newly created pad |
|
397 * @islast: #TRUE if this is the last pad to be added. Deprecated. |
|
398 * |
|
399 * This signal gets emitted as soon as a new pad of the same type as one of |
|
400 * the valid 'raw' types is added. |
|
401 */ |
|
402 gst_decode_bin_signals[SIGNAL_NEW_DECODED_PAD] = |
|
403 g_signal_new ("new-decoded-pad", G_TYPE_FROM_CLASS (klass), |
|
404 G_SIGNAL_RUN_LAST, |
|
405 G_STRUCT_OFFSET (GstDecodeBinClass, new_decoded_pad), NULL, NULL, |
|
406 gst_play_marshal_VOID__OBJECT_BOOLEAN, G_TYPE_NONE, 2, GST_TYPE_PAD, |
|
407 G_TYPE_BOOLEAN); |
|
408 |
|
409 /** |
|
410 * GstDecodeBin2::removed-decoded-pad: |
|
411 * @pad: the pad that was removed |
|
412 * |
|
413 * This signal is emitted when a 'final' caps pad has been removed. |
|
414 */ |
|
415 gst_decode_bin_signals[SIGNAL_REMOVED_DECODED_PAD] = |
|
416 g_signal_new ("removed-decoded-pad", G_TYPE_FROM_CLASS (klass), |
|
417 G_SIGNAL_RUN_LAST, |
|
418 G_STRUCT_OFFSET (GstDecodeBinClass, removed_decoded_pad), NULL, NULL, |
|
419 gst_marshal_VOID__OBJECT, G_TYPE_NONE, 1, GST_TYPE_PAD); |
|
420 |
|
421 /** |
|
422 * GstDecodeBin2::unknown-type: |
|
423 * @pad: the new pad containing caps that cannot be resolved to a 'final' stream type. |
|
424 * @caps: the #GstCaps of the pad that cannot be resolved. |
|
425 * |
|
426 * This signal is emitted when a pad for which there is no further possible |
|
427 * decoding is added to the decodebin. |
|
428 */ |
|
429 gst_decode_bin_signals[SIGNAL_UNKNOWN_TYPE] = |
|
430 g_signal_new ("unknown-type", G_TYPE_FROM_CLASS (klass), |
|
431 G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstDecodeBinClass, unknown_type), |
|
432 NULL, NULL, gst_marshal_VOID__OBJECT_OBJECT, G_TYPE_NONE, 2, |
|
433 GST_TYPE_PAD, GST_TYPE_CAPS); |
|
434 |
|
435 /** |
|
436 * GstDecodeBin2::autoplug-continue: |
|
437 * @pad: The #GstPad. |
|
438 * @caps: The #GstCaps found. |
|
439 * |
|
440 * This signal is emitted whenever decodebin2 finds a new stream. It is |
|
441 * emitted before looking for any elements that can handle that stream. |
|
442 * |
|
443 * Returns: #TRUE if you wish decodebin2 to look for elements that can |
|
444 * handle the given @caps. If #FALSE, those caps will be considered as |
|
445 * final and the pad will be exposed as such (see 'new-decoded-pad' |
|
446 * signal). |
|
447 */ |
|
448 gst_decode_bin_signals[SIGNAL_AUTOPLUG_CONTINUE] = |
|
449 g_signal_new ("autoplug-continue", G_TYPE_FROM_CLASS (klass), |
|
450 G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstDecodeBinClass, autoplug_continue), |
|
451 _gst_boolean_accumulator, NULL, gst_play_marshal_BOOLEAN__OBJECT_OBJECT, |
|
452 G_TYPE_BOOLEAN, 2, GST_TYPE_PAD, GST_TYPE_CAPS); |
|
453 |
|
454 /** |
|
455 * GstDecodeBin2::autoplug-factories: |
|
456 * @pad: The #GstPad. |
|
457 * @caps: The #GstCaps found. |
|
458 * |
|
459 * This function is emited when an array of possible factories for @caps on |
|
460 * @pad is needed. Decodebin2 will by default return an array with all |
|
461 * compatible factories, sorted by rank. |
|
462 * |
|
463 * If this function returns NULL, @pad will be exposed as a final caps. |
|
464 * |
|
465 * If this function returns an empty array, the pad will be considered as |
|
466 * having an unhandled type media type. |
|
467 * |
|
468 * Returns: a #GValueArray* with a list of factories to try. The factories are |
|
469 * by default tried in the returned order or based on the index returned by |
|
470 * "autoplug-select". |
|
471 */ |
|
472 gst_decode_bin_signals[SIGNAL_AUTOPLUG_FACTORIES] = |
|
473 g_signal_new ("autoplug-factories", G_TYPE_FROM_CLASS (klass), |
|
474 G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstDecodeBinClass, |
|
475 autoplug_factories), _gst_array_accumulator, NULL, |
|
476 gst_play_marshal_BOXED__OBJECT_OBJECT, G_TYPE_VALUE_ARRAY, 2, |
|
477 GST_TYPE_PAD, GST_TYPE_CAPS); |
|
478 |
|
479 /** |
|
480 * GstDecodeBin2::autoplug-sort: |
|
481 * @pad: The #GstPad. |
|
482 * @caps: The #GstCaps. |
|
483 * @factories: A #GValueArray of possible #GstElementFactory to use. |
|
484 * |
|
485 * Once decodebin2 has found the possible #GstElementFactory objects to try |
|
486 * for @caps on @pad, this signal is emited. The purpose of the signal is for |
|
487 * the application to perform additional sorting or filtering on the element |
|
488 * factory array. |
|
489 * |
|
490 * The callee should copy and modify @factories. |
|
491 * |
|
492 * Returns: A new sorted array of #GstElementFactory objects. |
|
493 */ |
|
494 gst_decode_bin_signals[SIGNAL_AUTOPLUG_SORT] = |
|
495 g_signal_new ("autoplug-sort", G_TYPE_FROM_CLASS (klass), |
|
496 G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstDecodeBinClass, autoplug_sort), |
|
497 NULL, NULL, gst_play_marshal_BOXED__OBJECT_OBJECT_BOXED, |
|
498 G_TYPE_VALUE_ARRAY, 3, GST_TYPE_PAD, GST_TYPE_CAPS, G_TYPE_VALUE_ARRAY); |
|
499 |
|
500 /** |
|
501 * GstDecodeBin2::autoplug-select: |
|
502 * @pad: The #GstPad. |
|
503 * @caps: The #GstCaps. |
|
504 * @factories: A #GValueArray of possible #GstElementFactory to use, sorted by |
|
505 * rank (higher ranks come first). |
|
506 * |
|
507 * This signal is emitted once decodebin2 has found all the possible |
|
508 * #GstElementFactory that can be used to handle the given @caps. |
|
509 * |
|
510 * Returns: A #gint indicating what factory index from the @factories array |
|
511 * that you wish decodebin2 to use for trying to decode the given @caps. |
|
512 * Return -1 to stop selection of a factory and expose the pad as a raw type. |
|
513 * The default handler always returns the first possible factory (index 0). |
|
514 */ |
|
515 gst_decode_bin_signals[SIGNAL_AUTOPLUG_SELECT] = |
|
516 g_signal_new ("autoplug-select", G_TYPE_FROM_CLASS (klass), |
|
517 G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstDecodeBinClass, autoplug_select), |
|
518 _gst_select_accumulator, NULL, |
|
519 gst_play_marshal_ENUM__OBJECT_OBJECT_OBJECT, |
|
520 GST_TYPE_AUTOPLUG_SELECT_RESULT, 3, GST_TYPE_PAD, GST_TYPE_CAPS, |
|
521 GST_TYPE_ELEMENT_FACTORY); |
|
522 |
|
523 /** |
|
524 * GstDecodeBin2::drained |
|
525 * |
|
526 * This signal is emitted once decodebin2 has finished decoding all the data. |
|
527 * |
|
528 * Since: 0.10.16 |
|
529 */ |
|
530 gst_decode_bin_signals[SIGNAL_DRAINED] = |
|
531 g_signal_new ("drained", G_TYPE_FROM_CLASS (klass), |
|
532 G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstDecodeBinClass, drained), |
|
533 NULL, NULL, gst_marshal_VOID__VOID, G_TYPE_NONE, 0, G_TYPE_NONE); |
|
534 |
|
535 g_object_class_install_property (gobject_klass, PROP_CAPS, |
|
536 g_param_spec_boxed ("caps", "Caps", "The caps on which to stop decoding.", |
|
537 GST_TYPE_CAPS, G_PARAM_READWRITE)); |
|
538 |
|
539 g_object_class_install_property (gobject_klass, PROP_SUBTITLE_ENCODING, |
|
540 g_param_spec_string ("subtitle-encoding", "subtitle encoding", |
|
541 "Encoding to assume if input subtitles are not in UTF-8 encoding. " |
|
542 "If not set, the GST_SUBTITLE_ENCODING environment variable will " |
|
543 "be checked for an encoding to use. If that is not set either, " |
|
544 "ISO-8859-15 will be assumed.", NULL, G_PARAM_READWRITE)); |
|
545 |
|
546 klass->autoplug_continue = |
|
547 GST_DEBUG_FUNCPTR (gst_decode_bin_autoplug_continue); |
|
548 klass->autoplug_factories = |
|
549 GST_DEBUG_FUNCPTR (gst_decode_bin_autoplug_factories); |
|
550 klass->autoplug_sort = GST_DEBUG_FUNCPTR (gst_decode_bin_autoplug_sort); |
|
551 klass->autoplug_select = GST_DEBUG_FUNCPTR (gst_decode_bin_autoplug_select); |
|
552 |
|
553 gst_element_class_add_pad_template (gstelement_klass, |
|
554 gst_static_pad_template_get (&decoder_bin_sink_template)); |
|
555 gst_element_class_add_pad_template (gstelement_klass, |
|
556 gst_static_pad_template_get (&decoder_bin_src_template)); |
|
557 |
|
558 gst_element_class_set_details (gstelement_klass, &gst_decode_bin_details); |
|
559 |
|
560 gstelement_klass->change_state = |
|
561 GST_DEBUG_FUNCPTR (gst_decode_bin_change_state); |
|
562 } |
|
563 |
|
564 static void |
|
565 gst_decode_bin_init (GstDecodeBin * decode_bin) |
|
566 { |
|
567 /* first filter out the interesting element factories */ |
|
568 decode_bin->factories = |
|
569 gst_factory_list_get_elements (GST_FACTORY_LIST_DECODER); |
|
570 |
|
571 /* we create the typefind element only once */ |
|
572 decode_bin->typefind = gst_element_factory_make ("typefind", "typefind"); |
|
573 if (!decode_bin->typefind) { |
|
574 g_warning ("can't find typefind element, decodebin will not work"); |
|
575 } else { |
|
576 GstPad *pad; |
|
577 GstPad *gpad; |
|
578 |
|
579 /* add the typefind element */ |
|
580 if (!gst_bin_add (GST_BIN (decode_bin), decode_bin->typefind)) { |
|
581 g_warning ("Could not add typefind element, decodebin will not work"); |
|
582 gst_object_unref (decode_bin->typefind); |
|
583 decode_bin->typefind = NULL; |
|
584 } |
|
585 |
|
586 /* get the sinkpad */ |
|
587 pad = gst_element_get_pad (decode_bin->typefind, "sink"); |
|
588 |
|
589 /* ghost the sink pad to ourself */ |
|
590 gpad = gst_ghost_pad_new ("sink", pad); |
|
591 gst_pad_set_active (gpad, TRUE); |
|
592 gst_element_add_pad (GST_ELEMENT (decode_bin), gpad); |
|
593 |
|
594 gst_object_unref (pad); |
|
595 |
|
596 /* connect a signal to find out when the typefind element found |
|
597 * a type */ |
|
598 decode_bin->have_type_id = |
|
599 g_signal_connect (G_OBJECT (decode_bin->typefind), "have-type", |
|
600 G_CALLBACK (type_found), decode_bin); |
|
601 } |
|
602 |
|
603 decode_bin->lock = g_mutex_new (); |
|
604 decode_bin->activegroup = NULL; |
|
605 decode_bin->groups = NULL; |
|
606 |
|
607 decode_bin->caps = |
|
608 gst_caps_from_string ("video/x-raw-yuv;video/x-raw-rgb;video/x-raw-gray;" |
|
609 "audio/x-raw-int;audio/x-raw-float;" "text/plain;text/x-pango-markup"); |
|
610 |
|
611 add_fakesink (decode_bin); |
|
612 |
|
613 /* FILLME */ |
|
614 } |
|
615 |
|
616 static void |
|
617 gst_decode_bin_dispose (GObject * object) |
|
618 { |
|
619 GstDecodeBin *decode_bin; |
|
620 GList *tmp; |
|
621 |
|
622 decode_bin = GST_DECODE_BIN (object); |
|
623 |
|
624 if (decode_bin->factories) |
|
625 g_value_array_free (decode_bin->factories); |
|
626 decode_bin->factories = NULL; |
|
627 |
|
628 if (decode_bin->activegroup) { |
|
629 gst_decode_group_free (decode_bin->activegroup); |
|
630 decode_bin->activegroup = NULL; |
|
631 } |
|
632 |
|
633 /* remove groups */ |
|
634 for (tmp = decode_bin->groups; tmp; tmp = g_list_next (tmp)) { |
|
635 GstDecodeGroup *group = (GstDecodeGroup *) tmp->data; |
|
636 |
|
637 gst_decode_group_free (group); |
|
638 } |
|
639 g_list_free (decode_bin->groups); |
|
640 decode_bin->groups = NULL; |
|
641 |
|
642 for (tmp = decode_bin->oldgroups; tmp; tmp = g_list_next (tmp)) { |
|
643 GstDecodeGroup *group = (GstDecodeGroup *) tmp->data; |
|
644 |
|
645 gst_decode_group_free (group); |
|
646 } |
|
647 g_list_free (decode_bin->oldgroups); |
|
648 decode_bin->oldgroups = NULL; |
|
649 |
|
650 if (decode_bin->caps) |
|
651 gst_caps_unref (decode_bin->caps); |
|
652 decode_bin->caps = NULL; |
|
653 |
|
654 g_free (decode_bin->encoding); |
|
655 decode_bin->encoding = NULL; |
|
656 |
|
657 remove_fakesink (decode_bin); |
|
658 |
|
659 G_OBJECT_CLASS (parent_class)->dispose (object); |
|
660 } |
|
661 |
|
662 static void |
|
663 gst_decode_bin_finalize (GObject * object) |
|
664 { |
|
665 GstDecodeBin *decode_bin; |
|
666 |
|
667 decode_bin = GST_DECODE_BIN (object); |
|
668 |
|
669 if (decode_bin->lock) { |
|
670 g_mutex_free (decode_bin->lock); |
|
671 decode_bin->lock = NULL; |
|
672 } |
|
673 |
|
674 G_OBJECT_CLASS (parent_class)->finalize (object); |
|
675 } |
|
676 |
|
677 /* _set_caps |
|
678 * Changes the caps on which decodebin will stop decoding. |
|
679 * Will unref the previously set one. The refcount of the given caps will be |
|
680 * increased. |
|
681 * @caps can be NULL. |
|
682 * |
|
683 * MT-safe |
|
684 */ |
|
685 static void |
|
686 gst_decode_bin_set_caps (GstDecodeBin * dbin, GstCaps * caps) |
|
687 { |
|
688 GST_DEBUG_OBJECT (dbin, "Setting new caps: %" GST_PTR_FORMAT, caps); |
|
689 |
|
690 DECODE_BIN_LOCK (dbin); |
|
691 if (dbin->caps) |
|
692 gst_caps_unref (dbin->caps); |
|
693 if (caps) |
|
694 gst_caps_ref (caps); |
|
695 dbin->caps = caps; |
|
696 DECODE_BIN_UNLOCK (dbin); |
|
697 } |
|
698 |
|
699 /* _get_caps |
|
700 * Returns the currently configured caps on which decodebin will stop decoding. |
|
701 * The returned caps (if not NULL), will have its refcount incremented. |
|
702 * |
|
703 * MT-safe |
|
704 */ |
|
705 |
|
706 static GstCaps * |
|
707 gst_decode_bin_get_caps (GstDecodeBin * dbin) |
|
708 { |
|
709 GstCaps *caps; |
|
710 |
|
711 GST_DEBUG_OBJECT (dbin, "Getting currently set caps"); |
|
712 |
|
713 DECODE_BIN_LOCK (dbin); |
|
714 caps = dbin->caps; |
|
715 if (caps) |
|
716 gst_caps_ref (caps); |
|
717 DECODE_BIN_UNLOCK (dbin); |
|
718 |
|
719 return caps; |
|
720 } |
|
721 |
|
722 static void |
|
723 gst_decode_bin_set_subs_encoding (GstDecodeBin * dbin, const gchar * encoding) |
|
724 { |
|
725 GST_DEBUG_OBJECT (dbin, "Setting new encoding: %s", GST_STR_NULL (encoding)); |
|
726 |
|
727 DECODE_BIN_LOCK (dbin); |
|
728 g_free (dbin->encoding); |
|
729 dbin->encoding = g_strdup (encoding); |
|
730 DECODE_BIN_UNLOCK (dbin); |
|
731 } |
|
732 |
|
733 static gchar * |
|
734 gst_decode_bin_get_subs_encoding (GstDecodeBin * dbin) |
|
735 { |
|
736 gchar *encoding; |
|
737 |
|
738 GST_DEBUG_OBJECT (dbin, "Getting currently set encoding"); |
|
739 |
|
740 DECODE_BIN_LOCK (dbin); |
|
741 encoding = g_strdup (dbin->encoding); |
|
742 DECODE_BIN_UNLOCK (dbin); |
|
743 |
|
744 return encoding; |
|
745 } |
|
746 |
|
747 static void |
|
748 gst_decode_bin_set_property (GObject * object, guint prop_id, |
|
749 const GValue * value, GParamSpec * pspec) |
|
750 { |
|
751 GstDecodeBin *dbin; |
|
752 |
|
753 dbin = GST_DECODE_BIN (object); |
|
754 |
|
755 switch (prop_id) { |
|
756 case PROP_CAPS: |
|
757 gst_decode_bin_set_caps (dbin, g_value_get_boxed (value)); |
|
758 break; |
|
759 case PROP_SUBTITLE_ENCODING: |
|
760 gst_decode_bin_set_subs_encoding (dbin, g_value_get_string (value)); |
|
761 break; |
|
762 default: |
|
763 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); |
|
764 break; |
|
765 } |
|
766 } |
|
767 |
|
768 static void |
|
769 gst_decode_bin_get_property (GObject * object, guint prop_id, |
|
770 GValue * value, GParamSpec * pspec) |
|
771 { |
|
772 GstDecodeBin *dbin; |
|
773 |
|
774 dbin = GST_DECODE_BIN (object); |
|
775 switch (prop_id) { |
|
776 case PROP_CAPS: |
|
777 g_value_take_boxed (value, gst_decode_bin_get_caps (dbin)); |
|
778 break; |
|
779 case PROP_SUBTITLE_ENCODING: |
|
780 g_value_take_string (value, gst_decode_bin_get_subs_encoding (dbin)); |
|
781 break; |
|
782 default: |
|
783 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); |
|
784 break; |
|
785 } |
|
786 } |
|
787 |
|
788 |
|
789 static GValueArray *find_compatibles (GstDecodeBin * decode_bin, |
|
790 GstPad * pad, const GstCaps * caps); |
|
791 |
|
792 /***** |
|
793 * Default autoplug signal handlers |
|
794 *****/ |
|
795 static gboolean |
|
796 gst_decode_bin_autoplug_continue (GstElement * element, GstPad * pad, |
|
797 GstCaps * caps) |
|
798 { |
|
799 GST_DEBUG_OBJECT (element, "autoplug-continue returns TRUE"); |
|
800 |
|
801 /* by default we always continue */ |
|
802 return TRUE; |
|
803 } |
|
804 |
|
805 static GValueArray * |
|
806 gst_decode_bin_autoplug_factories (GstElement * element, GstPad * pad, |
|
807 GstCaps * caps) |
|
808 { |
|
809 GValueArray *result; |
|
810 |
|
811 /* return all compatible factories for caps */ |
|
812 result = find_compatibles (GST_DECODE_BIN (element), pad, caps); |
|
813 |
|
814 GST_DEBUG_OBJECT (element, "autoplug-factories returns %p", result); |
|
815 |
|
816 return result; |
|
817 } |
|
818 |
|
819 static GValueArray * |
|
820 gst_decode_bin_autoplug_sort (GstElement * element, GstPad * pad, |
|
821 GstCaps * caps, GValueArray * factories) |
|
822 { |
|
823 GValueArray *result; |
|
824 |
|
825 result = g_value_array_copy (factories); |
|
826 |
|
827 GST_DEBUG_OBJECT (element, "autoplug-sort returns %p", result); |
|
828 |
|
829 /* return input */ |
|
830 return result; |
|
831 } |
|
832 |
|
833 static GstAutoplugSelectResult |
|
834 gst_decode_bin_autoplug_select (GstElement * element, GstPad * pad, |
|
835 GstCaps * caps, GstElementFactory * factory) |
|
836 { |
|
837 GST_DEBUG_OBJECT (element, "default autoplug-select returns TRY"); |
|
838 |
|
839 /* Try factory. */ |
|
840 return GST_AUTOPLUG_SELECT_TRY; |
|
841 } |
|
842 |
|
843 /******** |
|
844 * Discovery methods |
|
845 *****/ |
|
846 |
|
847 static gboolean are_raw_caps (GstDecodeBin * dbin, GstCaps * caps); |
|
848 static gboolean is_demuxer_element (GstElement * srcelement); |
|
849 |
|
850 static gboolean connect_pad (GstDecodeBin * dbin, GstElement * src, |
|
851 GstPad * pad, GstCaps * caps, GValueArray * factories, |
|
852 GstDecodeGroup * group); |
|
853 static gboolean connect_element (GstDecodeBin * dbin, GstElement * element, |
|
854 GstDecodeGroup * group); |
|
855 static void expose_pad (GstDecodeBin * dbin, GstElement * src, GstPad * pad, |
|
856 GstDecodeGroup * group); |
|
857 |
|
858 static void pad_added_group_cb (GstElement * element, GstPad * pad, |
|
859 GstDecodeGroup * group); |
|
860 static void pad_removed_group_cb (GstElement * element, GstPad * pad, |
|
861 GstDecodeGroup * group); |
|
862 static void no_more_pads_group_cb (GstElement * element, |
|
863 GstDecodeGroup * group); |
|
864 static void pad_added_cb (GstElement * element, GstPad * pad, |
|
865 GstDecodeBin * dbin); |
|
866 static void pad_removed_cb (GstElement * element, GstPad * pad, |
|
867 GstDecodeBin * dbin); |
|
868 static void no_more_pads_cb (GstElement * element, GstDecodeBin * dbin); |
|
869 |
|
870 static GstDecodeGroup *get_current_group (GstDecodeBin * dbin); |
|
871 |
|
872 /* called when a new pad is discovered. It will perform some basic actions |
|
873 * before trying to link something to it. |
|
874 * |
|
875 * - Check the caps, don't do anything when there are no caps or when they have |
|
876 * no good type. |
|
877 * - signal AUTOPLUG_CONTINUE to check if we need to continue autoplugging this |
|
878 * pad. |
|
879 * - if the caps are non-fixed, setup a handler to continue autoplugging when |
|
880 * the caps become fixed (connect to notify::caps). |
|
881 * - get list of factories to autoplug. |
|
882 * - continue autoplugging to one of the factories. |
|
883 */ |
|
884 static void |
|
885 analyze_new_pad (GstDecodeBin * dbin, GstElement * src, GstPad * pad, |
|
886 GstCaps * caps, GstDecodeGroup * group) |
|
887 { |
|
888 gboolean apcontinue = TRUE; |
|
889 GValueArray *factories = NULL, *result = NULL; |
|
890 |
|
891 GST_DEBUG_OBJECT (dbin, "Pad %s:%s caps:%" GST_PTR_FORMAT, |
|
892 GST_DEBUG_PAD_NAME (pad), caps); |
|
893 |
|
894 if ((caps == NULL) || gst_caps_is_empty (caps)) |
|
895 goto unknown_type; |
|
896 |
|
897 if (gst_caps_is_any (caps)) |
|
898 goto any_caps; |
|
899 |
|
900 /* 1. Emit 'autoplug-continue' the result will tell us if this pads needs |
|
901 * further autoplugging. */ |
|
902 g_signal_emit (G_OBJECT (dbin), |
|
903 gst_decode_bin_signals[SIGNAL_AUTOPLUG_CONTINUE], 0, pad, caps, |
|
904 &apcontinue); |
|
905 |
|
906 /* 1.a if autoplug-continue is FALSE or caps is a raw format, goto pad_is_final */ |
|
907 if ((!apcontinue) || are_raw_caps (dbin, caps)) |
|
908 goto expose_pad; |
|
909 |
|
910 /* 1.b when the caps are not fixed yet, we can't be sure what element to |
|
911 * connect. We delay autoplugging until the caps are fixed */ |
|
912 if (!gst_caps_is_fixed (caps)) |
|
913 goto non_fixed; |
|
914 |
|
915 /* 1.c else get the factories and if there's no compatible factory goto |
|
916 * unknown_type */ |
|
917 g_signal_emit (G_OBJECT (dbin), |
|
918 gst_decode_bin_signals[SIGNAL_AUTOPLUG_FACTORIES], 0, pad, caps, |
|
919 &factories); |
|
920 |
|
921 /* NULL means that we can expose the pad */ |
|
922 if (factories == NULL) |
|
923 goto expose_pad; |
|
924 |
|
925 /* if the array is empty, we have an unknown type */ |
|
926 if (factories->n_values == 0) { |
|
927 /* no compatible factories */ |
|
928 g_value_array_free (factories); |
|
929 goto unknown_type; |
|
930 } |
|
931 |
|
932 /* 1.d sort some more. */ |
|
933 g_signal_emit (G_OBJECT (dbin), |
|
934 gst_decode_bin_signals[SIGNAL_AUTOPLUG_SORT], 0, pad, caps, factories, |
|
935 &result); |
|
936 g_value_array_free (factories); |
|
937 factories = result; |
|
938 |
|
939 /* 1.e else continue autoplugging something from the list. */ |
|
940 GST_LOG_OBJECT (pad, "Let's continue discovery on this pad"); |
|
941 connect_pad (dbin, src, pad, caps, factories, group); |
|
942 |
|
943 g_value_array_free (factories); |
|
944 |
|
945 return; |
|
946 |
|
947 expose_pad: |
|
948 { |
|
949 GST_LOG_OBJECT (dbin, "Pad is final. autoplug-continue:%d", apcontinue); |
|
950 expose_pad (dbin, src, pad, group); |
|
951 return; |
|
952 } |
|
953 unknown_type: |
|
954 { |
|
955 GST_LOG_OBJECT (pad, "Unknown type, firing signal"); |
|
956 g_signal_emit (G_OBJECT (dbin), |
|
957 gst_decode_bin_signals[SIGNAL_UNKNOWN_TYPE], 0, pad, caps); |
|
958 |
|
959 /* Check if there are no pending groups, if so, remove fakesink */ |
|
960 if (dbin->groups == NULL) |
|
961 remove_fakesink (dbin); |
|
962 |
|
963 if (src == dbin->typefind) { |
|
964 gchar *desc; |
|
965 |
|
966 desc = gst_pb_utils_get_decoder_description (caps); |
|
967 GST_ELEMENT_ERROR (dbin, STREAM, CODEC_NOT_FOUND, |
|
968 (_("A %s plugin is required to play this stream, but not installed."), |
|
969 desc), |
|
970 ("No decoder to handle media type '%s'", |
|
971 gst_structure_get_name (gst_caps_get_structure (caps, 0)))); |
|
972 g_free (desc); |
|
973 } |
|
974 |
|
975 gst_element_post_message (GST_ELEMENT_CAST (dbin), |
|
976 gst_missing_decoder_message_new (GST_ELEMENT_CAST (dbin), caps)); |
|
977 return; |
|
978 } |
|
979 non_fixed: |
|
980 { |
|
981 GST_DEBUG_OBJECT (pad, "pad has non-fixed caps delay autoplugging"); |
|
982 goto setup_caps_delay; |
|
983 } |
|
984 any_caps: |
|
985 { |
|
986 GST_WARNING_OBJECT (pad, |
|
987 "pad has ANY caps, not able to autoplug to anything"); |
|
988 goto setup_caps_delay; |
|
989 } |
|
990 setup_caps_delay: |
|
991 { |
|
992 /* connect to caps notification */ |
|
993 if (group) { |
|
994 GROUP_MUTEX_LOCK (group); |
|
995 group->nbdynamic++; |
|
996 GST_LOG ("Group %p has now %d dynamic elements", group, group->nbdynamic); |
|
997 GROUP_MUTEX_UNLOCK (group); |
|
998 g_signal_connect (G_OBJECT (pad), "notify::caps", |
|
999 G_CALLBACK (caps_notify_group_cb), group); |
|
1000 } else |
|
1001 g_signal_connect (G_OBJECT (pad), "notify::caps", |
|
1002 G_CALLBACK (caps_notify_cb), dbin); |
|
1003 return; |
|
1004 } |
|
1005 } |
|
1006 |
|
1007 |
|
1008 /* connect_pad: |
|
1009 * |
|
1010 * Try to connect the given pad to an element created from one of the factories, |
|
1011 * and recursively. |
|
1012 * |
|
1013 * Returns TRUE if an element was properly created and linked |
|
1014 */ |
|
1015 static gboolean |
|
1016 connect_pad (GstDecodeBin * dbin, GstElement * src, GstPad * pad, |
|
1017 GstCaps * caps, GValueArray * factories, GstDecodeGroup * group) |
|
1018 { |
|
1019 gboolean res = FALSE; |
|
1020 GstPad *mqpad = NULL; |
|
1021 |
|
1022 g_return_val_if_fail (factories != NULL, FALSE); |
|
1023 g_return_val_if_fail (factories->n_values > 0, FALSE); |
|
1024 |
|
1025 GST_DEBUG_OBJECT (dbin, "pad %s:%s , group:%p", |
|
1026 GST_DEBUG_PAD_NAME (pad), group); |
|
1027 |
|
1028 /* 1. is element demuxer or parser */ |
|
1029 if (is_demuxer_element (src)) { |
|
1030 GST_LOG_OBJECT (src, "is a demuxer, connecting the pad through multiqueue"); |
|
1031 |
|
1032 if (!group) |
|
1033 if (!(group = get_current_group (dbin))) { |
|
1034 group = gst_decode_group_new (dbin, TRUE); |
|
1035 DECODE_BIN_LOCK (dbin); |
|
1036 dbin->groups = g_list_append (dbin->groups, group); |
|
1037 DECODE_BIN_UNLOCK (dbin); |
|
1038 } |
|
1039 |
|
1040 if (!(mqpad = gst_decode_group_control_demuxer_pad (group, pad))) |
|
1041 goto beach; |
|
1042 src = group->multiqueue; |
|
1043 pad = mqpad; |
|
1044 } |
|
1045 |
|
1046 /* 2. Try to create an element and link to it */ |
|
1047 while (factories->n_values > 0) { |
|
1048 GstAutoplugSelectResult ret; |
|
1049 GstElementFactory *factory; |
|
1050 GstElement *element; |
|
1051 GstPad *sinkpad; |
|
1052 |
|
1053 /* take first factory */ |
|
1054 factory = g_value_get_object (g_value_array_get_nth (factories, 0)); |
|
1055 /* Remove selected factory from the list. */ |
|
1056 g_value_array_remove (factories, 0); |
|
1057 |
|
1058 /* emit autoplug-select to see what we should do with it. */ |
|
1059 g_signal_emit (G_OBJECT (dbin), |
|
1060 gst_decode_bin_signals[SIGNAL_AUTOPLUG_SELECT], |
|
1061 0, pad, caps, factory, &ret); |
|
1062 |
|
1063 switch (ret) { |
|
1064 case GST_AUTOPLUG_SELECT_TRY: |
|
1065 GST_DEBUG_OBJECT (dbin, "autoplug select requested try"); |
|
1066 break; |
|
1067 case GST_AUTOPLUG_SELECT_EXPOSE: |
|
1068 GST_DEBUG_OBJECT (dbin, "autoplug select requested expose"); |
|
1069 /* expose the pad, we don't have the source element */ |
|
1070 expose_pad (dbin, src, pad, group); |
|
1071 res = TRUE; |
|
1072 goto beach; |
|
1073 case GST_AUTOPLUG_SELECT_SKIP: |
|
1074 GST_DEBUG_OBJECT (dbin, "autoplug select requested skip"); |
|
1075 continue; |
|
1076 default: |
|
1077 GST_WARNING_OBJECT (dbin, "autoplug select returned unhandled %d", ret); |
|
1078 break; |
|
1079 } |
|
1080 |
|
1081 /* 2.1. Try to create an element */ |
|
1082 if ((element = gst_element_factory_create (factory, NULL)) == NULL) { |
|
1083 GST_WARNING_OBJECT (dbin, "Could not create an element from %s", |
|
1084 gst_plugin_feature_get_name (GST_PLUGIN_FEATURE (factory))); |
|
1085 continue; |
|
1086 } |
|
1087 |
|
1088 /* ... activate it ... We do this before adding it to the bin so that we |
|
1089 * don't accidentally make it post error messages that will stop |
|
1090 * everything. */ |
|
1091 if ((gst_element_set_state (element, |
|
1092 GST_STATE_READY)) == GST_STATE_CHANGE_FAILURE) { |
|
1093 GST_WARNING_OBJECT (dbin, "Couldn't set %s to READY", |
|
1094 GST_ELEMENT_NAME (element)); |
|
1095 gst_object_unref (element); |
|
1096 continue; |
|
1097 } |
|
1098 |
|
1099 /* 2.3. Find its sink pad, this should work after activating it. */ |
|
1100 if (!(sinkpad = find_sink_pad (element))) { |
|
1101 GST_WARNING_OBJECT (dbin, "Element %s doesn't have a sink pad", |
|
1102 GST_ELEMENT_NAME (element)); |
|
1103 gst_object_unref (element); |
|
1104 continue; |
|
1105 } |
|
1106 |
|
1107 /* 2.4 add it ... */ |
|
1108 if (!(gst_bin_add (GST_BIN_CAST (dbin), element))) { |
|
1109 GST_WARNING_OBJECT (dbin, "Couldn't add %s to the bin", |
|
1110 GST_ELEMENT_NAME (element)); |
|
1111 gst_object_unref (sinkpad); |
|
1112 gst_object_unref (element); |
|
1113 continue; |
|
1114 } |
|
1115 |
|
1116 /* 2.5 ...and try to link */ |
|
1117 if ((gst_pad_link (pad, sinkpad)) != GST_PAD_LINK_OK) { |
|
1118 GST_WARNING_OBJECT (dbin, "Link failed on pad %s:%s", |
|
1119 GST_DEBUG_PAD_NAME (sinkpad)); |
|
1120 gst_element_set_state (element, GST_STATE_NULL); |
|
1121 gst_object_unref (sinkpad); |
|
1122 gst_bin_remove (GST_BIN (dbin), element); |
|
1123 continue; |
|
1124 } |
|
1125 gst_object_unref (sinkpad); |
|
1126 GST_LOG_OBJECT (dbin, "linked on pad %s:%s", GST_DEBUG_PAD_NAME (pad)); |
|
1127 |
|
1128 /* link this element further */ |
|
1129 connect_element (dbin, element, group); |
|
1130 |
|
1131 /* Bring the element to the state of the parent */ |
|
1132 if ((gst_element_set_state (element, |
|
1133 GST_STATE_PAUSED)) == GST_STATE_CHANGE_FAILURE) { |
|
1134 GST_WARNING_OBJECT (dbin, "Couldn't set %s to PAUSED", |
|
1135 GST_ELEMENT_NAME (element)); |
|
1136 gst_element_set_state (element, GST_STATE_NULL); |
|
1137 gst_bin_remove (GST_BIN (dbin), element); |
|
1138 continue; |
|
1139 } |
|
1140 |
|
1141 res = TRUE; |
|
1142 break; |
|
1143 } |
|
1144 |
|
1145 beach: |
|
1146 if (mqpad) |
|
1147 gst_object_unref (mqpad); |
|
1148 |
|
1149 return res; |
|
1150 } |
|
1151 |
|
1152 static gboolean |
|
1153 connect_element (GstDecodeBin * dbin, GstElement * element, |
|
1154 GstDecodeGroup * group) |
|
1155 { |
|
1156 GList *pads; |
|
1157 gboolean res = TRUE; |
|
1158 gboolean dynamic = FALSE; |
|
1159 GList *to_connect = NULL; |
|
1160 |
|
1161 GST_DEBUG_OBJECT (dbin, "Attempting to connect element %s [group:%p] further", |
|
1162 GST_ELEMENT_NAME (element), group); |
|
1163 |
|
1164 /* 1. Loop over pad templates, grabbing existing pads along the way */ |
|
1165 for (pads = GST_ELEMENT_GET_CLASS (element)->padtemplates; pads; |
|
1166 pads = g_list_next (pads)) { |
|
1167 GstPadTemplate *templ = GST_PAD_TEMPLATE (pads->data); |
|
1168 const gchar *templ_name; |
|
1169 |
|
1170 /* we are only interested in source pads */ |
|
1171 if (GST_PAD_TEMPLATE_DIRECTION (templ) != GST_PAD_SRC) |
|
1172 continue; |
|
1173 |
|
1174 templ_name = GST_PAD_TEMPLATE_NAME_TEMPLATE (templ); |
|
1175 GST_DEBUG_OBJECT (dbin, "got a source pad template %s", templ_name); |
|
1176 |
|
1177 /* figure out what kind of pad this is */ |
|
1178 switch (GST_PAD_TEMPLATE_PRESENCE (templ)) { |
|
1179 case GST_PAD_ALWAYS: |
|
1180 { |
|
1181 /* get the pad that we need to autoplug */ |
|
1182 GstPad *pad = gst_element_get_pad (element, templ_name); |
|
1183 |
|
1184 if (pad) { |
|
1185 GST_DEBUG_OBJECT (dbin, "got the pad for always template %s", |
|
1186 templ_name); |
|
1187 /* here is the pad, we need to autoplug it */ |
|
1188 to_connect = g_list_prepend (to_connect, pad); |
|
1189 } else { |
|
1190 /* strange, pad is marked as always but it's not |
|
1191 * there. Fix the element */ |
|
1192 GST_WARNING_OBJECT (dbin, |
|
1193 "could not get the pad for always template %s", templ_name); |
|
1194 } |
|
1195 break; |
|
1196 } |
|
1197 case GST_PAD_SOMETIMES: |
|
1198 { |
|
1199 /* try to get the pad to see if it is already created or |
|
1200 * not */ |
|
1201 GstPad *pad = gst_element_get_pad (element, templ_name); |
|
1202 |
|
1203 if (pad) { |
|
1204 GST_DEBUG_OBJECT (dbin, "got the pad for sometimes template %s", |
|
1205 templ_name); |
|
1206 /* the pad is created, we need to autoplug it */ |
|
1207 to_connect = g_list_prepend (to_connect, pad); |
|
1208 } else { |
|
1209 GST_DEBUG_OBJECT (dbin, |
|
1210 "did not get the sometimes pad of template %s", templ_name); |
|
1211 /* we have an element that will create dynamic pads */ |
|
1212 dynamic = TRUE; |
|
1213 } |
|
1214 break; |
|
1215 } |
|
1216 case GST_PAD_REQUEST: |
|
1217 /* ignore request pads */ |
|
1218 GST_DEBUG_OBJECT (dbin, "ignoring request padtemplate %s", templ_name); |
|
1219 break; |
|
1220 } |
|
1221 } |
|
1222 |
|
1223 /* 2. if there are more potential pads, connect to relevent signals */ |
|
1224 if (dynamic) { |
|
1225 if (group) { |
|
1226 GST_LOG ("Adding signals to element %s in group %p", |
|
1227 GST_ELEMENT_NAME (element), group); |
|
1228 GROUP_MUTEX_LOCK (group); |
|
1229 group->nbdynamic++; |
|
1230 GST_LOG ("Group %p has now %d dynamic elements", group, group->nbdynamic); |
|
1231 GROUP_MUTEX_UNLOCK (group); |
|
1232 g_signal_connect (G_OBJECT (element), "pad-added", |
|
1233 G_CALLBACK (pad_added_group_cb), group); |
|
1234 g_signal_connect (G_OBJECT (element), "pad-removed", |
|
1235 G_CALLBACK (pad_removed_group_cb), group); |
|
1236 g_signal_connect (G_OBJECT (element), "no-more-pads", |
|
1237 G_CALLBACK (no_more_pads_group_cb), group); |
|
1238 } else { |
|
1239 /* This is a non-grouped element, the handlers are different */ |
|
1240 g_signal_connect (G_OBJECT (element), "pad-added", |
|
1241 G_CALLBACK (pad_added_cb), dbin); |
|
1242 g_signal_connect (G_OBJECT (element), "pad-removed", |
|
1243 G_CALLBACK (pad_removed_cb), dbin); |
|
1244 g_signal_connect (G_OBJECT (element), "no-more-pads", |
|
1245 G_CALLBACK (no_more_pads_cb), dbin); |
|
1246 } |
|
1247 } |
|
1248 |
|
1249 /* 3. for every available pad, connect it */ |
|
1250 for (pads = to_connect; pads; pads = g_list_next (pads)) { |
|
1251 GstPad *pad = GST_PAD_CAST (pads->data); |
|
1252 GstCaps *caps; |
|
1253 |
|
1254 caps = gst_pad_get_caps (pad); |
|
1255 analyze_new_pad (dbin, element, pad, caps, group); |
|
1256 if (caps) |
|
1257 gst_caps_unref (caps); |
|
1258 |
|
1259 gst_object_unref (pad); |
|
1260 } |
|
1261 g_list_free (to_connect); |
|
1262 |
|
1263 return res; |
|
1264 } |
|
1265 |
|
1266 /* expose_pad: |
|
1267 * |
|
1268 * Expose the given pad on the group as a decoded pad. |
|
1269 * If group is NULL, a GstDecodeGroup will be created and setup properly. |
|
1270 */ |
|
1271 static void |
|
1272 expose_pad (GstDecodeBin * dbin, GstElement * src, GstPad * pad, |
|
1273 GstDecodeGroup * group) |
|
1274 { |
|
1275 gboolean newgroup = FALSE; |
|
1276 gboolean isdemux; |
|
1277 GstPad *mqpad = NULL; |
|
1278 |
|
1279 GST_DEBUG_OBJECT (dbin, "pad %s:%s, group:%p", |
|
1280 GST_DEBUG_PAD_NAME (pad), group); |
|
1281 |
|
1282 isdemux = is_demuxer_element (src); |
|
1283 |
|
1284 if (!group) |
|
1285 if (!(group = get_current_group (dbin))) { |
|
1286 group = gst_decode_group_new (dbin, isdemux); |
|
1287 DECODE_BIN_LOCK (dbin); |
|
1288 dbin->groups = g_list_append (dbin->groups, group); |
|
1289 DECODE_BIN_UNLOCK (dbin); |
|
1290 newgroup = TRUE; |
|
1291 } |
|
1292 |
|
1293 if (isdemux) { |
|
1294 GST_LOG_OBJECT (src, "connecting the pad through multiqueue"); |
|
1295 |
|
1296 if (!(mqpad = gst_decode_group_control_demuxer_pad (group, pad))) |
|
1297 goto beach; |
|
1298 pad = mqpad; |
|
1299 } |
|
1300 |
|
1301 gst_decode_group_control_source_pad (group, pad); |
|
1302 |
|
1303 if (newgroup && !isdemux) { |
|
1304 /* If we have discovered a raw pad and it doesn't belong to any group, |
|
1305 * that means there wasn't any demuxer. In that case, we consider the |
|
1306 * group as being complete. */ |
|
1307 gst_decode_group_set_complete (group); |
|
1308 } |
|
1309 if (mqpad) |
|
1310 gst_object_unref (mqpad); |
|
1311 |
|
1312 beach: |
|
1313 return; |
|
1314 } |
|
1315 |
|
1316 static void |
|
1317 type_found (GstElement * typefind, guint probability, |
|
1318 GstCaps * caps, GstDecodeBin * decode_bin) |
|
1319 { |
|
1320 GstPad *pad; |
|
1321 |
|
1322 GST_DEBUG_OBJECT (decode_bin, "typefind found caps %" GST_PTR_FORMAT, caps); |
|
1323 |
|
1324 /* we can only deal with one type, we don't yet support dynamically changing |
|
1325 * caps from the typefind element */ |
|
1326 if (decode_bin->have_type) |
|
1327 goto exit; |
|
1328 |
|
1329 decode_bin->have_type = TRUE; |
|
1330 |
|
1331 pad = gst_element_get_static_pad (typefind, "src"); |
|
1332 |
|
1333 analyze_new_pad (decode_bin, typefind, pad, caps, NULL); |
|
1334 |
|
1335 gst_object_unref (pad); |
|
1336 |
|
1337 exit: |
|
1338 return; |
|
1339 } |
|
1340 |
|
1341 static void |
|
1342 pad_added_group_cb (GstElement * element, GstPad * pad, GstDecodeGroup * group) |
|
1343 { |
|
1344 GstCaps *caps; |
|
1345 gboolean expose = FALSE; |
|
1346 |
|
1347 GST_DEBUG_OBJECT (pad, "pad added, group:%p", group); |
|
1348 |
|
1349 caps = gst_pad_get_caps (pad); |
|
1350 analyze_new_pad (group->dbin, element, pad, caps, group); |
|
1351 if (caps) |
|
1352 gst_caps_unref (caps); |
|
1353 |
|
1354 GROUP_MUTEX_LOCK (group); |
|
1355 group->nbdynamic--; |
|
1356 GST_LOG ("Group %p has now %d dynamic objects", group, group->nbdynamic); |
|
1357 if (group->nbdynamic == 0) |
|
1358 expose = TRUE; |
|
1359 GROUP_MUTEX_UNLOCK (group); |
|
1360 |
|
1361 if (expose) { |
|
1362 GST_LOG |
|
1363 ("That was the last dynamic object, now attempting to expose the group"); |
|
1364 DECODE_BIN_LOCK (group->dbin); |
|
1365 gst_decode_group_expose (group); |
|
1366 DECODE_BIN_UNLOCK (group->dbin); |
|
1367 } |
|
1368 } |
|
1369 |
|
1370 static void |
|
1371 pad_removed_group_cb (GstElement * element, GstPad * pad, |
|
1372 GstDecodeGroup * group) |
|
1373 { |
|
1374 GST_LOG_OBJECT (pad, "pad removed, group:%p", group); |
|
1375 |
|
1376 /* In fact, we don't have to do anything here, the active group will be |
|
1377 * removed when the group's multiqueue is drained */ |
|
1378 } |
|
1379 |
|
1380 static void |
|
1381 no_more_pads_group_cb (GstElement * element, GstDecodeGroup * group) |
|
1382 { |
|
1383 GST_LOG_OBJECT (element, "no more pads, setting group %p to complete", group); |
|
1384 |
|
1385 /* FIXME : FILLME */ |
|
1386 gst_decode_group_set_complete (group); |
|
1387 } |
|
1388 |
|
1389 static void |
|
1390 pad_added_cb (GstElement * element, GstPad * pad, GstDecodeBin * dbin) |
|
1391 { |
|
1392 GstCaps *caps; |
|
1393 |
|
1394 GST_LOG_OBJECT (pad, "Pad added to non-grouped element"); |
|
1395 |
|
1396 caps = gst_pad_get_caps (pad); |
|
1397 analyze_new_pad (dbin, element, pad, caps, NULL); |
|
1398 if (caps) |
|
1399 gst_caps_unref (caps); |
|
1400 } |
|
1401 |
|
1402 static void |
|
1403 pad_removed_cb (GstElement * element, GstPad * pad, GstDecodeBin * dbin) |
|
1404 { |
|
1405 GST_LOG_OBJECT (pad, "Pad removed from non-grouped element"); |
|
1406 } |
|
1407 |
|
1408 static void |
|
1409 no_more_pads_cb (GstElement * element, GstDecodeBin * dbin) |
|
1410 { |
|
1411 GstDecodeGroup *group; |
|
1412 |
|
1413 GST_LOG_OBJECT (element, "No more pads, setting current group to complete"); |
|
1414 |
|
1415 /* Find the non-complete group, there should only be one */ |
|
1416 if (!(group = get_current_group (dbin))) |
|
1417 goto no_group; |
|
1418 |
|
1419 gst_decode_group_set_complete (group); |
|
1420 return; |
|
1421 |
|
1422 no_group: |
|
1423 { |
|
1424 GST_WARNING_OBJECT (dbin, "We couldn't find a non-completed group !!"); |
|
1425 return; |
|
1426 } |
|
1427 } |
|
1428 |
|
1429 static void |
|
1430 caps_notify_cb (GstPad * pad, GParamSpec * unused, GstDecodeBin * dbin) |
|
1431 { |
|
1432 GstElement *element; |
|
1433 |
|
1434 GST_LOG_OBJECT (dbin, "Notified caps for pad %s:%s", |
|
1435 GST_DEBUG_PAD_NAME (pad)); |
|
1436 |
|
1437 element = GST_ELEMENT_CAST (gst_pad_get_parent (pad)); |
|
1438 |
|
1439 pad_added_cb (element, pad, dbin); |
|
1440 |
|
1441 gst_object_unref (element); |
|
1442 } |
|
1443 |
|
1444 static void |
|
1445 caps_notify_group_cb (GstPad * pad, GParamSpec * unused, GstDecodeGroup * group) |
|
1446 { |
|
1447 GstElement *element; |
|
1448 |
|
1449 GST_LOG_OBJECT (pad, "Notified caps for pad %s:%s", GST_DEBUG_PAD_NAME (pad)); |
|
1450 |
|
1451 element = GST_ELEMENT_CAST (gst_pad_get_parent (pad)); |
|
1452 |
|
1453 pad_added_group_cb (element, pad, group); |
|
1454 |
|
1455 gst_object_unref (element); |
|
1456 } |
|
1457 |
|
1458 /* this function runs through the element factories and returns a value array of |
|
1459 * all elements that are able to sink the given caps |
|
1460 */ |
|
1461 static GValueArray * |
|
1462 find_compatibles (GstDecodeBin * decode_bin, GstPad * pad, const GstCaps * caps) |
|
1463 { |
|
1464 GValueArray *result; |
|
1465 |
|
1466 GST_DEBUG_OBJECT (decode_bin, "finding factories"); |
|
1467 |
|
1468 result = gst_factory_list_filter (decode_bin->factories, caps); |
|
1469 |
|
1470 return result; |
|
1471 } |
|
1472 |
|
1473 /* Decide whether an element is a demuxer based on the |
|
1474 * klass and number/type of src pad templates it has */ |
|
1475 static gboolean |
|
1476 is_demuxer_element (GstElement * srcelement) |
|
1477 { |
|
1478 GstElementFactory *srcfactory; |
|
1479 GstElementClass *elemclass; |
|
1480 GList *templates, *walk; |
|
1481 const gchar *klass; |
|
1482 gint potential_src_pads = 0; |
|
1483 |
|
1484 srcfactory = gst_element_get_factory (srcelement); |
|
1485 klass = gst_element_factory_get_klass (srcfactory); |
|
1486 |
|
1487 /* Can't be a demuxer unless it has Demux in the klass name */ |
|
1488 if (!strstr (klass, "Demux")) |
|
1489 return FALSE; |
|
1490 |
|
1491 /* Walk the src pad templates and count how many the element |
|
1492 * might produce */ |
|
1493 elemclass = GST_ELEMENT_GET_CLASS (srcelement); |
|
1494 |
|
1495 walk = templates = gst_element_class_get_pad_template_list (elemclass); |
|
1496 while (walk != NULL) { |
|
1497 GstPadTemplate *templ; |
|
1498 |
|
1499 templ = (GstPadTemplate *) walk->data; |
|
1500 if (GST_PAD_TEMPLATE_DIRECTION (templ) == GST_PAD_SRC) { |
|
1501 switch (GST_PAD_TEMPLATE_PRESENCE (templ)) { |
|
1502 case GST_PAD_ALWAYS: |
|
1503 case GST_PAD_SOMETIMES: |
|
1504 if (strstr (GST_PAD_TEMPLATE_NAME_TEMPLATE (templ), "%")) |
|
1505 potential_src_pads += 2; /* Might make multiple pads */ |
|
1506 else |
|
1507 potential_src_pads += 1; |
|
1508 break; |
|
1509 case GST_PAD_REQUEST: |
|
1510 potential_src_pads += 2; |
|
1511 break; |
|
1512 } |
|
1513 } |
|
1514 walk = g_list_next (walk); |
|
1515 } |
|
1516 |
|
1517 if (potential_src_pads < 2) |
|
1518 return FALSE; |
|
1519 |
|
1520 return TRUE; |
|
1521 } |
|
1522 |
|
1523 /* Returns TRUE if the caps are raw, or if they are compatible with the caps |
|
1524 * specified in the 'caps' property |
|
1525 * |
|
1526 * The decodebin_lock should be taken ! |
|
1527 */ |
|
1528 static gboolean |
|
1529 are_raw_caps (GstDecodeBin * dbin, GstCaps * caps) |
|
1530 { |
|
1531 GstCaps *intersection; |
|
1532 gboolean res; |
|
1533 |
|
1534 GST_LOG_OBJECT (dbin, "Checking with caps %" GST_PTR_FORMAT, caps); |
|
1535 |
|
1536 intersection = gst_caps_intersect (dbin->caps, caps); |
|
1537 |
|
1538 res = (!(gst_caps_is_empty (intersection))); |
|
1539 |
|
1540 gst_caps_unref (intersection); |
|
1541 |
|
1542 GST_LOG_OBJECT (dbin, "Caps are %sfinal caps", res ? "" : "not "); |
|
1543 |
|
1544 return res; |
|
1545 } |
|
1546 |
|
1547 |
|
1548 /**** |
|
1549 * GstDecodeGroup functions |
|
1550 ****/ |
|
1551 |
|
1552 static void |
|
1553 multi_queue_overrun_cb (GstElement * queue, GstDecodeGroup * group) |
|
1554 { |
|
1555 GST_LOG_OBJECT (group->dbin, "multiqueue is full"); |
|
1556 |
|
1557 /* if we haven't exposed the group, do it */ |
|
1558 DECODE_BIN_LOCK (group->dbin); |
|
1559 gst_decode_group_expose (group); |
|
1560 DECODE_BIN_UNLOCK (group->dbin); |
|
1561 } |
|
1562 |
|
1563 static void |
|
1564 multi_queue_underrun_cb (GstElement * queue, GstDecodeGroup * group) |
|
1565 { |
|
1566 GstDecodeBin *dbin = group->dbin; |
|
1567 |
|
1568 GST_LOG_OBJECT (dbin, "multiqueue is empty for group %p", group); |
|
1569 |
|
1570 /* Check if we need to activate another group */ |
|
1571 DECODE_BIN_LOCK (dbin); |
|
1572 if ((group == dbin->activegroup) && dbin->groups) { |
|
1573 GST_DEBUG_OBJECT (dbin, "Switching to new group"); |
|
1574 /* unexpose current active */ |
|
1575 gst_decode_group_hide (group); |
|
1576 |
|
1577 /* expose first group of groups */ |
|
1578 gst_decode_group_expose ((GstDecodeGroup *) dbin->groups->data); |
|
1579 } |
|
1580 DECODE_BIN_UNLOCK (dbin); |
|
1581 } |
|
1582 |
|
1583 /* gst_decode_group_new |
|
1584 * |
|
1585 * Creates a new GstDecodeGroup. It is up to the caller to add it to the list |
|
1586 * of groups. |
|
1587 */ |
|
1588 static GstDecodeGroup * |
|
1589 gst_decode_group_new (GstDecodeBin * dbin, gboolean use_queue) |
|
1590 { |
|
1591 GstDecodeGroup *group; |
|
1592 GstElement *mq; |
|
1593 |
|
1594 GST_LOG_OBJECT (dbin, "Creating new group"); |
|
1595 |
|
1596 if (use_queue) { |
|
1597 if (!(mq = gst_element_factory_make ("multiqueue", NULL))) { |
|
1598 GST_WARNING ("Couldn't create multiqueue element"); |
|
1599 return NULL; |
|
1600 } |
|
1601 } else { |
|
1602 mq = NULL; |
|
1603 } |
|
1604 |
|
1605 group = g_new0 (GstDecodeGroup, 1); |
|
1606 group->lock = g_mutex_new (); |
|
1607 group->dbin = dbin; |
|
1608 group->multiqueue = mq; |
|
1609 group->exposed = FALSE; |
|
1610 group->drained = FALSE; |
|
1611 group->blocked = FALSE; |
|
1612 group->complete = FALSE; |
|
1613 group->endpads = NULL; |
|
1614 group->reqpads = NULL; |
|
1615 |
|
1616 if (mq) { |
|
1617 /* we first configure the multiqueue to buffer an unlimited number of |
|
1618 * buffers up to 5 seconds or, when no timestamps are present, up to 2 MB of |
|
1619 * memory. When this queue overruns, we assume the group is complete and can |
|
1620 * be exposed. */ |
|
1621 g_object_set (G_OBJECT (mq), |
|
1622 "max-size-bytes", 2 * 1024 * 1024, |
|
1623 "max-size-time", 5 * GST_SECOND, "max-size-buffers", 0, NULL); |
|
1624 /* will expose the group */ |
|
1625 group->overrunsig = g_signal_connect (G_OBJECT (mq), "overrun", |
|
1626 G_CALLBACK (multi_queue_overrun_cb), group); |
|
1627 /* will hide the group again, this is usually called when the multiqueue is |
|
1628 * drained because of EOS. */ |
|
1629 group->underrunsig = g_signal_connect (G_OBJECT (mq), "underrun", |
|
1630 G_CALLBACK (multi_queue_underrun_cb), group); |
|
1631 |
|
1632 gst_bin_add (GST_BIN (dbin), mq); |
|
1633 gst_element_set_state (mq, GST_STATE_PAUSED); |
|
1634 } |
|
1635 |
|
1636 GST_LOG_OBJECT (dbin, "Returning new group %p", group); |
|
1637 |
|
1638 return group; |
|
1639 } |
|
1640 |
|
1641 /** get_current_group: |
|
1642 * |
|
1643 * Returns the current non-completed group. |
|
1644 * |
|
1645 * Returns NULL if no groups are available, or all groups are completed. |
|
1646 */ |
|
1647 static GstDecodeGroup * |
|
1648 get_current_group (GstDecodeBin * dbin) |
|
1649 { |
|
1650 GList *tmp; |
|
1651 GstDecodeGroup *group = NULL; |
|
1652 |
|
1653 DECODE_BIN_LOCK (dbin); |
|
1654 for (tmp = dbin->groups; tmp; tmp = g_list_next (tmp)) { |
|
1655 GstDecodeGroup *this = (GstDecodeGroup *) tmp->data; |
|
1656 |
|
1657 GST_LOG_OBJECT (dbin, "group %p, complete:%d", this, this->complete); |
|
1658 |
|
1659 if (!this->complete) { |
|
1660 group = this; |
|
1661 break; |
|
1662 } |
|
1663 } |
|
1664 DECODE_BIN_UNLOCK (dbin); |
|
1665 |
|
1666 GST_LOG_OBJECT (dbin, "Returning group %p", group); |
|
1667 |
|
1668 return group; |
|
1669 } |
|
1670 |
|
1671 static gboolean |
|
1672 group_demuxer_event_probe (GstPad * pad, GstEvent * event, |
|
1673 GstDecodeGroup * group) |
|
1674 { |
|
1675 if (GST_EVENT_TYPE (event) == GST_EVENT_EOS) { |
|
1676 GST_DEBUG_OBJECT (group->dbin, |
|
1677 "Got EOS on group input pads, exposing group if it wasn't before"); |
|
1678 DECODE_BIN_LOCK (group->dbin); |
|
1679 gst_decode_group_expose (group); |
|
1680 DECODE_BIN_UNLOCK (group->dbin); |
|
1681 } |
|
1682 return TRUE; |
|
1683 } |
|
1684 |
|
1685 /* gst_decode_group_control_demuxer_pad |
|
1686 * |
|
1687 * Adds a new demuxer srcpad to the given group. |
|
1688 * |
|
1689 * Returns the srcpad of the multiqueue corresponding the given pad. |
|
1690 * Returns NULL if there was an error. |
|
1691 */ |
|
1692 static GstPad * |
|
1693 gst_decode_group_control_demuxer_pad (GstDecodeGroup * group, GstPad * pad) |
|
1694 { |
|
1695 GstPad *srcpad, *sinkpad; |
|
1696 gchar *nb, *sinkname, *srcname; |
|
1697 |
|
1698 GST_LOG ("group:%p pad %s:%s", group, GST_DEBUG_PAD_NAME (pad)); |
|
1699 |
|
1700 srcpad = NULL; |
|
1701 |
|
1702 if (!(sinkpad = gst_element_get_request_pad (group->multiqueue, "sink%d"))) { |
|
1703 GST_ERROR ("Couldn't get sinkpad from multiqueue"); |
|
1704 return NULL; |
|
1705 } |
|
1706 |
|
1707 if ((gst_pad_link (pad, sinkpad) != GST_PAD_LINK_OK)) { |
|
1708 GST_ERROR ("Couldn't link demuxer and multiqueue"); |
|
1709 goto beach; |
|
1710 } |
|
1711 |
|
1712 group->reqpads = g_list_append (group->reqpads, sinkpad); |
|
1713 |
|
1714 sinkname = gst_pad_get_name (sinkpad); |
|
1715 nb = sinkname + 4; |
|
1716 srcname = g_strdup_printf ("src%s", nb); |
|
1717 g_free (sinkname); |
|
1718 |
|
1719 GROUP_MUTEX_LOCK (group); |
|
1720 |
|
1721 if (!(srcpad = gst_element_get_pad (group->multiqueue, srcname))) { |
|
1722 GST_ERROR ("Couldn't get srcpad %s from multiqueue", srcname); |
|
1723 goto chiringuito; |
|
1724 } |
|
1725 |
|
1726 /* connect event handler on pad to intercept EOS events */ |
|
1727 gst_pad_add_event_probe (pad, G_CALLBACK (group_demuxer_event_probe), group); |
|
1728 |
|
1729 chiringuito: |
|
1730 g_free (srcname); |
|
1731 GROUP_MUTEX_UNLOCK (group); |
|
1732 |
|
1733 beach: |
|
1734 gst_object_unref (sinkpad); |
|
1735 return srcpad; |
|
1736 } |
|
1737 |
|
1738 static gboolean |
|
1739 gst_decode_group_control_source_pad (GstDecodeGroup * group, GstPad * pad) |
|
1740 { |
|
1741 GstDecodePad *dpad; |
|
1742 |
|
1743 g_return_val_if_fail (group != NULL, FALSE); |
|
1744 |
|
1745 GST_LOG ("group:%p , pad %s:%s", group, GST_DEBUG_PAD_NAME (pad)); |
|
1746 |
|
1747 /* FIXME : check if pad is already controlled */ |
|
1748 |
|
1749 GROUP_MUTEX_LOCK (group); |
|
1750 |
|
1751 /* Create GstDecodePad for the pad */ |
|
1752 dpad = gst_decode_pad_new (group, pad, TRUE); |
|
1753 |
|
1754 group->endpads = g_list_append (group->endpads, dpad); |
|
1755 |
|
1756 GROUP_MUTEX_UNLOCK (group); |
|
1757 |
|
1758 return TRUE; |
|
1759 } |
|
1760 |
|
1761 /* gst_decode_group_check_if_blocked: |
|
1762 * |
|
1763 * Call this when one of the pads blocked status has changed. |
|
1764 * If the group is complete and blocked, the group will be marked as blocked |
|
1765 * and will ghost/expose all pads on decodebin if the group is the current one. |
|
1766 * |
|
1767 * Call with the group lock taken ! MT safe |
|
1768 */ |
|
1769 static void |
|
1770 gst_decode_group_check_if_blocked (GstDecodeGroup * group) |
|
1771 { |
|
1772 GList *tmp; |
|
1773 gboolean blocked = TRUE; |
|
1774 |
|
1775 GST_LOG ("group : %p , ->complete:%d , ->nbdynamic:%d", |
|
1776 group, group->complete, group->nbdynamic); |
|
1777 |
|
1778 /* 1. don't do anything if group is not complete */ |
|
1779 if (!group->complete || group->nbdynamic) { |
|
1780 GST_DEBUG_OBJECT (group->dbin, "Group isn't complete yet"); |
|
1781 return; |
|
1782 } |
|
1783 |
|
1784 for (tmp = group->endpads; tmp; tmp = g_list_next (tmp)) { |
|
1785 GstDecodePad *dpad = (GstDecodePad *) tmp->data; |
|
1786 |
|
1787 if (!dpad->blocked) { |
|
1788 blocked = FALSE; |
|
1789 break; |
|
1790 } |
|
1791 } |
|
1792 |
|
1793 /* 2. Update status of group */ |
|
1794 group->blocked = blocked; |
|
1795 GST_LOG ("group is blocked:%d", blocked); |
|
1796 |
|
1797 /* 3. don't do anything if not blocked completely */ |
|
1798 if (!blocked) |
|
1799 return; |
|
1800 |
|
1801 /* 4. if we're the current group, expose pads */ |
|
1802 DECODE_BIN_LOCK (group->dbin); |
|
1803 if (!gst_decode_group_expose (group)) |
|
1804 GST_WARNING_OBJECT (group->dbin, "Couldn't expose group"); |
|
1805 DECODE_BIN_UNLOCK (group->dbin); |
|
1806 } |
|
1807 |
|
1808 static void |
|
1809 gst_decode_group_check_if_drained (GstDecodeGroup * group) |
|
1810 { |
|
1811 GList *tmp; |
|
1812 GstDecodeBin *dbin = group->dbin; |
|
1813 gboolean drained = TRUE; |
|
1814 |
|
1815 GST_LOG ("group : %p", group); |
|
1816 |
|
1817 for (tmp = group->endpads; tmp; tmp = g_list_next (tmp)) { |
|
1818 GstDecodePad *dpad = (GstDecodePad *) tmp->data; |
|
1819 |
|
1820 GST_LOG ("testing dpad %p", dpad); |
|
1821 |
|
1822 if (!dpad->drained) { |
|
1823 drained = FALSE; |
|
1824 break; |
|
1825 } |
|
1826 } |
|
1827 |
|
1828 group->drained = drained; |
|
1829 if (!drained) |
|
1830 return; |
|
1831 |
|
1832 /* we are drained. Check if there is a next group to activate */ |
|
1833 DECODE_BIN_LOCK (dbin); |
|
1834 if ((group == dbin->activegroup) && dbin->groups) { |
|
1835 GST_DEBUG_OBJECT (dbin, "Switching to new group"); |
|
1836 |
|
1837 /* hide current group */ |
|
1838 gst_decode_group_hide (group); |
|
1839 /* expose next group */ |
|
1840 gst_decode_group_expose ((GstDecodeGroup *) dbin->groups->data); |
|
1841 /* we're not yet drained now */ |
|
1842 drained = FALSE; |
|
1843 } |
|
1844 DECODE_BIN_UNLOCK (dbin); |
|
1845 |
|
1846 if (drained) { |
|
1847 /* no more groups to activate, we're completely drained now */ |
|
1848 GST_LOG ("all groups drained, fire signal"); |
|
1849 g_signal_emit (G_OBJECT (dbin), gst_decode_bin_signals[SIGNAL_DRAINED], 0, |
|
1850 NULL); |
|
1851 } |
|
1852 } |
|
1853 |
|
1854 /* sort_end_pads: |
|
1855 * GCompareFunc to use with lists of GstPad. |
|
1856 * Sorts pads by mime type. |
|
1857 * First video (raw, then non-raw), then audio (raw, then non-raw), |
|
1858 * then others. |
|
1859 * |
|
1860 * Return: negative if a<b, 0 if a==b, positive if a>b |
|
1861 */ |
|
1862 |
|
1863 static gint |
|
1864 sort_end_pads (GstDecodePad * da, GstDecodePad * db) |
|
1865 { |
|
1866 GstPad *a, *b; |
|
1867 gint va, vb; |
|
1868 GstCaps *capsa, *capsb; |
|
1869 GstStructure *sa, *sb; |
|
1870 const gchar *namea, *nameb; |
|
1871 |
|
1872 a = da->pad; |
|
1873 b = db->pad; |
|
1874 |
|
1875 capsa = gst_pad_get_caps (a); |
|
1876 capsb = gst_pad_get_caps (b); |
|
1877 |
|
1878 sa = gst_caps_get_structure ((const GstCaps *) capsa, 0); |
|
1879 sb = gst_caps_get_structure ((const GstCaps *) capsb, 0); |
|
1880 |
|
1881 namea = gst_structure_get_name (sa); |
|
1882 nameb = gst_structure_get_name (sb); |
|
1883 |
|
1884 if (g_strrstr (namea, "video/x-raw-")) |
|
1885 va = 0; |
|
1886 else if (g_strrstr (namea, "video/")) |
|
1887 va = 1; |
|
1888 else if (g_strrstr (namea, "audio/x-raw")) |
|
1889 va = 2; |
|
1890 else if (g_strrstr (namea, "audio/")) |
|
1891 va = 3; |
|
1892 else |
|
1893 va = 4; |
|
1894 |
|
1895 if (g_strrstr (nameb, "video/x-raw-")) |
|
1896 vb = 0; |
|
1897 else if (g_strrstr (nameb, "video/")) |
|
1898 vb = 1; |
|
1899 else if (g_strrstr (nameb, "audio/x-raw")) |
|
1900 vb = 2; |
|
1901 else if (g_strrstr (nameb, "audio/")) |
|
1902 vb = 3; |
|
1903 else |
|
1904 vb = 4; |
|
1905 |
|
1906 gst_caps_unref (capsa); |
|
1907 gst_caps_unref (capsb); |
|
1908 |
|
1909 return va - vb; |
|
1910 } |
|
1911 |
|
1912 /* gst_decode_group_expose: |
|
1913 * |
|
1914 * Expose this group's pads. |
|
1915 * |
|
1916 * Not MT safe, please take the group lock |
|
1917 */ |
|
1918 static gboolean |
|
1919 gst_decode_group_expose (GstDecodeGroup * group) |
|
1920 { |
|
1921 GList *tmp; |
|
1922 GList *next = NULL; |
|
1923 |
|
1924 if (group->dbin->activegroup) { |
|
1925 GST_DEBUG_OBJECT (group->dbin, "A group is already active and exposed"); |
|
1926 return TRUE; |
|
1927 } |
|
1928 |
|
1929 if (group->dbin->activegroup == group) { |
|
1930 GST_WARNING ("Group %p is already exposed", group); |
|
1931 return TRUE; |
|
1932 } |
|
1933 |
|
1934 if (!group->dbin->groups |
|
1935 || (group != (GstDecodeGroup *) group->dbin->groups->data)) { |
|
1936 GST_WARNING ("Group %p is not the first group to expose", group); |
|
1937 return FALSE; |
|
1938 } |
|
1939 |
|
1940 if (group->nbdynamic) { |
|
1941 GST_WARNING ("Group %p still has %d dynamic objects, not exposing yet", |
|
1942 group, group->nbdynamic); |
|
1943 return FALSE; |
|
1944 } |
|
1945 |
|
1946 GST_LOG ("Exposing group %p", group); |
|
1947 |
|
1948 if (group->multiqueue) { |
|
1949 /* update runtime limits. At runtime, we try to keep the amount of buffers |
|
1950 * in the queues as low as possible (but at least 5 buffers). */ |
|
1951 g_object_set (G_OBJECT (group->multiqueue), |
|
1952 "max-size-bytes", 2 * 1024 * 1024, |
|
1953 "max-size-time", 2 * GST_SECOND, "max-size-buffers", 5, NULL); |
|
1954 /* we can now disconnect any overrun signal, which is used to expose the |
|
1955 * group. */ |
|
1956 if (group->overrunsig) { |
|
1957 GST_LOG ("Disconnecting overrun"); |
|
1958 g_signal_handler_disconnect (group->multiqueue, group->overrunsig); |
|
1959 group->overrunsig = 0; |
|
1960 } |
|
1961 } |
|
1962 |
|
1963 /* re-order pads : video, then audio, then others */ |
|
1964 group->endpads = g_list_sort (group->endpads, (GCompareFunc) sort_end_pads); |
|
1965 |
|
1966 /* Expose pads */ |
|
1967 |
|
1968 for (tmp = group->endpads; tmp; tmp = next) { |
|
1969 GstDecodePad *dpad = (GstDecodePad *) tmp->data; |
|
1970 gchar *padname; |
|
1971 GstPad *ghost; |
|
1972 |
|
1973 next = g_list_next (tmp); |
|
1974 |
|
1975 /* 1. ghost pad */ |
|
1976 padname = g_strdup_printf ("src%d", group->dbin->nbpads); |
|
1977 group->dbin->nbpads++; |
|
1978 |
|
1979 GST_LOG_OBJECT (group->dbin, "About to expose pad %s:%s", |
|
1980 GST_DEBUG_PAD_NAME (dpad->pad)); |
|
1981 |
|
1982 ghost = gst_ghost_pad_new (padname, dpad->pad); |
|
1983 gst_pad_set_active (ghost, TRUE); |
|
1984 gst_element_add_pad (GST_ELEMENT (group->dbin), ghost); |
|
1985 group->ghosts = g_list_append (group->ghosts, ghost); |
|
1986 |
|
1987 g_free (padname); |
|
1988 |
|
1989 /* 2. emit signal */ |
|
1990 GST_DEBUG_OBJECT (group->dbin, "emitting new-decoded-pad"); |
|
1991 g_signal_emit (G_OBJECT (group->dbin), |
|
1992 gst_decode_bin_signals[SIGNAL_NEW_DECODED_PAD], 0, ghost, |
|
1993 (next == NULL)); |
|
1994 GST_DEBUG_OBJECT (group->dbin, "emitted new-decoded-pad"); |
|
1995 } |
|
1996 |
|
1997 /* signal no-more-pads. This allows the application to hook stuff to the |
|
1998 * exposed pads */ |
|
1999 GST_LOG_OBJECT (group->dbin, "signalling no-more-pads"); |
|
2000 gst_element_no_more_pads (GST_ELEMENT (group->dbin)); |
|
2001 |
|
2002 /* 3. Unblock internal pads. The application should have connected stuff now |
|
2003 * so that streaming can continue. */ |
|
2004 for (tmp = group->endpads; tmp; tmp = next) { |
|
2005 GstDecodePad *dpad = (GstDecodePad *) tmp->data; |
|
2006 |
|
2007 next = g_list_next (tmp); |
|
2008 |
|
2009 GST_DEBUG_OBJECT (dpad->pad, "unblocking"); |
|
2010 gst_pad_set_blocked_async (dpad->pad, FALSE, |
|
2011 (GstPadBlockCallback) source_pad_blocked_cb, dpad); |
|
2012 GST_DEBUG_OBJECT (dpad->pad, "unblocked"); |
|
2013 } |
|
2014 |
|
2015 group->dbin->activegroup = group; |
|
2016 |
|
2017 /* pop off the first group */ |
|
2018 group->dbin->groups = |
|
2019 g_list_delete_link (group->dbin->groups, group->dbin->groups); |
|
2020 |
|
2021 remove_fakesink (group->dbin); |
|
2022 |
|
2023 group->exposed = TRUE; |
|
2024 |
|
2025 GST_LOG_OBJECT (group->dbin, "Group %p exposed", group); |
|
2026 return TRUE; |
|
2027 } |
|
2028 |
|
2029 static void |
|
2030 gst_decode_group_hide (GstDecodeGroup * group) |
|
2031 { |
|
2032 GList *tmp; |
|
2033 |
|
2034 GST_LOG ("Hiding group %p", group); |
|
2035 |
|
2036 if (group != group->dbin->activegroup) { |
|
2037 GST_WARNING ("This group is not the active one, aborting"); |
|
2038 return; |
|
2039 } |
|
2040 |
|
2041 GROUP_MUTEX_LOCK (group); |
|
2042 |
|
2043 /* Remove ghost pads */ |
|
2044 for (tmp = group->ghosts; tmp; tmp = g_list_next (tmp)) |
|
2045 gst_element_remove_pad (GST_ELEMENT (group->dbin), (GstPad *) tmp->data); |
|
2046 |
|
2047 g_list_free (group->ghosts); |
|
2048 group->ghosts = NULL; |
|
2049 |
|
2050 group->exposed = FALSE; |
|
2051 |
|
2052 GROUP_MUTEX_UNLOCK (group); |
|
2053 |
|
2054 group->dbin->activegroup = NULL; |
|
2055 group->dbin->oldgroups = g_list_append (group->dbin->oldgroups, group); |
|
2056 } |
|
2057 |
|
2058 static void |
|
2059 deactivate_free_recursive (GstDecodeGroup * group, GstElement * element) |
|
2060 { |
|
2061 GstIterator *it; |
|
2062 GstIteratorResult res; |
|
2063 gpointer point; |
|
2064 |
|
2065 GST_LOG ("element:%s", GST_ELEMENT_NAME (element)); |
|
2066 |
|
2067 /* call on downstream elements */ |
|
2068 it = gst_element_iterate_src_pads (element); |
|
2069 |
|
2070 restart: |
|
2071 |
|
2072 while (1) { |
|
2073 res = gst_iterator_next (it, &point); |
|
2074 switch (res) { |
|
2075 case GST_ITERATOR_DONE: |
|
2076 goto done; |
|
2077 case GST_ITERATOR_RESYNC: |
|
2078 gst_iterator_resync (it); |
|
2079 goto restart; |
|
2080 case GST_ITERATOR_ERROR: |
|
2081 { |
|
2082 GST_WARNING ("Had an error while iterating source pads of element: %s", |
|
2083 GST_ELEMENT_NAME (element)); |
|
2084 goto beach; |
|
2085 } |
|
2086 case GST_ITERATOR_OK: |
|
2087 { |
|
2088 GstPad *pad = GST_PAD (point); |
|
2089 GstPad *peerpad = NULL; |
|
2090 |
|
2091 if ((peerpad = gst_pad_get_peer (pad))) { |
|
2092 GstObject *parent; |
|
2093 |
|
2094 parent = gst_pad_get_parent (peerpad); |
|
2095 gst_object_unref (peerpad); |
|
2096 |
|
2097 if (parent && GST_IS_ELEMENT (parent)) |
|
2098 deactivate_free_recursive (group, GST_ELEMENT (parent)); |
|
2099 if (parent) |
|
2100 gst_object_unref (parent); |
|
2101 } |
|
2102 } |
|
2103 break; |
|
2104 default: |
|
2105 break; |
|
2106 } |
|
2107 } |
|
2108 |
|
2109 done: |
|
2110 gst_element_set_state (element, GST_STATE_NULL); |
|
2111 gst_bin_remove (GST_BIN (group->dbin), element); |
|
2112 |
|
2113 beach: |
|
2114 gst_iterator_free (it); |
|
2115 |
|
2116 return; |
|
2117 } |
|
2118 |
|
2119 static void |
|
2120 gst_decode_group_free (GstDecodeGroup * group) |
|
2121 { |
|
2122 GList *tmp; |
|
2123 |
|
2124 GST_LOG ("group %p", group); |
|
2125 |
|
2126 GROUP_MUTEX_LOCK (group); |
|
2127 |
|
2128 /* free ghost pads */ |
|
2129 if (group == group->dbin->activegroup) { |
|
2130 for (tmp = group->ghosts; tmp; tmp = g_list_next (tmp)) |
|
2131 gst_element_remove_pad (GST_ELEMENT (group->dbin), (GstPad *) tmp->data); |
|
2132 |
|
2133 g_list_free (group->ghosts); |
|
2134 group->ghosts = NULL; |
|
2135 } |
|
2136 |
|
2137 /* Clear all GstDecodePad */ |
|
2138 for (tmp = group->endpads; tmp; tmp = g_list_next (tmp)) { |
|
2139 GstDecodePad *dpad = (GstDecodePad *) tmp->data; |
|
2140 |
|
2141 g_free (dpad); |
|
2142 } |
|
2143 g_list_free (group->endpads); |
|
2144 group->endpads = NULL; |
|
2145 |
|
2146 /* release request pads */ |
|
2147 for (tmp = group->reqpads; tmp; tmp = g_list_next (tmp)) { |
|
2148 gst_element_release_request_pad (group->multiqueue, GST_PAD (tmp->data)); |
|
2149 } |
|
2150 g_list_free (group->reqpads); |
|
2151 group->reqpads = NULL; |
|
2152 |
|
2153 /* disconnect signal handlers on multiqueue */ |
|
2154 if (group->multiqueue) { |
|
2155 if (group->underrunsig) |
|
2156 g_signal_handler_disconnect (group->multiqueue, group->underrunsig); |
|
2157 if (group->overrunsig) |
|
2158 g_signal_handler_disconnect (group->multiqueue, group->overrunsig); |
|
2159 deactivate_free_recursive (group, group->multiqueue); |
|
2160 } |
|
2161 |
|
2162 /* remove all elements */ |
|
2163 |
|
2164 GROUP_MUTEX_UNLOCK (group); |
|
2165 |
|
2166 g_mutex_free (group->lock); |
|
2167 g_free (group); |
|
2168 } |
|
2169 |
|
2170 /* gst_decode_group_set_complete: |
|
2171 * |
|
2172 * Mark the group as complete. This means no more streams will be controlled |
|
2173 * through this group. |
|
2174 * |
|
2175 * MT safe |
|
2176 */ |
|
2177 static void |
|
2178 gst_decode_group_set_complete (GstDecodeGroup * group) |
|
2179 { |
|
2180 GST_LOG_OBJECT (group->dbin, "Setting group %p to COMPLETE", group); |
|
2181 |
|
2182 GROUP_MUTEX_LOCK (group); |
|
2183 group->complete = TRUE; |
|
2184 gst_decode_group_check_if_blocked (group); |
|
2185 GROUP_MUTEX_UNLOCK (group); |
|
2186 } |
|
2187 |
|
2188 |
|
2189 |
|
2190 /************************* |
|
2191 * GstDecodePad functions |
|
2192 *************************/ |
|
2193 |
|
2194 static void |
|
2195 source_pad_blocked_cb (GstPad * pad, gboolean blocked, GstDecodePad * dpad) |
|
2196 { |
|
2197 GST_LOG_OBJECT (pad, "blocked:%d , dpad:%p, dpad->group:%p", |
|
2198 blocked, dpad, dpad->group); |
|
2199 |
|
2200 /* Update this GstDecodePad status */ |
|
2201 dpad->blocked = blocked; |
|
2202 |
|
2203 if (blocked) { |
|
2204 GROUP_MUTEX_LOCK (dpad->group); |
|
2205 gst_decode_group_check_if_blocked (dpad->group); |
|
2206 GROUP_MUTEX_UNLOCK (dpad->group); |
|
2207 } |
|
2208 } |
|
2209 |
|
2210 static gboolean |
|
2211 source_pad_event_probe (GstPad * pad, GstEvent * event, GstDecodePad * dpad) |
|
2212 { |
|
2213 GST_LOG_OBJECT (pad, "%s dpad:%p", GST_EVENT_TYPE_NAME (event), dpad); |
|
2214 |
|
2215 if (GST_EVENT_TYPE (event) == GST_EVENT_EOS) { |
|
2216 /* Set our pad as drained */ |
|
2217 dpad->drained = TRUE; |
|
2218 |
|
2219 GST_DEBUG_OBJECT (pad, "we received EOS"); |
|
2220 |
|
2221 /* Check if all pads are drained. If there is a next group to expose, we |
|
2222 * will remove the ghostpad of the current group first, which unlinks the |
|
2223 * peer and so drops the EOS. */ |
|
2224 gst_decode_group_check_if_drained (dpad->group); |
|
2225 } |
|
2226 /* never drop events */ |
|
2227 return TRUE; |
|
2228 } |
|
2229 |
|
2230 /*gst_decode_pad_new: |
|
2231 * |
|
2232 * Creates a new GstDecodePad for the given pad. |
|
2233 * If block is TRUE, Sets the pad blocking asynchronously |
|
2234 */ |
|
2235 static GstDecodePad * |
|
2236 gst_decode_pad_new (GstDecodeGroup * group, GstPad * pad, gboolean block) |
|
2237 { |
|
2238 GstDecodePad *dpad; |
|
2239 |
|
2240 dpad = g_new0 (GstDecodePad, 1); |
|
2241 dpad->pad = pad; |
|
2242 dpad->group = group; |
|
2243 dpad->blocked = FALSE; |
|
2244 dpad->drained = TRUE; |
|
2245 |
|
2246 if (block) |
|
2247 gst_pad_set_blocked_async (pad, TRUE, |
|
2248 (GstPadBlockCallback) source_pad_blocked_cb, dpad); |
|
2249 gst_pad_add_event_probe (pad, G_CALLBACK (source_pad_event_probe), dpad); |
|
2250 return dpad; |
|
2251 } |
|
2252 |
|
2253 |
|
2254 /***** |
|
2255 * Element add/remove |
|
2256 *****/ |
|
2257 |
|
2258 /* |
|
2259 * add_fakesink / remove_fakesink |
|
2260 * |
|
2261 * We use a sink so that the parent ::change_state returns GST_STATE_CHANGE_ASYNC |
|
2262 * when that sink is present (since it's not connected to anything it will |
|
2263 * always return GST_STATE_CHANGE_ASYNC). |
|
2264 * |
|
2265 * But this is an ugly way of achieving this goal. |
|
2266 * Ideally, we shouldn't use a sink and just return GST_STATE_CHANGE_ASYNC in |
|
2267 * our ::change_state if we have not exposed the active group. |
|
2268 * We also need to override ::get_state to fake the asynchronous behaviour. |
|
2269 * Once the active group is exposed, we would then post a |
|
2270 * GST_MESSAGE_STATE_DIRTY and return GST_STATE_CHANGE_SUCCESS (which will call |
|
2271 * ::get_state . |
|
2272 */ |
|
2273 |
|
2274 static gboolean |
|
2275 add_fakesink (GstDecodeBin * decode_bin) |
|
2276 { |
|
2277 GST_DEBUG_OBJECT (decode_bin, "Adding the fakesink"); |
|
2278 |
|
2279 if (decode_bin->fakesink) |
|
2280 return TRUE; |
|
2281 |
|
2282 decode_bin->fakesink = |
|
2283 gst_element_factory_make ("fakesink", "async-fakesink"); |
|
2284 if (!decode_bin->fakesink) |
|
2285 goto no_fakesink; |
|
2286 |
|
2287 /* enable sync so that we force ASYNC preroll */ |
|
2288 g_object_set (G_OBJECT (decode_bin->fakesink), "sync", TRUE, NULL); |
|
2289 |
|
2290 /* hacky, remove sink flag, we don't want our decodebin to become a sink |
|
2291 * just because we add a fakesink element to make us ASYNC */ |
|
2292 GST_OBJECT_FLAG_UNSET (decode_bin->fakesink, GST_ELEMENT_IS_SINK); |
|
2293 |
|
2294 if (!gst_bin_add (GST_BIN (decode_bin), decode_bin->fakesink)) |
|
2295 goto could_not_add; |
|
2296 |
|
2297 return TRUE; |
|
2298 |
|
2299 /* ERRORS */ |
|
2300 no_fakesink: |
|
2301 { |
|
2302 g_warning ("can't find fakesink element, decodebin will not work"); |
|
2303 return FALSE; |
|
2304 } |
|
2305 could_not_add: |
|
2306 { |
|
2307 g_warning ("Could not add fakesink to decodebin, decodebin will not work"); |
|
2308 gst_object_unref (decode_bin->fakesink); |
|
2309 decode_bin->fakesink = NULL; |
|
2310 return FALSE; |
|
2311 } |
|
2312 } |
|
2313 |
|
2314 static void |
|
2315 remove_fakesink (GstDecodeBin * decode_bin) |
|
2316 { |
|
2317 if (decode_bin->fakesink == NULL) |
|
2318 return; |
|
2319 |
|
2320 GST_DEBUG_OBJECT (decode_bin, "Removing the fakesink"); |
|
2321 |
|
2322 gst_element_set_state (decode_bin->fakesink, GST_STATE_NULL); |
|
2323 gst_bin_remove (GST_BIN (decode_bin), decode_bin->fakesink); |
|
2324 decode_bin->fakesink = NULL; |
|
2325 } |
|
2326 |
|
2327 /***** |
|
2328 * convenience functions |
|
2329 *****/ |
|
2330 |
|
2331 /* find_sink_pad |
|
2332 * |
|
2333 * Returns the first sink pad of the given element, or NULL if it doesn't have |
|
2334 * any. |
|
2335 */ |
|
2336 |
|
2337 static GstPad * |
|
2338 find_sink_pad (GstElement * element) |
|
2339 { |
|
2340 GstIterator *it; |
|
2341 GstPad *pad = NULL; |
|
2342 gpointer point; |
|
2343 |
|
2344 it = gst_element_iterate_sink_pads (element); |
|
2345 |
|
2346 if ((gst_iterator_next (it, &point)) == GST_ITERATOR_OK) |
|
2347 pad = (GstPad *) point; |
|
2348 |
|
2349 gst_iterator_free (it); |
|
2350 |
|
2351 return pad; |
|
2352 } |
|
2353 |
|
2354 static GstStateChangeReturn |
|
2355 gst_decode_bin_change_state (GstElement * element, GstStateChange transition) |
|
2356 { |
|
2357 GstStateChangeReturn ret; |
|
2358 GstDecodeBin *dbin = GST_DECODE_BIN (element); |
|
2359 |
|
2360 switch (transition) { |
|
2361 case GST_STATE_CHANGE_NULL_TO_READY: |
|
2362 if (dbin->typefind == NULL) |
|
2363 goto missing_typefind; |
|
2364 break; |
|
2365 case GST_STATE_CHANGE_READY_TO_PAUSED:{ |
|
2366 dbin->have_type = FALSE; |
|
2367 if (!add_fakesink (dbin)) |
|
2368 goto missing_fakesink; |
|
2369 break; |
|
2370 } |
|
2371 default: |
|
2372 break; |
|
2373 } |
|
2374 |
|
2375 ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); |
|
2376 |
|
2377 /* FIXME : put some cleanup functions here.. if needed */ |
|
2378 |
|
2379 return ret; |
|
2380 |
|
2381 /* ERRORS */ |
|
2382 missing_typefind: |
|
2383 { |
|
2384 gst_element_post_message (element, |
|
2385 gst_missing_element_message_new (element, "typefind")); |
|
2386 GST_ELEMENT_ERROR (dbin, CORE, MISSING_PLUGIN, (NULL), ("no typefind!")); |
|
2387 return GST_STATE_CHANGE_FAILURE; |
|
2388 } |
|
2389 missing_fakesink: |
|
2390 { |
|
2391 gst_element_post_message (element, |
|
2392 gst_missing_element_message_new (element, "fakesink")); |
|
2393 GST_ELEMENT_ERROR (dbin, CORE, MISSING_PLUGIN, (NULL), ("no fakesink!")); |
|
2394 return GST_STATE_CHANGE_FAILURE; |
|
2395 } |
|
2396 } |
|
2397 |
|
2398 static gboolean |
|
2399 gst_decode_bin_plugin_init (GstPlugin * plugin) |
|
2400 { |
|
2401 GST_DEBUG_CATEGORY_INIT (gst_decode_bin_debug, "decodebin2", 0, |
|
2402 "decoder bin"); |
|
2403 |
|
2404 #ifdef ENABLE_NLS |
|
2405 GST_DEBUG ("binding text domain %s to locale dir %s", GETTEXT_PACKAGE, |
|
2406 LOCALEDIR); |
|
2407 bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR); |
|
2408 #endif /* ENABLE_NLS */ |
|
2409 |
|
2410 return gst_element_register (plugin, "decodebin2", GST_RANK_NONE, |
|
2411 GST_TYPE_DECODE_BIN); |
|
2412 } |
|
2413 |
|
2414 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, |
|
2415 GST_VERSION_MINOR, |
|
2416 "decodebin2", |
|
2417 "decoder bin2", gst_decode_bin_plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, |
|
2418 GST_PACKAGE_ORIGIN); |
|
2419 |
|
2420 #ifdef __SYMBIAN32__ |
|
2421 EXPORT_C |
|
2422 #endif |
|
2423 GstPluginDesc* _GST_PLUGIN_DESC() |
|
2424 { |
|
2425 return &gst_plugin_desc; |
|
2426 } |