程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> HEVC幀間預測之一——TComDataCU::getInterMergeCandidates函數分析

HEVC幀間預測之一——TComDataCU::getInterMergeCandidates函數分析

編輯:C++入門知識

 從今天開始,正式轉入到幀間預測方向。由於幀間預測涉及到的方面廣且復雜,所以我的理解出現錯誤的情況可能會更多,請大家以辯證的眼光來看待我的帖子,有問題歡迎大家批評指正。   大家都知道xCompressCU是實際進行預測編碼的函數,故很容易就能鎖定幀間預測的一個大致范圍,在研究了幀內預測的基礎上,相信很快就能在該函數中找到與幀間預測相關的函數:xCheckRDCostInter,xCheckRDCostMerge2Nx2N。前者進行除了merge模式以外的所有幀間預測,後者則是針對merge模式的。由於merge模式相對於H.264來說是個新事物,我們考慮先從研究它入手。   進入到xCheckRDCostMerge2Nx2N函數後,開頭有一個比較重要的函數getInterMergeCandidates,它的功能是創建一個merge list,在該模式中是個很重要的函數,故我們先討論它。下面按照慣例,給出我對這個函數的注釋:   [cpp]   Void TComDataCU::getInterMergeCandidates( UInt uiAbsPartIdx, UInt uiPUIdx, TComMvField* pcMvFieldNeighbours, UChar* puhInterDirNeighbours, Int& numValidMergeCand, Int mrgCandIdx )   {     UInt uiAbsPartAddr = m_uiAbsIdxInLCU + uiAbsPartIdx; //!< 當前CU的ZScan地址     UInt uiIdx = 1;     Bool abCandIsInter[ MRG_MAX_NUM_CANDS ];     for( UInt ui = 0; ui < getSlice()->getMaxNumMergeCand(); ++ui ) //!< m_maxNumMergeCand = 5     {       abCandIsInter[ui] = false;     }     numValidMergeCand = getSlice()->getMaxNumMergeCand(); //!< 5     // compute the location of the current PU     Int xP, yP, nPSW, nPSH;     this->getPartPosition(uiPUIdx, xP, yP, nPSW, nPSH); //!< 獲得當前PU的地址和大小        Int iCount = 0; //!< 統計Merge candidate的個數        UInt uiPartIdxLT, uiPartIdxRT, uiPartIdxLB;     PartSize cCurPS = getPartitionSize( uiAbsPartIdx ); //!< CU的分割模式     deriveLeftRightTopIdxGeneral( uiAbsPartIdx, uiPUIdx, uiPartIdxLT, uiPartIdxRT ); //!< 左上部,右上部     deriveLeftBottomIdxGeneral  ( uiAbsPartIdx, uiPUIdx, uiPartIdxLB ); //!< 左下部        //left     UInt uiLeftPartIdx = 0;     TComDataCU* pcCULeft = 0;     pcCULeft = getPULeft( uiLeftPartIdx, uiPartIdxLB, true, false );   #if MERGE_CLEANUP_AND_K0197 //!< 在有多個PU在一個CU中的時候,去除第二個PU對A1和B1的依賴性     Bool isAvailableA1 = pcCULeft &&     pcCULeft->isDiffMER(xP -1, yP+nPSH-1, xP, yP) && //!< 當前PU和它的相鄰PU不在同一個ME區域     !( uiPUIdx == 1 && (cCurPS == SIZE_Nx2N || cCurPS == SIZE_nLx2N || cCurPS == SIZE_nRx2N) ) &&     !pcCULeft->isIntra( uiLeftPartIdx ) ;     if ( isAvailableA1 )   #else     if (pcCULeft)     {       if (!pcCULeft->isDiffMER(xP -1, yP+nPSH-1, xP, yP))       {         pcCULeft = NULL;       }     }     PartSize partSize = getPartitionSize( uiAbsPartIdx );     if (!(uiPUIdx == 1 && (partSize == SIZE_Nx2N || partSize == SIZE_nLx2N || partSize == SIZE_nRx2N)))     {     if ( pcCULeft && !pcCULeft->isIntra( uiLeftPartIdx ) )   #endif     {       abCandIsInter[iCount] = true;       // get Inter Dir       puhInterDirNeighbours[iCount] = pcCULeft->getInterDir( uiLeftPartIdx ); //!< inter dir分L0,L1,Bi       // get Mv from Left,將pcCULeft的MV存放到pcMvFieldNeighbours中       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] );       }       if ( mrgCandIdx == iCount )       {         return;       }       iCount ++;     }   #if !MERGE_CLEANUP_AND_K0197     }   #endif          // early termination     if (iCount == getSlice()->getMaxNumMergeCand())      {       return;     }     // above     UInt uiAbovePartIdx = 0;     TComDataCU* pcCUAbove = 0;   #if LINEBUF_CLEANUP     pcCUAbove = getPUAbove( uiAbovePartIdx, uiPartIdxRT, true, false );   #else     pcCUAbove = getPUAbove( uiAbovePartIdx, uiPartIdxRT, true, false, true );   #endif   #if MERGE_CLEANUP_AND_K0197 //!<      Bool isAvailableB1 = pcCUAbove &&     pcCUAbove->isDiffMER(xP+nPSW-1, yP-1, xP, yP) &&     !( uiPUIdx == 1 && (cCurPS == SIZE_2NxN || cCurPS == SIZE_2NxnU || cCurPS == SIZE_2NxnD) ) &&     !pcCUAbove->isIntra( uiAbovePartIdx );     if ( isAvailableB1 && (!isAvailableA1 || !pcCULeft->hasEqualMotion( uiLeftPartIdx, pcCUAbove, uiAbovePartIdx ) ) )   #else//!< 如果A1可用,則檢查A1和B1的MV是否相同,否則不需要檢查     if (pcCUAbove)     {       if (!pcCUAbove->isDiffMER(xP+nPSW-1, yP-1, xP, yP))       {         pcCUAbove = NULL;       }     }     if ( pcCUAbove && !pcCUAbove->isIntra( uiAbovePartIdx )        && !(uiPUIdx == 1 && (cCurPS == SIZE_2NxN || cCurPS == SIZE_2NxnU || cCurPS == SIZE_2NxnD))       && ( !pcCULeft || pcCULeft->isIntra( uiLeftPartIdx ) || !pcCULeft->hasEqualMotion( uiLeftPartIdx, pcCUAbove, uiAbovePartIdx ) ) )   #endif     {       abCandIsInter[iCount] = true;       // get Inter Dir       puhInterDirNeighbours[iCount] = pcCUAbove->getInterDir( uiAbovePartIdx );       // get Mv from Above       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;   #if LINEBUF_CLEANUP     pcCUAboveRight = getPUAboveRight( uiAboveRightPartIdx, uiPartIdxRT, true, false );   #else     pcCUAboveRight = getPUAboveRight( uiAboveRightPartIdx, uiPartIdxRT, true, false, true );   #endif   #if MERGE_CLEANUP_AND_K0197     Bool isAvailableB0 = pcCUAboveRight &&     pcCUAboveRight->isDiffMER(xP+nPSW, yP-1, xP, yP) &&     !pcCUAboveRight->isIntra( uiAboveRightPartIdx );     if ( isAvailableB0 && ( !isAvailableB1 || !pcCUAbove->hasEqualMotion( uiAbovePartIdx, pcCUAboveRight, uiAboveRightPartIdx ) ) )   #else//!< 如果B1可用,則檢查B1和B0的MV是否相同,否則不需要檢查     if (pcCUAboveRight)     {       if (!pcCUAboveRight->isDiffMER(xP+nPSW, yP-1, xP, yP))       {         pcCUAboveRight = NULL;       }     }     if ( pcCUAboveRight && !pcCUAboveRight->isIntra( uiAboveRightPartIdx ) && ( !pcCUAbove || pcCUAbove->isIntra( uiAbovePartIdx ) || !pcCUAbove->hasEqualMotion( uiAbovePartIdx, pcCUAboveRight, uiAboveRightPartIdx ) ) )   #endif     {       abCandIsInter[iCount] = true;       // get Inter Dir       puhInterDirNeighbours[iCount] = pcCUAboveRight->getInterDir( uiAboveRightPartIdx );       // get Mv from AboveRight       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, true, false );   #if MERGE_CLEANUP_AND_K0197     Bool isAvailableA0 = pcCULeftBottom &&     pcCULeftBottom->isDiffMER(xP-1, yP+nPSH, xP, yP) &&     !pcCULeftBottom->isIntra( uiLeftBottomPartIdx ) ;     if ( isAvailableA0 && ( !isAvailableA1 || !pcCULeft->hasEqualMotion( uiLeftPartIdx, pcCULeftBottom, uiLeftBottomPartIdx ) ) )   #else//!< 如果A1可用,則檢查A1和A0的MV是否相同,否則不需要檢查     if (pcCULeftBottom)     {       if (!pcCULeftBottom->isDiffMER(xP-1, yP+nPSH, xP, yP))       {         pcCULeftBottom = NULL;       }     }     if ( pcCULeftBottom && !pcCULeftBottom->isIntra( uiLeftBottomPartIdx ) && ( !pcCULeft || pcCULeft->isIntra( uiLeftPartIdx ) || !pcCULeft->hasEqualMotion( uiLeftPartIdx, pcCULeftBottom, uiLeftBottomPartIdx ) ) )   #endif     {       abCandIsInter[iCount] = true;       // get Inter Dir       puhInterDirNeighbours[iCount] = pcCULeftBottom->getInterDir( uiLeftBottomPartIdx );       // get Mv from LeftBottom       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;   #if LINEBUF_CLEANUP       pcCUAboveLeft = getPUAboveLeft( uiAboveLeftPartIdx, uiAbsPartAddr, true, false );   #else       pcCUAboveLeft = getPUAboveLeft( uiAboveLeftPartIdx, uiAbsPartAddr, true, false, true );   #endif   #if MERGE_CLEANUP_AND_K0197       Bool isAvailableB2 = pcCUAboveLeft &&       pcCUAboveLeft->isDiffMER(xP-1, yP-1, xP, yP) &&       !pcCUAboveLeft->isIntra( uiAboveLeftPartIdx );       if ( isAvailableB2 && ( !isAvailableA1 || !pcCULeft->hasEqualMotion( uiLeftPartIdx, pcCUAboveLeft, uiAboveLeftPartIdx ) )           && ( !isAvailableB1 || !pcCUAbove->hasEqualMotion( uiAbovePartIdx, pcCUAboveLeft, uiAboveLeftPartIdx ) ) )   #else//!< 分別將B2與A1、B1的mv進行比較       if (pcCUAboveLeft)       {         if (!pcCUAboveLeft->isDiffMER(xP-1, yP-1, xP, yP))         {           pcCUAboveLeft = NULL;         }       }       if( pcCUAboveLeft && !pcCUAboveLeft->isIntra( uiAboveLeftPartIdx )        && ( !pcCULeft || pcCULeft->isIntra( uiLeftPartIdx ) || !pcCULeft->hasEqualMotion( uiLeftPartIdx, pcCUAboveLeft, uiAboveLeftPartIdx ) )        && ( !pcCUAbove || pcCUAbove->isIntra( uiAbovePartIdx ) || !pcCUAbove->hasEqualMotion( uiAbovePartIdx, pcCUAboveLeft, uiAboveLeftPartIdx ) )        )   #endif       {         abCandIsInter[iCount] = true;         // get Inter Dir         puhInterDirNeighbours[iCount] = pcCUAboveLeft->getInterDir( uiAboveLeftPartIdx );         // get Mv from AboveLeft         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()) //!< 如果可用的merge candidates達到預設的最大值(5),則提前退出     {       return;     }     if ( getSlice()->getEnableTMVPFlag()) //!< default is 1     {       //>> MTK colocated-RightBottom       UInt uiPartIdxRB;       Int uiLCUIdx = getAddr();          deriveRightBottomIdx( uiPUIdx, uiPartIdxRB ); //!< 當前PU的右下部的地址          UInt uiAbsPartIdxTmp = g_auiZscanToRaster[uiPartIdxRB];       UInt uiNumPartInCUWidth = m_pcPic->getNumPartInWidth(); //!< CU以partition為單位的寬度          TComMv cColMv;       Int iRefIdx;          if      ( ( m_pcPic->getCU(m_uiCUAddr)->getCUPelX() + g_auiRasterToPelX[uiAbsPartIdxTmp] + m_pcPic->getMinCUWidth() ) >= m_pcSlice->getSPS()->getPicWidthInLumaSamples() )  // image boundary check       {         uiLCUIdx = -1;       }//!< 橫坐標超出圖像邊界       else if ( ( m_pcPic->getCU(m_uiCUAddr)->getCUPelY() + g_auiRasterToPelY[uiAbsPartIdxTmp] + m_pcPic->getMinCUHeight() ) >= m_pcSlice->getSPS()->getPicHeightInLumaSamples() )       {         uiLCUIdx = -1;       }//!< 縱坐標超出圖像邊界       else       {         if ( ( uiAbsPartIdxTmp % uiNumPartInCUWidth < uiNumPartInCUWidth - 1 ) &&           // is not at the last column of LCU            ( uiAbsPartIdxTmp / uiNumPartInCUWidth < m_pcPic->getNumPartInHeight() - 1 ) ) // is not at the last row    of LCU         {//!< 不在LCU的最後一列且不在LCU的最後一行,SIZE_NxN的第1個PU           uiAbsPartAddr = g_auiRasterToZscan[ uiAbsPartIdxTmp + uiNumPartInCUWidth + 1 ]; //!< 下一行+1           uiLCUIdx = getAddr(); //!< 與當前PU屬於相同的CU         }         else if ( uiAbsPartIdxTmp % uiNumPartInCUWidth < uiNumPartInCUWidth - 1 )           // is not at the last column of LCU But is last row of LCU         {//!< 不在LCU的最後一列但在LCU的最後一行,SIZE_Nx2N的第1個PU,SIZE_NxN的第3個PU,SIZE_nLx2N的第1個PU,SIZE_nRx2N的第1個PU           uiAbsPartAddr = g_auiRasterToZscan[ (uiAbsPartIdxTmp + uiNumPartInCUWidth + 1) % m_pcPic->getNumPartInCU() ];           uiLCUIdx = -1 ;          }         else if ( uiAbsPartIdxTmp / uiNumPartInCUWidth < m_pcPic->getNumPartInHeight() - 1 ) // is not at the last row of LCU But is last column of LCU         {//!< 不在LCU的最後一行但在LCU的最後一列,SIZE_2NxN的第1個PU,SIZE_NxN的第2個PU,SIZE_2NxnU的第1個PU,SIZE_2NxnD的第1個PU           uiAbsPartAddr = g_auiRasterToZscan[ uiAbsPartIdxTmp + 1 ];           uiLCUIdx = getAddr() + 1;         }         else //is the right bottom corner of LCU,SIZE_2Nx2N                                {           uiAbsPartAddr = 0;           uiLCUIdx = -1 ;          }       }       iRefIdx = 0;          Bool bExistMV = false;       UInt uiPartIdxCenter;       UInt uiCurLCUIdx = getAddr();       xDeriveCenterIdx( uiPUIdx, uiPartIdxCenter ); //!< 根據uiPUIdx計算PU的中心地址uiPartIdxCenter       //! 獲取colocated CU的mv,並經scaled過的。       bExistMV = uiLCUIdx >= 0 && xGetColMVP( REF_PIC_LIST_0, uiLCUIdx, uiAbsPartAddr, cColMv, iRefIdx );       if( bExistMV == false )       {         bExistMV = xGetColMVP( REF_PIC_LIST_0, uiCurLCUIdx, uiPartIdxCenter,  cColMv, iRefIdx );       }       if( bExistMV )       {         UInt uiArrayAddr = iCount;         abCandIsInter[uiArrayAddr] = true;         pcMvFieldNeighbours[uiArrayAddr << 1].setMvField( cColMv, iRefIdx );            if ( getSlice()->isInterB() )         {                  iRefIdx = 0;           bExistMV = uiLCUIdx >= 0 && xGetColMVP( REF_PIC_LIST_1, uiLCUIdx, uiAbsPartAddr, cColMv, iRefIdx);           if( bExistMV == false )           {             bExistMV = xGetColMVP( REF_PIC_LIST_1, uiCurLCUIdx, uiPartIdxCenter,  cColMv, iRefIdx );           }           if( bExistMV )           {             pcMvFieldNeighbours[ ( uiArrayAddr << 1 ) + 1 ].setMvField( cColMv, iRefIdx );             puhInterDirNeighbours[uiArrayAddr] = 3; //!< Bi           }           else           {             puhInterDirNeighbours[uiArrayAddr] = 1; //!< L0           }         }         else         {           puhInterDirNeighbours[uiArrayAddr] = 1; //!< L0         }         if ( mrgCandIdx == iCount )         {           return;         }         iCount++;       }       uiIdx++;        }     // early termination     if (iCount == getSlice()->getMaxNumMergeCand())      {       return;     }     UInt uiArrayAddr = iCount;     UInt uiCutoff = uiArrayAddr;            if ( getSlice()->isInterB())     {//! 參考draft Table 8-6 ---- Specification of l0CandIdx and l1CandIdx       UInt uiPriorityList0[12] = {0 , 1, 0, 2, 1, 2, 0, 3, 1, 3, 2, 3};       UInt uiPriorityList1[12] = {1 , 0, 2, 0, 2, 1, 3, 0, 3, 1, 3, 2};          for (Int idx=0; idx<uiCutoff*(uiCutoff-1) && uiArrayAddr!= getSlice()->getMaxNumMergeCand(); idx++)       {         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;     }     //! 當可用的merge candidates數目仍小於預設值時,將余量均設置為零運動矢量     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);       }  www.2cto.com     uiArrayAddr++;       if ( refcnt == iNumRefIdx - 1 ) //!< 達到參考幀列表的參考幀數       {         r = 0;       }       else       {         ++r;         ++refcnt;       }     }        numValidMergeCand = uiArrayAddr;   }    

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved