VVC/JEM代码学习27:xIntraRecBlk

Void
TDecCu::xIntraRecBlk(       TComYuv*    pcRecoYuv,
                            TComYuv*    pcPredYuv,
                            TComYuv*    pcResiYuv,
                      const ComponentID compID,
                            TComTU     &rTu)
{
  if (!rTu.ProcessComponentSection(compID))
  {
    return;
  }
  const Bool       bIsLuma = isLuma(compID);


  TComDataCU *pcCU = rTu.getCU();
#if COM16_C983_RSAF || !JVET_D0033_ADAPTIVE_CLIPPING
  const TComSPS &sps=*(pcCU->getSlice()->getSPS());
#endif
  const UInt uiAbsPartIdx=rTu.GetAbsPartIdxTU();

  const TComRectangle &tuRect  =rTu.getRect(compID);
  const UInt uiWidth           = tuRect.width;
  const UInt uiHeight          = tuRect.height;
  const UInt uiStride          = pcRecoYuv->getStride (compID);
        Pel* piPred            = pcPredYuv->getAddr( compID, uiAbsPartIdx );
  const ChromaFormat chFmt     = rTu.GetChromaFormat();

#if !JVET_C0024_QTBT
  if (uiWidth != uiHeight)
  {
    //------------------------------------------------

    //split at current level if dividing into square sub-TUs

    TComTURecurse subTURecurse(rTu, false, TComTU::VERTICAL_SPLIT, true, compID);

    //recurse further
    do
    {
      xIntraRecBlk(pcRecoYuv, pcPredYuv, pcResiYuv, compID, subTURecurse);
    } while (subTURecurse.nextSection(rTu));

    //------------------------------------------------

    return;
  }
#endif

  const UInt uiChPredMode  = pcCU->getIntraDir( toChannelType(compID), uiAbsPartIdx );//得到预测模式;
#if JVET_C0024_QTBT
#if JVET_E0062_MULTI_DMS
  const UInt uiChCodedMode = uiChPredMode; 
#else
  const UInt uiChCodedMode = (uiChPredMode==DM_CHROMA_IDX && !bIsLuma) ? pcCU->getIntraDir(CHANNEL_TYPE_LUMA, uiAbsPartIdx) : uiChPredMode;
#endif
#else
  const UInt partsPerMinCU = 1<<(2*(sps.getMaxTotalCUDepth() - sps.getLog2DiffMaxMinCodingBlockSize()));
  const UInt uiChCodedMode = (uiChPredMode==DM_CHROMA_IDX && !bIsLuma) ? pcCU->getIntraDir(CHANNEL_TYPE_LUMA, getChromasCorrespondingPULumaIdx(uiAbsPartIdx, chFmt, partsPerMinCU)) : uiChPredMode;
#endif

  const UInt uiChFinalMode = ((chFmt == CHROMA_422)       && !bIsLuma) ? g_chroma422IntraAngleMappingTable[uiChCodedMode] : uiChCodedMode;
  //===== init availability pattern ,初始化可获得pattern=====
#if !COM16_C983_RSAF
  const 
#endif  //是否使用滤波的参考像素,与编码端一致
        Bool bUseFilteredPredictions=TComPrediction::filteringIntraReferenceSamples(compID, 
                                                                                    uiChFinalMode, 
                                                                                    uiWidth, 
                                                                                    uiHeight, 
                                                                                    chFmt, 
                                                                                    pcCU->getSlice()->getSPS()->getSpsRangeExtension().getIntraSmoothingDisabledFlag()
#if COM16_C983_RSAF_PREVENT_OVERSMOOTHING
                                                                                  , sps.getUseRSAF()
#endif
                                                                                   );

#if DEBUG_STRING
  std::ostream &ss(std::cout);
#endif

#if COM16_C983_RSAF
  Bool bFilter = false;
#if COM16_C1046_PDPC_RSAF_HARMONIZATION
  if (compID == COMPONENT_Y && sps.getUseRSAF() && pcCU->getPDPCIdx(uiAbsPartIdx) == 0)
#else
  if (compID==COMPONENT_Y && sps.getUseRSAF())
#endif
  {
    bFilter = (pcCU->getLumaIntraFilter( uiAbsPartIdx )) != 0;
#if JVET_C0024_QTBT
    bFilter &= !(pcCU->getWidth(0)*pcCU->getHeight(0)>1024);
#else
    bFilter &= !(pcCU->getWidth(0)>32);
#endif
  }
#endif


  DEBUG_STRING_NEW(sTemp)
  m_pcPrediction->initIntraPatternChType( rTu, compID, bUseFilteredPredictions  
#if COM16_C983_RSAF
                                        , (compID==COMPONENT_Y) ? bFilter : false
#endif
                                          DEBUG_STRING_PASS_INTO(sTemp) );//初始化参考像素


  //===== get prediction signal,得到预测信号,过程跟编码端也一致=====

#if COM16_C806_LMCHROMA
  if( uiChFinalMode == LM_CHROMA_IDX 
#if JVET_E0077_ENHANCED_LM
      || IsLMMode(uiChFinalMode)
#endif
      )//是CCLM模式
  {
    m_pcPrediction->getLumaRecPixels( rTu, uiWidth, uiHeight );//对相邻亮度色度和当前亮度进行下采样;
#if JVET_E0077_ENHANCED_LM
    Int iLMType = uiChFinalMode;
    m_pcPrediction->predLMIntraChroma(rTu, compID, piPred, uiStride, uiWidth, uiHeight, iLMType);//用亮度预测色度
#else
    m_pcPrediction->predLMIntraChroma( rTu, compID, piPred, uiStride, uiWidth, uiHeight );
#endif
  }
  else//普通角度模式
  {
#endif 
#if COM16_C983_RSAF
  if (compID==COMPONENT_Y && sps.getUseRSAF()) 
  {
    bUseFilteredPredictions = (bFilter != false);
  }
#endif//这个也是和编码时一样的函数
    m_pcPrediction->predIntraAng( compID,   uiChFinalMode, 0 /* Decoder does not have an original image */, 0, piPred, uiStride, rTu, bUseFilteredPredictions );

#if COM16_C806_LMCHROMA
    if( compID == COMPONENT_Cr && pcCU->getSlice()->getSPS()->getUseLMChroma() )
    { 
	  //std::cout << "传统预测模式是 " << uiChFinalMode << std::endl;
      m_pcPrediction->addCrossColorResi( rTu, compID, piPred, uiStride, uiWidth, uiHeight, pcResiYuv->getAddr( COMPONENT_Cb, uiAbsPartIdx ), pcResiYuv->getStride(COMPONENT_Cb) );
    }
  }
#endif

#if DEBUG_STRING
  ss << sTemp;
#endif

  //===== inverse transform ,反变换和反量化=====
  Pel*      piResi            = pcResiYuv->getAddr( compID, uiAbsPartIdx );//残差YUV
  TCoeff*   pcCoeff           = pcCU->getCoeff(compID) + rTu.getCoefficientOffset(compID);//( uiNumCoeffInc * uiAbsPartIdx );

  const QpParam cQP(*pcCU, compID);


  DEBUG_STRING_NEW(sDebug);
#if DEBUG_STRING
  const Int debugPredModeMask=DebugStringGetPredModeMask(MODE_INTRA);
  std::string *psDebug=(DebugOptionList::DebugString_InvTran.getInt()&debugPredModeMask) ? &sDebug : 0;
#endif

  if (pcCU->getCbf(uiAbsPartIdx, compID, rTu.GetTransformDepthRel()) != 0)//如果cbf!=0,则对残差进行反量化和反变换
  {
    m_pcTrQuant->invTransformNxN( rTu, compID, piResi, uiStride, pcCoeff, cQP DEBUG_STRING_PASS_INTO(psDebug) );
  }
  else//如果cbf=0,则直接令残差数据为0
  {
    for (UInt y = 0; y < uiHeight; y++)
    {
      for (UInt x = 0; x < uiWidth; x++)
      {
        piResi[(y * uiStride) + x] = 0;
      }
    }
  }

#if DEBUG_STRING
  if (psDebug)
  {
    ss << (*psDebug);
  }
#endif

  //===== reconstruction ,重建=预测加残差=====
  const UInt uiRecIPredStride  = pcCU->getPic()->getPicYuvRec()->getStride(compID);

  const Bool useCrossComponentPrediction = isChroma(compID) && (pcCU->getCrossComponentPredictionAlpha(uiAbsPartIdx, compID) != 0);
  const Pel* pResiLuma  = pcResiYuv->getAddr( COMPONENT_Y, uiAbsPartIdx );
  const Int  strideLuma = pcResiYuv->getStride( COMPONENT_Y );

        Pel* pPred      = piPred;
        Pel* pResi      = piResi;
        Pel* pReco      = pcRecoYuv->getAddr( compID, uiAbsPartIdx );
        Pel* pRecIPred  = pcCU->getPic()->getPicYuvRec()->getAddr( compID, pcCU->getCtuRsAddr(), pcCU->getZorderIdxInCtu() + uiAbsPartIdx );


#if DEBUG_STRING
  const Bool bDebugPred=((DebugOptionList::DebugString_Pred.getInt()&debugPredModeMask) && DEBUG_STRING_CHANNEL_CONDITION(compID));
  const Bool bDebugResi=((DebugOptionList::DebugString_Resi.getInt()&debugPredModeMask) && DEBUG_STRING_CHANNEL_CONDITION(compID));
  const Bool bDebugReco=((DebugOptionList::DebugString_Reco.getInt()&debugPredModeMask) && DEBUG_STRING_CHANNEL_CONDITION(compID));
  if (bDebugPred || bDebugResi || bDebugReco)
  {
    ss << "###: " << "CompID: " << compID << " pred mode (ch/fin): " << uiChPredMode << "/" << uiChFinalMode << " absPartIdx: " << rTu.GetAbsPartIdxTU() << std::endl;
  }
#endif

#if !JVET_D0033_ADAPTIVE_CLIPPING
  const Int clipbd = sps.getBitDepth(toChannelType(compID));
#endif
#if O0043_BEST_EFFORT_DECODING
  const Int bitDepthDelta = sps.getStreamBitDepth(toChannelType(compID)) - clipbd;
#endif

  if( useCrossComponentPrediction )
  {
    TComTrQuant::crossComponentPrediction( rTu, compID, pResiLuma, piResi, piResi, uiWidth, uiHeight, strideLuma, uiStride, uiStride, true );
  }
  //if (compID == 2 && uiChFinalMode >= 0 && uiChFinalMode < 67)
  //{
	//  std::cout << "cr分量的重建残差: " << std::endl;
  //}
  for( UInt uiY = 0; uiY < uiHeight; uiY++ )
  {
#if DEBUG_STRING
    if (bDebugPred || bDebugResi || bDebugReco)
    {
      ss << "###: ";
    }

    if (bDebugPred)
    {
      ss << " - pred: ";
      for( UInt uiX = 0; uiX < uiWidth; uiX++ )
      {
        ss << pPred[ uiX ] << ", ";
      }
    }
    if (bDebugResi)
    {
      ss << " - resi: ";
    }
#endif

    for( UInt uiX = 0; uiX < uiWidth; uiX++ )
    {
#if DEBUG_STRING
      if (bDebugResi)
      {
        ss << pResi[ uiX ] << ", ";
      }
#endif
#if O0043_BEST_EFFORT_DECODING
#if JVET_D0033_ADAPTIVE_CLIPPING
      pReco    [ uiX ] = ClipA( rightShiftEvenRounding<Pel>(pPred[ uiX ] + pResi[ uiX ], bitDepthDelta),  compID);
#else
      pReco    [ uiX ] = ClipBD( rightShiftEvenRounding<Pel>(pPred[ uiX ] + pResi[ uiX ], bitDepthDelta), clipbd );
#endif
#else

#if JVET_D0033_ADAPTIVE_CLIPPING // decoder intra rec
      pReco    [ uiX ] = ClipA(pPred[ uiX ] + pResi[ uiX ], compID);//重建值等于预测值加残差;	
#else
      pReco    [ uiX ] = ClipBD( pPred[ uiX ] + pResi[ uiX ], clipbd );
#endif
#endif
      pRecIPred[ uiX ] = pReco[ uiX ];//保存重建值,用于下一帧的预测;
	  //if (compID == 2 && uiChFinalMode >= 0 && uiChFinalMode < 67)
		//  printf("%4d", pResi[uiX]);
    }
	//if (compID == 2 && uiChFinalMode >= 0 && uiChFinalMode < 67)
		//std::cout << std::endl;
#if DEBUG_STRING
    if (bDebugReco)
    {
      ss << " - reco: ";
      for( UInt uiX = 0; uiX < uiWidth; uiX++ )
      {
        ss << pReco[ uiX ] << ", ";
      }
    }

    if (bDebugPred || bDebugResi || bDebugReco)
    {
      ss << "\n";
    }
#endif
    pPred     += uiStride;
    pResi     += uiStride;
    pReco     += uiStride;
    pRecIPred += uiRecIPredStride;
  }
  //if (compID == 2 && uiChFinalMode >= 0 && uiChFinalMode < 67)
  //{
	//  std::cout << std::endl;
	//  std::cout << std::endl;
  //}
#if JVET_F0096_BILATERAL_FILTER
  if(pcCU->getSlice()->getSPS()->getUseBilateralFilter()) //重建完使用双边滤波,和编码端一致,只对亮度分量使用    
  {
    Pel* piReco = pcRecoYuv->getAddr( compID, uiAbsPartIdx );
    Pel* piRecIPred = pcCU->getPic()->getPicYuvRec()->getAddr( compID, pcCU->getCtuRsAddr(), pcCU->getZorderIdxInCtu() + uiAbsPartIdx );

    if (isLuma(compID))
    {
      if ((pcCU->getCbf(uiAbsPartIdx, compID, rTu.GetTransformDepthRel()) != 0) && (pcCU->getQP(COMPONENT_Y) > 17))
      {//双边滤波器即重建CU中的每一个亮度采样都用其自身及其邻近采样的加权平均替代
        TComBilateralFilter::instance()->bilateralFilterIntra(pcCU, uiWidth, uiHeight, piReco, uiStride, pcCU->getQP(COMPONENT_Y));
        for( UInt uiY = 0; uiY < uiHeight; uiY++ )
        {
          memcpy(piRecIPred + uiY * uiRecIPredStride, piReco + uiY * uiStride , uiWidth * sizeof(Short));
          uiY++;
          memcpy(piRecIPred + uiY * uiRecIPredStride, piReco + uiY * uiStride , uiWidth * sizeof(Short));
        }
      }
    }
  }
#endif
}

猜你喜欢

转载自blog.csdn.net/cxy19931018/article/details/80634027