diff --git a/source/Lib/CommonLib/CommonDef.h b/source/Lib/CommonLib/CommonDef.h
index f3c86093d1fe003f2b94c90e097d33c64cab757f..043201f9b2ce2ebe3c498f0ec7041e8e396da1eb 100644
--- a/source/Lib/CommonLib/CommonDef.h
+++ b/source/Lib/CommonLib/CommonDef.h
@@ -704,6 +704,9 @@ static const int PROF_BORDER_EXT_H            =                     1;
 static const int BCW_NUM =                                          5; ///< the number of weight options
 static const int BCW_DEFAULT =                                      ((uint8_t)(BCW_NUM >> 1)); ///< Default weighting index representing for w=0.5
 static const int BCW_SIZE_CONSTRAINT =                            256; ///< disabling Bcw if cu size is smaller than 256
+#if JVET_AB0079_TM_BCW_MRG
+static const int BCW_MRG_NUM =                                      7;
+#endif
 #if NON_ADJACENT_MRG_CAND
 static const int MAX_NUM_HMVP_CANDS =                              5; ///< maximum number of HMVP candidates to be stored and used in merge list
 #else
diff --git a/source/Lib/CommonLib/InterPrediction.cpp b/source/Lib/CommonLib/InterPrediction.cpp
index 1077287a8b28e690df7396d3425dad43eb771c30..96ac4882297fc3612b2774921eab6ec1c04cc0b4 100644
--- a/source/Lib/CommonLib/InterPrediction.cpp
+++ b/source/Lib/CommonLib/InterPrediction.cpp
@@ -7207,6 +7207,188 @@ void InterPrediction::adjustMergeCandidatesInOneCandidateGroup(PredictionUnit &p
   }
 }
 
+#if JVET_AB0079_TM_BCW_MRG
+void InterPrediction::adjustMergeCandidatesBcwIdx(PredictionUnit& pu, MergeCtx& mrgCtx, const int mergeIdx)
+{
+  if (pu.ciipFlag || pu.cu->geoFlag || !pu.cs->sps->getUseAML())
+  {
+    return;
+  }
+  int nWidth = pu.lumaSize().width;
+  int nHeight = pu.lumaSize().height;
+  if (!xAMLGetCurBlkTemplate(pu, nWidth, nHeight))
+  {
+    return;
+  }
+
+  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)));
+  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)));
+
+  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));
+
+  DistParam cDistParam;
+  cDistParam.applyWeight = false;
+  int origBcwIdx = 0, bestBcwIdx = -1;
+  Distortion uiBestCost = MAX_UINT64;
+  Distortion uiCost = 0;
+
+  for (uint32_t uiMergeCand = 0; uiMergeCand < mrgCtx.numValidMergeCand; uiMergeCand++)
+  {
+    if (mrgCtx.interDirNeighbours[uiMergeCand] != 3)
+    {
+      continue;
+    }
+    if (mergeIdx != -1 && uiMergeCand != mergeIdx)
+    {
+      continue;
+    }
+
+    mrgCtx.setMergeInfo(pu, uiMergeCand);
+#if JVET_Z0067_RPR_ENABLE
+    bool bRefIsRescaled = false;
+    for (uint32_t refList = 0; refList < NUM_REF_PIC_LIST_01; refList++)
+    {
+      const RefPicList eRefPicList = refList ? REF_PIC_LIST_1 : REF_PIC_LIST_0;
+      bRefIsRescaled |= (pu.refIdx[refList] >= 0) ? pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[refList])->isRefScaled(pu.cs->pps) : false;
+    }
+    if (bRefIsRescaled)
+    {
+      continue;
+    }
+#endif
+    if (xCheckIdenticalMotion(pu))
+    {
+      continue;
+    }
+
+    // perform interpolation for template
+    for (uint32_t refList = 0; refList < NUM_REF_PIC_LIST_01; refList++)
+    {
+      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 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
+      }
+      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 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
+      }
+    }
+
+    // perform bi-prediction with different BCW index
+    origBcwIdx = mrgCtx.BcwIdx[uiMergeCand];
+    bestBcwIdx = -1;
+    uiBestCost = MAX_UINT64;
+    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;
+
+    for (int idx = 0; idx < BCW_MRG_NUM; idx++)
+    {
+      pu.cu->BcwIdx = g_BcwMrgParsingOrder[idx];
+      if (abs(origWeight - getBcwWeight(pu.cu->BcwIdx, REF_PIC_LIST_0)) > 1)
+      {
+        continue;
+      }
+      uiCost = 0;
+      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])
+      {
+        CPelUnitBuf srcPred0 = CPelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefLeftTemplate[0][0], pcBufPredRefLeft.Y()));
+        CPelUnitBuf srcPred1 = CPelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefLeftTemplate[1][0], pcBufPredRefLeft.Y()));
+        xWeightedAverageY(pu, srcPred0, srcPred1, pcBufPredRefLeft, pu.cu->slice->getSPS()->getBitDepths(), pu.cu->slice->clpRngs());
+        m_pcRdCost->setDistParam(cDistParam, pcBufPredCurLeft.Y(), pcBufPredRefLeft.Y(), pu.cs->sps->getBitDepth(CHANNEL_TYPE_LUMA), COMPONENT_Y, false);
+        uiCost += cDistParam.distFunc(cDistParam);
+      }
+
+      if (origBcwIdx == pu.cu->BcwIdx && bioApplied && pu.cu->BcwIdx == BCW_DEFAULT)
+      {
+        uiCost = uiCost - (uiCost >> 3) - (uiCost >> 4);
+      }
+      else if (origBcwIdx == pu.cu->BcwIdx)
+      {
+        uiCost = uiCost - (uiCost >> 4) - (uiCost >> 5);
+      }
+      else if (bioApplied && pu.cu->BcwIdx == BCW_DEFAULT)
+      {
+        uiCost = uiCost - (uiCost >> 4) - (uiCost >> 5);
+      }
+
+      if (uiCost < uiBestCost)
+      {
+        uiBestCost = uiCost;
+        bestBcwIdx = pu.cu->BcwIdx;
+      }
+    } // for (int idx = 0; idx < loopBcw; idx++)
+
+    pu.cu->BcwIdx = bestBcwIdx;
+    mrgCtx.BcwIdx[uiMergeCand] = bestBcwIdx;
+  } // for (uint32_t uiMergeCand = 0; uiMergeCand < mrgCtx.numValidMergeCand; uiMergeCand++)
+  pu.mergeIdx = mergeIdx;
+}
+#endif
+
 #if JVET_Z0102_NO_ARMC_FOR_ZERO_CAND
 void InterPrediction::adjustMergeCandidates(PredictionUnit& pu, MergeCtx& mvpMergeCandCtx, int numRetrievedMergeCand)
 {
diff --git a/source/Lib/CommonLib/InterPrediction.h b/source/Lib/CommonLib/InterPrediction.h
index 90191b11a6f909bc8c9cee425acfb41944b84338..8437016cada883090f058de1450bb6c1ffe1fad8 100644
--- a/source/Lib/CommonLib/InterPrediction.h
+++ b/source/Lib/CommonLib/InterPrediction.h
@@ -625,6 +625,9 @@ public:
 #if JVET_Z0102_NO_ARMC_FOR_ZERO_CAND
   void adjustMergeCandidates(PredictionUnit& pu, MergeCtx& smvpMergeCandCtx, int numRetrievedMergeCand);
 #endif
+#if JVET_AB0079_TM_BCW_MRG
+  void adjustMergeCandidatesBcwIdx(PredictionUnit& pu, MergeCtx& mrgCtx, const int mergeIdx = -1);
+#endif
 #if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING
   void    adjustMergeCandidatesInOneCandidateGroup(PredictionUnit &pu, MergeCtx& smvpMergeCandCtx, int numRetrievedMergeCand, int mrgCandIdx = -1);
   void    updateCandInOneCandidateGroup(MergeCtx& mrgCtx, uint32_t* RdCandList, int numCandInCategory = -1);
diff --git a/source/Lib/CommonLib/Rom.cpp b/source/Lib/CommonLib/Rom.cpp
index 3a4932f7834ce1782b597edfc1472cf141ad1933..4244a632d8e679d4a2b0425ce5e01be6615238b7 100644
--- a/source/Lib/CommonLib/Rom.cpp
+++ b/source/Lib/CommonLib/Rom.cpp
@@ -3774,7 +3774,13 @@ public:
 };
 const int8_t g_BcwLog2WeightBase = 3;
 const int8_t g_BcwWeightBase = (1 << g_BcwLog2WeightBase);
+#if JVET_AB0079_TM_BCW_MRG
+const int8_t g_BcwWeights[BCW_NUM] = { 1, 3, 4, 5, 7 };
+const int8_t g_BcwMrgWeights[BCW_MRG_NUM] = { 1, 3, 4, 5, 7, 2, 6 };
+      int8_t g_BcwMrgParsingOrder[BCW_MRG_NUM];
+#else
 const int8_t g_BcwWeights[BCW_NUM] = { -2, 3, 4, 5, 10 };
+#endif
 const int8_t g_BcwSearchOrder[BCW_NUM] = { BCW_DEFAULT, BCW_DEFAULT - 2, BCW_DEFAULT + 2, BCW_DEFAULT - 1, BCW_DEFAULT + 1 };
 int8_t g_BcwCodingOrder[BCW_NUM];
 int8_t g_BcwParsingOrder[BCW_NUM];
@@ -3783,7 +3789,11 @@ int8_t getBcwWeight(uint8_t bcwIdx, uint8_t uhRefFrmList)
 {
   // Weghts for the model: P0 + w * (P1 - P0) = (1-w) * P0 + w * P1
   // Retuning  1-w for P0 or w for P1
+#if JVET_AB0079_TM_BCW_MRG
+  return (uhRefFrmList == REF_PIC_LIST_0 ? g_BcwWeightBase - g_BcwMrgWeights[bcwIdx] : g_BcwMrgWeights[bcwIdx]);
+#else
   return (uhRefFrmList == REF_PIC_LIST_0 ? g_BcwWeightBase - g_BcwWeights[bcwIdx] : g_BcwWeights[bcwIdx]);
+#endif
 }
 
 void resetBcwCodingOrder(bool bRunDecoding, const CodingStructure &cs)
@@ -3795,7 +3805,16 @@ void resetBcwCodingOrder(bool bRunDecoding, const CodingStructure &cs)
     g_BcwParsingOrder[2 * i - 1] = BCW_DEFAULT + (int8_t)i;
     g_BcwParsingOrder[2 * i] = BCW_DEFAULT - (int8_t)i;
   }
-
+#if JVET_AB0079_TM_BCW_MRG
+  for (int i = 0; i < BCW_NUM; i++)
+  {
+    g_BcwMrgParsingOrder[i] = g_BcwParsingOrder[i];
+  }
+  for (int i = BCW_NUM; i < BCW_MRG_NUM; i++)
+  {
+    g_BcwMrgParsingOrder[i] = i;
+  }
+#endif
   // Form encoding order
   if (!bRunDecoding)
   {
diff --git a/source/Lib/CommonLib/Rom.h b/source/Lib/CommonLib/Rom.h
index 81cd7ac835d1ee02c6b9f97021e9a8a01619e1be..b782d80f43558205873c2ff0d03596435dfcd961 100644
--- a/source/Lib/CommonLib/Rom.h
+++ b/source/Lib/CommonLib/Rom.h
@@ -283,6 +283,10 @@ extern const int8_t g_BcwWeights[BCW_NUM];
 extern const int8_t g_BcwSearchOrder[BCW_NUM];
 extern       int8_t g_BcwCodingOrder[BCW_NUM];
 extern       int8_t g_BcwParsingOrder[BCW_NUM];
+#if JVET_AB0079_TM_BCW_MRG
+extern const int8_t g_BcwMrgWeights[BCW_MRG_NUM];
+extern       int8_t g_BcwMrgParsingOrder[BCW_MRG_NUM];
+#endif
 
 class CodingStructure;
 int8_t getBcwWeight(uint8_t bcwIdx, uint8_t uhRefFrmList);
diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h
index f165780b835cede48af1fb344965fe04b207c093..b09d1ba7e8ac66c62edb8e814e73dcef725e72dc 100644
--- a/source/Lib/CommonLib/TypeDef.h
+++ b/source/Lib/CommonLib/TypeDef.h
@@ -228,6 +228,7 @@
 #define JVET_AA0093_REFINED_MOTION_FOR_ARMC               1 // JVET-AA0093: Refined motion for ARMC
 #define JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC          1 // JVET-AA0093: Diversity criterion for ARMC reordering
 #endif
+#define JVET_AB0079_TM_BCW_MRG                            1 // JVET-AB0079: Template matching based BCW index derivation for merge mode with positive weights only
 
 // Transform and coefficient coding
 #define TCQ_8STATES                                       1
diff --git a/source/Lib/DecoderLib/DecCu.cpp b/source/Lib/DecoderLib/DecCu.cpp
index edaade64905bdb9ec41f1abe6238d9a050237f16..081d6f1994086ad318d7403c2fef2a9a6b85c2eb 100644
--- a/source/Lib/DecoderLib/DecCu.cpp
+++ b/source/Lib/DecoderLib/DecCu.cpp
@@ -1698,6 +1698,9 @@ void DecCu::xDeriveCUMV( CodingUnit &cu )
         PU::getInterMMVDMergeCandidates(pu, mrgCtx,
           pu.mmvdMergeIdx
         );
+#if JVET_AB0079_TM_BCW_MRG
+        m_pcInterPred->adjustMergeCandidatesBcwIdx(pu, mrgCtx, fPosBaseIdx);
+#endif
 #if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
         uint32_t mmvdLUT[MMVD_ADD_NUM];
 #if JVET_AA0093_ENHANCED_MMVD_EXTENSION
@@ -2191,12 +2194,25 @@ void DecCu::xDeriveCUMV( CodingUnit &cu )
                     }
                     pu.bmDir = 0;
                     m_pcInterPred->adjustMergeCandidatesInOneCandidateGroup(pu, mrgCtx, bmDir == 2 ? applyBDMVR4BM : NULL, NULL, NULL, mergeIdx + 1, subPuRefineList, subPuRefineListTmp, mergeIdx);
+#if JVET_AB0079_TM_BCW_MRG
+                    m_pcInterPred->adjustMergeCandidatesBcwIdx(pu, mrgCtx, mergeIdx);
+#endif
                     pu.bmDir = bmDir;
                     pu.mergeIdx = orgMergeIdx;
                     mrgCtx.setMergeInfo( pu, pu.mergeIdx);
                     m_pcInterPred->setBdmvrSubPuMvBuf(m_mvBufBDMVR[0], m_mvBufBDMVR[1]);
                     m_pcInterPred->processBDMVRSubPU(pu, subPuRefineList[mergeIdx][pu.bmDir - 1]);
                   }
+#if JVET_AB0079_TM_BCW_MRG
+                  else
+                  {
+                    auto orgMergeIdx = pu.mergeIdx;
+                    pu.bmDir = 0;
+                    m_pcInterPred->adjustMergeCandidatesBcwIdx(pu, mrgCtx, mergeIdx);
+                    pu.bmDir = bmDir;
+                    pu.mergeIdx = orgMergeIdx;
+                  }
+#endif
 #if !JVET_AA0093_REFINED_MOTION_FOR_ARMC
                   else
 #endif
@@ -2258,6 +2274,9 @@ void DecCu::xDeriveCUMV( CodingUnit &cu )
                     }
                     pu.bmDir = 0;
                     m_pcInterPred->adjustMergeCandidatesInOneCandidateGroup(pu, mrgCtx, bmDir == 2 ? applyBDMVR4BM : NULL, NULL, NULL, mergeIdx + 1, subPuRefineList, subPuRefineListTmp, mergeIdx);
+#if JVET_AB0079_TM_BCW_MRG
+                    m_pcInterPred->adjustMergeCandidatesBcwIdx(pu, mrgCtx, mergeIdx);
+#endif
                     pu.bmDir = bmDir;
                     pu.mergeIdx = orgMergeIdx;
                     mrgCtx.setMergeInfo( pu, pu.mergeIdx);
@@ -2266,8 +2285,19 @@ void DecCu::xDeriveCUMV( CodingUnit &cu )
                   }
                 }
                 else
+#endif
+#if JVET_AB0079_TM_BCW_MRG
+                {
 #endif
                 m_pcInterPred->adjustInterMergeCandidates(pu, mrgCtx, mergeIdx);
+#if JVET_AB0079_TM_BCW_MRG
+                  auto orgMergeIdx = pu.mergeIdx;
+                  pu.bmDir = 0;
+                  m_pcInterPred->adjustMergeCandidatesBcwIdx(pu, mrgCtx, mergeIdx);
+                  pu.bmDir = bmDir;
+                  pu.mergeIdx = orgMergeIdx;
+                }
+#endif
 #if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_Y0134_TMVP_NAMVP_CAND_REORDERING
                 }
 #endif
@@ -2432,10 +2462,16 @@ void DecCu::xDeriveCUMV( CodingUnit &cu )
                   }
                   pu.reduceTplSize = false;
                   m_pcInterPred->adjustMergeCandidatesInOneCandidateGroup(pu, mrgCtx, applyBDMVR4TM, NULL, NULL, mrgCtx.numValidMergeCand);
+#if JVET_AB0079_TM_BCW_MRG
+                  m_pcInterPred->adjustMergeCandidatesBcwIdx(pu, mrgCtx, tmpPuMrgIdx);
+#endif
                   pu.mergeIdx = tmpPuMrgIdx;
                 }
                 else
 #endif
+#if JVET_AB0079_TM_BCW_MRG
+                {
+#endif
 #if JVET_Z0102_NO_ARMC_FOR_ZERO_CAND
                 m_pcInterPred->adjustMergeCandidates(pu, mrgCtx, 
 #if TM_MRG
@@ -2445,6 +2481,10 @@ void DecCu::xDeriveCUMV( CodingUnit &cu )
 #else
                 m_pcInterPred->adjustMergeCandidatesInOneCandidateGroup(pu, mrgCtx, pu.mergeIdx + 1, pu.mergeIdx);
 #endif
+#if JVET_AB0079_TM_BCW_MRG
+                m_pcInterPred->adjustMergeCandidatesBcwIdx(pu, mrgCtx, pu.mergeIdx);
+                }
+#endif
 #if JVET_AA0093_REFINED_MOTION_FOR_ARMC
                 if (mrgCtx.numCandToTestEnc > mrgCtx.numValidMergeCand)
                 {
@@ -2541,11 +2581,21 @@ void DecCu::xDeriveCUMV( CodingUnit &cu )
                 }
                 pu.reduceTplSize = false;
                 m_pcInterPred->adjustMergeCandidatesInOneCandidateGroup(pu, mrgCtx, applyBDMVR4TM, NULL, NULL, mrgCtx.numValidMergeCand);
+#if JVET_AB0079_TM_BCW_MRG
+                m_pcInterPred->adjustMergeCandidatesBcwIdx(pu, mrgCtx, tmpPuMrgIdx);
+#endif
                 pu.mergeIdx = tmpPuMrgIdx;
               }
               else
+#endif
+#if JVET_AB0079_TM_BCW_MRG
+              {
 #endif
               m_pcInterPred->adjustInterMergeCandidates(pu, mrgCtx, pu.mergeIdx);
+#if JVET_AB0079_TM_BCW_MRG
+              m_pcInterPred->adjustMergeCandidatesBcwIdx(pu, mrgCtx, pu.mergeIdx);
+              }
+#endif
 #if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_Y0134_TMVP_NAMVP_CAND_REORDERING
               }
 #endif
diff --git a/source/Lib/EncoderLib/EncCu.cpp b/source/Lib/EncoderLib/EncCu.cpp
index 360b96298ed37b6e71aba8c82986d03adfce84aa..217d80989b60af60aef231e0143973a071a6ec71 100644
--- a/source/Lib/EncoderLib/EncCu.cpp
+++ b/source/Lib/EncoderLib/EncCu.cpp
@@ -3221,7 +3221,9 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
   MergeCtx ciipTmMrgCtx;
 #endif
 #endif
-
+#if JVET_AB0079_TM_BCW_MRG
+  MergeCtx mrgCtxCiip;
+#endif
 
 #if JVET_X0049_ADAPT_DMVR
   MergeCtx bmMrgCtx;
@@ -3242,6 +3244,9 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
 #if JVET_X0141_CIIP_TIMD_TM
     ciipTmMrgCtx.subPuMvpMiBuf = MotionBuf(m_SubPuMiBuf, bufSize);
 #endif
+#endif
+#if JVET_AB0079_TM_BCW_MRG
+    mrgCtxCiip.subPuMvpMiBuf = MotionBuf(m_SubPuMiBuf, bufSize);
 #endif
   }
 #endif
@@ -3394,6 +3399,30 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
       mergeCtx.candCost[ui] = MAX_UINT64;
     }
 #endif
+
+#if JVET_AB0079_TM_BCW_MRG
+    mrgCtxCiip.numValidMergeCand = mergeCtx.numValidMergeCand;
+#if JVET_Z0102_NO_ARMC_FOR_ZERO_CAND
+    mrgCtxCiip.numCandToTestEnc = mergeCtx.numCandToTestEnc;
+#endif
+    for (uint32_t uiMergeCand = 0; uiMergeCand < mergeCtx.numValidMergeCand; uiMergeCand++)
+    {
+      mrgCtxCiip.BcwIdx[uiMergeCand] = mergeCtx.BcwIdx[uiMergeCand];
+      mrgCtxCiip.interDirNeighbours[uiMergeCand] = mergeCtx.interDirNeighbours[uiMergeCand];
+      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 INTER_LIC 
+      mrgCtxCiip.LICFlags[uiMergeCand] = mergeCtx.LICFlags[uiMergeCand];
+#endif
+#if MULTI_HYP_PRED
+      mrgCtxCiip.addHypNeighbours[uiMergeCand] = mergeCtx.addHypNeighbours[uiMergeCand];
+#endif
+      mrgCtxCiip.candCost[uiMergeCand] = mergeCtx.candCost[uiMergeCand];
+    }
+    
+    m_pcInterSearch->adjustMergeCandidatesBcwIdx(pu, mergeCtx);
+#endif
     PU::getInterMergeCandidates(pu, mergeCtxtmp, 0);
 #endif
 
@@ -3482,6 +3511,9 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
 #if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
     bool flag = pu.mmvdMergeFlag;
     pu.mmvdMergeFlag = true;
+#if JVET_AB0079_TM_BCW_MRG
+    m_pcInterSearch->adjustMergeCandidatesBcwIdx(pu, mergeCtxtmp);
+#endif
     m_pcInterSearch->sortInterMergeMMVDCandidates(pu, mergeCtxtmp, mmvdLUT);
     pu.mmvdMergeFlag = flag;
 #endif
@@ -3569,6 +3601,9 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
           if (!tmMergeRefinedMotion)
 #endif
           m_pcInterSearch->adjustInterMergeCandidates(pu, tmMrgCtx);
+#if JVET_AB0079_TM_BCW_MRG
+          m_pcInterSearch->adjustMergeCandidatesBcwIdx(pu, tmMrgCtx);
+#endif
         }
         else
 #endif
@@ -3578,6 +3613,18 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
           m_pcInterSearch->adjustMergeCandidates(pu, tmMrgCtx, 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 (tmMrgCtx.numValidMergeCand > pu.cs->sps->getMaxNumTMMergeCand())
+            {
+              tmMrgCtx.numValidMergeCand = pu.cs->sps->getMaxNumTMMergeCand();
+            }
+            m_pcInterSearch->adjustMergeCandidatesBcwIdx(pu, tmMrgCtx);
+          }
 #endif
         }
         if (tmMrgCtx.numValidMergeCand > pu.cs->sps->getMaxNumTMMergeCand())
@@ -3677,6 +3724,9 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
       if (tmMergeRefinedMotion)
       {
         m_pcInterSearch->adjustMergeCandidatesInOneCandidateGroup(pu, tmMrgCtx, applyBDMVR4TM, NULL, NULL, pu.cs->sps->getMaxNumTMMergeCand());
+#if JVET_AB0079_TM_BCW_MRG
+        m_pcInterSearch->adjustMergeCandidatesBcwIdx(pu, tmMrgCtx);
+#endif
         pu.tmMergeFlag = true;
         for( uint32_t uiMergeCand = 0; uiMergeCand < tmMrgCtx.numValidMergeCand; uiMergeCand++ )
         {
@@ -3872,6 +3922,9 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
             if(!admvrRefinedMotion)
 #endif
             m_pcInterSearch->adjustInterMergeCandidates(pu, bmMrgCtx);
+#if JVET_AB0079_TM_BCW_MRG
+            m_pcInterSearch->adjustMergeCandidatesBcwIdx(pu, bmMrgCtx);
+#endif
           }
           else
 #endif
@@ -3879,6 +3932,13 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
           {
 #if JVET_Z0102_NO_ARMC_FOR_ZERO_CAND 
             m_pcInterSearch->adjustMergeCandidates(pu, bmMrgCtx, pu.cs->sps->getMaxNumBMMergeCand());
+#if !JVET_AA0093_REFINED_MOTION_FOR_ARMC && JVET_AB0079_TM_BCW_MRG
+            if (bmMrgCtx.numValidMergeCand > pu.cs->sps->getMaxNumBMMergeCand())
+            {
+              bmMrgCtx.numValidMergeCand = pu.cs->sps->getMaxNumBMMergeCand();
+            }
+            m_pcInterSearch->adjustMergeCandidatesBcwIdx(pu, bmMrgCtx);
+#endif
 #if JVET_AA0093_REFINED_MOTION_FOR_ARMC
             if (bmMrgCtx.numCandToTestEnc > bmMrgCtx.numValidMergeCand)
             {
@@ -4329,7 +4389,11 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
       if (isIntrainterEnabled)
       {
 #if MERGE_ENC_OPT
+#if JVET_AB0079_TM_BCW_MRG
+        xCheckSATDCostCiipMerge(tempCS, cu, pu, mrgCtxCiip, acMergeTempBuffer, singleMergeTempBuffer, acMergeTmpBuffer, uiNumMrgSATDCand, rdModeList, candCostList, distParam, ctxStart);
+#else
         xCheckSATDCostCiipMerge(tempCS, cu, pu, mergeCtx, acMergeTempBuffer, singleMergeTempBuffer, acMergeTmpBuffer, uiNumMrgSATDCand, rdModeList, candCostList, distParam, ctxStart);
+#endif
 #if JVET_X0141_CIIP_TIMD_TM && TM_MRG
         if (sps.getUseCiipTmMrg())
         {
@@ -4757,7 +4821,11 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
         }
         else
 #endif
+#if JVET_AB0079_TM_BCW_MRG
+          mrgCtxCiip.setMergeInfo(pu, uiMergeCand);
+#else
         mergeCtx.setMergeInfo(pu, uiMergeCand);
+#endif
 #else
         mergeCtx.setMergeInfo(pu, uiMergeCand);
         pu.ciipFlag = true;
@@ -13382,6 +13450,9 @@ void EncCu::xCheckSATDCostBMMerge(CodingStructure*& tempCS,
     }
     pu.bmDir = 0;
     m_pcInterSearch->adjustMergeCandidatesInOneCandidateGroup(pu, mrgCtx, NULL, NULL, NULL, mrgCtx.numValidMergeCand, subRefineList, subRefineListTmp);
+#if JVET_AB0079_TM_BCW_MRG
+    m_pcInterSearch->adjustMergeCandidatesBcwIdx(pu, mrgCtx);
+#endif
     if (hasAtLeastOne2nd)
     {
       m_pcInterSearch->adjustMergeCandidatesInOneCandidateGroup(pu, mrgCtxDir2, applyBDMVR + BM_MRG_MAX_NUM_INIT_CANDS, NULL, NULL, mrgCtxDir2.numValidMergeCand, &subRefineList[BM_MRG_MAX_NUM_INIT_CANDS], &subRefineListTmp[BM_MRG_MAX_NUM_INIT_CANDS]);
@@ -13402,8 +13473,19 @@ void EncCu::xCheckSATDCostBMMerge(CodingStructure*& tempCS,
     {
       mrgCtxDir2.numValidMergeCand = pu.cs->sps->getMaxNumBMMergeCand();
     }
+#if JVET_AB0079_TM_BCW_MRG
+      m_pcInterSearch->adjustMergeCandidatesBcwIdx(pu, mrgCtxDir2);
+#endif
     maxNumCand = ::min(mrgCtx.numValidMergeCand, (int)pu.cs->sps->getMaxNumBMMergeCand());
   }
+#if JVET_AB0079_TM_BCW_MRG
+  if(pu.cs->sps->getUseAML() && !armcRefinedMotion)
+  {
+    pu.bmDir = 0;
+    m_pcInterSearch->adjustMergeCandidatesBcwIdx(pu, mrgCtx);
+    mrgCtxDir2 = mrgCtx;
+  }
+#endif
 #endif
   for (uint32_t candIdx = 0; candIdx < maxNumCand; candIdx++)
   {