📄 decode.c
字号:
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 next-to-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++; } }}static ogg_uint32_t ExtractToken(oggpack_buffer *opb, HUFF_ENTRY * CurrentRoot){ long ret; ogg_uint32_t 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 ){ theora_read(opb, 1, &ret); if (ret < 0) break; /* out of packet data! */ if (ret) CurrentRoot = CurrentRoot->OneChild; else CurrentRoot = CurrentRoot->ZeroChild; } Token = CurrentRoot->Value; return Token;}static void UnpackAndExpandDcToken( PB_INSTANCE *pbi, Q_LIST_ENTRY *ExpandedBlock, unsigned char * CoeffIndex ){ long ret; ogg_int32_t ExtraBits = 0; ogg_uint32_t Token; Token = ExtractToken(pbi->opb, pbi->HuffRoot_VP3x[pbi->DcHuffChoice]); /* Now.. if we are using the DCT optimised coding system, extract any * assosciated additional bits token. */ if ( pbi->ExtraBitLengths_VP3x[Token] > 0 ){ /* Extract the appropriate number of extra bits. */ theora_read(pbi->opb,pbi->ExtraBitLengths_VP3x[Token], &ret); ExtraBits = ret; } /* Take token dependant action */ if ( Token >= DCT_SHORT_ZRL_TOKEN ) { /* "Value", "zero run" and "zero run value" tokens */ ExpandToken(ExpandedBlock, CoeffIndex, Token, ExtraBits ); if ( *CoeffIndex >= BLOCK_SIZE ) pbi->BlocksToDecode --; } else if ( Token == DCT_EOB_TOKEN ){ *CoeffIndex = BLOCK_SIZE; pbi->BlocksToDecode --; }else{ /* Special action and EOB tokens */ switch ( Token ){ case DCT_EOB_PAIR_TOKEN: pbi->EOB_Run = 1; *CoeffIndex = BLOCK_SIZE; pbi->BlocksToDecode --; break; case DCT_EOB_TRIPLE_TOKEN: pbi->EOB_Run = 2; *CoeffIndex = BLOCK_SIZE; pbi->BlocksToDecode --; break; case DCT_REPEAT_RUN_TOKEN: pbi->EOB_Run = ExtraBits + 3; *CoeffIndex = BLOCK_SIZE; pbi->BlocksToDecode --; break; case DCT_REPEAT_RUN2_TOKEN: pbi->EOB_Run = ExtraBits + 7; *CoeffIndex = BLOCK_SIZE; pbi->BlocksToDecode --; break; case DCT_REPEAT_RUN3_TOKEN: pbi->EOB_Run = ExtraBits + 15; *CoeffIndex = BLOCK_SIZE; pbi->BlocksToDecode --; break; case DCT_REPEAT_RUN4_TOKEN: pbi->EOB_Run = ExtraBits - 1; *CoeffIndex = BLOCK_SIZE; pbi->BlocksToDecode --; break; } }}static void UnpackAndExpandAcToken( PB_INSTANCE *pbi, Q_LIST_ENTRY * ExpandedBlock, unsigned char * CoeffIndex ) { long ret; ogg_int32_t ExtraBits = 0; ogg_uint32_t Token; Token = ExtractToken(pbi->opb, pbi->HuffRoot_VP3x[pbi->ACHuffChoice]); /* Now.. if we are using the DCT optimised coding system, extract any * assosciated additional bits token. */ if ( pbi->ExtraBitLengths_VP3x[Token] > 0 ){ /* Extract the appropriate number of extra bits. */ theora_read(pbi->opb,pbi->ExtraBitLengths_VP3x[Token], &ret); ExtraBits = ret; } /* Take token dependant action */ if ( Token >= DCT_SHORT_ZRL_TOKEN ){ /* "Value", "zero run" and "zero run value" tokens */ ExpandToken(ExpandedBlock, CoeffIndex, Token, ExtraBits ); if ( *CoeffIndex >= BLOCK_SIZE ) pbi->BlocksToDecode --; } else if ( Token == DCT_EOB_TOKEN ) { *CoeffIndex = BLOCK_SIZE; pbi->BlocksToDecode --; } else { /* Special action and EOB tokens */ switch ( Token ) { case DCT_EOB_PAIR_TOKEN: pbi->EOB_Run = 1; *CoeffIndex = BLOCK_SIZE; pbi->BlocksToDecode --; break; case DCT_EOB_TRIPLE_TOKEN: pbi->EOB_Run = 2; *CoeffIndex = BLOCK_SIZE; pbi->BlocksToDecode --; break; case DCT_REPEAT_RUN_TOKEN: pbi->EOB_Run = ExtraBits + 3; *CoeffIndex = BLOCK_SIZE; pbi->BlocksToDecode --; break; case DCT_REPEAT_RUN2_TOKEN: pbi->EOB_Run = ExtraBits + 7; *CoeffIndex = BLOCK_SIZE; pbi->BlocksToDecode --; break; case DCT_REPEAT_RUN3_TOKEN: pbi->EOB_Run = ExtraBits + 15; *CoeffIndex = BLOCK_SIZE; pbi->BlocksToDecode --; break; case DCT_REPEAT_RUN4_TOKEN: pbi->EOB_Run = ExtraBits - 1; *CoeffIndex = BLOCK_SIZE; pbi->BlocksToDecode --; break; } }}static void UnPackVideo (PB_INSTANCE *pbi){ long ret; ogg_int32_t EncodedCoeffs = 1; ogg_int32_t FragIndex; ogg_int32_t * CodedBlockListPtr; ogg_int32_t * CodedBlockListEnd; unsigned char AcHuffIndex1; unsigned char AcHuffIndex2; unsigned char AcHuffChoice1; unsigned char AcHuffChoice2; unsigned char DcHuffChoice1; unsigned char DcHuffChoice2; /* Bail out immediately if a decode error has already been reported. */ if ( pbi->DecoderErrorCode ) return; /* Clear down the array that indicates the current coefficient index for each block. */ memset(pbi->FragCoeffs, 0, pbi->UnitFragments); memset(pbi->FragCoefEOB, 0, pbi->UnitFragments); /* Clear down the pbi->QFragData structure for all coded blocks. */ ClearDownQFragData(pbi); /* Note the number of blocks to decode */ pbi->BlocksToDecode = pbi->CodedBlockIndex; /* Get the DC huffman table choice for Y and then UV */ theora_read(pbi->opb,DC_HUFF_CHOICE_BITS,&ret); DcHuffChoice1 = ret + DC_HUFF_OFFSET; if (ret < 0 || DcHuffChoice1 >= NUM_HUFF_TABLES) { DcHuffChoice1 = DC_HUFF_OFFSET; pbi->DecoderErrorCode = 1; } theora_read(pbi->opb,DC_HUFF_CHOICE_BITS,&ret); DcHuffChoice2 = ret + DC_HUFF_OFFSET; if (ret < 0 || DcHuffChoice2 >= NUM_HUFF_TABLES) { DcHuffChoice2 = DC_HUFF_OFFSET; pbi->DecoderErrorCode = 1; } /* UnPack DC coefficients / tokens */ CodedBlockListPtr = pbi->CodedBlockList; CodedBlockListEnd = &pbi->CodedBlockList[pbi->CodedBlockIndex]; while ( CodedBlockListPtr < CodedBlockListEnd ) { /* Get the block data index */ FragIndex = *CodedBlockListPtr; pbi->FragCoefEOB[FragIndex] = pbi->FragCoeffs[FragIndex]; /* Select the appropriate huffman table offset according to whether the token is from a Y or UV block */ if ( FragIndex < (ogg_int32_t)pbi->YPlaneFragments ) pbi->DcHuffChoice = DcHuffChoice1; else pbi->DcHuffChoice = DcHuffChoice2; /* If we are in the middle of an EOB run */ if ( pbi->EOB_Run ){ /* Mark the current block as fully expanded and decrement EOB_RUN count */ pbi->FragCoeffs[FragIndex] = BLOCK_SIZE; pbi->EOB_Run --; pbi->BlocksToDecode --; }else{ /* Else unpack a DC token */ UnpackAndExpandDcToken( pbi, pbi->QFragData[FragIndex], &pbi->FragCoeffs[FragIndex] ); } CodedBlockListPtr++; } /* Get the AC huffman table choice for Y and then for UV. */ theora_read(pbi->opb,AC_HUFF_CHOICE_BITS,&ret); AcHuffIndex1 = ret + AC_HUFF_OFFSET; if (ret < 0 || AcHuffIndex1 >= NUM_HUFF_TABLES) { AcHuffIndex1 = AC_HUFF_OFFSET; pbi->DecoderErrorCode = 1; } theora_read(pbi->opb,AC_HUFF_CHOICE_BITS,&ret); AcHuffIndex2 = ret + AC_HUFF_OFFSET; if (ret < 0 || AcHuffIndex2 >= NUM_HUFF_TABLES) { AcHuffIndex2 = AC_HUFF_OFFSET; pbi->DecoderErrorCode = 1; } /* Unpack Lower AC coefficients. */ while ( EncodedCoeffs < 64 ) { /* Repeatedly scan through the list of blocks. */ CodedBlockListPtr = pbi->CodedBlockList; CodedBlockListEnd = &pbi->CodedBlockList[pbi->CodedBlockIndex]; /* Huffman table selection based upon which AC coefficient we are on */ if ( EncodedCoeffs <= AC_TABLE_2_THRESH ){ AcHuffChoice1 = AcHuffIndex1; AcHuffChoice2 = AcHuffIndex2; }else if ( EncodedCoeffs <= AC_TABLE_3_THRESH ){ AcHuffChoice1 = AcHuffIndex1 + AC_HUFF_CHOICES; AcHuffChoice2 = AcHuffIndex2 + AC_HUFF_CHOICES; } else if ( EncodedCoeffs <= AC_TABLE_4_THRESH ){ AcHuffChoice1 = AcHuffIndex1 + (AC_HUFF_CHOICES * 2); AcHuffChoice2 = AcHuffIndex2 + (AC_HUFF_CHOICES * 2); } else { AcHuffChoice1 = AcHuffIndex1 + (AC_HUFF_CHOICES * 3); AcHuffChoice2 = AcHuffIndex2 + (AC_HUFF_CHOICES * 3); } while( CodedBlockListPtr < CodedBlockListEnd ) { /* Get the linear index for the current fragment. */ FragIndex = *CodedBlockListPtr; /* Should we decode a token for this block on this pass. */ if ( pbi->FragCoeffs[FragIndex] <= EncodedCoeffs ) { pbi->FragCoefEOB[FragIndex] = pbi->FragCoeffs[FragIndex]; /* If we are in the middle of an EOB run */ if ( pbi->EOB_Run ) { /* Mark the current block as fully expanded and decrement EOB_RUN count */ pbi->FragCoeffs[FragIndex] = BLOCK_SIZE; pbi->EOB_Run --; pbi->BlocksToDecode --; }else{ /* Else unpack an AC token */ /* Work out which huffman table to use, then decode a token */ if ( FragIndex < (ogg_int32_t)pbi->YPlaneFragments ) pbi->ACHuffChoice = AcHuffChoice1; else pbi->ACHuffChoice = AcHuffChoice2; UnpackAndExpandAcToken( pbi, pbi->QFragData[FragIndex], &pbi->FragCoeffs[FragIndex] ); } } CodedBlockListPtr++; } /* Test for condition where there are no blocks left with any tokesn to decode */ if ( !pbi->BlocksToDecode ) break; EncodedCoeffs ++; }}static void DecodeData(PB_INSTANCE *pbi){ ogg_uint32_t i; /* Bail out immediately if a decode error has already been reported. */ if ( pbi->DecoderErrorCode ) return; /* Clear down the macro block level mode and MV arrays. */ for ( i = 0; i < pbi->UnitFragments; i++ ){ pbi->FragCodingMethod[i] = CODE_INTER_NO_MV; /* Default coding mode */ pbi->FragMVect[i].x = 0; pbi->FragMVect[i].y = 0; } /* Zero Decoder EOB run count */ pbi->EOB_Run = 0; /* Make a note of the number of coded blocks this frame */ pbi->CodedBlocksThisFrame = pbi->CodedBlockIndex; /* Decode the modes data */ DecodeModes( pbi, pbi->YSBRows, pbi->YSBCols); if (pbi->DecoderErrorCode) return; /* Unpack and decode the motion vectors. */ DecodeMVectors ( pbi, pbi->YSBRows, pbi->YSBCols); if (pbi->DecoderErrorCode) return; /* Unpack and decode the actual video data. */ UnPackVideo(pbi); if (pbi->DecoderErrorCode) return; /* Reconstruct and display the frame */ dsp_save_fpu (pbi->dsp); ReconRefFrames(pbi); dsp_restore_fpu (pbi->dsp);}int LoadAndDecode(PB_INSTANCE *pbi){ /* Reset the DC predictors. */ pbi->InvLastIntraDC = 0; pbi->InvLastInterDC = 0; if ( LoadFrame(pbi) == 0 ){ pbi->LastFrameQualityValue = pbi->ThisFrameQualityValue; /* Decode the data into the fragment buffer. */ DecodeData(pbi); if (pbi->DecoderErrorCode == 0) return 0; } return OC_BADPACKET;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -