您的位置:首页 > 编程语言

HTM-16.2代码(13)——getInterMergeCandidates

2016-12-28 16:33 253 查看
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 *pcCUAbove = getPUAbove( uiAbovePartIdx, uiPartIdxRT );//B1

Bool isAvailableB1 = pcCUAbove &&
pcCUAbove->isDiffMER(xP+nPSW-1, yP-1, xP, yP) &&
!( uiPUIdx == 1 && (cCurPS == SIZE_2NxN || cCurPS == SIZE_2NxnU || cCurPS == SIZE_2NxnD) ) &&
pcCUAbove->isInter( uiAbovePartIdx );//B1是否可用。。 当CU的划分模式为SIZE_2NxN、SIZE_2NxnU或SIZE_2NxnD,PU2不能使用B1的mv

if ( isAvailableB1 && (!isAvailableA1 || !pcCULeft->hasEqualMotion( uiLeftPartIdx, pcCUAbove, uiAbovePartIdx ) ) )//B1可用,且与A1的mv不相同
{
#if NH_3D_MLC
m_bAvailableFlagB1 = 1;
#endif
abCandIsInter[iCount] = true;
// get Inter Dir
puhInterDirNeighbours[iCount] = pcCUAbove->getInterDir( uiAbovePartIdx );
// get Mv from Left
TComDataCU::getMvField( pcCUAbove, uiAbovePartIdx, REF_PIC_LIST_0, pcMvFieldNeighbours[iCount<<1] );//从B1中得到mv,存入pcMvFieldNeighbours[iCount<<1]
if ( getSlice()->isInterB() )
{
TComDataCU::getMvField( pcCUAbove, uiAbovePartIdx, REF_PIC_LIST_1, pcMvFieldNeighbours[(iCount<<1)+1] );
}
if ( mrgCandIdx == iCount )
{
return;
}
iCount ++;
}
// early termination
if (iCount == getSlice()->getMaxNumMergeCand())
{
return;
}

// above right   B0
UInt uiAboveRightPartIdx = 0;
const TComDataCU *pcCUAboveRight = getPUAboveRight( uiAboveRightPartIdx, uiPartIdxRT );

Bool isAvailableB0 = pcCUAboveRight &&
pcCUAboveRight->isDiffMER(xP+nPSW, yP-1, xP, yP) &&
pcCUAboveRight->isInter( uiAboveRightPartIdx );

if ( isAvailableB0 && ( !isAvailableB1 || !pcCUAbove->hasEqualMotion( uiAbovePartIdx, pcCUAboveRight, uiAboveRightPartIdx ) ) )
{
#if NH_3D_MLC
m_bAvailableFlagB0 = 1;
#endif
abCandIsInter[iCount] = true;
// get Inter Dir
puhInterDirNeighbours[iCount] = pcCUAboveRight->getInterDir( uiAboveRightPartIdx );
// get Mv from Left
TComDataCU::getMvField( pcCUAboveRight, uiAboveRightPartIdx, REF_PIC_LIST_0, pcMvFieldNeighbours[iCount<<1] );
if ( getSlice()->isInterB() )
{
TComDataCU::getMvField( pcCUAboveRight, uiAboveRightPartIdx, REF_PIC_LIST_1, pcMvFieldNeighbours[(iCount<<1)+1] );
}
if ( mrgCandIdx == iCount )
{
return;
}
iCount ++;
}
// early termination
if (iCount == getSlice()->getMaxNumMergeCand())
{
return;
}

//left bottom   A0
UInt uiLeftBottomPartIdx = 0;
const TComDataCU *pcCULeftBottom = this->getPUBelowLeft( uiLeftBottomPartIdx, uiPartIdxLB );

Bool isAvailableA0 = pcCULeftBottom &&
pcCULeftBottom->isDiffMER(xP-1, yP+nPSH, xP, yP) &&
pcCULeftBottom->isInter( uiLeftBottomPartIdx ) ;

if ( isAvailableA0 && ( !isAvailableA1 || !pcCULeft->hasEqualMotion( uiLeftPartIdx, pcCULeftBottom, uiLeftBottomPartIdx ) ) )
{
#if NH_3D_MLC
m_bAvailableFlagA0 = 1;
#endif
abCandIsInter[iCount] = true;
// get Inter Dir
puhInterDirNeighbours[iCount] = pcCULeftBottom->getInterDir( uiLeftBottomPartIdx );
// get Mv from Left
TComDataCU::getMvField( pcCULeftBottom, uiLeftBottomPartIdx, REF_PIC_LIST_0, pcMvFieldNeighbours[iCount<<1] );
if ( getSlice()->isInterB() )
{
TComDataCU::getMvField( pcCULeftBottom, uiLeftBottomPartIdx, REF_PIC_LIST_1, pcMvFieldNeighbours[(iCount<<1)+1] );
}
if ( mrgCandIdx == iCount )
{
return;
}
iCount ++;
}
// early termination
if (iCount == getSlice()->getMaxNumMergeCand())
{
return;
}

// above left   B2
if( iCount < 4 )
{
UInt uiAboveLeftPartIdx = 0;
const TComDataCU *pcCUAboveLeft = getPUAboveLeft( uiAboveLeftPartIdx, uiAbsPartAddr );

Bool isAvailableB2 = pcCUAboveLeft &&
pcCUAboveLeft->isDiffMER(xP-1, yP-1, xP, yP) &&
pcCUAboveLeft->isInter( uiAboveLeftPartIdx );

if ( isAvailableB2 && ( !isAvailableA1 || !pcCULeft->hasEqualMotion( uiLeftPartIdx, pcCUAboveLeft, uiAboveLeftPartIdx ) )
&& ( !isAvailableB1 || !pcCUAbove->hasEqualMotion( uiAbovePartIdx, pcCUAboveLeft, uiAboveLeftPartIdx ) ) )
{
#if NH_3D_MLC
m_bAvailableFlagB2 = 1;
#endif
abCandIsInter[iCount] = true;
// get Inter Dir
puhInterDirNeighbours[iCount] = pcCUAboveLeft->getInterDir( uiAboveLeftPartIdx );
// get Mv from Left
TComDataCU::getMvField( pcCUAboveLeft, uiAboveLeftPartIdx, REF_PIC_LIST_0, pcMvFieldNeighbours[iCount<<1] );
if ( getSlice()->isInterB() )
{
TComDataCU::getMvField( pcCUAboveLeft, uiAboveLeftPartIdx, REF_PIC_LIST_1, pcMvFieldNeighbours[(iCount<<1)+1] );
}
if ( mrgCandIdx == iCount )
{
return;
}
iCount ++;
}
}
// early termination
if (iCount == getSlice()->getMaxNumMergeCand())
{
return;
}

//时域候选列表的建立
if ( getSlice()->getEnableTMVPFlag() )
{
//>> MTK colocated-RightBottom
UInt uiPartIdxRB;

deriveRightBottomIdx( uiPUIdx, uiPartIdxRB );

UInt uiAbsPartIdxTmp = g_auiZscanToRaster[uiPartIdxRB];
const UInt numPartInCtuWidth  = m_pcPic->getNumPartInCtuWidth();
const UInt numPartInCtuHeight = m_pcPic->getNumPartInCtuHeight();

TComMv cColMv;
Int iRefIdx;
Int ctuRsAddr = -1;

if (   ( ( m_pcPic->getCtu(m_ctuRsAddr)->getCUPelX() + g_auiRasterToPelX[uiAbsPartIdxTmp] + m_pcPic->getMinCUWidth () ) < m_pcSlice->getSPS()->getPicWidthInLumaSamples () )  // image boundary check
&& ( ( m_pcPic->getCtu(m_ctuRsAddr)->getCUPelY() + g_auiRasterToPelY[uiAbsPartIdxTmp] + m_pcPic->getMinCUHeight() ) < m_pcSlice->getSPS()->getPicHeightInLumaSamples() ) )
{//得到H的索引uiAbsPartAddr
if ( ( uiAbsPartIdxTmp % numPartInCtuWidth < numPartInCtuWidth - 1 ) &&           // is not at the last column of CTU
( uiAbsPartIdxTmp / numPartInCtuWidth < numPartInCtuHeight - 1 ) )              // is not at the last row    of CTU
{
uiAbsPartAddr = g_auiRasterToZscan[ uiAbsPartIdxTmp + numPartInCtuWidth + 1 ];
ctuRsAddr = getCtuRsAddr();
}
else if ( uiAbsPartIdxTmp % numPartInCtuWidth < numPartInCtuWidth - 1 )           // is not at the last column of CTU But is last row of CTU
{
uiAbsPartAddr = g_auiRasterToZscan[ (uiAbsPartIdxTmp + numPartInCtuWidth + 1) % m_pcPic->getNumPartitionsInCtu() ];
}
else if ( uiAbsPartIdxTmp / numPartInCtuWidth < numPartInCtuHeight - 1 )          // is not at the last row of CTU But is last column of CTU
{
uiAbsPartAddr = g_auiRasterToZscan[ uiAbsPartIdxTmp + 1 ];
ctuRsAddr = getCtuRsAddr() + 1;
}
else //is the right bottom corner of CTU
{
uiAbsPartAddr = 0;
}
}

iRefIdx = 0;

Bool bExistMV = false;
UInt uiPartIdxCenter;
Int dir = 0;
UInt uiArrayAddr = iCount;
xDeriveCenterIdx( uiPUIdx, uiPartIdxCenter );//得到C3的索引uiPartIdxCenter
bExistMV = ctuRsAddr >= 0 && xGetColMVP( REF_PIC_LIST_0, ctuRsAddr, uiAbsPartAddr, cColMv, iRefIdx );//根据H的索引uiAbsPartAddr,得到H的scaled mv
if( bExistMV == false )
{
bExistMV = xGetColMVP( REF_PIC_LIST_0, getCtuRsAddr(), uiPartIdxCenter,  cColMv, iRefIdx );//根据C3的索引uiPartIdxCenter,得到C3的scaled mv
}
if( bExistMV )
{
dir |= 1;
pcMvFieldNeighbours[ 2 * uiArrayAddr ].setMvField( cColMv, iRefIdx );
}

if ( getSlice()->isInterB() )//考虑list1
{
#if NH_3D_TMVP
iRefIdx = 0;
#endif
bExistMV = ctuRsAddr >= 0 && xGetColMVP( REF_PIC_LIST_1, ctuRsAddr, uiAbsPartAddr, cColMv, iRefIdx);
if( bExistMV == false )
{
bExistMV = xGetColMVP( REF_PIC_LIST_1, getCtuRsAddr(), uiPartIdxCenter, cColMv, iRefIdx );
}
if( bExistMV )
{
dir |= 2;
pcMvFieldNeighbours[ 2 * uiArrayAddr + 1 ].setMvField( cColMv, iRefIdx );
}
}

if (dir != 0)
{
puhInterDirNeighbours[uiArrayAddr] = dir;
abCandIsInter[uiArrayAddr] = true;
#if NH_3D_NBDV
pcMvFieldNeighbours[iCount<<1    ].getMv().setIDVFlag (false);
pcMvFieldNeighbours[(iCount<<1)+1].getMv().setIDVFlag (false);
#endif

if ( mrgCandIdx == iCount )
{
return;
}
iCount++;
}
}
// early termination
if (iCount == getSlice()->getMaxNumMergeCand())
{
return;
}

UInt uiArrayAddr = iCount;
UInt uiCutoff = uiArrayAddr;

//组合列表的建立
#if NH_3D_MLC
if ( getSlice()->isInterB() && iCount<5)
#else
if ( getSlice()->isInterB() )
#endif
{
static const UInt NUM_PRIORITY_LIST=12;
static const UInt uiPriorityList0[NUM_PRIORITY_LIST] = {0 , 1, 0, 2, 1, 2, 0, 3, 1, 3, 2, 3};
static const UInt uiPriorityList1[NUM_PRIORITY_LIST] = {1 , 0, 2, 0, 2, 1, 3, 0, 3, 1, 3, 2};

for (Int idx=0; idx<uiCutoff*(uiCutoff-1) && uiArrayAddr!= getSlice()->getMaxNumMergeCand(); idx++)
{
assert(idx<NUM_PRIORITY_LIST);
Int i = uiPriorityList0[idx];
Int j = uiPriorityList1[idx];
if (abCandIsInter[i] && abCandIsInter[j]&& (puhInterDirNeighbours[i]&0x1)&&(puhInterDirNeighbours[j]&0x2))
{
abCandIsInter[uiArrayAddr] = true;
puhInterDirNeighbours[uiArrayAddr] = 3;

// get Mv from cand[i] and cand[j]
pcMvFieldNeighbours[uiArrayAddr << 1].setMvField(pcMvFieldNeighbours[i<<1].getMv(), pcMvFieldNeighbours[i<<1].getRefIdx());
pcMvFieldNeighbours[( uiArrayAddr << 1 ) + 1].setMvField(pcMvFieldNeighbours[(j<<1)+1].getMv(), pcMvFieldNeighbours[(j<<1)+1].getRefIdx());

Int iRefPOCL0 = m_pcSlice->getRefPOC( REF_PIC_LIST_0, pcMvFieldNeighbours[(uiArrayAddr<<1)].getRefIdx() );
Int iRefPOCL1 = m_pcSlice->getRefPOC( REF_PIC_LIST_1, pcMvFieldNeighbours[(uiArrayAddr<<1)+1].getRefIdx() );
if (iRefPOCL0 == iRefPOCL1 && pcMvFieldNeighbours[(uiArrayAddr<<1)].getMv() == pcMvFieldNeighbours[(uiArrayAddr<<1)+1].getMv())
{
abCandIsInter[uiArrayAddr] = false;
}
else
{
uiArrayAddr++;
}
}
}
}
// early termination
if (uiArrayAddr == getSlice()->getMaxNumMergeCand())
{
return;
}

Int iNumRefIdx = (getSlice()->isInterB()) ? min(m_pcSlice->getNumRefIdx(REF_PIC_LIST_0), m_pcSlice->getNumRefIdx(REF_PIC_LIST_1)) : m_pcSlice->getNumRefIdx(REF_PIC_LIST_0);

Int r = 0;
Int refcnt = 0;
while (uiArrayAddr < getSlice()->getMaxNumMergeCand())//! 当可用的merge candidates数目仍小于预设值时,将余量均设置为零运动矢量
{
abCandIsInter[uiArrayAddr] = true;
puhInterDirNeighbours[uiArrayAddr] = 1;
pcMvFieldNeighbours[uiArrayAddr << 1].setMvField( TComMv(0, 0), r);

if ( getSlice()->isInterB() )
{
puhInterDirNeighbours[uiArrayAddr] = 3;
pcMvFieldNeighbours[(uiArrayAddr << 1) + 1].setMvField(TComMv(0, 0), r);
}
uiArrayAddr++;

if ( refcnt == iNumRefIdx - 1 )//!< 达到参考帧列表的参考帧数
{
r = 0;
}
else
{
++r;
++refcnt;
}
}
numValidMergeCand = uiArrayAddr;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: