diff --git a/gst/playback/gstplaybin2.c b/gst/playback/gstplaybin2.c
index 54b9c1d..27d3d96 100644
--- a/gst/playback/gstplaybin2.c
+++ b/gst/playback/gstplaybin2.c
@@ -309,6 +309,7 @@ struct _GstSourceGroup
   gulong autoplug_factories_id;
   gulong autoplug_select_id;
   gulong autoplug_continue_id;
+  gulong autoplug_sort_id;
 
   gulong sub_pad_added_id;
   gulong sub_pad_removed_id;
@@ -2876,6 +2877,154 @@ drained_cb (GstElement * decodebin, GstSourceGroup * group)
   setup_next_source (playbin, GST_STATE_PAUSED);
 }
 
+static gint
+_factory_cmp_func (const gpointer a, const gpointer b, GstCaps * sinkcaps)
+{
+  GstElementFactory *factory;
+  gboolean subset_a, subset_b, intersect_a, intersect_b;
+  guint rank_a, rank_b;
+
+  factory = g_value_get_object (a);
+  subset_a = FALSE;
+  intersect_a = gst_element_factory_can_src_caps (factory, sinkcaps);
+  if (intersect_a) {
+    const GList *l;
+    GstPadTemplate *template;
+    GstCaps *caps;
+
+    l = gst_element_factory_get_static_pad_templates (factory);
+    for (; l; l = l->next) {
+      template = gst_static_pad_template_get (l->data);
+      if (GST_PAD_TEMPLATE_DIRECTION (template) != GST_PAD_SRC ||
+          GST_PAD_TEMPLATE_PRESENCE (template) == GST_PAD_REQUEST)
+        continue;
+      caps = gst_pad_template_get_caps (template);
+      subset_a |= gst_caps_is_subset (caps, sinkcaps);
+      if (subset_a)
+        break;
+    }
+  }
+  rank_a = gst_plugin_feature_get_rank (GST_PLUGIN_FEATURE (factory));
+
+  factory = g_value_get_object (b);
+  subset_b = FALSE;
+  intersect_b = gst_element_factory_can_src_caps (factory, sinkcaps);
+  if (intersect_b) {
+    const GList *l;
+    GstPadTemplate *template;
+    GstCaps *caps;
+
+    l = gst_element_factory_get_static_pad_templates (factory);
+    for (; l; l = l->next) {
+      template = gst_static_pad_template_get (l->data);
+      if (GST_PAD_TEMPLATE_DIRECTION (template) != GST_PAD_SRC ||
+          GST_PAD_TEMPLATE_PRESENCE (template) == GST_PAD_REQUEST)
+        continue;
+      caps = gst_pad_template_get_caps (template);
+      subset_b |= gst_caps_is_subset (caps, sinkcaps);
+      if (subset_b)
+        break;
+    }
+  }
+  rank_b = gst_plugin_feature_get_rank (GST_PLUGIN_FEATURE (factory));
+
+  if (intersect_a != intersect_b)
+    return (intersect_a) ? -1 : 1;
+  else if (subset_a != subset_b)
+    return (subset_a) ? -1 : 1;
+  else
+    return (gint) rank_b - (gint) rank_a;
+}
+
+static GstCaps *
+_replace_default_caps (GstCaps * caps, GstElement * sink, const gchar * prefix)
+{
+  GstPad *sinkpad;
+  GstCaps *sinkcaps;
+  gint i;
+  GstStructure *st;
+
+  if (!prefix || g_str_equal (prefix, "") || !sink)
+    return caps;
+
+  sinkpad = gst_element_get_static_pad (sink, "sink");
+  if (!sinkpad)
+    return caps;
+
+  sinkcaps = gst_pad_get_caps (sinkpad);
+  gst_object_unref (sinkpad);
+  if (!sinkcaps)
+    return caps;
+  if (gst_caps_is_any (sinkcaps)) {
+    gst_caps_unref (sinkcaps);
+    return caps;
+  }
+
+  caps = gst_caps_make_writable (caps);
+  for (i = gst_caps_get_size (caps); i > 0; i--) {
+    st = gst_caps_get_structure (caps, i - 1);
+    if (g_str_has_prefix (gst_structure_get_name (st), prefix))
+      gst_caps_remove_structure (caps, i - 1);
+  }
+  gst_caps_merge (caps, sinkcaps);
+
+  return caps;
+}
+
+static GstCaps *
+_get_favored_sinkcaps (GstPlayBin * playbin, GstSourceGroup * group)
+{
+  GstCaps *caps;
+
+  GST_SOURCE_GROUP_LOCK (group);
+  g_object_get (group->uridecodebin, "caps", &caps, NULL);
+  GST_SOURCE_GROUP_UNLOCK (group);
+
+  if (playbin->text_sink)
+    caps = _replace_default_caps (caps, playbin->text_sink, "text/");
+
+  if (playbin->audio_sink)
+    caps = _replace_default_caps (caps, playbin->audio_sink, "audio/");
+
+  if (playbin->video_sink)
+    caps = _replace_default_caps (caps, playbin->video_sink, "video/");
+
+  GST_DEBUG_OBJECT (playbin,
+      "merged caps from the sink caps of all the sinks: %" GST_PTR_FORMAT,
+      caps);
+  return caps;
+}
+
+/* called after autoplug_factories() so that we can sort the listed factories
+ * in our own order.  must return the copied (and re-ordered) factories arg. */
+static GValueArray *
+autoplug_sort_cb (GstElement * element, GstPad * pad,
+    GstCaps * caps, GValueArray * factories, GstSourceGroup * group)
+{
+  GstPlayBin *playbin;
+  GstCaps *sinkcaps;
+  GValueArray *result;
+  guint i;
+
+  playbin = group->playbin;
+
+  GST_DEBUG_OBJECT (playbin, "sort group %p for %s:%s, %" GST_PTR_FORMAT,
+      group, GST_DEBUG_PAD_NAME (pad), caps);
+
+  GST_PLAY_BIN_LOCK (playbin);
+  sinkcaps = _get_favored_sinkcaps (playbin, group);
+  GST_PLAY_BIN_UNLOCK (playbin);
+
+  result = g_value_array_sort_with_data (g_value_array_copy (factories),
+      (GCompareDataFunc) _factory_cmp_func, sinkcaps);
+  gst_caps_unref (sinkcaps);
+  for (i = result->n_values; i > 0; i--)
+    GST_LOG_OBJECT (playbin, "result.. factory: %s",
+        gst_plugin_feature_get_name (g_value_get_object
+            (g_value_array_get_nth (result, i - 1))));
+  return result;
+}
+
 /* Called when we must provide a list of factories to plug to @pad with @caps.
  * We first check if we have a sink that can handle the format and if we do, we
  * return NULL, to expose the pad. If we have no sink (or the sink does not
@@ -3254,6 +3403,9 @@ activate_group (GstPlayBin * playbin, GstSourceGroup * group, GstState target)
   group->autoplug_continue_id =
       g_signal_connect (uridecodebin, "autoplug-continue",
       G_CALLBACK (autoplug_continue_cb), group);
+  group->autoplug_sort_id =
+      g_signal_connect (uridecodebin, "autoplug-sort",
+      G_CALLBACK (autoplug_sort_cb), group);
 
   if (group->suburi) {
     /* subtitles */
@@ -3425,6 +3577,7 @@ deactivate_group (GstPlayBin * playbin, GstSourceGroup * group)
     REMOVE_SIGNAL (group->uridecodebin, group->autoplug_factories_id);
     REMOVE_SIGNAL (group->uridecodebin, group->autoplug_select_id);
     REMOVE_SIGNAL (group->uridecodebin, group->autoplug_continue_id);
+    REMOVE_SIGNAL (group->uridecodebin, group->autoplug_sort_id);
     gst_bin_remove (GST_BIN_CAST (playbin), group->uridecodebin);
   }
 
diff --git a/gst/playback/gsturidecodebin.c b/gst/playback/gsturidecodebin.c
index d36fff9..380cd7c 100644
--- a/gst/playback/gsturidecodebin.c
+++ b/gst/playback/gsturidecodebin.c
@@ -119,6 +119,9 @@ struct _GstURIDecodeBinClass
   /* signal fired to get a list of factories to try to autoplug */
   GValueArray *(*autoplug_factories) (GstElement * element, GstPad * pad,
       GstCaps * caps);
+  /* signal fired to sort the factories */
+  GValueArray *(*autoplug_sort) (GstElement * element, GstPad * pad,
+      GstCaps * caps, GValueArray * factories);
   /* signal fired to select from the proposed list of factories */
     GstAutoplugSelectResult (*autoplug_select) (GstElement * element,
       GstPad * pad, GstCaps * caps, GValueArray * factories);
@@ -145,6 +148,7 @@ enum
   SIGNAL_AUTOPLUG_FACTORIES,
   SIGNAL_AUTOPLUG_SELECT,
   SIGNAL_DRAINED,
+  SIGNAL_AUTOPLUG_SORT,
   LAST_SIGNAL
 };
 
@@ -251,6 +255,22 @@ _gst_select_accumulator (GSignalInvocationHint * ihint,
 }
 
 static gboolean
+_gst_array_hasvalue_accumulator (GSignalInvocationHint * ihint,
+    GValue * return_accu, const GValue * handler_return, gpointer dummy)
+{
+  gpointer array;
+
+  array = g_value_get_boxed (handler_return);
+  if (!(ihint->run_type & G_SIGNAL_RUN_CLEANUP))
+    g_value_set_boxed (return_accu, array);
+
+  if (array != NULL)
+    return FALSE;
+
+  return TRUE;
+}
+
+static gboolean
 gst_uri_decode_bin_autoplug_continue (GstElement * element, GstPad * pad,
     GstCaps * caps)
 {
@@ -309,6 +329,19 @@ gst_uri_decode_bin_autoplug_factories (GstElement * element, GstPad * pad,
   return result;
 }
 
+static GValueArray *
+gst_uri_decode_bin_autoplug_sort (GstElement * element, GstPad * pad,
+    GstCaps * caps, GValueArray * factories)
+{
+  GValueArray *result;
+
+  result = g_value_array_copy (factories);
+
+  GST_DEBUG_OBJECT (element, "autoplug-sort returns %p", result);
+
+  /* return input */
+  return result;
+}
 
 static void
 gst_uri_decode_bin_class_init (GstURIDecodeBinClass * klass)
@@ -485,6 +518,29 @@ gst_uri_decode_bin_class_init (GstURIDecodeBinClass * klass)
       GST_TYPE_PAD, GST_TYPE_CAPS);
 
   /**
+   * GstURIDecodeBin::autoplug-sort:
+   * @bin: The decodebin
+   * @pad: The #GstPad.
+   * @caps: The #GstCaps.
+   * @factories: A #GValueArray of possible #GstElementFactory to use.
+   *
+   * Once decodebin2 has found the possible #GstElementFactory objects to try
+   * for @caps on @pad, this signal is emited. The purpose of the signal is for
+   * the application to perform additional sorting or filtering on the element
+   * factory array.
+   *
+   * The callee should copy and modify @factories.
+   *
+   * Returns: A new sorted array of #GstElementFactory objects.
+   */
+  gst_uri_decode_bin_signals[SIGNAL_AUTOPLUG_SORT] =
+      g_signal_new ("autoplug-sort", G_TYPE_FROM_CLASS (klass),
+      G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstURIDecodeBinClass, autoplug_sort),
+      _gst_array_hasvalue_accumulator, NULL,
+      gst_play_marshal_BOXED__OBJECT_BOXED_BOXED, G_TYPE_VALUE_ARRAY, 3,
+      GST_TYPE_PAD, GST_TYPE_CAPS, G_TYPE_VALUE_ARRAY);
+
+  /**
    * GstURIDecodeBin::autoplug-select:
    * @pad: The #GstPad.
    * @caps: The #GstCaps.
@@ -539,6 +595,7 @@ gst_uri_decode_bin_class_init (GstURIDecodeBinClass * klass)
       GST_DEBUG_FUNCPTR (gst_uri_decode_bin_autoplug_continue);
   klass->autoplug_factories =
       GST_DEBUG_FUNCPTR (gst_uri_decode_bin_autoplug_factories);
+  klass->autoplug_sort = GST_DEBUG_FUNCPTR (gst_uri_decode_bin_autoplug_sort);
 }
 
 static void
@@ -1369,6 +1426,21 @@ proxy_autoplug_factories_signal (GstElement * element, GstPad * pad,
   return result;
 }
 
+static GValueArray *
+proxy_autoplug_sort_signal (GstElement * element, GstPad * pad,
+    GstCaps * caps, GValueArray * factories, GstURIDecodeBin * dec)
+{
+  GValueArray *result;
+
+  g_signal_emit (dec,
+      gst_uri_decode_bin_signals[SIGNAL_AUTOPLUG_SORT], 0, pad, caps,
+      factories, &result);
+
+  GST_DEBUG_OBJECT (dec, "autoplug-sort returned %p", result);
+
+  return result;
+}
+
 static GstAutoplugSelectResult
 proxy_autoplug_select_signal (GstElement * element, GstPad * pad,
     GstCaps * caps, GstElementFactory * factory, GstURIDecodeBin * dec)
@@ -1420,6 +1492,8 @@ make_decoder (GstURIDecodeBin * decoder)
         G_CALLBACK (proxy_autoplug_continue_signal), decoder);
     g_signal_connect (decodebin, "autoplug-factories",
         G_CALLBACK (proxy_autoplug_factories_signal), decoder);
+    g_signal_connect (decodebin, "autoplug-sort",
+        G_CALLBACK (proxy_autoplug_sort_signal), decoder);
     g_signal_connect (decodebin, "autoplug-select",
         G_CALLBACK (proxy_autoplug_select_signal), decoder);
     g_signal_connect (decodebin, "drained",
