幀間預測--時域伸縮MV函數分析

感謝前輩HEVC_CJL,附上前輩專欄:http://blog.csdn.net/HEVC_CJL

這個函數在Merge模式下的getInterMergeCandidates中和AMVP模式下的fillMvpCand都被調用了,主要用來獲取時域候選列表需要的MVxGetColMVP調用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;
  }
}




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章