⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pwc-dec23.c

📁 webcam device driver
💻 C
📖 第 1 页 / 共 2 页
字号:
/* Linux driver for Philips webcam   Decompression for chipset version 2 et 3   (C) 2004-2006  Luc Saillard (luc@saillard.org)   NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx   driver and thus may have bugs that are not present in the original version.   Please send bug reports and support requests to <luc@saillard.org>.   The decompression routines have been implemented by reverse-engineering the   Nemosoft binary pwcx module. Caveat emptor.   This program is free software; you can redistribute it and/or modify   it under the terms of the GNU General Public License as published by   the Free Software Foundation; either version 2 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 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 "pwc-timon.h"#include "pwc-kiara.h"#include "pwc-dec23.h"#include "pwc-ioctl.h"#include <linux/string.h>/* * USE_LOOKUP_TABLE_TO_CLAMP *   0: use a C version of this tests:  {  a<0?0:(a>255?255:a) } *   1: use a faster lookup table for cpu with a big cache (intel) */#define USE_LOOKUP_TABLE_TO_CLAMP	1/* * UNROLL_LOOP_FOR_COPYING_BLOCK *   0: use a loop for a smaller code (but little slower) *   1: when unrolling the loop, gcc produces some faster code (perhaps only *   valid for intel processor class). Activating this option, automaticaly *   activate USE_LOOKUP_TABLE_TO_CLAMP */#define UNROLL_LOOP_FOR_COPY		1#if UNROLL_LOOP_FOR_COPY# undef USE_LOOKUP_TABLE_TO_CLAMP# define USE_LOOKUP_TABLE_TO_CLAMP 1#endif/* * ENABLE_BAYER_DECODER *   0: bayer decoder is not build (save some space) *   1: bayer decoder is build and can be used */#define ENABLE_BAYER_DECODER 0static void build_subblock_pattern(struct pwc_dec23_private *pdec){	static const unsigned int initial_values[12] = {		-0x526500, -0x221200, 0x221200, 0x526500,	       	           -0x3de200, 0x3de200,                -0x6db480, -0x2d5d00, 0x2d5d00, 0x6db480,			   -0x12c200, 0x12c200	};	static const unsigned int values_derivated[12] = {		0xa4ca, 0x4424, -0x4424, -0xa4ca, 			0x7bc4, -0x7bc4,		0xdb69, 0x5aba, -0x5aba, -0xdb69,			0x2584, -0x2584	};	unsigned int temp_values[12];	int i, j;	memcpy(temp_values, initial_values, sizeof(initial_values));	for (i = 0; i < 256; i++) {		for (j = 0; j < 12; j++) {			pdec->table_subblock[i][j] = temp_values[j];			temp_values[j] += values_derivated[j];		}	}}static void build_bit_powermask_table(struct pwc_dec23_private *pdec){	unsigned char *p;	unsigned int bit, byte, mask, val;	unsigned int bitpower = 1;	for (bit = 0; bit < 8; bit++) {		mask = bitpower - 1;		p = pdec->table_bitpowermask[bit];		for (byte = 0; byte < 256; byte++) {			val = (byte & mask);			if (byte & bitpower)				val = -val;			*p++ = val;		}		bitpower<<=1;	}}static void build_table_color(const unsigned int romtable[16][8],    			      unsigned char p0004[16][1024],			      unsigned char p8004[16][256]){	int compression_mode, j, k, bit, pw;	unsigned char *p0, *p8;	const unsigned int *r;	/* We have 16 compressions tables */	for (compression_mode = 0; compression_mode < 16; compression_mode++) {		p0 = p0004[compression_mode];		p8 = p8004[compression_mode];		r  = romtable[compression_mode];		for (j = 0; j < 8; j++, r++, p0 += 128) {			for (k = 0; k < 16; k++) {				if (k == 0)					bit = 1;				else if (k >= 1 && k < 3)					bit = (r[0] >> 15) & 7;				else if (k >= 3 && k < 6)					bit = (r[0] >> 12) & 7;				else if (k >= 6 && k < 10)					bit = (r[0] >> 9) & 7;				else if (k >= 10 && k < 13)					bit = (r[0] >> 6) & 7;				else if (k >= 13 && k < 15)					bit = (r[0] >> 3) & 7;				else					bit = (r[0]) & 7;				if (k == 0)					*p8++ = 8;				else					*p8++ = j - bit;				*p8++ = bit;				pw = 1 << bit;				p0[k + 0x00] = (1 * pw) + 0x80;				p0[k + 0x10] = (2 * pw) + 0x80;				p0[k + 0x20] = (3 * pw) + 0x80;				p0[k + 0x30] = (4 * pw) + 0x80;				p0[k + 0x40] = (-1 * pw) + 0x80;				p0[k + 0x50] = (-2 * pw) + 0x80;				p0[k + 0x60] = (-3 * pw) + 0x80;				p0[k + 0x70] = (-4 * pw) + 0x80;			}	/* end of for (k=0; k<16; k++, p8++) */		}	/* end of for (j=0; j<8; j++ , table++) */	} /* end of foreach compression_mode */}/* * */static void fill_table_dc00_d800(struct pwc_dec23_private *pdec){#define SCALEBITS 15#define ONE_HALF  (1UL << (SCALEBITS - 1))	int i;	unsigned int offset1 = ONE_HALF;	unsigned int offset2 = 0x0000;	for (i=0; i<256; i++) {		pdec->table_dc00[i] = offset1 & ~(ONE_HALF);		pdec->table_d800[i] = offset2;		offset1 += 0x7bc4;		offset2 += 0x7bc4;	}}/* * To decode the stream: *   if look_bits(2) == 0:	# op == 2 in the lookup table *      skip_bits(2) *      end of the stream *   elif look_bits(3) == 7:	# op == 1 in the lookup table *      skip_bits(3) *      yyyy = get_bits(4) *      xxxx = get_bits(8) *   else:			# op == 0 in the lookup table *      skip_bits(x) * * For speedup processing, we build a lookup table and we takes the first 6 bits. *  * struct { *   unsigned char op;	    // operation to execute *   unsigned char bits;    // bits use to perform operation *   unsigned char offset1; // offset to add to access in the table_0004 % 16 *   unsigned char offset2; // offset to add to access in the table_0004 * } * * How to build this table ? *   op == 2 when (i%4)==0 *   op == 1 when (i%8)==7 *   op == 0 otherwise * */static const unsigned char hash_table_ops[64*4] = {	0x02, 0x00, 0x00, 0x00,	0x00, 0x03, 0x01, 0x00,	0x00, 0x04, 0x01, 0x10,	0x00, 0x06, 0x01, 0x30,	0x02, 0x00, 0x00, 0x00,	0x00, 0x03, 0x01, 0x40,	0x00, 0x05, 0x01, 0x20,	0x01, 0x00, 0x00, 0x00,	0x02, 0x00, 0x00, 0x00,	0x00, 0x03, 0x01, 0x00,	0x00, 0x04, 0x01, 0x50,	0x00, 0x05, 0x02, 0x00,	0x02, 0x00, 0x00, 0x00,	0x00, 0x03, 0x01, 0x40,	0x00, 0x05, 0x03, 0x00,	0x01, 0x00, 0x00, 0x00,	0x02, 0x00, 0x00, 0x00,	0x00, 0x03, 0x01, 0x00,	0x00, 0x04, 0x01, 0x10,	0x00, 0x06, 0x02, 0x10,	0x02, 0x00, 0x00, 0x00,	0x00, 0x03, 0x01, 0x40,	0x00, 0x05, 0x01, 0x60,	0x01, 0x00, 0x00, 0x00,	0x02, 0x00, 0x00, 0x00,	0x00, 0x03, 0x01, 0x00,	0x00, 0x04, 0x01, 0x50,	0x00, 0x05, 0x02, 0x40,	0x02, 0x00, 0x00, 0x00,	0x00, 0x03, 0x01, 0x40,	0x00, 0x05, 0x03, 0x40,	0x01, 0x00, 0x00, 0x00,	0x02, 0x00, 0x00, 0x00,	0x00, 0x03, 0x01, 0x00,	0x00, 0x04, 0x01, 0x10,	0x00, 0x06, 0x01, 0x70,	0x02, 0x00, 0x00, 0x00,	0x00, 0x03, 0x01, 0x40,	0x00, 0x05, 0x01, 0x20,	0x01, 0x00, 0x00, 0x00,	0x02, 0x00, 0x00, 0x00,	0x00, 0x03, 0x01, 0x00,	0x00, 0x04, 0x01, 0x50,	0x00, 0x05, 0x02, 0x00,	0x02, 0x00, 0x00, 0x00,	0x00, 0x03, 0x01, 0x40,	0x00, 0x05, 0x03, 0x00,	0x01, 0x00, 0x00, 0x00,	0x02, 0x00, 0x00, 0x00,	0x00, 0x03, 0x01, 0x00,	0x00, 0x04, 0x01, 0x10,	0x00, 0x06, 0x02, 0x50,	0x02, 0x00, 0x00, 0x00,	0x00, 0x03, 0x01, 0x40,	0x00, 0x05, 0x01, 0x60,	0x01, 0x00, 0x00, 0x00,	0x02, 0x00, 0x00, 0x00,	0x00, 0x03, 0x01, 0x00,	0x00, 0x04, 0x01, 0x50,	0x00, 0x05, 0x02, 0x40,	0x02, 0x00, 0x00, 0x00,	0x00, 0x03, 0x01, 0x40,	0x00, 0x05, 0x03, 0x40,	0x01, 0x00, 0x00, 0x00};/* * */static const unsigned int MulIdx[16][16] = {	{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},	{0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,},	{0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3,},	{4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 4, 4, 4, 4,},	{6, 7, 8, 9, 7, 10, 11, 8, 8, 11, 10, 7, 9, 8, 7, 6,},	{4, 5, 5, 4, 4, 5, 5, 4, 4, 5, 5, 4, 4, 5, 5, 4,},	{1, 3, 0, 2, 1, 3, 0, 2, 1, 3, 0, 2, 1, 3, 0, 2,},	{0, 3, 3, 0, 1, 2, 2, 1, 2, 1, 1, 2, 3, 0, 0, 3,},	{0, 1, 2, 3, 3, 2, 1, 0, 3, 2, 1, 0, 0, 1, 2, 3,},	{1, 1, 1, 1, 3, 3, 3, 3, 0, 0, 0, 0, 2, 2, 2, 2,},	{7, 10, 11, 8, 9, 8, 7, 6, 6, 7, 8, 9, 8, 11, 10, 7,},	{4, 5, 5, 4, 5, 4, 4, 5, 5, 4, 4, 5, 4, 5, 5, 4,},	{7, 9, 6, 8, 10, 8, 7, 11, 11, 7, 8, 10, 8, 6, 9, 7,},	{1, 3, 0, 2, 2, 0, 3, 1, 2, 0, 3, 1, 1, 3, 0, 2,},	{1, 2, 2, 1, 3, 0, 0, 3, 0, 3, 3, 0, 2, 1, 1, 2,},	{10, 8, 7, 11, 8, 6, 9, 7, 7, 9, 6, 8, 11, 7, 8, 10}};#if USE_LOOKUP_TABLE_TO_CLAMP#define MAX_OUTER_CROP_VALUE	(512)static unsigned char pwc_crop_table[256 + 2*MAX_OUTER_CROP_VALUE];#define CLAMP(x) (pwc_crop_table[MAX_OUTER_CROP_VALUE+(x)])#else#define CLAMP(x) ((x)>255?255:((x)<0?0:x))#endif/* If the type or the command change, we rebuild the lookup table */int pwc_dec23_init(struct pwc_device *pwc, int type, unsigned char *cmd){	int flags, version, shift, i;	struct pwc_dec23_private *pdec;	if (pwc->decompress_data == NULL) {		pdec = kmalloc(sizeof(struct pwc_dec23_private), GFP_KERNEL);		if (pdec == NULL)			return -ENOMEM;		pwc->decompress_data = pdec;	}	pdec = pwc->decompress_data;	if (DEVICE_USE_CODEC3(type)) {		flags = cmd[2] & 0x18;		if (flags == 8)			pdec->nbits = 7;	/* More bits, mean more bits to encode the stream, but better quality */		else if (flags == 0x10)			pdec->nbits = 8;		else			pdec->nbits = 6;		version = cmd[2] >> 5;		build_table_color(KiaraRomTable[version][0], pdec->table_0004_pass1, pdec->table_8004_pass1);		build_table_color(KiaraRomTable[version][1], pdec->table_0004_pass2, pdec->table_8004_pass2);	} else {		flags = cmd[2] & 6;		if (flags == 2)			pdec->nbits = 7;		else if (flags == 4)			pdec->nbits = 8;		else			pdec->nbits = 6;		version = cmd[2] >> 3;		build_table_color(TimonRomTable[version][0], pdec->table_0004_pass1, pdec->table_8004_pass1);		build_table_color(TimonRomTable[version][1], pdec->table_0004_pass2, pdec->table_8004_pass2);	}	/* Informations can be coded on a variable number of bits but never less than 8 */	shift = 8 - pdec->nbits;	pdec->scalebits = SCALEBITS - shift;	pdec->nbitsmask = 0xFF >> shift;	fill_table_dc00_d800(pdec);	build_subblock_pattern(pdec);	build_bit_powermask_table(pdec);#if USE_LOOKUP_TABLE_TO_CLAMP	/* Build the static table to clamp value [0-255] */	for (i=0;i<MAX_OUTER_CROP_VALUE;i++)		pwc_crop_table[i] = 0;	for (i=0; i<256; i++)		pwc_crop_table[MAX_OUTER_CROP_VALUE+i] = i;	for (i=0; i<MAX_OUTER_CROP_VALUE; i++)		pwc_crop_table[MAX_OUTER_CROP_VALUE+256+i] = 255;#endif	return 0;}/* * Copy the 4x4 image block to Y plane buffer */static void copy_image_block_Y(const int *src, unsigned char *dst, unsigned int bytes_per_line, unsigned int scalebits){#if UNROLL_LOOP_FOR_COPY	const unsigned char *cm = pwc_crop_table+MAX_OUTER_CROP_VALUE;	const int *c = src;	unsigned char *d = dst;	*d++ = cm[c[0] >> scalebits];	*d++ = cm[c[1] >> scalebits];	*d++ = cm[c[2] >> scalebits];	*d++ = cm[c[3] >> scalebits];	d = dst + bytes_per_line;	*d++ = cm[c[4] >> scalebits];	*d++ = cm[c[5] >> scalebits];	*d++ = cm[c[6] >> scalebits];	*d++ = cm[c[7] >> scalebits];	d = dst + bytes_per_line*2;	*d++ = cm[c[8] >> scalebits];	*d++ = cm[c[9] >> scalebits];	*d++ = cm[c[10] >> scalebits];	*d++ = cm[c[11] >> scalebits];	d = dst + bytes_per_line*3;	*d++ = cm[c[12] >> scalebits];	*d++ = cm[c[13] >> scalebits];	*d++ = cm[c[14] >> scalebits];	*d++ = cm[c[15] >> scalebits];#else	int i;	const int *c = src;	unsigned char *d = dst;	for (i = 0; i < 4; i++, c++)		*d++ = CLAMP((*c) >> scalebits);	d = dst + bytes_per_line;	for (i = 0; i < 4; i++, c++)		*d++ = CLAMP((*c) >> scalebits);	d = dst + bytes_per_line*2;	for (i = 0; i < 4; i++, c++)		*d++ = CLAMP((*c) >> scalebits);	d = dst + bytes_per_line*3;	for (i = 0; i < 4; i++, c++)		*d++ = CLAMP((*c) >> scalebits);#endif}/* * Copy the 4x4 image block to a CrCb plane buffer *  */static void copy_image_block_CrCb(const int *src, unsigned char *dst, unsigned int bytes_per_line, unsigned int scalebits){#if UNROLL_LOOP_FOR_COPY	/* Unroll all loops */	const unsigned char *cm = pwc_crop_table+MAX_OUTER_CROP_VALUE;	const int *c = src;	unsigned char *d = dst;	*d++ = cm[c[0] >> scalebits];	*d++ = cm[c[4] >> scalebits];	*d++ = cm[c[1] >> scalebits];	*d++ = cm[c[5] >> scalebits];	*d++ = cm[c[2] >> scalebits];	*d++ = cm[c[6] >> scalebits];	*d++ = cm[c[3] >> scalebits];	*d++ = cm[c[7] >> scalebits];	d = dst + bytes_per_line;	*d++ = cm[c[12] >> scalebits];	*d++ = cm[c[8] >> scalebits];	*d++ = cm[c[13] >> scalebits];	*d++ = cm[c[9] >> scalebits];	*d++ = cm[c[14] >> scalebits];	*d++ = cm[c[10] >> scalebits];	*d++ = cm[c[15] >> scalebits];	*d++ = cm[c[11] >> scalebits];#else	int i;	const int *c1 = src;	const int *c2 = src + 4;	unsigned char *d = dst;	for (i = 0; i < 4; i++, c1++, c2++) {		*d++ = CLAMP((*c1) >> scalebits);		*d++ = CLAMP((*c2) >> scalebits);	}	c1 = src + 12;	d = dst + bytes_per_line;	for (i = 0; i < 4; i++, c1++, c2++) {		*d++ = CLAMP((*c1) >> scalebits);		*d++ = CLAMP((*c2) >> scalebits);	}#endif}#if ENABLE_BAYER_DECODER/* * Format: 8x2 pixels

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -