Skip to content
Snippets Groups Projects
SEIread.cpp 143 KiB
Newer Older
  • Learn to ignore specific revisions
  • /* The copyright in this software is being made available under the BSD
     * License, included below. This software may be subject to other third party
     * and contributor rights, including patent rights, and no such rights are
     * granted under this license.
     *
    
     * Copyright (c) 2010-2022, ITU/ISO/IEC
    
     * All rights reserved.
     *
     * Redistribution and use in source and binary forms, with or without
     * modification, are permitted provided that the following conditions are met:
     *
     *  * Redistributions of source code must retain the above copyright notice,
     *    this list of conditions and the following disclaimer.
     *  * Redistributions in binary form must reproduce the above copyright notice,
     *    this list of conditions and the following disclaimer in the documentation
     *    and/or other materials provided with the distribution.
     *  * Neither the name of the ITU/ISO/IEC nor the names of its contributors may
     *    be used to endorse or promote products derived from this software without
     *    specific prior written permission.
     *
     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
     * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
     * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
     * THE POSSIBILITY OF SUCH DAMAGE.
     */
    
    /**
     \file     SEIread.cpp
     \brief    reading funtionality for SEI messages
     */
    
    #include "CommonLib/CommonDef.h"
    #include "CommonLib/BitStream.h"
    #include "CommonLib/SEI.h"
    #include "CommonLib/Slice.h"
    #include "VLCReader.h"
    #include "SEIread.h"
    #include "CommonLib/Picture.h"
    #include "CommonLib/dtrace_next.h"
    #include <iomanip>
    
    
    //! \ingroup DecoderLib
    //! \{
    
    
    void SEIReader::sei_read_scode(std::ostream *pOS, uint32_t length, int& code, const char *pSymbolName)
    {
      READ_SCODE(length, code, pSymbolName);
      if (pOS)
      {
        (*pOS) << "  " << std::setw(55) << pSymbolName << ": " << code << "\n";
      }
    }
    
    
    void SEIReader::sei_read_code(std::ostream *pOS, uint32_t length, uint32_t &ruiCode, const char *pSymbolName)
    
      READ_CODE(length, ruiCode, pSymbolName);
    
      if (pOS)
      {
        (*pOS) << "  " << std::setw(55) << pSymbolName << ": " << ruiCode << "\n";
      }
    }
    
    void SEIReader::sei_read_uvlc(std::ostream *pOS, uint32_t& ruiCode, const char *pSymbolName)
    {
      READ_UVLC(ruiCode, pSymbolName);
      if (pOS)
      {
        (*pOS) << "  " << std::setw(55) << pSymbolName << ": " << ruiCode << "\n";
      }
    }
    
    void SEIReader::sei_read_svlc(std::ostream *pOS, int& ruiCode, const char *pSymbolName)
    {
      READ_SVLC(ruiCode, pSymbolName);
      if (pOS)
      {
        (*pOS) << "  " << std::setw(55) << pSymbolName << ": " << ruiCode << "\n";
      }
    }
    
    void SEIReader::sei_read_flag(std::ostream *pOS, uint32_t& ruiCode, const char *pSymbolName)
    {
      READ_FLAG(ruiCode, pSymbolName);
      if (pOS)
      {
        (*pOS) << "  " << std::setw(55) << pSymbolName << ": " << (ruiCode?1:0) << "\n";
      }
    }
    
    
    void SEIReader::sei_read_string(std::ostream* os, std::string& code, const char* symbolName)
    {
      READ_STRING(code, symbolName);
      if (os)
      {
        (*os) << "  " << std::setw(55) << symbolName << ": " << code << "\n";
      }
    }
    
    
    
    static inline void output_sei_message_header(SEI &sei, std::ostream *pDecodedMessageOutputStream, uint32_t payloadSize)
    {
      if (pDecodedMessageOutputStream)
      {
        std::string seiMessageHdr(SEI::getSEIMessageString(sei.payloadType())); seiMessageHdr+=" SEI message";
    
        (*pDecodedMessageOutputStream) << std::setfill('-') << std::setw((int) seiMessageHdr.size()) << "-"
                                       << std::setfill(' ') << "\n"
                                       << seiMessageHdr << " (" << payloadSize << " bytes)"
                                       << "\n";
    
    Taoran Lu's avatar
    Taoran Lu committed
    #undef READ_SCODE
    
    #undef READ_SVLC
    #undef READ_UVLC
    #undef READ_FLAG
    
    
    /**
     * unmarshal a single SEI message from bitstream bs
     */
    
     // note: for independent parsing no parameter set should not be required here
    
    void SEIReader::parseSEImessage(InputBitstream* bs, SEIMessages& seis, const NalUnitType nalUnitType, const uint32_t nuh_layer_id, const uint32_t temporalId, const VPS *vps, const SPS *sps, HRD &hrd, std::ostream *pDecodedMessageOutputStream)
    
      SEIMessages   seiListInCurNalu;
    
      setBitstream(bs);
      CHECK(m_pcBitstream->getNumBitsUntilByteAligned(), "Bitstream not aligned");
    
        xReadSEImessage(seis, nalUnitType, nuh_layer_id, temporalId, vps, sps, hrd, pDecodedMessageOutputStream);
    
        seiListInCurNalu.push_back(seis.back());
    
        /* SEI messages are an integer number of bytes, something has failed
        * in the parsing if bitstream not byte-aligned */
        CHECK(m_pcBitstream->getNumBitsUntilByteAligned(), "Bitstream not aligned");
      }
      while (m_pcBitstream->getNumBitsLeft() > 8);
    
    
      const SEIMessages fillerData = getSeisByType(seiListInCurNalu, SEI::PayloadType::FILLER_PAYLOAD);
    
      CHECK(fillerData.size() > 0 && fillerData.size() != seiListInCurNalu.size(), "When an SEI NAL unit contains an SEI message with payloadType equal to filler payload, the SEI NAL unit shall not contain any other SEI message with payloadType not equal to filler payload");
    
      const SEIMessages pictureTiming = getSeisByType(seiListInCurNalu, SEI::PayloadType::PICTURE_TIMING);
    
      CHECK(hrd.getGeneralHrdParameters().getGeneralSamePicTimingInAllOlsFlag() && pictureTiming.size() > 0 && pictureTiming.size() != seiListInCurNalu.size(),
    
            "When general_same_pic_timing_in_all_ols_flag is equal to 1 [...], and when an SEI NAL unit contains a non-scalable-nested SEI message with "
            "payloadType equal to 1 (PT), the SEI NAL unit shall not contain any other SEI message with payloadType not equal 1.");
    
    void SEIReader::parseAndExtractSEIScalableNesting(InputBitstream *bs, const NalUnitType nalUnitType,
                                                      const uint32_t nuh_layer_id, const VPS *vps, const SPS *sps, HRD &hrd,
                                                      uint32_t payloadSize, std::vector<SeiPayload> *seiList)
    
    Yang Wang's avatar
    Yang Wang committed
    {
    
    Frank Bossen's avatar
    Frank Bossen committed
      SEI *sei = nullptr;
    
    Yang Wang's avatar
    Yang Wang committed
      sei = new SEIScalableNesting;
      setBitstream(bs);
    
    Frank Bossen's avatar
    Frank Bossen committed
      xParseSEIScalableNestingBinary((SEIScalableNesting &) *sei, nalUnitType, nuh_layer_id, payloadSize, vps, sps, hrd,
                                     nullptr, seiList);
    
    Yang Wang's avatar
    Yang Wang committed
      int payloadBitsRemaining = getBitstream()->getNumBitsLeft();
      if (payloadBitsRemaining) /* more_data_in_payload() */
      {
        for (; payloadBitsRemaining > 9; payloadBitsRemaining--)
        {
          uint32_t reservedPayloadExtensionData;
    
    Frank Bossen's avatar
    Frank Bossen committed
          sei_read_code(nullptr, 1, reservedPayloadExtensionData, "reserved_payload_extension_data");
    
    Yang Wang's avatar
    Yang Wang committed
        }
    
        /* 2 */
        int finalBits = getBitstream()->peekBits(payloadBitsRemaining);
        int finalPayloadBits = 0;
        for (int mask = 0xff; finalBits & (mask >> finalPayloadBits); finalPayloadBits++)
        {
          continue;
        }
    
        /* 3 */
        for (; payloadBitsRemaining > 9 - finalPayloadBits; payloadBitsRemaining--)
        {
          uint32_t reservedPayloadExtensionData;
          sei_read_flag ( 0, reservedPayloadExtensionData, "reserved_payload_extension_data");
        }
    
        uint32_t dummy;
        sei_read_flag( 0, dummy, "payload_bit_equal_to_one"); payloadBitsRemaining--;
        while (payloadBitsRemaining)
        {
          sei_read_flag( 0, dummy, "payload_bit_equal_to_zero"); payloadBitsRemaining--;
        }
      }
      delete sei;
    }
    
    
    void SEIReader::getSEIDecodingUnitInfoDuiIdx(InputBitstream* bs, const NalUnitType nalUnitType, const uint32_t nuh_layer_id, HRD &hrd, uint32_t payloadSize, int& duiIdx)
    {
    
    Frank Bossen's avatar
    Frank Bossen committed
      const SEIBufferingPeriod *bp = nullptr;
    
      bp = hrd.getBufferingPeriodSEI();
      if (!bp)
      {
        // msg( WARNING, "Warning: Found Decoding unit information SEI message, but no active buffering period is available. Ignoring.");
      }
      else
      {
        InputBitstream bs2(*bs);
        setBitstream(&bs2);
    
    Frank Bossen's avatar
    Frank Bossen committed
        SEI *sei = nullptr;
    
        sei = new SEIDecodingUnitInfo;
    
    Frank Bossen's avatar
    Frank Bossen committed
        xParseSEIDecodingUnitInfo((SEIDecodingUnitInfo &) *sei, payloadSize, *bp, nuh_layer_id, nullptr);
    
        duiIdx = ((SEIDecodingUnitInfo&)*sei).m_decodingUnitIdx;
        delete sei;
        setBitstream(bs);
      }
    }
    
    Yang Wang's avatar
    Yang Wang committed
    
    
    void SEIReader::xReadSEImessage(SEIMessages& seis, const NalUnitType nalUnitType, const uint32_t nuh_layer_id, const uint32_t temporalId, const VPS *vps, const SPS *sps, HRD &hrd, std::ostream *pDecodedMessageOutputStream)
    
    {
    #if ENABLE_TRACING
      xTraceSEIHeader();
    #endif
      int payloadType = 0;
      uint32_t val = 0;
    
      do
      {
    
        sei_read_code(nullptr, 8, val, "payload_type");
    
        payloadType += val;
      } while (val==0xFF);
    
      uint32_t payloadSize = 0;
      do
      {
    
        sei_read_code(nullptr, 8, val, "payload_size");
    
        payloadSize += val;
      } while (val==0xFF);
    
    #if ENABLE_TRACING
      xTraceSEIMessageType((SEI::PayloadType)payloadType);
    #endif
    
      /* extract the payload for this single SEI message.
       * This allows greater safety in erroneous parsing of an SEI message
       * from affecting subsequent messages.
       * After parsing the payload, bs needs to be restored as the primary
       * bitstream.
       */
      InputBitstream *bs = getBitstream();
      setBitstream(bs->extractSubstream(payloadSize * 8));
    
    
      SEI                      *sei = nullptr;
      const SEIBufferingPeriod *bp  = nullptr;
    
        switch (SEI::PayloadType(payloadType))
    
        case SEI::PayloadType::FILLER_PAYLOAD:
    
    Sees's avatar
    Sees committed
          sei = new SEIFillerPayload;
          xParseSEIFillerPayload((SEIFillerPayload&) *sei, payloadSize, pDecodedMessageOutputStream);
          break;
    
        case SEI::PayloadType::USER_DATA_UNREGISTERED:
    
          sei = new SEIuserDataUnregistered;
          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);
          }
    
        case SEI::PayloadType::BUFFERING_PERIOD:
    
          xParseSEIBufferingPeriod((SEIBufferingPeriod&) *sei, payloadSize, pDecodedMessageOutputStream);
    
          hrd.setBufferingPeriodSEI((SEIBufferingPeriod*) sei);
    
        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.");
          }
          else
          {
            sei = new SEIPictureTiming;
            xParseSEIPictureTiming((SEIPictureTiming &) *sei, payloadSize, temporalId, *bp, pDecodedMessageOutputStream);
            hrd.setPictureTimingSEI((SEIPictureTiming *) sei);
    
        case SEI::PayloadType::SCALABLE_NESTING:
    
          sei = new SEIScalableNesting;
    
          xParseSEIScalableNesting((SEIScalableNesting &) *sei, nalUnitType, nuh_layer_id, payloadSize, vps, sps, hrd,
                                   pDecodedMessageOutputStream);
    
        case SEI::PayloadType::FRAME_FIELD_INFO:
    
          sei = new SEIFrameFieldInfo;
    
          xParseSEIFrameFieldinfo((SEIFrameFieldInfo &) *sei, payloadSize, pDecodedMessageOutputStream);
    
        case SEI::PayloadType::DEPENDENT_RAP_INDICATION:
    
          sei = new SEIDependentRAPIndication;
    
          xParseSEIDependentRAPIndication((SEIDependentRAPIndication &) *sei, payloadSize, pDecodedMessageOutputStream);
    
        case SEI::PayloadType::EXTENDED_DRAP_INDICATION:
    
          sei = new SEIExtendedDrapIndication;
    
          xParseSEIExtendedDrapIndication((SEIExtendedDrapIndication &) *sei, payloadSize, pDecodedMessageOutputStream);
    
          break;
    
        case SEI::PayloadType::FRAME_PACKING:
    
          xParseSEIFramePacking((SEIFramePacking &) *sei, payloadSize, pDecodedMessageOutputStream);
    
        case SEI::PayloadType::DISPLAY_ORIENTATION:
    
    yonghe's avatar
    yonghe committed
          sei = new SEIDisplayOrientation;
    
          xParseSEIDisplayOrientation((SEIDisplayOrientation &) *sei, payloadSize, pDecodedMessageOutputStream);
    
    yonghe's avatar
    yonghe committed
          break;
    
        case SEI::PayloadType::ANNOTATED_REGIONS:
    
          sei = new SEIAnnotatedRegions;
    
          xParseSEIAnnotatedRegions((SEIAnnotatedRegions &) *sei, payloadSize, pDecodedMessageOutputStream);
    
        case SEI::PayloadType::PARAMETER_SETS_INCLUSION_INDICATION:
    
          sei = new SEIParameterSetsInclusionIndication;
    
          xParseSEIParameterSetsInclusionIndication((SEIParameterSetsInclusionIndication &) *sei, payloadSize,
                                                    pDecodedMessageOutputStream);
    
        case SEI::PayloadType::MASTERING_DISPLAY_COLOUR_VOLUME:
    
          xParseSEIMasteringDisplayColourVolume((SEIMasteringDisplayColourVolume &) *sei, payloadSize,
                                                pDecodedMessageOutputStream);
    
        case SEI::PayloadType::ALTERNATIVE_TRANSFER_CHARACTERISTICS:
    
          sei = new SEIAlternativeTransferCharacteristics;
    
          xParseSEIAlternativeTransferCharacteristics((SEIAlternativeTransferCharacteristics &) *sei, payloadSize,
                                                      pDecodedMessageOutputStream);
    
        case SEI::PayloadType::EQUIRECTANGULAR_PROJECTION:
    
          sei = new SEIEquirectangularProjection;
    
          xParseSEIEquirectangularProjection((SEIEquirectangularProjection &) *sei, payloadSize,
                                             pDecodedMessageOutputStream);
    
        case SEI::PayloadType::SPHERE_ROTATION:
    
          sei = new SEISphereRotation;
    
          xParseSEISphereRotation((SEISphereRotation &) *sei, payloadSize, pDecodedMessageOutputStream);
    
        case SEI::PayloadType::OMNI_VIEWPORT:
    
          sei = new SEIOmniViewport;
    
          xParseSEIOmniViewport((SEIOmniViewport &) *sei, payloadSize, pDecodedMessageOutputStream);
    
        case SEI::PayloadType::REGION_WISE_PACKING:
    
          sei = new SEIRegionWisePacking;
    
          xParseSEIRegionWisePacking((SEIRegionWisePacking &) *sei, payloadSize, pDecodedMessageOutputStream);
    
        case SEI::PayloadType::GENERALIZED_CUBEMAP_PROJECTION:
    
          sei = new SEIGeneralizedCubemapProjection;
    
          xParseSEIGeneralizedCubemapProjection((SEIGeneralizedCubemapProjection &) *sei, payloadSize,
                                                pDecodedMessageOutputStream);
    
        case SEI::PayloadType::SCALABILITY_DIMENSION_INFO:
    
          sei = new SEIScalabilityDimensionInfo;
    
          xParseSEIScalabilityDimensionInfo((SEIScalabilityDimensionInfo &) *sei, payloadSize, pDecodedMessageOutputStream);
    
        case SEI::PayloadType::GREEN_METADATA:
    
          sei = new SEIGreenMetadataInfo;
    
          xParseSEIGreenMetadataInfo((SEIGreenMetadataInfo &) *sei, payloadSize, pDecodedMessageOutputStream);
    
          break;
    
        case SEI::PayloadType::MULTIVIEW_ACQUISITION_INFO:
    
          sei = new SEIMultiviewAcquisitionInfo;
    
          xParseSEIMultiviewAcquisitionInfo((SEIMultiviewAcquisitionInfo &) *sei, payloadSize, pDecodedMessageOutputStream);
    
        case SEI::PayloadType::MULTIVIEW_VIEW_POSITION:
    
          sei = new SEIMultiviewViewPosition;
    
          xParseSEIMultiviewViewPosition((SEIMultiviewViewPosition &) *sei, payloadSize, pDecodedMessageOutputStream);
    
        case SEI::PayloadType::ALPHA_CHANNEL_INFO:
    
          sei = new SEIAlphaChannelInfo;
    
          xParseSEIAlphaChannelInfo((SEIAlphaChannelInfo &) *sei, payloadSize, pDecodedMessageOutputStream);
    
        case SEI::PayloadType::DEPTH_REPRESENTATION_INFO:
    
          sei = new SEIDepthRepresentationInfo;
    
          xParseSEIDepthRepresentationInfo((SEIDepthRepresentationInfo &) *sei, payloadSize, pDecodedMessageOutputStream);
    
        case SEI::PayloadType::SUBPICTURE_LEVEL_INFO:
    
          sei = new SEISubpicureLevelInfo;
    
          xParseSEISubpictureLevelInfo((SEISubpicureLevelInfo &) *sei, payloadSize, pDecodedMessageOutputStream);
    
        case SEI::PayloadType::SAMPLE_ASPECT_RATIO_INFO:
    
          sei = new SEISampleAspectRatioInfo;
    
          xParseSEISampleAspectRatioInfo((SEISampleAspectRatioInfo &) *sei, payloadSize, pDecodedMessageOutputStream);
    
        case SEI::PayloadType::USER_DATA_REGISTERED_ITU_T_T35:
    
    Taoran Lu's avatar
    Taoran Lu committed
          sei = new SEIUserDataRegistered;
    
          xParseSEIUserDataRegistered((SEIUserDataRegistered &) *sei, payloadSize, pDecodedMessageOutputStream);
    
    Taoran Lu's avatar
    Taoran Lu committed
          break;
    
        case SEI::PayloadType::FILM_GRAIN_CHARACTERISTICS:
    
    Taoran Lu's avatar
    Taoran Lu committed
          sei = new SEIFilmGrainCharacteristics;
    
          xParseSEIFilmGrainCharacteristics((SEIFilmGrainCharacteristics &) *sei, payloadSize, pDecodedMessageOutputStream);
    
    Taoran Lu's avatar
    Taoran Lu committed
          break;
    
        case SEI::PayloadType::CONTENT_LIGHT_LEVEL_INFO:
    
    Taoran Lu's avatar
    Taoran Lu committed
          sei = new SEIContentLightLevelInfo;
    
          xParseSEIContentLightLevelInfo((SEIContentLightLevelInfo &) *sei, payloadSize, pDecodedMessageOutputStream);
    
    Taoran Lu's avatar
    Taoran Lu committed
          break;
    
        case SEI::PayloadType::AMBIENT_VIEWING_ENVIRONMENT:
    
    Taoran Lu's avatar
    Taoran Lu committed
          sei = new SEIAmbientViewingEnvironment;
    
          xParseSEIAmbientViewingEnvironment((SEIAmbientViewingEnvironment &) *sei, payloadSize,
                                             pDecodedMessageOutputStream);
    
    Taoran Lu's avatar
    Taoran Lu committed
          break;
    
        case SEI::PayloadType::CONTENT_COLOUR_VOLUME:
    
    Taoran Lu's avatar
    Taoran Lu committed
          sei = new SEIContentColourVolume;
    
          xParseSEIContentColourVolume((SEIContentColourVolume &) *sei, payloadSize, pDecodedMessageOutputStream);
    
    Taoran Lu's avatar
    Taoran Lu committed
          break;
    
        case SEI::PayloadType::COLOUR_TRANSFORM_INFO:
    
          sei = new SEIColourTransformInfo;
    
          xParseSEIColourTransformInfo((SEIColourTransformInfo &) *sei, payloadSize, pDecodedMessageOutputStream);
    
    #if JVET_T0056_SEI_MANIFEST
    
        case SEI::PayloadType::SEI_MANIFEST:
    
          sei = new SEIManifest;
    
          xParseSEISEIManifest((SEIManifest&) *sei, payloadSize, pDecodedMessageOutputStream);
    
          break;
    #endif
    #if JVET_T0056_SEI_PREFIX_INDICATION
    
        case SEI::PayloadType::SEI_PREFIX_INDICATION:
    
          sei = new SEIPrefixIndication;
    
          xParseSEISEIPrefixIndication((SEIPrefixIndication&) *sei, payloadSize, pDecodedMessageOutputStream);
    
    #endif
        case SEI::PayloadType::CONSTRAINED_RASL_ENCODING:
    
          sei = new SEIConstrainedRaslIndication;
    
          xParseSEIConstrainedRaslIndication((SEIConstrainedRaslIndication &) *sei, payloadSize,
                                             pDecodedMessageOutputStream);
    
        case SEI::PayloadType::SHUTTER_INTERVAL_INFO:
    
          xParseSEIShutterInterval((SEIShutterIntervalInfo &) *sei, payloadSize, pDecodedMessageOutputStream);
    
        case SEI::PayloadType::NEURAL_NETWORK_POST_FILTER_CHARACTERISTICS:
    
          sei = new SEINeuralNetworkPostFilterCharacteristics;
    
          xParseSEINNPostFilterCharacteristics((SEINeuralNetworkPostFilterCharacteristics &) *sei, payloadSize, sps,
                                               pDecodedMessageOutputStream);
    
            
            
    #if JVET_AB0049
          nnpfcValues.push_back(((SEINeuralNetworkPostFilterCharacteristics*)sei)->m_id);
    #endif
    
        case SEI::PayloadType::NEURAL_NETWORK_POST_FILTER_ACTIVATION:
    
          sei = new SEINeuralNetworkPostFilterActivation;
    
          xParseSEINNPostFilterActivation((SEINeuralNetworkPostFilterActivation &) *sei, payloadSize,
                                          pDecodedMessageOutputStream);
    
    #if JVET_AB0049
    
          nnpfcProcessed = false;
          CHECK(nnpfcValues.size() == 0, "At leaset one NNPFC SEI message should precede NNPFA")
    
          for(int i=0; i<nnpfcValues.size(); ++i)
          {
            if(((SEINeuralNetworkPostFilterCharacteristics*)sei)->m_id == nnpfcValues[i])
            {
              nnpfcProcessed = true;
            }
          }
    
          CHECK(!nnpfcProcessed, "No NNPFC, no NNPFA")
    
          nnpfcProcessed = false;
    #endif 
    
        case SEI::PayloadType::PHASE_INDICATION:
    
          xParseSEIPhaseIndication((SEIPhaseIndication &) *sei, payloadSize, pDecodedMessageOutputStream);
    
        case SEI::PayloadType::SEI_PROCESSING_ORDER:
    
          sei = new SEIProcessingOrderInfo;
    
          xParseSEIProcessingOrder((SEIProcessingOrderInfo &) *sei, payloadSize, pDecodedMessageOutputStream);
    
        default:
          for (uint32_t i = 0; i < payloadSize; i++)
          {
            uint32_t seiByte;
    
            sei_read_code(nullptr, 8, seiByte, "unknown prefix SEI payload byte");
    
          msg(WARNING, "Unknown prefix SEI message (payloadType = %d) was found!\n", payloadType);
    
            (*pDecodedMessageOutputStream) << "Unknown prefix SEI message (payloadType = " << payloadType
                                           << ") was found!\n";
    
        switch (SEI::PayloadType(payloadType))
        {
        case SEI::PayloadType::USER_DATA_UNREGISTERED:
          sei = new SEIuserDataUnregistered;
          xParseSEIuserDataUnregistered((SEIuserDataUnregistered &) *sei, payloadSize, pDecodedMessageOutputStream);
          break;
        case SEI::PayloadType::DECODED_PICTURE_HASH:
          sei = new SEIDecodedPictureHash;
          xParseSEIDecodedPictureHash((SEIDecodedPictureHash &) *sei, payloadSize, pDecodedMessageOutputStream);
          break;
        case SEI::PayloadType::SCALABLE_NESTING:
          sei = new SEIScalableNesting;
          xParseSEIScalableNesting((SEIScalableNesting &) *sei, nalUnitType, nuh_layer_id, payloadSize, vps, sps, hrd,
                                   pDecodedMessageOutputStream);
          break;
        case SEI::PayloadType::FILLER_PAYLOAD:
          sei = new SEIFillerPayload;
          xParseSEIFillerPayload((SEIFillerPayload &) *sei, payloadSize, pDecodedMessageOutputStream);
          break;
        default:
          for (uint32_t i = 0; i < payloadSize; i++)
          {
            uint32_t seiByte;
            sei_read_code(nullptr, 8, seiByte, "unknown suffix SEI payload byte");
          }
          msg(WARNING, "Unknown suffix SEI message (payloadType = %d) was found!\n", payloadType);
          if (pDecodedMessageOutputStream)
          {
            (*pDecodedMessageOutputStream) << "Unknown suffix SEI message (payloadType = " << payloadType
                                           << ") was found!\n";
          }
          break;
    
      if (sei != nullptr)
    
      {
        seis.push_back(sei);
      }
    
      /* By definition the underlying bitstream terminates in a byte-aligned manner.
       * 1. Extract all bar the last MIN(bitsremaining,nine) bits as reserved_payload_extension_data
       * 2. Examine the final 8 bits to determine the payload_bit_equal_to_one marker
       * 3. Extract the remainingreserved_payload_extension_data bits.
       *
       * If there are fewer than 9 bits available, extract them.
       */
      int payloadBitsRemaining = getBitstream()->getNumBitsLeft();
      if (payloadBitsRemaining) /* more_data_in_payload() */
      {
        for (; payloadBitsRemaining > 9; payloadBitsRemaining--)
        {
          uint32_t reservedPayloadExtensionData;
          sei_read_code ( pDecodedMessageOutputStream, 1, reservedPayloadExtensionData, "reserved_payload_extension_data");
        }
    
        /* 2 */
        int finalBits = getBitstream()->peekBits(payloadBitsRemaining);
        int finalPayloadBits = 0;
        for (int mask = 0xff; finalBits & (mask >> finalPayloadBits); finalPayloadBits++)
        {
          continue;
        }
    
        /* 3 */
        for (; payloadBitsRemaining > 9 - finalPayloadBits; payloadBitsRemaining--)
        {
          uint32_t reservedPayloadExtensionData;
          sei_read_flag ( 0, reservedPayloadExtensionData, "reserved_payload_extension_data");
        }
    
        uint32_t dummy;
        sei_read_flag( 0, dummy, "payload_bit_equal_to_one"); payloadBitsRemaining--;
        while (payloadBitsRemaining)
        {
          sei_read_flag( 0, dummy, "payload_bit_equal_to_zero"); payloadBitsRemaining--;
        }
      }
    
      /* restore primary bitstream for sei_message */
      delete getBitstream();
      setBitstream(bs);
    }
    
    
    Sees's avatar
    Sees committed
    void SEIReader::xParseSEIFillerPayload(SEIFillerPayload &sei, uint32_t payloadSize, std::ostream *pDecodedMessageOutputStream)
    {
    
      output_sei_message_header(sei, pDecodedMessageOutputStream, payloadSize);
    
    
    Sees's avatar
    Sees committed
      for (uint32_t i = 0; i < payloadSize; i++)
      {
    
    Sees's avatar
    Sees committed
        sei_read_code( nullptr, 8, val, "ff_byte");
    
        CHECK(val != 0xff, "ff_byte shall be a byte having the value 0xFF");
    
    /**
     * parse bitstream bs and unpack a user_data_unregistered SEI message
     * of payloasSize bytes into sei.
     */
    
    void SEIReader::xParseSEIuserDataUnregistered(SEIuserDataUnregistered &sei, uint32_t payloadSize, std::ostream *pDecodedMessageOutputStream)
    {
      CHECK(payloadSize < ISO_IEC_11578_LEN, "Payload too small");
      uint32_t val;
      output_sei_message_header(sei, pDecodedMessageOutputStream, payloadSize);
    
      for (uint32_t i = 0; i < ISO_IEC_11578_LEN; i++)
      {
        sei_read_code( pDecodedMessageOutputStream, 8, val, "uuid_iso_iec_11578");
        sei.uuid_iso_iec_11578[i] = val;
      }
    
      sei.userDataLength = payloadSize - ISO_IEC_11578_LEN;
      if (!sei.userDataLength)
      {
        sei.userData = 0;
        return;
      }
    
      sei.userData = new uint8_t[sei.userDataLength];
      for (uint32_t i = 0; i < sei.userDataLength; i++)
      {
    
        sei_read_code(nullptr, 8, val, "user_data_payload_byte");
    
        sei.userData[i] = val;
      }
      if (pDecodedMessageOutputStream)
      {
        (*pDecodedMessageOutputStream) << "  User data payload size: " << sei.userDataLength << "\n";
      }
    }
    
    
    void SEIReader::xParseSEIShutterInterval(SEIShutterIntervalInfo& sei, uint32_t payloadSize, std::ostream *pDecodedMessageOutputStream)
    {
      int32_t i;
      uint32_t val;
      output_sei_message_header(sei, pDecodedMessageOutputStream, payloadSize);
      sei_read_code(pDecodedMessageOutputStream, 32, val, "sii_time_scale");                      sei.m_siiTimeScale = val;
      sei_read_flag(pDecodedMessageOutputStream, val, "fixed_shutter_interval_within_clvs_flag"); sei.m_siiFixedSIwithinCLVS = val;
      if (sei.m_siiFixedSIwithinCLVS)
      {
        sei_read_code(pDecodedMessageOutputStream, 32, val, "sii_num_units_in_shutter_interval");   sei.m_siiNumUnitsInShutterInterval = val;
      }
      else
      {
        sei_read_code(pDecodedMessageOutputStream, 3, val, "sii_max_sub_layers_minus1 ");          sei.m_siiMaxSubLayersMinus1 = val;
        sei.m_siiSubLayerNumUnitsInSI.resize(sei.m_siiMaxSubLayersMinus1 + 1);
        for (i = 0; i <= sei.m_siiMaxSubLayersMinus1; i++)
        {
          sei_read_code(pDecodedMessageOutputStream, 32, val, "sub_layer_num_units_in_shutter_interval[ i ]");
          sei.m_siiSubLayerNumUnitsInSI[i] = val;
        }
      }
    }
    
    
    void SEIReader::xParseSEIProcessingOrder(SEIProcessingOrderInfo& sei, uint32_t payloadSize, std::ostream *decodedMessageOutputStream)
    {
      uint32_t i,b;
      uint32_t NumSEIMessages, val;
      output_sei_message_header(sei, decodedMessageOutputStream, payloadSize);
      //Here payload is in Bytes, Since "sei_payloadType" is 2 Bytes + "sei_payloadOrder" is 1 Byte so total = 3 Bytes
      //To get Number of SEI messages, just do payloadSize/3
      NumSEIMessages = payloadSize / 3;
      sei.m_posPayloadType.resize(NumSEIMessages);
      sei.m_posProcessingOrder.resize(NumSEIMessages);
      for(i=0,b=0; b < payloadSize; i++,b+=3)
      {
        sei_read_code(decodedMessageOutputStream, 16, val, "sei_payloadType[i]");
        sei.m_posPayloadType[i] = val;
    
    #if JVET_AB0069_SEI_PROCESSING_ORDER
        sei_read_code(decodedMessageOutputStream, 16, val, "sei_processingOrder[i]");
    #else
    
        sei_read_code(decodedMessageOutputStream, 8, val, "sei_processingOrder[i]");
    
        sei.m_posProcessingOrder[i] = val;
      }
    }
    
    
    /**
     * parse bitstream bs and unpack a decoded picture hash SEI message
     * of payloadSize bytes into sei.
     */
    void SEIReader::xParseSEIDecodedPictureHash(SEIDecodedPictureHash& sei, uint32_t payloadSize, std::ostream *pDecodedMessageOutputStream)
    {
      uint32_t bytesRead = 0;
      output_sei_message_header(sei, pDecodedMessageOutputStream, payloadSize);
    
      uint32_t val;
    
      sei_read_code( pDecodedMessageOutputStream, 8, val, "dph_sei_hash_type");
    
      sei.method = static_cast<HashType>(val); bytesRead++;
    
      sei_read_code( pDecodedMessageOutputStream, 1, val, "dph_sei_single_component_flag");
      sei.singleCompFlag = val;
      sei_read_code( pDecodedMessageOutputStream, 7, val, "dph_sei_reserved_zero_7bits");
      bytesRead++;
    
      uint32_t expectedSize =
        (sei.singleCompFlag ? 1 : 3) * (sei.method == HashType::MD5 ? 16 : (sei.method == HashType::CRC ? 2 : 4));
    
      CHECK ((payloadSize - bytesRead) != expectedSize, "The size of the decoded picture hash does not match the expected size.");
    
      case HashType::MD5:
        traceString = "picture_md5";
        break;
      case HashType::CRC:
        traceString = "picture_crc";
        break;
      case HashType::CHECKSUM:
        traceString = "picture_checksum";
        break;
      default:
        THROW("Unknown hash type");
        break;
    
      }
    
      if (pDecodedMessageOutputStream)
      {
        (*pDecodedMessageOutputStream) << "  " << std::setw(55) << traceString << ": " << std::hex << std::setfill('0');
      }
    
      sei.m_pictureHash.hash.clear();
      for(;bytesRead < payloadSize; bytesRead++)
      {
    
        sei_read_code(nullptr, 8, val, traceString);
    
        sei.m_pictureHash.hash.push_back((uint8_t)val);
        if (pDecodedMessageOutputStream)
        {
          (*pDecodedMessageOutputStream) << std::setw(2) << val;
        }
      }
    
      if (pDecodedMessageOutputStream)
      {
        (*pDecodedMessageOutputStream) << std::dec << std::setfill(' ') << "\n";
      }
    }
    
    
    void SEIReader::xParseSEIScalableNesting(SEIScalableNesting& sei, const NalUnitType nalUnitType, const uint32_t nuhLayerId, uint32_t payloadSize, const VPS* vps, const SPS* sps, HRD &hrd, std::ostream* decodedMessageOutputStream)
    
      SEIMessages seis;
    
      output_sei_message_header(sei, decodedMessageOutputStream, payloadSize);
    
      sei_read_flag(decodedMessageOutputStream, symbol, "sn_ols_flag"); sei.m_snOlsFlag = symbol;
    
      sei_read_flag(decodedMessageOutputStream, symbol, "sn_subpic_flag"); sei.m_snSubpicFlag = symbol;
    
        sei_read_uvlc(decodedMessageOutputStream, symbol, "sn_num_olss_minus1"); sei.m_snNumOlssMinus1 = symbol;
        for (uint32_t i = 0; i <= sei.m_snNumOlssMinus1; i++)
    
          sei_read_uvlc(decodedMessageOutputStream, symbol, "sn_ols_idx_delta_minus1[i]"); sei.m_snOlsIdxDeltaMinus1[i] = symbol;
    
        for (uint32_t i = 0; i <= sei.m_snNumOlssMinus1; i++)
    
            sei.m_snOlsIdx[i] = sei.m_snOlsIdxDeltaMinus1[i];
    
            sei.m_snOlsIdx[i] = sei.m_snOlsIdxDeltaMinus1[i] + sei.m_snOlsIdxDeltaMinus1[i - 1] + 1;
    
          for (uint32_t olsIdxForSEI = 0; olsIdxForSEI <= sei.m_snNumOlssMinus1; olsIdxForSEI++)
    
            int olsIdx = sei.m_snOlsIdx[olsIdxForSEI];
    
            for (int layerIdx = 0; layerIdx < vps->getNumLayersInOls(olsIdx); layerIdx++)
    
              if (lowestLayerId > vps->getLayerIdInOls(olsIdx, layerIdx))
              {
                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");
    
        sei_read_flag(decodedMessageOutputStream, symbol, "sn_all_layers_flag"); sei.m_snAllLayersFlag = symbol;
        if (!sei.m_snAllLayersFlag)
    
          sei_read_uvlc(decodedMessageOutputStream, symbol, "sn_num_layers_minus1"); sei.m_snNumLayersMinus1 = symbol;
    
          sei.m_snLayerId[0] = nuhLayerId;
          for (uint32_t i = 1; i <= sei.m_snNumLayersMinus1; i++)
    
            sei_read_code(decodedMessageOutputStream, 6, symbol, "sn_layer_id[i]"); sei.m_snLayerId[i] = symbol;
    
      if (sei.m_snSubpicFlag)
      {
        sei_read_uvlc(decodedMessageOutputStream, symbol, "sn_num_subpics_minus1"); sei.m_snNumSubpics = symbol + 1;
        sei_read_uvlc(decodedMessageOutputStream, symbol, "sn_subpic_id_len_minus1"); sei.m_snSubpicIdLen = symbol + 1;
        sei.m_snSubpicId.resize(sei.m_snNumSubpics);
        for (uint32_t i = 0; i < sei.m_snNumSubpics; i++)
        {
          sei_read_code(decodedMessageOutputStream, sei.m_snSubpicIdLen, symbol, "sn_subpic_id[i]"); sei.m_snSubpicId[i] = symbol;
        }
      }
    
      sei_read_uvlc(decodedMessageOutputStream, symbol, "sn_num_seis_minus1"); sei.m_snNumSEIs = symbol + 1;
      CHECK (sei.m_snNumSEIs > 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");
    
      // read nested SEI messages
      for (int32_t i=0; i<sei.m_snNumSEIs; i++)
      {
        SEIMessages tmpSEIs;
        xReadSEImessage(tmpSEIs, nalUnitType, nuhLayerId, 0, vps, sps, m_nestedHrd, decodedMessageOutputStream);
    
        if (tmpSEIs.front()->payloadType() == SEI::PayloadType::BUFFERING_PERIOD)
    
        {
          SEIBufferingPeriod *bp = (SEIBufferingPeriod*) tmpSEIs.front();
          m_nestedHrd.setBufferingPeriodSEI(bp);
    
          const SEIBufferingPeriod *nonNestedBp = hrd.getBufferingPeriodSEI();
          if (nonNestedBp)
          {
            checkBPSyntaxElementLength(nonNestedBp, bp);
          }
    
        }
        sei.m_nestedSEIs.push_back(tmpSEIs.front());
        tmpSEIs.clear();
      }
    
    
      xCheckScalableNestingConstraints(sei, nalUnitType, vps);
    
      if (decodedMessageOutputStream)
      {
        (*decodedMessageOutputStream) << "End of scalable nesting SEI message\n";
      }
    }
    
    
    
    void SEIReader::xParseSEIGreenMetadataInfo(SEIGreenMetadataInfo& sei, uint32_t payloadSize, std::ostream *pDecodedMessageOutputStream)
    {
      uint32_t code;
      output_sei_message_header(sei, pDecodedMessageOutputStream, payloadSize);
      sei_read_code(pDecodedMessageOutputStream, 8, code, "green_metadata_type");
      sei.m_greenMetadataType = code;
      printf("GREEN MPEG Output: \n");
      printf("Metadata Type: %i\n", sei.m_greenMetadataType);
    
      switch (sei.m_greenMetadataType)
      {
      case 0:
        sei_read_code(pDecodedMessageOutputStream, 4, code, "period_type");
        sei.m_periodType = code;
        sei_read_code(pDecodedMessageOutputStream, 3, code, "granularity_type");
        sei.m_greenMetadataGranularityType = code;
        sei_read_code(pDecodedMessageOutputStream, 1, code, "extended_representation_flag");
        sei.m_greenMetadataExtendedRepresentation = code;
    
        printf ("Period Type: %i\n",sei.m_periodType);
        printf ("Granularity Type: %i\n",sei.m_greenMetadataGranularityType);
        printf ("Extended Representation Flag Type: %i\n",sei.m_greenMetadataExtendedRepresentation);
    
        if (sei.m_periodType == 2)
        {
          sei_read_code(pDecodedMessageOutputStream, 16, code, "num_seconds");
          sei.m_numSeconds = code;
          printf ("Number of Seconds: %i\n",sei.m_numSeconds);
        }
        else if (sei.m_periodType == 3)
        {
          sei_read_code(pDecodedMessageOutputStream, 16, code, "num_pictures");
          sei.m_numPictures = code;
          printf ("Number of Pictures: %i\n",sei.m_numPictures);
        }
    
        if (sei.m_greenMetadataGranularityType == 0)
        {
          sei_read_code(pDecodedMessageOutputStream, 8, code, "portion_non_zero_blocks_area");
          sei.m_greenComplexityMetrics.portionNonZeroBlocksArea = code;
          sei_read_code(pDecodedMessageOutputStream, 8, code, "portion_non_zero_transform_coefficients_area");
          sei.m_greenComplexityMetrics.portionNonZeroTransformCoefficientsArea = code;
          sei_read_code(pDecodedMessageOutputStream, 8, code, "portion_intra_predicted_blocks_area");
          sei.m_greenComplexityMetrics.portionIntraPredictedBlocksArea = code;
          sei_read_code(pDecodedMessageOutputStream, 8, code, "portion_deblocking_instances");
          sei.m_greenComplexityMetrics.portionDeblockingInstances = code;
          sei_read_code(pDecodedMessageOutputStream, 8, code, "portion_alf_instances");
          sei.m_greenComplexityMetrics.portionAlfInstances = code;
    
          printf ("Portion Non Zero Blocks Area: %i\n",sei.m_greenComplexityMetrics.portionNonZeroBlocksArea);
          printf ("Portion Non Zero Transform Coefficients Area: %i\n",sei.m_greenComplexityMetrics.portionNonZeroTransformCoefficientsArea);
          printf ("Portion Intra Predicted Blocks Area: %i\n",sei.m_greenComplexityMetrics.portionIntraPredictedBlocksArea);
          printf ("Portion Deblocking Instances: %i\n",sei.m_greenComplexityMetrics.portionDeblockingInstances);
          printf ("Portion ALF Instances: %i\n",sei.m_greenComplexityMetrics.portionAlfInstances);
    
          if(sei.m_greenMetadataExtendedRepresentation == 1)
          {
            if(sei.m_greenComplexityMetrics.portionNonZeroBlocksArea != 0)
            {
              sei_read_code(pDecodedMessageOutputStream, 8, code, "portion_non_zero_4_8_16_blocks_area");
              sei.m_greenComplexityMetrics.portionNonZero_4_8_16BlocksArea = code;
              sei_read_code(pDecodedMessageOutputStream, 8, code, "portion_non_zero_32_64_128_blocks_area");
              sei.m_greenComplexityMetrics.portionNonZero_32_64_128BlocksArea = code;
              sei_read_code(pDecodedMessageOutputStream, 8, code, "portion_non_zero_256_512_1024_blocks_area");
              sei.m_greenComplexityMetrics.portionNonZero_256_512_1024BlocksArea = code;
              sei_read_code(pDecodedMessageOutputStream, 8, code, "portion_non_zero_2048_4096_blocks_area");
              sei.m_greenComplexityMetrics.portionNonZero_2048_4096BlocksArea = code;
              printf ("Portion Non Zero 4/8/16 Blocks Area: %i\n",sei.m_greenComplexityMetrics.portionNonZero_4_8_16BlocksArea);
              printf ("Portion Non Zero 32/64/128 Blocks Area: %i\n",sei.m_greenComplexityMetrics.portionNonZero_32_64_128BlocksArea);
              printf ("Portion Non Zero 256/512/1024 Blocks Area: %i\n",sei.m_greenComplexityMetrics.portionNonZero_256_512_1024BlocksArea);
              printf ("Portion Non Zero 2048/4096 Blocks Area: %i\n",sei.m_greenComplexityMetrics.portionNonZero_2048_4096BlocksArea);
            }
    
            if(sei.m_greenComplexityMetrics.portionIntraPredictedBlocksArea < 255)
            {
              sei_read_code(pDecodedMessageOutputStream, 8, code, "portion_bi_and_gpm_predicted_blocks_area");
              sei.m_greenComplexityMetrics.portionBiAndGpmPredictedBlocksArea = code;
              sei_read_code(pDecodedMessageOutputStream, 8, code, "portion_bdof_blocks_area");
              sei.m_greenComplexityMetrics.portionBdofBlocksArea = code;
              printf ("Portion BI and GPM Predicted Blocks Area: %i\n",sei.m_greenComplexityMetrics.portionBiAndGpmPredictedBlocksArea);
              printf ("Portion BDOF Blocks Area: %i\n",sei.m_greenComplexityMetrics.portionBdofBlocksArea);
            }
    
            sei_read_code(pDecodedMessageOutputStream, 8, code, "portion_sao_instances");
            sei.m_greenComplexityMetrics.portionSaoInstances = code;
            printf ("Portion SAO Instances: %i\n",sei.m_greenComplexityMetrics.portionSaoInstances);
          }
        }
        break;
      case 1:
        sei_read_code(pDecodedMessageOutputStream, 16, code, "xsd_subpic_number_minus1");
        sei.m_xsdSubpicNumberMinus1 = code;
        printf("XSD Subpic Number of Metrics: %i\n", sei.m_xsdSubpicNumberMinus1 + 1);
    
        int xsdSubpicIdc;
        int xsdMetricNumberMinus1;
    
        for (int i = 0; i <= sei.m_xsdSubpicNumberMinus1; i++)
        {
          sei_read_code(pDecodedMessageOutputStream, 16, code, "xsd_subpic_idc[i]");
          xsdSubpicIdc = code;
          printf("XSD Subpic Idc[i]: %i\n", xsdSubpicIdc);
    
          sei_read_code(pDecodedMessageOutputStream, 8, code, "xsd_metric_number_minus1[i]");
          xsdMetricNumberMinus1 = code;
          printf("XSD Metric Number Minus1[i]: %i\n", xsdMetricNumberMinus1);
    
          int xsdMetricType;
          int xsdMetricValue;
          for (int j = 0; j <= xsdMetricNumberMinus1; j++)
          {
            sei_read_code(pDecodedMessageOutputStream, 8, code, "xsd_metric_type[i][j]");
            xsdMetricType = code;
    
            sei_read_code(pDecodedMessageOutputStream, 16, code, "xsd_metric_value[i][j]");
            xsdMetricValue = code;
    
            switch (xsdMetricType)
            {
            case 0: //PSNR
              sei.m_xsdMetricValuePSNR = code;
              printf("PSNR value: %0.2f\n", (double(xsdMetricValue)/100.0));
              break;
            case 1: //SSIM
              sei.m_xsdMetricValueSSIM = code;
              printf("SSIM value: %0.2f\n", double(xsdMetricValue/100.0));
              break;
            case 2:  //W-PSNR
              sei.m_xsdMetricValueWPSNR = code;
              printf("W-PSNR value: %0.2f\n", double(xsdMetricValue/100.0));
              break;
            case 3: //WS-PSNR
              sei.m_xsdMetricValueWSPSNR = code;
              printf("WS-PSNR value: %0.2f\n", double(xsdMetricValue/100.0));
              break;
            default: //User Defined
              break;
            }
          }
        }
        break;
      }
    }
    
    
    void SEIReader::xParseSEIScalableNestingBinary(SEIScalableNesting &sei, 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)
    
    Yang Wang's avatar
    Yang Wang committed
    {
      uint32_t symbol;
      SEIMessages seis;
      output_sei_message_header(sei, decodedMessageOutputStream, payloadSize);
    
      sei_read_flag(decodedMessageOutputStream, symbol, "sn_ols_flag"); sei.m_snOlsFlag = symbol;
      sei_read_flag(decodedMessageOutputStream, symbol, "sn_subpic_flag"); sei.m_snSubpicFlag = symbol;
      if (sei.m_snOlsFlag)
      {
        sei_read_uvlc(decodedMessageOutputStream, symbol, "sn_num_olss_minus1"); sei.m_snNumOlssMinus1 = symbol;
        for (uint32_t i = 0; i <= sei.m_snNumOlssMinus1; i++)
        {
          sei_read_uvlc(decodedMessageOutputStream, symbol, "sn_ols_idx_delta_minus1[i]"); sei.m_snOlsIdxDeltaMinus1[i] = symbol;
        }