From 7964e5dabf3f89b02a89ac775466de5b3dfab8a9 Mon Sep 17 00:00:00 2001 From: Haihua Hu Date: Fri, 25 Nov 2016 14:48:44 +0800 Subject: [PATCH 23/26] Add ion dmabuf support in gldownload Support copy into dma-fb buffer if support the buffer format Upstream-Status: Inappropriate [i.MX specific] Signed-off-by: Haihua Hu --- ext/gl/gstgldownloadelement.c | 36 +++++- gst-libs/gst/gl/Makefile.am | 6 + gst-libs/gst/gl/gstgl_fwd.h | 4 + gst-libs/gst/gl/gstglmemorydma.c | 258 +++++++++++++++++++++++++++++++++++++++ gst-libs/gst/gl/gstglmemorydma.h | 76 ++++++++++++ 5 files changed, 376 insertions(+), 4 deletions(-) create mode 100644 gst-libs/gst/gl/gstglmemorydma.c create mode 100644 gst-libs/gst/gl/gstglmemorydma.h diff --git a/ext/gl/gstgldownloadelement.c b/ext/gl/gstgldownloadelement.c index 03f4479..1e6e728 100644 --- a/ext/gl/gstgldownloadelement.c +++ b/ext/gl/gstgldownloadelement.c @@ -29,6 +29,10 @@ #include #endif +#if GST_GL_HAVE_IONDMA +#include +#endif + GST_DEBUG_CATEGORY_STATIC (gst_gl_download_element_debug); #define GST_CAT_DEFAULT gst_gl_download_element_debug @@ -173,8 +177,22 @@ gst_gl_download_element_prepare_output_buffer (GstBaseTransform * bt, gint i, n; GstGLMemory *glmem; -#if GST_GL_HAVE_PHYMEM glmem = gst_buffer_peek_memory (inbuf, 0); +#if GST_GL_HAVE_IONDMA + if (gst_is_gl_memory_dma (glmem)) { + GstGLContext *context = GST_GL_BASE_FILTER (bt)->context; + GstVideoInfo info; + + gst_video_info_from_caps (&info, src_caps); + *outbuf = gst_gl_memory_dma_buffer_to_gstbuffer (context, &info, inbuf); + + GST_DEBUG_OBJECT (download, "gl download with dma buf."); + + return GST_FLOW_OK; + } +#endif + +#if GST_GL_HAVE_PHYMEM if (gst_is_gl_physical_memory (glmem)) { GstGLContext *context = GST_GL_BASE_FILTER (bt)->context; GstVideoInfo info; @@ -233,6 +251,7 @@ gst_gl_download_element_propose_allocation (GstBaseTransform * bt, GstCaps *caps; GstStructure *config; gsize size; + GstVideoFormat fmt; gst_query_parse_allocation (query, &caps, NULL); if (!gst_video_info_from_caps (&info, caps)) { @@ -240,12 +259,21 @@ gst_gl_download_element_propose_allocation (GstBaseTransform * bt, return FALSE; } - GST_DEBUG_OBJECT (bt, "video format is %s", gst_video_format_to_string (GST_VIDEO_INFO_FORMAT (&info))); - gst_allocation_params_init (¶ms); + fmt = GST_VIDEO_INFO_FORMAT (&info); + + GST_DEBUG_OBJECT (bt, "video format is %s", gst_video_format_to_string (fmt)); + +#if GST_GL_HAVE_IONDMA + if (fmt == GST_VIDEO_FORMAT_RGBA || fmt == GST_VIDEO_FORMAT_RGB16) { + allocator = gst_gl_memory_dma_allocator_obtain (); + GST_DEBUG_OBJECT (bt, "obtain dma memory allocator %p.", allocator); + } +#endif + #if GST_GL_HAVE_PHYMEM - if (gst_is_gl_physical_memory_supported_fmt (&info)) { + if (!allocator && gst_is_gl_physical_memory_supported_fmt (&info)) { allocator = gst_phy_mem_allocator_obtain (); GST_DEBUG_OBJECT (bt, "obtain physical memory allocator %p.", allocator); } diff --git a/gst-libs/gst/gl/Makefile.am b/gst-libs/gst/gl/Makefile.am index 03ce1b0..b0b6655 100644 --- a/gst-libs/gst/gl/Makefile.am +++ b/gst-libs/gst/gl/Makefile.am @@ -137,6 +137,12 @@ libgstgl_@GST_API_VERSION@include_HEADERS += gstglphymemory.h libgstgl_@GST_API_VERSION@_la_LIBADD += -lg2d endif +if HAVE_IONDMA +libgstgl_@GST_API_VERSION@_la_SOURCES += gstglmemorydma.c +libgstgl_@GST_API_VERSION@include_HEADERS += gstglmemorydma.h +endif + + configexecincludedir = $(libdir)/gstreamer-@GST_API_VERSION@/include/gst/gl nodist_configexecinclude_HEADERS = $(built_sys_header_configure) diff --git a/gst-libs/gst/gl/gstgl_fwd.h b/gst-libs/gst/gl/gstgl_fwd.h index 8f42e8d..0f5957d 100644 --- a/gst-libs/gst/gl/gstgl_fwd.h +++ b/gst-libs/gst/gl/gstgl_fwd.h @@ -51,6 +51,10 @@ typedef struct _GstGLMemory GstGLMemory; typedef struct _GstGLMemoryAllocator GstGLMemoryAllocator; typedef struct _GstGLMemoryAllocatorClass GstGLMemoryAllocatorClass; +typedef struct _GstGLMemoryDMA GstGLMemoryDMA; +typedef struct _GstGLMemoryDMAAllocator GstGLMemoryDMAAllocator; +typedef struct _GstGLMemoryDMAAllocatorClass GstGLMemoryDMAAllocatorClass; + typedef struct _GstGLMemoryPBO GstGLMemoryPBO; typedef struct _GstGLMemoryPBOAllocator GstGLMemoryPBOAllocator; typedef struct _GstGLMemoryPBOAllocatorClass GstGLMemoryPBOAllocatorClass; diff --git a/gst-libs/gst/gl/gstglmemorydma.c b/gst-libs/gst/gl/gstglmemorydma.c new file mode 100644 index 0000000..8774e6a --- /dev/null +++ b/gst-libs/gst/gl/gstglmemorydma.c @@ -0,0 +1,258 @@ +/* + * GStreamer + * Copyright (c) 2016, Freescale Semiconductor, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundatdma; either + * versdma 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundatdma, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include +#include + +#if GST_GL_HAVE_IONDMA +#include +#endif + +GST_DEBUG_CATEGORY_STATIC (GST_CAT_GL_DMA_MEMORY); +#define GST_CAT_DEFAULT GST_CAT_GL_DMA_MEMORY + +#define parent_class gst_gl_memory_dma_allocator_parent_class +G_DEFINE_TYPE (GstGLMemoryDMAAllocator, gst_gl_memory_dma_allocator, + GST_TYPE_GL_MEMORY_ALLOCATOR); + +static void +gst_gl_memory_dma_init_instance (void) +{ + GstAllocator *ion_allocator = NULL; + GstGLMemoryDMAAllocator *_gl_allocator; + + GST_DEBUG_CATEGORY_INIT (GST_CAT_GL_DMA_MEMORY, "glmemorydma", 0, "OpenGL dma memory"); + +#if GST_GL_HAVE_IONDMA + ion_allocator = gst_ion_allocator_obtain(); +#endif + + if (!ion_allocator) + return; + + gst_gl_memory_init_once (); + + _gl_allocator = (GstGLMemoryDMAAllocator *) g_object_new (GST_TYPE_GL_MEMORY_DMA_ALLOCATOR, NULL); + _gl_allocator->ion_allocator = ion_allocator; + + gst_allocator_register (GST_GL_MEMORY_DMA_ALLOCATOR_NAME, + gst_object_ref (_gl_allocator)); +} + +GstAllocator * +gst_gl_memory_dma_allocator_obtain (void) +{ + + static GOnce once = G_ONCE_INIT; + GstAllocator *allocator; + + g_once (&once, (GThreadFunc) gst_gl_memory_dma_init_instance, NULL); + + allocator = gst_allocator_find (GST_GL_MEMORY_DMA_ALLOCATOR_NAME); + if (allocator == NULL) + GST_WARNING ("No allocator named %s found", GST_GL_MEMORY_DMA_ALLOCATOR_NAME); + + return allocator; +} + +static void +gst_gl_memory_dma_allocator_dispose (GObject * object) +{ + GstGLMemoryDMAAllocator *gl_dma_alloc= GST_GL_MEMORY_DMA_ALLOCATOR (object); + + if (gl_dma_alloc->ion_allocator) { + GST_DEBUG ("free ion allocator"); + gst_object_unref (gl_dma_alloc->ion_allocator); + gl_dma_alloc->ion_allocator = NULL; + } + + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static gboolean +_gl_mem_create (GstGLMemoryDMA * gl_mem, GError ** error) +{ + GstGLContext *context = gl_mem->mem.mem.context; + GstGLBaseMemoryAllocatorClass *alloc_class; + guint dma_fd; + + alloc_class = GST_GL_BASE_MEMORY_ALLOCATOR_CLASS (parent_class); + if (!alloc_class->create ((GstGLBaseMemory *) gl_mem, error)) + return FALSE; + + dma_fd = gst_dmabuf_memory_get_fd ((GstMemory*) gl_mem->dma); + + gl_mem->eglimage = + gst_egl_image_from_dmabuf (context, dma_fd, &gl_mem->mem.info, 0,0); + + if (!gl_mem->eglimage) { + GST_CAT_ERROR (GST_CAT_GL_DMA_MEMORY, "Can't allocate eglimage memory"); + return FALSE; + } + + const GstGLFuncs *gl = context->gl_vtable; + + gl->ActiveTexture (GL_TEXTURE0); + gl->BindTexture (GL_TEXTURE_2D, gl_mem->mem.tex_id); + gl->EGLImageTargetTexture2D (GL_TEXTURE_2D, + gst_egl_image_get_image (gl_mem->eglimage)); + + GST_CAT_DEBUG (GST_CAT_GL_DMA_MEMORY, "generated dma buffer %p fd %u texid %u", + gl_mem, dma_fd, gl_mem->mem.tex_id); + + return TRUE; +} + +static GstMemory * +_gl_mem_alloc (GstAllocator * allocator, gsize size, + GstAllocationParams * params) +{ + g_warning ("Use gst_gl_base_memory_alloc () to allocate from this " + "GstGLMemoryDMA allocator"); + + return NULL; +} + +static void +_gl_mem_destroy (GstGLMemoryDMA * gl_mem) +{ + GST_CAT_DEBUG (GST_CAT_GL_DMA_MEMORY, "destroy gl dma buffer %p", gl_mem); + + if (gl_mem->eglimage) + gst_egl_image_unref (gl_mem->eglimage); + gl_mem->eglimage = NULL; + if (gl_mem->dma) + gst_memory_unref (GST_MEMORY_CAST (gl_mem->dma)); + gl_mem->dma = NULL; + + GST_GL_BASE_MEMORY_ALLOCATOR_CLASS (parent_class)->destroy ((GstGLBaseMemory + *) gl_mem); +} + +static GstGLMemoryDMA * +_gl_mem_dma_alloc (GstGLBaseMemoryAllocator * allocator, + GstGLVideoAllocationParams * params) +{ + GstGLMemoryDMA *mem; + guint alloc_flags; + gsize size; + GstGLMemoryDMAAllocator *gl_dma_alloc = GST_GL_MEMORY_DMA_ALLOCATOR (allocator); + + alloc_flags = params->parent.alloc_flags; + + g_return_val_if_fail (alloc_flags & GST_GL_ALLOCATION_PARAMS_ALLOC_FLAG_VIDEO, + NULL); + + mem = g_new0 (GstGLMemoryDMA, 1); + + mem->params = params->parent.alloc_params; + + size = gst_gl_get_plane_data_size (params->v_info, params->valign, params->plane); + mem->dma = gst_allocator_alloc (gl_dma_alloc->ion_allocator, size, mem->params); + + if (!mem->dma) { + GST_CAT_ERROR (GST_CAT_GL_DMA_MEMORY, "Can't allocate dma memory size %d", size); + g_free(mem); + return NULL; + } + + gst_gl_memory_init (GST_GL_MEMORY_CAST (mem), GST_ALLOCATOR_CAST (allocator), + NULL, params->parent.context, params->target, params->tex_format, + params->parent.alloc_params, params->v_info, params->plane, + params->valign, params->parent.user_data, params->parent.notify); + + return mem; +} + +static void +gst_gl_memory_dma_allocator_class_init (GstGLMemoryDMAAllocatorClass * klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + GstGLBaseMemoryAllocatorClass *gl_base; + GstAllocatorClass *allocator_class; + + gl_base = (GstGLBaseMemoryAllocatorClass *) klass; + allocator_class = (GstAllocatorClass *) klass; + + gl_base->alloc = (GstGLBaseMemoryAllocatorAllocFunction) _gl_mem_dma_alloc; + gl_base->create = (GstGLBaseMemoryAllocatorCreateFunction) _gl_mem_create; + gl_base->destroy = (GstGLBaseMemoryAllocatorDestroyFunction) _gl_mem_destroy; + gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_gl_memory_dma_allocator_dispose); + + allocator_class->alloc = _gl_mem_alloc; +} + +static void +gst_gl_memory_dma_allocator_init (GstGLMemoryDMAAllocator * allocator) +{ + GstAllocator *alloc = GST_ALLOCATOR_CAST (allocator); + + alloc->mem_type = GST_GL_MEMORY_DMA_ALLOCATOR_NAME; + + GST_OBJECT_FLAG_SET (allocator, GST_ALLOCATOR_FLAG_CUSTOM_ALLOC); +} + +gboolean +gst_is_gl_memory_dma (GstMemory * mem) +{ + return mem != NULL && mem->allocator != NULL + && g_type_is_a (G_OBJECT_TYPE (mem->allocator), + GST_TYPE_GL_MEMORY_DMA_ALLOCATOR); +} + +static void +_finish_texture (GstGLContext * ctx, gpointer *data) +{ + GstGLFuncs *gl = ctx->gl_vtable; + + gl->Finish (); +} + +GstBuffer * +gst_gl_memory_dma_buffer_to_gstbuffer (GstGLContext *ctx, GstVideoInfo * info, + GstBuffer * glbuf) +{ + GstBuffer *buf; + GstGLMemoryDMA *glmem; + + gst_gl_context_thread_add (ctx, (GstGLContextThreadFunc) _finish_texture, NULL); + + glmem = gst_buffer_peek_memory (glbuf, 0); + + buf = gst_buffer_new (); + gst_buffer_append_memory (buf, (GstMemory *) glmem->dma); + gst_memory_ref ((GstMemory *)glmem->dma); + + gst_buffer_add_video_meta_full (buf, 0, + GST_VIDEO_INFO_FORMAT (info), GST_VIDEO_INFO_WIDTH (info), + GST_VIDEO_INFO_HEIGHT (info), 1, info->offset, info->stride); + GST_BUFFER_FLAGS (buf) = GST_BUFFER_FLAGS (glbuf); + GST_BUFFER_PTS (buf) = GST_BUFFER_PTS (glbuf); + GST_BUFFER_DTS (buf) = GST_BUFFER_DTS (glbuf); + GST_BUFFER_DURATION (buf) = GST_BUFFER_DURATION (glbuf); + + return buf; +} diff --git a/gst-libs/gst/gl/gstglmemorydma.h b/gst-libs/gst/gl/gstglmemorydma.h new file mode 100644 index 0000000..f63442a --- /dev/null +++ b/gst-libs/gst/gl/gstglmemorydma.h @@ -0,0 +1,76 @@ +/* + * GStreamer + * Copyright (c) 2016, Freescale Semiconductor, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundatdma; either + * versdma 2 of the License, or (at your optdma) any later versdma. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundatdma, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef _GST_GL_MEMORY_DMA_H_ +#define _GST_GL_MEMORY_DMA_H_ + +#include +#include +#include +#include + +#include +#include +#include + +#include + +G_BEGIN_DECLS + +#define GST_TYPE_GL_MEMORY_DMA_ALLOCATOR (gst_gl_memory_dma_allocator_get_type()) +GType gst_gl_memory_dma_allocator_get_type(void); + +#define GST_IS_GL_MEMORY_DMA_ALLOCATOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_GL_MEMORY_DMA_ALLOCATOR)) +#define GST_IS_GL_MEMORY_DMA_ALLOCATOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_GL_MEMORY_DMA_ALLOCATOR)) +#define GST_GL_MEMORY_DMA_ALLOCATOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_GL_MEMORY_DMA_ALLOCATOR, GstGLMemoryDMAAllocatorClass)) +#define GST_GL_MEMORY_DMA_ALLOCATOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_GL_MEMORY_DMA_ALLOCATOR, GstGLMemoryDMAAllocator)) +#define GST_GL_MEMORY_DMA_ALLOCATOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_GL_MEMORY_DMA_ALLOCATOR, GstGLAllocatorClass)) +#define GST_GL_MEMORY_DMA_ALLOCATOR_CAST(obj) ((GstGLMemoryDMAAllocator *)(obj)) + +struct _GstGLMemoryDMA +{ + GstGLMemory mem; + + /* */ + GstEGLImage *eglimage; + GstMemory *dma; + GstAllocationParams *params; +}; + +#define GST_GL_MEMORY_DMA_ALLOCATOR_NAME "GLMemoryDMA" + +struct _GstGLMemoryDMAAllocator +{ + GstGLMemoryAllocator parent; + GstAllocator *ion_allocator; +}; + +struct _GstGLMemoryDMAAllocatorClass +{ + GstGLMemoryAllocatorClass parent_class; +}; + +GstAllocator *gst_gl_memory_dma_allocator_obtain (void); +gboolean gst_is_gl_memory_dma (GstMemory * mem); +GstBuffer * gst_gl_memory_dma_buffer_to_gstbuffer (GstGLContext * ctx, GstVideoInfo * info, GstBuffer * glbuf); + +G_END_DECLS + +#endif /* _GST_GL_MEMORY_DMA_H_ */ -- 1.9.1