getInterMergeCandidates是Merge技术候选列表的实现。空域:选取的顺序为A1->B1->B0->A0->(B2)。其中,B2只有在A1,B1,B0,A0中有一个不存在或者帧内预测的情况才可使用。时域:一般情况下首先考虑的是H位置,当H位置不存在或者编码模式使用的是帧内编码模式或者超出了CTU的边界时,选择C3位置。
//! Construct a list of merging candidates
#if NH_3D
Void TComDataCU::getInterMergeCandidates( UInt uiAbsPartIdx, UInt uiPUIdx, TComMvField* pcMvFieldNeighbours, UChar* puhInterDirNeighbours, Int& numValidMergeCand, Int mrgCandIdx )
#else
Void TComDataCU::getInterMergeCandidates( UInt uiAbsPartIdx, UInt uiPUIdx, TComMvField* pcMvFieldNeighbours, UChar* puhInterDirNeighbours, Int& numValidMergeCand, Int mrgCandIdx ) const
#endif
{
UInt uiAbsPartAddr = m_absZIdxInCtu + uiAbsPartIdx; //!< 当前CU的ZScan地址
#if NH_3D_MLC
Bool abCandIsInter[ MRG_MAX_NUM_CANDS_MEM ];
#else
Bool abCandIsInter[ MRG_MAX_NUM_CANDS ];
#endif
for( UInt ui = 0; ui < getSlice()->getMaxNumMergeCand(); ++ui )
{
abCandIsInter[ui] = false;
pcMvFieldNeighbours[ ( ui << 1 ) ].setRefIdx(NOT_VALID);
pcMvFieldNeighbours[ ( ui << 1 ) + 1 ].setRefIdx(NOT_VALID);
}
numValidMergeCand = getSlice()->getMaxNumMergeCand();//候选列表的数目
// compute the location of the current PU
Int xP, yP, nPSW, nPSH;
this->getPartPosition(uiPUIdx, xP, yP, nPSW, nPSH);//!< 获得当前PU的地址和大小
Int iCount = 0;//标记候选列表的数目
UInt uiPartIdxLT, uiPartIdxRT, uiPartIdxLB;
PartSize cCurPS = getPartitionSize( uiAbsPartIdx );//!< CU的分割模式
deriveLeftRightTopIdxGeneral( uiAbsPartIdx, uiPUIdx, uiPartIdxLT, uiPartIdxRT );//!< 左上部uiPartIdxLT,右上部uiPartIdxRT
deriveLeftBottomIdxGeneral( uiAbsPartIdx, uiPUIdx, uiPartIdxLB );//!< 左下部uiPartIdxLB
//left A1
UInt uiLeftPartIdx = 0;
const TComDataCU *pcCULeft = getPULeft( uiLeftPartIdx, uiPartIdxLB );//A1
Bool isAvailableA1 = pcCULeft &&
pcCULeft->isDiffMER(xP -1, yP+nPSH-1, xP, yP) &&
!( uiPUIdx == 1 && (cCurPS == SIZE_Nx2N || cCurPS == SIZE_nLx2N || cCurPS == SIZE_nRx2N) ) &&
pcCULeft->isInter( uiLeftPartIdx ) ;//A1是否可用。。 当CU的划分模式为SIZE_Nx2N、SIZE_nLx2N或SIZE_nRx2N,PU2不能使用A1的mv
if ( isAvailableA1 )//A1可用
{
#if NH_3D_MLC
m_bAvailableFlagA1 = 1;
#endif
abCandIsInter[iCount] = true;
// get Inter Dir
puhInterDirNeighbours[iCount] = pcCULeft->getInterDir( uiLeftPartIdx );
// get Mv from Left
TComDataCU::getMvField( pcCULeft, uiLeftPartIdx, REF_PIC_LIST_0, pcMvFieldNeighbours[iCount<<1] );//从A1中得到mv,存入pcMvFieldNeighbours[iCount<<1]
if ( getSlice()->isInterB() )
{
TComDataCU::getMvField( pcCULeft, uiLeftPartIdx, REF_PIC_LIST_1, pcMvFieldNeighbours[(iCount<<1)+1] );
}
if ( mrgCandIdx == iCount )
{
return;
}
iCount ++;
}
// early termination
if (iCount == getSlice()->getMaxNumMergeCand())
{
return;
}
// above B1
UInt uiAbovePartIdx = 0;
const TComDataCU *