fdmemory: add fd backed GstMemory to separate file
authorWim Taymans <wtaymans@redhat.com>
Sun, 15 Mar 2015 14:16:23 +0000 (15:16 +0100)
committerWim Taymans <wtaymans@redhat.com>
Sun, 15 Mar 2015 14:26:28 +0000 (15:26 +0100)
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.

gst-libs/gst/allocators/Makefile.am
gst-libs/gst/allocators/gstdmabuf.c
gst-libs/gst/allocators/gstfdmemory.c [new file with mode: 0644]
gst-libs/gst/allocators/gstfdmemory.h [new file with mode: 0644]

index c550ab0..1ff3800 100644 (file)
@@ -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)
index e435681..76bff24 100644 (file)
@@ -22,6 +22,7 @@
 #include "config.h"
 #endif
 
+#include "gstfdmemory.h"
 #include "gstdmabuf.h"
 
 /**
 #include <unistd.h>
 #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 (file)
index 0000000..bdd95fc
--- /dev/null
@@ -0,0 +1,222 @@
+/* GStreamer fd backed memory
+ * Copyright (C) 2013 Linaro SA
+ * Author: Benjamin Gaignard <benjamin.gaignard@linaro.org> 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 <sys/mman.h>
+#include <unistd.h>
+#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 (file)
index 0000000..d85bc43
--- /dev/null
@@ -0,0 +1,54 @@
+/* GStreamer fd memory
+ * Copyright (C) 2013 Linaro SA
+ * Author: Benjamin Gaignard <benjamin.gaignard@linaro.org> 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 <gst/gst.h>
+
+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__ */