📄 encode.c
字号:
oggpack_buffer *opb=cpi->oggbuffer;
/* Choose the coding method */
MvBitsPtr = &MvBits[MAX_MV_EXTENT];
for ( i = 0; i < (ogg_int32_t)cpi->MvListCount; i++ ) {
MethodBits[0] += MvBitsPtr[cpi->MVList[i].x];
MethodBits[0] += MvBitsPtr[cpi->MVList[i].y];
MethodBits[1] += 12; /* Simple six bits per mv component fallback
mechanism */
}
/* Select entropy table */
if ( MethodBits[0] < MethodBits[1] ) {
oggpackB_write( opb, 0, 1 );
MvBitsPtr = &MvBits[MAX_MV_EXTENT];
MvPatternPtr = &MvPattern[MAX_MV_EXTENT];
}else{
oggpackB_write( opb, 1, 1 );
MvBitsPtr = &MvBits2[MAX_MV_EXTENT];
MvPatternPtr = &MvPattern2[MAX_MV_EXTENT];
}
/* Pack and encode the motion vectors */
for ( i = 0; i < (ogg_int32_t)cpi->MvListCount; i++ ) {
oggpackB_write( opb, MvPatternPtr[cpi->MVList[i].x],
(ogg_uint32_t)MvBitsPtr[cpi->MVList[i].x] );
oggpackB_write( opb, MvPatternPtr[cpi->MVList[i].y],
(ogg_uint32_t)MvBitsPtr[cpi->MVList[i].y] );
}
}
static void PackEOBRun( CP_INSTANCE *cpi) {
if(cpi->RunLength == 0)
return;
/* Note the appropriate EOB or EOB run token and any extra bits in
the optimised token list. Use the huffman index assosciated with
the first token in the run */
/* Mark out which plane the block belonged to */
cpi->OptimisedTokenListPl[cpi->OptimisedTokenCount] =
(unsigned char)cpi->RunPlaneIndex;
/* Note the huffman index to be used */
cpi->OptimisedTokenListHi[cpi->OptimisedTokenCount] =
(unsigned char)cpi->RunHuffIndex;
if ( cpi->RunLength <= 3 ) {
if ( cpi->RunLength == 1 ) {
cpi->OptimisedTokenList[cpi->OptimisedTokenCount] = DCT_EOB_TOKEN;
} else if ( cpi->RunLength == 2 ) {
cpi->OptimisedTokenList[cpi->OptimisedTokenCount] = DCT_EOB_PAIR_TOKEN;
} else {
cpi->OptimisedTokenList[cpi->OptimisedTokenCount] = DCT_EOB_TRIPLE_TOKEN;
}
cpi->RunLength = 0;
} else {
/* Choose a token appropriate to the run length. */
if ( cpi->RunLength < 8 ) {
cpi->OptimisedTokenList[cpi->OptimisedTokenCount] =
DCT_REPEAT_RUN_TOKEN;
cpi->OptimisedTokenListEb[cpi->OptimisedTokenCount] =
cpi->RunLength - 4;
cpi->RunLength = 0;
} else if ( cpi->RunLength < 16 ) {
cpi->OptimisedTokenList[cpi->OptimisedTokenCount] =
DCT_REPEAT_RUN2_TOKEN;
cpi->OptimisedTokenListEb[cpi->OptimisedTokenCount] =
cpi->RunLength - 8;
cpi->RunLength = 0;
} else if ( cpi->RunLength < 32 ) {
cpi->OptimisedTokenList[cpi->OptimisedTokenCount] =
DCT_REPEAT_RUN3_TOKEN;
cpi->OptimisedTokenListEb[cpi->OptimisedTokenCount] =
cpi->RunLength - 16;
cpi->RunLength = 0;
} else if ( cpi->RunLength < 4096) {
cpi->OptimisedTokenList[cpi->OptimisedTokenCount] =
DCT_REPEAT_RUN4_TOKEN;
cpi->OptimisedTokenListEb[cpi->OptimisedTokenCount] =
cpi->RunLength;
cpi->RunLength = 0;
}
}
cpi->OptimisedTokenCount++;
/* Reset run EOB length */
cpi->RunLength = 0;
}
static void PackToken ( CP_INSTANCE *cpi, ogg_int32_t FragmentNumber,
ogg_uint32_t HuffIndex ) {
ogg_uint32_t Token =
cpi->pb.TokenList[FragmentNumber][cpi->FragTokens[FragmentNumber]];
ogg_uint32_t ExtraBitsToken =
cpi->pb.TokenList[FragmentNumber][cpi->FragTokens[FragmentNumber] + 1];
ogg_uint32_t OneOrTwo;
ogg_uint32_t OneOrZero;
/* Update the record of what coefficient we have got up to for this
block and unpack the encoded token back into the quantised data
array. */
if ( Token == DCT_EOB_TOKEN )
cpi->pb.FragCoeffs[FragmentNumber] = BLOCK_SIZE;
else
ExpandToken( cpi->pb.QFragData[FragmentNumber],
&cpi->pb.FragCoeffs[FragmentNumber],
Token, ExtraBitsToken );
/* Update record of tokens coded and where we are in this fragment. */
/* Is there an extra bits token */
OneOrTwo= 1 + ( cpi->pb.ExtraBitLengths_VP3x[Token] > 0 );
/* Advance to the next real token. */
cpi->FragTokens[FragmentNumber] += (unsigned char)OneOrTwo;
/* Update the counts of tokens coded */
cpi->TokensCoded += OneOrTwo;
cpi->TokensToBeCoded -= OneOrTwo;
OneOrZero = ( FragmentNumber < (ogg_int32_t)cpi->pb.YPlaneFragments );
if ( Token == DCT_EOB_TOKEN ) {
if ( cpi->RunLength == 0 ) {
cpi->RunHuffIndex = HuffIndex;
cpi->RunPlaneIndex = 1 - OneOrZero;
}
cpi->RunLength++;
/* we have exceeded our longest run length xmit an eob run token; */
if ( cpi->RunLength == 4095 ) PackEOBRun(cpi);
}else{
/* If we have an EOB run then code it up first */
if ( cpi->RunLength > 0 ) PackEOBRun( cpi);
/* Mark out which plane the block belonged to */
cpi->OptimisedTokenListPl[cpi->OptimisedTokenCount] =
(unsigned char)(1 - OneOrZero);
/* Note the token, extra bits and hufman table in the optimised
token list */
cpi->OptimisedTokenList[cpi->OptimisedTokenCount] =
(unsigned char)Token;
cpi->OptimisedTokenListEb[cpi->OptimisedTokenCount] =
ExtraBitsToken;
cpi->OptimisedTokenListHi[cpi->OptimisedTokenCount] =
(unsigned char)HuffIndex;
cpi->OptimisedTokenCount++;
}
}
static ogg_uint32_t GetBlockReconErrorSlow( CP_INSTANCE *cpi,
ogg_int32_t BlockIndex ) {
ogg_uint32_t ErrorVal;
unsigned char * SrcDataPtr =
&cpi->ConvDestBuffer[cpi->pb.pixel_index_table[BlockIndex]];
unsigned char * RecDataPtr =
&cpi->pb.LastFrameRecon[cpi->pb.recon_pixel_index_table[BlockIndex]];
ogg_int32_t SrcStride;
ogg_int32_t RecStride;
/* Is the block a Y block or a UV block. */
if ( BlockIndex < (ogg_int32_t)cpi->pb.YPlaneFragments ) {
SrcStride = cpi->pb.info.width;
RecStride = cpi->pb.YStride;
}else{
SrcStride = cpi->pb.info.width >> 1;
RecStride = cpi->pb.UVStride;
}
ErrorVal = dsp_static_sad8x8 (SrcDataPtr, SrcStride, RecDataPtr, RecStride);
return ErrorVal;
}
static void PackCodedVideo (CP_INSTANCE *cpi) {
ogg_int32_t i;
ogg_int32_t EncodedCoeffs = 1;
ogg_int32_t FragIndex;
ogg_uint32_t HuffIndex; /* Index to group of tables used to code a token */
/* Reset the count of second order optimised tokens */
cpi->OptimisedTokenCount = 0;
cpi->TokensToBeCoded = cpi->TotTokenCount;
cpi->TokensCoded = 0;
/* Calculate the bit rate at which this frame should be capped. */
cpi->MaxBitTarget = (ogg_uint32_t)((double)(cpi->ThisFrameTargetBytes * 8) *
cpi->BitRateCapFactor);
/* Blank the various fragment data structures before we start. */
memset(cpi->pb.FragCoeffs, 0, cpi->pb.UnitFragments);
memset(cpi->FragTokens, 0, cpi->pb.UnitFragments);
/* Clear down the QFragData structure for all coded blocks. */
ClearDownQFragData(&cpi->pb);
/* The tree is not needed (implicit) for key frames */
if ( GetFrameType(&cpi->pb) != KEY_FRAME ){
/* Pack the quad tree fragment mapping. */
PackAndWriteDFArray( cpi );
}
/* Note the number of bits used to code the tree itself. */
cpi->FrameBitCount = oggpackB_bytes(cpi->oggbuffer) << 3;
/* Mode and MV data not needed for key frames. */
if ( GetFrameType(&cpi->pb) != KEY_FRAME ){
/* Pack and code the mode list. */
PackModes(cpi);
/* Pack the motion vectors */
PackMotionVectors (cpi);
}
cpi->FrameBitCount = oggpackB_bytes(cpi->oggbuffer) << 3;
/* Optimise the DC tokens */
for ( i = 0; i < cpi->pb.CodedBlockIndex; i++ ) {
/* Get the linear index for the current fragment. */
FragIndex = cpi->pb.CodedBlockList[i];
cpi->pb.FragCoefEOB[FragIndex]=(unsigned char)EncodedCoeffs;
PackToken(cpi, FragIndex, DC_HUFF_OFFSET );
}
/* Pack any outstanding EOB tokens */
PackEOBRun(cpi);
/* Now output the optimised DC token list using the appropriate
entropy tables. */
EncodeDcTokenList(cpi);
/* Work out the number of DC bits coded */
/* Optimise the AC tokens */
while ( EncodedCoeffs < 64 ) {
/* Huffman table adjustment based upon coefficient number. */
if ( EncodedCoeffs <= AC_TABLE_2_THRESH )
HuffIndex = AC_HUFF_OFFSET;
else if ( EncodedCoeffs <= AC_TABLE_3_THRESH )
HuffIndex = AC_HUFF_OFFSET + AC_HUFF_CHOICES;
else if ( EncodedCoeffs <= AC_TABLE_4_THRESH )
HuffIndex = AC_HUFF_OFFSET + (AC_HUFF_CHOICES * 2);
else
HuffIndex = AC_HUFF_OFFSET + (AC_HUFF_CHOICES * 3);
/* Repeatedly scan through the list of blocks. */
for ( i = 0; i < cpi->pb.CodedBlockIndex; i++ ) {
/* Get the linear index for the current fragment. */
FragIndex = cpi->pb.CodedBlockList[i];
/* Should we code a token for this block on this pass. */
if ( cpi->FragTokens[FragIndex] < cpi->FragTokenCounts[FragIndex]
&& cpi->pb.FragCoeffs[FragIndex] <= EncodedCoeffs ) {
/* Bit pack and a token for this block */
cpi->pb.FragCoefEOB[FragIndex]=(unsigned char)EncodedCoeffs;
PackToken( cpi, FragIndex, HuffIndex );
}
}
EncodedCoeffs ++;
}
/* Pack any outstanding EOB tokens */
PackEOBRun(cpi);
/* Now output the optimised AC token list using the appropriate
entropy tables. */
EncodeAcTokenList(cpi);
}
static ogg_uint32_t QuadCodeDisplayFragments (CP_INSTANCE *cpi) {
ogg_int32_t i,j;
ogg_uint32_t coded_pixels=0;
int QIndex;
int k,m,n;
/* predictor multiplier up-left, up, up-right,left, shift
Entries are packed in the order L, UL, U, UR, with missing entries
moved to the end (before the shift parameters). */
static const ogg_int16_t pc[16][6]={
{0,0,0,0,0,0},
{1,0,0,0,0,0}, /* PL */
{1,0,0,0,0,0}, /* PUL */
{1,0,0,0,0,0}, /* PUL|PL */
{1,0,0,0,0,0}, /* PU */
{1,1,0,0,1,1}, /* PU|PL */
{0,1,0,0,0,0}, /* PU|PUL */
{29,-26,29,0,5,31}, /* PU|PUL|PL */
{1,0,0,0,0,0}, /* PUR */
{75,53,0,0,7,127}, /* PUR|PL */
{1,1,0,0,1,1}, /* PUR|PUL */
{75,0,53,0,7,127}, /* PUR|PUL|PL */
{1,0,0,0,0,0}, /* PUR|PU */
{75,0,53,0,7,127}, /* PUR|PU|PL */
{3,10,3,0,4,15}, /* PUR|PU|PUL */
{29,-26,29,0,5,31} /* PUR|PU|PUL|PL */
};
/* boundary case bit masks. */
static const int bc_mask[8]={
/* normal case no boundary condition */
PUR|PU|PUL|PL,
/* left column */
PUR|PU,
/* top row */
PL,
/* top row, left column */
0,
/* right column */
PU|PUL|PL,
/* right and left column */
PU,
/* top row, right column */
PL,
/* top row, right and left column */
0
};
/* value left value up-left, value up, value up-right, missing
values skipped. */
int v[4];
/* fragment number left, up-left, up, up-right */
int fn[4];
/* predictor count. */
int pcount;
/*which predictor constants to use */
ogg_int16_t wpc;
/* last used inter predictor (Raster Order) */
ogg_int16_t Last[3]; /* last value used for given frame */
int FragsAcross=cpi->pb.HFragments;
int FragsDown = cpi->pb.VFragments;
int FromFragment,ToFragment;
ogg_int32_t FragIndex;
int WhichFrame;
int WhichCase;
static const ogg_int16_t Mode2Frame[] = {
1, /* CODE_INTER_NO_MV 0 => Encoded diff from same MB last frame */
0, /* CODE_INTRA 1 => DCT Encoded Block */
1, /* CODE_INTER_PLUS_MV 2 => Encoded diff from included MV MB last frame */
1, /* CODE_INTER_LAST_MV 3 => Encoded diff from MRU MV MB last frame */
1, /* CODE_INTER_PRIOR_MV 4 => Encoded diff from included 4 separate MV blocks */
2, /* CODE_USING_GOLDEN 5 => Encoded diff from same MB golden frame */
2, /* CODE_GOLDEN_MV 6 => Encoded diff from included MV MB golden frame */
1 /* CODE_INTER_FOUR_MV 7 => Encoded diff from included 4 separate MV blocks */
};
ogg_int16_t PredictedDC;
/* Initialise the coded block indices variables. These allow
subsequent linear access to the quad tree ordered list of coded
blocks */
cpi->pb.CodedBlockIndex = 0;
/* Set the inter/intra descision control variables. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -