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

📄 ov518_decomp.c

📁 0v511摄像头linux最新驱动源码
💻 C
📖 第 1 页 / 共 4 页
字号:
	t=(base - val1 + val2 - val3 - tmp1 - tmp2 - C4 + C20) >> 17;
	out[19]= t&0xFFFFFF00? t<0?0:255 : (unsigned char)t;
	t=(base + val1 - val2 - val3) >> 17;
	out[20]= t&0xFFFFFF00? t<0?0:255 : (unsigned char)t;
}

#undef TIMES_16382
#undef TIMES_23168
#undef TIMES_30270
#undef TIMES_41986
#undef TIMES_35594
#undef TIMES_23783
#undef TIMES_8351
#undef TIMES_17391
#undef TIMES_14743
#undef TIMES_9851
#undef TIMES_3459
#undef TIMES_32134
#undef TIMES_27242
#undef TIMES_18202
#undef TIMES_6392
#undef TIMES_39550
#undef TIMES_6785
#undef TIMES_12538

/******************************************************************************
 * Main Decoder Functions
 ******************************************************************************/

/* This function handles the decompression of a single 8x4 block. It is
 * independent of the palette (YUV422, YUV420, YUV400, GBR422...). cinfo->bytes
 * determines the positin in the input buffer.
 */
static int 
decompress8x4(unsigned char *pOut,
	      unsigned char *pIn,
	      int	    *lastDC,
	      int	     uvFlag,
	      CompInfo 	    *cinfo)
{
	int i, x, y, dc;
	int coeffs[32];
	int deZigZag[32];
	int *dest;
	int *src;
	unsigned char *qt = cinfo->qt;

	if (! uvFlag) {
		huffmanDecoderY(coeffs, (int*) pIn, cinfo);

		/* iDPCM and dequantize first coefficient */
		dc = (*lastDC) + coeffs[0];
		coeffs[0] = dc * (qt[0] + 1);
		*lastDC = dc;

		/* ...and the second coefficient */
		coeffs[1] = ((qt[1] + 1) * coeffs[1]) >> 1;

		/* Dequantize, starting at 3rd element */
		for (i = 2; i < 32; i++)
			coeffs[i] = (qt[i] + 1) * coeffs[i];
	} else {
		huffmanDecoderUV(coeffs, (int*) pIn, cinfo);

		/* iDPCM */
		dc = (*lastDC) + coeffs[0];
		coeffs[0] = dc;
		*lastDC = dc;

		/* Dequantize */
		for (i = 0; i < 32; i++)
			coeffs[i] = (qt[32 + i] + 1) * coeffs[i];
	}

	/* Dezigzag */
	for (i = 0; i < 32; i++)
		deZigZag[i] = coeffs[ZigZag518[i]];

	/* Transpose the dezigzagged coefficient matrix */
	src = deZigZag;
	dest = coeffs;
	for (y = 0; y <= 3; ++y) {
		for (x = 0; x <= 7; ++x) {
			dest[x] = src[x * 4];
		}
		src += 1;
		dest += 8;
	}

	/* Do the inverse DCT transform */
	DCT_8x4(coeffs, pOut);

	return 0;	/* Always returns 0 */
}

static inline void 
copyBlock(unsigned char *src, unsigned char *dest, int destInc)
{
	int i;
	unsigned int *pSrc, *pDest;

	for (i = 0; i <= 3; i++) {
		pSrc = (unsigned int *) src;
		pDest = (unsigned int *) dest;
		pDest[0] = pSrc[0];
		pDest[1] = pSrc[1];
		src += 8;
		dest += destInc;
	}
}

static inline int
decompress400NoMMXOV518(unsigned char *pIn,
			unsigned char *pOut,
			unsigned char *pTmp,
			const int      w, 
			const int      h, 
			const int      numpix,
			CompInfo       *cinfo)
{
	int iOutY, x, y;
	int lastYDC = 0;

	/* Start Y loop */
	y = 0;
	do {
		iOutY = w * y;
		x = 0;
		do {
			decompress8x4(pTmp, pIn, &lastYDC, 0, cinfo);
			copyBlock(pTmp, pOut + iOutY, w);
			iOutY += 8;
			x += 8;
		} while (x < w);
		y += 4;
	} while (y < h);

	/* Did we decode too much? */
	if (cinfo->bytes > cinfo->rawLen + 897)
		return 1;

	/* Did we decode enough? */
	if (cinfo->bytes >= cinfo->rawLen - 897)
		return 0;
	else
		return 1;
}

static inline int
decompress420NoMMXOV518(unsigned char *pIn,
			unsigned char *pOut,
			unsigned char *pTmp,
			const int      w, 
			const int      h, 
			const int      numpix,
			CompInfo       *cinfo)
{
	unsigned char *pOutU = pOut + numpix;
	unsigned char *pOutV = pOutU + numpix / 4;
	int iOutY, iOutU, iOutV, x, y;
	int lastYDC = 0;
	int lastUDC = 0;
	int lastVDC = 0;

	/* Start Y loop */
	y = 0;
	do {
		iOutY = w * y;
		iOutV = iOutU = iOutY / 4;

		x = 0;
		do {
			decompress8x4(pTmp, pIn, &lastYDC, 0, cinfo);
			copyBlock(pTmp, pOut + iOutY, w);
			iOutY += 8;
			x += 8;
		} while (x < w);



		iOutY = w * (y + 4);
		x = 0;
		do {
			decompress8x4(pTmp, pIn, &lastUDC, 1, cinfo);
			copyBlock(pTmp, pOutU + iOutU, w/2);
			iOutU += 8;

			decompress8x4(pTmp, pIn, &lastVDC, 1, cinfo);
			copyBlock(pTmp, pOutV + iOutV, w/2);
			iOutV += 8;

			decompress8x4(pTmp, pIn, &lastYDC, 0, cinfo);
			copyBlock(pTmp, pOut + iOutY, w);
			iOutY += 8;

			decompress8x4(pTmp, pIn, &lastYDC, 0, cinfo);
			copyBlock(pTmp, pOut + iOutY, w);
			iOutY += 8;

			x += 16;
		} while (x < w);

		y += 8;
	} while (y < h);

	/* Did we decode too much? */
	if (cinfo->bytes > cinfo->rawLen + 897)
		return 1;

	/* Did we decode enough? */
	if (cinfo->bytes >= cinfo->rawLen - 897)
		return 0;
	else
		return 1;
}

/* Get quantization tables from static arrays
 * Returns: <0 if error, or >=0 otherwise */
static int
get_qt_static(CompInfo *cinfo)
{
	unsigned char qtY[] = OV518_YQUANTABLE;
	unsigned char qtUV[] = OV518_UVQUANTABLE;
	unsigned char qt[64];

	memcpy(qt, qtY, 32);
	memcpy(qt + 32, qtUV, 32);
	cinfo->qt = qt;

	return 0;
}


/* Get quantization tables from input
 * Returns: <0 if error, or >=0 otherwise */
static int
get_qt_dynamic(unsigned char *pIn, CompInfo *cinfo)
{
	int rawLen = cinfo->rawLen;

	/* Make sure input is actually big enough to hold trailer */
	if (rawLen < 72) {
		PDEBUG(1, "Not enough input to decompress");
		return -EINVAL;
	}

	cinfo->qt = pIn + rawLen - 64;

	print_qt(cinfo->qt);

	return 0;
}

/* Input format is raw isoc. data (with intact SOF header, packet numbers
 * stripped, and all-zero blocks removed).
 * Output format is planar YUV400
 * Returns uncompressed data length if success, or zero if error
 */
static int 
Decompress400(unsigned char *pIn,
	      unsigned char *pOut,
	      unsigned char *pTmp,
	      int	     w,
	      int	     h,
	      int	     inSize)
{
	CompInfo cinfo;
	int numpix = w * h;

	PDEBUG(4, "%dx%d pIn=%p pOut=%p pTmp=%p inSize=%d", w, h, pIn, pOut,
	       pTmp, inSize);

	cinfo.bytes = 0;
	cinfo.bits = 0;
	cinfo.rawLen = inSize;

	if (staticquant) {
		if (get_qt_static(&cinfo) < 0)
			return 0;
	} else {
		if (get_qt_dynamic(pIn, &cinfo) < 0)
			return 0;
	}

	/* Decompress, skipping the 8-byte SOF header */
	if (decompress400NoMMXOV518(pIn + 8, pOut, pTmp, w, h, numpix, &cinfo))
//		return 0;
		; /* Don't return error yet */

	return (numpix);
}

/* Input format is raw isoc. data (with intact SOF header, packet numbers
 * stripped, and all-zero blocks removed).
 * Output format is planar YUV420
 * Returns uncompressed data length if success, or zero if error
 */
static int 
Decompress420(unsigned char *pIn,
	      unsigned char *pOut,
	      unsigned char *pTmp,
	      int	     w,
	      int	     h,
	      int	     inSize)
{
	CompInfo cinfo;
	int numpix = w * h;

	PDEBUG(4, "%dx%d pIn=%p pOut=%p pTmp=%p inSize=%d", w, h, pIn, pOut,
	       pTmp, inSize);

	cinfo.bytes = 0;
	cinfo.bits = 0;
	cinfo.rawLen = inSize;

	if (staticquant) {
		if (get_qt_static(&cinfo) < 0)
			return 0;
	} else {
		if (get_qt_dynamic(pIn, &cinfo) < 0)
			return 0;
	}

	/* Decompress, skipping the 8-byte SOF header */
	if (decompress420NoMMXOV518(pIn + 8, pOut, pTmp, w, h, numpix, &cinfo))
//		return 0;
		; /* Don't return error yet */

/* OmniVision may have written this code for the OV518. It isn't tested yet */
#if 0
	/* For color saturation 8/22/00 */
	{
		int i, u, v;
		unsigned char *pU = pOut + numpix;
		unsigned char *pV = pU + numpix/4;
		for (i = 0; i < numpix/4; i++) {
			u = (int)*pU;
			v = (int)*pV;
			u -= 128;
			v -= 128;
			u = (u * 577) >> 10;	/*   u=0.564 */
			v = (v * 730) >> 10;	/*   v=0.713 */
			u += 128;
			v += 128;
			*pU++ = (unsigned char)u;
			*pV++ = (unsigned char)v;
		}
	}
#endif

	if (nouv) {
		int i;
		unsigned char *pU = pOut + numpix;
		unsigned char *pV = pU + numpix/4;

		for (i = 0; i < numpix/4; i++) {
			*pU++ = 127;
			*pV++ = 127;
		}
	}

	return (numpix * 3 / 2);
}

/******************************************************************************
 * Module Functions
 ******************************************************************************/

static struct ov51x_decomp_ops decomp_ops = {
	.decomp_400 =	Decompress400,	
	.decomp_420 =	Decompress420,	
	.owner =	THIS_MODULE,
};

static int __init 
decomp_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);
	PDEBUG(1, "Using %s, %s quantization", IDCT_MESSAGE, 
	       staticquant ? "static" : "dynamic");

	return 0;
}

static void __exit 
decomp_exit(void)
{
	ov511_deregister_decomp_module(ov518, mmx);
	info("deregistered");
}

module_init(decomp_init);
module_exit(decomp_exit);

⌨️ 快捷键说明

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