【转载】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;
}
首先,对于四叉树的分割形式,大家想必都已经了解了,这里就不进行过多的赘述,下面是常见的四叉树结构示意图:
接下来是代码部分:
该过程主要由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;
}
相关文章推荐
- 整数划分算法原理与实现(转载于 http://www.cnblogs.com/nokiaguy/archive/2008/05/11/1192308.html 李宁的极客世界)
- [转载]内存区划分、内存分配、常量存储区、堆、栈、自由存储区、全局区
- 内存区划分、内存分配、常量存储区、堆、栈、自由存储区、全局区[C++][内存管理][转载]
- 投影机显示屏幕的划分选择(转载)
- 内存区划分、内存分配、常量存储区、堆、栈、自由存储区、全局区[C++][内存管理][转载]
- [转载]内存区划分、内存分配、常量存储区、堆、栈、自由存储区、全局区
- 转:内存区划分、内存分配、常量存储区、堆、栈、自由存储区、全局区[C++][内存管理][转载]
- 【转载】IP地址的分类——a,b,c 类是如何划分的
- C#中38个常用运算符的优先级的划分和理解。 [转载]
- 三层式开发中的层次划分讨论[转载]
- 内存的划分和分配等[转载]
- 小团队开发J2ME游戏的阶段划分(转载)
- [转载]内存区划分、内存分配、常量存储区、堆、栈、自由存储区、全局区
- [转载收藏]三层式开发中的层次划分
- 扫描线划分Voronoi diagram_算法分析(英文转载)
- 【转载】CU、PU、TU划分显示代码
- 【转载】电磁波中的波段划分:L波段、S波段、C波段、X波段、Ku波段、K波段、Ka波段 等等
- 扫描线划分Voronoi diagram_算法分析(英文转载)
- HEVC中LCU分割 划分查看
- 内存区划分、内存分配、常量存储区、堆、栈、自由存储区、全局区[转载]