mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-11 09:55:36 +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 "v4l2_calls.h"
|
||||
|
||||
#include <gst/allocators/gstdmabuf.h>
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#define GST_V4L2_MEMORY_TYPE "V4l2Memory"
|
||||
|
||||
|
@ -121,7 +126,8 @@ _v4l2mem_dispose (GstV4l2Memory * mem)
|
|||
gboolean ret;
|
||||
|
||||
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);
|
||||
ret = FALSE;
|
||||
} else {
|
||||
|
@ -135,13 +141,15 @@ _v4l2mem_dispose (GstV4l2Memory * mem)
|
|||
static void
|
||||
_v4l2mem_free (GstV4l2Memory * mem)
|
||||
{
|
||||
if (mem->dmafd > 0)
|
||||
close (mem->dmafd);
|
||||
g_slice_free (GstV4l2Memory, mem);
|
||||
}
|
||||
|
||||
static inline GstV4l2Memory *
|
||||
_v4l2mem_new (GstMemoryFlags flags, GstAllocator * allocator,
|
||||
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;
|
||||
|
||||
|
@ -155,6 +163,7 @@ _v4l2mem_new (GstMemoryFlags flags, GstAllocator * allocator,
|
|||
|
||||
mem->plane = plane;
|
||||
mem->data = data;
|
||||
mem->dmafd = dmafd;
|
||||
mem->group = group;
|
||||
|
||||
return mem;
|
||||
|
@ -177,7 +186,7 @@ _v4l2mem_share (GstV4l2Memory * mem, gssize offset, gsize size)
|
|||
sub = _v4l2mem_new (GST_MINI_OBJECT_FLAGS (parent) |
|
||||
GST_MINI_OBJECT_FLAG_LOCK_READONLY, mem->mem.allocator, parent,
|
||||
mem->mem.maxsize, mem->mem.align, offset, size, mem->plane, mem->data,
|
||||
mem->group);
|
||||
-1, mem->group);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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
|
||||
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),
|
||||
NULL, group->planes[i].length, 0, 0, group->planes[i].length, i,
|
||||
data, group);
|
||||
data, -1, group);
|
||||
} else {
|
||||
/* Take back the allocator reference */
|
||||
gst_object_ref (allocator);
|
||||
|
@ -757,14 +773,90 @@ mmap_failed:
|
|||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
GstV4l2MemoryGroup *
|
||||
gst_v4l2_allocator_alloc_dmabuf (GstV4l2Allocator * allocator)
|
||||
gst_v4l2_allocator_alloc_dmabuf (GstV4l2Allocator * allocator,
|
||||
GstAllocator * dmabuf_allocator)
|
||||
{
|
||||
/* TODO */
|
||||
GstV4l2MemoryGroup *group;
|
||||
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 *
|
||||
gst_v4l2_allocator_import_dmabuf (GstV4l2Allocator * allocator,
|
||||
gint dmabuf_fd[VIDEO_MAX_PLANES])
|
||||
|
|
|
@ -72,6 +72,7 @@ struct _GstV4l2Memory
|
|||
gint plane;
|
||||
GstV4l2MemoryGroup *group;
|
||||
gpointer data;
|
||||
gint dmafd;
|
||||
};
|
||||
|
||||
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_dmabuf (GstV4l2Allocator * allocator,
|
||||
GstAllocator * dmabuf_allocator);
|
||||
|
||||
void gst_v4l2_allocator_flush (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))
|
||||
goto done;
|
||||
|
||||
if (gst_is_dmabuf_memory (mem))
|
||||
mem = mem->parent;
|
||||
|
||||
if (gst_is_v4l2_memory (mem)) {
|
||||
GstV4l2Memory *vmem = (GstV4l2Memory *) mem;
|
||||
valid = TRUE;
|
||||
|
@ -108,7 +111,8 @@ gst_v4l2_buffer_pool_alloc_buffer (GstBufferPool * bpool, GstBuffer ** buffer,
|
|||
group = gst_v4l2_allocator_alloc_mmap (pool->vallocator);
|
||||
break;
|
||||
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;
|
||||
case GST_V4L2_IO_USERPTR:
|
||||
default:
|
||||
|
@ -850,6 +854,7 @@ gst_v4l2_buffer_pool_acquire_buffer (GstBufferPool * bpool, GstBuffer ** buffer,
|
|||
break;
|
||||
|
||||
case GST_V4L2_IO_MMAP:
|
||||
case GST_V4L2_IO_DMABUF:
|
||||
/* get a free unqueued buffer */
|
||||
ret = GST_BUFFER_POOL_CLASS (parent_class)->acquire_buffer (bpool,
|
||||
buffer, params);
|
||||
|
@ -929,6 +934,7 @@ gst_v4l2_buffer_pool_release_buffer (GstBufferPool * bpool, GstBuffer * buffer)
|
|||
break;
|
||||
|
||||
case GST_V4L2_IO_MMAP:
|
||||
case GST_V4L2_IO_DMABUF:
|
||||
{
|
||||
GstV4l2MemoryGroup *group;
|
||||
guint index;
|
||||
|
@ -1172,6 +1178,7 @@ gst_v4l2_buffer_pool_process (GstV4l2BufferPool * pool, GstBuffer * buf)
|
|||
break;
|
||||
|
||||
case GST_V4L2_IO_MMAP:
|
||||
case GST_V4L2_IO_DMABUF:
|
||||
{
|
||||
GstBuffer *tmp;
|
||||
|
||||
|
|
Loading…
Reference in a new issue