glupload: Keep input frame mapped as long as needed
authorNicolas Dufresne <nicolas.dufresne@collabora.com>
Mon, 27 Jul 2015 20:58:22 +0000 (16:58 -0400)
committerNicolas Dufresne <nicolas.dufresne@collabora.co.uk>
Tue, 28 Jul 2015 12:54:29 +0000 (08:54 -0400)
When performing a raw upload, we need to keep the raw data mapped as
long as needed.

https://bugzilla.gnome.org/show_bug.cgi?id=752937

gst-libs/gst/gl/gstglmemory.c
gst-libs/gst/gl/gstglmemory.h
gst-libs/gst/gl/gstglupload.c

index e1818fb..5d3f73a 100644 (file)
@@ -1508,22 +1508,26 @@ gst_gl_memory_setup_buffer (GstGLContext * context,
  * @valign: a #GstVideoInfo
  * @data: a list of per plane data pointers
  * @textures: (transfer out): a list of #GstGLMemory
+ * @user_data: user data for the destroy function
+ * @notify: A function called each time a memory is freed
  *
  * Wraps per plane data pointer in @data into the corresponding entry in
- * @textures based on @info and padding from @valign.
+ * @textures based on @info and padding from @valign. Note that the @notify
+ * will be called as many time as there is planes.
  *
  * Returns: whether the memory's were sucessfully created.
  */
 gboolean
 gst_gl_memory_setup_wrapped (GstGLContext * context, GstVideoInfo * info,
     GstVideoAlignment * valign, gpointer data[GST_VIDEO_MAX_PLANES],
-    GstGLMemory * textures[GST_VIDEO_MAX_PLANES])
+    GstGLMemory * textures[GST_VIDEO_MAX_PLANES], gpointer user_data,
+    GDestroyNotify notify)
 {
   gint i;
 
   for (i = 0; i < GST_VIDEO_INFO_N_PLANES (info); i++) {
     textures[i] = (GstGLMemory *) gst_gl_memory_wrapped (context, info, i,
-        valign, data[i], NULL, NULL);
+        valign, data[i], user_data, notify);
   }
 
   return TRUE;
index d124c7c..7bc4607 100644 (file)
@@ -142,7 +142,9 @@ gboolean      gst_gl_memory_setup_wrapped (GstGLContext * context,
                                            GstVideoInfo * info,
                                            GstVideoAlignment *valign,
                                            gpointer data[GST_VIDEO_MAX_PLANES],
-                                           GstGLMemory *textures[GST_VIDEO_MAX_PLANES]);
+                                           GstGLMemory *textures[GST_VIDEO_MAX_PLANES],
+                                           gpointer user_data,
+                                           GDestroyNotify notify);
 
 gint          gst_gl_memory_get_texture_width  (GstGLMemory * gl_mem);
 gint          gst_gl_memory_get_texture_height (GstGLMemory * gl_mem);
index 2055c9a..3e2d28e 100644 (file)
@@ -696,12 +696,55 @@ static const UploadMethod _upload_meta_upload = {
   &_upload_meta_upload_free
 };
 
+struct RawUploadFrame
+{
+  gint ref_count;
+  GstVideoFrame frame;
+};
+
 struct RawUpload
 {
   GstGLUpload *upload;
-  GstVideoFrame in_frame;
+  struct RawUploadFrame *in_frame;
 };
 
+static struct RawUploadFrame *
+_raw_upload_frame_new (struct RawUpload *raw, GstBuffer * buffer)
+{
+  struct RawUploadFrame *frame;
+
+  if (!buffer)
+    return NULL;
+
+  frame = g_slice_new (struct RawUploadFrame);
+  frame->ref_count = 1;
+
+  if (!gst_video_frame_map (&frame->frame, &raw->upload->priv->in_info,
+          buffer, GST_MAP_READ)) {
+    g_slice_free (struct RawUploadFrame, frame);
+    return NULL;
+  }
+
+  raw->upload->priv->in_info = frame->frame.info;
+
+  return frame;
+}
+
+static void
+_raw_upload_frame_ref (struct RawUploadFrame *frame)
+{
+  g_atomic_int_inc (&frame->ref_count);
+}
+
+static void
+_raw_upload_frame_unref (struct RawUploadFrame *frame)
+{
+  if (g_atomic_int_dec_and_test (&frame->ref_count)) {
+    gst_video_frame_unmap (&frame->frame);
+    g_slice_free (struct RawUploadFrame, frame);
+  }
+}
+
 static gpointer
 _raw_data_upload_new (GstGLUpload * upload)
 {
@@ -738,15 +781,9 @@ _raw_data_upload_accept (gpointer impl, GstBuffer * buffer, GstCaps * in_caps,
   if (!gst_caps_features_contains (features, GST_CAPS_FEATURE_MEMORY_GL_MEMORY))
     return FALSE;
 
-  if (buffer) {
-    if (!gst_video_frame_map (&raw->in_frame, &raw->upload->priv->in_info,
-            buffer, GST_MAP_READ))
-      return FALSE;
-
-    raw->upload->priv->in_info = raw->in_frame.info;
-  }
+  raw->in_frame = _raw_upload_frame_new (raw, buffer);
 
-  return TRUE;
+  return (raw->in_frame != NULL);
 }
 
 static void
@@ -772,10 +809,12 @@ _raw_data_upload_perform (gpointer impl, GstBuffer * buffer,
     max_planes *= GST_VIDEO_INFO_VIEWS (in_info);
 
   gst_gl_memory_setup_wrapped (raw->upload->context,
-      &raw->upload->priv->in_info, NULL, raw->in_frame.data, in_tex);
+      &raw->upload->priv->in_info, NULL, raw->in_frame->frame.data, in_tex,
+      raw->in_frame, (GDestroyNotify) _raw_upload_frame_unref);
 
   *outbuf = gst_buffer_new ();
   for (i = 0; i < max_planes; i++) {
+    _raw_upload_frame_ref (raw->in_frame);
     gst_buffer_append_memory (*outbuf, (GstMemory *) in_tex[i]);
   }
 
@@ -786,8 +825,8 @@ static void
 _raw_data_upload_release (gpointer impl, GstBuffer * buffer)
 {
   struct RawUpload *raw = impl;
-
-  gst_video_frame_unmap (&raw->in_frame);
+  _raw_upload_frame_unref (raw->in_frame);
+  raw->in_frame = NULL;
 }
 
 static void