📄 decode.c
字号:
/* 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)
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;
theora_read(pbi->opb,DC_HUFF_CHOICE_BITS,&ret);
DcHuffChoice2 = ret + DC_HUFF_OFFSET;
/* 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;
theora_read(pbi->opb,AC_HUFF_CHOICE_BITS,&ret);
AcHuffIndex2 = ret + AC_HUFF_OFFSET;
/* 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);
/* Unpack and decode the motion vectors. */
DecodeMVectors ( pbi, pbi->YSBRows, pbi->YSBCols);
/* Unpack and decode the actual video data. */
UnPackVideo(pbi);
/* Reconstruct and display the frame */
ReconRefFrames(pbi);
}
int LoadAndDecode(PB_INSTANCE *pbi){
int LoadFrameOK;
/* Reset the DC predictors. */
pbi->InvLastIntraDC = 0;
pbi->InvLastInterDC = 0;
/* Load the next frame. */
LoadFrameOK = LoadFrame(pbi);
if ( LoadFrameOK ){
pbi->LastFrameQualityValue = pbi->ThisFrameQualityValue;
/* Decode the data into the fragment buffer. */
DecodeData(pbi);
return(0);
}
return(OC_BADPACKET);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -