[clutter-gst] Add HW accelerated element support



commit e165f2b5ea4757a1d1c56fe75f6b3ec82e719398
Author: Nicolas Dufresne <nicolas dufresne collabora com>
Date:   Fri Oct 7 18:21:52 2011 -0400

    Add HW accelerated element support

 clutter-gst/Makefile.am              |    5 +-
 clutter-gst/clutter-gst-player.c     |   44 ++++++++++++
 clutter-gst/clutter-gst-util.c       |   16 +++++
 clutter-gst/clutter-gst-video-sink.c |  121 ++++++++++++++++++++++++++++++++--
 configure.ac                         |   30 +++++++--
 5 files changed, 202 insertions(+), 14 deletions(-)
---
diff --git a/clutter-gst/Makefile.am b/clutter-gst/Makefile.am
index 47ca24d..4201e4f 100644
--- a/clutter-gst/Makefile.am
+++ b/clutter-gst/Makefile.am
@@ -75,11 +75,12 @@ AM_CFLAGS = 				\
 	$(CLUTTER_GST_DEBUG_CFLAGS)	\
 	$(CLUTTER_GST_CFLAGS)		\
 	$(GST_CFLAGS)			\
+	$(HW_CFLAGS)			\
 	$(NULL)
 
 lib_LTLIBRARIES = libclutter-gst- CLUTTER_GST_MAJORMINOR@.la
 
-libclutter_gst_ CLUTTER_GST_MAJORMINOR@_la_LIBADD  = @CLUTTER_GST_LIBS@ $(GST_LIBS)
+libclutter_gst_ CLUTTER_GST_MAJORMINOR@_la_LIBADD  = @CLUTTER_GST_LIBS@ $(GST_LIBS) $(HW_LIBS)
 libclutter_gst_ CLUTTER_GST_MAJORMINOR@_la_LDFLAGS =	\
 	$(CLUTTER_GST_LT_LDFLAGS)			\
 	$(GL_LDFLAGS)					\
@@ -105,7 +106,7 @@ libgstclutter_la_SOURCES =	\
 
 plugin_LTLIBRARIES = libgstclutter.la
 
-libgstclutter_la_LIBADD  = $(PLUGIN_LIBS)
+libgstclutter_la_LIBADD  = $(PLUGIN_LIBS) $(HW_LIBS)
 libgstclutter_la_LDFLAGS =	\
 	$(GL_LDFLAGS)		\
 	-module -avoid-version	\
diff --git a/clutter-gst/clutter-gst-player.c b/clutter-gst/clutter-gst-player.c
index d7ba013..b838de0 100644
--- a/clutter-gst/clutter-gst-player.c
+++ b/clutter-gst/clutter-gst-player.c
@@ -57,6 +57,13 @@
 #include "clutter-gst-player.h"
 #include "clutter-gst-private.h"
 
+#if CLUTTER_WINDOWING_X11 && HAVE_HW_DECODER_SUPPORT
+#define GST_USE_UNSTABLE_API 1
+#include <gst/video/videocontext.h>
+#include <clutter/x11/clutter-x11.h>
+#endif
+
+
 typedef ClutterGstPlayerIface       ClutterGstPlayerInterface;
 
 G_DEFINE_INTERFACE_WITH_CODE (ClutterGstPlayer, clutter_gst_player, G_TYPE_OBJECT,
@@ -1876,6 +1883,38 @@ clutter_gst_player_get_idle_impl (ClutterGstPlayer *player)
 
 /**/
 
+#if CLUTTER_WINDOWING_X11 && HAVE_HW_DECODER_SUPPORT
+static GstBusSyncReply
+on_sync_message (GstBus * bus, GstMessage * message, gpointer user_data)
+{
+  Display *display = user_data;
+  GstVideoContext *context;
+  const gchar **types;
+
+  if (gst_video_context_message_parse_prepare (message, &types, &context)) {
+    gint i;
+
+    for (i = 0; types[i]; i++) {
+
+      if (!strcmp(types[i], "x11-display")) {
+        gst_video_context_set_context_pointer (context, "x11-display", display);
+      }
+      else if (!strcmp(types[i], "x11-display-name")) {
+        gst_video_context_set_context_string (context, "x11-display-name",
+            DisplayString (display));
+      } else {
+        continue;
+      }
+
+      gst_message_unref (message);
+      return GST_BUS_DROP;
+    }
+  }
+
+  return GST_BUS_PASS;
+}
+#endif
+
 /**
  * clutter_gst_player_init:
  * @player: a #ClutterGstPlayer
@@ -1992,6 +2031,11 @@ clutter_gst_player_init (ClutterGstPlayer *player)
                     G_CALLBACK (on_current_text_changed),
                     player);
 
+#if CLUTTER_WINDOWING_X11 && HAVE_HW_DECODER_SUPPORT
+  gst_bus_set_sync_handler (priv->bus, on_sync_message,
+      clutter_x11_get_default_display ());
+#endif
+
   gst_object_unref (GST_OBJECT (priv->bus));
 
   return TRUE;
diff --git a/clutter-gst/clutter-gst-util.c b/clutter-gst/clutter-gst-util.c
index f344ede..a57b9e2 100644
--- a/clutter-gst/clutter-gst-util.c
+++ b/clutter-gst/clutter-gst-util.c
@@ -94,9 +94,15 @@
  * </example>
  */
 
+#include "config.h"
+
 #include <gst/gst.h>
 #include <clutter/clutter.h>
 
+#if CLUTTER_WINDOWING_X11
+#include <X11/Xlib.h>
+#endif
+
 #include "clutter-gst-debug.h"
 #include "clutter-gst-video-sink.h"
 #include "clutter-gst-util.h"
@@ -125,6 +131,11 @@ clutter_gst_init (int    *argc,
   if (clutter_gst_is_initialized)
     return CLUTTER_INIT_SUCCESS;
 
+#if CLUTTER_WINDOWING_X11
+  /* Required by some GStreamer element like VA */
+  XInitThreads ();
+#endif
+
   gst_init (argc, argv);
   retval = clutter_init (argc, argv);
 
@@ -179,6 +190,11 @@ clutter_gst_init_with_args (int            *argc,
   if (clutter_gst_is_initialized)
     return CLUTTER_INIT_SUCCESS;
 
+#if CLUTTER_WINDOWING_X11
+  /* Required by some gstreamer element like VA */
+  XInitThreads ();
+#endif
+
   context = g_option_context_new (parameter_string);
 
   g_option_context_add_group (context, gst_init_get_option_group ());
diff --git a/clutter-gst/clutter-gst-video-sink.c b/clutter-gst/clutter-gst-video-sink.c
index 94718a2..b6984d0 100644
--- a/clutter-gst/clutter-gst-video-sink.c
+++ b/clutter-gst/clutter-gst-video-sink.c
@@ -59,6 +59,11 @@
 #include <gst/interfaces/navigation.h>
 #include <gst/riff/riff-ids.h>
 
+#ifdef HAVE_HW_DECODER_SUPPORT
+#define GST_USE_UNSTABLE_API 1
+#include <gst/video/gstsurfacebuffer.h>
+#endif
+
 #include <glib.h>
 #include <string.h>
 
@@ -106,17 +111,25 @@ static gchar *yv12_to_rgba_shader = \
      FRAGMENT_SHADER_END
      "}";
 
+#define BASE_SINK_CAPS GST_VIDEO_CAPS_YUV("AYUV") ";" \
+                       GST_VIDEO_CAPS_YUV("YV12") ";" \
+                       GST_VIDEO_CAPS_YUV("I420") ";" \
+                       GST_VIDEO_CAPS_RGBA        ";" \
+                       GST_VIDEO_CAPS_BGRA        ";" \
+                       GST_VIDEO_CAPS_RGB         ";" \
+                       GST_VIDEO_CAPS_BGR
+
+#ifdef HAVE_HW_DECODER_SUPPORT
+#define SINK_CAPS GST_VIDEO_CAPS_SURFACE ";" BASE_SINK_CAPS
+#else
+#define SINK_CAPS BASE_SINK_CAPS
+#endif
+
 static GstStaticPadTemplate sinktemplate_all
  = GST_STATIC_PAD_TEMPLATE ("sink",
                             GST_PAD_SINK,
                             GST_PAD_ALWAYS,
-                            GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV("AYUV") ";" \
-                                             GST_VIDEO_CAPS_YUV("YV12") ";" \
-                                             GST_VIDEO_CAPS_YUV("I420") ";" \
-                                             GST_VIDEO_CAPS_RGBA        ";" \
-                                             GST_VIDEO_CAPS_BGRA        ";" \
-                                             GST_VIDEO_CAPS_RGB         ";" \
-                                             GST_VIDEO_CAPS_BGR));
+                            GST_STATIC_CAPS (SINK_CAPS));
 
 GST_DEBUG_CATEGORY_STATIC (clutter_gst_video_sink_debug);
 #define GST_CAT_DEFAULT clutter_gst_video_sink_debug
@@ -144,6 +157,7 @@ typedef enum
   CLUTTER_GST_AYUV,
   CLUTTER_GST_YV12,
   CLUTTER_GST_I420,
+  CLUTTER_GST_SURFACE
 } ClutterGstVideoFormat;
 
 /*
@@ -221,6 +235,10 @@ struct _ClutterGstVideoSinkPrivate
   ClutterGstRenderer      *renderer;
 
   GArray                  *signal_handler_ids;
+
+#ifdef HAVE_HW_DECODER_SUPPORT
+  GstSurfaceConverter     *converter;
+#endif
 };
 
 #define GstNavigationClass GstNavigationInterface
@@ -367,6 +385,12 @@ clutter_gst_parse_caps (GstCaps             *caps,
       format = CLUTTER_GST_AYUV;
       bgr = FALSE;
     }
+#ifdef HAVE_HW_DECODER_SUPPORT
+  else if (gst_structure_has_name (structure, GST_VIDEO_CAPS_SURFACE))
+    {
+      format = CLUTTER_GST_SURFACE;
+    }
+#endif
   else
     {
       guint32 mask;
@@ -934,6 +958,86 @@ static ClutterGstRenderer ayuv_glsl_renderer =
   clutter_gst_ayuv_upload,
 };
 
+/*
+ * HW Surfaces
+ */
+
+#ifdef HAVE_HW_DECODER_SUPPORT
+static void
+clutter_gst_hw_init (ClutterGstVideoSink *sink)
+{
+  ClutterGstVideoSinkPrivate *priv = sink->priv;
+  CoglHandle tex;
+  CoglHandle material;
+
+  /* Default texture is 1x1, let's replace it with one big enough. */
+  tex = cogl_texture_new_with_size (priv->width, priv->height,
+                                    CLUTTER_GST_TEXTURE_FLAGS,
+                                    COGL_PIXEL_FORMAT_BGRA_8888);
+
+  material = cogl_material_new ();
+  cogl_material_set_layer (material, 0, tex);
+  clutter_texture_set_cogl_material (priv->texture, material);
+
+  cogl_object_unref (tex);
+  cogl_object_unref (material);
+}
+
+static void
+clutter_gst_hw_deinit (ClutterGstVideoSink *sink)
+{
+  ClutterGstVideoSinkPrivate *priv = sink->priv;
+
+  if (priv->converter != NULL)
+    g_object_unref (priv->converter);
+  priv->converter = NULL;
+}
+
+static void
+clutter_gst_hw_upload (ClutterGstVideoSink *sink,
+                       GstBuffer           *buffer)
+{
+  ClutterGstVideoSinkPrivate *priv = sink->priv;
+  GstSurfaceBuffer *surface;
+
+  g_return_if_fail (GST_IS_SURFACE_BUFFER (buffer));
+  surface = GST_SURFACE_BUFFER (buffer);
+
+  if (G_UNLIKELY (priv->converter == NULL)) {
+    CoglHandle tex;
+    GLuint gl_texture;
+    GLenum gl_target;
+    GValue value = {0};
+
+    tex = clutter_texture_get_cogl_texture (priv->texture);
+    cogl_texture_get_gl_texture (tex, &gl_texture, &gl_target);
+    g_return_if_fail (gl_target == GL_TEXTURE_2D);
+
+    g_value_init (&value, G_TYPE_UINT);
+    g_value_set_uint (&value, gl_texture);
+
+    priv->converter = gst_surface_buffer_create_converter (surface, "opengl", &value);
+    g_return_if_fail (priv->converter);
+  }
+
+  gst_surface_converter_upload (priv->converter, surface);
+
+  /* The texture is dirty, schedule a redraw */
+  clutter_actor_queue_redraw (CLUTTER_ACTOR (priv->texture));
+}
+
+static ClutterGstRenderer hw_renderer =
+{
+  "HW surface",
+  CLUTTER_GST_SURFACE,
+  0,
+  GST_STATIC_CAPS (GST_VIDEO_CAPS_SURFACE ", opengl=true"),
+  clutter_gst_hw_init,
+  clutter_gst_hw_deinit,
+  clutter_gst_hw_upload,
+};
+#endif
+
 static GSList *
 clutter_gst_build_renderers_list (void)
 {
@@ -955,6 +1059,9 @@ clutter_gst_build_renderers_list (void)
       &i420_fp_renderer,
 #endif
       &ayuv_glsl_renderer,
+#ifdef HAVE_HW_DECODER_SUPPORT
+      &hw_renderer,
+#endif
       NULL
     };
 
diff --git a/configure.ac b/configure.ac
index cbd9864..f4b500a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -79,6 +79,7 @@ AC_SUBST([CLUTTER_GST_RELEASE_STATUS], [clutter_gst_release_status])
 GLIB_REQ_VERSION=2.18.0
 CLUTTER_REQ_VERSION=1.6.0
 GSTREAMER_REQ_VERSION=0.10.26
+GST_PLUGINS_BAD_REQ_VERSION=0.10.22.1
 
 AC_SUBST(GLIB_REQ_VERSION)
 AC_SUBST(CLUTTER_REQ_VERSION)
@@ -136,22 +137,29 @@ AM_CONDITIONAL([HAVE_PYTHON], [test "x$have_python" = "xyes"])
 
 dnl ========================================================================
 
-pkg_modules="clutter-1.0 >= $CLUTTER_REQ_VERSION gio-2.0 >= $GLIB_REQ_VERSION"
-PKG_CHECK_MODULES(CLUTTER_GST, [$pkg_modules])
+PKG_CHECK_MODULES(CLUTTER_GST,
+                  [clutter-1.0 >= $CLUTTER_REQ_VERSION
+                   gio-2.0 >= $GLIB_REQ_VERSION])
 
 dnl ========================================================================
 
 GST_MAJORMINOR=0.10
 
-pkg_modules="gstreamer-$GST_MAJORMINOR >= $GSTREAMER_REQ_VERSION gstreamer-plugins-base-$GST_MAJORMINOR gstreamer-base-$GST_MAJORMINOR gstreamer-interfaces-$GST_MAJORMINOR gstreamer-video-$GST_MAJORMINOR gstreamer-audio-$GST_MAJORMINOR gstreamer-tag-$GST_MAJORMINOR"
-PKG_CHECK_MODULES(GST, [$pkg_modules])
+PKG_CHECK_MODULES(GST,
+                  [gstreamer-$GST_MAJORMINOR >= $GSTREAMER_REQ_VERSION
+                   gstreamer-plugins-base-$GST_MAJORMINOR
+                   gstreamer-base-$GST_MAJORMINOR
+                   gstreamer-interfaces-$GST_MAJORMINOR
+                   gstreamer-video-$GST_MAJORMINOR
+                   gstreamer-audio-$GST_MAJORMINOR
+                   gstreamer-tag-$GST_MAJORMINOR])
 
 dnl libs used by the plugin
 PKG_CHECK_MODULES([PLUGIN],
                   [clutter-1.0 >= $CLUTTER_REQ_VERSION
                    gstreamer-$GST_MAJORMINOR >= $GSTREAMER_REQ_VERSION
                    gstreamer-base-$GST_MAJORMINOR
-                   gstreamer-interfaces-$GST_MAJORMINOR])
+                   gstreamer-interfaces-$GST_MAJORMINOR ])
 
 dnl define location of gstreamer plugin directory
 plugindir="\$(libdir)/gstreamer-$GST_MAJORMINOR"
@@ -202,6 +210,17 @@ AS_IF([test "x$have_cogl_1_8" != xyes],
       ])
 
 dnl ========================================================================
+dnl Experimental support for hardware accelerated decoders.
+
+PKG_CHECK_MODULES(HW,
+                 [gstreamer-basevideo-$GST_MAJORMINOR >= $GST_PLUGINS_BAD_REQ_VERSION],
+                 [
+                   have_hw_decoder_support=yes
+                   AC_DEFINE([HAVE_HW_DECODER_SUPPORT], [1],
+                             ["Defined if building Clutter with HW decoder support"])
+                 ],[ have_hw_decoder_support=no ])
+
+dnl ========================================================================
 
 m4_define([maintainer_default], [m4_if(clutter_gst_release_status,
                                        [git], [yes], [no])])
@@ -303,4 +322,5 @@ echo ""
 echo " â Extra:"
 echo "        API documentation : ${enable_gtk_doc}"
 echo "        Introspection data: ${enable_introspection}"
+echo "        HW Decoder support: ${have_hw_decoder_support}"
 echo ""



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]