From 8e2ed7867188ed9dcafff560a4644c43afbf2e5c Mon Sep 17 00:00:00 2001
From: ywchen <yiwenchen@kwai.com>
Date: Thu, 11 Apr 2019 19:40:02 -0700
Subject: [PATCH] Integration of N0324 on Regular Merge Flag

---
 source/Lib/CommonLib/ContextModelling.cpp |   7 +-
 source/Lib/CommonLib/Contexts.cpp         |  10 +-
 source/Lib/CommonLib/Contexts.h           |   3 +
 source/Lib/CommonLib/TypeDef.h            |   2 +
 source/Lib/CommonLib/Unit.cpp             |   9 ++
 source/Lib/CommonLib/Unit.h               |   3 +
 source/Lib/DecoderLib/CABACReader.cpp     | 111 +++++++++++++++++++++-
 source/Lib/EncoderLib/CABACWriter.cpp     |  96 +++++++++++++++++++
 source/Lib/EncoderLib/EncCu.cpp           |  50 ++++++++--
 source/Lib/EncoderLib/InterSearch.cpp     |  33 ++++++-
 10 files changed, 313 insertions(+), 11 deletions(-)

diff --git a/source/Lib/CommonLib/ContextModelling.cpp b/source/Lib/CommonLib/ContextModelling.cpp
index aa3f10f470..bc2f329ab9 100644
--- a/source/Lib/CommonLib/ContextModelling.cpp
+++ b/source/Lib/CommonLib/ContextModelling.cpp
@@ -382,7 +382,9 @@ unsigned DeriveCtx::CtxIBCFlag(const CodingUnit& cu)
 void MergeCtx::setMergeInfo( PredictionUnit& pu, int candIdx )
 {
   CHECK( candIdx >= numValidMergeCand, "Merge candidate does not exist" );
-
+#if JVET_N0324_REGULAR_MRG_FLAG
+  pu.regularMergeFlag        = !(pu.mhIntraFlag || pu.cu->triangle);
+#endif
   pu.mergeFlag               = true;
   pu.mmvdMergeFlag = false;
   pu.interDir                = interDirNeighbours[candIdx];
@@ -562,6 +564,9 @@ void MergeCtx::setMmvdMergeCandiInfo(PredictionUnit& pu, int candIdx)
   pu.mmvdMergeFlag = true;
   pu.mmvdMergeIdx = candIdx;
   pu.mergeFlag = true;
+#if JVET_N0324_REGULAR_MRG_FLAG
+  pu.regularMergeFlag = false;
+#endif
   pu.mergeIdx = candIdx;
   pu.mergeType = MRG_TYPE_DEFAULT_N;
   pu.mvd[REF_PIC_LIST_0] = Mv();
diff --git a/source/Lib/CommonLib/Contexts.cpp b/source/Lib/CommonLib/Contexts.cpp
index 48c8f7d981..d922e52996 100644
--- a/source/Lib/CommonLib/Contexts.cpp
+++ b/source/Lib/CommonLib/Contexts.cpp
@@ -245,7 +245,15 @@ const CtxSet ContextSetCfg::MergeFlag = ContextSetCfg::addCtxSet
   { 153, },
   { 5, },
 });
-
+#if JVET_N0324_REGULAR_MRG_FLAG
+const CtxSet ContextSetCfg::RegularMergeFlag = ContextSetCfg::addCtxSet
+({
+  { 111, 111, },
+  { 111, 111, },
+  { 153, 153, },
+  { 5, 5, },
+  });
+#endif
 const CtxSet ContextSetCfg::MergeIdx = ContextSetCfg::addCtxSet
 ({
   { 138, },
diff --git a/source/Lib/CommonLib/Contexts.h b/source/Lib/CommonLib/Contexts.h
index 9841ca34eb..4cffdab370 100644
--- a/source/Lib/CommonLib/Contexts.h
+++ b/source/Lib/CommonLib/Contexts.h
@@ -201,6 +201,9 @@ public:
   static const CtxSet   Split12Flag;
   static const CtxSet   SkipFlag;
   static const CtxSet   MergeFlag;
+#if JVET_N0324_REGULAR_MRG_FLAG
+  static const CtxSet   RegularMergeFlag;
+#endif
   static const CtxSet   MergeIdx;
   static const CtxSet   PartSize;
   static const CtxSet   PredMode;
diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h
index fb51e135bd..a0b913f4d6 100644
--- a/source/Lib/CommonLib/TypeDef.h
+++ b/source/Lib/CommonLib/TypeDef.h
@@ -50,6 +50,8 @@
 #include <assert.h>
 #include <cassert>
 
+#define JVET_N0324_REGULAR_MRG_FLAG                       1
+
 #define JVET_N0068_AFFINE_MEM_BW                          1 // memory bandwidth reduction for affine mode
 
 #define JVET_N0308_MAX_CU_SIZE_FOR_ISP                    1
diff --git a/source/Lib/CommonLib/Unit.cpp b/source/Lib/CommonLib/Unit.cpp
index ef6bb54766..739c4518d6 100644
--- a/source/Lib/CommonLib/Unit.cpp
+++ b/source/Lib/CommonLib/Unit.cpp
@@ -403,6 +403,9 @@ void PredictionUnit::initData()
 
   // inter data
   mergeFlag   = false;
+#if JVET_N0324_REGULAR_MRG_FLAG
+  regularMergeFlag = false;
+#endif
   mergeIdx    = MAX_UCHAR;
   triangleSplitDir  = MAX_UCHAR;
   triangleMergeIdx0 = MAX_UCHAR;
@@ -455,6 +458,9 @@ PredictionUnit& PredictionUnit::operator=(const IntraPredictionData& predData)
 PredictionUnit& PredictionUnit::operator=(const InterPredictionData& predData)
 {
   mergeFlag   = predData.mergeFlag;
+#if JVET_N0324_REGULAR_MRG_FLAG
+  regularMergeFlag = predData.regularMergeFlag;
+#endif
   mergeIdx    = predData.mergeIdx;
   triangleSplitDir  = predData.triangleSplitDir  ;
   triangleMergeIdx0 = predData.triangleMergeIdx0 ;
@@ -501,6 +507,9 @@ PredictionUnit& PredictionUnit::operator=( const PredictionUnit& other )
   multiRefIdx = other.multiRefIdx;
 
   mergeFlag   = other.mergeFlag;
+#if JVET_N0324_REGULAR_MRG_FLAG
+  regularMergeFlag = other.regularMergeFlag;
+#endif
   mergeIdx    = other.mergeIdx;
   triangleSplitDir  = other.triangleSplitDir  ;
   triangleMergeIdx0 = other.triangleMergeIdx0 ;
diff --git a/source/Lib/CommonLib/Unit.h b/source/Lib/CommonLib/Unit.h
index 45b04ca9d7..5713546932 100644
--- a/source/Lib/CommonLib/Unit.h
+++ b/source/Lib/CommonLib/Unit.h
@@ -361,6 +361,9 @@ struct IntraPredictionData
 struct InterPredictionData
 {
   bool      mergeFlag;
+#if JVET_N0324_REGULAR_MRG_FLAG
+  bool      regularMergeFlag;
+#endif
   uint8_t     mergeIdx;
   uint8_t     triangleSplitDir;
   uint8_t     triangleMergeIdx0;
diff --git a/source/Lib/DecoderLib/CABACReader.cpp b/source/Lib/DecoderLib/CABACReader.cpp
index 890d34e242..f9799185af 100644
--- a/source/Lib/DecoderLib/CABACReader.cpp
+++ b/source/Lib/DecoderLib/CABACReader.cpp
@@ -657,7 +657,9 @@ bool CABACReader::coding_unit( CodingUnit &cu, Partitioner &partitioner, CUCtx&
   {
     cu_transquant_bypass_flag( cu );
   }
-
+#if JVET_N0324_REGULAR_MRG_FLAG
+  PredictionUnit&    pu = cs.addPU(cu, partitioner.chType);
+#endif
   // skip flag
   if ((!cs.slice->isIntra() || cs.slice->getSPS()->getIBCFlag()) && cu.Y().valid())
   {
@@ -668,7 +670,9 @@ bool CABACReader::coding_unit( CodingUnit &cu, Partitioner &partitioner, CUCtx&
   if( cu.skip )
   {
     cs.addTU         ( cu, partitioner.chType );
+#if !JVET_N0324_REGULAR_MRG_FLAG
     PredictionUnit&    pu = cs.addPU( cu, partitioner.chType );
+#endif
     pu.shareParentPos = cu.shareParentPos;
     pu.shareParentSize = cu.shareParentSize;
     MergeCtx           mrgCtx;
@@ -680,8 +684,9 @@ bool CABACReader::coding_unit( CodingUnit &cu, Partitioner &partitioner, CUCtx&
   pred_mode ( cu );
 
   // --> create PUs
+#if !JVET_N0324_REGULAR_MRG_FLAG
   CU::addPUs( cu );
-
+#endif
   // pcm samples
   if( CU::isIntra(cu) )
   {
@@ -780,6 +785,9 @@ void CABACReader::cu_skip_flag( CodingUnit& cu )
       cu.rootCbf = false;
       cu.predMode = MODE_IBC;
       cu.mmvdSkip = false;
+#if JVET_N0324_REGULAR_MRG_FLAG
+      cu.firstPU->regularMergeFlag = false;
+#endif
     }
     else
     {
@@ -797,6 +805,44 @@ void CABACReader::cu_skip_flag( CodingUnit& cu )
   if ((skip && CU::isInter(cu) && cu.cs->slice->getSPS()->getIBCFlag()) ||
     (skip && !cu.cs->slice->getSPS()->getIBCFlag()))
   {
+#if JVET_N0324_REGULAR_MRG_FLAG
+    unsigned regularMergeFlag = (m_BinDecoder.decodeBin(Ctx::RegularMergeFlag(0)));
+    DTRACE(g_trace_ctx, D_SYNTAX, "regular_merge_flag() ctx=%d regularMergeFlag=%d\n", 0, regularMergeFlag?1:0);
+    cu.firstPU->regularMergeFlag = regularMergeFlag;
+    if (cu.firstPU->regularMergeFlag)
+    {
+      cu.mmvdSkip = false;
+      cu.firstPU->mmvdMergeFlag = false;
+      cu.firstPU->mhIntraFlag = false;
+      cu.affine = false;
+      cu.triangle = false;
+    }
+    else 
+    {
+#if JVET_N0127_MMVD_SPS_FLAG 
+    if (cu.cs->slice->getSPS()->getUseMMVD())
+    {
+#endif
+      bool isCUWithOnlyRegularAndMMVD=((cu.firstPU->lwidth() == 4 && cu.firstPU->lheight() == 4) || (cu.firstPU->lwidth() == 8 && cu.firstPU->lheight() == 4) || (cu.firstPU->lwidth() == 4 && cu.firstPU->lheight() == 8));
+      if (isCUWithOnlyRegularAndMMVD)
+      {
+        cu.mmvdSkip = !(cu.firstPU->regularMergeFlag);
+      }
+      else
+      {
+        unsigned mmvdSkip = m_BinDecoder.decodeBin(Ctx::MmvdFlag(0));
+        cu.mmvdSkip = mmvdSkip;
+        DTRACE(g_trace_ctx, D_SYNTAX, "mmvd_cu_skip_flag() ctx=%d mmvd_skip=%d\n", 0, mmvdSkip ? 1 : 0);
+      }
+#if JVET_N0127_MMVD_SPS_FLAG 
+    }
+    else
+    {
+      cu.mmvdSkip = false;
+    }
+#endif  
+    }
+#else
 #if JVET_MMVD_OFF_MACRO
     cu.mmvdSkip = false;
 #else
@@ -814,6 +860,7 @@ void CABACReader::cu_skip_flag( CodingUnit& cu )
       cu.mmvdSkip = false;
     }
 #endif  
+#endif
 #endif
     cu.skip     = true;
     cu.rootCbf  = false;
@@ -1454,6 +1501,14 @@ void CABACReader::prediction_unit( PredictionUnit& pu, MergeCtx& mrgCtx )
     }
     else
     {
+#if JVET_N0324_REGULAR_MRG_FLAG
+      if (pu.regularMergeFlag)
+      {
+        merge_idx(pu);
+      }
+      else
+      {
+#endif
     subblock_merge_flag( *pu.cu );
     MHIntra_flag(pu);
     if (pu.mhIntraFlag)
@@ -1461,13 +1516,23 @@ void CABACReader::prediction_unit( PredictionUnit& pu, MergeCtx& mrgCtx )
       MHIntra_luma_pred_modes(*pu.cu);
       pu.intraDir[1] = DM_CHROMA_IDX;
     }
+#if JVET_N0324_REGULAR_MRG_FLAG
+    else
+    {      
+      pu.cu->triangle = pu.cu->cs->slice->getSPS()->getUseTriangle() && pu.cu->cs->slice->isInterB() && !pu.cu->affine && !pu.mmvdMergeFlag && !pu.cu->mmvdSkip;
+    }
+#else
     triangle_mode( *pu.cu );
+#endif
     if (pu.mmvdMergeFlag)
     {
       mmvd_merge_idx(pu);
     }
     else
       merge_data   ( pu );
+#if JVET_N0324_REGULAR_MRG_FLAG
+      }
+#endif
     }
   }
   else if (CU::isIBC(*pu.cu))
@@ -1621,8 +1686,49 @@ void CABACReader::merge_flag( PredictionUnit& pu )
   if (pu.mergeFlag && CU::isIBC(*pu.cu))
   {
     pu.mmvdMergeFlag = false;
+#if JVET_N0324_REGULAR_MRG_FLAG
+    pu.regularMergeFlag = false;
+#endif
     return;
   }
+#if JVET_N0324_REGULAR_MRG_FLAG
+  if (pu.mergeFlag)
+  {
+    pu.regularMergeFlag = (m_BinDecoder.decodeBin(Ctx::RegularMergeFlag(1)));
+    DTRACE(g_trace_ctx, D_SYNTAX, "regular_merge_flag() ctx=%d pu.regularMergeFlag=%d\n", 1, pu.regularMergeFlag?1:0);
+    if (pu.regularMergeFlag)
+    {
+      pu.mmvdMergeFlag = false;
+      pu.mhIntraFlag = false;
+      pu.cu->affine = false;
+      pu.cu->triangle = false;
+    }
+    else 
+    {
+#if JVET_N0127_MMVD_SPS_FLAG 
+      if (pu.cs->sps->getUseMMVD())
+      {
+#endif
+      bool isCUWithOnlyRegularAndMMVD=((pu.lwidth() == 4 && pu.lheight() == 4) || (pu.lwidth() == 8 && pu.lheight() == 4) || (pu.lwidth() == 4 && pu.lheight() == 8));
+      if (isCUWithOnlyRegularAndMMVD)
+      {
+      pu.mmvdMergeFlag = !(pu.regularMergeFlag);
+      }
+      else
+      {
+      pu.mmvdMergeFlag = (m_BinDecoder.decodeBin(Ctx::MmvdFlag(0)));
+      DTRACE(g_trace_ctx, D_SYNTAX, "mmvd_merge_flag() mmvd_merge=%d pos=(%d,%d) size=%dx%d\n", pu.mmvdMergeFlag ? 1 : 0, pu.lumaPos().x, pu.lumaPos().y, pu.lumaSize().width, pu.lumaSize().height);
+      }
+#if JVET_N0127_MMVD_SPS_FLAG 
+      }
+      else
+      {
+        pu.mmvdMergeFlag = false;
+      }
+#endif 
+    }
+  }
+#else
 #if JVET_MMVD_OFF_MACRO
   pu.mmvdMergeFlag = false;
 #else
@@ -1642,6 +1748,7 @@ void CABACReader::merge_flag( PredictionUnit& pu )
   }
 #endif 
 #endif
+#endif
 }
 
 
diff --git a/source/Lib/EncoderLib/CABACWriter.cpp b/source/Lib/EncoderLib/CABACWriter.cpp
index 9b949e89cd..fb3c6a40a7 100644
--- a/source/Lib/EncoderLib/CABACWriter.cpp
+++ b/source/Lib/EncoderLib/CABACWriter.cpp
@@ -674,6 +674,30 @@ void CABACWriter::cu_skip_flag( const CodingUnit& cu )
 #if JVET_N0318_N0467_IBC_SIZE
     }
 #endif
+#if JVET_N0324_REGULAR_MRG_FLAG
+    if (CU::isInter(cu))
+    {
+      m_BinEncoder.encodeBin(cu.firstPU->regularMergeFlag, Ctx::RegularMergeFlag(0));
+      DTRACE(g_trace_ctx, D_SYNTAX, "regularMergeFlag() ctx=%d regularMergeFlag=%d\n", 0, cu.firstPU->regularMergeFlag?1:0);      
+#if JVET_N0127_MMVD_SPS_FLAG 
+      if (cu.cs->slice->getSPS()->getUseMMVD())
+      {
+#endif
+      bool isCUWithOnlyRegularAndMMVD=((cu.firstPU->lwidth() == 4 && cu.firstPU->lheight() == 4) || (cu.firstPU->lwidth() == 8 && cu.firstPU->lheight() == 4) || (cu.firstPU->lwidth() == 4 && cu.firstPU->lheight() == 8));
+      if (isCUWithOnlyRegularAndMMVD)
+      {
+        CHECK(cu.mmvdSkip==cu.firstPU->regularMergeFlag, "mmvdSkip_flag must be !regularMergeFlag");
+      }
+      else if (!cu.firstPU->regularMergeFlag)
+      {
+        m_BinEncoder.encodeBin(cu.mmvdSkip, Ctx::MmvdFlag(0));
+        DTRACE(g_trace_ctx, D_SYNTAX, "mmvd_cu_skip_flag() ctx=%d mmvd_skip=%d\n", 0, cu.mmvdSkip ? 1 : 0);
+      }
+#if JVET_N0127_MMVD_SPS_FLAG 
+      }
+#endif
+    }
+#else
 #if !JVET_MMVD_OFF_MACRO
 #if JVET_N0127_MMVD_SPS_FLAG 
     if (CU::isInter(cu) && cu.cs->slice->getSPS()->getUseMMVD())
@@ -684,8 +708,33 @@ void CABACWriter::cu_skip_flag( const CodingUnit& cu )
       m_BinEncoder.encodeBin(cu.mmvdSkip, Ctx::MmvdFlag(0));
       DTRACE(g_trace_ctx, D_SYNTAX, "mmvd_cu_skip_flag() ctx=%d mmvd_skip=%d\n", 0, cu.mmvdSkip ? 1 : 0);
     }
+#endif
 #endif
   }
+#if JVET_N0324_REGULAR_MRG_FLAG
+  if (cu.skip && !cu.cs->slice->getSPS()->getIBCFlag())
+  {
+    m_BinEncoder.encodeBin(cu.firstPU->regularMergeFlag, Ctx::RegularMergeFlag(0));
+    DTRACE(g_trace_ctx, D_SYNTAX, "regularMergeFlag() ctx=%d regularMergeFlag=%d\n", 0, cu.firstPU->regularMergeFlag?1:0);
+#if JVET_N0127_MMVD_SPS_FLAG 
+  if (cu.cs->slice->getSPS()->getUseMMVD())
+    {
+#endif
+    bool isCUWithOnlyRegularAndMMVD=((cu.firstPU->lwidth() == 4 && cu.firstPU->lheight() == 4) || (cu.firstPU->lwidth() == 8 && cu.firstPU->lheight() == 4) || (cu.firstPU->lwidth() == 4 && cu.firstPU->lheight() == 8));
+    if (isCUWithOnlyRegularAndMMVD)
+    {
+      CHECK(cu.mmvdSkip==cu.firstPU->regularMergeFlag, "mmvdSkip_flag must be !regularMergeFlag");
+    }
+    else if (!cu.firstPU->regularMergeFlag)
+    {
+      m_BinEncoder.encodeBin(cu.mmvdSkip, Ctx::MmvdFlag(0));
+      DTRACE(g_trace_ctx, D_SYNTAX, "mmvd_cu_skip_flag() ctx=%d mmvd_skip=%d\n", 0, cu.mmvdSkip ? 1 : 0);
+    }
+#if JVET_N0127_MMVD_SPS_FLAG 
+    }
+#endif
+  }
+#else
 #if !JVET_MMVD_OFF_MACRO
 #if JVET_N0127_MMVD_SPS_FLAG 
   if (cu.skip && !cu.cs->slice->getSPS()->getIBCFlag() && cu.cs->slice->getSPS()->getUseMMVD())
@@ -697,6 +746,7 @@ void CABACWriter::cu_skip_flag( const CodingUnit& cu )
     DTRACE(g_trace_ctx, D_SYNTAX, "mmvd_cu_skip_flag() ctx=%d mmvd_skip=%d\n", 0, cu.mmvdSkip ? 1 : 0);
   }
 #endif
+#endif
 }
 
 
@@ -1372,19 +1422,40 @@ void CABACWriter::prediction_unit( const PredictionUnit& pu )
       merge_idx(pu);
       return;
     }
+#if JVET_N0324_REGULAR_MRG_FLAG
+    if (pu.regularMergeFlag)
+    {
+      merge_idx(pu);
+    }
+    else
+    {
+#endif
     subblock_merge_flag( *pu.cu );
     MHIntra_flag( pu );
     if ( pu.mhIntraFlag )
     {
       MHIntra_luma_pred_modes( *pu.cu );
     }
+#if JVET_N0324_REGULAR_MRG_FLAG
+    else
+    {
+      if (!pu.cu->affine && !pu.mmvdMergeFlag && !pu.cu->mmvdSkip)
+      {
+        CHECK(!pu.cu->triangle, "triangle_flag must be true");
+      }
+    }
+#else
     triangle_mode( *pu.cu );
+#endif
     if (pu.mmvdMergeFlag)
     {
       mmvd_merge_idx(pu);
     }
     else
     merge_idx    ( pu );
+#if JVET_N0324_REGULAR_MRG_FLAG
+    }
+#endif
   }
   else if (CU::isIBC(*pu.cu))
   {
@@ -1502,6 +1573,30 @@ void CABACWriter::merge_flag( const PredictionUnit& pu )
   {
     return;
   }
+#if JVET_N0324_REGULAR_MRG_FLAG
+  if (pu.mergeFlag)
+  {
+    m_BinEncoder.encodeBin(pu.regularMergeFlag, Ctx::RegularMergeFlag(1));
+    DTRACE(g_trace_ctx, D_SYNTAX, "regularMergeFlag() ctx=%d regularMergeFlag=%d\n", 1, pu.regularMergeFlag?1:0);
+#if JVET_N0127_MMVD_SPS_FLAG 
+  if (pu.cs->sps->getUseMMVD())
+  {
+#endif
+    bool isCUWithOnlyRegularAndMMVD=((pu.lwidth() == 4 && pu.lheight() == 4) || (pu.lwidth() == 8 && pu.lheight() == 4) || (pu.lwidth() == 4 && pu.lheight() == 8));
+    if (isCUWithOnlyRegularAndMMVD)
+    {
+      CHECK(pu.mmvdMergeFlag==pu.regularMergeFlag, "mmvdMergeFlag must be !regularMergeFlag");
+    }
+    else if (!pu.regularMergeFlag)
+    {
+      m_BinEncoder.encodeBin(pu.mmvdMergeFlag, Ctx::MmvdFlag(0));
+      DTRACE(g_trace_ctx, D_SYNTAX, "mmvd_merge_flag() mmvd_merge=%d pos=(%d,%d) size=%dx%d\n", pu.mmvdMergeFlag ? 1 : 0, pu.lumaPos().x, pu.lumaPos().y, pu.lumaSize().width, pu.lumaSize().height);
+    }
+#if JVET_N0127_MMVD_SPS_FLAG 
+    }
+#endif
+  }
+#else
 #if !JVET_MMVD_OFF_MACRO
 #if JVET_N0127_MMVD_SPS_FLAG 
   if (pu.mergeFlag && pu.cs->sps->getUseMMVD())
@@ -1513,6 +1608,7 @@ void CABACWriter::merge_flag( const PredictionUnit& pu )
     DTRACE(g_trace_ctx, D_SYNTAX, "mmvd_merge_flag() mmvd_merge=%d pos=(%d,%d) size=%dx%d\n", pu.mmvdMergeFlag ? 1 : 0, pu.lumaPos().x, pu.lumaPos().y, pu.lumaSize().width, pu.lumaSize().height);
   }
 #endif
+#endif
 }
 
 void CABACWriter::imv_mode( const CodingUnit& cu )
diff --git a/source/Lib/EncoderLib/EncCu.cpp b/source/Lib/EncoderLib/EncCu.cpp
index dda7462a9f..489d32f2e7 100644
--- a/source/Lib/EncoderLib/EncCu.cpp
+++ b/source/Lib/EncoderLib/EncCu.cpp
@@ -1704,6 +1704,9 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
       , 0
     );
     PU::getInterMMVDMergeCandidates(pu, mergeCtx);
+#if JVET_N0324_REGULAR_MRG_FLAG
+    pu.regularMergeFlag = true;
+#endif
   }
   bool candHasNoResidual[MRG_MAX_NUM_CANDS + MMVD_ADD_NUM];
   for (uint32_t ui = 0; ui < MRG_MAX_NUM_CANDS + MMVD_ADD_NUM; ui++)
@@ -1962,7 +1965,11 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
             }
             m_CABACEstimator->getCtx() = SubCtx(Ctx::MHIntraPredMode, ctxStartIntraMode);
             uint64_t fracModeBits = m_pcIntraSearch->xFracModeBitsIntra(pu, pu.intraDir[0], CHANNEL_TYPE_LUMA);
+#if JVET_N0324_REGULAR_MRG_FLAG
+            double cost = (double)sadValue + (double)(bitsCand + 9) * sqrtLambdaForFirstPass + (double)fracModeBits * sqrtLambdaForFirstPassIntra;
+#else
             double cost = (double)sadValue + (double)(bitsCand + 1) * sqrtLambdaForFirstPass + (double)fracModeBits * sqrtLambdaForFirstPassIntra;
+#endif
             insertPos = -1;
             updateDoubleCandList(mergeCand + MRG_MAX_NUM_CANDS + MMVD_ADD_NUM, cost, RdModeList, candCostList, RdModeList2, pu.intraDir[0], uiNumMrgSATDCand, &insertPos);
             if (insertPos != -1)
@@ -2023,8 +2030,11 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
           }
 
           bitsCand = bitsBaseIdx + bitsRefineStep + bitsDirection;
+#if JVET_N0324_REGULAR_MRG_FLAG
+          bitsCand += 7;
+#else
           bitsCand++; // for mmvd_flag
-
+#endif
           mergeCtx.setMmvdMergeCandiInfo(pu, mmvdMergeCand);
 
           PU::spanMotionInfo(pu, mergeCtx);
@@ -2165,6 +2175,9 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
         cu.mmvdSkip = false;
         mergeCtx.setMergeInfo(pu, uiMergeCand);
         pu.mhIntraFlag = true;
+#if JVET_N0324_REGULAR_MRG_FLAG
+        pu.regularMergeFlag = false;
+#endif
         pu.intraDir[0] = RdModeList2[uiMrgHADIdx];
         CHECK(pu.intraDir[0]<0 || pu.intraDir[0]>(NUM_LUMA_MODE - 1), "out of intra mode");
         pu.intraDir[1] = DM_CHROMA_IDX;
@@ -2361,7 +2374,9 @@ void EncCu::xCheckRDCostMergeTriangle2Nx2N( CodingStructure *&tempCS, CodingStru
     PredictionUnit pu( tempCS->area );
     pu.cu = &cu;
     pu.cs = tempCS;
-
+#if JVET_N0324_REGULAR_MRG_FLAG
+    pu.regularMergeFlag = false;
+#endif
 
     PU::getTriangleMergeCandidates( pu, triangleMrgCtx );
     for( uint8_t mergeCand = 0; mergeCand < TRIANGLE_MAX_NUM_UNI_CANDS; mergeCand++ )
@@ -2426,6 +2441,9 @@ void EncCu::xCheckRDCostMergeTriangle2Nx2N( CodingStructure *&tempCS, CodingStru
       pu.triangleMergeIdx0 = candIdx0;
       pu.triangleMergeIdx1 = candIdx1;
       pu.mergeFlag = true;
+#if JVET_N0324_REGULAR_MRG_FLAG
+      pu.regularMergeFlag = false;
+#endif
       triangleWeightedBuffer[mergeCand] = m_acTriangleWeightedBuffer[mergeCand].getBuf( localUnitArea );
       triangleBuffer[candIdx0] = m_acMergeBuffer[candIdx0].getBuf( localUnitArea );
       triangleBuffer[candIdx1] = m_acMergeBuffer[candIdx1].getBuf( localUnitArea );
@@ -2467,7 +2485,9 @@ void EncCu::xCheckRDCostMergeTriangle2Nx2N( CodingStructure *&tempCS, CodingStru
       pu.triangleMergeIdx0 = candIdx0;
       pu.triangleMergeIdx1 = candIdx1;
       pu.mergeFlag = true;
-
+#if JVET_N0324_REGULAR_MRG_FLAG
+      pu.regularMergeFlag = false;
+#endif
       m_pcInterSearch->weightedTriangleBlk( pu, splitDir, CHANNEL_TYPE_CHROMA, triangleWeightedBuffer[mergeCand], triangleBuffer[candIdx0], triangleBuffer[candIdx1] );
     }
 
@@ -2521,7 +2541,9 @@ void EncCu::xCheckRDCostMergeTriangle2Nx2N( CodingStructure *&tempCS, CodingStru
         pu.triangleMergeIdx0 = candIdx0;
         pu.triangleMergeIdx1 = candIdx1;
         pu.mergeFlag = true;
-
+#if JVET_N0324_REGULAR_MRG_FLAG
+        pu.regularMergeFlag = false;
+#endif
         PU::spanTriangleMotionInfo(pu, triangleMrgCtx, splitDir, candIdx0, candIdx1 );
 
         if( m_pcEncCfg->getMCTSEncConstraint() && ( !( MCTSHelper::checkMvBufferForMCTSConstraint( *cu.firstPU ) ) ) )
@@ -2599,7 +2621,9 @@ void EncCu::xCheckRDCostAffineMerge2Nx2N( CodingStructure *&tempCS, CodingStruct
     PredictionUnit pu( tempCS->area );
     pu.cu = &cu;
     pu.cs = tempCS;
-
+#if JVET_N0324_REGULAR_MRG_FLAG
+    pu.regularMergeFlag = false;
+#endif
     PU::getAffineMergeCand( pu, affineMergeCtx );
 
     if ( affineMergeCtx.numValidMergeCand <= 0 )
@@ -2675,6 +2699,9 @@ void EncCu::xCheckRDCostAffineMerge2Nx2N( CodingStructure *&tempCS, CodingStruct
         // set merge information
         pu.interDir = affineMergeCtx.interDirNeighbours[uiMergeCand];
         pu.mergeFlag = true;
+#if JVET_N0324_REGULAR_MRG_FLAG
+        pu.regularMergeFlag = false;
+#endif
         pu.mergeIdx = uiMergeCand;
         cu.affineType = affineMergeCtx.affineType[uiMergeCand];
         cu.GBiIdx = affineMergeCtx.GBiIdx[uiMergeCand];
@@ -2891,6 +2918,9 @@ void EncCu::xCheckRDCostIBCModeMerge2Nx2N(CodingStructure *&tempCS, CodingStruct
     pu.cs = tempCS;
     cu.mmvdSkip = false;
     pu.mmvdMergeFlag = false;
+#if JVET_N0324_REGULAR_MRG_FLAG
+    pu.regularMergeFlag = false;
+#endif
     cu.triangle = false;
     pu.shareParentPos = tempCS->sharedBndPos;
     pu.shareParentSize = tempCS->sharedBndSize;
@@ -2937,6 +2967,9 @@ void EncCu::xCheckRDCostIBCModeMerge2Nx2N(CodingStructure *&tempCS, CodingStruct
 #endif
       PredictionUnit &pu = tempCS->addPU(cu, partitioner.chType); //tempCS->addPU(cu);
       pu.mmvdMergeFlag = false;
+#if JVET_N0324_REGULAR_MRG_FLAG
+      pu.regularMergeFlag = false;
+#endif
       Picture* refPic = pu.cu->slice->getPic();
       const CPelBuf refBuf = refPic->getRecoBuf(pu.blocks[COMPONENT_Y]);
       const Pel*        piRefSrch = refBuf.buf;
@@ -3050,6 +3083,9 @@ void EncCu::xCheckRDCostIBCModeMerge2Nx2N(CodingStructure *&tempCS, CodingStruct
             pu.intraDir[1] = PLANAR_IDX; // set intra pred for ibc block
             cu.mmvdSkip = false;
             pu.mmvdMergeFlag = false;
+#if JVET_N0324_REGULAR_MRG_FLAG
+            pu.regularMergeFlag = false;
+#endif
             cu.triangle = false;
             mergeCtx.setMergeInfo(pu, mergeCand);
             PU::spanMotionInfo(pu, mergeCtx);
@@ -3136,7 +3172,9 @@ void EncCu::xCheckRDCostIBCMode(CodingStructure *&tempCS, CodingStructure *&best
     PredictionUnit& pu = *cu.firstPU;
     cu.mmvdSkip = false;
     pu.mmvdMergeFlag = false;
-
+#if JVET_N0324_REGULAR_MRG_FLAG
+    pu.regularMergeFlag = false;
+#endif
 #if JVET_N0843_BVP_SIMPLIFICATION
     pu.shareParentPos  = tempCS->sharedBndPos;
     pu.shareParentSize = tempCS->sharedBndSize;
diff --git a/source/Lib/EncoderLib/InterSearch.cpp b/source/Lib/EncoderLib/InterSearch.cpp
index 59e74f97b3..8f0aa171d8 100644
--- a/source/Lib/EncoderLib/InterSearch.cpp
+++ b/source/Lib/EncoderLib/InterSearch.cpp
@@ -2788,6 +2788,9 @@ void InterSearch::predInterSearch(CodingUnit& cu, Partitioner& partitioner)
         // set hevc me result
         cu.affine = false;
         pu.mergeFlag = bMergeFlag;
+#if JVET_N0324_REGULAR_MRG_FLAG
+        pu.regularMergeFlag = false;
+#endif
         pu.mergeIdx = uiMRGIndex;
         pu.interDir = uiInterDir;
         cu.smvdMode = iSymMode;
@@ -4296,7 +4299,9 @@ void InterSearch::xPredAffineInterSearch( PredictionUnit&       pu,
 
   pu.cu->affine = true;
   pu.mergeFlag = false;
-
+#if JVET_N0324_REGULAR_MRG_FLAG
+  pu.regularMergeFlag = false;
+#endif
   if( gbiIdx != GBI_DEFAULT )
   {
     pu.cu->GBiIdx = gbiIdx;
@@ -7016,14 +7021,27 @@ void InterSearch::encodeResAndCalcRdInterCU(CodingStructure &cs, Partitioner &pa
     }
     else
     {
+#if JVET_N0324_REGULAR_MRG_FLAG
+      if (pu.regularMergeFlag)
+      {
+        m_CABACEstimator->merge_idx(pu);
+      }
+      else
+      {
+#endif
     m_CABACEstimator->subblock_merge_flag( cu );
+#if !JVET_N0324_REGULAR_MRG_FLAG
     m_CABACEstimator->triangle_mode ( cu );
+#endif
     if (cu.mmvdSkip)
     {
       m_CABACEstimator->mmvd_merge_idx(pu);
     }
     else
     m_CABACEstimator->merge_idx     ( pu );
+#if JVET_N0324_REGULAR_MRG_FLAG
+      }
+#endif
     }
 
     cs.dist     = distortion;
@@ -7227,14 +7245,27 @@ uint64_t InterSearch::xGetSymbolFracBitsInter(CodingStructure &cs, Partitioner &
     }
 
     m_CABACEstimator->cu_skip_flag  ( cu );
+#if JVET_N0324_REGULAR_MRG_FLAG
+    if (cu.firstPU->regularMergeFlag)
+    {
+      m_CABACEstimator->merge_idx(*cu.firstPU);
+    }
+    else
+    {
+#endif
     m_CABACEstimator->subblock_merge_flag( cu );
+#if !JVET_N0324_REGULAR_MRG_FLAG
     m_CABACEstimator->triangle_mode ( cu );
+#endif
     if (cu.mmvdSkip)
     {
       m_CABACEstimator->mmvd_merge_idx(*cu.firstPU);
     }
     else
     m_CABACEstimator->merge_idx     ( *cu.firstPU );
+#if JVET_N0324_REGULAR_MRG_FLAG
+    }
+#endif
     fracBits   += m_CABACEstimator->getEstFracBits();
   }
   else
-- 
GitLab