📄 h261decoder.cpp
字号:
/* //////////////////////////////////////////////////////////////////////////
//
// INTEL CORPORATION PROPRIETARY INFORMATION
// This software is supplied under the terms of a license agreement or
// nondisclosure agreement with Intel Corporation and may not be copied
// or disclosed except in accordance with the terms of that agreement.
// Copyright (c) 2005-2007 Intel Corporation. All Rights Reserved.
//
*/
#include "h261decoder.h"
static Ipp32u _ShowBits(H261DEC_STATE* dec_state, Ipp32s n)
{
Ipp8u* ptr = dec_state->bufptr;
Ipp32u tmp = (ptr[0] << 24) | (ptr[1] << 16) | (ptr[2] << 8) | (ptr[3]);
tmp <<= dec_state->bitoff;
tmp >>= 32 - n;
return tmp;
}
static void _FlushBits(H261DEC_STATE* dec_state, Ipp32s n)
{
n = n + dec_state->bitoff;
dec_state->bufptr += n >> 3;
dec_state->bitoff = n & 7;
}
static Ipp32u _GetBits(H261DEC_STATE* dec_state, Ipp32s n)
{
Ipp8u* ptr = dec_state->bufptr;
Ipp32u tmp = (ptr[0] << 24) | (ptr[1] << 16) | (ptr[2] << 8) | (ptr[3]);
tmp <<= dec_state->bitoff;
tmp >>= 32 - n;
n = n + dec_state->bitoff;
dec_state->bufptr += n >> 3;
dec_state->bitoff = n & 7;
return tmp;
}
Ipp32s getPictureHeader(H261DEC_STATE* dec_state)
{
Ipp32u code;
// PSC
code = _GetBits(dec_state, 20);
if (code != 16)
return 1;
// decode TR
code = _GetBits(dec_state, 5);
// set picture time
if (code < dec_state->tr)
code += 32;
if (dec_state->tr < 32)
dec_state->time += code - dec_state->tr;
dec_state->tr = (Ipp8u)(code & 0x1F);
// decode PTYPE
code = _GetBits(dec_state, 6);
// Split screen indicator is ignored
// if (code & 0x20) {
// ErrMsg("Split Screen Indicator not supported");
// return -1;
// }
// Document camera indicator is ignored
// if (code & 0x10) {
// ErrMsg("Document Camera Indicator not supported");
// return -1;
// }
// Freeze Picture Release bit is ignored
// if (code & 0x8) {
// ErrMsg("Freeze Picture Release not supported");
// return -1;
// }
// Source format
if (code & 0x4) {
dec_state->picture_format = 1; // CIF
dec_state->picture_width = 352;
dec_state->picture_height = 288;
dec_state->numgob = 12;
} else {
dec_state->picture_format = 0; // QCIF
dec_state->picture_width = 352/2;
dec_state->picture_height = 288/2;
dec_state->numgob = 3;
}
// Still image bit is ignored - Annex D not supported
// if ((code & 0x2) == 0) {
// ErrMsg("Still Image Mode not supported");
// return -1;
// }
// bit 6 of PTYPE is spare
while (_GetBits(dec_state, 1)) { // extra insertion information (PEI)
_FlushBits(dec_state, 8); // PSPARE
}
return 0;
} // getPictureHeader()
#define H261_LIMIT_MV(bx, by, mvx, mvy, width, height) \
if (mvx < -(bx)) \
mvx = -(bx); \
if (mvx > (width) - (bx) - 16) \
mvx = (width) - (bx) - 16; \
if (mvy < -(by)) \
mvy = -(by); \
if (mvy > (height) - (by) - 16) \
mvy = (height) - (by) - 16; \
static void reconstruct(Ipp32s bx, Ipp32s by, Ipp32s mvx, Ipp32s mvy, Ipp32s filter, H261DEC_STATE* dec_state)
{
Ipp8u* src;
Ipp8u* dst;
Ipp32s i;
Ipp32s lx = dec_state->picture_width;
H261_LIMIT_MV(bx, by, mvx, mvy, dec_state->picture_width, dec_state->picture_height)
/* Y */
src = dec_state->refPic[0] + lx * (by + mvy) + bx + mvx;
dst = dec_state->curPic[0] + lx * by + bx;
if (filter) {
Ipp8u *dblock, *sblock;
for (i = 0; i < 4; i++) {
dblock = dst + (i & 2)*4*lx + (i & 1)*8;
sblock = src + (i & 2)*4*lx + (i & 1)*8;
ippiFilter8x8_H261_8u_C1R(sblock, lx, dblock, lx);
}
} else {
ippiCopy16x16_8u_C1R(src, lx, dst, lx);
}
/* Chroma */
lx >>= 1;
bx >>= 1;
by >>= 1;
mvx /= 2; // truncate towards zero, can be negative
mvy /= 2;
src = dec_state->refPic[1] + lx * (by + mvy) + bx + mvx;
dst = dec_state->curPic[1] + lx * by + bx;
if (filter)
ippiFilter8x8_H261_8u_C1R(src, lx, dst, lx);
else
ippiCopy8x8_8u_C1R(src, lx, dst, lx);
src = dec_state->refPic[2] + lx * (by + mvy) + bx + mvx;
dst = dec_state->curPic[2] + lx * by + bx;
if (filter)
ippiFilter8x8_H261_8u_C1R(src, lx, dst, lx);
else
ippiCopy8x8_8u_C1R(src, lx, dst, lx);
} // reconstruct()
static Ipp32s fillBlock(Ipp32s bx, Ipp32s by, Ipp32s i, Ipp32s quant, H261DEC_STATE* dec_state)
{
__ALIGN16(Ipp16s, coeffs, 64);
Ipp32s step;
Ipp8u* pDst;
IppStatus status;
Ipp32s iLNZ;
Ipp32s picture_width = dec_state->picture_width;
#if 0
{
__ALIGN16(Ipp16s, coeffsZ, 64);
status = ippiDecodeCoeffsIntra_H261_1u16s(&dec_state->bufptr, &dec_state->bitoff,
coeffsZ, &iLNZ, -1);
if (status != ippStsNoErr)
return -1;
status = ippiQuantInvIntra_H263_16s_C1I(coeffsZ, iLNZ, quant, 0, 0);
if (status != ippStsNoErr)
return -1;
status = ippiScanInv_16s_C1(coeffsZ, coeffs, iLNZ, IPPVC_SCAN_ZIGZAG);
}
#else
status = ippiReconstructCoeffsIntra_H261_1u16s(&dec_state->bufptr, &dec_state->bitoff,
coeffs, &iLNZ, quant);
#endif
if (status != ippStsNoErr)
return -1;
if (i > 3) {
step = picture_width >> 1;
bx >>= 1;
by >>= 1;
pDst = dec_state->curPic[i-3] + step*by + bx;
} else {
step = picture_width;
pDst = dec_state->curPic[0] + picture_width*(by + (i & 2)*4) + bx + (i & 1)*8;
}
ippiDCT8x8Inv_16s8u_C1R(coeffs, pDst, step);
return 0;
} // fillBlock()
static Ipp32s reconBlock(Ipp32s bx, Ipp32s by, Ipp32s i, Ipp32s quant, H261DEC_STATE* dec_state)
{
__ALIGN16(Ipp16s, coeffs, 64);
Ipp32s step;
Ipp8u* pSrcDst;
IppStatus status = ippStsErr;
Ipp32s iLNZ;
Ipp32s picture_width = dec_state->picture_width;
#if 0
{
__ALIGN16(Ipp16s, coeffsZ, 64);
status = ippiDecodeCoeffsInter_H261_1u16s(&dec_state->bufptr, &dec_state->bitoff,
coeffsZ, &iLNZ, -1);
if (status != ippStsNoErr)
return -1;
status = ippiQuantInvInter_H263_16s_C1I(coeffsZ, iLNZ, quant, 0);
if (status != ippStsNoErr)
return -1;
status = ippiScanInv_16s_C1(coeffsZ, coeffs, iLNZ, IPPVC_SCAN_ZIGZAG);
}
#else
status = ippiReconstructCoeffsInter_H261_1u16s(&dec_state->bufptr, &dec_state->bitoff,
coeffs, &iLNZ, quant);
#endif
if (status != ippStsNoErr)
return -1;
if ((iLNZ < 5) && (!coeffs[16]))
ippiDCT8x8Inv_2x2_16s_C1I(coeffs);
else if ((iLNZ < 10) || ((iLNZ < 14) && (!coeffs[32])) ||
((iLNZ < 19) && (!(coeffs[32] | coeffs[4] | coeffs[5] | coeffs[12]))))
ippiDCT8x8Inv_4x4_16s_C1I(coeffs);
else
ippiDCT8x8Inv_16s_C1I(coeffs);
if (i > 3) {
step = picture_width >> 1;
bx >>= 1;
by >>= 1;
pSrcDst = dec_state->curPic[i-3] + step*by + bx;
} else {
step = picture_width;
pSrcDst = dec_state->curPic[0] + picture_width*(by + (i & 2)*4) + bx + (i & 1)*8;
}
ippiAdd8x8_16s8u_C1IRS(coeffs, 16, pSrcDst, step);
return 0;
} // reconBlock()
/*-------------------------------------------------------------*/
typedef struct {
Ipp16u val;
Ipp16u len;
} H261_vlc;
#define VLC_ERR -1
static const H261_vlc mba_tab1[15] =
{
{7,5}, {6,5}, {5,4}, {5,4}, {4,4}, {4,4}, {3,3}, {3,3}, {3,3}, {3,3},
{2,3}, {2,3}, {2,3}, {2,3}, {1,1}
};
static const H261_vlc mba_tab2[46] =
{
{21,6}, {20,6}, {19,6}, {18,6}, {17,6}, {16,6},
{15,4}, {15,4}, {15,4}, {15,4}, {14,4}, {14,4}, {14,4}, {14,4},
{13,4}, {13,4}, {13,4}, {13,4}, {12,4}, {12,4}, {12,4}, {12,4},
{11,4}, {11,4}, {11,4}, {11,4}, {10,4}, {10,4}, {10,4}, {10,4},
{9, 3}, {9, 3}, {9, 3}, {9, 3}, {9, 3}, {9, 3}, {9, 3}, {9, 3},
{8, 3}, {8, 3}, {8, 3}, {8, 3}, {8, 3}, {8, 3}, {8, 3}, {8, 3},
};
static Ipp32s dec_MBA(H261DEC_STATE* dec_state)
{
Ipp32u code;
Ipp32s mba, len;
H261_vlc vlc;
code = _ShowBits(dec_state, 5);
if (code >= 16) {
_FlushBits(dec_state, 1);
mba = 1;
} else if (code > 1) {
vlc = mba_tab1[code - 2];
mba = vlc.val;
len = vlc.len;
_FlushBits(dec_state, len);
} else {
_FlushBits(dec_state, 4);
code = _ShowBits(dec_state, 7);
if ((code >> 1) >= 18) {
vlc = mba_tab2[(code >> 1) - 18];
mba = vlc.val;
len = vlc.len;
} else {
len = 7;
if (code >= 16) {
mba = 57 - code;
} else
// mba = (code == 15) ? IPPVC_MB_STUFFING : VLC_ERR;
mba = -1;
}
_FlushBits(dec_state, len);
}
return mba;
}
/*-------------------------------------------------------------*/
#define MTYPE_INTRA 1
#define MTYPE_MQUANT 2
#define MTYPE_MVD 4
#define MTYPE_TCOEFF 8
#define MTYPE_FIL 16
static const Ipp8u mtype_tab[10] =
{
MTYPE_TCOEFF,
MTYPE_TCOEFF | MTYPE_MVD | MTYPE_FIL,
MTYPE_MVD | MTYPE_FIL,
MTYPE_INTRA, // | MTYPE_TCOEFF,
MTYPE_TCOEFF | MTYPE_MQUANT,
MTYPE_TCOEFF | MTYPE_MQUANT | MTYPE_MVD | MTYPE_FIL,
MTYPE_INTRA | MTYPE_MQUANT, // | MTYPE_TCOEFF,
MTYPE_TCOEFF | MTYPE_MVD,
MTYPE_MVD,
MTYPE_TCOEFF | MTYPE_MQUANT | MTYPE_MVD
};
static Ipp32s dec_MTYPE(H261DEC_STATE* dec_state)
{
Ipp32u code;
Ipp32s mtype;
Ipp32s i;
code = _ShowBits(dec_state, 10);
for (i = 0; i < 10; i++) {
if (code & (512 >> i)) break;
}
if (i > 9) return VLC_ERR;
mtype = mtype_tab[i];
_FlushBits(dec_state, i+1);
return mtype;
}
/*-------------------------------------------------------------*/
static const H261_vlc mvd_tab1[14] =
{
{3,5}, {29,5}, {2,4}, {2,4}, {30,4}, {30,4},
{1,3}, {1,3}, {1,3}, {1,3}, {31,3}, {31,3}, {31,3}, {31,3}
};
static const H261_vlc mvd_tab2[103] =
{
{16,11}, {15,11}, {17,11}, {14,11}, {18,11}, {13,11}, {19,11}, {12,11},
{20,11}, {11,11}, {21,11}, {10,10}, {10,10}, {22,10}, {22,10},
{9,10}, {9,10}, {23,10}, {23,10}, {8,10}, {8,10}, {24,10}, {24,10},
{7,8}, {7,8}, {7,8}, {7,8}, {7,8}, {7,8}, {7,8}, {7,8},
{25,8}, {25,8}, {25,8}, {25,8}, {25,8}, {25,8}, {25,8}, {25,8},
{6,8}, {6,8}, {6,8}, {6,8}, {6,8}, {6,8}, {6,8}, {6,8},
{26,8}, {26,8}, {26,8}, {26,8}, {26,8}, {26,8}, {26,8}, {26,8},
{5,8}, {5,8}, {5,8}, {5,8}, {5,8}, {5,8}, {5,8}, {5,8},
{27,8}, {27,8}, {27,8}, {27,8}, {27,8}, {27,8}, {27,8}, {27,8},
{4,7}, {4,7}, {4,7}, {4,7}, {4,7}, {4,7}, {4,7}, {4,7},
{4,7}, {4,7}, {4,7}, {4,7}, {4,7}, {4,7}, {4,7}, {4,7},
{28,7}, {28,7}, {28,7}, {28,7}, {28,7}, {28,7}, {28,7}, {28,7},
{28,7}, {28,7}, {28,7}, {28,7}, {28,7}, {28,7}, {28,7}, {28,7}
};
static Ipp32s dec_MVD(H261DEC_STATE* dec_state)
{
Ipp32u code;
Ipp32s mvd, len;
H261_vlc vlc;
code = _ShowBits(dec_state, 11);
if (code & 1024) {
mvd = 0;
len = 1;
} else if ((code >> 6) >= 2) {
vlc = mvd_tab1[(code >> 6) - 2];
mvd = vlc.val;
len = vlc.len;
} else if (code >= 25) {
vlc = mvd_tab2[code - 25];
mvd = vlc.val;
len = vlc.len;
} else
return VLC_ERR;
_FlushBits(dec_state, len);
return mvd;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -