diff --git a/source/App/DecoderApp/DecApp.cpp b/source/App/DecoderApp/DecApp.cpp index 2bc5fc91f04b74ae174a02360dc721618761659d..a1e1abf51dcd5f57323bc02391543750a22ab153 100644 --- a/source/App/DecoderApp/DecApp.cpp +++ b/source/App/DecoderApp/DecApp.cpp @@ -286,10 +286,12 @@ uint32_t DecApp::decode() { m_cDecLib.CheckNoOutputPriorPicFlagsInAccessUnit(); m_cDecLib.resetAccessUnitNoOutputPriorPicFlags(); + m_cDecLib.checkLayerIdIncludedInCvss(); + m_cDecLib.resetAccessUnitEos(); + m_cDecLib.resetAudIrapOrGdrAuFlag(); } if(bNewAccessUnit) { - m_cDecLib.isCvsStart(); m_cDecLib.checkTidLayerIdInAccessUnit(); m_cDecLib.resetAccessUnitSeiTids(); m_cDecLib.checkSEIInAccessUnit(); diff --git a/source/Lib/DecoderLib/DecLib.cpp b/source/Lib/DecoderLib/DecLib.cpp index 13db0951a4baab7eafbdaaeab9ab8a750c944c55..754e86dd1d350f5e64641794026451121774bec0 100644 --- a/source/Lib/DecoderLib/DecLib.cpp +++ b/source/Lib/DecoderLib/DecLib.cpp @@ -427,6 +427,7 @@ DecLib::DecLib() , m_bFirstSliceInPicture(true) , m_firstSliceInSequence{ true } , m_firstSliceInBitstream(true) + , m_isFirstAuInCvs( true ) , m_prevSliceSkipped(false) , m_skippedPOC(0) , m_lastPOCNoOutputPriorPics(-1) @@ -434,6 +435,7 @@ DecLib::DecLib() , m_lastNoOutputBeforeRecoveryFlag{ false } , m_sliceLmcsApsId(-1) , m_pDecodedSEIOutputStream(NULL) + , m_audIrapOrGdrAuFlag( false ) , m_decodedPictureHashSEIEnabled(false) , m_numberOfChecksumErrorsDetected(0) , m_warningMessageSkipPicture(false) @@ -451,6 +453,7 @@ DecLib::DecLib() #if ENABLE_SIMD_OPT_BUFFER g_pelBufOP.initPelBufOpsX86(); #endif + memset(m_accessUnitEos, false, sizeof(m_accessUnitEos)); for (int i = 0; i < MAX_VPS_LAYERS; i++) { m_associatedIRAPType[i] = NAL_UNIT_INVALID; @@ -886,37 +889,47 @@ void DecLib::xCreateUnavailablePicture(int iUnavailablePoc, bool longTermFlag, c { m_pocRandomAccess = iUnavailablePoc; } - } -void DecLib::isCvsStart() +void DecLib::checkLayerIdIncludedInCvss() { - for (auto pic = m_accessUnitPicInfo.begin(); pic != m_accessUnitPicInfo.end(); pic++) + if (getVPS() == nullptr || getVPS()->getMaxLayers() == 1) + { + return; + } + + if (m_audIrapOrGdrAuFlag && + (m_isFirstAuInCvs || m_accessUnitPicInfo.begin()->m_nalUnitType == NAL_UNIT_CODED_SLICE_IDR_N_LP || m_accessUnitPicInfo.begin()->m_nalUnitType == NAL_UNIT_CODED_SLICE_IDR_W_RADL)) { - if (pic->m_nalUnitType != NAL_UNIT_CODED_SLICE_IDR_N_LP && pic->m_nalUnitType != NAL_UNIT_CODED_SLICE_IDR_W_RADL) + // store layerIDs in the first AU + m_firstAccessUnitPicInfo.assign(m_accessUnitPicInfo.begin(), m_accessUnitPicInfo.end()); + } + else + { + // check whether the layerIDs in an AU are included in the layerIDs of the first AU + for (auto pic = m_accessUnitPicInfo.begin(); pic != m_accessUnitPicInfo.end(); pic++) { - checkIncludedInFirstAu(); - return; + bool layerIdFind; + for (auto picFirst = m_firstAccessUnitPicInfo.begin(); picFirst != m_firstAccessUnitPicInfo.end(); picFirst++) + { + layerIdFind = pic->m_nuhLayerId == picFirst->m_nuhLayerId ? true : false; + if (layerIdFind) + { + break; + } + } + CHECK(!layerIdFind, "each picture in an AU in a CVS shall have nuh_layer_id equal to the nuh_layer_id of one of the pictures present in the first AU of the CVS"); } } - //save the first AU info for a CVS start - m_firstAccessUnitPicInfo.assign(m_accessUnitPicInfo.begin(), m_accessUnitPicInfo.end()); -} -void DecLib::checkIncludedInFirstAu() -{ + // update the value of m_isFirstAuInCvs for the next AU according to NAL_UNIT_EOS in each layer for (auto pic = m_accessUnitPicInfo.begin(); pic != m_accessUnitPicInfo.end(); pic++) { - bool isFind = 0; - for (auto picFirst = m_firstAccessUnitPicInfo.begin(); picFirst != m_firstAccessUnitPicInfo.end(); picFirst++) + m_isFirstAuInCvs = m_accessUnitEos[pic->m_nuhLayerId] ? true : false; + if(!m_isFirstAuInCvs) { - if (pic->m_nuhLayerId == picFirst->m_nuhLayerId) - { - isFind = 1; - break; - } + break; } - CHECK(!isFind, "each picture in an AU in a CVS shall have nuh_layer_id equal to the nuh_layer_id of one of the pictures present in the first AU of the CVS"); } } @@ -2712,14 +2725,14 @@ bool DecLib::decode(InputNALUnit& nalu, int& iSkipFrame, int& iPOCLastDisplay, i m_prevPOC = MAX_INT; m_prevSliceSkipped = false; m_skippedPOC = 0; + m_accessUnitEos[nalu.m_nuhLayerId] = true; return false; case NAL_UNIT_ACCESS_UNIT_DELIMITER: { AUDReader audReader; uint32_t picType; - uint32_t audIrapOrGdrAuFlag; - audReader.parseAccessUnitDelimiter(&(nalu.getBitstream()), audIrapOrGdrAuFlag, picType); + audReader.parseAccessUnitDelimiter(&(nalu.getBitstream()), m_audIrapOrGdrAuFlag, picType); return !m_bFirstSliceInPicture; } diff --git a/source/Lib/DecoderLib/DecLib.h b/source/Lib/DecoderLib/DecLib.h index 2a1995739d1117855eaf01a04f310f1f10c9f5e9..bb721bfca5732bdd884607a8d8b3ae992fa32dae 100644 --- a/source/Lib/DecoderLib/DecLib.h +++ b/source/Lib/DecoderLib/DecLib.h @@ -125,6 +125,8 @@ private: bool m_bFirstSliceInPicture; bool m_firstSliceInSequence[MAX_VPS_LAYERS]; bool m_firstSliceInBitstream; + bool m_isFirstAuInCvs; + bool m_accessUnitEos[MAX_VPS_LAYERS]; bool m_prevSliceSkipped; int m_skippedPOC; int m_lastPOCNoOutputPriorPics; @@ -132,6 +134,7 @@ private: bool m_lastNoOutputBeforeRecoveryFlag[MAX_VPS_LAYERS]; //value of variable NoOutputBeforeRecoveryFlag of the assocated CRA/GDR pic int m_sliceLmcsApsId; //value of LmcsApsId, constraint is same id for all slices in one picture std::ostream *m_pDecodedSEIOutputStream; + uint32_t m_audIrapOrGdrAuFlag; int m_decodedPictureHashSEIEnabled; ///< Checksum(3)/CRC(2)/MD5(1)/disable(0) acting on decoded picture hash SEI message uint32_t m_numberOfChecksumErrorsDetected; @@ -229,11 +232,12 @@ public: void resetAccessUnitPicInfo() { m_accessUnitPicInfo.clear(); } void resetAccessUnitApsNals() { m_accessUnitApsNals.clear(); } void resetAccessUnitSeiTids() { m_accessUnitSeiTids.clear(); } + void resetAudIrapOrGdrAuFlag() { m_audIrapOrGdrAuFlag = false; } + void resetAccessUnitEos() { memset(m_accessUnitEos, false, sizeof(m_accessUnitEos)); } void checkTidLayerIdInAccessUnit(); void resetAccessUnitSeiPayLoadTypes() { m_accessUnitSeiPayLoadTypes.clear(); } void checkSEIInAccessUnit(); - void isCvsStart(); - void checkIncludedInFirstAu(); + void checkLayerIdIncludedInCvss(); void CheckNoOutputPriorPicFlagsInAccessUnit(); void resetAccessUnitNoOutputPriorPicFlags() { m_accessUnitNoOutputPriorPicFlags.clear(); } void checkSeiInPictureUnit(); @@ -254,6 +258,7 @@ public: void setAPSMapEnc( ParameterSetMap<APS>* apsMap ) { m_apsMapEnc = apsMap; } bool isNewPicture( std::ifstream *bitstreamFile, class InputByteStream *bytestream ); bool isNewAccessUnit( bool newPicture, std::ifstream *bitstreamFile, class InputByteStream *bytestream ); + protected: void xUpdateRasInit(Slice* slice);