summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLaurent Pinchart <laurent.pinchart@ideasonboard.com>2018-06-09 12:11:25 +0300
committerLaurent Pinchart <laurent.pinchart@ideasonboard.com>2018-06-09 12:20:02 +0300
commitdf651c5b397a4b6648695cdf725a8243ff512dcd (patch)
treea8f88286cedafe8c8d35cbaa38698063a2e64961
parent6dc91f22f9bb2aafeee2f7c5df53a02a37acc3a0 (diff)
v4l2: Extract video buffer structure to separate file
The v4l2_video_buffer structure describes a video buffer. It is used by the v4l2_device class only, but isn't otherwise tied to V4L2. To prepare for non-V4L2 video sources, extract it to a separate file and rename it to video_buffer. At the same time, add a new video_buffer_set structure to represent as set of video buffers. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
-rw-r--r--Makefile3
-rw-r--r--stream.c10
-rw-r--r--v4l2.c71
-rw-r--r--v4l2.h49
-rw-r--r--video-buffers.c40
-rw-r--r--video-buffers.h48
6 files changed, 141 insertions, 80 deletions
diff --git a/Makefile b/Makefile
index 3785140..484f533 100644
--- a/Makefile
+++ b/Makefile
@@ -13,7 +13,8 @@ OBJS := \
main.o \
stream.o \
uvc.o \
- v4l2.o
+ v4l2.o \
+ video-buffers.o
all: uvc-gadget
diff --git a/stream.c b/stream.c
index 13b8493..e08aca7 100644
--- a/stream.c
+++ b/stream.c
@@ -47,7 +47,7 @@ struct uvc_stream
static void capture_video_process(void *d)
{
struct uvc_stream *stream = d;
- struct v4l2_video_buffer buf;
+ struct video_buffer buf;
int ret;
ret = v4l2_dequeue_buffer(stream->cap, &buf);
@@ -60,7 +60,7 @@ static void capture_video_process(void *d)
static void uvc_video_process(void *d)
{
struct uvc_stream *stream = d;
- struct v4l2_video_buffer buf;
+ struct video_buffer buf;
int ret;
ret = v4l2_dequeue_buffer(stream->uvc->vdev, &buf);
@@ -92,7 +92,7 @@ static int uvc_video_enable(struct uvc_stream *stream, int enable)
return ret;
}
- ret = v4l2_import_buffers(dev->vdev, dev->vdev->nbufs, cap->buffers);
+ ret = v4l2_import_buffers(dev->vdev, &cap->buffers);
if (ret < 0) {
printf("Failed to import buffers: %s (%d)\n", strerror(-ret), -ret);
goto error;
@@ -137,8 +137,8 @@ static int capture_video_stream(struct uvc_stream *stream, int enable)
goto error;
}
- for (i = 0; i < cap->nbufs; ++i) {
- struct v4l2_video_buffer *buf = &cap->buffers[i];
+ for (i = 0; i < cap->buffers.nbufs; ++i) {
+ struct video_buffer *buf = &cap->buffers.buffers[i];
ret = v4l2_queue_buffer(cap, buf);
if (ret < 0)
diff --git a/v4l2.c b/v4l2.c
index 6b1c753..9030270 100644
--- a/v4l2.c
+++ b/v4l2.c
@@ -30,6 +30,7 @@
#include "list.h"
#include "tools.h"
#include "v4l2.h"
+#include "video-buffers.h"
#ifndef V4L2_BUF_FLAG_ERROR
#define V4L2_BUF_FLAG_ERROR 0x0040
@@ -510,7 +511,7 @@ int v4l2_alloc_buffers(struct v4l2_device *dev, enum v4l2_memory memtype,
unsigned int i;
int ret;
- if (dev->nbufs != 0)
+ if (dev->buffers.nbufs != 0)
return -EBUSY;
if (memtype != V4L2_MEMORY_MMAP && memtype != V4L2_MEMORY_DMABUF)
@@ -541,19 +542,17 @@ int v4l2_alloc_buffers(struct v4l2_device *dev, enum v4l2_memory memtype,
/* Allocate the buffer objects. */
dev->memtype = memtype;
- dev->nbufs = rb.count;
+ dev->buffers.nbufs = rb.count;
- dev->buffers = malloc(sizeof *dev->buffers * nbufs);
- if (dev->buffers == NULL) {
+ dev->buffers.buffers = calloc(nbufs, sizeof *dev->buffers.buffers);
+ if (dev->buffers.buffers == NULL) {
ret = -ENOMEM;
goto done;
}
- memset(dev->buffers, 0, sizeof *dev->buffers * nbufs);
-
- for (i = 0; i < dev->nbufs; ++i) {
- dev->buffers[i].index = i;
- dev->buffers[i].dmabuf = -1;
+ for (i = 0; i < dev->buffers.nbufs; ++i) {
+ dev->buffers.buffers[i].index = i;
+ dev->buffers.buffers[i].dmabuf = -1;
}
ret = 0;
@@ -571,11 +570,11 @@ int v4l2_free_buffers(struct v4l2_device *dev)
unsigned int i;
int ret;
- if (dev->nbufs == 0)
+ if (dev->buffers.nbufs == 0)
return 0;
- for (i = 0; i < dev->nbufs; ++i) {
- struct v4l2_video_buffer *buffer = &dev->buffers[i];
+ for (i = 0; i < dev->buffers.nbufs; ++i) {
+ struct video_buffer *buffer = &dev->buffers.buffers[i];
if (buffer->mem) {
ret = munmap(buffer->mem, buffer->size);
@@ -608,9 +607,9 @@ int v4l2_free_buffers(struct v4l2_device *dev)
return -errno;
}
- free(dev->buffers);
- dev->buffers = NULL;
- dev->nbufs = 0;
+ free(dev->buffers.buffers);
+ dev->buffers.buffers = NULL;
+ dev->buffers.nbufs = 0;
return 0;
}
@@ -620,13 +619,13 @@ int v4l2_export_buffers(struct v4l2_device *dev)
unsigned int i;
int ret;
- if (dev->nbufs == 0)
+ if (dev->buffers.nbufs == 0)
return -EINVAL;
if (dev->memtype != V4L2_MEMORY_MMAP)
return -EINVAL;
- for (i = 0; i < dev->nbufs; ++i) {
+ for (i = 0; i < dev->buffers.nbufs; ++i) {
struct v4l2_exportbuffer expbuf = {
.type = dev->type,
.index = i,
@@ -650,30 +649,30 @@ int v4l2_export_buffers(struct v4l2_device *dev)
return -errno;
}
- dev->buffers[i].size = buf.length;
- dev->buffers[i].dmabuf = expbuf.fd;
+ dev->buffers.buffers[i].size = buf.length;
+ dev->buffers.buffers[i].dmabuf = expbuf.fd;
printf("%s: buffer %u exported with fd %u.\n",
- dev->name, i, dev->buffers[i].dmabuf);
+ dev->name, i, dev->buffers.buffers[i].dmabuf);
}
return 0;
}
-int v4l2_import_buffers(struct v4l2_device *dev, unsigned int nbufs,
- const struct v4l2_video_buffer *buffers)
+int v4l2_import_buffers(struct v4l2_device *dev,
+ const struct video_buffer_set *buffers)
{
unsigned int i;
int ret;
- if (dev->nbufs == 0 || dev->nbufs > nbufs)
+ if (dev->buffers.nbufs == 0 || dev->buffers.nbufs > buffers->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];
+ for (i = 0; i < dev->buffers.nbufs; ++i) {
+ const struct video_buffer *buffer = &buffers->buffers[i];
struct v4l2_buffer buf = {
.index = i,
.type = dev->type,
@@ -703,8 +702,8 @@ int v4l2_import_buffers(struct v4l2_device *dev, unsigned int nbufs,
printf("%s: buffer %u valid.\n", dev->name, i);
- dev->buffers[i].dmabuf = fd;
- dev->buffers[i].size = buffer->size;
+ dev->buffers.buffers[i].dmabuf = fd;
+ dev->buffers.buffers[i].size = buffer->size;
}
return 0;
@@ -718,8 +717,8 @@ int v4l2_mmap_buffers(struct v4l2_device *dev)
if (dev->memtype != V4L2_MEMORY_MMAP)
return -EINVAL;
- for (i = 0; i < dev->nbufs; ++i) {
- struct v4l2_video_buffer *buffer = &dev->buffers[i];
+ for (i = 0; i < dev->buffers.nbufs; ++i) {
+ struct video_buffer *buffer = &dev->buffers.buffers[i];
struct v4l2_buffer buf = {
.index = i,
.type = dev->type,
@@ -752,7 +751,7 @@ int v4l2_mmap_buffers(struct v4l2_device *dev)
return 0;
}
-int v4l2_dequeue_buffer(struct v4l2_device *dev, struct v4l2_video_buffer *buffer)
+int v4l2_dequeue_buffer(struct v4l2_device *dev, struct video_buffer *buffer)
{
struct v4l2_buffer buf;
int ret;
@@ -764,11 +763,11 @@ int v4l2_dequeue_buffer(struct v4l2_device *dev, struct v4l2_video_buffer *buffe
ret = ioctl(dev->fd, VIDIOC_DQBUF, &buf);
if (ret < 0) {
printf("%s: unable to dequeue buffer index %u/%u (%d)\n",
- dev->name, buf.index, dev->nbufs, errno);
+ dev->name, buf.index, dev->buffers.nbufs, errno);
return -errno;
}
- *buffer = dev->buffers[buf.index];
+ buffer->index = buf.index;
buffer->bytesused = buf.bytesused;
buffer->timestamp = buf.timestamp;
buffer->error = !!(buf.flags & V4L2_BUF_FLAG_ERROR);
@@ -776,12 +775,12 @@ int v4l2_dequeue_buffer(struct v4l2_device *dev, struct v4l2_video_buffer *buffe
return 0;
}
-int v4l2_queue_buffer(struct v4l2_device *dev, struct v4l2_video_buffer *buffer)
+int v4l2_queue_buffer(struct v4l2_device *dev, struct video_buffer *buffer)
{
struct v4l2_buffer buf;
int ret;
- if (buffer->index >= dev->nbufs)
+ if (buffer->index >= dev->buffers.nbufs)
return -EINVAL;
memset(&buf, 0, sizeof buf);
@@ -790,7 +789,7 @@ int v4l2_queue_buffer(struct v4l2_device *dev, struct v4l2_video_buffer *buffer)
buf.memory = dev->memtype;
if (dev->memtype == V4L2_MEMORY_DMABUF)
- buf.m.fd = (unsigned long)dev->buffers[buffer->index].dmabuf;
+ buf.m.fd = (unsigned long)dev->buffers.buffers[buffer->index].dmabuf;
if (dev->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
buf.bytesused = buffer->bytesused;
@@ -798,7 +797,7 @@ int v4l2_queue_buffer(struct v4l2_device *dev, struct v4l2_video_buffer *buffer)
ret = ioctl(dev->fd, VIDIOC_QBUF, &buf);
if (ret < 0) {
printf("%s: unable to queue buffer index %u/%u (%d)\n",
- dev->name, buf.index, dev->nbufs, errno);
+ dev->name, buf.index, dev->buffers.nbufs, errno);
return -errno;
}
diff --git a/v4l2.h b/v4l2.h
index f9da5aa..8d7b3c5 100644
--- a/v4l2.h
+++ b/v4l2.h
@@ -14,36 +14,11 @@
#ifndef __V4L2_H
#define __V4L2_H
-#include <stdbool.h>
-
#include <linux/videodev2.h>
-
-#include <sys/time.h>
+#include <stdint.h>
#include "list.h"
-
-/*
- * struct v4l2_video_buffer - Video buffer information
- * @index: Zero-based buffer index, limited to the number of buffers minus one
- * @size: Size of the video memory, in bytes
- * @bytesused: Number of bytes used by video data, smaller or equal to @size
- * @timestamp: Time stamp at which the buffer has been captured
- * @error: True if an error occured while capturing video data for the buffer
- * @allocated: True if memory for the buffer has been allocated
- * @mem: Video data memory
- * @dmabuf: Video data dmabuf handle
- */
-struct v4l2_video_buffer
-{
- unsigned int index;
- unsigned int size;
- unsigned int bytesused;
- struct timeval timestamp;
- bool error;
- bool allocated;
- void *mem;
- int dmabuf;
-};
+#include "video-buffers.h"
struct v4l2_device
{
@@ -57,8 +32,7 @@ struct v4l2_device
struct v4l2_pix_format format;
struct v4l2_rect crop;
- unsigned int nbufs;
- struct v4l2_video_buffer *buffers;
+ struct video_buffer_set buffers;
};
/*
@@ -144,7 +118,7 @@ int v4l2_set_crop(struct v4l2_device *dev, struct v4l2_rect *rect);
*
* Request the driver to allocate @nbufs buffers. The driver can modify the
* number of buffers depending on its needs. The number of allocated buffers
- * will be stored in the @dev::nbufs field.
+ * will be stored in the @dev->buffers.nbufs field.
*
* When @memtype is set to V4L2_MEMORY_MMAP the buffers are allocated by the
* driver. They can then be mapped to userspace by calling v4l2_mmap_buffers().
@@ -166,7 +140,7 @@ int v4l2_alloc_buffers(struct v4l2_device *dev, enum v4l2_memory memtype,
* objects are freed, and the caller is responsible for freeing the video frames
* memory if required.
*
- * When successful this function sets the @dev::nbufs field to zero.
+ * When successful this function sets the @dev->buffers.nbufs field to zero.
*
* Return 0 on success or a negative error code on failure.
*/
@@ -194,14 +168,13 @@ int v4l2_export_buffers(struct v4l2_device *dev);
/*
* v4l2_import_buffers - Import buffer backing store as dmabuf objects
* @dev: Device instance
- * @nbufs: Number of buffers in the @buffers array
* @buffers: Buffers to be imported
*
* Import the dmabuf objects from @buffers as backing store for the device
* buffers previously allocated by v4l2_alloc_buffers().
*
* The dmabuf file handles are duplicated and stored in the dmabuf field of the
- * @dev::buffers array. The handles from the @buffers array can thus be closed
+ * @dev::buffers array. The handles from the @buffers set can thus be closed
* independently without impacting usage of the imported dmabuf objects. The
* duplicated file handles will be automatically closed when the buffers are
* freed with v4l2_free_buffers().
@@ -209,12 +182,12 @@ int v4l2_export_buffers(struct v4l2_device *dev);
* This function can only be called when buffers have been allocated with the
* memory type set to V4L2_MEMORY_DMABUF. If the memory type is different, if no
* buffers have been allocated, or if the number of allocated buffers is larger
- * than @nbufs, it will return -EINVAL.
+ * than @buffers->nbufs, it will return -EINVAL.
*
* Return 0 on success or a negative error code on failure.
*/
-int v4l2_import_buffers(struct v4l2_device *dev, unsigned int nbufs,
- const struct v4l2_video_buffer *buffers);
+int v4l2_import_buffers(struct v4l2_device *dev,
+ const struct video_buffer_set *buffers);
/*
* v4l2_mmap_buffers - Map buffers to application memory space
@@ -263,7 +236,7 @@ int v4l2_mmap_buffers(struct v4l2_device *dev);
*
* Return 0 on success or a negative error code on failure.
*/
-int v4l2_queue_buffer(struct v4l2_device *dev, struct v4l2_video_buffer *buffer);
+int v4l2_queue_buffer(struct v4l2_device *dev, struct video_buffer *buffer);
/*
* v4l2_dequeue_buffer - Dequeue the next buffer
@@ -287,7 +260,7 @@ int v4l2_queue_buffer(struct v4l2_device *dev, struct v4l2_video_buffer *buffer)
* results in @buffer:error being set is not considered as a failure condition
* for the purpose of the return value.
*/
-int v4l2_dequeue_buffer(struct v4l2_device *dev, struct v4l2_video_buffer *buffer);
+int v4l2_dequeue_buffer(struct v4l2_device *dev, struct video_buffer *buffer);
/*
* v4l2_stream_on - Start video streaming
diff --git a/video-buffers.c b/video-buffers.c
new file mode 100644
index 0000000..f5dc6ec
--- /dev/null
+++ b/video-buffers.c
@@ -0,0 +1,40 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Video buffers
+ *
+ * Copyright (C) 2018 Laurent Pinchart
+ *
+ * Contact: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ */
+
+#include "video-buffers.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+struct video_buffer_set *video_buffer_set_new(unsigned int nbufs)
+{
+ struct video_buffer_set *buffers;
+
+ buffers = malloc(sizeof *buffers);
+ if (!buffers)
+ return NULL;
+
+ buffers->nbufs = nbufs;
+ buffers->buffers = calloc(nbufs, sizeof *buffers->buffers);
+ if (!buffers->buffers) {
+ free(buffers);
+ return NULL;
+ }
+
+ return buffers;
+}
+
+void video_buffer_set_delete(struct video_buffer_set *buffers)
+{
+ if (!buffers)
+ return;
+
+ free(buffers->buffers);
+ free(buffers);
+}
diff --git a/video-buffers.h b/video-buffers.h
new file mode 100644
index 0000000..001f75e
--- /dev/null
+++ b/video-buffers.h
@@ -0,0 +1,48 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Video buffers
+ *
+ * Copyright (C) 2018 Laurent Pinchart
+ *
+ * Contact: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ */
+#ifndef __VIDEO_BUFFERS_H__
+#define __VIDEO_BUFFERS_H__
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <sys/time.h>
+
+/*
+ *
+ * struct video_buffer - Video buffer information
+ * @index: Zero-based buffer index, limited to the number of buffers minus one
+ * @size: Size of the video memory, in bytes
+ * @bytesused: Number of bytes used by video data, smaller or equal to @size
+ * @timestamp: Time stamp at which the buffer has been captured
+ * @error: True if an error occured while capturing video data for the buffer
+ * @allocated: True if memory for the buffer has been allocated
+ * @mem: Video data memory
+ * @dmabuf: Video data dmabuf handle
+ */
+struct video_buffer
+{
+ unsigned int index;
+ unsigned int size;
+ unsigned int bytesused;
+ struct timeval timestamp;
+ bool error;
+ void *mem;
+ int dmabuf;
+};
+
+struct video_buffer_set
+{
+ struct video_buffer *buffers;
+ unsigned int nbufs;
+};
+
+struct video_buffer_set *video_buffer_set_new(unsigned int nbufs);
+void video_buffer_set_delete(struct video_buffer_set *buffers);
+
+#endif /* __VIDEO_BUFFERS_H__ */