Index: docs/libs/gstreamer-libs-sections.txt
===================================================================
RCS file: /cvs/gstreamer/gstreamer/docs/libs/gstreamer-libs-sections.txt,v
retrieving revision 1.85
diff -u -B -b -p -r1.85 gstreamer-libs-sections.txt
--- docs/libs/gstreamer-libs-sections.txt	22 Oct 2008 14:47:03 -0000	1.85
+++ docs/libs/gstreamer-libs-sections.txt	9 Jan 2009 17:53:47 -0000
@@ -514,6 +514,7 @@ gst_push_src_get_type
 <INCLUDE>gst/base/gsttypefindhelper.h</INCLUDE>
 gst_type_find_helper
 gst_type_find_helper_for_buffer
+gst_type_find_helper_for_extension
 GstTypeFindHelperGetRangeFunction
 gst_type_find_helper_get_range
 <SUBSECTION Private>
Index: gst/gsttypefind.c
===================================================================
RCS file: /cvs/gstreamer/gstreamer/gst/gsttypefind.c,v
retrieving revision 1.64
diff -u -B -b -p -r1.64 gsttypefind.c
--- gst/gsttypefind.c	31 Oct 2008 14:24:49 -0000	1.64
+++ gst/gsttypefind.c	9 Jan 2009 17:53:47 -0000
@@ -78,7 +78,6 @@ gst_type_find_register (GstPlugin * plug
   GstTypeFindFactory *factory;
 
   g_return_val_if_fail (name != NULL, FALSE);
-  g_return_val_if_fail (func != NULL, FALSE);
 
   GST_INFO ("registering typefind function for %s", name);
 
Index: gst/gsttypefindfactory.c
===================================================================
RCS file: /cvs/gstreamer/gstreamer/gst/gsttypefindfactory.c,v
retrieving revision 1.16
diff -u -B -b -p -r1.16 gsttypefindfactory.c
--- gst/gsttypefindfactory.c	12 Dec 2007 23:19:59 -0000	1.16
+++ gst/gsttypefindfactory.c	9 Jan 2009 17:53:47 -0000
@@ -238,8 +238,7 @@ gst_type_find_factory_call_function (Gst
       GST_TYPE_FIND_FACTORY (gst_plugin_feature_load (GST_PLUGIN_FEATURE
           (factory)));
   if (new_factory) {
-    g_assert (new_factory->function != NULL);
-
+    if (new_factory->function)
     new_factory->function (find, new_factory->user_data);
     gst_object_unref (new_factory);
   }
Index: libs/gst/base/gsttypefindhelper.c
===================================================================
RCS file: /cvs/gstreamer/gstreamer/libs/gst/base/gsttypefindhelper.c,v
retrieving revision 1.24
diff -u -B -b -p -r1.24 gsttypefindhelper.c
--- libs/gst/base/gsttypefindhelper.c	10 Oct 2008 15:12:11 -0000	1.24
+++ libs/gst/base/gsttypefindhelper.c	9 Jan 2009 17:53:48 -0000
@@ -146,8 +146,7 @@ helper_find_peek (gpointer data, gint64 
   caps = GST_BUFFER_CAPS (buffer);
 
   if (caps && !gst_caps_is_empty (caps) && !gst_caps_is_any (caps)) {
-    GST_DEBUG ("buffer has caps %" GST_PTR_FORMAT ", suggest max probability",
-        caps);
+    GST_DEBUG ("buffer has caps %"GST_PTR_FORMAT", suggest max probability", caps);
 
     gst_caps_replace (&helper->caps, caps);
     helper->best_probability = GST_TYPE_FIND_MAXIMUM;
@@ -476,3 +475,68 @@ gst_type_find_helper_for_buffer (GstObje
 
   return result;
 }
+
+/**
+ * gst_type_find_helper_for_extension:
+ * @obj: object doing the typefinding, or NULL (used for logging)
+ * @extension: an extension
+ *
+ * Tries to find the best #GstCaps associated with @extension.
+ *
+ * All available typefinders will be checked against the extension in order
+ * of rank. The caps of the first typefinder that can handle @extension will be
+ * returned.
+ *
+ * Returns: The #GstCaps corresponding to @extension, or #NULL if no type could
+ * be found. The caller should free the caps returned with gst_caps_unref().
+ * 
+ * Since: 0.10.23
+ */
+GstCaps *
+gst_type_find_helper_for_extension (GstObject * obj, const gchar * extension)
+{
+  GList *l, *type_list;
+  GstCaps *result = NULL;
+
+  g_return_val_if_fail (extension != NULL, NULL);
+
+  GST_LOG_OBJECT (obj, "finding caps for extension %s", extension);
+
+  type_list = gst_type_find_factory_get_list ();
+  type_list = g_list_sort (type_list, type_find_factory_rank_cmp);
+
+  for (l = type_list; l; l = g_list_next (l)) {
+    GstTypeFindFactory *factory;
+    gchar **ext;
+    gint i;
+
+    factory = GST_TYPE_FIND_FACTORY (l->data);
+
+    /* get the extension that this typefind factory can handle */
+    ext = gst_type_find_factory_get_extensions (factory);
+    if (ext == NULL)
+      continue;
+
+    /* we only want to check those factories without a function */
+    if (factory->function != NULL)
+      continue;
+    
+    /* there are extension, see if one of them matches the requested
+     * extension */
+    for (i = 0; ext[i]; i++) {
+      if (strcmp (ext[i], extension) == 0) {
+	/* we found a matching extension, take the caps */
+	if ((result = gst_type_find_factory_get_caps (factory))) {
+          gst_caps_ref (result);
+	  goto done;
+	}
+      }
+    }
+  }
+done:
+  gst_plugin_feature_list_free (type_list);
+
+  GST_LOG_OBJECT (obj, "Returning %" GST_PTR_FORMAT, result);
+
+  return result;
+}
Index: libs/gst/base/gsttypefindhelper.h
===================================================================
RCS file: /cvs/gstreamer/gstreamer/libs/gst/base/gsttypefindhelper.h,v
retrieving revision 1.4
diff -u -B -b -p -r1.4 gsttypefindhelper.h
--- libs/gst/base/gsttypefindhelper.h	2 Mar 2006 13:45:32 -0000	1.4
+++ libs/gst/base/gsttypefindhelper.h	9 Jan 2009 17:53:48 -0000
@@ -34,6 +34,9 @@ GstCaps * gst_type_find_helper_for_buffe
                                            GstBuffer              *buf,
                                            GstTypeFindProbability *prob);
 
+GstCaps * gst_type_find_helper_for_extension (GstObject * obj,
+                                              const gchar * extension);
+
 /**
  * GstTypeFindHelperGetRangeFunction:
  * @obj: a #GstObject that will handle the getrange request
Index: plugins/elements/gsttypefindelement.c
===================================================================
RCS file: /cvs/gstreamer/gstreamer/plugins/elements/gsttypefindelement.c,v
retrieving revision 1.94
diff -u -B -b -p -r1.94 gsttypefindelement.c
--- plugins/elements/gsttypefindelement.c	31 Oct 2008 08:53:27 -0000	1.94
+++ plugins/elements/gsttypefindelement.c	9 Jan 2009 17:53:48 -0000
@@ -606,6 +606,71 @@ gst_type_find_element_setcaps (GstPad * 
   return TRUE;
 }
 
+static GstCaps *
+gst_type_find_guess_by_extension (GstTypeFindElement *typefind, GstPad *pad,
+    GstTypeFindProbability *probability)
+{
+  GstQuery *query;
+  gchar *uri;
+  size_t len;
+  gint find;
+  GstCaps *caps;
+
+  query = gst_query_new_uri ();
+
+  /* try getting the caps with an uri query and from the extension */
+  if (!gst_pad_peer_query (pad, query))
+    goto peer_query_failed;
+
+  gst_query_parse_uri (query, &uri);
+  if (uri == NULL)
+    goto no_uri;
+
+  GST_DEBUG_OBJECT (typefind, "finding extension of %s", uri);
+
+  /* find the extension on the uri, this is everything after a '.' */
+  len = strlen (uri);
+  find = len - 1;
+
+  while (find >= 0) {
+    if (uri[find] == '.')
+      break;
+    find--;
+  }
+  if (find < 0) 
+    goto no_extension;
+
+  GST_DEBUG_OBJECT (typefind, "found extension %s", &uri[find+1]);
+
+  caps = gst_type_find_helper_for_extension (GST_OBJECT_CAST (typefind), &uri[find+1]);
+  if (caps)
+    *probability = GST_TYPE_FIND_MAXIMUM;
+
+  gst_query_unref (query);
+
+  return caps;
+
+  /* ERRORS */
+peer_query_failed:
+  {
+    GST_WARNING_OBJECT (typefind, "failed to query peer uri");
+    gst_query_unref (query);
+    return NULL;
+  }
+no_uri:
+  {
+    GST_WARNING_OBJECT (typefind, "could not parse the peer uri");
+    gst_query_unref (query);
+    return NULL;
+  }
+no_extension:
+  {
+    GST_WARNING_OBJECT (typefind, "could not find uri extension in %s", uri);
+    gst_query_unref (query);
+    return NULL;
+  }
+}
+
 static GstFlowReturn
 gst_type_find_element_chain (GstPad * pad, GstBuffer * buffer)
 {
@@ -752,9 +817,11 @@ gst_type_find_element_activate (GstPad *
      2. try to pull type find.
      3. deactivate pull mode.
      4. src pad might have been activated push by the state change. deactivate.
-     5. if we didn't find any caps, fail.
-     6. emit have-type; maybe the app connected the source pad to something.
-     7. if the sink pad is activated, we are in pull mode. succeed.
+     5. if we didn't find any caps, try getting the uri extension by doing an uri
+        query.
+     6. if we didn't find any caps, fail.
+     7. emit have-type; maybe the app connected the source pad to something.
+     8. if the sink pad is activated, we are in pull mode. succeed.
      otherwise activate both pads in push mode and succeed.
    */
 
@@ -804,6 +871,11 @@ gst_type_find_element_activate (GstPad *
 
   /* 5 */
   if (!found_caps || probability < typefind->min_probability) {
+    found_caps = gst_type_find_guess_by_extension (typefind, pad, &probability);
+  }
+
+  /* 6 */
+  if (!found_caps || probability < typefind->min_probability) {
     GST_ELEMENT_ERROR (typefind, STREAM, TYPE_NOT_FOUND, (NULL), (NULL));
     gst_caps_replace (&found_caps, NULL);
     return FALSE;
@@ -809,14 +881,15 @@ gst_type_find_element_activate (GstPad *
     return FALSE;
   }
 
+
 done:
-  /* 6 */
+  /* 7 */
   g_signal_emit (typefind, gst_type_find_element_signals[HAVE_TYPE],
       0, probability, found_caps);
   gst_caps_unref (found_caps);
   typefind->mode = MODE_NORMAL;
 
-  /* 7 */
+  /* 8 */
   if (gst_pad_is_active (pad))
     return TRUE;
   else {
