HEVC代码学习21:xTZSearch函数

来源:互联网 发布:lol物品数据库 编辑:程序博客网 时间:2024/05/16 09:59

今天来继续学习运动估计的整像素搜索,来看下xTZSearch函数。

昨天已经说了xTZSearch是Diamond搜索的入口函数,其中调用了重要函数xTZSearchHelp和xTZ8PointDiamondSearch 。

其主要工作流程如下:
1、使用宏TZ_SEARCH_CONFIGURATION,配置相关的搜索参数,初始化搜索范围、跨度、像素值和SAD。
2、假设中值预测MV为最优点。
3、测试PRED_A, PRED_B, PRED_C的MV和零MV,确定最优点。
5、以上述过程找到的最优点为起点,进行第一遍菱形搜索,并测试零MV,确定新的最优点。当找到的最优点对应搜索步长为1时,对最优点周围未搜索的两个点进行搜索。注意在第一遍菱形搜索时,默认开启了bFirstSearchStop,当cStruct.uiBestRound >= uiFirstSearchRounds(默认为3)时,会结束第一遍菱形搜索。该过程中,搜索了1、2、4、8步长的菱形点。
6、当搜索步长过大时,改用光栅搜索。
7、以上述过程找到的最优点为起点,进行第二遍菱形搜索。
8、记录最优点对应的MV和SAD。

搜索算法理论详细可见:
http://blog.csdn.net/lin453701006/article/details/54340405

在代码中还提供了xTZ8PointSquareSearch搜索算法。在TZ search中提供了两种搜索模板:菱形搜索模板和正方形搜索模板。HM中默认使用xTZ8PointDiamondSearch菱形搜素,xTZ8PointSquareSearch正方形搜索没有被用到。

Void TEncSearch::xTZSearch( TComDataCU*  pcCU,    TComPattern* pcPatternKey,    Pel*         piRefY,    Int          iRefStride,    TComMv*      pcMvSrchRngLT,    TComMv*      pcMvSrchRngRB,    TComMv      &rcMv,    Distortion  &ruiSAD,    const TComMv* pIntegerMv2Nx2NPred ){    Int   iSrchRngHorLeft   = pcMvSrchRngLT->getHor();      //左边界    Int   iSrchRngHorRight  = pcMvSrchRngRB->getHor();      //右边界    Int   iSrchRngVerTop    = pcMvSrchRngLT->getVer();      //上边界    Int   iSrchRngVerBottom = pcMvSrchRngRB->getVer();      //下边界    TZ_SEARCH_CONFIGURATION     //TZ search的配置参数    UInt uiSearchRange = m_iSearchRange;        //搜索范围,cfg中通过SearchRange设置,一般设为256    pcCU->clipMv( rcMv );       //防止越界    rcMv >>= 2;         //右移2位,因为rcMv以1/4精度为单位    // init TZSearchStruct    IntTZSearchStruct cStruct;    cStruct.iYStride    = iRefStride;    cStruct.piRefY      = piRefY;    cStruct.uiBestSad   = MAX_UINT;    // set rcMv (Median predictor) as start point and as best point    xTZSearchHelp( pcPatternKey, cStruct, rcMv.getHor(), rcMv.getVer(), 0, 0 );     //中值预测MV    // test whether one of PRED_A, PRED_B, PRED_C MV is better start point than Median predictor    //测试PRED_A, PRED_B, PRED_C的MV,一般bTestOtherPredictedMV为假    if ( bTestOtherPredictedMV )                {        for ( UInt index = 0; index < NUM_MV_PREDICTORS; index++ )        {            TComMv cMv = m_acMvPredictors[index];            pcCU->clipMv( cMv );            cMv >>= 2;            xTZSearchHelp( pcPatternKey, cStruct, cMv.getHor(), cMv.getVer(), 0, 0 );        }    }    // test whether zero Mv is better start point than Median predictor    if ( bTestZeroVector )  //测试零MV    {        xTZSearchHelp( pcPatternKey, cStruct, 0, 0, 0, 0 );    }    if (pIntegerMv2Nx2NPred != 0)    {        TComMv integerMv2Nx2NPred = *pIntegerMv2Nx2NPred;        integerMv2Nx2NPred <<= 2;        pcCU->clipMv( integerMv2Nx2NPred );        integerMv2Nx2NPred >>= 2;        xTZSearchHelp(pcPatternKey, cStruct, integerMv2Nx2NPred.getHor(), integerMv2Nx2NPred.getVer(), 0, 0);        // reset search range        TComMv cMvSrchRngLT;        TComMv cMvSrchRngRB;        Int iSrchRng = m_iSearchRange;        TComMv currBestMv(cStruct.iBestX, cStruct.iBestY );        currBestMv <<= 2;        xSetSearchRange( pcCU, currBestMv, iSrchRng, cMvSrchRngLT, cMvSrchRngRB );        iSrchRngHorLeft   = cMvSrchRngLT.getHor();        iSrchRngHorRight  = cMvSrchRngRB.getHor();        iSrchRngVerTop    = cMvSrchRngLT.getVer();        iSrchRngVerBottom = cMvSrchRngRB.getVer();    }    // start search    //以前面测试的MV找到的最好位置为起点进行搜索    Int  iDist = 0;    Int  iStartX = cStruct.iBestX;    Int  iStartY = cStruct.iBestY;    // first search    for ( iDist = 1; iDist <= (Int)uiSearchRange; iDist*=2 )            {        if ( bFirstSearchDiamond == 1 )     //默认使用Diamond搜索        {            xTZ8PointDiamondSearch ( pcPatternKey, cStruct, pcMvSrchRngLT, pcMvSrchRngRB, iStartX, iStartY, iDist );        }        else        {            xTZ8PointSquareSearch  ( pcPatternKey, cStruct, pcMvSrchRngLT, pcMvSrchRngRB, iStartX, iStartY, iDist );        }        if ( bFirstSearchStop && ( cStruct.uiBestRound >= uiFirstSearchRounds ) ) // stop criterion        {            break;        }    }    // test whether zero Mv is a better start point than Median predictor       //测试零MV是否是最优点    if ( bTestZeroVectorStart && ((cStruct.iBestX != 0) || (cStruct.iBestY != 0)) )    {        xTZSearchHelp( pcPatternKey, cStruct, 0, 0, 0, 0 );        if ( (cStruct.iBestX == 0) && (cStruct.iBestY == 0) )        {            // test its neighborhood            for ( iDist = 1; iDist <= (Int)uiSearchRange; iDist*=2 )            {                xTZ8PointDiamondSearch( pcPatternKey, cStruct, pcMvSrchRngLT, pcMvSrchRngRB, 0, 0, iDist );                if ( bTestZeroVectorStop && (cStruct.uiBestRound > 0) ) // stop criterion                {                    break;                }            }        }    }    // calculate only 2 missing points instead 8 points if cStruct.uiBestDistance == 1    //当最优点对应步长为1,对最优点周围未搜索的两个点进行搜索    if ( cStruct.uiBestDistance == 1 )    {        cStruct.uiBestDistance = 0;        xTZ2PointSearch( pcPatternKey, cStruct, pcMvSrchRngLT, pcMvSrchRngRB );    }    // raster search if distance is too big    //当搜索的最佳步长过大时,改用光栅搜索法,步长设为iRaster,搜索范围为设定的运动估计范围      if ( bEnableRasterSearch && ( ((Int)(cStruct.uiBestDistance) > iRaster) || bAlwaysRasterSearch ) )   //bRasterRefinementEnable默认为1,bAlwaysRasterSearch默认为0    {        cStruct.uiBestDistance = iRaster;   //iRaster = 5        for ( iStartY = iSrchRngVerTop; iStartY <= iSrchRngVerBottom; iStartY += iRaster )        {            for ( iStartX = iSrchRngHorLeft; iStartX <= iSrchRngHorRight; iStartX += iRaster )            {                xTZSearchHelp( pcPatternKey, cStruct, iStartX, iStartY, 0, iRaster );            }        }    }    // raster refinement 光栅细化搜索,bRasterRefinementEnable默认为false    if ( bRasterRefinementEnable && cStruct.uiBestDistance > 0 )    {        while ( cStruct.uiBestDistance > 0 )        {            iStartX = cStruct.iBestX;            iStartY = cStruct.iBestY;            if ( cStruct.uiBestDistance > 1 )            {                iDist = cStruct.uiBestDistance >>= 1;                if ( bRasterRefinementDiamond == 1 )                {                    xTZ8PointDiamondSearch ( pcPatternKey, cStruct, pcMvSrchRngLT, pcMvSrchRngRB, iStartX, iStartY, iDist );                }                else                {                    xTZ8PointSquareSearch  ( pcPatternKey, cStruct, pcMvSrchRngLT, pcMvSrchRngRB, iStartX, iStartY, iDist );                }            }            // calculate only 2 missing points instead 8 points if cStruct.uiBestDistance == 1            if ( cStruct.uiBestDistance == 1 )            {                cStruct.uiBestDistance = 0;                if ( cStruct.ucPointNr != 0 )                {                    xTZ2PointSearch( pcPatternKey, cStruct, pcMvSrchRngLT, pcMvSrchRngRB );                }            }        }    }    // start refinement 细化搜索    //从找到的最优点开始进行第二次搜索    if ( bStarRefinementEnable && cStruct.uiBestDistance > 0 )   //bStarRefinementEnable默认为1    {        while ( cStruct.uiBestDistance > 0 )        {            iStartX = cStruct.iBestX;            iStartY = cStruct.iBestY;            cStruct.uiBestDistance = 0;            cStruct.ucPointNr = 0;            for ( iDist = 1; iDist < (Int)uiSearchRange + 1; iDist*=2 )            {                if ( bStarRefinementDiamond == 1 )                {                    xTZ8PointDiamondSearch ( pcPatternKey, cStruct, pcMvSrchRngLT, pcMvSrchRngRB, iStartX, iStartY, iDist );                }                else                {                    xTZ8PointSquareSearch  ( pcPatternKey, cStruct, pcMvSrchRngLT, pcMvSrchRngRB, iStartX, iStartY, iDist );                }                if ( bStarRefinementStop && (cStruct.uiBestRound >= uiStarRefinementRounds) ) // stop criterion                {                    break;                }            }            // calculate only 2 missing points instead 8 points if cStrukt.uiBestDistance == 1            if ( cStruct.uiBestDistance == 1 )            {                cStruct.uiBestDistance = 0;                if ( cStruct.ucPointNr != 0 )                {                    xTZ2PointSearch( pcPatternKey, cStruct, pcMvSrchRngLT, pcMvSrchRngRB );                }            }        }    }    // write out best match    //记录最优点的MV和SAD    rcMv.set( cStruct.iBestX, cStruct.iBestY );    ruiSAD = cStruct.uiBestSad - m_pcRdCost->getCost( cStruct.iBestX, cStruct.iBestY );}

宏TZ_SEARCH_CONFIGURATION设置的默认参数如下:

#define TZ_SEARCH_CONFIGURATION                                                                                 \    const Int  iRaster                  = 5;  /* TZ soll von aussen ?ergeben werden */                            \    const Bool bTestOtherPredictedMV    = 0;                                                                      \    const Bool bTestZeroVector          = 1;                                                                      \    const Bool bTestZeroVectorStart     = 0;                                                                      \    const Bool bTestZeroVectorStop      = 0;                                                                      \    const Bool bFirstSearchDiamond      = 1;  /* 1 = xTZ8PointDiamondSearch   0 = xTZ8PointSquareSearch */        \    const Bool bFirstSearchStop         = m_pcEncCfg->getFastMEAssumingSmootherMVEnabled();                       \    const UInt uiFirstSearchRounds      = 3;  /* first search stop X rounds after best match (must be >=1) */     \    const Bool bEnableRasterSearch      = 1;                                                                      \    const Bool bAlwaysRasterSearch      = 0;  /* ===== 1: BETTER but factor 2 slower ===== */                     \    const Bool bRasterRefinementEnable  = 0;  /* enable either raster refinement or star refinement */            \    const Bool bRasterRefinementDiamond = 0;  /* 1 = xTZ8PointDiamondSearch   0 = xTZ8PointSquareSearch */        \    const Bool bStarRefinementEnable    = 1;  /* enable either star refinement or raster refinement */            \    const Bool bStarRefinementDiamond   = 1;  /* 1 = xTZ8PointDiamondSearch   0 = xTZ8PointSquareSearch */        \    const Bool bStarRefinementStop      = 0;                                                                      \    const UInt uiStarRefinementRounds   = 2;  /* star refinement stop X rounds after best match (must be >=1) */  \
原创粉丝点击