安徽365热线-Bets365-365bet线上娱乐

CompressCU函数:LCU的编码,包括CU的划分,PU模式的决定,TU的划分

CompressCU函数:LCU的编码,包括CU的划分,PU模式的决定,TU的划分

CompressCU函数:LCU的编码,包括CU的划分,PU模式的决定,TU的划分

最新推荐文章于 2025-08-26 15:16:47 发布

转载

最新推荐文章于 2025-08-26 15:16:47 发布

·

3.8k 阅读

·

3

·

17

文章标签:

#hevc

#压缩

#标准

#编码

#视频

视频编码

专栏收录该内容

27 篇文章

订阅专栏

本文详细解析了CompressCU函数及其内部的xCompressCU函数,旨在优化熵编码过程。通过理解CU的递归划分和PU模式的决定,文章揭示了如何在编码过程中减少比特数并提高效率。重点分析了CU划分的步骤,从64x64到8x8的逐步细化,以及在每一级划分中如何选择最优的预测模式和模式存储策略。

看过好几次CompressCU函数,都是一知半解。这次要做的是把模式保留下来,可以减少熵编码的比特数。这样就必须彻底的弄清楚CU的递归的划分也就是xcompressCU这个函数。这样才知道什么时候保存需要的模式,保存到哪里去,以什么形式存储,在熵编码的时候如何对PU的模式进行索引。

1.xCompressCU 函数的调用

在编码一个片的函数CompressSlice 函数中有这个几行代码

// run CU encoder

m_pcCuEncoder->compressCU( pcCU ); 就是一个LCU的编码,包括CU的划分,PU模式的决定,TU的划分

m_pcCuEncoder->encodeCU( pcCU ); 这里可以看出来pcCU是存储着需要编码的信息。

2.进入这个函数

Void TEncCu::compressCU( TComDataCU*& rpcCU )

{

// initialize CU data

m_ppcBestCU[0]->initCU( rpcCU->getPic(), rpcCU->getAddr() );

//这里的 m_ppcBestCU[0]和m_ppcTempCU[0]都是记录模式信息的,至于如何记录我们一点点的来看。由于是递归的划分CU,这里容易绕晕啊。

m_ppcTempCU[0]->initCU( rpcCU->getPic(), rpcCU->getAddr() );

// analysis of CU

xCompressCU( m_ppcBestCU[0], m_ppcTempCU[0], 0 ); 这里进入xCompressCU函数,这里的第三个参数是 CU的分割深度。64x64的深度为0,以此类推,最小的CU为8x8深度为3。至于如何将最优的模式信息赋值到pcCU里,我们后面跟踪代码可以看到。

这里首先要弄清一个概念,就是CU的划分是递归的

第一步 CU的大小为64x64, 搜索最优的PU的划分得到最优的预测模式,进行TU的划分

第二步 CU的大小为32x32, 第一个CU(按之子扫描顺序) 同上

第三步 CU的大小为16x16, 第一个CU 同上

第四步 CU的大小为8x8, 以此进行第一个CU,第二个CU,第三个CU和第四个CU的PU和TU的划分和最优模式的选择。这里面完成每个CU后将这个的RD与前面进行累加。

第五步 返回到CU为 16x16的CU,将其RD-COST 与第四部记录的四个8X8的CU的RD-cost进行比较。决定了这个16X16的最优的CU划分及最优的CU下的PU和CU的划分。

第六步 CU的大小为 16X16,第二个CU。重复 第四步第五步,可以得到第二个最优的16x16的CU的划分和PU TU 的模式。 同时将改第二个CU的最优的RD-COST与5步得到的第一个16x16的CURD-COST进行累加。

第七步 :同理完成第三个和第四个的16X16的CU的最优的划分和模式的选择,将其RD-COST累加。这样我们就得到了分割为16X16最佳的RD-cost。

第八步 : 返回到第二步,比较第一个32X32CU的RD-cost 和 分割为4个16X16的CU的RD-cost,得了第一个32X32 CU的分割信息和最优的模式。

第九步:同理完成第二个32x32,第三个32X32和第四个32X32的最优的划分和模式选择。通过记录和累加每一个32x32的RD-cost,与64x64的CU的RD-Cost进行比较。我们得到了最终的CU 的划分和每个CU的最优的PU的划分及PU的预测模式以及TU的划分。

}

3.xCompressCU( m_ppcBestCU[0], m_ppcTempCU[0], 0 )函数

现在就按照2中的过程来看一看这函数的流程:

首先进入该函数,CU的大小已经确定了为64x64,进行PU的划分和TU的划分

PU的划分将按下列顺序进行尝试:

帧间

xCheckRDCostInter( rpcBestCU, rpcTempCU, SIZE_2Nx2N, bFMD ) skip 2NX2N

xCheckRDCostMerge2Nx2N( rpcBestCU, rpcTempCU, &earlyDetectionSkipMode ); Merge 2NX2N

xCheckRDCostInter( rpcBestCU, rpcTempCU, SIZE_2Nx2N, bFMD ); 2NX2N

xCheckRDCostInter( rpcBestCU, rpcTempCU, SIZE_NxN, bFMD ); NXN 划分为4个PU

xCheckRDCostInter( rpcBestCU, rpcTempCU, SIZE_Nx2N, bFMD ); Nx2N 划分为2个PU

xCheckRDCostInter ( rpcBestCU, rpcTempCU, SIZE_2NxN, bFMD );

xCheckRDCostInter( rpcBestCU, rpcTempCU, SIZE_2NxnU, bFMD );

xCheckRDCostInter( rpcBestCU, rpcTempCU, SIZE_2NxnD, bFMD ); 4种非对称的划分

xCheckRDCostInter( rpcBestCU, rpcTempCU, SIZE_nLx2N, bFMD );

这里在调用这个帧内RDcost函数时,rpcBestCU中始终存放的是当前CU下最优的PU的模式和划分信息的CU结构体。

帧内:

xCheckRDCostIntra( rpcBestCU, rpcTempCU, SIZE_2Nx2N ); 2NX2N的划分。 PU为CU的大小。

xCheckRDCostIntra( rpcBestCU, rpcTempCU, SIZE_NxN ); 当CU为最小的CU的时候,将尝试 分割为4个PU。

在RD-cost的函数的最后有这样一个函数

xCheckBestMode(rpcBestCU, rpcTempCU, uiDepth);

接下来就该递归的分割LCU,下面看看分割的判断

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++ )

{

pcSubBestPartCU->initSubCU( rpcTempCU, uiPartUnitIdx, uhNextDepth, iQP );

pcSubTempPartCU->initSubCU( rpcTempCU, uiPartUnitIdx, uhNextDepth, iQP );

注意这里是用rpcTempCU对pcSubBestPartCU和pcSubTemPartC进行初始化,函数到此 rpcBestCU里面还是当前CU64x64大小最优的PU信息。

接下来是递归的调用自己

if ( rpcBestCU->isIntra(0) )

{

xCompressCU( pcSubBestPartCU, pcSubTempPartCU, uhNextDepth, SIZE_NONE );

进入这个函数后,CU的大小为32X32 iPartUnitIdx 这里pcSubBestPartCU就和rpcBestCU一样始终放着当前最优的预测的信息。

}

else

{

xCompressCU( pcSubBestPartCU, pcSubTempPartCU, uhNextDepth, rpcBestCU->getPartitionSize(0) );

}

显然这里要做的是将4个最优的32X32CU的RD-cost累加。注意这里有一个语句是

rpcTempCU->copyPartFrom( pcSubBestPartCU, uiPartUnitIdx, uhNextDepth );

跟进去一看这个函数的几个代码就知道这个语句就是完成4个划分的最优的信息的累加,以便和为分割前的CU的最优的预测模式的RD-cost进行比较也就是m_ppcBestCU进行比较。

}

} 分割的循环

完成了四个分割,即2中的过程2中的第九步。这里就 rpcTempCU存储的是CU的4个划分的信息。

可以看见 xCheckBestMode( rpcBestCU, rpcTempCU, uiDepth);函数将未分割的CU和分割之后的4个CU进行比较来决定是否进行CU的划分。

}

但是奇怪的是如何和最开始CompressCU的参数pcCU的参数联系上。这里有个函数。在最后面

rpcBestCU->copyToPic(uiDepth);

这个函数就是将得到的最优的PU的模式和预测信息,及CU的划分的信息赋值到pcCU中。

进去看这个函数,

TComDataCU*& rpcCU = m_pcPic->getCU( m_uiCUAddr );第一个语句中的rpcCU正好是CompressCU的参数。

相关推荐