decodebin: Correctly expose pads from elements that have directly exposable pads
authorSebastian Dröge <sebastian@centricular.com>
Thu, 21 Jan 2016 16:30:40 +0000 (18:30 +0200)
committerSebastian Dröge <sebastian@centricular.com>
Mon, 25 Jan 2016 12:50:26 +0000 (13:50 +0100)
analyze_new_pad() can return a new decode chain, which might have a new
GstDecodePad in the end. We should use those two for expose_pad() and not the
original ones that were passed to analyze_new_pad().

This fails when having a demuxer element that has raw pads immediately or
if a decoder with raw caps is after an adaptive demuxer.

https://bugzilla.gnome.org/show_bug.cgi?id=760949

gst/playback/gstdecodebin2.c

index 9668849..e97cf2a 100644 (file)
@@ -2067,6 +2067,12 @@ demuxer_source_pad_probe (GstPad * pad, GstPadProbeInfo * info,
   return GST_PAD_PROBE_OK;
 }
 
+typedef struct
+{
+  GstDecodeChain *chain;
+  GstPad *pad;
+} PadExposeData;
+
 /* connect_pad:
  *
  * Try to connect the given pad to an element created from one of the factories,
@@ -2124,6 +2130,7 @@ connect_pad (GstDecodeBin * dbin, GstElement * src, GstDecodePad * dpad,
     GParamSpec *pspec;
     gboolean subtitle;
     GList *to_connect = NULL;
+    GList *to_expose = NULL;
     gboolean is_parser_converter = FALSE;
 
     /* Set dpad target to pad again, it might've been unset
@@ -2448,34 +2455,31 @@ connect_pad (GstDecodeBin * dbin, GstElement * src, GstDecodePad * dpad,
     /* link this element further */
     to_connect = connect_element (dbin, delem, chain);
 
-    {
-      GList *l;
-      for (l = to_connect; l;) {
-        GstPad *opad = GST_PAD_CAST (l->data);
-        gboolean to_expose = FALSE;
-        GstCaps *ocaps;
-
-        ocaps = get_pad_caps (opad);
-        to_expose =
-            analyze_new_pad (dbin, delem->element, opad, ocaps, chain, &chain);
-
-        if (ocaps)
-          gst_caps_unref (ocaps);
-
-        if (!to_expose) {
-          GList *l2 = l;
-
-          gst_object_unref (opad);
-
-          l2 = g_list_next (l);
-          to_connect = g_list_delete_link (to_connect, l);
-          l = l2;
-        } else {
-          l = g_list_next (l);
-        }
+    while (to_connect) {
+      GstPad *opad = to_connect->data;
+      gboolean expose_pad = FALSE;
+      GstDecodeChain *new_chain;
+      GstCaps *ocaps;
+
+      ocaps = get_pad_caps (opad);
+      expose_pad =
+          analyze_new_pad (dbin, delem->element, opad, ocaps, chain,
+          &new_chain);
+
+      if (ocaps)
+        gst_caps_unref (ocaps);
+
+      if (expose_pad) {
+        PadExposeData *expose_data = g_new0 (PadExposeData, 1);
+        expose_data->chain = new_chain;
+        expose_data->pad = gst_object_ref (opad);
+        to_expose = g_list_prepend (to_expose, expose_data);
       }
-      /* any pads left in to_connect are to be exposed */
+
+      gst_object_unref (opad);
+      to_connect = g_list_delete_link (to_connect, to_connect);
     }
+    /* any pads left in to_expose are to be exposed */
 
     /* Bring the element to the state of the parent */
 
@@ -2496,9 +2500,12 @@ connect_pad (GstDecodeBin * dbin, GstElement * src, GstDecodePad * dpad,
       GST_WARNING_OBJECT (dbin, "Couldn't set %s to PAUSED",
           GST_ELEMENT_NAME (element));
 
-      g_list_foreach (to_connect, (GFunc) gst_object_unref, NULL);
-      g_list_free (to_connect);
-      to_connect = NULL;
+      while (to_expose) {
+        PadExposeData *expose_data = to_expose->data;
+        gst_object_unref (expose_data->pad);
+        g_free (expose_data);
+        to_expose = g_list_delete_link (to_expose, to_expose);
+      }
 
       remove_error_filter (dbin, element, &error_msg);
 
@@ -2586,22 +2593,20 @@ connect_pad (GstDecodeBin * dbin, GstElement * src, GstDecodePad * dpad,
       SUBTITLE_UNLOCK (dbin);
     }
 
-    {
-      GList *l;
-      for (l = to_connect; l; l = g_list_next (l)) {
-        GstPad *opad = GST_PAD_CAST (l->data);
-        GstCaps *ocaps;
+    while (to_expose) {
+      PadExposeData *expose_data = to_expose->data;
+      GstCaps *ocaps;
 
-        ocaps = get_pad_caps (opad);
-        expose_pad (dbin, delem->element, dpad, opad, ocaps, chain, TRUE);
+      ocaps = get_pad_caps (expose_data->pad);
+      expose_pad (dbin, delem->element, expose_data->chain->current_pad,
+          expose_data->pad, ocaps, expose_data->chain, TRUE);
 
-        if (ocaps)
-          gst_caps_unref (ocaps);
+      if (ocaps)
+        gst_caps_unref (ocaps);
 
-        gst_object_unref (opad);
-      }
-      g_list_free (to_connect);
-      to_connect = NULL;
+      gst_object_unref (expose_data->pad);
+      g_free (expose_data);
+      to_expose = g_list_delete_link (to_expose, to_expose);
     }
 
     res = TRUE;