mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-06-06 07:28:53 +00:00
v4l2: Add dmabuf export support
This can be enabled sing io-mode=dmabuf. This will enabled mmap base drivers to export the buffers as dmabuf.
This commit is contained in:
parent
7b00d7ac46
commit
1ab90ababa
3 changed files with 112 additions and 9 deletions
|
@ -23,7 +23,12 @@
|
||||||
#include "gstv4l2allocator.h"
|
#include "gstv4l2allocator.h"
|
||||||
#include "v4l2_calls.h"
|
#include "v4l2_calls.h"
|
||||||
|
|
||||||
|
#include <gst/allocators/gstdmabuf.h>
|
||||||
|
|
||||||
|
#include <fcntl.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
#define GST_V4L2_MEMORY_TYPE "V4l2Memory"
|
#define GST_V4L2_MEMORY_TYPE "V4l2Memory"
|
||||||
|
|
||||||
|
@ -121,7 +126,8 @@ _v4l2mem_dispose (GstV4l2Memory * mem)
|
||||||
gboolean ret;
|
gboolean ret;
|
||||||
|
|
||||||
if (group->mem[mem->plane]) {
|
if (group->mem[mem->plane]) {
|
||||||
gst_memory_ref ((GstMemory *) mem);
|
/* We may have a dmabuf, replace it with returned original memory */
|
||||||
|
group->mem[mem->plane] = gst_memory_ref ((GstMemory *) mem);
|
||||||
gst_v4l2_allocator_release (allocator, mem);
|
gst_v4l2_allocator_release (allocator, mem);
|
||||||
ret = FALSE;
|
ret = FALSE;
|
||||||
} else {
|
} else {
|
||||||
|
@ -135,13 +141,15 @@ _v4l2mem_dispose (GstV4l2Memory * mem)
|
||||||
static void
|
static void
|
||||||
_v4l2mem_free (GstV4l2Memory * mem)
|
_v4l2mem_free (GstV4l2Memory * mem)
|
||||||
{
|
{
|
||||||
|
if (mem->dmafd > 0)
|
||||||
|
close (mem->dmafd);
|
||||||
g_slice_free (GstV4l2Memory, mem);
|
g_slice_free (GstV4l2Memory, mem);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline GstV4l2Memory *
|
static inline GstV4l2Memory *
|
||||||
_v4l2mem_new (GstMemoryFlags flags, GstAllocator * allocator,
|
_v4l2mem_new (GstMemoryFlags flags, GstAllocator * allocator,
|
||||||
GstMemory * parent, gsize maxsize, gsize align, gsize offset, gsize size,
|
GstMemory * parent, gsize maxsize, gsize align, gsize offset, gsize size,
|
||||||
gint plane, gpointer data, GstV4l2MemoryGroup * group)
|
gint plane, gpointer data, int dmafd, GstV4l2MemoryGroup * group)
|
||||||
{
|
{
|
||||||
GstV4l2Memory *mem;
|
GstV4l2Memory *mem;
|
||||||
|
|
||||||
|
@ -155,6 +163,7 @@ _v4l2mem_new (GstMemoryFlags flags, GstAllocator * allocator,
|
||||||
|
|
||||||
mem->plane = plane;
|
mem->plane = plane;
|
||||||
mem->data = data;
|
mem->data = data;
|
||||||
|
mem->dmafd = dmafd;
|
||||||
mem->group = group;
|
mem->group = group;
|
||||||
|
|
||||||
return mem;
|
return mem;
|
||||||
|
@ -177,7 +186,7 @@ _v4l2mem_share (GstV4l2Memory * mem, gssize offset, gsize size)
|
||||||
sub = _v4l2mem_new (GST_MINI_OBJECT_FLAGS (parent) |
|
sub = _v4l2mem_new (GST_MINI_OBJECT_FLAGS (parent) |
|
||||||
GST_MINI_OBJECT_FLAG_LOCK_READONLY, mem->mem.allocator, parent,
|
GST_MINI_OBJECT_FLAG_LOCK_READONLY, mem->mem.allocator, parent,
|
||||||
mem->mem.maxsize, mem->mem.align, offset, size, mem->plane, mem->data,
|
mem->mem.maxsize, mem->mem.align, offset, size, mem->plane, mem->data,
|
||||||
mem->group);
|
-1, mem->group);
|
||||||
|
|
||||||
return sub;
|
return sub;
|
||||||
}
|
}
|
||||||
|
@ -192,6 +201,13 @@ _v4l2mem_is_span (GstV4l2Memory * mem1, GstV4l2Memory * mem2, gsize * offset)
|
||||||
return mem1->mem.offset + mem1->mem.size == mem2->mem.offset;
|
return mem1->mem.offset + mem1->mem.size == mem2->mem.offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_v4l2mem_parent_to_dmabuf (GstV4l2Memory * mem, GstMemory * dma_mem)
|
||||||
|
{
|
||||||
|
gst_memory_lock (&mem->mem, GST_LOCK_FLAG_EXCLUSIVE);
|
||||||
|
dma_mem->parent = gst_memory_ref (&mem->mem);
|
||||||
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
gst_is_v4l2_memory (GstMemory * mem)
|
gst_is_v4l2_memory (GstMemory * mem)
|
||||||
{
|
{
|
||||||
|
@ -721,7 +737,7 @@ gst_v4l2_allocator_alloc_mmap (GstV4l2Allocator * allocator)
|
||||||
|
|
||||||
group->mem[i] = (GstMemory *) _v4l2mem_new (0, GST_ALLOCATOR (allocator),
|
group->mem[i] = (GstMemory *) _v4l2mem_new (0, GST_ALLOCATOR (allocator),
|
||||||
NULL, group->planes[i].length, 0, 0, group->planes[i].length, i,
|
NULL, group->planes[i].length, 0, 0, group->planes[i].length, i,
|
||||||
data, group);
|
data, -1, group);
|
||||||
} else {
|
} else {
|
||||||
/* Take back the allocator reference */
|
/* Take back the allocator reference */
|
||||||
gst_object_ref (allocator);
|
gst_object_ref (allocator);
|
||||||
|
@ -757,14 +773,90 @@ mmap_failed:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
GstV4l2MemoryGroup *
|
GstV4l2MemoryGroup *
|
||||||
gst_v4l2_allocator_alloc_dmabuf (GstV4l2Allocator * allocator)
|
gst_v4l2_allocator_alloc_dmabuf (GstV4l2Allocator * allocator,
|
||||||
|
GstAllocator * dmabuf_allocator)
|
||||||
{
|
{
|
||||||
/* TODO */
|
GstV4l2MemoryGroup *group;
|
||||||
return NULL;
|
gint i;
|
||||||
|
|
||||||
|
g_return_val_if_fail (allocator->memory == V4L2_MEMORY_MMAP, NULL);
|
||||||
|
|
||||||
|
group = gst_v4l2_allocator_alloc (allocator);
|
||||||
|
|
||||||
|
if (group == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
for (i = 0; i < group->n_mem; i++) {
|
||||||
|
GstV4l2Memory *mem;
|
||||||
|
GstMemory *dma_mem;
|
||||||
|
gint dmafd;
|
||||||
|
|
||||||
|
if (group->mem[i] == NULL) {
|
||||||
|
struct v4l2_exportbuffer expbuf = { 0 };
|
||||||
|
|
||||||
|
expbuf.type = allocator->type;
|
||||||
|
expbuf.index = group->buffer.index;
|
||||||
|
expbuf.plane = i;
|
||||||
|
expbuf.flags = O_CLOEXEC | O_RDWR;
|
||||||
|
|
||||||
|
if (v4l2_ioctl (allocator->video_fd, VIDIOC_EXPBUF, &expbuf) < 0)
|
||||||
|
goto expbuf_failed;
|
||||||
|
|
||||||
|
GST_LOG_OBJECT (allocator, "exported DMABUF as fd %i plane %d",
|
||||||
|
expbuf.fd, i);
|
||||||
|
|
||||||
|
group->mem[i] = (GstMemory *) _v4l2mem_new (0, GST_ALLOCATOR (allocator),
|
||||||
|
NULL, group->planes[i].length, 0, 0, group->planes[i].length, i,
|
||||||
|
NULL, expbuf.fd, group);
|
||||||
|
} else {
|
||||||
|
/* Take back the allocator reference */
|
||||||
|
gst_object_ref (allocator);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_assert (gst_is_v4l2_memory (group->mem[i]));
|
||||||
|
mem = (GstV4l2Memory *) group->mem[i];
|
||||||
|
|
||||||
|
if ((dmafd = dup (mem->dmafd)) < 0)
|
||||||
|
goto dup_failed;
|
||||||
|
|
||||||
|
dma_mem = gst_dmabuf_allocator_alloc (dmabuf_allocator, dmafd,
|
||||||
|
mem->mem.maxsize);
|
||||||
|
_v4l2mem_parent_to_dmabuf (mem, dma_mem);
|
||||||
|
|
||||||
|
group->mem[i] = dma_mem;
|
||||||
|
group->mems_allocated++;
|
||||||
|
}
|
||||||
|
|
||||||
|
gst_v4l2_allocator_reset_size (allocator, group);
|
||||||
|
|
||||||
|
return group;
|
||||||
|
|
||||||
|
expbuf_failed:
|
||||||
|
{
|
||||||
|
GST_ERROR_OBJECT (allocator, "Failed to export DMABUF: %s",
|
||||||
|
g_strerror (errno));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
dup_failed:
|
||||||
|
{
|
||||||
|
GST_ERROR_OBJECT (allocator, "Failed to dup DMABUF descriptor: %s",
|
||||||
|
g_strerror (errno));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
cleanup:
|
||||||
|
{
|
||||||
|
if (group->mems_allocated > 0) {
|
||||||
|
for (i = 0; i < group->n_mem; i++)
|
||||||
|
gst_memory_unref (group->mem[i]);
|
||||||
|
} else {
|
||||||
|
gst_atomic_queue_push (allocator->free_queue, group);
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
GstV4l2MemoryGroup *
|
GstV4l2MemoryGroup *
|
||||||
gst_v4l2_allocator_import_dmabuf (GstV4l2Allocator * allocator,
|
gst_v4l2_allocator_import_dmabuf (GstV4l2Allocator * allocator,
|
||||||
gint dmabuf_fd[VIDEO_MAX_PLANES])
|
gint dmabuf_fd[VIDEO_MAX_PLANES])
|
||||||
|
|
|
@ -72,6 +72,7 @@ struct _GstV4l2Memory
|
||||||
gint plane;
|
gint plane;
|
||||||
GstV4l2MemoryGroup *group;
|
GstV4l2MemoryGroup *group;
|
||||||
gpointer data;
|
gpointer data;
|
||||||
|
gint dmafd;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _GstV4l2MemoryGroup
|
struct _GstV4l2MemoryGroup
|
||||||
|
@ -122,6 +123,9 @@ gboolean gst_v4l2_allocator_stop (GstV4l2Allocator * alloc
|
||||||
|
|
||||||
GstV4l2MemoryGroup* gst_v4l2_allocator_alloc_mmap (GstV4l2Allocator * allocator);
|
GstV4l2MemoryGroup* gst_v4l2_allocator_alloc_mmap (GstV4l2Allocator * allocator);
|
||||||
|
|
||||||
|
GstV4l2MemoryGroup* gst_v4l2_allocator_alloc_dmabuf (GstV4l2Allocator * allocator,
|
||||||
|
GstAllocator * dmabuf_allocator);
|
||||||
|
|
||||||
void gst_v4l2_allocator_flush (GstV4l2Allocator * allocator);
|
void gst_v4l2_allocator_flush (GstV4l2Allocator * allocator);
|
||||||
|
|
||||||
gboolean gst_v4l2_allocator_qbuf (GstV4l2Allocator * allocator,
|
gboolean gst_v4l2_allocator_qbuf (GstV4l2Allocator * allocator,
|
||||||
|
|
|
@ -73,6 +73,9 @@ gst_v4l2_is_buffer_valid (GstBuffer * buffer, GstV4l2MemoryGroup ** group)
|
||||||
if (GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_TAG_MEMORY))
|
if (GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_TAG_MEMORY))
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
|
if (gst_is_dmabuf_memory (mem))
|
||||||
|
mem = mem->parent;
|
||||||
|
|
||||||
if (gst_is_v4l2_memory (mem)) {
|
if (gst_is_v4l2_memory (mem)) {
|
||||||
GstV4l2Memory *vmem = (GstV4l2Memory *) mem;
|
GstV4l2Memory *vmem = (GstV4l2Memory *) mem;
|
||||||
valid = TRUE;
|
valid = TRUE;
|
||||||
|
@ -108,7 +111,8 @@ gst_v4l2_buffer_pool_alloc_buffer (GstBufferPool * bpool, GstBuffer ** buffer,
|
||||||
group = gst_v4l2_allocator_alloc_mmap (pool->vallocator);
|
group = gst_v4l2_allocator_alloc_mmap (pool->vallocator);
|
||||||
break;
|
break;
|
||||||
case GST_V4L2_IO_DMABUF:
|
case GST_V4L2_IO_DMABUF:
|
||||||
/* TODO group = gst_v4l2_allocator_alloc_dmabuf (pool->vallocator); */
|
group = gst_v4l2_allocator_alloc_dmabuf (pool->vallocator,
|
||||||
|
pool->allocator);
|
||||||
break;
|
break;
|
||||||
case GST_V4L2_IO_USERPTR:
|
case GST_V4L2_IO_USERPTR:
|
||||||
default:
|
default:
|
||||||
|
@ -850,6 +854,7 @@ gst_v4l2_buffer_pool_acquire_buffer (GstBufferPool * bpool, GstBuffer ** buffer,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GST_V4L2_IO_MMAP:
|
case GST_V4L2_IO_MMAP:
|
||||||
|
case GST_V4L2_IO_DMABUF:
|
||||||
/* get a free unqueued buffer */
|
/* get a free unqueued buffer */
|
||||||
ret = GST_BUFFER_POOL_CLASS (parent_class)->acquire_buffer (bpool,
|
ret = GST_BUFFER_POOL_CLASS (parent_class)->acquire_buffer (bpool,
|
||||||
buffer, params);
|
buffer, params);
|
||||||
|
@ -929,6 +934,7 @@ gst_v4l2_buffer_pool_release_buffer (GstBufferPool * bpool, GstBuffer * buffer)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GST_V4L2_IO_MMAP:
|
case GST_V4L2_IO_MMAP:
|
||||||
|
case GST_V4L2_IO_DMABUF:
|
||||||
{
|
{
|
||||||
GstV4l2MemoryGroup *group;
|
GstV4l2MemoryGroup *group;
|
||||||
guint index;
|
guint index;
|
||||||
|
@ -1172,6 +1178,7 @@ gst_v4l2_buffer_pool_process (GstV4l2BufferPool * pool, GstBuffer * buf)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GST_V4L2_IO_MMAP:
|
case GST_V4L2_IO_MMAP:
|
||||||
|
case GST_V4L2_IO_DMABUF:
|
||||||
{
|
{
|
||||||
GstBuffer *tmp;
|
GstBuffer *tmp;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue