diff --git a/doc/software-manual.tex b/doc/software-manual.tex index 58b58c50d1dbd7faaf7f626666d440d858292116..098535c725f87b510d719d719163803a238e9e8d 100644 --- a/doc/software-manual.tex +++ b/doc/software-manual.tex @@ -5707,12 +5707,13 @@ Specifies sii_num_units_in_shutter_interval for single entry.If multiple entries Specifies the purpose of the \emph{i}-th neural network post-filter. \par \begin{tabular}{cp{0.35\textwidth}} - 0 & Unknown or unspecified \\ - 1 & Visual quality improvement \\ - 2 & Chroma upsampling from the 4:2:0 chroma format to the 4:2:2 or 4:4:4 chroma format, or from the 4:2:2 chroma format to the 4:4:4 chroma format \\ - 3 & Increasing the width or height of the cropped decoded output picture without changing the chroma format \\ - 4 & Increasing the width or height of the cropped decoded output picture and upsampling the chroma format \\ - 5 & Frame rate upsampling \\ + 0 & Determined by the application \\ + (nnpfc\_purpose \& 0x01) != 0 & Visual quality improvement \\ + (nnpfc\_purpose \& 0x02) != 0 & Chroma upsampling from the 4:2:0 chroma format to the 4:2:2 or 4:4:4 chroma format, or from the 4:2:2 chroma format to the 4:4:4 chroma format \\ + (nnpfc\_purpose \& 0x04) != 0 & Resolution upsampling (increasing the width or height) \\ + (nnpfc\_purpose \& 0x08) != 0 & Frame rate upsampling \\ + (nnpfc\_purpose \& 0x10) != 0 & Bit depth upsampling \\ + (nnpfc\_purpose \& 0x20) != 0 & Colourization \\ \end{tabular} \\ \Option{SEINNPostFilterCharacteristicsOutSubCFlag\emph{i}} & @@ -5725,6 +5726,16 @@ Specifies sii_num_units_in_shutter_interval for single entry.If multiple entries \end{tabular} \\ \\ + \Option{SEINNPostFilterCharacteristicsOutColourFormatIdc\emph{i}} & + \Default{0} & + Specifies the colour format of the NNPF output. + \par + \begin{tabular}{cp{0.35\textwidth}} + 1 & The colour format of the NNPF output is the 4:2:0 format \\ + 2 & The colour format of the NNPF output is the 4:2:2 format \\ + 3 & The colour format of the NNPF output is the 4:4:4 format \\ + \end{tabular} + \\ \Option{SEINNPostFilterCharacteristicsPicWidthInLumaSamples\emph{i}} & \Default{0} & Specifies the horizontal luma sample counts of the output picture for the \emph{i}-th neural network post-filter. diff --git a/source/App/EncoderApp/EncApp.cpp b/source/App/EncoderApp/EncApp.cpp index 2ac877aa4d76111fa403d31d42cbb8bbf9d9372c..411e580fb9d29f214ae3121f4c9728ae34aa9f72 100644 --- a/source/App/EncoderApp/EncApp.cpp +++ b/source/App/EncoderApp/EncApp.cpp @@ -1191,6 +1191,12 @@ void EncApp::xInitLibCfg( int layerIdx ) { m_cEncLib.setNNPostFilterSEICharacteristicsOutSubCFlag(m_nnPostFilterSEICharacteristicsOutSubCFlag[i], i); } +#if JVET_AC0154 + if ((m_cEncLib.getNNPostFilterSEICharacteristicsPurpose(i) & NNPC_PurposeType::COLOURIZATION) != 0) + { + m_cEncLib.setNNPostFilterSEICharacteristicsOutColourFormatIdc(ChromaFormat(m_nnPostFilterSEICharacteristicsOutColourFormatIdc[i]), i); + } +#endif if (m_cEncLib.getNNPostFilterSEICharacteristicsPurpose(i) == 3 || m_cEncLib.getNNPostFilterSEICharacteristicsPurpose(i) == 4) { m_cEncLib.setNNPostFilterSEICharacteristicsPicWidthInLumaSamples (m_nnPostFilterSEICharacteristicsPicWidthInLumaSamples[i], i); diff --git a/source/App/EncoderApp/EncAppCfg.cpp b/source/App/EncoderApp/EncAppCfg.cpp index 374637333c6138e60151b479fe0b5eb404ef902f..4e0779f507c94b0aef1377172ffe5ff9e9d0a8a9 100644 --- a/source/App/EncoderApp/EncAppCfg.cpp +++ b/source/App/EncoderApp/EncAppCfg.cpp @@ -1754,6 +1754,12 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] ) outSubWidthCFlag << "SEINNPostFilterCharacteristicsOutSubCFlag" << i; opts.addOptions()(outSubWidthCFlag.str(), m_nnPostFilterSEICharacteristicsOutSubCFlag[i], false, "Specifies output chroma format when upsampling"); +#if JVET_AC0154 + std::ostringstream outColourFormatIdc; + outColourFormatIdc << "SEINNPostFilterCharacteristicsOutColourFormatIdc" << i; + opts.addOptions()(outColourFormatIdc.str(), m_nnPostFilterSEICharacteristicsOutColourFormatIdc[i], 1u, "Specifies output chroma format for colourization purpose"); +#endif + std::ostringstream picWidthInLumaSamples; picWidthInLumaSamples << "SEINNPostFilterCharacteristicsPicWidthInLumaSamples" << i; opts.addOptions()(picWidthInLumaSamples.str(), m_nnPostFilterSEICharacteristicsPicWidthInLumaSamples[i], 0u, "Specifies the horizontal luma sample counts of the output picture in the Neural Network Post Filter Characteristics SEI message"); @@ -4900,7 +4906,12 @@ bool EncAppCfg::xCheckParameter() xConfirmPara(m_nnPostFilterSEICharacteristicsPaddingType[i] > (1 << 4) - 1, "SEINNPostFilterPaddingType must be in the range of 0 to 2^4-1"); xConfirmPara(m_nnPostFilterSEICharacteristicsLog2ParameterBitLengthMinus3[i] > 3, "SEINNPostFilterCharacteristicsLog2ParameterBitLengthMinus3 must be in the range of 0 to 3"); xConfirmPara(m_nnPostFilterSEICharacteristicsNumParametersIdc[i] > 52, "SEINNPostFilterCharacteristicsNumParametersIdc must be in the range of 0 to 52"); +#if JVET_AC0154 + xConfirmPara(m_nnPostFilterSEICharacteristicsTotalKilobyteSize[i] > (uint32_t) (((uint64_t) 1 << 32) - 2), "SEINNPostFilterCharacteristicsTotalKilobyteSize must be in the range of 0 to 2^32-2"); + xConfirmPara(m_nnPostFilterSEICharacteristicsNumKmacOperationsIdc[i] > (uint32_t) (((uint64_t) 1 << 32) - 2), "SEICharacteristicsNumKmacOperationsIdc must be in the range of 0 to 2^32-2"); +#else xConfirmPara(m_nnPostFilterSEICharacteristicsTotalKilobyteSize[i] > (uint32_t) (((uint64_t) 1 << 32) - 1), "SEINNPostFilterCharacteristicsTotalKilobyteSize must be in the range of 0 to 2^32-1"); +#endif } } diff --git a/source/App/EncoderApp/EncAppCfg.h b/source/App/EncoderApp/EncAppCfg.h index af600ac7e724142917c0bea90ecaaa5c963b03c6..d771a4091ffe720285000738d1de58b02b89725b 100644 --- a/source/App/EncoderApp/EncAppCfg.h +++ b/source/App/EncoderApp/EncAppCfg.h @@ -735,6 +735,9 @@ protected: bool m_nnPostFilterSEICharacteristicsPurposeAndFormattingFlag[MAX_NUM_NN_POST_FILTERS]; uint32_t m_nnPostFilterSEICharacteristicsPurpose[MAX_NUM_NN_POST_FILTERS]; bool m_nnPostFilterSEICharacteristicsOutSubCFlag[MAX_NUM_NN_POST_FILTERS]; +#if JVET_AC0154 + uint32_t m_nnPostFilterSEICharacteristicsOutColourFormatIdc[MAX_NUM_NN_POST_FILTERS]; +#endif uint32_t m_nnPostFilterSEICharacteristicsPicWidthInLumaSamples[MAX_NUM_NN_POST_FILTERS]; uint32_t m_nnPostFilterSEICharacteristicsPicHeightInLumaSamples[MAX_NUM_NN_POST_FILTERS]; uint32_t m_nnPostFilterSEICharacteristicsInpTensorBitDepthMinus8[MAX_NUM_NN_POST_FILTERS]; diff --git a/source/Lib/CommonLib/SEI.h b/source/Lib/CommonLib/SEI.h index b25f7c3284313d8686bf4a3c49981873fce16583..18b901c8935fa0405bd521cbc17e0a7438fda847 100644 --- a/source/Lib/CommonLib/SEI.h +++ b/source/Lib/CommonLib/SEI.h @@ -1165,6 +1165,9 @@ public: , m_outSubCFlag(0) , m_outSubWidthC(1) , m_outSubHeightC(1) +#if JVET_AC0154 + , m_outColourFormatIdc(ChromaFormat::CHROMA_420) +#endif , m_picWidthInLumaSamples(0) , m_picHeightInLumaSamples(0) , m_inpTensorBitDepthMinus8(0) @@ -1214,6 +1217,9 @@ public: bool m_outSubCFlag; uint8_t m_outSubWidthC; uint8_t m_outSubHeightC; + #if JVET_AC0154 + ChromaFormat m_outColourFormatIdc; + #endif uint32_t m_picWidthInLumaSamples; uint32_t m_picHeightInLumaSamples; uint32_t m_inpTensorBitDepthMinus8; diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h index adbd4439429cd0f934f242c205f14f60b8f18cd6..8fa448a6b428ab7f57bad79a8170e03aeed46597 100644 --- a/source/Lib/CommonLib/TypeDef.h +++ b/source/Lib/CommonLib/TypeDef.h @@ -58,7 +58,7 @@ #define JVET_AC0139_UNIFIED_MERGE 1 #define JVET_AC0096 1 - +#define JVET_AC0154 1 //########### place macros to be be kept below this line ############### #define GDR_ENABLED 1 @@ -761,6 +761,18 @@ enum NNPC_PaddingType FIXED_PADDING = 4 }; +#if JVET_AC0154 +enum NNPC_PurposeType +{ + UNKONWN = 0, + VISUAL_QUALITY_IMPROVEMENT = 1, + CHROMA_UPSAMPLING = 2, + RESOLUTION_UPSAMPLING = 4, + FRAME_RATE_UPSAMPLING = 8, + BIT_DEPTH_UPSAMPLING = 16, + COLOURIZATION = 32 +}; +#else enum NNPC_PurposeType { UNKONWN = 0, @@ -768,8 +780,9 @@ enum NNPC_PurposeType CHROMA_UPSAMPLING = 2, INCREASE_PICT_DIMENSION_WITHOUT_CHROMA_UPSAMPLING = 3, INCREASE_PICT_DIMENSION_WITH_CHROMA_UPSMAPLING = 4, - FRANE_RATE_UPSAMPLING = 5 + FRAME_RATE_UPSAMPLING = 5 }; +#endif enum POST_FILTER_MODE { diff --git a/source/Lib/DecoderLib/SEIread.cpp b/source/Lib/DecoderLib/SEIread.cpp index 9148e46ef658e7a22cb0eaa898a35cb479fdeffb..d394a022ef4055105802ba649c7c1db728d7aa4a 100644 --- a/source/Lib/DecoderLib/SEIread.cpp +++ b/source/Lib/DecoderLib/SEIread.cpp @@ -2719,13 +2719,37 @@ void SEIReader::xParseSEINNPostFilterCharacteristics(SEINeuralNetworkPostFilterC sei.m_outSubHeightC = 1; } } +#if !JVET_AC0154 else { sei.m_outSubWidthC = subWidthC; sei.m_outSubHeightC = subHeightC; } +#endif CHECK(((subWidthC == 1) && (subHeightC == 1)) && ((sei.m_purpose == 2) || (sei.m_purpose == 4)), "If SubWidthC is equal to 1 and SubHeightC is equal to 1, nnpfc_purpose shall not be equal to 2 or 4"); + +#if JVET_AC0154 + if((sei.m_purpose & NNPC_PurposeType::COLOURIZATION) != 0) + { + CHECK(((chromaFormatIDC != ChromaFormat::CHROMA_400) || (sei.m_purpose & NNPC_PurposeType::CHROMA_UPSAMPLING) != 0), + "When ChromaFormatIdc or nnpfc_purpose & 0x02 is not equal to 0, nnpfc_purpose & 0x20 shall be equal to 0"); + + sei_read_code(pDecodedMessageOutputStream, 2, val, "nnpfc_out_colour_format_idc"); + sei.m_outColourFormatIdc = ChromaFormat(val); + CHECK(sei.m_outColourFormatIdc == 0, "The value of nnpfc_out_colour_format_idc shall not be equal to 0"); + + sei.m_outSubWidthC = SPS::getWinUnitX(sei.m_outColourFormatIdc); + sei.m_outSubHeightC = SPS::getWinUnitY(sei.m_outColourFormatIdc); + } + + if (((sei.m_purpose & NNPC_PurposeType::CHROMA_UPSAMPLING) == 0) && ((sei.m_purpose & NNPC_PurposeType::COLOURIZATION) == 0)) + { + sei.m_outSubWidthC = subWidthC; + sei.m_outSubHeightC = subHeightC; + } +#endif + if(sei.m_purpose == 3 || sei.m_purpose == 4) { sei_read_flag(pDecodedMessageOutputStream, val, "nnpfc_pic_width_in_luma_samples"); @@ -2734,16 +2758,30 @@ void SEIReader::xParseSEINNPostFilterCharacteristics(SEINeuralNetworkPostFilterC sei.m_picHeightInLumaSamples = val; } - if (sei.m_purpose == NNPC_PurposeType::FRANE_RATE_UPSAMPLING) + if (sei.m_purpose == NNPC_PurposeType::FRAME_RATE_UPSAMPLING) { sei_read_uvlc(pDecodedMessageOutputStream, val, "nnpfc_number_of_input_pictures_minus2"); sei.m_numberInputDecodedPicturesMinus2 = val; sei.m_numberInterpolatedPictures.resize(sei.m_numberInputDecodedPicturesMinus2 + 1); +#if JVET_AC0154 + bool allZeroFlag = false; + for (int i = 0; i < sei.m_numberInterpolatedPictures.size(); i++) + { + sei_read_uvlc(pDecodedMessageOutputStream, val, "nnpfc_interpolated_pictures"); + sei.m_numberInterpolatedPictures[i] = val; + if(sei.m_numberInterpolatedPictures[i] > 0) + { + allZeroFlag = true; + } + } + CHECK(!allZeroFlag, "At least one value of nnpfc_interpolated_pics[i] shall be greater than 0"); +#else for (int i = 0; i < sei.m_numberInterpolatedPictures.size(); i++) { sei_read_uvlc(pDecodedMessageOutputStream, val, "nnpfc_interpolated_pictures"); sei.m_numberInterpolatedPictures[i] = val; } +#endif } sei_read_flag(pDecodedMessageOutputStream, val, "nnpfc_component_last_flag"); diff --git a/source/Lib/EncoderLib/EncCfg.h b/source/Lib/EncoderLib/EncCfg.h index f321b4f3e16193fdc3dbce27003d5ea06c4ed8d4..31cfb14c290892d3abd776cfbf29f353916c2583 100644 --- a/source/Lib/EncoderLib/EncCfg.h +++ b/source/Lib/EncoderLib/EncCfg.h @@ -691,6 +691,9 @@ protected: bool m_nnPostFilterSEICharacteristicsPurposeAndFormattingFlag[MAX_NUM_NN_POST_FILTERS]; uint32_t m_nnPostFilterSEICharacteristicsPurpose[MAX_NUM_NN_POST_FILTERS]; bool m_nnPostFilterSEICharacteristicsOutSubCFlag[MAX_NUM_NN_POST_FILTERS]; +#if JVET_AC0154 + ChromaFormat m_nnPostFilterSEICharacteristicsOutColourFormatIdc[MAX_NUM_NN_POST_FILTERS]; +#endif uint32_t m_nnPostFilterSEICharacteristicsPicWidthInLumaSamples[MAX_NUM_NN_POST_FILTERS]; uint32_t m_nnPostFilterSEICharacteristicsPicHeightInLumaSamples[MAX_NUM_NN_POST_FILTERS]; uint32_t m_nnPostFilterSEICharacteristicsInpTensorBitDepthMinus8[MAX_NUM_NN_POST_FILTERS]; @@ -1889,6 +1892,10 @@ public: void setNNPostFilterSEICharacteristicsOutSubCFlag(bool SubCFlag, int filterIdx) { m_nnPostFilterSEICharacteristicsOutSubCFlag[filterIdx] = SubCFlag; } bool getNNPostFilterSEICharacteristicsOutSubCFlag(int filterIdx) const { return m_nnPostFilterSEICharacteristicsOutSubCFlag[filterIdx]; } +#if JVET_AC0154 + void setNNPostFilterSEICharacteristicsOutColourFormatIdc(ChromaFormat outColourFormatIdc, int filterIdx) { m_nnPostFilterSEICharacteristicsOutColourFormatIdc[filterIdx] = outColourFormatIdc; } + ChromaFormat getNNPostFilterSEICharacteristicsOutColourFormatIdc(int filterIdx) const { return m_nnPostFilterSEICharacteristicsOutColourFormatIdc[filterIdx]; } +#endif void setNNPostFilterSEICharacteristicsPicWidthInLumaSamples(uint32_t picWidthInLumaSamples, int filterIdx) { m_nnPostFilterSEICharacteristicsPicWidthInLumaSamples[filterIdx] = picWidthInLumaSamples; } uint32_t getNNPostFilterSEICharacteristicsPicWidthInLumaSamples(int filterIdx) const { return m_nnPostFilterSEICharacteristicsPicWidthInLumaSamples[filterIdx]; } void setNNPostFilterSEICharacteristicsPicHeightInLumaSamples(uint32_t picHeightInLumaSamples, int filterIdx) { m_nnPostFilterSEICharacteristicsPicHeightInLumaSamples[filterIdx] = picHeightInLumaSamples; } diff --git a/source/Lib/EncoderLib/SEIEncoder.cpp b/source/Lib/EncoderLib/SEIEncoder.cpp index 4e96a2c3c9d79053cd241347bfe81d1d6ba4c9b1..6f92e4ed785a799b38061223e351900609aaf10a 100644 --- a/source/Lib/EncoderLib/SEIEncoder.cpp +++ b/source/Lib/EncoderLib/SEIEncoder.cpp @@ -1312,6 +1312,12 @@ void SEIEncoder::initSEINeuralNetworkPostFilterCharacteristics(SEINeuralNetworkP { sei->m_outSubCFlag = m_pcCfg->getNNPostFilterSEICharacteristicsOutSubCFlag(filterIdx); } +#if JVET_AC0154 + if((sei->m_purpose & NNPC_PurposeType::COLOURIZATION) != 0) + { + sei->m_outColourFormatIdc = m_pcCfg->getNNPostFilterSEICharacteristicsOutColourFormatIdc(filterIdx); + } +#endif if(sei->m_purpose == 3 || sei->m_purpose == 4) { sei->m_picWidthInLumaSamples = m_pcCfg->getNNPostFilterSEICharacteristicsPicWidthInLumaSamples(filterIdx); @@ -1346,7 +1352,7 @@ void SEIEncoder::initSEINeuralNetworkPostFilterCharacteristics(SEINeuralNetworkP CHECK(!(sei->m_picWidthInLumaSamples >= croppedWidth && sei->m_picWidthInLumaSamples <= croppedWidth * 16 - 1), "m_picWidthInLumaSamples shall be in the range of croppedWidth to croppedWidth * 16 - 1"); CHECK(!(sei->m_picHeightInLumaSamples >= croppedHeight && sei->m_picHeightInLumaSamples <= croppedHeight * 16 - 1), "m_picHeightInLumaSamples shall be in the range of croppedHeight to croppedHeight * 16 - 1"); } - if (sei->m_purpose == NNPC_PurposeType::FRANE_RATE_UPSAMPLING) + if (sei->m_purpose == NNPC_PurposeType::FRAME_RATE_UPSAMPLING) { sei->m_numberInputDecodedPicturesMinus2 = m_pcCfg->getNNPostFilterSEICharacteristicsNumberInputDecodedPicturesMinus2(filterIdx); sei->m_numberInterpolatedPictures = m_pcCfg->getNNPostFilterSEICharacteristicsNumberInterpolatedPictures(filterIdx); diff --git a/source/Lib/EncoderLib/SEIwrite.cpp b/source/Lib/EncoderLib/SEIwrite.cpp index 159dc6d224421a93050508672bf6f648d4cc8cbf..5be7b918e523fa4620ca2ae873302cdcea417911 100644 --- a/source/Lib/EncoderLib/SEIwrite.cpp +++ b/source/Lib/EncoderLib/SEIwrite.cpp @@ -1700,6 +1700,12 @@ void SEIWriter::xWriteSEINeuralNetworkPostFilterCharacteristics(const SEINeuralN { xWriteFlag(sei.m_outSubCFlag, "nnpfc_out_sub_c_flag"); } +#if JVET_AC0154 + if((sei.m_purpose & NNPC_PurposeType::COLOURIZATION) != 0) + { + xWriteCode(uint32_t(sei.m_outColourFormatIdc), 2, "nnpfc_out_colour_format_idc"); + } +#endif if(sei.m_purpose == 3 || sei.m_purpose == 4) { xWriteUvlc(sei.m_picWidthInLumaSamples, "nnpfc_pic_width_in_luma_samples");