h261dec.c
上传用户:dangjiwu
上传日期:2013-07-19
资源大小:42019k
文件大小:63k
- /* ***** BEGIN LICENSE BLOCK *****
- * Source last modified: $Id: h261dec.c,v 1.3.34.1 2004/07/09 01:56:22 hubbe Exp $
- *
- * Portions Copyright (c) 1995-2004 RealNetworks, Inc. All Rights Reserved.
- *
- * The contents of this file, and the files included with this file,
- * are subject to the current version of the RealNetworks Public
- * Source License (the "RPSL") available at
- * http://www.helixcommunity.org/content/rpsl unless you have licensed
- * the file under the current version of the RealNetworks Community
- * Source License (the "RCSL") available at
- * http://www.helixcommunity.org/content/rcsl, in which case the RCSL
- * will apply. You may also obtain the license terms directly from
- * RealNetworks. You may not use this file except in compliance with
- * the RPSL or, if you have a valid RCSL with RealNetworks applicable
- * to this file, the RCSL. Please see the applicable RPSL or RCSL for
- * the rights, obligations and limitations governing use of the
- * contents of the file.
- *
- * Alternatively, the contents of this file may be used under the
- * terms of the GNU General Public License Version 2 or later (the
- * "GPL") in which case the provisions of the GPL are applicable
- * instead of those above. If you wish to allow use of your version of
- * this file only under the terms of the GPL, and not to allow others
- * to use your version of this file under the terms of either the RPSL
- * or RCSL, indicate your decision by deleting the provisions above
- * and replace them with the notice and other provisions required by
- * the GPL. If you do not delete the provisions above, a recipient may
- * use your version of this file under the terms of any one of the
- * RPSL, the RCSL or the GPL.
- *
- * This file is part of the Helix DNA Technology. RealNetworks is the
- * developer of the Original Code and owns the copyrights in the
- * portions it created.
- *
- * This file, and the files included with this file, is distributed
- * and made available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY
- * KIND, EITHER EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS
- * ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES
- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET
- * ENJOYMENT OR NON-INFRINGEMENT.
- *
- * Technology Compatibility Kit Test Suite(s) Location:
- * http://www.helixcommunity.org/content/tck
- *
- * Contributor(s):
- *
- * ***** END LICENSE BLOCK ***** */
- #include "hxtypes.h"
- #include "dllindex.h"
- #include "h261defs.h"
- #include "vldstate.h"
- #include "h261func.h"
- #include "hvscodes.h" /* getImgParms can be called */
- #include "dec_blk.h" /* set the proper pragmas for decode_block */
- #include "vldecode.h" /* set the proper pragmas for VLDecode */
- #include "h263plus.h"
- //#define ANNOTATE_PICTURE // Include diagnostic info in output picture
- #ifdef TESTING
- #include <stdio.h>
- #include <stdlib.h>
- #define BS_ERR_MSG(a) a // Generate messages on bitstream error (i.e., illegal
- // bitstream syntax) to simplify debugging
- #define CHECKSYM(a) a // Check symbol types to verify decoder state tables
- #else
- #define BS_ERR_MSG(a) // Suppress error messages
- #define CHECKSYM(a) // Don't check symbol types
- #endif
- // Declarations of local functions
- static int findPSC( BS_PTR start[], int gn[], int num_sc, int *sc, H261Decoder *s );
- static void savePSCpointer( BS_PTR *bsPSC, H261Decoder *s );
- static void outputBsPointer( BS_PTR * start, BS_PTR * output, int codingMethod );
- static int decodeBitstream( H261Decoder *s,
- GOB_DESCR *gob,
- BS_PTR start[2],
- int gn[2],
- int *structStatus,
- int *decStatus );
- static int doGobStructures( H261Decoder *s, GOB_DESCR *gob, MACROBLOCK_DESCR mb[],
- BS_PTR start[2], int gn[2] );
- static int doGobDecoding( H261Decoder *s, GOB_DESCR *gob, MACROBLOCK_DESCR mb[],
- BS_PTR start[2], SYMBOL sym[], int maxsym );
- static void gobConcealment( H261Decoder *s, GOB_DESCR *gob, MACROBLOCK_DESCR mb[] );
- static int build_gob_struct( S32 format, S32 gn, GOB_DESCR * gob);
- static int build263gob( S32 format, S32 gn, int next_gn, GOB_DESCR * gob,
- PICTURE_DESCR * pic );
- /*static void update_decMB( GOB_DESCR * gob, MACROBLOCK_DESCR mb[], int mb_per_row,
- int codingMethod, MBMap * decMB, S32 * iFrame, int forcedUpdate );*/
- static int initializePicture( H261Decoder * s );
- static int decodePicLayer( BS_PTR * bs, int nbits, PICTURE_DESCR * pic,
- SYMBOL sym[], int maxsym, int codingMethod, GOB_DESCR * gob,
- int * ptype );
- static int decode_pic261( BS_PTR * bs, int nbits, PICTURE_DESCR * pic,
- SYMBOL sym[], int maxsym);
- static int decode261gob( BS_PTR * bs, int nbits, GOB_DESCR * gob,
- MACROBLOCK_DESCR mb[], SYMBOL sym[], int maxsym);
- static int decode_mb( SYMBOL insym[], int * nextsym, int * quant,
- GOB_DESCR * gob, MACROBLOCK_DESCR mb[], int mbnum,
- SYMBOL outsym[]);
- static int decode_intra_block( SYMBOL insym[], int * nextsym,
- BLOCK_DESCR * block, SYMBOL outsym[]);
- 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
- 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
- #ifdef ANNOTATE_PICTURE
- // saveOrRestoreReconPicture
- static void saveOrRestoreReconPicture( PICTURE *pic, // Picture to be saved or restored
- int restore // Save if 0, otherwise restore
- );
- // annotatePicture - Draw motion vectors etc.
- static void annotatePicture( PICTURE *pic, MACROBLOCK_DESCR mb[]);
- // annotateMacroblock
- static void annotateMacroblock( PIXEL data[], int xdim, MACROBLOCK_DESCR *mb,
- int xMin, int xMax, int yMin, int yMax );
- static void drawMv( PIXEL data[], int xdim, int mvX, int mvY,
- int xMin, int xMax, int yMin, int yMax );
- static void plusMb( PIXEL data[], int xdim );
- static void crossMb( PIXEL data[], int xdim );
- static void fillMb( PIXEL data[], int xdim );
- static void markPixel( PIXEL *pixel );
- static int DrawVector( unsigned char data[], int xdim, int x1, int y1, int x2, int y2 );
- static int drawVec( unsigned char data[], int xdim, int x1, int y1 );
- #endif
- #define GN_END_OF_SEQUENCE (31) // GN=31 for EOS
- #define H263_START_ZEROS (16)
- #define H263_GN_BITS (5)
- #define H261_START_ZEROS (15)
- #define H261_GN_BITS (4)
- //
- //
- // ****************************************************
- // H261Decode - Decode one or several GOBs in a picture
- // ****************************************************
- //
- //
- extern int H261Decode( H261Decoder * s )
- #define NUM_SC 0
- #define NUMGOB 1
- #define ERRGOB 2
- #define IFRAME 3
- {
- BS_PTR *pStart; // Position of startcodes ("start")
- int *pGn; // GOB numbers following each startcode ("gn")
- GOB_DESCR *pGob; // Can refer to several GOBs, if GOB headers are left out ("gob")
- int *pNum_sc; // Points to number of startcodes found ("num_sc")
- int *pSc; // Points to current startcode ("sc")
- BS_PTR bsPSC;
- int status, structStatus, decStatus;
- BS_ERR_MSG(char msg[120];) /* Flawfinder: ignore */
- s->state.actComp = 0; // Init computation measure
- pStart = s->state.bspStartCode;
- pGn = s->state.gobNumber;
- pGob = &s->state.currentGob;
- pNum_sc = &s->state.nStartCodes;
- pSc = &s->state.currentStartCode;
- if (s->pic_layer.decodingInProgress) {
- // Restore internal state; we interrupted reconstruction with status=OK
- structStatus = decStatus = OK;
- s->pic_layer.decodingInProgress = FALSE; // Set only if we time out again
- } else { // We did not time out last time, so do the usual thing
- s->state.i = 0; // Tell ReconGob to reset its state
- /* Find Picture and GOB Start Codes */
- *pNum_sc = find_startcodes( &s->bsStart, BsDiff(s->bsEnd, s->bsStart),
- pStart, pGn, SC_MAX, (int)s->codingMethod );
- /*{ // Print startcode positions
- int i;
- for (i = 0; i < *pNum_sc; i++) {
- printf("Startcode %d: gn = %d starts in byte %d, bit %dn", i,
- pGn[i], pStart[i].byteptr - s->bsStart.byteptr, pStart[i].bitptr);
- }
- printf("Continue? ");
- scanf("%d", &i);
- }*/
- s->status.dwStartcodes = *pNum_sc;
- s->status.dwGobs = 0; // # GOBs processed
- s->status.dwBadgobs = 0; // # erroneous GOBs
- s->status.dwUpdateGobs = 0; // # GOBs for fast updating
- s->status.dwFirstBadgob = 0; // First bad Gob
- s->status.dwPsc = FALSE; // indicates that a picture layer was successfully decoded
- s->newBs = s->bsStart; // Just in case... (will be updated later)
- if (*pNum_sc < 2) {
- if (*pNum_sc == 1) {
- outputBsPointer( &pStart[0], &s->newBs, (int)s->codingMethod ); // If we exit, begin here next time
- } else if ((s->bsEnd.byteptr - s->bsStart.byteptr) < 4) {
- // No startcode found and bitstream is less than 4 bytes long
- s->newBs = s->bsStart;
- } else {
- // No startcode found; skip to end of bitstream
- s->newBs = s->bsEnd;
- s->newBs.byteptr -= 4; // Back up 32 bits (22-bit PSC and one byte margin)
- }
- return( NO );
- }
- *pSc = 0;
- if (s->next_gob == 0) { // Decode Picture Layer info
- do {
- if (findPSC( pStart, pGn, *pNum_sc, pSc, s ) != YES) // Find Picture Start Code
- return( NO );
- // Try to decode Picture Layer
- outputBsPointer( &pStart[*pSc], &bsPSC, (int)s->codingMethod ); // Save possible picture start code pointer
- status = decodePicLayer( &pStart[*pSc], BsDiff(pStart[*pSc + 1], pStart[*pSc]),
- &s->pic_layer, s->sym, s->maxSym, (int)s->codingMethod, pGob,
- &s->ptype );
- // H.263: pStart[*pSc] gets bumped by decodePicLayer; now pointing to MB layer
- if (status != OK) {
- ++s->status.dwBadgobs;
- BS_ERR_MSG( H261ErrMsg( "Bitstream error when decoding Picture Layer" ); )
- } else { // Decoded Picture Layer successfully
- savePSCpointer( &bsPSC, s );
- // Initialize image structures according to received image format: QCIF or CIF
- status = initializePicture ( s );
- if (status != OK) H261ErrMsg("Decoder: illegal picture format");
- s->status.dwIntraFrame = 1; // Assume intraframe (set to zero if we encounter a non-INTRA MacroBlock)
- #ifdef ANNOTATE_PICTURE
- saveOrRestoreReconPicture( &s->oldOut, 1 ); // Restore prev. from local memory
- #endif
- if (s->codingMethod == H263_CODING && status == OK) {
- s->next_gob = 0; // First GOB is gn=0 for H.263
- break; // Don't increment *pSc; decode GOB 0 first
- } else if (status == OK) { // H.261 decoding
- s->next_gob = 1; // Go on to decode first GOB (gn=1 for H.261)
- }
- }
- ++(*pSc);
- } while (status != OK);
- }
-
- // Decode GOBs until we reach next to last startcode or until picture complete
- if (*pSc >= *pNum_sc - 1) return NO;
- // Decode bitstream for the first GOB
- status = decodeBitstream( s, pGob, &pStart[*pSc], &pGn[*pSc], &structStatus, &decStatus );
- if (status == H261_ERROR) return NO; // Exit to resync on next PSC
- } // end if !s->pic_layer.decodingInProgress
- while (1) { // Process until next to last startcode
- // Reconstruct GOB
- if (structStatus == OK) {
- // decStatus!=OK means that we found bitstream errors
- if (decStatus == OK) {
- //printf("Calling ReconGob n");
- ReconGob( pGob, s->mb, &s->oldOut, &s->newOut, &s->B_Out,
- s->pic_layer.advancedPred, s->pic_layer.PBframeMode,
- s->PBframeCap, s->pic_layer.reducedResUpdate, s->pic_layer.advancedIntraMode,
- &s->state, s->maxComp );
- // Time to exit?
- if (s->state.i > 0) { // ReconGob timed out
- s->pic_layer.decodingInProgress = TRUE;
- return NO;
- }
- /*// Update macroblock map to control RGB conversion
- // This is not very useful anymore; skipped blocks might change when
- // we use overlapped MC or deblocking filter /SE 4/4/97
- update_decMB( pGob, pGob->mb, (int)(s->newOut.y.nhor >> 4),
- (int)s->codingMethod, &s->decMB,
- &s->status.dwIntraFrame, NO );*/
- } else { // Bitstream error
- gobConcealment( s, pGob, s->mb );
- }
- s->status.dwGobs += pGob->num_mb / max(1,pGob->mb_width);
- s->next_gob = pGob->next_gn;
- }
- (*pSc)++;
- outputBsPointer( &pStart[*pSc], &s->newBs, (int)s->codingMethod ); // If we exit, begin here next time
- if (s->next_gob == 0) { // Completed picture
- #ifdef DO_H263_PLUS
- // Perform deblocking filtering
- if(s->pic_layer.reducedResUpdate) {
- ReducedResDeblockingFilter( &s->newOut, s->mb );
- } else if(s->pic_layer.deblockingFilterMode) {
- ApplyDeblockingFilter(&s->newOut, s->mb, FALSE);
- if(s->pic_layer.PBframeMode && s->PBframeCap)
- ApplyDeblockingFilter(&s->B_Out, s->mb, TRUE);
- }
- #endif
- //checkPicture( s->newOut ); // Very useful when chasing subtle encoder bugs
- #ifdef ANNOTATE_PICTURE
- saveOrRestoreReconPicture( &s->newOut, 0 ); // Save new picture to local memory
- annotatePicture( &s->newOut, s->mb ); // Draw motion vectors etc.
- annotatePicture( &s->B_Out, s->mb );
- #endif
- return (YES);
- }
- if (*pSc >= *pNum_sc - 1) return NO;
- // Decode bitstream for the next GOB
- status = decodeBitstream( s, pGob, &pStart[*pSc], &pGn[*pSc],
- &structStatus, &decStatus );
- if (status == H261_ERROR) return NO; // Exit to resync on next PSC
- }
- }
- // findPSC - Search for Picture Start Code
- static int findPSC( BS_PTR start[], int gn[], int num_sc, int *sc, H261Decoder *s )
- {
- do {
- if (*sc > num_sc - 2) { // Reached last startcode?
- return (NO);
- }
- (*sc)++;
- outputBsPointer( &start[*sc], &s->newBs, (int)s->codingMethod ); // If we exit, begin here next time
- } while (gn[*sc - 1] != 0); // GN=0 indicates PSC
- *sc = *sc - 1; // Back up to point at PSC
- return( YES );
- }
- // 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 %dn", 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 = %dn", 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;
- }
- }
- }
- return;
- }
- *****************/
- /**************************************************************************
- * initializePicture ( H261Decoder *s) -
- *
- * this function initializes the picture structures according to the
- * format: QCIF or CIF
- *
- ***************************************************************************/
- #ifdef WATD
- extern void BreakPoint(void);
- #pragma aux BreakPoint = 0xcc;
- #endif
- static int initializePicture( H261Decoder * s )
- {
- S16 format; /* locals used for call to getImgParms */
- S16 numGOBs; /* this is done for consistency with */
- S16 numMBs; /* old init method */
- S32 imgSize ;
- S32 lumaSize;
- S32 chromaLineLength;
- S32 chromaRows;
- S32 maxsym;
- int status, mbHor, mbVert;
- #ifdef WATD
- //BreakPoint();
- #endif
- format = (S16)s->pic_layer.format;
- s->decMB.format = format;
- s->decMB.type = DECODER_MAP;
-
- if ( (s->formatCap == QCIF) && (format == CIF) )
- H261ErrMsg("decoder not CIF capable");
- /* get the image parameters for the current format */
- if (format == ANYSIZE) {
- mbHor = (s->pic_layer.cols + 15) >> 4;
- mbVert = (s->pic_layer.rows + 15) >> 4;
- //imgSize = (long)384 * mbHor * mbVert;
- lumaSize = (long)256 * mbHor * mbVert;
- chromaLineLength = 8 * mbHor;
- chromaRows = 8 * mbVert;
- //numGOBs = mbVert;
- numMBs = mbHor * mbVert;
- //maxsym = 8 * lumaSize;
- status = 0;
- /////////if (numMBs > xxxxx) status = UNKNOWN_PICTURE_FORMAT;
- } else {
- status = getImgParms (format, &numGOBs, &numMBs, &imgSize, &lumaSize, &chromaLineLength,
- &chromaRows, &maxsym);
- }
- if (status != 0) {
- H261ErrMsg ("Decoder Error: initializePicture - UNKNOWN_PICTURE_FORMAT");
- status = H261_ERROR;
- } else if (numMBs > s->maxMbnum) {
- H261ErrMsg ("Decoder Error: initializePicture - Too large picture");
- status = H261_ERROR;
- } else if (numMBs > s->maxMbnum) {
- H261ErrMsg ("Decoder Error: initializePicture - Too large picture");
- status = H261_ERROR;
- } else {
- status = OK;
- }
- // setup the image structures
- //s->newOut.picLayout = s->B_Out.picLayout = VVS_LAYOUT_TEE;
- //s->oldOut.picLayout = VVS_LAYOUT_TEE;
- s->newOut.picLayout = s->B_Out.picLayout = VVS_LAYOUT_YUV12;
-
- // Memory was already allocated when the decoder first opened.
- // The luma pointers hold the address of the start of the memory for image buffers
-
- // Set up chroma pointers
- // helix needs 420 out -gneel
- // Layout_Tee also works.
- if(s->newOut.picLayout == VVS_LAYOUT_YUV12)
- {
- s->newOut.cb.ptr = s->newOut.y.ptr + lumaSize;
- s->B_Out.cb.ptr = s->B_Out.y.ptr + lumaSize;
- s->newOut.cr.ptr = s->newOut.cb.ptr + (lumaSize>>2);
- s->B_Out.cr.ptr = s->B_Out.cb.ptr + (lumaSize>>2);
- s->newOut.cb.ptrAlias = s->newOut.y.ptrAlias + lumaSize;
- s->B_Out.cb.ptrAlias = s->B_Out.y.ptrAlias + lumaSize;
-
- s->newOut.cr.ptrAlias = s->newOut.cb.ptrAlias + (lumaSize>>2);
- s->B_Out.cr.ptrAlias = s->B_Out.cb.ptrAlias + (lumaSize>>2);
- // Set up remainder of COMPONENT structs
- s->newOut.y.nhor = s->B_Out.y.nhor = chromaLineLength * 2;
- s->newOut.y.nvert = s->B_Out.y.nvert = chromaRows * 2;
- s->newOut.y.hoffset = s->B_Out.y.hoffset = chromaLineLength * 2;
- s->newOut.cb.nhor = s->B_Out.cb.nhor = chromaLineLength;
- s->newOut.cb.nvert = s->B_Out.cb.nvert = chromaRows;
- s->newOut.cb.hoffset = s->B_Out.cb.hoffset = chromaLineLength;
- s->newOut.cr.nhor = s->B_Out.cr.nhor = chromaLineLength;
- s->newOut.cr.nvert = s->B_Out.cr.nvert = chromaRows;
- s->newOut.cr.hoffset = s->B_Out.cr.hoffset = chromaLineLength;
- } else {
- s->newOut.cb.ptr = s->newOut.y.ptr + lumaSize;
- s->B_Out.cb.ptr = s->B_Out.y.ptr + lumaSize;
- //s->oldOut.cb.ptr = s->oldOut.y.ptr + lumaSize;
-
- s->newOut.cr.ptr = s->newOut.cb.ptr + chromaLineLength;
- s->B_Out.cr.ptr = s->B_Out.cb.ptr + chromaLineLength;
- //s->oldOut.cr.ptr = s->oldOut.cb.ptr + chromaLineLength;
- s->newOut.cb.ptrAlias = s->newOut.y.ptrAlias + lumaSize;
- s->B_Out.cb.ptrAlias = s->B_Out.y.ptrAlias + lumaSize;
- //s->oldOut.cb.ptrAlias = s->oldOut.y.ptrAlias + lumaSize;
- s->newOut.cr.ptrAlias = s->newOut.cb.ptrAlias + chromaLineLength;
- s->B_Out.cr.ptrAlias = s->B_Out.cb.ptrAlias + chromaLineLength;
- //s->oldOut.cr.ptrAlias = s->oldOut.cb.ptrAlias + chromaLineLength;
- // Set up remainder of COMPONENT structs
- s->newOut.y.nhor = s->B_Out.y.nhor = chromaLineLength * 2;
- s->newOut.y.nvert = s->B_Out.y.nvert = chromaRows * 2;
- s->newOut.y.hoffset = s->B_Out.y.hoffset = chromaLineLength * 2;
- s->newOut.cb.nhor = s->B_Out.cb.nhor = chromaLineLength;
- s->newOut.cb.nvert = s->B_Out.cb.nvert = chromaRows;
- s->newOut.cb.hoffset = s->B_Out.cb.hoffset = chromaLineLength * 2;
- s->newOut.cr.nhor = s->B_Out.cr.nhor = chromaLineLength;
- s->newOut.cr.nvert = s->B_Out.cr.nvert = chromaRows;
- s->newOut.cr.hoffset = s->B_Out.cr.hoffset = chromaLineLength * 2;
- }
- return (status);
- }
- // decodePicLayer - Decode Picture Layer information
- static int decodePicLayer( BS_PTR * bs, int nbits, PICTURE_DESCR * pic,
- SYMBOL sym[], int maxsym, int codingMethod, GOB_DESCR * gob,
- int * ptype )
- {
- int status;
-
- if (codingMethod == H263_CODING) {
- status = DecPicLayer263( bs, nbits, pic, gob, ptype );
- } else {
- status = decode_pic261( bs, nbits, pic, sym, maxsym );
- }
- return( status );
- }
- // decode_pic261 - Decode H.261 Picture Layer information
- // This routine is very picky when determining whether bitstream is valid.
- // It returns OK only if a startcode ends the bitstream; otherwise, it
- // returns H261_ERROR.
- static int decode_pic261( BS_PTR * bs, int nbits, PICTURE_DESCR * pic,
- SYMBOL sym[], int maxsym)
- {
- int state, status, parsed_bits, nsym, i;
- BS_ERR_MSG( char msg[120] ); /* Flawfinder: ignore */
- state = ST_AFTER_STARTCODE;
- //printf( "DecodePic: Entering VLDecode with State = %d nbits = %dn",
- // state, nbits);
- status = VLDECODE( *bs, nbits, &state, &parsed_bits, &nsym, sym, maxsym);
- if (parsed_bits != nbits) {
- BS_ERR_MSG( sprintf( msg, "decode_pic_layer: Tried to decode %d bits, exit after %d bits", /* Flawfinder: ignore */
- nbits, parsed_bits);
- H261ErrMsg( msg ); )
- return (H261_ERROR);
- }
- if (state != ST_AFTER_STARTCODE) {
- BS_ERR_MSG( sprintf( msg, "decode_pic_layer: Bitstream did not end with startcode"); /* Flawfinder: ignore */
- H261ErrMsg( msg); )
- return (H261_ERROR);
- }
- /* {
- int i;
- printf( "DecodePic: Status = %d State = %d Decoded %d bits, %d symbolsn",
- status, state, parsed_bits, nsym);
- // Print decoded symbols
- printf("n");
- for (i = 0; i < nsym; i++) {
- printf("DecodePic: "); printsym( sym[i] ); printf("n");
- }
- printf("n");
- }*/
- CHECKSYM( if (checksym( sym[0], SYM_GN, "decode_pic_layer") != OK) exit(0); )
- i = 1; // Skip first symbol ("GN" = 0)
- CHECKSYM( if (checksym( sym[i], SYM_QUANT_TR, "decode_pic_layer") != OK) exit(0); )
- pic->tr = sym[i++].value;
- CHECKSYM( if (checksym( sym[i], SYM_PTYPE, "decode_pic_layer") != OK) exit(0); )
- pic->ptype = sym[i++].value;
- pic->splitscreen = pic->ptype & FLAG_SPLITSCREEN;
- pic->doccamera = pic->ptype & FLAG_DOCCAMERA;
- pic->fp_release = pic->ptype & FLAG_FP_RELEASE;
- if (pic->ptype & FLAG_CIF_FORMAT) {
- pic->format = CIF;
- } else {
- pic->format = QCIF;
- }
- pic->hi_res = (pic->ptype & FLAG_HI_RES) ^ FLAG_HI_RES; // 1 = off, 0 = on
- pic->advancedPred = 0; // No overlapped MC for H.261
- pic->PBframeMode = 0; // No PB-frames for H.261
- #ifdef DO_H263_PLUS
- pic->reducedResUpdate = 0;
- #endif
- pic->peiCount = 0; // Loop 'til PEI=0
- while (sym[i].type == SYM_SPARE) {
- //char msg[100];
- //sprintf(msg,"n Decode DLL: PEI=%x", sym[i].value);
- //OutputDebugString(msg);
- if (pic->peiCount < MAX_PEI_COUNT) {
- //char msg[100];
- //sprintf(msg,"n Decode DLL: pSpare: %2x", sym[i].value);
- //OutputDebugString(msg);
- pic->pSpare[pic->peiCount] = sym[i].value;
- }
- pic->peiCount++; // Inc counter
- i++; // Next Symbol
- }
- CHECKSYM( if (checksym( sym[i], SYM_GEI_PEI, "decode_pic_layer") != OK) exit(0));
- i++; // Skip PEI Symbol
-
- if (sym[i].type != SYM_STARTCODE) {
- BS_ERR_MSG( sprintf( msg, "decode_pic_layer: Did not find startcode after pic_layer"); /* Flawfinder: ignore */
- H261ErrMsg( msg ); )
- return (H261_ERROR);
- }
- return (OK);
- }
- // decode261gob - Decode all symbols for a Group Of Blocks
- // This routine is very picky when determining whether bitstream is valid.
- // It returns OK only if a startcode ends the bitstream; otherwise, it
- // returns H261_ERROR.
- static int decode261gob( BS_PTR * bs, int nbits, GOB_DESCR * gob,
- MACROBLOCK_DESCR mb[], SYMBOL sym[], int maxsym)
- {
- int state, status, parsed_bits, mbnum, nextsym, quant, i, mba,
- nsym, // # symbols returned by VLDecode
- isym; // # symbols returned by this routine, i.e.,
- // after deletion of EOBs etc.
- BS_ERR_MSG ( char msg[120] ); /* Flawfinder: ignore */
- state = ST_AFTER_STARTCODE;
- //printf( "DecodeGOB: Entering VLDecode with State: ");
- //printstate( state ); printf(" nbits = %dn", nbits);
- status = VLDECODE( *bs, nbits, &state, &parsed_bits, &nsym, sym, maxsym);
- if (parsed_bits != nbits) {
- BS_ERR_MSG( sprintf( msg, "decode261gob: Tried to decode %d bits, exit after %d bits", /* Flawfinder: ignore */
- nbits, parsed_bits);
- H261ErrMsg( msg ); )
- return (H261_ERROR);
- }
- if (state != ST_AFTER_STARTCODE) {
- BS_ERR_MSG( sprintf( msg, "decode261gob: Bitstream did not end with startcode"); /* Flawfinder: ignore */
- H261ErrMsg( msg ); )
- return (H261_ERROR);
- }
- /* {
- int num;
- printf( "DecodeGOB: Status = %d State: ", status); printstate( state );
- printf(" Decoded %d bits, %d symbolsn", parsed_bits, nsym);
- // Print decoded symbols
- printf("DecodeGOB: # symbols to print: ");
- scanf("%d", &num);
- for (i = 0; i < num; i++) {
- printf("DecodeGOB: "); printsym( sym[i] ); printf("n");
- }
- printf("n");
- }
- */
- nextsym = 0;
- CHECKSYM( if (checksym( sym[nextsym], SYM_GN, "decode261gob") != OK) exit(0); )
- gob->gn = sym[nextsym++].value; // GOB number
- CHECKSYM( if (checksym( sym[nextsym], SYM_QUANT_TR, "decode261gob") != OK) exit(0); )
- quant = sym[nextsym++].value;
- if (quant < QUANT_MIN || quant > QUANT_MAX) {
- BS_ERR_MSG( sprintf( msg, "decode261gob: quant = %d", quant); /* Flawfinder: ignore */
- H261ErrMsg( msg ); )
- return (H261_ERROR);
- }
- gob->gquant = quant;
- //CHECKSYM( if (checksym( sym[nextsym], SYM_GEI_PEI, "decode261gob") != OK) exit(0); )
- //gob->gei = sym[nextsym].value;
- gob->num_gspare = 0;
- while (sym[nextsym].type == SYM_SPARE) { // Loop until GEI=0
- CHECKSYM( if (checksym( sym[nextsym], SYM_SPARE, "decode261gob") != OK) exit(0); )
- ++nextsym; // Drop GSPARE on the floor
- ++(gob->num_gspare);
-
- }
- CHECKSYM( if (checksym( sym[nextsym], SYM_GEI_PEI, "decode261gob") != OK) exit(0); )
- ++nextsym; // Skip GEI
-
-
- mbnum = 0;
- isym = 0;
- // We expect MBA, MBA Stuffing, or Startcode
- while (sym[nextsym].type == SYM_MBA_STUFFING) {
- ++nextsym; // Remove MBA stuffing
- }
- while (sym[nextsym].type != SYM_STARTCODE) { // Keep going until next startcode
- // We expect MBA
- CHECKSYM( if (checksym( sym[nextsym], SYM_MBA, "decode261gob") != OK) exit(0); )
- mba = sym[nextsym++].value;
- //printf("MB #%d: ", mbnum+mba); printsym( sym[nextsym-1] ); // MBA
- //printf(" "); printsym( sym[nextsym] ); printf("n"); // MTYPE
- if (mbnum + mba > gob->num_mb) {
- BS_ERR_MSG( sprintf( msg, "decode261gob: Bitstream error, mbnum=%d", mbnum + mba); /* Flawfinder: ignore */
- H261ErrMsg( msg ); )
- return (H261_ERROR);
- }
- for (i = mbnum + 1; i < mbnum + mba; i++) {
- mb[i-1].mtype = MTYPE_SKIP;
- }
- mbnum += mba;
- status = decode_mb( sym, &nextsym, &quant, gob, mb, mbnum-1, &sym[isym] );
- if (status == H261_ERROR) {
- BS_ERR_MSG( sprintf( msg, "decode261gob: Bitstream error, MB #%d", mbnum); /* Flawfinder: ignore */
- H261ErrMsg( msg ); )
- return (H261_ERROR);
- }
- 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 = %dn", 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 = %dn", 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 );
- return (H261_ERROR);
- }
- }
- #endif // TESTING
- #ifdef ANNOTATE_PICTURE
- // saveOrRestoreReconPicture
- static void saveOrRestoreReconPicture( PICTURE *pic, // Picture to be saved or restored
- int restore // Save if 0, otherwise restore
- )
- {
- #define MAX_BYTES ((176*144*3)/2)
- int nBytes;
- static PIXEL savePic[MAX_BYTES];
-
- nBytes = (pic->y.nhor * pic->y.nvert * 3) >> 1;
- // Packed format is assumed
- if (nBytes > MAX_BYTES) {
- H261ErrMsg("Error in saveOrRestoreReconPicturen");
- exit(0);
- } else if (restore) { // Restore the saved picture
- memcpy( pic->y.ptr, savePic, nBytes ); /* Flawfinder: ignore */
- } else { // Save picture for next decoding
- memcpy( savePic, pic->y.ptr, nBytes ); /* Flawfinder: ignore */
- }
- }
- // annotatePicture - Draw motion vectors etc.
- static void annotatePicture( PICTURE *pic, MACROBLOCK_DESCR mb[])
- {
- int xSize, ySize, numMb, i, x, y;
- PIXEL *upperLeft;
-
- xSize = pic->y.nhor;
- ySize = pic->y.nvert;
- numMb = (xSize * ySize) >> 8;
- for (i = 0; i < numMb; ++i) {
- x = 16 * mb[i].x;
- y = 16 * mb[i].y;
- upperLeft = pic->y.ptr + x + y * pic->y.hoffset;
- annotateMacroblock( upperLeft, pic->y.hoffset, &mb[i],
- -x, xSize - 1 - x,
- -y, ySize - 1 - y );
- }
- }
- #define WHITE (255)
- #define BLACK (0)
- #define BLACK_THRESHOLD (192) // Paint with black if pixel is brighter than threshold
- // Limit x to interval [low,high]
- #define LIMIT( low, x, high ) max( low, min( x, high ))
- // annotateMacroblock
- static void annotateMacroblock( PIXEL data[], int xdim, MACROBLOCK_DESCR *mb,
- int xMin, int xMax, int yMin, int yMax )
- {
- switch (mb->mtype)
- {
- case MTYPE_SKIP:
- // Do nothing
- break;
- case MTYPE263_INTER:
- case MTYPE263_INTER_Q:
- // Draw motion vector
- drawMv( &data[7 + 7 * xdim], xdim, mb->mv_x, mb->mv_y,
- xMin-7, xMax-7, yMin-7, yMax-7 );
- break;
- case MTYPE263_INTER4V:
- // Draw a "plus"
- plusMb( data, xdim );
- // Draw 4 motion vectors
- drawMv( &data[3 + 3 * xdim], xdim, mb->blkMvX[0], mb->blkMvY[0],
- xMin-3, xMax-3, yMin-3, yMax-3 );
- drawMv( &data[11 + 3 * xdim], xdim, mb->blkMvX[1], mb->blkMvY[1],
- xMin-11, xMax-11, yMin-3, yMax-3 );
- drawMv( &data[3 + 11 * xdim], xdim, mb->blkMvX[2], mb->blkMvY[2],
- xMin-3, xMax-3, yMin-11, yMax-11 );
- drawMv( &data[11 + 11 * xdim], xdim, mb->blkMvX[3], mb->blkMvY[3],
- xMin-11, xMax-11, yMin-11, yMax-11 );
- break;
- case MTYPE263_INTRA:
- case MTYPE263_INTRA_Q:
- // Draw motion vector and mark block with a cross
- drawMv( &data[7 + 7 * xdim], xdim, mb->mv_x, mb->mv_y,
- xMin-7, xMax-7, yMin-7, yMax-7 );
- crossMb( data, xdim );
- break;
- default:
- // Fill block with white
- fillMb( data, xdim );
- break;
- }
- }
- // drawMv - Draw motion vector starting in (0,0)
- static void drawMv( PIXEL data[], int xdim, int mvX, int mvY,
- int xMin, int xMax, int yMin, int yMax )
- {
- if (mvX == 0 && mvY == 0) {
- // Draw a circle
- markPixel( &data[-xdim] );
- markPixel( &data[-xdim + 1] );
- markPixel( &data[-1] );
- markPixel( &data[2] );
- markPixel( &data[xdim - 1] );
- markPixel( &data[xdim + 2] );
- markPixel( &data[2*xdim] );
- markPixel( &data[2*xdim+1] );
- } else { // Draw motion vector
- // Divide by 2 (one frac. bit); round "away" from 0
- /*if (mvX > 0) ++mvX;
- mvX >>= 1;
- if (mvY > 0) ++mvY;
- mvY >>= 1;*/ // Leave mv's scaled up by factor of 2
- // Clip to picture rectangle
- mvX = LIMIT( xMin, mvX, xMax );
- mvY = LIMIT( yMin, mvY, yMax );
- DrawVector( data, xdim, 0, 0, mvX, mvY );
- }
- }
- // plusMb - Mark block with a "plus"
- static void plusMb( PIXEL data[], int xdim )
- {
- int col;
-
- // Horizontal line
- data += 7 * xdim;
- for (col = 5; col <= 9; ++col) {
- markPixel( &data[col] );
- }
- // Vertical line
- markPixel( &data[7 - 2 * xdim] );
- markPixel( &data[7 - 1 * xdim] );
- markPixel( &data[7 + 1 * xdim] );
- markPixel( &data[7 + 2 * xdim] );
- }
- // crossMb - Mark block with a cross
- static void crossMb( PIXEL data[], int xdim )
- {
- int row;
-
- for (row = 0; row < 16; ++row) {
- markPixel( &data[row] );
- markPixel( &data[15 - row] );
- data += xdim;
- }
- }
- // fillMb - Fill block with white
- static void fillMb( PIXEL data[], int xdim )
- {
- int row, col;
-
- for (row = 0; row < 16; ++row) {
- for (col = 0; col < 16; ++col) {
- markPixel( &data[col] );
- }
- data += xdim;
- }
- }
- // markPixel - Set pixel to white if < 192, otherwise set it to black
- static void markPixel( PIXEL *pixel )
- {
- if (*pixel < BLACK_THRESHOLD) {
- *pixel = WHITE;
- } else {
- *pixel = BLACK;
- }
- }
- ///////////// Graphics routines /////////////
- #include <stdlib.h>
- #include <math.h>
- // Static function declarations
- static int DrawVector( unsigned char data[], int xdim, int x1, int y1, int x2, int y2 );
- static int drawVec( unsigned char data[], int xdim, int x1, int y1 );
- // DrawVector - Draw vector from (x1,y1) to (x2,y2)
- static int DrawVector( unsigned char data[], int xdim, int x1, int y1, int x2, int y2 )
- {
- int x, y;
-
- if (y1 == y2) { // Draw horizontal line
- data += y1 * xdim;
- for (x = min(x1,x2); x <= max(x1,x2); ++x) markPixel( &data[x] );
- } else if (x1 == x2) { // Draw vertical line
- data += min(y1,y2) * xdim;
- for (y = min(y1,y2); y <= max(y1,y2); ++y) {
- markPixel( &data[x1] );
- data += xdim;
- }
- } else if (x2 > x1) { // Use (x1,y1) as origin
- data += x1 + y1 * xdim;
- drawVec( data, xdim, x2-x1, y2-y1 );
- } else { // Use (x2,y2) as origin
- data += x2 + y2 * xdim;
- drawVec( data, xdim, x1-x2, y1-y2 );
- }
- return(1);
- }
- // drawVec - Draw vector from origin to (x1,y1)
- // Assumes that x1 > 0, and y1 != 0
- // Draw pixels that are within 0.5 units distance of vector
- static int drawVec( unsigned char data[], int xdim, int x1, int y1 )
- {
- int x, y, xLast, xNew;
- float fX1, fY1, fNorm, fA, fB, fXstep, fX, fDist;
-
- if (y1 < 0) {
- y1 = -y1;
- xdim = -xdim;
- }
- // Now, both x1 and y1 are >0
- // Compute equation for line: ax + by = 0, where (a,b) is normal vector of length 1
- // The distance between (x,y) and the line is the inner product: abs(ax + by)
- fX1 = (float)x1;
- fY1 = (float)y1;
- fNorm = (float) sqrt( fX1*fX1 + fY1*fY1);
- fA = -fY1 / fNorm; // fA < 0
- fB = fX1 / fNorm; // fB > 0
- fXstep = fX1 / fY1; // x increment per row
- // First row
- fX = (float)(0.5 * fXstep); // Intersection with y=0.5
- xLast = (int)fX; // Truncate (Note: fX > 0; int always truncates towards zero)
- for (x = 0; x <= xLast; ++x) markPixel( &data[x] );
- // Intermediate rows
- for (y = 1; y < y1; ++y) {
- data += xdim;
- // Check distance to (xLast, y)
- fDist = fA * (float)xLast + fB * (float)y; // fDist > 0
- if (fDist < 0.4999) {
- markPixel( &data[xLast] );
- } else if (fDist + fA - fB > -0.4999) { // Check distance to (xLast+1, y-1)
- //fDist = fA * (float)(xLast+1) + fB * (float)(y-1); // fDist < 0
- markPixel( &data[xLast+1 - xdim] );
- }
- fX += fXstep; // Intersection with y+0.5
- xNew = (int)fX;
- for (x = xLast + 1; x <= xNew; ++x) markPixel( &data[x] );
- xLast = xNew;
- }
- // Last row (y = y1)
- data += xdim;
- // Check distance to (xLast, y1)
- fDist = fA * (float)xLast + fB * (float)y1; // fDist > 0
- if (fDist < 0.4999) {
- markPixel( &data[xLast] );
- } else if (fDist + fA - fB > -0.4999) { // Check distance to (xLast+1, y1-1)
- markPixel( &data[xLast+1 - xdim] );
- }
- for (x = xLast + 1; x <= x1; ++x) markPixel( &data[x] );
-
- return(1);
- }
- #endif /* ANNOTATE_PICTURE */
- /*
- // Compute checksums for picture (used for debugging only)
- static int checkPicture( PICTURE pic );
- static int checkComponent( COMPONENT comp );
- static PIXEL encPic[176*144], decPic[176*144], diffPic[176*144];
- extern int storePicture( PICTURE pic, int picNum )
- {
- int i, j;
- PIXEL *in, *out;
- in = pic.y.ptr;
- if (picNum == 0)
- out = encPic;
- else
- out = decPic;
- for (i = 0; i < pic.y.nvert; i++) {
- for (j = 0; j < pic.y.nhor; j++) {
- out[j] = in[j];
- }
- in += pic.y.hoffset;
- out += pic.y.nhor;
- }
- return( 1 );
- }
- static int checkPicture( PICTURE pic )
- {
- int y, cb, cr, i;
- static int sum = 0;
- storePicture( pic, 1 );
- y = checkComponent( pic.y );
- cb = checkComponent( pic.cb );
- cr = checkComponent( pic.cr );
- sum += y + cb + cr;
- for (i = 0; i < 176*144; ++i)
- diffPic[i] = encPic[i] - decPic[i];
- return( sum );
- }
- static int checkComponent( COMPONENT comp )
- {
- int i, j, sum;
- PIXEL *p;
- sum = 0, p = comp.ptr;
- for (i = 0; i < comp.nvert; i++) {
- for (j = 0; j < comp.nhor; j++) {
- sum += p[j];
- }
- p += comp.hoffset;
- }
- return( sum );
- }
- */