diff --git a/source/Lib/CommonLib/Slice.cpp b/source/Lib/CommonLib/Slice.cpp index a09e25920e63433f0e69700b131cf9bf71325108..ca8864bcc3efbdfe34336b022579d4d0068b3913 100644 --- a/source/Lib/CommonLib/Slice.cpp +++ b/source/Lib/CommonLib/Slice.cpp @@ -1953,6 +1953,9 @@ SPSRExt::SPSRExt() SPS::SPS() : m_SPSId ( 0) , m_decodingParameterSetId ( 0 ) +#if JVET_P0205_VPS_ID_0 +, m_VPSId ( 0 ) +#endif , m_affineAmvrEnabledFlag ( false ) , m_DMVR ( false ) , m_MMVD ( false ) @@ -2999,8 +3002,14 @@ ParameterSetManager::ParameterSetManager() , m_ppsMap(MAX_NUM_PPS) , m_apsMap(MAX_NUM_APS * MAX_NUM_APS_TYPE) , m_dpsMap(MAX_NUM_DPS) +#if JVET_P0205_VPS_ID_0 +, m_vpsMap(MAX_NUM_VPS) +#endif , m_activeDPSId(-1) , m_activeSPSId(-1) +#if JVET_P0205_VPS_ID_0 +, m_activeVPSId(-1) +#endif { } @@ -3081,6 +3090,29 @@ bool ParameterSetManager::activatePPS(int ppsId, bool isIRAP) } } +#if JVET_P0205_VPS_ID_0 + int vpsId = sps->getVPSId(); + if(vpsId != 0) + { + VPS *vps = m_vpsMap.getPS(vpsId); + if(vps) + { + m_activeVPSId = vpsId; + m_vpsMap.setActive(vpsId); + } + else + { + msg( WARNING, "Warning: tried to activate PPS that refers to non-existing VPS." ); + } + } + else + { + //No actual VPS + m_activeVPSId = -1; + m_vpsMap.clear(); + } +#endif + m_spsMap.clear(); m_spsMap.setActive(spsId); m_activeSPSId = spsId; diff --git a/source/Lib/CommonLib/Slice.h b/source/Lib/CommonLib/Slice.h index eaf9f055efffc2d8b5150635e58481692baeac1c..525470cfbd9fea89dfce6905bef1a28a48f48249 100644 --- a/source/Lib/CommonLib/Slice.h +++ b/source/Lib/CommonLib/Slice.h @@ -883,6 +883,9 @@ class SPS private: int m_SPSId; int m_decodingParameterSetId; +#if JVET_P0205_VPS_ID_0 + int m_VPSId; +#endif bool m_affineAmvrEnabledFlag; bool m_DMVR; @@ -1033,6 +1036,11 @@ public: void setSPSId(int i) { m_SPSId = i; } void setDecodingParameterSetId(int val) { m_decodingParameterSetId = val; } int getDecodingParameterSetId() const { return m_decodingParameterSetId; } +#if JVET_P0205_VPS_ID_0 + int getVPSId() const { return m_VPSId; } + void setVPSId(int i) { m_VPSId = i; } +#endif + ChromaFormat getChromaFormatIdc () const { return m_chromaFormatIdc; } void setChromaFormatIdc (ChromaFormat i) { m_chromaFormatIdc = i; } #if JVET_P1006_PICTURE_HEADER @@ -2744,6 +2752,7 @@ public: bool getDPSChangedFlag(int dpsId) const { return m_dpsMap.getChangedFlag(dpsId); } void clearDPSChangedFlag(int dpsId) { m_dpsMap.clearChangedFlag(dpsId); } DPS* getFirstDPS() { return m_dpsMap.getFirstPS(); }; + //! store sequence parameter set and take ownership of it void storeSPS(SPS *sps, const std::vector<uint8_t> &naluData) { m_spsMap.storePS( sps->getSPSId(), sps, &naluData); }; //! get pointer to existing sequence parameter set @@ -2785,11 +2794,17 @@ protected: ParameterSetMap<PPS> m_ppsMap; ParameterSetMap<APS> m_apsMap; ParameterSetMap<DPS> m_dpsMap; +#if JVET_P0205_VPS_ID_0 + ParameterSetMap<VPS> m_vpsMap; +#endif APS* m_apss[ALF_CTB_MAX_NUM_APS]; int m_activeDPSId; // -1 for nothing active int m_activeSPSId; // -1 for nothing active +#if JVET_P0205_VPS_ID_0 + int m_activeVPSId; // -1 for nothing active +#endif }; class PreCalcValues diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h index 11a3a8b3c7cc66e8ea9bb0db11f7cf3425ebbf61..2ecb6695793dc05830e69573497a97cdcbe768a2 100644 --- a/source/Lib/CommonLib/TypeDef.h +++ b/source/Lib/CommonLib/TypeDef.h @@ -50,6 +50,8 @@ #include <assert.h> #include <cassert> +#define JVET_P0205_VPS_ID_0 1 // JVET-P0205: VPS ID zero in SPS means no VPS in bitstream + #define JVET_P1006_PICTURE_HEADER 1 // JVET-P1006: Add picture header and related syntax changes #define JVET_P0365_SCALING_MATRIX_LFNST 1 // JVET-P0365: Signal flag to indicate whether scaling matrices are used for LFNST-coded blocks diff --git a/source/Lib/DecoderLib/VLCReader.cpp b/source/Lib/DecoderLib/VLCReader.cpp index cb58d4d29b7d319544ff1fa39505caee1a062004..b9c50fc07aa640940637d31988249fd1124ef245 100644 --- a/source/Lib/DecoderLib/VLCReader.cpp +++ b/source/Lib/DecoderLib/VLCReader.cpp @@ -1214,6 +1214,9 @@ void HLSyntaxReader::parseSPS(SPS* pcSPS) xTraceSPSHeader (); #endif READ_CODE( 4, uiCode, "sps_decoding_parameter_set_id"); pcSPS->setDecodingParameterSetId( uiCode ); +#if JVET_P0205_VPS_ID_0 + READ_CODE( 4, uiCode, "sps_video_parameter_set_id" ); pcSPS->setVPSId( uiCode ); +#endif READ_CODE(3, uiCode, "sps_max_sub_layers_minus1"); pcSPS->setMaxTLayers (uiCode + 1); CHECK(uiCode > 6, "Invalid maximum number of T-layer signalled"); READ_CODE(5, uiCode, "sps_reserved_zero_5bits"); @@ -1779,7 +1782,14 @@ void HLSyntaxReader::parseVPS(VPS* pcVPS) #endif uint32_t uiCode; +#if JVET_P0205_VPS_ID_0 + READ_CODE(4, uiCode, "vps_video_parameter_set_id"); + CHECK( uiCode == 0, "vps_video_parameter_set_id equal to zero is reserved and shall not be used in a bitstream" ); + pcVPS->setVPSId(uiCode); +#else READ_CODE(4, uiCode, "vps_video_parameter_set_id"); pcVPS->setVPSId(uiCode); +#endif + READ_CODE(8, uiCode, "vps_max_layers_minus1"); pcVPS->setMaxLayers(uiCode + 1); CHECK(uiCode + 1 > MAX_VPS_LAYERS, "Invalid code"); for (uint32_t i = 0; i <= pcVPS->getMaxLayers() - 1; i++) { diff --git a/source/Lib/EncoderLib/EncGOP.cpp b/source/Lib/EncoderLib/EncGOP.cpp index c3c4526fc6d996d8217a3fd8e252a1c3669899cc..9f85f0a1383a83eadc8c8c0479ba50517eee24f9 100644 --- a/source/Lib/EncoderLib/EncGOP.cpp +++ b/source/Lib/EncoderLib/EncGOP.cpp @@ -383,6 +383,9 @@ int EncGOP::xWriteParameterSets( AccessUnit &accessUnit, Slice *slice, const boo #if JVET_N0278_FIXES if( bSeqFirst ) { +#if JVET_P0205_VPS_ID_0 + if (slice->getSPS()->getVPSId() != 0) +#endif actualTotalBits += xWriteVPS( accessUnit, m_pcEncLib->getVPS() ); actualTotalBits += xWriteDPS( accessUnit, m_pcEncLib->getDPS() ); @@ -397,8 +400,12 @@ int EncGOP::xWriteParameterSets( AccessUnit &accessUnit, Slice *slice, const boo { actualTotalBits += xWritePPS( accessUnit, slice->getPPS(), slice->getSPS(), m_pcEncLib->getLayerId() ); } +#if JVET_P0205_VPS_ID_0 + // No VPS in the bitstream if the SPS refers to VPS ID zero + if (bSeqFirst && slice->getSPS()->getVPSId() != 0) #else if (bSeqFirst) +#endif { actualTotalBits += xWriteVPS(accessUnit, m_pcEncLib->getVPS()); } diff --git a/source/Lib/EncoderLib/VLCWriter.cpp b/source/Lib/EncoderLib/VLCWriter.cpp index f129117940551341150f9342216afcc5f1fa46ae..0bd805f5266b228ac130bdeec9a4c5dd824f5671 100644 --- a/source/Lib/EncoderLib/VLCWriter.cpp +++ b/source/Lib/EncoderLib/VLCWriter.cpp @@ -740,6 +740,9 @@ void HLSWriter::codeSPS( const SPS* pcSPS ) xTraceSPSHeader (); #endif WRITE_CODE( pcSPS->getDecodingParameterSetId (), 4, "sps_decoding_parameter_set_id" ); +#if JVET_P0205_VPS_ID_0 + WRITE_CODE( pcSPS->getVPSId(), 4, "sps_video_parameter_set_id" ); +#endif CHECK(pcSPS->getMaxTLayers() == 0, "Maximum number of temporal sub-layers is '0'"); WRITE_CODE(pcSPS->getMaxTLayers() - 1, 3, "sps_max_sub_layers_minus1");