VTM5.0中帧内技术主要接收的提案有以下三个:
N0271 CCLM derived with four neighbouring samples (也是本人所在的实验室提出的,蹭个热度~)
N0137 Intra chroma partitioning and prediction restriction
N0217 Affine linear weighted intra prediction
其中前两个都是一种改进,最新最具有技术性的应该是第三个,也就是本文想要探究的MIP技术。
对于帧内预测的框架代码解析,见H.266/VVC代码学习26:VTM5.0中IntraPrediction类及其相应全局函数
1 综述
根据提案中的叙述,我们可以得知大体框架:
(1) 对亮度块上和左参考行进行平均操作(下采样),获得采样点(4或8个)。
(2) 对得到的样本进行矩阵向量乘法,并加上一个偏移,得到部分预测值(4x4;4x8;8x4;8x8)。
(3) 进行双线性插值获得最终亮度预测值。
2 入口代码
应用到MIP技术的位置在IntraSearch的亮度预测中,这里根据不同的块尺寸,会得到不同的矩阵,对应不同的矩阵新增加了不同于传统67种模式的新的MIP模式,共65种(4x4的块增加35种模式,8x4,4x8,8x8 增加19种模式,其他的块增加11种模式)。
大体过程在亮度预测的第二轮SATD的筛选中(详情见H.266/VVC代码学习5:VTM4.0帧内亮度预测代码(estIntraPredLumaQT))。可以看出和传统预测的入口代码框架一样,过程为:初始化-预测-根据代价更新模式列表。至于具体操作代码将放在后面进行学习。
/**************************************************** 进行第一次的MIP预测 **********************************************************/
//*** Derive MIP candidates using Hadamard 使用Hadamard导出MIP候选模式
if (testMip)
{
cu.mipFlag = true;
pu.multiRefIdx = 0;
initIntraMip( pu );//////////////////////////////////////////////////////////////////初始化MIP
for (uint32_t uiMode = 0; uiMode < getNumModesMip(pu.Y()); uiMode++)/////////////////获取MIP模式,35 or 19 or 11 or 0
{
pu.intraDir[CHANNEL_TYPE_LUMA] = uiMode;//这里的uimode是MIP模式的标号
predIntraMip(COMPONENT_Y, piPred, pu);/////////////////////////////////////////////进行predIntraMip的预测
#if JVET_N0363_INTRA_COST_MOD
// Use the min between SAD and HAD as the cost criterion
// SAD is scaled by 2 to align with the scaling of HAD
Distortion minSadHad = std::min(distParamSad.distFunc(distParamSad)*2, distParamHad.distFunc(distParamHad));
#else
Distortion dist = distParam.distFunc(distParam);
#endif
m_CABACEstimator->getCtx() = SubCtx( Ctx::MipFlag, ctxStartMipFlag );
m_CABACEstimator->getCtx() = SubCtx( Ctx::MipMode, ctxStartMipMode );
uint64_t fracModeBits = xFracModeBitsIntra(pu, uiMode, CHANNEL_TYPE_LUMA);
#if JVET_N0363_INTRA_COST_MOD
double cost = double(minSadHad) + double(fracModeBits) * sqrtLambdaForFirstPass;//得到MIP模式的代价值
#else
double cost = double(dist) + double(fracModeBits) * sqrtLambdaForFirstPass;
#endif
updateCandList(ModeInfo(true, 0, NOT_INTRA_SUBPARTITIONS, uiMode), cost, uiRdModeList, CandCostList, numModesForFullRD);//根据代价值,更新最小代价值序列
#if JVET_N0363_INTRA_COST_MOD
updateCandList(ModeInfo(true, 0, NOT_INTRA_SUBPARTITIONS, uiMode), double(minSadHad), uiHadModeList, CandHadList, numHadCand);
#else
updateCandList(ModeInfo(true, 0, NOT_INTRA_SUBPARTITIONS, uiMode), double(dist), uiHadModeList, CandHadList, numHadCand);
#endif
}
3 底层代码
代码结构如下: