[PATCH] add sn9c20x-i420 decoder to libv4l-0.5.7

Vasily Khoruzhick <[email protected]> Thu, 8 Jan 2009 22:56:17 +0200
Newsgroups gmane.linux.drivers.spca50x.devel
Message-ID <[email protected]>
--===============3183349066270622764==
Content-Type: multipart/signed; boundary="nextPart1506573.8Pyuxi00LT";
	protocol="application/pgp-signature"; micalg=pgp-sha1
Content-Transfer-Encoding: 7bit

--nextPart1506573.8Pyuxi00LT
Content-Type: multipart/mixed;
  boundary="Boundary-01=_xhmZJNl/IrCbrIw"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

--Boundary-01=_xhmZJNl/IrCbrIw
Content-Type: text/plain;
  charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: inline

Hi, Hans

Recent sn9c20x driver written by microdia project=20
(http://groups.goolge.com/group/microdia) introduce new output format -=20
sn9c20x-i420. This format is actually scrambled yuv420, so it's very easy a=
nd=20
fast to convert it to yuv420. This patch adds sn9c20x-i420 decoder to the=20
libv4l-0.5.7

This decoder is much faster than jpeg one (sn9c20x supports JPEG too):=20
sn9c20x-i420 decoder eats only 10% of 1GHz CPU at 640x480x25fps vs 40% of=20
1GHz CPU in jpeg at same frame size/rate.

This format should be preffered for sn9c20x, because sn9c20x driver support=
s=20
SBGGR8 too, so it should go before SBGGR8 in supported_src_pixfmts.

Regards
Vasily

P.S. sn9c20x-i420 decoder code was originally written by myself and license=
d=20
under GPLv2 license, I grant you permission to relicense it under LGPLv2 or=
=20
later.

--Boundary-01=_xhmZJNl/IrCbrIw
Content-Type: text/x-diff; charset="iso 8859-15";
	name="0001-Added-sn9c20x-i420-decoder.patch"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
	filename="0001-Added-sn9c20x-i420-decoder.patch"

=46rom 00c284bd74c19c3f9ef8858a8ca92d17e81b2d80 Mon Sep 17 00:00:00 2001
=46rom: Vasily Khoruzhick <[email protected]>
Date: Thu, 8 Jan 2009 00:33:21 +0200
Subject: [PATCH] Added sn9c20x i420 decoder


Signed-off-by: Vasily Khoruzhick <[email protected]>
=2D--
 libv4lconvert/Makefile             |    2 +-
 libv4lconvert/libv4lconvert-priv.h |    7 ++
 libv4lconvert/libv4lconvert.c      |    5 ++
 libv4lconvert/sn9c20x.c            |  137 ++++++++++++++++++++++++++++++++=
++++
 4 files changed, 150 insertions(+), 1 deletions(-)
 create mode 100644 libv4lconvert/sn9c20x.c

diff --git a/libv4lconvert/Makefile b/libv4lconvert/Makefile
index 65748bb..011949b 100644
=2D-- a/libv4lconvert/Makefile
+++ b/libv4lconvert/Makefile
@@ -10,7 +10,7 @@ CONVERT_LIB   =3D libv4lconvert.so
 override CPPFLAGS +=3D -fPIC
 endif
=20
=2DCONVERT_OBJS  =3D libv4lconvert.o tinyjpeg.o sn9c10x.o pac207.o flip.o c=
rop.o \
+CONVERT_OBJS  =3D 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       =3D $(CONVERT_LIB) libv4lconvert.pc
 INCLUDES      =3D ../include/libv4lconvert.h
diff --git a/libv4lconvert/libv4lconvert-priv.h b/libv4lconvert/libv4lconve=
rt-priv.h
index 55a5b49..f34036d 100644
=2D-- a/libv4lconvert/libv4lconvert-priv.h
+++ b/libv4lconvert/libv4lconvert-priv.h
@@ -63,6 +63,10 @@
 #define V4L2_PIX_FMT_YVYU v4l2_fourcc('Y', 'V', 'Y', 'U')
 #endif
=20
+#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
 #define V4LCONVERT_MAX_FRAMESIZES 16
=20
@@ -147,6 +151,9 @@ void v4lconvert_spca505_to_yuv420(const unsigned char *=
src, unsigned char *dst,
 void v4lconvert_spca508_to_yuv420(const unsigned char *src, unsigned char =
*dst,
   int width, int height, int yvu);
=20
+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 *ds=
t,
   int width, int height);
=20
diff --git a/libv4lconvert/libv4lconvert.c b/libv4lconvert/libv4lconvert.c
index b3487b6..e123d7b 100644
=2D-- a/libv4lconvert/libv4lconvert.c
+++ b/libv4lconvert/libv4lconvert.c
@@ -44,6 +44,7 @@ static const struct v4lconvert_pixfmt supported_src_pixfm=
ts[] =3D {
   SUPPORTED_DST_PIXFMTS,
   { V4L2_PIX_FMT_YUYV,    0 },
   { V4L2_PIX_FMT_YVYU,    0 },
+  { V4L2_PIX_FMT_SN9C20X_I420, 0 },
   { V4L2_PIX_FMT_SBGGR8,  0 },
   { V4L2_PIX_FMT_SGBRG8,  0 },
   { V4L2_PIX_FMT_SGRBG8,  0 },
@@ -538,6 +539,7 @@ static int v4lconvert_convert_pixfmt(struct v4lconvert_=
data *data,
     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 =3D 0;
@@ -564,6 +566,9 @@ static int v4lconvert_convert_pixfmt(struct v4lconvert_=
data *data,
 	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;
       }
=20
       switch (dest_pix_fmt) {
diff --git a/libv4lconvert/sn9c20x.c b/libv4lconvert/sn9c20x.c
new file mode 100644
index 0000000..4817079
=2D-- /dev/null
+++ b/libv4lconvert/sn9c20x.c
@@ -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 publishe=
d 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  U=
SA
+ *
+ * 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] =3D {0, 1, 2, 3,=20
+			8, 9, 10, 11,=20
+			16, 17, 18, 19,=20
+			24, 25, 26, 27,=20
+			4, 5, 6, 7,
+			12, 13, 14, 15,
+			20, 21, 22, 23,
+			28, 29, 30, 31};
+
+static const int Y_coords_624x[128][2] =3D {
+{ 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 =3D buf[i + 128 + j];
+}
+
+static void do_write_v(const unsigned char *buf, unsigned char *ptr,
+	int i, int j)
+{
+	*ptr =3D buf[i + 160 + j];
+}
+
+void v4lconvert_sn9c20x_to_yuv420(const unsigned char *raw, unsigned char =
*i420,
+  int width, int height, int yvu)
+{
+	int i =3D 0, x =3D 0, y =3D 0, j, relX, relY, x_div2, y_div2;
+	const unsigned char *buf =3D raw;
+	unsigned char *ptr;
+	int frame_size =3D width * height;
+	int frame_size_div2 =3D frame_size >> 1;
+	int frame_size_div4 =3D frame_size >> 2;
+	int width_div2 =3D width >> 1;
+	int height_div2 =3D height >> 1;
+	void (*do_write_uv1)(const unsigned char *buf, unsigned char *ptr, int i,
+	int j) =3D NULL;
+	void (*do_write_uv2)(const unsigned char *buf, unsigned char *ptr, int i,
+	int j) =3D NULL;
+
+	if (yvu) {
+		do_write_uv1 =3D do_write_v;
+		do_write_uv2 =3D do_write_u;
+	}
+	else {
+		do_write_uv1 =3D do_write_u;
+		do_write_uv2 =3D do_write_v;
+	}
+
+	while (i < (frame_size + frame_size_div2)) {
+		for (j =3D 0; j < 128; j++) {
+			relX =3D x + Y_coords_624x[j][0];
+			relY =3D y + Y_coords_624x[j][1];
+
+#if (DO_SANITY_CHECKS=3D=3D1)
+			if ((relX < width) && (relY < height)) {
+#endif
+				ptr =3D i420 + relY * width + relX;
+				*ptr =3D buf[i + j];
+#if (DO_SANITY_CHECKS=3D=3D1)
+			}
+#endif
+
+		}
+		x_div2 =3D x >> 1;
+		y_div2 =3D y >> 1;
+		for (j =3D 0; j < 32; j++) {
+			relX =3D (x_div2) + (j & 0x07);
+			relY =3D (y_div2) + (j >> 3);
+
+#if (DO_SANITY_CHECKS=3D=3D1)
+			if ((relX < width_div2) && (relY < height_div2)) {
+#endif
+				ptr =3D i420 + frame_size +
+					relY * width_div2 + relX;
+				do_write_uv1(buf, ptr, i, j);
+				ptr +=3D frame_size_div4;
+				do_write_uv2(buf, ptr, i, j);
+#if (DO_SANITY_CHECKS=3D=3D1)
+			}
+#endif
+		}
+
+		i +=3D 192;
+		x +=3D 16;
+		if (x >=3D width) {
+			x =3D 0;
+			y +=3D 8;
+		}
+	}
+}
=2D-=20
1.6.0.6


--Boundary-01=_xhmZJNl/IrCbrIw--

--nextPart1506573.8Pyuxi00LT
Content-Type: application/pgp-signature; name=signature.asc 
Content-Description: This is a digitally signed message part.

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.9 (GNU/Linux)

iEYEABECAAYFAklmaIQACgkQRM6pQpltKE7HUgCdFdIM1hcHj4AflaKT2qleQN0i
8UoAnA278E9e8brPOzEWfVzDypt8Oktk
=6/Nw
-----END PGP SIGNATURE-----

--nextPart1506573.8Pyuxi00LT--


--===============3183349066270622764==
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

------------------------------------------------------------------------------
Check out the new SourceForge.net Marketplace.
It is the best place to buy or sell services for
just about anything Open Source.
http://p.sf.net/sfu/Xq1LFB
--===============3183349066270622764==
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

_______________________________________________
Spca50x-devs mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/spca50x-devs

--===============3183349066270622764==--