mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-24 01:00:37 +00:00
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.
This commit is contained in:
parent
b0b0ae1f24
commit
4e6fba8604
4 changed files with 284 additions and 169 deletions
|
@ -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)
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "gstfdmemory.h"
|
||||
#include "gstdmabuf.h"
|
||||
|
||||
/**
|
||||
|
@ -37,154 +38,9 @@
|
|||
#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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
222
gst-libs/gst/allocators/gstfdmemory.c
Normal file
222
gst-libs/gst/allocators/gstfdmemory.c
Normal file
|
@ -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;
|
||||
}
|
54
gst-libs/gst/allocators/gstfdmemory.h
Normal file
54
gst-libs/gst/allocators/gstfdmemory.h
Normal file
|
@ -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__ */
|
Loading…
Reference in a new issue