diff --git a/source/App/DecoderApp/DecApp.cpp b/source/App/DecoderApp/DecApp.cpp index 0c029914ab1f569a1f7bb330d057614839943144..3424e6ea64d489006c474c00a36407b85292ba0a 100644 --- a/source/App/DecoderApp/DecApp.cpp +++ b/source/App/DecoderApp/DecApp.cpp @@ -122,7 +122,11 @@ uint32_t DecApp::decode() } // main decoder loop +#if JVET_P0125_EOS_LAYER_SPECIFIC + bool loopFiltered[MAX_VPS_LAYERS] = { 0 }; +#else bool loopFiltered = false; +#endif bool bPicSkipped = false; @@ -207,23 +211,42 @@ uint32_t DecApp::decode() } } - +#if JVET_P0125_EOS_LAYER_SPECIFIC + if ((bNewPicture || !bitstreamFile || nalu.m_nalUnitType == NAL_UNIT_EOS) && !m_cDecLib.getFirstSliceInSequence(nalu.m_nuhLayerId) && !bPicSkipped) +#else if ((bNewPicture || !bitstreamFile || nalu.m_nalUnitType == NAL_UNIT_EOS) && !m_cDecLib.getFirstSliceInSequence() && !bPicSkipped) +#endif { +#if JVET_P0125_EOS_LAYER_SPECIFIC + if (!loopFiltered[nalu.m_nuhLayerId] || bitstreamFile) +#else if (!loopFiltered || bitstreamFile) +#endif { m_cDecLib.executeLoopFilters(); m_cDecLib.finishPicture( poc, pcListPic ); } +#if JVET_P0125_EOS_LAYER_SPECIFIC + loopFiltered[nalu.m_nuhLayerId] = (nalu.m_nalUnitType == NAL_UNIT_EOS); +#else loopFiltered = (nalu.m_nalUnitType == NAL_UNIT_EOS); +#endif if (nalu.m_nalUnitType == NAL_UNIT_EOS) { +#if JVET_P0125_EOS_LAYER_SPECIFIC + m_cDecLib.setFirstSliceInSequence(true, nalu.m_nuhLayerId); +#else m_cDecLib.setFirstSliceInSequence(true); +#endif } } else if ( (bNewPicture || !bitstreamFile || nalu.m_nalUnitType == NAL_UNIT_EOS ) && +#if JVET_P0125_EOS_LAYER_SPECIFIC + m_cDecLib.getFirstSliceInSequence(nalu.m_nuhLayerId)) +#else m_cDecLib.getFirstSliceInSequence () ) +#endif { m_cDecLib.setFirstSliceInPicture (true); } diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h index 03b4c827d26e0ea0887fa932410760c407bbd80e..ddbbff462bde5acb4ce07de0a4271a584eeb8ba4 100644 --- a/source/Lib/CommonLib/TypeDef.h +++ b/source/Lib/CommonLib/TypeDef.h @@ -52,6 +52,8 @@ #define JVET_Q0416_WRAPAROUND_OFFSET 1 //JVET-Q0416: subtract (CtbSizeY / MinCbSizeY + 2) from wraparound offset before signaling +#define JVET_P0125_EOS_LAYER_SPECIFIC 1 // JVET-P0125: Specify EOS NAL units to be layer specific + #define JVET_Q0482_REMOVE_CONSTANT_PARAMS 1 // JVET-Q0482: Remove constant slice header parameter settings in PPS #define JVET_Q0505_CHROAM_QM_SIGNALING_400 1 //JVET-Q0505: Cleanup of chroma quantization matrix signaling for 400 color format diff --git a/source/Lib/DecoderLib/DecLib.cpp b/source/Lib/DecoderLib/DecLib.cpp index 1ab78f0beb0aebc7e078cc48f46acbbdb8d21044..7da085fc3446f050d4f73f460691ce6575451624 100644 --- a/source/Lib/DecoderLib/DecLib.cpp +++ b/source/Lib/DecoderLib/DecLib.cpp @@ -62,7 +62,11 @@ bool tryDecodePicture( Picture* pcEncPic, const int expectedPoc, const std::stri PicList* pcListPic = NULL; static bool bFirstCall = true; /* TODO: MT */ +#if JVET_P0125_EOS_LAYER_SPECIFIC + static bool loopFiltered[MAX_VPS_LAYERS] = { false }; /* TODO: MT */ +#else static bool loopFiltered = false; /* TODO: MT */ +#endif static int iPOCLastDisplay = -MAX_INT; /* TODO: MT */ static std::ifstream* bitstreamFile = nullptr; /* TODO: MT */ @@ -147,9 +151,17 @@ bool tryDecodePicture( Picture* pcEncPic, const int expectedPoc, const std::stri } } +#if JVET_P0125_EOS_LAYER_SPECIFIC + if ((bNewPicture || !*bitstreamFile || nalu.m_nalUnitType == NAL_UNIT_EOS) && !pcDecLib->getFirstSliceInSequence(nalu.m_nuhLayerId)) +#else if( ( bNewPicture || !*bitstreamFile || nalu.m_nalUnitType == NAL_UNIT_EOS ) && !pcDecLib->getFirstSliceInSequence() ) +#endif { +#if JVET_P0125_EOS_LAYER_SPECIFIC + if (!loopFiltered[nalu.m_nuhLayerId] || *bitstreamFile) +#else if( !loopFiltered || *bitstreamFile ) +#endif { pcDecLib->finishPictureLight( poc, pcListPic ); @@ -344,14 +356,26 @@ bool tryDecodePicture( Picture* pcEncPic, const int expectedPoc, const std::stri } +#if JVET_P0125_EOS_LAYER_SPECIFIC + loopFiltered[nalu.m_nuhLayerId] = (nalu.m_nalUnitType == NAL_UNIT_EOS); +#else loopFiltered = ( nalu.m_nalUnitType == NAL_UNIT_EOS ); +#endif if( nalu.m_nalUnitType == NAL_UNIT_EOS ) { +#if JVET_P0125_EOS_LAYER_SPECIFIC + pcDecLib->setFirstSliceInSequence(true, nalu.m_nuhLayerId); +#else pcDecLib->setFirstSliceInSequence( true ); +#endif } } +#if JVET_P0125_EOS_LAYER_SPECIFIC + else if ((bNewPicture || !*bitstreamFile || nalu.m_nalUnitType == NAL_UNIT_EOS) && pcDecLib->getFirstSliceInSequence(nalu.m_nuhLayerId)) +#else else if( ( bNewPicture || !*bitstreamFile || nalu.m_nalUnitType == NAL_UNIT_EOS ) && pcDecLib->getFirstSliceInSequence() ) +#endif { pcDecLib->setFirstSliceInPicture( true ); } @@ -369,7 +393,14 @@ bool tryDecodePicture( Picture* pcEncPic, const int expectedPoc, const std::stri pcDecLib = nullptr; } bFirstCall = true; +#if JVET_P0125_EOS_LAYER_SPECIFIC + for (int i = 0; i < MAX_VPS_LAYERS; i++) + { + loopFiltered[i] = false; + } +#else loopFiltered = false; +#endif iPOCLastDisplay = -MAX_INT; if( bytestream ) @@ -421,7 +452,11 @@ DecLib::DecLib() , m_prevPOC(MAX_INT) , m_prevTid0POC(0) , m_bFirstSliceInPicture(true) +#if JVET_P0125_EOS_LAYER_SPECIFIC + , m_bFirstSliceInSequence{ true } +#else , m_bFirstSliceInSequence(true) +#endif , m_prevSliceSkipped(false) , m_skippedPOC(0) , m_bFirstSliceInBitstream(true) @@ -1580,9 +1615,15 @@ bool DecLib::xDecodeSlice(InputNALUnit &nalu, int &iSkipFrame, int iPOCLastDispl //For inference of NoOutputOfPriorPicsFlag if (m_apcSlicePilot->getRapPicFlag() || m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_GDR) { +#if JVET_P0125_EOS_LAYER_SPECIFIC + if ((m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_CRA && m_bFirstSliceInSequence[nalu.m_nuhLayerId]) || + (m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_CRA && m_apcSlicePilot->getHandleCraAsCvsStartFlag()) || + (m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_GDR && m_bFirstSliceInSequence[nalu.m_nuhLayerId])) +#else if ((m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_CRA && m_bFirstSliceInSequence) || (m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_CRA && m_apcSlicePilot->getHandleCraAsCvsStartFlag()) || (m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_GDR && m_bFirstSliceInSequence)) +#endif { m_apcSlicePilot->setNoIncorrectPicOutputFlag(true); } @@ -1680,7 +1721,11 @@ bool DecLib::xDecodeSlice(InputNALUnit &nalu, int &iSkipFrame, int iPOCLastDispl m_prevSliceSkipped = false; //we should only get a different poc for a new picture (with CTU address==0) +#if JVET_P0125_EOS_LAYER_SPECIFIC + if (m_apcSlicePilot->getPOC() != m_prevPOC && !m_bFirstSliceInSequence[nalu.m_nuhLayerId] && (m_apcSlicePilot->getFirstCtuRsAddrInSlice() != 0)) +#else if(m_apcSlicePilot->getPOC() != m_prevPOC && !m_bFirstSliceInSequence && (m_apcSlicePilot->getFirstCtuRsAddrInSlice() != 0)) +#endif { msg( WARNING, "Warning, the first slice of a picture might have been lost!\n"); } @@ -1746,7 +1791,11 @@ bool DecLib::xDecodeSlice(InputNALUnit &nalu, int &iSkipFrame, int iPOCLastDispl // actual decoding starts here xActivateParameterSets( nalu.m_nuhLayerId ); +#if JVET_P0125_EOS_LAYER_SPECIFIC + m_bFirstSliceInSequence[nalu.m_nuhLayerId] = false; +#else m_bFirstSliceInSequence = false; +#endif m_bFirstSliceInBitstream = false; diff --git a/source/Lib/DecoderLib/DecLib.h b/source/Lib/DecoderLib/DecLib.h index 4f60dc1840d5828f5040ed0a64d6ecfeb12e1142..a388bd9f9cdb22faff4ed8a081de206fbb42ec3f 100644 --- a/source/Lib/DecoderLib/DecLib.h +++ b/source/Lib/DecoderLib/DecLib.h @@ -111,7 +111,11 @@ private: int m_prevPOC; int m_prevTid0POC; bool m_bFirstSliceInPicture; +#if JVET_P0125_EOS_LAYER_SPECIFIC + bool m_bFirstSliceInSequence[MAX_VPS_LAYERS]; +#else bool m_bFirstSliceInSequence; +#endif bool m_prevSliceSkipped; int m_skippedPOC; bool m_bFirstSliceInBitstream; @@ -183,8 +187,13 @@ public: void setNoOutputPriorPicsFlag (bool val) { m_isNoOutputPriorPics = val; } void setFirstSliceInPicture (bool val) { m_bFirstSliceInPicture = val; } bool getFirstSliceInPicture () const { return m_bFirstSliceInPicture; } +#if JVET_P0125_EOS_LAYER_SPECIFIC + bool getFirstSliceInSequence(int layer) const { return m_bFirstSliceInSequence[layer]; } + void setFirstSliceInSequence(bool val, int layer) { m_bFirstSliceInSequence[layer] = val; } +#else bool getFirstSliceInSequence () const { return m_bFirstSliceInSequence; } void setFirstSliceInSequence (bool val) { m_bFirstSliceInSequence = val; } +#endif void setDecodedSEIMessageOutputStream(std::ostream *pOpStream) { m_pDecodedSEIOutputStream = pOpStream; } uint32_t getNumberOfChecksumErrorsDetected() const { return m_numberOfChecksumErrorsDetected; }