diff options
author | hans@rhel5-devel.localdomain <hans@rhel5-devel.localdomain> | 2009-03-11 13:10:27 +0100 |
---|---|---|
committer | hans@rhel5-devel.localdomain <hans@rhel5-devel.localdomain> | 2009-03-11 13:10:27 +0100 |
commit | 5f90628a20098c6dcde990310eaaabec2cef4694 (patch) | |
tree | 9be82eb41d9fc20107ef85d6aad1dda5115eca33 /v4l2-apps | |
parent | b326eb353c8691cc4c32ca59c0a2cf60ca74c3b6 (diff) | |
download | mediapointer-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')
-rw-r--r-- | v4l2-apps/libv4l/ChangeLog | 3 | ||||
-rw-r--r-- | v4l2-apps/libv4l/TODO | 4 | ||||
-rw-r--r-- | v4l2-apps/libv4l/libv4lconvert/bayer.c | 17 | ||||
-rw-r--r-- | v4l2-apps/libv4l/libv4lconvert/crop.c | 1 | ||||
-rw-r--r-- | v4l2-apps/libv4l/libv4lconvert/flip.c | 2 | ||||
-rw-r--r-- | v4l2-apps/libv4l/libv4lconvert/libv4lconvert-priv.h | 24 | ||||
-rw-r--r-- | v4l2-apps/libv4l/libv4lconvert/libv4lconvert.c | 101 | ||||
-rw-r--r-- | v4l2-apps/libv4l/libv4lconvert/rgbyuv.c | 139 | ||||
-rw-r--r-- | v4l2-apps/libv4l/libv4lconvert/spca501.c | 36 |
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; |