h261dec.c
来自「symbian 下的helix player源代码」· C语言 代码 · 共 1,645 行 · 第 1/5 页
C
1,645 行
}
isym += status;
// We expect MBA, MBA Stuffing, or Startcode
while (sym[nextsym].type == SYM_MBA_STUFFING) {
++nextsym; // Remove MBA stuffing
}
}
for (i = mbnum + 1; i <= gob->num_mb; i++) {
mb[i-1].mtype = MTYPE_SKIP;
}
return (OK);
}
// insym[*nextsym] contains MTYPE when we enter
static int decode_mb( SYMBOL insym[], int * nextsym, int * quant,
GOB_DESCR * gob, MACROBLOCK_DESCR mb[], int mbnum,
SYMBOL outsym[])
{
int isym, blk, status, mask;
CHECKSYM ( char msg[120] ); /* Flawfinder: ignore */
//printf("decode_mb: "); printsym( insym[*nextsym] ); printf("\n");
isym = 0;
CHECKSYM( if (checksym( insym[*nextsym], SYM_MTYPE, "decode_mb") != OK) exit(0); )
mb[mbnum].mtype = insym[(*nextsym)++].value;
switch ( mb[mbnum].mtype ) {
case MTYPE_INTER_MQUANT:
CHECKSYM( if (checksym( insym[*nextsym], SYM_QUANT_TR, "decode_mb") != OK) exit(0); )
*quant = insym[(*nextsym)++].value;
if (*quant < QUANT_MIN || *quant > QUANT_MAX) {
BS_ERR_MSG( sprintf( msg, "decode_mb: quant = %d", *quant); /* Flawfinder: ignore */
H261ErrMsg( msg ); )
return (H261_ERROR);
}
// FALLTHROUGH
case MTYPE_INTER:
CHECKSYM( if (checksym( insym[*nextsym], SYM_CBP, "decode_mb") != OK) exit(0); )
mb[mbnum].cbp = insym[(*nextsym)++].value;
mask = 0x20; // Bitmask for first block
for (blk = 0; blk < 6; blk++) {
mb[mbnum].block[blk].nsym = 0;
if ((mb[mbnum].cbp & mask) != 0) {
status = decode_block( insym, nextsym,
&(mb[mbnum].block[blk]),
&outsym[isym] );
if (status == H261_ERROR) {
BS_ERR_MSG( sprintf( msg, "decode_mb: Bitstream error, block #%d", blk); /* Flawfinder: ignore */
H261ErrMsg( msg ); )
return (H261_ERROR);
}
isym += status;
}
mask >>= 1;
}
break;
case MTYPE_MCFILT_MQUANT:
case MTYPE_MC_MQUANT:
CHECKSYM( if (checksym( insym[*nextsym], SYM_QUANT_TR, "decode_mb") != OK) exit(0); )
*quant = insym[(*nextsym)++].value;
if (*quant < QUANT_MIN || *quant > QUANT_MAX) {
BS_ERR_MSG( sprintf( msg, "decode_mb: quant = %d", *quant); /* Flawfinder: ignore */
H261ErrMsg( msg ); )
return (H261_ERROR);
}
// FALLTHROUGH
case MTYPE_MCFILT_CBP:
case MTYPE_MC_CBP:
CHECKSYM( if (checksym( insym[*nextsym], SYM_MVD, "decode_mb") != OK) exit(0); )
mb[mbnum].mvd_x = insym[(*nextsym)++].value;
CHECKSYM( if (checksym( insym[*nextsym], SYM_MVD, "decode_mb") != OK) exit(0); )
mb[mbnum].mvd_y = insym[(*nextsym)++].value;
if (mbnum % gob->mb_width > 0 &&
mb[mbnum-1].mtype >= MTYPE_MC_NOCBP) {
mb[mbnum].mv_x = mb[mbnum-1].mv_x + mb[mbnum].mvd_x;
mb[mbnum].mv_y = mb[mbnum-1].mv_y + mb[mbnum].mvd_y;
} else {
mb[mbnum].mv_x = mb[mbnum].mvd_x;
mb[mbnum].mv_y = mb[mbnum].mvd_y;
}
CHECKSYM( if (checksym( insym[*nextsym], SYM_CBP, "decode_mb") != OK) exit(0); )
mb[mbnum].cbp = insym[(*nextsym)++].value;
mask = 0x20; // Bitmask for first block
for (blk = 0; blk < 6; blk++) {
mb[mbnum].block[blk].nsym = 0;
if ((mb[mbnum].cbp & mask) != 0) {
status = decode_block( insym, nextsym,
&(mb[mbnum].block[blk]),
&outsym[isym] );
if (status == H261_ERROR) {
BS_ERR_MSG( sprintf( msg, "decode_mb: Bitstream error, block #%d", blk); /* Flawfinder: ignore */
H261ErrMsg( msg ); )
return (H261_ERROR);
}
isym += status;
}
mask >>= 1;
}
break;
case MTYPE_MCFILT_NOCBP:
case MTYPE_MC_NOCBP:
CHECKSYM( if (checksym( insym[*nextsym], SYM_MVD, "decode_mb") != OK) exit(0); )
mb[mbnum].mvd_x = insym[(*nextsym)++].value;
CHECKSYM( if (checksym( insym[*nextsym], SYM_MVD, "decode_mb") != OK) exit(0); )
mb[mbnum].mvd_y = insym[(*nextsym)++].value;
if (mbnum % gob->mb_width > 0 &&
mb[mbnum-1].mtype >= MTYPE_MC_NOCBP) {
mb[mbnum].mv_x = mb[mbnum-1].mv_x + mb[mbnum].mvd_x;
mb[mbnum].mv_y = mb[mbnum-1].mv_y + mb[mbnum].mvd_y;
} else {
mb[mbnum].mv_x = mb[mbnum].mvd_x;
mb[mbnum].mv_y = mb[mbnum].mvd_y;
}
break;
case MTYPE_INTRA_MQUANT:
CHECKSYM( if (checksym( insym[*nextsym], SYM_QUANT_TR, "decode_mb") != OK) exit(0); )
*quant = insym[(*nextsym)++].value;
if (*quant < QUANT_MIN || *quant > QUANT_MAX) {
BS_ERR_MSG( sprintf( msg, "decode_mb: quant = %d", *quant); /* Flawfinder: ignore */
H261ErrMsg( msg ); )
return (H261_ERROR);
}
// FALLTHROUGH
case MTYPE_INTRA:
for (blk = 0; blk < 6; blk++) {
status = decode_intra_block( insym, nextsym,
&(mb[mbnum].block[blk]),
&outsym[isym] );
if (status == H261_ERROR) {
BS_ERR_MSG( sprintf( msg, "decode_mb: Bitstream error, block #%d", blk); /* Flawfinder: ignore */
H261ErrMsg( msg ); )
return (H261_ERROR);
}
isym += status;
}
break;
default: // Illegal MTYPE is due to program error; not from bit errors
CHECKSYM( sprintf( msg, "decode_mb: MTYPE = %d", mb[mbnum].mtype); /* Flawfinder: ignore */
H261ErrMsg( msg ); )
return (H261_ERROR);
break;
}
mb[mbnum].quant = *quant;
return (isym);
}
static int decode_intra_block( SYMBOL insym[], int * nextsym,
BLOCK_DESCR * block, SYMBOL outsym[])
{
int isym, zzpos, run;
CHECKSYM ( char msg[120] ); /* Flawfinder: ignore */
/* DC coefficient */
//printf("decode_intra_block DC: "); printsym( insym[*nextsym] ); printf("\n");
CHECKSYM( if (checksym( insym[*nextsym], SYM_INTRA_DC, "decode_intra") != OK) exit(0); )
outsym[0].type = 0;
outsym[0].value = insym[(*nextsym)++].value;
/* AC coefficients */
isym = 1;
zzpos = 1;
//printf("decode_intra_block AC: "); printsym( insym[*nextsym] ); printf("\n");
while (insym[*nextsym].type != SYM_EOB) {
if (insym[*nextsym].type == SYM_ESC_RUN) {
run = insym[(*nextsym)++].value;
outsym[isym].type = run;
CHECKSYM( if (checksym( insym[*nextsym], SYM_ESC_LEVEL, "decode_intra") != OK) exit(0); )
outsym[isym++].value = insym[(*nextsym)++].value;
} else {
run = insym[*nextsym].type;
CHECKSYM( if (run < 0) {
sprintf( msg, "PROGRAM ERROR: run = %d in decode_intra", run); /* Flawfinder: ignore */
H261ErrMsg( msg );
return( H261_ERROR );
} )
outsym[isym++] = insym[(*nextsym)++];
}
zzpos += run + 1;
// printf("decode_intra_block AC: "); printsym( insym[*nextsym] );
// printf(" zzpos = %d\n", zzpos);
if (zzpos > 64) { // If we decoded coeff. 63, we will now have zzpos=64
BS_ERR_MSG( sprintf( msg, "decode_intra_block: Bitstream error, zzpos=%d", zzpos); /* Flawfinder: ignore */
H261ErrMsg( msg ); )
return (H261_ERROR);
}
}
(*nextsym)++; /* Advance pointer to symbol after EOB */
block->sym = outsym;
block->nsym = isym;
return (isym);
}
/* Compute # bits in segment bs1 - bs2 */
extern int BsDiff( BS_PTR bs1, BS_PTR bs2 )
{
int bits;
bits = 8 * (bs1.byteptr - bs2.byteptr) + bs1.bitptr - bs2.bitptr;
return (bits);
}
static int find_startcodes( BS_PTR * bs, // Points to beginning of bitstream
int numbits, // length of bitstream in bits
BS_PTR start[], // Returns positions for startcodes; size "max_start"
int gobnum[], // Returns 4 bits after startcode (5 bits for H.263); size "max_start"
int max_start, // Max number of start codes to be returned
int codingMethod ) // Indicate H.261 or H.263 syntax
{
int i, bits_left, startZeros, gnBits;
BS_PTR bs_next;
if (codingMethod == H263_CODING) {
startZeros = H263_START_ZEROS;
gnBits = H263_GN_BITS;
} else { // H.261
startZeros = H261_START_ZEROS;
gnBits = H261_GN_BITS;
}
i = 0;
bs_next = *bs;
while (i < max_start) {
bits_left = numbits - BsDiff( bs_next, *bs);
if (find_sc( &bs_next, bits_left, startZeros, &start[i] ) != YES) {
return (i);
}
gobnum[i] = Get8Bits( start[i] ) >> (8 - gnBits);
bs_next = start[i];
i++;
}
return (max_start);
}
static U8 leading[256];
static U8 trailing[256];
extern void InitFindSC( void )
{
int i, j, bitmask;
for (i = 0; i < 256; i++) {
leading[i] = 0;
bitmask = 0x80;
for (j = 0; j < 8; j++) {
if ((i & bitmask) != 0) {
break;
}
bitmask >>= 1;
++leading[i];
}
trailing[i] = 0;
bitmask = 0x1;
for (j = 0; j < 8; j++) {
if ((i & bitmask) != 0) {
break;
}
bitmask <<= 1;
++trailing[i];
}
//printf("%3x: Leading = %d Trailing = %d\n", i, leading[i], trailing[i]);
}
return;
}
// find_sc - Find startcode consisting of startZeros zeros followed by 1
// Returns YES if startcode found, otherwise NO
// Operates on byte boundaries; might not look at last 8 bits in bitstream
static int find_sc( BS_PTR * bs, // Points to beginning of bitstream
int numbits, // length of bitstream in bits
int startZeros, // number of zeros in startcode
BS_PTR * start ) // Returns position for bit after startcode
{
int zeros, nbytes, i, validBitsInLastByte;
U8 b;
/* Read first byte from bitstream; set "irrelevant bits" to 1 */
b = *bs->byteptr | (0xff & (0xff << (8 - bs->bitptr)));
zeros = trailing[b];
// nbytes = (numbits + bs->bitptr - 8 - max(H263_GN_BITS, H261_GN_BITS) ) >> 3;
nbytes = (numbits + bs->bitptr - 1 ) >> 3;
validBitsInLastByte = (numbits + bs->bitptr) &07;
if (validBitsInLastByte == 0)
validBitsInLastByte = 8;
start->byteptr = bs->byteptr + 1;
for (i = 0; i < nbytes; i++) {
b = *start->byteptr;
zeros += leading[b];
if (zeros < startZeros && b != 0) {
zeros = trailing[b];
} else if (b != 0) { /* Found startcode */
start->bitptr = leading[b] + 1;
if (i == nbytes - 1 &&
start->bitptr + H263_GN_BITS > validBitsInLastByte
||
i == nbytes - 2 &&
start->bitptr + H263_GN_BITS > 8 + validBitsInLastByte)
return(NO);
if (start->bitptr > 7) {
++(start->byteptr);
start->bitptr -= 8;
}
return (YES);
} /* else: b=0; continue until 1 is found */
++(start->byteptr);
}
return (NO);
}
#ifdef TESTING
/////////// Routines for debugging //////////////
extern int checksym( SYMBOL sym, int type, char routine[] )
{
char msg[120], csym[80], ctype[80]; /* Flawfinder: ignore */
if (sym.type == type) {
return (OK);
} else { // Not expected type
sprintsym( sym , csym, 80);
sprinttype( type, ctype, 80);
SafeSprintf(msg, 120, "%s: Encountered %s Expected %s", routine, csym, ctype);
H261ErrMsg( msg );
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?