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