//!< 运动估计(基本思想就是用TZSearch算法先进行整像素搜索,确定一个局部的最佳值,然后以这个最佳点为中心再进行精度更高的分像素搜索。)
Void TEncSearch::xMotionEstimation( TComDataCU* pcCU,
TComYuv* pcYuvOrg,
Int iPartIdx,
RefPicList eRefPicList,
TComMv* pcMvPred,
Int iRefIdxPred,
TComMv& rcMv,
UInt& ruiBits,
UInt& ruiCost,
Bool bBi )
{
UInt uiPartAddr;
Int iRoiWidth;
Int iRoiHeight;
TComMv cMvHalf, cMvQter;
TComMv cMvSrchRngLT;
TComMv cMvSrchRngRB;
TComYuv* pcYuv = pcYuvOrg;
m_iSearchRange = m_aaiAdaptSR[eRefPicList][iRefIdxPred];//!< 根据参考帧列表类型、参考帧序号自适应设置搜索范围
Int iSrchRng = ( bBi ? m_bipredSearchRange : m_iSearchRange ); //!< 根据是否是双向预测设置搜索范围
TComPattern* pcPatternKey = pcCU->getPattern ();//!< 用于获取neighbor的信息
Double fWeight = 1.0;
pcCU->getPartIndexAndSize( iPartIdx, uiPartAddr, iRoiWidth, iRoiHeight );//!< 获取PU的地址,宽度和高度
if ( bBi )
{
TComYuv* pcYuvOther = &m_acYuvPred[1-(Int)eRefPicList];
pcYuv = &m_cYuvPredTemp;
pcYuvOrg->copyPartToPartYuv( pcYuv, uiPartAddr, iRoiWidth, iRoiHeight );
pcYuv->removeHighFreq( pcYuvOther, uiPartAddr, iRoiWidth, iRoiHeight );
fWeight = 0.5;
}
// Search key pattern initialization
pcPatternKey->initPattern( pcYuv->getLumaAddr( uiPartAddr ),
pcYuv->getCbAddr ( uiPartAddr ),
pcYuv->getCrAddr ( uiPartAddr ),
iRoiWidth,
iRoiHeight,
pcYuv->getStride(),
0, 0 );//!< 设置待搜索的PU的相关参数,首地址,宽度,高度,跨度等
//!< 获取参考图像首地址和跨度(已编码的)
Pel* piRefY = pcCU->getSlice()->getRefPic( eRefPicList, iRefIdxPred )->getPicYuvRec()->getLumaAddr( pcCU->getAddr(), pcCU->getZorderIdxInCU() + uiPartAddr );
Int iRefStride = pcCU->getSlice()->getRefPic( eRefPicList, iRefIdxPred )->getPicYuvRec()->getStride();
/***************************************************************
cout<<"iRoiWidth = "<getMotionCost ( 1, 0 );
m_pcRdCost->setPredictor ( *pcMvPred );
m_pcRdCost->setCostScale ( 2 );
setWpScalingDistParam( pcCU, iRefIdxPred, eRefPicList );//!< 设置跟weighted prediction相关的参数
// Do integer search
if ( !m_iFastSearch || bBi )
{
xPatternSearch ( pcPatternKey, piRefY, iRefStride, &cMvSrchRngLT, &cMvSrchRngRB, rcMv, ruiCost );
}
else
{
rcMv = *pcMvPred;
xPatternSearchFast ( pcCU, pcPatternKey, piRefY, iRefStride, &cMvSrchRngLT, &cMvSrchRngRB, rcMv, ruiCost );
}
m_pcRdCost->getMotionCost( 1, 0 );
m_pcRdCost->setCostScale ( 1 );
//!< 分像素搜索
xPatternSearchFracDIF( pcCU, pcPatternKey, piRefY, iRefStride, &rcMv, cMvHalf, cMvQter, ruiCost,bBi );
m_pcRdCost->setCostScale( 0 );
rcMv <<= 2;//!< 整像素
rcMv += (cMvHalf <<= 1);//!< 1/2 像素
rcMv += cMvQter;//!< 1/4 像素
//!< 故rcMv最终以1/4像素为单位
UInt uiMvBits = m_pcRdCost->getBits( rcMv.getHor(), rcMv.getVer() );
ruiBits += uiMvBits;
ruiCost = (UInt)( floor( fWeight * ( (Double)ruiCost - (Double)m_pcRdCost->getCost( uiMvBits ) ) ) + (Double)m_pcRdCost->getCost( ruiBits ) );
}