(3.10 update) 找到了别人对这个函数的整理,质量比我这个高很多,作为学习的目标,链接在这里:
HM编码器代码阅读(12)——CU编码_NB_vol_1的博客-CSDN博客
我之前的理解有点偏差,把AMVP和标准帧间预测当作两个东西了,但是实际上标准帧间预测里面就会用到AMVP,AMVP技术只是给标准帧间预测提供运动搜索的起点的,在这里做个修正。
---
代码版本:HM-16.6
记录编码过程中的核心函数xCompressCU的整理。
先说一句别的,在看编码器代码的时候发现有两类函数:compressXXX和encodeXXX。
比如TEncCu::compressCtu和TEncCu::encodeCtu,以及TEncCu::xCompressCU和TEncCu::xEncodeCU。那么有什么差别呢?我发现compress函数是进行模式搜索的,而encode函数则是完成模式搜索,确定最优模式之后,实际将搜索结果进行编码(即生成压缩后的文件的)。所以先在这里mark一下。
首先需要看看EncCu这个类有些什么成员变量,我先截取了一部分。
首先我又有点小发现,就是成员变量的命名上,为什么会有一点前缀,比如m_ppc, m_pc之类的。我暂时觉得应该是希望读者能够通过看成员变量的变量名。m_不必多说,是member的含义。ppc代表该变量是指向指针的指针,pc代表是指针。后面还有个TEncSbac*** m_pppcRDSbacCoder;,可以验证我的想法。uh前缀还不确定,但是u应当是unsigned的意思。
言归正传,这个类的前两个成员变量是指针数组,其数组长度在TEncCu::create中被指定,大小为m_uhTotalDepth-1。因此并不会很大,并且可以看到每一个深度上实际只有一个TComDataCU数据结构。(这是不是意味着不能并行编码?)
同时第三个成员变量的含义似乎并不是单纯的最大深度,因为create函数中它被初始化为:m_uhTotalDepth = uhTotalDepth + 1; 我还没有理解这个+1的操作的意义(new TComDataCU的时候又变成m_uhTotalDepth-1,一加一减正好抵消,很奇怪)
/// CU encoder class
class TEncCu
{
private:
TComDataCU** m_ppcBestCU; ///< Best CUs in each depth
TComDataCU** m_ppcTempCU; ///< Temporary CUs in each depth
UChar m_uhTotalDepth;
TComYuv** m_ppcPredYuvBest; ///< Best Prediction Yuv for each depth
TComYuv** m_ppcResiYuvBest; ///< Best Residual Yuv for each depth
TComYuv** m_ppcRecoYuvBest; ///< Best Reconstruction Yuv for each depth
TComYuv** m_ppcPredYuvTemp; ///< Temporary Prediction Yuv for each depth
TComYuv** m_ppcResiYuvTemp; ///< Temporary Residual Yuv for each depth
TComYuv** m_ppcRecoYuvTemp; ///< Temporary Reconstruction Yuv for each depth
TComYuv** m_ppcOrigYuv; ///< Original Yuv for each depth
// ...
};
接下来看正式开始编码部分。首先是inter部分,分别进行inter模式,SKIP模式。这里有一个getUseEarlySkipDetection,会控制进行inter模式尝试还是Skip模式尝试的先后顺序。我还不是很懂这个先后顺序对于编码过程的影响。
// do inter modes, SKIP and 2Nx2N
if( rpcBestCU->getSlice()->getSliceType() != I_SLICE )
{
// 2Nx2N
if(m_pcEncCfg->getUseEarlySkipDetection())
{
xCheckRDCostInter( rpcBestCU, rpcTempCU, SIZE_2Nx2N DEBUG_STRING_PASS_INTO(sDebug) );
rpcTempCU->initEstData( uiDepth, iQP, bIsLossl