H.266/VVC代码学习笔记2 :深入解析帧内色度预测模式的编码方式及其代码详解

之前的博客中我详细的讲解了关于视频编码中熵编码部分的具体的技术细节
H.266/VVC代码学习笔记5:VTM4.0中的熵编码CABAC部分的详细解析
今天就来具体的讲一下在帧内色度预测模式中的熵编码具体是怎么编码的。

一、VTM2.0中的帧内色度模式的编码

1.编码端的Rdcost:
按照下表的顺序对这6种模式进行Rdcost检测;

    modeList[  0 ] = PLANAR_IDX;
    modeList[  1 ] = VER_IDX;
    modeList[  2 ] = HOR_IDX;
    modeList[  3 ] = DC_IDX;
	modeList[4] = LM_CHROMA_IDX;
    modeList[5] = DM_CHROMA_IDX;

DM模式检测的是对应亮度块的帧内模式;
当DM模式对应的帧内模式与前4种模式相同时,将前面的该模式置为角度模式66去进行Rdcost检测

2.熵编码
在这里插入图片描述

编码的第一位是判断是否用DM模式(0有效)
编码的第二位是判断是否用LM模式(0有效)
第一位用上下文模型1,第二位用上下文模型2,其余位用旁路编码器去编码。

二、VTM4.0中的帧内色度模式的编码

1.编码端的Rdcost:
(1)在Rdcost之前增加提前的SATD检测:
对VER,HOR,LM_L,LM_T,DM(角度模式和MDLM)这5种模式提前进行残差的(预测值与原始值之间)SATD检测,根据SATD的结果从小到大排序,将SATD最大的两种模式去掉(即这两种模式不进行Rdcost检测);
对PLANAR,DC,LM(非角度模式和LM)不进行提前的SATD检测,直接进行Rdcost检测;
(2)将剩余的6种模式按照右表的顺序进行Rdcost检测,选择最优模式;
(3)DM模式检测的是对应亮度块的帧内模式;当DM模式对应的帧内模式与前4种模式相同时,将前面的该模式置为角度模式66去进行Rdcost检测

    modeList[  0 ] = PLANAR_IDX;
    modeList[  1 ] = VER_IDX;
    modeList[  2 ] = HOR_IDX;
    modeList[  3 ] = DC_IDX;
    modeList[4] = LM_CHROMA_IDX;
    modeList[5] = MDLM_L_IDX;
    modeList[6] = MDLM_T_IDX;
    modeList[7] = DM_CHROMA_IDX;

2.熵编码
在这里插入图片描述

注:VTM3.0中为MDLM设计了一个初始值固定的ctx3
第一位是否用DM(0有效)
第二位是否用LM(67)(0有效)
第三位是否用LM_L或者LM_T (1有效)

若第三位为1,则第四位标志MDLM的方向,是L还是T
若第三位为0,则第四位和第五位按顺序标志四种传统角度模式

具体到代码中如下:
这是帧内色度的8种预测模式的熵编码的流程具体细节

void CABACWriter::intra_chroma_pred_mode( const PredictionUnit& pu )
{
  const unsigned intraDir = pu.intraDir[1];
  const bool     isDerivedMode = intraDir == DM_CHROMA_IDX;//首先判断是否为DM模式

  m_BinEncoder.encodeBin(isDerivedMode ? 0 : 1, Ctx::IntraChromaPredMode(0));//如果是DM模式,只将第一位编为0,用ctx1.

  if (isDerivedMode)
  {
    return;
  }

  // LM chroma mode
  if( pu.cs->sps->getUseLMChroma() )//如果是lm模式,将第一位编为1,用ctx1.
  {
    intra_chroma_lmc_mode( pu );//LM模式的三种编码方式
    if ( PU::isLMCMode( intraDir ) )
    {
      return;
    }
  }

  // chroma candidate index
  unsigned chromaCandModes[ NUM_CHROMA_MODE ];
  PU::getIntraChromaCandModes( pu, chromaCandModes );

  int candId = 0;
  //如果经过前面的判断都不是DM或者LM模式,则进入下面的四种常规模式的编码
 
  for ( ; candId < NUM_CHROMA_MODE; candId++ )
  {
    if( intraDir == chromaCandModes[ candId ] )
    {
      break;   
     }
  }

  CHECK( candId >= NUM_CHROMA_MODE, "Chroma prediction mode index out of bounds" );
  CHECK( chromaCandModes[ candId ] == DM_CHROMA_IDX, "The intra dir cannot be DM_CHROMA for this path" );
  {
    m_BinEncoder.encodeBinsEP( candId, 2 );//这里选用常规编码器,编码最后的两位
  }
}

这是为三种LM模式单独准备的熵编码的函数

void CABACWriter::intra_chroma_lmc_mode( const PredictionUnit& pu )
{
  const unsigned intraDir = pu.intraDir[1];
    int lmModeList[10];
    int maxSymbol = PU::getLMSymbolList( pu, lmModeList );//maxSymbol=3.
    int symbol    = -1;
    for ( int k = 0; k < LM_SYMBOL_NUM; k++ )
    {
      if ( lmModeList[k] == intraDir || ( lmModeList[k] == -1 && intraDir < LM_CHROMA_IDX ) )
      {
        symbol = k;
        break;
      }
      //如果选中LM模式,symbol=0
      //如果选中其他模式,symbol=1
      //如果选中L模式,symbol=2
      //如果选中T模式,symbol=3

    }
    CHECK( symbol < 0, "invalid symbol found" );
    //这里对LM选用合适的上下文模型进行具体的编码
    unary_max_symbol(symbol, Ctx::IntraChromaPredMode(1), Ctx::IntraChromaPredMode(2), maxSymbol - 1);
}

这里是三种LM模式具体的编码方式

void CABACWriter::unary_max_symbol( unsigned symbol, unsigned ctxId0, unsigned ctxIdN, unsigned maxSymbol )
{
  CHECK( symbol > maxSymbol, "symbol > maxSymbol" );
  const unsigned totalBinsToWrite = std::min( symbol + 1, maxSymbol );
  //如果是LM模式,totalBinsToWrite=1,symbol=0
  //如果是其他模式,totalBinsToWrite=2,symbol=1
  //如果是L模式,totalBinsToWrite=3,symbol=2
  //如果是T模式,totalBinsToWrite=3,symbol=3
  for( unsigned binsWritten = 0; binsWritten < totalBinsToWrite; ++binsWritten )
  {
    const unsigned nextBin = symbol > binsWritten;
    //如果是LM模式,nextBin=1;第二位编0
    //如果是其他模式,nextBin=1;第二位编1,nextBin++,第三位编0
    //如果是L模式,nextBin=1;第二位编1,nextBin++,第三位编1,nextBin++,第四位编0
    //如果是T模式,nextBin=1;第二位编1,nextBin++,第三位编1,nextBin++,第四位编1
    m_BinEncoder.encodeBin( nextBin, binsWritten == 0 ? ctxId0 : ctxIdN );
  }
}
  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值