感谢前辈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;
}
}