diff options
author | Benjamin Gaignard <benjamin.gaignard@linaro.org> | 2013-02-19 11:47:20 +0100 |
---|---|---|
committer | Sebastian Dröge <sebastian.droege@collabora.co.uk> | 2013-02-19 12:57:07 +0100 |
commit | e29ab42922706e0c4a1bb3fc8041c9a9dac6d4f1 (patch) | |
tree | 139b1521f253a9ba7761d712335d5fc6057f587e | |
parent | 5b19be933b36d5dd9c203b0f658ca46bd946f267 (diff) |
v4l2: Add support of dmabuf
v4l has add a new IOCTL to export a buffer by using dmabuf.
This patch allow to use this new IOTCL if it has been defined in videodev2.h
I introduce a new IO mode (GST_V4L2_IO_DMABUF) to enable this way of working.
https://bugzilla.gnome.org/show_bug.cgi?id=693826
-rw-r--r-- | configure.ac | 18 | ||||
-rw-r--r-- | sys/v4l2/Makefile.am | 6 | ||||
-rw-r--r-- | sys/v4l2/gstv4l2bufferpool.c | 65 | ||||
-rw-r--r-- | sys/v4l2/gstv4l2object.c | 1 | ||||
-rw-r--r-- | sys/v4l2/gstv4l2object.h | 3 | ||||
-rw-r--r-- | sys/v4l2/gstv4l2src.c | 1 |
6 files changed, 74 insertions, 20 deletions
diff --git a/configure.ac b/configure.ac index 5b29cb965..9817ab76b 100644 --- a/configure.ac +++ b/configure.ac @@ -582,6 +582,24 @@ if test x$HAVE_GST_V4L2 = xyes; then fi fi +# Check if v4l2 support dmabuf +if test x$HAVE_GST_V4L2 = xyes; then + AC_CHECK_DECLS(V4L2_MEMORY_DMABUF,,,[ + #include <sys/types.h> + #ifdef __sun /* Solaris */ + #include <sys/types.h> + #include <sys/videodev2.h> + #elif __FreeBSD__ + #include <linux/videodev2.h> + #else /* Linux */ + #include <linux/types.h> + #define _LINUX_TIME_H + #define __user + #include <linux/videodev2.h> + #endif + ]) +fi + dnl Check for X11 translit(dnm, m, l) AM_CONDITIONAL(USE_X, true) AG_GST_CHECK_FEATURE(X, [X libraries and plugins], diff --git a/sys/v4l2/Makefile.am b/sys/v4l2/Makefile.am index 4330da6e1..6b5134fca 100644 --- a/sys/v4l2/Makefile.am +++ b/sys/v4l2/Makefile.am @@ -8,7 +8,6 @@ xv_source = xv_libs = endif - # variables used for enum/marshal generation glib_enum_headers = tuner.h tunernorm.h tunerchannel.h glib_enum_define = GST_INTERFACES @@ -56,11 +55,10 @@ libgstvideo4linux2_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) \ libgstvideo4linux2_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) libgstvideo4linux2_la_LIBTOOLFLAGS = --tag=disable-static - libgstvideo4linux2_la_LIBADD = $(GST_PLUGINS_BASE_LIBS) \ - $(GST_BASE_LIBS) \ - $(GST_PLUGINS_BASE_LIBS) \ + -lgstallocators-$(GST_API_VERSION) \ -lgstvideo-$(GST_API_VERSION) \ + $(GST_BASE_LIBS) \ $(GST_LIBS) \ $(xv_libs) \ $(LIBV4L2_LIBS) \ diff --git a/sys/v4l2/gstv4l2bufferpool.c b/sys/v4l2/gstv4l2bufferpool.c index 0a9481862..6208d1385 100644 --- a/sys/v4l2/gstv4l2bufferpool.c +++ b/sys/v4l2/gstv4l2bufferpool.c @@ -29,10 +29,14 @@ #include <sys/mman.h> #include <string.h> #include <unistd.h> +#if HAVE_DECL_V4L2_MEMORY_DMABUF +#include <fcntl.h> +#endif #include "gst/video/video.h" #include "gst/video/gstvideometa.h" #include "gst/video/gstvideopool.h" +#include "gst/allocators/gstdmabuf.h" #include <gstv4l2bufferpool.h> @@ -104,6 +108,7 @@ gst_v4l2_buffer_pool_free_buffer (GstBufferPool * bpool, GstBuffer * buffer) switch (obj->mode) { case GST_V4L2_IO_RW: + case GST_V4L2_IO_DMABUF: break; case GST_V4L2_IO_MMAP: { @@ -152,6 +157,7 @@ gst_v4l2_buffer_pool_alloc_buffer (GstBufferPool * bpool, GstBuffer ** buffer, break; } case GST_V4L2_IO_MMAP: + case GST_V4L2_IO_DMABUF: { newbuf = gst_buffer_new (); meta = GST_V4L2_META_ADD (newbuf); @@ -175,19 +181,35 @@ gst_v4l2_buffer_pool_alloc_buffer (GstBufferPool * bpool, GstBuffer ** buffer, GST_LOG_OBJECT (pool, " memory: %d", meta->vbuffer.memory); if (meta->vbuffer.memory == V4L2_MEMORY_MMAP) GST_LOG_OBJECT (pool, " MMAP offset: %u", meta->vbuffer.m.offset); - GST_LOG_OBJECT (pool, " length: %u", meta->vbuffer.length); - - meta->mem = v4l2_mmap (0, meta->vbuffer.length, - PROT_READ | PROT_WRITE, MAP_SHARED, pool->video_fd, - meta->vbuffer.m.offset); - if (meta->mem == MAP_FAILED) - goto mmap_failed; - - gst_buffer_append_memory (newbuf, - gst_memory_new_wrapped (GST_MEMORY_FLAG_NO_SHARE, - meta->mem, meta->vbuffer.length, 0, meta->vbuffer.length, NULL, - NULL)); + if (obj->mode == GST_V4L2_IO_MMAP) { + meta->mem = v4l2_mmap (0, meta->vbuffer.length, + PROT_READ | PROT_WRITE, MAP_SHARED, pool->video_fd, + meta->vbuffer.m.offset); + if (meta->mem == MAP_FAILED) + goto mmap_failed; + + gst_buffer_append_memory (newbuf, + gst_memory_new_wrapped (GST_MEMORY_FLAG_NO_SHARE, + meta->mem, meta->vbuffer.length, 0, meta->vbuffer.length, NULL, + NULL)); + } +#if HAVE_DECL_V4L2_MEMORY_DMABUF + if (obj->mode == GST_V4L2_IO_DMABUF) { + struct v4l2_exportbuffer expbuf; + + expbuf.type = meta->vbuffer.type; + expbuf.index = meta->vbuffer.index; + expbuf.flags = O_CLOEXEC; + if (v4l2_ioctl (pool->video_fd, VIDIOC_EXPBUF, &expbuf) < 0) + goto mmap_failed; + + meta->vbuffer.memory = V4L2_MEMORY_DMABUF; + gst_buffer_append_memory (newbuf, + gst_dmabuf_allocator_alloc (pool->allocator, expbuf.fd, + meta->vbuffer.length)); + } +#endif /* add metadata to raw video buffers */ if (pool->add_videometa && info->finfo) { const GstVideoFormatInfo *finfo = info->finfo; @@ -298,6 +320,7 @@ gst_v4l2_buffer_pool_set_config (GstBufferPool * bpool, GstStructure * config) num_buffers = 1; copy_threshold = 0; break; + case GST_V4L2_IO_DMABUF: case GST_V4L2_IO_MMAP: { /* request a reasonable number of buffers when no max specified. We will @@ -357,6 +380,10 @@ gst_v4l2_buffer_pool_set_config (GstBufferPool * bpool, GstStructure * config) pool->size = size; pool->num_buffers = num_buffers; pool->copy_threshold = copy_threshold; + + if (obj->mode == GST_V4L2_IO_DMABUF) + allocator = gst_dmabuf_allocator_obtain (); + if (pool->allocator) gst_object_unref (pool->allocator); if ((pool->allocator = allocator)) @@ -406,6 +433,7 @@ start_streaming (GstV4l2BufferPool * pool) break; case GST_V4L2_IO_MMAP: case GST_V4L2_IO_USERPTR: + case GST_V4L2_IO_DMABUF: GST_DEBUG_OBJECT (pool, "STREAMON"); if (v4l2_ioctl (pool->video_fd, VIDIOC_STREAMON, &obj->type) < 0) goto start_failed; @@ -478,6 +506,7 @@ gst_v4l2_buffer_pool_stop (GstBufferPool * bpool) break; case GST_V4L2_IO_MMAP: case GST_V4L2_IO_USERPTR: + case GST_V4L2_IO_DMABUF: /* we actually need to sync on all queued buffers but not * on the non-queued ones */ GST_DEBUG_OBJECT (pool, "STREAMOFF"); @@ -614,7 +643,12 @@ gst_v4l2_buffer_pool_dqbuf (GstV4l2BufferPool * pool, GstBuffer ** buffer) memset (&vbuffer, 0x00, sizeof (vbuffer)); vbuffer.type = obj->type; - vbuffer.memory = V4L2_MEMORY_MMAP; +#if HAVE_DECL_V4L2_MEMORY_DMABUF + if (obj->mode == GST_V4L2_IO_DMABUF) + vbuffer.memory = V4L2_MEMORY_DMABUF; + else +#endif + vbuffer.memory = V4L2_MEMORY_MMAP; GST_LOG_OBJECT (pool, "doing DQBUF"); if (v4l2_ioctl (pool->video_fd, VIDIOC_DQBUF, &vbuffer) < 0) @@ -743,7 +777,7 @@ gst_v4l2_buffer_pool_acquire_buffer (GstBufferPool * bpool, GstBuffer ** buffer, ret = GST_BUFFER_POOL_CLASS (parent_class)->acquire_buffer (bpool, buffer, params); break; - + case GST_V4L2_IO_DMABUF: case GST_V4L2_IO_MMAP: /* just dequeue a buffer, we basically use the queue of v4l2 as the * storage for our buffers. This function does poll first so we can @@ -831,6 +865,7 @@ gst_v4l2_buffer_pool_release_buffer (GstBufferPool * bpool, GstBuffer * buffer) GST_BUFFER_POOL_CLASS (parent_class)->release_buffer (bpool, buffer); break; + case GST_V4L2_IO_DMABUF: case GST_V4L2_IO_MMAP: /* queue back in the device */ gst_v4l2_buffer_pool_qbuf (pool, buffer); @@ -1083,7 +1118,7 @@ gst_v4l2_buffer_pool_process (GstV4l2BufferPool * pool, GstBuffer * buf) /* FIXME, do write() */ GST_WARNING_OBJECT (pool, "implement write()"); break; - + case GST_V4L2_IO_DMABUF: case GST_V4L2_IO_MMAP: { GstBuffer *to_queue; diff --git a/sys/v4l2/gstv4l2object.c b/sys/v4l2/gstv4l2object.c index ec61b2c75..81654e20a 100644 --- a/sys/v4l2/gstv4l2object.c +++ b/sys/v4l2/gstv4l2object.c @@ -389,6 +389,7 @@ gst_v4l2_io_mode_get_type (void) {GST_V4L2_IO_RW, "GST_V4L2_IO_RW", "rw"}, {GST_V4L2_IO_MMAP, "GST_V4L2_IO_MMAP", "mmap"}, {GST_V4L2_IO_USERPTR, "GST_V4L2_IO_USERPTR", "userptr"}, + {GST_V4L2_IO_DMABUF, "GST_V4L2_IO_DMABUF", "dmabuf"}, {0, NULL, NULL} }; diff --git a/sys/v4l2/gstv4l2object.h b/sys/v4l2/gstv4l2object.h index 361181a48..54703e95c 100644 --- a/sys/v4l2/gstv4l2object.h +++ b/sys/v4l2/gstv4l2object.h @@ -75,7 +75,8 @@ typedef enum { GST_V4L2_IO_AUTO = 0, GST_V4L2_IO_RW = 1, GST_V4L2_IO_MMAP = 2, - GST_V4L2_IO_USERPTR = 3 + GST_V4L2_IO_USERPTR = 3, + GST_V4L2_IO_DMABUF = 4 } GstV4l2IOMode; typedef gboolean (*GstV4l2GetInOutFunction) (GstV4l2Object * v4l2object, gint * input); diff --git a/sys/v4l2/gstv4l2src.c b/sys/v4l2/gstv4l2src.c index 807ffea84..caa9f84bf 100644 --- a/sys/v4l2/gstv4l2src.c +++ b/sys/v4l2/gstv4l2src.c @@ -571,6 +571,7 @@ gst_v4l2src_decide_allocation (GstBaseSrc * bsrc, GstQuery * query) break; case GST_V4L2_IO_MMAP: case GST_V4L2_IO_USERPTR: + case GST_V4L2_IO_DMABUF: /* in streaming mode, prefer our own pool */ pool = GST_BUFFER_POOL_CAST (obj->pool); size = obj->sizeimage; |