? gstdecodebin.c.diff
Index: gstdecodebin.c
===================================================================
RCS file: /cvs/gstreamer/gst-plugins-base/gst/playback/gstdecodebin.c,v
retrieving revision 1.75
diff -u -3 -p -b -B -d -r1.75 gstdecodebin.c
--- gstdecodebin.c	23 Jun 2006 16:45:50 -0000	1.75
+++ gstdecodebin.c	5 Jul 2006 06:32:01 -0000
@@ -67,6 +67,7 @@ struct _GstDecodeBin
   GList *factories;             /* factories we can use for selecting elements */
   gint numpads;
   gint numwaiting;
+  guint numwaiting_any;
 
   guint have_type_id;           /* signal id for the typefind element */
 
@@ -136,8 +137,7 @@ static void type_found (GstElement * typ
 static GstElement *try_to_link_1 (GstDecodeBin * decode_bin,
     GstElement * origelement, GstPad * pad, GList * factories);
 static void close_link (GstElement * element, GstDecodeBin * decode_bin);
-static void close_pad_link (GstElement * element, GstPad * pad,
-    GstCaps * caps, GstDecodeBin * decode_bin, gboolean more);
+static void close_pad_link (GstPad * pad, GstDecodeBin * decode_bin);
 static void unlinked (GstPad * pad, GstPad * peerpad,
     GstDecodeBin * decode_bin);
 static void new_pad (GstElement * element, GstPad * pad, GstDynamic * dynamic);
@@ -235,7 +235,7 @@ gst_decode_bin_class_init (GstDecodeBinC
 static gboolean
 gst_decode_bin_is_dynamic (GstDecodeBin * decode_bin)
 {
-  return decode_bin->dynamics != NULL;
+  return (decode_bin->dynamics != NULL) || (decode_bin->numwaiting_any > 0);
 }
 
 /* the filter function for selecting the elements we can use in
@@ -590,6 +590,18 @@ pad_probe (GstPad * pad, GstMiniObject *
   return TRUE;
 }
 
+static void
+on_have_type (GstElement * element, guint probability,
+    const GstCaps * caps, GstDecodeBin * decode_bin)
+{
+  GST_DEBUG_OBJECT (decode_bin, "Caps are now known.");
+  close_pad_link (gst_element_get_pad (element, "src"), decode_bin);
+  g_signal_handlers_disconnect_matched (element,
+      G_SIGNAL_MATCH_DATA | G_SIGNAL_MATCH_FUNC, 0, 0, NULL,
+      on_have_type, decode_bin);
+  decode_bin->numwaiting_any--;
+}
+
 /* given a pad and a caps from an element, find the list of elements
  * that could connect to the pad
  *
@@ -600,31 +612,44 @@ pad_probe (GstPad * pad, GstMiniObject *
  * the unknown_type signal.
  */
 static void
-close_pad_link (GstElement * element, GstPad * pad, GstCaps * caps,
-    GstDecodeBin * decode_bin, gboolean more)
+close_pad_link (GstPad * pad, GstDecodeBin * decode_bin)
 {
+  GstElement *element = GST_PAD_PARENT (pad);
   GstStructure *structure;
   const gchar *mimetype;
   gchar *padname;
   gint diff;
+  GstCaps *caps;
 
+  /* hack.. ignore current pads */
   padname = gst_pad_get_name (pad);
   diff = strncmp (padname, "current_", 8);
   g_free (padname);
-
-  /* hack.. ignore current pads */
   if (!diff)
     return;
 
-  /* the caps is empty, this means the pad has no type, we can only
-   * decide to fire the unknown_type signal. */
-  if (caps == NULL || gst_caps_is_empty (caps))
-    goto unknown_type;
+  /* If caps is NULL, empty or any, we need to let typefind figure out
+   * more specific caps. */
+  caps = gst_pad_get_caps (pad);
+  if (caps == NULL || gst_caps_is_empty (caps) || gst_caps_is_any (caps)) {
+    GList *to_try;
+    GstElement *e;
 
-  /* the caps is any, this means the pad can be anything and
-   * we don't know yet */
-  if (gst_caps_is_any (caps))
-    goto dont_know_yet;
+    if (caps)
+      gst_caps_unref (caps);
+    if (!strcmp ("GstTypeFindElement", G_OBJECT_TYPE_NAME (element)))
+      return;
+    GST_LOG_OBJECT (decode_bin, "Type is not known yet.");
+    to_try = g_list_append (NULL, gst_element_factory_find ("typefind"));
+    e = try_to_link_1 (decode_bin, element, pad, to_try);
+    g_list_free (to_try);
+    if (e) {
+      g_signal_connect (e, "have_type", G_CALLBACK (on_have_type), decode_bin);
+      decode_bin->numwaiting_any++;
+    } else
+      GST_LOG_OBJECT (decode_bin, "Could not create typefind element.");
+    return;
+  }
 
   GST_LOG_OBJECT (element, "trying to close %" GST_PTR_FORMAT, caps);
 
@@ -664,7 +689,8 @@ close_pad_link (GstElement * element, Gs
     /* our own signal with an extra flag that this is the only pad */
     GST_DEBUG_OBJECT (decode_bin, "emitting new-decoded-pad");
     g_signal_emit (G_OBJECT (decode_bin),
-        gst_decode_bin_signals[SIGNAL_NEW_DECODED_PAD], 0, ghost, !more);
+        gst_decode_bin_signals[SIGNAL_NEW_DECODED_PAD], 0, ghost,
+        !gst_decode_bin_is_dynamic (decode_bin));
     GST_DEBUG_OBJECT (decode_bin, "emitted new-decoded-pad");
 
     g_free (padname);
@@ -685,6 +711,7 @@ close_pad_link (GstElement * element, Gs
     /* can free the list again now */
     g_list_free (to_try);
   }
+  gst_caps_unref (caps);
   return;
 
 unknown_type:
@@ -692,16 +719,13 @@ unknown_type:
     GST_LOG_OBJECT (pad, "unkown type found, fire signal");
     g_signal_emit (G_OBJECT (decode_bin),
         gst_decode_bin_signals[SIGNAL_UNKNOWN_TYPE], 0, pad, caps);
-    return;
-  }
-dont_know_yet:
-  {
-    GST_LOG_OBJECT (pad, "type is not known yet, waiting to close link");
+    gst_caps_unref (caps);
     return;
   }
 many_types:
   {
     GST_LOG_OBJECT (pad, "many possible types, waiting to close link");
+    gst_caps_unref (caps);
     return;
   }
 }
@@ -1141,8 +1165,6 @@ static void
 new_pad (GstElement * element, GstPad * pad, GstDynamic * dynamic)
 {
   GstDecodeBin *decode_bin = dynamic->decode_bin;
-  GstCaps *caps;
-  gboolean more;
 
   GST_OBJECT_LOCK (decode_bin);
   if (decode_bin->shutting_down)
@@ -1153,13 +1175,7 @@ new_pad (GstElement * element, GstPad * 
   if (decode_bin->shutting_down)
     goto shutting_down2;
 
-  /* see if any more pending dynamic connections exist */
-  more = gst_decode_bin_is_dynamic (decode_bin);
-
-  caps = gst_pad_get_caps (pad);
-  close_pad_link (element, pad, caps, decode_bin, more);
-  if (caps)
-    gst_caps_unref (caps);
+  close_pad_link (pad, decode_bin);
   GST_STATE_UNLOCK (decode_bin);
 
   return;
@@ -1267,7 +1283,6 @@ close_link (GstElement * element, GstDec
   GList *pads;
   gboolean dynamic = FALSE;
   GList *to_connect = NULL;
-  gboolean more;
 
   GST_DEBUG_OBJECT (decode_bin, "closing links with element %s",
       GST_ELEMENT_NAME (element));
@@ -1343,30 +1358,14 @@ close_link (GstElement * element, GstDec
     decode_bin->dynamics = g_list_prepend (decode_bin->dynamics, dyn);
   }
 
-  /* Check if this is an element with more than 1 pad. If this element
-   * has more than 1 pad, we need to be carefull not to signal the 
-   * no_more_pads signal after connecting the first pad. */
-  more = g_list_length (to_connect) > 1;
-
   /* now loop over all the pads we need to connect */
   for (pads = to_connect; pads; pads = g_list_next (pads)) {
     GstPad *pad = GST_PAD_CAST (pads->data);
-    GstCaps *caps;
-
-    /* we have more pads if we have more than 1 pad to connect or
-     * dynamics. If we have only 1 pad and no dynamics, more will be
-     * set to FALSE and the no-more-pads signal will be fired. Note
-     * that this can change after the close_pad_link call. */
-    more |= gst_decode_bin_is_dynamic (decode_bin);
 
     GST_DEBUG_OBJECT (decode_bin, "closing pad link for %s",
         GST_OBJECT_NAME (pad));
 
-    /* continue autoplugging on the pads */
-    caps = gst_pad_get_caps (pad);
-    close_pad_link (element, pad, caps, decode_bin, more);
-    if (caps)
-      gst_caps_unref (caps);
+    close_pad_link (pad, decode_bin);
 
     gst_object_unref (pad);
   }
@@ -1390,7 +1389,8 @@ type_found (GstElement * typefind, guint
 
   /* autoplug the new pad with the caps that the signal gave us. */
   pad = gst_element_get_pad (typefind, "src");
-  close_pad_link (typefind, pad, caps, decode_bin, FALSE);
+  gst_pad_set_caps (pad, caps);
+  close_pad_link (pad, decode_bin);
   gst_object_unref (pad);
 
   dynamic = gst_decode_bin_is_dynamic (decode_bin);
