From: Wim Taymans Date: Sun, 15 Mar 2015 14:16:23 +0000 (+0100) Subject: fdmemory: add fd backed GstMemory to separate file X-Git-Tag: 1.19.3~511^2~3779 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=4e6fba86049d2429d622eaf0e5b081aa8919a18b;p=platform%2Fupstream%2Fgstreamer.git fdmemory: add fd backed GstMemory to separate file Make a separate file for the code to handle the fd backed memory. This would make it possible later to add other allocators also using fd backed memory. --- diff --git a/gst-libs/gst/allocators/Makefile.am b/gst-libs/gst/allocators/Makefile.am index c550ab0..1ff3800 100644 --- a/gst-libs/gst/allocators/Makefile.am +++ b/gst-libs/gst/allocators/Makefile.am @@ -6,9 +6,10 @@ libgstallocators_@GST_API_VERSION@_include_HEADERS = \ allocators.h \ gstdmabuf.h -noinst_HEADERS = +noinst_HEADERS = gstfdmemory.h libgstallocators_@GST_API_VERSION@_la_SOURCES = \ + gstfdmemory.c \ gstdmabuf.c libgstallocators_@GST_API_VERSION@_la_LIBADD = $(GST_LIBS) $(LIBM) diff --git a/gst-libs/gst/allocators/gstdmabuf.c b/gst-libs/gst/allocators/gstdmabuf.c index e435681..76bff24 100644 --- a/gst-libs/gst/allocators/gstdmabuf.c +++ b/gst-libs/gst/allocators/gstdmabuf.c @@ -22,6 +22,7 @@ #include "config.h" #endif +#include "gstfdmemory.h" #include "gstdmabuf.h" /** @@ -37,154 +38,9 @@ #include #endif -/* - * GstDmaBufMemory - * @fd: the file descriptor associated this memory - * @data: mmapped address - * @mmapping_flags: mmapping flags - * @mmap_count: mmapping counter - * @lock: a mutex to make mmapping thread safe - */ -typedef struct -{ - GstMemory mem; - - gint fd; - gpointer data; - gint mmapping_flags; - gint mmap_count; - GMutex lock; -} GstDmaBufMemory; - GST_DEBUG_CATEGORY_STATIC (dmabuf_debug); #define GST_CAT_DEFAULT dmabuf_debug -static void -gst_dmabuf_allocator_free (GstAllocator * allocator, GstMemory * gmem) -{ -#ifdef HAVE_MMAP - GstDmaBufMemory *mem = (GstDmaBufMemory *) gmem; - - if (mem->data) { - g_warning (G_STRLOC ":%s: Freeing memory %p still mapped", G_STRFUNC, mem); - munmap ((void *) mem->data, gmem->maxsize); - } - if (mem->fd >= 0 && gmem->parent == NULL) - close (mem->fd); - g_mutex_clear (&mem->lock); - g_slice_free (GstDmaBufMemory, mem); - GST_DEBUG ("%p: freed", mem); -#endif -} - -static gpointer -gst_dmabuf_mem_map (GstMemory * gmem, gsize maxsize, GstMapFlags flags) -{ -#ifdef HAVE_MMAP - GstDmaBufMemory *mem = (GstDmaBufMemory *) gmem; - gint prot; - gpointer ret = NULL; - - if (gmem->parent) - return gst_dmabuf_mem_map (gmem->parent, maxsize, flags); - - g_mutex_lock (&mem->lock); - - prot = flags & GST_MAP_READ ? PROT_READ : 0; - prot |= flags & GST_MAP_WRITE ? PROT_WRITE : 0; - - /* do not mmap twice the buffer */ - if (mem->data) { - /* only return address if mapping flags are a subset - * of the previous flags */ - if ((mem->mmapping_flags & prot) == prot) { - ret = mem->data; - mem->mmap_count++; - } - - goto out; - } - - if (mem->fd != -1) { - mem->data = mmap (0, gmem->maxsize, prot, MAP_SHARED, mem->fd, 0); - if (mem->data == MAP_FAILED) { - mem->data = NULL; - GST_ERROR ("%p: fd %d: mmap failed: %s", mem, mem->fd, - g_strerror (errno)); - goto out; - } - } - - GST_DEBUG ("%p: fd %d: mapped %p", mem, mem->fd, mem->data); - - if (mem->data) { - mem->mmapping_flags = prot; - mem->mmap_count++; - ret = mem->data; - } - -out: - g_mutex_unlock (&mem->lock); - return ret; -#else /* !HAVE_MMAP */ - return FALSE; -#endif -} - -static void -gst_dmabuf_mem_unmap (GstMemory * gmem) -{ -#ifdef HAVE_MMAP - GstDmaBufMemory *mem = (GstDmaBufMemory *) gmem; - - if (gmem->parent) - return gst_dmabuf_mem_unmap (gmem->parent); - - g_mutex_lock (&mem->lock); - - if (mem->data && !(--mem->mmap_count)) { - munmap ((void *) mem->data, gmem->maxsize); - mem->data = NULL; - mem->mmapping_flags = 0; - GST_DEBUG ("%p: fd %d unmapped", mem, mem->fd); - } - g_mutex_unlock (&mem->lock); -#endif -} - -static GstMemory * -gst_dmabuf_mem_share (GstMemory * gmem, gssize offset, gssize size) -{ -#ifdef HAVE_MMAP - GstDmaBufMemory *mem = (GstDmaBufMemory *) gmem; - GstDmaBufMemory *sub; - GstMemory *parent; - - GST_DEBUG ("%p: share %" G_GSSIZE_FORMAT " %" G_GSIZE_FORMAT, mem, offset, - size); - - /* find the real parent */ - if ((parent = mem->mem.parent) == NULL) - parent = (GstMemory *) mem; - - if (size == -1) - size = gmem->maxsize - offset; - - sub = g_slice_new0 (GstDmaBufMemory); - /* the shared memory is always readonly */ - gst_memory_init (GST_MEMORY_CAST (sub), GST_MINI_OBJECT_FLAGS (parent) | - GST_MINI_OBJECT_FLAG_LOCK_READONLY, mem->mem.allocator, parent, - mem->mem.maxsize, mem->mem.align, mem->mem.offset + offset, size); - - sub->fd = mem->fd; - g_mutex_init (&sub->lock); - - return GST_MEMORY_CAST (sub); -#else /* !HAVE_MMAP */ - return NULL; -#endif -} - typedef struct { GstAllocator parent; @@ -208,8 +64,7 @@ dmabuf_mem_allocator_class_init (GstDmaBufAllocatorClass * klass) allocator_class = (GstAllocatorClass *) klass; - allocator_class->alloc = NULL; - allocator_class->free = gst_dmabuf_allocator_free; + __gst_fd_memory_class_init_allocator (allocator_class); } static void @@ -217,11 +72,7 @@ dmabuf_mem_allocator_init (GstDmaBufAllocator * allocator) { GstAllocator *alloc = GST_ALLOCATOR_CAST (allocator); - alloc->mem_type = GST_ALLOCATOR_DMABUF; - alloc->mem_map = gst_dmabuf_mem_map; - alloc->mem_unmap = gst_dmabuf_mem_unmap; - alloc->mem_share = gst_dmabuf_mem_share; - /* Use the default, fallback copy function */ + __gst_fd_memory_init_allocator (alloc, GST_ALLOCATOR_DMABUF); GST_OBJECT_FLAG_SET (allocator, GST_ALLOCATOR_FLAG_CUSTOM_ALLOC); } @@ -263,26 +114,13 @@ GstMemory * gst_dmabuf_allocator_alloc (GstAllocator * allocator, gint fd, gsize size) { #ifdef HAVE_MMAP - GstDmaBufMemory *mem; - if (!GST_IS_DMABUF_ALLOCATOR (allocator)) { GST_WARNING ("it isn't the correct allocator for dmabuf"); return NULL; } GST_DEBUG ("alloc from allocator %p", allocator); - - mem = g_slice_new0 (GstDmaBufMemory); - - gst_memory_init (GST_MEMORY_CAST (mem), 0, allocator, NULL, size, 0, 0, size); - - mem->fd = fd; - g_mutex_init (&mem->lock); - - GST_DEBUG ("%p: fd: %d size %" G_GSIZE_FORMAT, mem, mem->fd, - mem->mem.maxsize); - - return (GstMemory *) mem; + return __gst_fd_memory_new (allocator, fd, size); #else /* !HAVE_MMAP */ return NULL; #endif @@ -303,11 +141,11 @@ gst_dmabuf_allocator_alloc (GstAllocator * allocator, gint fd, gsize size) gint gst_dmabuf_memory_get_fd (GstMemory * mem) { - GstDmaBufMemory *dbmem = (GstDmaBufMemory *) mem; + GstFdMemory *fdmem = (GstFdMemory *) mem; g_return_val_if_fail (gst_is_dmabuf_memory (mem), -1); - return dbmem->fd; + return fdmem->fd; } /** diff --git a/gst-libs/gst/allocators/gstfdmemory.c b/gst-libs/gst/allocators/gstfdmemory.c new file mode 100644 index 0000000..bdd95fc --- /dev/null +++ b/gst-libs/gst/allocators/gstfdmemory.c @@ -0,0 +1,222 @@ +/* GStreamer fd backed memory + * Copyright (C) 2013 Linaro SA + * Author: Benjamin Gaignard for Linaro. + * + * 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 mordetails. + * + * 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gstfdmemory.h" + +#ifdef HAVE_MMAP +#include +#include +#endif + +static void +gst_fd_mem_free (GstAllocator * allocator, GstMemory * gmem) +{ +#ifdef HAVE_MMAP + GstFdMemory *mem = (GstFdMemory *) gmem; + + if (mem->data) { + g_warning (G_STRLOC ":%s: Freeing memory %p still mapped", G_STRFUNC, mem); + munmap ((void *) mem->data, gmem->maxsize); + } + if (mem->fd >= 0 && gmem->parent == NULL) + close (mem->fd); + g_mutex_clear (&mem->lock); + g_slice_free (GstFdMemory, mem); + GST_DEBUG ("%p: freed", mem); +#endif +} + +static gpointer +gst_fd_mem_map (GstMemory * gmem, gsize maxsize, GstMapFlags flags) +{ +#ifdef HAVE_MMAP + GstFdMemory *mem = (GstFdMemory *) gmem; + gint prot; + gpointer ret = NULL; + + if (gmem->parent) + return gst_fd_mem_map (gmem->parent, maxsize, flags); + + g_mutex_lock (&mem->lock); + + prot = flags & GST_MAP_READ ? PROT_READ : 0; + prot |= flags & GST_MAP_WRITE ? PROT_WRITE : 0; + + /* do not mmap twice the buffer */ + if (mem->data) { + /* only return address if mapping flags are a subset + * of the previous flags */ + if ((mem->mmapping_flags & prot) == prot) { + ret = mem->data; + mem->mmap_count++; + } + + goto out; + } + + if (mem->fd != -1) { + mem->data = mmap (0, gmem->maxsize, prot, MAP_SHARED, mem->fd, 0); + if (mem->data == MAP_FAILED) { + mem->data = NULL; + GST_ERROR ("%p: fd %d: mmap failed: %s", mem, mem->fd, + g_strerror (errno)); + goto out; + } + } + + GST_DEBUG ("%p: fd %d: mapped %p", mem, mem->fd, mem->data); + + if (mem->data) { + mem->mmapping_flags = prot; + mem->mmap_count++; + ret = mem->data; + } + +out: + g_mutex_unlock (&mem->lock); + return ret; +#else /* !HAVE_MMAP */ + return FALSE; +#endif +} + +static void +gst_fd_mem_unmap (GstMemory * gmem) +{ +#ifdef HAVE_MMAP + GstFdMemory *mem = (GstFdMemory *) gmem; + + if (gmem->parent) + return gst_fd_mem_unmap (gmem->parent); + + g_mutex_lock (&mem->lock); + + if (mem->data && !(--mem->mmap_count)) { + munmap ((void *) mem->data, gmem->maxsize); + mem->data = NULL; + mem->mmapping_flags = 0; + GST_DEBUG ("%p: fd %d unmapped", mem, mem->fd); + } + g_mutex_unlock (&mem->lock); +#endif +} + +static GstMemory * +gst_fd_mem_share (GstMemory * gmem, gssize offset, gssize size) +{ +#ifdef HAVE_MMAP + GstFdMemory *mem = (GstFdMemory *) gmem; + GstFdMemory *sub; + GstMemory *parent; + + GST_DEBUG ("%p: share %" G_GSSIZE_FORMAT " %" G_GSIZE_FORMAT, mem, offset, + size); + + /* find the real parent */ + if ((parent = mem->mem.parent) == NULL) + parent = (GstMemory *) mem; + + if (size == -1) + size = gmem->maxsize - offset; + + sub = g_slice_new0 (GstFdMemory); + /* the shared memory is always readonly */ + gst_memory_init (GST_MEMORY_CAST (sub), GST_MINI_OBJECT_FLAGS (parent) | + GST_MINI_OBJECT_FLAG_LOCK_READONLY, mem->mem.allocator, parent, + mem->mem.maxsize, mem->mem.align, mem->mem.offset + offset, size); + + sub->fd = mem->fd; + g_mutex_init (&sub->lock); + + return GST_MEMORY_CAST (sub); +#else /* !HAVE_MMAP */ + return NULL; +#endif +} + +/** + * gst_fd_memory_new: + * @allocator: allocator to be used for this memory + * @fd: file descriptor + * @size: memory size + * + * Return a %GstMemory that wraps a file descriptor. + * + * Returns: (transfer full): a GstMemory based on @allocator. + * When the buffer is released, @fd is closed. + * The memory is only mmapped on gst_buffer_mmap() request. + * + * Since: 1.2 + */ +GstMemory * +__gst_fd_memory_new (GstAllocator * allocator, gint fd, gsize size) +{ +#ifdef HAVE_MMAP + GstFdMemory *mem; + + mem = g_slice_new0 (GstFdMemory); + gst_memory_init (GST_MEMORY_CAST (mem), 0, allocator, NULL, size, 0, 0, size); + + mem->fd = fd; + g_mutex_init (&mem->lock); + + GST_DEBUG ("%p: fd: %d size %" G_GSIZE_FORMAT, mem, mem->fd, + mem->mem.maxsize); + + return (GstMemory *) mem; +#else /* !HAVE_MMAP */ + return NULL; +#endif +} + +/** + * gst_fd_memory_class_init_allocator: + * @allocator: a #GstAllocatorClass + * + * Sets up the methods to alloc and free fd backed memory created + * with @gst_fd_memory_new by @allocator. + */ +void +__gst_fd_memory_class_init_allocator (GstAllocatorClass * allocator) +{ + allocator->alloc = NULL; + allocator->free = gst_fd_mem_free; +} + +/** + * gst_fd_memory_init_allocator: + * @allocator: a #GstAllocator + * @type: the memory type + * + * Sets up the methods to map and unmap and share fd backed memory + * created with @allocator. + */ +void +__gst_fd_memory_init_allocator (GstAllocator * allocator, const gchar * type) +{ + allocator->mem_type = type; + allocator->mem_map = gst_fd_mem_map; + allocator->mem_unmap = gst_fd_mem_unmap; + allocator->mem_share = gst_fd_mem_share; +} diff --git a/gst-libs/gst/allocators/gstfdmemory.h b/gst-libs/gst/allocators/gstfdmemory.h new file mode 100644 index 0000000..d85bc43 --- /dev/null +++ b/gst-libs/gst/allocators/gstfdmemory.h @@ -0,0 +1,54 @@ +/* GStreamer fd memory + * Copyright (C) 2013 Linaro SA + * Author: Benjamin Gaignard for Linaro. + * + * 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_FD_MEMORY_H__ +#define __GST_FD_MEMORY_H__ + +#include + +G_BEGIN_DECLS + +/* + * GstFdfMemory + * @fd: the file descriptor associated this memory + * @data: mmapped address + * @mmapping_flags: mmapping flags + * @mmap_count: mmapping counter + * @lock: a mutex to make mmapping thread safe + */ +typedef struct +{ + GstMemory mem; + + gint fd; + gpointer data; + gint mmapping_flags; + gint mmap_count; + GMutex lock; +} GstFdMemory; + +void __gst_fd_memory_class_init_allocator (GstAllocatorClass * allocator); +void __gst_fd_memory_init_allocator (GstAllocator * allocator, const gchar *type); + +GstMemory * __gst_fd_memory_new (GstAllocator * allocator, gint fd, gsize size); + + +G_END_DECLS +#endif /* __GST_FD_MEMORY_H__ */