简介
predInterSearch主要的工作是ME(运动估计)和MC(运动补偿)。
函数中有一个bTestNormalMC变量,它表示是否进行正常的MC过程,正常的MC过程就是进行ME再进行MC。
正常的MC流程是,遍历所有的参考帧,进行ME(运动估计:xEstimateMvPredAMVP和xMotionEstimation),然后记录MVP或者MV的信息,进行MC(运动补偿,目的是选出最优的参数),然后更新最优的参数,遍历完所有的参考帧之后,就选出了最优的参数了;然后循环结束,接着进行正式的MC(运动补偿)。
广义B帧技术
在高效的预测模式下,HEVC仍然采用了H.264中的B预测方式,同时还增加了广义B(Generalized P and B picture,GPB)预测方式取代低时延应用场景中的P预测方式。GPB预测结构是指对传统P帧采取类似于B帧的双向预测方式进行预测。在这种预测方式下,前向和后向参考列表中的参考图像都必须为当前图像之前的图像,且两个参考列表完全一致。对P帧采取B帧的运动预测方式增加了运动估计的准确度,提高了编码效率,同时也有利于编码流程的统一。具体细节可以参考博客:点击打开链接
函数流程
predInterSearch主要的工作是ME(运动估计)和MC(运动补偿)。
函数中有一个bTestNormalMC变量,它表示是否进行正常的MC过程,正常的MC过程就是进行ME再进行MC。
正常的MC流程是,遍历所有的参考帧,进行ME(运动估计:xEstimateMvPredAMVP和xMotionEstimation),然后记录AVP或者MV的信息,进行MC(运动补偿,目的是选出最优的参数),然后更新最优的参数,遍历完所有的参考帧之后,就选出了最优的参数了;然后循环结束,接着进行正式的MC(运动补偿)。
TEncSearch::predInterSearch的详解:
(1)定义若干变量,注意AMVPInfo和TComMv等信息,它保存者运动信息
(2)遍历当前CU被分成的若干个PU
1)一个帧最多可以参考16个其他的帧
2)调用xGetBlkBits,计算CU在ePartSize模式下所需要消耗的比特数
3)计算当前PU的索引和大小
4)遍历两个参考图像列表(list0和list1)
a)遍历当前帧的所有参考帧:
①调用xEstimateMvPredAMVP,进行MV预测和AMVP的计算
②记录这个参考帧计算出来的MVP索引,数量等信息
③更新最优的参数
④计算比特数
⑤如果使用了list1(即B帧)
Ⅰ)如果list0和list1之间有映射(即这个帧同时出现在list0和list1中),那么直接把在list0中的计算信息复制过来就行了。
Ⅱ)如果没有映射,那么调用xMotionEstimation进行运动估计。
⑥如果对于使用list0的帧(P帧和B帧),调用xMotionEstimation进行运动估计。
⑦复制AMVP信息
⑧选择最优的MVP
⑨设置各种计算出来的运动信息
5)如果当前帧是B帧
a)并且list1是空的(getMvdL1ZeroFlag标志为真),那么调用motionCompensation进行运动补偿运算
b)对当前CU的4个子CU进行遍历计算:
①如果是第一个子CU,并且getMvdL1ZeroFlag为false,那么调用motionCompensation进行运动补偿计算
②遍历当前帧的所有参考帧:
Ⅰ)调用xMotionEstimation,进行运动估计
Ⅱ)调用xCopyAMVPInfo复制AMVP信息,调用xCheckBestMVP选择最好的MVP
Ⅲ)如果找到了更优的方式,那么更新信息,并且如果不是第一个子CU的话,还需要调用motionCompensation进行运动补偿
③如果没有选择出更优的代价,那么复制AMVP信息,选择最优的MVP等
6)设置各种MV的信息
7)同样,还是设置各种MVP以及MV的信息
8)对于分割类型不是2Nx2N(即当前CU没有划分)
a)调用xGetInterPredictionError进行运动补偿(该函数内部实质是调用motionCompensation)
b)调用xMergeEstimation,合并估计信息
9)调用motionCompensation进行运动补偿计算
(3)调用setWpScalingDistParam,设置wp(加权预测)参数
下面的代码为了方便理解,删除了定义ZERO_MVD_EST宏才会生效的代码,以及其他的无关的代码
- #if AMP_MRG
- Void TEncSearch::predInterSearch( TComDataCU* pcCU, TComYuv* pcOrgYuv, TComYuv*& rpcPredYuv, TComYuv*& rpcResiYuv, TComYuv*& rpcRecoYuv, Bool bUseRes, Bool bUseMRG )
- #else
- Void TEncSearch::predInterSearch( TComDataCU* pcCU, TComYuv* pcOrgYuv, TComYuv*& rpcPredYuv, TComYuv*& rpcResiYuv, TComYuv*& rpcRecoYuv, Bool bUseRes )
- #endif
- {
-
-
-
- for ( Int iPartIdx = 0; iPartIdx < iNumPart; iPartIdx++ )
- {
-
-
-
- xGetBlkBits( ePartSize, pcCU->getSlice()->isInterP(), iPartIdx, uiLastMode, uiMbBits);
-
-
- pcCU->getPartIndexAndSize( iPartIdx, uiPartAddr, iRoiWidth, iRoiHeight );
-
- #if AMP_MRG
- Bool bTestNormalMC = true;
-
- if ( bUseMRG && pcCU->getWidth( 0 ) > 8 && iNumPart == 2 )
- {
- bTestNormalMC = false;
- }
-
- if (bTestNormalMC)
- {
- #endif
-
-
-
- for ( Int iRefList = 0; iRefList < iNumPredDir; iRefList++ )
- {
-
- RefPicList eRefPicList = ( iRefList ? REF_PIC_LIST_1 : REF_PIC_LIST_0 );
-
-
- for ( Int iRefIdxTemp = 0; iRefIdxTemp < pcCU->getSlice()->getNumRefIdx(eRefPicList); iRefIdxTemp++ )
- {
-
-
-
- xEstimateMvPredAMVP( pcCU, pcOrgYuv, iPartIdx, eRefPicList, iRefIdxTemp, cMvPred[iRefList][iRefIdxTemp], false, &biPDistTemp);
-
-
-
-
-
-
- #if GPB_SIMPLE_UNI // 广义B帧技术GPB,相关细节可以参考http://blog.csdn.net/yangxiao_xiang/article/details/9045777
-
- if ( iRefList == 1 )
- {
-
- if ( pcCU->getSlice()->getList1IdxToList0Idx( iRefIdxTemp ) >= 0 )
- {
-
-
-
- }
-
- else
- {
-
- xMotionEstimation ( pcCU, pcOrgYuv, iPartIdx, eRefPicList, &cMvPred[iRefList][iRefIdxTemp], iRefIdxTemp, cMvTemp[iRefList][iRefIdxTemp], uiBitsTemp, uiCostTemp );
- }
- }
-
- else
- {
-
- xMotionEstimation ( pcCU, pcOrgYuv, iPartIdx, eRefPicList, &cMvPred[iRefList][iRefIdxTemp], iRefIdxTemp, cMvTemp[iRefList][iRefIdxTemp], uiBitsTemp, uiCostTemp );
- }
- #else // else of GPB_SIMPLE_UNI
-
-
- xMotionEstimation ( pcCU, pcOrgYuv, iPartIdx, eRefPicList, &cMvPred[iRefList][iRefIdxTemp], iRefIdxTemp, cMvTemp[iRefList][iRefIdxTemp], uiBitsTemp, uiCostTemp );
- #endif // end of GPB_SIMPLE_UNI
-
- xCopyAMVPInfo(pcCU->getCUMvField(eRefPicList)->getAMVPInfo(), &aacAMVPInfo[iRefList][iRefIdxTemp]);
-
- xCheckBestMVP(pcCU, eRefPicList, cMvTemp[iRefList][iRefIdxTemp], cMvPred[iRefList][iRefIdxTemp], aaiMvpIdx[iRefList][iRefIdxTemp], uiBitsTemp, uiCostTemp);
-
-
- }
- }
-
-
-
- if ( (pcCU->getSlice()->isInterB()) && (pcCU->isBipredRestriction(iPartIdx) == false) )
- {
-
-
-
-
- if(pcCU->getSlice()->getMvdL1ZeroFlag())
- {
-
-
-
- motionCompensation( pcCU, pcYuvPred, REF_PIC_LIST_1, iPartIdx );
-
-
- }
- else
- {
- uiMotBits[0] = uiBits[0] - uiMbBits[0];
- uiMotBits[1] = uiBits[1] - uiMbBits[1];
- uiBits[2] = uiMbBits[2] + uiMotBits[0] + uiMotBits[1];
- }
-
-
- Int iNumIter = 4;
-
-
- if ( m_pcEncCfg->getUseFastEnc() || pcCU->getSlice()->getMvdL1ZeroFlag())
- {
- iNumIter = 1;
- }
-
-
- for ( Int iIter = 0; iIter < iNumIter; iIter++ )
- {
-
- Int iRefList = iIter % 2;
- if ( m_pcEncCfg->getUseFastEnc() )
- {
- if( uiCost[0] <= uiCost[1] )
- {
- iRefList = 1;
- }
- else
- {
- iRefList = 0;
- }
- }
- else if ( iIter == 0 )
- {
- iRefList = 0;
- }
-
-
- if ( iIter == 0 && !pcCU->getSlice()->getMvdL1ZeroFlag())
- {
-
-
- motionCompensation ( pcCU, pcYuvPred, RefPicList(1-iRefList), iPartIdx );
- }
-
-
- RefPicList eRefPicList = ( iRefList ? REF_PIC_LIST_1 : REF_PIC_LIST_0 );
-
- if(pcCU->getSlice()->getMvdL1ZeroFlag())
- {
- iRefList = 0;
- eRefPicList = REF_PIC_LIST_0;
- }
-
- Bool bChanged = false;
-
- iRefStart = 0;
- iRefEnd = pcCU->getSlice()->getNumRefIdx(eRefPicList)-1;
-
-
- for ( Int iRefIdxTemp = iRefStart; iRefIdxTemp <= iRefEnd; iRefIdxTemp++ )
- {
-
-
-
-
- xMotionEstimation ( pcCU, pcOrgYuv, iPartIdx, eRefPicList, &cMvPredBi[iRefList][iRefIdxTemp], iRefIdxTemp, cMvTemp[iRefList][iRefIdxTemp], uiBitsTemp, uiCostTemp, true );
- xCopyAMVPInfo(&aacAMVPInfo[iRefList][iRefIdxTemp], pcCU->getCUMvField(eRefPicList)->getAMVPInfo());
-
- xCheckBestMVP(pcCU, eRefPicList, cMvTemp[iRefList][iRefIdxTemp], cMvPredBi[iRefList][iRefIdxTemp], aaiMvpIdxBi[iRefList][iRefIdxTemp], uiBitsTemp, uiCostTemp);
-
-
- if ( uiCostTemp < uiCostBi )
- {
-
- }
- }
-
- if ( !bChanged )
- {
-
- }
- }
- }
-
-
- #if AMP_MRG
- }
- #endif
-
-
- #if AMP_MRG
-
- if (bTestNormalMC)
- {
- #endif
-
- #if AMP_MRG
- }
- #endif
-
-
-
- if ( pcCU->getPartitionSize( uiPartAddr ) != SIZE_2Nx2N )
- {
-
- #if AMP_MRG
-
-
- if (bTestNormalMC)
- {
- xGetInterPredictionError( pcCU, pcOrgYuv, iPartIdx, uiMEError, m_pcEncCfg->getUseHADME() );
- uiMECost = uiMEError + m_pcRdCost->getCost( uiMEBits );
- }
- #else
-
-
- UInt uiMEError = MAX_UINT;
- xGetInterPredictionError( pcCU, pcOrgYuv, iPartIdx, uiMEError, m_pcEncCfg->getUseHADME() );
-
- #endif
-
-
-
-
- UInt uiMRGCost = MAX_UINT;
-
- xMergeEstimation( pcCU, pcOrgYuv, iPartIdx, uiMRGInterDir, cMRGMvField, uiMRGIndex, uiMRGCost, cMvFieldNeighbours, uhInterDirNeighbours, numValidMergeCand);
-
-
- if ( uiMRGCost < uiMECost )
- {
-
-
- }
- else
- {
-
-
- }
- }
-
-
-
- motionCompensation ( pcCU, rpcPredYuv, REF_PIC_LIST_X, iPartIdx );
-
- }
-
- setWpScalingDistParam( pcCU, -1, REF_PIC_LIST_X );
-
- return;
- }