summaryrefslogtreecommitdiff
path: root/v4l2-apps/libv4l
diff options
context:
space:
mode:
authorhans@rhel5-devel.localdomain <hans@rhel5-devel.localdomain>2009-03-11 13:10:27 +0100
committerhans@rhel5-devel.localdomain <hans@rhel5-devel.localdomain>2009-03-11 13:10:27 +0100
commit5f90628a20098c6dcde990310eaaabec2cef4694 (patch)
tree9be82eb41d9fc20107ef85d6aad1dda5115eca33 /v4l2-apps/libv4l
parentb326eb353c8691cc4c32ca59c0a2cf60ca74c3b6 (diff)
downloadmediapointer-dvb-s2-5f90628a20098c6dcde990310eaaabec2cef4694.tar.gz
mediapointer-dvb-s2-5f90628a20098c6dcde990310eaaabec2cef4694.tar.bz2
libv4l: add support for converting to YV12 planar
From: Hans de Goede <hdegoede@redhat.com> Add support for converting to YV12 planar (next to the already supported YU12 / I420) and implement RGB/BGR24 -> YU/YV12 conversion Priority: normal Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Diffstat (limited to 'v4l2-apps/libv4l')
-rw-r--r--v4l2-apps/libv4l/ChangeLog3
-rw-r--r--v4l2-apps/libv4l/TODO4
-rw-r--r--v4l2-apps/libv4l/libv4lconvert/bayer.c17
-rw-r--r--v4l2-apps/libv4l/libv4lconvert/crop.c1
-rw-r--r--v4l2-apps/libv4l/libv4lconvert/flip.c2
-rw-r--r--v4l2-apps/libv4l/libv4lconvert/libv4lconvert-priv.h24
-rw-r--r--v4l2-apps/libv4l/libv4lconvert/libv4lconvert.c101
-rw-r--r--v4l2-apps/libv4l/libv4lconvert/rgbyuv.c139
-rw-r--r--v4l2-apps/libv4l/libv4lconvert/spca501.c36
9 files changed, 260 insertions, 67 deletions
diff --git a/v4l2-apps/libv4l/ChangeLog b/v4l2-apps/libv4l/ChangeLog
index b6097fe41..49f1fd035 100644
--- a/v4l2-apps/libv4l/ChangeLog
+++ b/v4l2-apps/libv4l/ChangeLog
@@ -5,6 +5,9 @@ libv4l-0.5.4
* Add support for downscaling to make apps which want low resolutions
(skype, spcaview) happy when used with cams which can only do high
resolutions (by Lukáš Karas <lukas.karas@centrum.cz>).
+* Add support for converting to YV12 planar (next to the already supported
+ YU12 / I420)
+* Implement RGB/BGR24 -> YU/YV12 conversion
libv4l-0.5.3
------------
diff --git a/v4l2-apps/libv4l/TODO b/v4l2-apps/libv4l/TODO
index f3f9ff527..debb9c78c 100644
--- a/v4l2-apps/libv4l/TODO
+++ b/v4l2-apps/libv4l/TODO
@@ -7,6 +7,4 @@
impossible for overlays) can be done, so that it will no longer be
necessary to implement CGMBUF in the kernel for each driver.
--check v4l2_field during conversion
-
--add conversion from bgr24 to yuv420
+-take the possibility of pitch != width into account everywhere
diff --git a/v4l2-apps/libv4l/libv4lconvert/bayer.c b/v4l2-apps/libv4l/libv4lconvert/bayer.c
index ca7bb486f..033ee2724 100644
--- a/v4l2-apps/libv4l/libv4lconvert/bayer.c
+++ b/v4l2-apps/libv4l/libv4lconvert/bayer.c
@@ -433,16 +433,23 @@ static void v4lconvert_border_bayer_line_to_y(
}
}
-void v4lconvert_bayer_to_yuv420(const unsigned char *bayer,
- unsigned char *yuv, int width, int height, unsigned int pixfmt)
+void v4lconvert_bayer_to_yuv420(const unsigned char *bayer, unsigned char *yuv,
+ int width, int height, unsigned int src_pixfmt, int yvu)
{
int blue_line = 0, start_with_green = 0, x, y;
unsigned char *ydst = yuv;
- unsigned char *udst = yuv + width * height;
- unsigned char *vdst = udst + width * height / 4;
+ unsigned char *udst, *vdst;
+
+ if (yvu) {
+ vdst = yuv + width * height;
+ udst = vdst + width * height / 4;
+ } else {
+ udst = yuv + width * height;
+ vdst = udst + width * height / 4;
+ }
/* First calculate the u and v planes 2x2 pixels at a time */
- switch (pixfmt) {
+ switch (src_pixfmt) {
case V4L2_PIX_FMT_SBGGR8:
for (y = 0; y < height; y += 2) {
for (x = 0; x < width; x += 2) {
diff --git a/v4l2-apps/libv4l/libv4lconvert/crop.c b/v4l2-apps/libv4l/libv4lconvert/crop.c
index dcfa5152a..4294fbeaf 100644
--- a/v4l2-apps/libv4l/libv4lconvert/crop.c
+++ b/v4l2-apps/libv4l/libv4lconvert/crop.c
@@ -156,6 +156,7 @@ void v4lconvert_crop(unsigned char *src, unsigned char *dest,
v4lconvert_crop_rgbbgr24(src, dest, src_fmt, dest_fmt);
break;
case V4L2_PIX_FMT_YUV420:
+ case V4L2_PIX_FMT_YVU420:
if (src_fmt->fmt.pix.width >= 2 * dest_fmt->fmt.pix.width &&
src_fmt->fmt.pix.height >= 2 * dest_fmt->fmt.pix.height)
v4lconvert_reduceandcrop_yuv420(src, dest, src_fmt, dest_fmt);
diff --git a/v4l2-apps/libv4l/libv4lconvert/flip.c b/v4l2-apps/libv4l/libv4lconvert/flip.c
index 5a108c8d9..f47afde72 100644
--- a/v4l2-apps/libv4l/libv4lconvert/flip.c
+++ b/v4l2-apps/libv4l/libv4lconvert/flip.c
@@ -119,6 +119,7 @@ void v4lconvert_rotate(unsigned char *src, unsigned char *dest,
v4lconvert_rotate90_rgbbgr24(src, dest, width, height);
break;
case V4L2_PIX_FMT_YUV420:
+ case V4L2_PIX_FMT_YVU420:
v4lconvert_rotate90_yuv420(src, dest, width, height);
break;
}
@@ -130,6 +131,7 @@ void v4lconvert_rotate(unsigned char *src, unsigned char *dest,
v4lconvert_rotate180_rgbbgr24(src, dest, width, height);
break;
case V4L2_PIX_FMT_YUV420:
+ case V4L2_PIX_FMT_YVU420:
v4lconvert_rotate180_yuv420(src, dest, width, height);
break;
}
diff --git a/v4l2-apps/libv4l/libv4lconvert/libv4lconvert-priv.h b/v4l2-apps/libv4l/libv4lconvert/libv4lconvert-priv.h
index 8473ba68f..a534ca321 100644
--- a/v4l2-apps/libv4l/libv4lconvert/libv4lconvert-priv.h
+++ b/v4l2-apps/libv4l/libv4lconvert/libv4lconvert-priv.h
@@ -104,11 +104,14 @@ struct v4lconvert_pixfmt {
int flags;
};
+void v4lconvert_rgb24_to_yuv420(const unsigned char *src, unsigned char *dest,
+ const struct v4l2_format *src_fmt, int bgr, int yvu);
+
void v4lconvert_yuv420_to_rgb24(const unsigned char *src, unsigned char *dst,
- int width, int height);
+ int width, int height, int yvu);
void v4lconvert_yuv420_to_bgr24(const unsigned char *src, unsigned char *dst,
- int width, int height);
+ int width, int height, int yvu);
void v4lconvert_yuyv_to_rgb24(const unsigned char *src, unsigned char *dst,
int width, int height);
@@ -117,7 +120,7 @@ void v4lconvert_yuyv_to_bgr24(const unsigned char *src, unsigned char *dst,
int width, int height);
void v4lconvert_yuyv_to_yuv420(const unsigned char *src, unsigned char *dst,
- int width, int height);
+ int width, int height, int yvu);
void v4lconvert_yvyu_to_rgb24(const unsigned char *src, unsigned char *dst,
int width, int height);
@@ -126,19 +129,22 @@ void v4lconvert_yvyu_to_bgr24(const unsigned char *src, unsigned char *dst,
int width, int height);
void v4lconvert_yvyu_to_yuv420(const unsigned char *src, unsigned char *dst,
- int width, int height);
+ int width, int height, int yvu);
void v4lconvert_swap_rgb(const unsigned char *src, unsigned char *dst,
int width, int height);
+void v4lconvert_swap_uv(const unsigned char *src, unsigned char *dst,
+ const struct v4l2_format *src_fmt);
+
void v4lconvert_spca501_to_yuv420(const unsigned char *src, unsigned char *dst,
- int width, int height);
+ int width, int height, int yvu);
void v4lconvert_spca505_to_yuv420(const unsigned char *src, unsigned char *dst,
- int width, int height);
+ int width, int height, int yvu);
void v4lconvert_spca508_to_yuv420(const unsigned char *src, unsigned char *dst,
- int width, int height);
+ int width, int height, int yvu);
void v4lconvert_decode_spca561(const unsigned char *src, unsigned char *dst,
int width, int height);
@@ -155,8 +161,8 @@ void v4lconvert_bayer_to_rgb24(const unsigned char *bayer,
void v4lconvert_bayer_to_bgr24(const unsigned char *bayer,
unsigned char *rgb, int width, int height, unsigned int pixfmt);
-void v4lconvert_bayer_to_yuv420(const unsigned char *bayer,
- unsigned char *yuv, int width, int height, unsigned int pixfmt);
+void v4lconvert_bayer_to_yuv420(const unsigned char *bayer, unsigned char *yuv,
+ int width, int height, unsigned int src_pixfmt, int yvu);
void v4lconvert_rotate(unsigned char *src, unsigned char *dest,
int width, int height, unsigned int pix_fmt, int rotate);
diff --git a/v4l2-apps/libv4l/libv4lconvert/libv4lconvert.c b/v4l2-apps/libv4l/libv4lconvert/libv4lconvert.c
index 536e5363d..c6c50c2e5 100644
--- a/v4l2-apps/libv4l/libv4lconvert/libv4lconvert.c
+++ b/v4l2-apps/libv4l/libv4lconvert/libv4lconvert.c
@@ -32,7 +32,8 @@
#define SUPPORTED_DST_PIXFMTS \
{ V4L2_PIX_FMT_RGB24, 0 }, \
{ V4L2_PIX_FMT_BGR24, 0 }, \
- { V4L2_PIX_FMT_YUV420, 0 }
+ { V4L2_PIX_FMT_YUV420, 0 }, \
+ { V4L2_PIX_FMT_YVU420, 0 }
static void v4lconvert_get_framesizes(struct v4lconvert_data *data,
unsigned int pixelformat);
@@ -243,6 +244,7 @@ static void v4lconvert_fixup_fmt(struct v4l2_format *fmt)
fmt->fmt.pix.sizeimage = fmt->fmt.pix.width * fmt->fmt.pix.height * 3;
break;
case V4L2_PIX_FMT_YUV420:
+ case V4L2_PIX_FMT_YVU420:
fmt->fmt.pix.bytesperline = fmt->fmt.pix.width;
fmt->fmt.pix.sizeimage = fmt->fmt.pix.width * fmt->fmt.pix.height * 3 / 2;
break;
@@ -354,13 +356,15 @@ static unsigned char *v4lconvert_alloc_buffer(struct v4lconvert_data *data,
}
static int v4lconvert_convert_pixfmt(struct v4lconvert_data *data,
- unsigned int src_pix_fmt, unsigned int dest_pix_fmt,
- unsigned int width, unsigned int height,
- unsigned char *src, int src_size, unsigned char *dest)
+ unsigned char *src, int src_size, unsigned char *dest,
+ const struct v4l2_format *src_fmt, unsigned int dest_pix_fmt)
{
unsigned int header_width, header_height;
int result = 0, jpeg_flags = TINYJPEG_FLAGS_MJPEG_TABLE;
unsigned char *components[3];
+ unsigned int src_pix_fmt = src_fmt->fmt.pix.pixelformat;
+ unsigned int width = src_fmt->fmt.pix.width;
+ unsigned int height = src_fmt->fmt.pix.height;
switch (src_pix_fmt) {
case V4L2_PIX_FMT_PJPG:
@@ -404,8 +408,6 @@ static int v4lconvert_convert_pixfmt(struct v4lconvert_data *data,
}
components[0] = dest;
- components[1] = components[0] + width * height;
- components[2] = components[1] + width * height / 4;
switch (dest_pix_fmt) {
case V4L2_PIX_FMT_RGB24:
@@ -417,6 +419,14 @@ static int v4lconvert_convert_pixfmt(struct v4lconvert_data *data,
result = tinyjpeg_decode(data->jdec, TINYJPEG_FMT_BGR24);
break;
case V4L2_PIX_FMT_YUV420:
+ components[1] = components[0] + width * height;
+ components[2] = components[1] + width * height / 4;
+ tinyjpeg_set_components(data->jdec, components, 3);
+ result = tinyjpeg_decode(data->jdec, TINYJPEG_FMT_YUV420P);
+ break;
+ case V4L2_PIX_FMT_YVU420:
+ components[2] = components[0] + width * height;
+ components[1] = components[2] + width * height / 4;
tinyjpeg_set_components(data->jdec, components, 3);
result = tinyjpeg_decode(data->jdec, TINYJPEG_FMT_YUV420P);
break;
@@ -454,7 +464,10 @@ static int v4lconvert_convert_pixfmt(struct v4lconvert_data *data,
v4lconvert_bayer_to_bgr24(src, dest, width, height, src_pix_fmt);
break;
case V4L2_PIX_FMT_YUV420:
- v4lconvert_bayer_to_yuv420(src, dest, width, height, src_pix_fmt);
+ v4lconvert_bayer_to_yuv420(src, dest, width, height, src_pix_fmt, 0);
+ break;
+ case V4L2_PIX_FMT_YVU420:
+ v4lconvert_bayer_to_yuv420(src, dest, width, height, src_pix_fmt, 1);
break;
}
break;
@@ -465,8 +478,10 @@ static int v4lconvert_convert_pixfmt(struct v4lconvert_data *data,
case V4L2_PIX_FMT_SPCA508:
{
unsigned char *d;
+ int yvu = 0;
- if (dest_pix_fmt != V4L2_PIX_FMT_YUV420) {
+ if (dest_pix_fmt != V4L2_PIX_FMT_YUV420 &&
+ dest_pix_fmt != V4L2_PIX_FMT_YVU420) {
d = v4lconvert_alloc_buffer(data, width * height * 3 / 2,
&data->convert_pixfmt_buf, &data->convert_pixfmt_buf_size);
if (!d)
@@ -474,26 +489,29 @@ static int v4lconvert_convert_pixfmt(struct v4lconvert_data *data,
} else
d = dest;
+ if (dest_pix_fmt == V4L2_PIX_FMT_YVU420)
+ yvu = 1;
+
switch (src_pix_fmt) {
case V4L2_PIX_FMT_SPCA501:
- v4lconvert_spca501_to_yuv420(src, d, width, height);
+ v4lconvert_spca501_to_yuv420(src, d, width, height, yvu);
break;
case V4L2_PIX_FMT_SPCA505:
- v4lconvert_spca505_to_yuv420(src, d, width, height);
+ v4lconvert_spca505_to_yuv420(src, d, width, height, yvu);
break;
case V4L2_PIX_FMT_SPCA508:
- v4lconvert_spca508_to_yuv420(src, d, width, height);
+ v4lconvert_spca508_to_yuv420(src, d, width, height, yvu);
break;
}
switch (dest_pix_fmt) {
case V4L2_PIX_FMT_RGB24:
v4lconvert_yuv420_to_rgb24(data->convert_pixfmt_buf, dest, width,
- height);
+ height, yvu);
break;
case V4L2_PIX_FMT_BGR24:
v4lconvert_yuv420_to_bgr24(data->convert_pixfmt_buf, dest, width,
- height);
+ height, yvu);
break;
}
break;
@@ -535,7 +553,10 @@ static int v4lconvert_convert_pixfmt(struct v4lconvert_data *data,
v4lconvert_bayer_to_bgr24(tmpbuf, dest, width, height, bayer_fmt);
break;
case V4L2_PIX_FMT_YUV420:
- v4lconvert_bayer_to_yuv420(tmpbuf, dest, width, height, bayer_fmt);
+ v4lconvert_bayer_to_yuv420(tmpbuf, dest, width, height, bayer_fmt, 0);
+ break;
+ case V4L2_PIX_FMT_YVU420:
+ v4lconvert_bayer_to_yuv420(tmpbuf, dest, width, height, bayer_fmt, 1);
break;
}
break;
@@ -547,7 +568,10 @@ static int v4lconvert_convert_pixfmt(struct v4lconvert_data *data,
v4lconvert_swap_rgb(src, dest, width, height);
break;
case V4L2_PIX_FMT_YUV420:
- printf("FIXME add rgb24 -> yuv420 conversion\n");
+ v4lconvert_rgb24_to_yuv420(src, dest, src_fmt, 0, 0);
+ break;
+ case V4L2_PIX_FMT_YVU420:
+ v4lconvert_rgb24_to_yuv420(src, dest, src_fmt, 0, 1);
break;
}
break;
@@ -558,7 +582,10 @@ static int v4lconvert_convert_pixfmt(struct v4lconvert_data *data,
v4lconvert_swap_rgb(src, dest, width, height);
break;
case V4L2_PIX_FMT_YUV420:
- printf("FIXME add bgr24 -> yuv420 conversion\n");
+ v4lconvert_rgb24_to_yuv420(src, dest, src_fmt, 1, 0);
+ break;
+ case V4L2_PIX_FMT_YVU420:
+ v4lconvert_rgb24_to_yuv420(src, dest, src_fmt, 1, 1);
break;
}
break;
@@ -567,11 +594,30 @@ static int v4lconvert_convert_pixfmt(struct v4lconvert_data *data,
switch (dest_pix_fmt) {
case V4L2_PIX_FMT_RGB24:
v4lconvert_yuv420_to_rgb24(src, dest, width,
- height);
+ height, 0);
break;
case V4L2_PIX_FMT_BGR24:
v4lconvert_yuv420_to_bgr24(src, dest, width,
- height);
+ height, 0);
+ break;
+ case V4L2_PIX_FMT_YVU420:
+ v4lconvert_swap_uv(src, dest, src_fmt);
+ break;
+ }
+ break;
+
+ case V4L2_PIX_FMT_YVU420:
+ switch (dest_pix_fmt) {
+ case V4L2_PIX_FMT_RGB24:
+ v4lconvert_yuv420_to_rgb24(src, dest, width,
+ height, 1);
+ break;
+ case V4L2_PIX_FMT_BGR24:
+ v4lconvert_yuv420_to_bgr24(src, dest, width,
+ height, 1);
+ break;
+ case V4L2_PIX_FMT_YUV420:
+ v4lconvert_swap_uv(src, dest, src_fmt);
break;
}
break;
@@ -585,7 +631,10 @@ static int v4lconvert_convert_pixfmt(struct v4lconvert_data *data,
v4lconvert_yuyv_to_bgr24(src, dest, width, height);
break;
case V4L2_PIX_FMT_YUV420:
- v4lconvert_yuyv_to_yuv420(src, dest, width, height);
+ v4lconvert_yuyv_to_yuv420(src, dest, width, height, 0);
+ break;
+ case V4L2_PIX_FMT_YVU420:
+ v4lconvert_yuyv_to_yuv420(src, dest, width, height, 1);
break;
}
break;
@@ -599,7 +648,10 @@ static int v4lconvert_convert_pixfmt(struct v4lconvert_data *data,
v4lconvert_yvyu_to_bgr24(src, dest, width, height);
break;
case V4L2_PIX_FMT_YUV420:
- v4lconvert_yvyu_to_yuv420(src, dest, width, height);
+ v4lconvert_yvyu_to_yuv420(src, dest, width, height, 0);
+ break;
+ case V4L2_PIX_FMT_YVU420:
+ v4lconvert_yvyu_to_yuv420(src, dest, width, height, 1);
break;
}
break;
@@ -645,6 +697,7 @@ int v4lconvert_convert(struct v4lconvert_data *data,
temp_needed = my_src_fmt.fmt.pix.width * my_src_fmt.fmt.pix.height * 3;
break;
case V4L2_PIX_FMT_YUV420:
+ case V4L2_PIX_FMT_YVU420:
dest_needed =
my_dest_fmt.fmt.pix.width * my_dest_fmt.fmt.pix.height * 3 / 2;
temp_needed =
@@ -694,11 +747,9 @@ int v4lconvert_convert(struct v4lconvert_data *data,
}
if (convert) {
- res = v4lconvert_convert_pixfmt(data, my_src_fmt.fmt.pix.pixelformat,
- my_dest_fmt.fmt.pix.pixelformat,
- my_src_fmt.fmt.pix.width,
- my_src_fmt.fmt.pix.height,
- src, src_size, convert_dest);
+ res = v4lconvert_convert_pixfmt(data, src, src_size, convert_dest,
+ &my_src_fmt,
+ my_dest_fmt.fmt.pix.pixelformat);
if (res)
return res;
diff --git a/v4l2-apps/libv4l/libv4lconvert/rgbyuv.c b/v4l2-apps/libv4l/libv4lconvert/rgbyuv.c
index 0f26b227a..d5feb457e 100644
--- a/v4l2-apps/libv4l/libv4lconvert/rgbyuv.c
+++ b/v4l2-apps/libv4l/libv4lconvert/rgbyuv.c
@@ -20,13 +20,65 @@
*/
+#include <string.h>
#include "libv4lconvert-priv.h"
-#define RGB2YUV(r,g,b,y,u,v) \
- (y) = (( 8453*(r) + 16594*(g) + 3223*(b) + 524288) >> 15); \
+#define RGB2Y(r,g,b,y) \
+ (y) = (( 8453*(r) + 16594*(g) + 3223*(b) + 524288) >> 15)
+
+#define RGB2UV(r,g,b,u,v) \
(u) = (( -4878*(r) - 9578*(g) + 14456*(b) + 4210688) >> 15); \
(v) = (( 14456*(r) - 12105*(g) - 2351*(b) + 4210688) >> 15)
+void v4lconvert_rgb24_to_yuv420(const unsigned char *src, unsigned char *dest,
+ const struct v4l2_format *src_fmt, int bgr, int yvu)
+{
+ int x, y;
+ unsigned char *udest, *vdest;
+
+ /* Y */
+ for (y = 0; y < src_fmt->fmt.pix.height; y++) {
+ for (x = 0; x < src_fmt->fmt.pix.width; x++) {
+ if (bgr) {
+ RGB2Y(src[2], src[1], src[0], *dest++);
+ } else {
+ RGB2Y(src[0], src[1], src[2], *dest++);
+ }
+ src += 3;
+ }
+ src += src_fmt->fmt.pix.bytesperline - 3 * 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++) {
+ int avg_src[3];
+ avg_src[0] = (src[0] + src[3] + src[src_fmt->fmt.pix.bytesperline] +
+ src[src_fmt->fmt.pix.bytesperline + 3]) / 4;
+ avg_src[1] = (src[1] + src[4] + src[src_fmt->fmt.pix.bytesperline + 1] +
+ src[src_fmt->fmt.pix.bytesperline + 4]) / 4;
+ avg_src[2] = (src[2] + src[5] + src[src_fmt->fmt.pix.bytesperline + 2] +
+ src[src_fmt->fmt.pix.bytesperline + 5]) / 4;
+ if (bgr) {
+ RGB2UV(avg_src[2], avg_src[1], avg_src[0], *udest++, *vdest++);
+ } else {
+ RGB2UV(avg_src[0], avg_src[1], avg_src[2], *udest++, *vdest++);
+ }
+ src += 6;
+ }
+ src += 2 * src_fmt->fmt.pix.bytesperline - 3 * src_fmt->fmt.pix.width;
+ }
+}
+
#define YUV2R(y, u, v) ({ \
int r = (y) + ((((v)-128)*1436) >> 10); r > 255 ? 255 : r < 0 ? 0 : r; })
#define YUV2G(y, u, v) ({ \
@@ -37,13 +89,20 @@
#define CLIP(color) (unsigned char)(((color)>0xFF)?0xff:(((color)<0)?0:(color)))
void v4lconvert_yuv420_to_bgr24(const unsigned char *src, unsigned char *dest,
- int width, int height)
+ int width, int height, int yvu)
{
int i,j;
const unsigned char *ysrc = src;
- const unsigned char *usrc = src + width * height;
- const unsigned char *vsrc = usrc + (width * height) / 4;
+ const unsigned char *usrc, *vsrc;
+
+ if (yvu) {
+ vsrc = src + width * height;
+ usrc = vsrc + (width * height) / 4;
+ } else {
+ usrc = src + width * height;
+ vsrc = usrc + (width * height) / 4;
+ }
for (i = 0; i < height; i++) {
for (j = 0; j < width; j += 2) {
@@ -84,13 +143,20 @@ void v4lconvert_yuv420_to_bgr24(const unsigned char *src, unsigned char *dest,
}
void v4lconvert_yuv420_to_rgb24(const unsigned char *src, unsigned char *dest,
- int width, int height)
+ int width, int height, int yvu)
{
int i,j;
const unsigned char *ysrc = src;
- const unsigned char *usrc = src + width * height;
- const unsigned char *vsrc = usrc + (width * height) / 4;
+ const unsigned char *usrc, *vsrc;
+
+ if (yvu) {
+ vsrc = src + width * height;
+ usrc = vsrc + (width * height) / 4;
+ } else {
+ usrc = src + width * height;
+ vsrc = usrc + (width * height) / 4;
+ }
for (i = 0; i < height; i++) {
for (j = 0; j < width; j += 2) {
@@ -183,11 +249,11 @@ void v4lconvert_yuyv_to_rgb24(const unsigned char *src, unsigned char *dest,
}
void v4lconvert_yuyv_to_yuv420(const unsigned char *src, unsigned char *dest,
- int width, int height)
+ int width, int height, int yvu)
{
int i, j;
const unsigned char *src1;
- unsigned char *vdest;
+ unsigned char *udest, *vdest;
/* copy the Y values */
src1 = src;
@@ -202,10 +268,16 @@ void v4lconvert_yuyv_to_yuv420(const unsigned char *src, unsigned char *dest,
/* copy the U and V values */
src++; /* point to V */
src1 = src + width * 2; /* next line */
- vdest = dest + width * height / 4;
+ if (yvu) {
+ vdest = dest;
+ udest = dest + width * height / 4;
+ } else {
+ udest = dest;
+ vdest = dest + width * height / 4;
+ }
for (i = 0; i < height; i += 2) {
for (j = 0; j < width; j += 2) {
- *dest++ = ((int) src[0] + src1[0]) / 2; /* U */
+ *udest++ = ((int) src[0] + src1[0]) / 2; /* U */
*vdest++ = ((int) src[2] + src1[2]) / 2; /* V */
src += 4;
src1 += 4;
@@ -268,11 +340,11 @@ void v4lconvert_yvyu_to_rgb24(const unsigned char *src, unsigned char *dest,
}
void v4lconvert_yvyu_to_yuv420(const unsigned char *src, unsigned char *dest,
- int width, int height)
+ int width, int height, int yvu)
{
int i, j;
const unsigned char *src1;
- unsigned char *vdest;
+ unsigned char *udest, *vdest;
/* copy the Y values */
src1 = src;
@@ -287,10 +359,16 @@ void v4lconvert_yvyu_to_yuv420(const unsigned char *src, unsigned char *dest,
/* copy the U and V values */
src++; /* point to V */
src1 = src + width * 2; /* next line */
- vdest = dest + width * height / 4;
+ if (yvu) {
+ vdest = dest;
+ udest = dest + width * height / 4;
+ } else {
+ udest = dest;
+ vdest = dest + width * height / 4;
+ }
for (i = 0; i < height; i += 2) {
for (j = 0; j < width; j += 2) {
- *dest++ = ((int) src[2] + src1[2]) / 2; /* U */
+ *udest++ = ((int) src[2] + src1[2]) / 2; /* U */
*vdest++ = ((int) src[0] + src1[0]) / 2; /* V */
src += 4;
src1 += 4;
@@ -314,3 +392,32 @@ void v4lconvert_swap_rgb(const unsigned char *src, unsigned char *dst,
*dst++ = tmp0;
}
}
+
+void v4lconvert_swap_uv(const unsigned char *src, unsigned char *dest,
+ const struct v4l2_format *src_fmt)
+{
+ int y;
+
+ /* Copy Y */
+ for (y = 0; y < src_fmt->fmt.pix.height; y++) {
+ memcpy(dest, src, src_fmt->fmt.pix.width);
+ dest += src_fmt->fmt.pix.width;
+ src += src_fmt->fmt.pix.bytesperline;
+ }
+
+ /* Copy component 2 */
+ src += src_fmt->fmt.pix.height * src_fmt->fmt.pix.bytesperline / 4;
+ for (y = 0; y < src_fmt->fmt.pix.height / 2; y++) {
+ memcpy(dest, src, src_fmt->fmt.pix.width / 2);
+ dest += src_fmt->fmt.pix.width / 2;
+ src += src_fmt->fmt.pix.bytesperline / 2;
+ }
+
+ /* Copy component 1 */
+ src -= src_fmt->fmt.pix.height * src_fmt->fmt.pix.bytesperline / 2;
+ for (y = 0; y < src_fmt->fmt.pix.height / 2; y++) {
+ memcpy(dest, src, src_fmt->fmt.pix.width / 2);
+ dest += src_fmt->fmt.pix.width / 2;
+ src += src_fmt->fmt.pix.bytesperline / 2;
+ }
+}
diff --git a/v4l2-apps/libv4l/libv4lconvert/spca501.c b/v4l2-apps/libv4l/libv4lconvert/spca501.c
index 9157629e3..f491512e3 100644
--- a/v4l2-apps/libv4l/libv4lconvert/spca501.c
+++ b/v4l2-apps/libv4l/libv4lconvert/spca501.c
@@ -20,7 +20,7 @@
/* YUYV per line */
void v4lconvert_spca501_to_yuv420(const unsigned char *src, unsigned char *dst,
- int width, int height)
+ int width, int height, int yvu)
{
int i,j;
unsigned long *lsrc = (unsigned long *)src;
@@ -34,7 +34,10 @@ void v4lconvert_spca501_to_yuv420(const unsigned char *src, unsigned char *dst,
}
/* -128 - 127 --> 0 - 255 and copy 1 line U */
- ldst = (unsigned long *)(dst + width * height + i * width / 4);
+ if (yvu)
+ ldst = (unsigned long *)(dst + (width * height * 5) / 4 + i * width / 4);
+ else
+ ldst = (unsigned long *)(dst + width * height + i * width / 4);
for (j = 0; j < width/2; j += sizeof(long)) {
*ldst = *lsrc++;
*ldst++ ^= 0x8080808080808080ULL;
@@ -48,7 +51,10 @@ void v4lconvert_spca501_to_yuv420(const unsigned char *src, unsigned char *dst,
}
/* -128 - 127 --> 0 - 255 and copy 1 line V */
- ldst = (unsigned long *)(dst + (width * height * 5) / 4 + i * width / 4);
+ if (yvu)
+ ldst = (unsigned long *)(dst + width * height + i * width / 4);
+ else
+ ldst = (unsigned long *)(dst + (width * height * 5) / 4 + i * width / 4);
for (j = 0; j < width/2; j += sizeof(long)) {
*ldst = *lsrc++;
*ldst++ ^= 0x8080808080808080ULL;
@@ -58,7 +64,7 @@ void v4lconvert_spca501_to_yuv420(const unsigned char *src, unsigned char *dst,
/* YYUV per line */
void v4lconvert_spca505_to_yuv420(const unsigned char *src, unsigned char *dst,
- int width, int height)
+ int width, int height, int yvu)
{
int i,j;
unsigned long *lsrc = (unsigned long *)src;
@@ -72,14 +78,20 @@ void v4lconvert_spca505_to_yuv420(const unsigned char *src, unsigned char *dst,
}
/* -128 - 127 --> 0 - 255 and copy 1 line U */
- ldst = (unsigned long *)(dst + width * height + i * width / 4);
+ if (yvu)
+ ldst = (unsigned long *)(dst + (width * height * 5) / 4 + i * width / 4);
+ else
+ ldst = (unsigned long *)(dst + width * height + i * width / 4);
for (j = 0; j < width/2; j += sizeof(long)) {
*ldst = *lsrc++;
*ldst++ ^= 0x8080808080808080ULL;
}
/* -128 - 127 --> 0 - 255 and copy 1 line V */
- ldst = (unsigned long *)(dst + (width * height * 5) / 4 + i * width / 4);
+ if (yvu)
+ ldst = (unsigned long *)(dst + width * height + i * width / 4);
+ else
+ ldst = (unsigned long *)(dst + (width * height * 5) / 4 + i * width / 4);
for (j = 0; j < width/2; j += sizeof(long)) {
*ldst = *lsrc++;
*ldst++ ^= 0x8080808080808080ULL;
@@ -89,7 +101,7 @@ void v4lconvert_spca505_to_yuv420(const unsigned char *src, unsigned char *dst,
/* YUVY per line */
void v4lconvert_spca508_to_yuv420(const unsigned char *src, unsigned char *dst,
- int width, int height)
+ int width, int height, int yvu)
{
int i,j;
unsigned long *lsrc = (unsigned long *)src;
@@ -103,14 +115,20 @@ void v4lconvert_spca508_to_yuv420(const unsigned char *src, unsigned char *dst,
}
/* -128 - 127 --> 0 - 255 and copy 1 line U */
- ldst = (unsigned long *)(dst + width * height + i * width / 4);
+ if (yvu)
+ ldst = (unsigned long *)(dst + (width * height * 5) / 4 + i * width / 4);
+ else
+ ldst = (unsigned long *)(dst + width * height + i * width / 4);
for (j = 0; j < width/2; j += sizeof(long)) {
*ldst = *lsrc++;
*ldst++ ^= 0x8080808080808080ULL;
}
/* -128 - 127 --> 0 - 255 and copy 1 line V */
- ldst = (unsigned long *)(dst + (width * height * 5) / 4 + i * width / 4);
+ if (yvu)
+ ldst = (unsigned long *)(dst + width * height + i * width / 4);
+ else
+ ldst = (unsigned long *)(dst + (width * height * 5) / 4 + i * width / 4);
for (j = 0; j < width/2; j += sizeof(long)) {
*ldst = *lsrc++;
*ldst++ ^= 0x8080808080808080ULL;