* [PATCH] libv4l: add support for RGB565 format
@ 2009-07-03 2:19 Mauro Carvalho Chehab
2009-07-03 9:01 ` Hans de Goede
0 siblings, 1 reply; 2+ messages in thread
From: Mauro Carvalho Chehab @ 2009-07-03 2:19 UTC (permalink / raw)
To: Hans de Goede; +Cc: Linux Media Mailing List
Currently, em28xx driver outputs webcams only at RGB565 format. However,
several webcam applications don't support this format.
In order to properly work with those applications, a RGB565 handler should be
added at libv4l.
Tested with Silvercrest 1.3 mpix with v4l2grab (V4L2, with native libv4l
support) and two LD_PRELOAD applications: camorama (V4L1 API) and skype (using compat32).
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
diff --git a/v4l2-apps/libv4l/libv4lconvert/libv4lconvert-priv.h b/v4l2-apps/libv4l/libv4lconvert/libv4lconvert-priv.h
--- a/v4l2-apps/libv4l/libv4lconvert/libv4lconvert-priv.h
+++ b/v4l2-apps/libv4l/libv4lconvert/libv4lconvert-priv.h
@@ -184,6 +184,15 @@ void v4lconvert_swap_rgb(const unsigned
void v4lconvert_swap_uv(const unsigned char *src, unsigned char *dst,
const struct v4l2_format *src_fmt);
+void v4lconvert_rgb565_to_rgb24(const unsigned char *src, unsigned char *dest,
+ int width, int height);
+
+void v4lconvert_rgb565_to_bgr24(const unsigned char *src, unsigned char *dest,
+ int width, int height);
+
+void v4lconvert_rgb565_to_yuv420(const unsigned char *src, unsigned char *dest,
+ const struct v4l2_format *src_fmt, int yvu);
+
void v4lconvert_spca501_to_yuv420(const unsigned char *src, unsigned char *dst,
int width, int height, int yvu);
diff --git a/v4l2-apps/libv4l/libv4lconvert/libv4lconvert.c b/v4l2-apps/libv4l/libv4lconvert/libv4lconvert.c
--- a/v4l2-apps/libv4l/libv4lconvert/libv4lconvert.c
+++ b/v4l2-apps/libv4l/libv4lconvert/libv4lconvert.c
@@ -46,6 +46,7 @@ static const struct v4lconvert_pixfmt su
{ V4L2_PIX_FMT_YUYV, 0 },
{ V4L2_PIX_FMT_YVYU, 0 },
{ V4L2_PIX_FMT_UYVY, 0 },
+ { V4L2_PIX_FMT_RGB565, 0 },
{ V4L2_PIX_FMT_SN9C20X_I420, V4LCONVERT_NEEDS_CONVERSION },
{ V4L2_PIX_FMT_SBGGR8, V4LCONVERT_NEEDS_CONVERSION },
{ V4L2_PIX_FMT_SGBRG8, V4LCONVERT_NEEDS_CONVERSION },
@@ -787,6 +788,23 @@ static int v4lconvert_convert_pixfmt(str
}
break;
+ case V4L2_PIX_FMT_RGB565:
+ switch (dest_pix_fmt) {
+ case V4L2_PIX_FMT_RGB24:
+ v4lconvert_rgb565_to_rgb24(src, dest, width, height);
+ break;
+ case V4L2_PIX_FMT_BGR24:
+ v4lconvert_rgb565_to_bgr24(src, dest, width, height);
+ break;
+ case V4L2_PIX_FMT_YUV420:
+ v4lconvert_rgb565_to_yuv420(src, dest, fmt, 0);
+ break;
+ case V4L2_PIX_FMT_YVU420:
+ v4lconvert_rgb565_to_yuv420(src, dest, fmt, 1);
+ break;
+ }
+ break;
+
case V4L2_PIX_FMT_RGB24:
switch (dest_pix_fmt) {
case V4L2_PIX_FMT_BGR24:
diff --git a/v4l2-apps/libv4l/libv4lconvert/rgbyuv.c b/v4l2-apps/libv4l/libv4lconvert/rgbyuv.c
--- a/v4l2-apps/libv4l/libv4lconvert/rgbyuv.c
+++ b/v4l2-apps/libv4l/libv4lconvert/rgbyuv.c
@@ -1,8 +1,10 @@
/*
# RGB <-> YUV conversion routines
+# (C) 2008 Hans de Goede <j.w.r.degoede@hhs.nl>
-# (C) 2008 Hans de Goede <j.w.r.degoede@hhs.nl>
+# RGB565 conversion routines
+# (C) 2009 Mauro Carvalho Chehab <mchehab@redhat.com>
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
@@ -472,3 +474,103 @@ void v4lconvert_swap_uv(const unsigned c
src += src_fmt->fmt.pix.bytesperline / 2;
}
}
+
+void v4lconvert_rgb565_to_rgb24(const unsigned char *src, unsigned char *dest,
+ int width, int height)
+{
+ int j;
+ while (--height >= 0) {
+ for (j = 0; j < width; j++) {
+ unsigned short tmp = *(unsigned short *)src;
+
+ /* Original format: rrrrrggg gggbbbbb */
+ *dest++ = 0xf8 & (tmp >> 8);
+ *dest++ = 0xfc & (tmp >> 3);
+ *dest++ = 0xf8 & (tmp << 3);
+
+ src += 2;
+ }
+ }
+}
+
+void v4lconvert_rgb565_to_bgr24(const unsigned char *src, unsigned char *dest,
+ int width, int height)
+{
+ int j;
+ while (--height >= 0) {
+ for (j = 0; j < width; j++) {
+ unsigned short tmp = *(unsigned short *)src;
+
+ /* Original format: rrrrrggg gggbbbbb */
+ *dest++ = 0xf8 & (tmp << 3);
+ *dest++ = 0xfc & (tmp >> 3);
+ *dest++ = 0xf8 & (tmp >> 8);
+
+ src += 2;
+ }
+ }
+}
+
+void v4lconvert_rgb565_to_yuv420(const unsigned char *src, unsigned char *dest,
+ const struct v4l2_format *src_fmt, int yvu)
+{
+ int x, y;
+ unsigned short tmp;
+ unsigned char *udest, *vdest;
+ unsigned r[4], g[4], b[4];
+ int avg_src[3];
+
+ /* Y */
+ for (y = 0; y < src_fmt->fmt.pix.height; y++) {
+ for (x = 0; x < src_fmt->fmt.pix.width; x++) {
+ tmp = *(unsigned short *)src;
+ r[0] = 0xf8 & (tmp << 3);
+ g[0] = 0xfc & (tmp >> 3);
+ b[0] = 0xf8 & (tmp >> 8);
+ RGB2Y(r[0], g[0], b[0], *dest++);
+ src += 2;
+ }
+ src += src_fmt->fmt.pix.bytesperline - 2 * src_fmt->fmt.pix.width;
+ }
+ src -= src_fmt->fmt.pix.height * src_fmt->fmt.pix.bytesperline;
+
+ /* U + V */
+ if (yvu) {
+ vdest = dest;
+ udest = dest + src_fmt->fmt.pix.width * src_fmt->fmt.pix.height / 4;
+ } else {
+ udest = dest;
+ vdest = dest + src_fmt->fmt.pix.width * src_fmt->fmt.pix.height / 4;
+ }
+
+ for (y = 0; y < src_fmt->fmt.pix.height / 2; y++) {
+ for (x = 0; x < src_fmt->fmt.pix.width / 2; x++) {
+ tmp = *(unsigned short *)src;
+ r[0] = 0xf8 & (tmp << 3);
+ g[0] = 0xfc & (tmp >> 3);
+ b[0] = 0xf8 & (tmp >> 8);
+
+ tmp = *(((unsigned short *)src) + 1);
+ r[1] = 0xf8 & (tmp << 3);
+ g[1] = 0xfc & (tmp >> 3);
+ b[1] = 0xf8 & (tmp >> 8);
+
+ tmp = *(((unsigned short *)src) + src_fmt->fmt.pix.bytesperline);
+ r[2] = 0xf8 & (tmp << 3);
+ g[2] = 0xfc & (tmp >> 3);
+ b[2] = 0xf8 & (tmp >> 8);
+
+ tmp = *(((unsigned short *)src) + src_fmt->fmt.pix.bytesperline + 1);
+ r[3] = 0xf8 & (tmp << 3);
+ g[3] = 0xfc & (tmp >> 3);
+ b[3] = 0xf8 & (tmp >> 8);
+
+ avg_src[0] = (r[0] + r[1] + r[2] + r[3]) /4;
+ avg_src[1] = (g[0] + g[1] + g[2] + g[3]) /4;
+ avg_src[2] = (b[0] + b[1] + b[2] + b[3]) /4;
+ RGB2UV(avg_src[0], avg_src[1], avg_src[2], *udest++, *vdest++);
+ src += 4;
+ }
+ src += 2 * src_fmt->fmt.pix.bytesperline - 2 * src_fmt->fmt.pix.width;
+ }
+}
--
Cheers,
Mauro
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: [PATCH] libv4l: add support for RGB565 format
2009-07-03 2:19 [PATCH] libv4l: add support for RGB565 format Mauro Carvalho Chehab
@ 2009-07-03 9:01 ` Hans de Goede
0 siblings, 0 replies; 2+ messages in thread
From: Hans de Goede @ 2009-07-03 9:01 UTC (permalink / raw)
To: Mauro Carvalho Chehab; +Cc: Linux Media Mailing List
Hi,
Thanks for the patch I've applied it to my tree, and it will be in the
to be released soon libv4l-0.6.0 release.
Regards,
Hans
On 07/03/2009 04:19 AM, Mauro Carvalho Chehab wrote:
> Currently, em28xx driver outputs webcams only at RGB565 format. However,
> several webcam applications don't support this format.
>
> In order to properly work with those applications, a RGB565 handler should be
> added at libv4l.
>
> Tested with Silvercrest 1.3 mpix with v4l2grab (V4L2, with native libv4l
> support) and two LD_PRELOAD applications: camorama (V4L1 API) and skype (using compat32).
>
> Signed-off-by: Mauro Carvalho Chehab<mchehab@redhat.com>
>
> diff --git a/v4l2-apps/libv4l/libv4lconvert/libv4lconvert-priv.h b/v4l2-apps/libv4l/libv4lconvert/libv4lconvert-priv.h
> --- a/v4l2-apps/libv4l/libv4lconvert/libv4lconvert-priv.h
> +++ b/v4l2-apps/libv4l/libv4lconvert/libv4lconvert-priv.h
> @@ -184,6 +184,15 @@ void v4lconvert_swap_rgb(const unsigned
> void v4lconvert_swap_uv(const unsigned char *src, unsigned char *dst,
> const struct v4l2_format *src_fmt);
>
> +void v4lconvert_rgb565_to_rgb24(const unsigned char *src, unsigned char *dest,
> + int width, int height);
> +
> +void v4lconvert_rgb565_to_bgr24(const unsigned char *src, unsigned char *dest,
> + int width, int height);
> +
> +void v4lconvert_rgb565_to_yuv420(const unsigned char *src, unsigned char *dest,
> + const struct v4l2_format *src_fmt, int yvu);
> +
> void v4lconvert_spca501_to_yuv420(const unsigned char *src, unsigned char *dst,
> int width, int height, int yvu);
>
> diff --git a/v4l2-apps/libv4l/libv4lconvert/libv4lconvert.c b/v4l2-apps/libv4l/libv4lconvert/libv4lconvert.c
> --- a/v4l2-apps/libv4l/libv4lconvert/libv4lconvert.c
> +++ b/v4l2-apps/libv4l/libv4lconvert/libv4lconvert.c
> @@ -46,6 +46,7 @@ static const struct v4lconvert_pixfmt su
> { V4L2_PIX_FMT_YUYV, 0 },
> { V4L2_PIX_FMT_YVYU, 0 },
> { V4L2_PIX_FMT_UYVY, 0 },
> + { V4L2_PIX_FMT_RGB565, 0 },
> { V4L2_PIX_FMT_SN9C20X_I420, V4LCONVERT_NEEDS_CONVERSION },
> { V4L2_PIX_FMT_SBGGR8, V4LCONVERT_NEEDS_CONVERSION },
> { V4L2_PIX_FMT_SGBRG8, V4LCONVERT_NEEDS_CONVERSION },
> @@ -787,6 +788,23 @@ static int v4lconvert_convert_pixfmt(str
> }
> break;
>
> + case V4L2_PIX_FMT_RGB565:
> + switch (dest_pix_fmt) {
> + case V4L2_PIX_FMT_RGB24:
> + v4lconvert_rgb565_to_rgb24(src, dest, width, height);
> + break;
> + case V4L2_PIX_FMT_BGR24:
> + v4lconvert_rgb565_to_bgr24(src, dest, width, height);
> + break;
> + case V4L2_PIX_FMT_YUV420:
> + v4lconvert_rgb565_to_yuv420(src, dest, fmt, 0);
> + break;
> + case V4L2_PIX_FMT_YVU420:
> + v4lconvert_rgb565_to_yuv420(src, dest, fmt, 1);
> + break;
> + }
> + break;
> +
> case V4L2_PIX_FMT_RGB24:
> switch (dest_pix_fmt) {
> case V4L2_PIX_FMT_BGR24:
> diff --git a/v4l2-apps/libv4l/libv4lconvert/rgbyuv.c b/v4l2-apps/libv4l/libv4lconvert/rgbyuv.c
> --- a/v4l2-apps/libv4l/libv4lconvert/rgbyuv.c
> +++ b/v4l2-apps/libv4l/libv4lconvert/rgbyuv.c
> @@ -1,8 +1,10 @@
> /*
>
> # RGB<-> YUV conversion routines
> +# (C) 2008 Hans de Goede<j.w.r.degoede@hhs.nl>
>
> -# (C) 2008 Hans de Goede<j.w.r.degoede@hhs.nl>
> +# RGB565 conversion routines
> +# (C) 2009 Mauro Carvalho Chehab<mchehab@redhat.com>
>
> # This program is free software; you can redistribute it and/or modify
> # it under the terms of the GNU Lesser General Public License as published by
> @@ -472,3 +474,103 @@ void v4lconvert_swap_uv(const unsigned c
> src += src_fmt->fmt.pix.bytesperline / 2;
> }
> }
> +
> +void v4lconvert_rgb565_to_rgb24(const unsigned char *src, unsigned char *dest,
> + int width, int height)
> +{
> + int j;
> + while (--height>= 0) {
> + for (j = 0; j< width; j++) {
> + unsigned short tmp = *(unsigned short *)src;
> +
> + /* Original format: rrrrrggg gggbbbbb */
> + *dest++ = 0xf8& (tmp>> 8);
> + *dest++ = 0xfc& (tmp>> 3);
> + *dest++ = 0xf8& (tmp<< 3);
> +
> + src += 2;
> + }
> + }
> +}
> +
> +void v4lconvert_rgb565_to_bgr24(const unsigned char *src, unsigned char *dest,
> + int width, int height)
> +{
> + int j;
> + while (--height>= 0) {
> + for (j = 0; j< width; j++) {
> + unsigned short tmp = *(unsigned short *)src;
> +
> + /* Original format: rrrrrggg gggbbbbb */
> + *dest++ = 0xf8& (tmp<< 3);
> + *dest++ = 0xfc& (tmp>> 3);
> + *dest++ = 0xf8& (tmp>> 8);
> +
> + src += 2;
> + }
> + }
> +}
> +
> +void v4lconvert_rgb565_to_yuv420(const unsigned char *src, unsigned char *dest,
> + const struct v4l2_format *src_fmt, int yvu)
> +{
> + int x, y;
> + unsigned short tmp;
> + unsigned char *udest, *vdest;
> + unsigned r[4], g[4], b[4];
> + int avg_src[3];
> +
> + /* Y */
> + for (y = 0; y< src_fmt->fmt.pix.height; y++) {
> + for (x = 0; x< src_fmt->fmt.pix.width; x++) {
> + tmp = *(unsigned short *)src;
> + r[0] = 0xf8& (tmp<< 3);
> + g[0] = 0xfc& (tmp>> 3);
> + b[0] = 0xf8& (tmp>> 8);
> + RGB2Y(r[0], g[0], b[0], *dest++);
> + src += 2;
> + }
> + src += src_fmt->fmt.pix.bytesperline - 2 * src_fmt->fmt.pix.width;
> + }
> + src -= src_fmt->fmt.pix.height * src_fmt->fmt.pix.bytesperline;
> +
> + /* U + V */
> + if (yvu) {
> + vdest = dest;
> + udest = dest + src_fmt->fmt.pix.width * src_fmt->fmt.pix.height / 4;
> + } else {
> + udest = dest;
> + vdest = dest + src_fmt->fmt.pix.width * src_fmt->fmt.pix.height / 4;
> + }
> +
> + for (y = 0; y< src_fmt->fmt.pix.height / 2; y++) {
> + for (x = 0; x< src_fmt->fmt.pix.width / 2; x++) {
> + tmp = *(unsigned short *)src;
> + r[0] = 0xf8& (tmp<< 3);
> + g[0] = 0xfc& (tmp>> 3);
> + b[0] = 0xf8& (tmp>> 8);
> +
> + tmp = *(((unsigned short *)src) + 1);
> + r[1] = 0xf8& (tmp<< 3);
> + g[1] = 0xfc& (tmp>> 3);
> + b[1] = 0xf8& (tmp>> 8);
> +
> + tmp = *(((unsigned short *)src) + src_fmt->fmt.pix.bytesperline);
> + r[2] = 0xf8& (tmp<< 3);
> + g[2] = 0xfc& (tmp>> 3);
> + b[2] = 0xf8& (tmp>> 8);
> +
> + tmp = *(((unsigned short *)src) + src_fmt->fmt.pix.bytesperline + 1);
> + r[3] = 0xf8& (tmp<< 3);
> + g[3] = 0xfc& (tmp>> 3);
> + b[3] = 0xf8& (tmp>> 8);
> +
> + avg_src[0] = (r[0] + r[1] + r[2] + r[3]) /4;
> + avg_src[1] = (g[0] + g[1] + g[2] + g[3]) /4;
> + avg_src[2] = (b[0] + b[1] + b[2] + b[3]) /4;
> + RGB2UV(avg_src[0], avg_src[1], avg_src[2], *udest++, *vdest++);
> + src += 4;
> + }
> + src += 2 * src_fmt->fmt.pix.bytesperline - 2 * src_fmt->fmt.pix.width;
> + }
> +}
>
>
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2009-07-03 8:58 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-07-03 2:19 [PATCH] libv4l: add support for RGB565 format Mauro Carvalho Chehab
2009-07-03 9:01 ` Hans de Goede
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox