The patch number 11008 was added via h...@rhel5-devel.localdomain to http://linuxtv.org/hg/v4l-dvb master development tree.
Kernel patches in this development tree may be modified to be backward compatible with older kernels. Compatibility modifications will be removed before inclusion into the mainstream Kernel If anyone has any objections, please let us know by sending a message to: Linux Media Mailing List <linux-me...@vger.kernel.org> ------ From: Vasily Khoruzhick <anars...@gmail.com> libv4l: add sn9c20x-i420 decoder Recent sn9c20x driver written by microdia project (http://groups.goolge.com/group/microdia) introduce new output format - sn9c20x-i420. This format is actually scrambled yuv420, so it's very easy and fast to convert it to yuv420. This patch adds sn9c20x-i420 decoder to the libv4l-0.5.7 This decoder is much faster than jpeg one (sn9c20x supports JPEG too): sn9c20x-i420 decoder eats only 10% of 1GHz CPU at 640x480x25fps vs 40% of 1GHz CPU in jpeg at same frame size/rate. This format should be preffered for sn9c20x, because sn9c20x driver supports SBGGR8 too, so it should go before SBGGR8 in supported_src_pixfmts. Priority: normal Signed-off-by: Vasily Khoruzhick <anars...@gmail.com> Signed-off-by: Hans de Goede <hdego...@redhat.com --- v4l2-apps/libv4l/ChangeLog | 2 v4l2-apps/libv4l/libv4lconvert/Makefile | 2 v4l2-apps/libv4l/libv4lconvert/libv4lconvert-priv.h | 7 v4l2-apps/libv4l/libv4lconvert/libv4lconvert.c | 7 v4l2-apps/libv4l/libv4lconvert/sn9c20x.c | 137 ++++++++++++ 5 files changed, 153 insertions(+), 2 deletions(-) diff -r e647b7aba85a -r a220b0585970 v4l2-apps/libv4l/ChangeLog --- a/v4l2-apps/libv4l/ChangeLog Wed Mar 11 13:23:30 2009 +0100 +++ b/v4l2-apps/libv4l/ChangeLog Wed Mar 11 13:26:09 2009 +0100 @@ -8,6 +8,8 @@ libv4l-0.5.8 * Switch to using USB-id's instead of USB product string, as not all devices set a unique product string. This fixes the upside down issues with genius e-messenger 112 cams +* Add support for sn9c20x-i420 format patch by Vasily Khoruzhick + <anars...@gmail.com> libv4l-0.5.7 ------------ diff -r e647b7aba85a -r a220b0585970 v4l2-apps/libv4l/libv4lconvert/Makefile --- a/v4l2-apps/libv4l/libv4lconvert/Makefile Wed Mar 11 13:23:30 2009 +0100 +++ b/v4l2-apps/libv4l/libv4lconvert/Makefile Wed Mar 11 13:26:09 2009 +0100 @@ -10,7 +10,7 @@ override CPPFLAGS += -fPIC override CPPFLAGS += -fPIC endif -CONVERT_OBJS = libv4lconvert.o tinyjpeg.o sn9c10x.o pac207.o flip.o crop.o \ +CONVERT_OBJS = libv4lconvert.o tinyjpeg.o sn9c10x.o sn9c20x.o pac207.o flip.o crop.o \ jidctflt.o spca561-decompress.o rgbyuv.o spca501.o bayer.o TARGETS = $(CONVERT_LIB) libv4lconvert.pc INCLUDES = ../include/libv4lconvert.h diff -r e647b7aba85a -r a220b0585970 v4l2-apps/libv4l/libv4lconvert/libv4lconvert-priv.h --- a/v4l2-apps/libv4l/libv4lconvert/libv4lconvert-priv.h Wed Mar 11 13:23:30 2009 +0100 +++ b/v4l2-apps/libv4l/libv4lconvert/libv4lconvert-priv.h Wed Mar 11 13:26:09 2009 +0100 @@ -61,6 +61,10 @@ #ifndef V4L2_PIX_FMT_YVYU #define V4L2_PIX_FMT_YVYU v4l2_fourcc('Y', 'V', 'Y', 'U') +#endif + +#ifndef V4L2_PIX_FMT_SN9C20X_I420 +#define V4L2_PIX_FMT_SN9C20X_I420 v4l2_fourcc('S', '9', '2', '0') #endif #define V4LCONVERT_ERROR_MSG_SIZE 256 @@ -157,6 +161,9 @@ void v4lconvert_spca508_to_yuv420(const void v4lconvert_spca508_to_yuv420(const unsigned char *src, unsigned char *dst, int width, int height, int yvu); +void v4lconvert_sn9c20x_to_yuv420(const unsigned char *src, unsigned char *dst, + int width, int height, int yvu); + void v4lconvert_decode_spca561(const unsigned char *src, unsigned char *dst, int width, int height); diff -r e647b7aba85a -r a220b0585970 v4l2-apps/libv4l/libv4lconvert/libv4lconvert.c --- a/v4l2-apps/libv4l/libv4lconvert/libv4lconvert.c Wed Mar 11 13:23:30 2009 +0100 +++ b/v4l2-apps/libv4l/libv4lconvert/libv4lconvert.c Wed Mar 11 13:26:09 2009 +0100 @@ -47,6 +47,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_SN9C20X_I420, 0 }, { V4L2_PIX_FMT_SBGGR8, 0 }, { V4L2_PIX_FMT_SGBRG8, 0 }, { V4L2_PIX_FMT_SGRBG8, 0 }, @@ -572,10 +573,11 @@ static int v4lconvert_convert_pixfmt(str } break; - /* YUYV line by line formats */ + /* Custom cam specific YUV formats */ case V4L2_PIX_FMT_SPCA501: case V4L2_PIX_FMT_SPCA505: case V4L2_PIX_FMT_SPCA508: + case V4L2_PIX_FMT_SN9C20X_I420: { unsigned char *d; int yvu = 0; @@ -601,6 +603,9 @@ static int v4lconvert_convert_pixfmt(str break; case V4L2_PIX_FMT_SPCA508: v4lconvert_spca508_to_yuv420(src, d, width, height, yvu); + break; + case V4L2_PIX_FMT_SN9C20X_I420: + v4lconvert_sn9c20x_to_yuv420(src, d, width, height, yvu); break; } diff -r e647b7aba85a -r a220b0585970 v4l2-apps/libv4l/libv4lconvert/sn9c20x.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/v4l2-apps/libv4l/libv4lconvert/sn9c20x.c Wed Mar 11 13:26:09 2009 +0100 @@ -0,0 +1,137 @@ +/* + * Sonix SN9C20X decoder + * Vasily Khoruzhick, (C) 2008-2009 + * Algorithm based on Java code written by Jens on microdia google group + * + * 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 + * + * Note this code was originally licensed under the GNU GPL instead of the + * GNU LGPL, its license has been changed by its author. + */ + +#include "libv4lconvert-priv.h" + +#define DO_SANITY_CHECKS 0 + +static const int UVTranslate[32] = {0, 1, 2, 3, + 8, 9, 10, 11, + 16, 17, 18, 19, + 24, 25, 26, 27, + 4, 5, 6, 7, + 12, 13, 14, 15, + 20, 21, 22, 23, + 28, 29, 30, 31}; + +static const int Y_coords_624x[128][2] = { +{ 0, 0}, { 1, 0}, { 2, 0}, { 3, 0}, { 4, 0}, { 5, 0}, { 6, 0}, { 7, 0}, +{ 0, 1}, { 1, 1}, { 2, 1}, { 3, 1}, { 4, 1}, { 5, 1}, { 6, 1}, { 7, 1}, +{ 0, 2}, { 1, 2}, { 2, 2}, { 3, 2}, { 4, 2}, { 5, 2}, { 6, 2}, { 7, 2}, +{ 0, 3}, { 1, 3}, { 2, 3}, { 3, 3}, { 4, 3}, { 5, 3}, { 6, 3}, { 7, 3}, + +{ 0, 4}, { 1, 4}, { 2, 4}, { 3, 4}, { 4, 4}, { 5, 4}, { 6, 4}, { 7, 4}, +{ 0, 5}, { 1, 5}, { 2, 5}, { 3, 5}, { 4, 5}, { 5, 5}, { 6, 5}, { 7, 5}, +{ 0, 6}, { 1, 6}, { 2, 6}, { 3, 6}, { 4, 6}, { 5, 6}, { 6, 6}, { 7, 6}, +{ 0, 7}, { 1, 7}, { 2, 7}, { 3, 7}, { 4, 7}, { 5, 7}, { 6, 7}, { 7, 7}, + +{ 8, 0}, { 9, 0}, {10, 0}, {11, 0}, {12, 0}, {13, 0}, {14, 0}, {15, 0}, +{ 8, 1}, { 9, 1}, {10, 1}, {11, 1}, {12, 1}, {13, 1}, {14, 1}, {15, 1}, +{ 8, 2}, { 9, 2}, {10, 2}, {11, 2}, {12, 2}, {13, 2}, {14, 2}, {15, 2}, +{ 8, 3}, { 9, 3}, {10, 3}, {11, 3}, {12, 3}, {13, 3}, {14, 3}, {15, 3}, + +{ 8, 4}, { 9, 4}, {10, 4}, {11, 4}, {12, 4}, {13, 4}, {14, 4}, {15, 4}, +{ 8, 5}, { 9, 5}, {10, 5}, {11, 5}, {12, 5}, {13, 5}, {14, 5}, {15, 5}, +{ 8, 6}, { 9, 6}, {10, 6}, {11, 6}, {12, 6}, {13, 6}, {14, 6}, {15, 6}, +{ 8, 7}, { 9, 7}, {10, 7}, {11, 7}, {12, 7}, {13, 7}, {14, 7}, {15, 7} +}; + +static void do_write_u(const unsigned char *buf, unsigned char *ptr, + int i, int j) +{ + *ptr = buf[i + 128 + j]; +} + +static void do_write_v(const unsigned char *buf, unsigned char *ptr, + int i, int j) +{ + *ptr = buf[i + 160 + j]; +} + +void v4lconvert_sn9c20x_to_yuv420(const unsigned char *raw, unsigned char *i420, + int width, int height, int yvu) +{ + int i = 0, x = 0, y = 0, j, relX, relY, x_div2, y_div2; + const unsigned char *buf = raw; + unsigned char *ptr; + int frame_size = width * height; + int frame_size_div2 = frame_size >> 1; + int frame_size_div4 = frame_size >> 2; + int width_div2 = width >> 1; + int height_div2 = height >> 1; + void (*do_write_uv1)(const unsigned char *buf, unsigned char *ptr, int i, + int j) = NULL; + void (*do_write_uv2)(const unsigned char *buf, unsigned char *ptr, int i, + int j) = NULL; + + if (yvu) { + do_write_uv1 = do_write_v; + do_write_uv2 = do_write_u; + } + else { + do_write_uv1 = do_write_u; + do_write_uv2 = do_write_v; + } + + while (i < (frame_size + frame_size_div2)) { + for (j = 0; j < 128; j++) { + relX = x + Y_coords_624x[j][0]; + relY = y + Y_coords_624x[j][1]; + +#if (DO_SANITY_CHECKS==1) + if ((relX < width) && (relY < height)) { +#endif + ptr = i420 + relY * width + relX; + *ptr = buf[i + j]; +#if (DO_SANITY_CHECKS==1) + } +#endif + + } + x_div2 = x >> 1; + y_div2 = y >> 1; + for (j = 0; j < 32; j++) { + relX = (x_div2) + (j & 0x07); + relY = (y_div2) + (j >> 3); + +#if (DO_SANITY_CHECKS==1) + if ((relX < width_div2) && (relY < height_div2)) { +#endif + ptr = i420 + frame_size + + relY * width_div2 + relX; + do_write_uv1(buf, ptr, i, j); + ptr += frame_size_div4; + do_write_uv2(buf, ptr, i, j); +#if (DO_SANITY_CHECKS==1) + } +#endif + } + + i += 192; + x += 16; + if (x >= width) { + x = 0; + y += 8; + } + } +} --- Patch is available at: http://linuxtv.org/hg/v4l-dvb/rev/a220b0585970ddb5424a4aad0565f3d64d4ce7aa _______________________________________________ linuxtv-commits mailing list linuxtv-commits@linuxtv.org http://www.linuxtv.org/cgi-bin/mailman/listinfo/linuxtv-commits