Message ID | 7fd6ccf110b7c167a2304ffd482e6c04252c4909.1549028130.git.mchehab+samsung@kernel.org (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | media: vim2m: add bayer capture formats | expand |
Hi Mauro, On Fri, Feb 1, 2019 at 11:19 PM Mauro Carvalho Chehab <mchehab+samsung@kernel.org> wrote: > > The vim2m device is interesting to simulate a webcam. Hmm, how would you simulate a webcam with a mem2mem device? The same process needs to control both OUTPUT and CAPTURE queues, so regular webcam apps wouldn't work. Best regards, Tomasz > As most > sensors are arranged using bayer formats, the best is to support > to output data using those formats. > > So, add support for them. > > All 4 8-bit bayer formats tested with: > > $ qvidcap -p & > $ v4l2-ctl --stream-mmap --stream-out-mmap --stream-to-host localhost --stream-lossless --stream-out-hor-speed 1 -v pixelformat=RGGB > > Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org> > --- > drivers/media/platform/vim2m.c | 97 ++++++++++++++++++++++++++++++++-- > 1 file changed, 92 insertions(+), 5 deletions(-) > > diff --git a/drivers/media/platform/vim2m.c b/drivers/media/platform/vim2m.c > index e31c14c7d37f..6240878def80 100644 > --- a/drivers/media/platform/vim2m.c > +++ b/drivers/media/platform/vim2m.c > @@ -82,24 +82,47 @@ static struct platform_device vim2m_pdev = { > struct vim2m_fmt { > u32 fourcc; > int depth; > + /* Types the format can be used for */ > + u32 types; > }; > > static struct vim2m_fmt formats[] = { > { > .fourcc = V4L2_PIX_FMT_RGB565, /* rrrrrggg gggbbbbb */ > .depth = 16, > + .types = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT, > }, { > .fourcc = V4L2_PIX_FMT_RGB565X, /* gggbbbbb rrrrrggg */ > .depth = 16, > + .types = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT, > }, { > .fourcc = V4L2_PIX_FMT_RGB24, > .depth = 24, > + .types = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT, > }, { > .fourcc = V4L2_PIX_FMT_BGR24, > .depth = 24, > + .types = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT, > }, { > .fourcc = V4L2_PIX_FMT_YUYV, > .depth = 16, > + .types = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT, > + }, { > + .fourcc = V4L2_PIX_FMT_SBGGR8, > + .depth = 8, > + .types = MEM2MEM_CAPTURE, > + }, { > + .fourcc = V4L2_PIX_FMT_SGBRG8, > + .depth = 8, > + .types = MEM2MEM_CAPTURE, > + }, { > + .fourcc = V4L2_PIX_FMT_SGRBG8, > + .depth = 8, > + .types = MEM2MEM_CAPTURE, > + }, { > + .fourcc = V4L2_PIX_FMT_SRGGB8, > + .depth = 8, > + .types = MEM2MEM_CAPTURE, > }, > }; > > @@ -208,7 +231,7 @@ static struct vim2m_q_data *get_q_data(struct vim2m_ctx *ctx, > (u8)(((__color) > 0xff) ? 0xff : (((__color) < 0) ? 0 : (__color))) > > static void copy_two_pixels(struct vim2m_fmt *in, struct vim2m_fmt *out, > - u8 **src, u8 **dst, bool reverse) > + u8 **src, u8 **dst, int y, bool reverse) > { > u8 _r[2], _g[2], _b[2], *r, *g, *b; > int i, step; > @@ -379,7 +402,8 @@ static void copy_two_pixels(struct vim2m_fmt *in, struct vim2m_fmt *out, > *(*dst)++ = *r++; > } > return; > - default: /* V4L2_PIX_FMT_YUYV */ > + case V4L2_PIX_FMT_YUYV: > + default: > { > u8 y, y1, u, v; > > @@ -399,6 +423,42 @@ static void copy_two_pixels(struct vim2m_fmt *in, struct vim2m_fmt *out, > *(*dst)++ = v; > return; > } > + case V4L2_PIX_FMT_SBGGR8: > + if (!(y & 1)) { > + *(*dst)++ = *b; > + *(*dst)++ = *++g; > + } else { > + *(*dst)++ = *g; > + *(*dst)++ = *++r; > + } > + return; > + case V4L2_PIX_FMT_SGBRG8: > + if (!(y & 1)) { > + *(*dst)++ = *g; > + *(*dst)++ = *++b; > + } else { > + *(*dst)++ = *r; > + *(*dst)++ = *++g; > + } > + return; > + case V4L2_PIX_FMT_SGRBG8: > + if (!(y & 1)) { > + *(*dst)++ = *g; > + *(*dst)++ = *++r; > + } else { > + *(*dst)++ = *b; > + *(*dst)++ = *++g; > + } > + return; > + case V4L2_PIX_FMT_SRGGB8: > + if (!(y & 1)) { > + *(*dst)++ = *r; > + *(*dst)++ = *++g; > + } else { > + *(*dst)++ = *g; > + *(*dst)++ = *++b; > + } > + return; > } > } > > @@ -449,7 +509,7 @@ static int device_process(struct vim2m_ctx *ctx, > p += bytesperline - (q_data_in->fmt->depth >> 3); > > for (x = 0; x < width >> 1; x++) > - copy_two_pixels(in, out, &p, &p_out, > + copy_two_pixels(in, out, &p, &p_out, y, > ctx->mode & MEM2MEM_HFLIP); > } > > @@ -562,11 +622,25 @@ static int vidioc_querycap(struct file *file, void *priv, > > static int enum_fmt(struct v4l2_fmtdesc *f, u32 type) > { > + int i, num; > struct vim2m_fmt *fmt; > > - if (f->index < NUM_FORMATS) { > + num = 0; > + > + for (i = 0; i < NUM_FORMATS; ++i) { > + if (formats[i].types & type) { > + /* index-th format of type type found ? */ > + if (num == f->index) > + break; > + /* Correct type but haven't reached our index yet, > + * just increment per-type index */ > + ++num; > + } > + } > + > + if (i < NUM_FORMATS) { > /* Format found */ > - fmt = &formats[f->index]; > + fmt = &formats[i]; > f->pixelformat = fmt->fourcc; > return 0; > } > @@ -657,6 +731,12 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, > f->fmt.pix.pixelformat = formats[0].fourcc; > fmt = find_format(f); > } > + if (!(fmt->types & MEM2MEM_CAPTURE)) { > + v4l2_err(&ctx->dev->v4l2_dev, > + "Fourcc format (0x%08x) invalid.\n", > + f->fmt.pix.pixelformat); > + return -EINVAL; > + } > f->fmt.pix.colorspace = ctx->colorspace; > f->fmt.pix.xfer_func = ctx->xfer_func; > f->fmt.pix.ycbcr_enc = ctx->ycbcr_enc; > @@ -669,12 +749,19 @@ static int vidioc_try_fmt_vid_out(struct file *file, void *priv, > struct v4l2_format *f) > { > struct vim2m_fmt *fmt; > + struct vim2m_ctx *ctx = file2ctx(file); > > fmt = find_format(f); > if (!fmt) { > f->fmt.pix.pixelformat = formats[0].fourcc; > fmt = find_format(f); > } > + if (!(fmt->types & MEM2MEM_OUTPUT)) { > + v4l2_err(&ctx->dev->v4l2_dev, > + "Fourcc format (0x%08x) invalid.\n", > + f->fmt.pix.pixelformat); > + return -EINVAL; > + } > if (!f->fmt.pix.colorspace) > f->fmt.pix.colorspace = V4L2_COLORSPACE_REC709; > > -- > 2.20.1 >
diff --git a/drivers/media/platform/vim2m.c b/drivers/media/platform/vim2m.c index e31c14c7d37f..6240878def80 100644 --- a/drivers/media/platform/vim2m.c +++ b/drivers/media/platform/vim2m.c @@ -82,24 +82,47 @@ static struct platform_device vim2m_pdev = { struct vim2m_fmt { u32 fourcc; int depth; + /* Types the format can be used for */ + u32 types; }; static struct vim2m_fmt formats[] = { { .fourcc = V4L2_PIX_FMT_RGB565, /* rrrrrggg gggbbbbb */ .depth = 16, + .types = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT, }, { .fourcc = V4L2_PIX_FMT_RGB565X, /* gggbbbbb rrrrrggg */ .depth = 16, + .types = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT, }, { .fourcc = V4L2_PIX_FMT_RGB24, .depth = 24, + .types = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT, }, { .fourcc = V4L2_PIX_FMT_BGR24, .depth = 24, + .types = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT, }, { .fourcc = V4L2_PIX_FMT_YUYV, .depth = 16, + .types = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT, + }, { + .fourcc = V4L2_PIX_FMT_SBGGR8, + .depth = 8, + .types = MEM2MEM_CAPTURE, + }, { + .fourcc = V4L2_PIX_FMT_SGBRG8, + .depth = 8, + .types = MEM2MEM_CAPTURE, + }, { + .fourcc = V4L2_PIX_FMT_SGRBG8, + .depth = 8, + .types = MEM2MEM_CAPTURE, + }, { + .fourcc = V4L2_PIX_FMT_SRGGB8, + .depth = 8, + .types = MEM2MEM_CAPTURE, }, }; @@ -208,7 +231,7 @@ static struct vim2m_q_data *get_q_data(struct vim2m_ctx *ctx, (u8)(((__color) > 0xff) ? 0xff : (((__color) < 0) ? 0 : (__color))) static void copy_two_pixels(struct vim2m_fmt *in, struct vim2m_fmt *out, - u8 **src, u8 **dst, bool reverse) + u8 **src, u8 **dst, int y, bool reverse) { u8 _r[2], _g[2], _b[2], *r, *g, *b; int i, step; @@ -379,7 +402,8 @@ static void copy_two_pixels(struct vim2m_fmt *in, struct vim2m_fmt *out, *(*dst)++ = *r++; } return; - default: /* V4L2_PIX_FMT_YUYV */ + case V4L2_PIX_FMT_YUYV: + default: { u8 y, y1, u, v; @@ -399,6 +423,42 @@ static void copy_two_pixels(struct vim2m_fmt *in, struct vim2m_fmt *out, *(*dst)++ = v; return; } + case V4L2_PIX_FMT_SBGGR8: + if (!(y & 1)) { + *(*dst)++ = *b; + *(*dst)++ = *++g; + } else { + *(*dst)++ = *g; + *(*dst)++ = *++r; + } + return; + case V4L2_PIX_FMT_SGBRG8: + if (!(y & 1)) { + *(*dst)++ = *g; + *(*dst)++ = *++b; + } else { + *(*dst)++ = *r; + *(*dst)++ = *++g; + } + return; + case V4L2_PIX_FMT_SGRBG8: + if (!(y & 1)) { + *(*dst)++ = *g; + *(*dst)++ = *++r; + } else { + *(*dst)++ = *b; + *(*dst)++ = *++g; + } + return; + case V4L2_PIX_FMT_SRGGB8: + if (!(y & 1)) { + *(*dst)++ = *r; + *(*dst)++ = *++g; + } else { + *(*dst)++ = *g; + *(*dst)++ = *++b; + } + return; } } @@ -449,7 +509,7 @@ static int device_process(struct vim2m_ctx *ctx, p += bytesperline - (q_data_in->fmt->depth >> 3); for (x = 0; x < width >> 1; x++) - copy_two_pixels(in, out, &p, &p_out, + copy_two_pixels(in, out, &p, &p_out, y, ctx->mode & MEM2MEM_HFLIP); } @@ -562,11 +622,25 @@ static int vidioc_querycap(struct file *file, void *priv, static int enum_fmt(struct v4l2_fmtdesc *f, u32 type) { + int i, num; struct vim2m_fmt *fmt; - if (f->index < NUM_FORMATS) { + num = 0; + + for (i = 0; i < NUM_FORMATS; ++i) { + if (formats[i].types & type) { + /* index-th format of type type found ? */ + if (num == f->index) + break; + /* Correct type but haven't reached our index yet, + * just increment per-type index */ + ++num; + } + } + + if (i < NUM_FORMATS) { /* Format found */ - fmt = &formats[f->index]; + fmt = &formats[i]; f->pixelformat = fmt->fourcc; return 0; } @@ -657,6 +731,12 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, f->fmt.pix.pixelformat = formats[0].fourcc; fmt = find_format(f); } + if (!(fmt->types & MEM2MEM_CAPTURE)) { + v4l2_err(&ctx->dev->v4l2_dev, + "Fourcc format (0x%08x) invalid.\n", + f->fmt.pix.pixelformat); + return -EINVAL; + } f->fmt.pix.colorspace = ctx->colorspace; f->fmt.pix.xfer_func = ctx->xfer_func; f->fmt.pix.ycbcr_enc = ctx->ycbcr_enc; @@ -669,12 +749,19 @@ static int vidioc_try_fmt_vid_out(struct file *file, void *priv, struct v4l2_format *f) { struct vim2m_fmt *fmt; + struct vim2m_ctx *ctx = file2ctx(file); fmt = find_format(f); if (!fmt) { f->fmt.pix.pixelformat = formats[0].fourcc; fmt = find_format(f); } + if (!(fmt->types & MEM2MEM_OUTPUT)) { + v4l2_err(&ctx->dev->v4l2_dev, + "Fourcc format (0x%08x) invalid.\n", + f->fmt.pix.pixelformat); + return -EINVAL; + } if (!f->fmt.pix.colorspace) f->fmt.pix.colorspace = V4L2_COLORSPACE_REC709;
The vim2m device is interesting to simulate a webcam. As most sensors are arranged using bayer formats, the best is to support to output data using those formats. So, add support for them. All 4 8-bit bayer formats tested with: $ qvidcap -p & $ v4l2-ctl --stream-mmap --stream-out-mmap --stream-to-host localhost --stream-lossless --stream-out-hor-speed 1 -v pixelformat=RGGB Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org> --- drivers/media/platform/vim2m.c | 97 ++++++++++++++++++++++++++++++++-- 1 file changed, 92 insertions(+), 5 deletions(-)