/* 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-2023, 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. */ #pragma once #ifndef __PARAMETERSETMANAGER__ #define __PARAMETERSETMANAGER__ #include "Slice.h" #include void calculateParameterSetChangedFlag(bool &changed, const std::vector *pOldData, const std::vector *pNewData); template class ParameterSetMap { public: template struct MapData { bool changed; std::vector *pNaluData; // Can be null Tm* parameterSet; }; ParameterSetMap(int maxId = 0) : m_maxId(maxId), m_lastActiveParameterSet(nullptr) { m_activePsId.clear(); } ~ParameterSetMap() { for (typename std::map >::iterator i = m_paramsetMap.begin(); i!= m_paramsetMap.end(); i++) { delete (*i).second.pNaluData; delete (*i).second.parameterSet; } delete m_lastActiveParameterSet; m_lastActiveParameterSet = nullptr; } T *allocatePS(const int psId) { CHECK( psId >= m_maxId, "Invalid PS id" ); if ( m_paramsetMap.find(psId) == m_paramsetMap.end() ) { m_paramsetMap[psId].changed = true; m_paramsetMap[psId].pNaluData=0; m_paramsetMap[psId].parameterSet = new T; setID(m_paramsetMap[psId].parameterSet, psId); } return m_paramsetMap[psId].parameterSet; } void clearMap() { m_paramsetMap.clear(); } void storePS( int psId, T *ps ) { CHECK( psId >= m_maxId, "Invalid PS id" ); if( m_paramsetMap.find( psId ) != m_paramsetMap.end() ) { delete m_paramsetMap[psId].parameterSet; } m_paramsetMap[psId].parameterSet = ps; m_paramsetMap[psId].changed = true; } void storePS(int psId, T *ps, const std::vector *pNaluData) { CHECK( psId >= m_maxId, "Invalid PS id" ); if ( m_paramsetMap.find(psId) != m_paramsetMap.end() ) { MapData &mapData=m_paramsetMap[psId]; // work out changed flag calculateParameterSetChangedFlag(mapData.changed, mapData.pNaluData, pNaluData); if (!mapData.changed) { // just keep the old one delete ps; return; } if (find(m_activePsId.begin(), m_activePsId.end(), psId) != m_activePsId.end()) { std::swap( m_paramsetMap[psId].parameterSet, m_lastActiveParameterSet ); } delete m_paramsetMap[psId].pNaluData; delete m_paramsetMap[psId].parameterSet; m_paramsetMap[psId].parameterSet = ps; } else { m_paramsetMap[psId].parameterSet = ps; m_paramsetMap[psId].changed = false; } if (pNaluData != 0) { m_paramsetMap[psId].pNaluData=new std::vector; *(m_paramsetMap[psId].pNaluData) = *pNaluData; } else { m_paramsetMap[psId].pNaluData=0; } } void checkAuApsContent( APS *aps, std::vector& accessUnitApsNals ) { int apsId = aps->getAPSId(); if (std::find(accessUnitApsNals.begin(), accessUnitApsNals.end(), apsId) != accessUnitApsNals.end()) { CHECK( m_paramsetMap.find( apsId ) == m_paramsetMap.end(), "APS does not exist" ); APS* existedAPS = m_paramsetMap[apsId].parameterSet; bool sameNalUnitType = aps->getHasPrefixNalUnitType() == existedAPS->getHasPrefixNalUnitType(); bool samePU = aps->getLayerId() == existedAPS->getLayerId(); if (aps->getAPSType() == ApsType::LMCS) { CHECK( samePU && sameNalUnitType && aps->getReshaperAPSInfo() != existedAPS->getReshaperAPSInfo(), "All APS NAL units with a particular value of nal_unit_type, a particular value of aps_adaptation_parameter_set_id, and a particular value of aps_params_type within a PU shall have the same content" ); } else if (aps->getAPSType() == ApsType::ALF) { CHECK( samePU && sameNalUnitType && aps->getAlfAPSParam() != existedAPS->getAlfAPSParam(), "All APS NAL units with a particular value of nal_unit_type, a particular value of aps_adaptation_parameter_set_id, and a particular value of aps_params_type within a PU shall have the same content" ); } else if (aps->getAPSType() == ApsType::SCALING_LIST) { CHECK( samePU && sameNalUnitType && aps->getScalingList() != existedAPS->getScalingList(), "All APS NAL units with a particular value of nal_unit_type, a particular value of aps_adaptation_parameter_set_id, and a particular value of aps_params_type within a PU shall have the same content" ); } else { THROW("Wrong APS type"); } } else { accessUnitApsNals.push_back( apsId ); } } void setChangedFlag(int psId, bool changed = true) { if ( m_paramsetMap.find(psId) != m_paramsetMap.end() ) { m_paramsetMap[psId].changed = changed; } } void clearChangedFlag(int psId) { if ( m_paramsetMap.find(psId) != m_paramsetMap.end() ) { m_paramsetMap[psId].changed = false; } } bool getChangedFlag(int psId) const { const typename std::map >::const_iterator constit=m_paramsetMap.find(psId); if ( constit != m_paramsetMap.end() ) { return constit->second.changed; } return false; } T* getPS(int psId) { typename std::map >::iterator it=m_paramsetMap.find(psId); return (it == m_paramsetMap.end()) ? nullptr : (it)->second.parameterSet; } const T* getPS(int psId) const { typename std::map >::const_iterator it=m_paramsetMap.find(psId); return (it == m_paramsetMap.end()) ? nullptr : (it)->second.parameterSet; } T* getFirstPS() { return (m_paramsetMap.begin() == m_paramsetMap.end()) ? nullptr : m_paramsetMap.begin()->second.parameterSet; } void setActive(int psId) { m_activePsId.push_back(psId); } void clearActive() { m_activePsId.clear(); } private: std::map > m_paramsetMap; int m_maxId; std::vector m_activePsId; T* m_lastActiveParameterSet; static void setID(T* parameterSet, const int psId); }; class ParameterSetManager { public: ParameterSetManager(); virtual ~ParameterSetManager(); // store video parameter set and take ownership of it // warning: vps object cannot be used after storing (repeated parameter sets are directly deleted) void storeVPS(VPS *vps, const std::vector &naluData) { m_vpsMap.storePS(vps->getVPSId(), vps, &naluData); } VPS* getVPS( int vpsId ); // store sequence parameter set and take ownership of it // warning: sps object cannot be used after storing (repeated parameter sets are directly deleted) void storeSPS(SPS *sps, const std::vector &naluData) { m_spsMap.storePS( sps->getSPSId(), sps, &naluData); }; // get pointer to existing sequence parameter set SPS* getSPS(int spsId) { return m_spsMap.getPS(spsId); }; bool getSPSChangedFlag(int spsId) const { return m_spsMap.getChangedFlag(spsId); } void clearSPSChangedFlag(int spsId) { m_spsMap.clearChangedFlag(spsId); } SPS* getFirstSPS() { return m_spsMap.getFirstPS(); }; // store picture parameter set and take ownership of it // warning: pps object cannot be used after storing (repeated parameter sets are directly deleted) void storePPS(PPS *pps, const std::vector &naluData) { m_ppsMap.storePS( pps->getPPSId(), pps, &naluData); }; // get pointer to existing picture parameter set PPS* getPPS(int ppsId) { return m_ppsMap.getPS(ppsId); }; bool getPPSChangedFlag(int ppsId) const { return m_ppsMap.getChangedFlag(ppsId); } void clearPPSChangedFlag(int ppsId) { m_ppsMap.clearChangedFlag(ppsId); } PPS* getFirstPPS() { return m_ppsMap.getFirstPS(); }; // activate a PPS and depending on isIRAP parameter also SPS // returns true, if activation is successful bool activatePPS(int ppsId, bool isIRAP); APS** getAPSs() { return &m_apss[0]; } ParameterSetMap *getApsMap(ApsType apsType) { return &m_apsMap[apsType]; } // store adaptation parameter set and take ownership of it // warning: aps object cannot be used after storing (repeated parameter sets are directly deleted) void storeAPS(APS *aps, const std::vector &naluData) { m_apsMap[aps->getAPSType()].storePS(aps->getAPSId(), aps, &naluData); } APS *getAPS(int apsId, ApsType apsType) { return m_apsMap[apsType].getPS(apsId); }; bool getAPSChangedFlag(int apsId, ApsType apsType) const { return m_apsMap[apsType].getChangedFlag(apsId); } void clearAPSChangedFlag(int apsId, ApsType apsType) { m_apsMap[apsType].clearChangedFlag(apsId); } bool activateAPS(uint8_t apsId, ApsType apsType); const SPS* getActiveSPS()const { return m_spsMap.getPS(m_activeSPSId); }; void checkAuApsContent(APS *aps, std::vector &accessUnitApsNals) { m_apsMap[aps->getAPSType()].checkAuApsContent(aps, accessUnitApsNals); } protected: ParameterSetMap m_spsMap; ParameterSetMap m_ppsMap; EnumArray, ApsType> m_apsMap; ParameterSetMap m_vpsMap; APS* m_apss[ALF_CTB_MAX_NUM_APS]; int m_activeSPSId; // -1 for nothing active int m_activeVPSId; // -1 for nothing active }; #endif