From: Hans Verkuil <hans.verkuil@xxxxxxxxx> This is very useful for testing whether userspace can handle the various formats correctly. Signed-off-by: Hans Verkuil <hans.verkuil@xxxxxxxxx> --- drivers/media/video/vivi.c | 165 ++++++++++++++++++++++++++++++++++++-------- 1 file changed, 135 insertions(+), 30 deletions(-) diff --git a/drivers/media/video/vivi.c b/drivers/media/video/vivi.c index d64d482..2a0198f 100644 --- a/drivers/media/video/vivi.c +++ b/drivers/media/video/vivi.c @@ -95,6 +95,16 @@ static struct vivi_fmt formats[] = { .depth = 16, }, { + .name = "4:2:2, packed, YVYU", + .fourcc = V4L2_PIX_FMT_YVYU, + .depth = 16, + }, + { + .name = "4:2:2, packed, VYUY", + .fourcc = V4L2_PIX_FMT_VYUY, + .depth = 16, + }, + { .name = "RGB565 (LE)", .fourcc = V4L2_PIX_FMT_RGB565, /* gggbbbbb rrrrrggg */ .depth = 16, @@ -114,6 +124,26 @@ static struct vivi_fmt formats[] = { .fourcc = V4L2_PIX_FMT_RGB555X, /* arrrrrgg gggbbbbb */ .depth = 16, }, + { + .name = "RGB24 (LE)", + .fourcc = V4L2_PIX_FMT_RGB24, /* rgb */ + .depth = 24, + }, + { + .name = "RGB24 (BE)", + .fourcc = V4L2_PIX_FMT_BGR24, /* bgr */ + .depth = 24, + }, + { + .name = "RGB32 (LE)", + .fourcc = V4L2_PIX_FMT_RGB32, /* argb */ + .depth = 32, + }, + { + .name = "RGB32 (BE)", + .fourcc = V4L2_PIX_FMT_BGR32, /* bgra */ + .depth = 32, + }, }; static struct vivi_fmt *get_format(struct v4l2_format *f) @@ -204,8 +234,9 @@ struct vivi_dev { enum v4l2_field field; unsigned int field_count; - u8 bars[9][3]; - u8 line[MAX_WIDTH * 4]; + u8 bars[9][3]; + u8 line[MAX_WIDTH * 8]; + unsigned int pixelsize; }; /* ------------------------------------------------------------------ @@ -284,6 +315,8 @@ static void precalculate_bars(struct vivi_dev *dev) switch (dev->fmt->fourcc) { case V4L2_PIX_FMT_YUYV: case V4L2_PIX_FMT_UYVY: + case V4L2_PIX_FMT_YVYU: + case V4L2_PIX_FMT_VYUY: is_yuv = 1; break; case V4L2_PIX_FMT_RGB565: @@ -298,6 +331,11 @@ static void precalculate_bars(struct vivi_dev *dev) g >>= 3; b >>= 3; break; + case V4L2_PIX_FMT_RGB24: + case V4L2_PIX_FMT_BGR24: + case V4L2_PIX_FMT_RGB32: + case V4L2_PIX_FMT_BGR32: + break; } if (is_yuv) { @@ -317,7 +355,8 @@ static void precalculate_bars(struct vivi_dev *dev) #define TSTAMP_INPUT_X 10 #define TSTAMP_MIN_X (54 + TSTAMP_INPUT_X) -static void gen_twopix(struct vivi_dev *dev, u8 *buf, int colorpos) +/* 'odd' is true for pixels 1, 3, 5, etc. and false for pixels 0, 2, 4, etc. */ +static void gen_twopix(struct vivi_dev *dev, u8 *buf, int colorpos, bool odd) { u8 r_y, g_u, b_v; int color; @@ -327,46 +366,56 @@ static void gen_twopix(struct vivi_dev *dev, u8 *buf, int colorpos) g_u = dev->bars[colorpos][1]; /* G or precalculated U */ b_v = dev->bars[colorpos][2]; /* B or precalculated V */ - for (color = 0; color < 4; color++) { + for (color = 0; color < dev->pixelsize; color++) { p = buf + color; switch (dev->fmt->fourcc) { case V4L2_PIX_FMT_YUYV: switch (color) { case 0: - case 2: *p = r_y; break; case 1: - *p = g_u; - break; - case 3: - *p = b_v; + *p = odd ? b_v : g_u; break; } break; case V4L2_PIX_FMT_UYVY: switch (color) { + case 0: + *p = odd ? b_v : g_u; + break; case 1: - case 3: *p = r_y; break; + } + break; + case V4L2_PIX_FMT_YVYU: + switch (color) { + case 0: + *p = r_y; + break; + case 1: + *p = odd ? g_u : b_v; + break; + } + break; + case V4L2_PIX_FMT_VYUY: + switch (color) { case 0: - *p = g_u; + *p = odd ? g_u : b_v; break; - case 2: - *p = b_v; + case 1: + *p = r_y; break; } break; case V4L2_PIX_FMT_RGB565: switch (color) { case 0: - case 2: *p = (g_u << 5) | b_v; break; case 1: - case 3: *p = (r_y << 3) | (g_u >> 3); break; } @@ -374,11 +423,9 @@ static void gen_twopix(struct vivi_dev *dev, u8 *buf, int colorpos) case V4L2_PIX_FMT_RGB565X: switch (color) { case 0: - case 2: *p = (r_y << 3) | (g_u >> 3); break; case 1: - case 3: *p = (g_u << 5) | b_v; break; } @@ -386,11 +433,9 @@ static void gen_twopix(struct vivi_dev *dev, u8 *buf, int colorpos) case V4L2_PIX_FMT_RGB555: switch (color) { case 0: - case 2: *p = (g_u << 5) | b_v; break; case 1: - case 3: *p = (r_y << 2) | (g_u >> 3); break; } @@ -398,15 +443,71 @@ static void gen_twopix(struct vivi_dev *dev, u8 *buf, int colorpos) case V4L2_PIX_FMT_RGB555X: switch (color) { case 0: - case 2: *p = (r_y << 2) | (g_u >> 3); break; case 1: - case 3: *p = (g_u << 5) | b_v; break; } break; + case V4L2_PIX_FMT_RGB24: + switch (color) { + case 0: + *p = r_y; + break; + case 1: + *p = g_u; + break; + case 2: + *p = b_v; + break; + } + break; + case V4L2_PIX_FMT_BGR24: + switch (color) { + case 0: + *p = b_v; + break; + case 1: + *p = g_u; + break; + case 2: + *p = r_y; + break; + } + break; + case V4L2_PIX_FMT_RGB32: + switch (color) { + case 0: + *p = 0; + break; + case 1: + *p = r_y; + break; + case 2: + *p = g_u; + break; + case 3: + *p = b_v; + break; + } + break; + case V4L2_PIX_FMT_BGR32: + switch (color) { + case 0: + *p = b_v; + break; + case 1: + *p = g_u; + break; + case 2: + *p = r_y; + break; + case 3: + *p = 0; + break; + } + break; } } } @@ -415,10 +516,10 @@ static void precalculate_line(struct vivi_dev *dev) { int w; - for (w = 0; w < dev->width * 2; w += 2) { - int colorpos = (w / (dev->width / 8) % 8); + for (w = 0; w < dev->width * 2; w++) { + int colorpos = w / (dev->width / 8) % 8; - gen_twopix(dev, dev->line + w * 2, colorpos); + gen_twopix(dev, dev->line + w * dev->pixelsize, colorpos, w & 1); } } @@ -434,7 +535,7 @@ static void gen_text(struct vivi_dev *dev, char *basep, /* Print stream time */ for (line = y; line < y + 16; line++) { int j = 0; - char *pos = basep + line * dev->width * 2 + x * 2; + char *pos = basep + line * dev->width * dev->pixelsize + x * dev->pixelsize; char *s; for (s = text; *s; s++) { @@ -444,9 +545,9 @@ static void gen_text(struct vivi_dev *dev, char *basep, for (i = 0; i < 7; i++, j++) { /* Draw white font on black background */ if (chr & (1 << (7 - i))) - gen_twopix(dev, pos + j * 2, WHITE); + gen_twopix(dev, pos + j * dev->pixelsize, WHITE, (x+y) & 1); else - gen_twopix(dev, pos + j * 2, TEXT_BLACK); + gen_twopix(dev, pos + j * dev->pixelsize, TEXT_BLACK, (x+y) & 1); } } } @@ -467,7 +568,9 @@ static void vivi_fillbuff(struct vivi_dev *dev, struct vivi_buffer *buf) return; for (h = 0; h < hmax; h++) - memcpy(vbuf + h * wmax * 2, dev->line + (dev->mv_count % wmax) * 2, wmax * 2); + memcpy(vbuf + h * wmax * dev->pixelsize, + dev->line + (dev->mv_count % wmax) * dev->pixelsize, + wmax * dev->pixelsize); /* Updates stream time */ @@ -662,7 +765,7 @@ static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt, struct vivi_dev *dev = vb2_get_drv_priv(vq); unsigned long size; - size = dev->width * dev->height * 2; + size = dev->width * dev->height * dev->pixelsize; if (0 == *nbuffers) *nbuffers = 32; @@ -726,7 +829,7 @@ static int buffer_prepare(struct vb2_buffer *vb) dev->height < 32 || dev->height > MAX_HEIGHT) return -EINVAL; - size = dev->width * dev->height * 2; + size = dev->width * dev->height * dev->pixelsize; if (vb2_plane_size(vb, 0) < size) { dprintk(dev, 1, "%s data will not fit into plane (%lu < %lu)\n", __func__, vb2_plane_size(vb, 0), size); @@ -920,6 +1023,7 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, } dev->fmt = get_format(f); + dev->pixelsize = dev->fmt->depth / 8; dev->width = f->fmt.pix.width; dev->height = f->fmt.pix.height; dev->field = f->fmt.pix.field; @@ -1266,6 +1370,7 @@ static int __init vivi_create_instance(int inst) dev->fmt = &formats[0]; dev->width = 640; dev->height = 480; + dev->pixelsize = dev->fmt->depth / 8; hdl = &dev->ctrl_handler; v4l2_ctrl_handler_init(hdl, 11); dev->volume = v4l2_ctrl_new_std(hdl, &vivi_ctrl_ops, -- 1.7.10 -- 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