From 859c574bcacfac4cf0f099402a69341667981a93 Mon Sep 17 00:00:00 2001
From: Shelly Chiang <chiangshelly@yahoo.com.tw>
Date: Tue, 30 Oct 2018 10:14:03 +0800
Subject: [PATCH] update the codebase

---
 source/Lib/CommonLib/UnitTools.h      |  22 +++
 source/Lib/DecoderLib/CABACReader.cpp |   7 +
 source/Lib/DecoderLib/DecCu.cpp       |   3 +
 source/Lib/EncoderLib/CABACWriter.cpp |   7 +
 source/Lib/EncoderLib/EncCu.cpp       | 270 +++++++++++++++-----------
 source/Lib/EncoderLib/EncCu.h         |   7 +-
 6 files changed, 204 insertions(+), 112 deletions(-)

diff --git a/source/Lib/CommonLib/UnitTools.h b/source/Lib/CommonLib/UnitTools.h
index 6832771d5..c10c682fd 100644
--- a/source/Lib/CommonLib/UnitTools.h
+++ b/source/Lib/CommonLib/UnitTools.h
@@ -259,7 +259,11 @@ uint32_t updateCandList( T uiMode, double uiCost, static_vector<T, N>& candModeL
 
 #if JVET_L0100_MULTI_HYPOTHESIS_INTRA
 template<typename T, size_t N>
+#if JVET_L0054_MMVD
+uint32_t updateDoubleCandList(T mode, double cost, static_vector<T, N>& candModeList, static_vector<double, N>& candCostList, static_vector<T, N>& candModeList2, T mode2, size_t fastCandNum = N, int* iserttPos = nullptr)
+#else
 uint32_t updateDoubleCandList(T mode, double cost, static_vector<T, N>& candModeList, static_vector<double, N>& candCostList, static_vector<T, N>& candModeList2, T mode2, size_t fastCandNum = N)
+#endif
 {
   CHECK(std::min(fastCandNum, candModeList.size()) != std::min(fastCandNum, candCostList.size()), "Sizes do not match!");
   CHECK(fastCandNum > candModeList.capacity(), "The vector is to small to hold all the candidates!");
@@ -284,6 +288,12 @@ uint32_t updateDoubleCandList(T mode, double cost, static_vector<T, N>& candMode
     candModeList[currSize - shift] = mode;
     candModeList2[currSize - shift] = mode2;
     candCostList[currSize - shift] = cost;
+#if JVET_L0054_MMVD
+    if (iserttPos != nullptr)
+    {
+      *iserttPos = int(currSize - shift);
+    }
+#endif
     return 1;
   }
   else if (currSize < fastCandNum)
@@ -291,9 +301,21 @@ uint32_t updateDoubleCandList(T mode, double cost, static_vector<T, N>& candMode
     candModeList.insert(candModeList.end() - shift, mode);
     candModeList2.insert(candModeList2.end() - shift, mode2);
     candCostList.insert(candCostList.end() - shift, cost);
+#if JVET_L0054_MMVD
+    if (iserttPos != nullptr)
+    {
+      *iserttPos = int(candModeList.size() - shift - 1);
+    }
+#endif
     return 1;
   }
 
+#if JVET_L0054_MMVD
+  if (iserttPos != nullptr)
+  {
+    *iserttPos = -1;
+  }
+#endif
   return 0;
 }
 #endif
diff --git a/source/Lib/DecoderLib/CABACReader.cpp b/source/Lib/DecoderLib/CABACReader.cpp
index 18ed6a4e8..1958ba184 100644
--- a/source/Lib/DecoderLib/CABACReader.cpp
+++ b/source/Lib/DecoderLib/CABACReader.cpp
@@ -1522,6 +1522,13 @@ void CABACReader::MHIntra_flag(PredictionUnit& pu)
     return;
   }
 
+#if JVET_L0054_MMVD
+  if (pu.mmvdMergeFlag)
+  {
+    pu.MHIntraFlag = false;
+    return;
+  }
+#endif
   if (pu.cu->lwidth() * pu.cu->lheight() < 64 || pu.cu->lwidth() >= MAX_CU_SIZE || pu.cu->lheight() >= MAX_CU_SIZE)
   {
     pu.MHIntraFlag = false;
diff --git a/source/Lib/DecoderLib/DecCu.cpp b/source/Lib/DecoderLib/DecCu.cpp
index 96c56be01..084207be7 100644
--- a/source/Lib/DecoderLib/DecCu.cpp
+++ b/source/Lib/DecoderLib/DecCu.cpp
@@ -433,6 +433,9 @@ void DecCu::xDeriveCUMV( CodingUnit &cu )
 #if JVET_L0054_MMVD
       if (pu.mmvdMergeFlag || pu.cu->mmvdSkip)
       {
+#if JVET_L0100_MULTI_HYPOTHESIS_INTRA
+        CHECK(pu.MHIntraFlag == true, "invalid MHIntra");
+#endif
         if (pu.cs->sps->getSpsNext().getUseSubPuMvp())
         {
           Size bufSize = g_miScaling.scale(pu.lumaSize());
diff --git a/source/Lib/EncoderLib/CABACWriter.cpp b/source/Lib/EncoderLib/CABACWriter.cpp
index 831cfd59c..f1c044e9c 100644
--- a/source/Lib/EncoderLib/CABACWriter.cpp
+++ b/source/Lib/EncoderLib/CABACWriter.cpp
@@ -1455,6 +1455,13 @@ void CABACWriter::MHIntra_flag(const PredictionUnit& pu)
     CHECK(pu.MHIntraFlag == true, "invalid MHIntra and skip");
     return;
   }
+#if JVET_L0054_MMVD
+  if (pu.mmvdMergeFlag)
+  {
+    CHECK(pu.MHIntraFlag == true, "invalid MHIntra and mmvd");
+    return;
+  }
+#endif
   if (pu.cu->lwidth() * pu.cu->lheight() < 64 || pu.cu->lwidth() >= MAX_CU_SIZE || pu.cu->lheight() >= MAX_CU_SIZE)
   {
     CHECK(pu.MHIntraFlag == true, "invalid MHIntra and blk");
diff --git a/source/Lib/EncoderLib/EncCu.cpp b/source/Lib/EncoderLib/EncCu.cpp
index 1632d618b..175824884 100644
--- a/source/Lib/EncoderLib/EncCu.cpp
+++ b/source/Lib/EncoderLib/EncCu.cpp
@@ -191,6 +191,12 @@ void EncCu::create( EncCfg* encCfg )
   {
     m_acMergeBuffer[ui].create( chromaFormat, Area( 0, 0, uiMaxWidth, uiMaxHeight ) );
   }
+#if JVET_L0100_MULTI_HYPOTHESIS_INTRA
+  for (unsigned ui = 0; ui < MRG_MAX_NUM_CANDS; ui++)
+  {
+    m_acRealMergeBuffer[ui].create(chromaFormat, Area(0, 0, uiMaxWidth, uiMaxHeight));
+  }
+#endif
 
   m_CtxBuffer.resize( maxDepth );
   m_CurrCtx = 0;
@@ -284,6 +290,9 @@ void EncCu::destroy()
   for( unsigned ui = 0; ui < MRG_MAX_NUM_CANDS; ui++ )
   {
     m_acMergeBuffer[ui].destroy();
+#if JVET_L0100_MULTI_HYPOTHESIS_INTRA
+    m_acRealMergeBuffer[ui].destroy();
+#endif
   }
 }
 
@@ -1616,6 +1625,9 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
 
   bool                                        bestIsSkip = false;
   bool                                        bestIsMMVDSkip = true;
+#if JVET_L0100_MULTI_HYPOTHESIS_INTRA
+  PelUnitBuf                                  acMergeBuffer[MRG_MAX_NUM_CANDS];
+#endif
   PelUnitBuf                                  acMergeRealBuffer[MMVD_MRG_MAX_RD_BUF_NUM];
   PelUnitBuf *                                acMergeTempBuffer[MMVD_MRG_MAX_RD_NUM];
   PelUnitBuf *                                singleMergeTempBuffer;
@@ -1667,18 +1679,17 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
 #endif
 
 #if JVET_L0100_MULTI_HYPOTHESIS_INTRA
+#if JVET_L0054_MMVD
+  static_vector<unsigned, MRG_MAX_NUM_CANDS + MMVD_ADD_NUM>  RdModeList2; // store the Intra mode for Intrainter
+#else
   static_vector<unsigned, MRG_MAX_NUM_CANDS>  RdModeList2; // store the Intra mode for Intrainter
+#endif
   RdModeList2.clear();
   bool isIntrainterEnabled = sps.getSpsNext().getUseMHIntra();
   if (bestCS->area.lwidth() * bestCS->area.lheight() < 64 || bestCS->area.lwidth() >= MAX_CU_SIZE || bestCS->area.lheight() >= MAX_CU_SIZE)
   {
     isIntrainterEnabled = false;
   }
-  bool isTestSkipMerge[MRG_MAX_NUM_CANDS]; // record if the merge candidate has tried skip mode 
-  for (uint32_t uiMerge = 0; uiMerge < MRG_MAX_NUM_CANDS; uiMerge++)
-  {
-    isTestSkipMerge[uiMerge] = false;
-  }
 #endif
 #if JVET_L0100_MULTI_HYPOTHESIS_INTRA
   if( m_pcEncCfg->getUseFastMerge() || isIntrainterEnabled)
@@ -1717,7 +1728,11 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
 #endif
 
 #if JVET_L0100_MULTI_HYPOTHESIS_INTRA
+#if JVET_L0054_MMVD
+    for (uint32_t idx = 0; idx < MRG_MAX_NUM_CANDS + MMVD_ADD_NUM; idx++)
+#else
     for (uint32_t idx = 0; idx < MRG_MAX_NUM_CANDS; idx++)
+#endif
     {
       candCostList[idx] = MAX_DOUBLE;
     }
@@ -1770,6 +1785,10 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
 #if JVET_L0054_MMVD
         distParam.cur = singleMergeTempBuffer->Y();
         m_pcInterSearch->motionCompensation(pu, *singleMergeTempBuffer);
+#if JVET_L0100_MULTI_HYPOTHESIS_INTRA
+        acMergeBuffer[uiMergeCand] = m_acRealMergeBuffer[uiMergeCand].getBuf(localUnitArea);
+        acMergeBuffer[uiMergeCand].copyFrom(*singleMergeTempBuffer);
+#endif
 #else
         distParam.cur = acMergeBuffer[uiMergeCand].Y();
 
@@ -1796,7 +1815,11 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
         double cost     = (double)uiSad + (double)uiBitsCand * sqrtLambdaForFirstPass;
 #if JVET_L0054_MMVD
         insertPos = -1;
+#if JVET_L0100_MULTI_HYPOTHESIS_INTRA
+        updateDoubleCandList(uiMergeCand, cost, RdModeList, candCostList, RdModeList2, (uint32_t)NUM_LUMA_MODE, uiNumMrgSATDCand, &insertPos);
+#else
         updateCandList(uiMergeCand, cost, RdModeList, candCostList, uiNumMrgSATDCand, &insertPos);
+#endif
         if (insertPos != -1)
         {
           if (insertPos == RdModeList.size() - 1)
@@ -1818,6 +1841,7 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
         updateDoubleCandList(uiMergeCand, cost, RdModeList, candCostList, RdModeList2, (uint32_t)NUM_LUMA_MODE, uiNumMrgSATDCand);
 #else
         updateCandList( uiMergeCand, cost, RdModeList, candCostList, uiNumMrgSATDCand );
+#endif
 #endif
         CHECK( std::min( uiMergeCand + 1, uiNumMrgSATDCand ) != RdModeList.size(), "" );
       }
@@ -1825,7 +1849,103 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
 #if JVET_L0100_MULTI_HYPOTHESIS_INTRA
       if (isIntrainterEnabled)
       {
-        getMHIntraLCCand(pu, RdModeList, candCostList, RdModeList2, uiNumMrgSATDCand, sqrtLambdaForFirstPass, sqrtLambdaForFirstPassIntra, distParam, localUnitArea);
+        int numTestIntraMode = 4;
+        // prepare for Intra bits calculation
+        const TempCtx ctxStart(m_CtxCache, m_CABACEstimator->getCtx());
+        const TempCtx ctxStartIntraMode(m_CtxCache, SubCtx(Ctx::MHIntraPredMode, m_CABACEstimator->getCtx()));
+
+        // for Intrainter fast, recored the best intra mode during the first round for mrege 0
+        int bestMHIntraMode = -1;
+        double bestMHIntraCost = MAX_DOUBLE;
+
+        pu.MHIntraFlag = true;
+
+        // save the to-be-tested merge candidates
+        uint32_t MHIntraMergeCand[NUM_MRG_SATD_CAND];
+
+        for (uint32_t mergeCnt = 0; mergeCnt < NUM_MRG_SATD_CAND; mergeCnt++)
+        {
+          MHIntraMergeCand[mergeCnt] = RdModeList[mergeCnt];
+        }
+        for (uint32_t mergeCnt = 0; mergeCnt < std::min(NUM_MRG_SATD_CAND, 4); mergeCnt++)
+        {
+          uint32_t mergeCand = MHIntraMergeCand[mergeCnt];
+#if JVET_L0054_MMVD
+          acMergeBuffer[mergeCand] = m_acRealMergeBuffer[mergeCand].getBuf(localUnitArea);
+#else
+          acMergeBuffer[mergeCand] = m_acMergeBuffer[mergeCand].getBuf(localUnitArea);
+#endif
+
+          // estimate merge bits
+          uint32_t bitsCand = mergeCand + 1;
+          if (mergeCand == pu.cs->slice->getMaxNumMergeCand() - 1)
+          {
+            bitsCand--;
+          }
+
+          // first round
+          for (uint32_t intraCnt = 0; intraCnt < numTestIntraMode; intraCnt++)
+          {
+            pu.intraDir[0] = (intraCnt < 2) ? intraCnt : ((intraCnt == 2) ? HOR_IDX : VER_IDX);
+
+            // fast 2
+            if (mergeCnt > 0 && bestMHIntraMode != pu.intraDir[0])
+            {
+              continue;
+            }
+            int narrowCase = PU::getNarrowShape(pu.lwidth(), pu.lheight());
+            if (narrowCase == 1 && pu.intraDir[0] == HOR_IDX)
+            {
+              continue;
+            }
+            if (narrowCase == 2 && pu.intraDir[0] == VER_IDX)
+            {
+              continue;
+            }
+            // generate intrainter Y prediction
+            if (mergeCnt == 0)
+            {
+              bool isUseFilter = IntraPrediction::useFilteredIntraRefSamples(COMPONENT_Y, pu, true, pu);
+              m_pcIntraSearch->initIntraPatternChType(*pu.cu, pu.Y(), isUseFilter);
+              m_pcIntraSearch->predIntraAng(COMPONENT_Y, pu.cs->getPredBuf(pu).Y(), pu, isUseFilter);
+              m_pcIntraSearch->switchBuffer(pu, COMPONENT_Y, pu.cs->getPredBuf(pu).Y(), m_pcIntraSearch->getPredictorPtr2(COMPONENT_Y, intraCnt));
+            }
+            pu.cs->getPredBuf(pu).copyFrom(acMergeBuffer[mergeCand]);
+            m_pcIntraSearch->geneWeightedPred(COMPONENT_Y, pu.cs->getPredBuf(pu).Y(), pu, m_pcIntraSearch->getPredictorPtr2(COMPONENT_Y, intraCnt));
+
+            // calculate cost
+            distParam.cur = pu.cs->getPredBuf(pu).Y();
+            Distortion sadValue = distParam.distFunc(distParam);
+            m_CABACEstimator->getCtx() = SubCtx(Ctx::MHIntraPredMode, ctxStartIntraMode);
+            uint64_t fracModeBits = m_pcIntraSearch->xFracModeBitsIntra(pu, pu.intraDir[0], CHANNEL_TYPE_LUMA);
+            double cost = (double)sadValue + (double)(bitsCand + 1) * sqrtLambdaForFirstPass + (double)fracModeBits * sqrtLambdaForFirstPassIntra;
+            cost = MAX_DOUBLE;
+#if JVET_L0054_MMVD
+            insertPos = -1;
+            updateDoubleCandList(mergeCand + MRG_MAX_NUM_CANDS + MMVD_ADD_NUM, cost, RdModeList, candCostList, RdModeList2, pu.intraDir[0], uiNumMrgSATDCand, &insertPos);
+#else
+            updateDoubleCandList(mergeCand + MRG_MAX_NUM_CANDS + MRG_MAX_NUM_CANDS, cost, RdModeList, candCostList, RdModeList2, pu.intraDir[0], uiNumMrgSATDCand);
+#endif
+#if JVET_L0054_MMVD
+            if (insertPos != -1)
+            {
+              for (int i = int(RdModeList.size()) - 1; i > insertPos; i--)
+              {
+                swap(acMergeTempBuffer[i - 1], acMergeTempBuffer[i]);
+              }
+              swap(singleMergeTempBuffer, acMergeTempBuffer[insertPos]);
+            }
+#endif
+            // fast 2
+            if (mergeCnt == 0 && cost < bestMHIntraCost)
+            {
+              bestMHIntraMode = pu.intraDir[0];
+              bestMHIntraCost = cost;
+            }
+          }
+        }
+        pu.MHIntraFlag = false;
+        m_CABACEstimator->getCtx() = ctxStart;
       }
 #endif
 
@@ -1900,7 +2020,11 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
 #endif
 #if JVET_L0054_MMVD
         insertPos = -1;
+#if JVET_L0100_MULTI_HYPOTHESIS_INTRA
+        updateDoubleCandList(mergeCand, cost, RdModeList, candCostList, RdModeList2, (uint32_t)NUM_LUMA_MODE, uiNumMrgSATDCand, &insertPos);
+#else
         updateCandList(mergeCand, cost, RdModeList, candCostList, uiNumMrgSATDCand, &insertPos);
+#endif
         if (insertPos != -1)
         {
           for (int i = int(RdModeList.size()) - 1; i > insertPos; i--)
@@ -1933,7 +2057,11 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
         pu.MHIntraFlag = true;
         for (uint32_t mergeCnt = 0; mergeCnt < uiNumMrgSATDCand; mergeCnt++)
         {
+#if JVET_L0054_MMVD
+          if (RdModeList[mergeCnt] >= (MRG_MAX_NUM_CANDS + MMVD_ADD_NUM))
+#else
           if (RdModeList[mergeCnt] >= (MRG_MAX_NUM_CANDS + MRG_MAX_NUM_CANDS))
+#endif
           {
             pu.intraDir[0] = RdModeList2[mergeCnt];
             pu.intraDir[1] = DM_CHROMA_IDX;
@@ -1981,13 +2109,18 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
       uint32_t uiMergeCand = RdModeList[uiMrgHADIdx];
 
 #if JVET_L0100_MULTI_HYPOTHESIS_INTRA
+#if JVET_L0054_MMVD
+      if (uiNoResidualPass != 0 && uiMergeCand >= (MRG_MAX_NUM_CANDS + MMVD_ADD_NUM)) // intrainter does not support skip mode
+#else
       if (uiNoResidualPass != 0 && uiMergeCand >= (MRG_MAX_NUM_CANDS + MRG_MAX_NUM_CANDS)) // intrainter does not support skip mode
+#endif
       {
+#if JVET_L0054_MMVD
+        uiMergeCand -= (MRG_MAX_NUM_CANDS + MMVD_ADD_NUM); // for skip, map back to normal merge candidate idx and try RDO
+#else
         uiMergeCand -= (MRG_MAX_NUM_CANDS + MRG_MAX_NUM_CANDS); // for skip, map back to normal merge candidate idx and try RDO
-        if (isTestSkipMerge[uiMergeCand]) // avoid redundancy
-        {
-          continue;
-        }
+#endif
+        continue;
       }
 #endif
 
@@ -2023,9 +2156,19 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
       PredictionUnit &pu  = tempCS->addPU( cu, partitioner.chType );
 
 #if JVET_L0100_MULTI_HYPOTHESIS_INTRA
+#if JVET_L0054_MMVD
+      if (uiNoResidualPass == 0 && uiMergeCand >= (MRG_MAX_NUM_CANDS + MMVD_ADD_NUM))
+#else
       if (uiNoResidualPass == 0 && uiMergeCand >= (MRG_MAX_NUM_CANDS + MRG_MAX_NUM_CANDS))
+#endif
       {
+#if JVET_L0054_MMVD
+        uiMergeCand -= (MRG_MAX_NUM_CANDS + MMVD_ADD_NUM);
+        cu.mmvdSkip = false;
+        mergeCtx.setMergeInfo(pu, uiMergeCand);
+#else
         uiMergeCand -= (MRG_MAX_NUM_CANDS + MRG_MAX_NUM_CANDS);
+#endif
         pu.MHIntraFlag = true;
         pu.intraDir[0] = RdModeList2[uiMrgHADIdx];
         CHECK(pu.intraDir[0]<0 || pu.intraDir[0]>(NUM_LUMA_MODE - 1), "out of intra mode");
@@ -2034,7 +2177,11 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
 #endif
 
 #if JVET_L0054_MMVD
+#if JVET_L0100_MULTI_HYPOTHESIS_INTRA
+      else if (uiMergeCand >= mergeCtx.numValidMergeCand && uiMergeCand < MRG_MAX_NUM_CANDS + MMVD_ADD_NUM)
+#else
       if (uiMergeCand >= mergeCtx.numValidMergeCand)
+#endif
       {
         cu.mmvdSkip = true;
         mergeCtx.setMmvdMergeCandiInfo(pu, uiMergeCand - mergeCtx.numValidMergeCand);
@@ -2070,13 +2217,18 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
         }
         else
         {
+#if JVET_L0054_MMVD
+          tempCS->getPredBuf().copyFrom(*acMergeTempBuffer[uiMrgHADIdx]);
+#else
           tempCS->getPredBuf().copyFrom(acMergeBuffer[uiMergeCand]);
+#endif
         }
 #else
 #if JVET_L0054_MMVD
         tempCS->getPredBuf().copyFrom(*acMergeTempBuffer[uiMrgHADIdx]);
 #else
         tempCS->getPredBuf().copyFrom( acMergeBuffer[ uiMergeCand ]);
+#endif
 #endif
       }
       else
@@ -2085,13 +2237,6 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
         
       }
 
-#if JVET_L0100_MULTI_HYPOTHESIS_INTRA
-      if (!pu.MHIntraFlag && uiNoResidualPass != 0)
-      {
-        isTestSkipMerge[uiMergeCand] = true;
-      }
-#endif
-
 #if JVET_L0054_MMVD
       xEncodeInterResidual(tempCS, bestCS, partitioner, encTestMode, uiNoResidualPass
         , NULL
@@ -2838,96 +2983,5 @@ void EncCu::xReuseCachedResult( CodingStructure *&tempCS, CodingStructure *&best
 
 #endif
 
-#if JVET_L0100_MULTI_HYPOTHESIS_INTRA
-template<typename T, size_t N>
-void EncCu::getMHIntraLCCand(PredictionUnit &pu, static_vector<T, N>& RdModeList, static_vector<double, N>& candCostList, static_vector<T, N>& RdModeList2, uint32_t uiNumMrgSATDCand, const double sqrtLambdaForFirstPass, const double sqrtLambdaForFirstPassIntra, DistParam distParam, const UnitArea localUnitArea)
-{
-  PelUnitBuf acMergeBuffer[MRG_MAX_NUM_CANDS]; // acquire normal merge pred buffer
-
-  int numTestIntraMode = 4;
-  // prepare for Intra bits calculation
-  const TempCtx ctxStart(m_CtxCache, m_CABACEstimator->getCtx());
-  const TempCtx ctxStartIntraMode(m_CtxCache, SubCtx(Ctx::MHIntraPredMode, m_CABACEstimator->getCtx()));
-
-  // for Intrainter fast, recored the best intra mode during the first round for mrege 0
-  int bestMHIntraMode = -1;
-  double bestMHIntraCost = MAX_DOUBLE;
-
-  pu.MHIntraFlag = true;
-
-  // save the to-be-tested merge candidates
-  uint32_t MHIntraMergeCand[NUM_MRG_SATD_CAND];
-
-  for (uint32_t mergeCnt = 0; mergeCnt < NUM_MRG_SATD_CAND; mergeCnt++)
-  {
-    MHIntraMergeCand[mergeCnt] = RdModeList[mergeCnt];
-  }
-
-  for (uint32_t mergeCnt = 0; mergeCnt < std::min(NUM_MRG_SATD_CAND, 4); mergeCnt++)
-  {
-    uint32_t mergeCand = MHIntraMergeCand[mergeCnt];
-    acMergeBuffer[mergeCand] = m_acMergeBuffer[mergeCand].getBuf(localUnitArea);
-
-    // estimate merge bits
-    uint32_t bitsCand = mergeCand + 1;
-    if (mergeCand == pu.cs->slice->getMaxNumMergeCand() - 1)
-    {
-      bitsCand--;
-    }
-
-    // first round
-    for (uint32_t intraCnt = 0; intraCnt < numTestIntraMode; intraCnt++)
-    {
-      pu.intraDir[0] = (intraCnt < 2) ? intraCnt : ((intraCnt == 2) ? HOR_IDX : VER_IDX);
-
-      // fast 2
-      if (mergeCnt > 0 && bestMHIntraMode != pu.intraDir[0])
-      {
-        continue;
-      }
-      int narrowCase = PU::getNarrowShape(pu.lwidth(), pu.lheight());
-      if (narrowCase == 1 && pu.intraDir[0] == HOR_IDX)
-      {
-        continue;
-      }
-      if (narrowCase == 2 && pu.intraDir[0] == VER_IDX)
-      {
-        continue;
-      }
-      // generate intrainter Y prediction
-      if (mergeCnt == 0)
-      {
-        bool isUseFilter = IntraPrediction::useFilteredIntraRefSamples(COMPONENT_Y, pu, true, pu);
-        m_pcIntraSearch->initIntraPatternChType(*pu.cu, pu.Y(), isUseFilter);
-        m_pcIntraSearch->predIntraAng(COMPONENT_Y, pu.cs->getPredBuf(pu).Y(), pu, isUseFilter);
-        m_pcIntraSearch->switchBuffer(pu, COMPONENT_Y, pu.cs->getPredBuf(pu).Y(), m_pcIntraSearch->getPredictorPtr2(COMPONENT_Y, intraCnt));
-      }
-
-      pu.cs->getPredBuf(pu).copyFrom(acMergeBuffer[mergeCand]);
-      m_pcIntraSearch->geneWeightedPred(COMPONENT_Y, pu.cs->getPredBuf(pu).Y(), pu, m_pcIntraSearch->getPredictorPtr2(COMPONENT_Y, intraCnt));
-
-      // calculate cost
-      distParam.cur = pu.cs->getPredBuf(pu).Y();
-      Distortion sadValue = distParam.distFunc(distParam);
-      m_CABACEstimator->getCtx() = SubCtx(Ctx::MHIntraPredMode, ctxStartIntraMode);
-      uint64_t fracModeBits = m_pcIntraSearch->xFracModeBitsIntra(pu, pu.intraDir[0], CHANNEL_TYPE_LUMA);
-      double cost = (double)sadValue + (double)(bitsCand + 1) * sqrtLambdaForFirstPass + (double)fracModeBits * sqrtLambdaForFirstPassIntra;
-
-      updateDoubleCandList(mergeCand + MRG_MAX_NUM_CANDS + MRG_MAX_NUM_CANDS, cost, RdModeList, candCostList, RdModeList2, pu.intraDir[0], uiNumMrgSATDCand);
-
-      // fast 2
-      if (mergeCnt == 0 && cost < bestMHIntraCost)
-      {
-        bestMHIntraMode = pu.intraDir[0];
-        bestMHIntraCost = cost;
-      }
-    }
-  }
-  pu.MHIntraFlag = false;
-  m_CABACEstimator->getCtx() = ctxStart;
-  return;
-}
-#endif
-
 
 //! \}
diff --git a/source/Lib/EncoderLib/EncCu.h b/source/Lib/EncoderLib/EncCu.h
index 7f0646dfa..fe9586555 100644
--- a/source/Lib/EncoderLib/EncCu.h
+++ b/source/Lib/EncoderLib/EncCu.h
@@ -114,6 +114,9 @@ private:
   EncModeCtrl          *m_modeCtrl;
 #if JVET_L0054_MMVD
   PelStorage            m_acMergeBuffer[MMVD_MRG_MAX_RD_BUF_NUM];
+#if JVET_L0100_MULTI_HYPOTHESIS_INTRA
+  PelStorage            m_acRealMergeBuffer[MRG_MAX_NUM_CANDS];
+#endif
 #else
   PelStorage            m_acMergeBuffer[MRG_MAX_NUM_CANDS];
 #endif
@@ -239,10 +242,6 @@ protected:
        ||  abs(cu.slice->getPOC() - cu.slice->getRefPOC(REF_PIC_LIST_1, cu.refIdxBi[1])) == 1))));
   }
 #endif
-#if JVET_L0100_MULTI_HYPOTHESIS_INTRA
-  template<typename T, size_t N>
-  void getMHIntraLCCand       (PredictionUnit &pu, static_vector<T, N>& RdModeList, static_vector<double, N>& candCostList, static_vector<T, N>& RdModeList2, uint32_t uiNumMrgSATDCand, const double sqrtLambdaForFirstPass, const double sqrtLambdaForFirstPassIntra, DistParam distParam, const UnitArea localUnitArea);
-#endif
 };
 
 //! \}
-- 
GitLab