From d12cce0674fefb373fcf10e7e18f49fb13cd43f5 Mon Sep 17 00:00:00 2001 From: Maria Santamaria <maria.santamaria_gomez@nokia.com> Date: Sat, 28 May 2022 01:10:23 +0000 Subject: [PATCH] JVET-Z0244: NN post-filter SEI --- .../neural_network_post_filter_activation.cfg | 4 + ...al_network_post_filter_characteristics.cfg | 30 +++ doc/software-manual.tex | 185 ++++++++++++++++++ source/App/EncoderApp/EncApp.cpp | 34 ++++ source/App/EncoderApp/EncAppCfg.cpp | 140 +++++++++++++ source/App/EncoderApp/EncAppCfg.h | 32 +++ source/Lib/CommonLib/CommonDef.h | 4 + source/Lib/CommonLib/SEI.cpp | 4 + source/Lib/CommonLib/SEI.h | 88 +++++++++ source/Lib/CommonLib/TypeDef.h | 1 + source/Lib/DecoderLib/SEIread.cpp | 139 +++++++++++++ source/Lib/DecoderLib/SEIread.h | 7 + source/Lib/EncoderLib/Analyze.h | 7 + source/Lib/EncoderLib/EncCfg.h | 99 ++++++++++ source/Lib/EncoderLib/EncGOP.cpp | 67 ++++++- source/Lib/EncoderLib/EncGOP.h | 12 ++ source/Lib/EncoderLib/SEIEncoder.cpp | 84 ++++++++ source/Lib/EncoderLib/SEIEncoder.h | 4 + source/Lib/EncoderLib/SEIwrite.cpp | 107 ++++++++++ source/Lib/EncoderLib/SEIwrite.h | 13 ++ 20 files changed, 1060 insertions(+), 1 deletion(-) create mode 100644 cfg/sei_vui/neural_network_post_filter_activation.cfg create mode 100644 cfg/sei_vui/neural_network_post_filter_characteristics.cfg diff --git a/cfg/sei_vui/neural_network_post_filter_activation.cfg b/cfg/sei_vui/neural_network_post_filter_activation.cfg new file mode 100644 index 0000000000..3bfec6b9d2 --- /dev/null +++ b/cfg/sei_vui/neural_network_post_filter_activation.cfg @@ -0,0 +1,4 @@ +#======== Neural Network Post Filter activation SEI message ===================== + +SEINNPostFilterActivationEnabled: 1 +SEINNPostFilterActivationId: 1 diff --git a/cfg/sei_vui/neural_network_post_filter_characteristics.cfg b/cfg/sei_vui/neural_network_post_filter_characteristics.cfg new file mode 100644 index 0000000000..f8ab758678 --- /dev/null +++ b/cfg/sei_vui/neural_network_post_filter_characteristics.cfg @@ -0,0 +1,30 @@ +#======== Neural Network Post Filter characteristics SEI message ===================== + +SEINNPostFilterCharacteristicsEnabled: 1 +SEINNPostFilterCharacteristicsNumFilters: 1 + +SEINNPostFilterCharacteristicsId0: 1 +SEINNPostFilterCharacteristicsModeIdc0: 1 +SEINNPostFilterCharacteristicsPurpose0: 2 +SEINNPostFilterCharacteristicsOutSubWidthCFlag0: 1 +SEINNPostFilterCharacteristicsOutSubHeightCFlag0: 1 +SEINNPostFilterCharacteristicsComponentLastFlag0: 0 +SEINNPostFilterCharacteristicsInpSampleIdc0: 1 +SEINNPostFilterCharacteristicsInpTensorBitDepthMinus80: 2 +SEINNPostFilterCharacteristicsInpOrderIdc0: 2 +SEINNPostFilterCharacteristicsOutSampleIdc0: 1 +SEINNPostFilterCharacteristicsOutTensorBitDepthMinus80: 2 +SEINNPostFilterCharacteristicsOutOrderIdc0: 2 +SEINNPostFilterCharacteristicsConstantPatchSizeFlag0: 1 +SEINNPostFilterCharacteristicsPatchWidthMinus10: 127 +SEINNPostFilterCharacteristicsPatchHeightMinus10: 127 +SEINNPostFilterCharacteristicsOverlap0: 4 +SEINNPostFilterCharacteristicsPaddingType0: 1 +SEINNPostFilterCharacteristicsComplexityIdc0: 1 + +SEINNPostFilterCharacteristicsParameterTypeFlag0: 1 +SEINNPostFilterCharacteristicsLog2ParameterBitLengthMinus30: 3 +SEINNPostFilterCharacteristicsNumParametersIdc0: 2 +SEINNPostFilterCharacteristicsNumKmacOperationsIdc0: 512 + +SEINNPostFilterCharacteristicsPayloadFilename0: test.nnr diff --git a/doc/software-manual.tex b/doc/software-manual.tex index 1b9d77d281..7245f6e269 100644 --- a/doc/software-manual.tex +++ b/doc/software-manual.tex @@ -3731,6 +3731,8 @@ The table below lists the SEI messages defined for Version 1 and Range-Extension 205 & Scalability Dimension Information & Table \ref{tab:sei-sdi} \\ 207 & Constrained RASL encoding & Table \ref{tab:sei-constrained-rasl-encoding} \\ 209 & Shutter Interval Information & Table \ref{tab:sei-sii} \\ + 210 & Neural network post-filter characteristics & Table \ref{tab:sei-nn-post-filter-characteristics} \\ + 211 & Neural netowrk post-filter activation & Table \ref{tab:sei-nn-post-filter-activation} \\ \end{SEIListTable} %% %% SEI messages @@ -5323,6 +5325,189 @@ Specifies sii_num_units_in_shutter_interval for single entry.If multiple entries \\ \end{OptionTableNoShorthand} +\begin{OptionTableNoShorthand}{Neural network post-filter characteristics}{tab:sei-nn-post-filter-characteristics} + \Option{SEINNPostFilterCharacteristicsEnabled} & + \Default{false} & + Enables (true) or disables (false) the insertion of the neural network post-filter characteristics SEI message. + \\ + \Option{SEINNPostFilterCharacteristicsNumFilters} & + \Default{0} & + Specifies the number of neural network post-filters. + \\ + \Option{SEINNPostFilterCharacteristicsId\emph{i}} & + \Default{0} & + Specifies the id of the \emph{i}-th neural network post-filter. + \\ + \Option{SEINNPostFilterCharacteristicsModeIdc\emph{i}} & + \Default{0} & + Specifies the nnpfc_mode_idc of the \emph{i}-th neural network post-filter. + \\ + \Option{SEINNPostFilterCharacteristicsPurpose\emph{i}} & + \Default{0} & + 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 \\ + \end{tabular} + \\ + \Option{SEINNPostFilterCharacteristicsOutSubWidthCFlag\emph{i}} & + \Default{false} & + When true (non-zero) specifies, for the \emph{i}-th neural network post-filter, the output SubWidthC (horizontal chroma subsampling ratio relative to luma) is smaller than the input SubWidthC. + \\ + \Option{SEINNPostFilterCharacteristicsOutSubHeightCFlag\emph{i}} & + \Default{false} & + When true (non-zero) specifies, for the \emph{i}-th neural network post-filter, the output SubHeightC (vertical chroma subsampling ratio relative to luma) is smaller than the input SubHeightC. + \\ + \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. + \\ + \Option{SEINNPostFilterCharacteristicsPicHeightInLumaSamples\emph{i}} & + \Default{0} & + Specifies the vertical luma sample counts of the output picture for the \emph{i}-th neural network post-filter. + \\ + \Option{SEINNPostFilterCharacteristicsComponentLastFlag\emph{i}} & + \Default{false} & + Specifies, for the \emph{i}-th neural network post-filter, the location of the channel component in the input and output tensors. + \par + \begin{tabular}{cp{0.35\textwidth}} + true & Specifies that the last dimension in the input tensor to the \emph{i}-th neural network post-filter and the output tensor outputTensor resulting from the \emph{i}-th neural network post-filter is used for the channel. \\ + false & Specifies that the second dimension in the input tensor to the \emph{i}-th neural network post-filter and the output tensor resulting from the \emph{i}-th neural network post-filter is used for the channel. \\ + \end{tabular} + \\ + \Option{SEINNPostFilterCharacteristicsInpSampleIdc\emph{i}} & + \Default{0} & + Specifies the method of converting an input sample for the \emph{i}-th neural network post-filter. + \\ + \Option{SEINNPostFilterCharacteristicsInpTensorBitDepthMinus8\emph{i}} & + \Default{0} & + Specifies the bit depth of the input tensor - 8 for the \emph{i}-th neural network post-filter, when nnpfc_inp_sample_idc = 4. + \\ + \Option{SEINNPostFilterCharacteristicsInpOrderIdc\emph{i}} & + \Default{0} & + Specifies the method of ordering the input sample arrays for the \emph{i}-th neural network post-filter. + \par + \begin{tabular}{cp{0.35\textwidth}} + 0 & Only the luma matrix is present in the input tensor, thus the number of channels is 1 \\ + 1 & Only the chroma matrices are present in the input tensor, thus the number of channels is 2 \\ + 2 & The luma and chroma matrices are present in the input tensor, thus the number of channels is 3 \\ + 3 & Four luma matrices, two chroma matrices, and a quantization parameter matrix are present in the input tensor, thus the number of channels is 7 \\ + \end{tabular} + \\ + \Option{SEINNPostFilterCharacteristicsOutSampleIdc\emph{i}} & + \Default{0} & + Specifies the method of converting an output sample for the \emph{i}-th neural network post-filter. + \\ + \Option{SEINNPostFilterCharacteristicsOutTensorBitDepthMinus8\emph{i}} & + \Default{0} & + Specifies the bit depth of the output tensor - 8 for the \emph{i}-th neural network post-filter, when nnpfc_out_sample_idc = 4. + \\ + \Option{SEINNPostFilterCharacteristicsOutOrderIdc\emph{i}} & + \Default{0} & + Specifies the method of ordering the output sample arrays for the \emph{i}-th neural network post-filter. + \par + \begin{tabular}{cp{0.35\textwidth}} + 0 & Only the luma matrix is present in the input tensor, thus the number of channels is 1 \\ + 1 & Only the chroma matrices are present in the input tensor, thus the number of channels is 2 \\ + 2 & The luma and chroma matrices are present in the input tensor, thus the number of channels is 3 \\ + 3 & Four luma matrices, two chroma matrices, and a quantization parameter matrix are present in the input tensor, thus the number of channels is 7 \\ + \end{tabular} + \\ + \Option{SEINNPostFilterCharacteristicsConstantPatchSizeFlag\emph{i}} & + \Default{false} & + Specifies nnpfc_constant_patch_size_flag of the \emph{i}-th neural network post-filter. + \par + \begin{tabular}{p{0.49\columnwidth}} + When true (non-zero) specifies that the \emph{i}-th neural network post-filter accepts exactly the patch size indicated by nnpfc_patch_width_minus1 and nnpfc_patch_height_minus1 as input. \\ + When false specifies that the \emph{i}-th neural network post-filter accepts any patch size that is a positive integer multiple of the patch size indicated by nnpfc_patch_width_minus1 and nnpfc_patch_height_minus1 as input. \\ + \end{tabular} + \\ + \Option{SEINNPostFilterCharacteristicsPatchWidthMinus1\emph{i}} & + \Default{0} & + Specifies the horizontal sample counts of a patch for the \emph{i}-th neural network post-filter. + \par + \begin{tabular}{p{0.49\columnwidth}} + When nnpfc_constant_patch_size_flag is true (non-zero), specifies the horizontal sample counts of the patch size required for the input to the \emph{i}-th neural network post-filter. \\ + When nnpfc_constant_patch_size_flag is false, any positive integer multiple of ( nnpfc_patch_width_minus1 + 1 ) may be used as the horizontal sample counts of the patch size used for the input to the \emph{i}-th neural network post-filter. \\ + \end{tabular} + \\ + \Option{SEINNPostFilterCharacteristicsPatchHeightMinus1\emph{i}} & + \Default{0} & + Specifies the vertical sample counts of a patch for the \emph{i}-th neural network post-filter. + \par + \begin{tabular}{p{0.49\columnwidth}} + When nnpfc_constant_patch_size_flag is true (non-zero), specifies the vertical sample counts of the patch size required for the input to the \emph{i}-th neural network post-filter. \\ + When nnpfc_constant_patch_size_flag is false, any positive integer multiple of ( nnpfc_patch_height_minus1 + 1 ) may be used as the vertical sample counts of the patch size used for the input to the \emph{i}-th neural network post-filter. \\ + \end{tabular} + \\ + \Option{SEINNPostFilterCharacteristicsOverlap\emph{i}} & + \Default{0} & + Specifies the overlapping horizontal and vertical sample counts of adjacent input tensors of the \emph{i}-th neural network post-filter. + \\ + \Option{SEINNPostFilterCharacteristicsPaddingType\emph{i}} & + \Default{0} & + Specifies the process of padding when referencing sample locations outside the boundaries of the cropped decoded output picture for the \emph{i}-th neural network post-filter. + \par + \begin{tabular}{cp{0.35\textwidth}} + 0 & zero padding \\ + 1 & replication padding \\ + 2 & reflection padding \\ + \end{tabular} + \\ + \Option{SEINNPostFilterCharacteristicsComplexityIdc\emph{i}} & + \Default{0} & + Specifies the nnpfc_complexity_idc of the \emph{i}-th neural network post-filter. + \\ + \Option{SEINNPostFilterCharacteristicsParameterTypeFlag\emph{i}} & + \Default{false} & + Specifies the nnpfc_parameter_type_flag of the \emph{i}-th neural network post-filter. + \par + \begin{tabular}{cp{0.35\textwidth}} + false & Indicates that the \emph{i}-th neural network post-filter uses only integer parameters \\ + true & Indicates that the \emph{i}-th neural network post-filter may use floating point or integer parameters \\ + \end{tabular} + \\ + \Option{SEINNPostFilterCharacteristicsLog2ParameterBitLengthMinus3\emph{i}} & + \Default{0} & + 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{SEINNPostFilterCharacteristicsNumParametersIdc\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 + parameters is not specified. + \\ + \Option{SEINNPostFilterCharacteristicsNumParametersIdc\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 specifies that the maximum number of neural network parameters is not specified. + \\ + \Option{SEINNPostFilterCharacteristicsNumKmacOperationsIdc\emph{i}} & + \Default{0} & + Specifies that the maximum number of multiply-accumulate (MAC) operations per sample of the \emph{i}-th neural network post-filter is less than or equal to nnpfc_num_kmac_operations_idc * 1000. + nnpfc_num_kmac_operations_idc = 0 specifies that the maximum number of MAC operations of the network is not specified. + \\ + \Option{SEINNPostFilterCharacteristicsPayloadFilename\emph{i}} & + \Default{""} & + Specifies the NNR bitstream of the \emph{i}-th neural network post-filter. + \\ +\end{OptionTableNoShorthand} + +\begin{OptionTableNoShorthand}{Neural network post-filter characteristics}{tab:sei-nn-post-filter-activation} + \Option{SEINNPostFilterActivationEnabled} & + \Default{false} & + Enables (true) or disables (false) the insertion of the neural network post-filter activation SEI message. + \\ + \Option{SEINNPostFilterActivationId} & + \Default{0} & + Specifies the id of the neural network post-filter. + \\ + \end{OptionTableNoShorthand} +\end{OptionTableNoShorthand} %\Option{SEITimeCode} & %\Default{false} & diff --git a/source/App/EncoderApp/EncApp.cpp b/source/App/EncoderApp/EncApp.cpp index 74ea378a6c..3fb52c6c44 100644 --- a/source/App/EncoderApp/EncApp.cpp +++ b/source/App/EncoderApp/EncApp.cpp @@ -1115,6 +1115,40 @@ void EncApp::xInitLibCfg() #if JVET_Z0120_SII_SEI_PROCESSING m_cEncLib.setShutterFilterFlag(m_ShutterFilterEnable); m_cEncLib.setBlendingRatioSII(m_SII_BlendingRatio); +#endif +#if JVET_Z0244 + m_cEncLib.setNNPostFilterSEICharacteristicsEnabled (m_nnPostFilterSEICharacteristicsEnabled); + m_cEncLib.setNNPostFilterSEICharacteristicsNumFilters (m_nnPostFilterSEICharacteristicsNumFilters); + for (int i = 0; i < m_nnPostFilterSEICharacteristicsNumFilters; i++) + { + m_cEncLib.setNNPostFilterSEICharacteristicsId (m_nnPostFilterSEICharacteristicsId[i], i); + m_cEncLib.setNNPostFilterSEICharacteristicsModeIdc (m_nnPostFilterSEICharacteristicsModeIdc[i], i); + m_cEncLib.setNNPostFilterSEICharacteristicsPurpose (m_nnPostFilterSEICharacteristicsPurpose[i], i); + m_cEncLib.setNNPostFilterSEICharacteristicsOutSubWidthCFlag (m_nnPostFilterSEICharacteristicsOutSubWidthCFlag[i], i); + m_cEncLib.setNNPostFilterSEICharacteristicsOutSubHeightCFlag (m_nnPostFilterSEICharacteristicsOutSubHeightCFlag[i], i); + m_cEncLib.setNNPostFilterSEICharacteristicsPicWidthInLumaSamples (m_nnPostFilterSEICharacteristicsPicWidthInLumaSamples[i], i); + m_cEncLib.setNNPostFilterSEICharacteristicsPicHeightInLumaSamples (m_nnPostFilterSEICharacteristicsPicHeightInLumaSamples[i], i); + m_cEncLib.setNNPostFilterSEICharacteristicsInpTensorBitDepthMinus8 (m_nnPostFilterSEICharacteristicsInpTensorBitDepthMinus8[i], i); + m_cEncLib.setNNPostFilterSEICharacteristicsOutTensorBitDepthMinus8 (m_nnPostFilterSEICharacteristicsOutTensorBitDepthMinus8[i], i); + m_cEncLib.setNNPostFilterSEICharacteristicsComponentLastFlag (m_nnPostFilterSEICharacteristicsComponentLastFlag[i], i); + m_cEncLib.setNNPostFilterSEICharacteristicsInpSampleIdc (m_nnPostFilterSEICharacteristicsInpSampleIdc[i], i); + m_cEncLib.setNNPostFilterSEICharacteristicsInpOrderIdc (m_nnPostFilterSEICharacteristicsInpOrderIdc[i], i); + m_cEncLib.setNNPostFilterSEICharacteristicsOutSampleIdc (m_nnPostFilterSEICharacteristicsOutSampleIdc[i], i); + m_cEncLib.setNNPostFilterSEICharacteristicsOutOrderIdc (m_nnPostFilterSEICharacteristicsOutOrderIdc[i], i); + m_cEncLib.setNNPostFilterSEICharacteristicsConstantPatchSizeFlag ( m_nnPostFilterSEICharacteristicsConstantPatchSizeFlag[i], i); + m_cEncLib.setNNPostFilterSEICharacteristicsPatchWidthMinus1 ( m_nnPostFilterSEICharacteristicsPatchWidthMinus1[i], i); + m_cEncLib.setNNPostFilterSEICharacteristicsPatchHeightMinus1 ( m_nnPostFilterSEICharacteristicsPatchHeightMinus1[i], i); + m_cEncLib.setNNPostFilterSEICharacteristicsOverlap ( m_nnPostFilterSEICharacteristicsOverlap[i], i); + m_cEncLib.setNNPostFilterSEICharacteristicsPaddingType ( m_nnPostFilterSEICharacteristicsPaddingType[i], i); + m_cEncLib.setNNPostFilterSEICharacteristicsPayloadFilename ( m_nnPostFilterSEICharacteristicsPayloadFilename[i], i); + m_cEncLib.setNNPostFilterSEICharacteristicsComplexityIdc ( m_nnPostFilterSEICharacteristicsComplexityIdc[i], i); + m_cEncLib.setNNPostFilterSEICharacteristicsParameterTypeFlag ( m_nnPostFilterSEICharacteristicsParameterTypeFlag[i], i); + m_cEncLib.setNNPostFilterSEICharacteristicsLog2ParameterBitLengthMinus3 ( m_nnPostFilterSEICharacteristicsLog2ParameterBitLengthMinus3[i], i); + m_cEncLib.setNNPostFilterSEICharacteristicsNumParametersIdc ( m_nnPostFilterSEICharacteristicsNumParametersIdc[i], i); + m_cEncLib.setNNPostFilterSEICharacteristicsNumKmacOperationsIdc ( m_nnPostFilterSEICharacteristicsNumKmacOperationsIdc[i], i); + } + m_cEncLib.setNnPostFilterSEIActivationEnabled (m_nnPostFilterSEIActivationEnabled); + m_cEncLib.setNnPostFilterSEIActivationId (m_nnPostFilterSEIActivationId); #endif m_cEncLib.setEntropyCodingSyncEnabledFlag ( m_entropyCodingSyncEnabledFlag ); m_cEncLib.setEntryPointPresentFlag ( m_entryPointPresentFlag ); diff --git a/source/App/EncoderApp/EncAppCfg.cpp b/source/App/EncoderApp/EncAppCfg.cpp index 6a1ddc3fbc..39bd6ebca9 100644 --- a/source/App/EncoderApp/EncAppCfg.cpp +++ b/source/App/EncoderApp/EncAppCfg.cpp @@ -1660,6 +1660,116 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] ) opts.addOptions()(cOSS2.str(), m_olsPtlIdx[i], 0); } +#if JVET_Z0244 + opts.addOptions()("SEINNPostFilterCharacteristicsEnabled", m_nnPostFilterSEICharacteristicsEnabled, false, "Control generation of the Neural Network Post Filter Characteristics SEI messages"); + opts.addOptions()( "SEINNPostFilterCharacteristicsNumFilters", m_nnPostFilterSEICharacteristicsNumFilters, 0, "Specifies the number of Neural Network Post Filter Characteristics SEI messages" ); + for (int i = 0; i < MAX_NUM_NN_POST_FILTERS; i++) + { + std::ostringstream id; + id << "SEINNPostFilterCharacteristicsId" << i; + opts.addOptions()(id.str(), m_nnPostFilterSEICharacteristicsId[i], 0u, "Specifies the identifying number in the Neural Network Post Filter Characteristics SEI message"); + + std::ostringstream modeIdc; + modeIdc << "SEINNPostFilterCharacteristicsModeIdc" << i; + opts.addOptions()(modeIdc.str(), m_nnPostFilterSEICharacteristicsModeIdc[i], 0u, "Specifies the Neural Network Post Filter IDC in the Neural Network Post Filter Characteristics SEI message"); + + 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"); + + std::ostringstream outSubWidthCFlag; + outSubWidthCFlag << "SEINNPostFilterCharacteristicsOutSubWidthCFlag" << i; + opts.addOptions()(outSubWidthCFlag.str(), m_nnPostFilterSEICharacteristicsOutSubWidthCFlag[i], false, "Specifies if the output SubWidthC (horizontal chroma subsampling ratio relative to luma) is smaller than the input SubWidthC"); + + std::ostringstream outSubHeightCFlag; + outSubHeightCFlag << "SEINNPostFilterCharacteristicsOutSubHeightCFlag" << i; + opts.addOptions()(outSubHeightCFlag.str(), m_nnPostFilterSEICharacteristicsOutSubHeightCFlag[i], false, "Specifies if the output SubHeightC (vertical chroma subsampling ratio relative to luma) is smaller than the input SubHeightC"); + + 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"); + + std::ostringstream picHeightInLumaSamples; + picHeightInLumaSamples << "SEINNPostFilterCharacteristicsPicHeightInLumaSamples" << i; + opts.addOptions()(picHeightInLumaSamples.str(), m_nnPostFilterSEICharacteristicsPicHeightInLumaSamples[i], 0u, "Specifies the vertical luma sample counts of the output picture in the Neural Network Post Filter Characteristics SEI message"); + + std::ostringstream inpTensorBitDepthMinus8; + inpTensorBitDepthMinus8 << "SEINNPostFilterCharacteristicsInpTensorBitDepthMinus8" << i; + opts.addOptions()(inpTensorBitDepthMinus8.str(), m_nnPostFilterSEICharacteristicsInpTensorBitDepthMinus8[i], 0u, "Specifies the bit depth of the input tensor minus 8 in the Neural Network Post Filter Characteristics SEI message"); + + std::ostringstream outTensorBitDepthMinus8; + outTensorBitDepthMinus8 << "SEINNPostFilterCharacteristicsOutTensorBitDepthMinus8" << i; + opts.addOptions()(outTensorBitDepthMinus8.str(), m_nnPostFilterSEICharacteristicsOutTensorBitDepthMinus8[i], 0u, "Specifies the bit depth of the output tensor minus 8 in the Neural Network Post Filter Characteristics SEI message"); + + std::ostringstream componentLastFlag; + componentLastFlag << "SEINNPostFilterCharacteristicsComponentLastFlag" << i; + opts.addOptions()(componentLastFlag.str(), m_nnPostFilterSEICharacteristicsComponentLastFlag[i], false, "Specifies the channel component is located in the last dimension for the Neural Network Post Filter Characteristics SEI message"); + + std::ostringstream inpSampleIdc; + inpSampleIdc << "SEINNPostFilterCharacteristicsInpSampleIdc" << i; + opts.addOptions()(inpSampleIdc.str(), m_nnPostFilterSEICharacteristicsInpSampleIdc[i], 0u, "Specifies the method of converting an input sample in the the Neural Network Post Filter Characteristics SEI message"); + + std::ostringstream inpOrderIdc; + inpOrderIdc << "SEINNPostFilterCharacteristicsInpOrderIdc" << i; + opts.addOptions()(inpOrderIdc.str(), m_nnPostFilterSEICharacteristicsInpOrderIdc[i], 0u, "Specifies the method of ordering the input sample arrays in the Neural Network Post Filter Characteristics SEI message"); + + std::ostringstream outSampleIdc; + outSampleIdc << "SEINNPostFilterCharacteristicsOutSampleIdc" << i; + opts.addOptions()(outSampleIdc.str(), m_nnPostFilterSEICharacteristicsOutSampleIdc[i], 0u, "Specifies the method of converting an output sample in the the Neural Network Post Filter Characteristics SEI message"); + + std::ostringstream outOrderIdc; + outOrderIdc << "SEINNPostFilterCharacteristicsOutOrderIdc" << i; + opts.addOptions()(outOrderIdc.str(), m_nnPostFilterSEICharacteristicsOutOrderIdc[i], 0u, "Specifies the method of ordering the output sample arrays in the Neural Network Post Filter Characteristics SEI message"); + + std::ostringstream constantPatchSizeFlag; + constantPatchSizeFlag << "SEINNPostFilterCharacteristicsConstantPatchSizeFlag" << i; + opts.addOptions()(constantPatchSizeFlag.str(), m_nnPostFilterSEICharacteristicsConstantPatchSizeFlag[i], false, "Specifies the patch size flag in the the Neural Network Post Filter Characteristics SEI message"); + + std::ostringstream patchWidthMinus1; + patchWidthMinus1 << "SEINNPostFilterCharacteristicsPatchWidthMinus1" << i; + opts.addOptions()(patchWidthMinus1.str(), m_nnPostFilterSEICharacteristicsPatchWidthMinus1[i], 0u, "Specifies the horizontal sample counts of a patch in the Neural Network Post Filter Characteristics SEI message"); + + std::ostringstream patchHeightMinus1; + patchHeightMinus1 << "SEINNPostFilterCharacteristicsPatchHeightMinus1" << i; + opts.addOptions()(patchHeightMinus1.str(), m_nnPostFilterSEICharacteristicsPatchHeightMinus1[i], 0u, "Specifies the vertical sample counts of a patch in the Neural Network Post Filter Characteristics SEI message"); + + std::ostringstream overlap; + overlap << "SEINNPostFilterCharacteristicsOverlap" << i; + opts.addOptions()(overlap.str(), m_nnPostFilterSEICharacteristicsOverlap[i], 0u, "Specifies the overlap in the Neural Network Post Filter Characteristics SEI message"); + + std::ostringstream paddingType; + paddingType << "SEINNPostFilterCharacteristicsPaddingType" << i; + opts.addOptions()(paddingType.str(), m_nnPostFilterSEICharacteristicsPaddingType[i], 0u, "Specifies the process of padding when referencing sample locations outside the boundaries of the cropped decoded output picture "); + + std::ostringstream complexityIdc; + complexityIdc << "SEINNPostFilterCharacteristicsComplexityIdc" << i; + opts.addOptions()(complexityIdc.str(), m_nnPostFilterSEICharacteristicsComplexityIdc[i], 0u, "Specifies the value of nnpfc_complexity_idc in the Neural Network Post Filter Characteristics SEI message"); + + std::ostringstream parameterTypeFlag; + parameterTypeFlag << "SEINNPostFilterCharacteristicsParameterTypeFlag" << i; + opts.addOptions()(parameterTypeFlag.str(), m_nnPostFilterSEICharacteristicsParameterTypeFlag[i], false, "Specifies the data type of parameters in the Neural Network Post Filter Characteristics SEI message"); + + std::ostringstream log2ParameterBitLengthMinus3; + log2ParameterBitLengthMinus3 << "SEINNPostFilterCharacteristicsLog2ParameterBitLengthMinus3" << i; + opts.addOptions()(log2ParameterBitLengthMinus3.str(), m_nnPostFilterSEICharacteristicsLog2ParameterBitLengthMinus3[i], 0u, "Indicates that the neural network does not use parameter of bit length greater than 2^(N+3) bits"); + + std::ostringstream numParametersIdc; + numParametersIdc << "SEINNPostFilterCharacteristicsNumParametersIdc" << i; + opts.addOptions()(numParametersIdc.str(), m_nnPostFilterSEICharacteristicsNumParametersIdc[i], 0u, "Specifies the maximum number of parameters ((2048<<NumParametersIdc)-1) in the Neural Network Post Filter Characteristics SEI message"); + + std::ostringstream numKmacOperationsIdc; + numKmacOperationsIdc << "SEINNPostFilterCharacteristicsNumKmacOperationsIdc" << i; + opts.addOptions()(numKmacOperationsIdc.str(), m_nnPostFilterSEICharacteristicsNumKmacOperationsIdc[i], 0u, "Specifies the maximum number of operations (KMAC) per pixel in the Neural Network Post Filter Characteristics SEI message"); + + std::ostringstream payloadFilename; + payloadFilename << "SEINNPostFilterCharacteristicsPayloadFilename" << i; + opts.addOptions()(payloadFilename.str(), m_nnPostFilterSEICharacteristicsPayloadFilename[i], string(""), "Specifies the NNR bitstream in the Neural Network Post Filter Characteristics SEI message"); + + opts.addOptions()("SEINNPostFilterActivationEnabled", m_nnPostFilterSEIActivationEnabled, false, "Control use of the Neural Network Post Filter SEI on current picture"); + opts.addOptions()("SEINNPostFilterActivationId", m_nnPostFilterSEIActivationId , 0u, "Id of the Neural Network Post Filter on current picture"); + } +#endif + po::setDefaults(opts); po::ErrorReporter err; const list<const char*>& argv_unhandled = po::scanArgv(opts, argc, (const char**) argv, err); @@ -4468,6 +4578,36 @@ bool EncAppCfg::xCheckParameter() } #endif +#if JVET_Z0244 + if (m_nnPostFilterSEICharacteristicsEnabled) + { + for (int i = 0; i < m_nnPostFilterSEICharacteristicsNumFilters; i++) + { + xConfirmPara(m_nnPostFilterSEICharacteristicsId[i] > (uint32_t)(((uint64_t)1 << 32) - 2), "SEINNPostFilterCharacteristicsId must be in the range of 0 to 2^32-2"); + xConfirmPara(m_nnPostFilterSEICharacteristicsModeIdc[i] > 255, "SEINNPostFilterCharacteristicsModeIdc must be in the range of 0 to 255"); + xConfirmPara(m_nnPostFilterSEICharacteristicsPurpose[i] > (uint32_t)(((uint64_t)1 << 32) - 2), "SEINNPostFilterCharacteristicsPurpose must be in the range of 0 to 2^32-2"); + xConfirmPara(m_nnPostFilterSEICharacteristicsInpTensorBitDepthMinus8[i] > 24, "SEINNPostFilterCharacteristicsInpTensorBitDepthMinus8 must be in the range of 0 to 24"); + xConfirmPara(m_nnPostFilterSEICharacteristicsOutTensorBitDepthMinus8[i] > 24, "SEINNPostFilterCharacteristicsOutTensorBitDepthMinus8 must be in the range of 0 to 24"); + xConfirmPara(m_nnPostFilterSEICharacteristicsInpSampleIdc[i] > 255, "SEINNPostFilterCharacteristicsInpSampleIdc must be in the range of 0 to 255"); + xConfirmPara(m_nnPostFilterSEICharacteristicsInpOrderIdc[i] > 255, "SEINNPostFilterCharacteristicsInpOrderIdc must be in the range of 0 to 255"); + xConfirmPara(m_nnPostFilterSEICharacteristicsOutSampleIdc[i] > 255, "SEINNPostFilterCharacteristicsOutSampleIdc must be in the range of 0 to 255"); + xConfirmPara(m_nnPostFilterSEICharacteristicsOutOrderIdc[i] > 255, "SEINNPostFilterCharacteristicsOutOrderIdc must be in the range of 0 to 255"); + xConfirmPara(m_nnPostFilterSEICharacteristicsPatchWidthMinus1[i] > 32766, "SEINNPostFilterCharacteristicsPatchWidthMinus1 must be in the range of 0 to 32766"); + xConfirmPara(m_nnPostFilterSEICharacteristicsPatchHeightMinus1[i] > 32766, "SEINNPostFilterCharacteristicsPatchHeightMinus1 must be in the range of 0 to 32766"); + xConfirmPara(m_nnPostFilterSEICharacteristicsOverlap[i] > 16383, "SEINNPostFilterCharacteristicsOverlap must be in the range of 0 to 16383"); + xConfirmPara(m_nnPostFilterSEICharacteristicsPaddingType[i] > (1 << 4) - 1, "SEINNPostFilterPaddingType must be in the range of 0 to 2^4-1"); + xConfirmPara(m_nnPostFilterSEICharacteristicsComplexityIdc[i] > 255, "SEINNPostFilterCharacteristicsComplexityIdc must be in the range of 0 to 255"); + xConfirmPara(m_nnPostFilterSEICharacteristicsLog2ParameterBitLengthMinus3[i] > 3, "SEINNPostFilterCharacteristicsLog2ParameterBitLengthMinus3 must be in the range of 0 to 3"); + xConfirmPara(m_nnPostFilterSEICharacteristicsNumParametersIdc[i] > 255, "SEINNPostFilterCharacteristicsNumParametersIdc must be in the range of 0 to 255"); + } + } + + if (m_nnPostFilterSEIActivationEnabled) + { + xConfirmPara(m_nnPostFilterSEIActivationId > (1 << 20) - 1, "SEINNPostFilterActivationId must be in the range of 0 to 2^20-1"); + } +#endif + xConfirmPara(m_log2ParallelMergeLevel < 2, "Log2ParallelMergeLevel should be larger than or equal to 2"); xConfirmPara(m_log2ParallelMergeLevel > m_uiCTUSize, "Log2ParallelMergeLevel should be less than or equal to CTU size"); #if U0033_ALTERNATIVE_TRANSFER_CHARACTERISTICS_SEI diff --git a/source/App/EncoderApp/EncAppCfg.h b/source/App/EncoderApp/EncAppCfg.h index 792fba6498..7d39613cdd 100644 --- a/source/App/EncoderApp/EncAppCfg.h +++ b/source/App/EncoderApp/EncAppCfg.h @@ -727,6 +727,38 @@ protected: CfgSEISubpictureLevel m_cfgSubpictureLevelInfoSEI; +#if JVET_Z0244 + bool m_nnPostFilterSEICharacteristicsEnabled; + int m_nnPostFilterSEICharacteristicsNumFilters; + uint32_t m_nnPostFilterSEICharacteristicsId[MAX_NUM_NN_POST_FILTERS]; + uint32_t m_nnPostFilterSEICharacteristicsModeIdc[MAX_NUM_NN_POST_FILTERS]; + uint32_t m_nnPostFilterSEICharacteristicsPurpose[MAX_NUM_NN_POST_FILTERS]; + bool m_nnPostFilterSEICharacteristicsOutSubWidthCFlag[MAX_NUM_NN_POST_FILTERS]; + bool m_nnPostFilterSEICharacteristicsOutSubHeightCFlag[MAX_NUM_NN_POST_FILTERS]; + 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]; + uint32_t m_nnPostFilterSEICharacteristicsOutTensorBitDepthMinus8[MAX_NUM_NN_POST_FILTERS]; + bool m_nnPostFilterSEICharacteristicsComponentLastFlag[MAX_NUM_NN_POST_FILTERS]; + uint32_t m_nnPostFilterSEICharacteristicsInpSampleIdc[MAX_NUM_NN_POST_FILTERS]; + uint32_t m_nnPostFilterSEICharacteristicsInpOrderIdc[MAX_NUM_NN_POST_FILTERS]; + uint32_t m_nnPostFilterSEICharacteristicsOutSampleIdc[MAX_NUM_NN_POST_FILTERS]; + uint32_t m_nnPostFilterSEICharacteristicsOutOrderIdc[MAX_NUM_NN_POST_FILTERS]; + bool m_nnPostFilterSEICharacteristicsConstantPatchSizeFlag[MAX_NUM_NN_POST_FILTERS]; + uint32_t m_nnPostFilterSEICharacteristicsPatchWidthMinus1[MAX_NUM_NN_POST_FILTERS]; + uint32_t m_nnPostFilterSEICharacteristicsPatchHeightMinus1[MAX_NUM_NN_POST_FILTERS]; + uint32_t m_nnPostFilterSEICharacteristicsOverlap[MAX_NUM_NN_POST_FILTERS]; + uint32_t m_nnPostFilterSEICharacteristicsPaddingType[MAX_NUM_NN_POST_FILTERS]; + std::string m_nnPostFilterSEICharacteristicsPayloadFilename[MAX_NUM_NN_POST_FILTERS]; + uint32_t m_nnPostFilterSEICharacteristicsComplexityIdc[MAX_NUM_NN_POST_FILTERS]; + bool m_nnPostFilterSEICharacteristicsParameterTypeFlag[MAX_NUM_NN_POST_FILTERS]; + uint32_t m_nnPostFilterSEICharacteristicsLog2ParameterBitLengthMinus3[MAX_NUM_NN_POST_FILTERS]; + uint32_t m_nnPostFilterSEICharacteristicsNumParametersIdc[MAX_NUM_NN_POST_FILTERS]; + uint32_t m_nnPostFilterSEICharacteristicsNumKmacOperationsIdc[MAX_NUM_NN_POST_FILTERS]; + bool m_nnPostFilterSEIActivationEnabled; + uint32_t m_nnPostFilterSEIActivationId; +#endif + bool m_constrainedRaslEncoding; bool m_sampleAspectRatioInfoSEIEnabled; diff --git a/source/Lib/CommonLib/CommonDef.h b/source/Lib/CommonLib/CommonDef.h index 4401be2761..458184e345 100644 --- a/source/Lib/CommonLib/CommonDef.h +++ b/source/Lib/CommonLib/CommonDef.h @@ -168,6 +168,10 @@ static const int MAX_VPS_SUBLAYERS = 7; static const int MAX_NUM_OLSS = 256; static const int MAX_VPS_OLS_MODE_IDC = 2; +#if JVET_Z0244 +static const int MAX_NUM_NN_POST_FILTERS = 8; +#endif + static const int MIP_MAX_WIDTH = MAX_TB_SIZEY; static const int MIP_MAX_HEIGHT = MAX_TB_SIZEY; diff --git a/source/Lib/CommonLib/SEI.cpp b/source/Lib/CommonLib/SEI.cpp index 778050f99b..d85b7a1f3e 100644 --- a/source/Lib/CommonLib/SEI.cpp +++ b/source/Lib/CommonLib/SEI.cpp @@ -479,6 +479,10 @@ const char *SEI::getSEIMessageString(SEI::PayloadType payloadType) case SEI::VDI_SEI_ENVELOPE: return "Video decoding interface SEI envelope"; #if JVET_Z0120_SHUTTER_INTERVAL_SEI case SEI::SHUTTER_INTERVAL_INFO: return "Shutter interval information"; +#endif +#if JVET_Z0244 + case SEI::NEURAL_NETWORK_POST_FILTER_CHARACTERISTICS: return "Neural network post-filter characteristics"; + case SEI::NEURAL_NETWORK_POST_FILTER_ACTIVATION: return "Neural network post-filter activation"; #endif default: return "Unknown"; } diff --git a/source/Lib/CommonLib/SEI.h b/source/Lib/CommonLib/SEI.h index 0cb2f50e70..61d064bd1f 100644 --- a/source/Lib/CommonLib/SEI.h +++ b/source/Lib/CommonLib/SEI.h @@ -93,6 +93,10 @@ public: VDI_SEI_ENVELOPE = 208, #if JVET_Z0120_SHUTTER_INTERVAL_SEI SHUTTER_INTERVAL_INFO = 209, +#endif +#if JVET_Z0244 + NEURAL_NETWORK_POST_FILTER_CHARACTERISTICS = 210, + NEURAL_NETWORK_POST_FILTER_ACTIVATION = 211, #endif }; @@ -1064,6 +1068,90 @@ public: SEIVDISeiEnvelope() {} virtual ~SEIVDISeiEnvelope() {} }; + +#if JVET_Z0244 +class SEINeuralNetworkPostFilterCharacteristics : public SEI +{ +public: + PayloadType payloadType() const override { return NEURAL_NETWORK_POST_FILTER_CHARACTERISTICS; } + SEINeuralNetworkPostFilterCharacteristics() + : m_id(0) + , m_modeIdc(0) + , m_purpose(0) + , m_outSubWidthCFlag(false) + , m_outSubHeightCFlag(false) + , m_picWidthInLumaSamples(0) + , m_picHeightInLumaSamples(0) + , m_inpTensorBitDepthMinus8(0) + , m_outTensorBitDepthMinus8(0) + , m_componentLastFlag(false) + , m_inpSampleIdc(0) + , m_inpOrderIdc(0) + , m_outSampleIdc(0) + , m_outOrderIdc(0) + , m_constantPatchSizeFlag(false) + , m_patchWidthMinus1(0) + , m_patchHeightMinus1(0) + , m_overlap(0) + , m_paddingType(0) + , m_payloadByte(nullptr) + , m_complexityIdc(0) + , m_parameterTypeFlag(false) + , m_log2ParameterBitLengthMinus3(0) + , m_numParametersIdc(0) + , m_numKmacOperationsIdc(0) + {} + + ~SEINeuralNetworkPostFilterCharacteristics() override + { + if (m_payloadByte) + { + delete m_payloadByte; + m_payloadByte = nullptr; + } + } + + uint32_t m_id; + uint32_t m_modeIdc; + uint32_t m_purpose; + bool m_outSubWidthCFlag; + bool m_outSubHeightCFlag; + uint32_t m_picWidthInLumaSamples; + uint32_t m_picHeightInLumaSamples; + uint32_t m_inpTensorBitDepthMinus8; + uint32_t m_outTensorBitDepthMinus8; + bool m_componentLastFlag; + uint32_t m_inpSampleIdc; + uint32_t m_inpOrderIdc; + uint32_t m_outSampleIdc; + uint32_t m_outOrderIdc; + bool m_constantPatchSizeFlag; + uint32_t m_patchWidthMinus1; + uint32_t m_patchHeightMinus1; + uint32_t m_overlap; + uint32_t m_paddingType; + uint64_t m_payloadLength; + char* m_payloadByte; + uint32_t m_complexityIdc; + bool m_parameterTypeFlag; + uint32_t m_log2ParameterBitLengthMinus3; + uint32_t m_numParametersIdc; + uint32_t m_numKmacOperationsIdc; +}; + +class SEINeuralNetworkPostFilterActivation : public SEI +{ +public: + PayloadType payloadType() const { return NEURAL_NETWORK_POST_FILTER_ACTIVATION; } + SEINeuralNetworkPostFilterActivation() + : m_id(0) + {} + virtual ~SEINeuralNetworkPostFilterActivation() {} + + uint32_t m_id; +}; +#endif + //! \} diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h index e76c212af0..c816248c86 100644 --- a/source/Lib/CommonLib/TypeDef.h +++ b/source/Lib/CommonLib/TypeDef.h @@ -57,6 +57,7 @@ #define JVET_Z0111_ADAPT_BYPASS_AFFINE_ME 1 // JVET-Z0111 #define JVET_Z0046_Green_Metadata 1 // JVET-Z0046 #define JVET_Z0120_SHUTTER_INTERVAL_SEI 1 // JVET-Z0120 +#define JVET_Z0244 1 // JVET-Z0244 //########### place macros to be be kept below this line ############### #define JVET_X0143_ALF_APS_ID_OFFSET 0 // A value between 0 to 7 inclusive. This macro should be kept, or to be defined as a configuration parameter if possible. diff --git a/source/Lib/DecoderLib/SEIread.cpp b/source/Lib/DecoderLib/SEIread.cpp index c473b3a719..54b9b9c4e9 100644 --- a/source/Lib/DecoderLib/SEIread.cpp +++ b/source/Lib/DecoderLib/SEIread.cpp @@ -408,6 +408,16 @@ void SEIReader::xReadSEImessage(SEIMessages& seis, const NalUnitType nalUnitType sei = new SEIShutterIntervalInfo; xParseSEIShutterInterval((SEIShutterIntervalInfo&)*sei, payloadSize, pDecodedMessageOutputStream); break; +#endif +#if JVET_Z0244 + case SEI::NEURAL_NETWORK_POST_FILTER_CHARACTERISTICS: + sei = new SEINeuralNetworkPostFilterCharacteristics; + xParseSEINNPostFilterCharacteristics((SEINeuralNetworkPostFilterCharacteristics&)*sei, payloadSize, pDecodedMessageOutputStream); + break; + case SEI::NEURAL_NETWORK_POST_FILTER_ACTIVATION: + sei = new SEINeuralNetworkPostFilterActivation; + xParseSEINNPostFilterActivation((SEINeuralNetworkPostFilterActivation&)*sei, payloadSize, pDecodedMessageOutputStream); + break; #endif default: for (uint32_t i = 0; i < payloadSize; i++) @@ -2466,6 +2476,135 @@ void SEIReader::xParseSEIConstrainedRaslIndication( SEIConstrainedRaslIndication output_sei_message_header(sei, pDecodedMessageOutputStream, payloadSize); } +#if JVET_Z0244 +void SEIReader::xParseSEINNPostFilterCharacteristics(SEINeuralNetworkPostFilterCharacteristics& sei, uint32_t payloadSize, std::ostream *pDecodedMessageOutputStream) +{ + output_sei_message_header(sei, pDecodedMessageOutputStream, payloadSize); + uint32_t val; + + sei_read_uvlc( pDecodedMessageOutputStream, val, "nnpfc_id" ); + sei.m_id = val; + + sei_read_uvlc( pDecodedMessageOutputStream, val, "nnpfc_mode_idc" ); + sei.m_modeIdc = val; + + if (sei.m_modeIdc == 1) + { + sei_read_uvlc(pDecodedMessageOutputStream, val, "nnpfc_purpose"); + sei.m_purpose = val; + + if(sei.m_purpose == 2 || sei.m_purpose == 4) + { + sei_read_flag(pDecodedMessageOutputStream, val, "nnpfc_out_sub_width_c_flag"); + sei.m_outSubWidthCFlag = val; + sei_read_flag(pDecodedMessageOutputStream, val, "nnpfc_out_sub_height_c_flag"); + sei.m_outSubHeightCFlag = val; + } + if(sei.m_purpose == 3 || sei.m_purpose == 4) + { + sei_read_flag(pDecodedMessageOutputStream, val, "nnpfc_pic_width_in_luma_samples"); + sei.m_picWidthInLumaSamples = val; + sei_read_flag(pDecodedMessageOutputStream, val, "nnpfc_pic_height_in_luma_samples"); + sei.m_picHeightInLumaSamples = val; + } + + sei_read_flag(pDecodedMessageOutputStream, val, "nnpfc_component_last_flag"); + sei.m_componentLastFlag = val; + + sei_read_uvlc(pDecodedMessageOutputStream, val, "nnpfc_inp_sample_idc"); + sei.m_inpSampleIdc = val; + + if(sei.m_inpSampleIdc == 4) + { + sei_read_uvlc(pDecodedMessageOutputStream, val, "nnpfc_inp_tensor_bitdepth_minus8"); + sei.m_inpTensorBitDepthMinus8 = val; + } + + sei_read_uvlc(pDecodedMessageOutputStream, val, "nnpfc_inp_order_idc"); + sei.m_inpOrderIdc = val; + + sei_read_uvlc(pDecodedMessageOutputStream, val, "nnpfc_out_sample_idc"); + sei.m_outSampleIdc = val; + + if(sei.m_outSampleIdc == 4) + { + sei_read_uvlc(pDecodedMessageOutputStream, val, "nnpfc_out_tensor_bitdepth_minus8"); + sei.m_outTensorBitDepthMinus8 = val; + } + + sei_read_uvlc(pDecodedMessageOutputStream, val, "nnpfc_out_order_idc"); + sei.m_outOrderIdc = val; + + sei_read_flag(pDecodedMessageOutputStream, val, "nnpfc_constant_patch_size_flag"); + sei.m_constantPatchSizeFlag = val; + + sei_read_uvlc(pDecodedMessageOutputStream, val, "nnpfc_patch_width_minus1"); + sei.m_patchWidthMinus1 = val; + + sei_read_uvlc(pDecodedMessageOutputStream, val, "nnpfc_patch_height_minus1"); + sei.m_patchHeightMinus1 = val; + + sei_read_uvlc(pDecodedMessageOutputStream, val, "nnpfc_overlap"); + sei.m_overlap = val; + + sei_read_uvlc(pDecodedMessageOutputStream, val, "nnpfc_padding_type"); + sei.m_paddingType = val; + + sei_read_uvlc(pDecodedMessageOutputStream, val, "nnpfc_complexity_idc"); + sei.m_complexityIdc = val; + + if(sei.m_complexityIdc > 0) + { + if(sei.m_complexityIdc == 1) + { + sei_read_flag(pDecodedMessageOutputStream, val, "nnpfc_parameter_type_flag"); + sei.m_parameterTypeFlag = val; + + sei_read_code(pDecodedMessageOutputStream, 2, val, "nnpfc_log2_parameter_bit_length_minus3"); + sei.m_log2ParameterBitLengthMinus3 = val; + + sei_read_code(pDecodedMessageOutputStream, 8, val, "nnpfc_num_parameters_idc"); + sei.m_numParametersIdc = val; + + sei_read_uvlc(pDecodedMessageOutputStream, val, "nnpfc_num_kmac_operations_idc"); + sei.m_numKmacOperationsIdc = val; + } + } + } + if (sei.m_modeIdc == 1) + { + while (!isByteAligned()) + { + sei_read_flag( pDecodedMessageOutputStream, val, "nnpfc_reserved_zero_bit"); + CHECK (val != 0, "nnpfc_reserved_zero_bit not equal to zero"); + } + + int payloadBytesRemaining = getBitstream()->getNumBitsLeft() / 8; + int code; + + std::string filename = "payloadByte" + std::to_string(sei.m_id) + ".nnr"; + + std::ofstream outFile(filename.c_str(), std::ofstream::binary); + + for (int i = 0; i < payloadBytesRemaining; i++) + { + sei_read_scode ( pDecodedMessageOutputStream, 8, code, "nnpfc_payload_byte[i]"); + outFile.write((char*)&code, 1); + } + outFile.close(); + } +} + +void SEIReader::xParseSEINNPostFilterActivation(SEINeuralNetworkPostFilterActivation &sei, uint32_t payloadSize, std::ostream *pDecodedMessageOutputStream) +{ + output_sei_message_header(sei, pDecodedMessageOutputStream, payloadSize); + uint32_t val; + + sei_read_uvlc( pDecodedMessageOutputStream, val, "nnpfa_id" ); + sei.m_id =val; +} +#endif + #if JVET_S0257_DUMP_360SEI_MESSAGE void SeiCfgFileDump::write360SeiDump (std::string decoded360MessageFileName, SEIMessages& seis, const SPS* sps) { diff --git a/source/Lib/DecoderLib/SEIread.h b/source/Lib/DecoderLib/SEIread.h index 80bce57556..628f078213 100644 --- a/source/Lib/DecoderLib/SEIread.h +++ b/source/Lib/DecoderLib/SEIread.h @@ -43,6 +43,9 @@ #pragma once #endif // _MSC_VER > 1000 +#if JVET_Z0244 +#include <fstream> +#endif //! \ingroup DecoderLib //! \{ @@ -106,6 +109,10 @@ protected: #if JVET_Z0120_SHUTTER_INTERVAL_SEI void xParseSEIShutterInterval(SEIShutterIntervalInfo& sei, uint32_t payloadSize, std::ostream *pDecodedMessageOutputStream); #endif +#if JVET_Z0244 + void xParseSEINNPostFilterCharacteristics(SEINeuralNetworkPostFilterCharacteristics& sei, uint32_t payloadSize, std::ostream *pDecodedMessageOutputStream); + void xParseSEINNPostFilterActivation(SEINeuralNetworkPostFilterActivation& sei, uint32_t payloadSize, std::ostream *pDecodedMessageOutputStream); +#endif void sei_read_scode(std::ostream *pOS, uint32_t length, int& code, const char *pSymbolName); void sei_read_code(std::ostream *pOS, uint32_t length, uint32_t &ruiCode, const char *pSymbolName); diff --git a/source/Lib/EncoderLib/Analyze.h b/source/Lib/EncoderLib/Analyze.h index 9481964361..1ad6b6d604 100644 --- a/source/Lib/EncoderLib/Analyze.h +++ b/source/Lib/EncoderLib/Analyze.h @@ -83,6 +83,13 @@ public: virtual ~Analyze() {} Analyze() { clear(); } +#if JVET_Z0244 + void addBits(double bits) + { + m_dAddBits += bits; + } +#endif + void addResult( double psnr[MAX_NUM_COMPONENT], double bits, const double MSEyuvframe[MAX_NUM_COMPONENT], const double upscaledPSNR[MAX_NUM_COMPONENT], const double msssim[MAX_NUM_COMPONENT], bool isEncodeLtRef ) { diff --git a/source/Lib/EncoderLib/EncCfg.h b/source/Lib/EncoderLib/EncCfg.h index bdaf7940ef..79db3b9411 100644 --- a/source/Lib/EncoderLib/EncCfg.h +++ b/source/Lib/EncoderLib/EncCfg.h @@ -666,6 +666,39 @@ protected: std::vector<uint32_t> m_siiSEISubLayerNumUnitsInSI; #endif +#if JVET_Z0244 + bool m_nnPostFilterSEICharacteristicsEnabled; + int m_nnPostFilterSEICharacteristicsNumFilters; + uint32_t m_nnPostFilterSEICharacteristicsId[MAX_NUM_NN_POST_FILTERS]; + uint32_t m_nnPostFilterSEICharacteristicsModeIdc[MAX_NUM_NN_POST_FILTERS]; + uint32_t m_nnPostFilterSEICharacteristicsPurpose[MAX_NUM_NN_POST_FILTERS]; + bool m_nnPostFilterSEICharacteristicsOutSubWidthCFlag[MAX_NUM_NN_POST_FILTERS]; + bool m_nnPostFilterSEICharacteristicsOutSubHeightCFlag[MAX_NUM_NN_POST_FILTERS]; + 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]; + uint32_t m_nnPostFilterSEICharacteristicsOutTensorBitDepthMinus8[MAX_NUM_NN_POST_FILTERS]; + bool m_nnPostFilterSEICharacteristicsComponentLastFlag[MAX_NUM_NN_POST_FILTERS]; + uint32_t m_nnPostFilterSEICharacteristicsInpSampleIdc[MAX_NUM_NN_POST_FILTERS]; + uint32_t m_nnPostFilterSEICharacteristicsInpOrderIdc[MAX_NUM_NN_POST_FILTERS]; + uint32_t m_nnPostFilterSEICharacteristicsOutSampleIdc[MAX_NUM_NN_POST_FILTERS]; + uint32_t m_nnPostFilterSEICharacteristicsOutOrderIdc[MAX_NUM_NN_POST_FILTERS]; + bool m_nnPostFilterSEICharacteristicsConstantPatchSizeFlag[MAX_NUM_NN_POST_FILTERS]; + uint32_t m_nnPostFilterSEICharacteristicsPatchWidthMinus1[MAX_NUM_NN_POST_FILTERS]; + uint32_t m_nnPostFilterSEICharacteristicsPatchHeightMinus1[MAX_NUM_NN_POST_FILTERS]; + uint32_t m_nnPostFilterSEICharacteristicsOverlap[MAX_NUM_NN_POST_FILTERS]; + uint32_t m_nnPostFilterSEICharacteristicsPaddingType[MAX_NUM_NN_POST_FILTERS]; + std::string m_nnPostFilterSEICharacteristicsPayloadFilename[MAX_NUM_NN_POST_FILTERS]; + uint32_t m_nnPostFilterSEICharacteristicsComplexityIdc[MAX_NUM_NN_POST_FILTERS]; + bool m_nnPostFilterSEICharacteristicsParameterTypeFlag [MAX_NUM_NN_POST_FILTERS]; + uint32_t m_nnPostFilterSEICharacteristicsLog2ParameterBitLengthMinus3[MAX_NUM_NN_POST_FILTERS]; + uint32_t m_nnPostFilterSEICharacteristicsNumParametersIdc[MAX_NUM_NN_POST_FILTERS]; + uint32_t m_nnPostFilterSEICharacteristicsNumKmacOperationsIdc[MAX_NUM_NN_POST_FILTERS]; + + bool m_nnPostFilterSEIActivationEnabled; + uint32_t m_nnPostFilterSEIActivationId; +#endif + // film grain characterstics sei bool m_fgcSEIEnabled; bool m_fgcSEICancelFlag; @@ -1728,6 +1761,72 @@ public: void setSiiSEISubLayerNumUnitsInSI(const std::vector<uint32_t>& b) { m_siiSEISubLayerNumUnitsInSI = b; } uint32_t getSiiSEISubLayerNumUnitsInSI(uint32_t idx) const { return m_siiSEISubLayerNumUnitsInSI[idx]; } #endif + +#if JVET_Z0244 + void setNNPostFilterSEICharacteristicsEnabled(bool enabledFlag) { m_nnPostFilterSEICharacteristicsEnabled = enabledFlag; } + bool getNNPostFilterSEICharacteristicsEnabled() const { return m_nnPostFilterSEICharacteristicsEnabled; } + void setNNPostFilterSEICharacteristicsNumFilters(int numFilters) { m_nnPostFilterSEICharacteristicsNumFilters = numFilters; } + int getNNPostFilterSEICharacteristicsNumFilters() const { return m_nnPostFilterSEICharacteristicsNumFilters; } + void setNNPostFilterSEICharacteristicsId(uint32_t id, int filterIdx) { m_nnPostFilterSEICharacteristicsId[filterIdx] = id; } + uint32_t getNNPostFilterSEICharacteristicsId(int filterIdx) const { return m_nnPostFilterSEICharacteristicsId[filterIdx]; } + void setNNPostFilterSEICharacteristicsModeIdc(uint32_t idc, int filterIdx) { m_nnPostFilterSEICharacteristicsModeIdc[filterIdx] = idc; } + uint32_t getNNPostFilterSEICharacteristicsModeIdc(int filterIdx) const { return m_nnPostFilterSEICharacteristicsModeIdc[filterIdx]; } + void setNNPostFilterSEICharacteristicsPurpose(uint32_t purpose, int filterIdx) { m_nnPostFilterSEICharacteristicsPurpose[filterIdx] = purpose; } + uint32_t getNNPostFilterSEICharacteristicsPurpose(int filterIdx) const { return m_nnPostFilterSEICharacteristicsPurpose[filterIdx]; } + + void setNNPostFilterSEICharacteristicsOutSubWidthCFlag(bool outSubWidthCFlag, int filterIdx) { m_nnPostFilterSEICharacteristicsOutSubWidthCFlag[filterIdx] = outSubWidthCFlag; } + bool getNNPostFilterSEICharacteristicsOutSubWidthCFlag(int filterIdx) const { return m_nnPostFilterSEICharacteristicsOutSubWidthCFlag[filterIdx]; } + void setNNPostFilterSEICharacteristicsOutSubHeightCFlag(bool outSubHeightCFlag, int filterIdx) { m_nnPostFilterSEICharacteristicsOutSubHeightCFlag[filterIdx] = outSubHeightCFlag; } + bool getNNPostFilterSEICharacteristicsOutSubHeightCFlag(int filterIdx) const { return m_nnPostFilterSEICharacteristicsOutSubHeightCFlag[filterIdx]; } + 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; } + uint32_t getNNPostFilterSEICharacteristicsPicHeightInLumaSamples(int filterIdx) const { return m_nnPostFilterSEICharacteristicsPicHeightInLumaSamples[filterIdx]; } + void setNNPostFilterSEICharacteristicsInpTensorBitDepthMinus8(uint32_t inpTensorBitDepthMinus8, int filterIdx) { m_nnPostFilterSEICharacteristicsInpTensorBitDepthMinus8[filterIdx] = inpTensorBitDepthMinus8; } + uint32_t getNNPostFilterSEICharacteristicsInpTensorBitDepthMinus8(int filterIdx) const { return m_nnPostFilterSEICharacteristicsInpTensorBitDepthMinus8[filterIdx]; } + void setNNPostFilterSEICharacteristicsOutTensorBitDepthMinus8(uint32_t outTensorBitDepthMinus8, int filterIdx) { m_nnPostFilterSEICharacteristicsOutTensorBitDepthMinus8[filterIdx] = outTensorBitDepthMinus8; } + uint32_t getNNPostFilterSEICharacteristicsOutTensorBitDepthMinus8(int filterIdx) const { return m_nnPostFilterSEICharacteristicsOutTensorBitDepthMinus8[filterIdx]; } + + void setNNPostFilterSEICharacteristicsComponentLastFlag(bool componentLastFlag, int filterIdx) { m_nnPostFilterSEICharacteristicsComponentLastFlag[filterIdx] = componentLastFlag; } + bool getNNPostFilterSEICharacteristicsComponentLastFlag(int filterIdx) const { return m_nnPostFilterSEICharacteristicsComponentLastFlag[filterIdx]; } + void setNNPostFilterSEICharacteristicsInpSampleIdc(uint32_t inpSampleIdc, int filterIdx) { m_nnPostFilterSEICharacteristicsInpSampleIdc[filterIdx] = inpSampleIdc; } + uint32_t getNNPostFilterSEICharacteristicsInpSampleIdc(int filterIdx) const { return m_nnPostFilterSEICharacteristicsInpSampleIdc[filterIdx]; } + void setNNPostFilterSEICharacteristicsInpOrderIdc(uint32_t inpOrderIdc, int filterIdx) { m_nnPostFilterSEICharacteristicsInpOrderIdc[filterIdx] = inpOrderIdc; } + uint32_t getNNPostFilterSEICharacteristicsInpOrderIdc(int filterIdx) const { return m_nnPostFilterSEICharacteristicsInpOrderIdc[filterIdx]; } + void setNNPostFilterSEICharacteristicsOutSampleIdc(uint32_t outSampleIdc, int filterIdx) { m_nnPostFilterSEICharacteristicsOutSampleIdc[filterIdx] = outSampleIdc; } + uint32_t getNNPostFilterSEICharacteristicsOutSampleIdc(int filterIdx) const { return m_nnPostFilterSEICharacteristicsOutSampleIdc[filterIdx]; } + void setNNPostFilterSEICharacteristicsOutOrderIdc(uint32_t outOrderIdc, int filterIdx) { m_nnPostFilterSEICharacteristicsOutOrderIdc[filterIdx] = outOrderIdc; } + uint32_t getNNPostFilterSEICharacteristicsOutOrderIdc(int filterIdx) const { return m_nnPostFilterSEICharacteristicsOutOrderIdc[filterIdx]; } + void setNNPostFilterSEICharacteristicsConstantPatchSizeFlag(bool constantPatchSizeFlag, int filterIdx) { m_nnPostFilterSEICharacteristicsConstantPatchSizeFlag[filterIdx] = constantPatchSizeFlag; } + bool getNNPostFilterSEICharacteristicsConstantPatchSizeFlag(int filterIdx) const { return m_nnPostFilterSEICharacteristicsConstantPatchSizeFlag[filterIdx]; } + void setNNPostFilterSEICharacteristicsPatchWidthMinus1(uint32_t patchWidthMinus1, int filterIdx) { m_nnPostFilterSEICharacteristicsPatchWidthMinus1[filterIdx] = patchWidthMinus1; } + uint32_t getNNPostFilterSEICharacteristicsPatchWidthMinus1(int filterIdx) const { return m_nnPostFilterSEICharacteristicsPatchWidthMinus1[filterIdx]; } + void setNNPostFilterSEICharacteristicsPatchHeightMinus1(uint32_t patchHeightMinus1, int filterIdx) { m_nnPostFilterSEICharacteristicsPatchHeightMinus1[filterIdx] = patchHeightMinus1; } + uint32_t getNNPostFilterSEICharacteristicsPatchHeightMinus1(int filterIdx) const { return m_nnPostFilterSEICharacteristicsPatchHeightMinus1[filterIdx]; } + void setNNPostFilterSEICharacteristicsOverlap(uint32_t overlap, int filterIdx) { m_nnPostFilterSEICharacteristicsOverlap[filterIdx] = overlap; } + uint32_t getNNPostFilterSEICharacteristicsOverlap(int filterIdx) const { return m_nnPostFilterSEICharacteristicsOverlap[filterIdx]; } + void setNNPostFilterSEICharacteristicsPaddingType(uint32_t paddingType, int filterIdx) { m_nnPostFilterSEICharacteristicsPaddingType[filterIdx] = paddingType; } + uint32_t getNNPostFilterSEICharacteristicsPaddingType(int filterIdx) const { return m_nnPostFilterSEICharacteristicsPaddingType[filterIdx]; } + + void setNNPostFilterSEICharacteristicsComplexityIdc (uint32_t complexityIdc , int filterIdx) { m_nnPostFilterSEICharacteristicsComplexityIdc[filterIdx] = complexityIdc ; } + uint32_t getNNPostFilterSEICharacteristicsComplexityIdc (int filterIdx) const { return m_nnPostFilterSEICharacteristicsComplexityIdc[filterIdx]; } + void setNNPostFilterSEICharacteristicsParameterTypeFlag(bool parameterTypeFlag, int filterIdx) { m_nnPostFilterSEICharacteristicsParameterTypeFlag[filterIdx] = parameterTypeFlag; } + bool getNNPostFilterSEICharacteristicsParameterTypeFlag(int filterIdx) const { return m_nnPostFilterSEICharacteristicsParameterTypeFlag[filterIdx]; } + void setNNPostFilterSEICharacteristicsLog2ParameterBitLengthMinus3 (uint32_t log2ParameterBitLengthMinus3 , int filterIdx) { m_nnPostFilterSEICharacteristicsLog2ParameterBitLengthMinus3[filterIdx] = log2ParameterBitLengthMinus3 ; } + uint32_t getNNPostFilterSEICharacteristicsLog2ParameterBitLengthMinus3 (int filterIdx) const { return m_nnPostFilterSEICharacteristicsLog2ParameterBitLengthMinus3[filterIdx]; } + void setNNPostFilterSEICharacteristicsNumParametersIdc (uint32_t numParametersIdc , int filterIdx) { m_nnPostFilterSEICharacteristicsNumParametersIdc[filterIdx] = numParametersIdc ; } + uint32_t getNNPostFilterSEICharacteristicsNumParametersIdc (int filterIdx) const { return m_nnPostFilterSEICharacteristicsNumParametersIdc[filterIdx]; } + void setNNPostFilterSEICharacteristicsNumKmacOperationsIdc(uint32_t numKmacOperationsIdc , int filterIdx) { m_nnPostFilterSEICharacteristicsNumKmacOperationsIdc[filterIdx] = numKmacOperationsIdc ; } + uint32_t getNNPostFilterSEICharacteristicsNumKmacOperationsIdc(int filterIdx) const { return m_nnPostFilterSEICharacteristicsNumKmacOperationsIdc[filterIdx]; } + + void setNNPostFilterSEICharacteristicsPayloadFilename(std::string payloadFilename, int filterIdx) { m_nnPostFilterSEICharacteristicsPayloadFilename[filterIdx] = payloadFilename; } + std::string getNNPostFilterSEICharacteristicsPayloadFilename(int filterIdx) const { return m_nnPostFilterSEICharacteristicsPayloadFilename[filterIdx]; } + void setNnPostFilterSEIActivationEnabled(bool enabledFlag) { m_nnPostFilterSEIActivationEnabled = enabledFlag; } + bool getNnPostFilterSEIActivationEnabled() const { return m_nnPostFilterSEIActivationEnabled; } + void setNnPostFilterSEIActivationId(uint32_t id) { m_nnPostFilterSEIActivationId = id; } + uint32_t getNnPostFilterSEIActivationId() const { return m_nnPostFilterSEIActivationId; } +#endif + void setBufferingPeriodSEIEnabled(bool b) { m_bufferingPeriodSEIEnabled = b; } bool getBufferingPeriodSEIEnabled() const { return m_bufferingPeriodSEIEnabled; } void setPictureTimingSEIEnabled(bool b) { m_pictureTimingSEIEnabled = b; } diff --git a/source/Lib/EncoderLib/EncGOP.cpp b/source/Lib/EncoderLib/EncGOP.cpp index c12f5fac23..68613c81a8 100644 --- a/source/Lib/EncoderLib/EncGOP.cpp +++ b/source/Lib/EncoderLib/EncGOP.cpp @@ -505,22 +505,43 @@ void EncGOP::xWriteSEI (NalUnitType naluType, SEIMessages& seiMessages, AccessUn auPos++; } +#if JVET_Z0244 +uint32_t EncGOP::xWriteSEISeparately (NalUnitType naluType, SEIMessages& seiMessages, AccessUnit &accessUnit, AccessUnit::iterator &auPos, int temporalId) +#else void EncGOP::xWriteSEISeparately (NalUnitType naluType, SEIMessages& seiMessages, AccessUnit &accessUnit, AccessUnit::iterator &auPos, int temporalId) +#endif { // don't do anything, if we get an empty list if (seiMessages.empty()) { +#if JVET_Z0244 + return 0; +#else return; +#endif } + +#if JVET_Z0244 + uint32_t numBits = 0; +#endif + for (SEIMessages::const_iterator sei = seiMessages.begin(); sei!=seiMessages.end(); sei++ ) { SEIMessages tmpMessages; tmpMessages.push_back(*sei); OutputNALUnit nalu( naluType, m_pcEncLib->getLayerId(), temporalId ); +#if JVET_Z0244 + numBits += m_seiWriter.writeSEImessages(nalu.m_Bitstream, tmpMessages, *m_HRD, false, temporalId); +#else m_seiWriter.writeSEImessages(nalu.m_Bitstream, tmpMessages, *m_HRD, false, temporalId); +#endif auPos = accessUnit.insert(auPos, new NALUnitEBSP(nalu)); auPos++; } + +#if JVET_Z0244 + return numBits; +#endif } void EncGOP::xClearSEIs(SEIMessages& seiMessages, bool deleteMessages) @@ -536,7 +557,11 @@ void EncGOP::xClearSEIs(SEIMessages& seiMessages, bool deleteMessages) } // write SEI messages as separate NAL units ordered +#if JVET_Z0244 +uint32_t EncGOP::xWriteLeadingSEIOrdered (SEIMessages& seiMessages, SEIMessages& duInfoSeiMessages, AccessUnit &accessUnit, int temporalId, bool testWrite) +#else void EncGOP::xWriteLeadingSEIOrdered (SEIMessages& seiMessages, SEIMessages& duInfoSeiMessages, AccessUnit &accessUnit, int temporalId, bool testWrite) +#endif { AccessUnit::iterator itNalu = accessUnit.begin(); @@ -598,17 +623,28 @@ void EncGOP::xWriteLeadingSEIOrdered (SEIMessages& seiMessages, SEIMessages& duI // And finally everything else one by one +#if JVET_Z0244 + uint32_t numBits = xWriteSEISeparately(NAL_UNIT_PREFIX_SEI, localMessages, accessUnit, itNalu, temporalId); +#else xWriteSEISeparately(NAL_UNIT_PREFIX_SEI, localMessages, accessUnit, itNalu, temporalId); +#endif xClearSEIs(localMessages, !testWrite); if (!testWrite) { seiMessages.clear(); } -} +#if JVET_Z0244 + return numBits; +#endif +} +#if JVET_Z0244 +uint32_t EncGOP::xWriteLeadingSEIMessages (SEIMessages& seiMessages, SEIMessages& duInfoSeiMessages, AccessUnit &accessUnit, int temporalId, const SPS *sps, std::deque<DUData> &duData) +#else void EncGOP::xWriteLeadingSEIMessages (SEIMessages& seiMessages, SEIMessages& duInfoSeiMessages, AccessUnit &accessUnit, int temporalId, const SPS *sps, std::deque<DUData> &duData) +#endif { AccessUnit testAU; SEIMessages picTimingSEIs = getSeisByType(seiMessages, SEI::PICTURE_TIMING); @@ -622,7 +658,11 @@ void EncGOP::xWriteLeadingSEIMessages (SEIMessages& seiMessages, SEIMessages& du xUpdateTimingSEI(picTiming, duData, sps); xUpdateDuInfoSEI(duInfoSeiMessages, picTiming, sps->getMaxTLayers()); // actual writing +#if JVET_Z0244 + return xWriteLeadingSEIOrdered(seiMessages, duInfoSeiMessages, accessUnit, temporalId, false); +#else xWriteLeadingSEIOrdered(seiMessages, duInfoSeiMessages, accessUnit, temporalId, false); +#endif // testAU will automatically be cleaned up when losing scope } @@ -852,6 +892,17 @@ void EncGOP::xCreateIRAPLeadingSEIMessages (SEIMessages& seiMessages, const SPS seiMessages.push_back(seiShutterInterval); } #endif +#if JVET_Z0244 + if (m_pcCfg->getNNPostFilterSEICharacteristicsEnabled()) + { + for (int i = 0; i < m_pcCfg->getNNPostFilterSEICharacteristicsNumFilters(); i++) + { + SEINeuralNetworkPostFilterCharacteristics *seiNNPostFilterCharacteristics = new SEINeuralNetworkPostFilterCharacteristics; + m_seiEncoder.initSEINeuralNetworkPostFilterCharacteristics(seiNNPostFilterCharacteristics, i); + seiMessages.push_back(seiNNPostFilterCharacteristics); + } + } +#endif } void EncGOP::xCreatePerPictureSEIMessages (int picInGOP, SEIMessages& seiMessages, SEIMessages& nestedSeiMessages, Slice *slice) @@ -931,6 +982,15 @@ void EncGOP::xCreatePerPictureSEIMessages (int picInGOP, SEIMessages& seiMessage } seiMessages.push_back(fgcSEI); } + +#if JVET_Z0244 + if (m_pcCfg->getNnPostFilterSEIActivationEnabled()) + { + SEINeuralNetworkPostFilterActivation *nnpfActivationSEI = new SEINeuralNetworkPostFilterActivation; + m_seiEncoder.initSEINeuralNetworkPostFilterActivation(nnpfActivationSEI); + seiMessages.push_back(nnpfActivationSEI); + } +#endif } void EncGOP::xCreateScalableNestingSEI(SEIMessages& seiMessages, SEIMessages& nestedSeiMessages, const std::vector<int> &targetOLSs, const std::vector<int> &targetLayers, const std::vector<uint16_t>& subpicIDs, uint16_t maxSubpicIdInPic) @@ -4164,7 +4224,12 @@ void EncGOP::compressGOP( int iPOCLast, int iNumPicRcvd, PicList& rcListPic, xCreateScalableNestingSEI(leadingSeiMessages, nestedSeiMessages, targetOLS, targetLayers, subpicIDs, maxSubpicIdInPic); } +#if JVET_Z0244 + double seiBits = (double)xWriteLeadingSEIMessages( leadingSeiMessages, duInfoSeiMessages, accessUnit, pcSlice->getTLayer(), pcSlice->getSPS(), duData ); + m_gcAnalyzeAll.addBits(seiBits); +#else xWriteLeadingSEIMessages( leadingSeiMessages, duInfoSeiMessages, accessUnit, pcSlice->getTLayer(), pcSlice->getSPS(), duData ); +#endif xWriteDuSEIMessages( duInfoSeiMessages, accessUnit, pcSlice->getTLayer(), duData ); m_AUWriterIf->outputAU( accessUnit ); diff --git a/source/Lib/EncoderLib/EncGOP.h b/source/Lib/EncoderLib/EncGOP.h index 8dd3167eea..bc0b7203c4 100644 --- a/source/Lib/EncoderLib/EncGOP.h +++ b/source/Lib/EncoderLib/EncGOP.h @@ -334,10 +334,22 @@ protected: void xUpdateDuInfoSEI(SEIMessages &duInfoSeiMessages, SEIPictureTiming *pictureTimingSEI, int maxSubLayers); void xCreateScalableNestingSEI(SEIMessages& seiMessages, SEIMessages& nestedSeiMessages, const std::vector<int> &targetOLSs, const std::vector<int> &targetLayers, const std::vector<uint16_t>& subpicIDs, uint16_t maxSubpicIdInPic); void xWriteSEI (NalUnitType naluType, SEIMessages& seiMessages, AccessUnit &accessUnit, AccessUnit::iterator &auPos, int temporalId); +#if JVET_Z0244 + uint32_t xWriteSEISeparately (NalUnitType naluType, SEIMessages& seiMessages, AccessUnit &accessUnit, AccessUnit::iterator &auPos, int temporalId); +#else void xWriteSEISeparately (NalUnitType naluType, SEIMessages& seiMessages, AccessUnit &accessUnit, AccessUnit::iterator &auPos, int temporalId); +#endif void xClearSEIs(SEIMessages& seiMessages, bool deleteMessages); +#if JVET_Z0244 + uint32_t xWriteLeadingSEIOrdered (SEIMessages& seiMessages, SEIMessages& duInfoSeiMessages, AccessUnit &accessUnit, int temporalId, bool testWrite); +#else void xWriteLeadingSEIOrdered (SEIMessages& seiMessages, SEIMessages& duInfoSeiMessages, AccessUnit &accessUnit, int temporalId, bool testWrite); +#endif +#if JVET_Z0244 + uint32_t xWriteLeadingSEIMessages (SEIMessages& seiMessages, SEIMessages& duInfoSeiMessages, AccessUnit &accessUnit, int temporalId, const SPS *sps, std::deque<DUData> &duData); +#else void xWriteLeadingSEIMessages (SEIMessages& seiMessages, SEIMessages& duInfoSeiMessages, AccessUnit &accessUnit, int temporalId, const SPS *sps, std::deque<DUData> &duData); +#endif void xWriteTrailingSEIMessages (SEIMessages& seiMessages, AccessUnit &accessUnit, int temporalId); void xWriteDuSEIMessages (SEIMessages& duInfoSeiMessages, AccessUnit &accessUnit, int temporalId, std::deque<DUData> &duData); diff --git a/source/Lib/EncoderLib/SEIEncoder.cpp b/source/Lib/EncoderLib/SEIEncoder.cpp index 3422168f88..d9692baba6 100644 --- a/source/Lib/EncoderLib/SEIEncoder.cpp +++ b/source/Lib/EncoderLib/SEIEncoder.cpp @@ -1154,5 +1154,89 @@ void SEIEncoder::initSEISubpictureLevelInfo(SEISubpicureLevelInfo *sei, const SP } } +#if JVET_Z0244 +void SEIEncoder::initSEINeuralNetworkPostFilterCharacteristics(SEINeuralNetworkPostFilterCharacteristics *sei, int filterIdx) +{ + CHECK(!(m_isInitialized), "Unspecified error"); + CHECK(!(sei != NULL), "Unspecified error"); + sei->m_id = m_pcCfg->getNNPostFilterSEICharacteristicsId(filterIdx); + sei->m_modeIdc = m_pcCfg->getNNPostFilterSEICharacteristicsModeIdc(filterIdx); + if (sei->m_modeIdc == 1) + { + sei->m_purpose = m_pcCfg->getNNPostFilterSEICharacteristicsPurpose(filterIdx); + + if(sei->m_purpose == 2 || sei->m_purpose == 4) + { + sei->m_outSubWidthCFlag = m_pcCfg->getNNPostFilterSEICharacteristicsOutSubWidthCFlag(filterIdx); + sei->m_outSubHeightCFlag = m_pcCfg->getNNPostFilterSEICharacteristicsOutSubHeightCFlag(filterIdx); + } + if(sei->m_purpose == 3 || sei->m_purpose == 4) + { + sei->m_picWidthInLumaSamples = m_pcCfg->getNNPostFilterSEICharacteristicsPicWidthInLumaSamples(filterIdx); + sei->m_picHeightInLumaSamples = m_pcCfg->getNNPostFilterSEICharacteristicsPicHeightInLumaSamples(filterIdx); + } + + sei->m_componentLastFlag = m_pcCfg->getNNPostFilterSEICharacteristicsComponentLastFlag(filterIdx); + sei->m_inpSampleIdc = m_pcCfg->getNNPostFilterSEICharacteristicsInpSampleIdc(filterIdx); + + if(sei->m_inpSampleIdc == 4) + { + sei->m_inpTensorBitDepthMinus8 = m_pcCfg->getNNPostFilterSEICharacteristicsInpTensorBitDepthMinus8(filterIdx); + } + + sei->m_inpOrderIdc = m_pcCfg->getNNPostFilterSEICharacteristicsInpOrderIdc(filterIdx); + sei->m_outSampleIdc = m_pcCfg->getNNPostFilterSEICharacteristicsOutSampleIdc(filterIdx); + + if(sei->m_outSampleIdc == 4) + { + sei->m_outTensorBitDepthMinus8 = m_pcCfg->getNNPostFilterSEICharacteristicsOutTensorBitDepthMinus8(filterIdx); + } + + sei->m_outOrderIdc = m_pcCfg->getNNPostFilterSEICharacteristicsOutOrderIdc(filterIdx); + sei->m_constantPatchSizeFlag = m_pcCfg->getNNPostFilterSEICharacteristicsConstantPatchSizeFlag(filterIdx); + sei->m_patchWidthMinus1 = m_pcCfg->getNNPostFilterSEICharacteristicsPatchWidthMinus1(filterIdx); + sei->m_patchHeightMinus1 = m_pcCfg->getNNPostFilterSEICharacteristicsPatchHeightMinus1(filterIdx); + sei->m_overlap = m_pcCfg->getNNPostFilterSEICharacteristicsOverlap(filterIdx); + sei->m_paddingType = m_pcCfg->getNNPostFilterSEICharacteristicsPaddingType(filterIdx); + + sei->m_complexityIdc = m_pcCfg->getNNPostFilterSEICharacteristicsComplexityIdc(filterIdx); + if(sei->m_complexityIdc > 0) + { + if(sei->m_complexityIdc == 1) + { + sei->m_parameterTypeFlag = m_pcCfg->getNNPostFilterSEICharacteristicsParameterTypeFlag(filterIdx); + sei->m_log2ParameterBitLengthMinus3 = m_pcCfg->getNNPostFilterSEICharacteristicsLog2ParameterBitLengthMinus3(filterIdx); + sei->m_numParametersIdc = m_pcCfg->getNNPostFilterSEICharacteristicsNumParametersIdc(filterIdx); + sei->m_numKmacOperationsIdc = m_pcCfg->getNNPostFilterSEICharacteristicsNumKmacOperationsIdc(filterIdx); + } + } + } + if (sei->m_modeIdc == 1) + { + const string payloadFilename = m_pcCfg->getNNPostFilterSEICharacteristicsPayloadFilename(filterIdx); + ifstream bitstreamFile(payloadFilename.c_str(), ifstream::in | ifstream::binary); + if (!bitstreamFile) + { + EXIT( "Failed to open bitstream file " << payloadFilename.c_str() << " for reading" ) ; + } + + bitstreamFile.seekg(0, std::ifstream::end); + sei->m_payloadLength = bitstreamFile.tellg(); + bitstreamFile.seekg(0, std::ifstream::beg); + + sei->m_payloadByte = new char[sei->m_payloadLength]; + bitstreamFile.read(sei->m_payloadByte, sei->m_payloadLength); + bitstreamFile.close(); + } +} + +void SEIEncoder::initSEINeuralNetworkPostFilterActivation(SEINeuralNetworkPostFilterActivation *sei) +{ + CHECK(!(m_isInitialized), "Unspecified error"); + CHECK(!(sei != NULL), "Unspecified error"); + sei->m_id = m_pcCfg->getNnPostFilterSEIActivationId(); +} +#endif + //! \} diff --git a/source/Lib/EncoderLib/SEIEncoder.h b/source/Lib/EncoderLib/SEIEncoder.h index 4382de86e4..5bf3dc31d7 100644 --- a/source/Lib/EncoderLib/SEIEncoder.h +++ b/source/Lib/EncoderLib/SEIEncoder.h @@ -93,6 +93,10 @@ public: #if JVET_Z0120_SHUTTER_INTERVAL_SEI void initSEIShutterIntervalInfo(SEIShutterIntervalInfo *sei); #endif +#if JVET_Z0244 + void initSEINeuralNetworkPostFilterCharacteristics(SEINeuralNetworkPostFilterCharacteristics *sei, int filterIdx); + void initSEINeuralNetworkPostFilterActivation(SEINeuralNetworkPostFilterActivation *sei); +#endif private: EncCfg* m_pcCfg; EncLib* m_pcEncLib; diff --git a/source/Lib/EncoderLib/SEIwrite.cpp b/source/Lib/EncoderLib/SEIwrite.cpp index fbceadccfd..98b88f20bf 100644 --- a/source/Lib/EncoderLib/SEIwrite.cpp +++ b/source/Lib/EncoderLib/SEIwrite.cpp @@ -161,6 +161,14 @@ void SEIWriter::xWriteSEIpayloadData(OutputBitstream &bs, const SEI& sei, HRD &h case SEI::SHUTTER_INTERVAL_INFO: xWriteSEIShutterInterval(*static_cast<const SEIShutterIntervalInfo*>(&sei)); break; +#endif +#if JVET_Z0244 + case SEI::NEURAL_NETWORK_POST_FILTER_CHARACTERISTICS: + xWriteSEINeuralNetworkPostFilterCharacteristics(*static_cast<const SEINeuralNetworkPostFilterCharacteristics*>(&sei)); + break; + case SEI::NEURAL_NETWORK_POST_FILTER_ACTIVATION: + xWriteSEINeuralNetworkPostFilterActivation(*static_cast<const SEINeuralNetworkPostFilterActivation*>(&sei)); + break; #endif default: THROW("Trying to write unhandled SEI message"); @@ -172,13 +180,21 @@ void SEIWriter::xWriteSEIpayloadData(OutputBitstream &bs, const SEI& sei, HRD &h /** * marshal all SEI messages in provided list into one bitstream bs */ +#if JVET_Z0244 +uint32_t SEIWriter::writeSEImessages(OutputBitstream& bs, const SEIMessages &seiList, HRD &hrd, bool isNested, const uint32_t temporalId) +#else void SEIWriter::writeSEImessages(OutputBitstream& bs, const SEIMessages &seiList, HRD &hrd, bool isNested, const uint32_t temporalId) +#endif { #if ENABLE_TRACING if (g_HLSTraceEnable) xTraceSEIHeader(); #endif +#if JVET_Z0244 + uint32_t numBits = 0; +#endif + OutputBitstream bs_count; for (SEIMessages::const_iterator sei=seiList.begin(); sei!=seiList.end(); sei++) @@ -199,6 +215,10 @@ void SEIWriter::writeSEImessages(OutputBitstream& bs, const SEIMessages &seiList uint32_t payload_data_num_bits = bs_count.getNumberOfWrittenBits(); CHECK(0 != payload_data_num_bits % 8, "Invalid number of payload data bits"); +#if JVET_Z0244 + numBits += payload_data_num_bits; +#endif + setBitstream(&bs); uint32_t payloadType = (*sei)->payloadType(); for (; payloadType >= 0xff; payloadType -= 0xff) @@ -207,6 +227,10 @@ void SEIWriter::writeSEImessages(OutputBitstream& bs, const SEIMessages &seiList } WRITE_CODE(payloadType, 8, "payload_type"); +#if JVET_Z0244 + numBits += 8; +#endif + uint32_t payloadSize = payload_data_num_bits/8; for (; payloadSize >= 0xff; payloadSize -= 0xff) { @@ -226,6 +250,10 @@ void SEIWriter::writeSEImessages(OutputBitstream& bs, const SEIMessages &seiList { xWriteRbspTrailingBits(); } + +#if JVET_Z0244 + return numBits; +#endif } /** @@ -1382,4 +1410,83 @@ void SEIWriter::xWriteSEIConstrainedRaslIndication(const SEIConstrainedRaslIndic { // intentionally empty } + +#if JVET_Z0244 +void SEIWriter::xWriteSEINeuralNetworkPostFilterCharacteristics(const SEINeuralNetworkPostFilterCharacteristics &sei) +{ + WRITE_UVLC(sei.m_id, "nnpfc_id"); + WRITE_UVLC(sei.m_modeIdc, "nnpfc_mode_idc"); + if (sei.m_modeIdc == 1) + { + WRITE_UVLC(sei.m_purpose, "nnpfc_purpose"); + + if(sei.m_purpose == 2 || sei.m_purpose == 4) + { + WRITE_FLAG(sei.m_outSubWidthCFlag, "nnpfc_out_sub_width_c_flag"); + WRITE_FLAG(sei.m_outSubHeightCFlag, "nnpfc_out_sub_height_c_flag"); + } + if(sei.m_purpose == 3 || sei.m_purpose == 4) + { + WRITE_UVLC(sei.m_picWidthInLumaSamples, "nnpfc_pic_width_in_luma_samples"); + WRITE_UVLC(sei.m_picHeightInLumaSamples, "nnpfc_pic_height_in_luma_samples"); + } + + WRITE_FLAG(sei.m_componentLastFlag, "nnpfc_component_last_flag"); + WRITE_UVLC(sei.m_inpSampleIdc, "nnpfc_inp_sample_idc"); + + if(sei.m_inpSampleIdc == 4) + { + WRITE_UVLC(sei.m_inpTensorBitDepthMinus8, "nnpfc_inp_tensor_bitdepth_minus8"); + } + + WRITE_UVLC(sei.m_inpOrderIdc, "nnpfc_inp_order_idc"); + WRITE_UVLC(sei.m_outSampleIdc, "nnpfc_out_sample_idc"); + + if(sei.m_outSampleIdc == 4) + { + WRITE_UVLC(sei.m_outTensorBitDepthMinus8, "nnpfc_out_tensor_bitdepth_minus8"); + } + + WRITE_UVLC(sei.m_outOrderIdc, "nnpfc_out_order_idc"); + WRITE_FLAG(sei.m_constantPatchSizeFlag, "nnpfc_constant_patch_size_flag"); + WRITE_UVLC(sei.m_patchWidthMinus1, "nnpfc_patch_width_minus1"); + WRITE_UVLC(sei.m_patchHeightMinus1, "nnpfc_patch_height_minus1"); + WRITE_UVLC(sei.m_overlap, "nnpfc_overlap"); + WRITE_UVLC(sei.m_paddingType, "nnpfc_padding_type"); + + WRITE_UVLC(sei.m_complexityIdc, "nnpfc_complexity_idc"); + if(sei.m_complexityIdc > 0) + { + xWriteNNPFCComplexityElement(sei); + } + } + if (sei.m_modeIdc == 1) + { + while (!isByteAligned()) + { + WRITE_FLAG(0, "nnpfc_reserved_zero_bit"); + } + for (long i = 0; i < sei.m_payloadLength; i++) + { + WRITE_SCODE(sei.m_payloadByte[i], 8, "nnpfc_payload_byte[i]"); + } + } +} + +void SEIWriter::xWriteNNPFCComplexityElement(const SEINeuralNetworkPostFilterCharacteristics &sei) +{ + if(sei.m_complexityIdc == 1) + { + WRITE_FLAG(sei.m_parameterTypeFlag, "nnpfc_parameter_type_flag"); + WRITE_CODE(sei.m_log2ParameterBitLengthMinus3, 2, "nnpfc_log2_parameter_bit_length_minus3"); + WRITE_CODE(sei.m_numParametersIdc, 8, "nnpfc_num_parameters_idc"); + WRITE_UVLC(sei.m_numKmacOperationsIdc, "nnpfc_num_kmac_operations_idc"); + } +} + +void SEIWriter::xWriteSEINeuralNetworkPostFilterActivation(const SEINeuralNetworkPostFilterActivation &sei) +{ + WRITE_UVLC(sei.m_id, "nnpfa_id"); +} +#endif //! \} diff --git a/source/Lib/EncoderLib/SEIwrite.h b/source/Lib/EncoderLib/SEIwrite.h index 1e7b075366..49e2b2c5d3 100644 --- a/source/Lib/EncoderLib/SEIwrite.h +++ b/source/Lib/EncoderLib/SEIwrite.h @@ -36,6 +36,10 @@ #ifndef __SEIWRITE__ #define __SEIWRITE__ +#if JVET_Z0244 +#include <fstream> +#endif + #include "VLCWriter.h" #include "CommonLib/SEI.h" @@ -49,7 +53,11 @@ public: SEIWriter() {}; virtual ~SEIWriter() {}; +#if JVET_Z0244 + uint32_t writeSEImessages(OutputBitstream& bs, const SEIMessages &seiList, HRD &hrd, bool isNested, const uint32_t temporalId); +#else void writeSEImessages(OutputBitstream& bs, const SEIMessages &seiList, HRD &hrd, bool isNested, const uint32_t temporalId); +#endif protected: void xWriteSEIuserDataUnregistered(const SEIuserDataUnregistered &sei); @@ -94,6 +102,11 @@ protected: #endif void xWriteSEIpayloadData(OutputBitstream &bs, const SEI& sei, HRD &hrd, const uint32_t temporalId); void xWriteByteAlign(); +#if JVET_Z0244 + void xWriteSEINeuralNetworkPostFilterCharacteristics(const SEINeuralNetworkPostFilterCharacteristics& sei); + void xWriteNNPFCComplexityElement(const SEINeuralNetworkPostFilterCharacteristics& sei); + void xWriteSEINeuralNetworkPostFilterActivation(const SEINeuralNetworkPostFilterActivation &sei); +#endif protected: HRD m_nestingHrd; }; -- GitLab