Index: clutter-helix/clutter-helix-shaders.h
===================================================================
--- clutter-helix/clutter-helix-shaders.h	(revision 0)
+++ clutter-helix/clutter-helix-shaders.h	(revision 0)
@@ -0,0 +1,43 @@
+
+#ifndef CLUTTER_GST_SHADERS_H
+#define CLUTTER_GST_SHADERS_H
+
+#include <clutter/clutter.h>
+
+/* Copied from test-shaders */
+
+/* These variables are used instead of the standard GLSL variables on
+   GLES 2 */
+#ifdef HAVE_COGL_GLES2
+
+#define GLES2_VARS              \
+  "precision mediump float;\n"  \
+  "varying vec2 tex_coord;\n"   \
+  "varying vec4 frag_color;\n"
+#define TEX_COORD "tex_coord"
+#define COLOR_VAR "frag_color"
+
+#else /* HAVE_COGL_GLES2 */
+
+#define GLES2_VARS ""
+#define TEX_COORD "gl_TexCoord[0]"
+#define COLOR_VAR "gl_Color"
+
+#endif /* HAVE_COGL_GLES2 */
+
+/* a couple of boilerplate defines that are common amongst all the
+ * sample shaders
+ */
+
+#define FRAGMENT_SHADER_VARS      \
+  GLES2_VARS
+
+/* FRAGMENT_SHADER_END: apply the changed color to the output buffer correctly
+ * blended with the gl specified color (makes the opacity of actors work
+ * correctly).
+ */
+#define FRAGMENT_SHADER_END                             \
+     "  gl_FragColor = gl_FragColor * " COLOR_VAR ";"
+
+#endif
+
Index: clutter-helix/clutter-helix-video-texture.c
===================================================================
--- clutter-helix/clutter-helix-video-texture.c	(revision 3607)
+++ clutter-helix/clutter-helix-video-texture.c	(working copy)
@@ -41,10 +41,13 @@
 #include "config.h"
 
 #include "clutter-helix-video-texture.h"
+#include "clutter-helix-shaders.h"
 #include "player.h"
 
 #include <glib.h>
 
+typedef void (*GLUNIFORM1IPROC)(COGLint location, COGLint value);
+
 struct _ClutterHelixVideoTexturePrivate
 {
   void             *player;
@@ -60,6 +63,13 @@
   unsigned int      width;
   unsigned int      height;
   gint              cid;
+  gboolean               shaders_init;
+  CoglHandle             u_tex;
+  CoglHandle             v_tex;
+  CoglHandle             program;
+  CoglHandle             shader;
+  gboolean               use_shaders;
+  GLUNIFORM1IPROC        glUniform1iARB;
 };
 
 enum {
@@ -80,6 +90,30 @@
 
 static gboolean tick_timeout (ClutterHelixVideoTexture *video_texture);
 
+static gchar *dummy_shader = \
+     FRAGMENT_SHADER_VARS
+	 "void main () {"
+	 "}";
+
+static gchar *yv12_to_rgba_shader = \
+     FRAGMENT_SHADER_VARS
+	 "uniform sampler2D ytex;"
+	 "uniform sampler2D utex;"
+	 "uniform sampler2D vtex;"
+	 "void main () {"
+	 "  vec2 coord = vec2(" TEX_COORD ");"
+	 "  float y = 1.1640625 * (texture2D (ytex, coord).g - 0.0625);"
+	 "  float u = texture2D (utex, coord).g - 0.5;"
+	 "  float v = texture2D (vtex, coord).g - 0.5;"
+	 "  vec4 color;"
+	 "  color.r = y + 1.59765625 * v;"
+	 "  color.g = y - 0.390625 * u - 0.8125 * v;"
+	 "  color.b = y + 2.015625 * u;"
+	 "  color.a = 1.0;"
+	 "  gl_FragColor = color;"
+	 FRAGMENT_SHADER_END
+	 "}";
+
 G_DEFINE_TYPE_WITH_CODE (ClutterHelixVideoTexture,
                          clutter_helix_video_texture,
                          CLUTTER_TYPE_TEXTURE,
@@ -147,10 +181,10 @@
       priv->uri = NULL;
     
       if (priv->tick_timeout_id > 0) 
-        {
-	  g_source_remove (priv->tick_timeout_id);
-	  priv->tick_timeout_id = 0;
-	}
+	    {
+	      g_source_remove (priv->tick_timeout_id);
+	      priv->tick_timeout_id = 0;
+	    }
     }
   
   priv->can_seek = FALSE;
@@ -436,7 +470,73 @@
     }
 }
 
+
 static void
+clutter_helix_video_paint (ClutterActor        *actor,
+				                              ClutterHelixVideoTexture *video_texture)
+{
+		  ClutterHelixVideoTexturePrivate *priv = video_texture->priv;
+		  	    if (priv->program)
+								    cogl_program_use (priv->program);
+}
+
+
+static void
+clutter_helix_video_set_shader (ClutterHelixVideoTexture *video_texture,
+		const gchar         *shader_src)
+{
+	ClutterHelixVideoTexturePrivate *priv = video_texture->priv;
+
+	priv->shaders_init = FALSE;
+	if (video_texture)
+		clutter_actor_set_shader (CLUTTER_ACTOR (video_texture), NULL);
+
+	if (priv->program)
+	{
+		cogl_program_unref (priv->program);
+		priv->program = NULL;
+	}
+
+	if (priv->shader)
+	{
+		cogl_program_unref (priv->shader);
+		priv->shader = NULL;
+	}
+
+	if (shader_src)
+	{
+		ClutterShader *shader;
+
+		/* Set a dummy shader so we don't interfere with the shader stack */
+		shader = clutter_shader_new ();
+		clutter_shader_set_fragment_source (shader, dummy_shader, -1);
+		clutter_actor_set_shader (CLUTTER_ACTOR (video_texture), shader);
+		g_object_unref (shader);
+
+		/* Create shader through COGL - necessary as we need to be able to set
+		 *        * integer uniform variables for multi-texturing.
+		 *               */
+		priv->shader = cogl_create_shader (CGL_FRAGMENT_SHADER);
+		cogl_shader_source (priv->shader, shader_src);
+		cogl_shader_compile (priv->shader);
+
+		priv->program = cogl_create_program ();
+		cogl_program_attach_shader (priv->program, priv->shader);
+		cogl_program_link (priv->program);
+
+		/* Hook onto the pre-paint signal to replace the dummy shader with
+		 *        * the real shader.
+		 *               */
+		g_signal_connect (video_texture,
+				"paint",
+				G_CALLBACK (clutter_helix_video_paint),
+				video_texture);
+
+		priv->shaders_init = TRUE;
+	}
+}
+
+static void
 clutter_helix_video_texture_get_property (GObject    *object, 
 				        guint       property_id,
 				        GValue     *value, 
@@ -548,7 +648,49 @@
 				   video_texture,
 				   NULL);
 }
+static void
+clutter_helix_yv12_paint (ClutterActor        *actor,
+		                        ClutterHelixVideoTexture *video_texture)
+{
+#ifdef CLUTTER_COGL_HAS_GL
+	ClutterHelixVideoTexturePrivate *priv = video_texture->priv;
+	GLuint texture;
 
+	/* Bind the U and V textures in texture units 1 and 2 */
+	if (priv->u_tex)
+	{
+		cogl_texture_get_gl_texture (priv->u_tex, &texture, NULL);
+		glActiveTexture (GL_TEXTURE1);
+		glEnable (GL_TEXTURE_2D);
+		glBindTexture (GL_TEXTURE_2D, texture);
+	}
+
+	if (priv->v_tex)
+	{
+		cogl_texture_get_gl_texture (priv->v_tex, &texture, NULL);
+		glActiveTexture (GL_TEXTURE2);
+		glEnable (GL_TEXTURE_2D);
+		glBindTexture (GL_TEXTURE_2D, texture);
+	}
+
+	glActiveTexture (GL_TEXTURE0_ARB);
+#endif
+}
+
+static void
+clutter_helix_yv12_post_paint (ClutterActor        *actor,
+		                             ClutterHelixVideoTexture *video_texture)
+{
+#ifdef CLUTTER_COGL_HAS_GL
+	/* Disable the extra texture units */
+	glActiveTexture (GL_TEXTURE1);
+	glDisable (GL_TEXTURE_2D);
+	glActiveTexture (GL_TEXTURE2);
+	glDisable (GL_TEXTURE_2D);
+	glActiveTexture (GL_TEXTURE0);
+#endif
+}
+
 /* Probably gets called with a mutex held in helix */
 static void
 on_state_change_cb (unsigned short old_state, unsigned short new_state, void *context)
@@ -572,38 +714,115 @@
 {
   GError *error;
   unsigned char *buffer;
+  gint cid;
   ClutterHelixVideoTexture *video_texture = (ClutterHelixVideoTexture *)data;
   ClutterHelixVideoTexturePrivate *priv;
 
   priv = video_texture->priv;
 
   buffer = g_async_queue_try_pop (priv->async_queue);
+  printf("line:%d\n", __LINE__);
   if (buffer == NULL) 
     {
       return FALSE;
     }
 
   error = NULL;
-  if (priv->cid == CID_ARGB32)
+  cid = priv->cid;
+  if (cid == CID_ARGB32)
     {
       if (!clutter_texture_set_from_rgb_data (CLUTTER_TEXTURE (video_texture),
-					      buffer,
-					      TRUE,
-					      priv->width,
-					      priv->height,
-					      4 * priv->width ,
-					      4,
-					      CLUTTER_TEXTURE_RGB_FLAG_BGR,
-					      &error))
+					  buffer,
+					  TRUE,
+					  priv->width,
+					  priv->height,
+					  4 * priv->width ,
+					  4,
+					  CLUTTER_TEXTURE_RGB_FLAG_BGR,
+					  &error))
         g_warning ("clutter_texture_set_from_rgb_data: %s", error->message);
     }
-  else if (priv->cid == CID_LIBVA)
+  else if (cid == CID_I420)
+  {
+	  CoglHandle y_tex =
+		  cogl_texture_new_from_data (priv->width,
+				  priv->height,
+				  -1,
+				  FALSE,
+				  COGL_PIXEL_FORMAT_G_8,
+				  COGL_PIXEL_FORMAT_G_8,
+				  priv->width,
+				  buffer);
+	  cogl_texture_set_filters (y_tex, CGL_LINEAR, CGL_LINEAR);
+		  clutter_texture_set_cogl_texture (CLUTTER_TEXTURE(video_texture), y_tex);
+	  cogl_texture_unref (y_tex);
+
+	  if (priv->u_tex)
+		  cogl_texture_unref (priv->u_tex);
+
+	  if (priv->v_tex)
+		  cogl_texture_unref (priv->v_tex);
+
+	  priv->u_tex =
+		  cogl_texture_new_from_data (priv->width/2,
+				  priv->height/2,
+				  -1,
+				  FALSE,
+				  COGL_PIXEL_FORMAT_G_8,
+				  COGL_PIXEL_FORMAT_G_8,
+				  priv->width/2,
+				  buffer +
+				  (priv->width * priv->height));
+	  cogl_texture_set_filters (priv->u_tex, CGL_LINEAR, CGL_LINEAR);
+
+		  priv->v_tex =
+		  cogl_texture_new_from_data (priv->width/2,
+				  priv->height/2,
+				  -1,
+				  FALSE,
+				  COGL_PIXEL_FORMAT_G_8,
+				  COGL_PIXEL_FORMAT_G_8,
+				  priv->width/2,
+				  buffer +
+				  (priv->width * priv->height) +
+				  (priv->width/2 * priv->height/2));
+	  cogl_texture_set_filters (priv->v_tex, CGL_LINEAR, CGL_LINEAR);
+  printf("line:%d\n", __LINE__);
+
+	  /* Initialise YV12 shader */
+	  if (!priv->shaders_init)
+	  {
+#ifdef CLUTTER_COGL_HAS_GL
+		  COGLint location;
+		  clutter_helix_video_set_shader (video_texture, yv12_to_rgba_shader);
+
+		  cogl_program_use (priv->program);
+		  location = cogl_program_get_uniform_location (priv->program, "ytex");
+		  priv->glUniform1iARB (location, 0);
+		  location = cogl_program_get_uniform_location (priv->program, "utex");
+		  priv->glUniform1iARB (location, 1);
+		  location = cogl_program_get_uniform_location (priv->program, "vtex");
+		  priv->glUniform1iARB (location, 2);
+		  cogl_program_use (COGL_INVALID_HANDLE);
+
+		  g_signal_connect (video_texture,
+				  "paint",
+				  G_CALLBACK (clutter_helix_yv12_paint),
+				  video_texture);
+		  g_signal_connect_after (video_texture,
+				  "paint",
+				  G_CALLBACK (clutter_helix_yv12_post_paint),
+				  video_texture);
+#endif
+	  }
+  }
+  else if (cid == CID_LIBVA)
     {
       /* TODO: Add implementation to perform libva blitting */
     }
   else
     {
-      g_warning ("Unsupported colorspace id: %i", priv->cid);
+      g_warning ("Unsupported colorspace id:%d", cid);
     }
 
   return FALSE;
@@ -670,6 +889,7 @@
     on_error_cb
   };
 
+
   video_texture->priv  = priv =
     G_TYPE_INSTANCE_GET_PRIVATE (video_texture,
 				 CLUTTER_HELIX_TYPE_VIDEO_TEXTURE,
@@ -678,6 +898,11 @@
   get_player(&priv->player, &callbacks, (void *)video_texture);
 
   priv->async_queue = g_async_queue_new ();
+#ifdef CLUTTER_COGL_HAS_GL
+  priv->glUniform1iARB = (GLUNIFORM1IPROC)
+		    cogl_get_proc_address ("glUniform1iARB");
+#endif
+
 }
 
 
