对应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
;
}