diff options
-rw-r--r-- | v4l2-apps/libv4l/ChangeLog | 2 | ||||
-rw-r--r-- | v4l2-apps/libv4l/libv4lconvert/Makefile | 2 | ||||
-rw-r--r-- | v4l2-apps/libv4l/libv4lconvert/hm12.c | 159 | ||||
-rw-r--r-- | v4l2-apps/libv4l/libv4lconvert/libv4lconvert-priv.h | 13 | ||||
-rw-r--r-- | v4l2-apps/libv4l/libv4lconvert/libv4lconvert.c | 19 |
5 files changed, 194 insertions, 1 deletions
diff --git a/v4l2-apps/libv4l/ChangeLog b/v4l2-apps/libv4l/ChangeLog index c6ff3c3d9..11f6ca2fd 100644 --- a/v4l2-apps/libv4l/ChangeLog +++ b/v4l2-apps/libv4l/ChangeLog @@ -3,6 +3,8 @@ libv4l-0.5.9 * Add support for MR97310A decompression by Kyle Guinn <elyk03@gmail.com> * Add support for sq905c decompression by Theodore Kilgore <kilgota@auburn.edu> +* Add hm12 support for the cx2341x MPEG encoder devices by Hans Verkuil + <hverkuil@xs4all.nl> libv4l-0.5.8 ------------ diff --git a/v4l2-apps/libv4l/libv4lconvert/Makefile b/v4l2-apps/libv4l/libv4lconvert/Makefile index 5d968057d..f779011b4 100644 --- a/v4l2-apps/libv4l/libv4lconvert/Makefile +++ b/v4l2-apps/libv4l/libv4lconvert/Makefile @@ -12,7 +12,7 @@ endif CONVERT_OBJS = libv4lconvert.o tinyjpeg.o sn9c10x.o sn9c20x.o pac207.o \ mr97310a.o flip.o crop.o jidctflt.o spca561-decompress.o \ - rgbyuv.o spca501.o sq905c.o bayer.o + rgbyuv.o spca501.o sq905c.o bayer.o hm12.o TARGETS = $(CONVERT_LIB) libv4lconvert.pc INCLUDES = ../include/libv4lconvert.h diff --git a/v4l2-apps/libv4l/libv4lconvert/hm12.c b/v4l2-apps/libv4l/libv4lconvert/hm12.c new file mode 100644 index 000000000..f711627b4 --- /dev/null +++ b/v4l2-apps/libv4l/libv4lconvert/hm12.c @@ -0,0 +1,159 @@ +/* + +cx2341x HM12 conversion routines + +(C) 2009 Hans Verkuil <hverkuil@xs4all.nl> + +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 +the Free Software Foundation; either version 2.1 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + */ + +#include "libv4lconvert-priv.h" +#include <string.h> + +/* The HM12 format is used in the Conexant cx23415/6/8 MPEG encoder devices. + It is a macroblock format with separate Y and UV planes, each plane + consisting of 16x16 values. All lines are always 720 bytes long. If the + width of the image is less than 720, then the remainder is padding. + + The height has to be a multiple of 32 in order to get correct chroma + values. + + It is basically a by-product of the MPEG encoding inside the device, + which is available for raw video as a 'bonus feature'. + */ + +#define CLIP(color) \ + (unsigned char)(((color) > 0xff) ? 0xff : (((color) < 0) ? 0 : (color))) + +static const int stride = 720; + +static void v4lconvert_hm12_to_rgb(const unsigned char *src, unsigned char *dest, + int width, int height, int rgb) +{ + unsigned int y, x, i, j; + const unsigned char *y_base = src; + const unsigned char *uv_base = src + stride * height; + const unsigned char *src_y; + const unsigned char *src_uv; + int mb_size = 256; + int r = rgb ? 0 : 2; + int b = 2 - r; + + for (y = 0; y < height; y += 16) { + int mb_y = (y / 16) * (stride / 16); + int mb_uv = (y / 32) * (stride / 16); + int maxy = (height - y < 16 ? height - y : 16); + + for (x = 0; x < width; x += 16, mb_y++, mb_uv++) { + int maxx = (width - x < 16 ? width - x : 16); + + src_y = y_base + mb_y * mb_size; + src_uv = uv_base + mb_uv * mb_size; + + if (y & 0x10) + src_uv += mb_size / 2; + + for (i = 0; i < maxy; i++) { + int idx = (x + (y + i) * width) * 3; + + for (j = 0; j < maxx; j++) { + int y = src_y[j]; + int u = src_uv[j & ~1]; + int v = src_uv[j | 1]; + int u1 = (((u - 128) << 7) + (u - 128)) >> 6; + int rg = (((u - 128) << 1) + (u - 128) + + ((v - 128) << 2) + ((v - 128) << 1)) >> 3; + int v1 = (((v - 128) << 1) + (v - 128)) >> 1; + + dest[idx+r] = CLIP(y + v1); + dest[idx+1] = CLIP(y - rg); + dest[idx+b] = CLIP(y + u1); + idx += 3; + } + src_y += 16; + if (i & 1) + src_uv += 16; + } + } + } +} + +void v4lconvert_hm12_to_rgb24(const unsigned char *src, unsigned char *dest, + int width, int height) +{ + v4lconvert_hm12_to_rgb(src, dest, width, height, 1); +} + +void v4lconvert_hm12_to_bgr24(const unsigned char *src, unsigned char *dest, + int width, int height) +{ + v4lconvert_hm12_to_rgb(src, dest, width, height, 0); +} + +static void de_macro_uv(unsigned char *dstu, unsigned char *dstv, + const unsigned char *src, int w, int h) +{ + unsigned int y, x, i, j; + + for (y = 0; y < h; y += 16) { + for (x = 0; x < w; x += 8) { + const unsigned char *src_uv = src + y * stride + x * 32; + int maxy = (h - y < 16 ? h - y : 16); + int maxx = (w - x < 8 ? w - x : 8); + + for (i = 0; i < maxy; i++) { + int idx = x + (y + i) * w; + + for (j = 0; j < maxx; j++) { + dstu[idx+j] = src_uv[2 * j]; + dstv[idx+j] = src_uv[2 * j + 1]; + } + src_uv += 16; + } + } + } +} + +static void de_macro_y(unsigned char *dst, const unsigned char *src, + int w, int h) +{ + unsigned int y, x, i; + + for (y = 0; y < h; y += 16) { + for (x = 0; x < w; x += 16) { + const unsigned char *src_y = src + y * stride + x * 16; + int maxy = (h - y < 16 ? h - y : 16); + int maxx = (w - x < 16 ? w - x : 16); + + for (i = 0; i < maxy; i++) { + memcpy(dst + x + (y + i) * w, src_y, maxx); + src_y += 16; + } + } + } +} + +void v4lconvert_hm12_to_yuv420(const unsigned char *src, unsigned char *dest, + int width, int height, int yvu) +{ + de_macro_y(dest, src, width, height); + dest += width * height; + src += stride * height; + if (yvu) + de_macro_uv(dest + width * height / 4, dest, src, width / 2, height / 2); + else + de_macro_uv(dest, dest + width * height / 4, src, width / 2, height / 2); +} diff --git a/v4l2-apps/libv4l/libv4lconvert/libv4lconvert-priv.h b/v4l2-apps/libv4l/libv4lconvert/libv4lconvert-priv.h index f3e80e82c..5ce7bde3b 100644 --- a/v4l2-apps/libv4l/libv4lconvert/libv4lconvert-priv.h +++ b/v4l2-apps/libv4l/libv4lconvert/libv4lconvert-priv.h @@ -71,6 +71,10 @@ #define V4L2_PIX_FMT_YVYU v4l2_fourcc('Y', 'V', 'Y', 'U') #endif +#ifndef V4L2_PIX_FMT_HM12 +#define V4L2_PIX_FMT_HM12 v4l2_fourcc('H', 'M', '1', '2') +#endif + #ifndef V4L2_PIX_FMT_SN9C20X_I420 #define V4L2_PIX_FMT_SN9C20X_I420 v4l2_fourcc('S', '9', '2', '0') #endif @@ -196,6 +200,15 @@ void v4lconvert_bayer_to_bgr24(const unsigned char *bayer, void v4lconvert_bayer_to_yuv420(const unsigned char *bayer, unsigned char *yuv, int width, int height, unsigned int src_pixfmt, int yvu); +void v4lconvert_hm12_to_rgb24(const unsigned char *src, + unsigned char *dst, int width, int height); + +void v4lconvert_hm12_to_bgr24(const unsigned char *src, + unsigned char *dst, int width, int height); + +void v4lconvert_hm12_to_yuv420(const unsigned char *src, + unsigned char *dst, int width, int height, 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 1ba7f45d7..1204e8ef2 100644 --- a/v4l2-apps/libv4l/libv4lconvert/libv4lconvert.c +++ b/v4l2-apps/libv4l/libv4lconvert/libv4lconvert.c @@ -55,6 +55,7 @@ static const struct v4lconvert_pixfmt supported_src_pixfmts[] = { { V4L2_PIX_FMT_SPCA501, 0 }, { V4L2_PIX_FMT_SPCA505, 0 }, { V4L2_PIX_FMT_SPCA508, 0 }, + { V4L2_PIX_FMT_HM12, 0 }, { V4L2_PIX_FMT_MJPEG, V4LCONVERT_COMPRESSED }, { V4L2_PIX_FMT_JPEG, V4LCONVERT_COMPRESSED }, { V4L2_PIX_FMT_SPCA561, V4LCONVERT_COMPRESSED }, @@ -604,6 +605,24 @@ static int v4lconvert_convert_pixfmt(struct v4lconvert_data *data, break; } + /* Conexant cx2341x raw video macroblock format */ + case V4L2_PIX_FMT_HM12: + switch (dest_pix_fmt) { + case V4L2_PIX_FMT_RGB24: + v4lconvert_hm12_to_rgb24(src, dest, width, height); + break; + case V4L2_PIX_FMT_BGR24: + v4lconvert_hm12_to_bgr24(src, dest, width, height); + break; + case V4L2_PIX_FMT_YUV420: + v4lconvert_hm12_to_yuv420(src, dest, width, height, 0); + break; + case V4L2_PIX_FMT_YVU420: + v4lconvert_hm12_to_yuv420(src, dest, width, height, 1); + break; + } + break; + /* compressed bayer formats */ case V4L2_PIX_FMT_SPCA561: case V4L2_PIX_FMT_SN9C10X: |