H.266/VVC专栏传送
上一篇:H.266/VVC-VTM代码学习-帧内预测14-ISP模式在estIntraPredLumaQT中的设定(2)
下一篇:H.266/VVC-VTM代码学习-帧内预测16-解码端xIntraRecBlk完成TU指定分量帧内重建(附ISP变换和预测尺寸不同、JCCR、LMCS简述)
目录
前言
VTM是H.266/VVC视频编码标准的参考软件,研究VTM代码给研究人员解释了VVC编码标准的详细标准规范与细节。
本文是笔者对VTM代码的一点学习记录,成文于笔者刚开始接触VVC期间,期间很多概念和理论框架还很不成熟,若文中存在错误欢迎批评指正,也欢迎广大视频编码学习者沟通交流、共同进步。
VTM代码的下载及编译请参考博文:
【视频编码学习】H.266/VVC参考软件VTM配置运行(VTM-6.0版本)
本文涉及的代码主要存在于工程下的Lib\DecoderLib\DecCu.cpp文件中。
一、decompressCtu函数作为帧内重建的入口函数
void DecCu::decompressCtu( CodingStructure& cs, const UnitArea& ctuArea )
{
//DualITree时maxNumChannelType=2
//即I帧且亮度色度双重树时,CTU对亮度域和色度域有两套划分树,有两套CU,所以分开处理
//不是400色彩采样率,且是双重树时,maxNumChannelType=2
const int maxNumChannelType = cs.pcv->chrFormat != CHROMA_400 && CS::isDualITree( cs ) ? 2 : 1;
//若需要重置IBCBuffer
if (cs.resetIBCBuffer)
{
//重置IBC的Buffer(用-1填充)
m_pcInterPred->resetIBCBuffer(cs.pcv->chrFormat, cs.slice->getSPS()->getMaxCUHeight());
cs.resetIBCBuffer = false;
}
//DualITree时亮度和色度分开处理,非DualITree时这个循环只执行一次
//DualITree需要严格区分luma和chroma,而非DualITree无需区分luma和chroma的,因为此时的cu同时包含了Y/Cb/Cr域
for( int ch = 0; ch < maxNumChannelType; ch++ )
{
const ChannelType chType = ChannelType( ch );
Position prevTmpPos;
prevTmpPos.x = -1; prevTmpPos.y = -1;
//遍历当前CTU的CU,逐个进行解压缩
for( auto &currCU : cs.traverseCUs( CS::getArea( cs, ctuArea, chType ), chType ) )
{
//如果当前Y分量有效(当前色彩采样类型有效、当前分量有效、当前块尺寸大于0)
if(currCU.Y().valid())
{
//为IBC重置VPDU
//VSize是VPDU的尺寸,设置为CU的尺寸和64中的较小值
const int vSize = cs.slice->getSPS()->getMaxCUHeight() > 64 ? 64 : cs.slice->getSPS()->getMaxCUHeight();
if((currCU.Y().x % vSize) == 0 && (currCU.Y().y % vSize) == 0)
{
for(int x = currCU.Y().x; x < currCU.Y().x + currCU.Y().width; x += vSize)
{
for(int y = currCU.Y().y; y < currCU.Y().y + currCU.Y().height; y += vSize)
{
m_pcInterPred->resetVPDUforIBC(cs.pcv->chrFormat, cs.slice->getSPS()->getMaxCUHeight(), vSize, x + g_IBCBufferSize / cs.slice->getSPS()->getMaxCUHeight() / 2, y);
}
}
}
}
//当前模式不为intra和PLT,且当前CU的Y分量有效(当前色彩采样类型有效、当前分量有效、当前块尺寸大于0)
if (currCU.predMode != MODE_INTRA && currCU.predMode != MODE_PLT && currCU.Y().valid())
{
//根据解码的运动信息,得到mv
xDeriveCUMV(currCU);
#if K0149_BLOCK_STATISTICS
if(currCU.geoFlag)
{
storeGeoMergeCtx(m_geoMrgCtx);
}
#endif
}
//对当前CU预测模式判断,作相应重建
switch( currCU.predMode )
{
case MODE_INTER:
case MODE_IBC:
//帧间模式的重建
xReconInter( currCU );
break;
case MODE_PLT:
case MODE_INTRA:
//帧内模式的重建
xReconIntraQT( currCU );
break;
default:
THROW( "Invalid prediction mode" );
break;
}
//用解码后的采样点填充 IBC Buffer
m_pcInterPred->xFillIBCBuffer(currCU);
DTRACE_BLOCK_REC( cs.picture->getRecoBuf( currCU ), currCU, currCU.predMode );
}
}
#if K0149_BLOCK_STATISTICS
getAndStoreBlockStatistics(cs, ctuArea);
#endif
}
二、xReconIntraQT函数调用函数实现PLT模式和INTRA模式的重建(入口在一中)
void DecCu::xReconIntraQT( CodingUnit &cu )
{
//若当前CU是PLT模式
if (CU::isPLT(cu))
{
//当前划分树是separate tree(分离树)
//当前树的状态不是TREE_D(TREE_D对于单树表示联合树,对于二重树表示TREE_L和TREE_C),或当前CS是二重树
if (cu.isSepTree())
{
//当前CU是Luma CU
if (cu.chType == CHANNEL_TYPE_LUMA)
{
//对Luma进行重建
xReconPLT(cu, COMPONENT_Y, 1);
}
//色彩采样率不为400 且 当前CU是Chroma CU
if (cu.chromaFormat != CHROMA_400 && (cu.chType == CHANNEL_TYPE_CHROMA))
{
//对Chroma两通道进行重建
xReconPLT(cu, COMPONENT_Cb, 2);
}
}
//当前划分树不是separate tree
//当前树状态是TREE_D,且当前CS不是二重树
else
{
//色彩采样率不为400
if( cu.chromaFormat != CHROMA_400 )
{
//对三个通道进行重建
xReconPLT(cu, COMPONENT_Y, 3);
}
//色彩采样率为400
else
{
xReconPLT(cu, COMPONENT_Y, 1);//只对Luma一个通道重建
}
}
return;
}
/******* 以下是对帧内模式的重建 *******/
//若采用ACT变换
if (cu.colorTransform)
{
//进行ACT变换的帧内模式重建
xIntraRecACTQT(cu);
}
//若不采用ACT变换
else
{
//获取通道数量
const uint32_t numChType = ::getNumberValidChannels( cu.chromaFormat );
for( uint32_t chType = CHANNEL_TYPE_LUMA; chType < numChType; chType++ )
{
if( cu.blocks[chType].valid() )
{
//cu分别对luma和chroma,实现帧内像素的重建
xIntraRecQT( cu, ChannelType( chType ) );
}
}
}
}
三、xIntraRecQT函数调用函数实现不使用ACT变换时的帧内预测模式重建(入口在二中)
void DecCu::xIntraRecQT(CodingUnit &cu, const ChannelType chType)
{
//对CU的每个TU分别进行帧内像素重建
for( auto &currTU : CU::traverseTUs( cu ) )
{
if( isLuma( chType ) )
{
//Luma TB 的重建
xIntraRecBlk( currTU, COMPONENT_Y );
}
else
{
const uint32_t numValidComp = getNumberValidComponents( cu.chromaFormat );
for( uint32_t compID = COMPONENT_Cb; compID < numValidComp; compID++ )
{
//色度Cb、Cr的像素重建
xIntraRecBlk( currTU, ComponentID( compID ) );
}
}
}
}
上一篇:H.266/VVC-VTM代码学习-帧内预测14-ISP模式在estIntraPredLumaQT中的设定(2)
下一篇:H.266/VVC-VTM代码学习-帧内预测16-解码端xIntraRecBlk完成TU指定分量帧内重建(附ISP变换和预测尺寸不同、JCCR、LMCS简述)