From patchwork Tue Feb 19 13:48:41 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Benjamin Gaignard X-Patchwork-Id: 14986 Return-Path: X-Original-To: patchwork@peony.canonical.com Delivered-To: patchwork@peony.canonical.com Received: from fiordland.canonical.com (fiordland.canonical.com [91.189.94.145]) by peony.canonical.com (Postfix) with ESMTP id 4303723FD3 for ; Tue, 19 Feb 2013 13:49:18 +0000 (UTC) Received: from mail-ve0-f171.google.com (mail-ve0-f171.google.com [209.85.128.171]) by fiordland.canonical.com (Postfix) with ESMTP id DB658A18F7A for ; Tue, 19 Feb 2013 13:49:17 +0000 (UTC) Received: by mail-ve0-f171.google.com with SMTP id b10so5803849vea.2 for ; Tue, 19 Feb 2013 05:49:17 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=x-received:x-forwarded-to:x-forwarded-for:delivered-to:x-received :received-spf:x-received:from:to:cc:subject:date:message-id:x-mailer :x-gm-message-state; bh=QEr93xPcGJ+vHITnlen5mMgx9rd1osrEnsvye1q7JJE=; b=NFGzkzer/cspmKdD4E27oZV7Jtq4ccj9jptesiRWGvzhXGCknv3PlwcvViCKM5NPLb hxaqoTQgekJC9D+qM5zAbcAenHrzyj/fAnw/nI2BK57fbO+jspOg5Cu2aL9jeH6HmlR8 NtYunI/UuQBMyjmXQW0lbpQKKiR/7b8l9OkVsI0Ppcnr6OUeFB0QsgYuWhgo7regDF9W n5X65KsevEDDXUcjzuhZGVXDr1ptLaI4JfFv8CyTqo/ecJQkD7CtZHS/1adaoMZd+183 Ph+SYGyFUi+DD0i6iN2GmigQUdXKpcODNQPMxBPUR6txqc1OYwWI+E0iHiGVo0A8gEuv xb/Q== X-Received: by 10.58.247.132 with SMTP id ye4mr21338920vec.9.1361281757330; Tue, 19 Feb 2013 05:49:17 -0800 (PST) X-Forwarded-To: linaro-patchwork@canonical.com X-Forwarded-For: patch@linaro.org linaro-patchwork@canonical.com Delivered-To: patches@linaro.org Received: by 10.58.145.101 with SMTP id st5csp142529veb; Tue, 19 Feb 2013 05:49:11 -0800 (PST) X-Received: by 10.194.109.41 with SMTP id hp9mr26330692wjb.32.1361281750892; Tue, 19 Feb 2013 05:49:10 -0800 (PST) Received: from mail-wi0-x22a.google.com ([2a00:1450:400c:c05::22a]) by mx.google.com with ESMTPS id p6si23471077wja.9.2013.02.19.05.49.10 (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Tue, 19 Feb 2013 05:49:10 -0800 (PST) Received-SPF: neutral (google.com: 2a00:1450:400c:c05::22a is neither permitted nor denied by best guess record for domain of benjamin.gaignard@linaro.org) client-ip=2a00:1450:400c:c05::22a; Authentication-Results: mx.google.com; spf=neutral (google.com: 2a00:1450:400c:c05::22a is neither permitted nor denied by best guess record for domain of benjamin.gaignard@linaro.org) smtp.mail=benjamin.gaignard@linaro.org Received: by mail-wi0-f170.google.com with SMTP id hm11so5011931wib.5 for ; Tue, 19 Feb 2013 05:49:10 -0800 (PST) X-Received: by 10.180.80.74 with SMTP id p10mr25586720wix.19.1361281748627; Tue, 19 Feb 2013 05:49:08 -0800 (PST) Received: from localhost.localdomain (LPuteaux-156-14-44-212.w82-127.abo.wanadoo.fr. [82.127.83.212]) by mx.google.com with ESMTPS id ex1sm27905437wib.7.2013.02.19.05.49.07 (version=TLSv1 cipher=RC4-SHA bits=128/128); Tue, 19 Feb 2013 05:49:08 -0800 (PST) From: benjamin.gaignard@linaro.org To: patches@linaro.org Cc: Benjamin Gaignard Subject: [PATCH] [v4l2src] add support of dmabuf Date: Tue, 19 Feb 2013 14:48:41 +0100 Message-Id: <1361281721-23468-1-git-send-email-benjamin.gaignard@linaro.org> X-Mailer: git-send-email 1.7.10 X-Gm-Message-State: ALoCoQmVGtZCv/wD0PdUM5EDD+QepVn/d4sUXs1hDbkPLRvz1RZNwtfVCKZNnfN6r3OAxQkS7R18 From: Benjamin Gaignard 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. Signed-off-by: Benjamin Gaignard --- configure.ac | 18 ++++++++++++ sys/v4l2/Makefile.am | 4 +-- sys/v4l2/gstv4l2bufferpool.c | 65 ++++++++++++++++++++++++++++++++---------- sys/v4l2/gstv4l2object.c | 1 + sys/v4l2/gstv4l2object.h | 3 +- sys/v4l2/gstv4l2src.c | 1 + 6 files changed, 74 insertions(+), 18 deletions(-) diff --git a/configure.ac b/configure.ac index 4b6ceda..14d336b 100644 --- a/configure.ac +++ b/configure.ac @@ -579,6 +579,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 + #ifdef __sun /* Solaris */ + #include + #include + #elif __FreeBSD__ + #include + #else /* Linux */ + #include + #define _LINUX_TIME_H + #define __user + #include + #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 29a32ba..299bb3c 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 @@ -64,7 +63,8 @@ libgstvideo4linux2_la_LIBADD = $(GST_PLUGINS_BASE_LIBS) \ $(GST_LIBS) \ $(xv_libs) \ $(LIBV4L2_LIBS) \ - $(GUDEV_LIBS) + $(GUDEV_LIBS) \ + -lgstallocators-$(GST_API_VERSION) noinst_HEADERS = \ gstv4l2bufferpool.h \ diff --git a/sys/v4l2/gstv4l2bufferpool.c b/sys/v4l2/gstv4l2bufferpool.c index f6fabbb..91f395c 100644 --- a/sys/v4l2/gstv4l2bufferpool.c +++ b/sys/v4l2/gstv4l2bufferpool.c @@ -29,10 +29,14 @@ #include #include #include +#if HAVE_DECL_V4L2_MEMORY_DMABUF +#include +#endif #include "gst/video/video.h" #include "gst/video/gstvideometa.h" #include "gst/video/gstvideopool.h" +#include "gst/allocators/gstdmabuf.h" #include @@ -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; @@ -296,6 +318,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 @@ -355,6 +378,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)) @@ -404,6 +431,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; @@ -476,6 +504,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"); @@ -612,7 +641,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) @@ -741,7 +775,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 @@ -829,6 +863,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); @@ -1081,7 +1116,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 8556dcd..052347e 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 9b3c5d2..2cc7cd2 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 ce92d36..54a3d10 100644 --- a/sys/v4l2/gstv4l2src.c +++ b/sys/v4l2/gstv4l2src.c @@ -572,6 +572,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;