📄 h261decoder.cpp
字号:
/*-------------------------------------------------------------*/
static const Ipp8u cbp_tab1[64] =
{
34, 18, 10, 6, 33, 17, 9, 5, 63, 63, 3, 3,
36, 36, 24, 24, 62, 62, 62, 62, 2, 2, 2, 2,
61, 61, 61, 61, 1, 1, 1, 1, 56, 56, 56, 56,
52, 52, 52, 52, 44, 44, 44, 44, 28, 28, 28, 28,
40, 40, 40, 40, 20, 20, 20, 20, 48, 48, 48, 48,
12, 12, 12, 12
};
static const Ipp8s cbp_tab2[64] =
{
VLC_ERR, VLC_ERR, 39, 27, 59, 55, 47, 31,
58, 58, 54, 54, 46, 46, 30, 30, 57, 57, 53, 53,
45, 45, 29, 29, 38, 38, 26, 26, 37, 37, 25, 25,
43, 43, 23, 23, 51, 51, 15, 15, 42, 42, 22, 22,
50, 50, 14, 14, 41, 41, 21, 21, 49, 49, 13, 13,
35, 35, 19, 19, 11, 11, 7, 7
};
static Ipp32s dec_CBP(H261DEC_STATE* dec_state)
{
Ipp32u code;
Ipp32s val, len, c4;
code = _ShowBits(dec_state, 9);
c4 = code >> 5;
if (c4 >= 10) {
if (c4 >= 14) {
val = 60;
len = 3;
} else {
val = 1 << (15 - c4);
len = 4;
}
} else if (c4 > 1) {
val = cbp_tab1[(code >> 2) - 16];
len = (c4 > 3) ? 5 : (9 - c4);
} else {
val = cbp_tab2[code];
len = (code > 7) ? 8 : 9;
}
_FlushBits(dec_state, len);
return val;
}
static void copy_GOBs(H261DEC_STATE* dec_state, Ipp32s gobS, Ipp32s gobE, Ipp32s gob_step)
{
Ipp32s gob;
Ipp32s xpos, ypos;
IppiSize roiY, roiC;
Ipp32s offY, offC;
roiY.height = 48;
roiC.height = 24;
roiY.width = 176;
roiC.width = roiY.width >> 1;
for (gob = gobS; gob < gobE; gob += gob_step) {
xpos = (gob & 1) ? 0 : 176;
ypos = ((gob - 1) >> 1) * 3 * 16;
offY = ypos * dec_state->picture_width + xpos;
offC = (ypos * dec_state->picture_width >> 2) + (xpos >> 1);
ippiCopy_8u_C1R(dec_state->refPic[0] + offY, dec_state->picture_width,
dec_state->curPic[0] + offY, dec_state->picture_width, roiY);
ippiCopy_8u_C1R(dec_state->refPic[1] + offC, dec_state->picture_width >> 1,
dec_state->curPic[1] + offC, dec_state->picture_width >> 1, roiC);
ippiCopy_8u_C1R(dec_state->refPic[2] + offC, dec_state->picture_width >> 1,
dec_state->curPic[2] + offC, dec_state->picture_width >> 1, roiC);
}
}
static void copy_Macroblocks(H261DEC_STATE* dec_state, Ipp32s mbaS, Ipp32s nmbs, Ipp32s xpos, Ipp32s ypos)
{
Ipp32s w;
IppiSize roiY, roiC;
Ipp32s mbxpos, mbypos;
Ipp32s offY, offC, bx, by;
mbxpos = mbaS % 11;
mbypos = mbaS / 11;
roiY.height = 16;
roiC.height = 8;
if (nmbs > 33 - mbaS)
nmbs = 33 - mbaS; /* error or end of stream */
while (nmbs > 0) {
bx = 16 * (mbxpos + xpos);
by = 16 * (mbypos + ypos);
offY = by * dec_state->picture_width + bx;
offC = (by * dec_state->picture_width >> 2) + (bx >> 1);
w = nmbs > (11 - mbxpos) ? (11 - mbxpos) : nmbs;
nmbs -= w;
roiY.width = w*16;
roiC.width = roiY.width >> 1;
ippiCopy_8u_C1R(dec_state->refPic[0] + offY, dec_state->picture_width,
dec_state->curPic[0] + offY, dec_state->picture_width, roiY);
ippiCopy_8u_C1R(dec_state->refPic[1] + offC, dec_state->picture_width >> 1,
dec_state->curPic[1] + offC, dec_state->picture_width >> 1, roiC);
ippiCopy_8u_C1R(dec_state->refPic[2] + offC, dec_state->picture_width >> 1,
dec_state->curPic[2] + offC, dec_state->picture_width >> 1, roiC);
mbxpos = 0;
mbypos++;
}
}
static Ipp32s find_GBSC(H261DEC_STATE* dec_state, Ipp32u *outCode)
{
Ipp32s end_of_frame = 0;
Ipp32u code = *outCode;
for (;;) {
while (dec_state->bufptr[1] != 0) {
dec_state->bufptr++;
if (dec_state->buflen - (dec_state->bufptr - dec_state->buffer) < 3) {
end_of_frame = 1;
break;
}
}
if (end_of_frame)
break;
for (dec_state->bitoff = 1; dec_state->bitoff < 8; dec_state->bitoff++) {
code = _ShowBits(dec_state, 16);
if (code == 1)
break;
}
if (code != 1) {
dec_state->bufptr++;
dec_state->bitoff = 0;
code = _ShowBits(dec_state, 16);
}
if (dec_state->bitoff + 20 > (dec_state->buflen - (dec_state->bufptr - dec_state->buffer)) << 3) {
end_of_frame = 1;
break;
}
if (code == 1) {
code = _ShowBits(dec_state, 20);
break;
}
}
*outCode = code;
return end_of_frame;
}
/*-------------------------------------------------------------*/
// decoded picture will be in dec_state->refPic
Ipp32s getPicture(H261DEC_STATE* dec_state)
{
Ipp32s i, numgob, picType = 0, err = 0;
Ipp32s xpos;
Ipp32s ypos;
Ipp32s mbxpos, mbypos;
Ipp32s gob = 1, prev_gob = 0, gob_step = dec_state->picture_format ? 1 : 2;
Ipp32s mba = 0, mba_dif;
Ipp32s mtype;
Ipp32s cbp;
Ipp32s mquant;
Ipp32s r;
Ipp32s mvx, mvy, mvxd, mvyd;
Ipp32s bx, by;
Ipp32u code;
Ipp32s end_of_frame;
Ipp32s ret = 0;
for (numgob = 0; numgob < dec_state->numgob || err == -1; numgob++) {
err = 0;
if (dec_state->bitoff + 20 > (dec_state->buflen - (dec_state->bufptr - dec_state->buffer)) << 3)
break;
// GBSC
code = _ShowBits(dec_state, 20);
if ((code &~ 0xf) != 0x10) {
end_of_frame = find_GBSC(dec_state, &code);
if (end_of_frame)
break;
}
if (code == 0x10)
break;
_FlushBits(dec_state, 20);
gob = code & 15;
if ((gob <= 0) || (gob > 12) || ((dec_state->picture_format == 0) && ((gob > 5) || ((gob & 1) == 0)))) {
ErrMsg("Invalid GOB number"); // gob numbers 13-15 are reserved for future use
err = -1;
continue;
}
if (gob - prev_gob - gob_step > 0) { // skipped GOB(s)
numgob += (gob - prev_gob - gob_step) >> (gob_step - 1);
copy_GOBs(dec_state, prev_gob + gob_step, gob, gob_step);
}
prev_gob = gob;
mquant = _GetBits(dec_state, 5); // To be used until overriden by any subsequent MQUANT
if (!mquant) {
ErrMsg("Invalid GQUANT");
err = -1;
continue;
}
while (_GetBits(dec_state, 1)) { // extra insertion information (GEI)
_FlushBits(dec_state, 8); // GSPARE
}
xpos = (gob & 1) ? 0 : 11;
ypos = ((gob - 1) >> 1) * 3;
mba = 0;
mvx = mvy = 0;
for (;;) {
Ipp32s bits_left = (dec_state->buflen - (dec_state->bufptr - dec_state->buffer)) << 3;
// 6 bits is minimum MB code length: non-MC MB with in-loop filter on
for (;;) {
if (dec_state->bitoff + 6 <= bits_left) {
code = _ShowBits(dec_state, 6);
if (code == 0 && (dec_state->bitoff + 11 <= bits_left)) {
code = _ShowBits(dec_state, 11);
if (code == 15) {
_FlushBits(dec_state, 11);
continue;
}
}
} else
code = 0;
break;
}
if (code == 0) { /* start code */
if (mba < 33) /* need to copy the gob's skipped tail */
copy_Macroblocks(dec_state, mba, 33 - mba, xpos, ypos);
break;
}
mba_dif = dec_MBA(dec_state);
if (mba_dif < 0) {
ErrMsg("Invalid MBA");
mba++; // macroblock at mba was decoded correctly - need not be copied from prev. frame
err = -1;
break;
}
if (mba + mba_dif > 33) { /* can happen at the end of stream */
mba++; // macroblock at mba was decoded correctly
err = -1;
break;
}
if (mba_dif > 1) /* need to copy the skipped mbs */
copy_Macroblocks(dec_state, mba, mba_dif - 1, xpos, ypos);
mba += mba_dif;
mbxpos = xpos + ((mba - 1) % 11);
mbypos = ypos + (mba - 1) / 11;
if ((mba == 12) || (mba == 23) || (mba_dif > 1)) {
mvx = mvy = 0;
}
mtype = dec_MTYPE(dec_state);
if (mtype < 0) {
ErrMsg("Invalid MTYPE");
err = -1;
break;
}
if (mtype & MTYPE_MQUANT) {
mquant = _GetBits(dec_state, 5); // To be used until overriden by any subsequent MQUANT
if (!mquant) {
ErrMsg("Invalid MQUANT");
err = -1;
break;
}
}
if (mtype & MTYPE_MVD) {
mvxd = dec_MVD(dec_state);
if (mvxd < 0) {
ErrMsg("Invalid horizontal MV");
err = -1;
break;
}
mvyd = dec_MVD(dec_state);
if (mvyd < 0) {
ErrMsg("Invalid vertical MV");
err = -1;
break;
}
mvx += mvxd;
if (mvx > 16) // MV range is [-15,15], (mv==16) implies an error in the stream
mvx -= 32;
mvy += mvyd;
if (mvy > 16)
mvy -= 32;
} else {
mvx = mvy = 0;
}
if (mtype & MTYPE_INTRA)
cbp = 63;
else if (mtype & MTYPE_TCOEFF) {
cbp = dec_CBP(dec_state);
if (cbp < 0) {
ErrMsg("Invalid CBP");
err = -1;
break;
}
} else
cbp = 0;
bx = 16 * mbxpos;
by = 16 * mbypos;
if (!(mtype & MTYPE_INTRA)) {
picType = 1;
reconstruct(bx, by, mvx, mvy, mtype & MTYPE_FIL, dec_state);
for (i = 0; i < 6; i++) {
if (cbp & (32 >> i)) {
r = reconBlock(bx, by, i, mquant, dec_state);
if (r < 0) {
ErrMsg("reconBlock failed");
err = -1;
break;
}
}
}
} else { // intra
for (i = 0; i < 6; i++) {
r = fillBlock(bx, by, i, mquant, dec_state);
if (r < 0) {
ErrMsg("fillBlock failed");
err = -1;
break;
}
}
}
}
if (err == -1) {
copy_Macroblocks(dec_state, mba - 1, 33 - mba + 1, xpos, ypos);
ret = -1;
}
}
gob = dec_state->picture_format ? 13 : 6;
if (gob - prev_gob - gob_step > 0)
copy_GOBs(dec_state, prev_gob + gob_step, dec_state->picture_format ? 13 : 6, gob_step);
// _SWAP(Ipp8u*, dec_state->curPic[0], dec_state->refPic[0]);
// _SWAP(Ipp8u*, dec_state->curPic[1], dec_state->refPic[1]);
// _SWAP(Ipp8u*, dec_state->curPic[2], dec_state->refPic[2]);
_SWAP(Ipp32u, dec_state->mid_cur, dec_state->mid_ref);
dec_state->picType = picType;
// return err;
return ret;
} // getPicture()
Ipp32s initDecoder(H261DEC_STATE *dec_state)
{
// Ipp32s picture_width, picture_height;
Ipp32s status;
dec_state->bufptr = dec_state->buffer;
dec_state->bitoff = 0;
status = getPictureHeader(dec_state);
if (status != 0)
return status;
dec_state->bufptr = dec_state->buffer;
dec_state->bitoff = 0;
/*
picture_width = dec_state->picture_width;
picture_height = dec_state->picture_height;
dec_state->curPic[0] = dec_state->curPic[1] = dec_state->curPic[2] =
dec_state->refPic[0] = dec_state->refPic[1] = dec_state->refPic[2] = 0;
dec_state->curPic[0] = ippsMalloc_8u(picture_width * picture_height);
dec_state->curPic[1] = ippsMalloc_8u(picture_width * picture_height / 4);
dec_state->curPic[2] = ippsMalloc_8u(picture_width * picture_height / 4);
dec_state->refPic[0] = ippsMalloc_8u(picture_width * picture_height);
dec_state->refPic[1] = ippsMalloc_8u(picture_width * picture_height / 4);
dec_state->refPic[2] = ippsMalloc_8u(picture_width * picture_height / 4);
if (!dec_state->curPic[0] || !dec_state->curPic[1] || !dec_state->curPic[2] ||
!dec_state->refPic[0] || !dec_state->refPic[1] || !dec_state->refPic[2]) {
freeDecoder(dec_state);
return false;
}
*/
return 0;
} // initDecoder()
/*
void freeDecoder(H261DEC_STATE* dec_state)
{
ippsFree(dec_state->curPic[0]);
ippsFree(dec_state->curPic[1]);
ippsFree(dec_state->curPic[2]);
ippsFree(dec_state->refPic[0]);
ippsFree(dec_state->refPic[1]);
ippsFree(dec_state->refPic[2]);
} // freeDecoder()
*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -