From 25e0d1ad1483990164f7034be923c6e1d1e21a35 Mon Sep 17 00:00:00 2001
From: Tangi Poirier <tangi.poirier@interdigital.com>
Date: Tue, 7 Dec 2021 02:38:57 +0000
Subject: [PATCH] Add check of reference frame structure to detect low delay
 configuration

---
 source/App/EncoderApp/EncApp.cpp      |  1 +
 source/App/EncoderApp/EncAppCfg.cpp   |  4 ++++
 source/App/EncoderApp/EncAppCfg.h     |  1 +
 source/Lib/EncoderLib/EncCfg.h        |  4 ++++
 source/Lib/EncoderLib/EncCu.cpp       |  4 ++--
 source/Lib/EncoderLib/EncLib.cpp      | 11 ++++++-----
 source/Lib/EncoderLib/EncSlice.cpp    |  2 +-
 source/Lib/EncoderLib/InterSearch.cpp |  4 ++--
 8 files changed, 21 insertions(+), 10 deletions(-)

diff --git a/source/App/EncoderApp/EncApp.cpp b/source/App/EncoderApp/EncApp.cpp
index eb4ea5113..fd349f1bf 100644
--- a/source/App/EncoderApp/EncApp.cpp
+++ b/source/App/EncoderApp/EncApp.cpp
@@ -597,6 +597,7 @@ void EncApp::xInitLibCfg()
   m_cEncLib.setEnablePictureHeaderInSliceHeader                  ( m_enablePictureHeaderInSliceHeader );
 
   m_cEncLib.setMaxTempLayer                                      ( m_maxTempLayer );
+  m_cEncLib.setIsLowDelay                                        ( m_isLowDelay );
 
   //===== Slice ========
 
diff --git a/source/App/EncoderApp/EncAppCfg.cpp b/source/App/EncoderApp/EncAppCfg.cpp
index 8f7e8e384..4eaba3123 100644
--- a/source/App/EncoderApp/EncAppCfg.cpp
+++ b/source/App/EncoderApp/EncAppCfg.cpp
@@ -3529,6 +3529,7 @@ bool EncAppCfg::xCheckParameter()
   xConfirmPara( m_fastLocalDualTreeMode < 0 || m_fastLocalDualTreeMode > 2, "FastLocalDualTreeMode must be in range [0..2]" );
 
   int extraRPLs = 0;
+  bool hasFutureRef = false;
   //start looping through frames in coding order until we can verify that the GOP structure is correct.
   while (!verifiedGOP && !errorGOP)
   {
@@ -3738,6 +3739,7 @@ bool EncAppCfg::xCheckParameter()
       for (int i = 0; i< m_RPLList0[curGOP].m_numRefPics; i++)
       {
         int absPOC = curPOC - m_RPLList0[curGOP].m_deltaRefPics[i];
+        hasFutureRef |= (m_RPLList0[curGOP].m_deltaRefPics[i] < 0);
         if (absPOC >= 0)
         {
           refList[numRefs] = absPOC;
@@ -3747,6 +3749,7 @@ bool EncAppCfg::xCheckParameter()
       for (int i = 0; i< m_RPLList1[curGOP].m_numRefPics; i++)
       {
         int absPOC = curPOC - m_RPLList1[curGOP].m_deltaRefPics[i];
+        hasFutureRef |= (m_RPLList1[curGOP].m_deltaRefPics[i] < 0);
         if (absPOC >= 0)
         {
           bool alreadyExist = false;
@@ -3769,6 +3772,7 @@ bool EncAppCfg::xCheckParameter()
     }
     checkGOP++;
   }
+  m_isLowDelay = !hasFutureRef && m_iIntraPeriod != 1;
   xConfirmPara(errorGOP, "Invalid GOP structure given");
 
   m_maxTempLayer = 1;
diff --git a/source/App/EncoderApp/EncAppCfg.h b/source/App/EncoderApp/EncAppCfg.h
index a52f68234..90725a554 100644
--- a/source/App/EncoderApp/EncAppCfg.h
+++ b/source/App/EncoderApp/EncAppCfg.h
@@ -317,6 +317,7 @@ protected:
   bool      m_bUseWPSNR;                                      ///< Flag to output perceptually weighted peak SNR (WPSNR) instead of PSNR
 #endif
   int       m_maxTempLayer;                                   ///< Max temporal layer
+  bool      m_isLowDelay;
 
   // coding unit (CU) definition
   unsigned  m_uiCTUSize;
diff --git a/source/Lib/EncoderLib/EncCfg.h b/source/Lib/EncoderLib/EncCfg.h
index 2d6adad24..948b3791a 100644
--- a/source/Lib/EncoderLib/EncCfg.h
+++ b/source/Lib/EncoderLib/EncCfg.h
@@ -299,6 +299,7 @@ protected:
                                                  // TODO: We need to have a common sliding mechanism used by both the encoder and decoder
 
   int       m_maxTempLayer;                      ///< Max temporal layer
+  bool      m_isLowDelay;
   unsigned  m_CTUSize;
   bool                  m_subPicInfoPresentFlag;
   uint32_t              m_numSubPics;
@@ -1127,6 +1128,9 @@ public:
   int       getMaxTempLayer                 ()                              { return m_maxTempLayer;              }
   void      setMaxTempLayer                 ( int maxTempLayer )            { m_maxTempLayer = maxTempLayer;      }
 
+  bool      getIsLowDelay                   ()                              { return m_isLowDelay;       }
+  void      setIsLowDelay                   ( bool isLowDelay )             { m_isLowDelay = isLowDelay; }
+
   void      setCTUSize                      ( unsigned  u )      { m_CTUSize  = u; }
   void      setMinQTSizes                   ( unsigned* minQT)   { m_uiMinQT[0] = minQT[0]; m_uiMinQT[1] = minQT[1]; m_uiMinQT[2] = minQT[2]; }
   void      setMaxBTSizes                   ( unsigned* maxBT)   { m_uiMaxBT[0] = maxBT[0]; m_uiMaxBT[1] = maxBT[1]; m_uiMaxBT[2] = maxBT[2]; }
diff --git a/source/Lib/EncoderLib/EncCu.cpp b/source/Lib/EncoderLib/EncCu.cpp
index 2bd9df9e6..32265733b 100644
--- a/source/Lib/EncoderLib/EncCu.cpp
+++ b/source/Lib/EncoderLib/EncCu.cpp
@@ -4243,7 +4243,7 @@ void EncCu::xCheckRDCostInter( CodingStructure *&tempCS, CodingStructure *&bestC
 
     if (m_pcEncCfg->getUseBcwFast())
     {
-      if (isEqualUni == true && m_pcEncCfg->getIntraPeriod() == -1)
+      if (isEqualUni == true && m_pcEncCfg->getIsLowDelay())
       {
         break;
       }
@@ -4498,7 +4498,7 @@ bool EncCu::xCheckRDCostInterIMV(CodingStructure *&tempCS, CodingStructure *&bes
 
   if( m_pcEncCfg->getUseBcwFast() )
   {
-    if( isEqualUni == true && m_pcEncCfg->getIntraPeriod() == -1 )
+    if( isEqualUni == true && m_pcEncCfg->getIsLowDelay())
     {
       break;
     }
diff --git a/source/Lib/EncoderLib/EncLib.cpp b/source/Lib/EncoderLib/EncLib.cpp
index fa906fcec..76ab64ae4 100644
--- a/source/Lib/EncoderLib/EncLib.cpp
+++ b/source/Lib/EncoderLib/EncLib.cpp
@@ -2019,7 +2019,7 @@ void EncLib::xInitRPL(SPS &sps)
 
 void EncLib::getActiveRefPicListNumForPOC(const SPS *sps, int POCCurr, int GOPid, uint32_t *activeL0, uint32_t *activeL1)
 {
-  if (m_intraPeriod < 0)  //Only for RA
+  if (m_isLowDelay)  //Only for RA
   {
     *activeL0 = *activeL1 = 0;
     return;
@@ -2030,7 +2030,7 @@ void EncLib::getActiveRefPicListNumForPOC(const SPS *sps, int POCCurr, int GOPid
   int fullListNum = m_iGOPSize;
   int partialListNum = getRPLCandidateSize(0) - m_iGOPSize;
   int extraNum = fullListNum;
-  if (m_intraPeriod < 0)
+  if (m_isLowDelay)
   {
     if (POCCurr < (2 * m_iGOPSize + 2))
     {
@@ -2093,11 +2093,12 @@ void EncLib::selectReferencePictureList(Slice* slice, int POCCurr, int GOPid, in
     }
   }
 
-  if (rplPeriod < 0)
+  if (m_isLowDelay)
   {
-    if (POCCurr < (2 * m_iGOPSize + 2))
+    const int currPOCsinceLastIDR = POCCurr - slice->getLastIDR();
+    if (currPOCsinceLastIDR < (2 * m_iGOPSize + 2))
     {
-      int candidateIdx = (POCCurr + m_iGOPSize - 1 >= fullListNum + partialListNum) ? GOPid : POCCurr + m_iGOPSize - 1;
+      int candidateIdx = (currPOCsinceLastIDR + m_iGOPSize - 1 >= fullListNum + partialListNum) ? GOPid : currPOCsinceLastIDR + m_iGOPSize - 1;
       slice->setRPL0idx(candidateIdx);
       slice->setRPL1idx(candidateIdx);
     }
diff --git a/source/Lib/EncoderLib/EncSlice.cpp b/source/Lib/EncoderLib/EncSlice.cpp
index 8c0560d07..3cc7f917d 100644
--- a/source/Lib/EncoderLib/EncSlice.cpp
+++ b/source/Lib/EncoderLib/EncSlice.cpp
@@ -1684,7 +1684,7 @@ void EncSlice::encodeCtus( Picture* pcPic, const bool bCompressEntireSlice, cons
       (pcSlice->getSPS()->getIBCFlag() && m_pcCuEncoder->getEncCfg()->getIBCHashSearch()))
   {
     m_pcCuEncoder->getIbcHashMap().rebuildPicHashMap(cs.picture->getTrueOrigBuf());
-    if (m_pcCfg->getIntraPeriod() != -1)
+    if (!m_pcCfg->getIsLowDelay())
     {
       int hashBlkHitPerc = m_pcCuEncoder->getIbcHashMap().calHashBlkMatchPerc(cs.area.Y());
       cs.slice->setDisableSATDForRD(hashBlkHitPerc > 59);
diff --git a/source/Lib/EncoderLib/InterSearch.cpp b/source/Lib/EncoderLib/InterSearch.cpp
index 039078e9e..80feb43aa 100644
--- a/source/Lib/EncoderLib/InterSearch.cpp
+++ b/source/Lib/EncoderLib/InterSearch.cpp
@@ -265,7 +265,7 @@ void InterSearch::init( EncCfg*        pcEncCfg,
   m_tmpAffiDeri[0] = new int[MAX_CU_SIZE * MAX_CU_SIZE];
   m_tmpAffiDeri[1] = new int[MAX_CU_SIZE * MAX_CU_SIZE];
   m_pTempPel = new Pel[maxCUWidth*maxCUHeight];
-  m_affMVListMaxSize = (pcEncCfg->getIntraPeriod() == (uint32_t)-1) ? AFFINE_ME_LIST_SIZE_LD : AFFINE_ME_LIST_SIZE;
+  m_affMVListMaxSize = pcEncCfg->getIsLowDelay() ? AFFINE_ME_LIST_SIZE_LD : AFFINE_ME_LIST_SIZE;
   if (!m_affMVList)
   {
     m_affMVList = new AffineMVInfo[m_affMVListMaxSize];
@@ -8702,7 +8702,7 @@ void InterSearch::xAffineMotionEstimation( PredictionUnit& pu,
 
     // 8 nearest neighbor search
     int testPos[8][2] = { { -1, 0 },{ 0, -1 },{ 0, 1 },{ 1, 0 },{ -1, -1 },{ -1, 1 },{ 1, 1 },{ 1, -1 } };
-    const int maxSearchRound = (pu.cu->imv) ? 3 : ((m_pcEncCfg->getUseAffineAmvrEncOpt() && m_pcEncCfg->getIntraPeriod() == (uint32_t)-1) ? 2 : 3);
+    const int maxSearchRound = (pu.cu->imv) ? 3 : ((m_pcEncCfg->getUseAffineAmvrEncOpt() && m_pcEncCfg->getIsLowDelay()) ? 2 : 3);
 
     for (int rnd = 0; rnd < maxSearchRound; rnd++)
     {
-- 
GitLab