对应Merge模式的建立
/** Constructs a list of merging candidates
* \param uiAbsPartIdx
* \param uiPUIdx
* \param uiDepth
* \param pcMvFieldNeighbours
* \param puhInterDirNeighbours
* \param numValidMergeCand
*/
Void TComDataCU ::getInterMergeCandidates( UInt uiAbsPartIdx, UInt uiPUIdx , TComMvField* pcMvFieldNeighbours, UChar * puhInterDirNeighbours, Int& numValidMergeCand , Int mrgCandIdx )
{
UInt uiAbsPartAddr
= m_absZIdxInCtu + uiAbsPartIdx;
Bool abCandIsInter[ MRG_MAX_NUM_CANDS ];
for( UInt ui
= 0; ui < getSlice()->getMaxNumMergeCand(); ++ui ) //!< m_maxNumMergeCand=5
{
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);//uiPUIdx为分割索引号,加入采取NxN模式,则为4块,此时取值0,1,2,3
Int iCount
= 0;
UInt uiPartIdxLT,
uiPartIdxRT, uiPartIdxLB;
PartSize cCurPS
= getPartitionSize( uiAbsPartIdx );
deriveLeftRightTopIdxGeneral( uiAbsPartIdx, uiPUIdx ,
uiPartIdxLT, uiPartIdxRT );//获得此时PU的左顶方和右顶方的Z值
deriveLeftBottomIdxGeneral( uiAbsPartIdx, uiPUIdx ,
uiPartIdxLB );
//left
UInt uiLeftPartIdx
= 0;
TComDataCU*
pcCULeft = 0;
pcCULeft = getPULeft( uiLeftPartIdx, uiPartIdxLB ); //uiLeftPartIdx为左边的PU地址
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 ) ;
if (
isAvailableA1 )
{
abCandIsInter[iCount] = true;
//
get Inter Dir
puhInterDirNeighbours[iCount]
= pcCULeft->getInterDir( uiLeftPartIdx ); //L0,L1,Bi
//
get Mv from Left
pcCULeft->getMvField( pcCULeft, uiLeftPartIdx, REF_PIC_LIST_0, pcMvFieldNeighbours [iCount<<1]
);
if (
getSlice()->isInterB() )
{
pcCULeft->getMvField( pcCULeft, uiLeftPartIdx, REF_PIC_LIST_1, pcMvFieldNeighbours[(iCount<<1)+1]
);//获得左侧A1的参考帧MV与参考帧索引
}
if ( mrgCandIdx ==
iCount )
{
return;
}
iCount ++;
}
//
early termination
if (iCount
== getSlice()->getMaxNumMergeCand())
{
return;
}
//
above
UInt uiAbovePartIdx
= 0;
TComDataCU*
pcCUAbove = 0;
pcCUAbove = getPUAbove( uiAbovePartIdx, uiPartIdxRT );
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 );
if (
isAvailableB1 && (!isAvailableA1 || !pcCULeft->hasEqualMotion( uiLeftPartIdx, pcCUAbove, uiAbovePartIdx ) ) )
{
abCandIsInter[iCount] = true;
//
get Inter Dir
puhInterDirNeighbours[iCount]
= pcCUAbove->getInterDir( uiAbovePartIdx );
//
get Mv from Left
pcCUAbove->getMvField( pcCUAbove, uiAbovePartIdx, REF_PIC_LIST_0, pcMvFieldNeighbours[iCount<<1]
);
if (
getSlice()->isInterB() )
{
pcCUAbove->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
UInt uiAboveRightPartIdx
= 0;
TComDataCU*
pcCUAboveRight = 0;
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 ) ) )
{
abCandIsInter[iCount] = true;
//
get Inter Dir
puhInterDirNeighbours[iCount]
= pcCUAboveRight->getInterDir( uiAboveRightPartIdx );
//
get Mv from Left
pcCUAboveRight->getMvField( pcCUAboveRight, uiAboveRightPartIdx, REF_PIC_LIST_0, pcMvFieldNeighbours[iCount<<1]
);
if (
getSlice()->isInterB() )
{
pcCUAboveRight->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
UInt uiLeftBottomPartIdx
= 0;
TComDataCU*
pcCULeftBottom = 0;
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 ) ) )
{
abCandIsInter[iCount] = true;
//
get Inter Dir
puhInterDirNeighbours[iCount]
= pcCULeftBottom->getInterDir( uiLeftBottomPartIdx );
//
get Mv from Left
pcCULeftBottom->getMvField( pcCULeftBottom, uiLeftBottomPartIdx, REF_PIC_LIST_0, pcMvFieldNeighbours[iCount<<1]
);
if (
getSlice()->isInterB() )
{
pcCULeftBottom->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
if(
iCount < 4 )
{
UInt uiAboveLeftPartIdx
= 0;
TComDataCU*
pcCUAboveLeft = 0;
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
) ) )
{
abCandIsInter[iCount] = true;
//
get Inter Dir
puhInterDirNeighbours[iCount]
= pcCUAboveLeft->getInterDir( uiAboveLeftPartIdx );
//
get Mv from Left
pcCUAboveLeft->getMvField( pcCUAboveLeft, uiAboveLeftPartIdx, REF_PIC_LIST_0, pcMvFieldNeighbours[iCount<<1]
);
if (
getSlice()->isInterB() )
{
pcCUAboveLeft->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() ) )
{
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 ]; //获得同位PU的Z地址
ctuRsAddr = getCtuRsAddr(); //获得同位PU所在的CTU的首地址
}
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 );
bExistMV = ctuRsAddr >= 0 && xGetColMVP( REF_PIC_LIST_0,
ctuRsAddr, uiAbsPartAddr, cColMv, iRefIdx );
cout<<iRefIdx<<endl;
if(
bExistMV == false )
{
bExistMV = xGetColMVP( REF_PIC_LIST_0,
getCtuRsAddr(), uiPartIdxCenter, cColMv, iRefIdx );
}
if(
bExistMV )
{
dir |= 1;
pcMvFieldNeighbours[
2 * uiArrayAddr ].setMvField( cColMv, iRefIdx );
}
if (
getSlice()->isInterB() )
{
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 ( mrgCandIdx ==
iCount )
{
return;
}
iCount++;
}
}
//
early termination
if (iCount
== getSlice()->getMaxNumMergeCand())
{
return;
}
UInt uiArrayAddr
= iCount;
UInt uiCutoff
= uiArrayAddr;
//建立组合列表
if (
getSlice()->isInterB() )
{
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())
{
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;
}
/**
* \param eRefPicList
* \param uiCUAddr
* \param uiPartUnitIdx
* \param riRefIdx
* \returns Bool
*/
Bool TComDataCU ::xGetColMVP( RefPicList eRefPicList, Int ctuRsAddr, Int uiPartUnitIdx , TComMv& rcMv, Int & riRefIdx ) //得到同位pu的运动向量
{
UInt uiAbsPartAddr
= uiPartUnitIdx;
RefPicList
eColRefPicList;
Int iColPOC,
iColRefPOC, iCurrPOC, iCurrRefPOC, iScale;
TComMv cColMv;
//
use coldir.
TComPic *pColPic
= getSlice()->getRefPic( RefPicList(getSlice()->isInterB()
? 1-getSlice()->getColFromL0Flag() : 0), getSlice()->getColRefIdx());//得到同位参考帧
TComDataCU *pColCtu
= pColPic->getCtu( ctuRsAddr );
if(pColCtu->getPic()==0||pColCtu->getPartitionSize( uiPartUnitIdx)==NUMBER_OF_PART_SIZES )
{
return false;
}
iCurrPOC = m_pcSlice->getPOC();
iColPOC = pColCtu->getSlice()->getPOC();
if (!pColCtu->isInter(uiAbsPartAddr))
{
return false;
}
eColRefPicList = getSlice()->getCheckLDC() ? eRefPicList : RefPicList (getSlice()->getColFromL0Flag());
Int iColRefIdx
= pColCtu->getCUMvField( RefPicList(eColRefPicList))->getRefIdx(uiAbsPartAddr);
if (iColRefIdx
< 0 )
{
eColRefPicList = RefPicList(1
- eColRefPicList);
iColRefIdx = pColCtu->getCUMvField( RefPicList(eColRefPicList))->getRefIdx(uiAbsPartAddr);
if (iColRefIdx
< 0 )
{
return false;
}
}
//
Scale the vector.
iColRefPOC = pColCtu->getSlice()->getRefPOC(eColRefPicList, iColRefIdx);
cColMv = pColCtu->getCUMvField(eColRefPicList)->getMv(uiAbsPartAddr);
iCurrRefPOC = m_pcSlice->getRefPic( eRefPicList, riRefIdx )->getPOC();
Bool bIsCurrRefLongTerm
= m_pcSlice->getRefPic( eRefPicList, riRefIdx )->getIsLongTerm();
Bool bIsColRefLongTerm
= pColCtu->getSlice()->getIsUsedAsLongTerm(eColRefPicList, iColRefIdx);
if (
bIsCurrRefLongTerm != bIsColRefLongTerm )
{
return false;
}
if (
bIsCurrRefLongTerm || bIsColRefLongTerm )
{
rcMv =
cColMv;
}
else
{
iScale = xGetDistScaleFactor(iCurrPOC, iCurrRefPOC, iColPOC, iColRefPOC);
if (
iScale == 4096 )
{
rcMv =
cColMv;
}
else
{
rcMv =
cColMv.scaleMv( iScale ); //获得MV的的时域向量
}
}
return true;
}