diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h
index 0a2889bb2fb743b1aeb152ae1887d2bf3e815161..7f070086d338bfa8a7af08e37d0162cb66e03004 100644
--- a/source/Lib/CommonLib/TypeDef.h
+++ b/source/Lib/CommonLib/TypeDef.h
@@ -50,6 +50,8 @@
 #include <assert.h>
 #include <cassert>
 
+#define JVET_L0104_NO_4x4BI_INTER_CU                      1 // Prohibit 4x4 bi-prediction for inter CU
+
 #define JVET_L0553_FIX_INITQP                             1
 
 #define JVET_L0147_ALF_SUBSAMPLED_LAPLACIAN               1 // Subsampled Laplacian calculation
diff --git a/source/Lib/CommonLib/UnitTools.cpp b/source/Lib/CommonLib/UnitTools.cpp
index 065e4fe39742efeb66e7cff63714dc3909d5d84f..ad55e2ec379c61087bbfd6a9fdb37ad57391b434 100644
--- a/source/Lib/CommonLib/UnitTools.cpp
+++ b/source/Lib/CommonLib/UnitTools.cpp
@@ -1955,6 +1955,12 @@ bool PU::addMVPCandWithScaling( const PredictionUnit &pu, const RefPicList &eRef
 bool PU::isBipredRestriction(const PredictionUnit &pu)
 {
   const SPSNext &spsNext = pu.cs->sps->getSpsNext();
+#if JVET_L0104_NO_4x4BI_INTER_CU
+  if(pu.cu->lumaSize().width == 4 && pu.cu->lumaSize().height ==4 )
+  {
+    return true;
+  }
+#endif
   if( !pu.cs->pcv->only2Nx2N && !spsNext.getUseSubPuMvp() && pu.cu->lumaSize().width == 8 && ( pu.lumaSize().width < 8 || pu.lumaSize().height < 8 ) )
   {
     return true;
diff --git a/source/Lib/DecoderLib/CABACReader.cpp b/source/Lib/DecoderLib/CABACReader.cpp
index 70aae0890cdc0a0bd6a842586cf89ef874d7ad75..f6c572efa44731ca674f93ba6942086e9b755c45 100644
--- a/source/Lib/DecoderLib/CABACReader.cpp
+++ b/source/Lib/DecoderLib/CABACReader.cpp
@@ -1329,7 +1329,11 @@ void CABACReader::inter_pred_idc( PredictionUnit& pu )
     pu.interDir = 1;
     return;
   }
+#if JVET_L0104_NO_4x4BI_INTER_CU
+  if( !(PU::isBipredRestriction(pu)) && ( pu.cu->partSize == SIZE_2Nx2N || pu.cs->sps->getSpsNext().getUseSubPuMvp() || pu.cu->lumaSize().width != 8 ) )
+#else
   if( pu.cu->partSize == SIZE_2Nx2N || pu.cs->sps->getSpsNext().getUseSubPuMvp() || pu.cu->lumaSize().width != 8 )
+#endif
   {
     unsigned ctxId = DeriveCtx::CtxInterDir(pu);
     if( m_BinDecoder.decodeBin( Ctx::InterDir(ctxId) ) )
diff --git a/source/Lib/EncoderLib/CABACWriter.cpp b/source/Lib/EncoderLib/CABACWriter.cpp
index 6eb95048a8d34be9fdb4d2bd1d56368420e34b0e..03d4197ea3e76b0331654aaa8e8fa39971d8dbb3 100644
--- a/source/Lib/EncoderLib/CABACWriter.cpp
+++ b/source/Lib/EncoderLib/CABACWriter.cpp
@@ -1284,7 +1284,11 @@ void CABACWriter::inter_pred_idc( const PredictionUnit& pu )
   {
     return;
   }
+#if JVET_L0104_NO_4x4BI_INTER_CU
+  if( !(PU::isBipredRestriction(pu)) && ( pu.cu->partSize == SIZE_2Nx2N || pu.cs->sps->getSpsNext().getUseSubPuMvp() || pu.cu->lumaSize().width != 8 ) )
+#else
   if( pu.cu->partSize == SIZE_2Nx2N || pu.cs->sps->getSpsNext().getUseSubPuMvp() || pu.cu->lumaSize().width != 8 )
+#endif
   {
     unsigned ctxId = DeriveCtx::CtxInterDir(pu);
     if( pu.interDir == 3 )
diff --git a/source/Lib/EncoderLib/EncCu.cpp b/source/Lib/EncoderLib/EncCu.cpp
index 926841c1057fb2740c447752eab355c7ab3f2bc3..60b08917056def793fde1fd21b93894c8a99b258 100644
--- a/source/Lib/EncoderLib/EncCu.cpp
+++ b/source/Lib/EncoderLib/EncCu.cpp
@@ -1415,6 +1415,22 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
     pu.cs = tempCS;
 
     PU::getInterMergeCandidates(pu, mergeCtx);
+#if JVET_L0104_NO_4x4BI_INTER_CU
+    if (PU::isBipredRestriction(pu))
+    {
+      for( uint32_t mergeCand = 0; mergeCand < mergeCtx.numValidMergeCand; ++mergeCand )
+      {
+        if( mergeCtx.interDirNeighbours[ mergeCand ] == 3 )
+        {
+          mergeCtx.interDirNeighbours[ mergeCand ] = 1;
+          mergeCtx.mvFieldNeighbours[( mergeCand << 1 ) + 1].setMvField( Mv( 0, 0 ), -1 );
+#if JVET_L0646_GBI
+          mergeCtx.GBiIdx[mergeCand] = GBI_DEFAULT;
+#endif
+        }
+      }
+    }
+#endif
   }