//!< 运动估计(基本思想就是用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 = "<<iRoiWidth<<endl; cout<<"iRoiHeight = "<<iRoiHeight<<endl; cout<<"iRefStride = "<<iRefStride<<endl; for (int y = 0; y < iRoiHeight; y++) { for(int x=0;x<iRoiWidth;x++) { if(x%16==0) cout<<endl; cout<<*(piRefY+x)<<" "; } cout<<endl<<"****************************************************************"<<"y="<<(y+1)<<endl; piRefY += iRefStride; } /***************************************************************/ TComMv cMvPred = *pcMvPred; //!< 设置运动估计的搜索范围,LeftTop & RightBottom if ( bBi ) xSetSearchRange ( pcCU, rcMv , iSrchRng, cMvSrchRngLT, cMvSrchRngRB ); else xSetSearchRange ( pcCU, cMvPred, iSrchRng, cMvSrchRngLT, cMvSrchRngRB ); m_pcRdCost->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 ) ); }