/////////////////////////////////////////////////////////////////////////////////////////////////// Compress a slice // Slice compression if (m_pcCfg->getUseASR()) { m_pcSliceEncoder->setSearchRange(pcSlice); } Bool bGPBcheck=false; if ( pcSlice->getSliceType() == B_SLICE) { if ( pcSlice->getNumRefIdx(RefPicList( 0 ) ) == pcSlice->getNumRefIdx(RefPicList( 1 ) ) ) { bGPBcheck=true; Int i; for ( i=0; i < pcSlice->getNumRefIdx(RefPicList( 1 ) ); i++ ) { if ( pcSlice->getRefPOC(RefPicList(1), i) != pcSlice->getRefPOC(RefPicList(0), i) ) { bGPBcheck=false; break; } } } } if(bGPBcheck) { pcSlice->setMvdL1ZeroFlag(true); } else { pcSlice->setMvdL1ZeroFlag(false); } pcPic->getSlice(pcSlice->getSliceIdx())->setMvdL1ZeroFlag(pcSlice->getMvdL1ZeroFlag());
码率控制:对每一幅picture需要用到的相关参数进行初始化
Double lambda = 0.0; Int actualHeadBits = 0; Int actualTotalBits = 0; Int estimatedBits = 0; Int tmpBitsBeforeWriting = 0; if ( m_pcCfg->getUseRateCtrl() ) { Int frameLevel = m_pcRateCtrl->getRCSeq()->getGOPID2Level( iGOPid ); if ( pcPic->getSlice(0)->getSliceType() == I_SLICE ) { frameLevel = 0; } m_pcRateCtrl->initRCPic( frameLevel ); estimatedBits = m_pcRateCtrl->getRCPic()->getTargetBits(); Int sliceQP = m_pcCfg->getInitialQP(); if ( ( pcSlice->getPOC() == 0 && m_pcCfg->getInitialQP() > 0 ) || ( frameLevel == 0 && m_pcCfg->getForceIntraQP() ) ) // QP is specified { Int NumberBFrames = ( m_pcCfg->getGOPSize() - 1 ); Double dLambda_scale = 1.0 - Clip3( 0.0, 0.5, 0.05*(Double)NumberBFrames ); Double dQPFactor = 0.57*dLambda_scale; Int SHIFT_QP = 12; Int bitdepth_luma_qp_scale = 0; Double qp_temp = (Double) sliceQP + bitdepth_luma_qp_scale - SHIFT_QP; lambda = dQPFactor*pow( 2.0, qp_temp/3.0 ); } else if ( frameLevel == 0 ) // intra case, but use the model { m_pcSliceEncoder->calCostSliceI(pcPic); if ( m_pcCfg->getIntraPeriod() != 1 ) // do not refine allocated bits for all intra case { Int bits = m_pcRateCtrl->getRCSeq()->getLeftAverageBits(); bits = m_pcRateCtrl->getRCPic()->getRefineBitsForIntra( bits ); if ( bits < 200 ) { bits = 200; } m_pcRateCtrl->getRCPic()->setTargetBits( bits ); } list<TEncRCPic*> listPreviousPicture = m_pcRateCtrl->getPicList(); m_pcRateCtrl->getRCPic()->getLCUInitTargetBits(); lambda = m_pcRateCtrl->getRCPic()->estimatePicLambda( listPreviousPicture, pcSlice->getSliceType()); sliceQP = m_pcRateCtrl->getRCPic()->estimatePicQP( lambda, listPreviousPicture ); } else // normal case { list<TEncRCPic*> listPreviousPicture = m_pcRateCtrl->getPicList(); lambda = m_pcRateCtrl->getRCPic()->estimatePicLambda( listPreviousPicture, pcSlice->getSliceType()); sliceQP = m_pcRateCtrl->getRCPic()->estimatePicQP( lambda, listPreviousPicture ); } sliceQP = Clip3( -pcSlice->getSPS()->getQpBDOffsetY(), MAX_QP, sliceQP ); m_pcRateCtrl->getRCPic()->setPicEstQP( sliceQP ); m_pcSliceEncoder->resetQP( pcPic, sliceQP, lambda ); }
/*Slice Compression部分*/ UInt uiNumSlices = 1; UInt uiInternalAddress = pcPic->getNumPartInCU()-4;//CU内部Zscan顺序 UInt uiExternalAddress = pcPic->getPicSym()->getNumberOfCUsInFrame()-1;//CU相对于整帧图像的位置 UInt uiPosX = ( uiExternalAddress % pcPic->getFrameWidthInCU() ) * g_uiMaxCUWidth+ g_auiRasterToPelX[ g_auiZscanToRaster[uiInternalAddress] ];//CU的绝对位置 UInt uiPosY = ( uiExternalAddress / pcPic->getFrameWidthInCU() ) * g_uiMaxCUHeight+ g_auiRasterToPelY[ g_auiZscanToRaster[uiInternalAddress] ]; UInt uiWidth = pcSlice->getSPS()->getPicWidthInLumaSamples(); UInt uiHeight = pcSlice->getSPS()->getPicHeightInLumaSamples(); while(uiPosX>=uiWidth||uiPosY>=uiHeight) { uiInternalAddress--; uiPosX = ( uiExternalAddress % pcPic->getFrameWidthInCU() ) * g_uiMaxCUWidth+ g_auiRasterToPelX[ g_auiZscanToRaster[uiInternalAddress] ]; uiPosY = ( uiExternalAddress / pcPic->getFrameWidthInCU() ) * g_uiMaxCUHeight+ g_auiRasterToPelY[ g_auiZscanToRaster[uiInternalAddress] ]; } uiInternalAddress++; if(uiInternalAddress==pcPic->getNumPartInCU()) { uiInternalAddress = 0; uiExternalAddress++; } UInt uiRealEndAddress = uiExternalAddress*pcPic->getNumPartInCU()+uiInternalAddress; Int p, j; UInt uiEncCUAddr; pcPic->getPicSym()->initTiles(pcSlice->getPPS()); // Allocate some coders, now we know how many tiles there are. Int iNumSubstreams = pcSlice->getPPS()->getNumSubstreams(); //generate the Coding Order Map and Inverse Coding Order Map for(p=0, uiEncCUAddr=0; p<pcPic->getPicSym()->getNumberOfCUsInFrame(); p++, uiEncCUAddr = pcPic->getPicSym()->xCalculateNxtCUAddr(uiEncCUAddr)) { pcPic->getPicSym()->setCUOrderMap(p, uiEncCUAddr); pcPic->getPicSym()->setInverseCUOrderMap(uiEncCUAddr, p); } pcPic->getPicSym()->setCUOrderMap(pcPic->getPicSym()->getNumberOfCUsInFrame(), pcPic->getPicSym()->getNumberOfCUsInFrame()); pcPic->getPicSym()->setInverseCUOrderMap(pcPic->getPicSym()->getNumberOfCUsInFrame(), pcPic->getPicSym()->getNumberOfCUsInFrame()); // Allocate some coders, now we know how many tiles there are. m_pcEncTop->createWPPCoders(iNumSubstreams); pcSbacCoders = m_pcEncTop->getSbacCoders(); pcSubstreamsOut = new TComOutputBitstream[iNumSubstreams]; UInt startCUAddrSliceIdx = 0; // used to index "m_uiStoredStartCUAddrForEncodingSlice" containing locations of slice boundaries UInt startCUAddrSlice = 0; // used to keep track of current slice's starting CU addr. pcSlice->setSliceCurStartCUAddr( startCUAddrSlice ); // Setting "start CU addr" for current slice m_storedStartCUAddrForEncodingSlice.clear(); UInt startCUAddrSliceSegmentIdx = 0; // used to index "m_uiStoredStartCUAddrForEntropyEncodingSlice" containing locations of slice boundaries UInt startCUAddrSliceSegment = 0; // used to keep track of current Dependent slice's starting CU addr. pcSlice->setSliceSegmentCurStartCUAddr( startCUAddrSliceSegment ); // Setting "start CU addr" for current Dependent slice m_storedStartCUAddrForEncodingSliceSegment.clear(); UInt nextCUAddr = 0; m_storedStartCUAddrForEncodingSlice.push_back (nextCUAddr); startCUAddrSliceIdx++; m_storedStartCUAddrForEncodingSliceSegment.push_back(nextCUAddr); startCUAddrSliceSegmentIdx++;
while(nextCUAddr<uiRealEndAddress) // determine slice boundaries { pcSlice->setNextSlice ( false ); pcSlice->setNextSliceSegment( false ); assert(pcPic->getNumAllocatedSlice() == startCUAddrSliceIdx); m_pcSliceEncoder->precompressSlice( pcPic ); m_pcSliceEncoder->compressSlice ( pcPic ); Bool bNoBinBitConstraintViolated = (!pcSlice->isNextSlice() && !pcSlice->isNextSliceSegment()); if (pcSlice->isNextSlice() || (bNoBinBitConstraintViolated && m_pcCfg->getSliceMode()==FIXED_NUMBER_OF_LCU)) { startCUAddrSlice = pcSlice->getSliceCurEndCUAddr(); // Reconstruction slice m_storedStartCUAddrForEncodingSlice.push_back(startCUAddrSlice); startCUAddrSliceIdx++; // Dependent slice if (startCUAddrSliceSegmentIdx>0 && m_storedStartCUAddrForEncodingSliceSegment[startCUAddrSliceSegmentIdx-1] != startCUAddrSlice) { m_storedStartCUAddrForEncodingSliceSegment.push_back(startCUAddrSlice); startCUAddrSliceSegmentIdx++; } if (startCUAddrSlice < uiRealEndAddress) { pcPic->allocateNewSlice(); pcPic->setCurrSliceIdx ( startCUAddrSliceIdx-1 ); m_pcSliceEncoder->setSliceIdx ( startCUAddrSliceIdx-1 ); pcSlice = pcPic->getSlice ( startCUAddrSliceIdx-1 ); pcSlice->copySliceInfo ( pcPic->getSlice(0) ); pcSlice->setSliceIdx ( startCUAddrSliceIdx-1 ); pcSlice->setSliceCurStartCUAddr ( startCUAddrSlice ); pcSlice->setSliceSegmentCurStartCUAddr ( startCUAddrSlice ); pcSlice->setSliceBits(0); uiNumSlices ++; } } else if (pcSlice->isNextSliceSegment() || (bNoBinBitConstraintViolated && m_pcCfg->getSliceSegmentMode()==FIXED_NUMBER_OF_LCU)) { startCUAddrSliceSegment = pcSlice->getSliceSegmentCurEndCUAddr(); m_storedStartCUAddrForEncodingSliceSegment.push_back(startCUAddrSliceSegment); startCUAddrSliceSegmentIdx++; pcSlice->setSliceSegmentCurStartCUAddr( startCUAddrSliceSegment ); } else { startCUAddrSlice = pcSlice->getSliceCurEndCUAddr(); startCUAddrSliceSegment = pcSlice->getSliceSegmentCurEndCUAddr(); } nextCUAddr = (startCUAddrSlice > startCUAddrSliceSegment) ? startCUAddrSlice : startCUAddrSliceSegment; } m_storedStartCUAddrForEncodingSlice.push_back( pcSlice->getSliceCurEndCUAddr()); startCUAddrSliceIdx++; m_storedStartCUAddrForEncodingSliceSegment.push_back(pcSlice->getSliceCurEndCUAddr()); startCUAddrSliceSegmentIdx++; pcSlice = pcPic->getSlice(0); // SAO parameter estimation using non-deblocked pixels for LCU bottom and right boundary areas if( pcSlice->getSPS()->getUseSAO() && m_pcCfg->getSaoLcuBoundary() ) { m_pcSAO->getPreDBFStatistics(pcPic); } //-- Loop filter Bool bLFCrossTileBoundary = pcSlice->getPPS()->getLoopFilterAcrossTilesEnabledFlag(); m_pcLoopFilter->setCfg(bLFCrossTileBoundary); if ( m_pcCfg->getDeblockingFilterMetric() ) { dblMetric(pcPic, uiNumSlices); } m_pcLoopFilter->loopFilterPic( pcPic );
/////////////////////////////////////////////////////////////////////////////////////////////////// File writing // Set entropy coder m_pcEntropyCoder->setEntropyCoder ( m_pcCavlcCoder, pcSlice ); /* write various header sets. */ if ( m_bSeqFirst ) { OutputNALUnit nalu(NAL_UNIT_VPS); m_pcEntropyCoder->setBitstream(&nalu.m_Bitstream); m_pcEntropyCoder->encodeVPS(m_pcEncTop->getVPS()); writeRBSPTrailingBits(nalu.m_Bitstream); accessUnit.push_back(new NALUnitEBSP(nalu)); actualTotalBits += UInt(accessUnit.back()->m_nalUnitData.str().size()) * 8; nalu = NALUnit(NAL_UNIT_SPS); m_pcEntropyCoder->setBitstream(&nalu.m_Bitstream); if (m_bSeqFirst) { pcSlice->getSPS()->setNumLongTermRefPicSPS(m_numLongTermRefPicSPS); for (Int k = 0; k < m_numLongTermRefPicSPS; k++) { pcSlice->getSPS()->setLtRefPicPocLsbSps(k, m_ltRefPicPocLsbSps[k]); pcSlice->getSPS()->setUsedByCurrPicLtSPSFlag(k, m_ltRefPicUsedByCurrPicFlag[k]); } } if( m_pcCfg->getPictureTimingSEIEnabled() || m_pcCfg->getDecodingUnitInfoSEIEnabled() ) { UInt maxCU = m_pcCfg->getSliceArgument() >> ( pcSlice->getSPS()->getMaxCUDepth() << 1); UInt numDU = ( m_pcCfg->getSliceMode() == 1 ) ? ( pcPic->getNumCUsInFrame() / maxCU ) : ( 0 ); if( pcPic->getNumCUsInFrame() % maxCU != 0 || numDU == 0 ) { numDU ++; } pcSlice->getSPS()->getVuiParameters()->getHrdParameters()->setNumDU( numDU ); pcSlice->getSPS()->setHrdParameters( m_pcCfg->getFrameRate(), numDU, m_pcCfg->getTargetBitrate(), ( m_pcCfg->getIntraPeriod() > 0 ) ); } if( m_pcCfg->getBufferingPeriodSEIEnabled() || m_pcCfg->getPictureTimingSEIEnabled() || m_pcCfg->getDecodingUnitInfoSEIEnabled() ) { pcSlice->getSPS()->getVuiParameters()->setHrdParametersPresentFlag( true ); } m_pcEntropyCoder->encodeSPS(pcSlice->getSPS()); writeRBSPTrailingBits(nalu.m_Bitstream); accessUnit.push_back(new NALUnitEBSP(nalu)); actualTotalBits += UInt(accessUnit.back()->m_nalUnitData.str().size()) * 8; nalu = NALUnit(NAL_UNIT_PPS); m_pcEntropyCoder->setBitstream(&nalu.m_Bitstream); m_pcEntropyCoder->encodePPS(pcSlice->getPPS()); writeRBSPTrailingBits(nalu.m_Bitstream); accessUnit.push_back(new NALUnitEBSP(nalu)); actualTotalBits += UInt(accessUnit.back()->m_nalUnitData.str().size()) * 8; xCreateLeadingSEIMessages(accessUnit, pcSlice->getSPS()); m_bSeqFirst = false; } if (writeSOP) // write SOP description SEI (if enabled) at the beginning of GOP { Int SOPcurrPOC = pocCurr; OutputNALUnit nalu(NAL_UNIT_PREFIX_SEI); m_pcEntropyCoder->setEntropyCoder(m_pcCavlcCoder, pcSlice); m_pcEntropyCoder->setBitstream(&nalu.m_Bitstream); SEISOPDescription SOPDescriptionSEI; SOPDescriptionSEI.m_sopSeqParameterSetId = pcSlice->getSPS()->getSPSId(); UInt i = 0; UInt prevEntryId = iGOPid; for (j = iGOPid; j < m_iGopSize; j++) { Int deltaPOC = m_pcCfg->getGOPEntry(j).m_POC - m_pcCfg->getGOPEntry(prevEntryId).m_POC; if ((SOPcurrPOC + deltaPOC) < m_pcCfg->getFramesToBeEncoded()) { SOPcurrPOC += deltaPOC; SOPDescriptionSEI.m_sopDescVclNaluType[i] = getNalUnitType(SOPcurrPOC, m_iLastIDR, isField); SOPDescriptionSEI.m_sopDescTemporalId[i] = m_pcCfg->getGOPEntry(j).m_temporalId; SOPDescriptionSEI.m_sopDescStRpsIdx[i] = m_pcEncTop->getReferencePictureSetIdxForSOP(pcSlice, SOPcurrPOC, j); SOPDescriptionSEI.m_sopDescPocDelta[i] = deltaPOC; prevEntryId = j; i++; } } SOPDescriptionSEI.m_numPicsInSopMinus1 = i - 1; m_seiWriter.writeSEImessage( nalu.m_Bitstream, SOPDescriptionSEI, pcSlice->getSPS()); writeRBSPTrailingBits(nalu.m_Bitstream); accessUnit.push_back(new NALUnitEBSP(nalu)); writeSOP = false; } if( ( m_pcCfg->getPictureTimingSEIEnabled() || m_pcCfg->getDecodingUnitInfoSEIEnabled() ) && ( pcSlice->getSPS()->getVuiParametersPresentFlag() ) && ( ( pcSlice->getSPS()->getVuiParameters()->getHrdParameters()->getNalHrdParametersPresentFlag() ) || ( pcSlice->getSPS()->getVuiParameters()->getHrdParameters()->getVclHrdParametersPresentFlag() ) ) ) { if( pcSlice->getSPS()->getVuiParameters()->getHrdParameters()->getSubPicCpbParamsPresentFlag() ) { UInt numDU = pcSlice->getSPS()->getVuiParameters()->getHrdParameters()->getNumDU(); pictureTimingSEI.m_numDecodingUnitsMinus1 = ( numDU - 1 ); pictureTimingSEI.m_duCommonCpbRemovalDelayFlag = false; if( pictureTimingSEI.m_numNalusInDuMinus1 == NULL ) { pictureTimingSEI.m_numNalusInDuMinus1 = new UInt[ numDU ]; } if( pictureTimingSEI.m_duCpbRemovalDelayMinus1 == NULL ) { pictureTimingSEI.m_duCpbRemovalDelayMinus1 = new UInt[ numDU ]; } if( accumBitsDU == NULL ) { accumBitsDU = new UInt[ numDU ]; } if( accumNalsDU == NULL ) { accumNalsDU = new UInt[ numDU ]; } } pictureTimingSEI.m_auCpbRemovalDelay = std::min<Int>(std::max<Int>(1, m_totalCoded - m_lastBPSEI), static_cast<Int>(pow(2, static_cast<double>(pcSlice->getSPS()->getVuiParameters()->getHrdParameters()->getCpbRemovalDelayLengthMinus1()+1)))); // Syntax element signalled as minus, hence the . pictureTimingSEI.m_picDpbOutputDelay = pcSlice->getSPS()->getNumReorderPics(pcSlice->getSPS()->getMaxTLayers()-1) + pcSlice->getPOC() - m_totalCoded; #if EFFICIENT_FIELD_IRAP if(IRAPGOPid > 0 && IRAPGOPid < m_iGopSize) { // if pictures have been swapped there is likely one more picture delay on their tid. Very rough approximation pictureTimingSEI.m_picDpbOutputDelay ++; } #endif Int factor = pcSlice->getSPS()->getVuiParameters()->getHrdParameters()->getTickDivisorMinus2() + 2; pictureTimingSEI.m_picDpbOutputDuDelay = factor * pictureTimingSEI.m_picDpbOutputDelay; if( m_pcCfg->getDecodingUnitInfoSEIEnabled() ) { picSptDpbOutputDuDelay = factor * pictureTimingSEI.m_picDpbOutputDelay; } } if( ( m_pcCfg->getBufferingPeriodSEIEnabled() ) && ( pcSlice->getSliceType() == I_SLICE ) && ( pcSlice->getSPS()->getVuiParametersPresentFlag() ) && ( ( pcSlice->getSPS()->getVuiParameters()->getHrdParameters()->getNalHrdParametersPresentFlag() ) || ( pcSlice->getSPS()->getVuiParameters()->getHrdParameters()->getVclHrdParametersPresentFlag() ) ) ) { OutputNALUnit nalu(NAL_UNIT_PREFIX_SEI); m_pcEntropyCoder->setEntropyCoder(m_pcCavlcCoder, pcSlice); m_pcEntropyCoder->setBitstream(&nalu.m_Bitstream); SEIBufferingPeriod sei_buffering_period; UInt uiInitialCpbRemovalDelay = (90000/2); // 0.5 sec sei_buffering_period.m_initialCpbRemovalDelay [0][0] = uiInitialCpbRemovalDelay; sei_buffering_period.m_initialCpbRemovalDelayOffset[0][0] = uiInitialCpbRemovalDelay; sei_buffering_period.m_initialCpbRemovalDelay [0][1] = uiInitialCpbRemovalDelay; sei_buffering_period.m_initialCpbRemovalDelayOffset[0][1] = uiInitialCpbRemovalDelay; Double dTmp = (Double)pcSlice->getSPS()->getVuiParameters()->getTimingInfo()->getNumUnitsInTick() / (Double)pcSlice->getSPS()->getVuiParameters()->getTimingInfo()->getTimeScale(); UInt uiTmp = (UInt)( dTmp * 90000.0 ); uiInitialCpbRemovalDelay -= uiTmp; uiInitialCpbRemovalDelay -= uiTmp / ( pcSlice->getSPS()->getVuiParameters()->getHrdParameters()->getTickDivisorMinus2() + 2 ); sei_buffering_period.m_initialAltCpbRemovalDelay [0][0] = uiInitialCpbRemovalDelay; sei_buffering_period.m_initialAltCpbRemovalDelayOffset[0][0] = uiInitialCpbRemovalDelay; sei_buffering_period.m_initialAltCpbRemovalDelay [0][1] = uiInitialCpbRemovalDelay; sei_buffering_period.m_initialAltCpbRemovalDelayOffset[0][1] = uiInitialCpbRemovalDelay; sei_buffering_period.m_rapCpbParamsPresentFlag = 0; //for the concatenation, it can be set to one during splicing. sei_buffering_period.m_concatenationFlag = 0; //since the temporal layer HRD is not ready, we assumed it is fixed sei_buffering_period.m_auCpbRemovalDelayDelta = 1; sei_buffering_period.m_cpbDelayOffset = 0; sei_buffering_period.m_dpbDelayOffset = 0; m_seiWriter.writeSEImessage( nalu.m_Bitstream, sei_buffering_period, pcSlice->getSPS()); writeRBSPTrailingBits(nalu.m_Bitstream); { UInt seiPositionInAu = xGetFirstSeiLocation(accessUnit); UInt offsetPosition = m_activeParameterSetSEIPresentInAU; // Insert BP SEI after APS SEI AccessUnit::iterator it; for(j = 0, it = accessUnit.begin(); j < seiPositionInAu + offsetPosition; j++) { it++; } accessUnit.insert(it, new NALUnitEBSP(nalu)); m_bufferingPeriodSEIPresentInAU = true; } if (m_pcCfg->getScalableNestingSEIEnabled()) { OutputNALUnit naluTmp(NAL_UNIT_PREFIX_SEI); m_pcEntropyCoder->setEntropyCoder(m_pcCavlcCoder, pcSlice); m_pcEntropyCoder->setBitstream(&naluTmp.m_Bitstream); scalableNestingSEI.m_nestedSEIs.clear(); scalableNestingSEI.m_nestedSEIs.push_back(&sei_buffering_period); m_seiWriter.writeSEImessage( naluTmp.m_Bitstream, scalableNestingSEI, pcSlice->getSPS()); writeRBSPTrailingBits(naluTmp.m_Bitstream); UInt seiPositionInAu = xGetFirstSeiLocation(accessUnit); UInt offsetPosition = m_activeParameterSetSEIPresentInAU + m_bufferingPeriodSEIPresentInAU + m_pictureTimingSEIPresentInAU; // Insert BP SEI after non-nested APS, BP and PT SEIs AccessUnit::iterator it; for(j = 0, it = accessUnit.begin(); j < seiPositionInAu + offsetPosition; j++) { it++; } accessUnit.insert(it, new NALUnitEBSP(naluTmp)); m_nestedBufferingPeriodSEIPresentInAU = true; } m_lastBPSEI = m_totalCoded; m_cpbRemovalDelay = 0; } m_cpbRemovalDelay ++; if( ( m_pcEncTop->getRecoveryPointSEIEnabled() ) && ( pcSlice->getSliceType() == I_SLICE ) ) { if( m_pcEncTop->getGradualDecodingRefreshInfoEnabled() && !pcSlice->getRapPicFlag() ) { // Gradual decoding refresh SEI OutputNALUnit nalu(NAL_UNIT_PREFIX_SEI); m_pcEntropyCoder->setEntropyCoder(m_pcCavlcCoder, pcSlice); m_pcEntropyCoder->setBitstream(&nalu.m_Bitstream); SEIGradualDecodingRefreshInfo seiGradualDecodingRefreshInfo; seiGradualDecodingRefreshInfo.m_gdrForegroundFlag = true; // Indicating all "foreground" m_seiWriter.writeSEImessage( nalu.m_Bitstream, seiGradualDecodingRefreshInfo, pcSlice->getSPS() ); writeRBSPTrailingBits(nalu.m_Bitstream); accessUnit.push_back(new NALUnitEBSP(nalu)); } // Recovery point SEI OutputNALUnit nalu(NAL_UNIT_PREFIX_SEI); m_pcEntropyCoder->setEntropyCoder(m_pcCavlcCoder, pcSlice); m_pcEntropyCoder->setBitstream(&nalu.m_Bitstream); SEIRecoveryPoint sei_recovery_point; sei_recovery_point.m_recoveryPocCnt = 0; sei_recovery_point.m_exactMatchingFlag = ( pcSlice->getPOC() == 0 ) ? (true) : (false); sei_recovery_point.m_brokenLinkFlag = false; #if ALLOW_RECOVERY_POINT_AS_RAP if(m_pcCfg->getDecodingRefreshType() == 3) { m_iLastRecoveryPicPOC = pocCurr; } #endif m_seiWriter.writeSEImessage( nalu.m_Bitstream, sei_recovery_point, pcSlice->getSPS() ); writeRBSPTrailingBits(nalu.m_Bitstream); accessUnit.push_back(new NALUnitEBSP(nalu)); }