From 68f456222cbe25116995703d5f88eebc200acce6 Mon Sep 17 00:00:00 2001
From: Karsten Suehring <karsten.suehring@hhi.fraunhofer.de>
Date: Wed, 15 Apr 2020 11:55:50 +0200
Subject: [PATCH] Refactor: convert static arrays into vectors

- converts static arrays to vectors for subpicture related parameters
- improved encoder parameter checking
- mode automatic calculation of subpicture ID length at encoder
- update theoretical limit of maximum number of subpictures
---
 doc/software-manual.tex             |  1 +
 source/App/EncoderApp/EncApp.cpp    | 36 ++++-------
 source/App/EncoderApp/EncAppCfg.cpp | 52 ++++++++++-----
 source/App/EncoderApp/EncAppCfg.h   |  6 +-
 source/Lib/CommonLib/CommonDef.h    |  2 +-
 source/Lib/CommonLib/Slice.cpp      |  6 --
 source/Lib/CommonLib/Slice.h        | 99 ++++++++++++++++++-----------
 source/Lib/DecoderLib/VLCReader.cpp |  9 +--
 source/Lib/EncoderLib/EncCfg.h      | 37 ++++++++---
 source/Lib/EncoderLib/EncLib.cpp    | 29 +++------
 source/Lib/EncoderLib/VLCWriter.cpp |  4 ++
 11 files changed, 156 insertions(+), 125 deletions(-)

diff --git a/doc/software-manual.tex b/doc/software-manual.tex
index 4a5521da6..1e948bbfe 100644
--- a/doc/software-manual.tex
+++ b/doc/software-manual.tex
@@ -2107,6 +2107,7 @@ Specifies wheter to signal the subpicture ID map in SPS or PPS. If SubPicIdMappi
 %\ShortOption{\None} &
 \Default{0} &
 Length of the subpicture IDs in bits. (1<<SubPicIdLen) must be bigger than the number of subpictures and the highes subpicture ID specifid in SubPicId. 
+If the value "0" is used, the encoder tries to determine the number of required bits from the number of subpictures or the highest subpicture ID. This mode should not be used, if merging of bistreams is intended. 
 \\
 
 \Option{SubPicId} &
diff --git a/source/App/EncoderApp/EncApp.cpp b/source/App/EncoderApp/EncApp.cpp
index 9af6405cb..80cf6c11d 100644
--- a/source/App/EncoderApp/EncApp.cpp
+++ b/source/App/EncoderApp/EncApp.cpp
@@ -425,38 +425,26 @@ void EncApp::xInitLibCfg()
 #endif
   {
     m_cEncLib.setNumSubPics                                      ( m_numSubPics );
-    for (int i = 0; i < m_numSubPics; i++)
-    {
-      m_cEncLib.setSubPicCtuTopLeftX                             ( m_subPicCtuTopLeftX[i], i );
-      m_cEncLib.setSubPicCtuTopLeftY                             ( m_subPicCtuTopLeftY[i], i );
-      m_cEncLib.setSubPicWidth                                   ( m_subPicWidth[i], i );
-      m_cEncLib.setSubPicHeight                                  ( m_subPicHeight[i], i );
-      m_cEncLib.setSubPicTreatedAsPicFlag                        ( m_subPicTreatedAsPicFlag[i], i );
-      m_cEncLib.setLoopFilterAcrossSubpicEnabledFlag             ( m_loopFilterAcrossSubpicEnabledFlag[i], i );
-    }
-  }
-
-#if JVET_Q0119_CLEANUPS
-  m_cEncLib.setSubPicIdMappingExplicitlySignalledFlag            ( m_subPicIdMappingExplicitlySignalledFlag );
-  if (m_subPicIdMappingExplicitlySignalledFlag)
-  {
+    m_cEncLib.setSubPicCtuTopLeftX                               ( m_subPicCtuTopLeftX );
+    m_cEncLib.setSubPicCtuTopLeftY                               ( m_subPicCtuTopLeftY );
+    m_cEncLib.setSubPicWidth                                     ( m_subPicWidth );
+    m_cEncLib.setSubPicHeight                                    ( m_subPicHeight );
+    m_cEncLib.setSubPicTreatedAsPicFlag                          ( m_subPicTreatedAsPicFlag );
+    m_cEncLib.setLoopFilterAcrossSubpicEnabledFlag               ( m_loopFilterAcrossSubpicEnabledFlag );
     m_cEncLib.setSubPicIdMappingInSpsFlag                        ( m_subPicIdMappingInSpsFlag );
-    if(m_subPicIdMappingInSpsFlag)
+    m_cEncLib.setSubPicIdLen                                     ( m_subPicIdLen );
+#if JVET_Q0119_CLEANUPS
+    m_cEncLib.setSubPicIdMappingExplicitlySignalledFlag          ( m_subPicIdMappingExplicitlySignalledFlag );
+    if (m_subPicIdMappingExplicitlySignalledFlag)
 #else
-  m_cEncLib.setSubPicIdPresentFlag                               ( m_subPicIdPresentFlag );
-  if (m_subPicIdPresentFlag) 
-  {
     m_cEncLib.setSubPicIdSignallingPresentFlag                   ( m_subPicIdSignallingPresentFlag );
     if(m_subPicIdSignallingPresentFlag)
 #endif
     {
-      m_cEncLib.setSubPicIdLen                                   ( m_subPicIdLen );
-      for (int i = 0; i < m_numSubPics; i++)
-      {
-        m_cEncLib.setSubPicId                                    ( m_subPicId[i], i );
-      }
+      m_cEncLib.setSubPicId                                      ( m_subPicId );
     }
   }
+
   m_cEncLib.setUseSplitConsOverride                              ( m_SplitConsOverrideEnabledFlag );
   m_cEncLib.setMinQTSizes                                        ( m_uiMinQT );
   m_cEncLib.setMaxMTTHierarchyDepth                              ( m_uiMaxMTTHierarchyDepth, m_uiMaxMTTHierarchyDepthI, m_uiMaxMTTHierarchyDepthIChroma );
diff --git a/source/App/EncoderApp/EncAppCfg.cpp b/source/App/EncoderApp/EncAppCfg.cpp
index 087269d5c..7470907d4 100644
--- a/source/App/EncoderApp/EncAppCfg.cpp
+++ b/source/App/EncoderApp/EncAppCfg.cpp
@@ -751,9 +751,9 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] )
   SMultiValueInput<uint32_t>  cfg_subPicCtuTopLeftY(0, std::numeric_limits<uint32_t>::max(), 0, MAX_NUM_SUB_PICS);
   SMultiValueInput<uint32_t>  cfg_subPicWidth(1, std::numeric_limits<uint32_t>::max(), 0, MAX_NUM_SUB_PICS);
   SMultiValueInput<uint32_t>  cfg_subPicHeight(1, std::numeric_limits<uint32_t>::max(), 0, MAX_NUM_SUB_PICS);
-  SMultiValueInput<uint32_t>  cfg_subPicTreatedAsPicFlag(0, 1, 0, MAX_NUM_SUB_PICS);
-  SMultiValueInput<uint32_t>  cfg_loopFilterAcrossSubpicEnabledFlag(0, 1, 0, MAX_NUM_SUB_PICS);
-  SMultiValueInput<uint32_t>  cfg_subPicId(0, std::numeric_limits<uint32_t>::max(), 0, MAX_NUM_SUB_PICS);
+  SMultiValueInput<bool>      cfg_subPicTreatedAsPicFlag(0, 1, 0, MAX_NUM_SUB_PICS);
+  SMultiValueInput<bool>      cfg_loopFilterAcrossSubpicEnabledFlag(0, 1, 0, MAX_NUM_SUB_PICS);
+  SMultiValueInput<uint32_t>  cfg_subPicId(0, std::numeric_limits<uint16_t>::max(), 0, MAX_NUM_SUB_PICS);
 
 #if JVET_SUBPIC_LEVEL_CFG
   SMultiValueInput<int>          cfg_sliFractions(0, 100, 0, std::numeric_limits<int>::max());
@@ -1687,32 +1687,52 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] )
   if ( m_subPicPresentFlag )
 #endif
   {
-    CHECK( m_numSubPics > 255 || m_numSubPics < 1, "Number of subpicture must be within 1 to 255" );
+    CHECK( m_numSubPics > MAX_NUM_SUB_PICS || m_numSubPics < 1, "Number of subpicture must be within 1 to 2^16" );
+    CHECK( cfg_subPicCtuTopLeftX.values.size() != m_numSubPics, "Number of SubPicCtuTopLeftX values must be equal to NumSubPics");
+    CHECK( cfg_subPicCtuTopLeftY.values.size() != m_numSubPics, "Number of SubPicCtuTopLeftY values must be equal to NumSubPics");
+    CHECK( cfg_subPicWidth.values.size() != m_numSubPics, "Number of SubPicWidth values must be equal to NumSubPics");
+    CHECK( cfg_subPicHeight.values.size() != m_numSubPics, "Number of SubPicHeight values must be equal to NumSubPics");
+    CHECK( cfg_subPicTreatedAsPicFlag.values.size() != m_numSubPics, "Number of SubPicTreatedAsPicFlag values must be equal to NumSubPics");
+    CHECK( cfg_loopFilterAcrossSubpicEnabledFlag.values.size() != m_numSubPics, "Number of LoopFilterAcrossSubpicEnabledFlag values must be equal to NumSubPics");
+    if (m_subPicIdMappingExplicitlySignalledFlag)
+    {
+      CHECK( cfg_subPicId.values.size() != m_numSubPics, "Number of SubPicId values must be equal to NumSubPics");
+    }
     m_subPicCtuTopLeftX                 = cfg_subPicCtuTopLeftX.values;
     m_subPicCtuTopLeftY                 = cfg_subPicCtuTopLeftY.values;
     m_subPicWidth                       = cfg_subPicWidth.values;
     m_subPicHeight                      = cfg_subPicHeight.values;
     m_subPicTreatedAsPicFlag            = cfg_subPicTreatedAsPicFlag.values;
     m_loopFilterAcrossSubpicEnabledFlag = cfg_loopFilterAcrossSubpicEnabledFlag.values;
-    m_subPicId                          = cfg_subPicId.values;
-    for(int i = 0; i < m_numSubPics; i++)
+    if (m_subPicIdMappingExplicitlySignalledFlag)
     {
-      CHECK(m_subPicCtuTopLeftX[i] + m_subPicWidth[i] > (m_iSourceWidth + m_uiCTUSize - 1) / m_uiCTUSize, "subpicture must not exceed picture boundary");
-      CHECK(m_subPicCtuTopLeftY[i] + m_subPicHeight[i] > (m_iSourceHeight + m_uiCTUSize - 1) / m_uiCTUSize, "subpicture must not exceed picture boundary");
+      for (int i=0; i < m_numSubPics; i++)
+      {
+        m_subPicId[i]                   = cfg_subPicId.values[i];
+      }
     }
-#if JVET_Q0119_CLEANUPS
-    if (m_subPicIdMappingExplicitlySignalledFlag)
+    for(int i = 0; i < m_numSubPics; i++)
     {
-      if (m_subPicIdMappingInSpsFlag)
-#else
-    if (m_subPicIdPresentFlag) 
+      CHECK(m_subPicCtuTopLeftX[i] + m_subPicWidth[i] > (m_iSourceWidth + m_uiCTUSize - 1) / m_uiCTUSize, "Subpicture must not exceed picture boundary");
+      CHECK(m_subPicCtuTopLeftY[i] + m_subPicHeight[i] > (m_iSourceHeight + m_uiCTUSize - 1) / m_uiCTUSize, "Subpicture must not exceed picture boundary");
+    }
+    // automatically determine subpicture ID lenght in case it is not specified
+    if (m_subPicIdLen == 0)
     {
-      if (m_subPicIdSignallingPresentFlag) 
-#endif
+      if (m_subPicIdMappingExplicitlySignalledFlag)
       {
-        CHECK( m_subPicIdLen > 16, "sibpic ID length must not exceed 16 bits" );
+        // use the heighest specified ID
+        auto maxIdVal = std::max_element(m_subPicId.begin(),m_subPicId.end());
+        m_subPicIdLen = ceilLog2(*maxIdVal);
+      }
+      else
+      {
+        // use the number of subpictures
+        m_subPicIdLen = ceilLog2(m_numSubPics);
       }
     }
+
+    CHECK( m_subPicIdLen > 16, "SubPicIdLen must not exceed 16 bits" );
 #if JVET_Q0043_RPR_and_Subpics
     CHECK( m_rprEnabled, "RPR and subpictures cannot be enabled together" );
 #endif
diff --git a/source/App/EncoderApp/EncAppCfg.h b/source/App/EncoderApp/EncAppCfg.h
index 197ebafd8..0a82b669b 100644
--- a/source/App/EncoderApp/EncAppCfg.h
+++ b/source/App/EncoderApp/EncAppCfg.h
@@ -295,8 +295,8 @@ protected:
   std::vector<uint32_t> m_subPicCtuTopLeftY;
   std::vector<uint32_t> m_subPicWidth;
   std::vector<uint32_t> m_subPicHeight;
-  std::vector<uint32_t> m_subPicTreatedAsPicFlag;
-  std::vector<uint32_t> m_loopFilterAcrossSubpicEnabledFlag;
+  std::vector<bool>     m_subPicTreatedAsPicFlag;
+  std::vector<bool>     m_loopFilterAcrossSubpicEnabledFlag;
 #if JVET_Q0119_CLEANUPS
   bool m_subPicIdMappingExplicitlySignalledFlag;
   bool m_subPicIdMappingInSpsFlag;
@@ -305,7 +305,7 @@ protected:
   bool m_subPicIdSignallingPresentFlag;
 #endif
   unsigned m_subPicIdLen;
-  std::vector<uint32_t> m_subPicId;
+  std::vector<uint16_t> m_subPicId;
   bool      m_SplitConsOverrideEnabledFlag;
   unsigned  m_uiMinQT[3]; // 0: I slice luma; 1: P/B slice; 2: I slice chroma
   unsigned  m_uiMaxMTTHierarchyDepth;
diff --git a/source/Lib/CommonLib/CommonDef.h b/source/Lib/CommonLib/CommonDef.h
index 13997bbf0..834705078 100644
--- a/source/Lib/CommonLib/CommonDef.h
+++ b/source/Lib/CommonLib/CommonDef.h
@@ -287,7 +287,7 @@ static const int LUMA_INTERPOLATION_FILTER_SUB_SAMPLE_POSITIONS_SIGNAL = 1 << MV
 static const int LUMA_INTERPOLATION_FILTER_SUB_SAMPLE_POSITIONS = 1 << MV_FRACTIONAL_BITS_INTERNAL;
 static const int CHROMA_INTERPOLATION_FILTER_SUB_SAMPLE_POSITIONS = 1 << (MV_FRACTIONAL_BITS_INTERNAL + 1);
 
-static const int MAX_NUM_SUB_PICS =                               255;
+static const int MAX_NUM_SUB_PICS =                         (1 << 16);
 static const int MAX_NUM_LONG_TERM_REF_PICS =                      33;
 static const int NUM_LONG_TERM_REF_PIC_SPS =                        0;
 
diff --git a/source/Lib/CommonLib/Slice.cpp b/source/Lib/CommonLib/Slice.cpp
index 8b4e46e7d..7ab3aabff 100644
--- a/source/Lib/CommonLib/Slice.cpp
+++ b/source/Lib/CommonLib/Slice.cpp
@@ -2774,12 +2774,6 @@ SPS::SPS()
 #if JVET_Q0179_SCALING_WINDOW_SIZE_CONSTRAINT
   ::memset(m_ppsValidFlag, 0, sizeof(m_ppsValidFlag));
 #endif
-  ::memset(m_subPicCtuTopLeftX, 0, sizeof(m_subPicCtuTopLeftX));
-  ::memset(m_subPicCtuTopLeftY, 0, sizeof(m_subPicCtuTopLeftY));
-  ::memset(m_SubPicWidth, 0, sizeof(m_SubPicWidth));
-  ::memset(m_SubPicHeight, 0, sizeof(m_SubPicHeight));
-  ::memset(m_subPicTreatedAsPicFlag, 0, sizeof(m_subPicTreatedAsPicFlag));
-  ::memset(m_loopFilterAcrossSubpicEnabledFlag, 0, sizeof(m_loopFilterAcrossSubpicEnabledFlag));
 }
 
 SPS::~SPS()
diff --git a/source/Lib/CommonLib/Slice.h b/source/Lib/CommonLib/Slice.h
index 24cd03419..6254ec6d9 100644
--- a/source/Lib/CommonLib/Slice.h
+++ b/source/Lib/CommonLib/Slice.h
@@ -1337,13 +1337,13 @@ private:
 #else
   bool                  m_subPicPresentFlag;                    // indicates the presence of sub-pictures
 #endif
-  uint8_t               m_numSubPics;                        //!< number of sub-pictures used
-  uint32_t              m_subPicCtuTopLeftX[MAX_NUM_SUB_PICS];                
-  uint32_t              m_subPicCtuTopLeftY[MAX_NUM_SUB_PICS];                
-  uint32_t              m_SubPicWidth[MAX_NUM_SUB_PICS];                      
-  uint32_t              m_SubPicHeight[MAX_NUM_SUB_PICS];                     
-  bool                  m_subPicTreatedAsPicFlag[MAX_NUM_SUB_PICS];           
-  bool                  m_loopFilterAcrossSubpicEnabledFlag[MAX_NUM_SUB_PICS];
+  uint32_t              m_numSubPics;                        //!< number of sub-pictures used
+  std::vector<uint32_t> m_subPicCtuTopLeftX;
+  std::vector<uint32_t> m_subPicCtuTopLeftY;
+  std::vector<uint32_t> m_subPicWidth;
+  std::vector<uint32_t> m_subPicHeight;
+  std::vector<bool>     m_subPicTreatedAsPicFlag;
+  std::vector<bool>     m_loopFilterAcrossSubpicEnabledFlag;
 #if JVET_Q0119_CLEANUPS
   bool                  m_subPicIdMappingExplicitlySignalledFlag;
   bool                  m_subPicIdMappingInSpsFlag;
@@ -1352,7 +1352,7 @@ private:
   bool                  m_subPicIdSignallingPresentFlag;     //!< indicates the presence of sub-picture ID signalling in the SPS
 #endif
   uint32_t              m_subPicIdLen;                       //!< sub-picture ID length in bits
-  uint16_t              m_subPicId[MAX_NUM_SUB_PICS];        //!< sub-picture ID for each sub-picture in the sequence
+  std::vector<uint16_t> m_subPicId;                          //!< sub-picture ID for each sub-picture in the sequence
 
   int               m_log2MinCodingBlockSize;
 #if !JVET_Q0468_Q0469_MIN_LUMA_CB_AND_MIN_QT_FIX
@@ -1571,27 +1571,45 @@ public:
 #endif
 
 #if JVET_Q0119_CLEANUPS
-  void                    setSubPicInfoPresentFlag(bool b)                                                { m_subPicInfoPresentFlag = b;            }
-  bool                    getSubPicInfoPresentFlag() const                                                { return m_subPicInfoPresentFlag;         }
+  void      setSubPicInfoPresentFlag(bool b)                                                { m_subPicInfoPresentFlag = b;            }
+  bool      getSubPicInfoPresentFlag() const                                                { return m_subPicInfoPresentFlag;         }
 #else
-  void                    setSubPicPresentFlag(bool b)                                                    { m_subPicPresentFlag = b;                }
-  bool                    getSubPicPresentFlag() const                                                    { return m_subPicPresentFlag;             }
-#endif
-
-  void                    setNumSubPics( uint8_t u )                                                      { m_numSubPics = u;                        }
-  uint8_t                 getNumSubPics( ) const                                                          { return  m_numSubPics;                    }
-  void                    setSubPicCtuTopLeftX( int i, uint32_t u )                                       { CHECK( i >= MAX_NUM_SUB_PICS, "Sub-picture index exceeds valid range" ); m_subPicCtuTopLeftX[i] = u;                     }
-  uint32_t                getSubPicCtuTopLeftX( int i ) const                                             { CHECK( i >= MAX_NUM_SUB_PICS, "Sub-picture index exceeds valid range" ); return  m_subPicCtuTopLeftX[i];                 }
-  void                    setSubPicCtuTopLeftY( int i, uint32_t u )                                       { CHECK( i >= MAX_NUM_SUB_PICS, "Sub-picture index exceeds valid range" ); m_subPicCtuTopLeftY[i] = u;                     }
-  uint32_t                getSubPicCtuTopLeftY( int i ) const                                             { CHECK( i >= MAX_NUM_SUB_PICS, "Sub-picture index exceeds valid range" ); return  m_subPicCtuTopLeftY[i];                 }
-  void                    setSubPicWidth( int i, uint32_t u )                                             { CHECK( i >= MAX_NUM_SUB_PICS, "Sub-picture index exceeds valid range" ); m_SubPicWidth[i] = u;                           }
-  uint32_t                getSubPicWidth( int i ) const                                                   { CHECK( i >= MAX_NUM_SUB_PICS, "Sub-picture index exceeds valid range" ); return  m_SubPicWidth[i];                       }
-  void                    setSubPicHeight( int i, uint32_t u )                                            { CHECK( i >= MAX_NUM_SUB_PICS, "Sub-picture index exceeds valid range" ); m_SubPicHeight[i] = u;                          }
-  uint32_t                getSubPicHeight( int i ) const                                                  { CHECK( i >= MAX_NUM_SUB_PICS, "Sub-picture index exceeds valid range" ); return  m_SubPicHeight[i];                      }
-  void                    setSubPicTreatedAsPicFlag( int i, bool u )                                      { CHECK( i >= MAX_NUM_SUB_PICS, "Sub-picture index exceeds valid range" ); m_subPicTreatedAsPicFlag[i] = u;                }
-  bool                    getSubPicTreatedAsPicFlag( int i ) const                                        { CHECK( i >= MAX_NUM_SUB_PICS, "Sub-picture index exceeds valid range" ); return  m_subPicTreatedAsPicFlag[i];            }
-  void                    setLoopFilterAcrossSubpicEnabledFlag( int i, bool u )                           { CHECK( i >= MAX_NUM_SUB_PICS, "Sub-picture index exceeds valid range" ); m_loopFilterAcrossSubpicEnabledFlag[i] = u;     }
-  bool                    getLoopFilterAcrossSubpicEnabledFlag( int i ) const                             { CHECK( i >= MAX_NUM_SUB_PICS, "Sub-picture index exceeds valid range" ); return  m_loopFilterAcrossSubpicEnabledFlag[i]; }
+  void      setSubPicPresentFlag(bool b)                                                    { m_subPicPresentFlag = b;                }
+  bool      getSubPicPresentFlag() const                                                    { return m_subPicPresentFlag;             }
+#endif
+
+  void      setNumSubPics( uint32_t u )                                                     { CHECK( u >= MAX_NUM_SUB_PICS, "Maximum number of subpictures exceeded" );
+                                                                                              m_numSubPics = u;
+                                                                                              m_subPicCtuTopLeftX.resize(m_numSubPics);
+                                                                                              m_subPicCtuTopLeftY.resize(m_numSubPics);
+                                                                                              m_subPicWidth.resize(m_numSubPics);
+                                                                                              m_subPicHeight.resize(m_numSubPics);
+                                                                                              m_subPicTreatedAsPicFlag.resize(m_numSubPics);
+                                                                                              m_loopFilterAcrossSubpicEnabledFlag.resize(m_numSubPics);
+                                                                                              m_subPicId.resize(m_numSubPics);
+                                                                                            }
+  uint32_t  getNumSubPics( ) const                                                          { return  m_numSubPics;                           }
+  void      setSubPicCtuTopLeftX( int i, uint32_t u )                                       { m_subPicCtuTopLeftX[i] = u;                     }
+  uint32_t  getSubPicCtuTopLeftX( int i ) const                                             { return  m_subPicCtuTopLeftX[i];                 }
+  void      setSubPicCtuTopLeftY( int i, uint32_t u )                                       { m_subPicCtuTopLeftY[i] = u;                     }
+  uint32_t  getSubPicCtuTopLeftY( int i ) const                                             { return  m_subPicCtuTopLeftY[i];                 }
+  void      setSubPicWidth( int i, uint32_t u )                                             { m_subPicWidth[i] = u;                           }
+  uint32_t  getSubPicWidth( int i ) const                                                   { return  m_subPicWidth[i];                       }
+  void      setSubPicHeight( int i, uint32_t u )                                            { m_subPicHeight[i] = u;                          }
+  uint32_t  getSubPicHeight( int i ) const                                                  { return  m_subPicHeight[i];                      }
+  void      setSubPicTreatedAsPicFlag( int i, bool u )                                      { m_subPicTreatedAsPicFlag[i] = u;                }
+  bool      getSubPicTreatedAsPicFlag( int i ) const                                        { return  m_subPicTreatedAsPicFlag[i];            }
+  void      setLoopFilterAcrossSubpicEnabledFlag( int i, bool u )                           { m_loopFilterAcrossSubpicEnabledFlag[i] = u;     }
+  bool      getLoopFilterAcrossSubpicEnabledFlag( int i ) const                             { return  m_loopFilterAcrossSubpicEnabledFlag[i]; }
+
+  void      setSubPicCtuTopLeftX                        (const std::vector<uint32_t> &v)   { CHECK(v.size()!=m_numSubPics, "number of vector entries must be equal to numSubPics") ;m_subPicCtuTopLeftX = v; }
+  void      setSubPicCtuTopLeftY                        (const std::vector<uint32_t> &v)   { CHECK(v.size()!=m_numSubPics, "number of vector entries must be equal to numSubPics") ;m_subPicCtuTopLeftY = v; }
+  void      setSubPicWidth                              (const std::vector<uint32_t> &v)   { CHECK(v.size()!=m_numSubPics, "number of vector entries must be equal to numSubPics") ;m_subPicWidth = v; }
+  void      setSubPicHeight                             (const std::vector<uint32_t> &v)   { CHECK(v.size()!=m_numSubPics, "number of vector entries must be equal to numSubPics") ;m_subPicHeight = v; }
+  void      setSubPicTreatedAsPicFlag                   (const std::vector<bool> &v)       { CHECK(v.size()!=m_numSubPics, "number of vector entries must be equal to numSubPics") ;m_subPicTreatedAsPicFlag = v; }
+  void      setLoopFilterAcrossSubpicEnabledFlag        (const std::vector<bool> &v)       { CHECK(v.size()!=m_numSubPics, "number of vector entries must be equal to numSubPics") ;m_loopFilterAcrossSubpicEnabledFlag = v; }
+
+
 #if JVET_Q0119_CLEANUPS
   void                    setSubPicIdMappingExplicitlySignalledFlag( bool b )                             { m_subPicIdMappingExplicitlySignalledFlag = b;    }
   bool                    getSubPicIdMappingExplicitlySignalledFlag() const                               { return m_subPicIdMappingExplicitlySignalledFlag; }
@@ -1605,8 +1623,9 @@ public:
 #endif
   void                    setSubPicIdLen( uint32_t u )                                                    { m_subPicIdLen = u;                       }
   uint32_t                getSubPicIdLen() const                                                          { return  m_subPicIdLen;                   }
-  void                    setSubPicId( int i, uint16_t u )                                                { CHECK( i >= MAX_NUM_SUB_PICS, "Sub-picture index exceeds valid range" ); m_subPicId[i] = u;     }
-  uint16_t                getSubPicId( int i ) const                                                      { CHECK( i >= MAX_NUM_SUB_PICS, "Sub-picture index exceeds valid range" ); return  m_subPicId[i]; }
+  void                    setSubPicId( int i, uint16_t u )                                                { m_subPicId[i] = u;     }
+  uint16_t                getSubPicId( int i ) const                                                      { return  m_subPicId[i]; }
+  void                    setSubPicId(const std::vector<uint16_t> &v)                                     { CHECK(v.size()!=m_numSubPics, "number of vector entries must be equal to numSubPics") ; m_subPicId = v; }
 
   uint32_t                getNumLongTermRefPicSPS() const                                                 { return m_numLongTermRefPicSPS;                                       }
   void                    setNumLongTermRefPicSPS(uint32_t val)                                           { m_numLongTermRefPicSPS = val;                                        }
@@ -2038,14 +2057,14 @@ private:
   bool             m_bUseWeightPred;                    //!< Use of Weighting Prediction (P_SLICE)
   bool             m_useWeightedBiPred;                 //!< Use of Weighting Bi-Prediction (B_SLICE)
   bool             m_OutputFlagPresentFlag;             //!< Indicates the presence of output_flag in slice header
-  uint8_t          m_numSubPics;                        //!< number of sub-pictures used - must match SPS
+  uint32_t         m_numSubPics;                        //!< number of sub-pictures used - must match SPS
 #if JVET_Q0119_CLEANUPS
   bool             m_subPicIdMappingInPpsFlag;
 #else
   bool             m_subPicIdSignallingPresentFlag;     //!< indicates the presence of sub-picture ID signalling in the PPS
 #endif
   uint32_t         m_subPicIdLen;                       //!< sub-picture ID length in bits
-  uint16_t         m_subPicId[MAX_NUM_SUB_PICS];        //!< sub-picture ID for each sub-picture in the sequence
+  std::vector<uint16_t> m_subPicId;                     //!< sub-picture ID for each sub-picture in the sequence
   bool             m_noPicPartitionFlag;                //!< no picture partitioning flag - single slice, single tile
   uint8_t          m_log2CtuSize;                       //!< log2 of the CTU size - required to match corresponding value in SPS
   uint8_t          m_ctuSize;                           //!< CTU size
@@ -2223,8 +2242,11 @@ public:
 
   void                   setOutputFlagPresentFlag( bool b )                               { m_OutputFlagPresentFlag = b;                  }
   bool                   getOutputFlagPresentFlag() const                                 { return m_OutputFlagPresentFlag;               }
-  void                   setNumSubPics( uint8_t u )                                       { m_numSubPics = u;                             }
-  uint8_t                getNumSubPics( ) const                                           { return  m_numSubPics;                         }
+  void                   setNumSubPics(uint32_t u )                                       { CHECK( u >= MAX_NUM_SUB_PICS, "Maximum number of subpictures exceeded" );
+                                                                                            m_numSubPics = u;
+                                                                                            m_subPicId.resize(m_numSubPics);
+                                                                                          }
+  uint32_t               getNumSubPics( ) const                                           { return  m_numSubPics;                         }
 #if JVET_Q0119_CLEANUPS
   void                   setSubPicIdMappingInPpsFlag( bool b )                            { m_subPicIdMappingInPpsFlag = b;               }
   bool                   getSubPicIdMappingInPpsFlag() const                              { return m_subPicIdMappingInPpsFlag;            }
@@ -2234,8 +2256,9 @@ public:
 #endif
   void                   setSubPicIdLen( uint32_t u )                                     { m_subPicIdLen = u;                            }
   uint32_t               getSubPicIdLen() const                                           { return  m_subPicIdLen;                        }
-  void                   setSubPicId( int i, uint16_t u )                                 { CHECK( i >= MAX_NUM_SUB_PICS, "Sub-picture index exceeds valid range" ); m_subPicId[i] = u;     }
-  uint16_t               getSubPicId( int i ) const                                       { CHECK( i >= MAX_NUM_SUB_PICS, "Sub-picture index exceeds valid range" ); return  m_subPicId[i]; }
+  void                   setSubPicId( int i, uint16_t u )                                 { m_subPicId[i] = u;     }
+  void                   setSubPicId(const std::vector<uint16_t> &v)                      { CHECK(v.size()!=m_numSubPics, "number of vector entries must be equal to numSubPics") ; m_subPicId = v; }
+  uint16_t               getSubPicId( int i ) const                                       { return  m_subPicId[i]; }
 #if JVET_Q0044_SLICE_IDX_WITH_SUBPICS
   uint32_t               getSubPicIdxFromSubPicId( uint32_t subPicId ) const;
 #endif
@@ -2668,8 +2691,8 @@ public:
   bool                        getSubPicIdSignallingPresentFlag() const                  { return  m_subPicIdSignallingPresentFlag;                                                     }
   void                        setSubPicIdLen( uint32_t u )                              { m_subPicIdLen = u;                                                                           }
   uint32_t                    getSubPicIdLen() const                                    { return  m_subPicIdLen;                                                                       }
-  void                        setSubPicId( int i, uint16_t u )                           { CHECK( i >= MAX_NUM_SUB_PICS, "Sub-pic index exceeds valid range" ); m_subPicId[i] = u;      }
-  uint16_t                    getSubPicId( int i ) const                                { CHECK( i >= MAX_NUM_SUB_PICS, "Sub-pic index exceeds valid range" ); return  m_subPicId[i];  }
+  void                        setSubPicId( int i, uint16_t u )                          { m_subPicId[i] = u;      }
+  uint16_t                    getSubPicId( int i ) const                                { return  m_subPicId[i];  }
 #endif
 #if JVET_Q0246_VIRTUAL_BOUNDARY_ENABLE_FLAG 
   void                        setVirtualBoundariesPresentFlag( bool b )                 { m_virtualBoundariesPresentFlag = b;                                                          }
diff --git a/source/Lib/DecoderLib/VLCReader.cpp b/source/Lib/DecoderLib/VLCReader.cpp
index 519c336b6..12fb500dc 100644
--- a/source/Lib/DecoderLib/VLCReader.cpp
+++ b/source/Lib/DecoderLib/VLCReader.cpp
@@ -497,13 +497,6 @@ void HLSyntaxReader::parsePPS( PPS* pcPPS )
       READ_CODE( pcPPS->getSubPicIdLen( ), uiCode, "pps_subpic_id[i]" );   pcPPS->setSubPicId( picIdx, uiCode );
     }
   }
-  else 
-  {
-    for( int picIdx = 0; picIdx < MAX_NUM_SUB_PICS; picIdx++ )
-    {
-      pcPPS->setSubPicId( picIdx, picIdx );
-    }
-  }
 
   READ_FLAG( uiCode, "no_pic_partition_flag" );                       pcPPS->setNoPicPartitionFlag( uiCode == 1 );
   if(!pcPPS->getNoPicPartitionFlag())
@@ -1775,7 +1768,7 @@ void HLSyntaxReader::parseSPS(SPS* pcSPS)
 #if JVET_Q0119_CLEANUPS
     READ_UVLC( uiCode, "sps_subpic_id_len_minus1" );                       pcSPS->setSubPicIdLen( uiCode + 1 );
     CHECK( uiCode > 15, "Invalid sps_subpic_id_len_minus1 value" );
-    CHECK( (1 << (uiCode + 1)) < pcSPS->getNumSubPics() + 1, "Invalid sps_subpic_id_len_minus1 value" );
+    CHECK( (1 << (uiCode + 1)) < pcSPS->getNumSubPics(), "Invalid sps_subpic_id_len_minus1 value" );
     READ_FLAG( uiCode, "subpic_id_mapping_explicitly_signalled_flag" );    pcSPS->setSubPicIdMappingExplicitlySignalledFlag( uiCode != 0 );
     if (pcSPS->getSubPicIdMappingExplicitlySignalledFlag())
     {
diff --git a/source/Lib/EncoderLib/EncCfg.h b/source/Lib/EncoderLib/EncCfg.h
index d8969e265..f06b1c0eb 100644
--- a/source/Lib/EncoderLib/EncCfg.h
+++ b/source/Lib/EncoderLib/EncCfg.h
@@ -280,13 +280,13 @@ protected:
 #else
   bool                  m_subPicPresentFlag;
 #endif
-  unsigned              m_numSubPics;
-  uint32_t              m_subPicCtuTopLeftX[MAX_NUM_SUB_PICS];
-  uint32_t              m_subPicCtuTopLeftY[MAX_NUM_SUB_PICS];
-  uint32_t              m_subPicWidth[MAX_NUM_SUB_PICS];
-  uint32_t              m_subPicHeight[MAX_NUM_SUB_PICS];
-  uint32_t              m_subPicTreatedAsPicFlag[MAX_NUM_SUB_PICS];
-  uint32_t              m_loopFilterAcrossSubpicEnabledFlag[MAX_NUM_SUB_PICS];
+  uint32_t              m_numSubPics;
+  std::vector<uint32_t> m_subPicCtuTopLeftX;
+  std::vector<uint32_t> m_subPicCtuTopLeftY;
+  std::vector<uint32_t> m_subPicWidth;
+  std::vector<uint32_t> m_subPicHeight;
+  std::vector<bool>     m_subPicTreatedAsPicFlag;
+  std::vector<bool>     m_loopFilterAcrossSubpicEnabledFlag;
 #if JVET_Q0119_CLEANUPS
   bool                  m_subPicIdMappingExplicitlySignalledFlag;
   bool                  m_subPicIdMappingInSpsFlag;
@@ -295,7 +295,7 @@ protected:
   bool                  m_subPicIdSignallingPresentFlag;
 #endif
   unsigned              m_subPicIdLen;
-  uint32_t              m_subPicId[MAX_NUM_SUB_PICS];
+  std::vector<uint16_t> m_subPicId;
   bool      m_useSplitConsOverride;
   unsigned  m_uiMinQT[3]; //0: I slice; 1: P/B slice, 2: I slice chroma
 #if JVET_Q0330_BLOCK_PARTITION
@@ -1006,13 +1006,29 @@ public:
 #else
   void      setSubPicPresentFlag                        (bool b)                    { m_subPicPresentFlag = b; }
 #endif
-  void      setNumSubPics                               (uint32_t u)                { m_numSubPics = u; }
+  void      setNumSubPics                               ( uint32_t u )              { CHECK( u >= MAX_NUM_SUB_PICS, "Maximum number of subpictures exceeded" );
+                                                                                      m_numSubPics = u;
+                                                                                      m_subPicCtuTopLeftX.resize(m_numSubPics);
+                                                                                      m_subPicCtuTopLeftY.resize(m_numSubPics);
+                                                                                      m_subPicWidth.resize(m_numSubPics);
+                                                                                      m_subPicHeight.resize(m_numSubPics);
+                                                                                      m_subPicTreatedAsPicFlag.resize(m_numSubPics);
+                                                                                      m_loopFilterAcrossSubpicEnabledFlag.resize(m_numSubPics);
+                                                                                      m_subPicId.resize(m_numSubPics);
+                                                                                    }
   void      setSubPicCtuTopLeftX                        (uint32_t u, int i)         { m_subPicCtuTopLeftX[i] = u; }
   void      setSubPicCtuTopLeftY                        (uint32_t u, int i)         { m_subPicCtuTopLeftY[i] = u; }
   void      setSubPicWidth                              (uint32_t u, int i)         { m_subPicWidth[i] = u; }
   void      setSubPicHeight                             (uint32_t u, int i)         { m_subPicHeight[i] = u; }
   void      setSubPicTreatedAsPicFlag                   (bool b, int i)             { m_subPicTreatedAsPicFlag[i] = b; }
-  void      setLoopFilterAcrossSubpicEnabledFlag        (uint32_t u, int i)         { m_loopFilterAcrossSubpicEnabledFlag[i] = u; }
+  void      setLoopFilterAcrossSubpicEnabledFlag        (bool b, int i)             { m_loopFilterAcrossSubpicEnabledFlag[i] = b; }
+
+  void      setSubPicCtuTopLeftX                        (const std::vector<uint32_t> &v)   { CHECK(v.size()!=m_numSubPics, "number of vector entries must be equal to numSubPics") ;m_subPicCtuTopLeftX = v; }
+  void      setSubPicCtuTopLeftY                        (const std::vector<uint32_t> &v)   { CHECK(v.size()!=m_numSubPics, "number of vector entries must be equal to numSubPics") ;m_subPicCtuTopLeftY = v; }
+  void      setSubPicWidth                              (const std::vector<uint32_t> &v)   { CHECK(v.size()!=m_numSubPics, "number of vector entries must be equal to numSubPics") ;m_subPicWidth = v; }
+  void      setSubPicHeight                             (const std::vector<uint32_t> &v)   { CHECK(v.size()!=m_numSubPics, "number of vector entries must be equal to numSubPics") ;m_subPicHeight = v; }
+  void      setSubPicTreatedAsPicFlag                   (const std::vector<bool> &v)       { CHECK(v.size()!=m_numSubPics, "number of vector entries must be equal to numSubPics") ;m_subPicTreatedAsPicFlag = v; }
+  void      setLoopFilterAcrossSubpicEnabledFlag        (const std::vector<bool> &v)       { CHECK(v.size()!=m_numSubPics, "number of vector entries must be equal to numSubPics") ;m_loopFilterAcrossSubpicEnabledFlag = v; }
 
 #if JVET_Q0119_CLEANUPS
   void      setSubPicIdMappingExplicitlySignalledFlag   (bool b)                    { m_subPicIdMappingExplicitlySignalledFlag = b; }
@@ -1023,6 +1039,7 @@ public:
 #endif
   void      setSubPicIdLen                              (uint32_t u)                { m_subPicIdLen = u; }
   void      setSubPicId                                 (uint32_t b, int i)         { m_subPicId[i] = b; }
+  void      setSubPicId                                 (const std::vector<uint16_t> &v)   { CHECK(v.size()!=m_numSubPics, "number of vector entries must be equal to numSubPics"); m_subPicId = v; }
 
 #if JVET_Q0119_CLEANUPS
   bool      getSubPicInfoPresentFlag                    ()                          { return m_subPicInfoPresentFlag; }
diff --git a/source/Lib/EncoderLib/EncLib.cpp b/source/Lib/EncoderLib/EncLib.cpp
index e5c753713..f6585d391 100644
--- a/source/Lib/EncoderLib/EncLib.cpp
+++ b/source/Lib/EncoderLib/EncLib.cpp
@@ -1532,15 +1532,13 @@ void EncLib::xInitSPS( SPS& sps, VPS& vps )
 #endif
   {
     sps.setNumSubPics(m_numSubPics);
-    for (int i = 0; i < m_numSubPics; i++) 
-    {
-      sps.setSubPicCtuTopLeftX(i, m_subPicCtuTopLeftX[i] );
-      sps.setSubPicCtuTopLeftY(i, m_subPicCtuTopLeftY[i]);
-      sps.setSubPicWidth(i, m_subPicWidth[i]);
-      sps.setSubPicHeight(i, m_subPicHeight[i]);
-      sps.setSubPicTreatedAsPicFlag(i, m_subPicTreatedAsPicFlag[i]);
-      sps.setLoopFilterAcrossSubpicEnabledFlag(i, m_loopFilterAcrossSubpicEnabledFlag[i]);
-    }
+    sps.setSubPicCtuTopLeftX(m_subPicCtuTopLeftX);
+    sps.setSubPicCtuTopLeftY(m_subPicCtuTopLeftY);
+    sps.setSubPicWidth(m_subPicWidth);
+    sps.setSubPicHeight(m_subPicHeight);
+    sps.setSubPicTreatedAsPicFlag(m_subPicTreatedAsPicFlag);
+    sps.setLoopFilterAcrossSubpicEnabledFlag(m_loopFilterAcrossSubpicEnabledFlag);
+    sps.setSubPicIdLen(m_subPicIdLen);
   }
 #if JVET_Q0044_SLICE_IDX_WITH_SUBPICS
   else   //In that case, there is only one subpicture that contains the whole picture
@@ -1552,6 +1550,7 @@ void EncLib::xInitSPS( SPS& sps, VPS& vps )
     sps.setSubPicHeight(0, m_iSourceHeight);
     sps.setSubPicTreatedAsPicFlag(0, 1);
     sps.setLoopFilterAcrossSubpicEnabledFlag(0, 0);
+    sps.setSubPicIdLen(0);
   }
 #endif
 #if JVET_Q0119_CLEANUPS
@@ -1561,11 +1560,7 @@ void EncLib::xInitSPS( SPS& sps, VPS& vps )
     sps.setSubPicIdMappingInSpsFlag(m_subPicIdMappingInSpsFlag);
     if (m_subPicIdMappingInSpsFlag)
     {
-      sps.setSubPicIdLen(m_subPicIdLen);
-      for (int i = 0; i < m_numSubPics; i++)
-      {
-        sps.setSubPicId(i, m_subPicId[i]);
-      }
+      sps.setSubPicId(m_subPicId);
     }
   }
 #else
@@ -1575,11 +1570,7 @@ void EncLib::xInitSPS( SPS& sps, VPS& vps )
     sps.setSubPicIdSignallingPresentFlag(m_subPicIdSignallingPresentFlag);
     if (m_subPicIdSignallingPresentFlag)
     {
-      sps.setSubPicIdLen(m_subPicIdLen);
-      for (int i = 0; i < m_numSubPics; i++)
-  {
-        sps.setSubPicId(i, m_subPicId[i]);
-      }
+      sps.setSubPicId(m_subPicId);
     }
   }
 #endif
diff --git a/source/Lib/EncoderLib/VLCWriter.cpp b/source/Lib/EncoderLib/VLCWriter.cpp
index 303455d53..48108efb1 100644
--- a/source/Lib/EncoderLib/VLCWriter.cpp
+++ b/source/Lib/EncoderLib/VLCWriter.cpp
@@ -303,8 +303,10 @@ void HLSWriter::codePPS( const PPS* pcPPS )
   if( pcPPS->getSubPicIdSignallingPresentFlag() )
 #endif
   {
+    CHECK(pcPPS->getNumSubPics() < 1, "PPS: NumSubPics cannot be less than 1");
     WRITE_UVLC( pcPPS->getNumSubPics() - 1, "pps_num_subpics_minus1" );
 
+    CHECK(pcPPS->getSubPicIdLen() < 1, "PPS: SubPicIdLen cannot be less than 1");
     WRITE_UVLC( pcPPS->getSubPicIdLen() - 1, "pps_subpic_id_len_minus1" );
 
 #if JVET_Q0169_SUBPIC_LEN_CONFORM    
@@ -1079,6 +1081,7 @@ void HLSWriter::codeSPS( const SPS* pcSPS )
   if(pcSPS->getSubPicPresentFlag())
 #endif
   {
+    CHECK(pcSPS->getNumSubPics() < 1, "SPS: NumSubPics cannot be less than 1");
 #if JVET_Q0119_CLEANUPS
     WRITE_UVLC(pcSPS->getNumSubPics() - 1, "sps_num_subpics_minus1");
 #else
@@ -1144,6 +1147,7 @@ void HLSWriter::codeSPS( const SPS* pcSPS )
 #endif
 
 #if JVET_Q0119_CLEANUPS
+    CHECK(pcSPS->getSubPicIdLen() < 1, "SPS: SubPicIdLen cannot be less than 1");
     WRITE_UVLC(pcSPS->getSubPicIdLen() - 1, "sps_subpic_id_len_minus1");
     WRITE_FLAG(pcSPS->getSubPicIdMappingExplicitlySignalledFlag(), "subpic_id_mapping_explicitly_signalled_flag");
     if (pcSPS->getSubPicIdMappingExplicitlySignalledFlag())
-- 
GitLab