Fast CU Depth Decision Algorithm for HEVC Intra Coding

2024-02-12 09:32

本文主要是介绍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%左右。

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

这篇关于Fast CU Depth Decision Algorithm for HEVC Intra Coding的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/702279

相关文章

hevc和H.264格式的区别

HEVC(High Efficiency Video Coding)和H.264(也称为Advanced Video Coding,AVC)都是视频压缩标准,但它们之间存在一些显著的区别,主要集中在压缩效率、资源需求和兼容性方面。 压缩效率 HEVC,也被称为H.265,提供了比H.264更高的压缩效率。这意味着在相同的视频质量下,HEVC能够以大约一半的比特率进行编码,从而减少存储空间需求和

鹅算法(GOOSE Algorithm,GOOSE)求解复杂城市地形下无人机避障三维航迹规划,可以修改障碍物及起始点(Matlab代码)

一、鹅算法 鹅优化算法(GOOSE Algorithm,GOOSE)从鹅的休息和觅食行为获得灵感,当鹅听到任何奇怪的声音或动作时,它们会发出响亮的声音来唤醒群中的个体,并保证它们的安全。 参考文献 [1]Hamad R K, Rashid T A. GOOSE algorithm: a powerful optimization tool for real-world engineering

iOS OC底层面试题(KVC(Key-value coding)

KVC(Key-value coding) -(id)valueForKey:(NSString *)key;-(void)setValue:(id)value forKey:(NSString *)key; KVC就是指iOS的开发中,可以允许开发者通过Key名直接访问对象的属性,或者给对象的属性赋值。而不需要调用明确的存取方法。这样就可以在运行时动态地访问和修改对象的属性。而不是在编译时

Depth Anything V2:抖音开源高性能任何单目图像深度估计V2版本,并开放具有精确注释和多样化场景的多功能评估基准

📜文献卡 题目: Depth Anything V2作者: Lihe Yang; Bingyi Kang; Zilong Huang; Zhen Zhao; Xiaogang Xu; Jiashi Feng; Hengshuang ZhaoDOI: 10.48550/arXiv.2406.09414摘要: This work presents Depth Anything V2. With

5.How Fast Should You Be When Learning?(你应该用多快的速度学习? (一))

Normally when I talk about learing quickly, I’m using speed as a synonym for efficiency.Use more effective methods and you’ll learn more in less time.All else being equal, that means you’re learing fa

【GNU笔记】内联函数与宏一样快 An Inline Function is As Fast As a Macro

内联函数与宏一样快 An Inline Function is As Fast As a Macro 通过声明内联函数,你可以指示 GCC 更快地调用该函数。GCC 可以实现这一点的一种方法是将该函数的代码集成到其调用者的代码中。这通过消除函数调用开销使执行速度更快;此外,如果任何实际参数值是常量,则它们的已知值可能允许在编译时进行简化,因此不需要包含所有内联函数的代码。对代码大小的影响是难以预

fast DFS 单机使用实例

fast DFS 单机使用实例 我在一台服务器上简单测试了fastdfs。client, tracker, storage server都是同一个物理服务器。   1. 编译fastdfs:   sles207:/opt/mars/FastDFS # ./make.sh   storage_service.o: In function `storage_service_init':/opt/ma

Reconstructing Position From Depth

需求: 根据当前像素的Depth计算出其View空间的Position 先说一种惯性思维的方法: 既然知道depth是怎么算出来的, 那么进行逆运算回去不就得到position了? 先说说depth是怎么出来的: Vertex shader: output.position = mul(input.postion, matWorldViewProject); output.depth

[rejected]master -> master (non-fast-forward)的解决方法

☆ 问题描述 [rejected]master -> master (non-fast-forward)的解决方法 本地已经创建了一个项目,想要把远程库的代码合并到本地库上,报错… ★ 解决方案 git pull <远程服务器> <远程分支> --allow-unrelated-histories 先使用这个代码合并两个分支 –allow-unrelated-historie

density based clustering algorithm,

1. 首先看到这个webSite讲的比较清楚,可以看下,https://blog.dominodatalab.com/topology-and-density-based-clustering/    We're hiring! BLOG HOME  LEARN MORE ABOUT DOMINO   Density-Based Clustering dat