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

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

  1. 判断当前模式是垂直类模式还是水平类模式
  2. 根据当前模式计算角度偏移值
  3. 根据当前模式判断PDPC是否可用
  4. 判断是否对当前模式参考像素进行滤波
// Function for initialization of intra prediction parameters
// 初始化帧内预测参数
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 );//使用ISP

  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 = getWideAngle( 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;
  m_ipaParam.applyPDPC            = ((puSize.width >= MIN_TB_SIZEY && puSize.height >= MIN_TB_SIZEY) || !isLuma(compId)) && m_ipaParam.multiRefIndex == 0;
  //如果predMode>=34,则intraPredAngleMode=predMode-VER_IDX(50)
  //否则,intraPredAngleMode=predMode-HOR_IDX(18)
  //由于宽角度模式为-14~80,故该值为-32~30
  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

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

    m_ipaParam.invAngle              = invAngTable[absAngMode];
    m_ipaParam.intraPredAngle        = signAng * absAng;// 预测模式转化为预测角度
    if (intraPredAngleMode < 0)//模式19~49,不使用PDPC
    {
      m_ipaParam.applyPDPC = false;
    }
    else if (intraPredAngleMode > 0)
    {
      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.invAngle - 2) - 8));
      m_ipaParam.applyPDPC &= m_ipaParam.angularScale >= 0;
    }
  }
  /******************判断是否对参考像素进行滤波*************************/
  // high level conditions and DC intra prediction
  // 高层条件与DC帧内预测
  if(   sps.getSpsRangeExtension().getIntraSmoothingDisabledFlag()
    || !isLuma( chType )
    || useISP
    || PU::isMIP( pu, chType )
    || m_ipaParam.multiRefIndex
    || DC_IDX == dirMode
    )
  {
  }
#if JVET_P0059_CHROMA_BDPCM
  else if ((isLuma(chType) && pu.cu->bdpcmMode) || (!isLuma(chType) && pu.cu->bdpcmModeChroma)) // BDPCM
#else
  else if (isLuma( chType ) && pu.cu->bdpcmMode) // BDPCM
#endif
  {
    m_ipaParam.refFilterFlag = false;
  }
  else if (dirMode == PLANAR_IDX) // Planar intra prediction Planar模式
  {
    m_ipaParam.refFilterFlag = puSize.width * puSize.height > 32 ? true : false;
  }
  else if (!useISP)// HOR, VER and angular modes (MDIS) 水平、垂直和其余角度模式
  {
    bool filterFlag = false;
    {
      const int diff = std::min<int>( abs( predMode - HOR_IDX ), abs( predMode - VER_IDX ) );
      const int log2Size = ((floorLog2(puSize.width) + floorLog2(puSize.height)) >> 1);
      CHECK( log2Size >= MAX_INTRA_FILTER_DEPTHS, "Size not supported" );
      filterFlag = (diff > m_aucIntraFilter[log2Size]);
    }

    // Selelection of either ([1 2 1] / 4 ) reference 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;
    }
  }
}
发布了95 篇原创文章 · 获赞 138 · 访问量 6万+

猜你喜欢

转载自blog.csdn.net/BigDream123/article/details/104520821