gst_plugins_base/gst/playback/gstdecodebin.c
branchRCL_3
changeset 30 7e817e7e631c
parent 29 567bb019e3e3
--- a/gst_plugins_base/gst/playback/gstdecodebin.c	Tue Aug 31 15:30:33 2010 +0300
+++ b/gst_plugins_base/gst/playback/gstdecodebin.c	Wed Sep 01 12:16:41 2010 +0100
@@ -17,17 +17,6 @@
  * Boston, MA 02111-1307, USA.
  */
 
-/**
- * SECTION:element-decodebin
- *
- * #GstBin that auto-magically constructs a decoding pipeline using available
- * decoders and demuxers via auto-plugging.
- *
- * When using decodebin in your application, connect a signal handler to
- * #GstDecodeBin::new-decoded-pad and connect your sinks from within the
- * callback function.
- */
-
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
@@ -37,6 +26,7 @@
 #include <string.h>
 #include <gst/gst.h>
 #include <gst/pbutils/pbutils.h>
+#include <glib_global.h>
 
 #include "gstplay-marshal.h"
 
@@ -65,11 +55,6 @@
 typedef struct _GstDecodeBin GstDecodeBin;
 typedef struct _GstDecodeBinClass GstDecodeBinClass;
 
-/**
- * GstDecodeBin:
- *
- * Auto-plugging decoder element structure
- */
 struct _GstDecodeBin
 {
   GstBin bin;                   /* we extend GstBin */
@@ -119,13 +104,6 @@
   LAST_SIGNAL
 };
 
-/* Properties */
-enum
-{
-  PROP_0,
-  PROP_SINK_CAPS,
-};
-
 
 typedef struct
 {
@@ -151,10 +129,6 @@
 
 static void gst_decode_bin_class_init (GstDecodeBinClass * klass);
 static void gst_decode_bin_init (GstDecodeBin * decode_bin);
-static void gst_decode_bin_set_property (GObject * object, guint prop_id,
-    const GValue * value, GParamSpec * pspec);
-static void gst_decode_bin_get_property (GObject * object, guint prop_id,
-    GValue * value, GParamSpec * pspec);
 static void gst_decode_bin_dispose (GObject * object);
 static void gst_decode_bin_finalize (GObject * object);
 
@@ -182,8 +156,6 @@
 static void queue_filled_cb (GstElement * queue, GstDecodeBin * decode_bin);
 static void queue_underrun_cb (GstElement * queue, GstDecodeBin * decode_bin);
 
-static gboolean is_demuxer_element (GstElement * srcelement);
-
 static GstElementClass *parent_class;
 static guint gst_decode_bin_signals[LAST_SIGNAL] = { 0 };
 
@@ -234,58 +206,25 @@
 
   parent_class = g_type_class_peek_parent (klass);
 
-  gobject_klass->set_property = GST_DEBUG_FUNCPTR (gst_decode_bin_set_property);
-  gobject_klass->get_property = GST_DEBUG_FUNCPTR (gst_decode_bin_get_property);
-  gobject_klass->dispose = GST_DEBUG_FUNCPTR (gst_decode_bin_dispose);
-  gobject_klass->finalize = GST_DEBUG_FUNCPTR (gst_decode_bin_finalize);
-
-  /**
-   * GstDecodeBin::new-decoded-pad:
-   * @bin: The decodebin
-   * @pad: The newly created pad
-   * @islast: #TRUE if this is the last pad to be added. Deprecated.
-   *
-   * This signal gets emitted as soon as a new pad of the same type as one of
-   * the valid 'raw' types is added.
-   */
   gst_decode_bin_signals[SIGNAL_NEW_DECODED_PAD] =
       g_signal_new ("new-decoded-pad", G_TYPE_FROM_CLASS (klass),
       G_SIGNAL_RUN_LAST,
       G_STRUCT_OFFSET (GstDecodeBinClass, new_decoded_pad), NULL, NULL,
       gst_play_marshal_VOID__OBJECT_BOOLEAN, G_TYPE_NONE, 2, GST_TYPE_PAD,
       G_TYPE_BOOLEAN);
-  /**
-   * GstDecodeBin::removed-decoded-pad:
-   * @bin: The decodebin
-   * @pad: The pad that was removed
-   *
-   * This signal is emitted when a 'final' caps pad has been removed.
-   */
   gst_decode_bin_signals[SIGNAL_REMOVED_DECODED_PAD] =
       g_signal_new ("removed-decoded-pad", G_TYPE_FROM_CLASS (klass),
       G_SIGNAL_RUN_LAST,
       G_STRUCT_OFFSET (GstDecodeBinClass, removed_decoded_pad), NULL, NULL,
       gst_marshal_VOID__OBJECT, G_TYPE_NONE, 1, GST_TYPE_PAD);
-  /**
-   * GstDecodeBin::unknown-type:
-   * @bin: The decodebin
-   * @pad: The new pad containing caps that cannot be resolved to a 'final'
-   *       stream type.
-   * @caps: The #GstCaps of the pad that cannot be resolved.
-   *
-   * This signal is emitted when a pad for which there is no further possible
-   * decoding is added to the decodebin.
-   */
   gst_decode_bin_signals[SIGNAL_UNKNOWN_TYPE] =
       g_signal_new ("unknown-type", G_TYPE_FROM_CLASS (klass),
       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstDecodeBinClass, unknown_type),
-      NULL, NULL, gst_marshal_VOID__OBJECT_BOXED, G_TYPE_NONE, 2,
+      NULL, NULL, gst_marshal_VOID__OBJECT_OBJECT, G_TYPE_NONE, 2,
       GST_TYPE_PAD, GST_TYPE_CAPS);
 
-  g_object_class_install_property (gobject_klass, PROP_SINK_CAPS,
-      g_param_spec_boxed ("sink-caps", "Sink Caps",
-          "The caps of the input data. (NULL = use typefind element)",
-          GST_TYPE_CAPS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+  gobject_klass->dispose = GST_DEBUG_FUNCPTR (gst_decode_bin_dispose);
+  gobject_klass->finalize = GST_DEBUG_FUNCPTR (gst_decode_bin_finalize);
 
   gst_element_class_add_pad_template (gstelement_klass,
       gst_static_pad_template_get (&decoder_bin_sink_template));
@@ -399,7 +338,7 @@
     }
 
     /* get the sinkpad */
-    pad = gst_element_get_static_pad (decode_bin->typefind, "sink");
+    pad = gst_element_get_pad (decode_bin->typefind, "sink");
 
     /* ghost the sink pad to ourself */
     gpad = gst_ghost_pad_new ("sink", pad);
@@ -441,61 +380,6 @@
 }
 
 static void
-gst_decode_bin_set_sink_caps (GstDecodeBin * dbin, GstCaps * caps)
-{
-  GST_DEBUG_OBJECT (dbin, "Setting new caps: %" GST_PTR_FORMAT, caps);
-
-  g_object_set (dbin->typefind, "force-caps", caps, NULL);
-}
-
-static GstCaps *
-gst_decode_bin_get_sink_caps (GstDecodeBin * dbin)
-{
-  GstCaps *caps;
-
-  GST_DEBUG_OBJECT (dbin, "Getting currently set caps");
-
-  g_object_get (dbin->typefind, "force-caps", &caps, NULL);
-
-  return caps;
-}
-
-static void
-gst_decode_bin_set_property (GObject * object, guint prop_id,
-    const GValue * value, GParamSpec * pspec)
-{
-  GstDecodeBin *dbin;
-
-  dbin = GST_DECODE_BIN (object);
-
-  switch (prop_id) {
-    case PROP_SINK_CAPS:
-      gst_decode_bin_set_sink_caps (dbin, g_value_get_boxed (value));
-      break;
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-  }
-}
-
-static void
-gst_decode_bin_get_property (GObject * object, guint prop_id,
-    GValue * value, GParamSpec * pspec)
-{
-  GstDecodeBin *dbin;
-
-  dbin = GST_DECODE_BIN (object);
-  switch (prop_id) {
-    case PROP_SINK_CAPS:
-      g_value_take_boxed (value, gst_decode_bin_get_sink_caps (dbin));
-      break;
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-  }
-}
-
-static void
 gst_decode_bin_finalize (GObject * object)
 {
   GstDecodeBin *decode_bin = GST_DECODE_BIN (object);
@@ -686,25 +570,6 @@
   decode_bin->probes = NULL;
 }
 
-/* used when we need to remove a probe because the decoder we plugged failed
- * to activate */
-static void
-free_pad_probe_for_element (GstDecodeBin * decode_bin, GstElement * element)
-{
-  GList *l;
-
-  for (l = decode_bin->probes; l != NULL; l = g_list_next (l)) {
-    PadProbeData *data = (PadProbeData *) l->data;
-
-    if (GST_ELEMENT_CAST (GST_PAD_PARENT (data->pad)) == element) {
-      gst_pad_remove_data_probe (data->pad, data->sigid);
-      decode_bin->probes = g_list_delete_link (decode_bin->probes, l);
-      g_free (data);
-      return;
-    }
-  }
-}
-
 static gboolean
 add_fakesink (GstDecodeBin * decode_bin)
 {
@@ -751,9 +616,6 @@
   if (decode_bin->fakesink) {
     GST_DEBUG_OBJECT (decode_bin, "Removing fakesink and marking state dirty");
 
-    /* Lock the state to prevent it from changing state to non-NULL
-     * before it's removed */
-    gst_element_set_locked_state (decode_bin->fakesink, TRUE);
     /* setting the state to NULL is never async */
     gst_element_set_state (decode_bin->fakesink, GST_STATE_NULL);
     gst_bin_remove (GST_BIN (decode_bin), decode_bin->fakesink);
@@ -805,47 +667,6 @@
   return TRUE;
 }
 
-/* FIXME: this should be somehow merged with the queue code in
- * try_to_link_1() to reduce code duplication */
-static GstPad *
-add_raw_queue (GstDecodeBin * decode_bin, GstPad * pad)
-{
-  GstElement *queue = NULL;
-  GstPad *queuesinkpad = NULL, *queuesrcpad = NULL;
-
-  queue = gst_element_factory_make ("queue", NULL);
-  decode_bin->queue_type = G_OBJECT_TYPE (queue);
-
-  g_object_set (G_OBJECT (queue), "max-size-buffers", 0, NULL);
-  g_object_set (G_OBJECT (queue), "max-size-time", G_GINT64_CONSTANT (0), NULL);
-  g_object_set (G_OBJECT (queue), "max-size-bytes", 8192, NULL);
-  gst_bin_add (GST_BIN (decode_bin), queue);
-  gst_element_set_state (queue, GST_STATE_READY);
-  queuesinkpad = gst_element_get_static_pad (queue, "sink");
-  queuesrcpad = gst_element_get_static_pad (queue, "src");
-
-  if (gst_pad_link (pad, queuesinkpad) != GST_PAD_LINK_OK) {
-    GST_WARNING_OBJECT (decode_bin,
-        "Linking queue failed, trying without queue");
-    gst_element_set_state (queue, GST_STATE_NULL);
-    gst_object_unref (queuesrcpad);
-    gst_object_unref (queuesinkpad);
-    gst_bin_remove (GST_BIN (decode_bin), queue);
-    return gst_object_ref (pad);
-  }
-
-  decode_bin->queues = g_list_append (decode_bin->queues, queue);
-  g_signal_connect (G_OBJECT (queue),
-      "overrun", G_CALLBACK (queue_filled_cb), decode_bin);
-  g_signal_connect (G_OBJECT (queue),
-      "underrun", G_CALLBACK (queue_underrun_cb), decode_bin);
-
-  gst_element_set_state (queue, GST_STATE_PAUSED);
-  gst_object_unref (queuesinkpad);
-
-  return queuesrcpad;
-}
-
 /* given a pad and a caps from an element, find the list of elements
  * that could connect to the pad
  *
@@ -898,17 +719,6 @@
     GstPad *ghost;
     PadProbeData *data;
 
-    /* If we're at a demuxer element but have raw data already
-     * we have to add a queue here. For non-raw data this is done
-     * in try_to_link_1() */
-    if (is_demuxer_element (element)) {
-      GST_DEBUG_OBJECT (decode_bin,
-          "Element %s is a demuxer, inserting a queue",
-          GST_OBJECT_NAME (element));
-
-      pad = add_raw_queue (decode_bin, pad);
-    }
-
     /* make a unique name for this new pad */
     padname = g_strdup_printf ("src%d", decode_bin->numpads);
     decode_bin->numpads++;
@@ -938,11 +748,6 @@
     GST_DEBUG_OBJECT (decode_bin, "emitted new-decoded-pad");
 
     g_free (padname);
-
-    /* If we're at a demuxer element pad was set to a queue's
-     * srcpad and must be unref'd here */
-    if (is_demuxer_element (element))
-      gst_object_unref (pad);
   } else {
     GList *to_try;
 
@@ -1096,8 +901,8 @@
     g_object_set (G_OBJECT (queue), "max-size-bytes", 8192, NULL);
     gst_bin_add (GST_BIN (decode_bin), queue);
     gst_element_set_state (queue, GST_STATE_READY);
-    queuesinkpad = gst_element_get_static_pad (queue, "sink");
-    usedsrcpad = queuesrcpad = gst_element_get_static_pad (queue, "src");
+    queuesinkpad = gst_element_get_pad (queue, "sink");
+    usedsrcpad = queuesrcpad = gst_element_get_pad (queue, "src");
 
     dqlink = gst_pad_link (pad, queuesinkpad);
     g_return_val_if_fail (dqlink == GST_PAD_LINK_OK, NULL);
@@ -1124,7 +929,7 @@
     /* try to link the given pad to a sinkpad */
     /* FIXME, find the sinkpad by looping over the pads instead of
      * looking it up by name */
-    if ((sinkpad = gst_element_get_static_pad (element, "sink")) == NULL) {
+    if ((sinkpad = gst_element_get_pad (element, "sink")) == NULL) {
       /* if no pad is found we can't do anything */
       GST_WARNING_OBJECT (decode_bin, "could not find sinkpad in element");
       continue;
@@ -1188,8 +993,6 @@
                   GST_STATE_PAUSED)) == GST_STATE_CHANGE_FAILURE) {
         GST_WARNING_OBJECT (decode_bin, "Couldn't set %s to PAUSED",
             GST_ELEMENT_NAME (element));
-        /* close_link -> close_pad_link -> might have set up a pad probe */
-        free_pad_probe_for_element (decode_bin, element);
         gst_element_set_state (element, GST_STATE_NULL);
         gst_bin_remove (GST_BIN (decode_bin), element);
         continue;
@@ -1286,9 +1089,7 @@
 static void
 remove_element_chain (GstDecodeBin * decode_bin, GstPad * pad)
 {
-  GstIterator *iter;
-  gboolean done = FALSE;
-  gpointer item;
+  GList *int_links, *walk;
   GstElement *elem = GST_ELEMENT (GST_OBJECT_PARENT (pad));
 
   while (GST_OBJECT_PARENT (elem) &&
@@ -1302,86 +1103,69 @@
   }
 
   GST_DEBUG_OBJECT (decode_bin, "%s:%s", GST_DEBUG_PAD_NAME (pad));
-  iter = gst_pad_iterate_internal_links (pad);
-  if (!iter)
-    goto no_iter;
+  int_links = gst_pad_get_internal_links (pad);
 
   /* remove all elements linked to this pad up to the ghostpad
    * that we created for this stream */
-  while (!done) {
-    switch (gst_iterator_next (iter, &item)) {
-      case GST_ITERATOR_OK:{
-        GstPad *pad;
-        GstPad *ghostpad;
-        GstPad *peer;
+  for (walk = int_links; walk; walk = g_list_next (walk)) {
+    GstPad *pad;
+    GstPad *ghostpad;
+    GstPad *peer;
 
-        pad = GST_PAD (item);
-        GST_DEBUG_OBJECT (decode_bin, "inspecting internal pad %s:%s",
-            GST_DEBUG_PAD_NAME (pad));
-
-        ghostpad = get_our_ghost_pad (decode_bin, pad);
-        if (ghostpad) {
-          GST_DEBUG_OBJECT (decode_bin, "found our ghost pad %s:%s for %s:%s",
-              GST_DEBUG_PAD_NAME (ghostpad), GST_DEBUG_PAD_NAME (pad));
+    pad = GST_PAD (walk->data);
+    GST_DEBUG_OBJECT (decode_bin, "inspecting internal pad %s:%s",
+        GST_DEBUG_PAD_NAME (pad));
 
-          g_signal_emit (G_OBJECT (decode_bin),
-              gst_decode_bin_signals[SIGNAL_REMOVED_DECODED_PAD], 0, ghostpad);
+    ghostpad = get_our_ghost_pad (decode_bin, pad);
+    if (ghostpad) {
+      GST_DEBUG_OBJECT (decode_bin, "found our ghost pad %s:%s for %s:%s",
+          GST_DEBUG_PAD_NAME (ghostpad), GST_DEBUG_PAD_NAME (pad));
 
-          gst_element_remove_pad (GST_ELEMENT (decode_bin), ghostpad);
-          gst_object_unref (ghostpad);
-          continue;
-        } else {
-          GST_DEBUG_OBJECT (decode_bin, "not one of our ghostpads");
-        }
+      g_signal_emit (G_OBJECT (decode_bin),
+          gst_decode_bin_signals[SIGNAL_REMOVED_DECODED_PAD], 0, ghostpad);
 
-        peer = gst_pad_get_peer (pad);
-        if (peer) {
-          GstObject *parent = gst_pad_get_parent (peer);
-
-          GST_DEBUG_OBJECT (decode_bin,
-              "internal pad %s:%s linked to pad %s:%s",
-              GST_DEBUG_PAD_NAME (pad), GST_DEBUG_PAD_NAME (peer));
+      gst_element_remove_pad (GST_ELEMENT (decode_bin), ghostpad);
+      gst_object_unref (ghostpad);
+      continue;
+    } else {
+      GST_DEBUG_OBJECT (decode_bin, "not one of our ghostpads");
+    }
 
-          if (parent) {
-            GstObject *grandparent = gst_object_get_parent (parent);
+    peer = gst_pad_get_peer (pad);
+    if (peer == NULL)
+      continue;
+
+    GST_DEBUG_OBJECT (decode_bin, "internal pad %s:%s linked to pad %s:%s",
+        GST_DEBUG_PAD_NAME (pad), GST_DEBUG_PAD_NAME (peer));
+
+    {
+      GstObject *parent = gst_pad_get_parent (peer);
 
-            if (grandparent != NULL) {
-              if (GST_ELEMENT (grandparent) != GST_ELEMENT (decode_bin)) {
-                GST_DEBUG_OBJECT (decode_bin, "dead end pad %s:%s parent %s",
-                    GST_DEBUG_PAD_NAME (peer), GST_OBJECT_NAME (grandparent));
-              } else {
-                GST_DEBUG_OBJECT (decode_bin,
-                    "recursing element %s on pad %s:%s",
-                    GST_ELEMENT_NAME (elem), GST_DEBUG_PAD_NAME (pad));
-                remove_element_chain (decode_bin, peer);
-              }
-              gst_object_unref (grandparent);
-            }
-            gst_object_unref (parent);
+      if (parent) {
+        GstObject *grandparent = gst_object_get_parent (parent);
+
+        if (grandparent != NULL) {
+          if (GST_ELEMENT (grandparent) != GST_ELEMENT (decode_bin)) {
+            GST_DEBUG_OBJECT (decode_bin, "dead end pad %s:%s parent %s",
+                GST_DEBUG_PAD_NAME (peer), GST_OBJECT_NAME (grandparent));
+          } else {
+            GST_DEBUG_OBJECT (decode_bin, "recursing element %s on pad %s:%s",
+                GST_ELEMENT_NAME (elem), GST_DEBUG_PAD_NAME (pad));
+            remove_element_chain (decode_bin, peer);
           }
-          gst_object_unref (peer);
+          gst_object_unref (grandparent);
         }
-        gst_object_unref (item);
+        gst_object_unref (parent);
       }
-        break;
-      case GST_ITERATOR_RESYNC:
-        gst_iterator_resync (iter);
-        break;
-      case GST_ITERATOR_ERROR:
-        GST_ERROR_OBJECT (pad, "Could not iterate over internally linked pads");
-        done = TRUE;
-        break;
-      case GST_ITERATOR_DONE:
-        done = TRUE;
-        break;
     }
+    gst_object_unref (peer);
   }
   GST_DEBUG_OBJECT (decode_bin, "removing %s", GST_ELEMENT_NAME (elem));
 
-  gst_iterator_free (iter);
+  g_list_free (int_links);
 
-no_iter:
   gst_element_set_state (elem, GST_STATE_NULL);
+
   gst_bin_remove (GST_BIN (decode_bin), elem);
 }
 
@@ -1614,7 +1398,7 @@
       {
         /* try to get the pad to see if it is already created or
          * not */
-        GstPad *pad = gst_element_get_static_pad (element, templ_name);
+        GstPad *pad = gst_element_get_pad (element, templ_name);
 
         if (pad) {
           GST_DEBUG_OBJECT (decode_bin, "got the pad for sometimes template %s",
@@ -1701,7 +1485,7 @@
       case GST_PAD_ALWAYS:
       {
         /* get the pad that we need to autoplug */
-        GstPad *pad = gst_element_get_static_pad (element, templ_name);
+        GstPad *pad = gst_element_get_pad (element, templ_name);
 
         if (pad) {
           GST_DEBUG_OBJECT (decode_bin, "got the pad for always template %s",
@@ -1720,7 +1504,7 @@
       {
         /* try to get the pad to see if it is already created or
          * not */
-        GstPad *pad = gst_element_get_static_pad (element, templ_name);
+        GstPad *pad = gst_element_get_pad (element, templ_name);
 
         if (pad) {
           GST_DEBUG_OBJECT (decode_bin, "got the pad for sometimes template %s",
@@ -1821,7 +1605,7 @@
   }
 
   /* autoplug the new pad with the caps that the signal gave us. */
-  pad = gst_element_get_static_pad (typefind, "src");
+  pad = gst_element_get_pad (typefind, "src");
   close_pad_link (typefind, pad, caps, decode_bin, FALSE);
   gst_object_unref (pad);
 
@@ -1887,7 +1671,7 @@
 
   GST_DEBUG_OBJECT (decode_bin, "cleaning up decodebin");
 
-  typefind_pad = gst_element_get_static_pad (decode_bin->typefind, "src");
+  typefind_pad = gst_element_get_pad (decode_bin->typefind, "src");
   if (GST_IS_PAD (typefind_pad)) {
     g_signal_handlers_block_by_func (typefind_pad, (gpointer) unlinked,
         decode_bin);
@@ -2038,7 +1822,6 @@
   GST_DEBUG ("binding text domain %s to locale dir %s", GETTEXT_PACKAGE,
       LOCALEDIR);
   bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
-  bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
 #endif /* ENABLE_NLS */
 
   return gst_element_register (plugin, "decodebin", GST_RANK_NONE,