From 4951ad32d7ee14663d7b80931358574e4541745e Mon Sep 17 00:00:00 2001 From: Jack Enhorn <jack.enhorn@ericsson.com> Date: Fri, 26 Feb 2021 13:27:46 +0100 Subject: [PATCH] GDR related decoder fixes --- source/App/DecoderApp/DecApp.cpp | 63 ++++++++++++++++++++++++++ source/Lib/CommonLib/Slice.cpp | 76 +++++++++++++++++++------------- source/Lib/DecoderLib/DecLib.cpp | 71 ++++++++++++++++++++++++----- source/Lib/DecoderLib/DecLib.h | 5 ++- 4 files changed, 173 insertions(+), 42 deletions(-) diff --git a/source/App/DecoderApp/DecApp.cpp b/source/App/DecoderApp/DecApp.cpp index 2357da0c2..923753891 100644 --- a/source/App/DecoderApp/DecApp.cpp +++ b/source/App/DecoderApp/DecApp.cpp @@ -165,6 +165,9 @@ uint32_t DecApp::decode() m_cDecLib.setHTidExternalSetFlag(m_mTidExternalSet); m_cDecLib.setTOlsIdxExternalFlag(m_tOlsIdxTidExternalSet); + bool gdrRecoveryPeriod[MAX_NUM_LAYER_IDS] = { false }; + bool prevPicSkipped = true; + while (!!bitstreamFile) { InputNALUnit nalu; @@ -249,7 +252,40 @@ uint32_t DecApp::decode() bPicSkipped = false; } } + + int skipFrameCounter = m_iSkipFrame; m_cDecLib.decode(nalu, m_iSkipFrame, m_iPOCLastDisplay, m_targetOlsIdx); + + if ( prevPicSkipped && nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_GDR ) + { + gdrRecoveryPeriod[nalu.m_nuhLayerId] = true; + } + + if ( skipFrameCounter == 1 && ( nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_GDR || nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_CRA )) + { + skipFrameCounter--; + } + + if ( m_iSkipFrame < skipFrameCounter && + ((nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_TRAIL) || (nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_STSA) || (nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_RASL) || (nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_RADL) || (nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_IDR_W_RADL) || (nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_IDR_N_LP) || (nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_CRA) || (nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_GDR))) + { + if (m_cDecLib.isSliceNaluFirstInAU(true, nalu)) + { + m_cDecLib.checkSeiInPictureUnit(); + m_cDecLib.resetPictureSeiNalus(); + m_cDecLib.checkAPSInPictureUnit(); + m_cDecLib.resetPictureUnitNals(); + m_cDecLib.resetAccessUnitSeiTids(); + m_cDecLib.checkSEIInAccessUnit(); + m_cDecLib.resetAccessUnitSeiPayLoadTypes(); + m_cDecLib.resetAccessUnitNals(); + m_cDecLib.resetAccessUnitApsNals(); + m_cDecLib.resetAccessUnitPicInfo(); + } + bPicSkipped = true; + m_iSkipFrame++; // skipFrame count restore, the real decrement occur at the begin of next frame + } + if (nalu.m_nalUnitType == NAL_UNIT_OPI) { if (!m_cDecLib.getHTidExternalSetFlag() && m_cDecLib.getOPI()->getHtidInfoPresentFlag()) @@ -270,6 +306,12 @@ uint32_t DecApp::decode() bPicSkipped = true; } } + + if( nalu.isSlice() ) + { + prevPicSkipped = bPicSkipped; + } + // once an EOS NAL unit appears in the current PU, mark the variable isEosPresentInPu as true if (nalu.m_nalUnitType == NAL_UNIT_EOS) { @@ -299,6 +341,14 @@ uint32_t DecApp::decode() m_cDecLib.updateAssociatedIRAP(); m_cDecLib.updatePrevGDRInSameLayer(); m_cDecLib.updatePrevIRAPAndGDRSubpic(); + + if ( gdrRecoveryPeriod[nalu.m_nuhLayerId] ) + { + if ( m_cDecLib.getGDRRecoveryPocReached() ) + { + gdrRecoveryPeriod[nalu.m_nuhLayerId] = false; + } + } } else if ( (bNewPicture || !bitstreamFile || nalu.m_nalUnitType == NAL_UNIT_EOS ) && m_cDecLib.getFirstSliceInSequence(nalu.m_nuhLayerId)) @@ -308,6 +358,19 @@ uint32_t DecApp::decode() if( pcListPic ) { + if ( gdrRecoveryPeriod[nalu.m_nuhLayerId] ) // Suppress YUV and OPL output during GDR recovery + { + PicList::iterator iterPic = pcListPic->begin(); + while (iterPic != pcListPic->end()) + { + Picture *pcPic = *(iterPic++); + if (pcPic->layerId == nalu.m_nuhLayerId) + { + pcPic->neededForOutput = false; + } + } + } + if( !m_reconFileName.empty() && !m_cVideoIOYuvReconFile[nalu.m_nuhLayerId].isOpen() ) { const BitDepths &bitDepths=pcListPic->front()->cs->sps->getBitDepths(); // use bit depths of first reconstructed picture. diff --git a/source/Lib/CommonLib/Slice.cpp b/source/Lib/CommonLib/Slice.cpp index e0fd63754..4b5c04742 100644 --- a/source/Lib/CommonLib/Slice.cpp +++ b/source/Lib/CommonLib/Slice.cpp @@ -614,12 +614,19 @@ void Slice::checkRPL(const ReferencePictureList* pRPL0, const ReferencePictureLi int irapPOC = getAssociatedIRAPPOC(); - const int numEntries[] = { pRPL0->getNumberOfShorttermPictures() + pRPL0->getNumberOfLongtermPictures() + pRPL0->getNumberOfInterLayerPictures(), pRPL1->getNumberOfShorttermPictures() + pRPL1->getNumberOfLongtermPictures() + pRPL1->getNumberOfInterLayerPictures() }; + int numEntries[] = { pRPL0->getNumberOfShorttermPictures() + pRPL0->getNumberOfLongtermPictures() + pRPL0->getNumberOfInterLayerPictures(), pRPL1->getNumberOfShorttermPictures() + pRPL1->getNumberOfLongtermPictures() + pRPL1->getNumberOfInterLayerPictures() }; const int numActiveEntries[] = { getNumRefIdx( REF_PIC_LIST_0 ), getNumRefIdx( REF_PIC_LIST_1 ) }; const ReferencePictureList* rpl[] = { pRPL0, pRPL1 }; const bool fieldSeqFlag = getSPS()->getFieldSeqFlag(); const int layerIdx = m_pcPic->cs->vps == nullptr ? 0 : m_pcPic->cs->vps->getGeneralLayerIdx( m_pcPic->layerId ); + if ( rcListPic.size() < numEntries[0] || rcListPic.size() < numEntries[1] ) + { + numEntries[0] = 0; + numEntries[1] = 0; + msg( NOTICE, "Reset numEntriesL0 and numEntriesL1. E.g. receive a CRA after some skipped slices\n"); + } + for( int refPicList = 0; refPicList < 2; refPicList++ ) { for( int i = 0; i < numEntries[refPicList]; i++ ) @@ -668,7 +675,7 @@ void Slice::checkRPL(const ReferencePictureList* pRPL0, const ReferencePictureLi // Generated reference picture does not have picture header const bool isGeneratedRefPic = pcRefPic->slices[0]->getPicHeader() ? false : true; - const bool nonReferencePictureFlag = isGeneratedRefPic ? pcRefPic->slices[0]->getPicHeader()->getNonReferencePictureFlag() : pcRefPic->nonReferencePictureFlag; + const bool nonReferencePictureFlag = isGeneratedRefPic ? pcRefPic->nonReferencePictureFlag : pcRefPic->slices[0]->getPicHeader()->getNonReferencePictureFlag(); CHECK( pcRefPic == m_pcPic || nonReferencePictureFlag, "The picture referred to by each entry in RefPicList[ 0 ] or RefPicList[ 1 ] shall not be the current picture and shall have ph_non_ref_pic_flag equal to 0" ); if( i < numActiveEntries[refPicList] ) @@ -1110,37 +1117,40 @@ void Slice::checkLeadingPictureRestrictions(PicList& rcListPic, const PPS& pps) } const Slice* pcSlice = pcPic->slices[0]; - if (pcSlice->getPicHeader()->getPicOutputFlag() == 1 && !this->getNoOutputOfPriorPicsFlag() && pcPic->layerId == this->m_nuhLayerId) + if(pcSlice->getPicHeader()) // Generated reference picture does not have picture header { - if ((nalUnitType == NAL_UNIT_CODED_SLICE_CRA || nalUnitType == NAL_UNIT_CODED_SLICE_IDR_N_LP || nalUnitType == NAL_UNIT_CODED_SLICE_IDR_W_RADL) && !pps.getMixedNaluTypesInPicFlag()) + if (pcSlice->getPicHeader()->getPicOutputFlag() == 1 && !this->getNoOutputOfPriorPicsFlag() && pcPic->layerId == this->m_nuhLayerId) { - CHECK(pcPic->poc >= this->getPOC(), "Any picture, with nuh_layer_id equal to a particular value layerId, that precedes an IRAP picture with nuh_layer_id " - "equal to layerId in decoding order shall precede the IRAP picture in output order."); + if ((nalUnitType == NAL_UNIT_CODED_SLICE_CRA || nalUnitType == NAL_UNIT_CODED_SLICE_IDR_N_LP || nalUnitType == NAL_UNIT_CODED_SLICE_IDR_W_RADL) && !pps.getMixedNaluTypesInPicFlag()) + { + CHECK(pcPic->poc >= this->getPOC(), "Any picture, with nuh_layer_id equal to a particular value layerId, that precedes an IRAP picture with nuh_layer_id " + "equal to layerId in decoding order shall precede the IRAP picture in output order."); + } } - } - if (pcSlice->getPicHeader()->getPicOutputFlag() == 1 && pcPic->layerId == this->m_nuhLayerId) - { - if (nalUnitType == NAL_UNIT_CODED_SLICE_RADL) + if (pcSlice->getPicHeader()->getPicOutputFlag() == 1 && pcPic->layerId == this->m_nuhLayerId) { - if (this->getAssociatedIRAPPOC() > pcSlice->getAssociatedIRAPPOC() && !pps.getMixedNaluTypesInPicFlag()) + if (nalUnitType == NAL_UNIT_CODED_SLICE_RADL) { - if (this->getAssociatedIRAPPOC() != pcPic->poc) + if (this->getAssociatedIRAPPOC() > pcSlice->getAssociatedIRAPPOC() && !pps.getMixedNaluTypesInPicFlag()) { - CHECK(pcPic->poc >= this->getPOC(), "Any picture, with nuh_layer_id equal to a particular value layerId, that precedes an IRAP picture with nuh_layer_id " - "equal to layerId in decoding order shall precede any RADL picture associated with the IRAP picture in output order."); + if (this->getAssociatedIRAPPOC() != pcPic->poc) + { + CHECK(pcPic->poc >= this->getPOC(), "Any picture, with nuh_layer_id equal to a particular value layerId, that precedes an IRAP picture with nuh_layer_id " + "equal to layerId in decoding order shall precede any RADL picture associated with the IRAP picture in output order."); + } } } } - } - if (pcSlice->getPicHeader()->getPicOutputFlag() == 1 && !this->getPicHeader()->getNoOutputBeforeRecoveryFlag() && pcPic->layerId == this->m_nuhLayerId - && nalUnitType != NAL_UNIT_CODED_SLICE_GDR && this->getPicHeader()->getRecoveryPocCnt() != -1) - { - if (this->getPOC() == this->getPicHeader()->getRecoveryPocCnt() + this->getPrevGDRInSameLayerPOC()) + if (pcSlice->getPicHeader()->getPicOutputFlag() == 1 && !this->getPicHeader()->getNoOutputBeforeRecoveryFlag() && pcPic->layerId == this->m_nuhLayerId + && nalUnitType != NAL_UNIT_CODED_SLICE_GDR && this->getPicHeader()->getRecoveryPocCnt() != -1) { - CHECK(pcPic->poc >= this->getPOC(), "Any picture, with nuh_layer_id equal to a particular value layerId, that precedes a recovery point picture with " - "nuh_layer_id equal to layerId in decoding order shall precede the recovery point picture in output order."); + if (this->getPOC() == this->getPicHeader()->getRecoveryPocCnt() + this->getPrevGDRInSameLayerPOC()) + { + CHECK(pcPic->poc >= this->getPOC(), "Any picture, with nuh_layer_id equal to a particular value layerId, that precedes a recovery point picture with " + "nuh_layer_id equal to layerId in decoding order shall precede the recovery point picture in output order."); + } } } @@ -1251,14 +1261,18 @@ void Slice::checkSubpicTypeConstraints(PicList& rcListPic, const ReferencePictur bool isBufPicOutput = false; int bufSubpicType = NAL_UNIT_INVALID; int bufSubpicPrevIRAPSubpicPOC = 0; - for (int i = 0; i < bufPic->numSlices; i++) + + if (bufPic->slices[0]->getPicHeader() != NULL) // Generated reference picture does not have picture header { - if (bufPic->sliceSubpicIdx[i] == curSubpicIdx) + for (int i = 0; i < bufPic->numSlices; i++) { - isBufPicOutput = bufPic->slices[i]->getPicHeader()->getPicOutputFlag(); - bufSubpicType = bufPic->slices[i]->getNalUnitType(); - bufSubpicPrevIRAPSubpicPOC = bufPic->slices[i]->getPrevIRAPSubpicPOC(); - break; + if (bufPic->sliceSubpicIdx[i] == curSubpicIdx) + { + isBufPicOutput = bufPic->slices[i]->getPicHeader()->getPicOutputFlag(); + bufSubpicType = bufPic->slices[i]->getNalUnitType(); + bufSubpicPrevIRAPSubpicPOC = bufPic->slices[i]->getPrevIRAPSubpicPOC(); + break; + } } } @@ -1813,7 +1827,7 @@ int Slice::checkThatAllRefPicsAreAvailable(PicList& rcListPic, const ReferencePi { if (printErrors) { - msg(ERROR, "\nCurrent picture: %d Long-term reference picture with POC = %3d seems to have been removed or not correctly decoded.", this->getPOC(), notPresentPoc); + msg(ERROR, "Error: Current picture: %d Long-term reference picture with POC = %3d seems to have been removed or not correctly decoded.\n", this->getPOC(), notPresentPoc); } return notPresentPoc; } @@ -1844,7 +1858,7 @@ int Slice::checkThatAllRefPicsAreAvailable(PicList& rcListPic, const ReferencePi { if (printErrors) { - msg(ERROR, "\nCurrent picture: %d Short-term reference picture with POC = %3d seems to have been removed or not correctly decoded.", this->getPOC(), notPresentPoc); + msg(ERROR, "Error: Current picture: %d Short-term reference picture with POC = %3d seems to have been removed or not correctly decoded.\n", this->getPOC(), notPresentPoc); } return notPresentPoc; } @@ -1923,7 +1937,7 @@ int Slice::checkThatAllRefPicsAreAvailable(PicList& rcListPic, const ReferencePi { if (printErrors) { - msg(ERROR, "\nCurrent picture: %d Long-term reference picture with POC = %3d seems to have been removed or not correctly decoded.", this->getPOC(), notPresentPoc); + msg(ERROR, "Error: Current picture: %d Long-term reference picture with POC = %3d seems to have been removed or not correctly decoded.\n", this->getPOC(), notPresentPoc); } *refPicIndex = ii; return notPresentPoc; @@ -1955,7 +1969,7 @@ int Slice::checkThatAllRefPicsAreAvailable(PicList& rcListPic, const ReferencePi { if (printErrors) { - msg(ERROR, "\nCurrent picture: %d Short-term reference picture with POC = %3d seems to have been removed or not correctly decoded.", this->getPOC(), notPresentPoc); + msg(ERROR, "Error: Current picture: %d Short-term reference picture with POC = %3d seems to have been removed or not correctly decoded.\n", this->getPOC(), notPresentPoc); } *refPicIndex = ii; return notPresentPoc; diff --git a/source/Lib/DecoderLib/DecLib.cpp b/source/Lib/DecoderLib/DecLib.cpp index 02b40f218..6452ff0af 100644 --- a/source/Lib/DecoderLib/DecLib.cpp +++ b/source/Lib/DecoderLib/DecLib.cpp @@ -424,11 +424,11 @@ DecLib::DecLib() , m_prevPicPOC(MAX_INT) , m_prevTid0POC(0) , m_bFirstSliceInPicture(true) - , m_firstSliceInSequence{ true } , m_firstSliceInBitstream(true) , m_isFirstAuInCvs( true ) , m_prevSliceSkipped(false) - , m_skippedPOC(0) + , m_skippedPOC(MAX_INT) + , m_skippedLayerID(MAX_INT) , m_lastPOCNoOutputPriorPics(-1) , m_isNoOutputPriorPics(false) , m_lastNoOutputBeforeRecoveryFlag{ false } @@ -463,6 +463,8 @@ DecLib::DecLib() memset(m_prevEOS, false, sizeof(m_prevEOS)); memset(m_accessUnitEos, false, sizeof(m_accessUnitEos)); std::fill_n(m_prevGDRInSameLayerPOC, MAX_VPS_LAYERS, -MAX_INT); + std::fill_n(m_prevGDRInSameLayerRecoveryPOC, MAX_VPS_LAYERS, -MAX_INT); + std::fill_n(m_firstSliceInSequence, MAX_VPS_LAYERS, true); std::fill_n(m_pocCRA, MAX_VPS_LAYERS, -MAX_INT); for (int i = 0; i < MAX_VPS_LAYERS; i++) { @@ -898,13 +900,22 @@ void DecLib::xCreateLostPicture( int iLostPoc, const int layerId ) void DecLib::xCreateUnavailablePicture( const PPS *pps, const int iUnavailablePoc, const bool longTermFlag, const int temporalId, const int layerId, const bool interLayerRefPicFlag ) { - msg(INFO, "\ninserting unavailable poc : %d\n", iUnavailablePoc); + msg(INFO, "Note: Inserting unavailable POC : %d\n", iUnavailablePoc); Picture* cFillPic = xGetNewPicBuffer( *( m_parameterSetManager.getFirstSPS() ), *( m_parameterSetManager.getFirstPPS() ), 0, layerId ); - CHECK(!cFillPic->slices.size(), "No slices in picture"); + cFillPic->cs = new CodingStructure( g_globalUnitCache.cuCache, g_globalUnitCache.puCache, g_globalUnitCache.tuCache ); + cFillPic->cs->sps = m_parameterSetManager.getFirstSPS(); + cFillPic->cs->pps = m_parameterSetManager.getFirstPPS(); + cFillPic->cs->vps = m_parameterSetManager.getVPS(0); + cFillPic->cs->create(cFillPic->cs->sps->getChromaFormatIdc(), Area(0, 0, cFillPic->cs->pps->getPicWidthInLumaSamples(), cFillPic->cs->pps->getPicHeightInLumaSamples()), true, (bool)(cFillPic->cs->sps->getPLTMode())); + cFillPic->allocateNewSlice(); cFillPic->slices[0]->initSlice(); + cFillPic->setDecodingOrderNumber(0); + cFillPic->subLayerNonReferencePictureDueToSTSA = false; + cFillPic->unscaledPic = cFillPic; + uint32_t yFill = 1 << (m_parameterSetManager.getFirstSPS()->getBitDepth(CHANNEL_TYPE_LUMA) - 1); uint32_t cFill = 1 << (m_parameterSetManager.getFirstSPS()->getBitDepth(CHANNEL_TYPE_CHROMA) - 1); cFillPic->getRecoBuf().Y().fill(yFill); @@ -916,7 +927,12 @@ void DecLib::xCreateUnavailablePicture( const PPS *pps, const int iUnavailableP cFillPic->interLayerRefPicFlag = interLayerRefPicFlag; cFillPic->longTerm = longTermFlag; cFillPic->slices[0]->setPOC(iUnavailablePoc); - xUpdatePreviousTid0POC(cFillPic->slices[0]); + cFillPic->poc = iUnavailablePoc; + if( (cFillPic->slices[0]->getTLayer() == 0) && (cFillPic->slices[0]->getNalUnitType() != NAL_UNIT_CODED_SLICE_RASL) && (cFillPic->slices[0]->getNalUnitType() != NAL_UNIT_CODED_SLICE_RADL) ) + { + m_prevTid0POC = cFillPic->slices[0]->getPOC(); + } + cFillPic->reconstructed = true; cFillPic->neededForOutput = false; // picture header is not derived for generated reference picture @@ -955,6 +971,11 @@ void DecLib::checkLayerIdIncludedInCvss() for (auto pic = m_accessUnitPicInfo.begin(); pic != m_accessUnitPicInfo.end(); pic++) { bool layerIdFind; + if ( m_firstAccessUnitPicInfo.size() == 0 ) + { + msg( NOTICE, "Note: checkIncludedInFirstAu(), m_firstAccessUnitPicInfo.size() is 0.\n"); + continue; + } for (auto picFirst = m_firstAccessUnitPicInfo.begin(); picFirst != m_firstAccessUnitPicInfo.end(); picFirst++) { layerIdFind = pic->m_nuhLayerId == picFirst->m_nuhLayerId ? true : false; @@ -2086,6 +2107,11 @@ bool DecLib::xDecodeSlice(InputNALUnit &nalu, int &iSkipFrame, int iPOCLastDispl m_accessUnitNoOutputPriorPicFlags.push_back(m_apcSlicePilot->getNoOutputOfPriorPicsFlag()); } + if (m_picHeader.getGdrPicFlag()) + { + m_prevGDRInSameLayerRecoveryPOC[nalu.m_nuhLayerId] = m_picHeader.getRecoveryPocCnt(); + } + PPS *pps = m_parameterSetManager.getPPS(m_picHeader.getPPSId()); CHECK(pps == 0, "No PPS present"); SPS *sps = m_parameterSetManager.getSPS(pps->getSPSId()); @@ -2282,10 +2308,12 @@ bool DecLib::xDecodeSlice(InputNALUnit &nalu, int &iSkipFrame, int iPOCLastDispl // Skip pictures due to random access - if (isRandomAccessSkipPicture(iSkipFrame, iPOCLastDisplay, pps->getMixedNaluTypesInPicFlag())) + if (isRandomAccessSkipPicture(iSkipFrame, iPOCLastDisplay, pps->getMixedNaluTypesInPicFlag(), nalu.m_nuhLayerId)) { m_prevSliceSkipped = true; m_skippedPOC = m_apcSlicePilot->getPOC(); + m_skippedLayerID = nalu.m_nuhLayerId; + // reset variables for bitstream conformance tests resetAccessUnitNals(); resetAccessUnitApsNals(); @@ -2335,7 +2363,7 @@ bool DecLib::xDecodeSlice(InputNALUnit &nalu, int &iSkipFrame, int iPOCLastDispl { if (m_apcSlicePilot->getRPL0()->isInterLayerRefPic(refPicIndex) == 0) { - xCreateUnavailablePicture( m_apcSlicePilot->getPPS(), lostPoc - 1, m_apcSlicePilot->getRPL0()->isRefPicLongterm( refPicIndex ), m_apcSlicePilot->getPic()->temporalId, m_apcSlicePilot->getPic()->layerId, m_apcSlicePilot->getRPL0()->isInterLayerRefPic( refPicIndex ) ); + xCreateUnavailablePicture( pps, lostPoc, m_apcSlicePilot->getRPL0()->isRefPicLongterm( refPicIndex ), m_apcSlicePilot->getTLayer(), m_apcSlicePilot->getNalUnitLayerId(), m_apcSlicePilot->getRPL0()->isInterLayerRefPic( refPicIndex ) ); } } else @@ -2956,6 +2984,11 @@ bool DecLib::decode(InputNALUnit& nalu, int& iSkipFrame, int& iPOCLastDisplay, i case NAL_UNIT_SUFFIX_SEI: if (m_pcPic) { + if ( m_prevSliceSkipped ) + { + msg( NOTICE, "Note: received suffix SEI but current picture is skipped.\n"); + return false; + } m_pictureSeiNalus.push_back(new InputNALUnit(nalu)); m_accessUnitSeiTids.push_back(nalu.m_temporalId); const SPS *sps = m_parameterSetManager.getActiveSPS(); @@ -2987,6 +3020,7 @@ bool DecLib::decode(InputNALUnit& nalu, int& iSkipFrame, int& iPOCLastDisplay, i m_associatedIRAPType[nalu.m_nuhLayerId] = NAL_UNIT_INVALID; m_pocCRA[nalu.m_nuhLayerId] = -MAX_INT; m_prevGDRInSameLayerPOC[nalu.m_nuhLayerId] = -MAX_INT; + m_prevGDRInSameLayerRecoveryPOC[nalu.m_nuhLayerId] = -MAX_INT; std::fill_n(m_prevGDRSubpicPOC[nalu.m_nuhLayerId], MAX_NUM_SUB_PICS, -MAX_INT); std::fill_n(m_prevIRAPSubpicPOC[nalu.m_nuhLayerId], MAX_NUM_SUB_PICS, -MAX_INT); memset(m_prevIRAPSubpicDecOrderNo[nalu.m_nuhLayerId], 0, sizeof(int)*MAX_NUM_SUB_PICS); @@ -3055,11 +3089,22 @@ bool DecLib::decode(InputNALUnit& nalu, int& iSkipFrame, int& iPOCLastDisplay, i * equal to or greater than the random access point POC is attempted. For non IDR/CRA/BLA random * access point there is no guarantee that the decoder will not crash. */ -bool DecLib::isRandomAccessSkipPicture( int& iSkipFrame, int& iPOCLastDisplay, bool mixedNaluInPicFlag ) +bool DecLib::isRandomAccessSkipPicture( int& iSkipFrame, int& iPOCLastDisplay, bool mixedNaluInPicFlag, uint32_t layerId ) { + if( (iSkipFrame > 0) && + (m_apcSlicePilot->getFirstCtuRsAddrInSlice() == 0 && layerId == 0) && + (m_skippedPOC != MAX_INT) && (m_skippedLayerID != MAX_INT)) + { + // When skipFrame count greater than 0, and current frame is not the first frame of sequence, decrement skipFrame count. + // If skipFrame count is still greater than 0, the current frame will be skipped. + iSkipFrame--; + } + if (iSkipFrame) { iSkipFrame--; // decrement the counter + m_maxDecSubPicIdx = 0; + m_maxDecSliceAddrInSubPic = -1; return true; } else if ( m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_IDR_W_RADL || m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_IDR_N_LP ) @@ -3068,7 +3113,7 @@ bool DecLib::isRandomAccessSkipPicture( int& iSkipFrame, int& iPOCLastDisplay, b } else if (m_pocRandomAccess == MAX_INT) // start of random access point, m_pocRandomAccess has not been set yet. { - if (m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_CRA || ( m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_GDR && m_apcSlicePilot->getPicHeader()->getRecoveryPocCnt() == 0 ) ) + if (m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_CRA || m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_GDR ) { // set the POC random access since we need to skip the reordered pictures in the case of CRA/CRANT/BLA/BLANT. m_pocRandomAccess = m_apcSlicePilot->getPOC(); @@ -3077,9 +3122,12 @@ bool DecLib::isRandomAccessSkipPicture( int& iSkipFrame, int& iPOCLastDisplay, b { if(!m_warningMessageSkipPicture) { - msg( WARNING, "\nWarning: this is not a valid random access point and the data is discarded until the first CRA picture"); + msg( WARNING, "Warning: This is not a valid random access point and the data is discarded until the first CRA or GDR picture\n"); m_warningMessageSkipPicture = true; } + iSkipFrame--; + m_maxDecSubPicIdx = 0; + m_maxDecSliceAddrInSubPic = -1; return true; } } @@ -3089,6 +3137,9 @@ bool DecLib::isRandomAccessSkipPicture( int& iSkipFrame, int& iPOCLastDisplay, b mixedNaluInPicFlag)) { iPOCLastDisplay++; + iSkipFrame--; + m_maxDecSubPicIdx = 0; + m_maxDecSliceAddrInSubPic = -1; return true; } // if we reach here, then the picture is not skipped. diff --git a/source/Lib/DecoderLib/DecLib.h b/source/Lib/DecoderLib/DecLib.h index 0d13e56f3..3c02b7ead 100644 --- a/source/Lib/DecoderLib/DecLib.h +++ b/source/Lib/DecoderLib/DecLib.h @@ -73,6 +73,7 @@ private: GeneralHrdParams m_prevGeneralHrdParams; int m_prevGDRInSameLayerPOC[MAX_VPS_LAYERS]; ///< POC number of the latest GDR picture + int m_prevGDRInSameLayerRecoveryPOC[MAX_VPS_LAYERS]; ///< Recovery POC number of the latest GDR picture NalUnitType m_associatedIRAPType[MAX_VPS_LAYERS]; ///< NAL unit type of the previous IRAP picture int m_pocCRA[MAX_VPS_LAYERS]; ///< POC number of the previous CRA picture int m_associatedIRAPDecodingOrderNumber[MAX_VPS_LAYERS]; ///< Decoding order number of the previous IRAP picture @@ -119,7 +120,7 @@ private: #if JVET_J0090_MEMORY_BANDWITH_MEASURE CacheModel m_cacheModel; #endif - bool isRandomAccessSkipPicture(int& iSkipFrame, int& iPOCLastDisplay, bool mixedNaluInPicFlag); + bool isRandomAccessSkipPicture(int& iSkipFrame, int& iPOCLastDisplay, bool mixedNaluInPicFlag, uint32_t layerId); Picture* m_pcPic; uint32_t m_uiSliceSegmentIdx; uint32_t m_prevLayerID; @@ -133,6 +134,7 @@ private: bool m_accessUnitEos[MAX_VPS_LAYERS]; bool m_prevSliceSkipped; int m_skippedPOC; + uint32_t m_skippedLayerID; int m_lastPOCNoOutputPriorPics; bool m_isNoOutputPriorPics; bool m_lastNoOutputBeforeRecoveryFlag[MAX_VPS_LAYERS]; //value of variable NoOutputBeforeRecoveryFlag of the assocated CRA/GDR pic @@ -228,6 +230,7 @@ public: void updateAssociatedIRAP(); void updatePrevGDRInSameLayer(); void updatePrevIRAPAndGDRSubpic(); + bool getGDRRecoveryPocReached() { return ( m_pcPic->getPOC() >= m_prevGDRInSameLayerPOC[m_pcPic->layerId] + m_prevGDRInSameLayerRecoveryPOC[m_pcPic->layerId] ); } #if JVET_S0078_NOOUTPUTPRIORPICFLAG bool getAudIrapOrGdrAuFlag() const { return m_audIrapOrGdrAuFlag; } -- GitLab