From c6a54ff37345eaff1f7ae3730a7141a4e5cd561d Mon Sep 17 00:00:00 2001 From: delagrangep <philippe.delagrange@interdigital.com> Date: Wed, 10 Feb 2021 18:16:06 +0100 Subject: [PATCH] Fix tickets #1461, #1462, #1463: chroma dQP bug fixes and configuration parameters improvements. --- source/App/EncoderApp/EncApp.cpp | 2 + source/App/EncoderApp/EncAppCfg.cpp | 56 +++++++++++++++++++- source/App/EncoderApp/EncAppCfg.h | 4 +- source/Lib/EncoderLib/CABACWriter.cpp | 2 + source/Lib/EncoderLib/EncCfg.h | 11 ++-- source/Lib/EncoderLib/EncCu.cpp | 76 ++++++++++++++++----------- source/Lib/EncoderLib/EncLib.cpp | 23 ++++---- source/Lib/EncoderLib/EncModeCtrl.cpp | 2 +- source/Lib/EncoderLib/EncSlice.cpp | 2 +- source/Lib/EncoderLib/VLCWriter.cpp | 11 +--- 10 files changed, 128 insertions(+), 61 deletions(-) diff --git a/source/App/EncoderApp/EncApp.cpp b/source/App/EncoderApp/EncApp.cpp index 2755f729d..59a247668 100644 --- a/source/App/EncoderApp/EncApp.cpp +++ b/source/App/EncoderApp/EncApp.cpp @@ -585,6 +585,8 @@ void EncApp::xInitLibCfg() m_cEncLib.setMaxDeltaQP ( m_iMaxDeltaQP ); m_cEncLib.setCuQpDeltaSubdiv ( m_cuQpDeltaSubdiv ); m_cEncLib.setCuChromaQpOffsetSubdiv ( m_cuChromaQpOffsetSubdiv ); + m_cEncLib.setCuChromaQpOffsetList ( m_cuChromaQpOffsetList ); + m_cEncLib.setCuChromaQpOffsetEnabled ( m_cuChromaQpOffsetEnabled ); m_cEncLib.setChromaCbQpOffset ( m_cbQpOffset ); m_cEncLib.setChromaCrQpOffset ( m_crQpOffset ); m_cEncLib.setChromaCbQpOffsetDualTree ( m_cbQpOffsetDualTree ); diff --git a/source/App/EncoderApp/EncAppCfg.cpp b/source/App/EncoderApp/EncAppCfg.cpp index 7094cf7ed..d32a7a312 100644 --- a/source/App/EncoderApp/EncAppCfg.cpp +++ b/source/App/EncoderApp/EncAppCfg.cpp @@ -606,6 +606,11 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] ) SMultiValueInput<int> cfg_qpOutValCr (MIN_QP_VALUE_FOR_16_BIT, MAX_QP, 0, MAX_NUM_QP_VALUES, zeroVector, 1); SMultiValueInput<int> cfg_qpInValCbCr (MIN_QP_VALUE_FOR_16_BIT, MAX_QP, 0, MAX_NUM_QP_VALUES, zeroVector, 1); SMultiValueInput<int> cfg_qpOutValCbCr (MIN_QP_VALUE_FOR_16_BIT, MAX_QP, 0, MAX_NUM_QP_VALUES, zeroVector, 1); + const int cQpOffsets[] = { 6 }; + SMultiValueInput<int> cfg_cbQpOffsetList (-12, 12, 0, 6, cQpOffsets, 0); + SMultiValueInput<int> cfg_crQpOffsetList (-12, 12, 0, 6, cQpOffsets, 0); + SMultiValueInput<int> cfg_cbCrQpOffsetList (-12, 12, 0, 6, cQpOffsets, 0); + 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)); @@ -1039,7 +1044,8 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] ) ("DeltaQpRD,-dqr", m_uiDeltaQpRD, 0u, "max dQp offset for slice") ("MaxDeltaQP,d", m_iMaxDeltaQP, 0, "max dQp offset for block") ("MaxCuDQPSubdiv,-dqd", m_cuQpDeltaSubdiv, 0, "Maximum subdiv for CU luma Qp adjustment") - ("MaxCuChromaQpOffsetSubdiv", m_cuChromaQpOffsetSubdiv, -1, "Maximum subdiv for CU chroma Qp adjustment - set less than 0 to disable") + ("MaxCuChromaQpOffsetSubdiv", m_cuChromaQpOffsetSubdiv, -1, "Maximum subdiv for CU chroma Qp adjustment") + ("CuChromaQpOffsetEnabled", m_cuChromaQpOffsetEnabled, -1, "Enable local chroma QP offsets (slice level flag)") ("FastDeltaQP", m_bFastDeltaQP, false, "Fast Delta QP Algorithm") #if SHARP_LUMA_DELTA_QP ("LumaLevelToDeltaQPMode", lumaLevelToDeltaQPMode, 0u, "Luma based Delta QP 0(default): not used. 1: Based on CTU average, 2: Based on Max luma in CTU") @@ -1075,6 +1081,9 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] ) ("SliceCbQpOffsetIntraOrPeriodic", m_sliceChromaQpOffsetIntraOrPeriodic[0], 0, "Chroma Cb QP Offset at slice level for I slice or for periodic inter slices as defined by SliceChromaQPOffsetPeriodicity. Replaces offset in the GOP table.") ("SliceCrQpOffsetIntraOrPeriodic", m_sliceChromaQpOffsetIntraOrPeriodic[1], 0, "Chroma Cr QP Offset at slice level for I slice or for periodic inter slices as defined by SliceChromaQPOffsetPeriodicity. Replaces offset in the GOP table.") #endif + ("CbQpOffsetList", cfg_cbQpOffsetList, cfg_cbQpOffsetList, "Chroma Cb QP offset list for local adjustment") + ("CrQpOffsetList", cfg_crQpOffsetList, cfg_crQpOffsetList, "Chroma Cb QP offset list for local adjustment") + ("CbCrQpOffsetList", cfg_cbCrQpOffsetList, cfg_cbCrQpOffsetList, "Chroma joint Cb-Cr QP offset list for local adjustment") ("AdaptiveQP,-aq", m_bUseAdaptiveQP, false, "QP adaptation based on a psycho-visual model") ("MaxQPAdaptationRange,-aqr", m_iQPAdaptationRange, 6, "QP adaptation range") @@ -2132,6 +2141,35 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] ) } } + /* Local chroma QP offsets configuration */ + if (m_cuChromaQpOffsetEnabled < 0) + { + m_cuChromaQpOffsetEnabled = (m_cuChromaQpOffsetSubdiv >= 0 || cfg_cbQpOffsetList.values.size() > 0); // auto-enable if unspecified + } + if (m_cuChromaQpOffsetSubdiv < 0) + { + m_cuChromaQpOffsetSubdiv = 0; // default = 0 (CTU-level) + } + CHECK(cfg_crQpOffsetList.values.size() != cfg_cbQpOffsetList.values.size(), "Chroma QP offset lists shall be the same size"); + CHECK(cfg_cbCrQpOffsetList.values.size() != cfg_cbQpOffsetList.values.size(), "Chroma QP offset lists shall be the same size"); + /* generate default chroma QP offset lists if none provided */ + if (cfg_cbQpOffsetList.values.size() == 0 && m_cuChromaQpOffsetEnabled) + { + for (int i=0; i < sizeof(cQpOffsets)/sizeof(int); i++) + { + cfg_cbQpOffsetList.values.push_back(cQpOffsets[i]); + cfg_crQpOffsetList.values.push_back(cQpOffsets[i]); + cfg_cbCrQpOffsetList.values.push_back(cQpOffsets[i]); + } + } + m_cuChromaQpOffsetList.resize(cfg_cbQpOffsetList.values.size()); + for (int i=0; i < cfg_cbQpOffsetList.values.size(); i++) + { + m_cuChromaQpOffsetList[i].u.comp.CbOffset = cfg_cbQpOffsetList.values[i]; + m_cuChromaQpOffsetList[i].u.comp.CrOffset = cfg_crQpOffsetList.values[i]; + m_cuChromaQpOffsetList[i].u.comp.JointCbCrOffset = cfg_cbCrQpOffsetList.values[i]; + } + #if LUMA_ADAPTIVE_DEBLOCKING_FILTER_QP_OFFSET if ( m_LadfEnabed ) { @@ -3871,7 +3909,21 @@ void EncAppCfg::xPrintParameter() msg( DETAILS, "MSB-extended bit depth : (Y:%d, C:%d)\n", m_MSBExtendedBitDepth[CHANNEL_TYPE_LUMA], m_MSBExtendedBitDepth[CHANNEL_TYPE_CHROMA] ); msg( DETAILS, "Internal bit depth : (Y:%d, C:%d)\n", m_internalBitDepth[CHANNEL_TYPE_LUMA], m_internalBitDepth[CHANNEL_TYPE_CHROMA] ); msg( DETAILS, "Intra reference smoothing : %s\n", (m_enableIntraReferenceSmoothing ? "Enabled" : "Disabled") ); - msg( DETAILS, "cu_chroma_qp_offset_subdiv : %d\n", m_cuChromaQpOffsetSubdiv); + if (m_cuChromaQpOffsetList.size() > 0) + { + msg( DETAILS, "Chroma QP offset list : (" ); + for (int i=0; i < m_cuChromaQpOffsetList.size(); i++) + { + msg( DETAILS, "%d %d %d%s", m_cuChromaQpOffsetList[i].u.comp.CbOffset, m_cuChromaQpOffsetList[i].u.comp.CrOffset, m_cuChromaQpOffsetList[i].u.comp.JointCbCrOffset, + (i+1 < m_cuChromaQpOffsetList.size() ? ", " : ")\n") ); + } + msg( DETAILS, "cu_chroma_qp_offset_subdiv : %d\n", m_cuChromaQpOffsetSubdiv); + msg( DETAILS, "cu_chroma_qp_offset_enabled_flag : %d\n", m_cuChromaQpOffsetEnabled); + } + else + { + msg( DETAILS, "Chroma QP offset list : Disabled\n" ); + } msg( DETAILS, "extended_precision_processing_flag : %s\n", (m_extendedPrecisionProcessingFlag ? "Enabled" : "Disabled") ); msg( DETAILS, "transform_skip_rotation_enabled_flag : %s\n", (m_transformSkipRotationEnabledFlag ? "Enabled" : "Disabled") ); msg( DETAILS, "transform_skip_context_enabled_flag : %s\n", (m_transformSkipContextEnabledFlag ? "Enabled" : "Disabled") ); diff --git a/source/App/EncoderApp/EncAppCfg.h b/source/App/EncoderApp/EncAppCfg.h index c3a789847..c9737da13 100644 --- a/source/App/EncoderApp/EncAppCfg.h +++ b/source/App/EncoderApp/EncAppCfg.h @@ -253,9 +253,11 @@ protected: std::string m_dQPFileName; ///< QP offset for each slice (initialized from external file) int* m_aidQP; ///< array of slice QP values int m_iMaxDeltaQP; ///< max. |delta QP| - uint32_t m_uiDeltaQpRD; ///< dQP range for multi-pass slice QP optimization + uint32_t m_uiDeltaQpRD; ///< dQP range for multi-pass slice QP optimization int m_cuQpDeltaSubdiv; ///< Maximum subdiv for CU luma Qp adjustment (0:default) int m_cuChromaQpOffsetSubdiv; ///< If negative, then do not apply chroma qp offsets. + std::vector<ChromaQpAdj> m_cuChromaQpOffsetList; ///< Local chroma QP offsets list (to be signalled in PPS) + int m_cuChromaQpOffsetEnabled; ///< Enable local chroma QP offsets (slice level flag) bool m_bFastDeltaQP; ///< Fast Delta QP (false:default) int m_cbQpOffset; ///< Chroma Cb QP Offset (0:default) diff --git a/source/Lib/EncoderLib/CABACWriter.cpp b/source/Lib/EncoderLib/CABACWriter.cpp index fb739b395..96948ed51 100644 --- a/source/Lib/EncoderLib/CABACWriter.cpp +++ b/source/Lib/EncoderLib/CABACWriter.cpp @@ -2575,6 +2575,8 @@ void CABACWriter::transform_unit( const TransformUnit& tu, CUCtx& cuCtx, Partiti } } } + + DTRACE_COND( ( isEncoding() ), g_trace_ctx, D_DQP, "x=%d, y=%d, d=%d, qpAdj=%d\n", cu.blocks[cu.chType].lumaPos().x, cu.blocks[cu.chType].lumaPos().y, cu.qtDepth, cu.chromaQpAdj ); } void CABACWriter::cu_qp_delta( const CodingUnit& cu, int predQP, const int8_t qp ) diff --git a/source/Lib/EncoderLib/EncCfg.h b/source/Lib/EncoderLib/EncCfg.h index 45ffac06c..626a04524 100644 --- a/source/Lib/EncoderLib/EncCfg.h +++ b/source/Lib/EncoderLib/EncCfg.h @@ -428,7 +428,9 @@ protected: //====== Quality control ======== int m_iMaxDeltaQP; // Max. absolute delta QP (1:default) int m_cuQpDeltaSubdiv; // Max. subdivision level for a CuDQP (0:default) - int m_cuChromaQpOffsetSubdiv; ///< If negative, then do not apply chroma qp offsets. + unsigned m_cuChromaQpOffsetSubdiv; ///< Max. subdivision level for a chroma QP adjustment (0:default) + bool m_cuChromaQpOffsetEnabled; ///< Local chroma QP offset enable flag + std::vector<ChromaQpAdj> m_cuChromaQpOffsetList; ///< Local chroma QP offsets list (to be signalled in PPS) int m_chromaCbQpOffset; // Chroma Cb QP Offset (0:default) int m_chromaCrQpOffset; // Chroma Cr Qp Offset (0:default) @@ -1232,8 +1234,11 @@ public: //====== Quality control ======== void setMaxDeltaQP ( int i ) { m_iMaxDeltaQP = i; } void setCuQpDeltaSubdiv ( int i ) { m_cuQpDeltaSubdiv = i; } - int getCuChromaQpOffsetSubdiv () const { return m_cuChromaQpOffsetSubdiv; } - void setCuChromaQpOffsetSubdiv (int value) { m_cuChromaQpOffsetSubdiv = value; } + unsigned getCuChromaQpOffsetSubdiv () const { return m_cuChromaQpOffsetSubdiv; } + void setCuChromaQpOffsetSubdiv ( unsigned value ) { m_cuChromaQpOffsetSubdiv = value; } + bool getCuChromaQpOffsetEnabled () const { return m_cuChromaQpOffsetEnabled; } + void setCuChromaQpOffsetEnabled ( bool value ) { m_cuChromaQpOffsetEnabled = value; } + void setCuChromaQpOffsetList (const std::vector<ChromaQpAdj> &list) { m_cuChromaQpOffsetList = list; } void setChromaCbQpOffset ( int i ) { m_chromaCbQpOffset = i; } void setChromaCrQpOffset ( int i ) { m_chromaCrQpOffset = i; } diff --git a/source/Lib/EncoderLib/EncCu.cpp b/source/Lib/EncoderLib/EncCu.cpp index 1e7a9db44..882255138 100644 --- a/source/Lib/EncoderLib/EncCu.cpp +++ b/source/Lib/EncoderLib/EncCu.cpp @@ -626,18 +626,20 @@ void EncCu::xCompressCU( CodingStructure*& tempCS, CodingStructure*& bestCS, Par m_CurrCtx->start = m_CABACEstimator->getCtx(); - m_cuChromaQpOffsetIdxPlus1 = 0; - if( slice.getUseChromaQpAdj() ) { // TODO M0133 : double check encoder decisions with respect to chroma QG detection and actual encode int lgMinCuSize = sps.getLog2MinCodingBlockSize() + - std::max<int>(0, floorLog2(sps.getCTUSize()) - sps.getLog2MinCodingBlockSize() - int(slice.getCuChromaQpOffsetSubdiv() / 2)); + std::max<int>(0, floorLog2(sps.getCTUSize()) - sps.getLog2MinCodingBlockSize() - int((slice.getCuChromaQpOffsetSubdiv()+1) / 2)); if( partitioner.currQgChromaEnable() ) { m_cuChromaQpOffsetIdxPlus1 = ( ( uiLPelX >> lgMinCuSize ) + ( uiTPelY >> lgMinCuSize ) ) % ( pps.getChromaQpOffsetListLen() + 1 ); } } + else + { + m_cuChromaQpOffsetIdxPlus1 = 0; + } if( !m_modeCtrl->anyMode() ) { @@ -1293,6 +1295,7 @@ void EncCu::xCheckModeSplit(CodingStructure *&tempCS, CodingStructure *&bestCS, partitioner.splitCurrArea( split, *tempCS ); bool qgEnableChildren = partitioner.currQgEnable(); // QG possible at children level + bool qgChromaEnableChildren = partitioner.currQgChromaEnable(); // Chroma QG possible at children level m_CurrCtx++; @@ -1500,6 +1503,13 @@ void EncCu::xCheckModeSplit(CodingStructure *&tempCS, CodingStructure *&bestCS, partitioner.treeType = TREE_D; partitioner.modeType = MODE_TYPE_ALL; } + else + { + if (!qgChromaEnableChildren) // check at deepest cQG level only + { + xCheckChromaQPOffset( *tempCS, partitioner ); + } + } // Finally, generate split-signaling bits for RD-cost check const PartSplit implicitSplit = partitioner.getImplicitSplit( *tempCS ); @@ -2156,43 +2166,47 @@ void EncCu::xCheckChromaQPOffset( CodingStructure& cs, Partitioner& partitioner return; } - // not needed after the first coded TU in the chroma QG + // check cost only at cQG top-level (everything below shall not be influenced by adj coding: it occurs only once) if( !partitioner.currQgChromaEnable() ) { return; } - CodingUnit& cu = *cs.getCU( partitioner.chType ); - // check if chroma is coded or not - bool hasResidual = false; - for( const TransformUnit &tu : CU::traverseTUs(cu) ) + bool isCoded = false; + for( auto &cu : cs.cus ) { - if( tu.cbf[COMPONENT_Cb] || tu.cbf[COMPONENT_Cr] ) + SizeType channelWidth = !cu->isSepTree() ? cu->lwidth() : cu->chromaSize().width; + SizeType channelHeight = !cu->isSepTree() ? cu->lheight() : cu->chromaSize().height; + + for( const TransformUnit &tu : CU::traverseTUs(*cu) ) { - hasResidual = true; + if( tu.cbf[COMPONENT_Cb] || tu.cbf[COMPONENT_Cr] || channelWidth > 64 || channelHeight > 64) + { + isCoded = true; + break; + } + } + if (isCoded) + { + // estimate cost for coding cu_chroma_qp_offset + TempCtx ctxTempAdjFlag( m_CtxCache ); + TempCtx ctxTempAdjIdc( m_CtxCache ); + ctxTempAdjFlag = SubCtx( Ctx::ChromaQpAdjFlag, m_CABACEstimator->getCtx() ); + ctxTempAdjIdc = SubCtx( Ctx::ChromaQpAdjIdc, m_CABACEstimator->getCtx() ); + m_CABACEstimator->resetBits(); + m_CABACEstimator->cu_chroma_qp_offset( *cu ); + cs.fracBits += m_CABACEstimator->getEstFracBits(); + cs.cost = m_pcRdCost->calcRdCost(cs.fracBits, cs.dist); + m_CABACEstimator->getCtx() = SubCtx( Ctx::ChromaQpAdjFlag, ctxTempAdjFlag ); + m_CABACEstimator->getCtx() = SubCtx( Ctx::ChromaQpAdjIdc, ctxTempAdjIdc ); break; } - } - - if( hasResidual ) - { - // estimate cost for coding cu_chroma_qp_offset - TempCtx ctxTempAdjFlag( m_CtxCache ); - TempCtx ctxTempAdjIdc( m_CtxCache ); - ctxTempAdjFlag = SubCtx( Ctx::ChromaQpAdjFlag, m_CABACEstimator->getCtx() ); - ctxTempAdjIdc = SubCtx( Ctx::ChromaQpAdjIdc, m_CABACEstimator->getCtx() ); - m_CABACEstimator->resetBits(); - m_CABACEstimator->cu_chroma_qp_offset( cu ); - cs.fracBits += m_CABACEstimator->getEstFracBits(); - cs.cost = m_pcRdCost->calcRdCost(cs.fracBits, cs.dist); - m_CABACEstimator->getCtx() = SubCtx( Ctx::ChromaQpAdjFlag, ctxTempAdjFlag ); - m_CABACEstimator->getCtx() = SubCtx( Ctx::ChromaQpAdjIdc, ctxTempAdjIdc ); - } - else - { - // reset chroma QP offset to 0 if it will not be coded - cu.chromaQpAdj = 0; + else + { + // chroma QP adj is forced to 0 for leading uncoded CUs + cu->chromaQpAdj = 0; + } } } @@ -2864,6 +2878,7 @@ void EncCu::xCheckRDCostMergeGeo2Nx2N(CodingStructure *&tempCS, CodingStructure cu.predMode = MODE_INTER; cu.slice = tempCS->slice; cu.tileIdx = tempCS->pps->getTileIdx(tempCS->area.lumaPos()); + cu.chromaQpAdj = m_cuChromaQpOffsetIdxPlus1; cu.qp = encTestMode.qp; cu.affine = false; cu.mtsFlag = false; @@ -3083,6 +3098,7 @@ void EncCu::xCheckRDCostMergeGeo2Nx2N(CodingStructure *&tempCS, CodingStructure cu.predMode = MODE_INTER; cu.slice = tempCS->slice; cu.tileIdx = tempCS->pps->getTileIdx(tempCS->area.lumaPos()); + cu.chromaQpAdj = m_cuChromaQpOffsetIdxPlus1; cu.qp = encTestMode.qp; cu.affine = false; cu.mtsFlag = false; diff --git a/source/Lib/EncoderLib/EncLib.cpp b/source/Lib/EncoderLib/EncLib.cpp index 34c2862a1..e6de9ff33 100644 --- a/source/Lib/EncoderLib/EncLib.cpp +++ b/source/Lib/EncoderLib/EncLib.cpp @@ -1609,11 +1609,15 @@ void EncLib::xInitPPS(PPS &pps, const SPS &sps) pps.setUseDQP(false); } - if ( m_cuChromaQpOffsetSubdiv >= 0 ) + if ( m_cuChromaQpOffsetList.size() > 0 ) { + /* insert table entries from cfg parameters (NB, 0 should not be touched) */ pps.clearChromaQpOffsetList(); - pps.setChromaQpOffsetListEntry(1, 6, 6, 6); - /* todo, insert table entries from command line (NB, 0 should not be touched) */ + for (int i=0; i < m_cuChromaQpOffsetList.size(); i++) + { + pps.setChromaQpOffsetListEntry(i + 1, m_cuChromaQpOffsetList[i].u.comp.CbOffset, + m_cuChromaQpOffsetList[i].u.comp.CrOffset, m_cuChromaQpOffsetList[i].u.comp.JointCbCrOffset); + } } else { @@ -1929,17 +1933,8 @@ void EncLib::xInitPicHeader(PicHeader &picHeader, const SPS &sps, const PPS &pps picHeader.setCuQpDeltaSubdivInter( 0 ); } - if( m_cuChromaQpOffsetSubdiv >= 0 ) - { - picHeader.setCuChromaQpOffsetSubdivIntra(m_cuChromaQpOffsetSubdiv); - picHeader.setCuChromaQpOffsetSubdivInter(m_cuChromaQpOffsetSubdiv); - } - else - { - picHeader.setCuChromaQpOffsetSubdivIntra(0); - picHeader.setCuChromaQpOffsetSubdivInter(0); - } - + picHeader.setCuChromaQpOffsetSubdivIntra(m_cuChromaQpOffsetSubdiv); + picHeader.setCuChromaQpOffsetSubdivInter(m_cuChromaQpOffsetSubdiv); // virtual boundaries if( sps.getVirtualBoundariesEnabledFlag() ) diff --git a/source/Lib/EncoderLib/EncModeCtrl.cpp b/source/Lib/EncoderLib/EncModeCtrl.cpp index 26aac4f07..92bb6c05e 100644 --- a/source/Lib/EncoderLib/EncModeCtrl.cpp +++ b/source/Lib/EncoderLib/EncModeCtrl.cpp @@ -1314,7 +1314,7 @@ void EncModeCtrlMTnoRQT::initCULevel( Partitioner &partitioner, const CodingStru { const int qp = std::max( qpLoop, lowestQP ); #if REUSE_CU_RESULTS - const bool isReusingCu = isValid( cs, partitioner, qp ); + const bool isReusingCu = isValid( cs, partitioner, qp ) && !cs.slice->getUseChromaQpAdj(); cuECtx.set( IS_REUSING_CU, isReusingCu ); if( isReusingCu ) { diff --git a/source/Lib/EncoderLib/EncSlice.cpp b/source/Lib/EncoderLib/EncSlice.cpp index bec81962a..637c50754 100644 --- a/source/Lib/EncoderLib/EncSlice.cpp +++ b/source/Lib/EncoderLib/EncSlice.cpp @@ -628,7 +628,7 @@ void EncSlice::initEncSlice(Picture* pcPic, const int pocLast, const int pocCurr rpcSlice->setSliceChromaQpDelta( COMPONENT_Cr, 0 ); rpcSlice->setSliceChromaQpDelta( JOINT_CbCr, 0 ); #endif - rpcSlice->setUseChromaQpAdj( rpcSlice->getPPS()->getCuChromaQpOffsetListEnabledFlag() ); + rpcSlice->setUseChromaQpAdj( m_pcCfg->getCuChromaQpOffsetEnabled() ); rpcSlice->setNumRefIdx(REF_PIC_LIST_0, m_pcCfg->getRPLEntry(0, iGOPid).m_numRefPicsActive); rpcSlice->setNumRefIdx(REF_PIC_LIST_1, m_pcCfg->getRPLEntry(1, iGOPid).m_numRefPicsActive); diff --git a/source/Lib/EncoderLib/VLCWriter.cpp b/source/Lib/EncoderLib/VLCWriter.cpp index c4bf74615..8f4ed84b8 100644 --- a/source/Lib/EncoderLib/VLCWriter.cpp +++ b/source/Lib/EncoderLib/VLCWriter.cpp @@ -1875,10 +1875,6 @@ WRITE_FLAG(picHeader->getGdrOrIrapPicFlag(), "ph_gdr_or_irap_pic_flag"); { WRITE_UVLC( picHeader->getCuChromaQpOffsetSubdivIntra(), "ph_cu_chroma_qp_offset_subdiv_intra_slice" ); } - else - { - picHeader->setCuChromaQpOffsetSubdivIntra( 0 ); - } } @@ -1908,11 +1904,8 @@ WRITE_FLAG(picHeader->getGdrOrIrapPicFlag(), "ph_gdr_or_irap_pic_flag"); { WRITE_UVLC(picHeader->getCuChromaQpOffsetSubdivInter(), "ph_cu_chroma_qp_offset_subdiv_inter_slice"); } - else - { - picHeader->setCuChromaQpOffsetSubdivInter(0); - } - // temporal motion vector prediction + + // temporal motion vector prediction if (sps->getSPSTemporalMVPEnabledFlag()) { WRITE_FLAG( picHeader->getEnableTMVPFlag(), "ph_temporal_mvp_enabled_flag" ); -- GitLab