From 8b376f80cb4d63e9a1acfe032a7e19660e6ded72 Mon Sep 17 00:00:00 2001
From: Frank Bossen <fbossen@gmail.com>
Date: Fri, 9 Feb 2024 07:58:51 -0500
Subject: [PATCH] Remove xParseSEIScalableNestingBinary to avoid code
 duplication

---
 source/Lib/DecoderLib/SEIread.cpp | 348 ++++++++++++------------------
 source/Lib/DecoderLib/SEIread.h   |   5 +-
 2 files changed, 134 insertions(+), 219 deletions(-)

diff --git a/source/Lib/DecoderLib/SEIread.cpp b/source/Lib/DecoderLib/SEIread.cpp
index 2cefc1529..6b81a1524 100644
--- a/source/Lib/DecoderLib/SEIread.cpp
+++ b/source/Lib/DecoderLib/SEIread.cpp
@@ -165,8 +165,8 @@ void SEIReader::parseAndExtractSEIScalableNesting(InputBitstream *bs, const NalU
   SEI *sei = nullptr;
   sei = new SEIScalableNesting;
   setBitstream(bs);
-  xParseSEIScalableNestingBinary((SEIScalableNesting &) *sei, nalUnitType, nuh_layer_id, payloadSize, vps, sps, hrd,
-                                 nullptr, seiList);
+  xParseSEIScalableNesting((SEIScalableNesting&) *sei, nalUnitType, nuh_layer_id, payloadSize, vps, sps, hrd, nullptr,
+                           seiList);
   int payloadBitsRemaining = getBitstream()->getNumBitsLeft();
   if (payloadBitsRemaining) /* more_data_in_payload() */
   {
@@ -358,8 +358,8 @@ bool SEIReader::xReadSEImessage(SEIMessages& seis, const NalUnitType nalUnitType
       }
     case SEI::PayloadType::SCALABLE_NESTING:
       sei = new SEIScalableNesting;
-      xParseSEIScalableNesting((SEIScalableNesting &) *sei, nalUnitType, nuh_layer_id, payloadSize, vps, sps, hrd,
-                               pDecodedMessageOutputStream);
+      xParseSEIScalableNesting((SEIScalableNesting&) *sei, nalUnitType, nuh_layer_id, payloadSize, vps, sps, hrd,
+                               pDecodedMessageOutputStream, nullptr);
       break;
     case SEI::PayloadType::FRAME_FIELD_INFO:
       sei = new SEIFrameFieldInfo;
@@ -576,8 +576,8 @@ bool SEIReader::xReadSEImessage(SEIMessages& seis, const NalUnitType nalUnitType
       break;
     case SEI::PayloadType::SCALABLE_NESTING:
       sei = new SEIScalableNesting;
-      xParseSEIScalableNesting((SEIScalableNesting &) *sei, nalUnitType, nuh_layer_id, payloadSize, vps, sps, hrd,
-                               pDecodedMessageOutputStream);
+      xParseSEIScalableNesting((SEIScalableNesting&) *sei, nalUnitType, nuh_layer_id, payloadSize, vps, sps, hrd,
+                               pDecodedMessageOutputStream, nullptr);
       break;
     case SEI::PayloadType::NEURAL_NETWORK_POST_FILTER_CHARACTERISTICS:
       sei = new SEINeuralNetworkPostFilterCharacteristics;
@@ -955,10 +955,10 @@ void SEIReader::xParseSEIDecodedPictureHash(SEIDecodedPictureHash& sei, uint32_t
 
 void SEIReader::xParseSEIScalableNesting(SEIScalableNesting& sn, const NalUnitType nalUnitType,
                                          const uint32_t nuhLayerId, uint32_t payloadSize, const VPS* vps,
-                                         const SPS* sps, HRD& hrd, std::ostream* decodedMessageOutputStream)
+                                         const SPS* sps, HRD& hrd, std::ostream* decodedMessageOutputStream,
+                                         std::vector<SeiPayload>* seiList)
 {
   uint32_t symbol;
-  SEIMessages seis;
   output_sei_message_header(sn, decodedMessageOutputStream, payloadSize);
 
   sei_read_flag(decodedMessageOutputStream, symbol, "sn_ols_flag");
@@ -1038,35 +1038,141 @@ void SEIReader::xParseSEIScalableNesting(SEIScalableNesting& sn, const NalUnitTy
     sei_read_flag(decodedMessageOutputStream, symbol, "sn_zero_bit");
   }
 
-  // read nested SEI messages
-  for (int i = 0; i < numSeis; i++)
+  if (seiList == nullptr)
   {
-    SEIMessages tmpSEIs;
-    const bool seiMessageRead = xReadSEImessage(tmpSEIs, nalUnitType, nuhLayerId, 0, vps, sps, m_nestedHrd, decodedMessageOutputStream);
-    if (seiMessageRead)
+    // read nested SEI messages
+    for (int i = 0; i < numSeis; i++)
     {
-      if (tmpSEIs.front()->payloadType() == SEI::PayloadType::BUFFERING_PERIOD)
+      SEIMessages tmpSEIs;
+      const bool  seiMessageRead =
+        xReadSEImessage(tmpSEIs, nalUnitType, nuhLayerId, 0, vps, sps, m_nestedHrd, decodedMessageOutputStream);
+      if (seiMessageRead)
       {
-        auto bp = reinterpret_cast<SEIBufferingPeriod*>(tmpSEIs.front());
-        m_nestedHrd.setBufferingPeriodSEI(bp);
-        const SEIBufferingPeriod *nonNestedBp = hrd.getBufferingPeriodSEI();
-        if (nonNestedBp)
+        if (tmpSEIs.front()->payloadType() == SEI::PayloadType::BUFFERING_PERIOD)
         {
-          checkBPSyntaxElementLength(nonNestedBp, bp);
+          auto bp = reinterpret_cast<SEIBufferingPeriod*>(tmpSEIs.front());
+          m_nestedHrd.setBufferingPeriodSEI(bp);
+          const SEIBufferingPeriod* nonNestedBp = hrd.getBufferingPeriodSEI();
+          if (nonNestedBp)
+          {
+            checkBPSyntaxElementLength(nonNestedBp, bp);
+          }
         }
+        sn.nestedSeis.push_back(tmpSEIs.front());
+        tmpSEIs.clear();
       }
-      sn.nestedSeis.push_back(tmpSEIs.front());
-      tmpSEIs.clear();
     }
+
+    const GeneralHrdParams* generalHrd = vps && vps->getVPSGeneralHrdParamsPresentFlag()
+                                           ? vps->getGeneralHrdParameters()
+                                         : sps->getGeneralHrdParametersPresentFlag() ? sps->getGeneralHrdParameters()
+                                                                                     : nullptr;
+
+    xCheckScalableNestingConstraints(sn, nalUnitType, generalHrd);
   }
+  else
+  {
+    for (int i = 0; i < numSeis; i++)
+    {
+      uint32_t payloadTypeVal = 0;
+      do
+      {
+        sei_read_code(nullptr, 8, symbol, "payload_type");
+        payloadTypeVal += symbol;
+      } while (symbol == 0xff);
+
+      auto payloadType = static_cast<SEI::PayloadType>(payloadTypeVal);
+
+      uint32_t payloadSize = 0;
+      do
+      {
+        sei_read_code(nullptr, 8, symbol, "payload_size");
+        payloadSize += symbol;
+      } while (symbol == 0xff);
+
+      int duiIdx = 0;
+      if (SEI::PayloadType(payloadType) == SEI::PayloadType::DECODING_UNIT_INFO)
+      {
+        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
+        {
+          InputBitstream* bs = getBitstream();
+          InputBitstream  bsTmp(*bs);
+          setBitstream(&bsTmp);
+
+          SEIDecodingUnitInfo dui;
+          xParseSEIDecodingUnitInfo(dui, payloadSize, *bp, nuhLayerId, nullptr);
+          duiIdx = dui.decodingUnitIdx;
+
+          setBitstream(bs);
+        }
+      }
 
-  const GeneralHrdParams *generalHrd = vps && vps->getVPSGeneralHrdParamsPresentFlag()
-    ? vps->getGeneralHrdParameters()
-    : sps->getGeneralHrdParametersPresentFlag()
-      ? sps->getGeneralHrdParameters()
-      : nullptr;
+      auto payload = new uint8_t[payloadSize];
+      for (uint32_t j = 0; j < payloadSize; j++)
+      {
+        sei_read_code(nullptr, 8, symbol, "payload_content");
+        payload[j] = symbol;
+      }
+
+      auto&&   subpicId    = !sn.subpicId.empty() ? sn.subpicId : std::vector<uint16_t>{ 0 };
+      uint8_t* payloadTemp = payload;
+
+      if (!sn.olsIdx.empty())
+      {
+        for (uint32_t j = 0; j < sn.olsIdx.size(); j++)
+        {
+          for (uint32_t k = 0; k < subpicId.size(); k++)
+          {
+            if (j != 0 || k != 0)
+            {
+              payloadTemp = new uint8_t[payloadSize];
+              std::copy_n(payload, payloadSize, payloadTemp);
+            }
+
+            seiList->push_back(
+              SeiPayload{ payloadType, sn.olsIdx[j], false, payloadSize, payloadTemp, duiIdx, subpicId[k] });
+          }
+        }
+      }
+      else if (sn.allLayersFlag())
+      {
+        for (uint32_t k = 0; k < subpicId.size(); k++)
+        {
+          if (k != 0)
+          {
+            payloadTemp = new uint8_t[payloadSize];
+            std::copy_n(payload, payloadSize, payloadTemp);
+          }
+
+          seiList->push_back(
+            SeiPayload{ payloadType, nuhLayerId, true, payloadSize, payloadTemp, duiIdx, subpicId[k] });
+        }
+      }
+      else
+      {
+        for (uint32_t j = 0; j < sn.layerId.size(); j++)
+        {
+          for (uint32_t k = 0; k < subpicId.size(); k++)
+          {
+            if (j != 0 || k != 0)
+            {
+              payloadTemp = new uint8_t[payloadSize];
+              std::copy_n(payload, payloadSize, payloadTemp);
+            }
 
-  xCheckScalableNestingConstraints(sn, nalUnitType, generalHrd);
+            seiList->push_back(
+              SeiPayload{ payloadType, sn.layerId[j], false, payloadSize, payloadTemp, duiIdx, subpicId[k] });
+          }
+        }
+      }
+    }
+  }
 
   if (decodedMessageOutputStream)
   {
@@ -1219,194 +1325,6 @@ void SEIReader::xParseSEIGreenMetadataInfo(SEIGreenMetadataInfo& sei, uint32_t p
   }
 }
 
-void SEIReader::xParseSEIScalableNestingBinary(SEIScalableNesting& sn, const NalUnitType nalUnitType,
-                                               const uint32_t nuhLayerId, uint32_t payloadSize, const VPS* vps,
-                                               const SPS* sps, HRD& hrd, std::ostream* decodedMessageOutputStream,
-                                               std::vector<SeiPayload>* seiList)
-{
-  uint32_t symbol;
-  SEIMessages seis;
-  output_sei_message_header(sn, decodedMessageOutputStream, payloadSize);
-
-  sei_read_flag(decodedMessageOutputStream, symbol, "sn_ols_flag");
-  const bool hasOldIdx = symbol != 0;
-
-  sei_read_flag(decodedMessageOutputStream, symbol, "sn_subpic_flag");
-  const bool hasSubpicId = symbol != 0;
-
-  if (hasOldIdx)
-  {
-    sei_read_uvlc(decodedMessageOutputStream, symbol, "sn_num_olss_minus1");
-    sn.olsIdx.resize(symbol + 1);
-
-    for (uint32_t i = 0; i < sn.olsIdx.size(); i++)
-    {
-      const uint32_t pred = i == 0 ? 0 : sn.olsIdx[i - 1] + 1;
-
-      sei_read_uvlc(decodedMessageOutputStream, symbol, "sn_ols_idx_delta_minus1[i]");
-      sn.olsIdx[i] = pred + symbol;
-    }
-    if (vps && vps->getVPSId() != 0)
-    {
-      uint32_t lowestLayerId = std::numeric_limits<uint32_t>::max();
-      for (uint32_t olsIdx: sn.olsIdx)
-      {
-        for (int layerIdx = 0; layerIdx < vps->getNumLayersInOls(olsIdx); layerIdx++)
-        {
-          lowestLayerId = std::min(lowestLayerId, vps->getLayerIdInOls(olsIdx, layerIdx));
-        }
-      }
-      CHECK(lowestLayerId!= nuhLayerId, "nuh_layer_id is not equal to the lowest layer among Olss that the scalable SEI applies");
-    }
-  }
-  else
-  {
-    sei_read_flag(decodedMessageOutputStream, symbol, "sn_all_layers_flag");
-    const bool allLayersFlag = symbol != 0;
-    if (!allLayersFlag)
-    {
-      sei_read_uvlc(decodedMessageOutputStream, symbol, "sn_num_layers_minus1");
-      sn.layerId.resize(symbol + 1);
-      sn.layerId[0] = nuhLayerId;
-      for (uint32_t i = 1; i < sn.layerId.size(); i++)
-      {
-        sei_read_code(decodedMessageOutputStream, 6, symbol, "sn_layer_id[i]");
-        sn.layerId[i] = symbol;
-      }
-    }
-    else
-    {
-      sn.layerId.clear();
-    }
-  }
-  if (hasSubpicId)
-  {
-    sei_read_uvlc(decodedMessageOutputStream, symbol, "sn_num_subpics_minus1");
-    sn.subpicId.resize(symbol + 1);
-
-    sei_read_uvlc(decodedMessageOutputStream, symbol, "sn_subpic_id_len_minus1");
-    sn.subpicIdLen = symbol + 1;
-
-    for (uint32_t i = 0; i < sn.subpicId.size(); i++)
-    {
-      sei_read_code(decodedMessageOutputStream, sn.subpicIdLen, symbol, "sn_subpic_id[i]");
-      sn.subpicId[i] = symbol;
-    }
-  }
-
-  sei_read_uvlc(decodedMessageOutputStream, symbol, "sn_num_seis_minus1");
-  const uint32_t numSeis = symbol + 1;
-
-  CHECK(numSeis > 64, "The value of sn_num_seis_minus1 shall be in the range of 0 to 63");
-
-  // byte alignment
-  while (m_pcBitstream->getNumBitsRead() % 8 != 0)
-  {
-    sei_read_flag(decodedMessageOutputStream, symbol, "sn_zero_bit");
-  }
-
-  // above codes are exactly same as those in xParseSEIScalableNesting()
-  // read and save nested SEI messages in binary form
-  for (int i = 0; i < numSeis; i++)
-  {
-    uint32_t payloadTypeVal = 0;
-    do
-    {
-      sei_read_code(nullptr, 8, symbol, "payload_type");
-      payloadTypeVal += symbol;
-    } while (symbol == 0xff);
-
-    auto payloadType = static_cast<SEI::PayloadType>(payloadTypeVal);
-
-    uint32_t payloadSize = 0;
-    do
-    {
-      sei_read_code(nullptr, 8, symbol, "payload_size");
-      payloadSize += symbol;
-    } while (symbol == 0xff);
-
-    int duiIdx = 0;
-    if (SEI::PayloadType(payloadType) == SEI::PayloadType::DECODING_UNIT_INFO)
-    {
-      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
-      {
-        InputBitstream *bs = getBitstream();
-        InputBitstream  bsTmp(*bs);
-        setBitstream(&bsTmp);
-
-        SEIDecodingUnitInfo dui;
-        xParseSEIDecodingUnitInfo(dui, payloadSize, *bp, nuhLayerId, nullptr);
-        duiIdx = dui.decodingUnitIdx;
-
-        setBitstream(bs);
-      }
-    }
-
-    auto payload = new uint8_t[payloadSize];
-    for (uint32_t j = 0; j < payloadSize; j++)
-    {
-      sei_read_code(nullptr, 8, symbol, "payload_content");
-      payload[j] = symbol;
-    }
-
-    auto&&   subpicId    = !sn.subpicId.empty() ? sn.subpicId : std::vector<uint16_t>{ 0 };
-    uint8_t* payloadTemp = payload;
-
-    if (!sn.olsIdx.empty())
-    {
-      for (uint32_t j = 0; j < sn.olsIdx.size(); j++)
-      {
-        for (uint32_t k = 0; k < subpicId.size(); k++)
-        {
-          if (j != 0 || k != 0)
-          {
-            payloadTemp = new uint8_t[payloadSize];
-            std::copy_n(payload, payloadSize, payloadTemp);
-          }
-
-          seiList->push_back(
-            SeiPayload{ payloadType, sn.olsIdx[j], false, payloadSize, payloadTemp, duiIdx, subpicId[k] });
-        }
-      }
-    }
-    else if (sn.allLayersFlag())
-    {
-      for (uint32_t k = 0; k < subpicId.size(); k++)
-      {
-        if (k != 0)
-        {
-          payloadTemp = new uint8_t[payloadSize];
-          memcpy(payloadTemp, payload, payloadSize * sizeof(uint8_t));
-        }
-
-        seiList->push_back(SeiPayload{ payloadType, nuhLayerId, true, payloadSize, payloadTemp, duiIdx, subpicId[k] });
-      }
-    }
-    else
-    {
-      for (uint32_t j = 0; j < sn.layerId.size(); j++)
-      {
-        for (uint32_t k = 0; k < subpicId.size(); k++)
-        {
-          if (j != 0 || k != 0)
-          {
-            payloadTemp = new uint8_t[payloadSize];
-            memcpy(payloadTemp, payload, payloadSize * sizeof(uint8_t));
-          }
-
-          seiList->push_back(
-            SeiPayload{ payloadType, sn.layerId[j], false, payloadSize, payloadTemp, duiIdx, subpicId[k] });
-        }
-      }
-    }
-  }
-}
-
 void SEIReader::xCheckScalableNestingConstraints(const SEIScalableNesting& sn, const NalUnitType nalUnitType,
                                                  const GeneralHrdParams* generalHrd)
 {
diff --git a/source/Lib/DecoderLib/SEIread.h b/source/Lib/DecoderLib/SEIread.h
index 4bd071d07..5b78c21ae 100644
--- a/source/Lib/DecoderLib/SEIread.h
+++ b/source/Lib/DecoderLib/SEIread.h
@@ -77,10 +77,7 @@ protected:
                               const SEIBufferingPeriod& bp, std::ostream* pDecodedMessageOutputStream);
   void xParseSEIScalableNesting(SEIScalableNesting& sn, const NalUnitType nalUnitType, const uint32_t nuhLayerId,
                                 uint32_t payloadSize, const VPS* vps, const SPS* sps, HRD& hrd,
-                                std::ostream* decodedMessageOutputStream);
-  void xParseSEIScalableNestingBinary(SEIScalableNesting& sn, const NalUnitType nalUnitType, const uint32_t nuhLayerId,
-                                      uint32_t payloadSize, const VPS* vps, const SPS* sps, HRD& hrd,
-                                      std::ostream* decodedMessageOutputStream, std::vector<SeiPayload>* seiList);
+                                std::ostream* decodedMessageOutputStream, std::vector<SeiPayload>* seiList);
   void xCheckScalableNestingConstraints(const SEIScalableNesting& sn, const NalUnitType nalUnitType,
                                         const GeneralHrdParams* generalHrd);
   void xParseSEIFrameFieldinfo                (SEIFrameFieldInfo& sei,                uint32_t payloadSize, std::ostream *pDecodedMessageOutputStream);
-- 
GitLab