diff options
author | Simon Farnsworth <simon.farnsworth@onelan.co.uk> | 2011-05-03 08:57:40 -0300 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2011-05-20 09:30:22 -0300 |
commit | 1bf5842fe3b61d2dbbced96dbd27ad26fe93444a (patch) | |
tree | 26c19327c2668ca8690e3a47b0846f9825beb991 /drivers/media/video/cx18/cx18-ioctl.c | |
parent | 81dfea886c73ea36439672b90626a354354dadd2 (diff) |
[media] cx18: Clean up mmap() support for raw YUV
The initial version of this patch (commit
d5976931639176bb6777755d96b9f8d959f79e9e) had some issues:
* It didn't correctly calculate the size of the YUV buffer for 4:2:2,
resulting in capture sometimes being offset by 1/3rd of a picture.
* There were a lot of variables duplicating information the driver
already knew, which have been removed.
* There was an in-kernel format conversion - libv4l can do this one,
and is the right place to do format conversions anyway.
* Some magic numbers weren't properly explained.
Fix all these issues, leaving just the move from videobuf to videobuf2
to do.
Signed-off-by: Simon Farnsworth <simon.farnsworth@onelan.co.uk>
Acked-by: Andy Walls <awalls@md.metrocast.net>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/cx18/cx18-ioctl.c')
-rw-r--r-- | drivers/media/video/cx18/cx18-ioctl.c | 84 |
1 files changed, 50 insertions, 34 deletions
diff --git a/drivers/media/video/cx18/cx18-ioctl.c b/drivers/media/video/cx18/cx18-ioctl.c index 777d7265c8a8..1933d4d11bf2 100644 --- a/drivers/media/video/cx18/cx18-ioctl.c +++ b/drivers/media/video/cx18/cx18-ioctl.c @@ -41,18 +41,6 @@ #include <media/tveeprom.h> #include <media/v4l2-chip-ident.h> -static struct v4l2_fmtdesc formats[] = { - { 0, V4L2_BUF_TYPE_VIDEO_CAPTURE, 0, - "HM12 (YUV 4:1:1)", V4L2_PIX_FMT_HM12, { 0, 0, 0, 0 } - }, - { 1, V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FMT_FLAG_COMPRESSED, - "MPEG", V4L2_PIX_FMT_MPEG, { 0, 0, 0, 0 } - }, - { 2, V4L2_BUF_TYPE_VIDEO_CAPTURE, 0, - "YUYV 4:2:2", V4L2_PIX_FMT_YUYV, { 0, 0, 0, 0 } - }, -}; - u16 cx18_service2vbi(int type) { switch (type) { @@ -172,8 +160,12 @@ static int cx18_g_fmt_vid_cap(struct file *file, void *fh, pixfmt->priv = 0; if (id->type == CX18_ENC_STREAM_TYPE_YUV) { pixfmt->pixelformat = s->pixelformat; - /* YUV size is (Y=(h*720) + UV=(h*(720/2))) */ - pixfmt->sizeimage = pixfmt->height * 720 * 3 / 2; + /* HM12 YUV size is (Y=(h*720) + UV=(h*(720/2))) + UYUV YUV size is (Y=(h*720) + UV=(h*(720))) */ + if (s->pixelformat == V4L2_PIX_FMT_HM12) + pixfmt->sizeimage = pixfmt->height * 720 * 3 / 2; + else + pixfmt->sizeimage = pixfmt->height * 720 * 2; pixfmt->bytesperline = 720; } else { pixfmt->pixelformat = V4L2_PIX_FMT_MPEG; @@ -296,16 +288,15 @@ static int cx18_s_fmt_vid_cap(struct file *file, void *fh, w = fmt->fmt.pix.width; h = fmt->fmt.pix.height; - s->pixelformat = fmt->fmt.pix.pixelformat; - s->vbheight = h; - s->vbwidth = w; - - if (cx->cxhdl.width == w && cx->cxhdl.height == h) + if (cx->cxhdl.width == w && cx->cxhdl.height == h && + s->pixelformat == fmt->fmt.pix.pixelformat) return 0; if (atomic_read(&cx->ana_capturing) > 0) return -EBUSY; + s->pixelformat = fmt->fmt.pix.pixelformat; + mbus_fmt.width = cx->cxhdl.width = w; mbus_fmt.height = cx->cxhdl.height = h; mbus_fmt.code = V4L2_MBUS_FMT_FIXED; @@ -557,6 +548,18 @@ static int cx18_g_crop(struct file *file, void *fh, struct v4l2_crop *crop) static int cx18_enum_fmt_vid_cap(struct file *file, void *fh, struct v4l2_fmtdesc *fmt) { + static const struct v4l2_fmtdesc formats[] = { + { 0, V4L2_BUF_TYPE_VIDEO_CAPTURE, 0, + "HM12 (YUV 4:1:1)", V4L2_PIX_FMT_HM12, { 0, 0, 0, 0 } + }, + { 1, V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FMT_FLAG_COMPRESSED, + "MPEG", V4L2_PIX_FMT_MPEG, { 0, 0, 0, 0 } + }, + { 2, V4L2_BUF_TYPE_VIDEO_CAPTURE, 0, + "UYVY 4:2:2", V4L2_PIX_FMT_UYVY, { 0, 0, 0, 0 } + }, + }; + if (fmt->index > ARRAY_SIZE(formats) - 1) return -EINVAL; *fmt = formats[fmt->index]; @@ -874,10 +877,12 @@ static int cx18_g_enc_index(struct file *file, void *fh, static struct videobuf_queue *cx18_vb_queue(struct cx18_open_id *id) { struct videobuf_queue *q = NULL; + struct cx18 *cx = id->cx; + struct cx18_stream *s = &cx->streams[id->type]; - switch (id->vb_type) { + switch (s->vb_type) { case V4L2_BUF_TYPE_VIDEO_CAPTURE: - q = &id->vbuf_q; + q = &s->vbuf_q; break; case V4L2_BUF_TYPE_VBI_CAPTURE: break; @@ -895,15 +900,15 @@ static int cx18_streamon(struct file *file, void *priv, struct cx18_stream *s = &cx->streams[id->type]; /* Start the hardware only if we're the video device */ - if ((id->vb_type != V4L2_BUF_TYPE_VIDEO_CAPTURE) && - (id->vb_type != V4L2_BUF_TYPE_VBI_CAPTURE)) + if ((s->vb_type != V4L2_BUF_TYPE_VIDEO_CAPTURE) && + (s->vb_type != V4L2_BUF_TYPE_VBI_CAPTURE)) return -EINVAL; if (id->type != CX18_ENC_STREAM_TYPE_YUV) return -EINVAL; /* Establish a buffer timeout */ - mod_timer(&s->vb_timeout, jiffies + (HZ * 2)); + mod_timer(&s->vb_timeout, msecs_to_jiffies(2000) + jiffies); return videobuf_streamon(cx18_vb_queue(id)); } @@ -912,10 +917,12 @@ static int cx18_streamoff(struct file *file, void *priv, enum v4l2_buf_type type) { struct cx18_open_id *id = file->private_data; + struct cx18 *cx = id->cx; + struct cx18_stream *s = &cx->streams[id->type]; /* Start the hardware only if we're the video device */ - if ((id->vb_type != V4L2_BUF_TYPE_VIDEO_CAPTURE) && - (id->vb_type != V4L2_BUF_TYPE_VBI_CAPTURE)) + if ((s->vb_type != V4L2_BUF_TYPE_VIDEO_CAPTURE) && + (s->vb_type != V4L2_BUF_TYPE_VBI_CAPTURE)) return -EINVAL; if (id->type != CX18_ENC_STREAM_TYPE_YUV) @@ -928,9 +935,11 @@ static int cx18_reqbufs(struct file *file, void *priv, struct v4l2_requestbuffers *rb) { struct cx18_open_id *id = file->private_data; + struct cx18 *cx = id->cx; + struct cx18_stream *s = &cx->streams[id->type]; - if ((id->vb_type != V4L2_BUF_TYPE_VIDEO_CAPTURE) && - (id->vb_type != V4L2_BUF_TYPE_VBI_CAPTURE)) + if ((s->vb_type != V4L2_BUF_TYPE_VIDEO_CAPTURE) && + (s->vb_type != V4L2_BUF_TYPE_VBI_CAPTURE)) return -EINVAL; return videobuf_reqbufs(cx18_vb_queue(id), rb); @@ -940,9 +949,11 @@ static int cx18_querybuf(struct file *file, void *priv, struct v4l2_buffer *b) { struct cx18_open_id *id = file->private_data; + struct cx18 *cx = id->cx; + struct cx18_stream *s = &cx->streams[id->type]; - if ((id->vb_type != V4L2_BUF_TYPE_VIDEO_CAPTURE) && - (id->vb_type != V4L2_BUF_TYPE_VBI_CAPTURE)) + if ((s->vb_type != V4L2_BUF_TYPE_VIDEO_CAPTURE) && + (s->vb_type != V4L2_BUF_TYPE_VBI_CAPTURE)) return -EINVAL; return videobuf_querybuf(cx18_vb_queue(id), b); @@ -951,9 +962,11 @@ static int cx18_querybuf(struct file *file, void *priv, static int cx18_qbuf(struct file *file, void *priv, struct v4l2_buffer *b) { struct cx18_open_id *id = file->private_data; + struct cx18 *cx = id->cx; + struct cx18_stream *s = &cx->streams[id->type]; - if ((id->vb_type != V4L2_BUF_TYPE_VIDEO_CAPTURE) && - (id->vb_type != V4L2_BUF_TYPE_VBI_CAPTURE)) + if ((s->vb_type != V4L2_BUF_TYPE_VIDEO_CAPTURE) && + (s->vb_type != V4L2_BUF_TYPE_VBI_CAPTURE)) return -EINVAL; return videobuf_qbuf(cx18_vb_queue(id), b); @@ -962,8 +975,11 @@ static int cx18_qbuf(struct file *file, void *priv, struct v4l2_buffer *b) static int cx18_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b) { struct cx18_open_id *id = file->private_data; - if ((id->vb_type != V4L2_BUF_TYPE_VIDEO_CAPTURE) && - (id->vb_type != V4L2_BUF_TYPE_VBI_CAPTURE)) + struct cx18 *cx = id->cx; + struct cx18_stream *s = &cx->streams[id->type]; + + if ((s->vb_type != V4L2_BUF_TYPE_VIDEO_CAPTURE) && + (s->vb_type != V4L2_BUF_TYPE_VBI_CAPTURE)) return -EINVAL; return videobuf_dqbuf(cx18_vb_queue(id), b, file->f_flags & O_NONBLOCK); |