(轉載請註明出處)
候選列表的建立包括兩部分,一個是Merge模式,一個是AMVP模式,因爲這部分代碼中涉及到了較多其他模塊的參數,對新手讀起來可能不容易理解,我盡力把我作爲一個新手的理解過程表述出來,當然代碼我看了好幾遍纔看懂,沒辦法,經驗是個很重要的東西,沒人帶路,不走幾遍哪來的經驗。
先熟悉一下代碼結構:
定位代碼:
atrl+F查找encmain.cpp裏的入口,從外到裏的調用層次爲:
①int main()->encode(),調了cTAppEncTop類裏的encode()函數
②encode()->encode,調用了處理one frame 的函數m_cTEncTop.encode()
③encode->compressGOP,encode裏獲取源圖片,計算image characteristics,最後調用編碼GOP的m_cGOPEncoder.compressGOP()。
④compressGOP->precompressSlice->compressSlice與compressGOP->compressSlice,這裏通過自帶的註釋先了解各大概。
⑤compressSlice->compressCU->xCompressCU,compressCU調用xCompressCU編碼CU,xCompressCU還遞歸調用自身進行編碼(這和CU的四叉樹劃分方式有關)。
⑥xCompressCU->xCheckRDCostInter,這裏調用的xCheckRDCostInter主要就是完成inter預測的主要部分。
⑦xCheckRDCostInter->predInterSearch->xMergeEstimation->getInterMergeCandidates
直接定位到getInterMergeCandidate,這個是建立Merge使用的候選列表。
⑦xCheckRDCostInter -> predInterSearch -> xEstimateMvPredAMVP->fillMvpCand,這個建立是AMVP模式下的候選列表
另外,代碼中,skip和merge的關係,可以這樣理解,預測模式有三種:skip、Merge、AMVP,其中skip模式僅傳輸運動參數集索引,skip相當於merge模式在2Nx2N情況下的特例,單獨在xCheckRDCostMerge2Nx2N中實現,其他全在xCheckRDCostInter中。
Merge候選列表的建立:
表格的而建立,先是獲得當前PU地址,按左,上,右上,左下,左上的順序依次將相鄰PU的信息填入列表中。
處理左塊,左塊可用的條件:左塊所在CU存在,與當前塊一個ME,不是左右分割情況下的第二塊,不是幀內預測模式。左塊可用,將標誌位設爲true,並把左塊dir(方向)和mv(距離)放到對應的矩陣。
如果當前Slice是B slice,還需要填充另一個mv到list1中。其他塊的處理方式與左塊無異,就是要注意一下:B1與A1mv相同,B1不用;B1與B0相同,B0不用。A0的mv不同於A1時,A0纔可用。B2的mv不同於A1、B1時,B2纔可用。
建立時域候選列表,先右下角再中部的順序,再建立B幀用的建立組合列表,最後數目不夠的時補零。
Void TComDataCU::getInterMergeCandidates( UInt uiAbsPartIdx, UInt uiPUIdx, TComMvField* pcMvFieldNeighbours, UChar* puhInterDirNeighbours, Int& numValidMergeCand, Int mrgCandIdx )
{//每次處理一個PU
UInt uiAbsPartAddr = m_uiAbsIdxInLCU + uiAbsPartIdx;//當前PU地址
Bool abCandIsInter[ MRG_MAX_NUM_CANDS ];//Merge最大候選數量爲5
for( UInt ui = 0; ui < getSlice()->getMaxNumMergeCand(); ++ui )//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);//獲得當前PU的位置和大小
Int iCount = 0;//!< 統計merge candidate的個數
UInt uiPartIdxLT, uiPartIdxRT, uiPartIdxLB;//!<分別標識左上、右上、左下
PartSize cCurPS = getPartitionSize( uiAbsPartIdx );//!<CU的分割模式
deriveLeftRightTopIdxGeneral( uiAbsPartIdx, uiPUIdx, uiPartIdxLT, uiPartIdxRT );
deriveLeftBottomIdxGeneral ( uiAbsPartIdx, uiPUIdx, uiPartIdxLB );
//lefti
UInt uiLeftPartIdx = 0;
TComDataCU* pcCULeft = 0;
pcCULeft = getPULeft( uiLeftPartIdx, uiPartIdxLB );//左
Bool isAvailableA1 = pcCULeft &&//A1是否可用
pcCULeft->isDiffMER(xP -1, yP+nPSH-1, xP, yP) &&//!<MER當前PU與其相鄰PU不在同一個ME區域
!( uiPUIdx == 1 && (cCurPS == SIZE_Nx2N || cCurPS == SIZE_nLx2N || cCurPS == SIZE_nRx2N) ) &&//劃分方式不爲左右劃分時的第二塊
!pcCULeft->isIntra( uiLeftPartIdx ) ;//不是幀內預測
if ( isAvailableA1 )//!<A1可用
{
abCandIsInter[iCount] = true;//A1的標誌位改爲可用
// get Inter Dir幀間方向
puhInterDirNeighbours[iCount] = pcCULeft->getInterDir( uiLeftPartIdx );//!<inter dir分L0,L1,Bi
// get Mv from Left,將pcCULeft的MV存放到pcMvFieldNeighbours中
pcCULeft->getMvField( pcCULeft, uiLeftPartIdx, REF_PIC_LIST_0, pcMvFieldNeighbours[iCount<<1] );
if ( getSlice()->isInterB() )//B slice 存在兩個mv,再存一個
{
pcCULeft->getMvField( pcCULeft, uiLeftPartIdx, REF_PIC_LIST_1, pcMvFieldNeighbours[(iCount<<1)+1] );
}
if ( mrgCandIdx == iCount )//候選數量如果等於mrgCandIdx就返回
{
return;
}
iCount ++;
}
// early termination
if (iCount == getSlice()->getMaxNumMergeCand())
{
return;
}
// above與上面處理A1的方式類似
UInt uiAbovePartIdx = 0;//同上一個,上方塊的idx
TComDataCU* pcCUAbove = 0;//
pcCUAbove = getPUAbove( uiAbovePartIdx, uiPartIdxRT );//上方CU的地址
Bool isAvailableB1 = pcCUAbove &&//上方CU存在
pcCUAbove->isDiffMER(xP+nPSW-1, yP-1, xP, yP) &&//上放與當前在同一個ME塊中
!( uiPUIdx == 1 && (cCurPS == SIZE_2NxN || cCurPS == SIZE_2NxnU || cCurPS == SIZE_2NxnD) ) &&//當前PU不是上下分割模式的第二個
!pcCUAbove->isIntra( uiAbovePartIdx );//不是幀內
if ( isAvailableB1 && (!isAvailableA1 || !pcCULeft->hasEqualMotion( uiLeftPartIdx, pcCUAbove, uiAbovePartIdx ) ) )//B1可用且A1存在時mv不同於A1
{
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->isIntra( uiAboveRightPartIdx );
if ( isAvailableB0 && ( !isAvailableB1 || !pcCUAbove->hasEqualMotion( uiAbovePartIdx, pcCUAboveRight, uiAboveRightPartIdx ) ) )//B1可用且B1不同於B0
{
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->isIntra( uiLeftBottomPartIdx ) ;
if ( isAvailableA0 && ( !isAvailableA1 || !pcCULeft->hasEqualMotion( uiLeftPartIdx, pcCULeftBottom, uiLeftBottomPartIdx ) ) )//!<A0可用且MV不同於A1
{
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->isIntra( uiAboveLeftPartIdx );
if ( isAvailableB2 && ( !isAvailableA1 || !pcCULeft->hasEqualMotion( uiLeftPartIdx, pcCUAboveLeft, uiAboveLeftPartIdx ) )//B2與B1、A1的mv做比較
&& ( !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()) //可用的merge candidates達到最大值,返回
{
return;
}
//2.時域候選列表
if ( getSlice()->getEnableTMVPFlag())//default is 1
{
//>> MTK colocated-RightBottom
UInt uiPartIdxRB;
Int uiLCUIdx = getAddr();
deriveRightBottomIdx( uiPUIdx, uiPartIdxRB ); //獲取
UInt uiAbsPartIdxTmp = g_auiZscanToRaster[uiPartIdxRB];//轉換掃描順序
UInt uiNumPartInCUWidth = m_pcPic->getNumPartInWidth();//CU的寬度
TComMv cColMv;
Int iRefIdx;
if ( ( m_pcPic->getCU(m_uiCUAddr)->getCUPelX() + g_auiRasterToPelX[uiAbsPartIdxTmp] + m_pcPic->getMinCUWidth() ) >= m_pcSlice->getSPS()->getPicWidthInLumaSamples() ) // image boundary check
{
uiLCUIdx = -1;
}//橫座標超出圖像邊界
else if ( ( m_pcPic->getCU(m_uiCUAddr)->getCUPelY() + g_auiRasterToPelY[uiAbsPartIdxTmp] + m_pcPic->getMinCUHeight() ) >= m_pcSlice->getSPS()->getPicHeightInLumaSamples() )
{
uiLCUIdx = -1;
}//縱座標超出圖像邊界
else
{
if ( ( uiAbsPartIdxTmp % uiNumPartInCUWidth < uiNumPartInCUWidth - 1 ) && // is not at the last column of LCU
( uiAbsPartIdxTmp / uiNumPartInCUWidth < m_pcPic->getNumPartInHeight() - 1 ) ) // is not at the last row of LCU
{
//不在LCU的最後一列且不在LCU的最後一行,SIZE_NxN的第一個PU
uiAbsPartAddr = g_auiRasterToZscan[ uiAbsPartIdxTmp + uiNumPartInCUWidth + 1 ];
uiLCUIdx = getAddr();//與當前pu屬於相同cu
}
else if ( uiAbsPartIdxTmp % uiNumPartInCUWidth < uiNumPartInCUWidth - 1 ) // is not at the last column of LCU But is last row of LCU
{
//不在LCU的最後一列但在LCU的最後一行,SIZE_Nx2N的第1個PU,SIZE_NxN的第3個PU,SIZE_nLx2N的第1個PU,SIZE_nRx2N的第1個PU
uiAbsPartAddr = g_auiRasterToZscan[ (uiAbsPartIdxTmp + uiNumPartInCUWidth + 1) % m_pcPic->getNumPartInCU() ];
uiLCUIdx = -1 ;
}
else if ( uiAbsPartIdxTmp / uiNumPartInCUWidth < m_pcPic->getNumPartInHeight() - 1 ) // is not at the last row of LCU But is last column of LCU
{
//!<?不在LCU的最後一行但在LCU的最後一列,SIZE_2NxN的第1個PU,SIZE_NxN的第2個PU,SIZE_2NxnU的第1個PU,SIZE_2NxnD的第1個PU??
uiAbsPartAddr = g_auiRasterToZscan[ uiAbsPartIdxTmp + 1 ];
uiLCUIdx = getAddr() + 1;
}
else //is the right bottom corner of LCU
{
uiAbsPartAddr = 0;
uiLCUIdx = -1 ;
}
}
//3.中間部分的mv
iRefIdx = 0;
Bool bExistMV = false;
UInt uiPartIdxCenter;
UInt uiCurLCUIdx = getAddr();
Int dir = 0;
UInt uiArrayAddr = iCount;
xDeriveCenterIdx( uiPUIdx, uiPartIdxCenter );//!<根據uiPUIdx計算PU的中心地址uiPartIdxCenter
//獲取colocated的經scaled過的mv。
bExistMV = uiLCUIdx >= 0 && xGetColMVP( REF_PIC_LIST_0, uiLCUIdx, uiAbsPartAddr, cColMv, iRefIdx );
if( bExistMV == false )//右下角MV不存在
{
bExistMV = xGetColMVP( REF_PIC_LIST_0, uiCurLCUIdx, uiPartIdxCenter, cColMv, iRefIdx );
}
if( bExistMV )
{//填充mv
dir |= 1;
pcMvFieldNeighbours[ 2 * uiArrayAddr ].setMvField( cColMv, iRefIdx );
}
//B slice有兩個mv,還得再填一個
if ( getSlice()->isInterB() )
{
bExistMV = uiLCUIdx >= 0 && xGetColMVP( REF_PIC_LIST_1, uiLCUIdx, uiAbsPartAddr, cColMv, iRefIdx);
if( bExistMV == false )
{
bExistMV = xGetColMVP( REF_PIC_LIST_1, uiCurLCUIdx, 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;
//B slice 要建立組合列表
if ( getSlice()->isInterB())
{//!<參考draft?Table?8-6?----?Specification?of?l0CandIdx?and?l1CandIdx
//建立組合列表
UInt uiPriorityList0[12] = {0 , 1, 0, 2, 1, 2, 0, 3, 1, 3, 2, 3};
UInt uiPriorityList1[12] = {1 , 0, 2, 0, 2, 1, 3, 0, 3, 1, 3, 2};
for (Int idx=0; idx<uiCutoff*(uiCutoff-1) && uiArrayAddr!= getSlice()->getMaxNumMergeCand(); idx++)
{
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;
}
//當可用的merge?candidates數目仍小於預設值時,將餘量均設置爲零運動矢量
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;
}
AMVP模式候選列表建立:
類似Merge。這裏我感覺我有理解錯誤的地方。
Void TComDataCU::fillMvpCand ( UInt uiPartIdx, UInt uiPartAddr, RefPicList eRefPicList, Int iRefIdx, AMVPInfo* pInfo )
{
TComMv cMvPred;
Bool bAddedSmvp = false;
pInfo->iN = 0;
if (iRefIdx < 0)
{
return;
}
//AMVP模式下,候選列表長度爲2,空域5個,時域2個,最後只留下2個
//-- Get Spatial MV
UInt uiPartIdxLT, uiPartIdxRT, uiPartIdxLB;
UInt uiNumPartInCUWidth = m_pcPic->getNumPartInWidth();
Bool bAdded = false;
deriveLeftRightTopIdx( uiPartIdx, uiPartIdxLT, uiPartIdxRT );
deriveLeftBottomIdx( uiPartIdx, uiPartIdxLB );
TComDataCU* tmpCU = NULL;
UInt idx;
tmpCU = getPUBelowLeft(idx, uiPartIdxLB);
bAddedSmvp = (tmpCU != NULL) && (tmpCU->getPredictionMode(idx) != MODE_INTRA);
if (!bAddedSmvp)
{
tmpCU = getPULeft(idx, uiPartIdxLB);
bAddedSmvp = (tmpCU != NULL) && (tmpCU->getPredictionMode(idx) != MODE_INTRA);
}
// Left predictor search
bAdded = xAddMVPCand( pInfo, eRefPicList, iRefIdx, uiPartIdxLB, MD_BELOW_LEFT);
if (!bAdded)//左下不行就換左
{
bAdded = xAddMVPCand( pInfo, eRefPicList, iRefIdx, uiPartIdxLB, MD_LEFT );
}
if(!bAdded)
{
bAdded = xAddMVPCandOrder( pInfo, eRefPicList, iRefIdx, uiPartIdxLB, MD_BELOW_LEFT);
if (!bAdded)
{
bAdded = xAddMVPCandOrder( pInfo, eRefPicList, iRefIdx, uiPartIdxLB, MD_LEFT );
}
}
// Above predictor search
bAdded = xAddMVPCand( pInfo, eRefPicList, iRefIdx, uiPartIdxRT, MD_ABOVE_RIGHT);
if (!bAdded)//同樣,右上不行就換右
{
bAdded = xAddMVPCand( pInfo, eRefPicList, iRefIdx, uiPartIdxRT, MD_ABOVE);
}
if(!bAdded)
{
bAdded = xAddMVPCand( pInfo, eRefPicList, iRefIdx, uiPartIdxLT, MD_ABOVE_LEFT);
}
bAdded = bAddedSmvp;
if (pInfo->iN==2) bAdded = true;
if(!bAdded)
{
bAdded = xAddMVPCandOrder( pInfo, eRefPicList, iRefIdx, uiPartIdxRT, MD_ABOVE_RIGHT);
if (!bAdded)
{
bAdded = xAddMVPCandOrder( pInfo, eRefPicList, iRefIdx, uiPartIdxRT, MD_ABOVE);
}
if(!bAdded)//都不行換左上
{
bAdded = xAddMVPCandOrder( pInfo, eRefPicList, iRefIdx, uiPartIdxLT, MD_ABOVE_LEFT);
}
}
if ( pInfo->iN == 2 )
{
if ( pInfo->m_acMvCand[ 0 ] == pInfo->m_acMvCand[ 1 ] )
{
pInfo->iN = 1;
}
}
//時域候選列表的建立
if ( getSlice()->getEnableTMVPFlag() )
{
// Get Temporal Motion Predictor
Int iRefIdx_Col = iRefIdx;
TComMv cColMv;
UInt uiPartIdxRB;
UInt uiAbsPartIdx;
UInt uiAbsPartAddr;
Int uiLCUIdx = getAddr();
deriveRightBottomIdx( uiPartIdx, uiPartIdxRB );
uiAbsPartAddr = m_uiAbsIdxInLCU + uiPartAddr;
//---- co-located RightBottom Temporal Predictor (H) ---//
uiAbsPartIdx = g_auiZscanToRaster[uiPartIdxRB];
if ( ( m_pcPic->getCU(m_uiCUAddr)->getCUPelX() + g_auiRasterToPelX[uiAbsPartIdx] + m_pcPic->getMinCUWidth() ) >= m_pcSlice->getSPS()->getPicWidthInLumaSamples() ) // image boundary check
{
uiLCUIdx = -1;
}
else if ( ( m_pcPic->getCU(m_uiCUAddr)->getCUPelY() + g_auiRasterToPelY[uiAbsPartIdx] + m_pcPic->getMinCUHeight() ) >= m_pcSlice->getSPS()->getPicHeightInLumaSamples() )
{
uiLCUIdx = -1;
}
else
{
if ( ( uiAbsPartIdx % uiNumPartInCUWidth < uiNumPartInCUWidth - 1 ) && // is not at the last column of LCU
( uiAbsPartIdx / uiNumPartInCUWidth < m_pcPic->getNumPartInHeight() - 1 ) ) // is not at the last row of LCU
{
uiAbsPartAddr = g_auiRasterToZscan[ uiAbsPartIdx + uiNumPartInCUWidth + 1 ];
uiLCUIdx = getAddr();
}
else if ( uiAbsPartIdx % uiNumPartInCUWidth < uiNumPartInCUWidth - 1 ) // is not at the last column of LCU But is last row of LCU
{
uiAbsPartAddr = g_auiRasterToZscan[ (uiAbsPartIdx + uiNumPartInCUWidth + 1) % m_pcPic->getNumPartInCU() ];
uiLCUIdx = -1 ;
}
else if ( uiAbsPartIdx / uiNumPartInCUWidth < m_pcPic->getNumPartInHeight() - 1 ) // is not at the last row of LCU But is last column of LCU
{
uiAbsPartAddr = g_auiRasterToZscan[ uiAbsPartIdx + 1 ];
uiLCUIdx = getAddr() + 1;
}
else //is the right bottom corner of LCU
{
uiAbsPartAddr = 0;
uiLCUIdx = -1 ;
}
}
if ( uiLCUIdx >= 0 && xGetColMVP( eRefPicList, uiLCUIdx, uiAbsPartAddr, cColMv, iRefIdx_Col ) )
{
pInfo->m_acMvCand[pInfo->iN++] = cColMv;
}
else
{
UInt uiPartIdxCenter;
UInt uiCurLCUIdx = getAddr();
xDeriveCenterIdx( uiPartIdx, uiPartIdxCenter );
if (xGetColMVP( eRefPicList, uiCurLCUIdx, uiPartIdxCenter, cColMv, iRefIdx_Col ))
{
pInfo->m_acMvCand[pInfo->iN++] = cColMv;
}
}
//---- co-located RightBottom Temporal Predictor ---//
}
if (pInfo->iN > AMVP_MAX_NUM_CANDS)
{
pInfo->iN = AMVP_MAX_NUM_CANDS;
}
while (pInfo->iN < AMVP_MAX_NUM_CANDS)
{
pInfo->m_acMvCand[pInfo->iN].set(0,0);
pInfo->iN++;
}
return ;
}