xTZSearch调用了2个最为主要的函数:xTZ8PointDiamondSearch和xTZ2PointSearch,值得一提的是,HM中还提供了另外一个搜索函数xTZ8PointSquareSearch,但由于实际并没有使用这个函数,且它其实跟钻石搜索只是搜索点的选择略有不同,分析起来基本上也是一样的。
__inline Void TEncSearch::xTZ8PointDiamondSearch( TComPattern* pcPatternKey, IntTZSearchStruct& rcStruct, TComMv* pcMvSrchRngLT, TComMv* pcMvSrchRngRB, const Int iStartX, const Int iStartY, const Int iDist )
{
Int iSrchRngHorLeft = pcMvSrchRngLT->getHor();
Int iSrchRngHorRight = pcMvSrchRngRB->getHor();
Int iSrchRngVerTop = pcMvSrchRngLT->getVer();
Int iSrchRngVerBottom = pcMvSrchRngRB->getVer();
// 8 point search, // 1 2 3
// search around the start point // 4 0 5
// with the required distance // 6 7 8
assert ( iDist != 0 );
const Int iTop = iStartY - iDist;//!< 2
const Int iBottom = iStartY + iDist;//!< 7
const Int iLeft = iStartX - iDist;//!< 4
const Int iRight = iStartX + iDist;//!< 5
rcStruct.uiBestRound += 1;//!< 每次调用xTZSearchHelp,一旦发现当前搜索点的sad小于存放的最佳值,则将uiBestRound清零
if ( iDist == 1 ) // iDist == 1
{//!< 搜索步长等于1时,只搜索2,4,5,7这四个位置,这也就是在后面最佳步长为1时,仍然要进行2点钻石搜索的原因
if ( iTop >= iSrchRngVerTop ) // check top
{
xTZSearchHelp( pcPatternKey, rcStruct, iStartX, iTop, 2, iDist );
}
if ( iLeft >= iSrchRngHorLeft ) // check middle left
{
xTZSearchHelp( pcPatternKey, rcStruct, iLeft, iStartY, 4, iDist );
}
if ( iRight <= iSrchRngHorRight ) // check middle right
{
xTZSearchHelp( pcPatternKey, rcStruct, iRight, iStartY, 5, iDist );
}
if ( iBottom <= iSrchRngVerBottom ) // check bottom
{
xTZSearchHelp( pcPatternKey, rcStruct, iStartX, iBottom, 7, iDist );
}
}
else // if (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 >= iSrchRngVerTop && iLeft >= iSrchRngHorLeft &&
iRight <= iSrchRngHorRight && iBottom <= iSrchRngVerBottom ) // check border,保证在搜索范围内
{
xTZSearchHelp( pcPatternKey, rcStruct, iStartX, iTop, 2, iDist );
xTZSearchHelp( pcPatternKey, rcStruct, iLeft_2, iTop_2, 1, iDist>>1 );
xTZSearchHelp( pcPatternKey, rcStruct, iRight_2, iTop_2, 3, iDist>>1 );
xTZSearchHelp( pcPatternKey, rcStruct, iLeft, iStartY, 4, iDist );
xTZSearchHelp( pcPatternKey, rcStruct, iRight, iStartY, 5, iDist );
xTZSearchHelp( pcPatternKey, rcStruct, iLeft_2, iBottom_2, 6, iDist>>1 );
xTZSearchHelp( pcPatternKey, rcStruct, iRight_2, iBottom_2, 8, iDist>>1 );
xTZSearchHelp( pcPatternKey, rcStruct, iStartX, iBottom, 7, iDist );
}
else // check border,有部分越界,在确保不越界的情况下搜索对应点
{
if ( iTop >= iSrchRngVerTop ) // check top
{
xTZSearchHelp( pcPatternKey, rcStruct, iStartX, iTop, 2, iDist );
}
if ( iTop_2 >= iSrchRngVerTop ) // check half top
{
if ( iLeft_2 >= iSrchRngHorLeft ) // check half left
{
xTZSearchHelp( pcPatternKey, rcStruct, iLeft_2, iTop_2, 1, (iDist>>1) );
}
if ( iRight_2 <= iSrchRngHorRight ) // check half right
{
xTZSearchHelp( pcPatternKey, rcStruct, iRight_2, iTop_2, 3, (iDist>>1) );
}
} // check half top
if ( iLeft >= iSrchRngHorLeft ) // check left
{
xTZSearchHelp( pcPatternKey, rcStruct, iLeft, iStartY, 4, iDist );
}
if ( iRight <= iSrchRngHorRight ) // check right
{
xTZSearchHelp( pcPatternKey, rcStruct, iRight, iStartY, 5, iDist );
}
if ( iBottom_2 <= iSrchRngVerBottom ) // check half bottom
{
if ( iLeft_2 >= iSrchRngHorLeft ) // check half left
{
xTZSearchHelp( pcPatternKey, rcStruct, iLeft_2, iBottom_2, 6, (iDist>>1) );
}
if ( iRight_2 <= iSrchRngHorRight ) // check half right
{
xTZSearchHelp( pcPatternKey, rcStruct, iRight_2, iBottom_2, 8, (iDist>>1) );
}
} // check half bottom
if ( iBottom <= iSrchRngVerBottom ) // check bottom
{
xTZSearchHelp( pcPatternKey, rcStruct, iStartX, iBottom, 7, iDist );
}
} // check border
}
else // iDist > 8,搜索步长大于8以后,ucPointNr统一设置为0
{
if ( iTop >= iSrchRngVerTop && iLeft >= iSrchRngHorLeft &&
iRight <= iSrchRngHorRight && iBottom <= iSrchRngVerBottom ) // check border,在搜索范围内
{
xTZSearchHelp( pcPatternKey, rcStruct, iStartX, iTop, 0, iDist );//!< 2
xTZSearchHelp( pcPatternKey, rcStruct, iLeft, iStartY, 0, iDist );//!< 4
xTZSearchHelp( pcPatternKey, rcStruct, iRight, iStartY, 0, iDist );//!< 5
xTZSearchHelp( pcPatternKey, rcStruct, iStartX, iBottom, 0, iDist );//!< 7
for ( Int index = 1; index < 4; index++ )//!< 不妨假设此时iDist = 16,搜索的点可以以(iStartX, iStartY)为原点进行描点,不难得出钻石扫描的pattern
{
Int iPosYT = iTop + ((iDist>>2) * index);//!< iTop + 4 (8, 12)
Int iPosYB = iBottom - ((iDist>>2) * index);//!< iBottom - 4 (8, 12)
Int iPosXL = iStartX - ((iDist>>2) * index);//!< iStartX - 4 (8, 12)
Int iPosXR = iStartX + ((iDist>>2) * index); //!< iStartX + 4 (8, 12)
xTZSearchHelp( pcPatternKey, rcStruct, iPosXL, iPosYT, 0, iDist );
xTZSearchHelp( pcPatternKey, rcStruct, iPosXR, iPosYT, 0, iDist );
xTZSearchHelp( pcPatternKey, rcStruct, iPosXL, iPosYB, 0, iDist );
xTZSearchHelp( pcPatternKey, rcStruct, iPosXR, iPosYB, 0, iDist );
}
}
else // check border,有部分越界,在确保不越界的地方进行搜索
{
if ( iTop >= iSrchRngVerTop ) // check top
{
xTZSearchHelp( pcPatternKey, rcStruct, iStartX, iTop, 0, iDist );
}
if ( iLeft >= iSrchRngHorLeft ) // check left
{
xTZSearchHelp( pcPatternKey, rcStruct, iLeft, iStartY, 0, iDist );
}
if ( iRight <= iSrchRngHorRight ) // check right
{
xTZSearchHelp( pcPatternKey, rcStruct, iRight, iStartY, 0, iDist );
}
if ( iBottom <= iSrchRngVerBottom ) // check bottom
{
xTZSearchHelp( pcPatternKey, rcStruct, 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 >= iSrchRngVerTop ) // check top
{
if ( iPosXL >= iSrchRngHorLeft ) // check left
{
xTZSearchHelp( pcPatternKey, rcStruct, iPosXL, iPosYT, 0, iDist );
}
if ( iPosXR <= iSrchRngHorRight ) // check right
{
xTZSearchHelp( pcPatternKey, rcStruct, iPosXR, iPosYT, 0, iDist );
}
} // check top
if ( iPosYB <= iSrchRngVerBottom ) // check bottom
{
if ( iPosXL >= iSrchRngHorLeft ) // check left
{
xTZSearchHelp( pcPatternKey, rcStruct, iPosXL, iPosYB, 0, iDist );
}
if ( iPosXR <= iSrchRngHorRight ) // check right
{
xTZSearchHelp( pcPatternKey, rcStruct, iPosXR, iPosYB, 0, iDist );
}
} // check bottom
} // for ...
} // check border
} // iDist <= 8
} // iDist == 1
}