本文對該函數進行較為詳細的分析: [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.2cto.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 ); }