From 51e6122d8852743852495c7b817a6d85852af70e Mon Sep 17 00:00:00 2001
From: Damian Ruiz Coll <druizcoll@ofinno.com>
Date: Wed, 22 Feb 2023 17:53:54 +0000
Subject: [PATCH] SPS flag for BVP clustering tool control

---
 source/App/EncoderApp/EncApp.cpp         |   3 +
 source/App/EncoderApp/EncAppCfg.cpp      |  14 ++
 source/App/EncoderApp/EncAppCfg.h        |   3 +
 source/Lib/CommonLib/CommonDef.h         |   2 +-
 source/Lib/CommonLib/InterPrediction.cpp |  28 +++-
 source/Lib/CommonLib/InterPrediction.h   |   2 +-
 source/Lib/CommonLib/RdCost.h            |  30 ++--
 source/Lib/CommonLib/Slice.h             |   7 +
 source/Lib/CommonLib/Unit.cpp            |  12 ++
 source/Lib/CommonLib/Unit.h              |   3 +
 source/Lib/CommonLib/UnitTools.cpp       | 198 ++++++++++++++++++-----
 source/Lib/DecoderLib/CABACReader.cpp    | 117 ++++++++++----
 source/Lib/DecoderLib/CABACReader.h      |  11 +-
 source/Lib/DecoderLib/DecCu.cpp          |  33 ++--
 source/Lib/DecoderLib/VLCReader.cpp      |   3 +
 source/Lib/EncoderLib/CABACWriter.cpp    | 113 ++++++++++---
 source/Lib/EncoderLib/CABACWriter.h      |  17 +-
 source/Lib/EncoderLib/EncCfg.h           |   7 +
 source/Lib/EncoderLib/EncLib.cpp         |   3 +
 source/Lib/EncoderLib/InterSearch.cpp    |  38 ++++-
 source/Lib/EncoderLib/InterSearch.h      |   6 +-
 source/Lib/EncoderLib/VLCWriter.cpp      |   3 +
 22 files changed, 502 insertions(+), 151 deletions(-)

diff --git a/source/App/EncoderApp/EncApp.cpp b/source/App/EncoderApp/EncApp.cpp
index f6df711d2..3383adc0e 100644
--- a/source/App/EncoderApp/EncApp.cpp
+++ b/source/App/EncoderApp/EncApp.cpp
@@ -907,6 +907,9 @@ void EncApp::xInitLibCfg()
 #if JVET_AC0104_IBC_BVD_PREDICTION
   m_cEncLib.setUseBvdPred                                        (m_bvdPred);
 #endif
+#if JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV
+  m_cEncLib.setUseBvpCluster                                     (m_bvpCluster);
+#endif
 #if JVET_Z0054_BLK_REF_PIC_REORDER
   m_cEncLib.setUseARL                                            (m_useARL);
 #endif
diff --git a/source/App/EncoderApp/EncAppCfg.cpp b/source/App/EncoderApp/EncAppCfg.cpp
index e33240d3a..44122dc52 100644
--- a/source/App/EncoderApp/EncAppCfg.cpp
+++ b/source/App/EncoderApp/EncAppCfg.cpp
@@ -1137,6 +1137,9 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] )
 #if JVET_AC0104_IBC_BVD_PREDICTION
   ("BvdPred",                                         m_bvdPred,                                         true, "Block vector difference Prediction (0:off, 1:on)")
 #endif
+#if JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV
+  ("BvpCluster",                                      m_bvpCluster,                                      true, "IBC BVP clusteriing and BV with one zero component sign prediction (0:off, 1:on)")
+#endif
 #if JVET_Z0054_BLK_REF_PIC_REORDER
   ("ARL",                                             m_useARL,                                          true, "Adaptive Reference List (0:off, 1:on)")
 #endif
@@ -3935,6 +3938,14 @@ bool EncAppCfg::xCheckParameter()
       msg(WARNING, "BVD prediction is forcefully disabled since the enable flag of TM tools is set off. \n");
       m_bvdPred = false;
     }
+#endif
+#if JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV
+    if (m_bvpCluster)
+    {
+      msg(WARNING, "BVP clustering and BV with one zero component prediction is forcefully disabled since the enable "
+                   "flag of TM tools is set off. \n");
+      m_bvpCluster = false;
+    }
 #endif
   }
 #endif
@@ -5228,6 +5239,9 @@ void EncAppCfg::xPrintParameter()
 #if JVET_AC0104_IBC_BVD_PREDICTION
     msg(VERBOSE, "IBCBvdPred:%d ", m_bvdPred);
 #endif
+#if JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV
+    msg(VERBOSE, "IBCBvpCluster:%d ", m_bvpCluster);
+#endif
 #if JVET_AC0112_IBC_CIIP
   msg( VERBOSE, "IBCCIIP:%d ", m_ibcCiip);
 #endif
diff --git a/source/App/EncoderApp/EncAppCfg.h b/source/App/EncoderApp/EncAppCfg.h
index 95e5ea37e..dd2d711c5 100644
--- a/source/App/EncoderApp/EncAppCfg.h
+++ b/source/App/EncoderApp/EncAppCfg.h
@@ -488,6 +488,9 @@ protected:
 #if JVET_AC0104_IBC_BVD_PREDICTION
   bool      m_bvdPred;
 #endif
+#if JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV
+  bool      m_bvpCluster;
+#endif
 #if JVET_Z0054_BLK_REF_PIC_REORDER
   bool      m_useARL;
 #endif
diff --git a/source/Lib/CommonLib/CommonDef.h b/source/Lib/CommonLib/CommonDef.h
index 40c28282d..854eea607 100644
--- a/source/Lib/CommonLib/CommonDef.h
+++ b/source/Lib/CommonLib/CommonDef.h
@@ -158,7 +158,7 @@ static const int MAX_NUM_REF =                                     16; ///< max.
 static const int MAX_QP =                                          63;
 static const int NOT_VALID =                                       -1;
 
-#if TM_AMVP || (JVET_Z0084_IBC_TM && IBC_TM_AMVP)
+#if TM_AMVP || (JVET_Z0084_IBC_TM && IBC_TM_AMVP) || JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV
 static const int REGULAR_AMVP_MAX_NUM_CANDS =                       5; ///< AMVP: advanced motion vector prediction - max number of final candidate for regular inter mode
 #endif
 static const int AMVP_MAX_NUM_CANDS =                               2; ///< AMVP: advanced motion vector prediction - max number of final candidates
diff --git a/source/Lib/CommonLib/InterPrediction.cpp b/source/Lib/CommonLib/InterPrediction.cpp
index 9ffdbd4ef..f2ee46efa 100644
--- a/source/Lib/CommonLib/InterPrediction.cpp
+++ b/source/Lib/CommonLib/InterPrediction.cpp
@@ -10858,7 +10858,7 @@ void  InterPrediction::updateIBCCandInfo( PredictionUnit &pu, MergeCtx& mrgCtx,
 #endif
 
 #if JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV
-Distortion InterPrediction::getRdCostOTF(const PredictionUnit &pu, const PelBuf &org, const PelBuf &cur)
+Distortion InterPrediction::getTempCost(const PredictionUnit &pu, const PelBuf &org, const PelBuf &cur)
 {
   Distortion uiCost;
   DistParam  cDistParam;
@@ -17282,7 +17282,9 @@ void InterPrediction::deriveBvdSignIBC(const Mv& cMvPred, const Mv& cMvdKnownAtD
   
   const int iTotalNumberOfBins = iHorMSBins + iVerMSBins;
 #if JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV && JVET_AA0070_RRIBC
-  const int numSignBits = (pu.cu->rribcFlipType != 0) ? 0 :
+  const int numSignBits = (pu.cu->rribcFlipType != 0 && pu.isBvpClusterApplicable())
+                            ? 0
+                            :
 #else 
   const int numSignBits =
 #endif
@@ -17331,6 +17333,12 @@ void InterPrediction::deriveBvdSignIBC(const Mv& cMvPred, const Mv& cMvdKnownAtD
 #endif
 
 #if JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV && JVET_AA0070_RRIBC
+  bool horPositiveAllowed;
+  bool horNegativeAllowed;
+  bool verPositiveAllowed;
+  bool verNegativeAllowed;
+  if (pu.isBvpClusterApplicable())
+  {
   const bool horPositiveAllowedRRIBC = pu.mvpIdx[REF_PIC_LIST_0] == 1 && rrIBCmode;
   const bool horNegativeAllowedRRIBC = pu.mvpIdx[REF_PIC_LIST_0] == 0 && rrIBCmode;
   const bool verPositiveAllowedRRIBC = pu.mvpIdx[REF_PIC_LIST_0] == 1 && rrIBCmode;
@@ -17339,10 +17347,18 @@ void InterPrediction::deriveBvdSignIBC(const Mv& cMvPred, const Mv& cMvdKnownAtD
   CHECK(pu.mvpIdx[REF_PIC_LIST_0] >= AMVP_MAX_NUM_CANDS, "pu.mvpIdx[REF_PIC_LIST_0] >= AMVP_MAX_NUM_CANDS");
   CHECK(iHorKnown == 0 && cMvdKnownAtDecoder.getHor() != 0, "cMvdKnownAtDecoder.getHor() != 0");
 
-  const bool horPositiveAllowed = horPositiveAllowedRRIBC || (!rrIBCmode && !si.horEncodeSignInEP) || (!rrIBCmode && si.horEncodeSignInEP && cMvdKnownAtDecoder.getHor() > 0);
-  const bool horNegativeAllowed = horNegativeAllowedRRIBC || (!rrIBCmode && !si.horEncodeSignInEP) || (!rrIBCmode && si.horEncodeSignInEP && cMvdKnownAtDecoder.getHor() < 0);
-  const bool verPositiveAllowed = verPositiveAllowedRRIBC || (!rrIBCmode && !si.verEncodeSignInEP) || (!rrIBCmode && si.verEncodeSignInEP && cMvdKnownAtDecoder.getVer() > 0);
-  const bool verNegativeAllowed = verNegativeAllowedRRIBC || (!rrIBCmode && !si.verEncodeSignInEP) || (!rrIBCmode && si.verEncodeSignInEP && cMvdKnownAtDecoder.getVer() < 0);
+  horPositiveAllowed = horPositiveAllowedRRIBC || (!rrIBCmode && !si.horEncodeSignInEP) || (!rrIBCmode && si.horEncodeSignInEP && cMvdKnownAtDecoder.getHor() > 0);
+  horNegativeAllowed = horNegativeAllowedRRIBC || (!rrIBCmode && !si.horEncodeSignInEP) || (!rrIBCmode && si.horEncodeSignInEP && cMvdKnownAtDecoder.getHor() < 0);
+  verPositiveAllowed = verPositiveAllowedRRIBC || (!rrIBCmode && !si.verEncodeSignInEP) || (!rrIBCmode && si.verEncodeSignInEP && cMvdKnownAtDecoder.getVer() > 0);
+  verNegativeAllowed = verNegativeAllowedRRIBC || (!rrIBCmode && !si.verEncodeSignInEP) || (!rrIBCmode && si.verEncodeSignInEP && cMvdKnownAtDecoder.getVer() < 0);
+  }
+  else
+  {
+    horPositiveAllowed = !si.horEncodeSignInEP || (si.horEncodeSignInEP && cMvdKnownAtDecoder.getHor() > 0);
+    horNegativeAllowed = !si.horEncodeSignInEP || (si.horEncodeSignInEP && cMvdKnownAtDecoder.getHor() < 0);
+    verPositiveAllowed = !si.verEncodeSignInEP || (si.verEncodeSignInEP && cMvdKnownAtDecoder.getVer() > 0);
+    verNegativeAllowed = !si.verEncodeSignInEP || (si.verEncodeSignInEP && cMvdKnownAtDecoder.getVer() < 0);
+  }
 #else
   const bool horPositiveAllowed = !si.horEncodeSignInEP || (si.horEncodeSignInEP && cMvdKnownAtDecoder.getHor() > 0);
   const bool horNegativeAllowed = !si.horEncodeSignInEP || (si.horEncodeSignInEP && cMvdKnownAtDecoder.getHor() < 0);
diff --git a/source/Lib/CommonLib/InterPrediction.h b/source/Lib/CommonLib/InterPrediction.h
index 6ef4d28f7..a97382d28 100644
--- a/source/Lib/CommonLib/InterPrediction.h
+++ b/source/Lib/CommonLib/InterPrediction.h
@@ -733,7 +733,7 @@ public:
 #endif
 #endif
 #if JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV
-  Distortion getRdCostOTF(const PredictionUnit &pu, const PelBuf &org, const PelBuf &cur);
+  Distortion getTempCost(const PredictionUnit &pu, const PelBuf &org, const PelBuf &cur);
 #endif
 #if JVET_AC0112_IBC_GPM
   void    motionCompensationIbcGpm(CodingUnit &cu, MergeCtx &ibcGpmMrgCtx, IntraPrediction* pcIntraPred);
diff --git a/source/Lib/CommonLib/RdCost.h b/source/Lib/CommonLib/RdCost.h
index de71d009b..e4e441461 100644
--- a/source/Lib/CommonLib/RdCost.h
+++ b/source/Lib/CommonLib/RdCost.h
@@ -308,11 +308,13 @@ public:
 
 #if JVET_AA0070_RRIBC
   void setPredictors(Mv pcMv[3][2]);
-#if JVET_Z0131_IBC_BVD_BINARIZATION
+#if JVET_Z0131_IBC_BVD_BINARIZATION || JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV
   EstBvdBitsStruct *getBvdBitCosts() { return &m_cBvdBitCosts; }
 
-#if JVET_Z0084_IBC_TM && IBC_TM_AMVP
-  inline Distortion getBvCostMultiplePreds(int x, int y, bool useIMV, int rribcFlipType, uint8_t *bvImvResBest = NULL, int *bvpIdxBest = NULL, bool flag = false, AMVPInfo *amvpInfo4Pel = NULL)
+#if (JVET_Z0084_IBC_TM && IBC_TM_AMVP) || JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV
+  inline Distortion getBvCostMultiplePreds(int x, int y, bool useIMV, int rribcFlipType, uint8_t *bvImvResBest = NULL,
+                                           int *bvpIdxBest = NULL, bool flag = false, AMVPInfo *amvpInfo4Pel = NULL,
+                                           const bool useBvpCluster = true)
 #else
   inline Distortion getBvCostMultiplePreds(int x, int y, bool useIMV, int rribcFlipType, uint8_t *bvImvResBest = NULL, int *bvpIdxBest = NULL)
 #endif
@@ -345,7 +347,10 @@ public:
     }
     uint32_t bBest    = (b1 < b0) ? b1 : b0;
 #if JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV
-    bBest += (rribcFlipType) ? m_cBvdBitCosts.bitsRribc : 0;
+    if (useBvpCluster)
+    {
+      bBest += (rribcFlipType) ? m_cBvdBitCosts.bitsRribc : 0;
+    }
 #endif
     int      bBestIdx = (b1 < b0) ? 1 : 0;
     uint8_t  bestRes;
@@ -372,7 +377,7 @@ public:
     {
       Mv cMv(x >> 2, y >> 2);
 
-#if JVET_Z0084_IBC_TM && IBC_TM_AMVP
+#if (JVET_Z0084_IBC_TM && IBC_TM_AMVP) || JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV 
       Mv tmpBv0;
       Mv tmpBv1;
       if (flag)
@@ -413,12 +418,15 @@ public:
         bQ1 = (cMv.getVer() == tmpBv1.getVer()) ? std::numeric_limits<uint32_t>::max() : (xGetExpGolombNumberOfBitsIBCV(cMv.getVer() - tmpBv1.getVer()) + m_cBvdBitCosts.bitsIdx[1]);
       }
 #if JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV
-      bQ0 += (rribcFlipType && (cMv.getHor() != tmpBv0.getHor()) && (cMv.getVer() != tmpBv0.getVer()))
-               ? m_cBvdBitCosts.bitsRribc
-               : 0;
-      bQ1 += (rribcFlipType && (cMv.getHor() != tmpBv1.getHor()) && (cMv.getVer() != tmpBv1.getVer()))
-               ? m_cBvdBitCosts.bitsRribc
-               : 0;
+      if (useBvpCluster)
+      {
+        bQ0 += (rribcFlipType && (cMv.getHor() != tmpBv0.getHor()) && (cMv.getVer() != tmpBv0.getVer()))
+                 ? m_cBvdBitCosts.bitsRribc
+                 : 0;
+        bQ1 += (rribcFlipType && (cMv.getHor() != tmpBv1.getHor()) && (cMv.getVer() != tmpBv1.getVer()))
+                 ? m_cBvdBitCosts.bitsRribc
+                 : 0;
+      }
 #endif
       uint32_t bQBest = (bQ1 < bQ0) ? bQ1 : bQ0;
       bQBest += (bQBest < std::numeric_limits<uint32_t>::max()) ? m_cBvdBitCosts.bitsImv[1] : 0;
diff --git a/source/Lib/CommonLib/Slice.h b/source/Lib/CommonLib/Slice.h
index 2aa1ef87b..49aca599d 100644
--- a/source/Lib/CommonLib/Slice.h
+++ b/source/Lib/CommonLib/Slice.h
@@ -1572,6 +1572,9 @@ private:
 #if JVET_AC0104_IBC_BVD_PREDICTION
   bool              m_bvdPred;
 #endif
+#if JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV
+  bool              m_bvpCluster;
+#endif
 #if JVET_Z0054_BLK_REF_PIC_REORDER
   bool              m_useARL;
 #endif
@@ -2138,6 +2141,10 @@ void                    setCCALFEnabledFlag( bool b )
   void                    setUseBvdPred(bool b)                                                           { m_bvdPred = b; }
   bool                    getUseBvdPred() const                                                           { return m_bvdPred; }
 #endif
+#if JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV
+  void                    setUseBvpCluster(bool b)                                                        { m_bvpCluster = b; }
+  bool                    getUseBvpCluster() const                                                        { return m_bvpCluster; }
+#endif
 #if JVET_Z0054_BLK_REF_PIC_REORDER
   void                    setUseARL(bool b) { m_useARL = b; }
   bool                    getUseARL()const { return m_useARL; }
diff --git a/source/Lib/CommonLib/Unit.cpp b/source/Lib/CommonLib/Unit.cpp
index 5b5f96c51..076132143 100644
--- a/source/Lib/CommonLib/Unit.cpp
+++ b/source/Lib/CommonLib/Unit.cpp
@@ -1353,6 +1353,18 @@ bool PredictionUnit::isBvdPredApplicable() const
 }
 #endif
 
+#if JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV
+bool PredictionUnit::isBvpClusterApplicable() const
+{
+  if (!cs->sps->getUseBvpCluster())
+  {
+    return false;
+  }
+
+  return true;
+}
+#endif
+
 #if JVET_W0123_TIMD_FUSION
 const uint8_t& PredictionUnit::getIpmInfo() const
 {
diff --git a/source/Lib/CommonLib/Unit.h b/source/Lib/CommonLib/Unit.h
index d23a27479..290fa0533 100644
--- a/source/Lib/CommonLib/Unit.h
+++ b/source/Lib/CommonLib/Unit.h
@@ -701,6 +701,9 @@ struct PredictionUnit : public UnitArea, public IntraPredictionData, public Inte
 #if JVET_AC0104_IBC_BVD_PREDICTION
   bool              isBvdPredApplicable() const;
 #endif
+#if JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV
+  bool isBvpClusterApplicable() const;
+#endif
 };
 
 // ---------------------------------------------------------------------------
diff --git a/source/Lib/CommonLib/UnitTools.cpp b/source/Lib/CommonLib/UnitTools.cpp
index d9f04f450..469020750 100644
--- a/source/Lib/CommonLib/UnitTools.cpp
+++ b/source/Lib/CommonLib/UnitTools.cpp
@@ -3168,13 +3168,13 @@ inline Distortion PU::getTMCost(const PredictionUnit &pu, CPelBuf pRecY, Mv Cand
   {
     PU::getTemplateRefTop(pu, pRecY, pu.cs->m_pcBufPredRefTop, CandMv, pu.cs->m_pcBufPredCurTop.width,
                           AML_MERGE_TEMPLATE_SIZE);
-    uiCost += pcInter->getRdCostOTF(pu, pu.cs->m_pcBufPredCurTop, pu.cs->m_pcBufPredRefTop);
+    uiCost += pcInter->getTempCost(pu, pu.cs->m_pcBufPredCurTop, pu.cs->m_pcBufPredRefTop);
   }
   if (availableTmLeft)
   {
     PU::getTemplateRefLeft(pu, pRecY, pu.cs->m_pcBufPredRefLeft, CandMv, AML_MERGE_TEMPLATE_SIZE,
                            pu.cs->m_pcBufPredCurLeft.height);
-    uiCost += pcInter->getRdCostOTF(pu, pu.cs->m_pcBufPredCurLeft, pu.cs->m_pcBufPredRefLeft);
+    uiCost += pcInter->getTempCost(pu, pu.cs->m_pcBufPredCurLeft, pu.cs->m_pcBufPredRefLeft);
   }
   return uiCost;
 }
@@ -3363,10 +3363,23 @@ void PU::getIBCMergeCandidates(const PredictionUnit &pu, MergeCtx& mrgCtx, const
 #else
   const uint32_t maxNumMergeCand = pu.cs->sps->getMaxNumIBCMergeCand();
 #endif
-#if JVET_Z0084_IBC_TM
+#if JVET_Z0084_IBC_TM || JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV
 #if IBC_TM_MRG
 #if JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV
-  const uint32_t mvdSimilarityThresh = (pu.tmMergeFlag && pu.mergeFlag) ? PU::getTMMvdThreshold(pu) : 1;
+  uint32_t       mvdSimilarityThresh = 1;
+  if (pu.isBvpClusterApplicable())
+  {
+    mvdSimilarityThresh = (pu.tmMergeFlag && pu.mergeFlag) ? PU::getTMMvdThreshold(pu) : 1;
+  }
+  else
+  {
+#if JVET_AA0070_RRIBC
+    mvdSimilarityThresh =
+      ((pu.tmMergeFlag && pu.mergeFlag) || (!pu.mergeFlag && !pu.cu->rribcFlipType)) ? PU::getTMMvdThreshold(pu) : 1;
+#else
+    const uint32_t mvdSimilarityThresh = pu.tmMergeFlag ? PU::getTMMvdThreshold(pu) : 1;
+#endif
+  }
 #else
 #if JVET_AA0070_RRIBC
   const uint32_t mvdSimilarityThresh =
@@ -9920,31 +9933,80 @@ void PU::fillIBCMvpCand(PredictionUnit &pu, AMVPInfo &amvpInfo)
   MergeCtx mergeCtx;
 
 #if JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV
-#if JVET_AA0070_RRIBC
-  if (pu.cu->rribcFlipType)
+  if (pu.isBvpClusterApplicable())
   {
-    getRribcBvpCand(pu, pInfo);
+#if JVET_AA0070_RRIBC
+    if (pu.cu->rribcFlipType)
+    {
+      getRribcBvpCand(pu, pInfo);
+    }
+    else
+#endif
+    {
+      const int  cbWidth      = pu.lwidth();
+      const int  cbHeight     = pu.lheight();
+      const bool availableTop = (pu.cs->getPURestricted(pu.Y().topRight().offset(0, -1), pu, pu.chType)) ? true : false;
+      const bool availableLeft =
+        (pu.cs->getPURestricted(pu.Y().bottomLeft().offset(-1, 0), pu, pu.chType)) ? true : false;
+      const CPelBuf pRecY           = pu.cs->picture->getRecoBuf(pu.cs->picture->blocks[COMPONENT_Y]);
+      pInfo->maxSimilarityThreshold = 1;
+
+      PU::getIBCMergeCandidates(pu, mergeCtx);
+      pu.cs->createTMBuf(cbWidth, cbHeight);
+      PU::getTemplateTop(availableTop, pu, pRecY, pu.cs->m_pcBufPredCurTop, Position(0, -AML_MERGE_TEMPLATE_SIZE),
+                         cbWidth, AML_MERGE_TEMPLATE_SIZE);
+      PU::getTemplateLeft(availableLeft, pu, pRecY, pu.cs->m_pcBufPredCurLeft, Position(-AML_MERGE_TEMPLATE_SIZE, 0),
+                          AML_MERGE_TEMPLATE_SIZE, cbHeight);
+
+      int candIdx = 0;
+      while ((pInfo->numCand < (REGULAR_AMVP_MAX_NUM_CANDS + 1)) && (candIdx < mergeCtx.numAMVPMergeCand))
+      {
+        pInfo->mvCand[pInfo->numCand] = mergeCtx.mvFieldNeighbours[candIdx << 1].mv;
+        pInfo->mvCost[pInfo->numCand] =
+          getTMCost(pu, pRecY, pInfo->mvCand[pInfo->numCand], availableTop, availableLeft, pcInter);
+        pInfo->mvCand[pInfo->numCand].roundIbcPrecInternal2Amvr(pu.cu->imv);
+        if (!pInfo->xCheckSimilarMotion(pInfo->numCand))
+        {
+          pInfo->numCand++;
+        }
+        candIdx++;
+      }
+      pu.cs->destroyTMBuf();
+      clusterBvpCand(cbWidth, cbHeight, pInfo);
+    }
   }
   else
-#endif
   {
-    const int     cbWidth         = pu.lwidth();
-    const int     cbHeight        = pu.lheight();
-    const bool    availableTop    = (pu.cs->getPURestricted(pu.Y().topRight().offset(0, -1), pu, pu.chType))   ? true : false;
-    const bool    availableLeft   = (pu.cs->getPURestricted(pu.Y().bottomLeft().offset(-1, 0), pu, pu.chType)) ? true : false;
-    const CPelBuf pRecY           = pu.cs->picture->getRecoBuf(pu.cs->picture->blocks[COMPONENT_Y]);
-    pInfo->maxSimilarityThreshold = 1;
-  
+#if JVET_Z0084_IBC_TM && IBC_TM_AMVP
+#if JVET_AA0070_RRIBC
+    pInfo->maxSimilarityThreshold =
+      (pu.cs->sps->getUseDMVDMode() && pcInter && !pu.cu->rribcFlipType) ? PU::getTMMvdThreshold(pu) : 1;
+#if IBC_TM_MRG
+    if (!pu.cu->rribcFlipType)
+    {
+      pu.tmMergeFlag = true;
+    }
+#endif
+#else
+    pInfo->maxSimilarityThreshold = (pu.cs->sps->getUseDMVDMode() && pcInter) ? PU::getTMMvdThreshold(pu) : 1;
+#if IBC_TM_MRG
+    pu.tmMergeFlag = true;
+#endif
+#endif
+
+#if JVET_Z0075_IBC_HMVP_ENLARGE
+    PU::getIBCMergeCandidates(pu, mergeCtx, pu.cs->sps->getMaxNumIBCMergeCand());
+#else
     PU::getIBCMergeCandidates(pu, mergeCtx);
-    pu.cs->createTMBuf(cbWidth, cbHeight);
-    PU::getTemplateTop(availableTop, pu, pRecY, pu.cs->m_pcBufPredCurTop, Position(0, -AML_MERGE_TEMPLATE_SIZE), cbWidth, AML_MERGE_TEMPLATE_SIZE);
-    PU::getTemplateLeft(availableLeft, pu, pRecY, pu.cs->m_pcBufPredCurLeft, Position(-AML_MERGE_TEMPLATE_SIZE, 0), AML_MERGE_TEMPLATE_SIZE, cbHeight);
+#endif
+#if IBC_TM_MRG
+    pu.tmMergeFlag = false;
+#endif
 
     int candIdx = 0;
-    while ((pInfo->numCand < (REGULAR_AMVP_MAX_NUM_CANDS + 1)) && (candIdx < mergeCtx.numAMVPMergeCand))
+    while ((pInfo->numCand < AMVP_MAX_NUM_CANDS_MEM) && (candIdx < mergeCtx.numValidMergeCand))
     {
       pInfo->mvCand[pInfo->numCand] = mergeCtx.mvFieldNeighbours[candIdx << 1].mv;
-      pInfo->mvCost[pInfo->numCand] = getTMCost(pu, pRecY, pInfo->mvCand[pInfo->numCand], availableTop, availableLeft, pcInter);
       pInfo->mvCand[pInfo->numCand].roundIbcPrecInternal2Amvr(pu.cu->imv);
       if (!pInfo->xCheckSimilarMotion(pInfo->numCand))
       {
@@ -9952,8 +10014,64 @@ void PU::fillIBCMvpCand(PredictionUnit &pu, AMVPInfo &amvpInfo)
       }
       candIdx++;
     }
-    pu.cs->destroyTMBuf();
-    clusterBvpCand(cbWidth, cbHeight, pInfo);
+
+#if JVET_AA0070_RRIBC
+    if (pu.cs->sps->getUseDMVDMode() && pcInter && pInfo->numCand > 0 && !pu.cu->rribcFlipType)
+#else
+    if (pu.cs->sps->getUseDMVDMode() && pcInter && pInfo->numCand > 0)
+#endif
+    {
+      struct amvpSort
+      {
+        Mv         amvpCand;
+        Distortion cost;
+      };
+      amvpSort              temp;
+      std::vector<amvpSort> input;
+      const auto            costIncSort = [](const amvpSort &x, const amvpSort &y) { return x.cost < y.cost; };
+      Distortion            tmCost      = std::numeric_limits<Distortion>::max();
+
+      for (int candIdx = 0; candIdx < pInfo->numCand; ++candIdx)
+      {
+        tmCost = pcInter->deriveTMMv(pu, true, std::numeric_limits<Distortion>::max(), REF_PIC_LIST_0, MAX_NUM_REF,
+                                     TM_MAX_NUM_OF_ITERATIONS, pInfo->mvCand[candIdx]);
+        pInfo->mvCand[candIdx].roundIbcPrecInternal2Amvr(pu.cu->imv);
+        temp.amvpCand = pInfo->mvCand[candIdx];
+        temp.cost     = tmCost;
+        input.push_back(temp);
+      }
+
+      stable_sort(input.begin(), input.end(), costIncSort);
+      for (int candIdx = 0; candIdx < pInfo->numCand; ++candIdx)
+      {
+        pInfo->mvCand[candIdx] = input.at(candIdx).amvpCand;
+      }
+    }
+
+    if (pInfo->numCand > AMVP_MAX_NUM_CANDS)
+    {
+      pInfo->numCand = AMVP_MAX_NUM_CANDS;
+    }
+
+    while (pInfo->numCand < AMVP_MAX_NUM_CANDS)
+    {
+      pInfo->mvCand[pInfo->numCand++] = Mv(0, 0);
+    }
+#else
+    PU::getIBCMergeCandidates(pu, mergeCtx, AMVP_MAX_NUM_CANDS - 1);
+    int candIdx = 0;
+    while (pInfo->numCand < AMVP_MAX_NUM_CANDS)
+    {
+      pInfo->mvCand[pInfo->numCand] = mergeCtx.mvFieldNeighbours[(candIdx << 1) + 0].mv;
+      pInfo->numCand++;
+      candIdx++;
+    }
+
+    for (Mv &mv: pInfo->mvCand)
+    {
+      mv.roundIbcPrecInternal2Amvr(pu.cu->imv);
+    }
+#endif
   }
 #else
 #if JVET_Z0084_IBC_TM && IBC_TM_AMVP
@@ -10000,14 +10118,14 @@ void PU::fillIBCMvpCand(PredictionUnit &pu, AMVPInfo &amvpInfo)
   if (pu.cs->sps->getUseDMVDMode() && pcInter && pInfo->numCand > 0)
 #endif
   {
-    struct AMVPSort
+    struct amvpSort
     {
-      Mv AMVPCand;
+      Mv amvpCand;
       Distortion cost;
     };
-    AMVPSort temp;
-    std::vector<AMVPSort> input;
-    const auto CostIncSort = [](const AMVPSort &x, const AMVPSort &y) { return x.cost < y.cost; };
+    amvpSort temp;
+    std::vector<amvpSort> input;
+    const auto costIncSort = [](const amvpSort &x, const amvpSort &y) { return x.cost < y.cost; };
     Distortion tmCost = std::numeric_limits<Distortion>::max();
 
     for (int candIdx = 0; candIdx < pInfo->numCand; ++candIdx)
@@ -10015,15 +10133,15 @@ void PU::fillIBCMvpCand(PredictionUnit &pu, AMVPInfo &amvpInfo)
       tmCost = pcInter->deriveTMMv(pu, true, std::numeric_limits<Distortion>::max(), REF_PIC_LIST_0, MAX_NUM_REF,
                                    TM_MAX_NUM_OF_ITERATIONS, pInfo->mvCand[candIdx]);
       pInfo->mvCand[candIdx].roundIbcPrecInternal2Amvr(pu.cu->imv);
-      temp.AMVPCand = pInfo->mvCand[candIdx];
+      temp.amvpCand = pInfo->mvCand[candIdx];
       temp.cost = tmCost;
       input.push_back(temp);
     }
 
-    stable_sort(input.begin(), input.end(), CostIncSort);
+    stable_sort(input.begin(), input.end(), costIncSort);
     for (int candIdx = 0; candIdx < pInfo->numCand; ++candIdx)
     {
-      pInfo->mvCand[candIdx] = input.at(candIdx).AMVPCand;
+      pInfo->mvCand[candIdx] = input.at(candIdx).amvpCand;
     }
   }
 
@@ -10515,14 +10633,14 @@ void PU::fillMvpCand(PredictionUnit &pu, const RefPicList &eRefPicList, const in
 #endif
     && interPred != nullptr && pInfo->numCand > 0)
   {
-    struct AMVPSort
+    struct amvpSort
     {
-      Mv AMVPCand;
+      Mv amvpCand;
       Distortion cost;
     };
-    AMVPSort temp;
-    std::vector<AMVPSort> input;
-    const auto CostIncSort = [](const AMVPSort &x, const AMVPSort &y) { return x.cost < y.cost; };
+    amvpSort temp;
+    std::vector<amvpSort> input;
+    const auto costIncSort = [](const amvpSort &x, const amvpSort &y) { return x.cost < y.cost; };
     Distortion tmCost[REGULAR_AMVP_MAX_NUM_CANDS];
     for (int i = 0; i < REGULAR_AMVP_MAX_NUM_CANDS; i++)
     {
@@ -10540,11 +10658,11 @@ void PU::fillMvpCand(PredictionUnit &pu, const RefPicList &eRefPicList, const in
       for (int candIdx = 0; candIdx < pInfo->numCand; ++candIdx)
       {
         tmCost[candIdx] = interPred->deriveTMMv(pu, true, std::numeric_limits<Distortion>::max(), eRefPicList, refIdx, 0, pInfo->mvCand[candIdx]);
-        temp.AMVPCand = pInfo->mvCand[candIdx];
+        temp.amvpCand = pInfo->mvCand[candIdx];
         temp.cost = tmCost[candIdx];
         input.push_back(temp);
       }
-      stable_sort(input.begin(), input.end(), CostIncSort);
+      stable_sort(input.begin(), input.end(), costIncSort);
       for (int candIdx = 1; candIdx < pInfo->numCand; ++candIdx)
       {
         if (input.at(candIdx).cost > 5 * input.at(0).cost)
@@ -10565,15 +10683,15 @@ void PU::fillMvpCand(PredictionUnit &pu, const RefPicList &eRefPicList, const in
                                             , 0
 #endif
                                             , pInfo->mvCand[candIdx]);
-      temp.AMVPCand = pInfo->mvCand[candIdx];
+      temp.amvpCand = pInfo->mvCand[candIdx];
       temp.cost = tmCost[candIdx];
       input.push_back(temp);
     }
 
-    stable_sort(input.begin(), input.end(), CostIncSort);
+    stable_sort(input.begin(), input.end(), costIncSort);
     for (int candIdx = 0; candIdx < pInfo->numCand; ++candIdx)
     {
-      pInfo->mvCand[candIdx] = input.at(candIdx).AMVPCand;
+      pInfo->mvCand[candIdx] = input.at(candIdx).amvpCand;
       tmCost[candIdx] = input.at(candIdx).cost;
     }
 #if JVET_AA0093_REFINED_MOTION_FOR_ARMC
diff --git a/source/Lib/DecoderLib/CABACReader.cpp b/source/Lib/DecoderLib/CABACReader.cpp
index c61ec5c64..c1514feaa 100644
--- a/source/Lib/DecoderLib/CABACReader.cpp
+++ b/source/Lib/DecoderLib/CABACReader.cpp
@@ -3301,7 +3301,16 @@ void CABACReader::prediction_unit( PredictionUnit& pu, MergeCtx& mrgCtx )
   rribcData(*pu.cu);
 #endif
 #else
-  bvOneZeroComp(*pu.cu);
+  if (pu.isBvpClusterApplicable())
+  {
+    bvOneZeroComp(*pu.cu);
+  }
+#if JVET_AA0070_RRIBC
+  else
+  {
+    rribcData(*pu.cu);
+  }
+#endif
 #endif
 #if JVET_AC0112_IBC_LIC
   cuIbcLicFlag(*pu.cu);
@@ -3336,13 +3345,15 @@ void CABACReader::prediction_unit( PredictionUnit& pu, MergeCtx& mrgCtx )
 #if JVET_Z0131_IBC_BVD_BINARIZATION
 #if JVET_AC0104_IBC_BVD_PREDICTION
 #if JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV
-    bvdCoding(pu.mvd[REF_PIC_LIST_0], pu.bvdSuffixInfo, pu.isBvdPredApplicable(), pu.cu->bvOneZeroComp, pu.cu->bvZeroCompDir);
+    bvdCoding(pu.mvd[REF_PIC_LIST_0], pu.bvdSuffixInfo, pu.isBvdPredApplicable(), pu.isBvpClusterApplicable(),
+              pu.cu->bvOneZeroComp, pu.cu->bvZeroCompDir, pu.cu->rribcFlipType);
 #else
     bvdCoding(pu.mvd[REF_PIC_LIST_0], pu.bvdSuffixInfo, pu.isBvdPredApplicable(), pu.cu->rribcFlipType);
 #endif
 #else
 #if JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV
-    bvdCoding(pu.mvd[REF_PIC_LIST_0], pu.cu->bvOneZeroComp, pu.cu->bvZeroCompDir);
+    bvdCoding(pu.mvd[REF_PIC_LIST_0], pu.isBvpClusterApplicable(), pu.cu->bvOneZeroComp, pu.cu->bvZeroCompDir,
+              pu.cu->rribcFlipType);
 #else
     bvdCoding(pu.mvd[REF_PIC_LIST_0], pu.cu->rribcFlipType);
 #endif
@@ -3356,13 +3367,14 @@ void CABACReader::prediction_unit( PredictionUnit& pu, MergeCtx& mrgCtx )
 #elif JVET_Z0131_IBC_BVD_BINARIZATION
 #if JVET_AC0104_IBC_BVD_PREDICTION
 #if JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV
-    bvdCoding(pu.mvd[REF_PIC_LIST_0], pu.bvdSuffixInfo, pu.isBvdPredApplicable(), pu.cu->bvOneZeroComp, pu.cu->bvZeroCompDir);
+    bvdCoding(pu.mvd[REF_PIC_LIST_0], pu.bvdSuffixInfo, pu.isBvdPredApplicable(), pu.isBvpClusterApplicable(),
+              pu.cu->bvOneZeroComp, pu.cu->bvZeroCompDir);
 #else
     bvdCoding(pu.mvd[REF_PIC_LIST_0], pu.bvdSuffixInfo, pu.isBvdPredApplicable());
 #endif
 #else
 #if JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV
-    bvdCoding(pu.mvd[REF_PIC_LIST_0], pu.cu->bvOneZeroComp, pu.cu->bvZeroCompDir);
+    bvdCoding(pu.mvd[REF_PIC_LIST_0], pu.isBvpClusterApplicable(), pu.cu->bvOneZeroComp, pu.cu->bvZeroCompDir);
 #else
     bvdCoding(pu.mvd[REF_PIC_LIST_0]);
 #endif
@@ -3380,15 +3392,18 @@ void CABACReader::prediction_unit( PredictionUnit& pu, MergeCtx& mrgCtx )
       mvp_flag(pu, REF_PIC_LIST_0);
     }
 #if JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV && JVET_AA0070_RRIBC
-    if (pu.mvpIdx[REF_PIC_LIST_0] == 0)
+    if (pu.isBvpClusterApplicable())
     {
-      if (pu.cu->bvZeroCompDir == 1)
+      if (pu.mvpIdx[REF_PIC_LIST_0] == 0)
       {
-        pu.mvd[REF_PIC_LIST_0].hor = -pu.mvd[REF_PIC_LIST_0].hor;
-      }
-      else if (pu.cu->bvZeroCompDir == 2)
-      {
-        pu.mvd[REF_PIC_LIST_0].ver = -pu.mvd[REF_PIC_LIST_0].ver;
+        if (pu.cu->bvZeroCompDir == 1)
+        {
+          pu.mvd[REF_PIC_LIST_0].hor = -pu.mvd[REF_PIC_LIST_0].hor;
+        }
+        else if (pu.cu->bvZeroCompDir == 2)
+        {
+          pu.mvd[REF_PIC_LIST_0].ver = -pu.mvd[REF_PIC_LIST_0].ver;
+        }
       }
     }
 #endif
@@ -5897,13 +5912,15 @@ void CABACReader::bvdCodingRemainder(Mv& rMvd, MvdSuffixInfo& si, const int imv
 #if JVET_AA0070_RRIBC
 #if JVET_AC0104_IBC_BVD_PREDICTION
 #if JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV
-void CABACReader::bvdCoding(Mv& rMvd, MvdSuffixInfo& si, const bool useBvdPred, int bvOneZeroComp, int bvZeroCompDir)
+void CABACReader::bvdCoding(Mv &rMvd, MvdSuffixInfo &si, const bool useBvdPred, const bool useBvpCluster,
+                            int bvOneZeroComp, int bvZeroCompDir, const int &rribcFlipType)
 #else
 void CABACReader::bvdCoding(Mv& rMvd, MvdSuffixInfo& si, const bool useBvdPred, const int& rribcFlipType)
 #endif
 #else
 #if JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV
-void CABACReader::bvdCoding(Mv& rMvd, int bvOneZeroComp, int bvZeroCompDir)
+void CABACReader::bvdCoding(Mv &rMvd, const bool useBvpCluster, int bvOneZeroComp, int bvZeroCompDir,
+                            const int &rribcFlipType)
 #else
 void CABACReader::bvdCoding(Mv& rMvd, const int& rribcFlipType)
 #endif
@@ -5912,22 +5929,36 @@ void CABACReader::bvdCoding(Mv& rMvd, const int& rribcFlipType)
   int horAbs = 0, verAbs = 0;
 
 #if JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV
-  if (bvOneZeroComp)
+  if (useBvpCluster)
   {
-    if (bvZeroCompDir == 1)
-    { 
-      horAbs = (int) m_BinDecoder.decodeBin(Ctx::Bvd(HOR_BVD_CTX_OFFSET));
-    }
+    if (bvOneZeroComp)
+    {
+      if (bvZeroCompDir == 1)
+      {
+        horAbs = (int) m_BinDecoder.decodeBin(Ctx::Bvd(HOR_BVD_CTX_OFFSET));
+      }
 
-    if (bvZeroCompDir == 2)
+      if (bvZeroCompDir == 2)
+      {
+        verAbs = (int) m_BinDecoder.decodeBin(Ctx::Bvd(VER_BVD_CTX_OFFSET));
+      }
+    }
+    else
     {
-      verAbs = (int)m_BinDecoder.decodeBin(Ctx::Bvd(VER_BVD_CTX_OFFSET));
+      horAbs = (int) m_BinDecoder.decodeBin(Ctx::Bvd(HOR_BVD_CTX_OFFSET));
+      verAbs = (int) m_BinDecoder.decodeBin(Ctx::Bvd(VER_BVD_CTX_OFFSET));
     }
   }
   else
   {
-    horAbs = (int) m_BinDecoder.decodeBin(Ctx::Bvd(HOR_BVD_CTX_OFFSET));
-    verAbs = (int) m_BinDecoder.decodeBin(Ctx::Bvd(VER_BVD_CTX_OFFSET));
+    if (rribcFlipType != 2)
+    {
+      horAbs = (int) m_BinDecoder.decodeBin(Ctx::Bvd(HOR_BVD_CTX_OFFSET));
+    }
+    if (rribcFlipType != 1)
+    {
+      verAbs = (int) m_BinDecoder.decodeBin(Ctx::Bvd(VER_BVD_CTX_OFFSET));
+    }
   }
 #else
   if (rribcFlipType != 2)
@@ -5942,13 +5973,14 @@ void CABACReader::bvdCoding(Mv& rMvd, const int& rribcFlipType)
 #else
 #if JVET_AC0104_IBC_BVD_PREDICTION
 #if JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV
-void CABACReader::bvdCoding(Mv & rMvd, MvdSuffixInfo & si, const bool useBvdPred, int bvOneZeroComp, int bvZeroCompDir)
+void CABACReader::bvdCoding(Mv &rMvd, MvdSuffixInfo &si, const bool useBvdPred, const bool useBvpCluster,
+                            int bvOneZeroComp, int bvZeroCompDir)
 #else
 void CABACReader::bvdCoding(Mv & rMvd, MvdSuffixInfo & si, const bool useBvdPred)
 #endif
 #else
 #if JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV
-void CABACReader::bvdCoding(Mv & rMvd, int bvOneZeroComp, int bvZeroCompDir)
+void CABACReader::bvdCoding(Mv &rMvd, const bool useBvpCluster, int bvOneZeroComp, int bvZeroCompDir)
 #else
 void CABACReader::bvdCoding(Mv & rMvd)
 #endif
@@ -5975,7 +6007,17 @@ void CABACReader::bvdCoding(Mv & rMvd)
     {
       horAbs += xReadBvdContext(NUM_HOR_BVD_CTX, HOR_BVD_CTX_OFFSET, BVD_CODING_GOLOMB_ORDER);
 #if JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV && JVET_AA0070_RRIBC
-      if (!bvOneZeroComp)
+      if (useBvpCluster)
+      {
+        if (!bvOneZeroComp)
+        {
+          if (m_BinDecoder.decodeBinEP())
+          {
+            horAbs = -horAbs;
+          }
+        }
+      }
+      else 
       {
         if (m_BinDecoder.decodeBinEP())
         {
@@ -5993,7 +6035,17 @@ void CABACReader::bvdCoding(Mv & rMvd)
     {
       verAbs += xReadBvdContext(NUM_VER_BVD_CTX, VER_BVD_CTX_OFFSET, BVD_CODING_GOLOMB_ORDER);
 #if JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV && JVET_AA0070_RRIBC
-      if (!bvOneZeroComp)
+      if (useBvpCluster)
+      {
+        if (!bvOneZeroComp)
+        {
+          if (m_BinDecoder.decodeBinEP())
+          {
+            verAbs = -verAbs;
+          }
+        }
+      }
+      else
       {
         if (m_BinDecoder.decodeBinEP())
         {
@@ -6097,11 +6149,14 @@ void CABACReader::mvsdIdxFunc(PredictionUnit &pu, RefPicList eRefList)
     trMv.changeTransPrecAmvr2Internal(pu.cu->imv);
 
 #if JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV && JVET_AA0070_RRIBC
-    if (0 != pu.cu->rribcFlipType)
+    if (pu.isBvpClusterApplicable())
     {
-      pu.mvsdIdx[eRefList] = mvsdIdx;
-      bvdCodingRemainder(pu.mvd[REF_PIC_LIST_0], pu.bvdSuffixInfo, pu.cu->imv);
-      return;
+      if (0 != pu.cu->rribcFlipType)
+      {
+        pu.mvsdIdx[eRefList] = mvsdIdx;
+        bvdCodingRemainder(pu.mvd[REF_PIC_LIST_0], pu.bvdSuffixInfo, pu.cu->imv);
+        return;
+      }
     }
 #endif
     if (pu.mvd[eRefList].getHor())
diff --git a/source/Lib/DecoderLib/CABACReader.h b/source/Lib/DecoderLib/CABACReader.h
index 83e1cba89..6bc5d81a2 100644
--- a/source/Lib/DecoderLib/CABACReader.h
+++ b/source/Lib/DecoderLib/CABACReader.h
@@ -238,7 +238,8 @@ public:
 #if JVET_Z0131_IBC_BVD_BINARIZATION
 #if JVET_AC0104_IBC_BVD_PREDICTION
 #if JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV
-   void        bvdCoding                ( Mv& rMvd, MvdSuffixInfo& si, const bool useBvdPred = true, int bvOneZeroComp = 0, int bvZeroCompDir = 0 );
+   void bvdCoding(Mv &rMvd, MvdSuffixInfo &si, const bool useBvdPred = true, const bool useBvpCluster = true,
+                  int bvOneZeroComp = 0, int bvZeroCompDir = 0, const int &rribcFlipType = 0 );
 #else                                     
    void        bvdCoding                ( Mv& rMvd, MvdSuffixInfo& si, const bool useBvdPred = true, const int& rribcFlipType = 0 );
 #endif
@@ -247,7 +248,8 @@ public:
    void        bvdCodingRemainder       ( Mv& rMvd, MvdSuffixInfo& si, const int imv );
 #else
 #if JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV
-   void        bvdCoding                ( Mv& rMvd, int bvOneZeroComp = 0, int bvZeroCompDir = 0);
+   void bvdCoding(Mv &rMvd, const bool useBvpCluster = true, int bvOneZeroComp = 0, int bvZeroCompDir = 0,
+                  const int &rribcFlipType = 0 );
 #else                                     
    void        bvdCoding                ( Mv& rMvd, const int& rribcFlipType = 0);
 #endif
@@ -262,7 +264,8 @@ public:
 #if JVET_Z0131_IBC_BVD_BINARIZATION
 #if JVET_AC0104_IBC_BVD_PREDICTION
 #if JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV
-  void        bvdCoding                 ( Mv& rMvd, MvdSuffixInfo& si, const bool useBvdPred = true, int bvOneZeroComp = 0, int bvZeroCompDir = 0 );
+  void        bvdCoding(Mv &rMvd, MvdSuffixInfo &si, const bool useBvdPred = true, const bool useBvpCluster = true,
+                        int bvOneZeroComp = 0, int bvZeroCompDir = 0);
 #else                                     
   void        bvdCoding                 ( Mv& rMvd, MvdSuffixInfo& si, const bool useBvdPred = true );
 #endif
@@ -271,7 +274,7 @@ public:
   void        bvdCodingRemainder        ( Mv& rMvd, MvdSuffixInfo& si, const int imv );
 #else
 #if JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV
-  void        bvdCoding                 ( Mv& rMvd, int bvOneZeroComp = 0, int bvZeroCompDir = 0 );
+  void bvdCoding(Mv &rMvd, const bool useBvpCluster = true, int bvOneZeroComp = 0, int bvZeroCompDir = 0);
 #else                                     
   void        bvdCoding                 ( Mv& rMvd );
 #endif
diff --git a/source/Lib/DecoderLib/DecCu.cpp b/source/Lib/DecoderLib/DecCu.cpp
index 46b16fc79..b9289744c 100644
--- a/source/Lib/DecoderLib/DecCu.cpp
+++ b/source/Lib/DecoderLib/DecCu.cpp
@@ -3205,27 +3205,30 @@ void DecCu::xDeriveCUMV( CodingUnit &cu )
 #if (JVET_Z0084_IBC_TM && IBC_TM_AMVP) || JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV
           PU::fillIBCMvpCand(pu, amvpInfo, m_pcInterPred);
 #if JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV
+          if (pu.isBvpClusterApplicable())
+          {
 #if JVET_AA0070_RRIBC
-          if (pu.cu->rribcFlipType == 0)
+            if (pu.cu->rribcFlipType == 0)
 #endif
-          {
-            if (pu.cu->bvZeroCompDir == 1)
             {
-              for (int i = 0; i < 2; i++)
+              if (pu.cu->bvZeroCompDir == 1)
               {
-                amvpInfo.mvCand[i] = Mv(i == 0 ? std::max(-(int) pu.lwidth(), -pu.Y().x) : -pu.Y().x, 0);
-                amvpInfo.mvCand[i].changePrecision(MV_PRECISION_INT, MV_PRECISION_INTERNAL);
+                for (int i = 0; i < 2; i++)
+                {
+                  amvpInfo.mvCand[i] = Mv(i == 0 ? std::max(-(int) pu.lwidth(), -pu.Y().x) : -pu.Y().x, 0);
+                  amvpInfo.mvCand[i].changePrecision(MV_PRECISION_INT, MV_PRECISION_INTERNAL);
+                }
               }
-            }
-            else if (pu.cu->bvZeroCompDir == 2)
-            {
-              const int ctbSize     = pu.cs->sps->getCTUSize();
-              const int numCurrCtuY = (pu.Y().y >> (floorLog2(ctbSize)));
-              const int rrTop       = (numCurrCtuY < 3) ? -pu.Y().y : -((pu.Y().y & (ctbSize - 1)) + 2 * ctbSize);
-              for (int i = 0; i < 2; i++)
+              else if (pu.cu->bvZeroCompDir == 2)
               {
-                amvpInfo.mvCand[i] = Mv(0, i == 0 ? std::max(-(int) pu.lheight(), rrTop) : rrTop);
-                amvpInfo.mvCand[i].changePrecision(MV_PRECISION_INT, MV_PRECISION_INTERNAL);
+                const int ctbSize     = pu.cs->sps->getCTUSize();
+                const int numCurrCtuY = (pu.Y().y >> (floorLog2(ctbSize)));
+                const int rrTop       = (numCurrCtuY < 3) ? -pu.Y().y : -((pu.Y().y & (ctbSize - 1)) + 2 * ctbSize);
+                for (int i = 0; i < 2; i++)
+                {
+                  amvpInfo.mvCand[i] = Mv(0, i == 0 ? std::max(-(int) pu.lheight(), rrTop) : rrTop);
+                  amvpInfo.mvCand[i].changePrecision(MV_PRECISION_INT, MV_PRECISION_INTERNAL);
+                }
               }
             }
           }
diff --git a/source/Lib/DecoderLib/VLCReader.cpp b/source/Lib/DecoderLib/VLCReader.cpp
index 06677d93c..fb0e34f36 100644
--- a/source/Lib/DecoderLib/VLCReader.cpp
+++ b/source/Lib/DecoderLib/VLCReader.cpp
@@ -2579,6 +2579,9 @@ void HLSyntaxReader::parseSPS(SPS* pcSPS)
 #if JVET_AC0104_IBC_BVD_PREDICTION
     READ_FLAG( uiCode, "sps_bvd_pred_enabled_flag" );                   pcSPS->setUseBvdPred             ( uiCode != 0 );
 #endif
+#if JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV
+    READ_FLAG( uiCode, "sps_bvp_cluster_enabled_flag" );                pcSPS->setUseBvpCluster          ( uiCode != 0 );
+#endif
 #if JVET_AC0112_IBC_CIIP
     READ_FLAG( uiCode, "sps_ibc_ciip_enabled_flag" );                   pcSPS->setUseIbcCiip             ( uiCode != 0 );
 #endif
diff --git a/source/Lib/EncoderLib/CABACWriter.cpp b/source/Lib/EncoderLib/CABACWriter.cpp
index 896682396..ea6a716bd 100644
--- a/source/Lib/EncoderLib/CABACWriter.cpp
+++ b/source/Lib/EncoderLib/CABACWriter.cpp
@@ -2930,7 +2930,16 @@ void CABACWriter::prediction_unit( const PredictionUnit& pu )
   rribcData(*pu.cu);
 #endif
 #else
-  bvOneZeroComp(*pu.cu);
+  if (pu.isBvpClusterApplicable())
+  {
+    bvOneZeroComp(*pu.cu);
+  }
+#if JVET_AA0070_RRIBC
+  else
+  {
+    rribcData(*pu.cu);
+  }
+#endif
 #endif
 #if JVET_AC0112_IBC_LIC
   cuIbcLicFlag(*pu.cu);
@@ -2966,13 +2975,15 @@ void CABACWriter::prediction_unit( const PredictionUnit& pu )
 #if JVET_Z0131_IBC_BVD_BINARIZATION
 #if JVET_AC0104_IBC_BVD_PREDICTION
 #if JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV
-    bvdCoding(mvd, pu.isBvdPredApplicable(), pu.cu->bvOneZeroComp, pu.cu->bvZeroCompDir);   // already changed to signaling precision
+    bvdCoding(mvd, pu.isBvdPredApplicable(), pu.isBvpClusterApplicable(), pu.cu->bvOneZeroComp, pu.cu->bvZeroCompDir,
+              pu.cu->rribcFlipType);   // already changed to signaling precision
 #else
     bvdCoding(mvd, pu.isBvdPredApplicable(), pu.cu->rribcFlipType);   // already changed to signaling precision
 #endif
 #else
 #if JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV
-    bvdCoding(mvd, pu.cu->bvOneZeroComp, pu.cu->bvZeroCompDir);   // already changed to signaling precision
+    bvdCoding(mvd, pu.isBvpClusterApplicable(), pu.cu->bvOneZeroComp, pu.cu->bvZeroCompDir,
+              pu.cu->rribcFlipType);   // already changed to signaling precision
 #else
     bvdCoding(mvd, pu.cu->rribcFlipType);   // already changed to signaling precision
 #endif
@@ -2985,13 +2996,15 @@ void CABACWriter::prediction_unit( const PredictionUnit& pu )
 #if JVET_Z0131_IBC_BVD_BINARIZATION
 #if JVET_AC0104_IBC_BVD_PREDICTION
 #if JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV
-    bvdCoding(mvd, pu.isBvdPredApplicable(), pu.cu->bvOneZeroComp, pu.cu->bvZeroCompDir);   // already changed to signaling precision
+    bvdCoding(mvd, pu.isBvdPredApplicable(), pu.isBvpClusterApplicable(), pu.cu->bvOneZeroComp,
+              pu.cu->bvZeroCompDir);   // already changed to signaling precision
 #else
     bvdCoding(mvd, pu.isBvdPredApplicable());   // already changed to signaling precision
 #endif  
 #else
 #if JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV
-    bvdCoding(mvd, pu.cu->bvOneZeroComp, pu.cu->bvZeroCompDir);   // already changed to signaling precision
+    bvdCoding(mvd, pu.isBvpClusterApplicable(), pu.cu->bvOneZeroComp,
+              pu.cu->bvZeroCompDir);   // already changed to signaling precision
 #else
     bvdCoding(mvd);   // already changed to signaling precision
 #endif
@@ -5646,13 +5659,15 @@ void CABACWriter::bvdCodingRemainder(const Mv& rMvd, const MvdSuffixInfo& si, in
 #if JVET_AA0070_RRIBC
 #if JVET_AC0104_IBC_BVD_PREDICTION
 #if JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV
-void CABACWriter::bvdCoding(const Mv& rMvd, const bool useBvdPred, int bvOneZeroComp, int bvZeroCompDir)
+void CABACWriter::bvdCoding(const Mv &rMvd, const bool useBvdPred, const bool useBvpCluster, int bvOneZeroComp,
+                            int bvZeroCompDir, const int &rribcFlipType)
 #else
 void CABACWriter::bvdCoding(const Mv& rMvd, const bool useBvdPred, const int& rribcFlipType)
 #endif
 #else 
 #if JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV
-void CABACWriter::bvdCoding(const Mv& rMvd, int bvOneZeroComp, int bvZeroCompDir)
+void CABACWriter::bvdCoding(const Mv &rMvd, const bool useBvpCluster, int bvOneZeroComp, int bvZeroCompDir,
+                            const int &rribcFlipType)
 #else
 void CABACWriter::bvdCoding(const Mv& rMvd, const int& rribcFlipType)
 #endif
@@ -5660,13 +5675,14 @@ void CABACWriter::bvdCoding(const Mv& rMvd, const int& rribcFlipType)
 #else
 #if JVET_AC0104_IBC_BVD_PREDICTION
 #if JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV
-void CABACWriter::bvdCoding(const Mv& rMvd, const bool useBvdPred, int bvOneZeroComp, int bvZeroCompDir)
+void CABACWriter::bvdCoding(const Mv &rMvd, const bool useBvdPred, const bool useBvpCluster, int bvOneZeroComp,
+                            int bvZeroCompDir)
 #else
 void CABACWriter::bvdCoding(const Mv& rMvd, const bool useBvdPred)
 #endif
 #else 
 #if JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV
-void CABACWriter::bvdCoding(const Mv& rMvd, int bvOneZeroComp, int bvZeroCompDir)
+void CABACWriter::bvdCoding(const Mv &rMvd, const bool useBvpCluster, int bvOneZeroComp, int bvZeroCompDir)
 #else
 void CABACWriter::bvdCoding(const Mv& rMvd)
 #endif
@@ -5680,21 +5696,40 @@ void CABACWriter::bvdCoding(const Mv& rMvd)
   unsigned  verAbs  = unsigned( verMvd < 0 ? -verMvd : verMvd );
 
 #if JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV
-  if (bvOneZeroComp)
+  if (useBvpCluster)
   {
-    if (bvZeroCompDir == 1)
+    if (bvOneZeroComp)
     {
-      m_BinEncoder.encodeBin((horAbs > 0), Ctx::Bvd(HOR_BVD_CTX_OFFSET));
+      if (bvZeroCompDir == 1)
+      {
+        m_BinEncoder.encodeBin((horAbs > 0), Ctx::Bvd(HOR_BVD_CTX_OFFSET));
+      }
+      if (bvZeroCompDir == 2)
+      {
+        m_BinEncoder.encodeBin((verAbs > 0), Ctx::Bvd(VER_BVD_CTX_OFFSET));
+      }
     }
-    if (bvZeroCompDir == 2)
+    else
     {
+      m_BinEncoder.encodeBin((horAbs > 0), Ctx::Bvd(HOR_BVD_CTX_OFFSET));
       m_BinEncoder.encodeBin((verAbs > 0), Ctx::Bvd(VER_BVD_CTX_OFFSET));
     }
   }
-  else
+  else 
   {
+#if JVET_AA0070_RRIBC
+    if (rribcFlipType != 2)
+    {
+      m_BinEncoder.encodeBin((horAbs > 0), Ctx::Bvd(HOR_BVD_CTX_OFFSET));
+    }
+    if (rribcFlipType != 1)
+    {
+      m_BinEncoder.encodeBin((verAbs > 0), Ctx::Bvd(VER_BVD_CTX_OFFSET));
+    }
+#else
     m_BinEncoder.encodeBin((horAbs > 0), Ctx::Bvd(HOR_BVD_CTX_OFFSET));
     m_BinEncoder.encodeBin((verAbs > 0), Ctx::Bvd(VER_BVD_CTX_OFFSET));
+#endif
   }
 #else
 #if JVET_AA0070_RRIBC
@@ -5732,7 +5767,14 @@ void CABACWriter::bvdCoding(const Mv& rMvd)
     {
       xWriteBvdContext(horAbs - 1, NUM_HOR_BVD_CTX, HOR_BVD_CTX_OFFSET, BVD_CODING_GOLOMB_ORDER);
 #if JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV && JVET_AA0070_RRIBC
-      if (!bvOneZeroComp)   // not send the sign
+      if (useBvpCluster)
+      {
+        if (!bvOneZeroComp)   // not send the sign
+        {
+          m_BinEncoder.encodeBinEP((horMvd < 0));
+        }
+      }
+      else
       {
         m_BinEncoder.encodeBinEP((horMvd < 0));
       }
@@ -5744,7 +5786,14 @@ void CABACWriter::bvdCoding(const Mv& rMvd)
     {
       xWriteBvdContext(verAbs - 1, NUM_VER_BVD_CTX, VER_BVD_CTX_OFFSET, BVD_CODING_GOLOMB_ORDER);
 #if JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV && JVET_AA0070_RRIBC
-      if (!bvOneZeroComp)   // not send the sign
+      if (useBvpCluster)
+      {
+        if (!bvOneZeroComp)   // not send the sign
+        {
+          m_BinEncoder.encodeBinEP((verMvd < 0));
+        }
+      }
+      else
       {
         m_BinEncoder.encodeBinEP((verMvd < 0));
       }
@@ -5801,20 +5850,32 @@ void CABACWriter::mvsdIdxFunc(const PredictionUnit &pu, RefPicList eRefList)
   }
 #endif
 
-  Mv TrMv = Mv(pu.mvd[eRefList].getAbsHor(), pu.mvd[eRefList].getAbsVer());
+  Mv  trMv  = Mv(pu.mvd[eRefList].getAbsHor(), pu.mvd[eRefList].getAbsVer());
   int Thres = THRES_TRANS;
-  
+
   int mvsdIdx = pu.mvsdIdx[eRefList];
-  
+
 #if JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV && JVET_AA0070_RRIBC
-  if (TrMv != Mv(0, 0) && pu.cu->rribcFlipType == 0)
+  if (pu.isBvpClusterApplicable())
+  {
+    if (trMv != Mv(0, 0) && pu.cu->rribcFlipType == 0)
+    {
+      CHECK(mvsdIdx == -1, "mvsdIdx == -1 for transMv");
+    }
+  }
+  else
+  {
+    if (trMv != Mv(0, 0))
+    {
+      CHECK(mvsdIdx == -1, "mvsdIdx == -1 for transMv");
+    }
+  }
 #else
-  if (TrMv != Mv(0, 0))
-#endif 
+  if (trMv != Mv(0, 0))
   {
     CHECK(mvsdIdx == -1, "mvsdIdx == -1 for transMv");
   }
-
+#endif 
 
 #if JVET_AC0104_IBC_BVD_PREDICTION
   if (CU::isIBC(*pu.cu))
@@ -5849,7 +5910,7 @@ void CABACWriter::mvsdIdxFunc(const PredictionUnit &pu, RefPicList eRefList)
                  verPrefix < 0 ? 0 : MvdSuffixInfo::xGetGolombGroupMinValue(verPrefix));
     trMv.changeTransPrecAmvr2Internal(pu.cu->imv);
 #if JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV && JVET_AA0070_RRIBC
-    if (0 != pu.cu->rribcFlipType)
+    if (0 != pu.cu->rribcFlipType && pu.isBvpClusterApplicable())
     {
       bvdCodingRemainder(mvd, si, pu.cu->imv);
       return;
@@ -5900,7 +5961,7 @@ void CABACWriter::mvsdIdxFunc(const PredictionUnit &pu, RefPicList eRefList)
 #if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
   if (pu.mvd[eRefList].getHor())
   {
-    uint8_t ctxId = (TrMv.getHor() <= Thres) ? 0 : 1;
+    uint8_t ctxId = (trMv.getHor() <= Thres) ? 0 : 1;
     int bin = mvsdIdx & 1;
     m_BinEncoder.encodeBin(bin, Ctx::MvsdIdx(ctxId));
     mvsdIdx >>= 1;
@@ -5908,7 +5969,7 @@ void CABACWriter::mvsdIdxFunc(const PredictionUnit &pu, RefPicList eRefList)
   if (pu.mvd[eRefList].getVer())
   {
 
-    uint8_t ctxId = (TrMv.getVer() <= Thres) ? 0 : 1;
+    uint8_t ctxId = (trMv.getVer() <= Thres) ? 0 : 1;
 
     int bin = mvsdIdx & 1;
     m_BinEncoder.encodeBin(bin, Ctx::MvsdIdx(ctxId));
diff --git a/source/Lib/EncoderLib/CABACWriter.h b/source/Lib/EncoderLib/CABACWriter.h
index f705a465e..f9517d515 100644
--- a/source/Lib/EncoderLib/CABACWriter.h
+++ b/source/Lib/EncoderLib/CABACWriter.h
@@ -262,16 +262,17 @@ public:
   void        mvd_coding                ( const Mv &rMvd, int8_t imv, const int &rribcFlipType = 0 );
 #endif
 #if JVET_Z0131_IBC_BVD_BINARIZATION
-
 #if JVET_AC0104_IBC_BVD_PREDICTION
 #if JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV
-  void        bvdCoding                 ( const Mv& rMvd, const bool useBvdPred = true, int bvOneZeroComp = 0, int bvZeroCompDir = 0 );
+  void bvdCoding(const Mv &rMvd, const bool useBvdPred = true, const bool useBvpCluster = true, int bvOneZeroComp = 0,
+                 int bvZeroCompDir = 0, const int &rribcFlipType = 0 );
 #else                                     
   void        bvdCoding                 ( const Mv& rMvd, const bool useBvdPred = true, const int& rribcFlipType = 0 );
 #endif
 #else
 #if JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV
-  void        bvdCoding                 ( const Mv& rMvd, int bvOneZeroComp = 0, int bvZeroCompDir = 0 );
+  void bvdCoding(const Mv &rMvd, const bool useBvpCluster = true, int bvOneZeroComp = 0, int bvZeroCompDir = 0,
+                 const int &rribcFlipType = 0 );
 #else                                     
   void        bvdCoding                 ( const Mv& rMvd, const int& rribcFlipType = 0 );
 #endif
@@ -292,16 +293,10 @@ public:
   );
 
 #if JVET_Z0131_IBC_BVD_BINARIZATION
-#if JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV
-  void        bvdCoding                 ( const Mv &rMvd, int8_t imv, int bvOneZeroComp = 0, int bvZeroCompDir = 0 );
-#elif JVET_AA0070_RRIBC
-  void        bvdCoding                 ( const Mv &rMvd, int8_t imv, const int &rribcFlipType = 0 );
-#else
-  void        bvdCoding                 ( const Mv &rMvd, int8_t imv );
-#endif
 #if JVET_AC0104_IBC_BVD_PREDICTION
 #if JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV
-  void        bvdCoding                 ( const Mv& rMvd, const bool useBvdPred = true, int bvOneZeroComp = 0, int bvZeroCompDir = 0 );
+  void bvdCoding(const Mv &rMvd, const bool useBvdPred = true, const bool useBvpCluster = true, int bvOneZeroComp = 0,
+                 int bvZeroCompDir = 0);
 #else                                     
   void        bvdCoding                 ( const Mv& rMvd, const bool useBvdPred = true );
 #endif                                    
diff --git a/source/Lib/EncoderLib/EncCfg.h b/source/Lib/EncoderLib/EncCfg.h
index 1eac06749..f85e8acea 100644
--- a/source/Lib/EncoderLib/EncCfg.h
+++ b/source/Lib/EncoderLib/EncCfg.h
@@ -495,6 +495,9 @@ protected:
 #if JVET_AC0104_IBC_BVD_PREDICTION
   bool      m_bvdPred;
 #endif
+#if JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV
+  bool      m_bvpCluster;
+#endif
 #if JVET_Z0054_BLK_REF_PIC_REORDER
   bool      m_useARL;
 #endif
@@ -1574,6 +1577,10 @@ public:
   void      setUseBvdPred(bool b)                            { m_bvdPred = b; }
   bool      getUseBvdPred()                            const { return m_bvdPred; }
 #endif
+#if JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV
+  void      setUseBvpCluster(bool b)                         { m_bvpCluster = b; }
+  bool      getUseBvpCluster()                        const  { return m_bvpCluster; }
+#endif
 #if JVET_Z0054_BLK_REF_PIC_REORDER
   void      setUseARL(bool b) { m_useARL = b; }
   bool      getUseARL()                               const { return m_useARL; }
diff --git a/source/Lib/EncoderLib/EncLib.cpp b/source/Lib/EncoderLib/EncLib.cpp
index 6d1d60b7f..e7bffb99e 100644
--- a/source/Lib/EncoderLib/EncLib.cpp
+++ b/source/Lib/EncoderLib/EncLib.cpp
@@ -1879,6 +1879,9 @@ void EncLib::xInitSPS( SPS& sps )
 #if JVET_AC0104_IBC_BVD_PREDICTION
   sps.setUseBvdPred            (m_bvdPred);
 #endif
+#if JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV
+  sps.setUseBvpCluster         (m_bvpCluster);
+#endif
 #if JVET_Z0054_BLK_REF_PIC_REORDER
   sps.setUseARL                (m_useARL);
 #endif
diff --git a/source/Lib/EncoderLib/InterSearch.cpp b/source/Lib/EncoderLib/InterSearch.cpp
index 5f29394c9..b45879784 100644
--- a/source/Lib/EncoderLib/InterSearch.cpp
+++ b/source/Lib/EncoderLib/InterSearch.cpp
@@ -87,7 +87,11 @@ static const Mv s_acMvRefineQ[9] =
 };
 
 #if JVET_Z0131_IBC_BVD_BINARIZATION
+#if JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV
+void InterSearch::xEstBvdBitCosts(EstBvdBitsStruct *p, const bool useBvpCluster)
+#else
 void InterSearch::xEstBvdBitCosts(EstBvdBitsStruct *p)
+#endif
 {
   const FracBitsAccess& fracBits = m_CABACEstimator->getCtx().getFracBitsAcess();
 
@@ -147,7 +151,14 @@ void InterSearch::xEstBvdBitCosts(EstBvdBitsStruct *p)
   p->bitsImv[0] = fracBits.getFracBitsArray(Ctx::ImvFlag(1)).intBits[0];
   p->bitsImv[1] = fracBits.getFracBitsArray(Ctx::ImvFlag(1)).intBits[1];
 #if JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV && JVET_AA0070_RRIBC
-  p->bitsRribc  = fracBits.getFracBitsArray(Ctx::rribcFlipType(0)).intBits[1];
+  if (useBvpCluster)
+  {
+    p->bitsRribc  = fracBits.getFracBitsArray(Ctx::rribcFlipType(0)).intBits[1];
+  }
+  else
+  {
+    p->bitsRribc = 0;
+  }
 #endif
 }
 #endif
@@ -2158,8 +2169,16 @@ bool InterSearch::predIBCSearch(CodingUnit& cu, Partitioner& partitioner, const
   Mv           cMvPred;
 
 #if JVET_Z0131_IBC_BVD_BINARIZATION
+#if JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV
+  const PredictionUnit &pu = *cu.firstPU;
+  if (pu.isBvpClusterApplicable())
+  {
+    xEstBvdBitCosts(m_pcRdCost->getBvdBitCosts(), pu.isBvpClusterApplicable());
+  }
+#else
   xEstBvdBitCosts(m_pcRdCost->getBvdBitCosts());
 #endif
+#endif
 #if JVET_AA0070_RRIBC
   CodedCUInfo& relatedCU = ((EncModeCtrlMTnoRQT *)m_modeCtrl)->getBlkInfo(partitioner.currArea());
 #if JVET_AC0112_IBC_LIC
@@ -2432,12 +2451,16 @@ bool InterSearch::predIBCSearch(CodingUnit& cu, Partitioner& partitioner, const
     m_pcRdCost->setPredictors(cMvPred);
     m_pcRdCost->setCostScale(0);
 #if JVET_AA0070_RRIBC
-#if JVET_Z0084_IBC_TM && IBC_TM_AMVP
+#if (JVET_Z0084_IBC_TM && IBC_TM_AMVP) || JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV
 #if JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV
+    if (pu.isBvpClusterApplicable())
+    {
 #if !JVET_AC0112_IBC_CIIP && !JVET_AC0112_IBC_LIC
     Distortion initCost = 
 #endif
-      m_pcRdCost->getBvCostMultiplePreds(cMv.getHor(), cMv.getVer(), pu.cs->sps->getAMVREnabledFlag(), pu.cu->rribcFlipType, &pu.cu->imv, &bvpIdxBest, true, &amvpInfo4Pel[pu.cu->rribcFlipType]);
+        m_pcRdCost->getBvCostMultiplePreds(cMv.getHor(), cMv.getVer(), pu.cs->sps->getAMVREnabledFlag(),
+                                           pu.cu->rribcFlipType, &pu.cu->imv, &bvpIdxBest, true,
+                                           &amvpInfo4Pel[pu.cu->rribcFlipType], pu.isBvpClusterApplicable());
 
     if (pu.cu->rribcFlipType)
     {
@@ -2450,6 +2473,13 @@ bool InterSearch::predIBCSearch(CodingUnit& cu, Partitioner& partitioner, const
       getBestBvpBvOneZeroComp(pu, cMv, initCost, &bvpIdxBest , &amvpInfo[0], &amvpInfo4Pel[0]);
     }
 #endif
+    }
+    else
+    {
+      m_pcRdCost->getBvCostMultiplePreds(cMv.getHor(), cMv.getVer(), pu.cs->sps->getAMVREnabledFlag(),
+                                         pu.cu->rribcFlipType, &pu.cu->imv, &bvpIdxBest, true,
+                                         &amvpInfo4Pel[pu.cu->rribcFlipType]);
+    }
 #else
     m_pcRdCost->getBvCostMultiplePreds(cMv.getHor(), cMv.getVer(), pu.cs->sps->getAMVREnabledFlag(),
                                        pu.cu->rribcFlipType, &pu.cu->imv, &bvpIdxBest, true,
@@ -2774,7 +2804,7 @@ void InterSearch::xxIBCHashSearch(PredictionUnit &pu, Mv *mvPred, int numMvPred,
 
 #if JVET_Z0131_IBC_BVD_BINARIZATION
 #if JVET_AA0070_RRIBC
-#if JVET_Z0084_IBC_TM && IBC_TM_AMVP
+#if (JVET_Z0084_IBC_TM && IBC_TM_AMVP) || JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV
         Distortion cost = m_pcRdCost->getBvCostMultiplePreds(candMv.getHor(), candMv.getVer(), pu.cs->sps->getAMVREnabledFlag(), rribcFlipType, &pu.cu->imv, &idxMvPred, true, &amvpInfo4Pel[rribcFlipType]);
 #else
         Distortion cost = m_pcRdCost->getBvCostMultiplePreds(candMv.getHor(), candMv.getVer(), pu.cs->sps->getAMVREnabledFlag(), rribcFlipType, &pu.cu->imv, &idxMvPred);
diff --git a/source/Lib/EncoderLib/InterSearch.h b/source/Lib/EncoderLib/InterSearch.h
index cecf69913..561930e9e 100644
--- a/source/Lib/EncoderLib/InterSearch.h
+++ b/source/Lib/EncoderLib/InterSearch.h
@@ -711,7 +711,11 @@ protected:
   Distortion  xPatternRefinement    ( const CPelBuf* pcPatternKey, Mv baseRefMv, int iFrac, Mv& rcMvFrac, bool bAllowUseOfHadamard );
 
 #if JVET_Z0131_IBC_BVD_BINARIZATION
+#if JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV
+  void xEstBvdBitCosts(EstBvdBitsStruct *p, const bool useBvpCluster = true );
+#else
   void xEstBvdBitCosts(EstBvdBitsStruct *p);
+#endif
 #endif
 
    typedef struct
@@ -1134,7 +1138,7 @@ private:
 #else
   void  xxIBCHashSearch(PredictionUnit& pu, Mv* mvPred, int numMvPred, Mv &mv, int& idxMvPred, IbcHashMap& ibcHashMap);
 #endif
-  #if JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV
+#if JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV
   inline void getBestBvpBvOneZeroComp(PredictionUnit &pu, Mv cMv, Distortion initCost, int *bvpIdxBest,
                                                    AMVPInfo *amvp1Pel = NULL, AMVPInfo *amvp4Pel = NULL);
 #endif
diff --git a/source/Lib/EncoderLib/VLCWriter.cpp b/source/Lib/EncoderLib/VLCWriter.cpp
index aee393e26..45a5d065c 100644
--- a/source/Lib/EncoderLib/VLCWriter.cpp
+++ b/source/Lib/EncoderLib/VLCWriter.cpp
@@ -1639,6 +1639,9 @@ void HLSWriter::codeSPS( const SPS* pcSPS )
 #if JVET_AC0104_IBC_BVD_PREDICTION
     WRITE_FLAG(pcSPS->getUseBvdPred() ? 1 : 0,                                          "sps_ibc_bvd_pred_enabled_flag");
 #endif
+#if JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV
+    WRITE_FLAG(pcSPS->getUseBvpCluster() ? 1 : 0,                                       "sps_ibc_bvp_cluster_enabled_flag");
+#endif
 #if JVET_AC0112_IBC_CIIP
     WRITE_FLAG( pcSPS->getUseIbcCiip() ? 1 : 0,                                         "sps_ibc_ciip_enabled_flag" );
 #endif
-- 
GitLab