VTM010.0xIntraRecBlk函数解析

Posted 神遁克里苏

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了VTM010.0xIntraRecBlk函数解析相关的知识,希望对你有一定的参考价值。

本函数完成了重建值的生成。
1.获取当前块的pred
2.反量化反变换得到resi
3.resi+pred=reco

void DecCu::xIntraRecBlk( TransformUnit& tu, const ComponentID compID )

  if( !tu.blocks[ compID ].valid() )
  //如果当前的tu块是无效的,则返回
    return;
  

        CodingStructure &cs = *tu.cs;
  const CompArea &area      = tu.blocks[compID];

  const ChannelType chType  = toChannelType( compID );

        PelBuf piPred       = cs.getPredBuf( area );

  const PredictionUnit &pu  = *tu.cs->getPU( area.pos(), chType );
  const uint32_t uiChFinalMode  = PU::getFinalIntraMode( pu, chType );
  PelBuf pReco              = cs.getRecoBuf(area);

  //===== init availability pattern =====
  bool predRegDiffFromTB = CU::isPredRegDiffFromTB(*tu.cu, compID);
  bool firstTBInPredReg = CU::isFirstTBInPredReg(*tu.cu, compID, area);
  CompArea areaPredReg(COMPONENT_Y, tu.chromaFormat, area);
  if (tu.cu->ispMode && isLuma(compID))
  
    if (predRegDiffFromTB)
    
      if (firstTBInPredReg)
      
        CU::adjustPredArea(areaPredReg);
        m_pcIntraPred->initIntraPatternChTypeISP(*tu.cu, areaPredReg, pReco);
      
    
    else
    //初始化ISP模式
      m_pcIntraPred->initIntraPatternChTypeISP(*tu.cu, area, pReco);
    
  
  else
  //如果不是ISP模式,则使用initIntraPatternChType初始化
    m_pcIntraPred->initIntraPatternChType(*tu.cu, area);
  

  //===== get prediction signal =====
  if( compID != COMPONENT_Y && PU::isLMCMode( uiChFinalMode ) )
  //如果当前是色度  且是CCLM模式
    const PredictionUnit& pu = *tu.cu->firstPU;
    m_pcIntraPred->xGetLumaRecPixels( pu, area );//获取亮度区域并对其下采样
    m_pcIntraPred->predIntraChromaLM( compID, piPred, pu, area, uiChFinalMode );//进行CCLM
  
  else
  
    if( PU::isMIP( pu, chType ) )
    //如果是MIP模式
      m_pcIntraPred->initIntraMip( pu, area );
      m_pcIntraPred->predIntraMip( compID, piPred, pu );
    
    else
    
      if (predRegDiffFromTB)
      
        if (firstTBInPredReg)
        
          PelBuf piPredReg = cs.getPredBuf(areaPredReg);
          m_pcIntraPred->predIntraAng(compID, piPredReg, pu);
        
      
      else//传统角度模式
        m_pcIntraPred->predIntraAng(compID, piPred, pu);
    
  
  const Slice           &slice = *cs.slice;
  bool flag = slice.getLmcsEnabledFlag() && (slice.isIntra() || (!slice.isIntra() && m_pcReshape->getCTUFlag()));
  if (flag && slice.getPicHeader()->getLmcsChromaResidualScaleFlag() && (compID != COMPONENT_Y) && (tu.cbf[COMPONENT_Cb] || tu.cbf[COMPONENT_Cr]))
  
    const Area area = tu.Y().valid() ? tu.Y() : Area(recalcPosition(tu.chromaFormat, tu.chType, CHANNEL_TYPE_LUMA, tu.blocks[tu.chType].pos()), recalcSize(tu.chromaFormat, tu.chType, CHANNEL_TYPE_LUMA, tu.blocks[tu.chType].size()));
    const CompArea &areaY = CompArea(COMPONENT_Y, tu.chromaFormat, area);
    int adj = m_pcReshape->calculateChromaAdjVpduNei(tu, areaY);
    tu.setChromaAdj(adj);
  
  //===== inverse transform =====反变换量化
  PelBuf piResi = cs.getResiBuf( area );

  const QpParam cQP( tu, compID );

  if( tu.jointCbCr && isChroma(compID) )
  
    if( compID == COMPONENT_Cb )
    
      PelBuf resiCr = cs.getResiBuf( tu.blocks[ COMPONENT_Cr ] );
      if( tu.jointCbCr >> 1 )
      
        m_pcTrQuant->invTransformNxN( tu, COMPONENT_Cb, piResi, cQP );
      
      else
      
        const QpParam qpCr( tu, COMPONENT_Cr );
        m_pcTrQuant->invTransformNxN( tu, COMPONENT_Cr, resiCr, qpCr );
      
      m_pcTrQuant->invTransformICT( tu, piResi, resiCr );
    
  
  else
  if( TU::getCbf( tu, compID ) )
  
    m_pcTrQuant->invTransformNxN( tu, compID, piResi, cQP );
  
  else
  
    piResi.fill( 0 );
  

  //===== reconstruction =====
  flag = flag && (tu.blocks[compID].width*tu.blocks[compID].height > 4);
  if (flag && (TU::getCbf(tu, compID) || tu.jointCbCr) && isChroma(compID) && slice.getPicHeader()->getLmcsChromaResidualScaleFlag())
  
    piResi.scaleSignal(tu.getChromaAdj(), 0, tu.cu->cs->slice->clpRng(compID));
  

  if( !tu.cu->ispMode || !isLuma( compID ) )
  
    cs.setDecomp( area );
  
  else if( tu.cu->ispMode && isLuma( compID ) && CU::isISPFirst( *tu.cu, tu.blocks[compID], compID ) )
  
    cs.setDecomp( tu.cu->blocks[compID] );
  

#if REUSE_CU_RESULTS
  CompArea    tmpArea(COMPONENT_Y, area.chromaFormat, Position(0, 0), area.size());
  PelBuf tmpPred;
#endif
  if (slice.getLmcsEnabledFlag() && (m_pcReshape->getCTUFlag() || slice.isIntra()) && compID == COMPONENT_Y)
  
#if REUSE_CU_RESULTS
    
      tmpPred = m_tmpStorageLCU->getBuf(tmpArea);
      tmpPred.copyFrom(piPred);
    
#endif
  
  
#if KEEP_PRED_AND_RESI_SIGNALS
  pReco.reconstruct( piPred, piResi, tu.cu->cs->slice->clpRng( compID ) );//保留resi和pred
#else
  piPred.reconstruct( piPred, piResi, tu.cu->cs->slice->clpRng( compID ) );//不保留resi和pred
#endif
#if !KEEP_PRED_AND_RESI_SIGNALS
  pReco.copyFrom( piPred );
#endif
  if (slice.getLmcsEnabledFlag() && (m_pcReshape->getCTUFlag() || slice.isIntra()) && compID == COMPONENT_Y)
  
#if REUSE_CU_RESULTS
    
      piPred.copyFrom(tmpPred);
    
#endif
  
#if REUSE_CU_RESULTS
  if( cs.pcv->isEncoder )
  
    cs.picture->getRecoBuf( area ).copyFrom( pReco );
    cs.picture->getPredBuf(area).copyFrom(piPred);
  
#endif

以上是关于VTM010.0xIntraRecBlk函数解析的主要内容,如果未能解决你的问题,请参考以下文章

VTM10.0predIntraAng函数解析

VTM10.0predIntraAng函数解析

VTM10.0xPredIntraAng函数解析

VTM10.0xPredIntraAng函数解析

H.266/VVC-VTM代码学习27-VTM中编码器主函数逻辑

VVC/VTM帧内编码主要流程图与划分函数