帧间预测(一)Void TComDataCU ::getInterMergeCandidates


对应Merge模式的建立

/** Constructs a list of merging candidates
 * \param uiAbsPartIdx
 * \param uiPUIdx
 * \param uiDepth
 * \param pcMvFieldNeighbours
 * \param puhInterDirNeighbours
 * \param numValidMergeCand
 */
Void  TComDataCU  ::getInterMergeCandidates(  UInt  uiAbsPartIdx ,  UInt  uiPUIdx  ,  TComMvField *  pcMvFieldNeighbours ,  UChar  *  puhInterDirNeighbours ,  Int &  numValidMergeCand  ,  Int  mrgCandIdx  )
{
   UInt  uiAbsPartAddr = m_absZIdxInCtu +  uiAbsPartIdx ;
   Bool  abCandIsInter[  MRG_MAX_NUM_CANDS  ];
   for (  UInt  ui = 0; ui < getSlice()->getMaxNumMergeCand(); ++ui )  //!< m_maxNumMergeCand=5
  {
    abCandIsInter[ui] =  false ;
     pcMvFieldNeighbours [ ( ui << 1 )     ].setRefIdx(  NOT_VALID );
     pcMvFieldNeighbours [ ( ui << 1 ) + 1 ].setRefIdx(  NOT_VALID );
  }
   numValidMergeCand  = getSlice()->getMaxNumMergeCand();
   // compute the location of the current PU
   Int  xP, yP, nPSW, nPSH;
   this ->getPartPosition(  uiPUIdx , xP, yP, nPSW, nPSH); //uiPUIdx为分割索引号,加入采取NxN模式,则为4块,此时取值0,1,2,3

   Int  iCount = 0;

   UInt  uiPartIdxLT, uiPartIdxRT, uiPartIdxLB;
   PartSize  cCurPS = getPartitionSize(  uiAbsPartIdx  );
  deriveLeftRightTopIdxGeneral(  uiAbsPartIdx ,  uiPUIdx  , uiPartIdxLT, uiPartIdxRT ); //获得此时PU的左顶方和右顶方的Z值
  deriveLeftBottomIdxGeneral(  uiAbsPartIdx ,  uiPUIdx  , uiPartIdxLB );

   //left
   UInt  uiLeftPartIdx = 0;
   TComDataCU * pcCULeft = 0;
  pcCULeft = getPULeft( uiLeftPartIdx, uiPartIdxLB );  //uiLeftPartIdx为左边的PU地址

   Bool  isAvailableA1 = pcCULeft &&
                       pcCULeft->isDiffMER(xP -1, yP+nPSH-1, xP, yP) &&
                       !(  uiPUIdx  == 1 && (cCurPS ==  SIZE_Nx2N  || cCurPS ==  SIZE_nLx2N  || cCurPS ==  SIZE_nRx2N ) ) &&
                       pcCULeft->isInter( uiLeftPartIdx ) ;

   if  ( isAvailableA1 )
  {
    abCandIsInter[iCount] =  true ;
     // get Inter Dir
     puhInterDirNeighbours [iCount] = pcCULeft->getInterDir( uiLeftPartIdx );  //L0,L1,Bi
     // get Mv from Left
    pcCULeft->getMvField( pcCULeft, uiLeftPartIdx,  REF_PIC_LIST_0 ,  pcMvFieldNeighbours  [iCount<<1] );
     if  ( getSlice()->isInterB() )
    {
      pcCULeft->getMvField( pcCULeft, uiLeftPartIdx,  REF_PIC_LIST_1 ,  pcMvFieldNeighbours [(iCount<<1)+1] ); //获得左侧A1的参考帧MV与参考帧索引

    }
     if  (  mrgCandIdx  == iCount )
    {
       return ;
    }
    iCount ++;
  }

   // early termination
   if  (iCount == getSlice()->getMaxNumMergeCand())
  {
     return ;
  }
   // above
   UInt  uiAbovePartIdx = 0;
   TComDataCU * pcCUAbove = 0;
  pcCUAbove = getPUAbove( uiAbovePartIdx, uiPartIdxRT );

   Bool  isAvailableB1 = pcCUAbove &&
                       pcCUAbove->isDiffMER(xP+nPSW-1, yP-1, xP, yP) &&
                       !(  uiPUIdx  == 1 && (cCurPS ==  SIZE_2NxN  || cCurPS ==  SIZE_2NxnU  || cCurPS ==  SIZE_2NxnD ) ) &&
                       pcCUAbove->isInter( uiAbovePartIdx );

   if  ( isAvailableB1 && (!isAvailableA1 || !pcCULeft->hasEqualMotion( uiLeftPartIdx, pcCUAbove, uiAbovePartIdx ) ) )
  {
    abCandIsInter[iCount] =  true ;
     // get Inter Dir
     puhInterDirNeighbours [iCount] = pcCUAbove->getInterDir( uiAbovePartIdx );
     // get Mv from Left
    pcCUAbove->getMvField( pcCUAbove, uiAbovePartIdx,  REF_PIC_LIST_0 ,  pcMvFieldNeighbours [iCount<<1] );
     if  ( getSlice()->isInterB() )
    {
      pcCUAbove->getMvField( pcCUAbove, uiAbovePartIdx,  REF_PIC_LIST_1 ,  pcMvFieldNeighbours [(iCount<<1)+1] );
    }
     if  (  mrgCandIdx  == iCount )
    {
       return ;
    }
    iCount ++;
  }
   // early termination
   if  (iCount == getSlice()->getMaxNumMergeCand())
  {
     return ;
  }

   // above right
   UInt  uiAboveRightPartIdx = 0;
   TComDataCU * pcCUAboveRight = 0;
  pcCUAboveRight = getPUAboveRight( uiAboveRightPartIdx, uiPartIdxRT );

   Bool  isAvailableB0 = pcCUAboveRight &&
                       pcCUAboveRight->isDiffMER(xP+nPSW, yP-1, xP, yP) &&
                       pcCUAboveRight->isInter( uiAboveRightPartIdx );

   if  ( isAvailableB0 && ( !isAvailableB1 || !pcCUAbove->hasEqualMotion( uiAbovePartIdx, pcCUAboveRight, uiAboveRightPartIdx ) ) )
  {
    abCandIsInter[iCount] =  true ;
     // get Inter Dir
     puhInterDirNeighbours [iCount] = pcCUAboveRight->getInterDir( uiAboveRightPartIdx );
     // get Mv from Left
    pcCUAboveRight->getMvField( pcCUAboveRight, uiAboveRightPartIdx,  REF_PIC_LIST_0 ,  pcMvFieldNeighbours [iCount<<1] );
     if  ( getSlice()->isInterB() )
    {
      pcCUAboveRight->getMvField( pcCUAboveRight, uiAboveRightPartIdx,  REF_PIC_LIST_1 ,  pcMvFieldNeighbours [(iCount<<1)+1] );
    }
     if  (  mrgCandIdx  == iCount )
    {
       return ;
    }
    iCount ++;
  }
   // early termination
   if  (iCount == getSlice()->getMaxNumMergeCand())
  {
     return ;
  }

   //left bottom
   UInt  uiLeftBottomPartIdx = 0;
   TComDataCU * pcCULeftBottom = 0;
  pcCULeftBottom =  this ->getPUBelowLeft( uiLeftBottomPartIdx, uiPartIdxLB );

   Bool  isAvailableA0 = pcCULeftBottom &&
                       pcCULeftBottom->isDiffMER(xP-1, yP+nPSH, xP, yP) &&
                       pcCULeftBottom->isInter( uiLeftBottomPartIdx ) ;

   if  ( isAvailableA0 && ( !isAvailableA1 || !pcCULeft->hasEqualMotion( uiLeftPartIdx, pcCULeftBottom, uiLeftBottomPartIdx ) ) )
  {
    abCandIsInter[iCount] =  true ;
     // get Inter Dir
     puhInterDirNeighbours [iCount] = pcCULeftBottom->getInterDir( uiLeftBottomPartIdx );
     // get Mv from Left
    pcCULeftBottom->getMvField( pcCULeftBottom, uiLeftBottomPartIdx,  REF_PIC_LIST_0 ,  pcMvFieldNeighbours [iCount<<1] );
     if  ( getSlice()->isInterB() )
    {
      pcCULeftBottom->getMvField( pcCULeftBottom, uiLeftBottomPartIdx,  REF_PIC_LIST_1 ,  pcMvFieldNeighbours [(iCount<<1)+1] );
    }
     if  (  mrgCandIdx  == iCount )
    {
       return ;
    }
    iCount ++;
  }
   // early termination
   if  (iCount == getSlice()->getMaxNumMergeCand())
  {
     return ;
  }

   // above left
   if ( iCount < 4 )
  {
     UInt  uiAboveLeftPartIdx = 0;
     TComDataCU * pcCUAboveLeft = 0;
    pcCUAboveLeft = getPUAboveLeft( uiAboveLeftPartIdx, uiAbsPartAddr );

     Bool  isAvailableB2 = pcCUAboveLeft &&
                         pcCUAboveLeft->isDiffMER(xP-1, yP-1, xP, yP) &&
                         pcCUAboveLeft->isInter( uiAboveLeftPartIdx );

     if  ( isAvailableB2 && ( !isAvailableA1 || !pcCULeft->hasEqualMotion( uiLeftPartIdx, pcCUAboveLeft, uiAboveLeftPartIdx ) )
        && ( !isAvailableB1 || !pcCUAbove->hasEqualMotion( uiAbovePartIdx, pcCUAboveLeft, uiAboveLeftPartIdx ) ) )
    {
      abCandIsInter[iCount] =  true ;
       // get Inter Dir
       puhInterDirNeighbours [iCount] = pcCUAboveLeft->getInterDir( uiAboveLeftPartIdx );
       // get Mv from Left
      pcCUAboveLeft->getMvField( pcCUAboveLeft, uiAboveLeftPartIdx,  REF_PIC_LIST_0 ,  pcMvFieldNeighbours [iCount<<1] );
       if  ( getSlice()->isInterB() )
      {
        pcCUAboveLeft->getMvField( pcCUAboveLeft, uiAboveLeftPartIdx,  REF_PIC_LIST_1 ,  pcMvFieldNeighbours [(iCount<<1)+1] );
      }
       if  (  mrgCandIdx  == iCount )
      {
         return ;
      }
      iCount ++;
    }
  }
   // early termination
   if  (iCount == getSlice()->getMaxNumMergeCand())
  {
     return ;
  }

   if  ( getSlice()->getEnableTMVPFlag() )  //时域候选列表的建立
  {
     //>> MTK colocated-RightBottom
     UInt  uiPartIdxRB;

    deriveRightBottomIdx(  uiPUIdx , uiPartIdxRB );

     UInt  uiAbsPartIdxTmp = g_auiZscanToRaster[uiPartIdxRB];
     const  UInt  numPartInCtuWidth  = m_pcPic->getNumPartInCtuWidth();
     const  UInt  numPartInCtuHeight = m_pcPic->getNumPartInCtuHeight();

     TComMv  cColMv;
     Int  iRefIdx;
     Int  ctuRsAddr = -1;

     if  (   ( ( m_pcPic->getCtu(m_ctuRsAddr)->getCUPelX() + g_auiRasterToPelX[uiAbsPartIdxTmp] + m_pcPic->getMinCUWidth () ) < m_pcSlice->getSPS()->getPicWidthInLumaSamples () )   // image boundary check
        && ( ( m_pcPic->getCtu(m_ctuRsAddr)->getCUPelY() + g_auiRasterToPelY[uiAbsPartIdxTmp] + m_pcPic->getMinCUHeight() ) < m_pcSlice->getSPS()->getPicHeightInLumaSamples() ) )
    {
       if  ( ( uiAbsPartIdxTmp % numPartInCtuWidth < numPartInCtuWidth - 1 ) &&            // is not at the last column of CTU
        ( uiAbsPartIdxTmp / numPartInCtuWidth < numPartInCtuHeight - 1 ) )               // is not at the last row    of CTU
      {
        uiAbsPartAddr = g_auiRasterToZscan[ uiAbsPartIdxTmp + numPartInCtuWidth + 1 ];  //获得同位PU的Z地址
        ctuRsAddr = getCtuRsAddr();  //获得同位PU所在的CTU的首地址
      }
       else  if  ( uiAbsPartIdxTmp % numPartInCtuWidth < numPartInCtuWidth - 1 )            // is not at the last column of CTU But is last row of CTU
      {
        uiAbsPartAddr = g_auiRasterToZscan[ (uiAbsPartIdxTmp + numPartInCtuWidth + 1) % m_pcPic->getNumPartitionsInCtu() ];
      }
       else  if  ( uiAbsPartIdxTmp / numPartInCtuWidth < numPartInCtuHeight - 1 )           // is not at the last row of CTU But is last column of CTU
      {
        uiAbsPartAddr = g_auiRasterToZscan[ uiAbsPartIdxTmp + 1 ];
        ctuRsAddr = getCtuRsAddr() + 1;
      }
       else  //is the right bottom corner of CTU
      {
        uiAbsPartAddr = 0;
      }
    }

    iRefIdx = 0;

     Bool  bExistMV =  false ;
     UInt  uiPartIdxCenter;
     Int  dir = 0;
     UInt  uiArrayAddr = iCount;
    xDeriveCenterIdx(  uiPUIdx , uiPartIdxCenter );
    bExistMV = ctuRsAddr >= 0 && xGetColMVP(  REF_PIC_LIST_0 , ctuRsAddr, uiAbsPartAddr, cColMv, iRefIdx );
                cout<<iRefIdx<<endl;
     if ( bExistMV ==  false  )
    {
      bExistMV = xGetColMVP(  REF_PIC_LIST_0 , getCtuRsAddr(), uiPartIdxCenter,  cColMv, iRefIdx );
    }
     if ( bExistMV )
    {
      dir |= 1;
       pcMvFieldNeighbours [ 2 * uiArrayAddr ].setMvField( cColMv, iRefIdx );
    }

     if  ( getSlice()->isInterB() )
    {
      bExistMV = ctuRsAddr >= 0 && xGetColMVP(  REF_PIC_LIST_1 , ctuRsAddr, uiAbsPartAddr, cColMv, iRefIdx);
       if ( bExistMV ==  false  )
      {
        bExistMV = xGetColMVP(  REF_PIC_LIST_1 , getCtuRsAddr(), uiPartIdxCenter, cColMv, iRefIdx );
      }
       if ( bExistMV )
      {
        dir |= 2;
         pcMvFieldNeighbours [ 2 * uiArrayAddr + 1 ].setMvField( cColMv, iRefIdx );
      }
    }

     if  (dir != 0)
    {
       puhInterDirNeighbours [uiArrayAddr] = dir;
      abCandIsInter[uiArrayAddr] =  true ;

       if  (  mrgCandIdx  == iCount )
      {
         return ;
      }
      iCount++;
    }
  }
   // early termination
   if  (iCount == getSlice()->getMaxNumMergeCand())
  {
     return ;
  }

   UInt  uiArrayAddr = iCount;
   UInt  uiCutoff = uiArrayAddr;
//建立组合列表
   if  ( getSlice()->isInterB() )
  {
     static  const  UInt  NUM_PRIORITY_LIST=12;
     static  const  UInt  uiPriorityList0[NUM_PRIORITY_LIST] = {0 , 1, 0, 2, 1, 2, 0, 3, 1, 3, 2, 3};
     static  const  UInt  uiPriorityList1[NUM_PRIORITY_LIST] = {1 , 0, 2, 0, 2, 1, 3, 0, 3, 1, 3, 2};

     for  ( Int  idx=0; idx<uiCutoff*(uiCutoff-1) && uiArrayAddr!= getSlice()->getMaxNumMergeCand(); idx++)
    {
       assert (idx<NUM_PRIORITY_LIST);
       Int  i = uiPriorityList0[idx];
       Int  j = uiPriorityList1[idx];
       if  (abCandIsInter[i] && abCandIsInter[j]&& ( puhInterDirNeighbours  [i]&0x1)&&( puhInterDirNeighbours [j]&0x2))
      {
        abCandIsInter[uiArrayAddr] =  true ;
         puhInterDirNeighbours [uiArrayAddr] = 3;

         // get Mv from cand[i] and cand[j]
         pcMvFieldNeighbours [uiArrayAddr << 1].setMvField( pcMvFieldNeighbours [i<<1].getMv(),  pcMvFieldNeighbours [i<<1].getRefIdx());
         pcMvFieldNeighbours [( uiArrayAddr << 1 ) + 1].setMvField( pcMvFieldNeighbours [(j<<1)+1].getMv(),  pcMvFieldNeighbours [(j<<1)+1].getRefIdx());

         Int  iRefPOCL0 = m_pcSlice->getRefPOC(  REF_PIC_LIST_0 ,  pcMvFieldNeighbours [(uiArrayAddr<<1)].getRefIdx() );
         Int  iRefPOCL1 = m_pcSlice->getRefPOC(  REF_PIC_LIST_1 ,  pcMvFieldNeighbours [(uiArrayAddr<<1)+1].getRefIdx() );
         if  (iRefPOCL0 == iRefPOCL1 &&  pcMvFieldNeighbours [(uiArrayAddr<<1)].getMv() ==  pcMvFieldNeighbours [(uiArrayAddr<<1)+1].getMv())
        {
          abCandIsInter[uiArrayAddr] =  false ;
        }
         else
        {
          uiArrayAddr++;
        }
      }
    }
  }
   // early termination
   if  (uiArrayAddr == getSlice()->getMaxNumMergeCand())
  {
     return ;
  }

   Int  iNumRefIdx = (getSlice()->isInterB()) ? min(m_pcSlice->getNumRefIdx(  REF_PIC_LIST_0 ), m_pcSlice->getNumRefIdx( REF_PIC_LIST_1  )) : m_pcSlice->getNumRefIdx( REF_PIC_LIST_0 );

   Int  r = 0;
   Int  refcnt = 0;
   while  (uiArrayAddr < getSlice()->getMaxNumMergeCand())
  {
    abCandIsInter[uiArrayAddr] =  true ;
     puhInterDirNeighbours [uiArrayAddr] = 1;
     pcMvFieldNeighbours [uiArrayAddr << 1].setMvField(  TComMv (0, 0), r);

     if  ( getSlice()->isInterB() )
    {
       puhInterDirNeighbours [uiArrayAddr] = 3;
       pcMvFieldNeighbours [(uiArrayAddr << 1) + 1].setMvField(  TComMv (0, 0), r);
    }
    uiArrayAddr++;

     if  ( refcnt == iNumRefIdx - 1 )
    {
      r = 0;
    }
     else
    {
      ++r;
      ++refcnt;
    }
  }
   numValidMergeCand  = uiArrayAddr;
}







/**
 * \param eRefPicList
 * \param uiCUAddr
 * \param uiPartUnitIdx
 * \param riRefIdx
 * \returns Bool
 */
Bool  TComDataCU  ::xGetColMVP(  RefPicList  eRefPicList ,  Int  ctuRsAddr ,  Int  uiPartUnitIdx  ,  TComMv &  rcMv ,  Int  &  riRefIdx  )  //得到同位pu的运动向量
{
   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  *pColCtu = pColPic->getCtu(  ctuRsAddr  );
   if (pColCtu->getPic()==0||pColCtu->getPartitionSize(  uiPartUnitIdx )== NUMBER_OF_PART_SIZES  )
  {
     return  false ;
  }
  iCurrPOC = m_pcSlice->getPOC();
  iColPOC = pColCtu->getSlice()->getPOC();

   if  (!pColCtu->isInter(uiAbsPartAddr))
  {
     return  false ;
  }

  eColRefPicList = getSlice()->getCheckLDC() ?  eRefPicList  :  RefPicList  (getSlice()->getColFromL0Flag());

   Int  iColRefIdx = pColCtu->getCUMvField(  RefPicList (eColRefPicList))->getRefIdx(uiAbsPartAddr);

   if  (iColRefIdx < 0 )
  {
    eColRefPicList =  RefPicList (1 - eColRefPicList);
    iColRefIdx = pColCtu->getCUMvField(  RefPicList (eColRefPicList))->getRefIdx(uiAbsPartAddr);

     if  (iColRefIdx < 0 )
    {
       return  false ;
    }
  }

   // Scale the vector.
  iColRefPOC = pColCtu->getSlice()->getRefPOC(eColRefPicList, iColRefIdx);
  cColMv = pColCtu->getCUMvField(eColRefPicList)->getMv(uiAbsPartAddr);

  iCurrRefPOC = m_pcSlice->getRefPic(  eRefPicList ,  riRefIdx  )->getPOC();

   Bool  bIsCurrRefLongTerm = m_pcSlice->getRefPic(  eRefPicList ,  riRefIdx  )->getIsLongTerm();
   Bool  bIsColRefLongTerm = pColCtu->getSlice()->getIsUsedAsLongTerm(eColRefPicList, iColRefIdx);

   if  ( bIsCurrRefLongTerm != bIsColRefLongTerm )
  {
     return  false ;
  }

   if  ( bIsCurrRefLongTerm || bIsColRefLongTerm )
  {
     rcMv  = cColMv;
  }
   else
  {
    iScale = xGetDistScaleFactor(iCurrPOC, iCurrRefPOC, iColPOC, iColRefPOC);
     if  ( iScale == 4096 )
    {
       rcMv  = cColMv;
    }
     else
    {
       rcMv  = cColMv.scaleMv( iScale );  //获得MV的的时域向量
    }
  }

   return  true ;
}


你可能感兴趣的:(帧间预测(一)Void TComDataCU ::getInterMergeCandidates)