summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--v4l2-apps/libv4l/ChangeLog2
-rw-r--r--v4l2-apps/libv4l/libv4lconvert/Makefile2
-rw-r--r--v4l2-apps/libv4l/libv4lconvert/hm12.c159
-rw-r--r--v4l2-apps/libv4l/libv4lconvert/libv4lconvert-priv.h13
-rw-r--r--v4l2-apps/libv4l/libv4lconvert/libv4lconvert.c19
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: