diff --git a/doc/software-manual.tex b/doc/software-manual.tex index 57e43f5aba3436085053d626ff92a243afa833b6..d37680111d6f54b55211f6a2ab47e310772bf51f 100644 --- a/doc/software-manual.tex +++ b/doc/software-manual.tex @@ -5817,6 +5817,18 @@ Specifies sii_num_units_in_shutter_interval for single entry.If multiple entries For the \emph{i}-th neural network post-filter, nnpfc_log2_parameter_bit_length_minus3 equal to 0, 1, 2, and 3 indicates that the neural network does not use parameters of bit length greater than 8, 16, 32, and 64, respectively. \\ + \Option{SEINNPFCAapplicationPurposeTagUriPresentFlag\emph{i}} & + \Default{false} & + Specifies the nnpfc_application_purpose_tag_uri_present_flag syntax element for the \emph{i}-th neural network post-filter. + \par + When true (non-zero) specifies the presence of the nnpfc_application_purpose_tag_uri syntax element in the NNPFC SEI message. + \par + When false specifies the absence of the nnpfc_application_purpose_tag_uri syntax element in the NNPFC SEI message. + \\ + \Option{SEINNPFCApplicationPurposeTagUri\emph{i}} & + \Default{""} & + specifies a tag URI with syntax and semantics as specified in IETF RFC 4151 identifying the application determined purpose of the NNPF, when nnpfc_purpose is equal to 0 of the \emph{i}-th neural network post-filter. + \\ \Option{SEINNPFCNumParametersIdc\emph{i}} & \Default{0} & Specifies the maximum number of neural network parameters for the \emph{i}-th neural network post-filter in units of a power of 2048. nnpfc_num_parameters_idc = 0 indicates that the maximum number of neural network diff --git a/source/App/EncoderApp/EncApp.cpp b/source/App/EncoderApp/EncApp.cpp index b468c425e938fed249b632904c0b35b390afbb51..3ad4f1b45db123d9dae9cbef5caaed1a983b60bf 100644 --- a/source/App/EncoderApp/EncApp.cpp +++ b/source/App/EncoderApp/EncApp.cpp @@ -1295,6 +1295,16 @@ void EncApp::xInitLibCfg( int layerIdx ) m_cEncLib.setNNPostFilterSEICharacteristicsTotalKilobyteSize ( m_nnPostFilterSEICharacteristicsTotalKilobyteSize[i], i); } +#if JVET_AF2032_NNPFC_APPLICATION_INFORMATION_SIGNALING + if (m_cEncLib.getNNPostFilterSEICharacteristicsPurpose(i) == 0) + { + m_cEncLib.setNNPostFilterSEICharacteristicsApplicationPurposeTagUriPresentFlag (m_nnPostFilterSEICharacteristicsApplicationPurposeTagUriPresentFlag[i], i); + if (m_cEncLib.getNNPostFilterSEICharacteristicsApplicationPurposeTagUriPresentFlag(i)) + { + m_cEncLib.setNNPostFilterSEICharacteristicsApplicationPurposeTagUri(m_nnPostFilterSEICharacteristicsApplicationPurposeTagUri[i],i); + } + } +#endif m_cEncLib.setNNPostFilterSEICharacteristicsUriTag ( m_nnPostFilterSEICharacteristicsUriTag[i], i); m_cEncLib.setNNPostFilterSEICharacteristicsUri ( m_nnPostFilterSEICharacteristicsUri[i], i); } diff --git a/source/App/EncoderApp/EncAppCfg.cpp b/source/App/EncoderApp/EncAppCfg.cpp index f21df7f7316890aef95170667866016d6c04bc6e..fe15a36c560e4b3c95f89d7a2957539e4be757f1 100644 --- a/source/App/EncoderApp/EncAppCfg.cpp +++ b/source/App/EncoderApp/EncAppCfg.cpp @@ -1916,6 +1916,16 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] ) complexityInfoPresentFlag << "SEINNPFCComplexityInfoPresentFlag" << i; opts.addOptions()(complexityInfoPresentFlag.str(), m_nnPostFilterSEICharacteristicsComplexityInfoPresentFlag[i], false, "Specifies the value of nnpfc_complexity_info_present_flag in the Neural Network Post Filter Characteristics SEI message"); +#if JVET_AF2032_NNPFC_APPLICATION_INFORMATION_SIGNALING + std::ostringstream applicationPurposeTagUriPresentFlag; + applicationPurposeTagUriPresentFlag << "SEINNPFCApplicationPurposeTagUriPresentFlag" << i; + opts.addOptions()(applicationPurposeTagUriPresentFlag.str(), m_nnPostFilterSEICharacteristicsApplicationPurposeTagUriPresentFlag[i], false, "equal to 1 indicates that the nnpfc_application_purpose_tag_uri syntax element is present in this NNPFC SEI message. nnpfc_application_purpose_tag_uri_present_flag equal to 0 indicates that the nnpfc_application_purpose_tag_uri syntax element is not present in this NNPFC SEI message."); + + std::ostringstream applicationPurposeTagUri; + applicationPurposeTagUri << "SEINNPFCApplicationPurposeTagUri" << i; + opts.addOptions()(applicationPurposeTagUri.str(), m_nnPostFilterSEICharacteristicsApplicationPurposeTagUri[i], std::string(""), "specifies a tag URI with syntax and semantics as specified in IETF RFC 4151 identifying the application determined purpose of the NNPF, when nnpfc_purpose is equal to 0."); +#endif + std::ostringstream uriTag; uriTag << "SEINNPFCUriTag" << i; opts.addOptions()( diff --git a/source/App/EncoderApp/EncAppCfg.h b/source/App/EncoderApp/EncAppCfg.h index b2ec7e087da05cc4e4ce2f2918d651dfd0199358..ca2bc49499a1d687ca51292c029f96076e7178af 100644 --- a/source/App/EncoderApp/EncAppCfg.h +++ b/source/App/EncoderApp/EncAppCfg.h @@ -776,6 +776,10 @@ protected: uint32_t m_nnPostFilterSEICharacteristicsCrPadding[MAX_NUM_NN_POST_FILTERS]; std::string m_nnPostFilterSEICharacteristicsPayloadFilename[MAX_NUM_NN_POST_FILTERS]; bool m_nnPostFilterSEICharacteristicsComplexityInfoPresentFlag[MAX_NUM_NN_POST_FILTERS]; +#if JVET_AF2032_NNPFC_APPLICATION_INFORMATION_SIGNALING + bool m_nnPostFilterSEICharacteristicsApplicationPurposeTagUriPresentFlag[MAX_NUM_NN_POST_FILTERS]; + std::string m_nnPostFilterSEICharacteristicsApplicationPurposeTagUri[MAX_NUM_NN_POST_FILTERS]; +#endif std::string m_nnPostFilterSEICharacteristicsUriTag[MAX_NUM_NN_POST_FILTERS]; std::string m_nnPostFilterSEICharacteristicsUri[MAX_NUM_NN_POST_FILTERS]; uint32_t m_nnPostFilterSEICharacteristicsParameterTypeIdc[MAX_NUM_NN_POST_FILTERS]; diff --git a/source/Lib/CommonLib/SEI.cpp b/source/Lib/CommonLib/SEI.cpp index 1aec07c4bd77debae289e775eec750132329e23e..2a454f345630dfa38a603800f9c0fe57be19344a 100644 --- a/source/Lib/CommonLib/SEI.cpp +++ b/source/Lib/CommonLib/SEI.cpp @@ -984,6 +984,10 @@ SEINeuralNetworkPostFilterCharacteristics::SEINeuralNetworkPostFilterCharacteris m_payloadLength = sei.m_payloadLength; m_payloadByte = sei.m_payloadByte ? new char(*sei.m_payloadByte) : nullptr; m_complexityInfoPresentFlag = sei.m_complexityInfoPresentFlag; +#if JVET_AF2032_NNPFC_APPLICATION_INFORMATION_SIGNALING + m_applicationPurposeTagUriPresentFlag = sei.m_applicationPurposeTagUriPresentFlag; + m_applicationPurposeTagUri = sei.m_applicationPurposeTagUri; +#endif m_uriTag = sei.m_uriTag; m_uri = sei.m_uri; m_parameterTypeIdc = sei.m_parameterTypeIdc; @@ -1042,6 +1046,10 @@ bool SEINeuralNetworkPostFilterCharacteristics::operator == (const SEINeuralNetw m_cbPadding == sei.m_cbPadding && m_crPadding == sei.m_crPadding && m_complexityInfoPresentFlag == sei.m_complexityInfoPresentFlag && +#if JVET_AF2032_NNPFC_APPLICATION_INFORMATION_SIGNALING + m_applicationPurposeTagUriPresentFlag == sei.m_applicationPurposeTagUriPresentFlag && + m_applicationPurposeTagUri == sei.m_applicationPurposeTagUri && +#endif m_uriTag == sei.m_uriTag && m_uri == sei.m_uri && m_parameterTypeIdc == sei.m_parameterTypeIdc && diff --git a/source/Lib/CommonLib/SEI.h b/source/Lib/CommonLib/SEI.h index 53545f8689a67db0567cd223b1a2c2d7426b632e..2707cebbc42a9f5eb0dbe6090d3b8a6d5a380ce6 100644 --- a/source/Lib/CommonLib/SEI.h +++ b/source/Lib/CommonLib/SEI.h @@ -1321,6 +1321,10 @@ public: , m_crPadding(0) , m_payloadByte(nullptr) , m_complexityInfoPresentFlag(false) +#if JVET_AF2032_NNPFC_APPLICATION_INFORMATION_SIGNALING + , m_applicationPurposeTagUriPresentFlag(false) + , m_applicationPurposeTagUri("") +#endif , m_uriTag("") , m_uri("") , m_parameterTypeIdc(0) @@ -1393,6 +1397,10 @@ public: uint64_t m_payloadLength; char* m_payloadByte; bool m_complexityInfoPresentFlag; +#if JVET_AF2032_NNPFC_APPLICATION_INFORMATION_SIGNALING + bool m_applicationPurposeTagUriPresentFlag; + std::string m_applicationPurposeTagUri; +#endif std::string m_uriTag; std::string m_uri; uint32_t m_parameterTypeIdc; diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h index 6db760e8e6817e787b3c09df13a7ef99c1f0fd23..e23e8330676059cde452af1906d8eeb83cb4e74c 100644 --- a/source/Lib/CommonLib/TypeDef.h +++ b/source/Lib/CommonLib/TypeDef.h @@ -62,6 +62,8 @@ +#define JVET_AF2032_NNPFC_APPLICATION_INFORMATION_SIGNALING 1 // JVET-AF2032: Conditionally signal application tag URI presence flag and tag URI in the NNPFC metadata extension + //########### place macros to be be kept below this line ############### #define GDR_ENABLED 1 diff --git a/source/Lib/DecoderLib/SEIread.cpp b/source/Lib/DecoderLib/SEIread.cpp index 2acb373c640ad11246333c7bc15165c5cf7f5b77..46006958c816b1fa3192fd77d45a1986383dc3e6 100644 --- a/source/Lib/DecoderLib/SEIread.cpp +++ b/source/Lib/DecoderLib/SEIread.cpp @@ -3129,6 +3129,34 @@ void SEIReader::xParseSEINNPostFilterCharacteristics(SEINeuralNetworkPostFilterC sei.m_totalKilobyteSize = val; } +#if JVET_AF2032_NNPFC_APPLICATION_INFORMATION_SIGNALING + sei_read_uvlc(pDecodedMessageOutputStream, val, "nnpfc_metadata_extension_num_bits"); + uint32_t metadataExtensionNumBits = val; + uint32_t numberExtensionBitsUsed = 0; + if ( metadataExtensionNumBits > 0 ) + { + CHECK (val > 4096, "Values of nnpfc_metadata_extension_num_bits greater than 4096 shall not be present in bitstreams"); + if ( sei.m_purpose == 0 ) + { + sei_read_flag(pDecodedMessageOutputStream, val, "nnpfc_application_purpose_tag_uri_present_flag"); + sei.m_applicationPurposeTagUriPresentFlag = val; + numberExtensionBitsUsed++; + if ( sei.m_applicationPurposeTagUriPresentFlag ) + { + std::string val2; + sei_read_string(pDecodedMessageOutputStream, val2, "nnpfc_application_purpose_tag_uri"); + sei.m_applicationPurposeTagUri = val2; + numberExtensionBitsUsed += (static_cast<uint32_t>(sei.m_applicationPurposeTagUri.length() + 1) * 8); + } + } + uint32_t numberExtensionBitRemaining = metadataExtensionNumBits - numberExtensionBitsUsed; + for (uint32_t i = 0; i < numberExtensionBitRemaining; i++) + { + uint32_t val2; + sei_read_code(pDecodedMessageOutputStream, 1, val2, "nnpfc_reserved_metadata_extension"); + } + } +#else sei_read_uvlc(pDecodedMessageOutputStream, val, "nnpfc_metadata_extension_num_bits"); // nnpfc_metadata_extension_num_bits shall be equal to 0 in the current edition CHECK (val > 2048, "Values of nnpfc_metadata_extension_num_bits greater than 2048 shall not be present in bitstreams"); for (uint32_t i = 0; i < val; i++) @@ -3136,6 +3164,7 @@ void SEIReader::xParseSEINNPostFilterCharacteristics(SEINeuralNetworkPostFilterC uint32_t val2; sei_read_code(pDecodedMessageOutputStream, 1, val2, "nnpfc_reserved_metadata_extension"); // Decoders shall ignore the presence and value of nnpfc_reserved_metadata_extension } +#endif } if (sei.m_modeIdc == POST_FILTER_MODE::ISO_IEC_15938_17) @@ -3449,4 +3478,4 @@ void SEIReader::xParseSEISEIPrefixIndication(SEIPrefixIndication &sei, uint32_t } } -//! \} +//! \} \ No newline at end of file diff --git a/source/Lib/EncoderLib/EncCfg.h b/source/Lib/EncoderLib/EncCfg.h index 22e75b316601789e2ac7ba881c4e189bdab6908f..3b7de8e171aa27dd0d684be1db932afb1fa3c4f6 100644 --- a/source/Lib/EncoderLib/EncCfg.h +++ b/source/Lib/EncoderLib/EncCfg.h @@ -736,6 +736,10 @@ protected: uint32_t m_nnPostFilterSEICharacteristicsCbPadding[MAX_NUM_NN_POST_FILTERS]; std::string m_nnPostFilterSEICharacteristicsPayloadFilename[MAX_NUM_NN_POST_FILTERS]; bool m_nnPostFilterSEICharacteristicsComplexityInfoPresentFlag[MAX_NUM_NN_POST_FILTERS]; +#if JVET_AF2032_NNPFC_APPLICATION_INFORMATION_SIGNALING + bool m_nnPostFilterSEICharacteristicsApplicationPurposeTagUriPresentFlag[MAX_NUM_NN_POST_FILTERS]; + std::string m_nnPostFilterSEICharacteristicsApplicationPurposeTagUri[MAX_NUM_NN_POST_FILTERS]; +#endif std::string m_nnPostFilterSEICharacteristicsUriTag[MAX_NUM_NN_POST_FILTERS]; std::string m_nnPostFilterSEICharacteristicsUri[MAX_NUM_NN_POST_FILTERS]; uint32_t m_nnPostFilterSEICharacteristicsParameterTypeIdc[MAX_NUM_NN_POST_FILTERS]; @@ -2038,6 +2042,12 @@ public: void setNNPostFilterSEICharacteristicsComplexityInfoPresentFlag(bool complexityInfoPresentFlag, int filterIdx) { m_nnPostFilterSEICharacteristicsComplexityInfoPresentFlag[filterIdx] = complexityInfoPresentFlag; } bool getNNPostFilterSEICharacteristicsComplexityInfoPresentFlag(int filterIdx) const { return m_nnPostFilterSEICharacteristicsComplexityInfoPresentFlag[filterIdx]; } +#if JVET_AF2032_NNPFC_APPLICATION_INFORMATION_SIGNALING + void setNNPostFilterSEICharacteristicsApplicationPurposeTagUriPresentFlag(bool applicationPurposeTagUriPresentFlag, int filterIdx) { m_nnPostFilterSEICharacteristicsApplicationPurposeTagUriPresentFlag[filterIdx] = applicationPurposeTagUriPresentFlag; } + bool getNNPostFilterSEICharacteristicsApplicationPurposeTagUriPresentFlag(int filterIdx) const { return m_nnPostFilterSEICharacteristicsApplicationPurposeTagUriPresentFlag[filterIdx]; } + void setNNPostFilterSEICharacteristicsApplicationPurposeTagUri(std::string applicationPurposeTagUri, int filterIdx) { m_nnPostFilterSEICharacteristicsApplicationPurposeTagUri[filterIdx] = applicationPurposeTagUri; } + std::string getNNPostFilterSEICharacteristicsApplicationPurposeTagUri(int filterIdx) const { return m_nnPostFilterSEICharacteristicsApplicationPurposeTagUri[filterIdx]; } +#endif void setNNPostFilterSEICharacteristicsUriTag(std::string uriTag, int filterIdx) { m_nnPostFilterSEICharacteristicsUriTag[filterIdx] = uriTag; } std::string getNNPostFilterSEICharacteristicsUriTag(int filterIdx) const { return m_nnPostFilterSEICharacteristicsUriTag[filterIdx]; } void setNNPostFilterSEICharacteristicsUri(std::string uri, int filterIdx) { m_nnPostFilterSEICharacteristicsUri[filterIdx] = uri; } diff --git a/source/Lib/EncoderLib/SEIEncoder.cpp b/source/Lib/EncoderLib/SEIEncoder.cpp index 5336070187e8fd37b6c199dab50701dade617a1b..ae2548a09b33f57d2a5ec30d3674f1c679a4ea5e 100644 --- a/source/Lib/EncoderLib/SEIEncoder.cpp +++ b/source/Lib/EncoderLib/SEIEncoder.cpp @@ -1499,6 +1499,16 @@ void SEIEncoder::initSEINeuralNetworkPostFilterCharacteristics(SEINeuralNetworkP sei->m_numKmacOperationsIdc = m_pcCfg->getNNPostFilterSEICharacteristicsNumKmacOperationsIdc(filterIdx); sei->m_totalKilobyteSize = m_pcCfg->getNNPostFilterSEICharacteristicsTotalKilobyteSize(filterIdx); } +#if JVET_AF2032_NNPFC_APPLICATION_INFORMATION_SIGNALING + if (sei->m_purpose == 0) + { + sei->m_applicationPurposeTagUriPresentFlag = m_pcCfg->getNNPostFilterSEICharacteristicsApplicationPurposeTagUriPresentFlag(filterIdx); + if (sei->m_applicationPurposeTagUriPresentFlag) + { + sei->m_applicationPurposeTagUri = m_pcCfg->getNNPostFilterSEICharacteristicsApplicationPurposeTagUri(filterIdx); + } + } + #endif } if (sei->m_modeIdc == POST_FILTER_MODE::ISO_IEC_15938_17) { diff --git a/source/Lib/EncoderLib/SEIwrite.cpp b/source/Lib/EncoderLib/SEIwrite.cpp index 69bcce2b71a81bb2c83d0026b323393072d37759..383b4226c81dde771e37896667c128888a0a80a8 100644 --- a/source/Lib/EncoderLib/SEIwrite.cpp +++ b/source/Lib/EncoderLib/SEIwrite.cpp @@ -1895,8 +1895,29 @@ void SEIWriter::xWriteSEINeuralNetworkPostFilterCharacteristics(const SEINeuralN xWriteUvlc(sei.m_numKmacOperationsIdc, "nnpfc_num_kmac_operations_idc"); xWriteUvlc(sei.m_totalKilobyteSize, "nnpfc_total_kilobyte_size"); } - +#if JVET_AF2032_NNPFC_APPLICATION_INFORMATION_SIGNALING + uint32_t metadataExtensionNumBits = 0; + if (sei.m_purpose == 0) + { + metadataExtensionNumBits++; + if (sei.m_applicationPurposeTagUriPresentFlag) + { + metadataExtensionNumBits += (static_cast<uint32_t>(sei.m_applicationPurposeTagUri.length() + 1) * 8); + } + xWriteUvlc(metadataExtensionNumBits, "nnpfc_metadata_extension_num_bits"); + xWriteFlag(sei.m_applicationPurposeTagUriPresentFlag, "nnpfc_application_purpose_tag_uri_present_flag"); + if ( sei.m_applicationPurposeTagUriPresentFlag ) + { + xWriteString(sei.m_applicationPurposeTagUri, "nnpfc_application_purpose_tag_uri"); + } + } + else + { + xWriteUvlc(metadataExtensionNumBits, "nnpfc_metadata_extension_num_bits"); + } +#else xWriteUvlc(0, "nnpfc_metadata_extension_num_bits"); // nnpfc_metadata_extension_num_bits shall be equal to 0 in the current edition +#endif } if (sei.m_modeIdc == POST_FILTER_MODE::ISO_IEC_15938_17) {