From fcf374da2be945b5a4c2e5f034ba77f515ebfdb0 Mon Sep 17 00:00:00 2001
From: Yang Wang <wangyang.cs@bytedance.com>
Date: Thu, 8 Feb 2024 17:08:26 +0000
Subject: [PATCH] JVET-AG0276: LIC improvements (Test 2.6j)

---
 source/App/EncoderApp/EncApp.cpp          |   19 +
 source/App/EncoderApp/EncAppCfg.cpp       |   48 +
 source/App/EncoderApp/EncAppCfg.h         |   19 +
 source/Lib/CommonLib/Buffer.cpp           |   13 +
 source/Lib/CommonLib/Common.h             |   31 +
 source/Lib/CommonLib/CommonDef.h          |   13 +
 source/Lib/CommonLib/ContextModelling.cpp |  503 ++-
 source/Lib/CommonLib/ContextModelling.h   |   49 +
 source/Lib/CommonLib/Contexts.h           |    8 +
 source/Lib/CommonLib/Contexts_ecm12.inl   |   94 +
 source/Lib/CommonLib/InterPrediction.cpp  | 4969 ++++++++++++++++-----
 source/Lib/CommonLib/InterPrediction.h    |  163 +
 source/Lib/CommonLib/Rom.cpp              |    3 +
 source/Lib/CommonLib/Rom.h                |    3 +
 source/Lib/CommonLib/Slice.cpp            |   24 +
 source/Lib/CommonLib/Slice.h              |   64 +-
 source/Lib/CommonLib/TypeDef.h            |    4 +
 source/Lib/CommonLib/Unit.cpp             |   41 +
 source/Lib/CommonLib/Unit.h               |   18 +
 source/Lib/CommonLib/UnitTools.cpp        | 2087 ++++++++-
 source/Lib/CommonLib/UnitTools.h          |   52 +-
 source/Lib/DecoderLib/CABACReader.cpp     |   54 +
 source/Lib/DecoderLib/DecCu.cpp           |  375 +-
 source/Lib/DecoderLib/VLCReader.cpp       |   65 +
 source/Lib/EncoderLib/CABACWriter.cpp     |   52 +
 source/Lib/EncoderLib/EncCfg.h            |   51 +
 source/Lib/EncoderLib/EncCu.cpp           | 1794 +++++++-
 source/Lib/EncoderLib/EncCu.h             |   45 +
 source/Lib/EncoderLib/EncLib.cpp          |   58 +
 source/Lib/EncoderLib/EncModeCtrl.cpp     |  100 +
 source/Lib/EncoderLib/InterSearch.cpp     |   35 +
 source/Lib/EncoderLib/InterSearch.h       |   31 +
 source/Lib/EncoderLib/VLCWriter.cpp       |   54 +
 33 files changed, 9623 insertions(+), 1316 deletions(-)

diff --git a/source/App/EncoderApp/EncApp.cpp b/source/App/EncoderApp/EncApp.cpp
index dc9ed416f..f8fbb124d 100644
--- a/source/App/EncoderApp/EncApp.cpp
+++ b/source/App/EncoderApp/EncApp.cpp
@@ -811,6 +811,9 @@ void EncApp::xInitLibCfg()
   m_cEncLib.setAffineType                                        ( m_AffineType );
 #if JVET_AF0163_TM_SUBBLOCK_REFINEMENT
   m_cEncLib.setUseAffineTM                                       ( m_useAffineTM );
+#if JVET_AG0276_NLIC
+  m_cEncLib.setUseAffAltLMTM                                     ( m_useAffAltLMTM );
+#endif
 #endif
 #if AFFINE_MMVD
   m_cEncLib.setAffineMmvdMode                                    ( m_AffineMmvdMode );
@@ -852,6 +855,15 @@ void EncApp::xInitLibCfg()
   m_cEncLib.setBIO                                               (m_BIO);
 #if JVET_W0090_ARMC_TM
   m_cEncLib.setAML                                               ( m_AML );
+#if JVET_AG0276_NLIC
+  m_cEncLib.setAltLM                                             ( m_altLM );
+  m_cEncLib.setAffAltLM                                          ( m_affAltLM );
+#endif
+#endif
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+  m_cEncLib.setMergeOppositeLic                                  ( m_mergeOppositeLic );
+  m_cEncLib.setMergeTMOppositeLic                                ( m_mergeTMOppositeLic );
+  m_cEncLib.setMergeAffOppositeLic                               ( m_mergeAffOppositeLic );
 #endif
 #if JVET_AA0093_REFINED_MOTION_FOR_ARMC
   m_cEncLib.setArmcRefinedMotion                                 ( m_iQP < 25 ? false : m_armcRefinedMotion );
@@ -1132,6 +1144,10 @@ void EncApp::xInitLibCfg()
   }
 
   m_cEncLib.setMaxNumMergeCand                                   ( m_maxNumMergeCand );
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+  m_cEncLib.setMaxNumOppositeLicMergeCand                        ( m_maxNumOppositeLicMergeCand );
+  m_cEncLib.setMaxNumAffineOppositeLicMergeCand                  ( m_maxNumAffineOppositeLicMergeCand);
+#endif
 #if JVET_X0049_ADAPT_DMVR
   m_cEncLib.setMaxNumBMMergeCand                                 ( m_maxNumBMMergeCand );
 #endif
@@ -1489,6 +1505,9 @@ void EncApp::xInitLibCfg()
       m_cEncLib.setFastLicAffine(true);
     }
   }
+#if JVET_AG0276_LIC_SLOPE_ADJUST
+  m_cEncLib.setUseLicSlopeAdjust                                 ( m_lic ? m_licSlopeAdjust : false );
+#endif
 #endif
 #endif
 #if DUMP_BEFORE_INLOOP
diff --git a/source/App/EncoderApp/EncAppCfg.cpp b/source/App/EncoderApp/EncAppCfg.cpp
index fd1e68618..93ca7833e 100644
--- a/source/App/EncoderApp/EncAppCfg.cpp
+++ b/source/App/EncoderApp/EncAppCfg.cpp
@@ -1036,6 +1036,9 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] )
   ("AffineType",                                      m_AffineType,                                      true,  "Enable affine type prediction (0:off, 1:on)  [default: on]" )
 #if JVET_AF0163_TM_SUBBLOCK_REFINEMENT
   ("AffineTM",                                        m_useAffineTM,                                     true, "Enable TM-based subblock motion refinement (0:off, 1:on)  [default: on]")
+#if JVET_AG0276_NLIC
+  ("AffAltLMTM",                                      m_useAffAltLMTM,                                   true, "Enable TM-based subblock motion refinement for affine AltLM")
+#endif
 #endif
 #if AFFINE_MMVD
   ("AffineMMVD",                                      m_AffineMmvdMode,                                  true, "Affine MMVD mode (0:off, 1:on)  [default: on]" )
@@ -1077,6 +1080,15 @@ 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")
+#if JVET_AG0276_NLIC
+  ("AltLM",                                           m_altLM,                                           true, "Enable altLM")
+  ("AffAltLM",                                        m_affAltLM,                                        true, "Enable affine altLM")
+#endif
+#endif
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+  ("MergeOppositeLic",                                m_mergeOppositeLic,                                true, "Enable opposite LIC flag for merge")
+  ("MergeTMOppositeLic",                              m_mergeTMOppositeLic,                              true, "Enable opposite LIC flag for TM merge")
+  ("MergeAffOppositeLic",                             m_mergeAffOppositeLic,                             true, "Enable opposite LIC flag for Affine merge")
 #endif
 #if JVET_AA0093_REFINED_MOTION_FOR_ARMC
   ("ArmcRefinedMotion",                               m_armcRefinedMotion,                               true, "Enable adaptive re-ordering of merge candidates with refined motion")
@@ -1555,6 +1567,9 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] )
 #else
   ("MaxNumMergeCand",                                 m_maxNumMergeCand,                                   5u, "Maximum number of merge candidates")
 #endif
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+  ("MaxNumOppositeLicMergeCand",                      m_maxNumOppositeLicMergeCand,                       (uint32_t)(REG_MRG_MAX_NUM_CANDS_OPPOSITELIC), "Maximum number of merge candidates with opposite LIC flag")
+#endif
 #if JVET_X0049_ADAPT_DMVR
   ("MaxNumBMMergeCand",                               m_maxNumBMMergeCand,                                 4u, "Maximum number of BM merge candidates")
 #endif
@@ -1563,6 +1578,9 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] )
 #else
   ("MaxNumAffineMergeCand",                           m_maxNumAffineMergeCand,                             5u, "Maximum number of affine merge candidates")
 #endif
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+  ("MaxNumAffineOppositeLicMergeCand",                m_maxNumAffineOppositeLicMergeCand,                  (uint32_t)(AFF_MRG_MAX_NUM_CANDS_OPPOSITELIC), "Maximum number of affine merge candidates with opposite LIC flag")
+#endif
 #if NON_ADJACENT_MRG_CAND
   ("MaxNumGeoCand",                                   m_maxNumGeoCand,                                     10u, "Maximum number of geometric partitioning mode candidates")
 #else
@@ -1826,6 +1844,9 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] )
 #if INTER_LIC
   ("LIC",                                             m_lic,                                     true, "Local illumination compensation [LIC] (0:disabled, 1:enabled)  [default: 1]")
   ("FastPicLevelLIC",                                 m_fastPicLevelLIC,                         true, "Fast picture level LIC decision (0:disabled, 1:enabled)  [default: 1]")
+#if JVET_AG0276_LIC_SLOPE_ADJUST
+  ("LicSlopeAdjust",                                  m_licSlopeAdjust,                          true, "LIC with slope adjustment (0:disabled, 1:enabled)  [default: 1]")
+#endif
 #endif
   ( "ScalingRatioHor",                                m_scalingRatioHor,                          1.0, "Scaling ratio in hor direction" )
   ( "ScalingRatioVer",                                m_scalingRatioVer,                          1.0, "Scaling ratio in ver direction" )
@@ -4002,6 +4023,9 @@ bool EncAppCfg::xCheckParameter()
   xConfirmPara(m_maxNumAffineMergeCand < (m_sbTmvpEnableFlag ? 1 : 0),
                "MaxNumAffineMergeCand must be greater than 0 when SbTMVP is enabled");
   xConfirmPara( m_maxNumAffineMergeCand > AFFINE_MRG_MAX_NUM_CANDS, "MaxNumAffineMergeCand must be no more than AFFINE_MRG_MAX_NUM_CANDS." );
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+  xConfirmPara(m_maxNumAffineOppositeLicMergeCand > AFF_MRG_MAX_NUM_CANDS_OPPOSITELIC, "MaxNumAffineOppositeLicMergeCand must be no more than AFF_MRG_MAX_NUM_CANDS_OPPOLIC.");
+#endif
 #if JVET_AE0174_NONINTER_TM_TOOLS_CONTROL
   if (!m_tmNoninterToolsEnableFlag)
   {
@@ -4092,6 +4116,9 @@ bool EncAppCfg::xCheckParameter()
     m_maxNumAffineMergeCand = m_sbTmvpEnableFlag ? 1 : 0;
     if (m_PROF) msg(WARNING, "PROF is forcefully disabled when Affine is off \n");
     m_PROF = false;
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+    m_maxNumAffineOppositeLicMergeCand = 0;
+#endif
   }
 #if MULTI_PASS_DMVR
   if (m_DMVR && m_DMVDMode)
@@ -4200,6 +4227,24 @@ bool EncAppCfg::xCheckParameter()
 #endif
   }
 #endif
+#if JVET_AG0276_NLIC
+  if (!m_AML)
+  {
+    msg(WARNING, "AltLM is forcefully disabled since ARMC is set off\n");
+    m_altLM = false;
+    m_affAltLM = false;
+  }
+  if (!m_affAltLM)
+  {
+    msg(WARNING, "Affine AltLM TM is disabled since affine AltLM is set off\n");
+    m_useAffAltLMTM = false;
+  }
+  if (!m_useAffineTM)
+  {
+    msg(WARNING, "Affine AltLM TM is disabled since TM-based affine TM is set off\n");
+    m_useAffAltLMTM = false;
+  }
+#endif
 #if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_W0097_GPM_MMVD_TM && TM_MRG
   if (!m_Geo && m_tmGPMMode)
   {
@@ -5788,6 +5833,9 @@ void EncAppCfg::xPrintParameter()
   if( m_lic )
   {
     msg( VERBOSE, "FastPicLevelLIC:%d ", m_fastPicLevelLIC );
+#if JVET_AG0276_LIC_SLOPE_ADJUST
+    msg( VERBOSE, "LicSlopeAdust:%d ", m_licSlopeAdjust );
+#endif
   }
 #endif
 #if JVET_AE0059_INTER_CCCM
diff --git a/source/App/EncoderApp/EncAppCfg.h b/source/App/EncoderApp/EncAppCfg.h
index 55b44ac41..2f41e4ed7 100644
--- a/source/App/EncoderApp/EncAppCfg.h
+++ b/source/App/EncoderApp/EncAppCfg.h
@@ -399,6 +399,9 @@ protected:
   bool      m_AffineType;
 #if JVET_AF0163_TM_SUBBLOCK_REFINEMENT
   bool      m_useAffineTM;
+#if JVET_AG0276_NLIC
+  bool      m_useAffAltLMTM;
+#endif
 #endif
 #if JVET_AG0135_AFFINE_CIIP
   bool      m_useCiipAffine;
@@ -440,6 +443,15 @@ protected:
   bool      m_BIO;
 #if JVET_W0090_ARMC_TM
   bool      m_AML;
+#if JVET_AG0276_NLIC
+  bool      m_altLM;
+  bool      m_affAltLM;
+#endif
+#endif
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+  bool      m_mergeOppositeLic;
+  bool      m_mergeTMOppositeLic;
+  bool      m_mergeAffOppositeLic;
 #endif
 #if JVET_AA0093_REFINED_MOTION_FOR_ARMC
   bool      m_armcRefinedMotion;
@@ -913,6 +925,10 @@ protected:
 
   uint32_t      m_log2ParallelMergeLevel;                         ///< Parallel merge estimation region
   uint32_t      m_maxNumMergeCand;                                ///< Max number of merge candidates
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+  uint32_t      m_maxNumOppositeLicMergeCand;                     ///< Max number of merge candidates with opposite LIC flag
+  uint32_t      m_maxNumAffineOppositeLicMergeCand;               ///< Max number of affine merge candidates with opposite LIC flag
+#endif
 #if JVET_X0049_ADAPT_DMVR
   uint32_t      m_maxNumBMMergeCand;                                ///< Max number of BM merge candidates
 #endif
@@ -1013,6 +1029,9 @@ protected:
 #if INTER_LIC
   bool        m_lic;
   bool        m_fastPicLevelLIC;
+#if JVET_AG0276_LIC_SLOPE_ADJUST
+  bool        m_licSlopeAdjust;
+#endif
 #endif
 
   double      m_scalingRatioHor;
diff --git a/source/Lib/CommonLib/Buffer.cpp b/source/Lib/CommonLib/Buffer.cpp
index 989b7b740..3cd17e9a7 100644
--- a/source/Lib/CommonLib/Buffer.cpp
+++ b/source/Lib/CommonLib/Buffer.cpp
@@ -1951,6 +1951,9 @@ void AreaBuf<Pel>::linearTransform( const int scale, const int shift, const int
 {
   const Pel* src = buf;
         Pel* dst = buf;
+#if JVET_AG0276_NLIC
+  const uint32_t areaT = area();
+#endif
 
 #if JVET_W0090_ARMC_TM || JVET_Z0056_GPM_SPLIT_MODE_REORDERING
   if (width == 0)
@@ -1963,6 +1966,16 @@ void AreaBuf<Pel>::linearTransform( const int scale, const int shift, const int
     THROW( "Blocks of width = 1 not supported" );
   }
 #endif
+#if JVET_AG0276_NLIC
+  else if (width == stride && (areaT & 7) == 0)
+  {
+    g_pelBufOP.linTf8(src, areaT, dst, areaT, areaT, 1, scale, shift, offset, clpRng, bClip);
+  }
+  else if (width == stride && (areaT & 3) == 0)
+  {
+    g_pelBufOP.linTf4(src, areaT, dst, areaT, areaT, 1, scale, shift, offset, clpRng, bClip);
+  }
+#endif
 #if ENABLE_SIMD_OPT_BUFFER && defined(TARGET_SIMD_X86)
   else if( ( width & 7 ) == 0 )
   {
diff --git a/source/Lib/CommonLib/Common.h b/source/Lib/CommonLib/Common.h
index 1fa2461c0..17ea3c597 100644
--- a/source/Lib/CommonLib/Common.h
+++ b/source/Lib/CommonLib/Common.h
@@ -654,4 +654,35 @@ struct DecoderDerivedCcpCandidate
 };
 #endif
 
+#if JVET_AG0276_NLIC
+struct AltLMInterUnit
+{
+  int scale[MAX_NUM_COMPONENT];
+  int offset[MAX_NUM_COMPONENT];
+
+  void resetAltLinearModel()
+  {
+    for (int comp = 0; comp < MAX_NUM_COMPONENT; comp++)
+    {
+      scale[comp] = 32;
+      offset[comp] = 0;
+    }
+  }
+
+  AltLMInterUnit()
+  {
+    resetAltLinearModel();
+  }
+
+  AltLMInterUnit &operator=(const AltLMInterUnit &other)
+  {
+    for (int comp = 0; comp < MAX_NUM_COMPONENT; comp++)
+    {
+      scale[comp] = other.scale[comp];
+      offset[comp] = other.offset[comp];
+    }
+    return *this;
+  }
+};
+#endif
 #endif
diff --git a/source/Lib/CommonLib/CommonDef.h b/source/Lib/CommonLib/CommonDef.h
index f260da955..3f025d71c 100644
--- a/source/Lib/CommonLib/CommonDef.h
+++ b/source/Lib/CommonLib/CommonDef.h
@@ -233,6 +233,11 @@ static const int RMVF_NUM_SUBBLK_THRED = 255;
 static const int RMVF_PARAM_THRED = (1 << 20);
 #endif
 #endif
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+static const int AFF_MRG_MAX_NUM_CANDS_OPPOSITELIC =                8;
+static const int REG_MRG_MAX_NUM_CANDS_OPPOSITELIC =                5;
+static const int TM_MRG_MAX_NUM_CANDS_OPPOSITELIC =                 3;
+#endif
 static const int IBC_MRG_MAX_NUM_CANDS =                            6; ///< IBC MERGE
 #if JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV
 static const int IBC_MRG_MAX_NUM_CANDS_MEM =                        28;   ///< IBC AMVP- max number of candidates
@@ -1158,6 +1163,14 @@ static const int ADAPTIVE_SUB_GROUP_SIZE_MMVD_AFF = AF_MMVD_MAX_REFINE_NUM;
 #endif
 #endif
 
+#if JVET_AG0276_NLIC
+static const int ALT_MRG_MAX_NUM_CANDS     = 16;
+static const int ALT_AFF_MRG_MAX_NUM_CANDS = 6;
+#endif
+#if JVET_AG0276_LIC_SLOPE_ADJUST
+static const int LIC_SLOPE_MAX_NUM_DELTA  = 2;
+#endif
+
 #if JVET_AA0057_CCCM || JVET_AB0092_GLM_WITH_LUMA || JVET_AC0119_LM_CHROMA_FUSION
 static const int CCCM_WINDOW_SIZE         = 6;
 static const int CCCM_NUM_PARAMS          = 7;
diff --git a/source/Lib/CommonLib/ContextModelling.cpp b/source/Lib/CommonLib/ContextModelling.cpp
index bd590a97e..62437f961 100644
--- a/source/Lib/CommonLib/ContextModelling.cpp
+++ b/source/Lib/CommonLib/ContextModelling.cpp
@@ -514,6 +514,22 @@ unsigned DeriveCtx::CtxSkipFlag( const CodingUnit& cu )
   return ctxId;
 }
 
+#if JVET_AG0276_LIC_SLOPE_ADJUST
+unsigned DeriveCtx::CtxLicFlag( const CodingUnit& cu )
+{
+  const CodingStructure *cs = cu.cs;
+  unsigned ctxId = 0;
+
+  const CodingUnit *cuLeft = cs->getCURestricted( cu.lumaPos().offset( -1, 0 ), cu, CH_L );
+  ctxId = ( cuLeft && !cuLeft->firstPU->mergeFlag && !cuLeft->firstPU->amvpMergeModeFlag[0] && !cuLeft->firstPU->amvpMergeModeFlag[1] ) ? 1 : 0;
+
+  const CodingUnit *cuAbove = cs->getCURestricted( cu.lumaPos().offset( 0, -1 ), cu, CH_L );
+  ctxId += ( cuAbove && !cuAbove->firstPU->mergeFlag && !cuAbove->firstPU->amvpMergeModeFlag[0] && !cuAbove->firstPU->amvpMergeModeFlag[1]  ) ? 1 : 0;
+
+  return ctxId;
+}
+#endif
+
 #if ENABLE_DIMD 
 unsigned DeriveCtx::CtxDIMDFlag(const CodingUnit& cu)
 {
@@ -630,6 +646,10 @@ void MergeCtx::copyRegularMergeCand(int dstCandIdx, MergeCtx& srcCtx, int srcCan
   mvFieldNeighbours[ dstCandIdx << 1     ] = srcCtx.mvFieldNeighbours[ srcCandIdx << 1     ];
   mvFieldNeighbours[(dstCandIdx << 1) + 1] = srcCtx.mvFieldNeighbours[(srcCandIdx << 1) + 1];
   bcwIdx            [dstCandIdx] = srcCtx.bcwIdx            [srcCandIdx];
+#if JVET_AG0276_NLIC
+  altLMFlag[dstCandIdx] = srcCtx.altLMFlag[srcCandIdx];
+  altLMParaNeighbours[dstCandIdx] = srcCtx.altLMParaNeighbours[srcCandIdx];
+#endif
 #if INTER_LIC
   licFlags          [dstCandIdx] = srcCtx.licFlags          [srcCandIdx];
 #endif
@@ -701,6 +721,16 @@ void MergeCtx::saveMergeInfo(PredictionUnit& puTmp, PredictionUnit pu)
 
   puTmp.mmvdEncOptMode = pu.mmvdEncOptMode;
   puTmp.cu->licFlag = pu.cu->licFlag;
+#if JVET_AG0276_NLIC
+  puTmp.cu->altLMFlag = pu.cu->altLMFlag;
+  puTmp.cu->altLMParaUnit = pu.cu->altLMParaUnit;
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+  puTmp.cu->altLMBRParaUnit = pu.cu->altLMBRParaUnit;
+#endif
+#endif
+#if JVET_AG0276_LIC_SLOPE_ADJUST
+  puTmp.cu->licDelta = pu.cu->licDelta;
+#endif
 }
 #endif
 void MergeCtx::setMergeInfo( PredictionUnit& pu, int candIdx )
@@ -732,6 +762,10 @@ void MergeCtx::setMergeInfo( PredictionUnit& pu, int candIdx )
 #endif
   pu.refIdx[REF_PIC_LIST_0] = mvFieldNeighbours[(candIdx << 1) + 0].refIdx;
   pu.refIdx[REF_PIC_LIST_1] = mvFieldNeighbours[(candIdx << 1) + 1].refIdx;
+#if JVET_AG0276_NLIC
+  pu.cu->altLMFlag = altLMFlag[candIdx];
+  pu.cu->altLMParaUnit = altLMParaNeighbours[candIdx];
+#endif
 
   if (CU::isIBC(*pu.cu))
   {
@@ -800,6 +834,9 @@ void MergeCtx::setMergeInfo( PredictionUnit& pu, int candIdx )
 
 #if INTER_LIC
   pu.cu->licFlag = pu.cs->slice->getUseLIC() ? licFlags[candIdx] : false;
+#if JVET_AG0276_LIC_SLOPE_ADJUST
+  pu.cu->licDelta = 0;
+#endif
 #if !JVET_AD0213_LIC_IMP
   if (pu.interDir == 3)
   {
@@ -1006,6 +1043,10 @@ bool MergeCtx::xCheckSimilarMotion(int mergeCandIndex, uint32_t mvdSimilarityThr
 void MergeCtx::initMrgCand(int cnt)
 {
   bcwIdx[cnt] = BCW_DEFAULT;
+#if JVET_AG0276_NLIC
+  altLMFlag[cnt] = false;
+  altLMParaNeighbours[cnt].resetAltLinearModel();
+#endif
 #if INTER_LIC
   licFlags[cnt] = false;
 #endif
@@ -1370,8 +1411,15 @@ void MergeCtx::setGeoMmvdMergeInfo(PredictionUnit& pu, int mergeIdx, int mmvdIdx
 #endif
   pu.mmvdEncOptMode = 0;
 
+#if JVET_AG0276_NLIC
+  pu.cu->altLMFlag = altLMFlag[mergeIdx];
+  pu.cu->altLMParaUnit = altLMParaNeighbours[mergeIdx];
+#endif
 #if INTER_LIC
   pu.cu->licFlag = pu.cs->slice->getUseLIC() ? licFlags[mergeIdx] : false;
+#if JVET_AG0276_LIC_SLOPE_ADJUST
+  pu.cu->licDelta = 0;
+#endif
   if (pu.interDir == 3)
   {
     CHECK(pu.cu->licFlag, "LIC is not used with bi-prediction in merge");
@@ -1655,8 +1703,15 @@ void MergeCtx::setMmvdMergeCandiInfo(PredictionUnit& pu, int candIdx)
   pu.mvpNum[REF_PIC_LIST_0] = NOT_VALID;
   pu.mvpNum[REF_PIC_LIST_1] = NOT_VALID;
   pu.cu->imv = mmvdUseAltHpelIf[fPosBaseIdx] ? IMV_HPEL : 0;
+#if JVET_AG0276_NLIC
+  pu.cu->altLMFlag = altLMFlag[fPosBaseIdx];
+  pu.cu->altLMParaUnit = altLMParaNeighbours[fPosBaseIdx];
+#endif
 #if INTER_LIC
   pu.cu->licFlag = licFlags[fPosBaseIdx];
+#if JVET_AG0276_LIC_SLOPE_ADJUST
+  pu.cu->licDelta = 0;
+#endif
 #endif
   pu.cu->bcwIdx = (interDirNeighbours[fPosBaseIdx] == 3) ? bcwIdx[fPosBaseIdx] : BCW_DEFAULT;
 
@@ -1829,6 +1884,145 @@ bool AffineMergeCtx::xCheckSimilarMotion(int mergeCandIndex, uint32_t mvdSimilar
   return false;
 }
 #endif
+#if JVET_AG0276_NLIC
+bool AffineMergeCtx::xCheckSimilarMotion1(int mergeCandIndex, uint32_t mvdSimilarityThresh, bool isAlt) const
+{
+  if (mvFieldNeighbours[(mergeCandIndex << 1)][0].refIdx < 0 && mvFieldNeighbours[(mergeCandIndex << 1) + 1][0].refIdx < 0)
+  {
+    return true;
+  }
+
+  if (mvdSimilarityThresh > 1)
+  {
+    int mvdTh = mvdSimilarityThresh;
+    for (uint32_t ui = 0; ui < mergeCandIndex; ui++)
+    {
+      if (!isAlt && altLMFlag[ui])
+      {
+        continue;
+      }
+      if (isAlt && !altLMFlag[ui])
+      {
+        continue;
+      }
+      if (interDirNeighbours[ui] == interDirNeighbours[mergeCandIndex])
+      {
+        if (interDirNeighbours[ui] == 3)
+        {
+          if (mvFieldNeighbours[(ui << 1)][0].refIdx == mvFieldNeighbours[(mergeCandIndex << 1)][0].refIdx &&
+              mvFieldNeighbours[(ui << 1) + 1][0].refIdx == mvFieldNeighbours[(mergeCandIndex << 1) + 1][0].refIdx)
+          {
+            Mv mvDiff0L0 = mvFieldNeighbours[(ui << 1)][0].mv - mvFieldNeighbours[(mergeCandIndex << 1)][0].mv;
+            Mv mvDiff0L1 = mvFieldNeighbours[(ui << 1) + 1][0].mv - mvFieldNeighbours[(mergeCandIndex << 1) + 1][0].mv;
+
+            Mv mvDiff1L0 = mvFieldNeighbours[(ui << 1)][1].mv - mvFieldNeighbours[(mergeCandIndex << 1)][1].mv;
+            Mv mvDiff1L1 = mvFieldNeighbours[(ui << 1) + 1][1].mv - mvFieldNeighbours[(mergeCandIndex << 1) + 1][1].mv;
+
+            Mv mvDiff2L0 = mvFieldNeighbours[(ui << 1)][2].mv - mvFieldNeighbours[(mergeCandIndex << 1)][2].mv;
+            Mv mvDiff2L1 = mvFieldNeighbours[(ui << 1) + 1][2].mv - mvFieldNeighbours[(mergeCandIndex << 1) + 1][2].mv;
+            if (mvDiff0L0.getAbsHor() < mvdTh && mvDiff0L0.getAbsVer() < mvdTh
+                && mvDiff0L1.getAbsHor() < mvdTh && mvDiff0L1.getAbsVer() < mvdTh
+                &&mvDiff1L0.getAbsHor() < mvdTh && mvDiff1L0.getAbsVer() < mvdTh
+                && mvDiff1L1.getAbsHor() < mvdTh && mvDiff1L1.getAbsVer() < mvdTh
+                &&mvDiff2L0.getAbsHor() < mvdTh && mvDiff2L0.getAbsVer() < mvdTh
+                && mvDiff2L1.getAbsHor() < mvdTh && mvDiff2L1.getAbsVer() < mvdTh
+                )
+            {
+              return true;
+            }
+          }
+        }
+        else if (interDirNeighbours[ui] == 1)
+        {
+          if (mvFieldNeighbours[(ui << 1)][0].refIdx == mvFieldNeighbours[(mergeCandIndex << 1)][0].refIdx)
+          {
+            Mv mvDiff0 = mvFieldNeighbours[(ui << 1)][0].mv - mvFieldNeighbours[(mergeCandIndex << 1)][0].mv;
+            Mv mvDiff1 = mvFieldNeighbours[(ui << 1)][1].mv - mvFieldNeighbours[(mergeCandIndex << 1)][1].mv;
+            Mv mvDiff2 = mvFieldNeighbours[(ui << 1)][2].mv - mvFieldNeighbours[(mergeCandIndex << 1)][2].mv;
+            if (mvDiff0.getAbsHor() < mvdTh && mvDiff0.getAbsVer() < mvdTh
+                &&mvDiff1.getAbsHor() < mvdTh && mvDiff1.getAbsVer() < mvdTh
+                &&mvDiff2.getAbsHor() < mvdTh && mvDiff2.getAbsVer() < mvdTh
+                )
+            {
+              return true;
+            }
+          }
+        }
+        else if (interDirNeighbours[ui] == 2)
+        {
+          if (mvFieldNeighbours[(ui << 1) + 1][0].refIdx == mvFieldNeighbours[(mergeCandIndex << 1) + 1][0].refIdx)
+          {
+            Mv mvDiff0 = mvFieldNeighbours[(ui << 1) + 1][0].mv - mvFieldNeighbours[(mergeCandIndex << 1) + 1][0].mv;
+            Mv mvDiff1 = mvFieldNeighbours[(ui << 1) + 1][1].mv - mvFieldNeighbours[(mergeCandIndex << 1) + 1][1].mv;
+            Mv mvDiff2 = mvFieldNeighbours[(ui << 1) + 1][2].mv - mvFieldNeighbours[(mergeCandIndex << 1) + 1][2].mv;
+            if (mvDiff0.getAbsHor() < mvdTh && mvDiff0.getAbsVer() < mvdTh
+                &&mvDiff1.getAbsHor() < mvdTh && mvDiff1.getAbsVer() < mvdTh
+                && mvDiff2.getAbsHor() < mvdTh && mvDiff2.getAbsVer() < mvdTh
+                )
+            {
+              return true;
+            }
+          }
+        }
+      }
+    }
+    return false;
+  }
+
+  for (uint32_t ui = 0; ui < mergeCandIndex; ui++)
+  {
+    if (!isAlt && altLMFlag[ui])
+    {
+      continue;
+    }
+    if (isAlt && !altLMFlag[ui])
+    {
+      continue;
+    }
+    if (interDirNeighbours[ui] == interDirNeighbours[mergeCandIndex])
+    {
+      if (interDirNeighbours[ui] == 3)
+      {
+        if (mvFieldNeighbours[(ui << 1)][0].refIdx == mvFieldNeighbours[(mergeCandIndex << 1)][0].refIdx &&
+            mvFieldNeighbours[(ui << 1) + 1][0].refIdx == mvFieldNeighbours[(mergeCandIndex << 1) + 1][0].refIdx &&
+            mvFieldNeighbours[(ui << 1)][0].mv == mvFieldNeighbours[(mergeCandIndex << 1)][0].mv     &&
+            mvFieldNeighbours[(ui << 1) + 1][0].mv == mvFieldNeighbours[(mergeCandIndex << 1) + 1][0].mv&&
+            mvFieldNeighbours[(ui << 1)][1].mv == mvFieldNeighbours[(mergeCandIndex << 1)][1].mv     &&
+            mvFieldNeighbours[(ui << 1) + 1][1].mv == mvFieldNeighbours[(mergeCandIndex << 1) + 1][1].mv&&
+            mvFieldNeighbours[(ui << 1)][2].mv == mvFieldNeighbours[(mergeCandIndex << 1)][2].mv     &&
+            mvFieldNeighbours[(ui << 1) + 1][2].mv == mvFieldNeighbours[(mergeCandIndex << 1) + 1][2].mv
+            )
+        {
+          return true;
+        }
+      }
+      else if (interDirNeighbours[ui] == 1)
+      {
+        if (mvFieldNeighbours[(ui << 1)][0].refIdx == mvFieldNeighbours[(mergeCandIndex << 1)][0].refIdx &&
+            mvFieldNeighbours[(ui << 1)][0].mv == mvFieldNeighbours[(mergeCandIndex << 1)][0].mv&&
+            mvFieldNeighbours[(ui << 1)][1].mv == mvFieldNeighbours[(mergeCandIndex << 1)][1].mv&&
+            mvFieldNeighbours[(ui << 1)][2].mv == mvFieldNeighbours[(mergeCandIndex << 1)][2].mv
+            )
+        {
+          return true;
+        }
+      }
+      else if (interDirNeighbours[ui] == 2)
+      {
+        if (mvFieldNeighbours[(ui << 1) + 1][0].refIdx == mvFieldNeighbours[(mergeCandIndex << 1) + 1][0].refIdx &&
+            mvFieldNeighbours[(ui << 1) + 1][0].mv == mvFieldNeighbours[(mergeCandIndex << 1) + 1][0].mv &&
+            mvFieldNeighbours[(ui << 1) + 1][1].mv == mvFieldNeighbours[(mergeCandIndex << 1) + 1][1].mv &&
+            mvFieldNeighbours[(ui << 1) + 1][2].mv == mvFieldNeighbours[(mergeCandIndex << 1) + 1][2].mv
+            )
+        {
+          return true;
+        }
+      }
+    }
+  }
+  return false;
+}
+#endif
 #if JVET_AA0061_IBC_MBVD
 #if JVET_AE0169_BIPREDICTIVE_IBC
 bool MergeCtx::setIbcMbvdMergeCandiInfo(PredictionUnit& pu, int candIdx, int candIdxMaped, int candIdx1, int candIdxMaped1)
@@ -2067,6 +2261,309 @@ bool MergeCtx::setIbcMbvdMergeCandiInfo(PredictionUnit& pu, int candIdx, int can
 }
 #endif
 
+#if JVET_AG0276_NLIC
+void AltLMMergeCtx::initAltLMMergeCtx(int idx)
+{
+  altLMParaNeighbours[idx].resetAltLinearModel();
+  mvFieldNeighbours[(idx << 1) + 0].setMvField(Mv(), -1);
+  mvFieldNeighbours[(idx << 1) + 1].setMvField(Mv(), -1);
+  interDirNeighbours[idx] = 0;
+  bcwIdx[idx] = BCW_DEFAULT;
+  useAltHpelIf[idx] = false;
+}
+
+bool AltLMMergeCtx::xCheckSameMotion(int mrgCandIdx, uint32_t mvdSimilarityThresh)
+{
+  for (int ui = 0; ui < mrgCandIdx; ui++)
+  {
+    bool sameMotion = false;
+    bool sameInterDir = (interDirNeighbours[ui] == interDirNeighbours[mrgCandIdx]);
+    if (sameInterDir && interDirNeighbours[mrgCandIdx] == 3)
+    {
+      sameInterDir = (bcwIdx[ui] == bcwIdx[mrgCandIdx]);
+    }
+
+    if (sameInterDir)
+    {
+      if (interDirNeighbours[ui] == 3)
+      {
+        if (mvFieldNeighbours[(ui << 1)].refIdx == mvFieldNeighbours[(mrgCandIdx << 1)].refIdx     &&
+          mvFieldNeighbours[(ui << 1) + 1].refIdx == mvFieldNeighbours[(mrgCandIdx << 1) + 1].refIdx)
+        {
+          Mv mvDiffL0 = mvFieldNeighbours[(ui << 1)].mv - mvFieldNeighbours[(mrgCandIdx << 1)].mv;
+          Mv mvDiffL1 = mvFieldNeighbours[(ui << 1) + 1].mv - mvFieldNeighbours[(mrgCandIdx << 1) + 1].mv;
+
+          if (mvDiffL0.getAbsHor() < mvdSimilarityThresh && mvDiffL0.getAbsVer() < mvdSimilarityThresh
+            && mvDiffL1.getAbsHor() < mvdSimilarityThresh && mvDiffL1.getAbsVer() < mvdSimilarityThresh)
+          {
+            sameMotion = true;
+          }
+        }
+      }
+      else if (interDirNeighbours[ui] == 1)
+      {
+        if (mvFieldNeighbours[(ui << 1)].refIdx == mvFieldNeighbours[(mrgCandIdx << 1)].refIdx)
+        {
+          Mv mvDiff = mvFieldNeighbours[(ui << 1)].mv - mvFieldNeighbours[(mrgCandIdx << 1)].mv;
+          if (mvDiff.getAbsHor() < mvdSimilarityThresh && mvDiff.getAbsVer() < mvdSimilarityThresh)
+          {
+            sameMotion = true;
+          }
+        }
+      }
+      else if (interDirNeighbours[ui] == 2)
+      {
+        if (mvFieldNeighbours[(ui << 1) + 1].refIdx == mvFieldNeighbours[(mrgCandIdx << 1) + 1].refIdx)
+        {
+          Mv mvDiff = mvFieldNeighbours[(ui << 1) + 1].mv - mvFieldNeighbours[(mrgCandIdx << 1) + 1].mv;
+          if (mvDiff.getAbsHor() < mvdSimilarityThresh && mvDiff.getAbsVer() < mvdSimilarityThresh)
+          {
+            sameMotion = true;
+          }
+        }
+      }
+    }
+
+    if (sameMotion)
+    {
+      return true;
+    }
+  }
+  return false;
+}
+#endif
+
+#if JVET_AG0276_NLIC
+bool AltLMAffineMergeCtx::xCheckSameAffMotion(const PredictionUnit& pu, int cnt)
+{
+  if (cnt < 1)
+  {
+    return true;
+  }
+
+  const int CPMV_SIMILARITY_THREH = 1;
+  const int PARA_SIMILARITY_THREH = 1;
+
+  const int lastIdx = cnt;
+  for (int idx = 0; idx < cnt; idx++)
+  {
+    if (affineType[idx] != affineType[lastIdx])
+    {
+      continue;
+    }
+
+    if (interDirNeighbours[idx] != interDirNeighbours[lastIdx])
+    {
+      continue;
+    }
+
+    if (interDirNeighbours[idx] == 3 && bcwIdx[idx] != bcwIdx[lastIdx])
+    {
+      continue;
+    }
+
+    if ((interDirNeighbours[lastIdx] & 1) != 0)
+    {
+      if (mvFieldNeighbours[(idx << 1)][0].refIdx != mvFieldNeighbours[(lastIdx << 1)][0].refIdx)
+      {
+        continue;
+      }
+      Mv acMvTemp[3];
+      int affinePara[4], affineParaLast[4];
+      acMvTemp[0] = mvFieldNeighbours[(idx << 1)][0].mv;
+      acMvTemp[1] = mvFieldNeighbours[(idx << 1)][1].mv;
+      acMvTemp[2] = mvFieldNeighbours[(idx << 1)][2].mv;
+      PU::deriveAffineParametersFromMVs(pu, acMvTemp, affinePara, affineType[idx]);
+      acMvTemp[0] = mvFieldNeighbours[(lastIdx << 1)][0].mv;
+      acMvTemp[1] = mvFieldNeighbours[(lastIdx << 1)][1].mv;
+      acMvTemp[2] = mvFieldNeighbours[(lastIdx << 1)][2].mv;
+      PU::deriveAffineParametersFromMVs(pu, acMvTemp, affineParaLast, affineType[idx]);
+
+      if (
+        abs(mvFieldNeighbours[(idx << 1)][0].mv.getHor() - mvFieldNeighbours[(lastIdx << 1)][0].mv.getHor()) > CPMV_SIMILARITY_THREH ||
+        abs(mvFieldNeighbours[(idx << 1)][0].mv.getVer() - mvFieldNeighbours[(lastIdx << 1)][0].mv.getVer()) > CPMV_SIMILARITY_THREH ||
+        abs(affinePara[0] - affineParaLast[0]) > PARA_SIMILARITY_THREH ||
+        abs(affinePara[2] - affineParaLast[2]) > PARA_SIMILARITY_THREH
+        )
+      {
+        continue;
+      }
+
+
+      if (affineType[idx] == AFFINEMODEL_6PARAM)
+      {
+        if (abs(affinePara[1] - affineParaLast[1]) > PARA_SIMILARITY_THREH ||
+          abs(affinePara[3] - affineParaLast[3]) > PARA_SIMILARITY_THREH)
+        {
+          continue;
+        }
+      }
+    }
+
+    if ((interDirNeighbours[lastIdx] & 2) != 0)
+    {
+      if (mvFieldNeighbours[(idx << 1) + 1][0].refIdx != mvFieldNeighbours[(lastIdx << 1) + 1][0].refIdx)
+      {
+        continue;
+      }
+      Mv acMvTemp[3];
+      int affinePara[4], affineParaLast[4];
+      acMvTemp[0] = mvFieldNeighbours[(idx << 1) + 1][0].mv;
+      acMvTemp[1] = mvFieldNeighbours[(idx << 1) + 1][1].mv;
+      acMvTemp[2] = mvFieldNeighbours[(idx << 1) + 1][2].mv;
+      PU::deriveAffineParametersFromMVs(pu, acMvTemp, affinePara, affineType[idx]);
+      acMvTemp[0] = mvFieldNeighbours[(lastIdx << 1) + 1][0].mv;
+      acMvTemp[1] = mvFieldNeighbours[(lastIdx << 1) + 1][1].mv;
+      acMvTemp[2] = mvFieldNeighbours[(lastIdx << 1) + 1][2].mv;
+      PU::deriveAffineParametersFromMVs(pu, acMvTemp, affineParaLast, affineType[idx]);
+
+      if (
+        abs(mvFieldNeighbours[(idx << 1) + 1][0].mv.getHor() - mvFieldNeighbours[(lastIdx << 1) + 1][0].mv.getHor()) > CPMV_SIMILARITY_THREH ||
+        abs(mvFieldNeighbours[(idx << 1) + 1][0].mv.getVer() - mvFieldNeighbours[(lastIdx << 1) + 1][0].mv.getVer()) > CPMV_SIMILARITY_THREH ||
+        abs(affinePara[0] - affineParaLast[0]) > PARA_SIMILARITY_THREH ||
+        abs(affinePara[2] - affineParaLast[2]) > PARA_SIMILARITY_THREH)
+      {
+        continue;
+      }
+
+      if (affineType[idx] == AFFINEMODEL_6PARAM)
+      {
+        if (abs(affinePara[1] - affineParaLast[1]) > PARA_SIMILARITY_THREH ||
+          abs(affinePara[3] - affineParaLast[3]) > PARA_SIMILARITY_THREH)
+        {
+          continue;
+        }
+      }
+    }
+    return false;
+  }
+  return true;
+}
+
+void AltLMAffineMergeCtx::initAltLMAffMergeCtx(int idx)
+{
+  altLMParaNeighbours[idx].resetAltLinearModel();
+  for (int mvNum = 0; mvNum < 3; mvNum++)
+  {
+    mvFieldNeighbours[(idx << 1) + 0][mvNum].setMvField(Mv(), -1);
+    mvFieldNeighbours[(idx << 1) + 1][mvNum].setMvField(Mv(), -1);
+  }
+  interDirNeighbours[idx] = 0;
+  affineType[idx] = AFFINEMODEL_4PARAM;
+  bcwIdx[idx] = BCW_DEFAULT;
+#if JVET_AD0193_ADAPTIVE_OBMC_CONTROL
+  obmcFlags[idx] = true;
+#endif
+}
+
+void AltLMAffineMergeCtx::init()
+{
+  for (int i = 0; i < ALT_AFF_MRG_MAX_NUM_CANDS; i++)
+  {
+    initAltLMAffMergeCtx(i);
+  }
+  numValidMergeCand = 0;
+}
+
+bool AltLMAffineMergeCtx::xCheckSameAffMotion(const PredictionUnit& pu, int cnt, AltLMAffineMergeCtx& altAffMrgCtx1)
+{
+  const int cpmvSimilarityThresh = 1;
+  const int paraSimilarityThresh = 1;
+
+  const int lastIdx = cnt;
+  for (int idx = 0; idx < altAffMrgCtx1.numValidMergeCand; idx++)
+  {
+    if (altAffMrgCtx1.affineType[idx] != affineType[lastIdx])
+    {
+      continue;
+    }
+
+    if (altAffMrgCtx1.interDirNeighbours[idx] != interDirNeighbours[lastIdx])
+    {
+      continue;
+    }
+
+    if (altAffMrgCtx1.interDirNeighbours[idx] == 3 && altAffMrgCtx1.bcwIdx[idx] != bcwIdx[lastIdx])
+    {
+      continue;
+    }
+
+    if ((interDirNeighbours[lastIdx] & 1) != 0)
+    {
+      if (altAffMrgCtx1.mvFieldNeighbours[(idx << 1)][0].refIdx != mvFieldNeighbours[(lastIdx << 1)][0].refIdx)
+      {
+        continue;
+      }
+      Mv acMvTemp[3];
+      int affinePara[4], affineParaLast[4];
+      acMvTemp[0] = altAffMrgCtx1.mvFieldNeighbours[(idx << 1)][0].mv;
+      acMvTemp[1] = altAffMrgCtx1.mvFieldNeighbours[(idx << 1)][1].mv;
+      acMvTemp[2] = altAffMrgCtx1.mvFieldNeighbours[(idx << 1)][2].mv;
+      PU::deriveAffineParametersFromMVs(pu, acMvTemp, affinePara, affineType[idx]);
+      acMvTemp[0] = mvFieldNeighbours[(lastIdx << 1)][0].mv;
+      acMvTemp[1] = mvFieldNeighbours[(lastIdx << 1)][1].mv;
+      acMvTemp[2] = mvFieldNeighbours[(lastIdx << 1)][2].mv;
+      PU::deriveAffineParametersFromMVs(pu, acMvTemp, affineParaLast, affineType[idx]);
+
+      if (abs(altAffMrgCtx1.mvFieldNeighbours[(idx << 1)][0].mv.getHor() - mvFieldNeighbours[(lastIdx << 1)][0].mv.getHor()) > cpmvSimilarityThresh ||
+        abs(altAffMrgCtx1.mvFieldNeighbours[(idx << 1)][0].mv.getVer() - mvFieldNeighbours[(lastIdx << 1)][0].mv.getVer()) > cpmvSimilarityThresh ||
+        abs(affinePara[0] - affineParaLast[0]) > paraSimilarityThresh ||
+        abs(affinePara[2] - affineParaLast[2]) > paraSimilarityThresh)
+      {
+        continue;
+      }
+
+
+      if (affineType[idx] == AFFINEMODEL_6PARAM)
+      {
+        if (abs(affinePara[1] - affineParaLast[1]) > paraSimilarityThresh ||
+          abs(affinePara[3] - affineParaLast[3]) > paraSimilarityThresh)
+        {
+          continue;
+        }
+      }
+    }
+
+    if ((interDirNeighbours[lastIdx] & 2) != 0)
+    {
+      if (altAffMrgCtx1.mvFieldNeighbours[(idx << 1) + 1][0].refIdx != mvFieldNeighbours[(lastIdx << 1) + 1][0].refIdx)
+      {
+        continue;
+      }
+      Mv acMvTemp[3];
+      int affinePara[4], affineParaLast[4];
+      acMvTemp[0] = altAffMrgCtx1.mvFieldNeighbours[(idx << 1) + 1][0].mv;
+      acMvTemp[1] = altAffMrgCtx1.mvFieldNeighbours[(idx << 1) + 1][1].mv;
+      acMvTemp[2] = altAffMrgCtx1.mvFieldNeighbours[(idx << 1) + 1][2].mv;
+      PU::deriveAffineParametersFromMVs(pu, acMvTemp, affinePara, affineType[idx]);
+      acMvTemp[0] = mvFieldNeighbours[(lastIdx << 1) + 1][0].mv;
+      acMvTemp[1] = mvFieldNeighbours[(lastIdx << 1) + 1][1].mv;
+      acMvTemp[2] = mvFieldNeighbours[(lastIdx << 1) + 1][2].mv;
+      PU::deriveAffineParametersFromMVs(pu, acMvTemp, affineParaLast, affineType[idx]);
+
+      if (abs(altAffMrgCtx1.mvFieldNeighbours[(idx << 1) + 1][0].mv.getHor() - mvFieldNeighbours[(lastIdx << 1) + 1][0].mv.getHor()) > cpmvSimilarityThresh ||
+        abs(altAffMrgCtx1.mvFieldNeighbours[(idx << 1) + 1][0].mv.getVer() - mvFieldNeighbours[(lastIdx << 1) + 1][0].mv.getVer()) > cpmvSimilarityThresh ||
+        abs(affinePara[0] - affineParaLast[0]) > paraSimilarityThresh ||
+        abs(affinePara[2] - affineParaLast[2]) > paraSimilarityThresh)
+      {
+        continue;
+      }
+
+      if (affineType[idx] == AFFINEMODEL_6PARAM)
+      {
+        if (abs(affinePara[1] - affineParaLast[1]) > paraSimilarityThresh ||
+          abs(affinePara[3] - affineParaLast[3]) > paraSimilarityThresh)
+        {
+          continue;
+        }
+      }
+    }
+    return false;
+  }
+  return true;
+}
+#endif
+
 #if JVET_AD0086_ENHANCED_INTRA_TMP
 unsigned DeriveCtx::CtxTmpFusionFlag(const CodingUnit& cu)
 {
@@ -2205,6 +2702,10 @@ void AffineMergeCtx::setAffMergeInfo(PredictionUnit &pu, int candIdx, int8_t mmv
   pu.interDir       = interDirNeighbours[candIdx];
   pu.cu->affineType = affineType[candIdx];
   pu.cu->bcwIdx     = bcwIdx[candIdx];
+#if JVET_AG0276_NLIC
+  pu.cu->altLMFlag = altLMFlag[candIdx];
+  pu.cu->altLMParaUnit = altLMParaNeighbours[candIdx];
+#endif
 #if INTER_LIC
   pu.cu->licFlag = licFlags[candIdx];
 #endif
@@ -2252,4 +2753,4 @@ void AffineMergeCtx::setAffMergeInfo(PredictionUnit &pu, int candIdx, int8_t mmv
     }
   }
 }
-#endif
\ No newline at end of file
+#endif
diff --git a/source/Lib/CommonLib/ContextModelling.h b/source/Lib/CommonLib/ContextModelling.h
index ccba64a50..a0ea15254 100644
--- a/source/Lib/CommonLib/ContextModelling.h
+++ b/source/Lib/CommonLib/ContextModelling.h
@@ -793,6 +793,10 @@ public:
   MultiHypVec   addHypNeighbours[NUM_MERGE_CANDS];
 #endif
   Distortion    candCost[NUM_MERGE_CANDS];
+#if JVET_AG0276_NLIC
+  bool          altLMFlag[NUM_MERGE_CANDS];
+  AltLMInterUnit altLMParaNeighbours[NUM_MERGE_CANDS];
+#endif
 #else
   MergeCtx() : numValidMergeCand( 0 ), hasMergedCandList( false ) { }
   ~MergeCtx() {}
@@ -928,6 +932,10 @@ public:
   unsigned char interDirNeighbours[RMVF_AFFINE_MRG_MAX_CAND_LIST_SIZE];
   Distortion    candCost[RMVF_AFFINE_MRG_MAX_CAND_LIST_SIZE];
   EAffineModel  affineType[RMVF_AFFINE_MRG_MAX_CAND_LIST_SIZE];
+#if JVET_AG0276_NLIC
+  bool          altLMFlag[RMVF_AFFINE_MRG_MAX_CAND_LIST_SIZE];
+  AltLMInterUnit altLMParaNeighbours[RMVF_AFFINE_MRG_MAX_CAND_LIST_SIZE];
+#endif
 #if INTER_LIC
   bool          licFlags[RMVF_AFFINE_MRG_MAX_CAND_LIST_SIZE];
 #endif
@@ -952,6 +960,9 @@ public:
   int           m_isGPMAff;
   void          setAffMergeInfo(PredictionUnit &pu, int candIdx, int8_t mmvdIdx = -1) const;
 #endif
+#if JVET_AG0276_NLIC
+  bool          xCheckSimilarMotion1(int mergeCandIndex, uint32_t mvdSimilarityThresh = 1, bool isAltLM = false) const;
+#endif
 };
 #else
 class AffineMergeCtx
@@ -981,6 +992,41 @@ public:
 };
 #endif
 
+#if JVET_AG0276_NLIC
+class AltLMMergeCtx
+{
+public:
+  AltLMInterUnit altLMParaNeighbours[ALT_MRG_MAX_NUM_CANDS];
+  MvField        mvFieldNeighbours[ALT_MRG_MAX_NUM_CANDS << 1];
+  uint8_t        bcwIdx[ALT_MRG_MAX_NUM_CANDS];
+  unsigned char  interDirNeighbours[ALT_MRG_MAX_NUM_CANDS];
+  bool           useAltHpelIf[ALT_MRG_MAX_NUM_CANDS];
+  int            numValidMergeCand;
+
+  void           initAltLMMergeCtx(int idx);
+  bool           xCheckSameMotion(int cnt, uint32_t mvdSimilarityThresh);
+};
+
+class AltLMAffineMergeCtx
+{
+public:
+  AltLMInterUnit  altLMParaNeighbours[ALT_AFF_MRG_MAX_NUM_CANDS];
+  MvField         mvFieldNeighbours[ALT_AFF_MRG_MAX_NUM_CANDS << 1][3]; // double length for mv of both lists
+  unsigned char   interDirNeighbours[ALT_AFF_MRG_MAX_NUM_CANDS];
+  EAffineModel    affineType[ALT_AFF_MRG_MAX_NUM_CANDS];
+  uint8_t         bcwIdx[ALT_AFF_MRG_MAX_NUM_CANDS];
+#if JVET_AD0193_ADAPTIVE_OBMC_CONTROL
+  bool            obmcFlags[ALT_AFF_MRG_MAX_NUM_CANDS];
+#endif
+  int             numValidMergeCand;
+
+  bool            xCheckSameAffMotion(const PredictionUnit& pu, int cnt);
+  void            initAltLMAffMergeCtx(int idx);
+  void            init();
+  bool            xCheckSameAffMotion(const PredictionUnit& pu, int cnt, AltLMAffineMergeCtx& altAffMrgCtx1);
+};
+#endif
+
 namespace DeriveCtx
 {
 void     CtxSplit     ( const CodingStructure& cs, Partitioner& partitioner, unsigned& ctxSpl, unsigned& ctxQt, unsigned& ctxHv, unsigned& ctxHorBt, unsigned& ctxVerBt, bool* canSplit = nullptr );
@@ -990,6 +1036,9 @@ unsigned CtxModeConsFlag( const CodingStructure& cs, Partitioner& partitioner );
 unsigned CtxQtCbf     ( const ComponentID compID, const bool prevCbf = false, const int ispIdx = 0 );
 unsigned CtxInterDir  ( const PredictionUnit& pu );
 unsigned CtxSkipFlag  ( const CodingUnit& cu );
+#if JVET_AG0276_LIC_SLOPE_ADJUST
+unsigned CtxLicFlag  ( const CodingUnit& cu );
+#endif
 unsigned CtxAffineFlag( const CodingUnit& cu );
 #if JVET_AG0135_AFFINE_CIIP
 unsigned CtxCiipAffineFlag(const CodingUnit& cu);
diff --git a/source/Lib/CommonLib/Contexts.h b/source/Lib/CommonLib/Contexts.h
index 9d35cd333..3dd1551e2 100644
--- a/source/Lib/CommonLib/Contexts.h
+++ b/source/Lib/CommonLib/Contexts.h
@@ -500,6 +500,11 @@ public:
 #endif
   static const CtxSet   SkipFlag;
   static const CtxSet   MergeFlag;
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+  static const CtxSet   MergeFlagOppositeLic;
+  static const CtxSet   TmMergeFlagOppositeLic;
+  static const CtxSet   AffineFlagOppositeLic;
+#endif
   static const CtxSet   RegularMergeFlag;
   static const CtxSet   MergeIdx;
 #if JVET_AG0164_AFFINE_GPM
@@ -783,6 +788,9 @@ public:
   static const CtxSet   JointCbCrFlag;
 #if INTER_LIC
   static const CtxSet   LICFlag;
+#if JVET_AG0276_LIC_SLOPE_ADJUST
+  static const CtxSet   LicDelta;
+#endif
 #endif
 #if SIGN_PREDICTION
   static const CtxSet   signPred[2];
diff --git a/source/Lib/CommonLib/Contexts_ecm12.inl b/source/Lib/CommonLib/Contexts_ecm12.inl
index 781e9995f..4942aeb1e 100644
--- a/source/Lib/CommonLib/Contexts_ecm12.inl
+++ b/source/Lib/CommonLib/Contexts_ecm12.inl
@@ -111,6 +111,63 @@ const CtxSet ContextSetCfg::MergeFlag = ContextSetCfg::addCtxSet({
   { 109 },
 });
 
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+const CtxSet ContextSetCfg::MergeFlagOppositeLic = ContextSetCfg::addCtxSet
+({
+  {  12, },
+  {   4, },
+  { CNU, },
+  {   5, },
+  {   5, },
+  { DWS, },
+  {  11, },
+  {   4, },
+  { DWE, },
+  { 132, },
+  { 132, },
+  { 132, },
+  { 132, },
+  { 132, },
+  { 132, },
+  });
+const CtxSet ContextSetCfg::AffineFlagOppositeLic = ContextSetCfg::addCtxSet
+({
+  {  12, },
+  {   4, },
+  { CNU, },
+  {   5, },
+  {   5, },
+  { DWS, },
+  {  11, },
+  {   4, },
+  { DWE, },
+  { 132, },
+  { 132, },
+  { 132, },
+  { 132, },
+  { 132, },
+  { 132, },
+  });
+const CtxSet ContextSetCfg::TmMergeFlagOppositeLic = ContextSetCfg::addCtxSet
+({
+  {  12, },
+  {   4, },
+  { CNU, },
+  {   5, },
+  {   5, },
+  { DWS, },
+  {  11, },
+  {   4, },
+  { DWE, },
+  { 132, },
+  { 132, },
+  { 132, },
+  { 132, },
+  { 132, },
+  { 132, },
+  });
+#endif
+
 const CtxSet ContextSetCfg::RegularMergeFlag = ContextSetCfg::addCtxSet({
   { 30, 14 },
   { 23, 6 },
@@ -1170,6 +1227,23 @@ const CtxSet ContextSetCfg::AffMergeIdx = ContextSetCfg::addCtxSet({
 });
 
 const CtxSet ContextSetCfg::LICFlag = ContextSetCfg::addCtxSet({
+#if JVET_AG0276_LIC_SLOPE_ADJUST
+  {  26, CNU, CNU, },
+  {  11, CNU, CNU, },
+  {  35, CNU, CNU, },
+  {   5, DWS, DWS, },
+  {   5, DWS, DWS, },
+  {   8, DWS, DWS, },
+  {  18, DWE, DWE, },
+  {   4, DWE, DWE, },
+  {  18, DWE, DWE, },
+  { 108, DWO, DWO, },
+  { 122, DWO, DWO, },
+  { 116, 119, 119, },
+  { 148, 119, 119, },
+  { 119, 119, 119, },
+  { 119, 119, 119, },
+#else
   { 26 },
   { 11 },
   { 35 },
@@ -1185,8 +1259,28 @@ const CtxSet ContextSetCfg::LICFlag = ContextSetCfg::addCtxSet({
   { 148 },
   { 119 },
   { 119 },
+#endif
 });
 
+#if JVET_AG0276_LIC_SLOPE_ADJUST
+const CtxSet ContextSetCfg::LicDelta = ContextSetCfg::addCtxSet
+({
+  {  CNU, CNU, },
+  {  CNU, CNU, },
+  {  CNU, CNU, },
+  {  DWS, DWS, },
+  {  DWS, DWS, },
+  {  DWS, DWS, },
+  {  DWE, DWE, },
+  {  DWE, DWE, },
+  {  DWE, DWE, },
+  {  DWO, DWO, },
+  {  DWO, DWO, },
+  {  119, 119, },
+  {  119, 119, },
+  });
+#endif
+
 const CtxSet ContextSetCfg::BcwIdx = ContextSetCfg::addCtxSet({
   { 12 },
   { 5 },
diff --git a/source/Lib/CommonLib/InterPrediction.cpp b/source/Lib/CommonLib/InterPrediction.cpp
index a5b74de30..ce5e4e83c 100644
--- a/source/Lib/CommonLib/InterPrediction.cpp
+++ b/source/Lib/CommonLib/InterPrediction.cpp
@@ -341,6 +341,9 @@ InterPrediction::InterPrediction()
   m_mbvdSearchCandsList = nullptr;
   m_mbvdTestedCandsList = nullptr;
 #endif
+#if JVET_AG0276_NLIC
+  m_skipDoLic = false;
+#endif
 }
 
 InterPrediction::~InterPrediction()
@@ -586,7 +589,7 @@ void InterPrediction::init( RdCost* pcRdCost, ChromaFormat chromaFormatIDC, cons
       m_dmvrBottomBoundary[c] = (Pel*)xMalloc( Pel, 16 );
     }
 #endif
-    
+
     for( uint32_t c = 0; c < MAX_NUM_COMPONENT; c++ )
     {
 #if IF_12TAP || MULTI_PASS_DMVR
@@ -1100,6 +1103,28 @@ void InterPrediction::xSubPuMC( PredictionUnit& pu, PelUnitBuf& predBuf, const R
   {
     m_subPuMC = false;
     pu.cu->affine = isAffine;
+#if JVET_AG0276_LIC_BDOF_BDMVR && JVET_AG0276_NLIC
+    if (pu.cu->altLMFlag)
+    {
+      for (int comp = 0; comp < MAX_NUM_COMPONENT; comp++)
+      {
+        ComponentID compID = (ComponentID)comp;
+        if (!luma && isLuma(compID))
+        {
+          continue;
+        }
+        if (!chroma && isChroma(compID))
+        {
+          continue;
+        }
+
+        int scale = pu.cu->altLMParaUnit.scale[comp];
+        int shift = 5;
+        int offset = pu.cu->altLMParaUnit.offset[comp];
+        predBuf.bufs[comp].linearTransform(scale, shift, offset, true, pu.cu->slice->clpRng(compID));
+      }
+    }
+#endif
     return;
   }
 #endif
@@ -1635,7 +1660,11 @@ void InterPrediction::xPredInterUni(const PredictionUnit &pu, const RefPicList &
       continue;
     }
 #if MULTI_PASS_DMVR
+#if JVET_AG0276_LIC_BDOF_BDMVR
+    if (compID != COMPONENT_Y && bioApplied && isBdofMvRefine && pu.cu->licFlag == false)
+#else
     if (compID != COMPONENT_Y && bioApplied && isBdofMvRefine)
+#endif
     {
       continue;
     }
@@ -1751,7 +1780,11 @@ void InterPrediction::xPredInterBiSubPuBDOF(PredictionUnit &pu, PelUnitBuf &pcYu
       }
       else
 #endif
+#if JVET_AG0276_LIC_BDOF_BDMVR
+      if (pu.bdmvrRefine == true && pu.cu->licFlag == false)
+#else
       if (pu.bdmvrRefine)
+#endif
       {
         bioDx2 = bioDx;
         bioDy2 = bioDy;
@@ -1784,7 +1817,11 @@ void InterPrediction::xPredInterBiSubPuBDOF(PredictionUnit &pu, PelUnitBuf &pcYu
       }
       else
 #endif
+#if JVET_AG0276_LIC_BDOF_BDMVR
+      if (pu.bdmvrRefine == true && pu.cu->licFlag == false)
+#else
       if (pu.bdmvrRefine)
+#endif
       {
         const int bdmvrSubPuIdx = (yStart >> DMVR_SUBCU_HEIGHT_LOG2) * DMVR_SUBPU_STRIDE + (xStart >> DMVR_SUBCU_WIDTH_LOG2);
         subPu.mv[0] = m_bdmvrSubPuMvBuf[0][bdmvrSubPuIdx] + bioMv;
@@ -2044,6 +2081,24 @@ void InterPrediction::xPredInterBiBDMVR(PredictionUnit &pu, PelUnitBuf &pcYuvPre
       }
     }
 
+#if JVET_AG0276_NLIC
+    if (bioApplied && pu.cu->altLMFlag)
+    {
+#if JVET_AG0276_LIC_BDOF_BDMVR
+      if (m_subPuMC)
+      {
+        bioApplied = true;
+      }
+      else
+      {
+#endif
+        bioApplied = false;
+#if JVET_AG0276_LIC_BDOF_BDMVR
+      }
+#endif
+    }
+#endif
+
     if (bioApplied && pu.ciipFlag)
     {
       bioApplied = false;
@@ -2636,6 +2691,19 @@ void InterPrediction::xPredInterBiBDMVR2(PredictionUnit &pu, PelUnitBuf &pcYuvPr
           bioApplied = true;
         }
       }
+#if JVET_AG0276_NLIC
+      if (bioApplied && pu.cu->altLMFlag)
+      {
+#if JVET_AG0276_LIC_BDOF_BDMVR
+        if (m_subPuMC)
+        {
+          bioApplied = true;
+        }
+        else
+#endif
+        bioApplied = false;
+      }
+#endif
     if (bioApplied && pu.ciipFlag)
     {
       bioApplied = false;
@@ -2778,7 +2846,11 @@ void InterPrediction::xPredInterBiBDMVR2(PredictionUnit &pu, PelUnitBuf &pcYuvPr
       }
       else
 #endif
+#if JVET_AG0276_LIC_BDOF_BDMVR
+      if (pu.bdmvrRefine == true && pu.cu->licFlag == false)
+#else
       if (pu.bdmvrRefine)
+#endif
       {
         const int bdmvrSubPuIdx = (yStart >> DMVR_SUBCU_HEIGHT_LOG2) * DMVR_SUBPU_STRIDE + (xStart >> DMVR_SUBCU_WIDTH_LOG2);
         subPu.mv[0] = m_bdmvrSubPuMvBuf[0][bdmvrSubPuIdx] + bioMv;
@@ -2955,7 +3027,11 @@ void InterPrediction::xPredInterBi(PredictionUnit &pu, PelUnitBuf &pcYuvPred, co
   const PPS   &pps = *pu.cs->pps;
   const Slice &slice = *pu.cs->slice;
 #if MULTI_PASS_DMVR
+#if JVET_AG0276_LIC_BDOF_BDMVR
+  if (pu.bdmvrRefine && pu.cu->licFlag == false)
+#else
   if ( pu.bdmvrRefine )
+#endif
   {
     if (yuvPredTmp && (pu.lwidth() > DMVR_SUBCU_WIDTH || pu.lheight() > DMVR_SUBCU_HEIGHT)) // pre-do MC for yuvPredTmp to avoid MC for yuvPredTmp within the subblock loop
     {
@@ -3045,6 +3121,16 @@ void InterPrediction::xPredInterBi(PredictionUnit &pu, PelUnitBuf &pcYuvPred, co
     return;
   }
 #endif
+#if JVET_AG0276_LIC_BDOF_BDMVR
+  if (pu.bdmvrRefine == true)
+  {
+    if (pu.amvpMergeModeFlag[0] == false && pu.amvpMergeModeFlag[1] == false)
+    {
+      pu.mv[0] = m_bdmvrSubPuMvBuf[REF_PIC_LIST_0][0];
+      pu.mv[1] = m_bdmvrSubPuMvBuf[REF_PIC_LIST_1][0];
+    }
+  }
+#endif
 #if !INTER_RM_SIZE_CONSTRAINTS
 #if ENABLE_OBMC
   if (pu.cu->isobmcMC == false)
@@ -3060,7 +3146,7 @@ void InterPrediction::xPredInterBi(PredictionUnit &pu, PelUnitBuf &pcYuvPred, co
   bool bioApplied = false;
   if (pu.cs->sps->getBDOFEnabledFlag() && (!pu.cs->picHeader->getDisBdofFlag()))
   {
-#if INTER_LIC
+#if INTER_LIC && !JVET_AG0276_LIC_BDOF_BDMVR
     if (pu.cu->affine || m_subPuMC || pu.cu->licFlag)
 #else
     if (pu.cu->affine || m_subPuMC)
@@ -3087,6 +3173,13 @@ void InterPrediction::xPredInterBi(PredictionUnit &pu, PelUnitBuf &pcYuvPred, co
       }
     }
 
+#if JVET_AG0276_NLIC && !JVET_AG0276_LIC_BDOF_BDMVR
+    if (bioApplied && pu.cu->altLMFlag)
+    {
+      bioApplied = false;
+    }
+#endif
+
     if (bioApplied && pu.ciipFlag)
     {
       bioApplied = false;
@@ -3263,6 +3356,13 @@ void InterPrediction::xPredInterBi(PredictionUnit &pu, PelUnitBuf &pcYuvPred, co
                            CPelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvPred[1][0], pcYuvPred.Y()), PelBuf(m_acYuvPred[1][1], pcYuvPred.Cb()), PelBuf(m_acYuvPred[1][2], pcYuvPred.Cr())) );
   const bool lumaOnly   = luma && !chroma;
   const bool chromaOnly = !luma && chroma;
+#if JVET_AG0276_LIC_BDOF_BDMVR
+  if (bioApplied == true && pu.cu->licFlag == true)
+  {
+    xLicCompAdjBdof(pu, pcYuvPred, lumaOnly, chromaOnly);
+  }
+  else
+#endif
 #if JVET_AD0213_LIC_IMP
   xLicCompAdj(pu, pcYuvPred, lumaOnly, chromaOnly);
 #endif
@@ -3395,6 +3495,32 @@ void InterPrediction::xPredInterBi(PredictionUnit &pu, PelUnitBuf &pcYuvPred, co
           slice.getSPS()->getBitDepths(), slice.clpRngs(), bioApplied, lumaOnly, chromaOnly, yuvPredTmp );
 #endif
 #endif
+#if JVET_AG0276_NLIC
+#if JVET_AG0276_LIC_BDOF_BDMVR
+      if (pu.cu->altLMFlag && !bioApplied)
+#else
+      if (pu.cu->altLMFlag)
+#endif
+      {
+        for (int comp = 0; comp < MAX_NUM_COMPONENT; comp++)
+        {
+          ComponentID compID = (ComponentID)comp;
+          if (!luma && isLuma(compID))
+          {
+            continue;
+          }
+          if (!chroma && isChroma(compID))
+          {
+            continue;
+          }
+
+          int scale = pu.cu->altLMParaUnit.scale[comp];
+          int shift = 5;
+          int offset = pu.cu->altLMParaUnit.offset[comp];
+          pcYuvPred.bufs[comp].linearTransform(scale, shift, offset, true, pu.cu->slice->clpRng(compID));
+        }
+      }
+#endif
 #if JVET_AD0213_LIC_IMP
       if (m_storeBeforeLIC)
       {
@@ -3459,6 +3585,120 @@ void InterPrediction::xPredInterBi(PredictionUnit &pu, PelUnitBuf &pcYuvPred, co
   }
 }
 
+#if JVET_AG0276_NLIC
+void InterPrediction::xPredWoRefinement(PredictionUnit& pu, PelUnitBuf &pcYuvPred, const bool luma, const bool chroma)
+{
+  if (xCheckIdenticalMotion(pu))
+  {
+    xPredInterUni(pu, REF_PIC_LIST_0, pcYuvPred, false, false, luma, chroma);
+    return;
+  }
+
+  const PPS   &pps = *pu.cs->pps;
+  const Slice &slice = *pu.cs->slice;
+  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);
+    m_iRefListIdx = refList;
+
+    PelUnitBuf pcMbBuf = (pu.chromaFormat == CHROMA_400 ?
+      PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvPred[refList][0], pcYuvPred.Y())) :
+      PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvPred[refList][0], pcYuvPred.Y()), PelBuf(m_acYuvPred[refList][1], pcYuvPred.Cb()), PelBuf(m_acYuvPred[refList][2], pcYuvPred.Cr())));
+
+    if (pu.refIdx[0] >= 0 && pu.refIdx[1] >= 0)
+    {
+      xPredInterUni(pu, eRefPicList, pcMbBuf, true, false, luma, chroma);
+    }
+    else
+    {
+      if (((pps.getUseWP() && slice.getSliceType() == P_SLICE) || (pps.getWPBiPred() && slice.getSliceType() == B_SLICE)))
+      {
+        xPredInterUni(pu, eRefPicList, pcMbBuf, true, false, luma, chroma);
+      }
+      else
+      {
+        xPredInterUni(pu, eRefPicList, pcMbBuf, false, false, luma, chroma);
+      }
+    }
+  }
+  CPelUnitBuf srcPred0 = (pu.chromaFormat == CHROMA_400 ?
+    CPelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvPred[0][0], pcYuvPred.Y())) :
+    CPelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvPred[0][0], pcYuvPred.Y()), PelBuf(m_acYuvPred[0][1], pcYuvPred.Cb()), PelBuf(m_acYuvPred[0][2], pcYuvPred.Cr())));
+  CPelUnitBuf srcPred1 = (pu.chromaFormat == CHROMA_400 ?
+    CPelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvPred[1][0], pcYuvPred.Y())) :
+    CPelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvPred[1][0], pcYuvPred.Y()), PelBuf(m_acYuvPred[1][1], pcYuvPred.Cb()), PelBuf(m_acYuvPred[1][2], pcYuvPred.Cr())));
+  const bool lumaOnly = luma && !chroma;
+  const bool chromaOnly = !luma && chroma;
+  if (pps.getWPBiPred() && slice.getSliceType() == B_SLICE && pu.cu->bcwIdx == BCW_DEFAULT)
+  {
+    xWeightedPredictionBi(pu, srcPred0, srcPred1, pcYuvPred, m_maxCompIDToPred, lumaOnly, chromaOnly);
+  }
+  else if (pps.getUseWP() && slice.getSliceType() == P_SLICE)
+  {
+    xWeightedPredictionUni(pu, srcPred0, REF_PIC_LIST_0, pcYuvPred, -1, m_maxCompIDToPred, lumaOnly, chromaOnly);
+  }
+  else
+  {
+#if JVET_Z0136_OOB
+    bool isOOB[2] = { false,false };
+    if (pu.interDir == 3)
+    {
+      if (pu.cu->affine && pu.mergeType != MRG_TYPE_SUBPU_ATMVP)  // affine
+      {
+        bool *pMcMask0 = pu.cs->mcMask[0];
+        bool *pMcMask1 = pu.cs->mcMask[1];
+        for (int h = 0; h < (int)pu.lumaSize().height && (!isOOB[0] || !isOOB[1]); h++)
+        {
+          for (int w = 0; w < (int)pu.lumaSize().width && (!isOOB[0] || !isOOB[1]); w++)
+          {
+            isOOB[0] |= pMcMask0[w];
+            isOOB[1] |= pMcMask1[w];
+          }
+          pMcMask0 += (int)pu.lumaSize().width;
+          pMcMask1 += (int)pu.lumaSize().width;
+        }
+      }
+      else
+      {
+#if JVET_AA0146_WRAP_AROUND_FIX
+        if (pu.cu->slice->getRefPic(REF_PIC_LIST_0, pu.refIdx[0])->isWrapAroundEnabled(pu.cs->pps))
+        {
+          isOOB[0] = false;
+        }
+        else
+#endif
+          isOOB[0] = isMvOOB(pu.mv[0], pu.Y().topLeft(), pu.lumaSize(), pu.cu->slice->getSPS(), pu.cu->slice->getPPS(), pu.cs->mcMask[0], pu.cs->mcMaskChroma[0]);
+#if JVET_AA0146_WRAP_AROUND_FIX
+        if (pu.cu->slice->getRefPic(REF_PIC_LIST_1, pu.refIdx[1])->isWrapAroundEnabled(pu.cs->pps))
+        {
+          isOOB[1] = false;
+        }
+        else
+#endif
+          isOOB[1] = isMvOOB(pu.mv[1], pu.Y().topLeft(), pu.lumaSize(), pu.cu->slice->getSPS(), pu.cu->slice->getPPS(), pu.cs->mcMask[1], pu.cs->mcMaskChroma[1]);
+      }
+      xWeightedAverage(false/*isBdofMvRefine*/, 0/*bioSubPuOffset*/, pu, srcPred0, srcPred1, pcYuvPred, slice.getSPS()->getBitDepths(), slice.clpRngs(), false, lumaOnly, chromaOnly, NULL, pu.cs->mcMask, pcYuvPred.Y().width, pu.cs->mcMaskChroma, pu.chromaFormat == CHROMA_400 ? 0 : pcYuvPred.Cb().width, isOOB);
+    }
+    else
+    {
+      xWeightedAverage(false/*isBdofMvRefine*/, 0/*bioSubPuOffset*/, pu, srcPred0, srcPred1, pcYuvPred, slice.getSPS()->getBitDepths(), slice.clpRngs(), false, lumaOnly, chromaOnly, NULL, pu.cs->mcMask, pcYuvPred.Y().width, pu.cs->mcMaskChroma, pu.chromaFormat == CHROMA_400 ? 0 : pcYuvPred.Cb().width, isOOB);
+    }
+#else
+#if MULTI_PASS_DMVR
+    xWeightedAverage(false/*isBdofMvRefine*/, 0/*bioSubPuOffset*/, pu, srcPred0, srcPred1, pcYuvPred, slice.getSPS()->getBitDepths(), slice.clpRngs(), false, lumaOnly, chromaOnly);
+#else
+    xWeightedAverage(pu, srcPred0, srcPred1, pcYuvPred, slice.getSPS()->getBitDepths(), slice.clpRngs(), false, lumaOnly, chromaOnly);
+#endif
+#endif
+  }
+}
+#endif
+
 void InterPrediction::xPredInterBlk ( const ComponentID& compID, const PredictionUnit& pu, const Picture* refPic, const Mv& _mv, PelUnitBuf& dstPic, const bool& bi, const ClpRng& clpRng
                                      , const bool& bioApplied
                                      , bool isIBC
@@ -3480,6 +3720,140 @@ void InterPrediction::xPredInterBlk ( const ComponentID& compID, const Predictio
 #endif
                                     )
 {
+#if JVET_AG0276_LIC_BDOF_BDMVR
+  if (bioApplied == true && pu.cu->licFlag == true && isAML == false && isIBC == false && fastOBMC == false && bilinearMC == false)
+  {
+    int filterIdx = 0;
+    JVET_J0090_SET_REF_PICTURE(refPic, compID);
+    const ChromaFormat  chFmt = pu.chromaFormat;
+    const bool          rndRes = !bi;
+    int shiftHor = MV_FRACTIONAL_BITS_INTERNAL + ::getComponentScaleX(compID, chFmt);
+    int shiftVer = MV_FRACTIONAL_BITS_INTERNAL + ::getComponentScaleY(compID, chFmt);
+
+    bool  wrapRef = false;
+    Mv    mv(_mv);
+    if (!isIBC && refPic->isWrapAroundEnabled(pu.cs->pps))
+    {
+      wrapRef = wrapClipMv(mv, pu.blocks[0].pos(), pu.blocks[0].size(), pu.cs->sps, pu.cs->pps);
+    }
+
+    bool useAltHpelIf = pu.cu->imv == IMV_HPEL;
+    int xFrac = mv.hor & ((1 << shiftHor) - 1);
+    int yFrac = mv.ver & ((1 << shiftVer) - 1);
+    PelBuf & dstBuf = dstPic.bufs[compID];
+    unsigned width = dstBuf.width;
+    unsigned height = dstBuf.height;
+    CPelBuf refBuf;
+    Position offset = pu.blocks[compID].pos().offset(mv.getHor() >> shiftHor, mv.getVer() >> shiftVer);
+    int refBufExtendSize = 0;
+    if (bioApplied && compID == COMPONENT_Y)
+    {
+      refBufExtendSize = ((BIO_EXTEND_SIZE + 1) << 1);  // trick to use SIMD filter
+      offset.x -= (BIO_EXTEND_SIZE + 1);
+      offset.y -= (BIO_EXTEND_SIZE + 1);
+    }
+    if (dmvrWidth)
+    {
+      refBuf = refPic->getRecoBuf(CompArea(compID, chFmt, offset, Size(dmvrWidth + refBufExtendSize, dmvrHeight + refBufExtendSize)), wrapRef);
+    }
+    else
+    {
+      refBuf = refPic->getRecoBuf(CompArea(compID, chFmt, offset, Size(pu.blocks[compID].width + refBufExtendSize, pu.blocks[compID].height + refBufExtendSize)), wrapRef);
+    }
+
+    int  backupWidth = width;
+    int  backupHeight = height;
+    Pel *backupDstBufPtr = dstBuf.buf;
+    int  backupDstBufStride = dstBuf.stride;
+
+    if (bioApplied && compID == COMPONENT_Y)
+    {
+      backupWidth += ((BIO_EXTEND_SIZE + 1) << 1);
+      backupHeight += ((BIO_EXTEND_SIZE + 1) << 1);
+      dstBuf.stride = backupWidth;
+      dstBuf.buf = m_filteredBlockTmp[2 + m_iRefListIdx][compID];
+    }
+    if (yFrac == 0)
+    {
+      m_if.filterHor(compID, (Pel*)refBuf.buf, refBuf.stride, dstBuf.buf, dstBuf.stride, backupWidth, backupHeight, xFrac, rndRes, chFmt, clpRng, filterIdx, bilinearMC, useAltHpelIf);
+    }
+    else if (xFrac == 0)
+    {
+      m_if.filterVer(compID, (Pel*)refBuf.buf, refBuf.stride, dstBuf.buf, dstBuf.stride, backupWidth, backupHeight, yFrac, true, rndRes, chFmt, clpRng, filterIdx, bilinearMC, useAltHpelIf);
+    }
+    else
+    {
+#if SIMD_4x4_12 && defined(TARGET_SIMD_X86)
+      if (compID == COMPONENT_Y
+        && backupWidth == 4
+        && backupHeight == 4
+        && !((xFrac == 8 || yFrac == 8) && useAltHpelIf)
+        && dmvrWidth == 0                                  
+        )
+        m_if.filter4x4(clpRng, (Pel*)refBuf.buf, refBuf.stride, dstBuf.buf, dstBuf.stride, xFrac, yFrac, rndRes);
+      else
+      {
+#endif
+        PelBuf tmpBuf = dmvrWidth ? PelBuf(m_filteredBlockTmp[0][compID], Size(dmvrWidth, dmvrHeight)) : PelBuf(m_filteredBlockTmp[0][compID], pu.blocks[compID]);
+        if (dmvrWidth == 0)
+        {
+          tmpBuf.stride = dstBuf.stride;
+        }
+#if MULTI_PASS_DMVR || SAMPLE_BASED_BDOF
+        if (bioApplied && compID == COMPONENT_Y)
+        {
+          tmpBuf = PelBuf(m_filteredBlockTmp[0][compID], Size(backupWidth, backupWidth));
+          tmpBuf.stride = dstBuf.stride;
+        }
+#endif
+        int vFilterSize = isLuma(compID) ? NTAPS_LUMA(0) : NTAPS_CHROMA;
+        if (isLuma(compID) && filterIdx == 1)
+        {
+          vFilterSize = NTAPS_BILINEAR;
+        }
+        m_if.filterHor(compID, (Pel*)refBuf.buf - ((vFilterSize >> 1) - 1) * refBuf.stride, refBuf.stride, tmpBuf.buf, tmpBuf.stride, backupWidth, backupHeight + vFilterSize - 1, xFrac, false, chFmt, clpRng, filterIdx, bilinearMC, useAltHpelIf);
+        JVET_J0090_SET_CACHE_ENABLE(false);
+        m_if.filterVer(compID, (Pel*)tmpBuf.buf + ((vFilterSize >> 1) - 1) * tmpBuf.stride, tmpBuf.stride, dstBuf.buf, dstBuf.stride, backupWidth, backupHeight, yFrac, false, rndRes, chFmt, clpRng, filterIdx, bilinearMC, useAltHpelIf);
+#if SIMD_4x4_12 && defined(TARGET_SIMD_X86)
+      }
+#endif
+    }
+    JVET_J0090_SET_CACHE_ENABLE((srcPadStride == 0) && (bioApplied == false));
+
+    if (bioApplied && compID == COMPONENT_Y)
+    {
+      dstBuf.buf = backupDstBufPtr;
+      dstBuf.stride = backupDstBufStride;
+    }
+    if (m_storeBeforeLIC)
+    {
+      UnitArea localUnitArea(chFmt, Area(0, 0, pu.lumaSize().width, pu.lumaSize().height));
+      PelUnitBuf predBeforeLICBuffer = m_acPredBeforeLICBuffer[m_iRefListIdx].getBuf(localUnitArea);
+      predBeforeLICBuffer.bufs[compID].copyFrom(dstBuf);
+      if (compID == COMPONENT_Y)
+      {
+        const int realSrcBufStride = pu.lwidth() + ((BIO_EXTEND_SIZE + 1) << 1);
+        const int realSrcBufStart = (BIO_EXTEND_SIZE + 1) * (realSrcBufStride + 1);
+        for (int y = 0; y < predBeforeLICBuffer.bufs[compID].height; y++)
+        {
+          for (int x = 0; x < predBeforeLICBuffer.bufs[compID].width; x++)
+          {
+            const int curSrcIdx = x + y * predBeforeLICBuffer.bufs[compID].stride;
+            const int realSrcIdx = x + y * realSrcBufStride + realSrcBufStart;
+            *(predBeforeLICBuffer.bufs[compID].buf + curSrcIdx) = *(m_filteredBlockTmp[2 + m_iRefListIdx][compID] + realSrcIdx);
+          }
+        }
+      }
+    }
+    xGetSublkTemplateAndRef(*pu.cu, compID, *refPic, _mv, pu.blocks[compID].width, pu.blocks[compID].height, 0, 0, m_numTemplate[compID], m_pcLICRefLeftTemplate[m_iRefListIdx][compID], m_pcLICRefAboveTemplate[m_iRefListIdx][compID], m_pcLICRecLeftTemplate[compID], m_pcLICRecAboveTemplate[compID], (m_iRefListIdx == 0 ? true : false), true);
+
+    if (m_iRefListIdx == 0)
+    {
+      m_fillLicTpl[compID] = true;
+    }
+    return;
+  }
+#endif
 #if JVET_W0090_ARMC_TM || JVET_Z0056_GPM_SPLIT_MODE_REORDERING || JVET_Z0061_TM_OBMC
   int filterIdx = 0;
 #if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
@@ -3936,6 +4310,10 @@ void InterPrediction::xPredInterBlk ( const ComponentID& compID, const Predictio
 #if JVET_W0090_ARMC_TM
           if (isAML)
           {
+#if JVET_AG0276_NLIC
+            if (!m_skipDoLic)
+            {
+#endif
             if (m_iRefListIdx == 0)
             {
               m_numTemplate[compID][0] = 0;
@@ -3945,6 +4323,9 @@ void InterPrediction::xPredInterBlk ( const ComponentID& compID, const Predictio
             xGetSublkTemplateAndRef(*pu.cu, compID, *refPic, mvCurr, pu.blocks[compID].width, pu.blocks[compID].height, 0, 0, m_numTemplate[compID], m_pcLICRefLeftTemplate[m_iRefListIdx][compID], m_pcLICRefAboveTemplate[m_iRefListIdx][compID], m_pcLICRecLeftTemplate[compID], m_pcLICRecAboveTemplate[compID], (m_iRefListIdx == 0 ? true : false), true, &scalingRatio);
 #else
             xGetSublkTemplateAndRef(*pu.cu, compID, *refPic, mvCurr, pu.blocks[compID].width, pu.blocks[compID].height, 0, 0, m_numTemplate[compID], m_pcLICRefLeftTemplate[m_iRefListIdx][compID], m_pcLICRefAboveTemplate[m_iRefListIdx][compID], m_pcLICRecLeftTemplate[compID], m_pcLICRecAboveTemplate[compID], (m_iRefListIdx == 0 ? true : false), true);
+#endif
+#if JVET_AG0276_NLIC
+            }
 #endif
           }
           else
@@ -5419,13 +5800,36 @@ void InterPrediction::xPredAffineBlk(const ComponentID &compID, const Prediction
     PelBuf &dstBuf = dstPic.bufs[compID];
     int LICshift = 0, scale = 0, offset = 0;
 #if !JVET_AD0213_LIC_IMP
-    xGetLICParamGeneral(*pu.cu, compID, numTemplate, refLeftTemplate, refAboveTemplate, recLeftTemplate, recAboveTemplate, LICshift, scale, offset);
+#if JVET_AG0276_LIC_SLOPE_ADJUST
+    int midVal[1] = {0};
+#if JVET_AE0078_IBC_LIC_EXTENSION
+    xGetLICParamGeneral(*pu.cu, compID, numTemplate, refLeftTemplate, refAboveTemplate, recLeftTemplate, recAboveTemplate, LICshift, scale, offset, nullptr, nullptr, nullptr, nullptr, midVal);
+#else
+    xGetLICParamGeneral(*pu.cu, compID, numTemplate, refLeftTemplate, refAboveTemplate, recLeftTemplate, recAboveTemplate, LICshift, scale, offset, midVal);
+#endif
+    xUpdateLicModel(scale, offset, LICshift, midVal[0], pu.cu->licDelta);
+#else
+    xGetLICParamGeneral(*pu.cu, compID, numTemplate, refLeftTemplate, refAboveTemplate, recLeftTemplate, recAboveTemplate, LICshift, scale, offset);
+#endif
 #endif
 
     const ClpRng& clpRng = pu.cu->cs->slice->clpRng(compID);
 #if JVET_AD0213_LIC_IMP
     if (!bi)
     {
+#if JVET_AG0276_LIC_SLOPE_ADJUST
+      if (pu.cu->licFlag)
+      {
+        int midVal[1] = {0};
+#if JVET_AE0078_IBC_LIC_EXTENSION
+        xGetLICParamGeneral(*pu.cu, compID, numTemplate, refLeftTemplate, refAboveTemplate, recLeftTemplate, recAboveTemplate, LICshift, scale, offset, nullptr, nullptr, nullptr, nullptr, midVal);
+#else
+        xGetLICParamGeneral(*pu.cu, compID, numTemplate, refLeftTemplate, refAboveTemplate, recLeftTemplate, recAboveTemplate, LICshift, scale, offset, midVal);
+#endif
+        xUpdateLicModel(scale, offset, LICshift, midVal[0], pu.cu->licDelta);
+      }
+      else
+#endif
       xGetLICParamGeneral(*pu.cu, compID, numTemplate, refLeftTemplate, refAboveTemplate, recLeftTemplate, recAboveTemplate, LICshift, scale, offset);
       if (!m_isAddHypMC)
       {
@@ -5542,6 +5946,12 @@ void InterPrediction::applyBiOptFlow(const PredictionUnit &pu, const CPelUnitBuf
   {
     iteIdx = 1;
   }
+#if JVET_AG0276_LIC_BDOF_BDMVR
+  if (pu.cu->licFlag)
+  {
+    iteIdx = 0;
+  }
+#endif
   int bdofSubPuAreaThre = (iter == iteIdx) ? ((m_subPuMC == true) ? BDOF_SUBPU_AREA_THRESHOLDAFFINE0 : BDOF_SUBPU_AREA_THRESHOLD0) : ((m_subPuMC == true) ? BDOF_SUBPU_AREA_THRESHOLD2 : BDOF_SUBPU_AREA_THRESHOLD1);
 #else
   int bdofSubPuAreaThre = (iter == 0) ? BDOF_SUBPU_AREA_THRESHOLD0 : ((m_subPuMC == true) ? BDOF_SUBPU_AREA_THRESHOLD2 : BDOF_SUBPU_AREA_THRESHOLD1);
@@ -5549,9 +5959,17 @@ void InterPrediction::applyBiOptFlow(const PredictionUnit &pu, const CPelUnitBuf
 #else
   int bdofSubPuAreaThre = (iter == 0) ? BDOF_SUBPU_AREA_THRESHOLD0 : BDOF_SUBPU_AREA_THRESHOLD1;
 #endif
+#if JVET_AG0276_LIC_BDOF_BDMVR
+  if ((!m_subPuMC && isBdofMvRefine && pu.bdmvrRefine && pu.cu->licFlag == false && (ww*hh < bdofSubPuAreaThre)) || (!m_subPuMC && !isBdofMvRefine && ((width % 8 == 4) && (width != 4))))
+#else
   if ((isBdofMvRefine && pu.bdmvrRefine && (ww*hh < bdofSubPuAreaThre)) || (!isBdofMvRefine && ((width % 8 == 4) && (width != 4) )))
+#endif
+#else
+#if JVET_AG0276_LIC_BDOF_BDMVR
+    if ((!m_subPuMC && isBdofMvRefine && pu.bdmvrRefine && pu.cu->licFlag == false && (ww*hh < BDOF_SUBPU_AREA_THRE)) || (!m_subPuMC && !isBdofMvRefine && ((width % 8 == 4) && (width != 4))))
 #else
     if ((isBdofMvRefine && pu.bdmvrRefine && (ww*hh < BDOF_SUBPU_AREA_THRESHOLD)) || (!isBdofMvRefine && ((width % 8 == 4) && (width != 4) )))
+#endif
 #endif
     {
       scaleBDOF = 1;
@@ -5565,7 +5983,11 @@ void InterPrediction::applyBiOptFlow(const PredictionUnit &pu, const CPelUnitBuf
   }
 #endif
 #if JVET_AG0067_DMVR_EXTENSIONS
-  if (iter == 0 && isBdofMvRefine && !m_subPuMC)
+  if (iter == 0 && isBdofMvRefine && !m_subPuMC
+#if JVET_AG0276_LIC_BDOF_BDMVR
+    && !pu.cu->licFlag
+#endif
+    )
   {
     scaleBDOF = 4;
     scaleBDOFLog2 = 2;
@@ -5589,7 +6011,11 @@ void InterPrediction::applyBiOptFlow(const PredictionUnit &pu, const CPelUnitBuf
   {
 #if JVET_AD0195_HIGH_PRECISION_BDOF_CORE
     bool simBIOParameter = false;
+#if JVET_AG0276_LIC_BDOF_BDMVR
+    if (pu.bdmvrRefine == true && pu.cu->licFlag == false)
+#else
     if (pu.bdmvrRefine)
+#endif
     {
       g_pelBufOP.calcBIOParameterHighPrecision(srcY0, srcY1, gradX0, gradX1, gradY0, gradY1, widthG, heightG, src0Stride, src1Stride, widthG,
                                                bitDepth, m_piDotProduct1, m_piDotProduct2, m_piDotProduct3, m_piDotProduct5, m_piDotProduct6, m_dI
@@ -5608,12 +6034,20 @@ void InterPrediction::applyBiOptFlow(const PredictionUnit &pu, const CPelUnitBuf
     g_pelBufOP.calcBIOParameter(srcY0, srcY1, gradX0, gradX1, gradY0, gradY1, widthG, heightG, src0Stride, src1Stride, widthG,
                                 bitDepth, m_absGx, m_absGy, m_dIx, m_dIy, m_signGxGy, m_dI);
 #endif
+#if JVET_AG0276_LIC_BDOF_BDMVR
+    m_bdofMvRefined = (pu.cu->licFlag == false);
+#else
     m_bdofMvRefined = true;
+#endif
     int bioSubPuMvIndex = 0;
     const int bioSubPuMvIndexIncrementY = BDOF_SUBPU_STRIDE - std::max(1, (width >> BDOF_SUBPU_DIM_LOG2));
 #if JVET_AE0091_ITERATIVE_BDOF
 #if JVET_AG0067_DMVR_EXTENSIONS
+#if JVET_AG0276_LIC_BDOF_BDMVR
+    const int   bioBlockDistTh = (m_subPuMC || (iter == 2) || pu.cu->licFlag) ? ((bioDx * bioDy) << (6 - 4)) : ((bioDx * bioDy) << (6 - 4 + ((pu.cu->slice->getPPS()->getPicInitQPMinus26() + 26) >> 5)));
+#else
     const int   bioBlockDistTh = (m_subPuMC || (iter == 2)) ? ((bioDx * bioDy) << (6 - 4)) : ((bioDx * bioDy) << (6 - 4 + ((pu.cu->slice->getPPS()->getPicInitQPMinus26() + 26) >> 5)));
+#endif
 #else
     const int   bioBlockDistTh = (iter == 0) ? ((bioDx * bioDy) << (6 - 4)) : ((bioDx * bioDy) << (6 - 4));
 #endif
@@ -5730,7 +6164,11 @@ void InterPrediction::applyBiOptFlow(const PredictionUnit &pu, const CPelUnitBuf
 #endif
 #endif
 #if JVET_AG0067_DMVR_EXTENSIONS
-          if ((iter != 0) || !pu.bdmvrRefine || m_subPuMC)
+          if ((iter != 0) || !pu.bdmvrRefine || m_subPuMC
+#if JVET_AG0276_LIC_BDOF_BDMVR
+            || pu.cu->licFlag
+#endif
+            )
           {
 #endif
             if (bioDx == 4)
@@ -5775,7 +6213,11 @@ void InterPrediction::applyBiOptFlow(const PredictionUnit &pu, const CPelUnitBuf
 #endif
           continue;
         }
+#if JVET_AG0276_LIC_BDOF_BDMVR
+        if (pu.bdmvrRefine == false || pu.cu->licFlag == true)
+#else
         if (!pu.bdmvrRefine)
+#endif
         {
 #if JVET_AG0067_DMVR_EXTENSIONS
           if (iter == 0)
@@ -5881,6 +6323,16 @@ void InterPrediction::applyBiOptFlow(const PredictionUnit &pu, const CPelUnitBuf
 #endif
           continue;
         }
+#if JVET_AG0276_LIC_BDOF_BDMVR && JVET_AG0276_NLIC
+        Mv bioMv;
+        if (m_subPuMC && pu.cu->altLMFlag)
+        {
+          bioMv.hor = 0; 
+          bioMv.ver = 0;
+        }
+        else
+        {
+#endif
 #if JVET_AD0195_HIGH_PRECISION_BDOF_CORE
         int32_t sumS1 = 0, sumS2 = 0,  sumS3 = 0, sumS5 = 0, sumS6 = 0;
 #if JVET_AG0067_DMVR_EXTENSIONS
@@ -5948,7 +6400,9 @@ void InterPrediction::applyBiOptFlow(const PredictionUnit &pu, const CPelUnitBuf
 #endif
         tmpXblock = Clip3(-256, 256, tmpXblock);
         tmpYblock = Clip3(-256, 256, tmpYblock);
+#if !(JVET_AG0276_LIC_BDOF_BDMVR && JVET_AG0276_NLIC)
         Mv bioMv;
+#endif
 #if JVET_AD0195_HIGH_PRECISION_BDOF_CORE
         if (tmpXblock >= 0)
         {
@@ -5985,6 +6439,9 @@ void InterPrediction::applyBiOptFlow(const PredictionUnit &pu, const CPelUnitBuf
           bioMv.ver = (-1) * ((((-1) * tmpYblock) + 4) >> 3);
         }
 #endif
+#if JVET_AG0276_LIC_BDOF_BDMVR && JVET_AG0276_NLIC
+        }
+#endif
 #if JVET_AG0067_DMVR_EXTENSIONS
           if (iter == 0)
           {
@@ -6016,6 +6473,7 @@ void InterPrediction::applyBiOptFlow(const PredictionUnit &pu, const CPelUnitBuf
             }
           }
 #else
+
 #if JVET_AE0091_ITERATIVE_BDOF
         if (iter == 0)
         {
@@ -6527,6 +6985,12 @@ void InterPrediction::xWeightedAverage(
       pcYuvDst.addAvg(pcYuvSrc0, pcYuvSrc1, clpRngs, bioApplied);
 #endif
     }
+#if JVET_AG0276_LIC_BDOF_BDMVR
+    else if (isBdofMvRefine == true && pu.cu->licFlag == true)
+    {
+      pcYuvDst.addWeightedAvg(pcYuvSrc0, pcYuvSrc1, clpRngs, BCW_DEFAULT, true/*chromaOnly*/, false/*lumaOnly*/, mcMask, mcStride, mcMaskChroma, mcCStride, isOOB);
+    }
+#endif
     if (yuvDstTmp)
     {
       if (bioApplied)
@@ -7285,6 +7749,28 @@ void InterPrediction::motionCompensation( PredictionUnit &pu, PelUnitBuf &predBu
       else if( xCheckIdenticalMotion( pu ) )
       {
         xPredInterUni( pu, REF_PIC_LIST_0, predBuf, false, false, luma, chroma );
+#if JVET_AG0276_NLIC
+        if (pu.cu->altLMFlag)
+        {
+          for (int comp = 0; comp < MAX_NUM_COMPONENT; comp++)
+          {
+            ComponentID compID = (ComponentID)comp;
+            if (!luma && isLuma(compID))
+            {
+              continue;
+            }
+            if (!chroma && isChroma(compID))
+            {
+              continue;
+            }
+
+            int scale = pu.cu->altLMParaUnit.scale[comp];
+            int shift = 5;
+            int offset = pu.cu->altLMParaUnit.offset[comp];
+            predBuf.bufs[comp].linearTransform(scale, shift, offset, true, pu.cu->slice->clpRng(compID));
+          }
+        }
+#endif
 #if JVET_AD0213_LIC_IMP
         Slice* slice = pu.cu->slice;
         if (m_storeBeforeLIC)
@@ -7333,6 +7819,28 @@ void InterPrediction::motionCompensation( PredictionUnit &pu, PelUnitBuf &predBu
         if (m_bdofMvRefined)
         {
           xPredInterBiSubPuBDOF(pu, predBuf, luma, chroma);  // do not change the predBufWOBIO
+#if JVET_AG0276_LIC_BDOF_BDMVR && JVET_AG0276_NLIC
+          if (pu.cu->altLMFlag)
+          {
+            for (int comp = 0; comp < MAX_NUM_COMPONENT; comp++)
+            {
+              ComponentID compID = (ComponentID)comp;
+              if (!luma && isLuma(compID))
+              {
+                continue;
+              }
+              if (!chroma && isChroma(compID))
+              {
+                continue;
+              }
+
+              int scale = pu.cu->altLMParaUnit.scale[comp];
+              int shift = 5;
+              int offset = pu.cu->altLMParaUnit.offset[comp];
+              predBuf.bufs[comp].linearTransform(scale, shift, offset, true, pu.cu->slice->clpRng(compID));
+            }
+          }
+#endif
           m_bdofMvRefined = false;
         }
 #else
@@ -7430,6 +7938,10 @@ void InterPrediction::subBlockOBMC(PredictionUnit  &pu, PelUnitBuf* pDst)
   MotionInfo NeighMi = MotionInfo();
 
   int bcwIdx = pu.cu->bcwIdx;
+#if JVET_AG0276_NLIC
+  bool altLMFlag = pu.cu->altLMFlag;
+  AltLMInterUnit altLMParaUnit = pu.cu->altLMParaUnit;
+#endif
 #if JVET_AD0213_LIC_IMP
   bool licFlag = pu.cu->licFlag;
   int  licScale[2][3], licOffset[2][3];
@@ -7477,6 +7989,10 @@ void InterPrediction::subBlockOBMC(PredictionUnit  &pu, PelUnitBuf* pDst)
     {
       int      iLength = 0;
       Position curOffset = (iBlkBoundary == 0) ? Position(iSub * uiMinCUW, 0) : Position(0, iSub * uiMinCUW);
+#if JVET_AG0276_NLIC
+      subPu.cu->altLMFlag = altLMFlag;
+      subPu.cu->altLMParaUnit = altLMParaUnit;
+#endif
 #if JVET_AD0213_LIC_IMP
       Position posNeighbor;
       subPu.cu->licFlag = licFlag;
@@ -7538,6 +8054,10 @@ void InterPrediction::subBlockOBMC(PredictionUnit  &pu, PelUnitBuf* pDst)
           }
         }
 #endif
+#if JVET_AG0276_NLIC
+        subPu.cu->altLMFlag = neighPu->cu->altLMFlag;
+        subPu.cu->altLMParaUnit = neighPu->cu->secAltLMParaUnit;
+#endif
 #if JVET_AA0132_CONFIGURABLE_TM_TOOLS
         if (iOBMCmode == -1)
         {
@@ -7618,6 +8138,10 @@ void InterPrediction::subBlockOBMC(PredictionUnit  &pu, PelUnitBuf* pDst)
 #endif
   {
     pu.cu->bcwIdx = bcwIdx;
+#if JVET_AG0276_NLIC
+    pu.cu->altLMFlag = altLMFlag;
+    pu.cu->altLMParaUnit = altLMParaUnit;
+#endif
 #if JVET_AD0213_LIC_IMP
     pu.cu->licFlag = licFlag;
     for (int refList = 0; refList < 2; refList++)
@@ -7634,6 +8158,10 @@ void InterPrediction::subBlockOBMC(PredictionUnit  &pu, PelUnitBuf* pDst)
     return;
   }
 
+#if JVET_AG0276_NLIC
+  subPu.cu->altLMFlag = altLMFlag;
+  subPu.cu->altLMParaUnit = altLMParaUnit;
+#endif
 #if JVET_AD0213_LIC_IMP
   subPu.cu->licFlag = licFlag;
   for (int refList = 0; refList < 2; refList++)
@@ -7721,6 +8249,10 @@ void InterPrediction::subBlockOBMC(PredictionUnit  &pu, PelUnitBuf* pDst)
     }
   }
   pu.cu->bcwIdx = bcwIdx;
+#if JVET_AG0276_NLIC
+  pu.cu->altLMFlag = altLMFlag;
+  pu.cu->altLMParaUnit = altLMParaUnit;
+#endif
 #if JVET_AD0213_LIC_IMP
   pu.cu->licFlag = licFlag;
   for (int refList = 0; refList < 2; refList++)
@@ -8105,6 +8637,20 @@ void InterPrediction::xSubBlockMotionCompensation(PredictionUnit &pu, PelUnitBuf
   if (xCheckIdenticalMotion(pu))
   {
     xPredInterUni(pu, REF_PIC_LIST_0, pcYuvPred, false, false, true, true);
+#if JVET_AG0276_NLIC
+    if (pu.cu->altLMFlag)
+    {
+      for (int comp = 0; comp < MAX_NUM_COMPONENT; comp++)
+      {
+        ComponentID compID = (ComponentID)comp;
+
+        int scale = pu.cu->altLMParaUnit.scale[comp];
+        int shift = 5;
+        int offset = pu.cu->altLMParaUnit.offset[comp];
+        pcYuvPred.bufs[comp].linearTransform(scale, shift, offset, true, pu.cu->slice->clpRng(compID));
+      }
+    }
+#endif
   }
   else
   {
@@ -11298,6 +11844,10 @@ void  InterPrediction::sortInterMergeMMVDCandidates(PredictionUnit &pu, MergeCtx
     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 JVET_AG0276_NLIC
+    pu.cu->altLMFlag = mrgCtx.altLMFlag[fPosBaseIdx];
+    pu.cu->altLMParaUnit = mrgCtx.altLMParaNeighbours[fPosBaseIdx];
+#endif
 #if INTER_LIC
     pu.cu->licFlag = mrgCtx.licFlags[fPosBaseIdx];
 #endif
@@ -11800,6 +12350,10 @@ void  InterPrediction::sortAffineMergeCandidates(PredictionUnit pu, AffineMergeC
     pu.interDir = affMrgCtx.interDirNeighbours[pu.mergeIdx];
     pu.cu->affineType = affMrgCtx.affineType[pu.mergeIdx];
     pu.cu->bcwIdx = affMrgCtx.bcwIdx[pu.mergeIdx];
+#if JVET_AG0276_NLIC
+    pu.cu->altLMFlag = affMrgCtx.altLMFlag[pu.mergeIdx];
+    pu.cu->altLMParaUnit = affMrgCtx.altLMParaNeighbours[pu.mergeIdx];
+#endif
 #if JVET_AD0213_LIC_IMP
     pu.cu->licFlag = affMrgCtx.licFlags[pu.mergeIdx];
 #endif
@@ -12777,6 +13331,12 @@ void InterPrediction::adjustMergeCandidatesBcwIdx(PredictionUnit& pu, MergeCtx&
 #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);
 #endif
+#endif
+#if JVET_AG0276_NLIC
+        if (m_bAMLTemplateAvailabe[1])
+        {
+          m_skipDoLic = true;
+        }
 #endif
       }
       if (m_bAMLTemplateAvailabe[1])
@@ -12811,6 +13371,9 @@ void InterPrediction::adjustMergeCandidatesBcwIdx(PredictionUnit& pu, MergeCtx&
 #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
+#endif
+#if JVET_AG0276_NLIC
+        m_skipDoLic = false;
 #endif
       }
     }
@@ -12822,6 +13385,12 @@ void InterPrediction::adjustMergeCandidatesBcwIdx(PredictionUnit& pu, MergeCtx&
     uiCost = 0;
     const int origWeight = getBcwWeight(origBcwIdx, REF_PIC_LIST_0);
     bool bioApplied = pu.cs->sps->getBDOFEnabledFlag() && !pu.cs->picHeader->getDisBdofFlag() && PU::isBiPredFromDifferentDirEqDistPoc(pu) ? true : false;
+#if JVET_AG0276_NLIC
+    if (pu.cu->altLMFlag)
+    {
+      bioApplied = false;
+    }
+#endif
 #if JVET_AD0213_LIC_IMP
     if (pu.cu->licFlag)
     {
@@ -12842,6 +13411,15 @@ void InterPrediction::adjustMergeCandidatesBcwIdx(PredictionUnit& pu, MergeCtx&
         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 JVET_AG0276_NLIC
+        if (pu.cu->altLMFlag)
+        {
+          int scale = pu.cu->altLMParaUnit.scale[0];
+          int shift = 5;
+          int offset = pu.cu->altLMParaUnit.offset[0];
+          pcBufPredRefTop.Y().linearTransform(scale, shift, offset, true, pu.cu->slice->clpRng(COMPONENT_Y));
+        }
+#endif
         m_pcRdCost->setDistParam(cDistParam, pcBufPredCurTop.Y(), pcBufPredRefTop.Y(), pu.cs->sps->getBitDepth(CHANNEL_TYPE_LUMA), COMPONENT_Y, false);
         uiCost += cDistParam.distFunc(cDistParam);
       }
@@ -12850,6 +13428,15 @@ void InterPrediction::adjustMergeCandidatesBcwIdx(PredictionUnit& pu, MergeCtx&
         CPelUnitBuf srcPred0 = CPelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefLeftTemplate[0][0], pcBufPredRefLeftTranspose.Y()));
         CPelUnitBuf srcPred1 = CPelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefLeftTemplate[1][0], pcBufPredRefLeftTranspose.Y()));
         xWeightedAverageY(pu, srcPred0, srcPred1, pcBufPredRefLeftTranspose, pu.cu->slice->getSPS()->getBitDepths(), pu.cu->slice->clpRngs());
+#if JVET_AG0276_NLIC
+        if (pu.cu->altLMFlag)
+        {
+          int scale = pu.cu->altLMParaUnit.scale[0];
+          int shift = 5;
+          int offset = pu.cu->altLMParaUnit.offset[0];
+          pcBufPredRefLeftTranspose.Y().linearTransform(scale, shift, offset, true, pu.cu->slice->clpRng(COMPONENT_Y));
+        }
+#endif
         m_pcRdCost->setDistParam(cDistParam, pcBufPredCurLeft.Y(), pcBufPredRefLeftTranspose.Y(), pu.cs->sps->getBitDepth(CHANNEL_TYPE_LUMA), COMPONENT_Y, false);
         uiCost += cDistParam.distFunc(cDistParam);
       }
@@ -13151,7 +13738,10 @@ void InterPrediction::adjustMergeCandidates(PredictionUnit& pu, MergeCtx& mvpMer
 
       pairMergeCand.mvFieldNeighbours[cnt * 2].setMvField(Mv(0, 0), NOT_VALID);
       pairMergeCand.mvFieldNeighbours[cnt * 2 + 1].setMvField(Mv(0, 0), NOT_VALID);
-
+#if JVET_AG0276_NLIC
+      pairMergeCand.altLMFlag[cnt] = false;
+      pairMergeCand.altLMParaNeighbours[cnt].resetAltLinearModel();
+#endif
 #if INTER_LIC
       pairMergeCand.licFlags[cnt] = mvpMergeCandCtx.licFlags[rdCandList[0]];
 #endif
@@ -13389,108 +13979,59 @@ void InterPrediction::adjustMergeCandidates(PredictionUnit& pu, MergeCtx& mvpMer
 }
 #endif
 
-#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC
-void  InterPrediction::updateCandInTwoCandidateGroups(MergeCtx& mrgCtx, uint32_t* rdCandList, int numCandInCategory, MergeCtx mrgCtx2)
+#if JVET_AG0276_NLIC
+void InterPrediction::adjustMergeCandidates(PredictionUnit& pu, MergeCtx& mvpMergeCandCtx, AltLMMergeCtx& altLMMrgCtx, int numRetrievedMergeCand)
 {
-  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
+  MergeCtx altLMMergeCand;
+  altLMMergeCand.numValidMergeCand = 0;
+  altLMMergeCand.numCandToTestEnc = 0;
+  for (uint32_t mrgIdx = 0; mrgIdx < altLMMrgCtx.numValidMergeCand; mrgIdx++)
+  {
+    altLMMergeCand.altLMFlag[altLMMergeCand.numValidMergeCand] = true;
+    altLMMergeCand.altLMParaNeighbours[altLMMergeCand.numValidMergeCand] = altLMMrgCtx.altLMParaNeighbours[mrgIdx];
+    altLMMergeCand.licFlags[altLMMergeCand.numValidMergeCand] = false;
+    altLMMergeCand.interDirNeighbours[altLMMergeCand.numValidMergeCand] = altLMMrgCtx.interDirNeighbours[mrgIdx];
+    altLMMergeCand.mvFieldNeighbours[(altLMMergeCand.numValidMergeCand << 1) + 0] = altLMMrgCtx.mvFieldNeighbours[(mrgIdx << 1) + 0];
+    altLMMergeCand.mvFieldNeighbours[(altLMMergeCand.numValidMergeCand << 1) + 1] = altLMMrgCtx.mvFieldNeighbours[(mrgIdx << 1) + 1];
+    altLMMergeCand.useAltHpelIf[altLMMergeCand.numValidMergeCand] = altLMMrgCtx.useAltHpelIf[mrgIdx];
+    altLMMergeCand.bcwIdx[altLMMergeCand.numValidMergeCand] = altLMMrgCtx.bcwIdx[mrgIdx];
+    altLMMergeCand.addHypNeighbours[altLMMergeCand.numValidMergeCand].clear();
+    altLMMergeCand.candCost[altLMMergeCand.numValidMergeCand] = MAX_UINT64;
+
+    altLMMergeCand.numValidMergeCand++;
+    altLMMergeCand.numCandToTestEnc++;
+  }
+
+  if (mvpMergeCandCtx.numValidMergeCand + altLMMergeCand.numValidMergeCand <= 1)
+  {
+    for (uint32_t mrgIdx = 0; mrgIdx < altLMMergeCand.numValidMergeCand; mrgIdx++)
+    {
+      mvpMergeCandCtx.altLMFlag[mvpMergeCandCtx.numValidMergeCand] = altLMMergeCand.altLMFlag[mrgIdx];
+      mvpMergeCandCtx.altLMParaNeighbours[mvpMergeCandCtx.numValidMergeCand] = altLMMergeCand.altLMParaNeighbours[mrgIdx];
+      mvpMergeCandCtx.licFlags[mvpMergeCandCtx.numValidMergeCand] = altLMMergeCand.licFlags[mrgIdx];
+      mvpMergeCandCtx.interDirNeighbours[mvpMergeCandCtx.numValidMergeCand] = altLMMergeCand.interDirNeighbours[mrgIdx];
+      mvpMergeCandCtx.mvFieldNeighbours[(mvpMergeCandCtx.numValidMergeCand << 1) + 0] = altLMMergeCand.mvFieldNeighbours[(mrgIdx << 1) + 0];
+      mvpMergeCandCtx.mvFieldNeighbours[(mvpMergeCandCtx.numValidMergeCand << 1) + 1] = altLMMergeCand.mvFieldNeighbours[(mrgIdx << 1) + 1];
+      mvpMergeCandCtx.useAltHpelIf[mvpMergeCandCtx.numValidMergeCand] = altLMMergeCand.useAltHpelIf[mrgIdx];
+      mvpMergeCandCtx.bcwIdx[mvpMergeCandCtx.numValidMergeCand] = altLMMergeCand.bcwIdx[mrgIdx];
+      mvpMergeCandCtx.addHypNeighbours[mvpMergeCandCtx.numValidMergeCand] = altLMMergeCand.addHypNeighbours[mrgIdx];
+      mvpMergeCandCtx.candCost[mvpMergeCandCtx.numValidMergeCand] = altLMMergeCand.candCost[mrgIdx];
+      mvpMergeCandCtx.numValidMergeCand++;
     }
+    return;
   }
-}
-#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
+  int numCandInCategory = MAX_INT;
 
-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];
+  uint32_t   rdCandList[NUM_MERGE_CANDS + MRG_MAX_NUM_CANDS + ALT_MRG_MAX_NUM_CANDS];
+  uint32_t   candCategory[NUM_MERGE_CANDS + MRG_MAX_NUM_CANDS + ALT_MRG_MAX_NUM_CANDS];
+  Distortion candCostList[NUM_MERGE_CANDS + MRG_MAX_NUM_CANDS + ALT_MRG_MAX_NUM_CANDS];
 
-  for (uint32_t i = 0; i < MRG_MAX_NUM_CANDS; i++)
+  for (uint32_t j = 0; j < NUM_MERGE_CANDS + MRG_MAX_NUM_CANDS + ALT_MRG_MAX_NUM_CANDS; j++)
   {
-    for (uint32_t j = 0; j < MRG_MAX_NUM_CANDS; j++)
-    {
-      rdCandList[i][j] = j;
-      candCostList[i][j] = MAX_UINT;
-    }
+    rdCandList[j] = MAX_UINT;
+    candCategory[j] = MAX_UINT;
+    candCostList[j] = MAX_UINT64;
   }
 
   Distortion uiCost;
@@ -13498,144 +14039,34 @@ void  InterPrediction::adjustInterMergeCandidates(PredictionUnit &pu, MergeCtx&
   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;
-  }
+  auto origMergeIdx = pu.mergeIdx;
 
-#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)
+  PelUnitBuf pcBufPredCurTop = (PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvCurAMLTemplate[0][0], nWidth, AML_MERGE_TEMPLATE_SIZE)));
+  PelUnitBuf pcBufPredCurLeft = (PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvCurAMLTemplate[1][0], AML_MERGE_TEMPLATE_SIZE, nHeight)));
+
+  for (uint32_t uiMergeCand = 0; uiMergeCand < mvpMergeCandCtx.numValidMergeCand; 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 (mvpMergeCandCtx.numCandToTestEnc != mvpMergeCandCtx.numValidMergeCand)
     {
-      break;
+      if (uiMergeCand >= mvpMergeCandCtx.numCandToTestEnc)
+      {
+        mvpMergeCandCtx.candCost[uiMergeCand] = MAX_UINT64 - 1;
+      }
     }
-    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], nHeight, AML_MERGE_TEMPLATE_SIZE)));
 
-#if JVET_Y0128_NON_CTC
-#if !JVET_AF0190_RPR_TMP_REORDER_LIC
-    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
+    if (mvpMergeCandCtx.candCost[uiMergeCand] == MAX_UINT64)
     {
-#endif
-    getBlkAMLRefTemplate(pu, pcBufPredRefTop, pcBufPredRefLeft);
+      uiCost = 0;
 
-    if (m_bAMLTemplateAvailabe[0])
-    {
-      m_pcRdCost->setDistParam(cDistParam, pcBufPredCurTop.Y(), pcBufPredRefTop.Y(), pu.cs->sps->getBitDepth(CHANNEL_TYPE_LUMA), COMPONENT_Y, false);
+      mvpMergeCandCtx.setMergeInfo(pu, uiMergeCand);
 
-      uiCost += cDistParam.distFunc(cDistParam);
-    }
+      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)));
 
-    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 TM_MRG
-    if ((
-#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
-          pu.cs->sps->getUseTMMrgMode() &&
-#endif
-    	  pu.tmMergeFlag) || (mvpMergeCandCtx.numCandToTestEnc != mvpMergeCandCtx.numValidMergeCand && uiMergeCand > mvpMergeCandCtx.numCandToTestEnc ))
-#else
-    if ((mvpMergeCandCtx.numCandToTestEnc != mvpMergeCandCtx.numValidMergeCand && uiMergeCand > mvpMergeCandCtx.numCandToTestEnc ))
-#endif
-    {
-      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], pu.lheight(), AML_MERGE_TEMPLATE_SIZE)));
 #if JVET_Z0067_RPR_ENABLE
-#if !JVET_AF0190_RPR_TMP_REORDER_LIC
       bool bRefIsRescaled = false;
       for (uint32_t refList = 0; refList < NUM_REF_PIC_LIST_01; refList++)
       {
@@ -13647,210 +14078,361 @@ void InterPrediction::adjustMergeCandidatesInOneCandidateGroup(PredictionUnit &p
         uiCost = std::numeric_limits<Distortion>::max();
       }
       else
-#endif
       {
 #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
 
-      getBlkAMLRefTemplate(pu, pcBufPredRefTop, pcBufPredRefLeft);
-      if (m_bAMLTemplateAvailabe[0])
+#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC 
+      if (m_bAMLTemplateAvailabe[0] && !m_bAMLTemplateAvailabe[1])
       {
-        m_pcRdCost->setDistParam(cDistParam, pcBufPredCurTop.Y(), pcBufPredRefTop.Y(), pu.cs->sps->getBitDepth(CHANNEL_TYPE_LUMA), COMPONENT_Y, false);
-        uiCost += cDistParam.distFunc(cDistParam);
+        uiCost += (uiCost * nHeight) / nWidth;
       }
-      if (m_bAMLTemplateAvailabe[1])
+      if (!m_bAMLTemplateAvailabe[0] && 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
+        uiCost += (uiCost * nWidth) / nHeight;
       }
 #endif
-
     }
-    updateCandList(uiMergeCand, uiCost, numCandInCategory, rdCandList, candCostList);
+    else
+    {
+      uiCost = mvpMergeCandCtx.candCost[uiMergeCand];
+    }
+
+    updateCandList(uiMergeCand, 0, uiCost, mvpMergeCandCtx.numValidMergeCand, rdCandList, candCategory, candCostList);
   }
   pu.mergeIdx = origMergeIdx;
 
-  updateCandInOneCandidateGroup(mvpMergeCandCtx, rdCandList, applyBDMVR, mvBufBDMVR, mvBufBDMVRTmp, subRefineList, subRefineListTmp, numCandInCategory);
-}
+  MergeCtx pairMergeCand;
+  pairMergeCand.numValidMergeCand = 0;
+  pairMergeCand.numCandToTestEnc = 0;
+  bool pairAdded = false;
 
-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++)
+  if (mvpMergeCandCtx.numCandToTestEnc > 1)
   {
-    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)
+    int          cnt = 0;
+    int maxPairToBeAdded = std::min(mvpMergeCandCtx.numCandToTestEnc, std::min(numRetrievedMergeCand, mvpMergeCandCtx.numValidMergeCand));
+
+    int cand1 = 0;
+    cnt = 0;
+    for (int cand2 = 1; cand2 < std::min(maxPairToBeAdded, MRG_MAX_NUM_CANDS); cand2++)
     {
-      applyBDMVRTmp[uiMergeCand] = applyBDMVR[uiMergeCand];
-    }
-  }
-  //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 (cand1 == cand2)
+      {
+        continue;
+      }
+
+      pairMergeCand.mvFieldNeighbours[cnt * 2].setMvField(Mv(0, 0), NOT_VALID);
+      pairMergeCand.mvFieldNeighbours[cnt * 2 + 1].setMvField(Mv(0, 0), NOT_VALID);
+#if JVET_AG0276_NLIC
+      pairMergeCand.altLMFlag[cnt] = false;
+      pairMergeCand.altLMParaNeighbours[cnt].resetAltLinearModel();
+#endif
 #if INTER_LIC
-    mrgCtx.licFlags[uiMergeCand] = mrgCtxTmp.licFlags[rdCandList[uiMergeCand]];
+      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
-    mrgCtx.addHypNeighbours[uiMergeCand] = mrgCtxTmp.addHypNeighbours[rdCandList[uiMergeCand]];
-#endif
-    if (applyBDMVR)
-    {
-      applyBDMVR[uiMergeCand] = applyBDMVRTmp[rdCandList[uiMergeCand]];
-    }
-    if (mvBufBDMVR && mvBufBDMVRTmp)
-    {
-      mvBufBDMVRTmp[(uiMergeCand << 1)] = mvBufBDMVR[(rdCandList[uiMergeCand] << 1)];
-      mvBufBDMVRTmp[(uiMergeCand << 1) + 1] = mvBufBDMVR[(rdCandList[uiMergeCand] << 1) + 1];
-    }
-    if (subRefineList && subRefineListTmp)
-    {
-      subRefineList[uiMergeCand][0] = subRefineListTmp[rdCandList[uiMergeCand]][0];
-      subRefineList[uiMergeCand][1] = subRefineListTmp[rdCandList[uiMergeCand]][1];
-    }
-  }
-  if (mvBufBDMVR && mvBufBDMVRTmp)
-  {
-    for (uint32_t uiMergeCand = 0; uiMergeCand < numCandInCategory; uiMergeCand++)
-    {
-      mvBufBDMVR[(uiMergeCand << 1)] = mvBufBDMVRTmp[(uiMergeCand << 1)];
-      mvBufBDMVR[(uiMergeCand << 1) + 1] = mvBufBDMVRTmp[(uiMergeCand << 1) + 1];
-    }
-  }
-}
-#endif
+      pairMergeCand.addHypNeighbours[cnt].clear();
 #endif
 
-#if JVET_W0090_ARMC_TM || JVET_Z0056_GPM_SPLIT_MODE_REORDERING || JVET_Z0061_TM_OBMC || JVET_AA0061_IBC_MBVD || JVET_Y0058_IBC_LIST_MODIFY
-bool InterPrediction::xAMLGetCurBlkTemplate(PredictionUnit& pu, int nCurBlkWidth, int nCurBlkHeight)
-{
-  m_bAMLTemplateAvailabe[0] = xAMLIsTopTempAvailable(pu);
-  m_bAMLTemplateAvailabe[1] = xAMLIsLeftTempAvailable(pu);
-
-  if (!m_bAMLTemplateAvailabe[0] && !m_bAMLTemplateAvailabe[1])
-  {
-    return false;
-  }
-
-  /* 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));*/
-  const Picture&  currPic = *pu.cs->picture;
-  const CPelBuf recBuf = currPic.getRecoBuf(pu.cs->picture->blocks[COMPONENT_Y]);
-  std::vector<Pel>& invLUT = m_pcReshape->getInvLUT();
-
-#if JVET_Z0054_BLK_REF_PIC_REORDER
-  if(!m_fillCurTplAboveARMC)
+      // calculate average MV for L0 and L1 seperately
+      unsigned char interDir = 0;
+#if JVET_AD0213_LIC_IMP
+      bool averageUsed = false;
 #endif
-  if (m_bAMLTemplateAvailabe[0])
-  {
-    const Pel*    rec = recBuf.bufAt(pu.blocks[COMPONENT_Y].pos().offset(0, -AML_MERGE_TEMPLATE_SIZE));
-    Pel*   pcY = m_acYuvCurAMLTemplate[0][0];
-    for (int k = 0; k < nCurBlkWidth; k++)
-    {
-      for (int l = 0; l < AML_MERGE_TEMPLATE_SIZE; l++)
+      for (int refListId = 0; refListId < (pu.cu->slice->isInterB() ? 2 : 1); refListId++)
       {
-        int recVal = rec[k + l * recBuf.stride];
+        const short refIdxI = mvpMergeCandCtx.mvFieldNeighbours[rdCandList[cand1] * 2 + refListId].refIdx;
+        const short refIdxJ = mvpMergeCandCtx.mvFieldNeighbours[rdCandList[cand2] * 2 + refListId].refIdx;
 
-        if (m_pcReshape->getSliceReshaperInfo().getUseSliceReshaper() && m_pcReshape->getCTUFlag())
+        // both MVs are invalid, skip
+        if ((refIdxI == NOT_VALID) && (refIdxJ == NOT_VALID))
         {
-          recVal = invLUT[recVal];
+          continue;
         }
 
-        pcY[k + l * nCurBlkWidth] = recVal;
-      }
-    }
-#if JVET_Z0054_BLK_REF_PIC_REORDER
-    m_fillCurTplAboveARMC = true;
-#endif
-  }
+        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;
 
-#if JVET_Z0054_BLK_REF_PIC_REORDER
-  if(!m_fillCurTplLeftARMC)
-#endif
-  if (m_bAMLTemplateAvailabe[1])
-  {
-    Pel* pcY = m_acYuvCurAMLTemplate[1][0];
-    const Pel*    rec = recBuf.bufAt(pu.blocks[COMPONENT_Y].pos().offset(-AML_MERGE_TEMPLATE_SIZE, 0));
-    for (int k = 0; k < nCurBlkHeight; k++)
-    {
-      for (int l = 0; l < AML_MERGE_TEMPLATE_SIZE; l++)
-      {
-        int recVal = rec[recBuf.stride * k + l];
+          // average two MVs
+          Mv avgMv = mvI;
+          avgMv += mvJ;
+          roundAffineMv(avgMv.hor, avgMv.ver, 1);
 
-        if (m_pcReshape->getSliceReshaperInfo().getUseSliceReshaper() && m_pcReshape->getCTUFlag())
+          pairMergeCand.mvFieldNeighbours[cnt * 2 + refListId].setMvField(avgMv, refIdxI);
+#if JVET_AD0213_LIC_IMP
+          averageUsed = true;
+#endif
+        }
+        // only one MV is valid, take the only one MV
+        else if (refIdxI != NOT_VALID)
         {
-          recVal = invLUT[recVal];
+          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);
         }
+      }
 
-        pcY[AML_MERGE_TEMPLATE_SIZE * k + l] = recVal;
+      pairMergeCand.interDirNeighbours[cnt] = interDir;
+#if JVET_AD0213_LIC_IMP
+      if (averageUsed && !(((pu.cu->slice->getPOC() - pu.cu->slice->getRefPOC(REF_PIC_LIST_0, 0)) == 1) && pu.cu->slice->getPicHeader()->getMvdL1ZeroFlag()))
+      {
+        pairMergeCand.licFlags[cnt] = false;
       }
-    }
-#if JVET_Z0054_BLK_REF_PIC_REORDER
-    m_fillCurTplLeftARMC = true;
 #endif
-  }
+
+      if (interDir > 0)
+      {
+#if INTER_LIC && !JVET_AD0213_LIC_IMP
+        if (interDir == 3)
+        {
+          pairMergeCand.licFlags[cnt] = false;
+        }
+#endif
+        uint32_t mvdSimilarityThresh = 1;
+        if (!pairMergeCand.xCheckSimilarMotion(cnt, mvdSimilarityThresh))
+        {
+          if (!mvpMergeCandCtx.xCheckSimilarMotion2Lists(cnt, &pairMergeCand, mvdSimilarityThresh))
+          {
+            pairAdded = true;
+            cnt++;
+            pairMergeCand.numValidMergeCand++;
+            pairMergeCand.numCandToTestEnc++;
+            if (pairMergeCand.numValidMergeCand == MAX_PAIR_CANDS)
+            {
+              break;
+            }
+          }
 #if JVET_AD0213_LIC_IMP
-  if (!m_fillLicTpl[COMPONENT_Y])
-  {
-    const int precShift = std::max(0, pu.cu->slice->clpRng(COMPONENT_Y).bd - 12);
-    if (!precShift)
+          else
+          {
+            pairMergeCand.initMrgCand(cnt);
+          }
+#endif
+        }
+#if JVET_AD0213_LIC_IMP
+        else
+        {
+          pairMergeCand.initMrgCand(cnt);
+        }
+#endif
+      }
+    }
+
+    if (pairAdded)
     {
-      if (m_bAMLTemplateAvailabe[0])
+      for (uint32_t uiMergeCand = 0; uiMergeCand < pairMergeCand.numValidMergeCand; uiMergeCand++)
       {
-        memcpy(m_pcLICRecAboveTemplate[0], m_acYuvCurAMLTemplate[0][0], nCurBlkWidth * sizeof(Pel));
+        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, 1, uiCost, (mvpMergeCandCtx.numValidMergeCand + pairMergeCand.numValidMergeCand), rdCandList, candCategory, candCostList);
       }
+      pu.mergeIdx = origMergeIdx;
+    }
 
-      if (m_bAMLTemplateAvailabe[1])
+    if (altLMMergeCand.numValidMergeCand)
+    {
+      for (uint32_t uiMergeCand = 0; uiMergeCand < altLMMergeCand.numValidMergeCand; uiMergeCand++)
       {
-        memcpy(m_pcLICRecLeftTemplate[0], m_acYuvCurAMLTemplate[1][0], nCurBlkHeight * sizeof(Pel));
+        if (altLMMergeCand.candCost[uiMergeCand] == MAX_UINT64)
+        {
+          uiCost = 0;
+          altLMMergeCand.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 = altLMMergeCand.candCost[uiMergeCand];
+        }
+        updateCandList(uiMergeCand, 2, uiCost, (mvpMergeCandCtx.numValidMergeCand + pairMergeCand.numValidMergeCand + altLMMergeCand.numValidMergeCand), rdCandList, candCategory, candCostList);
       }
+      pu.mergeIdx = origMergeIdx;
+    }
 
-      m_fillLicTpl[COMPONENT_Y] = true;
+    Distortion cost = pu.cs->slice->getCostForARMC();
+    uint32_t   candToBeRemoved = NUM_MERGE_CANDS + MRG_MAX_NUM_CANDS + ALT_MRG_MAX_NUM_CANDS;
+    Distortion min = MAX_UINT64;
+
+    numCandInCategory = std::min(numRetrievedMergeCand, mvpMergeCandCtx.numValidMergeCand + pairMergeCand.numValidMergeCand + altLMMergeCand.numValidMergeCand);
+    for (int sizeCandList = mvpMergeCandCtx.numCandToTestEnc + pairMergeCand.numValidMergeCand + altLMMergeCand.numValidMergeCand; sizeCandList > 1; sizeCandList--)
+    {
+      min = MAX_UINT64;
+      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];
+        uint32_t   candGrp = candCategory[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)];
+          candCategory[ui] = candCategory[(ui + 1)];
+        }
+        candCostList[candToBeReplaced] = candCost;
+        rdCandList[candToBeReplaced] = rdCand;
+        candCategory[candToBeReplaced] = candGrp;
+      }
+      else
+      {
+        break;
+      }
     }
   }
-#endif
+  else
+  {
+    if (altLMMergeCand.numValidMergeCand)
+    {
+      for (uint32_t uiMergeCand = 0; uiMergeCand < altLMMergeCand.numValidMergeCand; uiMergeCand++)
+      {
+        if (altLMMergeCand.candCost[uiMergeCand] == MAX_UINT64)
+        {
+          uiCost = 0;
+          altLMMergeCand.setMergeInfo(pu, uiMergeCand);
 
-  return true;
-}
+          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)));
 
-bool InterPrediction::xAMLIsTopTempAvailable(PredictionUnit& pu)
-{
-  const CodingStructure &cs = *pu.cs;
-  Position posRT = pu.Y().topRight();
-  const PredictionUnit *puAbove = cs.getPURestricted(posRT.offset(0, -1), pu, pu.chType);
+          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 = altLMMergeCand.candCost[uiMergeCand];
+        }
+        updateCandList(uiMergeCand, 2, uiCost, (mvpMergeCandCtx.numValidMergeCand + altLMMergeCand.numValidMergeCand), rdCandList, candCategory, candCostList);
+      }
+      pu.mergeIdx = origMergeIdx;
+    }
+    numCandInCategory = std::min(numRetrievedMergeCand, mvpMergeCandCtx.numValidMergeCand + altLMMergeCand.numValidMergeCand);
+  }
 
-  return (puAbove && pu.cu != puAbove->cu);
-}
+  updateCandInThreeCandidateGroups(mvpMergeCandCtx, pairMergeCand, altLMMergeCand, rdCandList, candCategory, numCandInCategory);
 
-bool InterPrediction::xAMLIsLeftTempAvailable(PredictionUnit& pu)
-{
-  const CodingStructure &cs = *pu.cs;
-  Position posLB = pu.Y().bottomLeft();
-  const PredictionUnit *puLeft = cs.getPURestricted(posLB.offset(-1, 0), pu, pu.chType);
+  for (int idx = 0; idx < numCandInCategory; idx++)
+  {
+    mvpMergeCandCtx.candCost[idx] = candCostList[idx];
+  }
 
-  return (puLeft && pu.cu != puLeft->cu);
+  mvpMergeCandCtx.numValidMergeCand = numCandInCategory;
 }
-#endif
 
-#if JVET_W0090_ARMC_TM || JVET_AA0070_RRIBC
-void InterPrediction::updateCandList(uint32_t uiCand, Distortion uiCost, uint32_t uiMrgCandNum, uint32_t* rdCandList, Distortion* candCostList)
+void InterPrediction::updateCandList(uint32_t uiCand, uint32_t uiCandGrp, Distortion uiCost, uint32_t uiMrgCandNum, uint32_t* rdCandList, uint32_t* rdCandGrpList, Distortion* candCostList)
 {
   uint32_t i;
   uint32_t shift = 0;
@@ -13865,937 +14447,2271 @@ void InterPrediction::updateCandList(uint32_t uiCand, Distortion uiCost, uint32_
     for (i = 1; i < shift; i++)
     {
       rdCandList[uiMrgCandNum - i] = rdCandList[uiMrgCandNum - 1 - i];
+      rdCandGrpList[uiMrgCandNum - i] = rdCandGrpList[uiMrgCandNum - 1 - i];
       candCostList[uiMrgCandNum - i] = candCostList[uiMrgCandNum - 1 - i];
     }
     rdCandList[uiMrgCandNum - shift] = uiCand;
+    rdCandGrpList[uiMrgCandNum - shift] = uiCandGrp;
     candCostList[uiMrgCandNum - shift] = uiCost;
   }
 }
-#endif
 
-#if JVET_W0090_ARMC_TM
-void  InterPrediction::updateCandInfo(MergeCtx& mrgCtx, uint32_t(*RdCandList)[MRG_MAX_NUM_CANDS], int mrgCandIdx)
+void InterPrediction::updateCandInThreeCandidateGroups(MergeCtx& mrgCtx, MergeCtx mrgCtx2, MergeCtx mrgCtx3, uint32_t* rdCandList, uint32_t* rdCandGrpList, int numCandInCategory)
 {
   MergeCtx mrgCtxTmp;
-  for (uint32_t ui = 0; ui < MRG_MAX_NUM_CANDS; ++ui)
+  for (uint32_t uiMergeCand = 0; uiMergeCand < mrgCtx.numValidMergeCand; uiMergeCand++)
   {
-    mrgCtxTmp.bcwIdx[ui] = BCW_DEFAULT;
-    mrgCtxTmp.interDirNeighbours[ui] = 0;
-    mrgCtxTmp.mvFieldNeighbours[(ui << 1)].refIdx = NOT_VALID;
-    mrgCtxTmp.mvFieldNeighbours[(ui << 1) + 1].refIdx = NOT_VALID;
-    mrgCtxTmp.useAltHpelIf[ui] = false;
-#if INTER_LIC
-    mrgCtxTmp.licFlags[ui] = false;
+    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];
+    mrgCtxTmp.altLMFlag[uiMergeCand] = mrgCtx.altLMFlag[uiMergeCand];
+    mrgCtxTmp.altLMParaNeighbours[uiMergeCand] = mrgCtx.altLMParaNeighbours[uiMergeCand];
+#if INTER_LIC 
+    mrgCtxTmp.licFlags[uiMergeCand] = mrgCtx.licFlags[uiMergeCand];
 #endif
 #if MULTI_HYP_PRED
-    mrgCtxTmp.addHypNeighbours[ui].clear();
+    mrgCtxTmp.addHypNeighbours[uiMergeCand] = mrgCtx.addHypNeighbours[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)
+  //update
+  for (uint32_t uiMergeCand = 0; uiMergeCand < numCandInCategory; 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 (rdCandGrpList[uiMergeCand] == 2)
     {
-      break;
+      mrgCtx.bcwIdx[uiMergeCand] = mrgCtx3.bcwIdx[rdCandList[uiMergeCand]];
+      mrgCtx.interDirNeighbours[uiMergeCand] = mrgCtx3.interDirNeighbours[rdCandList[uiMergeCand]];
+      mrgCtx.mvFieldNeighbours[(uiMergeCand << 1)] = mrgCtx3.mvFieldNeighbours[rdCandList[uiMergeCand] << 1];
+      mrgCtx.mvFieldNeighbours[(uiMergeCand << 1) + 1] = mrgCtx3.mvFieldNeighbours[(rdCandList[uiMergeCand] << 1) + 1];
+      mrgCtx.useAltHpelIf[uiMergeCand] = mrgCtx3.useAltHpelIf[rdCandList[uiMergeCand]];
+      mrgCtx.altLMFlag[uiMergeCand] = mrgCtx3.altLMFlag[rdCandList[uiMergeCand]];
+      mrgCtx.altLMParaNeighbours[uiMergeCand] = mrgCtx3.altLMParaNeighbours[rdCandList[uiMergeCand]];
+#if INTER_LIC
+      mrgCtx.licFlags[uiMergeCand] = mrgCtx3.licFlags[rdCandList[uiMergeCand]];
+#endif
+#if MULTI_HYP_PRED
+      mrgCtx.addHypNeighbours[uiMergeCand] = mrgCtx3.addHypNeighbours[rdCandList[uiMergeCand]];
+#endif
+    }
+    else if (rdCandGrpList[uiMergeCand] == 1)
+    {
+      mrgCtx.bcwIdx[uiMergeCand] = mrgCtx2.bcwIdx[rdCandList[uiMergeCand]];
+      mrgCtx.interDirNeighbours[uiMergeCand] = mrgCtx2.interDirNeighbours[rdCandList[uiMergeCand]];
+      mrgCtx.mvFieldNeighbours[(uiMergeCand << 1)] = mrgCtx2.mvFieldNeighbours[rdCandList[uiMergeCand] << 1];
+      mrgCtx.mvFieldNeighbours[(uiMergeCand << 1) + 1] = mrgCtx2.mvFieldNeighbours[(rdCandList[uiMergeCand] << 1) + 1];
+      mrgCtx.useAltHpelIf[uiMergeCand] = mrgCtx2.useAltHpelIf[rdCandList[uiMergeCand]];
+      mrgCtx.altLMFlag[uiMergeCand] = mrgCtx2.altLMFlag[rdCandList[uiMergeCand]];
+      mrgCtx.altLMParaNeighbours[uiMergeCand] = mrgCtx2.altLMParaNeighbours[rdCandList[uiMergeCand]];
+#if INTER_LIC
+      mrgCtx.licFlags[uiMergeCand] = mrgCtx2.licFlags[rdCandList[uiMergeCand]];
+#endif
+#if MULTI_HYP_PRED
+      mrgCtx.addHypNeighbours[uiMergeCand] = mrgCtx2.addHypNeighbours[rdCandList[uiMergeCand]];
+#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 JVET_AG0276_NLIC
+      mrgCtx.altLMFlag[uiMergeCand] = mrgCtxTmp.altLMFlag[rdCandList[uiMergeCand]];
+      mrgCtx.altLMParaNeighbours[uiMergeCand] = mrgCtxTmp.altLMParaNeighbours[rdCandList[uiMergeCand]];
+#endif
+#if INTER_LIC
+      mrgCtx.licFlags[uiMergeCand] = mrgCtxTmp.licFlags[rdCandList[uiMergeCand]];
+#endif
+#if MULTI_HYP_PRED
+      mrgCtx.addHypNeighbours[uiMergeCand] = mrgCtxTmp.addHypNeighbours[rdCandList[uiMergeCand]];
+#endif
     }
+  }
+}
+#endif
+
+#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 JVET_AG0276_NLIC
+    mrgCtxTmp.altLMFlag[uiMergeCand] = mrgCtx.altLMFlag[uiMergeCand];
+    mrgCtxTmp.altLMParaNeighbours[uiMergeCand] = mrgCtx.altLMParaNeighbours[uiMergeCand];
+#endif
 #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 = ((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)
+  for (uint32_t uiMergeCand = 0; uiMergeCand < numCandInCategory; 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 (rdCandList[uiMergeCand] >= mrgCtx.numValidMergeCand)
     {
-      break;
-    }
+      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 JVET_AG0276_NLIC
+      mrgCtx.altLMFlag[uiMergeCand] = mrgCtx2.altLMFlag[rdCandList[uiMergeCand] - mrgCtx.numValidMergeCand];
+      mrgCtx.altLMParaNeighbours[uiMergeCand] = mrgCtx2.altLMParaNeighbours[rdCandList[uiMergeCand] - mrgCtx.numValidMergeCand];
+#endif
+#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
 
-    mrgCtx.bcwIdx[uiMergeCand] = mrgCtxTmp.bcwIdx[RdCandList[uiMergeCand / ADAPTIVE_SUB_GROUP_SIZE][uiMergeCand%ADAPTIVE_SUB_GROUP_SIZE]];
-    mrgCtx.interDirNeighbours[uiMergeCand] = mrgCtxTmp.interDirNeighbours[RdCandList[uiMergeCand / ADAPTIVE_SUB_GROUP_SIZE][uiMergeCand%ADAPTIVE_SUB_GROUP_SIZE]];
-    mrgCtx.mvFieldNeighbours[(uiMergeCand << 1)] = mrgCtxTmp.mvFieldNeighbours[(RdCandList[uiMergeCand / ADAPTIVE_SUB_GROUP_SIZE][uiMergeCand%ADAPTIVE_SUB_GROUP_SIZE] << 1)];
-    mrgCtx.mvFieldNeighbours[(uiMergeCand << 1) + 1] = mrgCtxTmp.mvFieldNeighbours[(RdCandList[uiMergeCand / ADAPTIVE_SUB_GROUP_SIZE][uiMergeCand%ADAPTIVE_SUB_GROUP_SIZE] << 1) + 1];
-    mrgCtx.useAltHpelIf[uiMergeCand] = mrgCtxTmp.useAltHpelIf[RdCandList[uiMergeCand / ADAPTIVE_SUB_GROUP_SIZE][uiMergeCand%ADAPTIVE_SUB_GROUP_SIZE]];
+    }
+    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 JVET_AG0276_NLIC
+      mrgCtx.altLMFlag[uiMergeCand] = mrgCtxTmp.altLMFlag[rdCandList[uiMergeCand]];
+      mrgCtx.altLMParaNeighbours[uiMergeCand] = mrgCtxTmp.altLMParaNeighbours[rdCandList[uiMergeCand]];
+#endif
 #if INTER_LIC
-    mrgCtx.licFlags[uiMergeCand] = mrgCtxTmp.licFlags[RdCandList[uiMergeCand / ADAPTIVE_SUB_GROUP_SIZE][uiMergeCand%ADAPTIVE_SUB_GROUP_SIZE]];
+      mrgCtx.licFlags[uiMergeCand] = mrgCtxTmp.licFlags[rdCandList[uiMergeCand]];
 #endif
 #if MULTI_HYP_PRED
-    mrgCtx.addHypNeighbours[uiMergeCand] = mrgCtxTmp.addHypNeighbours[RdCandList[uiMergeCand / ADAPTIVE_SUB_GROUP_SIZE][uiMergeCand%ADAPTIVE_SUB_GROUP_SIZE]];
+      mrgCtx.addHypNeighbours[uiMergeCand] = mrgCtxTmp.addHypNeighbours[rdCandList[uiMergeCand]];
 #endif
+    }
   }
 }
 #endif
-#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION 
-void InterPrediction::getBlkAMLRefTemplateSubTMVP(PredictionUnit &pu, PelUnitBuf &pcBufPredRefTop, PelUnitBuf &pcBufPredRefLeft)
-{
-  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 (xCheckIdenticalMotionSubTMVP(pu))
+void  InterPrediction::updateCandInOneCandidateGroup(MergeCtx& mrgCtx, uint32_t* rdCandList, int numCandInCategory)
+{
+  MergeCtx mrgCtxTmp;
+  for (uint32_t uiMergeCand = 0; uiMergeCand < mrgCtx.numValidMergeCand; uiMergeCand++)
   {
-    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);
-
-#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]);
-#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);
-#else
-      xPredInterBlk(COMPONENT_Y, pu, picRef, mvTop, pcBufPredRefTop,
-        false, pu.cu->slice->clpRng(COMPONENT_Y), false, false, scalingRatio, 0, 0, false, NULL, 0, true);
+    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 JVET_AG0276_NLIC
+    mrgCtxTmp.altLMFlag[uiMergeCand] = mrgCtx.altLMFlag[uiMergeCand];
+    mrgCtxTmp.altLMParaNeighbours[uiMergeCand] = mrgCtx.altLMParaNeighbours[uiMergeCand];
 #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);
-#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);
+#if INTER_LIC 
+    mrgCtxTmp.licFlags[uiMergeCand] = mrgCtx.licFlags[uiMergeCand];
 #endif
+#if MULTI_HYP_PRED
+    mrgCtxTmp.addHypNeighbours[uiMergeCand] = mrgCtx.addHypNeighbours[uiMergeCand];
 #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);
-
-#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]);
-#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);
-#else
-      xPredInterBlk(COMPONENT_Y, pu, picRef, mvLeft, pcBufPredRefLeft,
-        false, pu.cu->slice->clpRng(COMPONENT_Y), false, false, scalingRatio, 0, 0, false, NULL, 0, true);
+  }
+  //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 JVET_AG0276_NLIC
+    mrgCtx.altLMFlag[uiMergeCand] = mrgCtxTmp.altLMFlag[rdCandList[uiMergeCand]];
+    mrgCtx.altLMParaNeighbours[uiMergeCand] = mrgCtxTmp.altLMParaNeighbours[rdCandList[uiMergeCand]];
 #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);
-#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);
+    mrgCtx.licFlags[uiMergeCand] = mrgCtxTmp.licFlags[rdCandList[uiMergeCand]];
 #endif
+#if MULTI_HYP_PRED
+    mrgCtx.addHypNeighbours[uiMergeCand] = mrgCtxTmp.addHypNeighbours[rdCandList[uiMergeCand]];
 #endif
-    }
   }
-  else
+}
+#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 refList = 0; refList < NUM_REF_PIC_LIST_01; refList++)
+    for (uint32_t j = 0; j < MRG_MAX_NUM_CANDS; j++)
     {
-      if (!(pu.interDir & (1 << refList)))
-      {
-        continue;
-      }
-      RefPicList eRefPicList = (refList ? REF_PIC_LIST_1 : REF_PIC_LIST_0);
-      CHECK(pu.refIdx[refList] >= pu.cu->slice->getNumRefIdx(eRefPicList), "Invalid reference index");
+      rdCandList[i][j] = j;
+      candCostList[i][j] = MAX_UINT;
+    }
+  }
 
-      m_iRefListIdx = refList;
-      mvCurr = pu.mv[refList];
-      Mv subPelMv = mvCurr;
-      clipMv(mvCurr, pu.lumaPos(), pu.lumaSize(), *pu.cs->sps, *pu.cs->pps);
+  Distortion uiCost;
 
-      if (m_bAMLTemplateAvailabe[0])
-      {
-        Mv mvTop(0, -(AML_MERGE_TEMPLATE_SIZE << verShift));
-        mvTop += subPelMv;
+  DistParam cDistParam;
+  cDistParam.applyWeight = false;
 
-        clipMv(mvTop, pu.lumaPos(), pu.lumaSize(), *pu.cs->sps, *pu.cs->pps);
+  /*const SPS &sps = *pu.cs->sps;
+  Position puPos = pu.lumaPos();*/
+  int nWidth = pu.lumaSize().width;
+  int nHeight = pu.lumaSize().height;
 
-        PelUnitBuf pcMbBuf =
-          PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefAboveTemplate[refList][0], pcBufPredRefTop.Y()));
+  if (!xAMLGetCurBlkTemplate(pu, nWidth, nHeight))
+  {
+    return;
+  }
 
-        if (pu.interDir == 3)
-        {
-#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]);
-#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);
-#else
-          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);
+#if JVET_X0049_ADAPT_DMVR
+#if JVET_AA0093_ENHANCED_MMVD_EXTENSION
+  uint16_t origMergeIdx = pu.mergeIdx;
 #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);
+  uint8_t origMergeIdx = pu.mergeIdx;
 #endif
 #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]);
-#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);
-#else
-          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);
-#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);
-#endif
-#endif
-        }
-      }
-      if (m_bAMLTemplateAvailabe[1])
-      {
-        Mv mvLeft(-(AML_MERGE_TEMPLATE_SIZE << horShift), 0);
-        mvLeft += subPelMv;
+  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;
 
-        clipMv(mvLeft, pu.lumaPos(), pu.lumaSize(), *pu.cs->sps, *pu.cs->pps);
+    mrgCtx.setMergeInfo(pu, uiMergeCand);
+    PU::spanMotionInfo(pu, mrgCtx);
 
-        PelUnitBuf pcMbBuf =
-          PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefLeftTemplate[refList][0], pcBufPredRefLeft.Y()));
+    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], nHeight, AML_MERGE_TEMPLATE_SIZE)));
 
-        if (pu.interDir == 3)
-        {
-#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]);
-#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);
-#else
-          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
-#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]);
-#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);
-#else
-          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);
-#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);
+#if JVET_Y0128_NON_CTC
+#if !JVET_AF0190_RPR_TMP_REORDER_LIC
+    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
+    {
 #endif
-        }
-      }
-    }
+    getBlkAMLRefTemplate(pu, pcBufPredRefTop, pcBufPredRefLeft);
+
     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());
+      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])
     {
-      PelUnitBuf pcBufPredRefLeftTranspose = PelUnitBuf(pu.chromaFormat, PelBuf(pcBufPredRefLeft.Y().buf, pcBufPredRefLeft.Y().height, pcBufPredRefLeft.Y().width));
-      CPelUnitBuf srcPred0 = CPelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefLeftTemplate[0][0], pcBufPredRefLeftTranspose.Y()));
-      CPelUnitBuf srcPred1 = CPelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefLeftTemplate[1][0], pcBufPredRefLeftTranspose.Y()));
-      xWeightedAverageY(pu, srcPred0, srcPred1, pcBufPredRefLeftTranspose, pu.cu->slice->getSPS()->getBitDepths(),
-        pu.cu->slice->clpRngs());
+      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
-#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)
+
+    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
-void InterPrediction::getBlkAMLRefTemplate(PredictionUnit &pu, PelUnitBuf &pcBufPredRefTop, PelUnitBuf &pcBufPredRefLeft)
-#endif
-{
-#if JVET_AA0093_ENHANCED_MMVD_EXTENSION
-  bool bLoadSave = (posList0 != -1);
+  pu.mergeIdx = mrgCandIdx;    //restore the merge index
 #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));
+  updateCandInfo(mrgCtx, rdCandList
+    , mrgCandIdx
+  );
 
-#if JVET_AA0093_ENHANCED_MMVD_EXTENSION
-  if (!bLoadSave && xCheckIdenticalMotion(pu))
-#else
-    if (xCheckIdenticalMotion(pu))
+}
 #endif
-    {
-      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;
+#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;
+  }
 
-        clipMv(mvTop, pu.lumaPos(), pu.lumaSize(), *pu.cs->sps, *pu.cs->pps);
+  const int numCandInCategory = std::min(numRetrievedMergeCand, mvpMergeCandCtx.numValidMergeCand);
 
-#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]);
-#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 );
-#else
-        xPredInterBlk( COMPONENT_Y, pu, picRef, mvTop, pcBufPredRefTop,
-                      false, pu.cu->slice->clpRng( COMPONENT_Y ), false, false, scalingRatio, 0, 0, false, NULL, 0, true );
+  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 TM_MRG
+    if ((
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+          pu.cs->sps->getUseTMMrgMode() &&
 #endif
+    	  pu.tmMergeFlag) || (mvpMergeCandCtx.numCandToTestEnc != mvpMergeCandCtx.numValidMergeCand && uiMergeCand > mvpMergeCandCtx.numCandToTestEnc ))
 #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 );
-#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 );
+    if ((mvpMergeCandCtx.numCandToTestEnc != mvpMergeCandCtx.numValidMergeCand && uiMergeCand > mvpMergeCandCtx.numCandToTestEnc ))
+#endif
+    {
+      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], pu.lheight(), AML_MERGE_TEMPLATE_SIZE)));
+#if JVET_Z0067_RPR_ENABLE
+#if !JVET_AF0190_RPR_TMP_REORDER_LIC
+      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
+      {
 #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])
       {
-        Mv mvLeft(-(AML_MERGE_TEMPLATE_SIZE << horShift), 0);
-        mvLeft += subPelMv;
-
-        clipMv(mvLeft, pu.lumaPos(), pu.lumaSize(), *pu.cs->sps, *pu.cs->pps);
+        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 JVET_AG0276_NLIC
+    mrgCtxTmp.altLMFlag[uiMergeCand] = mrgCtx.altLMFlag[uiMergeCand];
+    mrgCtxTmp.altLMParaNeighbours[uiMergeCand] = mrgCtx.altLMParaNeighbours[uiMergeCand];
+#endif
+#if INTER_LIC
+    mrgCtxTmp.licFlags[uiMergeCand] = mrgCtx.licFlags[uiMergeCand];
+#endif
+#if MULTI_HYP_PRED
+    mrgCtxTmp.addHypNeighbours[uiMergeCand] = mrgCtx.addHypNeighbours[uiMergeCand];
+#endif
+    if (applyBDMVR)
+    {
+      applyBDMVRTmp[uiMergeCand] = applyBDMVR[uiMergeCand];
+    }
+  }
+  //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 JVET_AG0276_NLIC
+    mrgCtx.altLMFlag[uiMergeCand] = mrgCtxTmp.altLMFlag[rdCandList[uiMergeCand]];
+    mrgCtx.altLMParaNeighbours[uiMergeCand] = mrgCtxTmp.altLMParaNeighbours[rdCandList[uiMergeCand]];
+#endif
+#if INTER_LIC
+    mrgCtx.licFlags[uiMergeCand] = mrgCtxTmp.licFlags[rdCandList[uiMergeCand]];
+#endif
+#if MULTI_HYP_PRED
+    mrgCtx.addHypNeighbours[uiMergeCand] = mrgCtxTmp.addHypNeighbours[rdCandList[uiMergeCand]];
+#endif
+    if (applyBDMVR)
+    {
+      applyBDMVR[uiMergeCand] = applyBDMVRTmp[rdCandList[uiMergeCand]];
+    }
+    if (mvBufBDMVR && mvBufBDMVRTmp)
+    {
+      mvBufBDMVRTmp[(uiMergeCand << 1)] = mvBufBDMVR[(rdCandList[uiMergeCand] << 1)];
+      mvBufBDMVRTmp[(uiMergeCand << 1) + 1] = mvBufBDMVR[(rdCandList[uiMergeCand] << 1) + 1];
+    }
+    if (subRefineList && subRefineListTmp)
+    {
+      subRefineList[uiMergeCand][0] = subRefineListTmp[rdCandList[uiMergeCand]][0];
+      subRefineList[uiMergeCand][1] = subRefineListTmp[rdCandList[uiMergeCand]][1];
+    }
+  }
+  if (mvBufBDMVR && mvBufBDMVRTmp)
+  {
+    for (uint32_t uiMergeCand = 0; uiMergeCand < numCandInCategory; uiMergeCand++)
+    {
+      mvBufBDMVR[(uiMergeCand << 1)] = mvBufBDMVRTmp[(uiMergeCand << 1)];
+      mvBufBDMVR[(uiMergeCand << 1) + 1] = mvBufBDMVRTmp[(uiMergeCand << 1) + 1];
+    }
+  }
+}
+#endif
+#endif
+
+#if JVET_W0090_ARMC_TM || JVET_Z0056_GPM_SPLIT_MODE_REORDERING || JVET_Z0061_TM_OBMC || JVET_AA0061_IBC_MBVD || JVET_Y0058_IBC_LIST_MODIFY
+bool InterPrediction::xAMLGetCurBlkTemplate(PredictionUnit& pu, int nCurBlkWidth, int nCurBlkHeight)
+{
+  m_bAMLTemplateAvailabe[0] = xAMLIsTopTempAvailable(pu);
+  m_bAMLTemplateAvailabe[1] = xAMLIsLeftTempAvailable(pu);
+
+  if (!m_bAMLTemplateAvailabe[0] && !m_bAMLTemplateAvailabe[1])
+  {
+    return false;
+  }
+
+  /* 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));*/
+  const Picture&  currPic = *pu.cs->picture;
+  const CPelBuf recBuf = currPic.getRecoBuf(pu.cs->picture->blocks[COMPONENT_Y]);
+  std::vector<Pel>& invLUT = m_pcReshape->getInvLUT();
+
+#if JVET_Z0054_BLK_REF_PIC_REORDER
+  if(!m_fillCurTplAboveARMC)
+#endif
+  if (m_bAMLTemplateAvailabe[0])
+  {
+    const Pel*    rec = recBuf.bufAt(pu.blocks[COMPONENT_Y].pos().offset(0, -AML_MERGE_TEMPLATE_SIZE));
+    Pel*   pcY = m_acYuvCurAMLTemplate[0][0];
+    for (int k = 0; k < nCurBlkWidth; k++)
+    {
+      for (int l = 0; l < AML_MERGE_TEMPLATE_SIZE; l++)
+      {
+        int recVal = rec[k + l * recBuf.stride];
+
+        if (m_pcReshape->getSliceReshaperInfo().getUseSliceReshaper() && m_pcReshape->getCTUFlag())
+        {
+          recVal = invLUT[recVal];
+        }
+
+        pcY[k + l * nCurBlkWidth] = recVal;
+      }
+    }
+#if JVET_Z0054_BLK_REF_PIC_REORDER
+    m_fillCurTplAboveARMC = true;
+#endif
+  }
+
+#if JVET_Z0054_BLK_REF_PIC_REORDER
+  if(!m_fillCurTplLeftARMC)
+#endif
+  if (m_bAMLTemplateAvailabe[1])
+  {
+    Pel* pcY = m_acYuvCurAMLTemplate[1][0];
+    const Pel*    rec = recBuf.bufAt(pu.blocks[COMPONENT_Y].pos().offset(-AML_MERGE_TEMPLATE_SIZE, 0));
+    for (int k = 0; k < nCurBlkHeight; k++)
+    {
+      for (int l = 0; l < AML_MERGE_TEMPLATE_SIZE; l++)
+      {
+        int recVal = rec[recBuf.stride * k + l];
+
+        if (m_pcReshape->getSliceReshaperInfo().getUseSliceReshaper() && m_pcReshape->getCTUFlag())
+        {
+          recVal = invLUT[recVal];
+        }
+
+        pcY[AML_MERGE_TEMPLATE_SIZE * k + l] = recVal;
+      }
+    }
+#if JVET_Z0054_BLK_REF_PIC_REORDER
+    m_fillCurTplLeftARMC = true;
+#endif
+  }
+#if JVET_AD0213_LIC_IMP
+  if (!m_fillLicTpl[COMPONENT_Y])
+  {
+    const int precShift = std::max(0, pu.cu->slice->clpRng(COMPONENT_Y).bd - 12);
+    if (!precShift)
+    {
+      if (m_bAMLTemplateAvailabe[0])
+      {
+        memcpy(m_pcLICRecAboveTemplate[0], m_acYuvCurAMLTemplate[0][0], nCurBlkWidth * sizeof(Pel));
+      }
+
+      if (m_bAMLTemplateAvailabe[1])
+      {
+        memcpy(m_pcLICRecLeftTemplate[0], m_acYuvCurAMLTemplate[1][0], nCurBlkHeight * sizeof(Pel));
+      }
+
+      m_fillLicTpl[COMPONENT_Y] = true;
+    }
+  }
+#endif
+
+  return true;
+}
+
+bool InterPrediction::xAMLIsTopTempAvailable(PredictionUnit& pu)
+{
+  const CodingStructure &cs = *pu.cs;
+  Position posRT = pu.Y().topRight();
+  const PredictionUnit *puAbove = cs.getPURestricted(posRT.offset(0, -1), pu, pu.chType);
+
+  return (puAbove && pu.cu != puAbove->cu);
+}
+
+bool InterPrediction::xAMLIsLeftTempAvailable(PredictionUnit& pu)
+{
+  const CodingStructure &cs = *pu.cs;
+  Position posLB = pu.Y().bottomLeft();
+  const PredictionUnit *puLeft = cs.getPURestricted(posLB.offset(-1, 0), pu, pu.chType);
+
+  return (puLeft && pu.cu != puLeft->cu);
+}
+#endif
+
+#if JVET_W0090_ARMC_TM || JVET_AA0070_RRIBC
+void InterPrediction::updateCandList(uint32_t uiCand, Distortion uiCost, uint32_t uiMrgCandNum, uint32_t* rdCandList, Distortion* candCostList)
+{
+  uint32_t i;
+  uint32_t shift = 0;
+
+  while (shift < uiMrgCandNum && uiCost < candCostList[uiMrgCandNum - 1 - shift])
+  {
+    shift++;
+  }
+
+  if (shift != 0)
+  {
+    for (i = 1; i < shift; i++)
+    {
+      rdCandList[uiMrgCandNum - i] = rdCandList[uiMrgCandNum - 1 - i];
+      candCostList[uiMrgCandNum - i] = candCostList[uiMrgCandNum - 1 - i];
+    }
+    rdCandList[uiMrgCandNum - shift] = uiCand;
+    candCostList[uiMrgCandNum - shift] = uiCost;
+  }
+}
+#endif
+
+#if JVET_W0090_ARMC_TM
+void  InterPrediction::updateCandInfo(MergeCtx& mrgCtx, uint32_t(*RdCandList)[MRG_MAX_NUM_CANDS], int mrgCandIdx)
+{
+  MergeCtx mrgCtxTmp;
+  for (uint32_t ui = 0; ui < MRG_MAX_NUM_CANDS; ++ui)
+  {
+    mrgCtxTmp.bcwIdx[ui] = BCW_DEFAULT;
+    mrgCtxTmp.interDirNeighbours[ui] = 0;
+    mrgCtxTmp.mvFieldNeighbours[(ui << 1)].refIdx = NOT_VALID;
+    mrgCtxTmp.mvFieldNeighbours[(ui << 1) + 1].refIdx = NOT_VALID;
+    mrgCtxTmp.useAltHpelIf[ui] = false;
+#if JVET_AG0276_NLIC
+    mrgCtxTmp.altLMFlag[ui] = false;
+    mrgCtxTmp.altLMParaNeighbours[ui].resetAltLinearModel();
+#endif
+#if INTER_LIC
+    mrgCtxTmp.licFlags[ui] = false;
+#endif
+#if MULTI_HYP_PRED
+    mrgCtxTmp.addHypNeighbours[ui].clear();
+#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;
+    }
+    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 JVET_AG0276_NLIC
+    mrgCtxTmp.altLMFlag[uiMergeCand] = mrgCtx.altLMFlag[uiMergeCand];
+    mrgCtxTmp.altLMParaNeighbours[uiMergeCand] = mrgCtx.altLMParaNeighbours[uiMergeCand];
+#endif
+#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 = ((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;
+    }
+
+#if JVET_AG0276_LIC_FLAG_SIGNALING || JVET_AG0276_LIC_BDOF_BDMVR
+    int srcCand = RdCandList[uiMergeCand / ADAPTIVE_SUB_GROUP_SIZE][uiMergeCand%ADAPTIVE_SUB_GROUP_SIZE];
+    mrgCtx.bcwIdx            [uiMergeCand]            = mrgCtxTmp.bcwIdx            [srcCand];
+    mrgCtx.interDirNeighbours[uiMergeCand]            = mrgCtxTmp.interDirNeighbours[srcCand];
+    mrgCtx.mvFieldNeighbours [(uiMergeCand << 1)]     = mrgCtxTmp.mvFieldNeighbours [(srcCand << 1)];
+    mrgCtx.mvFieldNeighbours [(uiMergeCand << 1) + 1] = mrgCtxTmp.mvFieldNeighbours [(srcCand << 1) + 1];
+    mrgCtx.useAltHpelIf      [uiMergeCand]            = mrgCtxTmp.useAltHpelIf      [srcCand];
+#if JVET_AG0276_NLIC
+    mrgCtx.altLMFlag[uiMergeCand]                     = mrgCtxTmp.altLMFlag[srcCand];
+    mrgCtx.altLMParaNeighbours[uiMergeCand]           = mrgCtxTmp.altLMParaNeighbours[srcCand];
+#endif
+#if INTER_LIC
+    mrgCtx.licFlags          [uiMergeCand]            = mrgCtxTmp.licFlags          [srcCand];
+#endif
+#if MULTI_HYP_PRED
+    mrgCtx.addHypNeighbours  [uiMergeCand]            = mrgCtxTmp.addHypNeighbours  [srcCand];
+#endif
+#else
+    mrgCtx.bcwIdx[uiMergeCand] = mrgCtxTmp.bcwIdx[RdCandList[uiMergeCand / ADAPTIVE_SUB_GROUP_SIZE][uiMergeCand%ADAPTIVE_SUB_GROUP_SIZE]];
+    mrgCtx.interDirNeighbours[uiMergeCand] = mrgCtxTmp.interDirNeighbours[RdCandList[uiMergeCand / ADAPTIVE_SUB_GROUP_SIZE][uiMergeCand%ADAPTIVE_SUB_GROUP_SIZE]];
+    mrgCtx.mvFieldNeighbours[(uiMergeCand << 1)] = mrgCtxTmp.mvFieldNeighbours[(RdCandList[uiMergeCand / ADAPTIVE_SUB_GROUP_SIZE][uiMergeCand%ADAPTIVE_SUB_GROUP_SIZE] << 1)];
+    mrgCtx.mvFieldNeighbours[(uiMergeCand << 1) + 1] = mrgCtxTmp.mvFieldNeighbours[(RdCandList[uiMergeCand / ADAPTIVE_SUB_GROUP_SIZE][uiMergeCand%ADAPTIVE_SUB_GROUP_SIZE] << 1) + 1];
+    mrgCtx.useAltHpelIf[uiMergeCand] = mrgCtxTmp.useAltHpelIf[RdCandList[uiMergeCand / ADAPTIVE_SUB_GROUP_SIZE][uiMergeCand%ADAPTIVE_SUB_GROUP_SIZE]];
+#if JVET_AG0276_NLIC
+    mrgCtx.altLMFlag[uiMergeCand] = mrgCtxTmp.altLMFlag[RdCandList[uiMergeCand / ADAPTIVE_SUB_GROUP_SIZE][uiMergeCand%ADAPTIVE_SUB_GROUP_SIZE]];
+    mrgCtx.altLMParaNeighbours[uiMergeCand] = mrgCtxTmp.altLMParaNeighbours[RdCandList[uiMergeCand / ADAPTIVE_SUB_GROUP_SIZE][uiMergeCand%ADAPTIVE_SUB_GROUP_SIZE]];
+#endif
+#if INTER_LIC
+    mrgCtx.licFlags[uiMergeCand] = mrgCtxTmp.licFlags[RdCandList[uiMergeCand / ADAPTIVE_SUB_GROUP_SIZE][uiMergeCand%ADAPTIVE_SUB_GROUP_SIZE]];
+#endif
+#if MULTI_HYP_PRED
+    mrgCtx.addHypNeighbours[uiMergeCand] = mrgCtxTmp.addHypNeighbours[RdCandList[uiMergeCand / ADAPTIVE_SUB_GROUP_SIZE][uiMergeCand%ADAPTIVE_SUB_GROUP_SIZE]];
+#endif
+#endif
+  }
+}
+#endif
+#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION 
+void InterPrediction::getBlkAMLRefTemplateSubTMVP(PredictionUnit &pu, PelUnitBuf &pcBufPredRefTop, PelUnitBuf &pcBufPredRefLeft)
+{
+  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 (xCheckIdenticalMotionSubTMVP(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])
+    {
+      Mv mvTop(0, -(AML_MERGE_TEMPLATE_SIZE << verShift));
+      mvTop += subPelMv;
+
+      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]);
+#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);
+#else
+      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);
+#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);
+#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);
+
+#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]);
+#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);
+#else
+      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);
+#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);
+#endif
+#endif
+    }
+  }
+  else
+  {
+    for (uint32_t refList = 0; refList < NUM_REF_PIC_LIST_01; refList++)
+    {
+      if (!(pu.interDir & (1 << refList)))
+      {
+        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];
+      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);
+
+        PelUnitBuf pcMbBuf =
+          PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefAboveTemplate[refList][0], pcBufPredRefTop.Y()));
+
+        if (pu.interDir == 3)
+        {
+#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]);
+#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);
+#else
+          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);
+#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);
+#endif
+#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]);
+#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);
+#else
+          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);
+#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);
+#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.interDir == 3)
+        {
+#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]);
+#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);
+#else
+          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
+#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]);
+#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);
+#else
+          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);
+#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);
+#endif
+#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])
+    {
+      PelUnitBuf pcBufPredRefLeftTranspose = PelUnitBuf(pu.chromaFormat, PelBuf(pcBufPredRefLeft.Y().buf, pcBufPredRefLeft.Y().height, pcBufPredRefLeft.Y().width));
+      CPelUnitBuf srcPred0 = CPelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefLeftTemplate[0][0], pcBufPredRefLeftTranspose.Y()));
+      CPelUnitBuf srcPred1 = CPelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefLeftTemplate[1][0], pcBufPredRefLeftTranspose.Y()));
+      xWeightedAverageY(pu, srcPred0, srcPred1, pcBufPredRefLeftTranspose, pu.cu->slice->getSPS()->getBitDepths(),
+        pu.cu->slice->clpRngs());
+    }
+  }
+}
+#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 JVET_AA0093_ENHANCED_MMVD_EXTENSION
+  if (!bLoadSave && xCheckIdenticalMotion(pu))
+#else
+    if (xCheckIdenticalMotion(pu))
+#endif
+    {
+      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);
+
+#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]);
+#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 );
+#else
+        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 );
+#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 );
+#endif
+#endif
+#if JVET_AG0276_NLIC
+        if (m_bAMLTemplateAvailabe[1])
+        {
+          m_skipDoLic = true;
+        }
+        if (pu.cu->altLMFlag)
+        {
+          int scale = pu.cu->altLMParaUnit.scale[0];
+          int shift = 5;
+          int offset = pu.cu->altLMParaUnit.offset[0];
+          pcBufPredRefTop.Y().linearTransform(scale, shift, offset, true, pu.cu->slice->clpRng(COMPONENT_Y));
+        }
+#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);
+
+#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]);
+#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 );
+#else
+        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 );
+#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 );
+#endif
+#endif
+#if JVET_AG0276_NLIC
+        m_skipDoLic = false;
+        if (pu.cu->altLMFlag)
+        {
+          int scale = pu.cu->altLMParaUnit.scale[0];
+          int shift = 5;
+          int offset = pu.cu->altLMParaUnit.offset[0];
+          PelUnitBuf pcBufPredRefLeftTranspose = PelUnitBuf(pu.chromaFormat, PelBuf(pcBufPredRefLeft.Y().buf, pcBufPredRefLeft.Y().height, pcBufPredRefLeft.Y().width));
+          pcBufPredRefLeftTranspose.Y().linearTransform(scale, shift, offset, true, pu.cu->slice->clpRng(COMPONENT_Y));
+        }
+#endif
+      }
+    }
+    else
+    {
+#if JVET_AD0213_LIC_IMP
+      const int biShift = IF_INTERNAL_PREC - pu.cu->slice->clpRng(COMPONENT_Y).bd;
+      const Pel biOffset = -IF_INTERNAL_OFFS;
+#endif
+      for (uint32_t refList = 0; refList < NUM_REF_PIC_LIST_01; refList++)
+      {
+        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]);
+#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 );
+#else
+            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 );
+#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 );
+#endif
+#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]);
+#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 );
+#else
+            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 );
+#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 );
+#endif
+#endif
+          }
+#if JVET_AG0276_NLIC
+          if (m_bAMLTemplateAvailabe[1])
+          {
+            m_skipDoLic = true;
+          }
+#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);
+          
+#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] );
+#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 );
+#else
+            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
+#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]);
+#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 );
+#else
+            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 );
+#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 );
+#endif
+#endif
+          }
+#if JVET_AG0276_NLIC
+          m_skipDoLic = false;
+#endif
+        }
+      }
+#if JVET_AD0213_LIC_IMP
+      if (pu.cu->licFlag && pu.refIdx[0] >= 0 && pu.refIdx[1] >= 0)
+      {
+        const ClpRng& clpRng = pu.cu->slice->clpRng(COMPONENT_Y);
+        int cWidth = pu.Y().width;
+        int cHeight = pu.Y().height;
+
+#if !JVET_AF0190_RPR_TMP_REORDER_LIC
+        if (!pu.cs->sps->getRprEnabledFlag())
+        {
+#endif
+          if (m_bAMLTemplateAvailabe[0])
+          {
+            CHECK(m_numTemplate[COMPONENT_Y][0] != cWidth, "invalid template width");
+          }
+          if (m_bAMLTemplateAvailabe[1])
+          {
+            CHECK(m_numTemplate[COMPONENT_Y][1] != cHeight, "invalid template height");
+          }
+          for (uint32_t licIdx = 0; licIdx < NUM_LIC_ITERATION; licIdx++)
+          {
+            int licRefList = (licIdx % 2);
+            xLicRemHighFreq(*pu.cu, COMPONENT_Y, licIdx);
+            xGetLICParamGeneral(*pu.cu, COMPONENT_Y, m_numTemplate[COMPONENT_Y], m_pcLICRefLeftTemplate[licRefList][COMPONENT_Y], m_pcLICRefAboveTemplate[licRefList][COMPONENT_Y], m_curLICRecLeftTemplate[COMPONENT_Y], m_curLICRecAboveTemplate[COMPONENT_Y], m_shift[licRefList][COMPONENT_Y], m_scale[licRefList][COMPONENT_Y], m_offset[licRefList][COMPONENT_Y]);
+            if (licIdx < (NUM_LIC_ITERATION - 1))
+            {
+              if (m_numTemplate[COMPONENT_Y][0])
+              {
+                PelBuf aboveTemplate(m_pcLICRefAboveTemplate[licRefList][COMPONENT_Y], Size(cWidth, 1));
+                PelBuf curAboveTemplate(m_curLICRefAboveTemplate[licRefList][COMPONENT_Y], Size(cWidth, 1));
+                curAboveTemplate.copyFrom(aboveTemplate);
+                curAboveTemplate.linearTransform(m_scale[licRefList][COMPONENT_Y], m_shift[licRefList][COMPONENT_Y], m_offset[licRefList][COMPONENT_Y], true, clpRng);
+              }
+              if (m_numTemplate[COMPONENT_Y][1])
+              {
+                PelBuf leftTemplate(m_pcLICRefLeftTemplate[licRefList][COMPONENT_Y], Size(cHeight, 1));
+                PelBuf curLeftTemplate(m_curLICRefLeftTemplate[licRefList][COMPONENT_Y], Size(cHeight, 1));
+                curLeftTemplate.copyFrom(leftTemplate);
+                curLeftTemplate.linearTransform(m_scale[licRefList][COMPONENT_Y], m_shift[licRefList][COMPONENT_Y], m_offset[licRefList][COMPONENT_Y], true, clpRng);
+              }
+            }
+          }
+
+          for (int refList = 0; refList < NUM_REF_PIC_LIST_01; refList++)
+          {
+            if (m_bAMLTemplateAvailabe[0])
+            {
+              PelUnitBuf curSrcPred = PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefAboveTemplate[refList][0], Size(cWidth, 1)));
+              curSrcPred.bufs[COMPONENT_Y].toLast(clpRng);
+              curSrcPred.bufs[COMPONENT_Y].linearTransform(m_scale[refList][COMPONENT_Y], m_shift[refList][COMPONENT_Y], m_offset[refList][COMPONENT_Y], true, clpRng);
+              curSrcPred.bufs[COMPONENT_Y].linearTransform(1, -biShift, biOffset, false, clpRng);
+            }
+            if (m_bAMLTemplateAvailabe[1])
+            {
+              PelUnitBuf curSrcPred = PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefLeftTemplate[refList][0], Size(cHeight, 1)));
+              curSrcPred.bufs[COMPONENT_Y].toLast(clpRng);
+              curSrcPred.bufs[COMPONENT_Y].linearTransform(m_scale[refList][COMPONENT_Y], m_shift[refList][COMPONENT_Y], m_offset[refList][COMPONENT_Y], true, clpRng);
+              curSrcPred.bufs[COMPONENT_Y].linearTransform(1, -biShift, biOffset, false, clpRng);
+            }
+          }
+#if !JVET_AF0190_RPR_TMP_REORDER_LIC
+        }
+#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 JVET_AG0276_NLIC
+        if (pu.cu->altLMFlag)
+        {
+          int scale = pu.cu->altLMParaUnit.scale[0];
+          int shift = 5;
+          int offset = pu.cu->altLMParaUnit.offset[0];
+          pcBufPredRefTop.Y().linearTransform(scale, shift, offset, true, pu.cu->slice->clpRng(COMPONENT_Y));
+        }
+#endif
+      }
+      if (m_bAMLTemplateAvailabe[1])
+      {
+        PelUnitBuf pcBufPredRefLeftTranspose = PelUnitBuf(pu.chromaFormat, PelBuf(pcBufPredRefLeft.Y().buf, pcBufPredRefLeft.Y().height, pcBufPredRefLeft.Y().width));
+        CPelUnitBuf srcPred0 = CPelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefLeftTemplate[0][0] + offset0, pcBufPredRefLeftTranspose.Y()));  // changed
+        CPelUnitBuf srcPred1 = CPelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefLeftTemplate[1][0] + offset1, pcBufPredRefLeftTranspose.Y()));  // changed
+        xWeightedAverageY(pu, srcPred0, srcPred1, pcBufPredRefLeftTranspose, pu.cu->slice->getSPS()->getBitDepths(),
+                          pu.cu->slice->clpRngs());
+#if JVET_AG0276_NLIC
+        if (pu.cu->altLMFlag)
+        {
+          int scale = pu.cu->altLMParaUnit.scale[0];
+          int shift = 5;
+          int offset = pu.cu->altLMParaUnit.offset[0];
+          pcBufPredRefLeftTranspose.Y().linearTransform(scale, shift, offset, true, pu.cu->slice->clpRng(COMPONENT_Y));
+        }
+#endif
+      }
+
+#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], pcBufPredRefLeftTranspose.Y()));
+        CPelUnitBuf srcPred1 = CPelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefLeftTemplate[1][0], pcBufPredRefLeftTranspose.Y()));
+        xWeightedAverageY(pu, srcPred0, srcPred1, pcBufPredRefLeftTranspose, pu.cu->slice->getSPS()->getBitDepths(),
+                          pu.cu->slice->clpRngs());
+      }
+#endif
+    }
+}
+#if JVET_AD0213_LIC_IMP
+void InterPrediction::getBlkAMLRefTemplateAlt(PredictionUnit &pu, PelUnitBuf &pcBufPredRefTop, PelUnitBuf &pcBufPredRefLeft, int8_t posList0, int8_t posList1, bool load0, bool load1)
+{
+  bool bLoadSave = (posList0 != -1);
+  CHECK(!bLoadSave, "invalid bLoadSave value");
+  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));
+
+  CHECK(pu.refIdx[REF_PIC_LIST_0] < 0 || pu.refIdx[REF_PIC_LIST_1] < 0, "the function only deals with MMVD bi-pred reordering");
+
+  PelUnitBuf pcBufPredRefLeftTranspose = PelUnitBuf(pu.chromaFormat, PelBuf(pcBufPredRefLeft.Y().buf, pcBufPredRefLeft.Y().height, pcBufPredRefLeft.Y().width));
+
+  const int biShift = IF_INTERNAL_PREC - pu.cu->slice->clpRng(COMPONENT_Y).bd;
+  const Pel biOffset = -IF_INTERNAL_OFFS;
+  for (uint32_t refList = 0; refList < NUM_REF_PIC_LIST_01; refList++)
+  {
+    if (bLoadSave && (((refList == 0) && load0) || ((refList == 1) && load1)))// changed
+    {
+      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];
+    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);
+
+      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
 
 #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]);
-#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 );
+      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 (pu.cu->licFlag)
+      {
+        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);
+        pcMbBuf.bufs[0].linearTransform(1, -biShift, biOffset, false, pu.cu->slice->clpRng(COMPONENT_Y));
+      }
+      else
+      {
+        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, mvLeft, pcBufPredRefLeft,
-                      false, pu.cu->slice->clpRng( COMPONENT_Y ), false, false, scalingRatio, 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, true, mvCurr);
+#endif
+#if JVET_AG0276_NLIC
+      if (m_bAMLTemplateAvailabe[1])
+      {
+        m_skipDoLic = true;
+      }
+#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);
+
+      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
+
+#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]);
+      if (pu.cu->licFlag)
+      {
+        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);
+        PelUnitBuf pcMbBufTranspose = PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefLeftTemplate[refList][0] + offsetA, pcBufPredRefLeftTranspose.Y())); // changed
+        pcMbBufTranspose.bufs[0].linearTransform(1, -biShift, biOffset, false, pu.cu->slice->clpRng(COMPONENT_Y));
+      }
+      else
+      {
+        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, 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);
+#endif
+#if JVET_AG0276_NLIC
+      m_skipDoLic = false;
+#endif
+    }
+  }
+
+  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 JVET_AG0276_NLIC
+    if (pu.cu->altLMFlag)
+    {
+      int scale = pu.cu->altLMParaUnit.scale[0];
+      int shift = 5;
+      int offset = pu.cu->altLMParaUnit.offset[0];
+      pcBufPredRefTop.Y().linearTransform(scale, shift, offset, true, pu.cu->slice->clpRng(COMPONENT_Y));
+    }
+#endif
+  }
+  if (m_bAMLTemplateAvailabe[1])
+  {
+    CPelUnitBuf srcPred0 = CPelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefLeftTemplate[0][0] + offset0, pcBufPredRefLeftTranspose.Y()));  // changed
+    CPelUnitBuf srcPred1 = CPelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefLeftTemplate[1][0] + offset1, pcBufPredRefLeftTranspose.Y()));  // changed
+    xWeightedAverageY(pu, srcPred0, srcPred1, pcBufPredRefLeftTranspose, pu.cu->slice->getSPS()->getBitDepths(), pu.cu->slice->clpRngs());
+#if JVET_AG0276_NLIC
+    if (pu.cu->altLMFlag)
+    {
+      int scale = pu.cu->altLMParaUnit.scale[0];
+      int shift = 5;
+      int offset = pu.cu->altLMParaUnit.offset[0];
+      pcBufPredRefLeftTranspose.Y().linearTransform(scale, shift, offset, true, pu.cu->slice->clpRng(COMPONENT_Y));
+    }
+#endif
+  }
+}
+#endif
+#endif
+
+#if JVET_W0090_ARMC_TM
+void  InterPrediction::adjustAffineMergeCandidates(PredictionUnit &pu, AffineMergeCtx& affMrgCtx, int mrgCandIdx
+#if JVET_Z0139_NA_AFF
+    , int sortedCandNum
+#endif
+)
+{
+#if JVET_Z0139_NA_AFF
+  const uint32_t maxNumAffineMergeCand = (sortedCandNum > 0) ? sortedCandNum: pu.cs->slice->getPicHeader()->getMaxNumAffineMergeCand();
+#endif
+#if JVET_AA0107_RMVF_AFFINE_MERGE_DERIVATION
+  uint32_t rdCandList[RMVF_AFFINE_MRG_MAX_CAND_LIST_SIZE][RMVF_AFFINE_MRG_MAX_CAND_LIST_SIZE];
+  Distortion candCostList[RMVF_AFFINE_MRG_MAX_CAND_LIST_SIZE][RMVF_AFFINE_MRG_MAX_CAND_LIST_SIZE];
+#else
+  uint32_t rdCandList[AFFINE_MRG_MAX_NUM_CANDS][AFFINE_MRG_MAX_NUM_CANDS];
+  Distortion candCostList[AFFINE_MRG_MAX_NUM_CANDS][AFFINE_MRG_MAX_NUM_CANDS];
+#endif
+#if JVET_AA0107_RMVF_AFFINE_MERGE_DERIVATION
+  for (uint32_t i = 0; i < RMVF_AFFINE_MRG_MAX_CAND_LIST_SIZE; i++)
+  {
+    for (uint32_t j = 0; j < RMVF_AFFINE_MRG_MAX_CAND_LIST_SIZE; j++)
+#else
+  for (uint32_t i = 0; i < AFFINE_MRG_MAX_NUM_CANDS; i++)
+  {
+    for (uint32_t j = 0; j < AFFINE_MRG_MAX_NUM_CANDS; j++)
+#endif
+    {
+      rdCandList[i][j] = j;
+      candCostList[i][j] = 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;
+  }
+
+  for (uint32_t uiMergeCand = ((mrgCandIdx < 0) ? 0 : (mrgCandIdx / ADAPTIVE_AFFINE_SUB_GROUP_SIZE)*ADAPTIVE_AFFINE_SUB_GROUP_SIZE); uiMergeCand < (((mrgCandIdx < 0) || ((mrgCandIdx / ADAPTIVE_AFFINE_SUB_GROUP_SIZE + 1)*ADAPTIVE_AFFINE_SUB_GROUP_SIZE > affMrgCtx.maxNumMergeCand)) ? affMrgCtx.maxNumMergeCand : ((mrgCandIdx / ADAPTIVE_AFFINE_SUB_GROUP_SIZE + 1)*ADAPTIVE_AFFINE_SUB_GROUP_SIZE)); ++uiMergeCand)
+  {
+    bool firstGroup = (uiMergeCand / ADAPTIVE_AFFINE_SUB_GROUP_SIZE) == 0 ? true : false;
+    bool lastGroup = ((uiMergeCand / ADAPTIVE_AFFINE_SUB_GROUP_SIZE + 1)*ADAPTIVE_AFFINE_SUB_GROUP_SIZE >= affMrgCtx.maxNumMergeCand) ? true : false;
+    if (lastGroup && !firstGroup)
+    {
+      break;
+    }
+#if JVET_AA0107_RMVF_AFFINE_MERGE_DERIVATION
+    bool lowPrio = false;
+    if (uiMergeCand >= affMrgCtx.numAffCandToTestEnc)
+    {
+      affMrgCtx.candCost[uiMergeCand] = MAX_UINT64 >> 1;
+      uiCost = MAX_UINT >> 1;
+      lowPrio = true;
+    }
+    if (affMrgCtx.candCost[uiMergeCand] == MAX_UINT64)
+    {
+#endif
+    uiCost = 0;
+
+    // set merge information
+    pu.interDir = affMrgCtx.interDirNeighbours[uiMergeCand];
+    pu.mergeFlag = true;
+    pu.regularMergeFlag = false;
+    pu.mergeIdx = uiMergeCand;
+    pu.cu->affine = true;
+    pu.cu->affineType = affMrgCtx.affineType[uiMergeCand];
+#if AFFINE_MMVD
+    pu.afMmvdFlag = false;
+#endif
+    pu.cu->bcwIdx = affMrgCtx.bcwIdx[uiMergeCand];
+#if JVET_AG0276_NLIC
+    pu.cu->altLMFlag = affMrgCtx.altLMFlag[uiMergeCand];
+    pu.cu->altLMParaUnit = affMrgCtx.altLMParaNeighbours[uiMergeCand];
 #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 );
+    pu.cu->licFlag = affMrgCtx.licFlags[uiMergeCand];
+#endif
+#if JVET_AD0193_ADAPTIVE_OBMC_CONTROL
+    pu.cu->obmcFlag = affMrgCtx.obmcFlags[uiMergeCand];
+#endif
+#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION
+    pu.colIdx = affMrgCtx.colIdx[uiMergeCand];
+#endif
+    pu.mergeType = affMrgCtx.mergeType[uiMergeCand];
+#if JVET_Z0139_NA_AFF
+#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION
+#if JVET_AG0135_AFFINE_CIIP
+    if ((pu.cu->slice->getTLayer() < 4 && PU::checkAffineTMCondition(pu)) || ((pu.mergeType == MRG_TYPE_DEFAULT_N) || (pu.mergeType == MRG_TYPE_SUBPU_ATMVP && uiMergeCand)))
 #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 );
+    if ((pu.mergeType == MRG_TYPE_DEFAULT_N) || (pu.mergeType == MRG_TYPE_SUBPU_ATMVP && uiMergeCand))
 #endif
+#else
+    if (pu.mergeType == MRG_TYPE_DEFAULT_N)
 #endif
-      }
+#else
+    if (pu.mergeType == MRG_TYPE_SUBPU_ATMVP)
+    {
+      pu.refIdx[0] = affMrgCtx.mvFieldNeighbours[(uiMergeCand << 1) + 0][0].refIdx;
+      pu.refIdx[1] = affMrgCtx.mvFieldNeighbours[(uiMergeCand << 1) + 1][0].refIdx;
+      PU::spanMotionInfo(pu, *affMrgCtx.mrgCtx);
     }
     else
-    {
-#if JVET_AD0213_LIC_IMP
-      const int biShift = IF_INTERNAL_PREC - pu.cu->slice->clpRng(COMPONENT_Y).bd;
-      const Pel biOffset = -IF_INTERNAL_OFFS;
 #endif
+    {
       for (uint32_t refList = 0; refList < NUM_REF_PIC_LIST_01; refList++)
       {
-        if (pu.refIdx[refList] < 0)
+        for (int i = 0; i < 3; i++)
         {
-          continue;
+          pu.mvAffi[refList][i] = affMrgCtx.mvFieldNeighbours[(uiMergeCand << 1) + refList][i].mv;
         }
-#if JVET_AA0093_ENHANCED_MMVD_EXTENSION
-        if (bLoadSave && (((refList == 0) && load0) || ((refList == 1) && load1)) )// changed
+        pu.refIdx[refList] = affMrgCtx.mvFieldNeighbours[(uiMergeCand << 1) + refList][0].refIdx;
+      }
+
+      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], nHeight, AML_MERGE_TEMPLATE_SIZE)));
+
+#if RPR_ENABLE && !JVET_AF0190_RPR_TMP_REORDER_LIC
+      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;
+#if JVET_Z0118_GDR
+        Picture *refPic = pu.refIdx[refList] >= 0 ? pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[refList]) : nullptr;
+        if (refPic)
         {
-          continue;
+          bRefIsRescaled |= pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[refList])->isRefScaled(pu.cs->pps);
         }
+#else
+        bRefIsRescaled |= (pu.refIdx[refList] >= 0) ? pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[refList])->isRefScaled(pu.cs->pps) : false;
+#endif        
+      }
+
+      if ( !bRefIsRescaled )
+      {
 #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
+
+      getAffAMLRefTemplate(pu, pcBufPredRefTop, pcBufPredRefLeft
+#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION
+        , pu.cs->sps->getUseFastSubTmvp(), affMrgCtx
+#endif
+      );
+
+      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
+
+#if RPR_ENABLE && !JVET_AF0190_RPR_TMP_REORDER_LIC
+      }
+#endif
+    }
+#if JVET_AA0107_RMVF_AFFINE_MERGE_DERIVATION
+    }
+    else if (!lowPrio)
+    {
+      uiCost = affMrgCtx.candCost[uiMergeCand];
+    }
+#endif
+#if JVET_Z0139_NA_AFF
+    updateCandList(uiMergeCand, uiCost, maxNumAffineMergeCand, rdCandList[uiMergeCand / ADAPTIVE_AFFINE_SUB_GROUP_SIZE], candCostList[uiMergeCand / ADAPTIVE_AFFINE_SUB_GROUP_SIZE]);
 #else
-          PelUnitBuf pcMbBuf = PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefAboveTemplate[refList][0], pcBufPredRefTop.Y()));
+    updateCandList(uiMergeCand, uiCost, ADAPTIVE_AFFINE_SUB_GROUP_SIZE, RdCandList[uiMergeCand / ADAPTIVE_AFFINE_SUB_GROUP_SIZE], candCostList[uiMergeCand / ADAPTIVE_AFFINE_SUB_GROUP_SIZE]);
 #endif
-          
-          if (pu.refIdx[0] >= 0 && pu.refIdx[1] >= 0)
+  }
+  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])))
           {
-#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]);
-#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 );
+            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
+  );
+
+}
+
+void  InterPrediction::updateAffineCandInfo(PredictionUnit &pu, AffineMergeCtx& affMrgCtx, 
+#if JVET_AA0107_RMVF_AFFINE_MERGE_DERIVATION
+  uint32_t(*RdCandList)[RMVF_AFFINE_MRG_MAX_CAND_LIST_SIZE],
 #else
-            xPredInterBlk( COMPONENT_Y, pu, picRef, mvTop, pcMbBuf, true,
-                          pu.cu->slice->clpRng( COMPONENT_Y ), false, false, scalingRatio, 0, 0, false, NULL, 0, true );
+  uint32_t(*RdCandList)[AFFINE_MRG_MAX_NUM_CANDS], 
+#endif
+  int mrgCandIdx)
+{
+  AffineMergeCtx affMrgCtxTmp;
+#if JVET_AA0107_RMVF_AFFINE_MERGE_DERIVATION
+  const uint32_t maxNumAffineMergeCand = pu.cs->slice->getPicHeader()->getMaxNumAffineMergeCand() + ADDITIONAL_AFFINE_CAND_NUM;
+  const uint32_t outputListSize = pu.cs->slice->getPicHeader()->getMaxNumAffineMergeCand();
+#else
+  const uint32_t maxNumAffineMergeCand = pu.cs->slice->getPicHeader()->getMaxNumAffineMergeCand();
+#endif
+  for (int i = 0; i < maxNumAffineMergeCand; i++)
+  {
+    for (int mvNum = 0; mvNum < 3; mvNum++)
+    {
+      affMrgCtxTmp.mvFieldNeighbours[(i << 1) + 0][mvNum].setMvField(Mv(), -1);
+      affMrgCtxTmp.mvFieldNeighbours[(i << 1) + 1][mvNum].setMvField(Mv(), -1);
+    }
+    affMrgCtxTmp.interDirNeighbours[i] = 0;
+    affMrgCtxTmp.affineType[i] = AFFINEMODEL_4PARAM;
+    affMrgCtxTmp.mergeType[i] = MRG_TYPE_DEFAULT_N;
+    affMrgCtxTmp.bcwIdx[i] = BCW_DEFAULT;
+#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION
+    affMrgCtxTmp.colIdx[i] = 0;
+#endif
+#if JVET_AG0276_NLIC
+    affMrgCtxTmp.altLMFlag[i] = false;
+    affMrgCtxTmp.altLMParaNeighbours[i].resetAltLinearModel();
+#endif
+#if INTER_LIC
+    affMrgCtxTmp.licFlags[i] = false;
+#endif
+#if JVET_AD0193_ADAPTIVE_OBMC_CONTROL
+    affMrgCtxTmp.obmcFlags[i] = true;
+#endif
+  }
+  for (uint32_t uiMergeCand = ((mrgCandIdx < 0) ? 0 : (mrgCandIdx / ADAPTIVE_AFFINE_SUB_GROUP_SIZE)*ADAPTIVE_AFFINE_SUB_GROUP_SIZE); uiMergeCand < (((mrgCandIdx < 0) || ((mrgCandIdx / ADAPTIVE_AFFINE_SUB_GROUP_SIZE + 1)*ADAPTIVE_AFFINE_SUB_GROUP_SIZE > affMrgCtx.maxNumMergeCand)) ? affMrgCtx.maxNumMergeCand : ((mrgCandIdx / ADAPTIVE_AFFINE_SUB_GROUP_SIZE + 1)*ADAPTIVE_AFFINE_SUB_GROUP_SIZE)); ++uiMergeCand)
+  {
+    bool firstGroup = (uiMergeCand / ADAPTIVE_AFFINE_SUB_GROUP_SIZE) == 0 ? true : false;
+    bool lastGroup = ((uiMergeCand / ADAPTIVE_AFFINE_SUB_GROUP_SIZE + 1)*ADAPTIVE_AFFINE_SUB_GROUP_SIZE >= affMrgCtx.maxNumMergeCand) ? true : false;
+    if (lastGroup && !firstGroup)
+    {
+      break;
+    }
+    for (int mvNum = 0; mvNum < 3; mvNum++)
+    {
+      affMrgCtxTmp.mvFieldNeighbours[(uiMergeCand << 1) + 0][mvNum] = affMrgCtx.mvFieldNeighbours[(uiMergeCand << 1) + 0][mvNum];
+      affMrgCtxTmp.mvFieldNeighbours[(uiMergeCand << 1) + 1][mvNum] = affMrgCtx.mvFieldNeighbours[(uiMergeCand << 1) + 1][mvNum];
+    }
+    affMrgCtxTmp.interDirNeighbours[uiMergeCand] = affMrgCtx.interDirNeighbours[uiMergeCand];
+    affMrgCtxTmp.affineType[uiMergeCand] = affMrgCtx.affineType[uiMergeCand];
+    affMrgCtxTmp.mergeType[uiMergeCand] = affMrgCtx.mergeType[uiMergeCand];
+    affMrgCtxTmp.bcwIdx[uiMergeCand] = affMrgCtx.bcwIdx[uiMergeCand];
+#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION
+    affMrgCtxTmp.colIdx[uiMergeCand] = affMrgCtx.colIdx[uiMergeCand];
 #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 );
-#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 );
+#if JVET_AG0276_NLIC
+    affMrgCtxTmp.altLMFlag[uiMergeCand] = affMrgCtx.altLMFlag[uiMergeCand];
+    affMrgCtxTmp.altLMParaNeighbours[uiMergeCand] = affMrgCtx.altLMParaNeighbours[uiMergeCand];
 #endif
+#if INTER_LIC                                                   
+    affMrgCtxTmp.licFlags[uiMergeCand] = affMrgCtx.licFlags[uiMergeCand];
 #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]);
-#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 );
-#else
-            xPredInterBlk( COMPONENT_Y, pu, picRef, mvTop, pcMbBuf,
-                          false, pu.cu->slice->clpRng( COMPONENT_Y ), false, false, scalingRatio, 0, 0, false, NULL, 0, true );
+#if JVET_AD0193_ADAPTIVE_OBMC_CONTROL
+    affMrgCtxTmp.obmcFlags[uiMergeCand] = affMrgCtx.obmcFlags[uiMergeCand];
 #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 );
-#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 );
+  }
+  //update
+  for (uint32_t uiMergeCand = ((mrgCandIdx < 0) ? 0 : (mrgCandIdx / ADAPTIVE_AFFINE_SUB_GROUP_SIZE)*ADAPTIVE_AFFINE_SUB_GROUP_SIZE); uiMergeCand < (((mrgCandIdx < 0) || ((mrgCandIdx / ADAPTIVE_AFFINE_SUB_GROUP_SIZE + 1)*ADAPTIVE_AFFINE_SUB_GROUP_SIZE > affMrgCtx.maxNumMergeCand)) ? affMrgCtx.maxNumMergeCand : ((mrgCandIdx / ADAPTIVE_AFFINE_SUB_GROUP_SIZE + 1)*ADAPTIVE_AFFINE_SUB_GROUP_SIZE)); ++uiMergeCand)
+  {
+    bool firstGroup = (uiMergeCand / ADAPTIVE_AFFINE_SUB_GROUP_SIZE) == 0 ? true : false;
+    bool lastGroup = ((uiMergeCand / ADAPTIVE_AFFINE_SUB_GROUP_SIZE + 1)*ADAPTIVE_AFFINE_SUB_GROUP_SIZE >= affMrgCtx.maxNumMergeCand) ? true : false;
+    if (lastGroup && !firstGroup)
+    {
+      break;
+    }
+#if JVET_AA0107_RMVF_AFFINE_MERGE_DERIVATION
+    if (uiMergeCand == outputListSize)
+    {
+      break;
+    }
 #endif
+#if JVET_AG0276_LIC_FLAG_SIGNALING || JVET_AG0276_LIC_BDOF_BDMVR
+    int srcCand = (int)RdCandList[uiMergeCand / ADAPTIVE_AFFINE_SUB_GROUP_SIZE][uiMergeCand % ADAPTIVE_AFFINE_SUB_GROUP_SIZE];
+    for (int mvNum = 0; mvNum < 3; mvNum++)
+    {
+      affMrgCtx.mvFieldNeighbours[(uiMergeCand << 1) + 0][mvNum] = affMrgCtxTmp.mvFieldNeighbours[(srcCand << 1) + 0][mvNum];
+      affMrgCtx.mvFieldNeighbours[(uiMergeCand << 1) + 1][mvNum] = affMrgCtxTmp.mvFieldNeighbours[(srcCand << 1) + 1][mvNum];
+    }
+    affMrgCtx.interDirNeighbours[uiMergeCand] = affMrgCtxTmp.interDirNeighbours[srcCand];
+    affMrgCtx.affineType[uiMergeCand] = affMrgCtxTmp.affineType[srcCand];
+    affMrgCtx.mergeType[uiMergeCand] = affMrgCtxTmp.mergeType[srcCand];
+    affMrgCtx.bcwIdx[uiMergeCand] = affMrgCtxTmp.bcwIdx[srcCand];
+#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION
+    affMrgCtx.colIdx[uiMergeCand] = affMrgCtxTmp.colIdx[srcCand];
 #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);
-          
-#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()));
+#if JVET_AG0276_NLIC
+    affMrgCtx.altLMFlag[uiMergeCand] = affMrgCtxTmp.altLMFlag[srcCand];
+    affMrgCtx.altLMParaNeighbours[uiMergeCand] = affMrgCtxTmp.altLMParaNeighbours[srcCand];
 #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] );
-#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 );
-#else
-            xPredInterBlk( COMPONENT_Y, pu, picRef, mvLeft, pcMbBuf,
-                          true, pu.cu->slice->clpRng( COMPONENT_Y ), false, false, scalingRatio, 0, 0, false, NULL, 0, true );
+#if INTER_LIC 
+    affMrgCtx.licFlags[uiMergeCand] = affMrgCtxTmp.licFlags[srcCand];
+#endif
+#if JVET_AD0193_ADAPTIVE_OBMC_CONTROL
+    affMrgCtx.obmcFlags[uiMergeCand] = affMrgCtxTmp.obmcFlags[srcCand];
 #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);
+    for (int mvNum = 0; mvNum < 3; mvNum++)
+    {
+      affMrgCtx.mvFieldNeighbours[(uiMergeCand << 1) + 0][mvNum] = affMrgCtxTmp.mvFieldNeighbours[(RdCandList[uiMergeCand / ADAPTIVE_AFFINE_SUB_GROUP_SIZE][uiMergeCand%ADAPTIVE_AFFINE_SUB_GROUP_SIZE] << 1) + 0][mvNum];
+      affMrgCtx.mvFieldNeighbours[(uiMergeCand << 1) + 1][mvNum] = affMrgCtxTmp.mvFieldNeighbours[(RdCandList[uiMergeCand / ADAPTIVE_AFFINE_SUB_GROUP_SIZE][uiMergeCand%ADAPTIVE_AFFINE_SUB_GROUP_SIZE] << 1) + 1][mvNum];
+    }
+    affMrgCtx.interDirNeighbours[uiMergeCand] = affMrgCtxTmp.interDirNeighbours[RdCandList[uiMergeCand / ADAPTIVE_AFFINE_SUB_GROUP_SIZE][uiMergeCand%ADAPTIVE_AFFINE_SUB_GROUP_SIZE]];
+    affMrgCtx.affineType[uiMergeCand] = affMrgCtxTmp.affineType[RdCandList[uiMergeCand / ADAPTIVE_AFFINE_SUB_GROUP_SIZE][uiMergeCand%ADAPTIVE_AFFINE_SUB_GROUP_SIZE]];
+    affMrgCtx.mergeType[uiMergeCand] = affMrgCtxTmp.mergeType[RdCandList[uiMergeCand / ADAPTIVE_AFFINE_SUB_GROUP_SIZE][uiMergeCand%ADAPTIVE_AFFINE_SUB_GROUP_SIZE]];
+    affMrgCtx.bcwIdx[uiMergeCand] = affMrgCtxTmp.bcwIdx[RdCandList[uiMergeCand / ADAPTIVE_AFFINE_SUB_GROUP_SIZE][uiMergeCand%ADAPTIVE_AFFINE_SUB_GROUP_SIZE]];
+#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION
+    affMrgCtx.colIdx[uiMergeCand] = affMrgCtxTmp.colIdx[RdCandList[uiMergeCand / ADAPTIVE_AFFINE_SUB_GROUP_SIZE][uiMergeCand%ADAPTIVE_AFFINE_SUB_GROUP_SIZE]];
 #endif
+#if JVET_AG0276_NLIC
+    affMrgCtx.altLMFlag[uiMergeCand] = affMrgCtxTmp.altLMFlag[RdCandList[uiMergeCand / ADAPTIVE_AFFINE_SUB_GROUP_SIZE][uiMergeCand%ADAPTIVE_AFFINE_SUB_GROUP_SIZE]];
+    affMrgCtx.altLMParaNeighbours[uiMergeCand] = affMrgCtxTmp.altLMParaNeighbours[RdCandList[uiMergeCand / ADAPTIVE_AFFINE_SUB_GROUP_SIZE][uiMergeCand%ADAPTIVE_AFFINE_SUB_GROUP_SIZE]];
 #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]);
-#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 );
-#else
-            xPredInterBlk( COMPONENT_Y, pu, picRef, mvLeft, pcMbBuf,
-                          false, pu.cu->slice->clpRng( COMPONENT_Y ), false, false, scalingRatio, 0, 0, false, NULL, 0, true );
+#if INTER_LIC 
+    affMrgCtx.licFlags[uiMergeCand] = affMrgCtxTmp.licFlags[RdCandList[uiMergeCand / ADAPTIVE_AFFINE_SUB_GROUP_SIZE][uiMergeCand%ADAPTIVE_AFFINE_SUB_GROUP_SIZE]];
 #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 );
-#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 );
+#if JVET_AD0193_ADAPTIVE_OBMC_CONTROL
+    affMrgCtx.obmcFlags[uiMergeCand] = affMrgCtxTmp.obmcFlags[RdCandList[uiMergeCand / ADAPTIVE_AFFINE_SUB_GROUP_SIZE][uiMergeCand % ADAPTIVE_AFFINE_SUB_GROUP_SIZE]];
 #endif
 #endif
-          }
-        }
-      }
-#if JVET_AD0213_LIC_IMP
-      if (pu.cu->licFlag && pu.refIdx[0] >= 0 && pu.refIdx[1] >= 0)
-      {
-        const ClpRng& clpRng = pu.cu->slice->clpRng(COMPONENT_Y);
-        int cWidth = pu.Y().width;
-        int cHeight = pu.Y().height;
+  }
+}
 
-#if !JVET_AF0190_RPR_TMP_REORDER_LIC
-        if (!pu.cs->sps->getRprEnabledFlag())
-        {
-#endif
-          if (m_bAMLTemplateAvailabe[0])
-          {
-            CHECK(m_numTemplate[COMPONENT_Y][0] != cWidth, "invalid template width");
-          }
-          if (m_bAMLTemplateAvailabe[1])
-          {
-            CHECK(m_numTemplate[COMPONENT_Y][1] != cHeight, "invalid template height");
-          }
-          for (uint32_t licIdx = 0; licIdx < NUM_LIC_ITERATION; licIdx++)
-          {
-            int licRefList = (licIdx % 2);
-            xLicRemHighFreq(*pu.cu, COMPONENT_Y, licIdx);
-            xGetLICParamGeneral(*pu.cu, COMPONENT_Y, m_numTemplate[COMPONENT_Y], m_pcLICRefLeftTemplate[licRefList][COMPONENT_Y], m_pcLICRefAboveTemplate[licRefList][COMPONENT_Y], m_curLICRecLeftTemplate[COMPONENT_Y], m_curLICRecAboveTemplate[COMPONENT_Y], m_shift[licRefList][COMPONENT_Y], m_scale[licRefList][COMPONENT_Y], m_offset[licRefList][COMPONENT_Y]);
-            if (licIdx < (NUM_LIC_ITERATION - 1))
-            {
-              if (m_numTemplate[COMPONENT_Y][0])
-              {
-                PelBuf aboveTemplate(m_pcLICRefAboveTemplate[licRefList][COMPONENT_Y], Size(cWidth, 1));
-                PelBuf curAboveTemplate(m_curLICRefAboveTemplate[licRefList][COMPONENT_Y], Size(cWidth, 1));
-                curAboveTemplate.copyFrom(aboveTemplate);
-                curAboveTemplate.linearTransform(m_scale[licRefList][COMPONENT_Y], m_shift[licRefList][COMPONENT_Y], m_offset[licRefList][COMPONENT_Y], true, clpRng);
-              }
-              if (m_numTemplate[COMPONENT_Y][1])
-              {
-                PelBuf leftTemplate(m_pcLICRefLeftTemplate[licRefList][COMPONENT_Y], Size(cHeight, 1));
-                PelBuf curLeftTemplate(m_curLICRefLeftTemplate[licRefList][COMPONENT_Y], Size(cHeight, 1));
-                curLeftTemplate.copyFrom(leftTemplate);
-                curLeftTemplate.linearTransform(m_scale[licRefList][COMPONENT_Y], m_shift[licRefList][COMPONENT_Y], m_offset[licRefList][COMPONENT_Y], true, clpRng);
-              }
-            }
-          }
+#if JVET_AG0276_NLIC
+void InterPrediction::adjustAffineMergeCandidates(PredictionUnit &pu, AffineMergeCtx& affMrgCtx, AltLMAffineMergeCtx& altLMAffMrgCtx, AltLMAffineMergeCtx& altLMRMVFMrgCtx)
+{
+  const uint32_t maxNumAffineMergeCand = pu.cs->slice->getPicHeader()->getMaxNumAffineMergeCand();
 
-          for (int refList = 0; refList < NUM_REF_PIC_LIST_01; refList++)
-          {
-            if (m_bAMLTemplateAvailabe[0])
-            {
-              PelUnitBuf curSrcPred = PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefAboveTemplate[refList][0], Size(cWidth, 1)));
-              curSrcPred.bufs[COMPONENT_Y].toLast(clpRng);
-              curSrcPred.bufs[COMPONENT_Y].linearTransform(m_scale[refList][COMPONENT_Y], m_shift[refList][COMPONENT_Y], m_offset[refList][COMPONENT_Y], true, clpRng);
-              curSrcPred.bufs[COMPONENT_Y].linearTransform(1, -biShift, biOffset, false, clpRng);
-            }
-            if (m_bAMLTemplateAvailabe[1])
-            {
-              PelUnitBuf curSrcPred = PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefLeftTemplate[refList][0], Size(cHeight, 1)));
-              curSrcPred.bufs[COMPONENT_Y].toLast(clpRng);
-              curSrcPred.bufs[COMPONENT_Y].linearTransform(m_scale[refList][COMPONENT_Y], m_shift[refList][COMPONENT_Y], m_offset[refList][COMPONENT_Y], true, clpRng);
-              curSrcPred.bufs[COMPONENT_Y].linearTransform(1, -biShift, biOffset, false, clpRng);
-            }
-          }
-#if !JVET_AF0190_RPR_TMP_REORDER_LIC
-        }
-#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])
+  AffineMergeCtx altLMAffMergeCand;
+  altLMAffMergeCand.numValidMergeCand = 0;
+  altLMAffMergeCand.numAffCandToTestEnc = 0;
+  for (uint32_t mrgIdx = 0; mrgIdx < altLMAffMrgCtx.numValidMergeCand; mrgIdx++)
+  {
+    altLMAffMergeCand.altLMFlag[altLMAffMergeCand.numValidMergeCand] = true;
+    altLMAffMergeCand.altLMParaNeighbours[altLMAffMergeCand.numValidMergeCand] = altLMAffMrgCtx.altLMParaNeighbours[mrgIdx];
+    altLMAffMergeCand.licFlags[altLMAffMergeCand.numValidMergeCand] = false;
+    altLMAffMergeCand.interDirNeighbours[altLMAffMergeCand.numValidMergeCand] = altLMAffMrgCtx.interDirNeighbours[mrgIdx];
+    for (uint32_t refList = 0; refList < NUM_REF_PIC_LIST_01; refList++)
+    {
+      for (int i = 0; i < 3; i++)
       {
-        PelUnitBuf pcBufPredRefLeftTranspose = PelUnitBuf(pu.chromaFormat, PelBuf(pcBufPredRefLeft.Y().buf, pcBufPredRefLeft.Y().height, pcBufPredRefLeft.Y().width));
-        CPelUnitBuf srcPred0 = CPelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefLeftTemplate[0][0] + offset0, pcBufPredRefLeftTranspose.Y()));  // changed
-        CPelUnitBuf srcPred1 = CPelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefLeftTemplate[1][0] + offset1, pcBufPredRefLeftTranspose.Y()));  // changed
-        xWeightedAverageY(pu, srcPred0, srcPred1, pcBufPredRefLeftTranspose, pu.cu->slice->getSPS()->getBitDepths(),
-                          pu.cu->slice->clpRngs());
+        altLMAffMergeCand.mvFieldNeighbours[(altLMAffMergeCand.numValidMergeCand << 1) + refList][i] = altLMAffMrgCtx.mvFieldNeighbours[(mrgIdx << 1) + refList][i];
       }
+    }
+    altLMAffMergeCand.mergeType[altLMAffMergeCand.numValidMergeCand] = MRG_TYPE_DEFAULT_N;
+    altLMAffMergeCand.affineType[altLMAffMergeCand.numValidMergeCand] = altLMAffMrgCtx.affineType[mrgIdx];
+    altLMAffMergeCand.bcwIdx[altLMAffMergeCand.numValidMergeCand] = altLMAffMrgCtx.bcwIdx[mrgIdx];
+#if JVET_AD0193_ADAPTIVE_OBMC_CONTROL
+    altLMAffMergeCand.obmcFlags[altLMAffMergeCand.numValidMergeCand] = altLMAffMrgCtx.obmcFlags[mrgIdx];
+#endif
+#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION
+    altLMAffMergeCand.colIdx[altLMAffMergeCand.numValidMergeCand] = 0;
+#endif
+    altLMAffMergeCand.candCost[altLMAffMergeCand.numValidMergeCand] = MAX_UINT64;
 
-#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])
+    altLMAffMergeCand.numValidMergeCand++;
+    altLMAffMergeCand.numAffCandToTestEnc++;
+  }
+  AffineMergeCtx altLMRMVFCand;
+  altLMRMVFCand.numValidMergeCand = 0;
+  altLMRMVFCand.numAffCandToTestEnc = 0;
+  for (uint32_t mrgIdx = 0; mrgIdx < altLMRMVFMrgCtx.numValidMergeCand; mrgIdx++)
+  {
+    if (!altLMRMVFMrgCtx.xCheckSameAffMotion(pu, mrgIdx, altLMAffMrgCtx))
+    {
+      continue;
+    }
+
+    altLMRMVFCand.altLMFlag[altLMRMVFCand.numValidMergeCand] = true;
+    altLMRMVFCand.altLMParaNeighbours[altLMRMVFCand.numValidMergeCand] = altLMRMVFMrgCtx.altLMParaNeighbours[mrgIdx];
+    altLMRMVFCand.licFlags[altLMRMVFCand.numValidMergeCand] = false;
+    altLMRMVFCand.interDirNeighbours[altLMRMVFCand.numValidMergeCand] = altLMRMVFMrgCtx.interDirNeighbours[mrgIdx];
+    for (uint32_t refList = 0; refList < NUM_REF_PIC_LIST_01; refList++)
+    {
+      for (int i = 0; i < 3; i++)
       {
-        CPelUnitBuf srcPred0 = CPelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefLeftTemplate[0][0], pcBufPredRefLeftTranspose.Y()));
-        CPelUnitBuf srcPred1 = CPelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefLeftTemplate[1][0], pcBufPredRefLeftTranspose.Y()));
-        xWeightedAverageY(pu, srcPred0, srcPred1, pcBufPredRefLeftTranspose, pu.cu->slice->getSPS()->getBitDepths(),
-                          pu.cu->slice->clpRngs());
+        altLMRMVFCand.mvFieldNeighbours[(altLMRMVFCand.numValidMergeCand << 1) + refList][i] = altLMRMVFMrgCtx.mvFieldNeighbours[(mrgIdx << 1) + refList][i];
       }
-#endif
     }
-}
-#if JVET_AD0213_LIC_IMP
-void InterPrediction::getBlkAMLRefTemplateAlt(PredictionUnit &pu, PelUnitBuf &pcBufPredRefTop, PelUnitBuf &pcBufPredRefLeft, int8_t posList0, int8_t posList1, bool load0, bool load1)
-{
-  bool bLoadSave = (posList0 != -1);
-  CHECK(!bLoadSave, "invalid bLoadSave value");
-  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));
+    altLMRMVFCand.mergeType[altLMRMVFCand.numValidMergeCand] = MRG_TYPE_DEFAULT_N;
+    altLMRMVFCand.affineType[altLMRMVFCand.numValidMergeCand] = altLMRMVFMrgCtx.affineType[mrgIdx];
+    altLMRMVFCand.bcwIdx[altLMRMVFCand.numValidMergeCand] = altLMRMVFMrgCtx.bcwIdx[mrgIdx];
+#if JVET_AD0193_ADAPTIVE_OBMC_CONTROL
+    altLMRMVFCand.obmcFlags[altLMRMVFCand.numValidMergeCand] = altLMRMVFMrgCtx.obmcFlags[mrgIdx];
+#endif
+#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION
+    altLMRMVFCand.colIdx[altLMRMVFCand.numValidMergeCand] = 0;
+#endif
+    altLMRMVFCand.candCost[altLMRMVFCand.numValidMergeCand] = MAX_UINT64;
 
-  CHECK(pu.refIdx[REF_PIC_LIST_0] < 0 || pu.refIdx[REF_PIC_LIST_1] < 0, "the function only deals with MMVD bi-pred reordering");
+    altLMRMVFCand.numValidMergeCand++;
+    altLMRMVFCand.numAffCandToTestEnc++;
+  }
 
-  PelUnitBuf pcBufPredRefLeftTranspose = PelUnitBuf(pu.chromaFormat, PelBuf(pcBufPredRefLeft.Y().buf, pcBufPredRefLeft.Y().height, pcBufPredRefLeft.Y().width));
+  uint32_t rdCandList[RMVF_AFFINE_MRG_MAX_CAND_LIST_SIZE + (ALT_AFF_MRG_MAX_NUM_CANDS << 1)];
+  uint32_t candCategory[RMVF_AFFINE_MRG_MAX_CAND_LIST_SIZE + (ALT_AFF_MRG_MAX_NUM_CANDS << 1)];
+  Distortion candCostList[RMVF_AFFINE_MRG_MAX_CAND_LIST_SIZE + (ALT_AFF_MRG_MAX_NUM_CANDS << 1)];
 
-  const int biShift = IF_INTERNAL_PREC - pu.cu->slice->clpRng(COMPONENT_Y).bd;
-  const Pel biOffset = -IF_INTERNAL_OFFS;
-  for (uint32_t refList = 0; refList < NUM_REF_PIC_LIST_01; refList++)
+  for (uint32_t i = 0; i < RMVF_AFFINE_MRG_MAX_CAND_LIST_SIZE + (ALT_AFF_MRG_MAX_NUM_CANDS << 1); i++)
   {
-    if (bLoadSave && (((refList == 0) && load0) || ((refList == 1) && load1)))// changed
-    {
-      continue;
-    }
-    RefPicList eRefPicList = (refList ? REF_PIC_LIST_1 : REF_PIC_LIST_0);
-    CHECK(pu.refIdx[refList] >= pu.cu->slice->getNumRefIdx(eRefPicList), "Invalid reference index");
+    rdCandList[i] = MAX_UINT;
+    candCategory[i] = MAX_UINT;
+    candCostList[i] = MAX_UINT64;
+  }
 
-    m_iRefListIdx = refList;
-    mvCurr = pu.mv[refList];
-    Mv subPelMv = mvCurr;
-    clipMv(mvCurr, pu.lumaPos(), pu.lumaSize(), *pu.cs->sps, *pu.cs->pps);
+  Distortion uiCost;
 
-    if (m_bAMLTemplateAvailabe[0])
-    {
-      Mv mvTop(0, -(AML_MERGE_TEMPLATE_SIZE << verShift));
-      mvTop += subPelMv;
+  DistParam cDistParam;
+  cDistParam.applyWeight = false;
 
-      clipMv(mvTop, pu.lumaPos(), pu.lumaSize(), *pu.cs->sps, *pu.cs->pps);
+  int nWidth = pu.lumaSize().width;
+  int nHeight = pu.lumaSize().height;
 
-      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
+  if (!xAMLGetCurBlkTemplate(pu, nWidth, nHeight))
+  {
+    return;
+  }
 
-#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]);
-      if (pu.cu->licFlag)
+  auto origMergeIdx = pu.mergeIdx;
+  for (uint32_t uiMergeCand = 0; uiMergeCand < affMrgCtx.numValidMergeCand; ++uiMergeCand)
+  {
+#if JVET_AA0107_RMVF_AFFINE_MERGE_DERIVATION
+    bool lowPrio = false;
+    if (uiMergeCand >= affMrgCtx.numAffCandToTestEnc)
+    {
+      affMrgCtx.candCost[uiMergeCand] = MAX_UINT64 >> 1;
+      uiCost = MAX_UINT >> 1;
+      lowPrio = true;
+    }
+    if (affMrgCtx.candCost[uiMergeCand] == MAX_UINT64)
+    {
+#endif
+      uiCost = 0;
+
+      // set merge information
+      pu.interDir = affMrgCtx.interDirNeighbours[uiMergeCand];
+      pu.mergeFlag = true;
+      pu.regularMergeFlag = false;
+      pu.mergeIdx = uiMergeCand;
+      pu.cu->affine = true;
+      pu.cu->affineType = affMrgCtx.affineType[uiMergeCand];
+#if AFFINE_MMVD
+      pu.afMmvdFlag = false;
+#endif
+      pu.cu->bcwIdx = affMrgCtx.bcwIdx[uiMergeCand];
+#if JVET_AG0276_NLIC
+      pu.cu->altLMFlag = affMrgCtx.altLMFlag[uiMergeCand];
+      pu.cu->altLMParaUnit = affMrgCtx.altLMParaNeighbours[uiMergeCand];
+#endif
+#if INTER_LIC
+      pu.cu->licFlag = affMrgCtx.licFlags[uiMergeCand];
+#endif
+#if JVET_AD0193_ADAPTIVE_OBMC_CONTROL
+      pu.cu->obmcFlag = affMrgCtx.obmcFlags[uiMergeCand];
+#endif
+#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION
+      pu.colIdx = affMrgCtx.colIdx[uiMergeCand];
+#endif
+      pu.mergeType = affMrgCtx.mergeType[uiMergeCand];
+#if JVET_Z0139_NA_AFF
+#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION
+      if ((pu.mergeType == MRG_TYPE_DEFAULT_N) || (pu.mergeType == MRG_TYPE_SUBPU_ATMVP && uiMergeCand))
+#else
+      if (pu.mergeType == MRG_TYPE_DEFAULT_N)
+#endif
+#else
+      if (pu.mergeType == MRG_TYPE_SUBPU_ATMVP)
       {
-        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);
-        pcMbBuf.bufs[0].linearTransform(1, -biShift, biOffset, false, pu.cu->slice->clpRng(COMPONENT_Y));
+        pu.refIdx[0] = affMrgCtx.mvFieldNeighbours[(uiMergeCand << 1) + 0][0].refIdx;
+        pu.refIdx[1] = affMrgCtx.mvFieldNeighbours[(uiMergeCand << 1) + 1][0].refIdx;
+        PU::spanMotionInfo(pu, *affMrgCtx.mrgCtx);
       }
       else
+#endif
       {
-        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);
-      }
+        for (uint32_t refList = 0; refList < NUM_REF_PIC_LIST_01; refList++)
+        {
+          for (int i = 0; i < 3; i++)
+          {
+            pu.mvAffi[refList][i] = affMrgCtx.mvFieldNeighbours[(uiMergeCand << 1) + refList][i].mv;
+          }
+          pu.refIdx[refList] = affMrgCtx.mvFieldNeighbours[(uiMergeCand << 1) + refList][0].refIdx;
+        }
+
+        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 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;
+#if JVET_Z0118_GDR
+          Picture *refPic = pu.refIdx[refList] >= 0 ? pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[refList]) : nullptr;
+          if (refPic)
+          {
+            bRefIsRescaled |= pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[refList])->isRefScaled(pu.cs->pps);
+          }
 #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, true, mvCurr);
+          bRefIsRescaled |= (pu.refIdx[refList] >= 0) ? pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[refList])->isRefScaled(pu.cs->pps) : false;
+#endif        
+        }
+        if (!bRefIsRescaled)
+        {
 #endif
-    }
-    if (m_bAMLTemplateAvailabe[1])
-    {
-      Mv mvLeft(-(AML_MERGE_TEMPLATE_SIZE << horShift), 0);
-      mvLeft += subPelMv;
+          getAffAMLRefTemplate(pu, pcBufPredRefTop, pcBufPredRefLeft
+#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION
+            , pu.cs->sps->getUseFastSubTmvp(), affMrgCtx
+#endif
+          );
 
-      clipMv(mvLeft, pu.lumaPos(), pu.lumaSize(), *pu.cs->sps, *pu.cs->pps);
+          if (m_bAMLTemplateAvailabe[0])
+          {
+            m_pcRdCost->setDistParam(cDistParam, pcBufPredCurTop.Y(), pcBufPredRefTop.Y(), pu.cs->sps->getBitDepth(CHANNEL_TYPE_LUMA), COMPONENT_Y, false);
 
-      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
+            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
 #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]);
-      if (pu.cu->licFlag)
-      {
-        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);
-        PelUnitBuf pcMbBufTranspose = PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefLeftTemplate[refList][0] + offsetA, pcBufPredRefLeftTranspose.Y())); // changed
-        pcMbBufTranspose.bufs[0].linearTransform(1, -biShift, biOffset, false, pu.cu->slice->clpRng(COMPONENT_Y));
-      }
-      else
-      {
-        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, 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);
+        }
 #endif
+      }
+#if JVET_AA0107_RMVF_AFFINE_MERGE_DERIVATION
+    }
+    else if (!lowPrio)
+    {
+      uiCost = affMrgCtx.candCost[uiMergeCand];
     }
+#endif
+    updateCandList(uiMergeCand, 0, uiCost, maxNumAffineMergeCand, rdCandList, candCategory, candCostList);
   }
+  pu.mergeIdx = origMergeIdx;    //restore the merge index
 
-  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])
+  if (altLMRMVFCand.numValidMergeCand)
   {
-    CPelUnitBuf srcPred0 = CPelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefLeftTemplate[0][0] + offset0, pcBufPredRefLeftTranspose.Y()));  // changed
-    CPelUnitBuf srcPred1 = CPelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefLeftTemplate[1][0] + offset1, pcBufPredRefLeftTranspose.Y()));  // changed
-    xWeightedAverageY(pu, srcPred0, srcPred1, pcBufPredRefLeftTranspose, pu.cu->slice->getSPS()->getBitDepths(), pu.cu->slice->clpRngs());
-  }
-}
+    for (uint32_t uiMergeCand = 0; uiMergeCand < altLMRMVFCand.numValidMergeCand; uiMergeCand++)
+    {
+      if (altLMRMVFCand.candCost[uiMergeCand] == MAX_UINT64)
+      {
+        uiCost = 0;
+        pu.interDir = altLMRMVFCand.interDirNeighbours[uiMergeCand];
+        pu.mergeFlag = true;
+        pu.regularMergeFlag = false;
+        pu.mergeIdx = uiMergeCand;
+        pu.cu->affine = true;
+        pu.cu->affineType = altLMRMVFCand.affineType[uiMergeCand];
+#if AFFINE_MMVD
+        pu.afMmvdFlag = false;
 #endif
+        pu.cu->bcwIdx = altLMRMVFCand.bcwIdx[uiMergeCand];
+        pu.cu->altLMFlag = altLMRMVFCand.altLMFlag[uiMergeCand];
+        pu.cu->altLMParaUnit = altLMRMVFCand.altLMParaNeighbours[uiMergeCand];
+#if INTER_LIC
+        pu.cu->licFlag = altLMRMVFCand.licFlags[uiMergeCand];
 #endif
-
-#if JVET_W0090_ARMC_TM
-void  InterPrediction::adjustAffineMergeCandidates(PredictionUnit &pu, AffineMergeCtx& affMrgCtx, int mrgCandIdx
-#if JVET_Z0139_NA_AFF
-    , int sortedCandNum
+#if JVET_AD0193_ADAPTIVE_OBMC_CONTROL
+        pu.cu->obmcFlag = altLMRMVFCand.obmcFlags[uiMergeCand];
 #endif
-)
-{
-#if JVET_Z0139_NA_AFF
-  const uint32_t maxNumAffineMergeCand = (sortedCandNum > 0) ? sortedCandNum: pu.cs->slice->getPicHeader()->getMaxNumAffineMergeCand();
+#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION
+        pu.colIdx = altLMRMVFCand.colIdx[uiMergeCand];
 #endif
-#if JVET_AA0107_RMVF_AFFINE_MERGE_DERIVATION
-  uint32_t rdCandList[RMVF_AFFINE_MRG_MAX_CAND_LIST_SIZE][RMVF_AFFINE_MRG_MAX_CAND_LIST_SIZE];
-  Distortion candCostList[RMVF_AFFINE_MRG_MAX_CAND_LIST_SIZE][RMVF_AFFINE_MRG_MAX_CAND_LIST_SIZE];
+        pu.mergeType = altLMRMVFCand.mergeType[uiMergeCand];
+        for (uint32_t refList = 0; refList < NUM_REF_PIC_LIST_01; refList++)
+        {
+          for (int i = 0; i < 3; i++)
+          {
+            pu.mvAffi[refList][i] = altLMRMVFCand.mvFieldNeighbours[(uiMergeCand << 1) + refList][i].mv;
+          }
+          pu.refIdx[refList] = altLMRMVFCand.mvFieldNeighbours[(uiMergeCand << 1) + refList][0].refIdx;
+        }
+
+        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 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;
+#if JVET_Z0118_GDR
+          Picture *refPic = pu.refIdx[refList] >= 0 ? pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[refList]) : nullptr;
+          if (refPic)
+          {
+            bRefIsRescaled |= pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[refList])->isRefScaled(pu.cs->pps);
+          }
 #else
-  uint32_t rdCandList[AFFINE_MRG_MAX_NUM_CANDS][AFFINE_MRG_MAX_NUM_CANDS];
-  Distortion candCostList[AFFINE_MRG_MAX_NUM_CANDS][AFFINE_MRG_MAX_NUM_CANDS];
+          bRefIsRescaled |= (pu.refIdx[refList] >= 0) ? pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[refList])->isRefScaled(pu.cs->pps) : false;
+#endif        
+        }
+        if (!bRefIsRescaled)
+        {
 #endif
-#if JVET_AA0107_RMVF_AFFINE_MERGE_DERIVATION
-  for (uint32_t i = 0; i < RMVF_AFFINE_MRG_MAX_CAND_LIST_SIZE; i++)
-  {
-    for (uint32_t j = 0; j < RMVF_AFFINE_MRG_MAX_CAND_LIST_SIZE; j++)
-#else
-  for (uint32_t i = 0; i < AFFINE_MRG_MAX_NUM_CANDS; i++)
-  {
-    for (uint32_t j = 0; j < AFFINE_MRG_MAX_NUM_CANDS; j++)
+          getAffAMLRefTemplate(pu, pcBufPredRefTop, pcBufPredRefLeft
+#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION
+            , pu.cs->sps->getUseFastSubTmvp(), affMrgCtx
+#endif
+          );
+          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
+#if RPR_ENABLE
+        }
 #endif
-    {
-      rdCandList[i][j] = j;
-      candCostList[i][j] = MAX_UINT;
+      }
+      else
+      {
+        uiCost = altLMRMVFCand.candCost[uiMergeCand];
+      }
+      updateCandList(uiMergeCand, 2, uiCost, maxNumAffineMergeCand, rdCandList, candCategory, candCostList);
     }
+    pu.mergeIdx = origMergeIdx;
   }
 
-  Distortion uiCost;
-
-  DistParam cDistParam;
-  cDistParam.applyWeight = false;
-
-  int nWidth = pu.lumaSize().width;
-  int nHeight = pu.lumaSize().height;
-
-  if (!xAMLGetCurBlkTemplate(pu, nWidth, nHeight))
-  {
-    return;
-  }
-
-  for (uint32_t uiMergeCand = ((mrgCandIdx < 0) ? 0 : (mrgCandIdx / ADAPTIVE_AFFINE_SUB_GROUP_SIZE)*ADAPTIVE_AFFINE_SUB_GROUP_SIZE); uiMergeCand < (((mrgCandIdx < 0) || ((mrgCandIdx / ADAPTIVE_AFFINE_SUB_GROUP_SIZE + 1)*ADAPTIVE_AFFINE_SUB_GROUP_SIZE > affMrgCtx.maxNumMergeCand)) ? affMrgCtx.maxNumMergeCand : ((mrgCandIdx / ADAPTIVE_AFFINE_SUB_GROUP_SIZE + 1)*ADAPTIVE_AFFINE_SUB_GROUP_SIZE)); ++uiMergeCand)
+  if (altLMAffMergeCand.numValidMergeCand)
   {
-    bool firstGroup = (uiMergeCand / ADAPTIVE_AFFINE_SUB_GROUP_SIZE) == 0 ? true : false;
-    bool lastGroup = ((uiMergeCand / ADAPTIVE_AFFINE_SUB_GROUP_SIZE + 1)*ADAPTIVE_AFFINE_SUB_GROUP_SIZE >= affMrgCtx.maxNumMergeCand) ? true : false;
-    if (lastGroup && !firstGroup)
-    {
-      break;
-    }
-#if JVET_AA0107_RMVF_AFFINE_MERGE_DERIVATION
-    bool lowPrio = false;
-    if (uiMergeCand >= affMrgCtx.numAffCandToTestEnc)
-    {
-      affMrgCtx.candCost[uiMergeCand] = MAX_UINT64 >> 1;
-      uiCost = MAX_UINT >> 1;
-      lowPrio = true;
-    }
-    if (affMrgCtx.candCost[uiMergeCand] == MAX_UINT64)
+    for (uint32_t uiMergeCand = 0; uiMergeCand < altLMAffMergeCand.numValidMergeCand; uiMergeCand++)
     {
-#endif
-    uiCost = 0;
-
-    // set merge information
-    pu.interDir = affMrgCtx.interDirNeighbours[uiMergeCand];
-    pu.mergeFlag = true;
-    pu.regularMergeFlag = false;
-    pu.mergeIdx = uiMergeCand;
-    pu.cu->affine = true;
-    pu.cu->affineType = affMrgCtx.affineType[uiMergeCand];
+      if (altLMAffMergeCand.candCost[uiMergeCand] == MAX_UINT64)
+      {
+        uiCost = 0;
+        pu.interDir = altLMAffMergeCand.interDirNeighbours[uiMergeCand];
+        pu.mergeFlag = true;
+        pu.regularMergeFlag = false;
+        pu.mergeIdx = uiMergeCand;
+        pu.cu->affine = true;
+        pu.cu->affineType = altLMAffMergeCand.affineType[uiMergeCand];
 #if AFFINE_MMVD
-    pu.afMmvdFlag = false;
+        pu.afMmvdFlag = false;
 #endif
-    pu.cu->bcwIdx = affMrgCtx.bcwIdx[uiMergeCand];
+        pu.cu->bcwIdx = altLMAffMergeCand.bcwIdx[uiMergeCand];
+        pu.cu->altLMFlag = altLMAffMergeCand.altLMFlag[uiMergeCand];
+        pu.cu->altLMParaUnit = altLMAffMergeCand.altLMParaNeighbours[uiMergeCand];
 #if INTER_LIC
-    pu.cu->licFlag = affMrgCtx.licFlags[uiMergeCand];
+        pu.cu->licFlag = altLMAffMergeCand.licFlags[uiMergeCand];
 #endif
 #if JVET_AD0193_ADAPTIVE_OBMC_CONTROL
-    pu.cu->obmcFlag = affMrgCtx.obmcFlags[uiMergeCand];
-#endif
-#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION
-    pu.colIdx = affMrgCtx.colIdx[uiMergeCand];
+        pu.cu->obmcFlag = altLMAffMergeCand.obmcFlags[uiMergeCand];
 #endif
-    pu.mergeType = affMrgCtx.mergeType[uiMergeCand];
-#if JVET_Z0139_NA_AFF
 #if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION
-#if JVET_AG0135_AFFINE_CIIP
-      if ((pu.cu->slice->getTLayer() < 4 && PU::checkAffineTMCondition(pu)) || ((pu.mergeType == MRG_TYPE_DEFAULT_N) || (pu.mergeType == MRG_TYPE_SUBPU_ATMVP && uiMergeCand)))
-#else
-      if ((pu.mergeType == MRG_TYPE_DEFAULT_N) || (pu.mergeType == MRG_TYPE_SUBPU_ATMVP && uiMergeCand))
-#endif
-#else
-      if (pu.mergeType == MRG_TYPE_DEFAULT_N)
+        pu.colIdx = altLMAffMergeCand.colIdx[uiMergeCand];
 #endif
-#else
-      if (pu.mergeType == MRG_TYPE_SUBPU_ATMVP)
-      {
-        pu.refIdx[0] = affMrgCtx.mvFieldNeighbours[(uiMergeCand << 1) + 0][0].refIdx;
-        pu.refIdx[1] = affMrgCtx.mvFieldNeighbours[(uiMergeCand << 1) + 1][0].refIdx;
-        PU::spanMotionInfo(pu, *affMrgCtx.mrgCtx);
-      }
-      else
-#endif
-      {
+        pu.mergeType = altLMAffMergeCand.mergeType[uiMergeCand];
         for (uint32_t refList = 0; refList < NUM_REF_PIC_LIST_01; refList++)
         {
           for (int i = 0; i < 3; i++)
           {
-            pu.mvAffi[refList][i] = affMrgCtx.mvFieldNeighbours[(uiMergeCand << 1) + refList][i].mv;
+            pu.mvAffi[refList][i] = altLMAffMergeCand.mvFieldNeighbours[(uiMergeCand << 1) + refList][i].mv;
           }
-          pu.refIdx[refList] = affMrgCtx.mvFieldNeighbours[(uiMergeCand << 1) + refList][0].refIdx;
+          pu.refIdx[refList] = altLMAffMergeCand.mvFieldNeighbours[(uiMergeCand << 1) + refList][0].refIdx;
         }
 
-      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], nHeight, AML_MERGE_TEMPLATE_SIZE)));
+        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 RPR_ENABLE && !JVET_AF0190_RPR_TMP_REORDER_LIC
-      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;
-#if JVET_Z0118_GDR
-        Picture *refPic = pu.refIdx[refList] >= 0 ? pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[refList]) : nullptr;
-        if (refPic)
+#if RPR_ENABLE
+        bool bRefIsRescaled = false;
+        for (uint32_t refList = 0; refList < NUM_REF_PIC_LIST_01; refList++)
         {
-          bRefIsRescaled |= pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[refList])->isRefScaled(pu.cs->pps);
-        }
+          const RefPicList eRefPicList = refList ? REF_PIC_LIST_1 : REF_PIC_LIST_0;
+#if JVET_Z0118_GDR
+          Picture *refPic = pu.refIdx[refList] >= 0 ? pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[refList]) : nullptr;
+          if (refPic)
+          {
+            bRefIsRescaled |= pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[refList])->isRefScaled(pu.cs->pps);
+          }
 #else
-        bRefIsRescaled |= (pu.refIdx[refList] >= 0) ? pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[refList])->isRefScaled(pu.cs->pps) : false;
+          bRefIsRescaled |= (pu.refIdx[refList] >= 0) ? pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[refList])->isRefScaled(pu.cs->pps) : false;
 #endif        
-      }
-
-      if ( !bRefIsRescaled )
-      {
+        }
+        if (!bRefIsRescaled)
+        {
 #endif
-
-      getAffAMLRefTemplate(pu, pcBufPredRefTop, pcBufPredRefLeft
+          getAffAMLRefTemplate(pu, pcBufPredRefTop, pcBufPredRefLeft
 #if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION
-        , pu.cs->sps->getUseFastSubTmvp(), affMrgCtx
+            , pu.cs->sps->getUseFastSubTmvp(), affMrgCtx
 #endif
-      );
-
-      if (m_bAMLTemplateAvailabe[0])
-      {
-        m_pcRdCost->setDistParam(cDistParam, pcBufPredCurTop.Y(), pcBufPredRefTop.Y(), pu.cs->sps->getBitDepth(CHANNEL_TYPE_LUMA), COMPONENT_Y, false);
+          );
+          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);
-      }
+            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);
 
-      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);
+          }
 
-        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 * nHeight) / nWidth;
+          }
+          if (!m_bAMLTemplateAvailabe[0] && m_bAMLTemplateAvailabe[1])
+          {
+            uiCost += (uiCost * nWidth) / nHeight;
+          }
+#endif
+#if RPR_ENABLE
+        }
+#endif
       }
-      if (!m_bAMLTemplateAvailabe[0] && m_bAMLTemplateAvailabe[1])
+      else
       {
-        uiCost += (uiCost * nWidth) / nHeight;
+        uiCost = altLMAffMergeCand.candCost[uiMergeCand];
       }
-#endif
-
-#if RPR_ENABLE && !JVET_AF0190_RPR_TMP_REORDER_LIC
-      }
-#endif
-    }
-#if JVET_AA0107_RMVF_AFFINE_MERGE_DERIVATION
-    }
-    else if (!lowPrio)
-    {
-      uiCost = affMrgCtx.candCost[uiMergeCand];
+      updateCandList(uiMergeCand, 1, uiCost, maxNumAffineMergeCand, rdCandList, candCategory, candCostList);
     }
-#endif
-#if JVET_Z0139_NA_AFF
-    updateCandList(uiMergeCand, uiCost, maxNumAffineMergeCand, rdCandList[uiMergeCand / ADAPTIVE_AFFINE_SUB_GROUP_SIZE], candCostList[uiMergeCand / ADAPTIVE_AFFINE_SUB_GROUP_SIZE]);
-#else
-    updateCandList(uiMergeCand, uiCost, ADAPTIVE_AFFINE_SUB_GROUP_SIZE, RdCandList[uiMergeCand / ADAPTIVE_AFFINE_SUB_GROUP_SIZE], candCostList[uiMergeCand / ADAPTIVE_AFFINE_SUB_GROUP_SIZE]);
-#endif
+    pu.mergeIdx = origMergeIdx;
   }
-  pu.mergeIdx = mrgCandIdx;    //restore the merge index
+
 #if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC
   if (maxNumAffineMergeCand > 2)
   {
@@ -14808,9 +16724,9 @@ void  InterPrediction::adjustAffineMergeCandidates(PredictionUnit &pu, AffineMer
       min = MAX_UINT64;
       for (uint32_t uiMergeCand = 0; uiMergeCand < sizeCandList - 1; ++uiMergeCand)
       {
-        if (min > abs((int)(candCostList[0][uiMergeCand + 1] - candCostList[0][uiMergeCand])))
+        if (min > abs((int)(candCostList[uiMergeCand + 1] - candCostList[uiMergeCand])))
         {
-          min = abs((int)(candCostList[0][uiMergeCand + 1] - candCostList[0][uiMergeCand]));
+          min = abs((int)(candCostList[uiMergeCand + 1] - candCostList[uiMergeCand]));
           candToBeRemoved = uiMergeCand + 1;
         }
       }
@@ -14822,9 +16738,9 @@ void  InterPrediction::adjustAffineMergeCandidates(PredictionUnit &pu, AffineMer
       {
         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)
+        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])))
+          if (cost < abs((int)(candCostList[uiMergeCand] - candCostList[candToBeRemoved])))
           {
             candToBeReplaced = uiMergeCand;
             break;
@@ -14836,15 +16752,18 @@ void  InterPrediction::adjustAffineMergeCandidates(PredictionUnit &pu, AffineMer
           candToBeReplaced = sizeCandList - 1;
         }
 
-        uint32_t   rdCand = rdCandList[0][candToBeRemoved];
-        Distortion candCost = candCostList[0][(candToBeRemoved)];
+        uint32_t   rdCand = rdCandList[candToBeRemoved];
+        uint32_t   candGrp = candCategory[candToBeRemoved];
+        Distortion candCost = candCostList[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[ui] = candCostList[ui + 1];
+          rdCandList[ui] = rdCandList[ui + 1];
+          candCategory[ui] = candCategory[ui + 1];
         }
-        candCostList[0][candToBeReplaced] = candCost;
-        rdCandList[0][candToBeReplaced] = rdCand;
+        candCostList[candToBeReplaced] = candCost;
+        rdCandList[candToBeReplaced] = rdCand;
+        candCategory[candToBeReplaced] = candGrp;
       }
       else
       {
@@ -14853,56 +16772,15 @@ void  InterPrediction::adjustAffineMergeCandidates(PredictionUnit &pu, AffineMer
     }
   }
 #endif
-  updateAffineCandInfo(pu, affMrgCtx, rdCandList
-    , mrgCandIdx
-  );
-
+  updateAffineCandInThreeGrp(pu, affMrgCtx, altLMAffMergeCand, altLMRMVFCand, rdCandList, candCategory, maxNumAffineMergeCand);
 }
 
-void  InterPrediction::updateAffineCandInfo(PredictionUnit &pu, AffineMergeCtx& affMrgCtx, 
-#if JVET_AA0107_RMVF_AFFINE_MERGE_DERIVATION
-  uint32_t(*RdCandList)[RMVF_AFFINE_MRG_MAX_CAND_LIST_SIZE],
-#else
-  uint32_t(*RdCandList)[AFFINE_MRG_MAX_NUM_CANDS], 
-#endif
-  int mrgCandIdx)
+void InterPrediction::updateAffineCandInThreeGrp(PredictionUnit &pu, AffineMergeCtx& affMrgCtx, AffineMergeCtx& altLMAffMrgCtx, AffineMergeCtx& altLMAffMrgCtx1, uint32_t* rdCandList, uint32_t* rdCandGrpList, int listsize)
 {
   AffineMergeCtx affMrgCtxTmp;
-#if JVET_AA0107_RMVF_AFFINE_MERGE_DERIVATION
-  const uint32_t maxNumAffineMergeCand = pu.cs->slice->getPicHeader()->getMaxNumAffineMergeCand() + ADDITIONAL_AFFINE_CAND_NUM;
-  const uint32_t outputListSize = pu.cs->slice->getPicHeader()->getMaxNumAffineMergeCand();
-#else
-  const uint32_t maxNumAffineMergeCand = pu.cs->slice->getPicHeader()->getMaxNumAffineMergeCand();
-#endif
-  for (int i = 0; i < maxNumAffineMergeCand; i++)
-  {
-    for (int mvNum = 0; mvNum < 3; mvNum++)
-    {
-      affMrgCtxTmp.mvFieldNeighbours[(i << 1) + 0][mvNum].setMvField(Mv(), -1);
-      affMrgCtxTmp.mvFieldNeighbours[(i << 1) + 1][mvNum].setMvField(Mv(), -1);
-    }
-    affMrgCtxTmp.interDirNeighbours[i] = 0;
-    affMrgCtxTmp.affineType[i] = AFFINEMODEL_4PARAM;
-    affMrgCtxTmp.mergeType[i] = MRG_TYPE_DEFAULT_N;
-    affMrgCtxTmp.bcwIdx[i] = BCW_DEFAULT;
-#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION
-    affMrgCtxTmp.colIdx[i] = 0;
-#endif
-#if INTER_LIC
-    affMrgCtxTmp.licFlags[i] = false;
-#endif
-#if JVET_AD0193_ADAPTIVE_OBMC_CONTROL
-    affMrgCtxTmp.obmcFlags[i] = true;
-#endif
-  }
-  for (uint32_t uiMergeCand = ((mrgCandIdx < 0) ? 0 : (mrgCandIdx / ADAPTIVE_AFFINE_SUB_GROUP_SIZE)*ADAPTIVE_AFFINE_SUB_GROUP_SIZE); uiMergeCand < (((mrgCandIdx < 0) || ((mrgCandIdx / ADAPTIVE_AFFINE_SUB_GROUP_SIZE + 1)*ADAPTIVE_AFFINE_SUB_GROUP_SIZE > affMrgCtx.maxNumMergeCand)) ? affMrgCtx.maxNumMergeCand : ((mrgCandIdx / ADAPTIVE_AFFINE_SUB_GROUP_SIZE + 1)*ADAPTIVE_AFFINE_SUB_GROUP_SIZE)); ++uiMergeCand)
+
+  for (uint32_t uiMergeCand = 0; uiMergeCand < affMrgCtx.numValidMergeCand; ++uiMergeCand)
   {
-    bool firstGroup = (uiMergeCand / ADAPTIVE_AFFINE_SUB_GROUP_SIZE) == 0 ? true : false;
-    bool lastGroup = ((uiMergeCand / ADAPTIVE_AFFINE_SUB_GROUP_SIZE + 1)*ADAPTIVE_AFFINE_SUB_GROUP_SIZE >= affMrgCtx.maxNumMergeCand) ? true : false;
-    if (lastGroup && !firstGroup)
-    {
-      break;
-    }
     for (int mvNum = 0; mvNum < 3; mvNum++)
     {
       affMrgCtxTmp.mvFieldNeighbours[(uiMergeCand << 1) + 0][mvNum] = affMrgCtx.mvFieldNeighbours[(uiMergeCand << 1) + 0][mvNum];
@@ -14915,6 +16793,8 @@ void  InterPrediction::updateAffineCandInfo(PredictionUnit &pu, AffineMergeCtx&
 #if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION
     affMrgCtxTmp.colIdx[uiMergeCand] = affMrgCtx.colIdx[uiMergeCand];
 #endif
+    affMrgCtxTmp.altLMFlag[uiMergeCand] = affMrgCtx.altLMFlag[uiMergeCand];
+    affMrgCtxTmp.altLMParaNeighbours[uiMergeCand] = affMrgCtx.altLMParaNeighbours[uiMergeCand];
 #if INTER_LIC                                                   
     affMrgCtxTmp.licFlags[uiMergeCand] = affMrgCtx.licFlags[uiMergeCand];
 #endif
@@ -14923,40 +16803,80 @@ void  InterPrediction::updateAffineCandInfo(PredictionUnit &pu, AffineMergeCtx&
 #endif
   }
   //update
-  for (uint32_t uiMergeCand = ((mrgCandIdx < 0) ? 0 : (mrgCandIdx / ADAPTIVE_AFFINE_SUB_GROUP_SIZE)*ADAPTIVE_AFFINE_SUB_GROUP_SIZE); uiMergeCand < (((mrgCandIdx < 0) || ((mrgCandIdx / ADAPTIVE_AFFINE_SUB_GROUP_SIZE + 1)*ADAPTIVE_AFFINE_SUB_GROUP_SIZE > affMrgCtx.maxNumMergeCand)) ? affMrgCtx.maxNumMergeCand : ((mrgCandIdx / ADAPTIVE_AFFINE_SUB_GROUP_SIZE + 1)*ADAPTIVE_AFFINE_SUB_GROUP_SIZE)); ++uiMergeCand)
+  for (uint32_t uiMergeCand = 0; uiMergeCand < listsize; ++uiMergeCand)
   {
-    bool firstGroup = (uiMergeCand / ADAPTIVE_AFFINE_SUB_GROUP_SIZE) == 0 ? true : false;
-    bool lastGroup = ((uiMergeCand / ADAPTIVE_AFFINE_SUB_GROUP_SIZE + 1)*ADAPTIVE_AFFINE_SUB_GROUP_SIZE >= affMrgCtx.maxNumMergeCand) ? true : false;
-    if (lastGroup && !firstGroup)
+    if (rdCandGrpList[uiMergeCand] == 0)
     {
-      break;
+      for (int mvNum = 0; mvNum < 3; mvNum++)
+      {
+        affMrgCtx.mvFieldNeighbours[(uiMergeCand << 1) + 0][mvNum] = affMrgCtxTmp.mvFieldNeighbours[(rdCandList[uiMergeCand] << 1) + 0][mvNum];
+        affMrgCtx.mvFieldNeighbours[(uiMergeCand << 1) + 1][mvNum] = affMrgCtxTmp.mvFieldNeighbours[(rdCandList[uiMergeCand] << 1) + 1][mvNum];
+      }
+      affMrgCtx.interDirNeighbours[uiMergeCand] = affMrgCtxTmp.interDirNeighbours[rdCandList[uiMergeCand]];
+      affMrgCtx.affineType[uiMergeCand] = affMrgCtxTmp.affineType[rdCandList[uiMergeCand]];
+      affMrgCtx.mergeType[uiMergeCand] = affMrgCtxTmp.mergeType[rdCandList[uiMergeCand]];
+      affMrgCtx.bcwIdx[uiMergeCand] = affMrgCtxTmp.bcwIdx[rdCandList[uiMergeCand]];
+#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION
+      affMrgCtx.colIdx[uiMergeCand] = affMrgCtxTmp.colIdx[rdCandList[uiMergeCand]];
+#endif
+      affMrgCtx.altLMFlag[uiMergeCand] = affMrgCtxTmp.altLMFlag[rdCandList[uiMergeCand]];
+      affMrgCtx.altLMParaNeighbours[uiMergeCand] = affMrgCtxTmp.altLMParaNeighbours[rdCandList[uiMergeCand]];
+#if INTER_LIC 
+      affMrgCtx.licFlags[uiMergeCand] = affMrgCtxTmp.licFlags[rdCandList[uiMergeCand]];
+#endif
+#if JVET_AD0193_ADAPTIVE_OBMC_CONTROL
+      affMrgCtx.obmcFlags[uiMergeCand] = affMrgCtxTmp.obmcFlags[rdCandList[uiMergeCand]];
+#endif
     }
-#if JVET_AA0107_RMVF_AFFINE_MERGE_DERIVATION
-    if (uiMergeCand == outputListSize)
+    else if (rdCandGrpList[uiMergeCand] == 2)
     {
-      break;
-    }
+      for (int mvNum = 0; mvNum < 3; mvNum++)
+      {
+        affMrgCtx.mvFieldNeighbours[(uiMergeCand << 1) + 0][mvNum] = altLMAffMrgCtx1.mvFieldNeighbours[(rdCandList[uiMergeCand] << 1) + 0][mvNum];
+        affMrgCtx.mvFieldNeighbours[(uiMergeCand << 1) + 1][mvNum] = altLMAffMrgCtx1.mvFieldNeighbours[(rdCandList[uiMergeCand] << 1) + 1][mvNum];
+      }
+      affMrgCtx.interDirNeighbours[uiMergeCand] = altLMAffMrgCtx1.interDirNeighbours[rdCandList[uiMergeCand]];
+      affMrgCtx.affineType[uiMergeCand] = altLMAffMrgCtx1.affineType[rdCandList[uiMergeCand]];
+      affMrgCtx.mergeType[uiMergeCand] = altLMAffMrgCtx1.mergeType[rdCandList[uiMergeCand]];
+      affMrgCtx.bcwIdx[uiMergeCand] = altLMAffMrgCtx1.bcwIdx[rdCandList[uiMergeCand]];
+#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION
+      affMrgCtx.colIdx[uiMergeCand] = altLMAffMrgCtx1.colIdx[rdCandList[uiMergeCand]];
+#endif
+      affMrgCtx.altLMFlag[uiMergeCand] = altLMAffMrgCtx1.altLMFlag[rdCandList[uiMergeCand]];
+      affMrgCtx.altLMParaNeighbours[uiMergeCand] = altLMAffMrgCtx1.altLMParaNeighbours[rdCandList[uiMergeCand]];
+#if INTER_LIC 
+      affMrgCtx.licFlags[uiMergeCand] = altLMAffMrgCtx1.licFlags[rdCandList[uiMergeCand]];
+#endif
+#if JVET_AD0193_ADAPTIVE_OBMC_CONTROL
+      affMrgCtx.obmcFlags[uiMergeCand] = altLMAffMrgCtx1.obmcFlags[rdCandList[uiMergeCand]];
 #endif
-    for (int mvNum = 0; mvNum < 3; mvNum++)
-    {
-      affMrgCtx.mvFieldNeighbours[(uiMergeCand << 1) + 0][mvNum] = affMrgCtxTmp.mvFieldNeighbours[(RdCandList[uiMergeCand / ADAPTIVE_AFFINE_SUB_GROUP_SIZE][uiMergeCand%ADAPTIVE_AFFINE_SUB_GROUP_SIZE] << 1) + 0][mvNum];
-      affMrgCtx.mvFieldNeighbours[(uiMergeCand << 1) + 1][mvNum] = affMrgCtxTmp.mvFieldNeighbours[(RdCandList[uiMergeCand / ADAPTIVE_AFFINE_SUB_GROUP_SIZE][uiMergeCand%ADAPTIVE_AFFINE_SUB_GROUP_SIZE] << 1) + 1][mvNum];
     }
-    affMrgCtx.interDirNeighbours[uiMergeCand] = affMrgCtxTmp.interDirNeighbours[RdCandList[uiMergeCand / ADAPTIVE_AFFINE_SUB_GROUP_SIZE][uiMergeCand%ADAPTIVE_AFFINE_SUB_GROUP_SIZE]];
-    affMrgCtx.affineType[uiMergeCand] = affMrgCtxTmp.affineType[RdCandList[uiMergeCand / ADAPTIVE_AFFINE_SUB_GROUP_SIZE][uiMergeCand%ADAPTIVE_AFFINE_SUB_GROUP_SIZE]];
-    affMrgCtx.mergeType[uiMergeCand] = affMrgCtxTmp.mergeType[RdCandList[uiMergeCand / ADAPTIVE_AFFINE_SUB_GROUP_SIZE][uiMergeCand%ADAPTIVE_AFFINE_SUB_GROUP_SIZE]];
-    affMrgCtx.bcwIdx[uiMergeCand] = affMrgCtxTmp.bcwIdx[RdCandList[uiMergeCand / ADAPTIVE_AFFINE_SUB_GROUP_SIZE][uiMergeCand%ADAPTIVE_AFFINE_SUB_GROUP_SIZE]];
+    else
+    {
+      for (int mvNum = 0; mvNum < 3; mvNum++)
+      {
+        affMrgCtx.mvFieldNeighbours[(uiMergeCand << 1) + 0][mvNum] = altLMAffMrgCtx.mvFieldNeighbours[(rdCandList[uiMergeCand] << 1) + 0][mvNum];
+        affMrgCtx.mvFieldNeighbours[(uiMergeCand << 1) + 1][mvNum] = altLMAffMrgCtx.mvFieldNeighbours[(rdCandList[uiMergeCand] << 1) + 1][mvNum];
+      }
+      affMrgCtx.interDirNeighbours[uiMergeCand] = altLMAffMrgCtx.interDirNeighbours[rdCandList[uiMergeCand]];
+      affMrgCtx.affineType[uiMergeCand] = altLMAffMrgCtx.affineType[rdCandList[uiMergeCand]];
+      affMrgCtx.mergeType[uiMergeCand] = altLMAffMrgCtx.mergeType[rdCandList[uiMergeCand]];
+      affMrgCtx.bcwIdx[uiMergeCand] = altLMAffMrgCtx.bcwIdx[rdCandList[uiMergeCand]];
 #if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION
-    affMrgCtx.colIdx[uiMergeCand] = affMrgCtxTmp.colIdx[RdCandList[uiMergeCand / ADAPTIVE_AFFINE_SUB_GROUP_SIZE][uiMergeCand%ADAPTIVE_AFFINE_SUB_GROUP_SIZE]];
+      affMrgCtx.colIdx[uiMergeCand] = altLMAffMrgCtx.colIdx[rdCandList[uiMergeCand]];
 #endif
+      affMrgCtx.altLMFlag[uiMergeCand] = altLMAffMrgCtx.altLMFlag[rdCandList[uiMergeCand]];
+      affMrgCtx.altLMParaNeighbours[uiMergeCand] = altLMAffMrgCtx.altLMParaNeighbours[rdCandList[uiMergeCand]];
 #if INTER_LIC 
-    affMrgCtx.licFlags[uiMergeCand] = affMrgCtxTmp.licFlags[RdCandList[uiMergeCand / ADAPTIVE_AFFINE_SUB_GROUP_SIZE][uiMergeCand%ADAPTIVE_AFFINE_SUB_GROUP_SIZE]];
+      affMrgCtx.licFlags[uiMergeCand] = altLMAffMrgCtx.licFlags[rdCandList[uiMergeCand]];
 #endif
 #if JVET_AD0193_ADAPTIVE_OBMC_CONTROL
-    affMrgCtx.obmcFlags[uiMergeCand] = affMrgCtxTmp.obmcFlags[RdCandList[uiMergeCand / ADAPTIVE_AFFINE_SUB_GROUP_SIZE][uiMergeCand % ADAPTIVE_AFFINE_SUB_GROUP_SIZE]];
+      affMrgCtx.obmcFlags[uiMergeCand] = altLMAffMrgCtx.obmcFlags[rdCandList[uiMergeCand]];
 #endif
+    }
   }
 }
+#endif
 
 #if JVET_AD0140_MVD_PREDICTION
 template <int iAbove1Left2All3>
@@ -15315,11 +17235,37 @@ void InterPrediction::getAffAMLRefTemplate(PredictionUnit &pu, PelUnitBuf &pcBuf
         }
         if (m_bAMLTemplateAvailabe[1])
         {
+#if JVET_AG0276_NLIC
+          PelUnitBuf    pcBufPredRefLeftTranspose = PelUnitBuf(pu.chromaFormat, PelBuf(pcBufPredRefLeft.Y().buf, pcBufPredRefLeft.Y().height, pcBufPredRefLeft.Y().width));
+          PelBuf &      dstBuf = pcBufPredRefLeftTranspose.bufs[0];
+#else
           PelBuf &      dstBuf = pcBufPredRefLeft.bufs[0];
+#endif
           const ClpRng &clpRng = pu.cu->cs->slice->clpRng(COMPONENT_Y);
           dstBuf.linearTransform(scale[0], LICshift[0], offset[0], true, clpRng);
         }
       }
+#endif
+#if JVET_AG0276_NLIC
+      if (pu.cu->altLMFlag)
+      {
+        int scale = pu.cu->altLMParaUnit.scale[0];
+        int shift = 5;
+        int offset = pu.cu->altLMParaUnit.offset[0];
+
+        const ClpRng &clpRng = pu.cu->cs->slice->clpRng(COMPONENT_Y);
+        if (m_bAMLTemplateAvailabe[0])
+        {
+          PelBuf &      dstBuf = pcBufPredRefTop.bufs[0];
+          dstBuf.linearTransform(scale, shift, offset, true, clpRng);
+        }
+        if (m_bAMLTemplateAvailabe[1])
+        {
+          PelUnitBuf    pcBufPredRefLeftTranspose = PelUnitBuf(pu.chromaFormat, PelBuf(pcBufPredRefLeft.Y().buf, pcBufPredRefLeft.Y().height, pcBufPredRefLeft.Y().width));
+          PelBuf &      dstBuf = pcBufPredRefLeftTranspose.bufs[0];
+          dstBuf.linearTransform(scale, shift, offset, true, clpRng);
+        }
+      }
 #endif
     }
     else
@@ -15393,8 +17339,13 @@ void InterPrediction::getAffAMLRefTemplate(PredictionUnit &pu, PelUnitBuf &pcBuf
         // buffer setting
         PelBuf srcRecAboveTemplate(m_acYuvCurAMLTemplate[0][0], Size(cWidth, 1));
         PelBuf dstRecAboveTemplate(m_pcLICRecAboveTemplate[0], Size(cWidth, 1));
+#if JVET_AG0276_NLIC
+        PelBuf srcRecLeftTemplate(m_acYuvCurAMLTemplate[1][0], Size(cHeight, 1));
+        PelBuf dstRecLeftTemplate(m_pcLICRecLeftTemplate[0], Size(cHeight, 1));
+#else
         PelBuf srcRecLeftTemplate(m_acYuvCurAMLTemplate[1][0], Size(1, cHeight));
         PelBuf dstRecLeftTemplate(m_pcLICRecLeftTemplate[0], Size(1, cHeight));
+#endif
         dstRecAboveTemplate.copyFrom(srcRecAboveTemplate);
         dstRecLeftTemplate.copyFrom(srcRecLeftTemplate);
 
@@ -15402,8 +17353,13 @@ void InterPrediction::getAffAMLRefTemplate(PredictionUnit &pu, PelUnitBuf &pcBuf
         {
           PelBuf srcRefAboveTemplate(m_acYuvRefAboveTemplate[refList][0], Size(cWidth, 1));
           PelBuf dstRefAboveTemplate(m_pcLICRefAboveTemplate[refList][0], Size(cWidth, 1));
+#if JVET_AG0276_NLIC
+          PelBuf srcRefLeftTemplate(m_acYuvRefLeftTemplate[refList][0], Size(cHeight, 1));
+          PelBuf dstRefLeftTemplate(m_pcLICRefLeftTemplate[refList][0], Size(cHeight, 1));
+#else
           PelBuf srcRefLeftTemplate(m_acYuvRefLeftTemplate[refList][0], Size(1, cHeight));
           PelBuf dstRefLeftTemplate(m_pcLICRefLeftTemplate[refList][0], Size(1, cHeight));
+#endif
 
           dstRefAboveTemplate.copyFrom(srcRefAboveTemplate);
           dstRefLeftTemplate.copyFrom(srcRefLeftTemplate);
@@ -15506,6 +17462,15 @@ void InterPrediction::getAffAMLRefTemplate(PredictionUnit &pu, PelUnitBuf &pcBuf
         }
         xWeightedAverageY(pu, srcPred[0], srcPred[1], pcBufPredRefTop, pu.cu->slice->getSPS()->getBitDepths(),
                           pu.cu->slice->clpRngs());
+#if JVET_AG0276_NLIC
+        if (pu.cu->altLMFlag)
+        {
+          int scale = pu.cu->altLMParaUnit.scale[0];
+          int shift = 5;
+          int offset = pu.cu->altLMParaUnit.offset[0];
+          pcBufPredRefTop.Y().linearTransform(scale, shift, offset, true, pu.cu->slice->clpRng(COMPONENT_Y));
+        }
+#endif
       }
       if (m_bAMLTemplateAvailabe[1])
       {
@@ -15559,6 +17524,15 @@ void InterPrediction::getAffAMLRefTemplate(PredictionUnit &pu, PelUnitBuf &pcBuf
         }
         xWeightedAverageY(pu, srcPred[0], srcPred[1], pcBufPredRefLeftTranspose, pu.cu->slice->getSPS()->getBitDepths(),
                           pu.cu->slice->clpRngs());
+#if JVET_AG0276_NLIC
+        if (pu.cu->altLMFlag)
+        {
+          int scale = pu.cu->altLMParaUnit.scale[0];
+          int shift = 5;
+          int offset = pu.cu->altLMParaUnit.offset[0];
+          pcBufPredRefLeftTranspose.Y().linearTransform(scale, shift, offset, true, pu.cu->slice->clpRng(COMPONENT_Y));
+        }
+#endif
       }
     }
 #if JVET_AD0140_MVD_PREDICTION
@@ -15670,6 +17644,15 @@ void InterPrediction::getAffAMLRefTemplateAlt(PredictionUnit &pu, PelUnitBuf &pc
     srcPred[1] = PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefAboveTemplate[1][0] + offset1, pcBufPredRefTop.Y())); //changed
     xWeightedAverageY(pu, srcPred[0], srcPred[1], pcBufPredRefTop, pu.cu->slice->getSPS()->getBitDepths(),
       pu.cu->slice->clpRngs());
+#if JVET_AG0276_NLIC
+    if (pu.cu->altLMFlag)
+    {
+      int scale = pu.cu->altLMParaUnit.scale[0];
+      int shift = 5;
+      int offset = pu.cu->altLMParaUnit.offset[0];
+      pcBufPredRefTop.Y().linearTransform(scale, shift, offset, true, pu.cu->slice->clpRng(COMPONENT_Y));
+    }
+#endif
   }
   if (m_bAMLTemplateAvailabe[1])
   {
@@ -15681,6 +17664,15 @@ void InterPrediction::getAffAMLRefTemplateAlt(PredictionUnit &pu, PelUnitBuf &pc
     srcPred[1] = PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefLeftTemplate[1][0] + offset1, pcBufPredRefLeftTranspose.Y())); //changed
     xWeightedAverageY(pu, srcPred[0], srcPred[1], pcBufPredRefLeftTranspose, pu.cu->slice->getSPS()->getBitDepths(),
       pu.cu->slice->clpRngs());
+#if JVET_AG0276_NLIC
+    if (pu.cu->altLMFlag)
+    {
+      int scale = pu.cu->altLMParaUnit.scale[0];
+      int shift = 5;
+      int offset = pu.cu->altLMParaUnit.offset[0];
+      pcBufPredRefLeftTranspose.Y().linearTransform(scale, shift, offset, true, pu.cu->slice->clpRng(COMPONENT_Y));
+    }
+#endif
   }
 }
 #endif
@@ -15776,6 +17768,10 @@ void  InterPrediction::updateIBCCandInfo(PredictionUnit &pu, MergeCtx& mrgCtx, u
     mrgCtxTmp.mvFieldNeighbours[(ui << 1)].refIdx = NOT_VALID;
     mrgCtxTmp.mvFieldNeighbours[(ui << 1) + 1].refIdx = NOT_VALID;
     mrgCtxTmp.useAltHpelIf[ui] = false;
+#if JVET_AG0276_NLIC
+    mrgCtxTmp.altLMFlag[ui] = false;
+    mrgCtxTmp.altLMParaNeighbours[ui].resetAltLinearModel();
+#endif
 #if INTER_LIC
     mrgCtxTmp.licFlags[ui] = false;
 #endif
@@ -15807,6 +17803,10 @@ void  InterPrediction::updateIBCCandInfo(PredictionUnit &pu, MergeCtx& mrgCtx, u
     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 JVET_AG0276_NLIC
+    mrgCtxTmp.altLMFlag[uiMergeCand] = mrgCtx.altLMFlag[uiMergeCand];
+    mrgCtxTmp.altLMParaNeighbours[uiMergeCand] = mrgCtx.altLMParaNeighbours[uiMergeCand];
+#endif
 #if INTER_LIC 
     mrgCtxTmp.licFlags[uiMergeCand] = mrgCtx.licFlags[uiMergeCand];
 #endif
@@ -15839,6 +17839,10 @@ void  InterPrediction::updateIBCCandInfo(PredictionUnit &pu, MergeCtx& mrgCtx, u
     mrgCtx.mvFieldNeighbours[(uiMergeCand << 1)] = mrgCtxTmp.mvFieldNeighbours[(RdCandList[uiMergeCand / ADAPTIVE_IBC_SUB_GROUP_SIZE][uiMergeCand%ADAPTIVE_IBC_SUB_GROUP_SIZE] << 1)];
     mrgCtx.mvFieldNeighbours[(uiMergeCand << 1) + 1] = mrgCtxTmp.mvFieldNeighbours[(RdCandList[uiMergeCand / ADAPTIVE_IBC_SUB_GROUP_SIZE][uiMergeCand%ADAPTIVE_IBC_SUB_GROUP_SIZE] << 1) + 1];
     mrgCtx.useAltHpelIf[uiMergeCand] = mrgCtxTmp.useAltHpelIf[RdCandList[uiMergeCand / ADAPTIVE_IBC_SUB_GROUP_SIZE][uiMergeCand%ADAPTIVE_IBC_SUB_GROUP_SIZE]];
+#if JVET_AG0276_NLIC
+    mrgCtx.altLMFlag[uiMergeCand] = mrgCtxTmp.altLMFlag[RdCandList[uiMergeCand / ADAPTIVE_IBC_SUB_GROUP_SIZE][uiMergeCand%ADAPTIVE_IBC_SUB_GROUP_SIZE]];
+    mrgCtx.altLMParaNeighbours[uiMergeCand] = mrgCtxTmp.altLMParaNeighbours[RdCandList[uiMergeCand / ADAPTIVE_IBC_SUB_GROUP_SIZE][uiMergeCand%ADAPTIVE_IBC_SUB_GROUP_SIZE]];
+#endif
 #if INTER_LIC
     mrgCtx.licFlags[uiMergeCand] = mrgCtxTmp.licFlags[RdCandList[uiMergeCand / ADAPTIVE_IBC_SUB_GROUP_SIZE][uiMergeCand%ADAPTIVE_IBC_SUB_GROUP_SIZE]];
 #endif
@@ -15980,6 +17984,10 @@ void  InterPrediction::adjustAffineMergeCandidatesOneGroup(PredictionUnit &pu, A
     pu.afMmvdFlag = false;
 #endif
     pu.cu->bcwIdx = affMrgCtx.bcwIdx[uiMergeCand];
+#if JVET_AG0276_NLIC
+    pu.cu->altLMFlag = affMrgCtx.altLMFlag[uiMergeCand];
+    pu.cu->altLMParaUnit = affMrgCtx.altLMParaNeighbours[uiMergeCand];
+#endif
 #if INTER_LIC
     pu.cu->licFlag = affMrgCtx.licFlags[uiMergeCand];
 #endif
@@ -16081,6 +18089,10 @@ void  InterPrediction::updateAffineCandInfo2(PredictionUnit &pu, AffineMergeCtx&
 #if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION
     affMrgCtxTmp.colIdx[uiMergeCand] = affMrgCtx.colIdx[uiMergeCand];
 #endif
+#if JVET_AG0276_NLIC
+    affMrgCtxTmp.altLMFlag[uiMergeCand] = affMrgCtx.altLMFlag[uiMergeCand];
+    affMrgCtxTmp.altLMParaNeighbours[uiMergeCand] = affMrgCtx.altLMParaNeighbours[uiMergeCand];
+#endif
 #if INTER_LIC                                                   
     affMrgCtxTmp.licFlags[uiMergeCand] = affMrgCtx.licFlags[uiMergeCand];
 #endif
@@ -16100,6 +18112,10 @@ void  InterPrediction::updateAffineCandInfo2(PredictionUnit &pu, AffineMergeCtx&
     affMrgCtx.affineType[uiMergeCand] = affMrgCtxTmp.affineType[rdCandList[uiMergeCand / listsize][uiMergeCand%listsize]];
     affMrgCtx.mergeType[uiMergeCand] = affMrgCtxTmp.mergeType[rdCandList[uiMergeCand / listsize][uiMergeCand%listsize]];
     affMrgCtx.bcwIdx[uiMergeCand] = affMrgCtxTmp.bcwIdx[rdCandList[uiMergeCand / listsize][uiMergeCand%listsize]];
+#if JVET_AG0276_NLIC
+    affMrgCtx.altLMFlag[uiMergeCand] = affMrgCtxTmp.altLMFlag[rdCandList[uiMergeCand / listsize][uiMergeCand%listsize]];
+    affMrgCtx.altLMParaNeighbours[uiMergeCand] = affMrgCtxTmp.altLMParaNeighbours[rdCandList[uiMergeCand / listsize][uiMergeCand%listsize]];
+#endif
 #if INTER_LIC 
     affMrgCtx.licFlags[uiMergeCand] = affMrgCtxTmp.licFlags[rdCandList[uiMergeCand / listsize][uiMergeCand%listsize]];
 #endif
@@ -16122,6 +18138,10 @@ void  InterPrediction::updateIBCCandInfo( PredictionUnit &pu, MergeCtx& mrgCtx,
     mrgCtxTmp.mvFieldNeighbours[( ui << 1 )].refIdx = NOT_VALID;
     mrgCtxTmp.mvFieldNeighbours[( ui << 1 ) + 1].refIdx = NOT_VALID;
     mrgCtxTmp.useAltHpelIf[ui] = false;
+#if JVET_AG0276_NLIC
+    mrgCtxTmp.altLMFlag[ui] = false;
+    mrgCtxTmp.altLMParaNeighbours[ui].resetAltLinearModel();
+#endif
 #if INTER_LIC
     mrgCtxTmp.licFlags[ui] = false;
 #endif
@@ -16147,6 +18167,10 @@ void  InterPrediction::updateIBCCandInfo( PredictionUnit &pu, MergeCtx& mrgCtx,
     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 JVET_AG0276_NLIC
+    mrgCtxTmp.altLMFlag[uiMergeCand] = mrgCtx.altLMFlag[uiMergeCand];
+    mrgCtxTmp.altLMParaNeighbours[uiMergeCand] = mrgCtx.altLMParaNeighbours[uiMergeCand];
+#endif
 #if INTER_LIC 
     mrgCtxTmp.licFlags[uiMergeCand] = mrgCtx.licFlags[uiMergeCand];
 #endif
@@ -16173,6 +18197,10 @@ void  InterPrediction::updateIBCCandInfo( PredictionUnit &pu, MergeCtx& mrgCtx,
     mrgCtx.mvFieldNeighbours[( uiMergeCand << 1 )] = mrgCtxTmp.mvFieldNeighbours[RdCandList[uiMergeCand - startPos] << 1];
     mrgCtx.mvFieldNeighbours[( uiMergeCand << 1 ) + 1] = mrgCtxTmp.mvFieldNeighbours[( RdCandList[uiMergeCand - startPos] << 1 ) + 1];
     mrgCtx.useAltHpelIf[uiMergeCand] = mrgCtxTmp.useAltHpelIf[RdCandList[uiMergeCand - startPos]];
+#if JVET_AG0276_NLIC
+    mrgCtx.altLMFlag[uiMergeCand] = mrgCtxTmp.altLMFlag[RdCandList[uiMergeCand - startPos]];
+    mrgCtx.altLMParaNeighbours[uiMergeCand] = mrgCtxTmp.altLMParaNeighbours[RdCandList[uiMergeCand - startPos]];
+#endif
 #if INTER_LIC
     mrgCtx.licFlags[uiMergeCand] = mrgCtxTmp.licFlags[RdCandList[uiMergeCand - startPos]];
 #endif
@@ -16304,6 +18332,10 @@ int InterPrediction::selectOBMCmode(PredictionUnit &pu, PredictionUnit &subblock
     candCostList[0] = uiCost;
 
     // 1: use neighbour mv to do MC for template;
+#if JVET_AG0276_NLIC
+    subblockPu.cu->altLMFlag = tmpPu->cu->altLMFlag;
+    subblockPu.cu->altLMParaUnit = tmpPu->cu->secAltLMParaUnit;
+#endif
 #if JVET_AD0213_LIC_IMP
     subblockPu.cu->licFlag = tmpPu->cu->licFlag;
     subblockPu.cu->bcwIdx = tmpPu->cu->bcwIdx;
@@ -16386,6 +18418,10 @@ int InterPrediction::selectOBMCmode(PredictionUnit &pu, PredictionUnit &subblock
     candCostList[0] = uiCost;
 
     // 1: use neighbour mv to do MC for template;
+#if JVET_AG0276_NLIC
+    subblockPu.cu->altLMFlag = tmpPu->cu->altLMFlag;
+    subblockPu.cu->altLMParaUnit = tmpPu->cu->secAltLMParaUnit;
+#endif
 #if JVET_AD0213_LIC_IMP
     subblockPu.cu->licFlag = tmpPu->cu->licFlag;
     subblockPu.cu->bcwIdx = tmpPu->cu->bcwIdx;
@@ -16532,6 +18568,15 @@ void InterPrediction::getBlkOBMCRefTemplate(PredictionUnit &subblockPu, PelUnitB
 #endif
 #endif
                     , true);
+#endif
+#if JVET_AG0276_NLIC
+      if (subblockPu.cu->altLMFlag)
+      {
+        int scale = subblockPu.cu->altLMParaUnit.scale[0];
+        int shift = 5;
+        int offset = subblockPu.cu->altLMParaUnit.offset[0];
+        pcBufPredRef.bufs[COMPONENT_Y].linearTransform(scale, shift, offset, true, subblockPu.cu->slice->clpRng(COMPONENT_Y));
+      }
 #endif
     }
 
@@ -16565,6 +18610,16 @@ void InterPrediction::getBlkOBMCRefTemplate(PredictionUnit &subblockPu, PelUnitB
 #endif
 #endif
                     , true);
+#endif
+#if JVET_AG0276_NLIC
+      if (subblockPu.cu->altLMFlag)
+      {
+        int scale = subblockPu.cu->altLMParaUnit.scale[0];
+        int shift = 5;
+        int offset = subblockPu.cu->altLMParaUnit.offset[0];
+        PelUnitBuf pcBufPredRefLeftTranspose = PelUnitBuf(subblockPu.chromaFormat, PelBuf(pcBufPredRef.Y().buf, pcBufPredRef.Y().height, pcBufPredRef.Y().width));
+        pcBufPredRefLeftTranspose.bufs[COMPONENT_Y].linearTransform(scale, shift, offset, true, subblockPu.cu->slice->clpRng(COMPONENT_Y));
+      }
 #endif
     }
   }
@@ -16648,6 +18703,15 @@ void InterPrediction::getBlkOBMCRefTemplate(PredictionUnit &subblockPu, PelUnitB
             xOBMCWeightedAverageY(subblockPu, srcPred0, srcPred1, pcBufPredRef,
                                   subblockPu.cu->slice->getSPS()->getBitDepths(), subblockPu.cu->slice->clpRngs(),
                                   tryMi);
+#if JVET_AG0276_NLIC
+            if (subblockPu.cu->altLMFlag)
+            {
+              int scale = subblockPu.cu->altLMParaUnit.scale[0];
+              int shift = 5;
+              int offset = subblockPu.cu->altLMParaUnit.offset[0];
+              pcBufPredRef.bufs[COMPONENT_Y].linearTransform(scale, shift, offset, true, subblockPu.cu->slice->clpRng(COMPONENT_Y));
+            }
+#endif
           }
         }
         else
@@ -16677,6 +18741,15 @@ void InterPrediction::getBlkOBMCRefTemplate(PredictionUnit &subblockPu, PelUnitB
 #endif
 #endif
                         , true);
+#endif
+#if JVET_AG0276_NLIC
+          if (subblockPu.cu->altLMFlag)
+          {
+            int scale = subblockPu.cu->altLMParaUnit.scale[0];
+            int shift = 5;
+            int offset = subblockPu.cu->altLMParaUnit.offset[0];
+            pcBufPredRef.bufs[COMPONENT_Y].linearTransform(scale, shift, offset, true, subblockPu.cu->slice->clpRng(COMPONENT_Y));
+          }
 #endif
         }
       }
@@ -16742,6 +18815,15 @@ void InterPrediction::getBlkOBMCRefTemplate(PredictionUnit &subblockPu, PelUnitB
             xOBMCWeightedAverageY(subblockPu, srcPred0, srcPred1, pcBufPredRefLeftTranspose,
                                   subblockPu.cu->slice->getSPS()->getBitDepths(), subblockPu.cu->slice->clpRngs(),
                                   tryMi);
+#if JVET_AG0276_NLIC
+            if (subblockPu.cu->altLMFlag)
+            {
+              int scale = subblockPu.cu->altLMParaUnit.scale[0];
+              int shift = 5;
+              int offset = subblockPu.cu->altLMParaUnit.offset[0];
+              pcBufPredRefLeftTranspose.bufs[COMPONENT_Y].linearTransform(scale, shift, offset, true, subblockPu.cu->slice->clpRng(COMPONENT_Y));
+            }
+#endif
           }
         }
         else
@@ -16771,6 +18853,16 @@ void InterPrediction::getBlkOBMCRefTemplate(PredictionUnit &subblockPu, PelUnitB
 #endif
 #endif
                         , true);
+#endif
+#if JVET_AG0276_NLIC
+          if (subblockPu.cu->altLMFlag)
+          {
+            int scale = subblockPu.cu->altLMParaUnit.scale[0];
+            int shift = 5;
+            int offset = subblockPu.cu->altLMParaUnit.offset[0];
+            PelUnitBuf pcBufPredRefLeftTranspose = PelUnitBuf(subblockPu.chromaFormat, PelBuf(pcBufPredRef.Y().buf, pcBufPredRef.Y().height, pcBufPredRef.Y().width));
+            pcBufPredRefLeftTranspose.bufs[COMPONENT_Y].linearTransform(scale, shift, offset, true, subblockPu.cu->slice->clpRng(COMPONENT_Y));
+          }
 #endif
         }
       }
@@ -17603,6 +19695,10 @@ void InterPrediction::xLocalIlluComp(const PredictionUnit& pu,
   Pel* recAboveTemplate = m_pcLICRecAboveTemplate;
 #endif
   int numTemplate[2] = { 0 , 0 }; // 0:Above, 1:Left
+#if JVET_AG0276_NLIC
+  static int shift_s, scale_s, offset_s;
+  if (!m_skipDoLic)
+#endif
 #if JVET_AA0146_WRAP_AROUND_FIX
 #if JVET_AF0190_RPR_TMP_REORDER_LIC
   xGetSublkTemplate(*pu.cu, compID, refPic, mv, pu.blocks[compID].width, pu.blocks[compID].height, 0, 0, numTemplate, refLeftTemplate, refAboveTemplate, recLeftTemplate, recAboveTemplate, wrapRef, scalingRatio);
@@ -17617,7 +19713,29 @@ void InterPrediction::xLocalIlluComp(const PredictionUnit& pu,
 #endif
 
   int shift = 0, scale = 0, offset = 0;
+#if JVET_AG0276_NLIC
+  if (m_skipDoLic)
+  {
+    shift = shift_s; scale = scale_s; offset = offset_s;
+  }
+  else
+  {
+#endif
+#if JVET_AG0276_LIC_SLOPE_ADJUST
+  int midVal[1] = {0};
+#if JVET_AE0078_IBC_LIC_EXTENSION
+  xGetLICParamGeneral(*pu.cu, compID, numTemplate, refLeftTemplate, refAboveTemplate, recLeftTemplate, recAboveTemplate, shift, scale, offset, nullptr, nullptr, nullptr, nullptr, midVal);
+#else
+  xGetLICParamGeneral(*pu.cu, compID, numTemplate, refLeftTemplate, refAboveTemplate, recLeftTemplate, recAboveTemplate, shift, scale, offset, midVal);
+#endif
+  xUpdateLicModel(scale, offset, shift, midVal[0], pu.cu->licDelta);
+#else
   xGetLICParamGeneral(*pu.cu, compID, numTemplate, refLeftTemplate, refAboveTemplate, recLeftTemplate, recAboveTemplate, shift, scale, offset);
+#endif
+#if JVET_AG0276_NLIC
+  shift_s = shift; scale_s = scale; offset_s = offset;
+  }
+#endif
 #if JVET_AD0213_LIC_IMP
   if (!biPred)
   {
@@ -17715,7 +19833,6 @@ void InterPrediction::xGetSublkTemplate(const CodingUnit& cu,
     }
 #else
     const Pel*    rec = recBuf.bufAt(cu.blocks[compID].pos().offset(0, -1));
-
     for (int k = posW; k < posW + sublkWidth; k++)
     {
       int refVal = refAboveTemplate[k];
@@ -18105,6 +20222,88 @@ void InterPrediction::xLicCompAdj(const PredictionUnit& pu, PelUnitBuf& pcYuvPre
 #endif
   }
 }
+#if JVET_AG0276_LIC_BDOF_BDMVR
+void InterPrediction::xLicCompAdjBdof(const PredictionUnit& pu, PelUnitBuf& pcYuvPred, const bool lumaOnly, const bool chromaOnly)
+{
+  for (uint32_t licIdx = 0; licIdx < NUM_LIC_ITERATION; licIdx++)
+  {
+    int licRefList = (licIdx % 2);
+
+    for (int compID = 0; compID < MAX_NUM_COMPONENT; compID++)
+    {
+      if (isLuma(ComponentID(compID)) && chromaOnly)
+      {
+        continue;
+      }
+      if (isChroma(ComponentID(compID)) && lumaOnly)
+      {
+        continue;
+      }
+
+      xLicRemHighFreq(*pu.cu, compID, licIdx);
+      xGetLICParamGeneral(*pu.cu, ComponentID(compID), m_numTemplate[compID], m_pcLICRefLeftTemplate[licRefList][compID], m_pcLICRefAboveTemplate[licRefList][compID], m_curLICRecLeftTemplate[compID], m_curLICRecAboveTemplate[compID], m_shift[licRefList][compID], m_scale[licRefList][compID], m_offset[licRefList][compID]);
+
+      const ClpRng& clpRng = pu.cu->slice->clpRng(ComponentID(compID));
+      if (licIdx < (NUM_LIC_ITERATION - 1))
+      {
+        if (m_numTemplate[compID][0])
+        {
+          int cWidth = pu.blocks[compID].width;
+          PelBuf aboveTemplate(m_pcLICRefAboveTemplate[licRefList][compID], Size(cWidth, 1));
+          PelBuf curAboveTemplate(m_curLICRefAboveTemplate[licRefList][compID], Size(cWidth, 1));
+          curAboveTemplate.copyFrom(aboveTemplate);
+          curAboveTemplate.linearTransform(m_scale[licRefList][compID], m_shift[licRefList][compID], m_offset[licRefList][compID], true, clpRng);
+        }
+        if (m_numTemplate[compID][1])
+        {
+          int cHeight = pu.blocks[compID].height;
+          PelBuf leftTemplate(m_pcLICRefLeftTemplate[licRefList][compID], Size(cHeight, 1));
+          PelBuf curLeftTemplate(m_curLICRefLeftTemplate[licRefList][compID], Size(cHeight, 1));
+          curLeftTemplate.copyFrom(leftTemplate);
+          curLeftTemplate.linearTransform(m_scale[licRefList][compID], m_shift[licRefList][compID], m_offset[licRefList][compID], true, clpRng);
+        }
+      }
+    }
+  }
+
+  const Pel biOffset = -IF_INTERNAL_OFFS;
+  for (int refList = 0; refList < NUM_REF_PIC_LIST_01; refList++)
+  {
+    PelUnitBuf curSrcPred = (refList == 0) ? PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvPred[0][0], pcYuvPred.Y()), PelBuf(m_acYuvPred[0][1], pcYuvPred.Cb()), PelBuf(m_acYuvPred[0][2], pcYuvPred.Cr())) :
+      PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvPred[1][0], pcYuvPred.Y()), PelBuf(m_acYuvPred[1][1], pcYuvPred.Cb()), PelBuf(m_acYuvPred[1][2], pcYuvPred.Cr()));
+    for (int compID = 0; compID < MAX_NUM_COMPONENT; compID++)
+    {
+      if (isLuma(ComponentID(compID)) && chromaOnly)
+      {
+        continue;
+      }
+      if (isChroma(ComponentID(compID)) && lumaOnly)
+      {
+        continue;
+      }
+      if (compID == COMPONENT_Y)
+      {
+        curSrcPred.bufs[compID].height += ((BIO_EXTEND_SIZE + 1) << 1);
+        curSrcPred.bufs[compID].width += ((BIO_EXTEND_SIZE + 1) << 1);
+        curSrcPred.bufs[compID].stride += ((BIO_EXTEND_SIZE + 1) << 1);
+        curSrcPred.bufs[compID].buf = m_filteredBlockTmp[2 + refList][compID];
+      }
+      const ClpRng& clpRng = pu.cu->slice->clpRng(ComponentID(compID));
+      const int biShift = IF_INTERNAL_PREC - clpRng.bd;
+      curSrcPred.bufs[compID].toLast(clpRng);
+      curSrcPred.bufs[compID].linearTransform(m_scale[refList][compID], m_shift[refList][compID], m_offset[refList][compID], true, clpRng);
+      curSrcPred.bufs[compID].linearTransform(1, -biShift, biOffset, false, clpRng);
+      if (compID == COMPONENT_Y)
+      {
+        if (refList == 1)
+        {
+          m_fillLicTpl[compID] = false;
+        }
+      }
+    }
+  }
+}
+#endif
 #endif
 
 #if INTER_LIC || JVET_AC0112_IBC_LIC
@@ -18124,6 +20323,9 @@ void InterPrediction::xGetLICParamGeneral(const CodingUnit& cu,
                                           int*              offset2,
                                           int*              mean
 #endif
+#if JVET_AG0276_LIC_SLOPE_ADJUST
+                                          , int *midVal
+#endif
 )
 {
   const int       cuWidth = cu.blocks[compID].width;
@@ -18150,6 +20352,10 @@ void InterPrediction::xGetLICParamGeneral(const CodingUnit& cu,
   int recSamples[MAX_CU_SIZE] = { 0 };
   int startPos = (numTemplate[0] != 0) ? numSteps : 0;
 #endif
+#if JVET_AG0276_LIC_SLOPE_ADJUST
+  int sumVal = 0;
+  int numPels = numTemplate[0] != 0 && numTemplate[1] != 0 ? 2*numSteps : (numTemplate[0] != 0 || numTemplate[1] != 0 ? numSteps : 0);
+#endif
 
   // above
   if (numTemplate[0] != 0)
@@ -18168,6 +20374,9 @@ void InterPrediction::xGetLICParamGeneral(const CodingUnit& cu,
       y += recVal;
       xx += refVal * refVal;
       xy += refVal * recVal;
+#if JVET_AG0276_LIC_SLOPE_ADJUST
+      sumVal += refVal;
+#endif
     }
 
     cntShift = dimShift;
@@ -18190,10 +20399,19 @@ void InterPrediction::xGetLICParamGeneral(const CodingUnit& cu,
       y += recVal;
       xx += refVal * refVal;
       xy += refVal * recVal;
+#if JVET_AG0276_LIC_SLOPE_ADJUST
+      sumVal += refVal;
+#endif
     }
 
     cntShift += (cntShift ? 1 : dimShift);
   }
+#if JVET_AG0276_LIC_SLOPE_ADJUST
+  if (midVal)
+  {
+    *midVal = numPels ? PU::getMeanValue( sumVal + (numPels >> 1), numPels ) : 1 << (bitDepth - 1);
+  }
+#endif
 
   //----- determine scale and offset -----
 #if JVET_AE0078_IBC_LIC_EXTENSION
@@ -18661,6 +20879,28 @@ void InterPrediction::xGenerateIbcFilterPred(PelBuf& piPred, unsigned int uiBlkW
 }
 #endif
 
+#if JVET_AG0276_LIC_SLOPE_ADJUST
+void InterPrediction::xUpdateLicModel(int &scale, int &offset, int &shift, int midVal, int delta)
+{
+  if ( delta )
+  {
+    const int dShift = 3;
+    delta = scale > 0 ? -delta : delta;
+    if ( shift < dShift )
+    {
+      scale    <<= ( dShift - shift );
+      shift = dShift;
+    }
+    else if ( shift > dShift )
+    {
+      delta <<= ( shift - dShift );
+    }
+    scale += delta;
+    offset -= ( delta * midVal ) >> shift;
+  }
+}
+#endif
+
 #if INTER_LIC
 template <bool trueAfalseL>
 void InterPrediction::xGetPredBlkTpl(const CodingUnit& cu, const ComponentID compID, const CPelBuf& refBuf, const Mv& mv, const int posW, const int posH, const int tplSize, Pel* predBlkTpl
@@ -23095,11 +25335,136 @@ bool InterPrediction::processBDMVR(PredictionUnit& pu)
     else
 #endif
     {
+#if JVET_AG0276_LIC_FLAG_SIGNALING && JVET_AG0276_LIC_BDOF_BDMVR
+      if (pu.cu->licFlag == true && pu.cu->slice->getUseLIC() == true)
+      {
+        m_numTemplate[COMPONENT_Y][0] = 0;
+        m_numTemplate[COMPONENT_Y][1] = 0;
+        m_fillLicTpl[COMPONENT_Y] = false;
+        m_scale[0][COMPONENT_Y] = 1;
+        m_scale[1][COMPONENT_Y] = 1;
+        m_shift[0][COMPONENT_Y] = 0;
+        m_shift[1][COMPONENT_Y] = 0;
+        m_offset[0][COMPONENT_Y] = 0;
+        m_offset[1][COMPONENT_Y] = 0;
+
+        Mv mv0Clip = pu.mv[0], mv1Clip = pu.mv[1];
+        clipMv(mv0Clip, pu.lumaPos(), pu.lumaSize(), *pu.cs->sps, *pu.cs->pps);
+        clipMv(mv1Clip, pu.lumaPos(), pu.lumaSize(), *pu.cs->sps, *pu.cs->pps);
+        xGetSublkTemplateAndRef(*pu.cu, COMPONENT_Y, *pu.cu->slice->getRefPic(REF_PIC_LIST_0, pu.refIdx[0]), mv0Clip, pu.blocks[COMPONENT_Y].width, pu.blocks[COMPONENT_Y].height, 0, 0, m_numTemplate[COMPONENT_Y],
+          m_pcLICRefLeftTemplate[0][COMPONENT_Y], m_pcLICRefAboveTemplate[0][COMPONENT_Y],
+          m_pcLICRecLeftTemplate[COMPONENT_Y], m_pcLICRecAboveTemplate[COMPONENT_Y], true, true);
+        xGetSublkTemplateAndRef(*pu.cu, COMPONENT_Y, *pu.cu->slice->getRefPic(REF_PIC_LIST_1, pu.refIdx[1]), mv1Clip, pu.blocks[COMPONENT_Y].width, pu.blocks[COMPONENT_Y].height, 0, 0, m_numTemplate[COMPONENT_Y],
+          m_pcLICRefLeftTemplate[1][COMPONENT_Y], m_pcLICRefAboveTemplate[1][COMPONENT_Y],
+          m_pcLICRecLeftTemplate[COMPONENT_Y], m_pcLICRecAboveTemplate[COMPONENT_Y], false, true);
+        if (m_numTemplate[COMPONENT_Y][0] + m_numTemplate[COMPONENT_Y][1] > 0)
+        {
+          for (uint32_t licIdx = 0; licIdx < NUM_LIC_ITERATION; licIdx++)
+          {
+            int licRefList = (licIdx % 2);
+            xLicRemHighFreq(*pu.cu, COMPONENT_Y, licIdx);
+            xGetLICParamGeneral(*pu.cu, COMPONENT_Y, m_numTemplate[COMPONENT_Y],
+              m_pcLICRefLeftTemplate[licRefList][COMPONENT_Y], m_pcLICRefAboveTemplate[licRefList][COMPONENT_Y],
+              m_curLICRecLeftTemplate[COMPONENT_Y], m_curLICRecAboveTemplate[COMPONENT_Y],
+              m_shift[licRefList][COMPONENT_Y], m_scale[licRefList][COMPONENT_Y], m_offset[licRefList][COMPONENT_Y]);
+            const ClpRng& clpRng = pu.cu->slice->clpRng(COMPONENT_Y);
+            if (licIdx < (NUM_LIC_ITERATION - 1))
+            {
+              if (m_numTemplate[COMPONENT_Y][0])
+              {
+                int cWidth = pu.blocks[COMPONENT_Y].width;
+                PelBuf aboveTemplate(m_pcLICRefAboveTemplate[licRefList][COMPONENT_Y], Size(cWidth, 1));
+                PelBuf curAboveTemplate(m_curLICRefAboveTemplate[licRefList][COMPONENT_Y], Size(cWidth, 1));
+                curAboveTemplate.copyFrom(aboveTemplate);
+                curAboveTemplate.linearTransform(m_scale[licRefList][COMPONENT_Y], m_shift[licRefList][COMPONENT_Y], m_offset[licRefList][COMPONENT_Y], true, clpRng);
+              }
+              if (m_numTemplate[COMPONENT_Y][1])
+              {
+                int cHeight = pu.blocks[COMPONENT_Y].height;
+                PelBuf leftTemplate(m_pcLICRefLeftTemplate[licRefList][COMPONENT_Y], Size(cHeight, 1));
+                PelBuf curLeftTemplate(m_curLICRefLeftTemplate[licRefList][COMPONENT_Y], Size(cHeight, 1));
+                curLeftTemplate.copyFrom(leftTemplate);
+                curLeftTemplate.linearTransform(m_scale[licRefList][COMPONENT_Y], m_shift[licRefList][COMPONENT_Y], m_offset[licRefList][COMPONENT_Y], true, clpRng);
+              }
+            }
+          }
+        }
+      }
+#endif
       minCost = xBDMVRMvSquareSearch<false>( mvFinal_PU, minCost, pu, mvInitial_PU, BDMVR_INTME_SQUARE_SEARCH_MAX_NUM_ITERATIONS, MV_FRACTIONAL_BITS_INTERNAL,     bUseMR, false );
       if (minCost > 0)
       {
+#if JVET_AG0276_LIC_FLAG_SIGNALING && JVET_AG0276_LIC_BDOF_BDMVR
+        if (pu.cu->licFlag == true && pu.cu->slice->getUseLIC() == true)
+        {
+          pu.mv[0] = mvFinal_PU[0];
+          pu.mv[1] = mvFinal_PU[1];
+
+          m_numTemplate[COMPONENT_Y][0] = 0;
+          m_numTemplate[COMPONENT_Y][1] = 0;
+          m_fillLicTpl[COMPONENT_Y] = false;
+          m_scale[0][COMPONENT_Y] = 1;
+          m_scale[1][COMPONENT_Y] = 1;
+          m_shift[0][COMPONENT_Y] = 0;
+          m_shift[1][COMPONENT_Y] = 0;
+          m_offset[0][COMPONENT_Y] = 0;
+          m_offset[1][COMPONENT_Y] = 0;
+          Mv mv0Clip = pu.mv[0], mv1Clip = pu.mv[1];
+          clipMv(mv0Clip, pu.lumaPos(), pu.lumaSize(), *pu.cs->sps, *pu.cs->pps);
+          clipMv(mv1Clip, pu.lumaPos(), pu.lumaSize(), *pu.cs->sps, *pu.cs->pps);
+          xGetSublkTemplateAndRef(*pu.cu, COMPONENT_Y, *pu.cu->slice->getRefPic(REF_PIC_LIST_0, pu.refIdx[0]), mv0Clip, pu.blocks[COMPONENT_Y].width, pu.blocks[COMPONENT_Y].height, 0, 0, m_numTemplate[COMPONENT_Y],
+            m_pcLICRefLeftTemplate[0][COMPONENT_Y], m_pcLICRefAboveTemplate[0][COMPONENT_Y],
+            m_pcLICRecLeftTemplate[COMPONENT_Y], m_pcLICRecAboveTemplate[COMPONENT_Y], true, true);
+          xGetSublkTemplateAndRef(*pu.cu, COMPONENT_Y, *pu.cu->slice->getRefPic(REF_PIC_LIST_1, pu.refIdx[1]), mv1Clip, pu.blocks[COMPONENT_Y].width, pu.blocks[COMPONENT_Y].height, 0, 0, m_numTemplate[COMPONENT_Y],
+            m_pcLICRefLeftTemplate[1][COMPONENT_Y], m_pcLICRefAboveTemplate[1][COMPONENT_Y],
+            m_pcLICRecLeftTemplate[COMPONENT_Y], m_pcLICRecAboveTemplate[COMPONENT_Y], false, true);
+          if (m_numTemplate[COMPONENT_Y][0] + m_numTemplate[COMPONENT_Y][1] > 0)
+          {
+            for (uint32_t licIdx = 0; licIdx < NUM_LIC_ITERATION; licIdx++)
+            {
+              int licRefList = (licIdx % 2);
+              xLicRemHighFreq(*pu.cu, COMPONENT_Y, licIdx);
+              xGetLICParamGeneral(*pu.cu, COMPONENT_Y, m_numTemplate[COMPONENT_Y],
+                m_pcLICRefLeftTemplate[licRefList][COMPONENT_Y], m_pcLICRefAboveTemplate[licRefList][COMPONENT_Y],
+                m_curLICRecLeftTemplate[COMPONENT_Y], m_curLICRecAboveTemplate[COMPONENT_Y],
+                m_shift[licRefList][COMPONENT_Y], m_scale[licRefList][COMPONENT_Y], m_offset[licRefList][COMPONENT_Y]);
+              const ClpRng& clpRng = pu.cu->slice->clpRng(COMPONENT_Y);
+              if (licIdx < (NUM_LIC_ITERATION - 1))
+              {
+                if (m_numTemplate[COMPONENT_Y][0])
+                {
+                  int cWidth = pu.blocks[COMPONENT_Y].width;
+                  PelBuf aboveTemplate(m_pcLICRefAboveTemplate[licRefList][COMPONENT_Y], Size(cWidth, 1));
+                  PelBuf curAboveTemplate(m_curLICRefAboveTemplate[licRefList][COMPONENT_Y], Size(cWidth, 1));
+                  curAboveTemplate.copyFrom(aboveTemplate);
+                  curAboveTemplate.linearTransform(m_scale[licRefList][COMPONENT_Y], m_shift[licRefList][COMPONENT_Y], m_offset[licRefList][COMPONENT_Y], true, clpRng);
+                }
+                if (m_numTemplate[COMPONENT_Y][1])
+                {
+                  int cHeight = pu.blocks[COMPONENT_Y].height;
+                  PelBuf leftTemplate(m_pcLICRefLeftTemplate[licRefList][COMPONENT_Y], Size(cHeight, 1));
+                  PelBuf curLeftTemplate(m_curLICRefLeftTemplate[licRefList][COMPONENT_Y], Size(cHeight, 1));
+                  curLeftTemplate.copyFrom(leftTemplate);
+                  curLeftTemplate.linearTransform(m_scale[licRefList][COMPONENT_Y], m_shift[licRefList][COMPONENT_Y], m_offset[licRefList][COMPONENT_Y], true, clpRng);
+                }
+              }
+            }
+          }
+        }
+#endif
         minCost = xBDMVRMvSquareSearch<true>(mvFinal_PU, minCost, pu, mvInitial_PU, 2, MV_FRACTIONAL_BITS_INTERNAL - 1, bUseMR, false);
       }
+#if JVET_AG0276_LIC_FLAG_SIGNALING && JVET_AG0276_LIC_BDOF_BDMVR
+      m_numTemplate[COMPONENT_Y][0] = 0;
+      m_numTemplate[COMPONENT_Y][1] = 0;
+      m_fillLicTpl[COMPONENT_Y] = false;
+      m_scale[0][COMPONENT_Y] = 1;
+      m_scale[1][COMPONENT_Y] = 1;
+      m_shift[0][COMPONENT_Y] = 0;
+      m_shift[1][COMPONENT_Y] = 0;
+      m_offset[0][COMPONENT_Y] = 0;
+      m_offset[1][COMPONENT_Y] = 0;
+#endif
     }
 #else
     minCost = xBDMVRMvSquareSearch( mvFinal_PU, minCost, pu, mvInitial_PU, BDMVR_INTME_SQUARE_SEARCH_MAX_NUM_ITERATIONS, MV_FRACTIONAL_BITS_INTERNAL,     bUseMR, false );
@@ -23141,7 +25506,12 @@ bool InterPrediction::processBDMVR(PredictionUnit& pu)
     return true;
   }
 #endif
-
+#if JVET_AG0276_LIC_BDOF_BDMVR
+  if (pu.cu->licFlag == true)
+  {
+    subPURefine = false;
+  }
+#endif
   if (!subPURefine)
   {
     // span motion to subPU
@@ -24232,6 +26602,12 @@ Distortion InterPrediction::xBDMVRMvSquareSearch(Mv (&curBestMv)[2], Distortion
 
     for( int nIdx = nDirectStart ; nIdx <= nDirectEnd ; nIdx++ )
     {
+#if JVET_AG0276_LIC_BDOF_BDMVR
+      if (curBestCost == 0)
+      {
+        return curBestCost;
+      }
+#endif
       int nDirect = ( nIdx + nDirectRounding ) & nDirectMask;
 
       Mv mvOffset(cSearchOffset[nDirect].getHor() << searchStepShift, cSearchOffset[nDirect].getVer() << searchStepShift);
@@ -25048,6 +27424,48 @@ Distortion InterPrediction::xBDMVRGetMatchingError(const PredictionUnit& pu, con
     xBDMVRPreInterpolation( pu, mvCenter, searchStepShift == MV_FRACTIONAL_BITS_INTERNAL, searchStepShift == MV_FRACTIONAL_BITS_INTERNAL - 1 );
 #endif
     doPreInterpolation = false;
+#if JVET_AG0276_LIC_BDOF_BDMVR
+    bool applyLicToDmvr = false;
+    applyLicToDmvr |= (pu.amvpMergeModeFlag[0] || pu.amvpMergeModeFlag[1]);
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+    applyLicToDmvr |= (pu.amvpMergeModeFlag[0] == false && pu.amvpMergeModeFlag[1] == false && pu.bmMergeFlag == false);
+#endif
+    applyLicToDmvr &= (pu.cu->licFlag == true && pu.cu->slice->getUseLIC() == true);
+    applyLicToDmvr &= (m_scale[0][COMPONENT_Y] != 0 && m_scale[1][COMPONENT_Y] != 0);
+    if (applyLicToDmvr == true)
+    {
+      const ClpRng& clpRng = pu.cu->slice->clpRng(COMPONENT_Y);
+      for (int refList = 0; refList < NUM_REF_PIC_LIST_01; refList++)
+      {
+        if (searchStepShift == MV_FRACTIONAL_BITS_INTERNAL)
+        {
+          int dstStride = MAX_CU_SIZE + (BDMVR_INTME_RANGE << 1) + (BDMVR_SIMD_IF_FACTOR - 2);
+          int iWidthExt = (int)pu.lwidth() + (BDMVR_INTME_RANGE << 1);
+          int iHeightExt = (int)pu.lheight() + (BDMVR_INTME_RANGE << 1);
+          int iWidthOffset = BDMVR_SIMD_IF_FACTOR - (iWidthExt & (BDMVR_SIMD_IF_FACTOR - 1));
+          iWidthOffset &= (BDMVR_SIMD_IF_FACTOR - 1);
+          iWidthExt += iWidthOffset; // This ensures that iWidthExt is a factor-of-n number, assuming BDMVR_SIMD_IF_FACTOR is equal to n
+          PelUnitBuf curSrcPred = (PelUnitBuf(pu.chromaFormat, PelBuf(m_filteredBlock[3][refList][0], dstStride, iWidthExt, iHeightExt)));
+          curSrcPred.bufs[COMPONENT_Y].linearTransform(m_scale[refList][COMPONENT_Y], m_shift[refList][COMPONENT_Y], m_offset[refList][COMPONENT_Y], true, clpRng);
+        }
+        if (searchStepShift == MV_FRACTIONAL_BITS_INTERNAL - 1)
+        {
+          for (int phaseIdx = 0; phaseIdx < 3; phaseIdx++)
+          {
+            int iRefStride = MAX_CU_SIZE + (BDMVR_INTME_RANGE << 1) + (BDMVR_SIMD_IF_FACTOR - 2);
+            int iWidthExt = (int)pu.lwidth() + 1 - (phaseIdx >> 1);
+            int iHeightExt = (int)pu.lheight() + 1 - ((2 - phaseIdx) >> 1);
+            int iWidthOffset = BDMVR_SIMD_IF_FACTOR - (iWidthExt & (BDMVR_SIMD_IF_FACTOR - 1));
+            iWidthOffset &= (BDMVR_SIMD_IF_FACTOR - 1);
+            iWidthExt += iWidthOffset; // This ensures that iWidthExt is a factor-of-n number, assuming BDMVR_SIMD_IF_FACTOR is equal to n
+            PelUnitBuf curSrcPred = PelUnitBuf(pu.chromaFormat, PelBuf(m_filteredBlock[phaseIdx][refList][0], iRefStride, iWidthExt, iHeightExt));
+            curSrcPred.bufs[COMPONENT_Y].linearTransform(m_scale[refList][COMPONENT_Y], m_shift[refList][COMPONENT_Y], m_offset[refList][COMPONENT_Y], true, clpRng);
+          }
+        }
+      }
+
+    }
+#endif
   }
 
   // Locate L0'a and L1's prediction blocks in pre-interpolation buffer
@@ -25159,6 +27577,10 @@ void InterPrediction::xAddHypMC(PredictionUnit& pu, PelUnitBuf& predBuf, PelUnit
   PelUnitBuf tempBuf = m_additionalHypothesisStorage.getBuf(unitAreaFromPredBuf);
   const auto savedAffine = pu.cu->affine;
   const auto savedIMV = pu.cu->imv;
+#if JVET_AG0276_NLIC
+  auto savedAltLMFlag = pu.cu->altLMFlag;
+  auto savedAltLMParaUnit = pu.cu->altLMParaUnit;
+#endif
 #if INTER_LIC
   auto savedLICFlag = pu.cu->licFlag;
 #endif
@@ -25195,6 +27617,10 @@ void InterPrediction::xAddHypMC(PredictionUnit& pu, PelUnitBuf& predBuf, PelUnit
     fakePredData.mv[iRefPicList] = mhData.mv;
     fakePredData.refIdx[iRefPicList] = iRefIdx;
     fakePredData.refIdx[1 - iRefPicList] = -1;
+#if JVET_AG0276_NLIC
+    fakePredData.cu->altLMFlag = false;
+    fakePredData.cu->altLMParaUnit.resetAltLinearModel();
+#endif
 #if INTER_LIC
     fakePredData.cu->licFlag = mhData.licFlag;
 #if JVET_AD0213_LIC_IMP
@@ -25212,6 +27638,10 @@ void InterPrediction::xAddHypMC(PredictionUnit& pu, PelUnitBuf& predBuf, PelUnit
     CHECK(mhData.weightIdx >= MULTI_HYP_PRED_NUM_WEIGHTS, "Multi Hyp: mhData.weightIdx >= MULTI_HYP_PRED_NUM_WEIGHTS");
     predBuf.addHypothesisAndClip(tempBuf, g_addHypWeight[mhData.weightIdx], pu.cs->slice->clpRngs(), lumaOnly);
   }
+#if JVET_AG0276_NLIC
+  pu.cu->altLMFlag = savedAltLMFlag;
+  pu.cu->altLMParaUnit = savedAltLMParaUnit;
+#endif
 #if INTER_LIC
   pu.cu->licFlag = savedLICFlag;
 #endif
@@ -25255,6 +27685,7 @@ void InterPrediction::getAmvpMergeModeMergeList(PredictionUnit& pu, MvField* mvF
 #if !JVET_Y0128_NON_CTC
   const int curPoc = pu.cu->slice->getPOC();
 #endif
+
 #if JVET_AD0213_LIC_IMP
   bool orgLICFlag = pu.cu->licFlag;
 #endif
@@ -25629,7 +28060,11 @@ void InterPrediction::amvpMergeModeMvRefinement(PredictionUnit& pu, MvField* mvF
   {
 #endif
 #if JVET_AD0213_LIC_IMP
+#if JVET_AG0276_LIC_BDOF_BDMVR
+    if ((mergeRefPoc - curPoc) == (curPoc - amvpRefPoc))
+#else
     if ((mergeRefPoc - curPoc) == (curPoc - amvpRefPoc) && !pu.cu->licFlag)
+#endif
 #else
   if ((mergeRefPoc - curPoc) == (curPoc - amvpRefPoc))
 #endif
@@ -25640,15 +28075,143 @@ void InterPrediction::amvpMergeModeMvRefinement(PredictionUnit& pu, MvField* mvF
     Mv         mvFinal[2] = { mvInitial[0], mvInitial[1] };
     Distortion curBmCost = std::numeric_limits<Distortion>::max();
 #if JVET_X0049_BDMVR_SW_OPT
+#if JVET_AG0276_LIC_BDOF_BDMVR
+    if (pu.cu->licFlag == true && pu.cu->slice->getUseLIC() == true)
+    {
+      m_numTemplate[COMPONENT_Y][0] = 0;
+      m_numTemplate[COMPONENT_Y][1] = 0;
+      m_fillLicTpl[COMPONENT_Y] = false;
+      m_scale[0][COMPONENT_Y] = 1;
+      m_scale[1][COMPONENT_Y] = 1;
+      m_shift[0][COMPONENT_Y] = 0;
+      m_shift[1][COMPONENT_Y] = 0;
+      m_offset[0][COMPONENT_Y] = 0;
+      m_offset[1][COMPONENT_Y] = 0;
+      Mv mv0Clip = pu.mv[0], mv1Clip = pu.mv[1];
+      clipMv(mv0Clip, pu.lumaPos(), pu.lumaSize(), *pu.cs->sps, *pu.cs->pps);
+      clipMv(mv1Clip, pu.lumaPos(), pu.lumaSize(), *pu.cs->sps, *pu.cs->pps);
+      xGetSublkTemplateAndRef(*pu.cu, COMPONENT_Y, *pu.cu->slice->getRefPic(REF_PIC_LIST_0, pu.refIdx[0]), mv0Clip, pu.blocks[COMPONENT_Y].width, pu.blocks[COMPONENT_Y].height, 0, 0, m_numTemplate[COMPONENT_Y],
+        m_pcLICRefLeftTemplate[0][COMPONENT_Y], m_pcLICRefAboveTemplate[0][COMPONENT_Y],
+        m_pcLICRecLeftTemplate[COMPONENT_Y], m_pcLICRecAboveTemplate[COMPONENT_Y], true, true);
+      xGetSublkTemplateAndRef(*pu.cu, COMPONENT_Y, *pu.cu->slice->getRefPic(REF_PIC_LIST_1, pu.refIdx[1]), mv1Clip, pu.blocks[COMPONENT_Y].width, pu.blocks[COMPONENT_Y].height, 0, 0, m_numTemplate[COMPONENT_Y],
+        m_pcLICRefLeftTemplate[1][COMPONENT_Y], m_pcLICRefAboveTemplate[1][COMPONENT_Y],
+        m_pcLICRecLeftTemplate[COMPONENT_Y], m_pcLICRecAboveTemplate[COMPONENT_Y], false, true);
+      if (m_numTemplate[COMPONENT_Y][0] + m_numTemplate[COMPONENT_Y][1] > 0)
+      {
+        for (uint32_t licIdx = 0; licIdx < NUM_LIC_ITERATION; licIdx++)
+        {
+          int licRefList = (licIdx % 2);
+          xLicRemHighFreq(*pu.cu, COMPONENT_Y, licIdx);
+          xGetLICParamGeneral(*pu.cu, COMPONENT_Y, m_numTemplate[COMPONENT_Y],
+            m_pcLICRefLeftTemplate[licRefList][COMPONENT_Y], m_pcLICRefAboveTemplate[licRefList][COMPONENT_Y],
+            m_curLICRecLeftTemplate[COMPONENT_Y], m_curLICRecAboveTemplate[COMPONENT_Y],
+            m_shift[licRefList][COMPONENT_Y], m_scale[licRefList][COMPONENT_Y], m_offset[licRefList][COMPONENT_Y]);
+          const ClpRng& clpRng = pu.cu->slice->clpRng(COMPONENT_Y);
+          if (licIdx < (NUM_LIC_ITERATION - 1))
+          {
+            if (m_numTemplate[COMPONENT_Y][0])
+            {
+              int cWidth = pu.blocks[COMPONENT_Y].width;
+              PelBuf aboveTemplate(m_pcLICRefAboveTemplate[licRefList][COMPONENT_Y], Size(cWidth, 1));
+              PelBuf curAboveTemplate(m_curLICRefAboveTemplate[licRefList][COMPONENT_Y], Size(cWidth, 1));
+              curAboveTemplate.copyFrom(aboveTemplate);
+              curAboveTemplate.linearTransform(m_scale[licRefList][COMPONENT_Y], m_shift[licRefList][COMPONENT_Y], m_offset[licRefList][COMPONENT_Y], true, clpRng);
+            }
+            if (m_numTemplate[COMPONENT_Y][1])
+            {
+              int cHeight = pu.blocks[COMPONENT_Y].height;
+              PelBuf leftTemplate(m_pcLICRefLeftTemplate[licRefList][COMPONENT_Y], Size(cHeight, 1));
+              PelBuf curLeftTemplate(m_curLICRefLeftTemplate[licRefList][COMPONENT_Y], Size(cHeight, 1));
+              curLeftTemplate.copyFrom(leftTemplate);
+              curLeftTemplate.linearTransform(m_scale[licRefList][COMPONENT_Y], m_shift[licRefList][COMPONENT_Y], m_offset[licRefList][COMPONENT_Y], true, clpRng);
+            }
+          }
+        }
+      }
+    }
+#endif
     curBmCost = xBDMVRMvSquareSearch<false>(mvFinal, curBmCost, pu, mvInitial,
         AMVP_MERGE_MODE_REDUCED_MV_REFINE_SEARCH_ROUND, MV_FRACTIONAL_BITS_INTERNAL, useMR, false);
-    curBmCost = xBDMVRMvSquareSearch<true>(mvFinal, curBmCost, pu, mvInitial,
-      2, MV_FRACTIONAL_BITS_INTERNAL - 1, useMR, false);
+#if JVET_AG0276_LIC_BDOF_BDMVR
+    if (pu.cu->licFlag == true && pu.cu->slice->getUseLIC() == true && curBmCost > 0)
+    {
+      pu.mv[0] = mvFinal[0];
+      pu.mv[1] = mvFinal[1];
+      m_numTemplate[COMPONENT_Y][0] = 0;
+      m_numTemplate[COMPONENT_Y][1] = 0;
+      m_fillLicTpl[COMPONENT_Y] = false;
+      m_scale[0][COMPONENT_Y] = 1;
+      m_scale[1][COMPONENT_Y] = 1;
+      m_shift[0][COMPONENT_Y] = 0;
+      m_shift[1][COMPONENT_Y] = 0;
+      m_offset[0][COMPONENT_Y] = 0;
+      m_offset[1][COMPONENT_Y] = 0;
+      Mv mv0Clip = pu.mv[0], mv1Clip = pu.mv[1];
+      clipMv(mv0Clip, pu.lumaPos(), pu.lumaSize(), *pu.cs->sps, *pu.cs->pps);
+      clipMv(mv1Clip, pu.lumaPos(), pu.lumaSize(), *pu.cs->sps, *pu.cs->pps);
+      xGetSublkTemplateAndRef(*pu.cu, COMPONENT_Y, *pu.cu->slice->getRefPic(REF_PIC_LIST_0, pu.refIdx[0]), mv0Clip, pu.blocks[COMPONENT_Y].width, pu.blocks[COMPONENT_Y].height, 0, 0, m_numTemplate[COMPONENT_Y],
+        m_pcLICRefLeftTemplate[0][COMPONENT_Y], m_pcLICRefAboveTemplate[0][COMPONENT_Y],
+        m_pcLICRecLeftTemplate[COMPONENT_Y], m_pcLICRecAboveTemplate[COMPONENT_Y], true, true);
+      xGetSublkTemplateAndRef(*pu.cu, COMPONENT_Y, *pu.cu->slice->getRefPic(REF_PIC_LIST_1, pu.refIdx[1]), mv1Clip, pu.blocks[COMPONENT_Y].width, pu.blocks[COMPONENT_Y].height, 0, 0, m_numTemplate[COMPONENT_Y],
+        m_pcLICRefLeftTemplate[1][COMPONENT_Y], m_pcLICRefAboveTemplate[1][COMPONENT_Y],
+        m_pcLICRecLeftTemplate[COMPONENT_Y], m_pcLICRecAboveTemplate[COMPONENT_Y], false, true);
+      if (m_numTemplate[COMPONENT_Y][0] + m_numTemplate[COMPONENT_Y][1] > 0)
+      {
+        for (uint32_t licIdx = 0; licIdx < NUM_LIC_ITERATION; licIdx++)
+        {
+          int licRefList = (licIdx % 2);
+          xLicRemHighFreq(*pu.cu, COMPONENT_Y, licIdx);
+          xGetLICParamGeneral(*pu.cu, COMPONENT_Y, m_numTemplate[COMPONENT_Y],
+            m_pcLICRefLeftTemplate[licRefList][COMPONENT_Y], m_pcLICRefAboveTemplate[licRefList][COMPONENT_Y],
+            m_curLICRecLeftTemplate[COMPONENT_Y], m_curLICRecAboveTemplate[COMPONENT_Y],
+            m_shift[licRefList][COMPONENT_Y], m_scale[licRefList][COMPONENT_Y], m_offset[licRefList][COMPONENT_Y]);
+          const ClpRng& clpRng = pu.cu->slice->clpRng(COMPONENT_Y);
+          if (licIdx < (NUM_LIC_ITERATION - 1))
+          {
+            if (m_numTemplate[COMPONENT_Y][0])
+            {
+              int cWidth = pu.blocks[COMPONENT_Y].width;
+              PelBuf aboveTemplate(m_pcLICRefAboveTemplate[licRefList][COMPONENT_Y], Size(cWidth, 1));
+              PelBuf curAboveTemplate(m_curLICRefAboveTemplate[licRefList][COMPONENT_Y], Size(cWidth, 1));
+              curAboveTemplate.copyFrom(aboveTemplate);
+              curAboveTemplate.linearTransform(m_scale[licRefList][COMPONENT_Y], m_shift[licRefList][COMPONENT_Y], m_offset[licRefList][COMPONENT_Y], true, clpRng);
+            }
+            if (m_numTemplate[COMPONENT_Y][1])
+            {
+              int cHeight = pu.blocks[COMPONENT_Y].height;
+              PelBuf leftTemplate(m_pcLICRefLeftTemplate[licRefList][COMPONENT_Y], Size(cHeight, 1));
+              PelBuf curLeftTemplate(m_curLICRefLeftTemplate[licRefList][COMPONENT_Y], Size(cHeight, 1));
+              curLeftTemplate.copyFrom(leftTemplate);
+              curLeftTemplate.linearTransform(m_scale[licRefList][COMPONENT_Y], m_shift[licRefList][COMPONENT_Y], m_offset[licRefList][COMPONENT_Y], true, clpRng);
+            }
+          }
+        }
+      }
+    }
+#endif
+#if JVET_AG0276_LIC_BDOF_BDMVR
+    if (curBmCost > 0)
+#endif
+    {
+      curBmCost = xBDMVRMvSquareSearch<true>(mvFinal, curBmCost, pu, mvInitial,
+        2, MV_FRACTIONAL_BITS_INTERNAL - 1, useMR, false);
+    }
 #else
     curBmCost = xBDMVRMvSquareSearch( mvFinal, curBmCost, pu, mvInitial,
         AMVP_MERGE_MODE_REDUCED_MV_REFINE_SEARCH_ROUND, MV_FRACTIONAL_BITS_INTERNAL, useMR, false );
     curBmCost = xBDMVRMvSquareSearch( mvFinal, curBmCost, pu, mvInitial,
         2, MV_FRACTIONAL_BITS_INTERNAL - 1, useMR, false );
+#endif
+#if JVET_AG0276_LIC_BDOF_BDMVR
+    m_numTemplate[COMPONENT_Y][0] = 0;
+    m_numTemplate[COMPONENT_Y][1] = 0;
+    m_fillLicTpl[COMPONENT_Y] = false;
+    m_scale[0][COMPONENT_Y] = 1;
+    m_scale[1][COMPONENT_Y] = 1;
+    m_shift[0][COMPONENT_Y] = 0;
+    m_shift[1][COMPONENT_Y] = 0;
+    m_offset[0][COMPONENT_Y] = 0;
+    m_offset[1][COMPONENT_Y] = 0;
 #endif
     pu.mv[refListMerge] = mvFinal[refListMerge];
     pu.mv[refListAmvp] = mvFinal[refListAmvp];
@@ -27254,8 +29817,13 @@ void InterPrediction::reorderRefPairList(PredictionUnit &pu, std::vector<RefPicP
                 // buffer setting
                 CPelBuf srcRecAboveTemplate(m_acYuvCurAMLTemplate[0][0], Size(cWidth, 1));
                 PelBuf dstRecAboveTemplate(m_pcLICRecAboveTemplate[0], Size(cWidth, 1));
+#if JVET_AG0276_NLIC
+                CPelBuf srcRecLeftTemplate(m_acYuvCurAMLTemplate[1][0], Size(cHeight, 1));
+                PelBuf dstRecLeftTemplate(m_pcLICRecLeftTemplate[0], Size(cHeight, 1));
+#else
                 CPelBuf srcRecLeftTemplate(m_acYuvCurAMLTemplate[1][0], Size(1, cHeight));
                 PelBuf dstRecLeftTemplate(m_pcLICRecLeftTemplate[0], Size(1, cHeight));
+#endif
                 dstRecAboveTemplate.copyFrom(srcRecAboveTemplate);
                 dstRecLeftTemplate.copyFrom(srcRecLeftTemplate);
 
@@ -27270,8 +29838,13 @@ void InterPrediction::reorderRefPairList(PredictionUnit &pu, std::vector<RefPicP
 
                   CPelBuf srcRefAboveTemplate(srcTplAbovePtr[refList], Size(cWidth, 1));
                   PelBuf dstRefAboveTemplate(m_pcLICRefAboveTemplate[refList][0], Size(cWidth, 1));
+#if JVET_AG0276_NLIC
+                  CPelBuf srcRefLeftTemplate(srcTplLeftPtr[refList], Size(cHeight, 1));
+                  PelBuf dstRefLeftTemplate(m_pcLICRefLeftTemplate[refList][0], Size(cHeight, 1));
+#else
                   CPelBuf srcRefLeftTemplate(srcTplLeftPtr[refList], Size(1, cHeight));
                   PelBuf dstRefLeftTemplate(m_pcLICRefLeftTemplate[refList][0], Size(1, cHeight));
+#endif
 
                   const ClpRng& clpRng = pu.cu->cs->slice->clpRng(COMPONENT_Y);
                   if (m_bAMLTemplateAvailabe[0])
@@ -27660,8 +30233,13 @@ void InterPrediction::reorderRefPairList(PredictionUnit &pu, std::vector<RefPicP
             // buffer setting
             CPelBuf srcRecAboveTemplate(m_acYuvCurAMLTemplate[0][0], Size(cWidth, 1));
             PelBuf dstRecAboveTemplate(m_pcLICRecAboveTemplate[0], Size(cWidth, 1));
+#if JVET_AG0276_NLIC
+            CPelBuf srcRecLeftTemplate(m_acYuvCurAMLTemplate[1][0], Size(cHeight, 1));
+            PelBuf dstRecLeftTemplate(m_pcLICRecLeftTemplate[0], Size(cHeight, 1));
+#else
             CPelBuf srcRecLeftTemplate(m_acYuvCurAMLTemplate[1][0], Size(1, cHeight));
             PelBuf dstRecLeftTemplate(m_pcLICRecLeftTemplate[0], Size(1, cHeight));
+#endif
             dstRecAboveTemplate.copyFrom(srcRecAboveTemplate);
             dstRecLeftTemplate.copyFrom(srcRecLeftTemplate);
 
@@ -27676,8 +30254,13 @@ void InterPrediction::reorderRefPairList(PredictionUnit &pu, std::vector<RefPicP
 
               CPelBuf srcRefAboveTemplate(srcTplAbovePtr[refList], Size(cWidth, 1));
               PelBuf dstRefAboveTemplate(m_pcLICRefAboveTemplate[refList][0], Size(cWidth, 1));
+#if JVET_AG0276_NLIC
+              CPelBuf srcRefLeftTemplate(srcTplLeftPtr[refList], Size(cHeight, 1));
+              PelBuf dstRefLeftTemplate(m_pcLICRefLeftTemplate[refList][0], Size(cHeight, 1));
+#else
               CPelBuf srcRefLeftTemplate(srcTplLeftPtr[refList], Size(1, cHeight));
               PelBuf dstRefLeftTemplate(m_pcLICRefLeftTemplate[refList][0], Size(1, cHeight));
+#endif
 
               const ClpRng& clpRng = pu.cu->cs->slice->clpRng(COMPONENT_Y);
               if (m_bAMLTemplateAvailabe[0])
diff --git a/source/Lib/CommonLib/InterPrediction.h b/source/Lib/CommonLib/InterPrediction.h
index f4bcf5ac6..e569089bb 100644
--- a/source/Lib/CommonLib/InterPrediction.h
+++ b/source/Lib/CommonLib/InterPrediction.h
@@ -173,6 +173,9 @@ public:
   bool              m_isAddHypMC;
 #endif
   bool              m_storeBeforeLIC;
+#if JVET_AG0276_NLIC
+  bool              m_skipDoLic;
+#endif
 #endif
 #if JVET_AD0140_MVD_PREDICTION
   struct MvdDerivedInfo
@@ -1066,6 +1069,10 @@ public:
     , int sortedCandNum = -1
 #endif
   );
+#if JVET_AG0276_NLIC
+  void    adjustAffineMergeCandidates(PredictionUnit &pu, AffineMergeCtx& affMrgCtx, AltLMAffineMergeCtx& altLMAffMrgCtx, AltLMAffineMergeCtx& altLMRMVFMrgCtx);
+  void    updateAffineCandInThreeGrp(PredictionUnit &pu, AffineMergeCtx& affMrgCtx, AffineMergeCtx& altLMAffMrgCtx, AffineMergeCtx& altLMAffMrgCtx1, uint32_t* rdCandList, uint32_t* rdCandGrpList, int listsize);
+#endif
   void    updateAffineCandInfo(PredictionUnit &pu, AffineMergeCtx& affMrgCtx, 
 #if JVET_AA0107_RMVF_AFFINE_MERGE_DERIVATION  
     uint32_t(*RdCandList)[RMVF_AFFINE_MRG_MAX_CAND_LIST_SIZE], 
@@ -1146,6 +1153,9 @@ public:
 #if JVET_Z0102_NO_ARMC_FOR_ZERO_CAND
   void adjustMergeCandidates(PredictionUnit& pu, MergeCtx& smvpMergeCandCtx, int numRetrievedMergeCand);
 #endif
+#if JVET_AG0276_NLIC
+  void adjustMergeCandidates(PredictionUnit& pu, MergeCtx& mvpMergeCandCtx, AltLMMergeCtx& altLMMrgCtx, int numRetrievedMergeCand);
+#endif
 #if JVET_AB0079_TM_BCW_MRG
   void adjustMergeCandidatesBcwIdx(PredictionUnit& pu, MergeCtx& mrgCtx, const int mergeIdx = -1);
 #endif
@@ -1163,6 +1173,10 @@ public:
   void    updateCandInTwoCandidateGroups(MergeCtx& mrgCtx, uint32_t* rdCandList, int numCandInCategory, MergeCtx mrgCtx2);
 #endif
 #endif
+#if JVET_AG0276_NLIC
+  void    updateCandList(uint32_t uiCand, uint32_t uiCandGrp, Distortion uiCost, uint32_t uiMrgCandNum, uint32_t* rdCandList, uint32_t* rdCandGrpList, Distortion* candCostList);
+  void    updateCandInThreeCandidateGroups(MergeCtx& mrgCtx, MergeCtx mrgCtx2, MergeCtx mrgCtx3, uint32_t* rdCandList, uint32_t* rdCandGrpList, int numCandInCategory);
+#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);
@@ -1265,11 +1279,19 @@ public:
 #endif
 #if INTER_LIC || JVET_AC0112_IBC_LIC
 #if JVET_AE0078_IBC_LIC_EXTENSION
+#if JVET_AG0276_LIC_SLOPE_ADJUST
+  void xGetLICParamGeneral (const CodingUnit& cu, const ComponentID compID, int* numTemplate, Pel* refLeftTemplate, Pel* refAboveTemplate, Pel* recLeftTemplate, Pel* recAboveTemplate, int& shift, int& scale, int& offset, int* shift2 = nullptr, int* scale2 = nullptr, int* offset2 = nullptr, int* mean = nullptr, int *midVal = nullptr);
+#else
   void xGetLICParamGeneral (const CodingUnit& cu, const ComponentID compID, int* numTemplate, Pel* refLeftTemplate, Pel* refAboveTemplate, Pel* recLeftTemplate, Pel* recAboveTemplate, int& shift, int& scale, int& offset, int* shift2 = nullptr, int* scale2 = nullptr, int* offset2 = nullptr, int* mean = nullptr);
+#endif
+#else
+#if JVET_AG0276_LIC_SLOPE_ADJUST
+  void xGetLICParamGeneral (const CodingUnit& cu, const ComponentID compID, int* numTemplate, Pel* refLeftTemplate, Pel* refAboveTemplate, Pel* recLeftTemplate, Pel* recAboveTemplate, int& shift, int& scale, int& offset, int *midVal = nullptr);
 #else
   void xGetLICParamGeneral (const CodingUnit& cu, const ComponentID compID, int* numTemplate, Pel* refLeftTemplate, Pel* refAboveTemplate, Pel* recLeftTemplate, Pel* recAboveTemplate, int& shift, int& scale, int& offset);
 #endif
 #endif
+#endif
 #if JVET_AE0159_FIBC
   void xGetIbcFilterRefBuf(PelBuf& piPred, CodingUnit* pcCU, const ComponentID compID, const Mv& mv, unsigned int uiBlkWidth, unsigned int uiBlkHeight );
   void xCalIbcFilterParam(PelBuf& piPred, CodingUnit* pcCU, const ComponentID compID, const Mv& mv, unsigned int uiBlkWidth, unsigned int uiBlkHeight ); 
@@ -1301,6 +1323,9 @@ public:
   void setLicParam(int refList, int compID, int& licScale, int& licOffset) { licScale = m_scale[refList][compID]; licOffset = m_offset[refList][compID]; }
   void resetFillLicTpl() { m_fillLicTpl[COMPONENT_Y] = m_fillLicTpl[COMPONENT_Cb] = m_fillLicTpl[COMPONENT_Cr] = false; }
   void xLicCompAdj(const PredictionUnit& pu, PelUnitBuf& pcYuvPred, const bool lumaOnly, const bool chromaOnly);
+#if JVET_AG0276_LIC_BDOF_BDMVR
+  void xLicCompAdjBdof(const PredictionUnit& pu, PelUnitBuf& pcYuvPred, const bool lumaOnly, const bool chromaOnly);
+#endif
 #endif
   template <bool trueAfalseL>
   void xGetPredBlkTpl(const CodingUnit& cu, const ComponentID compID, const CPelBuf& refBuf, const Mv& mv, const int posW, const int posH, const int tplSize, Pel* predBlkTpl
@@ -1313,6 +1338,9 @@ public:
 #endif
                       );
 #endif
+#if JVET_AG0276_LIC_SLOPE_ADJUST
+  void xUpdateLicModel (int &scale, int &offset, int &shift, int midVal, int delta);
+#endif
 
 #if JVET_AC0112_IBC_LIC
   void xGetSublkTemplate (const CodingUnit& cu, const ComponentID compID, const Mv& bv, const int sublkWidth, const int sublkHeight, const int posW, const int posH, int* numTemplate, Pel* refLeftTemplate, Pel* refAboveTemplate, Pel* recLeftTemplate, Pel* recAboveTemplate);
@@ -1509,6 +1537,141 @@ public:
   void setFillCurTplLeftARMC(bool b) { m_fillCurTplLeftARMC = b; }
 #endif
 
+#if JVET_AG0276_NLIC
+public:
+  void xPredWoRefinement(PredictionUnit& pu, PelUnitBuf &pcYuvPred, const bool luma = true, const bool chroma = true);
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+  template <bool isBRcand>
+#endif
+  void xDevSecLicPara(CodingUnit&     cu, PelUnitBuf& predBuf, PelUnitBuf& dstBuf)
+  {
+    for (int comp = 0; comp < MAX_NUM_COMPONENT; comp++)
+    {
+      ComponentID compID = ComponentID(comp);
+      Pel* pred = predBuf.get(compID).buf;
+      int  predStride = predBuf.get(compID).stride;
+      Pel* rec = dstBuf.get(compID).buf;
+      int  recStride = dstBuf.get(compID).stride;
+
+      const int cuWidth = cu.blocks[compID].width;
+      const int cuHeight = cu.blocks[compID].height;
+
+      const int bitDepth = cu.cs->sps->getBitDepth(toChannelType(compID));
+      const int precShift = std::max(0, bitDepth - 12);
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+      const int maxNumMinus1 = isBRcand ? (30 - 2 * std::min(bitDepth, 12) - 1) : (30 - 2 * std::min(bitDepth, 12));
+#else
+      const int maxNumMinus1 = 30 - 2 * std::min(bitDepth, 12);
+#endif
+      const int minDimBit = floorLog2(std::min(cuHeight, cuWidth));
+      const int minDim = 1 << minDimBit;
+      int       minStepBit = minDim > 8 ? 1 : 0;
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+      while (isBRcand ? (minDimBit > minStepBit + maxNumMinus1) : (((minDimBit - minStepBit) << 1) > maxNumMinus1))
+#else
+      while (((minDimBit - minStepBit) << 1) > maxNumMinus1) 
+#endif
+      { minStepBit++; } //make sure 2*log2(minDim/tmpStep) + 2*min(bitDepth,12) <= 30
+      const int numSteps = minDim >> minStepBit;
+      const int dimShift = minDimBit - minStepBit;
+
+      //----- get correlation data -----
+      int x = 0, y = 0, xx = 0, xy = 0;
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+      int cntShift = 0;
+      if (isBRcand)
+      {
+        Pel* refBottom = pred + (cuHeight - 1) * predStride;
+        Pel* recBottom = rec + (cuHeight - 1) * recStride;
+        for (int k = 0; k < numSteps; k++)
+        {
+          int idx = (k * cuWidth) >> dimShift;
+          int refVal = refBottom[idx];
+          int recVal = recBottom[idx];
+          x += refVal;
+          y += recVal;
+          xx += refVal * refVal;
+          xy += refVal * recVal;
+        }
+        cntShift = dimShift;
+
+        Pel* refRight = pred + cuWidth - 1;
+        Pel* recRight = rec + cuWidth - 1;
+        for (int k = 0; k < numSteps; k++)
+        {
+          int idx = (k * cuHeight) >> dimShift;
+          int refVal = refRight[idx * predStride];
+          int recVal = recRight[idx * recStride];
+          x += refVal;
+          y += recVal;
+          xx += refVal * refVal;
+          xy += refVal * recVal;
+        }
+        cntShift += (cntShift ? 1 : dimShift);
+      }
+      else
+#endif
+      {
+        for (int h = 0; h < numSteps; h++)
+        {
+          int vDim = ((h * cuHeight) >> dimShift);
+
+          for (int w = 0; w < numSteps; w++)
+          {
+            int hDim = ((w * cuWidth) >> dimShift);
+
+            int predVal = pred[vDim * predStride + hDim] >> precShift;
+            int recVal = rec[vDim * recStride + hDim] >> precShift;
+
+            x += predVal;
+            y += recVal;
+            xx += predVal * predVal;
+            xy += predVal * recVal;
+          }
+        }
+      }
+
+      int  shift = m_LICShift;
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+      int& scale = isBRcand ? cu.altLMBRParaUnit.scale[compID] : cu.altLMParaUnit.scale[compID];
+      int& offset = isBRcand ? cu.altLMBRParaUnit.offset[compID] : cu.altLMParaUnit.offset[compID];
+      if (!isBRcand)
+      {
+        cntShift = (dimShift << 1); 
+        CHECK(!cntShift, "cntShift == 0");
+      }
+#else
+      int& scale = cu.altLMParaUnit.scale[compID];
+      int& offset = cu.altLMParaUnit.offset[compID];
+      cntShift = (dimShift << 1); CHECK(!cntShift, "cntShift == 0");
+#endif
+      const int cropShift = std::max(0, bitDepth - precShift + cntShift - 15);
+      const int xzOffset = (xx >> m_LICRegShift);
+      const int sumX = (x << precShift);
+      const int sumY = (y << precShift);
+      const int sumXX = ((xx + xzOffset) >> (cropShift << 1)) << cntShift;
+      const int sumXY = ((xy + xzOffset) >> (cropShift << 1)) << cntShift;
+      const int sumXsumX = (x >> cropShift) * (x >> cropShift);
+      const int sumXsumY = (x >> cropShift) * (y >> cropShift);
+      int       a1 = sumXY - sumXsumY;
+      int       a2 = sumXX - sumXsumX;
+      int       scaleShiftA2 = getMSB(abs(a2)) - 6;
+      int       scaleShiftA1 = scaleShiftA2 - m_LICShiftDiff;
+      scaleShiftA2 = std::max(0, scaleShiftA2);
+      scaleShiftA1 = std::max(0, scaleShiftA1);
+      const int scaleShiftA = scaleShiftA2 + 15 - shift - scaleShiftA1;
+      a1 = a1 >> scaleShiftA1;
+      a2 = Clip3(0, 63, a2 >> scaleShiftA2);
+      scale = int((int64_t(a1) * int64_t(m_LICMultApprox[a2])) >> scaleShiftA);
+      scale = Clip3(0, 1 << (shift + 2), scale);
+      const int maxOffset = (1 << (bitDepth - 1)) - 1;
+      const int minOffset = -1 - maxOffset;
+      offset = (sumY - ((scale * sumX) >> shift) + ((1 << (cntShift)) >> 1)) >> cntShift;
+      offset = Clip3(minOffset, maxOffset, offset);
+    }
+  }
+#endif
+
 #if JVET_AA0096_MC_BOUNDARY_PADDING
   void mcFramePad(Picture *pcCurPic, Slice &slice);
 #if JVET_Z0118_GDR
diff --git a/source/Lib/CommonLib/Rom.cpp b/source/Lib/CommonLib/Rom.cpp
index 7f6117709..5468f1c27 100644
--- a/source/Lib/CommonLib/Rom.cpp
+++ b/source/Lib/CommonLib/Rom.cpp
@@ -5597,4 +5597,7 @@ const int8_t g_amvpSbTmvp_mvd_offset[6] = { 4, 8, 12, 16, 24, 32 };
 uint32_t g_picAmvpSbTmvpEnabledArea = 0;
 #endif
 
+#if JVET_AG0276_LIC_SLOPE_ADJUST
+const int g_licSlopeDeltaSet[LIC_SLOPE_MAX_NUM_DELTA + 1] = {0, 1, -1};
+#endif
 //! \}
diff --git a/source/Lib/CommonLib/Rom.h b/source/Lib/CommonLib/Rom.h
index 2a73e75db..575cf0f82 100644
--- a/source/Lib/CommonLib/Rom.h
+++ b/source/Lib/CommonLib/Rom.h
@@ -450,5 +450,8 @@ extern uint32_t g_picAmvpSbTmvpEnabledArea;
 extern const Position g_eipFilter[NUM_EIP_SHAPE][EIP_FILTER_TAP];
 extern const EIPInfo  g_eipInfoLut[4][4][9];
 #endif
+#if JVET_AG0276_LIC_SLOPE_ADJUST
+extern const int g_licSlopeDeltaSet[LIC_SLOPE_MAX_NUM_DELTA + 1];
+#endif
 #endif  //__TCOMROM__
 
diff --git a/source/Lib/CommonLib/Slice.cpp b/source/Lib/CommonLib/Slice.cpp
index d5f231c6b..8f02b685a 100644
--- a/source/Lib/CommonLib/Slice.cpp
+++ b/source/Lib/CommonLib/Slice.cpp
@@ -3446,6 +3446,9 @@ PicHeader::PicHeader()
 , m_picColFromL0Flag                              ( true )
 , m_mvdL1ZeroFlag                                 ( 0 )
 , m_maxNumAffineMergeCand                         ( AFFINE_MRG_MAX_NUM_CANDS )
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+, m_maxNumAffineOppositeLicMergeCand              ( AFF_MRG_MAX_NUM_CANDS_OPPOSITELIC )
+#endif
 , m_disFracMMVD                                   ( 0 )
 , m_disBdofFlag                                   ( 0 )
 , m_disDmvrFlag                                   ( 0 )
@@ -3544,6 +3547,9 @@ void PicHeader::initPicHeader()
   m_picColFromL0Flag                              = true;
   m_mvdL1ZeroFlag                                 = 0;
   m_maxNumAffineMergeCand                         = AFFINE_MRG_MAX_NUM_CANDS;
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+  m_maxNumAffineOppositeLicMergeCand              = AFF_MRG_MAX_NUM_CANDS_OPPOSITELIC;
+#endif
   m_disFracMMVD                                   = 0;
   m_disBdofFlag                                   = 0;
   m_disDmvrFlag                                   = 0;
@@ -3851,6 +3857,9 @@ SPS::SPS()
 , m_AffineType                ( false )
 #if JVET_AF0163_TM_SUBBLOCK_REFINEMENT
 , m_useAffineTM               ( false )
+#if JVET_AG0276_NLIC
+, m_useAffAltLMTM             ( false )
+#endif
 #endif
 , m_PROF                      ( false )
 #if ENABLE_DIMD
@@ -3923,6 +3932,15 @@ SPS::SPS()
 , m_MIP                       ( false )
 #if JVET_W0090_ARMC_TM
 , m_AML                       ( false )
+#if JVET_AG0276_NLIC
+, m_altLM                     ( false )
+, m_affAltLM                  ( false )
+#endif
+#endif
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+, m_mergeOppositeLic          ( false )
+, m_mergeTMOppositeLic        ( false )
+, m_mergeAffOppositeLic       ( false )
 #endif
 #if JVET_AA0093_REFINED_MOTION_FOR_ARMC
 , m_armcRefinedMotion         ( false )
@@ -3936,10 +3954,16 @@ SPS::SPS()
 , m_rprSwitchingQPOffsetOrderList{ 0 }
 #endif
 , m_maxNumMergeCand(MRG_MAX_NUM_CANDS)
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+, m_maxNumOppositeLicMergeCand(REG_MRG_MAX_NUM_CANDS_OPPOSITELIC)
+#endif
 #if JVET_X0049_ADAPT_DMVR
 , m_maxNumBMMergeCand(BM_MRG_MAX_NUM_CANDS)
 #endif
 , m_maxNumAffineMergeCand(AFFINE_MRG_MAX_NUM_CANDS)
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+, m_maxNumAffineOppositeLicMergeCand(AFF_MRG_MAX_NUM_CANDS_OPPOSITELIC)
+#endif
 , m_maxNumIBCMergeCand(IBC_MRG_MAX_NUM_CANDS)
 , m_maxNumGeoCand(0)
 #if JVET_AG0164_AFFINE_GPM
diff --git a/source/Lib/CommonLib/Slice.h b/source/Lib/CommonLib/Slice.h
index fa47841c5..eb783dc3e 100644
--- a/source/Lib/CommonLib/Slice.h
+++ b/source/Lib/CommonLib/Slice.h
@@ -1777,6 +1777,9 @@ private:
   bool              m_AffineType;
 #if JVET_AF0163_TM_SUBBLOCK_REFINEMENT
   bool              m_useAffineTM;
+#if JVET_AG0276_NLIC
+  bool              m_useAffAltLMTM;
+#endif
 #endif
   bool              m_PROF;
   bool              m_bcw;                        //
@@ -1836,6 +1839,9 @@ private:
   bool              m_Geo;
 #if INTER_LIC
   bool              m_licEnabledFlag;
+#if JVET_AG0276_LIC_SLOPE_ADJUST
+  bool              m_licSlopeAdjustEnabledFlag;
+#endif
 #endif
 
 #if JVET_AE0059_INTER_CCCM
@@ -1867,6 +1873,15 @@ private:
 #if JVET_W0090_ARMC_TM || JVET_Y0058_IBC_LIST_MODIFY || JVET_Z0075_IBC_HMVP_ENLARGE
   bool              m_AML;
 #endif
+#if JVET_AG0276_NLIC
+  bool              m_altLM;
+  bool              m_affAltLM;
+#endif
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+  bool              m_mergeOppositeLic;
+  bool              m_mergeTMOppositeLic;
+  bool              m_mergeAffOppositeLic;
+#endif
 #if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION 
   bool              m_fastSubTmvp;
 #endif
@@ -1892,10 +1907,16 @@ private:
   bool              m_ppsValidFlag[64];
   Size              m_scalingWindowSizeInPPS[64];
   uint32_t          m_maxNumMergeCand;
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+  uint32_t          m_maxNumOppositeLicMergeCand;
+#endif
 #if JVET_X0049_ADAPT_DMVR
   uint32_t          m_maxNumBMMergeCand;
 #endif
   uint32_t          m_maxNumAffineMergeCand;
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+  uint32_t          m_maxNumAffineOppositeLicMergeCand;
+#endif
   uint32_t          m_maxNumIBCMergeCand;
   uint32_t          m_maxNumGeoCand;
 #if JVET_AG0164_AFFINE_GPM
@@ -2320,7 +2341,15 @@ void                    setCCALFEnabledFlag( bool b )
 #if TM_MRG
   uint32_t                getMaxNumTMMergeCand() const { return std::min((uint32_t)TM_MRG_MAX_NUM_CANDS, m_maxNumMergeCand); }
 #endif
-
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+  uint32_t                getMaxNumOppositeLicMergeCand() const { return m_maxNumOppositeLicMergeCand; }
+  void                    setMaxNumOppositeLicMergeCand(uint32_t u) { m_maxNumOppositeLicMergeCand = u; }
+#endif
+#if TM_MRG
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+  uint32_t                getMaxNumTMOppositeLicMergeCand() const { return std::min((uint32_t)TM_MRG_MAX_NUM_CANDS_OPPOSITELIC, m_maxNumOppositeLicMergeCand); }
+#endif
+#endif
 #if JVET_X0141_CIIP_TIMD_TM && TM_MRG
   uint32_t                getMaxNumCiipTMMergeCand() const { return std::min((uint32_t)CIIP_TM_MRG_MAX_NUM_CANDS, m_maxNumMergeCand); }
 #endif
@@ -2330,6 +2359,10 @@ void                    setCCALFEnabledFlag( bool b )
 #endif
   uint32_t                getMaxNumAffineMergeCand() const { return m_maxNumAffineMergeCand; }
   void                    setMaxNumAffineMergeCand(uint32_t u) { m_maxNumAffineMergeCand = u; }
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+  uint32_t                getMaxNumAffineOppositeLicMergeCand() const { return m_maxNumAffineOppositeLicMergeCand; }
+  void                    setMaxNumAffineOppositeLicMergeCand(uint32_t u) { m_maxNumAffineOppositeLicMergeCand = u; }
+#endif
   uint32_t                getMaxNumIBCMergeCand() const { return m_maxNumIBCMergeCand; }
   void                    setMaxNumIBCMergeCand(uint32_t u) { m_maxNumIBCMergeCand = u; }
   uint32_t                getMaxNumGeoCand() const                                                        { CHECK( m_maxNumGeoCand >= GEO_MAX_NUM_UNI_CANDS, "Number of GEO candidates exceed GEO_MAX_NUM_CANDS" ); return m_maxNumGeoCand; }
@@ -2519,6 +2552,10 @@ void                    setCCALFEnabledFlag( bool b )
 #if INTER_LIC
   void      setLicEnabledFlag     ( bool b )                                        { m_licEnabledFlag = b; }
   bool      getLicEnabledFlag     ()                                     const      { return m_licEnabledFlag; }
+#if JVET_AG0276_LIC_SLOPE_ADJUST
+  void      setLicSlopeAdjustEnabledFlag     ( bool b )                             { m_licSlopeAdjustEnabledFlag = b; }
+  bool      getLicSlopeAdjustEnabledFlag     ()                          const      { return m_licSlopeAdjustEnabledFlag; }
+#endif
 #endif
 #if JVET_AE0059_INTER_CCCM
   void      setUseInterCccm       ( bool b )                                         { m_interCccm = b; }
@@ -2536,9 +2573,23 @@ void                    setCCALFEnabledFlag( bool b )
   void      setUseCiipAffine      ( bool b )                                        { m_ciipAffine = b; }
   bool      getUseCiipAffine      ()                                      const     { return m_ciipAffine; }
 #endif
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+  void      setUseMergeOppositeLic( bool b )                                        { m_mergeOppositeLic = b; }
+  bool      getUseMergeOppositeLic()                                      const     { return m_mergeOppositeLic; }
+  void      setUseTMMergeOppositeLic( bool b )                                      { m_mergeTMOppositeLic = b; }
+  bool      getUseTMMergeOppositeLic()                                    const     { return m_mergeTMOppositeLic; }
+  void      setUseAffMergeOppositeLic( bool b )                                     { m_mergeAffOppositeLic = b; }
+  bool      getUseAffMergeOppositeLic()                                   const     { return m_mergeAffOppositeLic; }
+#endif
 #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; }
+#if JVET_AG0276_NLIC
+  void      setUseAltLM           ( bool b )                                        { m_altLM = b; }
+  bool      getUseAltLM           ()                                      const     { return m_altLM; }
+  void      setUseAffAltLM        ( bool b )                                        { m_affAltLM = b; }
+  bool      getUseAffAltLM        ()                                      const     { return m_affAltLM; }
+#endif
 #endif
 #if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION 
   void      setUseFastSubTmvp     ( bool b )                                        { m_fastSubTmvp = b; }
@@ -2547,6 +2598,10 @@ void                    setCCALFEnabledFlag( bool b )
 #if JVET_AF0163_TM_SUBBLOCK_REFINEMENT
   void      setUseAffineTM        ( bool b )                                        { m_useAffineTM = b; }
   bool      getUseAffineTM        ()                                     const      { return  m_useAffineTM; }
+#if JVET_AG0276_NLIC
+  void      setUseAffAltLMTM      ( bool b )                                        { m_useAffAltLMTM = b; }
+  bool      getUseAffAltLMTM      ()                                      const     { return m_useAffAltLMTM; }
+#endif
 #endif
 #if JVET_AA0093_REFINED_MOTION_FOR_ARMC
   void      setUseArmcRefinedMotion ( bool b )                                      { m_armcRefinedMotion = b; }
@@ -3149,6 +3204,9 @@ private:
 #endif
   bool                        m_mvdL1ZeroFlag;                                          //!< L1 MVD set to zero flag
   uint32_t                    m_maxNumAffineMergeCand;                                  //!< max number of sub-block merge candidates
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+  uint32_t                    m_maxNumAffineOppositeLicMergeCand;                       //!< max number of sub-block merge candidates with opposite LIC flag
+#endif
   bool                        m_disFracMMVD;                                            //!< fractional MMVD offsets disabled flag
   bool                        m_disBdofFlag;                                            //!< picture level BDOF disable flag
   bool                        m_disDmvrFlag;                                            //!< picture level DMVR disable flag
@@ -3305,6 +3363,10 @@ public:
   bool                        getMvdL1ZeroFlag() const                                  { return m_mvdL1ZeroFlag;                                                                      }
   void                        setMaxNumAffineMergeCand( uint32_t val )                  { m_maxNumAffineMergeCand = val;                                                               }
   uint32_t                    getMaxNumAffineMergeCand() const                          { return m_maxNumAffineMergeCand;                                                              }
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+  void                        setMaxNumAffineOppositeLicMergeCand( uint32_t val )       { m_maxNumAffineOppositeLicMergeCand = val; }
+  uint32_t                    getMaxNumAffineOppositeLicMergeCand() const               { return m_maxNumAffineOppositeLicMergeCand; }
+#endif
   void                        setDisFracMMVD( bool val )                                { m_disFracMMVD = val;                                                                         }
   bool                        getDisFracMMVD() const                                    { return m_disFracMMVD;                                                                        }
   void                        setDisBdofFlag( bool val )                                { m_disBdofFlag = val;                                                                         }
diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h
index 9bf23afb6..4430937f5 100644
--- a/source/Lib/CommonLib/TypeDef.h
+++ b/source/Lib/CommonLib/TypeDef.h
@@ -255,6 +255,10 @@
 #if INTER_LIC
 #define JVET_AD0213_LIC_IMP                               1 // JVET-AD0213: bi-predictive LIC and the combination of LIC and OBMC
 #define JVET_AF0128_LIC_MERGE_TM                          1 // JVET-AF0128: LIC flag derivation for merge candidates with template costs
+#define JVET_AG0276_NLIC                                  1 // JVET-AG0276: non-local LIC
+#define JVET_AG0276_LIC_FLAG_SIGNALING                    1 // JVET-AG0276: signal LIC flag for merge mode
+#define JVET_AG0276_LIC_BDOF_BDMVR                        1 // JVET-AG0276: LIC BDOF and BDMVR
+#define JVET_AG0276_LIC_SLOPE_ADJUST                      1 // JVET-AG0276: LIC with slope adjustment
 #endif
 #define NON_ADJACENT_MRG_CAND                             1 // Add non-adjacent merge candidates
 #define MULTI_HYP_PRED                                    1 // Multiple hypothesis prediction
diff --git a/source/Lib/CommonLib/Unit.cpp b/source/Lib/CommonLib/Unit.cpp
index 41fea8671..0c38590f1 100644
--- a/source/Lib/CommonLib/Unit.cpp
+++ b/source/Lib/CommonLib/Unit.cpp
@@ -413,6 +413,16 @@ CodingUnit& CodingUnit::operator=( const CodingUnit& other )
   dimdDerivedIntraDir = other.dimdDerivedIntraDir;
 #endif
 #endif
+#if JVET_AG0276_NLIC
+  altLMFlag         = other.altLMFlag;
+  altLMParaUnit     = other.altLMParaUnit;
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+  altLMBRParaUnit   = other.altLMBRParaUnit;
+#endif
+#if ENABLE_OBMC
+  secAltLMParaUnit  = other.secAltLMParaUnit;
+#endif
+#endif
 #if INTER_LIC
   licFlag           = other.licFlag;
 #if JVET_AD0213_LIC_IMP
@@ -425,6 +435,9 @@ CodingUnit& CodingUnit::operator=( const CodingUnit& other )
     }
   }
 #endif
+#if JVET_AG0276_LIC_SLOPE_ADJUST
+  licDelta         = other.licDelta;
+#endif
 #endif
 #if JVET_AC0112_IBC_LIC
   ibcLicFlag = other.ibcLicFlag;
@@ -643,6 +656,16 @@ void CodingUnit::initData()
   dimdDerivedIntraDir = 0;
 #endif
 #endif
+#if JVET_AG0276_NLIC
+  altLMFlag = false;
+  altLMParaUnit.resetAltLinearModel();
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+  altLMBRParaUnit.resetAltLinearModel();
+#endif
+#if ENABLE_OBMC
+  secAltLMParaUnit.resetAltLinearModel();
+#endif
+#endif
 #if INTER_LIC
   licFlag = false;
 #if JVET_AD0213_LIC_IMP
@@ -655,6 +678,9 @@ void CodingUnit::initData()
     }
   }
 #endif
+#if JVET_AG0276_LIC_SLOPE_ADJUST
+  licDelta = 0;
+#endif
 #endif
 #if JVET_AC0112_IBC_LIC
   ibcLicFlag = false;
@@ -967,6 +993,11 @@ void PredictionUnit::initData()
   colIdx = 0;
 #endif
   mergeFlag   = false;
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+  mergeOppositeLic = false;
+  affineOppositeLic = false;
+  tmMergeFlagOppositeLic = false;
+#endif
   regularMergeFlag = false;
   mergeIdx    = MAX_UCHAR;
   geoSplitDir  = MAX_UCHAR;
@@ -1185,6 +1216,11 @@ PredictionUnit& PredictionUnit::operator=(const InterPredictionData& predData)
   colIdx = predData.colIdx;
 #endif
   mergeFlag   = predData.mergeFlag;
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+  mergeOppositeLic = predData.mergeOppositeLic;
+  affineOppositeLic = predData.affineOppositeLic;
+  tmMergeFlagOppositeLic = predData.tmMergeFlagOppositeLic;
+#endif
   regularMergeFlag = predData.regularMergeFlag;
   mergeIdx    = predData.mergeIdx;
   geoSplitDir  = predData.geoSplitDir;
@@ -1400,6 +1436,11 @@ PredictionUnit& PredictionUnit::operator=( const PredictionUnit& other )
   ccpMergeFusionType = other.ccpMergeFusionType;
 #endif
   mergeFlag   = other.mergeFlag;
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+  mergeOppositeLic = other.mergeOppositeLic;
+  affineOppositeLic = other.affineOppositeLic;
+  tmMergeFlagOppositeLic = other.tmMergeFlagOppositeLic;
+#endif
   regularMergeFlag = other.regularMergeFlag;
 #if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION
   colIdx = other.colIdx;
diff --git a/source/Lib/CommonLib/Unit.h b/source/Lib/CommonLib/Unit.h
index df7240fc1..806a4e4c0 100644
--- a/source/Lib/CommonLib/Unit.h
+++ b/source/Lib/CommonLib/Unit.h
@@ -431,12 +431,25 @@ struct CodingUnit : public UnitArea
   int            intraTmpDimdMode;
 #endif
 #endif
+#if JVET_AG0276_NLIC
+  bool           altLMFlag;
+  AltLMInterUnit altLMParaUnit;
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+  AltLMInterUnit altLMBRParaUnit;
+#endif
+#if ENABLE_OBMC
+  AltLMInterUnit secAltLMParaUnit;
+#endif
+#endif
 #if INTER_LIC
   bool           licFlag;
 #if JVET_AD0213_LIC_IMP
   int            licScale[2][3];
   int            licOffset[2][3];
 #endif
+#if JVET_AG0276_LIC_SLOPE_ADJUST
+  int            licDelta;
+#endif
 #endif
 #if JVET_AC0112_IBC_LIC
   bool           ibcLicFlag;
@@ -658,6 +671,11 @@ struct InterPredictionData
 #if TM_MRG || (JVET_Z0084_IBC_TM && IBC_TM_MRG)
   bool        tmMergeFlag;
 #endif
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+  bool        tmMergeFlagOppositeLic;
+  bool        mergeOppositeLic;
+  bool        affineOppositeLic;
+#endif
 #if JVET_X0049_ADAPT_DMVR
   uint8_t     bmMergeFlag;
   uint8_t     bmDir;
diff --git a/source/Lib/CommonLib/UnitTools.cpp b/source/Lib/CommonLib/UnitTools.cpp
index 86e9a16d3..188c81d8b 100644
--- a/source/Lib/CommonLib/UnitTools.cpp
+++ b/source/Lib/CommonLib/UnitTools.cpp
@@ -357,6 +357,163 @@ void CU::checkConformanceILRP(Slice *slice)
   return;
 }
 
+#if JVET_AG0276_NLIC
+bool CU::isSecLicParaNeeded(const CodingUnit &cu)
+{
+  if (!isInter(cu))
+  {
+    return false;
+  }
+  if (cu.geoFlag)
+  {
+    return false;
+  }
+  if (cu.firstPU->mergeFlag && cu.firstPU->mergeType == MRG_TYPE_SUBPU_ATMVP)
+  {
+    return false;
+  }
+#if JVET_AG0098_AMVP_WITH_SBTMVP
+  if (cu.firstPU->amvpSbTmvpFlag)
+  {
+    return false;
+  }
+#endif
+  return true;
+}
+
+bool CU::isPredRefined(const CodingUnit &cu)
+{
+  PredictionUnit* pu = cu.firstPU;
+
+#if INTER_LIC
+  if (cu.licFlag)
+  {
+    return true;
+  }
+#endif
+  if (cu.altLMFlag)
+  {
+    return true;
+  }
+#if MULTI_PASS_DMVR
+  if (pu->bdmvrRefine)
+  {
+    return true;
+  }
+#endif
+  if (pu->ciipFlag)
+  {
+    return true;
+  }
+#if MULTI_HYP_PRED
+  if (!pu->addHypData.empty())
+  {
+    return true;
+  }
+#endif
+
+  bool bioApplied = false;
+#if JVET_AF0159_AFFINE_SUBPU_BDOF_REFINEMENT
+  if (pu->cu->affine)
+  {
+    bioApplied = PU::checkDoAffineBdofRefine(*pu, NULL);
+  }
+  else
+  {
+#endif
+    if (pu->cs->sps->getBDOFEnabledFlag() && !pu->cs->picHeader->getDisBdofFlag())
+    {
+#if INTER_LIC
+      if (cu.affine || (pu->mergeFlag && (pu->mergeType == MRG_TYPE_SUBPU_ATMVP)) || cu.licFlag)
+#else
+      if (cu.affine || (pu->mergeFlag && (pu->mergeType == MRG_TYPE_SUBPU_ATMVP)))
+#endif
+      {
+        bioApplied = false;
+      }
+      else
+      {
+        int                  refIdx0 = pu->refIdx[REF_PIC_LIST_0];
+        int                  refIdx1 = pu->refIdx[REF_PIC_LIST_1];
+        const WPScalingParam *wp0 = cu.cs->slice->getWpScaling(REF_PIC_LIST_0, refIdx0);
+        const WPScalingParam *wp1 = cu.cs->slice->getWpScaling(REF_PIC_LIST_1, refIdx1);
+
+        const bool biocheck0 = !((WPScalingParam::isWeighted(wp0) || WPScalingParam::isWeighted(wp1)) && cu.cs->slice->getSliceType() == B_SLICE);
+        const bool biocheck1 = !(cu.cs->pps->getUseWP() && cu.cs->slice->getSliceType() == P_SLICE);
+        if (biocheck0 && biocheck1
+          && PU::isBiPredFromDifferentDirEqDistPoc(*pu)
+#if !BDOF_RM_CONSTRAINTS
+          && (cu.Y().height >= 8)
+          && (cu.Y().width >= 8)
+          && ((cu.Y().height * cu.Y().width) >= 128)
+#endif
+          )
+        {
+          bioApplied = true;
+        }
+        if (bioApplied && pu->ciipFlag)
+        {
+          bioApplied = false;
+        }
+        if (bioApplied && cu.smvdMode)
+        {
+          bioApplied = false;
+        }
+        if (cu.cs->sps->getUseBcw() && bioApplied && cu.bcwIdx != BCW_DEFAULT)
+        {
+          bioApplied = false;
+        }
+      }
+    }
+#if JVET_AF0159_AFFINE_SUBPU_BDOF_REFINEMENT
+  }
+#endif
+  if (bioApplied)
+  {
+    return true;
+  }
+
+  return false;
+}
+bool CU::isAllowSecLicPara(const CodingUnit &cu)
+{
+  if (!cu.slice->getSPS()->getUseAltLM())
+  {
+    if (!cu.slice->getSPS()->getUseAffAltLM())
+    {
+      return false;
+    }
+    else
+    {
+      if (!cu.affine)
+      {
+        return false;
+      }
+    }
+  }
+  if (isTLCond(cu))
+  {
+    return false;
+  }
+  return true;
+}
+bool CU::isTLCond(const CodingUnit &cu)
+{
+  if (!cu.slice->getSPS()->getUseAltLM() && !cu.slice->getSPS()->getUseAffAltLM())
+  {
+    return false;
+  }
+  if (cu.slice->getTLayer() >= 5)
+  {
+    return true;
+  }
+  else
+  {
+    return false;
+  }
+}
+#endif
+
 bool CU::isIntra(const CodingUnit &cu)
 {
   return cu.predMode == MODE_INTRA;
@@ -3084,6 +3241,32 @@ bool PU::checkIsChromaBvCandidateValid(const PredictionUnit &pu, const Mv chroma
   return true;
 }
 #endif
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+bool PU::isOppositeLIC(const PredictionUnit &pu)
+{
+  return pu.mergeOppositeLic
+    || pu.tmMergeFlagOppositeLic
+    || pu.affineOppositeLic
+    ;
+}
+
+bool PU::hasOppositeLICFlag(const PredictionUnit &pu)
+{
+  if (pu.cu->slice->getUseLIC() && pu.cs->slice->getTLayer() < 5)
+  {
+    int blkArea = pu.lumaSize().area();
+    if (pu.cu->affine)
+    {
+      return blkArea > 64 && blkArea < 8192;
+    }
+    else
+    {
+      return blkArea >= 32 && blkArea < 16384;
+    }
+  }
+  return false;
+}
+#endif
 #if JVET_AD0120_LBCCP
 bool PU::isModetobeFiltered(int intraMode)
 {
@@ -5703,6 +5886,10 @@ void PU::getIBCMergeCandidates(const PredictionUnit &pu, MergeCtx& mrgCtx, const
     mrgCtx.mvFieldNeighbours[ui * 2].refIdx = NOT_VALID;
     mrgCtx.mvFieldNeighbours[ui * 2 + 1].refIdx = NOT_VALID;
     mrgCtx.useAltHpelIf[ui] = false;
+#if JVET_AG0276_NLIC
+    mrgCtx.altLMFlag[ui] = false;
+    mrgCtx.altLMParaNeighbours[ui].resetAltLinearModel();
+#endif
 #if INTER_LIC
     mrgCtx.licFlags[ui] = false;
 #endif
@@ -8149,6 +8336,10 @@ void PU::getInterMergeCandidatesSubTMVP(const PredictionUnit &pu, MergeCtx& mrgC
   for (uint32_t ui = 0; ui < maxNumMergeCand; ++ui)
   {
     mrgCtx.bcwIdx[ui] = BCW_DEFAULT;
+#if JVET_AG0276_NLIC
+    mrgCtx.altLMFlag[ui] = false;
+    mrgCtx.altLMParaNeighbours[ui].resetAltLinearModel();
+#endif
 #if INTER_LIC
     mrgCtx.licFlags[ui] = false;
 #endif
@@ -8589,6 +8780,10 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx,
   for (uint32_t ui = 0; ui < maxNumMergeCand; ++ui)
   {
     mrgCtx.bcwIdx[ui] = BCW_DEFAULT;
+#if JVET_AG0276_NLIC
+    mrgCtx.altLMFlag[ui] = false;
+    mrgCtx.altLMParaNeighbours[ui].resetAltLinearModel();
+#endif
 #if INTER_LIC
     mrgCtx.licFlags[ui] = false;
 #endif
@@ -8705,7 +8900,11 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx,
     // get Mv from Above
     mrgCtx.bcwIdx[cnt] = (mrgCtx.interDirNeighbours[cnt] == 3) ? puAbove->cu->bcwIdx : BCW_DEFAULT;
 #if INTER_LIC
+#if JVET_AG0276_NLIC
+    mrgCtx.licFlags[cnt] = miAbove.usesLIC || (puAbove->cu->altLMFlag && slice.getUseLIC());
+#else
     mrgCtx.licFlags[cnt] = miAbove.usesLIC;
+#endif
 #endif
     mrgCtx.mvFieldNeighbours[cnt << 1].setMvField(miAbove.mv[0], miAbove.refIdx[0]);
 
@@ -8792,7 +8991,11 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx,
       mrgCtx.useAltHpelIf[cnt] = miLeft.useAltHpelIf;
       mrgCtx.bcwIdx[cnt] = (mrgCtx.interDirNeighbours[cnt] == 3) ? puLeft->cu->bcwIdx : BCW_DEFAULT;
 #if INTER_LIC
+#if JVET_AG0276_NLIC
+      mrgCtx.licFlags[cnt] = miLeft.usesLIC || (puLeft->cu->altLMFlag && slice.getUseLIC());
+#else
       mrgCtx.licFlags[cnt] = miLeft.usesLIC;
+#endif
 #endif
       // get Mv from Left
       mrgCtx.mvFieldNeighbours[cnt << 1].setMvField(miLeft.mv[0], miLeft.refIdx[0]);
@@ -8880,7 +9083,11 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx,
       // get Mv from Above-right
       mrgCtx.bcwIdx[cnt] = (mrgCtx.interDirNeighbours[cnt] == 3) ? puAboveRight->cu->bcwIdx : BCW_DEFAULT;
 #if INTER_LIC
+#if JVET_AG0276_NLIC
+      mrgCtx.licFlags[cnt] = miAboveRight.usesLIC || (puAboveRight->cu->altLMFlag && slice.getUseLIC());
+#else
       mrgCtx.licFlags[cnt] = miAboveRight.usesLIC;
+#endif
 #endif
       mrgCtx.mvFieldNeighbours[cnt << 1].setMvField( miAboveRight.mv[0], miAboveRight.refIdx[0] );
 
@@ -8965,7 +9172,11 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx,
       mrgCtx.useAltHpelIf[cnt] = miBelowLeft.useAltHpelIf;
       mrgCtx.bcwIdx[cnt] = (mrgCtx.interDirNeighbours[cnt] == 3) ? puLeftBottom->cu->bcwIdx : BCW_DEFAULT;
 #if INTER_LIC
+#if JVET_AG0276_NLIC
+      mrgCtx.licFlags[cnt] = miBelowLeft.usesLIC || (puLeftBottom->cu->altLMFlag && slice.getUseLIC());
+#else
       mrgCtx.licFlags[cnt] = miBelowLeft.usesLIC;
+#endif
 #endif
       // get Mv from Bottom-Left
       mrgCtx.mvFieldNeighbours[cnt << 1].setMvField( miBelowLeft.mv[0], miBelowLeft.refIdx[0] );
@@ -9066,7 +9277,11 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx,
         mrgCtx.useAltHpelIf[cnt] = miAboveLeft.useAltHpelIf;
         mrgCtx.bcwIdx[cnt] = (mrgCtx.interDirNeighbours[cnt] == 3) ? puAboveLeft->cu->bcwIdx : BCW_DEFAULT;
 #if INTER_LIC
+#if JVET_AG0276_NLIC
+        mrgCtx.licFlags[cnt] = miAboveLeft.usesLIC || (puAboveLeft->cu->altLMFlag && slice.getUseLIC());
+#else
         mrgCtx.licFlags[cnt] = miAboveLeft.usesLIC;
+#endif
 #endif
         // get Mv from Above-Left
         mrgCtx.mvFieldNeighbours[cnt << 1].setMvField( miAboveLeft.mv[0], miAboveLeft.refIdx[0] );
@@ -9499,7 +9714,11 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx,
         // get Mv from Above-right
         mrgCtx.bcwIdx[cnt] = (mrgCtx.interDirNeighbours[cnt] == 3) ? puNonAdjacent->cu->bcwIdx : BCW_DEFAULT;
 #if INTER_LIC
+#if JVET_AG0276_NLIC
+        mrgCtx.licFlags[cnt] = miNeighbor.usesLIC || (puNonAdjacent->cu->altLMFlag && slice.getUseLIC());
+#else
         mrgCtx.licFlags[cnt] = miNeighbor.usesLIC;
+#endif
 #endif
         if (slice.isInterB())
         {
@@ -10457,6 +10676,12 @@ void PU::xCalcRMVFParameters(std::vector<RMVFInfo> &mvpInfoVec, int64_t dMatrix[
 void PU::getRMVFAffineGuideCand(const PredictionUnit &pu, const PredictionUnit &abovePU, AffineMergeCtx &affMrgCtx
   , std::vector<RMVFInfo> mvp[NUM_REF_PIC_LIST_01][MAX_NUM_REF]
   , int mrgCandIdx
+#if JVET_AG0276_NLIC
+  , AltLMAffineMergeCtx* altAffineMergeCtx
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+  , AltLMAffineMergeCtx* altBRAffineMergeCtx
+#endif
+#endif
 )
 {
   const CodingStructure &cs = *pu.cs;
@@ -10855,6 +11080,50 @@ void PU::getRMVFAffineGuideCand(const PredictionUnit &pu, const PredictionUnit &
 #if JVET_AB0189_RMVF_BITLENGTH_CONTROL
   if (enoughBlk[0] || enoughBlk[1])
   {
+#endif
+#if JVET_AG0276_NLIC
+    if (PU::isValidAltMergeCandidate(abovePU) && (altAffineMergeCtx->numValidMergeCand < ALT_AFF_MRG_MAX_NUM_CANDS))
+    {
+      int cnt = altAffineMergeCtx->numValidMergeCand;
+      altAffineMergeCtx->affineType[cnt] = AFFINEMODEL_6PARAM;
+      for (int mvNum = 0; mvNum < 3; mvNum++)
+      {
+        altAffineMergeCtx->mvFieldNeighbours[(cnt << 1) + 0][mvNum].setMvField(cMVOri[0][mvNum], referenceidx[0]);
+        altAffineMergeCtx->mvFieldNeighbours[(cnt << 1) + 1][mvNum].setMvField(cMVOri[1][mvNum], referenceidx[1]);
+      }
+      altAffineMergeCtx->interDirNeighbours[cnt] = abovePU.interDir;
+      altAffineMergeCtx->bcwIdx[cnt] = abovePU.cu->bcwIdx;
+#if JVET_AD0193_ADAPTIVE_OBMC_CONTROL
+      altAffineMergeCtx->obmcFlags[cnt] = abovePU.cu->affine ? abovePU.cu->obmcFlag : true;
+#endif
+      altAffineMergeCtx->altLMParaNeighbours[cnt] = abovePU.cu->altLMParaUnit;
+      if (altAffineMergeCtx->xCheckSameAffMotion(pu, cnt))
+      {
+        altAffineMergeCtx->numValidMergeCand++;
+      }
+    }
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+    if (PU::isValidAltMergeCandidate(abovePU, true) && (altBRAffineMergeCtx->numValidMergeCand < ALT_AFF_MRG_MAX_NUM_CANDS))
+    {
+      int cnt = altBRAffineMergeCtx->numValidMergeCand;
+      altBRAffineMergeCtx->affineType[cnt] = AFFINEMODEL_6PARAM;
+      for (int mvNum = 0; mvNum < 3; mvNum++)
+      {
+        altBRAffineMergeCtx->mvFieldNeighbours[(cnt << 1) + 0][mvNum].setMvField(cMVOri[0][mvNum], referenceidx[0]);
+        altBRAffineMergeCtx->mvFieldNeighbours[(cnt << 1) + 1][mvNum].setMvField(cMVOri[1][mvNum], referenceidx[1]);
+      }
+      altBRAffineMergeCtx->interDirNeighbours[cnt] = abovePU.interDir;
+      altBRAffineMergeCtx->bcwIdx[cnt] = abovePU.cu->bcwIdx;
+#if JVET_AD0193_ADAPTIVE_OBMC_CONTROL
+      altBRAffineMergeCtx->obmcFlags[cnt] = abovePU.cu->affine ? abovePU.cu->obmcFlag : true;
+#endif
+      altBRAffineMergeCtx->altLMParaNeighbours[cnt] = abovePU.cu->altLMBRParaUnit;
+      if (altBRAffineMergeCtx->xCheckSameAffMotion(pu, cnt))
+      {
+        altBRAffineMergeCtx->numValidMergeCand++;
+      }
+    }
+#endif
 #endif
     if (!xCPMVSimCheck(pu, affMrgCtx, cMVOri, abovePU.interDir, referenceidx, AFFINEMODEL_6PARAM, abovePU.cu->bcwIdx, abovePU.cu->licFlag))
     {
@@ -10894,6 +11163,50 @@ void PU::getRMVFAffineGuideCand(const PredictionUnit &pu, const PredictionUnit &
 #endif
   if (available[REF_PIC_LIST_0] || available[REF_PIC_LIST_1])
   {
+#if JVET_AG0276_NLIC
+    if (PU::isValidAltMergeCandidate(abovePU) && (altAffineMergeCtx->numValidMergeCand < ALT_AFF_MRG_MAX_NUM_CANDS))
+    {
+      int cnt = altAffineMergeCtx->numValidMergeCand;
+      altAffineMergeCtx->affineType[cnt] = AFFINEMODEL_6PARAM;
+      for (int mvNum = 0; mvNum < 3; mvNum++)
+      {
+        altAffineMergeCtx->mvFieldNeighbours[(cnt << 1) + 0][mvNum].setMvField(cMV[0][mvNum], referenceidx[0]);
+        altAffineMergeCtx->mvFieldNeighbours[(cnt << 1) + 1][mvNum].setMvField(cMV[1][mvNum], referenceidx[1]);
+      }
+      altAffineMergeCtx->interDirNeighbours[cnt] = abovePU.interDir;
+      altAffineMergeCtx->bcwIdx[cnt] = abovePU.cu->bcwIdx;
+#if JVET_AD0193_ADAPTIVE_OBMC_CONTROL
+      altAffineMergeCtx->obmcFlags[cnt] = abovePU.cu->affine ? abovePU.cu->obmcFlag : true;
+#endif
+      altAffineMergeCtx->altLMParaNeighbours[cnt] = abovePU.cu->altLMParaUnit;
+      if (altAffineMergeCtx->xCheckSameAffMotion(pu, cnt))
+      {
+        altAffineMergeCtx->numValidMergeCand++;
+      }
+    }
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+    if (PU::isValidAltMergeCandidate(abovePU, true) && (altBRAffineMergeCtx->numValidMergeCand < ALT_AFF_MRG_MAX_NUM_CANDS))
+    {
+      int cnt = altBRAffineMergeCtx->numValidMergeCand;
+      altBRAffineMergeCtx->affineType[cnt] = AFFINEMODEL_6PARAM;
+      for (int mvNum = 0; mvNum < 3; mvNum++)
+      {
+        altBRAffineMergeCtx->mvFieldNeighbours[(cnt << 1) + 0][mvNum].setMvField(cMV[0][mvNum], referenceidx[0]);
+        altBRAffineMergeCtx->mvFieldNeighbours[(cnt << 1) + 1][mvNum].setMvField(cMV[1][mvNum], referenceidx[1]);
+      }
+      altBRAffineMergeCtx->interDirNeighbours[cnt] = abovePU.interDir;
+      altBRAffineMergeCtx->bcwIdx[cnt] = abovePU.cu->bcwIdx;
+#if JVET_AD0193_ADAPTIVE_OBMC_CONTROL
+      altBRAffineMergeCtx->obmcFlags[cnt] = abovePU.cu->affine ? abovePU.cu->obmcFlag : true;
+#endif
+      altBRAffineMergeCtx->altLMParaNeighbours[cnt] = abovePU.cu->altLMBRParaUnit;
+      if (altBRAffineMergeCtx->xCheckSameAffMotion(pu, cnt))
+      {
+        altBRAffineMergeCtx->numValidMergeCand++;
+      }
+    }
+#endif
+#endif
     if (!xCPMVSimCheck(pu, affMrgCtx, cMV, abovePU.interDir, referenceidx, AFFINEMODEL_6PARAM, BCW_DEFAULT, false))
     {
       int i = affMrgCtx.numValidMergeCand;
@@ -11160,6 +11473,10 @@ void PU::getInterBMCandidates(const PredictionUnit &pu, MergeCtx& mrgCtx,
   for (uint32_t ui = 0; ui < maxNumMergeCand; ++ui)
   {
     mrgCtx.bcwIdx[ui] = BCW_DEFAULT;
+#if JVET_AG0276_NLIC
+    mrgCtx.altLMFlag[ui] = false;
+    mrgCtx.altLMParaNeighbours[ui].resetAltLinearModel();
+#endif
 #if INTER_LIC
     mrgCtx.licFlags[ui] = false;
 #endif
@@ -11914,6 +12231,10 @@ void PU::getTmvpBMCand(const PredictionUnit &pu, MergeCtx& mrgCtx)
   for (uint32_t ui = 0; ui < maxNumMergeCand; ++ui)
   {
     mrgCtx.bcwIdx[ui] = BCW_DEFAULT;
+#if JVET_AG0276_NLIC
+    mrgCtx.altLMFlag[ui] = false;
+    mrgCtx.altLMParaNeighbours[ui].resetAltLinearModel();
+#endif
 #if INTER_LIC
     mrgCtx.licFlags[ui] = false;
 #endif
@@ -12133,6 +12454,10 @@ void PU::getNonAdjacentBMCand(const PredictionUnit &pu, MergeCtx& mrgCtx)
   for (uint32_t ui = 0; ui < maxNumMergeCand; ++ui)
   {
     mrgCtx.bcwIdx[ui] = BCW_DEFAULT;
+#if JVET_AG0276_NLIC
+    mrgCtx.altLMFlag[ui] = false;
+    mrgCtx.altLMParaNeighbours[ui].resetAltLinearModel();
+#endif
 #if INTER_LIC
     mrgCtx.licFlags[ui] = false;
 #endif
@@ -12304,6 +12629,10 @@ void PU::getTmvpMergeCand(const PredictionUnit &pu, MergeCtx& mrgCtx)
   for (uint32_t ui = 0; ui < maxNumMergeCand; ++ui)
   {
     mrgCtx.bcwIdx[ui] = BCW_DEFAULT;
+#if JVET_AG0276_NLIC
+    mrgCtx.altLMFlag[ui] = false;
+    mrgCtx.altLMParaNeighbours[ui].resetAltLinearModel();
+#endif
 #if INTER_LIC
     mrgCtx.licFlags[ui] = false;
 #endif
@@ -12837,6 +13166,10 @@ void PU::getNonAdjacentMergeCandSubTMVP(const PredictionUnit &pu, MergeCtx& mrgC
   for (uint32_t ui = 0; ui < maxNumMergeCand; ++ui)
   {
     mrgCtx.bcwIdx[ui] = BCW_DEFAULT;
+#if JVET_AG0276_NLIC
+    mrgCtx.altLMFlag[ui] = false;
+    mrgCtx.altLMParaNeighbours[ui].resetAltLinearModel();
+#endif
 #if INTER_LIC
     mrgCtx.licFlags[ui] = false;
 #endif
@@ -13044,6 +13377,10 @@ void PU::getNonAdjacentMergeCand(const PredictionUnit &pu, MergeCtx& mrgCtx)
   for (uint32_t ui = 0; ui < maxNumMergeCand; ++ui)
   {
     mrgCtx.bcwIdx[ui] = BCW_DEFAULT;
+#if JVET_AG0276_NLIC
+    mrgCtx.altLMFlag[ui] = false;
+    mrgCtx.altLMParaNeighbours[ui].resetAltLinearModel();
+#endif
 #if INTER_LIC
     mrgCtx.licFlags[ui] = false;
 #endif
@@ -13093,52 +13430,1381 @@ void PU::getNonAdjacentMergeCand(const PredictionUnit &pu, MergeCtx& mrgCtx)
 
       const PredictionUnit *puNonAdjacent = cs.getPURestricted(posLT.offset(offsetX, offsetY), pu, pu.chType);
 
-#if JVET_Y0065_GPM_INTRA
-      bool isAvailableNonAdjacent = puNonAdjacent && isDiffMER(pu.lumaPos(), posLT.offset(offsetX, offsetY), plevel) && CU::isInter(*puNonAdjacent->cu) && puNonAdjacent->getMotionInfo(posLT.offset(offsetX, offsetY)).isInter;
-#else
+#if JVET_Y0065_GPM_INTRA
+      bool isAvailableNonAdjacent = puNonAdjacent && isDiffMER(pu.lumaPos(), posLT.offset(offsetX, offsetY), plevel) && CU::isInter(*puNonAdjacent->cu) && puNonAdjacent->getMotionInfo(posLT.offset(offsetX, offsetY)).isInter;
+#else
+      bool isAvailableNonAdjacent = puNonAdjacent && isDiffMER(pu.lumaPos(), posLT.offset(offsetX, offsetY), plevel) && CU::isInter(*puNonAdjacent->cu);
+#endif
+
+      if (isAvailableNonAdjacent)
+      {
+        miNeighbor = puNonAdjacent->getMotionInfo(posLT.offset(offsetX, offsetY));
+
+        // get Inter Dir
+        mrgCtx.interDirNeighbours[cnt] = miNeighbor.interDir;
+        // get Mv from Above-Left
+        mrgCtx.mvFieldNeighbours[cnt << 1].setMvField(miNeighbor.mv[0], miNeighbor.refIdx[0]);
+        mrgCtx.useAltHpelIf[cnt] = miNeighbor.useAltHpelIf;
+        // get Mv from Above-right
+        mrgCtx.bcwIdx[cnt] = (mrgCtx.interDirNeighbours[cnt] == 3) ? puNonAdjacent->cu->bcwIdx : BCW_DEFAULT;
+#if INTER_LIC
+#if JVET_AG0276_NLIC
+        mrgCtx.licFlags[cnt] = miNeighbor.usesLIC || (puNonAdjacent->cu->altLMFlag && slice.getUseLIC());
+#else
+        mrgCtx.licFlags[cnt] = miNeighbor.usesLIC;
+#endif
+#endif
+        if (slice.isInterB())
+        {
+          mrgCtx.mvFieldNeighbours[(cnt << 1) + 1].setMvField(miNeighbor.mv[1], miNeighbor.refIdx[1]);
+#if MULTI_HYP_PRED
+          mrgCtx.addHypNeighbours[cnt] = puNonAdjacent->addHypData;
+#endif
+        }
+
+#if NON_ADJACENT_MRG_CAND || TM_MRG
+        if (!mrgCtx.xCheckSimilarMotion(cnt
+#if TM_MRG
+          , mvdSimilarityThresh
+#endif
+        ))
+#endif
+        {
+          cnt++;
+        }
+#if JVET_AD0213_LIC_IMP
+        else
+        {
+          mrgCtx.initMrgCand(cnt);
+        }
+#endif
+      }
+
+    }
+  }
+
+  const int numNACandidate2[7] = { 4, 4, 4, 4, 4, 4, 4 };
+  const int idxMap2[7][5] = { { 0, 1, 2, 3 },{ 0, 1, 2, 3 },{ 0, 1, 2, 3 },{ 0, 1, 2, 3 },{ 0, 1, 2, 3 },{ 0, 1, 2, 3 },{ 0, 1, 2, 3 } };
+
+  for (int iDistanceIndex = 0; iDistanceIndex < 7 && cnt < maxNumMergeCand; iDistanceIndex++)
+  {
+    const int iNADistanceHor = pu.Y().width  * (iDistanceIndex + 1);
+    const int iNADistanceVer = pu.Y().height * (iDistanceIndex + 1);
+
+    for (int iNASPIdx = 0; iNASPIdx < numNACandidate2[iDistanceIndex] && cnt < maxNumMergeCand; iNASPIdx++)
+    {
+      switch (idxMap2[iDistanceIndex][iNASPIdx])
+      {
+      case 0:offsetX = offsetX0 = -iNADistanceHor - 1;                                                         offsetY = offsetY2 + ((pu.Y().height + iNADistanceVer - 1 - offsetY2) >> 1); break;
+      case 1:offsetX = offsetX2 + ((pu.Y().width + iNADistanceHor - 1 - offsetX2) >> 1);                       offsetY = offsetY0 = -iNADistanceVer - 1; break;
+      case 2:offsetX = offsetX0;                                                                               offsetY = offsetY0 + ((offsetY2 - offsetY0) >> 1); break;
+      case 3:offsetX = offsetX0 + ((offsetX2 - offsetX0) >> 1);                                                offsetY = offsetY0; break;
+      default: printf("error!"); exit(0); break;
+      }
+
+      const PredictionUnit *puNonAdjacent = cs.getPURestricted(posLT.offset(offsetX, offsetY), pu, pu.chType);
+
+#if JVET_Y0065_GPM_INTRA
+      bool isAvailableNonAdjacent = puNonAdjacent && isDiffMER(pu.lumaPos(), posLT.offset(offsetX, offsetY), plevel) && CU::isInter(*puNonAdjacent->cu) && puNonAdjacent->getMotionInfo(posLT.offset(offsetX, offsetY)).isInter;
+#else
+      bool isAvailableNonAdjacent = puNonAdjacent && isDiffMER(pu.lumaPos(), posLT.offset(offsetX, offsetY), plevel) && CU::isInter(*puNonAdjacent->cu);
+#endif
+
+      if (isAvailableNonAdjacent)
+      {
+        miNeighbor = puNonAdjacent->getMotionInfo(posLT.offset(offsetX, offsetY));
+
+        // get Inter Dir
+        mrgCtx.interDirNeighbours[cnt] = miNeighbor.interDir;
+        // get Mv from Above-Left
+        mrgCtx.mvFieldNeighbours[cnt << 1].setMvField(miNeighbor.mv[0], miNeighbor.refIdx[0]);
+        mrgCtx.useAltHpelIf[cnt] = miNeighbor.useAltHpelIf;
+        // get Mv from Above-right
+        mrgCtx.bcwIdx[cnt] = (mrgCtx.interDirNeighbours[cnt] == 3) ? puNonAdjacent->cu->bcwIdx : BCW_DEFAULT;
+#if INTER_LIC
+#if JVET_AG0276_NLIC
+        mrgCtx.licFlags[cnt] = miNeighbor.usesLIC || (puNonAdjacent->cu->altLMFlag && slice.getUseLIC());
+#else
+        mrgCtx.licFlags[cnt] = miNeighbor.usesLIC;
+#endif
+#endif
+        if (slice.isInterB())
+        {
+          mrgCtx.mvFieldNeighbours[(cnt << 1) + 1].setMvField(miNeighbor.mv[1], miNeighbor.refIdx[1]);
+#if MULTI_HYP_PRED
+          mrgCtx.addHypNeighbours[cnt] = puNonAdjacent->addHypData;
+#endif
+        }
+
+#if NON_ADJACENT_MRG_CAND || TM_MRG
+        if (!mrgCtx.xCheckSimilarMotion(cnt
+#if TM_MRG
+          , mvdSimilarityThresh
+#endif
+        ))
+#endif
+        {
+          cnt++;
+        }
+#if JVET_AD0213_LIC_IMP
+        else
+        {
+          mrgCtx.initMrgCand(cnt);
+        }
+#endif
+      }
+    }
+  }
+
+  mrgCtx.numValidMergeCand = cnt;
+}
+#endif
+
+#if JVET_AG0276_NLIC
+uint32_t PU::getAltMergeMvdThreshold(const PredictionUnit &pu)
+{
+  uint32_t numPixels = pu.lwidth() * pu.lheight();
+  if (numPixels < 64)
+  {
+    return 1 << MV_FRACTIONAL_BITS_INTERNAL;
+  }
+  else if (numPixels < 256)
+  {
+    return 2 << MV_FRACTIONAL_BITS_INTERNAL;
+  }
+  else
+  {
+    return 4 << MV_FRACTIONAL_BITS_INTERNAL;
+  }
+}
+
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+bool PU::isValidAltMergeCandidate(const PredictionUnit &pu, bool isBRCand)
+#else
+bool PU::isValidAltMergeCandidate(const PredictionUnit &pu)
+#endif
+{
+  bool valid = true;
+  if (!CU::isInter(*pu.cu))
+  {
+    valid = false;
+  }
+  if (pu.cu->geoFlag)
+  {
+    valid = false;
+  }
+  if (pu.mergeFlag && pu.mergeType == MRG_TYPE_SUBPU_ATMVP)
+  {
+    valid = false;
+  }
+
+  if (!valid)
+  {
+    return false;
+  }
+
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+  bool trivial = false;
+  if (!isBRCand)
+  {
+    trivial = (pu.cu->altLMParaUnit.scale[0] == 32 && pu.cu->altLMParaUnit.offset[0] == 0);
+  }
+  else
+  {
+    trivial = (pu.cu->altLMBRParaUnit.scale[0] == 32 && pu.cu->altLMBRParaUnit.offset[0] == 0);
+  }
+#else
+  bool trivial = (pu.cu->altLMParaUnit.scale[0] == 32 && pu.cu->altLMParaUnit.offset[0] == 0);
+#endif
+
+  if (trivial)
+  {
+    return false;
+  }
+  return true;
+}
+
+void PU::getAltMergeCandidates(const PredictionUnit &pu, AltLMMergeCtx& cMrgCtx)
+{
+  const uint32_t         maxNumMergeCand = ALT_MRG_MAX_NUM_CANDS;
+  const unsigned         plevel = pu.cs->sps->getLog2ParallelMergeLevelMinus2() + 2;
+  const CodingStructure& cs = *pu.cs;
+  const Slice&           slice = *pu.cs->slice;
+  const uint32_t         mvdSimilarityThresh = getAltMergeMvdThreshold(pu);
+
+  for (int i = 0; i < maxNumMergeCand; i++)
+  {
+    cMrgCtx.initAltLMMergeCtx(i);
+  }
+
+  int cnt = 0;
+
+  const Position posLT = pu.Y().topLeft();
+  const Position posRT = pu.Y().topRight();
+  const Position posLB = pu.Y().bottomLeft();
+
+  // above
+  const PredictionUnit *puAbove = cs.getPURestricted(posRT.offset(0, -1), pu, pu.chType);
+  bool                 isAvailableB1 = puAbove && isDiffMER(pu.lumaPos(), posRT.offset(0, -1), plevel) && CU::isInter(*puAbove->cu);
+  if (isAvailableB1 && PU::isValidAltMergeCandidate(*puAbove))
+  {
+    MotionInfo miAbove = puAbove->getMotionInfo(posRT.offset(0, -1));
+    cMrgCtx.interDirNeighbours[cnt] = miAbove.interDir;
+    cMrgCtx.useAltHpelIf[cnt] = miAbove.useAltHpelIf;
+    cMrgCtx.bcwIdx[cnt] = (cMrgCtx.interDirNeighbours[cnt] == 3) ? puAbove->cu->bcwIdx : BCW_DEFAULT;
+    cMrgCtx.mvFieldNeighbours[cnt << 1].setMvField(miAbove.mv[0], miAbove.refIdx[0]);
+    if (slice.isInterB())
+    {
+      cMrgCtx.mvFieldNeighbours[(cnt << 1) + 1].setMvField(miAbove.mv[1], miAbove.refIdx[1]);
+    }
+    cMrgCtx.altLMParaNeighbours[cnt] = puAbove->cu->altLMParaUnit;
+    if (!cMrgCtx.xCheckSameMotion(cnt, mvdSimilarityThresh))
+    {
+      cnt++;
+    }
+    else
+    {
+      cMrgCtx.initAltLMMergeCtx(cnt);
+    }
+  }
+
+  if (cnt == maxNumMergeCand)
+  {
+    return;
+  }
+
+  //left
+  const PredictionUnit* puLeft = cs.getPURestricted(posLB.offset(-1, 0), pu, pu.chType);
+  const bool            isAvailableA1 = puLeft && isDiffMER(pu.lumaPos(), posLB.offset(-1, 0), plevel) && CU::isInter(*puLeft->cu);
+  if (isAvailableA1 && PU::isValidAltMergeCandidate(*puLeft))
+  {
+    MotionInfo miLeft = puLeft->getMotionInfo(posLB.offset(-1, 0));
+    cMrgCtx.interDirNeighbours[cnt] = miLeft.interDir;
+    cMrgCtx.useAltHpelIf[cnt] = miLeft.useAltHpelIf;
+    cMrgCtx.bcwIdx[cnt] = (cMrgCtx.interDirNeighbours[cnt] == 3) ? puLeft->cu->bcwIdx : BCW_DEFAULT;
+    cMrgCtx.mvFieldNeighbours[cnt << 1].setMvField(miLeft.mv[0], miLeft.refIdx[0]);
+    if (slice.isInterB())
+    {
+      cMrgCtx.mvFieldNeighbours[(cnt << 1) + 1].setMvField(miLeft.mv[1], miLeft.refIdx[1]);
+    }
+    cMrgCtx.altLMParaNeighbours[cnt] = puLeft->cu->altLMParaUnit;
+    if (!cMrgCtx.xCheckSameMotion(cnt, mvdSimilarityThresh))
+    {
+      cnt++;
+    }
+    else
+    {
+      cMrgCtx.initAltLMMergeCtx(cnt);
+    }
+  }
+
+  if (cnt == maxNumMergeCand)
+  {
+    return;
+  }
+
+  // above right
+  const PredictionUnit *puAboveRight = cs.getPURestricted(posRT.offset(1, -1), pu, pu.chType);
+  const bool            isAvailableB0 = puAboveRight && isDiffMER(pu.lumaPos(), posRT.offset(1, -1), plevel) && CU::isInter(*puAboveRight->cu);
+  if (isAvailableB0 && PU::isValidAltMergeCandidate(*puAboveRight))
+  {
+    MotionInfo miAboveRight = puAboveRight->getMotionInfo(posRT.offset(1, -1));
+    cMrgCtx.interDirNeighbours[cnt] = miAboveRight.interDir;
+    cMrgCtx.useAltHpelIf[cnt] = miAboveRight.useAltHpelIf;
+    cMrgCtx.bcwIdx[cnt] = (cMrgCtx.interDirNeighbours[cnt] == 3) ? puAboveRight->cu->bcwIdx : BCW_DEFAULT;
+    cMrgCtx.mvFieldNeighbours[cnt << 1].setMvField(miAboveRight.mv[0], miAboveRight.refIdx[0]);
+    if (slice.isInterB())
+    {
+      cMrgCtx.mvFieldNeighbours[(cnt << 1) + 1].setMvField(miAboveRight.mv[1], miAboveRight.refIdx[1]);
+    }
+    cMrgCtx.altLMParaNeighbours[cnt] = puAboveRight->cu->altLMParaUnit;
+    if (!cMrgCtx.xCheckSameMotion(cnt, mvdSimilarityThresh))
+    {
+      cnt++;
+    }
+    else
+    {
+      cMrgCtx.initAltLMMergeCtx(cnt);
+    }
+  }
+
+  if (cnt == maxNumMergeCand)
+  {
+    return;
+  }
+
+  //left bottom
+  const PredictionUnit *puLeftBottom = cs.getPURestricted(posLB.offset(-1, 1), pu, pu.chType);
+  bool                 isAvailableA0 = puLeftBottom && isDiffMER(pu.lumaPos(), posLB.offset(-1, 1), plevel) && CU::isInter(*puLeftBottom->cu);
+  if (isAvailableA0 && PU::isValidAltMergeCandidate(*puLeftBottom))
+  {
+    MotionInfo miBelowLeft = puLeftBottom->getMotionInfo(posLB.offset(-1, 1));
+    cMrgCtx.interDirNeighbours[cnt] = miBelowLeft.interDir;
+    cMrgCtx.useAltHpelIf[cnt] = miBelowLeft.useAltHpelIf;
+    cMrgCtx.bcwIdx[cnt] = (cMrgCtx.interDirNeighbours[cnt] == 3) ? puLeftBottom->cu->bcwIdx : BCW_DEFAULT;
+    cMrgCtx.mvFieldNeighbours[cnt << 1].setMvField(miBelowLeft.mv[0], miBelowLeft.refIdx[0]);
+    if (slice.isInterB())
+    {
+      cMrgCtx.mvFieldNeighbours[(cnt << 1) + 1].setMvField(miBelowLeft.mv[1], miBelowLeft.refIdx[1]);
+    }
+    cMrgCtx.altLMParaNeighbours[cnt] = puLeftBottom->cu->altLMParaUnit;
+    if (!cMrgCtx.xCheckSameMotion(cnt, mvdSimilarityThresh))
+    {
+      cnt++;
+    }
+    else
+    {
+      cMrgCtx.initAltLMMergeCtx(cnt);
+    }
+  }
+
+  if (cnt == maxNumMergeCand)
+  {
+    return;
+  }
+
+  // above left
+  const PredictionUnit *puAboveLeft = cs.getPURestricted(posLT.offset(-1, -1), pu, pu.chType);
+  bool                 isAvailableB2 = puAboveLeft && isDiffMER(pu.lumaPos(), posLT.offset(-1, -1), plevel) && CU::isInter(*puAboveLeft->cu);
+  if (isAvailableB2 && PU::isValidAltMergeCandidate(*puAboveLeft))
+  {
+    MotionInfo miAboveLeft = puAboveLeft->getMotionInfo(posLT.offset(-1, -1));
+    cMrgCtx.interDirNeighbours[cnt] = miAboveLeft.interDir;
+    cMrgCtx.useAltHpelIf[cnt] = miAboveLeft.useAltHpelIf;
+    cMrgCtx.bcwIdx[cnt] = (cMrgCtx.interDirNeighbours[cnt] == 3) ? puAboveLeft->cu->bcwIdx : BCW_DEFAULT;
+    cMrgCtx.mvFieldNeighbours[cnt << 1].setMvField(miAboveLeft.mv[0], miAboveLeft.refIdx[0]);
+    if (slice.isInterB())
+    {
+      cMrgCtx.mvFieldNeighbours[(cnt << 1) + 1].setMvField(miAboveLeft.mv[1], miAboveLeft.refIdx[1]);
+    }
+    cMrgCtx.altLMParaNeighbours[cnt] = puAboveLeft->cu->altLMParaUnit;
+    if (!cMrgCtx.xCheckSameMotion(cnt, mvdSimilarityThresh))
+    {
+      cnt++;
+    }
+    else
+    {
+      cMrgCtx.initAltLMMergeCtx(cnt);
+    }
+  }
+
+  if (cnt == maxNumMergeCand)
+  {
+    return;
+  }
+
+  int offsetX = 0;
+  int offsetY = 0;
+  int offsetX0 = 0; int offsetX1 = 0; int offsetX2 = pu.Y().width >> 1;
+  int offsetY0 = 0; int offsetY1 = 0; int offsetY2 = pu.Y().height >> 1;
+
+  const int numNACandidate[7] = { 5, 9, 9, 9, 9, 9, 9 };
+  const int idxMap[7][9] = { { 0, 1, 2, 3, 4 },{ 0, 1, 2, 3, 4, 5, 6, 7, 8 },{ 0, 1, 2, 3, 4, 5, 6, 7, 8 },{ 0, 1, 2, 3, 4, 5, 6, 7, 8 },{ 0, 1, 2, 3, 4, 5, 6, 7, 8 },{ 0, 1, 2, 3, 4, 5, 6, 7, 8 },{ 0, 1, 2, 3, 4, 5, 6, 7, 8 } };
+
+  for (int iDistanceIndex = 0; iDistanceIndex < 7 && cnt < maxNumMergeCand; iDistanceIndex++)
+  {
+    const int iNADistanceHor = pu.Y().width  * (iDistanceIndex + 1);
+    const int iNADistanceVer = pu.Y().height * (iDistanceIndex + 1);
+
+    for (int iNASPIdx = 0; iNASPIdx < numNACandidate[iDistanceIndex] && cnt < maxNumMergeCand; iNASPIdx++)
+    {
+      switch (idxMap[iDistanceIndex][iNASPIdx])
+      {
+      case 0:offsetX = offsetX0 = -iNADistanceHor - 1;               offsetY = offsetY0 = pu.Y().height + iNADistanceVer - 1; break;
+      case 1:offsetX = offsetX1 = pu.Y().width + iNADistanceHor - 1; offsetY = offsetY1 = -iNADistanceVer - 1;                break;
+      case 2:offsetX = offsetX2;                                     offsetY = offsetY1;                                      break;
+      case 3:offsetX = offsetX0;                                     offsetY = offsetY2;                                      break;
+      case 4:offsetX = offsetX0;                                     offsetY = offsetY1;                                      break;
+      case 5:offsetX = -1;                                           offsetY = offsetY0;                                      break;
+      case 6:offsetX = offsetX1;                                     offsetY = -1;                                            break;
+      case 7:offsetX = offsetX0 >> 1;                                offsetY = offsetY0;                                      break;
+      case 8:offsetX = offsetX1;                                     offsetY = offsetY1 >> 1;                                 break;
+      default: printf("error!"); exit(0); break;
+      }
+
+      const PredictionUnit *puNonAdjacent = cs.getPURestricted(posLT.offset(offsetX, offsetY), pu, pu.chType);
+
+      bool isAvailableNonAdjacent = puNonAdjacent && isDiffMER(pu.lumaPos(), posLT.offset(offsetX, offsetY), plevel) && CU::isInter(*puNonAdjacent->cu);
+      if (isAvailableNonAdjacent && PU::isValidAltMergeCandidate(*puNonAdjacent))
+      {
+        MotionInfo miNeighbor = puNonAdjacent->getMotionInfo(posLT.offset(offsetX, offsetY));
+        cMrgCtx.interDirNeighbours[cnt] = miNeighbor.interDir;
+        cMrgCtx.useAltHpelIf[cnt] = miNeighbor.useAltHpelIf;
+        cMrgCtx.bcwIdx[cnt] = (cMrgCtx.interDirNeighbours[cnt] == 3) ? puNonAdjacent->cu->bcwIdx : BCW_DEFAULT;
+        cMrgCtx.mvFieldNeighbours[cnt << 1].setMvField(miNeighbor.mv[0], miNeighbor.refIdx[0]);
+        if (slice.isInterB())
+        {
+          cMrgCtx.mvFieldNeighbours[(cnt << 1) + 1].setMvField(miNeighbor.mv[1], miNeighbor.refIdx[1]);
+        }
+        cMrgCtx.altLMParaNeighbours[cnt] = puNonAdjacent->cu->altLMParaUnit;
+        if (!cMrgCtx.xCheckSameMotion(cnt, mvdSimilarityThresh))
+        {
+          cnt++;
+        }
+        else
+        {
+          cMrgCtx.initAltLMMergeCtx(cnt);
+        }
+      }
+    }
+  }
+
+  const int numNACandidate2[7] = { 4, 4, 4, 4, 4, 4, 4 };
+  const int idxMap2[7][5] = { { 0, 1, 2, 3 },{ 0, 1, 2, 3 },{ 0, 1, 2, 3 },{ 0, 1, 2, 3 },{ 0, 1, 2, 3 },{ 0, 1, 2, 3 },{ 0, 1, 2, 3 } };
+
+  for (int iDistanceIndex = 0; iDistanceIndex < 7 && cnt < maxNumMergeCand; iDistanceIndex++)
+  {
+    const int iNADistanceHor = pu.Y().width  * (iDistanceIndex + 1);
+    const int iNADistanceVer = pu.Y().height * (iDistanceIndex + 1);
+
+    for (int iNASPIdx = 0; iNASPIdx < numNACandidate2[iDistanceIndex] && cnt < maxNumMergeCand; iNASPIdx++)
+    {
+      switch (idxMap2[iDistanceIndex][iNASPIdx])
+      {
+      case 0:offsetX = offsetX0 = -iNADistanceHor - 1;                                                         offsetY = offsetY2 + ((pu.Y().height + iNADistanceVer - 1 - offsetY2) >> 1); break;
+      case 1:offsetX = offsetX2 + ((pu.Y().width + iNADistanceHor - 1 - offsetX2) >> 1);                       offsetY = offsetY0 = -iNADistanceVer - 1; break;
+      case 2:offsetX = offsetX0;                                                                               offsetY = offsetY0 + ((offsetY2 - offsetY0) >> 1); break;
+      case 3:offsetX = offsetX0 + ((offsetX2 - offsetX0) >> 1);                                                offsetY = offsetY0; break;
+      default: printf("error!"); exit(0); break;
+      }
+
+      const PredictionUnit *puNonAdjacent = cs.getPURestricted(posLT.offset(offsetX, offsetY), pu, pu.chType);
+
+      bool isAvailableNonAdjacent = puNonAdjacent && isDiffMER(pu.lumaPos(), posLT.offset(offsetX, offsetY), plevel) && CU::isInter(*puNonAdjacent->cu);
+      if (isAvailableNonAdjacent && PU::isValidAltMergeCandidate(*puNonAdjacent))
+      {
+        MotionInfo miNeighbor = puNonAdjacent->getMotionInfo(posLT.offset(offsetX, offsetY));
+        cMrgCtx.interDirNeighbours[cnt] = miNeighbor.interDir;
+        cMrgCtx.useAltHpelIf[cnt] = miNeighbor.useAltHpelIf;
+        cMrgCtx.bcwIdx[cnt] = (cMrgCtx.interDirNeighbours[cnt] == 3) ? puNonAdjacent->cu->bcwIdx : BCW_DEFAULT;
+        cMrgCtx.mvFieldNeighbours[cnt << 1].setMvField(miNeighbor.mv[0], miNeighbor.refIdx[0]);
+        if (slice.isInterB())
+        {
+          cMrgCtx.mvFieldNeighbours[(cnt << 1) + 1].setMvField(miNeighbor.mv[1], miNeighbor.refIdx[1]);
+        }
+        cMrgCtx.altLMParaNeighbours[cnt] = puNonAdjacent->cu->altLMParaUnit;
+        if (!cMrgCtx.xCheckSameMotion(cnt, mvdSimilarityThresh))
+        {
+          cnt++;
+        }
+        else
+        {
+          cMrgCtx.initAltLMMergeCtx(cnt);
+        }
+      }
+    }
+  }
+
+  cMrgCtx.numValidMergeCand = cnt;
+  return;
+}
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+void PU::getAltBRMergeCandidates(const PredictionUnit &pu, AltLMMergeCtx& cMrgCtx)
+{
+  const uint32_t         maxNumMergeCand = ALT_MRG_MAX_NUM_CANDS;
+  const unsigned         plevel = pu.cs->sps->getLog2ParallelMergeLevelMinus2() + 2;
+  const CodingStructure& cs = *pu.cs;
+  const Slice&           slice = *pu.cs->slice;
+  const uint32_t         mvdSimilarityThresh = getAltMergeMvdThreshold(pu);
+
+  for (int i = 0; i < maxNumMergeCand; i++)
+  {
+    cMrgCtx.initAltLMMergeCtx(i);
+  }
+
+  int cnt = 0;
+
+  const Position posLT = pu.Y().topLeft();
+  const Position posRT = pu.Y().topRight();
+  const Position posLB = pu.Y().bottomLeft();
+
+  const PredictionUnit *puAbove = cs.getPURestricted(posRT.offset(0, -1), pu, pu.chType);
+  bool                 isAvailableB1 = puAbove && isDiffMER(pu.lumaPos(), posRT.offset(0, -1), plevel) && CU::isInter(*puAbove->cu);
+  if (isAvailableB1 && PU::isValidAltMergeCandidate(*puAbove, true))
+  {
+    MotionInfo miAbove = puAbove->getMotionInfo(posRT.offset(0, -1));
+    cMrgCtx.interDirNeighbours[cnt] = miAbove.interDir;
+    cMrgCtx.useAltHpelIf[cnt] = miAbove.useAltHpelIf;
+    cMrgCtx.bcwIdx[cnt] = (cMrgCtx.interDirNeighbours[cnt] == 3) ? puAbove->cu->bcwIdx : BCW_DEFAULT;
+    cMrgCtx.mvFieldNeighbours[cnt << 1].setMvField(miAbove.mv[0], miAbove.refIdx[0]);
+    if (slice.isInterB())
+    {
+      cMrgCtx.mvFieldNeighbours[(cnt << 1) + 1].setMvField(miAbove.mv[1], miAbove.refIdx[1]);
+    }
+    cMrgCtx.altLMParaNeighbours[cnt] = puAbove->cu->altLMBRParaUnit;
+    if (!cMrgCtx.xCheckSameMotion(cnt, mvdSimilarityThresh))
+    {
+      cnt++;
+    }
+    else
+    {
+      cMrgCtx.initAltLMMergeCtx(cnt);
+    }
+  }
+
+  if (cnt == maxNumMergeCand)
+  {
+    return;
+  }
+
+  const PredictionUnit* puLeft = cs.getPURestricted(posLB.offset(-1, 0), pu, pu.chType);
+  const bool            isAvailableA1 = puLeft && isDiffMER(pu.lumaPos(), posLB.offset(-1, 0), plevel) && CU::isInter(*puLeft->cu);
+  if (isAvailableA1 && PU::isValidAltMergeCandidate(*puLeft, true))
+  {
+    MotionInfo miLeft = puLeft->getMotionInfo(posLB.offset(-1, 0));
+    cMrgCtx.interDirNeighbours[cnt] = miLeft.interDir;
+    cMrgCtx.useAltHpelIf[cnt] = miLeft.useAltHpelIf;
+    cMrgCtx.bcwIdx[cnt] = (cMrgCtx.interDirNeighbours[cnt] == 3) ? puLeft->cu->bcwIdx : BCW_DEFAULT;
+    cMrgCtx.mvFieldNeighbours[cnt << 1].setMvField(miLeft.mv[0], miLeft.refIdx[0]);
+    if (slice.isInterB())
+    {
+      cMrgCtx.mvFieldNeighbours[(cnt << 1) + 1].setMvField(miLeft.mv[1], miLeft.refIdx[1]);
+    }
+    cMrgCtx.altLMParaNeighbours[cnt] = puLeft->cu->altLMBRParaUnit;
+    if (!cMrgCtx.xCheckSameMotion(cnt, mvdSimilarityThresh))
+    {
+      cnt++;
+    }
+    else
+    {
+      cMrgCtx.initAltLMMergeCtx(cnt);
+    }
+  }
+
+  if (cnt == maxNumMergeCand)
+  {
+    return;
+  }
+
+  const PredictionUnit *puAboveRight = cs.getPURestricted(posRT.offset(1, -1), pu, pu.chType);
+  const bool            isAvailableB0 = puAboveRight && isDiffMER(pu.lumaPos(), posRT.offset(1, -1), plevel) && CU::isInter(*puAboveRight->cu);
+  if (isAvailableB0 && PU::isValidAltMergeCandidate(*puAboveRight, true))
+  {
+    MotionInfo miAboveRight = puAboveRight->getMotionInfo(posRT.offset(1, -1));
+    cMrgCtx.interDirNeighbours[cnt] = miAboveRight.interDir;
+    cMrgCtx.useAltHpelIf[cnt] = miAboveRight.useAltHpelIf;
+    cMrgCtx.bcwIdx[cnt] = (cMrgCtx.interDirNeighbours[cnt] == 3) ? puAboveRight->cu->bcwIdx : BCW_DEFAULT;
+    cMrgCtx.mvFieldNeighbours[cnt << 1].setMvField(miAboveRight.mv[0], miAboveRight.refIdx[0]);
+    if (slice.isInterB())
+    {
+      cMrgCtx.mvFieldNeighbours[(cnt << 1) + 1].setMvField(miAboveRight.mv[1], miAboveRight.refIdx[1]);
+    }
+    cMrgCtx.altLMParaNeighbours[cnt] = puAboveRight->cu->altLMBRParaUnit;
+    if (!cMrgCtx.xCheckSameMotion(cnt, mvdSimilarityThresh))
+    {
+      cnt++;
+    }
+    else
+    {
+      cMrgCtx.initAltLMMergeCtx(cnt);
+    }
+  }
+
+  if (cnt == maxNumMergeCand)
+  {
+    return;
+  }
+
+  const PredictionUnit *puLeftBottom = cs.getPURestricted(posLB.offset(-1, 1), pu, pu.chType);
+  bool                 isAvailableA0 = puLeftBottom && isDiffMER(pu.lumaPos(), posLB.offset(-1, 1), plevel) && CU::isInter(*puLeftBottom->cu);
+  if (isAvailableA0 && PU::isValidAltMergeCandidate(*puLeftBottom, true))
+  {
+    MotionInfo miBelowLeft = puLeftBottom->getMotionInfo(posLB.offset(-1, 1));
+    cMrgCtx.interDirNeighbours[cnt] = miBelowLeft.interDir;
+    cMrgCtx.useAltHpelIf[cnt] = miBelowLeft.useAltHpelIf;
+    cMrgCtx.bcwIdx[cnt] = (cMrgCtx.interDirNeighbours[cnt] == 3) ? puLeftBottom->cu->bcwIdx : BCW_DEFAULT;
+    cMrgCtx.mvFieldNeighbours[cnt << 1].setMvField(miBelowLeft.mv[0], miBelowLeft.refIdx[0]);
+    if (slice.isInterB())
+    {
+      cMrgCtx.mvFieldNeighbours[(cnt << 1) + 1].setMvField(miBelowLeft.mv[1], miBelowLeft.refIdx[1]);
+    }
+    cMrgCtx.altLMParaNeighbours[cnt] = puLeftBottom->cu->altLMBRParaUnit;
+    if (!cMrgCtx.xCheckSameMotion(cnt, mvdSimilarityThresh))
+    {
+      cnt++;
+    }
+    else
+    {
+      cMrgCtx.initAltLMMergeCtx(cnt);
+    }
+  }
+
+  if (cnt == maxNumMergeCand)
+  {
+    return;
+  }
+
+  const PredictionUnit *puAboveLeft = cs.getPURestricted(posLT.offset(-1, -1), pu, pu.chType);
+  bool                 isAvailableB2 = puAboveLeft && isDiffMER(pu.lumaPos(), posLT.offset(-1, -1), plevel) && CU::isInter(*puAboveLeft->cu);
+  if (isAvailableB2 && PU::isValidAltMergeCandidate(*puAboveLeft, true))
+  {
+    MotionInfo miAboveLeft = puAboveLeft->getMotionInfo(posLT.offset(-1, -1));
+    cMrgCtx.interDirNeighbours[cnt] = miAboveLeft.interDir;
+    cMrgCtx.useAltHpelIf[cnt] = miAboveLeft.useAltHpelIf;
+    cMrgCtx.bcwIdx[cnt] = (cMrgCtx.interDirNeighbours[cnt] == 3) ? puAboveLeft->cu->bcwIdx : BCW_DEFAULT;
+    cMrgCtx.mvFieldNeighbours[cnt << 1].setMvField(miAboveLeft.mv[0], miAboveLeft.refIdx[0]);
+    if (slice.isInterB())
+    {
+      cMrgCtx.mvFieldNeighbours[(cnt << 1) + 1].setMvField(miAboveLeft.mv[1], miAboveLeft.refIdx[1]);
+    }
+    cMrgCtx.altLMParaNeighbours[cnt] = puAboveLeft->cu->altLMBRParaUnit;
+    if (!cMrgCtx.xCheckSameMotion(cnt, mvdSimilarityThresh))
+    {
+      cnt++;
+    }
+    else
+    {
+      cMrgCtx.initAltLMMergeCtx(cnt);
+    }
+  }
+
+  if (cnt == maxNumMergeCand)
+  {
+    return;
+  }
+
+  int offsetX = 0;
+  int offsetY = 0;
+  int offsetX0 = 0; int offsetX1 = 0; int offsetX2 = pu.Y().width >> 1;
+  int offsetY0 = 0; int offsetY1 = 0; int offsetY2 = pu.Y().height >> 1;
+
+  const int numNACandidate[7] = { 5, 9, 9, 9, 9, 9, 9 };
+  const int idxMap[7][9] = { { 0, 1, 2, 3, 4 },{ 0, 1, 2, 3, 4, 5, 6, 7, 8 },{ 0, 1, 2, 3, 4, 5, 6, 7, 8 },{ 0, 1, 2, 3, 4, 5, 6, 7, 8 },{ 0, 1, 2, 3, 4, 5, 6, 7, 8 },{ 0, 1, 2, 3, 4, 5, 6, 7, 8 },{ 0, 1, 2, 3, 4, 5, 6, 7, 8 } };
+
+  for (int iDistanceIndex = 0; iDistanceIndex < 7 && cnt < maxNumMergeCand; iDistanceIndex++)
+  {
+    const int iNADistanceHor = pu.Y().width  * (iDistanceIndex + 1);
+    const int iNADistanceVer = pu.Y().height * (iDistanceIndex + 1);
+
+    for (int iNASPIdx = 0; iNASPIdx < numNACandidate[iDistanceIndex] && cnt < maxNumMergeCand; iNASPIdx++)
+    {
+      switch (idxMap[iDistanceIndex][iNASPIdx])
+      {
+        case 0:offsetX = offsetX0 = -iNADistanceHor - 1;               offsetY = offsetY0 = pu.Y().height + iNADistanceVer - 1; break;
+        case 1:offsetX = offsetX1 = pu.Y().width + iNADistanceHor - 1; offsetY = offsetY1 = -iNADistanceVer - 1;                break;
+        case 2:offsetX = offsetX2;                                     offsetY = offsetY1;                                      break;
+        case 3:offsetX = offsetX0;                                     offsetY = offsetY2;                                      break;
+        case 4:offsetX = offsetX0;                                     offsetY = offsetY1;                                      break;
+        case 5:offsetX = -1;                                           offsetY = offsetY0;                                      break;
+        case 6:offsetX = offsetX1;                                     offsetY = -1;                                            break;
+        case 7:offsetX = offsetX0 >> 1;                                offsetY = offsetY0;                                      break;
+        case 8:offsetX = offsetX1;                                     offsetY = offsetY1 >> 1;                                 break;
+        default: printf("error!"); exit(0); break;
+      }
+
+      const PredictionUnit *puNonAdjacent = cs.getPURestricted(posLT.offset(offsetX, offsetY), pu, pu.chType);
+
+      bool isAvailableNonAdjacent = puNonAdjacent && isDiffMER(pu.lumaPos(), posLT.offset(offsetX, offsetY), plevel) && CU::isInter(*puNonAdjacent->cu);
+      if (isAvailableNonAdjacent && PU::isValidAltMergeCandidate(*puNonAdjacent, true))
+      {
+        MotionInfo miNeighbor = puNonAdjacent->getMotionInfo(posLT.offset(offsetX, offsetY));
+        cMrgCtx.interDirNeighbours[cnt] = miNeighbor.interDir;
+        cMrgCtx.useAltHpelIf[cnt] = miNeighbor.useAltHpelIf;
+        cMrgCtx.bcwIdx[cnt] = (cMrgCtx.interDirNeighbours[cnt] == 3) ? puNonAdjacent->cu->bcwIdx : BCW_DEFAULT;
+        cMrgCtx.mvFieldNeighbours[cnt << 1].setMvField(miNeighbor.mv[0], miNeighbor.refIdx[0]);
+        if (slice.isInterB())
+        {
+          cMrgCtx.mvFieldNeighbours[(cnt << 1) + 1].setMvField(miNeighbor.mv[1], miNeighbor.refIdx[1]);
+        }
+        cMrgCtx.altLMParaNeighbours[cnt] = puNonAdjacent->cu->altLMBRParaUnit;
+        if (!cMrgCtx.xCheckSameMotion(cnt, mvdSimilarityThresh))
+        {
+          cnt++;
+        }
+        else
+        {
+          cMrgCtx.initAltLMMergeCtx(cnt);
+        }
+      }
+    }
+  }
+
+  const int numNACandidate2[7] = { 4, 4, 4, 4, 4, 4, 4 };
+  const int idxMap2[7][5] = { { 0, 1, 2, 3 },{ 0, 1, 2, 3 },{ 0, 1, 2, 3 },{ 0, 1, 2, 3 },{ 0, 1, 2, 3 },{ 0, 1, 2, 3 },{ 0, 1, 2, 3 } };
+
+  for (int iDistanceIndex = 0; iDistanceIndex < 7 && cnt < maxNumMergeCand; iDistanceIndex++)
+  {
+    const int iNADistanceHor = pu.Y().width  * (iDistanceIndex + 1);
+    const int iNADistanceVer = pu.Y().height * (iDistanceIndex + 1);
+
+    for (int iNASPIdx = 0; iNASPIdx < numNACandidate2[iDistanceIndex] && cnt < maxNumMergeCand; iNASPIdx++)
+    {
+      switch (idxMap2[iDistanceIndex][iNASPIdx])
+      {
+        case 0:offsetX = offsetX0 = -iNADistanceHor - 1;                                                         offsetY = offsetY2 + ((pu.Y().height + iNADistanceVer - 1 - offsetY2) >> 1); break;
+        case 1:offsetX = offsetX2 + ((pu.Y().width + iNADistanceHor - 1 - offsetX2) >> 1);                       offsetY = offsetY0 = -iNADistanceVer - 1; break;
+        case 2:offsetX = offsetX0;                                                                               offsetY = offsetY0 + ((offsetY2 - offsetY0) >> 1); break;
+        case 3:offsetX = offsetX0 + ((offsetX2 - offsetX0) >> 1);                                                offsetY = offsetY0; break;
+        default: printf("error!"); exit(0); break;
+      }
+
+      const PredictionUnit *puNonAdjacent = cs.getPURestricted(posLT.offset(offsetX, offsetY), pu, pu.chType);
+
+      bool isAvailableNonAdjacent = puNonAdjacent && isDiffMER(pu.lumaPos(), posLT.offset(offsetX, offsetY), plevel) && CU::isInter(*puNonAdjacent->cu);
+      if (isAvailableNonAdjacent && PU::isValidAltMergeCandidate(*puNonAdjacent, true))
+      {
+        MotionInfo miNeighbor = puNonAdjacent->getMotionInfo(posLT.offset(offsetX, offsetY));
+        cMrgCtx.interDirNeighbours[cnt] = miNeighbor.interDir;
+        cMrgCtx.useAltHpelIf[cnt] = miNeighbor.useAltHpelIf;
+        cMrgCtx.bcwIdx[cnt] = (cMrgCtx.interDirNeighbours[cnt] == 3) ? puNonAdjacent->cu->bcwIdx : BCW_DEFAULT;
+        cMrgCtx.mvFieldNeighbours[cnt << 1].setMvField(miNeighbor.mv[0], miNeighbor.refIdx[0]);
+        if (slice.isInterB())
+        {
+          cMrgCtx.mvFieldNeighbours[(cnt << 1) + 1].setMvField(miNeighbor.mv[1], miNeighbor.refIdx[1]);
+        }
+        cMrgCtx.altLMParaNeighbours[cnt] = puNonAdjacent->cu->altLMBRParaUnit;
+        if (!cMrgCtx.xCheckSameMotion(cnt, mvdSimilarityThresh))
+        {
+          cnt++;
+        }
+        else
+        {
+          cMrgCtx.initAltLMMergeCtx(cnt);
+        }
+      }
+    }
+  }
+
+  cMrgCtx.numValidMergeCand = cnt;
+  return;
+}
+#endif
+#endif
+
+#if JVET_AG0276_NLIC
+void PU::getAltLMAffineMergeCand(const PredictionUnit &pu, AltLMAffineMergeCtx& affMrgCtx)
+{
+  const uint32_t         maxNumMergeCand = ALT_AFF_MRG_MAX_NUM_CANDS;
+  const unsigned         plevel = pu.cs->sps->getLog2ParallelMergeLevelMinus2() + 2;
+  const CodingStructure& cs = *pu.cs;
+  const Slice&           slice = *pu.cs->slice;
+
+  for (int i = 0; i < maxNumMergeCand; i++)
+  {
+    affMrgCtx.initAltLMAffMergeCtx(i);
+  }
+
+  int cnt = 0;
+
+  const Position posLT = pu.Y().topLeft();
+  const Position posRT = pu.Y().topRight();
+  const Position posLB = pu.Y().bottomLeft();
+
+  // above
+  const PredictionUnit *puAbove = cs.getPURestricted(posRT.offset(0, -1), pu, pu.chType);
+  bool isAvailableB1 = puAbove && isDiffMER(pu.lumaPos(), posRT.offset(0, -1), plevel) && CU::isInter(*puAbove->cu);
+  if (isAvailableB1 && puAbove->cu->affine && (puAbove->mergeType == MRG_TYPE_DEFAULT_N) && PU::isValidAltMergeCandidate(*puAbove))
+  {
+    Mv cMv[2][3];
+    affMrgCtx.affineType[cnt] = (EAffineModel)puAbove->cu->affineType;
+    pu.cu->affineType = puAbove->cu->affineType;
+    if (puAbove->interDir != 2)
+    {
+      xInheritedAffineMv(pu, puAbove, REF_PIC_LIST_0, cMv[0]);
+    }
+    if (slice.isInterB())
+    {
+      if (puAbove->interDir != 1)
+      {
+        xInheritedAffineMv(pu, puAbove, REF_PIC_LIST_1, cMv[1]);
+      }
+    }
+    for (int mvNum = 0; mvNum < 3; mvNum++)
+    {
+      affMrgCtx.mvFieldNeighbours[(cnt << 1) + 0][mvNum].setMvField(cMv[0][mvNum], puAbove->refIdx[0]);
+      affMrgCtx.mvFieldNeighbours[(cnt << 1) + 1][mvNum].setMvField(cMv[1][mvNum], puAbove->refIdx[1]);
+    }
+    affMrgCtx.interDirNeighbours[cnt] = puAbove->interDir;
+    affMrgCtx.bcwIdx[cnt] = (affMrgCtx.interDirNeighbours[cnt] == 3) ? puAbove->cu->bcwIdx : BCW_DEFAULT;
+#if JVET_AD0193_ADAPTIVE_OBMC_CONTROL
+    affMrgCtx.obmcFlags[cnt] = puAbove->cu->obmcFlag;
+#endif
+    affMrgCtx.altLMParaNeighbours[cnt] = puAbove->cu->altLMParaUnit;
+    if (affMrgCtx.xCheckSameAffMotion(pu, cnt))
+    {
+      cnt++;
+    }
+  }
+
+  if (cnt == maxNumMergeCand)
+  {
+    return;
+  }
+
+  //left
+  const PredictionUnit* puLeft = cs.getPURestricted(posLB.offset(-1, 0), pu, pu.chType);
+  const bool isAvailableA1 = puLeft && isDiffMER(pu.lumaPos(), posLB.offset(-1, 0), plevel) && CU::isInter(*puLeft->cu);
+  if (isAvailableA1 && puLeft->cu->affine && (puLeft->mergeType == MRG_TYPE_DEFAULT_N) && PU::isValidAltMergeCandidate(*puLeft))
+  {
+    Mv cMv[2][3];
+    affMrgCtx.affineType[cnt] = (EAffineModel)puLeft->cu->affineType;
+    pu.cu->affineType = puLeft->cu->affineType;
+    if (puLeft->interDir != 2)
+    {
+      xInheritedAffineMv(pu, puLeft, REF_PIC_LIST_0, cMv[0]);
+    }
+    if (slice.isInterB())
+    {
+      if (puLeft->interDir != 1)
+      {
+        xInheritedAffineMv(pu, puLeft, REF_PIC_LIST_1, cMv[1]);
+      }
+    }
+    for (int mvNum = 0; mvNum < 3; mvNum++)
+    {
+      affMrgCtx.mvFieldNeighbours[(cnt << 1) + 0][mvNum].setMvField(cMv[0][mvNum], puLeft->refIdx[0]);
+      affMrgCtx.mvFieldNeighbours[(cnt << 1) + 1][mvNum].setMvField(cMv[1][mvNum], puLeft->refIdx[1]);
+    }
+    affMrgCtx.interDirNeighbours[cnt] = puLeft->interDir;
+    affMrgCtx.bcwIdx[cnt] = (affMrgCtx.interDirNeighbours[cnt] == 3) ? puLeft->cu->bcwIdx : BCW_DEFAULT;
+#if JVET_AD0193_ADAPTIVE_OBMC_CONTROL
+    affMrgCtx.obmcFlags[cnt] = puLeft->cu->obmcFlag;
+#endif
+    affMrgCtx.altLMParaNeighbours[cnt] = puLeft->cu->altLMParaUnit;
+    if (affMrgCtx.xCheckSameAffMotion(pu, cnt))
+    {
+      cnt++;
+    }
+  }
+
+  if (cnt == maxNumMergeCand)
+  {
+    return;
+  }
+
+  // above right
+  const PredictionUnit *puAboveRight = cs.getPURestricted(posRT.offset(1, -1), pu, pu.chType);
+  const bool isAvailableB0 = puAboveRight && isDiffMER(pu.lumaPos(), posRT.offset(1, -1), plevel) && CU::isInter(*puAboveRight->cu);
+  if (isAvailableB0 && puAboveRight->cu->affine && (puAboveRight->mergeType == MRG_TYPE_DEFAULT_N) && PU::isValidAltMergeCandidate(*puAboveRight))
+  {
+    Mv cMv[2][3];
+    affMrgCtx.affineType[cnt] = (EAffineModel)puAboveRight->cu->affineType;
+    pu.cu->affineType = puAboveRight->cu->affineType;
+    if (puAboveRight->interDir != 2)
+    {
+      xInheritedAffineMv(pu, puAboveRight, REF_PIC_LIST_0, cMv[0]);
+    }
+    if (slice.isInterB())
+    {
+      if (puAboveRight->interDir != 1)
+      {
+        xInheritedAffineMv(pu, puAboveRight, REF_PIC_LIST_1, cMv[1]);
+      }
+    }
+    for (int mvNum = 0; mvNum < 3; mvNum++)
+    {
+      affMrgCtx.mvFieldNeighbours[(cnt << 1) + 0][mvNum].setMvField(cMv[0][mvNum], puAboveRight->refIdx[0]);
+      affMrgCtx.mvFieldNeighbours[(cnt << 1) + 1][mvNum].setMvField(cMv[1][mvNum], puAboveRight->refIdx[1]);
+    }
+    affMrgCtx.interDirNeighbours[cnt] = puAboveRight->interDir;
+    affMrgCtx.bcwIdx[cnt] = (affMrgCtx.interDirNeighbours[cnt] == 3) ? puAboveRight->cu->bcwIdx : BCW_DEFAULT;
+#if JVET_AD0193_ADAPTIVE_OBMC_CONTROL
+    affMrgCtx.obmcFlags[cnt] = puAboveRight->cu->obmcFlag;
+#endif
+    affMrgCtx.altLMParaNeighbours[cnt] = puAboveRight->cu->altLMParaUnit;
+    if (affMrgCtx.xCheckSameAffMotion(pu, cnt))
+    {
+      cnt++;
+    }
+  }
+
+  if (cnt == maxNumMergeCand)
+  {
+    return;
+  }
+
+  //left bottom
+  const PredictionUnit *puLeftBottom = cs.getPURestricted(posLB.offset(-1, 1), pu, pu.chType);
+  bool isAvailableA0 = puLeftBottom && isDiffMER(pu.lumaPos(), posLB.offset(-1, 1), plevel) && CU::isInter(*puLeftBottom->cu);
+  if (isAvailableA0 && puLeftBottom->cu->affine && (puLeftBottom->mergeType == MRG_TYPE_DEFAULT_N) && PU::isValidAltMergeCandidate(*puLeftBottom))
+  {
+    Mv cMv[2][3];
+    affMrgCtx.affineType[cnt] = (EAffineModel)puLeftBottom->cu->affineType;
+    pu.cu->affineType = puLeftBottom->cu->affineType;
+    if (puLeftBottom->interDir != 2)
+    {
+      xInheritedAffineMv(pu, puLeftBottom, REF_PIC_LIST_0, cMv[0]);
+    }
+    if (slice.isInterB())
+    {
+      if (puLeftBottom->interDir != 1)
+      {
+        xInheritedAffineMv(pu, puLeftBottom, REF_PIC_LIST_1, cMv[1]);
+      }
+    }
+    for (int mvNum = 0; mvNum < 3; mvNum++)
+    {
+      affMrgCtx.mvFieldNeighbours[(cnt << 1) + 0][mvNum].setMvField(cMv[0][mvNum], puLeftBottom->refIdx[0]);
+      affMrgCtx.mvFieldNeighbours[(cnt << 1) + 1][mvNum].setMvField(cMv[1][mvNum], puLeftBottom->refIdx[1]);
+    }
+    affMrgCtx.interDirNeighbours[cnt] = puLeftBottom->interDir;
+    affMrgCtx.bcwIdx[cnt] = (affMrgCtx.interDirNeighbours[cnt] == 3) ? puLeftBottom->cu->bcwIdx : BCW_DEFAULT;
+#if JVET_AD0193_ADAPTIVE_OBMC_CONTROL
+    affMrgCtx.obmcFlags[cnt] = puLeftBottom->cu->obmcFlag;
+#endif
+    affMrgCtx.altLMParaNeighbours[cnt] = puLeftBottom->cu->altLMParaUnit;
+    if (affMrgCtx.xCheckSameAffMotion(pu, cnt))
+    {
+      cnt++;
+    }
+  }
+
+  if (cnt == maxNumMergeCand)
+  {
+    return;
+  }
+
+  // above left
+  const PredictionUnit *puAboveLeft = cs.getPURestricted(posLT.offset(-1, -1), pu, pu.chType);
+  bool  isAvailableB2 = puAboveLeft && isDiffMER(pu.lumaPos(), posLT.offset(-1, -1), plevel) && CU::isInter(*puAboveLeft->cu);
+  if (isAvailableB2 && puAboveLeft->cu->affine && (puAboveLeft->mergeType == MRG_TYPE_DEFAULT_N) && PU::isValidAltMergeCandidate(*puAboveLeft))
+  {
+    Mv cMv[2][3];
+    affMrgCtx.affineType[cnt] = (EAffineModel)puAboveLeft->cu->affineType;
+    pu.cu->affineType = puAboveLeft->cu->affineType;
+    if (puAboveLeft->interDir != 2)
+    {
+      xInheritedAffineMv(pu, puAboveLeft, REF_PIC_LIST_0, cMv[0]);
+    }
+    if (slice.isInterB())
+    {
+      if (puAboveLeft->interDir != 1)
+      {
+        xInheritedAffineMv(pu, puAboveLeft, REF_PIC_LIST_1, cMv[1]);
+      }
+    }
+    for (int mvNum = 0; mvNum < 3; mvNum++)
+    {
+      affMrgCtx.mvFieldNeighbours[(cnt << 1) + 0][mvNum].setMvField(cMv[0][mvNum], puAboveLeft->refIdx[0]);
+      affMrgCtx.mvFieldNeighbours[(cnt << 1) + 1][mvNum].setMvField(cMv[1][mvNum], puAboveLeft->refIdx[1]);
+    }
+    affMrgCtx.interDirNeighbours[cnt] = puAboveLeft->interDir;
+    affMrgCtx.bcwIdx[cnt] = (affMrgCtx.interDirNeighbours[cnt] == 3) ? puAboveLeft->cu->bcwIdx : BCW_DEFAULT;
+#if JVET_AD0193_ADAPTIVE_OBMC_CONTROL
+    affMrgCtx.obmcFlags[cnt] = puAboveLeft->cu->obmcFlag;
+#endif
+    affMrgCtx.altLMParaNeighbours[cnt] = puAboveLeft->cu->altLMParaUnit;
+    if (affMrgCtx.xCheckSameAffMotion(pu, cnt))
+    {
+      cnt++;
+    }
+  }
+
+  if (cnt == maxNumMergeCand)
+  {
+    return;
+  }
+
+  int offsetX = 0;
+  int offsetY = 0;
+  int offsetX0 = 0; int offsetX1 = 0; int offsetX2 = pu.Y().width >> 1;
+  int offsetY0 = 0; int offsetY1 = 0; int offsetY2 = pu.Y().height >> 1;
+
+  const int numNACandidate[7] = { 5, 9, 9, 9, 9, 9, 9 };
+  const int idxMap[7][9] = { { 0, 1, 2, 3, 4 },{ 0, 1, 2, 3, 4, 5, 6, 7, 8 },{ 0, 1, 2, 3, 4, 5, 6, 7, 8 },{ 0, 1, 2, 3, 4, 5, 6, 7, 8 },{ 0, 1, 2, 3, 4, 5, 6, 7, 8 },{ 0, 1, 2, 3, 4, 5, 6, 7, 8 },{ 0, 1, 2, 3, 4, 5, 6, 7, 8 } };
+
+  for (int iDistanceIndex = 0; iDistanceIndex < 7 && cnt < maxNumMergeCand; iDistanceIndex++)
+  {
+    const int iNADistanceHor = pu.Y().width  * (iDistanceIndex + 1);
+    const int iNADistanceVer = pu.Y().height * (iDistanceIndex + 1);
+
+    for (int iNASPIdx = 0; iNASPIdx < numNACandidate[iDistanceIndex] && cnt < maxNumMergeCand; iNASPIdx++)
+    {
+      switch (idxMap[iDistanceIndex][iNASPIdx])
+      {
+      case 0:offsetX = offsetX0 = -iNADistanceHor - 1;               offsetY = offsetY0 = pu.Y().height + iNADistanceVer - 1; break;
+      case 1:offsetX = offsetX1 = pu.Y().width + iNADistanceHor - 1; offsetY = offsetY1 = -iNADistanceVer - 1;                break;
+      case 2:offsetX = offsetX2;                                     offsetY = offsetY1;                                      break;
+      case 3:offsetX = offsetX0;                                     offsetY = offsetY2;                                      break;
+      case 4:offsetX = offsetX0;                                     offsetY = offsetY1;                                      break;
+      case 5:offsetX = -1;                                           offsetY = offsetY0;                                      break;
+      case 6:offsetX = offsetX1;                                     offsetY = -1;                                            break;
+      case 7:offsetX = offsetX0 >> 1;                                offsetY = offsetY0;                                      break;
+      case 8:offsetX = offsetX1;                                     offsetY = offsetY1 >> 1;                                 break;
+      default: printf("error!"); exit(0); break;
+      }
+
+      const PredictionUnit *puNonAdjacent = cs.getPURestricted(posLT.offset(offsetX, offsetY), pu, pu.chType);
+
+      bool isAvailableNonAdjacent = puNonAdjacent && isDiffMER(pu.lumaPos(), posLT.offset(offsetX, offsetY), plevel) && CU::isInter(*puNonAdjacent->cu);
+      if (isAvailableNonAdjacent && puNonAdjacent->cu->affine && (puNonAdjacent->mergeType == MRG_TYPE_DEFAULT_N) && PU::isValidAltMergeCandidate(*puNonAdjacent))
+      {
+        Mv cMv[2][3];
+        affMrgCtx.affineType[cnt] = (EAffineModel)puNonAdjacent->cu->affineType;
+        pu.cu->affineType = puNonAdjacent->cu->affineType;
+        if (puNonAdjacent->interDir != 2)
+        {
+          xInheritedAffineMv(pu, puNonAdjacent, REF_PIC_LIST_0, cMv[0]);
+        }
+        if (slice.isInterB())
+        {
+          if (puNonAdjacent->interDir != 1)
+          {
+            xInheritedAffineMv(pu, puNonAdjacent, REF_PIC_LIST_1, cMv[1]);
+          }
+        }
+        for (int mvNum = 0; mvNum < 3; mvNum++)
+        {
+          affMrgCtx.mvFieldNeighbours[(cnt << 1) + 0][mvNum].setMvField(cMv[0][mvNum], puNonAdjacent->refIdx[0]);
+          affMrgCtx.mvFieldNeighbours[(cnt << 1) + 1][mvNum].setMvField(cMv[1][mvNum], puNonAdjacent->refIdx[1]);
+        }
+        affMrgCtx.interDirNeighbours[cnt] = puNonAdjacent->interDir;
+        affMrgCtx.bcwIdx[cnt] = (affMrgCtx.interDirNeighbours[cnt] == 3) ? puNonAdjacent->cu->bcwIdx : BCW_DEFAULT;
+#if JVET_AD0193_ADAPTIVE_OBMC_CONTROL
+        affMrgCtx.obmcFlags[cnt] = puNonAdjacent->cu->obmcFlag;
+#endif
+        affMrgCtx.altLMParaNeighbours[cnt] = puNonAdjacent->cu->altLMParaUnit;
+        if (affMrgCtx.xCheckSameAffMotion(pu, cnt))
+        {
+          cnt++;
+        }
+      }
+    }
+  }
+
+  const int numNACandidate2[7] = { 4, 4, 4, 4, 4, 4, 4 };
+  const int idxMap2[7][5] = { { 0, 1, 2, 3 },{ 0, 1, 2, 3 },{ 0, 1, 2, 3 },{ 0, 1, 2, 3 },{ 0, 1, 2, 3 },{ 0, 1, 2, 3 },{ 0, 1, 2, 3 } };
+
+  for (int iDistanceIndex = 0; iDistanceIndex < 7 && cnt < maxNumMergeCand; iDistanceIndex++)
+  {
+    const int iNADistanceHor = pu.Y().width  * (iDistanceIndex + 1);
+    const int iNADistanceVer = pu.Y().height * (iDistanceIndex + 1);
+
+    for (int iNASPIdx = 0; iNASPIdx < numNACandidate2[iDistanceIndex] && cnt < maxNumMergeCand; iNASPIdx++)
+    {
+      switch (idxMap2[iDistanceIndex][iNASPIdx])
+      {
+      case 0:offsetX = offsetX0 = -iNADistanceHor - 1;                                                         offsetY = offsetY2 + ((pu.Y().height + iNADistanceVer - 1 - offsetY2) >> 1); break;
+      case 1:offsetX = offsetX2 + ((pu.Y().width + iNADistanceHor - 1 - offsetX2) >> 1);                       offsetY = offsetY0 = -iNADistanceVer - 1; break;
+      case 2:offsetX = offsetX0;                                                                               offsetY = offsetY0 + ((offsetY2 - offsetY0) >> 1); break;
+      case 3:offsetX = offsetX0 + ((offsetX2 - offsetX0) >> 1);                                                offsetY = offsetY0; break;
+      default: printf("error!"); exit(0); break;
+      }
+
+      const PredictionUnit *puNonAdjacent = cs.getPURestricted(posLT.offset(offsetX, offsetY), pu, pu.chType);
+
+      bool isAvailableNonAdjacent = puNonAdjacent && isDiffMER(pu.lumaPos(), posLT.offset(offsetX, offsetY), plevel) && CU::isInter(*puNonAdjacent->cu);
+      if (isAvailableNonAdjacent && puNonAdjacent->cu->affine && (puNonAdjacent->mergeType == MRG_TYPE_DEFAULT_N) && PU::isValidAltMergeCandidate(*puNonAdjacent))
+      {
+        Mv cMv[2][3];
+        affMrgCtx.affineType[cnt] = (EAffineModel)puNonAdjacent->cu->affineType;
+        pu.cu->affineType = puNonAdjacent->cu->affineType;
+        if (puNonAdjacent->interDir != 2)
+        {
+          xInheritedAffineMv(pu, puNonAdjacent, REF_PIC_LIST_0, cMv[0]);
+        }
+        if (slice.isInterB())
+        {
+          if (puNonAdjacent->interDir != 1)
+          {
+            xInheritedAffineMv(pu, puNonAdjacent, REF_PIC_LIST_1, cMv[1]);
+          }
+        }
+        for (int mvNum = 0; mvNum < 3; mvNum++)
+        {
+          affMrgCtx.mvFieldNeighbours[(cnt << 1) + 0][mvNum].setMvField(cMv[0][mvNum], puNonAdjacent->refIdx[0]);
+          affMrgCtx.mvFieldNeighbours[(cnt << 1) + 1][mvNum].setMvField(cMv[1][mvNum], puNonAdjacent->refIdx[1]);
+        }
+        affMrgCtx.interDirNeighbours[cnt] = puNonAdjacent->interDir;
+        affMrgCtx.bcwIdx[cnt] = (affMrgCtx.interDirNeighbours[cnt] == 3) ? puNonAdjacent->cu->bcwIdx : BCW_DEFAULT;
+#if JVET_AD0193_ADAPTIVE_OBMC_CONTROL
+        affMrgCtx.obmcFlags[cnt] = puNonAdjacent->cu->obmcFlag;
+#endif
+        affMrgCtx.altLMParaNeighbours[cnt] = puNonAdjacent->cu->altLMParaUnit;
+        if (affMrgCtx.xCheckSameAffMotion(pu, cnt))
+        {
+          cnt++;
+        }
+      }
+    }
+  }
+
+  affMrgCtx.numValidMergeCand = cnt;
+  return;
+}
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+void PU::getAltLMBRAffineMergeCand(const PredictionUnit &pu, AltLMAffineMergeCtx& affMrgCtx)
+{
+  const uint32_t         maxNumMergeCand = ALT_AFF_MRG_MAX_NUM_CANDS;
+  const unsigned         plevel = pu.cs->sps->getLog2ParallelMergeLevelMinus2() + 2;
+  const CodingStructure& cs = *pu.cs;
+  const Slice&           slice = *pu.cs->slice;
+
+  for (int i = 0; i < maxNumMergeCand; i++)
+  {
+    affMrgCtx.initAltLMAffMergeCtx(i);
+  }
+
+  int cnt = 0;
+
+  const Position posLT = pu.Y().topLeft();
+  const Position posRT = pu.Y().topRight();
+  const Position posLB = pu.Y().bottomLeft();
+
+  const PredictionUnit *puAbove = cs.getPURestricted(posRT.offset(0, -1), pu, pu.chType);
+  bool isAvailableB1 = puAbove && isDiffMER(pu.lumaPos(), posRT.offset(0, -1), plevel) && CU::isInter(*puAbove->cu);
+  if (isAvailableB1 && puAbove->cu->affine && (puAbove->mergeType == MRG_TYPE_DEFAULT_N) && PU::isValidAltMergeCandidate(*puAbove, true))
+  {
+    Mv cMv[2][3];
+    affMrgCtx.affineType[cnt] = (EAffineModel)puAbove->cu->affineType;
+    pu.cu->affineType = puAbove->cu->affineType;
+    if (puAbove->interDir != 2)
+    {
+      xInheritedAffineMv(pu, puAbove, REF_PIC_LIST_0, cMv[0]);
+    }
+    if (slice.isInterB())
+    {
+      if (puAbove->interDir != 1)
+      {
+        xInheritedAffineMv(pu, puAbove, REF_PIC_LIST_1, cMv[1]);
+      }
+    }
+    for (int mvNum = 0; mvNum < 3; mvNum++)
+    {
+      affMrgCtx.mvFieldNeighbours[(cnt << 1) + 0][mvNum].setMvField(cMv[0][mvNum], puAbove->refIdx[0]);
+      affMrgCtx.mvFieldNeighbours[(cnt << 1) + 1][mvNum].setMvField(cMv[1][mvNum], puAbove->refIdx[1]);
+    }
+    affMrgCtx.interDirNeighbours[cnt] = puAbove->interDir;
+    affMrgCtx.bcwIdx[cnt] = (affMrgCtx.interDirNeighbours[cnt] == 3) ? puAbove->cu->bcwIdx : BCW_DEFAULT;
+#if JVET_AD0193_ADAPTIVE_OBMC_CONTROL
+    affMrgCtx.obmcFlags[cnt] = puAbove->cu->obmcFlag;
+#endif
+    affMrgCtx.altLMParaNeighbours[cnt] = puAbove->cu->altLMBRParaUnit;
+    if (affMrgCtx.xCheckSameAffMotion(pu, cnt))
+    {
+      cnt++;
+    }
+  }
+
+  if (cnt == maxNumMergeCand)
+  {
+    return;
+  }
+
+  const PredictionUnit* puLeft = cs.getPURestricted(posLB.offset(-1, 0), pu, pu.chType);
+  const bool isAvailableA1 = puLeft && isDiffMER(pu.lumaPos(), posLB.offset(-1, 0), plevel) && CU::isInter(*puLeft->cu);
+  if (isAvailableA1 && puLeft->cu->affine && (puLeft->mergeType == MRG_TYPE_DEFAULT_N) && PU::isValidAltMergeCandidate(*puLeft, true))
+  {
+    Mv cMv[2][3];
+    affMrgCtx.affineType[cnt] = (EAffineModel)puLeft->cu->affineType;
+    pu.cu->affineType = puLeft->cu->affineType;
+    if (puLeft->interDir != 2)
+    {
+      xInheritedAffineMv(pu, puLeft, REF_PIC_LIST_0, cMv[0]);
+    }
+    if (slice.isInterB())
+    {
+      if (puLeft->interDir != 1)
+      {
+        xInheritedAffineMv(pu, puLeft, REF_PIC_LIST_1, cMv[1]);
+      }
+    }
+    for (int mvNum = 0; mvNum < 3; mvNum++)
+    {
+      affMrgCtx.mvFieldNeighbours[(cnt << 1) + 0][mvNum].setMvField(cMv[0][mvNum], puLeft->refIdx[0]);
+      affMrgCtx.mvFieldNeighbours[(cnt << 1) + 1][mvNum].setMvField(cMv[1][mvNum], puLeft->refIdx[1]);
+    }
+    affMrgCtx.interDirNeighbours[cnt] = puLeft->interDir;
+    affMrgCtx.bcwIdx[cnt] = (affMrgCtx.interDirNeighbours[cnt] == 3) ? puLeft->cu->bcwIdx : BCW_DEFAULT;
+#if JVET_AD0193_ADAPTIVE_OBMC_CONTROL
+    affMrgCtx.obmcFlags[cnt] = puLeft->cu->obmcFlag;
+#endif
+    affMrgCtx.altLMParaNeighbours[cnt] = puLeft->cu->altLMBRParaUnit;
+    if (affMrgCtx.xCheckSameAffMotion(pu, cnt))
+    {
+      cnt++;
+    }
+  }
+
+  if (cnt == maxNumMergeCand)
+  {
+    return;
+  }
+
+  const PredictionUnit *puAboveRight = cs.getPURestricted(posRT.offset(1, -1), pu, pu.chType);
+  const bool isAvailableB0 = puAboveRight && isDiffMER(pu.lumaPos(), posRT.offset(1, -1), plevel) && CU::isInter(*puAboveRight->cu);
+  if (isAvailableB0 && puAboveRight->cu->affine && (puAboveRight->mergeType == MRG_TYPE_DEFAULT_N) && PU::isValidAltMergeCandidate(*puAboveRight, true))
+  {
+    Mv cMv[2][3];
+    affMrgCtx.affineType[cnt] = (EAffineModel)puAboveRight->cu->affineType;
+    pu.cu->affineType = puAboveRight->cu->affineType;
+    if (puAboveRight->interDir != 2)
+    {
+      xInheritedAffineMv(pu, puAboveRight, REF_PIC_LIST_0, cMv[0]);
+    }
+    if (slice.isInterB())
+    {
+      if (puAboveRight->interDir != 1)
+      {
+        xInheritedAffineMv(pu, puAboveRight, REF_PIC_LIST_1, cMv[1]);
+      }
+    }
+    for (int mvNum = 0; mvNum < 3; mvNum++)
+    {
+      affMrgCtx.mvFieldNeighbours[(cnt << 1) + 0][mvNum].setMvField(cMv[0][mvNum], puAboveRight->refIdx[0]);
+      affMrgCtx.mvFieldNeighbours[(cnt << 1) + 1][mvNum].setMvField(cMv[1][mvNum], puAboveRight->refIdx[1]);
+    }
+    affMrgCtx.interDirNeighbours[cnt] = puAboveRight->interDir;
+    affMrgCtx.bcwIdx[cnt] = (affMrgCtx.interDirNeighbours[cnt] == 3) ? puAboveRight->cu->bcwIdx : BCW_DEFAULT;
+#if JVET_AD0193_ADAPTIVE_OBMC_CONTROL
+    affMrgCtx.obmcFlags[cnt] = puAboveRight->cu->obmcFlag;
+#endif
+    affMrgCtx.altLMParaNeighbours[cnt] = puAboveRight->cu->altLMBRParaUnit;
+    if (affMrgCtx.xCheckSameAffMotion(pu, cnt))
+    {
+      cnt++;
+    }
+  }
+
+  if (cnt == maxNumMergeCand)
+  {
+    return;
+  }
+
+  const PredictionUnit *puLeftBottom = cs.getPURestricted(posLB.offset(-1, 1), pu, pu.chType);
+  bool isAvailableA0 = puLeftBottom && isDiffMER(pu.lumaPos(), posLB.offset(-1, 1), plevel) && CU::isInter(*puLeftBottom->cu);
+  if (isAvailableA0 && puLeftBottom->cu->affine && (puLeftBottom->mergeType == MRG_TYPE_DEFAULT_N) && PU::isValidAltMergeCandidate(*puLeftBottom, true))
+  {
+    Mv cMv[2][3];
+    affMrgCtx.affineType[cnt] = (EAffineModel)puLeftBottom->cu->affineType;
+    pu.cu->affineType = puLeftBottom->cu->affineType;
+    if (puLeftBottom->interDir != 2)
+    {
+      xInheritedAffineMv(pu, puLeftBottom, REF_PIC_LIST_0, cMv[0]);
+    }
+    if (slice.isInterB())
+    {
+      if (puLeftBottom->interDir != 1)
+      {
+        xInheritedAffineMv(pu, puLeftBottom, REF_PIC_LIST_1, cMv[1]);
+      }
+    }
+    for (int mvNum = 0; mvNum < 3; mvNum++)
+    {
+      affMrgCtx.mvFieldNeighbours[(cnt << 1) + 0][mvNum].setMvField(cMv[0][mvNum], puLeftBottom->refIdx[0]);
+      affMrgCtx.mvFieldNeighbours[(cnt << 1) + 1][mvNum].setMvField(cMv[1][mvNum], puLeftBottom->refIdx[1]);
+    }
+    affMrgCtx.interDirNeighbours[cnt] = puLeftBottom->interDir;
+    affMrgCtx.bcwIdx[cnt] = (affMrgCtx.interDirNeighbours[cnt] == 3) ? puLeftBottom->cu->bcwIdx : BCW_DEFAULT;
+#if JVET_AD0193_ADAPTIVE_OBMC_CONTROL
+    affMrgCtx.obmcFlags[cnt] = puLeftBottom->cu->obmcFlag;
+#endif
+    affMrgCtx.altLMParaNeighbours[cnt] = puLeftBottom->cu->altLMBRParaUnit;
+    if (affMrgCtx.xCheckSameAffMotion(pu, cnt))
+    {
+      cnt++;
+    }
+  }
+
+  if (cnt == maxNumMergeCand)
+  {
+    return;
+  }
+
+  const PredictionUnit *puAboveLeft = cs.getPURestricted(posLT.offset(-1, -1), pu, pu.chType);
+  bool  isAvailableB2 = puAboveLeft && isDiffMER(pu.lumaPos(), posLT.offset(-1, -1), plevel) && CU::isInter(*puAboveLeft->cu);
+  if (isAvailableB2 && puAboveLeft->cu->affine && (puAboveLeft->mergeType == MRG_TYPE_DEFAULT_N) && PU::isValidAltMergeCandidate(*puAboveLeft, true))
+  {
+    Mv cMv[2][3];
+    affMrgCtx.affineType[cnt] = (EAffineModel)puAboveLeft->cu->affineType;
+    pu.cu->affineType = puAboveLeft->cu->affineType;
+    if (puAboveLeft->interDir != 2)
+    {
+      xInheritedAffineMv(pu, puAboveLeft, REF_PIC_LIST_0, cMv[0]);
+    }
+    if (slice.isInterB())
+    {
+      if (puAboveLeft->interDir != 1)
+      {
+        xInheritedAffineMv(pu, puAboveLeft, REF_PIC_LIST_1, cMv[1]);
+      }
+    }
+    for (int mvNum = 0; mvNum < 3; mvNum++)
+    {
+      affMrgCtx.mvFieldNeighbours[(cnt << 1) + 0][mvNum].setMvField(cMv[0][mvNum], puAboveLeft->refIdx[0]);
+      affMrgCtx.mvFieldNeighbours[(cnt << 1) + 1][mvNum].setMvField(cMv[1][mvNum], puAboveLeft->refIdx[1]);
+    }
+    affMrgCtx.interDirNeighbours[cnt] = puAboveLeft->interDir;
+    affMrgCtx.bcwIdx[cnt] = (affMrgCtx.interDirNeighbours[cnt] == 3) ? puAboveLeft->cu->bcwIdx : BCW_DEFAULT;
+#if JVET_AD0193_ADAPTIVE_OBMC_CONTROL
+    affMrgCtx.obmcFlags[cnt] = puAboveLeft->cu->obmcFlag;
+#endif
+    affMrgCtx.altLMParaNeighbours[cnt] = puAboveLeft->cu->altLMBRParaUnit;
+    if (affMrgCtx.xCheckSameAffMotion(pu, cnt))
+    {
+      cnt++;
+    }
+  }
+
+  if (cnt == maxNumMergeCand)
+  {
+    return;
+  }
+
+  int offsetX = 0;
+  int offsetY = 0;
+  int offsetX0 = 0; int offsetX1 = 0; int offsetX2 = pu.Y().width >> 1;
+  int offsetY0 = 0; int offsetY1 = 0; int offsetY2 = pu.Y().height >> 1;
+
+  const int numNACandidate[7] = { 5, 9, 9, 9, 9, 9, 9 };
+  const int idxMap[7][9] = { { 0, 1, 2, 3, 4 },{ 0, 1, 2, 3, 4, 5, 6, 7, 8 },{ 0, 1, 2, 3, 4, 5, 6, 7, 8 },{ 0, 1, 2, 3, 4, 5, 6, 7, 8 },{ 0, 1, 2, 3, 4, 5, 6, 7, 8 },{ 0, 1, 2, 3, 4, 5, 6, 7, 8 },{ 0, 1, 2, 3, 4, 5, 6, 7, 8 } };
+
+  for (int iDistanceIndex = 0; iDistanceIndex < 7 && cnt < maxNumMergeCand; iDistanceIndex++)
+  {
+    const int iNADistanceHor = pu.Y().width  * (iDistanceIndex + 1);
+    const int iNADistanceVer = pu.Y().height * (iDistanceIndex + 1);
+
+    for (int iNASPIdx = 0; iNASPIdx < numNACandidate[iDistanceIndex] && cnt < maxNumMergeCand; iNASPIdx++)
+    {
+      switch (idxMap[iDistanceIndex][iNASPIdx])
+      {
+        case 0:offsetX = offsetX0 = -iNADistanceHor - 1;               offsetY = offsetY0 = pu.Y().height + iNADistanceVer - 1; break;
+        case 1:offsetX = offsetX1 = pu.Y().width + iNADistanceHor - 1; offsetY = offsetY1 = -iNADistanceVer - 1;                break;
+        case 2:offsetX = offsetX2;                                     offsetY = offsetY1;                                      break;
+        case 3:offsetX = offsetX0;                                     offsetY = offsetY2;                                      break;
+        case 4:offsetX = offsetX0;                                     offsetY = offsetY1;                                      break;
+        case 5:offsetX = -1;                                           offsetY = offsetY0;                                      break;
+        case 6:offsetX = offsetX1;                                     offsetY = -1;                                            break;
+        case 7:offsetX = offsetX0 >> 1;                                offsetY = offsetY0;                                      break;
+        case 8:offsetX = offsetX1;                                     offsetY = offsetY1 >> 1;                                 break;
+        default: printf("error!"); exit(0); break;
+      }
+
+      const PredictionUnit *puNonAdjacent = cs.getPURestricted(posLT.offset(offsetX, offsetY), pu, pu.chType);
+
       bool isAvailableNonAdjacent = puNonAdjacent && isDiffMER(pu.lumaPos(), posLT.offset(offsetX, offsetY), plevel) && CU::isInter(*puNonAdjacent->cu);
-#endif
-
-      if (isAvailableNonAdjacent)
+      if (isAvailableNonAdjacent && puNonAdjacent->cu->affine && (puNonAdjacent->mergeType == MRG_TYPE_DEFAULT_N) && PU::isValidAltMergeCandidate(*puNonAdjacent, true))
       {
-        miNeighbor = puNonAdjacent->getMotionInfo(posLT.offset(offsetX, offsetY));
-
-        // get Inter Dir
-        mrgCtx.interDirNeighbours[cnt] = miNeighbor.interDir;
-        // get Mv from Above-Left
-        mrgCtx.mvFieldNeighbours[cnt << 1].setMvField(miNeighbor.mv[0], miNeighbor.refIdx[0]);
-        mrgCtx.useAltHpelIf[cnt] = miNeighbor.useAltHpelIf;
-        // get Mv from Above-right
-        mrgCtx.bcwIdx[cnt] = (mrgCtx.interDirNeighbours[cnt] == 3) ? puNonAdjacent->cu->bcwIdx : BCW_DEFAULT;
-#if INTER_LIC
-        mrgCtx.licFlags[cnt] = miNeighbor.usesLIC;
-#endif
-        if (slice.isInterB())
+        Mv cMv[2][3];
+        affMrgCtx.affineType[cnt] = (EAffineModel)puNonAdjacent->cu->affineType;
+        pu.cu->affineType = puNonAdjacent->cu->affineType;
+        if (puNonAdjacent->interDir != 2)
         {
-          mrgCtx.mvFieldNeighbours[(cnt << 1) + 1].setMvField(miNeighbor.mv[1], miNeighbor.refIdx[1]);
-#if MULTI_HYP_PRED
-          mrgCtx.addHypNeighbours[cnt] = puNonAdjacent->addHypData;
-#endif
+          xInheritedAffineMv(pu, puNonAdjacent, REF_PIC_LIST_0, cMv[0]);
         }
-
-#if NON_ADJACENT_MRG_CAND || TM_MRG
-        if (!mrgCtx.xCheckSimilarMotion(cnt
-#if TM_MRG
-          , mvdSimilarityThresh
-#endif
-        ))
-#endif
+        if (slice.isInterB())
         {
-          cnt++;
+          if (puNonAdjacent->interDir != 1)
+          {
+            xInheritedAffineMv(pu, puNonAdjacent, REF_PIC_LIST_1, cMv[1]);
+          }
         }
-#if JVET_AD0213_LIC_IMP
-        else
+        for (int mvNum = 0; mvNum < 3; mvNum++)
         {
-          mrgCtx.initMrgCand(cnt);
+          affMrgCtx.mvFieldNeighbours[(cnt << 1) + 0][mvNum].setMvField(cMv[0][mvNum], puNonAdjacent->refIdx[0]);
+          affMrgCtx.mvFieldNeighbours[(cnt << 1) + 1][mvNum].setMvField(cMv[1][mvNum], puNonAdjacent->refIdx[1]);
         }
+        affMrgCtx.interDirNeighbours[cnt] = puNonAdjacent->interDir;
+        affMrgCtx.bcwIdx[cnt] = (affMrgCtx.interDirNeighbours[cnt] == 3) ? puNonAdjacent->cu->bcwIdx : BCW_DEFAULT;
+#if JVET_AD0193_ADAPTIVE_OBMC_CONTROL
+        affMrgCtx.obmcFlags[cnt] = puNonAdjacent->cu->obmcFlag;
 #endif
+        affMrgCtx.altLMParaNeighbours[cnt] = puNonAdjacent->cu->altLMBRParaUnit;
+        if (affMrgCtx.xCheckSameAffMotion(pu, cnt))
+        {
+          cnt++;
+        }
       }
-
     }
   }
 
@@ -13154,66 +14820,56 @@ void PU::getNonAdjacentMergeCand(const PredictionUnit &pu, MergeCtx& mrgCtx)
     {
       switch (idxMap2[iDistanceIndex][iNASPIdx])
       {
-      case 0:offsetX = offsetX0 = -iNADistanceHor - 1;                                                         offsetY = offsetY2 + ((pu.Y().height + iNADistanceVer - 1 - offsetY2) >> 1); break;
-      case 1:offsetX = offsetX2 + ((pu.Y().width + iNADistanceHor - 1 - offsetX2) >> 1);                       offsetY = offsetY0 = -iNADistanceVer - 1; break;
-      case 2:offsetX = offsetX0;                                                                               offsetY = offsetY0 + ((offsetY2 - offsetY0) >> 1); break;
-      case 3:offsetX = offsetX0 + ((offsetX2 - offsetX0) >> 1);                                                offsetY = offsetY0; break;
-      default: printf("error!"); exit(0); break;
+        case 0:offsetX = offsetX0 = -iNADistanceHor - 1;                                                         offsetY = offsetY2 + ((pu.Y().height + iNADistanceVer - 1 - offsetY2) >> 1); break;
+        case 1:offsetX = offsetX2 + ((pu.Y().width + iNADistanceHor - 1 - offsetX2) >> 1);                       offsetY = offsetY0 = -iNADistanceVer - 1; break;
+        case 2:offsetX = offsetX0;                                                                               offsetY = offsetY0 + ((offsetY2 - offsetY0) >> 1); break;
+        case 3:offsetX = offsetX0 + ((offsetX2 - offsetX0) >> 1);                                                offsetY = offsetY0; break;
+        default: printf("error!"); exit(0); break;
       }
 
       const PredictionUnit *puNonAdjacent = cs.getPURestricted(posLT.offset(offsetX, offsetY), pu, pu.chType);
 
-#if JVET_Y0065_GPM_INTRA
-      bool isAvailableNonAdjacent = puNonAdjacent && isDiffMER(pu.lumaPos(), posLT.offset(offsetX, offsetY), plevel) && CU::isInter(*puNonAdjacent->cu) && puNonAdjacent->getMotionInfo(posLT.offset(offsetX, offsetY)).isInter;
-#else
       bool isAvailableNonAdjacent = puNonAdjacent && isDiffMER(pu.lumaPos(), posLT.offset(offsetX, offsetY), plevel) && CU::isInter(*puNonAdjacent->cu);
-#endif
-
-      if (isAvailableNonAdjacent)
+      if (isAvailableNonAdjacent && puNonAdjacent->cu->affine && (puNonAdjacent->mergeType == MRG_TYPE_DEFAULT_N) && PU::isValidAltMergeCandidate(*puNonAdjacent, true))
       {
-        miNeighbor = puNonAdjacent->getMotionInfo(posLT.offset(offsetX, offsetY));
-
-        // get Inter Dir
-        mrgCtx.interDirNeighbours[cnt] = miNeighbor.interDir;
-        // get Mv from Above-Left
-        mrgCtx.mvFieldNeighbours[cnt << 1].setMvField(miNeighbor.mv[0], miNeighbor.refIdx[0]);
-        mrgCtx.useAltHpelIf[cnt] = miNeighbor.useAltHpelIf;
-        // get Mv from Above-right
-        mrgCtx.bcwIdx[cnt] = (mrgCtx.interDirNeighbours[cnt] == 3) ? puNonAdjacent->cu->bcwIdx : BCW_DEFAULT;
-#if INTER_LIC
-        mrgCtx.licFlags[cnt] = miNeighbor.usesLIC;
-#endif
-        if (slice.isInterB())
+        Mv cMv[2][3];
+        affMrgCtx.affineType[cnt] = (EAffineModel)puNonAdjacent->cu->affineType;
+        pu.cu->affineType = puNonAdjacent->cu->affineType;
+        if (puNonAdjacent->interDir != 2)
         {
-          mrgCtx.mvFieldNeighbours[(cnt << 1) + 1].setMvField(miNeighbor.mv[1], miNeighbor.refIdx[1]);
-#if MULTI_HYP_PRED
-          mrgCtx.addHypNeighbours[cnt] = puNonAdjacent->addHypData;
-#endif
+          xInheritedAffineMv(pu, puNonAdjacent, REF_PIC_LIST_0, cMv[0]);
         }
-
-#if NON_ADJACENT_MRG_CAND || TM_MRG
-        if (!mrgCtx.xCheckSimilarMotion(cnt
-#if TM_MRG
-          , mvdSimilarityThresh
-#endif
-        ))
-#endif
+        if (slice.isInterB())
         {
-          cnt++;
+          if (puNonAdjacent->interDir != 1)
+          {
+            xInheritedAffineMv(pu, puNonAdjacent, REF_PIC_LIST_1, cMv[1]);
+          }
         }
-#if JVET_AD0213_LIC_IMP
-        else
+        for (int mvNum = 0; mvNum < 3; mvNum++)
         {
-          mrgCtx.initMrgCand(cnt);
+          affMrgCtx.mvFieldNeighbours[(cnt << 1) + 0][mvNum].setMvField(cMv[0][mvNum], puNonAdjacent->refIdx[0]);
+          affMrgCtx.mvFieldNeighbours[(cnt << 1) + 1][mvNum].setMvField(cMv[1][mvNum], puNonAdjacent->refIdx[1]);
         }
+        affMrgCtx.interDirNeighbours[cnt] = puNonAdjacent->interDir;
+        affMrgCtx.bcwIdx[cnt] = (affMrgCtx.interDirNeighbours[cnt] == 3) ? puNonAdjacent->cu->bcwIdx : BCW_DEFAULT;
+#if JVET_AD0193_ADAPTIVE_OBMC_CONTROL
+        affMrgCtx.obmcFlags[cnt] = puNonAdjacent->cu->obmcFlag;
 #endif
+        affMrgCtx.altLMParaNeighbours[cnt] = puNonAdjacent->cu->altLMBRParaUnit;
+        if (affMrgCtx.xCheckSameAffMotion(pu, cnt))
+        {
+          cnt++;
+        }
       }
     }
   }
 
-  mrgCtx.numValidMergeCand = cnt;
+  affMrgCtx.numValidMergeCand = cnt;
+  return;
 }
 #endif
+#endif
 
 bool PU::checkDMVRCondition(const PredictionUnit& pu)
 {
@@ -13378,6 +15034,35 @@ bool PU::checkBDMVRCondition(const PredictionUnit& pu)
     const bool ref1IsScaled = refIdx1 < 0 || refIdx1 >= MAX_NUM_REF
       ? false
       : isResamplingPossible && pu.cu->slice->getRefPic( REF_PIC_LIST_1, refIdx1 )->isRefScaled( pu.cs->pps );
+#if JVET_AG0276_LIC_BDOF_BDMVR
+    bool meetBdmvrCondition = ((pu.mergeFlag && pu.mergeType == MRG_TYPE_DEFAULT_N) || (pu.amvpMergeModeFlag[0] || pu.amvpMergeModeFlag[1])) && !pu.ciipFlag && !pu.mmvdMergeFlag
+      && !pu.cu->mmvdSkip
+#if JVET_AG0067_DMVR_EXTENSIONS
+      && (PU::isBiPredFromDifferentDirEqDistPoc( pu ) || (PU::isBiPredFromDifferentDirGenDistPoc( pu ) && !pu.cu->geoFlag))
+#else
+      && PU::isBiPredFromDifferentDirEqDistPoc(pu)
+#endif
+      && !WPScalingParam::isWeighted(wp0) && !WPScalingParam::isWeighted(wp1) && !ref0IsScaled && !ref1IsScaled;
+    if (pu.cu->geoFlag || pu.cu->affine)
+    {
+      meetBdmvrCondition &= (pu.cu->licFlag == false);
+    }
+    if (pu.cu->licFlag == true)
+    {
+      meetBdmvrCondition &= (pu.tmMergeFlag == false);
+    }
+#if JVET_AG0276_NLIC
+    if (pu.cu->altLMFlag)
+    {
+      meetBdmvrCondition = false;
+    }
+#endif
+    return meetBdmvrCondition
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+      && !PU::isOppositeLIC(pu)
+#endif
+      ;
+#else
 #if JVET_AB0112_AFFINE_DMVR
 #if JVET_AD0182_AFFINE_DMVR_PLUS_EXTENSIONS
     return ((pu.mergeFlag && pu.mergeType == MRG_TYPE_DEFAULT_N) || (pu.amvpMergeModeFlag[0] || pu.amvpMergeModeFlag[1])) && !pu.ciipFlag && !pu.mmvdMergeFlag
@@ -13395,19 +15080,79 @@ bool PU::checkBDMVRCondition(const PredictionUnit& pu)
 #else
       && PU::isBiPredFromDifferentDirEqDistPoc( pu )
 #endif
+#if JVET_AG0276_NLIC
+      && !pu.cu->altLMFlag
+#endif
 #if JVET_AD0213_LIC_IMP
       && !pu.cu->licFlag
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+      && !PU::isOppositeLIC(pu)
+#endif
 #endif
 #if !JVET_Y0089_DMVR_BCW
       && ( pu.cu->bcwIdx == BCW_DEFAULT )
 #endif
       && !WPScalingParam::isWeighted( wp0 ) && !WPScalingParam::isWeighted( wp1 ) && !ref0IsScaled && !ref1IsScaled;
+#endif
+  }
+  else
+  {
+    return false;
+  }
+}
+#if JVET_AG0276_LIC_BDOF_BDMVR
+bool PU::checkBDMVRCondition4Aff(const PredictionUnit& pu)
+{
+  if (pu.cs->sps->getUseDMVDMode())
+  {
+    const int refIdx0 = pu.refIdx[REF_PIC_LIST_0];
+    const int refIdx1 = pu.refIdx[REF_PIC_LIST_1];
+
+    const WPScalingParam *wp0 = pu.cu->slice->getWpScaling(REF_PIC_LIST_0, refIdx0);
+    const WPScalingParam *wp1 = pu.cu->slice->getWpScaling(REF_PIC_LIST_1, refIdx1);
+
+    const bool isResamplingPossible = pu.cs->sps->getRprEnabledFlag();
+
+    const bool ref0IsScaled = refIdx0 < 0 || refIdx0 >= MAX_NUM_REF
+      ? false
+      : isResamplingPossible && pu.cu->slice->getRefPic(REF_PIC_LIST_0, refIdx0)->isRefScaled(pu.cs->pps);
+    const bool ref1IsScaled = refIdx1 < 0 || refIdx1 >= MAX_NUM_REF
+      ? false
+      : isResamplingPossible && pu.cu->slice->getRefPic(REF_PIC_LIST_1, refIdx1)->isRefScaled(pu.cs->pps);
+#if JVET_AB0112_AFFINE_DMVR
+#if JVET_AD0182_AFFINE_DMVR_PLUS_EXTENSIONS
+    return ((pu.mergeFlag && pu.mergeType == MRG_TYPE_DEFAULT_N) || (pu.amvpMergeModeFlag[0] || pu.amvpMergeModeFlag[1])) && !pu.ciipFlag && !pu.mmvdMergeFlag
+#else
+    return ((pu.mergeFlag && pu.mergeType == MRG_TYPE_DEFAULT_N && (!pu.cu->affine || !pu.afMmvdFlag)) || (pu.amvpMergeModeFlag[0] || pu.amvpMergeModeFlag[1])) && !pu.ciipFlag && !pu.mmvdMergeFlag
+#endif
+#elif JVET_X0083_BM_AMVP_MERGE_MODE
+    return ((pu.mergeFlag && pu.mergeType == MRG_TYPE_DEFAULT_N) || (pu.amvpMergeModeFlag[0] || pu.amvpMergeModeFlag[1])) && !pu.ciipFlag && !pu.cu->affine && !pu.mmvdMergeFlag
+#else
+    return pu.mergeFlag && pu.mergeType == MRG_TYPE_DEFAULT_N && !pu.ciipFlag && !pu.cu->affine && !pu.mmvdMergeFlag
+#endif
+      && !pu.cu->mmvdSkip
+#if JVET_AG0067_DMVR_EXTENSIONS
+      && (PU::isBiPredFromDifferentDirEqDistPoc(pu) || (PU::isBiPredFromDifferentDirGenDistPoc(pu) && !pu.cu->geoFlag))
+#else
+      && PU::isBiPredFromDifferentDirEqDistPoc(pu)
+#endif
+#if JVET_AG0276_NLIC
+      && !pu.cu->altLMFlag
+#endif
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+      && !PU::isOppositeLIC(pu)
+#endif
+#if !JVET_Y0089_DMVR_BCW
+      && (pu.cu->bcwIdx == BCW_DEFAULT)
+#endif
+      && !WPScalingParam::isWeighted(wp0) && !WPScalingParam::isWeighted(wp1) && !ref0IsScaled && !ref1IsScaled;
   }
   else
   {
     return false;
   }
 }
+#endif
 #if JVET_AG0135_AFFINE_CIIP
 #if JVET_AE0046_BI_GPM
 bool PU::checkBDMVRConditionCIIPAffine(const PredictionUnit& pu, bool disregardGpmFlag)
@@ -13457,9 +15202,13 @@ bool PU::checkBDMVRConditionCIIPAffine(const PredictionUnit& pu)
 #else
       && PU::isBiPredFromDifferentDirEqDistPoc(pu)
 #endif
-#if JVET_AD0213_LIC_IMP
+#if JVET_AD0213_LIC_IMP && !JVET_AG0276_LIC_BDOF_BDMVR
       && !pu.cu->licFlag
 #endif
+#if JVET_AG0276_NLIC
+      && !pu.cu->altLMFlag
+#endif
+
 #if !JVET_Y0089_DMVR_BCW
       && (pu.cu->bcwIdx == BCW_DEFAULT)
 #endif
@@ -15762,7 +17511,11 @@ bool PU::addMergeHMVPCandFromAffModel(const PredictionUnit& pu, MergeCtx& mrgCtx
 #endif
 #if INTER_LIC
 #if JVET_AD0213_LIC_IMP
+#if JVET_AG0276_NLIC
+        , puNei->cu->licFlag || (puNei->cu->altLMFlag && puNei->cu->slice->getUseLIC())
+#else
         , puNei->cu->licFlag
+#endif
 #else
         , mvInfo.interDir != 3 ? puNei->cu->licFlag : false
 #endif
@@ -15834,7 +17587,11 @@ bool PU::addMergeHMVPCandFromAffModel(const PredictionUnit& pu, MergeCtx& mrgCtx
 #endif
 #if INTER_LIC
 #if JVET_AD0213_LIC_IMP
+#if JVET_AG0276_NLIC
+        , puNei->cu->licFlag || (puNei->cu->altLMFlag && puNei->cu->slice->getUseLIC())
+#else
         , puNei->cu->licFlag
+#endif
 #else
         , mvInfo.interDir != 3 ? puNei->cu->licFlag : false
 #endif
@@ -17829,6 +19586,10 @@ void PU::getNonAdjCstMergeCand(const PredictionUnit &pu, AffineMergeCtx &affMrgC
       affMrgCtx.affineType[i]         = AFFINEMODEL_4PARAM;
       affMrgCtx.mergeType[i]          = MRG_TYPE_DEFAULT_N;
       affMrgCtx.bcwIdx[i]             = BCW_DEFAULT;
+#if JVET_AG0276_NLIC
+      affMrgCtx.altLMFlag[i] = false;
+      affMrgCtx.altLMParaNeighbours[i].resetAltLinearModel();
+#endif
 #if INTER_LIC
       affMrgCtx.licFlags[i] = false;
 #endif
@@ -18005,7 +19766,6 @@ const int getAvailableAffineNeighboursForAbovePredictor( const PredictionUnit &p
 
   return num;
 }
-
 void PU::getAffineMergeCand( const PredictionUnit &pu, AffineMergeCtx& affMrgCtx,
 #if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION   
   MergeCtx mrgCtxIn[2],
@@ -18065,6 +19825,10 @@ void PU::getAffineMergeCand( const PredictionUnit &pu, AffineMergeCtx& affMrgCtx
     affMrgCtx.affineType[i] = AFFINEMODEL_4PARAM;
     affMrgCtx.mergeType[i] = MRG_TYPE_DEFAULT_N;
     affMrgCtx.bcwIdx[i] = BCW_DEFAULT;
+#if JVET_AG0276_NLIC
+    affMrgCtx.altLMFlag[i] = false;
+    affMrgCtx.altLMParaNeighbours[i].resetAltLinearModel();
+#endif
 #if INTER_LIC
     affMrgCtx.licFlags[i] = false;
 #endif
@@ -18554,6 +20318,10 @@ void PU::getAffineMergeCand( const PredictionUnit &pu, AffineMergeCtx& affMrgCtx
       affMrgCtxTemp.affineType[i] = AFFINEMODEL_4PARAM;
       affMrgCtxTemp.mergeType[i] = MRG_TYPE_DEFAULT_N;
       affMrgCtxTemp.bcwIdx[i] = BCW_DEFAULT;
+#if JVET_AG0276_NLIC
+      affMrgCtxTemp.altLMFlag[i] = false;
+      affMrgCtxTemp.altLMParaNeighbours[i].resetAltLinearModel();
+#endif
 #if INTER_LIC
       affMrgCtxTemp.licFlags[i] = false;
 #endif
@@ -18599,6 +20367,10 @@ void PU::getAffineMergeCand( const PredictionUnit &pu, AffineMergeCtx& affMrgCtx
         affMrgCtx.affineType[affMrgCtx.numValidMergeCand] = EAffineModel(affMrgCtxTemp.affineType[i]);
         affMrgCtx.mergeType[affMrgCtx.numValidMergeCand] = MRG_TYPE_DEFAULT_N;
         affMrgCtx.bcwIdx[affMrgCtx.numValidMergeCand] = affMrgCtxTemp.bcwIdx[i];
+#if JVET_AG0276_NLIC
+        affMrgCtx.altLMFlag[affMrgCtx.numValidMergeCand] = affMrgCtxTemp.altLMFlag[i];
+        affMrgCtx.altLMParaNeighbours[affMrgCtx.numValidMergeCand] = affMrgCtxTemp.altLMParaNeighbours[i];
+#endif
 #if INTER_LIC
         affMrgCtx.licFlags[affMrgCtx.numValidMergeCand] = affMrgCtxTemp.licFlags[i];
 #endif
@@ -18651,6 +20423,10 @@ void PU::getAffineMergeCand( const PredictionUnit &pu, AffineMergeCtx& affMrgCtx
         affMrgCtx.affineType[affMrgCtx.numValidMergeCand] = EAffineModel(affMrgCtxTemp.affineType[i]);
         affMrgCtx.mergeType[affMrgCtx.numValidMergeCand] = MRG_TYPE_DEFAULT_N;
         affMrgCtx.bcwIdx[affMrgCtx.numValidMergeCand] = affMrgCtxTemp.bcwIdx[i];
+#if JVET_AG0276_NLIC
+        affMrgCtx.altLMFlag[affMrgCtx.numValidMergeCand] = affMrgCtxTemp.altLMFlag[i];
+        affMrgCtx.altLMParaNeighbours[affMrgCtx.numValidMergeCand] = affMrgCtxTemp.altLMParaNeighbours[i];
+#endif
 #if INTER_LIC
         affMrgCtx.licFlags[affMrgCtx.numValidMergeCand] = affMrgCtxTemp.licFlags[i];
 #endif
@@ -19372,6 +21148,10 @@ void PU::getBMAffineMergeCand(const PredictionUnit &pu, AffineMergeCtx& affineBM
     affineBMMergeCtx.affineType[i] = AFFINEMODEL_4PARAM;
     affineBMMergeCtx.mergeType[i] = MRG_TYPE_DEFAULT_N;
     affineBMMergeCtx.bcwIdx[i] = BCW_DEFAULT;
+#if JVET_AG0276_NLIC
+    affineBMMergeCtx.altLMFlag[i] = false;
+    affineBMMergeCtx.altLMParaNeighbours[i].resetAltLinearModel();
+#endif
 #if INTER_LIC
     affineBMMergeCtx.licFlags[i] = false;
 #endif
@@ -19537,6 +21317,10 @@ void PU::getBMAffineMergeCand(const PredictionUnit &pu, AffineMergeCtx& affineBM
         affineBMMergeCtx.affineType[affineBMMergeCtx.numValidMergeCand] = EAffineModel(affineMergeRMVFCtx.affineType[i]);
         affineBMMergeCtx.mergeType[affineBMMergeCtx.numValidMergeCand] = MRG_TYPE_DEFAULT_N;
         affineBMMergeCtx.bcwIdx[affineBMMergeCtx.numValidMergeCand] = affineMergeRMVFCtx.bcwIdx[i];
+#if JVET_AG0276_NLIC
+        affineBMMergeCtx.altLMFlag[affineBMMergeCtx.numValidMergeCand] = affineMergeRMVFCtx.altLMFlag[i];
+        affineBMMergeCtx.altLMParaNeighbours[affineBMMergeCtx.numValidMergeCand] = affineMergeRMVFCtx.altLMParaNeighbours[i];
+#endif
 #if INTER_LIC
         affineBMMergeCtx.licFlags[affineBMMergeCtx.numValidMergeCand] = affineMergeRMVFCtx.licFlags[i];
 #endif
@@ -20244,7 +22028,15 @@ void PU::getBMAffineMergeCand(const PredictionUnit &pu, AffineMergeCtx& affineBM
     affineBMMergeCtx.numValidMergeCand++;
   }
 }
-void PU::getRMVFAffineCand(const PredictionUnit &pu, AffineMergeCtx& affineMergeRMVFCtx, AffineMergeCtx& affineMergeRMVFOriCtx, InterPrediction* m_pcInterSearch, uint16_t &numCand)
+void PU::getRMVFAffineCand(const PredictionUnit &pu, AffineMergeCtx& affineMergeRMVFCtx, AffineMergeCtx& affineMergeRMVFOriCtx, InterPrediction* m_pcInterSearch
+  , uint16_t &numCand
+#if JVET_AG0276_NLIC
+  , AltLMAffineMergeCtx& altAffineMergeRMVFCtx
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+  , AltLMAffineMergeCtx& altBRAffineMergeRMVFCtx
+#endif
+#endif
+)
 {
   const int CHECKED_NEI_NUM = 7;
   const PredictionUnit *npu[CHECKED_NEI_NUM + AFF_MAX_NON_ADJACENT_INHERITED_CANDS + MAX_NUM_AFF_INHERIT_HMVP_CANDS];
@@ -20260,6 +22052,10 @@ void PU::getRMVFAffineCand(const PredictionUnit &pu, AffineMergeCtx& affineMerge
     affMrgCtxTemp.affineType[i] = AFFINEMODEL_4PARAM;
     affMrgCtxTemp.mergeType[i] = MRG_TYPE_DEFAULT_N;
     affMrgCtxTemp.bcwIdx[i] = BCW_DEFAULT;
+#if JVET_AG0276_NLIC
+    affMrgCtxTemp.altLMFlag[i] = false;
+    affMrgCtxTemp.altLMParaNeighbours[i].resetAltLinearModel();
+#endif
 #if INTER_LIC
     affMrgCtxTemp.licFlags[i] = false;
 #endif
@@ -20285,7 +22081,14 @@ void PU::getRMVFAffineCand(const PredictionUnit &pu, AffineMergeCtx& affineMerge
     {
       for (int i = 0; i < numAffNeighExtend2; i++)
       {
-        getRMVFAffineGuideCand(pu, *npu[i], affMrgCtxTemp, mvpInfoVec);
+        getRMVFAffineGuideCand(pu, *npu[i], affMrgCtxTemp, mvpInfoVec, -1
+#if JVET_AG0276_NLIC
+          , &altAffineMergeRMVFCtx
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+          , &altBRAffineMergeRMVFCtx
+#endif
+#endif
+        );
         if (affMrgCtxTemp.numValidMergeCand == affMrgCtxTemp.maxNumMergeCand)
         {
           break;
@@ -20324,7 +22127,14 @@ void PU::getRMVFAffineCand(const PredictionUnit &pu, AffineMergeCtx& affineMerge
 #endif
       for (int i = 0; i < numAffNeighExtend2; i++)
       {
-        getRMVFAffineGuideCand(pu, *npu[i], affMrgCtxTemp, mvpInfoVec, -1);
+        getRMVFAffineGuideCand(pu, *npu[i], affMrgCtxTemp, mvpInfoVec, -1
+#if JVET_AG0276_NLIC
+          , &altAffineMergeRMVFCtx
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+          , &altBRAffineMergeRMVFCtx
+#endif
+#endif
+        );
         if (affMrgCtxTemp.numValidMergeCand == affMrgCtxTemp.maxNumMergeCand)
         {
           break;
@@ -20897,6 +22707,12 @@ void PU::setAffineBdofRefinedMotion(PredictionUnit &pu, Mv* mvBufDecAffineBDOF)
 }
 bool PU::checkDoAffineBdofRefine(const PredictionUnit &pu, InterPrediction *interPred)
 {
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+  if (pu.affineOppositeLic)
+  {
+    return false;
+  }
+#endif
 #if JVET_AG0098_AMVP_WITH_SBTMVP
   if (pu.mergeType == MRG_TYPE_SUBPU_ATMVP || pu.amvpSbTmvpFlag)
 #else
@@ -20909,6 +22725,12 @@ bool PU::checkDoAffineBdofRefine(const PredictionUnit &pu, InterPrediction *inte
   {
     return false;
   }
+#if JVET_AG0276_NLIC && !JVET_AG0276_LIC_BDOF_BDMVR
+  if (pu.cu->altLMFlag)
+  {
+    return false;
+  }
+#endif
   const WPScalingParam *wp0 = pu.cu->slice->getWpScaling( REF_PIC_LIST_0, pu.refIdx[0] );
   const WPScalingParam *wp1 = pu.cu->slice->getWpScaling( REF_PIC_LIST_1, pu.refIdx[1] );
   const bool isResamplingPossible = pu.cs->sps->getRprEnabledFlag();
@@ -21001,6 +22823,10 @@ void PU::getTMVPCandOpt(const PredictionUnit &pu, RefPicList refList, int refIdx
   for (uint32_t ui = 0; ui < pu.cs->sps->getMaxNumMergeCand(); ++ui)
   {
     mrgCtx.bcwIdx[ui] = BCW_DEFAULT;
+#if JVET_AG0276_NLIC
+    mrgCtx.altLMFlag[ui] = false;
+    mrgCtx.altLMParaNeighbours[ui].resetAltLinearModel();
+#endif
 #if INTER_LIC
     mrgCtx.licFlags[ui] = false;
 #endif
@@ -22585,6 +24411,10 @@ void PU::getGeoMergeCandidates( const PredictionUnit &pu, MergeCtx& geoMrgCtx )
     geoMrgCtx.mvFieldNeighbours[(i << 1)].mv = Mv();
     geoMrgCtx.mvFieldNeighbours[(i << 1) + 1].mv = Mv();
     geoMrgCtx.useAltHpelIf[i] = false;
+#if JVET_AG0276_NLIC
+    geoMrgCtx.altLMFlag[i] = false;
+    geoMrgCtx.altLMParaNeighbours[i].resetAltLinearModel();
+#endif
 #if INTER_LIC
     geoMrgCtx.licFlags[i] = false;
 #endif
@@ -22634,6 +24464,10 @@ void PU::getGeoMergeCandidates( const PredictionUnit &pu, MergeCtx& geoMrgCtx )
     {
       geoMrgCtx.useAltHpelIf[i] = false;
       geoMrgCtx.bcwIdx[i] = BCW_DEFAULT;
+#if JVET_AG0276_NLIC
+      geoMrgCtx.altLMFlag[i] = false;
+      geoMrgCtx.altLMParaNeighbours[i].resetAltLinearModel();
+#endif
 #if INTER_LIC
       geoMrgCtx.licFlags[i] = false;
 #endif
@@ -25154,6 +26988,22 @@ unsigned int PU::getSameNeigMotion(PredictionUnit &pu, MotionInfo& mi, Position
         }
       }
     }
+#endif
+#if JVET_AG0276_NLIC
+    if (bIsSimilarMV)
+    {
+      if (tmpPu->cu->altLMFlag != pu.cu->altLMFlag)
+      {
+        bIsSimilarMV = false;
+      }
+      else if (tmpPu->cu->altLMFlag)
+      {
+        if (tmpPu->cu->secAltLMParaUnit.scale[0] != pu.cu->altLMParaUnit.scale[0] || tmpPu->cu->secAltLMParaUnit.offset[0] != pu.cu->altLMParaUnit.offset[0])
+        {
+          bIsSimilarMV = false;
+        }
+      }
+    }
 #endif
     for (unsigned int idx = 1; idx < iMaxLength; idx++)
     {
@@ -25234,6 +27084,22 @@ unsigned int PU::getSameNeigMotion(PredictionUnit &pu, MotionInfo& mi, Position
             }
           }
         }
+#endif
+#if JVET_AG0276_NLIC
+        if (bSameMv)
+        {
+          if (tmpPu1->cu->altLMFlag != tmpPu->cu->altLMFlag)
+          {
+            bSameMv = false;
+          }
+          else if (tmpPu1->cu->altLMFlag)
+          {
+            if (tmpPu1->cu->secAltLMParaUnit.scale[0] != tmpPu->cu->secAltLMParaUnit.scale[0] || tmpPu1->cu->secAltLMParaUnit.offset[0] != tmpPu->cu->secAltLMParaUnit.offset[0])
+            {
+              bSameMv = false;
+            }
+          }
+        }
 #endif
       }
 #if JVET_AD0213_LIC_IMP
@@ -25673,6 +27539,37 @@ void PU::spanLicFlags(PredictionUnit &pu, const bool LICFlag)
     motionInfo += mb.stride;
   }
 }
+
+#if JVET_AG0276_LIC_SLOPE_ADJUST
+bool CU::isLicSlopeAllowed(const CodingUnit& cu)
+{
+  if (!cu.cs->sps->getLicSlopeAdjustEnabledFlag())
+  {
+    return false;
+  }
+  if (!cu.lx() && !cu.ly())
+  {
+    return false;
+  }
+  if (!licSlopeSizeTlCond(cu.lwidth(), cu.lheight(), cu.cs->slice->getTLayer()))
+  {
+    return false;
+  }
+  return true;
+}
+bool CU::licSlopeSizeTlCond(const int bw, const int bh, const int layerId)
+{
+  if (bw*bh > 4096 || bw*bh < 64 || bw >= 128 || bh >= 128 || bw == 4 || bh == 4 || (bw >= 64 && bh >=64))
+  {
+    return false;
+  }
+  if (layerId >= 5)
+  {
+    return false;
+  }
+  return true;
+}
+#endif
 #endif
 
 #if SIGN_PREDICTION
@@ -26767,6 +28664,10 @@ void PU::getGeoAffMergeCandidates(PredictionUnit& pu, AffineMergeCtx& gpmAffMrgC
     gpmAffMrgCtx.affineType[i] = AFFINEMODEL_6PARAM;
     gpmAffMrgCtx.mergeType[i] = MRG_TYPE_DEFAULT_N;
     gpmAffMrgCtx.bcwIdx[i] = BCW_DEFAULT;
+#if JVET_AG0276_NLIC
+    gpmAffMrgCtx.altLMFlag[i] = false;
+    gpmAffMrgCtx.altLMParaNeighbours[i].resetAltLinearModel();
+#endif
 #if INTER_LIC
     gpmAffMrgCtx.licFlags[i] = false;
 #endif
@@ -26794,10 +28695,25 @@ void PU::getGeoAffMergeCandidates(PredictionUnit& pu, AffineMergeCtx& gpmAffMrgC
 #if JVET_AD0182_AFFINE_DMVR_PLUS_EXTENSIONS
     AffineMergeCtx affineRMVFCtx;
     AffineMergeCtx affineRMVFOriCtx;
+
+#if JVET_AG0276_NLIC
+    AltLMAffineMergeCtx altAffineRMVFCtx;
+    altAffineRMVFCtx.init();
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+    AltLMAffineMergeCtx altBRAffineRMVFCtx;
+    altBRAffineRMVFCtx.init();
+#endif
+#endif
     uint16_t addNumRMVF = 0;
-    PU::getRMVFAffineCand(pu, affineRMVFCtx, affineRMVFOriCtx, pcInterPred, addNumRMVF);
+    PU::getRMVFAffineCand(pu, affineRMVFCtx, affineRMVFOriCtx, pcInterPred, addNumRMVF
+#if JVET_AG0276_NLIC
+    , altAffineRMVFCtx
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+    , altBRAffineRMVFCtx
+#endif
+#endif
+    );
 #endif
-
     PU::getAffineMergeCand(pu, tmpMergeCtx
 #if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION  
       , mrgCtxAll
@@ -27163,7 +29079,8 @@ bool getAllowedEipMerge(const CodingUnit& cu, const ComponentID compId)
   return false;
 }
 
-int getAllowedCurEip(const CodingUnit &cu, const ComponentID compId, static_vector<EIPInfo, NUM_DERIVED_EIP>& eipInfoList)
{ 
+int getAllowedCurEip(const CodingUnit &cu, const ComponentID compId, static_vector<EIPInfo, NUM_DERIVED_EIP>& eipInfoList)
+{ 
   const int numOfCombEIP[4][4] = 
   {
     { 3, 3, 3, 2 },
diff --git a/source/Lib/CommonLib/UnitTools.h b/source/Lib/CommonLib/UnitTools.h
index 3ff91519c..739b85154 100644
--- a/source/Lib/CommonLib/UnitTools.h
+++ b/source/Lib/CommonLib/UnitTools.h
@@ -64,6 +64,12 @@ namespace CS
 // CU tools
 namespace CU
 {
+#if JVET_AG0276_NLIC
+  bool isSecLicParaNeeded             (const CodingUnit &cu);
+  bool isPredRefined                  (const CodingUnit &cu);
+  bool isAllowSecLicPara              (const CodingUnit &cu);
+  bool isTLCond                       (const CodingUnit &cu);
+#endif
   bool isIntra                        (const CodingUnit &cu);
   bool isInter                        (const CodingUnit &cu);
   bool isIBC                          (const CodingUnit &cu);
@@ -118,6 +124,10 @@ namespace CU
 #endif
 #if INTER_LIC
   bool isLICFlagPresent               (const CodingUnit& cu);
+#if JVET_AG0276_LIC_SLOPE_ADJUST
+  bool isLicSlopeAllowed              (const CodingUnit& cu);
+  bool licSlopeSizeTlCond             (const int bw, const int bh, const int layerId);
+#endif
 #endif
 #if JVET_AC0130_NSPT
   bool  isNSPTAllowed                 ( const TransformUnit& tu, const ComponentID compID, int width, int height, bool isIntra );
@@ -304,6 +314,16 @@ namespace PU
     , bool enableTh4Gpm = false
 #endif
   );
+#if JVET_AG0276_NLIC
+  void     getAltMergeCandidates    (const PredictionUnit &pu, AltLMMergeCtx& cMrgCtx);
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+  void     getAltBRMergeCandidates  (const PredictionUnit &pu, AltLMMergeCtx& cMrgCtx);
+  bool     isValidAltMergeCandidate (const PredictionUnit &pu, bool isBRCand = false);
+#else
+  bool     isValidAltMergeCandidate (const PredictionUnit &pu);
+#endif
+  uint32_t getAltMergeMvdThreshold  (const PredictionUnit &pu);
+#endif
 #if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM
 #if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION
   void getNonAdjacentMergeCandSubTMVP(const PredictionUnit &pu, MergeCtx& mvpMrgCtx, int col);
@@ -428,7 +448,14 @@ namespace PU
     , const MvpDir &eDir
 #endif
   );
-  void getRMVFAffineGuideCand(const PredictionUnit &pu, const PredictionUnit &abovePU, AffineMergeCtx &affMrgCtx, std::vector<RMVFInfo> mvp[NUM_REF_PIC_LIST_01][MAX_NUM_REF], int mrgCandIdx = -1);
+  void getRMVFAffineGuideCand(const PredictionUnit &pu, const PredictionUnit &abovePU, AffineMergeCtx &affMrgCtx, std::vector<RMVFInfo> mvp[NUM_REF_PIC_LIST_01][MAX_NUM_REF], int mrgCandIdx = -1
+#if JVET_AG0276_NLIC
+    , AltLMAffineMergeCtx* altAffineMergeCtx = NULL
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+    , AltLMAffineMergeCtx* altBRAffineMergeCtx = NULL
+#endif
+#endif
+  );
   Position convertNonAdjAffineBlkPos(const Position &pos, int curCtuX, int curCtuY);
   void collectNeiMotionInfo(std::vector<RMVFInfo> mvpInfoVec[NUM_REF_PIC_LIST_01][MAX_NUM_REF], const PredictionUnit &pu);
 #endif
@@ -603,9 +630,23 @@ namespace PU
                           , bool noSbTMVP = false
 #endif
   );
+#if JVET_AG0276_NLIC
+  void getAltLMAffineMergeCand(const PredictionUnit &pu, AltLMAffineMergeCtx& altLMAffMrgCtx);
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+  void getAltLMBRAffineMergeCand(const PredictionUnit &pu, AltLMAffineMergeCtx& altLMAffMrgCtx);
+#endif
+#endif
 #if JVET_AD0182_AFFINE_DMVR_PLUS_EXTENSIONS
   bool isAffBMMergeFlagCoded(const PredictionUnit& pu);
-  void getRMVFAffineCand(const PredictionUnit &pu, AffineMergeCtx& affineMergeRMVFCtx, AffineMergeCtx& affineMergeRMVFOriCtx, InterPrediction* m_pcInterSearch, uint16_t &numCand);
+  void getRMVFAffineCand(const PredictionUnit &pu, AffineMergeCtx& affineMergeRMVFCtx, AffineMergeCtx& affineMergeRMVFOriCtx, InterPrediction* m_pcInterSearch
+  , uint16_t &numCand
+#if JVET_AG0276_NLIC
+    , AltLMAffineMergeCtx& altAffineMergeRMVFCtx
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+    , AltLMAffineMergeCtx& altBRAffineMergeRMVFCtx
+#endif
+#endif
+  );
   void getBMAffineMergeCand(const PredictionUnit &pu, AffineMergeCtx& affineBMMergeCtx, AffineMergeCtx affineMergeRMVFCtx, int mrgCandIdx = -1);
   bool getBMNonAdjCstMergeCand(const PredictionUnit &pu, AffineMergeCtx &affMrgCtx, const int mrgCandIdx = -1);
 #endif
@@ -773,6 +814,9 @@ namespace PU
 #else
   bool checkBDMVRCondition(const PredictionUnit& pu);
 #endif
+#if JVET_AG0276_LIC_BDOF_BDMVR
+  bool checkBDMVRCondition4Aff(const PredictionUnit& pu);
+#endif
 #endif
 #if INTER_LIC && RPR_ENABLE
   bool checkRprLicCondition(const PredictionUnit& pu);
@@ -889,6 +933,10 @@ namespace PU
   bool isBvgCccmCand(const PredictionUnit &pu, Mv &chromaBv, int& rrIbcType, int candIdx = 0);
   bool checkIsChromaBvCandidateValid(const PredictionUnit &pu, const Mv chromaBv, int &iWidth, int &iHeight, bool isRefTemplate = false, bool isRefAbove = false);
 #endif
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+  bool isOppositeLIC(const PredictionUnit &pu);
+  bool hasOppositeLICFlag(const PredictionUnit &pu);
+#endif
 }
 
 // TU tools
diff --git a/source/Lib/DecoderLib/CABACReader.cpp b/source/Lib/DecoderLib/CABACReader.cpp
index 26d78f18c..ec2cbd343 100644
--- a/source/Lib/DecoderLib/CABACReader.cpp
+++ b/source/Lib/DecoderLib/CABACReader.cpp
@@ -5155,6 +5155,13 @@ void CABACReader::merge_data( PredictionUnit& pu )
       {
         affBmFlag(pu);
       }
+#endif
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+      pu.affineOppositeLic = false;
+      if (PU::hasOppositeLICFlag(pu) && !pu.afMmvdFlag && !pu.affBMMergeFlag && pu.cs->sps->getUseAffMergeOppositeLic())
+      {
+        pu.affineOppositeLic = m_BinDecoder.decodeBin(Ctx::AffineFlagOppositeLic(0));
+      }
 #endif
       merge_idx(pu);
       cu.firstPU->regularMergeFlag = false;
@@ -5334,6 +5341,21 @@ void CABACReader::merge_data( PredictionUnit& pu )
   }
   else
   {
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+    pu.mergeOppositeLic = false;
+    pu.tmMergeFlagOppositeLic = false;
+    if (pu.regularMergeFlag && PU::hasOppositeLICFlag(pu) && !pu.bmMergeFlag)
+    {
+      if (pu.tmMergeFlag && pu.cs->sps->getUseTMMergeOppositeLic())
+      {
+        pu.tmMergeFlagOppositeLic = m_BinDecoder.decodeBin(Ctx::TmMergeFlagOppositeLic(0));
+      }
+      else if (pu.cs->sps->getUseMergeOppositeLic())
+      {
+        pu.mergeOppositeLic = m_BinDecoder.decodeBin(Ctx::MergeFlagOppositeLic(0));
+      }
+    }
+#endif
     merge_idx(pu);
   }
 }
@@ -5359,6 +5381,12 @@ void CABACReader::merge_idx( PredictionUnit& pu )
     }
 #endif
     int numCandminus1 = int( pu.cs->picHeader->getMaxNumAffineMergeCand() ) - 1;
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+    if (pu.affineOppositeLic)
+    {
+      numCandminus1 = int(pu.cs->picHeader->getMaxNumAffineOppositeLicMergeCand()) - 1;
+    }
+#endif
     pu.mergeIdx = 0;
     if ( numCandminus1 > 0 )
     {
@@ -5659,6 +5687,16 @@ void CABACReader::merge_idx( PredictionUnit& pu )
   {
     numCandminus1 = int(pu.cs->sps->getMaxNumBMMergeCand()) - 1;
   }
+#endif
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+  if (pu.mergeOppositeLic)
+  {
+    numCandminus1 = int(pu.cs->sps->getMaxNumOppositeLicMergeCand()) - 1;
+  }
+  else if (pu.tmMergeFlagOppositeLic)
+  {
+    numCandminus1 = int(pu.cs->sps->getMaxNumTMOppositeLicMergeCand()) - 1;
+  }
 #endif
   if( numCandminus1 > 0 )
   {
@@ -9596,8 +9634,24 @@ void CABACReader::cu_lic_flag( CodingUnit& cu )
   if( CU::isLICFlagPresent( cu ) )
   {
     RExt__DECODER_DEBUG_BIT_STATISTICS_CREATE_SET_SIZE( STATS__CABAC_BITS__LIC_FLAG, cu.lumaSize() );
+#if JVET_AG0276_LIC_SLOPE_ADJUST
+    unsigned ctxId = DeriveCtx::CtxLicFlag( cu );
+    cu.licFlag = m_BinDecoder.decodeBin( Ctx::LICFlag( ctxId ) );
+#else
     cu.licFlag = m_BinDecoder.decodeBin( Ctx::LICFlag( 0 ) );
+#endif
     DTRACE( g_trace_ctx, D_SYNTAX, "cu_lic_flag() lic_flag=%d\n", cu.licFlag ? 1 : 0 );
+#if JVET_AG0276_LIC_SLOPE_ADJUST
+    if (cu.licFlag && CU::isLicSlopeAllowed(cu) && cu.firstPU->interDir != 3)
+    {
+      int delta = m_BinDecoder.decodeBin(Ctx::LicDelta(0)) ? 1 : 0;
+      if (delta)
+      {
+        delta *= m_BinDecoder.decodeBin(Ctx::LicDelta(1)) ? -1 : +1;
+      }
+      cu.licDelta = delta;
+    }
+#endif
   }
 }
 #endif
diff --git a/source/Lib/DecoderLib/DecCu.cpp b/source/Lib/DecoderLib/DecCu.cpp
index 92f202d31..fdb821d79 100644
--- a/source/Lib/DecoderLib/DecCu.cpp
+++ b/source/Lib/DecoderLib/DecCu.cpp
@@ -1978,9 +1978,57 @@ void DecCu::xReconInter(CodingUnit &cu)
       }
     }
 #endif
+#if JVET_AG0276_NLIC
+    if (!cu.cs->pcv->isEncoder)
+    {
+      if (CU::isSecLicParaNeeded(cu))
+      {
+        UnitArea localUnitArea(cu.chromaFormat, Area(0, 0, cu.lumaSize().width, cu.lumaSize().height));
+        PelUnitBuf predBeforeMCAdjBuffer = m_pcInterPred->m_acPredBeforeLICBuffer[REF_PIC_LIST_0].getBuf(localUnitArea);
+
+        if (CU::isAllowSecLicPara(cu))
+        {
+          if (CU::isPredRefined(cu))
+          {
+#if INTER_LIC
+            bool orgLicFlag = cu.licFlag;
+            cu.licFlag = false;
+#endif
+            bool orgCiipFlag = cu.firstPU->ciipFlag;
+            cu.firstPU->ciipFlag = false;
+            m_pcInterPred->xPredWoRefinement(*cu.firstPU, predBeforeMCAdjBuffer);
+#if INTER_LIC
+            cu.licFlag = orgLicFlag;
+#endif
+            cu.firstPU->ciipFlag = orgCiipFlag;
+          }
+          else
+          {
+            predBeforeMCAdjBuffer.copyFrom(cu.cs->getPredBuf(*cu.firstPU));
+          }
+        }
+        else
+        {
+          if (cu.affine && cu.firstPU->mergeFlag && cu.cs->sps->getUseOBMC() && cu.obmcFlag && (cu.cs->sps->getUseAltLM() || cu.cs->sps->getUseAffAltLM()))
+          {
+            if (cu.obmcFlag && m_pcInterPred->isSCC(*cu.firstPU) && !CU::isTLCond(cu))
+            {
+              cu.obmcFlag = false;
+            }
+          }
+        }
+      }
+    }
+#endif
 #if MULTI_PASS_DMVR
     if (cu.firstPU->bdmvrRefine)
     {
+#if JVET_AG0276_LIC_BDOF_BDMVR
+      if (cu.licFlag == true)
+      {
+        memset((void*)m_pcInterPred->getBdofSubPuMvOffset(), 0, BDOF_SUBPU_MAX_NUM * sizeof(Mv));
+      }
+#endif
       PU::spanMotionInfo(*cu.firstPU, MergeCtx(),
 #if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION
         cu.firstPU->colIdx,
@@ -2177,6 +2225,43 @@ void DecCu::xReconInter(CodingUnit &cu)
 #endif
 #endif
 
+#if JVET_AG0276_NLIC
+  if (!cu.cs->pcv->isEncoder)
+  {
+    if (cu.altLMFlag)
+    {
+      cu.secAltLMParaUnit = cu.altLMParaUnit;
+    }
+    else
+    {
+      cu.secAltLMParaUnit = cu.altLMParaUnit;
+    }
+    if (CU::isSecLicParaNeeded(cu) && CU::isAllowSecLicPara(cu))
+    {
+      UnitArea localUnitArea(cu.chromaFormat, Area(0, 0, cu.lumaSize().width, cu.lumaSize().height));
+      PelUnitBuf predBeforeMCAdjBuffer = m_pcInterPred->m_acPredBeforeLICBuffer[REF_PIC_LIST_0].getBuf(localUnitArea);
+      PelUnitBuf recBuf = m_pcInterPred->m_acPredBeforeLICBuffer[REF_PIC_LIST_1].getBuf(localUnitArea);
+      recBuf.copyFrom(cu.cs->getRecoBuf(*cu.firstPU));
+      if (cu.cs->slice->getLmcsEnabledFlag() && m_pcReshape->getCTUFlag())
+      {
+        recBuf.Y().rspSignal(m_pcInterPred->m_pcReshape->getInvLUT());
+      }
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+      m_pcInterPred->xDevSecLicPara<false>(cu, predBeforeMCAdjBuffer, recBuf);
+#else
+      m_pcInterPred->xDevSecLicPara(cu, predBeforeMCAdjBuffer, recBuf);
+#endif
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+      m_pcInterPred->xDevSecLicPara<true>(cu, predBeforeMCAdjBuffer, recBuf);
+      if ((cu.altLMBRParaUnit.scale[COMPONENT_Y] == cu.altLMParaUnit.scale[COMPONENT_Y]) && (cu.altLMBRParaUnit.offset[COMPONENT_Y] == cu.altLMParaUnit.offset[COMPONENT_Y]))
+      {
+        cu.altLMBRParaUnit.resetAltLinearModel();
+      }
+#endif
+    }
+  }
+#endif
+
   DTRACE    ( g_trace_ctx, D_TMP, "reco " );
   DTRACE_CRC( g_trace_ctx, D_TMP, *cu.cs, cu.cs->getRecoBuf( cu ), &cu.Y() );
 
@@ -2682,6 +2767,10 @@ void DecCu::xDeriveCUMV(CodingUnit &cu)
             m_geoTmMrgCtx0.numValidMergeCand = m_geoMrgCtx.numValidMergeCand;
             m_geoTmMrgCtx0.bcwIdx[pu.geoMergeIdx0] = BCW_DEFAULT;
             m_geoTmMrgCtx0.useAltHpelIf[pu.geoMergeIdx0] = false;
+#if JVET_AG0276_NLIC
+            m_geoTmMrgCtx0.altLMFlag[pu.geoMergeIdx0] = m_geoMrgCtx.altLMFlag[pu.geoMergeIdx0];
+            m_geoTmMrgCtx0.altLMParaNeighbours[pu.geoMergeIdx0] = m_geoMrgCtx.altLMParaNeighbours[pu.geoMergeIdx0];
+#endif
 #if INTER_LIC
             m_geoTmMrgCtx0.licFlags[pu.geoMergeIdx0] = false;
 #endif
@@ -2694,8 +2783,12 @@ void DecCu::xDeriveCUMV(CodingUnit &cu)
             m_geoTmMrgCtx0.mvFieldNeighbours[(pu.geoMergeIdx0 << 1)].refIdx = m_geoMrgCtx.mvFieldNeighbours[(pu.geoMergeIdx0 << 1)].refIdx;
             m_geoTmMrgCtx0.mvFieldNeighbours[(pu.geoMergeIdx0 << 1) + 1].refIdx = m_geoMrgCtx.mvFieldNeighbours[(pu.geoMergeIdx0 << 1) + 1].refIdx;
 #if JVET_Z0056_GPM_SPLIT_MODE_REORDERING
+#if JVET_AG0276_NLIC
+            m_geoTmMrgCtx[GEO_TM_SHAPE_A] = m_geoTmMrgCtx0;
+#else
             memcpy(&m_geoTmMrgCtx[GEO_TM_SHAPE_A], &m_geoTmMrgCtx0, sizeof(m_geoTmMrgCtx0));
 #endif
+#endif
 
 #if JVET_Z0056_GPM_SPLIT_MODE_REORDERING
             for (uint8_t tmType = GEO_TM_SHAPE_AL; tmType < GEO_NUM_TM_MV_CAND; ++tmType)
@@ -2732,6 +2825,10 @@ void DecCu::xDeriveCUMV(CodingUnit &cu)
             m_geoTmMrgCtx1.numValidMergeCand = m_geoMrgCtx.numValidMergeCand;
             m_geoTmMrgCtx1.bcwIdx[pu.geoMergeIdx1] = BCW_DEFAULT;
             m_geoTmMrgCtx1.useAltHpelIf[pu.geoMergeIdx1] = false;
+#if JVET_AG0276_NLIC
+            m_geoTmMrgCtx1.altLMFlag[pu.geoMergeIdx1] = m_geoMrgCtx.altLMFlag[pu.geoMergeIdx1];
+            m_geoTmMrgCtx1.altLMParaNeighbours[pu.geoMergeIdx1] = m_geoMrgCtx.altLMParaNeighbours[pu.geoMergeIdx1];
+#endif
 #if INTER_LIC
             m_geoTmMrgCtx1.licFlags[pu.geoMergeIdx1] = false;
 #endif
@@ -2744,8 +2841,12 @@ void DecCu::xDeriveCUMV(CodingUnit &cu)
             m_geoTmMrgCtx1.mvFieldNeighbours[(pu.geoMergeIdx1 << 1)].refIdx = m_geoMrgCtx.mvFieldNeighbours[(pu.geoMergeIdx1 << 1)].refIdx;
             m_geoTmMrgCtx1.mvFieldNeighbours[(pu.geoMergeIdx1 << 1) + 1].refIdx = m_geoMrgCtx.mvFieldNeighbours[(pu.geoMergeIdx1 << 1) + 1].refIdx;
 #if JVET_Z0056_GPM_SPLIT_MODE_REORDERING
+#if JVET_AG0276_NLIC
+            m_geoTmMrgCtx[GEO_TM_SHAPE_L] = m_geoTmMrgCtx1;
+#else
             memcpy(&m_geoTmMrgCtx[GEO_TM_SHAPE_L], &m_geoTmMrgCtx1, sizeof(m_geoTmMrgCtx1));
 #endif
+#endif
 
 #if JVET_Z0056_GPM_SPLIT_MODE_REORDERING
             for (uint8_t tmType = GEO_TM_SHAPE_AL; tmType < GEO_NUM_TM_MV_CAND; ++tmType)
@@ -2824,6 +2925,17 @@ void DecCu::xDeriveCUMV(CodingUnit &cu)
 #if JVET_AD0182_AFFINE_DMVR_PLUS_EXTENSIONS
           AffineMergeCtx affineRMVFCtx;
           AffineMergeCtx affineRMVFOriCtx;
+#endif
+#if JVET_AG0276_NLIC
+          AltLMAffineMergeCtx altAffineRMVFCtx;
+          altAffineRMVFCtx.init();
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+          AltLMAffineMergeCtx altBRAffineRMVFCtx;
+          altBRAffineRMVFCtx.init();
+#endif
+#endif
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+          AffineMergeCtx affineRMVFCtxOppositeLic;
 #endif
           if (pu.cs->sps->getSbTMVPEnabledFlag())
           {
@@ -2859,7 +2971,14 @@ void DecCu::xDeriveCUMV(CodingUnit &cu)
 #endif
 #if JVET_AD0182_AFFINE_DMVR_PLUS_EXTENSIONS
           uint16_t addNumRMVF = 0;
-          PU::getRMVFAffineCand(pu, affineRMVFCtx, affineRMVFOriCtx, m_pcInterPred, addNumRMVF);
+          PU::getRMVFAffineCand(pu, affineRMVFCtx, affineRMVFOriCtx, m_pcInterPred, addNumRMVF
+#if JVET_AG0276_NLIC
+            , altAffineRMVFCtx
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+            , altBRAffineRMVFCtx
+#endif
+#endif
+          );
           if (pu.affBMMergeFlag)
           {
             PU::getBMAffineMergeCand(pu, affineMergeCtx, affineRMVFOriCtx, -1);
@@ -2888,11 +3007,59 @@ void DecCu::xDeriveCUMV(CodingUnit &cu)
 #else
               , (pu.mergeIdx == 0 && !pu.affBMMergeFlag)
 #endif
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+                && !pu.affineOppositeLic
+#endif
 #else
               , pu.mergeIdx == 0
 #endif
 #endif
             );
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+            if (pu.affineOppositeLic && !pu.afMmvdFlag)
+            {
+              int cnt = 0;
+              affineRMVFCtxOppositeLic = affineMergeCtx;
+              affineMergeCtx.numValidMergeCand = 0;
+              for (int i = 0; i < affineRMVFCtxOppositeLic.numValidMergeCand; i++)
+              {
+                if (affineRMVFCtxOppositeLic.mergeType[i] == MRG_TYPE_DEFAULT_N)
+                {
+                  for (int mvNum = 0; mvNum < 3; mvNum++)
+                  {
+                    affineMergeCtx.mvFieldNeighbours[(cnt << 1) + 0][mvNum] = affineRMVFCtxOppositeLic.mvFieldNeighbours[(i << 1) + 0][mvNum];
+                    affineMergeCtx.mvFieldNeighbours[(cnt << 1) + 1][mvNum] = affineRMVFCtxOppositeLic.mvFieldNeighbours[(i << 1) + 1][mvNum];
+                  }
+                  affineMergeCtx.interDirNeighbours[cnt] = affineRMVFCtxOppositeLic.interDirNeighbours[i];
+                  affineMergeCtx.affineType[cnt] = affineRMVFCtxOppositeLic.affineType[i];
+                  affineMergeCtx.mergeType[cnt] = affineRMVFCtxOppositeLic.mergeType[i];
+                  affineMergeCtx.bcwIdx[cnt] = affineRMVFCtxOppositeLic.bcwIdx[i];
+#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION
+                  affineMergeCtx.colIdx[cnt] = affineRMVFCtxOppositeLic.colIdx[i];
+#endif
+#if JVET_AG0276_NLIC
+                  affineMergeCtx.altLMFlag[cnt] = affineRMVFCtxOppositeLic.altLMFlag[i];
+                  affineMergeCtx.altLMParaNeighbours[cnt] = affineRMVFCtxOppositeLic.altLMParaNeighbours[i];
+#endif
+#if INTER_LIC                                                   
+                  affineMergeCtx.licFlags[cnt] = !affineRMVFCtxOppositeLic.licFlags[i];
+#endif
+#if JVET_AD0193_ADAPTIVE_OBMC_CONTROL
+                  affineMergeCtx.obmcFlags[cnt] = affineRMVFCtxOppositeLic.obmcFlags[i];
+#endif
+                  affineMergeCtx.candCost[cnt] = affineRMVFCtxOppositeLic.candCost[i];
+                  cnt++;
+                  affineMergeCtx.numValidMergeCand++;
+                }
+                else
+                {
+                  continue;
+                }
+              }
+              affineMergeCtx.numAffCandToTestEnc = std::min(affineMergeCtx.numValidMergeCand, affineRMVFCtxOppositeLic.numAffCandToTestEnc);
+              affineMergeCtx.maxNumMergeCand = affineMergeCtx.numValidMergeCand;
+            }
+#endif
 #if JVET_AD0182_AFFINE_DMVR_PLUS_EXTENSIONS
           }
 #endif
@@ -2908,6 +3075,10 @@ void DecCu::xDeriveCUMV(CodingUnit &cu)
             pu.interDir = affineMergeCtx.interDirNeighbours[pu.mergeIdx];
             pu.cu->affineType = affineMergeCtx.affineType[pu.mergeIdx];
             pu.cu->bcwIdx = affineMergeCtx.bcwIdx[pu.mergeIdx];
+#if JVET_AG0276_NLIC
+            pu.cu->altLMFlag = affineMergeCtx.altLMFlag[pu.mergeFlag];
+            pu.cu->altLMParaUnit = affineMergeCtx.altLMParaNeighbours[pu.mergeFlag];
+#endif
 #if INTER_LIC
             pu.cu->licFlag = affineMergeCtx.licFlags[pu.mergeIdx];
 #endif
@@ -2934,7 +3105,11 @@ void DecCu::xDeriveCUMV(CodingUnit &cu)
                 }
               }
             }
+#if JVET_AG0276_LIC_BDOF_BDMVR
+            if (PU::checkBDMVRCondition4Aff(pu))
+#else
             if (PU::checkBDMVRCondition(pu))
+#endif
             {
               if (PU::checkBDMVR4Affine(pu))
               {
@@ -2974,6 +3149,50 @@ void DecCu::xDeriveCUMV(CodingUnit &cu)
 #if JVET_W0090_ARMC_TM
           else
           {
+#if JVET_AG0276_NLIC
+            if (pu.cs->sps->getUseAML()
+#if JVET_AE0174_NONINTER_TM_TOOLS_CONTROL
+              && pu.cs->sps->getTMToolsEnableFlag()
+#endif
+               )
+            {
+              if (pu.affBMMergeFlag)
+              {
+                m_pcInterPred->adjustAffineMergeCandidates(pu, affineMergeCtx, pu.mergeIdx);
+              }
+              else
+              {
+                if (affineMergeCtx.numValidMergeCand > 1)
+                {
+                  if (pu.cs->sps->getUseAffAltLM() && !CU::isTLCond(*pu.cu))
+                  {
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+                  if (!pu.affineOppositeLic)
+                  {
+#endif
+                    AltLMAffineMergeCtx altLMAffMrgCtx;
+                    PU::getAltLMAffineMergeCand(pu, altLMAffMrgCtx);
+                    m_pcInterPred->adjustAffineMergeCandidates(pu, affineMergeCtx, altLMAffMrgCtx, altAffineRMVFCtx);
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+                  }
+                  else
+                  {
+                    AltLMAffineMergeCtx altLMBRAffMrgCtx;
+                    PU::getAltLMBRAffineMergeCand(pu, altLMBRAffMrgCtx);
+                    m_pcInterPred->adjustAffineMergeCandidates(pu, affineMergeCtx, altLMBRAffMrgCtx, altBRAffineRMVFCtx);
+                  }
+#endif
+                  }
+                  else
+                  {
+                    m_pcInterPred->adjustAffineMergeCandidates(pu, affineMergeCtx, pu.mergeIdx);
+                  }
+                  affineMergeCtx.numValidMergeCand = pu.cu->slice->getPicHeader()->getMaxNumAffineMergeCand();
+                  affineMergeCtx.maxNumMergeCand = pu.cu->slice->getPicHeader()->getMaxNumAffineMergeCand();
+                }
+              }
+            }
+#else
             if (pu.cs->sps->getUseAML()
 #if JVET_AE0174_NONINTER_TM_TOOLS_CONTROL
                 && pu.cs->sps->getTMToolsEnableFlag()
@@ -2985,6 +3204,7 @@ void DecCu::xDeriveCUMV(CodingUnit &cu)
             {
               m_pcInterPred->adjustAffineMergeCandidates(pu, affineMergeCtx, pu.mergeIdx);
             }
+#endif
 #if JVET_AD0182_AFFINE_DMVR_PLUS_EXTENSIONS
             if (pu.affBMMergeFlag)
             {
@@ -3031,9 +3251,14 @@ void DecCu::xDeriveCUMV(CodingUnit &cu)
 #if JVET_AE0174_NONINTER_TM_TOOLS_CONTROL
             && pu.cs->sps->getTMToolsEnableFlag()
 #endif
-            && PU::checkAffineTMCondition(pu))
+            && PU::checkAffineTMCondition(pu)
+             )
           {
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+            for (uint32_t uiAffMergeCand = 0; uiAffMergeCand < (pu.affineOppositeLic ? int(pu.cs->picHeader->getMaxNumAffineOppositeLicMergeCand()) : affineMergeCtx.numValidMergeCand); uiAffMergeCand++)
+#else
             for (uint32_t uiAffMergeCand = 0; uiAffMergeCand < affineMergeCtx.numValidMergeCand; uiAffMergeCand++)
+#endif
             {
               if (affineMergeCtx.mvFieldNeighbours[(uiAffMergeCand << 1) + 0][0].mv == Mv(0, 0) && affineMergeCtx.mvFieldNeighbours[(uiAffMergeCand << 1) + 1][0].mv == Mv(0, 0) &&
                 affineMergeCtx.mvFieldNeighbours[(uiAffMergeCand << 1) + 0][1].mv == Mv(0, 0) && affineMergeCtx.mvFieldNeighbours[(uiAffMergeCand << 1) + 1][1].mv == Mv(0, 0) &&
@@ -3043,10 +3268,17 @@ void DecCu::xDeriveCUMV(CodingUnit &cu)
                 validNum = uiAffMergeCand;
                 break;
               }
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+              if (uiAffMergeCand == (pu.affineOppositeLic ? (int(pu.cs->picHeader->getMaxNumAffineOppositeLicMergeCand()) - 1) : pu.cu->slice->getPicHeader()->getMaxNumAffineMergeCand() - 1))
+              {
+                validNum = pu.affineOppositeLic ? int(pu.cs->picHeader->getMaxNumAffineOppositeLicMergeCand()) : pu.cu->slice->getPicHeader()->getMaxNumAffineMergeCand();
+              }
+#else
               if (uiAffMergeCand == pu.cu->slice->getPicHeader()->getMaxNumAffineMergeCand() - 1)
               {
                 validNum = pu.cu->slice->getPicHeader()->getMaxNumAffineMergeCand();
               }
+#endif
             }
             if (!pu.afMmvdFlag)
             {
@@ -3056,7 +3288,11 @@ void DecCu::xDeriveCUMV(CodingUnit &cu)
                 int value = pu.mergeIdx - validNum;
                 for (uint32_t uiAffMergeCand = 0; uiAffMergeCand < validNum; uiAffMergeCand++)
                 {
+#if JVET_AG0276_NLIC
+                  if (!affineMergeCtx.altLMFlag[uiAffMergeCand] && affineMergeCtx.interDirNeighbours[uiAffMergeCand] != 3 && affineMergeCtx.mergeType[uiAffMergeCand] != MRG_TYPE_SUBPU_ATMVP)
+#else
                   if (affineMergeCtx.interDirNeighbours[uiAffMergeCand] != 3 && affineMergeCtx.mergeType[uiAffMergeCand] != MRG_TYPE_SUBPU_ATMVP)
+#endif
                   {
                     value--;
                     if (value == -1)
@@ -3077,6 +3313,10 @@ void DecCu::xDeriveCUMV(CodingUnit &cu)
           pu.interDir = affineMergeCtx.interDirNeighbours[pu.mergeIdx];
           pu.cu->affineType = affineMergeCtx.affineType[pu.mergeIdx];
           pu.cu->bcwIdx = affineMergeCtx.bcwIdx[pu.mergeIdx];
+#if JVET_AG0276_NLIC
+          pu.cu->altLMFlag = affineMergeCtx.altLMFlag[pu.mergeIdx];
+          pu.cu->altLMParaUnit = affineMergeCtx.altLMParaNeighbours[pu.mergeIdx];
+#endif
 #if INTER_LIC
           pu.cu->licFlag = affineMergeCtx.licFlags[pu.mergeIdx];
 #endif
@@ -3111,9 +3351,17 @@ void DecCu::xDeriveCUMV(CodingUnit &cu)
           }
 #if JVET_AB0112_AFFINE_DMVR
 #if JVET_AG0135_AFFINE_CIIP
+#if JVET_AG0276_LIC_BDOF_BDMVR
+          if (!pu.afMmvdFlag&&pu.mergeType != MRG_TYPE_SUBPU_ATMVP && (pu.ciipAffine ? PU::checkBDMVRConditionCIIPAffine(pu) : PU::checkBDMVRCondition4Aff(pu)))
+#else
           if (!pu.afMmvdFlag&&pu.mergeType != MRG_TYPE_SUBPU_ATMVP && (pu.ciipAffine ? PU::checkBDMVRConditionCIIPAffine(pu) : PU::checkBDMVRCondition(pu)))
+#endif
+#else
+#if JVET_AG0276_LIC_BDOF_BDMVR
+          if (!pu.afMmvdFlag&&pu.mergeType != MRG_TYPE_SUBPU_ATMVP && PU::checkBDMVRCondition4Aff(pu))
 #else
           if (!pu.afMmvdFlag&&pu.mergeType != MRG_TYPE_SUBPU_ATMVP && PU::checkBDMVRCondition(pu))
+#endif
 #endif
           {
 #if !JVET_AC0144_AFFINE_DMVR_REGRESSION
@@ -3161,7 +3409,11 @@ void DecCu::xDeriveCUMV(CodingUnit &cu)
 #if JVET_AE0174_NONINTER_TM_TOOLS_CONTROL
             && pu.cs->sps->getTMToolsEnableFlag()
 #endif
-            && !pu.afMmvdFlag && pu.mergeType != MRG_TYPE_SUBPU_ATMVP && pu.interDir != 3 && !((pu.mergeIdx > validNum - 1) && !isAdditional) && PU::checkAffineTMCondition(pu))
+#if JVET_AG0276_NLIC
+            && (pu.cs->sps->getUseAffAltLMTM() || !pu.cu->altLMFlag)
+#endif
+            && !pu.afMmvdFlag && pu.mergeType != MRG_TYPE_SUBPU_ATMVP && pu.interDir != 3 && !((pu.mergeIdx > validNum - 1) && !isAdditional) && PU::checkAffineTMCondition(pu)
+             )
           {
             for (int i = 0; i < 3; i++)
             {
@@ -3171,7 +3423,12 @@ void DecCu::xDeriveCUMV(CodingUnit &cu)
             m_pcInterPred->setBdmvrSubPuMvBuf(m_mvBufBDMVR[0], m_mvBufBDMVR[1]);
             pu.bdmvrRefine = false;
 
+#if JVET_AG0276_NLIC
+            if ((!pu.cu->altLMFlag && !affineMergeCtx.xCheckSimilarMotion1(pu.mergeIdx, PU::getBDMVRMvdThreshold(pu), false)) ||
+                (pu.cu->altLMFlag && !affineMergeCtx.xCheckSimilarMotion1(pu.mergeIdx, PU::getBDMVRMvdThreshold(pu), true)))
+#else
             if (!affineMergeCtx.xCheckSimilarMotion(pu.mergeIdx, PU::getBDMVRMvdThreshold(pu)))
+#endif
             {
               m_pcInterPred->processTM4Affine(pu, affineMergeCtx, isAdditional ? 0 : -1, false);
               pu.mvAffi[0][0] += m_mvBufBDMVR[0][0];
@@ -3765,6 +4022,15 @@ void DecCu::xDeriveCUMV(CodingUnit &cu)
                                            pu.tmMergeFlag ? pu.cs->sps->getMaxNumTMMergeCand() :
 #endif
                                            pu.cs->sps->getMaxNumMergeCand();
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+                if ((pu.mergeOppositeLic || pu.tmMergeFlagOppositeLic) && !pu.bmMergeFlag)
+                {
+                  for (int i = 0; i < mrgCtx.numValidMergeCand; i++)
+                  {
+                    mrgCtx.licFlags[i] = !mrgCtx.licFlags[i];
+                  }
+                }
+#endif
               }
               else
 #endif
@@ -3786,6 +4052,15 @@ void DecCu::xDeriveCUMV(CodingUnit &cu)
 #if TM_MRG && JVET_AA0093_REFINED_MOTION_FOR_ARMC
                 if (pu.tmMergeFlag && tmMergeRefinedMotion)
                 {
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+                  if (pu.tmMergeFlagOppositeLic)
+                  {
+                    for (int i = 0; i < mrgCtx.numValidMergeCand; i++)
+                    {
+                      mrgCtx.licFlags[i] = !mrgCtx.licFlags[i];
+                    }
+                  }
+#endif
 #if JVET_Z0102_NO_ARMC_FOR_ZERO_CAND
                   m_pcInterPred->adjustMergeCandidates(pu, mrgCtx, pu.cs->sps->getMaxNumTMMergeCand());
 #else
@@ -3793,11 +4068,27 @@ void DecCu::xDeriveCUMV(CodingUnit &cu)
 #endif
                   int tmpPuMrgIdx = pu.mergeIdx;
                   pu.reduceTplSize = true;
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+                  if (pu.tmMergeFlagOppositeLic)
+                  {
+                    if (mrgCtx.numValidMergeCand > pu.cs->sps->getMaxNumTMOppositeLicMergeCand())
+                    {
+                      mrgCtx.numValidMergeCand = pu.cs->sps->getMaxNumTMOppositeLicMergeCand();
+                    }
+                  }
+                  else
+                  {
+                    if (mrgCtx.numValidMergeCand > pu.cs->sps->getMaxNumTMMergeCand())
+                    {
+                      mrgCtx.numValidMergeCand = pu.cs->sps->getMaxNumTMMergeCand();
+                    }
+                  }
+#else
                   if (mrgCtx.numValidMergeCand > pu.cs->sps->getMaxNumTMMergeCand())
                   {
                     mrgCtx.numValidMergeCand = pu.cs->sps->getMaxNumTMMergeCand();
                   }
-
+#endif
                   if (mrgCtx.numCandToTestEnc > mrgCtx.numValidMergeCand)
                   {
                     mrgCtx.numCandToTestEnc = mrgCtx.numValidMergeCand;
@@ -3806,6 +4097,10 @@ void DecCu::xDeriveCUMV(CodingUnit &cu)
                   for (uint32_t ui = mrgCtx.numValidMergeCand; ui < NUM_MERGE_CANDS; ++ui)
                   {
                     mrgCtx.bcwIdx[ui] = BCW_DEFAULT;
+#if JVET_AG0276_NLIC
+                    mrgCtx.altLMFlag[ui] = false;
+                    mrgCtx.altLMParaNeighbours[ui].resetAltLinearModel();
+#endif
 #if INTER_LIC
                     mrgCtx.licFlags[ui] = false;
 #endif
@@ -3869,6 +4164,19 @@ void DecCu::xDeriveCUMV(CodingUnit &cu)
 #if JVET_AB0079_TM_BCW_MRG
                 {
 #endif
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+                if (pu.mergeOppositeLic || pu.tmMergeFlagOppositeLic)
+                {
+                  for (int i = 0; i < mrgCtx.numValidMergeCand; i++)
+                  {
+                    mrgCtx.licFlags[i] = !mrgCtx.licFlags[i];
+                  }
+                }
+#endif
+#if JVET_AG0276_NLIC
+                if (pu.tmMergeFlag || pu.ciipFlag)
+                {
+#endif
 #if JVET_Z0102_NO_ARMC_FOR_ZERO_CAND
                 m_pcInterPred->adjustMergeCandidates(pu, mrgCtx, 
 #if TM_MRG
@@ -3878,6 +4186,43 @@ void DecCu::xDeriveCUMV(CodingUnit &cu)
 #else
                 m_pcInterPred->adjustMergeCandidatesInOneCandidateGroup(pu, mrgCtx, pu.mergeIdx + 1, pu.mergeIdx);
 #endif
+#if JVET_AG0276_NLIC
+                }
+                else
+                {
+                  if (pu.cs->sps->getUseAltLM() && !CU::isTLCond(*pu.cu))
+                  {
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+                  if (!pu.mergeOppositeLic)
+                  {
+#endif
+                    AltLMMergeCtx altLMMrgCtx;
+                    PU::getAltMergeCandidates(pu, altLMMrgCtx);
+                    m_pcInterPred->adjustMergeCandidates(pu, mrgCtx, altLMMrgCtx, pu.cs->sps->getMaxNumMergeCand());
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+                  }
+                  else
+                  {
+                    AltLMMergeCtx altLMBRMrgCtx;
+                    PU::getAltBRMergeCandidates(pu, altLMBRMrgCtx);
+                    m_pcInterPred->adjustMergeCandidates(pu, mrgCtx, altLMBRMrgCtx, pu.cs->sps->getMaxNumMergeCand());
+                  }
+#endif
+                  }
+                  else
+                  {
+#if JVET_Z0102_NO_ARMC_FOR_ZERO_CAND
+                    m_pcInterPred->adjustMergeCandidates(pu, mrgCtx, 
+#if TM_MRG
+                                                         pu.tmMergeFlag ? pu.cs->sps->getMaxNumTMMergeCand() : 
+#endif
+                                                         pu.cs->sps->getMaxNumMergeCand());
+#else
+                    m_pcInterPred->adjustMergeCandidatesInOneCandidateGroup(pu, mrgCtx, pu.mergeIdx + 1, pu.mergeIdx);
+#endif
+                  }
+                }
+#endif
 #if JVET_AB0079_TM_BCW_MRG
                 m_pcInterPred->adjustMergeCandidatesBcwIdx(pu, mrgCtx, pu.mergeIdx);
                 }
@@ -3917,6 +4262,15 @@ void DecCu::xDeriveCUMV(CodingUnit &cu)
 #endif
               if (pu.tmMergeFlag && tmMergeRefinedMotion)
               {
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+                if (pu.tmMergeFlagOppositeLic)
+                {
+                  for (int i = 0; i < mrgCtx.numValidMergeCand; i++)
+                  {
+                    mrgCtx.licFlags[i] = !mrgCtx.licFlags[i];
+                  }
+                }
+#endif
                 int tmpPuMrgIdx = pu.mergeIdx;
                 pu.reduceTplSize = true;
                 if (mrgCtx.numValidMergeCand > pu.cs->sps->getMaxNumTMMergeCand())
@@ -3932,6 +4286,10 @@ void DecCu::xDeriveCUMV(CodingUnit &cu)
                 for (uint32_t ui = mrgCtx.numValidMergeCand; ui < NUM_MERGE_CANDS; ++ui)
                 {
                   mrgCtx.bcwIdx[ui] = BCW_DEFAULT;
+#if JVET_AG0276_NLIC
+                  mrgCtx.altLMFlag[ui] = false;
+                  mrgCtx.altLMParaNeighbours[ui].resetAltLinearModel();
+#endif
 #if INTER_LIC
                   mrgCtx.licFlags[ui] = false;
 #endif
@@ -3994,6 +4352,15 @@ void DecCu::xDeriveCUMV(CodingUnit &cu)
 #endif
 #if JVET_AB0079_TM_BCW_MRG
               {
+#endif
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+                if (pu.mergeOppositeLic)
+                {
+                  for (int i = 0; i < mrgCtx.numValidMergeCand; i++)
+                  {
+                    mrgCtx.licFlags[i] = !mrgCtx.licFlags[i];
+                  }
+                }
 #endif
               m_pcInterPred->adjustInterMergeCandidates(pu, mrgCtx, pu.mergeIdx);
 #if JVET_AB0079_TM_BCW_MRG
diff --git a/source/Lib/DecoderLib/VLCReader.cpp b/source/Lib/DecoderLib/VLCReader.cpp
index 8eafb4297..9ec3b3e74 100644
--- a/source/Lib/DecoderLib/VLCReader.cpp
+++ b/source/Lib/DecoderLib/VLCReader.cpp
@@ -2243,6 +2243,12 @@ void HLSyntaxReader::parseSPS(SPS* pcSPS)
 #endif
 #if INTER_LIC
   READ_FLAG( uiCode, "sps_lic_enabled_flag" );                      pcSPS->setLicEnabledFlag( uiCode );
+#if JVET_AG0276_LIC_SLOPE_ADJUST
+  if (pcSPS->getLicEnabledFlag())
+  {
+    READ_FLAG( uiCode, "sps_lic_slope_adjust_enabled_flag" ); pcSPS->setLicSlopeAdjustEnabledFlag( uiCode );
+  }
+#endif
 #endif
 
   READ_FLAG(uiCode, "sps_ref_wraparound_enabled_flag");                  pcSPS->setWrapAroundEnabledFlag( uiCode ? true : false );
@@ -2391,6 +2397,12 @@ void HLSyntaxReader::parseSPS(SPS* pcSPS)
   {
     pcSPS->setFpelMmvdEnabledFlag( false );
   }
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+  pcSPS->setUseMergeOppositeLic( false );
+  pcSPS->setUseTMMergeOppositeLic( false );
+  READ_FLAG(uiCode, "sps_oppositelic_merge_enabled_flag");                     pcSPS->setUseMergeOppositeLic(uiCode != 0);
+  READ_FLAG(uiCode, "sps_TM_oppositelic_merge_enabled_flag");                     pcSPS->setUseTMMergeOppositeLic(uiCode != 0);
+#endif
 #if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED || JVET_AD0140_MVD_PREDICTION
 #if JVET_AA0132_CONFIGURABLE_TM_TOOLS
   uiCode = 0;
@@ -2402,6 +2414,13 @@ void HLSyntaxReader::parseSPS(SPS* pcSPS)
   READ_UVLC(uiCode, "six_minus_max_num_merge_cand");
   CHECK(MRG_MAX_NUM_CANDS <= uiCode, "Incorrrect max number of merge candidates!");
   pcSPS->setMaxNumMergeCand(MRG_MAX_NUM_CANDS - uiCode);
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+  if (pcSPS->getUseMergeOppositeLic())
+  {
+    READ_UVLC(uiCode, "five_max_num_oppolic_merge_cand");
+    pcSPS->setMaxNumOppositeLicMergeCand(REG_MRG_MAX_NUM_CANDS_OPPOSITELIC - uiCode);
+  }
+#endif
   READ_FLAG(uiCode, "sps_sbt_enabled_flag");                        pcSPS->setUseSBT                 ( uiCode != 0 );
 #if TM_AMVP || TM_MRG || JVET_Z0084_IBC_TM || MULTI_PASS_DMVR
   READ_FLAG( uiCode,    "sps_dmvd_enabled_flag" );                      pcSPS->setUseDMVDMode( uiCode != 0 );
@@ -2437,6 +2456,29 @@ void HLSyntaxReader::parseSPS(SPS* pcSPS)
   pcSPS->setMaxNumBMMergeCand(BM_MRG_MAX_NUM_CANDS - uiCode);
 #endif
   READ_FLAG( uiCode,    "sps_affine_enabled_flag" );                            pcSPS->setUseAffine              ( uiCode != 0 );
+#if JVET_AG0276_NLIC
+  pcSPS->setUseAltLM(false);
+  pcSPS->setUseAffAltLM(false);
+  if (pcSPS->getUseAML()
+#if JVET_AE0174_NONINTER_TM_TOOLS_CONTROL
+    && pcSPS->getTMToolsEnableFlag()
+#endif
+    )
+  {
+    READ_FLAG( uiCode, "sps_alt_lm_enabled_flag" );                     pcSPS->setUseAltLM( uiCode != 0 );
+    if (pcSPS->getUseAffine())
+    {
+      READ_FLAG( uiCode, "sps_affine_alt_lm_enabled_flag" );            pcSPS->setUseAffAltLM( uiCode != 0 );
+    }
+  }
+#endif
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+  pcSPS->setUseAffMergeOppositeLic(false);
+  if (pcSPS->getUseAffine())
+  {
+    READ_FLAG(uiCode, "sps_affine_oppolic_merge_enabled_flag");            pcSPS->setUseAffMergeOppositeLic(uiCode != 0);
+  }
+#endif
   if ( pcSPS->getUseAffine() )
   {
     READ_UVLC(uiCode, "five_minus_max_num_subblock_merge_cand");
@@ -2454,6 +2496,13 @@ void HLSyntaxReader::parseSPS(SPS* pcSPS)
     READ_FLAG( uiCode,  "sps_affine_type_flag" );                       pcSPS->setUseAffineType          ( uiCode != 0 );
 #if AFFINE_MMVD
     READ_FLAG( uiCode, "sps_affine_mmvd_enabled_flag" );                pcSPS->setUseAffineMmvdMode      ( uiCode != 0 );
+#endif
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+    if (pcSPS->getUseAffMergeOppositeLic())
+    {
+      READ_UVLC(uiCode, "eight_minus_max_num_aff_oppolic_merge_cand");
+      pcSPS->setMaxNumAffineOppositeLicMergeCand(AFF_MRG_MAX_NUM_CANDS_OPPOSITELIC - uiCode);
+    }
 #endif
     if( pcSPS->getAMVREnabledFlag())
     {
@@ -2483,6 +2532,16 @@ void HLSyntaxReader::parseSPS(SPS* pcSPS)
       pcSPS->setUseAffineTM( false );
     }
 #endif
+#if JVET_AG0276_NLIC
+    if (pcSPS->getUseAffineTM() && pcSPS->getUseAffAltLM())
+    {
+      READ_FLAG(uiCode, "sps_affine_alt_lm_tm_flag");                pcSPS->setUseAffAltLMTM(uiCode != 0);
+    }
+    else
+    {
+      pcSPS->setUseAffAltLMTM(false);
+    }
+#endif
 #endif
   }
 #if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
@@ -4103,10 +4162,16 @@ void HLSyntaxReader::parsePictureHeader( PicHeader* picHeader, ParameterSetManag
     if ( sps->getUseAffine() )
     {
       picHeader->setMaxNumAffineMergeCand(sps->getMaxNumAffineMergeCand());
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+      picHeader->setMaxNumAffineOppositeLicMergeCand(sps->getMaxNumAffineOppositeLicMergeCand());
+#endif
     }
     else
     {
       picHeader->setMaxNumAffineMergeCand(sps->getSbTMVPEnabledFlag() && picHeader->getEnableTMVPFlag());
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+      picHeader->setMaxNumAffineOppositeLicMergeCand(0);
+#endif
     }
 
   // full-pel MMVD flag
diff --git a/source/Lib/EncoderLib/CABACWriter.cpp b/source/Lib/EncoderLib/CABACWriter.cpp
index f1b19ce89..161e092da 100644
--- a/source/Lib/EncoderLib/CABACWriter.cpp
+++ b/source/Lib/EncoderLib/CABACWriter.cpp
@@ -4521,6 +4521,12 @@ void CABACWriter::merge_data(const PredictionUnit& pu)
     {
       affBmFlag(pu);
     }
+#endif
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+    if (PU::hasOppositeLICFlag(pu) && !pu.afMmvdFlag && !pu.affBMMergeFlag && pu.cs->sps->getUseAffMergeOppositeLic())
+    {
+      m_BinEncoder.encodeBin(pu.affineOppositeLic, Ctx::AffineFlagOppositeLic(0));
+    }
 #endif
     merge_idx(pu);
     return;
@@ -4602,6 +4608,19 @@ void CABACWriter::merge_data(const PredictionUnit& pu)
     }
     else
     {
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+      if (pu.regularMergeFlag && PU::hasOppositeLICFlag(pu) && !pu.bmMergeFlag)
+      {
+        if (pu.tmMergeFlag && pu.cs->sps->getUseTMMergeOppositeLic())
+        {
+          m_BinEncoder.encodeBin(pu.tmMergeFlagOppositeLic, Ctx::TmMergeFlagOppositeLic(0));
+        }
+        else if (pu.cs->sps->getUseMergeOppositeLic())
+        {
+          m_BinEncoder.encodeBin(pu.mergeOppositeLic, Ctx::MergeFlagOppositeLic(0));
+        }
+      }
+#endif
       merge_idx(pu);
     }
   }
@@ -4826,6 +4845,12 @@ void CABACWriter::merge_idx( const PredictionUnit& pu )
     }
 #endif
     int numCandminus1 = int( pu.cs->picHeader->getMaxNumAffineMergeCand() ) - 1;
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+    if (pu.affineOppositeLic)
+    {
+      numCandminus1 = int(pu.cs->picHeader->getMaxNumAffineOppositeLicMergeCand()) - 1;
+    }
+#endif
     if ( numCandminus1 > 0 )
     {
 #if JVET_AA0128_AFFINE_MERGE_CTX_INC
@@ -5142,6 +5167,17 @@ void CABACWriter::merge_idx( const PredictionUnit& pu )
 #endif
     else
       numCandminus1 = int(pu.cs->sps->getMaxNumMergeCand()) - 1;
+
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+    if (pu.mergeOppositeLic)
+    {
+      numCandminus1 = int(pu.cs->sps->getMaxNumOppositeLicMergeCand()) - 1;
+    }
+    else if (pu.tmMergeFlagOppositeLic)
+    {
+      numCandminus1 = int(pu.cs->sps->getMaxNumTMOppositeLicMergeCand()) - 1;
+    }
+#endif
   if( numCandminus1 > 0 )
   {
 #if TM_MRG || (JVET_Z0084_IBC_TM && IBC_TM_MRG)
@@ -9427,8 +9463,24 @@ void CABACWriter::cu_lic_flag(const CodingUnit& cu)
 {
   if (CU::isLICFlagPresent(cu))
   {
+#if JVET_AG0276_LIC_SLOPE_ADJUST
+    unsigned ctxId = DeriveCtx::CtxLicFlag( cu );
+    m_BinEncoder.encodeBin(cu.licFlag ? 1 : 0, Ctx::LICFlag(ctxId));
+#else
     m_BinEncoder.encodeBin(cu.licFlag ? 1 : 0, Ctx::LICFlag(0));
+#endif
     DTRACE(g_trace_ctx, D_SYNTAX, "cu_lic_flag() lic_flag=%d\n", cu.licFlag ? 1 : 0);
+#if JVET_AG0276_LIC_SLOPE_ADJUST
+    if (cu.licFlag && CU::isLicSlopeAllowed(cu) && cu.firstPU->interDir != 3)
+    {
+      int delta = cu.licDelta;
+      m_BinEncoder.encodeBin( delta != 0 ? 1 : 0, Ctx::LicDelta(0) );
+      if ( delta )
+      {
+        m_BinEncoder.encodeBin( delta < 0 ? 1 : 0, Ctx::LicDelta(1) );
+      }
+    }
+#endif
   }
 }
 #endif
diff --git a/source/Lib/EncoderLib/EncCfg.h b/source/Lib/EncoderLib/EncCfg.h
index 53dafb6bc..178b89130 100644
--- a/source/Lib/EncoderLib/EncCfg.h
+++ b/source/Lib/EncoderLib/EncCfg.h
@@ -414,6 +414,9 @@ protected:
   bool      m_AffineType;
 #if JVET_AF0163_TM_SUBBLOCK_REFINEMENT
   bool      m_useAffineTM; 
+#if JVET_AG0276_NLIC
+  bool      m_useAffAltLMTM;
+#endif
 #endif
 #if JVET_AG0135_AFFINE_CIIP
   bool      m_useCiipAffine;
@@ -455,6 +458,15 @@ protected:
   bool      m_BIO;
 #if JVET_W0090_ARMC_TM
   bool      m_AML;
+#if JVET_AG0276_NLIC
+  bool      m_altLM;
+  bool      m_affAltLM;
+#endif
+#endif
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+  bool      m_mergeOppositeLic;
+  bool      m_mergeTMOppositeLic;
+  bool      m_mergeAffOppositeLic;
 #endif
 #if JVET_AA0093_REFINED_MOTION_FOR_ARMC
   bool      m_armcRefinedMotion;
@@ -905,10 +917,16 @@ protected:
   WeightedPredictionMethod m_weightedPredictionMethod;
   uint32_t      m_log2ParallelMergeLevelMinus2;       ///< Parallel merge estimation region
   uint32_t      m_maxNumMergeCand;                    ///< Maximum number of merge candidates
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+  uint32_t      m_maxNumOppositeLicMergeCand;         ///< Maximum number of merge candidates with opposite LIC flag
+#endif
 #if JVET_X0049_ADAPT_DMVR
   uint32_t      m_maxNumBMMergeCand;                  ///< Maximum number of BM merge candidates
 #endif
   uint32_t      m_maxNumAffineMergeCand;              ///< Maximum number of affine merge candidates
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+  uint32_t      m_maxNumAffineOppositeLicMergeCand;   ///< Maximum number of affine merge candidates with opposite LIC flag
+#endif
   uint32_t      m_maxNumGeoCand;
 #if JVET_AG0164_AFFINE_GPM
   uint32_t      m_maxNumGpmAffCand;
@@ -1052,6 +1070,9 @@ protected:
   bool        m_fastLICAffine;
   bool        m_fastLICBcw;
 #endif
+#if JVET_AG0276_LIC_SLOPE_ADJUST
+  bool        m_licSlopeAdjust;
+#endif
 #endif
 
 #if JVET_O0756_CALCULATE_HDRMETRICS
@@ -1521,6 +1542,10 @@ public:
 #if JVET_AF0163_TM_SUBBLOCK_REFINEMENT
   void      setUseAffineTM( bool b )                         { m_useAffineTM = b; }
   bool      getUseAffineTM()                           const { return  m_useAffineTM; }
+#if JVET_AG0276_NLIC
+  void      setUseAffAltLMTM( bool b )                       { m_useAffAltLMTM = b; }
+  bool      getUseAffAltLMTM()                         const { return  m_useAffAltLMTM; }
+#endif
 #endif
 #if JVET_AG0135_AFFINE_CIIP
   void      setUseCIIPAffine(bool b)                         { m_useCiipAffine = b; }
@@ -1626,6 +1651,20 @@ public:
 #if JVET_W0090_ARMC_TM
   void      setAML(bool b)                                   { m_AML = b; }
   bool      getAML()                                   const { return m_AML; }
+#if JVET_AG0276_NLIC
+  void      setAltLM(bool b)                                 { m_altLM = b; }
+  bool      getAltLM()                                 const { return m_altLM; }
+  void      setAffAltLM(bool b)                              { m_affAltLM = b; }
+  bool      getAffAltLM()                              const { return m_affAltLM; }
+#endif
+#endif
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+  void      setMergeOppositeLic( bool b )                    { m_mergeOppositeLic = b; }
+  bool      setMergeOppositeLic()                      const { return m_mergeOppositeLic; }
+  void      setMergeTMOppositeLic( bool b )                  { m_mergeTMOppositeLic = b; }
+  bool      setMergeTMOppositeLic()                    const { return m_mergeTMOppositeLic; }
+  void      setMergeAffOppositeLic( bool b )                 { m_mergeAffOppositeLic = b; }
+  bool      setMergeAffOppositeLic()                   const { return m_mergeAffOppositeLic; }
 #endif
 #if JVET_AA0093_REFINED_MOTION_FOR_ARMC
   void      setArmcRefinedMotion(bool b)                     { m_armcRefinedMotion = b; }
@@ -2503,12 +2542,20 @@ public:
   uint32_t     getLog2ParallelMergeLevelMinus2()                     { return m_log2ParallelMergeLevelMinus2; }
   void         setMaxNumMergeCand                ( uint32_t u )          { m_maxNumMergeCand = u;      }
   uint32_t         getMaxNumMergeCand                ()                  { return m_maxNumMergeCand;   }
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+  void         setMaxNumOppositeLicMergeCand( uint32_t u )           { m_maxNumOppositeLicMergeCand = u; }
+  uint32_t     getMaxNumOppositeLicMergeCand()                       { return m_maxNumOppositeLicMergeCand; }
+#endif
 #if JVET_X0049_ADAPT_DMVR
   void         setMaxNumBMMergeCand              ( uint32_t u )          { m_maxNumBMMergeCand = u;      }
   uint32_t         getMaxNumBMMergeCand              ()                  { return m_maxNumBMMergeCand;   }
 #endif
   void         setMaxNumAffineMergeCand          ( uint32_t u )      { m_maxNumAffineMergeCand = u;    }
   uint32_t     getMaxNumAffineMergeCand          ()                  { return m_maxNumAffineMergeCand; }
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+  void         setMaxNumAffineOppositeLicMergeCand( uint32_t u )     { m_maxNumAffineOppositeLicMergeCand = u; }
+  uint32_t     getMaxNumAffineOppositeLicMergeCand()                 { return m_maxNumAffineOppositeLicMergeCand; }
+#endif
   void         setMaxNumGeoCand                  ( uint32_t u )      { m_maxNumGeoCand = u;    }
   uint32_t     getMaxNumGeoCand                  ()                  { return m_maxNumGeoCand; }
 #if JVET_AG0164_AFFINE_GPM
@@ -2739,6 +2786,10 @@ public:
   void        setFastLicBcw( bool b )                           { m_fastLICBcw = b; }
   bool        getFastLicBcw()                                   const { return m_fastLICBcw; }
 #endif
+#if JVET_AG0276_LIC_SLOPE_ADJUST
+  void         setUseLicSlopeAdjust( bool u )                         { m_licSlopeAdjust = u; }
+  bool         getUseLicSlopeAdjust()                           const { return m_licSlopeAdjust; }
+#endif
 #endif
 
 #if JVET_O0756_CALCULATE_HDRMETRICS
diff --git a/source/Lib/EncoderLib/EncCu.cpp b/source/Lib/EncoderLib/EncCu.cpp
index 3c6117c6f..9587edc24 100644
--- a/source/Lib/EncoderLib/EncCu.cpp
+++ b/source/Lib/EncoderLib/EncCu.cpp
@@ -3805,6 +3805,13 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
   MergeCtx mergeCtxCIIPtmp;
 #endif
 #endif
+#if JVET_AG0276_NLIC
+  MergeCtx mergeOrgCtx;
+#endif
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+  MergeCtx mergeCtxOppositeLic;
+  mergeCtxOppositeLic.numValidMergeCand = 0;
+#endif
 #if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
   uint32_t               mmvdLUT[MMVD_ADD_NUM];
 #endif
@@ -3844,12 +3851,20 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
   AffineMergeCtx affineRMVFCtx;
   AffineMergeCtx affineRMVFOriCtx;
 #endif
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+  AffineMergeCtx affineMergeCtxOppositeLic;
+  affineMergeCtxOppositeLic.numValidMergeCand = 0;
+#endif
 #if JVET_W0090_ARMC_TM
   AffineMergeCtx affineMergeCtxTmp;
 #endif
   MergeCtx mrgCtx;
 #if TM_MRG
   MergeCtx tmMrgCtx;
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+  MergeCtx tmMrgCtxOppositeLic;
+  tmMrgCtxOppositeLic.numValidMergeCand = 0;
+#endif
 #if JVET_X0141_CIIP_TIMD_TM
   MergeCtx ciipTmMrgCtx;
 #endif
@@ -3876,7 +3891,13 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
     for (int i = 0; i < SUB_TMVP_NUM; i++)
     {
       mergeCtx.subPuMvpMiBuf[i] = MotionBuf(m_subPuMiBuf[i], bufSize);
+#if JVET_AG0276_NLIC
+      mergeOrgCtx.subPuMvpMiBuf[i] = MotionBuf(m_subPuMiBuf[i], bufSize);
+#endif
       mrgCtx.subPuMvpMiBuf[i] = MotionBuf(m_subPuMiBuf[i], bufSize);
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+      mergeCtxOppositeLic.subPuMvpMiBuf[i] = MotionBuf(m_subPuMiBuf[i], bufSize);
+#endif
     }
 #else
     mergeCtx.subPuMvpMiBuf = MotionBuf(m_subPuMiBuf, bufSize);
@@ -3888,6 +3909,9 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
     for (int i = 0; i < SUB_TMVP_NUM; i++)
     {
       tmMrgCtx.subPuMvpMiBuf[i] = MotionBuf(m_subPuMiBuf[i], bufSize);
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+      tmMrgCtxOppositeLic.subPuMvpMiBuf[i] = MotionBuf(m_subPuMiBuf[i], bufSize);
+#endif
 #if JVET_X0141_CIIP_TIMD_TM
       ciipTmMrgCtx.subPuMvpMiBuf[i] = MotionBuf(m_subPuMiBuf[i], bufSize);
 #endif
@@ -3910,12 +3934,18 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
 
 #if MULTI_PASS_DMVR
   bool applyBDMVR[MRG_MAX_NUM_CANDS] = { false };
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+  bool applyBDMVROppositeLic[MRG_MAX_NUM_CANDS] = { false };
+#endif
 #if JVET_AF0057
   bool dmvrImpreciseMv[MRG_MAX_NUM_CANDS] = { false };
 #endif
 #if TM_MRG && MERGE_ENC_OPT
 #if JVET_AA0093_REFINED_MOTION_FOR_ARMC
   bool applyBDMVR4TM[TM_MRG_MAX_NUM_INIT_CANDS] = { false };
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+  bool applyBDMVR4TMOppositeLic[TM_MRG_MAX_NUM_INIT_CANDS] = { false };
+#endif
 #else
   bool applyBDMVR4TM[TM_MRG_MAX_NUM_CANDS] = { false };
 #endif
@@ -3937,6 +3967,10 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
 #endif
   setMergeBestSATDCost( MAX_DOUBLE );
 
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+  bool hasOppositelicMrg = false;
+  bool hasOppositelicAff = false;
+#endif
   {
     // first get merge candidates
     CodingUnit cu( tempCS->area );
@@ -3951,6 +3985,12 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
     PredictionUnit pu( tempCS->area );
     pu.cu = &cu;
     pu.cs = tempCS;
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+    hasOppositelicMrg = PU::hasOppositeLICFlag(pu);
+    pu.cu->affine = true;
+    hasOppositelicAff = PU::hasOppositeLICFlag(pu);
+    pu.cu->affine = false;
+#endif
 #if JVET_AF0057
     bool enableVisualCheck = false;
     if (((m_pcEncCfg->getFrameRate() <= DMVR_ENC_SELECT_FRAME_RATE_THR) || !(m_pcEncCfg->getDMVREncMvSelectDisableHighestTemporalLayer() && (pu.cu->slice->getTLayer() == (pu.cu->slice->getSPS()->getMaxTLayers() - 1))))
@@ -4066,6 +4106,19 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
       m_pcInterSearch->adjustMergeCandidatesLicFlag(pu, mergeCtx);
     }
 #endif
+#if JVET_AG0276_NLIC
+    mergeOrgCtx = mergeCtx;
+#endif
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+    if (hasOppositelicMrg && pu.cs->sps->getUseMergeOppositeLic())
+    {
+      mergeCtxOppositeLic = mergeCtx;
+      for (int i = 0; i < mergeCtx.numValidMergeCand; i++)
+      {
+        mergeCtxOppositeLic.licFlags[i] = !mergeCtx.licFlags[i];
+      }
+    }
+#endif
 #if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM
     if (sps.getUseAML()
 #if JVET_AE0174_NONINTER_TM_TOOLS_CONTROL
@@ -4077,6 +4130,9 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
       if (!sps.getUseTmvpNmvpReordering())
       {
         m_pcInterSearch->adjustInterMergeCandidates(pu, mergeCtx);
+#if JVET_AG0276_NLIC
+        mergeOrgCtx = mergeCtx;
+#endif
       }
       else
 #endif
@@ -4086,6 +4142,37 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
         m_pcInterSearch->adjustMergeCandidates(pu, mergeCtx, pu.cs->sps->getMaxNumMergeCand());
 #else
         m_pcInterSearch->adjustMergeCandidatesInOneCandidateGroup(pu, mergeCtx, pu.cs->sps->getMaxNumMergeCand());
+#endif
+#if JVET_AG0276_NLIC
+        if (pu.cs->sps->getUseAltLM() && !CU::isTLCond(*pu.cu))
+        {
+          AltLMMergeCtx altLMMrgCtx;
+          PU::getAltMergeCandidates(pu, altLMMrgCtx);
+          m_pcInterSearch->adjustMergeCandidates(pu, mergeOrgCtx, altLMMrgCtx, pu.cs->sps->getMaxNumMergeCand());
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+          if (hasOppositelicMrg && pu.cs->sps->getUseMergeOppositeLic())
+          {
+            AltLMMergeCtx altLMBRMrgCtx;
+            PU::getAltBRMergeCandidates(pu, altLMBRMrgCtx);
+            m_pcInterSearch->adjustMergeCandidates(pu, mergeCtxOppositeLic, altLMBRMrgCtx, pu.cs->sps->getMaxNumMergeCand());
+          }
+#endif
+        }
+        else
+        {
+          mergeOrgCtx = mergeCtx;
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+          if (hasOppositelicMrg && pu.cs->sps->getUseMergeOppositeLic())
+          {
+            m_pcInterSearch->adjustMergeCandidates(pu, mergeCtxOppositeLic, pu.cs->sps->getMaxNumMergeCand());
+          }
+#endif
+        }
+#elif JVET_AG0276_LIC_FLAG_SIGNALING
+        if (hasOppositelicMrg && pu.cs->sps->getUseMergeOppositeLic())
+        {
+          m_pcInterSearch->adjustMergeCandidates(pu, mergeCtxOppositeLic, pu.cs->sps->getMaxNumMergeCand());
+        }
 #endif
       }
     }
@@ -4094,9 +4181,22 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
     {
       mergeCtx.numValidMergeCand = pu.cs->sps->getMaxNumMergeCand();
     }
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+    if (hasOppositelicMrg && pu.cs->sps->getUseMergeOppositeLic())
+    {
+      if (mergeCtxOppositeLic.numValidMergeCand > pu.cs->sps->getMaxNumOppositeLicMergeCand())
+      {
+        mergeCtxOppositeLic.numValidMergeCand = pu.cs->sps->getMaxNumOppositeLicMergeCand();
+      }
+    }
+#endif
     for (uint32_t ui = mergeCtx.numValidMergeCand; ui < NUM_MERGE_CANDS; ++ui)
     {
       mergeCtx.bcwIdx[ui] = BCW_DEFAULT;
+#if JVET_AG0276_NLIC
+      mergeCtx.altLMFlag[ui] = false;
+      mergeCtx.altLMParaNeighbours[ui].resetAltLinearModel();
+#endif
 #if INTER_LIC
       mergeCtx.licFlags[ui] = false;
 #endif
@@ -4108,6 +4208,48 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
       mergeCtx.addHypNeighbours[ui].clear();
 #endif
       mergeCtx.candCost[ui] = MAX_UINT64;
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+      mergeCtxOppositeLic.bcwIdx[ui] = BCW_DEFAULT;
+#if JVET_AG0276_NLIC
+      mergeCtxOppositeLic.altLMFlag[ui] = false;
+      mergeCtxOppositeLic.altLMParaNeighbours[ui].resetAltLinearModel();
+#endif
+#if INTER_LIC
+      mergeCtxOppositeLic.licFlags[ui] = false;
+#endif
+      mergeCtxOppositeLic.interDirNeighbours[ui] = 0;
+      mergeCtxOppositeLic.mvFieldNeighbours[(ui << 1)].refIdx = NOT_VALID;
+      mergeCtxOppositeLic.mvFieldNeighbours[(ui << 1) + 1].refIdx = NOT_VALID;
+      mergeCtxOppositeLic.useAltHpelIf[ui] = false;
+#if MULTI_HYP_PRED
+      mergeCtxOppositeLic.addHypNeighbours[ui].clear();
+#endif
+      mergeCtxOppositeLic.candCost[ui] = MAX_UINT64;
+#endif
+    }
+#endif
+
+#if JVET_AG0276_NLIC
+    if (mergeOrgCtx.numValidMergeCand != pu.cs->sps->getMaxNumMergeCand())
+    {
+      mergeOrgCtx.numValidMergeCand = pu.cs->sps->getMaxNumMergeCand();
+    }
+    for (uint32_t ui = mergeOrgCtx.numValidMergeCand; ui < NUM_MERGE_CANDS; ++ui)
+    {
+      mergeOrgCtx.bcwIdx[ui] = BCW_DEFAULT;
+      mergeOrgCtx.altLMFlag[ui] = false;
+      mergeOrgCtx.altLMParaNeighbours[ui].resetAltLinearModel();
+#if INTER_LIC
+      mergeOrgCtx.licFlags[ui] = false;
+#endif
+      mergeOrgCtx.interDirNeighbours[ui] = 0;
+      mergeOrgCtx.mvFieldNeighbours[(ui << 1)].refIdx = NOT_VALID;
+      mergeOrgCtx.mvFieldNeighbours[(ui << 1) + 1].refIdx = NOT_VALID;
+      mergeOrgCtx.useAltHpelIf[ui] = false;
+#if MULTI_HYP_PRED
+      mergeOrgCtx.addHypNeighbours[ui].clear();
+#endif
+      mergeOrgCtx.candCost[ui] = MAX_UINT64;
     }
 #endif
 
@@ -4123,6 +4265,10 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
       mrgCtxCiip.mvFieldNeighbours[(uiMergeCand << 1)] = mergeCtx.mvFieldNeighbours[(uiMergeCand << 1)];
       mrgCtxCiip.mvFieldNeighbours[(uiMergeCand << 1) + 1] = mergeCtx.mvFieldNeighbours[(uiMergeCand << 1) + 1];
       mrgCtxCiip.useAltHpelIf[uiMergeCand] = mergeCtx.useAltHpelIf[uiMergeCand];
+#if JVET_AG0276_NLIC
+      mrgCtxCiip.altLMFlag[uiMergeCand] = mergeCtx.altLMFlag[uiMergeCand];
+      mrgCtxCiip.altLMParaNeighbours[uiMergeCand] = mergeCtx.altLMParaNeighbours[uiMergeCand];
+#endif
 #if INTER_LIC 
       mrgCtxCiip.licFlags[uiMergeCand] = mergeCtx.licFlags[uiMergeCand];
 #endif
@@ -4139,6 +4285,19 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
       )
     {
       m_pcInterSearch->adjustMergeCandidatesBcwIdx(pu, mergeCtx);
+#if JVET_AG0276_NLIC
+      m_pcInterSearch->adjustMergeCandidatesBcwIdx(pu, mergeOrgCtx);
+      MergeCtx mergeCtxTemp;
+      mergeCtxTemp = mergeCtx;
+      mergeCtx = mergeOrgCtx;
+      mergeOrgCtx = mergeCtxTemp;
+#endif
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+      if (hasOppositelicMrg && pu.cs->sps->getUseMergeOppositeLic())
+      {
+        m_pcInterSearch->adjustMergeCandidatesBcwIdx(pu, mergeCtxOppositeLic);
+      }
+#endif
     }
 #endif
     PU::getInterMergeCandidates(pu, mergeCtxtmp, 0);
@@ -4198,6 +4357,7 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
 #if JVET_AG0135_AFFINE_CIIP
       ciipTmMrgCtx = mergeCtxCIIPtmp;
       ciipTmMrgCtx.numValidMergeCand = int(pu.cs->sps->getMaxNumCiipTMMergeCand());
+#if !(JVET_AG0276_LIC_FLAG_SIGNALING || JVET_AG0276_LIC_BDOF_BDMVR || JVET_AG0276_NLIC)
       memcpy(ciipTmMrgCtx.bcwIdx, mergeCtxCIIPtmp.bcwIdx, CIIP_TM_MRG_MAX_NUM_CANDS * sizeof(uint8_t));
       memcpy(ciipTmMrgCtx.interDirNeighbours, mergeCtxCIIPtmp.interDirNeighbours, CIIP_TM_MRG_MAX_NUM_CANDS * sizeof(unsigned char));
       memcpy(ciipTmMrgCtx.mvFieldNeighbours, mergeCtxCIIPtmp.mvFieldNeighbours, (CIIP_TM_MRG_MAX_NUM_CANDS << 1) * sizeof(MvField));
@@ -4208,13 +4368,19 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
 #if MULTI_HYP_PRED
       memcpy(ciipTmMrgCtx.addHypNeighbours, mergeCtxCIIPtmp.addHypNeighbours, CIIP_TM_MRG_MAX_NUM_CANDS * sizeof(MultiHypVec));
 #endif
+#endif
 #else
       ciipTmMrgCtx = mergeCtxtmp;
       ciipTmMrgCtx.numValidMergeCand = int(pu.cs->sps->getMaxNumCiipTMMergeCand());
+#if !(JVET_AG0276_LIC_FLAG_SIGNALING || JVET_AG0276_LIC_BDOF_BDMVR || JVET_AG0276_NLIC)
       memcpy(ciipTmMrgCtx.bcwIdx, mergeCtxtmp.bcwIdx, CIIP_TM_MRG_MAX_NUM_CANDS * sizeof(uint8_t));
       memcpy(ciipTmMrgCtx.interDirNeighbours, mergeCtxtmp.interDirNeighbours, CIIP_TM_MRG_MAX_NUM_CANDS * sizeof(unsigned char));
       memcpy(ciipTmMrgCtx.mvFieldNeighbours, mergeCtxtmp.mvFieldNeighbours, (CIIP_TM_MRG_MAX_NUM_CANDS << 1) * sizeof(MvField));
       memcpy(ciipTmMrgCtx.useAltHpelIf, mergeCtxtmp.useAltHpelIf, CIIP_TM_MRG_MAX_NUM_CANDS * sizeof(bool));
+#if JVET_AG0276_NLIC
+      memcpy(ciipTmMrgCtx.altLMFlag, mergeCtxtmp.altLMFlag, CIIP_TM_MRG_MAX_NUM_CANDS * sizeof(bool));
+      memcpy(ciipTmMrgCtx.altLMParaNeighbours, mergeCtxtmp.altLMParaNeighbours, CIIP_TM_MRG_MAX_NUM_CANDS * sizeof(AltLMInterUnit));
+#endif
 #if INTER_LIC
       memcpy(ciipTmMrgCtx.licFlags, mergeCtxtmp.licFlags, CIIP_TM_MRG_MAX_NUM_CANDS * sizeof(bool));
 #endif
@@ -4222,9 +4388,11 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
       memcpy(ciipTmMrgCtx.addHypNeighbours, mergeCtxtmp.addHypNeighbours, CIIP_TM_MRG_MAX_NUM_CANDS * sizeof(MultiHypVec));
 #endif
 #endif
+#endif
 #else
       ciipTmMrgCtx = mergeCtx;
       ciipTmMrgCtx.numValidMergeCand = int(pu.cs->sps->getMaxNumCiipTMMergeCand());
+#if !(JVET_AG0276_LIC_FLAG_SIGNALING || JVET_AG0276_LIC_BDOF_BDMVR || JVET_AG0276_NLIC)
       memcpy(ciipTmMrgCtx.bcwIdx, mergeCtx.bcwIdx, CIIP_TM_MRG_MAX_NUM_CANDS * sizeof(uint8_t));
       memcpy(ciipTmMrgCtx.interDirNeighbours, mergeCtx.interDirNeighbours, CIIP_TM_MRG_MAX_NUM_CANDS * sizeof(unsigned char));
       memcpy(ciipTmMrgCtx.mvFieldNeighbours, mergeCtx.mvFieldNeighbours, (CIIP_TM_MRG_MAX_NUM_CANDS << 1) * sizeof(MvField));
@@ -4235,6 +4403,7 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
 #if MULTI_HYP_PRED
       memcpy(ciipTmMrgCtx.addHypNeighbours, mergeCtx.addHypNeighbours, CIIP_TM_MRG_MAX_NUM_CANDS * sizeof(MultiHypVec));
 #endif
+#endif
 #endif
 
       for (uint32_t uiMergeCand = 0; uiMergeCand < ciipTmMrgCtx.numValidMergeCand; uiMergeCand++)
@@ -4423,6 +4592,16 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
         m_pcInterSearch->adjustMergeCandidatesLicFlag(pu, tmMrgCtx);
       }
 #endif
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+      if (hasOppositelicMrg && pu.cs->sps->getUseTMMergeOppositeLic())
+      {
+        tmMrgCtxOppositeLic = tmMrgCtx;
+        for (int i = 0; i < tmMrgCtxOppositeLic.numValidMergeCand; i++)
+        {
+          tmMrgCtxOppositeLic.licFlags[i] = !tmMrgCtx.licFlags[i];
+        }
+      }
+#endif
 #if JVET_W0090_ARMC_TM
 #if JVET_AA0093_REFINED_MOTION_FOR_ARMC
       bool tmMergeRefinedMotion = PU::isArmcRefinedMotionEnabled(pu, 2);
@@ -4444,6 +4623,20 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
           m_pcInterSearch->adjustInterMergeCandidates(pu, tmMrgCtx);
 #if JVET_AB0079_TM_BCW_MRG
           m_pcInterSearch->adjustMergeCandidatesBcwIdx(pu, tmMrgCtx);
+#endif
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+          if (hasOppositelicMrg && pu.cs->sps->getUseTMMergeOppositeLic())
+          {
+#if JVET_AA0093_REFINED_MOTION_FOR_ARMC
+            if (!tmMergeRefinedMotion)
+#endif
+            {
+              m_pcInterSearch->adjustInterMergeCandidates(pu, tmMrgCtxOppositeLic);
+            }
+#if JVET_AB0079_TM_BCW_MRG
+            m_pcInterSearch->adjustMergeCandidatesBcwIdx(pu, tmMrgCtxOppositeLic);
+#endif
+          }
 #endif
         }
         else
@@ -4466,12 +4659,43 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
             }
             m_pcInterSearch->adjustMergeCandidatesBcwIdx(pu, tmMrgCtx);
           }
+#endif
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+          if (hasOppositelicMrg && pu.cs->sps->getUseTMMergeOppositeLic())
+          {
+#if JVET_Z0102_NO_ARMC_FOR_ZERO_CAND 
+            m_pcInterSearch->adjustMergeCandidates(pu, tmMrgCtxOppositeLic, pu.cs->sps->getMaxNumTMMergeCand());
+#else
+            m_pcInterSearch->adjustMergeCandidatesInOneCandidateGroup(pu, tmMrgCtx, pu.cs->sps->getMaxNumTMMergeCand());
+#endif
+#if JVET_AB0079_TM_BCW_MRG
+#if JVET_AA0093_REFINED_MOTION_FOR_ARMC
+            if (!tmMergeRefinedMotion)
+#endif
+            {
+              if (tmMrgCtxOppositeLic.numValidMergeCand > pu.cs->sps->getMaxNumTMOppositeLicMergeCand())
+              {
+                tmMrgCtxOppositeLic.numValidMergeCand = pu.cs->sps->getMaxNumTMOppositeLicMergeCand();
+              }
+              m_pcInterSearch->adjustMergeCandidatesBcwIdx(pu, tmMrgCtxOppositeLic);
+            }
+#endif
+          }
 #endif
         }
         if (tmMrgCtx.numValidMergeCand > pu.cs->sps->getMaxNumTMMergeCand())
         {
           tmMrgCtx.numValidMergeCand = pu.cs->sps->getMaxNumTMMergeCand();
         }
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+        if (hasOppositelicMrg && pu.cs->sps->getUseTMMergeOppositeLic())
+        {
+          if (tmMrgCtxOppositeLic.numValidMergeCand > pu.cs->sps->getMaxNumTMOppositeLicMergeCand())
+          {
+            tmMrgCtxOppositeLic.numValidMergeCand = pu.cs->sps->getMaxNumTMOppositeLicMergeCand();
+          }
+        }
+#endif
 #else
 #if JVET_AA0093_REFINED_MOTION_FOR_ARMC
         if (!tmMergeRefinedMotion)
@@ -4486,6 +4710,10 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
         for (uint32_t ui = tmMrgCtx.numValidMergeCand; ui < NUM_MERGE_CANDS; ++ui)
         {
           tmMrgCtx.bcwIdx[ui] = BCW_DEFAULT;
+#if JVET_AG0276_NLIC
+          tmMrgCtx.altLMFlag[ui] = false;
+          tmMrgCtx.altLMParaNeighbours[ui].resetAltLinearModel();
+#endif
 #if INTER_LIC
           tmMrgCtx.licFlags[ui] = false;
 #endif
@@ -4498,6 +4726,33 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
 #endif
           tmMrgCtx.candCost[ui] = MAX_UINT64;
         }
+#endif
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+#if JVET_AA0093_REFINED_MOTION_FOR_ARMC
+        if (tmMrgCtxOppositeLic.numCandToTestEnc > tmMrgCtxOppositeLic.numValidMergeCand)
+        {
+          tmMrgCtxOppositeLic.numCandToTestEnc = tmMrgCtxOppositeLic.numValidMergeCand;
+        }
+        for (uint32_t ui = tmMrgCtxOppositeLic.numValidMergeCand; ui < NUM_MERGE_CANDS; ++ui)
+        {
+          tmMrgCtxOppositeLic.bcwIdx[ui] = BCW_DEFAULT;
+#if JVET_AG0276_NLIC
+          tmMrgCtxOppositeLic.altLMFlag[ui] = false;
+          tmMrgCtxOppositeLic.altLMParaNeighbours[ui].resetAltLinearModel();
+#endif
+#if INTER_LIC
+          tmMrgCtxOppositeLic.licFlags[ui] = false;
+#endif
+          tmMrgCtxOppositeLic.interDirNeighbours[ui] = 0;
+          tmMrgCtxOppositeLic.mvFieldNeighbours[(ui << 1)].refIdx = NOT_VALID;
+          tmMrgCtxOppositeLic.mvFieldNeighbours[(ui << 1) + 1].refIdx = NOT_VALID;
+          tmMrgCtxOppositeLic.useAltHpelIf[ui] = false;
+#if MULTI_HYP_PRED
+          tmMrgCtxOppositeLic.addHypNeighbours[ui].clear();
+#endif
+          tmMrgCtxOppositeLic.candCost[ui] = MAX_UINT64;
+        }
+#endif
 #endif
       }
 #endif
@@ -4567,6 +4822,56 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
           tmMrgCtx.mvFieldNeighbours[2 * uiMergeCand    ].setMvField( Mv(), NOT_VALID );
         }
       }
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+      pu.tmMergeFlagOppositeLic = true;
+      for (uint32_t uiMergeCand = 0; uiMergeCand < tmMrgCtxOppositeLic.numValidMergeCand; uiMergeCand++)
+      {
+        tmMrgCtxOppositeLic.setMergeInfo(pu, uiMergeCand);
+#if MULTI_PASS_DMVR
+        applyBDMVR4TMOppositeLic[uiMergeCand] = PU::checkBDMVRCondition(pu);
+        if (applyBDMVR4TMOppositeLic[uiMergeCand])
+        {
+          pu.bdmvrRefine = true;
+          m_pcInterSearch->setBdmvrSubPuMvBuf(m_mvBufBDMVR4TMOPPOSITELIC[uiMergeCand << 1], m_mvBufBDMVR4TMOPPOSITELIC[(uiMergeCand << 1) + 1]);
+#if JVET_AA0093_REFINED_MOTION_FOR_ARMC
+          if (tmMergeRefinedMotion)
+          {
+            applyBDMVR4TMOppositeLic[uiMergeCand] = m_pcInterSearch->processBDMVR(pu, 1, tempCost);
+          }
+          else
+#endif
+            applyBDMVR4TMOppositeLic[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
+        tmMrgCtxOppositeLic.candCost[uiMergeCand] = tempCost[0];
+#endif
+        tmMrgCtxOppositeLic.interDirNeighbours[uiMergeCand] = pu.interDir;
+        tmMrgCtxOppositeLic.bcwIdx[uiMergeCand] = pu.cu->bcwIdx;
+        tmMrgCtxOppositeLic.mvFieldNeighbours[2 * uiMergeCand].setMvField(pu.mv[0], pu.refIdx[0]);
+        tmMrgCtxOppositeLic.mvFieldNeighbours[2 * uiMergeCand + 1].setMvField(pu.mv[1], pu.refIdx[1]);
+        if (pu.interDir == 1)
+        {
+          tmMrgCtxOppositeLic.mvFieldNeighbours[2 * uiMergeCand + 1].setMvField(Mv(), NOT_VALID);
+        }
+        if (pu.interDir == 2)
+        {
+          tmMrgCtxOppositeLic.mvFieldNeighbours[2 * uiMergeCand].setMvField(Mv(), NOT_VALID);
+        }
+      }
+      pu.tmMergeFlagOppositeLic = false;
+#endif
 #if JVET_AA0093_REFINED_MOTION_FOR_ARMC
       pu.reduceTplSize = false;
 #endif
@@ -4620,6 +4925,50 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
 #endif
         }
       }
+#endif
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+#if JVET_AA0093_REFINED_MOTION_FOR_ARMC
+      if (tmMergeRefinedMotion)
+      {
+        pu.tmMergeFlagOppositeLic = true;
+        m_pcInterSearch->adjustMergeCandidatesInOneCandidateGroup(pu, tmMrgCtxOppositeLic, applyBDMVR4TMOppositeLic, NULL, NULL, pu.cs->sps->getMaxNumTMMergeCand());
+#if JVET_AB0079_TM_BCW_MRG
+        m_pcInterSearch->adjustMergeCandidatesBcwIdx(pu, tmMrgCtxOppositeLic);
+#endif
+        pu.tmMergeFlag = true;
+        for (uint32_t uiMergeCand = 0; uiMergeCand < tmMrgCtxOppositeLic.numValidMergeCand; uiMergeCand++)
+        {
+          tmMrgCtxOppositeLic.setMergeInfo(pu, uiMergeCand);
+#if MULTI_PASS_DMVR
+          applyBDMVR4TMOppositeLic[uiMergeCand] = PU::checkBDMVRCondition(pu);
+          if (applyBDMVR4TMOppositeLic[uiMergeCand])
+          {
+            pu.bdmvrRefine = true;
+            m_pcInterSearch->setBdmvrSubPuMvBuf(m_mvBufBDMVR4TMOPPOSITELIC[uiMergeCand << 1], m_mvBufBDMVR4TMOPPOSITELIC[(uiMergeCand << 1) + 1]);
+            applyBDMVR4TMOppositeLic[uiMergeCand] = m_pcInterSearch->processBDMVR(pu);
+          }
+          else
+          {
+            m_pcInterSearch->deriveTMMv(pu);
+          }
+
+          tmMrgCtxOppositeLic.interDirNeighbours[uiMergeCand] = pu.interDir;
+          tmMrgCtxOppositeLic.bcwIdx[uiMergeCand] = pu.cu->bcwIdx;  // BCW may change, because bi may be reduced to uni by deriveTMMv(pu)
+          tmMrgCtxOppositeLic.mvFieldNeighbours[2 * uiMergeCand].setMvField(pu.mv[0], pu.refIdx[0]);
+          tmMrgCtxOppositeLic.mvFieldNeighbours[2 * uiMergeCand + 1].setMvField(pu.mv[1], pu.refIdx[1]);
+          if (pu.interDir == 1)
+          {
+            tmMrgCtxOppositeLic.mvFieldNeighbours[2 * uiMergeCand + 1].setMvField(Mv(), NOT_VALID);
+          }
+          if (pu.interDir == 2)
+          {
+            tmMrgCtxOppositeLic.mvFieldNeighbours[2 * uiMergeCand].setMvField(Mv(), NOT_VALID);
+          }
+#endif
+        }
+      }
+#endif
+      pu.tmMergeFlagOppositeLic = false;
 #endif
       pu.tmMergeFlag = false;
 #if MULTI_PASS_DMVR
@@ -4632,10 +4981,25 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
     {
       pu.regularMergeFlag = false;
       cu.affine = true;
+#if JVET_AG0276_NLIC
+      AltLMAffineMergeCtx altAffineRMVFCtx;
+      altAffineRMVFCtx.init();
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+      AltLMAffineMergeCtx altBRAffineRMVFCtx;
+      altBRAffineRMVFCtx.init();
+#endif
+#endif
 #if JVET_AD0182_AFFINE_DMVR_PLUS_EXTENSIONS
       checkaffBmMrg = PU::isAffBMMergeFlagCoded(pu);
       uint16_t addNumRMVF = 0;
-      PU::getRMVFAffineCand(pu, affineRMVFCtx, affineRMVFOriCtx, m_pcInterSearch, addNumRMVF);
+      PU::getRMVFAffineCand(pu, affineRMVFCtx, affineRMVFOriCtx, m_pcInterSearch, addNumRMVF
+#if JVET_AG0276_NLIC
+        , altAffineRMVFCtx
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+        , altBRAffineRMVFCtx
+#endif
+#endif
+      );
 #endif
       PU::getAffineMergeCand(pu, affineMergeCtx
 #if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION  
@@ -4650,6 +5014,51 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
         , addNumRMVF
 #endif
       );
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+      int cntAffOppositeLic = 0;
+      affineMergeCtxOppositeLic.numAffCandToTestEnc = 0;
+      affineMergeCtxOppositeLic.numValidMergeCand = 0;
+      if (hasOppositelicAff && pu.cs->sps->getUseAffMergeOppositeLic())
+      {
+        for (int i = 0; i < affineMergeCtx.numValidMergeCand; i++)
+        {
+          if (affineMergeCtx.mergeType[i] == MRG_TYPE_DEFAULT_N)
+          {
+            for (int mvNum = 0; mvNum < 3; mvNum++)
+            {
+              affineMergeCtxOppositeLic.mvFieldNeighbours[(cntAffOppositeLic << 1) + 0][mvNum] = affineMergeCtx.mvFieldNeighbours[(i << 1) + 0][mvNum];
+              affineMergeCtxOppositeLic.mvFieldNeighbours[(cntAffOppositeLic << 1) + 1][mvNum] = affineMergeCtx.mvFieldNeighbours[(i << 1) + 1][mvNum];
+            }
+            affineMergeCtxOppositeLic.interDirNeighbours[cntAffOppositeLic] = affineMergeCtx.interDirNeighbours[i];
+            affineMergeCtxOppositeLic.affineType[cntAffOppositeLic] = affineMergeCtx.affineType[i];
+            affineMergeCtxOppositeLic.mergeType[cntAffOppositeLic] = affineMergeCtx.mergeType[i];
+            affineMergeCtxOppositeLic.bcwIdx[cntAffOppositeLic] = affineMergeCtx.bcwIdx[i];
+#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION
+            affineMergeCtxOppositeLic.colIdx[cntAffOppositeLic] = affineMergeCtx.colIdx[i];
+#endif
+#if JVET_AG0276_NLIC
+            affineMergeCtxOppositeLic.altLMFlag[cntAffOppositeLic] = affineMergeCtx.altLMFlag[i];
+            affineMergeCtxOppositeLic.altLMParaNeighbours[cntAffOppositeLic] = affineMergeCtx.altLMParaNeighbours[i];
+#endif
+#if INTER_LIC                                                   
+            affineMergeCtxOppositeLic.licFlags[cntAffOppositeLic] = !affineMergeCtx.licFlags[i];
+#endif
+#if JVET_AD0193_ADAPTIVE_OBMC_CONTROL
+            affineMergeCtxOppositeLic.obmcFlags[cntAffOppositeLic] = affineMergeCtx.obmcFlags[i];
+#endif
+            affineMergeCtxOppositeLic.candCost[cntAffOppositeLic] = affineMergeCtx.candCost[i];
+            cntAffOppositeLic++;
+            affineMergeCtxOppositeLic.numValidMergeCand++;
+          }
+          else
+          {
+            continue;
+          }
+        }
+        affineMergeCtxOppositeLic.numAffCandToTestEnc = std::min(affineMergeCtxOppositeLic.numValidMergeCand, affineMergeCtx.numAffCandToTestEnc);
+        affineMergeCtxOppositeLic.maxNumMergeCand = affineMergeCtxOppositeLic.numValidMergeCand;
+      }
+#endif
 #if JVET_AD0182_AFFINE_DMVR_PLUS_EXTENSIONS
       if (checkaffBmMrg)
       {
@@ -4699,6 +5108,10 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
           cu.affineType = affineMergeCtxTmp.affineType[uiAffMergeCand];
           cu.bcwIdx = affineMergeCtxTmp.bcwIdx[uiAffMergeCand];
           pu.mmvdEncOptMode = 0;
+#if JVET_AG0276_NLIC
+          cu.altLMFlag = affineMergeCtxTmp.altLMFlag[uiAffMergeCand];
+          cu.altLMParaUnit = affineMergeCtxTmp.altLMParaNeighbours[uiAffMergeCand];
+#endif
 #if INTER_LIC
           cu.licFlag = affineMergeCtxTmp.licFlags[uiAffMergeCand];
 #endif
@@ -4713,7 +5126,11 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
           pu.mvAffi[REF_PIC_LIST_1][0] = affineMergeCtxTmp.mvFieldNeighbours[(uiAffMergeCand << 1) + 1][0].mv;
           pu.mvAffi[REF_PIC_LIST_1][1] = affineMergeCtxTmp.mvFieldNeighbours[(uiAffMergeCand << 1) + 1][1].mv;
           pu.mvAffi[REF_PIC_LIST_1][2] = affineMergeCtxTmp.mvFieldNeighbours[(uiAffMergeCand << 1) + 1][2].mv;
+#if JVET_AG0276_LIC_BDOF_BDMVR
+          if (PU::checkBDMVRCondition4Aff(pu))
+#else
           if (PU::checkBDMVRCondition(pu))
+#endif
           {
             if (PU::checkBDMVR4Affine(pu))
             {
@@ -4778,7 +5195,40 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
 #endif
         )
       {
+#if JVET_AG0276_NLIC
+        if (sps.getUseAffAltLM() && !CU::isTLCond(*pu.cu))
+        {
+          AltLMAffineMergeCtx altLMAffMrgCtx;
+          PU::getAltLMAffineMergeCand(pu, altLMAffMrgCtx);
+          m_pcInterSearch->adjustAffineMergeCandidates(pu, affineMergeCtx, altLMAffMrgCtx, altAffineRMVFCtx);
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+          if (hasOppositelicAff && pu.cs->sps->getUseAffMergeOppositeLic())
+          {
+            AltLMAffineMergeCtx altLMBRAffMrgCtx;
+            PU::getAltLMBRAffineMergeCand(pu, altLMBRAffMrgCtx);
+            m_pcInterSearch->adjustAffineMergeCandidates(pu, affineMergeCtxOppositeLic, altLMBRAffMrgCtx, altBRAffineRMVFCtx);
+          }
+#endif
+        }
+        else
+        {
+          m_pcInterSearch->adjustAffineMergeCandidates(pu, affineMergeCtx);
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+          if (hasOppositelicAff && pu.cs->sps->getUseAffMergeOppositeLic())
+          {
+            m_pcInterSearch->adjustAffineMergeCandidates(pu, affineMergeCtxOppositeLic);
+          }
+#endif
+        }
+#else
         m_pcInterSearch->adjustAffineMergeCandidates(pu, affineMergeCtx);
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+        if (hasOppolicAff && pu.cs->sps->getUseAffMergeOppositeLic())
+        {
+          m_pcInterSearch->adjustAffineMergeCandidates(pu, affineMergeCtxOppositeLic);
+        }
+#endif
+#endif
 #if JVET_AA0107_RMVF_AFFINE_MERGE_DERIVATION
         affineMergeCtx.numValidMergeCand = slice.getPicHeader()->getMaxNumAffineMergeCand();
         affineMergeCtx.maxNumMergeCand = slice.getPicHeader()->getMaxNumAffineMergeCand();
@@ -4788,6 +5238,13 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
         {
           m_pcInterSearch->adjustAffineMergeCandidates(pu, affineBMMergeCtx);
         }
+#endif
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+        if (hasOppositelicAff && pu.cs->sps->getUseAffMergeOppositeLic())
+        {
+          affineMergeCtxOppositeLic.numValidMergeCand = slice.getPicHeader()->getMaxNumAffineOppositeLicMergeCand();
+          affineMergeCtxOppositeLic.maxNumMergeCand = slice.getPicHeader()->getMaxNumAffineOppositeLicMergeCand();
+        }
 #endif
       }
 #endif
@@ -4844,6 +5301,41 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
           }
         }
       }
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+      if (hasOppositelicMrg && pu.cs->sps->getUseMergeOppositeLic())
+      {
+        pu.mergeOppositeLic = true;
+        cu.firstPU = &pu;
+        for (uint32_t uiMergeCand = 0; uiMergeCand < mergeCtxOppositeLic.numValidMergeCand; uiMergeCand++)
+        {
+          if (mergeCtxOppositeLic.interDirNeighbours[uiMergeCand] == 3)
+          {
+            mergeCtxOppositeLic.setMergeInfo(pu, uiMergeCand);
+            applyBDMVROppositeLic[uiMergeCand] = PU::checkBDMVRCondition(pu);
+
+            if (applyBDMVROppositeLic[uiMergeCand])
+            {
+              pu.bdmvrRefine = true;
+              m_pcInterSearch->setBdmvrSubPuMvBuf(m_mvBufBDMVR4OPPOSITELIC[uiMergeCand << 1], m_mvBufBDMVR4OPPOSITELIC[(uiMergeCand << 1) + 1]);
+
+              if (mergeCtxOppositeLic.xCheckSimilarMotion(pu.mergeIdx, PU::getBDMVRMvdThreshold(pu)))
+              {
+                for (int subPuIdx = 0; subPuIdx < MAX_NUM_SUBCU_DMVR; subPuIdx++)
+                {
+                  m_mvBufBDMVR4OPPOSITELIC[uiMergeCand << 1][subPuIdx] = pu.mv[0];
+                  m_mvBufBDMVR4OPPOSITELIC[(uiMergeCand << 1) + 1][subPuIdx] = pu.mv[1];
+                }
+              }
+              else
+              {
+                m_pcInterSearch->processBDMVR(pu);
+              }
+            }
+          }
+        }
+        pu.mergeOppositeLic = false;
+      }
+#endif
 #if JVET_AF0163_TM_SUBBLOCK_REFINEMENT
       int cnt = 0;
       int validNum = 0;
@@ -4871,6 +5363,35 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
         }
       }
 #endif
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+#if JVET_AF0163_TM_SUBBLOCK_REFINEMENT
+      int cntOppositeLic = 0;
+      int validNumOppositeLic = 0;
+      if (cu.cs->sps->getUseAffineTM()
+#if JVET_AE0174_NONINTER_TM_TOOLS_CONTROL
+        && sps.getTMToolsEnableFlag()
+#endif
+        && PU::checkAffineTMCondition(pu)
+        )
+      {
+        for (uint32_t uiAffMergeCand = 0; uiAffMergeCand < affineMergeCtxOppositeLic.numValidMergeCand; uiAffMergeCand++)
+        {
+          if (affineMergeCtxOppositeLic.mvFieldNeighbours[(uiAffMergeCand << 1) + 0][0].mv == Mv(0, 0) && affineMergeCtxOppositeLic.mvFieldNeighbours[(uiAffMergeCand << 1) + 1][0].mv == Mv(0, 0) &&
+            affineMergeCtxOppositeLic.mvFieldNeighbours[(uiAffMergeCand << 1) + 0][1].mv == Mv(0, 0) && affineMergeCtxOppositeLic.mvFieldNeighbours[(uiAffMergeCand << 1) + 1][1].mv == Mv(0, 0) &&
+            affineMergeCtxOppositeLic.mvFieldNeighbours[(uiAffMergeCand << 1) + 0][2].mv == Mv(0, 0) && affineMergeCtxOppositeLic.mvFieldNeighbours[(uiAffMergeCand << 1) + 1][2].mv == Mv(0, 0)
+            && affineMergeCtxOppositeLic.mergeType[uiAffMergeCand] != MRG_TYPE_SUBPU_ATMVP)
+          {
+            validNumOppositeLic = uiAffMergeCand;
+            break;
+          }
+          if (uiAffMergeCand == int(pu.cs->picHeader->getMaxNumAffineOppositeLicMergeCand()) - 1)
+          {
+            validNumOppositeLic = int(pu.cs->picHeader->getMaxNumAffineOppositeLicMergeCand());
+          }
+        }
+      }
+#endif
+#endif
 #if JVET_AB0112_AFFINE_DMVR
       if (affineMrgAvail
 #if JVET_AD0182_AFFINE_DMVR_PLUS_EXTENSIONS
@@ -4905,6 +5426,10 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
             cu.affineType = affineMergeCtx.affineType[uiAffMergeCand];
             cu.bcwIdx = affineMergeCtx.bcwIdx[uiAffMergeCand];
             pu.mmvdEncOptMode = 0;
+#if JVET_AG0276_NLIC
+            cu.altLMFlag = affineMergeCtx.altLMFlag[uiAffMergeCand];
+            cu.altLMParaUnit = affineMergeCtx.altLMParaNeighbours[uiAffMergeCand];
+#endif
 #if INTER_LIC
             cu.licFlag = affineMergeCtx.licFlags[uiAffMergeCand];
 #endif
@@ -4919,7 +5444,11 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
             pu.mvAffi[REF_PIC_LIST_1][0] = affineMergeCtx.mvFieldNeighbours[(uiAffMergeCand << 1) + 1][0].mv;
             pu.mvAffi[REF_PIC_LIST_1][1] = affineMergeCtx.mvFieldNeighbours[(uiAffMergeCand << 1) + 1][1].mv;
             pu.mvAffi[REF_PIC_LIST_1][2] = affineMergeCtx.mvFieldNeighbours[(uiAffMergeCand << 1) + 1][2].mv;
+#if JVET_AG0276_LIC_BDOF_BDMVR
+            if (PU::checkBDMVRCondition4Aff(pu))
+#else
             if(PU::checkBDMVRCondition(pu))
+#endif
             {
 #if !JVET_AC0144_AFFINE_DMVR_REGRESSION
                 // set merge information   
@@ -4996,6 +5525,10 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
           pu.mergeIdx = uiAffMergeCand;
           cu.affineType = affineBMMergeCtx.affineType[uiAffMergeCand];
           cu.bcwIdx = affineBMMergeCtx.bcwIdx[uiAffMergeCand];
+#if JVET_AG0276_NLIC
+          cu.altLMFlag = affineBMMergeCtx.altLMFlag[uiAffMergeCand];
+          cu.altLMParaUnit = affineBMMergeCtx.altLMParaNeighbours[uiAffMergeCand];
+#endif
 #if INTER_LIC
           cu.licFlag = affineBMMergeCtx.licFlags[uiAffMergeCand];
 #endif
@@ -5011,7 +5544,11 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
           pu.mvAffi[REF_PIC_LIST_1][1] = affineBMMergeCtx.mvFieldNeighbours[(uiAffMergeCand << 1) + 1][1].mv;
           pu.mvAffi[REF_PIC_LIST_1][2] = affineBMMergeCtx.mvFieldNeighbours[(uiAffMergeCand << 1) + 1][2].mv;
 
+#if JVET_AG0276_LIC_BDOF_BDMVR
+          if (PU::checkBDMVRCondition4Aff(pu))
+#else
           if (PU::checkBDMVRCondition(pu))
+#endif
           {
             m_pcInterSearch->processBDMVR4AdaptiveAffine(pu, refinedMvL0, refinedMvL1, affTypeL0, affTypeL1);
           
@@ -5063,6 +5600,10 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
 
           affineBMMergeL0.mergeType[uiAffMergeCand] = affineBMMergeCtx.mergeType[uiAffMergeCand];
           affineBMMergeL0.bcwIdx[uiAffMergeCand] = affineBMMergeCtx.bcwIdx[uiAffMergeCand];
+#if JVET_AG0276_NLIC
+          affineBMMergeL0.altLMFlag[uiAffMergeCand] = affineBMMergeCtx.altLMFlag[uiAffMergeCand];
+          affineBMMergeL0.altLMParaNeighbours[uiAffMergeCand] = affineBMMergeCtx.altLMParaNeighbours[uiAffMergeCand];
+#endif
 #if INTER_LIC
           affineBMMergeL0.licFlags[uiAffMergeCand] = affineBMMergeCtx.licFlags[uiAffMergeCand];
 #endif
@@ -5082,6 +5623,10 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
 
           affineBMMergeL1.mergeType[uiAffMergeCand] = affineBMMergeCtx.mergeType[uiAffMergeCand];
           affineBMMergeL1.bcwIdx[uiAffMergeCand] = affineBMMergeCtx.bcwIdx[uiAffMergeCand];
+#if JVET_AG0276_NLIC
+          affineBMMergeL1.altLMFlag[uiAffMergeCand] = affineBMMergeCtx.altLMFlag[uiAffMergeCand];
+          affineBMMergeL1.altLMParaNeighbours[uiAffMergeCand] = affineBMMergeCtx.altLMParaNeighbours[uiAffMergeCand];
+#endif
 #if INTER_LIC
           affineBMMergeL1.licFlags[uiAffMergeCand] = affineBMMergeCtx.licFlags[uiAffMergeCand];
 #endif
@@ -5092,6 +5637,114 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
         }
       }
 #endif
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+#if JVET_AB0112_AFFINE_DMVR
+      pu.affineOppositeLic = true;
+      if (affineMrgAvail
+#if JVET_AD0182_AFFINE_DMVR_PLUS_EXTENSIONS
+        && PU::checkBDMVR4Affine(pu)
+#endif
+        )
+      {
+#if JVET_AC0144_AFFINE_DMVR_REGRESSION
+        EAffineModel affType[AFFINE_MRG_MAX_NUM_CANDS];
+        Mv refinedAffineMv[AFFINE_MRG_MAX_NUM_CANDS << 1][3];
+        bool applyBDMVR4Affine[AFFINE_MRG_MAX_NUM_CANDS] = { false };
+#endif
+        for (uint32_t uiAffMergeCand = 0; uiAffMergeCand < affineMergeCtxOppositeLic.numValidMergeCand; uiAffMergeCand++)
+        {
+#if !JVET_AC0144_AFFINE_DMVR_REGRESSION
+          m_mvBufBDMVR4AFFINE[uiAffMergeCand << 1][0].setZero();
+          m_mvBufBDMVR4AFFINE[(uiAffMergeCand << 1) + 1][0].setZero();
+#endif
+          pu.bdmvrRefine = false;
+          if (affineMergeCtxOppositeLic.interDirNeighbours[uiAffMergeCand] == 3 && affineMergeCtxOppositeLic.mergeType[uiAffMergeCand] != MRG_TYPE_SUBPU_ATMVP)
+          {
+            pu.regularMergeFlag = false;
+            pu.mergeFlag = true;
+            pu.mmvdMergeFlag = false;
+            pu.cu->affine = true;
+            pu.interDir = affineMergeCtxOppositeLic.interDirNeighbours[uiAffMergeCand];
+            pu.cu->imv = 0;
+            pu.mergeType = affineMergeCtxOppositeLic.mergeType[uiAffMergeCand];
+            pu.mv[0].setZero();
+            pu.mv[1].setZero();
+            pu.mergeIdx = uiAffMergeCand;
+            cu.affineType = affineMergeCtxOppositeLic.affineType[uiAffMergeCand];
+            cu.bcwIdx = affineMergeCtxOppositeLic.bcwIdx[uiAffMergeCand];
+            pu.mmvdEncOptMode = 0;
+#if JVET_AG0276_NLIC
+            cu.altLMFlag = affineMergeCtxOppositeLic.altLMFlag[uiAffMergeCand];
+            cu.altLMParaUnit = affineMergeCtxOppositeLic.altLMParaNeighbours[uiAffMergeCand];
+#endif
+#if INTER_LIC
+            cu.licFlag = affineMergeCtxOppositeLic.licFlags[uiAffMergeCand];
+#endif
+#if JVET_AD0193_ADAPTIVE_OBMC_CONTROL
+            cu.obmcFlag = affineMergeCtxOppositeLic.obmcFlags[uiAffMergeCand];
+#endif
+            pu.refIdx[0] = affineMergeCtxOppositeLic.mvFieldNeighbours[(uiAffMergeCand << 1) + 0][0].refIdx;
+            pu.refIdx[1] = affineMergeCtxOppositeLic.mvFieldNeighbours[(uiAffMergeCand << 1) + 1][0].refIdx;
+            pu.mvAffi[REF_PIC_LIST_0][0] = affineMergeCtxOppositeLic.mvFieldNeighbours[(uiAffMergeCand << 1) + 0][0].mv;
+            pu.mvAffi[REF_PIC_LIST_0][1] = affineMergeCtxOppositeLic.mvFieldNeighbours[(uiAffMergeCand << 1) + 0][1].mv;
+            pu.mvAffi[REF_PIC_LIST_0][2] = affineMergeCtxOppositeLic.mvFieldNeighbours[(uiAffMergeCand << 1) + 0][2].mv;
+            pu.mvAffi[REF_PIC_LIST_1][0] = affineMergeCtxOppositeLic.mvFieldNeighbours[(uiAffMergeCand << 1) + 1][0].mv;
+            pu.mvAffi[REF_PIC_LIST_1][1] = affineMergeCtxOppositeLic.mvFieldNeighbours[(uiAffMergeCand << 1) + 1][1].mv;
+            pu.mvAffi[REF_PIC_LIST_1][2] = affineMergeCtxOppositeLic.mvFieldNeighbours[(uiAffMergeCand << 1) + 1][2].mv;
+#if JVET_AG0276_LIC_BDOF_BDMVR
+            if (PU::checkBDMVRCondition4Aff(pu))
+#else
+            if (PU::checkBDMVRCondition(pu))
+#endif
+            {
+#if !JVET_AC0144_AFFINE_DMVR_REGRESSION
+              // set merge information   
+              m_pcInterSearch->setBdmvrSubPuMvBuf(m_mvBufBDMVR4AFFINE[uiAffMergeCand << 1], m_mvBufBDMVR4AFFINE[(uiAffMergeCand << 1) + 1]);
+#endif
+              if (!affineMergeCtxOppositeLic.xCheckSimilarMotion(pu.mergeIdx, PU::getBDMVRMvdThreshold(pu)))
+              {
+                m_pcInterSearch->processBDMVR4Affine(pu);
+#if JVET_AC0144_AFFINE_DMVR_REGRESSION
+                refinedAffineMv[(uiAffMergeCand << 1) + 0][0] = pu.mvAffi[REF_PIC_LIST_0][0];
+                refinedAffineMv[(uiAffMergeCand << 1) + 0][1] = pu.mvAffi[REF_PIC_LIST_0][1];
+                refinedAffineMv[(uiAffMergeCand << 1) + 0][2] = pu.mvAffi[REF_PIC_LIST_0][2];
+                refinedAffineMv[(uiAffMergeCand << 1) + 1][0] = pu.mvAffi[REF_PIC_LIST_1][0];
+                refinedAffineMv[(uiAffMergeCand << 1) + 1][1] = pu.mvAffi[REF_PIC_LIST_1][1];
+                refinedAffineMv[(uiAffMergeCand << 1) + 1][2] = pu.mvAffi[REF_PIC_LIST_1][2];
+                affType[uiAffMergeCand] = (EAffineModel)pu.cu->affineType;
+                applyBDMVR4Affine[uiAffMergeCand] = true;
+#endif
+              }
+            }
+          }
+        }
+        for (uint32_t uiAffMergeCand = 0; uiAffMergeCand < affineMergeCtxOppositeLic.numValidMergeCand; uiAffMergeCand++)
+        {
+#if JVET_AC0144_AFFINE_DMVR_REGRESSION
+          if (!applyBDMVR4Affine[uiAffMergeCand])
+          {
+            continue;
+          }
+          affineMergeCtxOppositeLic.mvFieldNeighbours[(uiAffMergeCand << 1) + 0][0].mv = refinedAffineMv[(uiAffMergeCand << 1) + 0][0];
+          affineMergeCtxOppositeLic.mvFieldNeighbours[(uiAffMergeCand << 1) + 0][1].mv = refinedAffineMv[(uiAffMergeCand << 1) + 0][1];
+          affineMergeCtxOppositeLic.mvFieldNeighbours[(uiAffMergeCand << 1) + 0][2].mv = refinedAffineMv[(uiAffMergeCand << 1) + 0][2];
+          affineMergeCtxOppositeLic.mvFieldNeighbours[(uiAffMergeCand << 1) + 1][0].mv = refinedAffineMv[(uiAffMergeCand << 1) + 1][0];
+          affineMergeCtxOppositeLic.mvFieldNeighbours[(uiAffMergeCand << 1) + 1][1].mv = refinedAffineMv[(uiAffMergeCand << 1) + 1][1];
+          affineMergeCtxOppositeLic.mvFieldNeighbours[(uiAffMergeCand << 1) + 1][2].mv = refinedAffineMv[(uiAffMergeCand << 1) + 1][2];
+          affineMergeCtxOppositeLic.affineType[uiAffMergeCand] = affType[uiAffMergeCand];
+#else
+          affineMergeCtxOppositeLic.mvFieldNeighbours[(uiAffMergeCand << 1) + 0][0].mv += m_mvBufBDMVR4AFFINE[(uiAffMergeCand << 1) + 0][0];
+          affineMergeCtxOppositeLic.mvFieldNeighbours[(uiAffMergeCand << 1) + 0][1].mv += m_mvBufBDMVR4AFFINE[(uiAffMergeCand << 1) + 0][0];
+          affineMergeCtxOppositeLic.mvFieldNeighbours[(uiAffMergeCand << 1) + 0][2].mv += m_mvBufBDMVR4AFFINE[(uiAffMergeCand << 1) + 0][0];
+          affineMergeCtxOppositeLic.mvFieldNeighbours[(uiAffMergeCand << 1) + 1][0].mv += m_mvBufBDMVR4AFFINE[(uiAffMergeCand << 1) + 1][0];
+          affineMergeCtxOppositeLic.mvFieldNeighbours[(uiAffMergeCand << 1) + 1][1].mv += m_mvBufBDMVR4AFFINE[(uiAffMergeCand << 1) + 1][0];
+          affineMergeCtxOppositeLic.mvFieldNeighbours[(uiAffMergeCand << 1) + 1][2].mv += m_mvBufBDMVR4AFFINE[(uiAffMergeCand << 1) + 1][0];
+#endif
+        }
+      }
+      pu.affineOppositeLic = false;
+#endif
+#endif
 #endif
 #if JVET_AF0163_TM_SUBBLOCK_REFINEMENT 
       if (cu.cs->sps->getUseAffineTM() && affineMrgAvail
@@ -5109,16 +5762,28 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
             m_mvBufBDMVR4AFFINE[(uiAffMergeCand << 1) + 1][i].setZero();
           }
           pu.bdmvrRefine = false;
+#if JVET_AG0276_NLIC
+          if ((sps.getUseAffAltLMTM() || !affineMergeCtx.altLMFlag[uiAffMergeCand]) && affineMergeCtx.interDirNeighbours[uiAffMergeCand] != 3 && affineMergeCtx.mergeType[uiAffMergeCand] != MRG_TYPE_SUBPU_ATMVP)
+#else
           if (affineMergeCtx.interDirNeighbours[uiAffMergeCand] != 3 && affineMergeCtx.mergeType[uiAffMergeCand] != MRG_TYPE_SUBPU_ATMVP)
+#endif
           {
             int index = -1;
+#if JVET_AG0276_NLIC
+            if ((validNum + cnt) < affineMergeCtx.maxNumMergeCand && !affineMergeCtx.altLMFlag[uiAffMergeCand])
+#else
             if ((validNum + cnt) < affineMergeCtx.maxNumMergeCand)
+#endif
             {
               index = validNum + cnt;
               affineMergeCtx.interDirNeighbours[index] = affineMergeCtx.interDirNeighbours[uiAffMergeCand];
               affineMergeCtx.mergeType[index] = affineMergeCtx.mergeType[uiAffMergeCand];
               affineMergeCtx.affineType[index] = affineMergeCtx.affineType[uiAffMergeCand];
               affineMergeCtx.bcwIdx[index] = affineMergeCtx.bcwIdx[uiAffMergeCand];
+#if JVET_AG0276_NLIC
+              affineMergeCtx.altLMFlag[index] = affineMergeCtx.altLMFlag[uiAffMergeCand];
+              affineMergeCtx.altLMParaNeighbours[index] = affineMergeCtx.altLMParaNeighbours[uiAffMergeCand];
+#endif
 #if INTER_LIC
               affineMergeCtx.licFlags[index] = affineMergeCtx.licFlags[uiAffMergeCand];
 #endif
@@ -5148,6 +5813,10 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
             cu.affineType = affineMergeCtx.affineType[uiAffMergeCand];
             cu.bcwIdx = affineMergeCtx.bcwIdx[uiAffMergeCand];
             pu.mmvdEncOptMode = 0;
+#if JVET_AG0276_NLIC
+            pu.cu->altLMFlag = affineMergeCtx.altLMFlag[uiAffMergeCand];
+            pu.cu->altLMParaUnit = affineMergeCtx.altLMParaNeighbours[uiAffMergeCand];
+#endif
 #if INTER_LIC
             cu.licFlag = affineMergeCtx.licFlags[uiAffMergeCand];
 #endif
@@ -5164,7 +5833,13 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
             pu.mvAffi[REF_PIC_LIST_1][2] = affineMergeCtx.mvFieldNeighbours[(uiAffMergeCand << 1) + 1][2].mv;
 
             m_pcInterSearch->setBdmvrSubPuMvBuf(m_mvBufBDMVR4AFFINE[uiAffMergeCand << 1], m_mvBufBDMVR4AFFINE[(uiAffMergeCand << 1) + 1]);
+#if JVET_AG0276_NLIC
+            if ((!affineMergeCtx.altLMFlag[uiAffMergeCand] && !affineMergeCtx.xCheckSimilarMotion1(pu.mergeIdx, PU::getBDMVRMvdThreshold(pu), false)) ||
+                ( affineMergeCtx.altLMFlag[uiAffMergeCand] && !affineMergeCtx.xCheckSimilarMotion1(pu.mergeIdx, PU::getBDMVRMvdThreshold(pu), true) )
+               )
+#else
             if (!affineMergeCtx.xCheckSimilarMotion(pu.mergeIdx, PU::getBDMVRMvdThreshold(pu)))
+#endif
             {
               m_pcInterSearch->processTM4Affine(pu, affineMergeCtx, index, true);
             }
@@ -5181,6 +5856,118 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
         }
       }
 #endif
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+#if JVET_AF0163_TM_SUBBLOCK_REFINEMENT 
+      if (cu.cs->sps->getUseAffineTM() && affineMrgAvail
+#if JVET_AE0174_NONINTER_TM_TOOLS_CONTROL
+        && sps.getTMToolsEnableFlag()
+#endif
+        && PU::checkAffineTMCondition(pu)
+        )
+      {
+        for (uint32_t uiAffMergeCand = 0; uiAffMergeCand < validNumOppositeLic; uiAffMergeCand++)
+        {
+          for (int i = 0; i < 3; i++)
+          {
+            m_mvBufBDMVR4AFFINE[uiAffMergeCand << 1][i].setZero();
+            m_mvBufBDMVR4AFFINE[(uiAffMergeCand << 1) + 1][i].setZero();
+          }
+          pu.bdmvrRefine = false;
+#if JVET_AG0276_NLIC
+          if ((sps.getUseAffAltLMTM() || !affineMergeCtxOppositeLic.altLMFlag[uiAffMergeCand]) && affineMergeCtxOppositeLic.interDirNeighbours[uiAffMergeCand] != 3 && affineMergeCtxOppositeLic.mergeType[uiAffMergeCand] != MRG_TYPE_SUBPU_ATMVP)
+#else
+          if (affineMergeCtxOppositeLic.interDirNeighbours[uiAffMergeCand] != 3 && affineMergeCtxOppositeLic.mergeType[uiAffMergeCand] != MRG_TYPE_SUBPU_ATMVP)
+#endif
+          {
+            int index = -1;
+#if JVET_AG0276_NLIC
+            if ((validNumOppositeLic + cntOppositeLic) < affineMergeCtxOppositeLic.maxNumMergeCand && !affineMergeCtxOppositeLic.altLMFlag[uiAffMergeCand])
+#else
+            if ((validNumOppoLic + cntOppoLic) < affineMergeCtxOppoLic.maxNumMergeCand)
+#endif
+            {
+              index = validNumOppositeLic + cntOppositeLic;
+              affineMergeCtxOppositeLic.interDirNeighbours[index] = affineMergeCtxOppositeLic.interDirNeighbours[uiAffMergeCand];
+              affineMergeCtxOppositeLic.mergeType[index] = affineMergeCtxOppositeLic.mergeType[uiAffMergeCand];
+              affineMergeCtxOppositeLic.affineType[index] = affineMergeCtxOppositeLic.affineType[uiAffMergeCand];
+              affineMergeCtxOppositeLic.bcwIdx[index] = affineMergeCtxOppositeLic.bcwIdx[uiAffMergeCand];
+#if JVET_AG0276_NLIC
+              affineMergeCtxOppositeLic.altLMFlag[index] = affineMergeCtxOppositeLic.altLMFlag[uiAffMergeCand];
+              affineMergeCtxOppositeLic.altLMParaNeighbours[index] = affineMergeCtxOppositeLic.altLMParaNeighbours[uiAffMergeCand];
+#endif
+#if INTER_LIC
+              affineMergeCtxOppositeLic.licFlags[index] = affineMergeCtxOppositeLic.licFlags[uiAffMergeCand];
+#endif
+#if JVET_AD0193_ADAPTIVE_OBMC_CONTROL
+              affineMergeCtxOppositeLic.obmcFlags[index] = affineMergeCtxOppositeLic.obmcFlags[uiAffMergeCand];
+#endif
+              for (int i = 0; i < 2; i++)
+              {
+                for (int mvNum = 0; mvNum < 3; mvNum++)
+                {
+                  affineMergeCtxOppositeLic.mvFieldNeighbours[(index << 1) + i][mvNum].refIdx = affineMergeCtxOppositeLic.mvFieldNeighbours[(uiAffMergeCand << 1) + i][mvNum].refIdx;
+                  affineMergeCtxOppositeLic.mvFieldNeighbours[(index << 1) + i][mvNum].mv = affineMergeCtxOppositeLic.mvFieldNeighbours[(uiAffMergeCand << 1) + i][mvNum].mv;
+                }
+              }
+              cntOppositeLic++;
+            }
+            pu.regularMergeFlag = false;
+            pu.mergeFlag = true;
+            pu.mmvdMergeFlag = false;
+            pu.cu->affine = true;
+            pu.interDir = affineMergeCtxOppositeLic.interDirNeighbours[uiAffMergeCand];
+            pu.cu->imv = 0;
+            pu.mergeType = affineMergeCtxOppositeLic.mergeType[uiAffMergeCand];
+            pu.mv[0].setZero();
+            pu.mv[1].setZero();
+            pu.mergeIdx = uiAffMergeCand;
+            cu.affineType = affineMergeCtxOppositeLic.affineType[uiAffMergeCand];
+            cu.bcwIdx = affineMergeCtxOppositeLic.bcwIdx[uiAffMergeCand];
+            pu.mmvdEncOptMode = 0;
+#if JVET_AG0276_NLIC
+            pu.cu->altLMFlag = affineMergeCtxOppositeLic.altLMFlag[uiAffMergeCand];
+            pu.cu->altLMParaUnit = affineMergeCtxOppositeLic.altLMParaNeighbours[uiAffMergeCand];
+#endif
+#if INTER_LIC
+            cu.licFlag = affineMergeCtxOppositeLic.licFlags[uiAffMergeCand];
+#endif
+#if JVET_AD0193_ADAPTIVE_OBMC_CONTROL
+            cu.obmcFlag = affineMergeCtxOppositeLic.obmcFlags[uiAffMergeCand];
+#endif
+            pu.refIdx[0] = affineMergeCtxOppositeLic.mvFieldNeighbours[(uiAffMergeCand << 1) + 0][0].refIdx;
+            pu.refIdx[1] = affineMergeCtxOppositeLic.mvFieldNeighbours[(uiAffMergeCand << 1) + 1][0].refIdx;
+            pu.mvAffi[REF_PIC_LIST_0][0] = affineMergeCtxOppositeLic.mvFieldNeighbours[(uiAffMergeCand << 1) + 0][0].mv;
+            pu.mvAffi[REF_PIC_LIST_0][1] = affineMergeCtxOppositeLic.mvFieldNeighbours[(uiAffMergeCand << 1) + 0][1].mv;
+            pu.mvAffi[REF_PIC_LIST_0][2] = affineMergeCtxOppositeLic.mvFieldNeighbours[(uiAffMergeCand << 1) + 0][2].mv;
+            pu.mvAffi[REF_PIC_LIST_1][0] = affineMergeCtxOppositeLic.mvFieldNeighbours[(uiAffMergeCand << 1) + 1][0].mv;
+            pu.mvAffi[REF_PIC_LIST_1][1] = affineMergeCtxOppositeLic.mvFieldNeighbours[(uiAffMergeCand << 1) + 1][1].mv;
+            pu.mvAffi[REF_PIC_LIST_1][2] = affineMergeCtxOppositeLic.mvFieldNeighbours[(uiAffMergeCand << 1) + 1][2].mv;
+
+            m_pcInterSearch->setBdmvrSubPuMvBuf(m_mvBufBDMVR4AFFINE[uiAffMergeCand << 1], m_mvBufBDMVR4AFFINE[(uiAffMergeCand << 1) + 1]);
+#if JVET_AG0276_NLIC
+            if ((!affineMergeCtxOppositeLic.altLMFlag[uiAffMergeCand] && !affineMergeCtxOppositeLic.xCheckSimilarMotion1(pu.mergeIdx, PU::getBDMVRMvdThreshold(pu), false)) ||
+                ( affineMergeCtxOppositeLic.altLMFlag[uiAffMergeCand] && !affineMergeCtxOppositeLic.xCheckSimilarMotion1(pu.mergeIdx, PU::getBDMVRMvdThreshold(pu), true) )
+               )
+#else
+            if (!affineMergeCtxOppositeLic.xCheckSimilarMotion(pu.mergeIdx, PU::getBDMVRMvdThreshold(pu)))
+#endif
+            {
+              m_pcInterSearch->processTM4Affine(pu, affineMergeCtxOppositeLic, index, true);
+            }
+          }
+        }
+        for (uint32_t uiAffMergeCand = 0; uiAffMergeCand < validNumOppositeLic; uiAffMergeCand++)
+        {
+          affineMergeCtxOppositeLic.mvFieldNeighbours[(uiAffMergeCand << 1) + 0][0].mv += m_mvBufBDMVR4AFFINE[(uiAffMergeCand << 1) + 0][0];
+          affineMergeCtxOppositeLic.mvFieldNeighbours[(uiAffMergeCand << 1) + 0][1].mv += m_mvBufBDMVR4AFFINE[(uiAffMergeCand << 1) + 0][0];
+          affineMergeCtxOppositeLic.mvFieldNeighbours[(uiAffMergeCand << 1) + 0][2].mv += m_mvBufBDMVR4AFFINE[(uiAffMergeCand << 1) + 0][0];
+          affineMergeCtxOppositeLic.mvFieldNeighbours[(uiAffMergeCand << 1) + 1][0].mv += m_mvBufBDMVR4AFFINE[(uiAffMergeCand << 1) + 1][0];
+          affineMergeCtxOppositeLic.mvFieldNeighbours[(uiAffMergeCand << 1) + 1][1].mv += m_mvBufBDMVR4AFFINE[(uiAffMergeCand << 1) + 1][0];
+          affineMergeCtxOppositeLic.mvFieldNeighbours[(uiAffMergeCand << 1) + 1][2].mv += m_mvBufBDMVR4AFFINE[(uiAffMergeCand << 1) + 1][0];
+        }
+      }
+#endif
+#endif
 #if JVET_X0049_ADAPT_DMVR
       checkBmMrg = PU::isBMMergeFlagCoded(pu);
       if (checkBmMrg)
@@ -5592,6 +6379,10 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
       partitioner.setCUData( cu );
       cu.slice            = tempCS->slice;
       cu.tileIdx          = tempCS->pps->getTileIdx( tempCS->area.lumaPos() );
+#if JVET_AG0276_NLIC
+      cu.altLMFlag = false;
+      cu.altLMParaUnit.resetAltLinearModel();
+#endif
 #if INTER_LIC
       cu.licFlag          = false;
 #endif
@@ -5628,6 +6419,11 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
 #if MULTI_PASS_DMVR
       pu.bdmvrRefine = false;
 #endif
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+      pu.mergeOppositeLic = false;
+      pu.affineOppositeLic = false;
+      pu.tmMergeFlagOppositeLic = false;
+#endif
 #endif
       DistParam distParam;
       const bool bUseHadamard = !tempCS->slice->getDisableSATDForRD();
@@ -5793,7 +6589,11 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
       {
 #if MERGE_ENC_OPT
 #if JVET_AB0079_TM_BCW_MRG
+#if JVET_AG0276_NLIC
+        xCheckSATDCostCiipMerge(tempCS, cu, pu, mrgCtxCiip, acMergeTempBuffer, singleMergeTempBuffer, acMergeTmpBuffer, uiNumMrgSATDCand, rdModeList, candCostList, distParam, ctxStart, mergeOrgCtx);
+#else
         xCheckSATDCostCiipMerge(tempCS, cu, pu, mrgCtxCiip, acMergeTempBuffer, singleMergeTempBuffer, acMergeTmpBuffer, uiNumMrgSATDCand, rdModeList, candCostList, distParam, ctxStart);
+#endif
 #else
         xCheckSATDCostCiipMerge(tempCS, cu, pu, mergeCtx, acMergeTempBuffer, singleMergeTempBuffer, acMergeTmpBuffer, uiNumMrgSATDCand, rdModeList, candCostList, distParam, ctxStart);
 #endif
@@ -6081,7 +6881,45 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
           break;
         }
       }
-
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+      if (hasOppositelicMrg && pu.cs->sps->getUseMergeOppositeLic())
+      {
+        xCheckSATDCostRegularMergeOppositeLic(tempCS, cu, pu, mergeCtxOppositeLic, acMergeTempBuffer, singleMergeTempBuffer, acMergeTmpBuffer
+#if !MULTI_PASS_DMVR
+          , refinedMvdL0
+#endif
+          , uiNumMrgSATDCand, rdModeList, candCostList, distParam, ctxStart
+#if MULTI_PASS_DMVR
+          , applyBDMVROppositeLic
+#endif
+        );
+      }
+#if TM_MRG
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+      if (sps.getUseTMMrgMode())
+#else
+      if (sps.getUseDMVDMode())
+#endif
+      {
+        if (hasOppositelicMrg && pu.cs->sps->getUseTMMergeOppositeLic())
+        {
+          xCheckSATDCostTMMergeOppositeLic(tempCS, cu, pu, tmMrgCtxOppositeLic, acMergeTempBuffer, singleMergeTempBuffer, uiNumMrgSATDCand, rdModeList, candCostList, distParam, ctxStart
+#if MULTI_PASS_DMVR
+            , applyBDMVR4TMOppositeLic
+#endif
+          );
+        }
+#endif
+      }
+      if (affineMrgAvail)
+      {
+        if (hasOppositelicAff && pu.cs->sps->getUseAffMergeOppositeLic())
+        {
+          xCheckSATDCostAffineMergeOppositeLic(tempCS, cu, pu, affineMergeCtxOppositeLic, mrgCtx, acMergeTempBuffer, singleMergeTempBuffer, uiNumMrgSATDCand, rdModeList, candCostList, distParam, ctxStart
+          );
+        }
+      }
+#endif
       setMergeBestSATDCost( candCostList[0] );
 
       if (isIntrainterEnabled && isChromaEnabled(pu.cs->pcv->chrFormat))
@@ -6222,6 +7060,10 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
       cu.tileIdx          = tempCS->pps->getTileIdx( tempCS->area.lumaPos() );
       cu.skip             = false;
       cu.mmvdSkip = false;
+#if JVET_AG0276_NLIC
+      cu.altLMFlag = false;
+      cu.altLMParaUnit.resetAltLinearModel();
+#endif
 #if INTER_LIC
       cu.licFlag          = false;
 #if JVET_AD0213_LIC_IMP
@@ -6303,6 +7145,10 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
 #if INTER_LIC
             cu.licFlag = affineMergeCtx.licFlags[uiMergeCand];
 #endif
+#if JVET_AG0276_NLIC
+            cu.altLMFlag = affineMergeCtx.altLMFlag[uiMergeCand];
+            cu.altLMParaUnit = affineMergeCtx.altLMParaNeighbours[uiMergeCand];
+#endif
 #if JVET_AD0193_ADAPTIVE_OBMC_CONTROL
             cu.obmcFlag = affineMergeCtx.obmcFlags[uiMergeCand];
 #endif
@@ -6426,6 +7272,9 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
         cu.mmvdSkip         = false;
         pu.regularMergeFlag = false;
         pu.mmvdMergeFlag    = false;
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+        pu.affineOppositeLic = false;
+#endif
 
         pu.mergeFlag      = true;
         pu.afMmvdFlag     = true;
@@ -6438,6 +7287,10 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
 #endif
 #if JVET_W0090_ARMC_TM
         pu.mergeType = affineMergeCtxTmp.mergeType[pu.mergeIdx];
+#if JVET_AG0276_NLIC
+        pu.cu->altLMFlag = affineMergeCtxTmp.altLMFlag[pu.mergeIdx];
+        pu.cu->altLMParaUnit = affineMergeCtxTmp.altLMParaNeighbours[pu.mergeIdx];
+#endif
 #if INTER_LIC
         pu.cu->licFlag = affineMergeCtxTmp.licFlags[pu.mergeIdx];
 #endif
@@ -6492,6 +7345,9 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
           CHECK(uiMergeCand >= affineBMMergeL0.numValidMergeCand, "");
           cu.mmvdSkip = false;
           cu.affine = true;
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+          pu.affineOppositeLic = false;
+#endif
           cu.imv = 0;
           pu.afMmvdFlag = false;
           pu.regularMergeFlag = false;
@@ -6501,6 +7357,10 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
           pu.interDir = affineBMMergeL0.interDirNeighbours[uiMergeCand];
           cu.affineType = affineBMMergeL0.affineType[uiMergeCand];
           cu.bcwIdx = affineBMMergeL0.bcwIdx[uiMergeCand];
+#if JVET_AG0276_NLIC
+          cu.altLMFlag = affineBMMergeL0.altLMFlag[uiMergeCand];
+          cu.altLMParaUnit = affineBMMergeL0.altLMParaNeighbours[uiMergeCand];
+#endif
 #if INTER_LIC
           cu.licFlag = affineBMMergeL0.licFlags[uiMergeCand];
 #endif
@@ -6533,6 +7393,9 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
           CHECK(uiMergeCand >= affineBMMergeL1.numValidMergeCand, "");
           cu.mmvdSkip = false;
           cu.affine = true;
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+          pu.affineOppositeLic = false;
+#endif
           cu.imv = 0;
           pu.afMmvdFlag = false;
           pu.regularMergeFlag = false;
@@ -6542,6 +7405,10 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
           pu.interDir = affineBMMergeL1.interDirNeighbours[uiMergeCand];
           cu.affineType = affineBMMergeL1.affineType[uiMergeCand];
           cu.bcwIdx = affineBMMergeL1.bcwIdx[uiMergeCand];
+#if JVET_AG0276_NLIC
+          cu.altLMFlag = affineBMMergeL1.altLMFlag[uiMergeCand];
+          cu.altLMParaUnit = affineBMMergeL1.altLMParaNeighbours[uiMergeCand];
+#endif
 #if INTER_LIC
           cu.licFlag = affineBMMergeL1.licFlags[uiMergeCand];
 #endif
@@ -6574,12 +7441,65 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
           CHECK(true, "wrong affine BM dir!");
         }
       }
+#endif
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+      else if (rdModeList[uiMrgHADIdx].isAffOppositeLic)
+      {
+        cu.mmvdSkip = false;
+        cu.affine = true;
+        pu.affineOppositeLic = true;
+        cu.imv = 0;
+        pu.regularMergeFlag = false;
+        pu.mergeFlag = true;
+        pu.mergeIdx = uiMergeCand;
+        pu.mmvdMergeFlag = false;
+        pu.interDir = affineMergeCtxOppositeLic.interDirNeighbours[uiMergeCand];
+        cu.affineType = affineMergeCtxOppositeLic.affineType[uiMergeCand];
+        cu.bcwIdx = affineMergeCtxOppositeLic.bcwIdx[uiMergeCand];
+#if JVET_AG0276_NLIC
+        cu.altLMFlag = affineMergeCtxOppositeLic.altLMFlag[uiMergeCand];
+        cu.altLMParaUnit = affineMergeCtxOppositeLic.altLMParaNeighbours[uiMergeCand];
+#endif
+#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION
+        pu.colIdx = affineMergeCtxOppositeLic.colIdx[uiMergeCand];
+#endif
+#if INTER_LIC
+        cu.licFlag = affineMergeCtxOppositeLic.licFlags[uiMergeCand];
+#endif
+#if JVET_AD0193_ADAPTIVE_OBMC_CONTROL
+        cu.obmcFlag = affineMergeCtxOppositeLic.obmcFlags[uiMergeCand];
+#endif
+        pu.mv[0].setZero();
+        pu.mv[1].setZero();
+        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;
+        pu.mergeType = affineMergeCtxOppositeLic.mergeType[uiMergeCand];
+#if JVET_AD0182_AFFINE_DMVR_PLUS_EXTENSIONS
+        pu.affBMMergeFlag = false;
+#endif
+
+        for (int i = 0; i < 2; i++)
+        {
+          pu.refIdx[i] = affineMergeCtxOppositeLic.mvFieldNeighbours[(uiMergeCand << 1) + i][0].refIdx;
+          pu.mvAffi[i][0] = affineMergeCtxOppositeLic.mvFieldNeighbours[(uiMergeCand << 1) + i][0].mv;
+          pu.mvAffi[i][1] = affineMergeCtxOppositeLic.mvFieldNeighbours[(uiMergeCand << 1) + i][1].mv;
+          pu.mvAffi[i][2] = affineMergeCtxOppositeLic.mvFieldNeighbours[(uiMergeCand << 1) + i][2].mv;
+        }
+        PU::spanMotionInfo(pu);
+      }
 #endif
       else if (rdModeList[uiMrgHADIdx].isAffine)
       {
         CHECK(uiMergeCand >= affineMergeCtx.numValidMergeCand, "");
         cu.mmvdSkip = false;
         cu.affine = true;
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+        pu.affineOppositeLic = false;
+#endif
         cu.imv = 0;
         pu.regularMergeFlag = false;
         pu.mergeFlag = true;
@@ -6591,6 +7511,10 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
 #if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION
         pu.colIdx = affineMergeCtx.colIdx[uiMergeCand];
 #endif
+#if JVET_AG0276_NLIC
+        cu.altLMFlag = affineMergeCtx.altLMFlag[uiMergeCand];
+        cu.altLMParaUnit = affineMergeCtx.altLMParaNeighbours[uiMergeCand];
+#endif
 #if INTER_LIC
         cu.licFlag = affineMergeCtx.licFlags[uiMergeCand];
 #endif
@@ -6632,6 +7556,33 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
           PU::spanMotionInfo(pu);
         }
       }
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+#if TM_MRG && MERGE_ENC_OPT
+#if JVET_X0141_CIIP_TIMD_TM
+      else if (rdModeList[uiMrgHADIdx].isTMMrg && rdModeList[uiMrgHADIdx].isTMMrgOppositeLic && !rdModeList[uiMrgHADIdx].isCIIP)
+#else
+      else if (rdModeList[uiMrgHADIdx].isTMMrg)
+#endif
+      {
+        cu.mmvdSkip = false;
+        pu.regularMergeFlag = true;
+        pu.tmMergeFlag = true;
+        pu.tmMergeFlagOppositeLic = true;
+#if JVET_X0141_CIIP_TIMD_TM
+        pu.ciipFlag = false;
+#endif
+        tmMrgCtxOppositeLic.setMergeInfo(pu, uiMergeCand);
+#if MULTI_PASS_DMVR
+        if (applyBDMVR4TMOppositeLic[uiMergeCand])
+        {
+          isDMVR = true;
+          pu.bdmvrRefine = true;
+          m_pcInterSearch->setBdmvrSubPuMvBuf(m_mvBufBDMVR4TMOPPOSITELIC[uiMergeCand << 1], m_mvBufBDMVR4TMOPPOSITELIC[(uiMergeCand << 1) + 1]);
+        }
+#endif
+      }
+#endif
+#endif
 #if TM_MRG && MERGE_ENC_OPT
 #if JVET_X0141_CIIP_TIMD_TM
       else if (rdModeList[uiMrgHADIdx].isTMMrg && !rdModeList[uiMrgHADIdx].isCIIP)
@@ -6642,6 +7593,9 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
         cu.mmvdSkip         = false;
         pu.regularMergeFlag = true;
         pu.tmMergeFlag      = true;
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+        pu.tmMergeFlagOppositeLic = false;
+#endif
 #if JVET_X0141_CIIP_TIMD_TM
         pu.ciipFlag = false;
 #endif
@@ -6683,9 +7637,36 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
         }
       }
 #endif
+#endif
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+      else if (rdModeList[uiMrgHADIdx].isOppositeLic)
+      {
+        pu.mergeOppositeLic = true;
+        cu.mmvdSkip = false;
+        pu.regularMergeFlag = true;
+        pu.bmMergeFlag = false;
+        pu.affBMMergeFlag = false;
+        pu.cu->geoFlag = false;
+        mergeCtxOppositeLic.setMergeInfo(pu, uiMergeCand);
+#if JVET_X0141_CIIP_TIMD_TM && TM_MRG
+        pu.ciipFlag = false;
+        pu.tmMergeFlag = false;
+#endif
+#if MULTI_PASS_DMVR
+        if (applyBDMVROppositeLic[uiMergeCand])
+        {
+          isDMVR = true;
+          pu.bdmvrRefine = true;
+          m_pcInterSearch->setBdmvrSubPuMvBuf(m_mvBufBDMVR4OPPOSITELIC[uiMergeCand << 1], m_mvBufBDMVR4OPPOSITELIC[(uiMergeCand << 1) + 1]);
+        }
+#endif
+      }
 #endif
       else
       {
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+        pu.mergeOppositeLic = false;
+#endif
         cu.mmvdSkip = false;
         pu.regularMergeFlag = true;
         mergeCtx.setMergeInfo(pu, uiMergeCand);
@@ -6735,7 +7716,11 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
         }
       }
 #if MERGE_ENC_OPT
+#if JVET_AG0276_LIC_BDOF_BDMVR
+      if (mrgTempBufSet && uiMrgHADIdx < MMVD_MRG_MAX_RD_NUM && !(pu.bdmvrRefine == true && pu.cu->licFlag == true))
+#else
       if (mrgTempBufSet && uiMrgHADIdx < MMVD_MRG_MAX_RD_NUM)
+#endif
 #else
       if( mrgTempBufSet )
 #endif
@@ -6954,6 +7939,23 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
 #if MULTI_PASS_DMVR
             if (!rdModeList[uiMrgHADIdx].isAffine && !rdModeList[uiMrgHADIdx].isGeo && pu.bdmvrRefine)
             {
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+#if TM_MRG
+#if JVET_X0141_CIIP_TIMD_TM
+              if (pu.tmMergeFlag && pu.tmMergeFlagOppositeLic && !rdModeList[uiMrgHADIdx].isCIIP)
+#else
+              if (pu.tmMergeFlag)
+#endif
+              {
+                PU::spanMotionInfo(pu, mergeCtx,
+#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION
+                  pu.colIdx,
+#endif
+                  m_mvBufBDMVR4TMOPPOSITELIC[uiMergeCand << 1], m_mvBufBDMVR4TMOPPOSITELIC[(uiMergeCand << 1) + 1], m_pcInterSearch->getBdofSubPuMvOffset());
+              }
+              else
+#endif
+#endif
 #if TM_MRG
 #if JVET_X0141_CIIP_TIMD_TM
               if (pu.tmMergeFlag && !rdModeList[uiMrgHADIdx].isCIIP)
@@ -6979,6 +7981,25 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
                   m_mvBufBDMVR4BM[uiMergeCand << 1], m_mvBufBDMVR4BM[(uiMergeCand << 1) + 1], m_pcInterSearch->getBdofSubPuMvOffset());
               }
               else
+#endif
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+                if (pu.mergeOppositeLic)
+                {
+#if JVET_AG0276_LIC_BDOF_BDMVR
+                  if (pu.cu->licFlag == true)
+                  {
+                    memset((void*)m_pcInterSearch->getBdofSubPuMvOffset(), 0, BDOF_SUBPU_MAX_NUM * sizeof(Mv));
+                  }
+#endif
+
+                  PU::spanMotionInfo(pu, mergeCtxOppositeLic,
+#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION
+                    pu.colIdx,
+#endif
+                    m_mvBufBDMVR4OPPOSITELIC[uiMergeCand << 1], m_mvBufBDMVR4OPPOSITELIC[(uiMergeCand << 1) + 1], m_pcInterSearch->getBdofSubPuMvOffset());
+
+                }
+                else
 #endif
                 PU::spanMotionInfo(pu, mergeCtx,
 #if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION
@@ -7014,14 +8035,29 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
             tempCS->getPredBuf().copyFrom(*acMergeTempBuffer[uiMrgHADIdx]);
             PU::setAffineBdofRefinedMotion(pu, m_mvBufEncAffineBmBDOF[(uiMergeCand << 1) + rdModeList[uiMrgHADIdx].affBMDir - 1]);
           }
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+          else if (rdModeList[uiMrgHADIdx].isAffine == true && rdModeList[uiMrgHADIdx].isAffBMMrg == false && ((!pu.affineOppositeLic && m_doEncAffineBDOF[uiMergeCand] == true) || (pu.affineOppositeLic && m_doEncAffineBDOFOppositeLic[uiMergeCand] == true)))
+#else
           else if (rdModeList[uiMrgHADIdx].isAffine == true && rdModeList[uiMrgHADIdx].isAffBMMrg == false && m_doEncAffineBDOF[uiMergeCand] == true)
+#endif
           {
 #if JVET_AG0135_AFFINE_CIIP
             tempCS->getPredBuf().copyFrom(acMergeAffineBuffer[uiMergeCand]);
 #else
             tempCS->getPredBuf().copyFrom(*acMergeTempBuffer[uiMrgHADIdx]);
 #endif
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+            if (pu.affineOppositeLic)
+            {
+              PU::setAffineBdofRefinedMotion(pu, m_mvBufEncAffineBDOFOppositeLic[uiMergeCand]);
+            }
+            else
+            {
+              PU::setAffineBdofRefinedMotion(pu, m_mvBufEncAffineBDOF[uiMergeCand]);
+            }
+#else
             PU::setAffineBdofRefinedMotion(pu, m_mvBufEncAffineBDOF[uiMergeCand]);
+#endif
           }
 #endif
           else if (rdModeList[uiMrgHADIdx].isAffine)
@@ -7096,6 +8132,19 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
             if(pu.bdmvrRefine)
 #endif
             {
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+#if TM_MRG
+              if (pu.tmMergeFlag && pu.tmMergeFlagOppositeLic)
+              {
+                PU::spanMotionInfo(pu, mergeCtx,
+#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION
+                  pu.colIdx,
+#endif
+                  m_mvBufBDMVR4TMOPPOSITELIC[uiMergeCand << 1], m_mvBufBDMVR4TMOPPOSITELIC[(uiMergeCand << 1) + 1], m_mvBufEncBDOF4TMOPPOSITELIC[uiMergeCand]);
+              }
+              else
+#endif
+#endif
 #if TM_MRG
               if( pu.tmMergeFlag )
               {
@@ -7117,6 +8166,18 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
                   m_mvBufBDMVR4BM[uiMergeCand << 1], m_mvBufBDMVR4BM[(uiMergeCand << 1) + 1], m_mvBufEncBDOF4BM[uiMergeCand]);
               }
               else
+#endif
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+                if (pu.mergeOppositeLic)
+                {
+                  PU::spanMotionInfo(pu, mergeCtxOppositeLic,
+#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION
+                    pu.colIdx,
+#endif
+                    m_mvBufBDMVR4OPPOSITELIC[uiMergeCand << 1], m_mvBufBDMVR4OPPOSITELIC[(uiMergeCand << 1) + 1], m_mvBufEncBDOF4OPPOSITELIC[uiMergeCand]);
+
+                }
+                else
 #endif
                 PU::spanMotionInfo(pu, mergeCtx,
 #if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION
@@ -7160,6 +8221,19 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
 #if MULTI_PASS_DMVR
         if (pu.bdmvrRefine)
         {
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+#if TM_MRG
+          if (pu.tmMergeFlag && pu.tmMergeFlagOppositeLic)
+          {
+            PU::spanMotionInfo(pu, mergeCtx,
+#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION
+              pu.colIdx,
+#endif
+              m_mvBufBDMVR4TMOPPOSITELIC[uiMergeCand << 1], m_mvBufBDMVR4TMOPPOSITELIC[(uiMergeCand << 1) + 1], m_pcInterSearch->getBdofSubPuMvOffset());
+          }
+          else
+#endif
+#endif
 #if TM_MRG
           if( pu.tmMergeFlag )
           {
@@ -7181,12 +8255,34 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
                 m_mvBufBDMVR4BM[uiMergeCand << 1], m_mvBufBDMVR4BM[(uiMergeCand << 1) + 1], m_mvBufEncBDOF4BM[uiMergeCand]);
             }
             else
+#endif
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+              if (pu.mergeOppositeLic)
+              {
+                PU::spanMotionInfo(pu, mergeCtxOppositeLic,
+#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION
+                  pu.colIdx,
+#endif
+                  m_mvBufBDMVR4OPPOSITELIC[uiMergeCand << 1], m_mvBufBDMVR4OPPOSITELIC[(uiMergeCand << 1) + 1], m_mvBufEncBDOF4OPPOSITELIC[uiMergeCand]);
+
+              }
+              else
+#endif
+#if JVET_AG0276_LIC_BDOF_BDMVR
+              {
+                if (pu.cu->licFlag == true)
+                {
+                  memset((void*)m_pcInterSearch->getBdofSubPuMvOffset(), 0, BDOF_SUBPU_MAX_NUM * sizeof(Mv));
+                }
 #endif
               PU::spanMotionInfo(pu, mergeCtx,
 #if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION
                 pu.colIdx,
 #endif
                 m_mvBufBDMVR[uiMergeCand << 1], m_mvBufBDMVR[(uiMergeCand << 1) + 1], m_pcInterSearch->getBdofSubPuMvOffset());
+#if JVET_AG0276_LIC_BDOF_BDMVR
+              }
+#endif
         }
 #endif
       }
@@ -7199,6 +8295,10 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
 #endif
 #if AFFINE_MMVD && MERGE_ENC_OPT
           && !pu.afMmvdFlag
+#endif
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+        && !pu.mergeOppositeLic
+        && !pu.tmMergeFlagOppositeLic
 #endif
         )
       {
@@ -9658,6 +10758,10 @@ void EncCu::xCheckRDCostMergeGeoComb2Nx2N(CodingStructure *&tempCS, CodingStruct
           }
           mergeCtx[i].bcwIdx[idx] = BCW_DEFAULT;
           mergeCtx[i].useAltHpelIf[idx] = false;
+#if JVET_AG0276_NLIC
+          mergeCtx[i].altLMFlag[idx] = false;
+          mergeCtx[i].altLMParaNeighbours[idx].resetAltLinearModel();
+#endif
 #if INTER_LIC
           mergeCtx[i].licFlags[idx] = false;
 #endif
@@ -12017,8 +13121,15 @@ void EncCu::xCheckSATDCostRegularMerge(CodingStructure *&tempCS, CodingUnit &cu,
 
 )
 {
+#if JVET_AG0276_NLIC
+  cu.altLMFlag = false;
+  cu.altLMParaUnit.resetAltLinearModel();
+#endif
 #if INTER_LIC
   cu.licFlag = false;
+#endif
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+  pu.mergeOppositeLic = false;
 #endif
   cu.mmvdSkip = false;
   cu.geoFlag = false;
@@ -12053,11 +13164,17 @@ void EncCu::xCheckSATDCostRegularMerge(CodingStructure *&tempCS, CodingUnit &cu,
     pu.mvRefine = true;
     distParam.cur = singleMergeTempBuffer->Y();
     acMergeTmpBuffer[uiMergeCand] = m_acMergeTmpBuffer[uiMergeCand].getBuf(localUnitArea);
+#if JVET_AG0276_NLIC
+    m_pcInterSearch->m_storeBeforeLIC = false;
+#else
 #if INTER_LIC
 #if JVET_AD0213_LIC_IMP
     m_pcInterSearch->m_storeBeforeLIC = mergeCtx.licFlags[uiMergeCand] ? true : false;
 #else
     m_pcInterSearch->m_storeBeforeLIC = mergeCtx.interDirNeighbours[uiMergeCand] == 3 ? false : true;
+#endif
+#if JVET_AG0276_LIC_BDOF_BDMVR
+    m_pcInterSearch->m_storeBeforeLIC &= (applyBDMVR[uiMergeCand] == false);
 #endif
     if (m_pcInterSearch->m_storeBeforeLIC)
     {
@@ -12066,9 +13183,11 @@ void EncCu::xCheckSATDCostRegularMerge(CodingStructure *&tempCS, CodingUnit &cu,
     }
     else
 #endif
+#endif
 #if MULTI_PASS_DMVR
     if (applyBDMVR[uiMergeCand])
     {
+#if !JVET_AG0276_NLIC
       if (pu.cu->cs->sps->getUseCiip())
       {
 #if MULTI_HYP_PRED
@@ -12083,6 +13202,7 @@ void EncCu::xCheckSATDCostRegularMerge(CodingStructure *&tempCS, CodingUnit &cu,
         mergeCtx.setMergeInfo(pu, uiMergeCand);
 #endif
       }
+#endif
       pu.bdmvrRefine = true;
       m_pcInterSearch->setBdmvrSubPuMvBuf(m_mvBufBDMVR[uiMergeCand << 1], m_mvBufBDMVR[(uiMergeCand << 1) + 1]);
 
@@ -12091,6 +13211,16 @@ void EncCu::xCheckSATDCostRegularMerge(CodingStructure *&tempCS, CodingUnit &cu,
 
       if( pu.bdmvrRefine )
       {
+#if JVET_AG0276_LIC_BDOF_BDMVR
+        if (pu.cu->licFlag == true)
+        {
+          Mv* bdofMvBuf = m_pcInterSearch->getBdofSubPuMvOffset();
+          for (int z = 0; z < BDOF_SUBPU_MAX_NUM; z++)
+          {
+            bdofMvBuf[z].setZero();
+          }
+        }
+#endif
         ::memcpy( m_mvBufEncBDOF[uiMergeCand], m_pcInterSearch->getBdofSubPuMvOffset(), sizeof( Mv ) * BDOF_SUBPU_MAX_NUM );
       }
 
@@ -12099,7 +13229,11 @@ void EncCu::xCheckSATDCostRegularMerge(CodingStructure *&tempCS, CodingUnit &cu,
     else
 #endif
     {
+#if JVET_AG0276_NLIC
+      m_pcInterSearch->motionCompensation(pu, *singleMergeTempBuffer);
+#else
       m_pcInterSearch->motionCompensation(pu, *singleMergeTempBuffer, REF_PIC_LIST_X, true, true, &(acMergeTmpBuffer[uiMergeCand]));
+#endif
     }
 #if INTER_LIC
     m_pcInterSearch->m_storeBeforeLIC = false;
@@ -12147,7 +13281,11 @@ void EncCu::xCheckSATDCostRegularMerge(CodingStructure *&tempCS, CodingUnit &cu,
 #if MULTI_PASS_DMVR
       CHECK(pu.bdmvrRefine && !applyBDMVR[uiMergeCand], "");
 #endif
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+      uint32_t uiBitsCand = uiMergeCand + 1 + 1 + 1 + 1; // one bit for merge flag,  one bit for subblock_merge_flag, and one bit for regualr_merge_flag, one bit for mergeOppoLic flag
+#else
       uint32_t uiBitsCand = uiMergeCand + 1 + 1 + 1; // one bit for merge flag,  one bit for subblock_merge_flag, and one bit for regualr_merge_flag
+#endif
       MEResult mergeResult;
       mergeResult.cu = cu;
       mergeResult.pu = pu;
@@ -12191,6 +13329,9 @@ void EncCu::xCheckSATDCostCiipAffineMerge(CodingStructure *&tempCS, CodingUnit &
 {
 #if INTER_LIC
   cu.licFlag = false;
+#endif
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+  pu.affineOppositeLic = false;
 #endif
   cu.mmvdSkip = false;
   cu.geoFlag = false;
@@ -12232,6 +13373,10 @@ void EncCu::xCheckSATDCostCiipAffineMerge(CodingStructure *&tempCS, CodingUnit &
     cu.bcwIdx = affineMergeCtx.bcwIdx[uiAffMergeCand];
 #if INTER_LIC
     cu.licFlag = affineMergeCtx.licFlags[uiAffMergeCand];
+#endif
+#if JVET_AG0276_NLIC
+    cu.altLMFlag = affineMergeCtx.altLMFlag[uiAffMergeCand];
+    cu.altLMParaUnit = affineMergeCtx.altLMParaNeighbours[uiAffMergeCand];
 #endif
     pu.mv[0].setZero();
     pu.mv[1].setZero();
@@ -12335,9 +13480,151 @@ void EncCu::xCheckSATDCostCiipAffineMerge(CodingStructure *&tempCS, CodingUnit &
   pu.ciipAffine = false;
 }
 #endif
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+void EncCu::xCheckSATDCostRegularMergeOppositeLic(CodingStructure *&tempCS, CodingUnit &cu, PredictionUnit &pu, MergeCtx mergeCtxOppositeLic, PelUnitBuf *acMergeTempBuffer[MMVD_MRG_MAX_RD_NUM], PelUnitBuf *&singleMergeTempBuffer, PelUnitBuf  acMergeTmpBuffer[MRG_MAX_NUM_CANDS]
+#if !MULTI_PASS_DMVR
+  , Mv   refinedMvdL0[MAX_NUM_PARTS_IN_CTU][MRG_MAX_NUM_CANDS]
+#endif
+  , 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
+)
+{
+#if JVET_AG0276_NLIC
+  cu.altLMFlag = false;
+  cu.altLMParaUnit.resetAltLinearModel();
+#endif
+#if INTER_LIC
+  cu.licFlag = false;
+#endif
+  pu.mergeOppositeLic = true;
+  cu.mmvdSkip = false;
+  cu.geoFlag = false;
+  cu.affine = false;
+  cu.imv = 0;
+
+  pu.ciipFlag = false;
+#if CIIP_PDPC
+  pu.ciipPDPC = false;
+#endif
+  pu.mmvdMergeFlag = false;
+  pu.regularMergeFlag = true;
+
+  const double sqrtLambdaForFirstPassIntra = m_pcRdCost->getMotionLambda() * FRAC_BITS_SCALE;
+  const UnitArea localUnitArea(tempCS->area.chromaFormat, Area(0, 0, tempCS->area.Y().width, tempCS->area.Y().height));
+#if MULTI_HYP_PRED
+  const bool testMHP = tempCS->sps->getUseInterMultiHyp()
+    && (tempCS->area.lumaSize().area() > MULTI_HYP_PRED_RESTRICT_BLOCK_SIZE
+      && std::min(tempCS->area.lwidth(), tempCS->area.lheight()) >= MULTI_HYP_PRED_RESTRICT_MIN_WH);
+#endif
+
+  int insertPos = -1;
+  for (uint32_t uiMergeCand = 0; uiMergeCand < mergeCtxOppositeLic.numValidMergeCand; uiMergeCand++)
+  {
+    mergeCtxOppositeLic.setMergeInfo(pu, uiMergeCand);
+#if MULTI_PASS_DMVR
+    pu.bdmvrRefine = false; // init as false
+#endif
+    pu.mvRefine = true;
+    distParam.cur = singleMergeTempBuffer->Y();
+#if MULTI_PASS_DMVR
+    if (applyBDMVR[uiMergeCand])
+    {
+      pu.bdmvrRefine = true;
+      m_pcInterSearch->setBdmvrSubPuMvBuf(m_mvBufBDMVR4OPPOSITELIC[uiMergeCand << 1], m_mvBufBDMVR4OPPOSITELIC[(uiMergeCand << 1) + 1]);
+      
+      pu.mvRefine = true;
+      m_pcInterSearch->motionCompensation(pu, *singleMergeTempBuffer);
+      
+      if (pu.bdmvrRefine)
+      {
+        ::memcpy(m_mvBufEncBDOF4OPPOSITELIC[uiMergeCand], m_pcInterSearch->getBdofSubPuMvOffset(), sizeof(Mv) * BDOF_SUBPU_MAX_NUM);
+      }
+      
+      pu.mvRefine = false;
+    }
+    else
+#endif
+    {
+      m_pcInterSearch->motionCompensation(pu, *singleMergeTempBuffer);
+    }
+    pu.mvRefine = false;
+#if !MULTI_PASS_DMVR
+    if (mergeCtxOppositeLic.interDirNeighbours[uiMergeCand] == 3)
+    {
+      mergeCtxOppositeLic.mvFieldNeighbours[2 * uiMergeCand].mv = pu.mv[0];
+      mergeCtxOppositeLic.mvFieldNeighbours[2 * uiMergeCand + 1].mv = pu.mv[1];
+      {
+        int dx, dy, i, j, num = 0;
+        dy = std::min<int>(pu.lumaSize().height, DMVR_SUBCU_HEIGHT);
+        dx = std::min<int>(pu.lumaSize().width, DMVR_SUBCU_WIDTH);
+        if (PU::checkDMVRCondition(pu))
+        {
+          for (i = 0; i < (pu.lumaSize().height); i += dy)
+          {
+            for (j = 0; j < (pu.lumaSize().width); j += dx)
+            {
+              refinedMvdL0[num][uiMergeCand] = pu.mvdL0SubPu[num];
+              num++;
+            }
+          }
+        }
+      }
+    }
+#endif
+    
+    Distortion uiSad = distParam.distFunc(distParam);
+    m_CABACEstimator->getCtx() = ctxStart;
+    uint64_t fracBits = m_pcInterSearch->xCalcPuMeBits(pu);
+    double cost = (double)uiSad + (double)fracBits * sqrtLambdaForFirstPassIntra;
+#if MULTI_HYP_PRED
+    if (testMHP && pu.addHypData.size() < tempCS->sps->getMaxNumAddHyps())
+    {
+      uint32_t uiBitsCand = uiMergeCand + 1 + 1 + 1 + 1; // one bit for merge flag,  one bit for subblock_merge_flag, and one bit for regualr_merge_flag, one bit for mergeOppoLic flag
+      MEResult mergeResult;
+      mergeResult.cu = cu;
+      mergeResult.pu = pu;
+      mergeResult.bits = uiBitsCand;
+      mergeResult.cost = uiSad + m_pcRdCost->getCost(uiBitsCand);
+      m_baseResultsForMH.push_back(mergeResult);
+    }
+#endif
+    insertPos = -1;
+    updateCandList(ModeInfo(cu, pu), cost, rdModeList, candCostList, uiNumMrgSATDCand, &insertPos);
+    if (insertPos != -1 && insertPos < MMVD_MRG_MAX_RD_NUM)
+    {
+      if (insertPos == rdModeList.size() - 1)
+      {
+        swap(singleMergeTempBuffer, acMergeTempBuffer[insertPos]);
+      }
+      else
+      {
+        for (uint32_t i = uint32_t(rdModeList.size()) - 1; i > insertPos; i--)
+        {
+          swap(acMergeTempBuffer[i - 1], acMergeTempBuffer[i]);
+        }
+        swap(singleMergeTempBuffer, acMergeTempBuffer[insertPos]);
+      }
+    }
+  }
+#if MULTI_PASS_DMVR
+  pu.bdmvrRefine = false;
+#endif
+  pu.mergeOppositeLic = false;
+}
+#endif
 void EncCu::xCheckSATDCostCiipMerge(CodingStructure *&tempCS, CodingUnit &cu, PredictionUnit &pu, MergeCtx mergeCtx, PelUnitBuf *acMergeTempBuffer[MMVD_MRG_MAX_RD_NUM], PelUnitBuf *&singleMergeTempBuffer, PelUnitBuf  acMergeTmpBuffer[MRG_MAX_NUM_CANDS]
+#if JVET_AG0276_NLIC
+  , 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, MergeCtx mergeCtx1)
+#else
   , 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)
+#endif
 {
+#if JVET_AG0276_NLIC
+  cu.altLMFlag = false;
+  cu.altLMParaUnit.resetAltLinearModel();
+#endif
 #if INTER_LIC
   cu.licFlag = false;
 #endif
@@ -12381,7 +13668,27 @@ void EncCu::xCheckSATDCostCiipMerge(CodingStructure *&tempCS, CodingUnit &cu, Pr
     //acMergeTmpBuffer[mergeCand] = m_acMergeTmpBuffer[mergeCand].getBuf(localUnitArea);
 
     // estimate merge bits
+#if JVET_AG0276_NLIC
+    // lic flag is used to generate luma prediction samples for SATD RD to ensure the identical results as anchor; however, the correct solution is to remove such condition on lic flag
+    if (mergeCtx1.licFlags[mergeCand])
+    {
+      pu.ciipFlag = false;
+      mergeCtx1.setMergeInfo(pu, mergeCand);
+      m_pcInterSearch->m_storeBeforeLIC = true;
+      m_pcInterSearch->m_predictionBeforeLIC = acMergeTmpBuffer[mergeCand];
+      m_pcInterSearch->motionCompensation(pu, *singleMergeTempBuffer, REF_PIC_LIST_X, true, false);
+      m_pcInterSearch->m_storeBeforeLIC = false;
+      pu.ciipFlag = true;
+      mergeCtx.setMergeInfo(pu, mergeCand);
+    }
+    else
+    {
+#endif
     mergeCtx.setMergeInfo(pu, mergeCand);
+#if JVET_AG0276_NLIC
+    m_pcInterSearch->motionCompensation(pu, acMergeTmpBuffer[mergeCand], REF_PIC_LIST_X, true, false);
+    }
+#endif
 
     // first round
     pu.intraDir[0] = PLANAR_IDX;
@@ -12458,6 +13765,10 @@ pu.ciipAffine = false;
 void EncCu::xCheckSATDCostCiipTmMerge(CodingStructure *&tempCS, CodingUnit &cu, PredictionUnit &pu, MergeCtx mergeCtx, PelUnitBuf *acMergeTempBuffer[MMVD_MRG_MAX_RD_NUM], PelUnitBuf *&singleMergeTempBuffer, PelUnitBuf  acTmMergeTmpBuffer[MRG_MAX_NUM_CANDS]
   , 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_AG0276_NLIC
+  cu.altLMFlag = false;
+  cu.altLMParaUnit.resetAltLinearModel();
+#endif
 #if INTER_LIC
   cu.licFlag = false;
 #endif
@@ -12508,7 +13819,11 @@ void EncCu::xCheckSATDCostCiipTmMerge(CodingStructure *&tempCS, CodingUnit &cu,
     pu.numMergedAddHyps = 0;
 #endif
     acTmMergeTmpBuffer[mergeCand] = m_acTmMergeTmpBuffer[mergeCand].getBuf(localUnitArea);
+#if JVET_AG0276_NLIC
+    m_pcInterSearch->motionCompensation(pu, acTmMergeTmpBuffer[mergeCand], REF_PIC_LIST_X, true, false);
+#else
     m_pcInterSearch->motionCompensation(pu, acTmMergeTmpBuffer[mergeCand]);
+#endif
 
     // first round
     pu.intraDir[0] = PLANAR_IDX;
@@ -12589,6 +13904,10 @@ void EncCu::xCheckSATDCostMmvdMerge(CodingStructure *&tempCS, CodingUnit &cu, Pr
 #endif
                                     )
 {
+#if JVET_AG0276_NLIC
+  cu.altLMFlag = false;
+  cu.altLMParaUnit.resetAltLinearModel();
+#endif
 #if INTER_LIC
   cu.licFlag = false;
 #endif
@@ -12665,33 +13984,157 @@ void EncCu::xCheckSATDCostMmvdMerge(CodingStructure *&tempCS, CodingUnit &cu, Pr
 #if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
      && !pu.cs->sps->getUseTMMMVD()
 #endif
-      )
-    {
-      continue;
-    }
+      )
+    {
+      continue;
+    }
+#endif
+
+#if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
+    mergeCtx.setMmvdMergeCandiInfo(pu, mmvdMergeCandtemp, mmvdMergeCand);
+#else
+    mergeCtx.setMmvdMergeCandiInfo(pu, mmvdMergeCand);
+#endif
+    pu.mvRefine = true;
+    distParam.cur = singleMergeTempBuffer->Y();
+#if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
+    pu.mmvdEncOptMode = (refineStep > 1
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+                                    + (pu.cs->sps->getUseTMMMVD() ? 0 : 1)
+#endif
+                                    ? 2 : 1);
+#else
+    pu.mmvdEncOptMode = (refineStep > 2 ? 2 : 1);
+#endif
+    CHECK(!pu.mmvdMergeFlag, "MMVD merge should be set");
+    // Don't do chroma MC here
+    m_pcInterSearch->motionCompensation(pu, *singleMergeTempBuffer, REF_PIC_LIST_X, true, false);
+    pu.mmvdEncOptMode = 0;
+    pu.mvRefine = false;
+    Distortion uiSad = distParam.distFunc(distParam);
+
+    m_CABACEstimator->getCtx() = ctxStart;
+    uint64_t fracBits = m_pcInterSearch->xCalcPuMeBits(pu);
+    double cost = (double)uiSad + (double)fracBits * sqrtLambdaForFirstPassIntra;
+#if MULTI_HYP_PRED
+    if (testMHP && pu.addHypData.size() < tempCS->sps->getMaxNumAddHyps())
+    {
+      uint32_t uiBitsCand = baseIdx + refineStep + 2 + 1 + 1 + 1; // one bit for merge flag,  one bit for subblock_merge_flag, and one bit for regualr_merge_flag
+      MEResult mergeResult;
+      mergeResult.cu = cu;
+      mergeResult.pu = pu;
+      mergeResult.bits = uiBitsCand;
+      mergeResult.cost = uiSad + m_pcRdCost->getCost(uiBitsCand);
+
+      m_baseResultsForMH.push_back(mergeResult);
+    }
+#endif
+    insertPos = -1;
+    updateCandList(ModeInfo(cu, pu), cost, rdModeList, candCostList, uiNumMrgSATDCand, &insertPos);
+    if (insertPos != -1 && insertPos < MMVD_MRG_MAX_RD_NUM)
+    {
+      for (int i = int(rdModeList.size()) - 1; i > insertPos; i--)
+      {
+        swap(acMergeTempBuffer[i - 1], acMergeTempBuffer[i]);
+      }
+      swap(singleMergeTempBuffer, acMergeTempBuffer[insertPos]);
+    }
+  }
+}
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+void EncCu::xCheckSATDCostAffineMergeOppositeLic(CodingStructure *&tempCS, CodingUnit &cu, PredictionUnit &pu, AffineMergeCtx affineMergeCtx, 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
+)
+{
+  cu.mmvdSkip = false;
+  cu.geoFlag = false;
+  cu.affine = true;
+#if INTER_LIC
+  cu.licFlag = false;
+#endif
+  pu.affineOppositeLic = true;
+  pu.afMmvdFlag = false;
+  pu.affBMMergeFlag = false;
+  pu.mergeFlag = true;
+  pu.ciipFlag = false;
+#if CIIP_PDPC
+  pu.ciipPDPC = false;
+#endif
+  pu.mmvdMergeFlag = false;
+  pu.regularMergeFlag = false;
+#if MULTI_HYP_PRED
+  pu.addHypData.clear();
+  pu.numMergedAddHyps = 0;
+  const bool testMHP = tempCS->sps->getUseInterMultiHyp()
+    && (tempCS->area.lumaSize().area() > MULTI_HYP_PRED_RESTRICT_BLOCK_SIZE
+      && std::min(tempCS->area.lwidth(), tempCS->area.lheight()) >= MULTI_HYP_PRED_RESTRICT_MIN_WH);
+#endif
+
+  const double sqrtLambdaForFirstPassIntra = m_pcRdCost->getMotionLambda() * FRAC_BITS_SCALE;
+  int insertPos = -1;
+  for (uint32_t uiAffMergeCand = 0; uiAffMergeCand < affineMergeCtx.numValidMergeCand; uiAffMergeCand++)
+  {
+    // set merge information
+    pu.interDir = affineMergeCtx.interDirNeighbours[uiAffMergeCand];
+    pu.mergeIdx = uiAffMergeCand;
+    cu.affineType = affineMergeCtx.affineType[uiAffMergeCand];
+    cu.bcwIdx = affineMergeCtx.bcwIdx[uiAffMergeCand];
+#if JVET_AG0276_NLIC
+    cu.altLMFlag = affineMergeCtx.altLMFlag[uiAffMergeCand];
+    cu.altLMParaUnit = affineMergeCtx.altLMParaNeighbours[uiAffMergeCand];
+#endif
+#if INTER_LIC
+    cu.licFlag = affineMergeCtx.licFlags[uiAffMergeCand];
+#endif
+    pu.mv[0].setZero();
+    pu.mv[1].setZero();
+    cu.imv = 0;
+#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION
+    pu.colIdx = affineMergeCtx.colIdx[uiAffMergeCand];
 #endif
-
-#if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
-    mergeCtx.setMmvdMergeCandiInfo(pu, mmvdMergeCandtemp, mmvdMergeCand);
-#else
-    mergeCtx.setMmvdMergeCandiInfo(pu, mmvdMergeCand);
+    pu.mergeType = affineMergeCtx.mergeType[uiAffMergeCand];
+#if JVET_AD0193_ADAPTIVE_OBMC_CONTROL
+    cu.obmcFlag = affineMergeCtx.obmcFlags[uiAffMergeCand];
 #endif
-    pu.mvRefine = true;
+    PU::setAllAffineMvField(pu, affineMergeCtx.mvFieldNeighbours[(uiAffMergeCand << 1) + 0], REF_PIC_LIST_0);
+    PU::setAllAffineMvField(pu, affineMergeCtx.mvFieldNeighbours[(uiAffMergeCand << 1) + 1], REF_PIC_LIST_1);
+
     distParam.cur = singleMergeTempBuffer->Y();
-#if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
-    pu.mmvdEncOptMode = (refineStep > 1
-#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
-                                    + (pu.cs->sps->getUseTMMMVD() ? 0 : 1)
-#endif
-                                    ? 2 : 1);
+#if JVET_AF0159_AFFINE_SUBPU_BDOF_REFINEMENT
+    if (PU::checkDoAffineBdofRefine(pu, m_pcInterSearch))
+    {
+      pu.availableBdofRefinedMv = AFFINE_SUBPU_BDOF_APPLY_AND_STORE_MV;
+      m_pcInterSearch->setDoAffineSubPuBdof(false);
+      m_pcInterSearch->setBdofSubPuMvBuf(m_mvBufEncAffineBDOFOppositeLic[uiAffMergeCand]);
+      if (pu.mergeType == MRG_TYPE_SUBPU_ATMVP)
+      {
+        int bioSubPuIdx = 0;
+        const int bioSubPuStrideIncr = BDOF_SUBPU_STRIDE - (int)(pu.lumaSize().width >> BDOF_SUBPU_DIM_LOG2);
+        for (int y = 0; y < pu.lumaSize().height; y += 4)
+        {
+          for (int x = 0; x < pu.lumaSize().width; x += 4)
+          {
+            m_mvBufEncAffineBDOF[uiAffMergeCand][bioSubPuIdx].setZero();
+            bioSubPuIdx++;
+          }
+          bioSubPuIdx += bioSubPuStrideIncr;
+        }
+      }
+      else
+      {
+        PU::spanMotionInfo(pu);
+      }
+      m_pcInterSearch->motionCompensation(pu, *singleMergeTempBuffer, REF_PIC_LIST_X);
+    }
+    else
+    {
+      m_pcInterSearch->motionCompensation(pu, *singleMergeTempBuffer, REF_PIC_LIST_X, true, false);
+    }
+    pu.availableBdofRefinedMv = AFFINE_SUBPU_BDOF_NOT_APPLY;
+    m_doEncAffineBDOFOppositeLic[uiAffMergeCand] = false;
 #else
-    pu.mmvdEncOptMode = (refineStep > 2 ? 2 : 1);
-#endif
-    CHECK(!pu.mmvdMergeFlag, "MMVD merge should be set");
-    // Don't do chroma MC here
     m_pcInterSearch->motionCompensation(pu, *singleMergeTempBuffer, REF_PIC_LIST_X, true, false);
-    pu.mmvdEncOptMode = 0;
-    pu.mvRefine = false;
+#endif
     Distortion uiSad = distParam.distFunc(distParam);
 
     m_CABACEstimator->getCtx() = ctxStart;
@@ -12700,19 +14143,30 @@ void EncCu::xCheckSATDCostMmvdMerge(CodingStructure *&tempCS, CodingUnit &cu, Pr
 #if MULTI_HYP_PRED
     if (testMHP && pu.addHypData.size() < tempCS->sps->getMaxNumAddHyps())
     {
-      uint32_t uiBitsCand = baseIdx + refineStep + 2 + 1 + 1 + 1; // one bit for merge flag,  one bit for subblock_merge_flag, and one bit for regualr_merge_flag
+      uint32_t   uiBitsCand = uiAffMergeCand + 1;
+      if (uiAffMergeCand == tempCS->picHeader->getMaxNumAffineMergeCand() - 1)
+      {
+        uiBitsCand--;
+      }
+      uiBitsCand = uiBitsCand + 1 + 1 + 1; // one bit for merge flag, and one bit for subblock_merge_flag, one for affineOppoLic
       MEResult mergeResult;
       mergeResult.cu = cu;
       mergeResult.pu = pu;
       mergeResult.bits = uiBitsCand;
       mergeResult.cost = uiSad + m_pcRdCost->getCost(uiBitsCand);
-
       m_baseResultsForMH.push_back(mergeResult);
     }
+#endif
+#if JVET_AF0159_AFFINE_SUBPU_BDOF_REFINEMENT
+    m_pcInterSearch->setDoAffineSubPuBdof(false);
 #endif
     insertPos = -1;
     updateCandList(ModeInfo(cu, pu), cost, rdModeList, candCostList, uiNumMrgSATDCand, &insertPos);
+#if MERGE_ENC_OPT
     if (insertPos != -1 && insertPos < MMVD_MRG_MAX_RD_NUM)
+#else
+    if (insertPos != -1)
+#endif
     {
       for (int i = int(rdModeList.size()) - 1; i > insertPos; i--)
       {
@@ -12721,7 +14175,11 @@ void EncCu::xCheckSATDCostMmvdMerge(CodingStructure *&tempCS, CodingUnit &cu, Pr
       swap(singleMergeTempBuffer, acMergeTempBuffer[insertPos]);
     }
   }
+  pu.regularMergeFlag = true;
+  cu.affine = false;
+  pu.affineOppositeLic = false;
 }
+#endif
 #if JVET_AG0135_AFFINE_CIIP
 void EncCu::xCheckSATDCostAffineMerge(CodingStructure *&tempCS, CodingUnit &cu, PredictionUnit &pu, AffineMergeCtx affineMergeCtx, MergeCtx& mrgCtx, PelUnitBuf *acMergeTempBuffer[MMVD_MRG_MAX_RD_NUM], PelUnitBuf *&singleMergeTempBuffer, PelUnitBuf  acMergeAffineBuffer[AFFINE_MRG_MAX_NUM_CANDS]
   , 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)
@@ -12736,6 +14194,9 @@ void EncCu::xCheckSATDCostAffineMerge(CodingStructure *&tempCS, CodingUnit &cu,
 #if INTER_LIC
   cu.licFlag = false;
 #endif
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+  pu.affineOppositeLic = false;
+#endif
 
   pu.mergeFlag = true;
   pu.ciipFlag = false;
@@ -12766,6 +14227,10 @@ void EncCu::xCheckSATDCostAffineMerge(CodingStructure *&tempCS, CodingUnit &cu,
     pu.mergeIdx = uiAffMergeCand;
     cu.affineType = affineMergeCtx.affineType[uiAffMergeCand];
     cu.bcwIdx = affineMergeCtx.bcwIdx[uiAffMergeCand];
+#if JVET_AG0276_NLIC
+    cu.altLMFlag = affineMergeCtx.altLMFlag[uiAffMergeCand];
+    cu.altLMParaUnit = affineMergeCtx.altLMParaNeighbours[uiAffMergeCand];
+#endif
 #if INTER_LIC
     cu.licFlag = affineMergeCtx.licFlags[uiAffMergeCand];
 #endif
@@ -12854,7 +14319,11 @@ void EncCu::xCheckSATDCostAffineMerge(CodingStructure *&tempCS, CodingUnit &cu,
       {
         uiBitsCand--;
       }
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+      uiBitsCand = uiBitsCand + 1 + 1 + 1; // one bit for merge flag, and one bit for subblock_merge_flag
+#else
       uiBitsCand = uiBitsCand + 1 + 1; // one bit for merge flag, and one bit for subblock_merge_flag
+#endif
       MEResult mergeResult;
       mergeResult.cu = cu;
       mergeResult.pu = pu;
@@ -12928,6 +14397,10 @@ void EncCu::xCheckSATDCostBMAffineMerge(CodingStructure *&tempCS, CodingUnit &cu
     pu.mergeIdx = uiAffMergeCand;
     cu.affineType = affineMergeCtx.affineType[uiAffMergeCand];
     cu.bcwIdx = affineMergeCtx.bcwIdx[uiAffMergeCand];
+#if JVET_AG0276_NLIC
+    cu.altLMFlag = affineMergeCtx.altLMFlag[uiAffMergeCand];
+    cu.altLMParaUnit = affineMergeCtx.altLMParaNeighbours[uiAffMergeCand];
+#endif
 #if INTER_LIC
     cu.licFlag = affineMergeCtx.licFlags[uiAffMergeCand];
 #endif
@@ -13048,6 +14521,9 @@ void EncCu::xCheckSATDCostTMMerge(       CodingStructure*& tempCS,
   pu.mmvdMergeFlag    = false;
   pu.regularMergeFlag = false;
   pu.tmMergeFlag      = true;
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+  pu.tmMergeFlagOppositeLic = false;
+#endif
 
   const double sqrtLambdaForFirstPassIntra = m_pcRdCost->getMotionLambda() * FRAC_BITS_SCALE;
   int insertPos = -1;
@@ -13115,6 +14591,100 @@ void EncCu::xCheckSATDCostTMMerge(       CodingStructure*& tempCS,
   pu.bdmvrRefine      = false;
 #endif
 }
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+#if TM_MRG && MERGE_ENC_OPT
+void EncCu::xCheckSATDCostTMMergeOppositeLic( 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,
+#if MULTI_PASS_DMVR
+                                          bool*             applyBDMVR
+#endif
+)
+{
+  pu.mergeFlag = true;
+  cu.mmvdSkip = false;
+  cu.geoFlag = false;
+  cu.affine = false;
+  cu.imv = IMV_OFF;
+  pu.ciipFlag = false;
+#if CIIP_PDPC
+  pu.ciipPDPC = false;
+#endif
+  pu.mmvdMergeFlag = false;
+  pu.regularMergeFlag = false;
+  pu.tmMergeFlag = true;
+  pu.tmMergeFlagOppositeLic = true;
+  const double sqrtLambdaForFirstPassIntra = m_pcRdCost->getMotionLambda() * FRAC_BITS_SCALE;
+  int insertPos = -1;
+  for (uint32_t uiMergeCand = 0; uiMergeCand < mrgCtx.numValidMergeCand; uiMergeCand++)
+  {
+    mrgCtx.setMergeInfo(pu, uiMergeCand);
+#if MULTI_PASS_DMVR
+    if (applyBDMVR[uiMergeCand])
+    {
+      pu.bdmvrRefine = true;
+      m_pcInterSearch->setBdmvrSubPuMvBuf(m_mvBufBDMVR4TMOPPOSITELIC[uiMergeCand << 1], m_mvBufBDMVR4TMOPPOSITELIC[(uiMergeCand << 1) + 1]);
+    }
+#if !BDOF_RM_CONSTRAINTS
+    else
+#endif
+#endif
+#if !BDOF_RM_CONSTRAINTS
+    {
+      PU::spanMotionInfo(pu, mrgCtx);
+    }
+#endif
+
+    pu.mvRefine = false;
+#if INTER_LIC
+    m_pcInterSearch->m_storeBeforeLIC = false;
+#endif
+    m_pcInterSearch->motionCompensation(pu, *singleMergeTempBuffer);
+#if MULTI_PASS_DMVR
+    if (pu.bdmvrRefine)
+    {
+      ::memcpy(m_mvBufEncBDOF4TMOPPOSITELIC[uiMergeCand], m_pcInterSearch->getBdofSubPuMvOffset(), sizeof(Mv) * BDOF_SUBPU_MAX_NUM);
+    }
+#endif
+    distParam.cur = singleMergeTempBuffer->Y();
+    Distortion uiSad = distParam.distFunc(distParam);
+
+    m_CABACEstimator->getCtx() = ctxStart;
+    uint64_t fracBits = m_pcInterSearch->xCalcPuMeBits(pu);
+    double cost = (double)uiSad + (double)fracBits * sqrtLambdaForFirstPassIntra;
+    insertPos = -1;
+    updateCandList(ModeInfo(cu, pu), cost, rdModeList, candCostList, uiNumMrgSATDCand, &insertPos);
+
+    if (insertPos != -1 && insertPos < MMVD_MRG_MAX_RD_NUM)
+    {
+      for (int i = int(rdModeList.size()) - 1; i > insertPos; i--)
+      {
+        swap(acMergeTempBuffer[i - 1], acMergeTempBuffer[i]);
+      }
+      swap(singleMergeTempBuffer, acMergeTempBuffer[insertPos]);
+    }
+  }
+  pu.regularMergeFlag = true;
+  cu.affine = false;
+#if AFFINE_MMVD
+  pu.afMmvdFlag = false;
+#endif
+  pu.tmMergeFlag = false;
+  pu.tmMergeFlagOppositeLic = false;
+#if MULTI_PASS_DMVR
+  pu.bdmvrRefine = false;
+#endif
+}
+#endif
+#endif
 #endif
 
 #if AFFINE_MMVD && MERGE_ENC_OPT
@@ -13251,6 +14821,10 @@ void EncCu::xCheckSATDCostAffineMmvdMerge(       CodingStructure*& tempCS,
       pu.mergeType      = affineMergeCtx.mergeType         [pu.mergeIdx];
       pu.interDir       = affineMergeCtx.interDirNeighbours[pu.mergeIdx];
       pu.cu->affineType = affineMergeCtx.affineType        [pu.mergeIdx];
+#if JVET_AG0276_NLIC
+      pu.cu->altLMFlag = affineMergeCtx.altLMFlag[pu.mergeIdx];
+      pu.cu->altLMParaUnit = affineMergeCtx.altLMParaNeighbours[pu.mergeIdx];
+#endif
 #if INTER_LIC
       pu.cu->licFlag    = affineMergeCtx.licFlags          [pu.mergeIdx];
 #endif
@@ -17997,6 +19571,25 @@ void EncCu::xCheckRDCostInter( CodingStructure *&tempCS, CodingStructure *&bestC
 
   m_bestModeUpdated = tempCS->useDbCost = bestCS->useDbCost = false;
 
+#if JVET_AG0276_LIC_SLOPE_ADJUST
+  bool testLicSlopeAdjust = tempCS->sps->getLicSlopeAdjustEnabledFlag() && lic && bdmvrAmSearchLoop == 0;
+  testLicSlopeAdjust &= (tempCS->area.Y().x || tempCS->area.Y().y);
+  testLicSlopeAdjust &= CU::licSlopeSizeTlCond(tempCS->area.Y().width, tempCS->area.Y().height, tempCS->slice->getTLayer());
+  int licDeltaE = testLicSlopeAdjust ? LIC_SLOPE_MAX_NUM_DELTA : 0;
+  for (int licDeltaIdx = 0; licDeltaIdx <= licDeltaE; licDeltaIdx++)
+  {
+    int licDelta = g_licSlopeDeltaSet[licDeltaIdx];
+    bcwLoopNum = licDelta == 0 ? bcwLoopNum : 1;
+    if (licDelta != 0)
+    {
+      ComprCUCtx cuECtx = m_modeCtrl->getComprCUCtx();
+      double licCost = cuECtx.get<double>(BEST_LIC_COST);
+      if (licCost != MAX_DOUBLE * .5 && m_pcEncCfg->getFastLicAffine() && ((licCost > bestCS->cost * 1.5 && m_pcEncCfg->getIntraPeriod() > 1) || (licCost > bestCS->cost * 1.4 && m_pcEncCfg->getIntraPeriod() < 0)))
+      {
+        continue;
+      }
+    }
+#endif
   for( int bcwLoopIdx = 0; bcwLoopIdx < bcwLoopNum; bcwLoopIdx++ )
   {
     if( m_pcEncCfg->getUseBcwFast() )
@@ -18039,6 +19632,9 @@ void EncCu::xCheckRDCostInter( CodingStructure *&tempCS, CodingStructure *&bestC
   cu.predMode         = MODE_INTER;
 #if INTER_LIC
   cu.licFlag          = lic;
+#if JVET_AG0276_LIC_SLOPE_ADJUST
+  cu.licDelta        = licDelta;
+#endif
 #endif
   cu.chromaQpAdj      = m_cuChromaQpOffsetIdxPlus1;
   cu.qp               = encTestMode.qp;
@@ -18079,6 +19675,12 @@ void EncCu::xCheckRDCostInter( CodingStructure *&tempCS, CodingStructure *&bestC
   {
     m_pcInterSearch->setDoAffineLic(bestCS->cus.front()->affine || bestCS->cus.front()->licFlag);
   }
+#if JVET_AG0276_LIC_SLOPE_ADJUST
+  else if (licDelta != 0)
+  {
+    m_pcInterSearch->setDoAffineLic(bestCS->cus.front()->affine || bestCS->cus.front()->licFlag);
+  }
+#endif
 #endif
   if (cu.firstPU->amvpMergeModeFlag[0] || cu.firstPU->amvpMergeModeFlag[1])
   {
@@ -18125,6 +19727,14 @@ void EncCu::xCheckRDCostInter( CodingStructure *&tempCS, CodingStructure *&bestC
   }
   CHECK(!(testBcw || (!testBcw && bcwIdx == BCW_DEFAULT)), " !( bTestBcw || (!bTestBcw && bcwIdx == BCW_DEFAULT ) )");
 
+#if JVET_AG0276_LIC_SLOPE_ADJUST
+  if (licDelta != 0 && cu.firstPU->interDir == 3)
+  {
+    tempCS->initStructData(encTestMode.qp);
+    continue;
+  }
+#endif
+
   bool isEqualUni = false;
   if( m_pcEncCfg->getUseBcwFast() )
   {
@@ -18382,6 +19992,9 @@ void EncCu::xCheckRDCostInter( CodingStructure *&tempCS, CodingStructure *&bestC
     break;
   }
  }  // for( UChar bcwLoopIdx = 0; bcwLoopIdx < bcwLoopNum; bcwLoopIdx++ )
+#if JVET_AG0276_LIC_SLOPE_ADJUST
+  }
+#endif
   if ( m_bestModeUpdated && bestCS->cost != MAX_DOUBLE )
   {
     xCalDebCost( *bestCS, partitioner );
@@ -18451,7 +20064,32 @@ bool EncCu::xCheckRDCostInterIMV(CodingStructure *&tempCS, CodingStructure *&bes
 #endif
   double curBestCost = bestCS->cost;
   double equBcwCost = MAX_DOUBLE;
-
+#if JVET_AG0276_LIC_SLOPE_ADJUST
+  bool testLicSlopeAdjust = tempCS->sps->getLicSlopeAdjustEnabledFlag() && lic;
+  testLicSlopeAdjust &= (tempCS->area.Y().x || tempCS->area.Y().y);
+  testLicSlopeAdjust &= CU::licSlopeSizeTlCond(tempCS->area.Y().width, tempCS->area.Y().height, tempCS->slice->getTLayer());
+  int licDeltaE = testLicSlopeAdjust ? LIC_SLOPE_MAX_NUM_DELTA : 0;
+  for (int licDeltaIdx = 0; licDeltaIdx <= licDeltaE; licDeltaIdx++)
+  {
+    int licDelta = g_licSlopeDeltaSet[licDeltaIdx];
+    bcwLoopNum = licDelta == 0 ? bcwLoopNum : 1;
+    if (licDelta != 0 && iIMV > 1)
+    {
+      if (!bestCS->cus.front()->licFlag)
+      {
+        continue;
+      }
+    }
+    if (licDelta != 0)
+    {
+      ComprCUCtx cuECtx = m_modeCtrl->getComprCUCtx();
+      double licCost = cuECtx.get<double>(BEST_LIC_COST);
+      if (licCost != MAX_DOUBLE * .5 && m_pcEncCfg->getFastLicAffine() && ((licCost > bestCS->cost * 1.5 && m_pcEncCfg->getIntraPeriod() > 1) || (licCost > bestCS->cost * 1.4 && m_pcEncCfg->getIntraPeriod() < 0)))
+      {
+        continue;
+      }
+    }
+#endif
   for( int bcwLoopIdx = 0; bcwLoopIdx < bcwLoopNum; bcwLoopIdx++ )
   {
     if( m_pcEncCfg->getUseBcwFast() )
@@ -18507,6 +20145,9 @@ bool EncCu::xCheckRDCostInterIMV(CodingStructure *&tempCS, CodingStructure *&bes
   cu.predMode         = MODE_INTER;
 #if INTER_LIC
   cu.licFlag          = lic;
+#if JVET_AG0276_LIC_SLOPE_ADJUST
+  cu.licDelta        = licDelta;
+#endif
 #endif
   cu.chromaQpAdj      = m_cuChromaQpOffsetIdxPlus1;
   cu.qp               = encTestMode.qp;
@@ -18551,7 +20192,13 @@ bool EncCu::xCheckRDCostInterIMV(CodingStructure *&tempCS, CodingStructure *&bes
   {
     m_pcInterSearch->setDoAffineLic(bestCS->cus.front()->affine || bestCS->cus.front()->licFlag);
   }
-#endif 
+#if JVET_AG0276_LIC_SLOPE_ADJUST
+  else if (licDelta != 0)
+  {
+    m_pcInterSearch->setDoAffineLic(bestCS->cus.front()->affine || bestCS->cus.front()->licFlag);
+  }
+#endif
+#endif
 #endif
 #if JVET_AF0159_AFFINE_SUBPU_BDOF_REFINEMENT
   m_pcInterSearch->setBdofSubPuMvBuf(m_mvBufEncMhpAffineBDOF);
@@ -18587,6 +20234,14 @@ bool EncCu::xCheckRDCostInterIMV(CodingStructure *&tempCS, CodingStructure *&bes
   }
   CHECK(!(testBcw || (!testBcw && bcwIdx == BCW_DEFAULT)), " !( bTestBcw || (!bTestBcw && bcwIdx == BCW_DEFAULT ) )");
 
+#if JVET_AG0276_LIC_SLOPE_ADJUST
+  if (licDelta != 0 && cu.firstPU->interDir == 3)
+  {
+    tempCS->initStructData(encTestMode.qp);
+    continue;
+  }
+#endif
+
   bool isEqualUni = false;
   if( m_pcEncCfg->getUseBcwFast() )
   {
@@ -18864,6 +20519,9 @@ bool EncCu::xCheckRDCostInterIMV(CodingStructure *&tempCS, CodingStructure *&bes
   }
   validMode = true;
  } // for( UChar bcwLoopIdx = 0; bcwLoopIdx < bcwLoopNum; bcwLoopIdx++ )
+#if JVET_AG0276_LIC_SLOPE_ADJUST
+  }
+#endif
 
   if ( m_bestModeUpdated && bestCS->cost != MAX_DOUBLE )
   {
@@ -20273,12 +21931,28 @@ void EncCu::predInterSearchAdditionalHypothesisMulti(const MEResultVec& in, MERe
 #if MULTI_PASS_DMVR
     else if( pu.bdmvrRefine )
     {
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+#if TM_MRG
+      if (pu.tmMergeFlag && pu.tmMergeFlagOppositeLic)
+      {
+        m_pcInterSearch->setBdmvrSubPuMvBuf(m_mvBufBDMVR4TMOPPOSITELIC[pu.mergeIdx << 1], m_mvBufBDMVR4TMOPPOSITELIC[(pu.mergeIdx << 1) + 1]);
+      }
+      else
+#endif
+#endif
 #if TM_MRG
       if( pu.tmMergeFlag )
       {
         m_pcInterSearch->setBdmvrSubPuMvBuf( m_mvBufBDMVR4TM[pu.mergeIdx << 1], m_mvBufBDMVR4TM[( pu.mergeIdx << 1 ) + 1] );
       }
       else
+#endif
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+      if (pu.mergeOppositeLic)
+      {
+        m_pcInterSearch->setBdmvrSubPuMvBuf(m_mvBufBDMVR4OPPOSITELIC[pu.mergeIdx << 1], m_mvBufBDMVR4OPPOSITELIC[(pu.mergeIdx << 1) + 1]);
+      }
+      else
 #endif
       {
         m_pcInterSearch->setBdmvrSubPuMvBuf( m_mvBufBDMVR[pu.mergeIdx << 1], m_mvBufBDMVR[( pu.mergeIdx << 1 ) + 1] );
@@ -20392,6 +22066,15 @@ void EncCu::xCheckRDCostInterMultiHyp2Nx2N(CodingStructure *&tempCS, CodingStruc
 #if MULTI_PASS_DMVR
     if (pu.bdmvrRefine)
     {
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+#if TM_MRG
+      if (pu.tmMergeFlag && pu.tmMergeFlagOppositeLic)
+      {
+        m_pcInterSearch->setBdmvrSubPuMvBuf(m_mvBufBDMVR4TMOPPOSITELIC[pu.mergeIdx << 1], m_mvBufBDMVR4TMOPPOSITELIC[(pu.mergeIdx << 1) + 1]);
+      }
+      else
+#endif
+#endif
 #if TM_MRG
       if( pu.tmMergeFlag )
       {
@@ -20406,7 +22089,18 @@ void EncCu::xCheckRDCostInterMultiHyp2Nx2N(CodingStructure *&tempCS, CodingStruc
       }
       else
 #endif
-      m_pcInterSearch->setBdmvrSubPuMvBuf(m_mvBufBDMVR[pu.mergeIdx << 1], m_mvBufBDMVR[(pu.mergeIdx << 1) + 1]);
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+      if (pu.mergeOppositeLic)
+      {
+        m_pcInterSearch->setBdmvrSubPuMvBuf(m_mvBufBDMVR4OPPOSITELIC[pu.mergeIdx << 1], m_mvBufBDMVR4OPPOSITELIC[(pu.mergeIdx << 1) + 1]);
+      }
+      else
+      {
+#endif
+        m_pcInterSearch->setBdmvrSubPuMvBuf(m_mvBufBDMVR[pu.mergeIdx << 1], m_mvBufBDMVR[(pu.mergeIdx << 1) + 1]);
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+      }
+#endif
     }
     else
     {
@@ -20479,6 +22173,19 @@ void EncCu::xCheckRDCostInterMultiHyp2Nx2N(CodingStructure *&tempCS, CodingStruc
 #if MULTI_PASS_DMVR
     if (pu.bdmvrRefine)
     {
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+#if TM_MRG
+      if (pu.tmMergeFlag && pu.tmMergeFlagOppositeLic)
+      {
+        PU::spanMotionInfo(pu, mrgCtx,
+#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION
+          pu.colIdx,
+#endif
+          m_mvBufBDMVR4TMOPPOSITELIC[pu.mergeIdx << 1], m_mvBufBDMVR4TMOPPOSITELIC[(pu.mergeIdx << 1) + 1], m_pcInterSearch->getBdofSubPuMvOffset());
+      }
+      else
+#endif
+#endif
 #if TM_MRG
       if( pu.tmMergeFlag )
       {
@@ -20501,11 +22208,38 @@ void EncCu::xCheckRDCostInterMultiHyp2Nx2N(CodingStructure *&tempCS, CodingStruc
       }
       else
 #endif
-        PU::spanMotionInfo(pu, mrgCtx,
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+        if (pu.mergeOppositeLic)
+        {
+#if JVET_AG0276_LIC_BDOF_BDMVR
+          if (pu.cu->licFlag == true)
+          {
+            memset((void*)m_pcInterSearch->getBdofSubPuMvOffset(), 0, BDOF_SUBPU_MAX_NUM * sizeof(Mv));
+          }
+#endif
+          PU::spanMotionInfo(pu, mrgCtx,
+#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION
+            pu.colIdx,
+#endif
+            m_mvBufBDMVR4OPPOSITELIC[pu.mergeIdx << 1], m_mvBufBDMVR4OPPOSITELIC[(pu.mergeIdx << 1) + 1], m_pcInterSearch->getBdofSubPuMvOffset());
+        }
+        else
+#endif
+#if JVET_AG0276_LIC_BDOF_BDMVR
+        {
+          if (pu.cu->licFlag == true)
+          {
+            memset((void*)m_pcInterSearch->getBdofSubPuMvOffset(), 0, BDOF_SUBPU_MAX_NUM * sizeof(Mv));
+          }
+#endif
+          PU::spanMotionInfo(pu, mrgCtx,
 #if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION
           pu.colIdx,
 #endif
           m_mvBufBDMVR[pu.mergeIdx << 1], m_mvBufBDMVR[(pu.mergeIdx << 1) + 1], m_pcInterSearch->getBdofSubPuMvOffset());
+#if JVET_AG0276_LIC_BDOF_BDMVR
+        }
+#endif
     }
 #endif
     pu.mvRefine = false;
diff --git a/source/Lib/EncoderLib/EncCu.h b/source/Lib/EncoderLib/EncCu.h
index afe0df047..64bdcf4bc 100644
--- a/source/Lib/EncoderLib/EncCu.h
+++ b/source/Lib/EncoderLib/EncCu.h
@@ -392,6 +392,12 @@ private:
   Mv                    m_mvBufEncBDOF4BM[BM_MRG_MAX_NUM_CANDS<<1][BDOF_SUBPU_MAX_NUM];
 #endif
 #endif
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+  Mv                    m_mvBufBDMVR4OPPOSITELIC[MRG_MAX_NUM_CANDS << 1][MAX_NUM_SUBCU_DMVR];
+  Mv                    m_mvBufEncBDOF4OPPOSITELIC[MRG_MAX_NUM_CANDS][BDOF_SUBPU_MAX_NUM];
+  Mv                    m_mvBufBDMVR4TMOPPOSITELIC[(TM_MRG_MAX_NUM_INIT_CANDS << 1)][MAX_NUM_SUBCU_DMVR];
+  Mv                    m_mvBufEncBDOF4TMOPPOSITELIC[MRG_MAX_NUM_CANDS][BDOF_SUBPU_MAX_NUM];
+#endif
 #if JVET_AE0046_BI_GPM
   Mv*                   m_mvBufBDMVR4GPM[2];
   Mv*                   m_mvBufEncBDOF4GPM[GEO_NUM_TM_MV_CAND][MRG_MAX_NUM_CANDS];
@@ -406,6 +412,11 @@ private:
   bool                  m_doEncAffineBDOF[AFFINE_MRG_MAX_NUM_CANDS];
   bool                  m_doEncAffineBmBDOF[AFFINE_ADAPTIVE_DMVR_INIT_SIZE << 1];
   Mv                    m_mvBufEncMhpAffineBDOF[BDOF_SUBPU_MAX_NUM];
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+  Mv                    m_mvBufEncAffineBDOFOppositeLic[AFFINE_MRG_MAX_NUM_CANDS][BDOF_SUBPU_MAX_NUM];
+  bool                  m_doEncAffineBDOFOppositeLic[AFFINE_MRG_MAX_NUM_CANDS];
+  Mv                    m_mvBufEncMhpAffineBDOFOppositeLic[BDOF_SUBPU_MAX_NUM];
+#endif
 #endif
 #if JVET_X0083_BM_AMVP_MERGE_MODE || JVET_AE0046_BI_GPM
   Mv                    m_mvBufEncAmBDMVR[2][MAX_NUM_SUBCU_DMVR];
@@ -532,6 +543,18 @@ protected:
 #endif
 
                               );
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+  void xCheckSATDCostRegularMergeOppositeLic
+  (CodingStructure *&tempCS, CodingUnit &cu, PredictionUnit &pu, MergeCtx mergeCtxOppositeLic, PelUnitBuf *acMergeTempBuffer[MMVD_MRG_MAX_RD_NUM], PelUnitBuf *&singleMergeTempBuffer, PelUnitBuf  acMergeTmpBuffer[MRG_MAX_NUM_CANDS]
+#if !MULTI_PASS_DMVR
+    , Mv   refinedMvdL0[MAX_NUM_PARTS_IN_CTU][MRG_MAX_NUM_CANDS]
+#endif
+    , 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
+  );
+#endif
 #if JVET_X0049_ADAPT_DMVR
 #if JVET_AA0093_REFINED_MOTION_FOR_ARMC
   void xCheckSATDCostBMMerge
@@ -556,9 +579,14 @@ protected:
   (CodingStructure *&tempCS, CodingUnit &cu, PredictionUnit &pu, AffineMergeCtx affineMergeCtx, MergeCtx mergeCtx, PelUnitBuf *acMergeTempBuffer[MMVD_MRG_MAX_RD_NUM], PelUnitBuf *&singleMergeTempBuffer, PelUnitBuf  acMergeAffineBuffer[AFFINE_MRG_MAX_NUM_CANDS]
     , 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);
 #endif
+#if JVET_AG0276_NLIC
+  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],
+                               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, MergeCtx mergeCtx1);
+#else
   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]
                                 , 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);
+#endif
 #if JVET_X0141_CIIP_TIMD_TM && TM_MRG
   void xCheckSATDCostCiipTmMerge
                               (CodingStructure *&tempCS, CodingUnit &cu, PredictionUnit &pu, MergeCtx mergeCtx, PelUnitBuf *acMergeTempBuffer[MMVD_MRG_MAX_RD_NUM], PelUnitBuf *&singleMergeTempBuffer, PelUnitBuf  acTmMergeTmpBuffer[MRG_MAX_NUM_CANDS]
@@ -580,6 +608,12 @@ protected:
                               ( CodingStructure *&tempCS, CodingUnit &cu, PredictionUnit &pu, AffineMergeCtx affineMergeCtx, 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);
 #endif
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+  void xCheckSATDCostAffineMergeOppositeLic
+  (CodingStructure *&tempCS, CodingUnit &cu, PredictionUnit &pu, AffineMergeCtx affineMergeCtx, 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
+  );
+#endif
 #if JVET_AD0182_AFFINE_DMVR_PLUS_EXTENSIONS
   void xCheckSATDCostBMAffineMerge
   (CodingStructure *&tempCS, CodingUnit &cu, PredictionUnit &pu, AffineMergeCtx affineMergeCtxL0, RefPicList reflist, MergeCtx& mrgCtx, PelUnitBuf *acMergeTempBuffer[MMVD_MRG_MAX_RD_NUM], PelUnitBuf *&singleMergeTempBuffer
@@ -598,6 +632,17 @@ protected:
 #endif
                                );
 #endif
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+#if TM_MRG
+  void xCheckSATDCostTMMergeOppositeLic
+  (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
+#if MULTI_PASS_DMVR
+    , bool* applyBDMVR
+#endif
+  );
+#endif
+#endif
 #if TM_MRG
   void xCheckSATDCostTMMerge
                               ( CodingStructure *&tempCS, CodingUnit &cu, PredictionUnit &pu, MergeCtx& mrgCtx, PelUnitBuf *acMergeTempBuffer[MMVD_MRG_MAX_RD_NUM], PelUnitBuf *&singleMergeTempBuffer
diff --git a/source/Lib/EncoderLib/EncLib.cpp b/source/Lib/EncoderLib/EncLib.cpp
index 8e4b5044d..f1ee20cc4 100644
--- a/source/Lib/EncoderLib/EncLib.cpp
+++ b/source/Lib/EncoderLib/EncLib.cpp
@@ -1812,6 +1812,15 @@ void EncLib::xInitSPS( SPS& sps )
   sps.setBDOFEnabledFlag                    ( m_BIO );
 #if JVET_W0090_ARMC_TM
   sps.setUseAML                             ( m_AML );
+#if JVET_AG0276_NLIC
+  sps.setUseAltLM                           ( m_altLM );
+  sps.setUseAffAltLM                        ( m_affAltLM );
+#endif
+#endif
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+  sps.setUseMergeOppositeLic                ( m_mergeOppositeLic );
+  sps.setUseTMMergeOppositeLic              ( m_mergeTMOppositeLic );
+  sps.setUseAffMergeOppositeLic             ( m_mergeAffOppositeLic );
 #endif
 #if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION 
   sps.setUseFastSubTmvp                     ((m_sourceWidth * m_sourceHeight) > (m_intraPeriod == -1 ? 0 : 832 * 480));
@@ -1820,10 +1829,22 @@ void EncLib::xInitSPS( SPS& sps )
   sps.setUseArmcRefinedMotion               ( m_armcRefinedMotion );
 #endif
   sps.setMaxNumMergeCand(getMaxNumMergeCand());
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+  sps.setMaxNumOppositeLicMergeCand( getMaxNumOppositeLicMergeCand() );
+#endif
 #if JVET_X0049_ADAPT_DMVR
   sps.setMaxNumBMMergeCand(getMaxNumBMMergeCand());
 #endif
   sps.setMaxNumAffineMergeCand(getMaxNumAffineMergeCand());
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+  sps.setMaxNumAffineOppositeLicMergeCand( getMaxNumAffineOppositeLicMergeCand() );
+  if (getIntraPeriod() < 0 && getBaseQP() > 32 )
+  {
+    sps.setUseMergeOppositeLic(false);
+    sps.setUseTMMergeOppositeLic(false);
+    sps.setUseAffMergeOppositeLic(false);
+  }
+#endif
   sps.setMaxNumIBCMergeCand(getMaxNumIBCMergeCand());
   sps.setMaxNumGeoCand(getMaxNumGeoCand());
 #if JVET_AG0164_AFFINE_GPM
@@ -1836,6 +1857,37 @@ void EncLib::xInitSPS( SPS& sps )
   sps.setUseAffineType         ( m_AffineType );
 #if JVET_AF0163_TM_SUBBLOCK_REFINEMENT
   sps.setUseAffineTM           ( m_useAffineTM );
+#if JVET_AG0276_NLIC
+  sps.setUseAffAltLMTM         ( m_useAffAltLMTM );
+  if (getIntraPeriod() > 0)
+  {
+    if ((getSourceWidth() * getSourceHeight()) > (832 * 480) && ((getSourceWidth() * getSourceHeight()) < (3840 * 2160)))
+    {
+      sps.setUseAffAltLMTM(false);
+    }
+    if (getBaseQP() > 32)
+    {
+      sps.setUseAltLM(false);
+      sps.setUseAffAltLM(false);
+      sps.setUseAffAltLMTM(false);
+    }
+    else if (getBaseQP() < 27)
+    {
+      sps.setUseAltLM(false);
+      sps.setUseAffAltLM(true);
+      sps.setUseAffAltLMTM(true);
+    }
+  }
+  else
+  {
+    sps.setUseAffAltLM(false);
+    sps.setUseAffAltLMTM(false);
+    if (getBaseQP() < 27)
+    {
+      sps.setUseAltLM(false);
+    }
+  }
+#endif
 #endif
 #if JVET_AG0135_AFFINE_CIIP
   sps.setUseCiipAffine         (((m_sourceWidth * m_sourceHeight) > (m_intraPeriod == -1 ? 832 * 480 : 0)) ? m_useCiipAffine : false);
@@ -1882,6 +1934,9 @@ void EncLib::xInitSPS( SPS& sps )
   sps.setUseBcw                ( m_bcw );
 #if INTER_LIC
   sps.setLicEnabledFlag        ( m_lic );
+#if JVET_AG0276_LIC_SLOPE_ADJUST
+  sps.setLicSlopeAdjustEnabledFlag( m_licSlopeAdjust );
+#endif
 #endif
 #if LUMA_ADAPTIVE_DEBLOCKING_FILTER_QP_OFFSET
   sps.setLadfEnabled           ( m_LadfEnabled );
@@ -2709,6 +2764,9 @@ void EncLib::xInitPicHeader(PicHeader &picHeader, const SPS &sps, const PPS &pps
 
   // merge list sizes
   picHeader.setMaxNumAffineMergeCand(getMaxNumAffineMergeCand());
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+  picHeader.setMaxNumAffineOppositeLicMergeCand( getMaxNumAffineOppositeLicMergeCand() );
+#endif
   // copy partitioning constraints from SPS
   picHeader.setSplitConsOverrideFlag(false);
   picHeader.setMinQTSizes( sps.getMinQTSizes() );
diff --git a/source/Lib/EncoderLib/EncModeCtrl.cpp b/source/Lib/EncoderLib/EncModeCtrl.cpp
index 98b86025c..5cd6407fc 100644
--- a/source/Lib/EncoderLib/EncModeCtrl.cpp
+++ b/source/Lib/EncoderLib/EncModeCtrl.cpp
@@ -1733,6 +1733,9 @@ bool EncModeCtrlMTnoRQT::tryMode( const EncTestMode& encTestmode, const CodingSt
     )
 #endif
   {
+#if JVET_AG0276_NLIC
+    if (encTestmode.type != ETM_POST_DONT_SPLIT)
+#endif
     return false;
   }
 
@@ -1776,7 +1779,11 @@ bool EncModeCtrlMTnoRQT::tryMode( const EncTestMode& encTestmode, const CodingSt
   const uint32_t             numComp     = getNumberValidComponents( slice.getSPS()->getChromaFormatIdc() );
   const uint32_t             width       = partitioner.currArea().lumaSize().width;
   const CodingStructure *bestCS      = cuECtx.bestCS;
+#if JVET_AG0276_NLIC
+  CodingUnit            *bestCU = cuECtx.bestCU;
+#else
   const CodingUnit      *bestCU      = cuECtx.bestCU;
+#endif
   const EncTestMode      bestMode    = bestCS ? getCSEncMode( *bestCS ) : EncTestMode();
 
   CodedCUInfo    &relatedCU          = getBlkInfo( partitioner.currArea() );
@@ -2498,6 +2505,99 @@ bool EncModeCtrlMTnoRQT::tryMode( const EncTestMode& encTestmode, const CodingSt
         CacheBlkInfoCtrl::touch(partitioner.currArea());
 #endif
         cuECtx.set( IS_BEST_NOSPLIT_SKIP, bestCU->skip );
+#if JVET_AG0276_NLIC
+        if (cuECtx.bestCU->altLMFlag)
+        {
+          cuECtx.bestCU->secAltLMParaUnit = cuECtx.bestCU->altLMParaUnit;
+        }
+        else
+        {
+          cuECtx.bestCU->secAltLMParaUnit = cuECtx.bestCU->altLMParaUnit;
+        }
+        cuECtx.bestCU->altLMParaUnit.resetAltLinearModel();
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+        cuECtx.bestCU->altLMBRParaUnit.resetAltLinearModel();
+#endif
+        if (CU::isSecLicParaNeeded(*bestCU))
+        {
+          UnitArea   localUnitArea(bestCU->chromaFormat, Area(0, 0, bestCU->lumaSize().width, bestCU->lumaSize().height));
+          PelUnitBuf predBeforeMCAdjBuffer = m_pcInterSearch->m_acPredBeforeLICBuffer[REF_PIC_LIST_0].getBuf(localUnitArea);
+
+          bool isPredSampleRefined = CU::isPredRefined(*bestCU);
+          if (!isPredSampleRefined)
+          {
+            bool obmcApplied = true;
+            if (bestCU->cs->sps->getUseOBMC() == false || bestCU->obmcFlag == false || bestCU->lwidth() * bestCU->lheight() < 32)
+            {
+              obmcApplied = false;
+            }
+            if (obmcApplied && bestCU->firstPU->mergeFlag)
+            {
+              if (m_pcInterSearch->isSCC(*bestCU->firstPU))
+              {
+                obmcApplied = false;
+              }
+            }
+            if (obmcApplied)
+            {
+              isPredSampleRefined = true;
+            }
+          }
+          if (CU::isAllowSecLicPara(*bestCU))
+          {
+            if (isPredSampleRefined)
+            {
+#if INTER_LIC
+              bool orgLicFlag = bestCU->licFlag;
+              bestCU->licFlag = false;
+#endif
+              bool orgCiipFlag = bestCU->firstPU->ciipFlag;
+              bestCU->firstPU->ciipFlag = false;
+              m_pcInterSearch->xPredWoRefinement(*bestCU->firstPU, predBeforeMCAdjBuffer);
+#if INTER_LIC
+              bestCU->licFlag = orgLicFlag;
+#endif
+              bestCU->firstPU->ciipFlag = orgCiipFlag;
+            }
+            else
+            {
+              m_pcInterSearch->motionCompensation(*cuECtx.bestCU);
+              predBeforeMCAdjBuffer.copyFrom(cuECtx.bestCU->cs->getPredBuf(*cuECtx.bestCU->firstPU));
+            }
+          }
+          else
+          {
+            if (cuECtx.bestCU->affine && cuECtx.bestCU->firstPU->mergeFlag && cuECtx.bestCU->cs->sps->getUseOBMC() && cuECtx.bestCU->obmcFlag && (cuECtx.bestCU->cs->sps->getUseAltLM() || cuECtx.bestCU->cs->sps->getUseAffAltLM()))
+            {
+              if (cuECtx.bestCU->obmcFlag && m_pcInterSearch->isSCC(*cuECtx.bestCU->firstPU) && !CU::isTLCond(*cuECtx.bestCU))
+              {
+                cuECtx.bestCU->obmcFlag = false;
+              }
+            }
+          }
+          if (CU::isAllowSecLicPara(*bestCU))
+          {
+            PelUnitBuf recBuf = m_pcInterSearch->m_acPredBeforeLICBuffer[REF_PIC_LIST_1].getBuf(localUnitArea);
+            recBuf.copyFrom(cuECtx.bestCU->cs->getRecoBuf(*cuECtx.bestCU->firstPU));
+            if (bestCS->slice->getLmcsEnabledFlag() && m_pcInterSearch->m_pcReshape->getCTUFlag())
+            {
+              recBuf.Y().rspSignal(m_pcInterSearch->m_pcReshape->getInvLUT());
+            }
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+            m_pcInterSearch->xDevSecLicPara<false>(*cuECtx.bestCU, predBeforeMCAdjBuffer, recBuf);
+#else
+            m_pcInterSearch->xDevSecLicPara(*cuECtx.bestCU, predBeforeMCAdjBuffer, recBuf);
+#endif
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+            m_pcInterSearch->xDevSecLicPara<true>(*cuECtx.bestCU, predBeforeMCAdjBuffer, recBuf);
+            if ((cuECtx.bestCU->altLMBRParaUnit.scale[COMPONENT_Y] == cuECtx.bestCU->altLMParaUnit.scale[COMPONENT_Y]) && (cuECtx.bestCU->altLMBRParaUnit.offset[COMPONENT_Y] == cuECtx.bestCU->altLMParaUnit.offset[COMPONENT_Y]))
+            {
+              cuECtx.bestCU->altLMBRParaUnit.resetAltLinearModel();
+            }
+#endif
+          }
+        }
+#endif
       }
     }
 
diff --git a/source/Lib/EncoderLib/InterSearch.cpp b/source/Lib/EncoderLib/InterSearch.cpp
index ed3698952..b3b0e8e65 100644
--- a/source/Lib/EncoderLib/InterSearch.cpp
+++ b/source/Lib/EncoderLib/InterSearch.cpp
@@ -5936,6 +5936,9 @@ void InterSearch::predInterSearch(CodingUnit& cu, Partitioner& partitioner)
                                             pu.cu->imv <= (pu.cu->slice->getSPS()->getAMVREnabledFlag() ? IMV_4PEL : 0));
   CodingUnit *bestCU  = pu.cu->cs->bestCS != nullptr ? pu.cu->cs->bestCS->getCU( CHANNEL_TYPE_LUMA ) : nullptr;
   bool trySmvd        = ( bestCU != nullptr && pu.cu->imv == 2 && checkAffine ) ? ( !bestCU->firstPU->mergeFlag && !bestCU->affine ) : true;
+#if JVET_AG0276_LIC_SLOPE_ADJUST
+  trySmvd &= pu.cu->licDelta == 0;
+#endif
 #if JVET_AG0098_AMVP_WITH_SBTMVP
   bool bestSubTmvp = (bestCU != NULL && (bestCU->firstPU->mergeType == MRG_TYPE_SUBPU_ATMVP || bestCU->firstPU->amvpSbTmvpFlag)) ? true : false;
   bool tryAmvpSbTmvp = cs.sps->getSbTMVPEnabledFlag() && cs.slice->getAmvpSbTmvpEnabledFlag() && !cu.licFlag && checkNonAffine && bcwIdx == BCW_DEFAULT ? true : false;
@@ -6222,6 +6225,9 @@ void InterSearch::predInterSearch(CodingUnit& cu, Partitioner& partitioner)
       //  Bi-predictive Motion estimation
 #if JVET_AD0213_LIC_IMP
       bool condOn = cu.slice->getCheckLDC() || bcwIdx == BCW_DEFAULT || !m_affineModeSelected || !m_pcEncCfg->getUseBcwFast() || (cu.licFlag && bcwIdx != BCW_DEFAULT);
+#endif
+#if JVET_AG0276_LIC_SLOPE_ADJUST
+      condOn &= cu.licDelta == 0;
 #endif
       if( ( cs.slice->isInterB() ) && ( PU::isBipredRestriction( pu ) == false )
 #if JVET_AD0213_LIC_IMP
@@ -7500,6 +7506,12 @@ void InterSearch::predInterSearch(CodingUnit& cu, Partitioner& partitioner)
 #if JVET_X0083_BM_AMVP_MERGE_MODE
     if (pu.bdmvrRefine)
     {
+#if JVET_AG0276_LIC_BDOF_BDMVR
+      if (cu.licFlag == true)
+      {
+        memset((void*)getBdofSubPuMvOffset(), 0, BDOF_SUBPU_MAX_NUM * sizeof(Mv));
+      }
+#endif
       PU::spanMotionInfo(*cu.firstPU, MergeCtx(),
 #if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION
         pu.colIdx,
@@ -7896,6 +7908,10 @@ void InterSearch::predInterSearchAdditionalHypothesis(PredictionUnit& pu, const
   const int numWeights = sps.getNumAddHypWeights();
   unsigned idx1, idx2, idx3, idx4;
   getAreaIdx(pu.Y(), *pu.cs->slice->getPPS()->pcv, idx1, idx2, idx3, idx4);
+#if JVET_AG0276_NLIC
+  bool savedAltLMFlag = pu.cu->altLMFlag;
+  AltLMInterUnit savedAltLMParaUnit = pu.cu->altLMParaUnit;
+#endif
 #if INTER_LIC
   auto savedLICFlag = pu.cu->licFlag;
 #endif
@@ -7953,6 +7969,10 @@ void InterSearch::predInterSearchAdditionalHypothesis(PredictionUnit& pu, const
         fakePredData.refIdx[1 - refList] = -1;
         fakePredData.cu->affine = false;
         fakePredData.cu->imv = m_geoMrgCtx.useAltHpelIf[i] ? IMV_HPEL : 0;
+#if JVET_AG0276_NLIC
+        fakePredData.cu->altLMFlag = m_geoMrgCtx.altLMFlag[i];
+        fakePredData.cu->altLMParaUnit = m_geoMrgCtx.altLMParaNeighbours[i];
+#endif
         fakePredData.mvRefine = true;
         if (savedLICFlag)
         {
@@ -7964,6 +7984,10 @@ void InterSearch::predInterSearchAdditionalHypothesis(PredictionUnit& pu, const
         }
         fakePredData.mvRefine = false;
         // the restore of affine flag and imv flag has to be here
+#if JVET_AG0276_NLIC
+        fakePredData.cu->altLMFlag = savedAltLMFlag;
+        fakePredData.cu->altLMParaUnit = savedAltLMParaUnit;
+#endif
         fakePredData.cu->imv = savedIMV;
         fakePredData.cu->affine = savedAffine;
       }
@@ -8128,11 +8152,19 @@ void InterSearch::predInterSearchAdditionalHypothesis(PredictionUnit& pu, const
           cMv = cMvPred;
         }
         Distortion uiCostTemp = 0;
+#if JVET_AG0276_NLIC
+        pu.cu->altLMFlag = false;
+        pu.cu->altLMParaUnit.resetAltLinearModel();
+#endif
 #if INTER_LIC
         pu.cu->licFlag = tempMHPredData.licFlag;
 #endif
         xMotionEstimation(pu, tempOrigBuf, eRefPicList, cMvPred, iRefIdxPred, cMv, tempMHPredData.mvpIdx, uiBits, uiCostTemp, amvpInfo, false, g_addHypWeight[tempMHPredData.weightIdx]);
         xCheckBestMVP(eRefPicList, cMv, cMvPred, tempMHPredData.mvpIdx, amvpInfo, uiBits, uiCostTemp, pu.cu->imv);
+#if JVET_AG0276_NLIC
+        pu.cu->altLMFlag = savedAltLMFlag;
+        pu.cu->altLMParaUnit = savedAltLMParaUnit;
+#endif
 #if INTER_LIC
         pu.cu->licFlag = savedLICFlag;
 #endif
@@ -11024,6 +11056,9 @@ void InterSearch::xPredAffineInterSearch( PredictionUnit&       pu,
     // Therefore, the undefined bits would be stored in MHP candidates.
     && !(pu.cu->affineType == AFFINEMODEL_6PARAM && (refIdx4Para[0] == NOT_VALID || refIdx4Para[1] == NOT_VALID))
 #endif
+#if JVET_AG0276_LIC_SLOPE_ADJUST
+    && pu.cu->licDelta == 0
+#endif
 #if INTER_LIC && !JVET_AD0213_LIC_IMP
     && !pu.cu->licFlag
 #endif
diff --git a/source/Lib/EncoderLib/InterSearch.h b/source/Lib/EncoderLib/InterSearch.h
index cfc1d3cea..0574ce27e 100644
--- a/source/Lib/EncoderLib/InterSearch.h
+++ b/source/Lib/EncoderLib/InterSearch.h
@@ -121,6 +121,11 @@ struct ModeInfo
 #if TM_MRG
   bool     isTMMrg;
 #endif
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+  bool     isTMMrgOppositeLic;
+  bool     isOppositeLic;
+  bool     isAffOppositeLic;
+#endif
 #if JVET_X0049_ADAPT_DMVR
   bool     isBMMrg;
   uint8_t  bmDir;
@@ -157,6 +162,11 @@ struct ModeInfo
 #if TM_MRG
     , isTMMrg(false)
 #endif
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+    , isTMMrgOppositeLic(false)
+    , isOppositeLic(false)
+    , isAffOppositeLic(false)
+#endif
 #if JVET_X0049_ADAPT_DMVR
     , isBMMrg(false)
     , bmDir(0)
@@ -192,6 +202,11 @@ struct ModeInfo
 #endif
 #if TM_MRG
     , const bool isTMMrg = false
+#endif
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+    , const bool isTMMrgOppositeLic = false
+    , const bool isOppositeLic = false
+    , const bool isAffOppositeLic = false
 #endif
   ) :
     mergeCand(mergeCand), isRegularMerge(isRegularMerge), isMMVD(isMMVD), isCIIP(isCIIP)
@@ -211,6 +226,11 @@ struct ModeInfo
 #if TM_MRG
     , isTMMrg(isTMMrg)
 #endif
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+    , isTMMrgOppositeLic(isTMMrgOppositeLic)
+    , isOppositeLic(isOppositeLic)
+    , isAffOppositeLic(isAffOppositeLic)
+#endif
 #if JVET_X0049_ADAPT_DMVR
     , isBMMrg( false )
     , bmDir( 0 )
@@ -257,6 +277,11 @@ struct ModeInfo
 #if TM_MRG
     isTMMrg = pu.tmMergeFlag;
 #endif
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+    isTMMrgOppositeLic = pu.tmMergeFlagOppositeLic;
+    isOppositeLic = pu.mergeOppositeLic;
+    isAffOppositeLic = pu.affineOppositeLic;
+#endif
 #if JVET_X0049_ADAPT_DMVR
     isBMMrg = pu.bmMergeFlag;
     bmDir = pu.bmDir;
@@ -806,7 +831,13 @@ protected:
   BilateralFilter* m_bilateralFilter;
 #endif
   TrQuant*        m_pcTrQuant;
+#if JVET_AG0276_NLIC
+public:
   EncReshape*     m_pcReshape;
+protected:
+#else
+  EncReshape*     m_pcReshape;
+#endif
 
   // ME parameters
   int             m_iSearchRange;
diff --git a/source/Lib/EncoderLib/VLCWriter.cpp b/source/Lib/EncoderLib/VLCWriter.cpp
index b9f5d30e8..66e1915e4 100644
--- a/source/Lib/EncoderLib/VLCWriter.cpp
+++ b/source/Lib/EncoderLib/VLCWriter.cpp
@@ -1380,6 +1380,12 @@ void HLSWriter::codeSPS( const SPS* pcSPS )
 #endif
 #if INTER_LIC
   WRITE_FLAG(pcSPS->getLicEnabledFlag() ? 1 : 0, "sps_lic_enabled_flag");
+#if JVET_AG0276_LIC_SLOPE_ADJUST
+  if (pcSPS->getLicEnabledFlag())
+  {
+    WRITE_FLAG(pcSPS->getLicSlopeAdjustEnabledFlag() ? 1 : 0, "sps_lic_slope_adjust_enabled_flag");
+  }
+#endif
 #endif
 
   WRITE_FLAG( pcSPS->getWrapAroundEnabledFlag() ? 1 : 0,                              "sps_ref_wraparound_enabled_flag" );
@@ -1485,6 +1491,10 @@ void HLSWriter::codeSPS( const SPS* pcSPS )
   {
     WRITE_FLAG(pcSPS->getFpelMmvdEnabledFlag() ? 1 : 0,                               "sps_mmvd_fullpel_only_flag");
   }
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+  WRITE_FLAG(pcSPS->getUseMergeOppositeLic() ? 1 : 0,                                 "sps_oppositelic_merge_enabled_flag");
+  WRITE_FLAG(pcSPS->getUseTMMergeOppositeLic() ? 1 : 0,                               "sps_TM_oppositelic_merge_enabled_flag");
+#endif
 #if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED || JVET_AD0140_MVD_PREDICTION
 #if JVET_AA0132_CONFIGURABLE_TM_TOOLS
   if (pcSPS->getTMToolsEnableFlag())
@@ -1492,6 +1502,12 @@ void HLSWriter::codeSPS( const SPS* pcSPS )
   WRITE_FLAG(pcSPS->getUseMvdPred() ? 1 : 0,                                          "sps_mvd_pred_enabled_flag");
 #endif
   WRITE_UVLC(MRG_MAX_NUM_CANDS - pcSPS->getMaxNumMergeCand(), "six_minus_max_num_merge_cand");
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+  if (pcSPS->getUseMergeOppositeLic())
+  {
+    WRITE_UVLC(REG_MRG_MAX_NUM_CANDS_OPPOSITELIC - pcSPS->getMaxNumOppositeLicMergeCand(), "five_minus_max_num_oppositelic_merge_cand");
+  }
+#endif
   WRITE_FLAG( pcSPS->getUseSBT() ? 1 : 0,                                                      "sps_sbt_enabled_flag");
 #if TM_AMVP || TM_MRG || JVET_Z0084_IBC_TM || MULTI_PASS_DMVR
   WRITE_FLAG( pcSPS->getUseDMVDMode() ? 1 : 0,                                                 "sps_dmvd_enabled_flag" );
@@ -1516,12 +1532,38 @@ void HLSWriter::codeSPS( const SPS* pcSPS )
   WRITE_UVLC(BM_MRG_MAX_NUM_CANDS - pcSPS->getMaxNumBMMergeCand(), "six_minus_max_num_bm_merge_cand");
 #endif
   WRITE_FLAG( pcSPS->getUseAffine() ? 1 : 0,                                                   "sps_affine_enabled_flag" );
+#if JVET_AG0276_NLIC
+  if (pcSPS->getUseAML()
+#if JVET_AE0174_NONINTER_TM_TOOLS_CONTROL
+    && pcSPS->getTMToolsEnableFlag()
+#endif
+    )
+  {
+    WRITE_FLAG(pcSPS->getUseAltLM() ? 1 : 0, "sps_alt_lm_enabled_flag");
+    if (pcSPS->getUseAffine())
+    {
+      WRITE_FLAG(pcSPS->getUseAffAltLM() ? 1 : 0, "sps_affine_alt_lm_enabled_flag");
+    }
+  }
+#endif
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+  if (pcSPS->getUseAffine())
+  {
+    WRITE_FLAG(pcSPS->getUseAffMergeOppositeLic() ? 1 : 0, "sps_affine_oppositelic_merge_enabled_flag");
+  }
+#endif
   if ( pcSPS->getUseAffine() )
   {
     WRITE_UVLC(AFFINE_MRG_MAX_NUM_CANDS - pcSPS->getMaxNumAffineMergeCand(), "five_minus_max_num_subblock_merge_cand");
     WRITE_FLAG( pcSPS->getUseAffineType() ? 1 : 0,                                             "sps_affine_type_flag" );
 #if AFFINE_MMVD
     WRITE_FLAG( pcSPS->getUseAffineMmvdMode() ? 1 : 0,                                         "sps_affine_mmvd_enabled_flag" );
+#endif
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+    if (pcSPS->getUseAffMergeOppositeLic())
+    {
+      WRITE_UVLC(AFF_MRG_MAX_NUM_CANDS_OPPOSITELIC - pcSPS->getMaxNumAffineOppositeLicMergeCand(), "eight_minus_max_num_oppositelic_subblock_merge_cand");
+    }
 #endif
     if (pcSPS->getAMVREnabledFlag())
     {
@@ -1541,6 +1583,12 @@ void HLSWriter::codeSPS( const SPS* pcSPS )
     {
 #endif
       WRITE_FLAG(pcSPS->getUseAffineTM() ? 1 : 0,                                              "sps_tm_affine_flag");
+#if JVET_AG0276_NLIC
+      if (pcSPS->getUseAffineTM() && pcSPS->getUseAffAltLM())
+      {
+        WRITE_FLAG(pcSPS->getUseAffAltLMTM() ? 1 : 0,                                          "sps_affine_alt_lm_tm_flag");
+      }
+#endif
 #if JVET_AA0132_CONFIGURABLE_TM_TOOLS
     }
 #endif
@@ -2680,10 +2728,16 @@ void HLSWriter::codePictureHeader( PicHeader* picHeader, bool writeRbspTrailingB
     if ( sps->getUseAffine() )
     {
       picHeader->setMaxNumAffineMergeCand(sps->getMaxNumAffineMergeCand());
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+      picHeader->setMaxNumAffineOppositeLicMergeCand(sps->getMaxNumAffineOppositeLicMergeCand());
+#endif
     }
     else
     {
       picHeader->setMaxNumAffineMergeCand(sps->getSbTMVPEnabledFlag() && picHeader->getEnableTMVPFlag());
+#if JVET_AG0276_LIC_FLAG_SIGNALING
+      picHeader->setMaxNumAffineOppositeLicMergeCand(0);
+#endif
     }
 
   // full-pel MMVD flag
-- 
GitLab