此系列是为了记录自己学习VTM10.0的过程和锻炼表达能力,主要是从解码端进行入手。由于本人水平有限,出现的错误恳请大家指正,欢迎与大家一起交流进步。
上一篇博客(VTM10.0代码学习3)提到两个重要的函数coding_tree_unit()和decompressCtu(),接下来就用两篇博客的篇幅讲解一下coding_tree_unit()这个函数,本篇博客主要是讲从码流解析得到如何将CTU划分成CU,CU级的语义信息讲解会留在下一篇博客中。
1.coding_tree_unit()
CUCtx cuCtx( qps[CH_L] );//用prevLumaQP初始化CU上下文模型类
QTBTPartitioner partitioner;//定义划分类实例
partitioner.initCtu(area, CH_L, *cs.slice);
cs.treeType = partitioner.treeType = TREE_D;//设置默认树类型
cs.modeType = partitioner.modeType = MODE_TYPE_ALL;//设置默认可进行的预测模式
cuCtx:存储着CU上下文信息(即上一个CU的某些信息),这里用先前亮度分量的QP初始化,有可能是前一个CU的亮度分量QP,也有可能是slice的默认QP
partitioner:存储着和划分相关的信息
initCtu():初始化划分类实例,提供划分的区域和是色度划分还是亮度划分的信息
treeType:cs和划分类里面都有,色度和亮度划分相同就用TREE_D表示,色度和亮度划分不同就分别用TREE_L和TREE_C表示
modeType:cs和划分类里面都有,表示可进行的预测模式
sao( cs, ctuRsAddr );//有关SAO的语法元素解码,具体参考JVET-S2001 7.3.11.3 P113
有关于SAO的,这里就不具体展开了,等看到SAO再回过头来看也不迟。这里稍微提一下,解析出来的语法元素放在帧类的属性m_sao里,是SAOBlkParam类的容器。SAOBlkParam里面存着三个分量的SAOOffset类信息,SAOOffset里面就存着对应分量解码出来的sao语法元素。
//如果当前slice开启ALF,执行以下分支
if (cs.sps->getALFEnabledFlag() && (cs.slice->getTileGroupAlfEnabledFlag(COMPONENT_Y)))
{
}
//如果开启CCALF,则执行以下分支
if (cs.sps->getCCALFEnabledFlag())
{
}
这里有两个分支,都可以与JVET-S2001里面的7.3.11.2小节对应起来,这里就不再展开。第一个分支与ALF有关,解析出来的语法元素放在帧类的属性里;第二个分支与CCALF有关,解析出来的语法元素放在slice类的属性m_ccAlfFilterControl里。
if ( CS::isDualITree(cs) && cs.pcv->chrFormat != CHROMA_400 && cs.pcv->maxCUWidth > 64 )
{
//如果当前slice是I slice,且开启dual tree,且色度采样格式不是4:0:0,且CTU的宽高大于64
QTBTPartitioner chromaPartitioner;//定义色度的划分类实例
chromaPartitioner.initCtu(area, CH_C, *cs.slice);
CUCtx cuCtxChroma(qps[CH_C]);//用prevChromaQP初始化色度的CU上下文模型类
coding_tree(cs, partitioner, cuCtx, &chromaPartitioner, &cuCtxChroma);//具体参考JVET-S2001 7.3.11.4 P114,还包括一部分dual_tree_implicit_qt_split的内容
qps[CH_L] = cuCtx.qp;//更新prevLumaQP
qps[CH_C] = cuCtxChroma.qp;//更新prevChromaQP
}
else
{
coding_tree(cs, partitioner, cuCtx);//具体参考JVET-S2001 7.3.11.4 P114
qps[CH_L] = cuCtx.qp;//更新prevLumaQP
if( CS::isDualITree( cs ) && cs.pcv->chrFormat != CHROMA_400 )
{
//如果当前slice是I slice,且开启dual tree,且色度采样格式不是4:0:0
CUCtx cuCtxChroma( qps[CH_C] );//用prevChromaQP初始化色度的CU上下文模型类
partitioner.initCtu(area, CH_C, *cs.slice);//将partitioner变为色度的划分类实例
coding_tree(cs, partitioner, cuCtxChroma);//具体参考JVET-S2001 7.3.11.4 P114
qps[CH_C] = cuCtxChroma.qp;//更新prevChromaQP
}
}
当开启dual tree(意味着当前slice为I slice,采样格式不可能为4:0:0)时,同时CTU的宽高大于64执行if分支:
-
定义色度的划分类