From b0dd97ce114476e69bb1c19032bf4a91cc35987d Mon Sep 17 00:00:00 2001 From: francoise <edouard.francois@technicolor.com> Date: Wed, 30 Oct 2019 18:50:17 +0100 Subject: [PATCH] implementation of JVET-P0371: chroma residual scaling with offset --- cfg/encoder_randomaccess_vtm.cfg | 1 + cfg/per-class/classH1.cfg | 1 + source/App/EncoderApp/EncApp.cpp | 3 +++ source/App/EncoderApp/EncAppCfg.cpp | 10 ++++++++++ source/App/EncoderApp/EncAppCfg.h | 3 +++ source/Lib/CommonLib/Reshape.cpp | 7 +++++++ source/Lib/CommonLib/Slice.h | 9 +++++++++ source/Lib/CommonLib/TypeDef.h | 1 + source/Lib/DecoderLib/DecLib.cpp | 3 +++ source/Lib/DecoderLib/VLCReader.cpp | 11 +++++++++++ source/Lib/EncoderLib/EncCfg.h | 7 +++++++ source/Lib/EncoderLib/EncGOP.cpp | 7 +++++++ source/Lib/EncoderLib/EncReshape.cpp | 11 +++++++++++ source/Lib/EncoderLib/VLCWriter.cpp | 10 ++++++++++ 14 files changed, 84 insertions(+) diff --git a/cfg/encoder_randomaccess_vtm.cfg b/cfg/encoder_randomaccess_vtm.cfg index c3b70fe2b..673977990 100644 --- a/cfg/encoder_randomaccess_vtm.cfg +++ b/cfg/encoder_randomaccess_vtm.cfg @@ -150,6 +150,7 @@ AffineAmvr : 1 LMCSEnable : 1 # LMCS: 0: disable, 1:enable LMCSSignalType : 0 # Input signal type: 0:SDR, 1:HDR-PQ, 2:HDR-HLG LMCSUpdateCtrl : 0 # LMCS model update control: 0:RA, 1:AI, 2:LDB/LDP +LMCSoffset : 6 # chroma residual scaling offset MIP : 1 DMVR : 1 SMVD : 1 diff --git a/cfg/per-class/classH1.cfg b/cfg/per-class/classH1.cfg index e7cefecf6..afde72f0b 100644 --- a/cfg/per-class/classH1.cfg +++ b/cfg/per-class/classH1.cfg @@ -5,6 +5,7 @@ isSDR : 0 # 1: SDR in PQ container, 0: HDR # ======= LMCS ======================= LMCSEnable : 1 # turned on in HDR CTC LMCSSignalType : 1 # Input signal type: 0:SDR, 1:HDR-PQ, 2:HDR-HLG +LMCSoffset : 1 # chroma residual scaling offset #======== Chroma QP scale ============ WCGPPSEnable : 0 # enable WCG Chroma scale diff --git a/source/App/EncoderApp/EncApp.cpp b/source/App/EncoderApp/EncApp.cpp index a774e69e1..19148d5bb 100644 --- a/source/App/EncoderApp/EncApp.cpp +++ b/source/App/EncoderApp/EncApp.cpp @@ -637,6 +637,9 @@ void EncApp::xInitLibCfg() m_cEncLib.setReshapeSignalType ( m_reshapeSignalType ); m_cEncLib.setReshapeIntraCMD ( m_intraCMD ); m_cEncLib.setReshapeCW ( m_reshapeCW ); +#if JVET_P0371_CHROMA_SCALING_OFFSET + m_cEncLib.setReshapeCSoffset ( m_CSoffset ); +#endif #if JVET_O0756_CALCULATE_HDRMETRICS for (int i=0; i<hdrtoolslib::NB_REF_WHITE; i++) diff --git a/source/App/EncoderApp/EncAppCfg.cpp b/source/App/EncoderApp/EncAppCfg.cpp index 550b9c605..5b5784bac 100644 --- a/source/App/EncoderApp/EncAppCfg.cpp +++ b/source/App/EncoderApp/EncAppCfg.cpp @@ -993,6 +993,9 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] ) "1: rsp both (CW66 for QP<=22), 2: rsp TID0 (for all QP)," "3: rsp inter(CW66 for QP<=22), 4: rsp inter(for all QP).") ("LMCSInitialCW", m_initialCW, 0u, "LMCS initial total codeword (0~1023) when LMCSAdpOption > 0") +#if JVET_P0371_CHROMA_SCALING_OFFSET + ("LMCSOffset", m_CSoffset, 0, "LMCS chroma residual scaling offset") +#endif ("IntraCMD", m_intraCMD, 0u, "IntraChroma MD: 0: none, 1:fixed to default wPSNR weight") ("LCTUFast", m_useFastLCTU, false, "Fast methods for large CTU") ("FastMrg", m_useFastMrg, false, "Fast methods for inter merge") @@ -2709,6 +2712,10 @@ bool EncAppCfg::xCheckParameter() xConfirmPara(m_adpOption > 4, "Max. LMCS Adaptation Option is 4"); xConfirmPara(m_initialCW < 0, "Min. Initial Total Codeword is 0"); xConfirmPara(m_initialCW > 1023, "Max. Initial Total Codeword is 1023"); +#if JVET_P0371_CHROMA_SCALING_OFFSET + xConfirmPara(m_CSoffset < -7, "Min. LMCS Offset value is -7"); + xConfirmPara(m_CSoffset > 7, "Max. LMCS Offset value is 7"); +#endif if (m_updateCtrl > 0 && m_adpOption > 2) { m_adpOption -= 2; } } @@ -3718,6 +3725,9 @@ void EncAppCfg::xPrintParameter() msg(VERBOSE, "(Signal:%s ", m_reshapeSignalType == 0 ? "SDR" : (m_reshapeSignalType == 2 ? "HDR-HLG" : "HDR-PQ")); msg(VERBOSE, "Opt:%d", m_adpOption); if (m_adpOption > 0) { msg(VERBOSE, " CW:%d", m_initialCW); } +#if JVET_P0371_CHROMA_SCALING_OFFSET + msg(VERBOSE, " CSoffset:%d", m_CSoffset); +#endif msg(VERBOSE, ") "); } msg(VERBOSE, "MIP:%d ", m_MIP); diff --git a/source/App/EncoderApp/EncAppCfg.h b/source/App/EncoderApp/EncAppCfg.h index c6493979f..76ae65dd9 100644 --- a/source/App/EncoderApp/EncAppCfg.h +++ b/source/App/EncoderApp/EncAppCfg.h @@ -332,6 +332,9 @@ protected: int m_updateCtrl; int m_adpOption; uint32_t m_initialCW; +#if JVET_P0371_CHROMA_SCALING_OFFSET + int m_CSoffset; +#endif bool m_encDbOpt; unsigned m_uiMaxCUWidth; ///< max. CU width in pixel unsigned m_uiMaxCUHeight; ///< max. CU height in pixel diff --git a/source/Lib/CommonLib/Reshape.cpp b/source/Lib/CommonLib/Reshape.cpp index 40a5ed723..c029fec70 100644 --- a/source/Lib/CommonLib/Reshape.cpp +++ b/source/Lib/CommonLib/Reshape.cpp @@ -225,6 +225,9 @@ void Reshape::copySliceReshaperInfo(SliceReshapeInfo& tInfo, SliceReshapeInfo& s tInfo.reshaperModelMinBinIdx = sInfo.reshaperModelMinBinIdx; memcpy(tInfo.reshaperModelBinCWDelta, sInfo.reshaperModelBinCWDelta, sizeof(int)*(PIC_CODE_CW_BINS)); tInfo.maxNbitsNeededDeltaCW = sInfo.maxNbitsNeededDeltaCW; +#if JVET_P0371_CHROMA_SCALING_OFFSET + tInfo.chrResScalingOffset = sInfo.chrResScalingOffset; +#endif } tInfo.sliceReshaperEnableFlag = sInfo.sliceReshaperEnableFlag; if (sInfo.sliceReshaperEnableFlag) @@ -262,7 +265,11 @@ void Reshape::constructReshaper() else { m_invScaleCoef[i] = (int32_t)(m_initCW * (1 << FP_PREC) / m_binCW[i]); +#if JVET_P0371_CHROMA_SCALING_OFFSET + m_chromaAdjHelpLUT[i] = (int32_t)(m_initCW * (1 << FP_PREC) / ( m_binCW[i] + m_sliceReshapeInfo.chrResScalingOffset ) ); +#else m_chromaAdjHelpLUT[i] = m_invScaleCoef[i]; +#endif } } for (int lumaSample = 0; lumaSample < m_reshapeLUTSize; lumaSample++) diff --git a/source/Lib/CommonLib/Slice.h b/source/Lib/CommonLib/Slice.h index c0d36fcd8..ec635575a 100644 --- a/source/Lib/CommonLib/Slice.h +++ b/source/Lib/CommonLib/Slice.h @@ -451,6 +451,9 @@ public: uint32_t reshaperModelMaxBinIdx; int reshaperModelBinCWDelta[PIC_CODE_CW_BINS]; int maxNbitsNeededDeltaCW; +#if JVET_P0371_CHROMA_SCALING_OFFSET + int chrResScalingOffset; +#endif void setUseSliceReshaper(bool b) { sliceReshaperEnableFlag = b; } bool getUseSliceReshaper() const { return sliceReshaperEnableFlag; } void setSliceReshapeModelPresentFlag(bool b) { sliceReshaperModelPresentFlag = b; } @@ -484,6 +487,12 @@ public: { return false; } +#if JVET_P0371_CHROMA_SCALING_OFFSET + if (chrResScalingOffset != other.chrResScalingOffset) + { + return false; + } +#endif if( memcmp( reshaperModelBinCWDelta, other.reshaperModelBinCWDelta, sizeof( reshaperModelBinCWDelta ) ) ) { return false; diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h index e4cfb8d14..d7b01ffb5 100644 --- a/source/Lib/CommonLib/TypeDef.h +++ b/source/Lib/CommonLib/TypeDef.h @@ -53,6 +53,7 @@ #define JVET_P0345_LD_GOP_8 1 // JVET-P0345: low-delay gop size 8 +#define JVET_P0371_CHROMA_SCALING_OFFSET 1 // JVET-P0371: Signalling offset for chroma residual scaling #define JVET_P0803_COMBINED_MIP_CLEANUP 1 // JVET-P0803: Several MIP cleanups #define JVET_P0199_P0289_P0303_MIP_FULLMATRIX 1 // JVET-P0199/P0289/P0303: Full matrix multiplication for all MIP block shapes diff --git a/source/Lib/DecoderLib/DecLib.cpp b/source/Lib/DecoderLib/DecLib.cpp index 58b680f47..051d1d161 100644 --- a/source/Lib/DecoderLib/DecLib.cpp +++ b/source/Lib/DecoderLib/DecLib.cpp @@ -1534,6 +1534,9 @@ bool DecLib::xDecodeSlice(InputNALUnit &nalu, int &iSkipFrame, int iPOCLastDispl tInfo.reshaperModelMinBinIdx = sInfo.reshaperModelMinBinIdx; memcpy(tInfo.reshaperModelBinCWDelta, sInfo.reshaperModelBinCWDelta, sizeof(int)*(PIC_CODE_CW_BINS)); tInfo.maxNbitsNeededDeltaCW = sInfo.maxNbitsNeededDeltaCW; +#if JVET_P0371_CHROMA_SCALING_OFFSET + tInfo.chrResScalingOffset = sInfo.chrResScalingOffset; +#endif tInfo.setUseSliceReshaper(pcSlice->getLmcsEnabledFlag()); tInfo.setSliceReshapeChromaAdj(pcSlice->getLmcsChromaResidualScaleFlag()); tInfo.setSliceReshapeModelPresentFlag(true); diff --git a/source/Lib/DecoderLib/VLCReader.cpp b/source/Lib/DecoderLib/VLCReader.cpp index 0e695a0f8..3687b17bf 100644 --- a/source/Lib/DecoderLib/VLCReader.cpp +++ b/source/Lib/DecoderLib/VLCReader.cpp @@ -1004,6 +1004,17 @@ void HLSyntaxReader::parseLmcsAps( APS* aps ) int signCW = code; info.reshaperModelBinCWDelta[i] = (1 - 2 * signCW) * absCW; } +#if JVET_P0371_CHROMA_SCALING_OFFSET + READ_CODE(3, code, "lmcs_delta_abs_crs"); + int absCW = code; + if (absCW > 0) + { + READ_CODE(1, code, "lmcs_delta_sign_crs_flag"); + } + int signCW = code; + info.chrResScalingOffset = (1 - 2 * signCW) * absCW; +#endif + aps->setReshaperAPSInfo(info); } diff --git a/source/Lib/EncoderLib/EncCfg.h b/source/Lib/EncoderLib/EncCfg.h index feb45aadf..16eaf368d 100644 --- a/source/Lib/EncoderLib/EncCfg.h +++ b/source/Lib/EncoderLib/EncCfg.h @@ -340,6 +340,9 @@ protected: unsigned m_reshapeSignalType; unsigned m_intraCMD; ReshapeCW m_reshapeCW; +#if JVET_P0371_CHROMA_SCALING_OFFSET + int m_CSoffset; +#endif bool m_encDbOpt; bool m_useFastLCTU; bool m_useFastMrg; @@ -991,6 +994,10 @@ public: uint32_t getReshapeIntraCMD () { return m_intraCMD; } void setReshapeCW (const ReshapeCW &reshapeCW) { m_reshapeCW = reshapeCW; } const ReshapeCW& getReshapeCW () { return m_reshapeCW; } +#if JVET_P0371_CHROMA_SCALING_OFFSET + void setReshapeCSoffset (int CSoffset) { m_CSoffset = CSoffset; } + int getReshapeCSoffset () { return m_CSoffset; } +#endif void setMaxCUWidth ( uint32_t u ) { m_maxCUWidth = u; } uint32_t getMaxCUWidth () const { return m_maxCUWidth; } void setMaxCUHeight ( uint32_t u ) { m_maxCUHeight = u; } diff --git a/source/Lib/EncoderLib/EncGOP.cpp b/source/Lib/EncoderLib/EncGOP.cpp index d51c70c99..85f895a32 100644 --- a/source/Lib/EncoderLib/EncGOP.cpp +++ b/source/Lib/EncoderLib/EncGOP.cpp @@ -1753,6 +1753,10 @@ void EncGOP::xPicInitLMCS(Picture *pic, Slice *slice) m_pcReshaper->setSrcReshaped(false); m_pcReshaper->setRecReshaped(true); +#if JVET_P0371_CHROMA_SCALING_OFFSET + m_pcReshaper->getSliceReshaperInfo().chrResScalingOffset = m_pcCfg->getReshapeCSoffset(); +#endif + if (m_pcCfg->getReshapeSignalType() == RESHAPE_SIGNAL_PQ) { m_pcReshaper->preAnalyzerHDR(pic, sliceType, m_pcCfg->getReshapeCW(), m_pcCfg->getDualITree()); @@ -1854,6 +1858,9 @@ void EncGOP::xPicInitLMCS(Picture *pic, Slice *slice) tInfo.reshaperModelMinBinIdx = sInfo.reshaperModelMinBinIdx; memcpy(tInfo.reshaperModelBinCWDelta, sInfo.reshaperModelBinCWDelta, sizeof(int)*(PIC_CODE_CW_BINS)); tInfo.maxNbitsNeededDeltaCW = sInfo.maxNbitsNeededDeltaCW; +#if JVET_P0371_CHROMA_SCALING_OFFSET + tInfo.chrResScalingOffset = sInfo.chrResScalingOffset; +#endif m_pcEncLib->getApsMap()->setChangedFlag((lmcsAPS->getAPSId() << NUM_APS_TYPE_LEN) + LMCS_APS); } diff --git a/source/Lib/EncoderLib/EncReshape.cpp b/source/Lib/EncoderLib/EncReshape.cpp index b92b0cdb4..034d6b119 100644 --- a/source/Lib/EncoderLib/EncReshape.cpp +++ b/source/Lib/EncoderLib/EncReshape.cpp @@ -93,6 +93,9 @@ void EncReshape::createEnc(int picWidth, int picHeight, uint32_t maxCUWidth, ui m_sliceReshapeInfo.reshaperModelMinBinIdx = 0; m_sliceReshapeInfo.reshaperModelMaxBinIdx = PIC_CODE_CW_BINS - 1; memset(m_sliceReshapeInfo.reshaperModelBinCWDelta, 0, (PIC_CODE_CW_BINS) * sizeof(int)); +#if JVET_P0371_CHROMA_SCALING_OFFSET + m_sliceReshapeInfo.chrResScalingOffset = 0; +#endif m_picWidth = picWidth; m_picHeight = picHeight; @@ -962,7 +965,11 @@ void EncReshape::initLUTfromdQPModel() else { m_invScaleCoef[i] = (int32_t)(m_initCW * (1 << FP_PREC) / m_binCW[i]); +#if JVET_P0371_CHROMA_SCALING_OFFSET + m_chromaAdjHelpLUT[i] = (int32_t)(m_initCW * (1 << FP_PREC) / (m_binCW[i] + m_sliceReshapeInfo.chrResScalingOffset)); +#else m_chromaAdjHelpLUT[i] = m_invScaleCoef[i]; +#endif } } for (int lumaSample = 0; lumaSample < m_reshapeLUTSize; lumaSample++) @@ -1054,7 +1061,11 @@ void EncReshape::constructReshaperLMCS() else { m_invScaleCoef[i] = (int32_t)(m_initCW * (1 << FP_PREC) / m_binCW[i]); +#if JVET_P0371_CHROMA_SCALING_OFFSET + m_chromaAdjHelpLUT[i] = (int32_t)(m_initCW * (1 << FP_PREC) / (m_binCW[i] + m_sliceReshapeInfo.chrResScalingOffset)); +#else m_chromaAdjHelpLUT[i] = m_invScaleCoef[i]; +#endif } } for (int lumaSample = 0; lumaSample < m_reshapeLUTSize; lumaSample++) diff --git a/source/Lib/EncoderLib/VLCWriter.cpp b/source/Lib/EncoderLib/VLCWriter.cpp index 023d0a90c..31005a474 100644 --- a/source/Lib/EncoderLib/VLCWriter.cpp +++ b/source/Lib/EncoderLib/VLCWriter.cpp @@ -579,6 +579,16 @@ void HLSWriter::codeLmcsAps( APS* pcAPS ) WRITE_FLAG(signCW, "lmcs_delta_sign_cw_flag[ i ]"); } } +#if JVET_P0371_CHROMA_SCALING_OFFSET + int deltaCRS = param.chrResScalingOffset; + int signCRS = (deltaCRS < 0) ? 1 : 0; + int absCRS = (deltaCRS < 0) ? (-deltaCRS) : deltaCRS; + WRITE_CODE(absCRS, 3, "lmcs_delta_crs_val"); + if (absCRS > 0) + { + WRITE_FLAG(signCRS, "lmcs_delta_crs_val_flag"); + } +#endif } void HLSWriter::codeScalingListAps( APS* pcAPS ) -- GitLab