📄 encode.c
字号:
cpi->FourMVThreshold = (2500<<12); } else { cpi->ExhaustiveSearchThresh = (250<<12); cpi->FourMVThreshold = (500<<12); } 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 + -