本文分析xTZSearch调用了两个最为主要的函数:xTZ8PointDiamondSearch和xTZ2PointSearch
__inline Void TEncSearch::xTZ8PointDiamondSearch( const TComPattern*const pcPatternKey,
IntTZSearchStruct& rcStruct,
const TComMv*const pcMvSrchRngLT,
const TComMv*const pcMvSrchRngRB,
const Int iStartX,
const Int iStartY,
const Int iDist,
const Bool bCheckCornersAtDist1 )
{
const Int iSrchRngHorLeft = pcMvSrchRngLT->getHor();
const Int iSrchRngHorRight = pcMvSrchRngRB->getHor();
const Int iSrchRngVerTop = pcMvSrchRngLT->getVer();
const 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
//0为当前点
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 )//!< 搜索步长等于1时,最优点可能为2,4,5,7这四个位置。进行两点搜索,搜索与当前最优点距离最近的两个点(两点搜索主要目的是补充搜索最优点周围尚未搜索的点)
{
if ( iTop >= iSrchRngVerTop ) // check top
{
if (bCheckCornersAtDist1)
{
if ( iLeft >= iSrchRngHorLeft) // check top-left
{
xTZSearchHelp( pcPatternKey, rcStruct, iLeft, iTop, 1, iDist );//搜索1
}
xTZSearchHelp( pcPatternKey, rcStruct, iStartX, iTop, 2, iDist );//搜索2
if ( iRight <= iSrchRngHorRight ) // check middle right
{
xTZSearchHelp( pcPatternKey, rcStruct, iRight, iTop, 3, iDist );//搜索3
}
}
else
{
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
{
if (bCheckCornersAtDist1)
{
if ( iLeft >= iSrchRngHorLeft) // check top-left
{
xTZSearchHelp( pcPatternKey, rcStruct, iLeft, iBottom, 6, iDist );
}
xTZSearchHelp( pcPatternKey, rcStruct, iStartX, iBottom, 7, iDist );
if ( iRight <= iSrchRngHorRight ) // check middle right
{
xTZSearchHelp( pcPatternKey, rcStruct, iRight, iBottom, 8, iDist );
}
}
else
{
xTZSearchHelp( pcPatternKey, rcStruct, iStartX, iBottom, 7, iDist );
}
}
}
else
{
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
{
const Int iPosYT = iTop + ((iDist>>2) * index);
const Int iPosYB = iBottom - ((iDist>>2) * index);
const Int iPosXL = iStartX - ((iDist>>2) * index);
const Int iPosXR = iStartX + ((iDist>>2) * index);
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++ )
{
const Int iPosYT = iTop + ((iDist>>2) * index);
const Int iPosYB = iBottom - ((iDist>>2) * index);
const Int iPosXL = iStartX - ((iDist>>2) * index);
const 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
}
最优搜索步长等于1时,最优点可能为2,4,5,7这四个位置,此时需要进行两点搜索,搜索与当前最优点距离最近的两个点(两点搜索主要目的是补充搜索最优点周围尚未搜索的点)
__inline Void TEncSearch::xTZ2PointSearch( const TComPattern* const pcPatternKey, IntTZSearchStruct& rcStruct, const TComMv* const pcMvSrchRngLT, const TComMv* const pcMvSrchRngRB )
{
Int iSrchRngHorLeft = pcMvSrchRngLT->getHor();
Int iSrchRngHorRight = pcMvSrchRngRB->getHor();
Int iSrchRngVerTop = pcMvSrchRngLT->getVer();
Int iSrchRngVerBottom = pcMvSrchRngRB->getVer();
// 2 point search, // 1 2 3
// check only the 2 untested points // 4 0 5
// around the start point // 6 7 8
//!< 注意到,这里的1,3,6,8实际上是搜索步长iDist==2的时候由iDist>>1进行赋值的,实际距离以1计算,
//!< 在前面经过xTZ8PointSearch确定最佳步长为1后,会在这里对以最佳点为中心、周围没搜索过的点进行运动估计
Int iStartX = rcStruct.iBestX;
Int iStartY = rcStruct.iBestY;
switch( rcStruct.ucPointNr )//!< 主要思想是根据该最佳点的位置处理未搜索过的点
{
case 1:
{
if ( (iStartX - 1) >= iSrchRngHorLeft )
{
xTZSearchHelp( pcPatternKey, rcStruct, iStartX - 1, iStartY, 0, 2 );//左
}
if ( (iStartY - 1) >= iSrchRngVerTop )
{
xTZSearchHelp( pcPatternKey, rcStruct, iStartX, iStartY - 1, 0, 2 );//上
}
}
break;
case 2:
{
if ( (iStartY - 1) >= iSrchRngVerTop )
{
if ( (iStartX - 1) >= iSrchRngHorLeft )
{
xTZSearchHelp( pcPatternKey, rcStruct, iStartX - 1, iStartY - 1, 0, 2 );//左上
}
if ( (iStartX + 1) <= iSrchRngHorRight )
{
xTZSearchHelp( pcPatternKey, rcStruct, iStartX + 1, iStartY - 1, 0, 2 );//右上
}
}
}
break;
case 3:
{
if ( (iStartY - 1) >= iSrchRngVerTop )
{
xTZSearchHelp( pcPatternKey, rcStruct, iStartX, iStartY - 1, 0, 2 );//上
}
if ( (iStartX + 1) <= iSrchRngHorRight )
{
xTZSearchHelp( pcPatternKey, rcStruct, iStartX + 1, iStartY, 0, 2 );//右
}
}
break;
case 4:
{
if ( (iStartX - 1) >= iSrchRngHorLeft )
{
if ( (iStartY + 1) <= iSrchRngVerBottom )
{
xTZSearchHelp( pcPatternKey, rcStruct, iStartX - 1, iStartY + 1, 0, 2 );//左下
}
if ( (iStartY - 1) >= iSrchRngVerTop )
{
xTZSearchHelp( pcPatternKey, rcStruct, iStartX - 1, iStartY - 1, 0, 2 );//左上
}
}
}
break;
case 5:
{
if ( (iStartX + 1) <= iSrchRngHorRight )
{
if ( (iStartY - 1) >= iSrchRngVerTop )
{
xTZSearchHelp( pcPatternKey, rcStruct, iStartX + 1, iStartY - 1, 0, 2 );//右上
}
if ( (iStartY + 1) <= iSrchRngVerBottom )
{
xTZSearchHelp( pcPatternKey, rcStruct, iStartX + 1, iStartY + 1, 0, 2 );//右下
}
}
}
break;
case 6:
{
if ( (iStartX - 1) >= iSrchRngHorLeft )
{
xTZSearchHelp( pcPatternKey, rcStruct, iStartX - 1, iStartY , 0, 2 );//左
}
if ( (iStartY + 1) <= iSrchRngVerBottom )
{
xTZSearchHelp( pcPatternKey, rcStruct, iStartX, iStartY + 1, 0, 2 );//下
}
}
break;
case 7:
{
if ( (iStartY + 1) <= iSrchRngVerBottom )
{
if ( (iStartX - 1) >= iSrchRngHorLeft )
{
xTZSearchHelp( pcPatternKey, rcStruct, iStartX - 1, iStartY + 1, 0, 2 );//左下
}
if ( (iStartX + 1) <= iSrchRngHorRight )
{
xTZSearchHelp( pcPatternKey, rcStruct, iStartX + 1, iStartY + 1, 0, 2 );//右下
}
}
}
break;
case 8:
{
if ( (iStartX + 1) <= iSrchRngHorRight )
{
xTZSearchHelp( pcPatternKey, rcStruct, iStartX + 1, iStartY, 0, 2 );//右
}
if ( (iStartY + 1) <= iSrchRngVerBottom )
{
xTZSearchHelp( pcPatternKey, rcStruct, iStartX, iStartY + 1, 0, 2 );//下
}
}
break;
default:
{
assert( false );
}
break;
} // switch( rcStruct.ucPointNr )
}