📄 encode.c
字号:
}
cpi->MinImprovementForFourMV = cpi->MinImprovementForNewMV * 4;
if(cpi->MinImprovementForFourMV < (40<<12))
cpi->MinImprovementForFourMV = (40<<12);
cpi->FourMvChangeFactor = 8; /* cpi->MVChangeFactor - 0.05; */
/* decide what block type and motion vectors to use on all of the frames */
for ( SBrow=0; SBrow<SBRows; SBrow++ ) {
for ( SBcol=0; SBcol<SBCols; SBcol++ ) {
/* Check its four Macro-Blocks */
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(cpi->pb.BlockMap,SB,MB) < 0 ) continue;
/* Is the current macro block coded (in part or in whole) */
MBCodedFlag = 0;
for ( B=0; B<4; B++ ) {
YFragIndex = QuadMapToIndex1( cpi->pb.BlockMap, SB, MB, B );
/* Does Block lie in frame: */
if ( YFragIndex >= 0 ) {
/* In Frame: Is it coded: */
if ( cpi->pb.display_fragments[YFragIndex] ) {
MBCodedFlag = 1;
break;
}
} else
MBCodedFlag = 0;
}
/* This one isn't coded go to the next one */
if(!MBCodedFlag) continue;
/* Calculate U and V FragIndex from YFragIndex */
YFragIndex = QuadMapToMBTopLeft(cpi->pb.BlockMap, SB,MB);
UVRow = (YFragIndex / (cpi->pb.HFragments * 2));
UVColumn = (YFragIndex % cpi->pb.HFragments) / 2;
UVFragOffset = (UVRow * (cpi->pb.HFragments / 2)) + UVColumn;
UFragIndex = cpi->pb.YPlaneFragments + UVFragOffset;
VFragIndex = cpi->pb.YPlaneFragments + cpi->pb.UVPlaneFragments +
UVFragOffset;
/**************************************************************
Find the block choice with the lowest error
NOTE THAT if U or V is coded but no Y from a macro block then
the mode will be CODE_INTER_NO_MV as this is the default
state to which the mode data structure is initialised in
encoder and decoder at the start of each frame. */
BestError = HUGE_ERROR;
/* Look at the intra coding error. */
MBIntraError = GetMBIntraError( cpi, YFragIndex, PixelsPerLine );
BestError = (BestError > MBIntraError) ? MBIntraError : BestError;
/* Get the golden frame error */
MBGFError = GetMBInterError( cpi, cpi->ConvDestBuffer,
cpi->pb.GoldenFrame, YFragIndex,
0, 0, PixelsPerLine );
BestError = (BestError > MBGFError) ? MBGFError : BestError;
/* Calculate the 0,0 case. */
MBInterError = GetMBInterError( cpi, cpi->ConvDestBuffer,
cpi->pb.LastFrameRecon,
YFragIndex, 0, 0, PixelsPerLine );
BestError = (BestError > MBInterError) ? MBInterError : BestError;
/* Measure error for last MV */
MBLastInterError = GetMBInterError( cpi, cpi->ConvDestBuffer,
cpi->pb.LastFrameRecon,
YFragIndex, LastInterMVect.x,
LastInterMVect.y, PixelsPerLine );
BestError = (BestError > MBLastInterError) ?
MBLastInterError : BestError;
/* Measure error for prior last MV */
MBPriorLastInterError = GetMBInterError( cpi, cpi->ConvDestBuffer,
cpi->pb.LastFrameRecon,
YFragIndex,
PriorLastInterMVect.x,
PriorLastInterMVect.y,
PixelsPerLine );
BestError = (BestError > MBPriorLastInterError) ?
MBPriorLastInterError : BestError;
/* Temporarily force usage of no motionvector blocks */
MBInterMVError = HUGE_ERROR;
InterMVect.x = 0; /* Set 0,0 motion vector */
InterMVect.y = 0;
/* If the best error is above the required threshold search
for a new inter MV */
if ( BestError > cpi->MinImprovementForNewMV ) {
/* Use a mix of heirachical and exhaustive searches for
quick mode. */
if ( cpi->pb.info.quick_p ) {
MBInterMVError = GetMBMVInterError( cpi, cpi->pb.LastFrameRecon,
YFragIndex, PixelsPerLine,
cpi->MVPixelOffsetY,
&InterMVect );
/* If we still do not have a good match try an exhaustive
MBMV search */
if ( (MBInterMVError > cpi->ExhaustiveSearchThresh) &&
(BestError > cpi->ExhaustiveSearchThresh) ) {
MBInterMVExError =
GetMBMVExhaustiveSearch( cpi, cpi->pb.LastFrameRecon,
YFragIndex, PixelsPerLine,
&InterMVectEx );
/* Is the Variance measure for the EX search
better... If so then use it. */
if ( MBInterMVExError < MBInterMVError ) {
MBInterMVError = MBInterMVExError;
InterMVect.x = InterMVectEx.x;
InterMVect.y = InterMVectEx.y;
}
}
}else{
/* Use an exhaustive search */
MBInterMVError =
GetMBMVExhaustiveSearch( cpi, cpi->pb.LastFrameRecon,
YFragIndex, PixelsPerLine,
&InterMVect );
}
/* Is the improvement, if any, good enough to justify a new MV */
if ( (16 * MBInterMVError < (BestError * cpi->MVChangeFactor)) &&
((MBInterMVError + cpi->MinImprovementForNewMV) < BestError) ){
BestError = MBInterMVError;
}
}
/* If the best error is still above the required threshold
search for a golden frame MV */
MBGF_MVError = HUGE_ERROR;
GFMVect.x = 0; /* Set 0,0 motion vector */
GFMVect.y = 0;
if ( BestError > cpi->MinImprovementForNewMV ) {
/* Do an MV search in the golden reference frame */
MBGF_MVError = GetMBMVInterError( cpi, cpi->pb.GoldenFrame,
YFragIndex, PixelsPerLine,
cpi->MVPixelOffsetY, &GFMVect );
/* Measure error for last GFMV */
LastMBGF_MVError = GetMBInterError( cpi, cpi->ConvDestBuffer,
cpi->pb.GoldenFrame,
YFragIndex, LastGFMVect.x,
LastGFMVect.y, PixelsPerLine );
/* Check against last GF motion vector and reset if the
search has thrown a worse result. */
if ( LastMBGF_MVError < MBGF_MVError ) {
GFMVect.x = LastGFMVect.x;
GFMVect.y = LastGFMVect.y;
MBGF_MVError = LastMBGF_MVError;
}else{
LastGFMVect.x = GFMVect.x;
LastGFMVect.y = GFMVect.y;
}
/* Is the improvement, if any, good enough to justify a new MV */
if ( (16 * MBGF_MVError < (BestError * cpi->MVChangeFactor)) &&
((MBGF_MVError + cpi->MinImprovementForNewMV) < BestError) ) {
BestError = MBGF_MVError;
}
}
/* Finally... If the best error is still to high then consider
the 4MV mode */
MBInterFOURMVError = HUGE_ERROR;
if ( BestError > cpi->FourMVThreshold ) {
/* Get the 4MV error. */
MBInterFOURMVError =
GetFOURMVExhaustiveSearch( cpi, cpi->pb.LastFrameRecon,
YFragIndex, PixelsPerLine, FourMVect );
/* If the improvement is great enough then use the four MV mode */
if ( ((MBInterFOURMVError + cpi->MinImprovementForFourMV) <
BestError) && (16 * MBInterFOURMVError <
(BestError * cpi->FourMvChangeFactor))) {
BestError = MBInterFOURMVError;
}
}
/********************************************************
end finding the best error
*******************************************************
Figure out what to do with the block we chose
Over-ride and force intra if error high and Intra error similar
Now choose a mode based on lowest error (with bias towards no MV) */
if ( (BestError > cpi->InterTripOutThresh) &&
(10 * BestError > MBIntraError * 7 ) ) {
cpi->MBCodingMode = CODE_INTRA;
SetMBMotionVectorsAndMode(cpi,YFragIndex,UFragIndex,
VFragIndex,&ZeroVect);
} else if ( BestError == MBInterError ) {
cpi->MBCodingMode = CODE_INTER_NO_MV;
SetMBMotionVectorsAndMode(cpi,YFragIndex,UFragIndex,
VFragIndex,&ZeroVect);
} else if ( BestError == MBGFError ) {
cpi->MBCodingMode = CODE_USING_GOLDEN;
SetMBMotionVectorsAndMode(cpi,YFragIndex,UFragIndex,
VFragIndex,&ZeroVect);
} else if ( BestError == MBLastInterError ) {
cpi->MBCodingMode = CODE_INTER_LAST_MV;
SetMBMotionVectorsAndMode(cpi,YFragIndex,UFragIndex,
VFragIndex,&LastInterMVect);
} else if ( BestError == MBPriorLastInterError ) {
cpi->MBCodingMode = CODE_INTER_PRIOR_LAST;
SetMBMotionVectorsAndMode(cpi,YFragIndex,UFragIndex,
VFragIndex,&PriorLastInterMVect);
/* Swap the prior and last MV cases over */
TmpMVect.x = PriorLastInterMVect.x;
TmpMVect.y = PriorLastInterMVect.y;
PriorLastInterMVect.x = LastInterMVect.x;
PriorLastInterMVect.y = LastInterMVect.y;
LastInterMVect.x = TmpMVect.x;
LastInterMVect.y = TmpMVect.y;
} else if ( BestError == MBInterMVError ) {
cpi->MBCodingMode = CODE_INTER_PLUS_MV;
SetMBMotionVectorsAndMode(cpi,YFragIndex,UFragIndex,
VFragIndex,&InterMVect);
/* Update Prior last mv with last mv */
PriorLastInterMVect.x = LastInterMVect.x;
PriorLastInterMVect.y = LastInterMVect.y;
/* Note last inter MV for future use */
LastInterMVect.x = InterMVect.x;
LastInterMVect.y = InterMVect.y;
AddMotionVector( cpi, &InterMVect);
} else if ( BestError == MBGF_MVError ) {
cpi->MBCodingMode = CODE_GOLDEN_MV;
SetMBMotionVectorsAndMode(cpi,YFragIndex,UFragIndex,
VFragIndex,&GFMVect);
/* Note last inter GF MV for future use */
LastGFMVect.x = GFMVect.x;
LastGFMVect.y = GFMVect.y;
AddMotionVector( cpi, &GFMVect);
} else if ( BestError == MBInterFOURMVError ) {
cpi->MBCodingMode = CODE_INTER_FOURMV;
/* Calculate the UV vectors as the average of the Y plane ones. */
/* First .x component */
FourMVect[4].x = FourMVect[0].x + FourMVect[1].x +
FourMVect[2].x + FourMVect[3].x;
if ( FourMVect[4].x >= 0 )
FourMVect[4].x = (FourMVect[4].x + 2) / 4;
else
FourMVect[4].x = (FourMVect[4].x - 2) / 4;
FourMVect[5].x = FourMVect[4].x;
/* Then .y component */
FourMVect[4].y = FourMVect[0].y + FourMVect[1].y +
FourMVect[2].y + FourMVect[3].y;
if ( FourMVect[4].y >= 0 )
FourMVect[4].y = (FourMVect[4].y + 2) / 4;
else
FourMVect[4].y = (FourMVect[4].y - 2) / 4;
FourMVect[5].y = FourMVect[4].y;
SetFragMotionVectorAndMode(cpi, YFragIndex, &FourMVect[0]);
SetFragMotionVectorAndMode(cpi, YFragIndex + 1, &FourMVect[1]);
SetFragMotionVectorAndMode(cpi, YFragIndex + cpi->pb.HFragments,
&FourMVect[2]);
SetFragMotionVectorAndMode(cpi, YFragIndex + cpi->pb.HFragments + 1,
&FourMVect[3]);
SetFragMotionVectorAndMode(cpi, UFragIndex, &FourMVect[4]);
SetFragMotionVectorAndMode(cpi, VFragIndex, &FourMVect[5]);
/* Note the four MVs values for current macro-block. */
AddMotionVector( cpi, &FourMVect[0]);
AddMotionVector( cpi, &FourMVect[1]);
AddMotionVector( cpi, &FourMVect[2]);
AddMotionVector( cpi, &FourMVect[3]);
/* Update Prior last mv with last mv */
PriorLastInterMVect.x = LastInterMVect.x;
PriorLastInterMVect.y = LastInterMVect.y;
/* Note last inter MV for future use */
LastInterMVect.x = FourMVect[3].x;
LastInterMVect.y = FourMVect[3].y;
} else {
cpi->MBCodingMode = CODE_INTRA;
SetMBMotionVectorsAndMode(cpi,YFragIndex,UFragIndex,
VFragIndex,&ZeroVect);
}
/* setting up mode specific block types
*******************************************************/
*InterError += (BestError>>8);
*IntraError += (MBIntraError>>8);
}
SB++;
}
}
/* Return number of pixels coded */
return 0;
}
void WriteFrameHeader( CP_INSTANCE *cpi) {
ogg_uint32_t i;
oggpack_buffer *opb=cpi->oggbuffer;
/* Output the frame type (base/key frame or inter frame) */
oggpackB_write( opb, cpi->pb.FrameType, 1 );
/* Write out details of the current value of Q... variable resolution. */
for ( i = 0; i < Q_TABLE_SIZE; i++ ) {
if ( cpi->pb.ThisFrameQualityValue == cpi->pb.QThreshTable[i] ) {
oggpackB_write( opb, i, 6 );
break;
}
}
if ( i == Q_TABLE_SIZE ) {
/* An invalid DCT value was specified. */
/*IssueWarning( "Invalid Q Multiplier" );*/
oggpackB_write( opb, 31, 6 );
}
/* we only support one Q index per frame */
oggpackB_write( opb, 0, 1 );
/* If the frame was a base frame then write out the frame dimensions. */
if ( cpi->pb.FrameType == KEY_FRAME ) {
/* Key frame type / method */
oggpackB_write( opb, cpi->pb.KeyFrameType, 1 );
/* Spare configuration bits */
oggpackB_write( opb, 0, 2 );
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -