📄 motionestimation.cpp
字号:
{
xPelLogSearch ( pcRefPelData[0], cMv, uiMinSAD, false, m_iMaxLogStep << ((NULL == pcBSP) ? 1 : 0) );
}
break;
case 3:
{
rcMbDataAccess.getMvPredictors( m_acMvPredictors );
xPelLogSearch ( pcRefPelData[0], cMv, uiMinSAD, true, (NULL == pcBSP) ? 2 : 1 );
}
break;
case 4:
{
rcMbDataAccess.getMvPredictors( m_acMvPredictors );
xTZSearch( pcRefPelData[0], cMv, uiMinSAD );
}
break;
default:
RERR();
break;
}
}
cMv <<= 2;
}
else
{
Mv cMvBase = cMv;
cMv.limitComponents( m_cMin, m_cMax );
if( ! ( cMvBase == cMv ) )
{
// don't refine in that case
rcMv = cMvBase;
ruiBits += 2;
ruiCost = MSYS_UINT_MAX / 2;
// >>>> bug fix by H.Schwarz 19/9/05
if( bOriginalSearchModeIsYUVSAD )
{
m_cParams.setFullPelDFunc( DF_YUV_SAD );
}
// <<<< bug fix by H.Schwarz 19/9/05
return Err::m_nOK;
}
}
// heiko.schwarz@hhi.fhg.de (fix for uninitialized memory with YUV_SAD and bi-directional search) >>>>
if( bOriginalSearchModeIsYUVSAD )
{
m_cParams.setFullPelDFunc( DF_YUV_SAD );
}
// <<< heiko.schwarz@hhi.fhg.de (fix for uninitialized memory with YUV_SAD and bi-directional search)
//===== SUB-PEL ESTIMATION =====
xGetMotionCost( 1 != ( 1 & m_cParams.getSubPelDFunc() ), 0 );
m_pcXDistortion->getDistStruct( uiMode, m_cParams.getSubPelDFunc(), false, m_cXDSS );
m_cXDSS.pYOrg = pcWeightedYuvBuffer->getLumBlk();
xSetCostScale( 0 );
xSubPelSearch( pcRefPelData[1], cMv, uiMinSAD, uiBlk, uiMode, bQPelRefinementOnly );
Short sHor = cMv.getHor();
Short sVer = cMv.getVer();
UInt uiMvBits = xGetBits( sHor, sVer );
ruiBits += uiMvBits;
ruiCost = (UInt)floor( fWeight * (Double)( uiMinSAD - xGetCost( uiMvBits ) ) ) + xGetCost( ruiBits );
rcMv = cMv;
return Err::m_nOK;
}
#if JMVM_ONLY // JVT-U052
ErrVal
MotionEstimation::estimateBlockWithStart( Icp& rcIcp,
const MbDataAccess& rcMbDataAccess,
const IntFrame& rcRefFrame,
Mv& rcMv, // <-- MVSTART / --> MV
Mv& rcMvPred,
UInt& ruiBits,
UInt& ruiCost,
UInt uiBlk,
UInt uiMode,
Bool bQPelRefinementOnly,
UInt uiSearchRange,
const PW* pcPW,
MEBiSearchParameters* pcBSP )
{
const LumaIdx cIdx = B4x4Idx(uiBlk);
IntYuvMbBuffer* pcWeightedYuvBuffer = NULL;
IntYuvPicBuffer* pcRefPelData[2];
IntYuvMbBuffer cWeightedYuvBuffer;
pcRefPelData[0] = const_cast<IntFrame&>(rcRefFrame).getFullPelYuvBuffer();
pcRefPelData[1] = const_cast<IntFrame&>(rcRefFrame).getHalfPelYuvBuffer();
m_pcXDistortion->set4x4Block( cIdx );
pcRefPelData[0]->set4x4Block( cIdx );
pcRefPelData[1]->set4x4Block( cIdx );
if( bQPelRefinementOnly ) rcMv = rcMvPred;
UInt uiMinSAD = MSYS_UINT_MAX;
Mv cMv = rcMv;
Double fWeight = 1.0;
Double afCW[2] = { 1.0, 1.0 };
Icp cIcp = rcIcp;
Bool bOriginalSearchModeIsYUVSAD = ( m_cParams.getFullPelDFunc() == DF_YUV_SAD );
const Int iXSize = m_pcXDistortion->getBlockWidth ( uiMode );
const Int iYSize = m_pcXDistortion->getBlockHeight ( uiMode );
if( pcBSP ) // bi prediction
{
ROF( pcBSP->pcAltRefPelData );
ROF( pcBSP->pcAltRefFrame );
ROF( pcBSP->apcWeight[LIST_0] );
ROF( pcBSP->apcWeight[LIST_1] );
pcWeightedYuvBuffer = &cWeightedYuvBuffer;
pcWeightedYuvBuffer ->set4x4Block( cIdx );
pcBSP->pcAltRefPelData->set4x4Block( cIdx );
if( rcMbDataAccess.getSH().getPPS().getWeightedBiPredIdc() == 2 ) // implicit weighting
{
//----- get implicit weights -----
PW acIPW[2];
const IntFrame* pcFrameL0 = ( pcBSP->uiL1Search ? pcBSP->pcAltRefFrame : &rcRefFrame );
const IntFrame* pcFrameL1 = ( pcBSP->uiL1Search ? &rcRefFrame : pcBSP->pcAltRefFrame );
Int iScale = rcMbDataAccess.getSH().getDistScaleFactorWP( pcFrameL0, pcFrameL1 );
//----- weighting -----
if( iScale == 128 ) // same distance -> use normal function for same result
{
m_pcSampleWeighting->inverseLumaSamples ( pcWeightedYuvBuffer,
m_pcXDistortion->getYuvMbBuffer(),
pcBSP->pcAltRefPelData,
iYSize, iXSize );
fWeight = 0.5;
}
else
{
acIPW[1].scaleL1Weight( iScale );
acIPW[0].scaleL0Weight( acIPW[1] );
m_pcSampleWeighting->weightInverseLumaSamples ( pcWeightedYuvBuffer,
m_pcXDistortion->getYuvMbBuffer(),
pcBSP->pcAltRefPelData,
&acIPW[pcBSP->uiL1Search],
&acIPW[1-pcBSP->uiL1Search],
fWeight, iYSize, iXSize );
}
}
else if( pcBSP->apcWeight[LIST_0]->getLumaWeightFlag() ||
pcBSP->apcWeight[LIST_1]->getLumaWeightFlag() )
{
//----- explicit weighting -----
m_pcSampleWeighting->weightInverseLumaSamples ( pcWeightedYuvBuffer,
m_pcXDistortion->getYuvMbBuffer(),
pcBSP->pcAltRefPelData,
pcBSP->apcWeight[pcBSP->uiL1Search],
pcBSP->apcWeight[1-pcBSP->uiL1Search],
fWeight, iYSize, iXSize );
}
else
{
//----- standard weighting -----
m_pcSampleWeighting->inverseLumaSamples ( pcWeightedYuvBuffer,
m_pcXDistortion->getYuvMbBuffer(),
pcBSP->pcAltRefPelData,
iYSize, iXSize );
fWeight = 0.5;
}
}
else // unidirectional prediction
{
ROF( pcPW );
if( pcPW->getLumaWeightFlag() || ( bOriginalSearchModeIsYUVSAD && pcPW->getChromaWeightFlag() ) )
{
pcWeightedYuvBuffer = &cWeightedYuvBuffer;
pcWeightedYuvBuffer ->set4x4Block( cIdx );
//----- weighting -----
m_pcSampleWeighting->weightInverseLumaSamples ( pcWeightedYuvBuffer,
m_pcXDistortion->getYuvMbBuffer(),
pcPW, fWeight, iYSize, iXSize );
if( bOriginalSearchModeIsYUVSAD )
{
m_pcSampleWeighting->weightInverseChromaSamples( pcWeightedYuvBuffer,
m_pcXDistortion->getYuvMbBuffer(),
pcPW, afCW, iYSize, iXSize );
}
}
else
{
//----- no weighting -----
pcWeightedYuvBuffer = m_pcXDistortion->getYuvMbBuffer();
fWeight = afCW[0] = afCW[1] = 1.0;
}
}
//===== FULL-PEL ESTIMATION ======
if( bOriginalSearchModeIsYUVSAD && ( pcBSP /* bi-prediction */ || fWeight != afCW[0] || fWeight != afCW[1] /* different component weights */ ) )
{
m_cParams.setFullPelDFunc( DF_SAD ); // set to normal SAD
}
// <<< heiko.schwarz@hhi.fhg.de (fix for uninitialized memory with YUV_SAD and bi-directional search)
xGetMotionCost( ( 1 != m_cParams.getFullPelDFunc() ), 0 );
m_pcXDistortion->getDistStruct( uiMode, m_cParams.getFullPelDFunc(), false, m_cXDSS );
m_cXDSS.pYOrg = pcWeightedYuvBuffer->getLumBlk();
m_cXDSS.pUOrg = pcWeightedYuvBuffer->getCbBlk ();
m_cXDSS.pVOrg = pcWeightedYuvBuffer->getCrBlk ();
xSetPredictor( rcMvPred );
xSetCostScale( 2 );
if( ! bQPelRefinementOnly )
{
if( uiSearchRange )
{
xPelBlockSearch ( cIcp, pcRefPelData[0], cMv, uiMinSAD, uiSearchRange );
}
else
{
switch( m_cParams.getSearchMode() )
{
case 0:
{
xPelBlockSearch ( pcRefPelData[0], cMv, uiMinSAD );
}
break;
case 1:
{
xPelSpiralSearch( pcRefPelData[0], cMv, uiMinSAD );
}
break;
case 2:
{
xPelLogSearch ( pcRefPelData[0], cMv, uiMinSAD, false, m_iMaxLogStep << ((NULL == pcBSP) ? 1 : 0) );
}
break;
case 3:
{
rcMbDataAccess.getMvPredictors( m_acMvPredictors );
xPelLogSearch ( pcRefPelData[0], cMv, uiMinSAD, true, (NULL == pcBSP) ? 2 : 1 );
}
break;
case 4:
{
rcMbDataAccess.getMvPredictors( m_acMvPredictors );
xTZSearch( cIcp, pcRefPelData[0], cMv, uiMinSAD );
}
break;
default:
ROT(1);
break;
}
}
cMv <<= 2;
}
else
{
Mv cMvBase = cMv;
cMv.limitComponents( m_cMin, m_cMax );
if( ! ( cMvBase == cMv ) )
{
// don't refine in that case
rcMv = cMvBase;
ruiBits += 2;
ruiCost = MSYS_UINT_MAX / 2;
// >>>> bug fix by H.Schwarz 19/9/05
if( bOriginalSearchModeIsYUVSAD )
{
m_cParams.setFullPelDFunc( DF_YUV_SAD );
}
// <<<< bug fix by H.Schwarz 19/9/05
return Err::m_nOK;
}
}
// heiko.schwarz@hhi.fhg.de (fix for uninitialized memory with YUV_SAD and bi-directional search) >>>>
if( bOriginalSearchModeIsYUVSAD )
{
m_cParams.setFullPelDFunc( DF_YUV_SAD );
}
// <<< heiko.schwarz@hhi.fhg.de (fix for uninitialized memory with YUV_SAD and bi-directional search)
//===== SUB-PEL ESTIMATION =====
xGetMotionCost( 1 != ( 1 & m_cParams.getSubPelDFunc() ), 0 );
m_pcXDistortion->getDistStruct( uiMode, m_cParams.getSubPelDFunc(), false, m_cXDSS );
m_cXDSS.pYOrg = pcWeightedYuvBuffer->getLumBlk();
xSetCostScale( 0 );
xSubPelSearch( cIcp, pcRefPelData[1], cMv, uiMinSAD, uiBlk, uiMode, bQPelRefinementOnly );
Short sHor = cMv.getHor();
Short sVer = cMv.getVer();
UInt uiMvBits = xGetBits( sHor, sVer );
ruiBits += uiMvBits;
ruiCost = (UInt)floor( fWeight * (Double)( uiMinSAD - xGetCost( uiMvBits ) ) ) + xGetCost( ruiBits );
rcMv = cMv;
rcIcp = cIcp;
return Err::m_nOK;
}
#endif
ErrVal MotionEstimation::initMb( UInt uiMbPosY, UInt uiMbPosX, MbDataAccess& rcMbDataAccess )
{
RNOK( MotionCompensation::initMb( uiMbPosY, uiMbPosX) );
return Err::m_nOK;
}
Void MotionEstimation::xPelBlockSearch( IntYuvPicBuffer *pcPelData, Mv& rcMv, UInt& ruiSAD, UInt uiSearchRange )
{
if( ! uiSearchRange )
{
uiSearchRange = m_cParams.getSearchRange();
}
Int iYStride = pcPelData->getLStride();
XPel* pucYRef = pcPelData->getLumBlk ();
XPel* pucYSearch;
Int iCStride = pcPelData->getCStride();
XPel* pucURef = pcPelData->getCbBlk ();
XPel* pucVRef = pcPelData->getCrBlk ();
UInt uiSad;
Int y = 0;
Int x = 0;
m_cXDSS.iYStride = iYStride;
m_cXDSS.iCStride = iCStride;
ruiSAD = MSYS_UINT_MAX;
rcMv.limitComponents( m_cMin, m_cMax );
rcMv >>= 2;
SearchRect cSearchRect;
cSearchRect.init( uiSearchRange, rcMv, m_cMin, m_cMax );
pucYSearch = pucYRef - iYStride * (cSearchRect.iNegVerLimit);
for( y = -cSearchRect.iNegVerLimit; y <= cSearchRect.iPosVerLimit; y++ )
{
for( x = -cSearchRect.iNegHorLimit; x <= cSearchRect.iPosHorLimit; x++ )
{
//JVT-W080 BUG_FIX
if( OmitPDISearch( x, y+rcMv.getVer(),false ) )
continue;
//~JVT-W080 BUG_FIX
m_cXDSS.pYSearch = pucYSearch + x;
m_cXDSS.pUSearch = pucURef + (y>>1)*iCStride + (x>>1);
m_cXDSS.pVSearch = pucVRef + (y>>1)*iCStride + (x>>1);
uiSad = m_cXDSS.Func( &m_cXDSS );
uiSad += xGetCost( x, y);
if( ruiSAD > uiSad )
{
ruiSAD = uiSad;
rcMv.setVer( y );
rcMv.setHor( x );
}
}
pucYSearch += iYStride;
}
y = rcMv.getVer();
x = rcMv.getHor();
ruiSAD -= xGetCost( x, y);
DO_DBG( m_cXDSS.pYSearch = pucYRef + y * iYStride + x );
DO_DBG( m_cXDSS.pUSearch = pucURef + (y>>1) * iCStride + (x>>1) );
DO_DBG( m_cXDSS.pVSearch = pucVRef + (y>>1) * iCStride + (x>>1) );
uiSad = m_cXDSS.Func( &m_cXDSS );
AOF_DBG( ruiSAD == ( uiSad = m_cXDSS.Func( &m_cXDSS ) ) );
}
//JVT-W080 BUG_FIX
Bool MotionEstimation::OmitPDISearch( Int x, Int y, Bool bQPel ) // x, y: motion vector corresponding to pel/sub-pel
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -