aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/media/v4l2-core/v4l2-common.c72
-rw-r--r--drivers/media/v4l2-core/v4l2-dev.c4
-rw-r--r--drivers/media/v4l2-core/v4l2-ioctl.c146
-rw-r--r--drivers/media/v4l2-core/v4l2-mem2mem.c97
-rw-r--r--drivers/media/v4l2-core/videobuf2-v4l2.c332
-rw-r--r--include/media/v4l2-common.h5
-rw-r--r--include/media/v4l2-ioctl.h17
-rw-r--r--include/media/v4l2-mem2mem.h8
-rw-r--r--include/media/videobuf2-v4l2.h9
-rw-r--r--include/uapi/linux/videodev2.h47
10 files changed, 557 insertions, 180 deletions
diff --git a/drivers/media/v4l2-core/v4l2-common.c b/drivers/media/v4l2-core/v4l2-common.c
index a5ea1f5..9faa775 100644
--- a/drivers/media/v4l2-core/v4l2-common.c
+++ b/drivers/media/v4l2-core/v4l2-common.c
@@ -405,3 +405,75 @@ void v4l2_get_timestamp(struct timeval *tv)
tv->tv_usec = ts.tv_nsec / NSEC_PER_USEC;
}
EXPORT_SYMBOL_GPL(v4l2_get_timestamp);
+
+void v4l2_ext_buffer_to_buffer(const struct v4l2_ext_buffer *e,
+ struct v4l2_buffer *b)
+{
+ u64 nsecs;
+
+ b->index = e->index;
+ b->type = e->type;
+ b->flags = e->flags;
+ b->field = e->field;
+ b->sequence = e->sequence;
+ b->memory = e->memory;
+ b->timestamp.tv_sec = div64_u64_rem(e->timestamp, NSEC_PER_SEC, &nsecs);
+ b->timestamp.tv_usec = (u32)nsecs / NSEC_PER_USEC;
+ if (V4L2_TYPE_IS_MULTIPLANAR(b->type)) {
+ unsigned int i;
+
+ b->length = e->num_planes;
+ for (i = 0; i < e->num_planes; i++) {
+ b->m.planes[i].length = e->planes[i].length;
+ b->m.planes[i].bytesused = e->planes[i].bytesused;
+ b->m.planes[i].m.userptr = e->planes[i].m.userptr;
+ b->m.planes[i].data_offset = e->planes[i].data_offset;
+ memset(b->m.planes[i].reserved, 0,
+ sizeof(b->m.planes[i].reserved));
+ }
+ } else {
+ b->bytesused = e->planes[0].bytesused;
+ b->length = e->planes[0].length;
+ b->m.userptr = e->planes[0].m.userptr;
+ }
+ b->reserved2 = b->reserved = 0;
+ memset(&b->timecode, 0, sizeof(b->timecode));
+}
+EXPORT_SYMBOL_GPL(v4l2_ext_buffer_to_buffer);
+
+int v4l2_buffer_to_ext_buffer(const struct v4l2_buffer *b,
+ struct v4l2_ext_buffer *e)
+{
+ e->index = b->index;
+ e->type = b->type;
+ e->flags = b->flags;
+ e->field = b->field;
+ e->sequence = b->sequence;
+ e->memory = b->memory;
+ e->timestamp = b->timestamp.tv_sec * NSEC_PER_SEC +
+ b->timestamp.tv_usec * NSEC_PER_USEC;
+ if (V4L2_TYPE_IS_MULTIPLANAR(b->type)) {
+ unsigned int i;
+
+ if (b->m.planes == NULL)
+ return -EINVAL;
+ e->num_planes = b->length;
+ for (i = 0; i < e->num_planes; i++) {
+ e->planes[i].length = b->m.planes[i].length;
+ e->planes[i].bytesused = b->m.planes[i].bytesused;
+ e->planes[i].m.userptr = b->m.planes[i].m.userptr;
+ e->planes[i].data_offset = b->m.planes[i].data_offset;
+ memset(e->planes[i].reserved, 0,
+ sizeof(e->planes[i].reserved));
+ }
+ } else {
+ e->num_planes = 1;
+ e->planes[0].bytesused = b->bytesused;
+ e->planes[0].length = b->length;
+ e->planes[0].m.userptr = b->m.userptr;
+ e->planes[0].data_offset = 0;
+ }
+ memset(&e->reserved, 0, sizeof(e->reserved));
+ return 0;
+}
+EXPORT_SYMBOL_GPL(v4l2_buffer_to_ext_buffer);
diff --git a/drivers/media/v4l2-core/v4l2-dev.c b/drivers/media/v4l2-core/v4l2-dev.c
index c647ba6..1ce8063 100644
--- a/drivers/media/v4l2-core/v4l2-dev.c
+++ b/drivers/media/v4l2-core/v4l2-dev.c
@@ -678,6 +678,10 @@ static void determine_valid_ioctls(struct video_device *vdev)
SET_VALID_IOCTL(ops, VIDIOC_PREPARE_BUF, vidioc_prepare_buf);
SET_VALID_IOCTL(ops, VIDIOC_STREAMON, vidioc_streamon);
SET_VALID_IOCTL(ops, VIDIOC_STREAMOFF, vidioc_streamoff);
+ SET_VALID_IOCTL(ops, VIDIOC_EXT_QUERYBUF, vidioc_ext_querybuf);
+ SET_VALID_IOCTL(ops, VIDIOC_EXT_QBUF, vidioc_ext_qbuf);
+ SET_VALID_IOCTL(ops, VIDIOC_EXT_DQBUF, vidioc_ext_dqbuf);
+ SET_VALID_IOCTL(ops, VIDIOC_EXT_PREPARE_BUF, vidioc_ext_prepare_buf);
}
if (is_vid || is_vbi || is_tch) {
diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c
index 7961499..b014904 100644
--- a/drivers/media/v4l2-core/v4l2-ioctl.c
+++ b/drivers/media/v4l2-core/v4l2-ioctl.c
@@ -466,6 +466,28 @@ static void v4l_print_buffer(const void *arg, bool write_only)
tc->type, tc->flags, tc->frames, *(__u32 *)tc->userbits);
}
+static void v4l_print_ext_buffer(const void *arg, bool write_only)
+{
+ const struct v4l2_ext_buffer *p = arg;
+ const struct v4l2_ext_plane *plane;
+ int i;
+
+ pr_cont("%lld index=%d, type=%s, flags=0x%08x, field=%s, sequence=%d, memory=%s\n",
+ p->timestamp,
+ p->index,
+ prt_names(p->type, v4l2_type_names),
+ p->flags, prt_names(p->field, v4l2_field_names),
+ p->sequence, prt_names(p->memory, v4l2_memory_names));
+
+ for (i = 0; i < p->num_planes; ++i) {
+ plane = &p->planes[i];
+ printk(KERN_DEBUG
+ "plane %d: bytesused=%d, data_offset=0x%08x, offset/userptr=0x%llx, length=%d\n",
+ i, plane->bytesused, plane->data_offset,
+ plane->m.userptr, plane->length);
+ }
+}
+
static void v4l_print_exportbuffer(const void *arg, bool write_only)
{
const struct v4l2_exportbuffer *p = arg;
@@ -1897,27 +1919,51 @@ static int v4l_querybuf(const struct v4l2_ioctl_ops *ops,
struct file *file, void *fh, void *arg)
{
struct v4l2_buffer *p = arg;
+ struct v4l2_ext_buffer e;
int ret = check_fmt(file, p->type);
- return ret ? ret : ops->vidioc_querybuf(file, fh, p);
+ if (ret || ops->vidioc_querybuf)
+ return ret ? ret : ops->vidioc_querybuf(file, fh, p);
+
+ v4l2_buffer_to_ext_buffer(p, &e);
+ ret = ops->vidioc_ext_querybuf(file, fh, &e);
+ if (!ret)
+ v4l2_ext_buffer_to_buffer(&e, p);
+ return ret;
}
static int v4l_qbuf(const struct v4l2_ioctl_ops *ops,
struct file *file, void *fh, void *arg)
{
struct v4l2_buffer *p = arg;
+ struct v4l2_ext_buffer e;
int ret = check_fmt(file, p->type);
- return ret ? ret : ops->vidioc_qbuf(file, fh, p);
+ if (ret || ops->vidioc_qbuf)
+ return ret ? ret : ops->vidioc_qbuf(file, fh, p);
+
+ v4l2_buffer_to_ext_buffer(p, &e);
+ ret = ops->vidioc_ext_qbuf(file, fh, &e);
+ if (!ret)
+ v4l2_ext_buffer_to_buffer(&e, p);
+ return ret;
}
static int v4l_dqbuf(const struct v4l2_ioctl_ops *ops,
struct file *file, void *fh, void *arg)
{
struct v4l2_buffer *p = arg;
+ struct v4l2_ext_buffer e;
int ret = check_fmt(file, p->type);
- return ret ? ret : ops->vidioc_dqbuf(file, fh, p);
+ if (ret || ops->vidioc_dqbuf)
+ return ret ? ret : ops->vidioc_dqbuf(file, fh, p);
+
+ v4l2_buffer_to_ext_buffer(p, &e);
+ ret = ops->vidioc_ext_dqbuf(file, fh, &e);
+ if (!ret)
+ v4l2_ext_buffer_to_buffer(&e, p);
+ return ret;
}
static int v4l_create_bufs(const struct v4l2_ioctl_ops *ops,
@@ -1946,9 +1992,17 @@ static int v4l_prepare_buf(const struct v4l2_ioctl_ops *ops,
struct file *file, void *fh, void *arg)
{
struct v4l2_buffer *b = arg;
+ struct v4l2_ext_buffer e;
int ret = check_fmt(file, b->type);
- return ret ? ret : ops->vidioc_prepare_buf(file, fh, b);
+ if (ret || ops->vidioc_prepare_buf)
+ return ret ? ret : ops->vidioc_prepare_buf(file, fh, b);
+
+ v4l2_buffer_to_ext_buffer(b, &e);
+ ret = ops->vidioc_ext_prepare_buf(file, fh, &e);
+ if (!ret)
+ v4l2_ext_buffer_to_buffer(&e, b);
+ return ret;
}
static int v4l_g_parm(const struct v4l2_ioctl_ops *ops,
@@ -2511,6 +2565,86 @@ static int v4l_enum_freq_bands(const struct v4l2_ioctl_ops *ops,
return -ENOTTY;
}
+static int v4l_ext_prepare_buf(const struct v4l2_ioctl_ops *ops,
+ struct file *file, void *fh, void *arg)
+{
+ struct v4l2_ext_buffer *e = arg;
+ struct v4l2_plane planes[VIDEO_MAX_PLANES];
+ struct v4l2_buffer b = {
+ .m.planes = planes,
+ };
+ int ret = check_fmt(file, e->type);
+
+ if (ret || ops->vidioc_ext_prepare_buf)
+ return ret ? ret : ops->vidioc_ext_prepare_buf(file, fh, e);
+
+ v4l2_ext_buffer_to_buffer(e, &b);
+ ret = ops->vidioc_prepare_buf(file, fh, &b);
+ if (!ret)
+ v4l2_buffer_to_ext_buffer(&b, e);
+ return ret;
+}
+
+static int v4l_ext_querybuf(const struct v4l2_ioctl_ops *ops,
+ struct file *file, void *fh, void *arg)
+{
+ struct v4l2_ext_buffer *e = arg;
+ struct v4l2_plane planes[VIDEO_MAX_PLANES];
+ struct v4l2_buffer b = {
+ .m.planes = planes,
+ };
+ int ret = check_fmt(file, e->type);
+
+ if (ret || ops->vidioc_ext_querybuf)
+ return ret ? ret : ops->vidioc_ext_querybuf(file, fh, e);
+
+ v4l2_ext_buffer_to_buffer(e, &b);
+ ret = ops->vidioc_querybuf(file, fh, &b);
+ if (!ret)
+ v4l2_buffer_to_ext_buffer(&b, e);
+ return ret;
+}
+
+static int v4l_ext_qbuf(const struct v4l2_ioctl_ops *ops,
+ struct file *file, void *fh, void *arg)
+{
+ struct v4l2_ext_buffer *e = arg;
+ struct v4l2_plane planes[VIDEO_MAX_PLANES];
+ struct v4l2_buffer b = {
+ .m.planes = planes,
+ };
+ int ret = check_fmt(file, e->type);
+
+ if (ret || ops->vidioc_ext_qbuf)
+ return ret ? ret : ops->vidioc_ext_qbuf(file, fh, e);
+
+ v4l2_ext_buffer_to_buffer(e, &b);
+ ret = ops->vidioc_qbuf(file, fh, &b);
+ if (!ret)
+ v4l2_buffer_to_ext_buffer(&b, e);
+ return ret;
+}
+
+static int v4l_ext_dqbuf(const struct v4l2_ioctl_ops *ops,
+ struct file *file, void *fh, void *arg)
+{
+ struct v4l2_ext_buffer *e = arg;
+ struct v4l2_plane planes[VIDEO_MAX_PLANES];
+ struct v4l2_buffer b = {
+ .m.planes = planes,
+ };
+ int ret = check_fmt(file, e->type);
+
+ if (ret || ops->vidioc_ext_dqbuf)
+ return ret ? ret : ops->vidioc_ext_dqbuf(file, fh, e);
+
+ v4l2_ext_buffer_to_buffer(e, &b);
+ ret = ops->vidioc_dqbuf(file, fh, &b);
+ if (!ret)
+ v4l2_buffer_to_ext_buffer(&b, e);
+ return ret;
+}
+
struct v4l2_ioctl_info {
unsigned int ioctl;
u32 flags;
@@ -2642,6 +2776,10 @@ static struct v4l2_ioctl_info v4l2_ioctls[] = {
IOCTL_INFO_FNC(VIDIOC_ENUM_FREQ_BANDS, v4l_enum_freq_bands, v4l_print_freq_band, 0),
IOCTL_INFO_FNC(VIDIOC_DBG_G_CHIP_INFO, v4l_dbg_g_chip_info, v4l_print_dbg_chip_info, INFO_FL_CLEAR(v4l2_dbg_chip_info, match)),
IOCTL_INFO_FNC(VIDIOC_QUERY_EXT_CTRL, v4l_query_ext_ctrl, v4l_print_query_ext_ctrl, INFO_FL_CTRL | INFO_FL_CLEAR(v4l2_query_ext_ctrl, id)),
+ IOCTL_INFO_FNC(VIDIOC_EXT_QUERYBUF, v4l_ext_querybuf, v4l_print_ext_buffer, INFO_FL_QUEUE | INFO_FL_CLEAR(v4l2_ext_buffer, num_planes)),
+ IOCTL_INFO_FNC(VIDIOC_EXT_QBUF, v4l_ext_qbuf, v4l_print_ext_buffer, INFO_FL_QUEUE),
+ IOCTL_INFO_FNC(VIDIOC_EXT_DQBUF, v4l_ext_dqbuf, v4l_print_ext_buffer, INFO_FL_QUEUE),
+ IOCTL_INFO_FNC(VIDIOC_EXT_PREPARE_BUF, v4l_ext_prepare_buf, v4l_print_ext_buffer, INFO_FL_QUEUE),
};
#define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls)
diff --git a/drivers/media/v4l2-core/v4l2-mem2mem.c b/drivers/media/v4l2-core/v4l2-mem2mem.c
index f62e68a..fe9a7f9 100644
--- a/drivers/media/v4l2-core/v4l2-mem2mem.c
+++ b/drivers/media/v4l2-core/v4l2-mem2mem.c
@@ -423,6 +423,67 @@ int v4l2_m2m_prepare_buf(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
}
EXPORT_SYMBOL_GPL(v4l2_m2m_prepare_buf);
+int v4l2_m2m_ext_querybuf(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
+ struct v4l2_ext_buffer *buf)
+{
+ struct vb2_queue *vq;
+ int ret = 0;
+ unsigned int i;
+
+ vq = v4l2_m2m_get_vq(m2m_ctx, buf->type);
+ ret = vb2_ext_querybuf(vq, buf);
+
+ /* Adjust MMAP memory offsets for the CAPTURE queue */
+ if (buf->memory == V4L2_MEMORY_MMAP && !V4L2_TYPE_IS_OUTPUT(vq->type)) {
+ for (i = 0; i < buf->num_planes; ++i)
+ buf->planes[i].m.mem_offset
+ += DST_QUEUE_OFF_BASE;
+ }
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(v4l2_m2m_ext_querybuf);
+
+int v4l2_m2m_ext_qbuf(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
+ struct v4l2_ext_buffer *buf)
+{
+ struct vb2_queue *vq;
+ int ret;
+
+ vq = v4l2_m2m_get_vq(m2m_ctx, buf->type);
+ ret = vb2_ext_qbuf(vq, buf);
+ if (!ret)
+ v4l2_m2m_try_schedule(m2m_ctx);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(v4l2_m2m_ext_qbuf);
+
+int v4l2_m2m_ext_dqbuf(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
+ struct v4l2_ext_buffer *buf)
+{
+ struct vb2_queue *vq;
+
+ vq = v4l2_m2m_get_vq(m2m_ctx, buf->type);
+ return vb2_ext_dqbuf(vq, buf, file->f_flags & O_NONBLOCK);
+}
+EXPORT_SYMBOL_GPL(v4l2_m2m_ext_dqbuf);
+
+int v4l2_m2m_ext_prepare_buf(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
+ struct v4l2_ext_buffer *buf)
+{
+ struct vb2_queue *vq;
+ int ret;
+
+ vq = v4l2_m2m_get_vq(m2m_ctx, buf->type);
+ ret = vb2_ext_prepare_buf(vq, buf);
+ if (!ret)
+ v4l2_m2m_try_schedule(m2m_ctx);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(v4l2_m2m_ext_prepare_buf);
+
int v4l2_m2m_create_bufs(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
struct v4l2_create_buffers *create)
{
@@ -752,6 +813,42 @@ int v4l2_m2m_ioctl_prepare_buf(struct file *file, void *priv,
}
EXPORT_SYMBOL_GPL(v4l2_m2m_ioctl_prepare_buf);
+int v4l2_m2m_ioctl_ext_querybuf(struct file *file, void *priv,
+ struct v4l2_ext_buffer *buf)
+{
+ struct v4l2_fh *fh = file->private_data;
+
+ return v4l2_m2m_ext_querybuf(file, fh->m2m_ctx, buf);
+}
+EXPORT_SYMBOL_GPL(v4l2_m2m_ioctl_ext_querybuf);
+
+int v4l2_m2m_ioctl_ext_qbuf(struct file *file, void *priv,
+ struct v4l2_ext_buffer *buf)
+{
+ struct v4l2_fh *fh = file->private_data;
+
+ return v4l2_m2m_ext_qbuf(file, fh->m2m_ctx, buf);
+}
+EXPORT_SYMBOL_GPL(v4l2_m2m_ioctl_ext_qbuf);
+
+int v4l2_m2m_ioctl_ext_dqbuf(struct file *file, void *priv,
+ struct v4l2_ext_buffer *buf)
+{
+ struct v4l2_fh *fh = file->private_data;
+
+ return v4l2_m2m_ext_dqbuf(file, fh->m2m_ctx, buf);
+}
+EXPORT_SYMBOL_GPL(v4l2_m2m_ioctl_ext_dqbuf);
+
+int v4l2_m2m_ioctl_ext_prepare_buf(struct file *file, void *priv,
+ struct v4l2_ext_buffer *buf)
+{
+ struct v4l2_fh *fh = file->private_data;
+
+ return v4l2_m2m_ext_prepare_buf(file, fh->m2m_ctx, buf);
+}
+EXPORT_SYMBOL_GPL(v4l2_m2m_ioctl_ext_prepare_buf);
+
int v4l2_m2m_ioctl_expbuf(struct file *file, void *priv,
struct v4l2_exportbuffer *eb)
{
diff --git a/drivers/media/v4l2-core/videobuf2-v4l2.c b/drivers/media/v4l2-core/videobuf2-v4l2.c
index 0c06699..34ff016 100644
--- a/drivers/media/v4l2-core/videobuf2-v4l2.c
+++ b/drivers/media/v4l2-core/videobuf2-v4l2.c
@@ -51,22 +51,16 @@ module_param(debug, int, 0644);
/**
* __verify_planes_array() - verify that the planes array passed in struct
- * v4l2_buffer from userspace can be safely used
+ * v4l2_ext_buffer from userspace can be safely used
*/
-static int __verify_planes_array(struct vb2_buffer *vb, const struct v4l2_buffer *b)
+static int __verify_planes_array(struct vb2_buffer *vb, const struct v4l2_ext_buffer *b)
{
if (!V4L2_TYPE_IS_MULTIPLANAR(b->type))
return 0;
- /* Is memory for copying plane information present? */
- if (b->m.planes == NULL) {
- dprintk(1, "multi-planar buffer passed but planes array not provided\n");
- return -EINVAL;
- }
-
- if (b->length < vb->num_planes || b->length > VB2_MAX_PLANES) {
+ if (b->num_planes < vb->num_planes || b->num_planes > VB2_MAX_PLANES) {
dprintk(1, "incorrect planes array length, expected %d, got %d\n",
- vb->num_planes, b->length);
+ vb->num_planes, b->num_planes);
return -EINVAL;
}
@@ -82,7 +76,7 @@ static int __verify_planes_array_core(struct vb2_buffer *vb, const void *pb)
* __verify_length() - Verify that the bytesused value for each plane fits in
* the plane length and that the data offset doesn't exceed the bytesused value.
*/
-static int __verify_length(struct vb2_buffer *vb, const struct v4l2_buffer *b)
+static int __verify_length(struct vb2_buffer *vb, const struct v4l2_ext_buffer *b)
{
unsigned int length;
unsigned int bytesused;
@@ -91,27 +85,19 @@ static int __verify_length(struct vb2_buffer *vb, const struct v4l2_buffer *b)
if (!V4L2_TYPE_IS_OUTPUT(b->type))
return 0;
- if (V4L2_TYPE_IS_MULTIPLANAR(b->type)) {
- for (plane = 0; plane < vb->num_planes; ++plane) {
- length = (b->memory == VB2_MEMORY_USERPTR ||
- b->memory == VB2_MEMORY_DMABUF)
- ? b->m.planes[plane].length
- : vb->planes[plane].length;
- bytesused = b->m.planes[plane].bytesused
- ? b->m.planes[plane].bytesused : length;
-
- if (b->m.planes[plane].bytesused > length)
- return -EINVAL;
-
- if (b->m.planes[plane].data_offset > 0 &&
- b->m.planes[plane].data_offset >= bytesused)
- return -EINVAL;
- }
- } else {
- length = (b->memory == VB2_MEMORY_USERPTR)
- ? b->length : vb->planes[0].length;
+ for (plane = 0; plane < vb->num_planes; ++plane) {
+ length = (b->memory == VB2_MEMORY_USERPTR ||
+ b->memory == VB2_MEMORY_DMABUF)
+ ? b->planes[plane].length
+ : vb->planes[plane].length;
+ bytesused = b->planes[plane].bytesused
+ ? b->planes[plane].bytesused : length;
- if (b->bytesused > length)
+ if (b->planes[plane].bytesused > length)
+ return -EINVAL;
+
+ if (b->planes[plane].data_offset > 0 &&
+ b->planes[plane].data_offset >= bytesused)
return -EINVAL;
}
@@ -120,8 +106,7 @@ static int __verify_length(struct vb2_buffer *vb, const struct v4l2_buffer *b)
static void __copy_timestamp(struct vb2_buffer *vb, const void *pb)
{
- const struct v4l2_buffer *b = pb;
- struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+ const struct v4l2_ext_buffer *b = pb;
struct vb2_queue *q = vb->vb2_queue;
if (q->is_output) {
@@ -130,10 +115,7 @@ static void __copy_timestamp(struct vb2_buffer *vb, const void *pb)
* and the timecode field and flag if needed.
*/
if (q->copy_timestamp)
- vb->timestamp = timeval_to_ns(&b->timestamp);
- vbuf->flags |= b->flags & V4L2_BUF_FLAG_TIMECODE;
- if (b->flags & V4L2_BUF_FLAG_TIMECODE)
- vbuf->timecode = b->timecode;
+ vb->timestamp = b->timestamp;
}
};
@@ -154,7 +136,7 @@ static void vb2_warn_zero_bytesused(struct vb2_buffer *vb)
pr_warn("use the actual size instead.\n");
}
-static int vb2_queue_or_prepare_buf(struct vb2_queue *q, struct v4l2_buffer *b,
+static int vb2_queue_or_ext_prepare_buf(struct vb2_queue *q, struct v4l2_ext_buffer *b,
const char *opname)
{
if (b->type != q->type) {
@@ -187,7 +169,7 @@ static int vb2_queue_or_prepare_buf(struct vb2_queue *q, struct v4l2_buffer *b,
*/
static void __fill_v4l2_buffer(struct vb2_buffer *vb, void *pb)
{
- struct v4l2_buffer *b = pb;
+ struct v4l2_ext_buffer *b = pb;
struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct vb2_queue *q = vb->vb2_queue;
unsigned int plane;
@@ -196,50 +178,23 @@ static void __fill_v4l2_buffer(struct vb2_buffer *vb, void *pb)
b->index = vb->index;
b->type = vb->type;
b->memory = vb->memory;
- b->bytesused = 0;
b->flags = vbuf->flags;
b->field = vbuf->field;
- b->timestamp = ns_to_timeval(vb->timestamp);
- b->timecode = vbuf->timecode;
+ b->timestamp = vb->timestamp;
b->sequence = vbuf->sequence;
- b->reserved2 = 0;
- b->reserved = 0;
+ memset(b->reserved, 0, sizeof(b->reserved));
- if (q->is_multiplanar) {
- /*
- * Fill in plane-related data if userspace provided an array
- * for it. The caller has already verified memory and size.
- */
- b->length = vb->num_planes;
- for (plane = 0; plane < vb->num_planes; ++plane) {
- struct v4l2_plane *pdst = &b->m.planes[plane];
- struct vb2_plane *psrc = &vb->planes[plane];
-
- pdst->bytesused = psrc->bytesused;
- pdst->length = psrc->length;
- if (q->memory == VB2_MEMORY_MMAP)
- pdst->m.mem_offset = psrc->m.offset;
- else if (q->memory == VB2_MEMORY_USERPTR)
- pdst->m.userptr = psrc->m.userptr;
- else if (q->memory == VB2_MEMORY_DMABUF)
- pdst->m.fd = psrc->m.fd;
- pdst->data_offset = psrc->data_offset;
- memset(pdst->reserved, 0, sizeof(pdst->reserved));
- }
- } else {
- /*
- * We use length and offset in v4l2_planes array even for
- * single-planar buffers, but userspace does not.
- */
- b->length = vb->planes[0].length;
- b->bytesused = vb->planes[0].bytesused;
- if (q->memory == VB2_MEMORY_MMAP)
- b->m.offset = vb->planes[0].m.offset;
- else if (q->memory == VB2_MEMORY_USERPTR)
- b->m.userptr = vb->planes[0].m.userptr;
- else if (q->memory == VB2_MEMORY_DMABUF)
- b->m.fd = vb->planes[0].m.fd;
+ /*
+ * Fill in plane-related data if userspace provided an array
+ * for it. The caller has already verified memory and size.
+ */
+ b->num_planes = vb->num_planes;
+ for (plane = 0; plane < vb->num_planes; ++plane) {
+ b->planes[plane].bytesused = vb->planes[plane].bytesused;
+ b->planes[plane].length = vb->planes[plane].length;
+ b->planes[plane].data_offset = vb->planes[plane].data_offset;
+ b->planes[plane].m.userptr = vb->planes[plane].m.userptr;
}
/*
@@ -295,7 +250,7 @@ static int __fill_vb2_buffer(struct vb2_buffer *vb,
const void *pb, struct vb2_plane *planes)
{
struct vb2_queue *q = vb->vb2_queue;
- const struct v4l2_buffer *b = pb;
+ const struct v4l2_ext_buffer *b = pb;
struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
unsigned int plane;
int ret;
@@ -321,94 +276,55 @@ static int __fill_vb2_buffer(struct vb2_buffer *vb,
vb->timestamp = 0;
vbuf->sequence = 0;
- if (V4L2_TYPE_IS_MULTIPLANAR(b->type)) {
- if (b->memory == VB2_MEMORY_USERPTR) {
- for (plane = 0; plane < vb->num_planes; ++plane) {
- planes[plane].m.userptr =
- b->m.planes[plane].m.userptr;
- planes[plane].length =
- b->m.planes[plane].length;
- }
+ if (b->memory == VB2_MEMORY_USERPTR) {
+ for (plane = 0; plane < vb->num_planes; ++plane) {
+ planes[plane].m.userptr =
+ b->planes[plane].m.userptr;
+ planes[plane].length =
+ b->planes[plane].length;
}
- if (b->memory == VB2_MEMORY_DMABUF) {
- for (plane = 0; plane < vb->num_planes; ++plane) {
- planes[plane].m.fd =
- b->m.planes[plane].m.fd;
- planes[plane].length =
- b->m.planes[plane].length;
- }
+ }
+ if (b->memory == VB2_MEMORY_DMABUF) {
+ for (plane = 0; plane < vb->num_planes; ++plane) {
+ planes[plane].m.fd =
+ b->planes[plane].m.fd;
+ planes[plane].length =
+ b->planes[plane].length;
}
+ }
- /* Fill in driver-provided information for OUTPUT types */
- if (V4L2_TYPE_IS_OUTPUT(b->type)) {
- /*
- * Will have to go up to b->length when API starts
- * accepting variable number of planes.
- *
- * If bytesused == 0 for the output buffer, then fall
- * back to the full buffer size. In that case
- * userspace clearly never bothered to set it and
- * it's a safe assumption that they really meant to
- * use the full plane sizes.
- *
- * Some drivers, e.g. old codec drivers, use bytesused == 0
- * as a way to indicate that streaming is finished.
- * In that case, the driver should use the
- * allow_zero_bytesused flag to keep old userspace
- * applications working.
- */
- for (plane = 0; plane < vb->num_planes; ++plane) {
- struct vb2_plane *pdst = &planes[plane];
- struct v4l2_plane *psrc = &b->m.planes[plane];
-
- if (psrc->bytesused == 0)
- vb2_warn_zero_bytesused(vb);
-
- if (vb->vb2_queue->allow_zero_bytesused)
- pdst->bytesused = psrc->bytesused;
- else
- pdst->bytesused = psrc->bytesused ?
- psrc->bytesused : pdst->length;
- pdst->data_offset = psrc->data_offset;
- }
- }
- } else {
+ /* Fill in driver-provided information for OUTPUT types */
+ if (V4L2_TYPE_IS_OUTPUT(b->type)) {
/*
- * Single-planar buffers do not use planes array,
- * so fill in relevant v4l2_buffer struct fields instead.
- * In videobuf we use our internal V4l2_planes struct for
- * single-planar buffers as well, for simplicity.
+ * Will have to go up to b->length when API starts
+ * accepting variable number of planes.
*
- * If bytesused == 0 for the output buffer, then fall back
- * to the full buffer size as that's a sensible default.
+ * If bytesused == 0 for the output buffer, then fall
+ * back to the full buffer size. In that case
+ * userspace clearly never bothered to set it and
+ * it's a safe assumption that they really meant to
+ * use the full plane sizes.
*
- * Some drivers, e.g. old codec drivers, use bytesused == 0 as
- * a way to indicate that streaming is finished. In that case,
- * the driver should use the allow_zero_bytesused flag to keep
- * old userspace applications working.
+ * Some drivers, e.g. old codec drivers, use bytesused == 0
+ * as a way to indicate that streaming is finished.
+ * In that case, the driver should use the
+ * allow_zero_bytesused flag to keep old userspace
+ * applications working.
*/
- if (b->memory == VB2_MEMORY_USERPTR) {
- planes[0].m.userptr = b->m.userptr;
- planes[0].length = b->length;
- }
-
- if (b->memory == VB2_MEMORY_DMABUF) {
- planes[0].m.fd = b->m.fd;
- planes[0].length = b->length;
- }
+ for (plane = 0; plane < vb->num_planes; ++plane) {
+ struct vb2_plane *pdst = &planes[plane];
+ const struct v4l2_ext_plane *psrc = &b->planes[plane];
- if (V4L2_TYPE_IS_OUTPUT(b->type)) {
- if (b->bytesused == 0)
+ if (psrc->bytesused == 0)
vb2_warn_zero_bytesused(vb);
if (vb->vb2_queue->allow_zero_bytesused)
- planes[0].bytesused = b->bytesused;
+ pdst->bytesused = psrc->bytesused;
else
- planes[0].bytesused = b->bytesused ?
- b->bytesused : planes[0].length;
- } else
- planes[0].bytesused = 0;
-
+ pdst->bytesused = psrc->bytesused ?
+ psrc->bytesused : pdst->length;
+ pdst->data_offset = psrc->data_offset;
+ }
}
/* Zero flags that the vb2 core handles */
@@ -422,14 +338,12 @@ static int __fill_vb2_buffer(struct vb2_buffer *vb,
vbuf->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
}
+ vbuf->flags &= ~V4L2_BUF_FLAG_TIMECODE;
if (V4L2_TYPE_IS_OUTPUT(b->type)) {
/*
- * For output buffers mask out the timecode flag:
- * this will be handled later in vb2_qbuf().
* The 'field' is valid metadata for this output buffer
* and so that needs to be copied here.
*/
- vbuf->flags &= ~V4L2_BUF_FLAG_TIMECODE;
vbuf->field = b->field;
} else {
/* Zero any output buffer flags as this is a capture buffer */
@@ -446,6 +360,38 @@ static const struct vb2_buf_ops v4l2_buf_ops = {
.copy_timestamp = __copy_timestamp,
};
+int vb2_ext_querybuf(struct vb2_queue *q, struct v4l2_ext_buffer *b)
+{
+ struct vb2_buffer *vb;
+ int ret;
+
+ if (b->type != q->type) {
+ dprintk(1, "wrong buffer type\n");
+ return -EINVAL;
+ }
+
+ if (b->index >= q->num_buffers) {
+ dprintk(1, "buffer index out of range\n");
+ return -EINVAL;
+ }
+ vb = q->bufs[b->index];
+ ret = __verify_planes_array(vb, b);
+ if (!ret)
+ vb2_core_querybuf(q, b->index, b);
+ return ret;
+}
+EXPORT_SYMBOL(vb2_ext_querybuf);
+
+static int __buffer_to_ext_buffer(const struct v4l2_buffer *b,
+ struct v4l2_ext_buffer *e)
+{
+ int ret = v4l2_buffer_to_ext_buffer(b, e);
+
+ if (ret)
+ dprintk(1, "multi-planar buffer passed but planes array not provided\n");
+ return ret;
+}
+
/**
* vb2_querybuf() - query video buffer information
* @q: videobuf queue
@@ -461,22 +407,14 @@ static const struct vb2_buf_ops v4l2_buf_ops = {
*/
int vb2_querybuf(struct vb2_queue *q, struct v4l2_buffer *b)
{
- struct vb2_buffer *vb;
+ struct v4l2_ext_buffer e;
int ret;
- if (b->type != q->type) {
- dprintk(1, "wrong buffer type\n");
- return -EINVAL;
- }
-
- if (b->index >= q->num_buffers) {
- dprintk(1, "buffer index out of range\n");
- return -EINVAL;
- }
- vb = q->bufs[b->index];
- ret = __verify_planes_array(vb, b);
+ ret = __buffer_to_ext_buffer(b, &e);
if (!ret)
- vb2_core_querybuf(q, b->index, b);
+ ret = vb2_ext_querybuf(q, &e);
+ if (!ret)
+ v4l2_ext_buffer_to_buffer(&e, b);
return ret;
}
EXPORT_SYMBOL(vb2_querybuf);
@@ -489,7 +427,7 @@ int vb2_reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req)
}
EXPORT_SYMBOL_GPL(vb2_reqbufs);
-int vb2_prepare_buf(struct vb2_queue *q, struct v4l2_buffer *b)
+int vb2_ext_prepare_buf(struct vb2_queue *q, struct v4l2_ext_buffer *b)
{
int ret;
@@ -498,10 +436,24 @@ int vb2_prepare_buf(struct vb2_queue *q, struct v4l2_buffer *b)
return -EBUSY;
}
- ret = vb2_queue_or_prepare_buf(q, b, "prepare_buf");
+ ret = vb2_queue_or_ext_prepare_buf(q, b, "ext_prepare_buf");
return ret ? ret : vb2_core_prepare_buf(q, b->index, b);
}
+EXPORT_SYMBOL_GPL(vb2_ext_prepare_buf);
+
+int vb2_prepare_buf(struct vb2_queue *q, struct v4l2_buffer *b)
+{
+ struct v4l2_ext_buffer e;
+ int ret;
+
+ ret = __buffer_to_ext_buffer(b, &e);
+ if (!ret)
+ ret = vb2_ext_prepare_buf(q, &e);
+ if (!ret)
+ v4l2_ext_buffer_to_buffer(&e, b);
+ return ret;
+}
EXPORT_SYMBOL_GPL(vb2_prepare_buf);
int vb2_create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create)
@@ -558,7 +510,7 @@ int vb2_create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create)
}
EXPORT_SYMBOL_GPL(vb2_create_bufs);
-int vb2_qbuf(struct vb2_queue *q, struct v4l2_buffer *b)
+int vb2_ext_qbuf(struct vb2_queue *q, struct v4l2_ext_buffer *b)
{
int ret;
@@ -567,12 +519,26 @@ int vb2_qbuf(struct vb2_queue *q, struct v4l2_buffer *b)
return -EBUSY;
}
- ret = vb2_queue_or_prepare_buf(q, b, "qbuf");
+ ret = vb2_queue_or_ext_prepare_buf(q, b, "qbuf");
return ret ? ret : vb2_core_qbuf(q, b->index, b);
}
+EXPORT_SYMBOL_GPL(vb2_ext_qbuf);
+
+int vb2_qbuf(struct vb2_queue *q, struct v4l2_buffer *b)
+{
+ struct v4l2_ext_buffer e;
+ int ret;
+
+ ret = __buffer_to_ext_buffer(b, &e);
+ if (!ret)
+ ret = vb2_ext_qbuf(q, &e);
+ if (!ret)
+ v4l2_ext_buffer_to_buffer(&e, b);
+ return ret;
+}
EXPORT_SYMBOL_GPL(vb2_qbuf);
-int vb2_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b, bool nonblocking)
+int vb2_ext_dqbuf(struct vb2_queue *q, struct v4l2_ext_buffer *b, bool nonblocking)
{
int ret;
@@ -596,6 +562,20 @@ int vb2_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b, bool nonblocking)
return ret;
}
+EXPORT_SYMBOL_GPL(vb2_ext_dqbuf);
+
+int vb2_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b, bool nonblocking)
+{
+ struct v4l2_ext_buffer e;
+ int ret;
+
+ ret = __buffer_to_ext_buffer(b, &e);
+ if (!ret)
+ ret = vb2_ext_dqbuf(q, &e, nonblocking);
+ if (!ret)
+ v4l2_ext_buffer_to_buffer(&e, b);
+ return ret;
+}
EXPORT_SYMBOL_GPL(vb2_dqbuf);
int vb2_streamon(struct vb2_queue *q, enum v4l2_buf_type type)
diff --git a/include/media/v4l2-common.h b/include/media/v4l2-common.h
index aac8b7b..b10d865 100644
--- a/include/media/v4l2-common.h
+++ b/include/media/v4l2-common.h
@@ -264,4 +264,9 @@ const struct v4l2_frmsize_discrete *v4l2_find_nearest_format(
void v4l2_get_timestamp(struct timeval *tv);
+int v4l2_buffer_to_ext_buffer(const struct v4l2_buffer *b,
+ struct v4l2_ext_buffer *e);
+void v4l2_ext_buffer_to_buffer(const struct v4l2_ext_buffer *e,
+ struct v4l2_buffer *b);
+
#endif /* V4L2_COMMON_H_ */
diff --git a/include/media/v4l2-ioctl.h b/include/media/v4l2-ioctl.h
index bd53121..4944a42 100644
--- a/include/media/v4l2-ioctl.h
+++ b/include/media/v4l2-ioctl.h
@@ -159,6 +159,14 @@ struct v4l2_fh;
* :ref:`VIDIOC_CREATE_BUFS <vidioc_create_bufs>` ioctl
* @vidioc_prepare_buf: pointer to the function that implements
* :ref:`VIDIOC_PREPARE_BUF <vidioc_prepare_buf>` ioctl
+ * @vidioc_ext_querybuf: pointer to the function that implements
+ * :ref:`VIDIOC_EXT_QUERYBUF <vidioc_querybuf>` ioctl
+ * @vidioc_ext_qbuf: pointer to the function that implements
+ * :ref:`VIDIOC_EXT_QBUF <vidioc_qbuf>` ioctl
+ * @vidioc_ext_dqbuf: pointer to the function that implements
+ * :ref:`VIDIOC_EXT_DQBUF <vidioc_qbuf>` ioctl
+ * @vidioc_ext_prepare_buf: pointer to the function that implements
+ * :ref:`VIDIOC_EXT_PREPARE_BUF <vidioc_prepare_buf>` ioctl
* @vidioc_overlay: pointer to the function that implements
* :ref:`VIDIOC_OVERLAY <vidioc_overlay>` ioctl
* @vidioc_g_fbuf: pointer to the function that implements
@@ -419,6 +427,15 @@ struct v4l2_ioctl_ops {
int (*vidioc_prepare_buf)(struct file *file, void *fh,
struct v4l2_buffer *b);
+ int (*vidioc_ext_querybuf)(struct file *file, void *fh,
+ struct v4l2_ext_buffer *b);
+ int (*vidioc_ext_qbuf)(struct file *file, void *fh,
+ struct v4l2_ext_buffer *b);
+ int (*vidioc_ext_dqbuf)(struct file *file, void *fh,
+ struct v4l2_ext_buffer *b);
+ int (*vidioc_ext_prepare_buf)(struct file *file, void *fh,
+ struct v4l2_ext_buffer *b);
+
int (*vidioc_overlay)(struct file *file, void *fh, unsigned int i);
int (*vidioc_g_fbuf)(struct file *file, void *fh,
struct v4l2_framebuffer *a);
diff --git a/include/media/v4l2-mem2mem.h b/include/media/v4l2-mem2mem.h
index e157d5c..bff8387 100644
--- a/include/media/v4l2-mem2mem.h
+++ b/include/media/v4l2-mem2mem.h
@@ -588,14 +588,22 @@ int v4l2_m2m_ioctl_create_bufs(struct file *file, void *fh,
struct v4l2_create_buffers *create);
int v4l2_m2m_ioctl_querybuf(struct file *file, void *fh,
struct v4l2_buffer *buf);
+int v4l2_m2m_ioctl_ext_querybuf(struct file *file, void *fh,
+ struct v4l2_ext_buffer *buf);
int v4l2_m2m_ioctl_expbuf(struct file *file, void *fh,
struct v4l2_exportbuffer *eb);
int v4l2_m2m_ioctl_qbuf(struct file *file, void *fh,
struct v4l2_buffer *buf);
+int v4l2_m2m_ioctl_ext_qbuf(struct file *file, void *fh,
+ struct v4l2_ext_buffer *buf);
int v4l2_m2m_ioctl_dqbuf(struct file *file, void *fh,
struct v4l2_buffer *buf);
+int v4l2_m2m_ioctl_ext_dqbuf(struct file *file, void *fh,
+ struct v4l2_ext_buffer *buf);
int v4l2_m2m_ioctl_prepare_buf(struct file *file, void *fh,
struct v4l2_buffer *buf);
+int v4l2_m2m_ioctl_ext_prepare_buf(struct file *file, void *fh,
+ struct v4l2_ext_buffer *buf);
int v4l2_m2m_ioctl_streamon(struct file *file, void *fh,
enum v4l2_buf_type type);
int v4l2_m2m_ioctl_streamoff(struct file *file, void *fh,
diff --git a/include/media/videobuf2-v4l2.h b/include/media/videobuf2-v4l2.h
index 036127c..e9ea84c 100644
--- a/include/media/videobuf2-v4l2.h
+++ b/include/media/videobuf2-v4l2.h
@@ -51,6 +51,7 @@ struct vb2_v4l2_buffer {
container_of(vb, struct vb2_v4l2_buffer, vb2_buf)
int vb2_querybuf(struct vb2_queue *q, struct v4l2_buffer *b);
+int vb2_ext_querybuf(struct vb2_queue *q, struct v4l2_ext_buffer *b);
/**
* vb2_reqbufs() - Wrapper for vb2_core_reqbufs() that also verifies
@@ -90,6 +91,7 @@ int vb2_create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create);
* from vidioc_prepare_buf handler in driver.
*/
int vb2_prepare_buf(struct vb2_queue *q, struct v4l2_buffer *b);
+int vb2_ext_prepare_buf(struct vb2_queue *q, struct v4l2_ext_buffer *b);
/**
* vb2_qbuf() - Queue a buffer from userspace
@@ -111,6 +113,7 @@ int vb2_prepare_buf(struct vb2_queue *q, struct v4l2_buffer *b);
* from VIDIOC_QBUF() handler in driver.
*/
int vb2_qbuf(struct vb2_queue *q, struct v4l2_buffer *b);
+int vb2_ext_qbuf(struct vb2_queue *q, struct v4l2_ext_buffer *b);
/**
* vb2_expbuf() - Export a buffer as a file descriptor
@@ -147,6 +150,7 @@ int vb2_expbuf(struct vb2_queue *q, struct v4l2_exportbuffer *eb);
* from VIDIOC_DQBUF() handler in driver.
*/
int vb2_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b, bool nonblocking);
+int vb2_ext_dqbuf(struct vb2_queue *q, struct v4l2_ext_buffer *b, bool nonblocking);
/**
* vb2_streamon - start streaming
@@ -245,9 +249,14 @@ int vb2_ioctl_create_bufs(struct file *file, void *priv,
struct v4l2_create_buffers *p);
int vb2_ioctl_prepare_buf(struct file *file, void *priv,
struct v4l2_buffer *p);
+int vb2_ioctl_ext_prepare_buf(struct file *file, void *priv,
+ struct v4l2_ext_buffer *p);
int vb2_ioctl_querybuf(struct file *file, void *priv, struct v4l2_buffer *p);
+int vb2_ioctl_ext_querybuf(struct file *file, void *priv, struct v4l2_ext_buffer *p);
int vb2_ioctl_qbuf(struct file *file, void *priv, struct v4l2_buffer *p);
+int vb2_ioctl_ext_qbuf(struct file *file, void *priv, struct v4l2_ext_buffer *p);
int vb2_ioctl_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p);
+int vb2_ioctl_ext_dqbuf(struct file *file, void *priv, struct v4l2_ext_buffer *p);
int vb2_ioctl_streamon(struct file *file, void *priv, enum v4l2_buf_type i);
int vb2_ioctl_streamoff(struct file *file, void *priv, enum v4l2_buf_type i);
int vb2_ioctl_expbuf(struct file *file, void *priv,
diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h
index 185d6a0..908eeaa 100644
--- a/include/uapi/linux/videodev2.h
+++ b/include/uapi/linux/videodev2.h
@@ -875,6 +875,18 @@ struct v4l2_plane {
__u32 reserved[11];
};
+struct v4l2_ext_plane {
+ __u32 bytesused;
+ __u32 length;
+ union {
+ __u32 mem_offset;
+ __u64 userptr;
+ __s32 fd;
+ } m;
+ __u32 data_offset;
+ __u32 reserved[11];
+};
+
/**
* struct v4l2_buffer - video buffer info
* @index: id number of the buffer
@@ -928,6 +940,36 @@ struct v4l2_buffer {
__u32 reserved;
};
+/**
+ * struct v4l2_ext_buffer - video buffer info
+ * @index: id number of the buffer
+ * @type: enum v4l2_buf_type; buffer type (type == *_MPLANE for
+ * multiplanar buffers);
+ * @flags: buffer informational flags
+ * @field: enum v4l2_field; field order of the image in the buffer
+ * @timestamp: frame timestamp
+ * @sequence: sequence count of this frame
+ * @memory: enum v4l2_memory; the method, in which the actual video data is
+ * passed
+ * @planes: per-plane buffer information
+ * @num_planes: number of plane buffers
+ *
+ * Contains data exchanged by application and driver using one of the Streaming
+ * I/O methods.
+ */
+struct v4l2_ext_buffer {
+ __u32 index;
+ __u32 type;
+ __u32 flags;
+ __u32 field;
+ __u64 timestamp;
+ __u32 sequence;
+ __u32 memory;
+ struct v4l2_ext_plane planes[VIDEO_MAX_PLANES];
+ __u32 num_planes;
+ __u32 reserved[11];
+};
+
/* Flags for 'flags' field */
/* Buffer is mapped (flag) */
#define V4L2_BUF_FLAG_MAPPED 0x00000001
@@ -2397,6 +2439,11 @@ struct v4l2_create_buffers {
#define VIDIOC_QUERY_EXT_CTRL _IOWR('V', 103, struct v4l2_query_ext_ctrl)
+#define VIDIOC_EXT_QUERYBUF _IOWR('V', 104, struct v4l2_ext_buffer)
+#define VIDIOC_EXT_QBUF _IOWR('V', 105, struct v4l2_ext_buffer)
+#define VIDIOC_EXT_DQBUF _IOWR('V', 106, struct v4l2_ext_buffer)
+#define VIDIOC_EXT_PREPARE_BUF _IOWR('V', 107, struct v4l2_ext_buffer)
+
/* Reminder: when adding new ioctls please add support for them to
drivers/media/v4l2-core/v4l2-compat-ioctl32.c as well! */

Privacy Policy