branch | RCL_3 |
changeset 30 | 7e817e7e631c |
parent 29 | 567bb019e3e3 |
29:567bb019e3e3 | 30:7e817e7e631c |
---|---|
15 * License along with this library; if not, write to the |
15 * License along with this library; if not, write to the |
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
17 * Boston, MA 02111-1307, USA. |
17 * Boston, MA 02111-1307, USA. |
18 */ |
18 */ |
19 |
19 |
20 /** |
|
21 * SECTION:element-decodebin |
|
22 * |
|
23 * #GstBin that auto-magically constructs a decoding pipeline using available |
|
24 * decoders and demuxers via auto-plugging. |
|
25 * |
|
26 * When using decodebin in your application, connect a signal handler to |
|
27 * #GstDecodeBin::new-decoded-pad and connect your sinks from within the |
|
28 * callback function. |
|
29 */ |
|
30 |
|
31 #ifdef HAVE_CONFIG_H |
20 #ifdef HAVE_CONFIG_H |
32 #include "config.h" |
21 #include "config.h" |
33 #endif |
22 #endif |
34 |
23 |
35 #include <gst/gst-i18n-plugin.h> |
24 #include <gst/gst-i18n-plugin.h> |
36 |
25 |
37 #include <string.h> |
26 #include <string.h> |
38 #include <gst/gst.h> |
27 #include <gst/gst.h> |
39 #include <gst/pbutils/pbutils.h> |
28 #include <gst/pbutils/pbutils.h> |
29 #include <glib_global.h> |
|
40 |
30 |
41 #include "gstplay-marshal.h" |
31 #include "gstplay-marshal.h" |
42 |
32 |
43 /* generic templates */ |
33 /* generic templates */ |
44 static GstStaticPadTemplate decoder_bin_sink_template = |
34 static GstStaticPadTemplate decoder_bin_sink_template = |
63 #define GST_IS_DECODE_BIN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_DECODE_BIN)) |
53 #define GST_IS_DECODE_BIN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_DECODE_BIN)) |
64 |
54 |
65 typedef struct _GstDecodeBin GstDecodeBin; |
55 typedef struct _GstDecodeBin GstDecodeBin; |
66 typedef struct _GstDecodeBinClass GstDecodeBinClass; |
56 typedef struct _GstDecodeBinClass GstDecodeBinClass; |
67 |
57 |
68 /** |
|
69 * GstDecodeBin: |
|
70 * |
|
71 * Auto-plugging decoder element structure |
|
72 */ |
|
73 struct _GstDecodeBin |
58 struct _GstDecodeBin |
74 { |
59 { |
75 GstBin bin; /* we extend GstBin */ |
60 GstBin bin; /* we extend GstBin */ |
76 |
61 |
77 GstElement *typefind; /* this holds the typefind object */ |
62 GstElement *typefind; /* this holds the typefind object */ |
117 SIGNAL_UNKNOWN_TYPE, |
102 SIGNAL_UNKNOWN_TYPE, |
118 SIGNAL_REDIRECT, |
103 SIGNAL_REDIRECT, |
119 LAST_SIGNAL |
104 LAST_SIGNAL |
120 }; |
105 }; |
121 |
106 |
122 /* Properties */ |
|
123 enum |
|
124 { |
|
125 PROP_0, |
|
126 PROP_SINK_CAPS, |
|
127 }; |
|
128 |
|
129 |
107 |
130 typedef struct |
108 typedef struct |
131 { |
109 { |
132 GstPad *pad; |
110 GstPad *pad; |
133 gulong sigid; |
111 gulong sigid; |
149 } |
127 } |
150 GstDynamic; |
128 GstDynamic; |
151 |
129 |
152 static void gst_decode_bin_class_init (GstDecodeBinClass * klass); |
130 static void gst_decode_bin_class_init (GstDecodeBinClass * klass); |
153 static void gst_decode_bin_init (GstDecodeBin * decode_bin); |
131 static void gst_decode_bin_init (GstDecodeBin * decode_bin); |
154 static void gst_decode_bin_set_property (GObject * object, guint prop_id, |
|
155 const GValue * value, GParamSpec * pspec); |
|
156 static void gst_decode_bin_get_property (GObject * object, guint prop_id, |
|
157 GValue * value, GParamSpec * pspec); |
|
158 static void gst_decode_bin_dispose (GObject * object); |
132 static void gst_decode_bin_dispose (GObject * object); |
159 static void gst_decode_bin_finalize (GObject * object); |
133 static void gst_decode_bin_finalize (GObject * object); |
160 |
134 |
161 static GstStateChangeReturn gst_decode_bin_change_state (GstElement * element, |
135 static GstStateChangeReturn gst_decode_bin_change_state (GstElement * element, |
162 GstStateChange transition); |
136 GstStateChange transition); |
180 static void new_caps (GstPad * pad, GParamSpec * unused, GstDynamic * dynamic); |
154 static void new_caps (GstPad * pad, GParamSpec * unused, GstDynamic * dynamic); |
181 |
155 |
182 static void queue_filled_cb (GstElement * queue, GstDecodeBin * decode_bin); |
156 static void queue_filled_cb (GstElement * queue, GstDecodeBin * decode_bin); |
183 static void queue_underrun_cb (GstElement * queue, GstDecodeBin * decode_bin); |
157 static void queue_underrun_cb (GstElement * queue, GstDecodeBin * decode_bin); |
184 |
158 |
185 static gboolean is_demuxer_element (GstElement * srcelement); |
|
186 |
|
187 static GstElementClass *parent_class; |
159 static GstElementClass *parent_class; |
188 static guint gst_decode_bin_signals[LAST_SIGNAL] = { 0 }; |
160 static guint gst_decode_bin_signals[LAST_SIGNAL] = { 0 }; |
189 |
161 |
190 static const GstElementDetails gst_decode_bin_details = |
162 static const GstElementDetails gst_decode_bin_details = |
191 GST_ELEMENT_DETAILS ("Decoder Bin", |
163 GST_ELEMENT_DETAILS ("Decoder Bin", |
232 gstelement_klass = (GstElementClass *) klass; |
204 gstelement_klass = (GstElementClass *) klass; |
233 gstbin_klass = (GstBinClass *) klass; |
205 gstbin_klass = (GstBinClass *) klass; |
234 |
206 |
235 parent_class = g_type_class_peek_parent (klass); |
207 parent_class = g_type_class_peek_parent (klass); |
236 |
208 |
237 gobject_klass->set_property = GST_DEBUG_FUNCPTR (gst_decode_bin_set_property); |
|
238 gobject_klass->get_property = GST_DEBUG_FUNCPTR (gst_decode_bin_get_property); |
|
239 gobject_klass->dispose = GST_DEBUG_FUNCPTR (gst_decode_bin_dispose); |
|
240 gobject_klass->finalize = GST_DEBUG_FUNCPTR (gst_decode_bin_finalize); |
|
241 |
|
242 /** |
|
243 * GstDecodeBin::new-decoded-pad: |
|
244 * @bin: The decodebin |
|
245 * @pad: The newly created pad |
|
246 * @islast: #TRUE if this is the last pad to be added. Deprecated. |
|
247 * |
|
248 * This signal gets emitted as soon as a new pad of the same type as one of |
|
249 * the valid 'raw' types is added. |
|
250 */ |
|
251 gst_decode_bin_signals[SIGNAL_NEW_DECODED_PAD] = |
209 gst_decode_bin_signals[SIGNAL_NEW_DECODED_PAD] = |
252 g_signal_new ("new-decoded-pad", G_TYPE_FROM_CLASS (klass), |
210 g_signal_new ("new-decoded-pad", G_TYPE_FROM_CLASS (klass), |
253 G_SIGNAL_RUN_LAST, |
211 G_SIGNAL_RUN_LAST, |
254 G_STRUCT_OFFSET (GstDecodeBinClass, new_decoded_pad), NULL, NULL, |
212 G_STRUCT_OFFSET (GstDecodeBinClass, new_decoded_pad), NULL, NULL, |
255 gst_play_marshal_VOID__OBJECT_BOOLEAN, G_TYPE_NONE, 2, GST_TYPE_PAD, |
213 gst_play_marshal_VOID__OBJECT_BOOLEAN, G_TYPE_NONE, 2, GST_TYPE_PAD, |
256 G_TYPE_BOOLEAN); |
214 G_TYPE_BOOLEAN); |
257 /** |
|
258 * GstDecodeBin::removed-decoded-pad: |
|
259 * @bin: The decodebin |
|
260 * @pad: The pad that was removed |
|
261 * |
|
262 * This signal is emitted when a 'final' caps pad has been removed. |
|
263 */ |
|
264 gst_decode_bin_signals[SIGNAL_REMOVED_DECODED_PAD] = |
215 gst_decode_bin_signals[SIGNAL_REMOVED_DECODED_PAD] = |
265 g_signal_new ("removed-decoded-pad", G_TYPE_FROM_CLASS (klass), |
216 g_signal_new ("removed-decoded-pad", G_TYPE_FROM_CLASS (klass), |
266 G_SIGNAL_RUN_LAST, |
217 G_SIGNAL_RUN_LAST, |
267 G_STRUCT_OFFSET (GstDecodeBinClass, removed_decoded_pad), NULL, NULL, |
218 G_STRUCT_OFFSET (GstDecodeBinClass, removed_decoded_pad), NULL, NULL, |
268 gst_marshal_VOID__OBJECT, G_TYPE_NONE, 1, GST_TYPE_PAD); |
219 gst_marshal_VOID__OBJECT, G_TYPE_NONE, 1, GST_TYPE_PAD); |
269 /** |
|
270 * GstDecodeBin::unknown-type: |
|
271 * @bin: The decodebin |
|
272 * @pad: The new pad containing caps that cannot be resolved to a 'final' |
|
273 * stream type. |
|
274 * @caps: The #GstCaps of the pad that cannot be resolved. |
|
275 * |
|
276 * This signal is emitted when a pad for which there is no further possible |
|
277 * decoding is added to the decodebin. |
|
278 */ |
|
279 gst_decode_bin_signals[SIGNAL_UNKNOWN_TYPE] = |
220 gst_decode_bin_signals[SIGNAL_UNKNOWN_TYPE] = |
280 g_signal_new ("unknown-type", G_TYPE_FROM_CLASS (klass), |
221 g_signal_new ("unknown-type", G_TYPE_FROM_CLASS (klass), |
281 G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstDecodeBinClass, unknown_type), |
222 G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstDecodeBinClass, unknown_type), |
282 NULL, NULL, gst_marshal_VOID__OBJECT_BOXED, G_TYPE_NONE, 2, |
223 NULL, NULL, gst_marshal_VOID__OBJECT_OBJECT, G_TYPE_NONE, 2, |
283 GST_TYPE_PAD, GST_TYPE_CAPS); |
224 GST_TYPE_PAD, GST_TYPE_CAPS); |
284 |
225 |
285 g_object_class_install_property (gobject_klass, PROP_SINK_CAPS, |
226 gobject_klass->dispose = GST_DEBUG_FUNCPTR (gst_decode_bin_dispose); |
286 g_param_spec_boxed ("sink-caps", "Sink Caps", |
227 gobject_klass->finalize = GST_DEBUG_FUNCPTR (gst_decode_bin_finalize); |
287 "The caps of the input data. (NULL = use typefind element)", |
|
288 GST_TYPE_CAPS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); |
|
289 |
228 |
290 gst_element_class_add_pad_template (gstelement_klass, |
229 gst_element_class_add_pad_template (gstelement_klass, |
291 gst_static_pad_template_get (&decoder_bin_sink_template)); |
230 gst_static_pad_template_get (&decoder_bin_sink_template)); |
292 gst_element_class_add_pad_template (gstelement_klass, |
231 gst_element_class_add_pad_template (gstelement_klass, |
293 gst_static_pad_template_get (&decoder_bin_src_template)); |
232 gst_static_pad_template_get (&decoder_bin_src_template)); |
397 gst_object_unref (decode_bin->typefind); |
336 gst_object_unref (decode_bin->typefind); |
398 decode_bin->typefind = NULL; |
337 decode_bin->typefind = NULL; |
399 } |
338 } |
400 |
339 |
401 /* get the sinkpad */ |
340 /* get the sinkpad */ |
402 pad = gst_element_get_static_pad (decode_bin->typefind, "sink"); |
341 pad = gst_element_get_pad (decode_bin->typefind, "sink"); |
403 |
342 |
404 /* ghost the sink pad to ourself */ |
343 /* ghost the sink pad to ourself */ |
405 gpad = gst_ghost_pad_new ("sink", pad); |
344 gpad = gst_ghost_pad_new ("sink", pad); |
406 gst_pad_set_active (gpad, TRUE); |
345 gst_pad_set_active (gpad, TRUE); |
407 gst_element_add_pad (GST_ELEMENT (decode_bin), gpad); |
346 gst_element_add_pad (GST_ELEMENT (decode_bin), gpad); |
436 |
375 |
437 /* our parent dispose might trigger new signals when pads are unlinked |
376 /* our parent dispose might trigger new signals when pads are unlinked |
438 * etc. clean up the mess here. */ |
377 * etc. clean up the mess here. */ |
439 /* FIXME do proper cleanup when going to NULL */ |
378 /* FIXME do proper cleanup when going to NULL */ |
440 free_dynamics (decode_bin); |
379 free_dynamics (decode_bin); |
441 } |
|
442 |
|
443 static void |
|
444 gst_decode_bin_set_sink_caps (GstDecodeBin * dbin, GstCaps * caps) |
|
445 { |
|
446 GST_DEBUG_OBJECT (dbin, "Setting new caps: %" GST_PTR_FORMAT, caps); |
|
447 |
|
448 g_object_set (dbin->typefind, "force-caps", caps, NULL); |
|
449 } |
|
450 |
|
451 static GstCaps * |
|
452 gst_decode_bin_get_sink_caps (GstDecodeBin * dbin) |
|
453 { |
|
454 GstCaps *caps; |
|
455 |
|
456 GST_DEBUG_OBJECT (dbin, "Getting currently set caps"); |
|
457 |
|
458 g_object_get (dbin->typefind, "force-caps", &caps, NULL); |
|
459 |
|
460 return caps; |
|
461 } |
|
462 |
|
463 static void |
|
464 gst_decode_bin_set_property (GObject * object, guint prop_id, |
|
465 const GValue * value, GParamSpec * pspec) |
|
466 { |
|
467 GstDecodeBin *dbin; |
|
468 |
|
469 dbin = GST_DECODE_BIN (object); |
|
470 |
|
471 switch (prop_id) { |
|
472 case PROP_SINK_CAPS: |
|
473 gst_decode_bin_set_sink_caps (dbin, g_value_get_boxed (value)); |
|
474 break; |
|
475 default: |
|
476 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); |
|
477 break; |
|
478 } |
|
479 } |
|
480 |
|
481 static void |
|
482 gst_decode_bin_get_property (GObject * object, guint prop_id, |
|
483 GValue * value, GParamSpec * pspec) |
|
484 { |
|
485 GstDecodeBin *dbin; |
|
486 |
|
487 dbin = GST_DECODE_BIN (object); |
|
488 switch (prop_id) { |
|
489 case PROP_SINK_CAPS: |
|
490 g_value_take_boxed (value, gst_decode_bin_get_sink_caps (dbin)); |
|
491 break; |
|
492 default: |
|
493 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); |
|
494 break; |
|
495 } |
|
496 } |
380 } |
497 |
381 |
498 static void |
382 static void |
499 gst_decode_bin_finalize (GObject * object) |
383 gst_decode_bin_finalize (GObject * object) |
500 { |
384 { |
684 } |
568 } |
685 g_list_free (decode_bin->probes); |
569 g_list_free (decode_bin->probes); |
686 decode_bin->probes = NULL; |
570 decode_bin->probes = NULL; |
687 } |
571 } |
688 |
572 |
689 /* used when we need to remove a probe because the decoder we plugged failed |
|
690 * to activate */ |
|
691 static void |
|
692 free_pad_probe_for_element (GstDecodeBin * decode_bin, GstElement * element) |
|
693 { |
|
694 GList *l; |
|
695 |
|
696 for (l = decode_bin->probes; l != NULL; l = g_list_next (l)) { |
|
697 PadProbeData *data = (PadProbeData *) l->data; |
|
698 |
|
699 if (GST_ELEMENT_CAST (GST_PAD_PARENT (data->pad)) == element) { |
|
700 gst_pad_remove_data_probe (data->pad, data->sigid); |
|
701 decode_bin->probes = g_list_delete_link (decode_bin->probes, l); |
|
702 g_free (data); |
|
703 return; |
|
704 } |
|
705 } |
|
706 } |
|
707 |
|
708 static gboolean |
573 static gboolean |
709 add_fakesink (GstDecodeBin * decode_bin) |
574 add_fakesink (GstDecodeBin * decode_bin) |
710 { |
575 { |
711 if (decode_bin->fakesink != NULL) |
576 if (decode_bin->fakesink != NULL) |
712 return TRUE; |
577 return TRUE; |
749 |
614 |
750 g_mutex_lock (decode_bin->cb_mutex); |
615 g_mutex_lock (decode_bin->cb_mutex); |
751 if (decode_bin->fakesink) { |
616 if (decode_bin->fakesink) { |
752 GST_DEBUG_OBJECT (decode_bin, "Removing fakesink and marking state dirty"); |
617 GST_DEBUG_OBJECT (decode_bin, "Removing fakesink and marking state dirty"); |
753 |
618 |
754 /* Lock the state to prevent it from changing state to non-NULL |
|
755 * before it's removed */ |
|
756 gst_element_set_locked_state (decode_bin->fakesink, TRUE); |
|
757 /* setting the state to NULL is never async */ |
619 /* setting the state to NULL is never async */ |
758 gst_element_set_state (decode_bin->fakesink, GST_STATE_NULL); |
620 gst_element_set_state (decode_bin->fakesink, GST_STATE_NULL); |
759 gst_bin_remove (GST_BIN (decode_bin), decode_bin->fakesink); |
621 gst_bin_remove (GST_BIN (decode_bin), decode_bin->fakesink); |
760 decode_bin->fakesink = NULL; |
622 decode_bin->fakesink = NULL; |
761 |
623 |
803 if (alldone) |
665 if (alldone) |
804 remove_fakesink (decode_bin); |
666 remove_fakesink (decode_bin); |
805 return TRUE; |
667 return TRUE; |
806 } |
668 } |
807 |
669 |
808 /* FIXME: this should be somehow merged with the queue code in |
|
809 * try_to_link_1() to reduce code duplication */ |
|
810 static GstPad * |
|
811 add_raw_queue (GstDecodeBin * decode_bin, GstPad * pad) |
|
812 { |
|
813 GstElement *queue = NULL; |
|
814 GstPad *queuesinkpad = NULL, *queuesrcpad = NULL; |
|
815 |
|
816 queue = gst_element_factory_make ("queue", NULL); |
|
817 decode_bin->queue_type = G_OBJECT_TYPE (queue); |
|
818 |
|
819 g_object_set (G_OBJECT (queue), "max-size-buffers", 0, NULL); |
|
820 g_object_set (G_OBJECT (queue), "max-size-time", G_GINT64_CONSTANT (0), NULL); |
|
821 g_object_set (G_OBJECT (queue), "max-size-bytes", 8192, NULL); |
|
822 gst_bin_add (GST_BIN (decode_bin), queue); |
|
823 gst_element_set_state (queue, GST_STATE_READY); |
|
824 queuesinkpad = gst_element_get_static_pad (queue, "sink"); |
|
825 queuesrcpad = gst_element_get_static_pad (queue, "src"); |
|
826 |
|
827 if (gst_pad_link (pad, queuesinkpad) != GST_PAD_LINK_OK) { |
|
828 GST_WARNING_OBJECT (decode_bin, |
|
829 "Linking queue failed, trying without queue"); |
|
830 gst_element_set_state (queue, GST_STATE_NULL); |
|
831 gst_object_unref (queuesrcpad); |
|
832 gst_object_unref (queuesinkpad); |
|
833 gst_bin_remove (GST_BIN (decode_bin), queue); |
|
834 return gst_object_ref (pad); |
|
835 } |
|
836 |
|
837 decode_bin->queues = g_list_append (decode_bin->queues, queue); |
|
838 g_signal_connect (G_OBJECT (queue), |
|
839 "overrun", G_CALLBACK (queue_filled_cb), decode_bin); |
|
840 g_signal_connect (G_OBJECT (queue), |
|
841 "underrun", G_CALLBACK (queue_underrun_cb), decode_bin); |
|
842 |
|
843 gst_element_set_state (queue, GST_STATE_PAUSED); |
|
844 gst_object_unref (queuesinkpad); |
|
845 |
|
846 return queuesrcpad; |
|
847 } |
|
848 |
|
849 /* given a pad and a caps from an element, find the list of elements |
670 /* given a pad and a caps from an element, find the list of elements |
850 * that could connect to the pad |
671 * that could connect to the pad |
851 * |
672 * |
852 * If the pad has a raw format, this function will create a ghostpad |
673 * If the pad has a raw format, this function will create a ghostpad |
853 * for the pad onto the decodebin. |
674 * for the pad onto the decodebin. |
896 if (mimetype_is_raw (mimetype)) { |
717 if (mimetype_is_raw (mimetype)) { |
897 gchar *padname; |
718 gchar *padname; |
898 GstPad *ghost; |
719 GstPad *ghost; |
899 PadProbeData *data; |
720 PadProbeData *data; |
900 |
721 |
901 /* If we're at a demuxer element but have raw data already |
|
902 * we have to add a queue here. For non-raw data this is done |
|
903 * in try_to_link_1() */ |
|
904 if (is_demuxer_element (element)) { |
|
905 GST_DEBUG_OBJECT (decode_bin, |
|
906 "Element %s is a demuxer, inserting a queue", |
|
907 GST_OBJECT_NAME (element)); |
|
908 |
|
909 pad = add_raw_queue (decode_bin, pad); |
|
910 } |
|
911 |
|
912 /* make a unique name for this new pad */ |
722 /* make a unique name for this new pad */ |
913 padname = g_strdup_printf ("src%d", decode_bin->numpads); |
723 padname = g_strdup_printf ("src%d", decode_bin->numpads); |
914 decode_bin->numpads++; |
724 decode_bin->numpads++; |
915 |
725 |
916 /* make it a ghostpad */ |
726 /* make it a ghostpad */ |
936 g_signal_emit (G_OBJECT (decode_bin), |
746 g_signal_emit (G_OBJECT (decode_bin), |
937 gst_decode_bin_signals[SIGNAL_NEW_DECODED_PAD], 0, ghost, !more); |
747 gst_decode_bin_signals[SIGNAL_NEW_DECODED_PAD], 0, ghost, !more); |
938 GST_DEBUG_OBJECT (decode_bin, "emitted new-decoded-pad"); |
748 GST_DEBUG_OBJECT (decode_bin, "emitted new-decoded-pad"); |
939 |
749 |
940 g_free (padname); |
750 g_free (padname); |
941 |
|
942 /* If we're at a demuxer element pad was set to a queue's |
|
943 * srcpad and must be unref'd here */ |
|
944 if (is_demuxer_element (element)) |
|
945 gst_object_unref (pad); |
|
946 } else { |
751 } else { |
947 GList *to_try; |
752 GList *to_try; |
948 |
753 |
949 /* if the caps has many types, we need to delay */ |
754 /* if the caps has many types, we need to delay */ |
950 if (!gst_caps_is_fixed (caps)) |
755 if (!gst_caps_is_fixed (caps)) |
1094 g_object_set (G_OBJECT (queue), "max-size-time", G_GINT64_CONSTANT (0), |
899 g_object_set (G_OBJECT (queue), "max-size-time", G_GINT64_CONSTANT (0), |
1095 NULL); |
900 NULL); |
1096 g_object_set (G_OBJECT (queue), "max-size-bytes", 8192, NULL); |
901 g_object_set (G_OBJECT (queue), "max-size-bytes", 8192, NULL); |
1097 gst_bin_add (GST_BIN (decode_bin), queue); |
902 gst_bin_add (GST_BIN (decode_bin), queue); |
1098 gst_element_set_state (queue, GST_STATE_READY); |
903 gst_element_set_state (queue, GST_STATE_READY); |
1099 queuesinkpad = gst_element_get_static_pad (queue, "sink"); |
904 queuesinkpad = gst_element_get_pad (queue, "sink"); |
1100 usedsrcpad = queuesrcpad = gst_element_get_static_pad (queue, "src"); |
905 usedsrcpad = queuesrcpad = gst_element_get_pad (queue, "src"); |
1101 |
906 |
1102 dqlink = gst_pad_link (pad, queuesinkpad); |
907 dqlink = gst_pad_link (pad, queuesinkpad); |
1103 g_return_val_if_fail (dqlink == GST_PAD_LINK_OK, NULL); |
908 g_return_val_if_fail (dqlink == GST_PAD_LINK_OK, NULL); |
1104 } |
909 } |
1105 |
910 |
1122 } |
927 } |
1123 |
928 |
1124 /* try to link the given pad to a sinkpad */ |
929 /* try to link the given pad to a sinkpad */ |
1125 /* FIXME, find the sinkpad by looping over the pads instead of |
930 /* FIXME, find the sinkpad by looping over the pads instead of |
1126 * looking it up by name */ |
931 * looking it up by name */ |
1127 if ((sinkpad = gst_element_get_static_pad (element, "sink")) == NULL) { |
932 if ((sinkpad = gst_element_get_pad (element, "sink")) == NULL) { |
1128 /* if no pad is found we can't do anything */ |
933 /* if no pad is found we can't do anything */ |
1129 GST_WARNING_OBJECT (decode_bin, "could not find sinkpad in element"); |
934 GST_WARNING_OBJECT (decode_bin, "could not find sinkpad in element"); |
1130 continue; |
935 continue; |
1131 } |
936 } |
1132 |
937 |
1186 /* change the state of the element to that of the parent */ |
991 /* change the state of the element to that of the parent */ |
1187 if ((gst_element_set_state (element, |
992 if ((gst_element_set_state (element, |
1188 GST_STATE_PAUSED)) == GST_STATE_CHANGE_FAILURE) { |
993 GST_STATE_PAUSED)) == GST_STATE_CHANGE_FAILURE) { |
1189 GST_WARNING_OBJECT (decode_bin, "Couldn't set %s to PAUSED", |
994 GST_WARNING_OBJECT (decode_bin, "Couldn't set %s to PAUSED", |
1190 GST_ELEMENT_NAME (element)); |
995 GST_ELEMENT_NAME (element)); |
1191 /* close_link -> close_pad_link -> might have set up a pad probe */ |
|
1192 free_pad_probe_for_element (decode_bin, element); |
|
1193 gst_element_set_state (element, GST_STATE_NULL); |
996 gst_element_set_state (element, GST_STATE_NULL); |
1194 gst_bin_remove (GST_BIN (decode_bin), element); |
997 gst_bin_remove (GST_BIN (decode_bin), element); |
1195 continue; |
998 continue; |
1196 } |
999 } |
1197 |
1000 |
1284 * decoded stream. |
1087 * decoded stream. |
1285 */ |
1088 */ |
1286 static void |
1089 static void |
1287 remove_element_chain (GstDecodeBin * decode_bin, GstPad * pad) |
1090 remove_element_chain (GstDecodeBin * decode_bin, GstPad * pad) |
1288 { |
1091 { |
1289 GstIterator *iter; |
1092 GList *int_links, *walk; |
1290 gboolean done = FALSE; |
|
1291 gpointer item; |
|
1292 GstElement *elem = GST_ELEMENT (GST_OBJECT_PARENT (pad)); |
1093 GstElement *elem = GST_ELEMENT (GST_OBJECT_PARENT (pad)); |
1293 |
1094 |
1294 while (GST_OBJECT_PARENT (elem) && |
1095 while (GST_OBJECT_PARENT (elem) && |
1295 GST_OBJECT_PARENT (elem) != GST_OBJECT (decode_bin)) |
1096 GST_OBJECT_PARENT (elem) != GST_OBJECT (decode_bin)) |
1296 elem = GST_ELEMENT (GST_OBJECT_PARENT (elem)); |
1097 elem = GST_ELEMENT (GST_OBJECT_PARENT (elem)); |
1300 "Encountered demuxer output queue while removing element chain"); |
1101 "Encountered demuxer output queue while removing element chain"); |
1301 decode_bin->queues = g_list_remove (decode_bin->queues, elem); |
1102 decode_bin->queues = g_list_remove (decode_bin->queues, elem); |
1302 } |
1103 } |
1303 |
1104 |
1304 GST_DEBUG_OBJECT (decode_bin, "%s:%s", GST_DEBUG_PAD_NAME (pad)); |
1105 GST_DEBUG_OBJECT (decode_bin, "%s:%s", GST_DEBUG_PAD_NAME (pad)); |
1305 iter = gst_pad_iterate_internal_links (pad); |
1106 int_links = gst_pad_get_internal_links (pad); |
1306 if (!iter) |
|
1307 goto no_iter; |
|
1308 |
1107 |
1309 /* remove all elements linked to this pad up to the ghostpad |
1108 /* remove all elements linked to this pad up to the ghostpad |
1310 * that we created for this stream */ |
1109 * that we created for this stream */ |
1311 while (!done) { |
1110 for (walk = int_links; walk; walk = g_list_next (walk)) { |
1312 switch (gst_iterator_next (iter, &item)) { |
1111 GstPad *pad; |
1313 case GST_ITERATOR_OK:{ |
1112 GstPad *ghostpad; |
1314 GstPad *pad; |
1113 GstPad *peer; |
1315 GstPad *ghostpad; |
1114 |
1316 GstPad *peer; |
1115 pad = GST_PAD (walk->data); |
1317 |
1116 GST_DEBUG_OBJECT (decode_bin, "inspecting internal pad %s:%s", |
1318 pad = GST_PAD (item); |
1117 GST_DEBUG_PAD_NAME (pad)); |
1319 GST_DEBUG_OBJECT (decode_bin, "inspecting internal pad %s:%s", |
1118 |
1320 GST_DEBUG_PAD_NAME (pad)); |
1119 ghostpad = get_our_ghost_pad (decode_bin, pad); |
1321 |
1120 if (ghostpad) { |
1322 ghostpad = get_our_ghost_pad (decode_bin, pad); |
1121 GST_DEBUG_OBJECT (decode_bin, "found our ghost pad %s:%s for %s:%s", |
1323 if (ghostpad) { |
1122 GST_DEBUG_PAD_NAME (ghostpad), GST_DEBUG_PAD_NAME (pad)); |
1324 GST_DEBUG_OBJECT (decode_bin, "found our ghost pad %s:%s for %s:%s", |
1123 |
1325 GST_DEBUG_PAD_NAME (ghostpad), GST_DEBUG_PAD_NAME (pad)); |
1124 g_signal_emit (G_OBJECT (decode_bin), |
1326 |
1125 gst_decode_bin_signals[SIGNAL_REMOVED_DECODED_PAD], 0, ghostpad); |
1327 g_signal_emit (G_OBJECT (decode_bin), |
1126 |
1328 gst_decode_bin_signals[SIGNAL_REMOVED_DECODED_PAD], 0, ghostpad); |
1127 gst_element_remove_pad (GST_ELEMENT (decode_bin), ghostpad); |
1329 |
1128 gst_object_unref (ghostpad); |
1330 gst_element_remove_pad (GST_ELEMENT (decode_bin), ghostpad); |
1129 continue; |
1331 gst_object_unref (ghostpad); |
1130 } else { |
1332 continue; |
1131 GST_DEBUG_OBJECT (decode_bin, "not one of our ghostpads"); |
1333 } else { |
1132 } |
1334 GST_DEBUG_OBJECT (decode_bin, "not one of our ghostpads"); |
1133 |
1134 peer = gst_pad_get_peer (pad); |
|
1135 if (peer == NULL) |
|
1136 continue; |
|
1137 |
|
1138 GST_DEBUG_OBJECT (decode_bin, "internal pad %s:%s linked to pad %s:%s", |
|
1139 GST_DEBUG_PAD_NAME (pad), GST_DEBUG_PAD_NAME (peer)); |
|
1140 |
|
1141 { |
|
1142 GstObject *parent = gst_pad_get_parent (peer); |
|
1143 |
|
1144 if (parent) { |
|
1145 GstObject *grandparent = gst_object_get_parent (parent); |
|
1146 |
|
1147 if (grandparent != NULL) { |
|
1148 if (GST_ELEMENT (grandparent) != GST_ELEMENT (decode_bin)) { |
|
1149 GST_DEBUG_OBJECT (decode_bin, "dead end pad %s:%s parent %s", |
|
1150 GST_DEBUG_PAD_NAME (peer), GST_OBJECT_NAME (grandparent)); |
|
1151 } else { |
|
1152 GST_DEBUG_OBJECT (decode_bin, "recursing element %s on pad %s:%s", |
|
1153 GST_ELEMENT_NAME (elem), GST_DEBUG_PAD_NAME (pad)); |
|
1154 remove_element_chain (decode_bin, peer); |
|
1155 } |
|
1156 gst_object_unref (grandparent); |
|
1335 } |
1157 } |
1336 |
1158 gst_object_unref (parent); |
1337 peer = gst_pad_get_peer (pad); |
|
1338 if (peer) { |
|
1339 GstObject *parent = gst_pad_get_parent (peer); |
|
1340 |
|
1341 GST_DEBUG_OBJECT (decode_bin, |
|
1342 "internal pad %s:%s linked to pad %s:%s", |
|
1343 GST_DEBUG_PAD_NAME (pad), GST_DEBUG_PAD_NAME (peer)); |
|
1344 |
|
1345 if (parent) { |
|
1346 GstObject *grandparent = gst_object_get_parent (parent); |
|
1347 |
|
1348 if (grandparent != NULL) { |
|
1349 if (GST_ELEMENT (grandparent) != GST_ELEMENT (decode_bin)) { |
|
1350 GST_DEBUG_OBJECT (decode_bin, "dead end pad %s:%s parent %s", |
|
1351 GST_DEBUG_PAD_NAME (peer), GST_OBJECT_NAME (grandparent)); |
|
1352 } else { |
|
1353 GST_DEBUG_OBJECT (decode_bin, |
|
1354 "recursing element %s on pad %s:%s", |
|
1355 GST_ELEMENT_NAME (elem), GST_DEBUG_PAD_NAME (pad)); |
|
1356 remove_element_chain (decode_bin, peer); |
|
1357 } |
|
1358 gst_object_unref (grandparent); |
|
1359 } |
|
1360 gst_object_unref (parent); |
|
1361 } |
|
1362 gst_object_unref (peer); |
|
1363 } |
|
1364 gst_object_unref (item); |
|
1365 } |
1159 } |
1366 break; |
1160 } |
1367 case GST_ITERATOR_RESYNC: |
1161 gst_object_unref (peer); |
1368 gst_iterator_resync (iter); |
|
1369 break; |
|
1370 case GST_ITERATOR_ERROR: |
|
1371 GST_ERROR_OBJECT (pad, "Could not iterate over internally linked pads"); |
|
1372 done = TRUE; |
|
1373 break; |
|
1374 case GST_ITERATOR_DONE: |
|
1375 done = TRUE; |
|
1376 break; |
|
1377 } |
|
1378 } |
1162 } |
1379 GST_DEBUG_OBJECT (decode_bin, "removing %s", GST_ELEMENT_NAME (elem)); |
1163 GST_DEBUG_OBJECT (decode_bin, "removing %s", GST_ELEMENT_NAME (elem)); |
1380 |
1164 |
1381 gst_iterator_free (iter); |
1165 g_list_free (int_links); |
1382 |
1166 |
1383 no_iter: |
|
1384 gst_element_set_state (elem, GST_STATE_NULL); |
1167 gst_element_set_state (elem, GST_STATE_NULL); |
1168 |
|
1385 gst_bin_remove (GST_BIN (decode_bin), elem); |
1169 gst_bin_remove (GST_BIN (decode_bin), elem); |
1386 } |
1170 } |
1387 |
1171 |
1388 /* there are @bytes bytes in @queue, enlarge it |
1172 /* there are @bytes bytes in @queue, enlarge it |
1389 * |
1173 * |
1612 switch (GST_PAD_TEMPLATE_PRESENCE (templ)) { |
1396 switch (GST_PAD_TEMPLATE_PRESENCE (templ)) { |
1613 case GST_PAD_SOMETIMES: |
1397 case GST_PAD_SOMETIMES: |
1614 { |
1398 { |
1615 /* try to get the pad to see if it is already created or |
1399 /* try to get the pad to see if it is already created or |
1616 * not */ |
1400 * not */ |
1617 GstPad *pad = gst_element_get_static_pad (element, templ_name); |
1401 GstPad *pad = gst_element_get_pad (element, templ_name); |
1618 |
1402 |
1619 if (pad) { |
1403 if (pad) { |
1620 GST_DEBUG_OBJECT (decode_bin, "got the pad for sometimes template %s", |
1404 GST_DEBUG_OBJECT (decode_bin, "got the pad for sometimes template %s", |
1621 templ_name); |
1405 templ_name); |
1622 gst_object_unref (pad); |
1406 gst_object_unref (pad); |
1699 /* figure out what kind of pad this is */ |
1483 /* figure out what kind of pad this is */ |
1700 switch (GST_PAD_TEMPLATE_PRESENCE (templ)) { |
1484 switch (GST_PAD_TEMPLATE_PRESENCE (templ)) { |
1701 case GST_PAD_ALWAYS: |
1485 case GST_PAD_ALWAYS: |
1702 { |
1486 { |
1703 /* get the pad that we need to autoplug */ |
1487 /* get the pad that we need to autoplug */ |
1704 GstPad *pad = gst_element_get_static_pad (element, templ_name); |
1488 GstPad *pad = gst_element_get_pad (element, templ_name); |
1705 |
1489 |
1706 if (pad) { |
1490 if (pad) { |
1707 GST_DEBUG_OBJECT (decode_bin, "got the pad for always template %s", |
1491 GST_DEBUG_OBJECT (decode_bin, "got the pad for always template %s", |
1708 templ_name); |
1492 templ_name); |
1709 /* here is the pad, we need to autoplug it */ |
1493 /* here is the pad, we need to autoplug it */ |
1718 } |
1502 } |
1719 case GST_PAD_SOMETIMES: |
1503 case GST_PAD_SOMETIMES: |
1720 { |
1504 { |
1721 /* try to get the pad to see if it is already created or |
1505 /* try to get the pad to see if it is already created or |
1722 * not */ |
1506 * not */ |
1723 GstPad *pad = gst_element_get_static_pad (element, templ_name); |
1507 GstPad *pad = gst_element_get_pad (element, templ_name); |
1724 |
1508 |
1725 if (pad) { |
1509 if (pad) { |
1726 GST_DEBUG_OBJECT (decode_bin, "got the pad for sometimes template %s", |
1510 GST_DEBUG_OBJECT (decode_bin, "got the pad for sometimes template %s", |
1727 templ_name); |
1511 templ_name); |
1728 /* the pad is created, we need to autoplug it */ |
1512 /* the pad is created, we need to autoplug it */ |
1819 ("decodebin cannot decode plain text files")); |
1603 ("decodebin cannot decode plain text files")); |
1820 goto exit; |
1604 goto exit; |
1821 } |
1605 } |
1822 |
1606 |
1823 /* autoplug the new pad with the caps that the signal gave us. */ |
1607 /* autoplug the new pad with the caps that the signal gave us. */ |
1824 pad = gst_element_get_static_pad (typefind, "src"); |
1608 pad = gst_element_get_pad (typefind, "src"); |
1825 close_pad_link (typefind, pad, caps, decode_bin, FALSE); |
1609 close_pad_link (typefind, pad, caps, decode_bin, FALSE); |
1826 gst_object_unref (pad); |
1610 gst_object_unref (pad); |
1827 |
1611 |
1828 dynamic = gst_decode_bin_is_dynamic (decode_bin); |
1612 dynamic = gst_decode_bin_is_dynamic (decode_bin); |
1829 if (dynamic == FALSE) { |
1613 if (dynamic == FALSE) { |
1885 |
1669 |
1886 g_return_if_fail (GST_IS_DECODE_BIN (decode_bin)); |
1670 g_return_if_fail (GST_IS_DECODE_BIN (decode_bin)); |
1887 |
1671 |
1888 GST_DEBUG_OBJECT (decode_bin, "cleaning up decodebin"); |
1672 GST_DEBUG_OBJECT (decode_bin, "cleaning up decodebin"); |
1889 |
1673 |
1890 typefind_pad = gst_element_get_static_pad (decode_bin->typefind, "src"); |
1674 typefind_pad = gst_element_get_pad (decode_bin->typefind, "src"); |
1891 if (GST_IS_PAD (typefind_pad)) { |
1675 if (GST_IS_PAD (typefind_pad)) { |
1892 g_signal_handlers_block_by_func (typefind_pad, (gpointer) unlinked, |
1676 g_signal_handlers_block_by_func (typefind_pad, (gpointer) unlinked, |
1893 decode_bin); |
1677 decode_bin); |
1894 } |
1678 } |
1895 |
1679 |
2036 |
1820 |
2037 #ifdef ENABLE_NLS |
1821 #ifdef ENABLE_NLS |
2038 GST_DEBUG ("binding text domain %s to locale dir %s", GETTEXT_PACKAGE, |
1822 GST_DEBUG ("binding text domain %s to locale dir %s", GETTEXT_PACKAGE, |
2039 LOCALEDIR); |
1823 LOCALEDIR); |
2040 bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR); |
1824 bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR); |
2041 bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); |
|
2042 #endif /* ENABLE_NLS */ |
1825 #endif /* ENABLE_NLS */ |
2043 |
1826 |
2044 return gst_element_register (plugin, "decodebin", GST_RANK_NONE, |
1827 return gst_element_register (plugin, "decodebin", GST_RANK_NONE, |
2045 GST_TYPE_DECODE_BIN); |
1828 GST_TYPE_DECODE_BIN); |
2046 } |
1829 } |