H.266/VVC代码学习40:VTM6.0中ALF的框架代码(ALFProcess)

正好时隔一年,做回了老本行——环路滤波。
针对ALF,我去年夏天时看过一阵子,对早期BMS版本的ALF一知半解,可参考:H.266/VVC代码学习2:有关ALF
刚刚回归从O2002上看了看最新的ALF,明显感受到了简化,但也很多看不懂了,参考:H.266/VVC代码学习39:自适应环路滤波器算法简介(ALF,翻译自JVET-O2002)
嗯,下面,再一次开启我的ALF之旅。

1 有关ALF

在AlfFilterShape类中,构造函数的重要参数有如下内容

							//			   色度		亮度
  AlfFilterType filterType;	//滤波器类型		0	和	 1
  int filterLength;			//滤波器长度:	5	和	 7
  int numCoeff;				//滤波器抽头数:	7	和	 13		(需理解见pattern)
  int filterSize;			//滤波器大小:	5	和	 7
  std::vector<int> pattern;	//滤波图形
  std::vector<int> weights;	//滤波权重

赋值过程如下:

  AlfFilterShape( int size )
    : filterLength( size ),
    numCoeff( size * size / 4 + 1 ),
    filterSize( size * size / 2 + 1 )

ALF有两种滤波器:亮度7x7菱形滤波器,色度5x5菱形滤波器。代码中如下:

enum AlfFilterType //滤波器种类
{
  ALF_FILTER_5, //色度的5x5滤波器
  ALF_FILTER_7, //亮度的7x7滤波器
  ALF_NUM_OF_FILTER_TYPES //2种
};

对应的,滤波器形状及权重如下

  {
    if( size == 5 )
    {
      pattern = {
                 0,
             1,  2,  3,
         4,  5,  6,  5,  4,
             3,  2,  1,
                 0
      };

      weights = {
                 2,
              2, 2, 2,
           2, 2, 1, 1
      };
      
      filterType = ALF_FILTER_5;
    }
    else if( size == 7 )
    {
      pattern = {
                     0,
                 1,  2,  3,
             4,  5,  6,  7,  8,
         9, 10, 11, 12, 11, 10, 9,
             8,  7,  6,  5,  4,
                 3,  2,  1,
                     0
      };

      weights = {
                    2,
                2,  2,  2,
            2,  2,  2,  2,  2,
        2,  2,  2,  1,  1
      };
      
      filterType = ALF_FILTER_7;
    }
    else
    {
      filterType = ALF_NUM_OF_FILTER_TYPES;
      CHECK( 0, "Wrong ALF filter shape" );
    }
  }

2 所有参数

struct AlfParam
{
  bool                         enabledFlag[MAX_NUM_COMPONENT];                          // alf_slice_enable_flag, alf_chroma_idc—— 各通道每一帧是否使用ALF[三个通道]
#if JVET_O0090_ALF_CHROMA_FILTER_ALTERNATIVES_CTB
  bool                         nonLinearFlag[MAX_NUM_CHANNEL_TYPE][MAX_NUM_ALF_ALTERNATIVES_CHROMA]; // alf_[luma/chroma]_clip_flag—— 是否存在嵌位值??
#else
  bool                         nonLinearFlag[MAX_NUM_CHANNEL_TYPE];                     // alf_nonlinear_enable_flag[Luma/Chroma]
#endif
  short                        lumaCoeff[MAX_NUM_ALF_CLASSES * MAX_NUM_ALF_LUMA_COEFF]; // alf_coeff_luma_delta[i][j]——亮度滤波器系数[25类 x 13值]
  short                        lumaClipp[MAX_NUM_ALF_CLASSES * MAX_NUM_ALF_LUMA_COEFF]; // alf_clipp_luma_[i][j]——亮度滤波器嵌位值[25类 x 13值]
#if JVET_O0090_ALF_CHROMA_FILTER_ALTERNATIVES_CTB
  int                          numAlternativesChroma;                                                  // alf_chroma_num_alts_minus_one + 1 —— 色度可用ALF数量
  short                        chromaCoeff[MAX_NUM_ALF_ALTERNATIVES_CHROMA][MAX_NUM_ALF_CHROMA_COEFF]; // alf_coeff_chroma[i]——色度滤波器系数[8类 x 7值]
  short                        chromaClipp[MAX_NUM_ALF_ALTERNATIVES_CHROMA][MAX_NUM_ALF_CHROMA_COEFF]; // alf_clipp_chroma[i]——色度滤波器限幅值[8类 x 7值]
#else
  short                        chromaCoeff[MAX_NUM_ALF_CHROMA_COEFF];                   // alf_coeff_chroma[i]
  short                        chromaClipp[MAX_NUM_ALF_CHROMA_COEFF];                   // alf_clipp_chroma[i]
#endif
  short                        filterCoeffDeltaIdx[MAX_NUM_ALF_CLASSES];                // filter_coeff_delta[i] —— 亮度Delta索引????
  bool                         alfLumaCoeffFlag[MAX_NUM_ALF_CLASSES];                   // alf_luma_coeff_flag[i] —— 亮度ALF启用标志
  int                          numLumaFilters;                                          // number_of_filters_minus1 + 1 —— 亮度ALF可用数量
  bool                         alfLumaCoeffDeltaFlag;                                   // alf_luma_coeff_delta_flag —— 亮度Delta发出标志????
#if !JVET_O0669_REMOVE_ALF_COEFF_PRED
  bool                         alfLumaCoeffDeltaPredictionFlag;                         // alf_luma_coeff_delta_prediction_flag
#endif
  std::vector<AlfFilterShape>* filterShapes;//滤波器形状
  int                          tLayer;
  bool                         newFilterFlag[MAX_NUM_CHANNEL_TYPE];//新的滤波器使用标志??????
#if !JVET_O0669_REMOVE_ALF_COEFF_PRED
  int                          fixedFilterPattern;
  int                          fixedFilterIdx[MAX_NUM_ALF_CLASSES];
  int                          fixedFilterSetIndex;
#endif

};

  static const int             m_classToFilterMapping[NUM_FIXED_FILTER_SETS][MAX_NUM_ALF_CLASSES]; //分类->固定滤波器 的映射表
  static const int             m_fixedFilterSetCoeff[ALF_FIXED_FILTER_NUM][MAX_NUM_ALF_LUMA_COEFF];//固定滤波器设置滤波系数
  short                        m_fixedFilterSetCoeffDec[NUM_FIXED_FILTER_SETS][MAX_NUM_ALF_CLASSES * MAX_NUM_ALF_LUMA_COEFF];//固定滤波器系数[固定滤波器数量16][亮度系数数量25*13]
#if JVET_O0090_ALF_CHROMA_FILTER_ALTERNATIVES_CTB || JVET_O_MAX_NUM_ALF_APS_8
  short                        m_coeffApsLuma[ALF_CTB_MAX_NUM_APS][MAX_NUM_ALF_LUMA_COEFF * MAX_NUM_ALF_CLASSES];//APS滤波器系数[APS滤波器数量8][亮度系数数量25*13]
  short                        m_clippApsLuma[ALF_CTB_MAX_NUM_APS][MAX_NUM_ALF_LUMA_COEFF * MAX_NUM_ALF_CLASSES];//APS滤波器嵌位值[APS滤波器数量8][亮度系数数量25*13]
#else
  short                        m_coeffApsLuma[6][MAX_NUM_ALF_LUMA_COEFF * MAX_NUM_ALF_CLASSES];
  short                        m_clippApsLuma[6][MAX_NUM_ALF_LUMA_COEFF * MAX_NUM_ALF_CLASSES];
#endif
  short                        m_clipDefault[MAX_NUM_ALF_CLASSES * MAX_NUM_ALF_LUMA_COEFF];//固定滤波器嵌位值[固定滤波器数量16][亮度系数数量25*13]
  bool                         m_created = false;
#if JVET_O0090_ALF_CHROMA_FILTER_ALTERNATIVES_CTB
  short                        m_chromaCoeffFinal[MAX_NUM_ALF_ALTERNATIVES_CHROMA][MAX_NUM_ALF_CHROMA_COEFF];//最终色度系数[色度种类8][抽头位置7]
  AlfParam*                    m_alfParamChroma;//色度系数
#else
  short                        m_chromaCoeffFinal[MAX_NUM_ALF_LUMA_COEFF];
#endif
  Pel                          m_alfClippingValues[MAX_NUM_CHANNEL_TYPE][MaxAlfNumClippingValues];//每种分量的限幅值
  std::vector<AlfFilterShape>  m_filterShapes[MAX_NUM_CHANNEL_TYPE];
  AlfClassifier**              m_classifier;//最终分类:二维数组[第几个分类25][第几种几何变换方式4]
  short                        m_coeffFinal[MAX_NUM_ALF_CLASSES * MAX_NUM_ALF_LUMA_COEFF];//最终选到的滤波器集的系数[亮度系数数量25*13]
  short                        m_clippFinal[MAX_NUM_ALF_CLASSES * MAX_NUM_ALF_LUMA_COEFF];//最终选到的滤波器集的嵌位值[亮度系数数量25*13]
#if JVET_O0090_ALF_CHROMA_FILTER_ALTERNATIVES_CTB
  short                        m_chromaClippFinal[MAX_NUM_ALF_ALTERNATIVES_CHROMA][MAX_NUM_ALF_CHROMA_COEFF];//最终色度嵌位值[色度种类][抽头位置]
#else
  short                        m_chromaClippFinal[MAX_NUM_ALF_LUMA_COEFF];
#endif
  int**                        m_laplacian[NUM_DIRECTIONS];//拉普拉斯活动性:三维数组[四种梯度方向][第i行][第j列]
  uint8_t*                     m_ctuEnableFlag[MAX_NUM_COMPONENT];//CTU是否使用ALF标志[通道数][CTU标志]
#if JVET_O0090_ALF_CHROMA_FILTER_ALTERNATIVES_CTB
  uint8_t*                     m_ctuAlternative[MAX_NUM_COMPONENT];//CTU是否哪种色度ALF[通道数][CTU标志]


  const EncCfg*          m_encCfg;//获取cfg
  AlfCovariance***       m_alfCovariance[MAX_NUM_COMPONENT];          //CTU级每一种情况的ALF协方差:四维数组[3个通道][1个形状][CTU位置][classIdx]
#if JVET_O0090_ALF_CHROMA_FILTER_ALTERNATIVES_CTB
  AlfCovariance**        m_alfCovarianceFrame[MAX_NUM_CHANNEL_TYPE];   //帧级每一种情况的ALF协方差:三维数组[3个通道][1个形状][25个亮度分类/8种色度滤波器],比上面少了个CTU位置索引
  uint8_t*               m_ctuEnableFlagTmp[MAX_NUM_COMPONENT];//临时存储亮度CTU是否滤波[通道索引][CTU索引]
  uint8_t*               m_ctuEnableFlagTmp2[MAX_NUM_COMPONENT];//临时存储亮度CTU是否滤波[通道索引][CTU索引]
  uint8_t*               m_ctuAlternativeTmp[MAX_NUM_COMPONENT];//临时存储色度CTU使用的滤波器种类[通道索引][CTU索引]
#else
  AlfCovariance**        m_alfCovarianceFrame[MAX_NUM_CHANNEL_TYPE];   // [CHANNEL][shapeIdx][classIdx]
  uint8_t*                 m_ctuEnableFlagTmp[MAX_NUM_COMPONENT];
#endif

  //for RDO
  AlfParam               m_alfParamTemp;//用于RDO的临时ALF参数!!!很有用
  ParameterSetMap<APS>*  m_apsMap;//获取APS(自适应参数集)映射表
  AlfCovariance          m_alfCovarianceMerged[ALF_NUM_OF_FILTER_TYPES][MAX_NUM_ALF_CLASSES + 2];//协方差矩阵[滤波器种类][分类]
  int                    m_alfClipMerged[ALF_NUM_OF_FILTER_TYPES][MAX_NUM_ALF_CLASSES][MAX_NUM_ALF_CLASSES][MAX_NUM_ALF_LUMA_COEFF];
  CABACWriter*           m_CABACEstimator;//CABAC
  CtxCache*              m_CtxCache;//上下文缓存
  double                 m_lambda[MAX_NUM_COMPONENT];//三个通道的lambda值

#if JVET_O0090_ALF_CHROMA_FILTER_ALTERNATIVES_CTB
  int**                  m_filterCoeffSet; // [lumaClassIdx/chromaAltIdx][coeffIdx] 最终最终滤波系数集
  int**                  m_filterClippSet; // [lumaClassIdx/chromaAltIdx][coeffIdx] 滤波幅值集
#else
  int**                  m_filterCoeffSet;
  int**                  m_filterClippSet;
#endif
  int**                  m_diffFilterCoeff;//不同滤波系数???
#if !JVET_O0216_ALF_COEFF_EG3 || !JVET_O0064_SIMP_ALF_CLIP_CODING
  int                    m_kMinTab[MAX_NUM_ALF_LUMA_COEFF];
  int                    m_bitsCoeffScan[m_MAX_SCAN_VAL][m_MAX_EXP_GOLOMB];
#endif
  short                  m_filterIndices[MAX_NUM_ALF_CLASSES][MAX_NUM_ALF_CLASSES];
  unsigned               m_bitsNewFilter[MAX_NUM_CHANNEL_TYPE];//新滤波器
  int                    m_apsIdStart;//起始APS序号
  double                 *m_ctbDistortionFixedFilter;//固定滤波器失真[]
  double                 *m_ctbDistortionUnfilter[MAX_NUM_COMPONENT];//不滤波的失真[]
  std::vector<short>     m_alfCtbFilterSetIndexTmp;//临时滤波器集索引[]
  AlfParam               m_alfParamTempNL;
  int                    m_clipDefaultEnc[MAX_NUM_ALF_LUMA_COEFF];
  int                    m_filterTmp[MAX_NUM_ALF_LUMA_COEFF];//临时滤波器系数值[抽头数]
  int                    m_clipTmp[MAX_NUM_ALF_LUMA_COEFF];//临时滤波器嵌位值[抽头数]

3 编码端代码框架

H.266/VVC代码学习40:VTM6.0中ALF的框架代码(ALFProcess)_第1张图片

4 解码端代码

void AdaptiveLoopFilter::ALFProcess(CodingStructure& cs)
{
  if (!cs.slice->getTileGroupAlfEnabledFlag(COMPONENT_Y) && !cs.slice->getTileGroupAlfEnabledFlag(COMPONENT_Cb) && !cs.slice->getTileGroupAlfEnabledFlag(COMPONENT_Cr))
  {
    return;
  }


  // set clipping range
  m_clpRngs = cs.slice->getClpRngs();//获取嵌位值

  // set CTU enable flags
  for( int compIdx = 0; compIdx < MAX_NUM_COMPONENT; compIdx++ )//获取CTU标志
  {
    m_ctuEnableFlag[compIdx] = cs.picture->getAlfCtuEnableFlag( compIdx );
#if JVET_O0090_ALF_CHROMA_FILTER_ALTERNATIVES_CTB
    m_ctuAlternative[compIdx] = cs.picture->getAlfCtuAlternativeData( compIdx );
#endif

  }
  //获取APS的系数
  reconstructCoeffAPSs(cs, true, cs.slice->getTileGroupAlfEnabledFlag(COMPONENT_Cb) || cs.slice->getTileGroupAlfEnabledFlag(COMPONENT_Cr), false);
  short* alfCtuFilterIndex = cs.slice->getPic()->getAlfCtbFilterIndex();

  PelUnitBuf recYuv = cs.getRecoBuf();//获取重构像素值
  m_tempBuf.copyFrom( recYuv );
  PelUnitBuf tmpYuv = m_tempBuf.getBuf( cs.area );//临时像素值:先存储重构像素值,后用于存储alf滤波后的
  tmpYuv.extendBorderPel( MAX_ALF_FILTER_LENGTH >> 1 );

  const PreCalcValues& pcv = *cs.pcv;//获取图像信息

  int ctuIdx = 0;//CTU索引
  bool clipTop = false, clipBottom = false, clipLeft = false, clipRight = false;
  int numHorVirBndry = 0, numVerVirBndry = 0;
  int horVirBndryPos[] = { 0, 0, 0 };
  int verVirBndryPos[] = { 0, 0, 0 };

  for( int yPos = 0; yPos < pcv.lumaHeight; yPos += pcv.maxCUHeight )
  {
    for( int xPos = 0; xPos < pcv.lumaWidth; xPos += pcv.maxCUWidth )//遍历每个128x128
    {
      const int width = ( xPos + pcv.maxCUWidth > pcv.lumaWidth ) ? ( pcv.lumaWidth - xPos ) : pcv.maxCUWidth;
      const int height = ( yPos + pcv.maxCUHeight > pcv.lumaHeight ) ? ( pcv.lumaHeight - yPos ) : pcv.maxCUHeight;

	  /**** 当前CTU是否使用ALF ****/
      bool ctuEnableFlag = m_ctuEnableFlag[COMPONENT_Y][ctuIdx];//亮度获取当前CTU的CTU是否使用标志
      for( int compIdx = 1; compIdx < MAX_NUM_COMPONENT; compIdx++ )//两个色度获取当前CTU的CTU使用何种ALF
      {
        ctuEnableFlag |= m_ctuEnableFlag[compIdx][ctuIdx] > 0;
      }

      if( ctuEnableFlag && isCrossedByVirtualBoundaries( xPos, yPos, width, height, clipTop, clipBottom, clipLeft, clipRight, numHorVirBndry, numVerVirBndry, horVirBndryPos, verVirBndryPos, cs.slice->getPPS() ) )
      {
        int yStart = yPos;
        for( int i = 0; i <= numHorVirBndry; i++ )
        {
          const int yEnd = i == numHorVirBndry ? yPos + height : horVirBndryPos[i];
          const int h = yEnd - yStart;
          const bool clipT = ( i == 0 && clipTop ) || ( i > 0 ) || ( yStart == 0 );
          const bool clipB = ( i == numHorVirBndry && clipBottom ) || ( i < numHorVirBndry ) || ( yEnd == pcv.lumaHeight );

          int xStart = xPos;
          for( int j = 0; j <= numVerVirBndry; j++ )
          {
            const int xEnd = j == numVerVirBndry ? xPos + width : verVirBndryPos[j];
            const int w = xEnd - xStart;
            const bool clipL = ( j == 0 && clipLeft ) || ( j > 0 ) || ( xStart == 0 );
            const bool clipR = ( j == numVerVirBndry && clipRight ) || ( j < numVerVirBndry ) || ( xEnd == pcv.lumaWidth );

            const int wBuf = w + (clipL ? 0 : MAX_ALF_PADDING_SIZE) + (clipR ? 0 : MAX_ALF_PADDING_SIZE);
            const int hBuf = h + (clipT ? 0 : MAX_ALF_PADDING_SIZE) + (clipB ? 0 : MAX_ALF_PADDING_SIZE);
            PelUnitBuf buf = m_tempBuf2.subBuf( UnitArea( cs.area.chromaFormat, Area( 0, 0, wBuf, hBuf ) ) );
            buf.copyFrom( tmpYuv.subBuf( UnitArea( cs.area.chromaFormat, Area( xStart - (clipL ? 0 : MAX_ALF_PADDING_SIZE), yStart - (clipT ? 0 : MAX_ALF_PADDING_SIZE), wBuf, hBuf ) ) ) );
            buf.extendBorderPel( MAX_ALF_PADDING_SIZE );
            buf = buf.subBuf( UnitArea ( cs.area.chromaFormat, Area( clipL ? 0 : MAX_ALF_PADDING_SIZE, clipT ? 0 : MAX_ALF_PADDING_SIZE, w, h ) ) );

            if( m_ctuEnableFlag[COMPONENT_Y][ctuIdx] )
            {
              const Area blkSrc( 0, 0, w, h );
              const Area blkDst( xStart, yStart, w, h );
              deriveClassification( m_classifier, buf.get(COMPONENT_Y), blkDst, blkSrc );
              const Area blkPCM( xStart, yStart, w, h );
              resetPCMBlkClassInfo( cs, m_classifier, buf.get(COMPONENT_Y), blkPCM );
              short filterSetIndex = alfCtuFilterIndex[ctuIdx];
              short *coeff;
              short *clip;
              if (filterSetIndex >= NUM_FIXED_FILTER_SETS)
              {
                coeff = m_coeffApsLuma[filterSetIndex - NUM_FIXED_FILTER_SETS];
                clip = m_clippApsLuma[filterSetIndex - NUM_FIXED_FILTER_SETS];
              }
              else
              {
                coeff = m_fixedFilterSetCoeffDec[filterSetIndex];
                clip = m_clipDefault;
              }
              m_filter7x7Blk(m_classifier, recYuv, buf, blkDst, blkSrc, COMPONENT_Y, coeff, clip, m_clpRngs.comp[COMPONENT_Y], cs
                , m_alfVBLumaCTUHeight
                , ((yPos + pcv.maxCUHeight >= pcv.lumaHeight) ? pcv.lumaHeight : m_alfVBLumaPos)
              );
            }

            for( int compIdx = 1; compIdx < MAX_NUM_COMPONENT; compIdx++ )
            {
              ComponentID compID = ComponentID( compIdx );
              const int chromaScaleX = getComponentScaleX( compID, tmpYuv.chromaFormat );
              const int chromaScaleY = getComponentScaleY( compID, tmpYuv.chromaFormat );

              if( m_ctuEnableFlag[compIdx][ctuIdx] )
              {
                const Area blkSrc( 0, 0, w >> chromaScaleX, h >> chromaScaleY );
                const Area blkDst( xStart >> chromaScaleX, yStart >> chromaScaleY, w >> chromaScaleX, h >> chromaScaleY );
#if JVET_O0090_ALF_CHROMA_FILTER_ALTERNATIVES_CTB
                uint8_t alt_num = m_ctuAlternative[compIdx][ctuIdx];
                m_filter5x5Blk(m_classifier, recYuv, buf, blkDst, blkSrc, compID, m_chromaCoeffFinal[alt_num], m_chromaClippFinal[alt_num], m_clpRngs.comp[compIdx], cs
#else
                m_filter5x5Blk(m_classifier, recYuv, buf, blkDst, blkSrc, compID, m_chromaCoeffFinal, m_chromaClippFinal, m_clpRngs.comp[compIdx], cs
#endif
                  , m_alfVBChmaCTUHeight
                  , ((yPos + pcv.maxCUHeight >= pcv.lumaHeight) ? pcv.lumaHeight : m_alfVBChmaPos));
              }
            }

            xStart = xEnd;
          }

          yStart = yEnd;
        }
      }
      else
      {
	  /**** 亮度ALF滤波 ****/
      const UnitArea area( cs.area.chromaFormat, Area( xPos, yPos, width, height ) );
      if( m_ctuEnableFlag[COMPONENT_Y][ctuIdx] )
      {
        Area blk( xPos, yPos, width, height );
        deriveClassification( m_classifier, tmpYuv.get( COMPONENT_Y ), blk, blk );//获取分类
        Area blkPCM(xPos, yPos, width, height);
        resetPCMBlkClassInfo(cs, m_classifier, tmpYuv.get(COMPONENT_Y), blkPCM);//没有任何操作
        short filterSetIndex = alfCtuFilterIndex[ctuIdx];//当前CTU所使用的滤波器集合
        short *coeff;
        short *clip;
        if (filterSetIndex >= NUM_FIXED_FILTER_SETS)//如果使用的是APS滤波器,则filterSetIndex一定大于等于16
        {
          coeff = m_coeffApsLuma[filterSetIndex - NUM_FIXED_FILTER_SETS];
          clip = m_clippApsLuma[filterSetIndex - NUM_FIXED_FILTER_SETS];
        }
        else//使用的是固定滤波器
        {
          coeff = m_fixedFilterSetCoeffDec[filterSetIndex];
          clip = m_clipDefault;
        }
		//进行滤波
        m_filter7x7Blk(m_classifier, recYuv, tmpYuv, blk, blk, COMPONENT_Y, coeff, clip, m_clpRngs.comp[COMPONENT_Y], cs
          , m_alfVBLumaCTUHeight
          , ((yPos + pcv.maxCUHeight >= pcv.lumaHeight) ? pcv.lumaHeight : m_alfVBLumaPos)
        );
      }

	  /**** 色度ALF滤波 ****/
      for( int compIdx = 1; compIdx < MAX_NUM_COMPONENT; compIdx++ )
      {
        ComponentID compID = ComponentID( compIdx );
        const int chromaScaleX = getComponentScaleX( compID, tmpYuv.chromaFormat );
        const int chromaScaleY = getComponentScaleY( compID, tmpYuv.chromaFormat );

        if( m_ctuEnableFlag[compIdx][ctuIdx] )
        {
          Area blk( xPos >> chromaScaleX, yPos >> chromaScaleY, width >> chromaScaleX, height >> chromaScaleY );
#if JVET_O0090_ALF_CHROMA_FILTER_ALTERNATIVES_CTB
          uint8_t alt_num = m_ctuAlternative[compIdx][ctuIdx];
          m_filter5x5Blk(m_classifier, recYuv, tmpYuv, blk, blk, compID, m_chromaCoeffFinal[alt_num], m_chromaClippFinal[alt_num], m_clpRngs.comp[compIdx], cs
#else
          m_filter5x5Blk(m_classifier, recYuv, tmpYuv, blk, blk, compID, m_chromaCoeffFinal, m_chromaClippFinal, m_clpRngs.comp[compIdx], cs
#endif
            , m_alfVBChmaCTUHeight
            , ((yPos + pcv.maxCUHeight >= pcv.lumaHeight) ? pcv.lumaHeight : m_alfVBChmaPos));
        }
      }
      }
      ctuIdx++;//下一个CTU
    }
  }
}

void AdaptiveLoopFilter::reconstructCoeffAPSs(CodingStructure& cs, bool luma, bool chroma, bool isRdo)
{
  //luma
  APS** aps = cs.slice->getAlfAPSs();
  AlfParam alfParamTmp;
  APS* curAPS;
  if (luma)
  {
    for (int i = 0; i < cs.slice->getTileGroupNumAps(); i++)
    {
      int apsIdx = cs.slice->getTileGroupApsIdLuma()[i];//获取亮度的APS索引(索引为0~7????)
      curAPS = aps[apsIdx];//得到当前APS信息
      CHECK(curAPS == NULL, "invalid APS");
      alfParamTmp = curAPS->getAlfAPSParam();
      reconstructCoeff(alfParamTmp, CHANNEL_TYPE_LUMA, isRdo, true);//根据APS获得系数,存进m_coeffFinal
      memcpy(m_coeffApsLuma[i], m_coeffFinal, sizeof(m_coeffFinal));//把325个m_coeffFinal的值存进m_coeffApsLuma[i]
      memcpy(m_clippApsLuma[i], m_clippFinal, sizeof(m_clippFinal));
    }
  }

  //chroma
  if (chroma)
  {
    int apsIdxChroma = cs.slice->getTileGroupApsIdChroma();
    curAPS = aps[apsIdxChroma];
#if JVET_O0090_ALF_CHROMA_FILTER_ALTERNATIVES_CTB
    m_alfParamChroma = &curAPS->getAlfAPSParam();
    alfParamTmp = *m_alfParamChroma;
#else
    alfParamTmp = curAPS->getAlfAPSParam();
#endif
    reconstructCoeff(alfParamTmp, CHANNEL_TYPE_CHROMA, isRdo, true);
  }
}

void AdaptiveLoopFilter::reconstructCoeff( AlfParam& alfParam, ChannelType channel, const bool isRdo, const bool isRedo )
{
	/********************** 初始化 **********************/
  int factor = isRdo ? 0 : (1 << (m_NUM_BITS - 1));//中间位置的值:0
  AlfFilterType filterType = isLuma( channel ) ? ALF_FILTER_7 : ALF_FILTER_5;
  int numClasses = isLuma( channel ) ? MAX_NUM_ALF_CLASSES : 1;//滤波种类数量
  int numCoeff = filterType == ALF_FILTER_5 ? 7 : 13;//滤波系数数量
  int numCoeffMinus1 = numCoeff - 1;
#if !JVET_O0090_ALF_CHROMA_FILTER_ALTERNATIVES_CTB
  int numFilters = isLuma( channel ) ? alfParam.numLumaFilters : 1;
  short* coeff = isLuma( channel ) ? alfParam.lumaCoeff : alfParam.chromaCoeff;
  short* clipp = isLuma( channel ) ? alfParam.lumaClipp : alfParam.chromaClipp;
#endif
#if JVET_O0090_ALF_CHROMA_FILTER_ALTERNATIVES_CTB
  const int numAlts = isLuma( channel ) ? 1 : alfParam.numAlternativesChroma;//亮度1次,色度遍历4次

  for( int altIdx = 0; altIdx < numAlts; ++ altIdx )
  {
    int numFilters = isLuma( channel ) ? alfParam.numLumaFilters : 1;//亮度为6,色度为1
    short* coeff = isLuma( channel ) ? alfParam.lumaCoeff : alfParam.chromaCoeff[altIdx];//获取指针指向alfParam系数
    short* clipp = isLuma( channel ) ? alfParam.lumaClipp : alfParam.chromaClipp[altIdx];//亮度拉成了一维:325位 = 25类 X 13抽头 
																						 //色度依然是二维:325位 =  4类 X 7抽头 
#if !JVET_O0669_REMOVE_ALF_COEFF_PRED
    if( alfParam.alfLumaCoeffDeltaPredictionFlag && isLuma( channel ) )
    {
      for( int i = 1; i < numFilters; i++ )
      {
        for( int j = 0; j < numCoeffMinus1; j++ )
        {
          coeff[i * MAX_NUM_ALF_LUMA_COEFF + j] += coeff[( i - 1 ) * MAX_NUM_ALF_LUMA_COEFF + j];
        }
      }
    }

#endif
	/*********** 设置最中间的系数 **********/
    for( int filterIdx = 0; filterIdx < numFilters; filterIdx++ )
    {
      coeff[filterIdx* MAX_NUM_ALF_LUMA_COEFF + numCoeffMinus1] = factor;//处理最中间的系数,设为128
    }

	/************** 对色度:直接获取系数和嵌位值 **************/
    if( isChroma( channel ) )
    {
      for( int coeffIdx = 0; coeffIdx < numCoeffMinus1; ++coeffIdx )
      {
        m_chromaCoeffFinal[altIdx][coeffIdx] = coeff[coeffIdx];
        int clipIdx = alfParam.nonLinearFlag[channel][altIdx] ? clipp[coeffIdx] : 0;
        m_chromaClippFinal[altIdx][coeffIdx] = isRdo ? clipIdx : m_alfClippingValues[channel][clipIdx];
      }
      m_chromaCoeffFinal[altIdx][numCoeffMinus1] = factor;
      m_chromaClippFinal[altIdx][numCoeffMinus1] = isRdo ? 0 : m_alfClippingValues[channel][0];
      continue;
    }
	/************** 对亮度:直接获取系数和嵌位值 *************/
    for( int classIdx = 0; classIdx < numClasses; classIdx++ )//遍历0~25的每一个种类
    {
      int filterIdx = alfParam.filterCoeffDeltaIdx[classIdx];
#if !JVET_O0669_REMOVE_ALF_COEFF_PRED
      int fixedFilterIdx = alfParam.fixedFilterSetIndex;
      if (fixedFilterIdx > 0 && alfParam.fixedFilterIdx[classIdx] > 0)
      {
        fixedFilterIdx = m_classToFilterMapping[fixedFilterIdx - 1][classIdx];
      }
      else
      {
        fixedFilterIdx = -1;
      }
#endif
	  /*对系数的获取*/
      for (int coeffIdx = 0; coeffIdx < numCoeffMinus1; ++coeffIdx)//遍历12个系数
      {
        m_coeffFinal[classIdx * MAX_NUM_ALF_LUMA_COEFF + coeffIdx] = coeff[filterIdx * MAX_NUM_ALF_LUMA_COEFF + coeffIdx];//把系数填进去
#if !JVET_O0669_REMOVE_ALF_COEFF_PRED
        //fixed filter
        if (fixedFilterIdx >= 0)
        {
          m_coeffFinal[classIdx * MAX_NUM_ALF_LUMA_COEFF + coeffIdx] += m_fixedFilterSetCoeff[fixedFilterIdx][coeffIdx];
        }
#endif
      }
      m_coeffFinal[classIdx* MAX_NUM_ALF_LUMA_COEFF + numCoeffMinus1] = factor;//赋值最中间的第13个滤波系数为128

	  /*对限幅值的获取*/
      m_clippFinal[classIdx* MAX_NUM_ALF_LUMA_COEFF + numCoeffMinus1] = isRdo ? 0 : m_alfClippingValues[channel][0];//最中间位置的限幅值
      for( int coeffIdx = 0; coeffIdx < numCoeffMinus1; ++coeffIdx )//遍历12个限幅值
      {
        int clipIdx = alfParam.nonLinearFlag[channel][altIdx] ? (clipp + filterIdx * MAX_NUM_ALF_LUMA_COEFF)[coeffIdx] : 0;
        (m_clippFinal + classIdx * MAX_NUM_ALF_LUMA_COEFF)[coeffIdx] = isRdo ? clipIdx : m_alfClippingValues[channel][clipIdx];
      }
      m_clippFinal[classIdx* MAX_NUM_ALF_LUMA_COEFF + numCoeffMinus1] =
        isRdo ? 0 :
        m_alfClippingValues[channel][0];//赋值最中间的第13个限幅值
    }
  }
#if !JVET_O0669_REMOVE_ALF_COEFF_PRED

  if( isChroma( channel ) )
    return;

  if( isRedo && alfParam.alfLumaCoeffDeltaPredictionFlag )
  {
    int numFilters = alfParam.numLumaFilters;
    short* coeff = alfParam.lumaCoeff;

    for( int i = numFilters - 1; i > 0; i-- )
    {
      for( int j = 0; j < numCoeffMinus1; j++ )
      {
        coeff[i * MAX_NUM_ALF_LUMA_COEFF + j] = coeff[i * MAX_NUM_ALF_LUMA_COEFF + j] - coeff[( i - 1 ) * MAX_NUM_ALF_LUMA_COEFF + j];
      }
    }
  }
#endif
#else

#if !JVET_O0669_REMOVE_ALF_COEFF_PRED
  if( alfParam.alfLumaCoeffDeltaPredictionFlag && isLuma( channel ) )
  {
    for( int i = 1; i < numFilters; i++ )
    {
      for( int j = 0; j < numCoeffMinus1; j++ )
      {
        coeff[i * MAX_NUM_ALF_LUMA_COEFF + j] += coeff[( i - 1 ) * MAX_NUM_ALF_LUMA_COEFF + j];
      }
    }
  }
#endif

  for( int filterIdx = 0; filterIdx < numFilters; filterIdx++ )
  {
    coeff[filterIdx* MAX_NUM_ALF_LUMA_COEFF + numCoeffMinus1] = factor;
  }

  if( isChroma( channel ) )
  {
    for( int coeffIdx = 0; coeffIdx < numCoeffMinus1; ++coeffIdx )
    {
      m_chromaCoeffFinal[coeffIdx] = alfParam.chromaCoeff[coeffIdx];
      int clipIdx = alfParam.nonLinearFlag[channel] ? clipp[coeffIdx] : 0;
      m_chromaClippFinal[coeffIdx] = isRdo ? clipIdx : m_alfClippingValues[channel][clipIdx];
    }
    m_chromaCoeffFinal[numCoeffMinus1] = factor;
    m_chromaClippFinal[numCoeffMinus1] = isRdo ? 0 : m_alfClippingValues[channel][0];

    return;
  }

  for( int classIdx = 0; classIdx < numClasses; classIdx++ )
  {
    int filterIdx = alfParam.filterCoeffDeltaIdx[classIdx];
#if !JVET_O0669_REMOVE_ALF_COEFF_PRED
    int fixedFilterIdx = alfParam.fixedFilterSetIndex;
    if (fixedFilterIdx > 0 && alfParam.fixedFilterIdx[classIdx] > 0)
    {
      fixedFilterIdx = m_classToFilterMapping[fixedFilterIdx - 1][classIdx];
    }
    else
    {
      fixedFilterIdx = -1;
    }
#endif
    for (int coeffIdx = 0; coeffIdx < numCoeffMinus1; ++coeffIdx)
    {
      m_coeffFinal[classIdx * MAX_NUM_ALF_LUMA_COEFF + coeffIdx] = coeff[filterIdx * MAX_NUM_ALF_LUMA_COEFF + coeffIdx];
#if !JVET_O0669_REMOVE_ALF_COEFF_PRED
      //fixed filter
      if (fixedFilterIdx >= 0)
      {
        m_coeffFinal[classIdx * MAX_NUM_ALF_LUMA_COEFF + coeffIdx] += m_fixedFilterSetCoeff[fixedFilterIdx][coeffIdx];
      }
#endif
    }
    m_coeffFinal[classIdx* MAX_NUM_ALF_LUMA_COEFF + numCoeffMinus1] = factor;
    m_clippFinal[classIdx* MAX_NUM_ALF_LUMA_COEFF + numCoeffMinus1] = isRdo ? 0 : m_alfClippingValues[channel][0];
    for( int coeffIdx = 0; coeffIdx < numCoeffMinus1; ++coeffIdx )
    {
      int clipIdx = alfParam.nonLinearFlag[channel] ? (clipp + filterIdx * MAX_NUM_ALF_LUMA_COEFF)[coeffIdx] : 0;
      (m_clippFinal + classIdx * MAX_NUM_ALF_LUMA_COEFF)[coeffIdx] = isRdo ? clipIdx : m_alfClippingValues[channel][clipIdx];
    }
  }

#if !JVET_O0669_REMOVE_ALF_COEFF_PRED
  if(isRedo && alfParam.alfLumaCoeffDeltaPredictionFlag )
  {
    for( int i = numFilters - 1; i > 0; i-- )
    {
      for( int j = 0; j < numCoeffMinus1; j++ )
      {
        coeff[i * MAX_NUM_ALF_LUMA_COEFF + j] = coeff[i * MAX_NUM_ALF_LUMA_COEFF + j] - coeff[( i - 1 ) * MAX_NUM_ALF_LUMA_COEFF + j];
      }
    }
  }
#endif
#endif
}

你可能感兴趣的:(H.266/VVC视频编码)