summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--v4l2-apps/libv4l/ChangeLog1
-rw-r--r--v4l2-apps/libv4l/libv4lconvert/libv4lconvert-priv.h7
-rw-r--r--v4l2-apps/libv4l/libv4lconvert/libv4lconvert.c7
-rw-r--r--v4l2-apps/libv4l/libv4lconvert/sn9c2028-decomp.c157
4 files changed, 172 insertions, 0 deletions
diff --git a/v4l2-apps/libv4l/ChangeLog b/v4l2-apps/libv4l/ChangeLog
index 56a9714bd..1cdbedb9e 100644
--- a/v4l2-apps/libv4l/ChangeLog
+++ b/v4l2-apps/libv4l/ChangeLog
@@ -9,6 +9,7 @@ libv4l-0.6.1
it from the apps (do not assume it always needs conversion)
* Change controls shm segment name to include the username, as it is only
writable by the user (this means libv4l controls are per user) (Gregor Jasny)
+* Add support for decompressing sn9c2028 compressed bayer (Theodore Kilgore)
libv4l-0.6.0
------------
diff --git a/v4l2-apps/libv4l/libv4lconvert/libv4lconvert-priv.h b/v4l2-apps/libv4l/libv4lconvert/libv4lconvert-priv.h
index f10f3f607..05549e6b5 100644
--- a/v4l2-apps/libv4l/libv4lconvert/libv4lconvert-priv.h
+++ b/v4l2-apps/libv4l/libv4lconvert/libv4lconvert-priv.h
@@ -52,6 +52,10 @@
#define V4L2_PIX_FMT_MR97310A v4l2_fourcc('M','3','1','0')
#endif
+#ifndef V4L2_PIX_FMT_SN9C2028
+#define V4L2_PIX_FMT_SN9C2028 v4l2_fourcc('S', 'O', 'N', 'X')
+#endif
+
#ifndef V4L2_PIX_FMT_SQ905C
#define V4L2_PIX_FMT_SQ905C v4l2_fourcc('9', '0', '5', 'C')
#endif
@@ -219,6 +223,9 @@ int v4lconvert_decode_pac207(struct v4lconvert_data *data,
void v4lconvert_decode_mr97310a(const unsigned char *src, unsigned char *dst,
int width, int height);
+void v4lconvert_decode_sn9c2028(const unsigned char *src, unsigned char *dst,
+ int width, int height);
+
void v4lconvert_decode_sq905c(const unsigned char *src, unsigned char *dst,
int width, int height);
diff --git a/v4l2-apps/libv4l/libv4lconvert/libv4lconvert.c b/v4l2-apps/libv4l/libv4lconvert/libv4lconvert.c
index be4553cc7..b35254e4b 100644
--- a/v4l2-apps/libv4l/libv4lconvert/libv4lconvert.c
+++ b/v4l2-apps/libv4l/libv4lconvert/libv4lconvert.c
@@ -60,6 +60,7 @@ static const struct v4lconvert_pixfmt supported_src_pixfmts[] = {
{ V4L2_PIX_FMT_JPEG, V4LCONVERT_COMPRESSED },
{ V4L2_PIX_FMT_SPCA561, V4LCONVERT_COMPRESSED_AND_NEEDS_CONVERSION },
{ V4L2_PIX_FMT_SN9C10X, V4LCONVERT_COMPRESSED_AND_NEEDS_CONVERSION },
+ { V4L2_PIX_FMT_SN9C2028, V4LCONVERT_COMPRESSED_AND_NEEDS_CONVERSION },
{ V4L2_PIX_FMT_PAC207, V4LCONVERT_COMPRESSED_AND_NEEDS_CONVERSION },
{ V4L2_PIX_FMT_MR97310A, V4LCONVERT_COMPRESSED_AND_NEEDS_CONVERSION },
{ V4L2_PIX_FMT_SQ905C, V4LCONVERT_COMPRESSED_AND_NEEDS_CONVERSION },
@@ -493,6 +494,7 @@ static int v4lconvert_processing_needs_double_conversion(
case V4L2_PIX_FMT_SN9C10X:
case V4L2_PIX_FMT_PAC207:
case V4L2_PIX_FMT_MR97310A:
+ case V4L2_PIX_FMT_SN9C2028:
case V4L2_PIX_FMT_SQ905C:
case V4L2_PIX_FMT_SBGGR8:
case V4L2_PIX_FMT_SGBRG8:
@@ -727,6 +729,7 @@ static int v4lconvert_convert_pixfmt(struct v4lconvert_data *data,
case V4L2_PIX_FMT_SN9C10X:
case V4L2_PIX_FMT_PAC207:
case V4L2_PIX_FMT_MR97310A:
+ case V4L2_PIX_FMT_SN9C2028:
case V4L2_PIX_FMT_SQ905C:
{
unsigned char *tmpbuf;
@@ -759,6 +762,10 @@ static int v4lconvert_convert_pixfmt(struct v4lconvert_data *data,
v4lconvert_decode_mr97310a(src, tmpbuf, width, height);
tmpfmt.fmt.pix.pixelformat = V4L2_PIX_FMT_SBGGR8;
break;
+ case V4L2_PIX_FMT_SN9C2028:
+ v4lconvert_decode_sn9c2028(src, tmpbuf, width, height);
+ tmpfmt.fmt.pix.pixelformat = V4L2_PIX_FMT_SBGGR8;
+ break;
case V4L2_PIX_FMT_SQ905C:
v4lconvert_decode_sq905c(src, tmpbuf, width, height);
tmpfmt.fmt.pix.pixelformat = V4L2_PIX_FMT_SRGGB8;
diff --git a/v4l2-apps/libv4l/libv4lconvert/sn9c2028-decomp.c b/v4l2-apps/libv4l/libv4lconvert/sn9c2028-decomp.c
new file mode 100644
index 000000000..c21696752
--- /dev/null
+++ b/v4l2-apps/libv4l/libv4lconvert/sn9c2028-decomp.c
@@ -0,0 +1,157 @@
+/*
+ * sn9c2028-decomp.c
+ *
+ * Decompression function for the Sonix SN9C2028 dual-mode cameras.
+ *
+ * Code adapted from libgphoto2/camlibs/sonix, original version of which was
+ * Copyright (c) 2005 Theodore Kilgore <kilgota@auburn.edu>
+ *
+ * History:
+ *
+ * This decoding algorithm originates from the work of Bertrik Sikken for the
+ * SN9C102 cameras. This version is an adaptation of work done by Mattias
+ * Krauss for the webcam-osx (macam) project. There, it was further adapted
+ * for use with the Vivitar Vivicam 3350B (an SN9C2028 camera) by
+ * Harald Ruda <hrx@users.sourceforge.net>. Harald brought to my attention the
+ * work done in the macam project and suggested that I use it. One improvement
+ * of my own was to notice that the even and odd columns of the image have been
+ * reversed by the decompression algorithm, and this needs to be corrected
+ * during the decompression.
+ *
+ *
+ * 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"
+
+/* Four defines for bitstream operations, used in the decode function */
+
+#define PEEK_BITS(num,to) {\
+ if (bitBufCount < num) {\
+ do {\
+ bitBuf = (bitBuf << 8)|(*(src++));\
+ bitBufCount += 8; \
+ } \
+ while\
+ (bitBufCount < 24);\
+ } \
+ to = bitBuf >> (bitBufCount-num);\
+}
+
+/*
+ * PEEK_BITS puts the next <num> bits into the low bits of <to>.
+ * when the buffer is empty, it is completely refilled.
+ * This strategy tries to reduce memory access. Note that the high bits
+ * are NOT set to zero!
+ */
+
+#define EAT_BITS(num) { bitBufCount -= num; bits_eaten += num; }
+
+/*
+ * EAT_BITS consumes <num> bits (PEEK_BITS does not consume anything,
+ * it just peeks)
+ */
+
+#define PARSE_PIXEL(val) {\
+ PEEK_BITS(10, bits);\
+ if ((bits&0x200) == 0) {\
+ EAT_BITS(1);\
+ } \
+ else if ((bits&0x380) == 0x280) {\
+ EAT_BITS(3);\
+ val += 3;\
+ if (val > 255)\
+ val = 255;\
+ } \
+ else if ((bits&0x380) == 0x300) {\
+ EAT_BITS(3);\
+ val -= 3;\
+ if (val < 0)\
+ val = 0;\
+ } \
+ else if ((bits&0x3c0) == 0x200) {\
+ EAT_BITS(4);\
+ val += 8;\
+ if (val > 255)\
+ val = 255;\
+ } \
+ else if ((bits&0x3c0) == 0x240) {\
+ EAT_BITS(4);\
+ val -= 8;\
+ if (val < 0)\
+ val = 0;\
+ } \
+ else if ((bits&0x3c0) == 0x3c0) {\
+ EAT_BITS(4);\
+ val -= 20;\
+ if (val < 0)\
+ val = 0;\
+ } \
+ else if ((bits&0x3e0) == 0x380) {\
+ EAT_BITS(5);\
+ val += 20;\
+ if (val > 255)\
+ val = 255;\
+ } \
+ else {\
+ EAT_BITS(10);\
+ val = 8*(bits&0x1f)+0;\
+ } \
+}
+
+
+#define PUT_PIXEL_PAIR {\
+ long pp;\
+ pp = (c1val<<8)+c2val;\
+ *((unsigned short *) (dst+dst_index)) = pp;\
+ dst_index += 2;\
+}
+
+/* Now the decode function itself */
+
+void v4lconvert_decode_sn9c2028(const unsigned char *src, unsigned char *dst,
+ int width, int height)
+{
+ long dst_index = 0;
+ int starting_row = 0;
+ unsigned short bits;
+ short c1val, c2val;
+ int x, y;
+ unsigned long bitBuf = 0;
+ unsigned long bitBufCount = 0;
+ unsigned long bits_eaten = 0;
+
+ src += 12; /* Remove the header */
+
+ for (y = starting_row; y < height; y++) {
+ PEEK_BITS(8, bits);
+ EAT_BITS(8);
+ c2val = (bits & 0xff);
+ PEEK_BITS(8, bits);
+ EAT_BITS(8);
+ c1val = (bits & 0xff);
+
+ PUT_PIXEL_PAIR;
+
+ for (x = 2; x < width ; x += 2) {
+ /* The compression reversed the even and odd columns.*/
+ PARSE_PIXEL(c2val);
+ PARSE_PIXEL(c1val);
+ PUT_PIXEL_PAIR;
+ }
+ }
+}