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

📄 ov511_decomp.c

📁 是一个linux下的摄像头驱动,网上的驱动源码比较难找,这个基本能用,根据具体的摄像头配置和设置改下,linux下可编译
💻 C
字号:
/* OV511 Decompression Support Module * * Copyright (c) 1999-2002 Mark W. McClelland. All rights reserved. * Original decompression code Copyright 1998-2000 OmniVision Technologies * * Please see the file: linux/Documentation/usb/ov511.txt * and the web site at:  http://alpha.dyndns.org/ov511/ * for more info. * * 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; version 2 of the License. * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. * */#include <linux/config.h>#if defined(OUTSIDE_KERNEL)	#if defined(CONFIG_MODVERSIONS) && !defined(MODVERSIONS)		#define MODVERSIONS	#endif	#include <linux/version.h>	#ifdef MODVERSIONS		#include <linux/modversions.h>	#endif#else	#include <linux/version.h>#endif#include <linux/module.h>#include <linux/init.h>#include "ov511.h"/****************************************************************************** * Version Information ******************************************************************************/#define DRIVER_VERSION "v1.6"#define DRIVER_AUTHOR "Mark McClelland <mark@alpha.dyndns.org>, OmniVision \Technologies <http://www.ovt.com/>"#define DRIVER_DESC "OV511 Decompression Module"/****************************************************************************** * Prototypes ******************************************************************************/extern int ov511_register_decomp_module(int ver, struct ov51x_decomp_ops *ops,					int ov518, int mmx);extern void ov511_deregister_decomp_module(int ov518, int mmx);/****************************************************************************** * Decompression Module Interface Constants ******************************************************************************/static const int interface_ver = DECOMP_INTERFACE_VER;static const int ov518 = 0;static const int mmx = 0;/****************************************************************************** * Module Features ******************************************************************************/static int debug;MODULE_PARM(debug, "i");MODULE_PARM_DESC(debug,  "Debug level: 0=none, 1=inits, 2=warning, 3=config, 4=functions, 5=max");MODULE_AUTHOR(DRIVER_AUTHOR);MODULE_DESCRIPTION(DRIVER_DESC);#if defined(MODULE_LICENSE)	/* Introduced in ~2.4.10 */MODULE_LICENSE("GPL");#endif/****************************************************************************** * Decompression Functions ******************************************************************************/static voidDecompressYHI(unsigned char *pIn,	      unsigned char *pOut,	      int           *iIn,	/* in/out */	      int           *iOut,	/* in/out */	      const int      w,	      const int      YUVFlag){	short ZigZag[64];	int temp[64];	int Zcnt_Flag = 0;	int Num8_Flag = 0;	int in_pos = *iIn;	int out_pos = *iOut;	int tmp, tmp1, tmp2, tmp3;	unsigned char header, ZTable[64];	short tmpl, tmph, half_byte, idx, count;	unsigned long ZigZag_length = 0, ZT_length, i, j;	short DeZigZag[64];	const short a = 11584;	const short b = 16068;	const short c = 15136;	const short d = 13624;	const short e =  9104;	const short f =  6270;	const short g =  3196;	int out_idx;	/* Take off every 'Zig' */	for (i = 0; i < 64; i++) {		ZigZag[i] = 0;	}	/*****************************	 * Read in the Y header byte *	 *****************************/	header = pIn[in_pos];	in_pos++;	ZigZag_length = header & 0x3f;	ZigZag_length = ZigZag_length + 1;	Num8_Flag = header & 0x40;	Zcnt_Flag = header & 0x80;	/*************************	 * Read in the Y content *	 *************************/	if (Zcnt_Flag == 0) {    /* Without Zero Table read contents directly */		/* Read in ZigZag[0] */		ZigZag[0] = pIn[in_pos++];		tmpl = pIn[in_pos++];		tmph = tmpl<<8;		ZigZag[0] = ZigZag[0] | tmph;		ZigZag[0] = ZigZag[0]<<4;		ZigZag[0] = ZigZag[0]>>4;		if (Num8_Flag) { /* 8 Bits */			for (i = 1; i < ZigZag_length; i++) {				ZigZag[i] = pIn[in_pos++];				ZigZag[i] = ZigZag[i]<<8;				ZigZag[i] = ZigZag[i]>>8;			}		} else {   /* 12 bits and has no Zero Table */			idx = 1;			half_byte = 0;			for (i = 1; i < ZigZag_length; i++) {				if (half_byte == 0) {					ZigZag[i] = pIn[in_pos++];					tmpl = pIn[in_pos++];					tmph = tmpl<<8;					tmph = tmph&0x0f00;					ZigZag[i] = ZigZag[i] | tmph;					ZigZag[i] = ZigZag[i]<<4;					ZigZag[i] = ZigZag[i]>>4;					half_byte = 1;				} else {					ZigZag[i] = pIn[in_pos++];					ZigZag[i] = ZigZag[i]<<8;					tmpl = tmpl & 0x00f0;					ZigZag[i] = ZigZag[i] | tmpl;					ZigZag[i] = ZigZag[i]>>4;					half_byte = 0;				}			}		}	} else {  /* Has Zero Table */		/* Calculate Z-Table length */		ZT_length = ZigZag_length/8;		tmp = ZigZag_length%8;		if (tmp > 0) {			ZT_length = ZT_length + 1;		}		/* Read in Zero Table */		for (j = 0; j < ZT_length; j++) {			ZTable[j] = pIn[in_pos++];		}		/* Read in ZigZag[0] */		ZigZag[0] = pIn[in_pos++];		tmpl = pIn[in_pos++];		tmph = tmpl<<8;		ZigZag[0] = ZigZag[0] | tmph;		ZigZag[0] = ZigZag[0]<<4;		ZigZag[0] = ZigZag[0]>>4;		/* Decode ZigZag */		idx = 0;		ZTable[idx] = ZTable[idx]<<1;		count = 7;		if (Num8_Flag) {	/* 8 Bits and has zero table */			for (i = 1; i < ZigZag_length; i++) {				if ((ZTable[idx]&0x80)) {					ZigZag[i] = pIn[in_pos++];					ZigZag[i] = ZigZag[i]<<8;					ZigZag[i] = ZigZag[i]>>8;				}				ZTable[idx]=ZTable[idx]<<1;				count--;				if (count == 0)	{					count = 8;					idx++;				}			}		} else {	/* 12 bits and has Zero Table */			half_byte = 0;			for (i = 1; i < ZigZag_length; i++) {				if (ZTable[idx]&0x80) {					if (half_byte == 0) {						ZigZag[i] = pIn[in_pos++];						tmpl = pIn[in_pos++];						tmph = tmpl <<8;						tmph = tmph & 0x0f00;						ZigZag[i] = ZigZag[i] | tmph;						ZigZag[i] = ZigZag[i]<<4;						ZigZag[i] = ZigZag[i]>>4;						half_byte = 1;					} else {						ZigZag[i] = pIn[in_pos++];						ZigZag[i] = ZigZag[i]<<8;						tmpl = tmpl & 0x00f0;						ZigZag[i] = ZigZag[i] | tmpl;						ZigZag[i] = ZigZag[i]>>4;						half_byte = 0;					}				}				ZTable[idx] = ZTable[idx]<<1;				count--;				if (count == 0)	{					count = 8;					idx++;				}			}		}	}	/*************	 * De-ZigZag *	 *************/	for (j = 0; j < 64; j++) {		DeZigZag[j] = 0;	}	if (YUVFlag == 1) {		DeZigZag[0] = ZigZag[0];		DeZigZag[1] = ZigZag[1]<<1;		DeZigZag[2] = ZigZag[5]<<1;		DeZigZag[3] = ZigZag[6]<<2;		DeZigZag[8] = ZigZag[2]<<1;		DeZigZag[9] = ZigZag[4]<<1;		DeZigZag[10] = ZigZag[7]<<1;		DeZigZag[11] = ZigZag[13]<<2;		DeZigZag[16] = ZigZag[3]<<1;		DeZigZag[17] = ZigZag[8]<<1;		DeZigZag[18] = ZigZag[12]<<2;		DeZigZag[19] = ZigZag[17]<<2;		DeZigZag[24] = ZigZag[9]<<2;		DeZigZag[25] = ZigZag[11]<<2;		DeZigZag[26] = ZigZag[18]<<2;		DeZigZag[27] = ZigZag[24]<<3;	} else {		DeZigZag[0] = ZigZag[0];		DeZigZag[1] = ZigZag[1]<<2;		DeZigZag[2] = ZigZag[5]<<2;		DeZigZag[3] = ZigZag[6]<<3;		DeZigZag[8] = ZigZag[2]<<2;		DeZigZag[9] = ZigZag[4]<<2;		DeZigZag[10] = ZigZag[7]<<2;		DeZigZag[11] = ZigZag[13]<<4;		DeZigZag[16] = ZigZag[3]<<2;		DeZigZag[17] = ZigZag[8]<<2;		DeZigZag[18] = ZigZag[12]<<3;		DeZigZag[19] = ZigZag[17]<<4;		DeZigZag[24] = ZigZag[9]<<3;		DeZigZag[25] = ZigZag[11]<<4;		DeZigZag[26] = ZigZag[18]<<4;		DeZigZag[27] = ZigZag[24]<<4;	}#if 0	/* Dequante */	if (YUVFlag == 1) {		/* Dequante Y */		for (i=0; i<64; i++) {			ZigZag[i] = DeZigZag[i]<<DQTY[i];		}	} else {		/* Dequante UV */		for (i=0; i<64; i++) {			ZigZag[i] = DeZigZag[i]<<DQTUV[i];		}	}#endif	/*****************	 **** IDCT 1D ****	 *****************/#define IDCT_1D(c0, c1, c2, c3, in)					\	do {								\		tmp1=((c0)*DeZigZag[in])+((c2)*DeZigZag[(in)+2]);	\		tmp2=(c1)*DeZigZag[(in)+1];				\		tmp3=(c3)*DeZigZag[(in)+3];				\	} while (0)#define COMPOSE_1(out1, out2)		\	do {				\		tmp=tmp1+tmp2+tmp3;	\		temp[out1] = tmp>>15;	\		tmp=tmp1-tmp2-tmp3;	\		temp[out2] = tmp>>15;	\	} while (0)#define COMPOSE_2(out1, out2)		\	do {				\		tmp=tmp1+tmp2-tmp3;	\		temp[out1] = tmp>>15;	\		tmp=tmp1-tmp2+tmp3;	\		temp[out2] = tmp>>15;	\	} while (0)	/* j = 0 */	IDCT_1D(a, b,  c, d,  0); COMPOSE_1( 0, 56);	IDCT_1D(a, b,  c, d,  8); COMPOSE_1( 1, 57);	IDCT_1D(a, b,  c, d, 16); COMPOSE_1( 2, 58);	IDCT_1D(a, b,  c, d, 24); COMPOSE_1( 3, 59);	/* j = 1 */	IDCT_1D(a, d,  f, g,  0); COMPOSE_2( 8, 48);	IDCT_1D(a, d,  f, g,  8); COMPOSE_2( 9, 49);	IDCT_1D(a, d,  f, g, 16); COMPOSE_2(10, 50);	IDCT_1D(a, d,  f, g, 24); COMPOSE_2(11, 51);	/* j = 2 */	IDCT_1D(a, e, -f, b,  0); COMPOSE_2(16, 40);	IDCT_1D(a, e, -f, b,  8); COMPOSE_2(17, 41);	IDCT_1D(a, e, -f, b, 16); COMPOSE_2(18, 42);	IDCT_1D(a, e, -f, b, 24); COMPOSE_2(19, 43);	/* j = 3 */	IDCT_1D(a, g, -c, e,  0); COMPOSE_2(24, 32);	IDCT_1D(a, g, -c, e,  8); COMPOSE_2(25, 33);	IDCT_1D(a, g, -c, e, 16); COMPOSE_2(26, 34);	IDCT_1D(a, g, -c, e, 24); COMPOSE_2(27, 35);#undef IDCT_1D#undef COMPOSE_1#undef COMPOSE_2	/*****************	 **** IDCT 2D ****	 *****************/#define IDCT_2D(c0, c1, c2, c3, in)				\	do {							\		tmp = temp[in]*(c0) + temp[(in)+1]*(c1)		\		    + temp[(in)+2]*(c2) + temp[(in)+3]*(c3);	\	} while (0)#define STORE(i)				\	do {					\		tmp = tmp >> 15;		\		tmp = tmp + 128;		\		if (tmp > 255) tmp = 255;	\		if (tmp < 0)   tmp = 0;		\		pOut[i] = (unsigned char) tmp;	\	} while (0)#define IDCT_2D_ROW(in)						\	do {							\		IDCT_2D(a,  b,  c,  d, in); STORE(0+out_idx);	\		IDCT_2D(a,  d,  f, -g, in); STORE(1+out_idx);	\		IDCT_2D(a,  e, -f, -b, in); STORE(2+out_idx);	\		IDCT_2D(a,  g, -c, -e, in); STORE(3+out_idx);	\		IDCT_2D(a, -g, -c,  e, in); STORE(4+out_idx);	\		IDCT_2D(a, -e, -f,  b, in); STORE(5+out_idx);	\		IDCT_2D(a, -d,  f,  g, in); STORE(6+out_idx);	\		IDCT_2D(a, -b,  c, -d, in); STORE(7+out_idx);	\	} while (0)#define IDCT_2D_FAST(c0, c1, c2, c3, in)			\	do {							\		tmp1=((c0)*temp[in])+((c2)*temp[(in)+2]);	\		tmp2=(c1)*temp[(in)+1];				\		tmp3=(c3)*temp[(in)+3];				\	} while (0)#define STORE_FAST_1(out1, out2)				\	do {							\		tmp=tmp1+tmp2+tmp3;				\		STORE((out1)+out_idx);				\		tmp=tmp1-tmp2-tmp3;				\		STORE((out2)+out_idx);				\	} while (0)#define STORE_FAST_2(out1, out2)				\	do {							\		tmp=tmp1+tmp2-tmp3;				\		STORE((out1)+out_idx);				\		tmp=tmp1-tmp2+tmp3;				\		STORE((out2)+out_idx);				\	} while (0)#define IDCT_2D_FAST_ROW(in)						\	do {								\		IDCT_2D_FAST(a, b,  c, d, in);	STORE_FAST_1(0, 7);	\		IDCT_2D_FAST(a, d,  f, g, in);	STORE_FAST_2(1, 6);	\		IDCT_2D_FAST(a, e, -f, b, in);	STORE_FAST_2(2, 5);	\		IDCT_2D_FAST(a, g, -c, e, in);	STORE_FAST_2(3, 4);	\	} while (0)	out_idx = out_pos;	IDCT_2D_ROW(0);		out_idx += w;	IDCT_2D_ROW(8);		out_idx += w;	IDCT_2D_ROW(16);	out_idx += w;	IDCT_2D_ROW(24);	out_idx += w;	IDCT_2D_ROW(32);	out_idx += w;	IDCT_2D_ROW(40);	out_idx += w;	IDCT_2D_FAST_ROW(48);	out_idx += w;	IDCT_2D_FAST_ROW(56);	*iIn = in_pos;	*iOut = out_pos + 8;}#define DECOMP_Y() DecompressYHI(pIn, pY, &iIn, &iY, w, 1)#define DECOMP_U() DecompressYHI(pIn, pU, &iIn, &iU, w/2, 2)#define DECOMP_V() DecompressYHI(pIn, pV, &iIn, &iV, w/2, 2)inline static intDecompress400HiNoMMX(unsigned char *pIn,		     unsigned char *pOut,		     const int      w,		     const int      h,		     const int      inSize){	unsigned char *pY = pOut;	int x, y, iIn, iY;	iIn = 0;	for (y = 0; y < h; y += 8) {		iY = w*y;		for (x = 0; x < w; x += 8)			DECOMP_Y();	}	return 0;}inline static intDecompress420HiNoMMX(unsigned char *pIn,		     unsigned char *pOut,		     const int      w,		     const int      h,		     const int      inSize){	unsigned char *pY = pOut;	unsigned char *pU = pY + w*h;	unsigned char *pV = pU + w*h/4;	int xY, xUV, iY, iU, iV, iIn, count;	const int nBlocks = (w*h) / (32*8);	iIn = 0;	iY = iU = iV = 0;	xY = xUV = 0;	for (count = 0; count < nBlocks; count++) {			DECOMP_U();			DECOMP_V(); xUV += 16;			if (xUV >= w) {				iU += (w*7)/2;				iV += (w*7)/2;				xUV = 0;			}			DECOMP_Y();	xY += 8;			DECOMP_Y();	xY += 8;			if (xY >= w) {				iY += w*7;				xY = 0;			}			DECOMP_Y();	xY += 8;			DECOMP_Y();	xY += 8;			if (xY >= w) {				iY += w*7;				xY = 0;			}	}	return 0;}/* Input format is raw isoc. data (with header and packet * number stripped, and all-zero blocks removed). * Output format is YUV400 * Returns uncompressed data length if success, or zero if error */static intDecompress400(unsigned char *pIn,	      unsigned char *pOut,	      unsigned char *pTmp,	      int	     w,	      int	     h,	      int	     inSize){	int numpix = w * h;	int rc;	PDEBUG(4, "%dx%d pIn=%p pOut=%p inSize=%d", w, h, pIn, pOut, inSize);	rc = Decompress400HiNoMMX(pIn, pOut, w, h, inSize);	if (rc)		return 0;	return numpix;}/* Input format is raw isoc. data (with header and packet * number stripped, and all-zero blocks removed). * Output format is planar YUV420 * Returns uncompressed data length if success, or zero if error */static intDecompress420(unsigned char *pIn,	      unsigned char *pOut,	      unsigned char *pTmp,	      int	     w,	      int	     h,	      int	     inSize){	int numpix = w * h;	int rc;	PDEBUG(4, "%dx%d pIn=%p pOut=%p inSize=%d", w, h, pIn, pOut, inSize);	rc = Decompress420HiNoMMX(pIn, pOut, w, h, inSize);	if (rc)		return 0;/* Disabled by Mark */#if 0	/* For color saturation 8/22/00 */	{		long u , v;		unsigned char *pU = pOut + numpix;		unsigned char *pV = pU + numpix/4;		for (int i = 0; i < numpix/4; i++) {			u = (long)*pU;			v = (long)*pV;			u -= 128;			v -= 128;			u = (u * 577) >> 10;			v = (v * 730) >> 10;			u += 128;			v += 128;			*pU++ = (unsigned char)u;			*pV++ = (unsigned char)v;/*   u=0.564 *//*   v=0.713 */		}	}#endif	return (numpix * 3 / 2);}/****************************************************************************** * Module Functions ******************************************************************************/static struct ov51x_decomp_ops decomp_ops = {	.decomp_400 =	Decompress400,	.decomp_420 =	Decompress420,	.owner =	THIS_MODULE,};static int __initdecomp_init(void){	int rc;	EXPORT_NO_SYMBOLS;	rc = ov511_register_decomp_module(DECOMP_INTERFACE_VER, &decomp_ops,					  ov518, mmx);	if (rc) {		err("Could not register with ov511 (rc=%d)", rc);		return -1;	}	info(DRIVER_VERSION " : " DRIVER_DESC);	return 0;}static void __exitdecomp_exit(void){	ov511_deregister_decomp_module(ov518, mmx);	info("deregistered\n");}module_init(decomp_init);module_exit(decomp_exit);

⌨️ 快捷键说明

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