From f3beea87986aa7db4a121d000036575ec1e58908 Mon Sep 17 00:00:00 2001
From: Frank Bossen <fbossen@gmail.com>
Date: Sat, 3 Sep 2022 11:03:45 -0400
Subject: [PATCH] Clean up MMVD related code

---
 source/Lib/CommonLib/CommonDef.h              |  27 +++-
 source/Lib/CommonLib/ContextModelling.cpp     |  33 ++--
 source/Lib/CommonLib/ContextModelling.h       |  10 +-
 source/Lib/CommonLib/Rom.cpp                  |   3 +
 source/Lib/CommonLib/Unit.cpp                 |   2 +-
 source/Lib/CommonLib/Unit.h                   |  26 ++--
 source/Lib/CommonLib/UnitTools.cpp            |   6 +-
 source/Lib/CommonLib/UnitTools.h              |   2 +-
 .../Lib/CommonLib/dtrace_blockstatistics.cpp  |   6 +-
 source/Lib/DecoderLib/CABACReader.cpp         |  29 +---
 source/Lib/DecoderLib/DecCu.cpp               |   5 +-
 source/Lib/EncoderLib/CABACWriter.cpp         |  19 ++-
 source/Lib/EncoderLib/EncCu.cpp               | 145 +++++++++---------
 13 files changed, 158 insertions(+), 155 deletions(-)

diff --git a/source/Lib/CommonLib/CommonDef.h b/source/Lib/CommonLib/CommonDef.h
index 238f9fb4d6..fbe683a8dc 100644
--- a/source/Lib/CommonLib/CommonDef.h
+++ b/source/Lib/CommonLib/CommonDef.h
@@ -351,13 +351,32 @@ static constexpr int LAST_SIGNIFICANT_GROUPS =                         14;
 
 static constexpr int AFFINE_SUBBLOCK_SIZE = 4;   // Minimum affine MC block size
 
-static constexpr int MMVD_REFINE_STEP =                                 8; ///< max number of distance step
-static constexpr int MMVD_MAX_REFINE_NUM =                              (MMVD_REFINE_STEP * 4); ///< max number of candidate from a base candidate
-static constexpr int MMVD_BASE_MV_NUM =                                 2; ///< max number of base candidate
-static constexpr int MMVD_ADD_NUM =                                     (MMVD_MAX_REFINE_NUM * MMVD_BASE_MV_NUM);///< total number of mmvd candidate
 static constexpr int MMVD_MRG_MAX_RD_NUM =                              MRG_MAX_NUM_CANDS;
 static constexpr int MMVD_MRG_MAX_RD_BUF_NUM =                          (MMVD_MRG_MAX_RD_NUM + 1);///< increase buffer size by 1
 
+union MmvdIdx
+{
+  using T = uint8_t;
+
+  static constexpr int LOG_REFINE_STEP = 3;
+  static constexpr int REFINE_STEP     = 1 << LOG_REFINE_STEP;
+  static constexpr int LOG_BASE_MV_NUM = 1;
+  static constexpr int BASE_MV_NUM     = 1 << LOG_BASE_MV_NUM;
+  static constexpr int MAX_REFINE_NUM  = 4 * REFINE_STEP;
+  static constexpr int ADD_NUM         = MAX_REFINE_NUM * BASE_MV_NUM;
+  static constexpr int INVALID         = std::numeric_limits<T>::max();
+
+  struct
+  {
+    T baseIdx : LOG_BASE_MV_NUM;
+    T step : LOG_REFINE_STEP;
+    T position : 2;
+  } pos;
+  T val;
+};
+
+static_assert(sizeof(MmvdIdx::val) == sizeof(MmvdIdx::pos), "MmvdIdx::val is not wide enough");
+
 static constexpr int MAX_TU_LEVEL_CTX_CODED_BIN_CONSTRAINT_LUMA =      28;
 static constexpr int MAX_TU_LEVEL_CTX_CODED_BIN_CONSTRAINT_CHROMA =    28;
 
diff --git a/source/Lib/CommonLib/ContextModelling.cpp b/source/Lib/CommonLib/ContextModelling.cpp
index 317ad46982..6b533676bc 100644
--- a/source/Lib/CommonLib/ContextModelling.cpp
+++ b/source/Lib/CommonLib/ContextModelling.cpp
@@ -411,16 +411,9 @@ void MergeCtx::setMergeInfo( PredictionUnit& pu, int candIdx )
   pu.mmvdEncOptMode = 0;
 }
 
-void MergeCtx::setMmvdMergeCandiInfo(PredictionUnit& pu, int candIdx)
+void MergeCtx::setMmvdMergeCandiInfo(PredictionUnit &pu, const MmvdIdx candIdx)
 {
   const Slice &slice = *pu.cs->slice;
-  const int mvShift = MV_FRACTIONAL_BITS_DIFF;
-  const int refMvdCands[8] = { 1 << mvShift , 2 << mvShift , 4 << mvShift , 8 << mvShift , 16 << mvShift , 32 << mvShift,  64 << mvShift , 128 << mvShift };
-  int fPosGroup = 0;
-  int fPosBaseIdx = 0;
-  int fPosStep = 0;
-  int tempIdx = 0;
-  int fPosPosition = 0;
   Mv tempMv[2];
 
 #if GDR_ENABLED
@@ -428,14 +421,11 @@ void MergeCtx::setMmvdMergeCandiInfo(PredictionUnit& pu, int candIdx)
   const bool isEncodeGdrClean = cs.sps->getGDREnabledFlag() && cs.pcv->isEncoder && ((cs.picHeader->getInGdrInterval() && cs.isClean(pu.Y().topRight(), CHANNEL_TYPE_LUMA)) || (cs.picHeader->getNumVerVirtualBoundaries() == 0));
 #endif
 
-  tempIdx = candIdx;
-  fPosGroup = tempIdx / (MMVD_BASE_MV_NUM * MMVD_MAX_REFINE_NUM);
-  tempIdx = tempIdx - fPosGroup * (MMVD_BASE_MV_NUM * MMVD_MAX_REFINE_NUM);
-  fPosBaseIdx = tempIdx / MMVD_MAX_REFINE_NUM;
-  tempIdx = tempIdx - fPosBaseIdx * (MMVD_MAX_REFINE_NUM);
-  fPosStep = tempIdx / 4;
-  fPosPosition = tempIdx - fPosStep * (4);
-  int offset = refMvdCands[fPosStep];
+  const int fPosBaseIdx  = candIdx.pos.baseIdx;
+  const int fPosStep     = candIdx.pos.step;
+  const int fPosPosition = candIdx.pos.position;
+
+  int offset = 1 << (fPosStep + MV_FRACTIONAL_BITS_DIFF);
   if ( pu.cu->slice->getPicHeader()->getDisFracMMVD() )
   {
     offset <<= 2;
@@ -625,12 +615,13 @@ void MergeCtx::setMmvdMergeCandiInfo(PredictionUnit& pu, int candIdx)
 #endif
   }
 
-  pu.mmvdMergeFlag = true;
-  pu.mmvdMergeIdx = candIdx;
-  pu.mergeFlag = true;
+  pu.mmvdMergeFlag    = true;
+  pu.mmvdMergeIdx     = candIdx;
+  pu.mergeFlag        = true;
   pu.regularMergeFlag = true;
-  pu.mergeIdx = candIdx;
-  pu.mergeType = MRG_TYPE_DEFAULT_N;
+  pu.mergeIdx         = candIdx.val;
+  pu.mergeType        = MRG_TYPE_DEFAULT_N;
+
   pu.mvd[REF_PIC_LIST_0] = Mv();
   pu.mvd[REF_PIC_LIST_1] = Mv();
   pu.mvpIdx[REF_PIC_LIST_0] = NOT_VALID;
diff --git a/source/Lib/CommonLib/ContextModelling.h b/source/Lib/CommonLib/ContextModelling.h
index e56515b81b..1891741e68 100644
--- a/source/Lib/CommonLib/ContextModelling.h
+++ b/source/Lib/CommonLib/ContextModelling.h
@@ -619,13 +619,13 @@ public:
 
   MotionBuf     subPuMvpMiBuf;
   MotionBuf     subPuMvpExtMiBuf;
-  MvField mmvdBaseMv[MMVD_BASE_MV_NUM][2];
+  MvField       mmvdBaseMv[MmvdIdx::BASE_MV_NUM][2];
 #if GDR_ENABLED
-  bool          mmvdSolid[MMVD_BASE_MV_NUM][2];
-  bool          mmvdValid[MMVD_BASE_MV_NUM][2];
+  bool mmvdSolid[MmvdIdx::BASE_MV_NUM][2];
+  bool mmvdValid[MmvdIdx::BASE_MV_NUM][2];
 #endif
-  void setMmvdMergeCandiInfo(PredictionUnit& pu, int candIdx);
-  bool          mmvdUseAltHpelIf  [ MMVD_BASE_MV_NUM ];
+  void          setMmvdMergeCandiInfo(PredictionUnit &pu, MmvdIdx candIdx);
+  bool          mmvdUseAltHpelIf[MmvdIdx::BASE_MV_NUM];
   bool          useAltHpelIf      [ MRG_MAX_NUM_CANDS ];
   void setMergeInfo( PredictionUnit& pu, int candIdx );
 };
diff --git a/source/Lib/CommonLib/Rom.cpp b/source/Lib/CommonLib/Rom.cpp
index b88e90ae46..ecb5702f41 100644
--- a/source/Lib/CommonLib/Rom.cpp
+++ b/source/Lib/CommonLib/Rom.cpp
@@ -44,6 +44,9 @@
 #include <math.h>
 #include <iomanip>
 
+constexpr int MmvdIdx::ADD_NUM;
+constexpr int MmvdIdx::BASE_MV_NUM;
+
 // ====================================================================================================================
 // Initialize / destroy functions
 // ====================================================================================================================
diff --git a/source/Lib/CommonLib/Unit.cpp b/source/Lib/CommonLib/Unit.cpp
index cab7cd4aae..2b113f8380 100644
--- a/source/Lib/CommonLib/Unit.cpp
+++ b/source/Lib/CommonLib/Unit.cpp
@@ -542,7 +542,7 @@ void PredictionUnit::initData()
   geoMergeIdx0 = MAX_UCHAR;
   geoMergeIdx1 = MAX_UCHAR;
   mmvdMergeFlag = false;
-  mmvdMergeIdx = MAX_UINT;
+  mmvdMergeIdx.val = MmvdIdx::INVALID;
   interDir    = MAX_UCHAR;
   mergeType   = MRG_TYPE_DEFAULT_N;
   bv.setZero();
diff --git a/source/Lib/CommonLib/Unit.h b/source/Lib/CommonLib/Unit.h
index 5f7e1b8d79..b86e9089ab 100644
--- a/source/Lib/CommonLib/Unit.h
+++ b/source/Lib/CommonLib/Unit.h
@@ -383,19 +383,19 @@ struct IntraPredictionData
 
 struct InterPredictionData
 {
-  bool      mergeFlag;
-  bool      regularMergeFlag;
-  uint8_t     mergeIdx;
-  uint8_t     geoSplitDir;
-  uint8_t     geoMergeIdx0;
-  uint8_t     geoMergeIdx1;
-  bool           mmvdMergeFlag;
-  uint32_t       mmvdMergeIdx;
-  uint8_t     interDir;
-  uint8_t     mvpIdx  [NUM_REF_PIC_LIST_01];
-  uint8_t     mvpNum  [NUM_REF_PIC_LIST_01];
-  Mv        mvd     [NUM_REF_PIC_LIST_01];
-  Mv        mv      [NUM_REF_PIC_LIST_01];
+  bool    mergeFlag;
+  bool    regularMergeFlag;
+  uint8_t mergeIdx;
+  uint8_t geoSplitDir;
+  uint8_t geoMergeIdx0;
+  uint8_t geoMergeIdx1;
+  bool    mmvdMergeFlag;
+  MmvdIdx mmvdMergeIdx;
+  uint8_t interDir;
+  uint8_t mvpIdx[NUM_REF_PIC_LIST_01];
+  uint8_t mvpNum[NUM_REF_PIC_LIST_01];
+  Mv      mvd[NUM_REF_PIC_LIST_01];
+  Mv      mv[NUM_REF_PIC_LIST_01];
 #if GDR_ENABLED
   bool      mvSolid[NUM_REF_PIC_LIST_01];
   bool      mvValid[NUM_REF_PIC_LIST_01];
diff --git a/source/Lib/CommonLib/UnitTools.cpp b/source/Lib/CommonLib/UnitTools.cpp
index 5f8e1adce6..74c0473a33 100644
--- a/source/Lib/CommonLib/UnitTools.cpp
+++ b/source/Lib/CommonLib/UnitTools.cpp
@@ -1752,7 +1752,7 @@ int PU::getDistScaleFactor(const int &currPOC, const int &currRefPOC, const int
   return xGetDistScaleFactor(currPOC, currRefPOC, colPOC, colRefPOC);
 }
 
-void PU::getInterMMVDMergeCandidates(const PredictionUnit &pu, MergeCtx& mrgCtx, const int& mrgCandIdx)
+void PU::getInterMMVDMergeCandidates(const PredictionUnit &pu, MergeCtx &mrgCtx)
 {
   int refIdxList0, refIdxList1;
   int k;
@@ -1765,7 +1765,7 @@ void PU::getInterMMVDMergeCandidates(const PredictionUnit &pu, MergeCtx& mrgCtx,
 #endif
 
 #if GDR_ENABLED
-  for (int k = 0; k < MMVD_BASE_MV_NUM; k++)
+  for (int k = 0; k < MmvdIdx::BASE_MV_NUM; k++)
   {
     mrgCtx.mmvdSolid[k][0] = true;
     mrgCtx.mmvdSolid[k][1] = true;
@@ -1818,7 +1818,7 @@ void PU::getInterMMVDMergeCandidates(const PredictionUnit &pu, MergeCtx& mrgCtx,
 
     currBaseNum++;
 
-    if (currBaseNum == MMVD_BASE_MV_NUM)
+    if (currBaseNum == MmvdIdx::BASE_MV_NUM)
     {
       break;
     }
diff --git a/source/Lib/CommonLib/UnitTools.h b/source/Lib/CommonLib/UnitTools.h
index 20f9c5128c..199f2286c6 100644
--- a/source/Lib/CommonLib/UnitTools.h
+++ b/source/Lib/CommonLib/UnitTools.h
@@ -151,7 +151,7 @@ namespace PU
 
   void getInterMergeCandidates(const PredictionUnit &pu, MergeCtx &mrgCtx, int mmvdList, const int &mrgCandIdx = -1);
   void getIBCMergeCandidates          (const PredictionUnit &pu, MergeCtx& mrgCtx, const int& mrgCandIdx = -1);
-  void getInterMMVDMergeCandidates(const PredictionUnit &pu, MergeCtx& mrgCtx, const int& mrgCandIdx = -1);
+  void getInterMMVDMergeCandidates(const PredictionUnit &pu, MergeCtx &mrgCtx);
   int getDistScaleFactor(const int &currPOC, const int &currRefPOC, const int &colPOC, const int &colRefPOC);
   bool isDiffMER                      (const Position &pos1, const Position &pos2, const unsigned plevel);
   bool getColocatedMVP                (const PredictionUnit &pu, const RefPicList &eRefPicList, const Position &pos, Mv& rcMv, const int &refIdx, bool sbFlag);
diff --git a/source/Lib/CommonLib/dtrace_blockstatistics.cpp b/source/Lib/CommonLib/dtrace_blockstatistics.cpp
index 0e9da1860b..a747b941e2 100644
--- a/source/Lib/CommonLib/dtrace_blockstatistics.cpp
+++ b/source/Lib/CommonLib/dtrace_blockstatistics.cpp
@@ -598,7 +598,8 @@ void writeAllData(const CodingStructure& cs, const UnitArea& ctuArea)
               DTRACE_BLOCK_SCALAR(g_trace_ctx, D_BLOCK_STATISTICS_ALL, pu, GetBlockStatisticName(BlockStatistic::MMVDMergeFlag),  pu.mmvdMergeFlag);
               if (cu.mmvdSkip || pu.mmvdMergeFlag)
               {
-              DTRACE_BLOCK_SCALAR(g_trace_ctx, D_BLOCK_STATISTICS_ALL, pu, GetBlockStatisticName(BlockStatistic::MMVDMergeIdx),  pu.mmvdMergeIdx);
+                DTRACE_BLOCK_SCALAR(g_trace_ctx, D_BLOCK_STATISTICS_ALL, pu,
+                                    GetBlockStatisticName(BlockStatistic::MMVDMergeIdx), pu.mmvdMergeIdx.val);
               }
               DTRACE_BLOCK_SCALAR(g_trace_ctx, D_BLOCK_STATISTICS_ALL, pu, GetBlockStatisticName(BlockStatistic::CiipFlag),  pu.ciipFlag);
               if (pu.ciipFlag)
@@ -1039,7 +1040,8 @@ void writeAllCodedData(const CodingStructure & cs, const UnitArea & ctuArea)
               DTRACE_BLOCK_SCALAR(g_trace_ctx, D_BLOCK_STATISTICS_CODED, pu, GetBlockStatisticName(BlockStatistic::MMVDMergeFlag), pu.mmvdMergeFlag);
               if (pu.mmvdMergeFlag)
               {
-                DTRACE_BLOCK_SCALAR(g_trace_ctx, D_BLOCK_STATISTICS_CODED, pu, GetBlockStatisticName(BlockStatistic::MMVDMergeIdx), pu.mmvdMergeIdx);
+                DTRACE_BLOCK_SCALAR(g_trace_ctx, D_BLOCK_STATISTICS_CODED, pu,
+                                    GetBlockStatisticName(BlockStatistic::MMVDMergeIdx), pu.mmvdMergeIdx.val);
               }
               if (!cu.cs->slice->isIntra() && cu.cs->sps->getUseAffine() && cu.lumaSize().width >= 8 && cu.lumaSize().height >= 8
                 && !pu.mmvdMergeFlag && !cu.mmvdSkip
diff --git a/source/Lib/DecoderLib/CABACReader.cpp b/source/Lib/DecoderLib/CABACReader.cpp
index f45dbe642e..b4e58e8bc0 100644
--- a/source/Lib/DecoderLib/CABACReader.cpp
+++ b/source/Lib/DecoderLib/CABACReader.cpp
@@ -2440,16 +2440,16 @@ void CABACReader::mmvd_merge_idx(PredictionUnit& pu)
   int var0 = 0;
   if (pu.cs->sps->getMaxNumMergeCand() > 1)
   {
-    static_assert(MMVD_BASE_MV_NUM == 2, "");
+    static_assert(MmvdIdx::BASE_MV_NUM == 2, "");
     var0 = m_binDecoder.decodeBin(Ctx::MmvdMergeIdx());
   }
   DTRACE(g_trace_ctx, D_SYNTAX, "base_mvp_idx() base_mvp_idx=%d\n", var0);
-  int numCandminus1_step = MMVD_REFINE_STEP - 1;
+  int numStepCandMinus1 = MmvdIdx::REFINE_STEP - 1;
   int var1 = 0;
   if (m_binDecoder.decodeBin(Ctx::MmvdStepMvpIdx()))
   {
     var1++;
-    for (; var1 < numCandminus1_step; var1++)
+    for (; var1 < numStepCandMinus1; var1++)
     {
       if (!m_binDecoder.decodeBinEP())
       {
@@ -2458,26 +2458,11 @@ void CABACReader::mmvd_merge_idx(PredictionUnit& pu)
     }
   }
   DTRACE(g_trace_ctx, D_SYNTAX, "MmvdStepMvpIdx() MmvdStepMvpIdx=%d\n", var1);
-  int var2 = 0;
-  if (m_binDecoder.decodeBinEP())
-  {
-    var2 += 2;
-    if (m_binDecoder.decodeBinEP())
-    {
-      var2 += 1;
-    }
-  }
-  else
-  {
-    var2 += 0;
-    if (m_binDecoder.decodeBinEP())
-    {
-      var2 += 1;
-    }
-  }
+  const int var2 = m_binDecoder.decodeBinsEP(2);
   DTRACE(g_trace_ctx, D_SYNTAX, "pos() pos=%d\n", var2);
-  int mvpIdx = (var0 * MMVD_MAX_REFINE_NUM + var1 * 4 + var2);
-  pu.mmvdMergeIdx = mvpIdx;
+  pu.mmvdMergeIdx.pos.position = var2;
+  pu.mmvdMergeIdx.pos.step     = var1;
+  pu.mmvdMergeIdx.pos.baseIdx  = var0;
   DTRACE(g_trace_ctx, D_SYNTAX, "mmvd_merge_idx() mmvd_merge_idx=%d\n", pu.mmvdMergeIdx);
 }
 
diff --git a/source/Lib/DecoderLib/DecCu.cpp b/source/Lib/DecoderLib/DecCu.cpp
index d93c0a3fec..8b04e45482 100644
--- a/source/Lib/DecoderLib/DecCu.cpp
+++ b/source/Lib/DecoderLib/DecCu.cpp
@@ -850,9 +850,8 @@ void DecCu::xDeriveCuMvs(CodingUnit &cu)
           mrgCtx.subPuMvpMiBuf = MotionBuf(m_SubPuMiBuf, bufSize);
         }
 
-        int   fPosBaseIdx = pu.mmvdMergeIdx / MMVD_MAX_REFINE_NUM;
-        PU::getInterMergeCandidates(pu, mrgCtx, 1, fPosBaseIdx + 1);
-        PU::getInterMMVDMergeCandidates(pu, mrgCtx, pu.mmvdMergeIdx);
+        PU::getInterMergeCandidates(pu, mrgCtx, 1, pu.mmvdMergeIdx.pos.baseIdx + 1);
+        PU::getInterMMVDMergeCandidates(pu, mrgCtx);
         mrgCtx.setMmvdMergeCandiInfo(pu, pu.mmvdMergeIdx);
 
         PU::spanMotionInfo(pu, mrgCtx);
diff --git a/source/Lib/EncoderLib/CABACWriter.cpp b/source/Lib/EncoderLib/CABACWriter.cpp
index ecb4cf092f..032cec744d 100644
--- a/source/Lib/EncoderLib/CABACWriter.cpp
+++ b/source/Lib/EncoderLib/CABACWriter.cpp
@@ -2114,21 +2114,20 @@ void CABACWriter::merge_idx( const PredictionUnit& pu )
 }
 void CABACWriter::mmvd_merge_idx(const PredictionUnit& pu)
 {
-  int var0, var1, var2;
-  int mvpIdx = pu.mmvdMergeIdx;
-  var0 = mvpIdx / MMVD_MAX_REFINE_NUM;
-  var1 = (mvpIdx - (var0 * MMVD_MAX_REFINE_NUM)) / 4;
-  var2 = mvpIdx - (var0 * MMVD_MAX_REFINE_NUM) - var1 * 4;
+  const int var0 = pu.mmvdMergeIdx.pos.baseIdx;
+  const int var1 = pu.mmvdMergeIdx.pos.step;
+  const int var2 = pu.mmvdMergeIdx.pos.position;
+
   if (pu.cs->sps->getMaxNumMergeCand() > 1)
   {
-    static_assert(MMVD_BASE_MV_NUM == 2, "");
+    static_assert(MmvdIdx::BASE_MV_NUM == 2, "");
     assert(var0 < 2);
     m_binEncoder.encodeBin(var0, Ctx::MmvdMergeIdx());
   }
   DTRACE(g_trace_ctx, D_SYNTAX, "base_mvp_idx() base_mvp_idx=%d\n", var0);
 
-  int numCandminus1_step = MMVD_REFINE_STEP - 1;
-  if (numCandminus1_step > 0)
+  int numStepCandMinus1 = MmvdIdx::REFINE_STEP - 1;
+  if (numStepCandMinus1 > 0)
   {
     if (var1 == 0)
     {
@@ -2137,7 +2136,7 @@ void CABACWriter::mmvd_merge_idx(const PredictionUnit& pu)
     else
     {
       m_binEncoder.encodeBin(1, Ctx::MmvdStepMvpIdx());
-      for (unsigned idx = 1; idx < numCandminus1_step; idx++)
+      for (unsigned idx = 1; idx < numStepCandMinus1; idx++)
       {
         m_binEncoder.encodeBinEP(var1 == idx ? 0 : 1);
         if (var1 == idx)
@@ -2152,7 +2151,7 @@ void CABACWriter::mmvd_merge_idx(const PredictionUnit& pu)
   m_binEncoder.encodeBinsEP(var2, 2);
 
   DTRACE(g_trace_ctx, D_SYNTAX, "pos() pos=%d\n", var2);
-  DTRACE(g_trace_ctx, D_SYNTAX, "mmvd_merge_idx() mmvd_merge_idx=%d\n", pu.mmvdMergeIdx);
+  DTRACE(g_trace_ctx, D_SYNTAX, "mmvd_merge_idx() mmvd_merge_idx=%d\n", pu.mmvdMergeIdx.val);
 }
 
 void CABACWriter::inter_pred_idc( const PredictionUnit& pu )
diff --git a/source/Lib/EncoderLib/EncCu.cpp b/source/Lib/EncoderLib/EncCu.cpp
index 50b44b70da..f70ab559c4 100644
--- a/source/Lib/EncoderLib/EncCu.cpp
+++ b/source/Lib/EncoderLib/EncCu.cpp
@@ -2242,8 +2242,8 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
     isEncodeGdrClean = cs->sps->getGDREnabledFlag() && cs->pcv->isEncoder && ((cs->picHeader->getInGdrInterval() && cs->isClean(pu.Y().topRight(), CHANNEL_TYPE_LUMA)) || (cs->picHeader->getNumVerVirtualBoundaries() == 0));
 #endif
   }
-  bool candHasNoResidual[MRG_MAX_NUM_CANDS + MMVD_ADD_NUM];
-  for (uint32_t ui = 0; ui < MRG_MAX_NUM_CANDS + MMVD_ADD_NUM; ui++)
+  bool candHasNoResidual[MRG_MAX_NUM_CANDS + MmvdIdx::ADD_NUM];
+  for (uint32_t ui = 0; ui < MRG_MAX_NUM_CANDS + MmvdIdx::ADD_NUM; ui++)
   {
     candHasNoResidual[ui] = false;
   }
@@ -2256,7 +2256,7 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
   PelUnitBuf *acMergeTempBuffer[MMVD_MRG_MAX_RD_NUM];
   PelUnitBuf *singleMergeTempBuffer;
   int         insertPos;
-  unsigned    uiNumMrgSATDCand = mergeCtx.numValidMergeCand + MMVD_ADD_NUM;
+  unsigned    numMergeSatdCand = mergeCtx.numValidMergeCand + MmvdIdx::ADD_NUM;
 
   struct ModeInfo
   {
@@ -2269,26 +2269,24 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
       mergeCand(mergeCand), isRegularMerge(isRegularMerge), isMMVD(isMMVD), isCIIP(isCIIP) {}
   };
 
-  static_vector<ModeInfo, MRG_MAX_NUM_CANDS + MMVD_ADD_NUM>  RdModeList;
+  static_vector<ModeInfo, MRG_MAX_NUM_CANDS + MmvdIdx::ADD_NUM> rdModeList;
 
-  bool      mrgTempBufSet = false;
-  const int candNum =
-    mergeCtx.numValidMergeCand
-    + (tempCS->sps->getUseMMVD() ? std::min<int>(MMVD_BASE_MV_NUM, mergeCtx.numValidMergeCand) * MMVD_MAX_REFINE_NUM
-                                 : 0);
+  for (int i = 0; i < mergeCtx.numValidMergeCand; i++)
+  {
+    rdModeList.push_back(ModeInfo(i, true, false, false));
+  }
 
-  for (int i = 0; i < candNum; i++)
+  if (tempCS->sps->getUseMMVD())
   {
-    if (i < mergeCtx.numValidMergeCand)
-    {
-      RdModeList.push_back(ModeInfo(i, true, false, false));
-    }
-    else
+    const int numMmvdCand = std::min<int>(MmvdIdx::BASE_MV_NUM, mergeCtx.numValidMergeCand) * MmvdIdx::MAX_REFINE_NUM;
+    for (int i = 0; i < numMmvdCand; i++)
     {
-      RdModeList.push_back(ModeInfo(std::min(MMVD_ADD_NUM, i - mergeCtx.numValidMergeCand), false, true, false));
+      rdModeList.push_back(ModeInfo(i, false, true, false));
     }
   }
 
+  bool mrgTempBufSet = false;
+
   const UnitArea localUnitArea(tempCS->area.chromaFormat, Area(0, 0, tempCS->area.Y().width, tempCS->area.Y().height));
   for (unsigned i = 0; i < MMVD_MRG_MAX_RD_BUF_NUM; i++)
   {
@@ -2315,10 +2313,10 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
   }
   if( m_pcEncCfg->getUseFastMerge() || isIntrainterEnabled)
   {
-    uiNumMrgSATDCand = NUM_MRG_SATD_CAND;
+    numMergeSatdCand = NUM_MRG_SATD_CAND;
     if (isIntrainterEnabled)
     {
-      uiNumMrgSATDCand += 1;
+      numMergeSatdCand += 1;
     }
     bestIsSkip       = false;
 
@@ -2339,12 +2337,12 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
       bestIsSkip = false;
     }
 
-    static_vector<double, MRG_MAX_NUM_CANDS + MMVD_ADD_NUM> candCostList;
+    static_vector<double, MRG_MAX_NUM_CANDS + MmvdIdx::ADD_NUM> candCostList;
 
     // 1. Pass: get SATD-cost for selected candidates and reduce their count
     if( !bestIsSkip )
     {
-      RdModeList.clear();
+      rdModeList.clear();
       mrgTempBufSet       = true;
       const TempCtx ctxStart(m_ctxPool, m_CABACEstimator->getCtx());
 
@@ -2444,16 +2442,17 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
           }
         }
 #endif
-        updateCandList(ModeInfo(uiMergeCand, true, false, false), cost, RdModeList, candCostList, uiNumMrgSATDCand, &insertPos);
+        updateCandList(ModeInfo(uiMergeCand, true, false, false), cost, rdModeList, candCostList, numMergeSatdCand,
+                       &insertPos);
         if (insertPos != -1)
         {
-          if (insertPos == RdModeList.size() - 1)
+          if (insertPos == rdModeList.size() - 1)
           {
             swap(singleMergeTempBuffer, acMergeTempBuffer[insertPos]);
           }
           else
           {
-            for (uint32_t i = uint32_t(RdModeList.size()) - 1; i > insertPos; i--)
+            for (uint32_t i = uint32_t(rdModeList.size()) - 1; i > insertPos; i--)
             {
               swap(acMergeTempBuffer[i - 1], acMergeTempBuffer[i]);
             }
@@ -2461,7 +2460,7 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
           }
         }
 #if !GDR_ENABLED
-        CHECK(std::min(uiMergeCand + 1, uiNumMrgSATDCand) != RdModeList.size(), "");
+        CHECK(std::min(uiMergeCand + 1, numMergeSatdCand) != rdModeList.size(), "");
 #endif
       }
 
@@ -2474,7 +2473,7 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
         uint32_t CiipMergeCand[NUM_MRG_SATD_CAND];
         for (uint32_t mergeCnt = 0; mergeCnt < std::min(NUM_MRG_SATD_CAND, (const int)mergeCtx.numValidMergeCand); mergeCnt++)
         {
-          CiipMergeCand[mergeCnt] = RdModeList[mergeCnt].mergeCand;
+          CiipMergeCand[mergeCnt] = rdModeList[mergeCnt].mergeCand;
         }
         for (uint32_t mergeCnt = 0; mergeCnt < std::min(std::min(NUM_MRG_SATD_CAND, (const int)mergeCtx.numValidMergeCand), 4); mergeCnt++)
         {
@@ -2554,10 +2553,11 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
 #endif
 
           insertPos = -1;
-          updateCandList(ModeInfo(mergeCand, false, false, true), cost, RdModeList, candCostList, uiNumMrgSATDCand, &insertPos);
+          updateCandList(ModeInfo(mergeCand, false, false, true), cost, rdModeList, candCostList, numMergeSatdCand,
+                         &insertPos);
           if (insertPos != -1)
           {
-            for (int i = int(RdModeList.size()) - 1; i > insertPos; i--)
+            for (int i = int(rdModeList.size()) - 1; i > insertPos; i--)
             {
               swap(acMergeTempBuffer[i - 1], acMergeTempBuffer[i]);
             }
@@ -2570,12 +2570,13 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
       {
         cu.mmvdSkip = true;
         pu.regularMergeFlag = true;
-        const int tempNum = (mergeCtx.numValidMergeCand > 1) ? MMVD_ADD_NUM : MMVD_ADD_NUM >> 1;
+        const int tempNum   = (mergeCtx.numValidMergeCand > 1) ? MmvdIdx::ADD_NUM : MmvdIdx::ADD_NUM >> 1;
         for (int mmvdMergeCand = 0; mmvdMergeCand < tempNum; mmvdMergeCand++)
         {
-          int baseIdx = mmvdMergeCand / MMVD_MAX_REFINE_NUM;
-          int refineStep = (mmvdMergeCand - (baseIdx * MMVD_MAX_REFINE_NUM)) / 4;
-          if (refineStep >= m_pcEncCfg->getMmvdDisNum())
+          MmvdIdx mmvdIdx;
+          mmvdIdx.val = mmvdMergeCand;
+
+          if (mmvdIdx.pos.step >= m_pcEncCfg->getMmvdDisNum())
           {
             continue;
           }
@@ -2589,12 +2590,12 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
             pu.mvValid[REF_PIC_LIST_1] = true;
           }
 #endif
-          mergeCtx.setMmvdMergeCandiInfo(pu, mmvdMergeCand);
+          mergeCtx.setMmvdMergeCandiInfo(pu, mmvdIdx);
 
           PU::spanMotionInfo(pu, mergeCtx);
           pu.mvRefine = true;
           distParam.cur = singleMergeTempBuffer->Y();
-          pu.mmvdEncOptMode = (refineStep > 2 ? 2 : 1);
+          pu.mmvdEncOptMode = (mmvdIdx.pos.step > 2 ? 2 : 1);
           CHECK(!pu.mmvdMergeFlag, "MMVD merge should be set");
           // Don't do chroma MC here
           m_pcInterSearch->motionCompensation(pu, *singleMergeTempBuffer, REF_PIC_LIST_X, true, false, nullptr);
@@ -2631,10 +2632,11 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
             }
           }
 #endif
-          updateCandList(ModeInfo(mmvdMergeCand, false, true, false), cost, RdModeList, candCostList, uiNumMrgSATDCand, &insertPos);
+          updateCandList(ModeInfo(mmvdMergeCand, false, true, false), cost, rdModeList, candCostList, numMergeSatdCand,
+                         &insertPos);
           if (insertPos != -1)
           {
-            for (int i = int(RdModeList.size()) - 1; i > insertPos; i--)
+            for (int i = int(rdModeList.size()) - 1; i > insertPos; i--)
             {
               swap(acMergeTempBuffer[i - 1], acMergeTempBuffer[i]);
             }
@@ -2643,11 +2645,11 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
         }
       }
       // Try to limit number of candidates using SATD-costs
-      for( uint32_t i = 1; i < uiNumMrgSATDCand; i++ )
+      for (uint32_t i = 1; i < numMergeSatdCand; i++)
       {
         if( candCostList[i] > MRG_FAST_RATIO * candCostList[0] )
         {
-          uiNumMrgSATDCand = i;
+          numMergeSatdCand = i;
           break;
         }
       }
@@ -2657,9 +2659,9 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
       if (isIntrainterEnabled && isChromaEnabled(pu.cs->pcv->chrFormat))
       {
         pu.ciipFlag = true;
-        for (uint32_t mergeCnt = 0; mergeCnt < uiNumMrgSATDCand; mergeCnt++)
+        for (uint32_t mergeCnt = 0; mergeCnt < numMergeSatdCand; mergeCnt++)
         {
-          if (RdModeList[mergeCnt].isCIIP)
+          if (rdModeList[mergeCnt].isCIIP)
           {
             pu.intraDir[0] = PLANAR_IDX;
             pu.intraDir[1] = DM_CHROMA_IDX;
@@ -2687,11 +2689,12 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
     {
       if (bestIsMMVDSkip)
       {
-        uiNumMrgSATDCand = mergeCtx.numValidMergeCand + ((mergeCtx.numValidMergeCand > 1) ? MMVD_ADD_NUM : MMVD_ADD_NUM >> 1);
+        numMergeSatdCand =
+          mergeCtx.numValidMergeCand + ((mergeCtx.numValidMergeCand > 1) ? MmvdIdx::ADD_NUM : MmvdIdx::ADD_NUM >> 1);
       }
       else
       {
-        uiNumMrgSATDCand = mergeCtx.numValidMergeCand;
+        numMergeSatdCand = mergeCtx.numValidMergeCand;
       }
     }
   }
@@ -2701,11 +2704,11 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
   iteration = 2;
   for (uint32_t uiNoResidualPass = iterationBegin; uiNoResidualPass < iteration; ++uiNoResidualPass)
   {
-    for( uint32_t uiMrgHADIdx = 0; uiMrgHADIdx < uiNumMrgSATDCand; uiMrgHADIdx++ )
+    for (uint32_t uiMrgHADIdx = 0; uiMrgHADIdx < numMergeSatdCand; uiMrgHADIdx++)
     {
-      uint32_t uiMergeCand = RdModeList[uiMrgHADIdx].mergeCand;
+      uint32_t uiMergeCand = rdModeList[uiMrgHADIdx].mergeCand;
 
-      if (uiNoResidualPass != 0 && RdModeList[uiMrgHADIdx].isCIIP) // intrainter does not support skip mode
+      if (uiNoResidualPass != 0 && rdModeList[uiMrgHADIdx].isCIIP)   // intrainter does not support skip mode
       {
         if (isTestSkipMerge[uiMergeCand])
         {
@@ -2734,7 +2737,7 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
       cu.qp               = encTestMode.qp;
       PredictionUnit &pu  = tempCS->addPU( cu, partitioner.chType );
 
-      if (uiNoResidualPass == 0 && RdModeList[uiMrgHADIdx].isCIIP)
+      if (uiNoResidualPass == 0 && rdModeList[uiMrgHADIdx].isCIIP)
       {
         cu.mmvdSkip = false;
         mergeCtx.setMergeInfo(pu, uiMergeCand);
@@ -2744,11 +2747,13 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
         CHECK(pu.intraDir[0]<0 || pu.intraDir[0]>(NUM_LUMA_MODE - 1), "out of intra mode");
         pu.intraDir[1] = DM_CHROMA_IDX;
       }
-      else if (RdModeList[uiMrgHADIdx].isMMVD)
+      else if (rdModeList[uiMrgHADIdx].isMMVD)
       {
         cu.mmvdSkip = true;
         pu.regularMergeFlag = true;
-        mergeCtx.setMmvdMergeCandiInfo(pu, uiMergeCand);
+        MmvdIdx mmvdIdx;
+        mmvdIdx.val = uiMergeCand;
+        mergeCtx.setMmvdMergeCandiInfo(pu, mmvdIdx);
       }
       else
       {
@@ -2818,12 +2823,12 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
         }
         else
         {
-          if (RdModeList[uiMrgHADIdx].isMMVD)
+          if (rdModeList[uiMrgHADIdx].isMMVD)
           {
             pu.mmvdEncOptMode = 0;
             m_pcInterSearch->motionCompensatePu(pu, REF_PIC_LIST_X, true, true);
           }
-          else if (uiNoResidualPass != 0 && RdModeList[uiMrgHADIdx].isCIIP)
+          else if (uiNoResidualPass != 0 && rdModeList[uiMrgHADIdx].isCIIP)
           {
             tempCS->getPredBuf().copyFrom(acMergeBuffer[uiMergeCand]);
           }
@@ -3249,7 +3254,7 @@ void EncCu::xCheckRDCostMergeGeo2Nx2N(CodingStructure *&tempCS, CodingStructure
       pu.geoMergeIdx0     = (uint8_t) comboList.list[candidateIdx].mergeIdx0;
       pu.geoMergeIdx1     = (uint8_t) comboList.list[candidateIdx].mergeIdx1;
       pu.mmvdMergeFlag    = false;
-      pu.mmvdMergeIdx     = MAX_UINT;
+      pu.mmvdMergeIdx.val = MmvdIdx::INVALID;
 
       PU::spanGeoMotionInfo(pu, mergeCtx, pu.geoSplitDir, pu.geoMergeIdx0, pu.geoMergeIdx1);
       PelUnitBuf geoBuf = m_geoWeightedBuffers[candidateIdx].getBuf(localUnitArea);
@@ -3341,20 +3346,21 @@ void EncCu::xCheckRDCostAffineMerge2Nx2N( CodingStructure *&tempCS, CodingStruct
     candHasNoResidual[ui] = false;
   }
 
-  bool                                        bestIsSkip = false;
-  uint32_t                                    uiNumMrgSATDCand = affineMergeCtx.numValidMergeCand;
-  PelUnitBuf                                  acMergeBuffer[AFFINE_MRG_MAX_NUM_CANDS];
-  static_vector<uint32_t, AFFINE_MRG_MAX_NUM_CANDS>  RdModeList;
-  bool                                        mrgTempBufSet = false;
+  bool       bestIsSkip       = false;
+  bool       mrgTempBufSet    = false;
+  uint32_t   numMergeSatdCand = affineMergeCtx.numValidMergeCand;
+  PelUnitBuf acMergeBuffer[AFFINE_MRG_MAX_NUM_CANDS];
+
+  static_vector<uint32_t, AFFINE_MRG_MAX_NUM_CANDS> rdModeList;
 
   for ( uint32_t i = 0; i < AFFINE_MRG_MAX_NUM_CANDS; i++ )
   {
-    RdModeList.push_back( i );
+    rdModeList.push_back(i);
   }
 
   if ( m_pcEncCfg->getUseFastMerge() )
   {
-    uiNumMrgSATDCand = std::min( NUM_AFF_MRG_SATD_CAND, affineMergeCtx.numValidMergeCand );
+    numMergeSatdCand = std::min(NUM_AFF_MRG_SATD_CAND, affineMergeCtx.numValidMergeCand);
     bestIsSkip = false;
 
     if ( auto blkCache = dynamic_cast<CacheBlkInfoCtrl*>(m_modeCtrl) )
@@ -3367,7 +3373,7 @@ void EncCu::xCheckRDCostAffineMerge2Nx2N( CodingStructure *&tempCS, CodingStruct
     // 1. Pass: get SATD-cost for selected candidates and reduce their count
     if ( !bestIsSkip )
     {
-      RdModeList.clear();
+      rdModeList.clear();
       mrgTempBufSet = true;
       const double sqrtLambdaForFirstPass = m_pcRdCost->getMotionLambda( );
 
@@ -3458,18 +3464,17 @@ void EncCu::xCheckRDCostAffineMerge2Nx2N( CodingStructure *&tempCS, CodingStruct
           }
         }
 #endif
-        updateCandList( uiMergeCand, cost, RdModeList, candCostList
-          , uiNumMrgSATDCand );
+        updateCandList(uiMergeCand, cost, rdModeList, candCostList, numMergeSatdCand);
 
-        CHECK( std::min( uiMergeCand + 1, uiNumMrgSATDCand ) != RdModeList.size(), "" );
+        CHECK(std::min(uiMergeCand + 1, numMergeSatdCand) != rdModeList.size(), "");
       }
 
       // Try to limit number of candidates using SATD-costs
-      for ( uint32_t i = 1; i < uiNumMrgSATDCand; i++ )
+      for (uint32_t i = 1; i < numMergeSatdCand; i++)
       {
         if ( candCostList[i] > MRG_FAST_RATIO * candCostList[0] )
         {
-          uiNumMrgSATDCand = i;
+          numMergeSatdCand = i;
           break;
         }
       }
@@ -3480,7 +3485,7 @@ void EncCu::xCheckRDCostAffineMerge2Nx2N( CodingStructure *&tempCS, CodingStruct
     }
     else
     {
-      uiNumMrgSATDCand = affineMergeCtx.numValidMergeCand;
+      numMergeSatdCand = affineMergeCtx.numValidMergeCand;
     }
   }
 
@@ -3489,9 +3494,9 @@ void EncCu::xCheckRDCostAffineMerge2Nx2N( CodingStructure *&tempCS, CodingStruct
   iteration = 2;
   for (uint32_t uiNoResidualPass = iterationBegin; uiNoResidualPass < iteration; ++uiNoResidualPass)
   {
-    for ( uint32_t uiMrgHADIdx = 0; uiMrgHADIdx < uiNumMrgSATDCand; uiMrgHADIdx++ )
+    for (uint32_t uiMrgHADIdx = 0; uiMrgHADIdx < numMergeSatdCand; uiMrgHADIdx++)
     {
-      uint32_t uiMergeCand = RdModeList[uiMrgHADIdx];
+      uint32_t uiMergeCand = rdModeList[uiMrgHADIdx];
 
       if ( ((uiNoResidualPass != 0) && candHasNoResidual[uiMergeCand])
         || ((uiNoResidualPass == 0) && bestIsSkip) )
@@ -3718,10 +3723,10 @@ void EncCu::xCheckRDCostIBCModeMerge2Nx2N(CodingStructure *&tempCS, CodingStruct
 
   bool                                        bestIsSkip = false;
   unsigned                                    numMrgSATDCand = mergeCtx.numValidMergeCand;
-  static_vector<unsigned, MRG_MAX_NUM_CANDS>  RdModeList(MRG_MAX_NUM_CANDS);
+  static_vector<unsigned, MRG_MAX_NUM_CANDS>  rdModeList(MRG_MAX_NUM_CANDS);
   for (unsigned i = 0; i < MRG_MAX_NUM_CANDS; i++)
   {
-    RdModeList[i] = i;
+    rdModeList[i] = i;
   }
 
   static_vector<double, MRG_MAX_NUM_CANDS> candCostList(MRG_MAX_NUM_CANDS, MAX_DOUBLE);
@@ -3832,7 +3837,7 @@ void EncCu::xCheckRDCostIBCModeMerge2Nx2N(CodingStructure *&tempCS, CodingStruct
         }
       }
 #endif
-      updateCandList(mergeCand, cost, RdModeList, candCostList, numMrgSATDCand);
+      updateCandList(mergeCand, cost, rdModeList, candCostList, numMrgSATDCand);
     }
 
     // Try to limit number of candidates using SATD-costs
@@ -3868,7 +3873,7 @@ void EncCu::xCheckRDCostIBCModeMerge2Nx2N(CodingStructure *&tempCS, CodingStruct
   {
     for (unsigned int mrgHADIdx = 0; mrgHADIdx < numMrgSATDCand; mrgHADIdx++)
     {
-      unsigned int mergeCand = RdModeList[mrgHADIdx];
+      unsigned int mergeCand = rdModeList[mrgHADIdx];
       if (!(numResidualPass == 1 && candHasNoResidual[mergeCand] == 1))
       {
         if (!(bestIsSkip && (numResidualPass == 0)))
-- 
GitLab