本文分析xTZSearch调用了两个最为主要的函数:xTZ8PointDiamondSearch和xTZ2PointSearch,值得一提的是,HM中还提供了另外一个搜索函数xTZ8PointSquareSearch,但由于实际并没有使用这个函数,且它其实跟钻石搜索只是搜索点的选择略有不同,分析起来基本上也是一样的,这里就不重复啰嗦了。
__inline Void TEncSearch::xTZ2PointSearch( TComPattern* pcPatternKey, IntTZSearchStruct& rcStruct, TComMv* pcMvSrchRngLT, TComMv* 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 ) }
__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 }