当前位置:编程学习 > C/C++ >>

HEVC帧间预测之一——TComDataCU::getInterMergeCandidates函数分析

 从今天开始,正式转入到帧间预测方向。由于帧间预测涉及到的方面广且复杂,所以我的理解出现错误的情况可能会更多,请大家以辩证的眼光来看待我的帖子,有问题欢迎大家批评指正。
 
大家都知道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
补充:软件开发 , C++ ,
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,