[Cogl] [PATCH 05/13] cogl-gst: video-sink: add NV12 support

Lionel Landwerlin llandwerlin at gmail.com
Mon Dec 9 03:17:52 PST 2013


Based on a patch from Edward Hervey and Matthieu Bouron for
Clutter-Gst :

https://bugzilla.gnome.org/show_bug.cgi?id=712832
---
 cogl-gst/cogl-gst-video-sink.c | 113 +++++++++++++++++++++++++++++++++++++++--
 1 file changed, 110 insertions(+), 3 deletions(-)

diff --git a/cogl-gst/cogl-gst-video-sink.c b/cogl-gst/cogl-gst-video-sink.c
index 94e54bc..57dd3e9 100644
--- a/cogl-gst/cogl-gst-video-sink.c
+++ b/cogl-gst/cogl-gst-video-sink.c
@@ -57,7 +57,8 @@
                        "RGBA," \
                        "BGRA," \
                        "RGB," \
-                       "BGR }"
+                       "BGR," \
+                       "NV12 }"
 
 #define COGL_GST_PARAM_STATIC        \
   (G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)
@@ -106,7 +107,8 @@ typedef enum
   COGL_GST_AYUV,
   COGL_GST_YV12,
   COGL_GST_SURFACE,
-  COGL_GST_I420
+  COGL_GST_I420,
+  COGL_GST_NV12
 } CoglGstVideoFormat;
 
 typedef enum
@@ -865,6 +867,108 @@ static CoglGstRenderer ayuv_glsl_renderer =
   cogl_gst_ayuv_upload,
 };
 
+/**/
+
+static void
+cogl_gst_nv12_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;\n"
+                           "  float y = 1.1640625 * (texture2D (cogl_sampler%i, UV).r - 0.0625);\n"
+                           "  float uvr = int (texture2D (cogl_sampler%i, UV).r * 32);\n"
+                           "  float uvg = int (texture2D (cogl_sampler%i, UV).g * 64);\n"
+                           "  float uvb = int (texture2D (cogl_sampler%i, UV).b * 32);\n"
+                           "  float tg = floor (uvg / 8.0);\n"
+                           "  float u = (uvb + (uvg - tg * 8.0) * 32.0) / 256.0;\n"
+                           "  float v = (uvr * 8.0 + tg) / 256.0;\n"
+                           "  u -= 0.5;\n"
+                           "  v -= 0.5;\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 + 1,
+                           priv->custom_start + 1);
+
+      entry = add_cache_entry (sink, &snippet_cache, source);
+      g_free (source);
+    }
+
+  setup_pipeline_from_cache_entry (sink, pipeline, entry, 2);
+}
+
+static CoglBool
+cogl_gst_nv12_upload (CoglGstVideoSink *sink,
+                      GstBuffer *buffer)
+{
+  CoglGstVideoSinkPrivate *priv = sink->priv;
+  GstVideoFrame frame;
+
+  if (!gst_video_frame_map (&frame, &priv->info, buffer, GST_MAP_READ))
+    goto map_fail;
+
+  clear_frame_textures (sink);
+
+  priv->frame[0] =
+    video_texture_new_from_data (priv->ctx,
+                                 GST_VIDEO_INFO_COMP_WIDTH (&priv->info, 0),
+                                 GST_VIDEO_INFO_COMP_HEIGHT (&priv->info, 0),
+                                 COGL_PIXEL_FORMAT_G_8, COGL_PIXEL_FORMAT_G_8,
+                                 priv->info.stride[0], frame.data[0], NULL);
+
+  priv->frame[1] =
+    video_texture_new_from_data (priv->ctx,
+                                 GST_VIDEO_INFO_COMP_WIDTH (&priv->info, 1),
+                                 GST_VIDEO_INFO_COMP_HEIGHT (&priv->info, 1),
+                                 COGL_PIXEL_FORMAT_RGB_565, COGL_PIXEL_FORMAT_RGB_565,
+                                 priv->info.stride[1], frame.data[1], NULL);
+
+  gst_video_frame_unmap (&frame);
+
+  return TRUE;
+
+map_fail:
+  {
+    GST_ERROR_OBJECT (sink, "Could not map incoming video frame");
+    return FALSE;
+  }
+}
+
+static CoglGstRenderer nv12_glsl_renderer =
+{
+  "NV12 glsl",
+  COGL_GST_NV12,
+  COGL_GST_RENDERER_NEEDS_GLSL,
+  GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE_WITH_FEATURES("memory:SystemMemory", "NV12")),
+  2, /* n_layers */
+  {
+    COGL_PIPELINE_FILTER_LINEAR_MIPMAP_LINEAR, COGL_PIPELINE_FILTER_LINEAR,
+    COGL_PIPELINE_FILTER_LINEAR_MIPMAP_LINEAR, COGL_PIPELINE_FILTER_NEAREST,
+  },
+  cogl_gst_nv12_glsl_setup_pipeline,
+  cogl_gst_nv12_upload,
+};
+
+/**/
+
 static GSList*
 cogl_gst_build_renderers_list (CoglContext *ctx)
 {
@@ -878,6 +982,7 @@ cogl_gst_build_renderers_list (CoglContext *ctx)
     &yv12_glsl_renderer,
     &i420_glsl_renderer,
     &ayuv_glsl_renderer,
+    &nv12_glsl_renderer,
     NULL
   };
 
@@ -1004,7 +1109,9 @@ cogl_gst_video_sink_parse_caps (GstCaps *caps,
       break;
     case GST_VIDEO_FORMAT_AYUV:
       format = COGL_GST_AYUV;
-      bgr = FALSE;
+      break;
+    case GST_VIDEO_FORMAT_NV12:
+      format = COGL_GST_NV12;
       break;
     case GST_VIDEO_FORMAT_RGB:
       format = COGL_GST_RGB24;
-- 
1.8.5



More information about the Cogl mailing list