HEVC帧内预测编码之LCU四叉树结构分块

    从十月份开始,接触HEVC已经将近两个月了,可是效果并不是很明显,这两天都在看代码,经过一段时间的折腾,加上分析学习HEVC_CJL兄弟的文章,终于对HEVC帧内预测编码有了一定的理解,现在主要把本人对于如何LCU如何进一步细分成CU的过程跟大家分享一下,好了,闲话少叙,下面进入主题:


首先,对于四叉树的分割形式,大家想必都已经了解了,这里就不进行过多的赘述,下面是常见的四叉树结构示意图:

HEVC帧内预测编码之LCU四叉树结构分块_第1张图片

接下来是代码部分:

该过程主要由TEncCu::xCompressCU函数的递归实现

    // further split进一步进行CU的分割
    if( bSubBranch && bTrySplitDQP && uiDepth < g_uiMaxCUDepth - g_uiAddCUDepth )
    {
      UChar       uhNextDepth         = uiDepth+1;
      TComDataCU* pcSubBestPartCU     = m_ppcBestCU[uhNextDepth];
      TComDataCU* pcSubTempPartCU     = m_ppcTempCU[uhNextDepth];

      for ( UInt uiPartUnitIdx = 0; uiPartUnitIdx < 4; uiPartUnitIdx++ )//每次分成四个更小的CU
    {
        pcSubBestPartCU->initSubCU( rpcTempCU, uiPartUnitIdx, uhNextDepth, iQP );           // clear sub partition datas or init.
        pcSubTempPartCU->initSubCU( rpcTempCU, uiPartUnitIdx, uhNextDepth, iQP );           // clear sub partition datas or init.

        Bool bInSlice = pcSubBestPartCU->getSCUAddr()+pcSubBestPartCU->getTotalNumPart()>pcSlice->getDependentSliceCurStartCUAddr()&&pcSubBestPartCU->getSCUAddr()<pcSlice->getDependentSliceCurEndCUAddr();
        if(bInSlice && ( pcSubBestPartCU->getCUPelX() < pcSlice->getSPS()->getPicWidthInLumaSamples() ) && ( pcSubBestPartCU->getCUPelY() < pcSlice->getSPS()->getPicHeightInLumaSamples() ) )
        {
          if( m_bUseSBACRD )
          {
            if ( 0 == uiPartUnitIdx) //initialize RD with previous depth buffer
            {
              m_pppcRDSbacCoder[uhNextDepth][CI_CURR_BEST]->load(m_pppcRDSbacCoder[uiDepth][CI_CURR_BEST]);
            }
            else
            {
              m_pppcRDSbacCoder[uhNextDepth][CI_CURR_BEST]->load(m_pppcRDSbacCoder[uhNextDepth][CI_NEXT_BEST]);
            }
          }

#if AMP_ENC_SPEEDUP
          if ( rpcBestCU->isIntra(0) )
          {
            xCompressCU( pcSubBestPartCU, pcSubTempPartCU, uhNextDepth, SIZE_NONE );//递归函数
          }
          else
          {
            xCompressCU( pcSubBestPartCU, pcSubTempPartCU, uhNextDepth, rpcBestCU->getPartitionSize(0) );//递归函数
          }
#else
          xCompressCU( pcSubBestPartCU, pcSubTempPartCU, uhNextDepth );         
#endif

          rpcTempCU->copyPartFrom( pcSubBestPartCU, uiPartUnitIdx, uhNextDepth );         // Keep best part data to current temporary data.
          xCopyYuv2Tmp( pcSubBestPartCU->getTotalNumPart()*uiPartUnitIdx, uhNextDepth );
        }
        else if (bInSlice)
        {
          pcSubBestPartCU->copyToPic( uhNextDepth );
          rpcTempCU->copyPartFrom( pcSubBestPartCU, uiPartUnitIdx, uhNextDepth );
        }
      }


既然已经知道,CU的分割是通过递归实现的,那么怎么确定哪个uiDepth的CU为rpcBestCU呢?

上述递归函数结束后,然后再通过xCheckBestMode( rpcBestCU, rpcTempCU, uiDepth);判断决定是否选择本层CU还是下层CU.

以下是编程实现输出一个LCU的分割模式:

  // We need to split, so don't try these modes.
  if(!bSliceEnd && !bSliceStart && bInsidePicture )
  {
    for (Int iQP=iMinQP; iQP<=iMaxQP; iQP++)
    {
      if (isAddLowestQP && (iQP == iMinQP))
      {
        iQP = lowestQP;
      }
      // variables for fast encoder decision
      bEarlySkip  = false;
      bTrySplit    = true;
      fRD_Skip    = MAX_DOUBLE;

      rpcTempCU->initEstData( uiDepth, iQP );
     //==输出分区深度信息depth==//
      cout<<"Depth:";
      for(Int i=0;i<=uiDepth;i++)
       cout<<"->";
       cout<<uiDepth<<endl;

      // do inter modes, SKIP and 2Nx2N
打印输出的结构为:

Depth:->0
Depth:->->1
Depth:->->->2
Depth:->->->->3
Depth:->->->->3
Depth:->->->->3
Depth:->->->->3
Depth:->->->2
Depth:->->->->3
Depth:->->->->3
Depth:->->->->3
Depth:->->->->3
Depth:->->->2
Depth:->->->->3
Depth:->->->->3
Depth:->->->->3
Depth:->->->->3
Depth:->->->2
Depth:->->->->3
Depth:->->->->3
Depth:->->->->3
Depth:->->->->3
Depth:->->1
Depth:->->->2
Depth:->->->->3
Depth:->->->->3
Depth:->->->->3
Depth:->->->->3
Depth:->->->2
Depth:->->->->3
Depth:->->->->3
Depth:->->->->3
Depth:->->->->3
Depth:->->->2
Depth:->->->->3
Depth:->->->->3
Depth:->->->->3
Depth:->->->->3
Depth:->->->2
Depth:->->->->3
Depth:->->->->3
Depth:->->->->3
Depth:->->->->3
Depth:->->1
Depth:->->->2
Depth:->->->->3
Depth:->->->->3
Depth:->->->->3
Depth:->->->->3
Depth:->->->2
Depth:->->->->3
Depth:->->->->3
Depth:->->->->3
Depth:->->->->3
Depth:->->->2
Depth:->->->->3
Depth:->->->->3
Depth:->->->->3
Depth:->->->->3
Depth:->->->2
Depth:->->->->3
Depth:->->->->3
Depth:->->->->3
Depth:->->->->3
Depth:->->1
Depth:->->->2
Depth:->->->->3
Depth:->->->->3
Depth:->->->->3
Depth:->->->->3
Depth:->->->2
Depth:->->->->3
Depth:->->->->3
Depth:->->->->3
Depth:->->->->3
Depth:->->->2
Depth:->->->->3
Depth:->->->->3
Depth:->->->->3
Depth:->->->->3
Depth:->->->2
Depth:->->->->3
Depth:->->->->3
Depth:->->->->3
Depth:->->->->3


如有错误,还望不吝赐教,特别感谢zhuix7788的指导。

最终的LCU分割结果详见下一篇http://blog.csdn.net/yangxiao_xiang/article/details/8275181。






你可能感兴趣的:(C++,C++,HEVC,帧内预测,LCU,四叉树结构)