From: Hans de Goede <hdegoede@redhat.com>
To: kilgota@banach.math.auburn.edu
Cc: linux-media@vger.kernel.org
Subject: Re: [PATCH] libv4lconvert support for SQ905C decompression (revised)
Date: Wed, 11 Mar 2009 14:24:15 +0100 [thread overview]
Message-ID: <49B7BB7F.7020802@redhat.com> (raw)
In-Reply-To: <alpine.LNX.2.00.0903041730550.23054@banach.math.auburn.edu>
kilgota@banach.math.auburn.edu wrote:
>
> Hans,
>
> From an abundance of caution, I thought I had better run the v4lconvert
> patch which supports the SQ905C compressed format through the
> checkpatch.pl process, too. The result of that process appears here,
> below the signed-off-by line.
>
> Theodore Kilgore
>
Thanks applied to me tree:
http://linuxtv.org/hg/~hgoede/libv4l
I expect to release libv4l-0.5.9 with this in, soon.
Regards,
Hans
> ---------- Forwarded message ----------
> Date: Sun, 1 Mar 2009 17:45:32 -0600 (CST)
> From: kilgota@banach.math.auburn.edu
> To: Hans de Goede <hdegoede@redhat.com>, linux-media@vger.kernel.org
> Subject: [PATCH] libv4lconvert support for SQ905C decompression
>
> Hans,
>
> Below is a patch for libv4lconvert, to support the decompression used by
> the SQ905C cameras (0x2770:0x905C) and some other related cameras. There
> is at the moment no support module for these cameras in streaming mode,
> but I intend to submit one.
>
> This contribution was created in whole by me, based upon code in
> libgphoto2 which was created in whole by me, and which was licensed for
> libgphoto2 under the LGPL license.
>
> Signed-off-by: Theodore Kilgore <kilgota@auburn.edu>
>
> -----------------------------------------------------------------------
> diff -uprN libv4lconvert-old/Makefile libv4lconvert-new/Makefile
> --- libv4lconvert-old/Makefile 2009-03-01 15:37:38.000000000 -0600
> +++ libv4lconvert-new/Makefile 2009-03-04 16:22:52.000000000 -0600
> @@ -12,7 +12,7 @@ endif
>
> CONVERT_OBJS = libv4lconvert.o tinyjpeg.o sn9c10x.o sn9c20x.o pac207.o \
> mr97310a.o flip.o crop.o jidctflt.o spca561-decompress.o \
> - rgbyuv.o spca501.o bayer.o
> + rgbyuv.o spca501.o sq905c.o bayer.o
> TARGETS = $(CONVERT_LIB) libv4lconvert.pc
> INCLUDES = ../include/libv4lconvert.h
>
> diff -uprN libv4lconvert-old/libv4lconvert-priv.h
> libv4lconvert-new/libv4lconvert-priv.h
> --- libv4lconvert-old/libv4lconvert-priv.h 2009-03-01
> 15:37:38.000000000 -0600
> +++ libv4lconvert-new/libv4lconvert-priv.h 2009-03-04
> 16:22:52.000000000 -0600
> @@ -47,6 +47,10 @@
> #define V4L2_PIX_FMT_MR97310A v4l2_fourcc('M','3','1','0')
> #endif
>
> +#ifndef V4L2_PIX_FMT_SQ905C
> +#define V4L2_PIX_FMT_SQ905C v4l2_fourcc('9', '0', '5', 'C')
> +#endif
> +
> #ifndef V4L2_PIX_FMT_PJPG
> #define V4L2_PIX_FMT_PJPG v4l2_fourcc('P', 'J', 'P', 'G')
> #endif
> @@ -180,6 +184,9 @@ void v4lconvert_decode_pac207(const unsi
> void v4lconvert_decode_mr97310a(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);
> +
> void v4lconvert_bayer_to_rgb24(const unsigned char *bayer,
> unsigned char *rgb, int width, int height, unsigned int pixfmt);
>
> diff -uprN libv4lconvert-old/libv4lconvert.c
> libv4lconvert-new/libv4lconvert.c
> --- libv4lconvert-old/libv4lconvert.c 2009-03-01 15:37:38.000000000
> -0600
> +++ libv4lconvert-new/libv4lconvert.c 2009-03-04 16:22:52.000000000
> -0600
> @@ -61,6 +61,7 @@ static const struct v4lconvert_pixfmt su
> { V4L2_PIX_FMT_SN9C10X, V4LCONVERT_COMPRESSED },
> { V4L2_PIX_FMT_PAC207, V4LCONVERT_COMPRESSED },
> { V4L2_PIX_FMT_MR97310A, V4LCONVERT_COMPRESSED },
> + { V4L2_PIX_FMT_SQ905C, V4LCONVERT_COMPRESSED },
> { V4L2_PIX_FMT_PJPG, V4LCONVERT_COMPRESSED },
> };
>
> @@ -608,6 +609,7 @@ static int v4lconvert_convert_pixfmt(str
> case V4L2_PIX_FMT_SN9C10X:
> case V4L2_PIX_FMT_PAC207:
> case V4L2_PIX_FMT_MR97310A:
> + case V4L2_PIX_FMT_SQ905C:
> {
> unsigned char *tmpbuf;
>
> @@ -633,6 +635,10 @@ static int v4lconvert_convert_pixfmt(str
> v4lconvert_decode_mr97310a(src, tmpbuf, width, height);
> src_pix_fmt = V4L2_PIX_FMT_SBGGR8;
> break;
> + case V4L2_PIX_FMT_SQ905C:
> + v4lconvert_decode_sq905c(src, tmpbuf, width, height);
> + src_pix_fmt = V4L2_PIX_FMT_SRGGB8;
> + break;
> }
> src = tmpbuf;
> /* Deliberate fall through to raw bayer fmt code! */
> diff -uprN libv4lconvert-old/sq905c.c libv4lconvert-new/sq905c.c
> --- libv4lconvert-old/sq905c.c 1969-12-31 18:00:00.000000000 -0600
> +++ libv4lconvert-new/sq905c.c 2009-03-04 16:27:17.000000000 -0600
> @@ -0,0 +1,217 @@
> +/*
> + * sq905c.c
> + *
> + * Here is the decompression function for the SQ905C cameras. The
> functions
> + * used are adapted from the libgphoto2 functions for the same cameras,
> + * which was
> + * Copyright (c) 2005 and 2007 Theodore Kilgore <kilgota@auburn.edu>
> + * This version for libv4lconvert is
> + * Copyright (c) 2009 Theodore Kilgore <kilgota@auburn.edu>
> + *
> + * 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 <stdlib.h>
> +
> +#include "libv4lconvert-priv.h"
> +
> +
> +#define CLIP(x) ((x) < 0 ? 0 : ((x) > 0xff) ? 0xff : (x))
> +
> +
> +static int
> +sq905c_first_decompress(unsigned char *output, unsigned char *input,
> + unsigned int outputsize)
> +{
> + unsigned char parity = 0;
> + unsigned char nibble_to_keep[2];
> + unsigned char temp1 = 0, temp2 = 0;
> + unsigned char input_byte;
> + unsigned char lookup = 0;
> + unsigned int i = 0;
> + unsigned int bytes_used = 0;
> + unsigned int bytes_done = 0;
> + unsigned int bit_counter = 8;
> + unsigned int cycles = 0;
> + int table[9] = { -1, 0, 2, 6, 0x0e, 0x0e, 0x0e, 0x0e, 0xfb};
> + unsigned char lookup_table[16]
> + = {0, 2, 6, 0x0e, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4,
> + 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb};
> + unsigned char translator[16] = {8, 7, 9, 6, 10, 11, 12, 13,
> + 14, 15, 5, 4, 3, 2, 1, 0};
> +
> + nibble_to_keep[0] = 0;
> + nibble_to_keep[1] = 0;
> +
> + while (bytes_done < outputsize) {
> + while (parity < 2) {
> + while (lookup > table[cycles]) {
> + if (bit_counter == 8) {
> + input_byte = input[bytes_used];
> + bytes_used++;
> + temp1 = input_byte;
> + bit_counter = 0;
> + }
> + input_byte = temp1;
> + temp2 = (temp2 << 1) & 0xFF;
> + input_byte = input_byte >> 7;
> + temp2 = temp2 | input_byte;
> + temp1 = (temp1 << 1) & 0xFF;
> + bit_counter++;
> + cycles++;
> + if (cycles > 9)
> + return -1;
> + lookup = temp2 & 0xff;
> + }
> + temp2 = 0;
> + for (i = 0; i < 17; i++) {
> + if (lookup == lookup_table[i]) {
> + nibble_to_keep[parity] = translator[i];
> + break;
> + }
> + if (i == 16)
> + return -1;
> + }
> + cycles = 0;
> + parity++;
> + }
> + output[bytes_done] = (nibble_to_keep[0]<<4)|nibble_to_keep[1];
> + bytes_done++;
> + parity = 0;
> + }
> + return 0;
> +}
> +
> +static int
> +sq905c_second_decompress(unsigned char *uncomp, unsigned char *in,
> + int width, int height)
> +{
> + int diff = 0;
> + int tempval = 0;
> + int i, m, parity;
> + unsigned char delta_left = 0;
> + unsigned char delta_right = 0;
> + int input_counter = 0;
> + int delta_table[] = {-144, -110, -77, -53, -35, -21, -11, -3,
> + 2, 10, 20, 34, 52, 76, 110, 144};
> + unsigned char *templine_red;
> + unsigned char *templine_green;
> + unsigned char *templine_blue;
> + templine_red = malloc(width);
> + if (!templine_red) {
> + free(templine_red);
> + return -1;
> + }
> + for (i = 0; i < width; i++)
> + templine_red[i] = 0x80;
> + templine_green = malloc(width);
> + if (!templine_green) {
> + free(templine_green);
> + return -1;
> + }
> + for (i = 0; i < width; i++)
> + templine_green[i] = 0x80;
> + templine_blue = malloc(width);
> + if (!templine_blue) {
> + free(templine_blue);
> + return -1;
> + }
> + for (i = 0; i < width; i++)
> + templine_blue[i] = 0x80;
> + for (m = 0; m < height/2; m++) {
> + /* First we do an even-numbered line */
> + for (i = 0; i < width/2; i++) {
> + parity = i&1;
> + delta_right = in[input_counter] & 0x0f;
> + delta_left = (in[input_counter]>>4)&0xff;
> + input_counter++;
> + /* left pixel (red) */
> + diff = delta_table[delta_left];
> + if (!i)
> + tempval = templine_red[0] + diff;
> + else
> + tempval = (templine_red[i]
> + + uncomp[2*m*width+2*i-2])/2 + diff;
> + tempval = CLIP(tempval);
> + uncomp[2*m*width+2*i] = tempval;
> + templine_red[i] = tempval;
> + /* right pixel (green) */
> + diff = delta_table[delta_right];
> + if (!i)
> + tempval = templine_green[1] + diff;
> + else if (2*i == width - 2)
> + tempval = (templine_green[i]
> + + uncomp[2*m*width+2*i-1])/2
> + + diff;
> + else
> + tempval = (templine_green[i+1]
> + + uncomp[2*m*width+2*i-1])/2
> + + diff;
> + tempval = CLIP(tempval);
> + uncomp[2*m*width+2*i+1] = tempval;
> + templine_green[i] = tempval;
> + }
> + /* then an odd-numbered line */
> + for (i = 0; i < width/2; i++) {
> + delta_right = in[input_counter] & 0x0f;
> + delta_left = (in[input_counter]>>4) & 0xff;
> + input_counter++;
> + /* left pixel (green) */
> + diff = delta_table[delta_left];
> + if (!i)
> + tempval = templine_green[0] + diff;
> + else
> + tempval = (templine_green[i]
> + + uncomp[(2*m+1)*width+2*i-2])/2
> + + diff;
> + tempval = CLIP(tempval);
> + uncomp[(2*m+1)*width+2*i] = tempval;
> + templine_green[i] = tempval;
> + /* right pixel (blue) */
> + diff = delta_table[delta_right];
> + if (!i)
> + tempval = templine_blue[0] + diff;
> + else
> + tempval = (templine_blue[i]
> + + uncomp[(2*m+1)*width+2*i-1])/2
> + + diff;
> + tempval = CLIP(tempval);
> + uncomp[(2*m+1)*width+2*i+1] = tempval;
> + templine_blue[i] = tempval;
> + }
> + }
> + free(templine_green);
> + free(templine_red);
> + free(templine_blue);
> + return 0;
> +}
> +
> +void v4lconvert_decode_sq905c(const unsigned char *src, unsigned char
> *dst,
> + int width, int height)
> +{
> + int size;
> + unsigned char *temp_data;
> + unsigned char *raw;
> + /* here we get rid of the 0x50 bytes of header in src. */
> + raw = src + 0x50;
> + size = width*height/2;
> + temp_data = malloc(size);
> + if (!temp_data)
> + goto out;
> + sq905c_first_decompress(temp_data, raw, size);
> + sq905c_second_decompress(dst, temp_data, width, height);
> +out:
> + free(temp_data);
> +}
prev parent reply other threads:[~2009-03-11 13:23 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-03-04 23:37 [PATCH] libv4lconvert support for SQ905C decompression (revised) kilgota
2009-03-11 13:24 ` Hans de Goede [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=49B7BB7F.7020802@redhat.com \
--to=hdegoede@redhat.com \
--cc=kilgota@banach.math.auburn.edu \
--cc=linux-media@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).