/**************************************************************************** * * ROUTINE : UpRegulateMB * * INPUTS : UINT32 RegulationQ * (Q at which we are updating.) * * UINT32 SB,MB * (MB and SB indentifiers) * * BOOL NoCheck * (Should we check previous update Q) * * OUTPUTS : None. * * RETURNS : None. * * FUNCTION : Up regulate specified MB * * SPECIAL NOTES : None. * * * ERRORS : None. * ****************************************************************************/ void UpRegulateMB( CP_INSTANCE *cpi, UINT32 RegulationQ, UINT32 SB, UINT32 MB, BOOL NoCheck ) { INT32 FragIndex; UINT32 B; // Block indicex // Variables used in calculating corresponding row,col and index in UV planes UINT32 UVRow; UINT32 UVColumn; UINT32 UVFragOffset; // There may be MB's lying out of frame // which must be ignored. For these MB's // Top left block will have a negative Fragment Index. if ( QuadMapToMBTopLeft(cpi->pb.BlockMap, SB, MB ) >= 0 ) { // Up regulate the component blocks Y then UV. for ( B=0; B<4; B++ ) { FragIndex = QuadMapToIndex1( cpi->pb.BlockMap, SB, MB, B ); if ( ( !cpi->pb.display_fragments[FragIndex] ) && ( (NoCheck) || (cpi->FragmentLastQ[FragIndex] > RegulationQ) ) ) { cpi->pb.display_fragments[FragIndex] = 1; cpi->extra_fragments[FragIndex] = 1; cpi->FragmentLastQ[FragIndex] = RegulationQ; cpi->MotionScore++; } } // Check the two UV blocks FragIndex = QuadMapToMBTopLeft(cpi->pb.BlockMap, SB, MB ); UVRow = (FragIndex / (cpi->pb.HFragments * 2)); UVColumn = (FragIndex % cpi->pb.HFragments) / 2; UVFragOffset = (UVRow * (cpi->pb.HFragments / 2)) + UVColumn; FragIndex = cpi->pb.YPlaneFragments + UVFragOffset; if ( ( !cpi->pb.display_fragments[FragIndex] ) && ( (NoCheck) || (cpi->FragmentLastQ[FragIndex] > RegulationQ) ) ) { cpi->pb.display_fragments[FragIndex] = 1; cpi->extra_fragments[FragIndex] = 1; cpi->FragmentLastQ[FragIndex] = RegulationQ; cpi->MotionScore++; } FragIndex += cpi->pb.UVPlaneFragments; if ( ( !cpi->pb.display_fragments[FragIndex] ) && ( (NoCheck) || (cpi->FragmentLastQ[FragIndex] > RegulationQ) ) ) { cpi->pb.display_fragments[FragIndex] = 1; cpi->extra_fragments[FragIndex] = 1; cpi->FragmentLastQ[FragIndex] = RegulationQ; cpi->MotionScore++; } } }
static void UpRegulateMB( CP_INSTANCE *cpi, ogg_uint32_t RegulationQ, ogg_uint32_t SB, ogg_uint32_t MB, int NoCheck ) { ogg_int32_t FragIndex; ogg_uint32_t B; /* Variables used in calculating corresponding row,col and index in UV planes */ ogg_uint32_t UVRow; ogg_uint32_t UVColumn; ogg_uint32_t UVFragOffset; /* There may be MB's lying out of frame which must be ignored. For these MB's Top left block will have a negative Fragment Index. */ if ( QuadMapToMBTopLeft(cpi->pb.BlockMap, SB, MB ) >= 0 ) { /* Up regulate the component blocks Y then UV. */ for ( B=0; B<4; B++ ){ FragIndex = QuadMapToIndex1( cpi->pb.BlockMap, SB, MB, B ); if ( ( !cpi->pb.display_fragments[FragIndex] ) && ( (NoCheck) || (cpi->FragmentLastQ[FragIndex] > RegulationQ) ) ){ cpi->pb.display_fragments[FragIndex] = 1; cpi->extra_fragments[FragIndex] = 1; cpi->FragmentLastQ[FragIndex] = RegulationQ; cpi->MotionScore++; } } /* Check the two UV blocks */ FragIndex = QuadMapToMBTopLeft(cpi->pb.BlockMap, SB, MB ); UVRow = (FragIndex / (cpi->pb.HFragments * 2)); UVColumn = (FragIndex % cpi->pb.HFragments) / 2; UVFragOffset = (UVRow * (cpi->pb.HFragments / 2)) + UVColumn; FragIndex = cpi->pb.YPlaneFragments + UVFragOffset; if ( ( !cpi->pb.display_fragments[FragIndex] ) && ( (NoCheck) || (cpi->FragmentLastQ[FragIndex] > RegulationQ) ) ) { cpi->pb.display_fragments[FragIndex] = 1; cpi->extra_fragments[FragIndex] = 1; cpi->FragmentLastQ[FragIndex] = RegulationQ; cpi->MotionScore++; } FragIndex += cpi->pb.UVPlaneFragments; if ( ( !cpi->pb.display_fragments[FragIndex] ) && ( (NoCheck) || (cpi->FragmentLastQ[FragIndex] > RegulationQ) ) ) { cpi->pb.display_fragments[FragIndex] = 1; cpi->extra_fragments[FragIndex] = 1; cpi->FragmentLastQ[FragIndex] = RegulationQ; cpi->MotionScore++; } } }
/**************************************************************************** * * ROUTINE : QuadDeCodeDisplayFragments2 * * INPUTS : PB instance * * OUTPUTS : Mapping table BlockMap[SuperBlock][MacroBlock][Block] * * RETURNS : None. * * FUNCTION : Creates mapping table between (SuperBlock, MacroBlock, Block) * triplet and corresponding Fragment Index. * * SPECIAL NOTES : None. * * * ERRORS : None. * ****************************************************************************/ void QuadDecodeDisplayFragments2 ( PB_INSTANCE *pbi ) { UINT32 SB, MB, B; // Super-block, Macro-block and Block values BOOL DataToDecode = FALSE; INT32 dfIndex; UINT32 MBIndex = 0; UINT8 * MBFully; UINT8 * MBCoded; UINT8 BPattern; // Set up local pointers MBFully = pbi->MBFullyFlags; MBCoded = pbi->MBCodedFlags; // Reset various data structures common to key frames and inter frames. pbi->CodedBlockIndex = 0; memset( pbi->display_fragments, 0, pbi->UnitFragments ); // For "Key frames" mark all blocks as coded and return. // Else initialise the ArrayPtr array to 0 (all blocks uncoded by default) if ( GetFrameType(pbi) == BASE_FRAME ) { memset( MBFully, 1, pbi->MacroBlocks ); } else { memset( MBFully, 0, pbi->MacroBlocks ); memset( MBCoded, 0, pbi->MacroBlocks ); // Un-pack MBlist1 GetNextMbInit(pbi); for( MB = 0; MB < pbi->MacroBlocks; MB++) { MBFully[MB] = GetNextMbBit (pbi); } // If there are any macro blocks that are not fully coded then there is more to do. for( MB = 0; MB < pbi->MacroBlocks; MB++ ) { if ( !MBFully[MB] ) { DataToDecode = TRUE; break; } } // Build the coded MB list (Fully or partially coded) if ( DataToDecode ) { // Un-pack MBlist2 GetNextMbInit(pbi); for( MB = 0; MB < pbi->MacroBlocks; MB++) { if ( !MBFully[MB] ) MBCoded[MB] = GetNextMbBit( pbi ); } } } // Complete the block and macro block coded data structures. // Initialise the block pattern reader. ReadBlockPatternInit(pbi); // Follow the quad tree structure for ( SB=0; SB < pbi->SuperBlocks; SB++ ) { for ( MB=0; MB<4; MB++ ) { // If MB is in the frame if ( QuadMapToMBTopLeft(pbi->BlockMap, SB,MB) >= 0 ) { // Set or read the block pattern for the macro block# if ( MBFully[MBIndex] ) { MBCoded[MBIndex] = 1; BPattern = 0x0F; } else if ( MBCoded[MBIndex] ) { BPattern = ReadNextBlockPattern(pbi); } else { BPattern = 0; } for ( B=0; B<4; B++ ) { // If block is valid (in frame)... dfIndex = QuadMapToIndex2( pbi->BlockMap, SB, MB, B ); if ( dfIndex >= 0 ) { // Work out if this block is coded or not. pbi->display_fragments[dfIndex] = (BPattern & BlockPatternMask[B]) ? 1 : 0; } } for ( B=0; B<4; B++ ) { // If block is valid (in frame)... dfIndex = QuadMapToIndex1( pbi->BlockMap, SB, MB, B ); if ( dfIndex >= 0 ) { if ( pbi->display_fragments[dfIndex] ) { pbi->CodedBlockList[pbi->CodedBlockIndex] = dfIndex; pbi->CodedBlockIndex++; } } } // Increment the MB index. MBIndex++; } } } }
/**************************************************************************** * * ROUTINE : QuadDeCodeDisplayFragments * * INPUTS : PB instance * * OUTPUTS : Mapping table BlockMap[SuperBlock][MacroBlock][Block] * * RETURNS : None. * * FUNCTION : Creates mapping table between (SuperBlock, MacroBlock, Block) * triplet and corresponding Fragment Index. * * SPECIAL NOTES : None. * * * ERRORS : None. * ****************************************************************************/ void QuadDecodeDisplayFragments ( PB_INSTANCE *pbi ) { UINT32 SB, MB, B; // Super-block, Macro-block and Block values BOOL DataToDecode; INT32 dfIndex; UINT32 MBIndex = 0; // Reset various data structures common to key frames and inter frames. pbi->CodedBlockIndex = 0; memset ( pbi->display_fragments, 0, pbi->UnitFragments ); // For "Key frames" mark all blocks as coded and return. // Else initialise the ArrayPtr array to 0 (all blocks uncoded by default) if ( GetFrameType(pbi) == BASE_FRAME ) { memset( pbi->SBFullyFlags, 1, pbi->SuperBlocks ); memset( pbi->SBCodedFlags, 1, pbi->SuperBlocks ); memset( pbi->MBCodedFlags, 0, pbi->MacroBlocks ); } else { memset( pbi->SBFullyFlags, 0, pbi->SuperBlocks ); memset( pbi->MBCodedFlags, 0, pbi->MacroBlocks ); // Un-pack the list of partially coded Super-Blocks GetNextSbInit(pbi); for( SB = 0; SB < pbi->SuperBlocks; SB++) { pbi->SBCodedFlags[SB] = GetNextSbBit (pbi); } // Scan through the list of super blocks. // Unless all are marked as partially coded we have more to do. DataToDecode = FALSE; for ( SB=0; SB<pbi->SuperBlocks; SB++ ) { if ( !pbi->SBCodedFlags[SB] ) { DataToDecode = TRUE; break; } } // Are there further block map bits to decode ? if ( DataToDecode ) { // Un-pack the Super-Block fully coded flags. GetNextSbInit(pbi); for( SB = 0; SB < pbi->SuperBlocks; SB++) { // Skip blocks already marked as partially coded while( (SB < pbi->SuperBlocks) && pbi->SBCodedFlags[SB] ) SB++; if ( SB < pbi->SuperBlocks ) { pbi->SBFullyFlags[SB] = GetNextSbBit (pbi); if ( pbi->SBFullyFlags[SB] ) // If SB is fully coded. pbi->SBCodedFlags[SB] = 1; // Mark the SB as coded } } } // Scan through the list of coded super blocks. // If at least one is marked as partially coded then we have a block list to decode. for ( SB=0; SB<pbi->SuperBlocks; SB++ ) { if ( pbi->SBCodedFlags[SB] && !pbi->SBFullyFlags[SB] ) { // Initialise the block list decoder. GetNextBInit(pbi); break; } } } // Decode the block data from the bit stream. for ( SB=0; SB<pbi->SuperBlocks; SB++ ) { for ( MB=0; MB<4; MB++ ) { // If MB is in the frame if ( QuadMapToMBTopLeft(pbi->BlockMap, SB,MB) >= 0 ) { // Only read block level data if SB was fully or partially coded if ( pbi->SBCodedFlags[SB] ) { for ( B=0; B<4; B++ ) { // If block is valid (in frame)... dfIndex = QuadMapToIndex1( pbi->BlockMap, SB, MB, B ); if ( dfIndex >= 0 ) { if ( pbi->SBFullyFlags[SB] ) pbi->display_fragments[dfIndex] = 1; else pbi->display_fragments[dfIndex] = GetNextBBit(pbi); // Create linear list of coded block indices if ( pbi->display_fragments[dfIndex] ) { pbi->MBCodedFlags[MBIndex] = 1; pbi->CodedBlockList[pbi->CodedBlockIndex] = dfIndex; pbi->CodedBlockIndex++; } } } } MBIndex++; } } } }
void QuadDecodeDisplayFragments ( PB_INSTANCE *pbi ){ ogg_uint32_t SB, MB, B; int DataToDecode; ogg_int32_t dfIndex; ogg_uint32_t MBIndex = 0; /* Reset various data structures common to key frames and inter frames. */ pbi->CodedBlockIndex = 0; memset ( pbi->display_fragments, 0, pbi->UnitFragments ); /* For "Key frames" mark all blocks as coded and return. */ /* Else initialise the ArrayPtr array to 0 (all blocks uncoded by default) */ if ( GetFrameType(pbi) == BASE_FRAME ) { memset( pbi->SBFullyFlags, 1, pbi->SuperBlocks ); memset( pbi->SBCodedFlags, 1, pbi->SuperBlocks ); memset( pbi->MBCodedFlags, 0, pbi->MacroBlocks ); }else{ memset( pbi->SBFullyFlags, 0, pbi->SuperBlocks ); memset( pbi->MBCodedFlags, 0, pbi->MacroBlocks ); /* Un-pack the list of partially coded Super-Blocks */ GetNextSbInit(pbi); for( SB = 0; SB < pbi->SuperBlocks; SB++){ pbi->SBCodedFlags[SB] = GetNextSbBit (pbi); } /* Scan through the list of super blocks. Unless all are marked as partially coded we have more to do. */ DataToDecode = 0; for ( SB=0; SB<pbi->SuperBlocks; SB++ ) { if ( !pbi->SBCodedFlags[SB] ) { DataToDecode = 1; break; } } /* Are there further block map bits to decode ? */ if ( DataToDecode ) { /* Un-pack the Super-Block fully coded flags. */ GetNextSbInit(pbi); for( SB = 0; SB < pbi->SuperBlocks; SB++) { /* Skip blocks already marked as partially coded */ while( (SB < pbi->SuperBlocks) && pbi->SBCodedFlags[SB] ) SB++; if ( SB < pbi->SuperBlocks ) { pbi->SBFullyFlags[SB] = GetNextSbBit (pbi); if ( pbi->SBFullyFlags[SB] ) /* If SB is fully coded. */ pbi->SBCodedFlags[SB] = 1; /* Mark the SB as coded */ } } } /* Scan through the list of coded super blocks. If at least one is marked as partially coded then we have a block list to decode. */ for ( SB=0; SB<pbi->SuperBlocks; SB++ ) { if ( pbi->SBCodedFlags[SB] && !pbi->SBFullyFlags[SB] ) { /* Initialise the block list decoder. */ GetNextBInit(pbi); break; } } } /* Decode the block data from the bit stream. */ for ( SB=0; SB<pbi->SuperBlocks; SB++ ){ for ( MB=0; MB<4; MB++ ){ /* If MB is in the frame */ if ( QuadMapToMBTopLeft(pbi->BlockMap, SB,MB) >= 0 ){ /* Only read block level data if SB was fully or partially coded */ if ( pbi->SBCodedFlags[SB] ) { for ( B=0; B<4; B++ ){ /* If block is valid (in frame)... */ dfIndex = QuadMapToIndex1( pbi->BlockMap, SB, MB, B ); if ( dfIndex >= 0 ){ if ( pbi->SBFullyFlags[SB] ) pbi->display_fragments[dfIndex] = 1; else pbi->display_fragments[dfIndex] = GetNextBBit(pbi); /* Create linear list of coded block indices */ if ( pbi->display_fragments[dfIndex] ) { pbi->MBCodedFlags[MBIndex] = 1; pbi->CodedBlockList[pbi->CodedBlockIndex] = dfIndex; pbi->CodedBlockIndex++; } } } } MBIndex++; } } } }
void PackAndWriteDFArray( CP_INSTANCE *cpi ){ ogg_uint32_t i; unsigned char val; ogg_uint32_t run_count; ogg_uint32_t SB, MB, B; /* Block, MB and SB loop variables */ ogg_uint32_t BListIndex = 0; ogg_uint32_t LastSbBIndex = 0; ogg_int32_t DfBlockIndex; /* Block index in display_fragments */ /* Initialise workspaces */ memset( cpi->pb.SBFullyFlags, 1, cpi->pb.SuperBlocks); memset( cpi->pb.SBCodedFlags, 0, cpi->pb.SuperBlocks ); memset( cpi->PartiallyCodedFlags, 0, cpi->pb.SuperBlocks ); memset( cpi->BlockCodedFlags, 0, cpi->pb.UnitFragments); for( SB = 0; SB < cpi->pb.SuperBlocks; SB++ ) { /* Check for coded blocks and macro-blocks */ for ( MB=0; MB<4; MB++ ) { /* If MB in frame */ if ( QuadMapToMBTopLeft(cpi->pb.BlockMap,SB,MB) >= 0 ) { for ( B=0; B<4; B++ ) { DfBlockIndex = QuadMapToIndex1( cpi->pb.BlockMap,SB, MB, B ); /* Does Block lie in frame: */ if ( DfBlockIndex >= 0 ) { /* In Frame: If it is not coded then this SB is only partly coded.: */ if ( cpi->pb.display_fragments[DfBlockIndex] ) { cpi->pb.SBCodedFlags[SB] = 1; /* SB at least partly coded */ cpi->BlockCodedFlags[BListIndex] = 1; /* Block is coded */ }else{ cpi->pb.SBFullyFlags[SB] = 0; /* SB not fully coded */ cpi->BlockCodedFlags[BListIndex] = 0; /* Block is not coded */ } BListIndex++; } } } } /* Is the SB fully coded or uncoded. If so then backup BListIndex and MBListIndex */ if ( cpi->pb.SBFullyFlags[SB] || !cpi->pb.SBCodedFlags[SB] ) { BListIndex = LastSbBIndex; /* Reset to values from previous SB */ }else{ cpi->PartiallyCodedFlags[SB] = 1; /* Set up list of partially coded SBs */ LastSbBIndex = BListIndex; } } /* Code list of partially coded Super-Block. */ val = cpi->PartiallyCodedFlags[0]; oggpackB_write( cpi->oggbuffer, (ogg_uint32_t)val, 1); i = 0; while ( i < cpi->pb.SuperBlocks ) { run_count = 0; while ( (i<cpi->pb.SuperBlocks) && (cpi->PartiallyCodedFlags[i]==val) ) { i++; run_count++; } /* Code the run */ FrArrayCodeSBRun( cpi, run_count ); val = ( val == 0 ) ? 1 : 0; } /* RLC Super-Block fully/not coded. */ i = 0; /* Skip partially coded blocks */ while( (i < cpi->pb.SuperBlocks) && cpi->PartiallyCodedFlags[i] ) i++; if ( i < cpi->pb.SuperBlocks ) { val = cpi->pb.SBFullyFlags[i]; oggpackB_write( cpi->oggbuffer, (ogg_uint32_t)val, 1); while ( i < cpi->pb.SuperBlocks ) { run_count = 0; while ( (i < cpi->pb.SuperBlocks) && (cpi->pb.SBFullyFlags[i] == val) ) { i++; /* Skip partially coded blocks */ while( (i < cpi->pb.SuperBlocks) && cpi->PartiallyCodedFlags[i] ) i++; run_count++; } /* Code the run */ FrArrayCodeSBRun( cpi, run_count ); val = ( val == 0 ) ? 1 : 0; } } /* Now code the block flags */ if ( BListIndex > 0 ) { /* Code the block flags start value */ val = cpi->BlockCodedFlags[0]; oggpackB_write( cpi->oggbuffer, (ogg_uint32_t)val, 1); /* Now code the block flags. */ for ( i = 0; i < BListIndex; ) { run_count = 0; while ( (cpi->BlockCodedFlags[i] == val) && (i < BListIndex) ) { i++; run_count++; } FrArrayCodeBlockRun( cpi, run_count ); val = ( val == 0 ) ? 1 : 0; } } }
/**************************************************************************** * * 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++; } } }
/**************************************************************************** * * ROUTINE : DecodeModes * * INPUTS : None. * * OUTPUTS : Reconstructed frame. * * RETURNS : None. * * FUNCTION : Decodes the coding mode list for this frame. * * SPECIAL NOTES : None. * * * ERRORS : None. * ****************************************************************************/ void DecodeModes( 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 CODING_MODE CodingMethod; // Temp Storage for coding mode. UINT32 UVRow; UINT32 UVColumn; UINT32 UVFragOffset; UINT32 CodingScheme; // Coding scheme used to code modes. UINT32 MBListIndex = 0; UINT32 i; // If the frame is an intra frame then all blocks have mode intra. if ( GetFrameType(pbi) == BASE_FRAME ) { for ( i = 0; i < pbi->UnitFragments; i++ ) { pbi->FragCodingMethod[i] = CODE_INTRA; } } else { UINT32 ModeEntry; // Mode bits read // Read the coding method CodingScheme = bitread( &pbi->br, MODE_METHOD_BITS ); // If the coding method is method 0 then we have to read in a custom coding scheme if ( CodingScheme == 0 ) { // Read the coding scheme. for ( i = 0; i < MAX_MODES; i++ ) { ModeAlphabet[0][ bitread( &pbi->br, MODE_BITS) ] = (CODING_MODE)i; } } // 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 // top left block will have a negative Fragment Index. if ( QuadMapToMBTopLeft(pbi->BlockMap, SB,MB) >= 0 ) { // Is the Macro-Block coded: if ( pbi->MBCodedFlags[MBListIndex++] ) { // Upack the block level modes and motion vectors FragIndex = QuadMapToMBTopLeft( pbi->BlockMap, SB, MB ); // Unpack the mode. if ( CodingScheme == (MODE_METHODS-1) ) { // This is the fall back coding scheme. // Simply MODE_BITS bits per mode entry. CodingMethod = (CODING_MODE)bitread( &pbi->br, MODE_BITS ); } else { ModeEntry = FrArrayUnpackMode(pbi); CodingMethod = ModeAlphabet[CodingScheme][ ModeEntry ]; } // Note the coding mode for each block in macro block. pbi->FragCodingMethod[FragIndex] = CodingMethod; pbi->FragCodingMethod[FragIndex + 1] = CodingMethod; pbi->FragCodingMethod[FragIndex + pbi->HFragments] = CodingMethod; pbi->FragCodingMethod[FragIndex + pbi->HFragments + 1] = CodingMethod; // 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->FragCodingMethod[pbi->YPlaneFragments + UVFragOffset] = CodingMethod; pbi->FragCodingMethod[pbi->YPlaneFragments + pbi->UVPlaneFragments + UVFragOffset] = CodingMethod; } } } // Next Super-Block SB++; } } } }