glmemory: implement GstGLBaseMemory::alloc
authorMatthew Waters <matthew@centricular.com>
Wed, 16 Dec 2015 07:20:17 +0000 (18:20 +1100)
committerMatthew Waters <matthew@centricular.com>
Thu, 17 Dec 2015 02:49:55 +0000 (13:49 +1100)
- Create GstGLVideoAllocationParams which is a GstGLAllocationParams subclass.
- Make it possible to allocate glmemory objects directly if no frills are
  needed.

gst-libs/gst/gl/gstglmemory.c
gst-libs/gst/gl/gstglmemory.h
sys/androidmedia/gstamcvideodec.c

index 51930cf..6fdfa59 100644 (file)
@@ -60,6 +60,8 @@
 #define GL_MEM_HEIGHT(gl_mem) _get_plane_height (&gl_mem->info, gl_mem->plane)
 #define GL_MEM_STRIDE(gl_mem) GST_VIDEO_INFO_PLANE_STRIDE (&gl_mem->info, gl_mem->plane)
 
+static GstAllocator *_gl_memory_allocator;
+
 GST_DEBUG_CATEGORY_STATIC (GST_CAT_GL_MEMORY);
 #define GST_CAT_DEFAULT GST_CAT_GL_MEMORY
 
@@ -75,7 +77,7 @@ GST_DEBUG_CATEGORY_STATIC (GST_CAT_GL_MEMORY);
 #define GL_TEXTURE_EXTERNAL_OES 0x8D65
 #endif
 
-G_DEFINE_ABSTRACT_TYPE (GstGLMemoryAllocator, gst_gl_memory_allocator,
+G_DEFINE_TYPE (GstGLMemoryAllocator, gst_gl_memory_allocator,
     GST_TYPE_GL_BASE_MEMORY_ALLOCATOR);
 
 typedef struct
@@ -661,6 +663,41 @@ _gl_tex_destroy (GstGLMemory * gl_mem)
     gl->DeleteTextures (1, &gl_mem->tex_id);
 }
 
+static GstGLMemory *
+_default_gl_tex_alloc (GstGLMemoryAllocator * allocator,
+    GstGLVideoAllocationParams * params)
+{
+  GstGLMemory *mem;
+
+  g_return_val_if_fail (params->parent.
+      alloc_flags & GST_GL_ALLOCATION_PARAMS_ALLOC_FLAG_VIDEO, NULL);
+
+  mem = g_new0 (GstGLMemory, 1);
+
+  if (params->parent.
+      alloc_flags & GST_GL_ALLOCATION_PARAMS_ALLOC_FLAG_WRAP_GPU_HANDLE) {
+    mem->tex_id = params->parent.gl_handle;
+    mem->texture_wrapped = TRUE;
+  }
+
+  gst_gl_memory_init (mem, GST_ALLOCATOR_CAST (allocator), NULL,
+      params->parent.context, params->target, params->parent.alloc_params,
+      params->v_info, params->plane, params->valign, params->parent.notify,
+      params->parent.user_data);
+
+  if (params->parent.
+      alloc_flags & GST_GL_ALLOCATION_PARAMS_ALLOC_FLAG_WRAP_GPU_HANDLE) {
+    GST_MINI_OBJECT_FLAG_SET (mem, GST_GL_BASE_MEMORY_TRANSFER_NEED_DOWNLOAD);
+  }
+  if (params->parent.
+      alloc_flags & GST_GL_ALLOCATION_PARAMS_ALLOC_FLAG_WRAP_SYSMEM) {
+    mem->mem.data = params->parent.wrapped_data;
+    GST_MINI_OBJECT_FLAG_SET (mem, GST_GL_BASE_MEMORY_TRANSFER_NEED_UPLOAD);
+  }
+
+  return mem;
+}
+
 static void
 gst_gl_memory_allocator_class_init (GstGLMemoryAllocatorClass * klass)
 {
@@ -674,6 +711,8 @@ gst_gl_memory_allocator_class_init (GstGLMemoryAllocatorClass * klass)
   klass->unmap = (GstGLBaseMemoryAllocatorUnmapFunction) _default_gl_tex_unmap;
   klass->copy = (GstGLBaseMemoryAllocatorCopyFunction) _default_gl_tex_copy;
 
+  gl_base->alloc =
+      (GstGLBaseMemoryAllocatorAllocFunction) _default_gl_tex_alloc;
   gl_base->create = (GstGLBaseMemoryAllocatorCreateFunction) _gl_tex_create;
   gl_base->map = (GstGLBaseMemoryAllocatorMapFunction) _gl_tex_map;
   gl_base->unmap = (GstGLBaseMemoryAllocatorUnmapFunction) _gl_tex_unmap;
@@ -794,6 +833,11 @@ gst_gl_memory_init_once (void)
 
     GST_DEBUG_CATEGORY_INIT (GST_CAT_GL_MEMORY, "glbasetexture", 0,
         "OpenGL Base Texture Memory");
+
+    _gl_memory_allocator = g_object_new (GST_TYPE_GL_MEMORY_ALLOCATOR, NULL);
+
+    gst_allocator_register (GST_GL_MEMORY_ALLOCATOR_NAME, _gl_memory_allocator);
+
     g_once_init_leave (&_init, 1);
   }
 }
@@ -811,3 +855,253 @@ gst_is_gl_memory (GstMemory * mem)
       && g_type_is_a (G_OBJECT_TYPE (mem->allocator),
       GST_TYPE_GL_MEMORY_ALLOCATOR);
 }
+
+static void
+_gst_gl_video_allocation_params_set_video_alignment (GstGLVideoAllocationParams
+    * params, GstVideoAlignment * valign)
+{
+  g_return_if_fail (params != NULL);
+
+  if (!params->valign)
+    params->valign = g_new0 (GstVideoAlignment, 1);
+
+  if (valign) {
+    *params->valign = *valign;
+  } else {
+    gst_video_alignment_reset (params->valign);
+  }
+}
+
+gboolean
+gst_gl_video_allocation_params_init_full (GstGLVideoAllocationParams * params,
+    gsize struct_size, guint alloc_flags, GstGLAllocationParamsCopyFunc copy,
+    GstGLAllocationParamsFreeFunc free, GstGLContext * context,
+    GstAllocationParams * alloc_params, GstVideoInfo * v_info,
+    guint plane, GstVideoAlignment * valign, GstGLTextureTarget target,
+    gpointer wrapped_data, guint gl_handle, GDestroyNotify notify,
+    gpointer user_data)
+{
+  guint i;
+
+  g_return_val_if_fail (params != NULL, FALSE);
+  g_return_val_if_fail (copy != NULL, FALSE);
+  g_return_val_if_fail (free != NULL, FALSE);
+  g_return_val_if_fail (GST_IS_GL_CONTEXT (context), FALSE);
+  g_return_val_if_fail (v_info != NULL, FALSE);
+
+  memset (params, 0, sizeof (*params));
+
+  if (!gst_gl_allocation_params_init ((GstGLAllocationParams *) params,
+          struct_size, alloc_flags, copy, free, context, 0, alloc_params,
+          notify, user_data, wrapped_data, gl_handle))
+    return FALSE;
+
+  params->v_info = g_new0 (GstVideoInfo, 1);
+  *params->v_info = *v_info;
+  for (i = 0; i < GST_VIDEO_MAX_PLANES; i++) {
+    params->v_info->offset[i] = v_info->offset[i];
+    params->v_info->stride[i] = v_info->stride[i];
+  }
+  _gst_gl_video_allocation_params_set_video_alignment (params, valign);
+  params->target = target;
+  params->plane = plane;
+
+  return TRUE;
+}
+
+/**
+ * gst_gl_video_allocation_params_new:
+ * @context: a #GstGLContext
+ * @alloc_params: (allow-none): the #GstAllocationParams for @wrapped_data
+ * @v_info: the #GstVideoInfo for @wrapped_data
+ * @plane: the video plane @wrapped_data represents
+ * @valign: (allow-none): any #GstVideoAlignment applied to symem mappings of @wrapped_data
+ * @target: the #GstGLTextureTarget for @wrapped_data
+ *
+ * Returns: a new #GstGLVideoAllocationParams for allocating #GstGLMemory's
+ */
+GstGLVideoAllocationParams *
+gst_gl_video_allocation_params_new (GstGLContext * context,
+    GstAllocationParams * alloc_params, GstVideoInfo * v_info, guint plane,
+    GstVideoAlignment * valign, GstGLTextureTarget target)
+{
+  GstGLVideoAllocationParams *params = g_new0 (GstGLVideoAllocationParams, 1);
+
+  if (!gst_gl_video_allocation_params_init_full (params,
+          sizeof (GstGLVideoAllocationParams),
+          GST_GL_ALLOCATION_PARAMS_ALLOC_FLAG_ALLOC |
+          GST_GL_ALLOCATION_PARAMS_ALLOC_FLAG_VIDEO,
+          (GstGLAllocationParamsCopyFunc)
+          gst_gl_video_allocation_params_copy_data,
+          (GstGLAllocationParamsFreeFunc)
+          gst_gl_video_allocation_params_free_data, context, alloc_params,
+          v_info, plane, valign, target, NULL, 0, NULL, NULL)) {
+    g_free (params);
+    return NULL;
+  }
+
+  return params;
+}
+
+/**
+ * gst_gl_video_allocation_params_new_wrapped_data:
+ * @context: a #GstGLContext
+ * @alloc_params: (allow-none): the #GstAllocationParams for @wrapped_data
+ * @v_info: the #GstVideoInfo for @wrapped_data
+ * @plane: the video plane @wrapped_data represents
+ * @valign: (allow-none): any #GstVideoAlignment applied to symem mappings of @wrapped_data
+ * @target: the #GstGLTextureTarget for @wrapped_data
+ * @wrapped_data: the data pointer to wrap
+ * @notify: (allow-none): a #GDestroyNotify
+ * @user_data: (allow-none): user data to call @notify with
+ *
+ * Returns: a new #GstGLVideoAllocationParams for wrapping @wrapped_data
+ */
+GstGLVideoAllocationParams *
+gst_gl_video_allocation_params_new_wrapped_data (GstGLContext * context,
+    GstAllocationParams * alloc_params, GstVideoInfo * v_info, guint plane,
+    GstVideoAlignment * valign, GstGLTextureTarget target,
+    gpointer wrapped_data, GDestroyNotify notify, gpointer user_data)
+{
+  GstGLVideoAllocationParams *params = g_new0 (GstGLVideoAllocationParams, 1);
+
+  if (!gst_gl_video_allocation_params_init_full (params,
+          sizeof (GstGLVideoAllocationParams),
+          GST_GL_ALLOCATION_PARAMS_ALLOC_FLAG_WRAP_SYSMEM |
+          GST_GL_ALLOCATION_PARAMS_ALLOC_FLAG_VIDEO,
+          (GstGLAllocationParamsCopyFunc)
+          gst_gl_video_allocation_params_copy_data,
+          (GstGLAllocationParamsFreeFunc)
+          gst_gl_video_allocation_params_free_data, context, alloc_params,
+          v_info, plane, valign, target, wrapped_data, 0, notify, user_data)) {
+    g_free (params);
+    return NULL;
+  }
+
+  return params;
+}
+
+/**
+ * gst_gl_video_allocation_params_new_wrapped_texture:
+ * @context: a #GstGLContext
+ * @alloc_params: (allow-none): the #GstAllocationParams for @tex_id
+ * @v_info: the #GstVideoInfo for @tex_id
+ * @plane: the video plane @tex_id represents
+ * @valign: (allow-none): any #GstVideoAlignment applied to symem mappings of @tex_id
+ * @target: the #GstGLTextureTarget for @tex_id
+ * @tex_id: the GL texture to wrap
+ * @notify: (allow-none): a #GDestroyNotify
+ * @user_data: (allow-none): user data to call @notify with
+ *
+ * Returns: a new #GstGLVideoAllocationParams for wrapping @tex_id
+ */
+GstGLVideoAllocationParams *
+gst_gl_video_allocation_params_new_wrapped_texture (GstGLContext * context,
+    GstAllocationParams * alloc_params, GstVideoInfo * v_info, guint plane,
+    GstVideoAlignment * valign, GstGLTextureTarget target,
+    guint tex_id, GDestroyNotify notify, gpointer user_data)
+{
+  GstGLVideoAllocationParams *params = g_new0 (GstGLVideoAllocationParams, 1);
+
+  if (!gst_gl_video_allocation_params_init_full (params,
+          sizeof (GstGLVideoAllocationParams),
+          GST_GL_ALLOCATION_PARAMS_ALLOC_FLAG_WRAP_GPU_HANDLE |
+          GST_GL_ALLOCATION_PARAMS_ALLOC_FLAG_VIDEO,
+          (GstGLAllocationParamsCopyFunc)
+          gst_gl_video_allocation_params_copy_data,
+          (GstGLAllocationParamsFreeFunc)
+          gst_gl_video_allocation_params_free_data, context, alloc_params,
+          v_info, plane, valign, target, NULL, tex_id, notify, user_data)) {
+    g_free (params);
+    return NULL;
+  }
+
+  return params;
+}
+
+void
+gst_gl_video_allocation_params_free_data (GstGLVideoAllocationParams * params)
+{
+  g_free (params->v_info);
+  g_free (params->valign);
+
+  gst_gl_allocation_params_free_data (&params->parent);
+}
+
+void
+gst_gl_video_allocation_params_copy_data (GstGLVideoAllocationParams * src_vid,
+    GstGLVideoAllocationParams * dest_vid)
+{
+  GstGLAllocationParams *src = (GstGLAllocationParams *) src_vid;
+  GstGLAllocationParams *dest = (GstGLAllocationParams *) dest_vid;
+  guint i;
+
+  gst_gl_allocation_params_copy_data (src, dest);
+
+  dest_vid->v_info = g_new0 (GstVideoInfo, 1);
+  *dest_vid->v_info = *src_vid->v_info;
+  for (i = 0; i < GST_VIDEO_MAX_PLANES; i++) {
+    dest_vid->v_info->offset[i] = src_vid->v_info->offset[i];
+    dest_vid->v_info->stride[i] = src_vid->v_info->stride[i];
+  }
+  _gst_gl_video_allocation_params_set_video_alignment (dest_vid,
+      src_vid->valign);
+  dest_vid->target = src_vid->target;
+  dest_vid->plane = src_vid->plane;
+}
+
+/**
+ * gst_gl_memory_setup_buffer:
+ * @allocator: the @GstGLMemoryAllocator to allocate from
+ * @buffer: a #GstBuffer to setup
+ * @params: the #GstGLVideoAllocationParams to allocate with
+ *
+ * Returns: whether the buffer was correctly setup
+ */
+gboolean
+gst_gl_memory_setup_buffer (GstGLMemoryAllocator * allocator,
+    GstBuffer * buffer, GstGLVideoAllocationParams * params)
+{
+  GstGLBaseMemoryAllocator *base_allocator;
+  guint n_mem, i, v, views;
+
+  g_return_val_if_fail (params != NULL, FALSE);
+  g_return_val_if_fail ((params->parent.
+          alloc_flags & GST_GL_ALLOCATION_PARAMS_ALLOC_FLAG_WRAP_SYSMEM)
+      == 0, FALSE);
+  g_return_val_if_fail ((params->parent.alloc_flags &
+          GST_GL_ALLOCATION_PARAMS_ALLOC_FLAG_WRAP_GPU_HANDLE) == 0, FALSE);
+  g_return_val_if_fail (params->parent.
+      alloc_flags & GST_GL_ALLOCATION_PARAMS_ALLOC_FLAG_VIDEO, FALSE);
+
+  base_allocator = GST_GL_BASE_MEMORY_ALLOCATOR (allocator);
+  n_mem = GST_VIDEO_INFO_N_PLANES (params->v_info);
+
+  if (GST_VIDEO_INFO_MULTIVIEW_MODE (params->v_info) ==
+      GST_VIDEO_MULTIVIEW_MODE_SEPARATED)
+    views = params->v_info->views;
+  else
+    views = 1;
+
+  for (v = 0; v < views; v++) {
+    for (i = 0; i < n_mem; i++) {
+      GstGLMemory *gl_mem;
+
+      params->plane = i;
+
+      if (!(gl_mem = (GstGLMemory *) gst_gl_base_memory_alloc (base_allocator,
+                  (GstGLAllocationParams *) params)))
+        return FALSE;
+
+      gst_buffer_append_memory (buffer, (GstMemory *) gl_mem);
+    }
+
+    gst_buffer_add_video_meta_full (buffer, v,
+        GST_VIDEO_INFO_FORMAT (params->v_info),
+        GST_VIDEO_INFO_WIDTH (params->v_info),
+        GST_VIDEO_INFO_HEIGHT (params->v_info), n_mem, params->v_info->offset,
+        params->v_info->stride);
+  }
+
+  return TRUE;
+}
index de02697..3f3c41c 100644 (file)
@@ -80,6 +80,67 @@ struct _GstGLMemory
   guint                     tex_width;
 };
 
+typedef struct _GstGLVideoAllocationParams GstGLVideoAllocationParams;
+
+#define GST_GL_ALLOCATION_PARAMS_ALLOC_FLAG_VIDEO (1 << 3)
+
+struct _GstGLVideoAllocationParams
+{
+  GstGLAllocationParams  parent;
+
+  GstVideoInfo          *v_info;
+  guint                  plane;
+  GstVideoAlignment     *valign;
+  GstGLTextureTarget     target;
+};
+
+gboolean        gst_gl_video_allocation_params_init_full        (GstGLVideoAllocationParams * params,
+                                                                 gsize struct_size,
+                                                                 guint alloc_flags,
+                                                                 GstGLAllocationParamsCopyFunc copy,
+                                                                 GstGLAllocationParamsFreeFunc free,
+                                                                 GstGLContext * context,
+                                                                 GstAllocationParams * alloc_params,
+                                                                 GstVideoInfo * v_info,
+                                                                 guint plane,
+                                                                 GstVideoAlignment * valign,
+                                                                 GstGLTextureTarget target,
+                                                                 gpointer wrapped_data,
+                                                                 guint gl_handle,
+                                                                 GDestroyNotify notify,
+                                                                 gpointer user_data);
+GstGLVideoAllocationParams * gst_gl_video_allocation_params_new (GstGLContext * context,
+                                                                 GstAllocationParams * alloc_params,
+                                                                 GstVideoInfo * v_info,
+                                                                 guint plane,
+                                                                 GstVideoAlignment * valign,
+                                                                 GstGLTextureTarget target);
+GstGLVideoAllocationParams * gst_gl_video_allocation_params_new_wrapped_data    (GstGLContext * context,
+                                                                                 GstAllocationParams * alloc_params,
+                                                                                 GstVideoInfo * v_info,
+                                                                                 guint plane,
+                                                                                 GstVideoAlignment * valign,
+                                                                                 GstGLTextureTarget target,
+                                                                                 gpointer wrapped_data,
+                                                                                 GDestroyNotify notify,
+                                                                                 gpointer user_data);
+
+GstGLVideoAllocationParams * gst_gl_video_allocation_params_new_wrapped_texture (GstGLContext * context,
+                                                                                 GstAllocationParams * alloc_params,
+                                                                                 GstVideoInfo * v_info,
+                                                                                 guint plane,
+                                                                                 GstVideoAlignment * valign,
+                                                                                 GstGLTextureTarget target,
+                                                                                 guint tex_id,
+                                                                                 GDestroyNotify notify,
+                                                                                 gpointer user_data);
+
+/* subclass usage */
+void            gst_gl_video_allocation_params_free_data    (GstGLVideoAllocationParams * params);
+/* subclass usage */
+void            gst_gl_video_allocation_params_copy_data    (GstGLVideoAllocationParams * src,
+                                                             GstGLVideoAllocationParams * dest);
+
 /**
  * GstGLMemoryAllocator
  *
@@ -97,7 +158,7 @@ struct _GstGLMemoryAllocator
  */
 struct _GstGLMemoryAllocatorClass
 {
-  GstGLBaseMemoryAllocatorClass parent_class;
+  GstGLBaseMemoryAllocatorClass             parent_class;
 
   GstGLBaseMemoryAllocatorMapFunction       map;
   GstGLBaseMemoryAllocatorCopyFunction      copy;
@@ -151,6 +212,10 @@ GstVideoGLTextureType   gst_gl_memory_get_texture_type      (GstGLMemory * gl_me
 GstGLTextureTarget      gst_gl_memory_get_texture_target    (GstGLMemory * gl_mem);
 guint                   gst_gl_memory_get_texture_id        (GstGLMemory * gl_mem);
 
+gboolean                gst_gl_memory_setup_buffer          (GstGLMemoryAllocator * allocator,
+                                                             GstBuffer * buffer,
+                                                             GstGLVideoAllocationParams * params);
+
 G_END_DECLS
 
 #endif /* _GST_GL_MEMORY_H_ */
index ed24d22..1581d06 100644 (file)
@@ -989,8 +989,8 @@ _gl_sync_render_unlocked (struct gl_sync *sync)
   if (!af_meta) {
     GST_WARNING ("Failed to retreive the transformation meta from the "
         "gl_sync %p buffer %p", sync, sync->buffer);
-  } else if (gst_amc_surface_texture_get_transform_matrix (sync->
-          surface->texture, matrix, &error)) {
+  } else if (gst_amc_surface_texture_get_transform_matrix (sync->surface->
+          texture, matrix, &error)) {
 
     gst_video_affine_transformation_meta_apply_matrix (af_meta, matrix);
     gst_video_affine_transformation_meta_apply_matrix (af_meta, yflip_matrix);
@@ -1302,8 +1302,20 @@ retry:
     state = gst_video_decoder_get_output_state (GST_VIDEO_DECODER (self));
 
     if (!self->oes_mem) {
-      self->oes_mem = (GstGLMemory *) gst_gl_memory_pbo_alloc (self->gl_context,
-          GST_GL_TEXTURE_TARGET_EXTERNAL_OES, NULL, &state->info, 0, NULL);
+      GstGLBaseMemoryAllocator *base_mem_alloc;
+      GstGLVideoAllocationParams *params;
+
+      base_mem_alloc =
+          GST_GL_BASE_MEMORY_ALLOCATOR (gst_allocator_find
+          (GST_GL_MEMORY_ALLOCATOR_NAME));
+
+      params = gst_gl_video_allocation_params_new (self->gl_context, NULL,
+          &state->info, 0, NULL, GST_GL_TEXTURE_TARGET_EXTERNAL_OES);
+
+      self->oes_mem = (GstGLMemory *) gst_gl_base_memory_alloc (base_mem_alloc,
+          (GstGLAllocationParams *) params);
+      gst_gl_allocation_params_free ((GstGLAllocationParams *) params);
+      gst_object_unref (base_mem_alloc);
 
       gst_gl_context_thread_add (self->gl_context,
           (GstGLContextThreadFunc) _attach_mem_to_context, self);