diff options
author | Laurent Pinchart <laurent.pinchart@ideasonboard.com> | 2018-05-22 11:43:37 +0300 |
---|---|---|
committer | Laurent Pinchart <laurent.pinchart@ideasonboard.com> | 2018-05-22 11:43:37 +0300 |
commit | ab0c87921e03742df93e94a800fe0fcf80e5047b (patch) | |
tree | 52a73ed00ac90163196ecc6822cfe2a89d1c61a7 /v4l2.c | |
parent | 117cd47e08db4e31d2f966cb4b22987d3e5d6bb7 (diff) |
v4l2: Replace USERPTR support with DMABUF support
V4L2_MEMORY_USERPTR is deprecated, replace it with V4L2_MEMORY_DMABUF
support for buffer sharing. Two new functions are added,
v4l2_export_buffers() to export previously allocated buffers as dmabuf
objects, and v4l2_import_buffers() to import dmabuf objects as backing
store for V4L2 buffers.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Diffstat (limited to 'v4l2.c')
-rw-r--r-- | v4l2.c | 111 |
1 files changed, 98 insertions, 13 deletions
@@ -512,7 +512,7 @@ int v4l2_alloc_buffers(struct v4l2_device *dev, enum v4l2_memory memtype, if (dev->nbufs != 0) return -EBUSY; - if (memtype != V4L2_MEMORY_MMAP && memtype != V4L2_MEMORY_USERPTR) + if (memtype != V4L2_MEMORY_MMAP && memtype != V4L2_MEMORY_DMABUF) return -EINVAL; /* Request the buffers from the driver. */ @@ -550,8 +550,10 @@ int v4l2_alloc_buffers(struct v4l2_device *dev, enum v4l2_memory memtype, memset(dev->buffers, 0, sizeof *dev->buffers * nbufs); - for (i = 0; i < dev->nbufs; ++i) + for (i = 0; i < dev->nbufs; ++i) { dev->buffers[i].index = i; + dev->buffers[i].dmabuf = -1; + } ret = 0; @@ -571,13 +573,10 @@ int v4l2_free_buffers(struct v4l2_device *dev) if (dev->nbufs == 0) return 0; - if (dev->memtype == V4L2_MEMORY_MMAP) { - for (i = 0; i < dev->nbufs; ++i) { - struct v4l2_video_buffer *buffer = &dev->buffers[i]; - - if (buffer->mem == NULL) - continue; + for (i = 0; i < dev->nbufs; ++i) { + struct v4l2_video_buffer *buffer = &dev->buffers[i]; + if (buffer->mem) { ret = munmap(buffer->mem, buffer->size); if (ret < 0) { printf("%s: unable to unmap buffer %u (%d)\n", @@ -586,8 +585,14 @@ int v4l2_free_buffers(struct v4l2_device *dev) } buffer->mem = NULL; - buffer->size = 0; } + + if (buffer->dmabuf != -1) { + close(buffer->dmabuf); + buffer->dmabuf = -1; + } + + buffer->size = 0; } memset(&rb, 0, sizeof rb); @@ -609,6 +614,88 @@ int v4l2_free_buffers(struct v4l2_device *dev) return 0; } +int v4l2_export_buffers(struct v4l2_device *dev) +{ + unsigned int i; + int ret; + + if (dev->nbufs == 0) + return -EINVAL; + + if (dev->memtype != V4L2_MEMORY_MMAP) + return -EINVAL; + + for (i = 0; i < dev->nbufs; ++i) { + struct v4l2_exportbuffer expbuf = { + .type = dev->type, + .index = i, + }; + + ret = ioctl(dev->fd, VIDIOC_EXPBUF, &expbuf); + if (ret < 0) { + printf("Failed to export buffer %u.\n", i); + return ret; + } + + dev->buffers[i].dmabuf = expbuf.fd; + + printf("%s: buffer %u exported with fd %u.\n", + dev->name, i, dev->buffers[i].dmabuf); + } + + return 0; +} + +int v4l2_import_buffers(struct v4l2_device *dev, unsigned int nbufs, + const struct v4l2_video_buffer *buffers) +{ + unsigned int i; + int ret; + + if (dev->nbufs == 0 || dev->nbufs > nbufs) + return -EINVAL; + + if (dev->memtype != V4L2_MEMORY_DMABUF) + return -EINVAL; + + for (i = 0; i < dev->nbufs; ++i) { + const struct v4l2_video_buffer *buffer = &buffers[i]; + struct v4l2_buffer buf = { + .index = i, + .type = dev->type, + .memory = dev->memtype, + }; + int fd; + + ret = ioctl(dev->fd, VIDIOC_QUERYBUF, &buf); + if (ret < 0) { + printf("%s: unable to query buffer %u (%d).\n", + dev->name, i, errno); + return -errno; + } + + if (buffer->size < buf.length) { + printf("%s: buffer %u too small (%u bytes required, %u bytes available.\n", + dev->name, i, buf.length, buffer->size); + return -EINVAL; + } + + fd = dup(buffer->dmabuf); + if (fd < 0) { + printf("%s: failed to duplicate dmabuf fd %d.\n", + dev->name, buffer->dmabuf); + return ret; + } + + printf("%s: buffer %u valid.\n", dev->name, i); + + dev->buffers[i].dmabuf = fd; + dev->buffers[i].size = buffer->size; + } + + return 0; +} + int v4l2_mmap_buffers(struct v4l2_device *dev) { unsigned int i; @@ -688,10 +775,8 @@ int v4l2_queue_buffer(struct v4l2_device *dev, struct v4l2_video_buffer *buffer) buf.type = dev->type; buf.memory = dev->memtype; - if (dev->memtype == V4L2_MEMORY_USERPTR) - buf.m.userptr = (unsigned long)dev->buffers[buffer->index].mem; - - buf.length = dev->buffers[buffer->index].size; + if (dev->memtype == V4L2_MEMORY_DMABUF) + buf.m.fd = (unsigned long)dev->buffers[buffer->index].dmabuf; if (dev->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) buf.bytesused = buffer->bytesused; |