[Cogl] [PATCH 2/4] gst-video-sink: Implement a dirty flag for fetching the pipeline

Neil Roberts neil at linux.intel.com
Fri Mar 8 09:33:11 PST 2013


Previously whenever the pipeline is fetched from the video sink it
would always make a copy of the pipeline and update the textures on
it. It's not totally unlikely that an application would query the
pipeline multiple times per frame so it seems worthwhile to prevent it
allocating a new pipeline if the frames haven't changed. To make this
work this patch adds a dirty flag which gets set whenever there are
new textures. The sink now only updates the pipeline when the flag is
dirty.

As a side effect this also fixes it so that whenever a new frame is
created it makes sure to clear all of the frame textures, not just the
ones for the number of layers that the current renderer uses. As far
as I can tell it might be possible for the renderer to change using a
single sink and that would cause it to continue adding frame textures
from the old renderer if the number of layers changed.

There's no need to explicitly set the frame textures to NULL in the
init function because the private data is always cleared to zero on
allocation anyway.
---
 cogl-gst/cogl-gst-video-sink.c | 171 +++++++++++++++++++----------------------
 1 file changed, 81 insertions(+), 90 deletions(-)

diff --git a/cogl-gst/cogl-gst-video-sink.c b/cogl-gst/cogl-gst-video-sink.c
index 49e115d..205ed92 100644
--- a/cogl-gst/cogl-gst-video-sink.c
+++ b/cogl-gst/cogl-gst-video-sink.c
@@ -132,7 +132,8 @@ struct _CoglGstVideoSinkPrivate
 {
   CoglContext *ctx;
   CoglPipeline *pipeline;
-  CoglTexture *frame [3];
+  CoglTexture *frame[3];
+  CoglBool frame_dirty;
   CoglGstVideoFormat format;
   CoglBool bgr;
   CoglGstSource *source;
@@ -170,14 +171,14 @@ int
 cogl_gst_video_sink_attach_frame (CoglGstVideoSink *sink,
                                   CoglPipeline *pln)
 {
-  if (sink->priv->frame[0] != NULL)
-    cogl_pipeline_set_layer_texture (pln, 0, sink->priv->frame[0]);
-  if (sink->priv->frame[1] != NULL)
-    cogl_pipeline_set_layer_texture (pln, 1, sink->priv->frame[1]);
-  if (sink->priv->frame[2] != NULL)
-    cogl_pipeline_set_layer_texture (pln, 2, sink->priv->frame[2]);
+  CoglGstVideoSinkPrivate *priv = sink->priv;
+  int i;
 
-  return sink->priv->free_layer;
+  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]);
+
+  return priv->free_layer;
 }
 
 static CoglBool
@@ -269,35 +270,27 @@ create_template_pipeline (CoglGstVideoSink *sink,
                                        default_sample_snippet);
     }
 
+  priv->frame_dirty = TRUE;
+
   g_signal_emit (sink, video_sink_signals[PIPELINE_READY_SIGNAL], 0, NULL);
 }
 
-static void
-create_paint_pipeline (CoglGstVideoSink *sink,
-                       CoglTexture *tex0,
-                       CoglTexture *tex1,
-                       CoglTexture *tex2)
+CoglPipeline*
+cogl_gst_video_sink_get_pipeline (CoglGstVideoSink *vt)
 {
-  CoglGstVideoSinkPrivate *priv = sink->priv;
+  CoglGstVideoSinkPrivate *priv = vt->priv;
 
-  CoglPipeline *pln = cogl_pipeline_copy (priv->pipeline);
-  cogl_object_unref (priv->pipeline);
-  priv->pipeline = pln;
+  if (priv->frame_dirty)
+    {
+      CoglPipeline *pipeline = cogl_pipeline_copy (priv->pipeline);
+      cogl_object_unref (priv->pipeline);
+      priv->pipeline = pipeline;
 
-  if (tex0 != NULL)
-    cogl_pipeline_set_layer_texture (priv->pipeline, 0, tex0);
-  if (tex1 != NULL)
-    cogl_pipeline_set_layer_texture (priv->pipeline, 1, tex1);
-  if (tex2 != NULL)
-    cogl_pipeline_set_layer_texture (priv->pipeline, 2, tex2);
-}
+      cogl_gst_video_sink_attach_frame (vt, pipeline);
+
+      priv->frame_dirty = FALSE;
+    }
 
-CoglPipeline*
-cogl_gst_video_sink_get_pipeline (CoglGstVideoSink *vt)
-{
-  if (vt->priv->frame[0])
-    create_paint_pipeline (vt, vt->priv->frame[0], vt->priv->frame[1],
-                           vt->priv->frame[2]);
   return vt->priv->pipeline;
 }
 
@@ -307,6 +300,25 @@ cogl_gst_dummy_deinit (CoglGstVideoSink *sink)
 }
 
 static void
+clear_frame_textures (CoglGstVideoSink *sink)
+{
+  CoglGstVideoSinkPrivate *priv = sink->priv;
+  int i;
+
+  for (i = 0; i < G_N_ELEMENTS (priv->frame); i++)
+    {
+      if (priv->frame[i] == NULL)
+        break;
+      else
+        cogl_object_unref (priv->frame[i]);
+    }
+
+  memset (priv->frame, 0, sizeof (priv->frame));
+
+  priv->frame_dirty = TRUE;
+}
+
+static void
 cogl_gst_rgb_init (CoglGstVideoSink *sink)
 {
   CoglGstVideoSinkPrivate *priv = sink->priv;
@@ -340,16 +352,14 @@ cogl_gst_rgb24_upload (CoglGstVideoSink *sink,
   if (!gst_video_frame_map (&frame, &priv->info, buffer, GST_MAP_READ))
     goto map_fail;
 
-  if (priv->frame[0])
-    {
-      cogl_object_unref (priv->frame[0]);
-      priv->frame[0] = NULL;
-    }
+  clear_frame_textures (sink);
 
   priv->frame[0] = 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);
+                                               priv->info.height,
+                                               COGL_GST_TEXTURE_FLAGS,
+                                               format, format,
+                                               priv->info.stride[0],
+                                               frame.data[0], NULL);
 
   gst_video_frame_unmap (&frame);
 
@@ -390,16 +400,14 @@ cogl_gst_rgb32_upload (CoglGstVideoSink *sink,
   if (!gst_video_frame_map (&frame, &priv->info, buffer, GST_MAP_READ))
     goto map_fail;
 
-  if (priv->frame[0])
-    {
-      cogl_object_unref (priv->frame[0]);
-      priv->frame[0] = NULL;
-    }
+  clear_frame_textures (sink);
 
   priv->frame[0] = 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);
+                                               priv->info.height,
+                                               COGL_GST_TEXTURE_FLAGS,
+                                               format, format,
+                                               priv->info.stride[0],
+                                               frame.data[0], NULL);
 
   gst_video_frame_unmap (&frame);
 
@@ -434,37 +442,28 @@ cogl_gst_yv12_upload (CoglGstVideoSink *sink,
   if (!gst_video_frame_map (&frame, &priv->info, buffer, GST_MAP_READ))
     goto map_fail;
 
-  if (priv->frame[0] && priv->frame[1] && priv->frame[2])
-    {
-      cogl_object_unref (priv->frame[0]);
-      cogl_object_unref (priv->frame[1]);
-      cogl_object_unref (priv->frame[2]);
-
-      priv->frame[0] = NULL;
-      priv->frame[1] = NULL;
-      priv->frame[2] = NULL;
-    }
+  clear_frame_textures (sink);
 
   priv->frame[0] =
-     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);
+    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);
 
   priv->frame[1] =
-     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);
+    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);
 
   priv->frame[2] =
-     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);
+    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);
 
@@ -543,16 +542,14 @@ cogl_gst_ayuv_upload (CoglGstVideoSink *sink,
   if (!gst_video_frame_map (&frame, &priv->info, buffer, GST_MAP_READ))
     goto map_fail;
 
-  if (priv->frame[0])
-    {
-      cogl_object_unref (priv->frame[0]);
-      priv->frame[0] = NULL;
-    }
+  clear_frame_textures (sink);
 
   priv->frame[0] = 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);
+                                               priv->info.height,
+                                               COGL_GST_TEXTURE_FLAGS,
+                                               format, format,
+                                               priv->info.stride[0],
+                                               frame.data[0], NULL);
 
   gst_video_frame_unmap (&frame);
 
@@ -607,16 +604,13 @@ cogl_gst_hw_upload (CoglGstVideoSink *sink,
       unsigned int gl_tar;
       GValue value = {0};
 
-      if (priv->frame[0])
-        {
-          cogl_object_unref (priv->frame[0]);
-          priv->frame[0] = NULL;
-        }
+      clear_frame_textures (sink);
 
       priv->frame[0] = cogl_texture_new_with_size (priv->ctx, priv->info.width,
-                                        priv->info.height,
-                                        COGL_GST_TEXTURE_FLAGS,
-                                        COGL_PIXEL_FORMAT_BGRA_8888, NULL);
+                                                   priv->info.height,
+                                                   COGL_GST_TEXTURE_FLAGS,
+                                                   COGL_PIXEL_FORMAT_BGRA_8888,
+                                                   NULL);
 
       cogl_pipeline_set_layer_texture (priv->pipeline, 0, priv->frame[0]);
       cogl_texture_get_gl_texture (tex, &gl_texture, &gl_target);
@@ -972,9 +966,6 @@ cogl_gst_video_sink_init (CoglGstVideoSink *sink)
   sink->priv = priv = G_TYPE_INSTANCE_GET_PRIVATE (sink,
                                                    COGL_GST_TYPE_VIDEO_SINK,
                                                    CoglGstVideoSinkPrivate);
-  sink->priv->frame[0] = NULL;
-  sink->priv->frame[1] = NULL;
-  sink->priv->frame[2] = NULL;
 }
 
 static GstFlowReturn
-- 
1.7.11.3.g3c3efa5



More information about the Cogl mailing list