diff options
-rw-r--r-- | v4l2-apps/libv4l/ChangeLog | 1 | ||||
-rw-r--r-- | v4l2-apps/libv4l/libv4lconvert/libv4lconvert-priv.h | 7 | ||||
-rw-r--r-- | v4l2-apps/libv4l/libv4lconvert/libv4lconvert.c | 7 | ||||
-rw-r--r-- | v4l2-apps/libv4l/libv4lconvert/sn9c2028-decomp.c | 157 |
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; + } + } +} |