VVC/JEM代码学习8:predIntraAng

     (个人理解)

    predIntraAng()主要完成65种角度模式(外加DC和planar模式)的预测,预测之前还要对参考像素进行相应的滤波操作。

Void TComPrediction::predIntraAng( const ComponentID compID, UInt uiDirMode, Pel* piOrg /* Will be null for decoding */, UInt uiOrgStride, Pel* piPred, UInt uiStride, TComTU &rTu, const Bool bUseFilteredPredSamples, const Bool bUseLosslessDPCM )

{
  const ChannelType    channelType = toChannelType(compID);
  const TComRectangle &rect        = rTu.getRect(isLuma(compID) ? COMPONENT_Y : COMPONENT_Cb);
  const Int            iWidth      = rect.width;
  const Int            iHeight     = rect.height;

#if JVET_C0024_QTBT
  assert( g_aucConvertToBit[ iWidth ] >= -1 );  //2x2
  assert( g_aucConvertToBit[ iWidth ] <= MAX_CU_DEPTH - MIN_CU_LOG2 ); 

 Pel *pDst = piPred;

  // get starting pixel in block
#if JVET_C0024_QTBT
  const Int sw = (iHeight + iWidth + 1);
#else
  const Int sw = (2 * iWidth + 1);
#endif
#if COM16_C1046_PDPC_INTRA
  TComDataCU *const pcCU = rTu.getCU();
  const UInt uiAbsPartIdx = rTu.GetAbsPartIdxTU();
#endif

if ( bUseLosslessDPCM )//使用无损DPCM,默认关闭;
  {
    const Pel *ptrSrc = getPredictorPtr( compID, false );
    // Sample Adaptive intra-Prediction (SAP)
    if (uiDirMode==HOR_IDX)//水平模式;
    {
      // left column filled with reference samples
      // remaining columns filled with piOrg data (if available).
      for(Int y=0; y<iHeight; y++)
      {
        piPred[y*uiStride+0] = ptrSrc[(y+1)*sw];//当前块第一列的预测值用参考采样进行填充;
      }
      if (piOrg!=0)
      {
        piPred+=1; // miss off first column
        for(Int y=0; y<iHeight; y++, piPred+=uiStride, piOrg+=uiOrgStride)
        {
          memcpy(piPred, piOrg, (iWidth-1)*sizeof(Pel));//剩余列用piOrg指向的数据进行填充;
        }
      }
    }
    else // VER_IDX
    {
      // top row filled with reference samples
      // remaining rows filled with piOrd data (if available)
      for(Int x=0; x<iWidth; x++)
      {
        piPred[x] = ptrSrc[x+1];
      }
      if (piOrg!=0)
      {
        piPred+=uiStride; // miss off the first row
        for(Int y=1; y<iHeight; y++, piPred+=uiStride, piOrg+=uiOrgStride)
        {
          memcpy(piPred, piOrg, iWidth*sizeof(Pel));
        }
      }
    }
  }
  else
  {
#if COM16_C1046_PDPC_INTRA
#if !COM16_C1046_PDPC_RSAF_HARMONIZATION
    Pel *ptrSrc = getPredictorPtr(compID, false);//指向的是当前块的参考数据(左上角),即p[-1][-1];
#endif
#if JVET_G0104_PLANAR_PDPC
    if( uiDirMode == PLANAR_IDX )//如果是planar模式;

#if COM16_C1046_PDPC_RSAF_HARMONIZATION 

      Pel *ptrSrc = getPredictorPtr(compID, false);
#endif
#if JVET_C0024_QTBT
      const Int iSrcStride = iWidth + iHeight + 1;//129;
      const Int iDoubleSize = iWidth + iHeight;//128;
#else
      const Int iBlkSize = iWidth;
      const Int iSrcStride = (iWidth<<1) + 1;
      const Int iDoubleWidth = iWidth<<1;
#endif

#if JVET_G0104_PLANAR_PDPC
      const Int blkSizeGroup[2] = { std::min( 4, 1 + (Int)g_aucConvertToBit[iWidth] ), std::min( 4, 1 + (Int)g_aucConvertToBit[iHeight] ) };
      const Short *pdpcParam[2] = { g_pdpcParam[blkSizeGroup[0]], g_pdpcParam[blkSizeGroup[1]] };
      const Short *pPdpcPar = pdpcParam[iWidth < iHeight];

#if JVET_C0024_QTBT
      Int * piRefVector = piTempRef + iDoubleSize;
      Int * piLowpRefer = piFiltRef + iDoubleSize;
#else
      Int * piRefVector = piTempRef + iDoubleWidth;
      Int * piLowpRefer = piFiltRef + iDoubleWidth;
#endif

      //unfiltered reference
#if JVET_C0024_QTBT
      for (Int j = 0; j <= iDoubleSize; j++)
        piRefVector[j] = ptrSrc[j];

      for (Int i = 1; i <= iDoubleSize; i++)
        piRefVector[-i] = ptrSrc[i*iSrcStride];
#else
      for (Int j = 0; j <= iDoubleWidth; j++)
        piRefVector[j] = ptrSrc[j];

      for (Int i = 1; i <= iDoubleWidth; i++)
        piRefVector[-i] = ptrSrc[i*iSrcStride];
#endif

      if (pPdpcPar[5] != 0) 
      { // filter reference samples
#if JVET_C0024_QTBT
        xReferenceFilter(iDoubleSize, pPdpcPar[4], pPdpcPar[5], piRefVector, piLowpRefer);
        for (Int j = 0; j <= iDoubleSize; j++)
          ptrSrc[j] = piLowpRefer[j];
        for (Int i = 1; i <= iDoubleSize; i++)
          ptrSrc[i*iSrcStride] = piLowpRefer[-i];
#else
        xReferenceFilter(iBlkSize, pPdpcPar[4], pPdpcPar[5], piRefVector, piLowpRefer);
        for (Int j = 0; j <= iDoubleWidth; j++)
          ptrSrc[j] = piLowpRefer[j];
        for (Int i = 1; i <= iDoubleWidth; i++)
          ptrSrc[i*iSrcStride] = piLowpRefer[-i];
#endif
      }

      if (uiDirMode == PLANAR_IDX)//若是planar模式,利用对应的计算预测值的公式计算预测值;
        xPredIntraPlanar(ptrSrc + sw + 1, sw, pDst, uiStride, iWidth, iHeight);//ptrSrc + sw + 1,指向当前CU首地址;
      else//不是planar模式;
      {
        const Bool            enableEdgeFilters = !(pcCU->isRDPCMEnabled(uiAbsPartIdx) && pcCU->getCUTransquantBypass(uiAbsPartIdx));
#if O0043_BEST_EFFORT_DECODING
        const Int channelsBitDepthForPrediction = rTu.getCU()->getSlice()->getSPS()->getStreamBitDepth(channelType);
#else
        const Int channelsBitDepthForPrediction = rTu.getCU()->getSlice()->getSPS()->getBitDepth(channelType);
#endif
#if VCEG_AZ07_INTRA_4TAP_FILTER
        const Bool             enable4TapFilter = pcCU->getSlice()->getSPS()->getUseIntra4TapFilter();
#endif
//对DC模式和所有角度模式进行预测;
                xPredIntraAng(channelsBitDepthForPrediction, ptrSrc + sw + 1, sw, pDst, uiStride,
                              iWidth, iHeight,
#if JVET_D0033_ADAPTIVE_CLIPPING
                              compID,
              #else
                              channelType,
              #endif
                              uiDirMode, enableEdgeFilters
#if VCEG_AZ07_INTRA_4TAP_FILTER
          , enable4TapFilter
#endif
          );
      }
  //使用未参考采样用于加权预测,就是JEM里的PDPC;
      //use unfiltered reference sample for weighted prediction
      if (pPdpcPar[5] != 0) 
      {
#if JVET_C0024_QTBT
        for (int j = 0; j <= iDoubleSize; j++)
          ptrSrc[j] = piRefVector[j];

        for (int i = 1; i <= iDoubleSize; i++)
          ptrSrc[i*iSrcStride] = piRefVector[-i];
#else
        for (int j = 0; j <= iDoubleWidth; j++)
          ptrSrc[j] = piRefVector[j];

        for (int i = 1; i <= iDoubleWidth; i++)
          ptrSrc[i*iSrcStride] = piRefVector[-i];
#endif
      }

#if JVET_C0024_QTBT
      Int scale = g_aucConvertToBit[iWidth] + MIN_CU_LOG2 + g_aucConvertToBit[iHeight] + MIN_CU_LOG2 < 10 ? 0: 1;
#else
      Int scale = (iBlkSize < 32 ? 0 : 1);
#endif
#if !JVET_D0033_ADAPTIVE_CLIPPING
      Int bitDepth = rTu.getCU()->getSlice()->getSPS()->getBitDepth(channelType);
#endif
      Int ParShift = 6; //normalization factor
      Int ParScale = 1 << ParShift;//64;
      Int ParOffset = 1 << (ParShift - 1);//32;

#if JVET_C0024_QTBT
      for (Int row = 0; row < iHeight; row++) 
#else
      for (Int row = 0; row < iBlkSize; row++) 
#endif
      {
        Int pos          = row * uiStride;
        Int shiftRow     = row >> scale;
#if JVET_C0024_QTBT
        Int Coeff_Top    = pdpcParam[1][2] >> shiftRow;
        Int Coeff_offset = pdpcParam[1][3] >> shiftRow;
#else
        Int Coeff_Top    = pPdpcPar[2] >> shiftRow;
        Int Coeff_offset = pPdpcPar[3] >> shiftRow;
#endif

#if JVET_C0024_QTBT
        for (Int col = 0; col < iWidth; col++, pos++) 
#else
        for (Int col = 0; col < iBlkSize; col++, pos++) 
#endif
        {
          Int shiftCol      = col >> scale;
#if JVET_C0024_QTBT
          Int Coeff_Left    = pdpcParam[0][0] >> shiftCol;
          Int Coeff_TopLeft = (pdpcParam[0][1] >> shiftCol) + Coeff_offset;
#else
          Int Coeff_Left    = pPdpcPar[0] >> shiftCol;
          Int Coeff_TopLeft = (pPdpcPar[1] >> shiftCol) + Coeff_offset;
#endif
          Int Coeff_Cur     = ParScale - Coeff_Left - Coeff_Top + Coeff_TopLeft;

          Int sampleVal = (Coeff_Left* piRefVector[-row - 1] + Coeff_Top * piRefVector[col + 1] - Coeff_TopLeft * piRefVector[0] + Coeff_Cur * pDst[pos] + ParOffset) >> ParShift;
#if JVET_D0033_ADAPTIVE_CLIPPING
          pDst[pos] = ClipA(sampleVal,compID);
#else
          pDst[pos] = Clip3(0, ((1 << bitDepth) - 1), sampleVal);
#endif
        }
      }
      return; //terminate the prediction process
    }
#else
    const Pel *ptrSrc = getPredictorPtr( compID, bUseFilteredPredSamples );
#endif

#if JVET_G0104_PLANAR_PDPC
    if( isLuma( compID ) )
    {
      if( pcCU->getROTIdx( CHANNEL_TYPE_LUMA, uiAbsPartIdx ) )
      {
        ptrSrc = getPredictorPtr( compID, bUseFilteredPredSamples );
      }
    }
#elif COM16_C1046_PDPC_RSAF_HARMONIZATION
    const Pel *ptrSrc = getPredictorPtr(compID, bUseFilteredPredSamples);
#endif
#if VCEG_AZ05_INTRA_MPI
    TComDataCU *const pcCU = rTu.getCU();
    const UInt              uiAbsPartIdx = rTu.GetAbsPartIdxTU();
#endif
    if ( uiDirMode == PLANAR_IDX )
    {
      xPredIntraPlanar( ptrSrc+sw+1, sw, pDst, uiStride, iWidth, iHeight );
    }
    else
    {
      // Create the prediction
#if !VCEG_AZ05_INTRA_MPI && !COM16_C1046_PDPC_INTRA
      TComDataCU *const pcCU = rTu.getCU();
      const UInt              uiAbsPartIdx      = rTu.GetAbsPartIdxTU();
#endif//是否进行边缘滤波的标记;
      const Bool              enableEdgeFilters = !(pcCU->isRDPCMEnabled(uiAbsPartIdx) && pcCU->getCUTransquantBypass(uiAbsPartIdx));
#if O0043_BEST_EFFORT_DECODING
      const Int channelsBitDepthForPrediction = rTu.getCU()->getSlice()->getSPS()->getStreamBitDepth(channelType);
#else
      const Int channelsBitDepthForPrediction = rTu.getCU()->getSlice()->getSPS()->getBitDepth(channelType);
#endif
#if VCEG_AZ07_INTRA_4TAP_FILTER//JEM中新加的4抽头滤波;
      const Bool              enable4TapFilter     = pcCU->getSlice()->getSPS()->getUseIntra4TapFilter();
#endif

#if VCEG_AZ07_INTRA_BOUNDARY_FILTER

#if COM16_C983_RSAF_PREVENT_OVERSMOOTHING
#if VCEG_AZ05_INTRA_MPI
      const Bool              enableBoundaryFilter = pcCU->getSlice()->getSPS()->getUseIntraBoundaryFilter() && (pcCU->getMPIIdx(uiAbsPartIdx) <= 1 || pcCU->getWidth(uiAbsPartIdx)>=16 || !pcCU->getSlice()->getSPS()->getUseRSAF() );
#else
#if COM16_C1046_PDPC_INTRA
      const Bool              enableBoundaryFilter = pcCU->getSlice()->getSPS()->getUseIntraBoundaryFilter() && (pcCU->getPDPCIdx(uiAbsPartIdx) <= 1 || pcCU->getWidth(uiAbsPartIdx) >= 16 || !pcCU->getSlice()->getSPS()->getUseRSAF());
#else
      const Bool              enableBoundaryFilter = pcCU->getSlice()->getSPS()->getUseIntraBoundaryFilter() && (pcCU->getWidth(uiAbsPartIdx) >= 16 || !pcCU->getSlice()->getSPS()->getUseRSAF());
#endif
#endif
#else//是否进行边界滤波的标记,这里的边界指的是当前块的边界,不是参考像素的边界;
      const Bool              enableBoundaryFilter = pcCU->getSlice()->getSPS()->getUseIntraBoundaryFilter();
#endif

#endif
        xPredIntraAng( channelsBitDepthForPrediction, ptrSrc+sw+1, sw, pDst, uiStride, iWidth, iHeight,
#if JVET_D0033_ADAPTIVE_CLIPPING
             compID,
#else
             channelType,
#endif
        uiDirMode, enableEdgeFilters
#if VCEG_AZ07_INTRA_4TAP_FILTER
        , enable4TapFilter
#endif
#if COM16_C983_RSAF_PREVENT_OVERSMOOTHING
        , pcCU->getSlice()->getSPS()->getUseRSAF()
#endif
        );

#if VCEG_AZ05_INTRA_MPI
#if JVET_C0024_QTBT
      if (!(pcCU->getMPIIdx(uiAbsPartIdx) && isLuma(compID)) && (uiDirMode == DC_IDX))
#else
      if (!pcCU->getMPIIdx(uiAbsPartIdx) && (uiDirMode == DC_IDX))
#endif
#else
      if ( uiDirMode == DC_IDX )//如果是DC模式.
#endif
      {
        xDCPredFiltering( ptrSrc+sw+1, sw, pDst, uiStride, iWidth, iHeight, channelType );
      }
#if VCEG_AZ07_INTRA_BOUNDARY_FILTER
#if JVET_C0024_QTBT
      else if( enableBoundaryFilter && isLuma(compID) && iWidth>2 && iHeight>2)
#else
      else if( enableBoundaryFilter && isLuma(compID) )
#endif
      {
#if VCEG_AZ07_INTRA_65ANG_MODES
        if( uiDirMode == VDIA_IDX )
#else
        if( uiDirMode == 34 )
#endif
        {//对模式34进行预测滤波;
          xIntraPredFilteringMode34( ptrSrc+sw+1, sw, pDst, uiStride, iWidth, iHeight);
        }
        else  if( uiDirMode == 2 )
        {//对模式02进行预测滤波;
          xIntraPredFilteringMode02( ptrSrc+sw+1, sw, pDst, uiStride, iWidth, iHeight);
        }
#if VCEG_AZ07_INTRA_65ANG_MODES
        else if( ( uiDirMode<=10 && uiDirMode>2 ) || ( uiDirMode>=(VDIA_IDX-8) && uiDirMode<VDIA_IDX ) )
#else
        else if( ( uiDirMode<=6 && uiDirMode>2 ) || ( uiDirMode>=30 && uiDirMode<34 ) )
#endif
        {//对2<mode<10和58<mode<66的模式进行滤波;
          xIntraPredFilteringModeDGL( ptrSrc+sw+1, sw, pDst, uiStride, iWidth, iHeight, uiDirMode );
        }
      }
#endif
    }

 }


}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值