From 55207b49558b8589e6ce0fbdfe252666dde61cd4 Mon Sep 17 00:00:00 2001
From: Martin Pettersson <martin.m.pettersson@ericsson.com>
Date: Sun, 11 Aug 2019 02:14:36 +0200
Subject: [PATCH]  JVET-O0238 Parameters in PPS or slice headers (merge request
 2)

---
 cfg/encoder_lowdelay_P_vtm.cfg        |   1 +
 cfg/encoder_lowdelay_vtm.cfg          |   1 +
 cfg/encoder_randomaccess_vtm.cfg      |   1 +
 doc/software-manual.tex               |  27 ++++-
 source/App/EncoderApp/EncApp.cpp      |  17 +++
 source/App/EncoderApp/EncAppCfg.cpp   |  77 ++++++++++++-
 source/App/EncoderApp/EncAppCfg.h     |  14 +++
 source/Lib/CommonLib/Slice.cpp        |  15 +++
 source/Lib/CommonLib/Slice.h          |  49 ++++++++
 source/Lib/CommonLib/TypeDef.h        |   2 +
 source/Lib/CommonLib/UnitTools.cpp    |   4 +
 source/Lib/DecoderLib/CABACReader.cpp |   4 +
 source/Lib/DecoderLib/DecCu.cpp       |   8 ++
 source/Lib/DecoderLib/VLCReader.cpp   | 157 +++++++++++++++++++++++++-
 source/Lib/EncoderLib/CABACWriter.cpp |   4 +
 source/Lib/EncoderLib/EncCfg.h        |  36 ++++++
 source/Lib/EncoderLib/EncCu.cpp       |  18 +++
 source/Lib/EncoderLib/EncGOP.cpp      |   6 +
 source/Lib/EncoderLib/EncLib.cpp      |  19 ++++
 source/Lib/EncoderLib/EncModeCtrl.cpp |   8 ++
 source/Lib/EncoderLib/InterSearch.cpp |   4 +
 source/Lib/EncoderLib/VLCWriter.cpp   | 101 +++++++++++++++++
 22 files changed, 564 insertions(+), 9 deletions(-)

diff --git a/cfg/encoder_lowdelay_P_vtm.cfg b/cfg/encoder_lowdelay_P_vtm.cfg
index 31fcf4435..0b3a064f6 100644
--- a/cfg/encoder_lowdelay_P_vtm.cfg
+++ b/cfg/encoder_lowdelay_P_vtm.cfg
@@ -127,6 +127,7 @@ LMCSUpdateCtrl               : 2      # LMCS model update control: 0:RA, 1:AI, 2
 MIP                          : 1
 JointCbCr                    : 1      # joint coding of chroma residuals (if available): 0: disable, 1: enable
 PROF                         : 1
+PPSorSliceMode               : 3
 
 # Fast tools
 PBIntraFast                  : 1
diff --git a/cfg/encoder_lowdelay_vtm.cfg b/cfg/encoder_lowdelay_vtm.cfg
index 9f534f412..ed2e0530f 100644
--- a/cfg/encoder_lowdelay_vtm.cfg
+++ b/cfg/encoder_lowdelay_vtm.cfg
@@ -131,6 +131,7 @@ LMCSUpdateCtrl               : 2      # LMCS model update control: 0:RA, 1:AI, 2
 MIP                          : 1
 JointCbCr                    : 1      # joint coding of chroma residuals (if available): 0: disable, 1: enable
 PROF                         : 1
+PPSorSliceMode               : 2
 
 # Fast tools
 PBIntraFast                  : 1
diff --git a/cfg/encoder_randomaccess_vtm.cfg b/cfg/encoder_randomaccess_vtm.cfg
index 506a4753c..494811fec 100644
--- a/cfg/encoder_randomaccess_vtm.cfg
+++ b/cfg/encoder_randomaccess_vtm.cfg
@@ -149,6 +149,7 @@ DMVR                         : 1
 SMVD                         : 1
 JointCbCr                    : 1      # joint coding of chroma residuals (if available): 0: disable, 1: enable
 PROF                         : 1
+PPSorSliceMode               : 1
 
 # Fast tools
 PBIntraFast                  : 1
diff --git a/doc/software-manual.tex b/doc/software-manual.tex
index 41fdf9ada..cc4935403 100755
--- a/doc/software-manual.tex
+++ b/doc/software-manual.tex
@@ -2117,15 +2117,30 @@ is satisfied, the stronger intra smoothing filter is applied.
 If disabled, the intra smoothing filter when applied is the 1:2:1 smoothing filter.
 \\
 
-\Option{TMVPMode} &
+\Option{PPSorSliceMode} &
 %\ShortOption{\None} &
-\Default{1} &
-Controls the temporal motion vector prediction mode.
+\Default{0} &
+Enables signaling the below parameters either in PPS or per slice according to the following presets:
 \par
 \begin{tabular}{cp{0.45\textwidth}}
-  0 & Disabled for all slices. \\
-  1 & Enabled for all slices. \\
-  2 & Disabled only for the first picture of each GOPSize. \\
+  0 & Always signaled per slice. \\
+  1 & RA settings. \\
+  2 & LDB settings. \\
+  3 & LDP settings. \\ 
+\end{tabular}
+\par
+\begin{tabular}{p{5cm}llll}
+  Parameter & \multicolumn{3}{l}{Mode} \\
+  & 0 & 1 & 2 & 3 \\
+  dep_quant_enabled_flag & s & p & p & p \\
+  ref_pic_list_sps_flag0 & s & s & p & p \\
+  ref_pic_list_sps_flag1 & s & s & p & p \\
+  temporal_mvp_enabled_flag & s & s & p & p \\
+  mvd_l1_zero_flag & s & s & p & s \\
+  collocated_from_l0_flag & s & s & p & s \\
+  six_minus_max_num_merge_cand & s & p & p & p \\
+  five_minus_max_num_subblock_merge_cand & s & p & p & p \\
+  max_num_merge_cand_minus_max_num_triangle_cand & s & p & p & s \\
 \end{tabular}
 \\
 
diff --git a/source/App/EncoderApp/EncApp.cpp b/source/App/EncoderApp/EncApp.cpp
index cb9dd1388..d55f2e82a 100644
--- a/source/App/EncoderApp/EncApp.cpp
+++ b/source/App/EncoderApp/EncApp.cpp
@@ -130,7 +130,11 @@ void EncApp::xInitLibCfg()
   m_cEncLib.setNoPcmConstraintFlag                               ( !m_usePCM );
 #endif
   m_cEncLib.setNoRefWraparoundConstraintFlag                     ( m_bNoRefWraparoundConstraintFlag );
+#if JVET_O0238_PPS_OR_SLICE
+  m_cEncLib.setNoTemporalMvpConstraintFlag                       ( m_PPSTemporalMVPEnabledIdc != 1 ? false : true );
+#else
   m_cEncLib.setNoTemporalMvpConstraintFlag                       ( m_TMVPModeId ? false : true );
+#endif
   m_cEncLib.setNoSbtmvpConstraintFlag                            ( m_SubPuMvpMode ? false : true );
   m_cEncLib.setNoAmvrConstraintFlag                              ( m_bNoAmvrConstraintFlag );
   m_cEncLib.setNoBdofConstraintFlag                              ( !m_BIO );
@@ -560,7 +564,20 @@ void EncApp::xInitLibCfg()
   }
   m_cEncLib.setLFCrossTileBoundaryFlag                           ( m_bLFCrossTileBoundaryFlag );
   m_cEncLib.setEntropyCodingSyncEnabledFlag                      ( m_entropyCodingSyncEnabledFlag );
+#if JVET_O0238_PPS_OR_SLICE
+  m_cEncLib.setConstantSliceHeaderParamsEnabledFlag              ( m_constantSliceHeaderParamsEnabledFlag );
+  m_cEncLib.setPPSDepQuantEnabledIdc                             ( m_PPSDepQuantEnabledIdc );
+  m_cEncLib.setPPSRefPicListSPSIdc0                              ( m_PPSRefPicListSPSIdc0 );
+  m_cEncLib.setPPSRefPicListSPSIdc1                              ( m_PPSRefPicListSPSIdc1 );
+  m_cEncLib.setPPSTemporalMVPEnabledIdc                          ( m_PPSTemporalMVPEnabledIdc );
+  m_cEncLib.setPPSMvdL1ZeroIdc                                   ( m_PPSMvdL1ZeroIdc );
+  m_cEncLib.setPPSCollocatedFromL0Idc                            ( m_PPSCollocatedFromL0Idc );
+  m_cEncLib.setPPSSixMinusMaxNumMergeCandPlus1                   ( m_PPSSixMinusMaxNumMergeCandPlus1 );
+  m_cEncLib.setPPSFiveMinusMaxNumSubblockMergeCandPlus1          ( m_PPSFiveMinusMaxNumSubblockMergeCandPlus1 );
+  m_cEncLib.setPPSMaxNumMergeCandMinusMaxNumTriangleCandPlus1    ( m_PPSMaxNumMergeCandMinusMaxNumTriangleCandPlus1 );
+#else
   m_cEncLib.setTMVPModeId                                        ( m_TMVPModeId );
+#endif
   m_cEncLib.setUseScalingListId                                  ( m_useScalingListId  );
   m_cEncLib.setScalingListFileName                               ( m_scalingListFileName );
   m_cEncLib.setDepQuantEnabledFlag                               ( m_depQuantEnabledFlag);
diff --git a/source/App/EncoderApp/EncAppCfg.cpp b/source/App/EncoderApp/EncAppCfg.cpp
index c3f340c94..e7493935b 100644
--- a/source/App/EncoderApp/EncAppCfg.cpp
+++ b/source/App/EncoderApp/EncAppCfg.cpp
@@ -1201,7 +1201,12 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] )
                                                                                                                "\t2: CRC\n"
                                                                                                                "\t1: use MD5\n"
                                                                                                                "\t0: disable")
+#if JVET_O0238_PPS_OR_SLICE
+  ("PPSorSliceMode",                                  m_PPSorSliceMode,                                     0, "Enable signalling certain parameters either in PPS or per slice\n"
+                                                                                                                "\tmode 0: Always per slice, 1: RA settings, 2: LDB settings, 3: LDP settings")
+#else
   ("TMVPMode",                                        m_TMVPModeId,                                         1, "TMVP mode 0: TMVP disable for all slices. 1: TMVP enable for all slices (default) 2: TMVP enable for certain slices only")
+#endif
   ("FEN",                                             tmpFastInterSearchMode,   int(FASTINTERSEARCH_DISABLED), "fast encoder setting")
   ("ECU",                                             m_bUseEarlyCU,                                    false, "Early CU setting")
   ("FDM",                                             m_useFastDecisionForMerge,                         true, "Fast decision for Merge RD Cost")
@@ -3210,15 +3215,82 @@ bool EncAppCfg::xCheckParameter()
     }
   }
 
+#if JVET_O0238_PPS_OR_SLICE
+  // If m_PPSorSliceFlag is equal to 1, for each PPS parameter below,
+  //     0:  value is signaled in slice header
+  //     >0: value is derived from PPS parameter as value - 1
+  switch (m_PPSorSliceMode)
+  {
+  case 0: // All parameter values are signaled in slice header
+    m_constantSliceHeaderParamsEnabledFlag = 0;
+    m_PPSDepQuantEnabledIdc = 0;
+    m_PPSRefPicListSPSIdc0 = 0;
+    m_PPSRefPicListSPSIdc1 = 0;
+	  m_PPSTemporalMVPEnabledIdc = 0;
+    m_PPSMvdL1ZeroIdc = 0;
+    m_PPSCollocatedFromL0Idc = 0;
+    m_PPSSixMinusMaxNumMergeCandPlus1 = 0;
+    m_PPSFiveMinusMaxNumSubblockMergeCandPlus1 = 0;
+    m_PPSMaxNumMergeCandMinusMaxNumTriangleCandPlus1 = 0;
+    break;
+  case 1: // RA setting
+    m_constantSliceHeaderParamsEnabledFlag = 1;
+    m_PPSDepQuantEnabledIdc = 2;
+    m_PPSRefPicListSPSIdc0 = 0;
+    m_PPSRefPicListSPSIdc1 = 0;
+    m_PPSTemporalMVPEnabledIdc = 0;
+	  m_PPSMvdL1ZeroIdc = 0;
+    m_PPSCollocatedFromL0Idc = 0;
+    m_PPSSixMinusMaxNumMergeCandPlus1 = 1;
+    m_PPSFiveMinusMaxNumSubblockMergeCandPlus1 = 1;
+    m_PPSMaxNumMergeCandMinusMaxNumTriangleCandPlus1 = 2;
+    break;
+  case 2: // LDB setting
+    m_constantSliceHeaderParamsEnabledFlag = 1;
+    m_PPSDepQuantEnabledIdc = 2;
+    m_PPSRefPicListSPSIdc0 = 2;
+    m_PPSRefPicListSPSIdc1 = 2;
+    m_PPSTemporalMVPEnabledIdc = 2;
+    m_PPSMvdL1ZeroIdc = 2;
+    m_PPSCollocatedFromL0Idc = 1;
+    m_PPSSixMinusMaxNumMergeCandPlus1 = 1;
+    m_PPSFiveMinusMaxNumSubblockMergeCandPlus1 = 1;
+    m_PPSMaxNumMergeCandMinusMaxNumTriangleCandPlus1 = 2;
+    break;
+  case 3: // LDP setting
+    m_constantSliceHeaderParamsEnabledFlag = 1;
+    m_PPSDepQuantEnabledIdc = 2;
+    m_PPSRefPicListSPSIdc0 = 2;
+    m_PPSRefPicListSPSIdc1 = 2;
+	  m_PPSTemporalMVPEnabledIdc = 2;
+    m_PPSMvdL1ZeroIdc = 0;
+    m_PPSCollocatedFromL0Idc = 0;
+    m_PPSSixMinusMaxNumMergeCandPlus1 = 1;
+    m_PPSFiveMinusMaxNumSubblockMergeCandPlus1 = 1;
+    m_PPSMaxNumMergeCandMinusMaxNumTriangleCandPlus1 = 0;
+    break;
+  default:
+    THROW("Invalid value for PPSorSliceMode");
+  }
+#endif
+
   if ((m_MCTSEncConstraint) && (m_bLFCrossTileBoundaryFlag))
   {
     printf("Warning: Constrained Encoding for Motion Constrained Tile Sets (MCTS) is enabled. Disabling filtering across tile boundaries!\n");
     m_bLFCrossTileBoundaryFlag = false;
   }
+#if JVET_O0238_PPS_OR_SLICE
+  if ((m_MCTSEncConstraint) && (m_PPSTemporalMVPEnabledIdc != 1))
+#else
   if ((m_MCTSEncConstraint) && (m_TMVPModeId))
+#endif
   {
     printf("Warning: Constrained Encoding for Motion Constrained Tile Sets (MCTS) is enabled. Disabling TMVP!\n");
+#if JVET_O0238_PPS_OR_SLICE
+    m_PPSTemporalMVPEnabledIdc = 1;
+#else
     m_TMVPModeId = 0;
+#endif
   }
 
   if ((m_MCTSEncConstraint) && ( m_alf ))
@@ -3546,8 +3618,11 @@ void EncAppCfg::xPrintParameter()
   const int iWaveFrontSubstreams = m_entropyCodingSyncEnabledFlag ? (m_iSourceHeight + m_uiMaxCUHeight - 1) / m_uiMaxCUHeight : 1;
   msg( VERBOSE, " WaveFrontSynchro:%d WaveFrontSubstreams:%d", m_entropyCodingSyncEnabledFlag?1:0, iWaveFrontSubstreams);
   msg( VERBOSE, " ScalingList:%d ", m_useScalingListId );
+  #if JVET_O0238_PPS_OR_SLICE
+  msg( VERBOSE, "TMVPMode:%d ", m_PPSTemporalMVPEnabledIdc != 1  );
+#else
   msg( VERBOSE, "TMVPMode:%d ", m_TMVPModeId     );
-
+#endif
   msg( VERBOSE, " DQ:%d ", m_depQuantEnabledFlag);
   msg( VERBOSE, " SignBitHidingFlag:%d ", m_signDataHidingEnabledFlag);
   msg( VERBOSE, "RecalQP:%d ", m_recalculateQPAccordingToLambda ? 1 : 0 );
diff --git a/source/App/EncoderApp/EncAppCfg.h b/source/App/EncoderApp/EncAppCfg.h
index 9e3a47729..de4c7b4de 100644
--- a/source/App/EncoderApp/EncAppCfg.h
+++ b/source/App/EncoderApp/EncAppCfg.h
@@ -546,7 +546,21 @@ protected:
   uint32_t      m_maxNumIBCMergeCand;                             ///< Max number of IBC merge candidates
 #endif
 
+#if JVET_O0238_PPS_OR_SLICE
+  int       m_PPSorSliceMode;
+  bool      m_constantSliceHeaderParamsEnabledFlag;
+  int       m_PPSDepQuantEnabledIdc;
+  int       m_PPSRefPicListSPSIdc0;
+  int       m_PPSRefPicListSPSIdc1;
+  int       m_PPSTemporalMVPEnabledIdc;
+  int       m_PPSMvdL1ZeroIdc;                       
+  int       m_PPSCollocatedFromL0Idc;                            
+  uint32_t  m_PPSSixMinusMaxNumMergeCandPlus1;                        
+  uint32_t  m_PPSFiveMinusMaxNumSubblockMergeCandPlus1;
+  uint32_t  m_PPSMaxNumMergeCandMinusMaxNumTriangleCandPlus1;
+#else
   int       m_TMVPModeId;
+#endif
   bool      m_depQuantEnabledFlag;
   bool      m_signDataHidingEnabledFlag;
   bool      m_RCEnableRateControl;                ///< enable rate control or not
diff --git a/source/Lib/CommonLib/Slice.cpp b/source/Lib/CommonLib/Slice.cpp
index d068d5c87..91f552761 100644
--- a/source/Lib/CommonLib/Slice.cpp
+++ b/source/Lib/CommonLib/Slice.cpp
@@ -1433,7 +1433,9 @@ SPS::SPS()
 #if !JVET_O0525_REMOVE_PCM
 , m_bPCMFilterDisableFlag     (false)
 #endif
+#if !JVET_O0238_PPS_OR_SLICE
 , m_sbtmvpEnabledFlag         (false)
+#endif
 , m_bdofEnabledFlag           (false)
 , m_fpelMmvdEnabledFlag       ( false )
 #if JVET_O1140_SLICE_DISABLE_BDOF_DMVR_FLAG
@@ -1634,6 +1636,19 @@ PPS::PPS()
 , m_numBricksInPic                   (1)
 , m_signalledSliceIdFlag             (false)
 ,m_signalledSliceIdLengthMinus1      (0)
+#if JVET_O0238_PPS_OR_SLICE
+, m_constantSliceHeaderParamsEnabledFlag (false)
+, m_PPSDepQuantEnabledIdc            (0)
+, m_PPSRefPicListSPSIdc0             (0)
+, m_PPSRefPicListSPSIdc1             (0)
+, m_PPSTemporalMVPEnabledIdc         (0)
+, m_PPSMvdL1ZeroIdc                  (0)
+, m_PPSCollocatedFromL0Idc           (0)
+, m_PPSSixMinusMaxNumMergeCandPlus1  (0)
+, m_PPSFiveMinusMaxNumSubblockMergeCandPlus1 (0)
+, m_PPSMaxNumMergeCandMinusMaxNumTriangleCandPlus1 (0)
+, m_sbtmvpEnabledFlag                (false)
+#endif
 , m_cabacInitPresentFlag             (false)
 , m_sliceHeaderExtensionPresentFlag  (false)
 , m_loopFilterAcrossSlicesEnabledFlag(false)
diff --git a/source/Lib/CommonLib/Slice.h b/source/Lib/CommonLib/Slice.h
index ab8699180..47da58b9d 100644
--- a/source/Lib/CommonLib/Slice.h
+++ b/source/Lib/CommonLib/Slice.h
@@ -780,7 +780,9 @@ private:
   bool              m_rpl1IdxPresentFlag;
   bool              m_allRplEntriesHasSameSignFlag;
   bool              m_bLongTermRefsPresent;
+#if !JVET_O0238_PPS_OR_SLICE
   bool              m_SPSTemporalMVPEnabledFlag;
+#endif
   int               m_numReorderPics[MAX_TLAYER];
 
   // Tool list
@@ -808,7 +810,9 @@ private:
   bool              m_bPCMFilterDisableFlag;
 #endif
 
+#if !JVET_O0238_PPS_OR_SLICE
   bool              m_sbtmvpEnabledFlag;
+#endif
   bool              m_bdofEnabledFlag;
   bool              m_fpelMmvdEnabledFlag;
 #if JVET_O1140_SLICE_DISABLE_BDOF_DMVR_FLAG
@@ -1005,8 +1009,10 @@ public:
   bool                    getAllActiveRplEntriesHasSameSignFlag() const                                       { return m_allRplEntriesHasSameSignFlag;                               }
   bool                    getLongTermRefsPresent() const                                                  { return m_bLongTermRefsPresent;                                       }
   void                    setLongTermRefsPresent(bool b)                                                  { m_bLongTermRefsPresent=b;                                            }
+#if !JVET_O0238_PPS_OR_SLICE
   bool                    getSPSTemporalMVPEnabledFlag() const                                            { return m_SPSTemporalMVPEnabledFlag;                                  }
   void                    setSPSTemporalMVPEnabledFlag(bool b)                                            { m_SPSTemporalMVPEnabledFlag=b;                                       }
+#endif
 #if MAX_TB_SIZE_SIGNALLING
   void                    setLog2MaxTbSize( uint32_t u )                                                  { m_log2MaxTbSize = u;                                                 }
   uint32_t                getLog2MaxTbSize() const                                                        { return  m_log2MaxTbSize;                                             }
@@ -1035,8 +1041,11 @@ public:
   void                    setJointCbCrEnabledFlag(bool bVal)                                              { m_JointCbCrEnabledFlag = bVal; }
   bool                    getJointCbCrEnabledFlag() const                                                 { return m_JointCbCrEnabledFlag; }
 #endif
+
+#if !JVET_O0238_PPS_OR_SLICE
   bool                    getSBTMVPEnabledFlag() const                                                    { return m_sbtmvpEnabledFlag; }
   void                    setSBTMVPEnabledFlag(bool b)                                                    { m_sbtmvpEnabledFlag = b; }
+#endif
 
   void                    setBDOFEnabledFlag(bool b)                                                      { m_bdofEnabledFlag = b; }
   bool                    getBDOFEnabledFlag() const                                                      { return m_bdofEnabledFlag; }
@@ -1306,6 +1315,20 @@ private:
   int              m_signalledSliceIdLengthMinus1;
   std::vector<int> m_sliceId;
 
+#if JVET_O0238_PPS_OR_SLICE
+  bool              m_constantSliceHeaderParamsEnabledFlag;
+  int               m_PPSDepQuantEnabledIdc;
+  int               m_PPSRefPicListSPSIdc0;
+  int               m_PPSRefPicListSPSIdc1;
+  int               m_PPSTemporalMVPEnabledIdc;
+  int               m_PPSMvdL1ZeroIdc;
+  int               m_PPSCollocatedFromL0Idc;
+  uint32_t          m_PPSSixMinusMaxNumMergeCandPlus1;
+  uint32_t          m_PPSFiveMinusMaxNumSubblockMergeCandPlus1;
+  uint32_t          m_PPSMaxNumMergeCandMinusMaxNumTriangleCandPlus1;
+  bool              m_sbtmvpEnabledFlag;
+#endif
+
   bool             m_cabacInitPresentFlag;
 
   bool             m_sliceHeaderExtensionPresentFlag;
@@ -1461,6 +1484,32 @@ public:
   int                    getSliceId(uint32_t columnIdx) const                             { return  m_sliceId[columnIdx];                 }
   void                   setSliceId(const std::vector<int>& val)                          { m_sliceId = val;                              }
 
+  #if JVET_O0238_PPS_OR_SLICE
+  bool                    getConstantSliceHeaderParamsEnabledFlag() const                 { return m_constantSliceHeaderParamsEnabledFlag; }
+  void                    setConstantSliceHeaderParamsEnabledFlag(bool b)                 { m_constantSliceHeaderParamsEnabledFlag = b;   }
+  int                     getPPSDepQuantEnabledIdc() const                                { return m_PPSDepQuantEnabledIdc;               }
+  void                    setPPSDepQuantEnabledIdc(int u)                                 { m_PPSDepQuantEnabledIdc = u;                  }
+  int                     getPPSRefPicListSPSIdc0() const                                 { return m_PPSRefPicListSPSIdc0;                }
+  void                    setPPSRefPicListSPSIdc0(int u)                                  { m_PPSRefPicListSPSIdc0 = u;                   }
+  int                     getPPSRefPicListSPSIdc1() const                                 { return m_PPSRefPicListSPSIdc1;                }
+  void                    setPPSRefPicListSPSIdc1(int u)                                  { m_PPSRefPicListSPSIdc1 = u;                   }
+  int                     getPPSTemporalMVPEnabledIdc() const                             { return m_PPSTemporalMVPEnabledIdc;            }
+  void                    setPPSTemporalMVPEnabledIdc(int u)                              { m_PPSTemporalMVPEnabledIdc = u;               }
+  int                     getPPSMvdL1ZeroIdc() const                                      { return m_PPSMvdL1ZeroIdc;                     }
+  void                    setPPSMvdL1ZeroIdc(int u)                                       { m_PPSMvdL1ZeroIdc = u;                        }
+  int                     getPPSCollocatedFromL0Idc() const                               { return m_PPSCollocatedFromL0Idc;              }
+  void                    setPPSCollocatedFromL0Idc(int u)                                { m_PPSCollocatedFromL0Idc = u;                 }
+  uint32_t                getPPSSixMinusMaxNumMergeCandPlus1() const                      { return m_PPSSixMinusMaxNumMergeCandPlus1;     }
+  void                    setPPSSixMinusMaxNumMergeCandPlus1(uint32_t u)                  { m_PPSSixMinusMaxNumMergeCandPlus1 = u;        }
+  uint32_t                getPPSFiveMinusMaxNumSubblockMergeCandPlus1() const             { return m_PPSFiveMinusMaxNumSubblockMergeCandPlus1; }
+  void                    setPPSFiveMinusMaxNumSubblockMergeCandPlus1(uint32_t u)         { m_PPSFiveMinusMaxNumSubblockMergeCandPlus1 = u; }  
+  uint32_t                getPPSMaxNumMergeCandMinusMaxNumTriangleCandPlus1() const       { return m_PPSMaxNumMergeCandMinusMaxNumTriangleCandPlus1; }
+  void                    setPPSMaxNumMergeCandMinusMaxNumTriangleCandPlus1(uint32_t u)   { m_PPSMaxNumMergeCandMinusMaxNumTriangleCandPlus1 = u; }
+
+  bool                    getSBTMVPEnabledFlag() const                                    { return m_sbtmvpEnabledFlag;                   }
+  void                    setSBTMVPEnabledFlag(bool b)                                    { m_sbtmvpEnabledFlag = b;                      }
+#endif
+
   void                   setCabacInitPresentFlag( bool flag )                             { m_cabacInitPresentFlag = flag;                }
   bool                   getCabacInitPresentFlag() const                                  { return m_cabacInitPresentFlag;                }
   void                   setDeblockingFilterControlPresentFlag( bool val )                { m_deblockingFilterControlPresentFlag = val;   }
diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h
index 88063fe2c..0a1146cff 100644
--- a/source/Lib/CommonLib/TypeDef.h
+++ b/source/Lib/CommonLib/TypeDef.h
@@ -58,6 +58,8 @@
 #define RPR_CONF_WINDOW                                   1
 #endif
 
+#define JVET_O0238_PPS_OR_SLICE                           1 // JVET-O0238: Signal certain parameters either in PPS or per slice
+
 #define JVET_O0119_BASE_PALETTE_444                       1 // JVET-O0119: Palette mode in HEVC and palette mode signaling in JVET-N0258. Only enabled for YUV444.
 
 #define JVET_O0304_SIMPLIFIED_BDOF                        1 // JVET-O0304: Reduction of number of multiplications in BDOF
diff --git a/source/Lib/CommonLib/UnitTools.cpp b/source/Lib/CommonLib/UnitTools.cpp
index 8978e6191..87ffcd553 100755
--- a/source/Lib/CommonLib/UnitTools.cpp
+++ b/source/Lib/CommonLib/UnitTools.cpp
@@ -3200,7 +3200,11 @@ void PU::getAffineMergeCand( const PredictionUnit &pu, AffineMergeCtx& affMrgCtx
   affMrgCtx.numValidMergeCand = 0;
   affMrgCtx.maxNumMergeCand = maxNumAffineMergeCand;
 
+#if JVET_O0238_PPS_OR_SLICE
+  bool enableSubPuMvp = slice.getPPS()->getSBTMVPEnabledFlag() && !(slice.getPOC() == slice.getRefPic(REF_PIC_LIST_0, 0)->getPOC() && slice.isIRAP());
+#else
   bool enableSubPuMvp = slice.getSPS()->getSBTMVPEnabledFlag() && !(slice.getPOC() == slice.getRefPic(REF_PIC_LIST_0, 0)->getPOC() && slice.isIRAP());
+#endif
   bool isAvailableSubPu = false;
   if ( enableSubPuMvp && slice.getEnableTMVPFlag() )
   {
diff --git a/source/Lib/DecoderLib/CABACReader.cpp b/source/Lib/DecoderLib/CABACReader.cpp
index 691b93015..da7f61b01 100644
--- a/source/Lib/DecoderLib/CABACReader.cpp
+++ b/source/Lib/DecoderLib/CABACReader.cpp
@@ -2478,8 +2478,12 @@ void CABACReader::subblock_merge_flag( CodingUnit& cu )
 
 #if JVET_O0220_METHOD1_SUBBLK_FLAG_PARSING
   if ( !cu.cs->slice->isIntra() && (cu.slice->getMaxNumAffineMergeCand() > 0) && cu.lumaSize().width >= 8 && cu.lumaSize().height >= 8 )
+#else
+#if JVET_O0238_PPS_OR_SLICE
+  if ( !cu.cs->slice->isIntra() && (cu.cs->sps->getUseAffine() || cu.cs->pps->getSBTMVPEnabledFlag()) && cu.lumaSize().width >= 8 && cu.lumaSize().height >= 8 )
 #else
   if ( !cu.cs->slice->isIntra() && (cu.cs->sps->getUseAffine() || cu.cs->sps->getSBTMVPEnabledFlag()) && cu.lumaSize().width >= 8 && cu.lumaSize().height >= 8 )
+#endif
 #endif
   {
     RExt__DECODER_DEBUG_BIT_STATISTICS_CREATE_SET( STATS__CABAC_BITS__AFFINE_FLAG );
diff --git a/source/Lib/DecoderLib/DecCu.cpp b/source/Lib/DecoderLib/DecCu.cpp
index f71c5f161..72bdb156c 100644
--- a/source/Lib/DecoderLib/DecCu.cpp
+++ b/source/Lib/DecoderLib/DecCu.cpp
@@ -898,7 +898,11 @@ void DecCu::xDeriveCUMV( CodingUnit &cu )
       if (pu.mmvdMergeFlag || pu.cu->mmvdSkip)
       {
         CHECK(pu.mhIntraFlag == true, "invalid MHIntra");
+#if JVET_O0238_PPS_OR_SLICE
+        if (pu.cs->pps->getSBTMVPEnabledFlag())
+#else
         if (pu.cs->sps->getSBTMVPEnabledFlag())
+#endif
         {
           Size bufSize = g_miScaling.scale(pu.lumaSize());
           mrgCtx.subPuMvpMiBuf = MotionBuf(m_SubPuMiBuf, bufSize);
@@ -927,7 +931,11 @@ void DecCu::xDeriveCUMV( CodingUnit &cu )
         if( pu.cu->affine )
         {
           AffineMergeCtx affineMergeCtx;
+#if JVET_O0238_PPS_OR_SLICE
+          if ( pu.cs->pps->getSBTMVPEnabledFlag() )
+#else
           if ( pu.cs->sps->getSBTMVPEnabledFlag() )
+#endif
           {
             Size bufSize = g_miScaling.scale( pu.lumaSize() );
             mrgCtx.subPuMvpMiBuf = MotionBuf( m_SubPuMiBuf, bufSize );
diff --git a/source/Lib/DecoderLib/VLCReader.cpp b/source/Lib/DecoderLib/VLCReader.cpp
index ac9997d2e..ec40d43a1 100644
--- a/source/Lib/DecoderLib/VLCReader.cpp
+++ b/source/Lib/DecoderLib/VLCReader.cpp
@@ -396,6 +396,41 @@ void HLSyntaxReader::parsePPS( PPS* pcPPS, ParameterSetManager *parameterSetMana
   READ_FLAG(uiCode, "rpl1_idx_present_flag");
   pcPPS->setRpl1IdxPresentFlag(uiCode);
 
+#if JVET_O0238_PPS_OR_SLICE
+  READ_FLAG( uiCode, "constant_slice_header_params_enabled_flag"); pcPPS->setConstantSliceHeaderParamsEnabledFlag(uiCode);
+  if ( pcPPS->getConstantSliceHeaderParamsEnabledFlag() ) {
+    READ_CODE( 2, uiCode, "pps_dep_quant_enabled_idc");        pcPPS->setPPSDepQuantEnabledIdc(uiCode); 
+    READ_CODE( 2, uiCode, "pps_ref_pic_list_sps_idc[0]");      pcPPS->setPPSRefPicListSPSIdc0(uiCode);
+    READ_CODE( 2, uiCode, "pps_ref_pic_list_sps_idc[1]");      pcPPS->setPPSRefPicListSPSIdc1(uiCode);
+    READ_CODE( 2, uiCode, "pps_temporal_mvp_enabled_idc");     pcPPS->setPPSTemporalMVPEnabledIdc(uiCode);  
+    READ_CODE( 2, uiCode, "pps_mvd_l1_zero_idc");              pcPPS->setPPSMvdL1ZeroIdc(uiCode); 
+    READ_CODE( 2, uiCode, "pps_collocated_from_l0_idc");       pcPPS->setPPSCollocatedFromL0Idc(uiCode); 
+    READ_UVLC( uiCode, "pps_six_minus_max_num_merge_cand_plus1"); pcPPS->setPPSSixMinusMaxNumMergeCandPlus1(uiCode); 
+    READ_UVLC( uiCode, "pps_five_minus_max_num_subblock_merge_cand_plus1"); pcPPS->setPPSFiveMinusMaxNumSubblockMergeCandPlus1(uiCode); 
+    READ_UVLC( uiCode, "pps_max_num_merge_cand_minus_max_num_triangle_cand_plus1");pcPPS->setPPSMaxNumMergeCandMinusMaxNumTriangleCandPlus1(uiCode); 
+  } 
+  else
+  {
+    pcPPS->setPPSDepQuantEnabledIdc(0); 
+    pcPPS->setPPSRefPicListSPSIdc0(0);
+    pcPPS->setPPSRefPicListSPSIdc1(0);
+    pcPPS->setPPSTemporalMVPEnabledIdc(0);
+    pcPPS->setPPSMvdL1ZeroIdc(0); 
+    pcPPS->setPPSCollocatedFromL0Idc(0); 
+    pcPPS->setPPSSixMinusMaxNumMergeCandPlus1(0); 
+    pcPPS->setPPSFiveMinusMaxNumSubblockMergeCandPlus1(0); 
+    pcPPS->setPPSMaxNumMergeCandMinusMaxNumTriangleCandPlus1(0); 
+  }
+  if ( pcPPS->getPPSTemporalMVPEnabledIdc() != 1 )
+  {
+    READ_FLAG( uiCode,    "pps_sbtmvp_enabled_flag" );                   pcPPS->setSBTMVPEnabledFlag      ( uiCode != 0 );
+  }
+  else
+  {
+    pcPPS->setSBTMVPEnabledFlag(false);
+  }
+#endif
+
   READ_SVLC(iCode, "init_qp_minus26" );                            pcPPS->setPicInitQPMinus26(iCode);
   READ_FLAG( uiCode, "constrained_intra_pred_flag" );              pcPPS->setConstrainedIntraPred( uiCode ? true : false );
 #if !JVET_O1136_TS_BDPCM_SIGNALLING
@@ -1374,6 +1409,7 @@ void HLSyntaxReader::parseSPS(SPS* pcSPS)
   }
 #endif
 
+#if !JVET_O0238_PPS_OR_SLICE
   READ_FLAG( uiCode, "sps_temporal_mvp_enabled_flag" );                  pcSPS->setSPSTemporalMVPEnabledFlag(uiCode);
 
   if ( pcSPS->getSPSTemporalMVPEnabledFlag() )
@@ -1384,6 +1420,7 @@ void HLSyntaxReader::parseSPS(SPS* pcSPS)
   {
     pcSPS->setSBTMVPEnabledFlag(false);
   }
+#endif
 
   READ_FLAG( uiCode,  "sps_amvr_enabled_flag" );                     pcSPS->setAMVREnabledFlag ( uiCode != 0 );
 
@@ -1771,7 +1808,18 @@ void HLSyntaxReader::parseSliceHeader (Slice* pcSlice, ParameterSetManager *para
       //Read L0 related syntax elements
       if (sps->getNumRPL0() > 0)
       {
+#if JVET_O0238_PPS_OR_SLICE
+        if (!pps->getPPSRefPicListSPSIdc0())
+        {
+          READ_FLAG(uiCode, "ref_pic_list_sps_flag[0]");
+        }
+        else
+        {
+          uiCode = pps->getPPSRefPicListSPSIdc0() - 1;
+        }
+#else   
         READ_FLAG(uiCode, "ref_pic_list_sps_flag[0]");
+#endif
       }
       else
       {
@@ -1835,7 +1883,18 @@ void HLSyntaxReader::parseSliceHeader (Slice* pcSlice, ParameterSetManager *para
       {
         if (sps->getNumRPL1() > 0)
         {
+#if JVET_O0238_PPS_OR_SLICE
+          if (!pps->getPPSRefPicListSPSIdc1())
+          {
+            READ_FLAG(uiCode, "ref_pic_list_sps_flag[1]");
+          }
+          else
+          {
+            uiCode = pps->getPPSRefPicListSPSIdc1() - 1;
+          }
+#else
           READ_FLAG(uiCode, "ref_pic_list_sps_flag[1]");
+#endif
         }
         else
         {
@@ -1893,14 +1952,22 @@ void HLSyntaxReader::parseSliceHeader (Slice* pcSlice, ParameterSetManager *para
         }
       }
 
+#if JVET_O0238_PPS_OR_SLICE
+      if (!pps->getPPSTemporalMVPEnabledIdc())
+#else
       if (sps->getSPSTemporalMVPEnabledFlag())
+#endif
       {
         READ_FLAG( uiCode, "slice_temporal_mvp_enabled_flag" );
         pcSlice->setEnableTMVPFlag( uiCode == 1 ? true : false );
       }
       else
       {
+#if JVET_O0238_PPS_OR_SLICE
+        pcSlice->setEnableTMVPFlag((pps->getPPSTemporalMVPEnabledIdc() - 1) == 1 ? true: false);
+#else
         pcSlice->setEnableTMVPFlag(false);
+#endif
       }
     }
 
@@ -2085,7 +2152,20 @@ void HLSyntaxReader::parseSliceHeader (Slice* pcSlice, ParameterSetManager *para
 
     if (pcSlice->isInterB())
     {
-      READ_FLAG( uiCode, "mvd_l1_zero_flag" );       pcSlice->setMvdL1ZeroFlag( (uiCode ? true : false) );
+#if JVET_O0238_PPS_OR_SLICE
+      if (!pps->getPPSMvdL1ZeroIdc())
+      {
+        READ_FLAG(uiCode, "mvd_l1_zero_flag");
+      }
+      else
+      {
+        uiCode = pps->getPPSMvdL1ZeroIdc() - 1;
+      }
+#else   
+      READ_FLAG( uiCode, "mvd_l1_zero_flag" );
+#endif      
+
+      pcSlice->setMvdL1ZeroFlag( (uiCode ? true : false) );
     }
 
     pcSlice->setCabacInitFlag( false ); // default
@@ -2100,7 +2180,18 @@ void HLSyntaxReader::parseSliceHeader (Slice* pcSlice, ParameterSetManager *para
     {
       if ( pcSlice->getSliceType() == B_SLICE )
       {
+#if JVET_O0238_PPS_OR_SLICE
+        if (!pps->getPPSCollocatedFromL0Idc())
+        {
+          READ_FLAG(uiCode, "collocated_from_l0_flag");
+        }
+        else
+        {
+          uiCode = pps->getPPSCollocatedFromL0Idc() - 1;
+        }
+#else    
         READ_FLAG( uiCode, "collocated_from_l0_flag" );
+#endif
         pcSlice->setColFromL0Flag(uiCode);
       }
       else
@@ -2140,7 +2231,19 @@ void HLSyntaxReader::parseSliceHeader (Slice* pcSlice, ParameterSetManager *para
         }
       }
     }
+#if JVET_O0238_PPS_OR_SLICE
+    if (!pps->getPPSDepQuantEnabledIdc())
+    {
+      READ_FLAG(uiCode, "dep_quant_enabled_flag");
+    }
+    else
+    {
+      uiCode = pps->getPPSDepQuantEnabledIdc() - 1;
+    }
+#else   
     READ_FLAG( uiCode, "dep_quant_enabled_flag" );
+#endif
+
     pcSlice->setDepQuantEnabledFlag( uiCode != 0 );
     if( !pcSlice->getDepQuantEnabledFlag() )
     {
@@ -2196,24 +2299,52 @@ void HLSyntaxReader::parseSliceHeader (Slice* pcSlice, ParameterSetManager *para
     if (!pcSlice->isIntra() || sps->getIBCFlag())
 #endif
     {
+#if JVET_O0238_PPS_OR_SLICE
+      if (!pps->getPPSSixMinusMaxNumMergeCandPlus1())
+      {
+        READ_UVLC(uiCode, "six_minus_max_num_merge_cand");
+      }
+      else
+      {
+        uiCode = pps->getPPSSixMinusMaxNumMergeCandPlus1() - 1;
+      }
+#else      
       READ_UVLC(uiCode, "six_minus_max_num_merge_cand");
+#endif
+
       pcSlice->setMaxNumMergeCand(MRG_MAX_NUM_CANDS - uiCode);
     }
 
     if (!pcSlice->isIntra())
     {
 #if JVET_O0263_O0220_SUBBLOCK_SYNTAX_CLEANUP
+#if JVET_O0238_PPS_OR_SLICE
+      if (pps->getSBTMVPEnabledFlag() && pcSlice->getEnableTMVPFlag() && !sps->getUseAffine()) // ATMVP only
+#else
       if (sps->getSBTMVPEnabledFlag() && pcSlice->getEnableTMVPFlag() && !sps->getUseAffine()) // ATMVP only
+#endif
+#else
+#if JVET_O0238_PPS_OR_SLICE
+      if ( pps->getSBTMVPEnabledFlag() && !sps->getUseAffine() ) // ATMVP only
 #else
       if ( sps->getSBTMVPEnabledFlag() && !sps->getUseAffine() ) // ATMVP only
+#endif
 #endif
       {
         pcSlice->setMaxNumAffineMergeCand( 1 );
       }
 #if JVET_O0263_O0220_SUBBLOCK_SYNTAX_CLEANUP
-      else if (!(sps->getSBTMVPEnabledFlag() && pcSlice->getEnableTMVPFlag()) && !sps->getUseAffine())// both off
+#if JVET_O0238_PPS_OR_SLICE
+	  else if (!(pps->getSBTMVPEnabledFlag() && pcSlice->getEnableTMVPFlag()) && !sps->getUseAffine())// both off
+#else
+	  else if (!(sps->getSBTMVPEnabledFlag() && pcSlice->getEnableTMVPFlag()) && !sps->getUseAffine())// both off
+#endif
+#else
+#if JVET_O0238_PPS_OR_SLICE
+      else if ( !pps->getSBTMVPEnabledFlag() && !sps->getUseAffine() ) // both off
 #else
       else if ( !sps->getSBTMVPEnabledFlag() && !sps->getUseAffine() ) // both off
+#endif
 #endif
       {
         pcSlice->setMaxNumAffineMergeCand( 0 );
@@ -2221,7 +2352,18 @@ void HLSyntaxReader::parseSliceHeader (Slice* pcSlice, ParameterSetManager *para
       else
       if ( sps->getUseAffine() )
       {
+#if JVET_O0238_PPS_OR_SLICE
+        if (!pps->getPPSFiveMinusMaxNumSubblockMergeCandPlus1())
+        {
+          READ_UVLC(uiCode, "five_minus_max_num_affine_merge_cand");
+        }
+        else
+        {
+          uiCode = pps->getPPSFiveMinusMaxNumSubblockMergeCandPlus1() - 1;
+        }
+#else        
         READ_UVLC( uiCode, "five_minus_max_num_affine_merge_cand" );
+#endif
         pcSlice->setMaxNumAffineMergeCand( AFFINE_MRG_MAX_NUM_CANDS - uiCode );
       }
       if ( sps->getFpelMmvdEnabledFlag() )
@@ -2238,7 +2380,18 @@ void HLSyntaxReader::parseSliceHeader (Slice* pcSlice, ParameterSetManager *para
 #endif
       if (sps->getUseTriangle() && pcSlice->getMaxNumMergeCand() >= 2)
       {
+#if JVET_O0238_PPS_OR_SLICE
+        if (!pps->getPPSMaxNumMergeCandMinusMaxNumTriangleCandPlus1()) 
+		{
+          READ_UVLC(uiCode, "max_num_merge_cand_minus_max_num_triangle_cand");
+        }
+        else
+        {
+          uiCode = pps->getPPSMaxNumMergeCandMinusMaxNumTriangleCandPlus1() - 1;
+        }
+#else
         READ_UVLC(uiCode, "max_num_merge_cand_minus_max_num_triangle_cand");
+#endif
         CHECK(pcSlice->getMaxNumMergeCand() < uiCode, "Incorrrect max number of triangle candidates!");
         pcSlice->setMaxNumTriangleCand((uint32_t)(pcSlice->getMaxNumMergeCand() - uiCode));
       }
diff --git a/source/Lib/EncoderLib/CABACWriter.cpp b/source/Lib/EncoderLib/CABACWriter.cpp
index b39731549..33ebcc38f 100644
--- a/source/Lib/EncoderLib/CABACWriter.cpp
+++ b/source/Lib/EncoderLib/CABACWriter.cpp
@@ -2269,8 +2269,12 @@ void CABACWriter::subblock_merge_flag( const CodingUnit& cu )
 
 #if JVET_O0220_METHOD1_SUBBLK_FLAG_PARSING
   if ( !cu.cs->slice->isIntra() && (cu.slice->getMaxNumAffineMergeCand() > 0) && cu.lumaSize().width >= 8 && cu.lumaSize().height >= 8 )
+#else
+#if JVET_O0238_PPS_OR_SLICE
+  if ( !cu.cs->slice->isIntra() && (cu.cs->sps->getUseAffine() || cu.cs->pps->getSBTMVPEnabledFlag()) && cu.lumaSize().width >= 8 && cu.lumaSize().height >= 8 )
 #else
   if ( !cu.cs->slice->isIntra() && (cu.cs->sps->getUseAffine() || cu.cs->sps->getSBTMVPEnabledFlag()) && cu.lumaSize().width >= 8 && cu.lumaSize().height >= 8 )
+#endif
 #endif
   {
     unsigned ctxId = DeriveCtx::CtxAffineFlag( cu );
diff --git a/source/Lib/EncoderLib/EncCfg.h b/source/Lib/EncoderLib/EncCfg.h
index 107a639a9..432176d3b 100644
--- a/source/Lib/EncoderLib/EncCfg.h
+++ b/source/Lib/EncoderLib/EncCfg.h
@@ -588,7 +588,20 @@ protected:
 #endif
   ScalingListMode m_useScalingListId;             ///< Using quantization matrix i.e. 0=off, 1=default, 2=file.
   std::string m_scalingListFileName;              ///< quantization matrix file name
+#if JVET_O0238_PPS_OR_SLICE
+  bool      m_constantSliceHeaderParamsEnabledFlag;
+  int       m_PPSDepQuantEnabledIdc;
+  int       m_PPSRefPicListSPSIdc0;
+  int       m_PPSRefPicListSPSIdc1;
+  int       m_PPSTemporalMVPEnabledIdc;
+  int       m_PPSMvdL1ZeroIdc;                       
+  int       m_PPSCollocatedFromL0Idc;                            
+  uint32_t  m_PPSSixMinusMaxNumMergeCandPlus1;                        
+  uint32_t  m_PPSFiveMinusMaxNumSubblockMergeCandPlus1;
+  uint32_t  m_PPSMaxNumMergeCandMinusMaxNumTriangleCandPlus1;
+#else
   int       m_TMVPModeId;
+#endif
   bool      m_DepQuantEnabledFlag;
   bool      m_SignDataHidingEnabledFlag;
   bool      m_RCEnableRateControl;
@@ -1503,8 +1516,31 @@ public:
   ScalingListMode getUseScalingListId    ()                          { return m_useScalingListId;      }
   void         setScalingListFileName       ( const std::string &s ) { m_scalingListFileName = s;      }
   const std::string& getScalingListFileName () const                 { return m_scalingListFileName;   }
+#if JVET_O0238_PPS_OR_SLICE
+  void         setConstantSliceHeaderParamsEnabledFlag ( bool u )    { m_constantSliceHeaderParamsEnabledFlag = u; }
+  bool         getConstantSliceHeaderParamsEnabledFlag ()            { return m_constantSliceHeaderParamsEnabledFlag;}
+  void         setPPSDepQuantEnabledIdc ( int u )                    { m_PPSDepQuantEnabledIdc = u; }
+  int          getPPSDepQuantEnabledIdc ()                           { return m_PPSDepQuantEnabledIdc;}
+  void         setPPSRefPicListSPSIdc0 ( int u )                     { m_PPSRefPicListSPSIdc0 = u; }
+  int          getPPSRefPicListSPSIdc0 ()                            { return m_PPSRefPicListSPSIdc0; }
+  void         setPPSRefPicListSPSIdc1 ( int u )                     { m_PPSRefPicListSPSIdc1 = u; }
+  int          getPPSRefPicListSPSIdc1 ()                            { return m_PPSRefPicListSPSIdc1; }
+  void         setPPSTemporalMVPEnabledIdc ( int u )                 { m_PPSTemporalMVPEnabledIdc = u; }
+  int          getPPSTemporalMVPEnabledIdc ()                        { return m_PPSTemporalMVPEnabledIdc; }
+  void         setPPSMvdL1ZeroIdc ( int u )                          { m_PPSMvdL1ZeroIdc = u; }
+  int          getPPSMvdL1ZeroIdc ()                                 { return m_PPSMvdL1ZeroIdc; }                      
+  void         setPPSCollocatedFromL0Idc ( int u )                   { m_PPSCollocatedFromL0Idc = u; }
+  int          getPPSCollocatedFromL0Idc ()                          { return m_PPSCollocatedFromL0Idc; }
+  void         setPPSSixMinusMaxNumMergeCandPlus1 ( uint32_t u )     { m_PPSSixMinusMaxNumMergeCandPlus1 = u; }
+  uint32_t	   getPPSSixMinusMaxNumMergeCandPlus1 ()                 { return m_PPSSixMinusMaxNumMergeCandPlus1; }                        
+  void         setPPSFiveMinusMaxNumSubblockMergeCandPlus1 ( uint32_t u ) { m_PPSFiveMinusMaxNumSubblockMergeCandPlus1 = u; }
+  uint32_t     getPPSFiveMinusMaxNumSubblockMergeCandPlus1 ()        { return m_PPSFiveMinusMaxNumSubblockMergeCandPlus1; }
+  void         setPPSMaxNumMergeCandMinusMaxNumTriangleCandPlus1 ( uint32_t u ) { m_PPSMaxNumMergeCandMinusMaxNumTriangleCandPlus1 = u; }
+  uint32_t     getPPSMaxNumMergeCandMinusMaxNumTriangleCandPlus1 ()  { return m_PPSMaxNumMergeCandMinusMaxNumTriangleCandPlus1; }
+#else
   void         setTMVPModeId ( int  u )                              { m_TMVPModeId = u;    }
   int          getTMVPModeId ()                                      { return m_TMVPModeId; }
+#endif
   WeightedPredictionMethod getWeightedPredictionMethod() const       { return m_weightedPredictionMethod; }
   void         setWeightedPredictionMethod( WeightedPredictionMethod m ) { m_weightedPredictionMethod = m; }
   void         setDepQuantEnabledFlag( bool b )                      { m_DepQuantEnabledFlag = b;    }
diff --git a/source/Lib/EncoderLib/EncCu.cpp b/source/Lib/EncoderLib/EncCu.cpp
index f8bfd4c08..701541f40 100644
--- a/source/Lib/EncoderLib/EncCu.cpp
+++ b/source/Lib/EncoderLib/EncCu.cpp
@@ -2583,7 +2583,14 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
   MergeCtx mergeCtx;
   const SPS &sps = *tempCS->sps;
 
+#if JVET_O0238_PPS_OR_SLICE
+  const PPS &pps = *tempCS->pps;
+
+  if( pps.getSBTMVPEnabledFlag() )
+#else
   if( sps.getSBTMVPEnabledFlag() )
+#endif
+
   {
     Size bufSize = g_miScaling.scale( tempCS->area.lumaSize() );
     mergeCtx.subPuMvpMiBuf    = MotionBuf( m_SubPuMiBuf,    bufSize );
@@ -3467,7 +3474,13 @@ void EncCu::xCheckRDCostAffineMerge2Nx2N( CodingStructure *&tempCS, CodingStruct
   const SPS &sps = *tempCS->sps;
 
   MergeCtx mrgCtx;
+#if JVET_O0238_PPS_OR_SLICE
+  const PPS &pps = *tempCS->pps;
+
+  if ( pps.getSBTMVPEnabledFlag() )
+#else
   if ( sps.getSBTMVPEnabledFlag() )
+#endif
   {
     Size bufSize = g_miScaling.scale( tempCS->area.lumaSize() );
     mrgCtx.subPuMvpMiBuf = MotionBuf( m_SubPuMiBuf, bufSize );
@@ -3749,8 +3762,13 @@ void EncCu::xCheckRDCostIBCModeMerge2Nx2N(CodingStructure *&tempCS, CodingStruct
   tempCS->initStructData(encTestMode.qp, encTestMode.lossless);
   MergeCtx mergeCtx;
 
+#if JVET_O0238_PPS_OR_SLICE
+  const PPS &pps = *tempCS->pps;
 
+  if (pps.getSBTMVPEnabledFlag())
+#else
   if (sps.getSBTMVPEnabledFlag())
+#endif
   {
     Size bufSize = g_miScaling.scale(tempCS->area.lumaSize());
     mergeCtx.subPuMvpMiBuf = MotionBuf(m_SubPuMiBuf, bufSize);
diff --git a/source/Lib/EncoderLib/EncGOP.cpp b/source/Lib/EncoderLib/EncGOP.cpp
index 5835f3c64..ca5ac304d 100644
--- a/source/Lib/EncoderLib/EncGOP.cpp
+++ b/source/Lib/EncoderLib/EncGOP.cpp
@@ -2190,6 +2190,7 @@ void EncGOP::compressGOP( int iPOCLast, int iNumPicRcvd, PicList& rcListPic,
 
     pcSlice->setList1IdxToList0Idx();
 
+#if !JVET_O0238_PPS_OR_SLICE
     if (m_pcEncLib->getTMVPModeId() == 2)
     {
       if (iGOPid == 0) // first picture in SOP (i.e. forward B)
@@ -2202,7 +2203,12 @@ void EncGOP::compressGOP( int iPOCLast, int iNumPicRcvd, PicList& rcListPic,
         pcSlice->setEnableTMVPFlag(1);
       }
     }
+#endif
+#if JVET_O0238_PPS_OR_SLICE
+	if (m_pcEncLib->getPPSTemporalMVPEnabledIdc() != 1)
+#else
     else if (m_pcEncLib->getTMVPModeId() == 1)
+#endif
     {
       pcSlice->setEnableTMVPFlag(1);
     }
diff --git a/source/Lib/EncoderLib/EncLib.cpp b/source/Lib/EncoderLib/EncLib.cpp
index 963cd63e6..4fa176855 100644
--- a/source/Lib/EncoderLib/EncLib.cpp
+++ b/source/Lib/EncoderLib/EncLib.cpp
@@ -1065,7 +1065,9 @@ void EncLib::xInitSPS(SPS &sps)
   sps.setIDRRefParamListPresent              ( m_idrRefParamList );
   sps.setUseDualITree                        ( m_dualITree );
   sps.setUseLFNST                            ( m_LFNST );
+#if !JVET_O0238_PPS_OR_SLICE
   sps.setSBTMVPEnabledFlag                  ( m_SubPuMvpMode );
+#endif
   sps.setAMVREnabledFlag                ( m_ImvMode != IMV_OFF );
   sps.setBDOFEnabledFlag                    ( m_BIO );
   sps.setUseAffine             ( m_Affine );
@@ -1143,7 +1145,9 @@ void EncLib::xInitSPS(SPS &sps)
   sps.setBDPCMEnabledFlag(m_useBDPCM);
 #endif
 
+#if !JVET_O0238_PPS_OR_SLICE
   sps.setSPSTemporalMVPEnabledFlag((getTMVPModeId() == 2 || getTMVPModeId() == 1));
+#endif
 
 #if MAX_TB_SIZE_SIGNALLING
   sps.setLog2MaxTbSize   ( m_log2MaxTbSize );
@@ -1266,6 +1270,21 @@ void EncLib::xInitPPS(PPS &pps, const SPS &sps)
   // pps ID already initialised.
   pps.setSPSId(sps.getSPSId());
 
+  #if JVET_O0238_PPS_OR_SLICE
+  pps.setConstantSliceHeaderParamsEnabledFlag(getConstantSliceHeaderParamsEnabledFlag());
+  pps.setPPSDepQuantEnabledIdc(getPPSDepQuantEnabledIdc());
+  pps.setPPSRefPicListSPSIdc0(getPPSRefPicListSPSIdc0());
+  pps.setPPSRefPicListSPSIdc1(getPPSRefPicListSPSIdc1());
+  pps.setPPSTemporalMVPEnabledIdc(getPPSTemporalMVPEnabledIdc());
+  pps.setPPSMvdL1ZeroIdc(getPPSMvdL1ZeroIdc());
+  pps.setPPSCollocatedFromL0Idc(getPPSCollocatedFromL0Idc());
+  pps.setPPSSixMinusMaxNumMergeCandPlus1(getPPSSixMinusMaxNumMergeCandPlus1());
+  pps.setPPSFiveMinusMaxNumSubblockMergeCandPlus1(getPPSFiveMinusMaxNumSubblockMergeCandPlus1());  
+  pps.setPPSMaxNumMergeCandMinusMaxNumTriangleCandPlus1(getPPSMaxNumMergeCandMinusMaxNumTriangleCandPlus1());
+ 
+  pps.setSBTMVPEnabledFlag ( m_SubPuMvpMode );
+#endif
+
   pps.setConstrainedIntraPred( m_bUseConstrainedIntraPred );
   bool bUseDQP = (getCuQpDeltaSubdiv() > 0)? true : false;
 
diff --git a/source/Lib/EncoderLib/EncModeCtrl.cpp b/source/Lib/EncoderLib/EncModeCtrl.cpp
index 977571e9d..2193c9740 100644
--- a/source/Lib/EncoderLib/EncModeCtrl.cpp
+++ b/source/Lib/EncoderLib/EncModeCtrl.cpp
@@ -1450,7 +1450,11 @@ void EncModeCtrlMTnoRQT::initCULevel( Partitioner &partitioner, const CodingStru
           m_ComprCUCtxList.back().testModes.push_back( { ETM_MERGE_TRIANGLE, ETO_STANDARD, qp, lossless } );
         }
         m_ComprCUCtxList.back().testModes.push_back( { ETM_MERGE_SKIP,  ETO_STANDARD, qp, lossless } );
+#if JVET_O0238_PPS_OR_SLICE
+        if ( cs.sps->getUseAffine() || cs.pps->getSBTMVPEnabledFlag() )
+#else
         if ( cs.sps->getUseAffine() || cs.sps->getSBTMVPEnabledFlag() )
+#endif
         {
           m_ComprCUCtxList.back().testModes.push_back( { ETM_AFFINE,    ETO_STANDARD, qp, lossless } );
         }
@@ -1464,7 +1468,11 @@ void EncModeCtrlMTnoRQT::initCULevel( Partitioner &partitioner, const CodingStru
           m_ComprCUCtxList.back().testModes.push_back( { ETM_MERGE_TRIANGLE, ETO_STANDARD, qp, lossless } );
         }
         m_ComprCUCtxList.back().testModes.push_back( { ETM_MERGE_SKIP,  ETO_STANDARD, qp, lossless } );
+#if JVET_O0238_PPS_OR_SLICE
+        if ( cs.sps->getUseAffine() || cs.pps->getSBTMVPEnabledFlag() )
+#else
         if ( cs.sps->getUseAffine() || cs.sps->getSBTMVPEnabledFlag() )
+#endif
         {
           m_ComprCUCtxList.back().testModes.push_back( { ETM_AFFINE,    ETO_STANDARD, qp, lossless } );
         }
diff --git a/source/Lib/EncoderLib/InterSearch.cpp b/source/Lib/EncoderLib/InterSearch.cpp
index 267efd0b8..329b20568 100644
--- a/source/Lib/EncoderLib/InterSearch.cpp
+++ b/source/Lib/EncoderLib/InterSearch.cpp
@@ -2389,7 +2389,11 @@ void InterSearch::predInterSearch(CodingUnit& cu, Partitioner& partitioner)
 
     CHECK(pu.cu != &cu, "PU is contained in another CU");
 
+#if JVET_O0238_PPS_OR_SLICE
+    if (cu.cs->pps->getSBTMVPEnabledFlag())
+#else
     if (cu.cs->sps->getSBTMVPEnabledFlag())
+#endif
     {
       Size bufSize = g_miScaling.scale(pu.lumaSize());
       mergeCtx.subPuMvpMiBuf = MotionBuf(m_SubPuMiBuf, bufSize);
diff --git a/source/Lib/EncoderLib/VLCWriter.cpp b/source/Lib/EncoderLib/VLCWriter.cpp
index a6f144186..402963e6c 100644
--- a/source/Lib/EncoderLib/VLCWriter.cpp
+++ b/source/Lib/EncoderLib/VLCWriter.cpp
@@ -239,6 +239,25 @@ void HLSWriter::codePPS( const PPS* pcPPS )
   WRITE_UVLC( pcPPS->getNumRefIdxL1DefaultActive()-1,     "num_ref_idx_l1_default_active_minus1");
   WRITE_FLAG(pcPPS->getRpl1IdxPresentFlag() ? 1 : 0, "rpl1IdxPresentFlag");
 
+  #if JVET_O0238_PPS_OR_SLICE
+  WRITE_FLAG( pcPPS->getConstantSliceHeaderParamsEnabledFlag(),              "constant_slice_header_params_enabled_flag");
+  if ( pcPPS->getConstantSliceHeaderParamsEnabledFlag() ) {
+    WRITE_CODE( pcPPS->getPPSDepQuantEnabledIdc(), 2,                        "pps_dep_quant_enabled_idc");
+    WRITE_CODE( pcPPS->getPPSRefPicListSPSIdc0(), 2,                         "pps_ref_pic_list_sps_idc[0]");
+    WRITE_CODE( pcPPS->getPPSRefPicListSPSIdc1(), 2,                         "pps_ref_pic_list_sps_idc[1]");
+    WRITE_CODE( pcPPS->getPPSTemporalMVPEnabledIdc(), 2,                     "pps_temporal_mvp_enabled_idc");
+    WRITE_CODE( pcPPS->getPPSMvdL1ZeroIdc(), 2,                              "pps_mvd_l1_zero_idc");
+    WRITE_CODE( pcPPS->getPPSCollocatedFromL0Idc(), 2,                       "pps_collocated_from_l0_idc");
+    WRITE_UVLC( pcPPS->getPPSSixMinusMaxNumMergeCandPlus1(),                 "pps_six_minus_max_num_merge_cand_plus1");
+    WRITE_UVLC( pcPPS->getPPSFiveMinusMaxNumSubblockMergeCandPlus1(),        "pps_five_minus_max_num_subblock_merge_cand_plus1");
+    WRITE_UVLC( pcPPS->getPPSMaxNumMergeCandMinusMaxNumTriangleCandPlus1(),  "pps_max_num_merge_cand_minus_max_num_triangle_cand_plus1");
+  }
+  if ( pcPPS->getPPSTemporalMVPEnabledIdc() != 1 )
+  {
+    WRITE_FLAG( pcPPS->getSBTMVPEnabledFlag() ? 1 : 0,                       "pps_sbtmvp_enabled_flag");
+  }
+#endif
+
   WRITE_SVLC( pcPPS->getPicInitQPMinus26(),                  "init_qp_minus26");
   WRITE_FLAG( pcPPS->getConstrainedIntraPred() ? 1 : 0,      "constrained_intra_pred_flag" );
 #if !JVET_O1136_TS_BDPCM_SIGNALLING
@@ -942,12 +961,14 @@ void HLSWriter::codeSPS( const SPS* pcSPS )
   }
 #endif
 
+#if !JVET_O0238_PPS_OR_SLICE
   WRITE_FLAG( pcSPS->getSPSTemporalMVPEnabledFlag()  ? 1 : 0,                        "sps_temporal_mvp_enabled_flag" );
 
   if ( pcSPS->getSPSTemporalMVPEnabledFlag() )
   {
     WRITE_FLAG( pcSPS->getSBTMVPEnabledFlag() ? 1 : 0,                               "sps_sbtmvp_enabled_flag");
   }
+#endif
 
   WRITE_FLAG( pcSPS->getAMVREnabledFlag() ? 1 : 0,                                   "sps_amvr_enabled_flag" );
 
@@ -1238,7 +1259,14 @@ void HLSWriter::codeSliceHeader         ( Slice* pcSlice )
       //Write L0 related syntax elements
       if (pcSlice->getSPS()->getNumRPL0() > 0)
       {
+#if JVET_O0238_PPS_OR_SLICE
+        if (!pcSlice->getPPS()->getPPSRefPicListSPSIdc0())
+        {
+          WRITE_FLAG(pcSlice->getRPL0idx() != -1 ? 1 : 0, "ref_pic_list_sps_flag[0]");
+        } 
+#else
         WRITE_FLAG(pcSlice->getRPL0idx() != -1 ? 1 : 0, "ref_pic_list_sps_flag[0]");
+#endif
       }
       if (pcSlice->getRPL0idx() != -1)
       {
@@ -1293,7 +1321,14 @@ void HLSWriter::codeSliceHeader         ( Slice* pcSlice )
       {
         if (pcSlice->getSPS()->getNumRPL1() > 0)
         {
+#if JVET_O0238_PPS_OR_SLICE
+        if (!pcSlice->getPPS()->getPPSRefPicListSPSIdc1())
+        {
           WRITE_FLAG(pcSlice->getRPL1idx() != -1 ? 1 : 0, "ref_pic_list_sps_flag[1]");
+        } 
+#else
+          WRITE_FLAG(pcSlice->getRPL1idx() != -1 ? 1 : 0, "ref_pic_list_sps_flag[1]");
+#endif
         }
         if (pcSlice->getRPL1idx() != -1)
         {
@@ -1331,10 +1366,18 @@ void HLSWriter::codeSliceHeader         ( Slice* pcSlice )
           }
         }
       }
+#if JVET_O0238_PPS_OR_SLICE
+      if( !pcSlice->getPPS()->getPPSTemporalMVPEnabledIdc() )
+      {
+        WRITE_FLAG( pcSlice->getEnableTMVPFlag() ? 1 : 0, "slice_temporal_mvp_enabled_flag" );
+      }
+#else
       if( pcSlice->getSPS()->getSPSTemporalMVPEnabledFlag() )
       {
         WRITE_FLAG( pcSlice->getEnableTMVPFlag() ? 1 : 0, "slice_temporal_mvp_enabled_flag" );
       }
+#endif
+
     }
     if( pcSlice->getSPS()->getSAOEnabledFlag() )
     {
@@ -1465,7 +1508,14 @@ void HLSWriter::codeSliceHeader         ( Slice* pcSlice )
 
     if( pcSlice->isInterB() )
     {
+#if JVET_O0238_PPS_OR_SLICE
+      if (!pcSlice->getPPS()->getPPSMvdL1ZeroIdc())
+      {
+		    WRITE_FLAG( pcSlice->getMvdL1ZeroFlag() ? 1 : 0, "mvd_l1_zero_flag" );
+      }
+#else
       WRITE_FLAG( pcSlice->getMvdL1ZeroFlag() ? 1 : 0, "mvd_l1_zero_flag" );
+#endif
     }
 
     if( !pcSlice->isIntra() )
@@ -1484,7 +1534,14 @@ void HLSWriter::codeSliceHeader         ( Slice* pcSlice )
     {
       if( pcSlice->getSliceType() == B_SLICE )
       {
+#if JVET_O0238_PPS_OR_SLICE
+        if (!pcSlice->getPPS()->getPPSCollocatedFromL0Idc())
+        {
+			     WRITE_FLAG( pcSlice->getColFromL0Flag(), "collocated_from_l0_flag" );
+        }
+#else
         WRITE_FLAG( pcSlice->getColFromL0Flag(), "collocated_from_l0_flag" );
+#endif
       }
 
       if( pcSlice->getSliceType() != I_SLICE &&
@@ -1498,7 +1555,14 @@ void HLSWriter::codeSliceHeader         ( Slice* pcSlice )
     {
       xCodePredWeightTable( pcSlice );
     }
+#if JVET_O0238_PPS_OR_SLICE
+    if (!pcSlice->getPPS()->getPPSDepQuantEnabledIdc())
+    {
+		   WRITE_FLAG( pcSlice->getDepQuantEnabledFlag() ? 1 : 0, "dep_quant_enabled_flag" );
+    }
+#else
     WRITE_FLAG( pcSlice->getDepQuantEnabledFlag() ? 1 : 0, "dep_quant_enabled_flag" );
+#endif
     if( !pcSlice->getDepQuantEnabledFlag() )
     {
       WRITE_FLAG( pcSlice->getSignDataHidingEnabledFlag() ? 1 : 0, "sign_data_hiding_enabled_flag" );
@@ -1546,23 +1610,46 @@ void HLSWriter::codeSliceHeader         ( Slice* pcSlice )
 #endif
     {
       CHECK(pcSlice->getMaxNumMergeCand() > MRG_MAX_NUM_CANDS, "More merge candidates signalled than supported");
+#if JVET_O0238_PPS_OR_SLICE      
+      if (!pcSlice->getPPS()->getPPSSixMinusMaxNumMergeCandPlus1())
+      {
+		    WRITE_UVLC(MRG_MAX_NUM_CANDS - pcSlice->getMaxNumMergeCand(), "six_minus_max_num_merge_cand");
+      }
+#else
       WRITE_UVLC(MRG_MAX_NUM_CANDS - pcSlice->getMaxNumMergeCand(), "six_minus_max_num_merge_cand");
+#endif
     }
     if( !pcSlice->isIntra() )
     {
 #if JVET_O0263_O0220_SUBBLOCK_SYNTAX_CLEANUP
+#if JVET_O0238_PPS_OR_SLICE
+      if (pcSlice->getPPS()->getSBTMVPEnabledFlag() && pcSlice->getEnableTMVPFlag() && !pcSlice->getSPS()->getUseAffine())// ATMVP only
+#else
       if (pcSlice->getSPS()->getSBTMVPEnabledFlag() && pcSlice->getEnableTMVPFlag() && !pcSlice->getSPS()->getUseAffine())// ATMVP only
+#endif
+#else
+#if JVET_O0238_PPS_OR_SLICE
+      if ( pcSlice->getPPS()->getSBTMVPEnabledFlag() && !pcSlice->getSPS()->getUseAffine() ) // ATMVP only
 #else
       if ( pcSlice->getSPS()->getSBTMVPEnabledFlag() && !pcSlice->getSPS()->getUseAffine() ) // ATMVP only
+#endif
 #endif
       {
         CHECK( pcSlice->getMaxNumAffineMergeCand() != 1, "Sub-block merge can number should be 1" );
       }
       else
 #if JVET_O0263_O0220_SUBBLOCK_SYNTAX_CLEANUP
+#if JVET_O0238_PPS_OR_SLICE
+      if (!(pcSlice->getPPS()->getSBTMVPEnabledFlag() && pcSlice->getEnableTMVPFlag()) && !pcSlice->getSPS()->getUseAffine()) // both off
+#else
       if (!(pcSlice->getSPS()->getSBTMVPEnabledFlag() && pcSlice->getEnableTMVPFlag()) && !pcSlice->getSPS()->getUseAffine()) // both off
+#endif
+#else
+#if JVET_O0238_PPS_OR_SLICE
+      if ( !pcSlice->getPPS()->getSBTMVPEnabledFlag() && !pcSlice->getSPS()->getUseAffine() ) // both off
 #else
       if ( !pcSlice->getSPS()->getSBTMVPEnabledFlag() && !pcSlice->getSPS()->getUseAffine() ) // both off
+#endif
 #endif
       {
         CHECK( pcSlice->getMaxNumAffineMergeCand() != 0, "Sub-block merge can number should be 0" );
@@ -1571,7 +1658,14 @@ void HLSWriter::codeSliceHeader         ( Slice* pcSlice )
       if ( pcSlice->getSPS()->getUseAffine() )
       {
         CHECK( pcSlice->getMaxNumAffineMergeCand() > AFFINE_MRG_MAX_NUM_CANDS, "More affine merge candidates signalled than supported" );
+#if JVET_O0238_PPS_OR_SLICE
+        if (!pcSlice->getPPS()->getPPSFiveMinusMaxNumSubblockMergeCandPlus1())
+        {
+			WRITE_UVLC( AFFINE_MRG_MAX_NUM_CANDS - pcSlice->getMaxNumAffineMergeCand(), "five_minus_max_num_affine_merge_cand" );        
+        }
+#else
         WRITE_UVLC( AFFINE_MRG_MAX_NUM_CANDS - pcSlice->getMaxNumAffineMergeCand(), "five_minus_max_num_affine_merge_cand" );
+#endif
       }
       if ( pcSlice->getSPS()->getFpelMmvdEnabledFlag() )
       {
@@ -1586,7 +1680,14 @@ void HLSWriter::codeSliceHeader         ( Slice* pcSlice )
       if (pcSlice->getSPS()->getUseTriangle() && pcSlice->getMaxNumMergeCand() >= 2)
       {
         CHECK(pcSlice->getMaxNumMergeCand() < pcSlice->getMaxNumTriangleCand(), "Incorrrect max number of triangle candidates!");
+#if JVET_O0238_PPS_OR_SLICE
+        if (!pcSlice->getPPS()->getPPSMaxNumMergeCandMinusMaxNumTriangleCandPlus1()) 
+        {
+			     WRITE_UVLC(pcSlice->getMaxNumMergeCand() - pcSlice->getMaxNumTriangleCand(), "max_num_merge_cand_minus_max_num_triangle_cand");
+        }
+#else
         WRITE_UVLC(pcSlice->getMaxNumMergeCand() - pcSlice->getMaxNumTriangleCand(), "max_num_merge_cand_minus_max_num_triangle_cand");
+#endif
       }
       else
       {
-- 
GitLab