gst/playback/Makefile.am: Group decodebin2 and uridecodebin into the same plugin...
authorWim Taymans <wim.taymans@gmail.com>
Wed, 5 Dec 2007 17:11:48 +0000 (17:11 +0000)
committerWim Taymans <wim.taymans@gmail.com>
Wed, 5 Dec 2007 17:11:48 +0000 (17:11 +0000)
Original commit message from CVS:
* gst/playback/Makefile.am:
Group decodebin2 and uridecodebin into the same plugin so that they
can share the GEnumType.
* gst/playback/gstdecodebin2.c: (_gst_array_accumulator),
(_gst_select_accumulator), (gst_decode_bin_class_init),
(gst_decode_bin_init), (gst_decode_bin_autoplug_sort),
(gst_decode_bin_autoplug_select), (gst_decode_bin_autoplug_add),
(analyze_new_pad), (connect_pad), (gst_decode_bin_plugin_init):
Add signal to sort factories instead of the more awkward autoplug-select
signal.
Modify autoplug_select so that we can try, skip or expose the
autopluggin of an element on a pad.
* gst/playback/gstfactorylists.c: (compare_ranks),
(decoders_filter), (sinks_filter), (gst_factory_list_is_type),
(element_filter), (gst_factory_list_get_elements),
(gst_factory_list_debug), (gst_factory_list_filter):
* gst/playback/gstfactorylists.h:
Simplify the API, allow getting elements based on mask.
* gst/playback/gstplay-marshal.list:
Add some more marshallers.
* gst/playback/gstplaybin2.c: (init_group), (gst_play_bin_init),
(gst_play_bin_finalize), (pad_removed_cb), (autoplug_factories_cb),
(autoplug_select_cb), (activate_group):
Add support for managing non-raw sinks by providing a custom element and
sink list to decodebin2.
Try to plug non-raw sinks when decodebin2 using autoplug-select of
decodebin2.
* gst/playback/gstplaysink.c: (gen_video_chain), (gen_audio_chain),
(gst_play_sink_set_mode), (gst_play_sink_request_pad):
* gst/playback/gstplaysink.h:
Add support for raw and non-raw sinks.
Add support to force sinks selected by playbin2.
Don't plug raw converters for non-raw sinks.
* gst/playback/gsturidecodebin.c: (_gst_array_accumulator),
(_gst_select_accumulator), (gst_uri_decode_bin_class_init),
(proxy_autoplug_select_signal), (gst_uri_decode_bin_plugin_init),
(plugin_init):
Use right accumulators.
Proxy new signal.

ChangeLog
gst/playback/Makefile.am
gst/playback/gstdecodebin2.c
gst/playback/gstfactorylists.c
gst/playback/gstfactorylists.h
gst/playback/gstplay-marshal.list
gst/playback/gstplaybin2.c
gst/playback/gstplaysink.c
gst/playback/gstplaysink.h
gst/playback/gsturidecodebin.c

index 49676b3..1f181cc 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,51 @@
+2007-12-05  Wim Taymans  <wim.taymans@gmail.com>
+
+       * gst/playback/Makefile.am:
+       Group decodebin2 and uridecodebin into the same plugin so that they
+       can share the GEnumType.
+
+       * gst/playback/gstdecodebin2.c: (_gst_array_accumulator),
+       (_gst_select_accumulator), (gst_decode_bin_class_init),
+       (gst_decode_bin_init), (gst_decode_bin_autoplug_sort),
+       (gst_decode_bin_autoplug_select), (gst_decode_bin_autoplug_add),
+       (analyze_new_pad), (connect_pad), (gst_decode_bin_plugin_init):
+       Add signal to sort factories instead of the more awkward autoplug-select
+       signal.
+       Modify autoplug_select so that we can try, skip or expose the
+       autopluggin of an element on a pad.
+
+       * gst/playback/gstfactorylists.c: (compare_ranks),
+       (decoders_filter), (sinks_filter), (gst_factory_list_is_type),
+       (element_filter), (gst_factory_list_get_elements),
+       (gst_factory_list_debug), (gst_factory_list_filter):
+       * gst/playback/gstfactorylists.h:
+       Simplify the API, allow getting elements based on mask.
+
+       * gst/playback/gstplay-marshal.list:
+       Add some more marshallers.
+
+       * gst/playback/gstplaybin2.c: (init_group), (gst_play_bin_init),
+       (gst_play_bin_finalize), (pad_removed_cb), (autoplug_factories_cb),
+       (autoplug_select_cb), (activate_group):
+       Add support for managing non-raw sinks by providing a custom element and
+       sink list to decodebin2.
+       Try to plug non-raw sinks when decodebin2 using autoplug-select of
+       decodebin2.
+
+       * gst/playback/gstplaysink.c: (gen_video_chain), (gen_audio_chain),
+       (gst_play_sink_set_mode), (gst_play_sink_request_pad):
+       * gst/playback/gstplaysink.h:
+       Add support for raw and non-raw sinks. 
+       Add support to force sinks selected by playbin2.
+       Don't plug raw converters for non-raw sinks.
+
+       * gst/playback/gsturidecodebin.c: (_gst_array_accumulator),
+       (_gst_select_accumulator), (gst_uri_decode_bin_class_init),
+       (proxy_autoplug_select_signal), (gst_uri_decode_bin_plugin_init),
+       (plugin_init):
+       Use right accumulators.
+       Proxy new signal.
+
 2007-12-03  Wim Taymans  <wim.taymans@gmail.com>
 
        * gst-libs/gst/rtp/gstbasertppayload.c: (gst_basertppayload_push):
index 5f5c9b8..b694885 100644 (file)
@@ -7,8 +7,7 @@ built_headers = gstplay-marshal.h
 
 plugindir = $(libdir)/gstreamer-@GST_MAJORMINOR@
 
-plugin_LTLIBRARIES = libgstplaybin.la libgstdecodebin.la libgstdecodebin2.la libgstqueue2.la \
-                    libgsturidecodebin.la 
+plugin_LTLIBRARIES = libgstplaybin.la libgstdecodebin.la libgstdecodebin2.la libgstqueue2.la 
 
 libgstplaybin_la_SOURCES = \
        gstplayback.c \
@@ -16,6 +15,7 @@ libgstplaybin_la_SOURCES = \
        gstplaybin2.c \
        gstplaysink.c \
        gstplaybasebin.c \
+       gstplay-enum.c \
        gstfactorylists.c \
        gststreaminfo.c \
        gststreamselector.c
@@ -35,7 +35,7 @@ libgstdecodebin_la_LIBADD = \
        $(top_builddir)/gst-libs/gst/pbutils/libgstpbutils-@GST_MAJORMINOR@.la \
        $(GST_LIBS)
 
-libgstdecodebin2_la_SOURCES = gstdecodebin2.c gstfactorylists.c
+libgstdecodebin2_la_SOURCES = gstdecodebin2.c gsturidecodebin.c gstfactorylists.c gstplay-enum.c
 nodist_libgstdecodebin2_la_SOURCES = $(built_sources)
 libgstdecodebin2_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS)
 libgstdecodebin2_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
@@ -49,19 +49,12 @@ libgstqueue2_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS)
 libgstqueue2_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
 libgstqueue2_la_LIBADD = $(GST_LIBS)
 
-libgsturidecodebin_la_SOURCES = gsturidecodebin.c
-nodist_libgsturidecodebin_la_SOURCES = $(built_sources)
-libgsturidecodebin_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS)
-libgsturidecodebin_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
-libgsturidecodebin_la_LIBADD = \
-       $(top_builddir)/gst-libs/gst/pbutils/libgstpbutils-@GST_MAJORMINOR@.la \
-       $(GST_LIBS)
-
 noinst_HEADERS = \
        gstplaybasebin.h \
        gstplaysink.h \
        gststreaminfo.h \
        gstfactorylists.h \
+       gstplay-enum.h \
        gststreamselector.h
 
 noinst_PROGRAMS = test decodetest test2 test3 test4 test5 test6 test7
index 10a8ac7..314481d 100644 (file)
@@ -43,6 +43,7 @@
 #include <gst/pbutils/pbutils.h>
 
 #include "gstplay-marshal.h"
+#include "gstplay-enum.h"
 #include "gstfactorylists.h"
 
 /* generic templates */
@@ -121,9 +122,12 @@ struct _GstDecodeBinClass
   /* 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 */
-    gint (*autoplug_select) (GstElement * element, GstPad * pad, GstCaps * caps,
-      GValueArray * factories);
+    GstAutoplugSelectResult (*autoplug_select) (GstElement * element,
+      GstPad * pad, GstCaps * caps, GstElementFactory * factory);
 
   /* fired when the last group is drained */
   void (*drained) (GstElement * element);
@@ -138,6 +142,7 @@ enum
   SIGNAL_AUTOPLUG_CONTINUE,
   SIGNAL_AUTOPLUG_FACTORIES,
   SIGNAL_AUTOPLUG_SELECT,
+  SIGNAL_AUTOPLUG_SORT,
   SIGNAL_DRAINED,
   LAST_SIGNAL
 };
@@ -170,8 +175,10 @@ static gboolean gst_decode_bin_autoplug_continue (GstElement * element,
     GstPad * pad, GstCaps * caps);
 static GValueArray *gst_decode_bin_autoplug_factories (GstElement *
     element, GstPad * pad, GstCaps * caps);
-static gint gst_decode_bin_autoplug_select (GstElement * element,
-    GstPad * pad, GstCaps * caps, GValueArray * list);
+static GValueArray *gst_decode_bin_autoplug_sort (GstElement * element,
+    GstPad * pad, GstCaps * caps, GValueArray * factories);
+static GstAutoplugSelectResult gst_decode_bin_autoplug_select (GstElement *
+    element, GstPad * pad, GstCaps * caps, GstElementFactory * factory);
 
 static void gst_decode_bin_set_property (GObject * object, guint prop_id,
     const GValue * value, GParamSpec * pspec);
@@ -336,6 +343,33 @@ _gst_boolean_accumulator (GSignalInvocationHint * ihint,
   return myboolean;
 }
 
+/* we collect the first result */
+static gboolean
+_gst_array_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);
+
+  return FALSE;
+}
+
+static gboolean
+_gst_select_accumulator (GSignalInvocationHint * ihint,
+    GValue * return_accu, const GValue * handler_return, gpointer dummy)
+{
+  GstAutoplugSelectResult res;
+
+  res = g_value_get_enum (handler_return);
+  if (!(ihint->run_type & G_SIGNAL_RUN_CLEANUP))
+    g_value_set_enum (return_accu, res);
+
+  return FALSE;
+}
+
 static void
 gst_decode_bin_class_init (GstDecodeBinClass * klass)
 {
@@ -435,11 +469,32 @@ gst_decode_bin_class_init (GstDecodeBinClass * klass)
   gst_decode_bin_signals[SIGNAL_AUTOPLUG_FACTORIES] =
       g_signal_new ("autoplug-factories", G_TYPE_FROM_CLASS (klass),
       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstDecodeBinClass,
-          autoplug_factories), NULL, NULL,
+          autoplug_factories), _gst_array_accumulator, NULL,
       gst_play_marshal_BOXED__OBJECT_OBJECT, G_TYPE_VALUE_ARRAY, 2,
       GST_TYPE_PAD, GST_TYPE_CAPS);
 
   /**
+   * GstDecodeBin2::autoplug-sort:
+   * @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_decode_bin_signals[SIGNAL_AUTOPLUG_SORT] =
+      g_signal_new ("autoplug-sort", G_TYPE_FROM_CLASS (klass),
+      G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstDecodeBinClass, autoplug_sort),
+      NULL, NULL, gst_play_marshal_BOXED__OBJECT_OBJECT_BOXED,
+      G_TYPE_VALUE_ARRAY, 3, GST_TYPE_PAD, GST_TYPE_CAPS, G_TYPE_VALUE_ARRAY);
+
+  /**
    * GstDecodeBin2::autoplug-select:
    * @pad: The #GstPad.
    * @caps: The #GstCaps.
@@ -451,14 +506,16 @@ gst_decode_bin_class_init (GstDecodeBinClass * klass)
    *
    * Returns: A #gint indicating what factory index from the @factories array
    * that you wish decodebin2 to use for trying to decode the given @caps.
-   * -1 to stop selection of a factory. The default handler always
-   * returns the first possible factory.
+   * Return -1 to stop selection of a factory and expose the pad as a raw type. 
+   * The default handler always returns the first possible factory (index 0).
    */
   gst_decode_bin_signals[SIGNAL_AUTOPLUG_SELECT] =
       g_signal_new ("autoplug-select", G_TYPE_FROM_CLASS (klass),
       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstDecodeBinClass, autoplug_select),
-      NULL, NULL, gst_play_marshal_INT__OBJECT_OBJECT_BOXED,
-      G_TYPE_INT, 3, GST_TYPE_PAD, GST_TYPE_CAPS, G_TYPE_VALUE_ARRAY);
+      _gst_select_accumulator, NULL,
+      gst_play_marshal_ENUM__OBJECT_OBJECT_OBJECT,
+      GST_TYPE_AUTOPLUG_SELECT_RESULT, 3, GST_TYPE_PAD, GST_TYPE_CAPS,
+      GST_TYPE_ELEMENT_FACTORY);
 
   /**
    * GstDecodeBin2::drained
@@ -487,6 +544,7 @@ gst_decode_bin_class_init (GstDecodeBinClass * klass)
       GST_DEBUG_FUNCPTR (gst_decode_bin_autoplug_continue);
   klass->autoplug_factories =
       GST_DEBUG_FUNCPTR (gst_decode_bin_autoplug_factories);
+  klass->autoplug_sort = GST_DEBUG_FUNCPTR (gst_decode_bin_autoplug_sort);
   klass->autoplug_select = GST_DEBUG_FUNCPTR (gst_decode_bin_autoplug_select);
 
   gst_element_class_add_pad_template (gstelement_klass,
@@ -504,7 +562,8 @@ static void
 gst_decode_bin_init (GstDecodeBin * decode_bin)
 {
   /* first filter out the interesting element factories */
-  decode_bin->factories = gst_factory_list_get_decoders ();
+  decode_bin->factories =
+      gst_factory_list_get_elements (GST_FACTORY_LIST_DECODER);
 
   /* we create the typefind element only once */
   decode_bin->typefind = gst_element_factory_make ("typefind", "typefind");
@@ -754,17 +813,28 @@ gst_decode_bin_autoplug_factories (GstElement * element, GstPad * pad,
   return result;
 }
 
-static gint
-gst_decode_bin_autoplug_select (GstElement * element, GstPad * pad,
+static GValueArray *
+gst_decode_bin_autoplug_sort (GstElement * element, GstPad * pad,
     GstCaps * caps, GValueArray * factories)
 {
-  g_return_val_if_fail (factories != NULL, -1);
-  g_return_val_if_fail (factories->n_values > 0, -1);
+  GValueArray *result;
+
+  result = g_value_array_copy (factories);
 
-  GST_DEBUG_OBJECT (element, "default autoplug-select returns 0");
+  GST_DEBUG_OBJECT (element, "autoplug-sort returns %p", result);
 
-  /* Return first factory. */
-  return 0;
+  /* return input */
+  return result;
+}
+
+static GstAutoplugSelectResult
+gst_decode_bin_autoplug_select (GstElement * element, GstPad * pad,
+    GstCaps * caps, GstElementFactory * factory)
+{
+  GST_DEBUG_OBJECT (element, "default autoplug-select returns TRY");
+
+  /* Try factory. */
+  return GST_AUTOPLUG_SELECT_TRY;
 }
 
 /********
@@ -776,7 +846,7 @@ static gboolean is_demuxer_element (GstElement * srcelement);
 
 static gboolean connect_pad (GstDecodeBin * dbin, GstElement * src,
     GstPad * pad, GstCaps * caps, GValueArray * factories,
-    GstDecodeGroup * group);
+    GstDecodeGroup * group, gboolean * expose);
 static gboolean connect_element (GstDecodeBin * dbin, GstElement * element,
     GstDecodeGroup * group);
 static void expose_pad (GstDecodeBin * dbin, GstElement * src, GstPad * pad,
@@ -813,7 +883,8 @@ analyze_new_pad (GstDecodeBin * dbin, GstElement * src, GstPad * pad,
     GstCaps * caps, GstDecodeGroup * group)
 {
   gboolean apcontinue = TRUE;
-  GValueArray *factories = NULL;
+  GValueArray *factories = NULL, *result = NULL;
+  gboolean expose;
 
   GST_DEBUG_OBJECT (dbin, "Pad %s:%s caps:%" GST_PTR_FORMAT,
       GST_DEBUG_PAD_NAME (pad), caps);
@@ -856,12 +927,22 @@ analyze_new_pad (GstDecodeBin * dbin, GstElement * src, GstPad * pad,
     goto unknown_type;
   }
 
-  /* 1.d else continue autoplugging something from the list. */
+  /* 1.d sort some more. */
+  g_signal_emit (G_OBJECT (dbin),
+      gst_decode_bin_signals[SIGNAL_AUTOPLUG_SORT], 0, pad, caps, factories,
+      &result);
+  g_value_array_free (factories);
+  factories = result;
+
+  /* 1.e else continue autoplugging something from the list. */
   GST_LOG_OBJECT (pad, "Let's continue discovery on this pad");
-  connect_pad (dbin, src, pad, caps, factories, group);
+  connect_pad (dbin, src, pad, caps, factories, group, &expose);
 
   g_value_array_free (factories);
 
+  if (expose)
+    goto expose_pad;
+
   return;
 
 expose_pad:
@@ -934,7 +1015,8 @@ setup_caps_delay:
  */
 static gboolean
 connect_pad (GstDecodeBin * dbin, GstElement * src, GstPad * pad,
-    GstCaps * caps, GValueArray * factories, GstDecodeGroup * group)
+    GstCaps * caps, GValueArray * factories, GstDecodeGroup * group,
+    gboolean * expose)
 {
   gboolean res = FALSE;
   GstPad *mqpad = NULL;
@@ -942,6 +1024,8 @@ connect_pad (GstDecodeBin * dbin, GstElement * src, GstPad * pad,
   g_return_val_if_fail (factories != NULL, FALSE);
   g_return_val_if_fail (factories->n_values > 0, FALSE);
 
+  *expose = FALSE;
+
   GST_DEBUG_OBJECT (dbin, "pad %s:%s , group:%p",
       GST_DEBUG_PAD_NAME (pad), group);
 
@@ -964,32 +1048,37 @@ connect_pad (GstDecodeBin * dbin, GstElement * src, GstPad * pad,
 
   /* 2. Try to create an element and link to it */
   while (factories->n_values > 0) {
-    gint factidx;
+    GstAutoplugSelectResult ret;
     GstElementFactory *factory;
     GstElement *element;
     GstPad *sinkpad;
 
-    /* emit autoplug-select */
+    /* take first factory */
+    factory = g_value_get_object (g_value_array_get_nth (factories, 0));
+    /* Remove selected factory from the list. */
+    g_value_array_remove (factories, 0);
+
+    /* emit autoplug-select to see what we should do with it. */
     g_signal_emit (G_OBJECT (dbin),
         gst_decode_bin_signals[SIGNAL_AUTOPLUG_SELECT],
-        0, pad, caps, factories, &factidx);
+        0, pad, caps, factory, &ret);
 
-    /* when the function returns -1, we leave the loop and stop */
-    if (factidx == -1) {
-      GST_DEBUG_OBJECT (dbin, "autoplug select returned -1");
-      break;
+    switch (ret) {
+      case GST_AUTOPLUG_SELECT_TRY:
+        GST_DEBUG_OBJECT (dbin, "autoplug select requested try");
+        break;
+      case GST_AUTOPLUG_SELECT_EXPOSE:
+        GST_DEBUG_OBJECT (dbin, "autoplug select requested expose");
+        *expose = TRUE;
+        goto beach;
+      case GST_AUTOPLUG_SELECT_SKIP:
+        GST_DEBUG_OBJECT (dbin, "autoplug select requested skip");
+        continue;
+      default:
+        GST_WARNING_OBJECT (dbin, "autoplug select returned unhandled %d", ret);
+        break;
     }
 
-    GST_DEBUG_OBJECT (dbin, "autoplug select returned %d", factidx);
-
-    factory = g_value_get_object (g_value_array_get_nth (factories, factidx));
-
-    /* factory is != NULL now since the default handler selects the first
-     * factory if all connected user handlers returned NULL. */
-
-    /* Remove selected factory from the list. */
-    g_value_array_remove (factories, factidx);
-
     /* 2.1. Try to create an element */
     if ((element = gst_element_factory_create (factory, NULL)) == NULL) {
       GST_WARNING_OBJECT (dbin, "Could not create an element from %s",
@@ -997,30 +1086,31 @@ connect_pad (GstDecodeBin * dbin, GstElement * src, GstPad * pad,
       continue;
     }
 
-    /* 2.3. Find its sink pad */
-    if (!(sinkpad = find_sink_pad (element))) {
-      GST_WARNING_OBJECT (dbin, "Element %s doesn't have a sink pad",
+    /* ... activate it ... We do this before adding it to the bin so that we
+     * don't accidentally make it post error messages that will stop
+     * everything. */
+    if ((gst_element_set_state (element,
+                GST_STATE_READY)) == GST_STATE_CHANGE_FAILURE) {
+      GST_WARNING_OBJECT (dbin, "Couldn't set %s to READY",
           GST_ELEMENT_NAME (element));
       gst_object_unref (element);
       continue;
     }
 
-    /* 2.4 add it ... */
-    if (!(gst_bin_add (GST_BIN (dbin), element))) {
-      GST_WARNING_OBJECT (dbin, "Couldn't add %s to the bin",
+    /* 2.3. Find its sink pad, this should work after activating it. */
+    if (!(sinkpad = find_sink_pad (element))) {
+      GST_WARNING_OBJECT (dbin, "Element %s doesn't have a sink pad",
           GST_ELEMENT_NAME (element));
-      gst_object_unref (sinkpad);
       gst_object_unref (element);
       continue;
     }
 
-    /* ... activate it ... */
-    if ((gst_element_set_state (element,
-                GST_STATE_READY)) == GST_STATE_CHANGE_FAILURE) {
-      GST_WARNING_OBJECT (dbin, "Couldn't set %s to READY",
+    /* 2.4 add it ... */
+    if (!(gst_bin_add (GST_BIN_CAST (dbin), element))) {
+      GST_WARNING_OBJECT (dbin, "Couldn't add %s to the bin",
           GST_ELEMENT_NAME (element));
       gst_object_unref (sinkpad);
-      gst_bin_remove (GST_BIN (dbin), element);
+      gst_object_unref (element);
       continue;
     }
 
@@ -1053,10 +1143,10 @@ connect_pad (GstDecodeBin * dbin, GstElement * src, GstPad * pad,
     break;
   }
 
+beach:
   if (mqpad)
     gst_object_unref (mqpad);
 
-beach:
   return res;
 }
 
@@ -2306,8 +2396,8 @@ missing_fakesink:
   }
 }
 
-static gboolean
-plugin_init (GstPlugin * plugin)
+gboolean
+gst_decode_bin_plugin_init (GstPlugin * plugin)
 {
   GST_DEBUG_CATEGORY_INIT (gst_decode_bin_debug, "decodebin2", 0,
       "decoder bin");
@@ -2321,9 +2411,3 @@ plugin_init (GstPlugin * plugin)
   return gst_element_register (plugin, "decodebin2", GST_RANK_NONE,
       GST_TYPE_DECODE_BIN);
 }
-
-GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
-    GST_VERSION_MINOR,
-    "decodebin2",
-    "decoder bin newer version", plugin_init, VERSION, GST_LICENSE,
-    GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)
index ca6166d..667beaf 100644 (file)
 
 #include "gstfactorylists.h"
 
+typedef struct
+{
+  GstFactoryListType type;
+} FilterData;
+
 /* function used to sort element features. We first sort on the rank, then
  * on the element name (to get a consistent, predictable list) */
 static gint
@@ -44,61 +49,15 @@ compare_ranks (GValue * v1, GValue * v2)
   return diff;
 }
 
-#if 0
-static void
-print_feature (GstPluginFeature * feature)
-{
-  const gchar *rname;
-
-  rname = gst_plugin_feature_get_name (feature);
-
-  GST_DEBUG ("%s", rname);
-}
-#endif
-
-/* get a filtered feature list as a GValueArray */
-static GValueArray *
-get_feature_array (GstPluginFeatureFilter filter)
-{
-  GValueArray *result;
-  GList *walk, *list;
-
-  result = g_value_array_new (0);
-
-  /* get the feature list using the filter */
-  list = gst_default_registry_feature_filter (filter, FALSE, NULL);
-
-  /* convert to an array */
-  for (walk = list; walk; walk = g_list_next (walk)) {
-    GstElementFactory *factory = GST_ELEMENT_FACTORY (walk->data);
-    GValue val = { 0, };
-
-    g_value_init (&val, G_TYPE_OBJECT);
-    g_value_set_object (&val, factory);
-    g_value_array_append (result, &val);
-    g_value_unset (&val);
-  }
-  gst_plugin_feature_list_free (list);
-
-  /* sort on rank and name */
-  g_value_array_sort (result, (GCompareFunc) compare_ranks);
-
-  return result;
-}
-
 /* the filter function for selecting the elements we can use in
  * autoplugging */
 static gboolean
-decoders_filter (GstPluginFeature * feature)
+decoders_filter (GstElementFactory * factory)
 {
   guint rank;
   const gchar *klass;
 
-  /* we only care about element factories */
-  if (!GST_IS_ELEMENT_FACTORY (feature))
-    return FALSE;
-
-  klass = gst_element_factory_get_klass (GST_ELEMENT_FACTORY (feature));
+  klass = gst_element_factory_get_klass (factory);
   /* only demuxers, decoders, depayloaders and parsers can play */
   if (strstr (klass, "Demux") == NULL &&
       strstr (klass, "Decoder") == NULL &&
@@ -108,7 +67,7 @@ decoders_filter (GstPluginFeature * feature)
   }
 
   /* only select elements with autoplugging rank */
-  rank = gst_plugin_feature_get_rank (feature);
+  rank = gst_plugin_feature_get_rank (GST_PLUGIN_FEATURE (factory));
   if (rank < GST_RANK_MARGINAL)
     return FALSE;
 
@@ -118,16 +77,12 @@ decoders_filter (GstPluginFeature * feature)
 /* the filter function for selecting the elements we can use in
  * autoplugging */
 static gboolean
-sinks_filter (GstPluginFeature * feature)
+sinks_filter (GstElementFactory * factory)
 {
   guint rank;
   const gchar *klass;
 
-  /* we only care about element factories */
-  if (!GST_IS_ELEMENT_FACTORY (feature))
-    return FALSE;
-
-  klass = gst_element_factory_get_klass (GST_ELEMENT_FACTORY (feature));
+  klass = gst_element_factory_get_klass (factory);
   /* only sinks can play */
   if (strstr (klass, "Sink") == NULL) {
     return FALSE;
@@ -139,54 +94,116 @@ sinks_filter (GstPluginFeature * feature)
   }
 
   /* only select elements with autoplugging rank */
-  rank = gst_plugin_feature_get_rank (feature);
+  rank = gst_plugin_feature_get_rank (GST_PLUGIN_FEATURE (factory));
   if (rank < GST_RANK_MARGINAL)
     return FALSE;
 
   return TRUE;
 }
 
-
 /**
- * gst_factory_list_get_decoders:
+ * gst_factory_list_is_type:
+ * @factory: a #GstElementFactory
+ * @type: a #GstFactoryListType
  *
- * Get a sorted list of factories that can be used in decoding pipelines.
+ * Check if @factory if of the given types.
  *
- * Returns: a #GValueArray of #GstElementFactory elements. Use
- * g_value_array_free() after usage.
+ * Returns: %TRUE if @factory is of @type.
  */
-GValueArray *
-gst_factory_list_get_decoders (void)
+gboolean
+gst_factory_list_is_type (GstElementFactory * factory, GstFactoryListType type)
 {
-  GValueArray *result;
+  gboolean res = FALSE;
 
-  /* first filter out the interesting element factories */
-  result = get_feature_array ((GstPluginFeatureFilter) decoders_filter);
+  if (!res && (type & GST_FACTORY_LIST_SINK))
+    res = sinks_filter (factory);
+  if (!res && (type & GST_FACTORY_LIST_DECODER))
+    res = decoders_filter (factory);
 
-  return result;
+  return res;
+}
+
+static gboolean
+element_filter (GstPluginFeature * feature, FilterData * data)
+{
+  gboolean res;
+
+  /* we only care about element factories */
+  if (!GST_IS_ELEMENT_FACTORY (feature))
+    return FALSE;
+
+  res = gst_factory_list_is_type (GST_ELEMENT_FACTORY (feature), data->type);
+
+  return res;
 }
 
 /**
- * gst_factory_list_get_sinks:
+ * gst_factory_list_get_elements:
+ * @type: a #GstFactoryListType
  *
- * Get a sorted list of factories that can be used as sinks in a decoding
- * pipeline.
+ * Get a sorted list of factories of @type.
  *
  * Returns: a #GValueArray of #GstElementFactory elements. Use
  * g_value_array_free() after usage.
  */
 GValueArray *
-gst_factory_list_get_sinks (void)
+gst_factory_list_get_elements (GstFactoryListType type)
 {
   GValueArray *result;
+  GList *walk, *list;
+  FilterData data;
 
-  /* first filter out the interesting element factories */
-  result = get_feature_array ((GstPluginFeatureFilter) sinks_filter);
+  result = g_value_array_new (0);
+
+  /* prepare type */
+  data.type = type;
+
+  /* get the feature list using the filter */
+  list =
+      gst_default_registry_feature_filter ((GstPluginFeatureFilter)
+      element_filter, FALSE, &data);
+
+  /* convert to an array */
+  for (walk = list; walk; walk = g_list_next (walk)) {
+    GstElementFactory *factory = GST_ELEMENT_FACTORY (walk->data);
+    GValue val = { 0, };
+
+    g_value_init (&val, G_TYPE_OBJECT);
+    g_value_set_object (&val, factory);
+    g_value_array_append (result, &val);
+    g_value_unset (&val);
+  }
+  gst_plugin_feature_list_free (list);
+
+  /* sort on rank and name */
+  g_value_array_sort (result, (GCompareFunc) compare_ranks);
 
   return result;
 }
 
 /**
+ * gst_factory_list_debug:
+ * @array: an array of element factories
+ *
+ * Debug the element factory names in @array.
+ */
+void
+gst_factory_list_debug (GValueArray * array)
+{
+  gint i;
+
+  for (i = 0; i < array->n_values; i++) {
+    GValue *value;
+    GstPluginFeature *feature;
+
+    value = g_value_array_get_nth (array, i);
+    feature = g_value_get_object (value);
+
+    GST_DEBUG ("%s", gst_plugin_feature_get_name (feature));
+  }
+}
+
+/**
  * gst_factory_list_filter:
  * @array: a #GValueArray to filter
  * @caps: a #GstCaps
index 100535c..c8e5075 100644 (file)
 
 G_BEGIN_DECLS
 
-GValueArray * gst_factory_list_get_decoders (void);
-GValueArray * gst_factory_list_get_sinks    (void);
+typedef enum {
+  GST_FACTORY_LIST_DECODER = (1 << 0),
+  GST_FACTORY_LIST_ENCODER = (1 << 1),
+  GST_FACTORY_LIST_SINK    = (1 << 2),
+  GST_FACTORY_LIST_SRC     = (1 << 3)
+} GstFactoryListType;
+
+gboolean      gst_factory_list_is_type      (GstElementFactory *factory, GstFactoryListType type);
+GValueArray * gst_factory_list_get_elements (GstFactoryListType type);
+
+void          gst_factory_list_debug        (GValueArray *array);
 
 GValueArray * gst_factory_list_filter       (GValueArray *array, const GstCaps *caps);
 
index 03b6bfd..300a5b4 100644 (file)
@@ -1,4 +1,7 @@
 BOOLEAN:OBJECT,OBJECT
+BOOLEAN:OBJECT,OBJECT,OBJECT
 BOXED:OBJECT,OBJECT
 VOID:OBJECT,BOOLEAN
-INT:OBJECT,OBJECT,BOXED
+ENUM:OBJECT,OBJECT,BOXED
+ENUM:OBJECT,OBJECT,OBJECT
+BOXED:OBJECT,OBJECT,BOXED
index 5c6132e..8cb00f6 100644 (file)
 #include <gst/gst-i18n-plugin.h>
 #include <gst/pbutils/pbutils.h>
 
+#include "gstplay-enum.h"
 #include "gstplaysink.h"
 #include "gstfactorylists.h"
 #include "gststreaminfo.h"
@@ -321,8 +322,7 @@ struct _GstPlayBin
   /* our play sink */
   GstPlaySink *playsink;
 
-  GValueArray *elements;        /* factories we can use for selecting sinks */
-  GValueArray *sinks;           /* factories we can use for selecting sinks */
+  GValueArray *elements;        /* factories we can use for selecting elements */
 };
 
 struct _GstPlayBinClass
@@ -530,20 +530,28 @@ init_group (GstPlayBin * playbin, GstSourceGroup * group)
 {
   /* init selectors */
   group->playbin = playbin;
-  group->selector[0].media = "audio/";
-  group->selector[0].type = GST_PLAY_SINK_TYPE_AUDIO;
+  group->selector[0].media = "audio/x-raw-";
+  group->selector[0].type = GST_PLAY_SINK_TYPE_AUDIO_RAW;
   group->selector[0].mode = GST_PLAY_SINK_MODE_AUDIO;
-  group->selector[1].media = "video/";
-  group->selector[1].type = GST_PLAY_SINK_TYPE_VIDEO;
-  group->selector[1].mode = GST_PLAY_SINK_MODE_VIDEO;
-  group->selector[2].media = "text/";
-  group->selector[2].type = GST_PLAY_SINK_TYPE_TEXT;
-  group->selector[2].mode = GST_PLAY_SINK_MODE_TEXT;
+  group->selector[1].media = "audio/";
+  group->selector[1].type = GST_PLAY_SINK_TYPE_AUDIO;
+  group->selector[1].mode = GST_PLAY_SINK_MODE_AUDIO;
+  group->selector[2].media = "video/x-raw-";
+  group->selector[2].type = GST_PLAY_SINK_TYPE_VIDEO_RAW;
+  group->selector[2].mode = GST_PLAY_SINK_MODE_VIDEO;
+  group->selector[3].media = "video/";
+  group->selector[3].type = GST_PLAY_SINK_TYPE_VIDEO;
+  group->selector[3].mode = GST_PLAY_SINK_MODE_VIDEO;
+  group->selector[4].media = "text/";
+  group->selector[4].type = GST_PLAY_SINK_TYPE_TEXT;
+  group->selector[4].mode = GST_PLAY_SINK_MODE_TEXT;
 }
 
 static void
 gst_play_bin_init (GstPlayBin * playbin)
 {
+  GstFactoryListType type;
+
   /* init groups */
   playbin->curr_group = &playbin->groups[0];
   playbin->next_group = &playbin->groups[1];
@@ -551,7 +559,9 @@ gst_play_bin_init (GstPlayBin * playbin)
   init_group (playbin, &playbin->groups[1]);
 
   /* first filter out the interesting element factories */
-  playbin->sinks = gst_factory_list_get_sinks ();
+  type = GST_FACTORY_LIST_DECODER | GST_FACTORY_LIST_SINK;
+  playbin->elements = gst_factory_list_get_elements (type);
+  gst_factory_list_debug (playbin->elements);
 
   /* get the caps */
 }
@@ -563,7 +573,7 @@ gst_play_bin_finalize (GObject * object)
 
   play_bin = GST_PLAY_BIN (object);
 
-  g_value_array_free (play_bin->sinks);
+  g_value_array_free (play_bin->elements);
 
   G_OBJECT_CLASS (parent_class)->finalize (object);
 }
@@ -868,7 +878,6 @@ not_linked:
     GST_DEBUG_OBJECT (playbin, "pad not linked");
     return;
   }
-
 }
 
 /* we get called when all pads are available and we must connect the sinks to
@@ -949,25 +958,96 @@ drained_cb (GstElement * decodebin, GstSourceGroup * group)
   }
 }
 
-/* a callback is called */
+/* 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
+ * work), we return the list of elements that can connect. */
 static GValueArray *
 autoplug_factories_cb (GstElement * decodebin, GstPad * pad,
     GstCaps * caps, GstSourceGroup * group)
 {
   GstPlayBin *playbin;
-  GValueArray *result = NULL;
+  GValueArray *result;
 
   playbin = group->playbin;
 
-  GST_DEBUG_OBJECT (playbin, "continue group %p for %s:%s, %" GST_PTR_FORMAT,
+  GST_DEBUG_OBJECT (playbin, "factories group %p for %s:%s, %" GST_PTR_FORMAT,
       group, GST_DEBUG_PAD_NAME (pad), caps);
 
+  /* filter out the elements based on the caps. */
+  result = gst_factory_list_filter (playbin->elements, caps);
 
   GST_DEBUG_OBJECT (playbin, "found factories %p", result);
+  gst_factory_list_debug (result);
 
   return result;
 }
 
+/* We are asked to select an element. See if the next element to check
+ * is a sink. If this is the case, we see if the sink works by setting it to
+ * READY. If the sink works, we return -2 to make decodebin expose the raw pad
+ * so that we can setup the mixers. */
+static GstAutoplugSelectResult
+autoplug_select_cb (GstElement * decodebin, GstPad * pad,
+    GstCaps * caps, GstElementFactory * factory, GstSourceGroup * group)
+{
+  GstPlayBin *playbin;
+  GstElement *element;
+  const gchar *klass;
+
+  playbin = group->playbin;
+
+  GST_DEBUG_OBJECT (playbin, "select group %p for %s:%s, %" GST_PTR_FORMAT,
+      group, GST_DEBUG_PAD_NAME (pad), caps);
+
+  GST_DEBUG_OBJECT (playbin, "checking factory %s",
+      GST_PLUGIN_FEATURE_NAME (factory));
+
+  /* if it's not a sink, we just make decodebin try it */
+  if (!gst_factory_list_is_type (factory, GST_FACTORY_LIST_SINK))
+    return GST_AUTOPLUG_SELECT_TRY;
+
+  /* it's a sink, see if an instance of it actually works */
+  GST_DEBUG_OBJECT (playbin, "we found a sink");
+
+  if ((element = gst_element_factory_create (factory, NULL)) == NULL) {
+    GST_WARNING_OBJECT (playbin, "Could not create an element from %s",
+        gst_plugin_feature_get_name (GST_PLUGIN_FEATURE (factory)));
+    return GST_AUTOPLUG_SELECT_SKIP;
+  }
+
+  /* ... activate it ... We do this before adding it to the bin so that we
+   * don't accidentally make it post error messages that will stop
+   * everything. */
+  if ((gst_element_set_state (element,
+              GST_STATE_READY)) == GST_STATE_CHANGE_FAILURE) {
+    GST_WARNING_OBJECT (playbin, "Couldn't set %s to READY",
+        GST_ELEMENT_NAME (element));
+    gst_object_unref (element);
+    return GST_AUTOPLUG_SELECT_SKIP;
+  }
+
+  /* at this point, we have the sink working, configure it in playsink */
+  klass = gst_element_factory_get_klass (factory);
+
+  /* get klass to figure out if it's audio or video */
+  if (strstr (klass, "Audio")) {
+    GST_DEBUG_OBJECT (playbin, "configure audio sink");
+    gst_play_sink_set_audio_sink (playbin->playsink, element);
+  } else if (strstr (klass, "Video")) {
+    GST_DEBUG_OBJECT (playbin, "configure video sink");
+    gst_play_sink_set_video_sink (playbin->playsink, element);
+  } else {
+    GST_WARNING_OBJECT (playbin, "unknown sink klass %s found", klass);
+  }
+
+  /* tell decodebin to expose the pad because we are going to use this
+   * sink */
+  GST_DEBUG_OBJECT (playbin, "we found a working sink, expose pad");
+
+  return GST_AUTOPLUG_SELECT_EXPOSE;
+}
+
 /* unlink a group of uridecodebins from the sink */
 static void
 unlink_group (GstPlayBin * playbin, GstSourceGroup * group)
@@ -1022,11 +1102,14 @@ activate_group (GstPlayBin * playbin, GstSourceGroup * group)
    * next uri */
   g_signal_connect (uridecodebin, "drained", G_CALLBACK (drained_cb), group);
 
-  /* will be called when a new media type is found. We will see if we have a
-   * working sink that can natively handle this format. */
+  /* will be called when a new media type is found. We return a list of decoders
+   * including sinks for decodebin to try */
   g_signal_connect (uridecodebin, "autoplug-factories",
       G_CALLBACK (autoplug_factories_cb), group);
 
+  g_signal_connect (uridecodebin, "autoplug-select",
+      G_CALLBACK (autoplug_select_cb), group);
+
   /*  */
   gst_bin_add (GST_BIN_CAST (playbin), uridecodebin);
   group->uridecodebin = uridecodebin;
index 387a706..bdc2217 100644 (file)
@@ -74,7 +74,9 @@ struct _GstPlaySink
   GstPlayChain *videochain;
 
   GstPad *audio_pad;
+  gboolean audio_pad_raw;
   GstPad *video_pad;
+  gboolean video_pad_raw;
   GstPad *text_pad;
 
   /* properties */
@@ -388,7 +390,7 @@ beach:
       play_sink);
 }
 
-static void
+void
 gst_play_sink_set_video_sink (GstPlaySink * play_sink, GstElement * sink)
 {
   GST_OBJECT_LOCK (play_sink);
@@ -403,7 +405,7 @@ gst_play_sink_set_video_sink (GstPlaySink * play_sink, GstElement * sink)
   GST_OBJECT_UNLOCK (play_sink);
 }
 
-static void
+void
 gst_play_sink_set_audio_sink (GstPlaySink * play_sink, GstElement * sink)
 {
   GST_OBJECT_LOCK (play_sink);
@@ -418,7 +420,7 @@ gst_play_sink_set_audio_sink (GstPlaySink * play_sink, GstElement * sink)
   GST_OBJECT_UNLOCK (play_sink);
 }
 
-static void
+void
 gst_play_sink_set_vis_plugin (GstPlaySink * play_sink,
     GstElement * pending_visualisation)
 {
@@ -622,7 +624,7 @@ activate_chain (GstPlayChain * chain, gboolean activate)
  *           
  */
 static GstPlayChain *
-gen_video_chain (GstPlaySink * play_sink)
+gen_video_chain (GstPlaySink * play_sink, gboolean raw)
 {
   GstPlayVideoChain *chain;
   GstBin *bin;
@@ -650,11 +652,17 @@ gen_video_chain (GstPlaySink * play_sink)
   gst_object_sink (bin);
   gst_bin_add (bin, chain->sink);
 
+  if (raw) {
+    chain->conv = gst_element_factory_make ("ffmpegcolorspace", "vconv");
+    if (chain->conv == NULL)
+      goto no_colorspace;
+    gst_bin_add (bin, chain->conv);
 
-  chain->conv = gst_element_factory_make ("ffmpegcolorspace", "vconv");
-  if (chain->conv == NULL)
-    goto no_colorspace;
-  gst_bin_add (bin, chain->conv);
+    chain->scale = gst_element_factory_make ("videoscale", "vscale");
+    if (chain->scale == NULL)
+      goto no_videoscale;
+    gst_bin_add (bin, chain->scale);
+  }
 
   /* decouple decoder from sink, this improves playback quite a lot since the
    * decoder can continue while the sink blocks for synchronisation. We don't
@@ -665,19 +673,21 @@ gen_video_chain (GstPlaySink * play_sink)
       "max-size-bytes", 0, "max-size-time", (gint64) 0, NULL);
   gst_bin_add (bin, chain->queue);
 
-  chain->scale = gst_element_factory_make ("videoscale", "vscale");
-  if (chain->scale == NULL)
-    goto no_videoscale;
-  gst_bin_add (bin, chain->scale);
+  if (raw) {
+    gst_element_link_pads (chain->conv, "src", chain->queue, "sink");
+    gst_element_link_pads (chain->queue, "src", chain->scale, "sink");
+    /* be more careful with the pad from the custom sink element, it might not
+     * be named 'sink' */
+    if (!gst_element_link_pads (chain->scale, "src", chain->sink, NULL))
+      goto link_failed;
 
-  gst_element_link_pads (chain->conv, "src", chain->queue, "sink");
-  gst_element_link_pads (chain->queue, "src", chain->scale, "sink");
-  /* be more careful with the pad from the custom sink element, it might not
-   * be named 'sink' */
-  if (!gst_element_link_pads (chain->scale, "src", chain->sink, NULL))
-    goto link_failed;
+    pad = gst_element_get_pad (chain->conv, "sink");
+  } else {
+    if (!gst_element_link_pads (chain->queue, "src", chain->sink, NULL))
+      goto link_failed;
+    pad = gst_element_get_pad (chain->queue, "sink");
+  }
 
-  pad = gst_element_get_pad (chain->conv, "sink");
   chain->chain.sinkpad = gst_ghost_pad_new ("sink", pad);
   gst_object_unref (pad);
   gst_element_add_pad (chain->chain.bin, chain->chain.sinkpad);
@@ -817,7 +827,7 @@ no_overlay:
  *  +-------------------------------------------------------------+
  */
 static GstPlayChain *
-gen_audio_chain (GstPlaySink * play_sink)
+gen_audio_chain (GstPlaySink * play_sink, gboolean raw)
 {
   GstPlayAudioChain *chain;
   GstBin *bin;
@@ -843,27 +853,32 @@ gen_audio_chain (GstPlaySink * play_sink)
   gst_object_sink (bin);
   gst_bin_add (bin, chain->sink);
 
-  chain->conv = gst_element_factory_make ("audioconvert", "aconv");
-  if (chain->conv == NULL)
-    goto no_audioconvert;
-  gst_bin_add (bin, chain->conv);
-
-  chain->resample = gst_element_factory_make ("audioresample", "aresample");
-  if (chain->resample == NULL)
-    goto no_audioresample;
-  gst_bin_add (bin, chain->resample);
-
-  chain->volume = gst_element_factory_make ("volume", "volume");
-  g_object_set (G_OBJECT (chain->volume), "volume", play_sink->volume, NULL);
-  gst_bin_add (bin, chain->volume);
-
-  res = gst_element_link_pads (chain->conv, "src", chain->resample, "sink");
-  res &= gst_element_link_pads (chain->resample, "src", chain->volume, "sink");
-  res &= gst_element_link_pads (chain->volume, "src", chain->sink, NULL);
-  if (!res)
-    goto link_failed;
-
-  pad = gst_element_get_pad (chain->conv, "sink");
+  if (raw) {
+    chain->conv = gst_element_factory_make ("audioconvert", "aconv");
+    if (chain->conv == NULL)
+      goto no_audioconvert;
+    gst_bin_add (bin, chain->conv);
+
+    chain->resample = gst_element_factory_make ("audioresample", "aresample");
+    if (chain->resample == NULL)
+      goto no_audioresample;
+    gst_bin_add (bin, chain->resample);
+
+    chain->volume = gst_element_factory_make ("volume", "volume");
+    g_object_set (G_OBJECT (chain->volume), "volume", play_sink->volume, NULL);
+    gst_bin_add (bin, chain->volume);
+
+    res = gst_element_link_pads (chain->conv, "src", chain->resample, "sink");
+    res &=
+        gst_element_link_pads (chain->resample, "src", chain->volume, "sink");
+    res &= gst_element_link_pads (chain->volume, "src", chain->sink, NULL);
+    if (!res)
+      goto link_failed;
+
+    pad = gst_element_get_pad (chain->conv, "sink");
+  } else {
+    pad = gst_element_get_pad (chain->sink, "sink");
+  }
   chain->chain.sinkpad = gst_ghost_pad_new ("sink", pad);
   gst_object_unref (pad);
   gst_element_add_pad (chain->chain.bin, chain->chain.sinkpad);
@@ -1078,7 +1093,8 @@ gst_play_sink_set_mode (GstPlaySink * playsink, GstPlaySinkMode mode)
 {
   if (mode & GST_PLAY_SINK_MODE_AUDIO && playsink->audio_pad) {
     if (!playsink->audiochain)
-      playsink->audiochain = gen_audio_chain (playsink);
+      playsink->audiochain =
+          gen_audio_chain (playsink, playsink->audio_pad_raw);
     add_chain (playsink->audiochain, TRUE);
     activate_chain (playsink->audiochain, TRUE);
     gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (playsink->audio_pad),
@@ -1094,7 +1110,8 @@ gst_play_sink_set_mode (GstPlaySink * playsink, GstPlaySinkMode mode)
 
   if (mode & GST_PLAY_SINK_MODE_VIDEO && playsink->video_pad) {
     if (!playsink->videochain)
-      playsink->videochain = gen_video_chain (playsink);
+      playsink->videochain =
+          gen_video_chain (playsink, playsink->video_pad_raw);
     add_chain (playsink->videochain, TRUE);
     activate_chain (playsink->videochain, TRUE);
     gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (playsink->video_pad),
@@ -1118,22 +1135,29 @@ gst_play_sink_request_pad (GstPlaySink * playsink, GstPlaySinkType type)
 {
   GstPad *res = NULL;
   gboolean created = FALSE;
+  gboolean raw = FALSE;
 
   switch (type) {
+    case GST_PLAY_SINK_TYPE_AUDIO_RAW:
+      raw = TRUE;
     case GST_PLAY_SINK_TYPE_AUDIO:
       if (!playsink->audio_pad) {
         playsink->audio_pad =
             gst_ghost_pad_new_no_target ("audio_sink", GST_PAD_SINK);
         created = TRUE;
       }
+      playsink->audio_pad_raw = raw;
       res = playsink->audio_pad;
       break;
+    case GST_PLAY_SINK_TYPE_VIDEO_RAW:
+      raw = TRUE;
     case GST_PLAY_SINK_TYPE_VIDEO:
       if (!playsink->video_pad) {
         playsink->video_pad =
             gst_ghost_pad_new_no_target ("video_sink", GST_PAD_SINK);
         created = TRUE;
       }
+      playsink->video_pad_raw = raw;
       res = playsink->video_pad;
       break;
     case GST_PLAY_SINK_TYPE_TEXT:
index e319e2c..50da18e 100644 (file)
@@ -45,17 +45,30 @@ G_BEGIN_DECLS
  * Features to enable in the sink.
  */
 typedef enum {
-  GST_PLAY_SINK_MODE_VIDEO  = (1 << 0),
-  GST_PLAY_SINK_MODE_AUDIO  = (1 << 1),
-  GST_PLAY_SINK_MODE_TEXT   = (1 << 2),
-  GST_PLAY_SINK_MODE_VIS    = (1 << 3)
+  GST_PLAY_SINK_MODE_VIDEO       = (1 << 0),
+  GST_PLAY_SINK_MODE_AUDIO       = (1 << 1),
+  GST_PLAY_SINK_MODE_TEXT        = (1 << 2),
+  GST_PLAY_SINK_MODE_VIS         = (1 << 3)
 } GstPlaySinkMode;
 
+/**
+ * GstPlaySinkType:
+ * @GST_PLAY_SINK_TYPE_AUDIO: A non-raw audio pad
+ * @GST_PLAY_SINK_TYPE_AUDIO_RAW: a raw audio pad
+ * @GST_PLAY_SINK_TYPE_VIDEO: a non-raw video pad
+ * @GST_PLAY_SINK_TYPE_VIDEO_RAW: a raw video pad
+ * @GST_PLAY_SINK_TYPE_TEXT: a raw text pad
+ * @GST_PLAY_SINK_TYPE_LAST: the last type
+ *
+ * Types of pads that can be requested from the sinks.
+ */
 typedef enum {
-  GST_PLAY_SINK_TYPE_AUDIO = 0,
-  GST_PLAY_SINK_TYPE_VIDEO = 1,
-  GST_PLAY_SINK_TYPE_TEXT  = 2,
-  GST_PLAY_SINK_TYPE_LAST  = 3
+  GST_PLAY_SINK_TYPE_AUDIO     = 0,
+  GST_PLAY_SINK_TYPE_AUDIO_RAW = 1,
+  GST_PLAY_SINK_TYPE_VIDEO     = 2,
+  GST_PLAY_SINK_TYPE_VIDEO_RAW = 3,
+  GST_PLAY_SINK_TYPE_TEXT      = 4,
+  GST_PLAY_SINK_TYPE_LAST      = 5
 } GstPlaySinkType;
 
 typedef struct _GstPlaySink GstPlaySink;
@@ -66,6 +79,10 @@ GType gst_play_sink_get_type (void);
 GstPad *         gst_play_sink_request_pad    (GstPlaySink *playsink, GstPlaySinkType type);
 void             gst_play_sink_release_pad    (GstPlaySink *playsink, GstPad *pad);
 
+void             gst_play_sink_set_video_sink (GstPlaySink * play_sink, GstElement * sink);
+void             gst_play_sink_set_audio_sink (GstPlaySink * play_sink, GstElement * sink);
+void             gst_play_sink_set_vis_plugin (GstPlaySink * play_sink, GstElement * vis);
+
 GstPlaySinkMode  gst_play_sink_get_mode       (GstPlaySink *playsink);
 gboolean         gst_play_sink_set_mode       (GstPlaySink *playsink, GstPlaySinkMode mode);
 
index 90d031a..6013ba4 100644 (file)
@@ -34,6 +34,7 @@
 #include <gst/gst-i18n-plugin.h>
 
 #include "gstplay-marshal.h"
+#include "gstplay-enum.h"
 
 #define GST_TYPE_URI_DECODE_BIN \
   (gst_uri_decode_bin_get_type())
@@ -85,8 +86,8 @@ struct _GstURIDecodeBinClass
   GValueArray *(*autoplug_factories) (GstElement * element, GstPad * pad,
       GstCaps * caps);
   /* signal fired to select from the proposed list of factories */
-    gint (*autoplug_select) (GstElement * element, GstPad * pad, GstCaps * caps,
-      GValueArray * factories);
+    GstAutoplugSelectResult (*autoplug_select) (GstElement * element,
+      GstPad * pad, GstCaps * caps, GValueArray * factories);
 
   /* emited when all data is decoded */
   void (*drained) (GstElement * element);
@@ -175,6 +176,32 @@ _gst_boolean_accumulator (GSignalInvocationHint * ihint,
 }
 
 static gboolean
+_gst_array_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);
+
+  return FALSE;
+}
+
+static gboolean
+_gst_select_accumulator (GSignalInvocationHint * ihint,
+    GValue * return_accu, const GValue * handler_return, gpointer dummy)
+{
+  GstAutoplugSelectResult res;
+
+  res = g_value_get_enum (handler_return);
+  if (!(ihint->run_type & G_SIGNAL_RUN_CLEANUP))
+    g_value_set_enum (return_accu, res);
+
+  return FALSE;
+}
+
+static gboolean
 gst_uri_decode_bin_autoplug_continue (GstElement * element, GstPad * pad,
     GstCaps * caps)
 {
@@ -267,7 +294,7 @@ gst_uri_decode_bin_class_init (GstURIDecodeBinClass * klass)
   gst_uri_decode_bin_signals[SIGNAL_AUTOPLUG_FACTORIES] =
       g_signal_new ("autoplug-factories", G_TYPE_FROM_CLASS (klass),
       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstURIDecodeBinClass,
-          autoplug_factories), NULL, NULL,
+          autoplug_factories), _gst_array_accumulator, NULL,
       gst_play_marshal_BOXED__OBJECT_OBJECT, G_TYPE_VALUE_ARRAY, 2,
       GST_TYPE_PAD, GST_TYPE_CAPS);
 
@@ -289,9 +316,10 @@ gst_uri_decode_bin_class_init (GstURIDecodeBinClass * klass)
   gst_uri_decode_bin_signals[SIGNAL_AUTOPLUG_SELECT] =
       g_signal_new ("autoplug-select", G_TYPE_FROM_CLASS (klass),
       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstURIDecodeBinClass,
-          autoplug_select), NULL, NULL,
-      gst_play_marshal_INT__OBJECT_OBJECT_BOXED, G_TYPE_INT, 3, GST_TYPE_PAD,
-      GST_TYPE_CAPS, G_TYPE_VALUE_ARRAY);
+          autoplug_select), _gst_select_accumulator, NULL,
+      gst_play_marshal_ENUM__OBJECT_OBJECT_OBJECT,
+      GST_TYPE_AUTOPLUG_SELECT_RESULT, 3, GST_TYPE_PAD, GST_TYPE_CAPS,
+      GST_TYPE_ELEMENT_FACTORY);
 
   /**
    * GstURIDecodeBin::drained:
@@ -871,14 +899,14 @@ proxy_autoplug_factories_signal (GstElement * element, GstPad * pad,
   return result;
 }
 
-static gint
+static GstAutoplugSelectResult
 proxy_autoplug_select_signal (GstElement * element, GstPad * pad,
-    GstCaps * caps, GValueArray * array, GstURIDecodeBin * dec)
+    GstCaps * caps, GstElementFactory * factory, GstURIDecodeBin * dec)
 {
-  gint result;
+  GstAutoplugSelectResult result;
 
   g_signal_emit (G_OBJECT (dec),
-      gst_uri_decode_bin_signals[SIGNAL_AUTOPLUG_SELECT], 0, pad, caps, array,
+      gst_uri_decode_bin_signals[SIGNAL_AUTOPLUG_SELECT], 0, pad, caps, factory,
       &result);
 
   GST_DEBUG_OBJECT (dec, "autoplug-select returned %d", result);
@@ -1558,8 +1586,10 @@ setup_failed:
   }
 }
 
+gboolean gst_decode_bin_plugin_init (GstPlugin * plugin);
+
 static gboolean
-plugin_init (GstPlugin * plugin)
+gst_uri_decode_bin_plugin_init (GstPlugin * plugin)
 {
   GST_DEBUG_CATEGORY_INIT (gst_uri_decode_bin_debug, "uridecodebin", 0,
       "URI decoder element");
@@ -1574,6 +1604,17 @@ plugin_init (GstPlugin * plugin)
       GST_TYPE_URI_DECODE_BIN);
 }
 
+static gboolean
+plugin_init (GstPlugin * plugin)
+{
+  if (!gst_decode_bin_plugin_init (plugin))
+    return FALSE;
+  if (!gst_uri_decode_bin_plugin_init (plugin))
+    return FALSE;
+
+  return TRUE;
+}
+
 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
     GST_VERSION_MINOR,
     "uridecodebin",