本文对该函数进行较为详细的分析:
[cpp]
Bool TComDataCU::xGetColMVP( RefPicList eRefPicList, Int uiCUAddr, Int uiPartUnitIdx, TComMv& rcMv, Int& riRefIdx )
{//! 这部分的内容可以参考draft 8.5.2.1.7, Derivation process for temporal luma motion vector prediction
//! 这个函数的返回条件可以参考该部分的第3小点,The variables mvLXCol and availableFlagLXCol are derived as follows ...
UInt uiAbsPartAddr = uiPartUnitIdx;
RefPicList eColRefPicList;
Int iColPOC, iColRefPOC, iCurrPOC, iCurrRefPOC, iScale;
TComMv cColMv;
// use coldir.
//! Colocated Picture
TComPic *pColPic = getSlice()->getRefPic( RefPicList(getSlice()->isInterB() ? 1-getSlice()->getColFromL0Flag() : 0), getSlice()->getColRefIdx());
//! Colocated CU
TComDataCU *pColCU = pColPic->getCU( uiCUAddr );
if(pColCU->getPic()==0||pColCU->getPartitionSize(uiPartUnitIdx)==SIZE_NONE) //!< Colocated Picture or colocated CU不存在
{
return false;
}
iCurrPOC = m_pcSlice->getPOC(); //!< 当前slice的POC
iCurrRefPOC = m_pcSlice->getRefPic(eRefPicList, riRefIdx)->getPOC(); //!< 当前slice参考帧的POC
iColPOC = pColCU->getSlice()->getPOC(); //!< 当前slice的colocated picuture的POC
if (pColCU->isIntra(uiAbsPartAddr)) //!< colocated CU为帧内预测模式,即没有MV,故直接返回false
{
return false;
}
eColRefPicList = getSlice()->getCheckLDC() ? eRefPicList : RefPicList(getSlice()->getColFromL0Flag());
Int iColRefIdx = pColCU->getCUMvField(RefPicList(eColRefPicList))->getRefIdx(uiAbsPartAddr); //!< colocated CU对应的参考帧的序号
if (iColRefIdx < 0 )
{
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()->getRefPic(eColRefPicList, iColRefIdx)->getIsUsedAsLongTerm();
if ( bIsCurrRefLongTerm != bIsColRefLongTerm )
{
return false;
}
if ( bIsCurrRefLongTerm || bIsColRefLongTerm )
{
rcMv = cColMv; //!< draft 式子(8-155)
}
else
{
iScale = xGetDistScaleFactor(iCurrPOC, iCurrRefPOC, iColPOC, iColRefPOC); //!< 接下来分析
if ( iScale == 4096 )
{
rcMv = cColMv;
}
else
{
rcMv = cColMv.scaleMv( iScale ); //!< draft 式子(8-158)
}
}
return true;
}
[cpp]
Int TComDataCU::xGetDistScaleFactor(Int iCurrPOC, Int iCurrRefPOC, Int iColPOC, Int iColRefPOC)
{
Int iDiffPocD = iColPOC - iColRefPOC; //!< draft 式子(8-159)
Int iDiffPocB = iCurrPOC - iCurrRefPOC; //!< draft 式子(8-160)
if( iDiffPocD == iDiffPocB )
{
return 4096;
}
else
{ www.zzzyk.com
Int iTDB = Clip3( -128, 127, iDiffPocB );
Int iTDD = Clip3( -128, 127, iDiffPocD );
Int iX = (0x4000 + abs(iTDD/2)) / iTDD; //!< draft 式子(8-156)
Int iScale = Clip3( -4096, 4095, (iTDB * iX + 32) >> 6 ); //!< draft 式子(8-157)
return iScale;
}
}
[cpp]
const TComMv scaleMv( Int iScale ) const
{//! draft 式子(8-158)
Int mvx = Clip3( -32768, 32767, (iScale * getHor() + 127 + (iScale * getHor() < 0)) >> 8 );
Int mvy = Clip3( -32768, 32767, (iScale * getVer() + 127 + (iScale * getVer() < 0)) >> 8 );
return TComMv( mvx, mvy );
}