From 79bf25c5a62e655bb39172fb835038b8a176f63c Mon Sep 17 00:00:00 2001
From: vdrugeon <virginie.drugeon@eu.panasonic.com>
Date: Thu, 6 Feb 2020 15:04:09 +0000
Subject: [PATCH] JVET-Q0786: PTL part of VPS syntax

Modifications to VPS syntax (signal PTL for single layer OLSs)
PTL part only (HRD part to be implemented by Sharp)
---
 cfg/layers.cfg                      |  6 ++
 doc/software-manual.tex             | 71 ++++++++++++++++++++++++
 source/App/EncoderApp/EncApp.cpp    | 36 ++++++++++++
 source/App/EncoderApp/EncAppCfg.cpp | 16 ++++++
 source/App/EncoderApp/EncAppCfg.h   |  6 ++
 source/Lib/CommonLib/Slice.cpp      | 11 ++++
 source/Lib/CommonLib/Slice.h        | 25 +++++++++
 source/Lib/CommonLib/TypeDef.h      |  2 +
 source/Lib/DecoderLib/VLCReader.cpp | 86 ++++++++++++++++++++++++++++-
 source/Lib/DecoderLib/VLCReader.h   |  4 ++
 source/Lib/EncoderLib/EncLib.cpp    | 14 +++++
 source/Lib/EncoderLib/VLCWriter.cpp | 62 ++++++++++++++++++++-
 source/Lib/EncoderLib/VLCWriter.h   |  4 ++
 13 files changed, 340 insertions(+), 3 deletions(-)

diff --git a/cfg/layers.cfg b/cfg/layers.cfg
index f083583f8..85dd7842a 100644
--- a/cfg/layers.cfg
+++ b/cfg/layers.cfg
@@ -8,12 +8,18 @@ EachLayerIsAnOlsFlag          : 0
 OlsModeIdc                    : 2
 NumOutputLayerSets            : 2
 OlsOutputLayer1               : 1 0
+NumPTLsInVPS                  : 2
 #======== Layer-0 ===============
 LayerId0                      : 0
 #======== Layer-1 ===============
 LayerId1                      : 1
 NumRefLayers1                 : 1
 RefLayerIdx1                  : 0
+#======== OLS-0 ===============
+OlsPTLIdx0                    : 0
+#======== OLS-1 ===============
+LevelPTL1                     : 6.2
+OlsPTLIdx1                    : 1
 
 
 
diff --git a/doc/software-manual.tex b/doc/software-manual.tex
index 6c82974f6..bc084f6d6 100644
--- a/doc/software-manual.tex
+++ b/doc/software-manual.tex
@@ -1114,6 +1114,77 @@ Specifies the value of subpicture subpic_id_mapping_in_sps_flag
 Specifies the value to use to derive the vps_max_layers_minus1 for layered coding
 \\
 
+\Option{MaxSubLayers} &
+%\ShortOption{\None} &
+\Default{1} &
+Specifies the maximum number of temporal sublayers to signal in the VPS
+\\
+
+\Option{AllLayersSameNumSublayersFlag} &
+%\ShortOption{\None} &
+\Default{true} &
+Specifies the value of vps_all_layers_same_num_sublayers_flag in the VPS
+\\
+
+\Option{LayerId\emph{i}} &
+%\ShortOption{\None} &
+\Default{0} &
+Specifies the nuh_layer_id of the i-th layer (with i an integer greater than 0)
+\\
+
+\Option{NumRefLayers\emph{i}} &
+%\ShortOption{\None} &
+\Default{0} &
+Specifies the number of direct reference layers of the i-th layer (with i an integer greater than 0)
+\\
+
+\Option{RefLayerIdx\emph{i}} &
+%\ShortOption{\None} &
+\Default{""} &
+Specifies a list of indexes of the reference layers of the i-th layer (with i an integer greater than 0)
+\\
+
+\Option{EachLayerIsAnOlsFlag} &
+%\ShortOption{\None} &
+\Default{true} &
+Specifies the value of each_layer_is_an_ols_flag in the VPS
+\\
+
+\Option{OlsModeIdc} &
+%\ShortOption{\None} &
+\Default{0} &
+Specifies the value of ols_mode_idc in the VPS
+\\
+
+\Option{NumOutputLayerSets} &
+%\ShortOption{\None} &
+\Default{1} &
+Specifies the number of output layer sets (OLS) signalled in the VPS
+\\
+
+\Option{OlsOutputLayer\emph{i}} &
+%\ShortOption{\None} &
+\Default{""} &
+Specifies a list of indexes of the output layers of the i-th OLS (with i an integer greater than 0) 
+\\
+
+\Option{NumPTLsInVPS} &
+%\ShortOption{\None} &
+\Default{1} &
+Specifies the number of profile_tier_level (PTL) syntax structures signalled in the VPS 
+\\
+
+\Option{LevelPTL\emph{i}} &
+%\ShortOption{\None} &
+\Default{Level::NONE} &
+Specifies the level to signal in the i-th PTL of the VPS (with i an integer greater than 0) 
+\\
+
+\Option{OlsPTLIdx\emph{i}} &
+%\ShortOption{\None} &
+\Default{0} &
+Specifies the index of the PTL that applies to the i-th OLS (with i an integer greater than 0) 
+\\
 \end{OptionTableNoShorthand}
 
 
diff --git a/source/App/EncoderApp/EncApp.cpp b/source/App/EncoderApp/EncApp.cpp
index 49ab53b7a..09e5acaa2 100644
--- a/source/App/EncoderApp/EncApp.cpp
+++ b/source/App/EncoderApp/EncApp.cpp
@@ -175,6 +175,42 @@ void EncApp::xInitLibCfg()
       }
     }
   }
+#if JVET_Q0786_PTL_only
+  CHECK( m_numPtlsInVps == 0, "There has to be at least one PTL structure in the VPS." );
+  vps.setNumPtls                                                 ( m_numPtlsInVps );
+  vps.setPtPresentFlag                                           (0, 1);
+  for (int i = 0; i < vps.getNumPtls(); i++)
+  {
+    if( i > 0 )
+      vps.setPtPresentFlag                                         (i, 0);
+    vps.setPtlMaxTemporalId                                      (i, vps.getMaxSubLayers() - 1); 
+  }
+  for (int i = 0; i < vps.getNumOutputLayerSets(); i++)
+  {
+    vps.setOlsPtlIdx                                             (i, m_olsPtlIdx[i]);
+  }
+  std::vector<ProfileTierLevel> ptls;
+  ptls.resize(vps.getNumPtls());
+  // PTL0 shall be the same as the one signalled in the SPS
+  ptls[0].setLevelIdc                                            ( m_level );
+  ptls[0].setProfileIdc                                          ( m_profile);
+  ptls[0].setTierFlag                                            ( m_levelTier );
+  ptls[0].setNumSubProfile                                       ( m_numSubProfile );
+  for (int i = 0; i < m_numSubProfile; i++)
+  {
+    ptls[0].setSubProfileIdc                                   (i, m_subProfile[i]);
+  }
+  for(int i = 1; i < vps.getNumPtls(); i++)
+  {
+    ptls[i].setLevelIdc                                          (m_levelPtl[i]);
+  }
+  vps.setProfileTierLevel(ptls);
+  for(int i = 0; i < vps.getMaxLayers(); i++)
+  {
+    vps.setLayerChromaFormatIDC                                  (i, m_chromaFormatIDC);
+    vps.setLayerBitDepth                                         (i, m_internalBitDepth[CHANNEL_TYPE_LUMA]);
+  }
+#endif
   vps.setVPSExtensionFlag                                        ( false );
 #if !JVET_Q0814_DPB
   m_cEncLib.setVPS(&vps);
diff --git a/source/App/EncoderApp/EncAppCfg.cpp b/source/App/EncoderApp/EncAppCfg.cpp
index cac0d4e83..8376e59ba 100644
--- a/source/App/EncoderApp/EncAppCfg.cpp
+++ b/source/App/EncoderApp/EncAppCfg.cpp
@@ -1457,6 +1457,9 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] )
   ( "OlsModeIdc",                                     m_olsModeIdc,                                 0, "Output layer set mode")
   ( "NumOutputLayerSets",                             m_numOutputLayerSets,                         1, "Number of output layer sets")
   ( "OlsOutputLayer%d",                               m_olsOutputLayerStr, string(""), MAX_VPS_LAYERS, "Output layer index of i-th OLS")
+#if JVET_Q0786_PTL_only
+  ( "NumPTLsInVPS",                                   m_numPtlsInVps,                               1, "Number of profile_tier_level structures in VPS" )
+#endif
     ;
 
   opts.addOptions()
@@ -1477,6 +1480,19 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] )
     opts.addOptions()(cOSS.str(), m_GOPList[i-1], GOPEntry());
   }
 
+#if JVET_Q0786_PTL_only
+  for(int i = 0; i < MAX_NUM_OLSS; i++)
+  {
+    std::ostringstream cOSS1;
+    cOSS1<<"LevelPTL"<<i;
+    opts.addOptions()(cOSS1.str(), m_levelPtl[i], Level::NONE);
+
+    std::ostringstream cOSS2;
+    cOSS2<<"OlsPTLIdx"<<i;
+    opts.addOptions()(cOSS2.str(), m_olsPtlIdx[i], 0);
+  }
+#endif
+
   po::setDefaults(opts);
   po::ErrorReporter err;
   const list<const char*>& argv_unhandled = po::scanArgv(opts, argc, (const char**) argv, err);
diff --git a/source/App/EncoderApp/EncAppCfg.h b/source/App/EncoderApp/EncAppCfg.h
index e3c5027e2..b3b7c9e87 100644
--- a/source/App/EncoderApp/EncAppCfg.h
+++ b/source/App/EncoderApp/EncAppCfg.h
@@ -763,6 +763,12 @@ protected:
   int         m_numOutputLayerSets;
   std::string m_olsOutputLayerStr[MAX_VPS_LAYERS];
 
+#if JVET_Q0786_PTL_only
+  int         m_numPtlsInVps;
+  Level::Name m_levelPtl[MAX_NUM_OLSS];
+  int         m_olsPtlIdx[MAX_NUM_OLSS]; 
+#endif
+
 #if EXTENSION_360_VIDEO
   TExt360AppEncCfg m_ext360;
   friend class TExt360AppEncCfg;
diff --git a/source/Lib/CommonLib/Slice.cpp b/source/Lib/CommonLib/Slice.cpp
index ca189b08a..133ac250e 100644
--- a/source/Lib/CommonLib/Slice.cpp
+++ b/source/Lib/CommonLib/Slice.cpp
@@ -1596,6 +1596,9 @@ VPS::VPS()
   , m_vpsEachLayerIsAnOlsFlag (1)
   , m_vpsOlsModeIdc (0)
   , m_vpsNumOutputLayerSets (1)
+#if JVET_Q0786_PTL_only
+  , m_vpsNumPtls (1)
+#endif
   , m_vpsExtensionFlag()
 #if JVET_Q0814_DPB
   , m_totalNumOLSs( 0 )
@@ -1625,6 +1628,14 @@ VPS::VPS()
     {
       m_vpsOlsOutputLayerFlag[i][j] = 0;
     }
+#if JVET_Q0786_PTL_only
+    if(i == 0)
+      m_ptPresentFlag[i] = 1;
+    else
+      m_ptPresentFlag[i] = 0;
+    m_ptlMaxTemporalId[i] = m_vpsMaxSubLayers - 1;
+    m_olsPtlIdx[i] = 0;
+#endif
   }
 }
 
diff --git a/source/Lib/CommonLib/Slice.h b/source/Lib/CommonLib/Slice.h
index 97025ddb4..5e7845f01 100644
--- a/source/Lib/CommonLib/Slice.h
+++ b/source/Lib/CommonLib/Slice.h
@@ -856,6 +856,14 @@ private:
   uint32_t              m_directRefLayerIdx[MAX_VPS_LAYERS][MAX_VPS_LAYERS];
   uint32_t              m_generalLayerIdx[MAX_VPS_LAYERS];
 
+#if JVET_Q0786_PTL_only
+  uint32_t              m_vpsNumPtls;
+  bool                  m_ptPresentFlag[MAX_NUM_OLSS];
+  uint32_t              m_ptlMaxTemporalId[MAX_NUM_OLSS];
+  std::vector<ProfileTierLevel> m_vpsProfileTierLevel;
+  uint32_t              m_olsPtlIdx[MAX_NUM_OLSS];
+#endif
+
   // stores index ( ilrp_idx within 0 .. NumDirectRefLayers ) of the dependent reference layers 
   uint32_t              m_interLayerRefIdx[MAX_VPS_LAYERS][MAX_VPS_LAYERS];
   bool                  m_vpsExtensionFlag;
@@ -935,6 +943,23 @@ public:
   bool              getOlsOutputLayerFlag(uint32_t ols, uint32_t layer) const { return m_vpsOlsOutputLayerFlag[ols][layer]; }
   void              setOlsOutputLayerFlag(uint32_t ols, uint32_t layer, bool t) { m_vpsOlsOutputLayerFlag[ols][layer] = t; }
 
+#if JVET_Q0786_PTL_only
+  uint32_t          getNumPtls()                                   const { return m_vpsNumPtls; }
+  void              setNumPtls(uint32_t val)                             { m_vpsNumPtls = val; }
+
+  bool              getPtPresentFlag(int idx)                      const { return m_ptPresentFlag[idx]; }
+  void              setPtPresentFlag(int idx, bool val)                  { m_ptPresentFlag[idx] = val; }
+
+  uint32_t          getPtlMaxTemporalId(int idx)                   const { return m_ptlMaxTemporalId[idx]; }
+  void              setPtlMaxTemporalId(int idx, uint32_t val)           { m_ptlMaxTemporalId[idx] = val; }
+
+  void              setProfileTierLevel(const std::vector<ProfileTierLevel> &val)   { m_vpsProfileTierLevel = val; }
+  const ProfileTierLevel& getProfileTierLevel(int idx)             const { return m_vpsProfileTierLevel[idx]; }
+
+  uint32_t          getOlsPtlIdx(int idx)                          const { return m_olsPtlIdx[idx]; }
+  void              setOlsPtlIdx(int idx, uint32_t val)                  { m_olsPtlIdx[idx] = val; }
+#endif
+
   bool              getVPSExtensionFlag() const                          { return m_vpsExtensionFlag;                                 }
   void              setVPSExtensionFlag(bool t)                          { m_vpsExtensionFlag = t;                                    }
 
diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h
index 4d4e3e183..41c62ce2c 100644
--- a/source/Lib/CommonLib/TypeDef.h
+++ b/source/Lib/CommonLib/TypeDef.h
@@ -50,6 +50,8 @@
 #include <assert.h>
 #include <cassert>
 
+#define JVET_Q0786_PTL_only                               1 // JVET-Q0786: modifications to VPS syntax - PTL part only (signal PTL for single layer OLSs)
+
 #define JVET_Q0468_Q0469_MIN_LUMA_CB_AND_MIN_QT_FIX       1 // JVET-Q0468: add support of min Luma coding block size; JVET-Q0469: fix for signaling of Intra Chroma Min QT size
 
 #define JVET_Q0210_UEK_REMOVAL                            1 // JVET-Q0210 Aspect 8: Replace uek signalling in alf_data with ue(v).
diff --git a/source/Lib/DecoderLib/VLCReader.cpp b/source/Lib/DecoderLib/VLCReader.cpp
index 850a5383c..b160bdfbe 100644
--- a/source/Lib/DecoderLib/VLCReader.cpp
+++ b/source/Lib/DecoderLib/VLCReader.cpp
@@ -1286,7 +1286,11 @@ void HLSyntaxReader::parseSPS(SPS* pcSPS)
   READ_CODE(5, uiCode, "sps_reserved_zero_5bits");
   CHECK(uiCode != 0, "sps_reserved_zero_5bits not equal to zero");
 
+#if JVET_Q0786_PTL_only
+  parseProfileTierLevel(pcSPS->getProfileTierLevel(), true, pcSPS->getMaxTLayers() - 1);
+#else
   parseProfileTierLevel(pcSPS->getProfileTierLevel(), pcSPS->getMaxTLayers() - 1);
+#endif
 
   READ_FLAG(uiCode, "gdr_enabled_flag");
   pcSPS->setGDREnabledFlag(uiCode);
@@ -2066,7 +2070,11 @@ void HLSyntaxReader::parseDPS(DPS* dps)
   ptls.resize(numPTLs);
   for (int i=0; i<numPTLs; i++)
   {
+#if JVET_Q0786_PTL_only
+     parseProfileTierLevel(&ptls[i], true, 0);
+#else
      parseProfileTierLevel(&ptls[i], dps->getMaxSubLayersMinus1());
+#endif
   }
   dps->setProfileTierLevel(ptls);
 
@@ -2170,6 +2178,55 @@ void HLSyntaxReader::parseVPS(VPS* pcVPS)
     }
   }
 
+#if JVET_Q0786_PTL_only
+  pcVPS->deriveOutputLayerSets();
+  READ_CODE(8, uiCode, "vps_num_ptls_minus1");        pcVPS->setNumPtls(uiCode + 1);
+  for (int i = 0; i < pcVPS->getNumPtls(); i++)
+  {
+    if(i > 0)
+    {
+      READ_FLAG(uiCode, "pt_present_flag");           
+      pcVPS->setPtPresentFlag(i, uiCode);
+    }
+    else
+      pcVPS->setPtPresentFlag(0, 1);
+    if(pcVPS->getMaxSubLayers() > 1 && !pcVPS->getAllLayersSameNumSublayersFlag())
+    {
+      READ_CODE(3, uiCode, "ptl_max_temporal_id");    
+      pcVPS->setPtlMaxTemporalId(i, uiCode);
+    }
+    else if(pcVPS->getMaxSubLayers() > 1)
+      pcVPS->setPtlMaxTemporalId(i, pcVPS->getMaxSubLayers() - 1);
+    else
+      pcVPS->setPtlMaxTemporalId(i, 0);
+  }
+  int cnt = 0;
+  while (m_pcBitstream->getNumBitsUntilByteAligned())
+  {
+    READ_FLAG( uiCode, "vps_ptl_alignment_zero_bit");
+    CHECK(uiCode!=0, "Alignment bit is not '0'");
+    cnt++;
+  }
+  CHECK(cnt >= 8, "Read more than '8' alignment bits");
+  std::vector<ProfileTierLevel> ptls;
+  ptls.resize(pcVPS->getNumPtls());
+  for (int i = 0; i < pcVPS->getNumPtls(); i++)
+  {
+    parseProfileTierLevel(&ptls[i], pcVPS->getPtPresentFlag(i), pcVPS->getPtlMaxTemporalId(i) - 1);
+  }
+  pcVPS->setProfileTierLevel(ptls);
+  for (int i = 0; i < pcVPS->getTotalNumOLSs(); i++)
+  {
+    if(pcVPS->getNumPtls() > 1)
+    {
+      READ_CODE(8, uiCode, "ols_ptl_idx");
+      pcVPS->setOlsPtlIdx(i, uiCode);
+    }
+    else
+      pcVPS->setOlsPtlIdx(i, 0);
+  }
+#endif
+
 #if JVET_Q0814_DPB
   if( !pcVPS->getAllIndependentLayersFlag() )
   {
@@ -2223,7 +2280,9 @@ void HLSyntaxReader::parseVPS(VPS* pcVPS)
     }
   }
 
+#if !JVET_Q0786_PTL_only
   pcVPS->deriveOutputLayerSets();
+#endif
 
   for( int i = 0; i < pcVPS->getTotalNumOLSs(); i++ )
   {
@@ -4170,16 +4229,41 @@ void HLSyntaxReader::parseConstraintInfo(ConstraintInfo *cinfo)
 }
 
 
+#if JVET_Q0786_PTL_only
+void HLSyntaxReader::parseProfileTierLevel(ProfileTierLevel *ptl, bool profileTierPresentFlag, int maxNumSubLayersMinus1)
+#else
 void HLSyntaxReader::parseProfileTierLevel(ProfileTierLevel *ptl, int maxNumSubLayersMinus1)
+#endif
 {
   uint32_t symbol;
+#if JVET_Q0786_PTL_only
+  if(profileTierPresentFlag)
+  {
+    READ_CODE(7 , symbol,   "general_profile_idc"              ); ptl->setProfileIdc  (Profile::Name(symbol));
+    READ_FLAG(    symbol,   "general_tier_flag"                ); ptl->setTierFlag    (symbol ? Level::HIGH : Level::MAIN);
+    parseConstraintInfo( ptl->getConstraintInfo() );
+  }
+#else
   READ_CODE(7 , symbol,   "general_profile_idc"              ); ptl->setProfileIdc  (Profile::Name(symbol));
   READ_FLAG(    symbol,   "general_tier_flag"                ); ptl->setTierFlag    (symbol ? Level::HIGH : Level::MAIN);
 
   parseConstraintInfo( ptl->getConstraintInfo() );
+#endif
 
   READ_CODE( 8, symbol, "general_level_idc" ); ptl->setLevelIdc( Level::Name( symbol ) );
 
+#if JVET_Q0786_PTL_only
+  if(profileTierPresentFlag)
+  {
+    READ_CODE(8, symbol, "num_sub_profiles");
+    uint8_t numSubProfiles = symbol;
+    ptl->setNumSubProfile( numSubProfiles );
+    for (int i = 0; i < numSubProfiles; i++)
+    {
+      READ_CODE(32, symbol, "general_sub_profile_idc[i]"); ptl->setSubProfileIdc(i, symbol);
+    }
+  }
+#else
   READ_CODE(8, symbol, "num_sub_profiles");
   uint8_t numSubProfiles = symbol;
   ptl->setNumSubProfile( numSubProfiles );
@@ -4187,7 +4271,7 @@ void HLSyntaxReader::parseProfileTierLevel(ProfileTierLevel *ptl, int maxNumSubL
   {
     READ_CODE(32, symbol, "general_sub_profile_idc[i]"); ptl->setSubProfileIdc(i, symbol);
   }
-
+#endif
 
   for (int i = 0; i < maxNumSubLayersMinus1; i++)
   {
diff --git a/source/Lib/DecoderLib/VLCReader.h b/source/Lib/DecoderLib/VLCReader.h
index 553f0bdef..cf68f5d2d 100644
--- a/source/Lib/DecoderLib/VLCReader.h
+++ b/source/Lib/DecoderLib/VLCReader.h
@@ -165,7 +165,11 @@ public:
   void  parseScalingListAps ( APS* pcAPS );
   void  parseVUI            ( VUI* pcVUI, SPS* pcSPS );
   void  parseConstraintInfo   (ConstraintInfo *cinfo);
+#if JVET_Q0786_PTL_only
+  void  parseProfileTierLevel(ProfileTierLevel *ptl, bool profileTierPresentFlag, int maxNumSubLayersMinus1);
+#else
   void  parseProfileTierLevel ( ProfileTierLevel *ptl, int maxNumSubLayersMinus1);
+#endif
   void  parseHrdParameters  ( HRDParameters *hrd, uint32_t firstSubLayer, uint32_t tempLevelHigh );
 #if JVET_Q0775_PH_IN_SH
   void  parsePictureHeader  ( PicHeader* picHeader, ParameterSetManager *parameterSetManager, bool readRbspTrailingBits );
diff --git a/source/Lib/EncoderLib/EncLib.cpp b/source/Lib/EncoderLib/EncLib.cpp
index bbadea5e4..589abf17d 100644
--- a/source/Lib/EncoderLib/EncLib.cpp
+++ b/source/Lib/EncoderLib/EncLib.cpp
@@ -1066,7 +1066,9 @@ void EncLib::xInitVPS( const SPS& sps )
 {
   // The SPS must have already been set up.
   // set the VPS profile information.
+#if !JVET_Q0786_PTL_only
   m_vps->setMaxSubLayers( sps.getMaxTLayers() );
+#endif
 
   ProfileLevelTierFeatures profileLevelTierFeatures;
   profileLevelTierFeatures.extractPTLInformation( sps );
@@ -1148,7 +1150,9 @@ void EncLib::xInitVPS(VPS& vps, const SPS& sps)
 {
   // The SPS must have already been set up.
   // set the VPS profile information.
+#if !JVET_Q0786_PTL_only
   vps.setMaxSubLayers(sps.getMaxTLayers());
+#endif
 }
 #endif
 
@@ -1542,6 +1546,11 @@ void EncLib::xInitSPS( SPS& sps, VPS& vps )
   
   for( int i = 0; i < m_vps->getMaxLayers(); ++i )
   {
+#if JVET_Q0786_PTL_only
+    //Bug fix to make the decoder run with configfile layers.cfg
+    if(m_vps->getIndependentLayerFlag(i) == 1)
+      sps.setInterLayerPresentFlag(0);
+#endif
     CHECK((m_vps->getIndependentLayerFlag(i) == 1) && (sps.getInterLayerPresentFlag() != 0), " When vps_independent_layer_flag[GeneralLayerIdx[nuh_layer_id ]]  is equal to 1, the value of inter_layer_ref_pics_present_flag shall be equal to 0.");
   }
 #endif  
@@ -1553,6 +1562,11 @@ void EncLib::xInitSPS( SPS& sps, VPS& vps )
   sps.setInterLayerPresentFlag( vps.getMaxLayers() > 1 && !vps.getAllIndependentLayersFlag() );
   for (unsigned int i = 0; i < vps.getMaxLayers(); ++i)
   {
+#if JVET_Q0786_PTL_only
+    //Bug fix to make the decoder run with configfile layers.cfg
+    if(vps.getIndependentLayerFlag(i) == 1)
+      sps.setInterLayerPresentFlag(0);
+#endif
     CHECK((vps.getIndependentLayerFlag(i) == 1) && (sps.getInterLayerPresentFlag() != 0), " When vps_independent_layer_flag[GeneralLayerIdx[nuh_layer_id ]]  is equal to 1, the value of inter_layer_ref_pics_present_flag shall be equal to 0.");
   }
 #endif
diff --git a/source/Lib/EncoderLib/VLCWriter.cpp b/source/Lib/EncoderLib/VLCWriter.cpp
index fdbb056f8..2a251206b 100644
--- a/source/Lib/EncoderLib/VLCWriter.cpp
+++ b/source/Lib/EncoderLib/VLCWriter.cpp
@@ -850,7 +850,11 @@ void HLSWriter::codeSPS( const SPS* pcSPS )
   WRITE_CODE(pcSPS->getMaxTLayers() - 1, 3, "sps_max_sub_layers_minus1");
   WRITE_CODE(0,                          5, "sps_reserved_zero_5bits");
 
+#if JVET_Q0786_PTL_only
+  codeProfileTierLevel( pcSPS->getProfileTierLevel(), true, pcSPS->getMaxTLayers() - 1 );
+#else
   codeProfileTierLevel( pcSPS->getProfileTierLevel(), pcSPS->getMaxTLayers() - 1 );
+#endif
   WRITE_FLAG(pcSPS->getGDREnabledFlag(), "gdr_enabled_flag");
 
   WRITE_CODE( pcSPS->getSPSId (), 4, "sps_seq_parameter_set_id" );
@@ -1411,7 +1415,11 @@ void HLSWriter::codeDPS( const DPS* dps )
   for (int i=0; i< numPTLs; i++)
   {
     ProfileTierLevel ptl = dps->getProfileTierLevel(i);
+#if JVET_Q0786_PTL_only
+    codeProfileTierLevel( &ptl, true, 0 );
+#else
     codeProfileTierLevel( &ptl, dps->getMaxSubLayersMinus1() );
+#endif
   }
   WRITE_FLAG( 0,                                              "dps_extension_flag" );
   xWriteRbspTrailingBits();
@@ -1473,6 +1481,34 @@ void HLSWriter::codeVPS(const VPS* pcVPS)
     }
   }
 
+#if JVET_Q0786_PTL_only
+  int totalNumOlss = pcVPS->getTotalNumOLSs();
+  WRITE_CODE(pcVPS->getNumPtls() - 1, 8, "vps_num_ptls_minus1");
+  for (int i = 0; i < pcVPS->getNumPtls(); i++)
+  {
+    if(i > 0)
+      WRITE_FLAG(pcVPS->getPtPresentFlag(i), "pt_present_flag");           
+    if(pcVPS->getMaxSubLayers() > 1 && !pcVPS->getAllLayersSameNumSublayersFlag())
+      WRITE_CODE(pcVPS->getPtlMaxTemporalId(i) ,3, "ptl_max_temporal_id");    
+  }
+  int cnt = 0;
+  while (m_pcBitIf->getNumBitsUntilByteAligned())
+  {
+    WRITE_FLAG( 0, "rbsp_alignment_zero_bit");
+    cnt++;
+  }
+  CHECK(cnt>=8, "More than '8' alignment bytes written");
+  for (int i = 0; i < pcVPS->getNumPtls(); i++)
+  {
+    codeProfileTierLevel(&pcVPS->getProfileTierLevel(i), pcVPS->getPtPresentFlag(i), pcVPS->getPtlMaxTemporalId(i) - 1);
+  }
+  for (int i = 0; i < totalNumOlss; i++)
+  {
+    if(pcVPS->getNumPtls() > 1)
+      WRITE_CODE(pcVPS->getOlsPtlIdx(i), 8, "ols_ptl_idx");
+  }
+#endif
+
 #if JVET_Q0814_DPB
   if( !pcVPS->getAllIndependentLayersFlag() )
   {
@@ -2832,22 +2868,44 @@ void  HLSWriter::codeConstraintInfo  ( const ConstraintInfo* cinfo )
   WRITE_FLAG(cinfo->getNoApsConstraintFlag() ? 1 : 0, "no_aps_constraint_flag");
 }
 
-
+#if JVET_Q0786_PTL_only
+void  HLSWriter::codeProfileTierLevel    ( const ProfileTierLevel* ptl, bool profileTierPresentFlag, int maxNumSubLayersMinus1 )
+#else
 void  HLSWriter::codeProfileTierLevel    ( const ProfileTierLevel* ptl, int maxNumSubLayersMinus1 )
+#endif
 {
+#if JVET_Q0786_PTL_only
+  if(profileTierPresentFlag)
+  {
+    WRITE_CODE( int(ptl->getProfileIdc()), 7 ,   "general_profile_idc"                     );
+    WRITE_FLAG( ptl->getTierFlag()==Level::HIGH, "general_tier_flag"                       );
+    codeConstraintInfo( ptl->getConstraintInfo() );
+  }
+#else
   WRITE_CODE( int(ptl->getProfileIdc()), 7 ,   "general_profile_idc"                     );
   WRITE_FLAG( ptl->getTierFlag()==Level::HIGH, "general_tier_flag"                       );
 
   codeConstraintInfo( ptl->getConstraintInfo() );
+#endif
 
   WRITE_CODE( int( ptl->getLevelIdc() ), 8, "general_level_idc" );
 
+#if JVET_Q0786_PTL_only
+  if(profileTierPresentFlag)
+  {
+    WRITE_CODE(ptl->getNumSubProfile(), 8, "num_sub_profiles");
+    for (int i = 0; i < ptl->getNumSubProfile(); i++)
+    {
+      WRITE_CODE(ptl->getSubProfileIdc(i) , 32, "general_sub_profile_idc[i]");
+    }
+  }
+#else
   WRITE_CODE(ptl->getNumSubProfile(), 8, "num_sub_profiles");
   for (int i = 0; i < ptl->getNumSubProfile(); i++)
   {
     WRITE_CODE(ptl->getSubProfileIdc(i) , 32, "general_sub_profile_idc[i]");
   }
-
+#endif
 
   for (int i = 0; i < maxNumSubLayersMinus1; i++)
   {
diff --git a/source/Lib/EncoderLib/VLCWriter.h b/source/Lib/EncoderLib/VLCWriter.h
index 7e86444be..01e8ed40e 100644
--- a/source/Lib/EncoderLib/VLCWriter.h
+++ b/source/Lib/EncoderLib/VLCWriter.h
@@ -139,7 +139,11 @@ public:
 #endif
   void  codeSliceHeader         ( Slice* pcSlice );
   void  codeConstraintInfo      ( const ConstraintInfo* cinfo );
+#if JVET_Q0786_PTL_only
+  void  codeProfileTierLevel    ( const ProfileTierLevel* ptl, bool profileTierPresentFlag, int maxNumSubLayersMinus1 );
+#else
   void  codeProfileTierLevel    ( const ProfileTierLevel* ptl, int maxNumSubLayersMinus1 );
+#endif
   void  codeHrdParameters       ( const HRDParameters *hrd, const uint32_t firstSubLayer, const uint32_t maxNumSubLayersMinus1);
 
   void  codeTilesWPPEntryPoint  ( Slice* pSlice );
-- 
GitLab