码迷,mamicode.com
首页 > 其他好文 > 详细

HM编码器代码阅读(14)——帧间预测之二predInterSearch(inter模式)

时间:2016-04-16 19:21:23      阅读:287      评论:0      收藏:0      [点我收藏+]

标签:

predInterSearch主要的工作是ME(运动估计)和MC(运动补偿)。
函数中有一个bTestNormalMC变量,它表示是否进行正常的MC过程,正常的MC过程就是进行ME再进行MC。
正常的MC流程是,遍历所有的参考帧,进行ME(运动估计:xEstimateMvPredAMVP和xMotionEstimation),然后记录AVP或者MV的信息,进行MC(运动补偿,目的是选出最优的参数),然后更新最优的参数,遍历完所有的参考帧之后,就选出了最优的参数了;然后循环结束,接着进行正式的MC(运动补偿)。
TEncSearch::predInterSearch的详解:
(1)定义若干变量,注意AMVPInfo和TComMv等信息,它保存者运动信息
(2)遍历当前CU被分成的四个子CU
     1)一个帧最多可以参考16个其他的帧
     2)调用xGetBlkBits,计算CU在某种模式下所需要消耗的比特数
     3)计算当前子分割的索引和大小
     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参数
#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
{
	m_acYuvPred[0].clear();
	m_acYuvPred[1].clear();
	m_cYuvPredTemp.clear();
	rpcPredYuv->clear();

	if ( !bUseRes )
	{
		rpcResiYuv->clear();
	}

	rpcRecoYuv->clear();

    // 这两个mv表示搜索范围(左上角和右下角),但是没有用到
	TComMv        cMvSrchRngLT;
	TComMv        cMvSrchRngRB;

	TComMv        cMvZero;
	TComMv        TempMv; //kolya

	TComMv        cMv[2];
	TComMv        cMvBi[2];
	TComMv        cMvTemp[2][33];

    // 当前CU可以被分成多少部分
	// 根据partitionSize来确定,如果partitionSize是2Nx2N那么就是一个,如果是NxN就是4个
	Int           iNumPart    = pcCU->getNumPartitions();
    // 预测的方向的个数(B帧有两个,前向和后向;P帧有一个,前向)
	Int           iNumPredDir = pcCU->getSlice()->isInterP() ? 1 : 2;

	// 记录了每一个前向参考帧的MV
	TComMv        cMvPred[2][33];

	// 记录了每一个后向参考帧的MV
	TComMv        cMvPredBi[2][33];
	// 记录了每一个后向参考帧的MVP的索引
	Int           aaiMvpIdxBi[2][33];

	// 记录了每一个前向参考帧的MVP的索引
	Int           aaiMvpIdx[2][33];
	// 记录了每一个帧的MVP的数量
	Int           aaiMvpNum[2][33];

	// 记录每一个帧的MVP的信息
	AMVPInfo aacAMVPInfo[2][33];

	Int           iRefIdx[2]={0,0}; //If un-initialized, may cause SEGV in bi-directional prediction iterative stage.
	Int           iRefIdxBi[2];

	UInt          uiPartAddr;
	Int           iRoiWidth, iRoiHeight;

	UInt          uiMbBits[3] = {1, 1, 0};

	UInt          uiLastMode = 0;
	Int           iRefStart, iRefEnd;

	PartSize      ePartSize = pcCU->getPartitionSize( 0 );

	Int           bestBiPRefIdxL1 = 0;
	Int           bestBiPMvpL1 = 0;
	UInt          biPDistTemp = MAX_INT;

#if ZERO_MVD_EST
	Int           aiZeroMvdMvpIdx[2] = {-1, -1};
	Int           aiZeroMvdRefIdx[2] = {0, 0};
	Int           iZeroMvdDir = -1;
#endif

	TComMvField cMvFieldNeighbours[MRG_MAX_NUM_CANDS << 1]; // double length for mv of both lists
	UChar uhInterDirNeighbours[MRG_MAX_NUM_CANDS];
	Int numValidMergeCand = 0 ;

	// 遍历当前帧被分成的各个分部
	for ( Int iPartIdx = 0; iPartIdx < iNumPart; iPartIdx++ )
	{
		UInt          uiCost[2] = { MAX_UINT, MAX_UINT };
		UInt          uiCostBi  =   MAX_UINT;
		UInt          uiCostTemp;

		UInt          uiBits[3];
		UInt          uiBitsTemp;
#if ZERO_MVD_EST
		UInt          uiZeroMvdCost = MAX_UINT;
		UInt          uiZeroMvdCostTemp;
		UInt          uiZeroMvdBitsTemp;
		UInt          uiZeroMvdDistTemp = MAX_UINT;
		UInt          auiZeroMvdBits[3];
#endif
		UInt          bestBiPDist = MAX_INT;

		UInt          uiCostTempL0[MAX_NUM_REF];
		for (Int iNumRef=0; iNumRef < MAX_NUM_REF; iNumRef++)
		{
			uiCostTempL0[iNumRef] = MAX_UINT;
		}
		UInt          uiBitsTempL0[MAX_NUM_REF];

		TComMv        mvValidList1;
		Int           refIdxValidList1 = 0;
		UInt          bitsValidList1 = MAX_UINT;
		UInt          costValidList1 = MAX_UINT;

        // 得到某种模式下CU块的比特数
		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

			//  Uni-directional prediction
            // 遍历两个参考图像列表(如果是P帧,只参考一个列表;如果是B帧,会参考两个列表)
			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++ )
				{
					uiBitsTemp = uiMbBits[iRefList];
					if ( pcCU->getSlice()->getNumRefIdx(eRefPicList) > 1 )
					{
						uiBitsTemp += iRefIdxTemp+1;
						if ( iRefIdxTemp == pcCU->getSlice()->getNumRefIdx(eRefPicList)-1 ) uiBitsTemp--;
					}
#if ZERO_MVD_EST
					xEstimateMvPredAMVP( pcCU, pcOrgYuv, iPartIdx, eRefPicList, iRefIdxTemp, cMvPred[iRefList][iRefIdxTemp], false, &biPDistTemp, &uiZeroMvdDistTemp);
#else
                    // MV预测和AMVP
					// 针对每一个参考帧进行处理(主要是MVP的计算)
                    xEstimateMvPredAMVP( pcCU, pcOrgYuv, iPartIdx, eRefPicList, iRefIdxTemp, cMvPred[iRefList][iRefIdxTemp], false, &biPDistTemp);
#endif
                    // 记录该帧MVP的索引
					aaiMvpIdx[iRefList][iRefIdxTemp] = pcCU->getMVPIdx(eRefPicList, uiPartAddr);
					// 记录该帧MVP的数量
					aaiMvpNum[iRefList][iRefIdxTemp] = pcCU->getMVPNum(eRefPicList, uiPartAddr);

					// 更新最优的参数
					if(pcCU->getSlice()->getMvdL1ZeroFlag() && iRefList==1 && biPDistTemp < bestBiPDist)
					{
						bestBiPDist = biPDistTemp;
						bestBiPMvpL1 = aaiMvpIdx[iRefList][iRefIdxTemp];
						bestBiPRefIdxL1 = iRefIdxTemp;
					}

					uiBitsTemp += m_auiMVPIdxCost[aaiMvpIdx[iRefList][iRefIdxTemp]][AMVP_MAX_NUM_CANDS];
#if ZERO_MVD_EST
					if ( iRefList == 0 || pcCU->getSlice()->getList1IdxToList0Idx( iRefIdxTemp ) < 0 )
					{
						uiZeroMvdBitsTemp = uiBitsTemp;
						uiZeroMvdBitsTemp += 2; //zero mvd bits

						m_pcRdCost->getMotionCost( 1, 0 );
						uiZeroMvdCostTemp = uiZeroMvdDistTemp + m_pcRdCost->getCost(uiZeroMvdBitsTemp);

						if (uiZeroMvdCostTemp < uiZeroMvdCost)
						{
							uiZeroMvdCost = uiZeroMvdCostTemp;
							iZeroMvdDir = iRefList + 1;
							aiZeroMvdRefIdx[iRefList] = iRefIdxTemp;
							aiZeroMvdMvpIdx[iRefList] = aaiMvpIdx[iRefList][iRefIdxTemp];
							auiZeroMvdBits[iRefList] = uiZeroMvdBitsTemp;
						}          
					}
#endif

#if GPB_SIMPLE_UNI
                    // 如果是参考列表1(B帧使用)
					if ( iRefList == 1 )    // list 1
					{
						// 如果list0到list1之间有映射,说明该帧即出现在list0中也出现在list1中
						if ( pcCU->getSlice()->getList1IdxToList0Idx( iRefIdxTemp ) >= 0 )
						{
							cMvTemp[1][iRefIdxTemp] = cMvTemp[0][pcCU->getSlice()->getList1IdxToList0Idx( iRefIdxTemp )];
							uiCostTemp = uiCostTempL0[pcCU->getSlice()->getList1IdxToList0Idx( iRefIdxTemp )];
							/*first subtract the bit-rate part of the cost of the other list*/
							uiCostTemp -= m_pcRdCost->getCost( uiBitsTempL0[pcCU->getSlice()->getList1IdxToList0Idx( iRefIdxTemp )] );
							/*correct the bit-rate part of the current ref*/
							m_pcRdCost->setPredictor  ( cMvPred[iRefList][iRefIdxTemp] );
							uiBitsTemp += m_pcRdCost->getBits( cMvTemp[1][iRefIdxTemp].getHor(), cMvTemp[1][iRefIdxTemp].getVer() );
							/*calculate the correct cost*/
							uiCostTemp += m_pcRdCost->getCost( uiBitsTemp );
						}
						else
						{
                            // 运动估计
							xMotionEstimation ( pcCU, pcOrgYuv, iPartIdx, eRefPicList, &cMvPred[iRefList][iRefIdxTemp], iRefIdxTemp, cMvTemp[iRefList][iRefIdxTemp], uiBitsTemp, uiCostTemp );
						}
					}
					// 如果是P帧
					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 );
#endif
					xCopyAMVPInfo(pcCU->getCUMvField(eRefPicList)->getAMVPInfo(), &aacAMVPInfo[iRefList][iRefIdxTemp]); // must always be done ( also when AMVP_MODE = AM_NONE )
                    // 选择最优的MVP
                    xCheckBestMVP(pcCU, eRefPicList, cMvTemp[iRefList][iRefIdxTemp], cMvPred[iRefList][iRefIdxTemp], aaiMvpIdx[iRefList][iRefIdxTemp], uiBitsTemp, uiCostTemp);

					if ( iRefList == 0 )
					{
						uiCostTempL0[iRefIdxTemp] = uiCostTemp;
						uiBitsTempL0[iRefIdxTemp] = uiBitsTemp;
					}
					if ( uiCostTemp < uiCost[iRefList] )
					{
						uiCost[iRefList] = uiCostTemp;
						uiBits[iRefList] = uiBitsTemp; // storing for bi-prediction

						// set motion
						cMv[iRefList]     = cMvTemp[iRefList][iRefIdxTemp];
						iRefIdx[iRefList] = iRefIdxTemp;
					}

					if ( iRefList == 1 && uiCostTemp < costValidList1 && pcCU->getSlice()->getList1IdxToList0Idx( iRefIdxTemp ) < 0 )
					{
						costValidList1 = uiCostTemp;
						bitsValidList1 = uiBitsTemp;

						// set motion
						mvValidList1     = cMvTemp[iRefList][iRefIdxTemp];
						refIdxValidList1 = iRefIdxTemp;
					}
				}
			}
			//  Bi-directional prediction
            // 如果是B帧
			if ( (pcCU->getSlice()->isInterB()) && (pcCU->isBipredRestriction(iPartIdx) == false) )
			{

				cMvBi[0] = cMv[0];            cMvBi[1] = cMv[1];
				iRefIdxBi[0] = iRefIdx[0];    iRefIdxBi[1] = iRefIdx[1];

				::memcpy(cMvPredBi, cMvPred, sizeof(cMvPred));
				::memcpy(aaiMvpIdxBi, aaiMvpIdx, sizeof(aaiMvpIdx));

				UInt uiMotBits[2];

				if(pcCU->getSlice()->getMvdL1ZeroFlag())
				{
					xCopyAMVPInfo(&aacAMVPInfo[1][bestBiPRefIdxL1], pcCU->getCUMvField(REF_PIC_LIST_1)->getAMVPInfo());
					pcCU->setMVPIdxSubParts( bestBiPMvpL1, REF_PIC_LIST_1, uiPartAddr, iPartIdx, pcCU->getDepth(uiPartAddr));
					aaiMvpIdxBi[1][bestBiPRefIdxL1] = bestBiPMvpL1;
					cMvPredBi[1][bestBiPRefIdxL1]   = pcCU->getCUMvField(REF_PIC_LIST_1)->getAMVPInfo()->m_acMvCand[bestBiPMvpL1];

					cMvBi[1] = cMvPredBi[1][bestBiPRefIdxL1];
					iRefIdxBi[1] = bestBiPRefIdxL1;
					pcCU->getCUMvField( REF_PIC_LIST_1 )->setAllMv( cMvBi[1], ePartSize, uiPartAddr, 0, iPartIdx );
					pcCU->getCUMvField( REF_PIC_LIST_1 )->setAllRefIdx( iRefIdxBi[1], ePartSize, uiPartAddr, 0, iPartIdx );
					TComYuv* pcYuvPred = &m_acYuvPred[1];

                    // 运动补偿
					motionCompensation( pcCU, pcYuvPred, REF_PIC_LIST_1, iPartIdx );

					uiMotBits[0] = uiBits[0] - uiMbBits[0];
					uiMotBits[1] = uiMbBits[1];

					if ( pcCU->getSlice()->getNumRefIdx(REF_PIC_LIST_1) > 1 )
					{
						uiMotBits[1] += bestBiPRefIdxL1+1;
						if ( bestBiPRefIdxL1 == pcCU->getSlice()->getNumRefIdx(REF_PIC_LIST_1)-1 ) uiMotBits[1]--;
					}

					uiMotBits[1] += m_auiMVPIdxCost[aaiMvpIdxBi[1][bestBiPRefIdxL1]][AMVP_MAX_NUM_CANDS];

					uiBits[2] = uiMbBits[2] + uiMotBits[0] + uiMotBits[1];

					cMvTemp[1][bestBiPRefIdxL1] = cMvBi[1];
				}
				else
				{
					uiMotBits[0] = uiBits[0] - uiMbBits[0];
					uiMotBits[1] = uiBits[1] - uiMbBits[1];
					uiBits[2] = uiMbBits[2] + uiMotBits[0] + uiMotBits[1];
				}

				// 4-times iteration (default)
				Int iNumIter = 4;

				// fast encoder setting: only one iteration
				if ( m_pcEncCfg->getUseFastEnc() || pcCU->getSlice()->getMvdL1ZeroFlag())
				{
					iNumIter = 1;
				}

                // 遍历4次的原因是什么
				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())
					{
						pcCU->getCUMvField(RefPicList(1-iRefList))->setAllMv( cMv[1-iRefList], ePartSize, uiPartAddr, 0, iPartIdx );
						pcCU->getCUMvField(RefPicList(1-iRefList))->setAllRefIdx( iRefIdx[1-iRefList], ePartSize, uiPartAddr, 0, iPartIdx );
						TComYuv*  pcYuvPred = &m_acYuvPred[1-iRefList];
						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++ )
					{
						uiBitsTemp = uiMbBits[2] + uiMotBits[1-iRefList];
						if ( pcCU->getSlice()->getNumRefIdx(eRefPicList) > 1 )
						{
							uiBitsTemp += iRefIdxTemp+1;
							if ( iRefIdxTemp == pcCU->getSlice()->getNumRefIdx(eRefPicList)-1 ) uiBitsTemp--;
						}
						uiBitsTemp += m_auiMVPIdxCost[aaiMvpIdxBi[iRefList][iRefIdxTemp]][AMVP_MAX_NUM_CANDS];
						// call ME
                        // 运动估计
						xMotionEstimation ( pcCU, pcOrgYuv, iPartIdx, eRefPicList, &cMvPredBi[iRefList][iRefIdxTemp], iRefIdxTemp, cMvTemp[iRefList][iRefIdxTemp], uiBitsTemp, uiCostTemp, true );
						xCopyAMVPInfo(&aacAMVPInfo[iRefList][iRefIdxTemp], pcCU->getCUMvField(eRefPicList)->getAMVPInfo());
                        // 检查最好的MVP
                        xCheckBestMVP(pcCU, eRefPicList, cMvTemp[iRefList][iRefIdxTemp], cMvPredBi[iRefList][iRefIdxTemp], aaiMvpIdxBi[iRefList][iRefIdxTemp], uiBitsTemp, uiCostTemp);

                        // 如果找到了一个代价更小的方式,那么更新
						if ( uiCostTemp < uiCostBi )
						{
							bChanged = true;

							cMvBi[iRefList]     = cMvTemp[iRefList][iRefIdxTemp];
							iRefIdxBi[iRefList] = iRefIdxTemp;

							uiCostBi            = uiCostTemp;
							uiMotBits[iRefList] = uiBitsTemp - uiMbBits[2] - uiMotBits[1-iRefList];
							uiBits[2]           = uiBitsTemp;

							if(iNumIter!=1)
							{
								//  Set motion
								pcCU->getCUMvField( eRefPicList )->setAllMv( cMvBi[iRefList], ePartSize, uiPartAddr, 0, iPartIdx );
								pcCU->getCUMvField( eRefPicList )->setAllRefIdx( iRefIdxBi[iRefList], ePartSize, uiPartAddr, 0, iPartIdx );

								TComYuv* pcYuvPred = &m_acYuvPred[iRefList];
								motionCompensation( pcCU, pcYuvPred, eRefPicList, iPartIdx );
							}
						}
					} // for loop-iRefIdxTemp

                    // 最小代价没有更新
					if ( !bChanged )
					{
						if ( uiCostBi <= uiCost[0] && uiCostBi <= uiCost[1] )
						{
							xCopyAMVPInfo(&aacAMVPInfo[0][iRefIdxBi[0]], pcCU->getCUMvField(REF_PIC_LIST_0)->getAMVPInfo());
							xCheckBestMVP(pcCU, REF_PIC_LIST_0, cMvBi[0], cMvPredBi[0][iRefIdxBi[0]], aaiMvpIdxBi[0][iRefIdxBi[0]], uiBits[2], uiCostBi);
							if(!pcCU->getSlice()->getMvdL1ZeroFlag())
							{
								xCopyAMVPInfo(&aacAMVPInfo[1][iRefIdxBi[1]], pcCU->getCUMvField(REF_PIC_LIST_1)->getAMVPInfo());
								xCheckBestMVP(pcCU, REF_PIC_LIST_1, cMvBi[1], cMvPredBi[1][iRefIdxBi[1]], aaiMvpIdxBi[1][iRefIdxBi[1]], uiBits[2], uiCostBi);
							}
						}
						break;
					}
				} // for loop-iter
			} // if (B_SLICE)
#if ZERO_MVD_EST
			if ( (pcCU->getSlice()->isInterB()) && (pcCU->isBipredRestriction(iPartIdx) == false) )
			{
				m_pcRdCost->getMotionCost( 1, 0 );

				for ( Int iL0RefIdxTemp = 0; iL0RefIdxTemp <= pcCU->getSlice()->getNumRefIdx(REF_PIC_LIST_0)-1; iL0RefIdxTemp++ )
					for ( Int iL1RefIdxTemp = 0; iL1RefIdxTemp <= pcCU->getSlice()->getNumRefIdx(REF_PIC_LIST_1)-1; iL1RefIdxTemp++ )
					{
						UInt uiRefIdxBitsTemp = 0;
						if ( pcCU->getSlice()->getNumRefIdx(REF_PIC_LIST_0) > 1 )
						{
							uiRefIdxBitsTemp += iL0RefIdxTemp+1;
							if ( iL0RefIdxTemp == pcCU->getSlice()->getNumRefIdx(REF_PIC_LIST_0)-1 ) uiRefIdxBitsTemp--;
						}
						if ( pcCU->getSlice()->getNumRefIdx(REF_PIC_LIST_1) > 1 )
						{
							uiRefIdxBitsTemp += iL1RefIdxTemp+1;
							if ( iL1RefIdxTemp == pcCU->getSlice()->getNumRefIdx(REF_PIC_LIST_1)-1 ) uiRefIdxBitsTemp--;
						}

						Int iL0MVPIdx = 0;
						Int iL1MVPIdx = 0;

						for (iL0MVPIdx = 0; iL0MVPIdx < aaiMvpNum[0][iL0RefIdxTemp]; iL0MVPIdx++)
						{
							for (iL1MVPIdx = 0; iL1MVPIdx < aaiMvpNum[1][iL1RefIdxTemp]; iL1MVPIdx++)
							{
								uiZeroMvdBitsTemp = uiRefIdxBitsTemp;
								uiZeroMvdBitsTemp += uiMbBits[2];
								uiZeroMvdBitsTemp += m_auiMVPIdxCost[iL0MVPIdx][aaiMvpNum[0][iL0RefIdxTemp]] + m_auiMVPIdxCost[iL1MVPIdx][aaiMvpNum[1][iL1RefIdxTemp]];
								uiZeroMvdBitsTemp += 4; //zero mvd for both directions
								pcCU->getCUMvField( REF_PIC_LIST_0 )->setAllMvField( aacAMVPInfo[0][iL0RefIdxTemp].m_acMvCand[iL0MVPIdx], iL0RefIdxTemp, ePartSize, uiPartAddr, iPartIdx, 0 );
								pcCU->getCUMvField( REF_PIC_LIST_1 )->setAllMvField( aacAMVPInfo[1][iL1RefIdxTemp].m_acMvCand[iL1MVPIdx], iL1RefIdxTemp, ePartSize, uiPartAddr, iPartIdx, 0 );

								xGetInterPredictionError( pcCU, pcOrgYuv, iPartIdx, uiZeroMvdDistTemp, m_pcEncCfg->getUseHADME() );
								uiZeroMvdCostTemp = uiZeroMvdDistTemp + m_pcRdCost->getCost( uiZeroMvdBitsTemp );
								if (uiZeroMvdCostTemp < uiZeroMvdCost)
								{
									uiZeroMvdCost = uiZeroMvdCostTemp;
									iZeroMvdDir = 3;
									aiZeroMvdMvpIdx[0] = iL0MVPIdx;
									aiZeroMvdMvpIdx[1] = iL1MVPIdx;
									aiZeroMvdRefIdx[0] = iL0RefIdxTemp;
									aiZeroMvdRefIdx[1] = iL1RefIdxTemp;
									auiZeroMvdBits[2] = uiZeroMvdBitsTemp;
								}
							}
						}
					}
			}
#endif

#if AMP_MRG
		} //end if bTestNormalMC
#endif
		//  Clear Motion Field
		pcCU->getCUMvField(REF_PIC_LIST_0)->setAllMvField( TComMvField(), ePartSize, uiPartAddr, 0, iPartIdx );
		pcCU->getCUMvField(REF_PIC_LIST_1)->setAllMvField( TComMvField(), ePartSize, uiPartAddr, 0, iPartIdx );
		pcCU->getCUMvField(REF_PIC_LIST_0)->setAllMvd    ( cMvZero,       ePartSize, uiPartAddr, 0, iPartIdx );
		pcCU->getCUMvField(REF_PIC_LIST_1)->setAllMvd    ( cMvZero,       ePartSize, uiPartAddr, 0, iPartIdx );

		pcCU->setMVPIdxSubParts( -1, REF_PIC_LIST_0, uiPartAddr, iPartIdx, pcCU->getDepth(uiPartAddr));
		pcCU->setMVPNumSubParts( -1, REF_PIC_LIST_0, uiPartAddr, iPartIdx, pcCU->getDepth(uiPartAddr));
		pcCU->setMVPIdxSubParts( -1, REF_PIC_LIST_1, uiPartAddr, iPartIdx, pcCU->getDepth(uiPartAddr));
		pcCU->setMVPNumSubParts( -1, REF_PIC_LIST_1, uiPartAddr, iPartIdx, pcCU->getDepth(uiPartAddr));

		UInt uiMEBits = 0;
		// Set Motion Field_
		cMv[1] = mvValidList1;
		iRefIdx[1] = refIdxValidList1;
		uiBits[1] = bitsValidList1;
		uiCost[1] = costValidList1;
#if AMP_MRG
		if (bTestNormalMC)
		{
#endif
#if ZERO_MVD_EST
			if (uiZeroMvdCost <= uiCostBi && uiZeroMvdCost <= uiCost[0] && uiZeroMvdCost <= uiCost[1])
			{
				if (iZeroMvdDir == 3)
				{
					uiLastMode = 2;

					pcCU->getCUMvField(REF_PIC_LIST_0)->setAllMvField( aacAMVPInfo[0][aiZeroMvdRefIdx[0]].m_acMvCand[aiZeroMvdMvpIdx[0]], aiZeroMvdRefIdx[0], ePartSize, uiPartAddr, iPartIdx, 0 );
					pcCU->getCUMvField(REF_PIC_LIST_1)->setAllMvField( aacAMVPInfo[1][aiZeroMvdRefIdx[1]].m_acMvCand[aiZeroMvdMvpIdx[1]], aiZeroMvdRefIdx[1], ePartSize, uiPartAddr, iPartIdx, 0 );

					pcCU->setInterDirSubParts( 3, uiPartAddr, iPartIdx, pcCU->getDepth(0) );

					pcCU->setMVPIdxSubParts( aiZeroMvdMvpIdx[0], REF_PIC_LIST_0, uiPartAddr, iPartIdx, pcCU->getDepth(uiPartAddr));
					pcCU->setMVPNumSubParts( aaiMvpNum[0][aiZeroMvdRefIdx[0]], REF_PIC_LIST_0, uiPartAddr, iPartIdx, pcCU->getDepth(uiPartAddr));
					pcCU->setMVPIdxSubParts( aiZeroMvdMvpIdx[1], REF_PIC_LIST_1, uiPartAddr, iPartIdx, pcCU->getDepth(uiPartAddr));
					pcCU->setMVPNumSubParts( aaiMvpNum[1][aiZeroMvdRefIdx[1]], REF_PIC_LIST_1, uiPartAddr, iPartIdx, pcCU->getDepth(uiPartAddr));
					uiMEBits = auiZeroMvdBits[2];
				}
				else if (iZeroMvdDir == 1)
				{        
					uiLastMode = 0;

					pcCU->getCUMvField(REF_PIC_LIST_0)->setAllMvField( aacAMVPInfo[0][aiZeroMvdRefIdx[0]].m_acMvCand[aiZeroMvdMvpIdx[0]], aiZeroMvdRefIdx[0], ePartSize, uiPartAddr, iPartIdx, 0 );

					pcCU->setInterDirSubParts( 1, uiPartAddr, iPartIdx, pcCU->getDepth(0) );

					pcCU->setMVPIdxSubParts( aiZeroMvdMvpIdx[0], REF_PIC_LIST_0, uiPartAddr, iPartIdx, pcCU->getDepth(uiPartAddr));
					pcCU->setMVPNumSubParts( aaiMvpNum[0][aiZeroMvdRefIdx[0]], REF_PIC_LIST_0, uiPartAddr, iPartIdx, pcCU->getDepth(uiPartAddr));
					uiMEBits = auiZeroMvdBits[0];
				}
				else if (iZeroMvdDir == 2)
				{
					uiLastMode = 1;

					pcCU->getCUMvField(REF_PIC_LIST_1)->setAllMvField( aacAMVPInfo[1][aiZeroMvdRefIdx[1]].m_acMvCand[aiZeroMvdMvpIdx[1]], aiZeroMvdRefIdx[1], ePartSize, uiPartAddr, iPartIdx, 0 );

					pcCU->setInterDirSubParts( 2, uiPartAddr, iPartIdx, pcCU->getDepth(0) );

					pcCU->setMVPIdxSubParts( aiZeroMvdMvpIdx[1], REF_PIC_LIST_1, uiPartAddr, iPartIdx, pcCU->getDepth(uiPartAddr));
					pcCU->setMVPNumSubParts( aaiMvpNum[1][aiZeroMvdRefIdx[1]], REF_PIC_LIST_1, uiPartAddr, iPartIdx, pcCU->getDepth(uiPartAddr));
					uiMEBits = auiZeroMvdBits[1];
				}
				else
				{
					assert(0);
				}
			}
			else
#endif
				if ( uiCostBi <= uiCost[0] && uiCostBi <= uiCost[1])
				{
					uiLastMode = 2;
					pcCU->getCUMvField(REF_PIC_LIST_0)->setAllMv( cMvBi[0], ePartSize, uiPartAddr, 0, iPartIdx );
					pcCU->getCUMvField(REF_PIC_LIST_0)->setAllRefIdx( iRefIdxBi[0], ePartSize, uiPartAddr, 0, iPartIdx );
					pcCU->getCUMvField(REF_PIC_LIST_1)->setAllMv( cMvBi[1], ePartSize, uiPartAddr, 0, iPartIdx );
					pcCU->getCUMvField(REF_PIC_LIST_1)->setAllRefIdx( iRefIdxBi[1], ePartSize, uiPartAddr, 0, iPartIdx );

					TempMv = cMvBi[0] - cMvPredBi[0][iRefIdxBi[0]];
					pcCU->getCUMvField(REF_PIC_LIST_0)->setAllMvd    ( TempMv,                 ePartSize, uiPartAddr, 0, iPartIdx );

					TempMv = cMvBi[1] - cMvPredBi[1][iRefIdxBi[1]];
					pcCU->getCUMvField(REF_PIC_LIST_1)->setAllMvd    ( TempMv,                 ePartSize, uiPartAddr, 0, iPartIdx );

					pcCU->setInterDirSubParts( 3, uiPartAddr, iPartIdx, pcCU->getDepth(0) );

					pcCU->setMVPIdxSubParts( aaiMvpIdxBi[0][iRefIdxBi[0]], REF_PIC_LIST_0, uiPartAddr, iPartIdx, pcCU->getDepth(uiPartAddr));
					pcCU->setMVPNumSubParts( aaiMvpNum[0][iRefIdxBi[0]], REF_PIC_LIST_0, uiPartAddr, iPartIdx, pcCU->getDepth(uiPartAddr));
					pcCU->setMVPIdxSubParts( aaiMvpIdxBi[1][iRefIdxBi[1]], REF_PIC_LIST_1, uiPartAddr, iPartIdx, pcCU->getDepth(uiPartAddr));
					pcCU->setMVPNumSubParts( aaiMvpNum[1][iRefIdxBi[1]], REF_PIC_LIST_1, uiPartAddr, iPartIdx, pcCU->getDepth(uiPartAddr));

					uiMEBits = uiBits[2];
				}
				else if ( uiCost[0] <= uiCost[1] )
				{
					uiLastMode = 0;
					pcCU->getCUMvField(REF_PIC_LIST_0)->setAllMv( cMv[0], ePartSize, uiPartAddr, 0, iPartIdx );
					pcCU->getCUMvField(REF_PIC_LIST_0)->setAllRefIdx( iRefIdx[0], ePartSize, uiPartAddr, 0, iPartIdx );
					TempMv = cMv[0] - cMvPred[0][iRefIdx[0]];
					pcCU->getCUMvField(REF_PIC_LIST_0)->setAllMvd    ( TempMv,                 ePartSize, uiPartAddr, 0, iPartIdx );
					pcCU->setInterDirSubParts( 1, uiPartAddr, iPartIdx, pcCU->getDepth(0) );

					pcCU->setMVPIdxSubParts( aaiMvpIdx[0][iRefIdx[0]], REF_PIC_LIST_0, uiPartAddr, iPartIdx, pcCU->getDepth(uiPartAddr));
					pcCU->setMVPNumSubParts( aaiMvpNum[0][iRefIdx[0]], REF_PIC_LIST_0, uiPartAddr, iPartIdx, pcCU->getDepth(uiPartAddr));

					uiMEBits = uiBits[0];
				}
				else
				{
					uiLastMode = 1;
					pcCU->getCUMvField(REF_PIC_LIST_1)->setAllMv( cMv[1], ePartSize, uiPartAddr, 0, iPartIdx );
					pcCU->getCUMvField(REF_PIC_LIST_1)->setAllRefIdx( iRefIdx[1], ePartSize, uiPartAddr, 0, iPartIdx );
					TempMv = cMv[1] - cMvPred[1][iRefIdx[1]];
					pcCU->getCUMvField(REF_PIC_LIST_1)->setAllMvd    ( TempMv,                 ePartSize, uiPartAddr, 0, iPartIdx );
					pcCU->setInterDirSubParts( 2, uiPartAddr, iPartIdx, pcCU->getDepth(0) );

					pcCU->setMVPIdxSubParts( aaiMvpIdx[1][iRefIdx[1]], REF_PIC_LIST_1, uiPartAddr, iPartIdx, pcCU->getDepth(uiPartAddr));
					pcCU->setMVPNumSubParts( aaiMvpNum[1][iRefIdx[1]], REF_PIC_LIST_1, uiPartAddr, iPartIdx, pcCU->getDepth(uiPartAddr));

					uiMEBits = uiBits[1];
				}
#if AMP_MRG
		} // end if bTestNormalMC
#endif

        // 如果分割类型不是2Nx2N
		if ( pcCU->getPartitionSize( uiPartAddr ) != SIZE_2Nx2N )
		{
			UInt uiMRGInterDir = 0;     
			TComMvField cMRGMvField[2];
			UInt uiMRGIndex = 0;

			UInt uiMEInterDir = 0;
			TComMvField cMEMvField[2];

			m_pcRdCost->getMotionCost( 1, 0 );
#if AMP_MRG
			// calculate ME cost
			UInt uiMEError = MAX_UINT;
			UInt uiMECost = MAX_UINT;

			if (bTestNormalMC)
			{
				xGetInterPredictionError( pcCU, pcOrgYuv, iPartIdx, uiMEError, m_pcEncCfg->getUseHADME() );
				uiMECost = uiMEError + m_pcRdCost->getCost( uiMEBits );
			}
#else
			// calculate ME cost
			UInt uiMEError = MAX_UINT;
			xGetInterPredictionError( pcCU, pcOrgYuv, iPartIdx, uiMEError, m_pcEncCfg->getUseHADME() );
			UInt uiMECost = uiMEError + m_pcRdCost->getCost( uiMEBits );
#endif 
			// save ME result.
			uiMEInterDir = pcCU->getInterDir( uiPartAddr );
			pcCU->getMvField( pcCU, uiPartAddr, REF_PIC_LIST_0, cMEMvField[0] );
			pcCU->getMvField( pcCU, uiPartAddr, REF_PIC_LIST_1, cMEMvField[1] );

			// find Merge result
			UInt uiMRGCost = MAX_UINT;
            // 合并估计信息
			xMergeEstimation( pcCU, pcOrgYuv, iPartIdx, uiMRGInterDir, cMRGMvField, uiMRGIndex, uiMRGCost, cMvFieldNeighbours, uhInterDirNeighbours, numValidMergeCand);
			if ( uiMRGCost < uiMECost )
			{
				// set Merge result
				pcCU->setMergeFlagSubParts ( true,          uiPartAddr, iPartIdx, pcCU->getDepth( uiPartAddr ) );
				pcCU->setMergeIndexSubParts( uiMRGIndex,    uiPartAddr, iPartIdx, pcCU->getDepth( uiPartAddr ) );
				pcCU->setInterDirSubParts  ( uiMRGInterDir, uiPartAddr, iPartIdx, pcCU->getDepth( uiPartAddr ) );
				pcCU->getCUMvField( REF_PIC_LIST_0 )->setAllMvField( cMRGMvField[0], ePartSize, uiPartAddr, 0, iPartIdx );
				pcCU->getCUMvField( REF_PIC_LIST_1 )->setAllMvField( cMRGMvField[1], ePartSize, uiPartAddr, 0, iPartIdx );

				pcCU->getCUMvField(REF_PIC_LIST_0)->setAllMvd    ( cMvZero,            ePartSize, uiPartAddr, 0, iPartIdx );
				pcCU->getCUMvField(REF_PIC_LIST_1)->setAllMvd    ( cMvZero,            ePartSize, uiPartAddr, 0, iPartIdx );

				pcCU->setMVPIdxSubParts( -1, REF_PIC_LIST_0, uiPartAddr, iPartIdx, pcCU->getDepth(uiPartAddr));
				pcCU->setMVPNumSubParts( -1, REF_PIC_LIST_0, uiPartAddr, iPartIdx, pcCU->getDepth(uiPartAddr));
				pcCU->setMVPIdxSubParts( -1, REF_PIC_LIST_1, uiPartAddr, iPartIdx, pcCU->getDepth(uiPartAddr));
				pcCU->setMVPNumSubParts( -1, REF_PIC_LIST_1, uiPartAddr, iPartIdx, pcCU->getDepth(uiPartAddr));
			}
			else
			{
				// set ME result
				pcCU->setMergeFlagSubParts( false,        uiPartAddr, iPartIdx, pcCU->getDepth( uiPartAddr ) );
				pcCU->setInterDirSubParts ( uiMEInterDir, uiPartAddr, iPartIdx, pcCU->getDepth( uiPartAddr ) );
				pcCU->getCUMvField( REF_PIC_LIST_0 )->setAllMvField( cMEMvField[0], ePartSize, uiPartAddr, 0, iPartIdx );
				pcCU->getCUMvField( REF_PIC_LIST_1 )->setAllMvField( cMEMvField[1], ePartSize, uiPartAddr, 0, iPartIdx );
			}
		}

		//  MC
        // 运动补偿
		motionCompensation ( pcCU, rpcPredYuv, REF_PIC_LIST_X, iPartIdx );

	} //  end of for ( Int iPartIdx = 0; iPartIdx < iNumPart; iPartIdx++ )

	setWpScalingDistParam( pcCU, -1, REF_PIC_LIST_X );

	return;
}


HM编码器代码阅读(14)——帧间预测之二predInterSearch(inter模式)

标签:

原文地址:http://blog.csdn.net/nb_vol_1/article/details/51162391

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!