From 0a24c42a1df64dff9d5843e97b8385288bb31814 Mon Sep 17 00:00:00 2001
From: Karsten Suehring <karsten.suehring@hhi.fraunhofer.de>
Date: Thu, 30 Jul 2020 17:38:43 +0200
Subject: [PATCH] JVET-S0098 Item 3: Add non_subpic_layers_fraction syntax
 element

---
 cfg/sei_vui/subpicture_level.cfg     |  1 +
 doc/software-manual.tex              |  9 +++++++++
 source/App/EncoderApp/EncAppCfg.cpp  | 24 ++++++++++++++++++++++--
 source/Lib/CommonLib/SEI.h           |  3 +++
 source/Lib/CommonLib/TypeDef.h       |  2 ++
 source/Lib/DecoderLib/SEIread.cpp    | 12 ++++++++++++
 source/Lib/EncoderLib/EncCfgParam.h  |  3 +++
 source/Lib/EncoderLib/SEIEncoder.cpp | 12 ++++++++++++
 source/Lib/EncoderLib/SEIwrite.cpp   |  3 +++
 9 files changed, 67 insertions(+), 2 deletions(-)

diff --git a/cfg/sei_vui/subpicture_level.cfg b/cfg/sei_vui/subpicture_level.cfg
index a3e1b0b42..db05a2b73 100644
--- a/cfg/sei_vui/subpicture_level.cfg
+++ b/cfg/sei_vui/subpicture_level.cfg
@@ -4,6 +4,7 @@ SEISubpicLevelInfoNumSubpics:                2             # number of subpictur
 SEISubpicLevelInfoMaxSublayers:              7             # number of sublayers - has to be equal to vps_max_sublayers_minus1 + 1
 SEISubpicLevelInfoSublayerInfoPresentFlag:   0             # 0: all sublayers use the same level information, 1: each sublayer shall specify its own level information
 
+SEISubpicLevelInfoNonSubpicLayersFractions:  100           # see software manual for list format
 SEISubpicLevelInfoRefLevels:                 4.1           # see software manual for list format
 
 SEISubpicLevelInfoRefLevelFractions:         40 30         # see software manual for list format
diff --git a/doc/software-manual.tex b/doc/software-manual.tex
index 3180971ee..c5db86d64 100644
--- a/doc/software-manual.tex
+++ b/doc/software-manual.tex
@@ -4396,6 +4396,15 @@ Enable signalling of level information for each sublayer
 0 & All sublayers use the same level information \\
 \end{tabular}
 \\
+\Option{SEISubpicLevelInfoNonSubpicLayersFractions} &
+\Default{""} &
+List of fraction of levels to be signalled for non-subpicture layers.
+\par
+\begin{tabular}{p{0.49\columnwidth}}
+When sli_sublayer_info_present_flag = 0, the number of input elements shall be equal to numReflevels. List is ordered by level.\\
+When sli_sublayer_info_present_flag = 1, the number of input elements shall be equal to numReflevels * maxSublayers. List is ordered by level then sublayer. For example, let Amn denotes the reference level indices for the m-th sublayer and and n-th reference level, the first N elements (A00...A0n-1) denotes the RefLevelFractions for N levels in the 0-th sublayer, and the following N elements (A10...A1n-1) denotes the RefLevelFractions for N levels in the 1st sublayer, and so on, untill all MxN elements specified.\\
+\end{tabular}
+\\
 \Option{SEISubpicLevelInfoRefLevels} &
 \Default{""} &
 List of reference levels to be signalled.
diff --git a/source/App/EncoderApp/EncAppCfg.cpp b/source/App/EncoderApp/EncAppCfg.cpp
index a94c6c7a2..2b29049d2 100644
--- a/source/App/EncoderApp/EncAppCfg.cpp
+++ b/source/App/EncoderApp/EncAppCfg.cpp
@@ -663,7 +663,11 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] )
   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);
 
-  SMultiValueInput<int>          cfg_sliFractions(0, 100, 0, std::numeric_limits<int>::max());
+  SMultiValueInput<int>       cfg_sliFractions(0, 100, 0, std::numeric_limits<int>::max());
+#if JVET_S0098_SLI_FRACTION
+  SMultiValueInput<int>       cfg_sliNonSubpicLayersFractions(0, 100, 0, std::numeric_limits<int>::max());
+#endif
+
 #if  JVET_S0176_SLI_SEI
   SMultiValueInput<Level::Name>  cfg_sliRefLevels(Level::NONE, Level::LEVEL15_5, 0, 8 * MAX_VPS_SUBLAYERS);
 #else
@@ -1311,7 +1315,10 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] )
   ("SEISubpicLevelInfoMaxSublayers",                  m_cfgSubpictureLevelInfoSEI.m_sliMaxSublayers,               1,                    "Number of sublayers for Subpicture Level Information SEI messages")
   ("SEISubpicLevelInfoSublayerInfoPresentFlag",       m_cfgSubpictureLevelInfoSEI.m_sliSublayerInfoPresentFlag,    false,                "Enable sending of level information for all sublayers in Subpicture Level Information SEI messages")
 #endif
-  ("SEISubpicLevelInfoRefLevelFractions",             cfg_sliFractions,                                  cfg_sliFractions, "List of fractions for Subpicture Level Information SEI messages")
+  ("SEISubpicLevelInfoRefLevelFractions",             cfg_sliFractions,                                  cfg_sliFractions, "List of subpicture level fractions for Subpicture Level Information SEI messages")
+#if JVET_S0098_SLI_FRACTION
+  ("SEISubpicLevelInfoNonSubpicLayersFractions",      cfg_sliNonSubpicLayersFractions,                   cfg_sliNonSubpicLayersFractions, "List of level fractions for non-subpicture layers in Subpicture Level Information SEI messages")
+#endif
   ("SEISampleAspectRatioInfo",                        m_sampleAspectRatioInfoSEIEnabled,        false, "Control generation of Sample Aspect Ratio Information SEI messages")
   ("SEISARICancelFlag",                               m_sariCancelFlag,                         false, "Indicates that Sample Aspect Ratio Information SEI message cancels the persistence or follows")
   ("SEISARIPersistenceFlag",                          m_sariPersistenceFlag,                    true, "Specifies the persistence of the Sample Aspect Ratio Information SEI message")
@@ -1722,6 +1729,19 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] )
         CHECK((int)cfg_sliRefLevels.values.size() * m_cfgSubpictureLevelInfoSEI.m_numSubpictures != cfg_sliFractions.values.size(), "when sliSublayerInfoPresentFlag = 0, the number  of subpicture level fractions must be equal to the numer of subpictures times the number of reference levels");
       }
     }
+#if JVET_S0098_SLI_FRACTION
+    m_cfgSubpictureLevelInfoSEI.m_nonSubpicLayersFraction = cfg_sliNonSubpicLayersFractions.values;
+    if (m_cfgSubpictureLevelInfoSEI.m_sliSublayerInfoPresentFlag)
+    {
+      CHECK((int)cfg_sliNonSubpicLayersFractions.values.size() != ( cfg_sliRefLevels.values.size() * m_cfgSubpictureLevelInfoSEI.m_numSubpictures ),
+        "when sliSublayerInfoPresentFlag = 1, the number  of non-subpicture level fractions must be equal to the numer of reference levels times the number of sublayers");
+    }
+    else
+    {
+      CHECK((int)cfg_sliNonSubpicLayersFractions.values.size() != ( cfg_sliRefLevels.values.size() ),
+        "when sliSublayerInfoPresentFlag = 0, the number  of non-subpicture level fractions must be equal to the numer of reference levels");
+    }
+#endif
 #else
     if (m_cfgSubpictureLevelInfoSEI.m_explicitFraction)
     {
diff --git a/source/Lib/CommonLib/SEI.h b/source/Lib/CommonLib/SEI.h
index a7c09c822..033f88754 100644
--- a/source/Lib/CommonLib/SEI.h
+++ b/source/Lib/CommonLib/SEI.h
@@ -662,6 +662,9 @@ public:
 #if JVET_S0176_SLI_SEI
   int       m_sliMaxSublayers;
   bool      m_sliSublayerInfoPresentFlag;
+#if JVET_S0098_SLI_FRACTION
+  std::vector<std::vector<int>>              m_nonSubpicLayersFraction;
+#endif
   std::vector<std::vector<Level::Name>>      m_refLevelIdc;
   std::vector<std::vector<std::vector<int>>> m_refLevelFraction;
 #else
diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h
index fd0795154..2ae7cbbb6 100644
--- a/source/Lib/CommonLib/TypeDef.h
+++ b/source/Lib/CommonLib/TypeDef.h
@@ -103,6 +103,8 @@
 
 #define JVET_S0071_SAME_SIZE_SUBPIC_LAYOUT                1 // JVET-S0071 : shortcut when all subpictures have the same size
 
+#define JVET_S0098_SLI_FRACTION                           1 // JVET-S0098 Item 3: Add non_subpic_layers_fraction syntax element
+
 #define JVET_S0048_SCALING_OFFSET                         1 // JVET-S0048 Aspect2: change the constraint on the value ranges of scaling window offsets to be more flexible
 
 #define JVET_S0248_HRD_CLEANUP                            1 // JVET-S0248 Aspect7: When bp_alt_cpb_params_present_flag is equal to 1, the value of bp_du_hrd_params_present_flag shall be equal to 0.
diff --git a/source/Lib/DecoderLib/SEIread.cpp b/source/Lib/DecoderLib/SEIread.cpp
index 091b8c984..b82a55655 100644
--- a/source/Lib/DecoderLib/SEIread.cpp
+++ b/source/Lib/DecoderLib/SEIread.cpp
@@ -1513,9 +1513,15 @@ void SEIReader::xParseSEISubpictureLevelInfo(SEISubpicureLevelInfo& sei, uint32_
 
   sei.m_refLevelIdc.resize(sei.m_numRefLevels);
 #if JVET_S0176_SLI_SEI
+#if JVET_S0098_SLI_FRACTION
+  sei.m_nonSubpicLayersFraction.resize(sei.m_numRefLevels);
+#endif
   // sei parameters initialization
   for (int i = 0; i < sei.m_numRefLevels; i++)
   {
+#if JVET_S0098_SLI_FRACTION
+    sei.m_nonSubpicLayersFraction[i].resize(sei.m_sliMaxSublayers);
+#endif
     sei.m_refLevelIdc[i].resize(sei.m_sliMaxSublayers);
     for (int k = 0; k < sei.m_sliMaxSublayers; k++)
     {
@@ -1544,6 +1550,9 @@ void SEIReader::xParseSEISubpictureLevelInfo(SEISubpicureLevelInfo& sei, uint32_
   {
     for (int i = 0; i < sei.m_numRefLevels; i++)
     {
+#if JVET_S0098_SLI_FRACTION
+      sei_read_code(pDecodedMessageOutputStream, 8, val, "sli_non_subpic_layers_fraction[i][k]");    sei.m_nonSubpicLayersFraction[i][k] = (Level::Name) val;
+#endif
       sei_read_code(pDecodedMessageOutputStream, 8, val, "sli_ref_level_idc[i][k]");                 sei.m_refLevelIdc[i][k] = (Level::Name) val;
 
       if (sei.m_explicitFractionPresentFlag)
@@ -1563,6 +1572,9 @@ void SEIReader::xParseSEISubpictureLevelInfo(SEISubpicureLevelInfo& sei, uint32_
     {
       for (int i = 0; i < sei.m_numRefLevels; i++)
       {
+#if JVET_S0098_SLI_FRACTION
+        sei.m_nonSubpicLayersFraction[i][k] = sei.m_nonSubpicLayersFraction[i][sei.m_sliMaxSublayers - 1];
+#endif
         sei.m_refLevelIdc[i][k] = sei.m_refLevelIdc[i][sei.m_sliMaxSublayers - 1];
         if (sei.m_explicitFractionPresentFlag)
         {
diff --git a/source/Lib/EncoderLib/EncCfgParam.h b/source/Lib/EncoderLib/EncCfgParam.h
index 6e011727c..28e023897 100644
--- a/source/Lib/EncoderLib/EncCfgParam.h
+++ b/source/Lib/EncoderLib/EncCfgParam.h
@@ -76,6 +76,9 @@ public:
   std::vector<Level::Name>  m_refLevels;
   bool                      m_explicitFraction;
   int                       m_numSubpictures;
+#if JVET_S0098_SLI_FRACTION
+  std::vector<int>          m_nonSubpicLayersFraction;
+#endif
   std::vector<int>          m_fractions;
 #if JVET_S0176_SLI_SEI
   int                       m_sliMaxSublayers;
diff --git a/source/Lib/EncoderLib/SEIEncoder.cpp b/source/Lib/EncoderLib/SEIEncoder.cpp
index ab36a8d3e..7aec5025a 100644
--- a/source/Lib/EncoderLib/SEIEncoder.cpp
+++ b/source/Lib/EncoderLib/SEIEncoder.cpp
@@ -698,9 +698,15 @@ void SEIEncoder::initSEISubpictureLevelInfo(SEISubpicureLevelInfo *sei, const SP
   sei->m_explicitFractionPresentFlag = cfgSubPicLevel.m_explicitFraction;
 
   // sei parameters initialization
+#if JVET_S0098_SLI_FRACTION
+  sei->m_nonSubpicLayersFraction.resize(sei->m_numRefLevels);
+#endif
   sei->m_refLevelIdc.resize(sei->m_numRefLevels);
   for (int level = 0; level < sei->m_numRefLevels; level++)
   {
+#if JVET_S0098_SLI_FRACTION
+    sei->m_nonSubpicLayersFraction[level].resize(sei->m_sliMaxSublayers);
+#endif
     sei->m_refLevelIdc[level].resize(sei->m_sliMaxSublayers);
     for (int sublayer = 0; sublayer < sei->m_sliMaxSublayers; sublayer++)
     {
@@ -729,6 +735,9 @@ void SEIEncoder::initSEISubpictureLevelInfo(SEISubpicureLevelInfo *sei, const SP
   {
     for (int level = 0; level < sei->m_numRefLevels; level++)
     {
+#if JVET_S0098_SLI_FRACTION
+      sei->m_nonSubpicLayersFraction[level][sublayer] = cfgSubPicLevel.m_nonSubpicLayersFraction[cnta];
+#endif
       sei->m_refLevelIdc[level][sublayer] = cfgSubPicLevel.m_refLevels[cnta++];
       if (sei->m_explicitFractionPresentFlag)
       {
@@ -747,6 +756,9 @@ void SEIEncoder::initSEISubpictureLevelInfo(SEISubpicureLevelInfo *sei, const SP
     {
       for (int level = 0; level < sei->m_numRefLevels; level++)
       {
+#if JVET_S0098_SLI_FRACTION
+        sei->m_nonSubpicLayersFraction[level][sublayer] = sei->m_nonSubpicLayersFraction[level][sei->m_sliMaxSublayers - 1];
+#endif
         sei->m_refLevelIdc[level][sublayer] = sei->m_refLevelIdc[level][sei->m_sliMaxSublayers - 1];
         if (sei->m_explicitFractionPresentFlag)
         {
diff --git a/source/Lib/EncoderLib/SEIwrite.cpp b/source/Lib/EncoderLib/SEIwrite.cpp
index 34d4e6881..085fce9de 100644
--- a/source/Lib/EncoderLib/SEIwrite.cpp
+++ b/source/Lib/EncoderLib/SEIwrite.cpp
@@ -819,6 +819,9 @@ void SEIWriter::xWriteSEISubpictureLevelInfo(const SEISubpicureLevelInfo &sei)
   {
     for (int i = 0; i < sei.m_numRefLevels; i++)
     {
+#if JVET_S0098_SLI_FRACTION
+      WRITE_CODE((uint32_t)sei.m_nonSubpicLayersFraction[i][k], 8, "sli_non_subpic_layers_fraction[i][k]");
+#endif
       WRITE_CODE((uint32_t)sei.m_refLevelIdc[i][k], 8, "sli_ref_level_idc[i][k]");
       if (sei.m_explicitFractionPresentFlag)
       {
-- 
GitLab