/**************************************************************************** * * ROUTINE : ReadNextBlockPattern * * INPUTS : None. * * OUTPUTS : None. * * RETURNS : A pattern of coded or uncoded blocks for a macro block. * * FUNCTION : Returns the block pattern for the next macro block. * * SPECIAL NOTES : None. * * * ERRORS : None. * ****************************************************************************/ UINT8 ReadNextBlockPattern (PB_INSTANCE *pbi) { UINT8 BlockPattern = 0; UINT8 Bitpattern = 0; UINT32 BitCount = 3; // Read three bits and test to see if we have a valid token. Bitpattern = bitread(&pbi->br, 3); // Test pattern to see if is a valid token. BlockPattern = BlockDecode1[pbi->BlockPatternPredictor][Bitpattern]; // if pattern was not a valid token if ( !BlockPattern ) { BitCount++; Bitpattern = (Bitpattern << 1) + bitread1(&pbi->br); // Test pattern to see if is a valid token. BlockPattern = BlockDecode2[pbi->BlockPatternPredictor][Bitpattern]; if ( !BlockPattern ) { BitCount++; Bitpattern = (Bitpattern << 1) + bitread1(&pbi->br); BlockPattern = BlockDecode3[pbi->BlockPatternPredictor][Bitpattern]; } } // Update the entropy predictor for next time. pbi->BlockPatternPredictor = BPPredictor[BlockPattern]; return BlockPattern; }
/**************************************************************************** * * ROUTINE : GetNextSbInitSb * * INPUTS : None. * * OUTPUTS : None. * * RETURNS : None * * FUNCTION : Initialises decode process for an SB RLC stream. * * SPECIAL NOTES : None. * * * ERRORS : None. * ****************************************************************************/ void GetNextSbInit(PB_INSTANCE *pbi) { pbi->NextBit = bitread1(&pbi->br); // Read run length FrArrayDeCodeInit(pbi); while ( FrArrayDeCodeSBRun( pbi,bitread1(&pbi->br), &pbi->BitsLeft ) == FALSE ); }
/**************************************************************************** * * ROUTINE : ExtractMVectorComponentA * * INPUTS : None. * * OUTPUTS : None. * * RETURNS : None. * * FUNCTION : Extracts a motion vector component coded with method A. * * SPECIAL NOTES : None. * * * ERRORS : None. * ****************************************************************************/ INT32 ExtractMVectorComponentA(PB_INSTANCE *pbi) { INT32 MVectComponent; // temp storage for motion vector UINT32 MVCode = 0; // Temporary storage while decoding the MV UINT32 ExtraBits = 0; // Get group to which coded component belongs MVCode = bitread( &pbi->br, 3 ); // Now extract the appropriate number of bits to identify the component switch ( MVCode ) { case 0: MVectComponent = 0; break; case 1: MVectComponent = 1; break; case 2: MVectComponent = -1; break; case 3: if ( bitread1( &pbi->br )) MVectComponent = -2; else MVectComponent = 2; break; case 4: if ( bitread1( &pbi->br ) ) MVectComponent = -3; else MVectComponent = 3; break; case 5: ExtraBits = bitread( &pbi->br, 2 ); MVectComponent = 4 + ExtraBits; if ( bitread1( &pbi->br ) ) MVectComponent = -MVectComponent; break; case 6: ExtraBits = bitread( &pbi->br, 3 ); MVectComponent = 8 + ExtraBits; if ( bitread1( &pbi->br )) MVectComponent = -MVectComponent; break; case 7: ExtraBits = bitread( &pbi->br, 4 ); MVectComponent = 16 + ExtraBits; if ( bitread1( &pbi->br ) ) MVectComponent = -MVectComponent; break; } return MVectComponent; }
BOOL LoadFrameHeader(PB_INSTANCE *pbi) { UINT8 VersionByte0; // Must be 0 for VP30b and later UINT8 DctQMask; UINT8 SpareBits; // Spare cfg bits UINT8 Unused; BOOL RetVal = TRUE; // Is the frame and inter frame or a key frame pbi->FrameType = bitread1(&pbi->br); // unused bit Unused = bitread1(&pbi->br); // Quality (Q) index DctQMask = (UINT8)bitread( &pbi->br, 6 ); // If the frame was a base frame then read the frame dimensions and build a bitmap structure. if ( (pbi->FrameType == BASE_FRAME) ) { // Read the frame dimensions bytes (0,0 indicates vp31 or later) VersionByte0 = (UINT8)bitread( &pbi->br, 8 ); pbi->Vp3VersionNo = (UINT8)bitread( &pbi->br, 5 ); if(pbi->Vp3VersionNo > CURRENT_DECODE_VERSION) { RetVal = FALSE; return RetVal; } // Initialise version specific quantiser values InitQTables( pbi ); // Read the type / coding method for the key frame. pbi->KeyFrameType = (UINT8)bitread( &pbi->br, 1 ); SpareBits = (UINT8)bitread( &pbi->br, 2 ); // Select huffman tables SelectHuffmanSet( pbi ); } // Set this frame quality value from Q Index pbi->ThisFrameQualityValue = pbi->QThreshTable[DctQMask]; return RetVal; }
/**************************************************************************** * * ROUTINE : ExtractMVectorComponentB * * INPUTS : None. * * OUTPUTS : None. * * RETURNS : None. * * FUNCTION : Extracts an MV component coded using the fallback method * * SPECIAL NOTES : None. * * * ERRORS : None. * ****************************************************************************/ INT32 ExtractMVectorComponentB(PB_INSTANCE *pbi) { INT32 MVectComponent; // temp storage for motion vector // Get group to which coded component belongs MVectComponent = bitread( &pbi->br, 5 ); if ( bitread1( &pbi->br ) ) MVectComponent = -MVectComponent; return MVectComponent; }
/**************************************************************************** * * ROUTINE : ExtractToken * * INPUTS : INT8 * ExpandedBlock * Pointer to block structure into which the token * should be expanded. * * UINT32 * CoeffIndex * Where we are in the current block. * * OUTPUTS : * * RETURNS : The number of bits decoded * * FUNCTION : Unpacks and expands an DC DCT token. * * SPECIAL NOTES : PROBLEM !!!!!!!!!!! right now handles only left * justified bits in bitreader. the c version keeps every * thing in place so I can't use it!! * * * * ERRORS : None. * ****************************************************************************/ UINT32 ExtractToken(BITREADER *br, HUFF_ENTRY * CurrentRoot) { UINT32 Token; // Loop searches down through tree based upon bits read from the bitstream // until it hits a leaf at which point we have decoded a token while ( CurrentRoot->Value < 0 ) { if ( bitread1(br) ) CurrentRoot = (HUFF_ENTRY *)(CurrentRoot->OneChild); else CurrentRoot = (HUFF_ENTRY *)(CurrentRoot->ZeroChild); } Token = CurrentRoot->Value; return Token; }
/**************************************************************************** * * ROUTINE : GetNextSbBit * * INPUTS : None. * * OUTPUTS : None. * * RETURNS : Value of next bit in stream. * * FUNCTION : Returns next available bit value from an SB RLC stream. * * SPECIAL NOTES : None. * * * ERRORS : None. * ****************************************************************************/ UINT8 GetNextSbBit (PB_INSTANCE *pbi) { if ( !pbi->BitsLeft ) { // Toggle the value. pbi->NextBit = ( pbi->NextBit == 1 ) ? 0 : 1; // Read next run FrArrayDeCodeInit(pbi); while ( FrArrayDeCodeSBRun( pbi, bitread1(&pbi->br), &pbi->BitsLeft ) == FALSE ); } // Have read a bit pbi->BitsLeft--; // Return next bit value return pbi->NextBit; }
/**************************************************************************** * * ROUTINE : GetNextSbBit * * INPUTS : None. * * OUTPUTS : None. * * RETURNS : Value of next bit in stream. * * FUNCTION : Returns next available bit value from a MB RLC stream. * * SPECIAL NOTES : None. * * * ERRORS : None. * ****************************************************************************/ UINT8 GetNextMbBit (PB_INSTANCE *pbi) { if ( !pbi->BitsLeft ) { // Toggle the value. pbi->NextBit = ( pbi->NextBit == 1 ) ? 0 : 1; // Read next run FrArrayDeCodeInit(pbi); while ( FrArrayDeCodeMBRun( pbi, bitread1(&pbi->br), &pbi->BitsLeft ) == FALSE ); } // Decrement bits left in run counter pbi->BitsLeft--; // Return next bit value return pbi->NextBit; }
/**************************************************************************** * * ROUTINE : FrArrayUnpackMode * * INPUTS : None * * OUTPUTS : None * * RETURNS : A decoded mode token * * FUNCTION : Unpacks a mode token * * SPECIAL NOTES : None. * * * ERRORS : None. * ****************************************************************************/ CODING_MODE FrArrayUnpackMode(PB_INSTANCE *pbi) { // Coding scheme: // Token Codeword Bits // Entry 0 (most frequent) 0 1 // Entry 1 10 2 // Entry 2 110 3 // Entry 3 1110 4 // Entry 4 11110 5 // Entry 5 111110 6 // Entry 6 1111110 7 // Entry 7 1111111 7 // Initialise the decoding. pbi->bit_pattern = 0; pbi->bits_so_far = 0; pbi->bit_pattern = bitread1(&pbi->br); // Do we have a match if ( pbi->bit_pattern == 0 ) return (CODING_MODE)0; // Get the next bit pbi->bit_pattern = (pbi->bit_pattern << 1) | bitread1(&pbi->br); // Do we have a match if ( pbi->bit_pattern == 0x0002 ) return (CODING_MODE)1; pbi->bit_pattern = (pbi->bit_pattern << 1) | bitread1(&pbi->br); // Do we have a match if ( pbi->bit_pattern == 0x0006 ) return (CODING_MODE)2; pbi->bit_pattern = (pbi->bit_pattern << 1) | bitread1(&pbi->br); // Do we have a match if ( pbi->bit_pattern == 0x000E ) return (CODING_MODE)3; pbi->bit_pattern = (pbi->bit_pattern << 1) | bitread1(&pbi->br); // Do we have a match if ( pbi->bit_pattern == 0x001E ) return (CODING_MODE)4; pbi->bit_pattern = (pbi->bit_pattern << 1) | bitread1(&pbi->br); // Do we have a match if ( pbi->bit_pattern == 0x003E ) return (CODING_MODE)5; pbi->bit_pattern = (pbi->bit_pattern << 1) | bitread1(&pbi->br); // Do we have a match if ( pbi->bit_pattern == 0x007E ) return (CODING_MODE)6; else return (CODING_MODE)7; }
/**************************************************************************** * * ROUTINE : DecodeMVectors * * INPUTS : None. * * OUTPUTS : None. * * RETURNS : None. * * FUNCTION : Decodes the motion vectors for this frame. * * SPECIAL NOTES : None. * * * ERRORS : None. * ****************************************************************************/ void DecodeMVectors ( PB_INSTANCE *pbi, UINT32 SBRows, UINT32 SBCols, UINT32 HExtra, UINT32 VExtra ) { INT32 FragIndex; // Fragment number UINT32 MB; // Macro-Block, Block indices UINT32 SBrow; // Super-Block row number UINT32 SBcol; // Super-Block row number UINT32 SB=0; // Super-Block index UINT32 CodingMethod; // Temp Storage for coding mode. MOTION_VECTOR MVect[6]; // temp storage for motion vector MOTION_VECTOR TmpMVect; MOTION_VECTOR LastInterMV; // storage for last used Inter frame MB motion vector MOTION_VECTOR PriorLastInterMV; // storage for previous last used Inter frame MB motion vector INT32 (*ExtractMVectorComponent)(PB_INSTANCE *pbi); UINT32 UVRow; UINT32 UVColumn; UINT32 UVFragOffset; UINT32 MBListIndex = 0; UINT32 MVCode = 0; // Temporary storage while decoding the MV // Should not be decoding motion vectors if in INTRA only mode. if ( GetFrameType(pbi) == BASE_FRAME ) { return; } // set the default motion vector to 0,0 MVect[0].x = 0; MVect[0].y = 0; LastInterMV.x = 0; LastInterMV.y = 0; PriorLastInterMV.x = 0; PriorLastInterMV.y = 0; // Read the entropy method used and set up the appropriate decode option if ( bitread1( &pbi->br) == 0 ) ExtractMVectorComponent = ExtractMVectorComponentA; else ExtractMVectorComponent = ExtractMVectorComponentB; // Unravel the quad-tree for ( SBrow=0; SBrow<SBRows; SBrow++ ) { for ( SBcol=0; SBcol<SBCols; SBcol++ ) { for ( MB=0; MB<4; MB++ ) { // There may be MB's lying out of frame // which must be ignored. For these MB's // the top left block will have a negative Fragment Index. if ( QuadMapToMBTopLeft(pbi->BlockMap, SB,MB) >= 0 ) { // Is the Macro-Block further coded: if ( pbi->MBCodedFlags[MBListIndex++] ) { // Upack the block level modes and motion vectors FragIndex = QuadMapToMBTopLeft( pbi->BlockMap, SB, MB ); // Clear the motion vector before we start. MVect[0].x = 0; MVect[0].y = 0; // Unpack the mode (and motion vectors if necessary). CodingMethod = pbi->FragCodingMethod[FragIndex]; // Read the motion vector or vectors if present. if ( (CodingMethod == CODE_INTER_PLUS_MV) || (CodingMethod == CODE_GOLDEN_MV) ) { MVect[0].x = ExtractMVectorComponent(pbi); MVect[1].x = MVect[0].x; MVect[2].x = MVect[0].x; MVect[3].x = MVect[0].x; MVect[4].x = MVect[0].x; MVect[5].x = MVect[0].x; MVect[0].y = ExtractMVectorComponent(pbi); MVect[1].y = MVect[0].y; MVect[2].y = MVect[0].y; MVect[3].y = MVect[0].y; MVect[4].y = MVect[0].y; MVect[5].y = MVect[0].y; } else if ( CodingMethod == CODE_INTER_FOURMV ) { // Extrac the 4 Y MVs MVect[0].x = ExtractMVectorComponent(pbi); MVect[0].y = ExtractMVectorComponent(pbi); MVect[1].x = ExtractMVectorComponent(pbi); MVect[1].y = ExtractMVectorComponent(pbi); MVect[2].x = ExtractMVectorComponent(pbi); MVect[2].y = ExtractMVectorComponent(pbi); MVect[3].x = ExtractMVectorComponent(pbi); MVect[3].y = ExtractMVectorComponent(pbi); // Calculate the U and V plane MVs as the average of the Y plane MVs. // First .x component MVect[4].x = MVect[0].x + MVect[1].x + MVect[2].x + MVect[3].x; if ( MVect[4].x >= 0 ) MVect[4].x = (MVect[4].x + 2) / 4; else MVect[4].x = (MVect[4].x - 2) / 4; MVect[5].x = MVect[4].x; // Then .y component MVect[4].y = MVect[0].y + MVect[1].y + MVect[2].y + MVect[3].y; if ( MVect[4].y >= 0 ) MVect[4].y = (MVect[4].y + 2) / 4; else MVect[4].y = (MVect[4].y - 2) / 4; MVect[5].y = MVect[4].y; } // Keep track of last and prior last inter motion vectors. if ( CodingMethod == CODE_INTER_PLUS_MV ) { PriorLastInterMV.x = LastInterMV.x; PriorLastInterMV.y = LastInterMV.y; LastInterMV.x = MVect[0].x; LastInterMV.y = MVect[0].y; } else if ( CodingMethod == CODE_INTER_LAST_MV ) { // Use the last coded Inter motion vector. MVect[0].x = LastInterMV.x; MVect[1].x = MVect[0].x; MVect[2].x = MVect[0].x; MVect[3].x = MVect[0].x; MVect[4].x = MVect[0].x; MVect[5].x = MVect[0].x; MVect[0].y = LastInterMV.y; MVect[1].y = MVect[0].y; MVect[2].y = MVect[0].y; MVect[3].y = MVect[0].y; MVect[4].y = MVect[0].y; MVect[5].y = MVect[0].y; } else if ( CodingMethod == CODE_INTER_PRIOR_LAST ) { // Use the last coded Inter motion vector. MVect[0].x = PriorLastInterMV.x; MVect[1].x = MVect[0].x; MVect[2].x = MVect[0].x; MVect[3].x = MVect[0].x; MVect[4].x = MVect[0].x; MVect[5].x = MVect[0].x; MVect[0].y = PriorLastInterMV.y; MVect[1].y = MVect[0].y; MVect[2].y = MVect[0].y; MVect[3].y = MVect[0].y; MVect[4].y = MVect[0].y; MVect[5].y = MVect[0].y; // Swap the prior and last MV cases over TmpMVect.x = PriorLastInterMV.x; TmpMVect.y = PriorLastInterMV.y; PriorLastInterMV.x = LastInterMV.x; PriorLastInterMV.y = LastInterMV.y; LastInterMV.x = TmpMVect.x; LastInterMV.y = TmpMVect.y; } else if ( CodingMethod == CODE_INTER_FOURMV ) { // Update last MV and prior last mv PriorLastInterMV.x = LastInterMV.x; PriorLastInterMV.y = LastInterMV.y; LastInterMV.x = MVect[3].x; LastInterMV.y = MVect[3].y; } // Note the coding mode and vector for each block in the current macro block. pbi->FragMVect[FragIndex].x = MVect[0].x; pbi->FragMVect[FragIndex].y = MVect[0].y; pbi->FragMVect[FragIndex + 1].x = MVect[1].x; pbi->FragMVect[FragIndex + 1].y = MVect[1].y; pbi->FragMVect[FragIndex + pbi->HFragments].x = MVect[2].x; pbi->FragMVect[FragIndex + pbi->HFragments].y = MVect[2].y; pbi->FragMVect[FragIndex + pbi->HFragments + 1].x = MVect[3].x; pbi->FragMVect[FragIndex + pbi->HFragments + 1].y = MVect[3].y; // Matching fragments in the U and V planes UVRow = (FragIndex / (pbi->HFragments * 2)); UVColumn = (FragIndex % pbi->HFragments) / 2; UVFragOffset = (UVRow * (pbi->HFragments / 2)) + UVColumn; pbi->FragMVect[pbi->YPlaneFragments + UVFragOffset].x = MVect[4].x; pbi->FragMVect[pbi->YPlaneFragments + UVFragOffset].y = MVect[4].y; pbi->FragMVect[pbi->YPlaneFragments + pbi->UVPlaneFragments + UVFragOffset].x = MVect[5].x; pbi->FragMVect[pbi->YPlaneFragments + pbi->UVPlaneFragments + UVFragOffset].y = MVect[5].y; } } } // Next Super-Block SB++; } } }