glmemory: implement GstGLBaseMemory::alloc

- Create GstGLVideoAllocationParams which is a GstGLAllocationParams subclass.
- Make it possible to allocate glmemory objects directly if no frills are
  needed.
This commit is contained in:
Matthew Waters 2015-12-16 18:20:17 +11:00
parent bd61e1274c
commit 650e5c4fe5
3 changed files with 377 additions and 6 deletions

View 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;
}

View 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_ */

View 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);