Fast CU Depth Decision Algorithm for HEVC Intra Coding


转自:http://blog.csdn.net/beechina/article/details/25430737

在HEVC 参考代码中,一个CTU块通过xcompressCU()函数进行CU递归得到最优的CU深度。

递归的过程可如下图(from:Fast CU Splitting and Pruning for Suboptimal CU Partitioning in HEVC Intra Coding)所示。图中每一个方框表示一个CU块,方框内的数字表示xcompressCU()函数的执行顺序。显而易见,如果能在做xcompressCU()函数之前,将CU的递归深度确定下,显然可以减小HEVC编码器的复杂度。




针对帧内编码器,已经有很多文献提出了提前确定CU递归深度的方法。这里介绍了"Fast CU Size Decision and Mode Decision Algorithm for HEVC Intra Coding"中Section II.A部分的具体实现。在这篇文献中,周边块的CTU depth size用来给当前块深度进行预测。具体的细节可以去查看该文献。

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. Void TEncCu::compressCU( TComDataCU*& rpcCU )  
  2. {  
  3.   // initialize CU data  
  4.   m_ppcBestCU[0]->initCU( rpcCU->getPic(), rpcCU->getAddr() );  
  5.   m_ppcTempCU[0]->initCU( rpcCU->getPic(), rpcCU->getAddr() );  
  6.   
  7.   memset( m_preAnalyzeDepth,       0, rpcCU->getTotalNumPart() );  
  8.   memset( m_preAnaDepthDetermined, 0, rpcCU->getTotalNumPart() );  
  9.   memset( m_preAnaDepthRange     , 0, rpcCU->getTotalNumPart() );  
  10.   
  11.   // Neighboring CTUs.  
  12.   TComDataCU* t_pcCULeft      = rpcCU->getCULeft();  
  13.   TComDataCU* t_pcCUAbove     = rpcCU->getCUAbove();  
  14.   TComDataCU* t_pcCUAboveLeft = rpcCU->getCUAboveLeft();  
  15.   TComDataCU* t_pcCUAboveRight= rpcCU->getCUAboveRight();  
  16.   UInt DepthLeft       = 0;       // Max Depth of LeftCTU.  
  17.   UInt DepthAbove      = 0;       // Max Depth of AboveCTU.  
  18.   UInt DepthAboveLeft  = 0;  
  19.   UInt DepthAboveRight = 0;  
  20.   
  21.   UInt picWidth  = rpcCU->getSlice()->getSPS()->getPicWidthInLumaSamples();  
  22.   UInt picHeight = rpcCU->getSlice()->getSPS()->getPicHeightInLumaSamples();  
  23.   UInt uiLPelX   = rpcCU->getCUPelX();  
  24.   UInt uiRPelX   = uiLPelX + rpcCU->getWidth(0)  - 1;  
  25.   UInt uiTPelY   = rpcCU->getCUPelY();  
  26.   UInt uiBPelY   = uiTPelY + rpcCU->getHeight(0) - 1;  
  27.     
  28.   UChar    tDepth;  
  29.   
  30.   m_insidePicture= (uiRPelX<picWidth) && (uiBPelY<picHeight);  
  31.   // Considering Border CTUs.  
  32.   if ( t_pcCULeft!=NULL ) //获取左边CTU块最大的depth信息  
  33.   {  
  34.       for ( Int i=0; i<256; i++ )  
  35.       {  
  36.           tDepth    = t_pcCULeft->getDepth(i);  
  37.           if ( tDepth>DepthLeft )  
  38.           {  
  39.               DepthLeft = (UInt)tDepth;  
  40.           }  
  41.       }  
  42.   }  
  43.   else  
  44.       DepthLeft = 2; //如果是NULL,直接赋值2(16X16)  
  45.   
  46.   if ( t_pcCUAbove!=NULL )  
  47.   {  
  48.       for ( Int i=0; i<256; i++ )  
  49.       {  
  50.           tDepth    = t_pcCUAbove->getDepth(i);  
  51.           if ( tDepth>DepthAbove )  
  52.           {  
  53.               DepthAbove = (UInt)tDepth;  
  54.           }  
  55.       }  
  56.   }  
  57.   else  
  58.       DepthAbove = 2;  
  59.   
  60.   if ( t_pcCUAboveLeft!=NULL )  
  61.   {  
  62.       DepthAboveLeft = t_pcCUAboveLeft->getDepth(g_auiRasterToZscan[16*15+15]);  
  63.   }  
  64.   else  
  65.       DepthAboveLeft = 2;  
  66.   
  67.   if ( t_pcCUAboveRight!=NULL )  
  68.   {  
  69.       DepthAboveRight = t_pcCUAboveRight->getDepth(g_auiRasterToZscan[16*15]);  
  70.   }  
  71.   else  
  72.       DepthAboveRight = 2;  
  73.     
  74.   Double DepthPre = 0.3*DepthLeft+0.3*DepthAbove+0.2*DepthAboveLeft+0.2*DepthAboveRight; // 论文中Prediction Depth Type  
  75.   if ( DepthPre<=0.5 ) // 依据论文中的公式给出最小的depth level和最大的depth level  
  76.   {  
  77.       memset( m_preAnaDepthDetermined, 1, 256 );  
  78.       memset( m_preAnaDepthRange,      2, 256 );  
  79.       memset( m_preAnalyzeDepth,       0, 256 );  
  80.   }  
  81.   else if ( DepthPre<=1.5 )  
  82.   {  
  83.       memset( m_preAnaDepthDetermined, 1, 256 );  
  84.       memset( m_preAnaDepthRange,      3, 256 );  
  85.       memset( m_preAnalyzeDepth,       0, 256 );  
  86.   }  
  87.   else  
  88.   {  
  89.       memset( m_preAnaDepthDetermined, 1, 256 );  
  90.       memset( m_preAnaDepthRange,      3, 256 );  
  91.       memset( m_preAnalyzeDepth,       1, 256 );  
  92.   }  
  93.   
  94.   DEBUG_STRING_NEW(sDebug)  
  95.   
  96.   xCompressCU( m_ppcBestCU[0], m_ppcTempCU[0], 0 DEBUG_STRING_PASS_INTO(sDebug) );  
  97.   DEBUG_STRING_OUTPUT(std::cout, sDebug)  
  98.   // Double Check.  
  99.   UInt MaxDepthSize=0;  
  100.   // UInt CTUPelX, CTUPelY;  
  101.   if ( m_insidePicture )  
  102.   {  
  103.       for ( Int i=0; i<256; i++ )  
  104.       {  
  105.           // Decisioned.  
  106.           tDepth    = m_ppcBestCU[0]->getDepth(i);  
  107.   
  108.           UChar cuDepth         = m_preAnalyzeDepth[i];  
  109.           UChar cuPreDetermined = m_preAnaDepthDetermined[i];  
  110.           UChar cuRange         = m_preAnaDepthRange[i];  
  111.   
  112.           if ( tDepth<cuDepth && tDepth>=cuDepth+cuRange )  
  113.           {  
  114.               assert(0);  
  115.           }  
  116.       }  
  117.   }  
  118.   
  119. #if ADAPTIVE_QP_SELECTION  
  120.   if( m_pcEncCfg->getUseAdaptQpSelect() )  
  121.   {  
  122.     if(rpcCU->getSlice()->getSliceType()!=I_SLICE) //IIII  
  123.     {  
  124.       xLcuCollectARLStats( rpcCU);  
  125.     }  
  126.   }  
  127. #endif  
  128. }  

在xcompressCU函数中加入相关条件跳转。

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. // If slice start or slice end is within this cu...  
  2.  TComSlice * pcSlice = rpcTempCU->getPic()->getSlice(rpcTempCU->getPic()->getCurrSliceIdx());  
  3.  Bool bSliceStart = pcSlice->getSliceSegmentCurStartCUAddr()>rpcTempCU->getSCUAddr()&&pcSlice->getSliceSegmentCurStartCUAddr()<rpcTempCU->getSCUAddr()+rpcTempCU->getTotalNumPart();  
  4.  Bool bSliceEnd = (pcSlice->getSliceSegmentCurEndCUAddr()>rpcTempCU->getSCUAddr()&&pcSlice->getSliceSegmentCurEndCUAddr()<rpcTempCU->getSCUAddr()+rpcTempCU->getTotalNumPart());  
  5.  Bool bInsidePicture = ( uiRPelX < rpcBestCU->getSlice()->getSPS()->getPicWidthInLumaSamples() ) && ( uiBPelY < rpcBestCU->getSlice()->getSPS()->getPicHeightInLumaSamples() );  
  6.  // Fast CU decision Process.  
  7.  // When Current depth is not in the PreAnalyzedDepth Range, it just skips the PU/TU Decision process.  
  8.  // Added by xfHuang.  
  9.  Bool t_enCUSkip=false;  
  10.  if ( m_insidePicture )  
  11.  {  
  12.   // Split Analysis For CU32X32 And CU16X16.  
  13.   
  14.   if ( checkCurDepthInPreAnaRange( rpcBestCU, uiDepth ) == false ) //如果当前的depth level不在预测的depth level之内,后面直接将cost赋值成最大,不进行后面的预测操作。  
  15.   {  
  16.       t_enCUSkip = true;  
  17.       rpcBestCU->getTotalCost() = MAX_DOUBLE/16;  
  18.       rpcBestCU->getTotalDistortion() = MAX_UINT>>3;  
  19.       rpcBestCU->getTotalBits() = MAX_UINT>>3;  
  20.       // avoid assert disable.  
  21.       if ( uiDepth==3 )  
  22.       {  
  23.           rpcBestCU->setPartitionSize ( 0, SIZE_2Nx2N );        
  24.           rpcBestCU->setPredictionMode( 0, MODE_INTRA );   
  25.       }  
  26.   }  
  27.  }  
  28.    
  29.  // We need to split, so don't try these modes.  
  30.  if(!bSliceEnd && !bSliceStart && bInsidePicture )  
  31.  {  
  32. if( t_enCUSkip==false )  
  33. {  
  34.    for (Int iQP=iMinQP; iQP<=iMaxQP; iQP++)  
  35.    {  
  36.      const Bool bIsLosslessMode = isAddLowestQP && (iQP == iMinQP);  
  37.   
  38.      if (bIsLosslessMode)  
  39.      {  
  40.        iQP = lowestQP;  
  41.      }  
  42.   
  43.      rpcTempCU->initEstData( uiDepth, iQP, bIsLosslessMode );  

其中checkCurDepthInPreAnaRange函数如下:

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. Bool TEncCu::checkCurDepthInPreAnaRange( TComDataCU*& pCU, UInt uidepth )  
  2. {  
  3.     UChar cuDepth         = m_preAnalyzeDepth[pCU->getZorderIdxInCU()];  
  4.     UChar cuPreDetermined = m_preAnaDepthDetermined[pCU->getZorderIdxInCU()];  
  5.     UChar cuRange         = m_preAnaDepthRange[pCU->getZorderIdxInCU()];  
  6.     assert(cuDepth+cuRange<=5);  
  7.     if ( /*cuPreDetermined &&*/ uidepth>=cuDepth && uidepth<cuDepth+cuRange )  
  8.     {  
  9.         return true;  
  10.     }  
  11.     else  
  12.     {  
  13.         return false;  
  14.     }  
  15. }  

以上是一种基于周边CTU块信息来进行CU深度优化的一种方法。这个方法对于大部分来说只是不做64X64这一层depth,因此性能损失很小,平均大概在0.2%左右。时间可以节省10%左右。

[转载请注明作者和出处]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值