diff --git a/ext/gl/gstgloverlay.c b/ext/gl/gstgloverlay.c index fb3f9fc312..4ba1b798e6 100644 --- a/ext/gl/gstgloverlay.c +++ b/ext/gl/gstgloverlay.c @@ -638,7 +638,7 @@ gst_gl_overlay_load_jpeg (GstGLFilter * filter) overlay->image_width, overlay->image_height); overlay->image_memory = - (GstGLMemory *) gst_gl_memory_alloc (filter->context, &v_info, 0); + (GstGLMemory *) gst_gl_memory_alloc (filter->context, &v_info, 0, NULL); if (!gst_memory_map ((GstMemory *) overlay->image_memory, &map_info, GST_MAP_WRITE)) { @@ -740,7 +740,7 @@ gst_gl_overlay_load_png (GstGLFilter * filter) gst_video_info_set_format (&v_info, GST_VIDEO_FORMAT_RGBA, width, height); overlay->image_memory = - (GstGLMemory *) gst_gl_memory_alloc (filter->context, &v_info, 0); + (GstGLMemory *) gst_gl_memory_alloc (filter->context, &v_info, 0, NULL); if (!gst_memory_map ((GstMemory *) overlay->image_memory, &map_info, GST_MAP_WRITE)) { diff --git a/gst-libs/gst/gl/gstglbufferpool.c b/gst-libs/gst/gl/gstglbufferpool.c index 3d74fff535..730fecaea6 100644 --- a/gst-libs/gst/gl/gstglbufferpool.c +++ b/gst-libs/gst/gl/gstglbufferpool.c @@ -24,6 +24,7 @@ #include "gl.h" #include "gstglbufferpool.h" +#include "gstglutils.h" #if GST_GL_HAVE_PLATFORM_EGL #include @@ -50,6 +51,7 @@ struct _GstGLBufferPoolPrivate GstCaps *caps; gint im_format; GstVideoInfo info; + GstVideoAlignment valign; gboolean add_videometa; gboolean add_uploadmeta; gboolean add_glsyncmeta; @@ -75,7 +77,9 @@ gst_gl_buffer_pool_get_options (GstBufferPool * pool) { static const gchar *options[] = { GST_BUFFER_POOL_OPTION_VIDEO_META, GST_BUFFER_POOL_OPTION_VIDEO_GL_TEXTURE_UPLOAD_META, - GST_BUFFER_POOL_OPTION_GL_SYNC_META, NULL + GST_BUFFER_POOL_OPTION_GL_SYNC_META, + GST_BUFFER_POOL_OPTION_VIDEO_ALIGNMENT, + NULL }; return options; @@ -88,11 +92,13 @@ gst_gl_buffer_pool_set_config (GstBufferPool * pool, GstStructure * config) GstGLBufferPoolPrivate *priv = glpool->priv; GstVideoInfo info; GstCaps *caps = NULL; + guint min_buffers, max_buffers; GstAllocator *allocator = NULL; GstAllocationParams alloc_params; gboolean reset = TRUE; - if (!gst_buffer_pool_config_get_params (config, &caps, NULL, NULL, NULL)) + if (!gst_buffer_pool_config_get_params (config, &caps, NULL, &min_buffers, + &max_buffers)) goto wrong_config; if (caps == NULL) @@ -145,6 +151,29 @@ gst_gl_buffer_pool_set_config (GstBufferPool * pool, GstStructure * config) priv->want_eglimage = FALSE; #endif + if (gst_buffer_pool_config_has_option (config, + GST_BUFFER_POOL_OPTION_VIDEO_ALIGNMENT)) { + gint p; + + priv->add_videometa = TRUE; + + gst_buffer_pool_config_get_video_alignment (config, &priv->valign); + gst_video_info_align (&priv->info, &priv->valign); + + /* Recalulate the size as we don't add padding between planes. */ + priv->info.size = 0; + for (p = 0; p < GST_VIDEO_INFO_N_PLANES (&priv->info); p++) { + priv->info.size += + gst_gl_get_plane_data_size (&priv->info, &priv->valign, p); + } + + gst_buffer_pool_config_set_video_alignment (config, &priv->valign); + gst_buffer_pool_config_set_params (config, caps, priv->info.size, + min_buffers, max_buffers); + } else { + gst_video_alignment_reset (&priv->valign); + } + if (reset) { if (glpool->upload) gst_object_unref (glpool->upload); @@ -152,6 +181,7 @@ gst_gl_buffer_pool_set_config (GstBufferPool * pool, GstStructure * config) glpool->upload = gst_gl_upload_meta_new (glpool->context); } + return GST_BUFFER_POOL_CLASS (parent_class)->set_config (pool, config); /* ERRORS */ @@ -202,9 +232,11 @@ gst_gl_buffer_pool_alloc (GstBufferPool * pool, GstBuffer ** buffer, GstGLBufferPool *glpool = GST_GL_BUFFER_POOL_CAST (pool); GstGLBufferPoolPrivate *priv = glpool->priv; GstVideoInfo *info; + GstVideoAlignment *valign; GstBuffer *buf; info = &priv->info; + valign = &priv->valign; if (!(buf = gst_buffer_new ())) { goto no_buffer; @@ -222,7 +254,7 @@ gst_gl_buffer_pool_alloc (GstBufferPool * pool, GstBuffer ** buffer, } #endif - if (!gst_gl_memory_setup_buffer (glpool->context, info, buf)) + if (!gst_gl_memory_setup_buffer (glpool->context, info, valign, buf)) goto mem_create_failed; if (priv->add_uploadmeta) diff --git a/gst-libs/gst/gl/gstglcolorconvert.c b/gst-libs/gst/gl/gstglcolorconvert.c index 4cd6ff8aad..3c8667f402 100644 --- a/gst-libs/gst/gl/gstglcolorconvert.c +++ b/gst-libs/gst/gl/gstglcolorconvert.c @@ -1334,7 +1334,7 @@ _do_convert (GstGLContext * context, GstGLColorConvert * convert) convert->outbuf = gst_buffer_new (); if (!gst_gl_memory_setup_buffer (convert->context, &convert->out_info, - convert->outbuf)) { + NULL, convert->outbuf)) { convert->priv->result = FALSE; return; } @@ -1383,7 +1383,7 @@ _do_convert (GstGLContext * context, GstGLColorConvert * convert) if (!convert->priv->out_tex[j]) convert->priv->out_tex[j] = - (GstGLMemory *) gst_gl_memory_alloc (context, &temp_info, 0); + (GstGLMemory *) gst_gl_memory_alloc (context, &temp_info, 0, NULL); } else { convert->priv->out_tex[j] = out_tex; } diff --git a/gst-libs/gst/gl/gstgldownload.c b/gst-libs/gst/gl/gstgldownload.c index b0441ee69f..4e0f412b25 100644 --- a/gst-libs/gst/gl/gstgldownload.c +++ b/gst-libs/gst/gl/gstgldownload.c @@ -232,7 +232,7 @@ _gst_gl_download_perform_with_data_unlocked (GstGLDownload * download, download->priv->in_tex[0] = gst_gl_memory_wrapped_texture (download->context, texture_id, - &temp_info, 0, NULL, NULL); + &temp_info, 0, NULL, NULL, NULL); } download->priv->in_tex[0]->tex_id = texture_id; diff --git a/gst-libs/gst/gl/gstglmemory.c b/gst-libs/gst/gl/gstglmemory.c index 84bb292499..b6ef7afa7d 100644 --- a/gst-libs/gst/gl/gstglmemory.c +++ b/gst-libs/gst/gl/gstglmemory.c @@ -27,6 +27,7 @@ #include #include "gstglmemory.h" +#include "gstglutils.h" /** * SECTION:gstglmemory @@ -348,15 +349,6 @@ _get_plane_height (GstVideoInfo * info, guint plane) return GST_VIDEO_INFO_HEIGHT (info); } -static inline gsize -_get_plane_data_size (GstVideoInfo * info, guint plane) -{ - if (GST_VIDEO_INFO_N_PLANES (info) == plane + 1) - return info->offset[0] + info->size - info->offset[plane]; - - return info->offset[plane + 1] - info->offset[plane]; -} - typedef struct _GenTexture { guint width, height; @@ -575,14 +567,14 @@ error: static void _gl_mem_init (GstGLMemory * mem, GstAllocator * allocator, GstMemory * parent, - GstGLContext * context, GstVideoInfo * info, guint plane, - gpointer user_data, GDestroyNotify notify) + GstGLContext * context, GstVideoInfo * info, GstVideoAlignment * valign, + guint plane, gpointer user_data, GDestroyNotify notify) { gsize maxsize; g_return_if_fail (plane < GST_VIDEO_INFO_N_PLANES (info)); - maxsize = _get_plane_data_size (info, plane); + maxsize = gst_gl_get_plane_data_size (info, valign, plane); gst_memory_init (GST_MEMORY_CAST (mem), GST_MEMORY_FLAG_NO_SHARE, allocator, parent, maxsize, 0, 0, maxsize); @@ -598,6 +590,11 @@ _gl_mem_init (GstGLMemory * mem, GstAllocator * allocator, GstMemory * parent, mem->data_wrapped = FALSE; mem->texture_wrapped = FALSE; + if (valign) + mem->valign = *valign; + else + gst_video_alignment_reset (&mem->valign); + _calculate_unpack_length (mem); GST_CAT_DEBUG (GST_CAT_GL_MEMORY, "new GL texture memory:%p format:%u " @@ -607,14 +604,14 @@ _gl_mem_init (GstGLMemory * mem, GstAllocator * allocator, GstMemory * parent, static GstGLMemory * _gl_mem_new (GstAllocator * allocator, GstMemory * parent, - GstGLContext * context, GstVideoInfo * info, guint plane, - gpointer user_data, GDestroyNotify notify) + GstGLContext * context, GstVideoInfo * info, GstVideoAlignment * valign, + guint plane, gpointer user_data, GDestroyNotify notify) { GstGLMemory *mem; GenTexture data = { 0, }; mem = g_slice_new0 (GstGLMemory); - _gl_mem_init (mem, allocator, parent, context, info, plane, user_data, - notify); + _gl_mem_init (mem, allocator, parent, context, info, valign, plane, + user_data, notify); data.width = mem->tex_width; data.height = GL_MEM_HEIGHT (mem); @@ -849,7 +846,7 @@ _gl_mem_copy (GstGLMemory * src, gssize offset, gssize size) if (GST_GL_MEMORY_FLAG_IS_SET (src, GST_GL_MEMORY_FLAG_NEED_UPLOAD)) { dest = _gl_mem_new (src->mem.allocator, NULL, src->context, &src->info, - src->plane, NULL, NULL); + &src->valign, src->plane, NULL, NULL); dest->data = g_try_malloc (src->mem.maxsize); if (dest->data == NULL) { GST_CAT_WARNING (GST_CAT_GL_MEMORY, "Could not copy GL Memory"); @@ -873,7 +870,7 @@ _gl_mem_copy (GstGLMemory * src, gssize offset, gssize size) dest = g_slice_new0 (GstGLMemory); _gl_mem_init (dest, src->mem.allocator, NULL, src->context, &src->info, - src->plane, NULL, NULL); + &src->valign, src->plane, NULL, NULL); if (!copy_params.result) { GST_CAT_WARNING (GST_CAT_GL_MEMORY, "Could not copy GL Memory"); @@ -997,14 +994,29 @@ gst_gl_memory_copy_into_texture (GstGLMemory * gl_mem, guint tex_id, return copy_params.result; } +/** + * gst_gl_memory_wrapped_texture: + * @context: a #GstGLContext + * @texture_id: the GL texture handle + * @info: the #GstVideoInfo of the memory + * @plane: The plane this memory will represent + * @user_data: user data + * @notify: Destroy callback for the user data + * + * Wraps a texture handle into a #GstGLMemory. + * + * Returns: a newly allocated #GstGLMemory + */ GstGLMemory * gst_gl_memory_wrapped_texture (GstGLContext * context, guint texture_id, - GstVideoInfo * info, guint plane, gpointer user_data, GDestroyNotify notify) + GstVideoInfo * info, guint plane, GstVideoAlignment * valign, + gpointer user_data, GDestroyNotify notify) { GstGLMemory *mem; mem = g_slice_new0 (GstGLMemory); - _gl_mem_init (mem, _gl_allocator, NULL, context, info, plane, NULL, NULL); + _gl_mem_init (mem, _gl_allocator, NULL, context, info, valign, plane, NULL, + NULL); mem->tex_id = texture_id; mem->texture_wrapped = TRUE; @@ -1022,17 +1034,23 @@ gst_gl_memory_wrapped_texture (GstGLContext * context, guint texture_id, /** * gst_gl_memory_alloc: * @context:a #GstGLContext - * @v_info: the #GstVideoInfo of the memory + * @info: the #GstVideoInfo of the memory + * @plane: the plane this memory will represent + * @valign: the #GstVideoAlignment applied to @info * - * Returns: a #GstMemory object with a GL texture specified by @v_info + * Allocated a new #GstGlMemory. + * + * Returns: a #GstMemory object with a GL texture specified by @vinfo * from @context */ GstMemory * -gst_gl_memory_alloc (GstGLContext * context, GstVideoInfo * info, guint plane) +gst_gl_memory_alloc (GstGLContext * context, GstVideoInfo * info, + guint plane, GstVideoAlignment * valign) { GstGLMemory *mem; - mem = _gl_mem_new (_gl_allocator, NULL, context, info, plane, NULL, NULL); + mem = _gl_mem_new (_gl_allocator, NULL, context, info, valign, plane, NULL, + NULL); mem->data = g_try_malloc (mem->mem.maxsize); if (mem->data == NULL) { @@ -1044,25 +1062,30 @@ gst_gl_memory_alloc (GstGLContext * context, GstVideoInfo * info, guint plane) } /** - * gst_gl_memory_wrapped + * gst_gl_memory_wrapped: * @context:a #GstGLContext - * @v_info: the #GstVideoInfo of the memory and data + * @info: the #GstVideoInfo of the memory and data + * @plane: the plane this memory will represent + * @valign: the #GstVideoAlignment applied to @info * @data: the data to wrap * @user_data: data called with for @notify * @notify: function called with @user_data when @data needs to be freed * + * Wrapped @data into a #GstGLMemory. This version will account for padding + * added to the allocation and expressed through @valign. + * * Returns: a #GstGLMemory object with a GL texture specified by @v_info * from @context and contents specified by @data */ GstGLMemory * -gst_gl_memory_wrapped (GstGLContext * context, GstVideoInfo * info, guint plane, - gpointer data, gpointer user_data, GDestroyNotify notify) +gst_gl_memory_wrapped (GstGLContext * context, GstVideoInfo * info, + guint plane, GstVideoAlignment * valign, gpointer data, gpointer user_data, + GDestroyNotify notify) { GstGLMemory *mem; - mem = - _gl_mem_new (_gl_allocator, NULL, context, info, plane, user_data, - notify); + mem = _gl_mem_new (_gl_allocator, NULL, context, info, valign, plane, + user_data, notify); mem->data = data; mem->data_wrapped = TRUE; @@ -1152,16 +1175,17 @@ gst_is_gl_memory (GstMemory * mem) * gst_gl_memory_setup_buffer: * @context: a #GstGLContext * @info: a #GstVideoInfo + * @valign: the #GstVideoAlignment applied to @info * @buffer: a #GstBuffer * * Adds the required #GstGLMemorys with the correct configuration to - * @buffer based on @info. + * @buffer based on @info. This version handles padding through @valign. * * Returns: whether the memory's were sucessfully added. */ gboolean gst_gl_memory_setup_buffer (GstGLContext * context, GstVideoInfo * info, - GstBuffer * buffer) + GstVideoAlignment * valign, GstBuffer * buffer) { GstGLMemory *gl_mem[GST_VIDEO_MAX_PLANES] = { NULL, }; guint n_mem, i; @@ -1169,7 +1193,7 @@ gst_gl_memory_setup_buffer (GstGLContext * context, GstVideoInfo * info, n_mem = GST_VIDEO_INFO_N_PLANES (info); for (i = 0; i < n_mem; i++) { - gl_mem[i] = (GstGLMemory *) gst_gl_memory_alloc (context, info, i); + gl_mem[i] = (GstGLMemory *) gst_gl_memory_alloc (context, info, i, valign); if (gl_mem[i] == NULL) return FALSE; @@ -1187,24 +1211,25 @@ gst_gl_memory_setup_buffer (GstGLContext * context, GstVideoInfo * info, * gst_gl_memory_setup_wrapped: * @context: a #GstGLContext * @info: a #GstVideoInfo + * @valign: a #GstVideoInfo * @data: a list of per plane data pointers * @textures: (transfer out): a list of #GstGLMemory * * Wraps per plane data pointer in @data into the corresponding entry in - * @textures based on @info. + * @textures based on @info and padding from @valign. * * Returns: whether the memory's were sucessfully created. */ gboolean gst_gl_memory_setup_wrapped (GstGLContext * context, GstVideoInfo * info, - gpointer data[GST_VIDEO_MAX_PLANES], + GstVideoAlignment * valign, gpointer data[GST_VIDEO_MAX_PLANES], GstGLMemory * textures[GST_VIDEO_MAX_PLANES]) { gint i; for (i = 0; i < GST_VIDEO_INFO_N_PLANES (info); i++) { textures[i] = (GstGLMemory *) gst_gl_memory_wrapped (context, info, i, - data[i], NULL, NULL); + valign, data[i], NULL, NULL); } return TRUE; diff --git a/gst-libs/gst/gl/gstglmemory.h b/gst-libs/gst/gl/gstglmemory.h index 3e2e3c51d2..e64ae5668e 100644 --- a/gst-libs/gst/gl/gstglmemory.h +++ b/gst-libs/gst/gl/gstglmemory.h @@ -86,6 +86,7 @@ struct _GstGLMemory guint tex_id; GstVideoGLTextureType tex_type; GstVideoInfo info; + GstVideoAlignment valign; guint plane; gfloat tex_scaling[2]; @@ -150,11 +151,13 @@ struct _GstGLMemory void gst_gl_memory_init (void); gboolean gst_is_gl_memory (GstMemory * mem); -GstMemory * gst_gl_memory_alloc (GstGLContext * context, GstVideoInfo * info, guint plane); +GstMemory * gst_gl_memory_alloc (GstGLContext * context, GstVideoInfo * info, guint plane, + GstVideoAlignment *valign); GstGLMemory * gst_gl_memory_wrapped (GstGLContext * context, GstVideoInfo * info, guint plane, - gpointer data, gpointer user_data, GDestroyNotify notify); + GstVideoAlignment *valign, gpointer data, + gpointer user_data, GDestroyNotify notify); GstGLMemory * gst_gl_memory_wrapped_texture (GstGLContext * context, guint texture_id, - GstVideoInfo * info, guint plane, + GstVideoInfo * info, guint plane, GstVideoAlignment *valign, gpointer user_data, GDestroyNotify notify); gboolean gst_gl_memory_copy_into_texture (GstGLMemory *gl_mem, guint tex_id, @@ -162,9 +165,9 @@ gboolean gst_gl_memory_copy_into_texture (GstGLMemory *gl_mem, guint tex_id gint width, gint height, gint stride, gboolean respecify); -gboolean gst_gl_memory_setup_buffer (GstGLContext * context, GstVideoInfo * info, +gboolean gst_gl_memory_setup_buffer (GstGLContext * context, GstVideoInfo * info, GstVideoAlignment *valign, GstBuffer * buffer); -gboolean gst_gl_memory_setup_wrapped (GstGLContext * context, GstVideoInfo * info, +gboolean gst_gl_memory_setup_wrapped (GstGLContext * context, GstVideoInfo * info, GstVideoAlignment *valign, gpointer data[GST_VIDEO_MAX_PLANES], GstGLMemory *textures[GST_VIDEO_MAX_PLANES]); diff --git a/gst-libs/gst/gl/gstglupload.c b/gst-libs/gst/gl/gstglupload.c index 605bef5903..7fbf93c43e 100644 --- a/gst-libs/gst/gl/gstglupload.c +++ b/gst-libs/gst/gl/gstglupload.c @@ -261,7 +261,7 @@ _egl_image_upload_perform (gpointer impl, GstBuffer * buffer, /* FIXME: buffer pool */ *outbuf = gst_buffer_new (); gst_gl_memory_setup_buffer (image->upload->context, - &image->upload->priv->out_info, *outbuf); + &image->upload->priv->out_info, NULL, *outbuf); for (i = 0; i < GST_VIDEO_INFO_N_PLANES (&image->upload->priv->in_info); i++) { GstMemory *mem = gst_buffer_peek_memory (buffer, i); @@ -401,7 +401,7 @@ _upload_meta_upload_perform (gpointer impl, GstBuffer * buffer, /* FIXME: buffer pool */ *outbuf = gst_buffer_new (); gst_gl_memory_setup_buffer (upload->upload->context, - &upload->upload->priv->in_info, *outbuf); + &upload->upload->priv->in_info, NULL, *outbuf); for (i = 0; i < GST_VIDEO_MAX_PLANES; i++) { guint tex_id = 0; @@ -509,7 +509,7 @@ _raw_data_upload_perform (gpointer impl, GstBuffer * buffer, if (!raw->in_tex[0]) gst_gl_memory_setup_wrapped (raw->upload->context, - &raw->upload->priv->in_info, raw->in_frame.data, raw->in_tex); + &raw->upload->priv->in_info, NULL, raw->in_frame.data, raw->in_tex); for (i = 0; i < GST_VIDEO_MAX_PLANES; i++) { if (raw->in_tex[i]) { diff --git a/gst-libs/gst/gl/gstgluploadmeta.c b/gst-libs/gst/gl/gstgluploadmeta.c index c2dffd28d5..bab4b024d4 100644 --- a/gst-libs/gst/gl/gstgluploadmeta.c +++ b/gst-libs/gst/gl/gstgluploadmeta.c @@ -223,7 +223,7 @@ _perform_with_gl_memory (GstGLUploadMeta * upload, GstVideoGLTextureUploadMeta * if (!upload->priv->out_tex[i]) upload->priv->out_tex[i] = gst_gl_memory_wrapped_texture (upload->context, - texture_id[i], &upload->info, i, NULL, NULL); + texture_id[i], &upload->info, i, NULL, NULL, NULL); out_mem = upload->priv->out_tex[i]; @@ -256,7 +256,7 @@ _perform_with_data_unlocked (GstGLUploadMeta * upload, for (i = 0; i < GST_VIDEO_INFO_N_PLANES (&upload->info); i++) { if (!upload->priv->in_tex[i]) upload->priv->in_tex[i] = gst_gl_memory_wrapped (upload->context, - &upload->info, i, data[i], NULL, NULL); + &upload->info, i, NULL, data[i], NULL, NULL); upload->priv->in_tex[i]->data = data[i]; } diff --git a/gst-libs/gst/gl/gstglutils.c b/gst-libs/gst/gl/gstglutils.c index 76a78ed34b..b9e60ec2d3 100644 --- a/gst-libs/gst/gl/gstglutils.c +++ b/gst-libs/gst/gl/gstglutils.c @@ -852,3 +852,23 @@ gst_gl_handle_context_query (GstElement * element, GstQuery * query, return res; } + +gsize +gst_gl_get_plane_data_size (GstVideoInfo * info, GstVideoAlignment * align, + guint plane) +{ + gint padded_height; + gsize plane_size; + + padded_height = info->height; + + if (align) + padded_height += align->padding_top + align->padding_bottom; + + padded_height = + GST_VIDEO_FORMAT_INFO_SCALE_HEIGHT (info->finfo, plane, padded_height); + + plane_size = GST_VIDEO_INFO_PLANE_STRIDE (info, plane) * padded_height; + + return plane_size; +} diff --git a/gst-libs/gst/gl/gstglutils.h b/gst-libs/gst/gl/gstglutils.h index 231444df6c..b851612ee9 100644 --- a/gst-libs/gst/gl/gstglutils.h +++ b/gst-libs/gst/gl/gstglutils.h @@ -99,6 +99,9 @@ gboolean gst_gl_handle_set_context (GstElement * element, GstContext * context, gboolean gst_gl_handle_context_query (GstElement * element, GstQuery * query, GstGLDisplay ** display, GstGLContext ** other_context); +gsize gst_gl_get_plane_data_size (GstVideoInfo * info, GstVideoAlignment * align, + guint plane); + G_END_DECLS #endif /* __GST_GL_UTILS_H__ */