The patch number 8219 was added via Thierry MERLE <[EMAIL PROTECTED]>
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:
        [EMAIL PROTECTED]

------

From: Hans de Goede  <[EMAIL PROTECTED]>
v4l2-library: Add support for sonix (sn9c10x) bayer compression to libv4lconvert


Add support for sonix (sn9c10x) bayer compression to libv4lconvert

Signed-off-by: Hans de Goede <[EMAIL PROTECTED]>
Signed-off-by: Thierry MERLE <[EMAIL PROTECTED]>


---

 v4l2-apps/lib/libv4l/libv4lconvert/Makefile             |    2 
 v4l2-apps/lib/libv4l/libv4lconvert/libv4lconvert-priv.h |    3 
 v4l2-apps/lib/libv4l/libv4lconvert/libv4lconvert.c      |   28 +
 v4l2-apps/lib/libv4l/libv4lconvert/sn9c10x.c            |  199 ++++++++++
 4 files changed, 226 insertions(+), 6 deletions(-)

diff -r 40ccde267263 -r 4d00cbde75be v4l2-apps/lib/libv4l/libv4lconvert/Makefile
--- a/v4l2-apps/lib/libv4l/libv4lconvert/Makefile       Thu Jul 03 20:41:07 
2008 +0200
+++ b/v4l2-apps/lib/libv4l/libv4lconvert/Makefile       Thu Jul 03 20:47:43 
2008 +0200
@@ -9,7 +9,7 @@ LDFLAGS       = -shared
 LDFLAGS       = -shared
 
 CONVERT_LIB   = libv4lconvert.so
-CONVERT_OBJS  = libv4lconvert.o tinyjpeg.o \
+CONVERT_OBJS  = libv4lconvert.o tinyjpeg.o sn9c10x.o \
                jidctflt.o spca561-decompress.o rgbyuv.o spca501.o bayer.o
 TARGETS       = $(CONVERT_LIB)
 INCLUDES      = ../include/libv4lconvert.h
diff -r 40ccde267263 -r 4d00cbde75be 
v4l2-apps/lib/libv4l/libv4lconvert/libv4lconvert-priv.h
--- a/v4l2-apps/lib/libv4l/libv4lconvert/libv4lconvert-priv.h   Thu Jul 03 
20:41:07 2008 +0200
+++ b/v4l2-apps/lib/libv4l/libv4lconvert/libv4lconvert-priv.h   Thu Jul 03 
20:47:43 2008 +0200
@@ -71,6 +71,9 @@ void v4lconvert_decode_spca561(const uns
 void v4lconvert_decode_spca561(const unsigned char *src, unsigned char *dst,
   int width, int height);
 
+void v4lconvert_decode_sn9c10x(const unsigned char *src, unsigned char *dst,
+  int width, int height);
+
 void v4lconvert_bayer_to_bgr24(const unsigned char *bayer,
   unsigned char *rgb, int width, int height, unsigned int pixfmt);
 
diff -r 40ccde267263 -r 4d00cbde75be 
v4l2-apps/lib/libv4l/libv4lconvert/libv4lconvert.c
--- a/v4l2-apps/lib/libv4l/libv4lconvert/libv4lconvert.c        Thu Jul 03 
20:41:07 2008 +0200
+++ b/v4l2-apps/lib/libv4l/libv4lconvert/libv4lconvert.c        Thu Jul 03 
20:47:43 2008 +0200
@@ -37,6 +37,7 @@ static const unsigned int supported_src_
   V4L2_PIX_FMT_SRGGB8,
   V4L2_PIX_FMT_SPCA501,
   V4L2_PIX_FMT_SPCA561,
+  V4L2_PIX_FMT_SN9C10X,
   -1
 };
 
@@ -314,23 +315,40 @@ int v4lconvert_convert(struct v4lconvert
                                     dest_fmt->fmt.pix.height);
       break;
 
+    /* compressed bayer formats */
     case V4L2_PIX_FMT_SPCA561:
+    case V4L2_PIX_FMT_SN9C10X:
     {
-      static unsigned char tmpbuf[640 * 480];
-      v4lconvert_decode_spca561(src, tmpbuf, dest_fmt->fmt.pix.width,
-                               dest_fmt->fmt.pix.height);
+      unsigned char tmpbuf[dest_fmt->fmt.pix.width*dest_fmt->fmt.pix.height];
+      unsigned int bayer_fmt;
+
+      switch (src_fmt->fmt.pix.pixelformat) {
+       case V4L2_PIX_FMT_SPCA561:
+         v4lconvert_decode_spca561(src, tmpbuf, dest_fmt->fmt.pix.width,
+                                   dest_fmt->fmt.pix.height);
+         bayer_fmt = V4L2_PIX_FMT_SGBRG8;
+         break;
+       case V4L2_PIX_FMT_SN9C10X:
+         v4lconvert_decode_sn9c10x(src, tmpbuf, dest_fmt->fmt.pix.width,
+                                   dest_fmt->fmt.pix.height);
+         bayer_fmt = V4L2_PIX_FMT_SGBRG8;
+         break;
+      }
+
       if (dest_fmt->fmt.pix.pixelformat == V4L2_PIX_FMT_BGR24)
        v4lconvert_bayer_to_bgr24(tmpbuf, dest, dest_fmt->fmt.pix.width,
-                   dest_fmt->fmt.pix.height, V4L2_PIX_FMT_SGBRG8);
+                   dest_fmt->fmt.pix.height, bayer_fmt);
       else
        v4lconvert_bayer_to_yuv420(tmpbuf, dest, dest_fmt->fmt.pix.width,
-                   dest_fmt->fmt.pix.height, V4L2_PIX_FMT_SGBRG8);
+                   dest_fmt->fmt.pix.height, bayer_fmt);
       break;
     }
+
     case V4L2_PIX_FMT_BGR24:
       /* dest must be V4L2_PIX_FMT_YUV420 then */
       printf("FIXME add bgr24 -> yuv420 conversion\n");
       break;
+
     case V4L2_PIX_FMT_YUV420:
       /* dest must be V4L2_PIX_FMT_BGR24 then */
       v4lconvert_yuv420_to_bgr24(src, dest, dest_fmt->fmt.pix.width,
diff -r 40ccde267263 -r 4d00cbde75be 
v4l2-apps/lib/libv4l/libv4lconvert/sn9c10x.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/v4l2-apps/lib/libv4l/libv4lconvert/sn9c10x.c      Thu Jul 03 20:47:43 
2008 +0200
@@ -0,0 +1,199 @@
+/*
+#             (C) 2008 Hans de Goede <[EMAIL PROTECTED]>
+
+# 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 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"
+
+/* FIXME FIXME FIXME add permission notice from Bertrik Sikken to release
+   this code (which is his) under the LGPL */
+
+#define CLAMP(x)       ((x)<0?0:((x)>255)?255:(x))
+
+typedef struct {
+       int is_abs;
+       int len;
+       int val;
+       int unk;
+} code_table_t;
+
+
+/* local storage */
+/* FIXME not thread safe !! */
+static code_table_t table[256];
+static int init_done = 0;
+
+/* global variable */
+static int sonix_unknown = 0;
+
+/*
+       sonix_decompress_init
+       =====================
+               pre-calculates a locally stored table for efficient 
huffman-decoding.
+
+       Each entry at index x in the table represents the codeword
+       present at the MSB of byte x.
+
+*/
+void sonix_decompress_init(void)
+{
+       int i;
+       int is_abs, val, len, unk;
+
+       for (i = 0; i < 256; i++) {
+               is_abs = 0;
+               val = 0;
+               len = 0;
+               unk = 0;
+               if ((i & 0x80) == 0) {
+                       /* code 0 */
+                       val = 0;
+                       len = 1;
+               }
+               else if ((i & 0xE0) == 0x80) {
+                       /* code 100 */
+                       val = +4;
+                       len = 3;
+               }
+               else if ((i & 0xE0) == 0xA0) {
+                       /* code 101 */
+                       val = -4;
+                       len = 3;
+               }
+               else if ((i & 0xF0) == 0xD0) {
+                       /* code 1101 */
+                       val = +11;
+                       len = 4;
+               }
+               else if ((i & 0xF0) == 0xF0) {
+                       /* code 1111 */
+                       val = -11;
+                       len = 4;
+               }
+               else if ((i & 0xF8) == 0xC8) {
+                       /* code 11001 */
+                       val = +20;
+                       len = 5;
+               }
+               else if ((i & 0xFC) == 0xC0) {
+                       /* code 110000 */
+                       val = -20;
+                       len = 6;
+               }
+               else if ((i & 0xFC) == 0xC4) {
+                       /* code 110001xx: unknown */
+                       val = 0;
+                       len = 8;
+                       unk = 1;
+               }
+               else if ((i & 0xF0) == 0xE0) {
+                       /* code 1110xxxx */
+                       is_abs = 1;
+                       val = (i & 0x0F) << 4;
+                       len = 8;
+               }
+               table[i].is_abs = is_abs;
+               table[i].val = val;
+               table[i].len = len;
+               table[i].unk = unk;
+       }
+
+       sonix_unknown = 0;
+       init_done = 1;
+}
+
+
+/*
+       sonix_decompress
+       ================
+               decompresses an image encoded by a SN9C101 camera controller 
chip.
+
+       IN      width
+               height
+               inp             pointer to compressed frame (with header 
already stripped)
+       OUT     outp    pointer to decompressed frame
+
+       Returns 0 if the operation was successful.
+       Returns <0 if operation failed.
+
+*/
+void v4lconvert_decode_sn9c10x(const unsigned char *inp, unsigned char *outp,
+       int width, int height)
+{
+       int row, col;
+       int val;
+       int bitpos;
+       unsigned char code;
+       unsigned char *addr;
+
+       if (!init_done)
+               sonix_decompress_init();
+
+       bitpos = 0;
+       for (row = 0; row < height; row++) {
+
+               col = 0;
+
+               /* first two pixels in first two rows are stored as raw 8-bit */
+               if (row < 2) {
+                       addr = inp + (bitpos >> 3);
+                       code = (addr[0] << (bitpos & 7)) | (addr[1] >> (8 - 
(bitpos & 7)));
+                       bitpos += 8;
+                       *outp++ = code;
+
+                       addr = inp + (bitpos >> 3);
+                       code = (addr[0] << (bitpos & 7)) | (addr[1] >> (8 - 
(bitpos & 7)));
+                       bitpos += 8;
+                       *outp++ = code;
+
+                       col += 2;
+               }
+
+               while (col < width) {
+                       /* get bitcode from bitstream */
+                       addr = inp + (bitpos >> 3);
+                       code = (addr[0] << (bitpos & 7)) | (addr[1] >> (8 - 
(bitpos & 7)));
+
+                       /* update bit position */
+                       bitpos += table[code].len;
+
+                       /* update code statistics */
+                       sonix_unknown += table[code].unk;
+
+                       /* calculate pixel value */
+                       val = table[code].val;
+                       if (!table[code].is_abs) {
+                               /* value is relative to top and left pixel */
+                               if (col < 2) {
+                                       /* left column: relative to top pixel */
+                                       val += outp[-2*width];
+                               }
+                               else if (row < 2) {
+                                       /* top row: relative to left pixel */
+                                       val += outp[-2];
+                               }
+                               else {
+                                       /* main area: average of left pixel and 
top pixel */
+                                       val += (outp[-2] + outp[-2*width]) / 2;
+                               }
+                       }
+
+                       /* store pixel */
+                       *outp++ = CLAMP(val);
+                       col++;
+               }
+       }
+}


---

Patch is available at: 
http://linuxtv.org/hg/v4l-dvb/rev/4d00cbde75bee9f2ce3302a60f22d4b5e3bc0737

_______________________________________________
linuxtv-commits mailing list
[email protected]
http://www.linuxtv.org/cgi-bin/mailman/listinfo/linuxtv-commits

Reply via email to