diff --git a/cfg/sei_vui/neural_network_post_filter_characteristics.cfg b/cfg/sei_vui/neural_network_post_filter_characteristics.cfg index a69af8b28a519ce9103c47e2fa5b8475abb6ecf0..19a7cd521c7929630aab1ce95a9640a7e48cbc29 100644 --- a/cfg/sei_vui/neural_network_post_filter_characteristics.cfg +++ b/cfg/sei_vui/neural_network_post_filter_characteristics.cfg @@ -6,6 +6,7 @@ SEINNPostFilterCharacteristicsNumFilters: 1 SEINNPostFilterCharacteristicsId0: 1 SEINNPostFilterCharacteristicsModeIdc0: 1 SEINNPostFilterCharacteristicsPropertyPresentFlag0: 1 +SEINNPostFilterCharacteristicsBaseFlag0: 1 SEINNPostFilterCharacteristicsPurpose0: 2 SEINNPostFilterCharacteristicsOutSubCFlag0: 1 SEINNPostFilterCharacteristicsComponentLastFlag0: 0 diff --git a/doc/software-manual.tex b/doc/software-manual.tex index 28627fb0c4d90f50913da764fd46487db4deb209..2b3f5837d0c843dcc32a1030c651b83214e0c1d0 100644 --- a/doc/software-manual.tex +++ b/doc/software-manual.tex @@ -5702,6 +5702,10 @@ Specifies sii_num_units_in_shutter_interval for single entry.If multiple entries \Default{false} & When true (non-zero) specifies, for the \emph{i}-th neural network post-filter, that the filter input formatting, output formatting, and complexity are present. \\ + \Option{SEINNPostFilterCharacteristicsBaseFlag\emph{i}} & + \Default{false} & + When true (non-zero) specifies, for the \emph{i}-th neural network post-filter, that the filter is a base filter. + \\ \Option{SEINNPostFilterCharacteristicsPurpose\emph{i}} & \Default{0} & Specifies the purpose of the \emph{i}-th neural network post-filter. diff --git a/source/App/EncoderApp/EncApp.cpp b/source/App/EncoderApp/EncApp.cpp index 2f8957421f60bacbf5ef9f46808c9400dfee2fd6..f3b313e8bd9579e6790b8c953a9507ecacb76116 100644 --- a/source/App/EncoderApp/EncApp.cpp +++ b/source/App/EncoderApp/EncApp.cpp @@ -1187,6 +1187,22 @@ void EncApp::xInitLibCfg( int layerIdx ) m_cEncLib.setNNPostFilterSEICharacteristicsPropertyPresentFlag( m_nnPostFilterSEICharacteristicsPropertyPresentFlag[i], i); if (m_cEncLib.getNNPostFilterSEICharacteristicsPropertyPresentFlag(i)) { +#if JVET_AC0353_NNPFC_BASE_FLAG + m_cEncLib.setNNPostFilterSEICharacteristicsBaseFlag (m_nnPostFilterSEICharacteristicsBaseFlag[i], i); + if (!m_nnPostFilterSEICharacteristicsBaseFlag[i]) + { + bool baseFilterExist = false; + for (int j = i - 1; j >= 0; j--) + { + if (m_cEncLib.getNNPostFilterSEICharacteristicsId(i) == m_cEncLib.getNNPostFilterSEICharacteristicsId(j)) + { + baseFilterExist = true; + break; + } + } + CHECK(!baseFilterExist, "No base filter found! Cannot have an update filter without base filter.") + } +#endif m_cEncLib.setNNPostFilterSEICharacteristicsPurpose (m_nnPostFilterSEICharacteristicsPurpose[i], i); #if JVET_AC0127_BIT_MASKING_NNPFC_PURPOSE if ((m_cEncLib.getNNPostFilterSEICharacteristicsPurpose(i) & NNPC_PurposeType::CHROMA_UPSAMPLING) != 0) diff --git a/source/App/EncoderApp/EncAppCfg.cpp b/source/App/EncoderApp/EncAppCfg.cpp index 4e92b0777a3ffca2ee8e7e6cfaf7aae72a0a823e..25fba20940f5aef5c70fce281223ff31f3176a47 100644 --- a/source/App/EncoderApp/EncAppCfg.cpp +++ b/source/App/EncoderApp/EncAppCfg.cpp @@ -1771,6 +1771,12 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] ) propertyPresentFlag << "SEINNPostFilterCharacteristicsPropertyPresentFlag" << i; opts.addOptions()(propertyPresentFlag.str(), m_nnPostFilterSEICharacteristicsPropertyPresentFlag[i], false, "Specifies whether the filter purpose, input formatting, output formatting and complexity are present in the Neural Network Post Filter Characteristics SEI message"); +#if JVET_AC0353_NNPFC_BASE_FLAG + std::ostringstream nnpfcBaseFlag; + nnpfcBaseFlag << "SEINNPostFilterCharacteristicsBaseFlag" << i; + opts.addOptions()(nnpfcBaseFlag.str(), m_nnPostFilterSEICharacteristicsBaseFlag[i], false, "Specifies whether the filter is a base filter or not"); +#endif + std::ostringstream purpose; purpose << "SEINNPostFilterCharacteristicsPurpose" << i; opts.addOptions()(purpose.str(), m_nnPostFilterSEICharacteristicsPurpose[i], 0u, "Specifies the purpose in the Neural Network Post Filter Characteristics SEI message"); diff --git a/source/App/EncoderApp/EncAppCfg.h b/source/App/EncoderApp/EncAppCfg.h index b7c278083f636ccde1536929f53278b47354ebb6..ce088b438269f251e060e0a9b00182ad00a30201 100644 --- a/source/App/EncoderApp/EncAppCfg.h +++ b/source/App/EncoderApp/EncAppCfg.h @@ -732,6 +732,9 @@ protected: uint32_t m_nnPostFilterSEICharacteristicsId[MAX_NUM_NN_POST_FILTERS]; uint32_t m_nnPostFilterSEICharacteristicsModeIdc[MAX_NUM_NN_POST_FILTERS]; bool m_nnPostFilterSEICharacteristicsPropertyPresentFlag[MAX_NUM_NN_POST_FILTERS]; +#if JVET_AC0353_NNPFC_BASE_FLAG + bool m_nnPostFilterSEICharacteristicsBaseFlag[MAX_NUM_NN_POST_FILTERS]; +#endif uint32_t m_nnPostFilterSEICharacteristicsPurpose[MAX_NUM_NN_POST_FILTERS]; bool m_nnPostFilterSEICharacteristicsOutSubCFlag[MAX_NUM_NN_POST_FILTERS]; #if JVET_AC0154 diff --git a/source/Lib/CommonLib/SEI.h b/source/Lib/CommonLib/SEI.h index 821b2ed21f69f05cbbd40e14d3b923f51766abce..58f48aca035601f487e669f44360b983480fe58f 100644 --- a/source/Lib/CommonLib/SEI.h +++ b/source/Lib/CommonLib/SEI.h @@ -1301,6 +1301,9 @@ public: , m_modeIdc(0) , m_propertyPresentFlag(false) , m_purpose(0) +#if JVET_AC0353_NNPFC_BASE_FLAG + , m_baseFlag(false) +#endif , m_outSubCFlag(0) , m_outSubWidthC(1) , m_outSubHeightC(1) @@ -1367,6 +1370,9 @@ public: uint32_t m_modeIdc; bool m_propertyPresentFlag; uint32_t m_purpose; +#if JVET_AC0353_NNPFC_BASE_FLAG + bool m_baseFlag; +#endif bool m_outSubCFlag; uint8_t m_outSubWidthC; uint8_t m_outSubHeightC; diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h index e2c71ddaf72febd9e46307d698413876b420117c..0bee174db3b2f306d1de4ffacc2649dba8658e8f 100644 --- a/source/Lib/CommonLib/TypeDef.h +++ b/source/Lib/CommonLib/TypeDef.h @@ -65,7 +65,7 @@ #define JVET_AC0062_CONSTRAINT_CHECK 1 #define JVET_AC0344_NNPFC_PATCH 1 #define JVET_AC0074_USE_OF_NNPFC_FOR_PIC_RATE_UPSAMPLING 1 - +#define JVET_AC0353_NNPFC_BASE_FLAG 1 //########### place macros to be be kept below this line ############### diff --git a/source/Lib/DecoderLib/SEIread.cpp b/source/Lib/DecoderLib/SEIread.cpp index 54ede8ae6806b85f8767d5933b159d29071f0550..d9aed5b276413c5ea86a03bfa691086f69dbb426 100644 --- a/source/Lib/DecoderLib/SEIread.cpp +++ b/source/Lib/DecoderLib/SEIread.cpp @@ -219,6 +219,38 @@ void SEIReader::getSEIDecodingUnitInfoDuiIdx(InputBitstream* bs, const NalUnitTy } } +#if JVET_AC0353_NNPFC_BASE_FLAG +bool SEIReader::xCheckNnpfcSeiMsg(uint32_t seiId, bool baseFlag, const std::vector<int> nnpfcValueList) +{ + if (baseFlag) + { + //Check if this is a new filter or a repetition of an existing base flag + for (auto val : nnpfcValueList) + { + if (val == seiId) + { + //The filter is a repetition. + return false; + } + } + } + else + { + bool filterHasPresent = false; + for(auto val : nnpfcValueList) + { + if (val == seiId) + { + filterHasPresent = true; + break; + } + } + CHECK(!filterHasPresent, "Cannot have update filter without base filter already present!") + } + return true; +} +#endif + bool 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 @@ -444,8 +476,14 @@ bool SEIReader::xReadSEImessage(SEIMessages& seis, const NalUnitType nalUnitType xParseSEINNPostFilterCharacteristics((SEINeuralNetworkPostFilterCharacteristics &) *sei, payloadSize, sps, pDecodedMessageOutputStream); - +#if JVET_AC0353_NNPFC_BASE_FLAG + if (xCheckNnpfcSeiMsg( ((SEINeuralNetworkPostFilterCharacteristics*)sei)->m_id, ((SEINeuralNetworkPostFilterCharacteristics*)sei)->m_baseFlag, nnpfcValues) ) + { + nnpfcValues.push_back(((SEINeuralNetworkPostFilterCharacteristics*)sei)->m_id); + } +#else nnpfcValues.push_back(((SEINeuralNetworkPostFilterCharacteristics*)sei)->m_id); +#endif break; case SEI::PayloadType::NEURAL_NETWORK_POST_FILTER_ACTIVATION: sei = new SEINeuralNetworkPostFilterActivation; @@ -2722,6 +2760,10 @@ void SEIReader::xParseSEINNPostFilterCharacteristics(SEINeuralNetworkPostFilterC if (sei.m_propertyPresentFlag) { +#if JVET_AC0353_NNPFC_BASE_FLAG + sei_read_flag(pDecodedMessageOutputStream, val, "nnpfc_base_flag"); + sei.m_baseFlag = val; +#endif #if !JVET_AC0127_BIT_MASKING_NNPFC_PURPOSE sei_read_uvlc(pDecodedMessageOutputStream, val, "nnpfc_purpose"); sei.m_purpose = val; diff --git a/source/Lib/DecoderLib/SEIread.h b/source/Lib/DecoderLib/SEIread.h index 3892468a7b5c9d59d62b58d076009d6d293ebc2c..07531f7e01e815caf4fcdd2c0bf4ad0f374640ba 100644 --- a/source/Lib/DecoderLib/SEIread.h +++ b/source/Lib/DecoderLib/SEIread.h @@ -63,6 +63,9 @@ public: std::vector<int> nnpfcValues; protected: +#if JVET_AC0353_NNPFC_BASE_FLAG + bool xCheckNnpfcSeiMsg (uint32_t seiId, bool baseFlag, const std::vector<int> nnpfcValueList); +#endif bool 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); void xParseSEIFillerPayload (SEIFillerPayload &sei, uint32_t payloadSize, std::ostream *pDecodedMessageOutputStream); void xParseSEIuserDataUnregistered (SEIuserDataUnregistered &sei, uint32_t payloadSize, std::ostream *pDecodedMessageOutputStream); diff --git a/source/Lib/EncoderLib/EncCfg.h b/source/Lib/EncoderLib/EncCfg.h index 68af43ab0e59e56ab0fb1fd3b1df1b733300e4b6..dfe3c544efa4a8c896b576abbb2cc8dfc466ad2e 100644 --- a/source/Lib/EncoderLib/EncCfg.h +++ b/source/Lib/EncoderLib/EncCfg.h @@ -689,6 +689,9 @@ protected: uint32_t m_nnPostFilterSEICharacteristicsId[MAX_NUM_NN_POST_FILTERS]; uint32_t m_nnPostFilterSEICharacteristicsModeIdc[MAX_NUM_NN_POST_FILTERS]; bool m_nnPostFilterSEICharacteristicsPropertyPresentFlag[MAX_NUM_NN_POST_FILTERS]; +#if JVET_AC0353_NNPFC_BASE_FLAG + bool m_nnPostFilterSEICharacteristicsBaseFlag[MAX_NUM_NN_POST_FILTERS]; +#endif uint32_t m_nnPostFilterSEICharacteristicsPurpose[MAX_NUM_NN_POST_FILTERS]; bool m_nnPostFilterSEICharacteristicsOutSubCFlag[MAX_NUM_NN_POST_FILTERS]; #if JVET_AC0154 @@ -1913,6 +1916,10 @@ public: uint32_t getNNPostFilterSEICharacteristicsModeIdc(int filterIdx) const { return m_nnPostFilterSEICharacteristicsModeIdc[filterIdx]; } void setNNPostFilterSEICharacteristicsPropertyPresentFlag(bool propertyPresentFlag, int filterIdx) { m_nnPostFilterSEICharacteristicsPropertyPresentFlag[filterIdx] = propertyPresentFlag; } bool getNNPostFilterSEICharacteristicsPropertyPresentFlag(int filterIdx) const { return m_nnPostFilterSEICharacteristicsPropertyPresentFlag[filterIdx]; } +#if JVET_AC0353_NNPFC_BASE_FLAG + void setNNPostFilterSEICharacteristicsBaseFlag(bool baseFlag, int filterIdx) { m_nnPostFilterSEICharacteristicsBaseFlag[filterIdx] = baseFlag; } + bool getNNPostFilterSEICharacteristicsBaseFlag(int filterIdx) const { return m_nnPostFilterSEICharacteristicsBaseFlag[filterIdx]; } +#endif void setNNPostFilterSEICharacteristicsPurpose(uint32_t purpose, int filterIdx) { m_nnPostFilterSEICharacteristicsPurpose[filterIdx] = purpose; } uint32_t getNNPostFilterSEICharacteristicsPurpose(int filterIdx) const { return m_nnPostFilterSEICharacteristicsPurpose[filterIdx]; } diff --git a/source/Lib/EncoderLib/SEIEncoder.cpp b/source/Lib/EncoderLib/SEIEncoder.cpp index 28c1042b6af17cb490599b855a71134acff2c56e..0fbd9ef7f6dca7efb0da6017d5db415d1485c8d9 100644 --- a/source/Lib/EncoderLib/SEIEncoder.cpp +++ b/source/Lib/EncoderLib/SEIEncoder.cpp @@ -1325,6 +1325,9 @@ void SEIEncoder::initSEINeuralNetworkPostFilterCharacteristics(SEINeuralNetworkP sei->m_propertyPresentFlag = m_pcCfg->getNNPostFilterSEICharacteristicsPropertyPresentFlag(filterIdx); if (sei->m_propertyPresentFlag) { +#if JVET_AC0353_NNPFC_BASE_FLAG + sei->m_baseFlag = m_pcCfg->getNNPostFilterSEICharacteristicsBaseFlag(filterIdx); +#endif #if !JVET_AC0127_BIT_MASKING_NNPFC_PURPOSE sei->m_purpose = m_pcCfg->getNNPostFilterSEICharacteristicsPurpose(filterIdx); #endif diff --git a/source/Lib/EncoderLib/SEIwrite.cpp b/source/Lib/EncoderLib/SEIwrite.cpp index c65991d51716ca3de1c2e61d92277c1179624e2e..64ec77847adc418d78fba74186cf01e55ce40081 100644 --- a/source/Lib/EncoderLib/SEIwrite.cpp +++ b/source/Lib/EncoderLib/SEIwrite.cpp @@ -1715,6 +1715,9 @@ void SEIWriter::xWriteSEINeuralNetworkPostFilterCharacteristics(const SEINeuralN xWriteFlag(sei.m_propertyPresentFlag, "nnpfc_property_present_flag"); if (sei.m_propertyPresentFlag) { +#if JVET_AC0353_NNPFC_BASE_FLAG + xWriteFlag(sei.m_baseFlag, "nnpfc_base_flag"); +#endif #if !JVET_AC0127_BIT_MASKING_NNPFC_PURPOSE xWriteUvlc(sei.m_purpose, "nnpfc_purpose"); #endif