diff options
author | Nicolas Dufresne <nicolas.dufresne@collabora.com> | 2011-10-07 18:21:52 -0400 |
---|---|---|
committer | Damien Lespiau <damien.lespiau@intel.com> | 2011-11-07 15:34:56 +0000 |
commit | e165f2b5ea4757a1d1c56fe75f6b3ec82e719398 (patch) | |
tree | 7e1f2168d894f1803f083c9b9295007d93c07444 | |
parent | ac0dc977f1e0cca9ce72c0d72d771dc36c0f47e6 (diff) | |
download | clutter-gst-e165f2b5ea4757a1d1c56fe75f6b3ec82e719398.tar.gz |
Add HW accelerated element support
-rw-r--r-- | clutter-gst/Makefile.am | 5 | ||||
-rw-r--r-- | clutter-gst/clutter-gst-player.c | 44 | ||||
-rw-r--r-- | clutter-gst/clutter-gst-util.c | 16 | ||||
-rw-r--r-- | clutter-gst/clutter-gst-video-sink.c | 121 | ||||
-rw-r--r-- | 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 "" |