您的位置:首页 > 其它

【转载】LCU的划分

2014-12-24 21:55 155 查看
转载自 http://blog.sina.com.cn/s/blog_7b7ddaf90101edj2.html
首先,对于四叉树的分割形式,大家想必都已经了解了,这里就不进行过多的赘述,下面是常见的四叉树结构示意图:



接下来是代码部分:

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

[cpp] view plaincopy

// 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()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的分割模式:

[cpp] view plaincopy

// 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

上一篇文章对每个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 plaincopy

// run CU encoder

m_pcCuEncoder->compressCU( pcCU );

//==LCU分割单元深度信息输出==//

fprintf( g_hTrace,"=======LCU=========\n");

for(Int i=0;i<256;i++)

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 plaincopy

// analysis of CU

xCompressCU( m_ppcBestCU[0], m_ppcTempCU[0], 0 );

UInt LCUDepth[256] ;

for (Int i=0;i<256;i++)

{

LCUDepth[i]= m_ppcBestCU[0]->getDepth(i);

cout<<"CurTempCUDepth: "<<LCUDepth[i]<<endl;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐