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 + -
显示快捷键?