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