From: Mauro Carvalho Chehab <mchehab@redhat.com>
To: Pawel Osciak <p.osciak@samsung.com>
Cc: linux-media@vger.kernel.org, m.szyprowski@samsung.com,
kyungmin.park@samsung.com, hverkuil@xs4all.nl
Subject: Re: [PATCH v2 1/3] v4l: Add support for multi-plane buffers to V4L2 API.
Date: Tue, 09 Mar 2010 12:03:17 -0300 [thread overview]
Message-ID: <4B966335.5060101@redhat.com> (raw)
In-Reply-To: <1268146183-2018-2-git-send-email-p.osciak@samsung.com>
Pawel Osciak wrote:
> Current V4L2 API assumes that each video buffer contains exactly one,
> contiguous memory buffer for video data. Even in case of planar video
> formats, e.g. YCbCr with each component residing in a separate area
> of memory, it is specified that each of those planes immediately follows
> the previous one in memory.
>
> There exist hardware video devices that handle, or even require, each of
> the planes to reside in a separate, arbitrary memory area. Some even
> require different planes to be placed in different, physical memory banks.
>
> This patch introduces a backward-compatible extension of V4L2 API, which
> allows passing additional, per-plane info in the video buffer structure.
>
> Signed-off-by: Pawel Osciak <p.osciak@samsung.com>
> Reviewed-by: Marek Szyprowski <m.szyprowski@samsung.com>
> Reviewed-by: Kyungmin Park <kyungmin.park@samsung.com>
> ---
> drivers/media/video/v4l2-ioctl.c | 97 ++++++++++++++++++++++++++-----------
> include/linux/videodev2.h | 33 ++++++++++++-
> 2 files changed, 99 insertions(+), 31 deletions(-)
>
> diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c
> index 4b11257..b89b73f 100644
> --- a/drivers/media/video/v4l2-ioctl.c
> +++ b/drivers/media/video/v4l2-ioctl.c
> @@ -172,6 +172,8 @@ static const char *v4l2_memory_names[] = {
> [V4L2_MEMORY_MMAP] = "mmap",
> [V4L2_MEMORY_USERPTR] = "userptr",
> [V4L2_MEMORY_OVERLAY] = "overlay",
> + [V4L2_MEMORY_MULTI_USERPTR] = "multi-userptr",
> + [V4L2_MEMORY_MULTI_MMAP] = "multi-mmap",
> };
>
> #define prt_names(a, arr) ((((a) >= 0) && ((a) < ARRAY_SIZE(arr))) ? \
> @@ -1975,7 +1977,7 @@ static unsigned long cmd_input_size(unsigned int cmd)
> switch (cmd) {
> CMDINSIZE(ENUM_FMT, fmtdesc, type);
> CMDINSIZE(G_FMT, format, type);
> - CMDINSIZE(QUERYBUF, buffer, type);
> + CMDINSIZE(QUERYBUF, buffer, length);
> CMDINSIZE(G_PARM, streamparm, type);
> CMDINSIZE(ENUMSTD, standard, index);
> CMDINSIZE(ENUMINPUT, input, index);
> @@ -2000,6 +2002,46 @@ static unsigned long cmd_input_size(unsigned int cmd)
> }
> }
>
> +static int check_array_args(unsigned int cmd, void *parg, size_t *array_size,
> + void * __user *user_ptr, void ***kernel_ptr)
> +{
> + int ret = 0;
> +
> + switch(cmd) {
> + case VIDIOC_QUERYBUF:
> + case VIDIOC_QBUF:
> + case VIDIOC_DQBUF: {
> + struct v4l2_buffer *buf = parg;
> +
> + if ((buf->memory == V4L2_MEMORY_MULTI_USERPTR
> + || buf->memory == V4L2_MEMORY_MULTI_MMAP)) {
> + *user_ptr = (void __user *)buf->m.planes;
> + *kernel_ptr = (void **)&buf->m.planes;
> + *array_size = sizeof(struct v4l2_plane) * buf->length;
> + ret = 1;
> + }
> + break;
> + }
> +
> + case VIDIOC_S_EXT_CTRLS:
> + case VIDIOC_G_EXT_CTRLS:
> + case VIDIOC_TRY_EXT_CTRLS: {
> + struct v4l2_ext_controls *ctrls = parg;
> +
> + if (ctrls->count != 0) {
> + *user_ptr = (void __user *)ctrls->controls;
> + *kernel_ptr = (void **)&ctrls->controls;
> + *array_size = sizeof(struct v4l2_ext_control)
> + * ctrls->count;
> + ret = 1;
> + }
> + break;
> + }
> + }
> +
> + return ret;
> +}
> +
> long video_ioctl2(struct file *file,
> unsigned int cmd, unsigned long arg)
> {
> @@ -2007,15 +2049,16 @@ long video_ioctl2(struct file *file,
> void *mbuf = NULL;
> void *parg = NULL;
> long err = -EINVAL;
> - int is_ext_ctrl;
> - size_t ctrls_size = 0;
> + int has_array_args;
> + size_t array_size = 0;
> void __user *user_ptr = NULL;
> + void **kernel_ptr = NULL;
>
> #ifdef __OLD_VIDIOC_
> cmd = video_fix_command(cmd);
> #endif
> - is_ext_ctrl = (cmd == VIDIOC_S_EXT_CTRLS || cmd == VIDIOC_G_EXT_CTRLS ||
> - cmd == VIDIOC_TRY_EXT_CTRLS);
> + /*is_ext_ctrl = (cmd == VIDIOC_S_EXT_CTRLS || cmd == VIDIOC_G_EXT_CTRLS ||
> + cmd == VIDIOC_TRY_EXT_CTRLS);*/
Just drop it if not used anymore.
>
> /* Copy arguments into temp kernel buffer */
> if (_IOC_DIR(cmd) != _IOC_NONE) {
> @@ -2045,43 +2088,39 @@ long video_ioctl2(struct file *file,
> }
> }
>
> - if (is_ext_ctrl) {
> - struct v4l2_ext_controls *p = parg;
> + has_array_args = check_array_args(cmd, parg, &array_size,
> + &user_ptr, &kernel_ptr);
>
> - /* In case of an error, tell the caller that it wasn't
> - a specific control that caused it. */
> - p->error_idx = p->count;
> - user_ptr = (void __user *)p->controls;
> - if (p->count) {
> - ctrls_size = sizeof(struct v4l2_ext_control) * p->count;
> - /* Note: v4l2_ext_controls fits in sbuf[] so mbuf is still NULL. */
> - mbuf = kmalloc(ctrls_size, GFP_KERNEL);
> - err = -ENOMEM;
> - if (NULL == mbuf)
> - goto out_ext_ctrl;
> - err = -EFAULT;
> - if (copy_from_user(mbuf, user_ptr, ctrls_size))
> - goto out_ext_ctrl;
> - p->controls = mbuf;
> - }
> + if (has_array_args) {
> + /* When adding new types of array args, make sure that the
> + * parent argument to ioctl, which contains the array, fits into
> + * sbuf (so that mbuf will still remain unused up to here).
> + */
> + mbuf = kmalloc(array_size, GFP_KERNEL);
> + err = -ENOMEM;
> + if (NULL == mbuf)
> + goto out_array_args;
> + err = -EFAULT;
> + if (copy_from_user(mbuf, user_ptr, array_size))
> + goto out_array_args;
> + *kernel_ptr = mbuf;
You probably need something similar to this at v4l2-compat-ioctl32.c.
> }
>
> /* Handles IOCTL */
> err = __video_do_ioctl(file, cmd, parg);
> if (err == -ENOIOCTLCMD)
> err = -EINVAL;
> - if (is_ext_ctrl) {
> - struct v4l2_ext_controls *p = parg;
>
> - p->controls = (void *)user_ptr;
> - if (p->count && err == 0 && copy_to_user(user_ptr, mbuf, ctrls_size))
> + if (has_array_args) {
> + *kernel_ptr = user_ptr;
> + if (copy_to_user(user_ptr, mbuf, array_size))
> err = -EFAULT;
> - goto out_ext_ctrl;
> + goto out_array_args;
> }
> if (err < 0)
> goto out;
>
> -out_ext_ctrl:
> +out_array_args:
> /* Copy results into user buffer */
> switch (_IOC_DIR(cmd)) {
> case _IOC_READ:
> diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
> index d4962a7..bf3f33d 100644
> --- a/include/linux/videodev2.h
> +++ b/include/linux/videodev2.h
> @@ -70,6 +70,7 @@
> * Moved from videodev.h
> */
> #define VIDEO_MAX_FRAME 32
> +#define VIDEO_MAX_PLANES 3
>
> #ifndef __KERNEL__
>
> @@ -180,6 +181,10 @@ enum v4l2_memory {
> V4L2_MEMORY_MMAP = 1,
> V4L2_MEMORY_USERPTR = 2,
> V4L2_MEMORY_OVERLAY = 3,
> +
> + /* Discontiguous buffer types */
> + V4L2_MEMORY_MULTI_USERPTR = 4,
> + V4L2_MEMORY_MULTI_MMAP = 5,
> };
>
> /* see also http://vektor.theorem.ca/graphics/ycbcr/ */
> @@ -519,6 +524,29 @@ struct v4l2_requestbuffers {
> __u32 reserved[2];
> };
>
> +/* struct v4l2_plane - a multi-plane buffer plane.
> + *
> + * Multi-plane buffers consist of two or more planes, e.g. an YCbCr buffer
> + * with two planes has one plane for Y, and another for interleaved CbCr
> + * components. Each plane can reside in a separate memory buffer, or in
> + * a completely separate memory chip even (e.g. in embedded devices).
> + */
> +struct v4l2_plane {
> + __u32 bytesused;
> +
> + union {
> + __u32 offset;
> + unsigned long userptr;
> + } m;
> + __u32 length;
> + __u32 reserved[5];
> +};
> +
> +/* struct v4l2_buffer - a video buffer (frame)
> + * @length: size of the buffer (not its payload) for single-plane buffers,
> + * number of planes (and number of elements in planes array)
> + * for multi-plane
> + */
> struct v4l2_buffer {
> __u32 index;
> enum v4l2_buf_type type;
> @@ -532,8 +560,9 @@ struct v4l2_buffer {
> /* memory location */
> enum v4l2_memory memory;
> union {
> - __u32 offset;
> - unsigned long userptr;
> + __u32 offset;
> + unsigned long userptr;
> + struct v4l2_plane *planes;
> } m;
> __u32 length;
> __u32 input;
--
Cheers,
Mauro
next prev parent reply other threads:[~2010-03-09 15:03 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-03-09 14:49 [PATCH/RFC v2 0/3] Multi-plane video buffer support for V4L2 API and videobuf Pawel Osciak
2010-03-09 14:49 ` [PATCH v2 1/3] v4l: Add support for multi-plane buffers to V4L2 API Pawel Osciak
2010-03-09 15:03 ` Mauro Carvalho Chehab [this message]
2010-03-09 14:49 ` [PATCH v2 2/3] v4l: videobuf: Add support for multi-plane buffers Pawel Osciak
2010-03-09 14:49 ` [PATCH v2 3/3] v4l: vivi: add 2- and 3-planar YCbCr422 Pawel Osciak
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4B966335.5060101@redhat.com \
--to=mchehab@redhat.com \
--cc=hverkuil@xs4all.nl \
--cc=kyungmin.park@samsung.com \
--cc=linux-media@vger.kernel.org \
--cc=m.szyprowski@samsung.com \
--cc=p.osciak@samsung.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.