[Cogl] [PATCH] cogl-gst: Add a functions to facilitate layering

Neil Roberts neil at linux.intel.com
Wed Apr 17 09:25:19 PDT 2013


Thanks for the updated patch. I have some comments which I've
addressed in another version of the patch below.

I think it would be better if it only generated the default pipeline
lazily when it is first requested because there is no point in having
it if the application is only going to use the setup_pipeline
function. For this to work, instead of emitting the pipeline_ready
signal when we've actually created the pipeline, we can just emit it
immediately after the caps are decided. As far as I can tell, your
patch will end up emitting the ‘pipeline-ready’ signal as soon as
set_first_layer() is called, even if no renderer is decided yet. I
think it would be better to be able to call this as soon as the sink
is created.

I think it would be better to try to get the render to avoid
generating the shader snippet code if there is already a cached
snippet available. I think your version of the patch will generate the
source for the snippet and then free it if it detects it already has a
snippet.

If we go back to making the cache a static variable in the
setup_pipeline function then we don't need to store the render in the
snippet cache.

The global video sampling functions now all include the custom_start
value as part of the function name. What is the idea behind this? Is
it so that you could combine multiple video sinks into a single
pipeline or something? I've left this in for now.

The i420 renderer is using exactly the same source code as the yv12
snippet. We might as well just make them share the same setup_pipeline
function.

I've removed the deinit virtual.

Here is a proposed second version of the patch which implements these
changes and rebases the patch on top of my patch to avoid setting a
replace snippet.

-->8--
From: Plamena Manolova <plamena.n.manolova at intel.com>

These functions are used when attaching frames at a start point other
than layer 0 is required. This could potentially be used to "layer"
videos and textures on top of each other in the CoglPipeline. This
layering could come handy if videos are used as alpha masks or normal
maps, or when arranging layers in a perticular order, so Cogl could
blend them nicely without extra hassle.
---
 cogl-gst/Makefile.am               |   7 +-
 cogl-gst/cogl-gst-shader-private.h |  48 -----
 cogl-gst/cogl-gst-shader.c         |  81 ---------
 cogl-gst/cogl-gst-video-sink.c     | 359 ++++++++++++++++++++++++++-----------
 cogl-gst/cogl-gst-video-sink.h     |  11 ++
 5 files changed, 264 insertions(+), 242 deletions(-)
 delete mode 100644 cogl-gst/cogl-gst-shader-private.h
 delete mode 100644 cogl-gst/cogl-gst-shader.c

diff --git a/cogl-gst/Makefile.am b/cogl-gst/Makefile.am
index 57a64d8..d5e49ae 100644
--- a/cogl-gst/Makefile.am
+++ b/cogl-gst/Makefile.am
@@ -8,7 +8,6 @@ DISTCLEANFILES =
 EXTRA_DIST =
 
 source_c = \
-	cogl-gst-shader.c \
 	cogl-gst-video-sink.c \
 	$(NULL)
 
@@ -17,13 +16,9 @@ source_h = \
 	cogl-gst-video-sink.h \
 	$(NULL)
 
-source_h_priv = \
-	cogl-gst-shader-private.h \
-	$(NULL)
-
 lib_LTLIBRARIES = libcogl-gst.la
 
-libcogl_gst_la_SOURCES = $(source_c) $(source_h) $(source_h_priv)
+libcogl_gst_la_SOURCES = $(source_c) $(source_h)
 libcogl_gst_la_CFLAGS = $(COGL_DEP_CFLAGS) $(COGL_GST_DEP_CFLAGS) $(COGL_EXTRA_CFLAGS) $(MAINTAINER_CFLAGS)
 libcogl_gst_la_LIBADD = $(top_builddir)/cogl/libcogl2.la
 libcogl_gst_la_LIBADD += $(COGL_DEP_LIBS) $(COGL_GST_DEP_LIBS) $(COGL_EXTRA_LDFLAGS)
diff --git a/cogl-gst/cogl-gst-shader-private.h b/cogl-gst/cogl-gst-shader-private.h
deleted file mode 100644
index bdf7164..0000000
--- a/cogl-gst/cogl-gst-shader-private.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Cogl-GStreamer.
- *
- * GStreamer integration library for Cogl.
- *
- * cogl-gst-video-sink-private.h - Miscellaneous video sink functions
- *
- * Authored by Jonathan Matthew  <jonathan at kaolin.wh9.net>,
- *             Chris Lord        <chris at openedhand.com>
- *             Damien Lespiau    <damien.lespiau at intel.com>
- *             Matthew Allum     <mallum at openedhand.com>
- *             Plamena Manolova  <plamena.n.manolova at intel.com>
- *
- * Copyright (C) 2007, 2008 OpenedHand
- * Copyright (C) 2009, 2010, 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_SHADER_PRIVATE_H__
-#define __COGL_GST_SHADER_PRIVATE_H__
-
-extern const char
-_cogl_gst_shader_rgba_to_rgba_decl[];
-
-extern const char
-_cogl_gst_shader_yv12_to_rgba_decl[];
-
-extern const char
-_cogl_gst_shader_ayuv_to_rgba_decl[];
-
-extern const char
-_cogl_gst_shader_default_sample[];
-
-#endif /* __COGL_GST_SHADER_PRIVATE_H__ */
diff --git a/cogl-gst/cogl-gst-shader.c b/cogl-gst/cogl-gst-shader.c
deleted file mode 100644
index 7c34376..0000000
--- a/cogl-gst/cogl-gst-shader.c
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Cogl-GStreamer.
- *
- * GStreamer integration library for Cogl.
- *
- * cogl-gst-video-sink-private.h - Miscellaneous video sink functions
- *
- * Authored by Jonathan Matthew  <jonathan at kaolin.wh9.net>,
- *             Chris Lord        <chris at openedhand.com>
- *             Damien Lespiau    <damien.lespiau at intel.com>
- *             Matthew Allum     <mallum at openedhand.com>
- *             Plamena Manolova  <plamena.n.manolova at intel.com>
- *
- * Copyright (C) 2007, 2008 OpenedHand
- * Copyright (C) 2009, 2010, 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-shader-private.h"
-
-const char
-_cogl_gst_shader_rgba_to_rgba_decl[] =
-  "vec4\n"
-  "cogl_gst_sample_video (vec2 UV)\n"
-  "{\n"
-  "  return texture2D (cogl_sampler0, UV);\n"
-  "}\n";
-
-const char
-_cogl_gst_shader_yv12_to_rgba_decl[] =
-  "vec4\n"
-  "cogl_gst_sample_video (vec2 UV)\n"
-  "{\n"
-  "  float y = 1.1640625 * (texture2D (cogl_sampler0, UV).a - 0.0625);\n"
-  "  float u = texture2D (cogl_sampler1, UV).a - 0.5;\n"
-  "  float v = texture2D (cogl_sampler2, UV).a - 0.5;\n"
-  "  vec4 color;\n"
-  "  color.r = y + 1.59765625 * v;\n"
-  "  color.g = y - 0.390625 * u - 0.8125 * v;\n"
-  "  color.b = y + 2.015625 * u;\n"
-  "  color.a = 1.0;\n"
-  "  return color;\n"
-  "}\n";
-
-const char
-_cogl_gst_shader_ayuv_to_rgba_decl[] =
-  "vec4\n"
-  "cogl_gst_sample_video (vec2 UV)\n"
-  "{\n"
-  "  vec4 color = texture2D (cogl_sampler0, UV);\n"
-  "  float y = 1.1640625 * (color.g - 0.0625);\n"
-  "  float u = color.b - 0.5;\n"
-  "  float v = color.a - 0.5;\n"
-  "  color.a = color.r;\n"
-  "  color.r = y + 1.59765625 * v;\n"
-  "  color.g = y - 0.390625 * u - 0.8125 * v;\n"
-  "  color.b = y + 2.015625 * u;\n"
-  "  return color;\n"
-  "}\n";
-
-const char
-_cogl_gst_shader_default_sample[] =
-  "  cogl_layer *= cogl_gst_sample_video (cogl_tex_coord0_in.st);\n";
diff --git a/cogl-gst/cogl-gst-video-sink.c b/cogl-gst/cogl-gst-video-sink.c
index c36111c..321ded8 100644
--- a/cogl-gst/cogl-gst-video-sink.c
+++ b/cogl-gst/cogl-gst-video-sink.c
@@ -43,7 +43,6 @@
 #include <string.h>
 
 #include "cogl-gst-video-sink.h"
-#include "cogl-gst-shader-private.h"
 
 #define COGL_GST_TEXTURE_FLAGS \
        (COGL_TEXTURE_NO_SLICING | COGL_TEXTURE_NO_ATLAS)
@@ -99,6 +98,23 @@ typedef enum
   COGL_GST_RENDERER_NEEDS_GLSL = (1 << 0)
 } CoglGstRendererFlag;
 
+/* We want to cache the snippets instead of recreating a new one every
+ * time we initialise a pipeline so that if we end up recreating the
+ * same pipeline again then Cogl will be able to use the pipeline
+ * cache to avoid linking a redundant identical shader program */
+typedef struct
+{
+  CoglSnippet *vertex_snippet;
+  CoglSnippet *fragment_snippet;
+  CoglSnippet *default_sample_snippet;
+  int start_position;
+} SnippetCacheEntry;
+
+typedef struct
+{
+  GQueue entries;
+} SnippetCache;
+
 typedef struct _CoglGstSource
 {
   GSource source;
@@ -117,8 +133,9 @@ typedef struct _CoglGstRenderer
   CoglGstVideoFormat format;
   int flags;
   GstStaticCaps caps;
-  void (*init) (CoglGstVideoSink *sink);
-  void (*deinit) (CoglGstVideoSink *sink);
+  int n_layers;
+  void (*setup_pipeline) (CoglGstVideoSink *sink,
+                          CoglPipeline *pipeline);
   CoglBool (*upload) (CoglGstVideoSink *sink,
                       GstBuffer *buffer);
 } CoglGstRenderer;
@@ -136,7 +153,9 @@ struct _CoglGstVideoSinkPrivate
   GstCaps *caps;
   CoglGstRenderer *renderer;
   GstFlowReturn flow_return;
+  int custom_start;
   int free_layer;
+  CoglBool default_sample;
   GstVideoInfo info;
 };
 
@@ -168,7 +187,8 @@ cogl_gst_video_sink_attach_frame (CoglGstVideoSink *sink,
 
   for (i = 0; i < G_N_ELEMENTS (priv->frame); i++)
     if (priv->frame[i] != NULL)
-      cogl_pipeline_set_layer_texture (pln, i, priv->frame[i]);
+      cogl_pipeline_set_layer_texture (pln, i + priv->custom_start,
+                                       priv->frame[i]);
 
   return priv->free_layer;
 }
@@ -200,77 +220,139 @@ cogl_gst_video_sink_set_priority (CoglGstVideoSink *sink,
     g_source_set_priority ((GSource *) sink->priv->source, priority);
 }
 
-/* We want to cache the snippets instead of recreating a new one every
- * time we initialise a pipeline so that if we end up recreating the
- * same pipeline again then Cogl will be able to use the pipeline
- * cache to avoid linking a redundant identical shader program */
-typedef struct
-{
-  CoglSnippet *vertex_snippet;
-  CoglSnippet *fragment_snippet;
-} SnippetCache;
-
 static void
-create_template_pipeline (CoglGstVideoSink *sink,
-                          const char *decl,
-                          SnippetCache *snippet_cache,
-                          int n_layers)
+dirty_default_pipeline (CoglGstVideoSink *sink)
 {
   CoglGstVideoSinkPrivate *priv = sink->priv;
-  priv->free_layer = n_layers;
 
   if (priv->pipeline)
-    cogl_object_unref (priv->pipeline);
-  priv->pipeline = cogl_pipeline_new (priv->ctx);
+    {
+      cogl_object_unref (priv->pipeline);
+      priv->pipeline = NULL;
+    }
+}
+
+void
+cogl_gst_video_sink_set_first_layer (CoglGstVideoSink *sink,
+                                     int first_layer)
+{
+  if (first_layer != sink->priv->custom_start)
+    {
+      sink->priv->custom_start = first_layer;
+      dirty_default_pipeline (sink);
+
+      if (sink->priv->renderer)
+        sink->priv->free_layer = (sink->priv->custom_start +
+                                  sink->priv->renderer->n_layers);
+    }
+}
+
+void
+cogl_gst_video_sink_set_default_sample (CoglGstVideoSink *sink,
+                                        CoglBool default_sample)
+{
+  if (default_sample != sink->priv->default_sample)
+    {
+      sink->priv->default_sample = default_sample;
+      dirty_default_pipeline (sink);
+    }
+}
+
+void
+cogl_gst_video_sink_setup_pipeline (CoglGstVideoSink *sink,
+                                    CoglPipeline *pipeline)
+{
+  sink->priv->renderer->setup_pipeline (sink, pipeline);
+}
+
+static SnippetCacheEntry *
+get_cache_entry (CoglGstVideoSink *sink,
+                 SnippetCache *cache)
+{
+  CoglGstVideoSinkPrivate *priv = sink->priv;
+  GList *l;
+
+  for (l = cache->entries.head; l; l = l->next)
+    {
+      SnippetCacheEntry *entry = l->data;
+
+      if (entry->start_position == priv->custom_start)
+        return entry;
+    }
+
+  return NULL;
+}
+
+static SnippetCacheEntry *
+add_cache_entry (CoglGstVideoSink *sink,
+                 SnippetCache *cache,
+                 const char *decl)
+{
+  CoglGstVideoSinkPrivate *priv = sink->priv;
+  SnippetCacheEntry *entry = g_slice_new (SnippetCacheEntry);
+  char *default_source;
+
+  entry->start_position = priv->custom_start;
+
+  entry->vertex_snippet =
+    cogl_snippet_new (COGL_SNIPPET_HOOK_VERTEX_GLOBALS,
+                      decl,
+                      NULL /* post */);
+  entry->fragment_snippet =
+    cogl_snippet_new (COGL_SNIPPET_HOOK_FRAGMENT_GLOBALS,
+                      decl,
+                      NULL /* post */);
+
+  default_source =
+    g_strdup_printf ("  cogl_layer *= cogl_gst_sample_video%i "
+                     "(cogl_tex_coord%i_in.st);\n",
+                     priv->custom_start,
+                     priv->custom_start);
+  entry->default_sample_snippet =
+    cogl_snippet_new (COGL_SNIPPET_HOOK_LAYER_FRAGMENT,
+                      NULL, /* declarations */
+                      default_source);
+  g_free (default_source);
+
+  g_queue_push_head (&cache->entries, entry);
+
+  return entry;
+}
+
+static void
+setup_pipeline_from_cache_entry (CoglGstVideoSink *sink,
+                                 CoglPipeline *pipeline,
+                                 SnippetCacheEntry *cache_entry,
+                                 int n_layers)
+{
+  CoglGstVideoSinkPrivate *priv = sink->priv;
 
-  if (decl)
+  if (cache_entry)
     {
-      static CoglSnippet *default_sample_snippet = NULL;
       int i;
 
       /* The global sampling function gets added to both the fragment
        * and vertex stages. The hope is that the GLSL compiler will
        * easily remove the dead code if it's not actually used */
-      if (snippet_cache->vertex_snippet == NULL)
-        snippet_cache->vertex_snippet =
-          cogl_snippet_new (COGL_SNIPPET_HOOK_VERTEX_GLOBALS,
-                            decl,
-                            NULL /* post */);
-      cogl_pipeline_add_snippet (priv->pipeline,
-                                 snippet_cache->vertex_snippet);
-
-      if (snippet_cache->fragment_snippet == NULL)
-        snippet_cache->fragment_snippet =
-          cogl_snippet_new (COGL_SNIPPET_HOOK_FRAGMENT_GLOBALS,
-                            decl,
-                            NULL /* post */);
-      cogl_pipeline_add_snippet (priv->pipeline,
-                                 snippet_cache->fragment_snippet);
+      cogl_pipeline_add_snippet (pipeline, cache_entry->vertex_snippet);
+      cogl_pipeline_add_snippet (pipeline, cache_entry->fragment_snippet);
 
       /* Set all of the layers to just directly copy from the previous
        * layer so that it won't redundantly generate code to sample
        * the intermediate textures */
       for (i = 0; i < n_layers; i++)
-        cogl_pipeline_set_layer_combine (priv->pipeline,
-                                         i,
+        cogl_pipeline_set_layer_combine (pipeline,
+                                         priv->custom_start + i,
                                          "RGBA=REPLACE(PREVIOUS)",
                                          NULL);
 
-      if (default_sample_snippet == NULL)
-        {
-          default_sample_snippet =
-            cogl_snippet_new (COGL_SNIPPET_HOOK_LAYER_FRAGMENT,
-                              NULL, /* declarations */
-                              _cogl_gst_shader_default_sample);
-        }
-      cogl_pipeline_add_layer_snippet (priv->pipeline,
-                                       n_layers - 1,
-                                       default_sample_snippet);
+      if (priv->default_sample)
+        cogl_pipeline_add_layer_snippet (pipeline,
+                                         priv->custom_start + n_layers - 1,
+                                         cache_entry->default_sample_snippet);
     }
 
   priv->frame_dirty = TRUE;
-
-  g_signal_emit (sink, video_sink_signals[PIPELINE_READY_SIGNAL], 0, NULL);
 }
 
 CoglPipeline *
@@ -278,23 +360,24 @@ cogl_gst_video_sink_get_pipeline (CoglGstVideoSink *vt)
 {
   CoglGstVideoSinkPrivate *priv = vt->priv;
 
-  if (priv->frame_dirty)
+  if (priv->pipeline == NULL)
+    {
+      priv->pipeline = cogl_pipeline_new (priv->ctx);
+      cogl_gst_video_sink_setup_pipeline (vt, priv->pipeline);
+      cogl_gst_video_sink_attach_frame (vt, priv->pipeline);
+      priv->frame_dirty = FALSE;
+    }
+  else if (priv->frame_dirty)
     {
       CoglPipeline *pipeline = cogl_pipeline_copy (priv->pipeline);
       cogl_object_unref (priv->pipeline);
       priv->pipeline = pipeline;
 
       cogl_gst_video_sink_attach_frame (vt, pipeline);
-
       priv->frame_dirty = FALSE;
     }
 
-  return vt->priv->pipeline;
-}
-
-static void
-cogl_gst_dummy_deinit (CoglGstVideoSink *sink)
-{
+  return priv->pipeline;
 }
 
 static void
@@ -317,21 +400,35 @@ clear_frame_textures (CoglGstVideoSink *sink)
 }
 
 static void
-cogl_gst_rgb_init (CoglGstVideoSink *sink)
+cogl_gst_rgb_setup_pipeline (CoglGstVideoSink *sink,
+                             CoglPipeline *pipeline)
 {
   CoglGstVideoSinkPrivate *priv = sink->priv;
 
   if (cogl_has_feature (priv->ctx, COGL_FEATURE_ID_GLSL))
     {
       static SnippetCache snippet_cache;
+      SnippetCacheEntry *entry = get_cache_entry (sink, &snippet_cache);
 
-      create_template_pipeline (sink,
-                                _cogl_gst_shader_rgba_to_rgba_decl,
-                                &snippet_cache,
-                                1);
+      if (entry == NULL)
+        {
+          char *source;
+
+          source =
+            g_strdup_printf ("vec4\n"
+                             "cogl_gst_sample_video%i (vec2 UV)\n"
+                             "{\n"
+                             "  return texture2D (cogl_sampler%i, UV);\n"
+                             "}\n",
+                             priv->custom_start,
+                             priv->custom_start);
+
+          setup_pipeline_from_cache_entry (sink, pipeline, entry, 1);
+          g_free (source);
+        }
     }
   else
-    create_template_pipeline (sink, NULL, NULL, 1);
+    setup_pipeline_from_cache_entry (sink, pipeline, NULL, 1);
 }
 
 static CoglBool
@@ -376,8 +473,8 @@ static CoglGstRenderer rgb24_renderer =
   COGL_GST_RGB24,
   0,
   GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("{ RGB, BGR }")),
-  cogl_gst_rgb_init,
-  cogl_gst_dummy_deinit,
+  1, /* n_layers */
+  cogl_gst_rgb_setup_pipeline,
   cogl_gst_rgb24_upload,
 };
 
@@ -423,8 +520,8 @@ static CoglGstRenderer rgb32_renderer =
   COGL_GST_RGB32,
   0,
   GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("{ RGBA, BGRA }")),
-  cogl_gst_rgb_init,
-  cogl_gst_dummy_deinit,
+  1, /* n_layers */
+  cogl_gst_rgb_setup_pipeline,
   cogl_gst_rgb32_upload,
 };
 
@@ -474,14 +571,44 @@ map_fail:
 }
 
 static void
-cogl_gst_yv12_glsl_init (CoglGstVideoSink *sink)
+cogl_gst_yv12_glsl_setup_pipeline (CoglGstVideoSink *sink,
+                                   CoglPipeline *pipeline)
 {
+  CoglGstVideoSinkPrivate *priv = sink->priv;
   static SnippetCache snippet_cache;
+  SnippetCacheEntry *entry;
+
+  entry = get_cache_entry (sink, &snippet_cache);
+
+  if (entry == NULL)
+    {
+      char *source;
+
+      source =
+        g_strdup_printf ("vec4\n"
+                         "cogl_gst_sample_video%i (vec2 UV)\n"
+                         "{\n"
+                         "  float y = 1.1640625 * "
+                         "(texture2D (cogl_sampler%i, UV).a - 0.0625);\n"
+                         "  float u = texture2D (cogl_sampler%i, UV).a - 0.5;\n"
+                         "  float v = texture2D (cogl_sampler%i, UV).a - 0.5;\n"
+                         "  vec4 color;\n"
+                         "  color.r = y + 1.59765625 * v;\n"
+                         "  color.g = y - 0.390625 * u - 0.8125 * v;\n"
+                         "  color.b = y + 2.015625 * u;\n"
+                         "  color.a = 1.0;\n"
+                         "  return color;\n"
+                         "}\n",
+                         priv->custom_start,
+                         priv->custom_start,
+                         priv->custom_start + 1,
+                         priv->custom_start + 2);
+
+      entry = add_cache_entry (sink, &snippet_cache, source);
+      g_free (source);
+    }
 
-  create_template_pipeline (sink,
-                            _cogl_gst_shader_yv12_to_rgba_decl,
-                            &snippet_cache,
-                            3);
+  setup_pipeline_from_cache_entry (sink, pipeline, entry, 3);
 }
 
 static CoglGstRenderer yv12_glsl_renderer =
@@ -490,42 +617,57 @@ static CoglGstRenderer yv12_glsl_renderer =
   COGL_GST_YV12,
   COGL_GST_RENDERER_NEEDS_GLSL,
   GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("YV12")),
-  cogl_gst_yv12_glsl_init,
-  cogl_gst_dummy_deinit,
+  3, /* n_layers */
+  cogl_gst_yv12_glsl_setup_pipeline,
   cogl_gst_yv12_upload,
 };
 
-static void
-cogl_gst_i420_glsl_init (CoglGstVideoSink *sink)
-{
-  static SnippetCache snippet_cache;
-
-  create_template_pipeline (sink,
-                            _cogl_gst_shader_yv12_to_rgba_decl,
-                            &snippet_cache,
-                            3);
-}
-
 static CoglGstRenderer i420_glsl_renderer =
 {
   "I420 glsl",
   COGL_GST_I420,
   COGL_GST_RENDERER_NEEDS_GLSL,
   GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("I420")),
-  cogl_gst_i420_glsl_init,
-  cogl_gst_dummy_deinit,
+  3, /* n_layers */
+  cogl_gst_yv12_glsl_setup_pipeline,
   cogl_gst_yv12_upload,
 };
 
 static void
-cogl_gst_ayuv_glsl_init (CoglGstVideoSink *sink)
+cogl_gst_ayuv_glsl_setup_pipeline (CoglGstVideoSink *sink,
+                                   CoglPipeline *pipeline)
 {
+  CoglGstVideoSinkPrivate *priv = sink->priv;
   static SnippetCache snippet_cache;
+  SnippetCacheEntry *entry;
+
+  entry = get_cache_entry (sink, &snippet_cache);
+
+  if (entry == NULL)
+    {
+      char *source;
+
+      source
+        = g_strdup_printf ("vec4\n"
+                           "cogl_gst_sample_video%i (vec2 UV)\n"
+                           "{\n"
+                           "  vec4 color = texture2D (cogl_sampler%i, UV);\n"
+                           "  float y = 1.1640625 * (color.g - 0.0625);\n"
+                           "  float u = color.b - 0.5;\n"
+                           "  float v = color.a - 0.5;\n"
+                           "  color.a = color.r;\n"
+                           "  color.r = y + 1.59765625 * v;\n"
+                           "  color.g = y - 0.390625 * u - 0.8125 * v;\n"
+                           "  color.b = y + 2.015625 * u;\n"
+                           "  return color;\n"
+                           "}\n", priv->custom_start,
+                           priv->custom_start);
+
+      entry = add_cache_entry (sink, &snippet_cache, source);
+      g_free (source);
+    }
 
-  create_template_pipeline (sink,
-                            _cogl_gst_shader_ayuv_to_rgba_decl,
-                            &snippet_cache,
-                            1);
+  setup_pipeline_from_cache_entry (sink, pipeline, entry, 3);
 }
 
 static CoglBool
@@ -565,8 +707,8 @@ static CoglGstRenderer ayuv_glsl_renderer =
   COGL_GST_AYUV,
   COGL_GST_RENDERER_NEEDS_GLSL,
   GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("AYUV")),
-  cogl_gst_ayuv_glsl_init,
-  cogl_gst_dummy_deinit,
+  3, /* n_layers */
+  cogl_gst_ayuv_glsl_setup_pipeline,
   cogl_gst_ayuv_upload,
 };
 
@@ -814,14 +956,21 @@ cogl_gst_source_dispatch (GSource *source,
         gst_pad_get_current_caps (GST_BASE_SINK_PAD ((GST_BASE_SINK
                 (gst_source->sink))));
 
-      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->renderer->init (gst_source->sink);
       gst_source->has_new_caps = FALSE;
+      priv->free_layer = priv->custom_start + priv->renderer->n_layers;
+
+      dirty_default_pipeline (gst_source->sink);
+
+      /* We are now in a state where we could generate the pipeline if
+       * the application requests it so we can emit the signal.
+       * However we'll actually generate the pipeline lazily only if
+       * the application actually asks for it. */
+      g_signal_emit (gst_source->sink,
+                     video_sink_signals[PIPELINE_READY_SIGNAL],
+                     0 /* detail */);
     }
 
   buffer = gst_source->buffer;
@@ -942,12 +1091,6 @@ cogl_gst_video_sink_dispose (GObject *object)
 
   clear_frame_textures (self);
 
-  if (priv->renderer)
-    {
-      priv->renderer->deinit (self);
-      priv->renderer = NULL;
-    }
-
   if (priv->pipeline)
     {
       cogl_object_unref (priv->pipeline);
@@ -1113,6 +1256,8 @@ 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);
+  sink->priv->custom_start = 0;
+  sink->priv->default_sample = TRUE;
 
   return sink;
 }
diff --git a/cogl-gst/cogl-gst-video-sink.h b/cogl-gst/cogl-gst-video-sink.h
index 7ca054b..0bdf679 100644
--- a/cogl-gst/cogl-gst-video-sink.h
+++ b/cogl-gst/cogl-gst-video-sink.h
@@ -117,6 +117,17 @@ int
 cogl_gst_video_sink_attach_frame (CoglGstVideoSink *sink,
                                   CoglPipeline *pln);
 
+void
+cogl_gst_video_sink_set_first_layer (CoglGstVideoSink *sink,
+                                     int first_layer);
+
+void
+cogl_gst_video_sink_set_default_sample (CoglGstVideoSink *sink,
+                                        CoglBool default_sample);
+
+void
+cogl_gst_video_sink_setup_pipeline (CoglGstVideoSink *sink,
+                                    CoglPipeline *pipeline);
 G_END_DECLS
 
 #endif
-- 
1.7.11.3.g3c3efa5



More information about the Cogl mailing list