上一次我们学习了运动估计中使用的插值滤波器函数,这次来看具体的分像素差值函数xPatternSearchFracDIF。
在运动估计中,首先进行整像素的搜索,确定一个最优MV,然后在进行分像素搜索,得到以1/4为单位的MV。其分像素搜索通过xPatternSearchFracDIF函数实现,代码如下,主要功能是对Y分量进行亚像素搜索。首先进行1/2像素插值,然后进行1/4像素插值,最终得到以1/4为单位的MV。
Void TEncSearch::xPatternSearchFracDIF(
Bool bIsLosslessCoded,
TComPattern* pcPatternKey,
Pel* piRefY,
Int iRefStride,
TComMv* pcMvInt,
TComMv& rcMvHalf,
TComMv& rcMvQter,
Distortion& ruiCost
)
{
// Reference pattern initialization (integer scale)
TComPattern cPatternRoi;
Int iOffset = pcMvInt->getHor() + pcMvInt->getVer() * iRefStride; //MV_Hor + MV_Ver * Block_width
cPatternRoi.initPattern(piRefY + iOffset,
pcPatternKey->getROIYWidth(),
pcPatternKey->getROIYHeight(),
iRefStride,
pcPatternKey->getBitDepthY());
// Half-pel refinement
xExtDIFUpSamplingH ( &cPatternRoi ); //1/2像素插值
rcMvHalf = *pcMvInt; rcMvHalf <<= 1; // for mv-cost
TComMv baseRefMv(0, 0);
ruiCost = xPatternRefinement( pcPatternKey, baseRefMv, 2, rcMvHalf, !bIsLosslessCoded ); //计算以1/2单位的MV的代价
m_pcRdCost->setCostScale( 0 );
xExtDIFUpSamplingQ ( &cPatternRoi, rcMvHalf ); //1/4像素插值
baseRefMv = rcMvHalf;
baseRefMv <<= 1;
rcMvQter = *pcMvInt; rcMvQter <<= 1; // for mv-cost
rcMvQter += rcMvHalf; rcMvQter <<= 1;
ruiCost = xPatternRefinement( pcPatternKey, baseRefMv, 1, rcMvQter, !bIsLosslessCoded ); //计算以1/4单位的MV的代价
}
xExtDIFUpSamplingH为1/2像素插值,得到以1/2为单位的MV。
Void TEncSearch::xExtDIFUpSamplingH( TComPattern* pattern )
{
Int width = pattern->getROIYWidth();
Int height = pattern->getROIYHeight();
Int srcStride = pattern->getPatternLStride();
Int intStride = m_filteredBlockTmp[0].getStride(COMPONENT_Y); //m_iWidth
Int dstStride = m_filteredBlock[0][0].getStride(COMPONENT_Y); //m_iWidth
Pel *intPtr;
Pel *dstPtr;
Int filterSize = NTAPS_LUMA; //8
Int halfFilterSize = (filterSize>>1); //4
Pel *srcPtr = pattern->getROIY() - halfFilterSize*srcStride - 1;
const ChromaFormat chFmt = m_filteredBlock[0][0].getChromaFormat(); //色度格式
m_if.filterHor(COMPONENT_Y, srcPtr, srcStride, m_filteredBlockTmp[0].getAddr(COMPONENT_Y), intStride, width+1, height+filterSize, 0, false, chFmt, pattern->getBit