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

来源:互联网 发布:cctv中国网络电视台 编辑:程序博客网 时间:2024/05/22 02:14

原文地址:http://blog.csdn.net/yangxiao_xiang/article/details/8270723

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


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

接下来是代码部分:

该过程主要由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。



0 0