📄 motionestimation.cpp
字号:
if( ! bQPelRefinementOnly )
{
if( uiSearchRange )
{
xPelBlockSearch ( 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( 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;
}
ErrVal MotionEstimation::initMb( UInt uiMbPosY, UInt uiMbPosX, MbDataAccess& rcMbDataAccess )
{
RNOK( MotionCompensation::initMb( uiMbPosY, uiMbPosX, rcMbDataAccess) );// TMM_INTERLACE
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++ )
{
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 ) ) );
}
Void MotionEstimation::xPelSpiralSearch( IntYuvPicBuffer *pcPelData, Mv& rcMv, UInt& ruiSAD, UInt uiSearchRange )
{
if( ! uiSearchRange )
{
uiSearchRange = m_cParams.getSearchRange();
}
m_cXDSS.iYStride = pcPelData->getLStride();
m_cXDSS.iCStride = pcPelData->getCStride();
XPel* pucYRef = pcPelData->getLumBlk();
XPel* pucURef = pcPelData->getCbBlk ();
XPel* pucVRef = pcPelData->getCrBlk ();
UInt uiSad;
UInt uiBestPos = 0;
Mv cLimitMv( 4*uiSearchRange, 4*uiSearchRange );
Mv cMin = m_cMin + cLimitMv;
Mv cMax = m_cMax - cLimitMv;
rcMv.limitComponents( cMin, cMax );
rcMv >>= 2;
ruiSAD = MSYS_UINT_MAX;
for( UInt n = 0; n < m_uiSpiralSearchEntries; n++ )
{
Int x = rcMv.getHor() + m_pcMvSpiralSearch[n].getHor();
Int y = rcMv.getVer() + m_pcMvSpiralSearch[n].getVer();
m_cXDSS.pYSearch = pucYRef + y * m_cXDSS.iYStride + x;
m_cXDSS.pUSearch = pucURef + (y>>1) * m_cXDSS.iCStride + (x>>1);
m_cXDSS.pVSearch = pucVRef + (y>>1) * m_cXDSS.iCStride + (x>>1);
uiSad = m_cXDSS.Func( &m_cXDSS );
uiSad += xGetCost( x, y );
if( ruiSAD > uiSad )
{
ruiSAD = uiSad;
uiBestPos = n;
}
}
rcMv += m_pcMvSpiralSearch[uiBestPos];
Int y = rcMv.getVer();
Int x = rcMv.getHor();
ruiSAD -= xGetCost( x, y);
DO_DBG( m_cXDSS.pYSearch = pucYRef + y * m_cXDSS.iYStride + x );
DO_DBG( m_cXDSS.pUSearch = pucURef + (y>>1) * m_cXDSS.iCStride + (x>>1) );
DO_DBG( m_cXDSS.pVSearch = pucVRef + (y>>1) * m_cXDSS.iCStride + (x>>1) );
AOF_DBG( ruiSAD == ( uiSad = m_cXDSS.Func( &m_cXDSS ) ) );
}
Void MotionEstimation::xPelLogSearch( IntYuvPicBuffer *pcPelData, Mv& rcMv, UInt& ruiSAD, Bool bFme, UInt uiStep, UInt uiSearchRange )
{
if( ! uiSearchRange )
{
uiSearchRange = m_cParams.getSearchRange();
}
XPel* pucRef = pcPelData->getLumBlk();
XPel* pucSearch;
Int iStride = pcPelData->getLStride();
UInt uiSad;
UInt uiBestSad;
Int iStepSizeStart = uiStep;
Mv cMvPred = rcMv;
cMvPred.limitComponents( m_cMin, m_cMax );
cMvPred >>= 2;
SearchRect cSearchRect;
cSearchRect.init( uiSearchRange, cMvPred, m_cMin, m_cMax );
rcMv.limitComponents( m_cMin, m_cMax );
rcMv >>= 2;
m_cXDSS.iYStride = iStride;
m_cXDSS.pYSearch = pucRef + rcMv.getHor() + rcMv.getVer() * iStride;
uiBestSad = m_cXDSS.Func( &m_cXDSS );
uiBestSad += xGetCost( rcMv.getHor(), rcMv.getVer() );
if( bFme )
{
for( UInt n = 0; n < 3; n++ )
{
Mv cMv = m_acMvPredictors[n];
{
cMv.limitComponents( m_cMin, m_cMax );
cMv >>= 2;
XPel* pStart = pucRef + cMv.getHor() + cMv.getVer() * iStride;
m_cXDSS.pYSearch = pStart;
uiSad = m_cXDSS.Func( &m_cXDSS );
uiSad += xGetCost( cMv.getHor(), cMv.getVer());
if( uiBestSad > uiSad )
{
uiBestSad = uiSad;
rcMv = cMv;
}
}
}
}
Int x = rcMv.getHor();
Int y = rcMv.getVer();
pucSearch = pucRef + x + y * iStride;
Int dxOld = 0;
Int dyOld = 0;
Bool bContinue;
Int iStepStride;
Int iStep;
for( iStep = iStepSizeStart; iStep != 0; iStep >>= 1 )
{
bContinue = true;
iStepStride = iStep * iStride;
dxOld = 0;
dyOld = 0;
while( ruiSAD && bContinue )
{
Int dx = 0;
Int dy = 0;
if( dxOld <= 0 && -x <= cSearchRect.iNegHorLimit - iStep )
{
m_cXDSS.pYSearch = pucSearch - iStep;
uiSad = m_cXDSS.Func( &m_cXDSS );
uiSad += xGetCost( x - iStep, y);
if( uiBestSad > uiSad )
{
uiBestSad = uiSad;
dx = -iStep;
}
}
if( dxOld >= 0 && x < cSearchRect.iPosHorLimit - iStep)
{
m_cXDSS.pYSearch = pucSearch + iStep;
uiSad = m_cXDSS.Func( &m_cXDSS );
uiSad += xGetCost( x + iStep, y);
if( uiBestSad > uiSad )
{
uiBestSad = uiSad;
dx = iStep;
}
}
if( dyOld <= 0 && -y <= cSearchRect.iNegVerLimit - iStep)
{
m_cXDSS.pYSearch = pucSearch - iStepStride;
uiSad = m_cXDSS.Func( &m_cXDSS );
uiSad += xGetCost( x, y - iStep );
if( uiBestSad > uiSad )
{
uiBestSad = uiSad;
dx = 0;
dy = -iStep;
}
}
if( dyOld >= 0 && y < cSearchRect.iPosVerLimit - iStep)
{
m_cXDSS.pYSearch = pucSearch + iStepStride;
uiSad = m_cXDSS.Func( &m_cXDSS );
uiSad += xGetCost( x, y + iStep );
if( uiBestSad > uiSad )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -