From 6e1e6fe847a2ad8f802a062c2789103cb62b0487 Mon Sep 17 00:00:00 2001 From: Philippe de Lagrange <philippe.delagrange@technicolor.com> Date: Mon, 11 Mar 2019 17:32:30 +0100 Subject: [PATCH] Compatiblity with ENABLE_QPA_SUB_CTU --- source/App/EncoderApp/EncAppCfg.cpp | 4 ++++ source/Lib/CommonLib/TypeDef.h | 2 +- source/Lib/CommonLib/UnitPartitioner.cpp | 24 ++++++++++++++++++++++-- source/Lib/CommonLib/UnitPartitioner.h | 2 ++ source/Lib/EncoderLib/EncCu.cpp | 9 ++++++++- source/Lib/EncoderLib/EncGOP.cpp | 8 ++++++-- source/Lib/EncoderLib/EncModeCtrl.cpp | 14 +++++++++++--- source/Lib/EncoderLib/EncSlice.cpp | 8 +++++++- 8 files changed, 61 insertions(+), 10 deletions(-) diff --git a/source/App/EncoderApp/EncAppCfg.cpp b/source/App/EncoderApp/EncAppCfg.cpp index 2d44db673..7a06d6476 100644 --- a/source/App/EncoderApp/EncAppCfg.cpp +++ b/source/App/EncoderApp/EncAppCfg.cpp @@ -1940,7 +1940,11 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] ) && ((1 << (MAX_TB_LOG2_SIZEY + 1)) == m_uiCTUSize) && (m_iSourceWidth > 512 || m_iSourceHeight > 320)) #endif { +#if JVET_M0113_M0188_QG_SIZE + m_cuQpDeltaSubdiv = 2; +#else m_iMaxCuDQPDepth = 1; +#endif } #else #if QP_SWITCHING_FOR_PARALLEL diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h index d1b672254..eb5d6e010 100644 --- a/source/Lib/CommonLib/TypeDef.h +++ b/source/Lib/CommonLib/TypeDef.h @@ -372,7 +372,7 @@ typedef std::pair<int, int> TrCost; #define SHARP_LUMA_DELTA_QP 1 ///< include non-normative LCU deltaQP and normative chromaQP change #define ER_CHROMA_QP_WCG_PPS 1 ///< Chroma QP model for WCG used in Anchor 3.2 #define ENABLE_QPA 1 ///< Non-normative perceptual QP adaptation according to JVET-H0047 and JVET-K0206. Deactivated by default, activated using encoder arguments --PerceptQPA=1 --SliceChromaQPOffsetPeriodicity=1 -#define ENABLE_QPA_SUB_CTU ( !JVET_M0113_M0188_QG_SIZE && ENABLE_QPA ) ///< when maximum delta-QP depth is greater than zero, use sub-CTU QPA +#define ENABLE_QPA_SUB_CTU ( 1 && ENABLE_QPA ) ///< when maximum delta-QP depth is greater than zero, use sub-CTU QPA #define RDOQ_CHROMA 1 ///< use of RDOQ in chroma diff --git a/source/Lib/CommonLib/UnitPartitioner.cpp b/source/Lib/CommonLib/UnitPartitioner.cpp index fe5d47a07..c82867dcc 100644 --- a/source/Lib/CommonLib/UnitPartitioner.cpp +++ b/source/Lib/CommonLib/UnitPartitioner.cpp @@ -131,6 +131,8 @@ void Partitioner::copyState( const Partitioner& other ) currTrDepth = other.currTrDepth; #if JVET_M0113_M0188_QG_SIZE currSubdiv = other.currSubdiv; + currQgPos = other.currQgPos; + currQgChromaPos = other.currQgChromaPos; #endif currImplicitBtDepth = other.currImplicitBtDepth; @@ -241,6 +243,8 @@ void QTBTPartitioner::initCtu( const UnitArea& ctuArea, const ChannelType _chTyp currQtDepth = 0; #if JVET_M0113_M0188_QG_SIZE currSubdiv = 0; + currQgPos = ctuArea.lumaPos(); + currQgChromaPos = ctuArea.chromaPos(); #endif currImplicitBtDepth = 0; chType = _chType; @@ -344,8 +348,14 @@ void QTBTPartitioner::splitCurrArea( const PartSplit split, const CodingStructur #endif } #if JVET_M0113_M0188_QG_SIZE - m_partStack.back().qgEnable = qgEnable && (currSubdiv <= cs.pps->getCuQpDeltaSubdiv()); - m_partStack.back().qgChromaEnable = qgChromaEnable && (currSubdiv <= cs.pps->getPpsRangeExtension().getCuChromaQpOffsetSubdiv()); + qgEnable &= (currSubdiv <= cs.pps->getCuQpDeltaSubdiv()); + qgChromaEnable &= (currSubdiv <= cs.pps->getPpsRangeExtension().getCuChromaQpOffsetSubdiv()); + m_partStack.back().qgEnable = qgEnable; + m_partStack.back().qgChromaEnable = qgChromaEnable; + if (qgEnable) + currQgPos = currArea().lumaPos(); + if (qgChromaEnable) + currQgChromaPos = currArea().chromaPos(); #endif } @@ -667,6 +677,10 @@ void QTBTPartitioner::exitCurrSplit() currDepth--; #if JVET_M0113_M0188_QG_SIZE currSubdiv--; + if( currQgEnable() ) + currQgPos = currArea().lumaPos(); + if( currQgChromaEnable() ) + currQgChromaPos = currArea().chromaPos(); #endif #if _DEBUG m_currArea = m_partStack.back().parts[m_partStack.back().idx]; @@ -740,6 +754,12 @@ bool QTBTPartitioner::nextPart( const CodingStructure &cs, bool autoPop /*= fals else currSubdiv++; #endif } +#if JVET_M0113_M0188_QG_SIZE + if( currQgEnable() ) + currQgPos = currArea().lumaPos(); + if( currQgChromaEnable() ) + currQgChromaPos = currArea().chromaPos(); +#endif #if _DEBUG m_currArea = m_partStack.back().parts[currIdx]; #endif diff --git a/source/Lib/CommonLib/UnitPartitioner.h b/source/Lib/CommonLib/UnitPartitioner.h index b363b7b0c..b605b6f50 100644 --- a/source/Lib/CommonLib/UnitPartitioner.h +++ b/source/Lib/CommonLib/UnitPartitioner.h @@ -129,6 +129,8 @@ public: unsigned currMtDepth; #if JVET_M0113_M0188_QG_SIZE unsigned currSubdiv; + Position currQgPos; + Position currQgChromaPos; #endif unsigned currImplicitBtDepth; diff --git a/source/Lib/EncoderLib/EncCu.cpp b/source/Lib/EncoderLib/EncCu.cpp index 2eb72295a..5ea428b0e 100644 --- a/source/Lib/EncoderLib/EncCu.cpp +++ b/source/Lib/EncoderLib/EncCu.cpp @@ -779,6 +779,8 @@ void EncCu::xCompressCU( CodingStructure *&tempCS, CodingStructure *&bestCS, Par #if REUSE_CU_RESULTS else if( currTestMode.type == ETM_RECO_CACHED ) { +#pragma message "TODO: fix missing currQP init for RECO_CACHED ?" +// tempCS->currQP[partitioner.chType] = currTestMode.qp; xReuseCachedResult( tempCS, bestCS, partitioner ); } #endif @@ -1141,7 +1143,7 @@ void EncCu::xCheckModeSplit(CodingStructure *&tempCS, CodingStructure *&bestCS, const bool bIsLosslessMode = false; // False at this level. Next level down may set it to true. const int oldPrevQp = tempCS->prevQP[partitioner.chType]; const auto oldMotionLut = tempCS->motionLut; -#if !JVET_M0113_M0188_QG_SIZE +#if !JVET_M0113_M0188_QG_SIZE || ENABLE_QPA_SUB_CTU const PPS &pps = *tempCS->pps; const uint32_t currDepth = partitioner.currDepth; #endif @@ -1206,8 +1208,13 @@ void EncCu::xCheckModeSplit(CodingStructure *&tempCS, CodingStructure *&bestCS, if (cost > bestCS->cost #endif #if ENABLE_QPA_SUB_CTU +#if JVET_M0113_M0188_QG_SIZE + || (m_pcEncCfg->getUsePerceptQPA() && !m_pcEncCfg->getUseRateCtrl() && pps.getUseDQP() && (pps.getCuQpDeltaSubdiv() > 0) && (split == CU_HORZ_SPLIT || split == CU_VERT_SPLIT) && + (currDepth == 0)) // force quad-split or no split at CTU level +#else || (m_pcEncCfg->getUsePerceptQPA() && !m_pcEncCfg->getUseRateCtrl() && pps.getUseDQP() && (pps.getMaxCuDQPDepth() > 0) && (split == CU_HORZ_SPLIT || split == CU_VERT_SPLIT) && (partitioner.currArea().lwidth() == tempCS->pcv->maxCUWidth) && (partitioner.currArea().lheight() == tempCS->pcv->maxCUHeight)) // force quad-split or no split at CTU level +#endif #endif ) { diff --git a/source/Lib/EncoderLib/EncGOP.cpp b/source/Lib/EncoderLib/EncGOP.cpp index ca313995e..c983dafd0 100644 --- a/source/Lib/EncoderLib/EncGOP.cpp +++ b/source/Lib/EncoderLib/EncGOP.cpp @@ -2180,8 +2180,12 @@ void EncGOP::compressGOP( int iPOCLast, int iNumPicRcvd, PicList& rcListPic, #if ENABLE_QPA pcPic->m_uEnerHpCtu.resize (numberOfCtusInFrame); pcPic->m_iOffsetCtu.resize (numberOfCtusInFrame); - #if ENABLE_QPA_SUB_CTU +#if ENABLE_QPA_SUB_CTU +#if JVET_M0113_M0188_QG_SIZE + if (pcSlice->getPPS()->getUseDQP() && pcSlice->getPPS()->getCuQpDeltaSubdiv() > 0) +#else if (pcSlice->getPPS()->getUseDQP() && pcSlice->getPPS()->getMaxCuDQPDepth() > 0) +#endif { const PreCalcValues &pcv = *pcPic->cs->pcv; #if MAX_TB_SIZE_SIGNALLING @@ -2191,7 +2195,7 @@ void EncGOP::compressGOP( int iPOCLast, int iNumPicRcvd, PicList& rcListPic, #endif pcPic->m_subCtuQP.resize ((pcv.maxCUWidth >> mtsLog2) * (pcv.maxCUHeight >> mtsLog2)); } - #endif +#endif #endif if (pcSlice->getSPS()->getSAOEnabledFlag()) { diff --git a/source/Lib/EncoderLib/EncModeCtrl.cpp b/source/Lib/EncoderLib/EncModeCtrl.cpp index 0eb808692..6b4384396 100644 --- a/source/Lib/EncoderLib/EncModeCtrl.cpp +++ b/source/Lib/EncoderLib/EncModeCtrl.cpp @@ -158,8 +158,8 @@ void EncModeCtrl::xGetMinMaxQP( int& minQP, int& maxQP, const CodingStructure& c maxQP = Clip3( -sps.getQpBDOffset( CHANNEL_TYPE_LUMA ), MAX_QP, baseQP + deltaQP ); } #if ENABLE_QPA_SUB_CTU - else if( qgEnableChildren ) // more splits and not the deepest QG level -#warning TODO: OR with relevant conditions, but keep compatibility with QP-RDO + else if( qgEnableChildren || (pps.getUseDQP() && pps.getCuQpDeltaSubdiv() > 0 && (!CS::isDualITree (cs) || isLuma (partitioner.chType)))) // more splits and not the deepest QG level +#pragma message "TODO: repair compatibility with QP-RDO" #else else if( qgEnableChildren ) // more splits and not the deepest QG level #endif @@ -1139,7 +1139,7 @@ void EncModeCtrlMTnoRQT::initCTUEncoding( const Slice &slice ) } } -#if ENABLE_QPA_SUB_CTU +#if ENABLE_QPA_SUB_CTU && !JVET_M0113_M0188_QG_SIZE static Position getMaxLumaDQPDepthPos (const CodingStructure &cs, const Partitioner &partitioner) { if (partitioner.currDepth <= cs.pps->getMaxCuDQPDepth()) @@ -1215,13 +1215,21 @@ void EncModeCtrlMTnoRQT::initCULevel( Partitioner &partitioner, const CodingStru baseQP = Clip3(-cs.sps->getQpBDOffset(CHANNEL_TYPE_LUMA), MAX_QP, baseQP + xComputeDQP(cs, partitioner)); } #if ENABLE_QPA_SUB_CTU +#if JVET_M0113_M0188_QG_SIZE + else if (m_pcEncCfg->getUsePerceptQPA() && !m_pcEncCfg->getUseRateCtrl() && cs.pps->getUseDQP() && cs.pps->getCuQpDeltaSubdiv() > 0) +#else else if (m_pcEncCfg->getUsePerceptQPA() && !m_pcEncCfg->getUseRateCtrl() && cs.pps->getUseDQP() && cs.pps->getMaxCuDQPDepth() > 0) +#endif { const PreCalcValues &pcv = *cs.pcv; if ((partitioner.currArea().lwidth() < pcv.maxCUWidth) && (partitioner.currArea().lheight() < pcv.maxCUHeight) && cs.picture) { +#if JVET_M0113_M0188_QG_SIZE + const Position &pos = partitioner.currQgPos; +#else const Position &pos = getMaxLumaDQPDepthPos (cs, partitioner); +#endif #if MAX_TB_SIZE_SIGNALLING const unsigned mtsLog2 = (unsigned)g_aucLog2[std::min (cs.sps->getMaxTbSize(), pcv.maxCUWidth)]; #else diff --git a/source/Lib/EncoderLib/EncSlice.cpp b/source/Lib/EncoderLib/EncSlice.cpp index 2eb1d3725..dca7ba1ed 100644 --- a/source/Lib/EncoderLib/EncSlice.cpp +++ b/source/Lib/EncoderLib/EncSlice.cpp @@ -1042,7 +1042,9 @@ static bool applyQPAdaptation (Picture* const pcPic, Slice* const pcSlice, pcPic->m_iOffsetCtu[ctuRsAddr] = (Pel)iQPAdapt; // adapted QPs -#if ENABLE_QPA_SUB_CTU +#if ENABLE_QPA_SUB_CTU && JVET_M0113_M0188_QG_SIZE + if (pcv.widthInCtus > 1 && pcSlice->getPPS()->getCuQpDeltaSubdiv() == 0) // reduce local DQP rate peaks +#elif ENABLE_QPA_SUB_CTU if (pcv.widthInCtus > 1 && pcSlice->getPPS()->getMaxCuDQPDepth() == 0) // reduce local DQP rate peaks #else if (pcv.widthInCtus > 1) // try to reduce local bitrate peaks via minimum smoothing of the adapted QPs @@ -1088,7 +1090,11 @@ static int applyQPAdaptationSubCtu (CodingStructure &cs, const UnitArea ctuArea, const int bitDepth = cs.slice->getSPS()->getBitDepth (CHANNEL_TYPE_LUMA); // overall image bit-depth const int adaptedCtuQP = pcPic ? pcPic->m_iOffsetCtu[ctuAddr] : cs.slice->getSliceQpBase(); +#if JVET_M0113_M0188_QG_SIZE + if (!pcPic || cs.pps->getCuQpDeltaSubdiv() == 0) return adaptedCtuQP; +#else if (!pcPic || cs.pps->getMaxCuDQPDepth() == 0) return adaptedCtuQP; +#endif for (unsigned addr = 0; addr < cs.picture->m_subCtuQP.size(); addr++) { -- GitLab