H.266/VVC代码学习:帧内预测之初始化帧内预测参数(initPredIntraParams)

VTM中,在进行帧内预测之前,需要对帧内预测参数进行初始化,初始化函数是initPredIntraParams,该函数主要包含以下几个功能:

  1. 判断当前模式是垂直类模式还是水平类模式
  2. 根据当前模式计算角度偏移值
  3. 根据当前模式判断PDPC是否可用
  4. 判断是否对当前模式参考像素进行滤波
void IntraPrediction::initPredIntraParams(const PredictionUnit & pu, const CompArea area, const SPS& sps)
{
  const ComponentID compId = area.compID;
  const ChannelType chType = toChannelType(compId);

  const bool        useISP = NOT_INTRA_SUBPARTITIONS != pu.cu->ispMode && isLuma( chType );

  const Size   cuSize    = Size( pu.cu->blocks[compId].width, pu.cu->blocks[compId].height );
  const Size   puSize    = Size( area.width, area.height );
  const Size&  blockSize = useISP ? cuSize : puSize;
  const int      dirMode = PU::getFinalIntraMode(pu, chType); //获取角度模式
  const int     predMode = getModifiedWideAngle( blockSize.width, blockSize.height, dirMode ); //将角度模式扩展为宽角度模式

  m_ipaParam.isModeVer            = predMode >= DIA_IDX; //是否是垂直类角度模式(大于等于34)
  m_ipaParam.multiRefIndex        = isLuma (chType) ? pu.multiRefIdx : 0 ; //多参考行索引
  m_ipaParam.refFilterFlag        = false;
  m_ipaParam.interpolationFlag    = false;
  // 应用PDPC条件:大于等于4x4且没有使用多参考行
  m_ipaParam.applyPDPC            = (puSize.width >= MIN_TB_SIZEY && puSize.height >= MIN_TB_SIZEY) && m_ipaParam.multiRefIndex == 0;
  //如果predMode>=34,则intraPredAngleMode=predMode-VER_IDX(50)
  //否则,intraPredAngleMode=HOR_IDX(18)-predMode
  //由于宽角度模式为-14~80,故该值为-16~32
  const int    intraPredAngleMode = (m_ipaParam.isModeVer) ? predMode - VER_IDX : -(predMode - HOR_IDX);

  int absAng = 0;
  // 2~66种模式对应的偏移值
  if (dirMode > DC_IDX && dirMode < NUM_LUMA_MODE) // intraPredAngle for directional modes
  {
    // 先乘以256(左移8位),运算出结果再右移8位,以定点实现浮点运算精度
    static const int angTable[32]    = { 0,    1,    2,    3,    4,    6,     8,   10,   12,   14,   16,   18,   20,   23,   26,   29,   32,   35,   39,  45,  51,  57,  64,  73,  86, 102, 128, 171, 256, 341, 512, 1024 };
    // 设置invAngTable的目的是为了消除帧内角度预测模式在计算预测值时麻烦的除法运算
    static const int invAngTable[32] = {
      0,   16384, 8192, 5461, 4096, 2731, 2048, 1638, 1365, 1170, 1024, 910, 819, 712, 630, 565,
      512, 468,   420,  364,  321,  287,  256,  224,  191,  161,  128,  96,  64,  48,  32,  16
    };   // (512 * 32) /Angle 投影的位置,用的时候需要右移9位

    const int     absAngMode         = abs(intraPredAngleMode);//值为0~32
    const int     signAng            = intraPredAngleMode < 0 ? -1 : 1;
                  absAng             = angTable  [absAngMode];//当前角度的对应的下标值 得到的表格值

    m_ipaParam.absInvAngle           = invAngTable[absAngMode]; // 每种角度对应的投影位置
    m_ipaParam.intraPredAngle        = signAng * absAng;// 角度偏移值 offset
    if (intraPredAngleMode < 0)//模式19~49,不使用PDPC
    {
      m_ipaParam.applyPDPC = false;
    }
    else if (intraPredAngleMode > 0) //小于等于18或大于等于50
    {
      const int sideSize = m_ipaParam.isModeVer ? puSize.height : puSize.width;
      const int maxScale = 2;

      m_ipaParam.angularScale = std::min(maxScale, floorLog2(sideSize) - (floorLog2(3 * m_ipaParam.absInvAngle - 2) - 8));
      m_ipaParam.applyPDPC &= m_ipaParam.angularScale >= 0; // 对于非垂直和非水平模式,应用PDPC时要求Scale大于等于0
    }
  }
  /******************判断是否对参考像素进行滤波*************************/
  // high level conditions and DC intra prediction
  if(   sps.getSpsRangeExtension().getIntraSmoothingDisabledFlag()
    || !isLuma( chType )
    || useISP
    || PU::isMIP( pu, chType )
    || m_ipaParam.multiRefIndex
    || DC_IDX == dirMode
    )
  {
  }
  else if ((isLuma(chType) && pu.cu->bdpcmMode) || (!isLuma(chType) && pu.cu->bdpcmModeChroma)) // BDPCM
  {
    m_ipaParam.refFilterFlag = false;
  }
  else if (dirMode == PLANAR_IDX) // Planar intra prediction Planar模式 w*h>32时,才会对参考像素进行滤波
  {
    m_ipaParam.refFilterFlag = puSize.width * puSize.height > 32 ? true : false; // 使用[1 2 1]滤波器
  }
  else if (!useISP)// HOR, VER and angular modes (MDIS) 水平、垂直和其余角度模式
  {
    bool filterFlag = false;
    {
      // 水平或者垂直模式时, minDistVerHor等于0, 不可能大于intraHorVerDistThres[ nTbS ],即不会对水平和垂直模式滤波
      const int diff = std::min<int>( abs( predMode - HOR_IDX ), abs( predMode - VER_IDX ) ); // minDistVerHor
      const int log2Size = ((floorLog2(puSize.width) + floorLog2(puSize.height)) >> 1); // nTbS

      CHECK( log2Size >= MAX_INTRA_FILTER_DEPTHS, "Size not supported" );
      filterFlag = (diff > m_aucIntraFilter[log2Size]); // minDistVerHor是否大于intraHorVerDistThres[ nTbS ]
    }

    // Selelection of either ([1 2 1] / 4 ) refrence filter OR Gaussian 4-tap interpolation filter
    // 选择[1, 2, 1]参考像素滤波器或者4抽头高斯插值滤波器
    if (filterFlag)
    {
      const bool isRefFilter       =  isIntegerSlope(absAng); // 是否仅用整像素位置的参考像素
      CHECK( puSize.width * puSize.height <= 32, "DCT-IF interpolation filter is always used for 4x4, 4x8, and 8x4 luma CB" );
      m_ipaParam.refFilterFlag     =  isRefFilter;// 参考像素滤波
      m_ipaParam.interpolationFlag = !isRefFilter;  //插值滤波
    }
  }
}

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值