From b90113853e95cc28a6541dacf6efb2baaaf24a50 Mon Sep 17 00:00:00 2001
From: vdrugeon <virginie.drugeon@eu.panasonic.com>
Date: Mon, 4 May 2020 15:46:03 +0000
Subject: [PATCH] JVET-R0094: DPB output temporal sublayers offsets

---
 cfg/sei_vui/timing.cfg               |  2 +-
 source/Lib/CommonLib/SEI.cpp         |  4 ++++
 source/Lib/CommonLib/SEI.h           | 10 ++++++++++
 source/Lib/CommonLib/TypeDef.h       |  2 ++
 source/Lib/DecoderLib/SEIread.cpp    | 13 +++++++++++++
 source/Lib/EncoderLib/SEIEncoder.cpp | 15 +++++++++++++++
 source/Lib/EncoderLib/SEIwrite.cpp   | 10 ++++++++++
 7 files changed, 55 insertions(+), 1 deletion(-)

diff --git a/cfg/sei_vui/timing.cfg b/cfg/sei_vui/timing.cfg
index 63f37a739..12125434e 100644
--- a/cfg/sei_vui/timing.cfg
+++ b/cfg/sei_vui/timing.cfg
@@ -1,4 +1,4 @@
 SEIBufferingPeriod:  1
 SEIPictureTiming:  1
-VuiParametersPresent: 1
+HrdParametersPresent: 1
 RCCpbSize: 2000
diff --git a/source/Lib/CommonLib/SEI.cpp b/source/Lib/CommonLib/SEI.cpp
index 27550e7ba..ce9faa4a1 100644
--- a/source/Lib/CommonLib/SEI.cpp
+++ b/source/Lib/CommonLib/SEI.cpp
@@ -119,6 +119,10 @@ void SEIBufferingPeriod::copyTo (SEIBufferingPeriod& target) const
   target.m_sublayerInitialCpbRemovalDelayPresentFlag = m_sublayerInitialCpbRemovalDelayPresentFlag;
   target.m_concatenationFlag = m_concatenationFlag;
   target.m_maxInitialRemovalDelayForConcatenation = m_maxInitialRemovalDelayForConcatenation;
+#if JVET_R0094_DPB_TID_OFFSET
+  target.m_sublayerDpbOutputOffsetsPresentFlag = m_sublayerDpbOutputOffsetsPresentFlag;
+  ::memcpy(target.m_dpbOutputTidOffset, m_dpbOutputTidOffset, sizeof(m_dpbOutputTidOffset));
+#endif
   target.m_altCpbParamsPresentFlag = m_altCpbParamsPresentFlag;
 }
 
diff --git a/source/Lib/CommonLib/SEI.h b/source/Lib/CommonLib/SEI.h
index c45634c61..d51f7ccde 100644
--- a/source/Lib/CommonLib/SEI.h
+++ b/source/Lib/CommonLib/SEI.h
@@ -281,12 +281,18 @@ public:
     , m_sublayerInitialCpbRemovalDelayPresentFlag(false)
     , m_additionalConcatenationInfoPresentFlag (false)
     , m_maxInitialRemovalDelayForConcatenation (0)
+#if JVET_R0094_DPB_TID_OFFSET
+    , m_sublayerDpbOutputOffsetsPresentFlag (false)
+#endif
     , m_altCpbParamsPresentFlag (false)
     , m_useAltCpbParamsFlag (false)
   {
     ::memset(m_initialCpbRemovalDelay, 0, sizeof(m_initialCpbRemovalDelay));
     ::memset(m_initialCpbRemovalOffset, 0, sizeof(m_initialCpbRemovalOffset));
     ::memset(m_cpbRemovalDelayDelta, 0, sizeof(m_cpbRemovalDelayDelta));
+#if JVET_R0094_DPB_TID_OFFSET
+    ::memset(m_dpbOutputTidOffset, 0, sizeof(m_dpbOutputTidOffset));
+#endif
   }
   virtual ~SEIBufferingPeriod() {}
 
@@ -316,6 +322,10 @@ public:
   bool m_sublayerInitialCpbRemovalDelayPresentFlag;
   bool     m_additionalConcatenationInfoPresentFlag;
   uint32_t m_maxInitialRemovalDelayForConcatenation;
+#if JVET_R0094_DPB_TID_OFFSET
+  bool     m_sublayerDpbOutputOffsetsPresentFlag;
+  uint32_t m_dpbOutputTidOffset      [MAX_TLAYER];
+#endif
   bool     m_altCpbParamsPresentFlag;
   bool     m_useAltCpbParamsFlag;
 };
diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h
index 45d8bcfe2..5881f3afc 100644
--- a/source/Lib/CommonLib/TypeDef.h
+++ b/source/Lib/CommonLib/TypeDef.h
@@ -51,6 +51,8 @@
 #include <cassert>
 
 //########### place macros to be removed in next cycle below this line ###############
+#define JVET_R0094_DPB_TID_OFFSET                         1 // JVET-R0094: DPB output temporal ID offsets
+
 #define JVET_R0330_CRS_CLIP_REM                           1 // JVET-R0330: Remove redundant clipping in chroma residual scaling factor derivation
 
 #define JVET_R0059_RPL_CLEANUP                            1 // JVET-R0059 aspect 2: Condition the signalling of ltrp_in_header_flag[ listIdx ][ rplsIdx ].
diff --git a/source/Lib/DecoderLib/SEIread.cpp b/source/Lib/DecoderLib/SEIread.cpp
index d8b8049e5..78c3cbad5 100644
--- a/source/Lib/DecoderLib/SEIread.cpp
+++ b/source/Lib/DecoderLib/SEIread.cpp
@@ -661,6 +661,19 @@ void SEIReader::xParseSEIBufferingPeriod(SEIBufferingPeriod& sei, uint32_t paylo
       }
     }
   }
+#if JVET_R0094_DPB_TID_OFFSET
+  sei_read_flag( pDecodedMessageOutputStream, code, "sublayer_dpb_output_offsets_present_flag" );
+  sei.m_sublayerDpbOutputOffsetsPresentFlag = code;
+  if(sei.m_sublayerDpbOutputOffsetsPresentFlag)
+  {
+    for(int i = 0; i < sei.m_bpMaxSubLayers - 1; i++)
+    {
+      sei_read_uvlc( pDecodedMessageOutputStream, code, "dpb_output_tid_offset[i]" );
+      sei.m_dpbOutputTidOffset[i] = code;
+    }
+    sei.m_dpbOutputTidOffset[sei.m_bpMaxSubLayers-1] = 0;
+  }
+#endif
   if (sei.m_altCpbParamsPresentFlag)
   {
     sei_read_flag(pDecodedMessageOutputStream, code, "use_alt_cpb_params_flag"); sei.m_useAltCpbParamsFlag = code;
diff --git a/source/Lib/EncoderLib/SEIEncoder.cpp b/source/Lib/EncoderLib/SEIEncoder.cpp
index 7a0374862..cd9d01806 100644
--- a/source/Lib/EncoderLib/SEIEncoder.cpp
+++ b/source/Lib/EncoderLib/SEIEncoder.cpp
@@ -179,6 +179,21 @@ void SEIEncoder::initSEIBufferingPeriod(SEIBufferingPeriod *bufferingPeriodSEI,
         break;
     }
   }
+#if JVET_R0094_DPB_TID_OFFSET
+  bufferingPeriodSEI->m_sublayerDpbOutputOffsetsPresentFlag = true;
+  for(int i = 0; i < bufferingPeriodSEI->m_bpMaxSubLayers; i++)
+  {
+    bufferingPeriodSEI->m_dpbOutputTidOffset[i] = m_pcCfg->getNumReorderPics(i) * static_cast<int>(pow(2, static_cast<double>(bufferingPeriodSEI->m_bpMaxSubLayers-1-i)));
+    if(bufferingPeriodSEI->m_dpbOutputTidOffset[i] >= m_pcCfg->getNumReorderPics(bufferingPeriodSEI->m_bpMaxSubLayers-1))
+    {
+      bufferingPeriodSEI->m_dpbOutputTidOffset[i] -= m_pcCfg->getNumReorderPics(bufferingPeriodSEI->m_bpMaxSubLayers-1);
+    }
+    else
+    {
+      bufferingPeriodSEI->m_dpbOutputTidOffset[i] = 0;
+    }
+  }
+#endif
   // A commercial encoder should track the buffer state for all layers and sub-layers
   // to ensure CPB conformance. Such tracking is required for calculating alternative
   // CPB parameters.
diff --git a/source/Lib/EncoderLib/SEIwrite.cpp b/source/Lib/EncoderLib/SEIwrite.cpp
index 813af429f..9d84a8142 100644
--- a/source/Lib/EncoderLib/SEIwrite.cpp
+++ b/source/Lib/EncoderLib/SEIwrite.cpp
@@ -318,6 +318,16 @@ void SEIWriter::xWriteSEIBufferingPeriod(const SEIBufferingPeriod& sei)
       }
     }
   }
+#if JVET_R0094_DPB_TID_OFFSET
+  WRITE_FLAG(sei.m_sublayerDpbOutputOffsetsPresentFlag, "sublayer_dpb_output_offsets_present_flag");
+  if(sei.m_sublayerDpbOutputOffsetsPresentFlag)
+  {
+    for(int i = 0; i < sei.m_bpMaxSubLayers - 1; i++)
+    {
+      WRITE_UVLC( sei.m_dpbOutputTidOffset[i], "dpb_output_tid_offset[i]" );
+    }
+  }
+#endif
   if (sei.m_altCpbParamsPresentFlag)
   {
     WRITE_FLAG(sei.m_useAltCpbParamsFlag, "use_alt_cpb_params_flag");
-- 
GitLab