📄 ov518_decomp.c
字号:
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 + -