【转载】LCU的划分

转载自 http://blog.sina.com.cn/s/blog_7b7ddaf90101edj2.html

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

接下来是代码部分:

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

 

[cpp]  view plain copy
  1.     // further split进一步进行CU的分割  
  2.     ifbSubBranch && bTrySplitDQP && uiDepth g_uiMaxCUDepth g_uiAddCUDepth  
  3.      
  4.       UChar       uhNextDepth         uiDepth+1;  
  5.       TComDataCU* pcSubBestPartCU     m_ppcBestCU[uhNextDepth];  
  6.       TComDataCU* pcSubTempPartCU     m_ppcTempCU[uhNextDepth];  
  7.   
  8.       for UInt uiPartUnitIdx 0; uiPartUnitIdx 4; uiPartUnitIdx++ )//每次分成四个更小的CU  
  9.      
  10.         pcSubBestPartCU->initSubCU( rpcTempCU, uiPartUnitIdx, uhNextDepth, iQP );           // clear sub partition datas or init.  
  11.         pcSubTempPartCU->initSubCU( rpcTempCU, uiPartUnitIdx, uhNextDepth, iQP );           // clear sub partition datas or init.  
  12.   
  13.         Bool bInSlice pcSubBestPartCU->getSCUAddr()+pcSubBestPartCU->getTotalNumPart()>pcSlice->getDependentSliceCurStartCUAddr()&&pcSubBestPartCU->getSCUAddr()getDependentSliceCurEndCUAddr();  
  14.         if(bInSlice && pcSubBestPartCU->getCUPelX() pcSlice->getSPS()->getPicWidthInLumaSamples() && pcSubBestPartCU->getCUPelY() pcSlice->getSPS()->getPicHeightInLumaSamples()  
  15.          
  16.           ifm_bUseSBACRD  
  17.            
  18.             if == uiPartUnitIdx) //initialize RD with previous depth buffer  
  19.              
  20.               m_pppcRDSbacCoder[uhNextDepth][CI_CURR_BEST]->load(m_pppcRDSbacCoder[uiDepth][CI_CURR_BEST]);  
  21.              
  22.             else  
  23.              
  24.               m_pppcRDSbacCoder[uhNextDepth][CI_CURR_BEST]->load(m_pppcRDSbacCoder[uhNextDepth][CI_NEXT_BEST]);  
  25.              
  26.            
  27.   
  28. #if AMP_ENC_SPEEDUP  
  29.           if rpcBestCU->isIntra(0)  
  30.            
  31.             xCompressCU( pcSubBestPartCU, pcSubTempPartCU, uhNextDepth, SIZE_NONE );//递归函数  
  32.            
  33.           else  
  34.            
  35.             xCompressCU( pcSubBestPartCU, pcSubTempPartCU, uhNextDepth, rpcBestCU->getPartitionSize(0) );//递归函数  
  36.            
  37. #else  
  38.           xCompressCU( pcSubBestPartCU, pcSubTempPartCU, uhNextDepth );           
  39. #endif  
  40.   
  41.           rpcTempCU->copyPartFrom( pcSubBestPartCU, uiPartUnitIdx, uhNextDepth );         // Keep best part data to current temporary data.  
  42.           xCopyYuv2Tmp( pcSubBestPartCU->getTotalNumPart()*uiPartUnitIdx, uhNextDepth );  
  43.          
  44.         else if (bInSlice)  
  45.          
  46.           pcSubBestPartCU->copyToPic( uhNextDepth );  
  47.           rpcTempCU->copyPartFrom( pcSubBestPartCU, uiPartUnitIdx, uhNextDepth );  
  48.          
  49.        


 

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

 

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

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

 

[cpp]  view plain copy
  1. // We need to split, so don't try these modes.  
  2. if(!bSliceEnd && !bSliceStart && bInsidePicture  
  3.  
  4.   for (Int iQP=iMinQP; iQP<=iMaxQP; iQP++)  
  5.    
  6.     if (isAddLowestQP && (iQP == iMinQP))  
  7.      
  8.       iQP lowestQP;  
  9.      
  10.     // variables for fast encoder decision  
  11.     bEarlySkip  false 
  12.     bTrySplit    true 
  13.     fRD_Skip    MAX_DOUBLE;  
  14.   
  15.     rpcTempCU->initEstData( uiDepth, iQP );  
  16.    //==输出分区深度信息depth==//  
  17.     cout<<"Depth:" 
  18.     for(Int i=0;i<=uiDepth;i++)  
  19.      cout<<"->" 
  20.      cout<<uiDepth<<endl;  
  21.   
  22.     // 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


上一篇文章对每个LCU进行遍历所有的CU分支,只是显示LCU的分割过程,但是并不能确定一个LCU分割结果,经过zhuix7788指出,意识到自己的误区了,后来通过一天的折腾,终于找到了真正的分割输出的结果。因为一个LCU的最终分割是要经过预测和熵编码后才能通过率失真代价确定。

 

所以,可以在m_pcCuEncoder->compressCU( pcCU );后查看pcCU->m_puhDepth对应的数组。这是一个大小为256的数组, 表示LCU的256个4X4到底如何分割的!

详情可以参考 http://blog.csdn.net/feixiang_john/article/details/7876227#comments的评论部分。)

实现代码如下:

 

[cpp]  view plain copy
  1. // run CU encoder  
  2. m_pcCuEncoder->compressCU( pcCU );  
  3. //==LCU分割单元深度信息输出==//  
  4. fprintf( g_hTrace,"=======LCU=========\n");  
  5. for(Int i=0;i<256;i++)  
  6. fprintf( g_hTrace, "%d\t",pcCU->getDepth(i));  

输出结果前先要进行TraceEnc开启设定,在TComRom.h文件下设置#define  ENC_DEC_TRACE  1即可。

输出结果在HM-9.0-dev\cfg文件夹下的TraceEnc文件中。

打印输出结果如下:

 

=======LCU=========

2 2  2 2

2 2  2 2

2 2  2 2

2 2  2 2

2 2  2 2

2 2  2 2

2 2  2 2

2 2  2 2

2 2  2 2

2 2  2 2

2 2  2 2

2 2  2 2

2 2  2 2

2 2  2 2

2 2  2 2

2 2  2 2

2 2  2 2

2 2  2 2

2 2  2 2

2 2  2 2

2 2  2 2

2 2  2 2

2 2  2 2

2 2  2 2

1 1  1 1

1 1  1 1

1 1  1 1

1 1  1 1

1 1  1 1

1 1  1 1

1 1  1 1

1 1  1 1

1 1  1 1

1 1  1 1

1 1  1 1

1 1  1 1

1 1  1 1

1 1  1 1

1 1  1 1

1 1  1 1

2 2  2 2

2 2  2 2

2 2  2 2

2 2  2 2

2 2  2 2

2 2  2 2

2 2  2 2

2 2  2 2

3 3  3 3

3 3  3 3

3 3  3 3

3 3  3 3

3 3  3 3

3 3  3 3

3 3  3 3

3 3  3 3

LCU的基本存储单元为4x4的块,这个可以在HM平台的HM-9.0-dev\doc文件夹下找到一个README_data-structure文件,上面有介绍。以下就是一个LCU的存储结构示意图:


下面是根据输出结果重构的一个LCU(64x64)的分割示意图:


其中红色数字代表当前块的分割深度。

或者采用下面的方法也可以查看: 

 

[cpp]  view plain copy
  1. // analysis of CU  
  2.  xCompressCU( m_ppcBestCU[0], m_ppcTempCU[0], );  
  3. UInt LCUDepth[256]  
  4. for (Int i=0;i<256;i++)  
  5.  
  6.     LCUDepth[i]=  m_ppcBestCU[0]->getDepth(i);  
  7.     cout<<"CurTempCUDepth: "<<LCUDepth[i]<<endl;  
  8. }  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值