From 400b5e49283ff5f708b6a94f2557cdfaa919a3fe Mon Sep 17 00:00:00 2001
From: Frank Bossen <frank@bossentech.com>
Date: Fri, 4 Nov 2022 15:42:04 +0000
Subject: [PATCH] Clean up adaptive BT size related code

---
 source/Lib/CommonLib/Slice.cpp                |  4 +-
 source/Lib/CommonLib/Slice.h                  |  6 +-
 source/Lib/EncoderLib/EncGOP.cpp              | 96 ++++++++-----------
 source/Lib/EncoderLib/EncGOP.h                | 12 ++-
 source/Lib/EncoderLib/EncModeCtrl.cpp         | 11 ++-
 .../EncoderLib/EncSampleAdaptiveOffset.cpp    | 16 ++--
 source/Lib/EncoderLib/EncSlice.cpp            | 14 +--
 7 files changed, 75 insertions(+), 84 deletions(-)

diff --git a/source/Lib/CommonLib/Slice.cpp b/source/Lib/CommonLib/Slice.cpp
index 9a1f9aedc..e2c07e90c 100644
--- a/source/Lib/CommonLib/Slice.cpp
+++ b/source/Lib/CommonLib/Slice.cpp
@@ -82,7 +82,7 @@ Slice::Slice()
   , m_biDirPred(false)
   , m_lmChromaCheckDisable(false)
   , m_iSliceQpDelta(0)
-  , m_iDepth(0)
+  , m_hierPredLayerIdx(0)
   , m_pcSPS(nullptr)
   , m_pcPPS(nullptr)
   , m_pcPic(nullptr)
@@ -958,7 +958,7 @@ void Slice::copySliceInfo(Slice *pSrc, bool cpyAlmostAll)
   }
   if (cpyAlmostAll)
   {
-    m_iDepth = pSrc->m_iDepth;
+    m_hierPredLayerIdx = pSrc->m_hierPredLayerIdx;
   }
 
   // access channel
diff --git a/source/Lib/CommonLib/Slice.h b/source/Lib/CommonLib/Slice.h
index 064b232a3..44a1d4972 100644
--- a/source/Lib/CommonLib/Slice.h
+++ b/source/Lib/CommonLib/Slice.h
@@ -2744,7 +2744,7 @@ private:
   Picture*                   m_apcRefPicList [NUM_REF_PIC_LIST_01][MAX_NUM_REF+1];
   int                        m_aiRefPOCList  [NUM_REF_PIC_LIST_01][MAX_NUM_REF+1];
   bool                       m_bIsUsedAsLongTerm[NUM_REF_PIC_LIST_01][MAX_NUM_REF+1];
-  int                        m_iDepth;
+  int                        m_hierPredLayerIdx;   // hierarchical prediction layer index
   Picture*                   m_scaledRefPicList[NUM_REF_PIC_LIST_01][MAX_NUM_REF + 1];
   Picture*                   m_savedRefPicList[NUM_REF_PIC_LIST_01][MAX_NUM_REF + 1];
   std::pair<int, int>        m_scalingRatio[NUM_REF_PIC_LIST_01][MAX_NUM_REF_PICS];
@@ -2882,7 +2882,7 @@ public:
   const Picture*              getPic() const                                         { return m_pcPic;                                               }
   Picture *                   getRefPic(RefPicList e, int refIdx) const { return m_apcRefPicList[e][refIdx]; }
   int                         getRefPOC(RefPicList e, int refIdx) const { return m_aiRefPOCList[e][refIdx]; }
-  int                         getDepth() const                                       { return m_iDepth;                                              }
+  int                         getHierPredLayerIdx() const { return m_hierPredLayerIdx; }
   bool                        getColFromL0Flag() const                               { return m_colFromL0Flag;                                       }
   uint32_t                    getColRefIdx() const                                   { return m_colRefIdx;                                           }
   void                        checkColRefIdx(uint32_t curSliceSegmentIdx, const Picture* pic);
@@ -2933,7 +2933,7 @@ public:
 
   void                        setNumRefIdx( RefPicList e, int i )                    { m_aiNumRefIdx[e]    = i;                                      }
   void                        setPic( Picture* p )                                   { m_pcPic             = p;                                      }
-  void                        setDepth( int iDepth )                                 { m_iDepth            = iDepth;                                 }
+  void                        setHierPredLayerIdx(int idx) { m_hierPredLayerIdx = idx; }
 
   void                        constructRefPicList(PicList& rcListPic);
   void                        setRefPOCList();
diff --git a/source/Lib/EncoderLib/EncGOP.cpp b/source/Lib/EncoderLib/EncGOP.cpp
index 1b4de3b8a..7a1dbb29a 100644
--- a/source/Lib/EncoderLib/EncGOP.cpp
+++ b/source/Lib/EncoderLib/EncGOP.cpp
@@ -2704,33 +2704,33 @@ void EncGOP::compressGOP(int pocLast, int numPicRcvd, PicList &rcListPic, std::l
 
     xPicInitHashME( pcPic, pcSlice->getPPS(), rcListPic );
 
-    if( m_pcCfg->getUseAMaxBT() )
+    if (m_pcCfg->getUseAMaxBT())
     {
+      const SliceType sliceType = pcSlice->getSliceType();
+      const SPS      *sps       = pcSlice->getSPS();
+
       if (!pcSlice->isIRAP())
       {
-        int refLayer = pcSlice->getDepth();
-        if (refLayer > 9)
-        {
-          refLayer = 9;   // Max layer is 10
-        }
+        const int hierPredLayerIdx = std::min<int>(pcSlice->getHierPredLayerIdx(), (int) m_blkStat.size() - 1);
 
         if (m_initAMaxBt && pcSlice->getPOC() > m_prevISlicePoc)
         {
-          m_blkSize.fill(0);
-          m_numBlks.fill(0);
+          m_blkStat.fill({ 0, 0 });
           m_initAMaxBt = false;
         }
 
-        if (refLayer >= 0 && m_numBlks[refLayer] != 0)
+        if (hierPredLayerIdx >= 0 && m_blkStat[hierPredLayerIdx].count != 0)
         {
           picHeader->setSplitConsOverrideFlag(true);
-          double       dBlkSize     = sqrt((double) m_blkSize[refLayer] / m_numBlks[refLayer]);
-          unsigned int newMaxBtSize = picHeader->getMaxBTSize(pcSlice->getSliceType(), CHANNEL_TYPE_LUMA);
-          if( dBlkSize < AMAXBT_TH32 )
+
+          const double avgBlkSize = (double) m_blkStat[hierPredLayerIdx].area / m_blkStat[hierPredLayerIdx].count;
+
+          unsigned newMaxBtSize;
+          if (avgBlkSize < AMAXBT_TH32 * AMAXBT_TH32)
           {
             newMaxBtSize = 32;
           }
-          else if( dBlkSize < AMAXBT_TH64 )
+          else if (avgBlkSize < AMAXBT_TH64 * AMAXBT_TH64)
           {
             newMaxBtSize = 64;
           }
@@ -2738,64 +2738,51 @@ void EncGOP::compressGOP(int pocLast, int numPicRcvd, PicList &rcListPic, std::l
           {
             newMaxBtSize = 128;
           }
-          newMaxBtSize = Clip3(picHeader->getMinQTSize(pcSlice->getSliceType()), pcPic->cs->sps->getCTUSize(), newMaxBtSize);
+          newMaxBtSize = Clip3(picHeader->getMinQTSize(sliceType), sps->getCTUSize(), newMaxBtSize);
           picHeader->setMaxBTSize(1, newMaxBtSize);
 
-          m_blkSize[refLayer] = 0;
-          m_numBlks[refLayer] = 0;
+          m_blkStat[hierPredLayerIdx] = { 0, 0 };
         }
       }
       else
       {
         if (m_initAMaxBt)
         {
-          m_blkSize.fill(0);
-          m_numBlks.fill(0);
+          m_blkStat.fill({ 0, 0 });
         }
 
         m_prevISlicePoc = pcSlice->getPOC();
         m_initAMaxBt    = true;
       }
-      bool identicalToSPS=true;
-      const SPS* sps =pcSlice->getSPS();
 
-      if (picHeader->getPicInterSliceAllowedFlag())
+      bool identicalToSps = true;
+
+      if (identicalToSps && picHeader->getPicInterSliceAllowedFlag())
       {
-        if (picHeader->getMinQTSize(pcSlice->getSliceType()) != pcSlice->getSPS()->getMinQTSize(pcSlice->getSliceType()) ||
-            picHeader->getMaxMTTHierarchyDepth(pcSlice->getSliceType()) != pcSlice->getSPS()->getMaxMTTHierarchyDepth() ||
-            picHeader->getMaxBTSize(pcSlice->getSliceType()) != pcSlice->getSPS()->getMaxBTSize() ||
-            picHeader->getMaxTTSize(pcSlice->getSliceType()) != pcSlice->getSPS()->getMaxTTSize()
-          )
-        {
-          identicalToSPS=false;
-        }
+        identicalToSps = picHeader->getMinQTSize(sliceType) == sps->getMinQTSize(sliceType)
+                         && picHeader->getMaxMTTHierarchyDepth(sliceType) == sps->getMaxMTTHierarchyDepth()
+                         && picHeader->getMaxBTSize(sliceType) == sps->getMaxBTSize()
+                         && picHeader->getMaxTTSize(sliceType) == sps->getMaxTTSize();
       }
 
-      if (identicalToSPS && picHeader->getPicIntraSliceAllowedFlag())
+      if (identicalToSps && picHeader->getPicIntraSliceAllowedFlag())
       {
-        if (picHeader->getMinQTSize(I_SLICE) != sps->getMinQTSize(I_SLICE) ||
-            picHeader->getMaxMTTHierarchyDepth(I_SLICE) != sps->getMaxMTTHierarchyDepthI() ||
-            picHeader->getMaxBTSize(I_SLICE) != sps->getMaxBTSizeI() ||
-            picHeader->getMaxTTSize(I_SLICE) != sps->getMaxTTSizeI()
-        )
-        {
-          identicalToSPS=false;
-        }
+        identicalToSps = picHeader->getMinQTSize(I_SLICE) == sps->getMinQTSize(I_SLICE)
+                         && picHeader->getMaxMTTHierarchyDepth(I_SLICE) == sps->getMaxMTTHierarchyDepthI()
+                         && picHeader->getMaxBTSize(I_SLICE) == sps->getMaxBTSizeI()
+                         && picHeader->getMaxTTSize(I_SLICE) == sps->getMaxTTSizeI();
 
-        if (identicalToSPS && sps->getUseDualITree())
+        if (identicalToSps && sps->getUseDualITree())
         {
-          if (picHeader->getMinQTSize(I_SLICE, CHANNEL_TYPE_CHROMA) != sps->getMinQTSize(I_SLICE, CHANNEL_TYPE_CHROMA) ||
-              picHeader->getMaxMTTHierarchyDepth(I_SLICE, CHANNEL_TYPE_CHROMA) != sps->getMaxMTTHierarchyDepthIChroma() ||
-              picHeader->getMaxBTSize(I_SLICE, CHANNEL_TYPE_CHROMA) != sps->getMaxBTSizeIChroma() ||
-              picHeader->getMaxTTSize(I_SLICE, CHANNEL_TYPE_CHROMA) != sps->getMaxTTSizeIChroma()
-           )
-          {
-            identicalToSPS=false;
-          }
+          identicalToSps =
+            picHeader->getMinQTSize(I_SLICE, CHANNEL_TYPE_CHROMA) == sps->getMinQTSize(I_SLICE, CHANNEL_TYPE_CHROMA)
+            && picHeader->getMaxMTTHierarchyDepth(I_SLICE, CHANNEL_TYPE_CHROMA) == sps->getMaxMTTHierarchyDepthIChroma()
+            && picHeader->getMaxBTSize(I_SLICE, CHANNEL_TYPE_CHROMA) == sps->getMaxBTSizeIChroma()
+            && picHeader->getMaxTTSize(I_SLICE, CHANNEL_TYPE_CHROMA) == sps->getMaxTTSizeIChroma();
         }
       }
 
-      if (identicalToSPS)
+      if (identicalToSps)
       {
         picHeader->setSplitConsOverrideFlag(false);
       }
@@ -3654,15 +3641,14 @@ void EncGOP::compressGOP(int pocLast, int numPicRcvd, PicList &rcListPic, std::l
 
     pcSlice->freeScaledRefPicList( scaledRefPic );
 
-    if( m_pcCfg->getUseAMaxBT() )
+    if (m_pcCfg->getUseAMaxBT() && !pcSlice->isIntra())
     {
-      for( const CodingUnit *cu : pcPic->cs->cus )
+      const int hierPredLayerIdx = std::min<int>(pcSlice->getHierPredLayerIdx(), (int) m_blkStat.size() - 1);
+
+      for (const CodingUnit *cu: pcPic->cs->cus)
       {
-        if( !pcSlice->isIntra() )
-        {
-          m_blkSize[pcSlice->getDepth()] += cu->Y().area();
-          m_numBlks[pcSlice->getDepth()]++;
-        }
+        m_blkStat[hierPredLayerIdx].area += cu->Y().area();
+        m_blkStat[hierPredLayerIdx].count++;
       }
     }
 
diff --git a/source/Lib/EncoderLib/EncGOP.h b/source/Lib/EncoderLib/EncGOP.h
index 89ad652e1..3ddf1258c 100644
--- a/source/Lib/EncoderLib/EncGOP.h
+++ b/source/Lib/EncoderLib/EncGOP.h
@@ -185,10 +185,14 @@ private:
   int                     m_DBParam[MAX_ENCODER_DEBLOCKING_QUALITY_LAYERS][4];   //[layer_id][0: available; 1: bDBDisabled; 2: Beta Offset Div2; 3: Tc Offset Div2;]
 
   // members needed for adaptive max BT size
-  std::array<uint32_t, 8> m_blkSize;
-  std::array<uint32_t, 8> m_numBlks;
-  uint32_t                m_prevISlicePoc;
-  bool                    m_initAMaxBt;
+  struct BlkStat
+  {
+    uint32_t area;
+    uint32_t count;
+  };
+  std::array<BlkStat, 8> m_blkStat;
+  uint32_t               m_prevISlicePoc;
+  bool                   m_initAMaxBt;
 
   AUWriterIf*             m_AUWriterIf;
 #if GDR_ENABLED
diff --git a/source/Lib/EncoderLib/EncModeCtrl.cpp b/source/Lib/EncoderLib/EncModeCtrl.cpp
index 2b1181701..128e18eea 100644
--- a/source/Lib/EncoderLib/EncModeCtrl.cpp
+++ b/source/Lib/EncoderLib/EncModeCtrl.cpp
@@ -1103,11 +1103,12 @@ void EncModeCtrlMTnoRQT::initCULevel( Partitioner &partitioner, const CodingStru
   const CodingUnit* cuLeft  = cs.getCU( cs.area.blocks[partitioner.chType].pos().offset( -1, 0 ), partitioner.chType );
   const CodingUnit* cuAbove = cs.getCU( cs.area.blocks[partitioner.chType].pos().offset( 0, -1 ), partitioner.chType );
 
-  const bool qtBeforeBt = ( (  cuLeft  &&  cuAbove  && cuLeft ->qtDepth > partitioner.currQtDepth && cuAbove->qtDepth > partitioner.currQtDepth )
-                         || (  cuLeft  && !cuAbove  && cuLeft ->qtDepth > partitioner.currQtDepth )
-                         || ( !cuLeft  &&  cuAbove  && cuAbove->qtDepth > partitioner.currQtDepth )
-                         || ( !cuAbove && !cuLeft   && cs.area.lwidth() >= ( 32 << cs.slice->getDepth() ) ) )
-                         && ( cs.area.lwidth() > ( cs.pcv->getMinQtSize( *cs.slice, partitioner.chType ) << 1 ) );
+  const bool qtBeforeBt =
+    ((cuLeft && cuAbove && cuLeft->qtDepth > partitioner.currQtDepth && cuAbove->qtDepth > partitioner.currQtDepth)
+     || (cuLeft && !cuAbove && cuLeft->qtDepth > partitioner.currQtDepth)
+     || (!cuLeft && cuAbove && cuAbove->qtDepth > partitioner.currQtDepth)
+     || (!cuAbove && !cuLeft && cs.area.lwidth() >= (32 << cs.slice->getHierPredLayerIdx())))
+    && (cs.area.lwidth() > (cs.pcv->getMinQtSize(*cs.slice, partitioner.chType) << 1));
 
   // set features
   ComprCUCtx &cuECtx  = m_ComprCUCtxList.back();
diff --git a/source/Lib/EncoderLib/EncSampleAdaptiveOffset.cpp b/source/Lib/EncoderLib/EncSampleAdaptiveOffset.cpp
index 42a5fca38..717c6ad2e 100644
--- a/source/Lib/EncoderLib/EncSampleAdaptiveOffset.cpp
+++ b/source/Lib/EncoderLib/EncSampleAdaptiveOffset.cpp
@@ -356,7 +356,7 @@ void EncSampleAdaptiveOffset::decidePicParams(const Slice& slice, bool* sliceEna
     }
   }
 
-  const int picTempLayer = slice.getDepth();
+  const int hierPredLayerIdx = slice.getHierPredLayerIdx();
 
   //decide sliceEnabled[compIdx]
   const int numberOfComponents = m_numberOfComponents;
@@ -375,8 +375,9 @@ void EncSampleAdaptiveOffset::decidePicParams(const Slice& slice, bool* sliceEna
       if (saoEncodingRateChroma>0.0)
       {
         // decide slice-level on/off based on previous results
-        if( (picTempLayer > 0)
-          && (m_saoDisabledRate[compIdx][picTempLayer-1] > ((compIdx==COMPONENT_Y) ? saoEncodingRate : saoEncodingRateChroma)) )
+        if (hierPredLayerIdx > 0
+            && (m_saoDisabledRate[compIdx][hierPredLayerIdx - 1]
+                > ((compIdx == COMPONENT_Y) ? saoEncodingRate : saoEncodingRateChroma)))
         {
           sliceEnabled[compIdx] = false;
         }
@@ -384,8 +385,7 @@ void EncSampleAdaptiveOffset::decidePicParams(const Slice& slice, bool* sliceEna
       else
       {
         // decide slice-level on/off based on previous results
-        if( (picTempLayer > 0)
-          && (m_saoDisabledRate[COMPONENT_Y][0] > saoEncodingRate) )
+        if (hierPredLayerIdx > 0 && (m_saoDisabledRate[COMPONENT_Y][0] > saoEncodingRate))
         {
           sliceEnabled[compIdx] = false;
         }
@@ -1103,7 +1103,7 @@ void EncSampleAdaptiveOffset::disabledRate( CodingStructure& cs, SAOBlkParam* re
   {
     const PreCalcValues& pcv = *cs.pcv;
     const uint32_t numberOfComponents = getNumberValidComponents( cs.picture->chromaFormat );
-    int picTempLayer = cs.slice->getDepth();
+    const int            hierPredLayerIdx   = cs.slice->getHierPredLayerIdx();
     int numCtusForSAOOff[MAX_NUM_COMPONENT];
 
     for (int compIdx = 0; compIdx < numberOfComponents; compIdx++)
@@ -1121,10 +1121,10 @@ void EncSampleAdaptiveOffset::disabledRate( CodingStructure& cs, SAOBlkParam* re
     {
       for (int compIdx = 0; compIdx < numberOfComponents; compIdx++)
       {
-        m_saoDisabledRate[compIdx][picTempLayer] = (double)numCtusForSAOOff[compIdx]/(double)pcv.sizeInCtus;
+        m_saoDisabledRate[compIdx][hierPredLayerIdx] = (double) numCtusForSAOOff[compIdx] / (double) pcv.sizeInCtus;
       }
     }
-    else if (picTempLayer == 0)
+    else if (hierPredLayerIdx == 0)
     {
       m_saoDisabledRate[COMPONENT_Y][0] = (double)(numCtusForSAOOff[COMPONENT_Y]+numCtusForSAOOff[COMPONENT_Cb]+numCtusForSAOOff[COMPONENT_Cr])/(double)(pcv.sizeInCtus *3);
     }
diff --git a/source/Lib/EncoderLib/EncSlice.cpp b/source/Lib/EncoderLib/EncSlice.cpp
index 62fdc3322..af6750f0e 100644
--- a/source/Lib/EncoderLib/EncSlice.cpp
+++ b/source/Lib/EncoderLib/EncSlice.cpp
@@ -382,7 +382,7 @@ void EncSlice::initEncSlice(Picture *pcPic, const int pocLast, const int pocCurr
 #endif
 
   // depth computation based on GOP size
-  int depth;
+  int hierPredLayerIdx;
   {
     int poc = rpcSlice->getPOC();
     if(isField)
@@ -396,12 +396,12 @@ void EncSlice::initEncSlice(Picture *pcPic, const int pocLast, const int pocCurr
 
     if ( poc == 0 )
     {
-      depth = 0;
+      hierPredLayerIdx = 0;
     }
     else
     {
       int step = m_pcCfg->getGOPSize() * multipleFactor;
-      depth    = 0;
+      hierPredLayerIdx = 0;
       for( int i=step>>1; i>=1; i>>=1 )
       {
         for (int j = i; j<(m_pcCfg->getGOPSize() * multipleFactor); j += step)
@@ -413,7 +413,7 @@ void EncSlice::initEncSlice(Picture *pcPic, const int pocLast, const int pocCurr
           }
         }
         step >>= 1;
-        depth++;
+        hierPredLayerIdx++;
       }
     }
 
@@ -421,7 +421,7 @@ void EncSlice::initEncSlice(Picture *pcPic, const int pocLast, const int pocCurr
     {
       if (isField && ((rpcSlice->getPOC() % 2) == 1))
       {
-        depth++;
+        hierPredLayerIdx++;
       }
     }
   }
@@ -462,7 +462,7 @@ void EncSlice::initEncSlice(Picture *pcPic, const int pocLast, const int pocCurr
     eSliceType = (pocLast == 0 || pocCurr == 0 || m_pcGOPEncoder->getGOPSize() == 0) ? I_SLICE : eSliceType;
   }
 
-  rpcSlice->setDepth        ( depth );
+  rpcSlice->setHierPredLayerIdx(hierPredLayerIdx);
   rpcSlice->setSliceType    ( eSliceType );
 
   // ------------------------------------------------------------------------------------------------------------------
@@ -870,7 +870,7 @@ double EncSlice::initializeLambda(const Slice* slice, const int GOPid, const int
 
   dLambda = dQPFactor * pow(2.0, (dQP + bitDepthShift) / 3.0);
 
-  if (slice->getDepth() > 0 && !m_pcCfg->getLambdaFromQPEnable())
+  if (slice->getHierPredLayerIdx() > 0 && !m_pcCfg->getLambdaFromQPEnable())
   {
     dLambda *= Clip3(2.0, 4.0, ((refQP + bitDepthShift) / 6.0));
   }
-- 
GitLab