glimagesink: correctly use the sync meta across multiple contexts
authorMatthew Waters <matthew@centricular.com>
Tue, 19 May 2015 06:22:00 +0000 (16:22 +1000)
committerTim-Philipp Müller <tim@centricular.com>
Sat, 9 Dec 2017 19:32:01 +0000 (19:32 +0000)
1. Set the sync point after the (possible) upload has occured
2. Wait in the correct GL context (the draw context)

Note: We don't add the GL sync meta to the input buffer as it's not
writable and a copy would be expensive.

ext/gl/gstglimagesink.c
ext/gl/gstglimagesink.h

index c9bc67e..75d3b01 100644 (file)
@@ -832,6 +832,7 @@ gst_glimage_sink_query (GstBaseSink * bsink, GstQuery * query)
         gst_buffer_unref (buf);
 
       gst_buffer_replace (&glimage_sink->next_buffer, NULL);
+      gst_buffer_replace (&glimage_sink->next_sync, NULL);
 
       res = GST_BASE_SINK_CLASS (parent_class)->query (bsink, query);
       break;
@@ -901,13 +902,18 @@ gst_glimage_sink_change_state (GstElement * element, GstStateChange transition)
        * to avoid drawing
        */
       GST_GLIMAGE_SINK_LOCK (glimage_sink);
+      if (glimage_sink->stored_sync)
+        gst_buffer_unref (glimage_sink->stored_sync);
+      glimage_sink->stored_sync = NULL;
+
       glimage_sink->redisplay_texture = 0;
       if (glimage_sink->stored_buffer) {
         gst_buffer_unref (glimage_sink->stored_buffer);
         glimage_sink->stored_buffer = NULL;
       }
-      GST_GLIMAGE_SINK_UNLOCK (glimage_sink);
       gst_buffer_replace (&glimage_sink->next_buffer, NULL);
+      gst_buffer_replace (&glimage_sink->next_sync, NULL);
+      GST_GLIMAGE_SINK_UNLOCK (glimage_sink);
 
       glimage_sink->window_id = 0;
       /* but do not reset glimage_sink->new_window_id */
@@ -1095,6 +1101,8 @@ gst_glimage_sink_prepare (GstBaseSink * bsink, GstBuffer * buf)
 {
   GstGLImageSink *glimage_sink;
   GstVideoFrame gl_frame;
+  GstBuffer *next_sync, *old_sync, *old_buffer;
+  GstGLSyncMeta *sync_meta;
 
   glimage_sink = GST_GLIMAGE_SINK (bsink);
 
@@ -1113,9 +1121,24 @@ gst_glimage_sink_prepare (GstBaseSink * bsink, GstBuffer * buf)
     goto upload_failed;
   }
 
+  next_sync = gst_buffer_new ();
+  sync_meta = gst_buffer_add_gl_sync_meta (glimage_sink->context, next_sync);
+  gst_gl_sync_meta_set_sync_point (sync_meta, glimage_sink->context);
+
+  GST_GLIMAGE_SINK_LOCK (glimage_sink);
   glimage_sink->next_tex = *(guint *) gl_frame.data[0];
 
-  gst_buffer_replace (&glimage_sink->next_buffer, buf);
+  old_buffer = glimage_sink->next_buffer;
+  glimage_sink->next_buffer = gst_buffer_ref (buf);
+
+  old_sync = glimage_sink->next_sync;
+  glimage_sink->next_sync = next_sync;
+  GST_GLIMAGE_SINK_UNLOCK (glimage_sink);
+
+  if (old_buffer)
+    gst_buffer_unref (old_buffer);
+  if (old_sync)
+    gst_buffer_unref (old_sync);
 
   gst_video_frame_unmap (&gl_frame);
 
@@ -1142,7 +1165,7 @@ static GstFlowReturn
 gst_glimage_sink_show_frame (GstVideoSink * vsink, GstBuffer * buf)
 {
   GstGLImageSink *glimage_sink;
-  GstBuffer *stored_buffer;
+  GstBuffer *stored_buffer, *old_sync;
 
   GST_TRACE ("rendering buffer:%p", buf);
 
@@ -1159,6 +1182,10 @@ gst_glimage_sink_show_frame (GstVideoSink * vsink, GstBuffer * buf)
   glimage_sink->redisplay_texture = glimage_sink->next_tex;
   stored_buffer = glimage_sink->stored_buffer;
   glimage_sink->stored_buffer = gst_buffer_ref (glimage_sink->next_buffer);
+
+  old_sync = glimage_sink->stored_sync;
+  glimage_sink->stored_sync = gst_buffer_ref (glimage_sink->next_sync);
+
   GST_GLIMAGE_SINK_UNLOCK (glimage_sink);
 
   /* Ask the underlying window to redraw its content */
@@ -1169,6 +1196,8 @@ gst_glimage_sink_show_frame (GstVideoSink * vsink, GstBuffer * buf)
 
   if (stored_buffer)
     gst_buffer_unref (stored_buffer);
+  if (old_sync)
+    gst_buffer_unref (old_sync);
 
   if (g_atomic_int_get (&glimage_sink->to_quit) != 0) {
     GST_ELEMENT_ERROR (glimage_sink, RESOURCE, NOT_FOUND,
@@ -1522,9 +1551,9 @@ gst_glimage_sink_on_draw (GstGLImageSink * gl_sink)
     gl_sink->caps_change = FALSE;
   }
 
-  sync_meta = gst_buffer_get_gl_sync_meta (gl_sink->stored_buffer);
+  sync_meta = gst_buffer_get_gl_sync_meta (gl_sink->stored_sync);
   if (sync_meta)
-    gst_gl_sync_meta_wait (sync_meta, gl_sink->context);
+    gst_gl_sync_meta_wait (sync_meta, gst_gl_context_get_current ());
 
   /* make sure that the environnement is clean */
   gst_gl_context_clear_shader (gl_sink->context);
index 4fd2195..52db017 100644 (file)
@@ -68,6 +68,7 @@ struct _GstGLImageSink
 
     guint      next_tex;
     GstBuffer *next_buffer;
+    GstBuffer *next_sync;
 
     volatile gint to_quit;
     gboolean keep_aspect_ratio;
@@ -78,6 +79,7 @@ struct _GstGLImageSink
     /* avoid replacing the stored_buffer while drawing */
     GMutex drawing_lock;
     GstBuffer *stored_buffer;
+    GstBuffer *stored_sync;
     GLuint redisplay_texture;
 
     gboolean caps_change;