From 33d5f72b9ddb6845b7a9347c93c261cd3650b644 Mon Sep 17 00:00:00 2001
From: vdrugeon <virginie.drugeon@eu.panasonic.com>
Date: Mon, 28 Oct 2019 12:26:58 +0100
Subject: [PATCH] JVET-P0205: VPS ID 0

Constraint that vps_video_parameter_set_id shall be greater than 0
Added that the bitstream does not contain any VPS when
signalled sps_video_parameter_set_id is equal to zero
(was already in VVC Draft, but not in VTM)
---
 source/Lib/CommonLib/Slice.cpp      | 32 +++++++++++++++++++++++++++++
 source/Lib/CommonLib/Slice.h        | 15 ++++++++++++++
 source/Lib/CommonLib/TypeDef.h      |  2 ++
 source/Lib/DecoderLib/VLCReader.cpp | 10 +++++++++
 source/Lib/EncoderLib/EncGOP.cpp    |  7 +++++++
 source/Lib/EncoderLib/VLCWriter.cpp |  3 +++
 6 files changed, 69 insertions(+)

diff --git a/source/Lib/CommonLib/Slice.cpp b/source/Lib/CommonLib/Slice.cpp
index a09e25920..ca8864bcc 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 eaf9f055e..525470cfb 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 11a3a8b3c..2ecb66957 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 cb58d4d29..b9c50fc07 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 c3c4526fc..9f85f0a13 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 f12911794..0bd805f52 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");
-- 
GitLab