aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/v4l2-core/videobuf2-v4l2.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/v4l2-core/videobuf2-v4l2.c')
-rw-r--r--drivers/media/v4l2-core/videobuf2-v4l2.c332
1 files changed, 156 insertions, 176 deletions
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)

Privacy Policy