On Friday 30 July 2010 10:49:42 Pawel Osciak wrote: > Add multi-planar API core ioctl handling and conversion functions. > > Signed-off-by: Pawel Osciak <p.osciak@xxxxxxxxxxx> > Signed-off-by: Kyungmin Park <kyungmin.park@xxxxxxxxxxx> > Reviewed-by: Marek Szyprowski <m.szyprowski@xxxxxxxxxxx> > --- > drivers/media/video/v4l2-ioctl.c | 418 ++++++++++++++++++++++++++++++++++---- > include/media/v4l2-ioctl.h | 16 ++ > 2 files changed, 390 insertions(+), 44 deletions(-) > > diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c > index a830bbd..3b2880a 100644 > --- a/drivers/media/video/v4l2-ioctl.c > +++ b/drivers/media/video/v4l2-ioctl.c > @@ -476,20 +476,33 @@ static void dbgbuf(unsigned int cmd, struct video_device *vfd, > struct v4l2_buffer *p) > { > struct v4l2_timecode *tc = &p->timecode; > + struct v4l2_plane *plane; > + int i; > > dbgarg(cmd, "%02ld:%02d:%02d.%08ld index=%d, type=%s, " > - "bytesused=%d, flags=0x%08d, " > - "field=%0d, sequence=%d, memory=%s, offset/userptr=0x%08lx, length=%d\n", > + "flags=0x%08d, field=%0d, sequence=%d, memory=%s\n", > p->timestamp.tv_sec / 3600, > (int)(p->timestamp.tv_sec / 60) % 60, > (int)(p->timestamp.tv_sec % 60), > (long)p->timestamp.tv_usec, > p->index, > prt_names(p->type, v4l2_type_names), > - p->bytesused, p->flags, > - p->field, p->sequence, > - prt_names(p->memory, v4l2_memory_names), > - p->m.userptr, p->length); > + p->flags, p->field, p->sequence, > + prt_names(p->memory, v4l2_memory_names)); > + > + if (V4L2_TYPE_IS_MULTIPLANAR(p->type) && p->m.planes) { > + for (i = 0; i < p->length; ++i) { > + plane = &p->m.planes[i]; > + dbgarg2("plane %d: bytesused=%d, data_offset=0x%08x " > + "offset/userptr=0x%08lx, length=%d\n", > + i, plane->bytesused, plane->data_offset, > + plane->m.userptr, plane->length); > + } > + } else { > + dbgarg2("bytesused=%d, offset/userptr=0x%08lx, length=%d\n", > + p->bytesused, p->m.userptr, p->length); > + } > + > dbgarg2("timecode=%02d:%02d:%02d type=%d, " > "flags=0x%08d, frames=%d, userbits=0x%08x\n", > tc->hours, tc->minutes, tc->seconds, > @@ -517,6 +530,27 @@ static inline void v4l_print_pix_fmt(struct video_device *vfd, > fmt->bytesperline, fmt->sizeimage, fmt->colorspace); > }; > > +static inline void v4l_print_pix_fmt_mplane(struct video_device *vfd, > + struct v4l2_pix_format_mplane *fmt) > +{ > + int i; > + > + dbgarg2("width=%d, height=%d, format=%c%c%c%c, field=%s, " > + "colorspace=%d, num_planes=%d\n", > + fmt->width, fmt->height, > + (fmt->pixelformat & 0xff), > + (fmt->pixelformat >> 8) & 0xff, > + (fmt->pixelformat >> 16) & 0xff, > + (fmt->pixelformat >> 24) & 0xff, > + prt_names(fmt->field, v4l2_field_names), > + fmt->colorspace, fmt->num_planes); > + > + for (i = 0; i < fmt->num_planes; ++i) > + dbgarg2("plane %d: bytesperline=%d sizeimage=%d\n", i, > + fmt->plane_fmt[i].bytesperline, > + fmt->plane_fmt[i].sizeimage); > +} > + > static inline void v4l_print_ext_ctrls(unsigned int cmd, > struct video_device *vfd, struct v4l2_ext_controls *c, int show_vals) > { > @@ -570,7 +604,12 @@ static int check_fmt(const struct v4l2_ioctl_ops *ops, enum v4l2_buf_type type) > > switch (type) { > case V4L2_BUF_TYPE_VIDEO_CAPTURE: > - if (ops->vidioc_g_fmt_vid_cap) > + if (ops->vidioc_g_fmt_vid_cap || > + ops->vidioc_g_fmt_vid_cap_mplane) > + return 0; > + break; > + case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: > + if (ops->vidioc_g_fmt_vid_cap_mplane) > return 0; > break; > case V4L2_BUF_TYPE_VIDEO_OVERLAY: > @@ -578,7 +617,12 @@ static int check_fmt(const struct v4l2_ioctl_ops *ops, enum v4l2_buf_type type) > return 0; > break; > case V4L2_BUF_TYPE_VIDEO_OUTPUT: > - if (ops->vidioc_g_fmt_vid_out) > + if (ops->vidioc_g_fmt_vid_out || > + ops->vidioc_g_fmt_vid_out_mplane) > + return 0; > + break; > + case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: > + if (ops->vidioc_g_fmt_vid_out_mplane) > return 0; > break; > case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: > @@ -609,12 +653,70 @@ static int check_fmt(const struct v4l2_ioctl_ops *ops, enum v4l2_buf_type type) > return -EINVAL; > } > > +/** > + * fmt_sp_to_mp() - Convert a single-plane format to its multi-planar 1-plane > + * equivalent > + */ > +static int fmt_sp_to_mp(const struct v4l2_format *f_sp, > + struct v4l2_format *f_mp) > +{ > + struct v4l2_pix_format_mplane *pix_mp = &f_mp->fmt.pix_mp; > + const struct v4l2_pix_format *pix = &f_sp->fmt.pix; > + > + if (f_sp->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) > + f_mp->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; > + else if (f_sp->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) > + f_mp->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; > + else > + return -EINVAL; > + > + pix_mp->width = pix->width; > + pix_mp->height = pix->height; > + pix_mp->pixelformat = pix->pixelformat; > + pix_mp->field = pix->field; > + pix_mp->colorspace = pix->colorspace; > + pix_mp->num_planes = 1; > + pix_mp->plane_fmt[0].sizeimage = pix->sizeimage; > + pix_mp->plane_fmt[0].bytesperline = pix->bytesperline; > + > + return 0; > +} > + > +/** > + * fmt_mp_to_sp() - Convert a multi-planar 1-plane format to its single-planar > + * equivalent > + */ > +static int fmt_mp_to_sp(const struct v4l2_format *f_mp, > + struct v4l2_format *f_sp) > +{ > + const struct v4l2_pix_format_mplane *pix_mp = &f_mp->fmt.pix_mp; > + struct v4l2_pix_format *pix = &f_sp->fmt.pix; > + > + if (f_mp->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) > + f_sp->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; > + else if (f_mp->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) > + f_sp->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; > + else > + return -EINVAL; > + > + pix->width = pix_mp->width; > + pix->height = pix_mp->height; > + pix->pixelformat = pix_mp->pixelformat; > + pix->field = pix_mp->field; > + pix->colorspace = pix_mp->colorspace; > + pix->sizeimage = pix_mp->plane_fmt[0].sizeimage; > + pix->bytesperline = pix_mp->plane_fmt[0].bytesperline; > + > + return 0; > +} > + > static long __video_do_ioctl(struct file *file, > unsigned int cmd, void *arg) > { > struct video_device *vfd = video_devdata(file); > const struct v4l2_ioctl_ops *ops = vfd->ioctl_ops; > void *fh = file->private_data; > + struct v4l2_format f_copy; > long ret = -EINVAL; > > if (ops == NULL) { > @@ -720,6 +822,11 @@ static long __video_do_ioctl(struct file *file, > if (ops->vidioc_enum_fmt_vid_cap) > ret = ops->vidioc_enum_fmt_vid_cap(file, fh, f); > break; > + case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: > + if (ops->vidioc_enum_fmt_vid_cap_mplane) > + ret = ops->vidioc_enum_fmt_vid_cap_mplane(file, > + fh, f); > + break; > case V4L2_BUF_TYPE_VIDEO_OVERLAY: > if (ops->vidioc_enum_fmt_vid_overlay) > ret = ops->vidioc_enum_fmt_vid_overlay(file, > @@ -729,6 +836,11 @@ static long __video_do_ioctl(struct file *file, > if (ops->vidioc_enum_fmt_vid_out) > ret = ops->vidioc_enum_fmt_vid_out(file, fh, f); > break; > + case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: > + if (ops->vidioc_enum_fmt_vid_out_mplane) > + ret = ops->vidioc_enum_fmt_vid_out_mplane(file, > + fh, f); > + break; > case V4L2_BUF_TYPE_PRIVATE: > if (ops->vidioc_enum_fmt_type_private) > ret = ops->vidioc_enum_fmt_type_private(file, > @@ -757,22 +869,79 @@ static long __video_do_ioctl(struct file *file, > > switch (f->type) { > case V4L2_BUF_TYPE_VIDEO_CAPTURE: > - if (ops->vidioc_g_fmt_vid_cap) > + if (ops->vidioc_g_fmt_vid_cap) { > ret = ops->vidioc_g_fmt_vid_cap(file, fh, f); > + } else if (ops->vidioc_g_fmt_vid_cap_mplane) { > + if (fmt_sp_to_mp(f, &f_copy)) > + break; > + ret = ops->vidioc_g_fmt_vid_cap_mplane(file, fh, > + &f_copy); > + /* Driver is currently in multi-planar format, > + * we can't return it in single-planar API*/ > + if (f_copy.fmt.pix_mp.num_planes > 1) { Only do this if ret == 0. > + ret = -EBUSY; > + break; > + } > + > + ret = fmt_mp_to_sp(&f_copy, f); Ditto: 'ret' is overwritten here. Same happens elsewhere as well. <snip> Regards, Hans -- Hans Verkuil - video4linux developer - sponsored by TANDBERG, part of Cisco -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html