diff options
author | Thierry MERLE <thierry.merle@free.fr> | 2008-07-03 20:47:43 +0200 |
---|---|---|
committer | Thierry MERLE <thierry.merle@free.fr> | 2008-07-03 20:47:43 +0200 |
commit | 289901010b302b8f7cf3f1750b38a4ea702bd484 (patch) | |
tree | 43e08d9152a0a838df90b1ed72cf1679f6216bf2 /v4l2-apps/lib | |
parent | 9530d8bebf9a1259505bbe3b9ff237795bff3bee (diff) | |
download | mediapointer-dvb-s2-289901010b302b8f7cf3f1750b38a4ea702bd484.tar.gz mediapointer-dvb-s2-289901010b302b8f7cf3f1750b38a4ea702bd484.tar.bz2 |
v4l2-library: Add support for sonix (sn9c10x) bayer compression to libv4lconvert
From: Hans de Goede <j.w.r.degoede@hhs.nl>
Add support for sonix (sn9c10x) bayer compression to libv4lconvert
Signed-off-by: Hans de Goede <j.w.r.degoede@hhs.nl>
Signed-off-by: Thierry MERLE <thierry.merle@free.fr>
Diffstat (limited to 'v4l2-apps/lib')
-rw-r--r-- | v4l2-apps/lib/libv4l/libv4lconvert/Makefile | 2 | ||||
-rw-r--r-- | v4l2-apps/lib/libv4l/libv4lconvert/libv4lconvert-priv.h | 3 | ||||
-rw-r--r-- | v4l2-apps/lib/libv4l/libv4lconvert/libv4lconvert.c | 28 | ||||
-rw-r--r-- | v4l2-apps/lib/libv4l/libv4lconvert/sn9c10x.c | 199 |
4 files changed, 226 insertions, 6 deletions
diff --git a/v4l2-apps/lib/libv4l/libv4lconvert/Makefile b/v4l2-apps/lib/libv4l/libv4lconvert/Makefile index cbd54f471..9be0903e3 100644 --- a/v4l2-apps/lib/libv4l/libv4lconvert/Makefile +++ b/v4l2-apps/lib/libv4l/libv4lconvert/Makefile @@ -9,7 +9,7 @@ CFLAGS += -Wall -W -Wno-unused -Wpointer-arith -Wstrict-prototypes 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 --git a/v4l2-apps/lib/libv4l/libv4lconvert/libv4lconvert-priv.h b/v4l2-apps/lib/libv4l/libv4lconvert/libv4lconvert-priv.h index ce050119e..db88bfae2 100644 --- a/v4l2-apps/lib/libv4l/libv4lconvert/libv4lconvert-priv.h +++ b/v4l2-apps/lib/libv4l/libv4lconvert/libv4lconvert-priv.h @@ -71,6 +71,9 @@ void v4lconvert_spca501_to_bgr24(const unsigned char *src, unsigned char *dst, 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 --git a/v4l2-apps/lib/libv4l/libv4lconvert/libv4lconvert.c b/v4l2-apps/lib/libv4l/libv4lconvert/libv4lconvert.c index ad94c4ef3..b6d238c66 100644 --- a/v4l2-apps/lib/libv4l/libv4lconvert/libv4lconvert.c +++ b/v4l2-apps/lib/libv4l/libv4lconvert/libv4lconvert.c @@ -37,6 +37,7 @@ static const unsigned int supported_src_pixfmts[] = { 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_data *data, 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 --git a/v4l2-apps/lib/libv4l/libv4lconvert/sn9c10x.c b/v4l2-apps/lib/libv4l/libv4lconvert/sn9c10x.c new file mode 100644 index 000000000..28ec5fa01 --- /dev/null +++ b/v4l2-apps/lib/libv4l/libv4lconvert/sn9c10x.c @@ -0,0 +1,199 @@ +/* +# (C) 2008 Hans de Goede <j.w.r.degoede@hhs.nl> + +# 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++; + } + } +} |