gldownload: accelerate with dma-buf textures For the formats supported by the GPU stack, allocate dma-bufs for the texture to download and have upstream render to it. Downloading then becomes the task to sync dma-buf access before CPU acces (mmap). Note: Currently driver supports only RGBA/BGRA, not RGB/BGR. Change-Id: I04d45d2ba0780a60f5be22b5a48a4c8ba6ca69c7
diff --git a/ext/gl/gstgldownloadelement.c b/ext/gl/gstgldownloadelement.c index aefc289..37e4fff 100644 --- a/ext/gl/gstgldownloadelement.c +++ b/ext/gl/gstgldownloadelement.c
@@ -26,6 +26,7 @@ #if GST_GL_HAVE_PLATFORM_EGL && GST_GL_HAVE_DMABUF #include <gst/gl/egl/gsteglimage.h> #include <gst/allocators/gstdmabuf.h> +#include <gst/gl/gstglmemorydma.h> #endif #include "gstgldownloadelement.h" @@ -50,6 +51,8 @@ GstBuffer * buffer, GstBuffer ** outbuf); static GstFlowReturn gst_gl_download_element_transform (GstBaseTransform * bt, GstBuffer * buffer, GstBuffer * outbuf); +static gboolean gst_gl_download_element_propose_allocation (GstBaseTransform * + trans, GstQuery * decide_query, GstQuery * query); static gboolean gst_gl_download_element_decide_allocation (GstBaseTransform * trans, GstQuery * query); static void gst_gl_download_element_finalize (GObject * object); @@ -88,6 +91,7 @@ gst_gl_download_element_prepare_output_buffer; bt_class->transform = gst_gl_download_element_transform; bt_class->decide_allocation = gst_gl_download_element_decide_allocation; + bt_class->propose_allocation = gst_gl_download_element_propose_allocation; bt_class->passthrough_on_same_caps = TRUE; @@ -394,6 +398,13 @@ GstGLDownloadElement *dl = GST_GL_DOWNLOAD_ELEMENT (bt); gint i, n; + if (gst_is_gl_memory_dma (gst_buffer_peek_memory (inbuf, 0))) { + GstBuffer *buf = gst_gl_memory_dma_sync_buffer (inbuf); + GST_BASE_TRANSFORM_GET_CLASS (bt)->copy_metadata (bt, inbuf, buf); + *outbuf = buf; + return GST_FLOW_OK; + } + *outbuf = inbuf; if (dl->do_pbo_transfers) { @@ -464,6 +475,94 @@ query); } +static gboolean +gst_gl_download_element_propose_allocation (GstBaseTransform * trans, + GstQuery * decide_query, GstQuery * query) +{ + GstGLDownloadElement *dl; + GstGLContext *context; + GstAllocator *allocator; + GstCaps *caps; + GstVideoInfo info; + GstAllocationParams params; + GstVideoFormat format; + GstBufferPool *pool; + GstStructure *config; + GstMemory *mem; + guint n_pools, i; + + dl = GST_GL_DOWNLOAD_ELEMENT_CAST (trans); + gst_query_parse_allocation (query, &caps, NULL); + + if (!gst_video_info_from_caps (&info, caps)) { + GST_ERROR_OBJECT (trans, "invalid caps %" GST_PTR_FORMAT, caps); + goto base; + } + + format = GST_VIDEO_INFO_FORMAT (&info); + GST_DEBUG_OBJECT (dl, "format %s", gst_video_format_to_string (format)); + + switch (format) { + case GST_VIDEO_FORMAT_RGBA: + case GST_VIDEO_FORMAT_BGRA: + gst_gl_memory_dma_init_once (); + allocator = gst_allocator_find (GST_GL_MEMORY_DMA_ALLOCATOR_NAME); + /* Ensure allocator works (i.e. ION is present) */ + mem = gst_allocator_alloc (allocator, 1337, NULL); + if (mem) { + GST_DEBUG_OBJECT (dl, "downloading using dmabuf textures"); + gst_memory_unref (mem); + } else { + GST_ERROR_OBJECT (dl, "dmabuf texture allocator not working"); + gst_object_unref (allocator); + allocator = NULL; + } + break; + /* TODO: 24 bit formats are currently unsupported by the driver. */ + case GST_VIDEO_FORMAT_BGR: + case GST_VIDEO_FORMAT_RGB: + default: + allocator = NULL; + break; + } + + GST_DEBUG_OBJECT (dl, "allocator %p", allocator); + + if (!allocator) { + goto base; + } + + gst_allocation_params_init (¶ms); + gst_query_add_allocation_param (query, allocator, ¶ms); + gst_object_unref (allocator); + + n_pools = gst_query_get_n_allocation_pools (query); + for (i = 0; i < n_pools; ++i) { + gst_query_remove_nth_allocation_pool (query, i); + } + + pool = gst_gl_buffer_pool_new (GST_GL_BASE_FILTER (trans)->context); + config = gst_buffer_pool_get_config (pool); + gst_buffer_pool_config_set_params (config, caps, info.size, 0, 0); + gst_buffer_pool_config_add_option (config, + GST_BUFFER_POOL_OPTION_GL_SYNC_META); + + if (!gst_buffer_pool_set_config (pool, config)) { + gst_object_unref (pool); + GST_ERROR_OBJECT (dl, "gst_buffer_pool_set_config failed"); + goto base; + } + + gst_query_add_allocation_pool (query, pool, info.size, 0, 0); + gst_object_unref (pool); + + return TRUE; + +base: + return GST_BASE_TRANSFORM_CLASS (parent_class)->propose_allocation (trans, + decide_query, query); +} + static void gst_gl_download_element_finalize (GObject * object) {
diff --git a/gst-libs/gst/gl/Makefile.am b/gst-libs/gst/gl/Makefile.am index 4e77e8c..5a456d9 100644 --- a/gst-libs/gst/gl/Makefile.am +++ b/gst-libs/gst/gl/Makefile.am
@@ -13,6 +13,7 @@ gstglbasememory.c \ gstglbuffer.c \ gstglmemory.c \ + gstglmemorydma.c \ gstglmemorypbo.c \ gstglrenderbuffer.c \ gstglbufferpool.c \ @@ -44,6 +45,7 @@ gstglbasememory.h \ gstglbuffer.h \ gstglmemory.h \ + gstglmemorydma.h \ gstglmemorypbo.h \ gstglrenderbuffer.h \ gstglbufferpool.h \
diff --git a/gst-libs/gst/gl/gstglmemorydma.c b/gst-libs/gst/gl/gstglmemorydma.c new file mode 100644 index 0000000..5fbb24f --- /dev/null +++ b/gst-libs/gst/gl/gstglmemorydma.c
@@ -0,0 +1,374 @@ +/* + * # Copyright 2020 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gst/allocators/gstdmabuf.h> +#include <gst/gl/gstglfuncs.h> + +#include "gstglmemorydma.h" + +GST_DEBUG_CATEGORY_STATIC (GST_CAT_GL_MEMORY_DMA); +#define GST_CAT_DEFAULT GST_CAT_GL_MEMORY_DMA + +#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_allocator_finalize (GObject * object); +static GstGLBaseMemory * _gl_mem_dma_alloc + (GstGLBaseMemoryAllocator * allocator, GstGLAllocationParams * params); +static gboolean _gl_mem_dma_create (GstGLBaseMemory * glmem, GError ** error); +static void _gl_mem_dma_destroy (GstGLBaseMemory * glmem); +static GstMemory * _mem_alloc (GstAllocator * allocator, gsize size, + GstAllocationParams * params); + + +static void +gst_gl_memory_dma_allocator_class_init (GstGLMemoryDmaAllocatorClass * klass) +{ + GST_ALLOCATOR_CLASS (klass)->alloc = _mem_alloc; + + GST_GL_BASE_MEMORY_ALLOCATOR_CLASS (klass)->alloc = _gl_mem_dma_alloc; + GST_GL_BASE_MEMORY_ALLOCATOR_CLASS (klass)->create = _gl_mem_dma_create; + GST_GL_BASE_MEMORY_ALLOCATOR_CLASS (klass)->destroy = _gl_mem_dma_destroy; + + G_OBJECT_CLASS (klass)->finalize = gst_gl_memory_dma_allocator_finalize; + + GST_DEBUG_CATEGORY_INIT (GST_CAT_GL_MEMORY_DMA, "glmemorydma", 0, + "OpenGL DMA memory"); +} + +static void +gst_gl_memory_dma_allocator_init (GstGLMemoryDmaAllocator * alloc) +{ + GST_DEBUG_OBJECT (alloc, "init"); + GST_ALLOCATOR (alloc)->mem_type = GST_GL_MEMORY_DMA_ALLOCATOR_NAME; + GST_OBJECT_FLAG_SET (GST_OBJECT (alloc), GST_ALLOCATOR_FLAG_CUSTOM_ALLOC); + + /* ION allocator is in the "coral" plugin, load it. */ + alloc->plugin = gst_plugin_load_by_name ("coral"); + if (!alloc->plugin) { + GST_ERROR_OBJECT (alloc, "coral plugin not found"); + return; + } + + alloc->ion_allocator = gst_allocator_find ("ion"); + if (!alloc->ion_allocator) { + GST_ERROR_OBJECT (alloc, "ION allocator not found"); + return; + } + + GST_INFO_OBJECT (alloc, "ION allocator loaded"); +} + +static void +gst_gl_memory_dma_allocator_finalize (GObject * object) +{ + GstGLMemoryDmaAllocator *alloc = GST_GL_MEMORY_DMA_ALLOCATOR (object); + + GST_DEBUG_OBJECT (alloc, "finalize"); + + if (alloc->ion_allocator) { + gst_object_unref (alloc->ion_allocator); + alloc->ion_allocator = NULL; + } + + if (alloc->plugin) { + gst_object_unref (alloc->plugin); + alloc->plugin = NULL; + } + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static GstGLBaseMemory * + _gl_mem_dma_alloc (GstGLBaseMemoryAllocator * allocator, + GstGLAllocationParams * alloc_params) +{ + GstGLMemoryDmaAllocator *alloc; + GstGLMemoryDMA *dmamem; + GstGLVideoAllocationParams *params; + gsize size; + + alloc = GST_GL_MEMORY_DMA_ALLOCATOR (allocator); + params = (GstGLVideoAllocationParams *) alloc_params; + + g_return_val_if_fail (params->parent.alloc_flags & + GST_GL_ALLOCATION_PARAMS_ALLOC_FLAG_VIDEO, NULL); + + dmamem = g_new0 (GstGLMemoryDMA, 1); + dmamem->params = params->parent.alloc_params; + + /* GstVideoInfo defaults to 4 b stride align for RGB/BGR but we want to + * pack the buffer as tightly as possible (i.e. stride == width * bpp). + */ + switch (params->v_info->finfo->format) { + case GST_VIDEO_FORMAT_RGB: + case GST_VIDEO_FORMAT_BGR: + params->v_info->stride[0] = params->v_info->width * 3; + params->v_info->size = params->v_info->stride[0] * params->v_info->height; + break; + default: + break; + } + + size = gst_gl_get_plane_data_size (params->v_info, params->valign, + params->plane); + dmamem->dma = gst_allocator_alloc (alloc->ion_allocator, size, + dmamem->params); + + if (!dmamem->dma) { + GST_CAT_ERROR (GST_CAT_GL_MEMORY_DMA, "ION alloc of %zu b failed", size); + g_free (dmamem); + return NULL; + } + + GST_CAT_DEBUG (GST_CAT_GL_MEMORY_DMA, "ION alloc %zu b", size); + + gst_gl_memory_init (GST_GL_MEMORY_CAST (dmamem), GST_ALLOCATOR_CAST (alloc), + 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 GST_GL_BASE_MEMORY_CAST (dmamem); +} + +static gboolean +_gl_mem_dma_create (GstGLBaseMemory * glmem, GError ** error) +{ + GstGLMemoryDMA *dmamem; + const GstGLFuncs *gl; + gint fd; + guint tex_id; + + g_return_val_if_fail (glmem, FALSE); + g_return_val_if_fail (glmem->context, FALSE); + gl = glmem->context->gl_vtable; + + if (!GST_GL_BASE_MEMORY_ALLOCATOR_CLASS (parent_class)->create (glmem, + error)) { + return FALSE; + } + + dmamem = GST_GL_MEMORY_DMA_CAST (glmem); + fd = gst_dmabuf_memory_get_fd (dmamem->dma); + tex_id = GST_GL_MEMORY_CAST (&glmem->mem)->tex_id; + + dmamem->image = gst_egl_image_from_dmabuf (glmem->context, fd, + &GST_GL_MEMORY_CAST (glmem)->info, 0, 0); + if (!dmamem->image) { + GST_CAT_ERROR (GST_CAT_GL_MEMORY_DMA, "gst_egl_image_from_dmabuf failed"); + return FALSE; + } + + gl->ActiveTexture (GL_TEXTURE0); + gl->BindTexture (GL_TEXTURE_2D, tex_id); + gl->EGLImageTargetTexture2D (GL_TEXTURE_2D, gst_egl_image_get_image ( + dmamem->image)); + + GST_CAT_DEBUG (GST_CAT_GL_MEMORY_DMA, "created dma mem %p fd %d tex_id %u", + glmem, fd, tex_id); + + return TRUE; +} + +static void +_gl_mem_dma_destroy (GstGLBaseMemory * glmem) +{ + GstGLMemoryDMA *dmamem; + + GST_GL_BASE_MEMORY_ALLOCATOR_CLASS (parent_class)->destroy (glmem); + + dmamem = GST_GL_MEMORY_DMA_CAST (glmem); + + if (dmamem->image) { + gst_egl_image_unref (dmamem->image); + dmamem->image = NULL; + } + + if (dmamem->dma) { + gst_memory_unref (dmamem->dma); + dmamem->dma = NULL; + } + + /* Base class frees dmamem. */ + GST_GL_BASE_MEMORY_ALLOCATOR_CLASS (parent_class)->destroy (glmem); + GST_CAT_DEBUG (GST_CAT_GL_MEMORY_DMA, "destroyed dma mem %p", dmamem); +} + +static GstMemory * +_mem_alloc (GstAllocator * allocator, gsize size, + GstAllocationParams * params) +{ + /* Only used as an init check, does not support actual GL alloc. */ + + GstGLMemoryDmaAllocator *alloc; + + alloc = GST_GL_MEMORY_DMA_ALLOCATOR (allocator); + + g_return_val_if_fail (alloc->ion_allocator, NULL); + + return gst_allocator_alloc (alloc->ion_allocator, size, params); +} + +static EGLDisplay +_get_egl_display (GstGLContext * context) +{ + EGLDisplay egl_display; + GstGLDisplayEGL *display_egl; + if (!context->display) { + return EGL_NO_DISPLAY; + } + display_egl = gst_gl_display_egl_from_gl_display (context->display); + egl_display = + (EGLDisplay) gst_gl_display_get_handle (GST_GL_DISPLAY (display_egl)); + gst_object_unref (display_egl); + return egl_display; +} + +static EGLSyncKHR +_eglCreateSyncKHR (GstGLContext * context) +{ + GstClockTime ts; + EGLSyncKHR sync; + EGLSyncKHR (*gst_eglCreateSyncKHR) (EGLDisplay dpy, EGLenum type, + const EGLAttrib * attrib_list); + EGLDisplay dpy = _get_egl_display (context); + g_assert (dpy != EGL_NO_DISPLAY); + + ts = gst_util_get_timestamp (); + gst_eglCreateSyncKHR = gst_gl_context_get_proc_address (context, + "eglCreateSyncKHR"); + sync = gst_eglCreateSyncKHR (dpy, EGL_SYNC_FENCE_KHR, NULL); + GST_CAT_LOG (GST_CAT_GL_MEMORY_DMA, "created egl sync object %p", sync); + ts = gst_util_get_timestamp () - ts; + GST_CAT_LOG (GST_CAT_GL_MEMORY_DMA, "create %.2g ms",(double) ts / GST_MSECOND); + return sync; +} + +static EGLBoolean +_eglClientWaitSyncKHR (GstGLContext * context, EGLSyncKHR sync) +{ + EGLint (*gst_eglClientWaitSyncKHR) (EGLDisplay dpy, EGLSyncKHR sync, + EGLint flags, EGLTimeKHR timeout); + EGLDisplay dpy = _get_egl_display (context); + g_assert (dpy != EGL_NO_DISPLAY); + + GST_CAT_LOG (GST_CAT_GL_MEMORY_DMA, "waiting on egl sync object %p", sync); + gst_eglClientWaitSyncKHR = gst_gl_context_get_proc_address (context, + "eglClientWaitSyncKHR"); + return gst_eglClientWaitSyncKHR (dpy, sync, EGL_SYNC_FLUSH_COMMANDS_BIT_KHR, + 1000000000 /* 1s */ ) == EGL_CONDITION_SATISFIED_KHR; +} + +static EGLBoolean +_eglDestroySyncKHR (GstGLContext * context, EGLSyncKHR sync) +{ + EGLBoolean (*gst_eglDestroySyncKHR) (EGLDisplay dpy, EGLSyncKHR sync); + EGLDisplay dpy = _get_egl_display (context); + if (dpy == EGL_NO_DISPLAY) { + return EGL_FALSE; + } + + gst_eglDestroySyncKHR = gst_gl_context_get_proc_address (context, + "eglDestroySyncKHR"); + GST_CAT_LOG (GST_CAT_GL_MEMORY_DMA, "deleting egl sync object %p", sync); + return gst_eglDestroySyncKHR (dpy, sync); +} + +static void +_create_sync_gl (GstGLContext * context, gpointer data) +{ + EGLSyncKHR *sync = (EGLSyncKHR *) data; + *sync = _eglCreateSyncKHR (context); +} + +GstBuffer * +gst_gl_memory_dma_sync_buffer (GstBuffer * glbuf) +{ + GstBuffer *buf; + GstVideoInfo *info; + GstMemory *mem; + GstGLBaseMemory *glmem; + GstGLMemoryDMA *dmamem; + GstGLSyncMeta *sync_meta; + EGLSyncKHR sync; + EGLBoolean res; + GstClockTime ts; + + mem = gst_buffer_peek_memory (glbuf, 0); + g_assert (gst_is_gl_memory_dma (mem)); + + glmem = GST_GL_BASE_MEMORY_CAST (mem); + dmamem = GST_GL_MEMORY_DMA_CAST (mem); + sync_meta = gst_buffer_get_gl_sync_meta (glbuf); + + if (sync_meta) { + ts = gst_util_get_timestamp (); + gst_gl_sync_meta_wait_cpu (sync_meta, glmem->context); + ts = gst_util_get_timestamp () - ts; + GST_CAT_DEBUG (GST_CAT_GL_MEMORY_DMA, "wait_cpu %.2g ms", + (double) ts / GST_MSECOND); + } else { + ts = gst_util_get_timestamp (); + gst_gl_context_thread_add (glmem->context, _create_sync_gl, &sync); + g_assert (sync != EGL_NO_SYNC_KHR); + + do { + res = _eglClientWaitSyncKHR (glmem->context, sync); + } while (res == EGL_FALSE); + ts = gst_util_get_timestamp () - ts; + + res = _eglDestroySyncKHR (glmem->context, sync); + g_assert (res == EGL_TRUE); + ts = gst_util_get_timestamp () - ts; + GST_CAT_DEBUG (GST_CAT_GL_MEMORY_DMA, "egl_sync %.2g ms", + (double) ts / GST_MSECOND); + } + + info = &dmamem->mem.info; + buf = gst_buffer_new (); + gst_buffer_add_parent_buffer_meta (buf, glbuf); + gst_buffer_append_memory (buf, gst_memory_ref (dmamem->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); + + return buf; +} + +gboolean +gst_is_gl_memory_dma (GstMemory * mem) +{ + return mem && mem->allocator && g_type_is_a (G_OBJECT_TYPE (mem->allocator), + GST_TYPE_GL_MEMORY_DMA_ALLOCATOR); +} + +void +gst_gl_memory_dma_init_once (void) +{ + static volatile gsize _init = 0; + + if (g_once_init_enter (&_init)) { + GstAllocator *alloc = g_object_new (GST_TYPE_GL_MEMORY_DMA_ALLOCATOR, NULL); + gst_object_ref_sink (alloc); + gst_allocator_register (GST_GL_MEMORY_DMA_ALLOCATOR_NAME, alloc); + g_once_init_leave (&_init, 1); + } +}
diff --git a/gst-libs/gst/gl/gstglmemorydma.h b/gst-libs/gst/gl/gstglmemorydma.h new file mode 100644 index 0000000..8feb089 --- /dev/null +++ b/gst-libs/gst/gl/gstglmemorydma.h
@@ -0,0 +1,86 @@ +/* + * # Copyright 2020 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _GST_GL_MEMORY_DMA_H_ +#define _GST_GL_MEMORY_DMA_H_ + +#include <gst/gst.h> +#include <gst/gstallocator.h> +#include <gst/gl/gl.h> +#include <gst/gl/egl/gsteglimage.h> +#include <gst/gl/egl/gstegl.h> +#include <gst/gl/egl/gstgldisplay_egl.h> + +G_BEGIN_DECLS + +#define GST_TYPE_GL_MEMORY_DMA_ALLOCATOR (gst_gl_memory_dma_allocator_get_type()) + +#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)) +#define GST_GL_MEMORY_DMA_CAST(obj) ((GstGLMemoryDMA *)(obj)) + +#define GST_GL_MEMORY_DMA_ALLOCATOR_NAME "glmemorydma" + +typedef struct _GstGLMemoryDMA GstGLMemoryDMA; +typedef struct _GstGLMemoryDmaAllocator GstGLMemoryDmaAllocator; +typedef struct _GstGLMemoryDmaAllocatorClass GstGLMemoryDmaAllocatorClass; + +struct _GstGLMemoryDMA +{ + GstGLMemory mem; + + GstEGLImage *image; + GstMemory *dma; + GstAllocationParams *params; +}; + +struct _GstGLMemoryDmaAllocator +{ + GstGLMemoryAllocator alloc; + + GstPlugin *plugin; + GstAllocator *ion_allocator; +}; + +struct _GstGLMemoryDmaAllocatorClass +{ + GstGLMemoryAllocatorClass parent_class; +}; + +GST_GL_API +GType gst_gl_memory_dma_allocator_get_type(void); + +GST_GL_API +gboolean gst_is_gl_memory_dma (GstMemory * mem); + +GST_GL_API +GstBuffer * gst_gl_memory_dma_sync_buffer (GstBuffer * glbuf); + +GST_GL_API +void gst_gl_memory_dma_init_once (void); + +G_END_DECLS + +#endif /* _GST_GL_MEMORY_DMA_H_ */ + + + + +