[Cogl] [PATCH] cogl-gst: Upgrade cogl-gst to gstreamer-1.0

Plamena Manolova plamena.n.manolova at intel.com
Thu Feb 28 10:14:54 PST 2013


Upgrades cogl-gst to gstreamer-1.0 and gets rid
of the cogl-gst-video-player utility. Implements
cogl-gst-video-sink-new, but keeps plugin
registered for user convinience.
---
 cogl-gst/Makefile.am               |  30 +-
 cogl-gst/cogl-gst-video-player.c   | 273 -------------
 cogl-gst/cogl-gst-video-player.h   | 121 ------
 cogl-gst/cogl-gst-video-sink.c     | 772 +++++++++++++++++++++++--------------
 cogl-gst/cogl-gst-video-sink.h     |   4 +
 configure.ac                       |  12 +-
 examples/cogl-basic-video-player.c |  43 ++-
 7 files changed, 546 insertions(+), 709 deletions(-)
 delete mode 100644 cogl-gst/cogl-gst-video-player.c
 delete mode 100644 cogl-gst/cogl-gst-video-player.h

diff --git a/cogl-gst/Makefile.am b/cogl-gst/Makefile.am
index 316656e..d2afa93 100644
--- a/cogl-gst/Makefile.am
+++ b/cogl-gst/Makefile.am
@@ -9,13 +9,12 @@ EXTRA_DIST =
 
 source_c = \
 	cogl-gst-shader.c \
-	cogl-gst-video-player.c \
 	cogl-gst-video-sink.c \
 	$(NULL)
 
 source_h = \
 	cogl-gst.h \
-	cogl-gst-video-player.h \
+	cogl-gst-shader.h \
 	cogl-gst-video-sink.h \
 	$(NULL)
 
@@ -32,7 +31,8 @@ libcogl_gst_la_LDFLAGS = \
 	-export-dynamic \
 	-export-symbols-regex "^cogl_gst_.*" \
 	-no-undefined \
-	-version-info @COGL_LT_CURRENT@:@COGL_LT_REVISION@:@COGL_LT_AGE@
+	-version-info @COGL_LT_CURRENT@:@COGL_LT_REVISION@:@COGL_LT_AGE@ \
+	-rpath $(libdir)
 
 AM_CPPFLAGS = \
 	-DCOGL_COMPILATION		\
@@ -43,9 +43,31 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)			\
 	-I$(top_builddir)
 
-cogl_gstheadersdir = $(includedir)/cogl/cogl-gst
+cogl_gstheadersdir = $(includedir)/cogl2/cogl-gst
 cogl_gstheaders_HEADERS = $(source_h)
 
+plugin_source_c = 				\
+  $(srcdir)/cogl-gst.h \
+  $(srcdir)/cogl-gst-shader.c \
+  $(srcdir)/cogl-gst-shader.h \
+	$(srcdir)/cogl-gst-video-sink.c	\
+	$(srcdir)/cogl-gst-video-sink.h	\
+	$(NULL)
+
+libgstcogl_la_SOURCES =	\
+	$(plugin_source_c)      \
+	$(NULL)
+
+plugin_LTLIBRARIES = libgstcogl.la
+
+libgstcogl_la_CFLAGS = $(COGL_DEP_CFLAGS) $(COGL_GST_DEP_CFLAGS) $(COGL_EXTRA_CFLAGS) $(MAINTAINER_CFLAGS)
+libgstcogl_la_LIBADD = $(top_builddir)/cogl/libcogl2.la
+libgstcogl_la_LIBADD += $(COGL_DEP_LIBS) $(COGL_GST_DEP_LIBS) $(COGL_EXTRA_LDFLAGS)
+libgstcogl_la_LDFLAGS =	\
+	-avoid-version -no-undefined		\
+	$(NULL)
+
+
 pc_files = cogl-gst.pc
 
 pkgconfigdir = $(libdir)/pkgconfig
diff --git a/cogl-gst/cogl-gst-video-player.c b/cogl-gst/cogl-gst-video-player.c
deleted file mode 100644
index e5800a9..0000000
--- a/cogl-gst/cogl-gst-video-player.c
+++ /dev/null
@@ -1,273 +0,0 @@
-/*
- * Cogl-GStreamer.
- *
- * GStreamer integration library for Cogl.
- *
- * cogl-gst-video-player.c - A basic video player for user convinience.
- *
- * Authored by Plamena Manolova  <plamena.n.manolova at intel.com>
- *
- * Copyright (C) 2013 Intel Corporation
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "cogl-gst-video-player.h"
-
-G_DEFINE_TYPE (CoglGstVideoPlayer, cogl_gst_video_player, G_TYPE_OBJECT);
-
-#define COGL_GST_VIDEO_PLAYER_GET_PRIVATE(obj) \
-  (G_TYPE_INSTANCE_GET_PRIVATE ((obj), COGL_GST_TYPE_VIDEO_PLAYER, \
-                                CoglGstVideoPlayerPrivate))
-
-struct _CoglGstVideoPlayerPrivate
-{
-  CoglContext *ctx;
-  GstElement *sink;
-  GstElement *pipeline;
-  GstElement *bin;
-  char *uri;
-  unsigned int bus_watch;
-};
-
-#define COGL_GST_SEEK_FLAGS (GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_KEY_UNIT)
-
-enum
-{
-  PROP_0,
-  PROP_COGL_CONTEXT
-};
-
-static void
-cogl_gst_video_player_set_property (GObject *object,
-                                    unsigned int prop_id,
-                                    const GValue *value,
-                                    GParamSpec *pspec)
-{
-  CoglGstVideoPlayer *player = COGL_GST_VIDEO_PLAYER (object);
-  CoglGstVideoPlayerPrivate *priv = player->priv;
-
-  switch (prop_id)
-    {
-    case PROP_COGL_CONTEXT:
-      priv->ctx = cogl_object_ref (g_value_get_pointer (value));
-      break;
-
-     default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-   }
-}
-
-static void
-cogl_gst_video_player_finalize (GObject *object)
-{
-  CoglGstVideoPlayer *player = COGL_GST_VIDEO_PLAYER (object);
-  CoglGstVideoPlayerPrivate *priv = player->priv;
-
-  if (priv->ctx)
-    cogl_object_unref (priv->ctx);
-
-  G_OBJECT_CLASS (cogl_gst_video_player_parent_class)->finalize (object);
-}
-
-static void
-cogl_gst_video_player_class_init (CoglGstVideoPlayerClass *klass)
-{
-  GObjectClass *object_class = G_OBJECT_CLASS (klass);
-  GParamSpec *pspec;
-
-  object_class->set_property = cogl_gst_video_player_set_property;
-  object_class->finalize = cogl_gst_video_player_finalize;
-
-  g_type_class_add_private (klass, sizeof (CoglGstVideoPlayerPrivate));
-
-  pspec = g_param_spec_pointer ("cogl-context",
-                                "The Cogl Context",
-                                "The Cogl Context",
-                                G_PARAM_WRITABLE |
-                                G_PARAM_CONSTRUCT_ONLY |
-                                G_PARAM_STATIC_NAME |
-                                G_PARAM_STATIC_NICK |
-                                G_PARAM_STATIC_BLURB);
-  g_object_class_install_property (object_class, PROP_COGL_CONTEXT, pspec);
-}
-
-static void
-cogl_gst_video_player_init (CoglGstVideoPlayer *self)
-{
-  self->priv = COGL_GST_VIDEO_PLAYER_GET_PRIVATE (self);
-}
-
-static void
-_cogl_gst_prepare_new_video_pipeline (CoglContext *ctx,
-                                      CoglGstVideoPlayer *player,
-                                      char *uri)
-{
-  CoglGstVideoPlayerPrivate* priv = player->priv;
-  priv->pipeline = gst_pipeline_new ("gst-player");
-  priv->bin = gst_element_factory_make ("playbin", "bin");
-  priv->sink = gst_element_factory_make ("coglsink", "videosink");
-  priv->uri = uri;
-  priv->ctx = ctx;
-  priv->bus_watch = 0;
-
-  cogl_gst_video_sink_set_context (COGL_GST_VIDEO_SINK (priv->sink), ctx);
-
-  g_object_set (G_OBJECT (priv->bin), "video-sink", priv->sink, NULL);
-
-
-  gst_bin_add (GST_BIN (priv->pipeline), priv->bin);
-
-  if (priv->uri != NULL)
-    g_object_set (G_OBJECT (priv->bin), "uri", priv->uri, NULL);
-}
-
-CoglGstVideoPlayer*
-cogl_gst_video_player_new (CoglContext *ctx,
-                           CoglBool play,
-                           char *uri)
-{
-  CoglGstVideoPlayer *player =
-    g_object_new (COGL_GST_TYPE_VIDEO_PLAYER,
-                  "cogl-context", ctx,
-                  NULL);
-
-  _cogl_gst_prepare_new_video_pipeline (ctx, player, uri);
-
-  if (play == TRUE)
-    cogl_gst_play_video (player, player->priv->uri);
-
-  return player;
-}
-
-void
-cogl_gst_play_video (CoglGstVideoPlayer *player,
-                     char *uri)
-{
-  if (uri)
-    {
-      cogl_gst_video_player_stop (player);
-      _cogl_gst_prepare_new_video_pipeline (player->priv->ctx, player, uri);
-      gst_element_set_state (player->priv->pipeline, GST_STATE_PLAYING);
-    }
-  else
-    {
-      gst_element_set_state (player->priv->pipeline, GST_STATE_NULL);
-      g_error ("COGL-GST: Invalid uri");
-    }
-}
-
-CoglGstVideoSink*
-cogl_gst_video_player_get_sink (CoglGstVideoPlayer *player)
-{
-  return COGL_GST_VIDEO_SINK (player->priv->sink);
-}
-
-void
-cogl_gst_video_player_add_bus_watch (CoglGstVideoPlayer *player,
-                                     GstBusFunc func,
-                                     void *user_data)
-{
-  GstBus *bus;
-  bus = gst_pipeline_get_bus (GST_PIPELINE (player->priv->pipeline));
-  if (player->priv->bus_watch != 0)
-    g_source_remove (player->priv->bus_watch);
-
-  player->priv->bus_watch = gst_bus_add_watch (bus, func, user_data);
-  gst_object_unref (bus);
-}
-
-void
-cogl_gst_video_player_stop (CoglGstVideoPlayer *player)
-{
-  if (player->priv->pipeline)
-    {
-      gst_element_set_state (player->priv->pipeline, GST_STATE_NULL);
-      gst_object_unref (GST_OBJECT (player->priv->pipeline));
-    }
-}
-
-void
-cogl_gst_video_player_reset (CoglGstVideoPlayer *player)
-{
-  gst_element_seek (player->priv->pipeline, 1.0,
-                    GST_FORMAT_TIME, COGL_GST_SEEK_FLAGS,
-                    GST_SEEK_TYPE_SET, 0, GST_SEEK_TYPE_NONE,
-                    GST_CLOCK_TIME_NONE);
-}
-
-void
-cogl_gst_video_player_pause (CoglGstVideoPlayer *player)
-{
-  gst_element_set_state (player->priv->pipeline, GST_STATE_PAUSED);
-}
-
-void
-cogl_gst_video_player_resume (CoglGstVideoPlayer *player)
-{
-  gst_element_set_state (player->priv->pipeline, GST_STATE_PLAYING);
-}
-
-void
-cogl_gst_video_player_seek (CoglGstVideoPlayer *player,
-                            int value)
-{
-  gst_element_seek (player->priv->pipeline, 1.0,
-                    GST_FORMAT_TIME, COGL_GST_SEEK_FLAGS,
-                    GST_SEEK_TYPE_CUR, value * GST_SECOND, GST_SEEK_TYPE_NONE,
-                    GST_CLOCK_TIME_NONE);
-}
-
-void
-cogl_gst_video_player_seek_absolute (CoglGstVideoPlayer *player,
-                                     uint64_t value)
-{
-  gst_element_seek (player->priv->pipeline, 1.0, GST_FORMAT_TIME,
-                    COGL_GST_SEEK_FLAGS,
-                    GST_SEEK_TYPE_SET, value, GST_SEEK_TYPE_NONE,
-                    GST_CLOCK_TIME_NONE);
-}
-
-int64_t
-cogl_gst_video_player_get_progress (CoglGstVideoPlayer *player)
-{
-  GstFormat format = GST_FORMAT_TIME;
-  int64_t prog;
-
-  gst_element_query_position (player->priv->pipeline, &format, &prog);
-  if (format != GST_FORMAT_TIME)
-    return GST_CLOCK_TIME_NONE;
-
-  return prog;
-}
-
-int64_t
-cogl_gst_video_player_get_duration (CoglGstVideoPlayer *player)
-{
-  GstFormat format = GST_FORMAT_TIME;
-  int64_t dur;
-
-  gst_element_query_duration (player->priv->pipeline, &format, &dur);
-  if (format != GST_FORMAT_TIME)
-    return GST_CLOCK_TIME_NONE;
-
-  return dur;
-}
diff --git a/cogl-gst/cogl-gst-video-player.h b/cogl-gst/cogl-gst-video-player.h
deleted file mode 100644
index d83aa30..0000000
--- a/cogl-gst/cogl-gst-video-player.h
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * Cogl-GStreamer.
- *
- * GStreamer integration library for Cogl.
- *
- * cogl-gst-video-player.h - A basic video player for user convinience.
- *
- * Authored by Plamena Manolova  <plamena.n.manolova at intel.com>
- *
- * Copyright (C) 2013 Intel Corporation
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifndef __COGL_GST_VIDEO_PLAYER_H__
-#define __COGL_GST_VIDEO_PLAYER_H__
-
-#include <cogl-gst/cogl-gst-video-sink.h>
-
-G_BEGIN_DECLS
-
-#define COGL_GST_TYPE_VIDEO_PLAYER cogl_gst_video_player_get_type()
-
-#define COGL_GST_VIDEO_PLAYER(obj) \
-  (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
-  COGL_GST_TYPE_VIDEO_PLAYER, CoglGstVideoPlayer))
-
-#define COGL_GST_VIDEO_PLAYER_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_CAST ((klass), \
-  COGL_GST_TYPE_VIDEO_PLAYER, CoglGstVideoPlayerClass))
-
-#define COGL_GST_IS_VIDEO_PLAYER(obj) \
-  (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
-  COGL_GST_TYPE_VIDEO_PLAYER))
-
-#define COGL_GST_IS_VIDEO_PLAYER_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_TYPE ((klass), \
-  COGL_GST_TYPE_VIDEO_PLAYER))
-
-#define COGL_GST_VIDEO_PLAYER_GET_CLASS(obj) \
-  (G_TYPE_INSTANCE_GET_CLASS ((obj), \
-  COGL_GST_TYPE_VIDEO_PLAYER, CoglGstVideoPlayerClass))
-
-
-typedef struct _CoglGstVideoPlayer   CoglGstVideoPlayer;
-typedef struct _CoglGstVideoPlayerClass   CoglGstVideoPlayerClass;
-typedef struct _CoglGstVideoPlayerPrivate CoglGstVideoPlayerPrivate;
-typedef struct _CoglGstVideoPlayerPrivate CoglGstVideoPlayerPrivate;
-
-struct _CoglGstVideoPlayer
-{
-  GObject parent;
-  CoglGstVideoPlayerPrivate *priv;
-};
-
-struct _CoglGstVideoPlayerClass
-{
-  GObjectClass parent_class;
-};
-
-GType cogl_gst_video_player_get_type (void) G_GNUC_CONST;
-
-CoglGstVideoPlayer*
-cogl_gst_video_player_new (CoglContext *ctx,
-                           CoglBool play,
-                           char *uri);
-
-void
-cogl_gst_play_video (CoglGstVideoPlayer* player,
-                     char* uri);
-
-CoglGstVideoSink*
-cogl_gst_video_player_get_sink (CoglGstVideoPlayer *player);
-
-void
-cogl_gst_video_player_add_bus_watch (CoglGstVideoPlayer *player,
-                                     GstBusFunc func,
-                                     void *user_data);
-
-void
-cogl_gst_video_player_stop (CoglGstVideoPlayer* player);
-
-void
-cogl_gst_video_player_reset (CoglGstVideoPlayer *player);
-
-void
-cogl_gst_video_player_pause (CoglGstVideoPlayer *player);
-
-void
-cogl_gst_video_player_resume (CoglGstVideoPlayer *player);
-
-void
-cogl_gst_video_player_seek (CoglGstVideoPlayer *player,
-                            int value);
-
-void
-cogl_gst_video_player_seek_absolute (CoglGstVideoPlayer *player,
-                                     uint64_t value);
-
-int64_t
-cogl_gst_video_player_get_progress (CoglGstVideoPlayer *player);
-
-int64_t
-cogl_gst_video_player_get_duration (CoglGstVideoPlayer *player);
-
-G_END_DECLS
-
-#endif
diff --git a/cogl-gst/cogl-gst-video-sink.c b/cogl-gst/cogl-gst-video-sink.c
index 5bbd651..52ce311 100644
--- a/cogl-gst/cogl-gst-video-sink.c
+++ b/cogl-gst/cogl-gst-video-sink.c
@@ -47,27 +47,32 @@
 
 #define COGL_GST_TEXTURE_FLAGS \
        (COGL_TEXTURE_NO_SLICING | COGL_TEXTURE_NO_ATLAS)
-#define PACKAGE "GStreamer"
-#define VERSION "0.10"
+#define PACKAGE "CoglGst"
+#define VERSION "0.0"
 #define COGL_GST_DEFAULT_PRIORITY    (G_PRIORITY_HIGH_IDLE)
+#ifdef HAVE_HW_DECODER_SUPPORT
+#define GST_USE_UNSTABLE_API 1
+#include <gst/video/gstsurfacemeta.h>
+#endif
+
+#define BASE_SINK_CAPS "{ AYUV," \
+                       "YV12," \
+                       "I420," \
+                       "RGBA," \
+                       "BGRA," \
+                       "RGB," \
+                       "BGR }"
+
+
+#define SINK_CAPS GST_VIDEO_CAPS_MAKE(BASE_SINK_CAPS)
+
+static GstStaticPadTemplate sinktemplate_all = GST_STATIC_PAD_TEMPLATE ("sink",
+    GST_PAD_SINK,
+    GST_PAD_ALWAYS,
+    GST_STATIC_CAPS (SINK_CAPS));
 
-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));
-
-static GstElementDetails cogl_gst_video_sink_details =
-       GST_ELEMENT_DETAILS ("Cogl video sink", "Sink/Video",
-       "Sends video data from a GStreamer pipeline to a Cogl pipeline",
-       "Jonathan Matthew <jonathan at kaolin.wh9.net>, "
-       "Matthew Allum <mallum at o-hand.com, "
-       "Chris Lord <chris at o-hand.com>, "
-       "Plamena Manolova <plamena.n.manolova at intel.com>");
+#define cogl_gst_video_sink_parent_class parent_class
+G_DEFINE_TYPE (CoglGstVideoSink, cogl_gst_video_sink, GST_TYPE_BASE_SINK);
 
 enum
 {
@@ -82,7 +87,8 @@ typedef enum
   COGL_GST_RGB24,
   COGL_GST_AYUV,
   COGL_GST_YV12,
-  COGL_GST_I420,
+  COGL_GST_SURFACE,
+  COGL_GST_I420
 }CoglGstVideoFormat;
 
 typedef enum
@@ -96,6 +102,7 @@ typedef struct _CoglGstSource
   CoglGstVideoSink *sink;
   GMutex buffer_lock;
   GstBuffer *buffer;
+  CoglBool has_new_caps;
 }CoglGstSource;
 
 typedef void (CoglGstRendererPaint) (CoglGstVideoSink*);
@@ -109,45 +116,31 @@ typedef struct _CoglGstRenderer
   GstStaticCaps caps;
   void (*init)   (CoglGstVideoSink *sink);
   void (*deinit)  (CoglGstVideoSink *sink);
-  void (*upload) (CoglGstVideoSink *sink,
-                  GstBuffer *buffer);
+  CoglBool (*upload) (CoglGstVideoSink *sink,
+                      GstBuffer *buffer);
 }CoglGstRenderer;
 
-typedef enum _CoglGstRendererState
-{
-  COGL_GST_RENDERER_STOPPED,
-  COGL_GST_RENDERER_RUNNING,
-  COGL_GST_RENDERER_NEED_GC,
-}CoglGstRendererState;
-
 struct _CoglGstVideoSinkPrivate
 {
   CoglContext *ctx;
   CoglPipeline *pipeline;
   CoglGstVideoFormat format;
   CoglBool bgr;
-  int width;
-  int height;
-  int fps_n, fps_d;
-  int par_n, par_d;
-  int free_layer;
   CoglGstSource *source;
   GSList *renderers;
   GstCaps *caps;
   CoglGstRenderer *renderer;
-  CoglGstRendererState renderer_state;
   GMainContext *g_ctx;
   GMainLoop *loop;
   CoglSnippetHook hook;
+  GstFlowReturn flow_return;
+  int free_layer;
+  GstVideoInfo info;
+  #ifdef HAVE_HW_DECODER_SUPPORT
+  GstSurfaceConverter *converter;
+  #endif
 };
 
-
-GST_BOILERPLATE (CoglGstVideoSink,
-                 cogl_gst_video_sink,
-                 GstBaseSink,
-                 GST_TYPE_BASE_SINK
-                 );
-
 static void
 cogl_gst_source_finalize (GSource *source)
 {
@@ -161,27 +154,6 @@ cogl_gst_source_finalize (GSource *source)
   g_mutex_clear (&gst_source->buffer_lock);
 }
 
-static void
-cogl_gst_source_push (CoglGstSource *gst_source,
-                      GstBuffer *buffer)
-{
-  CoglGstVideoSinkPrivate *priv = gst_source->sink->priv;
-  g_mutex_lock (&gst_source->buffer_lock);
-  if (gst_source->buffer)
-    gst_buffer_unref (gst_source->buffer);
-  gst_source->buffer = gst_buffer_ref (buffer);
-  g_mutex_unlock (&gst_source->buffer_lock);
-
-  g_main_context_wakeup (priv->g_ctx);
-}
-
-void
-cogl_gst_set_shader_hook (CoglGstVideoSink *sink, CoglSnippetHook hook)
-{
-  sink->priv->hook = hook;
-}
-
-
 CoglPipeline*
 cogl_gst_video_sink_get_pipeline (CoglGstVideoSink *vt)
 {
@@ -219,72 +191,12 @@ cogl_gst_source_check (GSource *source)
   return gst_source->buffer != NULL;
 }
 
-static CoglBool
-cogl_gst_source_dispatch (GSource *source,
-                          GSourceFunc callback,
-                          void* user_data)
-{
-  CoglGstSource *gst_source= (CoglGstSource*) source;
-  CoglGstVideoSinkPrivate *priv = gst_source->sink->priv;
-  GstBuffer *buffer;
-
-  if (G_UNLIKELY (priv->renderer_state == COGL_GST_RENDERER_NEED_GC))
-    {
-      priv->renderer->deinit (gst_source->sink);
-      priv->renderer_state = COGL_GST_RENDERER_STOPPED;
-    }
-  if (G_UNLIKELY (priv->renderer_state == COGL_GST_RENDERER_STOPPED))
-    {
-      priv->renderer->init (gst_source->sink);
-      priv->renderer_state = COGL_GST_RENDERER_RUNNING;
-    }
-
-  g_mutex_lock (&gst_source->buffer_lock);
-  buffer = gst_source->buffer;
-  gst_source->buffer = NULL;
-  g_mutex_unlock (&gst_source->buffer_lock);
-
-  if (buffer)
-    {
-      priv->renderer->upload (gst_source->sink, buffer);
-      gst_buffer_unref (buffer);
-    }
-
-  return TRUE;
-}
-
-static GSourceFuncs gst_source_funcs =
-{
-  cogl_gst_source_prepare,
-  cogl_gst_source_check,
-  cogl_gst_source_dispatch,
-  cogl_gst_source_finalize
-};
-
-static CoglGstSource*
-cogl_gst_source_new (CoglGstVideoSink *sink)
-{
-  GSource *source;
-  CoglGstSource *gst_source;
-
-  source = g_source_new (&gst_source_funcs, sizeof (CoglGstSource));
-  gst_source = (CoglGstSource*) source;
-
-  g_source_set_can_recurse (source, TRUE);
-  g_source_set_priority (source, COGL_GST_DEFAULT_PRIORITY);
-
-  gst_source->sink = sink;
-  g_mutex_init (&gst_source->buffer_lock);
-  gst_source->buffer = NULL;
-
-  return gst_source;
-}
-
 static void
 cogl_gst_video_sink_set_priority (CoglGstVideoSink *sink,
                                   int priority)
 {
-  g_source_set_priority ((GSource*) sink->priv->source, priority);
+  if (sink->priv->source)
+    g_source_set_priority ((GSource*) sink->priv->source, priority);
 }
 
 static void
@@ -296,13 +208,8 @@ create_template_pipeline (CoglGstVideoSink *sink,
   priv->free_layer = n_layers;
 
   if (priv->pipeline)
-    {
-      CoglPipeline *pln = cogl_pipeline_copy (priv->pipeline);
-      cogl_object_unref (priv->pipeline);
-      priv->pipeline = pln;
-    }
-  else
-    priv->pipeline = cogl_pipeline_new (priv->ctx);
+    cogl_object_unref (priv->pipeline);
+  priv->pipeline = cogl_pipeline_new (priv->ctx);
 
   if (decl)
     {
@@ -336,7 +243,7 @@ create_template_pipeline (CoglGstVideoSink *sink,
       cogl_object_unref (snippet);
     }
 
-  g_signal_emit_by_name (sink, "cogl-pipeline-ready", 0);
+  g_signal_emit_by_name (sink, "cogl-pipeline-ready", NULL);
 }
 
 static void
@@ -386,25 +293,39 @@ cogl_gst_rgb_init (CoglGstVideoSink *sink)
     create_template_pipeline (sink, NULL, 1);
 }
 
-static void
+static CoglBool
 cogl_gst_rgb24_upload (CoglGstVideoSink *sink,
                        GstBuffer *buffer)
 {
   CoglGstVideoSinkPrivate *priv = sink->priv;
   CoglPixelFormat format;
   CoglTexture *tex;
+  GstVideoFrame frame;
 
   if (priv->bgr)
     format = COGL_PIXEL_FORMAT_BGR_888;
   else
     format = COGL_PIXEL_FORMAT_RGB_888;
-
-  tex = cogl_texture_new_from_data (priv->ctx, priv->width, priv->height,
-                                    COGL_GST_TEXTURE_FLAGS, format, format,
-                                    GST_ROUND_UP_4 (3 * priv->width),
-                                    GST_BUFFER_DATA (buffer), NULL);
+  
+  if (!gst_video_frame_map (&frame, &priv->info, buffer, GST_MAP_READ))
+    goto map_fail;
+  
+  tex = cogl_texture_new_from_data (priv->ctx, priv->info.width, 
+                                    priv->info.height, COGL_GST_TEXTURE_FLAGS, 
+                                    format, format, priv->info.stride[0], 
+                                    frame.data[0], NULL);
+                                    
+  gst_video_frame_unmap (&frame);
 
   create_paint_pipeline (sink, tex, NULL, NULL);
+  
+  return TRUE;
+  
+map_fail:
+  {
+    GST_ERROR_OBJECT (sink, "Could not map incoming video frame");
+    return FALSE;
+  }
 }
 
 
@@ -412,75 +333,103 @@ static CoglGstRenderer rgb24_renderer =
 {
   "RGB 24",
   COGL_GST_RGB24,
-  0,
-  GST_STATIC_CAPS (GST_VIDEO_CAPS_RGB ";" GST_VIDEO_CAPS_BGR),
+  COGL_GST_RENDERER_NEEDS_GLSL,
+  GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("{ RGB, BGR }")),
   cogl_gst_rgb_init,
   cogl_gst_dummy_deinit,
   cogl_gst_rgb24_upload,
 };
 
-static void
+static CoglBool
 cogl_gst_rgb32_upload (CoglGstVideoSink *sink,
                        GstBuffer *buffer)
 {
   CoglGstVideoSinkPrivate *priv = sink->priv;
   CoglPixelFormat format;
   CoglTexture *tex;
+  GstVideoFrame frame;
 
   if (priv->bgr)
     format = COGL_PIXEL_FORMAT_BGRA_8888;
   else
     format = COGL_PIXEL_FORMAT_RGBA_8888;
+    
+  if (!gst_video_frame_map (&frame, &priv->info, buffer, GST_MAP_READ))
+    goto map_fail;
 
-  tex = cogl_texture_new_from_data (priv->ctx, priv->width, priv->height,
-                                    COGL_GST_TEXTURE_FLAGS, format, format,
-                                    GST_ROUND_UP_4 (4 * priv->width),
-                                    GST_BUFFER_DATA (buffer), NULL);
+  tex = cogl_texture_new_from_data (priv->ctx, priv->info.width, 
+                                    priv->info.height, COGL_GST_TEXTURE_FLAGS, 
+                                    format, format, priv->info.stride[0], 
+                                    frame.data[0], NULL);
+                                    
+  gst_video_frame_unmap (&frame);
 
   create_paint_pipeline (sink, tex, NULL, NULL);
+  
+  return TRUE;
+  
+map_fail:
+  {
+    GST_ERROR_OBJECT (sink, "Could not map incoming video frame");
+    return FALSE;
+  }
 }
 
 static CoglGstRenderer rgb32_renderer =
 {
   "RGB 32",
   COGL_GST_RGB32,
-  0,
-  GST_STATIC_CAPS (GST_VIDEO_CAPS_RGBA ";" GST_VIDEO_CAPS_BGRA),
+  COGL_GST_RENDERER_NEEDS_GLSL,
+  GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("{ RGBA, BGRA }")),
   cogl_gst_rgb_init,
   cogl_gst_dummy_deinit,
   cogl_gst_rgb32_upload,
 };
 
-static void
+static CoglBool
 cogl_gst_yv12_upload (CoglGstVideoSink *sink,
                       GstBuffer *buffer)
 {
   CoglGstVideoSinkPrivate *priv = sink->priv;
-  int y_row_stride = GST_ROUND_UP_4 (priv->width);
-  int uv_row_stride = GST_ROUND_UP_4 (priv->width / 2);
   CoglTexture *y_tex, *u_tex, *v_tex;
-
+  GstVideoFrame frame;
   CoglPixelFormat format = COGL_PIXEL_FORMAT_G_8;
-
-  y_tex = cogl_texture_new_from_data (priv->ctx, priv->width, priv->height,
-                                      COGL_GST_TEXTURE_FLAGS, format, format,
-                                      y_row_stride, GST_BUFFER_DATA (buffer),
-                                      NULL);
-
-  u_tex = cogl_texture_new_from_data (priv->ctx, priv->width / 2,
-                                      priv->height / 2, COGL_GST_TEXTURE_FLAGS,
-                                      format, format, uv_row_stride,
-                                      GST_BUFFER_DATA (buffer) +
-                                      (y_row_stride * priv->height), NULL);
-
-  v_tex = cogl_texture_new_from_data (priv->ctx, priv->width / 2,
-                                      priv->height / 2, COGL_GST_TEXTURE_FLAGS,
-                                      format, format, uv_row_stride,
-                                      GST_BUFFER_DATA (buffer) +
-                                      (y_row_stride * priv->height) +
-                                      (uv_row_stride * priv->height / 2), NULL);
+  
+  if (!gst_video_frame_map (&frame, &priv->info, buffer, GST_MAP_READ))
+    goto map_fail;
+
+  y_tex = 
+     cogl_texture_new_from_data (priv->ctx, 
+                                 GST_VIDEO_INFO_COMP_WIDTH (&priv->info, 0), 
+                                 GST_VIDEO_INFO_COMP_HEIGHT (&priv->info, 0),
+                                 COGL_GST_TEXTURE_FLAGS, format, format,
+                                 priv->info.stride[0], frame.data[0], NULL);
+
+  u_tex = 
+     cogl_texture_new_from_data (priv->ctx, 
+                                 GST_VIDEO_INFO_COMP_WIDTH (&priv->info, 1), 
+                                 GST_VIDEO_INFO_COMP_HEIGHT (&priv->info, 1),
+                                 COGL_GST_TEXTURE_FLAGS, format, format,
+                                 priv->info.stride[1], frame.data[1], NULL);
+
+  v_tex = 
+     cogl_texture_new_from_data (priv->ctx, 
+                                 GST_VIDEO_INFO_COMP_WIDTH (&priv->info, 2), 
+                                 GST_VIDEO_INFO_COMP_HEIGHT (&priv->info, 2),
+                                 COGL_GST_TEXTURE_FLAGS, format, format,
+                                 priv->info.stride[2], frame.data[2], NULL);
+                                 
+  gst_video_frame_unmap (&frame);
 
   create_paint_pipeline (sink, y_tex, u_tex, v_tex);
+  
+  return TRUE;
+  
+map_fail:
+  {
+    GST_ERROR_OBJECT (sink, "Could not map incoming video frame");
+    return FALSE;
+  }
 }
 
 static void
@@ -496,7 +445,7 @@ static CoglGstRenderer yv12_glsl_renderer =
   "YV12 glsl",
   COGL_GST_YV12,
   COGL_GST_RENDERER_NEEDS_GLSL,
-  GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("YV12")),
+  GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("YV12")),
   cogl_gst_yv12_glsl_init,
   cogl_gst_dummy_deinit,
   cogl_gst_yv12_upload,
@@ -515,7 +464,7 @@ static CoglGstRenderer i420_glsl_renderer =
   "I420 glsl",
   COGL_GST_I420,
   COGL_GST_RENDERER_NEEDS_GLSL,
-  GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("I420")),
+  GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("I420")),
   cogl_gst_i420_glsl_init,
   cogl_gst_dummy_deinit,
   cogl_gst_yv12_upload,
@@ -529,20 +478,34 @@ cogl_gst_ayuv_glsl_init (CoglGstVideoSink *sink)
                             1);
 }
 
-static void
+static CoglBool
 cogl_gst_ayuv_upload (CoglGstVideoSink *sink,
                       GstBuffer *buffer)
 {
   CoglGstVideoSinkPrivate *priv = sink->priv;
   CoglPixelFormat format = COGL_PIXEL_FORMAT_RGBA_8888;
   CoglTexture *tex;
-
-  tex = cogl_texture_new_from_data (priv->ctx, priv->width, priv->height,
-                                    COGL_GST_TEXTURE_FLAGS, format, format,
-                                    GST_ROUND_UP_4 (4 * priv->width),
-                                    GST_BUFFER_DATA (buffer), NULL);
+  GstVideoFrame frame;
+  
+  if (!gst_video_frame_map (&frame, &priv->info, buffer, GST_MAP_READ))
+    goto map_fail;
+
+  tex = cogl_texture_new_from_data (priv->ctx, priv->info.width, 
+                                    priv->info.height, COGL_GST_TEXTURE_FLAGS, 
+                                    format, format, priv->info.stride[0],
+                                    frame.data[0], NULL);
+                                    
+  gst_video_frame_unmap (&frame);
 
   create_paint_pipeline (sink, tex, NULL, NULL);
+  
+  return TRUE;
+  
+map_fail:
+  {
+    GST_ERROR_OBJECT (sink, "Could not map incoming video frame");
+    return FALSE;
+  }
 }
 
 static CoglGstRenderer ayuv_glsl_renderer =
@@ -550,24 +513,90 @@ static CoglGstRenderer ayuv_glsl_renderer =
   "AYUV glsl",
   COGL_GST_AYUV,
   COGL_GST_RENDERER_NEEDS_GLSL,
-  GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("AYUV")),
+  GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("AYUV")),
   cogl_gst_ayuv_glsl_init,
   cogl_gst_dummy_deinit,
   cogl_gst_ayuv_upload,
 };
 
+#ifdef HAVE_HW_DECODER_SUPPORT
+
+static void
+cogl_gst_hw_init (CoglGstVideoSink *sink)
+{
+  create_template_pipeline (sink, NULL, NULL, FALSE, 1);
+}
+
+static void
+cogl_gst_hw_deinit (CoglGstVideoSink* sink)
+{
+  if (sink->priv->converter != NULL)
+    g_object_unref (sink->priv->converter);
+  sink->priv->converter = NULL;
+}
+
+static void
+cogl_gst_hw_upload (CoglGstVideoSink *sink, 
+                    GstBuffer *buffer)
+{
+  CoglGstVideoSinkPriv *priv = sink->priv;
+  GstSurfaceMeta* surface = gst_buffer_get_surface_meta (buffer);
+
+  g_return_if_fail (surface != NULL);
+  
+  if (G_UNLIKELY (priv->converter == NULL))
+    {
+      CoglTexture* tex;
+      unsigned int gl_tex;
+      unsigned int gl_tar;
+      GValue value = {0};
+      
+      tex = cogl_texture_new_with_size (priv->ctx, priv->info.width, 
+                                        priv->info.height, 
+                                        COGL_GST_TEXTURE_FLAGS, 
+                                        COGL_PIXEL_FORMAT_BGRA_8888, NULL);
+                                        
+      cogl_pipeline_set_layer_texture (priv->pipeline, 0, tex);
+      cogl_texture_get_gl_texture (tex, &gl_texture, &gl_target);
+      
+      g_value_init (&value, gl_texture);
+      g_value_set_uint (&value, gl_texture);
+      
+      priv->converter = gst_surface_meta_create_converter (surface, "opengl"
+                                                           &value);
+      cogl_object_unref (tex);
+      g_return_if_fail (priv->converter);
+    }
+  gst_surface_converter_upload (priv->converter, buffer);
+}
+
+static CoglGstRenderer hw_renderer = {
+  "HW surface",
+  COGL_GST_SURFACE,
+  0,
+  GST_STATIC_CAPS ("x-video/surface, opengl=true"),
+  cogl_gst_hw_init,
+  cogl_gst_hw_deinit,
+  cogl_gst_hw_upload,
+};
+
+#endif
+
 static GSList*
 cogl_gst_build_renderers_list (CoglContext *ctx)
 {
   GSList *list = NULL;
   CoglBool has_glsl;
   int i;
-  static CoglGstRenderer * const renderers[] =
+  static CoglGstRenderer *const renderers[] =
   {
     &rgb24_renderer,
     &rgb32_renderer,
     &yv12_glsl_renderer,
     &i420_glsl_renderer,
+    #ifdef HAVE_HW_DECODER_SUPPORT
+    &hw_renderer,
+    #endif
     &ayuv_glsl_renderer
   };
 
@@ -587,7 +616,6 @@ append_cap (gpointer data,
   CoglGstRenderer *renderer = (CoglGstRenderer*) data;
   GstCaps *caps = (GstCaps*) user_data;
   GstCaps *writable_caps;
-
   writable_caps =
     gst_caps_make_writable (gst_static_caps_get (&renderer->caps));
   gst_caps_append (caps, writable_caps);
@@ -654,50 +682,110 @@ cogl_gst_find_renderer_by_format (CoglGstVideoSink *sink,
   return renderer;
 }
 
-static void
-cogl_gst_video_sink_base_init (void *g_class)
+static GstCaps*
+cogl_gst_video_sink_get_caps (GstBaseSink *bsink,
+                              GstCaps *filter)
 {
-  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
-  gst_element_class_add_pad_template (element_class,
-                               gst_static_pad_template_get (&sinktemplate_all));
-  gst_element_class_set_details (element_class, &cogl_gst_video_sink_details);
-
+  CoglGstVideoSink *sink;
+  sink = COGL_GST_VIDEO_SINK (bsink);
+  return gst_caps_ref (sink->priv->caps);
 }
 
-
-static void
-cogl_gst_video_sink_init (CoglGstVideoSink *sink,
-                          CoglGstVideoSinkClass *klass)
+static CoglBool
+cogl_gst_video_sink_parse_caps (GstCaps *caps,
+                                CoglGstVideoSink *sink, 
+                                CoglBool save)
 {
-  CoglGstVideoSinkPrivate* priv;
+  CoglGstVideoSinkPrivate *priv = sink->priv;
+  GstCaps *intersection;
+  GstVideoInfo vinfo;
+  CoglGstVideoFormat format;
+  CoglBool bgr = FALSE;
+  CoglGstRenderer* renderer;
+  
+  intersection = gst_caps_intersect (priv->caps, caps);
+  if (gst_caps_is_empty (intersection))
+    goto no_intersection;
+    
+  gst_caps_unref (intersection);
+  
+  if (!gst_video_info_from_caps (&vinfo, caps))
+    goto unknown_format;
+    
+  switch (vinfo.finfo->format) {
+    case GST_VIDEO_FORMAT_YV12:
+      format = COGL_GST_YV12;
+      break;
+    case GST_VIDEO_FORMAT_I420:
+      format = COGL_GST_I420;
+      break;
+    case GST_VIDEO_FORMAT_AYUV:
+      format = COGL_GST_AYUV;
+      bgr = FALSE;
+      break;
+    case GST_VIDEO_FORMAT_RGB:
+      format = COGL_GST_RGB24;
+      bgr = FALSE;
+      break;
+    case GST_VIDEO_FORMAT_BGR:
+      format = COGL_GST_RGB24;
+      bgr = TRUE;
+      break;
+    case GST_VIDEO_FORMAT_RGBA:
+      format = COGL_GST_RGB32;
+      bgr = FALSE;
+      break;
+    case GST_VIDEO_FORMAT_BGRA:
+      format = COGL_GST_RGB32;
+      bgr = TRUE;
+      break;
+    default:
+      goto unhandled_format;
+  }
+  
+  renderer = cogl_gst_find_renderer_by_format (sink, format);
 
-  sink->priv = priv = G_TYPE_INSTANCE_GET_PRIVATE (sink,
-                                                   COGL_GST_TYPE_VIDEO_SINK,
-                                                   CoglGstVideoSinkPrivate);
+  if (G_UNLIKELY (renderer == NULL))
+    goto no_suitable_renderer;
 
-  sink->priv->loop = g_main_loop_new (NULL, TRUE);
-  sink->priv->g_ctx = g_main_loop_get_context (sink->priv->loop);
+  GST_INFO_OBJECT (sink, "found the %s renderer", renderer->name);
 
-  priv->renderer_state = COGL_GST_RENDERER_STOPPED;
-  priv->hook = COGL_SNIPPET_HOOK_FRAGMENT;
-}
+  if (save) {
+    priv->info = vinfo;
 
-static GstFlowReturn
-_cogl_gst_video_sink_render (GstBaseSink *bsink,
-                             GstBuffer *buffer)
-{
-  CoglGstVideoSink *sink = COGL_GST_VIDEO_SINK (bsink);
-  cogl_gst_source_push (sink->priv->source, buffer);
+    priv->format = format;
+    priv->bgr = bgr;
 
-  return GST_FLOW_OK;
-}
+    priv->renderer = renderer;
+  }
 
-static GstCaps*
-cogl_gst_video_sink_get_caps (GstBaseSink *bsink)
-{
-  CoglGstVideoSink *sink;
-  sink = COGL_GST_VIDEO_SINK (bsink);
-  return gst_caps_ref (sink->priv->caps);
+  return TRUE;
+
+
+no_intersection:
+  {
+    GST_WARNING_OBJECT (sink,
+        "Incompatible caps, don't intersect with %" GST_PTR_FORMAT, priv->caps);
+    return FALSE;
+  }
+
+unknown_format:
+  {
+    GST_WARNING_OBJECT (sink, "Could not figure format of input caps");
+    return FALSE;
+  }
+
+unhandled_format:
+  {
+    GST_ERROR_OBJECT (sink, "Provided caps aren't supported by clutter-gst");
+    return FALSE;
+  }
+
+no_suitable_renderer:
+  {
+    GST_ERROR_OBJECT (sink, "could not find a suitable renderer");
+    return FALSE;
+  }
 }
 
 static CoglBool
@@ -706,88 +794,153 @@ cogl_gst_video_sink_set_caps (GstBaseSink *bsink,
 {
   CoglGstVideoSink *sink;
   CoglGstVideoSinkPrivate *priv;
-  GstCaps *intersection;
-  GstStructure *structure;
-  CoglBool ret;
-  const GValue *fps;
-  const GValue *par;
-  int width, height;
-  uint32_t fourcc;
-  int red_mask, blue_mask;
 
   sink = COGL_GST_VIDEO_SINK (bsink);
   priv = sink->priv;
 
-  intersection = gst_caps_intersect (priv->caps, caps);
-  if (gst_caps_is_empty (intersection))
+  if (!cogl_gst_video_sink_parse_caps (caps, sink, FALSE))
     return FALSE;
 
-  gst_caps_unref (intersection);
+  g_mutex_lock (&priv->source->buffer_lock);
+  priv->source->has_new_caps = TRUE;
+  g_mutex_unlock (&priv->source->buffer_lock);
 
-  structure = gst_caps_get_structure (caps, 0);
+  return TRUE;
+}
 
-  ret = gst_structure_get_int (structure, "width", &width);
-  ret &= gst_structure_get_int (structure, "height", &height);
-  fps = gst_structure_get_value (structure, "framerate");
-  ret &= (fps != NULL);
+static CoglBool
+cogl_gst_source_dispatch (GSource *source,
+                          GSourceFunc callback,
+                          void* user_data)
+{
+  CoglGstSource *gst_source= (CoglGstSource*) source;
+  CoglGstVideoSinkPrivate *priv = gst_source->sink->priv;
+  GstBuffer *buffer;
 
-  par = gst_structure_get_value (structure, "pixel-aspect-ratio");
+  g_mutex_lock (&gst_source->buffer_lock);
+  
+  if (G_UNLIKELY (gst_source->has_new_caps))
+    {
+      GstCaps *caps =
+        gst_pad_get_current_caps (GST_BASE_SINK_PAD ((GST_BASE_SINK
+                (gst_source->sink))));
 
-  if (!ret)
-    return FALSE;
+      if (priv->renderer)
+        priv->renderer->deinit (gst_source->sink);
+      
+      if (!cogl_gst_video_sink_parse_caps (caps, gst_source->sink, TRUE))
+        goto negotiation_fail;
 
-  priv->width = width;
-  priv->height = height;
+      priv->renderer->init (gst_source->sink);
+      gst_source->has_new_caps = FALSE;
+    }
+  
+  buffer = gst_source->buffer;
+  gst_source->buffer = NULL;
 
-  priv->fps_n = gst_value_get_fraction_numerator (fps);
-  priv->fps_d = gst_value_get_fraction_denominator (fps);
+  g_mutex_unlock (&gst_source->buffer_lock);
 
-  if (par)
-    {
-      priv->par_n = gst_value_get_fraction_numerator (par);
-      priv->par_d = gst_value_get_fraction_denominator (par);
-    }
-  else
-    priv->par_n = priv->par_d = 1;
-
-  ret = gst_structure_get_fourcc (structure, "format", &fourcc);
-  if (ret && (fourcc == GST_MAKE_FOURCC ('Y', 'V', '1', '2')))
-    priv->format = COGL_GST_YV12;
-  else if (ret && (fourcc == GST_MAKE_FOURCC ('I', '4', '2', '0')))
-    priv->format = COGL_GST_I420;
-  else if (ret && (fourcc == GST_MAKE_FOURCC ('A', 'Y', 'U', 'V')))
+  if (buffer) 
     {
-      priv->format = COGL_GST_AYUV;
-      priv->bgr = FALSE;
-    }
+      if (!priv->renderer->upload (gst_source->sink, buffer))
+        goto fail_upload;
+
+      g_signal_emit_by_name (gst_source->sink, "cogl-gst-new-frame", NULL);
+      gst_buffer_unref (buffer);
+    } 
   else
-    {
-      uint32_t mask;
-      gst_structure_get_int (structure, "red_mask", &red_mask);
-      gst_structure_get_int (structure, "blue_mask", &blue_mask);
+    GST_WARNING_OBJECT (gst_source->sink, "No buffers available for display");
 
-      mask = red_mask | blue_mask;
+  return TRUE;
 
-      if (mask < 0x1000000)
-        {
-          priv->format = COGL_GST_RGB24;
-          priv->bgr = (red_mask == 0xff0000) ? FALSE : TRUE;
-        }
-      else
-        {
-          priv->format = COGL_GST_RGB32;
-          priv->bgr = (red_mask == 0xff000000) ? FALSE : TRUE;
-        }
-    }
 
-  priv->renderer = cogl_gst_find_renderer_by_format (sink, priv->format);
-  if (priv->renderer == NULL)
-    {
-      GST_ERROR_OBJECT (sink, "Could not find suitable renderer");
-      return FALSE;
-    }
+negotiation_fail:
+  {
+    GST_WARNING_OBJECT (gst_source->sink,
+        "Failed to handle caps. Stopping GSource");
+    priv->flow_return = GST_FLOW_NOT_NEGOTIATED;
+    g_mutex_unlock (&gst_source->buffer_lock);
 
-  return TRUE;
+    return FALSE;
+  }
+
+fail_upload:
+  {
+    GST_WARNING_OBJECT (gst_source->sink, "Failed to upload buffer");
+    priv->flow_return = GST_FLOW_ERROR;
+    gst_buffer_unref (buffer);
+    return FALSE;
+  }
+}
+
+static GSourceFuncs gst_source_funcs =
+{
+  cogl_gst_source_prepare,
+  cogl_gst_source_check,
+  cogl_gst_source_dispatch,
+  cogl_gst_source_finalize
+};
+
+static CoglGstSource*
+cogl_gst_source_new (CoglGstVideoSink *sink)
+{
+  GSource *source;
+  CoglGstSource *gst_source;
+
+  source = g_source_new (&gst_source_funcs, sizeof (CoglGstSource));
+  gst_source = (CoglGstSource*) source;
+
+  g_source_set_can_recurse (source, TRUE);
+  g_source_set_priority (source, COGL_GST_DEFAULT_PRIORITY);
+
+  gst_source->sink = sink;
+  g_mutex_init (&gst_source->buffer_lock);
+  gst_source->buffer = NULL;
+
+  return gst_source;
+}
+
+static void
+cogl_gst_video_sink_init (CoglGstVideoSink *sink)
+{
+  CoglGstVideoSinkPrivate* priv;
+
+  sink->priv = priv = G_TYPE_INSTANCE_GET_PRIVATE (sink,
+                                                   COGL_GST_TYPE_VIDEO_SINK,
+                                                   CoglGstVideoSinkPrivate);
+
+  sink->priv->loop = g_main_loop_new (NULL, TRUE);
+  sink->priv->g_ctx = g_main_loop_get_context (sink->priv->loop);
+}
+
+static GstFlowReturn
+_cogl_gst_video_sink_render (GstBaseSink *bsink,
+                             GstBuffer *buffer)
+{
+  CoglGstVideoSink *sink = COGL_GST_VIDEO_SINK (bsink);
+  CoglGstVideoSinkPrivate *priv = sink->priv;
+  CoglGstSource *gst_source = priv->source;
+  
+  g_mutex_lock (&gst_source->buffer_lock);
+  
+  if (G_UNLIKELY (priv->flow_return != GST_FLOW_OK))
+    goto dispatch_flow_ret;
+  
+  if (gst_source->buffer)
+    gst_buffer_unref (gst_source->buffer);
+    
+  gst_source->buffer = gst_buffer_ref (buffer);
+  g_mutex_unlock (&gst_source->buffer_lock);
+
+  g_main_context_wakeup (priv->g_ctx);
+
+  return GST_FLOW_OK;
+  
+  dispatch_flow_ret:
+  {
+    g_mutex_unlock (&gst_source->buffer_lock);
+    return priv->flow_return;
+  }
 }
 
 static void
@@ -798,12 +951,11 @@ cogl_gst_video_sink_dispose (GObject *object)
 
   self = COGL_GST_VIDEO_SINK (object);
   priv = self->priv;
-
-  if (priv->renderer_state == COGL_GST_RENDERER_RUNNING ||
-      priv->renderer_state == COGL_GST_RENDERER_NEED_GC)
+  
+  if (priv->renderer) 
     {
       priv->renderer->deinit (self);
-      priv->renderer_state = COGL_GST_RENDERER_STOPPED;
+      priv->renderer = NULL;
     }
 
   if (priv->pipeline)
@@ -818,7 +970,7 @@ cogl_gst_video_sink_dispose (GObject *object)
       priv->caps = NULL;
     }
 
-  G_OBJECT_CLASS (parent_class)->dispose (object);
+  G_OBJECT_CLASS(parent_class)->dispose (object);
 }
 
 static void
@@ -839,6 +991,7 @@ cogl_gst_video_sink_start (GstBaseSink *base_sink)
 
   priv->source = cogl_gst_source_new (sink);
   g_source_attach ((GSource*) priv->source, priv->g_ctx);
+  priv->flow_return = GST_FLOW_OK;
   return TRUE;
 }
 
@@ -895,8 +1048,6 @@ cogl_gst_video_sink_stop (GstBaseSink *base_sink)
       priv->source = NULL;
     }
 
-  priv->renderer_state = COGL_GST_RENDERER_STOPPED;
-
   return TRUE;
 }
 
@@ -905,13 +1056,24 @@ cogl_gst_video_sink_class_init (CoglGstVideoSinkClass *klass)
 {
   GObjectClass *go_class = G_OBJECT_CLASS (klass);
   GstBaseSinkClass *gb_class = GST_BASE_SINK_CLASS (klass);
-  GParamSpec *pspec;
+  GstElementClass *ge_class = GST_ELEMENT_CLASS (klass);
+  GParamSpec *pspec; 
 
   g_type_class_add_private (klass, sizeof (CoglGstVideoSinkPrivate));
   go_class->set_property = cogl_gst_video_sink_set_property;
   go_class->get_property = cogl_gst_video_sink_get_property;
   go_class->dispose = cogl_gst_video_sink_dispose;
   go_class->finalize = cogl_gst_video_sink_finalize;
+  
+  gst_element_class_add_pad_template (ge_class, 
+                                      gst_static_pad_template_get (&sinktemplate_all));
+  gst_element_class_set_metadata (ge_class, "Cogl video sink", "Sink/Video",
+            "Sends video data from GStreamer to a Cogl pipeline",
+            "Jonathan Matthew <jonathan at kaolin.wh9.net>, "
+            "Matthew Allum <mallum at o-hand.com, "
+            "Chris Lord <chris at o-hand.com>, " 
+            "Plamena Manolova <plamena.n.manolova at intel.com>");
+
   gb_class->render = _cogl_gst_video_sink_render;
   gb_class->preroll = _cogl_gst_video_sink_render;
   gb_class->start = cogl_gst_video_sink_start;
@@ -931,18 +1093,40 @@ cogl_gst_video_sink_class_init (CoglGstVideoSinkClass *klass)
   g_signal_new ("cogl-pipeline-ready", COGL_GST_TYPE_VIDEO_SINK,
                 G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID,
                 G_TYPE_NONE, 0, G_TYPE_NONE);
+                
+  g_signal_new ("cogl-gst-new-frame", COGL_GST_TYPE_VIDEO_SINK, 
+                G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID,
+                G_TYPE_NONE, 0, G_TYPE_NONE);
+}
 
+CoglGstVideoSink*
+cogl_gst_video_sink_new (CoglContext *ctx)
+{
+  CoglGstVideoSink* sink = g_object_new (COGL_GST_TYPE_VIDEO_SINK, NULL);
+  cogl_gst_video_sink_set_context (sink, ctx);
+  
+  return sink;
 }
 
+
 static CoglBool
-plugin_init (GstPlugin *plugin)
+_plugin_init (GstPlugin * coglgstvideosink)
 {
-  CoglBool ret = gst_element_register (plugin, "coglsink", GST_RANK_PRIMARY,
-                                       COGL_GST_TYPE_VIDEO_SINK);
-
-  return ret;
+  return gst_element_register (coglgstvideosink, "coglsink", GST_RANK_PRIMARY,
+      COGL_GST_TYPE_VIDEO_SINK);
 }
 
-GST_PLUGIN_DEFINE_STATIC (GST_VERSION_MAJOR, GST_VERSION_MINOR, "coglsink",
-                          "Element to attach frames to cogl pipelines",
-                          plugin_init, VERSION, "LGPL", PACKAGE, "...");
+GST_PLUGIN_DEFINE (
+    GST_VERSION_MAJOR,
+    GST_VERSION_MINOR,
+    cogl,
+    "Sends video data from GStreamer to a Cogl pipeline",
+    _plugin_init,
+    VERSION,
+    "LGPL",
+    "CoglGst",
+    "http://gstreamer.net/"
+)
+                   
+      
+
diff --git a/cogl-gst/cogl-gst-video-sink.h b/cogl-gst/cogl-gst-video-sink.h
index d3d9580..decf284 100644
--- a/cogl-gst/cogl-gst-video-sink.h
+++ b/cogl-gst/cogl-gst-video-sink.h
@@ -29,6 +29,7 @@
  * License along with this library; if not, write to the
  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  * Boston, MA 02111-1307, USA.
+ FLOP
  */
 
 #ifndef __COGL_GST_VIDEO_SINK_H__
@@ -90,6 +91,9 @@ struct _CoglGstVideoSinkClass
 
 GType       cogl_gst_video_sink_get_type    (void) G_GNUC_CONST;
 
+CoglGstVideoSink*
+cogl_gst_video_sink_new (CoglContext *ctx);
+
 CoglPipeline*
 cogl_gst_video_sink_get_pipeline (CoglGstVideoSink *vt);
 
diff --git a/configure.ac b/configure.ac
index 2404545..28dc240 100644
--- a/configure.ac
+++ b/configure.ac
@@ -447,10 +447,20 @@ AC_ARG_ENABLE(
 )
 AS_IF([test "x$enable_cogl_gst" = "xyes"],
       [
-  COGL_GST_PKG_REQUIRES="$COGL_GST_PKG_REQUIRES gstreamer-0.10 >= 0.10 gstreamer-fft-0.10 >= 0.10 gstreamer-interfaces-0.10 >= 0.10 gstreamer-base-0.10 >= 0.10"
+  COGL_GST_PKG_REQUIRES="$COGL_GST_PKG_REQUIRES gstreamer-1.0  gstreamer-fft-1.0 \
+                         gstreamer-audio-1.0 gstreamer-base-1.0 \
+                         gstreamer-video-1.0 gstreamer-plugins-base-1.0 \
+                         gstreamer-tag-1.0 gstreamer-controller-1.0"
+                         
+  GST_MAJORMINOR=1.0
+
+  dnl define location of gstreamer plugin directory
+  plugindir="\$(libdir)/gstreamer-$GST_MAJORMINOR"
+  AC_SUBST(plugindir)
       ]
 )
 
+
 dnl     ============================================================
 dnl     Choose image loading backend
 dnl     ============================================================
diff --git a/examples/cogl-basic-video-player.c b/examples/cogl-basic-video-player.c
index 2f72a74..183b1e3 100644
--- a/examples/cogl-basic-video-player.c
+++ b/examples/cogl-basic-video-player.c
@@ -58,20 +58,13 @@ _frame_callback (CoglOnscreen *onscreen,
 }
 
 static CoglBool
-_draw (void *user_data)
+_draw  (gpointer instance,
+        gpointer user_data)
 {
   Data *data = (Data*) user_data;
   CoglPipeline* current = cogl_gst_video_sink_get_pipeline (data->sink);
 
-/*
- * This checks whether the system compositor is ready to render and that
- * sink has retrieved a new frame (the cogl sink creates a new cogl pipeline
- * (by copying the previous one) for each frame so checking whether the
- * pipeline has changed is a way of querying whether there is a new frame to
- * render).
- */
-
-  if (data->draw_ready && current != data->pln && current)
+  if (data->draw_ready)
     {
       cogl_framebuffer_clear4f (data->fb,
                                 COGL_BUFFER_BIT_COLOR|COGL_BUFFER_BIT_DEPTH, 0,
@@ -108,7 +101,7 @@ _set_up_pipeline (gpointer instance,
 
   cogl_onscreen_add_frame_callback(COGL_ONSCREEN (data->fb), _frame_callback,
                                    &data, NULL);
-  g_idle_add (_draw, data);
+  g_signal_connect (data->sink,"cogl-gst-new-frame", G_CALLBACK (_draw), data);
 }
 
 int
@@ -119,9 +112,12 @@ main (int argc,
   CoglContext *ctx;
   CoglOnscreen *onscreen;
   CoglMatrix view;
-  CoglGstVideoPlayer *player;
   GMainLoop *loop;
   float fovy, aspect, z_near, z_2d, z_far;
+  GstElement *pipeline;
+  GstElement *bin;
+  GstBus *bus;
+  char *uri;
 
   ctx = cogl_context_new (NULL, NULL);
   onscreen = cogl_onscreen_new (ctx, 640, 480);
@@ -142,13 +138,28 @@ main (int argc,
   cogl_framebuffer_set_modelview_matrix (data.fb, &view);
 
   gst_init (&argc, &argv);
+  
+  data.sink = cogl_gst_video_sink_new (ctx); 
+
+  pipeline = gst_pipeline_new ("gst-player");
+  bin = gst_element_factory_make ("playbin", "bin");
+  
+  if (argc < 2)
+    uri = "http://docs.gstreamer.com/media/sintel_trailer-480p.webm";
+  else
+    uri = argv[1];
+
+  g_object_set (G_OBJECT (bin), "video-sink", GST_ELEMENT (data.sink), NULL);
+
 
-  player = cogl_gst_video_player_new (ctx, TRUE,
-                                      "http://docs.gstreamer.com/media/sintel_trailer-480p.webm");
+  gst_bin_add (GST_BIN (pipeline), bin);
 
-  data.sink = cogl_gst_video_player_get_sink (player);
+  g_object_set (G_OBJECT (bin), "uri", uri, NULL);
+  
+  gst_element_set_state (pipeline, GST_STATE_PLAYING);
+  bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
+  gst_bus_add_watch (bus, _bus_watch, &data);
 
-  cogl_gst_video_player_add_bus_watch (player, _bus_watch, &data);
   loop = cogl_gst_video_sink_get_main_loop (data.sink);
 
   g_signal_connect (data.sink, "cogl-pipeline-ready",
-- 
1.8.1.2

---------------------------------------------------------------------
Intel Corporation (UK) Limited
Registered No. 1134945 (England)
Registered Office: Pipers Way, Swindon SN3 1RJ
VAT No: 860 2173 47

This e-mail and any attachments may contain confidential material for
the sole use of the intended recipient(s). Any review or distribution
by others is strictly prohibited. If you are not the intended
recipient, please contact the sender and delete all copies.



More information about the Cogl mailing list