Skip to contentSkip to conversation

PATCH: Add support for sonix (sn9c10x) bayer compression to libv4lconvert

PATCH Hans de Goede 2 participants 2 messages Jul 3, 2008 Media (V4L/DVB)

lore
Share & tools
lore
#0 lore raw

Hi,

This patch adds support for sonix (sn9c10x) bayer compression to libv4lconvert.

Regards,

Hans

Add support for sonix (sn9c10x) bayer compression to libv4lconvert

v4l2-apps/lib/libv4l/libv4lconvert/Makefile +1 -1
diff -r e90ac66913c6 v4l2-apps/lib/libv4l/libv4lconvert/Makefile
@@ -9,7 +9,7 @@
 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
v4l2-apps/lib/libv4l/libv4lconvert/libv4lconvert-priv.h +3 -0
diff -r e90ac66913c6 v4l2-apps/lib/libv4l/libv4lconvert/libv4lconvert-priv.h
@@ -71,6 +71,9 @@
 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);
 
v4l2-apps/lib/libv4l/libv4lconvert/libv4lconvert.c +23 -5
diff -r e90ac66913c6 v4l2-apps/lib/libv4l/libv4lconvert/libv4lconvert.c
@@ -37,6 +37,7 @@
   V4L2_PIX_FMT_SRGGB8,
   V4L2_PIX_FMT_SPCA501,
   V4L2_PIX_FMT_SPCA561,
+  V4L2_PIX_FMT_SN9C10X,
   -1
 };
 
@@ -314,23 +315,40 @@
 				     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,
v4l2-apps/lib/libv4l/libv4lconvert/sn9c10x.c new file +199 -0

199 lines not on this page · raw message

--
video4linux-list mailing list
Unsubscribe mailto:[email protected]?subject=unsubscribe
https://www.redhat.com/mailman/listinfo/video4linux-list

#1 lore raw
Quoted 287 lines · Hans de Goede

Hi,

This patch adds support for sonix (sn9c10x) bayer compression to libv4lconvert.

Regards,

Hans
Add support for sonix (sn9c10x) bayer compression to libv4lconvert

diff -r e90ac66913c6 v4l2-apps/lib/libv4l/libv4lconvert/Makefile

v4l2-apps/lib/libv4l/libv4lconvert/Makefile +1 -1
@@ -9,7 +9,7 @@
 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 e90ac66913c6 v4l2-apps/lib/libv4l/libv4lconvert/libv4lconvert-priv.h

v4l2-apps/lib/libv4l/libv4lconvert/libv4lconvert-priv.h +3 -0
@@ -71,6 +71,9 @@
 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 e90ac66913c6 v4l2-apps/lib/libv4l/libv4lconvert/libv4lconvert.c

v4l2-apps/lib/libv4l/libv4lconvert/libv4lconvert.c +23 -5
@@ -37,6 +37,7 @@
   V4L2_PIX_FMT_SRGGB8,
   V4L2_PIX_FMT_SPCA501,
   V4L2_PIX_FMT_SPCA561,
+  V4L2_PIX_FMT_SN9C10X,
   -1
 };
 
@@ -314,23 +315,40 @@
 				     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 e90ac66913c6 v4l2-apps/lib/libv4l/libv4lconvert/sn9c10x.c

v4l2-apps/lib/libv4l/libv4lconvert/sn9c10x.c new file +189 -0
@@ -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 */

v4l2-apps/lib/libv4l/libv4lconvert/sn9c10x.c line 199

Quoted 10 lines
v4l2-apps/lib/libv4l/libv4lconvert/sn9c10x.c new file +10 -0
+					val += (outp[-2] + outp[-2*width]) / 2;
+				}
+			}
+
+			/* store pixel */
+			*outp++ = CLAMP(val);
+			col++;
+		}
+	}
+}

Applied on http://www.linuxtv.org/hg/~tmerle/v4l2-library

Cheers,

Thierry

--
video4linux-list mailing list
Unsubscribe mailto:[email protected]?subject=unsubscribe
https://www.redhat.com/mailman/listinfo/video4linux-list