xTZSearch是interME模式的重要过程,它是inter运动估计过程中的一种整像素搜索模式。其实,VTM3.0中整像素运动估计过程与VTM1.0代码是没有区别的,xTZSearch、xTZ8PointDiamondSearch、xPatternSearchFracDIF以及xTZSearchHelp函数,基本都没有任何差别。(xPatternSearchFracDIF和xTZSearchHelp函数中有一点点iMV代码的改变)
VTM1.0代码阅读:xTZSearch函数
VTM1.0代码阅读:xTZ8PointDiamondSearch函数
VTM1.0代码阅读:xTZSearchHelp函数
VTM1.0代码阅读:xPatternSearchFracDIF函数
inline void InterSearch::xTZSearchHelp( IntTZSearchStruct& rcStruct, const int iSearchX, const int iSearchY, const uint8_t ucPointNr, const uint32_t uiDistance )
{
Distortion uiSad = 0;
// CHECK(!( !( rcStruct.searchRange.left > iSearchX || rcStruct.searchRange.right < iSearchX || rcStruct.searchRange.top > iSearchY || rcStruct.searchRange.bottom < iSearchY )), "Unspecified error");
const Pel* const piRefSrch = rcStruct.piRefY + iSearchY * rcStruct.iRefStride + iSearchX; //根据搜索点坐标,获取从搜索点开始的ref像素地址
m_cDistParam.cur.buf = piRefSrch; //ref地址赋给m_cDistParam,用来计算失真
if( 1 == rcStruct.subShiftMode ) //搜索模式为MESEARCH_SELECTIVE时 该模式不是一次性计算像素匹配失真的,而是亚采样逐步计算的
{
// motion cost //这种模式时,m_cDistParam.subShift不为0,即匹配求失真时,采用了像素行的亚采样
Distortion uiBitCost = m_pcRdCost->getCostOfVectorWithPredictor( iSearchX, iSearchY, rcStruct.imvShift ); //mv的bit cost
// Skip search if bit cost is already larger than best SAD
if (uiBitCost < rcStruct.uiBestSad)
{
Distortion uiTempSad = m_cDistParam.distFunc( m_cDistParam ); //像素行亚采样的像素匹配
if((uiTempSad + uiBitCost) < rcStruct.uiBestSad)
{
// it's not supposed that any member of DistParams is manipulated beside cur.buf
int subShift = m_cDistParam.subShift;
const Pel* pOrgCpy = m_cDistParam.org.buf;
uiSad += uiTempSad >> m_cDistParam.subShift;
while( m_cDistParam.subShift > 0 ) //像素行亚采样
{
int isubShift = m_cDistParam.subShift -1;
m_cDistParam.org.buf = rcStruct.pcPatternKey->buf + (rcStruct.pcPatternKey->stride << isubShift);
m_cDistParam.cur.buf = piRefSrch + (rcStruct.iRefStride << isubShift); //像素行亚采样
uiTempSad = m_cDistParam.distFunc( m_cDistParam );
uiSad += uiTempSad >> m_cDistParam.subShift;
if(((uiSad << isubShift) + uiBitCost) > rcStruct.uiBestSad) //大于best匹配点,那么当前点没必要再计算了
{
break;
}
m_cDistParam.subShift--; //4行亚采样->偶数行亚采样->没有亚采样
}
if(m_cDistParam.subShift == 0)
{
uiSad += uiBitCost;
if( uiSad < rcStruct.uiBestSad ) //如果测试点更优,将最优信息保存到rcStruct
{
rcStruct.uiBestSad = uiSad;
rcStruct.iBestX = iSearchX; //更新最优匹配点
rcStruct.iBestY = iSearchY;
rcStruct.uiBestDistance = uiDistance;
rcStruct.uiBestRound = 0;
rcStruct.ucPointNr = ucPointNr;
m_cDistParam.maximumDistortionForEarlyExit = uiSad;
}
}
// restore org ptr
m_cDistParam.org.buf = pOrgCpy; //由于上面进行了亚采样求失真,现在将信息恢复到函数开始时那样
m_cDistParam.subShift = subShift;
}
}
}
else //除了MESEARCH_SELECTIVE之外的其它搜索模式时
{ //这时的m_cDistParam.subShift为0
uiSad = m_cDistParam.distFunc( m_cDistParam ); //计算像素匹配的失真
// only add motion cost if uiSad is smaller than best. Otherwise pointless
// to add motion cost.
if( uiSad < rcStruct.uiBestSad )
{
// motion cost //与VTM1.0唯一的区别就在这里,getCostOfVectorWithPredictor函数需要传入rcStruct.imvShift
uiSad += m_pcRdCost->getCostOfVectorWithPredictor( iSearchX, iSearchY, rcStruct.imvShift ); //像素失真再加上运动信息的cost,得到总失真
if( uiSad < rcStruct.uiBestSad ) //如果测试点更优,将最优信息保存到rcStruct
{
rcStruct.uiBestSad = uiSad;
rcStruct.iBestX = iSearchX; //更新最优匹配点
rcStruct.iBestY = iSearchY;
rcStruct.uiBestDistance = uiDistance;
rcStruct.uiBestRound = 0;
rcStruct.ucPointNr = ucPointNr;
m_cDistParam.maximumDistortionForEarlyExit = uiSad;
}
}
}
}