HEVC代码追踪(五):compressSlice

Void TEncSlice::compressSlice( TComPic*& rpcPic )
{
  UInt  uiCUAddr;
  UInt   uiStartCUAddr;
  UInt   uiBoundingCUAddr;
  rpcPic->getSlice(getSliceIdx())->setSliceSegmentBits(0);
  TEncBinCABAC* pppcRDSbacCoder = NULL;
  TComSlice* pcSlice            = rpcPic->getSlice(getSliceIdx());
  xDetermineStartAndBoundingCUAddr ( uiStartCUAddr, uiBoundingCUAddr, rpcPic, false );

  // initialize cost values
  m_uiPicTotalBits  = 0;
  m_dPicRdCost      = 0;
  m_uiPicDist       = 0;

  // set entropy coder
  m_pcSbacCoder->init( m_pcBinCABAC );
  m_pcEntropyCoder->setEntropyCoder   ( m_pcSbacCoder, pcSlice );
  m_pcEntropyCoder->resetEntropy      ();
  m_pppcRDSbacCoder[0][CI_CURR_BEST]->load(m_pcSbacCoder);
  pppcRDSbacCoder = (TEncBinCABAC *) m_pppcRDSbacCoder[0][CI_CURR_BEST]->getEncBinIf();
  pppcRDSbacCoder->setBinCountingEnableFlag( false );
  pppcRDSbacCoder->setBinsCoded( 0 );

  //------------------------------------------------------------------------------
  //  Weighted Prediction parameters estimation.
  //------------------------------------------------------------------------------
  // calculate AC/DC values for current picture
  if( pcSlice->getPPS()->getUseWP() || pcSlice->getPPS()->getWPBiPred() )
  {
    xCalcACDCParamSlice(pcSlice);
  }

  Bool bWp_explicit = (pcSlice->getSliceType()==P_SLICE && pcSlice->getPPS()->getUseWP()) || (pcSlice->getSliceType()==B_SLICE && pcSlice->getPPS()->getWPBiPred());

  if ( bWp_explicit )
  {
    //------------------------------------------------------------------------------
    //  Weighted Prediction implemented at Slice level. SliceMode=2 is not supported yet.
    //------------------------------------------------------------------------------
    if ( pcSlice->getSliceMode()==2 || pcSlice->getSliceSegmentMode()==2 )
    {
      printf("Weighted Prediction is not supported with slice mode determined by max number of bins.\n"); exit(0);
    }

    xEstimateWPParamSlice( pcSlice );
    pcSlice->initWpScaling();

    // check WP on/off
    xCheckWPEnable( pcSlice );
  }

#if ADAPTIVE_QP_SELECTION
  if( m_pcCfg->getUseAdaptQpSelect() )
  {
    m_pcTrQuant->clearSliceARLCnt();
    if(pcSlice->getSliceType()!=I_SLICE)
    {
      Int qpBase = pcSlice->getSliceQpBase();
      pcSlice->setSliceQp(qpBase + m_pcTrQuant->getQpDelta(qpBase));
    }
  }
#endif
  TEncTop* pcEncTop = (TEncTop*) m_pcCfg;
  TEncSbac**** ppppcRDSbacCoders    = pcEncTop->getRDSbacCoders();
  TComBitCounter* pcBitCounters     = pcEncTop->getBitCounters();
  Int  iNumSubstreams = 1;
  UInt uiTilesAcross  = 0;

  iNumSubstreams = pcSlice->getPPS()->getNumSubstreams();
  uiTilesAcross = rpcPic->getPicSym()->getNumColumnsMinus1()+1;
  delete[] m_pcBufferSbacCoders;
  delete[] m_pcBufferBinCoderCABACs;
  m_pcBufferSbacCoders     = new TEncSbac    [uiTilesAcross];
  m_pcBufferBinCoderCABACs = new TEncBinCABAC[uiTilesAcross];
  for (Int ui = 0; ui < uiTilesAcross; ui++)
  {
    m_pcBufferSbacCoders[ui].init( &m_pcBufferBinCoderCABACs[ui] );
  }
  for (UInt ui = 0; ui < uiTilesAcross; ui++)
  {
    m_pcBufferSbacCoders[ui].load(m_pppcRDSbacCoder[0][CI_CURR_BEST]);  //init. state
  }

  for ( UInt ui = 0 ; ui < iNumSubstreams ; ui++ ) //init all sbac coders for RD optimization
  {
    ppppcRDSbacCoders[ui][0][CI_CURR_BEST]->load(m_pppcRDSbacCoder[0][CI_CURR_BEST]);
  }

  delete[] m_pcBufferLowLatSbacCoders;
  delete[] m_pcBufferLowLatBinCoderCABACs;
  m_pcBufferLowLatSbacCoders     = new TEncSbac    [uiTilesAcross];
  m_pcBufferLowLatBinCoderCABACs = new TEncBinCABAC[uiTilesAcross];
  for (Int ui = 0; ui < uiTilesAcross; ui++)
  {
    m_pcBufferLowLatSbacCoders[ui].init( &m_pcBufferLowLatBinCoderCABACs[ui] );
  }
  for (UInt ui = 0; ui < uiTilesAcross; ui++)
    m_pcBufferLowLatSbacCoders[ui].load(m_pppcRDSbacCoder[0][CI_CURR_BEST]);  //init. state

  UInt uiWidthInLCUs  = rpcPic->getPicSym()->getFrameWidthInCU();
  //UInt uiHeightInLCUs = rpcPic->getPicSym()->getFrameHeightInCU();
  UInt uiCol=0, uiLin=0, uiSubStrm=0;
  UInt uiTileCol      = 0;
  UInt uiTileStartLCU = 0;
  UInt uiTileLCUX     = 0;
  Bool depSliceSegmentsEnabled = pcSlice->getPPS()->getDependentSliceSegmentsEnabledFlag();
  uiCUAddr = rpcPic->getPicSym()->getCUOrderMap( uiStartCUAddr /rpcPic->getNumPartInCU());
  uiTileStartLCU = rpcPic->getPicSym()->getTComTile(rpcPic->getPicSym()->getTileIdxMap(uiCUAddr))->getFirstCUAddr();
  if( depSliceSegmentsEnabled )
  {
    if((pcSlice->getSliceSegmentCurStartCUAddr()!= pcSlice->getSliceCurStartCUAddr())&&(uiCUAddr != uiTileStartLCU))
    {
      if( m_pcCfg->getWaveFrontsynchro() )
      {
        uiTileCol = rpcPic->getPicSym()->getTileIdxMap(uiCUAddr) % (rpcPic->getPicSym()->getNumColumnsMinus1()+1);
        m_pcBufferSbacCoders[uiTileCol].loadContexts( CTXMem[1] );
        Int iNumSubstreamsPerTile = iNumSubstreams/rpcPic->getPicSym()->getNumTiles();
        uiCUAddr = rpcPic->getPicSym()->getCUOrderMap( uiStartCUAddr /rpcPic->getNumPartInCU());
        uiLin     = uiCUAddr / uiWidthInLCUs;
        uiSubStrm = rpcPic->getPicSym()->getTileIdxMap(rpcPic->getPicSym()->getCUOrderMap(uiCUAddr))*iNumSubstreamsPerTile
          + uiLin%iNumSubstreamsPerTile;
        if ( (uiCUAddr%uiWidthInLCUs+1) >= uiWidthInLCUs  )
        {
          uiTileLCUX = uiTileStartLCU % uiWidthInLCUs;
          uiCol     = uiCUAddr % uiWidthInLCUs;
          if(uiCol==uiTileStartLCU)
          {
            CTXMem[0]->loadContexts(m_pcSbacCoder);
          }
        }
      }
      m_pppcRDSbacCoder[0][CI_CURR_BEST]->loadContexts( CTXMem[0] );
      ppppcRDSbacCoders[uiSubStrm][0][CI_CURR_BEST]->loadContexts( CTXMem[0] );
    }
    else
    {
      if(m_pcCfg->getWaveFrontsynchro())
      {
        CTXMem[1]->loadContexts(m_pcSbacCoder);
      }
      CTXMem[0]->loadContexts(m_pcSbacCoder);
    }
  }
  // for every CU in slice
  UInt uiEncCUOrder;
  for( uiEncCUOrder = uiStartCUAddr/rpcPic->getNumPartInCU();
       uiEncCUOrder < (uiBoundingCUAddr+(rpcPic->getNumPartInCU()-1))/rpcPic->getNumPartInCU();
       uiCUAddr = rpcPic->getPicSym()->getCUOrderMap(++uiEncCUOrder) )
  {
    // initialize CU encoder
    TComDataCU*& pcCU = rpcPic->getCU( uiCUAddr );
    pcCU->initCU( rpcPic, uiCUAddr );

    // inherit from TR if necessary, select substream to use.
    uiTileCol = rpcPic->getPicSym()->getTileIdxMap(uiCUAddr) % (rpcPic->getPicSym()->getNumColumnsMinus1()+1); // what column of tiles are we in?
    uiTileStartLCU = rpcPic->getPicSym()->getTComTile(rpcPic->getPicSym()->getTileIdxMap(uiCUAddr))->getFirstCUAddr();
    uiTileLCUX = uiTileStartLCU % uiWidthInLCUs;
    //UInt uiSliceStartLCU = pcSlice->getSliceCurStartCUAddr();
    uiCol     = uiCUAddr % uiWidthInLCUs;
    uiLin     = uiCUAddr / uiWidthInLCUs;
    if (pcSlice->getPPS()->getNumSubstreams() > 1)
    {
      // independent tiles => substreams are "per tile".  iNumSubstreams has already been multiplied.
      Int iNumSubstreamsPerTile = iNumSubstreams/rpcPic->getPicSym()->getNumTiles();
      uiSubStrm = rpcPic->getPicSym()->getTileIdxMap(uiCUAddr)*iNumSubstreamsPerTile
          + uiLin%iNumSubstreamsPerTile;
    }
    else
    {
      // dependent tiles => substreams are "per frame".
      uiSubStrm = uiLin % iNumSubstreams;
    }
    if ( ((pcSlice->getPPS()->getNumSubstreams() > 1) || depSliceSegmentsEnabled ) && (uiCol == uiTileLCUX) && m_pcCfg->getWaveFrontsynchro())
    {
      // We'll sync if the TR is available.
      TComDataCU *pcCUUp = pcCU->getCUAbove();
      UInt uiWidthInCU = rpcPic->getFrameWidthInCU();
      UInt uiMaxParts = 1<<(pcSlice->getSPS()->getMaxCUDepth()<<1);
      TComDataCU *pcCUTR = NULL;
      if ( pcCUUp && ((uiCUAddr%uiWidthInCU+1) < uiWidthInCU)  )
      {
        pcCUTR = rpcPic->getCU( uiCUAddr - uiWidthInCU + 1 );
      }
      if ( ((pcCUTR==NULL) || (pcCUTR->getSlice()==NULL) ||
          (pcCUTR->getSCUAddr()+uiMaxParts-1 < pcSlice->getSliceCurStartCUAddr()) ||
          ((rpcPic->getPicSym()->getTileIdxMap( pcCUTR->getAddr() ) != rpcPic->getPicSym()->getTileIdxMap(uiCUAddr)))
      )
      )
      {
        // TR not available.
      }
      else
      {
        // TR is available, we use it.
        ppppcRDSbacCoders[uiSubStrm][0][CI_CURR_BEST]->loadContexts( &m_pcBufferSbacCoders[uiTileCol] );
      }
    }
    m_pppcRDSbacCoder[0][CI_CURR_BEST]->load( ppppcRDSbacCoders[uiSubStrm][0][CI_CURR_BEST] ); //this load is used to simplify the code

    // reset the entropy coder
    if( uiCUAddr == rpcPic->getPicSym()->getTComTile(rpcPic->getPicSym()->getTileIdxMap(uiCUAddr))->getFirstCUAddr() &&                                   // must be first CU of tile
        uiCUAddr!=0 &&                                                                                                                                    // cannot be first CU of picture
        uiCUAddr!=rpcPic->getPicSym()->getPicSCUAddr(rpcPic->getSlice(rpcPic->getCurrSliceIdx())->getSliceSegmentCurStartCUAddr())/rpcPic->getNumPartInCU() &&
        uiCUAddr!=rpcPic->getPicSym()->getPicSCUAddr(rpcPic->getSlice(rpcPic->getCurrSliceIdx())->getSliceCurStartCUAddr())/rpcPic->getNumPartInCU())     // cannot be first CU of slice
    {
      SliceType sliceType = pcSlice->getSliceType();
      if (!pcSlice->isIntra() && pcSlice->getPPS()->getCabacInitPresentFlag() && pcSlice->getPPS()->getEncCABACTableIdx()!=I_SLICE)
      {
        sliceType = (SliceType) pcSlice->getPPS()->getEncCABACTableIdx();
      }
      m_pcEntropyCoder->updateContextTables ( sliceType, pcSlice->getSliceQp(), false );
      m_pcEntropyCoder->setEntropyCoder     ( m_pppcRDSbacCoder[0][CI_CURR_BEST], pcSlice );
      m_pcEntropyCoder->updateContextTables ( sliceType, pcSlice->getSliceQp() );
      m_pcEntropyCoder->setEntropyCoder     ( m_pcSbacCoder, pcSlice );
    }

    // set go-on entropy coder
    m_pcEntropyCoder->setEntropyCoder ( m_pcRDGoOnSbacCoder, pcSlice );
    m_pcEntropyCoder->setBitstream( &pcBitCounters[uiSubStrm] );

    ((TEncBinCABAC*)m_pcRDGoOnSbacCoder->getEncBinIf())->setBinCountingEnableFlag(true);

	/****************************************码率控制:对每一个LCU需要用到的相关参数进行初始化**********************************/
    Double oldLambda = m_pcRdCost->getLambda();
    if ( m_pcCfg->getUseRateCtrl() )
    {
      Int estQP        = pcSlice->getSliceQp();
      Double estLambda = -1.0;
      Double bpp       = -1.0;

      if ( ( rpcPic->getSlice( 0 )->getSliceType() == I_SLICE && m_pcCfg->getForceIntraQP() ) || !m_pcCfg->getLCULevelRC() )
      {
        estQP = pcSlice->getSliceQp();
      }
      else
      {
        bpp = m_pcRateCtrl->getRCPic()->getLCUTargetBpp(pcSlice->getSliceType());
        if ( rpcPic->getSlice( 0 )->getSliceType() == I_SLICE)
        {
          estLambda = m_pcRateCtrl->getRCPic()->getLCUEstLambdaAndQP(bpp, pcSlice->getSliceQp(), &estQP);
        }
        else
        {
          estLambda = m_pcRateCtrl->getRCPic()->getLCUEstLambda( bpp );
          estQP     = m_pcRateCtrl->getRCPic()->getLCUEstQP    ( estLambda, pcSlice->getSliceQp() );
        }

        estQP     = Clip3( -pcSlice->getSPS()->getQpBDOffsetY(), MAX_QP, estQP );

        m_pcRdCost->setLambda(estLambda);
#if RDOQ_CHROMA_LAMBDA
// set lambda for RDOQ
        Double weight=m_pcRdCost->getChromaWeight();
        const Double lambdaArray[3] = { estLambda, (estLambda / weight), (estLambda / weight) };
        m_pcTrQuant->setLambdas( lambdaArray );
#else
        m_pcTrQuant->setLambda( estLambda );
#endif
      }

      m_pcRateCtrl->setRCQP( estQP );
#if ADAPTIVE_QP_SELECTION
      pcCU->getSlice()->setSliceQpBase( estQP );
#endif
    }
	/**************************************************************************************************************/

    // run CU encoder
    m_pcCuEncoder->compressCU( pcCU );

    // restore entropy coder to an initial stage
    m_pcEntropyCoder->setEntropyCoder ( m_pppcRDSbacCoder[0][CI_CURR_BEST], pcSlice );
    m_pcEntropyCoder->setBitstream( &pcBitCounters[uiSubStrm] );
    m_pcCuEncoder->setBitCounter( &pcBitCounters[uiSubStrm] );
    m_pcBitCounter = &pcBitCounters[uiSubStrm];
    pppcRDSbacCoder->setBinCountingEnableFlag( true );
    m_pcBitCounter->resetBits();
    pppcRDSbacCoder->setBinsCoded( 0 );
    m_pcCuEncoder->encodeCU( pcCU );

    pppcRDSbacCoder->setBinCountingEnableFlag( false );
    if (m_pcCfg->getSliceMode()==FIXED_NUMBER_OF_BYTES && ( ( pcSlice->getSliceBits() + m_pcEntropyCoder->getNumberOfWrittenBits() ) ) > m_pcCfg->getSliceArgument()<<3)
    {
      pcSlice->setNextSlice( true );
      break;
    }
    if (m_pcCfg->getSliceSegmentMode()==FIXED_NUMBER_OF_BYTES && pcSlice->getSliceSegmentBits()+m_pcEntropyCoder->getNumberOfWrittenBits() > (m_pcCfg->getSliceSegmentArgument() << 3) &&pcSlice->getSliceCurEndCUAddr()!=pcSlice->getSliceSegmentCurEndCUAddr())
    {
      pcSlice->setNextSliceSegment( true );
      break;
    }

    ppppcRDSbacCoders[uiSubStrm][0][CI_CURR_BEST]->load( m_pppcRDSbacCoder[0][CI_CURR_BEST] );
    //Store probabilties of second LCU in line into buffer
    if ( ( uiCol == uiTileLCUX+1) && (depSliceSegmentsEnabled || (pcSlice->getPPS()->getNumSubstreams() > 1)) && m_pcCfg->getWaveFrontsynchro())
    {
      m_pcBufferSbacCoders[uiTileCol].loadContexts(ppppcRDSbacCoders[uiSubStrm][0][CI_CURR_BEST]);
    }

	/***************************************码率控制:每编码完一个LCU,进行一次更新********************************************/
    if ( m_pcCfg->getUseRateCtrl() )
    {

      Int actualQP        = g_RCInvalidQPValue;
      Double actualLambda = m_pcRdCost->getLambda();
      Int actualBits      = pcCU->getTotalBits();
      Int numberOfEffectivePixels    = 0;
      for ( Int idx = 0; idx < rpcPic->getNumPartInCU(); idx++ )
      {
        if ( pcCU->getPredictionMode( idx ) != MODE_NONE && ( !pcCU->isSkipped( idx ) ) )//!< 不考虑skip模式
        {
          numberOfEffectivePixels = numberOfEffectivePixels + 16;
          break;
        }
      }

      if ( numberOfEffectivePixels == 0 )
      {
        actualQP = g_RCInvalidQPValue;
      }
      else
      {
        actualQP = pcCU->getQP( 0 );
      }
      m_pcRdCost->setLambda(oldLambda);

      m_pcRateCtrl->getRCPic()->updateAfterLCU( m_pcRateCtrl->getRCPic()->getLCUCoded(), actualBits, actualQP, actualLambda,
          pcCU->getSlice()->getSliceType() == I_SLICE ? 0 : m_pcCfg->getLCULevelRC() );
    }
    /*******************************************************************************************************/

    m_uiPicTotalBits += pcCU->getTotalBits();
    m_dPicRdCost     += pcCU->getTotalCost();
    m_uiPicDist      += pcCU->getTotalDistortion();
  }
  if ((pcSlice->getPPS()->getNumSubstreams() > 1) && !depSliceSegmentsEnabled)
  {
    pcSlice->setNextSlice( true );
  }
  if(m_pcCfg->getSliceMode()==FIXED_NUMBER_OF_BYTES || m_pcCfg->getSliceSegmentMode()==FIXED_NUMBER_OF_BYTES)
  {
    if(pcSlice->getSliceCurEndCUAddr()<=pcSlice->getSliceSegmentCurEndCUAddr())
    {
       pcSlice->setNextSlice( true );
    }
    else
    {
       pcSlice->setNextSliceSegment( true );
    }
  }
  if( depSliceSegmentsEnabled )
  {
    if (m_pcCfg->getWaveFrontsynchro())
    {
      CTXMem[1]->loadContexts( &m_pcBufferSbacCoders[uiTileCol] );//ctx 2.LCU
    }
     CTXMem[0]->loadContexts( m_pppcRDSbacCoder[0][CI_CURR_BEST] );//ctx end of dep.slice
  }
  xRestoreWPparam( pcSlice );
}
时间: 2024-09-19 10:10:09

HEVC代码追踪(五):compressSlice的相关文章

HEVC代码追踪(十五):解码之decompressSlice

Void TDecGop::decompressSlice(TComInputBitstream* pcBitstream, TComPic*& rpcPic) { TComSlice* pcSlice = rpcPic->getSlice(rpcPic->getCurrSliceIdx()); // Table of extracted substreams. // These must be deallocated AND their internal fifos, too. TC

HEVC代码追踪(十一。五):运动估计/补偿之xTZSearch

Void TEncSearch::xTZSearch( TComDataCU* pcCU, TComPattern* pcPatternKey, Pel* piRefY, Int iRefStride, TComMv* pcMvSrchRngLT, TComMv* pcMvSrchRngRB, TComMv& rcMv, UInt& ruiSAD ) {//!< 确定运动估计搜索范围的边界 Int iSrchRngHorLeft = pcMvSrchRngLT->getHor(

HEVC代码追踪(十一):运动估计/补偿之理论知识

运动估计的英文名称是Motion Estimation,是视频编码和视频处理(例如去交织)中广泛使用的一种技术. 运动估计的基本思想是将图像序列的每一帧分成许多互不重叠的宏块,并认为宏块内所有像素的位移量都相同,然后对每个宏块到参考帧某一给定特定搜索范围内根据一定的匹配准则找出与当前块最相似的块,即匹配块,匹配块与当前块的相对位移即为运动矢量.视频压缩的时候,只需保存运动矢量和残差数据就可以完全恢复出当前块. 在帧间预测编码中,由于活动图像邻近帧中的景物存在着一定的相关性.因此,可将活动图像分成

HEVC代码追踪(十三):解码之decode

// ==================================================================================================================== // Public member functions // ====================================================================================================

HEVC代码追踪(一):int main

int main(int argc, char* argv[]) { TAppEncTop cTAppEncTop; // print information fprintf( stdout, "\n" ); fprintf( stdout, "HM software: Encoder Version [%s]", NV_VERSION ); fprintf( stdout, NVM_ONOS ); fprintf( stdout, NVM_COMPILEDBY )

HEVC代码追踪(四。二)

/////////////////////////////////////////////////////////////////////////////////////////////////// Compress a slice // Slice compression if (m_pcCfg->getUseASR()) { m_pcSliceEncoder->setSearchRange(pcSlice); } Bool bGPBcheck=false; if ( pcSlice->

HEVC代码追踪(十四):解码之xDecodeSlice

Bool TDecTop::decode(InputNALUnit& nalu, Int& iSkipFrame, Int& iPOCLastDisplay) { // Initialize entropy decoder m_cEntropyDecoder.setEntropyDecoder (&m_cCavlcDecoder); m_cEntropyDecoder.setBitstream (nalu.m_Bitstream); switch (nalu.m_nalUn

HEVC代码追踪(四。一)

Bool IRAPtoReorder = false; #if EFFICIENT_FIELD_IRAP if(IRAPtoReorder) { if(swapIRAPForward) { if(iGOPid == IRAPGOPid) { iGOPid = IRAPGOPid +1; } else if(iGOPid == IRAPGOPid +1) { iGOPid = IRAPGOPid; } } else { if(iGOPid == IRAPGOPid -1) { iGOPid = I

HEVC代码追踪(四。三)

/* use the main bitstream buffer for storing the marshalled picture */ m_pcEntropyCoder->setBitstream(NULL); startCUAddrSliceIdx = 0; startCUAddrSlice = 0; startCUAddrSliceSegmentIdx = 0; startCUAddrSliceSegment = 0; nextCUAddr = 0; pcSlice = pcPic->