h261dec.c

来自「symbian 下的helix player源代码」· C语言 代码 · 共 1,645 行 · 第 1/5 页

C
1,645
字号

// savePSCpointer - Pass the pointer to the picture start code to caller
static void savePSCpointer( BS_PTR *bsPSC, H261Decoder *s )
{
    s->status.dwPsc = TRUE; 
    s->status.pscIndex.ww.byte = bsPSC->byteptr - s->bsAbs.byteptr; 
    s->status.pscIndex.ww.bit =  bsPSC->bitptr & 0xff;
    return;
}

// outputBsPointer - Copy "start" pointer and back up by length of startcode
static void outputBsPointer( BS_PTR * start, BS_PTR * output, int codingMethod )
{
    int lenStartCode;
    
    if (codingMethod == H263_CODING) {
        lenStartCode = H263_START_ZEROS + 1;
    } else {
        lenStartCode = H261_START_ZEROS + 1;
    }
    *output = *start;
    IncBsPtr( output, -lenStartCode );
    return;
}


// decodeBitstream - Decode bitstream for a GOB
//  Returns H261_ERROR if we need to exit to resync on next PSC
static int decodeBitstream( H261Decoder *s,
                            GOB_DESCR   *gob,
                            BS_PTR      start[2],
                            int         gn[2],
                            int         *structStatus,
                            int         *decStatus )
{
    BS_ERR_MSG(char msg[120];) /* Flawfinder: ignore */
    int nextStart;

    *structStatus = doGobStructures( s, gob, s->mb, &start[0], &gn[0] );
    if (*structStatus == OK  &&  gn[0] == s->next_gob) {
        // GOB number is correct and structures in place
        *decStatus = doGobDecoding( s, gob, s->mb, &start[0], s->sym, s->maxSym );
    } else if (*structStatus == OK  &&  gn[0] == gob->next_gn) {     // GBSC was probably trashed
        // This case will not occur for H.263
        *structStatus = H261_ERROR;
        //printf("Calling ConcealGob \n");
        ConcealGob( gob, s->mb, s->pic_layer.reducedResUpdate, &s->oldOut, &s->newOut);
        ++s->status.dwBadgobs;
        s->status.dwGobs += gob->num_mb / max(1,gob->mb_width);
        s->next_gob = gob->next_gn;
        s->status.dwIntraFrame=0;
        BS_ERR_MSG(
            sprintf( msg, "Bitstream error: did not find GOB %d", s->next_gob); /* Flawfinder: ignore */
            H261ErrMsg( msg ); )
    } else if (gn[0] == 0) {   // Unexpected PSC; exit so we can resync
        *structStatus = H261_ERROR;
        if (s->codingMethod == H263_CODING  &&  s->next_gob == 0) {
            nextStart = 1;  // Try next startcode; this PSC did not work
        } else {
            nextStart = 0;  // Start with PSC next time
        }
        outputBsPointer( &start[nextStart], &s->newBs, (int)s->codingMethod );
        BS_ERR_MSG( H261ErrMsg("Bitstream error: encountered PSC when expecting GBSC"); )
        ++s->status.dwBadgobs;
        s->status.dwIntraFrame=0;
        s->next_gob = 0;
        return H261_ERROR;  // This picture did not get done; start again
    } else {    // Assume that GBSC was false; keep looking for GN = next_gob
        *structStatus = H261_ERROR;
    }
    return OK;
}


// doGobStructures - Create gob and mb structures
static int  doGobStructures( H261Decoder *s, GOB_DESCR *gob, MACROBLOCK_DESCR mb[],
                        BS_PTR start[2], int gn[2] )
{
    int     maxbits, status;
    
    //printf("Entering doGobStructures:  gn[] = %d %d\n", gn[0], gn[1]);
    gob->mb = mb;
    if (s->codingMethod == H263_CODING) {
        if (s->next_gob > 0) {  // No GOB Layer for GOB 0
            maxbits = BsDiff(start[1], start[0]);
            status = DecGobLayer263( &start[0], maxbits, gob, &s->gfid );
            // start[0] gets bumped by DecGobLayer263; now pointing to MB layer
            if (status != OK) {
                BS_ERR_MSG( H261ErrMsg( "Bit error: DecGobLayer263 returned error" );)
                return( H261_ERROR );
            }
        }
        status = build263gob( s->pic_layer.format, s->next_gob, gn[1], gob, &s->pic_layer );
        if (status != OK) {
            BS_ERR_MSG( H261ErrMsg( "Bit error: build263gob returned error" );)
            return( H261_ERROR );
        }
    } else {    // H.261
        status = build_gob_struct( s->pic_layer.format, s->next_gob, gob );
        if (status != OK) {
            H261ErrMsg( "Program error: build_gob_struct returned error" );
            return( H261_ERROR );
        }
    }
    return( status );
}


// doGobDecoding - Decode all information in a GOB
static int  doGobDecoding( H261Decoder *s, GOB_DESCR *gob, MACROBLOCK_DESCR mb[],
                        BS_PTR start[2], SYMBOL sym[], int maxsym )
{
    int     maxbits, status;
    
    //printf("Entering doGobDecoding:  num_mb = %d\n", gob->num_mb);
    maxbits = BsDiff(start[1], start[0]);
    if (s->codingMethod == H263_CODING) {
        mb += gob->first_col + gob->first_row * gob->mb_offset;
        status = DecMbLayer263( &start[0], maxbits, gob, mb,
                                    (int)s->pic_layer.interFrame,
                                    (int)s->pic_layer.PBframeMode,
                                    (int)s->pic_layer.unrestrictedMv,
                                    (int)s->pic_layer.advancedIntraMode,
                                    sym, maxsym);
    } else {    // H.261
        status = decode261gob( &start[0], maxbits, gob, mb, sym, maxsym);
    }
    if (status != OK) {
        BS_ERR_MSG( H261ErrMsg( "Bitstream error in doGobDecoding" );)
    }
    return( status );
}


// gobConcealment - Conceal error and update error counters
static void gobConcealment( H261Decoder *s, GOB_DESCR *gob, MACROBLOCK_DESCR mb[] )
{
    BS_ERR_MSG( char msg[120]; ) /* Flawfinder: ignore */
    
    //printf("Calling ConcealGob \n");
    ConcealGob( gob, mb, s->pic_layer.reducedResUpdate, &s->oldOut, &s->newOut );
    if (s->pic_layer.PBframeMode && s->PBframeCap) {
        // Conceal B-frame
        ConcealGob( gob, mb, s->pic_layer.reducedResUpdate, &s->oldOut, &s->B_Out );
    }
    if (s->status.dwUpdateGobs == 0)   // If this is the first bad gob
    {
        s->status.dwFirstBadgob = s->next_gob;      // then save the number
        s->status.dwUpdateGobs = gob->num_mb/max(1,gob->mb_width);
    } else {
        s->status.dwUpdateGobs = s->next_gob + gob->num_mb / max(1,gob->mb_width) -
                                s->status.dwFirstBadgob;
    }
    ++s->status.dwBadgobs;
    s->status.dwIntraFrame=0;
    BS_ERR_MSG(
        sprintf( msg, "Bitstream error when decoding GOB %d", s->next_gob); /* Flawfinder: ignore */
        H261ErrMsg( msg ); )
}


//  build_gob_struct - set up GOB descriptor and MB descriptors for GOB "gn"
static int build_gob_struct( S32 format, S32 gn, GOB_DESCR * gob)
#define MB_COLS_PER_GOB     11
#define MB_ROWS_PER_GOB     3
{
    int mb_col, mb_row, row, col, index;

    if (gn < 1  ||  gn > 12  ||     // CIF: GN=1,2,..,12
        (format == 0  &&  gn != 1  &&  gn != 3  &&  gn != 5)) { // QCIF: 1,3,5
        return (H261_ERROR);
    }
    // Fill in GOB descriptor
    gob->num_mb = MB_COLS_PER_GOB * MB_ROWS_PER_GOB;
    gob->first_col = 0;
    gob->first_row = 0;
    gob->mb_width = MB_COLS_PER_GOB;
    gob->mb_offset = MB_COLS_PER_GOB;
    // Determine next GOB number
    if (format == 0  &&  gn < 5) {  // QCIF
        gob->next_gn = gn + 2;
    } else if (format != 0  &&  gn < 12) {  // CIF
        gob->next_gn = gn + 1;
    } else {    // This is last GOB in picture
        gob->next_gn = 0;   // Look for PSC next time
    }
    // Fill in macroblock locations
    if ((gn & 0x1)  ==  1) {
        mb_col = 0;                 // Odd GOBs on left side
    } else {
        mb_col = MB_COLS_PER_GOB;   // Even GOBs on right side
    }
    mb_row = ((gn - 1) / 2) * MB_ROWS_PER_GOB;
    for (row = 0; row < MB_ROWS_PER_GOB; row++) {
        for (col = 0; col < MB_COLS_PER_GOB; col++) {
            index = row * MB_COLS_PER_GOB + col;
            (gob->mb + index)->x = col + mb_col;
            (gob->mb + index)->y = row + mb_row;
        }
    }
    return (OK);
}


// build263gob - set up GOB and MB descriptors for GOBS "gn" to "next_gn-1" (H.263)
static int build263gob( S32 format, S32 gn, int next_gn, GOB_DESCR * gob,
                        PICTURE_DESCR * pic )
{
    int mbhor, mbvert, num_gn, row, col, index, mbRowsPerGob;

    switch (format) {
    case SQCIF:
        mbhor = 8;
        num_gn = 6;
        mbRowsPerGob = 1;
        break;
    case QCIF:
        mbhor = 11;
        num_gn = 9;
        mbRowsPerGob = 1;
        break;
    case CIF:
        mbhor = 22;
        num_gn = 18;
        mbRowsPerGob = 1;
        break;
    case CIF4:
        mbhor = 44;
        num_gn = 18;
        mbRowsPerGob = 2;
        break;
    case CIF16:
        mbhor = 88;
        num_gn = 18;
        mbRowsPerGob = 4;
        break;
    case ANYSIZE:
        mbhor = (pic->cols + 15) >> 4;
        num_gn = (pic->rows + 15) >> 4;
        mbRowsPerGob = 1;
        while (num_gn > GN_END_OF_SEQUENCE) {   // Max Group Number is 30
            mbRowsPerGob *= 2;
            num_gn = (num_gn + 1) >> 1;
        }
        break;
    default:
        return( H261_ERROR );
        break;
    }
#ifdef DO_H263_PLUS
    if (pic->reducedResUpdate) {
        // Use 32x32 macroblocks
        mbhor = ROUNDDIV2( mbhor );
        if (mbRowsPerGob == 1) {
            num_gn = ROUNDDIV2( num_gn );
        } else {
            mbRowsPerGob = ROUNDDIV2( mbRowsPerGob );
        }
    }
#endif
    if (gn < 0  ||  gn >= num_gn)  return( H261_ERROR );
    // Fill in GOB descriptor
    if (next_gn == 0  ||  next_gn == GN_END_OF_SEQUENCE) {
        gob->next_gn = 0;   // Look for PSC next time
        mbvert = num_gn - gn;
    } else {
        gob->next_gn = next_gn;
        mbvert = next_gn - gn;
    }
    mbvert *= mbRowsPerGob;
    if (mbvert <= 0)  return( H261_ERROR );
    gob->num_mb = mbhor * mbvert;
    gob->first_col = 0;
    gob->first_row = gn * mbRowsPerGob; // Need previous row for advancedPred mode
    gob->mb_width = mbhor;
    gob->mb_offset = mbhor;
    // Fill in macroblock locations
    for (row = gn * mbRowsPerGob; row < gn * mbRowsPerGob + mbvert; row++) {
        for (col = 0; col < mbhor; col++) {
            index = row * mbhor + col;
            gob->mb[index].x = col;
            gob->mb[index].y = row;
        }
    }
    return (OK);
}

/*********************
//  update_decMB - Update macroblock map by ORing MTYPE for each MB
static void update_decMB( GOB_DESCR * gob, MACROBLOCK_DESCR mb[], int mb_per_row, 
                        int codingMethod, MBMap * decMB, S32 * iFrame, int forcedUpdate )
{
    int mbnum, i, row, col;
    U8  mtype;
    
    if (codingMethod == H263_CODING) {
        mbnum = gob->first_col + gob->first_row * gob->mb_offset;
        for (i = mbnum; i < mbnum + gob->num_mb; ++i) {
            mtype = mb[i].mtype;
            decMB->data[i] |= mtype;
            if ( mtype != MTYPE263_INTRA  &&  mtype != MTYPE263_INTRA_Q )  *iFrame = 0;
        } 
        if (forcedUpdate == YES) {  // Ensure that macroblock map is non-zero
            for (i = mbnum; i < mbnum + gob->num_mb; ++i) {
                decMB->data[i] = 1;
            } 
        }
    } else {    // H.261
        mbnum = mb[0].x + mb[0].y * mb_per_row;
        i = 0;
        for (row = 0; row < MB_ROWS_PER_GOB; row++) {
            for (col = 0; col < MB_COLS_PER_GOB; col++) {
                mtype = mb[i + col].mtype;
                decMB->data[mbnum + col] |= mtype;
                if ( mtype != MTYPE_INTRA  &&  mtype != MTYPE_INTRA_MQUANT )  *iFrame = 0;
            }
            mbnum += mb_per_row;
            i += MB_COLS_PER_GOB;
        } 
        if (forcedUpdate == YES) {  // Ensure that macroblock map is non-zero
            mbnum = mb[0].x + mb[0].y * mb_per_row;
            for (row = 0; row < MB_ROWS_PER_GOB; row++) {
                for (col = 0; col < MB_COLS_PER_GOB; col++) {
                    decMB->data[mbnum + col] = 1;
                }
                mbnum += mb_per_row;
            } 
        }
    }

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?