From ac7861d4820c9376520205a84b3123a9b7514278 Mon Sep 17 00:00:00 2001
From: Frank Bossen <fbossen@gmail.com>
Date: Fri, 26 Jan 2024 14:01:22 +0100
Subject: [PATCH] Clean up code related to BP SEI

Includes:
- fix syntax element names for tracing
- add validation checks
- move validation check to correct place
- define `enum HrdType` for indexing by `NAL` or `VCL`
- consistently use `bp` variable name for BP SEI objects
- use `static_vector` instead of having separate variable for array size
---
 source/Lib/CommonLib/HRD.h           |  17 +-
 source/Lib/CommonLib/SEI.cpp         |  59 +---
 source/Lib/CommonLib/SEI.h           | 111 ++++----
 source/Lib/DecoderLib/DecLib.cpp     |   6 +-
 source/Lib/DecoderLib/SEIread.cpp    | 390 +++++++++++++++------------
 source/Lib/DecoderLib/SEIread.h      |   3 +-
 source/Lib/EncoderLib/EncGOP.cpp     |  18 +-
 source/Lib/EncoderLib/EncGOP.h       |   2 +-
 source/Lib/EncoderLib/SEIEncoder.cpp | 148 +++++-----
 source/Lib/EncoderLib/SEIwrite.cpp   | 190 +++++++------
 10 files changed, 457 insertions(+), 487 deletions(-)

diff --git a/source/Lib/CommonLib/HRD.h b/source/Lib/CommonLib/HRD.h
index 4a39b68a1..a0c10126b 100644
--- a/source/Lib/CommonLib/HRD.h
+++ b/source/Lib/CommonLib/HRD.h
@@ -179,11 +179,11 @@ public:
 
 inline void checkBPSyntaxElementLength(const SEIBufferingPeriod* bp1, const SEIBufferingPeriod* bp2)
 {
-  CHECK(bp1->m_initialCpbRemovalDelayLength != bp2->m_initialCpbRemovalDelayLength ||
-        bp1->m_cpbRemovalDelayLength != bp2->m_cpbRemovalDelayLength ||
-        bp1->m_dpbOutputDelayLength != bp2->m_dpbOutputDelayLength ||
-        bp1->m_duCpbRemovalDelayIncrementLength != bp2->m_duCpbRemovalDelayIncrementLength ||
-        bp1->m_dpbOutputDelayDuLength != bp2->m_dpbOutputDelayDuLength,
+  CHECK(bp1->cpbInitialRemovalDelayLength != bp2->cpbInitialRemovalDelayLength
+          || bp1->cpbRemovalDelayLength != bp2->cpbRemovalDelayLength
+          || bp1->dpbOutputDelayLength != bp2->dpbOutputDelayLength
+          || bp1->duCpbRemovalDelayIncrementLength != bp2->duCpbRemovalDelayIncrementLength
+          || bp1->dpbOutputDelayDuLength != bp2->dpbOutputDelayDuLength,
         "All scalable-nested and non-scalable nested BP SEI messages in a CVS shall have the same value for "
         "each of the syntax elements bp_cpb_initial_removal_delay_length_minus1, bp_cpb_removal_delay_length_minus1, "
         "bp_dpb_output_delay_length_minus1, bp_du_cpb_removal_delay_increment_length_minus1, "
@@ -206,7 +206,7 @@ public:
   OlsHrdParams*          getOlsHrdParametersAddr() { return m_olsHrdParams; }
   const OlsHrdParams&    getOlsHrdParameters(int idx) const { return m_olsHrdParams[idx]; }
 
-  void                       setBufferingPeriodSEI(const SEIBufferingPeriod* bp)
+  void setBufferingPeriodSEI(const SEIBufferingPeriod* bp)
   {
     if (m_bufferingPeriodInitialized)
     {
@@ -216,7 +216,10 @@ public:
     m_bufferingPeriodInitialized = true;
   }
 
-  const SEIBufferingPeriod*  getBufferingPeriodSEI() const                        { return m_bufferingPeriodInitialized ? &m_bufferingPeriodSEI : nullptr; }
+  const SEIBufferingPeriod* getBufferingPeriodSEI() const
+  {
+    return m_bufferingPeriodInitialized ? &m_bufferingPeriodSEI : nullptr;
+  }
 
   void                       setPictureTimingSEI(const SEIPictureTiming* pt)  { pt->copyTo(m_pictureTimingSEI); m_pictureTimingAvailable = true; }
   const SEIPictureTiming*    getPictureTimingSEI() const                      { return m_pictureTimingAvailable ? &m_pictureTimingSEI : nullptr; }
diff --git a/source/Lib/CommonLib/SEI.cpp b/source/Lib/CommonLib/SEI.cpp
index aea00c887..1c6d3d321 100644
--- a/source/Lib/CommonLib/SEI.cpp
+++ b/source/Lib/CommonLib/SEI.cpp
@@ -96,34 +96,7 @@ void deleteSEIs (SEIMessages &seiList)
   seiList.clear();
 }
 
-void SEIBufferingPeriod::copyTo (SEIBufferingPeriod& target) const
-{
-  target.m_bpNalCpbParamsPresentFlag = m_bpNalCpbParamsPresentFlag;
-  target.m_bpVclCpbParamsPresentFlag = m_bpVclCpbParamsPresentFlag;
-  target.m_initialCpbRemovalDelayLength = m_initialCpbRemovalDelayLength;
-  target.m_cpbRemovalDelayLength = m_cpbRemovalDelayLength;
-  target.m_dpbOutputDelayLength = m_dpbOutputDelayLength;
-  target.m_duCpbRemovalDelayIncrementLength = m_duCpbRemovalDelayIncrementLength;
-  target.m_dpbOutputDelayDuLength = m_dpbOutputDelayDuLength;
-  target.m_concatenationFlag = m_concatenationFlag;
-  target.m_auCpbRemovalDelayDelta = m_auCpbRemovalDelayDelta;
-  target.m_cpbRemovalDelayDeltasPresentFlag =  m_cpbRemovalDelayDeltasPresentFlag;
-  target.m_numCpbRemovalDelayDeltas = m_numCpbRemovalDelayDeltas;
-  target.m_bpMaxSubLayers = m_bpMaxSubLayers;
-  ::memcpy(target.m_initialCpbRemovalDelay, m_initialCpbRemovalDelay, sizeof(m_initialCpbRemovalDelay));
-  ::memcpy(target.m_initialCpbRemovalOffset, m_initialCpbRemovalOffset, sizeof(m_initialCpbRemovalOffset));
-  ::memcpy(target.m_cpbRemovalDelayDelta, m_cpbRemovalDelayDelta, sizeof(m_cpbRemovalDelayDelta));
-  target.m_bpCpbCnt = m_bpCpbCnt;
-  target.m_bpDecodingUnitHrdParamsPresentFlag = m_bpDecodingUnitHrdParamsPresentFlag;
-  target.m_decodingUnitCpbParamsInPicTimingSeiFlag = m_decodingUnitCpbParamsInPicTimingSeiFlag;
-  target.m_decodingUnitDpbDuParamsInPicTimingSeiFlag = m_decodingUnitDpbDuParamsInPicTimingSeiFlag;
-  target.m_sublayerInitialCpbRemovalDelayPresentFlag = m_sublayerInitialCpbRemovalDelayPresentFlag;
-  target.m_concatenationFlag = m_concatenationFlag;
-  target.m_maxInitialRemovalDelayForConcatenation = m_maxInitialRemovalDelayForConcatenation;
-  target.m_sublayerDpbOutputOffsetsPresentFlag = m_sublayerDpbOutputOffsetsPresentFlag;
-  ::memcpy(target.m_dpbOutputTidOffset, m_dpbOutputTidOffset, sizeof(m_dpbOutputTidOffset));
-  target.m_altCpbParamsPresentFlag = m_altCpbParamsPresentFlag;
-}
+void SEIBufferingPeriod::copyTo(SEIBufferingPeriod& target) const { target = *this; }
 
 void SEIPictureTiming::copyTo (SEIPictureTiming& target) const
 {
@@ -787,35 +760,7 @@ SEIDecodedPictureHash::SEIDecodedPictureHash(const SEIDecodedPictureHash& sei)
   m_pictureHash = sei.m_pictureHash;
 }
 
-SEIBufferingPeriod::SEIBufferingPeriod(const SEIBufferingPeriod& sei)
-{
-  m_bpNalCpbParamsPresentFlag = sei.m_bpNalCpbParamsPresentFlag;
-  m_bpVclCpbParamsPresentFlag = sei.m_bpVclCpbParamsPresentFlag;
-  m_initialCpbRemovalDelayLength = sei.m_initialCpbRemovalDelayLength;
-  m_cpbRemovalDelayLength = sei.m_cpbRemovalDelayLength;
-  m_dpbOutputDelayLength = sei.m_dpbOutputDelayLength;
-  m_bpCpbCnt = sei.m_bpCpbCnt;
-  m_duCpbRemovalDelayIncrementLength = sei.m_duCpbRemovalDelayIncrementLength;
-  m_dpbOutputDelayDuLength = sei.m_dpbOutputDelayDuLength;
-  std::memcpy(m_initialCpbRemovalDelay, sei.m_initialCpbRemovalDelay, sizeof(sei.m_initialCpbRemovalDelay));
-  std::memcpy(m_initialCpbRemovalOffset, sei.m_initialCpbRemovalOffset, sizeof(sei.m_initialCpbRemovalOffset));
-  m_concatenationFlag = sei.m_concatenationFlag;
-  m_auCpbRemovalDelayDelta = sei.m_auCpbRemovalDelayDelta;
-  m_cpbRemovalDelayDeltasPresentFlag = sei.m_cpbRemovalDelayDeltasPresentFlag;
-  m_numCpbRemovalDelayDeltas = sei.m_numCpbRemovalDelayDeltas;
-  m_bpMaxSubLayers = sei.m_bpMaxSubLayers;
-  std::memcpy(m_cpbRemovalDelayDelta, sei.m_cpbRemovalDelayDelta, sizeof(sei.m_cpbRemovalDelayDelta));
-  m_bpDecodingUnitHrdParamsPresentFlag = sei.m_bpDecodingUnitHrdParamsPresentFlag;
-  m_decodingUnitCpbParamsInPicTimingSeiFlag = sei.m_decodingUnitCpbParamsInPicTimingSeiFlag;
-  m_decodingUnitDpbDuParamsInPicTimingSeiFlag = sei.m_decodingUnitDpbDuParamsInPicTimingSeiFlag;
-  m_sublayerInitialCpbRemovalDelayPresentFlag = sei.m_sublayerInitialCpbRemovalDelayPresentFlag;
-  m_additionalConcatenationInfoPresentFlag = sei.m_additionalConcatenationInfoPresentFlag;
-  m_maxInitialRemovalDelayForConcatenation = sei.m_maxInitialRemovalDelayForConcatenation;
-  m_sublayerDpbOutputOffsetsPresentFlag = sei.m_sublayerDpbOutputOffsetsPresentFlag;
-  std::memcpy(m_dpbOutputTidOffset, sei.m_dpbOutputTidOffset, sizeof(sei.m_dpbOutputTidOffset));
-  m_altCpbParamsPresentFlag = sei.m_altCpbParamsPresentFlag;
-  m_useAltCpbParamsFlag = sei.m_useAltCpbParamsFlag;
-}
+SEIBufferingPeriod::SEIBufferingPeriod(const SEIBufferingPeriod& sei) = default;
 
 SEIPictureTiming::SEIPictureTiming(const SEIPictureTiming& sei)
 {
diff --git a/source/Lib/CommonLib/SEI.h b/source/Lib/CommonLib/SEI.h
index 5f7e548ef..71f0a9a57 100644
--- a/source/Lib/CommonLib/SEI.h
+++ b/source/Lib/CommonLib/SEI.h
@@ -605,73 +605,74 @@ public:
   virtual ~SEIDependentRAPIndication() { }
 };
 
+enum class HrdType
+{
+  NAL,
+  VCL,
+  NUM
+};
 
 class SEIBufferingPeriod : public SEI
 {
 public:
+  struct CpbEntry
+  {
+    uint32_t delay;
+    uint32_t offset;
+  };
+
   PayloadType payloadType() const { return PayloadType::BUFFERING_PERIOD; }
-  void copyTo (SEIBufferingPeriod& target) const;
+  void        copyTo(SEIBufferingPeriod& target) const;
 
   SEIBufferingPeriod()
-  : m_bpNalCpbParamsPresentFlag (false)
-  , m_bpVclCpbParamsPresentFlag (false)
-  , m_initialCpbRemovalDelayLength (0)
-  , m_cpbRemovalDelayLength (0)
-  , m_dpbOutputDelayLength (0)
-  , m_bpCpbCnt(0)
-  , m_duCpbRemovalDelayIncrementLength (0)
-  , m_dpbOutputDelayDuLength (0)
-  , m_cpbRemovalDelayDeltasPresentFlag (false)
-  , m_numCpbRemovalDelayDeltas (0)
-  , m_bpMaxSubLayers (0)
-  , m_bpDecodingUnitHrdParamsPresentFlag (false)
-  , m_decodingUnitCpbParamsInPicTimingSeiFlag (false)
-  , m_decodingUnitDpbDuParamsInPicTimingSeiFlag(false)
-    , m_sublayerInitialCpbRemovalDelayPresentFlag(false)
-    , m_additionalConcatenationInfoPresentFlag (false)
-    , m_maxInitialRemovalDelayForConcatenation (0)
-    , m_sublayerDpbOutputOffsetsPresentFlag (false)
-    , 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));
-    ::memset(m_dpbOutputTidOffset, 0, sizeof(m_dpbOutputTidOffset));
+    hasHrdParams.fill(false);
+
+    for (auto hrdType: { HrdType::NAL, HrdType::VCL })
+    {
+      for (int sublayerIdx = 0; sublayerIdx < MAX_TLAYER; sublayerIdx++)
+      {
+        initialCpbRemoval[hrdType][sublayerIdx].fill({ 0, 0 });
+      }
+    }
+
+    cpbRemovalDelayDeltaVals.clear();
+    dpbOutputTidOffset.fill(0);
   }
+
   SEIBufferingPeriod(const SEIBufferingPeriod& sei);
   virtual ~SEIBufferingPeriod() {}
 
-  void      setDuCpbRemovalDelayIncrementLength( uint32_t value )        { m_duCpbRemovalDelayIncrementLength = value;        }
-  uint32_t  getDuCpbRemovalDelayIncrementLength( ) const                 { return m_duCpbRemovalDelayIncrementLength;         }
-  void      setDpbOutputDelayDuLength( uint32_t value )                  { m_dpbOutputDelayDuLength = value;                  }
-  uint32_t  getDpbOutputDelayDuLength( ) const                           { return m_dpbOutputDelayDuLength;                   }
-  bool m_bpNalCpbParamsPresentFlag;
-  bool m_bpVclCpbParamsPresentFlag;
-  uint32_t m_initialCpbRemovalDelayLength;
-  uint32_t m_cpbRemovalDelayLength;
-  uint32_t m_dpbOutputDelayLength;
-  int      m_bpCpbCnt;
-  uint32_t m_duCpbRemovalDelayIncrementLength;
-  uint32_t m_dpbOutputDelayDuLength;
-  uint32_t m_initialCpbRemovalDelay         [MAX_TLAYER][MAX_CPB_CNT][2];
-  uint32_t m_initialCpbRemovalOffset        [MAX_TLAYER][MAX_CPB_CNT][2];
-  bool m_concatenationFlag;
-  uint32_t m_auCpbRemovalDelayDelta;
-  bool m_cpbRemovalDelayDeltasPresentFlag;
-  int  m_numCpbRemovalDelayDeltas;
-  int  m_bpMaxSubLayers;
-  uint32_t m_cpbRemovalDelayDelta    [16];
-  bool m_bpDecodingUnitHrdParamsPresentFlag;
-  bool m_decodingUnitCpbParamsInPicTimingSeiFlag;
-  bool m_decodingUnitDpbDuParamsInPicTimingSeiFlag;
-  bool m_sublayerInitialCpbRemovalDelayPresentFlag;
-  bool     m_additionalConcatenationInfoPresentFlag;
-  uint32_t m_maxInitialRemovalDelayForConcatenation;
-  bool     m_sublayerDpbOutputOffsetsPresentFlag;
-  uint32_t m_dpbOutputTidOffset      [MAX_TLAYER];
-  bool     m_altCpbParamsPresentFlag;
-  bool     m_useAltCpbParamsFlag;
+  EnumArray<bool, HrdType> hasHrdParams;
+
+  bool concatenation                     = false;
+  bool hasDuHrdParams                    = false;
+  bool duCpbParamsInPicTimingSei         = false;
+  bool duDpbParamsInPicTimingSei         = false;
+  bool hasSublayerInitialCpbRemovalDelay = false;
+  bool hasAdditionalConcatenationInfo    = false;
+  bool hasSublayerDpbOutputOffsets       = false;
+  bool hasAltCpbParams                   = false;
+  bool useAltCpbParams                   = false;
+
+  uint32_t cpbInitialRemovalDelayLength           = 0;
+  uint32_t cpbRemovalDelayLength                  = 0;
+  uint32_t dpbOutputDelayLength                   = 0;
+  uint32_t cpbCount                               = 0;
+  uint32_t duCpbRemovalDelayIncrementLength       = 0;
+  uint32_t dpbOutputDelayDuLength                 = 0;
+  uint32_t cpbRemovalDelayDelta                   = 0;
+  uint32_t maxInitialRemovalDelayForConcatenation = 0;
+  int      maxSublayers                           = 0;
+
+  EnumArray<std::array<std::array<CpbEntry, MAX_CPB_CNT>, MAX_TLAYER>, HrdType> initialCpbRemoval;
+
+  static_vector<uint32_t, 16> cpbRemovalDelayDeltaVals;
+
+  bool     hasCpbRemovalDelayDeltas() const { return !cpbRemovalDelayDeltaVals.empty(); }
+  uint32_t numCpbRemovalDelayDeltas() const { return static_cast<uint32_t>(cpbRemovalDelayDeltaVals.size()); }
+
+  std::array<uint32_t, MAX_TLAYER> dpbOutputTidOffset;
 };
 
 class SEIPictureTiming : public SEI
diff --git a/source/Lib/DecoderLib/DecLib.cpp b/source/Lib/DecoderLib/DecLib.cpp
index 82f03b88f..4c2a50c4b 100644
--- a/source/Lib/DecoderLib/DecLib.cpp
+++ b/source/Lib/DecoderLib/DecLib.cpp
@@ -2754,10 +2754,10 @@ void DecLib::xCheckDUISEIMessages(SEIMessages &prefixSEIs)
   {
     bool duDelayFlag = false;
 
-    SEIBufferingPeriod *bp = (SEIBufferingPeriod *) BPSEIs.front();
-    if (bp->m_bpDecodingUnitHrdParamsPresentFlag)
+    auto* bp = reinterpret_cast<SEIBufferingPeriod*>(BPSEIs.front());
+    if (bp->hasDuHrdParams)
     {
-      if (!bp->m_decodingUnitDpbDuParamsInPicTimingSeiFlag)
+      if (!bp->duDpbParamsInPicTimingSei)
       {
         if (DUISEIs.empty())
         {
diff --git a/source/Lib/DecoderLib/SEIread.cpp b/source/Lib/DecoderLib/SEIread.cpp
index e2b6691e9..635352487 100644
--- a/source/Lib/DecoderLib/SEIread.cpp
+++ b/source/Lib/DecoderLib/SEIread.cpp
@@ -203,8 +203,7 @@ void SEIReader::parseAndExtractSEIScalableNesting(InputBitstream *bs, const NalU
 
 void SEIReader::getSEIDecodingUnitInfoDuiIdx(InputBitstream* bs, const NalUnitType nalUnitType, const uint32_t nuh_layer_id, HRD &hrd, uint32_t payloadSize, int& duiIdx)
 {
-  const SEIBufferingPeriod *bp = nullptr;
-  bp = hrd.getBufferingPeriodSEI();
+  const SEIBufferingPeriod* bp = hrd.getBufferingPeriodSEI();
   if (!bp)
   {
     // msg( WARNING, "Warning: Found Decoding unit information SEI message, but no active buffering period is available. Ignoring.");
@@ -303,8 +302,7 @@ bool SEIReader::xReadSEImessage(SEIMessages& seis, const NalUnitType nalUnitType
   InputBitstream *bs = getBitstream();
   setBitstream(bs->extractSubstream(payloadSize * 8));
 
-  SEI                      *sei = nullptr;
-  const SEIBufferingPeriod *bp  = nullptr;
+  SEI* sei = nullptr;
 
   if(nalUnitType == NAL_UNIT_PREFIX_SEI)
   {
@@ -319,36 +317,45 @@ bool SEIReader::xReadSEImessage(SEIMessages& seis, const NalUnitType nalUnitType
       xParseSEIuserDataUnregistered((SEIuserDataUnregistered&) *sei, payloadSize, pDecodedMessageOutputStream);
       break;
     case SEI::PayloadType::DECODING_UNIT_INFO:
-      bp = hrd.getBufferingPeriodSEI();
-      if (!bp)
       {
-        msg( WARNING, "Warning: Found Decoding unit information SEI message, but no active buffering period is available. Ignoring.");
-      }
-      else
-      {
-        sei = new SEIDecodingUnitInfo;
-        xParseSEIDecodingUnitInfo((SEIDecodingUnitInfo&) *sei, payloadSize, *bp, temporalId, pDecodedMessageOutputStream);
+        const SEIBufferingPeriod* bp = hrd.getBufferingPeriodSEI();
+        if (bp == nullptr)
+        {
+          msg(WARNING, "Warning: Found Decoding unit information SEI message, but no active buffering period is "
+                       "available. Ignoring.");
+        }
+        else
+        {
+          sei = new SEIDecodingUnitInfo;
+          xParseSEIDecodingUnitInfo((SEIDecodingUnitInfo&) *sei, payloadSize, *bp, temporalId,
+                                    pDecodedMessageOutputStream);
+        }
+        break;
       }
-      break;
     case SEI::PayloadType::BUFFERING_PERIOD:
-      sei = new SEIBufferingPeriod;
-      xParseSEIBufferingPeriod((SEIBufferingPeriod&) *sei, payloadSize, pDecodedMessageOutputStream);
-      hrd.setBufferingPeriodSEI((SEIBufferingPeriod*) sei);
-      break;
-    case SEI::PayloadType::PICTURE_TIMING:
-      bp = hrd.getBufferingPeriodSEI();
-      if (!bp)
       {
-        msg(WARNING,
-            "Warning: Found Picture timing SEI message, but no active buffering period is available. Ignoring.");
+        auto bp = new SEIBufferingPeriod;
+        xParseSEIBufferingPeriod(*bp, payloadSize, pDecodedMessageOutputStream);
+        hrd.setBufferingPeriodSEI(bp);
+        sei = bp;
+        break;
       }
-      else
+    case SEI::PayloadType::PICTURE_TIMING:
       {
-        sei = new SEIPictureTiming;
-        xParseSEIPictureTiming((SEIPictureTiming &) *sei, payloadSize, temporalId, *bp, pDecodedMessageOutputStream);
-        hrd.setPictureTimingSEI((SEIPictureTiming *) sei);
+        const SEIBufferingPeriod* bp = hrd.getBufferingPeriodSEI();
+        if (bp == nullptr)
+        {
+          msg(WARNING,
+              "Warning: Found Picture timing SEI message, but no active buffering period is available. Ignoring.");
+        }
+        else
+        {
+          sei = new SEIPictureTiming;
+          xParseSEIPictureTiming((SEIPictureTiming&) *sei, payloadSize, temporalId, *bp, pDecodedMessageOutputStream);
+          hrd.setPictureTimingSEI((SEIPictureTiming*) sei);
+        }
+        break;
       }
-      break;
     case SEI::PayloadType::SCALABLE_NESTING:
       sei = new SEIScalableNesting;
       xParseSEIScalableNesting((SEIScalableNesting &) *sei, nalUnitType, nuh_layer_id, payloadSize, vps, sps, hrd,
@@ -1031,7 +1038,7 @@ void SEIReader::xParseSEIScalableNesting(SEIScalableNesting& sei, const NalUnitT
     {
       if (tmpSEIs.front()->payloadType() == SEI::PayloadType::BUFFERING_PERIOD)
       {
-        SEIBufferingPeriod *bp = (SEIBufferingPeriod*)tmpSEIs.front();
+        auto bp = reinterpret_cast<SEIBufferingPeriod*>(tmpSEIs.front());
         m_nestedHrd.setBufferingPeriodSEI(bp);
         const SEIBufferingPeriod *nonNestedBp = hrd.getBufferingPeriodSEI();
         if (nonNestedBp)
@@ -1307,9 +1314,8 @@ void SEIReader::xParseSEIScalableNestingBinary(SEIScalableNesting &sei, const Na
     int duiIdx = 0;
     if (SEI::PayloadType(payloadType) == SEI::PayloadType::DECODING_UNIT_INFO)
     {
-      const SEIBufferingPeriod *bp = nullptr;
-      bp = hrd.getBufferingPeriodSEI();
-      if (!bp)
+      const SEIBufferingPeriod* bp = hrd.getBufferingPeriodSEI();
+      if (bp == nullptr)
       {
         //msg( WARNING, "Warning: Found Decoding unit information SEI message, but no active buffering period is available. Ignoring.");
       }
@@ -1492,11 +1498,11 @@ void SEIReader::xParseSEIDecodingUnitInfo(SEIDecodingUnitInfo& sei, uint32_t pay
   sei_read_uvlc( pDecodedMessageOutputStream, val, "decoding_unit_idx");
   sei.m_decodingUnitIdx = val;
 
-  if(!bp.m_decodingUnitCpbParamsInPicTimingSeiFlag)
+  if (!bp.duCpbParamsInPicTimingSei)
   {
-    for (int i = temporalId; i <= bp.m_bpMaxSubLayers - 1; i++)
+    for (int i = temporalId; i < bp.maxSublayers; i++)
     {
-      if (i < (bp.m_bpMaxSubLayers - 1))
+      if (i < bp.maxSublayers - 1)
       {
         sei_read_flag( pDecodedMessageOutputStream, val, "dui_sub_layer_delays_present_flag[i]" );
         sei.m_duiSubLayerDelaysPresentFlag[i] = val;
@@ -1507,7 +1513,8 @@ void SEIReader::xParseSEIDecodingUnitInfo(SEIDecodingUnitInfo& sei, uint32_t pay
       }
       if( sei.m_duiSubLayerDelaysPresentFlag[i] )
       {
-        sei_read_code( pDecodedMessageOutputStream, bp.getDuCpbRemovalDelayIncrementLength(), val, "du_spt_cpb_removal_delay_increment[i]");
+        sei_read_code(pDecodedMessageOutputStream, bp.duCpbRemovalDelayIncrementLength, val,
+                      "du_spt_cpb_removal_delay_increment[i]");
         sei.m_duSptCpbRemovalDelayIncrement[i] = val;
       }
       else
@@ -1518,13 +1525,13 @@ void SEIReader::xParseSEIDecodingUnitInfo(SEIDecodingUnitInfo& sei, uint32_t pay
   }
   else
   {
-    for( int i = temporalId; i < bp.m_bpMaxSubLayers - 1; i ++ )
+    for (int i = temporalId; i < bp.maxSublayers - 1; i++)
     {
       sei.m_duSptCpbRemovalDelayIncrement[i] = 0;
     }
   }
 
-  if (!bp.m_decodingUnitDpbDuParamsInPicTimingSeiFlag)
+  if (!bp.duDpbParamsInPicTimingSei)
   {
     sei_read_flag(pDecodedMessageOutputStream, val, "dpb_output_du_delay_present_flag"); sei.m_dpbOutputDuDelayPresentFlag = (val != 0);
   }
@@ -1534,130 +1541,155 @@ void SEIReader::xParseSEIDecodingUnitInfo(SEIDecodingUnitInfo& sei, uint32_t pay
   }
   if(sei.m_dpbOutputDuDelayPresentFlag)
   {
-    sei_read_code( pDecodedMessageOutputStream, bp.getDpbOutputDelayDuLength(), val, "pic_spt_dpb_output_du_delay");
-    if (sei.m_picSptDpbOutputDuDelay != -1)
-       CHECK(sei.m_picSptDpbOutputDuDelay!=val,"When signaled m_picSptDpbOutputDuDelay value must be same for DUs");
+    sei_read_code(pDecodedMessageOutputStream, bp.dpbOutputDelayDuLength, val, "pic_spt_dpb_output_du_delay");
+    CHECK(sei.m_picSptDpbOutputDuDelay != -1 && sei.m_picSptDpbOutputDuDelay != val,
+          "When signaled m_picSptDpbOutputDuDelay value must be same for DUs");
     sei.m_picSptDpbOutputDuDelay = val;
   }
 }
 
-void SEIReader::xParseSEIBufferingPeriod(SEIBufferingPeriod& sei, uint32_t payloadSize, std::ostream *pDecodedMessageOutputStream)
+void SEIReader::xParseSEIBufferingPeriod(SEIBufferingPeriod& bp, uint32_t payloadSize,
+                                         std::ostream* pDecodedMessageOutputStream)
 {
-  int i, nalOrVcl;
   uint32_t code;
 
-  output_sei_message_header(sei, pDecodedMessageOutputStream, payloadSize);
-
-  sei_read_flag( pDecodedMessageOutputStream, code, "bp_nal_hrd_parameters_present_flag" );               sei.m_bpNalCpbParamsPresentFlag = code;
-  sei_read_flag( pDecodedMessageOutputStream, code, "bp_vcl_hrd_parameters_present_flag" );               sei.m_bpVclCpbParamsPresentFlag = code;
-
-  sei_read_code( pDecodedMessageOutputStream, 5, code, "initial_cpb_removal_delay_length_minus1" );     sei.m_initialCpbRemovalDelayLength = code + 1;
-  sei_read_code( pDecodedMessageOutputStream, 5, code, "cpb_removal_delay_length_minus1" );             sei.m_cpbRemovalDelayLength        = code + 1;
-  sei_read_code( pDecodedMessageOutputStream, 5, code, "dpb_output_delay_length_minus1" );              sei.m_dpbOutputDelayLength         = code + 1;
-  sei_read_flag( pDecodedMessageOutputStream, code, "bp_decoding_unit_hrd_params_present_flag" );       sei.m_bpDecodingUnitHrdParamsPresentFlag = code;
-  if( sei.m_bpDecodingUnitHrdParamsPresentFlag )
-  {
-    sei_read_code( pDecodedMessageOutputStream, 5, code, "du_cpb_removal_delay_increment_length_minus1" );  sei.m_duCpbRemovalDelayIncrementLength = code + 1;
-    sei_read_code( pDecodedMessageOutputStream, 5, code, "dpb_output_delay_du_length_minus1" );             sei.m_dpbOutputDelayDuLength = code + 1;
-    sei_read_flag( pDecodedMessageOutputStream, code, "decoding_unit_cpb_params_in_pic_timing_sei_flag" );  sei.m_decodingUnitCpbParamsInPicTimingSeiFlag = code;
-    sei_read_flag(pDecodedMessageOutputStream, code, "decoding_unit_dpb_du_params_in_pic_timing_sei_flag");  sei.m_decodingUnitDpbDuParamsInPicTimingSeiFlag = code;
+  output_sei_message_header(bp, pDecodedMessageOutputStream, payloadSize);
+
+  sei_read_flag(pDecodedMessageOutputStream, code, "bp_nal_hrd_params_present_flag");
+  bp.hasHrdParams[HrdType::NAL] = code != 0;
+  sei_read_flag(pDecodedMessageOutputStream, code, "bp_vcl_hrd_params_present_flag");
+  bp.hasHrdParams[HrdType::VCL] = code != 0;
+
+  CHECK(!bp.hasHrdParams[HrdType::NAL] && !bp.hasHrdParams[HrdType::VCL],
+        "bp_vcl_hrd_params_present_flag and bp_nal_hrd_params_present_flag in a BP SEI message shall not both be equal "
+        "to 0");
+
+  sei_read_code(pDecodedMessageOutputStream, 5, code, "bp_cpb_initial_removal_delay_length_minus1");
+  bp.cpbInitialRemovalDelayLength = code + 1;
+  sei_read_code(pDecodedMessageOutputStream, 5, code, "bp_cpb_removal_delay_length_minus1");
+  bp.cpbRemovalDelayLength = code + 1;
+  sei_read_code(pDecodedMessageOutputStream, 5, code, "bp_dpb_output_delay_length_minus1");
+  bp.dpbOutputDelayLength = code + 1;
+  sei_read_flag(pDecodedMessageOutputStream, code, "bp_du_hrd_params_present_flag");
+  bp.hasDuHrdParams = code != 0;
+  if (bp.hasDuHrdParams)
+  {
+    sei_read_code(pDecodedMessageOutputStream, 5, code, "bp_du_cpb_removal_delay_increment_length_minus1");
+    bp.duCpbRemovalDelayIncrementLength = code + 1;
+    sei_read_code(pDecodedMessageOutputStream, 5, code, "bp_dpb_output_delay_du_length_minus1");
+    bp.dpbOutputDelayDuLength = code + 1;
+    sei_read_flag(pDecodedMessageOutputStream, code, "bp_du_cpb_params_in_pic_timing_sei_flag");
+    bp.duCpbParamsInPicTimingSei = code != 0;
+    sei_read_flag(pDecodedMessageOutputStream, code, "bp_du_dpb_params_in_pic_timing_sei_flag");
+    bp.duDpbParamsInPicTimingSei = code != 0;
   }
   else
   {
-    sei.m_duCpbRemovalDelayIncrementLength = 24;
-    sei.m_dpbOutputDelayDuLength = 24;
-    sei.m_decodingUnitCpbParamsInPicTimingSeiFlag = false;
-    sei.m_decodingUnitDpbDuParamsInPicTimingSeiFlag = false;
+    bp.duCpbRemovalDelayIncrementLength = 24;
+    bp.dpbOutputDelayDuLength           = 24;
+    bp.duCpbParamsInPicTimingSei        = false;
+    bp.duDpbParamsInPicTimingSei        = false;
   }
 
-  CHECK(sei.m_altCpbParamsPresentFlag && sei.m_bpDecodingUnitHrdParamsPresentFlag,"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");
-
-  sei_read_flag( pDecodedMessageOutputStream, code, "concatenation_flag");
-  sei.m_concatenationFlag = code;
-  sei_read_flag ( pDecodedMessageOutputStream, code, "additional_concatenation_info_present_flag");
-  sei.m_additionalConcatenationInfoPresentFlag = code;
-  if (sei.m_additionalConcatenationInfoPresentFlag)
+  sei_read_flag(pDecodedMessageOutputStream, code, "bp_concatenation_flag");
+  bp.concatenation = code != 0;
+  sei_read_flag(pDecodedMessageOutputStream, code, "bp_additional_concatenation_info_present_flag");
+  bp.hasAdditionalConcatenationInfo = code != 0;
+  if (bp.hasAdditionalConcatenationInfo)
   {
-    sei_read_code( pDecodedMessageOutputStream, sei.m_initialCpbRemovalDelayLength, code, "max_initial_removal_delay_for_concatenation" );
-    sei.m_maxInitialRemovalDelayForConcatenation = code;
+    sei_read_code(pDecodedMessageOutputStream, bp.cpbInitialRemovalDelayLength, code,
+                  "bp_max_initial_removal_delay_for_concatenation");
+    bp.maxInitialRemovalDelayForConcatenation = code;
   }
 
-  sei_read_code( pDecodedMessageOutputStream, ( sei.m_cpbRemovalDelayLength ), code, "au_cpb_removal_delay_delta_minus1" );
-  sei.m_auCpbRemovalDelayDelta = code + 1;
-  sei_read_code(pDecodedMessageOutputStream, 3, code, "bp_max_sub_layers_minus1");
-  sei.m_bpMaxSubLayers = code + 1;
-  if (sei.m_bpMaxSubLayers - 1 > 0)
-  {
-    sei_read_flag(pDecodedMessageOutputStream, code, "cpb_removal_delay_deltas_present_flag");
-    sei.m_cpbRemovalDelayDeltasPresentFlag = code;
-  }
-  else
-  {
-    sei.m_cpbRemovalDelayDeltasPresentFlag = false;
-  }
-  if (sei.m_cpbRemovalDelayDeltasPresentFlag)
+  sei_read_code(pDecodedMessageOutputStream, bp.cpbRemovalDelayLength, code, "bp_cpb_removal_delay_delta_minus1");
+  bp.cpbRemovalDelayDelta = code + 1;
+  sei_read_code(pDecodedMessageOutputStream, 3, code, "bp_max_sublayers_minus1");
+  bp.maxSublayers = code + 1;
+
+  bp.cpbRemovalDelayDeltaVals.clear();
+
+  if (bp.maxSublayers > 1)
   {
-    sei_read_uvlc( pDecodedMessageOutputStream, code, "num_cpb_removal_delay_deltas_minus1" );
-    CHECK(code>15, "The value of num_cpb_removal_offsets_minus1 shall be in the range of 0 to 15, inclusive.")
-    sei.m_numCpbRemovalDelayDeltas = code + 1;
-    for( i = 0; i < sei.m_numCpbRemovalDelayDeltas; i ++ )
+    sei_read_flag(pDecodedMessageOutputStream, code, "bp_cpb_removal_delay_deltas_present_flag");
+
+    if (code != 0)
     {
-      sei_read_code( pDecodedMessageOutputStream, ( sei.m_cpbRemovalDelayLength ), code, "cpb_removal_delay_delta[i]" );
-      sei.m_cpbRemovalDelayDelta[ i ] = code;
+      sei_read_uvlc(pDecodedMessageOutputStream, code, "bp_num_cpb_removal_delay_deltas_minus1");
+      CHECK(code >= bp.cpbRemovalDelayDeltaVals.capacity(),
+            "The value of num_cpb_removal_offsets_minus1 shall be in the range of 0 to 15, inclusive.")
+      bp.cpbRemovalDelayDeltaVals.resize(code + 1);
+      for (size_t i = 0; i < bp.numCpbRemovalDelayDeltas(); i++)
+      {
+        sei_read_code(pDecodedMessageOutputStream, bp.cpbRemovalDelayLength, code, "bp_cpb_removal_delay_delta_val[i]");
+        bp.cpbRemovalDelayDeltaVals[i] = code;
+      }
     }
   }
+
   sei_read_uvlc(pDecodedMessageOutputStream, code, "bp_cpb_cnt_minus1");
-  sei.m_bpCpbCnt = code + 1;
-  if (sei.m_bpMaxSubLayers - 1 > 0)
+  CHECK(code >= MAX_CPB_CNT, "The value of bp_cpb_cnt_minus1 shall be in the range of 0 to 31, inclusive");
+
+  bp.cpbCount = code + 1;
+  if (bp.maxSublayers > 1)
   {
     sei_read_flag(pDecodedMessageOutputStream, code, "bp_sublayer_initial_cpb_removal_delay_present_flag");
-    sei.m_sublayerInitialCpbRemovalDelayPresentFlag = code;
+    bp.hasSublayerInitialCpbRemovalDelay = code != 0;
   }
   else
   {
-    sei.m_sublayerInitialCpbRemovalDelayPresentFlag = false;
+    bp.hasSublayerInitialCpbRemovalDelay = false;
   }
-  for (i = (sei.m_sublayerInitialCpbRemovalDelayPresentFlag ? 0 : sei.m_bpMaxSubLayers - 1); i < sei.m_bpMaxSubLayers; i++)
+
+  for (int sublayerIdx = (bp.hasSublayerInitialCpbRemovalDelay ? 0 : bp.maxSublayers - 1);
+       sublayerIdx < bp.maxSublayers; sublayerIdx++)
   {
-    for( nalOrVcl = 0; nalOrVcl < 2; nalOrVcl ++ )
+    for (auto hrdType: { HrdType::NAL, HrdType::VCL })
     {
-      if( ( ( nalOrVcl == 0 ) && ( sei.m_bpNalCpbParamsPresentFlag ) ) ||
-         ( ( nalOrVcl == 1 ) && ( sei.m_bpVclCpbParamsPresentFlag ) ) )
+      if (bp.hasHrdParams[hrdType])
       {
-        for( int j = 0; j < ( sei.m_bpCpbCnt ); j ++ )
+        for (int j = 0; j < bp.cpbCount; j++)
         {
-          sei_read_code( pDecodedMessageOutputStream, sei.m_initialCpbRemovalDelayLength, code, nalOrVcl ? "vcl_initial_cpb_removal_delay[i][j]" : "nal_initial_cpb_removal_delay[i][j]" );
-          sei.m_initialCpbRemovalDelay[i][j][nalOrVcl] = code;
-          sei_read_code( pDecodedMessageOutputStream, sei.m_initialCpbRemovalDelayLength, code, nalOrVcl ? "vcl_initial_cpb_removal_offset[i][j]" : "nal_initial_cpb_removal_offset[i][j]" );
-          sei.m_initialCpbRemovalOffset[i][j][nalOrVcl] = code;
+          sei_read_code(pDecodedMessageOutputStream, bp.cpbInitialRemovalDelayLength, code,
+                        hrdType == HrdType::NAL ? "bp_nal_initial_cpb_removal_delay[i][j]"
+                                                : "bp_vcl_initial_cpb_removal_delay[i][j]");
+          bp.initialCpbRemoval[hrdType][sublayerIdx][j].delay = code;
+          sei_read_code(pDecodedMessageOutputStream, bp.cpbInitialRemovalDelayLength, code,
+                        hrdType == HrdType::NAL ? "bp_nal_initial_cpb_removal_offset[i][j]"
+                                                : "bp_vcl_initial_cpb_removal_offset[i][j]");
+          bp.initialCpbRemoval[hrdType][sublayerIdx][j].offset = code;
         }
       }
     }
   }
-  if (sei.m_bpMaxSubLayers-1 > 0)
+  if (bp.maxSublayers > 1)
   {
     sei_read_flag(pDecodedMessageOutputStream, code, "bp_sublayer_dpb_output_offsets_present_flag");
-    sei.m_sublayerDpbOutputOffsetsPresentFlag = code;
+    bp.hasSublayerDpbOutputOffsets = code;
   }
   else
   {
-    sei.m_sublayerDpbOutputOffsetsPresentFlag = false;
+    bp.hasSublayerDpbOutputOffsets = false;
   }
-  if(sei.m_sublayerDpbOutputOffsetsPresentFlag)
+  if (bp.hasSublayerDpbOutputOffsets)
   {
-    for(int i = 0; i < sei.m_bpMaxSubLayers - 1; i++)
+    for (int i = 0; i < bp.maxSublayers - 1; i++)
     {
-      sei_read_uvlc( pDecodedMessageOutputStream, code, "dpb_output_tid_offset[i]" );
-      sei.m_dpbOutputTidOffset[i] = code;
+      sei_read_uvlc(pDecodedMessageOutputStream, code, "bp_dpb_output_tid_offset[i]");
+      bp.dpbOutputTidOffset[i] = code;
     }
-    sei.m_dpbOutputTidOffset[sei.m_bpMaxSubLayers-1] = 0;
+    bp.dpbOutputTidOffset[bp.maxSublayers - 1] = 0;
   }
   sei_read_flag(pDecodedMessageOutputStream, code, "bp_alt_cpb_params_present_flag");
-  sei.m_altCpbParamsPresentFlag = code;
-  if (sei.m_altCpbParamsPresentFlag)
+  bp.hasAltCpbParams = code;
+  if (bp.hasAltCpbParams)
   {
-    sei_read_flag(pDecodedMessageOutputStream, code, "use_alt_cpb_params_flag"); sei.m_useAltCpbParamsFlag = code;
+    sei_read_flag(pDecodedMessageOutputStream, code, "bp_use_alt_cpb_params_flag");
+    bp.useAltCpbParams = code;
   }
+
+  CHECK(bp.hasAltCpbParams && bp.hasDuHrdParams, "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");
 }
 
 void SEIReader::xParseSEIPictureTiming(SEIPictureTiming& sei, uint32_t payloadSize, const uint32_t temporalId, const SEIBufferingPeriod& bp, std::ostream *pDecodedMessageOutputStream)
@@ -1665,16 +1697,17 @@ void SEIReader::xParseSEIPictureTiming(SEIPictureTiming& sei, uint32_t payloadSi
   output_sei_message_header(sei, pDecodedMessageOutputStream, payloadSize);
 
   uint32_t symbol;
-  sei_read_code( pDecodedMessageOutputStream, bp.m_cpbRemovalDelayLength, symbol, "pt_cpb_removal_delay_minus1[bp_max_sub_layers_minus1]" );
-  sei.m_auCpbRemovalDelay[bp.m_bpMaxSubLayers - 1] = symbol + 1;
-  sei.m_ptSubLayerDelaysPresentFlag[bp.m_bpMaxSubLayers - 1] = true;
-  for (int i = temporalId; i < bp.m_bpMaxSubLayers - 1; i++)
+  sei_read_code(pDecodedMessageOutputStream, bp.cpbRemovalDelayLength, symbol,
+                "pt_cpb_removal_delay_minus1[bp_max_sub_layers_minus1]");
+  sei.m_auCpbRemovalDelay[bp.maxSublayers - 1]           = symbol + 1;
+  sei.m_ptSubLayerDelaysPresentFlag[bp.maxSublayers - 1] = true;
+  for (int i = temporalId; i < bp.maxSublayers - 1; i++)
   {
     sei_read_flag(pDecodedMessageOutputStream, symbol, "pt_sublayer_delays_present_flag[i]");
     sei.m_ptSubLayerDelaysPresentFlag[i] = (symbol == 1);
     if (sei.m_ptSubLayerDelaysPresentFlag[i])
     {
-      if (bp.m_cpbRemovalDelayDeltasPresentFlag)
+      if (bp.hasCpbRemovalDelayDeltas())
       {
         sei_read_flag(pDecodedMessageOutputStream, symbol, "pt_cpb_removal_delay_delta_enabled_flag[i]");
         sei.m_cpbRemovalDelayDeltaEnabledFlag[i] = (symbol == 1);
@@ -1685,9 +1718,10 @@ void SEIReader::xParseSEIPictureTiming(SEIPictureTiming& sei, uint32_t payloadSi
       }
       if (sei.m_cpbRemovalDelayDeltaEnabledFlag[i])
       {
-        if ((bp.m_numCpbRemovalDelayDeltas - 1) > 0)
+        if (bp.numCpbRemovalDelayDeltas() > 1)
         {
-          sei_read_code(pDecodedMessageOutputStream, ceilLog2(bp.m_numCpbRemovalDelayDeltas), symbol, "pt_cpb_removal_delay_delta_idx[i]");
+          sei_read_code(pDecodedMessageOutputStream, ceilLog2(bp.numCpbRemovalDelayDeltas()), symbol,
+                        "pt_cpb_removal_delay_delta_idx[i]");
           sei.m_cpbRemovalDelayDeltaIdx[i] = symbol;
         }
         else
@@ -1697,75 +1731,73 @@ void SEIReader::xParseSEIPictureTiming(SEIPictureTiming& sei, uint32_t payloadSi
       }
       else
       {
-        sei_read_code(pDecodedMessageOutputStream, bp.m_cpbRemovalDelayLength, symbol, "pt_cpb_removal_delay_minus1[i]");
+        sei_read_code(pDecodedMessageOutputStream, bp.cpbRemovalDelayLength, symbol, "pt_cpb_removal_delay_minus1[i]");
         sei.m_auCpbRemovalDelay[i] = symbol + 1;
       }
     }
   }
-  sei_read_code(pDecodedMessageOutputStream, bp.m_dpbOutputDelayLength, symbol, "pt_dpb_output_delay");
+  sei_read_code(pDecodedMessageOutputStream, bp.dpbOutputDelayLength, symbol, "pt_dpb_output_delay");
   sei.m_picDpbOutputDelay = symbol;
 
-  if( bp.m_altCpbParamsPresentFlag )
+  if (bp.hasAltCpbParams)
   {
     sei_read_flag( pDecodedMessageOutputStream, symbol, "cpb_alt_timing_info_present_flag" ); sei.m_cpbAltTimingInfoPresentFlag = symbol;
     if( sei.m_cpbAltTimingInfoPresentFlag )
     {
-      if (bp.m_bpNalCpbParamsPresentFlag)
+      if (bp.hasHrdParams[HrdType::NAL])
       {
-        sei.m_nalCpbAltInitialRemovalDelayDelta.resize(bp.m_bpMaxSubLayers);
-        sei.m_nalCpbAltInitialRemovalOffsetDelta.resize(bp.m_bpMaxSubLayers);
-        for (int i = 0; i <= bp.m_bpMaxSubLayers - 1; ++i)
+        sei.m_nalCpbAltInitialRemovalDelayDelta.resize(bp.maxSublayers);
+        sei.m_nalCpbAltInitialRemovalOffsetDelta.resize(bp.maxSublayers);
+        for (int i = 0; i < bp.maxSublayers; ++i)
         {
-          sei.m_nalCpbAltInitialRemovalDelayDelta[i].resize(bp.m_bpCpbCnt, 0);
-          sei.m_nalCpbAltInitialRemovalOffsetDelta[i].resize(bp.m_bpCpbCnt, 0);
+          sei.m_nalCpbAltInitialRemovalDelayDelta[i].resize(bp.cpbCount, 0);
+          sei.m_nalCpbAltInitialRemovalOffsetDelta[i].resize(bp.cpbCount, 0);
         }
-        sei.m_nalCpbDelayOffset.resize(bp.m_bpMaxSubLayers, 0);
-        sei.m_nalDpbDelayOffset.resize(bp.m_bpMaxSubLayers, 0);
-        for (int i = (bp.m_sublayerInitialCpbRemovalDelayPresentFlag ? 0 : bp.m_bpMaxSubLayers - 1);
-             i <= bp.m_bpMaxSubLayers - 1; ++i)
+        sei.m_nalCpbDelayOffset.resize(bp.maxSublayers, 0);
+        sei.m_nalDpbDelayOffset.resize(bp.maxSublayers, 0);
+        for (int i = (bp.hasSublayerInitialCpbRemovalDelay ? 0 : bp.maxSublayers - 1); i < bp.maxSublayers; ++i)
         {
-          for (int j = 0; j < bp.m_bpCpbCnt; j++)
+          for (int j = 0; j < bp.cpbCount; j++)
           {
-            sei_read_code(pDecodedMessageOutputStream, bp.m_initialCpbRemovalDelayLength, symbol,
+            sei_read_code(pDecodedMessageOutputStream, bp.cpbInitialRemovalDelayLength, symbol,
                           "nal_cpb_alt_initial_cpb_removal_delay_delta[ i ][ j ]");
             sei.m_nalCpbAltInitialRemovalDelayDelta[i][j] = symbol;
-            sei_read_code(pDecodedMessageOutputStream, bp.m_initialCpbRemovalDelayLength, symbol,
+            sei_read_code(pDecodedMessageOutputStream, bp.cpbInitialRemovalDelayLength, symbol,
                           "nal_cpb_alt_initial_cpb_removal_offset_delta[ i ][ j ]");
             sei.m_nalCpbAltInitialRemovalOffsetDelta[i][j] = symbol;
           }
-          sei_read_code(pDecodedMessageOutputStream, bp.m_cpbRemovalDelayLength, sei.m_nalCpbDelayOffset[i],
+          sei_read_code(pDecodedMessageOutputStream, bp.cpbRemovalDelayLength, sei.m_nalCpbDelayOffset[i],
                         "nal_cpb_delay_offset[ i ]");
-          sei_read_code(pDecodedMessageOutputStream, bp.m_dpbOutputDelayLength, sei.m_nalDpbDelayOffset[i],
+          sei_read_code(pDecodedMessageOutputStream, bp.dpbOutputDelayLength, sei.m_nalDpbDelayOffset[i],
                         "nal_dpb_delay_offset[ i ]");
         }
       }
 
-      if (bp.m_bpVclCpbParamsPresentFlag)
+      if (bp.hasHrdParams[HrdType::VCL])
       {
-        sei.m_vclCpbAltInitialRemovalDelayDelta.resize(bp.m_bpMaxSubLayers);
-        sei.m_vclCpbAltInitialRemovalOffsetDelta.resize(bp.m_bpMaxSubLayers);
-        for (int i = 0; i <= bp.m_bpMaxSubLayers - 1; ++i)
+        sei.m_vclCpbAltInitialRemovalDelayDelta.resize(bp.maxSublayers);
+        sei.m_vclCpbAltInitialRemovalOffsetDelta.resize(bp.maxSublayers);
+        for (int i = 0; i < bp.maxSublayers; ++i)
         {
-          sei.m_vclCpbAltInitialRemovalDelayDelta[i].resize(bp.m_bpCpbCnt, 0);
-          sei.m_vclCpbAltInitialRemovalOffsetDelta[i].resize(bp.m_bpCpbCnt, 0);
+          sei.m_vclCpbAltInitialRemovalDelayDelta[i].resize(bp.cpbCount, 0);
+          sei.m_vclCpbAltInitialRemovalOffsetDelta[i].resize(bp.cpbCount, 0);
         }
-        sei.m_vclCpbDelayOffset.resize(bp.m_bpMaxSubLayers, 0);
-        sei.m_vclDpbDelayOffset.resize(bp.m_bpMaxSubLayers, 0);
-        for (int i = (bp.m_sublayerInitialCpbRemovalDelayPresentFlag ? 0 : bp.m_bpMaxSubLayers - 1);
-             i <= bp.m_bpMaxSubLayers - 1; ++i)
+        sei.m_vclCpbDelayOffset.resize(bp.maxSublayers, 0);
+        sei.m_vclDpbDelayOffset.resize(bp.maxSublayers, 0);
+        for (int i = (bp.hasSublayerInitialCpbRemovalDelay ? 0 : bp.maxSublayers - 1); i < bp.maxSublayers; ++i)
         {
-          for (int j = 0; j < bp.m_bpCpbCnt; j++)
+          for (int j = 0; j < bp.cpbCount; j++)
           {
-            sei_read_code(pDecodedMessageOutputStream, bp.m_initialCpbRemovalDelayLength, symbol,
+            sei_read_code(pDecodedMessageOutputStream, bp.cpbInitialRemovalDelayLength, symbol,
                           "vcl_cpb_alt_initial_cpb_removal_delay_delta[ i ][ j ]");
             sei.m_vclCpbAltInitialRemovalDelayDelta[i][j] = symbol;
-            sei_read_code(pDecodedMessageOutputStream, bp.m_initialCpbRemovalDelayLength, symbol,
+            sei_read_code(pDecodedMessageOutputStream, bp.cpbInitialRemovalDelayLength, symbol,
                           "vcl_cpb_alt_initial_cpb_removal_offset_delta[ i ][ j ]");
             sei.m_vclCpbAltInitialRemovalOffsetDelta[i][j] = symbol;
           }
-          sei_read_code(pDecodedMessageOutputStream, bp.m_cpbRemovalDelayLength, sei.m_vclCpbDelayOffset[i],
+          sei_read_code(pDecodedMessageOutputStream, bp.cpbRemovalDelayLength, sei.m_vclCpbDelayOffset[i],
                         "vcl_cpb_delay_offset[ i ]");
-          sei_read_code(pDecodedMessageOutputStream, bp.m_dpbOutputDelayLength, sei.m_vclDpbDelayOffset[i],
+          sei_read_code(pDecodedMessageOutputStream, bp.dpbOutputDelayLength, sei.m_vclDpbDelayOffset[i],
                         "vcl_dpb_delay_offset[ i ]");
         }
       }
@@ -1774,40 +1806,38 @@ void SEIReader::xParseSEIPictureTiming(SEIPictureTiming& sei, uint32_t payloadSi
   else
   {
     sei.m_cpbAltTimingInfoPresentFlag = false;
-    sei.m_nalCpbAltInitialRemovalDelayDelta.resize(bp.m_bpMaxSubLayers);
-    sei.m_nalCpbAltInitialRemovalOffsetDelta.resize(bp.m_bpMaxSubLayers);
-    sei.m_nalCpbDelayOffset.resize(bp.m_bpMaxSubLayers, 0);
-    sei.m_nalDpbDelayOffset.resize(bp.m_bpMaxSubLayers, 0);
-    for (int i = (bp.m_sublayerInitialCpbRemovalDelayPresentFlag ? 0 : bp.m_bpMaxSubLayers - 1);
-         i <= bp.m_bpMaxSubLayers - 1; ++i)
+    sei.m_nalCpbAltInitialRemovalDelayDelta.resize(bp.maxSublayers);
+    sei.m_nalCpbAltInitialRemovalOffsetDelta.resize(bp.maxSublayers);
+    sei.m_nalCpbDelayOffset.resize(bp.maxSublayers, 0);
+    sei.m_nalDpbDelayOffset.resize(bp.maxSublayers, 0);
+    for (int i = (bp.hasSublayerInitialCpbRemovalDelay ? 0 : bp.maxSublayers - 1); i < bp.maxSublayers; ++i)
     {
-      sei.m_nalCpbAltInitialRemovalDelayDelta[i].resize(bp.m_bpCpbCnt, 0);
-      sei.m_nalCpbAltInitialRemovalOffsetDelta[i].resize(bp.m_bpCpbCnt, 0);
+      sei.m_nalCpbAltInitialRemovalDelayDelta[i].resize(bp.cpbCount, 0);
+      sei.m_nalCpbAltInitialRemovalOffsetDelta[i].resize(bp.cpbCount, 0);
     }
 
-    sei.m_vclCpbAltInitialRemovalDelayDelta.resize(bp.m_bpMaxSubLayers);
-    sei.m_vclCpbAltInitialRemovalOffsetDelta.resize(bp.m_bpMaxSubLayers);
-    sei.m_vclCpbDelayOffset.resize(bp.m_bpMaxSubLayers, 0);
-    sei.m_vclDpbDelayOffset.resize(bp.m_bpMaxSubLayers, 0);
-    for (int i = (bp.m_sublayerInitialCpbRemovalDelayPresentFlag ? 0 : bp.m_bpMaxSubLayers - 1);
-         i <= bp.m_bpMaxSubLayers - 1; ++i)
+    sei.m_vclCpbAltInitialRemovalDelayDelta.resize(bp.maxSublayers);
+    sei.m_vclCpbAltInitialRemovalOffsetDelta.resize(bp.maxSublayers);
+    sei.m_vclCpbDelayOffset.resize(bp.maxSublayers, 0);
+    sei.m_vclDpbDelayOffset.resize(bp.maxSublayers, 0);
+    for (int i = (bp.hasSublayerInitialCpbRemovalDelay ? 0 : bp.maxSublayers - 1); i < bp.maxSublayers; ++i)
     {
-      sei.m_vclCpbAltInitialRemovalDelayDelta[i].resize(bp.m_bpCpbCnt, 0);
-      sei.m_vclCpbAltInitialRemovalOffsetDelta[i].resize(bp.m_bpCpbCnt, 0);
+      sei.m_vclCpbAltInitialRemovalDelayDelta[i].resize(bp.cpbCount, 0);
+      sei.m_vclCpbAltInitialRemovalOffsetDelta[i].resize(bp.cpbCount, 0);
     }
   }
 
-  if ( bp.m_bpDecodingUnitHrdParamsPresentFlag && bp.m_decodingUnitDpbDuParamsInPicTimingSeiFlag )
+  if (bp.hasDuHrdParams && bp.duDpbParamsInPicTimingSei)
   {
-    sei_read_code( pDecodedMessageOutputStream, bp.getDpbOutputDelayDuLength(), symbol, "pic_dpb_output_du_delay" );
+    sei_read_code(pDecodedMessageOutputStream, bp.dpbOutputDelayDuLength, symbol, "pic_dpb_output_du_delay");
     sei.m_picDpbOutputDuDelay = symbol;
   }
-  if( bp.m_bpDecodingUnitHrdParamsPresentFlag && bp.m_decodingUnitCpbParamsInPicTimingSeiFlag )
+  if (bp.hasDuHrdParams && bp.duCpbParamsInPicTimingSei)
   {
     sei_read_uvlc( pDecodedMessageOutputStream, symbol, "num_decoding_units_minus1" );
     sei.m_numDecodingUnitsMinus1 = symbol;
     sei.m_numNalusInDuMinus1.resize(sei.m_numDecodingUnitsMinus1 + 1 );
-    sei.m_duCpbRemovalDelayMinus1.resize( (sei.m_numDecodingUnitsMinus1 + 1) * bp.m_bpMaxSubLayers );
+    sei.m_duCpbRemovalDelayMinus1.resize((sei.m_numDecodingUnitsMinus1 + 1) * bp.maxSublayers);
 
     if (sei.m_numDecodingUnitsMinus1 > 0)
     {
@@ -1815,11 +1845,12 @@ void SEIReader::xParseSEIPictureTiming(SEIPictureTiming& sei, uint32_t payloadSi
       sei.m_duCommonCpbRemovalDelayFlag = symbol;
       if( sei.m_duCommonCpbRemovalDelayFlag )
       {
-        for( int i = temporalId; i <= bp.m_bpMaxSubLayers - 1; i ++ )
+        for (int i = temporalId; i < bp.maxSublayers; i++)
         {
           if( sei.m_ptSubLayerDelaysPresentFlag[i] )
           {
-            sei_read_code( pDecodedMessageOutputStream, bp.getDuCpbRemovalDelayIncrementLength(), symbol, "du_common_cpb_removal_delay_increment_minus1[i]" );
+            sei_read_code(pDecodedMessageOutputStream, bp.duCpbRemovalDelayIncrementLength, symbol,
+                          "du_common_cpb_removal_delay_increment_minus1[i]");
             sei.m_duCommonCpbRemovalDelayMinus1[i] = symbol;
           }
         }
@@ -1830,12 +1861,13 @@ void SEIReader::xParseSEIPictureTiming(SEIPictureTiming& sei, uint32_t payloadSi
         sei.m_numNalusInDuMinus1[i] = symbol;
         if( !sei.m_duCommonCpbRemovalDelayFlag && i < sei.m_numDecodingUnitsMinus1 )
         {
-          for( int j = temporalId; j <= bp.m_bpMaxSubLayers - 1; j ++ )
+          for (int j = temporalId; j < bp.maxSublayers; j++)
           {
             if( sei.m_ptSubLayerDelaysPresentFlag[j] )
             {
-              sei_read_code( pDecodedMessageOutputStream, bp.getDuCpbRemovalDelayIncrementLength(), symbol, "du_cpb_removal_delay_increment_minus1[i][j]" );
-              sei.m_duCpbRemovalDelayMinus1[i * bp.m_bpMaxSubLayers + j] = symbol;
+              sei_read_code(pDecodedMessageOutputStream, bp.duCpbRemovalDelayIncrementLength, symbol,
+                            "du_cpb_removal_delay_increment_minus1[i][j]");
+              sei.m_duCpbRemovalDelayMinus1[i * bp.maxSublayers + j] = symbol;
             }
           }
         }
diff --git a/source/Lib/DecoderLib/SEIread.h b/source/Lib/DecoderLib/SEIread.h
index 06e47e91d..f76514420 100644
--- a/source/Lib/DecoderLib/SEIread.h
+++ b/source/Lib/DecoderLib/SEIread.h
@@ -70,7 +70,8 @@ protected:
   void xParseSEIuserDataUnregistered          (SEIuserDataUnregistered &sei,          uint32_t payloadSize,                     std::ostream *pDecodedMessageOutputStream);
   void xParseSEIDecodingUnitInfo              (SEIDecodingUnitInfo& sei,              uint32_t payloadSize, const SEIBufferingPeriod& bp, const uint32_t temporalId, std::ostream *pDecodedMessageOutputStream);
   void xParseSEIDecodedPictureHash            (SEIDecodedPictureHash& sei,            uint32_t payloadSize,                     std::ostream *pDecodedMessageOutputStream);
-  void xParseSEIBufferingPeriod               (SEIBufferingPeriod& sei,               uint32_t payloadSize, std::ostream *pDecodedMessageOutputStream);
+  void xParseSEIBufferingPeriod(SEIBufferingPeriod& bp, uint32_t payloadSize,
+                                std::ostream* pDecodedMessageOutputStream);
   void xParseSEIPictureTiming                 (SEIPictureTiming& sei,                 uint32_t payloadSize, const uint32_t temporalId, const SEIBufferingPeriod& bp, std::ostream *pDecodedMessageOutputStream);
   void xParseSEIScalableNesting               (SEIScalableNesting& sei, const NalUnitType nalUnitType, const uint32_t nuhLayerId, uint32_t payloadSize, const VPS* vps, const SPS* sps, HRD &hrd, std::ostream* decodedMessageOutputStream);
   void xParseSEIScalableNestingBinary(SEIScalableNesting &sei, const NalUnitType nalUnitType, const uint32_t nuhLayerId,
diff --git a/source/Lib/EncoderLib/EncGOP.cpp b/source/Lib/EncoderLib/EncGOP.cpp
index cca9ce1d1..eae71dc0b 100644
--- a/source/Lib/EncoderLib/EncGOP.cpp
+++ b/source/Lib/EncoderLib/EncGOP.cpp
@@ -679,7 +679,7 @@ void EncGOP::xWriteTrailingSEIMessages (SEIMessages& seiMessages, AccessUnit &ac
 
 void EncGOP::xWriteDuSEIMessages (SEIMessages& duInfoSeiMessages, AccessUnit &accessUnit, int temporalId, std::deque<DUData> &duData)
 {
-  if( m_pcCfg->getDecodingUnitInfoSEIEnabled() && m_HRD->getBufferingPeriodSEI()->m_decodingUnitCpbParamsInPicTimingSeiFlag )
+  if (m_pcCfg->getDecodingUnitInfoSEIEnabled() && m_HRD->getBufferingPeriodSEI()->duCpbParamsInPicTimingSei)
   {
     int naluIdx = 0;
     AccessUnit::iterator nalu = accessUnit.begin();
@@ -945,7 +945,7 @@ void EncGOP::xCreatePerPictureSEIMessages (int picInGOP, SEIMessages& seiMessage
     slice->getNalUnitLayerId()==slice->getVPS()->getLayerId(0) &&
   (slice->getSPS()->getGeneralHrdParametersPresentFlag()))
   {
-    SEIBufferingPeriod *bufferingPeriodSEI = new SEIBufferingPeriod();
+    auto                bufferingPeriodSEI = new SEIBufferingPeriod;
     const bool          noLeadingPictures =
       slice->getNalUnitType() != NAL_UNIT_CODED_SLICE_IDR_W_RADL && slice->getNalUnitType() != NAL_UNIT_CODED_SLICE_CRA;
     m_seiEncoder.initSEIBufferingPeriod(bufferingPeriodSEI,noLeadingPictures);
@@ -955,7 +955,7 @@ void EncGOP::xCreatePerPictureSEIMessages (int picInGOP, SEIMessages& seiMessage
 
     if (m_pcCfg->getScalableNestingSEIEnabled())
     {
-      SEIBufferingPeriod *bufferingPeriodSEIcopy = new SEIBufferingPeriod();
+      auto bufferingPeriodSEIcopy = new SEIBufferingPeriod;
       bufferingPeriodSEI->copyTo(*bufferingPeriodSEIcopy);
       nestedSeiMessages.push_back(bufferingPeriodSEIcopy);
     }
@@ -1126,7 +1126,7 @@ void EncGOP::xCreatePictureTimingSEI(int irapGopId, SEIMessages &seiMessages, SE
       const uint32_t maxNumSubLayers = slice->getSPS()->getMaxTLayers();
       pictureTimingSEI->m_duCpbRemovalDelayMinus1.resize( numDU * maxNumSubLayers );
     }
-    const uint32_t cpbRemovalDelayLegth = m_HRD->getBufferingPeriodSEI()->m_cpbRemovalDelayLength;
+    const uint32_t cpbRemovalDelayLegth = m_HRD->getBufferingPeriodSEI()->cpbRemovalDelayLength;
     const uint32_t maxNumSubLayers = slice->getSPS()->getMaxTLayers();
     pictureTimingSEI->m_auCpbRemovalDelay[maxNumSubLayers-1] = std::min<int>(std::max<int>(1, m_totalCoded[maxNumSubLayers-1] - m_lastBPSEI[maxNumSubLayers-1]), static_cast<int>(pow(2, static_cast<double>(cpbRemovalDelayLegth)))); // Syntax element signalled as minus, hence the .
     CHECK( (m_totalCoded[maxNumSubLayers-1] - m_lastBPSEI[maxNumSubLayers-1]) > pow(2, static_cast<double>(cpbRemovalDelayLegth)), " cpbRemovalDelayLegth too small for m_auCpbRemovalDelay[pt_max_sub_layers_minus1] at picture timing SEI " );
@@ -1145,7 +1145,8 @@ void EncGOP::xCreatePictureTimingSEI(int irapGopId, SEIMessages &seiMessages, SE
       }
       else
       {
-        pictureTimingSEI->m_cpbRemovalDelayDeltaEnabledFlag[i] = m_HRD->getBufferingPeriodSEI()->m_cpbRemovalDelayDeltasPresentFlag;
+        pictureTimingSEI->m_cpbRemovalDelayDeltaEnabledFlag[i] =
+          m_HRD->getBufferingPeriodSEI()->hasCpbRemovalDelayDeltas();
       }
       if( pictureTimingSEI->m_cpbRemovalDelayDeltaEnabledFlag[i] )
       {
@@ -1473,7 +1474,7 @@ void EncGOP::xUpdateTimingSEI(SEIPictureTiming *pictureTimingSEI, std::deque<DUD
   }
 }
 
-void EncGOP::xUpdateDuInfoSEI(SEIMessages &duInfoSeiMessages, SEIPictureTiming *pictureTimingSEI, int maxSubLayers)
+void EncGOP::xUpdateDuInfoSEI(SEIMessages& duInfoSeiMessages, SEIPictureTiming* pictureTimingSEI, int maxSublayers)
 {
   if (duInfoSeiMessages.empty() || (pictureTimingSEI == nullptr))
   {
@@ -1486,10 +1487,11 @@ void EncGOP::xUpdateDuInfoSEI(SEIMessages &duInfoSeiMessages, SEIPictureTiming *
   {
     SEIDecodingUnitInfo *duInfoSEI = (SEIDecodingUnitInfo*) (*du);
     duInfoSEI->m_decodingUnitIdx = i;
-    for ( int j = 0; j < maxSubLayers; j++ )
+    for (int j = 0; j < maxSublayers; j++)
     {
       duInfoSEI->m_duiSubLayerDelaysPresentFlag[j] = pictureTimingSEI->m_ptSubLayerDelaysPresentFlag[j];
-      duInfoSEI->m_duSptCpbRemovalDelayIncrement[j] = pictureTimingSEI->m_duCpbRemovalDelayMinus1[i*maxSubLayers+j] + 1;
+      duInfoSEI->m_duSptCpbRemovalDelayIncrement[j] =
+        pictureTimingSEI->m_duCpbRemovalDelayMinus1[i * maxSublayers + j] + 1;
     }
     duInfoSEI->m_dpbOutputDuDelayPresentFlag = false;
     i++;
diff --git a/source/Lib/EncoderLib/EncGOP.h b/source/Lib/EncoderLib/EncGOP.h
index 5640b63b5..39f4b9975 100644
--- a/source/Lib/EncoderLib/EncGOP.h
+++ b/source/Lib/EncoderLib/EncGOP.h
@@ -354,7 +354,7 @@ protected:
                                SEIMessages &duInfoSeiMessages, Slice *slice, bool isField, std::deque<DUData> &duData);
   void xUpdateDuData(AccessUnit &testAU, std::deque<DUData> &duData);
   void xUpdateTimingSEI(SEIPictureTiming *pictureTimingSEI, std::deque<DUData> &duData, const SPS *sps);
-  void xUpdateDuInfoSEI(SEIMessages &duInfoSeiMessages, SEIPictureTiming *pictureTimingSEI, int maxSubLayers);
+  void xUpdateDuInfoSEI(SEIMessages& duInfoSeiMessages, SEIPictureTiming* pictureTimingSEI, int maxSublayers);
   void xCreateScalableNestingSEI(SEIMessages& seiMessages, SEIMessages& nestedSeiMessages, const std::vector<int> &targetOLSs, const std::vector<int> &targetLayers, const std::vector<uint16_t>& subpicIDs, uint16_t maxSubpicIdInPic);
   void xWriteSEI (NalUnitType naluType, SEIMessages& seiMessages, AccessUnit &accessUnit, AccessUnit::iterator &auPos, int temporalId);
   void xWriteSEISeparately (NalUnitType naluType, SEIMessages& seiMessages, AccessUnit &accessUnit, AccessUnit::iterator &auPos, int temporalId);
diff --git a/source/Lib/EncoderLib/SEIEncoder.cpp b/source/Lib/EncoderLib/SEIEncoder.cpp
index c24b1ca33..843ef0bae 100644
--- a/source/Lib/EncoderLib/SEIEncoder.cpp
+++ b/source/Lib/EncoderLib/SEIEncoder.cpp
@@ -80,36 +80,37 @@ void SEIEncoder::initSEIParameterSetsInclusionIndication(SEIParameterSetsInclusi
   seiParameterSetsInclusionIndication->m_selfContainedClvsFlag = m_pcCfg->getSelfContainedClvsFlag();
 }
 
-void SEIEncoder::initSEIBufferingPeriod(SEIBufferingPeriod *bufferingPeriodSEI, bool noLeadingPictures)
+void SEIEncoder::initSEIBufferingPeriod(SEIBufferingPeriod* bp, bool noLeadingPictures)
 {
   CHECK(!(m_isInitialized), "bufferingPeriodSEI already initialized");
-  CHECK(!(bufferingPeriodSEI != nullptr), "Need a bufferingPeriodSEI for initialization (got nullptr)");
-
-  uint32_t uiInitialCpbRemovalDelay = (90000/2);                      // 0.5 sec
-  bufferingPeriodSEI->m_bpNalCpbParamsPresentFlag = true;
-  bufferingPeriodSEI->m_bpVclCpbParamsPresentFlag = true;
-  bufferingPeriodSEI->m_bpMaxSubLayers = m_pcCfg->getMaxTempLayer() ;
-  bufferingPeriodSEI->m_bpCpbCnt = 1;
-  for(int i=0; i < bufferingPeriodSEI->m_bpMaxSubLayers; i++)
+  CHECK(bp == nullptr, "Need a bufferingPeriodSEI for initialization (got nullptr)");
+
+  const uint32_t initialCpbRemovalDelay = (90000 / 2);   // 0.5 sec
+  bp->maxSublayers                      = m_pcCfg->getMaxTempLayer();
+  bp->cpbCount                          = 1;
+
+  for (auto hrdType: { HrdType::NAL, HrdType::VCL })
   {
-    for(int j=0; j < bufferingPeriodSEI->m_bpCpbCnt; j++)
+    bp->hasHrdParams[hrdType] = true;
+    for (int sublayerIdx = 0; sublayerIdx < bp->maxSublayers; sublayerIdx++)
     {
-      bufferingPeriodSEI->m_initialCpbRemovalDelay[i][j][0] = uiInitialCpbRemovalDelay;
-      bufferingPeriodSEI->m_initialCpbRemovalDelay[i][j][1] = uiInitialCpbRemovalDelay;
-      bufferingPeriodSEI->m_initialCpbRemovalOffset[i][j][0] = uiInitialCpbRemovalDelay;
-      bufferingPeriodSEI->m_initialCpbRemovalOffset[i][j][1] = uiInitialCpbRemovalDelay;
+      for (int j = 0; j < bp->cpbCount; j++)
+      {
+        bp->initialCpbRemoval[hrdType][sublayerIdx][j] = { initialCpbRemovalDelay, initialCpbRemovalDelay };
+      }
     }
   }
+
   // We don't set concatenation_flag here. max_initial_removal_delay_for_concatenation depends on the usage scenario.
   // The parameters could be added to config file, but as long as the initialisation of generic buffering parameters is
   // not controllable, it does not seem to make sense to provide settings for these.
-  bufferingPeriodSEI->m_concatenationFlag = false;
-  bufferingPeriodSEI->m_maxInitialRemovalDelayForConcatenation = uiInitialCpbRemovalDelay;
+  bp->concatenation                          = false;
+  bp->maxInitialRemovalDelayForConcatenation = initialCpbRemovalDelay;
 
-  bufferingPeriodSEI->m_bpDecodingUnitHrdParamsPresentFlag = m_pcCfg->getNoPicPartitionFlag() == false;
-  bufferingPeriodSEI->m_decodingUnitCpbParamsInPicTimingSeiFlag = !m_pcCfg->getDecodingUnitInfoSEIEnabled();
+  bp->hasDuHrdParams            = m_pcCfg->getNoPicPartitionFlag() == false;
+  bp->duCpbParamsInPicTimingSei = !m_pcCfg->getDecodingUnitInfoSEIEnabled();
 
-  bufferingPeriodSEI->m_initialCpbRemovalDelayLength = 16;                  // assuming 0.5 sec, log2( 90,000 * 0.5 ) = 16-bit
+  bp->cpbInitialRemovalDelayLength = 16;   // assuming 0.5 sec, log2( 90,000 * 0.5 ) = 16-bit
   // Note: The following parameters require some knowledge about the GOP structure.
   //       Using getIntraPeriod() should be avoided though, because it assumes certain GOP
   //       properties, which are only valid in CTC.
@@ -117,98 +118,71 @@ void SEIEncoder::initSEIBufferingPeriod(SEIBufferingPeriod *bufferingPeriodSEI,
   bool isRandomAccess  = m_pcCfg->getIntraPeriod() > 0;
   if( isRandomAccess )
   {
-    bufferingPeriodSEI->m_cpbRemovalDelayLength = 6;                        // 32 = 2^5 (plus 1)
-    bufferingPeriodSEI->m_dpbOutputDelayLength =  6;                        // 32 + 3 = 2^6
+    bp->cpbRemovalDelayLength = 6;   // 32 = 2^5 (plus 1)
+    bp->dpbOutputDelayLength  = 6;   // 32 + 3 = 2^6
   }
   else
   {
-    bufferingPeriodSEI->m_cpbRemovalDelayLength = 9;                        // max. 2^10
-    bufferingPeriodSEI->m_dpbOutputDelayLength =  9;                        // max. 2^10
+    bp->cpbRemovalDelayLength = 9;   // max. 2^10
+    bp->dpbOutputDelayLength  = 9;   // max. 2^10
   }
-  bufferingPeriodSEI->m_duCpbRemovalDelayIncrementLength = 7;               // ceil( log2( tick_divisor_minus2 + 2 ) )
-  bufferingPeriodSEI->m_dpbOutputDelayDuLength = bufferingPeriodSEI->m_dpbOutputDelayLength + bufferingPeriodSEI->m_duCpbRemovalDelayIncrementLength;
+  bp->duCpbRemovalDelayIncrementLength = 7;   // ceil( log2( tick_divisor_minus2 + 2 ) )
+  bp->dpbOutputDelayDuLength           = bp->dpbOutputDelayLength + bp->duCpbRemovalDelayIncrementLength;
   //for the concatenation, it can be set to one during splicing.
-  bufferingPeriodSEI->m_concatenationFlag = 0;
+  bp->concatenation                    = 0;
   //since the temporal layer HRDParameters is not ready, we assumed it is fixed
-  bufferingPeriodSEI->m_auCpbRemovalDelayDelta = 1;
-  bufferingPeriodSEI->m_cpbRemovalDelayDeltasPresentFlag = m_pcCfg->getBpDeltasGOPStructure() ;
-  if (bufferingPeriodSEI->m_cpbRemovalDelayDeltasPresentFlag)
+  bp->cpbRemovalDelayDelta             = 1;
+
+  if (m_pcCfg->getBpDeltasGOPStructure())
   {
     switch (m_pcCfg->getGOPSize())
     {
-      case 8:
+    case 8:
+      if (noLeadingPictures)
       {
-        if (noLeadingPictures)
-        {
-          bufferingPeriodSEI->m_numCpbRemovalDelayDeltas         = 5;
-          bufferingPeriodSEI->m_cpbRemovalDelayDelta[0]          = 1;
-          bufferingPeriodSEI->m_cpbRemovalDelayDelta[1]          = 2;
-          bufferingPeriodSEI->m_cpbRemovalDelayDelta[2]          = 3;
-          bufferingPeriodSEI->m_cpbRemovalDelayDelta[3]          = 6;
-          bufferingPeriodSEI->m_cpbRemovalDelayDelta[4]          = 7;
-        }
-        else
-        {
-          bufferingPeriodSEI->m_numCpbRemovalDelayDeltas         = 3;
-          bufferingPeriodSEI->m_cpbRemovalDelayDelta[0]          = 1;
-          bufferingPeriodSEI->m_cpbRemovalDelayDelta[1]          = 2;
-          bufferingPeriodSEI->m_cpbRemovalDelayDelta[2]          = 3;
-        }
+        bp->cpbRemovalDelayDeltaVals = { 1, 2, 3, 6, 7 };
       }
-        break;
-      case 16:
+      else
       {
-        if (noLeadingPictures)
-        {
-          bufferingPeriodSEI->m_numCpbRemovalDelayDeltas         = 9;
-          bufferingPeriodSEI->m_cpbRemovalDelayDelta[0]          = 1;
-          bufferingPeriodSEI->m_cpbRemovalDelayDelta[1]          = 2;
-          bufferingPeriodSEI->m_cpbRemovalDelayDelta[2]          = 3;
-          bufferingPeriodSEI->m_cpbRemovalDelayDelta[3]          = 4;
-          bufferingPeriodSEI->m_cpbRemovalDelayDelta[4]          = 6;
-          bufferingPeriodSEI->m_cpbRemovalDelayDelta[5]          = 7;
-          bufferingPeriodSEI->m_cpbRemovalDelayDelta[6]          = 9;
-          bufferingPeriodSEI->m_cpbRemovalDelayDelta[7]          = 14;
-          bufferingPeriodSEI->m_cpbRemovalDelayDelta[8]          = 15;
-        }
-        else
-        {
-          bufferingPeriodSEI->m_numCpbRemovalDelayDeltas         = 5;
-          bufferingPeriodSEI->m_cpbRemovalDelayDelta[0]          = 1;
-          bufferingPeriodSEI->m_cpbRemovalDelayDelta[1]          = 2;
-          bufferingPeriodSEI->m_cpbRemovalDelayDelta[2]          = 3;
-          bufferingPeriodSEI->m_cpbRemovalDelayDelta[3]          = 6;
-          bufferingPeriodSEI->m_cpbRemovalDelayDelta[4]          = 7;
-        }
+        bp->cpbRemovalDelayDeltaVals = { 1, 2, 3 };
       }
-        break;
-      default:
+      break;
+    case 16:
+      if (noLeadingPictures)
       {
-        THROW("m_cpbRemovalDelayDelta not applicable for the GOP size");
+        bp->cpbRemovalDelayDeltaVals = { 1, 2, 3, 4, 6, 7, 9, 14, 15 };
       }
-        break;
+      else
+      {
+        bp->cpbRemovalDelayDeltaVals = { 1, 2, 3, 6, 7 };
+      }
+      break;
+    default:
+      THROW("cpbRemovalDelayDelta not applicable for the GOP size");
+      break;
     }
   }
-  bufferingPeriodSEI->m_sublayerDpbOutputOffsetsPresentFlag = true;
-  for(int i = 0; i < bufferingPeriodSEI->m_bpMaxSubLayers; i++)
+  else
   {
-    bufferingPeriodSEI->m_dpbOutputTidOffset[i] = m_pcCfg->getMaxNumReorderPics(i) * static_cast<int>(pow(2, static_cast<double>(bufferingPeriodSEI->m_bpMaxSubLayers-1-i)));
-    if(bufferingPeriodSEI->m_dpbOutputTidOffset[i] >= m_pcCfg->getMaxNumReorderPics(bufferingPeriodSEI->m_bpMaxSubLayers-1))
-    {
-      bufferingPeriodSEI->m_dpbOutputTidOffset[i] -= m_pcCfg->getMaxNumReorderPics(bufferingPeriodSEI->m_bpMaxSubLayers-1);
-    }
-    else
-    {
-      bufferingPeriodSEI->m_dpbOutputTidOffset[i] = 0;
-    }
+    bp->cpbRemovalDelayDeltaVals.clear();
+  }
+
+  bp->hasSublayerDpbOutputOffsets = true;
+  const uint32_t lastSublayer     = bp->maxSublayers - 1;
+  for (int sublayerIdx = 0; sublayerIdx <= lastSublayer; sublayerIdx++)
+  {
+    bp->dpbOutputTidOffset[sublayerIdx] =
+      std::max<int>(m_pcCfg->getMaxNumReorderPics(sublayerIdx) * (1 << (lastSublayer - sublayerIdx))
+                      - m_pcCfg->getMaxNumReorderPics(lastSublayer),
+                    0);
   }
   // 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.
   // Unfortunately VTM does not have such tracking. Thus we cannot encode alternative
   // CPB parameters here.
-  bufferingPeriodSEI->m_altCpbParamsPresentFlag = false;
-  bufferingPeriodSEI->m_useAltCpbParamsFlag = false;
+  bp->hasAltCpbParams = false;
+  bp->useAltCpbParams = false;
 }
 
 void SEIEncoder::initSEIErp(SEIEquirectangularProjection* seiEquirectangularProjection)
diff --git a/source/Lib/EncoderLib/SEIwrite.cpp b/source/Lib/EncoderLib/SEIwrite.cpp
index fe3900407..5d575a854 100644
--- a/source/Lib/EncoderLib/SEIwrite.cpp
+++ b/source/Lib/EncoderLib/SEIwrite.cpp
@@ -321,192 +321,202 @@ void SEIWriter::xWriteSEIDecodedPictureHash(const SEIDecodedPictureHash& sei)
 void SEIWriter::xWriteSEIDecodingUnitInfo(const SEIDecodingUnitInfo& sei, const SEIBufferingPeriod& bp, const uint32_t temporalId)
 {
   xWriteUvlc(sei.m_decodingUnitIdx, "decoding_unit_idx");
-  if( !bp.m_decodingUnitCpbParamsInPicTimingSeiFlag )
+  if (!bp.duCpbParamsInPicTimingSei)
   {
-    for (int i = temporalId; i <= bp.m_bpMaxSubLayers - 1; i++)
+    for (int i = temporalId; i < bp.maxSublayers; i++)
     {
-      if (i < bp.m_bpMaxSubLayers - 1)
+      if (i < bp.maxSublayers - 1)
       {
         xWriteFlag(sei.m_duiSubLayerDelaysPresentFlag[i], "dui_sub_layer_delays_present_flag[i]");
       }
       if( sei.m_duiSubLayerDelaysPresentFlag[i] )
       {
-        xWriteCode( sei.m_duSptCpbRemovalDelayIncrement[i], bp.getDuCpbRemovalDelayIncrementLength(), "du_spt_cpb_removal_delay_increment[i]");
+        xWriteCode(sei.m_duSptCpbRemovalDelayIncrement[i], bp.duCpbRemovalDelayIncrementLength,
+                   "du_spt_cpb_removal_delay_increment[i]");
       }
     }
   }
-  if (!bp.m_decodingUnitDpbDuParamsInPicTimingSeiFlag)
+  if (!bp.duDpbParamsInPicTimingSei)
   {
     xWriteFlag(sei.m_dpbOutputDuDelayPresentFlag, "dpb_output_du_delay_present_flag");
   }
 
   if(sei.m_dpbOutputDuDelayPresentFlag)
   {
-    xWriteCode(sei.m_picSptDpbOutputDuDelay, bp.getDpbOutputDelayDuLength(), "pic_spt_dpb_output_du_delay");
+    xWriteCode(sei.m_picSptDpbOutputDuDelay, bp.dpbOutputDelayDuLength, "pic_spt_dpb_output_du_delay");
   }
 }
 
 void SEIWriter::xWriteSEIBufferingPeriod(const SEIBufferingPeriod& sei)
 {
-  xWriteFlag( sei.m_bpNalCpbParamsPresentFlag, "bp_nal_hrd_parameters_present_flag");
-  xWriteFlag( sei.m_bpVclCpbParamsPresentFlag, "bp_vcl_hrd_parameters_present_flag");
-  CHECK(!sei.m_bpNalCpbParamsPresentFlag && !sei.m_bpVclCpbParamsPresentFlag, "bp_nal_hrd_parameters_present_flag and/or bp_vcl_hrd_parameters_present_flag must be true");
-  CHECK (sei.m_initialCpbRemovalDelayLength < 1, "sei.m_initialCpbRemovalDelayLength must be > 0");
-  xWriteCode( sei.m_initialCpbRemovalDelayLength - 1, 5, "initial_cpb_removal_delay_length_minus1" );
-  CHECK (sei.m_cpbRemovalDelayLength < 1, "sei.m_cpbRemovalDelayLength must be > 0");
-  xWriteCode( sei.m_cpbRemovalDelayLength - 1,        5, "cpb_removal_delay_length_minus1" );
-  CHECK (sei.m_dpbOutputDelayLength < 1, "sei.m_dpbOutputDelayLength must be > 0");
-  xWriteCode( sei.m_dpbOutputDelayLength - 1,         5, "dpb_output_delay_length_minus1" );
-  xWriteFlag( sei.m_bpDecodingUnitHrdParamsPresentFlag, "bp_decoding_unit_hrd_params_present_flag"  );
-  if( sei.m_bpDecodingUnitHrdParamsPresentFlag )
+  CHECK(!sei.hasHrdParams[HrdType::NAL] && !sei.hasHrdParams[HrdType::VCL],
+        "at least one of bp_nal_hrd_params_present_flag and bp_vcl_hrd_params_present_flag must be true");
+  xWriteFlag(sei.hasHrdParams[HrdType::NAL], "bp_nal_hrd_params_present_flag");
+  xWriteFlag(sei.hasHrdParams[HrdType::VCL], "bp_vcl_hrd_params_present_flag");
+
+  CHECK(sei.cpbInitialRemovalDelayLength < 1, "sei.cpbInitialRemovalDelayLength must be > 0");
+  xWriteCode(sei.cpbInitialRemovalDelayLength - 1, 5, "bp_cpb_initial_removal_delay_length_minus1");
+
+  CHECK(sei.cpbRemovalDelayLength < 1, "sei.cpbRemovalDelayLength must be > 0");
+  xWriteCode(sei.cpbRemovalDelayLength - 1, 5, "bp_cpb_removal_delay_length_minus1");
+
+  CHECK(sei.dpbOutputDelayLength < 1, "sei.dpbOutputDelayLength must be > 0");
+  xWriteCode(sei.dpbOutputDelayLength - 1, 5, "bp_dpb_output_delay_length_minus1");
+
+  xWriteFlag(sei.hasDuHrdParams, "bp_du_hrd_params_present_flag");
+  if (sei.hasDuHrdParams)
   {
-    CHECK (sei.m_duCpbRemovalDelayIncrementLength < 1, "sei.m_duCpbRemovalDelayIncrementLength must be > 0");
-    xWriteCode( sei.m_duCpbRemovalDelayIncrementLength - 1, 5, "du_cpb_removal_delay_increment_length_minus1" );
-    CHECK (sei.m_dpbOutputDelayDuLength < 1, "sei.m_dpbOutputDelayDuLength must be > 0");
-    xWriteCode( sei.m_dpbOutputDelayDuLength - 1, 5, "dpb_output_delay_du_length_minus1" );
-    xWriteFlag( sei.m_decodingUnitCpbParamsInPicTimingSeiFlag, "decoding_unit_cpb_params_in_pic_timing_sei_flag" );
-    xWriteFlag(sei.m_decodingUnitDpbDuParamsInPicTimingSeiFlag, "decoding_unit_dpb_du_params_in_pic_timing_sei_flag");
+    CHECK(sei.duCpbRemovalDelayIncrementLength < 1, "sei.duCpbRemovalDelayIncrementLength must be > 0");
+    xWriteCode(sei.duCpbRemovalDelayIncrementLength - 1, 5, "bp_du_cpb_removal_delay_increment_length_minus1");
+
+    CHECK(sei.dpbOutputDelayDuLength < 1, "sei.dpbOutputDelayDuLength must be > 0");
+    xWriteCode(sei.dpbOutputDelayDuLength - 1, 5, "bp_dpb_output_delay_du_length_minus1");
+
+    xWriteFlag(sei.duCpbParamsInPicTimingSei, "bp_du_cpb_params_in_pic_timing_sei_flag");
+    xWriteFlag(sei.duDpbParamsInPicTimingSei, "bp_du_dpb_params_in_pic_timing_sei_flag");
   }
 
-  xWriteFlag( sei.m_concatenationFlag, "concatenation_flag");
-  xWriteFlag( sei.m_additionalConcatenationInfoPresentFlag, "additional_concatenation_info_present_flag");
-  if (sei.m_additionalConcatenationInfoPresentFlag)
+  xWriteFlag(sei.concatenation, "bp_concatenation_flag");
+  xWriteFlag(sei.hasAdditionalConcatenationInfo, "bp_additional_concatenation_info_present_flag");
+  if (sei.hasAdditionalConcatenationInfo)
   {
-    xWriteCode( sei.m_maxInitialRemovalDelayForConcatenation, sei.m_initialCpbRemovalDelayLength, "max_initial_removal_delay_for_concatenation" );
+    xWriteCode(sei.maxInitialRemovalDelayForConcatenation, sei.cpbInitialRemovalDelayLength,
+               "bp_max_initial_removal_delay_for_concatenation");
   }
 
-  CHECK (sei.m_auCpbRemovalDelayDelta < 1, "sei.m_auCpbRemovalDelayDelta must be > 0");
-  xWriteCode( sei.m_auCpbRemovalDelayDelta - 1, sei.m_cpbRemovalDelayLength, "au_cpb_removal_delay_delta_minus1" );
+  CHECK(sei.cpbRemovalDelayDelta < 1, "sei.cpbRemovalDelayDelta must be > 0");
+  xWriteCode(sei.cpbRemovalDelayDelta - 1, sei.cpbRemovalDelayLength, "bp_cpb_removal_delay_delta_minus1");
 
-  CHECK(sei.m_bpMaxSubLayers < 1, "bp_max_sub_layers_minus1 must be > 0");
-  xWriteCode(sei.m_bpMaxSubLayers - 1, 3, "bp_max_sub_layers_minus1");
-  if (sei.m_bpMaxSubLayers - 1 > 0)
+  CHECK(sei.maxSublayers < 1, "bp_max_sublayers must be > 0");
+  xWriteCode(sei.maxSublayers - 1, 3, "bp_max_sublayers_minus1");
+  if (sei.maxSublayers > 1)
   {
-    xWriteFlag(sei.m_cpbRemovalDelayDeltasPresentFlag, "cpb_removal_delay_deltas_present_flag");
+    xWriteFlag(sei.hasCpbRemovalDelayDeltas(), "bp_cpb_removal_delay_deltas_present_flag");
   }
 
-  if (sei.m_cpbRemovalDelayDeltasPresentFlag)
+  if (sei.hasCpbRemovalDelayDeltas())
   {
-    CHECK (sei.m_numCpbRemovalDelayDeltas < 1, "m_numCpbRemovalDelayDeltas must be > 0");
-    xWriteUvlc( sei.m_numCpbRemovalDelayDeltas - 1, "num_cpb_removal_delay_deltas_minus1" );
-    for( int i = 0; i < sei.m_numCpbRemovalDelayDeltas; i ++ )
+    xWriteUvlc(sei.numCpbRemovalDelayDeltas() - 1, "bp_num_cpb_removal_delay_deltas_minus1");
+    for (int i = 0; i < sei.numCpbRemovalDelayDeltas(); i++)
     {
-      xWriteCode( sei.m_cpbRemovalDelayDelta[i],        sei.m_cpbRemovalDelayLength, "cpb_removal_delay_delta[i]" );
+      xWriteCode(sei.cpbRemovalDelayDeltaVals[i], sei.cpbRemovalDelayLength, "bp_cpb_removal_delay_delta_val[i]");
     }
   }
-  CHECK (sei.m_bpCpbCnt < 1, "sei.m_bpCpbCnt must be > 0");
-  xWriteUvlc( sei.m_bpCpbCnt - 1, "bp_cpb_cnt_minus1");
-  if (sei.m_bpMaxSubLayers - 1 > 0)
+  CHECK(sei.cpbCount < 1, "sei.cpbCount must be > 0");
+  xWriteUvlc(sei.cpbCount - 1, "bp_cpb_cnt_minus1");
+  if (sei.maxSublayers - 1 > 0)
   {
-    xWriteFlag(sei.m_sublayerInitialCpbRemovalDelayPresentFlag, "bp_sublayer_initial_cpb_removal_delay_present_flag");
+    xWriteFlag(sei.hasSublayerInitialCpbRemovalDelay, "bp_sublayer_initial_cpb_removal_delay_present_flag");
   }
-  for (int i = (sei.m_sublayerInitialCpbRemovalDelayPresentFlag ? 0 : sei.m_bpMaxSubLayers - 1); i < sei.m_bpMaxSubLayers; i++)
+  for (int i = (sei.hasSublayerInitialCpbRemovalDelay ? 0 : sei.maxSublayers - 1); i < sei.maxSublayers; i++)
   {
-    for( int nalOrVcl = 0; nalOrVcl < 2; nalOrVcl ++ )
+    for (auto hrdType: { HrdType::NAL, HrdType::VCL })
     {
-      if( ( ( nalOrVcl == 0 ) && ( sei.m_bpNalCpbParamsPresentFlag ) ) ||
-         ( ( nalOrVcl == 1 ) && ( sei.m_bpVclCpbParamsPresentFlag ) ) )
+      if (sei.hasHrdParams[hrdType])
       {
-        for( int j = 0; j < sei.m_bpCpbCnt; j ++ )
+        for (int j = 0; j < sei.cpbCount; j++)
         {
-          xWriteCode( sei.m_initialCpbRemovalDelay[i][j][nalOrVcl],  sei.m_initialCpbRemovalDelayLength,           "initial_cpb_removal_delay[i][j][nalOrVcl]" );
-          xWriteCode( sei.m_initialCpbRemovalOffset[i][j][nalOrVcl], sei.m_initialCpbRemovalDelayLength,           "initial_cpb_removal_delay_offset[i][j][nalOrVcl]" );
+          xWriteCode(sei.initialCpbRemoval[hrdType][i][j].delay, sei.cpbInitialRemovalDelayLength,
+                     hrdType == HrdType::NAL ? "bp_nal_initial_cpb_removal_delay[i][j]"
+                                             : "bp_vcl_initial_cpb_removal_delay[i][j]");
+          xWriteCode(sei.initialCpbRemoval[hrdType][i][j].offset, sei.cpbInitialRemovalDelayLength,
+                     hrdType == HrdType::NAL ? "bp_nal_initial_cpb_removal_offset[i][j]"
+                                             : "bp_vcl_initial_cpb_removal_offset[i][j]");
         }
       }
     }
   }
-  if (sei.m_bpMaxSubLayers-1 > 0)
+  if (sei.maxSublayers - 1 > 0)
   {
-    xWriteFlag(sei.m_sublayerDpbOutputOffsetsPresentFlag, "bp_sublayer_dpb_output_offsets_present_flag");
+    xWriteFlag(sei.hasSublayerDpbOutputOffsets, "bp_sublayer_dpb_output_offsets_present_flag");
   }
 
-  if(sei.m_sublayerDpbOutputOffsetsPresentFlag)
+  if (sei.hasSublayerDpbOutputOffsets)
   {
-    for(int i = 0; i < sei.m_bpMaxSubLayers - 1; i++)
+    for (int i = 0; i < sei.maxSublayers - 1; i++)
     {
-      xWriteUvlc( sei.m_dpbOutputTidOffset[i], "dpb_output_tid_offset[i]" );
+      xWriteUvlc(sei.dpbOutputTidOffset[i], "bp_dpb_output_tid_offset[i]");
     }
   }
-  xWriteFlag(sei.m_altCpbParamsPresentFlag, "bp_alt_cpb_params_present_flag");
-  if (sei.m_altCpbParamsPresentFlag)
+  xWriteFlag(sei.hasAltCpbParams, "bp_alt_cpb_params_present_flag");
+  if (sei.hasAltCpbParams)
   {
-    xWriteFlag(sei.m_useAltCpbParamsFlag, "use_alt_cpb_params_flag");
+    xWriteFlag(sei.useAltCpbParams, "bp_use_alt_cpb_params_flag");
   }
-
 }
 
 void SEIWriter::xWriteSEIPictureTiming(const SEIPictureTiming& sei, const SEIBufferingPeriod &bp, const uint32_t temporalId)
 {
-
-  xWriteCode( sei.m_auCpbRemovalDelay[bp.m_bpMaxSubLayers - 1] - 1, bp.m_cpbRemovalDelayLength,               "pt_cpb_removal_delay_minus1[bp_max_sub_layers_minus1]" );
-  for (int i = temporalId; i < bp.m_bpMaxSubLayers - 1; i++)
+  xWriteCode(sei.m_auCpbRemovalDelay[bp.maxSublayers - 1] - 1, bp.cpbRemovalDelayLength,
+             "pt_cpb_removal_delay_minus1[bp_max_sub_layers_minus1]");
+  for (int i = temporalId; i < bp.maxSublayers - 1; i++)
   {
     xWriteFlag(sei.m_ptSubLayerDelaysPresentFlag[i], "pt_sublayer_delays_present_flag[i]");
     if (sei.m_ptSubLayerDelaysPresentFlag[i])
     {
-      if (bp.m_cpbRemovalDelayDeltasPresentFlag)
+      if (bp.hasCpbRemovalDelayDeltas())
       {
         xWriteFlag(sei.m_cpbRemovalDelayDeltaEnabledFlag[i], "pt_cpb_removal_delay_delta_enabled_flag[i]");
       }
       if (sei.m_cpbRemovalDelayDeltaEnabledFlag[i])
       {
-        if ((bp.m_numCpbRemovalDelayDeltas - 1) > 0)
+        if (bp.numCpbRemovalDelayDeltas() > 1)
         {
-          xWriteCode(sei.m_cpbRemovalDelayDeltaIdx[i], ceilLog2(bp.m_numCpbRemovalDelayDeltas), "pt_cpb_removal_delay_delta_idx[i]");
+          xWriteCode(sei.m_cpbRemovalDelayDeltaIdx[i], ceilLog2(bp.numCpbRemovalDelayDeltas()),
+                     "pt_cpb_removal_delay_delta_idx[i]");
         }
       }
       else
       {
-        xWriteCode(sei.m_auCpbRemovalDelay[i] - 1, bp.m_cpbRemovalDelayLength, "pt_cpb_removal_delay_minus1[i]");
+        xWriteCode(sei.m_auCpbRemovalDelay[i] - 1, bp.cpbRemovalDelayLength, "pt_cpb_removal_delay_minus1[i]");
       }
     }
   }
-  xWriteCode(sei.m_picDpbOutputDelay, bp.m_dpbOutputDelayLength, "pt_dpb_output_delay");
-  if( bp.m_altCpbParamsPresentFlag )
+  xWriteCode(sei.m_picDpbOutputDelay, bp.dpbOutputDelayLength, "pt_dpb_output_delay");
+  if (bp.hasAltCpbParams)
   {
     xWriteFlag( sei.m_cpbAltTimingInfoPresentFlag, "cpb_alt_timing_info_present_flag" );
     if( sei.m_cpbAltTimingInfoPresentFlag )
     {
-      if (bp.m_bpNalCpbParamsPresentFlag)
+      if (bp.hasHrdParams[HrdType::NAL])
       {
-        for (int i = (bp.m_sublayerInitialCpbRemovalDelayPresentFlag ? 0 : bp.m_bpMaxSubLayers - 1); i <= bp.m_bpMaxSubLayers - 1; ++i)
+        for (int i = (bp.hasSublayerInitialCpbRemovalDelay ? 0 : bp.maxSublayers - 1); i < bp.maxSublayers; ++i)
         {
-          for (int j = 0; j < bp.m_bpCpbCnt; j++)
+          for (int j = 0; j < bp.cpbCount; j++)
           {
-            xWriteCode(sei.m_nalCpbAltInitialRemovalDelayDelta[i][j], bp.m_initialCpbRemovalDelayLength,
+            xWriteCode(sei.m_nalCpbAltInitialRemovalDelayDelta[i][j], bp.cpbInitialRemovalDelayLength,
                        "nal_cpb_alt_initial_cpb_removal_delay_delta[ i ][ j ]");
-            xWriteCode(sei.m_nalCpbAltInitialRemovalOffsetDelta[i][j], bp.m_initialCpbRemovalDelayLength,
+            xWriteCode(sei.m_nalCpbAltInitialRemovalOffsetDelta[i][j], bp.cpbInitialRemovalDelayLength,
                        "nal_cpb_alt_initial_cpb_removal_offset_delta[ i ][ j ]");
           }
-          xWriteCode(sei.m_nalCpbDelayOffset[i], bp.m_cpbRemovalDelayLength, "nal_cpb_delay_offset[ i ]");
-          xWriteCode(sei.m_nalDpbDelayOffset[i], bp.m_dpbOutputDelayLength, "nal_dpb_delay_offset[ i ]");
+          xWriteCode(sei.m_nalCpbDelayOffset[i], bp.cpbRemovalDelayLength, "nal_cpb_delay_offset[ i ]");
+          xWriteCode(sei.m_nalDpbDelayOffset[i], bp.dpbOutputDelayLength, "nal_dpb_delay_offset[ i ]");
         }
       }
 
-      if (bp.m_bpVclCpbParamsPresentFlag)
+      if (bp.hasHrdParams[HrdType::VCL])
       {
-        for (int i = (bp.m_sublayerInitialCpbRemovalDelayPresentFlag ? 0 : bp.m_bpMaxSubLayers - 1);
-             i <= bp.m_bpMaxSubLayers - 1; ++i)
+        for (int i = (bp.hasSublayerInitialCpbRemovalDelay ? 0 : bp.maxSublayers - 1); i < bp.maxSublayers; ++i)
         {
-          for (int j = 0; j < bp.m_bpCpbCnt; j++)
+          for (int j = 0; j < bp.cpbCount; j++)
           {
-            xWriteCode(sei.m_vclCpbAltInitialRemovalDelayDelta[i][j], bp.m_initialCpbRemovalDelayLength,
+            xWriteCode(sei.m_vclCpbAltInitialRemovalDelayDelta[i][j], bp.cpbInitialRemovalDelayLength,
                        "vcl_cpb_alt_initial_cpb_removal_delay_delta[ i ][ j ]");
-            xWriteCode(sei.m_vclCpbAltInitialRemovalOffsetDelta[i][j], bp.m_initialCpbRemovalDelayLength,
+            xWriteCode(sei.m_vclCpbAltInitialRemovalOffsetDelta[i][j], bp.cpbInitialRemovalDelayLength,
                        "vcl_cpb_alt_initial_cpb_removal_offset_delta[ i ][ j ]");
           }
-          xWriteCode(sei.m_vclCpbDelayOffset[i], bp.m_cpbRemovalDelayLength, "vcl_cpb_delay_offset[ i ]");
-          xWriteCode(sei.m_vclDpbDelayOffset[i], bp.m_dpbOutputDelayLength,  "vcl_dpb_delay_offset[ i ]");
+          xWriteCode(sei.m_vclCpbDelayOffset[i], bp.cpbRemovalDelayLength, "vcl_cpb_delay_offset[ i ]");
+          xWriteCode(sei.m_vclDpbDelayOffset[i], bp.dpbOutputDelayLength, "vcl_dpb_delay_offset[ i ]");
         }
       }
     }
   }
-  if (bp.m_bpDecodingUnitHrdParamsPresentFlag && bp.m_decodingUnitDpbDuParamsInPicTimingSeiFlag)
 
+  if (bp.hasDuHrdParams && bp.duDpbParamsInPicTimingSei)
   {
-    xWriteCode( sei.m_picDpbOutputDuDelay, bp.m_dpbOutputDelayDuLength, "pic_dpb_output_du_delay" );
+    xWriteCode(sei.m_picDpbOutputDuDelay, bp.dpbOutputDelayDuLength, "pic_dpb_output_du_delay");
   }
-  if( bp.m_bpDecodingUnitHrdParamsPresentFlag && bp.m_decodingUnitCpbParamsInPicTimingSeiFlag )
+  if (bp.hasDuHrdParams && bp.duCpbParamsInPicTimingSei)
   {
     xWriteUvlc( sei.m_numDecodingUnitsMinus1, "num_decoding_units_minus1" );
     if (sei.m_numDecodingUnitsMinus1 > 0)
@@ -514,11 +524,12 @@ void SEIWriter::xWriteSEIPictureTiming(const SEIPictureTiming& sei, const SEIBuf
       xWriteFlag( sei.m_duCommonCpbRemovalDelayFlag, "du_commmon_cpb_removal_delay_flag" );
       if( sei.m_duCommonCpbRemovalDelayFlag )
       {
-        for( int i = temporalId; i <= bp.m_bpMaxSubLayers - 1; i ++ )
+        for (int i = temporalId; i < bp.maxSublayers; i++)
         {
           if( sei.m_ptSubLayerDelaysPresentFlag[i] )
           {
-            xWriteCode( sei.m_duCommonCpbRemovalDelayMinus1[i], bp.m_duCpbRemovalDelayIncrementLength, "du_common_cpb_removal_delay_increment_minus1[i]" );
+            xWriteCode(sei.m_duCommonCpbRemovalDelayMinus1[i], bp.duCpbRemovalDelayIncrementLength,
+                       "du_common_cpb_removal_delay_increment_minus1[i]");
           }
         }
       }
@@ -527,11 +538,12 @@ void SEIWriter::xWriteSEIPictureTiming(const SEIPictureTiming& sei, const SEIBuf
         xWriteUvlc( sei.m_numNalusInDuMinus1[i], "num_nalus_in_du_minus1[i]" );
         if( !sei.m_duCommonCpbRemovalDelayFlag && i < sei.m_numDecodingUnitsMinus1 )
         {
-          for( int j = temporalId; j <= bp.m_bpMaxSubLayers - 1; j ++ )
+          for (int j = temporalId; j < bp.maxSublayers; j++)
           {
             if( sei.m_ptSubLayerDelaysPresentFlag[j] )
             {
-              xWriteCode( sei.m_duCpbRemovalDelayMinus1[i * bp.m_bpMaxSubLayers + j], bp.m_duCpbRemovalDelayIncrementLength, "du_cpb_removal_delay_increment_minus1[i][j]" );
+              xWriteCode(sei.m_duCpbRemovalDelayMinus1[i * bp.maxSublayers + j], bp.duCpbRemovalDelayIncrementLength,
+                         "du_cpb_removal_delay_increment_minus1[i][j]");
             }
           }
         }
-- 
GitLab