meta-digi/meta-digi-dey/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad-1.8.3/0014-ion-DMA-Buf-allocator-...

482 lines
13 KiB
Diff

From 145ef8665f68fd716fc9def3d765973fd2c2fdd8 Mon Sep 17 00:00:00 2001
From: Song Bing <bing.song@nxp.com>
Date: Mon, 20 Jun 2016 10:28:34 +0800
Subject: [PATCH] ion: DMA Buf allocator based on ion.
DMA Buf allocator based on ion.
Upstream-Status: Pending
https://bugzilla.gnome.org/show_bug.cgi?id=768794
---
configure.ac | 7 +
gst-libs/gst/Makefile.am | 10 +-
gst-libs/gst/ion/Makefile.am | 16 +++
gst-libs/gst/ion/gstionmemory.c | 297 ++++++++++++++++++++++++++++++++++++++++
gst-libs/gst/ion/gstionmemory.h | 72 ++++++++++
5 files changed, 399 insertions(+), 3 deletions(-)
create mode 100644 gst-libs/gst/ion/Makefile.am
create mode 100755 gst-libs/gst/ion/gstionmemory.c
create mode 100755 gst-libs/gst/ion/gstionmemory.h
diff --git a/configure.ac b/configure.ac
index 63cc7161cec5..c0145ae19c76 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2003,6 +2003,12 @@ AG_GST_CHECK_FEATURE(TINYALSA, [tinyalsa], tinyalsa, [
AC_CHECK_HEADER(tinyalsa/asoundlib.h, HAVE_TINYALSA="yes", HAVE_TINYALSA="no")
])
+dnl check for ion
+translit(dnm, m, l) AM_CONDITIONAL(USE_ION, true)
+AG_GST_CHECK_FEATURE(ION, [ion], ion, [
+ AC_CHECK_HEADER(linux/ion.h, HAVE_ION="yes", HAVE_ION="no")
+])
+
dnl *** ext plug-ins ***
dnl keep this list sorted alphabetically !
@@ -3656,6 +3662,7 @@ gst-libs/gst/uridownloader/Makefile
gst-libs/gst/wayland/Makefile
gst-libs/gst/base/Makefile
gst-libs/gst/player/Makefile
+gst-libs/gst/ion/Makefile
gst-libs/gst/video/Makefile
gst-libs/gst/audio/Makefile
sys/Makefile
diff --git a/gst-libs/gst/Makefile.am b/gst-libs/gst/Makefile.am
index 7d0b30925744..eb2031cf65b4 100644
--- a/gst-libs/gst/Makefile.am
+++ b/gst-libs/gst/Makefile.am
@@ -10,12 +10,16 @@ if USE_WAYLAND
WAYLAND_DIR=wayland
endif
+if USE_ION
+ION_DIR=ion
+endif
+
SUBDIRS = uridownloader adaptivedemux interfaces basecamerabinsrc codecparsers \
- insertbin mpegts base video audio player $(GL_DIR) $(WAYLAND_DIR)
+ insertbin mpegts base video audio player $(ION_DIR) $(GL_DIR) $(WAYLAND_DIR)
noinst_HEADERS = gst-i18n-plugin.h gettext.h glib-compat-private.h
DIST_SUBDIRS = uridownloader adaptivedemux interfaces gl basecamerabinsrc \
- codecparsers insertbin mpegts wayland base video audio player
+ codecparsers insertbin mpegts wayland base video audio player ion
#dependencies
video, audio: base
@@ -24,7 +28,7 @@ adaptivedemux: uridownloader
INDEPENDENT_SUBDIRS = \
interfaces basecamerabinsrc codecparsers insertbin uridownloader \
- mpegts base player $(GL_DIR) $(WAYLAND_DIR)
+ mpegts base player $(ION_DIR) $(GL_DIR) $(WAYLAND_DIR)
.PHONY: independent-subdirs $(INDEPENDENT_SUBDIRS)
diff --git a/gst-libs/gst/ion/Makefile.am b/gst-libs/gst/ion/Makefile.am
new file mode 100644
index 000000000000..0a9f9f3a8e48
--- /dev/null
+++ b/gst-libs/gst/ion/Makefile.am
@@ -0,0 +1,16 @@
+lib_LTLIBRARIES = libgstbadion-@GST_API_VERSION@.la
+
+libgstbadion_@GST_API_VERSION@_la_SOURCES = \
+ gstionmemory.c
+
+libgstbadion_@GST_API_VERSION@_la_CFLAGS = $(GST_CFLAGS) \
+ -DGST_USE_UNSTABLE_API
+
+libgstbadion_@GST_API_VERSION@_la_LIBADD = $(GST_LIBS)
+libgstbadion_@GST_API_VERSION@_la_LDFLAGS = $(GST_LIB_LDFLAGS) $(GST_ALL_LDFLAGS) $(GST_LT_LDFLAGS)
+
+libgstion_@GST_API_VERSION@includedir = $(includedir)/gstreamer-@GST_API_VERSION@/gst/ion
+libgstion_@GST_API_VERSION@include_HEADERS = gstionmemory.h
+
+EXTRA_DIST =
+
diff --git a/gst-libs/gst/ion/gstionmemory.c b/gst-libs/gst/ion/gstionmemory.c
new file mode 100755
index 000000000000..ea62ac4926c1
--- /dev/null
+++ b/gst-libs/gst/ion/gstionmemory.c
@@ -0,0 +1,297 @@
+/*
+ * Copyright (c) 2016, Freescale Semiconductor, Inc. All rights reserved.
+ *
+ * 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 Foundation; either
+ * version 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 Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <linux/ion.h>
+
+#include <gst/allocators/gstdmabuf.h>
+#include "gstionmemory.h"
+
+GST_DEBUG_CATEGORY_STATIC(ion_allocator_debug);
+#define GST_CAT_DEFAULT ion_allocator_debug
+
+#define gst_ion_allocator_parent_class parent_class
+
+#define PAGE_ALIGN(x) (((x) + 4095) & ~4095)
+
+G_DEFINE_TYPE(GstIONAllocator, gst_ion_allocator, GST_TYPE_ALLOCATOR)
+
+static int
+gst_ion_open()
+{
+ int fd = open("/dev/ion", O_RDWR);
+ if (fd < 0)
+ GST_ERROR ("open /dev/ion failed!\n");
+ return fd;
+}
+
+static int
+gst_ion_close(int fd)
+{
+ int ret = close(fd);
+ if (ret < 0)
+ return -errno;
+ return ret;
+}
+
+static int
+gst_ion_ioctl(int fd, int req, void *arg)
+{
+ int ret = ioctl(fd, req, arg);
+ if (ret < 0) {
+ GST_ERROR ("ioctl %x failed with code %d: %s\n", req,
+ ret, strerror(errno));
+ return -errno;
+ }
+ return ret;
+}
+
+static int
+gst_ion_alloc(int fd, size_t len, size_t align, unsigned int heap_mask,
+ unsigned int flags, ion_user_handle_t *handle)
+{
+ int ret;
+ struct ion_allocation_data data = {
+ .len = len,
+ .align = align,
+ .heap_id_mask = heap_mask,
+ .flags = flags,
+ };
+
+ if (handle == NULL)
+ return -EINVAL;
+
+ ret = gst_ion_ioctl(fd, ION_IOC_ALLOC, &data);
+ if (ret < 0)
+ return ret;
+ *handle = data.handle;
+ return ret;
+}
+
+static int
+gst_ion_free(int fd, ion_user_handle_t handle)
+{
+ struct ion_handle_data data = {
+ .handle = handle,
+ };
+ return gst_ion_ioctl(fd, ION_IOC_FREE, &data);
+}
+
+static int
+gst_ion_map(int fd, ion_user_handle_t handle, size_t length, int prot,
+ int flags, off_t offset, unsigned char **ptr, int *map_fd)
+{
+ int ret;
+ unsigned char *tmp_ptr;
+ struct ion_fd_data data = {
+ .handle = handle,
+ };
+
+ if (map_fd == NULL)
+ return -EINVAL;
+ if (ptr == NULL)
+ return -EINVAL;
+
+ ret = gst_ion_ioctl(fd, ION_IOC_MAP, &data);
+ if (ret < 0)
+ return ret;
+ if (data.fd < 0) {
+ GST_ERROR ("map ioctl returned negative fd\n");
+ return -EINVAL;
+ }
+ tmp_ptr = mmap(NULL, length, prot, flags, data.fd, offset);
+ if (tmp_ptr == MAP_FAILED) {
+ GST_ERROR ("mmap failed: %s\n", strerror(errno));
+ return -errno;
+ }
+ *map_fd = data.fd;
+ *ptr = tmp_ptr;
+ return ret;
+}
+
+static void
+gst_ion_mem_init(void)
+{
+ GstAllocator *allocator = g_object_new(gst_ion_allocator_get_type(), NULL);
+ GstIONAllocator *self = GST_ION_ALLOCATOR (allocator);
+ gint fd;
+
+ fd = gst_ion_open();
+ if (fd < 0) {
+ GST_ERROR ("Could not open ion driver");
+ g_object_unref (self);
+ return;
+ }
+
+ self->fd = fd;
+ self->dma_allocator = gst_dmabuf_allocator_new();
+
+ gst_allocator_register(GST_TYPE_ION_ALLOCATOR, allocator);
+}
+
+GstAllocator*
+gst_ion_allocator_obtain(void)
+{
+ static GOnce ion_allocator_once = G_ONCE_INIT;
+ GstAllocator *allocator;
+
+ g_once(&ion_allocator_once, (GThreadFunc)gst_ion_mem_init, NULL);
+
+ allocator = gst_allocator_find(GST_TYPE_ION_ALLOCATOR);
+ if (allocator == NULL)
+ GST_WARNING("No allocator named %s found", GST_TYPE_ION_ALLOCATOR);
+
+ return allocator;
+}
+
+GQuark
+gst_ion_memory_quark (void)
+{
+ static GQuark quark = 0;
+
+ if (quark == 0)
+ quark = g_quark_from_string ("GstIONPrivate");
+
+ return quark;
+}
+
+static GstMemory *
+gst_ion_alloc_alloc (GstAllocator * allocator, gint size,
+ GstAllocationParams * params)
+{
+ GstIONAllocator *self = GST_ION_ALLOCATOR (allocator);
+ gint dmafd = -1;
+ guint8 *ptr = NULL;
+ ion_user_handle_t ionHandle;
+ gint ionSize = PAGE_ALIGN (size + params->prefix + params->padding);
+ gint err;
+
+ if (self->fd < 0)
+ return NULL;
+
+ err = gst_ion_alloc(self->fd, ionSize, 8, 1, 0, &ionHandle);
+ if (err) {
+ GST_ERROR ("gst_ion_alloc failed.");
+ return NULL;
+ }
+
+ err = gst_ion_map(self->fd, ionHandle, ionSize, PROT_READ | PROT_WRITE,
+ MAP_SHARED, 0, &ptr, &dmafd);
+ if (err) {
+ GST_ERROR ("gst_ion_map failed.");
+ goto bail;
+ }
+ GST_DEBUG ("phyalloc ptr:0x%x, ionSize:%d dmafd: %d", (int32_t)ptr,
+ ionSize, dmafd);
+
+ GstIONMemory *ion_mem = g_slice_new0 (GstIONMemory);
+ gst_memory_init (GST_MEMORY_CAST (ion_mem), GST_MEMORY_FLAG_NO_SHARE,
+ allocator, 0, size, 0, 0, size);
+
+ ion_mem->vaddr = ptr;
+ ion_mem->size = ionSize;
+ ion_mem->handle = ionHandle;
+ ion_mem->fd = dmafd;
+
+ GstMemory * mem =
+ gst_dmabuf_allocator_alloc(self->dma_allocator, dmafd, ionSize);
+
+ gst_mini_object_set_qdata (GST_MINI_OBJECT (mem), GST_ION_MEMORY_QUARK,
+ ion_mem, gst_memory_unref);
+
+ GST_LOG ("allocated memory %p by allocator %p with qdata %p\n",
+ mem, allocator, ion_mem);
+
+ return mem;
+
+bail:
+ gst_ion_free(self->fd, ionHandle);
+ if (ptr != MAP_FAILED) {
+ munmap(ptr, ionSize);
+ }
+ if (dmafd > 0) {
+ close(dmafd);
+ }
+ return NULL;
+}
+
+static void
+gst_ion_alloc_free (GstAllocator * allocator, GstMemory * memory)
+{
+ GstIONAllocator *self = GST_ION_ALLOCATOR (allocator);
+ GstIONMemory *ion_mem = (GstIONMemory *) memory;
+
+ if (!ion_mem || self->fd < 0)
+ return;
+
+ ion_user_handle_t ionHandle =
+ (ion_user_handle_t)ion_mem->handle;
+ munmap(ion_mem->vaddr, ion_mem->size);
+ close(ion_mem->fd);
+ gst_ion_free(self->fd, ionHandle);
+
+ g_slice_free (GstIONMemory, ion_mem);
+}
+
+static void
+gst_ion_allocator_dispose (GObject * object)
+{
+ GstIONAllocator *self = GST_ION_ALLOCATOR (object);
+
+ if (self->fd > 0) {
+ close(self->fd);
+ self->fd = -1;
+ }
+
+ if (self->dma_allocator)
+ gst_object_unref(self->dma_allocator);
+ self->dma_allocator = NULL;
+
+ G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
+static void
+gst_ion_allocator_class_init (GstIONAllocatorClass * klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GstAllocatorClass *allocator_class = GST_ALLOCATOR_CLASS (klass);
+
+ allocator_class->alloc = GST_DEBUG_FUNCPTR (gst_ion_alloc_alloc);
+ allocator_class->free = GST_DEBUG_FUNCPTR (gst_ion_alloc_free);
+ gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_ion_allocator_dispose);
+
+ GST_DEBUG_CATEGORY_INIT(ion_allocator_debug, "ionmemory", 0, "DMA FD memory allocator based on ion");
+}
+
+static void
+gst_ion_allocator_init (GstIONAllocator * self)
+{
+ GstAllocator *allocator = GST_ALLOCATOR (self);
+
+ allocator->mem_type = GST_ALLOCATOR_ION;
+ allocator->mem_map = NULL;
+ allocator->mem_unmap = NULL;
+}
+
diff --git a/gst-libs/gst/ion/gstionmemory.h b/gst-libs/gst/ion/gstionmemory.h
new file mode 100755
index 000000000000..b6dca5fb9bfe
--- /dev/null
+++ b/gst-libs/gst/ion/gstionmemory.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2016, Freescale Semiconductor, Inc. All rights reserved.
+ *
+ * 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 Foundation; either
+ * version 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 Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GST_IONMEMORY_H__
+#define __GST_IONMEMORY_H__
+
+#include <gst/gst.h>
+#include <gst/gstallocator.h>
+
+G_BEGIN_DECLS
+
+typedef struct _GstIONAllocator GstIONAllocator;
+typedef struct _GstIONAllocatorClass GstIONAllocatorClass;
+typedef struct _GstIONMemory GstIONMemory;
+
+#define GST_ALLOCATOR_ION "ionmem"
+
+#define GST_TYPE_ION_ALLOCATOR gst_ion_allocator_get_type ()
+#define GST_IS_ION_ALLOCATOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
+ GST_TYPE_ION_ALLOCATOR))
+#define GST_ION_ALLOCATOR(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj), GST_TYPE_ION_ALLOCATOR, GstIONAllocator))
+#define GST_ION_ALLOCATOR_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass), GST_TYPE_ION_ALLOCATOR, GstIONAllocatorClass))
+#define GST_ION_ALLOCATOR_CAST(obj) ((GstIONAllocator *)(obj))
+
+#define GST_ION_MEMORY_QUARK gst_ion_memory_quark ()
+
+struct _GstIONAllocator
+{
+ GstAllocator parent;
+
+ gint fd;
+ GstAllocator *dma_allocator;
+};
+
+struct _GstIONAllocatorClass
+{
+ GstAllocatorClass parent;
+};
+
+struct _GstIONMemory {
+ GstMemory mem;
+
+ gint fd;
+ guint8 *vaddr;
+ gsize size;
+ gint handle;
+};
+
+GType gst_ion_allocator_get_type (void);
+GstAllocator* gst_ion_allocator_obtain (void);
+
+G_END_DECLS
+
+#endif /* __GST_IONMEMORY_H__ */