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