diff --git a/cfg/encoder_lowdelay_ecm.cfg b/cfg/encoder_lowdelay_ecm.cfg
index 6ba267eb682ccf1b42ff451f01cfb40e55601928..c82ae77afcfd935a3496762c90dd20e392a45ae0 100644
--- a/cfg/encoder_lowdelay_ecm.cfg
+++ b/cfg/encoder_lowdelay_ecm.cfg
@@ -121,6 +121,7 @@ Geo                          : 1
 IBC                          : 0      # turned off in CTC
 AllowDisFracMMVD             : 1
 AffineAmvr                   : 0
+ArmcRefinedMotion            : 0
 LMCSEnable                   : 1      # LMCS: 0: disable, 1:enable
 LMCSSignalType               : 0      # Input signal type: 0:SDR, 1:HDR-PQ, 2:HDR-HLG
 LMCSUpdateCtrl               : 2      # LMCS model update control: 0:RA, 1:AI, 2:LDB/LDP
diff --git a/source/App/EncoderApp/EncApp.cpp b/source/App/EncoderApp/EncApp.cpp
index 7f8151fddc6521cb75f609ee0616c590579b45e4..a815a0cc86168613c83a93758251f6540328104a 100644
--- a/source/App/EncoderApp/EncApp.cpp
+++ b/source/App/EncoderApp/EncApp.cpp
@@ -607,6 +607,12 @@ void EncApp::xInitLibCfg()
   m_cEncLib.setRPLList1                                          ( m_RPLList1);
   m_cEncLib.setIDRRefParamListPresent                            ( m_idrRefParamList );
   m_cEncLib.setGopList                                           ( m_GOPList );
+  
+#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC
+  m_cEncLib.setIsRA                                              ( m_isRA );
+  m_cEncLib.setNumQPOffset                                       ( m_numQPOffset );
+  m_cEncLib.setQPOffsetList                                      ( m_qpOffsetList );
+#endif
 
   for(int i = 0; i < MAX_TLAYER; i++)
   {
@@ -775,6 +781,9 @@ void EncApp::xInitLibCfg()
   m_cEncLib.setBIO                                               (m_BIO);
 #if JVET_W0090_ARMC_TM
   m_cEncLib.setAML                                               ( m_AML );
+#endif
+#if JVET_AA0093_REFINED_MOTION_FOR_ARMC
+  m_cEncLib.setArmcRefinedMotion                                 ( m_iQP < 25 ? false : m_armcRefinedMotion );
 #endif
   m_cEncLib.setUseLMChroma                                       ( m_LMChroma );
   m_cEncLib.setHorCollocatedChromaFlag                           ( m_horCollocatedChromaFlag );
diff --git a/source/App/EncoderApp/EncAppCfg.cpp b/source/App/EncoderApp/EncAppCfg.cpp
index 7ea5f1c7e1cbc5a68f2849d3970f975701599fd1..bb33a5d92bc9ebf6e793c8815086fefae8ee09f3 100644
--- a/source/App/EncoderApp/EncAppCfg.cpp
+++ b/source/App/EncoderApp/EncAppCfg.cpp
@@ -1014,6 +1014,9 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] )
   ("BIO",                                             m_BIO,                                            false, "Enable bi-directional optical flow")
 #if JVET_W0090_ARMC_TM
   ("AML",                                             m_AML,                                             true, "Enable adaptive merge list")
+#endif
+#if JVET_AA0093_REFINED_MOTION_FOR_ARMC
+  ("ArmcRefinedMotion",                               m_armcRefinedMotion,                               true, "Enable adaptive re-ordering of merge candidates with refined motion")
 #endif
   ("IMV",                                             m_ImvMode,                                            1, "Adaptive MV precision Mode (IMV)\n"
                                                                                                                "\t0: disabled\n"
@@ -1880,6 +1883,76 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] )
       }
     }
   }
+#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC
+  int numQPOffset[MAX_GOP][2];
+  int numQPOffsetadded = 0;
+
+  for (int i = 0; i < m_iGOPSize; i++)
+  {
+    numQPOffset[i][0] = MAX_INT;
+    numQPOffset[i][1] = 0;
+  }
+  for (int i = 0; i < m_iGOPSize; i++)
+  {
+    if (!(m_GOPList[i].m_numRefPicsActive0 > 0 || m_GOPList[i].m_numRefPicsActive1 > 0))
+    {
+      continue;
+    }
+
+    int qp = m_iQP + m_GOPList[i].m_QPOffset;
+
+    // adjust QP according to QPOffsetModel for the GOP entry.
+    double dqpOffset = qp * m_GOPList[i].m_QPOffsetModelScale + m_GOPList[i].m_QPOffsetModelOffset + 0.5;
+    int    qpOffset  = (int) floor(Clip3<double>(0.0, 3.0, dqpOffset));
+    qp += qpOffset;
+
+    bool isQpOffsetAllreadyIdentified = false;
+    for (int j = 0; j < numQPOffsetadded; j++)
+    {
+      if (numQPOffset[j][0] == qp - m_iQP && m_GOPList[i].m_sliceType != 0)
+      {
+        isQpOffsetAllreadyIdentified = true;
+        numQPOffset[j][1]++;
+        break;
+      }
+    }
+    if (!isQpOffsetAllreadyIdentified)
+    {
+      numQPOffset[numQPOffsetadded][0] = qp - m_iQP;
+      numQPOffset[numQPOffsetadded][1]++;
+      numQPOffsetadded++;
+    }
+  }
+
+  m_numQPOffset = numQPOffsetadded;
+  if (m_GOPList[0].m_deltaRefPics0[0] > 1)
+  {
+    m_isRA = true;
+  }
+  else
+  {
+    m_isRA = false;
+  }
+
+  for (int j = 0; j < m_numQPOffset; j++)
+  {
+    int max = MAX_INT;
+    int pos = -1;
+    for (int i = 0; i < numQPOffsetadded; i++)
+    {
+      if ((numQPOffset[i][1]>0) && (max > numQPOffset[i][0]))
+      {
+        max = numQPOffset[i][0];
+        pos = i;
+      }
+    }
+    if (pos != -1)
+    {
+      m_qpOffsetList[j] = numQPOffset[pos][0];
+    }
+    numQPOffset[pos][1] = -1;
+  }
+#endif 
 
   for (list<const char*>::const_iterator it = argv_unhandled.begin(); it != argv_unhandled.end(); it++)
   {
@@ -4778,6 +4851,9 @@ void EncAppCfg::xPrintParameter()
     msg( VERBOSE, "DualITree:%d ", m_dualTree );
     msg( VERBOSE, "IMV:%d ", m_ImvMode );
     msg( VERBOSE, "BIO:%d ", m_BIO );
+#if JVET_AA0093_REFINED_MOTION_FOR_ARMC
+    msg( VERBOSE, "ArmcRefinedMotion:%d ", m_armcRefinedMotion );
+#endif
     msg( VERBOSE, "LMChroma:%d ", m_LMChroma );
     msg( VERBOSE, "HorCollocatedChroma:%d ", m_horCollocatedChromaFlag );
     msg( VERBOSE, "VerCollocatedChroma:%d ", m_verCollocatedChromaFlag );
diff --git a/source/App/EncoderApp/EncAppCfg.h b/source/App/EncoderApp/EncAppCfg.h
index a940c531f07cf84e81bb8be33ed77a1b99c38bfc..7b0d539e19974f16303466bb4a5a53f2dc52d600 100644
--- a/source/App/EncoderApp/EncAppCfg.h
+++ b/source/App/EncoderApp/EncAppCfg.h
@@ -297,6 +297,11 @@ protected:
   bool      m_cabacBypassAlignmentEnabledFlag;
   bool      m_ISP;
   bool      m_useFastISP;                                    ///< flag for enabling fast methods for ISP
+#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC
+  bool      m_isRA;
+  int       m_numQPOffset;
+  int       m_qpOffsetList[MAX_GOP];
+#endif
 
   // coding quality
 #if QP_SWITCHING_FOR_PARALLEL
@@ -396,6 +401,9 @@ protected:
   bool      m_BIO;
 #if JVET_W0090_ARMC_TM
   bool      m_AML;
+#endif
+#if JVET_AA0093_REFINED_MOTION_FOR_ARMC
+  bool      m_armcRefinedMotion;
 #endif
   int       m_LMChroma;
   bool      m_horCollocatedChromaFlag;
diff --git a/source/Lib/CommonLib/Buffer.cpp b/source/Lib/CommonLib/Buffer.cpp
index 111680b57a04f3d21066a3605b562e550aa79261..2f73ff97c8d6730293a9aebee430ac701632c6c8 100644
--- a/source/Lib/CommonLib/Buffer.cpp
+++ b/source/Lib/CommonLib/Buffer.cpp
@@ -960,6 +960,10 @@ PelBufferOps::PelBufferOps()
   removeHighFreq8 = removeHighFreq;
   removeHighFreq4 = removeHighFreq;
 #endif
+#if JVET_AA0093_REFINED_MOTION_FOR_ARMC
+  removeWeightHighFreq1 = removeWeightHighFreq;
+  removeHighFreq1 = removeHighFreq;
+#endif
 
   profGradFilter = gradFilterCore <false>;
   applyPROF      = applyPROFCore;
diff --git a/source/Lib/CommonLib/Buffer.h b/source/Lib/CommonLib/Buffer.h
index 6adde3275b44b4e01c5d8087f69e4cdf87c56f16..5a67cf41dabac313632da090d30b6ff6b7ff265a 100644
--- a/source/Lib/CommonLib/Buffer.h
+++ b/source/Lib/CommonLib/Buffer.h
@@ -95,6 +95,10 @@ struct PelBufferOps
   void(*calcBlkGradient)(int sx, int sy, int    *arraysGx2, int     *arraysGxGy, int     *arraysGxdI, int     *arraysGy2, int     *arraysGydI, int     &sGx2, int     &sGy2, int     &sGxGy, int     &sGxdI, int     &sGydI, int width, int height, int unitSize);
   void(*copyBuffer)(Pel *src, int srcStride, Pel *dst, int dstStride, int width, int height);
   void(*padding)(Pel *dst, int stride, int width, int height, int padSize);
+#if JVET_AA0093_REFINED_MOTION_FOR_ARMC
+  void ( *removeWeightHighFreq1)  ( Pel* src0, int src0Stride, const Pel* src1, int src1Stride, int width, int height, int shift, int bcwWeight);
+  void ( *removeHighFreq1)        ( Pel* src0, int src0Stride, const Pel* src1, int src1Stride, int width, int height);
+#endif
 #if ENABLE_SIMD_OPT_BCW && defined(TARGET_SIMD_X86)
   void ( *removeWeightHighFreq8)  ( Pel* src0, int src0Stride, const Pel* src1, int src1Stride, int width, int height, int shift, int bcwWeight);
   void ( *removeWeightHighFreq4)  ( Pel* src0, int src0Stride, const Pel* src1, int src1Stride, int width, int height, int shift, int bcwWeight);
@@ -550,7 +554,11 @@ void AreaBuf<T>::removeWeightHighFreq(const AreaBuf<T>& other, const bool bClip,
     else if(!(width & 3))
       g_pelBufOP.removeWeightHighFreq4(dst, dstStride, src, srcStride, width, height, 16, bcwWeight);
     else
+#if JVET_AA0093_REFINED_MOTION_FOR_ARMC
+      g_pelBufOP.removeWeightHighFreq1(dst, dstStride, src, srcStride, width, height, 16, bcwWeight);
+#else
       CHECK(true, "Not supported");
+#endif
   }
   else
   {
@@ -613,7 +621,11 @@ void AreaBuf<T>::removeHighFreq( const AreaBuf<T>& other, const bool bClip, cons
     else if (!(width & 3))
       g_pelBufOP.removeHighFreq4(dst, dstStride, src, srcStride, width, height);
     else
+#if JVET_AA0093_REFINED_MOTION_FOR_ARMC
+      g_pelBufOP.removeHighFreq1(dst, dstStride, src, srcStride, width, height);
+#else
       CHECK(true, "Not supported");
+#endif
   }
   else
   {
diff --git a/source/Lib/CommonLib/CommonDef.h b/source/Lib/CommonLib/CommonDef.h
index 7fb8e912451565566a46ba98e4ebc1a00826bef4..4fc14c8f0b7e57918322be03798a95a413287b92 100644
--- a/source/Lib/CommonLib/CommonDef.h
+++ b/source/Lib/CommonLib/CommonDef.h
@@ -162,16 +162,26 @@ static const int AMVP_DECIMATION_FACTOR =                           1;
 static const int AMVP_DECIMATION_FACTOR =                           2;
 #endif
 #if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM
+#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC
+static const int NUM_MERGE_CANDS =                                 28; ///< for maximum buffer of merging candidates
+static const int NUM_TMVP_CANDS =                                  8; ///< TMVP
+static const int MAX_PAIR_CANDS =                                  4; ///< MAX Pairiwse candidates for Regular TM and BM merge modes
+#else
 static const int NUM_MERGE_CANDS =                                 30; ///< for maximum buffer of merging candidates
 static const int NUM_TMVP_CANDS =                                   9; ///< TMVP
+#endif
 #elif JVET_Z0075_IBC_HMVP_ENLARGE
 static const int NUM_MERGE_CANDS =                                 20;
 #endif
 #if NON_ADJACENT_MRG_CAND
 static const int MRG_MAX_NUM_CANDS =                                15; ///< MERGE
 #if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM
+#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC
+static const int NUM_NON_ADJ_CANDS =                                16; ///< Non-Adj
+#else
 static const int NUM_NON_ADJ_CANDS =                                18; ///< Non-Adj
 #endif
+#endif
 static const int LAST_MERGE_IDX_CABAC =                              5;
 #else
 static const int MRG_MAX_NUM_CANDS =                                6; ///< MERGE
@@ -205,6 +215,20 @@ static const int AMVP_MERGE_MODE_MERGE_LIST_MAX_CANDS =             6;
 static const int AMVP_MERGE_MODE_REDUCED_MV_REFINE_SEARCH_ROUND =   8;
 #endif
 
+#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC
+static const double LAMBDA_DEC_SIDE[MAX_QP] = {
+  0.777106,       0.872272,       0.979092,       1.098994,       1.233579,       1.384646,       1.554212,
+  1.744544,       1.958185,       2.197988,       2.467158,       2.769291,       3.108425,       3.489089,
+  3.916370,       4.395976,       4.934316,       5.538583,       6.216849,       6.978177,       7.832739,
+  8.791952,       9.868633,       11.077166,      12.433698,      13.956355,      15.665478,      17.583905,
+  19.737266,       22.154332,      24.867397,      27.912709,      31.330957,      35.167810,      39.474532,
+  44.308664,       49.734793,      55.825418,      62.661913,      70.335619,      78.949063,      88.617327,
+  99.469587,       111.650836,     125.323826,     140.671239,     157.898127,     177.234655,     198.939174,
+  223.301672,       250.647653,     281.342477,     315.796254,     354.469310,     397.878347,     446.603345,
+  501.295305,       562.684955,     631.592507,     708.938619,     795.756695,     893.206689,     1002.590610
+};
+#endif
+
 static const int MAX_TLAYER =                                       7; ///< Explicit temporal layer QP offset - max number of temporal layer
 
 static const int ADAPT_SR_SCALE =                                   1; ///< division factor for adaptive search range
@@ -577,15 +601,25 @@ static const int LAST_SIGNIFICANT_GROUPS =                         14;
 #endif
 
 static const int AFFINE_MIN_BLOCK_SIZE =                            4; ///< Minimum affine MC block size
-
+#if JVET_AA0093_ENHANCED_MMVD_EXTENSION
+static const int MMVD_BI_DIR =                                      3;
+static const int AFFINE_BI_DIR =                                    3;
+#endif
 #if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
 static const int MMVD_REFINE_STEP =                                 6; ///< max number of distance step
 #else
 static const int MMVD_REFINE_STEP =                                 8; ///< max number of distance step
 #endif
+#if JVET_AA0093_ENHANCED_MMVD_EXTENSION
+static const int MMVD_MAX_DIR_UNI =                                 16;
+#endif
 #if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
+#if JVET_AA0093_ENHANCED_MMVD_EXTENSION
+static const int MMVD_MAX_DIR =                                     MMVD_MAX_DIR_UNI * MMVD_BI_DIR;
+#else
 static const int MMVD_MAX_DIR =                                     16;
 #endif
+#endif
 
 #if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
 static const int MMVD_SIZE_SHIFT =                                   3;
@@ -596,7 +630,11 @@ static const int MMVD_MAX_REFINE_NUM =                              (MMVD_REFINE
 static const int MMVD_MAX_REFINE_NUM =                              (MMVD_REFINE_STEP * 4); ///< max number of candidate from a base candidate
 #endif
 
+#if JVET_AA0093_ENHANCED_MMVD_EXTENSION
+static const int MMVD_BASE_MV_NUM =                                 3; ///< max number of base candidate
+#else
 static const int MMVD_BASE_MV_NUM =                                 2; ///< max number of base candidate
+#endif
 static const int MMVD_ADD_NUM =                                     (MMVD_MAX_REFINE_NUM * MMVD_BASE_MV_NUM);///< total number of mmvd candidate
 #if MERGE_ENC_OPT
 static const int MMVD_MRG_MAX_RD_NUM =                              20;
@@ -701,10 +739,22 @@ static const int    NUM_MRG_SATD_CAND =                             4;
 static const double MRG_FAST_RATIO    =                             1.25;
 static const int    NUM_AFF_MRG_SATD_CAND =                         2;
 #if AFFINE_MMVD
+#if JVET_AA0093_ENHANCED_MMVD_EXTENSION
+static const int    AF_MMVD_BASE_NUM =                              3;
+#else
 static const int    AF_MMVD_BASE_NUM =                              1;
+#endif
+#if JVET_AA0093_ENHANCED_MMVD_EXTENSION
+static const int    AF_MMVD_STEP_NUM =                              4; // number of distance offset
+#else
 static const int    AF_MMVD_STEP_NUM =                              5; // number of distance offset
+#endif
 #if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
+#if JVET_AA0093_ENHANCED_MMVD_EXTENSION
+static const int    AF_MMVD_OFFSET_DIR =                            8 * AFFINE_BI_DIR;
+#else
 static const int    AF_MMVD_OFFSET_DIR =                            8;
+#endif
 #else
 static const int    AF_MMVD_OFFSET_DIR =                            4; // 00: (+, 0); 01: (-, 0); 10: (0, +); 11 (0, -);
 #endif
@@ -730,7 +780,7 @@ static const int    TM_LOG2_BASE_WEIGHT =                           5; ///< base
 static const int    TM_DISTANCE_WEIGHTS[][4] = { { 0, 1, 2, 3 }, { 1, 2, 3, 3 } }; ///< far to near
 static const int    TM_SPATIAL_WEIGHTS [][4] = { { 2, 2, 2, 2 }, { 0, 1, 1, 2 } }; ///< "left to right for above template" or "top to bottom for left template"
 #if TM_MRG
-#if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM
+#if (JVET_Y0134_TMVP_NAMVP_CAND_REORDERING || JVET_AA0093_REFINED_MOTION_FOR_ARMC) && JVET_W0090_ARMC_TM
 static const int    TM_MRG_MAX_NUM_INIT_CANDS =                    10; ///< maximum number of TM merge candidates for ARMC (note: should be at most equal to MRG_MAX_NUM_CANDS)
 #endif
 static const int    TM_MRG_MAX_NUM_CANDS =                          4; ///< maximum number of TM merge candidates (note: should be at most equal to MRG_MAX_NUM_CANDS)
@@ -744,7 +794,7 @@ static const int    TM_MAX_NUM_SATD_CAND = std::min((int)4, TM_MRG_MAX_NUM_CANDS
 #endif
 #endif
 #endif
-#if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM
+#if (JVET_Y0134_TMVP_NAMVP_CAND_REORDERING || JVET_AA0093_REFINED_MOTION_FOR_ARMC) && JVET_W0090_ARMC_TM
 static const int    BM_MRG_MAX_NUM_INIT_CANDS =                    10; ///< maximum number of BM merge candidates (note: should be at most equal to MRG_MAX_NUM_CANDS)
 #endif
 #if MULTI_PASS_DMVR
@@ -801,8 +851,12 @@ static const int ADAPTIVE_SUB_GROUP_SIZE_MMVD =   MMVD_MAX_REFINE_NUM;
 #endif
 
 #if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
+#if JVET_AA0093_ENHANCED_MMVD_EXTENSION
+static const int ADAPTIVE_SUB_GROUP_SIZE_MMVD_AFF = AF_MMVD_MAX_REFINE_NUM >> 1;
+#else
 static const int ADAPTIVE_SUB_GROUP_SIZE_MMVD_AFF = AF_MMVD_MAX_REFINE_NUM;
 #endif
+#endif
 
 #if JVET_AA0057_CCCM
 static const int CCCM_WINDOW_SIZE         = 6;
diff --git a/source/Lib/CommonLib/ContextModelling.cpp b/source/Lib/CommonLib/ContextModelling.cpp
index 105399327aace3b58a6bc217e18607eb5f82201e..4258d75e88064aae67af583182063ec4247d0f8a 100644
--- a/source/Lib/CommonLib/ContextModelling.cpp
+++ b/source/Lib/CommonLib/ContextModelling.cpp
@@ -649,6 +649,96 @@ bool MergeCtx::xCheckSimilarMotion(int mergeCandIndex, uint32_t mvdSimilarityThr
   return false;
 }
 #endif
+#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC
+bool MergeCtx::xCheckSimilarMotion2Lists(int mergeCandIndex, MergeCtx *mrgCtx, uint32_t mvdSimilarityThresh ) const
+{
+  if (mrgCtx->mvFieldNeighbours[(mergeCandIndex << 1)].refIdx < 0 && mrgCtx->mvFieldNeighbours[(mergeCandIndex << 1) + 1].refIdx < 0)
+  {
+    return true;
+  }
+
+  if (mvdSimilarityThresh > 1)
+  {
+    for (uint32_t ui = 0; ui < numValidMergeCand; ui++)
+    {
+      if (interDirNeighbours[ui] == mrgCtx->interDirNeighbours[mergeCandIndex])
+      {
+        if (interDirNeighbours[ui] == 3)
+        {
+          if (mvFieldNeighbours[(ui << 1)].refIdx == mrgCtx->mvFieldNeighbours[(mergeCandIndex << 1)].refIdx &&
+            mvFieldNeighbours[(ui << 1) + 1].refIdx == mrgCtx->mvFieldNeighbours[(mergeCandIndex << 1) + 1].refIdx)
+          {
+            Mv mvDiffL0 = mvFieldNeighbours[(ui << 1)].mv - mrgCtx->mvFieldNeighbours[(mergeCandIndex << 1)].mv;
+            Mv mvDiffL1 = mvFieldNeighbours[(ui << 1) + 1].mv - mrgCtx->mvFieldNeighbours[(mergeCandIndex << 1) + 1].mv;
+
+            if (mvDiffL0.getAbsHor() < mvdSimilarityThresh && mvDiffL0.getAbsVer() < mvdSimilarityThresh
+              && mvDiffL1.getAbsHor() < mvdSimilarityThresh && mvDiffL1.getAbsVer() < mvdSimilarityThresh)
+            {
+              return true;
+            }
+          }
+        }
+        else if (interDirNeighbours[ui] == 1)
+        {
+          if (mvFieldNeighbours[(ui << 1)].refIdx == mrgCtx->mvFieldNeighbours[(mergeCandIndex << 1)].refIdx)
+          {
+            Mv mvDiff = mvFieldNeighbours[(ui << 1)].mv - mrgCtx->mvFieldNeighbours[(mergeCandIndex << 1)].mv;
+            if (mvDiff.getAbsHor() < mvdSimilarityThresh && mvDiff.getAbsVer() < mvdSimilarityThresh)
+            {
+              return true;
+            }
+          }
+        }
+        else if (interDirNeighbours[ui] == 2)
+        {
+          if (mvFieldNeighbours[(ui << 1) + 1].refIdx == mrgCtx->mvFieldNeighbours[(mergeCandIndex << 1) + 1].refIdx)
+          {
+            Mv mvDiff = mvFieldNeighbours[(ui << 1) + 1].mv - mrgCtx->mvFieldNeighbours[(mergeCandIndex << 1) + 1].mv;
+            if (mvDiff.getAbsHor() < mvdSimilarityThresh && mvDiff.getAbsVer() < mvdSimilarityThresh)
+            {
+              return true;
+            }
+          }
+        }
+      }
+    }
+    return false;
+  }
+  for (uint32_t ui = 0; ui < numValidMergeCand; ui++)
+  {
+    if (interDirNeighbours[ui] == mrgCtx->interDirNeighbours[mergeCandIndex])
+    {
+      if (interDirNeighbours[ui] == 3)
+      {
+        if (mvFieldNeighbours[(ui << 1)].refIdx == mrgCtx->mvFieldNeighbours[(mergeCandIndex << 1)].refIdx &&
+          mvFieldNeighbours[(ui << 1) + 1].refIdx == mrgCtx->mvFieldNeighbours[(mergeCandIndex << 1) + 1].refIdx &&
+          mvFieldNeighbours[(ui << 1)].mv == mrgCtx->mvFieldNeighbours[(mergeCandIndex << 1)].mv &&
+          mvFieldNeighbours[(ui << 1) + 1].mv == mrgCtx->mvFieldNeighbours[(mergeCandIndex << 1) + 1].mv)
+        {
+          return true;
+        }
+      }
+      else if (interDirNeighbours[ui] == 1)
+      {
+        if (mvFieldNeighbours[(ui << 1)].refIdx == mrgCtx->mvFieldNeighbours[(mergeCandIndex << 1)].refIdx &&
+          mvFieldNeighbours[(ui << 1)].mv == mrgCtx->mvFieldNeighbours[(mergeCandIndex << 1)].mv)
+        {
+          return true;
+        }
+      }
+      else if (interDirNeighbours[ui] == 2)
+      {
+        if (mvFieldNeighbours[(ui << 1) + 1].refIdx == mrgCtx->mvFieldNeighbours[(mergeCandIndex << 1) + 1].refIdx &&
+          mvFieldNeighbours[(ui << 1) + 1].mv == mrgCtx->mvFieldNeighbours[(mergeCandIndex << 1) + 1].mv)
+        {
+          return true;
+        }
+      }
+    }
+  }
+  return false;
+}
+#endif
 #if JVET_Z0084_IBC_TM
 #if JVET_Z0075_IBC_HMVP_ENLARGE
 bool MergeCtx::xCheckSimilarIBCMotion(int mergeCandIndex, uint32_t mvdSimilarityThresh, int compareNum) const
@@ -855,10 +945,55 @@ void MergeCtx::setMmvdMergeCandiInfo(PredictionUnit& pu, int candIdx)
   const int refList1 = mmvdBaseMv[fPosBaseIdx][1].refIdx;
 
 #if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
+#if JVET_AA0093_ENHANCED_MMVD_EXTENSION
+                    //0   1   2   3   4   5   6   7  8   9  10  11 12  13  14  15
+  const int xDir[] = {1, -1,  0,  0,  1, -1,  1, -1, 2, -2, -2,  2, 1, -1, -1,  1};
+  const int yDir[] = {0,  0,  1, -1,  1, -1, -1,  1, 1, -1,  1, -1, 2, -2,  2, -2};
+#else
   const int xDir[] = {1, -1,  0,  0,  1, -1,  1, -1, 2, -2,  2, -2, 1,  1, -1, -1};
   const int yDir[] = {0,  0,  1, -1,  1, -1, -1,  1, 1,  1, -1, -1, 2, -2,  2, -2};
 #endif
-    
+#endif
+   
+#if JVET_AA0093_ENHANCED_MMVD_EXTENSION
+  if ((refList0 != -1) && (refList1 != -1))
+  {
+    tempMv[0] = Mv(0,0);
+    tempMv[1] = Mv(0,0);
+    int cutOff1 = 2 * MMVD_MAX_DIR_UNI;
+    int cutOff2 = MMVD_MAX_DIR_UNI;
+    if (fPosPosition >= cutOff1)
+    {
+      fPosPosition -= cutOff1;
+      const int poc0 = slice.getRefPOC(REF_PIC_LIST_0, refList0);
+      const int poc1 = slice.getRefPOC(REF_PIC_LIST_1, refList1);
+      const int currPoc = slice.getPOC();
+      tempMv[0] = Mv(xDir[fPosPosition] * offset, yDir[fPosPosition] * offset);
+      if ((poc1 - currPoc)*(poc0 - currPoc) > 0)
+      {
+        tempMv[1] = tempMv[0];
+      }
+      else
+      {
+        tempMv[1].set(-1 * tempMv[0].getHor(), -1 * tempMv[0].getVer());
+      }
+    }
+    else if (fPosPosition >= cutOff2)
+    {
+      fPosPosition -= cutOff2;
+      tempMv[1] = Mv(xDir[fPosPosition] * offset, yDir[fPosPosition] * offset);
+    }
+    else
+    {
+      tempMv[0] = Mv(xDir[fPosPosition] * offset, yDir[fPosPosition] * offset);
+    }
+    pu.interDir = 3;
+    pu.mv[REF_PIC_LIST_0] = mmvdBaseMv[fPosBaseIdx][0].mv + tempMv[0];
+    pu.refIdx[REF_PIC_LIST_0] = refList0;
+    pu.mv[REF_PIC_LIST_1] = mmvdBaseMv[fPosBaseIdx][1].mv + tempMv[1];
+    pu.refIdx[REF_PIC_LIST_1] = refList1;
+  }
+#else
   if ((refList0 != -1) && (refList1 != -1))
   {
     const int poc0 = slice.getRefPOC(REF_PIC_LIST_0, refList0);
@@ -934,6 +1069,7 @@ void MergeCtx::setMmvdMergeCandiInfo(PredictionUnit& pu, int candIdx)
     pu.mv[REF_PIC_LIST_1] = mmvdBaseMv[fPosBaseIdx][1].mv + tempMv[1];
     pu.refIdx[REF_PIC_LIST_1] = refList1;
   }
+#endif
   else if (refList0 != -1)
   {
 #if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
diff --git a/source/Lib/CommonLib/ContextModelling.h b/source/Lib/CommonLib/ContextModelling.h
index f11db5fe40a9c2acc2bef2e36f5ce84ba91cc63f..446f3ad05a1a3f6eff54a2789c968d84640ec599 100644
--- a/source/Lib/CommonLib/ContextModelling.h
+++ b/source/Lib/CommonLib/ContextModelling.h
@@ -607,6 +607,9 @@ public:
 #else
   bool xCheckSimilarMotion(int mergeCandIndex, uint32_t mvdSimilarityThresh = 1) const;
 #endif
+#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC
+  bool xCheckSimilarMotion2Lists(int mergeCandIndex, MergeCtx *mrgCtx, uint32_t mvdSimilarityThresh = 1) const;
+#endif
 #endif
 #if JVET_Z0084_IBC_TM
 #if JVET_Z0075_IBC_HMVP_ENLARGE
diff --git a/source/Lib/CommonLib/Contexts.cpp b/source/Lib/CommonLib/Contexts.cpp
index 705198c0beea465dadf9cad4e114382a6930fa63..4f3fe5204148286c11513893582eac836562d02c 100644
--- a/source/Lib/CommonLib/Contexts.cpp
+++ b/source/Lib/CommonLib/Contexts.cpp
@@ -912,6 +912,19 @@ const CtxSet ContextSetCfg::GPMIntraFlag = ContextSetCfg::addCtxSet
 
 const CtxSet ContextSetCfg::MmvdFlag = ContextSetCfg::addCtxSet
 ({
+#if JVET_AA0093_ENHANCED_MMVD_EXTENSION
+  {  18, 18, 18, 18},
+  {  18, 18, 18, 18},
+  { CNU, CNU, CNU, CNU },
+  {   6, 6, 6, 6 },
+  {   5, 5, 5, 5},
+  { DWS, DWS, DWS, DWS},
+  {  18, 18, 18, 18},
+  {  18, 18, 18, 18},
+  { DWE, DWE, DWE, DWE},
+  { 117, 117, 117, 117},
+  { 117, 117, 117, 117},
+#else
   {  18, },
   {  18, },
   { CNU, },
@@ -923,10 +936,24 @@ const CtxSet ContextSetCfg::MmvdFlag = ContextSetCfg::addCtxSet
   { DWE, },
   { 117, },
   { 117, },
+#endif
   });
 
 const CtxSet ContextSetCfg::MmvdMergeIdx = ContextSetCfg::addCtxSet
 ({
+#if JVET_AA0093_ENHANCED_MMVD_EXTENSION
+  {  58, 58, 58, 58},
+  {  43, 43, 43, 43},
+  { CNU, CNU, CNU, CNU },
+  {   9, 9, 9, 9},
+  {  10, 10, 10, 10},
+  { DWS, DWS,DWS,DWS},
+  {  18, 18,18,18},
+  {  11, 11,11,11},
+  { DWE, DWE,DWE,DWE},
+  { 116, 116,116,116},
+  { 118, 118,118,118},
+#else
   {  58, },
   {  43, },
   { CNU, },
@@ -938,6 +965,7 @@ const CtxSet ContextSetCfg::MmvdMergeIdx = ContextSetCfg::addCtxSet
   { DWE, },
   { 116, },
   { 118, },
+#endif
   });
 
 const CtxSet ContextSetCfg::MmvdStepMvpIdx = ContextSetCfg::addCtxSet
@@ -1053,6 +1081,19 @@ const CtxSet ContextSetCfg::AfMmvdFlag = ContextSetCfg::addCtxSet
 
 const CtxSet ContextSetCfg::AfMmvdIdx = ContextSetCfg::addCtxSet
 ({
+#if JVET_AA0093_ENHANCED_MMVD_EXTENSION
+  { CNU, CNU,CNU,CNU},
+  { CNU, CNU,CNU,CNU},
+  { CNU, CNU,CNU,CNU},
+  { DWS, DWS,DWS,DWS},
+  { DWS, DWS,DWS,DWS},
+  { DWS, DWS,DWS,DWS},
+  { DWE, DWE,DWE,DWE},
+  { DWE, DWE,DWE,DWE},
+  { DWE, DWE,DWE,DWE},
+  { 119, 119,119,119},
+  { 119, 119,119,119},
+#else
   { CNU, },
   { CNU, },
   { CNU, },
@@ -1064,11 +1105,25 @@ const CtxSet ContextSetCfg::AfMmvdIdx = ContextSetCfg::addCtxSet
   { DWE, },
   { 119, },
   { 119, },
+#endif
   });
 
 const CtxSet ContextSetCfg::AfMmvdOffsetStep = ContextSetCfg::addCtxSet
 ({
 #if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
+#if JVET_AA0093_ENHANCED_MMVD_EXTENSION
+  {  21,  29,  29,  29,  44, CNU},
+  {  13,  21,  36,  29,  44, CNU},
+  { CNU, CNU, CNU, CNU, CNU, CNU},
+  {   5,   5,   5,   4,   5, DWS},
+  {   5,   5,   4,   5,   9, DWS},
+  { DWS, DWS, DWS, DWS, DWS, DWS},
+  {  18,  18,  18,  11,  11, DWE},
+  {  18,  18,  11,  18,  25, DWE},
+  { DWE, DWE, DWE, DWE, DWE, DWE},
+  { 126, 141, 187, 219, 238, DWO},
+  { 117, 102, 100, 100,  87, DWO},
+#else
   {  21,  29,  29,  29,  44, },
   {  13,  21,  36,  29,  44, },
   { CNU, CNU, CNU, CNU, CNU, },
@@ -1080,6 +1135,7 @@ const CtxSet ContextSetCfg::AfMmvdOffsetStep = ContextSetCfg::addCtxSet
   { DWE, DWE, DWE, DWE, DWE, },
   { 126, 141, 187, 219, 238, },
   { 117, 102, 100, 100,  87, },
+#endif
 #else
   {  21 },
   {  13 },
diff --git a/source/Lib/CommonLib/InterPrediction.cpp b/source/Lib/CommonLib/InterPrediction.cpp
index 59e852616b9b0dc0ceae4c6fcaec55af4b33c657..c07fc2104e3907d62f86c7c92dd1a1854ac00664 100644
--- a/source/Lib/CommonLib/InterPrediction.cpp
+++ b/source/Lib/CommonLib/InterPrediction.cpp
@@ -1956,7 +1956,11 @@ void InterPrediction::xPredInterBlk ( const ComponentID& compID, const Predictio
 {
 #if JVET_W0090_ARMC_TM || JVET_Z0056_GPM_SPLIT_MODE_REORDERING || JVET_Z0061_TM_OBMC
 #if  JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
+#if JVET_AA0093_REFINED_MOTION_FOR_ARMC
+  int filterIdx = isAML && (pu.mmvdMergeFlag || (pu.tmMergeFlag && !pu.ciipFlag && !pu.cu->geoFlag)) ? 1 : 0;
+#else
   int filterIdx = isAML && pu.mmvdMergeFlag ? 1 : 0;
+#endif
 #else
   int filterIdx = 0;
 #endif
@@ -5882,9 +5886,9 @@ void InterPrediction::cacheAssign( CacheModel *cache )
 #endif
 
 #if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
-void  InterPrediction::sortInterMergeMMVDCandidates(PredictionUnit &pu, MergeCtx& mrgCtx, uint32_t * mmvdLUT, uint32_t MMVDIdx)
+#if JVET_AA0093_ENHANCED_MMVD_EXTENSION
+void  InterPrediction::sortInterMergeMMVDCandidates(PredictionUnit &pu, MergeCtx& mrgCtx, uint32_t * mmvdLUT, int16_t MMVDIdx)
 {
-  
   const int tempNum = (const int) (std::min<int>(MMVD_BASE_MV_NUM, mrgCtx.numValidMergeCand) * MMVD_MAX_REFINE_NUM);
   const int groupSize = std::min<int>(tempNum, ADAPTIVE_SUB_GROUP_SIZE_MMVD);
 #if _WINDOWS
@@ -5892,7 +5896,7 @@ void  InterPrediction::sortInterMergeMMVDCandidates(PredictionUnit &pu, MergeCtx
 #else
   Distortion candCostList[tempNum] ;
 #endif
-  
+
   for (uint32_t i = 0; i < tempNum; i++)
   {
     mmvdLUT[i] = i;
@@ -5907,7 +5911,13 @@ void  InterPrediction::sortInterMergeMMVDCandidates(PredictionUnit &pu, MergeCtx
   {
     return;
   }
-  
+
+  // Store
+  int8_t posList0 = 0;
+  int8_t posList1 = 0;
+  bool load0 = false;
+  bool load1 = false;
+
   int startMMVDIdx = 0;
   int endMMVDIdx = tempNum;
   if(MMVDIdx != -1)
@@ -5916,9 +5926,338 @@ void  InterPrediction::sortInterMergeMMVDCandidates(PredictionUnit &pu, MergeCtx
     startMMVDIdx = gpId * groupSize;
     endMMVDIdx = (gpId+1) * groupSize;
   }
-  
+
+  int shiftEnc = MMVD_SIZE_SHIFT;
+  int encGrpSize = groupSize >> shiftEnc;
+
+  encGrpSize /= MMVD_BI_DIR;
+#if !JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC
+  uint8_t curIdx = 0;
+  double threshold = 1.02;
+#endif
+  encGrpSize <<= MMVD_SIZE_SHIFT;
+
+  // Joint for all
+  const Slice &slice = *pu.cs->slice;
+  const int mvShift = MV_FRACTIONAL_BITS_DIFF;
+  const int refMvdCands[] = { 1 << mvShift , 2 << mvShift , 4 << mvShift , 8 << mvShift , 16 << mvShift ,  32 << mvShift };
+  const int xDir[] = {1, -1,  0,  0,  1, -1,  1, -1, 2, -2, -2,  2, 1, -1, -1,  1};
+  const int yDir[] = {0,  0,  1, -1,  1, -1, -1,  1, 1, -1,  1, -1, 2, -2,  2, -2};
+  pu.mmvdMergeFlag = true;
+  pu.mergeFlag = true;
+  pu.regularMergeFlag = true;
+  pu.mergeType = MRG_TYPE_DEFAULT_N;
+  pu.bdmvrRefine             = false;
+  pu.mvd[REF_PIC_LIST_0] = Mv();
+  pu.mvd[REF_PIC_LIST_1] = Mv();
+  pu.mvpIdx[REF_PIC_LIST_0] = NOT_VALID;
+  pu.mvpIdx[REF_PIC_LIST_1] = NOT_VALID;
+  pu.mvpNum[REF_PIC_LIST_0] = NOT_VALID;
+  pu.mvpNum[REF_PIC_LIST_1] = NOT_VALID;
+#if MULTI_HYP_PRED
+  pu.addHypData.clear();
+  pu.numMergedAddHyps = 0;
+#endif
+  // Joint for all ends
+  for (int fPosBaseIdx = startMMVDIdx/MMVD_MAX_REFINE_NUM; fPosBaseIdx < endMMVDIdx/MMVD_MAX_REFINE_NUM; fPosBaseIdx++)
+  {
+    // joint for each base
+    const int refList0 = mrgCtx.mmvdBaseMv[fPosBaseIdx][0].refIdx;
+    const int refList1 = mrgCtx.mmvdBaseMv[fPosBaseIdx][1].refIdx;
+    pu.cu->imv = mrgCtx.mmvdUseAltHpelIf[fPosBaseIdx] ? IMV_HPEL : 0;
+#if INTER_LIC
+    pu.cu->LICFlag = mrgCtx.LICFlags[fPosBaseIdx];
+#endif
+    pu.cu->BcwIdx = (mrgCtx.interDirNeighbours[fPosBaseIdx] == 3) ? mrgCtx.BcwIdx[fPosBaseIdx] : BCW_DEFAULT;
+    pu.refIdx[REF_PIC_LIST_0] = refList0;
+    pu.refIdx[REF_PIC_LIST_1] = refList1;
+    // joint for each base ends
+
+    //Store
+    posList0 = 0;
+    posList1 = 0;
+    load0 = false;
+    load1 = false;
+
+    for (int tempIdx = 0; tempIdx < MMVD_MAX_REFINE_NUM; tempIdx++)
+    {
+      // special for each case
+      int fPosStep = 0;
+      int fPosPosition = 0;
+      Mv tempMv[2];
+      fPosStep = tempIdx / MMVD_MAX_DIR;
+      fPosPosition = tempIdx - fPosStep * MMVD_MAX_DIR;
+      // special for each case
+
+      /*  Skipping dir 16 to 47 for uni  */
+      if ((fPosPosition >= MMVD_MAX_DIR_UNI) && ((refList0 == -1) || (refList1 == -1)))
+      {
+        continue;
+      }
+      int candIdx = fPosBaseIdx * MMVD_MAX_REFINE_NUM + tempIdx;
+      pu.mmvdMergeIdx = candIdx;
+      pu.mergeIdx = candIdx;
+      int offset = refMvdCands[fPosStep];
+      if ( pu.cu->slice->getPicHeader()->getDisFracMMVD() )
+      {
+        offset <<= 2;
+      }
+
+      if ((refList0 != -1) && (refList1 != -1))
+      {
+        tempMv[0] = Mv(0,0);
+        tempMv[1] = Mv(0,0);
+        
+        int fPosPosition1 = fPosPosition % MMVD_MAX_DIR_UNI;
+        int fPosPosition2 = fPosPosition / MMVD_MAX_DIR_UNI;
+        if (fPosPosition2 == 0)
+        {
+          tempMv[0] = Mv(xDir[fPosPosition1] * offset, yDir[fPosPosition1] * offset);
+          //Store
+          posList0 = fPosPosition1 + 1;
+          posList1 = 0;
+          load0 = false;
+          load1 = (fPosPosition1 != 0) || (fPosStep != 0);
+        }
+        else if (fPosPosition2 == 1)
+        {
+          tempMv[1] = Mv(xDir[fPosPosition1] * offset, yDir[fPosPosition1] * offset);
+          //Store
+          posList0 = 0;
+          posList1 = fPosPosition1 + 1;
+          load0 = (fPosPosition1 != 0) || (fPosStep != 0);
+          load1 = false;
+        }
+        else
+        {
+          const int poc0 = slice.getRefPOC(REF_PIC_LIST_0, refList0);
+          const int poc1 = slice.getRefPOC(REF_PIC_LIST_1, refList1);
+          const int currPoc = slice.getPOC();
+          tempMv[0] = Mv(xDir[fPosPosition1] * offset, yDir[fPosPosition1] * offset);
+          if ((poc1 - currPoc)*(poc0 - currPoc) > 0)
+          {
+            tempMv[1] = tempMv[0];
+            //Store
+            posList0 = fPosPosition1 + 1;
+            posList1 = fPosPosition1 + 1;
+            load0 = true;
+            load1 = true;
+          }
+          else
+          {
+            tempMv[1].set(-1 * tempMv[0].getHor(), -1 * tempMv[0].getVer());
+            //Store
+            posList0 = fPosPosition1 + 1;
+            posList1 = (fPosPosition1 ^ 1) + 1;
+            load0 = true;
+            load1 = true;
+          }
+        }
+        pu.interDir = 3;
+        pu.mv[REF_PIC_LIST_0] = mrgCtx.mmvdBaseMv[fPosBaseIdx][0].mv + tempMv[0];
+        pu.mv[REF_PIC_LIST_1] = mrgCtx.mmvdBaseMv[fPosBaseIdx][1].mv + tempMv[1];
+        pu.mv[0].clipToStorageBitDepth();
+        pu.mv[1].clipToStorageBitDepth();
+      }
+      else if (refList0 != -1)
+      {
+        tempMv[0] = Mv(xDir[fPosPosition] * offset, yDir[fPosPosition] * offset);
+        pu.interDir = 1;
+        pu.mv[REF_PIC_LIST_0] = mrgCtx.mmvdBaseMv[fPosBaseIdx][0].mv + tempMv[0];
+        pu.mv[REF_PIC_LIST_1] = Mv(0, 0);
+        pu.mv[0].clipToStorageBitDepth();
+      }
+      else
+      {
+        tempMv[1] = Mv(xDir[fPosPosition] * offset, yDir[fPosPosition] * offset);
+        pu.interDir = 2;
+        pu.mv[REF_PIC_LIST_0] = Mv(0, 0);
+        pu.mv[REF_PIC_LIST_1] = mrgCtx.mmvdBaseMv[fPosBaseIdx][1].mv + tempMv[1];
+        pu.mv[1].clipToStorageBitDepth();
+      }
+      // Derive prediction
+      for (int refList = 0; refList < 2; refList++)
+      {
+        if (pu.refIdx[refList] >= 0)
+        {
+          pu.mv[refList].roundToPrecision(MV_PRECISION_QUARTER, MV_PRECISION_INT);
+        }
+      }
+      uiCost = 0;
+
+      PelUnitBuf pcBufPredRefTop = (PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefAMLTemplate[0][0], nWidth, AML_MERGE_TEMPLATE_SIZE)));
+      PelUnitBuf pcBufPredCurTop = (PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvCurAMLTemplate[0][0], nWidth, AML_MERGE_TEMPLATE_SIZE)));
+      PelUnitBuf pcBufPredRefLeft = (PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefAMLTemplate[1][0], AML_MERGE_TEMPLATE_SIZE, nHeight)));
+      PelUnitBuf pcBufPredCurLeft = (PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvCurAMLTemplate[1][0], AML_MERGE_TEMPLATE_SIZE, nHeight)));
+      //Store
+      if ((refList0 != -1) && (refList1 != -1))
+      {
+        getBlkAMLRefTemplate(pu, pcBufPredRefTop, pcBufPredRefLeft, posList0, posList1, load0, load1);
+      }
+      else
+      {
+        getBlkAMLRefTemplate(pu, pcBufPredRefTop, pcBufPredRefLeft);
+      }
+      if (m_bAMLTemplateAvailabe[0])
+      {
+        m_pcRdCost->setDistParam(cDistParam, pcBufPredCurTop.Y(), pcBufPredRefTop.Y(), pu.cs->sps->getBitDepth(CHANNEL_TYPE_LUMA), COMPONENT_Y, false);
+        uiCost += cDistParam.distFunc(cDistParam);
+        
+      }
+
+      if (m_bAMLTemplateAvailabe[1])
+      {
+        m_pcRdCost->setDistParam(cDistParam, pcBufPredCurLeft.Y(), pcBufPredRefLeft.Y(), pu.cs->sps->getBitDepth(CHANNEL_TYPE_LUMA), COMPONENT_Y, false);
+        uiCost += cDistParam.distFunc(cDistParam);
+      }
+      
+#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC
+      if (m_bAMLTemplateAvailabe[0] && !m_bAMLTemplateAvailabe[1])
+      {
+        uiCost += (uiCost * nHeight) / nWidth;
+      }
+      if (!m_bAMLTemplateAvailabe[0] && m_bAMLTemplateAvailabe[1])
+      {
+        uiCost += (uiCost * nWidth) / nHeight;
+      }
+#endif
+      // update part
+      uint32_t i;
+      uint32_t shift = 0;
+      uint32_t gpIdx = candIdx/groupSize;
+      uint32_t endIdx = gpIdx * groupSize + encGrpSize;
+      while (shift < encGrpSize && uiCost < candCostList[endIdx - 1 - shift])
+      {
+        shift++;
+      }
+      if (shift != 0)
+      {
+        for (i = 1; i < shift; i++)
+        {
+          mmvdLUT[endIdx - i] = mmvdLUT[endIdx - 1 - i];
+          candCostList[endIdx - i] = candCostList[endIdx - 1 - i];
+        }
+        mmvdLUT[endIdx - shift] = candIdx;
+        candCostList[endIdx - shift] = uiCost;
+      }
+    }
+#if  !JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC
+    int startPoint = fPosBaseIdx * MMVD_MAX_REFINE_NUM;
+    for (int i = 1; i < encGrpSize; i++)
+    {
+      if(((double)candCostList[startPoint+i]/(double)candCostList[startPoint+curIdx]) > threshold)
+      {
+        mmvdLUT[startPoint+curIdx+1] = mmvdLUT[startPoint+i];
+        candCostList[startPoint+curIdx+1] = candCostList[startPoint+i];
+        curIdx++;
+        if (curIdx >= (encGrpSize >> MMVD_SIZE_SHIFT) -1)
+        {
+          break;
+        }
+      }
+    }
+    curIdx = 0;
+#endif
+
+  }
+#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC
+  Distortion lambdaTh = pu.cs->slice->getCostForARMC();
+  startMMVDIdx = 0;
+  endMMVDIdx = MMVD_BASE_MV_NUM;
+  if (MMVDIdx != -1)
+  {
+    uint32_t gpId = MMVDIdx / groupSize;
+    startMMVDIdx = gpId;
+    endMMVDIdx = (gpId + 1);
+  }
+  for (int mmvdBaseIdx = startMMVDIdx; mmvdBaseIdx < endMMVDIdx; mmvdBaseIdx++)
+  {
+    uint32_t startIdx = ( mmvdBaseIdx ) * groupSize;
+    int maxCand = (MMVD_MAX_REFINE_NUM >> MMVD_SIZE_SHIFT)/MMVD_BI_DIR;
+    bool enoughDiverse = false;
+    uint32_t diverseCand = 0;
+    uint32_t posToBeInserted = 0;
+    for (uint32_t uiCand = startIdx; uiCand < startIdx + maxCand - 1; ++uiCand)
+    {
+      for (uint32_t uiMergeCand = uiCand + 1; uiMergeCand < startIdx + groupSize - 2; ++uiMergeCand)
+      {
+        if (lambdaTh <= abs((int)(candCostList[uiMergeCand] - candCostList[uiCand])))
+        {
+          enoughDiverse = true;
+          for (uint32_t uiMergeCand3 = startIdx; uiMergeCand3 < uiCand; ++uiMergeCand3)
+          {
+            if (lambdaTh > abs((int)(candCostList[uiMergeCand] - candCostList[uiMergeCand3])))
+            {
+              enoughDiverse = false;
+              break;
+            }
+          }
+          if (enoughDiverse)
+          {
+            diverseCand = uiMergeCand;
+            posToBeInserted = uiCand + 1;
+            break;
+          }
+        }
+      }
+      if (enoughDiverse)
+      {
+        Distortion saveCandCost = candCostList[diverseCand];
+        uint32_t   mmvdLUTSave = mmvdLUT[diverseCand];
+        for (int i = diverseCand; i > posToBeInserted - 1; i--)
+        {
+          candCostList[i] = candCostList[i - 1];
+          mmvdLUT[i] = mmvdLUT[i - 1];
+        }
+        candCostList[posToBeInserted] = saveCandCost;
+        mmvdLUT[posToBeInserted] = mmvdLUTSave;
+      }
+    }
+  }
+#endif
+}
+#else
+void  InterPrediction::sortInterMergeMMVDCandidates(PredictionUnit& pu, MergeCtx& mrgCtx, uint32_t* mmvdLUT, uint32_t MMVDIdx)
+{
+
+  const int tempNum = (const int)(std::min<int>(MMVD_BASE_MV_NUM, mrgCtx.numValidMergeCand) * MMVD_MAX_REFINE_NUM);
+  const int groupSize = std::min<int>(tempNum, ADAPTIVE_SUB_GROUP_SIZE_MMVD);
+#if _WINDOWS
+  Distortion candCostList[MMVD_BASE_MV_NUM * MMVD_MAX_REFINE_NUM];
+#else
+  Distortion candCostList[tempNum];
+#endif
+
+  for (uint32_t i = 0; i < tempNum; i++)
+  {
+    mmvdLUT[i] = i;
+    candCostList[i] = MAX_UINT;
+  }
+  Distortion uiCost;
+  DistParam cDistParam;
+  cDistParam.applyWeight = false;
+  int nWidth = pu.lumaSize().width;
+  int nHeight = pu.lumaSize().height;
+  if (!xAMLGetCurBlkTemplate(pu, nWidth, nHeight))
+  {
+    return;
+  }
+
+  int startMMVDIdx = 0;
+  int endMMVDIdx = tempNum;
+  if (MMVDIdx != -1)
+  {
+    uint32_t gpId = MMVDIdx / groupSize;
+    startMMVDIdx = gpId * groupSize;
+    endMMVDIdx = (gpId + 1) * groupSize;
+  }
+
+#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC
+  int encGrpSize = groupSize;
+#else
   int shiftEnc = MMVD_SIZE_SHIFT;
   int encGrpSize = groupSize >> shiftEnc;
+#endif
   for (int mmvdMergeCand = startMMVDIdx; mmvdMergeCand < endMMVDIdx; mmvdMergeCand++)
   {
     mrgCtx.setMmvdMergeCandiInfo(pu, mmvdMergeCand, mmvdMergeCand);
@@ -5930,29 +6269,39 @@ void  InterPrediction::sortInterMergeMMVDCandidates(PredictionUnit &pu, MergeCtx
         pu.mv[refList].roundToPrecision(MV_PRECISION_QUARTER, MV_PRECISION_INT);
       }
     }
-    
+
     uiCost = 0;
-    
+
     PelUnitBuf pcBufPredRefTop = (PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefAMLTemplate[0][0], nWidth, AML_MERGE_TEMPLATE_SIZE)));
     PelUnitBuf pcBufPredCurTop = (PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvCurAMLTemplate[0][0], nWidth, AML_MERGE_TEMPLATE_SIZE)));
     PelUnitBuf pcBufPredRefLeft = (PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefAMLTemplate[1][0], AML_MERGE_TEMPLATE_SIZE, nHeight)));
     PelUnitBuf pcBufPredCurLeft = (PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvCurAMLTemplate[1][0], AML_MERGE_TEMPLATE_SIZE, nHeight)));
-    
+
     getBlkAMLRefTemplate(pu, pcBufPredRefTop, pcBufPredRefLeft);
     
     if (m_bAMLTemplateAvailabe[0])
     {
       m_pcRdCost->setDistParam(cDistParam, pcBufPredCurTop.Y(), pcBufPredRefTop.Y(), pu.cs->sps->getBitDepth(CHANNEL_TYPE_LUMA), COMPONENT_Y, false);
-      
+
       uiCost += cDistParam.distFunc(cDistParam);
     }
-    
+
     if (m_bAMLTemplateAvailabe[1])
     {
       m_pcRdCost->setDistParam(cDistParam, pcBufPredCurLeft.Y(), pcBufPredRefLeft.Y(), pu.cs->sps->getBitDepth(CHANNEL_TYPE_LUMA), COMPONENT_Y, false);
       
       uiCost += cDistParam.distFunc(cDistParam);
     }
+#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC
+    if (m_bAMLTemplateAvailabe[0] && !m_bAMLTemplateAvailabe[1])
+    {
+      uiCost += (uiCost * nHeight) / nWidth;
+    }
+    if (!m_bAMLTemplateAvailabe[0] && m_bAMLTemplateAvailabe[1])
+    {
+      uiCost += (uiCost * nWidth) / nHeight;
+    }
+#endif
     // update part
     uint32_t i;
     uint32_t shift = 0;
@@ -5974,98 +6323,397 @@ void  InterPrediction::sortInterMergeMMVDCandidates(PredictionUnit &pu, MergeCtx
     }
   }
   
+#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC
+  Distortion lambdaTh = pu.cs->slice->getCostForARMC();
+  startMMVDIdx = 0;
+  endMMVDIdx = MMVD_BASE_MV_NUM;
+  if (MMVDIdx != -1)
+  {
+    uint32_t gpId = MMVDIdx / groupSize;
+    startMMVDIdx = gpId;
+    endMMVDIdx = (gpId + 1);
+  }
+
+  for (int mmvdBaseIdx = startMMVDIdx; mmvdBaseIdx < endMMVDIdx; mmvdBaseIdx++)
+  {
+    uint32_t startIdx = (mmvdBaseIdx)*groupSize;
+    int maxCand = (MMVD_MAX_REFINE_NUM >> MMVD_SIZE_SHIFT);
+    bool enoughDiverse = false;
+    uint32_t diverseCand = 0;
+    uint32_t posToBeInserted = 0;
+    for (uint32_t uiCand = startIdx; uiCand < startIdx + maxCand - 1; ++uiCand)
+    {
+      for (uint32_t uiMergeCand = uiCand + 1; uiMergeCand < startIdx + groupSize - 2; ++uiMergeCand)
+      {
+        if (lambdaTh <= abs((int)(candCostList[uiMergeCand] - candCostList[uiCand])))
+        {
+          enoughDiverse = true;
+          for (uint32_t uiMergeCand3 = startIdx; uiMergeCand3 < uiCand; ++uiMergeCand3)
+          {
+            if (lambdaTh > abs((int)(candCostList[uiMergeCand] - candCostList[uiMergeCand3])))
+            {
+              enoughDiverse = false;
+              break;
+            }
+          }
+
+          if (enoughDiverse)
+          {
+            diverseCand = uiMergeCand;
+            posToBeInserted = uiCand + 1;
+            break;
+          }
+        }
+      }
+      if (enoughDiverse)
+      {
+        Distortion saveCandCost = candCostList[diverseCand];
+        uint32_t   mmvdLUTSave = mmvdLUT[diverseCand];
+
+        for (int i = diverseCand; i > posToBeInserted - 1; i--)
+        {
+          candCostList[i] = candCostList[i - 1];
+          mmvdLUT[i] = mmvdLUT[i - 1];
+        }
+        candCostList[posToBeInserted] = saveCandCost;
+        mmvdLUT[posToBeInserted] = mmvdLUTSave;
+      }
+    }
+  }
+#endif
 }
 #endif
+#endif
 
 #if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
-void  InterPrediction::sortAffineMergeCandidates(PredictionUnit pu, AffineMergeCtx& affMrgCtx, uint32_t * affMmvdLUT, uint32_t afMMVDIdx)
+#if JVET_AA0093_ENHANCED_MMVD_EXTENSION
+void  InterPrediction::sortAffineMergeCandidates(PredictionUnit pu, AffineMergeCtx& affMrgCtx, uint32_t * affMmvdLUT, int16_t afMMVDIdx, bool fromStart)
 {
-  const int tempNum = AF_MMVD_NUM;
   int baseIdxToMergeIdxOffset = (int)PU::getMergeIdxFromAfMmvdBaseIdx(affMrgCtx, 0);
   int baseCount               = std::min<int>((int)AF_MMVD_BASE_NUM, affMrgCtx.numValidMergeCand - baseIdxToMergeIdxOffset);
+  const int tempNum = baseCount * AF_MMVD_MAX_REFINE_NUM;
   const int groupSize = std::min<int>(tempNum, ADAPTIVE_SUB_GROUP_SIZE_MMVD_AFF);
+#if _WINDOWS
+  Distortion candCostList[AF_MMVD_BASE_NUM * AF_MMVD_MAX_REFINE_NUM];
+#else
   Distortion candCostList[tempNum];
+#endif
   for (uint32_t i = 0; i < tempNum; i++)
   {
     affMmvdLUT[i] = i;
     candCostList[i] = MAX_UINT;
   }
-  
+
   if (baseCount < 1)
   {
     return;
   }
   Distortion uiCost;
-  
+
   DistParam cDistParam;
   cDistParam.applyWeight = false;
-  
+
   int nWidth = pu.lumaSize().width;
   int nHeight = pu.lumaSize().height;
-  
+
   if (!xAMLGetCurBlkTemplate(pu, nWidth, nHeight))
   {
     return;
   }
-  
+
   int startMMVDIdx = 0;
   int endMMVDIdx = tempNum;
+  int8_t gpId = -1;
+  int stepCutoff = AF_MMVD_STEP_NUM >> 1;
   if(afMMVDIdx != -1)
   {
-    uint32_t gpId = afMMVDIdx/groupSize;
-    startMMVDIdx = gpId * groupSize;
-    endMMVDIdx = (gpId+1) * groupSize;
+    gpId = afMMVDIdx/groupSize;
+    startMMVDIdx = fromStart ? 0 :  gpId * groupSize;
+    endMMVDIdx = (gpId + 2) * groupSize;
+    gpId += (afMMVDIdx % 2);
   }
   int shiftEnc = AFFINE_MMVD_SIZE_SHIFT;
   int encGrpSize = groupSize >> shiftEnc;
-  for (int mmvdMergeCand = startMMVDIdx; mmvdMergeCand < endMMVDIdx; mmvdMergeCand++)
-  {
-    pu.afMmvdMergeIdx = (uint8_t)mmvdMergeCand;
-    
-    int baseIdx = (int)mmvdMergeCand / AF_MMVD_MAX_REFINE_NUM;
-    int stepIdx = (int)mmvdMergeCand - baseIdx * AF_MMVD_MAX_REFINE_NUM;
-    int dirIdx  = stepIdx % AF_MMVD_OFFSET_DIR;
-    stepIdx = stepIdx / AF_MMVD_OFFSET_DIR;
-    
-    pu.cu->affine = true;
-    pu.cu->imv    = IMV_OFF;
-    pu.cu->mmvdSkip         = false;
-    pu.regularMergeFlag = false;
-    pu.mmvdMergeFlag    = false;
-    pu.mergeFlag      = true;
-    pu.afMmvdFlag     = true;
+  encGrpSize /= AFFINE_BI_DIR; //changed
+  pu.cu->affine = true;
+  pu.cu->imv    = IMV_OFF;
+  pu.cu->mmvdSkip         = false;
+  pu.regularMergeFlag = false;
+  pu.mmvdMergeFlag    = false;
+  pu.mergeFlag      = true;
+  pu.afMmvdFlag     = true;
+  pu.cu->LICFlag = false;
+  pu.ciipFlag = false;
+  //Store
+  int8_t posList0 = 0;
+  int8_t posList1 = 0;
+  bool load0 = false;
+  bool load1 = false;
+
+  for (int fPosBaseIdx = startMMVDIdx/AF_MMVD_MAX_REFINE_NUM; fPosBaseIdx < endMMVDIdx/AF_MMVD_MAX_REFINE_NUM; fPosBaseIdx++)
+  {
+    int baseIdx = fPosBaseIdx;
     pu.afMmvdBaseIdx  = (uint8_t)baseIdx;
-    pu.afMmvdDir      = (uint8_t)dirIdx;
-    pu.afMmvdStep     = (uint8_t)stepIdx;
     pu.mergeIdx       = (uint8_t)(baseIdxToMergeIdxOffset + baseIdx);
     pu.mergeType = affMrgCtx.mergeType[pu.mergeIdx];
-#if INTER_LIC
-    pu.cu->LICFlag = affMrgCtx.LICFlags[pu.mergeIdx];
-    pu.cu->LICFlag = false;
-#endif
     pu.interDir = affMrgCtx.interDirNeighbours[pu.mergeIdx];
     pu.cu->affineType = affMrgCtx.affineType[pu.mergeIdx];
     pu.cu->BcwIdx = affMrgCtx.BcwIdx[pu.mergeIdx];
-    pu.ciipFlag = false;
-    MvField mvfMmvd[2][3];
-    PU::getAfMmvdMvf(pu, affMrgCtx, mvfMmvd, pu.mergeIdx, pu.afMmvdStep, pu.afMmvdDir);
-#if JVET_Z0067_RPR_ENABLE
-    bool  bIsRefScaled = false;
-#endif
-    for (int i = 0; i < 2; i++)
+    //Store
+    posList0 = 0;
+    posList1 = 0;
+    load0 = false;
+    load1 = false;
+    int startSub = 0;
+    int endSub = AF_MMVD_MAX_REFINE_NUM;
+    if (!fromStart)
     {
-      if( pu.cs->slice->getNumRefIdx( RefPicList( i ) ) > 0 )
+      if (gpId % 2)
       {
-        pu.mvpIdx[i] = 0;
-        pu.mvpNum[i] = 0;
-        pu.mvd[i]    = Mv();
-        pu.refIdx[i] = mvfMmvd[i][0].refIdx;
-        pu.mvAffi[i][0] = mvfMmvd[i][0].mv;
-        pu.mvAffi[i][1] = mvfMmvd[i][1].mv;
-        pu.mvAffi[i][2] = mvfMmvd[i][2].mv;
+        startSub = groupSize;
       }
-#if JVET_Z0067_RPR_ENABLE
-      if ( !bIsRefScaled && pu.refIdx[i]>=0 && pu.cu->slice->getRefPic(i ? REF_PIC_LIST_1 : REF_PIC_LIST_0, pu.refIdx[i])->isRefScaled(pu.cs->pps) )
+      else
+      {
+        endSub = groupSize;
+      }
+    }
+    for (int tempIdx = startSub; tempIdx < endSub; tempIdx++)
+    {
+      uint16_t mmvdMergeCand = fPosBaseIdx * AF_MMVD_MAX_REFINE_NUM + tempIdx;
+      pu.afMmvdMergeIdx = (uint16_t)mmvdMergeCand;
+      int stepIdx = tempIdx;
+      int dirIdx  = stepIdx % AF_MMVD_OFFSET_DIR;
+      int fPosPosition1 = dirIdx % 8;
+      stepIdx = stepIdx / AF_MMVD_OFFSET_DIR;
+      pu.afMmvdDir      = (uint8_t)dirIdx;
+      pu.afMmvdStep     = (uint8_t)stepIdx;
+      //changed
+      if ((pu.afMmvdDir >= 8) && (pu.interDir < 3))
+      {
+        continue;
+      }
+      MvField mvfMmvd[2][3];
+      PU::getAfMmvdMvf(pu, affMrgCtx, mvfMmvd, pu.mergeIdx, pu.afMmvdStep, pu.afMmvdDir);
+#if JVET_Z0067_RPR_ENABLE
+      bool  bIsRefScaled = false;
+#endif
+      for (int i = 0; i < 2; i++)
+      {
+        if( pu.cs->slice->getNumRefIdx( RefPicList( i ) ) > 0 )
+        {
+          pu.mvpIdx[i] = 0;
+          pu.mvpNum[i] = 0;
+          pu.mvd[i]    = Mv();
+          pu.refIdx[i] = mvfMmvd[i][0].refIdx;
+          pu.mvAffi[i][0] = mvfMmvd[i][0].mv;
+          pu.mvAffi[i][1] = mvfMmvd[i][1].mv;
+          pu.mvAffi[i][2] = mvfMmvd[i][2].mv;
+        }
+#if JVET_Z0067_RPR_ENABLE
+        if ( !bIsRefScaled && pu.refIdx[i]>=0 && pu.cu->slice->getRefPic(i ? REF_PIC_LIST_1 : REF_PIC_LIST_0, pu.refIdx[i])->isRefScaled(pu.cs->pps) )
+        {
+          bIsRefScaled = true;
+        }
+#endif
+      }
+      //Store
+      if (pu.interDir == 3)
+      {
+        if (dirIdx < 8)
+        {
+          posList0 = fPosPosition1 + 1;
+          posList1 = 0;
+          load0 = false;
+          load1 = (fPosPosition1 != 0) || (stepIdx != 0 && stepIdx != stepCutoff );
+        }
+        else if (dirIdx < 16)
+        {
+          posList0 = 0;
+          posList1 = fPosPosition1 + 1;
+          load0 = (fPosPosition1 != 0) || (stepIdx != 0 && stepIdx != stepCutoff );
+          load1 = false;
+        }
+        else
+        {
+          const int poc0 = pu.cu->slice->getRefPOC(REF_PIC_LIST_0, mvfMmvd[0][0].refIdx);
+          const int poc1 = pu.cu->slice->getRefPOC(REF_PIC_LIST_1, mvfMmvd[0][0].refIdx);
+          const int currPoc = pu.cu->slice->getPOC();
+          if ((poc1 - currPoc)*(poc0 - currPoc) > 0)
+          {
+            posList0 = fPosPosition1 + 1;
+            posList1 = fPosPosition1 + 1;
+            load0 = true;
+            load1 = true;
+          }
+          else
+          {
+            posList0 = fPosPosition1 + 1;
+            posList1 = (fPosPosition1 ^ 1) + 1;
+            load0 = true;
+            load1 = true;
+          }
+        }
+      }
+
+      uiCost = 0;
+#if JVET_Z0067_RPR_ENABLE
+      if ( bIsRefScaled )
+      {
+        uiCost = std::numeric_limits<Distortion>::max();
+      }
+      else
+      {
+#endif
+        PelUnitBuf pcBufPredRefTop = (PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefAMLTemplate[0][0], nWidth, AML_MERGE_TEMPLATE_SIZE)));
+        PelUnitBuf pcBufPredCurTop = (PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvCurAMLTemplate[0][0], nWidth, AML_MERGE_TEMPLATE_SIZE)));
+        PelUnitBuf pcBufPredRefLeft = (PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefAMLTemplate[1][0], AML_MERGE_TEMPLATE_SIZE, nHeight)));
+        PelUnitBuf pcBufPredCurLeft = (PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvCurAMLTemplate[1][0], AML_MERGE_TEMPLATE_SIZE, nHeight)));
+        //Store
+        if (pu.interDir == 3)
+        {
+          getAffAMLRefTemplate(pu, pcBufPredRefTop, pcBufPredRefLeft, posList0, posList1, load0, load1);
+        }
+        else
+        {
+          getAffAMLRefTemplate(pu, pcBufPredRefTop, pcBufPredRefLeft);
+        }
+        if (m_bAMLTemplateAvailabe[0])
+        {
+          m_pcRdCost->setDistParam(cDistParam, pcBufPredCurTop.Y(), pcBufPredRefTop.Y(), pu.cs->sps->getBitDepth(CHANNEL_TYPE_LUMA), COMPONENT_Y, false);
+          
+          uiCost += cDistParam.distFunc(cDistParam);
+        }
+        
+        if (m_bAMLTemplateAvailabe[1])
+        {
+          m_pcRdCost->setDistParam(cDistParam, pcBufPredCurLeft.Y(), pcBufPredRefLeft.Y(), pu.cs->sps->getBitDepth(CHANNEL_TYPE_LUMA), COMPONENT_Y, false);
+          
+          uiCost += cDistParam.distFunc(cDistParam);
+        }
+#if JVET_Z0067_RPR_ENABLE
+      }
+#endif
+
+      // update part
+      uint32_t i;
+      uint32_t shift = 0;
+      uint32_t gpIdx = mmvdMergeCand/groupSize;
+      uint32_t endIdx = gpIdx * groupSize + encGrpSize;
+      while (shift < encGrpSize && uiCost < candCostList[endIdx - 1 - shift])
+      {
+        shift++;
+      }
+
+      if (shift != 0)
+      {
+        for (i = 1; i < shift; i++)
+        {
+          affMmvdLUT[endIdx - i] = affMmvdLUT[endIdx - 1 - i];
+          candCostList[endIdx - i] = candCostList[endIdx - 1 - i];
+        }
+        affMmvdLUT[endIdx - shift] = mmvdMergeCand;
+        candCostList[endIdx - shift] = uiCost;
+      }
+    }
+    for (int j = encGrpSize - 1; j >= 0 ; j--)
+    {
+      affMmvdLUT[fPosBaseIdx * AF_MMVD_MAX_REFINE_NUM + 2*j] = affMmvdLUT[fPosBaseIdx * AF_MMVD_MAX_REFINE_NUM + j];
+    }
+    for (int j = 0; j < encGrpSize ; j++)
+    {
+      affMmvdLUT[fPosBaseIdx * AF_MMVD_MAX_REFINE_NUM + 2*j + 1] = affMmvdLUT[fPosBaseIdx * AF_MMVD_MAX_REFINE_NUM + groupSize + j];
+    }
+  }
+}
+#else
+void  InterPrediction::sortAffineMergeCandidates(PredictionUnit pu, AffineMergeCtx& affMrgCtx, uint32_t * affMmvdLUT, uint32_t afMMVDIdx)
+{
+  const int tempNum = AF_MMVD_NUM;
+  int baseIdxToMergeIdxOffset = (int)PU::getMergeIdxFromAfMmvdBaseIdx(affMrgCtx, 0);
+  int baseCount               = std::min<int>((int)AF_MMVD_BASE_NUM, affMrgCtx.numValidMergeCand - baseIdxToMergeIdxOffset);
+  const int groupSize = std::min<int>(tempNum, ADAPTIVE_SUB_GROUP_SIZE_MMVD_AFF);
+  Distortion candCostList[tempNum];
+  for (uint32_t i = 0; i < tempNum; i++)
+  {
+    affMmvdLUT[i] = i;
+    candCostList[i] = MAX_UINT;
+  }
+  
+  if (baseCount < 1)
+  {
+    return;
+  }
+  Distortion uiCost;
+  
+  DistParam cDistParam;
+  cDistParam.applyWeight = false;
+  
+  int nWidth = pu.lumaSize().width;
+  int nHeight = pu.lumaSize().height;
+  
+  if (!xAMLGetCurBlkTemplate(pu, nWidth, nHeight))
+  {
+    return;
+  }
+  
+  int startMMVDIdx = 0;
+  int endMMVDIdx = tempNum;
+  if(afMMVDIdx != -1)
+  {
+    uint32_t gpId = afMMVDIdx/groupSize;
+    startMMVDIdx = gpId * groupSize;
+    endMMVDIdx = (gpId+1) * groupSize;
+  }
+  int shiftEnc = AFFINE_MMVD_SIZE_SHIFT;
+  int encGrpSize = groupSize >> shiftEnc;
+  for (int mmvdMergeCand = startMMVDIdx; mmvdMergeCand < endMMVDIdx; mmvdMergeCand++)
+  {
+    pu.afMmvdMergeIdx = (uint8_t)mmvdMergeCand;
+    
+    int baseIdx = (int)mmvdMergeCand / AF_MMVD_MAX_REFINE_NUM;
+    int stepIdx = (int)mmvdMergeCand - baseIdx * AF_MMVD_MAX_REFINE_NUM;
+    int dirIdx  = stepIdx % AF_MMVD_OFFSET_DIR;
+    stepIdx = stepIdx / AF_MMVD_OFFSET_DIR;
+    
+    pu.cu->affine = true;
+    pu.cu->imv    = IMV_OFF;
+    pu.cu->mmvdSkip         = false;
+    pu.regularMergeFlag = false;
+    pu.mmvdMergeFlag    = false;
+    pu.mergeFlag      = true;
+    pu.afMmvdFlag     = true;
+    pu.afMmvdBaseIdx  = (uint8_t)baseIdx;
+    pu.afMmvdDir      = (uint8_t)dirIdx;
+    pu.afMmvdStep     = (uint8_t)stepIdx;
+    pu.mergeIdx       = (uint8_t)(baseIdxToMergeIdxOffset + baseIdx);
+    pu.mergeType = affMrgCtx.mergeType[pu.mergeIdx];
+#if INTER_LIC
+    pu.cu->LICFlag = affMrgCtx.LICFlags[pu.mergeIdx];
+    pu.cu->LICFlag = false;
+#endif
+    pu.interDir = affMrgCtx.interDirNeighbours[pu.mergeIdx];
+    pu.cu->affineType = affMrgCtx.affineType[pu.mergeIdx];
+    pu.cu->BcwIdx = affMrgCtx.BcwIdx[pu.mergeIdx];
+    pu.ciipFlag = false;
+    MvField mvfMmvd[2][3];
+    PU::getAfMmvdMvf(pu, affMrgCtx, mvfMmvd, pu.mergeIdx, pu.afMmvdStep, pu.afMmvdDir);
+#if JVET_Z0067_RPR_ENABLE
+    bool  bIsRefScaled = false;
+#endif
+    for (int i = 0; i < 2; i++)
+    {
+      if( pu.cs->slice->getNumRefIdx( RefPicList( i ) ) > 0 )
+      {
+        pu.mvpIdx[i] = 0;
+        pu.mvpNum[i] = 0;
+        pu.mvd[i]    = Mv();
+        pu.refIdx[i] = mvfMmvd[i][0].refIdx;
+        pu.mvAffi[i][0] = mvfMmvd[i][0].mv;
+        pu.mvAffi[i][1] = mvfMmvd[i][1].mv;
+        pu.mvAffi[i][2] = mvfMmvd[i][2].mv;
+      }
+#if JVET_Z0067_RPR_ENABLE
+      if ( !bIsRefScaled && pu.refIdx[i]>=0 && pu.cu->slice->getRefPic(i ? REF_PIC_LIST_1 : REF_PIC_LIST_0, pu.refIdx[i])->isRefScaled(pu.cs->pps) )
       {
         bIsRefScaled = true;
       }
@@ -6127,6 +6775,7 @@ void  InterPrediction::sortAffineMergeCandidates(PredictionUnit pu, AffineMergeC
   }
 }
 #endif
+#endif
 
 #if JVET_W0090_ARMC_TM
 #if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING
@@ -6215,12 +6864,19 @@ void InterPrediction::adjustMergeCandidates(PredictionUnit& pu, MergeCtx& mvpMer
 
   const int numCandInCategory = std::min(numRetrievedMergeCand, mvpMergeCandCtx.numValidMergeCand);
 
-  uint32_t RdCandList[MRG_MAX_NUM_CANDS];
+#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC
+  uint32_t   rdCandList[NUM_MERGE_CANDS + MRG_MAX_NUM_CANDS];
+  Distortion candCostList[NUM_MERGE_CANDS + MRG_MAX_NUM_CANDS];
+
+  for (uint32_t j = 0; j < NUM_MERGE_CANDS + MRG_MAX_NUM_CANDS; j++)
+#else
+  uint32_t rdCandList[MRG_MAX_NUM_CANDS];
   Distortion candCostList[MRG_MAX_NUM_CANDS];
 
   for (uint32_t j = 0; j < MRG_MAX_NUM_CANDS; j++)
+#endif  
   {
-    RdCandList[j] = j;
+    rdCandList[j] = j;
     candCostList[j] = MAX_UINT64;
   }
 
@@ -6258,6 +6914,21 @@ void InterPrediction::adjustMergeCandidates(PredictionUnit& pu, MergeCtx& mvpMer
       PelUnitBuf pcBufPredRefLeft =
         (PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefAMLTemplate[1][0], AML_MERGE_TEMPLATE_SIZE, nHeight)));
 
+#if JVET_Z0067_RPR_ENABLE
+      bool bRefIsRescaled = false;
+      for (uint32_t refList = 0; refList < NUM_REF_PIC_LIST_01; refList++)
+      {
+        const RefPicList eRefPicList = refList ? REF_PIC_LIST_1 : REF_PIC_LIST_0;
+        bRefIsRescaled |= (pu.refIdx[refList] >= 0) ? pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[refList])->isRefScaled(pu.cs->pps) : false;
+      }
+      if (bRefIsRescaled)
+      {
+        uiCost = std::numeric_limits<Distortion>::max();
+      }
+      else
+      {
+#endif
+
       getBlkAMLRefTemplate(pu, pcBufPredRefTop, pcBufPredRefLeft);
 
       if (m_bAMLTemplateAvailabe[0])
@@ -6275,160 +6946,593 @@ void InterPrediction::adjustMergeCandidates(PredictionUnit& pu, MergeCtx& mvpMer
 
         uiCost += cDistParam.distFunc(cDistParam);
       }
+#if JVET_Z0067_RPR_ENABLE
+      }
+#endif
+
+#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC 
+      if (m_bAMLTemplateAvailabe[0] && !m_bAMLTemplateAvailabe[1])
+      {
+        uiCost += (uiCost * nHeight) / nWidth;
+      }
+      if (!m_bAMLTemplateAvailabe[0] && m_bAMLTemplateAvailabe[1])
+      {
+        uiCost += (uiCost * nWidth) / nHeight;
+      }
+#endif
     }
     else
     {
       uiCost = mvpMergeCandCtx.candCost[uiMergeCand];
     }
     
-    updateCandList(uiMergeCand, uiCost, mvpMergeCandCtx.numValidMergeCand, RdCandList, candCostList);
+    updateCandList(uiMergeCand, uiCost, mvpMergeCandCtx.numValidMergeCand, rdCandList, candCostList);
 
   }
   pu.mergeIdx = origMergeIdx;
 
-  updateCandInOneCandidateGroup(mvpMergeCandCtx, RdCandList, mvpMergeCandCtx.numValidMergeCand);
+#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC
+  MergeCtx pairMergeCand;
+  pairMergeCand.numValidMergeCand = 0;
+  pairMergeCand.numCandToTestEnc = 0;
 
-  for (int idx = 0; idx < mvpMergeCandCtx.numValidMergeCand; idx++)
-  {
-    mvpMergeCandCtx.candCost[idx] = candCostList[idx];
-  }
+  bool pairAdded = false;
 
-  mvpMergeCandCtx.numValidMergeCand = numCandInCategory;
+  if (mvpMergeCandCtx.numCandToTestEnc > 1 )
+  { 
+    int          cnt = 0;
+    int maxPairToBeAdded = std::min(mvpMergeCandCtx.numCandToTestEnc, numCandInCategory); 
+    if (pu.tmMergeFlag)
+    {
+      maxPairToBeAdded = std::min(mvpMergeCandCtx.numCandToTestEnc, TM_MRG_MAX_NUM_INIT_CANDS);
+    }
 
-  for (int idx = 0; idx < numCandInCategory; idx++)
-  {
-    mvpMergeCandCtx.candCost[idx] = candCostList[idx];
-  }
-}
-#endif
+    int cand1 = 0;
+    cnt = 0;
+    for (int cand2 = 1; cand2 < std::min(maxPairToBeAdded, MRG_MAX_NUM_CANDS); cand2++)
+    {
+      if (cand1 == cand2)
+      {
+        continue;
+      }
 
-void  InterPrediction::updateCandInOneCandidateGroup(MergeCtx& mrgCtx, uint32_t* RdCandList, int numCandInCategory)
-{
-  MergeCtx mrgCtxTmp;
-  for (uint32_t uiMergeCand = 0; uiMergeCand < mrgCtx.numValidMergeCand; uiMergeCand++)
-  {
-    mrgCtxTmp.BcwIdx[uiMergeCand] = mrgCtx.BcwIdx[uiMergeCand];
-    mrgCtxTmp.interDirNeighbours[uiMergeCand] = mrgCtx.interDirNeighbours[uiMergeCand];
-    mrgCtxTmp.mvFieldNeighbours[(uiMergeCand << 1)] = mrgCtx.mvFieldNeighbours[(uiMergeCand << 1)];
-    mrgCtxTmp.mvFieldNeighbours[(uiMergeCand << 1) + 1] = mrgCtx.mvFieldNeighbours[(uiMergeCand << 1) + 1];
-    mrgCtxTmp.useAltHpelIf[uiMergeCand] = mrgCtx.useAltHpelIf[uiMergeCand];
-#if INTER_LIC 
-    mrgCtxTmp.LICFlags[uiMergeCand] = mrgCtx.LICFlags[uiMergeCand];
+      pairMergeCand.mvFieldNeighbours[cnt * 2].setMvField(Mv(0, 0), NOT_VALID);
+      pairMergeCand.mvFieldNeighbours[cnt * 2 + 1].setMvField(Mv(0, 0), NOT_VALID);
+
+#if INTER_LIC
+      pairMergeCand.LICFlags[cnt] = mvpMergeCandCtx.LICFlags[rdCandList[0]];
 #endif
+      pairMergeCand.BcwIdx[cnt] = mvpMergeCandCtx.BcwIdx[rdCandList[0]];
+      pairMergeCand.useAltHpelIf[cnt] = mvpMergeCandCtx.useAltHpelIf[rdCandList[0]];
+      pairMergeCand.candCost[cnt] = MAX_UINT64;
 #if MULTI_HYP_PRED
-    mrgCtxTmp.addHypNeighbours[uiMergeCand] = mrgCtx.addHypNeighbours[uiMergeCand];
+      pairMergeCand.addHypNeighbours[cnt].clear();
 #endif
-  }
-  //update
-  for (uint32_t uiMergeCand = 0; uiMergeCand < numCandInCategory; uiMergeCand++)
-  {
-    mrgCtx.BcwIdx[uiMergeCand] = mrgCtxTmp.BcwIdx[RdCandList[uiMergeCand]];
-    mrgCtx.interDirNeighbours[uiMergeCand] = mrgCtxTmp.interDirNeighbours[RdCandList[uiMergeCand]];
-    mrgCtx.mvFieldNeighbours[(uiMergeCand << 1)] = mrgCtxTmp.mvFieldNeighbours[(RdCandList[uiMergeCand] << 1)];
-    mrgCtx.mvFieldNeighbours[(uiMergeCand << 1) + 1] = mrgCtxTmp.mvFieldNeighbours[(RdCandList[uiMergeCand] << 1) + 1];
-    mrgCtx.useAltHpelIf[uiMergeCand] = mrgCtxTmp.useAltHpelIf[RdCandList[uiMergeCand]];
+
+      // calculate average MV for L0 and L1 seperately
+      unsigned char interDir = 0;
+      for (int refListId = 0; refListId < (pu.cu->slice->isInterB() ? 2 : 1); refListId++)
+      {
+        const short refIdxI = mvpMergeCandCtx.mvFieldNeighbours[rdCandList[cand1] * 2 + refListId].refIdx;
+        const short refIdxJ = mvpMergeCandCtx.mvFieldNeighbours[rdCandList[cand2] * 2 + refListId].refIdx;
+
+        // both MVs are invalid, skip
+        if ((refIdxI == NOT_VALID) && (refIdxJ == NOT_VALID))
+        {
+          continue;
+        }
+
+        interDir += 1 << refListId;
+        // both MVs are valid, average these two MVs
+        if ((refIdxI != NOT_VALID) && (refIdxJ != NOT_VALID) && refIdxI == refIdxJ)
+        {
+          const Mv& mvI = mvpMergeCandCtx.mvFieldNeighbours[rdCandList[cand1] * 2 + refListId].mv;
+          const Mv& mvJ = mvpMergeCandCtx.mvFieldNeighbours[rdCandList[cand2] * 2 + refListId].mv;
+
+          // average two MVs
+          Mv avgMv = mvI;
+          avgMv += mvJ;
+          roundAffineMv(avgMv.hor, avgMv.ver, 1);
+
+          pairMergeCand.mvFieldNeighbours[cnt * 2 + refListId].setMvField(avgMv, refIdxI);
+        }
+        // only one MV is valid, take the only one MV
+        else if (refIdxI != NOT_VALID)
+        {
+          Mv singleMv = mvpMergeCandCtx.mvFieldNeighbours[rdCandList[cand1] * 2 + refListId].mv;
+          pairMergeCand.mvFieldNeighbours[cnt * 2 + refListId].setMvField(singleMv, refIdxI);
+        }
+        else if (refIdxJ != NOT_VALID)
+        {
+          Mv singleMv = mvpMergeCandCtx.mvFieldNeighbours[rdCandList[cand2] * 2 + refListId].mv;
+          pairMergeCand.mvFieldNeighbours[cnt * 2 + refListId].setMvField(singleMv, refIdxJ);
+        }
+      }
+
+      pairMergeCand.interDirNeighbours[cnt] = interDir;
+
+      if (interDir > 0)
+      {
 #if INTER_LIC
-    mrgCtx.LICFlags[uiMergeCand] = mrgCtxTmp.LICFlags[RdCandList[uiMergeCand]];
-#endif
-#if MULTI_HYP_PRED
-    mrgCtx.addHypNeighbours[uiMergeCand] = mrgCtxTmp.addHypNeighbours[RdCandList[uiMergeCand]];
+        if (interDir == 3)
+        {
+          pairMergeCand.LICFlags[cnt] = false;
+        }
 #endif
+        if (!pairMergeCand.xCheckSimilarMotion(cnt, pu.tmMergeFlag ? PU::getTMMvdThreshold(pu) : 1))
+        {
+          if (!mvpMergeCandCtx.xCheckSimilarMotion2Lists(cnt, &pairMergeCand, pu.tmMergeFlag ? PU::getTMMvdThreshold(pu) : 1))
+          {
+            pairAdded = true;
+            cnt++;
+            pairMergeCand.numValidMergeCand++;
+            pairMergeCand.numCandToTestEnc++;
+            if (pairMergeCand.numValidMergeCand == MAX_PAIR_CANDS)
+            {
+              break;
+            }
+          }
+        }
+      }
+    }
+
+    if (pairAdded)
+    {
+      for (uint32_t uiMergeCand = 0; uiMergeCand < pairMergeCand.numValidMergeCand; uiMergeCand++)
+      {
+        if (pairMergeCand.candCost[uiMergeCand] == MAX_UINT64)
+        {
+          uiCost = 0;
+          pairMergeCand.setMergeInfo(pu, uiMergeCand);
+
+          PelUnitBuf pcBufPredRefTop =
+            (PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefAMLTemplate[0][0], nWidth, AML_MERGE_TEMPLATE_SIZE)));
+          PelUnitBuf pcBufPredRefLeft =
+            (PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefAMLTemplate[1][0], AML_MERGE_TEMPLATE_SIZE, nHeight)));
+
+          getBlkAMLRefTemplate(pu, pcBufPredRefTop, pcBufPredRefLeft);
+
+          if (m_bAMLTemplateAvailabe[0])
+          {
+            m_pcRdCost->setDistParam(cDistParam, pcBufPredCurTop.Y(), pcBufPredRefTop.Y(),
+              pu.cs->sps->getBitDepth(CHANNEL_TYPE_LUMA), COMPONENT_Y, false);
+            uiCost += cDistParam.distFunc(cDistParam);
+          }
+          if (m_bAMLTemplateAvailabe[1])
+          {
+            m_pcRdCost->setDistParam(cDistParam, pcBufPredCurLeft.Y(), pcBufPredRefLeft.Y(),
+              pu.cs->sps->getBitDepth(CHANNEL_TYPE_LUMA), COMPONENT_Y, false);
+            uiCost += cDistParam.distFunc(cDistParam);
+          }
+          if (m_bAMLTemplateAvailabe[0] && !m_bAMLTemplateAvailabe[1])
+          {
+            uiCost += (uiCost * nHeight) / nWidth;
+          }
+          if (!m_bAMLTemplateAvailabe[0] && m_bAMLTemplateAvailabe[1])
+          {
+            uiCost += (uiCost * nWidth) / nHeight;
+          }
+        }
+        else
+        {
+          uiCost = pairMergeCand.candCost[uiMergeCand];
+        }
+        updateCandList((uiMergeCand+ mvpMergeCandCtx.numValidMergeCand), uiCost, (mvpMergeCandCtx.numValidMergeCand + pairMergeCand.numValidMergeCand), rdCandList, candCostList);
+      }
+      pu.mergeIdx = origMergeIdx;
+    }
+
+    Distortion cost = pu.cs->slice->getCostForARMC();
+    uint32_t   candToBeRemoved = NUM_MERGE_CANDS + MRG_MAX_NUM_CANDS;
+    Distortion min = MAX_UINT64;
+
+    for (int sizeCandList = mvpMergeCandCtx.numCandToTestEnc+ pairMergeCand.numValidMergeCand; sizeCandList > 1; sizeCandList--)
+    {
+      min = MAX_UINT64;
+      if(pu.tmMergeFlag)
+      {
+        candToBeRemoved = 0;
+        min = candCostList[0];
+      }
+      for (uint32_t uiMergeCand = 0; uiMergeCand < sizeCandList - 1; ++uiMergeCand)
+      {
+        if (min > abs((int)(candCostList[uiMergeCand + 1] - candCostList[uiMergeCand])))
+        {
+          min = abs((int)(candCostList[uiMergeCand + 1] - candCostList[uiMergeCand]));
+          candToBeRemoved = uiMergeCand + 1;
+        }
+      }
+      if (min < cost)
+      {
+        uint32_t candToBeReplaced = sizeCandList - 1;
+
+        for (uint32_t uiMergeCand = candToBeRemoved + 1; uiMergeCand < sizeCandList; ++uiMergeCand)
+        {
+          if (cost < abs((int)((int)candCostList[uiMergeCand] - (int)candCostList[candToBeRemoved])))
+          {
+            candToBeReplaced = uiMergeCand;
+            break;
+          }
+        }
+
+        if (sizeCandList > numCandInCategory)
+        {
+          candToBeReplaced = sizeCandList - 1;
+        }
+
+        uint32_t   rdCand = rdCandList[candToBeRemoved];
+        Distortion candCost = candCostList[(candToBeRemoved)];
+        for (int ui = candToBeRemoved; ui < (candToBeReplaced > sizeCandList - 1 ? sizeCandList - 1 : candToBeReplaced); ui++)
+        {
+          candCostList[ui] = candCostList[(ui + 1)];
+          rdCandList[ui] = rdCandList[(ui + 1)];
+        }
+        candCostList[candToBeReplaced] = candCost;
+        rdCandList[candToBeReplaced] = rdCand;
+      }
+      else
+      {
+        break;
+      }
+    }
+  }
+
+  updateCandInTwoCandidateGroups(mvpMergeCandCtx, rdCandList, mvpMergeCandCtx.numValidMergeCand, pairMergeCand);
+#else
+  updateCandInOneCandidateGroup(mvpMergeCandCtx, rdCandList, mvpMergeCandCtx.numValidMergeCand);
+#endif
+
+  for (int idx = 0; idx < mvpMergeCandCtx.numValidMergeCand; idx++)
+  {
+    mvpMergeCandCtx.candCost[idx] = candCostList[idx];
+  }
+
+  mvpMergeCandCtx.numValidMergeCand = numCandInCategory;
+
+#if !JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC
+  for (int idx = 0; idx < numCandInCategory; idx++)
+  {
+    mvpMergeCandCtx.candCost[idx] = candCostList[idx];
   }
+#endif
 }
 #endif
-
-void  InterPrediction::adjustInterMergeCandidates(PredictionUnit &pu, MergeCtx& mrgCtx, int mrgCandIdx)
-{
-  uint32_t RdCandList[MRG_MAX_NUM_CANDS][MRG_MAX_NUM_CANDS];
-  Distortion candCostList[MRG_MAX_NUM_CANDS][MRG_MAX_NUM_CANDS];
-
-  for (uint32_t i = 0; i < MRG_MAX_NUM_CANDS; i++)
-  {
-    for (uint32_t j = 0; j < MRG_MAX_NUM_CANDS; j++)
+
+#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC
+void  InterPrediction::updateCandInTwoCandidateGroups(MergeCtx& mrgCtx, uint32_t* rdCandList, int numCandInCategory, MergeCtx mrgCtx2)
+{
+  MergeCtx mrgCtxTmp;
+  for (uint32_t uiMergeCand = 0; uiMergeCand < mrgCtx.numValidMergeCand; uiMergeCand++)
+  {
+    mrgCtxTmp.BcwIdx[uiMergeCand] = mrgCtx.BcwIdx[uiMergeCand];
+    mrgCtxTmp.interDirNeighbours[uiMergeCand] = mrgCtx.interDirNeighbours[uiMergeCand];
+    mrgCtxTmp.mvFieldNeighbours[(uiMergeCand << 1)] = mrgCtx.mvFieldNeighbours[(uiMergeCand << 1)];
+    mrgCtxTmp.mvFieldNeighbours[(uiMergeCand << 1) + 1] = mrgCtx.mvFieldNeighbours[(uiMergeCand << 1) + 1];
+    mrgCtxTmp.useAltHpelIf[uiMergeCand] = mrgCtx.useAltHpelIf[uiMergeCand];
+#if INTER_LIC 
+    mrgCtxTmp.LICFlags[uiMergeCand] = mrgCtx.LICFlags[uiMergeCand];
+#endif
+#if MULTI_HYP_PRED
+    mrgCtxTmp.addHypNeighbours[uiMergeCand] = mrgCtx.addHypNeighbours[uiMergeCand];
+#endif
+
+  }
+  //update
+  for (uint32_t uiMergeCand = 0; uiMergeCand < numCandInCategory; uiMergeCand++)
+  {
+    if (rdCandList[uiMergeCand] >= mrgCtx.numValidMergeCand)
+    {
+      mrgCtx.BcwIdx[uiMergeCand] = mrgCtx2.BcwIdx[rdCandList[uiMergeCand] - mrgCtx.numValidMergeCand];
+      mrgCtx.interDirNeighbours[uiMergeCand] = mrgCtx2.interDirNeighbours[rdCandList[uiMergeCand] - mrgCtx.numValidMergeCand];
+      mrgCtx.mvFieldNeighbours[(uiMergeCand << 1)] = mrgCtx2.mvFieldNeighbours[((rdCandList[uiMergeCand] -mrgCtx.numValidMergeCand) << 1)];
+      mrgCtx.mvFieldNeighbours[(uiMergeCand << 1) + 1] = mrgCtx2.mvFieldNeighbours[((rdCandList[uiMergeCand] - mrgCtx.numValidMergeCand) << 1) + 1];
+      mrgCtx.useAltHpelIf[uiMergeCand] = mrgCtx2.useAltHpelIf[rdCandList[uiMergeCand] - mrgCtx.numValidMergeCand];
+#if INTER_LIC
+      mrgCtx.LICFlags[uiMergeCand] = mrgCtx2.LICFlags[rdCandList[uiMergeCand] - mrgCtx.numValidMergeCand];
+#endif
+#if MULTI_HYP_PRED
+      mrgCtx.addHypNeighbours[uiMergeCand] = mrgCtx2.addHypNeighbours[rdCandList[uiMergeCand] - mrgCtx.numValidMergeCand];
+#endif
+
+    }
+    else
+    {
+      mrgCtx.BcwIdx[uiMergeCand] = mrgCtxTmp.BcwIdx[rdCandList[uiMergeCand]];
+      mrgCtx.interDirNeighbours[uiMergeCand] = mrgCtxTmp.interDirNeighbours[rdCandList[uiMergeCand]];
+      mrgCtx.mvFieldNeighbours[(uiMergeCand << 1)] = mrgCtxTmp.mvFieldNeighbours[(rdCandList[uiMergeCand] << 1)];
+      mrgCtx.mvFieldNeighbours[(uiMergeCand << 1) + 1] = mrgCtxTmp.mvFieldNeighbours[(rdCandList[uiMergeCand] << 1) + 1];
+      mrgCtx.useAltHpelIf[uiMergeCand] = mrgCtxTmp.useAltHpelIf[rdCandList[uiMergeCand]];
+#if INTER_LIC
+      mrgCtx.LICFlags[uiMergeCand] = mrgCtxTmp.LICFlags[rdCandList[uiMergeCand]];
+#endif
+#if MULTI_HYP_PRED
+      mrgCtx.addHypNeighbours[uiMergeCand] = mrgCtxTmp.addHypNeighbours[rdCandList[uiMergeCand]];
+#endif
+    }
+  }
+}
+#endif
+
+void  InterPrediction::updateCandInOneCandidateGroup(MergeCtx& mrgCtx, uint32_t* rdCandList, int numCandInCategory)
+{
+  MergeCtx mrgCtxTmp;
+  for (uint32_t uiMergeCand = 0; uiMergeCand < mrgCtx.numValidMergeCand; uiMergeCand++)
+  {
+    mrgCtxTmp.BcwIdx[uiMergeCand] = mrgCtx.BcwIdx[uiMergeCand];
+    mrgCtxTmp.interDirNeighbours[uiMergeCand] = mrgCtx.interDirNeighbours[uiMergeCand];
+    mrgCtxTmp.mvFieldNeighbours[(uiMergeCand << 1)] = mrgCtx.mvFieldNeighbours[(uiMergeCand << 1)];
+    mrgCtxTmp.mvFieldNeighbours[(uiMergeCand << 1) + 1] = mrgCtx.mvFieldNeighbours[(uiMergeCand << 1) + 1];
+    mrgCtxTmp.useAltHpelIf[uiMergeCand] = mrgCtx.useAltHpelIf[uiMergeCand];
+#if INTER_LIC 
+    mrgCtxTmp.LICFlags[uiMergeCand] = mrgCtx.LICFlags[uiMergeCand];
+#endif
+#if MULTI_HYP_PRED
+    mrgCtxTmp.addHypNeighbours[uiMergeCand] = mrgCtx.addHypNeighbours[uiMergeCand];
+#endif
+  }
+  //update
+  for (uint32_t uiMergeCand = 0; uiMergeCand < numCandInCategory; uiMergeCand++)
+  {
+    mrgCtx.BcwIdx[uiMergeCand] = mrgCtxTmp.BcwIdx[rdCandList[uiMergeCand]];
+    mrgCtx.interDirNeighbours[uiMergeCand] = mrgCtxTmp.interDirNeighbours[rdCandList[uiMergeCand]];
+    mrgCtx.mvFieldNeighbours[(uiMergeCand << 1)] = mrgCtxTmp.mvFieldNeighbours[(rdCandList[uiMergeCand] << 1)];
+    mrgCtx.mvFieldNeighbours[(uiMergeCand << 1) + 1] = mrgCtxTmp.mvFieldNeighbours[(rdCandList[uiMergeCand] << 1) + 1];
+    mrgCtx.useAltHpelIf[uiMergeCand] = mrgCtxTmp.useAltHpelIf[rdCandList[uiMergeCand]];
+#if INTER_LIC
+    mrgCtx.LICFlags[uiMergeCand] = mrgCtxTmp.LICFlags[rdCandList[uiMergeCand]];
+#endif
+#if MULTI_HYP_PRED
+    mrgCtx.addHypNeighbours[uiMergeCand] = mrgCtxTmp.addHypNeighbours[rdCandList[uiMergeCand]];
+#endif
+  }
+}
+#endif
+
+void  InterPrediction::adjustInterMergeCandidates(PredictionUnit &pu, MergeCtx& mrgCtx, int mrgCandIdx)
+{
+  uint32_t RdCandList[MRG_MAX_NUM_CANDS][MRG_MAX_NUM_CANDS];
+  Distortion candCostList[MRG_MAX_NUM_CANDS][MRG_MAX_NUM_CANDS];
+
+  for (uint32_t i = 0; i < MRG_MAX_NUM_CANDS; i++)
+  {
+    for (uint32_t j = 0; j < MRG_MAX_NUM_CANDS; j++)
+    {
+      RdCandList[i][j] = j;
+      candCostList[i][j] = MAX_UINT;
+    }
+  }
+
+  Distortion uiCost;
+
+  DistParam cDistParam;
+  cDistParam.applyWeight = false;
+
+  /*const SPS &sps = *pu.cs->sps;
+  Position puPos = pu.lumaPos();*/
+  int nWidth = pu.lumaSize().width;
+  int nHeight = pu.lumaSize().height;
+
+  if (!xAMLGetCurBlkTemplate(pu, nWidth, nHeight))
+  {
+    return;
+  }
+
+#if JVET_X0049_ADAPT_DMVR
+#if JVET_AA0093_ENHANCED_MMVD_EXTENSION
+  uint16_t origMergeIdx = pu.mergeIdx;
+#else
+  uint8_t origMergeIdx = pu.mergeIdx;
+#endif
+#endif
+  for (uint32_t uiMergeCand = ((mrgCandIdx < 0) ? 0 : (mrgCandIdx / ADAPTIVE_SUB_GROUP_SIZE)*ADAPTIVE_SUB_GROUP_SIZE); uiMergeCand < (((mrgCandIdx < 0) || ((mrgCandIdx / ADAPTIVE_SUB_GROUP_SIZE + 1)*ADAPTIVE_SUB_GROUP_SIZE > mrgCtx.numValidMergeCand)) ? mrgCtx.numValidMergeCand : ((mrgCandIdx / ADAPTIVE_SUB_GROUP_SIZE + 1)*ADAPTIVE_SUB_GROUP_SIZE)); ++uiMergeCand)
+  {
+    bool firstGroup = (uiMergeCand / ADAPTIVE_SUB_GROUP_SIZE) == 0 ? true : false;
+    bool lastGroup = ((uiMergeCand / ADAPTIVE_SUB_GROUP_SIZE + 1)*ADAPTIVE_SUB_GROUP_SIZE >= mrgCtx.numValidMergeCand) ? true : false;
+    if (lastGroup && !firstGroup)
+    {
+      break;
+    }
+    uiCost = 0;
+
+    mrgCtx.setMergeInfo(pu, uiMergeCand);
+    PU::spanMotionInfo(pu, mrgCtx);
+
+    PelUnitBuf pcBufPredRefTop = (PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefAMLTemplate[0][0], nWidth, AML_MERGE_TEMPLATE_SIZE)));
+    PelUnitBuf pcBufPredCurTop = (PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvCurAMLTemplate[0][0], nWidth, AML_MERGE_TEMPLATE_SIZE)));
+    PelUnitBuf pcBufPredRefLeft = (PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefAMLTemplate[1][0], AML_MERGE_TEMPLATE_SIZE, nHeight)));
+    PelUnitBuf pcBufPredCurLeft = (PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvCurAMLTemplate[1][0], AML_MERGE_TEMPLATE_SIZE, nHeight)));
+
+#if JVET_Y0128_NON_CTC
+    bool bRefIsRescaled = false;
+    for (uint32_t refList = 0; refList < NUM_REF_PIC_LIST_01; refList++)
+    {
+      const RefPicList eRefPicList = refList ? REF_PIC_LIST_1 : REF_PIC_LIST_0;
+      bRefIsRescaled |= (pu.refIdx[refList] >= 0) ? pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[refList])->isRefScaled(pu.cs->pps) : false;
+    }
+    if ( !bRefIsRescaled )
+    {
+#endif
+    getBlkAMLRefTemplate(pu, pcBufPredRefTop, pcBufPredRefLeft);
+
+    if (m_bAMLTemplateAvailabe[0])
+    {
+      m_pcRdCost->setDistParam(cDistParam, pcBufPredCurTop.Y(), pcBufPredRefTop.Y(), pu.cs->sps->getBitDepth(CHANNEL_TYPE_LUMA), COMPONENT_Y, false);
+
+      uiCost += cDistParam.distFunc(cDistParam);
+    }
+
+    if (m_bAMLTemplateAvailabe[1])
+    {
+      m_pcRdCost->setDistParam(cDistParam, pcBufPredCurLeft.Y(), pcBufPredRefLeft.Y(), pu.cs->sps->getBitDepth(CHANNEL_TYPE_LUMA), COMPONENT_Y, false);
+
+      uiCost += cDistParam.distFunc(cDistParam);
+    }
+#if JVET_Y0128_NON_CTC
+    }
+#endif
+
+    updateCandList(uiMergeCand, uiCost, ADAPTIVE_SUB_GROUP_SIZE, RdCandList[uiMergeCand / ADAPTIVE_SUB_GROUP_SIZE], candCostList[uiMergeCand / ADAPTIVE_SUB_GROUP_SIZE]);
+  }
+#if JVET_X0049_ADAPT_DMVR
+  pu.mergeIdx = origMergeIdx;
+#else
+  pu.mergeIdx = mrgCandIdx;    //restore the merge index
+#endif
+  updateCandInfo(mrgCtx, RdCandList
+    , mrgCandIdx
+  );
+
+}
+#endif
+
+#if JVET_W0090_ARMC_TM
+#if JVET_AA0093_REFINED_MOTION_FOR_ARMC
+void InterPrediction::adjustMergeCandidatesInOneCandidateGroup(PredictionUnit &pu, MergeCtx& mvpMergeCandCtx, bool* applyBDMVR, Mv** mvBufBDMVR, Mv** mvBufBDMVRTmp, int numRetrievedMergeCand, bool subRefineList[][2], bool subRefineListTmp[][2], int mrgCandIdx)
+{
+  if (mvpMergeCandCtx.numValidMergeCand <= 1)
+  {
+    return;
+  }
+  if (!xAMLIsTopTempAvailable(pu) && !xAMLIsLeftTempAvailable(pu))
+  {
+    return;
+  }
+
+  const int numCandInCategory = std::min(numRetrievedMergeCand, mvpMergeCandCtx.numValidMergeCand);
+
+  uint32_t rdCandList[10];
+  Distortion candCostList[10];
+  for (uint32_t j = 0; j < 10; j++)
+  {
+    rdCandList[j] = j;
+    candCostList[j] = MAX_UINT;
+  }
+
+  Distortion uiCost;
+  DistParam cDistParam;
+  cDistParam.applyWeight = false;
+  auto origMergeIdx = pu.mergeIdx;
+  for (uint32_t uiMergeCand = 0; uiMergeCand < mvpMergeCandCtx.numValidMergeCand; uiMergeCand++)
+  {
+    if (mvpMergeCandCtx.numCandToTestEnc != mvpMergeCandCtx.numValidMergeCand)
+    {
+      if (uiMergeCand > mvpMergeCandCtx.numCandToTestEnc)
+      {
+        mvpMergeCandCtx.candCost[uiMergeCand] = MAX_UINT64 - 1;
+      }
+    }
+    if (pu.tmMergeFlag || (mvpMergeCandCtx.numCandToTestEnc != mvpMergeCandCtx.numValidMergeCand && uiMergeCand > mvpMergeCandCtx.numCandToTestEnc ))
+    {
+      uiCost = mvpMergeCandCtx.candCost[uiMergeCand];
+    }
+    else
+    {
+      uiCost = 0;
+      mvpMergeCandCtx.setMergeInfo(pu, uiMergeCand);
+      PelUnitBuf pcBufPredRefTop = (PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefAMLTemplate[0][0], pu.lwidth(), AML_MERGE_TEMPLATE_SIZE)));
+      PelUnitBuf pcBufPredCurTop = (PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvCurAMLTemplate[0][0], pu.lwidth(), AML_MERGE_TEMPLATE_SIZE)));
+      PelUnitBuf pcBufPredRefLeft = (PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefAMLTemplate[1][0], AML_MERGE_TEMPLATE_SIZE, pu.lheight())));
+      PelUnitBuf pcBufPredCurLeft = (PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvCurAMLTemplate[1][0], AML_MERGE_TEMPLATE_SIZE, pu.lheight())));
+#if JVET_Z0067_RPR_ENABLE
+      bool bRefIsRescaled = false;
+      for (uint32_t refList = 0; refList < NUM_REF_PIC_LIST_01; refList++)
+      {
+        const RefPicList eRefPicList = refList ? REF_PIC_LIST_1 : REF_PIC_LIST_0;
+        bRefIsRescaled |= (pu.refIdx[refList] >= 0) ? pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[refList])->isRefScaled(pu.cs->pps) : false;
+      }
+      if (bRefIsRescaled)
+      {
+        uiCost = std::numeric_limits<Distortion>::max();
+      }
+      else
+      {
+#endif
+
+      getBlkAMLRefTemplate(pu, pcBufPredRefTop, pcBufPredRefLeft);
+      if (m_bAMLTemplateAvailabe[0])
+      {
+        m_pcRdCost->setDistParam(cDistParam, pcBufPredCurTop.Y(), pcBufPredRefTop.Y(), pu.cs->sps->getBitDepth(CHANNEL_TYPE_LUMA), COMPONENT_Y, false);
+        uiCost += cDistParam.distFunc(cDistParam);
+      }
+      if (m_bAMLTemplateAvailabe[1])
+      {
+        m_pcRdCost->setDistParam(cDistParam, pcBufPredCurLeft.Y(), pcBufPredRefLeft.Y(), pu.cs->sps->getBitDepth(CHANNEL_TYPE_LUMA), COMPONENT_Y, false);
+        uiCost += cDistParam.distFunc(cDistParam);
+      }
+#if JVET_Z0067_RPR_ENABLE
+      }
+#endif
+
+    }
+    updateCandList(uiMergeCand, uiCost, numCandInCategory, rdCandList, candCostList);
+  }
+  pu.mergeIdx = origMergeIdx;
+
+  updateCandInOneCandidateGroup(mvpMergeCandCtx, rdCandList, applyBDMVR, mvBufBDMVR, mvBufBDMVRTmp, subRefineList, subRefineListTmp, numCandInCategory);
+}
+
+void  InterPrediction::updateCandInOneCandidateGroup(MergeCtx& mrgCtx, uint32_t* rdCandList, bool* applyBDMVR, Mv** mvBufBDMVR, Mv** mvBufBDMVRTmp, bool subRefineList[][2], bool subRefineListTmp[][2],int numCandInCategory)
+{
+  bool applyBDMVRTmp[10];
+  MergeCtx mrgCtxTmp;
+  for (uint32_t uiMergeCand = 0; uiMergeCand < mrgCtx.numValidMergeCand; uiMergeCand++)
+  {
+    mrgCtxTmp.BcwIdx[uiMergeCand] = mrgCtx.BcwIdx[uiMergeCand];
+    mrgCtxTmp.interDirNeighbours[uiMergeCand] = mrgCtx.interDirNeighbours[uiMergeCand];
+    mrgCtxTmp.mvFieldNeighbours[(uiMergeCand << 1)] = mrgCtx.mvFieldNeighbours[(uiMergeCand << 1)];
+    mrgCtxTmp.mvFieldNeighbours[(uiMergeCand << 1) + 1] = mrgCtx.mvFieldNeighbours[(uiMergeCand << 1) + 1];
+    mrgCtxTmp.useAltHpelIf[uiMergeCand] = mrgCtx.useAltHpelIf[uiMergeCand];
+#if INTER_LIC
+    mrgCtxTmp.LICFlags[uiMergeCand] = mrgCtx.LICFlags[uiMergeCand];
+#endif
+#if MULTI_HYP_PRED
+    mrgCtxTmp.addHypNeighbours[uiMergeCand] = mrgCtx.addHypNeighbours[uiMergeCand];
+#endif
+    if (applyBDMVR)
     {
-      RdCandList[i][j] = j;
-      candCostList[i][j] = MAX_UINT;
+      applyBDMVRTmp[uiMergeCand] = applyBDMVR[uiMergeCand];
     }
   }
-
-  Distortion uiCost;
-
-  DistParam cDistParam;
-  cDistParam.applyWeight = false;
-
-  /*const SPS &sps = *pu.cs->sps;
-  Position puPos = pu.lumaPos();*/
-  int nWidth = pu.lumaSize().width;
-  int nHeight = pu.lumaSize().height;
-
-  if (!xAMLGetCurBlkTemplate(pu, nWidth, nHeight))
+  //update
+  for (uint32_t uiMergeCand = 0; uiMergeCand < numCandInCategory; uiMergeCand++)
   {
-    return;
-  }
-
-#if JVET_X0049_ADAPT_DMVR
-  uint8_t origMergeIdx = pu.mergeIdx;
+    mrgCtx.BcwIdx[uiMergeCand] = mrgCtxTmp.BcwIdx[rdCandList[uiMergeCand]];
+    mrgCtx.interDirNeighbours[uiMergeCand] = mrgCtxTmp.interDirNeighbours[rdCandList[uiMergeCand]];
+    mrgCtx.mvFieldNeighbours[(uiMergeCand << 1)] = mrgCtxTmp.mvFieldNeighbours[(rdCandList[uiMergeCand] << 1)];
+    mrgCtx.mvFieldNeighbours[(uiMergeCand << 1) + 1] = mrgCtxTmp.mvFieldNeighbours[(rdCandList[uiMergeCand] << 1) + 1];
+    mrgCtx.useAltHpelIf[uiMergeCand] = mrgCtxTmp.useAltHpelIf[rdCandList[uiMergeCand]];
+#if INTER_LIC
+    mrgCtx.LICFlags[uiMergeCand] = mrgCtxTmp.LICFlags[rdCandList[uiMergeCand]];
 #endif
-  for (uint32_t uiMergeCand = ((mrgCandIdx < 0) ? 0 : (mrgCandIdx / ADAPTIVE_SUB_GROUP_SIZE)*ADAPTIVE_SUB_GROUP_SIZE); uiMergeCand < (((mrgCandIdx < 0) || ((mrgCandIdx / ADAPTIVE_SUB_GROUP_SIZE + 1)*ADAPTIVE_SUB_GROUP_SIZE > mrgCtx.numValidMergeCand)) ? mrgCtx.numValidMergeCand : ((mrgCandIdx / ADAPTIVE_SUB_GROUP_SIZE + 1)*ADAPTIVE_SUB_GROUP_SIZE)); ++uiMergeCand)
-  {
-    bool firstGroup = (uiMergeCand / ADAPTIVE_SUB_GROUP_SIZE) == 0 ? true : false;
-    bool lastGroup = ((uiMergeCand / ADAPTIVE_SUB_GROUP_SIZE + 1)*ADAPTIVE_SUB_GROUP_SIZE >= mrgCtx.numValidMergeCand) ? true : false;
-    if (lastGroup && !firstGroup)
+#if MULTI_HYP_PRED
+    mrgCtx.addHypNeighbours[uiMergeCand] = mrgCtxTmp.addHypNeighbours[rdCandList[uiMergeCand]];
+#endif
+    if (applyBDMVR)
     {
-      break;
+      applyBDMVR[uiMergeCand] = applyBDMVRTmp[rdCandList[uiMergeCand]];
     }
-    uiCost = 0;
-
-    mrgCtx.setMergeInfo(pu, uiMergeCand);
-    PU::spanMotionInfo(pu, mrgCtx);
-
-    PelUnitBuf pcBufPredRefTop = (PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefAMLTemplate[0][0], nWidth, AML_MERGE_TEMPLATE_SIZE)));
-    PelUnitBuf pcBufPredCurTop = (PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvCurAMLTemplate[0][0], nWidth, AML_MERGE_TEMPLATE_SIZE)));
-    PelUnitBuf pcBufPredRefLeft = (PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefAMLTemplate[1][0], AML_MERGE_TEMPLATE_SIZE, nHeight)));
-    PelUnitBuf pcBufPredCurLeft = (PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvCurAMLTemplate[1][0], AML_MERGE_TEMPLATE_SIZE, nHeight)));
-
-#if JVET_Y0128_NON_CTC
-    bool bRefIsRescaled = false;
-    for (uint32_t refList = 0; refList < NUM_REF_PIC_LIST_01; refList++)
+    if (mvBufBDMVR && mvBufBDMVRTmp)
     {
-      const RefPicList eRefPicList = refList ? REF_PIC_LIST_1 : REF_PIC_LIST_0;
-      bRefIsRescaled |= (pu.refIdx[refList] >= 0) ? pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[refList])->isRefScaled(pu.cs->pps) : false;
+      mvBufBDMVRTmp[(uiMergeCand << 1)] = mvBufBDMVR[(rdCandList[uiMergeCand] << 1)];
+      mvBufBDMVRTmp[(uiMergeCand << 1) + 1] = mvBufBDMVR[(rdCandList[uiMergeCand] << 1) + 1];
     }
-    if ( !bRefIsRescaled )
-    {
-#endif
-    getBlkAMLRefTemplate(pu, pcBufPredRefTop, pcBufPredRefLeft);
-
-    if (m_bAMLTemplateAvailabe[0])
+    if (subRefineList && subRefineListTmp)
     {
-      m_pcRdCost->setDistParam(cDistParam, pcBufPredCurTop.Y(), pcBufPredRefTop.Y(), pu.cs->sps->getBitDepth(CHANNEL_TYPE_LUMA), COMPONENT_Y, false);
-
-      uiCost += cDistParam.distFunc(cDistParam);
+      subRefineList[uiMergeCand][0] = subRefineListTmp[rdCandList[uiMergeCand]][0];
+      subRefineList[uiMergeCand][1] = subRefineListTmp[rdCandList[uiMergeCand]][1];
     }
-
-    if (m_bAMLTemplateAvailabe[1])
+  }
+  if (mvBufBDMVR && mvBufBDMVRTmp)
+  {
+    for (uint32_t uiMergeCand = 0; uiMergeCand < numCandInCategory; uiMergeCand++)
     {
-      m_pcRdCost->setDistParam(cDistParam, pcBufPredCurLeft.Y(), pcBufPredRefLeft.Y(), pu.cs->sps->getBitDepth(CHANNEL_TYPE_LUMA), COMPONENT_Y, false);
-
-      uiCost += cDistParam.distFunc(cDistParam);
-    }
-#if JVET_Y0128_NON_CTC
+      mvBufBDMVR[(uiMergeCand << 1)] = mvBufBDMVRTmp[(uiMergeCand << 1)];
+      mvBufBDMVR[(uiMergeCand << 1) + 1] = mvBufBDMVRTmp[(uiMergeCand << 1) + 1];
     }
-#endif
-
-    updateCandList(uiMergeCand, uiCost, ADAPTIVE_SUB_GROUP_SIZE, RdCandList[uiMergeCand / ADAPTIVE_SUB_GROUP_SIZE], candCostList[uiMergeCand / ADAPTIVE_SUB_GROUP_SIZE]);
   }
-#if JVET_X0049_ADAPT_DMVR
-  pu.mergeIdx = origMergeIdx;
-#else
-  pu.mergeIdx = mrgCandIdx;    //restore the merge index
-#endif
-  updateCandInfo(mrgCtx, RdCandList
-    , mrgCandIdx
-  );
-
 }
 #endif
+#endif
 
 #if JVET_W0090_ARMC_TM || JVET_Z0056_GPM_SPLIT_MODE_REORDERING || JVET_Z0061_TM_OBMC
 bool InterPrediction::xAMLGetCurBlkTemplate(PredictionUnit& pu, int nCurBlkWidth, int nCurBlkHeight)
@@ -6609,226 +7713,276 @@ void  InterPrediction::updateCandInfo(MergeCtx& mrgCtx, uint32_t(*RdCandList)[MR
 #endif
 
 #if JVET_W0090_ARMC_TM || JVET_Z0056_GPM_SPLIT_MODE_REORDERING
+#if JVET_AA0093_ENHANCED_MMVD_EXTENSION
+void InterPrediction::getBlkAMLRefTemplate(PredictionUnit &pu, PelUnitBuf &pcBufPredRefTop, PelUnitBuf &pcBufPredRefLeft, int8_t posList0, int8_t posList1, bool load0, bool load1)
+#else
 void InterPrediction::getBlkAMLRefTemplate(PredictionUnit &pu, PelUnitBuf &pcBufPredRefTop, PelUnitBuf &pcBufPredRefLeft)
+#endif
 {
+#if JVET_AA0093_ENHANCED_MMVD_EXTENSION
+  bool bLoadSave = (posList0 != -1);
+#endif
   Mv mvCurr;
   const int lumaShift = 2 + MV_FRACTIONAL_BITS_DIFF;
   const int horShift  = (lumaShift + ::getComponentScaleX(COMPONENT_Y, pu.chromaFormat));
   const int verShift  = (lumaShift + ::getComponentScaleY(COMPONENT_Y, pu.chromaFormat));
 
-  if (xCheckIdenticalMotion(pu))
-  {
-    mvCurr = pu.mv[0];
-    /*const int horIntMv = (mvCurr.getHor() + ((1 << horShift) >> 1)) >> horShift;
-    const int verIntMv = (mvCurr.getVer() + ((1 << verShift) >> 1)) >> verShift;
-    Mv    subPelMv(horIntMv << horShift, verIntMv << verShift);*/
-    Mv subPelMv = mvCurr;
-    clipMv(mvCurr, pu.lumaPos(), pu.lumaSize(), *pu.cs->sps, *pu.cs->pps);
-    CHECK(pu.refIdx[0] < 0, "invalid ref idx");
-
-    if (m_bAMLTemplateAvailabe[0])
+#if JVET_AA0093_ENHANCED_MMVD_EXTENSION
+  if (!bLoadSave && xCheckIdenticalMotion(pu))
+#else
+    if (xCheckIdenticalMotion(pu))
+#endif
     {
-      Mv mvTop(0, -(AML_MERGE_TEMPLATE_SIZE << verShift));
-      mvTop += subPelMv;
+      mvCurr = pu.mv[0];
+      /*const int horIntMv = (mvCurr.getHor() + ((1 << horShift) >> 1)) >> horShift;
+        const int verIntMv = (mvCurr.getVer() + ((1 << verShift) >> 1)) >> verShift;
+        Mv    subPelMv(horIntMv << horShift, verIntMv << verShift);*/
+      Mv subPelMv = mvCurr;
+      clipMv(mvCurr, pu.lumaPos(), pu.lumaSize(), *pu.cs->sps, *pu.cs->pps);
+      CHECK(pu.refIdx[0] < 0, "invalid ref idx");
+
+      if (m_bAMLTemplateAvailabe[0])
+      {
+        Mv mvTop(0, -(AML_MERGE_TEMPLATE_SIZE << verShift));
+        mvTop += subPelMv;
 
-      clipMv(mvTop, pu.lumaPos(), pu.lumaSize(), *pu.cs->sps, *pu.cs->pps);
+        clipMv(mvTop, pu.lumaPos(), pu.lumaSize(), *pu.cs->sps, *pu.cs->pps);
 
 #if RPR_ENABLE
-      const Picture* picRef = pu.cu->slice->getRefPic(REF_PIC_LIST_0, pu.refIdx[0])->unscaledPic;
-      const std::pair<int, int>& scalingRatio = pu.cu->slice->getScalingRatio(REF_PIC_LIST_0, pu.refIdx[0]);
+        const Picture* picRef = pu.cu->slice->getRefPic(REF_PIC_LIST_0, pu.refIdx[0])->unscaledPic;
+        const std::pair<int, int>& scalingRatio = pu.cu->slice->getScalingRatio(REF_PIC_LIST_0, pu.refIdx[0]);
 #if INTER_LIC
-      xPredInterBlk( COMPONENT_Y, pu, picRef, mvTop, pcBufPredRefTop,
-                     false, pu.cu->slice->clpRng( COMPONENT_Y ), false, false, scalingRatio, 0, 0, false, NULL, 0, true, true, mvCurr );
+        xPredInterBlk( COMPONENT_Y, pu, picRef, mvTop, pcBufPredRefTop,
+                      false, pu.cu->slice->clpRng( COMPONENT_Y ), false, false, scalingRatio, 0, 0, false, NULL, 0, true, true, mvCurr );
 #else
-      xPredInterBlk( COMPONENT_Y, pu, picRef, mvTop, pcBufPredRefTop,
-                     false, pu.cu->slice->clpRng( COMPONENT_Y ), false, false, scalingRatio, 0, 0, false, NULL, 0, true );
+        xPredInterBlk( COMPONENT_Y, pu, picRef, mvTop, pcBufPredRefTop,
+                      false, pu.cu->slice->clpRng( COMPONENT_Y ), false, false, scalingRatio, 0, 0, false, NULL, 0, true );
 #endif
 #else
 #if INTER_LIC
-      xPredInterBlk( COMPONENT_Y, pu, pu.cu->slice->getRefPic( REF_PIC_LIST_0, pu.refIdx[0] ), mvTop, pcBufPredRefTop,
-                     false, pu.cu->slice->clpRng( COMPONENT_Y ), false, false, SCALE_1X, 0, 0, false, NULL, 0, true, true,
-                     mvCurr );
+        xPredInterBlk( COMPONENT_Y, pu, pu.cu->slice->getRefPic( REF_PIC_LIST_0, pu.refIdx[0] ), mvTop, pcBufPredRefTop,
+                      false, pu.cu->slice->clpRng( COMPONENT_Y ), false, false, SCALE_1X, 0, 0, false, NULL, 0, true, true,
+                      mvCurr );
 #else
-      xPredInterBlk( COMPONENT_Y, pu, pu.cu->slice->getRefPic( REF_PIC_LIST_0, pu.refIdx[0] ), mvTop, pcBufPredRefTop,
-                     false, pu.cu->slice->clpRng( COMPONENT_Y ), false, false, SCALE_1X, 0, 0, false, NULL, 0, true );
+        xPredInterBlk( COMPONENT_Y, pu, pu.cu->slice->getRefPic( REF_PIC_LIST_0, pu.refIdx[0] ), mvTop, pcBufPredRefTop,
+                      false, pu.cu->slice->clpRng( COMPONENT_Y ), false, false, SCALE_1X, 0, 0, false, NULL, 0, true );
 #endif
 #endif
-    }
-    if (m_bAMLTemplateAvailabe[1])
-    {
-      Mv mvLeft(-(AML_MERGE_TEMPLATE_SIZE << horShift), 0);
-      mvLeft += subPelMv;
+      }
+      if (m_bAMLTemplateAvailabe[1])
+      {
+        Mv mvLeft(-(AML_MERGE_TEMPLATE_SIZE << horShift), 0);
+        mvLeft += subPelMv;
 
-      clipMv(mvLeft, pu.lumaPos(), pu.lumaSize(), *pu.cs->sps, *pu.cs->pps);
+        clipMv(mvLeft, pu.lumaPos(), pu.lumaSize(), *pu.cs->sps, *pu.cs->pps);
 
 #if RPR_ENABLE
-      const Picture* picRef = pu.cu->slice->getRefPic(REF_PIC_LIST_0, pu.refIdx[0])->unscaledPic;
-      const std::pair<int, int>& scalingRatio = pu.cu->slice->getScalingRatio(REF_PIC_LIST_0, pu.refIdx[0]);
+        const Picture* picRef = pu.cu->slice->getRefPic(REF_PIC_LIST_0, pu.refIdx[0])->unscaledPic;
+        const std::pair<int, int>& scalingRatio = pu.cu->slice->getScalingRatio(REF_PIC_LIST_0, pu.refIdx[0]);
 #if INTER_LIC
-      xPredInterBlk( COMPONENT_Y, pu, picRef, mvLeft, pcBufPredRefLeft,
-                     false, pu.cu->slice->clpRng( COMPONENT_Y ), false, false, scalingRatio, 0, 0, false, NULL, 0, true, true, mvCurr );
+        xPredInterBlk( COMPONENT_Y, pu, picRef, mvLeft, pcBufPredRefLeft,
+                      false, pu.cu->slice->clpRng( COMPONENT_Y ), false, false, scalingRatio, 0, 0, false, NULL, 0, true, true, mvCurr );
 #else
-      xPredInterBlk( COMPONENT_Y, pu, picRef, mvLeft, pcBufPredRefLeft,
-                     false, pu.cu->slice->clpRng( COMPONENT_Y ), false, false, scalingRatio, 0, 0, false, NULL, 0, true );
+        xPredInterBlk( COMPONENT_Y, pu, picRef, mvLeft, pcBufPredRefLeft,
+                      false, pu.cu->slice->clpRng( COMPONENT_Y ), false, false, scalingRatio, 0, 0, false, NULL, 0, true );
 #endif
 #else
 #if INTER_LIC
-      xPredInterBlk( COMPONENT_Y, pu, pu.cu->slice->getRefPic( REF_PIC_LIST_0, pu.refIdx[0] ), mvLeft, pcBufPredRefLeft,
-                     false, pu.cu->slice->clpRng( COMPONENT_Y ), false, false, SCALE_1X, 0, 0, false, NULL, 0, true, true,
-                     mvCurr );
+        xPredInterBlk( COMPONENT_Y, pu, pu.cu->slice->getRefPic( REF_PIC_LIST_0, pu.refIdx[0] ), mvLeft, pcBufPredRefLeft,
+                      false, pu.cu->slice->clpRng( COMPONENT_Y ), false, false, SCALE_1X, 0, 0, false, NULL, 0, true, true,
+                      mvCurr );
 #else
-      xPredInterBlk( COMPONENT_Y, pu, pu.cu->slice->getRefPic( REF_PIC_LIST_0, pu.refIdx[0] ), mvLeft, pcBufPredRefLeft,
-                     false, pu.cu->slice->clpRng( COMPONENT_Y ), false, false, SCALE_1X, 0, 0, false, NULL, 0, true );
+        xPredInterBlk( COMPONENT_Y, pu, pu.cu->slice->getRefPic( REF_PIC_LIST_0, pu.refIdx[0] ), mvLeft, pcBufPredRefLeft,
+                      false, pu.cu->slice->clpRng( COMPONENT_Y ), false, false, SCALE_1X, 0, 0, false, NULL, 0, true );
 #endif
 #endif
+      }
     }
-  }
-  else
-  {
-    for (uint32_t refList = 0; refList < NUM_REF_PIC_LIST_01; refList++)
+    else
     {
-      if (pu.refIdx[refList] < 0)
-      {
-        continue;
-      }
-      RefPicList eRefPicList = (refList ? REF_PIC_LIST_1 : REF_PIC_LIST_0);
-      CHECK(pu.refIdx[refList] >= pu.cu->slice->getNumRefIdx(eRefPicList), "Invalid reference index");
-
-      m_iRefListIdx = refList;
-      mvCurr        = pu.mv[refList];
-      /*const int horIntMv = (mvCurr.getHor() + ((1 << horShift) >> 1)) >> horShift;
-      const int verIntMv = (mvCurr.getVer() + ((1 << verShift) >> 1)) >> verShift;
-      Mv    subPelMv(horIntMv << horShift, verIntMv << verShift);*/
-      Mv subPelMv = mvCurr;
-      clipMv(mvCurr, pu.lumaPos(), pu.lumaSize(), *pu.cs->sps, *pu.cs->pps);
-
-      if (m_bAMLTemplateAvailabe[0])
+      for (uint32_t refList = 0; refList < NUM_REF_PIC_LIST_01; refList++)
       {
-        Mv mvTop(0, -(AML_MERGE_TEMPLATE_SIZE << verShift));
-        mvTop += subPelMv;
-
-        clipMv(mvTop, pu.lumaPos(), pu.lumaSize(), *pu.cs->sps, *pu.cs->pps);
-
-        PelUnitBuf pcMbBuf =
-          PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefAboveTemplate[refList][0], pcBufPredRefTop.Y()));
-
-        if (pu.refIdx[0] >= 0 && pu.refIdx[1] >= 0)
+        if (pu.refIdx[refList] < 0)
+        {
+          continue;
+        }
+#if JVET_AA0093_ENHANCED_MMVD_EXTENSION
+        if (bLoadSave && (((refList == 0) && load0) || ((refList == 1) && load1)) )// changed
+        {
+          continue;
+        }
+#endif
+        RefPicList eRefPicList = (refList ? REF_PIC_LIST_1 : REF_PIC_LIST_0);
+        CHECK(pu.refIdx[refList] >= pu.cu->slice->getNumRefIdx(eRefPicList), "Invalid reference index");
+        
+        m_iRefListIdx = refList;
+        mvCurr        = pu.mv[refList];
+        /*const int horIntMv = (mvCurr.getHor() + ((1 << horShift) >> 1)) >> horShift;
+          const int verIntMv = (mvCurr.getVer() + ((1 << verShift) >> 1)) >> verShift;
+          Mv    subPelMv(horIntMv << horShift, verIntMv << verShift);*/
+        Mv subPelMv = mvCurr;
+        clipMv(mvCurr, pu.lumaPos(), pu.lumaSize(), *pu.cs->sps, *pu.cs->pps);
+        
+        if (m_bAMLTemplateAvailabe[0])
         {
+          Mv mvTop(0, -(AML_MERGE_TEMPLATE_SIZE << verShift));
+          mvTop += subPelMv;
+          
+          clipMv(mvTop, pu.lumaPos(), pu.lumaSize(), *pu.cs->sps, *pu.cs->pps);
+          
+#if JVET_AA0093_ENHANCED_MMVD_EXTENSION
+          int offsetA = bLoadSave ? (refList == 0 ? posList0 : posList1) * MAX_CU_SIZE : 0;
+          PelUnitBuf pcMbBuf = PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefAboveTemplate[refList][0] + offsetA, pcBufPredRefTop.Y())); // changed
+#else
+          PelUnitBuf pcMbBuf = PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefAboveTemplate[refList][0], pcBufPredRefTop.Y()));
+#endif
+          
+          if (pu.refIdx[0] >= 0 && pu.refIdx[1] >= 0)
+          {
 #if RPR_ENABLE
-          const Picture* picRef = pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[refList])->unscaledPic;
-          const std::pair<int, int>& scalingRatio = pu.cu->slice->getScalingRatio(eRefPicList, pu.refIdx[refList]);
+            const Picture* picRef = pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[refList])->unscaledPic;
+            const std::pair<int, int>& scalingRatio = pu.cu->slice->getScalingRatio(eRefPicList, pu.refIdx[refList]);
 #if INTER_LIC
-          xPredInterBlk( COMPONENT_Y, pu, picRef, mvTop, pcMbBuf, true,
-                         pu.cu->slice->clpRng( COMPONENT_Y ), false, false, scalingRatio, 0, 0, false, NULL, 0, true, true, mvCurr );
+            xPredInterBlk( COMPONENT_Y, pu, picRef, mvTop, pcMbBuf, true,
+                          pu.cu->slice->clpRng( COMPONENT_Y ), false, false, scalingRatio, 0, 0, false, NULL, 0, true, true, mvCurr );
 #else
-          xPredInterBlk( COMPONENT_Y, pu, picRef, mvTop, pcMbBuf, true,
-                         pu.cu->slice->clpRng( COMPONENT_Y ), false, false, scalingRatio, 0, 0, false, NULL, 0, true );
+            xPredInterBlk( COMPONENT_Y, pu, picRef, mvTop, pcMbBuf, true,
+                          pu.cu->slice->clpRng( COMPONENT_Y ), false, false, scalingRatio, 0, 0, false, NULL, 0, true );
 #endif
 #else
 #if INTER_LIC
-          xPredInterBlk( COMPONENT_Y, pu, pu.cu->slice->getRefPic( eRefPicList, pu.refIdx[refList] ), mvTop, pcMbBuf, true,
-                         pu.cu->slice->clpRng( COMPONENT_Y ), false, false, SCALE_1X, 0, 0, false, NULL, 0, true, true,
-                         mvCurr );
+            xPredInterBlk( COMPONENT_Y, pu, pu.cu->slice->getRefPic( eRefPicList, pu.refIdx[refList] ), mvTop, pcMbBuf, true,
+                          pu.cu->slice->clpRng( COMPONENT_Y ), false, false, SCALE_1X, 0, 0, false, NULL, 0, true, true,
+                          mvCurr );
 #else
-          xPredInterBlk( COMPONENT_Y, pu, pu.cu->slice->getRefPic( eRefPicList, pu.refIdx[refList] ), mvTop, pcMbBuf, true,
-                         pu.cu->slice->clpRng( COMPONENT_Y ), false, false, SCALE_1X, 0, 0, false, NULL, 0, true );
+            xPredInterBlk( COMPONENT_Y, pu, pu.cu->slice->getRefPic( eRefPicList, pu.refIdx[refList] ), mvTop, pcMbBuf, true,
+                          pu.cu->slice->clpRng( COMPONENT_Y ), false, false, SCALE_1X, 0, 0, false, NULL, 0, true );
 #endif
 #endif
-        }
-        else
-        {
+          }
+          else
+          {
 #if RPR_ENABLE
-          const Picture* picRef = pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[refList])->unscaledPic;
-          const std::pair<int, int>& scalingRatio = pu.cu->slice->getScalingRatio(eRefPicList, pu.refIdx[refList]);
+            const Picture* picRef = pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[refList])->unscaledPic;
+            const std::pair<int, int>& scalingRatio = pu.cu->slice->getScalingRatio(eRefPicList, pu.refIdx[refList]);
 #if INTER_LIC
-          xPredInterBlk( COMPONENT_Y, pu, picRef, mvTop, pcMbBuf,
-                         false, pu.cu->slice->clpRng( COMPONENT_Y ), false, false, scalingRatio, 0, 0, false, NULL, 0, true, true, mvCurr );
+            xPredInterBlk( COMPONENT_Y, pu, picRef, mvTop, pcMbBuf,
+                          false, pu.cu->slice->clpRng( COMPONENT_Y ), false, false, scalingRatio, 0, 0, false, NULL, 0, true, true, mvCurr );
 #else
-          xPredInterBlk( COMPONENT_Y, pu, picRef, mvTop, pcMbBuf,
-                         false, pu.cu->slice->clpRng( COMPONENT_Y ), false, false, scalingRatio, 0, 0, false, NULL, 0, true );
+            xPredInterBlk( COMPONENT_Y, pu, picRef, mvTop, pcMbBuf,
+                          false, pu.cu->slice->clpRng( COMPONENT_Y ), false, false, scalingRatio, 0, 0, false, NULL, 0, true );
 #endif
 #else
 #if INTER_LIC
-          xPredInterBlk( COMPONENT_Y, pu, pu.cu->slice->getRefPic( eRefPicList, pu.refIdx[refList] ), mvTop, pcMbBuf,
-                         false, pu.cu->slice->clpRng( COMPONENT_Y ), false, false, SCALE_1X, 0, 0, false, NULL, 0, true, true, mvCurr );
+            xPredInterBlk( COMPONENT_Y, pu, pu.cu->slice->getRefPic( eRefPicList, pu.refIdx[refList] ), mvTop, pcMbBuf,
+                          false, pu.cu->slice->clpRng( COMPONENT_Y ), false, false, SCALE_1X, 0, 0, false, NULL, 0, true, true, mvCurr );
 #else
-          xPredInterBlk( COMPONENT_Y, pu, pu.cu->slice->getRefPic( eRefPicList, pu.refIdx[refList] ), mvTop, pcMbBuf,
-                         false, pu.cu->slice->clpRng( COMPONENT_Y ), false, false, SCALE_1X, 0, 0, false, NULL, 0, true );
+            xPredInterBlk( COMPONENT_Y, pu, pu.cu->slice->getRefPic( eRefPicList, pu.refIdx[refList] ), mvTop, pcMbBuf,
+                          false, pu.cu->slice->clpRng( COMPONENT_Y ), false, false, SCALE_1X, 0, 0, false, NULL, 0, true );
 #endif
 #endif
+          }
         }
-      }
-      if (m_bAMLTemplateAvailabe[1])
-      {
-        Mv mvLeft(-(AML_MERGE_TEMPLATE_SIZE << horShift), 0);
-        mvLeft += subPelMv;
-
-        clipMv(mvLeft, pu.lumaPos(), pu.lumaSize(), *pu.cs->sps, *pu.cs->pps);
-
-        PelUnitBuf pcMbBuf =
-          PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefLeftTemplate[refList][0], pcBufPredRefLeft.Y()));
-
-        if (pu.refIdx[0] >= 0 && pu.refIdx[1] >= 0)
+        if (m_bAMLTemplateAvailabe[1])
         {
+          Mv mvLeft(-(AML_MERGE_TEMPLATE_SIZE << horShift), 0);
+          mvLeft += subPelMv;
+          
+          clipMv(mvLeft, pu.lumaPos(), pu.lumaSize(), *pu.cs->sps, *pu.cs->pps);
+          
+#if JVET_AA0093_ENHANCED_MMVD_EXTENSION
+          int offsetA = bLoadSave ? (refList == 0 ? posList0 : posList1) * MAX_CU_SIZE : 0;
+          PelUnitBuf pcMbBuf = PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefLeftTemplate[refList][0] + offsetA, pcBufPredRefLeft.Y())); // changed
+#else
+          PelUnitBuf pcMbBuf = PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefLeftTemplate[refList][0], pcBufPredRefLeft.Y()));
+#endif
+
+          if (pu.refIdx[0] >= 0 && pu.refIdx[1] >= 0)
+          {
 #if RPR_ENABLE
-          const Picture* picRef = pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[refList])->unscaledPic;
-          const std::pair<int, int>& scalingRatio = pu.cu->slice->getScalingRatio( eRefPicList, pu.refIdx[refList] );
+            const Picture* picRef = pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[refList])->unscaledPic;
+            const std::pair<int, int>& scalingRatio = pu.cu->slice->getScalingRatio( eRefPicList, pu.refIdx[refList] );
 #if INTER_LIC
-          xPredInterBlk( COMPONENT_Y, pu, picRef, mvLeft, pcMbBuf,
-                         true, pu.cu->slice->clpRng( COMPONENT_Y ), false, false, scalingRatio, 0, 0, false, NULL, 0, true, true, mvCurr );
+            xPredInterBlk( COMPONENT_Y, pu, picRef, mvLeft, pcMbBuf,
+                          true, pu.cu->slice->clpRng( COMPONENT_Y ), false, false, scalingRatio, 0, 0, false, NULL, 0, true, true, mvCurr );
 #else
-          xPredInterBlk( COMPONENT_Y, pu, picRef, mvLeft, pcMbBuf,
-                         true, pu.cu->slice->clpRng( COMPONENT_Y ), false, false, scalingRatio, 0, 0, false, NULL, 0, true );
+            xPredInterBlk( COMPONENT_Y, pu, picRef, mvLeft, pcMbBuf,
+                          true, pu.cu->slice->clpRng( COMPONENT_Y ), false, false, scalingRatio, 0, 0, false, NULL, 0, true );
 #endif
 #else
-  #if INTER_LIC
-          xPredInterBlk(COMPONENT_Y, pu, pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[refList]), mvLeft, pcMbBuf,
-                        true, pu.cu->slice->clpRng(COMPONENT_Y), false, false, SCALE_1X, 0, 0, false, NULL, 0, true, true, mvCurr);
-  #else
-          xPredInterBlk(COMPONENT_Y, pu, pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[refList]), mvLeft, pcMbBuf,
-                        true, pu.cu->slice->clpRng(COMPONENT_Y), false, false, SCALE_1X, 0, 0, false, NULL, 0, true);
-  #endif
+#if INTER_LIC
+            xPredInterBlk(COMPONENT_Y, pu, pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[refList]), mvLeft, pcMbBuf,
+                          true, pu.cu->slice->clpRng(COMPONENT_Y), false, false, SCALE_1X, 0, 0, false, NULL, 0, true, true, mvCurr);
+#else
+            xPredInterBlk(COMPONENT_Y, pu, pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[refList]), mvLeft, pcMbBuf,
+                          true, pu.cu->slice->clpRng(COMPONENT_Y), false, false, SCALE_1X, 0, 0, false, NULL, 0, true);
 #endif
-        }
-        else
-        {
+#endif
+          }
+          else
+          {
 #if RPR_ENABLE
-          const Picture* picRef = pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[refList])->unscaledPic;
-          const std::pair<int, int>& scalingRatio = pu.cu->slice->getScalingRatio(eRefPicList, pu.refIdx[refList]);
+            const Picture* picRef = pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[refList])->unscaledPic;
+            const std::pair<int, int>& scalingRatio = pu.cu->slice->getScalingRatio(eRefPicList, pu.refIdx[refList]);
 #if INTER_LIC
-          xPredInterBlk( COMPONENT_Y, pu, picRef, mvLeft, pcMbBuf,
-                         false, pu.cu->slice->clpRng( COMPONENT_Y ), false, false, scalingRatio, 0, 0, false, NULL, 0, true, true, mvCurr );
+            xPredInterBlk( COMPONENT_Y, pu, picRef, mvLeft, pcMbBuf,
+                          false, pu.cu->slice->clpRng( COMPONENT_Y ), false, false, scalingRatio, 0, 0, false, NULL, 0, true, true, mvCurr );
 #else
-          xPredInterBlk( COMPONENT_Y, pu, picRef, mvLeft, pcMbBuf,
-                         false, pu.cu->slice->clpRng( COMPONENT_Y ), false, false, scalingRatio, 0, 0, false, NULL, 0, true );
+            xPredInterBlk( COMPONENT_Y, pu, picRef, mvLeft, pcMbBuf,
+                          false, pu.cu->slice->clpRng( COMPONENT_Y ), false, false, scalingRatio, 0, 0, false, NULL, 0, true );
 #endif
 #else
 #if INTER_LIC
-          xPredInterBlk( COMPONENT_Y, pu, pu.cu->slice->getRefPic( eRefPicList, pu.refIdx[refList] ), mvLeft, pcMbBuf,
-                         false, pu.cu->slice->clpRng( COMPONENT_Y ), false, false, SCALE_1X, 0, 0, false, NULL, 0, true, true, mvCurr );
+            xPredInterBlk( COMPONENT_Y, pu, pu.cu->slice->getRefPic( eRefPicList, pu.refIdx[refList] ), mvLeft, pcMbBuf,
+                          false, pu.cu->slice->clpRng( COMPONENT_Y ), false, false, SCALE_1X, 0, 0, false, NULL, 0, true, true, mvCurr );
 #else
-          xPredInterBlk( COMPONENT_Y, pu, pu.cu->slice->getRefPic( eRefPicList, pu.refIdx[refList] ), mvLeft, pcMbBuf,
-                         false, pu.cu->slice->clpRng( COMPONENT_Y ), false, false, SCALE_1X, 0, 0, false, NULL, 0, true );
+            xPredInterBlk( COMPONENT_Y, pu, pu.cu->slice->getRefPic( eRefPicList, pu.refIdx[refList] ), mvLeft, pcMbBuf,
+                          false, pu.cu->slice->clpRng( COMPONENT_Y ), false, false, SCALE_1X, 0, 0, false, NULL, 0, true );
 #endif
 #endif
+          }
         }
       }
+#if JVET_AA0093_ENHANCED_MMVD_EXTENSION
+      int offset0 = 0;
+      int offset1 = 0;
+      if (bLoadSave)
+      {
+        offset0 = posList0 * MAX_CU_SIZE;
+        offset1 = posList1 * MAX_CU_SIZE;
+      }
+      if (m_bAMLTemplateAvailabe[0])
+      {
+        CPelUnitBuf srcPred0 = CPelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefAboveTemplate[0][0] + offset0, pcBufPredRefTop.Y()));  // changed
+        CPelUnitBuf srcPred1 = CPelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefAboveTemplate[1][0] + offset1, pcBufPredRefTop.Y()));  // changed
+        xWeightedAverageY(pu, srcPred0, srcPred1, pcBufPredRefTop, pu.cu->slice->getSPS()->getBitDepths(),
+                          pu.cu->slice->clpRngs());
+      }
+      if (m_bAMLTemplateAvailabe[1])
+      {
+        CPelUnitBuf srcPred0 = CPelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefLeftTemplate[0][0] + offset0, pcBufPredRefLeft.Y()));  // changed
+        CPelUnitBuf srcPred1 = CPelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefLeftTemplate[1][0] + offset1, pcBufPredRefLeft.Y()));  // changed
+        xWeightedAverageY(pu, srcPred0, srcPred1, pcBufPredRefLeft, pu.cu->slice->getSPS()->getBitDepths(),
+                          pu.cu->slice->clpRngs());
+      }
+
+#else
+      if (m_bAMLTemplateAvailabe[0])
+      {
+        CPelUnitBuf srcPred0 = CPelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefAboveTemplate[0][0], pcBufPredRefTop.Y()));
+        CPelUnitBuf srcPred1 = CPelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefAboveTemplate[1][0], pcBufPredRefTop.Y()));
+        xWeightedAverageY(pu, srcPred0, srcPred1, pcBufPredRefTop, pu.cu->slice->getSPS()->getBitDepths(),
+                          pu.cu->slice->clpRngs());
+      }
+      if (m_bAMLTemplateAvailabe[1])
+      {
+        CPelUnitBuf srcPred0 = CPelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefLeftTemplate[0][0], pcBufPredRefLeft.Y()));
+        CPelUnitBuf srcPred1 = CPelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefLeftTemplate[1][0], pcBufPredRefLeft.Y()));
+        xWeightedAverageY(pu, srcPred0, srcPred1, pcBufPredRefLeft, pu.cu->slice->getSPS()->getBitDepths(),
+                          pu.cu->slice->clpRngs());
+      }
+#endif
     }
-    if (m_bAMLTemplateAvailabe[0])
-    {
-      CPelUnitBuf srcPred0 = CPelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefAboveTemplate[0][0], pcBufPredRefTop.Y()));
-      CPelUnitBuf srcPred1 = CPelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefAboveTemplate[1][0], pcBufPredRefTop.Y()));
-      xWeightedAverageY(pu, srcPred0, srcPred1, pcBufPredRefTop, pu.cu->slice->getSPS()->getBitDepths(),
-                        pu.cu->slice->clpRngs());
-    }
-    if (m_bAMLTemplateAvailabe[1])
-    {
-      CPelUnitBuf srcPred0 = CPelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefLeftTemplate[0][0], pcBufPredRefLeft.Y()));
-      CPelUnitBuf srcPred1 = CPelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefLeftTemplate[1][0], pcBufPredRefLeft.Y()));
-      xWeightedAverageY(pu, srcPred0, srcPred1, pcBufPredRefLeft, pu.cu->slice->getSPS()->getBitDepths(),
-                        pu.cu->slice->clpRngs());
-    }
-  }
 }
 #endif
 
@@ -6975,6 +8129,17 @@ void  InterPrediction::adjustAffineMergeCandidates(PredictionUnit &pu, AffineMer
 
         uiCost += cDistParam.distFunc(cDistParam);
       }
+      
+#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC
+      if (m_bAMLTemplateAvailabe[0] && !m_bAMLTemplateAvailabe[1])
+      {
+        uiCost += (uiCost * nHeight) / nWidth;
+      }
+      if (!m_bAMLTemplateAvailabe[0] && m_bAMLTemplateAvailabe[1])
+      {
+        uiCost += (uiCost * nWidth) / nHeight;
+      }
+#endif
 
 #if RPR_ENABLE
       }
@@ -6994,6 +8159,63 @@ void  InterPrediction::adjustAffineMergeCandidates(PredictionUnit &pu, AffineMer
 #endif
   }
   pu.mergeIdx = mrgCandIdx;    //restore the merge index
+#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC
+  if (maxNumAffineMergeCand > 2)
+  {
+    Distortion cost = pu.cs->slice->getCostForARMC();
+    uint32_t   candToBeRemoved = AFFINE_MRG_MAX_NUM_CANDS - 1;
+    Distortion min = MAX_UINT64;
+
+    for (int sizeCandList = maxNumAffineMergeCand; sizeCandList > 1; sizeCandList--)
+    {
+      min = MAX_UINT64;
+      for (uint32_t uiMergeCand = 0; uiMergeCand < sizeCandList - 1; ++uiMergeCand)
+      {
+        if (min > abs((int)(candCostList[0][uiMergeCand + 1] - candCostList[0][uiMergeCand])))
+        {
+          min = abs((int)(candCostList[0][uiMergeCand + 1] - candCostList[0][uiMergeCand]));
+          candToBeRemoved = uiMergeCand + 1;
+        }
+      }
+      if (candToBeRemoved > AFFINE_MRG_MAX_NUM_CANDS - 2)
+      {
+        continue;
+      }
+      if (min < cost)
+      {
+        uint32_t candToBeReplaced = sizeCandList - 1;
+
+        for (uint32_t uiMergeCand = std::min( (int) (candToBeRemoved + 1), (int) (AFFINE_MRG_MAX_NUM_CANDS - 1) ); uiMergeCand < std::min((int)sizeCandList, (int)(AFFINE_MRG_MAX_NUM_CANDS - 1)); ++uiMergeCand)
+        {
+          if (cost < abs((int)(candCostList[0][uiMergeCand] - candCostList[0][candToBeRemoved])))
+          {
+            candToBeReplaced = uiMergeCand;
+            break;
+          }
+        }
+
+        if (sizeCandList > maxNumAffineMergeCand)
+        {
+          candToBeReplaced = sizeCandList - 1;
+        }
+
+        uint32_t   rdCand = rdCandList[0][candToBeRemoved];
+        Distortion candCost = candCostList[0][(candToBeRemoved)];
+        for (int ui = candToBeRemoved; ui < (candToBeReplaced > sizeCandList - 1 ? sizeCandList - 1 : candToBeReplaced); ui++)
+        {
+          candCostList[0][ui] = candCostList[0][(ui + 1)];
+          rdCandList[0][ui] = rdCandList[0][(ui + 1)];
+        }
+        candCostList[0][candToBeReplaced] = candCost;
+        rdCandList[0][candToBeReplaced] = rdCand;
+      }
+      else
+      {
+        break;
+      }
+    }
+  }
+#endif
   updateAffineCandInfo(pu, affMrgCtx, rdCandList
     , mrgCandIdx
   );
@@ -7146,62 +8368,34 @@ void InterPrediction::xGetSublkAMLTemplate(const CodingUnit& cu,
     }
   }
 }
+#if JVET_AA0093_ENHANCED_MMVD_EXTENSION
+void InterPrediction::getAffAMLRefTemplate(PredictionUnit &pu, PelUnitBuf &pcBufPredRefTop, PelUnitBuf &pcBufPredRefLeft, int8_t posList0, int8_t posList1, bool load0, bool load1)
+#else
 void InterPrediction::getAffAMLRefTemplate(PredictionUnit &pu, PelUnitBuf &pcBufPredRefTop, PelUnitBuf &pcBufPredRefLeft)
+#endif
 {
+#if JVET_AA0093_ENHANCED_MMVD_EXTENSION
+  bool bLoadSave = (posList0 != -1);
+#endif
 #if INTER_LIC
   int LICshift[2] = { 0 };
   int scale[2]    = { 0 };
   int offset[2]   = { 0 };
 #endif
   const int bitDepth = pu.cs->sps->getBitDepth(CHANNEL_TYPE_LUMA);
-  if (xCheckIdenticalMotion(pu))
-  {
-    Pel *            refLeftTemplate  = m_acYuvRefAMLTemplate[1][0];
-    Pel *            refAboveTemplate = m_acYuvRefAMLTemplate[0][0];
-    int              numTemplate[2]   = { 0, 0 };   // 0:Above, 1:Left
-    const RefPicList eRefPicList      = REF_PIC_LIST_0;
-#if JVET_Z0067_RPR_ENABLE
-    CHECK(pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[eRefPicList])->isRefScaled(pu.cs->pps), "getAffAMLRefTemplate not supported with ref scaled.");
-#endif
-    xPredAffineTpl(pu, eRefPicList, numTemplate, refLeftTemplate, refAboveTemplate);
-#if INTER_LIC
-    if (pu.cu->LICFlag)
-    {
-      Pel *recLeftTemplate  = m_acYuvCurAMLTemplate[1][0];
-      Pel *recAboveTemplate = m_acYuvCurAMLTemplate[0][0];
-      xGetLICParamGeneral(*pu.cu, COMPONENT_Y, numTemplate, refLeftTemplate, refAboveTemplate, recLeftTemplate,
-                          recAboveTemplate, LICshift[0], scale[0], offset[0]);
-      if (m_bAMLTemplateAvailabe[0])
-      {
-        PelBuf &      dstBuf = pcBufPredRefTop.bufs[0];
-        const ClpRng &clpRng = pu.cu->cs->slice->clpRng(COMPONENT_Y);
-        dstBuf.linearTransform(scale[0], LICshift[0], offset[0], true, clpRng);
-      }
-      if (m_bAMLTemplateAvailabe[1])
-      {
-        PelBuf &      dstBuf = pcBufPredRefLeft.bufs[0];
-        const ClpRng &clpRng = pu.cu->cs->slice->clpRng(COMPONENT_Y);
-        dstBuf.linearTransform(scale[0], LICshift[0], offset[0], true, clpRng);
-      }
-    }
+#if JVET_AA0093_ENHANCED_MMVD_EXTENSION
+  if (!bLoadSave && xCheckIdenticalMotion(pu))
+#else
+    if (xCheckIdenticalMotion(pu))
 #endif
-  }
-  else
-  {
-    for (uint32_t refList = 0; refList < NUM_REF_PIC_LIST_01; refList++)
     {
-      if (pu.refIdx[refList] < 0)
-      {
-        continue;
-      }
-      RefPicList eRefPicList = (refList ? REF_PIC_LIST_1 : REF_PIC_LIST_0);
-      CHECK(pu.refIdx[refList] >= pu.cu->slice->getNumRefIdx(eRefPicList), "Invalid reference index");
+      Pel *            refLeftTemplate  = m_acYuvRefAMLTemplate[1][0];
+      Pel *            refAboveTemplate = m_acYuvRefAMLTemplate[0][0];
+      int              numTemplate[2]   = { 0, 0 };   // 0:Above, 1:Left
+      const RefPicList eRefPicList      = REF_PIC_LIST_0;
 #if JVET_Z0067_RPR_ENABLE
       CHECK(pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[eRefPicList])->isRefScaled(pu.cs->pps), "getAffAMLRefTemplate not supported with ref scaled.");
 #endif
-      Pel *refLeftTemplate  = m_acYuvRefLeftTemplate[refList][0];
-      Pel *refAboveTemplate = m_acYuvRefAboveTemplate[refList][0];
-      int  numTemplate[2]   = { 0, 0 };   // 0:Above, 1:Left
       xPredAffineTpl(pu, eRefPicList, numTemplate, refLeftTemplate, refAboveTemplate);
 #if INTER_LIC
       if (pu.cu->LICFlag)
@@ -7209,81 +8403,167 @@ void InterPrediction::getAffAMLRefTemplate(PredictionUnit &pu, PelUnitBuf &pcBuf
         Pel *recLeftTemplate  = m_acYuvCurAMLTemplate[1][0];
         Pel *recAboveTemplate = m_acYuvCurAMLTemplate[0][0];
         xGetLICParamGeneral(*pu.cu, COMPONENT_Y, numTemplate, refLeftTemplate, refAboveTemplate, recLeftTemplate,
-                            recAboveTemplate, LICshift[refList], scale[refList], offset[refList]);
+                            recAboveTemplate, LICshift[0], scale[0], offset[0]);
+        if (m_bAMLTemplateAvailabe[0])
+        {
+          PelBuf &      dstBuf = pcBufPredRefTop.bufs[0];
+          const ClpRng &clpRng = pu.cu->cs->slice->clpRng(COMPONENT_Y);
+          dstBuf.linearTransform(scale[0], LICshift[0], offset[0], true, clpRng);
+        }
+        if (m_bAMLTemplateAvailabe[1])
+        {
+          PelBuf &      dstBuf = pcBufPredRefLeft.bufs[0];
+          const ClpRng &clpRng = pu.cu->cs->slice->clpRng(COMPONENT_Y);
+          dstBuf.linearTransform(scale[0], LICshift[0], offset[0], true, clpRng);
+        }
       }
 #endif
     }
-    if (m_bAMLTemplateAvailabe[0])
+    else
     {
-      PelUnitBuf srcPred[2];
-      srcPred[0] = PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefAboveTemplate[0][0], pcBufPredRefTop.Y()));
-      srcPred[1] = PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefAboveTemplate[1][0], pcBufPredRefTop.Y()));
-#if INTER_LIC
-      if (pu.cu->LICFlag)
+      for (uint32_t refList = 0; refList < NUM_REF_PIC_LIST_01; refList++)
       {
-        for (int i = 0; i < 2; i++)
+        if (pu.refIdx[refList] < 0)
         {
-          if (pu.refIdx[i] >= 0)
-          {
-            PelBuf &      dstBuf = srcPred[i].bufs[0];
-            const ClpRng &clpRng = pu.cu->cs->slice->clpRng(COMPONENT_Y);
-            dstBuf.linearTransform(scale[i], LICshift[i], offset[i], true, clpRng);
-          }
+          continue;
+        }
+#if JVET_AA0093_ENHANCED_MMVD_EXTENSION
+        if (bLoadSave && (((refList == 0) && load0) || ((refList == 1) && load1)) )// changed
+        {
+          continue;
         }
-      }
 #endif
-      const int iRefIdx0 = pu.refIdx[0];
-      const int iRefIdx1 = pu.refIdx[1];
-      if (iRefIdx0 >= 0 && iRefIdx1 >= 0)
-      {
-        for (int i = 0; i < 2; i++)
+        RefPicList eRefPicList = (refList ? REF_PIC_LIST_1 : REF_PIC_LIST_0);
+        CHECK(pu.refIdx[refList] >= pu.cu->slice->getNumRefIdx(eRefPicList), "Invalid reference index");
+#if JVET_Z0067_RPR_ENABLE
+        CHECK(pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[eRefPicList])->isRefScaled(pu.cs->pps), "getAffAMLRefTemplate not supported with ref scaled.");
+#endif
+        Pel *refLeftTemplate  = m_acYuvRefLeftTemplate[refList][0];
+        Pel *refAboveTemplate = m_acYuvRefAboveTemplate[refList][0];
+#if JVET_AA0093_ENHANCED_MMVD_EXTENSION
+        if (bLoadSave)
         {
-          PelBuf &  dstBuf   = srcPred[i].bufs[0];
-          const int biShift  = IF_INTERNAL_PREC - bitDepth;
-          const Pel biOffset = -IF_INTERNAL_OFFS;
-          ClpRng    clpRngDummy;
-          dstBuf.linearTransform(1, -biShift, biOffset, false, clpRngDummy);
+          refLeftTemplate  += (refList == 0 ? posList0 : posList1) * MAX_CU_SIZE;
+          refAboveTemplate += (refList == 0 ? posList0 : posList1) * MAX_CU_SIZE;// changed
         }
-      }
-      xWeightedAverageY(pu, srcPred[0], srcPred[1], pcBufPredRefTop, pu.cu->slice->getSPS()->getBitDepths(),
-                        pu.cu->slice->clpRngs());
-    }
-    if (m_bAMLTemplateAvailabe[1])
-    {
-      PelUnitBuf srcPred[2];
-      srcPred[0] = PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefLeftTemplate[0][0], pcBufPredRefLeft.Y()));
-      srcPred[1] = PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefLeftTemplate[1][0], pcBufPredRefLeft.Y()));
+#endif
+        int  numTemplate[2]   = { 0, 0 };   // 0:Above, 1:Left
+        xPredAffineTpl(pu, eRefPicList, numTemplate, refLeftTemplate, refAboveTemplate);
 #if INTER_LIC
-      if (pu.cu->LICFlag)
+        if (pu.cu->LICFlag)
+        {
+          Pel *recLeftTemplate  = m_acYuvCurAMLTemplate[1][0];
+          Pel *recAboveTemplate = m_acYuvCurAMLTemplate[0][0];
+          xGetLICParamGeneral(*pu.cu, COMPONENT_Y, numTemplate, refLeftTemplate, refAboveTemplate, recLeftTemplate,
+                              recAboveTemplate, LICshift[refList], scale[refList], offset[refList]);
+        }
+#endif
+      }
+      if (m_bAMLTemplateAvailabe[0])
       {
-        for (int i = 0; i < 2; i++)
+        PelUnitBuf srcPred[2];
+#if JVET_AA0093_ENHANCED_MMVD_EXTENSION
+        int offset0 = bLoadSave ? posList0 * MAX_CU_SIZE : 0;
+        int offset1 = bLoadSave ? posList1 * MAX_CU_SIZE : 0;
+        srcPred[0] = PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefAboveTemplate[0][0] + offset0, pcBufPredRefTop.Y())); //changed
+        srcPred[1] = PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefAboveTemplate[1][0] + offset1, pcBufPredRefTop.Y())); //changed
+#else
+        srcPred[0] = PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefAboveTemplate[0][0], pcBufPredRefTop.Y()));
+        srcPred[1] = PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefAboveTemplate[1][0], pcBufPredRefTop.Y()));
+#endif
+#if INTER_LIC
+#if JVET_AA0093_ENHANCED_MMVD_EXTENSION
+        if (!bLoadSave && pu.cu->LICFlag)
+#else
+          if (pu.cu->LICFlag)
+#endif
+          {
+            for (int i = 0; i < 2; i++)
+            {
+              if (pu.refIdx[i] >= 0)
+              {
+                PelBuf &      dstBuf = srcPred[i].bufs[0];
+                const ClpRng &clpRng = pu.cu->cs->slice->clpRng(COMPONENT_Y);
+                dstBuf.linearTransform(scale[i], LICshift[i], offset[i], true, clpRng);
+              }
+            }
+          }
+#endif
+        const int iRefIdx0 = pu.refIdx[0];
+        const int iRefIdx1 = pu.refIdx[1];
+        if (iRefIdx0 >= 0 && iRefIdx1 >= 0)
         {
-          if (pu.refIdx[i] >= 0)
+          for (int i = 0; i < 2; i++)
           {
-            PelBuf &      dstBuf = srcPred[i].bufs[0];
-            const ClpRng &clpRng = pu.cu->cs->slice->clpRng(COMPONENT_Y);
-            dstBuf.linearTransform(scale[i], LICshift[i], offset[i], true, clpRng);
+#if JVET_AA0093_ENHANCED_MMVD_EXTENSION
+            if (bLoadSave && (((i == 0) && load0) || ((i == 1) && load1)))// changed
+            {
+              continue;
+            }
+#endif
+            PelBuf &  dstBuf   = srcPred[i].bufs[0];
+            const int biShift  = IF_INTERNAL_PREC - bitDepth;
+            const Pel biOffset = -IF_INTERNAL_OFFS;
+            ClpRng    clpRngDummy;
+            dstBuf.linearTransform(1, -biShift, biOffset, false, clpRngDummy);
           }
         }
+        xWeightedAverageY(pu, srcPred[0], srcPred[1], pcBufPredRefTop, pu.cu->slice->getSPS()->getBitDepths(),
+                          pu.cu->slice->clpRngs());
       }
-#endif
-      const int iRefIdx0 = pu.refIdx[0];
-      const int iRefIdx1 = pu.refIdx[1];
-      if (iRefIdx0 >= 0 && iRefIdx1 >= 0)
+      if (m_bAMLTemplateAvailabe[1])
       {
-        for (int i = 0; i < 2; i++)
+        PelUnitBuf srcPred[2];
+#if JVET_AA0093_ENHANCED_MMVD_EXTENSION
+        int offset0 = bLoadSave ? posList0 * MAX_CU_SIZE : 0;
+        int offset1 = bLoadSave ? posList1 * MAX_CU_SIZE : 0;
+        srcPred[0] = PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefLeftTemplate[0][0] + offset0, pcBufPredRefLeft.Y())); //changed
+        srcPred[1] = PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefLeftTemplate[1][0] + offset1, pcBufPredRefLeft.Y())); //changed
+#else
+        srcPred[0] = PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefLeftTemplate[0][0], pcBufPredRefLeft.Y()));
+        srcPred[1] = PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefLeftTemplate[1][0], pcBufPredRefLeft.Y()));
+#endif
+#if INTER_LIC
+#if JVET_AA0093_ENHANCED_MMVD_EXTENSION
+        if (!bLoadSave && pu.cu->LICFlag)
+#else
+          if (pu.cu->LICFlag)
+#endif
+          {
+            for (int i = 0; i < 2; i++)
+            {
+              if (pu.refIdx[i] >= 0)
+              {
+                PelBuf &      dstBuf = srcPred[i].bufs[0];
+                const ClpRng &clpRng = pu.cu->cs->slice->clpRng(COMPONENT_Y);
+                dstBuf.linearTransform(scale[i], LICshift[i], offset[i], true, clpRng);
+              }
+            }
+          }
+#endif
+        const int iRefIdx0 = pu.refIdx[0];
+        const int iRefIdx1 = pu.refIdx[1];
+        if (iRefIdx0 >= 0 && iRefIdx1 >= 0)
         {
-          PelBuf &  dstBuf   = srcPred[i].bufs[0];
-          const int biShift  = IF_INTERNAL_PREC - bitDepth;
-          const Pel biOffset = -IF_INTERNAL_OFFS;
-          ClpRng    clpRngDummy;
-          dstBuf.linearTransform(1, -biShift, biOffset, false, clpRngDummy);
+          for (int i = 0; i < 2; i++)
+          {
+#if JVET_AA0093_ENHANCED_MMVD_EXTENSION
+            if (bLoadSave && (((i == 0) && load0) || ((i == 1) && load1)))// changed
+            {
+              continue;
+            }
+#endif
+            PelBuf &  dstBuf   = srcPred[i].bufs[0];
+            const int biShift  = IF_INTERNAL_PREC - bitDepth;
+            const Pel biOffset = -IF_INTERNAL_OFFS;
+            ClpRng    clpRngDummy;
+            dstBuf.linearTransform(1, -biShift, biOffset, false, clpRngDummy);
+          }
         }
+        xWeightedAverageY(pu, srcPred[0], srcPred[1], pcBufPredRefLeft, pu.cu->slice->getSPS()->getBitDepths(),
+                          pu.cu->slice->clpRngs());
       }
-      xWeightedAverageY(pu, srcPred[0], srcPred[1], pcBufPredRefLeft, pu.cu->slice->getSPS()->getBitDepths(),
-                        pu.cu->slice->clpRngs());
     }
-  }
 }
 #if JVET_Y0058_IBC_LIST_MODIFY
 void  InterPrediction::adjustIBCMergeCandidates(PredictionUnit &pu, MergeCtx& mrgCtx, int mrgCandIdx)
@@ -9349,7 +10629,18 @@ Distortion InterPrediction::deriveTMMv(const PredictionUnit& pu, bool fillCurTpl
 
   if (otherMvf == nullptr) // uni prediction
   {
+#if JVET_AA0093_REFINED_MOTION_FOR_ARMC
+    if (pu.reduceTplSize && pu.tmMergeFlag)
+    {
+      tplCtrl.deriveMvUni<1>();
+    }
+    else
+    {
+#endif
     tplCtrl.deriveMvUni<TM_TPL_SIZE>();
+#if JVET_AA0093_REFINED_MOTION_FOR_ARMC
+    }
+#endif
     mv = tplCtrl.getFinalMv();
     return tplCtrl.getMinCost();
   }
@@ -9362,8 +10653,20 @@ Distortion InterPrediction::deriveTMMv(const PredictionUnit& pu, bool fillCurTpl
     }
 #endif
     const Picture& otherRefPic = *cu.slice->getRefPic((RefPicList)(1-eRefList), otherMvf->refIdx)->unscaledPic;
+#if JVET_AA0093_REFINED_MOTION_FOR_ARMC
+    if (pu.reduceTplSize && pu.tmMergeFlag)
+    {
+      tplCtrl.removeHighFreq<1>(otherRefPic, otherMvf->mv, getBcwWeight(cu.BcwIdx, eRefList));
+      tplCtrl.deriveMvUni<1>();
+    }
+    else
+    {
+#endif
     tplCtrl.removeHighFreq<TM_TPL_SIZE>(otherRefPic, otherMvf->mv, getBcwWeight(cu.BcwIdx, eRefList));
     tplCtrl.deriveMvUni<TM_TPL_SIZE>();
+#if JVET_AA0093_REFINED_MOTION_FOR_ARMC
+    }
+#endif
     mv = tplCtrl.getFinalMv();
 
     int8_t intWeight = getBcwWeight(cu.BcwIdx, eRefList);
@@ -9372,7 +10675,11 @@ Distortion InterPrediction::deriveTMMv(const PredictionUnit& pu, bool fillCurTpl
 }
 
 #if TM_MRG || (JVET_Z0084_IBC_TM && IBC_TM_MRG)
+#if JVET_AA0093_REFINED_MOTION_FOR_ARMC
+void InterPrediction::deriveTMMv(PredictionUnit& pu, Distortion* tmCost)
+#else
 void InterPrediction::deriveTMMv(PredictionUnit& pu)
+#endif
 {
   if( !pu.tmMergeFlag )
   {
@@ -9388,6 +10695,12 @@ void InterPrediction::deriveTMMv(PredictionUnit& pu)
       minCostUni[iRefList] = deriveTMMv(pu, true, std::numeric_limits<Distortion>::max(), (RefPicList)iRefList, pu.refIdx[iRefList], TM_MAX_NUM_OF_ITERATIONS, pu.mv[iRefList]);
     }
   }
+#if JVET_AA0093_REFINED_MOTION_FOR_ARMC
+  if (tmCost)
+  {
+    *tmCost = minCostUni[0] <= minCostUni[1] ? minCostUni[0] : minCostUni[1];
+  }
+#endif
 
   if (pu.cu->slice->isInterB() && pu.interDir == 3
 #if MULTI_PASS_DMVR
@@ -9410,6 +10723,12 @@ void InterPrediction::deriveTMMv(PredictionUnit& pu)
       pu.mv    [eTargetPicList] = Mv();
       pu.refIdx[eTargetPicList] = NOT_VALID;
     }
+#if JVET_AA0093_REFINED_MOTION_FOR_ARMC
+    else if (tmCost)
+    {
+      *tmCost = minCostBi;
+    }
+#endif
   }
 }
 #endif // TM_MRG || (JVET_Z0084_IBC_TM && IBC_TM_MRG)
@@ -9450,8 +10769,58 @@ TplMatchingCtrl::TplMatchingCtrl( const PredictionUnit&     pu,
   }
 #endif
   // Initialization
+#if JVET_AA0093_REFINED_MOTION_FOR_ARMC
+  if (m_pu.reduceTplSize && pu.tmMergeFlag)
+  {
+    bool tplAvalableAbove = xFillCurTemplate<1, true >((fillCurTpl ? curTplAbove : nullptr));
+    bool tplAvalableLeft  = xFillCurTemplate<1, false>((fillCurTpl ? curTplLeft  : nullptr));
+    tplAvalableAbove &= !(tplAvalableLeft && pu.lwidth()*2 < pu.lheight());
+    tplAvalableLeft &= !(tplAvalableAbove && pu.lheight()*2 < pu.lwidth());
+
+    m_curTplAbove = tplAvalableAbove ? PelBuf(curTplAbove, pu.lwidth(),   1 ) : PelBuf();
+    m_curTplLeft  = tplAvalableLeft  ? PelBuf(curTplLeft , 1,   pu.lheight()) : PelBuf();
+    m_refTplAbove = tplAvalableAbove ? PelBuf(refTplAbove, m_curTplAbove              ) : PelBuf();
+    m_refTplLeft  = tplAvalableLeft  ? PelBuf(refTplLeft , m_curTplLeft               ) : PelBuf();
+#if JVET_X0056_DMVD_EARLY_TERMINATION
+    m_earlyTerminateTh = ((tplAvalableAbove ? m_pu.lwidth() : 0) + (tplAvalableLeft ? m_pu.lheight() : 0));
+#endif
+
+    // Pre-interpolate samples on search area
+#if JVET_Z0084_IBC_TM
+    m_refSrAbove = tplAvalableAbove && maxSearchRounds > 0 && !CU::isIBC(m_cu) ? PelBuf(interRes.m_preFillBufA, m_curTplAbove.width + 2 * TM_SEARCH_RANGE, m_curTplAbove.height + 2 * TM_SEARCH_RANGE) : PelBuf();
+#else
+    m_refSrAbove = tplAvalableAbove && maxSearchRounds > 0 ? PelBuf(interRes.m_preFillBufA, m_curTplAbove.width + 2 * TM_SEARCH_RANGE, m_curTplAbove.height + 2 * TM_SEARCH_RANGE) : PelBuf();
+#endif
+    if (m_refSrAbove.buf != nullptr)
+    {
+      m_refSrAbove = xGetRefTemplate<1, true, TM_SEARCH_RANGE>(m_pu, m_refPic, mvStart, m_refSrAbove);
+      m_refSrAbove = m_refSrAbove.subBuf(Position(TM_SEARCH_RANGE, TM_SEARCH_RANGE), m_curTplAbove);
+    }
+
+#if JVET_Z0084_IBC_TM
+    m_refSrLeft  = tplAvalableLeft  && maxSearchRounds > 0 && !CU::isIBC(m_cu) ? PelBuf(interRes.m_preFillBufL, m_curTplLeft .width + 2 * TM_SEARCH_RANGE, m_curTplLeft .height + 2 * TM_SEARCH_RANGE) : PelBuf();
+#else
+    m_refSrLeft  = tplAvalableLeft  && maxSearchRounds > 0 ? PelBuf(interRes.m_preFillBufL, m_curTplLeft .width + 2 * TM_SEARCH_RANGE, m_curTplLeft .height + 2 * TM_SEARCH_RANGE) : PelBuf();
+#endif
+    if (m_refSrLeft.buf != nullptr)
+    {
+      m_refSrLeft = xGetRefTemplate<1, false, TM_SEARCH_RANGE>(m_pu, m_refPic, mvStart, m_refSrLeft);
+      m_refSrLeft = m_refSrLeft.subBuf(Position(TM_SEARCH_RANGE, TM_SEARCH_RANGE), m_curTplLeft);
+    }
+  }
+  else
+  {
+    bool tplAvalableAbove = xFillCurTemplate<TM_TPL_SIZE, true >((fillCurTpl ? curTplAbove : nullptr));
+    bool tplAvalableLeft  = xFillCurTemplate<TM_TPL_SIZE, false>((fillCurTpl ? curTplLeft  : nullptr));
+    if (pu.reduceTplSize)
+    {
+      tplAvalableAbove &= !(tplAvalableLeft && pu.lwidth()*2 < pu.lheight());
+      tplAvalableLeft &= !(tplAvalableAbove && pu.lheight()*2 < pu.lwidth());
+    }
+#else
   const bool tplAvalableAbove = xFillCurTemplate<TM_TPL_SIZE, true >((fillCurTpl ? curTplAbove : nullptr));
   const bool tplAvalableLeft  = xFillCurTemplate<TM_TPL_SIZE, false>((fillCurTpl ? curTplLeft  : nullptr));
+#endif
   m_curTplAbove = tplAvalableAbove ? PelBuf(curTplAbove, pu.lwidth(),   TM_TPL_SIZE ) : PelBuf();
   m_curTplLeft  = tplAvalableLeft  ? PelBuf(curTplLeft , TM_TPL_SIZE,   pu.lheight()) : PelBuf();
   m_refTplAbove = tplAvalableAbove ? PelBuf(refTplAbove, m_curTplAbove              ) : PelBuf();
@@ -9482,6 +10851,9 @@ TplMatchingCtrl::TplMatchingCtrl( const PredictionUnit&     pu,
     m_refSrLeft = xGetRefTemplate<TM_TPL_SIZE, false, TM_SEARCH_RANGE>(m_pu, m_refPic, mvStart, m_refSrLeft);
     m_refSrLeft = m_refSrLeft.subBuf(Position(TM_SEARCH_RANGE, TM_SEARCH_RANGE), m_curTplLeft);
   }
+#if JVET_AA0093_REFINED_MOTION_FOR_ARMC
+  }
+#endif
 }
 
 int TplMatchingCtrl::getDeltaMean(const PelBuf& bufCur, const PelBuf& bufRef, const int rowSubShift, const int bd)
@@ -9513,6 +10885,9 @@ void TplMatchingCtrl::deriveMvUni()
 #endif
   xRefineMvSearch<tplSize, TplMatchingCtrl::TMSEARCH_CROSS  >(                1, searchStepShift - 2);
   xRefineMvSearch<tplSize, TplMatchingCtrl::TMSEARCH_CROSS  >(                1, searchStepShift - 3);
+#if JVET_AA0093_REFINED_MOTION_FOR_ARMC
+  xRefineMvSearch<tplSize, TplMatchingCtrl::TMSEARCH_CROSS  >(                1, searchStepShift - 4);
+#endif
 #if MULTI_PASS_DMVR
   }
   else
@@ -10050,7 +11425,9 @@ Distortion TplMatchingCtrl::xGetTempMatchError(const Mv& mv)
 #endif
     int tmWeightIdx  = (m_pu.lwidth() >= TM_MIN_CU_SIZE_FOR_ALT_WEIGHTED_COST && m_pu.lheight() >= TM_MIN_CU_SIZE_FOR_ALT_WEIGHTED_COST ? 1 : 0);
     m_interRes.m_pcRdCost->setDistParam( cDistParam, curTplBuf, refTplBuf, bitDepth, trueAfalseL, tmWeightIdx, rowSubShift, m_compID );
+#if !JVET_AA0093_REFINED_MOTION_FOR_ARMC
     CHECK(TM_TPL_SIZE != 4, "The distortion function of template matching is implemetned currently only for size=4.");
+#endif
     partSum = cDistParam.distFunc( cDistParam );
   }
   else
@@ -10189,15 +11566,29 @@ bool InterPrediction::processBDMVRPU2Dir(PredictionUnit& pu, bool subPURefine[2]
     return false;
   }
 
+#if JVET_AA0093_REFINED_MOTION_FOR_ARMC
+  if (pu.cu->cs->pcv->isEncoder || (!pu.cu->cs->pcv->isEncoder && pu.bmDir == 1))
+  {
+#endif
   minCost = xBDMVRMvOneTemplateHPelSquareSearch<1>(mvFinal, initCost, pu, mvInitial_PU, 2, MV_FRACTIONAL_BITS_INTERNAL - 1, bUseMR, false);
   subPURefine[0] = minCost >= lumaArea;
   finalMvDir[0] = mvFinal[0];
+#if JVET_AA0093_REFINED_MOTION_FOR_ARMC
+  }
+#endif
 
+#if JVET_AA0093_REFINED_MOTION_FOR_ARMC
+  if (pu.cu->cs->pcv->isEncoder || (!pu.cu->cs->pcv->isEncoder && pu.bmDir == 2))
+  {
+#endif
   mvFinal[0] = mvInitial_PU[0];
   mvFinal[1] = mvInitial_PU[1];
   minCost = xBDMVRMvOneTemplateHPelSquareSearch<2>(mvFinal, initCost, pu, mvInitial_PU, 2, MV_FRACTIONAL_BITS_INTERNAL - 1, bUseMR, false);
   subPURefine[1] = minCost >= lumaArea;
   finalMvDir[1] = mvFinal[1];
+#if JVET_AA0093_REFINED_MOTION_FOR_ARMC
+  }
+#endif
 
   return true;
 }
@@ -10340,7 +11731,11 @@ void InterPrediction::processBDMVRSubPU(PredictionUnit& pu, bool subPURefine)
 
 #endif
 
+#if JVET_AA0093_REFINED_MOTION_FOR_ARMC
+bool InterPrediction::processBDMVR(PredictionUnit& pu, int step, Distortion* tmCost)
+#else
 bool InterPrediction::processBDMVR(PredictionUnit& pu)
+#endif
 {
   if( !pu.cs->slice->getSPS()->getUseDMVDMode() || !pu.cs->slice->isInterB() )
   {
@@ -10352,6 +11747,9 @@ bool InterPrediction::processBDMVR(PredictionUnit& pu)
   const int lumaArea = pu.lumaSize().area();
   bool subPURefine = true;
   Mv puOrgMv[2] = { pu.mv[0], pu.mv[1] };
+#if JVET_AA0093_REFINED_MOTION_FOR_ARMC
+  if (step != 2)
+#endif
   {
     Distortion minCost = std::numeric_limits<Distortion>::max();
     bool       bUseMR = lumaArea > 64;
@@ -10399,9 +11797,17 @@ bool InterPrediction::processBDMVR(PredictionUnit& pu)
   }
 
 #if TM_MRG
+#if JVET_AA0093_REFINED_MOTION_FOR_ARMC
+  if (pu.tmMergeFlag && step != 2)
+#else
   if (pu.tmMergeFlag)
+#endif
   {
+#if JVET_AA0093_REFINED_MOTION_FOR_ARMC
+    deriveTMMv(pu, tmCost);
+#else
     deriveTMMv(pu);
+#endif
     if (pu.interDir != 3)
     {
       return false;
@@ -10409,6 +11815,27 @@ bool InterPrediction::processBDMVR(PredictionUnit& pu)
   }
 #endif
 
+#if JVET_AA0093_REFINED_MOTION_FOR_ARMC
+  if (step == 2 && pu.interDir != 3)
+  {
+    return false;
+  }
+  else if (step == 1)
+  {
+    return true;
+  }
+  else if (step == 2)
+  {
+    bool       bUseMR = lumaArea > 64;
+#if JVET_Y0089_DMVR_BCW
+    bUseMR    |= (pu.cu->BcwIdx != BCW_DEFAULT);
+#endif
+    Mv         mvInitial_PU[2] = { pu.mv[0], pu.mv[1] };
+    Distortion initCost = xBDMVRGetMatchingError(pu, mvInitial_PU, bUseMR, false);
+    subPURefine = initCost >= lumaArea;
+  }
+#endif
+
   if (!subPURefine)
   {
     // span motion to subPU
@@ -13074,6 +14501,55 @@ void InterPrediction::deriveMVDcandAffine(const PredictionUnit& pu, RefPicList e
 
     std::stable_sort(aMvCostVec.begin(), aMvCostVec.end(), [](const std::pair<Mv, Distortion> & l, const std::pair<Mv, Distortion> & r) {return l.second < r.second; });
     
+#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC
+    int sizeCandList = (int) distance(aMvCostVec.begin(), aMvCostVec.end());
+
+    if (sizeCandList > 2)
+    {
+      Distortion lambdaTh = pu.cs->slice->getCostForARMC();
+      bool enoughDiverse = false;
+      uint32_t diverseCand = 0;
+      uint32_t posToBeInserted = 0;
+      for (uint32_t uiCand = 0; uiCand < sizeCandList - 1; ++uiCand)
+      {
+        for (uint32_t uiMergeCand = uiCand + 1; uiMergeCand < sizeCandList; ++uiMergeCand)
+        {
+          if (lambdaTh <= abs((int)(aMvCostVec[uiMergeCand].second - aMvCostVec[uiCand].second)))
+          {
+            enoughDiverse = true;
+            for (uint32_t uiMergeCand3 = 0; uiMergeCand3 < uiCand; ++uiMergeCand3)
+            {
+              if (lambdaTh > abs((int)(aMvCostVec[uiMergeCand].second - aMvCostVec[uiMergeCand3].second)))
+              {
+                enoughDiverse = false;
+                break;
+              }
+            }
+
+            if (enoughDiverse)
+            {
+              diverseCand = uiMergeCand;
+              posToBeInserted = uiCand + 1;
+              break;
+            }
+          }
+        }
+        if (enoughDiverse)
+        {
+          Distortion saveCandCost = aMvCostVec[diverseCand].second;
+          Mv   mvSave = aMvCostVec[diverseCand].first;
+
+          for (int i = diverseCand; i > posToBeInserted - 1; i--)
+          {
+            aMvCostVec[i].second = aMvCostVec[i - 1].second;
+            aMvCostVec[i].first = aMvCostVec[i - 1].first;
+          }
+          aMvCostVec[posToBeInserted].second = saveCandCost;
+          aMvCostVec[posToBeInserted].first = mvSave;
+        }
+      }
+    }
+#endif
     for (int n = 0; n < patternsNum; ++n)
     {
       cMvdDerived[n] = aMvCostVec[n].first;
@@ -13139,6 +14615,55 @@ void InterPrediction::deriveMVDcandAffine(const PredictionUnit& pu, RefPicList e
       aMvCostVec.push_back(std::pair<Mv, Distortion>(*it, uiCost));
     }
     std::stable_sort(aMvCostVec.begin(), aMvCostVec.end(), [](const std::pair<Mv, Distortion> & l, const std::pair<Mv, Distortion> & r) {return l.second < r.second; });
+#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC
+
+    int sizeCandList = (int) distance( aMvCostVec.begin(), aMvCostVec.end());
+    if (sizeCandList > 2)
+    {
+      Distortion lambdaTh = pu.cs->slice->getCostForARMC();
+      bool enoughDiverse = false;
+      uint32_t diverseCand = 0;
+      uint32_t posToBeInserted = 0;
+      for (uint32_t uiCand = 0; uiCand < sizeCandList - 1; ++uiCand)
+      {
+        for (uint32_t uiMergeCand = uiCand + 1; uiMergeCand < sizeCandList; ++uiMergeCand)
+        {
+          if (lambdaTh <= abs((int)(aMvCostVec[uiMergeCand].second - aMvCostVec[uiCand].second)))
+          {
+            enoughDiverse = true;
+            for (uint32_t uiMergeCand3 = 0; uiMergeCand3 < uiCand; ++uiMergeCand3)
+            {
+              if (lambdaTh > abs((int)(aMvCostVec[uiMergeCand].second - aMvCostVec[uiMergeCand3].second)))
+              {
+                enoughDiverse = false;
+                break;
+              }
+            }
+
+            if (enoughDiverse)
+            {
+              diverseCand = uiMergeCand;
+              posToBeInserted = uiCand + 1;
+              break;
+            }
+          }
+        }
+        if (enoughDiverse)
+        {
+          Distortion saveCandCost = aMvCostVec[diverseCand].second;
+          Mv   mvSave = aMvCostVec[diverseCand].first;
+
+          for (int i = diverseCand; i > posToBeInserted - 1; i--)
+          {
+            aMvCostVec[i].second = aMvCostVec[i - 1].second;
+            aMvCostVec[i].first = aMvCostVec[i - 1].first;
+          }
+          aMvCostVec[posToBeInserted].second = saveCandCost;
+          aMvCostVec[posToBeInserted].first = mvSave;
+        }
+      }
+    }
+#endif
     for (size_t n = 0; n < cMvdDerived.size(); ++n)
     {
       cMvdDerived[n] = aMvCostVec[n].first;
@@ -13228,6 +14753,54 @@ void InterPrediction::deriveMVDcandAffine(const PredictionUnit& pu, RefPicList e
 
     std::stable_sort(aMvCostVec.begin(), aMvCostVec.end(), [](const std::pair<Mv, Distortion> & l, const std::pair<Mv, Distortion> & r) {return l.second < r.second; });
     
+#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC
+    int sizeCandList = (int) distance(aMvCostVec.begin(), aMvCostVec.end());
+    if (sizeCandList > 2)
+    {
+      Distortion lambdaTh = pu.cs->slice->getCostForARMC();
+      bool enoughDiverse = false;
+      uint32_t diverseCand = 0;
+      uint32_t posToBeInserted = 0;
+      for (uint32_t uiCand = 0; uiCand < sizeCandList - 1; ++uiCand)
+      {
+        for (uint32_t uiMergeCand = uiCand + 1; uiMergeCand < sizeCandList; ++uiMergeCand)
+        {
+          if (lambdaTh <= abs((int)(aMvCostVec[uiMergeCand].second - aMvCostVec[uiCand].second)))
+          {
+            enoughDiverse = true;
+            for (uint32_t uiMergeCand3 = 0; uiMergeCand3 < uiCand; ++uiMergeCand3)
+            {
+              if (lambdaTh > abs((int)(aMvCostVec[uiMergeCand].second - aMvCostVec[uiMergeCand3].second)))
+              {
+                enoughDiverse = false;
+                break;
+              }
+            }
+
+            if (enoughDiverse)
+            {
+              diverseCand = uiMergeCand;
+              posToBeInserted = uiCand + 1;
+              break;
+            }
+          }
+        }
+        if (enoughDiverse)
+        {
+          Distortion saveCandCost = aMvCostVec[diverseCand].second;
+          Mv   mvSave = aMvCostVec[diverseCand].first;
+
+          for (int i = diverseCand; i > posToBeInserted - 1; i--)
+          {
+            aMvCostVec[i].second = aMvCostVec[i - 1].second;
+            aMvCostVec[i].first = aMvCostVec[i - 1].first;
+          }
+          aMvCostVec[posToBeInserted].second = saveCandCost;
+          aMvCostVec[posToBeInserted].first = mvSave;
+        }
+      }
+    }
+#endif
     for (int n = 0; n < patternsNum; ++n)
     {
       cMvdDerived[n] = aMvCostVec[n].first;
@@ -13726,6 +15299,53 @@ void InterPrediction::deriveMVDcandAffine(const PredictionUnit& pu, RefPicList e
     //--------------------------------------------------------------------------------//
     /////////////////////////////////////////////////////////////////
     std::stable_sort(aMvCostVec.begin(), aMvCostVec.end(), [](const std::pair<int, Distortion> & l, const std::pair<int, Distortion> & r) {return l.second < r.second; });
+#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC
+    int sizeCandList = (int) distance(aMvCostVec.begin(), aMvCostVec.end());
+    if (sizeCandList > 2)
+    {
+      Distortion lambdaTh = pu.cs->slice->getCostForARMC();
+      bool enoughDiverse = false;
+      uint32_t diverseCand = 0;
+      uint32_t posToBeInserted = 0;
+      for (uint32_t uiCand = 0; uiCand < sizeCandList - 1; ++uiCand)
+      {
+        for (uint32_t uiMergeCand = uiCand + 1; uiMergeCand < sizeCandList; ++uiMergeCand)
+        {
+          if (lambdaTh <= abs((int)(aMvCostVec[uiMergeCand].second - aMvCostVec[uiCand].second)))
+          {
+            enoughDiverse = true;
+            for (uint32_t uiMergeCand3 = 0; uiMergeCand3 < uiCand; ++uiMergeCand3)
+            {
+              if (lambdaTh > abs((int)(aMvCostVec[uiMergeCand].second - aMvCostVec[uiMergeCand3].second)))
+              {
+                enoughDiverse = false;
+                break;
+              }
+            }
+            if (enoughDiverse)
+            {
+              diverseCand = uiMergeCand;
+              posToBeInserted = uiCand + 1;
+              break;
+            }
+          }
+        }
+        if (enoughDiverse)
+        {
+          Distortion saveCandCost = aMvCostVec[diverseCand].second;
+          int   mvSave = aMvCostVec[diverseCand].first;
+
+          for (int i = diverseCand; i > posToBeInserted - 1; i--)
+          {
+            aMvCostVec[i].second = aMvCostVec[i - 1].second;
+            aMvCostVec[i].first = aMvCostVec[i - 1].first;
+          }
+          aMvCostVec[posToBeInserted].second = saveCandCost;
+          aMvCostVec[posToBeInserted].first = mvSave;
+        }
+      }
+    }
+#endif
     for (int n = 0; n < patternsNum; ++n)
     {
       int index = aMvCostVec[n].first;
diff --git a/source/Lib/CommonLib/InterPrediction.h b/source/Lib/CommonLib/InterPrediction.h
index 0d0f0659d35a774c8c67255709a9e123f770fc9d..96199f6fbbdf8392d43bdd5bca40373abe715489 100644
--- a/source/Lib/CommonLib/InterPrediction.h
+++ b/source/Lib/CommonLib/InterPrediction.h
@@ -542,12 +542,20 @@ public:
   static bool isSubblockVectorSpreadOverLimit( int a, int b, int c, int d, int predType );
 #endif
 #if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
+#if JVET_AA0093_ENHANCED_MMVD_EXTENSION
+  void    sortInterMergeMMVDCandidates(PredictionUnit &pu, MergeCtx& mrgCtx, uint32_t * mmvdLUT, int16_t MMVDIdx = -1);
+#else
   void    sortInterMergeMMVDCandidates(PredictionUnit &pu, MergeCtx& mrgCtx, uint32_t * mmvdLUT, uint32_t MMVDIdx = -1);
 #endif
+#endif
     
 #if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
+#if JVET_AA0093_ENHANCED_MMVD_EXTENSION
+  void    sortAffineMergeCandidates(PredictionUnit pu, AffineMergeCtx& affMrgCtx, uint32_t * affMmvdLUT, int16_t afMMVDIdx = -1, bool fromStart = false);
+#else
   void    sortAffineMergeCandidates(PredictionUnit pu, AffineMergeCtx& affMrgCtx, uint32_t * affMmvdLUT, uint32_t afMMVDIdx = -1);
 #endif
+#endif
     
 #if JVET_W0090_ARMC_TM
   void    adjustInterMergeCandidates(PredictionUnit &pu, MergeCtx& mrgCtx, int mrgCandIdx = -1);
@@ -575,8 +583,12 @@ public:
   void    updateCandInfo(MergeCtx& mrgCtx, uint32_t(*RdCandList)[MRG_MAX_NUM_CANDS], int mrgCandIdx = -1);
 #endif
 #if JVET_W0090_ARMC_TM || JVET_Z0056_GPM_SPLIT_MODE_REORDERING
+#if JVET_AA0093_ENHANCED_MMVD_EXTENSION
+  void    getBlkAMLRefTemplate(PredictionUnit &pu, PelUnitBuf &pcBufPredRefTop, PelUnitBuf &pcBufPredRefLeft, int8_t posList0 = -1, int8_t posList1 = -1, bool load0 = false, bool load1 = false);
+#else
   void    getBlkAMLRefTemplate(PredictionUnit &pu, PelUnitBuf &pcBufPredRefTop, PelUnitBuf &pcBufPredRefLeft);
 #endif
+#endif
 #if JVET_W0090_ARMC_TM
   void    adjustAffineMergeCandidates(PredictionUnit &pu, AffineMergeCtx& affMrgCtx, int mrgCandIdx = -1
 #if JVET_Z0139_NA_AFF
@@ -598,13 +610,24 @@ public:
     , bool wrapRef = false
 #endif
                                );
+#if JVET_AA0093_ENHANCED_MMVD_EXTENSION
+  void    getAffAMLRefTemplate(PredictionUnit &pu, PelUnitBuf &pcBufPredRefTop, PelUnitBuf &pcBufPredRefLeft, int8_t posList0 = -1, int8_t posList1 = -1, bool loadSave0 = false, bool loadSave1 = false);
+#else
   void    getAffAMLRefTemplate(PredictionUnit &pu, PelUnitBuf &pcBufPredRefTop, PelUnitBuf &pcBufPredRefLeft);
+#endif
 #if JVET_Z0102_NO_ARMC_FOR_ZERO_CAND
   void adjustMergeCandidates(PredictionUnit& pu, MergeCtx& smvpMergeCandCtx, int numRetrievedMergeCand);
 #endif
 #if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING
   void    adjustMergeCandidatesInOneCandidateGroup(PredictionUnit &pu, MergeCtx& smvpMergeCandCtx, int numRetrievedMergeCand, int mrgCandIdx = -1);
   void    updateCandInOneCandidateGroup(MergeCtx& mrgCtx, uint32_t* RdCandList, int numCandInCategory = -1);
+#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC
+  void    updateCandInTwoCandidateGroups(MergeCtx& mrgCtx, uint32_t* rdCandList, int numCandInCategory, MergeCtx mrgCtx2);
+#endif
+#endif
+#if JVET_AA0093_REFINED_MOTION_FOR_ARMC
+  void    adjustMergeCandidatesInOneCandidateGroup(PredictionUnit &pu, MergeCtx& smvpMergeCandCtx, bool* applyBDMVR, Mv** mvBufBDMVR, Mv** mvBufBDMVRTmp, int numRetrievedMergeCand, bool subRefineList[][2] = NULL, bool subRefineListTmp[][2] = NULL, int mrgCandIdx = -1);
+  void    updateCandInOneCandidateGroup(MergeCtx& mrgCtx, uint32_t* rdCandList, bool* applyBDMVR, Mv** mvBufBDMVR, Mv** mvBufBDMVRTmp, bool subRefineList[][2] = NULL, bool subRefineListTmp[][2] = NULL, int numCandInCategory = -1);
 #endif
 #if JVET_AA0107_RMVF_AFFINE_MERGE_DERIVATION
   void    adjustAffineMergeCandidatesOneGroup(PredictionUnit &pu, AffineMergeCtx& affMrgCtx, int listsize, int mrgCandIdx = -1);
@@ -678,7 +701,11 @@ public:
 
 #if TM_AMVP || TM_MRG || JVET_Z0084_IBC_TM
 #if TM_MRG || (JVET_Z0084_IBC_TM && IBC_TM_MRG)
+#if JVET_AA0093_REFINED_MOTION_FOR_ARMC
+  void       deriveTMMv         (PredictionUnit& pu, Distortion* tmCost = NULL);
+#else
   void       deriveTMMv         (PredictionUnit& pu);
+#endif
 #endif
   Distortion deriveTMMv         (const PredictionUnit& pu, bool fillCurTpl, Distortion curBestCost, RefPicList eRefList, int refIdx, int maxSearchRounds, Mv& mv, const MvField* otherMvf = nullptr);
 #endif // TM_AMVP || TM_MRG || JVET_Z0084_IBC_TM
@@ -745,7 +772,11 @@ public:
 public:
   Mv*       getBdofSubPuMvOffset() {return m_bdofSubPuMvOffset;}
   void      setBdmvrSubPuMvBuf(Mv* mvBuf0, Mv* mvBuf1) { m_bdmvrSubPuMvBuf[0] = mvBuf0; m_bdmvrSubPuMvBuf[1] = mvBuf1; }
+#if JVET_AA0093_REFINED_MOTION_FOR_ARMC
+  bool      processBDMVR              (PredictionUnit& pu, int step = 0, Distortion* tmCost = NULL);
+#else
   bool      processBDMVR              (PredictionUnit& pu);
+#endif
 #if JVET_X0049_ADAPT_DMVR
   bool      processBDMVRPU2Dir        (PredictionUnit& pu, bool subPURefine[2], Mv(&finalMvDir)[2]);
   void      processBDMVRSubPU         (PredictionUnit& pu, bool subPURefine);
diff --git a/source/Lib/CommonLib/Slice.cpp b/source/Lib/CommonLib/Slice.cpp
index 4999ea7855074bf6265c166ef7d105025912f851..ab0b8a20f9a8cff488b6c2d06cf70fec8a326ce9 100644
--- a/source/Lib/CommonLib/Slice.cpp
+++ b/source/Lib/CommonLib/Slice.cpp
@@ -1533,6 +1533,9 @@ void Slice::copySliceInfo(Slice *pSrc, bool cpyAlmostAll)
   m_pcPicHeader          = pSrc->m_pcPicHeader;
   m_colFromL0Flag        = pSrc->m_colFromL0Flag;
   m_colRefIdx            = pSrc->m_colRefIdx;
+#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC
+  m_costForARMC          = pSrc->m_costForARMC;
+#endif
 
   if( cpyAlmostAll ) setLambdas(pSrc->getLambdas());
 
@@ -3517,6 +3520,9 @@ SPS::SPS()
 , m_uiMaxCUHeight             ( 32)
 , m_numRPL0                   ( 0 )
 , m_numRPL1                   ( 0 )
+#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC
+  , m_numLambda               ( 0 )
+#endif
 , m_rpl1CopyFromRpl0Flag      ( false )
 , m_rpl1IdxPresentFlag        ( false )
 , m_allRplEntriesHasSameSignFlag ( true )
@@ -3610,6 +3616,9 @@ SPS::SPS()
 #if JVET_W0090_ARMC_TM
 , m_AML                       ( false )
 #endif
+#if JVET_AA0093_REFINED_MOTION_FOR_ARMC
+, m_armcRefinedMotion         ( false )
+#endif
 , m_GDREnabledFlag            ( true )
 , m_SubLayerCbpParametersPresentFlag ( true )
 , m_rprEnabledFlag            ( false )
@@ -3670,7 +3679,29 @@ void  SPS::createRPLList1(int numRPL)
 
   m_rpl1IdxPresentFlag = (m_numRPL0 != m_numRPL1) ? true : false;
 }
-
+#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC
+int  SPS::getIdx(uint32_t val) const {
+  for (int i = 0; i < m_numLambda; i++)
+  {
+    if (m_lambdaVal[i] == val)
+    {
+      return i;
+    }
+  }
+  return -1;
+}
+int  SPS::getQPOffsetsIdx(int val) const
+{
+  for (int i = 0; i < m_numLambda; i++)
+  {
+    if (m_qpOffsets[i] == val)
+    {
+      return i;
+    }
+  }
+  return -1;
+}
+#endif
 
 const int SPS::m_winUnitX[]={1,2,2,1};
 const int SPS::m_winUnitY[]={1,2,1,1};
diff --git a/source/Lib/CommonLib/Slice.h b/source/Lib/CommonLib/Slice.h
index 008a2e36d0c9820ce0f862e4fafb2fce350b802a..477d3b69177c3c85c77e039009c9dc2cfd4bc31d 100644
--- a/source/Lib/CommonLib/Slice.h
+++ b/source/Lib/CommonLib/Slice.h
@@ -1581,6 +1581,13 @@ private:
   RPLList           m_RPLList1;
   uint32_t          m_numRPL0;
   uint32_t          m_numRPL1;
+  
+#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC
+  uint32_t          m_numLambda;
+  uint32_t          m_lambdaVal[MAX_GOP];
+  int               m_qpOffsets[MAX_GOP];
+  int               m_maxbitsLambdaVal;
+#endif
 
   bool              m_rpl1CopyFromRpl0Flag;
   bool              m_rpl1IdxPresentFlag;
@@ -1719,6 +1726,9 @@ private:
   bool              m_MIP;
 #if JVET_W0090_ARMC_TM || JVET_Y0058_IBC_LIST_MODIFY || JVET_Z0075_IBC_HMVP_ENLARGE
   bool              m_AML;
+#endif
+#if JVET_AA0093_REFINED_MOTION_FOR_ARMC
+  bool              m_armcRefinedMotion;
 #endif
   ChromaQpMappingTable m_chromaQpMappingTable;
   bool m_GDREnabledFlag;
@@ -1935,6 +1945,18 @@ public:
   RPLList*                getRPLList1()                                                                       { return &m_RPLList1;                                                  }
   uint32_t                getNumRPL0() const                                                                  { return m_numRPL0;                                                    }
   uint32_t                getNumRPL1() const                                                                  { return m_numRPL1;                                                    }
+#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC
+  uint32_t                getNumLambda() const                                                                { return m_numLambda;                                                  }
+  int                     getIdx(uint32_t val) const;
+  uint32_t                getLambdaVal(int idx) const                                                         { return m_lambdaVal[idx];                                             }
+  void                    setNumLambda(uint32_t numL)                                                         { m_numLambda = numL;                                                  }
+  void                    setLambdaVal(int idx, uint32_t val)                                                 { m_lambdaVal[idx] = val;                                              }
+  uint32_t                getMaxbitsLambdaVal() const                                                         { return m_maxbitsLambdaVal;                                           }
+  void                    setMaxbitsLambdaVal(int numL)                                                       { m_maxbitsLambdaVal = numL;                                           }
+  void                    setQPOffsets(int idx, int val)                                                      { m_qpOffsets[idx] = val;                                              }
+  int                     getQPOffsets(int idx) const                                                         { return m_qpOffsets[idx];                                             }
+  int                     getQPOffsetsIdx(int val) const;
+#endif 
   void                    setRPL1CopyFromRPL0Flag(bool isCopy)                                                { m_rpl1CopyFromRpl0Flag = isCopy;                                     }
   bool                    getRPL1CopyFromRPL0Flag() const                                                     { return m_rpl1CopyFromRpl0Flag;                                       }
   bool                    getRPL1IdxPresentFlag() const                                                       { return m_rpl1IdxPresentFlag;                                         }
@@ -2199,6 +2221,10 @@ void                    setCCALFEnabledFlag( bool b )
 #if JVET_W0090_ARMC_TM || JVET_Y0058_IBC_LIST_MODIFY || JVET_Z0075_IBC_HMVP_ENLARGE
   void      setUseAML             ( bool b )                                        { m_AML = b; }
   bool      getUseAML             ()                                      const     { return m_AML; }
+#endif
+#if JVET_AA0093_REFINED_MOTION_FOR_ARMC
+  void      setUseArmcRefinedMotion ( bool b )                                      { m_armcRefinedMotion = b; }
+  bool      getUseArmcRefinedMotion  ()                                   const     { return m_armcRefinedMotion; }
 #endif
   bool      getUseWP              ()                                      const     { return m_useWeightPred; }
   bool      getUseWPBiPred        ()                                      const     { return m_useWeightedBiPred; }
@@ -2759,6 +2785,9 @@ private:
   bool                        m_enableTMVPFlag;                                         //!< enable temporal motion vector prediction
   bool                        m_picColFromL0Flag;                                       //!< syntax element collocated_from_l0_flag
   uint32_t                    m_colRefIdx;
+#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC
+  uint32_t                    m_costForARMC;                                            //!< Cost for diversity criterion
+#endif
   bool                        m_mvdL1ZeroFlag;                                          //!< L1 MVD set to zero flag
   uint32_t                    m_maxNumAffineMergeCand;                                  //!< max number of sub-block merge candidates
   bool                        m_disFracMMVD;                                            //!< fractional MMVD offsets disabled flag
@@ -2896,6 +2925,10 @@ public:
   bool                        getPicColFromL0Flag() const                               { return m_picColFromL0Flag;                                                                    }
   void                        setColRefIdx( uint32_t refIdx)                             { m_colRefIdx = refIdx;                                                                       }
   uint32_t                    getColRefIdx()                                             { return m_colRefIdx;                                                                         }
+#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC
+  void                        setCostForARMC(uint32_t cost)                             { m_costForARMC = cost;                                                                        }
+  uint32_t                    getCostForARMC()                                          { return m_costForARMC;                                                                        }
+#endif
   void                        setMvdL1ZeroFlag( bool b )                                { m_mvdL1ZeroFlag = b;                                                                         }
   bool                        getMvdL1ZeroFlag() const                                  { return m_mvdL1ZeroFlag;                                                                      }
   void                        setMaxNumAffineMergeCand( uint32_t val )                  { m_maxNumAffineMergeCand = val;                                                               }
@@ -3136,6 +3169,9 @@ private:
 
 
   uint32_t                   m_colRefIdx;
+#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC
+  uint32_t                   m_costForARMC;
+#endif
 #if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING
   std::vector<int>           m_implicitRefIdx[NUM_REF_PIC_LIST_01][NUM_REF_PIC_LIST_01][MAX_NUM_REF + 1];
 #endif
@@ -3295,6 +3331,9 @@ public:
   bool                        getColFromL0Flag() const                               { return m_colFromL0Flag;                                       }
   uint32_t                    getColRefIdx() const                                   { return m_colRefIdx;                                           }
   void                        checkColRefIdx(uint32_t curSliceSegmentIdx, const Picture* pic);
+#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC
+  uint32_t                    getCostForARMC() const                                 { return m_costForARMC;                                         }
+#endif
 #if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING
   void resizeImBuf(int numSlices)
   {
@@ -3392,6 +3431,9 @@ public:
   void                        setColRefIdx( uint32_t refIdx)                             { m_colRefIdx = refIdx;                                         }
   void                        setCheckLDC( bool b )                                  { m_bCheckLDC = b;                                              }
 
+#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC
+  void                        setCostForARMC(uint32_t cost)                          { m_costForARMC = cost;                                         }
+#endif
   void                        setBiDirPred( bool b, int refIdx0, int refIdx1 ) { m_biDirPred = b; m_symRefIdx[0] = refIdx0; m_symRefIdx[1] = refIdx1; }
   bool                        getBiDirPred() const { return m_biDirPred; }
   int                         getSymRefIdx( int refList ) const { return m_symRefIdx[refList]; }
diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h
index 67201d86365cf5d7001b502058153ac20ee4303e..f24394be67d5ba8d1ba7edccbd593b5ed8350181 100644
--- a/source/Lib/CommonLib/TypeDef.h
+++ b/source/Lib/CommonLib/TypeDef.h
@@ -201,8 +201,13 @@
 #define JVET_Y0134_TMVP_NAMVP_CAND_REORDERING             1 // JVET-Y0134: MV candidate reordering for TMVP and NAMVP types (controlled by JVET_W0090_ARMC_TM), and reference picture selection for TMVP 
 #if JVET_W0090_ARMC_TM
 #define JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED            1 // JVET-Y0067: TM based reordering for MMVD and affine MMVD and MVD sign prediction
+#if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
+#define JVET_AA0093_ENHANCED_MMVD_EXTENSION               1 // JVET-AA0093: Test 2.3 part: Extension on TM based reordering for MMVD and affine MMVD
+#endif
 #define JVET_Z0102_NO_ARMC_FOR_ZERO_CAND                  1 // JVET-Z0102: No ARMC for the zero candidates of regular, TM and BM merge modes
 #define JVET_Z0054_BLK_REF_PIC_REORDER                    1 // JVET-Z0054: Block level TM based reordering of reference pictures
+#define JVET_AA0093_REFINED_MOTION_FOR_ARMC               1 // JVET-AA0093: Refined motion for ARMC
+#define JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC          1 // JVET-AA0093: Diversity criterion for ARMC reordering
 #endif
 
 // Transform and coefficient coding
diff --git a/source/Lib/CommonLib/Unit.cpp b/source/Lib/CommonLib/Unit.cpp
index 4b17a450b2f8462a2e1d0f4fc699455670f71cfa..1fefd8c815b3536b6f9ed68a04ab7f47182f59b7 100644
--- a/source/Lib/CommonLib/Unit.cpp
+++ b/source/Lib/CommonLib/Unit.cpp
@@ -705,6 +705,9 @@ void PredictionUnit::initData()
 #else
   ::memset(mvdL0SubPu, 0, sizeof(mvdL0SubPu));
 #endif
+#if JVET_AA0093_REFINED_MOTION_FOR_ARMC
+  reduceTplSize = false;
+#endif
 
 #if JVET_Z0054_BLK_REF_PIC_REORDER
   refIdxLC = -1;
@@ -830,6 +833,9 @@ PredictionUnit& PredictionUnit::operator=(const InterPredictionData& predData)
 #else
   ::memcpy(mvdL0SubPu, predData.mvdL0SubPu, sizeof(mvdL0SubPu));
 #endif
+#if JVET_AA0093_REFINED_MOTION_FOR_ARMC
+  reduceTplSize = predData.reduceTplSize;
+#endif
 
   for (uint32_t i = 0; i < NUM_REF_PIC_LIST_01; i++)
   {
@@ -951,6 +957,9 @@ PredictionUnit& PredictionUnit::operator=( const PredictionUnit& other )
 #else
   ::memcpy(mvdL0SubPu, other.mvdL0SubPu, sizeof(mvdL0SubPu));
 #endif
+#if JVET_AA0093_REFINED_MOTION_FOR_ARMC
+  reduceTplSize = other.reduceTplSize;
+#endif
 
   for (uint32_t i = 0; i < NUM_REF_PIC_LIST_01; i++)
   {
diff --git a/source/Lib/CommonLib/Unit.h b/source/Lib/CommonLib/Unit.h
index 72b66531d4fa420513d258aa052281d180bea337..39de95978dd388fa8b5db80f3d312076f4fe0000 100644
--- a/source/Lib/CommonLib/Unit.h
+++ b/source/Lib/CommonLib/Unit.h
@@ -439,7 +439,11 @@ struct InterPredictionData
 {
   bool      mergeFlag;
   bool      regularMergeFlag;
+#if JVET_AA0093_ENHANCED_MMVD_EXTENSION
+  uint16_t    mergeIdx;
+#else
   uint8_t     mergeIdx;
+#endif
   uint8_t     geoSplitDir;
 #if JVET_Z0056_GPM_SPLIT_MODE_REORDERING
   uint8_t     geoSyntaxMode;
@@ -464,16 +468,24 @@ struct InterPredictionData
   uint8_t     geoBldIdx;
 #endif
   bool           mmvdMergeFlag;
+#if JVET_AA0093_ENHANCED_MMVD_EXTENSION
+  uint16_t      mmvdMergeIdx;
+#else
   uint8_t       mmvdMergeIdx;
+#endif
 #if AFFINE_MMVD
   bool        afMmvdFlag;
   uint8_t     afMmvdBaseIdx; // base vector's merge index at the affine merge list, excluding sbTmvp
   uint8_t     afMmvdStep;
   uint8_t     afMmvdDir;
 #if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
+#if JVET_AA0093_ENHANCED_MMVD_EXTENSION
+  uint16_t    afMmvdMergeIdx;
+#else
   uint8_t     afMmvdMergeIdx;
 #endif
 #endif
+#endif
 #if TM_MRG || (JVET_Z0084_IBC_TM && IBC_TM_MRG)
   bool        tmMergeFlag;
 #endif
@@ -491,6 +503,9 @@ struct InterPredictionData
 #else
   Mv        mvdL0SubPu[MAX_NUM_SUBCU_DMVR];
 #endif
+#if JVET_AA0093_REFINED_MOTION_FOR_ARMC
+  bool      reduceTplSize;
+#endif
 #if JVET_X0083_BM_AMVP_MERGE_MODE
   bool      amvpMergeModeFlag[NUM_REF_PIC_LIST_01];
 #endif
diff --git a/source/Lib/CommonLib/UnitTools.cpp b/source/Lib/CommonLib/UnitTools.cpp
index 96efd102c1e39b3696602fe30d87b61f0597feb7..515b0fdacfe37c5fac12eed83e732d370304a11c 100644
--- a/source/Lib/CommonLib/UnitTools.cpp
+++ b/source/Lib/CommonLib/UnitTools.cpp
@@ -2799,11 +2799,25 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx,
   const Slice &slice         = *pu.cs->slice;
 #if TM_MRG
   const uint32_t mvdSimilarityThresh = pu.tmMergeFlag ? PU::getTMMvdThreshold(pu) : 1;
+#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC && JVET_Y0134_TMVP_NAMVP_CAND_REORDERING
+  uint32_t additionalMRGCand = 0;
+  if (tmvpMrgCtx != NULL)
+  {
+    additionalMRGCand = tmvpMrgCtx->numValidMergeCand;
+  }
+  if (namvpMrgCtx != NULL)
+  {
+    additionalMRGCand += namvpMrgCtx->numValidMergeCand;
+  }
+  const uint32_t maxNumMergeCand = pu.tmMergeFlag ? std::min((int)(TM_MRG_MAX_NUM_INIT_CANDS + additionalMRGCand), ((int)NUM_MERGE_CANDS - (3)))
+                                                  : std::min((int) (pu.cs->sps->getMaxNumMergeCand() + additionalMRGCand), ((int)NUM_MERGE_CANDS - (3)));
+#else
 #if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM
   const uint32_t maxNumMergeCand = pu.tmMergeFlag ? (pu.cs->sps->getUseAML()) ? TM_MRG_MAX_NUM_INIT_CANDS : pu.cs->sps->getMaxNumTMMergeCand() : pu.cs->sps->getMaxNumMergeCand();
 #else
   const uint32_t maxNumMergeCand     = pu.tmMergeFlag ? pu.cs->sps->getMaxNumTMMergeCand() : pu.cs->sps->getMaxNumMergeCand();
 #endif
+#endif
 #else
   const uint32_t maxNumMergeCand = pu.cs->sps->getMaxNumMergeCand();
 #endif
@@ -3428,6 +3442,84 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx,
     }
     else if (tmvpMrgCtx->numValidMergeCand > 0)
     {
+#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC
+      if (!pu.tmMergeFlag)
+      {
+        for (uint32_t ui = 0; ui < tmvpMrgCtx->numValidMergeCand && cnt < maxNumMergeCand - 1; ++ui)
+        {
+          mrgCtx.BcwIdx[cnt] = tmvpMrgCtx->BcwIdx[ui];
+#if INTER_LIC
+          mrgCtx.LICFlags[cnt] = tmvpMrgCtx->LICFlags[ui];
+#endif
+          mrgCtx.interDirNeighbours[cnt]     = tmvpMrgCtx->interDirNeighbours[ui];
+          mrgCtx.mvFieldNeighbours[cnt << 1] = tmvpMrgCtx->mvFieldNeighbours[ui << 1];
+          mrgCtx.useAltHpelIf[cnt]           = tmvpMrgCtx->useAltHpelIf[ui];
+          if (slice.isInterB())
+          {
+            mrgCtx.mvFieldNeighbours[(cnt << 1) + 1] = tmvpMrgCtx->mvFieldNeighbours[(ui << 1) + 1];
+#if MULTI_HYP_PRED
+            mrgCtx.addHypNeighbours[cnt] = tmvpMrgCtx->addHypNeighbours[ui];
+#endif
+          }
+
+#if NON_ADJACENT_MRG_CAND || TM_MRG
+          if (!mrgCtx.xCheckSimilarMotion(cnt
+#if TM_MRG
+                                          , mvdSimilarityThresh
+#endif
+                                          ))
+          {
+#endif
+            mrgCtx.candCost[cnt] = tmvpMrgCtx->candCost[ui];
+            if (mrgCandIdx == cnt)
+            {
+              return;
+            }
+
+            cnt++;
+#if NON_ADJACENT_MRG_CAND || TM_MRG
+          }
+#endif
+        }
+      }
+      else
+      {
+        mrgCtx.BcwIdx[cnt] = tmvpMrgCtx->BcwIdx[0];
+#if INTER_LIC
+        mrgCtx.LICFlags[cnt] = tmvpMrgCtx->LICFlags[0];
+#endif
+        mrgCtx.interDirNeighbours[cnt]     = tmvpMrgCtx->interDirNeighbours[0];
+        mrgCtx.mvFieldNeighbours[cnt << 1] = tmvpMrgCtx->mvFieldNeighbours[0];
+        mrgCtx.useAltHpelIf[cnt]           = tmvpMrgCtx->useAltHpelIf[0];
+        if (slice.isInterB())
+        {
+          mrgCtx.mvFieldNeighbours[(cnt << 1) + 1] = tmvpMrgCtx->mvFieldNeighbours[1];
+#if MULTI_HYP_PRED
+          mrgCtx.addHypNeighbours[cnt] = tmvpMrgCtx->addHypNeighbours[0];
+#endif
+        }
+
+#if NON_ADJACENT_MRG_CAND || TM_MRG
+        if (!mrgCtx.xCheckSimilarMotion(cnt
+#if TM_MRG
+                                        ,mvdSimilarityThresh
+#endif
+                                        ))
+        {
+#endif
+          mrgCtx.candCost[cnt] = tmvpMrgCtx->candCost[0];
+          if (mrgCandIdx == cnt)
+          {
+            return;
+          }
+
+          cnt++;
+#if NON_ADJACENT_MRG_CAND || TM_MRG
+        }
+#endif
+      }
+    }
+#else
       mrgCtx.BcwIdx[cnt] = tmvpMrgCtx->BcwIdx[0];
 #if INTER_LIC
       mrgCtx.LICFlags[cnt] = tmvpMrgCtx->LICFlags[0];
@@ -3462,6 +3554,7 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx,
       }
 #endif
     }
+#endif
 #endif
   }
 
@@ -3482,12 +3575,20 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx,
   const int iNACANDIDATE_NUM[4] = { 3, 5, 5, 5 };
   const int idxMap[4][5] = { { 0, 1, 4 },{ 0, 1, 2, 3, 4 },{ 0, 1, 2, 3, 4 },{ 0, 1, 2, 3, 4 } };
 
+#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC
+  for (int iDistanceIndex = 0; iDistanceIndex < NADISTANCE_LEVEL && cnt < maxNumMergeCand; iDistanceIndex++)
+#else
   for (int iDistanceIndex = 0; iDistanceIndex < NADISTANCE_LEVEL && cnt < maxNumMergeCand - 1; iDistanceIndex++)
+#endif
   {
     const int iNADistanceHor = pu.Y().width  * (iDistanceIndex + 1);
     const int iNADistanceVer = pu.Y().height * (iDistanceIndex + 1);
 
+#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC
+    for (int NASPIdx = 0; NASPIdx < iNACANDIDATE_NUM[iDistanceIndex] && cnt < maxNumMergeCand; NASPIdx++)
+#else
     for (int NASPIdx = 0; NASPIdx < iNACANDIDATE_NUM[iDistanceIndex] && cnt < maxNumMergeCand - 1; NASPIdx++)
+#endif
     {
       switch (idxMap[iDistanceIndex][NASPIdx])
       {
@@ -3571,7 +3672,11 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx,
   }
   else
   {
+#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC
+    for (uint32_t ui = 0; ui < namvpMrgCtx->numValidMergeCand && cnt < maxNumMergeCand; ++ui)
+#else
     for (uint32_t ui = 0; ui < namvpMrgCtx->numValidMergeCand && cnt < maxNumMergeCand - 1; ++ui)
+#endif
     {
       mrgCtx.BcwIdx[cnt] = namvpMrgCtx->BcwIdx[ui];
 #if INTER_LIC
@@ -3611,7 +3716,11 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx,
 #endif
 #endif
 
+#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC
+  int maxNumMergeCandMin1 = maxNumMergeCand;
+#else
   int maxNumMergeCandMin1 = maxNumMergeCand - 1;
+#endif
   if (cnt != maxNumMergeCandMin1)
   {
 #if !JVET_Z0075_IBC_HMVP_ENLARGE
@@ -3643,6 +3752,7 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx,
     }
   }
 
+#if !JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC 
   // pairwise-average candidates
   {
     if (cnt > 1 && cnt < maxNumMergeCand)
@@ -3742,6 +3852,13 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx,
       return;
     }
   }
+#else
+  // early termination
+  if (cnt == maxNumMergeCand)
+  {
+    return;
+  }
+#endif
 
 #if JVET_Z0139_HIST_AFF
   if (addMergeHMVPCandFromAffModel(pu, mrgCtx, mrgCandIdx, cnt
@@ -4685,7 +4802,21 @@ void PU::getInterBMCandidates(const PredictionUnit &pu, MergeCtx& mrgCtx,
   const CodingStructure &cs = *pu.cs;
   const Slice &slice = *pu.cs->slice;
 #if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM
+#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC
+  uint32_t additionalMRGCand = 0;
+  if (mvpMrgCtx1 != NULL)
+  {
+    additionalMRGCand = mvpMrgCtx1->numValidMergeCand;
+  }
+  if (mvpMrgCtx2 != NULL)
+  {
+    additionalMRGCand += mvpMrgCtx2->numValidMergeCand;
+  }
+  const uint32_t maxNumMergeCand = (pu.cs->sps->getUseAML()) ? std::min((int)(BM_MRG_MAX_NUM_INIT_CANDS + additionalMRGCand), ((int)NUM_MERGE_CANDS - (3))) 
+                                                             : pu.cs->sps->getMaxNumBMMergeCand();
+#else
   const uint32_t maxNumMergeCand = (pu.cs->sps->getUseAML()) ? BM_MRG_MAX_NUM_INIT_CANDS : pu.cs->sps->getMaxNumBMMergeCand();
+#endif
 #else
   const uint32_t maxNumMergeCand = pu.cs->sps->getMaxNumBMMergeCand();
 #endif
@@ -5060,6 +5191,33 @@ void PU::getInterBMCandidates(const PredictionUnit &pu, MergeCtx& mrgCtx,
     }
 #if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM
     }
+#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC
+    else if (mvpMrgCtx1->numValidMergeCand > 0)
+    {
+      for (int uiNumCand = 0; uiNumCand < mvpMrgCtx1->numValidMergeCand && cnt < maxNumMergeCand; uiNumCand++)
+      {
+        mrgCtx.interDirNeighbours[cnt] = mvpMrgCtx1->interDirNeighbours[uiNumCand];
+        mrgCtx.mvFieldNeighbours[cnt << 1] = mvpMrgCtx1->mvFieldNeighbours[uiNumCand << 1];
+        mrgCtx.useAltHpelIf[cnt] = mvpMrgCtx1->useAltHpelIf[uiNumCand];
+        mrgCtx.mvFieldNeighbours[(cnt << 1) + 1] = mvpMrgCtx1->mvFieldNeighbours[(uiNumCand << 1) + 1];
+#if JVET_Y0089_DMVR_BCW
+        mrgCtx.BcwIdx[cnt] = (mrgCtx.interDirNeighbours[cnt] == 3) ? mvpMrgCtx1->BcwIdx[uiNumCand] : BCW_DEFAULT;
+#endif
+#if NON_ADJACENT_MRG_CAND || TM_MRG
+        if (!mrgCtx.xCheckSimilarMotion(cnt, mvThreshod))
+#endif
+        {
+          mrgCtx.candCost[cnt] = mvpMrgCtx1->candCost[uiNumCand];
+          if (mrgCandIdx == cnt)
+          {
+            mrgCtx.numValidMergeCand = cnt + 1;
+            return;
+          }
+          cnt++;
+        }
+      }
+    }
+#else
     else if (mvpMrgCtx1->numValidMergeCand > 0)
     {
       mrgCtx.interDirNeighbours[cnt] = mvpMrgCtx1->interDirNeighbours[0];
@@ -5085,6 +5243,7 @@ void PU::getInterBMCandidates(const PredictionUnit &pu, MergeCtx& mrgCtx,
         cnt++;
       }
     }
+#endif
 #endif
   }
 
@@ -5095,7 +5254,11 @@ void PU::getInterBMCandidates(const PredictionUnit &pu, MergeCtx& mrgCtx,
     return;
   }
 
+#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC
+  int maxNumMergeCandMin1 = maxNumMergeCand;
+#else
   int maxNumMergeCandMin1 = maxNumMergeCand - 1;
+#endif
 #if NON_ADJACENT_MRG_CAND
 #if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM
   if (mvpMrgCtx2 == NULL)
@@ -5217,6 +5380,7 @@ void PU::getInterBMCandidates(const PredictionUnit &pu, MergeCtx& mrgCtx,
     }
   }
 
+#if !JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC
   {
     if (cnt > 1 && cnt < maxNumMergeCand)
     {
@@ -5244,12 +5408,12 @@ void PU::getInterBMCandidates(const PredictionUnit &pu, MergeCtx& mrgCtx,
         }
 
         interDir += 1 << refListId;
-        const Mv& MvI = mrgCtx.mvFieldNeighbours[0 * 2 + refListId].mv;
-        const Mv& MvJ = mrgCtx.mvFieldNeighbours[1 * 2 + refListId].mv;
+        const Mv& mvI = mrgCtx.mvFieldNeighbours[0 * 2 + refListId].mv;
+        const Mv& mvJ = mrgCtx.mvFieldNeighbours[1 * 2 + refListId].mv;
 
         // average two MVs
-        Mv avgMv = MvI;
-        avgMv += MvJ;
+        Mv avgMv = mvI;
+        avgMv += mvJ;
         roundAffineMv(avgMv.hor, avgMv.ver, 1);
 
         mrgCtx.mvFieldNeighbours[cnt * 2 + refListId].setMvField(avgMv, refIdxI);
@@ -5272,6 +5436,7 @@ void PU::getInterBMCandidates(const PredictionUnit &pu, MergeCtx& mrgCtx,
       return;
     }
   }
+#endif
 
   mrgCtx.numCandToTestEnc = cnt;
 
@@ -5656,7 +5821,11 @@ void PU::getTmvpMergeCand(const PredictionUnit &pu, MergeCtx& mrgCtx)
 #if TM_MRG
   const uint32_t mvdSimilarityThresh = 1;
 #endif
+#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC
+  const uint32_t maxNumMergeCand = pu.tmMergeFlag ? 1 :NUM_TMVP_CANDS;
+#else
   const uint32_t maxNumMergeCand = NUM_TMVP_CANDS;
+#endif
   for (uint32_t ui = 0; ui < maxNumMergeCand; ++ui)
   {
     mrgCtx.BcwIdx[ui] = BCW_DEFAULT;
@@ -5923,7 +6092,11 @@ void PU::getNonAdjacentMergeCand(const PredictionUnit &pu, MergeCtx& mrgCtx)
   const Slice &slice = *pu.cs->slice;
 
 #if TM_MRG
+#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC 
+  const uint32_t mvdSimilarityThresh = pu.tmMergeFlag ? PU::getTMMvdThreshold(pu) : 1;
+#else
   const uint32_t mvdSimilarityThresh = getBDMVRMvdThreshold(pu);
+#endif
 #endif
   const uint32_t maxNumMergeCand = NUM_NON_ADJ_CANDS;
 
@@ -7040,9 +7213,47 @@ void PU::fillMvpCand(PredictionUnit &pu, const RefPicList &eRefPicList, const in
       tmCost[i] = std::numeric_limits<Distortion>::max();
     }
 
+#if JVET_AA0093_REFINED_MOTION_FOR_ARMC
+    bool armcRefinedMotion = isArmcRefinedMotionEnabled(pu, 0);
+    if (armcRefinedMotion)
+    {
+      pu.reduceTplSize = true;
+    }
+    if (armcRefinedMotion && pInfo->numCand > 1)
+    {
+      for (int candIdx = 0; candIdx < pInfo->numCand; ++candIdx)
+      {
+        tmCost[candIdx] = interPred->deriveTMMv(pu, true, std::numeric_limits<Distortion>::max(), eRefPicList, refIdx, 0, pInfo->mvCand[candIdx]);
+        temp.AMVPCand = pInfo->mvCand[candIdx];
+        temp.cost = tmCost[candIdx];
+        input.push_back(temp);
+      }
+      stable_sort(input.begin(), input.end(), CostIncSort);
+      for (int candIdx = 1; candIdx < pInfo->numCand; ++candIdx)
+      {
+        if (input.at(candIdx).cost > 5 * input.at(0).cost)
+        {
+          pInfo->numCand = candIdx + 1;
+          break;
+        }
+      }
+      input.clear();
+    }
+#endif
     for (int candIdx = 0; candIdx < pInfo->numCand; ++candIdx)
     {
+#if JVET_AA0093_REFINED_MOTION_FOR_ARMC
+      if (armcRefinedMotion)
+      {
+        tmCost[candIdx] = interPred->deriveTMMv(pu, true, std::numeric_limits<Distortion>::max(), eRefPicList, refIdx, TM_MAX_NUM_OF_ITERATIONS, pInfo->mvCand[candIdx]);
+      }
+      else
+      {
+        tmCost[candIdx] = interPred->deriveTMMv(pu, true, std::numeric_limits<Distortion>::max(), eRefPicList, refIdx, 0, pInfo->mvCand[candIdx]);
+      }
+#else
       tmCost[candIdx] = interPred->deriveTMMv(pu, true, std::numeric_limits<Distortion>::max(), eRefPicList, refIdx, 0, pInfo->mvCand[candIdx]);
+#endif
       temp.AMVPCand = pInfo->mvCand[candIdx];
       temp.cost = tmCost[candIdx];
       input.push_back(temp);
@@ -7054,9 +7265,19 @@ void PU::fillMvpCand(PredictionUnit &pu, const RefPicList &eRefPicList, const in
       pInfo->mvCand[candIdx] = input.at(candIdx).AMVPCand;
       tmCost[candIdx] = input.at(candIdx).cost;
     }
+#if JVET_AA0093_REFINED_MOTION_FOR_ARMC
+    pu.reduceTplSize = false;
+#endif
 
     pInfo->numCand = 1;
+#if JVET_AA0093_REFINED_MOTION_FOR_ARMC
+    if (!armcRefinedMotion)
+    {
+#endif
     interPred->deriveTMMv(pu, true, tmCost[0], eRefPicList, refIdx, TM_MAX_NUM_OF_ITERATIONS, pInfo->mvCand[0]);
+#if JVET_AA0093_REFINED_MOTION_FOR_ARMC
+    }
+#endif
   }
 
   while (pInfo->numCand < pInfo->maxStorageSize)
@@ -10638,7 +10859,11 @@ void PU::getAfMmvdMvf(const PredictionUnit& pu, const AffineMergeCtx& affineMerg
   CHECK(!pu.cu->affine, "Affine flag is not on for Affine MMVD mode!");
   CHECK(affineMergeCtx.mergeType[afMmvdBase] != MRG_TYPE_DEFAULT_N, "AFF_MMVD base candidate type is not regular Affine!");
 
+#if JVET_AA0093_ENHANCED_MMVD_EXTENSION
+  static const int32_t refMvdCands[AF_MMVD_STEP_NUM] = { 1, 2, 4, 8 };
+#else
   static const int32_t refMvdCands[AF_MMVD_STEP_NUM] = { 1, 2, 4, 8, 16 };
+#endif
 #if JVET_Y0128_NON_CTC
   const int32_t iPicSize = pu.cu->slice->getPic()->lumaSize().area();
   const int32_t mvShift  = iPicSize < 921600 ? 0 : ( iPicSize < 4096000 ? 2 : MV_FRACTIONAL_BITS_INTERNAL - 1); // 921600 = 1280x720, 4096000 = 2560x1600
@@ -10667,8 +10892,13 @@ void PU::getAfMmvdMvf(const PredictionUnit& pu, const AffineMergeCtx& affineMerg
 #if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
   const int xDir[] = {1, -1,  0,  0,  1, -1,  1, -1, 2, -2,  2, -2, 1,  1, -1, -1};
   const int yDir[] = {0,  0,  1, -1,  1, -1, -1,  1, 1,  1, -1, -1, 2, -2,  2, -2};
+#if JVET_AA0093_ENHANCED_MMVD_EXTENSION
+  int offsetX = xDir[offsetDir % 8]  * step;
+  int offsetY = yDir[offsetDir % 8]  * step;
+#else
   int offsetX = xDir[offsetDir]  * step;
   int offsetY = yDir[offsetDir] * step;
+#endif
 #else
   int magY = (offsetDir >> 1) & 0x1;
   int sign = (offsetDir & 0x1) ? -1 : 1;
@@ -10688,6 +10918,31 @@ void PU::getAfMmvdMvf(const PredictionUnit& pu, const AffineMergeCtx& affineMerg
     {
       mvfMmvd[1][cpIdx].mv = baseMv[1][cpIdx] + offsetMv;
     }
+#if JVET_AA0093_ENHANCED_MMVD_EXTENSION
+    else if (interDir == 3)
+    {
+      if (offsetDir >=  16)
+      {
+        int poc_cur = pu.cu->slice->getPOC();
+        int poc_l0  = pu.cu->slice->getRefPOC(REF_PIC_LIST_0, refIdxL0);
+        int poc_l1  = pu.cu->slice->getRefPOC(REF_PIC_LIST_1, refIdxL1);
+        int distL0 = poc_l0 - poc_cur;
+        int distL1 = poc_l1 - poc_cur;
+        mvfMmvd[0][cpIdx].mv =                                                     baseMv[0][cpIdx] + offsetMv;
+        mvfMmvd[1][cpIdx].mv = distL0 * distL1 < 0 ? baseMv[1][cpIdx] - offsetMv : baseMv[1][cpIdx] + offsetMv;
+      }
+      else if (offsetDir >= 8)
+      {
+        mvfMmvd[0][cpIdx].mv =                                                   baseMv[0][cpIdx] ;
+        mvfMmvd[1][cpIdx].mv =                                                   baseMv[1][cpIdx] + offsetMv;
+      }
+      else
+      {
+        mvfMmvd[0][cpIdx].mv =                                                   baseMv[0][cpIdx] + offsetMv;
+        mvfMmvd[1][cpIdx].mv =                                                   baseMv[1][cpIdx] ;
+      }
+    }
+#else
     else if (interDir == 3)
     {
       int poc_cur = pu.cu->slice->getPOC();
@@ -10699,6 +10954,7 @@ void PU::getAfMmvdMvf(const PredictionUnit& pu, const AffineMergeCtx& affineMerg
       mvfMmvd[0][cpIdx].mv =                                                     baseMv[0][cpIdx] + offsetMv;
       mvfMmvd[1][cpIdx].mv = distL0 * distL1 < 0 ? baseMv[1][cpIdx] - offsetMv : baseMv[1][cpIdx] + offsetMv;
     }
+#endif
   }
 }
 
@@ -13716,6 +13972,31 @@ bool PU::checkIsValidMergeMvCand(const CodingStructure &cs, const PredictionUnit
   return true;
 }
 #endif
+#if JVET_AA0093_REFINED_MOTION_FOR_ARMC
+bool PU::isArmcRefinedMotionEnabled(const PredictionUnit &pu, unsigned mode)
+{
+  if (!pu.cs->sps->getUseAML() || !pu.cs->sps->getUseArmcRefinedMotion())
+  {
+    return false;
+  }
+  int blkSize = pu.lwidth() * pu.lheight();
+  if (mode == 0)
+  {
+    if (pu.cs->slice->getTLayer() < 5 && blkSize > 32 && blkSize <= 1024)
+    {
+      return true;
+    }
+  }
+  else
+  {
+    if ((blkSize <= (mode == 1 ? 2048 : 4096)) && ( blkSize > 64))
+    {
+      return true;
+    }
+  }
+  return false;
+}
+#endif
 #endif
 
 #if JVET_Z0135_TEMP_CABAC_WIN_WEIGHT
diff --git a/source/Lib/CommonLib/UnitTools.h b/source/Lib/CommonLib/UnitTools.h
index 12f2a13350218a528d9433756bcfec9f07025cf9..492c28ab478014209afc12bf8b221aed44a50521 100644
--- a/source/Lib/CommonLib/UnitTools.h
+++ b/source/Lib/CommonLib/UnitTools.h
@@ -400,6 +400,9 @@ namespace PU
 #endif
   bool isLMCModeEnabled               (const PredictionUnit &pu, unsigned mode);
   bool isChromaIntraModeCrossCheckMode(const PredictionUnit &pu);
+#if JVET_AA0093_REFINED_MOTION_FOR_ARMC
+  bool isArmcRefinedMotionEnabled(const PredictionUnit &pu, unsigned mode);
+#endif
 
 #if JVET_W0097_GPM_MMVD_TM
 #if TM_MRG
diff --git a/source/Lib/DecoderLib/CABACReader.cpp b/source/Lib/DecoderLib/CABACReader.cpp
index 7341fc244d9f1dc9ad49031d5a4e509f1c4cdf07..b903b3ec86f2340d093d30aa8d432369c39e85de 100644
--- a/source/Lib/DecoderLib/CABACReader.cpp
+++ b/source/Lib/DecoderLib/CABACReader.cpp
@@ -3317,42 +3317,68 @@ void CABACReader::affine_mmvd_data(PredictionUnit& pu)
     return;
   }
   RExt__DECODER_DEBUG_BIT_STATISTICS_CREATE_SET_SIZE(STATS__CABAC_BITS__AFFINE_MMVD, pu.lumaSize());
-
+  
   pu.afMmvdFlag = (m_BinDecoder.decodeBin(Ctx::AfMmvdFlag()));
   DTRACE(g_trace_ctx, D_SYNTAX, "affine_mmvd_flag() af_mmvd_merge=%d pos=(%d,%d) size=%dx%d\n", pu.afMmvdFlag ? 1 : 0, pu.lumaPos().x, pu.lumaPos().y, pu.lumaSize().width, pu.lumaSize().height);
-
+  
   if (!pu.afMmvdFlag)
   {
     return;
   }
-
+  
   // Base affine merge candidate idx
   uint8_t afMmvdBaseIdx = 0;
-  int numCandminus1_base = AF_MMVD_BASE_NUM - 1;
-  if (numCandminus1_base > 0)
+  int numCandMinus1Base = AF_MMVD_BASE_NUM - 1;
+#if JVET_AA0093_ENHANCED_MMVD_EXTENSION
+  unsigned ctxId = 0;
+  const CodingStructure *cs = pu.cu->cs;
+  const CodingUnit *cuLeft = cs->getCURestricted( pu.cu->lumaPos().offset( -1, 0 ), *pu.cu, CH_L );
+  ctxId = (cuLeft && cuLeft->affine) ? 1 : 0;
+  const CodingUnit *cuAbove = cs->getCURestricted( pu.cu->lumaPos().offset( 0, -1 ), *pu.cu, CH_L );
+  ctxId += (cuAbove && cuAbove->affine) ? 1 : 0;
+  numCandMinus1Base = (ctxId == 0) ? 0 : ((ctxId == 1) ? 1 : AF_MMVD_BASE_NUM-1);
+#endif
+  if (numCandMinus1Base > 0)
   {
     // to support more base candidates
-    if (m_BinDecoder.decodeBin(Ctx::AfMmvdIdx()))
-    {
-      afMmvdBaseIdx++;
-      for (; afMmvdBaseIdx < numCandminus1_base; afMmvdBaseIdx++)
+#if JVET_AA0093_ENHANCED_MMVD_EXTENSION
+    int ctx2 =  (numCandMinus1Base == 1) ? 1 : 0;
+    if (m_BinDecoder.decodeBin(Ctx::AfMmvdIdx(ctx2)))
+#else
+      if (m_BinDecoder.decodeBin(Ctx::AfMmvdIdx()))
+#endif
       {
-        if (!m_BinDecoder.decodeBinEP())
+        afMmvdBaseIdx++;
+        for (; afMmvdBaseIdx < numCandMinus1Base; afMmvdBaseIdx++)
         {
-          break;
+#if JVET_AA0093_ENHANCED_MMVD_EXTENSION
+          if (!m_BinDecoder.decodeBin(Ctx::AfMmvdIdx(afMmvdBaseIdx + 1)))
+#else
+            if (!m_BinDecoder.decodeBinEP())
+#endif
+            {
+              break;
+            }
         }
       }
-    }
   }
   pu.afMmvdBaseIdx = afMmvdBaseIdx;
   DTRACE(g_trace_ctx, D_SYNTAX, "afMmvd_base_idx() afMmvd_base_idx=%d\n", afMmvdBaseIdx);
-
+  
 #if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
   unsigned int ricePar = 1;
-  int numCandminus1_step =  (AF_MMVD_MAX_REFINE_NUM >> (ricePar + AFFINE_MMVD_SIZE_SHIFT))  - 1;
+#if JVET_AA0093_ENHANCED_MMVD_EXTENSION
+  int numStepCandMinus1 =  (AF_MMVD_MAX_REFINE_NUM >> (ricePar+AFFINE_MMVD_SIZE_SHIFT)) / AFFINE_BI_DIR  - 1;
+#else
+  int numStepCandMinus1 =  (AF_MMVD_MAX_REFINE_NUM >> (ricePar + AFFINE_MMVD_SIZE_SHIFT))  - 1;
+#endif
+#if JVET_AA0093_ENHANCED_MMVD_EXTENSION
+  int temp = m_BinDecoder.decodeBin(Ctx::AfMmvdOffsetStep(5));
+#else
   int temp = (ricePar == 0) ? 0 : m_BinDecoder.decodeBinsEP(ricePar);
+#endif
   int uiUnaryIdx = 0;
-  for (; uiUnaryIdx < numCandminus1_step; ++uiUnaryIdx)
+  for (; uiUnaryIdx < numStepCandMinus1; ++uiUnaryIdx)
   {
     if (!m_BinDecoder.decodeBin(Ctx::AfMmvdOffsetStep((uiUnaryIdx > LAST_MERGE_MMVD_IDX_CABAC - 1 ? LAST_MERGE_MMVD_IDX_CABAC - 1 : uiUnaryIdx))))
     {
@@ -3361,6 +3387,9 @@ void CABACReader::affine_mmvd_data(PredictionUnit& pu)
   }
   uiUnaryIdx <<= ricePar;
   uiUnaryIdx += temp;
+#if JVET_AA0093_ENHANCED_MMVD_EXTENSION
+  uiUnaryIdx += afMmvdBaseIdx * AF_MMVD_MAX_REFINE_NUM;
+#endif
   pu.afMmvdMergeIdx = uiUnaryIdx;
   pu.afMmvdStep = 0;
   pu.afMmvdDir = 0;
@@ -3368,13 +3397,13 @@ void CABACReader::affine_mmvd_data(PredictionUnit& pu)
   {
     // Decode Step Value
     uint8_t stepOffset = 0;
-    int numCandminus1_step = AF_MMVD_STEP_NUM - 1;
-    if (numCandminus1_step > 0)
+    int numStepCandMinus1 = AF_MMVD_STEP_NUM - 1;
+    if (numStepCandMinus1 > 0)
     {
       if (m_BinDecoder.decodeBin(Ctx::AfMmvdOffsetStep()))
       {
         stepOffset++;
-        for (; stepOffset < numCandminus1_step; stepOffset++)
+        for (; stepOffset < numStepCandMinus1; stepOffset++)
         {
           if (!m_BinDecoder.decodeBinEP())
           {
@@ -3542,8 +3571,13 @@ void CABACReader::merge_data( PredictionUnit& pu )
 #endif
         )
       {
-        RExt__DECODER_DEBUG_BIT_STATISTICS_CREATE_SET_SIZE(STATS__CABAC_BITS__MERGE_FLAG, pu.lumaSize()); 
+        RExt__DECODER_DEBUG_BIT_STATISTICS_CREATE_SET_SIZE(STATS__CABAC_BITS__MERGE_FLAG, pu.lumaSize());
+#if JVET_AA0093_ENHANCED_MMVD_EXTENSION
+        unsigned  ctxId = pu.cu->skip ? 0 : 1;
+        cu.firstPU->mmvdMergeFlag = m_BinDecoder.decodeBin(Ctx::MmvdFlag(ctxId));
+#else
         cu.firstPU->mmvdMergeFlag = m_BinDecoder.decodeBin(Ctx::MmvdFlag(0));
+#endif
         DTRACE(g_trace_ctx, D_SYNTAX, "mmvd_merge_flag() mmvd_merge=%d pos=(%d,%d) size=%dx%d\n", cu.firstPU->mmvdMergeFlag ? 1 : 0, pu.lumaPos().x, pu.lumaPos().y, pu.lumaSize().width, pu.lumaSize().height);
       }
       else
@@ -3873,12 +3907,12 @@ void CABACReader::merge_idx( PredictionUnit& pu )
 void CABACReader::geo_mmvd_idx(PredictionUnit& pu, RefPicList eRefPicList)
 {
   bool extMMVD = pu.cs->picHeader->getGPMMMVDTableFlag();
-  int numCandminus1_step = (extMMVD ? GPM_EXT_MMVD_REFINE_STEP : GPM_MMVD_REFINE_STEP) - 1;
+  int numStepCandMinus1 = (extMMVD ? GPM_EXT_MMVD_REFINE_STEP : GPM_MMVD_REFINE_STEP) - 1;
   int step = 0;
   if (m_BinDecoder.decodeBin(Ctx::GeoMmvdStepMvpIdx()))
   {
     step++;
-    for (; step < numCandminus1_step; step++)
+    for (; step < numStepCandMinus1; step++)
     {
       if (!m_BinDecoder.decodeBinEP())
       {
@@ -4093,18 +4127,41 @@ void CABACReader::mmvd_merge_idx(PredictionUnit& pu)
   RExt__DECODER_DEBUG_BIT_STATISTICS_CREATE_SET_SIZE(STATS__CABAC_BITS__MERGE_INDEX, pu.lumaSize());
   unsigned int uiUnaryIdx = 0;
   int var0 = 0;
+#if JVET_AA0093_ENHANCED_MMVD_EXTENSION
+  int numCandMinus1Base = std::min<int>(MMVD_BASE_MV_NUM, pu.cs->sps->getMaxNumMergeCand()) - 1;
+  if (numCandMinus1Base > 0)
+  {
+    // to support more base candidates
+    if (m_BinDecoder.decodeBin(Ctx::MmvdMergeIdx(0)))
+    {
+      var0++;
+      for (; var0 < numCandMinus1Base; var0++)
+      {
+        if (!m_BinDecoder.decodeBin(Ctx::MmvdMergeIdx(var0)))
+        {
+          break;
+        }
+      }
+    }
+  }
+#else
   if (pu.cs->sps->getMaxNumMergeCand() > 1)
   {
     static_assert(MMVD_BASE_MV_NUM == 2, "");
     var0 = m_BinDecoder.decodeBin(Ctx::MmvdMergeIdx());
   }
+#endif
   DTRACE(g_trace_ctx, D_SYNTAX, "mmvd_merge_idx() base_mvp_idx=%d\n", var0);
   unsigned int ricePar = 1;
-  int numCandminus1_step =  (MMVD_MAX_REFINE_NUM >> (ricePar+MMVD_SIZE_SHIFT))  - 1;
+#if JVET_AA0093_ENHANCED_MMVD_EXTENSION
+  int numStepCandMinus1 =  ((MMVD_MAX_REFINE_NUM >> (ricePar+MMVD_SIZE_SHIFT)))/MMVD_BI_DIR  - 1;
+#else
+  int numStepCandMinus1 =  (MMVD_MAX_REFINE_NUM >> (ricePar+MMVD_SIZE_SHIFT))  - 1;
+#endif
   int temp = 0;
   temp = m_BinDecoder.decodeBinsEP(ricePar);
   
-  for (; uiUnaryIdx < numCandminus1_step; ++uiUnaryIdx)
+  for (; uiUnaryIdx < numStepCandMinus1; ++uiUnaryIdx)
   {
     if (!m_BinDecoder.decodeBin(Ctx::MmvdStepMvpIdx((uiUnaryIdx > LAST_MERGE_MMVD_IDX_CABAC - 1 ? LAST_MERGE_MMVD_IDX_CABAC - 1 : uiUnaryIdx))))
     {
@@ -4128,12 +4185,12 @@ void CABACReader::mmvd_merge_idx(PredictionUnit& pu)
     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 = MMVD_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())
       {
diff --git a/source/Lib/DecoderLib/DecCu.cpp b/source/Lib/DecoderLib/DecCu.cpp
index 462995d2e5835a54c32f52c56fb97cd9a3031403..f00b2d95a114868980d389d1d2e1eb63c9db7388 100644
--- a/source/Lib/DecoderLib/DecCu.cpp
+++ b/source/Lib/DecoderLib/DecCu.cpp
@@ -1646,7 +1646,11 @@ void DecCu::xDeriveCUMV( CodingUnit &cu )
         );
 #if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
         uint32_t mmvdLUT[MMVD_ADD_NUM];
+#if JVET_AA0093_ENHANCED_MMVD_EXTENSION
+        uint16_t mmvdIdx = pu.mmvdMergeIdx;
+#else
         uint8_t mmvdIdx = pu.mmvdMergeIdx;
+#endif
         m_pcInterPred->sortInterMergeMMVDCandidates(pu, mrgCtx, mmvdLUT, mmvdIdx);
         mrgCtx.setMmvdMergeCandiInfo(pu, mmvdIdx, mmvdLUT[mmvdIdx]);
 #else
@@ -1923,13 +1927,22 @@ void DecCu::xDeriveCUMV( CodingUnit &cu )
 #endif
         else
         {
+#if JVET_AA0093_REFINED_MOTION_FOR_ARMC
+          bool applyBDMVR4TM[TM_MRG_MAX_NUM_INIT_CANDS] = { false };
+          bool tmMergeRefinedMotion = false;
+          bool admvrRefinedMotion = false;
+#endif
           if (CU::isIBC(*pu.cu))
           {
 #if JVET_Y0058_IBC_LIST_MODIFY && JVET_W0090_ARMC_TM
             if (pu.cs->sps->getUseAML())
             {
 #if JVET_Z0075_IBC_HMVP_ENLARGE
+#if JVET_AA0093_ENHANCED_MMVD_EXTENSION
+              uint16_t mrgCandIdx = pu.mergeIdx;
+#else
               uint8_t mrgCandIdx = pu.mergeIdx;
+#endif
               PU::getIBCMergeCandidates(pu, mrgCtx);
               m_pcInterPred->adjustIBCMergeCandidates(pu, mrgCtx, 0, IBC_MRG_MAX_NUM_CANDS_MEM);
               pu.mergeIdx = mrgCandIdx;
@@ -1957,8 +1970,16 @@ void DecCu::xDeriveCUMV( CodingUnit &cu )
 
                 uint8_t bmDir = pu.bmDir;
                 MergeCtx tmvpMergeCandCtx;
+#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC
+                if ( tplAvail)
+                {
+#endif
                 PU::getTmvpBMCand(pu, tmvpMergeCandCtx);
+#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC
+                }
+#endif
                 pu.bmDir = 0;
+#if !JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC
                 if (tplAvail)
                 {
                   m_pcInterPred->adjustMergeCandidatesInOneCandidateGroup(pu, tmvpMergeCandCtx, 1, pu.mergeIdx);
@@ -1967,9 +1988,18 @@ void DecCu::xDeriveCUMV( CodingUnit &cu )
                 {
                   tmvpMergeCandCtx.numValidMergeCand = std::min(1, tmvpMergeCandCtx.numValidMergeCand);
                 }
+#endif
                 MergeCtx namvpMergeCandCtx;
+#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC
+                if ( tplAvail)
+                {
+#endif
                 PU::getNonAdjacentBMCand(pu, namvpMergeCandCtx);
+#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC
+                }
+#endif
                 pu.bmDir = 0;
+#if !JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC
                 if (tplAvail)
                 {
                   m_pcInterPred->adjustMergeCandidatesInOneCandidateGroup(pu, namvpMergeCandCtx, 3, pu.mergeIdx);
@@ -1978,22 +2008,144 @@ void DecCu::xDeriveCUMV( CodingUnit &cu )
                 {
                   namvpMergeCandCtx.numValidMergeCand = std::min(3, namvpMergeCandCtx.numValidMergeCand);
                 }
+#else
+                if (!tplAvail)
+                {
+                  PU::getInterBMCandidates(pu, mrgCtx
+#if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM
+                    , -1
+                    , NULL
+                    , NULL
+#endif
+                  );
+              }
+                else
+#endif
                 PU::getInterBMCandidates(pu, mrgCtx, -1, &tmvpMergeCandCtx, &namvpMergeCandCtx);
+#else
+#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC
+                PU::getInterBMCandidates(pu, mrgCtx, -1);
 #else
                 PU::getInterBMCandidates(pu, mrgCtx, pu.cs->sps->getUseAML() && (((mergeIdx / ADAPTIVE_SUB_GROUP_SIZE + 1)*ADAPTIVE_SUB_GROUP_SIZE < pu.cs->sps->getMaxNumBMMergeCand()) || (mergeIdx / ADAPTIVE_SUB_GROUP_SIZE) == 0) ? mergeIdx / ADAPTIVE_SUB_GROUP_SIZE * ADAPTIVE_SUB_GROUP_SIZE + ADAPTIVE_SUB_GROUP_SIZE - 1 : mergeIdx);
+#endif
                 uint8_t bmDir = pu.bmDir;
 #endif
                 pu.bmDir = 0;
 #if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING
+#if JVET_AA0093_REFINED_MOTION_FOR_ARMC
+                admvrRefinedMotion = PU::isArmcRefinedMotionEnabled(pu, 1);
+                admvrRefinedMotion &= tplAvail;
+#endif
                 if (tplAvail)
                 {
+#if JVET_AA0093_REFINED_MOTION_FOR_ARMC
+                  m_pcInterPred->adjustMergeCandidates(pu, mrgCtx, pu.cs->sps->getMaxNumBMMergeCand());
+                  if (mrgCtx.numCandToTestEnc > mrgCtx.numValidMergeCand)
+                  {
+                    mrgCtx.numCandToTestEnc = mrgCtx.numValidMergeCand;
+                  }
+                  if (admvrRefinedMotion)
+                  {
+                    bool subPuRefineList[BM_MRG_MAX_NUM_INIT_CANDS][2] = { false, };
+                    bool subPuRefineListTmp[BM_MRG_MAX_NUM_INIT_CANDS][2] = { false, };
+#if JVET_AA0093_ENHANCED_MMVD_EXTENSION
+                    uint16_t orgMergeIdx = pu.mergeIdx;
+#else
+                    uint8_t orgMergeIdx = pu.mergeIdx;
+#endif
+                    pu.bmDir = 0;
+                    mrgCtx.setMergeInfo( pu, 0 );
+
+                    pu.bmDir = bmDir;
+                    pu.bdmvrRefine = true;
+                    for( uint32_t candIdx = 0; candIdx < mrgCtx.numValidMergeCand; candIdx++ )
+                    {
+                      pu.cu->imv = mrgCtx.useAltHpelIf[candIdx] ? IMV_HPEL : 0;
+                      pu.cu->BcwIdx = mrgCtx.BcwIdx[candIdx];
+                      pu.mv[0] = mrgCtx.mvFieldNeighbours[candIdx << 1].mv;
+                      pu.mv[1] = mrgCtx.mvFieldNeighbours[(candIdx << 1) + 1].mv;
+                      pu.refIdx[0] = mrgCtx.mvFieldNeighbours[candIdx << 1].refIdx;
+                      pu.refIdx[1] = mrgCtx.mvFieldNeighbours[(candIdx << 1) + 1].refIdx;
+
+                      Mv   finalMvDir[2];
+                      applyBDMVR4BM[candIdx] = m_pcInterPred->processBDMVRPU2Dir(pu, subPuRefineList[candIdx], finalMvDir);
+                      subPuRefineListTmp[candIdx][0] = subPuRefineList[candIdx][0];
+                      subPuRefineListTmp[candIdx][1] = subPuRefineList[candIdx][1];
+                      mrgCtx.mvFieldNeighbours[(candIdx << 1) + bmDir - 1].mv = finalMvDir[bmDir - 1];
+                    }
+                    pu.bmDir = 0;
+                    m_pcInterPred->adjustMergeCandidatesInOneCandidateGroup(pu, mrgCtx, bmDir == 2 ? applyBDMVR4BM : NULL, NULL, NULL, mergeIdx + 1, subPuRefineList, subPuRefineListTmp, mergeIdx);
+                    pu.bmDir = bmDir;
+                    pu.mergeIdx = orgMergeIdx;
+                    mrgCtx.setMergeInfo( pu, pu.mergeIdx);
+                    m_pcInterPred->setBdmvrSubPuMvBuf(m_mvBufBDMVR[0], m_mvBufBDMVR[1]);
+                    m_pcInterPred->processBDMVRSubPU(pu, subPuRefineList[mergeIdx][pu.bmDir - 1]);
+                  }
+#if !JVET_AA0093_REFINED_MOTION_FOR_ARMC
+                  else
+#endif
+#endif
 #if JVET_Z0102_NO_ARMC_FOR_ZERO_CAND 
+#if !JVET_AA0093_REFINED_MOTION_FOR_ARMC
                   m_pcInterPred->adjustMergeCandidates(pu, mrgCtx, pu.cs->sps->getMaxNumBMMergeCand());
+#endif
 #else
                   m_pcInterPred->adjustMergeCandidatesInOneCandidateGroup(pu, mrgCtx, mergeIdx + 1, mergeIdx);
 #endif
                 }
 #else
+#if JVET_AA0093_REFINED_MOTION_FOR_ARMC
+                admvrRefinedMotion = PU::isArmcRefinedMotionEnabled(pu, 1);
+                int nWidth = pu.lumaSize().width;
+                int nHeight = pu.lumaSize().height;
+                bool tplAvail = m_pcInterPred->xAMLGetCurBlkTemplate(pu, nWidth, nHeight);
+                admvrRefinedMotion &= tplAvail;
+                if (admvrRefinedMotion)
+                {
+                  if (mrgCtx.numCandToTestEnc > mrgCtx.numValidMergeCand)
+                  {
+                    mrgCtx.numCandToTestEnc = mrgCtx.numValidMergeCand;
+                  }
+                  if (admvrRefinedMotion)
+                  {
+                    bool subPuRefineList[BM_MRG_MAX_NUM_INIT_CANDS][2] = { false, };
+                    bool subPuRefineListTmp[BM_MRG_MAX_NUM_INIT_CANDS][2] = { false, };
+#if JVET_AA0093_ENHANCED_MMVD_EXTENSION
+                    uint16_t orgMergeIdx = pu.mergeIdx;
+#else
+                    uint8_t orgMergeIdx = pu.mergeIdx;
+#endif
+                    pu.bmDir = 0;
+                    mrgCtx.setMergeInfo( pu, 0 );
+
+                    pu.bmDir = bmDir;
+                    pu.bdmvrRefine = true;
+                    for( uint32_t candIdx = 0; candIdx < mrgCtx.numValidMergeCand; candIdx++ )
+                    {
+                      pu.cu->imv = mrgCtx.useAltHpelIf[candIdx] ? IMV_HPEL : 0;
+                      pu.cu->BcwIdx = mrgCtx.BcwIdx[candIdx];
+                      pu.mv[0] = mrgCtx.mvFieldNeighbours[candIdx << 1].mv;
+                      pu.mv[1] = mrgCtx.mvFieldNeighbours[(candIdx << 1) + 1].mv;
+                      pu.refIdx[0] = mrgCtx.mvFieldNeighbours[candIdx << 1].refIdx;
+                      pu.refIdx[1] = mrgCtx.mvFieldNeighbours[(candIdx << 1) + 1].refIdx;
+
+                      Mv   finalMvDir[2];
+                      applyBDMVR4BM[candIdx] = m_pcInterPred->processBDMVRPU2Dir(pu, subPuRefineList[candIdx], finalMvDir);
+                      subPuRefineListTmp[candIdx][0] = subPuRefineList[candIdx][0];
+                      subPuRefineListTmp[candIdx][1] = subPuRefineList[candIdx][1];
+                      mrgCtx.mvFieldNeighbours[(candIdx << 1) + bmDir - 1].mv = finalMvDir[bmDir - 1];
+                    }
+                    pu.bmDir = 0;
+                    m_pcInterPred->adjustMergeCandidatesInOneCandidateGroup(pu, mrgCtx, bmDir == 2 ? applyBDMVR4BM : NULL, NULL, NULL, mergeIdx + 1, subPuRefineList, subPuRefineListTmp, mergeIdx);
+                    pu.bmDir = bmDir;
+                    pu.mergeIdx = orgMergeIdx;
+                    mrgCtx.setMergeInfo( pu, pu.mergeIdx);
+                    m_pcInterPred->setBdmvrSubPuMvBuf(m_mvBufBDMVR[0], m_mvBufBDMVR[1]);
+                    m_pcInterPred->processBDMVRSubPU(pu, subPuRefineList[mergeIdx][pu.bmDir - 1]);
+                  }
+                }
+                else
+#endif
                 m_pcInterPred->adjustInterMergeCandidates(pu, mrgCtx, mergeIdx);
 #endif
                 pu.bmDir = bmDir;
@@ -2013,7 +2165,15 @@ void DecCu::xDeriveCUMV( CodingUnit &cu )
               bool tplAvail = m_pcInterPred->xAMLGetCurBlkTemplate(pu, nWidth, nHeight);
 
               MergeCtx tmvpMergeCandCtx;
+#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC
+              if (tplAvail)
+              {
+#endif
               PU::getTmvpMergeCand(pu, tmvpMergeCandCtx);
+#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC
+              }
+#endif
+#if !JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC
               if (tplAvail)
               {
                 m_pcInterPred->adjustMergeCandidatesInOneCandidateGroup(pu, tmvpMergeCandCtx, 1, pu.mergeIdx);
@@ -2022,8 +2182,17 @@ void DecCu::xDeriveCUMV( CodingUnit &cu )
               {
                 tmvpMergeCandCtx.numValidMergeCand = std::min(1, tmvpMergeCandCtx.numValidMergeCand);
               }
+#endif
               MergeCtx namvpMergeCandCtx;
+#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC
+              if (tplAvail)
+              {
+#endif
               PU::getNonAdjacentMergeCand(pu, namvpMergeCandCtx);
+#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC
+              }
+#endif
+#if !JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC
               if (tplAvail)
               {
                 m_pcInterPred->adjustMergeCandidatesInOneCandidateGroup(pu, namvpMergeCandCtx, 9, pu.mergeIdx);
@@ -2032,11 +2201,103 @@ void DecCu::xDeriveCUMV( CodingUnit &cu )
               {
                 namvpMergeCandCtx.numValidMergeCand = std::min(9, namvpMergeCandCtx.numValidMergeCand);
               }
+#else
+              if (!tplAvail)
+              {
+                PU::getInterMergeCandidates(pu, mrgCtx, 0, -1);
+                mrgCtx.numValidMergeCand = pu.tmMergeFlag ? pu.cs->sps->getMaxNumTMMergeCand() : pu.cs->sps->getMaxNumMergeCand();
+              }
+              else
+#endif
 
               PU::getInterMergeCandidates(pu, mrgCtx, 0, -1, &tmvpMergeCandCtx, &namvpMergeCandCtx);
 
+#if JVET_AA0093_REFINED_MOTION_FOR_ARMC
+              tmMergeRefinedMotion = PU::isArmcRefinedMotionEnabled(pu, 2);
+              tmMergeRefinedMotion &= tplAvail;
+#endif
               if (tplAvail)
               {
+#if JVET_AA0093_REFINED_MOTION_FOR_ARMC
+                if (pu.tmMergeFlag && tmMergeRefinedMotion)
+                {
+#if JVET_Z0102_NO_ARMC_FOR_ZERO_CAND
+                  m_pcInterPred->adjustMergeCandidates(pu, mrgCtx, pu.cs->sps->getMaxNumTMMergeCand());
+#else
+                  m_pcInterPred->adjustMergeCandidatesInOneCandidateGroup(pu, mrgCtx, mrgCtx.numValidMergeCand, pu.mergeIdx);
+#endif
+                  int tmpPuMrgIdx = pu.mergeIdx;
+                  pu.reduceTplSize = true;
+                  if (mrgCtx.numValidMergeCand > pu.cs->sps->getMaxNumTMMergeCand())
+                  {
+                    mrgCtx.numValidMergeCand = pu.cs->sps->getMaxNumTMMergeCand();
+                  }
+
+                  if (mrgCtx.numCandToTestEnc > mrgCtx.numValidMergeCand)
+                  {
+                    mrgCtx.numCandToTestEnc = mrgCtx.numValidMergeCand;
+                  }
+
+                  for (uint32_t ui = mrgCtx.numValidMergeCand; ui < NUM_MERGE_CANDS; ++ui)
+                  {
+                    mrgCtx.BcwIdx[ui] = BCW_DEFAULT;
+#if INTER_LIC
+                    mrgCtx.LICFlags[ui] = false;
+#endif
+                    mrgCtx.interDirNeighbours[ui] = 0;
+                    mrgCtx.mvFieldNeighbours[(ui << 1)].refIdx = NOT_VALID;
+                    mrgCtx.mvFieldNeighbours[(ui << 1) + 1].refIdx = NOT_VALID;
+                    mrgCtx.useAltHpelIf[ui] = false;
+#if MULTI_HYP_PRED
+                    mrgCtx.addHypNeighbours[ui].clear();
+#endif
+                    mrgCtx.candCost[ui] = MAX_UINT64;
+                  }
+
+                  Distortion tempCost[1];
+                  for( uint32_t uiMergeCand = 0; uiMergeCand < mrgCtx.numValidMergeCand; uiMergeCand++ )
+                  {
+                    mrgCtx.setMergeInfo( pu, uiMergeCand );
+#if MULTI_PASS_DMVR
+                    applyBDMVR4TM[uiMergeCand] = PU::checkBDMVRCondition(pu);
+                    if (applyBDMVR4TM[uiMergeCand])
+                    {
+                      m_pcInterPred->setBdmvrSubPuMvBuf(m_mvBufBDMVR[uiMergeCand << 1], m_mvBufBDMVR[(uiMergeCand << 1) + 1]);
+                      pu.bdmvrRefine = true;
+                      applyBDMVR4TM[uiMergeCand] = m_pcInterPred->processBDMVR( pu, 1, tempCost );
+                    }
+                    else
+                    {
+                      m_pcInterPred->deriveTMMv(pu, tempCost);
+                    }
+#else
+                    m_pcInterPred->deriveTMMv( pu );
+#endif
+
+                    mrgCtx.candCost[uiMergeCand] = tempCost[0];
+                    mrgCtx.interDirNeighbours[uiMergeCand] = pu.interDir;
+                    mrgCtx.BcwIdx[uiMergeCand] = pu.cu->BcwIdx;
+                    mrgCtx.mvFieldNeighbours[2 * uiMergeCand].mv = pu.mv[0];
+                    mrgCtx.mvFieldNeighbours[2 * uiMergeCand].refIdx = pu.refIdx[0];
+                    mrgCtx.mvFieldNeighbours[2 * uiMergeCand + 1].mv = pu.mv[1];
+                    mrgCtx.mvFieldNeighbours[2 * uiMergeCand + 1].refIdx = pu.refIdx[1];
+                    if( pu.interDir == 1 )
+                    {
+                      mrgCtx.mvFieldNeighbours[2 * uiMergeCand + 1].mv.setZero();
+                      mrgCtx.mvFieldNeighbours[2 * uiMergeCand + 1].refIdx = NOT_VALID;
+                    }
+                    if( pu.interDir == 2 )
+                    {
+                      mrgCtx.mvFieldNeighbours[2 * uiMergeCand].mv.setZero();
+                      mrgCtx.mvFieldNeighbours[2 * uiMergeCand].refIdx = NOT_VALID;
+                    }
+                  }
+                  pu.reduceTplSize = false;
+                  m_pcInterPred->adjustMergeCandidatesInOneCandidateGroup(pu, mrgCtx, applyBDMVR4TM, NULL, NULL, mrgCtx.numValidMergeCand);
+                  pu.mergeIdx = tmpPuMrgIdx;
+                }
+                else
+#endif
 #if JVET_Z0102_NO_ARMC_FOR_ZERO_CAND
                 m_pcInterPred->adjustMergeCandidates(pu, mrgCtx, 
 #if TM_MRG
@@ -2045,10 +2306,96 @@ void DecCu::xDeriveCUMV( CodingUnit &cu )
                                                      pu.cs->sps->getMaxNumMergeCand());
 #else
                 m_pcInterPred->adjustMergeCandidatesInOneCandidateGroup(pu, mrgCtx, pu.mergeIdx + 1, pu.mergeIdx);
+#endif
+#if JVET_AA0093_REFINED_MOTION_FOR_ARMC
+                if (mrgCtx.numCandToTestEnc > mrgCtx.numValidMergeCand)
+                {
+                  mrgCtx.numCandToTestEnc = mrgCtx.numValidMergeCand;
+                }
 #endif
               }
 #else
               PU::getInterMergeCandidates(pu, mrgCtx, 0, pu.cs->sps->getUseAML() && (((pu.mergeIdx / ADAPTIVE_SUB_GROUP_SIZE + 1)*ADAPTIVE_SUB_GROUP_SIZE < pu.cs->sps->getMaxNumMergeCand()) || (pu.mergeIdx / ADAPTIVE_SUB_GROUP_SIZE) == 0) ? pu.mergeIdx / ADAPTIVE_SUB_GROUP_SIZE * ADAPTIVE_SUB_GROUP_SIZE + ADAPTIVE_SUB_GROUP_SIZE - 1 : pu.mergeIdx);
+#if JVET_AA0093_REFINED_MOTION_FOR_ARMC
+              tmMergeRefinedMotion = PU::isArmcRefinedMotionEnabled(pu, 2);
+              int nWidth = pu.lumaSize().width;
+              int nHeight = pu.lumaSize().height;
+              bool tplAvail = m_pcInterPred->xAMLGetCurBlkTemplate(pu, nWidth, nHeight);
+              tmMergeRefinedMotion &= tplAvail;
+              if (pu.tmMergeFlag && tmMergeRefinedMotion)
+              {
+                int tmpPuMrgIdx = pu.mergeIdx;
+                pu.reduceTplSize = true;
+                if (mrgCtx.numValidMergeCand > pu.cs->sps->getMaxNumTMMergeCand())
+                {
+                  mrgCtx.numValidMergeCand = pu.cs->sps->getMaxNumTMMergeCand();
+                }
+
+                if (mrgCtx.numCandToTestEnc > mrgCtx.numValidMergeCand)
+                {
+                  mrgCtx.numCandToTestEnc = mrgCtx.numValidMergeCand;
+                }
+
+                for (uint32_t ui = mrgCtx.numValidMergeCand; ui < NUM_MERGE_CANDS; ++ui)
+                {
+                  mrgCtx.BcwIdx[ui] = BCW_DEFAULT;
+#if INTER_LIC
+                  mrgCtx.LICFlags[ui] = false;
+#endif
+                  mrgCtx.interDirNeighbours[ui] = 0;
+                  mrgCtx.mvFieldNeighbours[(ui << 1)].refIdx = NOT_VALID;
+                  mrgCtx.mvFieldNeighbours[(ui << 1) + 1].refIdx = NOT_VALID;
+                  mrgCtx.useAltHpelIf[ui] = false;
+#if MULTI_HYP_PRED
+                  mrgCtx.addHypNeighbours[ui].clear();
+#endif
+                  mrgCtx.candCost[ui] = MAX_UINT64;
+                }
+
+                Distortion tempCost[1];
+                for( uint32_t uiMergeCand = 0; uiMergeCand < mrgCtx.numValidMergeCand; uiMergeCand++ )
+                {
+                  mrgCtx.setMergeInfo( pu, uiMergeCand );
+#if MULTI_PASS_DMVR
+                  applyBDMVR4TM[uiMergeCand] = PU::checkBDMVRCondition(pu);
+                  if (applyBDMVR4TM[uiMergeCand])
+                  {
+                    m_pcInterPred->setBdmvrSubPuMvBuf(m_mvBufBDMVR[uiMergeCand << 1], m_mvBufBDMVR[(uiMergeCand << 1) + 1]);
+                    pu.bdmvrRefine = true;
+                    applyBDMVR4TM[uiMergeCand] = m_pcInterPred->processBDMVR( pu, 1, tempCost );
+                  }
+                  else
+                  {
+                    m_pcInterPred->deriveTMMv(pu, tempCost);
+                  }
+#else
+                  m_pcInterPred->deriveTMMv( pu );
+#endif
+
+                  mrgCtx.candCost[uiMergeCand] = tempCost[0];
+                  mrgCtx.interDirNeighbours[uiMergeCand] = pu.interDir;
+                  mrgCtx.BcwIdx[uiMergeCand] = pu.cu->BcwIdx;
+                  mrgCtx.mvFieldNeighbours[2 * uiMergeCand].mv = pu.mv[0];
+                  mrgCtx.mvFieldNeighbours[2 * uiMergeCand].refIdx = pu.refIdx[0];
+                  mrgCtx.mvFieldNeighbours[2 * uiMergeCand + 1].mv = pu.mv[1];
+                  mrgCtx.mvFieldNeighbours[2 * uiMergeCand + 1].refIdx = pu.refIdx[1];
+                  if( pu.interDir == 1 )
+                  {
+                    mrgCtx.mvFieldNeighbours[2 * uiMergeCand + 1].mv.setZero();
+                    mrgCtx.mvFieldNeighbours[2 * uiMergeCand + 1].refIdx = NOT_VALID;
+                  }
+                  if( pu.interDir == 2 )
+                  {
+                    mrgCtx.mvFieldNeighbours[2 * uiMergeCand].mv.setZero();
+                    mrgCtx.mvFieldNeighbours[2 * uiMergeCand].refIdx = NOT_VALID;
+                  }
+                }
+                pu.reduceTplSize = false;
+                m_pcInterPred->adjustMergeCandidatesInOneCandidateGroup(pu, mrgCtx, applyBDMVR4TM, NULL, NULL, mrgCtx.numValidMergeCand);
+                pu.mergeIdx = tmpPuMrgIdx;
+              }
+              else
+#endif
               m_pcInterPred->adjustInterMergeCandidates(pu, mrgCtx, pu.mergeIdx);
 #endif
             }
@@ -2060,6 +2407,25 @@ void DecCu::xDeriveCUMV( CodingUnit &cu )
             PU::getInterMergeCandidates(pu, mrgCtx, 0, pu.mergeIdx);
 #endif
           mrgCtx.setMergeInfo( pu, pu.mergeIdx );
+#if JVET_AA0093_REFINED_MOTION_FOR_ARMC
+          if (pu.tmMergeFlag && tmMergeRefinedMotion)
+          {
+            pu.bdmvrRefine = applyBDMVR4TM[pu.mergeIdx];
+            if (pu.bdmvrRefine)
+            {
+              m_pcInterPred->setBdmvrSubPuMvBuf(m_mvBufBDMVR[0], m_mvBufBDMVR[1]);
+              pu.bdmvrRefine = m_pcInterPred->processBDMVR( pu );
+            }
+            else
+            {
+              m_pcInterPred->deriveTMMv(pu);
+            }
+          }
+          if (pu.bmMergeFlag)
+          {
+            pu.bdmvrRefine = true;
+          }
+#endif
 #if (TM_MRG || (JVET_Z0084_IBC_TM && IBC_TM_MRG)) && !MULTI_PASS_DMVR
           if (pu.tmMergeFlag)
           {
@@ -2074,7 +2440,11 @@ void DecCu::xDeriveCUMV( CodingUnit &cu )
           }
 #endif
 #if MULTI_PASS_DMVR
+#if JVET_AA0093_REFINED_MOTION_FOR_ARMC
+          if (PU::checkBDMVRCondition(pu) && (!pu.tmMergeFlag || (pu.tmMergeFlag && !tmMergeRefinedMotion)) && (!pu.bmMergeFlag || (pu.bmMergeFlag && !admvrRefinedMotion)))
+#else
           if (PU::checkBDMVRCondition(pu))
+#endif
           {
             m_pcInterPred->setBdmvrSubPuMvBuf(m_mvBufBDMVR[0], m_mvBufBDMVR[1]);
             pu.bdmvrRefine = true;
@@ -2110,7 +2480,11 @@ void DecCu::xDeriveCUMV( CodingUnit &cu )
 #if TM_MRG || (JVET_Z0084_IBC_TM && IBC_TM_MRG)
           else
           {
+#if JVET_AA0093_REFINED_MOTION_FOR_ARMC
+            if (pu.tmMergeFlag && !tmMergeRefinedMotion)
+#else
             if (pu.tmMergeFlag)
+#endif
             {
               m_pcInterPred->deriveTMMv(pu);
 #if JVET_Z0084_IBC_TM && IBC_TM_MRG
diff --git a/source/Lib/DecoderLib/DecCu.h b/source/Lib/DecoderLib/DecCu.h
index dfc76bab69e33bbe7df7f7935f13ee268d11ceec..25ddddfe96f2fa0cc076ef405fc35576efa47642 100644
--- a/source/Lib/DecoderLib/DecCu.h
+++ b/source/Lib/DecoderLib/DecCu.h
@@ -100,9 +100,16 @@ private:
   PelStorage        m_ciipBuffer;
 
   MotionInfo        m_SubPuMiBuf[(MAX_CU_SIZE * MAX_CU_SIZE) >> (MIN_CU_LOG2 << 1)];
+#if JVET_AA0093_REFINED_MOTION_FOR_ARMC
+  bool applyBDMVR4BM[BM_MRG_MAX_NUM_INIT_CANDS];
+#endif
 #if MULTI_PASS_DMVR
+#if JVET_AA0093_REFINED_MOTION_FOR_ARMC
+  Mv                m_mvBufBDMVR[MRG_MAX_NUM_CANDS << 1][MAX_NUM_SUBCU_DMVR];
+#else
   Mv                m_mvBufBDMVR[2][MAX_NUM_SUBCU_DMVR];
 #endif
+#endif
 #if JVET_X0083_BM_AMVP_MERGE_MODE
   MvField           m_mvFieldAmListDec[MAX_NUM_AMVP_CANDS_MAX_REF << 1];
 #endif
diff --git a/source/Lib/DecoderLib/VLCReader.cpp b/source/Lib/DecoderLib/VLCReader.cpp
index 708ae2b0607d589c38d9b1712943b3fe19b28c10..b56096083646c2265d658a8039ab02eb89968969 100644
--- a/source/Lib/DecoderLib/VLCReader.cpp
+++ b/source/Lib/DecoderLib/VLCReader.cpp
@@ -2193,6 +2193,48 @@ void HLSyntaxReader::parseSPS(SPS* pcSPS)
 #if JVET_W0090_ARMC_TM
   READ_FLAG( uiCode, "sps_aml_enabled_flag");                        pcSPS->setUseAML ( uiCode != 0 );
 #endif
+#if JVET_AA0093_REFINED_MOTION_FOR_ARMC
+  if (pcSPS->getUseAML())
+  {
+    READ_FLAG( uiCode, "sps_ArmcRefinedMotion_enabled_flag");        pcSPS->setUseArmcRefinedMotion ( uiCode != 0 );
+  }
+#endif
+#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC
+  if (pcSPS->getUseAML())
+  {
+    READ_UVLC(uiCode, "num_Lambda");
+    pcSPS->setNumLambda(uiCode);
+
+    READ_CODE(4, uiCode, "MaxBitsLambda");
+    pcSPS->setMaxbitsLambdaVal(uiCode);
+
+    for (int i = 0; i < pcSPS->getNumLambda(); i++)
+    {
+      int32_t qpOffset = 0;
+      if (i == 0)
+      {
+        READ_SVLC(qpOffset, "QP_Offset");
+        pcSPS->setQPOffsets(i, (int)qpOffset);
+      }
+      else
+      {
+        if (pcSPS->getQPOffsets(i - 1) < 0)
+        {
+          READ_SVLC(qpOffset, "QP_Offset");
+          pcSPS->setQPOffsets(i, (int)qpOffset + pcSPS->getQPOffsets(i - 1));
+        }
+        else
+        {
+          READ_UVLC(uiCode, "QP_Offset");
+          pcSPS->setQPOffsets(i, (int)uiCode + pcSPS->getQPOffsets(i - 1));
+        }
+      }
+
+      READ_CODE(pcSPS->getMaxbitsLambdaVal(), uiCode, "Lambda");
+      pcSPS->setLambdaVal(i, uiCode);
+    }
+  }
+#endif
 #if JVET_Z0054_BLK_REF_PIC_REORDER
   READ_FLAG( uiCode, "sps_arl_enabled_flag");                        pcSPS->setUseARL ( uiCode != 0 );
 #endif
@@ -4899,6 +4941,23 @@ void HLSyntaxReader::parseSliceHeader (Slice* pcSlice, PicHeader* picHeader, Par
     pcSlice->setDefaultClpRng( *sps );
 
   }
+#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC
+  if (!pcSlice->isIntra() && sps->getUseAML())
+  {
+    int index = sps->getQPOffsetsIdx(pcSlice->getSliceQp() - (pps->getPicInitQPMinus26() + 26));
+    bool lambdaCanBePredicted = false;
+    if (index != -1)
+    {
+      lambdaCanBePredicted = true;
+      pcSlice->setCostForARMC(sps->getLambdaVal((int) index));
+    }
+    if (!lambdaCanBePredicted)
+    {
+      READ_CODE(9, uiCode, "lambda");
+      pcSlice->setCostForARMC((uint32_t)uiCode);
+    }
+  }
+#endif
 
 #if MULTI_HYP_PRED
   if (sps->getUseInterMultiHyp() && pcSlice->isInterB())
diff --git a/source/Lib/EncoderLib/CABACWriter.cpp b/source/Lib/EncoderLib/CABACWriter.cpp
index 431aeb02ec198406c54976929fec121fc055fa60..885fd265e41eccdc23ecf507999105491bb4095a 100644
--- a/source/Lib/EncoderLib/CABACWriter.cpp
+++ b/source/Lib/EncoderLib/CABACWriter.cpp
@@ -2922,17 +2922,35 @@ void CABACWriter::affine_mmvd_data(const PredictionUnit& pu)
   // Base affine merge candidate idx
   uint8_t afMmvdBaseIdx = pu.afMmvdBaseIdx;
 
-  int numCandminus1_base = AF_MMVD_BASE_NUM - 1;
-  if (numCandminus1_base > 0)
+  int numCandMinus1Base = AF_MMVD_BASE_NUM - 1;
+#if JVET_AA0093_ENHANCED_MMVD_EXTENSION
+  unsigned ctxId = 0;
+  const CodingStructure *cs = pu.cu->cs;
+  const CodingUnit *cuLeft = cs->getCURestricted( pu.cu->lumaPos().offset( -1, 0 ), *pu.cu, CH_L );
+  ctxId = (cuLeft && cuLeft->affine) ? 1 : 0;
+  const CodingUnit *cuAbove = cs->getCURestricted( pu.cu->lumaPos().offset( 0, -1 ), *pu.cu, CH_L );
+  ctxId += (cuAbove && cuAbove->affine) ? 1 : 0;
+  numCandMinus1Base = (ctxId == 0) ? 0 : ((ctxId == 1) ? 1 : AF_MMVD_BASE_NUM-1);
+#endif
+  if (numCandMinus1Base > 0)
   {
     // to support more base candidates
+#if JVET_AA0093_ENHANCED_MMVD_EXTENSION
+    int ctx2 =  (numCandMinus1Base == 1) ? 1 : 0;
+    m_BinEncoder.encodeBin((afMmvdBaseIdx == 0 ? 0 : 1), Ctx::AfMmvdIdx(ctx2));
+#else
     m_BinEncoder.encodeBin((afMmvdBaseIdx == 0 ? 0 : 1), Ctx::AfMmvdIdx());
-
+#endif
+    
     if (afMmvdBaseIdx > 0)
     {
-      for (unsigned idx = 1; idx < numCandminus1_base; idx++)
+      for (unsigned idx = 1; idx < numCandMinus1Base; idx++)
       {
+#if JVET_AA0093_ENHANCED_MMVD_EXTENSION
+        m_BinEncoder.encodeBin(afMmvdBaseIdx == idx ? 0 : 1, Ctx::AfMmvdIdx(idx + 1));
+#else
         m_BinEncoder.encodeBinEP(afMmvdBaseIdx == idx ? 0 : 1);
+#endif
         if (afMmvdBaseIdx == idx)
         {
           break;
@@ -2943,15 +2961,30 @@ void CABACWriter::affine_mmvd_data(const PredictionUnit& pu)
   DTRACE(g_trace_ctx, D_SYNTAX, "afMmvd_base_idx() afMmvd_base_idx=%d\n", afMmvdBaseIdx);
 
 #if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
+#if JVET_AA0093_ENHANCED_MMVD_EXTENSION
+  uint16_t sym = pu.afMmvdMergeIdx;
+#else
   uint8_t sym = pu.afMmvdMergeIdx;
+#endif
+#if JVET_AA0093_ENHANCED_MMVD_EXTENSION
+  sym -= afMmvdBaseIdx * AF_MMVD_MAX_REFINE_NUM;
+#endif
   unsigned int ricePar = 1;
-  int numCandminus1_step =  ((AF_MMVD_MAX_REFINE_NUM >> ricePar) >> AFFINE_MMVD_SIZE_SHIFT) - 1;
+#if JVET_AA0093_ENHANCED_MMVD_EXTENSION
+  int numStepCandMinus1 =  ((AF_MMVD_MAX_REFINE_NUM >> ricePar) >> AFFINE_MMVD_SIZE_SHIFT) / AFFINE_BI_DIR - 1;
+#else
+  int numStepCandMinus1 =  ((AF_MMVD_MAX_REFINE_NUM >> ricePar) >> AFFINE_MMVD_SIZE_SHIFT) - 1;
+#endif
   if(ricePar > 0)
   {
+#if JVET_AA0093_ENHANCED_MMVD_EXTENSION
+    m_BinEncoder.encodeBin( sym % (1 << ricePar), Ctx::AfMmvdOffsetStep(5));
+#else
     m_BinEncoder.encodeBinsEP( sym % (1 << ricePar), ricePar);
+#endif
   }
   sym >>= ricePar;
-  for (unsigned int uiUnaryIdx = 0; uiUnaryIdx < numCandminus1_step; ++uiUnaryIdx)
+  for (unsigned int uiUnaryIdx = 0; uiUnaryIdx < numStepCandMinus1; ++uiUnaryIdx)
   {
     unsigned int uiSymbol = sym == uiUnaryIdx ? 0 : 1;
     m_BinEncoder.encodeBin(uiSymbol, Ctx::AfMmvdOffsetStep((uiUnaryIdx > LAST_MERGE_MMVD_IDX_CABAC - 1 ? LAST_MERGE_MMVD_IDX_CABAC - 1 : uiUnaryIdx)));
@@ -2964,14 +2997,14 @@ void CABACWriter::affine_mmvd_data(const PredictionUnit& pu)
   {
     // Code Step Value
     uint8_t step = pu.afMmvdStep;
-    int numCandminus1_base = AF_MMVD_STEP_NUM - 1;
-    if (numCandminus1_base > 0)
+    int numCandMinus1Base = AF_MMVD_STEP_NUM - 1;
+    if (numCandMinus1Base > 0)
     {
       m_BinEncoder.encodeBin((step == 0 ? 0 : 1), Ctx::AfMmvdOffsetStep());
 
       if (step > 0)
       {
-        for (unsigned idx = 1; idx < numCandminus1_base; idx++)
+        for (unsigned idx = 1; idx < numCandMinus1Base; idx++)
         {
           m_BinEncoder.encodeBinEP(step == idx ? 0 : 1);
           if (step == idx)
@@ -3123,7 +3156,12 @@ void CABACWriter::merge_data(const PredictionUnit& pu)
 #endif
       )
     {
+#if JVET_AA0093_ENHANCED_MMVD_EXTENSION
+      unsigned  ctxId = pu.cu->skip ? 0 : 1;
+      m_BinEncoder.encodeBin(pu.mmvdMergeFlag, Ctx::MmvdFlag(ctxId));
+#else
       m_BinEncoder.encodeBin(pu.mmvdMergeFlag, Ctx::MmvdFlag(0));
+#endif
       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 (pu.mmvdMergeFlag || pu.cu->mmvdSkip)
@@ -3414,7 +3452,11 @@ void CABACWriter::merge_idx( const PredictionUnit& pu )
     }
     int numCandminus1;
 #if JVET_X0049_ADAPT_DMVR
+#if JVET_AA0093_ENHANCED_MMVD_EXTENSION
+    uint16_t mergeIdx = pu.mergeIdx;
+#else
     uint8_t mergeIdx = pu.mergeIdx;
+#endif
 #endif
     if (pu.cu->predMode == MODE_IBC)
       numCandminus1 = int(pu.cs->sps->getMaxNumIBCMergeCand()) - 1;
@@ -3524,21 +3566,45 @@ void CABACWriter::mmvd_merge_idx(const PredictionUnit& pu)
   int var0;
   var0 = mvpIdx / MMVD_MAX_REFINE_NUM;
   mvpIdx -= var0 * MMVD_MAX_REFINE_NUM;
+#if JVET_AA0093_ENHANCED_MMVD_EXTENSION
+  int numCandMinus1Base = std::min<int>(MMVD_BASE_MV_NUM, pu.cs->sps->getMaxNumMergeCand()) - 1;
+  if (numCandMinus1Base > 0)
+  {
+    // to support more base candidates
+    m_BinEncoder.encodeBin((var0 == 0 ? 0 : 1), Ctx::MmvdMergeIdx(0));
+    if (var0 > 0)
+    {
+      for (unsigned idx = 1; idx < numCandMinus1Base; idx++)
+      {
+        m_BinEncoder.encodeBin((var0 == idx ? 0 : 1), Ctx::MmvdMergeIdx(idx));
+        if (var0 == idx)
+        {
+          break;
+        }
+      }
+    }
+  }
+#else
   if (pu.cs->sps->getMaxNumMergeCand() > 1)
   {
     static_assert(MMVD_BASE_MV_NUM == 2, "");
     assert(var0 < 2);
     m_BinEncoder.encodeBin(var0, Ctx::MmvdMergeIdx());
   }
+#endif
   DTRACE(g_trace_ctx, D_SYNTAX, "mmvd_merge_idx() base_mvp_idx=%d\n", var0);
   unsigned int ricePar = 1;
-  int numCandminus1_step =  ((MMVD_MAX_REFINE_NUM >> ricePar) >> MMVD_SIZE_SHIFT) - 1;
+#if JVET_AA0093_ENHANCED_MMVD_EXTENSION
+  int numStepCandMinus1 =  ((MMVD_MAX_REFINE_NUM >> ricePar) >> MMVD_SIZE_SHIFT)/MMVD_BI_DIR - 1;
+#else
+  int numStepCandMinus1 =  ((MMVD_MAX_REFINE_NUM >> ricePar) >> MMVD_SIZE_SHIFT) - 1;
+#endif
   if(ricePar > 0)
   {
     m_BinEncoder.encodeBinsEP( mvpIdx % (1 << ricePar), ricePar);
   }
   mvpIdx >>= ricePar;
-  for (unsigned int uiUnaryIdx = 0; uiUnaryIdx < numCandminus1_step; ++uiUnaryIdx)
+  for (unsigned int uiUnaryIdx = 0; uiUnaryIdx < numStepCandMinus1; ++uiUnaryIdx)
   {
     unsigned int uiSymbol = mvpIdx == uiUnaryIdx ? 0 : 1;
     m_BinEncoder.encodeBin(uiSymbol, Ctx::MmvdStepMvpIdx((uiUnaryIdx > LAST_MERGE_MMVD_IDX_CABAC - 1 ? LAST_MERGE_MMVD_IDX_CABAC - 1 : uiUnaryIdx)));
@@ -3566,8 +3632,8 @@ void CABACWriter::mmvd_merge_idx(const PredictionUnit& pu)
   }
   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 = MMVD_REFINE_STEP - 1;
+  if (numStepCandMinus1 > 0)
   {
     if (var1 == 0)
     {
@@ -3576,7 +3642,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)
@@ -3668,8 +3734,8 @@ void CABACWriter::geo_mmvd_idx(const PredictionUnit& pu, RefPicList eRefPicList)
   int mmvdStepToIdx[GPM_EXT_MMVD_REFINE_STEP] = { 5, 0, 1, 2, 3, 4, 6, 7, 8 };
   step = mmvdStepToIdx[step];
 
-  int numCandminus1_step = (extMMVD ? GPM_EXT_MMVD_REFINE_STEP : GPM_MMVD_REFINE_STEP) - 1;
-  if (numCandminus1_step > 0)
+  int numStepCandMinus1 = (extMMVD ? GPM_EXT_MMVD_REFINE_STEP : GPM_MMVD_REFINE_STEP) - 1;
+  if (numStepCandMinus1 > 0)
   {
     if (step == 0)
     {
@@ -3678,7 +3744,7 @@ void CABACWriter::geo_mmvd_idx(const PredictionUnit& pu, RefPicList eRefPicList)
     else
     {
       m_BinEncoder.encodeBin(1, Ctx::GeoMmvdStepMvpIdx());
-      for (unsigned idx = 1; idx < numCandminus1_step; idx++)
+      for (unsigned idx = 1; idx < numStepCandMinus1; idx++)
       {
         m_BinEncoder.encodeBinEP(step == idx ? 0 : 1);
         if (step == idx)
@@ -3872,8 +3938,8 @@ uint64_t CABACWriter::geo_mmvdIdx_est(const TempCtx& ctxStart, const int geoMMVD
   int mmvdStepToIdx[GPM_EXT_MMVD_REFINE_STEP] = { 5, 0, 1, 2, 3, 4, 6, 7, 8 };
   step = mmvdStepToIdx[step];
 
-  int numCandminus1_step = (extMMVD ? GPM_EXT_MMVD_REFINE_STEP : GPM_MMVD_REFINE_STEP) - 1;
-  if (numCandminus1_step > 0)
+  int numStepCandMinus1 = (extMMVD ? GPM_EXT_MMVD_REFINE_STEP : GPM_MMVD_REFINE_STEP) - 1;
+  if (numStepCandMinus1 > 0)
   {
     if (step == 0)
     {
@@ -3882,7 +3948,7 @@ uint64_t CABACWriter::geo_mmvdIdx_est(const TempCtx& ctxStart, const int geoMMVD
     else
     {
       m_BinEncoder.encodeBin(1, Ctx::GeoMmvdStepMvpIdx());
-      for (unsigned idx = 1; idx < numCandminus1_step; idx++)
+      for (unsigned idx = 1; idx < numStepCandMinus1; idx++)
       {
         m_BinEncoder.encodeBinEP(step == idx ? 0 : 1);
         if (step == idx)
diff --git a/source/Lib/EncoderLib/EncCfg.h b/source/Lib/EncoderLib/EncCfg.h
index 45b660375a0908b266953192712e14ac7ec62bfd..85726c6e3c62609a12fd825e4dfc0ab22a6c514d 100644
--- a/source/Lib/EncoderLib/EncCfg.h
+++ b/source/Lib/EncoderLib/EncCfg.h
@@ -322,6 +322,11 @@ protected:
   int       m_maxDecPicBuffering[MAX_TLAYER];
   int       m_numReorderPics[MAX_TLAYER];
   int       m_drapPeriod;
+#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC
+  bool      m_isRA;
+  int       m_numQPOffset;
+  int       m_qpOffsetList[MAX_GOP];
+#endif
 
   int       m_iQP;                              //  if (AdaptiveQP == OFF)
   ChromaQpMappingTableParams m_chromaQpMappingTableParams;
@@ -412,6 +417,9 @@ protected:
 #if JVET_W0090_ARMC_TM
   bool      m_AML;
 #endif
+#if JVET_AA0093_REFINED_MOTION_FOR_ARMC
+  bool      m_armcRefinedMotion;
+#endif
 
   bool      m_SMVD;
   bool      m_compositeRefEnabled;        //composite reference
@@ -1172,6 +1180,10 @@ public:
       if (m_RPLList1[i].m_POC != -1) m_numRPLList1++;
     }
   }
+#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC
+  void      setIsRA                         (bool b)         { m_isRA = b; }
+  void      setNumQPOffset                  (int num)        { m_numQPOffset = num; }
+#endif
   const RPLEntry &getRPLEntry(int L01, int idx) const { return (L01 == 0) ? m_RPLList0[idx] : m_RPLList1[idx]; }
   int       getRPLCandidateSize(int L01) const { return  (L01 == 0) ? m_numRPLList0 : m_numRPLList1; }
   void      setEncodedFlag(uint32_t  i, bool value) { m_RPLList0[i].m_isEncoded = value; m_RPLList1[i].m_isEncoded = value; m_GOPList[i].m_isEncoded = value; }
@@ -1329,6 +1341,10 @@ public:
   void      setAML(bool b)                                   { m_AML = b; }
   bool      getAML()                                   const { return m_AML; }
 #endif
+#if JVET_AA0093_REFINED_MOTION_FOR_ARMC
+  void      setArmcRefinedMotion(bool b)                     { m_armcRefinedMotion = b; }
+  bool      getArmcRefinedMotion()                     const { return m_armcRefinedMotion; }
+#endif
 #if ENABLE_OBMC
   void      setUseOBMC                      ( bool n )       { m_OBMC = n; }
   bool      getUseOBMC                      ()         const { return m_OBMC; }
diff --git a/source/Lib/EncoderLib/EncCu.cpp b/source/Lib/EncoderLib/EncCu.cpp
index d0557810bee374097ccdf271ddb5a05c5f3aaee3..8c705f2c8dcaa00ae73807807100b60424029f4a 100644
--- a/source/Lib/EncoderLib/EncCu.cpp
+++ b/source/Lib/EncoderLib/EncCu.cpp
@@ -3144,6 +3144,22 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
 #if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
   uint32_t               mmvdLUT[MMVD_ADD_NUM];
 #endif
+#if JVET_AA0093_ENHANCED_MMVD_EXTENSION
+  uint8_t numBaseAffine = AF_MMVD_BASE_NUM;
+  unsigned ctxId = 0;
+  {
+    CodingUnit cu( tempCS->area );
+    cu.cs       = tempCS;
+    cu.predMode = MODE_INTER;
+    cu.slice    = tempCS->slice;
+    cu.tileIdx  = tempCS->pps->getTileIdx( tempCS->area.lumaPos() );
+    const CodingUnit*  cuLeft  = tempCS->getCURestricted(cu.lumaPos().offset(-1, 0), cu, partitioner.chType);
+    ctxId = (cuLeft && cuLeft->affine) ? 1 : 0;
+    const CodingUnit*  cuAbove = tempCS->getCURestricted(cu.lumaPos().offset( 0,-1), cu, partitioner.chType);
+    ctxId += (cuAbove && cuAbove->affine) ? 1 : 0;
+  }
+  numBaseAffine = (ctxId == 0) ? 1 : ((ctxId == 1) ? 2 : AF_MMVD_BASE_NUM);
+#endif
 #if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
   uint32_t               affMmvdLUT[AF_MMVD_NUM];
 #endif
@@ -3169,6 +3185,9 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
 #if JVET_X0049_ADAPT_DMVR
   MergeCtx bmMrgCtx;
   bool checkBmMrg = false;
+#if JVET_AA0093_REFINED_MOTION_FOR_ARMC
+  MergeCtx bmMrgCtxDir2;
+#endif
 #endif
 
   if (sps.getSbTMVPEnabledFlag())
@@ -3189,12 +3208,21 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
 #if MULTI_PASS_DMVR
   bool applyBDMVR[MRG_MAX_NUM_CANDS] = { false };
 #if TM_MRG && MERGE_ENC_OPT
+#if JVET_AA0093_REFINED_MOTION_FOR_ARMC
+  bool admvrRefinedMotion = false;
+  bool applyBDMVR4TM[TM_MRG_MAX_NUM_INIT_CANDS] = { false };
+#else
   bool applyBDMVR4TM[TM_MRG_MAX_NUM_CANDS] = { false };
 #endif
+#endif
 #if JVET_X0049_ADAPT_DMVR
+#if JVET_AA0093_REFINED_MOTION_FOR_ARMC
+  bool applyBDMVR4BM[(BM_MRG_MAX_NUM_INIT_CANDS << 1)<<1] = { false };
+#else
   bool applyBDMVR4BM[(BM_MRG_MAX_NUM_CANDS << 1)<<1] = { false };
 #endif
 #endif
+#endif
 #if !MULTI_PASS_DMVR
   Mv   refinedMvdL0[MAX_NUM_PARTS_IN_CTU][MRG_MAX_NUM_CANDS];
 #endif
@@ -3217,12 +3245,23 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
 #if TM_MRG || (JVET_Z0084_IBC_TM && IBC_TM_MRG)
     pu.tmMergeFlag = false;
 #endif
+#if JVET_AA0093_REFINED_MOTION_FOR_ARMC && !JVET_Y0134_TMVP_NAMVP_CAND_REORDERING
+    int nWidth = pu.lumaSize().width;
+    int nHeight = pu.lumaSize().height;
+    bool tplAvail = m_pcInterSearch->xAMLGetCurBlkTemplate(pu, nWidth, nHeight);
+#endif
 #if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM
     int nWidth = pu.lumaSize().width;
     int nHeight = pu.lumaSize().height;
     bool tplAvail = m_pcInterSearch->xAMLGetCurBlkTemplate(pu, nWidth, nHeight);
 
     MergeCtx tmvpMergeCandCtx;
+#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC
+    if (sps.getUseAML() && tplAvail)
+    {
+      PU::getTmvpMergeCand(pu, tmvpMergeCandCtx);
+    }
+#else
     if (sps.getUseAML())
     {
       PU::getTmvpMergeCand(pu, tmvpMergeCandCtx);
@@ -3235,7 +3274,14 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
         tmvpMergeCandCtx.numValidMergeCand = std::min(1, tmvpMergeCandCtx.numValidMergeCand);
       }
     }
+#endif
     MergeCtx namvpMergeCandCtx;
+#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC
+    if (sps.getUseAML() && tplAvail)
+    {
+      PU::getNonAdjacentMergeCand(pu, namvpMergeCandCtx);
+    }
+#else    
     if (sps.getUseAML())
     {
       PU::getNonAdjacentMergeCand(pu, namvpMergeCandCtx);
@@ -3249,6 +3295,16 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
       }
     }
 #endif
+#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC
+    if (!tplAvail)
+    {
+      PU::getInterMergeCandidates(pu, mergeCtx, 0, -1);
+      tmMrgCtx.numValidMergeCand = pu.cs->sps->getMaxNumMergeCand();
+    }
+    else
+#endif
+#endif
+
     PU::getInterMergeCandidates(pu, mergeCtx
       , 0
 #if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM
@@ -3269,6 +3325,27 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
 #endif
       }
     }
+#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC
+    if (mergeCtx.numValidMergeCand != pu.cs->sps->getMaxNumMergeCand())
+    {
+      mergeCtx.numValidMergeCand = pu.cs->sps->getMaxNumMergeCand();
+    }
+    for (uint32_t ui = mergeCtx.numValidMergeCand; ui < NUM_MERGE_CANDS; ++ui)
+    {
+      mergeCtx.BcwIdx[ui] = BCW_DEFAULT;
+#if INTER_LIC
+      mergeCtx.LICFlags[ui] = false;
+#endif
+      mergeCtx.interDirNeighbours[ui]                  = 0;
+      mergeCtx.mvFieldNeighbours[(ui << 1)].refIdx     = NOT_VALID;
+      mergeCtx.mvFieldNeighbours[(ui << 1) + 1].refIdx = NOT_VALID;
+      mergeCtx.useAltHpelIf[ui]                        = false;
+#if MULTI_HYP_PRED
+      mergeCtx.addHypNeighbours[ui].clear();
+#endif
+      mergeCtx.candCost[ui] = MAX_UINT64;
+    }
+#endif
     PU::getInterMergeCandidates(pu, mergeCtxtmp, 0);
 #endif
 
@@ -3365,7 +3442,16 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
     {
       cu.firstPU = &pu;
 #if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM
+#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC || JVET_AA0093_REFINED_MOTION_FOR_ARMC
+      pu.tmMergeFlag = true;
+#endif
       MergeCtx tmvpTmMergeCandCtx;
+#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC
+      if (sps.getUseAML() && tplAvail)
+      {
+        PU::getTmvpMergeCand(pu, tmvpTmMergeCandCtx);
+      }
+#else
       if (sps.getUseAML())
       {
         PU::getTmvpMergeCand(pu, tmvpTmMergeCandCtx);
@@ -3378,7 +3464,14 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
           tmvpTmMergeCandCtx.numValidMergeCand = std::min(1, tmvpTmMergeCandCtx.numValidMergeCand);
         }
       }
+#endif
       MergeCtx namvpTmMergeCandCtx;
+#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC
+      if (sps.getUseAML() && tplAvail)
+      {
+        PU::getNonAdjacentMergeCand(pu, namvpTmMergeCandCtx);
+      }
+#else
       if (sps.getUseAML())
       {
         PU::getNonAdjacentMergeCand(pu, namvpTmMergeCandCtx);
@@ -3391,8 +3484,17 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
           namvpTmMergeCandCtx.numValidMergeCand = std::min(9, namvpTmMergeCandCtx.numValidMergeCand);
         }
       }
+#endif
 #endif
       pu.tmMergeFlag = true;
+#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC && JVET_Y0134_TMVP_NAMVP_CAND_REORDERING
+      if (!tplAvail)
+      {
+        PU::getInterMergeCandidates(pu, tmMrgCtx, 0, -1);
+        tmMrgCtx.numValidMergeCand = pu.cs->sps->getMaxNumTMMergeCand();
+      }
+      else
+#endif
       PU::getInterMergeCandidates(pu, tmMrgCtx, 0
 #if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM
         , -1
@@ -3401,6 +3503,10 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
 #endif
       );
 #if JVET_W0090_ARMC_TM
+#if JVET_AA0093_REFINED_MOTION_FOR_ARMC
+      bool tmMergeRefinedMotion = PU::isArmcRefinedMotionEnabled(pu, 2);
+      tmMergeRefinedMotion &= tplAvail;
+#endif
       if (sps.getUseAML())
       {
 #if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING
@@ -3417,9 +3523,41 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
           tmMrgCtx.numValidMergeCand = pu.cs->sps->getMaxNumTMMergeCand();
         }
 #else
+#if JVET_AA0093_REFINED_MOTION_FOR_ARMC
+        if (!tmMergeRefinedMotion)
+#endif
         m_pcInterSearch->adjustInterMergeCandidates(pu, tmMrgCtx);
 #endif
+#if JVET_AA0093_REFINED_MOTION_FOR_ARMC
+        if (tmMrgCtx.numCandToTestEnc > tmMrgCtx.numValidMergeCand)
+        {
+          tmMrgCtx.numCandToTestEnc = tmMrgCtx.numValidMergeCand;
+        }
+        for (uint32_t ui = tmMrgCtx.numValidMergeCand; ui < NUM_MERGE_CANDS; ++ui)
+        {
+          tmMrgCtx.BcwIdx[ui] = BCW_DEFAULT;
+#if INTER_LIC
+          tmMrgCtx.LICFlags[ui] = false;
+#endif
+          tmMrgCtx.interDirNeighbours[ui] = 0;
+          tmMrgCtx.mvFieldNeighbours[(ui << 1)].refIdx = NOT_VALID;
+          tmMrgCtx.mvFieldNeighbours[(ui << 1) + 1].refIdx = NOT_VALID;
+          tmMrgCtx.useAltHpelIf[ui] = false;
+#if MULTI_HYP_PRED
+          tmMrgCtx.addHypNeighbours[ui].clear();
+#endif
+          tmMrgCtx.candCost[ui] = MAX_UINT64;
+        }
+#endif
+      }
+#endif
+
+#if JVET_AA0093_REFINED_MOTION_FOR_ARMC
+      if (tmMergeRefinedMotion)
+      {
+        pu.reduceTplSize = true;
       }
+      Distortion tempCost[1];
 #endif
 
       for( uint32_t uiMergeCand = 0; uiMergeCand < tmMrgCtx.numValidMergeCand; uiMergeCand++ )
@@ -3431,16 +3569,30 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
         {
           pu.bdmvrRefine = true;
           m_pcInterSearch->setBdmvrSubPuMvBuf(m_mvBufBDMVR4TM[uiMergeCand << 1], m_mvBufBDMVR4TM[(uiMergeCand << 1) + 1]);
+#if JVET_AA0093_REFINED_MOTION_FOR_ARMC
+          if (tmMergeRefinedMotion)
+          {
+            applyBDMVR4TM[uiMergeCand] =  m_pcInterSearch->processBDMVR(pu, 1, tempCost);
+          }
+          else
+#endif
           applyBDMVR4TM[uiMergeCand] =  m_pcInterSearch->processBDMVR(pu);
         }
         else
         {
+#if JVET_AA0093_REFINED_MOTION_FOR_ARMC
+          m_pcInterSearch->deriveTMMv(pu, tempCost);
+#else
           m_pcInterSearch->deriveTMMv(pu);
+#endif
         }
 #else
         m_pcInterSearch->deriveTMMv( pu );
 #endif
 
+#if JVET_AA0093_REFINED_MOTION_FOR_ARMC
+        tmMrgCtx.candCost[uiMergeCand] = tempCost[0];
+#endif
         // Store refined motion back to tmMrgCtx
         tmMrgCtx.interDirNeighbours[uiMergeCand] = pu.interDir;
         tmMrgCtx.BcwIdx[uiMergeCand] = pu.cu->BcwIdx;  // Bcw may change, because bi may be reduced to uni by deriveTMMv(pu)
@@ -3455,7 +3607,47 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
           tmMrgCtx.mvFieldNeighbours[2 * uiMergeCand    ].setMvField( Mv(), NOT_VALID );
         }
       }
+#if JVET_AA0093_REFINED_MOTION_FOR_ARMC
+      pu.reduceTplSize = false;
+#endif
 
+#if JVET_AA0093_REFINED_MOTION_FOR_ARMC
+      if (tmMergeRefinedMotion)
+      {
+        m_pcInterSearch->adjustMergeCandidatesInOneCandidateGroup(pu, tmMrgCtx, applyBDMVR4TM, NULL, NULL, pu.cs->sps->getMaxNumTMMergeCand());
+        pu.tmMergeFlag = true;
+        for( uint32_t uiMergeCand = 0; uiMergeCand < tmMrgCtx.numValidMergeCand; uiMergeCand++ )
+        {
+          tmMrgCtx.setMergeInfo( pu, uiMergeCand );
+#if MULTI_PASS_DMVR
+          applyBDMVR4TM[uiMergeCand] = PU::checkBDMVRCondition(pu);
+          if (applyBDMVR4TM[uiMergeCand])
+          {
+            pu.bdmvrRefine = true;
+            m_pcInterSearch->setBdmvrSubPuMvBuf(m_mvBufBDMVR4TM[uiMergeCand << 1], m_mvBufBDMVR4TM[(uiMergeCand << 1) + 1]);
+            applyBDMVR4TM[uiMergeCand] =  m_pcInterSearch->processBDMVR(pu);
+          }
+          else
+          {
+            m_pcInterSearch->deriveTMMv(pu);
+          }
+
+          tmMrgCtx.interDirNeighbours[uiMergeCand] = pu.interDir;
+          tmMrgCtx.BcwIdx[uiMergeCand] = pu.cu->BcwIdx;  // Bcw may change, because bi may be reduced to uni by deriveTMMv(pu)
+          tmMrgCtx.mvFieldNeighbours[2 * uiMergeCand    ].setMvField( pu.mv[0], pu.refIdx[0] );
+          tmMrgCtx.mvFieldNeighbours[2 * uiMergeCand + 1].setMvField( pu.mv[1], pu.refIdx[1] );
+          if( pu.interDir == 1 )
+          {
+            tmMrgCtx.mvFieldNeighbours[2 * uiMergeCand + 1].setMvField( Mv(), NOT_VALID );
+          }
+          if( pu.interDir == 2 )
+          {
+            tmMrgCtx.mvFieldNeighbours[2 * uiMergeCand    ].setMvField( Mv(), NOT_VALID );
+          }
+#endif
+        }
+      }
+#endif
       pu.tmMergeFlag = false;
 #if MULTI_PASS_DMVR
       pu.bdmvrRefine = false;
@@ -3479,7 +3671,11 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
       affineMergeCtxTmp.maxNumMergeCand = slice.getPicHeader()->getMaxNumAffineMergeCand();
 #endif
 #if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
+#if JVET_AA0093_ENHANCED_MMVD_EXTENSION
+      m_pcInterSearch->sortAffineMergeCandidates(pu, affineMergeCtxTmp, affMmvdLUT, (numBaseAffine - 1 ) * AF_MMVD_MAX_REFINE_NUM, true);
+#else
       m_pcInterSearch->sortAffineMergeCandidates(pu, affineMergeCtxTmp, affMmvdLUT);
+#endif
 #endif
       if (sps.getUseAML())
       {
@@ -3532,9 +3728,19 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
       checkBmMrg = PU::isBMMergeFlagCoded(pu);
       if (checkBmMrg)
       {
+#if JVET_AA0093_REFINED_MOTION_FOR_ARMC
+        admvrRefinedMotion = PU::isArmcRefinedMotionEnabled(pu, 1);
+        admvrRefinedMotion &= tplAvail;
+#endif
         pu.bmMergeFlag = true;
 #if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM
         MergeCtx tmvpMergeCandCtx2;
+#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC
+        if (sps.getUseAML() && tplAvail)
+        {
+          PU::getTmvpBMCand(pu, tmvpMergeCandCtx2);
+        }
+#else
         if (sps.getUseAML())
         {
           PU::getTmvpBMCand(pu, tmvpMergeCandCtx2);
@@ -3548,7 +3754,14 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
             tmvpMergeCandCtx2.numValidMergeCand = std::min(1, tmvpMergeCandCtx2.numValidMergeCand);
           }
         }
+#endif
         MergeCtx namvpMergeCandCtx2;
+#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC
+        if (sps.getUseAML() && tplAvail)
+        {
+          PU::getNonAdjacentBMCand(pu, namvpMergeCandCtx2);
+        }
+#else        
         if (sps.getUseAML())
         {
           PU::getNonAdjacentBMCand(pu, namvpMergeCandCtx2);
@@ -3563,6 +3776,21 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
           }
         }
 #endif
+#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC
+        if (!tplAvail)
+        {
+          PU::getInterBMCandidates(pu, bmMrgCtx
+#if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM
+            , -1
+            , NULL
+            , NULL
+#endif
+          );
+        }
+        else
+#endif
+#endif
+
         PU::getInterBMCandidates(pu, bmMrgCtx
 #if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM
           , -1
@@ -3579,6 +3807,12 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
           {
 #if JVET_Z0102_NO_ARMC_FOR_ZERO_CAND 
             m_pcInterSearch->adjustMergeCandidates(pu, bmMrgCtx, pu.cs->sps->getMaxNumBMMergeCand());
+#if JVET_AA0093_REFINED_MOTION_FOR_ARMC
+            if (bmMrgCtx.numCandToTestEnc > bmMrgCtx.numValidMergeCand)
+            {
+              bmMrgCtx.numCandToTestEnc = bmMrgCtx.numValidMergeCand;
+            }
+#endif
 #else
             m_pcInterSearch->adjustMergeCandidatesInOneCandidateGroup(pu, bmMrgCtx, pu.cs->sps->getMaxNumBMMergeCand());
 #endif
@@ -3588,6 +3822,9 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
             bmMrgCtx.numValidMergeCand = pu.cs->sps->getMaxNumBMMergeCand();
           }
 #else
+#if JVET_AA0093_REFINED_MOTION_FOR_ARMC
+          if (!admvrRefinedMotion)
+#endif
           m_pcInterSearch->adjustInterMergeCandidates(pu, bmMrgCtx);
 #endif
         }
@@ -3596,6 +3833,9 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
         {
           checkBmMrg = false;
         }
+#if JVET_AA0093_REFINED_MOTION_FOR_ARMC
+        bmMrgCtxDir2 = bmMrgCtx;
+#endif
 
         pu.bmMergeFlag = false;
         pu.bdmvrRefine = false;
@@ -4210,6 +4450,9 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
         xCheckSATDCostAffineMmvdMerge(tempCS, cu, pu, affineMergeCtxTmp, mrgCtx, acMergeTempBuffer, singleMergeTempBuffer, uiNumMrgSATDCand, RdModeList, candCostList, distParam, ctxStart
 #if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
                                           , affMmvdLUT
+#if JVET_AA0093_ENHANCED_MMVD_EXTENSION
+  , numBaseAffine
+#endif
 #endif
                                       );
 #else
@@ -4225,11 +4468,19 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
 #if JVET_X0049_ADAPT_DMVR
       if (sps.getUseDMVDMode() && checkBmMrg)
       {
+#if JVET_AA0093_REFINED_MOTION_FOR_ARMC
+        xCheckSATDCostBMMerge(tempCS, cu, pu, bmMrgCtx, bmMrgCtxDir2, admvrRefinedMotion, acMergeTempBuffer, singleMergeTempBuffer, uiNumMrgSATDCand, RdModeList, candCostList, distParam, ctxStart
+#if MULTI_PASS_DMVR
+          , applyBDMVR4BM
+#endif
+        );
+#else
         xCheckSATDCostBMMerge(tempCS, cu, pu, bmMrgCtx, acMergeTempBuffer, singleMergeTempBuffer, uiNumMrgSATDCand, RdModeList, candCostList, distParam, ctxStart
 #if MULTI_PASS_DMVR
           , applyBDMVR4BM
 #endif
         );
+#endif
       }
 #endif
       // Try to limit number of candidates using SATD-costs
@@ -4295,7 +4546,11 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
     {
       if (bestIsMMVDSkip)
       {
+#if JVET_AA0093_ENHANCED_MMVD_EXTENSION
+        uiNumMrgSATDCand = mergeCtx.numValidMergeCand + std::min<int>(MMVD_BASE_MV_NUM, mergeCtx.numValidMergeCand) * MMVD_MAX_REFINE_NUM;
+#else
         uiNumMrgSATDCand = mergeCtx.numValidMergeCand + ((mergeCtx.numValidMergeCand > 1) ? MMVD_ADD_NUM : MMVD_ADD_NUM >> 1);
+#endif
       }
       else
       {
@@ -4571,7 +4826,18 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
         pu.regularMergeFlag = true;
         pu.bmMergeFlag = true;
         pu.bmDir = RdModeList[uiMrgHADIdx].bmDir;
+#if JVET_AA0093_REFINED_MOTION_FOR_ARMC
+        if (pu.bmDir == 1)
+        {
+          bmMrgCtx.setMergeInfo(pu, uiMergeCand);
+        }
+        else
+        {
+          bmMrgCtxDir2.setMergeInfo(pu, uiMergeCand);
+        }
+#else
         bmMrgCtx.setMergeInfo(pu, uiMergeCand);
+#endif
         if (applyBDMVR4BM[uiMergeCand])
         {
           isDMVR = true;
@@ -8373,11 +8639,19 @@ void EncCu::xCheckSATDCostMmvdMerge(CodingStructure *&tempCS, CodingUnit &cu, Pr
       && std::min(tempCS->area.lwidth(), tempCS->area.lheight()) >= MULTI_HYP_PRED_RESTRICT_MIN_WH);
 #endif
 
+#if JVET_AA0093_ENHANCED_MMVD_EXTENSION
+  const int tempNum =  (std::min<int>(MMVD_BASE_MV_NUM, mergeCtx.numValidMergeCand) * MMVD_MAX_REFINE_NUM);
+#else
   const int tempNum = (mergeCtx.numValidMergeCand > 1) ? MMVD_ADD_NUM : MMVD_ADD_NUM >> 1;
+#endif
 #if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
   for (int mmvdMergeCandtemp = 0; mmvdMergeCandtemp < tempNum; mmvdMergeCandtemp++)
   {
+#if JVET_AA0093_ENHANCED_MMVD_EXTENSION
+    if(mmvdMergeCandtemp - (mmvdMergeCandtemp/MMVD_MAX_REFINE_NUM )* MMVD_MAX_REFINE_NUM  >= ((MMVD_MAX_REFINE_NUM >> MMVD_SIZE_SHIFT )/MMVD_BI_DIR))
+#else
     if(mmvdMergeCandtemp - (mmvdMergeCandtemp/MMVD_MAX_REFINE_NUM )* MMVD_MAX_REFINE_NUM  >= (MMVD_MAX_REFINE_NUM >> MMVD_SIZE_SHIFT ))
+#endif
     {
       continue;
     }
@@ -8656,6 +8930,9 @@ void EncCu::xCheckSATDCostAffineMmvdMerge(       CodingStructure*& tempCS,
                                            const TempCtx&          ctxStart
 #if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
                                           , uint32_t * affMmvdLUT
+#if JVET_AA0093_ENHANCED_MMVD_EXTENSION
+  , uint8_t numBaseAffine
+#endif
 #endif
 )
 {
@@ -8681,6 +8958,9 @@ void EncCu::xCheckSATDCostAffineMmvdMerge(       CodingStructure*& tempCS,
 
   int baseIdxToMergeIdxOffset = (int)PU::getMergeIdxFromAfMmvdBaseIdx(affineMergeCtx, 0);
   int baseCount               = std::min<int>((int)AF_MMVD_BASE_NUM, affineMergeCtx.numValidMergeCand - baseIdxToMergeIdxOffset);
+#if JVET_AA0093_ENHANCED_MMVD_EXTENSION
+  baseCount = std::min<int>(baseCount, numBaseAffine);
+#endif
   int afMmvdCandCount         = baseCount * AF_MMVD_MAX_REFINE_NUM;
   if (baseCount < 1)
   {
@@ -8698,7 +8978,11 @@ void EncCu::xCheckSATDCostAffineMmvdMerge(       CodingStructure*& tempCS,
   for (uint32_t uiMergeCandTemp = 0; uiMergeCandTemp < afMmvdCandCount; uiMergeCandTemp++)
   {
     uint32_t uiMergeCand = affMmvdLUT[uiMergeCandTemp];
+#if JVET_AA0093_ENHANCED_MMVD_EXTENSION
+    if(uiMergeCandTemp - (uiMergeCandTemp/AF_MMVD_MAX_REFINE_NUM )* AF_MMVD_MAX_REFINE_NUM  >= ((AF_MMVD_MAX_REFINE_NUM >> AFFINE_MMVD_SIZE_SHIFT ) / AFFINE_BI_DIR))
+#else
     if(uiMergeCandTemp - (uiMergeCandTemp/AF_MMVD_MAX_REFINE_NUM )* AF_MMVD_MAX_REFINE_NUM  >= (AF_MMVD_MAX_REFINE_NUM >> AFFINE_MMVD_SIZE_SHIFT))
+#endif
     {
       continue;
     }
@@ -8719,7 +9003,11 @@ void EncCu::xCheckSATDCostAffineMmvdMerge(       CodingStructure*& tempCS,
       pu.afMmvdStep     = (uint8_t)stepIdx;
       pu.mergeIdx       = (uint8_t)(baseIdx + baseIdxToMergeIdxOffset);
 #if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
+#if JVET_AA0093_ENHANCED_MMVD_EXTENSION
+      pu.afMmvdMergeIdx = (uint16_t)uiMergeCandTemp;
+#else
       pu.afMmvdMergeIdx = (uint8_t)uiMergeCandTemp;
+#endif
 #endif
       pu.mergeType      = affineMergeCtx.mergeType         [pu.mergeIdx];
       pu.interDir       = affineMergeCtx.interDirNeighbours[pu.mergeIdx];
@@ -12319,6 +12607,10 @@ void EncCu::xCheckSATDCostBMMerge(CodingStructure*& tempCS,
   CodingUnit&       cu,
   PredictionUnit&   pu,
   MergeCtx&         mrgCtx,
+#if JVET_AA0093_REFINED_MOTION_FOR_ARMC
+  MergeCtx&         mrgCtxDir2,
+  bool              armcRefinedMotion,
+#endif
   PelUnitBuf*       acMergeTempBuffer[MMVD_MRG_MAX_RD_NUM],
   PelUnitBuf*&      singleMergeTempBuffer,
   unsigned&         uiNumMrgSATDCand,
@@ -12356,12 +12648,108 @@ void EncCu::xCheckSATDCostBMMerge(CodingStructure*& tempCS,
   const double sqrtLambdaForFirstPassIntra = m_pcRdCost->getMotionLambda() * FRAC_BITS_SCALE;
   int insertPos = -1;
 #if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM
+#if JVET_AA0093_REFINED_MOTION_FOR_ARMC
+  uint32_t maxNumCand = armcRefinedMotion ? mrgCtx.numValidMergeCand : ((pu.cs->sps->getUseAML()) ? min(mrgCtx.numValidMergeCand, mrgCtx.numCandToTestEnc) : mrgCtx.numCandToTestEnc);
+#else
   const uint32_t maxNumCand = (pu.cs->sps->getUseAML()) ? min(mrgCtx.numValidMergeCand, mrgCtx.numCandToTestEnc) : mrgCtx.numCandToTestEnc;
+#endif
+#else
+#if JVET_AA0093_REFINED_MOTION_FOR_ARMC
+  uint32_t maxNumCand = armcRefinedMotion ? mrgCtx.numValidMergeCand : ((pu.cs->sps->getUseAML()) ? min(mrgCtx.numValidMergeCand, mrgCtx.numCandToTestEnc) : mrgCtx.numCandToTestEnc);
+#else
+#if JVET_AA0093_REFINED_MOTION_FOR_ARMC
+  uint32_t maxNumCand = armcRefinedMotion ? mrgCtx.numValidMergeCand : mrgCtx.numCandToTestEnc;
 #else
   const uint32_t maxNumCand = mrgCtx.numCandToTestEnc;
+#endif
+#endif
 #endif
   bool subPuRefine[2] = { false, false };
   Mv   finalMvDir[2];
+#if JVET_AA0093_REFINED_MOTION_FOR_ARMC
+  bool hasAtLeastOne2nd = false;
+  bool subRefineList[BM_MRG_MAX_NUM_INIT_CANDS << 2][2] = {{false, false}, };
+  bool subRefineListTmp[BM_MRG_MAX_NUM_INIT_CANDS << 2][2] = {{false, false}, };
+  if (armcRefinedMotion)
+  {
+    for (uint32_t candIdx = 0; candIdx < maxNumCand; candIdx++)
+    {
+      pu.cu->imv = mrgCtx.useAltHpelIf[candIdx] ? IMV_HPEL : 0;
+      pu.cu->BcwIdx = mrgCtx.BcwIdx[candIdx];
+      pu.mv[REF_PIC_LIST_0] = mrgCtx.mvFieldNeighbours[(candIdx << 1)].mv;
+      pu.mv[REF_PIC_LIST_1] = mrgCtx.mvFieldNeighbours[(candIdx << 1) + 1].mv;
+      pu.refIdx[REF_PIC_LIST_0] = mrgCtx.mvFieldNeighbours[(candIdx << 1)].refIdx;
+      pu.refIdx[REF_PIC_LIST_1] = mrgCtx.mvFieldNeighbours[(candIdx << 1) + 1].refIdx;
+      bool test2nd = m_pcInterSearch->processBDMVRPU2Dir(pu, subPuRefine, finalMvDir);
+      hasAtLeastOne2nd |= test2nd;
+      for (pu.bmDir = 1; pu.bmDir <= (test2nd ? 2 : 1); pu.bmDir++)
+      {
+        uint8_t curDir = pu.bmDir - 1;
+        uint8_t refDir = 1 - curDir;
+        uint32_t uiMergeCand = candIdx;
+        if (pu.bmDir == 2)
+        {
+          uiMergeCand = candIdx + BM_MRG_MAX_NUM_INIT_CANDS;
+        }
+        applyBDMVR[uiMergeCand] = true;
+        pu.mergeIdx = uiMergeCand;
+        pu.mv[curDir] = finalMvDir[curDir];
+        if (pu.bmDir == 1)
+        {
+          pu.mv[refDir] = mrgCtx.mvFieldNeighbours[(candIdx << 1) + refDir].mv;
+        }
+        else
+        {
+          pu.mv[refDir] = mrgCtxDir2.mvFieldNeighbours[(candIdx << 1) + refDir].mv;
+        }
+        if (pu.bmDir == 1)
+        {
+          mrgCtx.mvFieldNeighbours[2 * candIdx    ].setMvField( pu.mv[0], pu.refIdx[0] );
+          mrgCtx.mvFieldNeighbours[2 * candIdx + 1].setMvField( pu.mv[1], pu.refIdx[1] );
+        }
+        else
+        {
+          mrgCtxDir2.mvFieldNeighbours[2 * candIdx    ].setMvField( pu.mv[0], pu.refIdx[0] );
+          mrgCtxDir2.mvFieldNeighbours[2 * candIdx + 1].setMvField( pu.mv[1], pu.refIdx[1] );
+        }
+        subRefineList[uiMergeCand][curDir] = subPuRefine[curDir];
+        subRefineListTmp[uiMergeCand][curDir] = subRefineList[uiMergeCand][curDir];
+      }
+      if (!test2nd)
+      {
+        uint32_t uiMergeCand = candIdx + BM_MRG_MAX_NUM_INIT_CANDS;
+        applyBDMVR[uiMergeCand] = false;
+        pu.mv[0] = mrgCtxDir2.mvFieldNeighbours[(candIdx << 1)].mv;
+        pu.mv[1] = mrgCtxDir2.mvFieldNeighbours[(candIdx << 1) + 1].mv;
+        subRefineList[uiMergeCand][1] = subPuRefine[1];
+        subRefineListTmp[uiMergeCand][1] = subRefineList[uiMergeCand][1];
+      }
+    }
+    pu.bmDir = 0;
+    m_pcInterSearch->adjustMergeCandidatesInOneCandidateGroup(pu, mrgCtx, NULL, NULL, NULL, mrgCtx.numValidMergeCand, subRefineList, subRefineListTmp);
+    if (hasAtLeastOne2nd)
+    {
+      m_pcInterSearch->adjustMergeCandidatesInOneCandidateGroup(pu, mrgCtxDir2, applyBDMVR + BM_MRG_MAX_NUM_INIT_CANDS, NULL, NULL, mrgCtxDir2.numValidMergeCand, &subRefineList[BM_MRG_MAX_NUM_INIT_CANDS], &subRefineListTmp[BM_MRG_MAX_NUM_INIT_CANDS]);
+      for (uint32_t candIdx = BM_MRG_MAX_NUM_CANDS; candIdx < 2*BM_MRG_MAX_NUM_CANDS; candIdx++)
+      {
+        subRefineList[candIdx][1] = subRefineList[candIdx - BM_MRG_MAX_NUM_CANDS + BM_MRG_MAX_NUM_INIT_CANDS][1];
+      }
+    }
+    for (uint32_t candIdx = BM_MRG_MAX_NUM_CANDS; candIdx < 2*BM_MRG_MAX_NUM_CANDS; candIdx++)
+    {
+      applyBDMVR[candIdx] = applyBDMVR[candIdx - BM_MRG_MAX_NUM_CANDS + BM_MRG_MAX_NUM_INIT_CANDS];
+    }
+    if (mrgCtx.numValidMergeCand > pu.cs->sps->getMaxNumBMMergeCand())
+    {
+      mrgCtx.numValidMergeCand = pu.cs->sps->getMaxNumBMMergeCand();
+    }
+    if (mrgCtxDir2.numValidMergeCand > pu.cs->sps->getMaxNumBMMergeCand())
+    {
+      mrgCtxDir2.numValidMergeCand = pu.cs->sps->getMaxNumBMMergeCand();
+    }
+    maxNumCand = ::min(mrgCtx.numValidMergeCand, (int)pu.cs->sps->getMaxNumBMMergeCand());
+  }
+#endif
   for (uint32_t candIdx = 0; candIdx < maxNumCand; candIdx++)
   {
     pu.cu->imv = mrgCtx.useAltHpelIf[candIdx] ? IMV_HPEL : 0;
@@ -12370,7 +12758,11 @@ void EncCu::xCheckSATDCostBMMerge(CodingStructure*& tempCS,
     pu.mv[REF_PIC_LIST_1] = mrgCtx.mvFieldNeighbours[(candIdx << 1) + 1].mv;
     pu.refIdx[REF_PIC_LIST_0] = mrgCtx.mvFieldNeighbours[(candIdx << 1) + 0].refIdx;
     pu.refIdx[REF_PIC_LIST_1] = mrgCtx.mvFieldNeighbours[(candIdx << 1) + 1].refIdx;
+#if JVET_AA0093_REFINED_MOTION_FOR_ARMC
+    bool test2nd = armcRefinedMotion ? applyBDMVR[candIdx + BM_MRG_MAX_NUM_CANDS] : m_pcInterSearch->processBDMVRPU2Dir(pu, subPuRefine, finalMvDir);
+#else
     bool test2nd = m_pcInterSearch->processBDMVRPU2Dir(pu, subPuRefine, finalMvDir);
+#endif
     for (pu.bmDir = 1; pu.bmDir <= (test2nd ? 2 : 1); pu.bmDir++)
     {
       uint8_t curDir = pu.bmDir - 1;
@@ -12382,13 +12774,52 @@ void EncCu::xCheckSATDCostBMMerge(CodingStructure*& tempCS,
       }
 
       pu.mergeIdx = uiMergeCand;
+#if JVET_AA0093_REFINED_MOTION_FOR_ARMC
+      if (armcRefinedMotion)
+      {
+        if (pu.bmDir == 1)
+        {
+          pu.cu->imv = mrgCtx.useAltHpelIf[candIdx] ? IMV_HPEL : 0;
+          pu.cu->BcwIdx = mrgCtx.BcwIdx[candIdx];
+          pu.mv[0] = mrgCtx.mvFieldNeighbours[(candIdx << 1)].mv;
+          pu.mv[1] = mrgCtx.mvFieldNeighbours[(candIdx << 1) + 1].mv;
+          pu.refIdx[REF_PIC_LIST_0] = mrgCtx.mvFieldNeighbours[(candIdx << 1)].refIdx;
+          pu.refIdx[REF_PIC_LIST_1] = mrgCtx.mvFieldNeighbours[(candIdx << 1) + 1].refIdx;
+        }
+        else
+        {
+          pu.cu->imv = mrgCtxDir2.useAltHpelIf[candIdx] ? IMV_HPEL : 0;
+          pu.cu->BcwIdx = mrgCtxDir2.BcwIdx[candIdx];
+          pu.mv[0] = mrgCtxDir2.mvFieldNeighbours[(candIdx << 1)].mv;
+          pu.mv[1] = mrgCtxDir2.mvFieldNeighbours[(candIdx << 1) + 1].mv;
+          pu.refIdx[REF_PIC_LIST_0] = mrgCtxDir2.mvFieldNeighbours[(candIdx << 1)].refIdx;
+          pu.refIdx[REF_PIC_LIST_1] = mrgCtxDir2.mvFieldNeighbours[(candIdx << 1) + 1].refIdx;
+        }
+      }
+      else
+      {
+#endif
       pu.mv[curDir] = finalMvDir[curDir];
       pu.mv[refDir] = mrgCtx.mvFieldNeighbours[(candIdx << 1) + refDir].mv;
       applyBDMVR[uiMergeCand] = true;
+#if JVET_AA0093_REFINED_MOTION_FOR_ARMC
+      }
+#endif
       pu.bdmvrRefine = true;
       m_pcInterSearch->setBdmvrSubPuMvBuf(m_mvBufBDMVR4BM[uiMergeCand << 1], m_mvBufBDMVR4BM[(uiMergeCand << 1) + 1]);
       
+#if JVET_AA0093_REFINED_MOTION_FOR_ARMC
+      if (armcRefinedMotion)
+      {
+        m_pcInterSearch->processBDMVRSubPU(pu, subRefineList[uiMergeCand][curDir]);
+      }
+      else
+      {
+#endif
       m_pcInterSearch->processBDMVRSubPU(pu, subPuRefine[curDir]);
+#if JVET_AA0093_REFINED_MOTION_FOR_ARMC
+      }
+#endif
 
       m_pcInterSearch->motionCompensation(pu, *singleMergeTempBuffer);
 #if MULTI_PASS_DMVR 
diff --git a/source/Lib/EncoderLib/EncCu.h b/source/Lib/EncoderLib/EncCu.h
index cf62ce5eacb265e5a0bab4ec7588f130c02776a3..8274b2870df27fb0ca42b15c4e169045753e1bd7 100644
--- a/source/Lib/EncoderLib/EncCu.h
+++ b/source/Lib/EncoderLib/EncCu.h
@@ -331,15 +331,24 @@ private:
 #if MULTI_PASS_DMVR
   Mv                    m_mvBufBDMVR[(MRG_MAX_NUM_CANDS << 1)][MAX_NUM_SUBCU_DMVR];
 #if TM_MRG
+#if JVET_AA0093_REFINED_MOTION_FOR_ARMC
+  Mv                    m_mvBufBDMVR4TM[(TM_MRG_MAX_NUM_INIT_CANDS << 1)][MAX_NUM_SUBCU_DMVR];
+#else
   Mv                    m_mvBufBDMVR4TM[(TM_MRG_MAX_NUM_CANDS << 1)][MAX_NUM_SUBCU_DMVR];
+#endif
 #endif
   Mv                    m_mvBufEncBDOF[MRG_MAX_NUM_CANDS][BDOF_SUBPU_MAX_NUM];
   Mv                    m_mvBufEncBDOF4TM[MRG_MAX_NUM_CANDS][BDOF_SUBPU_MAX_NUM];
 #if JVET_X0049_ADAPT_DMVR
+#if JVET_AA0093_REFINED_MOTION_FOR_ARMC
+  Mv                    m_mvBufBDMVR4BM[(BM_MRG_MAX_NUM_INIT_CANDS << 1)<<1][MAX_NUM_SUBCU_DMVR];
+  Mv                    m_mvBufEncBDOF4BM[BM_MRG_MAX_NUM_INIT_CANDS<<1][BDOF_SUBPU_MAX_NUM];
+#else
   Mv                    m_mvBufBDMVR4BM[(BM_MRG_MAX_NUM_CANDS << 1)<<1][MAX_NUM_SUBCU_DMVR];
   Mv                    m_mvBufEncBDOF4BM[BM_MRG_MAX_NUM_CANDS<<1][BDOF_SUBPU_MAX_NUM];
 #endif
 #endif
+#endif
 #if JVET_X0083_BM_AMVP_MERGE_MODE
   Mv                    m_mvBufEncAmBDMVR[2][MAX_NUM_SUBCU_DMVR];
   MvField               m_mvFieldAmListEnc[MAX_NUM_AMVP_CANDS_MAX_REF << 1];
@@ -448,6 +457,15 @@ protected:
 #endif
                               );
 #if JVET_X0049_ADAPT_DMVR
+#if JVET_AA0093_REFINED_MOTION_FOR_ARMC
+  void xCheckSATDCostBMMerge
+                              ( CodingStructure *&tempCS, CodingUnit &cu, PredictionUnit &pu, MergeCtx& mrgCtx, MergeCtx& mrgCtxDir2, bool armcRefinedMotion, PelUnitBuf *acMergeTempBuffer[MMVD_MRG_MAX_RD_NUM], PelUnitBuf *&singleMergeTempBuffer
+                                , unsigned& uiNumMrgSATDCand, static_vector<ModeInfo, MRG_MAX_NUM_CANDS + MMVD_ADD_NUM>  &RdModeList, static_vector<double, MRG_MAX_NUM_CANDS + MMVD_ADD_NUM> &candCostList, DistParam distParam, const TempCtx &ctxStart
+#if MULTI_PASS_DMVR
+                                , bool* applyBDMVR
+#endif
+                              );
+#else
   void xCheckSATDCostBMMerge
                               ( CodingStructure *&tempCS, CodingUnit &cu, PredictionUnit &pu, MergeCtx& mrgCtx, PelUnitBuf *acMergeTempBuffer[MMVD_MRG_MAX_RD_NUM], PelUnitBuf *&singleMergeTempBuffer
                                 , unsigned& uiNumMrgSATDCand, static_vector<ModeInfo, MRG_MAX_NUM_CANDS + MMVD_ADD_NUM>  &RdModeList, static_vector<double, MRG_MAX_NUM_CANDS + MMVD_ADD_NUM> &candCostList, DistParam distParam, const TempCtx &ctxStart
@@ -455,6 +473,7 @@ protected:
                                 , bool* applyBDMVR
 #endif
                               );
+#endif
 #endif
   void xCheckSATDCostCiipMerge 
                               ( CodingStructure *&tempCS, CodingUnit &cu, PredictionUnit &pu, MergeCtx mergeCtx, PelUnitBuf *acMergeTempBuffer[MMVD_MRG_MAX_RD_NUM], PelUnitBuf *&singleMergeTempBuffer, PelUnitBuf  acMergeTmpBuffer[MRG_MAX_NUM_CANDS]
@@ -480,6 +499,9 @@ protected:
                                 , unsigned& uiNumMrgSATDCand, static_vector<ModeInfo, MRG_MAX_NUM_CANDS + MMVD_ADD_NUM>  &RdModeList, static_vector<double, MRG_MAX_NUM_CANDS + MMVD_ADD_NUM> &candCostList, DistParam distParam, const TempCtx &ctxStart
 #if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
                                           , uint32_t * affMmvdLUT
+#if JVET_AA0093_ENHANCED_MMVD_EXTENSION
+  , uint8_t numBaseAffine = AF_MMVD_BASE_NUM
+#endif
 #endif
                                );
 #endif
diff --git a/source/Lib/EncoderLib/EncGOP.cpp b/source/Lib/EncoderLib/EncGOP.cpp
index eb85f040fe723530ccd35cb74446132ec8a0183e..a30e7923647fd8c474dfcddc94e599939587698d 100644
--- a/source/Lib/EncoderLib/EncGOP.cpp
+++ b/source/Lib/EncoderLib/EncGOP.cpp
@@ -2580,6 +2580,53 @@ void EncGOP::compressGOP(int iPOCLast, int iNumPicRcvd, PicList &rcListPic, std:
     {
       pcSlice->setCheckLDC(true);
     }
+#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC
+    if (!pcSlice->isIntra() && pcSlice->getSPS()->getUseAML())
+    {
+      int index = pcSlice->getSPS()->getQPOffsetsIdx(pcSlice->getSliceQp() - (pcSlice->getPPS()->getPicInitQPMinus26() + 26));
+      if (index != -1)
+      {
+        const SPS* sps = pcSlice->getSPS();
+        pcSlice->setCostForARMC(sps->getLambdaVal(index));
+      }
+      else
+      {
+        pcSlice->setCostForARMC((uint32_t) LAMBDA_DEC_SIDE[min(max(pcSlice->getSliceQp(), 0), MAX_QP)]);
+      }
+
+      if (pcSlice->getCheckLDC())
+      {
+        int iCurrPOC = pcSlice->getPOC();
+        int iRefIdx  = 0;
+        int mindist  = MAX_INT;
+        for (iRefIdx = 0; iRefIdx < pcSlice->getNumRefIdx(REF_PIC_LIST_0); iRefIdx++)
+        {
+          if (abs(pcSlice->getRefPic(REF_PIC_LIST_0, iRefIdx)->getPOC() - iCurrPOC) < mindist)
+          {
+            mindist = abs(pcSlice->getRefPic(REF_PIC_LIST_0, iRefIdx)->getPOC() - iCurrPOC);
+          }
+        }
+        if (pcSlice->isInterB())
+        {
+          for (iRefIdx = 0; iRefIdx < pcSlice->getNumRefIdx(REF_PIC_LIST_1); iRefIdx++)
+          {
+            if (abs(pcSlice->getRefPic(REF_PIC_LIST_1, iRefIdx)->getPOC() - iCurrPOC) < mindist)
+            {
+              mindist = abs(pcSlice->getRefPic(REF_PIC_LIST_1, iRefIdx)->getPOC() - iCurrPOC);
+            }
+          }
+        }
+        if (mindist != 1 )
+        {
+          pcSlice->setCostForARMC((uint32_t) LAMBDA_DEC_SIDE[min(max(pcSlice->getSliceQp() - 4, 0), MAX_QP)]);
+        }
+      }
+      else
+      {
+        pcSlice->setCostForARMC((uint32_t) LAMBDA_DEC_SIDE[min(max(pcSlice->getSliceQp() - 4, 0), MAX_QP)]);
+      }
+    }
+#endif
 
 
     //-------------------------------------------------------------
diff --git a/source/Lib/EncoderLib/EncLib.cpp b/source/Lib/EncoderLib/EncLib.cpp
index 46d0c7ebc4098ff7c07212b15dfa217a1b83d1c7..35376a2d94409f445d531c01e082a5c50e543d87 100644
--- a/source/Lib/EncoderLib/EncLib.cpp
+++ b/source/Lib/EncoderLib/EncLib.cpp
@@ -356,6 +356,29 @@ void EncLib::init( bool isFieldCoding, AUWriterIf* auWriterIf )
   xInitPPS(pps0, sps0);
   // initialize APS
   xInitRPL(sps0, isFieldCoding);
+#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC
+  if (sps0.getUseAML())
+  {
+    sps0.setNumLambda(m_numQPOffset);
+    int maxBits = 0;
+    for (int idx = 0; idx < m_numQPOffset; idx++)
+    {
+      sps0.setQPOffsets(idx, m_qpOffsetList[idx]);
+      sps0.setLambdaVal(idx, (uint32_t)LAMBDA_DEC_SIDE[26 + pps0.getPicInitQPMinus26() + m_qpOffsetList[idx] - 4 * ((int)m_isRA)]);
+      uint32_t lambda = (uint32_t)LAMBDA_DEC_SIDE[26 + pps0.getPicInitQPMinus26() + m_qpOffsetList[idx] - 4 * ((int)m_isRA)];
+      for (int shift = 0; shift < 16; shift++)
+        if (lambda >> shift == 0)
+        {
+          if (shift > maxBits)
+          {
+            maxBits = shift;
+          }
+          break;
+        }
+    }
+    sps0.setMaxbitsLambdaVal(maxBits);
+  }
+#endif
 
   if (m_resChangeInClvsEnabled)
   {
@@ -943,6 +966,13 @@ bool EncLib::encode( const InputColourSpaceConversion snrCSC, std::list<PelUnitB
   return false;
 }
 
+#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC
+void EncLib::setQPOffsetList(const int QPOffset[MAX_GOP])
+{
+  std::memcpy(m_qpOffsetList, QPOffset,(MAX_GOP) * sizeof(int));
+}
+#endif
+
 /**------------------------------------------------
  Separate interlaced frame into two fields
  -------------------------------------------------**/
@@ -1504,6 +1534,9 @@ void EncLib::xInitSPS( SPS& sps )
   sps.setBDOFEnabledFlag                    ( m_BIO );
 #if JVET_W0090_ARMC_TM
   sps.setUseAML                             ( m_AML );
+#endif
+#if JVET_AA0093_REFINED_MOTION_FOR_ARMC
+  sps.setUseArmcRefinedMotion               ( m_armcRefinedMotion );
 #endif
   sps.setMaxNumMergeCand(getMaxNumMergeCand());
 #if JVET_X0049_ADAPT_DMVR
diff --git a/source/Lib/EncoderLib/EncLib.h b/source/Lib/EncoderLib/EncLib.h
index a5b40bcb180559602e7455ff17b8eaa31c8d33f9..f02f94a83936c8e7a92c7e9e12ad39ccb71f6f4f 100644
--- a/source/Lib/EncoderLib/EncLib.h
+++ b/source/Lib/EncoderLib/EncLib.h
@@ -320,6 +320,10 @@ public:
 #if DUMP_BEFORE_INLOOP
   std::string m_reconFileName;
 #endif
+
+#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC
+  void setQPOffsetList(const int QPOffset[MAX_GOP]);
+#endif
 };
 
 //! \}
diff --git a/source/Lib/EncoderLib/VLCWriter.cpp b/source/Lib/EncoderLib/VLCWriter.cpp
index 6cf009d29f4e0bd2a1972c53b9401ed99d4c4c71..fbc566e219d988dea2b87b5f0501a5ff0bba978c 100644
--- a/source/Lib/EncoderLib/VLCWriter.cpp
+++ b/source/Lib/EncoderLib/VLCWriter.cpp
@@ -1334,6 +1334,41 @@ void HLSWriter::codeSPS( const SPS* pcSPS )
 #if JVET_W0090_ARMC_TM
   WRITE_FLAG( pcSPS->getUseAML() ? 1 : 0,                                             "sps_aml_enabled_flag" );
 #endif
+#if JVET_AA0093_REFINED_MOTION_FOR_ARMC
+  if (pcSPS->getUseAML())
+  {
+    WRITE_FLAG( pcSPS->getUseArmcRefinedMotion() ? 1 : 0,                             "sps_ArmcRefinedMotion_enabled_flag" );
+  }
+#endif
+
+#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC
+  if (pcSPS->getUseAML())
+  {
+    WRITE_UVLC(pcSPS->getNumLambda(), "num_Lambda");
+    WRITE_CODE(pcSPS->getMaxbitsLambdaVal(), 4, "MaxBitsLambda");
+
+    for (int i = 0; i < pcSPS->getNumLambda(); i++)
+    {
+      int code = pcSPS->getQPOffsets(i);
+      if (i == 0)
+      {
+        WRITE_SVLC(code, "QP_Offset");
+      }
+      else
+      {
+        if (pcSPS->getQPOffsets(i - 1) < 0)
+        {
+          WRITE_SVLC((code - pcSPS->getQPOffsets(i - 1)), "QP_Offset");
+        }
+        else
+        {
+          WRITE_UVLC((code - pcSPS->getQPOffsets(i - 1)), "QP_Offset");
+        }
+      }
+      WRITE_CODE(pcSPS->getLambdaVal(i), pcSPS->getMaxbitsLambdaVal(), "Lambda");
+      }
+    }
+#endif
 #if JVET_Z0054_BLK_REF_PIC_REORDER
   WRITE_FLAG( pcSPS->getUseARL() ? 1 : 0,                                             "sps_arl_enabled_flag" );
 #endif
@@ -2995,6 +3030,25 @@ void HLSWriter::codeSliceHeader         ( Slice* pcSlice )
   {
     WRITE_FLAG(pcSlice->getTSResidualCodingDisabledFlag() ? 1 : 0, "slice_ts_residual_coding_disabled_flag");
   }
+#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC
+  if ( !pcSlice->isIntra() && pcSlice->getSPS()->getUseAML())
+  {
+    // Prediction of the Lambda value
+    int index = pcSlice->getSPS()->getQPOffsetsIdx(pcSlice->getSliceQp() - (pcSlice->getPPS()->getPicInitQPMinus26() + 26));
+    bool lambdaCanBePredicted = false;
+    if (index !=-1)
+    {
+      if(pcSlice->getSPS()->getLambdaVal(index) == pcSlice->getCostForARMC())
+      {
+        lambdaCanBePredicted = true;
+      }
+    }
+    if (!lambdaCanBePredicted)
+    {
+      WRITE_CODE(pcSlice->getCostForARMC(), 9, "Lambda");
+    }
+  }
+#endif
 
 #if MULTI_HYP_PRED
   if (pcSlice->getSPS()->getUseInterMultiHyp() && pcSlice->isInterB())