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 ); }