summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicolas Dufresne <nicolas.dufresne@collabora.com>2011-10-07 18:21:52 -0400
committerDamien Lespiau <damien.lespiau@intel.com>2011-11-07 15:34:56 +0000
commite165f2b5ea4757a1d1c56fe75f6b3ec82e719398 (patch)
tree7e1f2168d894f1803f083c9b9295007d93c07444
parentac0dc977f1e0cca9ce72c0d72d771dc36c0f47e6 (diff)
downloadclutter-gst-e165f2b5ea4757a1d1c56fe75f6b3ec82e719398.tar.gz
Add HW accelerated element support
-rw-r--r--clutter-gst/Makefile.am5
-rw-r--r--clutter-gst/clutter-gst-player.c44
-rw-r--r--clutter-gst/clutter-gst-util.c16
-rw-r--r--clutter-gst/clutter-gst-video-sink.c121
-rw-r--r--configure.ac30
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 ""