感謝前輩HEVC_CJL,附上前輩專欄:http://blog.csdn.net/HEVC_CJL
這個函數在Merge模式下的getInterMergeCandidates中和AMVP模式下的fillMvpCand都被調用了,主要用來獲取時域候選列表需要的MV,xGetColMVP調用xGetDistScaleFactor()完成比例伸縮部分,結合前面的理論部分和代碼註釋,理解起來沒什麼困難。
理論部分:http://blog.csdn.net/m0_37579288/article/details/79244986
1.xGetColMVP
Bool TComDataCU::xGetColMVP( RefPicList eRefPicList, Int uiCUAddr, Int uiPartUnitIdx, TComMv& rcMv, Int& riRefIdx )
{
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 *pColCU = pColPic->getCU( uiCUAddr );//!<同位CU
if(pColCU->getPic()==0||pColCU->getPartitionSize(uiPartUnitIdx)==SIZE_NONE)
{//不存在同位CU或同位幀
return false;
}
iCurrPOC = m_pcSlice->getPOC();//!<當前Slice的POC
iCurrRefPOC = m_pcSlice->getRefPic(eRefPicList, riRefIdx)->getPOC();//參考POC
iColPOC = pColCU->getSlice()->getPOC();//同位Col
if (pColCU->isIntra(uiAbsPartAddr))//不是幀內預測模式
{
return false;
}
eColRefPicList = getSlice()->getCheckLDC() ? eRefPicList : RefPicList(getSlice()->getColFromL0Flag());//同位的參考圖像
Int iColRefIdx = pColCU->getCUMvField(RefPicList(eColRefPicList))->getRefIdx(uiAbsPartAddr);//colref的Idx
if (iColRefIdx < 0 )
{
//同位幀圖像列表的選擇,
//REF_PIC_LIST_0 = 0, reference list 0
//REF_PIC_LIST_1 = 1, reference list 1
//REF_PIC_LIST_C = 2, combined reference list for uni-prediction in B-Slices
//REF_PIC_LIST_X = 100, special mark
eColRefPicList = RefPicList(1 - eColRefPicList);
iColRefIdx = pColCU->getCUMvField(RefPicList(eColRefPicList))->getRefIdx(uiAbsPartAddr);//同位參考圖像的地址
if (iColRefIdx < 0 )
{
return false;
}
}
// Scale the vector.
iColRefPOC = pColCU->getSlice()->getRefPOC(eColRefPicList, iColRefIdx);
cColMv = pColCU->getCUMvField(eColRefPicList)->getMv(uiAbsPartAddr);
iCurrRefPOC = m_pcSlice->getRefPic(eRefPicList, riRefIdx)->getPOC();
Bool bIsCurrRefLongTerm = m_pcSlice->getRefPic(eRefPicList, riRefIdx)->getIsLongTerm();
Bool bIsColRefLongTerm = pColCU->getSlice()->getIsUsedAsLongTerm(eColRefPicList, iColRefIdx);
if ( bIsCurrRefLongTerm != bIsColRefLongTerm )
{
return false;
}
if ( bIsCurrRefLongTerm || bIsColRefLongTerm )
{
rcMv = cColMv;
}
else
{
iScale = xGetDistScaleFactor(iCurrPOC, iCurrRefPOC, iColPOC, iColRefPOC);
if ( iScale == 4096 )//4096爲放大後,實際的比值爲iScale/4096
{
rcMv = cColMv;//距離相同,mv不調整
}
else
{
rcMv = cColMv.scaleMv( iScale );
}
}
return true;
}
2.xGetDistScaleFactor
Int TComDataCU::xGetDistScaleFactor(Int iCurrPOC, Int iCurrRefPOC, Int iColPOC, Int iColRefPOC)
{
Int iDiffPocD = iColPOC - iColRefPOC;//距離
Int iDiffPocB = iCurrPOC - iCurrRefPOC;//距離
if( iDiffPocD == iDiffPocB )
{
return 4096;
}
else
{
Int iTDB = Clip3( -128, 127, iDiffPocB );//限幅
Int iTDD = Clip3( -128, 127, iDiffPocD );//限幅
Int iX = (0x4000 + abs(iTDD/2)) / iTDD;
//這裏我覺得4096是個爲了提高精度而使用的,其實是把兩個的比值擴大了4096倍
//所以4096其實是1,即相等
Int iScale = Clip3( -4096, 4095, (iTDB * iX + 32) >> 6 );
return iScale;
}
}