diff --git a/source/App/EncoderApp/EncApp.cpp b/source/App/EncoderApp/EncApp.cpp index e67f36bcabcec0b66e364ada09663d1972ebca4c..a387bbc6ec1f4fb24c3c458935b507c1545fdd4b 100644 --- a/source/App/EncoderApp/EncApp.cpp +++ b/source/App/EncoderApp/EncApp.cpp @@ -167,6 +167,15 @@ void EncApp::xInitLibCfg() #if X0038_LAMBDA_FROM_QP_CAPABILITY m_cEncLib.setIntraQPOffset ( m_intraQPOffset ); m_cEncLib.setLambdaFromQPEnable ( m_lambdaFromQPEnable ); +#endif +#if JVET_O0650_SIGNAL_CHROMAQP_MAPPING_TABLE + m_cEncLib.setSameCQPTableForAllChroma(m_sameCQPTableForAllChroma); + for (int i = 0; i < (m_sameCQPTableForAllChroma ? 1 : 3); i++) + { + m_cEncLib.setNumPtsInCQPTableMinus1(i, (int)m_deltaInValMinus1[i].size() - 1); + m_cEncLib.setDeltaInValMinus1(i, m_deltaInValMinus1[i]); + m_cEncLib.setDeltaOutVal(i, m_deltaOutVal[i]); + } #endif m_cEncLib.setPad ( m_aiPad ); diff --git a/source/App/EncoderApp/EncAppCfg.cpp b/source/App/EncoderApp/EncAppCfg.cpp index 4715e0e251954dc7a80656b10ca90e5a4a744c49..0671b0259286ed8999548fdce1ef74ed163ac017 100644 --- a/source/App/EncoderApp/EncAppCfg.cpp +++ b/source/App/EncoderApp/EncAppCfg.cpp @@ -714,7 +714,19 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] ) SMultiValueInput<int> cfg_lumaLeveltoDQPMappingLuma (0, std::numeric_limits<int>::max(), 0, LUMA_LEVEL_TO_DQP_LUT_MAXSIZE, defaultLumaLevelTodQp_LumaChangePoints, sizeof(defaultLumaLevelTodQp_LumaChangePoints)/sizeof(int)); uint32_t lumaLevelToDeltaQPMode; #endif - +#if JVET_O0650_SIGNAL_CHROMAQP_MAPPING_TABLE + //const int qpInVals[] = { 25, 33, 43 }; + //const int qpOutVals[] = { 25, 32, 37 }; + const int qpInVals[] = { 8, 25, 33, 43 }; + const int qpOutVals[] = { 8, 26, 33, 38 }; + SMultiValueInput<int> cfg_qpInValCb(0, 63, 0, 64, qpInVals, sizeof(qpInVals)/sizeof(int)); + SMultiValueInput<int> cfg_qpOutValCb(0, 63, 0, 64, qpOutVals, sizeof(qpOutVals) / sizeof(int)); + const int zeroVector[] = { 0 }; + SMultiValueInput<int> cfg_qpInValCr(0, 63, 0, 64, zeroVector, 1); + SMultiValueInput<int> cfg_qpOutValCr(0, 63, 0, 64, zeroVector, 1); + SMultiValueInput<int> cfg_qpInValCbCr(0, 63, 0, 64, zeroVector, 1); + SMultiValueInput<int> cfg_qpOutValCbCr(0, 63, 0, 64, zeroVector, 1); +#endif const uint32_t defaultInputKneeCodes[3] = { 600, 800, 900 }; const uint32_t defaultOutputKneeCodes[3] = { 100, 250, 450 }; SMultiValueInput<uint32_t> cfg_kneeSEIInputKneePointValue (1, 999, 0, 999, defaultInputKneeCodes, sizeof(defaultInputKneeCodes )/sizeof(uint32_t)); @@ -1018,7 +1030,16 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] ) ("LumaLevelToDeltaQPMappingLuma", cfg_lumaLeveltoDQPMappingLuma, cfg_lumaLeveltoDQPMappingLuma, "Luma to Delta QP Mapping - luma thresholds") ("LumaLevelToDeltaQPMappingDQP", cfg_lumaLeveltoDQPMappingQP, cfg_lumaLeveltoDQPMappingQP, "Luma to Delta QP Mapping - DQP values") #endif - +#if JVET_O0650_SIGNAL_CHROMAQP_MAPPING_TABLE + ("UseIdentityTableForNon420Chroma", m_useIdentityTableForNon420Chroma, true, "True: Indicates that 422/444 chroma uses identity chroma QP mapping tables; False: explicit Qp table may be specified in config") + ("SameCQPTablesForAllChroma", m_sameCQPTableForAllChroma, true, "0: Different tables for Cb, Cr and joint Cb-Cr components, 1 (default): Same tables for all three chroma components") + ("QpInValCb", cfg_qpInValCb, cfg_qpInValCb, "Input coordinates for the QP table for Cb component") + ("QpOutValCb", cfg_qpOutValCb, cfg_qpOutValCb, "Output coordinates for the QP table for Cb component") + ("QpInValCr", cfg_qpInValCr, cfg_qpInValCr, "Input coordinates for the QP table for Cr component") + ("QpOutValCr", cfg_qpOutValCr, cfg_qpOutValCr, "Output coordinates for the QP table for Cr component") + ("QpInValCbCr", cfg_qpInValCbCr, cfg_qpInValCbCr, "Input coordinates for the QP table for joint Cb-Cr component") + ("QpOutValCbCr", cfg_qpOutValCbCr, cfg_qpOutValCbCr, "Output coordinates for the QP table for joint Cb-Cr component") +#endif ("CbQpOffset,-cbqpofs", m_cbQpOffset, 0, "Chroma Cb QP Offset") ("CrQpOffset,-crqpofs", m_crQpOffset, 0, "Chroma Cr QP Offset") ("CbQpOffsetDualTree", m_cbQpOffsetDualTree, 0, "Chroma Cb QP Offset for dual tree") @@ -1907,6 +1928,43 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] ) } } #endif +#if JVET_O0650_SIGNAL_CHROMAQP_MAPPING_TABLE + + CHECK(cfg_qpInValCb.values.size() != cfg_qpOutValCb.values.size(), "Chroma QP table for Cb is incomplete."); + CHECK(cfg_qpInValCr.values.size() != cfg_qpOutValCr.values.size(), "Chroma QP table for Cr is incomplete."); + CHECK(cfg_qpInValCbCr.values.size() != cfg_qpOutValCbCr.values.size(), "Chroma QP table for CbCr is incomplete."); + if (m_useIdentityTableForNon420Chroma && m_chromaFormatIDC != CHROMA_420) + { + m_sameCQPTableForAllChroma = true; + cfg_qpInValCb.values = { 0 }; + cfg_qpInValCr.values = { 0 }; + cfg_qpInValCbCr.values = { 0 }; + } + m_deltaInValMinus1[0].resize(cfg_qpInValCb.values.size()); + m_deltaOutVal[0].resize(cfg_qpOutValCb.values.size()); + for (int i = 0; i < cfg_qpInValCb.values.size(); i++) + { + m_deltaInValMinus1[0][i] = (i == 0) ? cfg_qpInValCb.values[i] + 6*(m_internalBitDepth[CHANNEL_TYPE_CHROMA]-8) : cfg_qpInValCb.values[i] - cfg_qpInValCb.values[i - 1] - 1; + m_deltaOutVal[0][i] = (i == 0) ? cfg_qpOutValCb.values[i] + 6*(m_internalBitDepth[CHANNEL_TYPE_CHROMA]-8) : cfg_qpOutValCb.values[i] - cfg_qpOutValCb.values[i - 1]; + } + if (!m_sameCQPTableForAllChroma) + { + m_deltaInValMinus1[1].resize(cfg_qpInValCr.values.size()); + m_deltaOutVal[1].resize(cfg_qpOutValCr.values.size()); + for (int i = 0; i < cfg_qpInValCb.values.size(); i++) + { + m_deltaInValMinus1[1][i] = (i == 0) ? cfg_qpInValCr.values[i] : cfg_qpInValCr.values[i] - cfg_qpInValCr.values[i - 1] - 1; + m_deltaOutVal[1][i] = (i == 0) ? cfg_qpOutValCr.values[i] : cfg_qpOutValCr.values[i] - cfg_qpOutValCr.values[i - 1]; + } + m_deltaInValMinus1[2].resize(cfg_qpInValCbCr.values.size()); + m_deltaOutVal[2].resize(cfg_qpOutValCbCr.values.size()); + for (int i = 0; i < cfg_qpInValCb.values.size(); i++) + { + m_deltaInValMinus1[2][i] = (i == 0) ? cfg_qpInValCbCr.values[i] : cfg_qpInValCbCr.values[i] - cfg_qpInValCbCr.values[i - 1] - 1; + m_deltaOutVal[2][i] = (i == 0) ? cfg_qpOutValCbCr.values[i] : cfg_qpOutValCbCr.values[i] - cfg_qpOutValCbCr.values[i - 1]; + } + } +#endif #if LUMA_ADAPTIVE_DEBLOCKING_FILTER_QP_OFFSET if ( m_LadfEnabed ) diff --git a/source/App/EncoderApp/EncAppCfg.h b/source/App/EncoderApp/EncAppCfg.h index 417ae65e7325a997e190477d55feccd743d79e55..60d6f4897497de7a0e4b625628c3ad328f66eea8 100644 --- a/source/App/EncoderApp/EncAppCfg.h +++ b/source/App/EncoderApp/EncAppCfg.h @@ -202,6 +202,13 @@ protected: double m_fQP; ///< QP value of key-picture (floating point) #endif int m_iQP; ///< QP value of key-picture (integer) +#if JVET_O0650_SIGNAL_CHROMAQP_MAPPING_TABLE + bool m_useIdentityTableForNon420Chroma; + bool m_sameCQPTableForAllChroma; + int m_numPtsInCQPTableMinus1[MAX_NUM_CQP_MAPPING_TABLES]; + std::vector<int> m_deltaInValMinus1[MAX_NUM_CQP_MAPPING_TABLES]; + std::vector<int> m_deltaOutVal[MAX_NUM_CQP_MAPPING_TABLES]; +#endif #if X0038_LAMBDA_FROM_QP_CAPABILITY int m_intraQPOffset; ///< QP offset for intra slice (integer) bool m_lambdaFromQPEnable; ///< enable flag for QP:lambda fix diff --git a/source/Lib/CommonLib/ChromaFormat.h b/source/Lib/CommonLib/ChromaFormat.h index 8be4be331e05168687d292ac87419a38c04be9d5..0400084e1fe7f02773ac735ed6be8b28f905e0e4 100644 --- a/source/Lib/CommonLib/ChromaFormat.h +++ b/source/Lib/CommonLib/ChromaFormat.h @@ -115,12 +115,12 @@ static inline int getTransformShift(const int channelBitDepth, const Size size, //------------------------------------------------ - +#if !JVET_O0650_SIGNAL_CHROMAQP_MAPPING_TABLE static inline int getScaledChromaQP(int unscaledChromaQP, const ChromaFormat chFmt) { return g_aucChromaScale[chFmt][Clip3(0, (chromaQPMappingTableSize - 1), unscaledChromaQP)]; } - +#endif //====================================================================================================================== //Scaling lists ======================================================================================================= diff --git a/source/Lib/CommonLib/LoopFilter.cpp b/source/Lib/CommonLib/LoopFilter.cpp index f8ddd4958720f6dda130f789bcbdd84403dedd72..a4352e58d21294115a7511eb5aca79dd21fe3376 100644 --- a/source/Lib/CommonLib/LoopFilter.cpp +++ b/source/Lib/CommonLib/LoopFilter.cpp @@ -1273,6 +1273,10 @@ void LoopFilter::xEdgeFilterChroma(const CodingUnit& cu, const DeblockEdgeDir ed const int chromaQPOffset = pps.getQpOffset( ComponentID( chromaIdx + 1 ) ); Pel* piTmpSrcChroma = (chromaIdx == 0) ? piTmpSrcCb : piTmpSrcCr; +#if JVET_O0650_SIGNAL_CHROMAQP_MAPPING_TABLE + int iQP = Clip3(0, MAX_QP, ((cuP.qp + cuQ.qp + 1) >> 1) + chromaQPOffset); + iQP = sps.getMappedChromaQPValue(ComponentID(chromaIdx + 1), iQP); +#else int iQP = ( ( cuP.qp + cuQ.qp + 1 ) >> 1 ) + chromaQPOffset; if (iQP >= chromaQPMappingTableSize) { @@ -1289,6 +1293,7 @@ void LoopFilter::xEdgeFilterChroma(const CodingUnit& cu, const DeblockEdgeDir ed { iQP = getScaledChromaQP(iQP, sps.getChromaFormatIdc()); } +#endif const int iIndexTC = Clip3<int>(0, MAX_QP + DEFAULT_INTRA_TC_OFFSET, iQP + DEFAULT_INTRA_TC_OFFSET * (bS[chromaIdx] - 1) + (tcOffsetDiv2 << 1)); #if JVET_O0159_10BITTCTABLE_DEBLOCKING diff --git a/source/Lib/CommonLib/Quant.cpp b/source/Lib/CommonLib/Quant.cpp index 71ca554f0148e2ad52516b588d51bfb7591be9d3..608c19b66fa0b548ce1f9bf47e66d8a993293ef9 100644 --- a/source/Lib/CommonLib/Quant.cpp +++ b/source/Lib/CommonLib/Quant.cpp @@ -63,23 +63,39 @@ // ==================================================================================================================== QpParam::QpParam(const int qpy, +#if JVET_O0650_SIGNAL_CHROMAQP_MAPPING_TABLE + const ComponentID compID, +#else const ChannelType chType, +#endif const int qpBdOffset, #if JVET_O0919_TS_MIN_QP const int minQpPrimeTsMinus4, #endif const int chromaQPOffset, const ChromaFormat chFmt, - const int dqp ) + const int dqp +#if JVET_O0650_SIGNAL_CHROMAQP_MAPPING_TABLE + , const SPS *sps +#endif +) { int baseQp; - +#if JVET_O0650_SIGNAL_CHROMAQP_MAPPING_TABLE + if (isLuma(compID)) +#else if(isLuma(chType)) +#endif { baseQp = qpy + qpBdOffset; } else { +#if JVET_O0650_SIGNAL_CHROMAQP_MAPPING_TABLE + int qpi = Clip3(-qpBdOffset, MAX_QP, qpy); + baseQp = sps->getMappedChromaQPValue(compID, qpi); + baseQp = Clip3(-qpBdOffset, MAX_QP, baseQp + chromaQPOffset) + qpBdOffset; +#else baseQp = Clip3( -qpBdOffset, (chromaQPMappingTableSize - 1), qpy + chromaQPOffset ); if(baseQp < 0) @@ -90,6 +106,7 @@ QpParam::QpParam(const int qpy, { baseQp = getScaledChromaQP(baseQp, chFmt) + qpBdOffset; } +#endif } baseQp = Clip3( 0, MAX_QP+qpBdOffset, baseQp + dqp ); @@ -147,10 +164,18 @@ QpParam::QpParam(const TransformUnit& tu, const ComponentID &compIDX, const int int dqp = 0; #if JVET_O0919_TS_MIN_QP +#if JVET_O0650_SIGNAL_CHROMAQP_MAPPING_TABLE + *this = QpParam(QP <= -MAX_INT ? tu.cu->qp : QP, compID, tu.cs->sps->getQpBDOffset(toChannelType(compID)), tu.cs->sps->getMinQpPrimeTsMinus4(toChannelType(compID)), chromaQpOffset, tu.chromaFormat, dqp, tu.cs->sps); +#else *this = QpParam(QP <= -MAX_INT ? tu.cu->qp : QP, toChannelType(compID), tu.cs->sps->getQpBDOffset(toChannelType(compID)), tu.cs->sps->getMinQpPrimeTsMinus4(toChannelType(compID)), chromaQpOffset, tu.chromaFormat, dqp); +#endif +#else +#if JVET_O0650_SIGNAL_CHROMAQP_MAPPING_TABLE + *this = QpParam(QP <= -MAX_INT ? tu.cu->qp : QP, compID, tu.cs->sps->getQpBDOffset(toChannelType(compID)), chromaQpOffset, tu.chromaFormat, dqp, tu.cs->sps); #else *this = QpParam(QP <= -MAX_INT ? tu.cu->qp : QP, toChannelType(compID), tu.cs->sps->getQpBDOffset(toChannelType(compID)), chromaQpOffset, tu.chromaFormat, dqp); #endif +#endif } diff --git a/source/Lib/CommonLib/Quant.h b/source/Lib/CommonLib/Quant.h index 16eba76cbc871781b021e5b6ebfe1909bc67c25f..eb36a1a4f80646d4731ba686f75a31f5eed9c622 100644 --- a/source/Lib/CommonLib/Quant.h +++ b/source/Lib/CommonLib/Quant.h @@ -84,14 +84,22 @@ struct QpParam private: QpParam(const int qpy, +#if JVET_O0650_SIGNAL_CHROMAQP_MAPPING_TABLE + const ComponentID compID, +#else const ChannelType chType, +#endif const int qpBdOffset, #if JVET_O0919_TS_MIN_QP const int minQpPrimeTsMinus4, #endif const int chromaQPOffset, const ChromaFormat chFmt, - const int dqp ); + const int dqp +#if JVET_O0650_SIGNAL_CHROMAQP_MAPPING_TABLE + , const SPS *sps +#endif + ); public: diff --git a/source/Lib/CommonLib/Rom.cpp b/source/Lib/CommonLib/Rom.cpp index e32c236eafd10652f87536d1831ca1c2808d9077..721e683b24a53970d6854862703be200a83a6fca 100644 --- a/source/Lib/CommonLib/Rom.cpp +++ b/source/Lib/CommonLib/Rom.cpp @@ -498,7 +498,7 @@ const int g_invQuantScales[2][SCALING_LIST_REM_NUM] = // can be represented as a //-------------------------------------------------------------------------------------------------- //coefficients //-------------------------------------------------------------------------------------------------- - +#if !JVET_O0650_SIGNAL_CHROMAQP_MAPPING_TABLE const uint8_t g_aucChromaScale[NUM_CHROMA_FORMAT][chromaQPMappingTableSize] = { //0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69 @@ -507,7 +507,7 @@ const uint8_t g_aucChromaScale[NUM_CHROMA_FORMAT][chromaQPMappingTableSize] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,63,63,63,63,63,63 }, { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,63,63,63,63,63,63 } }; - +#endif // ==================================================================================================================== // Intra prediction // ==================================================================================================================== diff --git a/source/Lib/CommonLib/Rom.h b/source/Lib/CommonLib/Rom.h index 877b947d770bd924ac19bc529bd2c5bef5b89cde..3bfe26e204d0077aabff6b31ca36553d5a40f5dd 100644 --- a/source/Lib/CommonLib/Rom.h +++ b/source/Lib/CommonLib/Rom.h @@ -82,14 +82,14 @@ extern const uint8_t g_intraMode65to33AngMapping[NUM_INTRA_MODE]; extern const uint8_t g_mapMipToAngular65[3][MAX_NUM_MIP_MODE]; extern const uint8_t g_mapAngular33ToMip[3][35]; extern const int g_sortedMipMpms [3][NUM_MPM_MIP]; - +#if !JVET_O0650_SIGNAL_CHROMAQP_MAPPING_TABLE // ==================================================================================================================== // Luma QP to Chroma QP mapping // ==================================================================================================================== static const int chromaQPMappingTableSize = (MAX_QP + 7); extern const uint8_t g_aucChromaScale[NUM_CHROMA_FORMAT][chromaQPMappingTableSize]; - +#endif // ==================================================================================================================== // Scanning order & context mapping table diff --git a/source/Lib/CommonLib/Slice.cpp b/source/Lib/CommonLib/Slice.cpp index 58b18d44b594b38d2a3921df60aecb1379323df4..301f00fec11af493b5d31bfa73f003c4965c79e2 100644 --- a/source/Lib/CommonLib/Slice.cpp +++ b/source/Lib/CommonLib/Slice.cpp @@ -1476,6 +1476,11 @@ SPS::SPS() ::memset(m_ltRefPicPocLsbSps, 0, sizeof(m_ltRefPicPocLsbSps)); ::memset(m_usedByCurrPicLtSPSFlag, 0, sizeof(m_usedByCurrPicLtSPSFlag)); +#if JVET_O0650_SIGNAL_CHROMAQP_MAPPING_TABLE + m_numPtsInCQPTableMinus1[0] = 0; + m_deltaInValMinus1[0] = { 0 }; + m_deltaOutVal[0] = { 0 }; +#endif } SPS::~SPS() @@ -1502,6 +1507,51 @@ void SPS::createRPLList1(int numRPL) const int SPS::m_winUnitX[]={1,2,2,1}; const int SPS::m_winUnitY[]={1,2,1,1}; +#if JVET_O0650_SIGNAL_CHROMAQP_MAPPING_TABLE +void SPS::derivedChromaQPMappingTables() +{ + for (int i = 0; i < (getSameCQPTableForAllChromaFlag() ? 1 : 3); i++) + { + const int qpBdOffsetC = this->getQpBDOffset(CHANNEL_TYPE_CHROMA); + const int numPtsInCQPTableMinus1 = getNumPtsInCQPTableMinus1(i); + std::vector<int> qpInVal(numPtsInCQPTableMinus1 + 1), qpOutVal(numPtsInCQPTableMinus1 + 1); + + qpInVal[0] = -qpBdOffsetC + getDeltaInValMinus1(i, 0); + qpOutVal[0] = -qpBdOffsetC + getDeltaOutVal(i, 0); + for (int j = 1; j <= getNumPtsInCQPTableMinus1(i); j++) + { + qpInVal[j] = qpInVal[j - 1] + getDeltaInValMinus1(i, j) + 1; + qpOutVal[j] = qpOutVal[j - 1] + getDeltaOutVal(i, j); + } + + for (int j = 0; j <= getNumPtsInCQPTableMinus1(i); j++) + { + CHECK(qpInVal[j] < -qpBdOffsetC || qpInVal[j] > MAX_QP, "qpInVal out of range"); + CHECK(qpOutVal[j] < -qpBdOffsetC || qpOutVal[j] > MAX_QP, "qpOutVal out of range"); + } + + m_chromaQPMappingTables[i][qpInVal[0]] = qpOutVal[0]; + for (int k = qpInVal[0] - 1; k >= -qpBdOffsetC; k--) + { + m_chromaQPMappingTables[i][k] = Clip3(-qpBdOffsetC, MAX_QP, m_chromaQPMappingTables[i][k + 1] - 1); + } + for (int j = 0; j < numPtsInCQPTableMinus1; j++) + { + int sh = (getDeltaInValMinus1(i, j + 1) + 1 + 1) >> 1; + for (int k = qpInVal[j] + 1, m = 1; k <= qpInVal[j + 1]; k++, m++) + { + m_chromaQPMappingTables[i][k] = m_chromaQPMappingTables[i][qpInVal[j]] + + (getDeltaOutVal(i, j + 1) * m + sh) / (getDeltaInValMinus1(i, j + 1) + 1); + } + } + for (int k = qpInVal[numPtsInCQPTableMinus1]+1; k <= MAX_QP; k++) + { + m_chromaQPMappingTables[i][k] = Clip3(-qpBdOffsetC, MAX_QP, m_chromaQPMappingTables[i][k - 1] + 1); + } + } +} +#endif + PPSRExt::PPSRExt() : m_log2MaxTransformSkipBlockSize (2) , m_crossComponentPredictionEnabledFlag(false) diff --git a/source/Lib/CommonLib/Slice.h b/source/Lib/CommonLib/Slice.h index 79b3f2c91684d164d54e1ae47cb19f633c15f027..31b36debd178437fb1c2d076708deb1ef787d385 100644 --- a/source/Lib/CommonLib/Slice.h +++ b/source/Lib/CommonLib/Slice.h @@ -815,7 +815,7 @@ private: bool m_MIP; #if JVET_O0650_SIGNAL_CHROMAQP_MAPPING_TABLE bool m_sameCQPTableForAllChromaFlag; - int m_numPtsInCQPTable[MAX_NUM_CQP_MAPPING_TABLES]; + int m_numPtsInCQPTableMinus1[MAX_NUM_CQP_MAPPING_TABLES]; std::vector<int> m_deltaInValMinus1[MAX_NUM_CQP_MAPPING_TABLES]; std::vector<int> m_deltaOutVal[MAX_NUM_CQP_MAPPING_TABLES]; std::map<int,int> m_chromaQPMappingTables[MAX_NUM_CQP_MAPPING_TABLES]; @@ -1083,16 +1083,18 @@ public: void setUseWPBiPred ( bool b ) { m_useWeightedBiPred = b; } #endif #if JVET_O0650_SIGNAL_CHROMAQP_MAPPING_TABLE - bool setSameCQPTableForAllChromaFlag (bool b) { m_sameCQPTableForAllChromaFlag = b; } + void setSameCQPTableForAllChromaFlag (bool b) { m_sameCQPTableForAllChromaFlag = b; } bool getSameCQPTableForAllChromaFlag() const { return m_sameCQPTableForAllChromaFlag; } - bool setNumPtsInCQPTableMinus1 (int tableIdx, int n) { m_numPtsInCQPTableMinus1[tableIdx] = n; } - bool getNumPtsInCQPTableMinus1(int tableIdx) const { return m_numPtsInCQPTableMinus1[tableIdx]; } - bool setDeltaInValMinus1 (int tableIdx, int idx, int n) { m_deltaInValMinus1[tableIdx][idx] = n; } - bool getDeltaInValMinus1(int tableIdx, int idx) const { return m_deltaInValMinus1[tableIdx][idx]; } - bool setDeltaOutVal(int tableIdx, int idx, int n) { m_deltaOutVal[tableIdx][idx] = n; } - bool getDeltaOutVal(int tableIdx, int idx) const { return m_deltaOutVal[tableIdx][idx]; } - - int getMappedChromaQPValue (ComponentID compID, const int qpVal) { return m_chromaQPMappingTables[m_sameCQPTableForAllChromaFlag ? 0 : compID - 1][qpVal]; } + void setNumPtsInCQPTableMinus1 (int tableIdx, int n) { m_numPtsInCQPTableMinus1[tableIdx] = n; } + int getNumPtsInCQPTableMinus1(int tableIdx) const { return m_numPtsInCQPTableMinus1[tableIdx]; } + void setDeltaInValMinus1(int tableIdx, std::vector<int> &inVals) { m_deltaInValMinus1[tableIdx] = inVals; } + void setDeltaInValMinus1 (int tableIdx, int idx, int n) { m_deltaInValMinus1[tableIdx][idx] = n; } + int getDeltaInValMinus1(int tableIdx, int idx) const { return m_deltaInValMinus1[tableIdx][idx]; } + void setDeltaOutVal(int tableIdx, std::vector<int> &outVals) { m_deltaOutVal[tableIdx] = outVals; } + void setDeltaOutVal(int tableIdx, int idx, int n) { m_deltaOutVal[tableIdx][idx] = n; } + int getDeltaOutVal(int tableIdx, int idx) const { return m_deltaOutVal[tableIdx][idx]; } + + int getMappedChromaQPValue (ComponentID compID, const int qpVal) const { return m_chromaQPMappingTables[m_sameCQPTableForAllChromaFlag ? 0 : (int)compID - 1].at(qpVal); } void derivedChromaQPMappingTables(); #endif }; diff --git a/source/Lib/DecoderLib/VLCReader.cpp b/source/Lib/DecoderLib/VLCReader.cpp index ee3c8b361fac33e1b1662760f743e897f4b8abe9..81be7ff9bf4d3d2bbcc04ac5fab9ac5a337334ba 100644 --- a/source/Lib/DecoderLib/VLCReader.cpp +++ b/source/Lib/DecoderLib/VLCReader.cpp @@ -1244,16 +1244,18 @@ void HLSyntaxReader::parseSPS(SPS* pcSPS) if (pcSPS->getChromaFormatIdc() != CHROMA_400) { READ_FLAG(uiCode, "same_qp_table_for_chroma"); pcSPS->setSameCQPTableForAllChromaFlag(uiCode); - for (int i = 0; i < pcSPS->getSameCQPTableForAllChromaFlag() ? 1 : 3; i++) + for (int i = 0; i < (pcSPS->getSameCQPTableForAllChromaFlag() ? 1 : 3); i++) { - int numPtsInTableMinus1 = 0; - READ_UVLC(uiCode, "num_points_in_qp_table_minus1"); pcSPS->setNumPtsInCQPTableMinus1(i, uiCode); - + READ_UVLC(uiCode, "num_points_in_qp_table_minus1"); pcSPS->setNumPtsInCQPTableMinus1(i,uiCode); + std::vector<int> deltaInValMinus1(pcSPS->getNumPtsInCQPTableMinus1(i) + 1); + std::vector<int> deltaOutVal(pcSPS->getNumPtsInCQPTableMinus1(i) + 1); for (int j = 0; j <= pcSPS->getNumPtsInCQPTableMinus1(i); j++) { - READ_UVLC(uiCode, "delta_qp_in_val_minus1"); pcSPS->setDeltaInValMinus1(i, j, uiCode); - READ_UVLC(uiCode, "delta_qp_out_val"); pcSPS->setDeltaOutVal(i, j, uiCode); + READ_UVLC(uiCode, "delta_qp_in_val_minus1"); deltaInValMinus1[j] = uiCode; + READ_UVLC(uiCode, "delta_qp_out_val"); deltaOutVal[j] = uiCode; } + pcSPS->setDeltaInValMinus1(i, deltaInValMinus1); + pcSPS->setDeltaOutVal(i, deltaOutVal); } pcSPS->derivedChromaQPMappingTables(); } diff --git a/source/Lib/EncoderLib/EncCfg.h b/source/Lib/EncoderLib/EncCfg.h index 240292bb808abeb7053bec27da00900fde4da9ee..1515a5f832b29310077b3b8640320c8b2ef5ab85 100644 --- a/source/Lib/EncoderLib/EncCfg.h +++ b/source/Lib/EncoderLib/EncCfg.h @@ -239,6 +239,12 @@ protected: int m_numReorderPics[MAX_TLAYER]; int m_iQP; // if (AdaptiveQP == OFF) +#if JVET_O0650_SIGNAL_CHROMAQP_MAPPING_TABLE + bool m_sameCQPTableForAllChroma; + int m_numPtsInCQPTableMinus1[MAX_NUM_CQP_MAPPING_TABLES]; + std::vector<int> m_deltaInValMinus1[MAX_NUM_CQP_MAPPING_TABLES]; + std::vector<int> m_deltaOutVal[MAX_NUM_CQP_MAPPING_TABLES]; +#endif #if X0038_LAMBDA_FROM_QP_CAPABILITY int m_intraQPOffset; ///< QP offset for intra slice (integer) int m_lambdaFromQPEnable; ///< enable lambda derivation from QP @@ -780,6 +786,18 @@ public: #if X0038_LAMBDA_FROM_QP_CAPABILITY void setIntraQPOffset ( int i ) { m_intraQPOffset = i; } void setLambdaFromQPEnable ( bool b ) { m_lambdaFromQPEnable = b; } +#endif +#if JVET_O0650_SIGNAL_CHROMAQP_MAPPING_TABLE + void setSameCQPTableForAllChroma(bool b) { m_sameCQPTableForAllChroma = b; } + bool getSameCQPTableForAllChroma() const { return m_sameCQPTableForAllChroma; } + void setNumPtsInCQPTableMinus1(int tableIdx, int n) { m_numPtsInCQPTableMinus1[tableIdx] = n; } + int getNumPtsInCQPTableMinus1(int tableIdx) const { return m_numPtsInCQPTableMinus1[tableIdx]; } + void setDeltaInValMinus1(int tableIdx, std::vector<int> &inVals) { m_deltaInValMinus1[tableIdx] = inVals; } + void setDeltaInValMinus1(int tableIdx, int idx, int n) { m_deltaInValMinus1[tableIdx][idx] = n; } + int getDeltaInValMinus1(int tableIdx, int idx) const { return m_deltaInValMinus1[tableIdx][idx]; } + void setDeltaOutVal(int tableIdx, std::vector<int> &outVals) { m_deltaOutVal[tableIdx] = outVals; } + void setDeltaOutVal(int tableIdx, int idx, int n) { m_deltaOutVal[tableIdx][idx] = n; } + int getDeltaOutVal(int tableIdx, int idx) const { return m_deltaOutVal[tableIdx][idx]; } #endif void setPad ( int* iPad ) { for ( int i = 0; i < 2; i++ ) m_aiPad[i] = iPad[i]; } diff --git a/source/Lib/EncoderLib/EncLib.cpp b/source/Lib/EncoderLib/EncLib.cpp index dd743359da715987bb89226d26cce6ec2fc741fc..c15d7c4bac55cb34e3302262f2c0d6d97e3147cd 100644 --- a/source/Lib/EncoderLib/EncLib.cpp +++ b/source/Lib/EncoderLib/EncLib.cpp @@ -1039,6 +1039,16 @@ void EncLib::xInitSPS(SPS &sps) sps.setLtRefPicPocLsbSps(k, 0); sps.setUsedByCurrPicLtSPSFlag(k, 0); } +#if JVET_O0650_SIGNAL_CHROMAQP_MAPPING_TABLE + sps.setSameCQPTableForAllChromaFlag(m_sameCQPTableForAllChroma); + for (int i = 0; i < (m_sameCQPTableForAllChroma ? 1 : 3); i++) + { + sps.setNumPtsInCQPTableMinus1(i, (int)m_deltaInValMinus1[i].size() - 1); + sps.setDeltaInValMinus1(i, m_deltaInValMinus1[i]); + sps.setDeltaOutVal(i, m_deltaOutVal[i]); + } + sps.derivedChromaQPMappingTables(); +#endif #if U0132_TARGET_BITS_SATURATION if( getPictureTimingSEIEnabled() || getDecodingUnitInfoSEIEnabled() || getCpbSaturationEnabled() ) diff --git a/source/Lib/EncoderLib/EncSlice.cpp b/source/Lib/EncoderLib/EncSlice.cpp index 1e75780bbd9b591b0458bf9c8f06a95d8b1aa350..2abbf9b1dc6b31b7885276bd8bd85c7194d00888 100644 --- a/source/Lib/EncoderLib/EncSlice.cpp +++ b/source/Lib/EncoderLib/EncSlice.cpp @@ -117,7 +117,11 @@ EncSlice::setUpLambda( Slice* slice, const double dLambda, int iQP) { const ComponentID compID = ComponentID( compIdx ); int chromaQPOffset = slice->getPPS()->getQpOffset( compID ) + slice->getSliceChromaQpDelta( compID ); +#if JVET_O0650_SIGNAL_CHROMAQP_MAPPING_TABLE + int qpc = slice->getSPS()->getMappedChromaQPValue(compID, iQP) + chromaQPOffset; +#else int qpc = ( iQP + chromaQPOffset < 0 ) ? iQP : getScaledChromaQP( iQP + chromaQPOffset, m_pcCfg->getChromaFormatIdc() ); +#endif double tmpWeight = pow( 2.0, ( iQP - qpc ) / 3.0 ); // takes into account of the chroma qp mapping and chroma qp Offset if( m_pcCfg->getDepQuantEnabledFlag() && !( m_pcCfg->getLFNST() ) ) { @@ -296,7 +300,11 @@ static int applyQPAdaptationChroma (Picture* const pcPic, Slice* const pcSlice, savedLumaQP = averageAdaptedLumaQP; } // savedLumaQP < 0 +#if JVET_O0650_SIGNAL_CHROMAQP_MAPPING_TABLE + const int lumaChromaMappingDQP = savedLumaQP - pcSlice->getSPS()->getMappedChromaQPValue(compID, savedLumaQP); +#else const int lumaChromaMappingDQP = savedLumaQP - getScaledChromaQP (savedLumaQP, pcEncCfg->getChromaFormatIdc()); +#endif optSliceChromaQpOffset[comp-1] = std::min (3 + lumaChromaMappingDQP, adaptChromaQPOffset + lumaChromaMappingDQP); } diff --git a/source/Lib/EncoderLib/VLCWriter.cpp b/source/Lib/EncoderLib/VLCWriter.cpp index 27f1230584248a5f2ac7eef7385399dc198bdafe..bf4fdc5e98cadcd4ea3d917849d0b39f771dc071 100644 --- a/source/Lib/EncoderLib/VLCWriter.cpp +++ b/source/Lib/EncoderLib/VLCWriter.cpp @@ -844,14 +844,13 @@ void HLSWriter::codeSPS( const SPS* pcSPS ) if (pcSPS->getChromaFormatIdc() != CHROMA_400) { WRITE_FLAG(pcSPS->getSameCQPTableForAllChromaFlag(), "same_qp_table_for_chroma"); - for (int i = 0; i < pcSPS->getSameCQPTableForAllChromaFlag() ? 1 : 3; i++) + for (int i = 0; i < (pcSPS->getSameCQPTableForAllChromaFlag() ? 1 : 3); i++) { - WRITE_UVLC(pcSPS->getNumPtsInCQPTableMinus[i], "num_points_in_qp_table_minus1"); - - for (int j = 0; j <= pcSPS->getNumPtsInCQPTableMinus[i]; j++) + WRITE_UVLC(pcSPS->getNumPtsInCQPTableMinus1(i), "num_points_in_qp_table_minus1"); + for (int j = 0; j <= pcSPS->getNumPtsInCQPTableMinus1(i); j++) { - WRITE_UVLC(pcSPS->getDeltaInValMinus1[i][j], "delta_qp_in_val_minus1"); - WRITE_UVLC(pcSPS->getDeltaOutVal[i][j], "delta_qp_out_val"); + WRITE_UVLC(pcSPS->getDeltaInValMinus1(i,j), "delta_qp_in_val_minus1"); + WRITE_UVLC(pcSPS->getDeltaOutVal(i, j), "delta_qp_out_val"); } } }