From 145ef8665f68fd716fc9def3d765973fd2c2fdd8 Mon Sep 17 00:00:00 2001 From: Song Bing 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 +#include +#include +#include +#include +#include +#include +#include + +#include +#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 +#include + +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__ */