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) */ \
- HEVC代码学习21:xTZSearch函数
- xTZSearch函数
- HEVC代码追踪(十一。五):运动估计/补偿之xTZSearch
- HEVC代码学习2:TAppEncTop::encode函数
- HEVC代码学习3:TEncTop::encode函数
- HEVC代码学习7:xPatternSearchFracDIF函数
- HEVC代码学习8:xMotionEstimation函数
- HEVC代码学习9:getInterMergeCandidates函数
- HEVC代码学习11:xCompressCU函数
- HEVC代码学习12:xCheckRDCostInter函数
- HEVC代码学习13:predInterSearch函数
- HEVC代码学习14:motionCompensation函数
- HEVC代码学习15:AMVP相关函数
- HEVC代码学习20:xPatternSearchFast函数
- HEVC代码学习22:xTZSearchHelp函数
- HEVC代码学习23:xTZ8PointDiamondSearch函数
- HEVC代码学习24:encodeResAndCalcRdInterCU函数
- HEVC代码学习25:xDecompressCU函数
- hdu 2188 简单巴什博奕
- LeetCode-108-Convert Sorted Array to Binary Search Tree(转化已排序数组到二叉排序树)
- neupy 时间序列信号处理
- 腾讯校招软件测试工程师题库
- FZU
- HEVC代码学习21:xTZSearch函数
- SAP JCO connector 例子
- ASP.NET MVC 5
- HDU1698 线段树 区间更新
- 用brew在mac上安装mysql
- ILI百度指数
- 认识onNewIntent
- 爬取知乎用户信息
- 剑指offer--二叉树的深度