📄 motionestimation.cpp
字号:
const Int iTop = iStartY - iDist;
const Int iBottom = iStartY + iDist;
const Int iLeft = iStartX - iDist;
const Int iRight = iStartX + iDist;
rcStrukt.uiBestRound += 1;
if ( iDist == 1 ) // iDist == 1
{
if ( iTop >= -rcSearchRect.iNegVerLimit ) // check top
{
xTZSearchHelp( rcStrukt, iStartX, iTop, 2, iDist );
}
if ( iLeft >= -rcSearchRect.iNegHorLimit ) // check middle left
{
xTZSearchHelp( rcStrukt, iLeft, iStartY, 4, iDist );
}
if ( iRight <= rcSearchRect.iPosHorLimit ) // check middle right
{
xTZSearchHelp( rcStrukt, iRight, iStartY, 5, iDist );
}
if ( iBottom <= rcSearchRect.iPosVerLimit ) // check bottom
{
xTZSearchHelp( rcStrukt, iStartX, iBottom, 7, iDist );
}
}
else // iDist == 1
{
if ( iDist <= 8 )
{
const Int iTop_2 = iStartY - (iDist>>1);
const Int iBottom_2 = iStartY + (iDist>>1);
const Int iLeft_2 = iStartX - (iDist>>1);
const Int iRight_2 = iStartX + (iDist>>1);
if ( iTop >= -rcSearchRect.iNegVerLimit && iLeft >= -rcSearchRect.iNegHorLimit &&
iRight <= rcSearchRect.iPosHorLimit && iBottom <= rcSearchRect.iPosVerLimit ) // check border
{
xTZSearchHelp( rcStrukt, iStartX, iTop, 2, iDist );
xTZSearchHelp( rcStrukt, iLeft_2, iTop_2, 1, iDist>>1 );
xTZSearchHelp( rcStrukt, iRight_2, iTop_2, 3, iDist>>1 );
xTZSearchHelp( rcStrukt, iLeft, iStartY, 4, iDist );
xTZSearchHelp( rcStrukt, iRight, iStartY, 5, iDist );
xTZSearchHelp( rcStrukt, iLeft_2, iBottom_2, 6, iDist>>1 );
xTZSearchHelp( rcStrukt, iRight_2, iBottom_2, 8, iDist>>1 );
xTZSearchHelp( rcStrukt, iStartX, iBottom, 7, iDist );
}
else // check border
{
if ( iTop >= -rcSearchRect.iNegVerLimit ) // check top
{
xTZSearchHelp( rcStrukt, iStartX, iTop, 2, iDist );
}
if ( iTop_2 >= -rcSearchRect.iNegVerLimit ) // check half top
{
if ( iLeft_2 >= -rcSearchRect.iNegHorLimit ) // check half left
{
xTZSearchHelp( rcStrukt, iLeft_2, iTop_2, 1, (iDist>>1) );
}
if ( iRight_2 <= rcSearchRect.iPosHorLimit ) // check half right
{
xTZSearchHelp( rcStrukt, iRight_2, iTop_2, 3, (iDist>>1) );
}
} // check half top
if ( iLeft >= -rcSearchRect.iNegHorLimit ) // check left
{
xTZSearchHelp( rcStrukt, iLeft, iStartY, 4, iDist );
}
if ( iRight <= rcSearchRect.iPosHorLimit ) // check right
{
xTZSearchHelp( rcStrukt, iRight, iStartY, 5, iDist );
}
if ( iBottom_2 <= rcSearchRect.iPosVerLimit ) // check half bottom
{
if ( iLeft_2 >= -rcSearchRect.iNegHorLimit ) // check half left
{
xTZSearchHelp( rcStrukt, iLeft_2, iBottom_2, 6, (iDist>>1) );
}
if ( iRight_2 <= rcSearchRect.iPosHorLimit ) // check half right
{
xTZSearchHelp( rcStrukt, iRight_2, iBottom_2, 8, (iDist>>1) );
}
} // check half bottom
if ( iBottom <= rcSearchRect.iPosVerLimit ) // check bottom
{
xTZSearchHelp( rcStrukt, iStartX, iBottom, 7, iDist );
}
} // check border
}
else // iDist <= 8
{
if ( iTop >= -rcSearchRect.iNegVerLimit && iLeft >= -rcSearchRect.iNegHorLimit &&
iRight <= rcSearchRect.iPosHorLimit && iBottom <= rcSearchRect.iPosVerLimit ) // check border
{
xTZSearchHelp( rcStrukt, iStartX, iTop, 0, iDist );
xTZSearchHelp( rcStrukt, iLeft, iStartY, 0, iDist );
xTZSearchHelp( rcStrukt, iRight, iStartY, 0, iDist );
xTZSearchHelp( rcStrukt, iStartX, iBottom, 0, iDist );
for ( Int index = 1; index < 4; index++ )
{
Int iPosYT = iTop + ((iDist>>2) * index);
Int iPosYB = iBottom - ((iDist>>2) * index);
Int iPosXL = iStartX - ((iDist>>2) * index);
Int iPosXR = iStartX + ((iDist>>2) * index);
xTZSearchHelp( rcStrukt, iPosXL, iPosYT, 0, iDist );
xTZSearchHelp( rcStrukt, iPosXR, iPosYT, 0, iDist );
xTZSearchHelp( rcStrukt, iPosXL, iPosYB, 0, iDist );
xTZSearchHelp( rcStrukt, iPosXR, iPosYB, 0, iDist );
}
}
else // check border
{
if ( iTop >= -rcSearchRect.iNegVerLimit ) // check top
{
xTZSearchHelp( rcStrukt, iStartX, iTop, 0, iDist );
}
if ( iLeft >= -rcSearchRect.iNegHorLimit ) // check left
{
xTZSearchHelp( rcStrukt, iLeft, iStartY, 0, iDist );
}
if ( iRight <= rcSearchRect.iPosHorLimit ) // check right
{
xTZSearchHelp( rcStrukt, iRight, iStartY, 0, iDist );
}
if ( iBottom <= rcSearchRect.iPosVerLimit ) // check bottom
{
xTZSearchHelp( rcStrukt, iStartX, iBottom, 0, iDist );
}
for ( Int index = 1; index < 4; index++ )
{
Int iPosYT = iTop + ((iDist>>2) * index);
Int iPosYB = iBottom - ((iDist>>2) * index);
Int iPosXL = iStartX - ((iDist>>2) * index);
Int iPosXR = iStartX + ((iDist>>2) * index);
if ( iPosYT >= -rcSearchRect.iNegVerLimit ) // check top
{
if ( iPosXL >= -rcSearchRect.iNegHorLimit ) // check left
{
xTZSearchHelp( rcStrukt, iPosXL, iPosYT, 0, iDist );
}
if ( iPosXR <= rcSearchRect.iPosHorLimit ) // check right
{
xTZSearchHelp( rcStrukt, iPosXR, iPosYT, 0, iDist );
}
} // check top
if ( iPosYB <= rcSearchRect.iPosVerLimit ) // check bottom
{
if ( iPosXL >= -rcSearchRect.iNegHorLimit ) // check left
{
xTZSearchHelp( rcStrukt, iPosXL, iPosYB, 0, iDist );
}
if ( iPosXR <= rcSearchRect.iPosHorLimit ) // check right
{
xTZSearchHelp( rcStrukt, iPosXR, iPosYB, 0, iDist );
}
} // check bottom
} // for ...
} // check border
} // iDist <= 8
} // iDist == 1
}
Void MotionEstimation::xTZSearch( YuvPicBuffer *pcPelData, Mv& rcMv, UInt& ruiSAD, Int iSearchRange )
{
TZ_SEARCH_CONFIGURATION
// limit search range
if( ! iSearchRange ) { iSearchRange = m_cParams.getSearchRange(); }
rcMv.limitComponents(MotionCompensation::m_cMin, MotionCompensation::m_cMax );
SearchRect cSearchRect;
rcMv >>= 2;
cSearchRect.init( iSearchRange, rcMv, MotionCompensation::m_cMin, MotionCompensation::m_cMax );
// init TZSearchStrukt
IntTZSearchStrukt cStrukt;
cStrukt.iYStride = pcPelData->getLStride();
cStrukt.iCStride = pcPelData->getCStride();
m_cXDSS.iYStride = cStrukt.iYStride;
m_cXDSS.iCStride = cStrukt.iCStride;
cStrukt.pucYRef = pcPelData->getLumBlk();
cStrukt.pucURef = pcPelData->getCbBlk ();
cStrukt.pucVRef = pcPelData->getCrBlk ();
cStrukt.uiBestSad = MSYS_UINT_MAX;
// set rcMv as start point and as best point
xTZSearchHelp( cStrukt, rcMv.getHor(), rcMv.getVer(), 0, 0 );
if( bTestOtherPredictedMV )
{
for( UInt index = 0; index < 3; index++ )
{
Mv cMv = m_acMvPredictors[index];
cMv.limitComponents( MotionCompensation::m_cMin, MotionCompensation::m_cMax );
cMv >>= 2;
xTZSearchHelp( cStrukt, cMv.getHor(), cMv.getVer(), 0, 0 );
}
}
// test whether zerovektor is a better start point than the current rcMv
if( bTestZeroVector )
{
xTZSearchHelp( cStrukt, 0, 0, 0, 0 );
}
// start search // ucPointNr
Int iDist = 0; // 1 2 3
Int iStartX = cStrukt.iBestX; // 4 0 5
Int iStartY = cStrukt.iBestY; // 6 7 8
// fist search
for( iDist = 1; iDist <= iSearchRange; iDist*=2 )
{
if( bFirstSearchDiamond == 1 )
{
xTZ8PointDiamondSearch( cStrukt, cSearchRect, iStartX, iStartY, iDist );
}
else
{
xTZ8PointSquareSearch( cStrukt, cSearchRect, iStartX, iStartY, iDist );
}
if( bFirstSearchStop && (cStrukt.uiBestRound >= uiFirstSearchRounds) ) // stop criterion
{
break;
}
}
// test whether zerovektor is a better start point than current rcMv
if( bTestZeroVectorStar && ((cStrukt.iBestX != 0) || (cStrukt.iBestY != 0)) )
{
xTZSearchHelp( cStrukt, 0, 0, 0, 0 );
if( (cStrukt.iBestX == 0) && (cStrukt.iBestY == 0) )
{
// test his neighborhood
for( iDist = 1; iDist <= iSearchRange; iDist*=2 )
{
xTZ8PointDiamondSearch( cStrukt, cSearchRect, 0, 0, iDist );
if( bTestZeroVectorStop && (cStrukt.uiBestRound > 0) ) // stop criterion
{
break;
}
}
}
}
// calculate only 2 missing points instead 8 points if cStrukt.uiBestDistance == 1
if( cStrukt.uiBestDistance == 1 )
{
cStrukt.uiBestDistance = 0;
xTZ2PointSearch( cStrukt, cSearchRect );
}
// raster search if distance is to big
if( bEnableRasterSearch && ( (cStrukt.uiBestDistance > iRaster) || bAlwaysRasterSearch ) )
{
cStrukt.uiBestDistance = iRaster;
for( iStartY = -cSearchRect.iNegVerLimit; iStartY <= cSearchRect.iPosVerLimit; iStartY += iRaster )
{
for( iStartX = -cSearchRect.iNegHorLimit; iStartX <= cSearchRect.iPosHorLimit; iStartX += iRaster )
{
xTZSearchHelp( cStrukt, iStartX, iStartY, 0, iRaster );
}
}
}
// raster refinement
if( bRasterRefinementEnable && cStrukt.uiBestDistance > 0 )
{
while( cStrukt.uiBestDistance > 0 )
{
iStartX = cStrukt.iBestX;
iStartY = cStrukt.iBestY;
if( cStrukt.uiBestDistance > 1 )
{
iDist = cStrukt.uiBestDistance >>= 1;
if( bRasterRefinementDiamond == 1 )
{
xTZ8PointDiamondSearch( cStrukt, cSearchRect, iStartX, iStartY, iDist );
}
else
{
xTZ8PointSquareSearch( cStrukt, cSearchRect, iStartX, iStartY, iDist );
}
}
// calculate only 2 missing points instead 8 points if cStrukt.uiBestDistance == 1
if( cStrukt.uiBestDistance == 1 )
{
cStrukt.uiBestDistance = 0;
if( cStrukt.ucPointNr != 0 )
{
xTZ2PointSearch( cStrukt, cSearchRect );
}
}
}
}
// star refinement
if( bStarRefinementEnable && cStrukt.uiBestDistance > 0 )
{
while( cStrukt.uiBestDistance > 0 )
{
iStartX = cStrukt.iBestX;
iStartY = cStrukt.iBestY;
cStrukt.uiBestDistance = 0;
cStrukt.ucPointNr = 0;
for( iDist = 1; iDist < iSearchRange + 1; iDist*=2 )
{
if( bStarRefinementDiamond == 1 )
{
xTZ8PointDiamondSearch( cStrukt, cSearchRect, iStartX, iStartY, iDist );
}
else
{
xTZ8PointSquareSearch( cStrukt, cSearchRect, iStartX, iStartY, iDist );
}
if( bStarRefinementStop && (cStrukt.uiBestRound >= uiStarRefinementRounds) ) // stop criterion
{
break;
}
}
// calculate only 2 missing points instead 8 points if cStrukt.uiBestDistance == 1
if( cStrukt.uiBestDistance == 1 )
{
cStrukt.uiBestDistance = 0;
if( cStrukt.ucPointNr != 0 )
{
xTZ2PointSearch( cStrukt, cSearchRect );
}
}
}
}
// write out best match
ruiSAD = cStrukt.uiBestSad - MotionEstimationCost::xGetCost( cStrukt.iBestX, cStrukt.iBestY);
rcMv.setHor( cStrukt.iBestX );
rcMv.setVer( cStrukt.iBestY );
// test for errors in debug mode
DO_DBG( m_cXDSS.pYSearch = cStrukt.pucYRef + cStrukt.iBestY * cStrukt.iYStride + cStrukt.iBestX );
DO_DBG( m_cXDSS.pUSearch = cStrukt.pucURef + (cStrukt.iBestY>>1) * cStrukt.iCStride + (cStrukt.iBestX>>1) );
DO_DBG( m_cXDSS.pVSearch = cStrukt.pucVRef + (cStrukt.iBestY>>1) * cStrukt.iCStride + (cStrukt.iBestX>>1) );
AOF_DBG( ruiSAD == ( m_cXDSS.Func( &m_cXDSS ) ) );
}
H264AVC_NAMESPACE_END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -