diff --git a/source/App/EncoderApp/EncApp.cpp b/source/App/EncoderApp/EncApp.cpp
index 54cfe178e2cfab8cf953d86c3f2a5ab06c59bc3b..022278ec48f570fb09fc1cc8b058195ebc0f9761 100644
--- a/source/App/EncoderApp/EncApp.cpp
+++ b/source/App/EncoderApp/EncApp.cpp
@@ -239,6 +239,9 @@ void EncApp::xInitLibCfg()
   m_cEncLib.setFastIntraEMT                                      ( m_FastEMT & m_EMT & 1 );
   m_cEncLib.setInterEMT                                          ( ( m_EMT >> 1 ) & 1 );
   m_cEncLib.setFastInterEMT                                      ( ( m_FastEMT >> 1 ) & ( m_EMT >> 1 ) & 1 );
+#endif
+#if JVET_M0303_IMPLICIT_MTS
+  m_cEncLib.setImplicitMTS                                       ( m_MTSImplicit );
 #endif
   m_cEncLib.setUseCompositeRef                                   ( m_compositeRefEnabled );
   m_cEncLib.setUseGBi                                            ( m_GBi );
diff --git a/source/App/EncoderApp/EncAppCfg.cpp b/source/App/EncoderApp/EncAppCfg.cpp
index f31fad8636275253c227ef20c31d5251b929fa5e..f817d6eccb92594aaf5661440411e169e78e71c8 100644
--- a/source/App/EncoderApp/EncAppCfg.cpp
+++ b/source/App/EncoderApp/EncAppCfg.cpp
@@ -852,6 +852,9 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] )
     "\t1:  Enable fast methods only for Intra EMT\n"
     "\t2:  Enable fast methods only for Inter EMT\n"
     "\t3:  Enable fast methods for both Intra & Inter EMT\n")
+#endif
+#if JVET_M0303_IMPLICIT_MTS
+  ("MTSImplicit",                                     m_MTSImplicit,                                        0, "Enable implicit MTS (when explicit MTS is off)\n")
 #endif
   ("CompositeLTReference",                            m_compositeRefEnabled,                            false, "Enable Composite Long Term Reference Frame")
   ("GBi",                                             m_GBi,                                            false, "Enable Generalized Bi-prediction(GBi)")
@@ -2299,9 +2302,15 @@ bool EncAppCfg::xCheckParameter()
   xConfirmPara( m_MTS < 0 || m_MTS > 3, "MTS must be greater than 0 smaller than 4" );
   xConfirmPara( m_MTSIntraMaxCand < 0 || m_MTSIntraMaxCand > 5, "m_MTSIntraMaxCand must be greater than 0 and smaller than 6" );
   xConfirmPara( m_MTSInterMaxCand < 0 || m_MTSInterMaxCand > 5, "m_MTSInterMaxCand must be greater than 0 and smaller than 6" );
+#if JVET_M0303_IMPLICIT_MTS
+  xConfirmPara( m_MTS != 0 && m_MTSImplicit != 0, "Both explicit and implicit MTS cannot be enabled at the same time" );
+#endif
 #else
   xConfirmPara( m_EMT < 0 || m_EMT >3, "EMT must be 0, 1, 2 or 3" );
   xConfirmPara( m_FastEMT < 0 || m_FastEMT >3, "FEMT must be 0, 1, 2 or 3" );
+#if JVET_M0303_IMPLICIT_MTS
+  xConfirmPara( m_EMT != 0 && m_MTSImplicit != 0, "Both explicit and implicit MTS cannot be enabled at the same time" );
+#endif
 #endif
   if( m_usePCM)
   {
diff --git a/source/App/EncoderApp/EncAppCfg.h b/source/App/EncoderApp/EncAppCfg.h
index c91c7ec580402ba1b0a7941bb7222fb0e4404b7f..1c5c5aa5178c7a081c57f24a44819a66abf6b560 100644
--- a/source/App/EncoderApp/EncAppCfg.h
+++ b/source/App/EncoderApp/EncAppCfg.h
@@ -224,6 +224,9 @@ protected:
   int       m_EMT;                                            ///< XZ: Enhanced Multiple Transform
   int       m_FastEMT;                                        ///< XZ: Fast Methods of Enhanced Multiple Transform
 #endif
+#if JVET_M0303_IMPLICIT_MTS
+  int       m_MTSImplicit;
+#endif
 
   bool      m_compositeRefEnabled;
   bool      m_GBi;
diff --git a/source/Lib/CommonLib/Slice.h b/source/Lib/CommonLib/Slice.h
index a4e2a209321b741c791666ac36898188b21a160b..5c1fe943dded0fd4957bca322887d7099b401f59 100644
--- a/source/Lib/CommonLib/Slice.h
+++ b/source/Lib/CommonLib/Slice.h
@@ -807,6 +807,9 @@ private:
 #if JVET_M0142_CCLM_COLLOCATED_CHROMA
   bool              m_cclmCollocatedChromaFlag;
 #endif
+#if JVET_M0303_IMPLICIT_MTS
+  bool              m_MTS;
+#endif
 #if JVET_M0464_UNI_MTS
   bool              m_IntraMTS;                   // 18
   bool              m_InterMTS;                   // 19
@@ -874,6 +877,15 @@ public:
   void      setCclmCollocatedChromaFlag( bool b )                                   { m_cclmCollocatedChromaFlag = b; }
   bool      getCclmCollocatedChromaFlag()                                 const     { return m_cclmCollocatedChromaFlag; }
 #endif
+#if JVET_M0303_IMPLICIT_MTS
+  void      setUseMTS             ( bool b )                                        { m_MTS = b; }
+  bool      getUseMTS             ()                                      const     { return m_MTS; }
+#if JVET_M0464_UNI_MTS
+  bool      getUseImplicitMTS     ()                                      const     { return m_MTS && !m_IntraMTS && !m_InterMTS; }
+#else
+  bool      getUseImplicitMTS     ()                                      const     { return m_MTS && !m_IntraEMT && !m_InterEMT; }
+#endif
+#endif
 #if JVET_M0464_UNI_MTS
   void      setUseIntraMTS        ( bool b )                                        { m_IntraMTS = b; }
   bool      getUseIntraMTS        ()                                      const     { return m_IntraMTS; }
diff --git a/source/Lib/CommonLib/TrQuant.cpp b/source/Lib/CommonLib/TrQuant.cpp
index 6396fe5c3b8c378fed8af9451dcaa382e05b1394..a148cb5a9170df948d39c94f4e6732782c5c4a09 100644
--- a/source/Lib/CommonLib/TrQuant.cpp
+++ b/source/Lib/CommonLib/TrQuant.cpp
@@ -296,7 +296,10 @@ void TrQuant::getTrTypes ( TransformUnit tu, const ComponentID compID, int &trTy
 #else
   bool emtActivated = CU::isIntra( *tu.cu ) ? tu.cs->sps->getSpsNext().getUseIntraEMT() : tu.cs->sps->getSpsNext().getUseInterEMT();
 #endif
-  
+#if JVET_M0303_IMPLICIT_MTS
+  bool mtsImplicit  = CU::isIntra( *tu.cu ) && tu.cs->sps->getSpsNext().getUseImplicitMTS() && compID == COMPONENT_Y;
+#endif
+
   trTypeHor = DCT2;
   trTypeVer = DCT2;
   
@@ -325,6 +328,22 @@ void TrQuant::getTrTypes ( TransformUnit tu, const ComponentID compID, int &trTy
       }
     }
   }
+#if JVET_M0303_IMPLICIT_MTS
+  else if ( mtsImplicit )
+  {
+    int  width       = tu.blocks[compID].width;
+    int  height      = tu.blocks[compID].height;
+    bool widthDstOk  = width  >= 4 && width  <= 16;
+    bool heightDstOk = height >= 4 && height <= 16;
+    
+    if ( width < height && widthDstOk )
+      trTypeHor = DST7;
+    else if ( height < width && heightDstOk )
+      trTypeVer = DST7;
+    else if ( width == height && widthDstOk )
+      trTypeHor = trTypeVer = DST7;
+  }
+#endif
 }
 
 void TrQuant::xT( const TransformUnit &tu, const ComponentID &compID, const CPelBuf &resi, CoeffBuf &dstCoeff, const int width, const int height )
diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h
index cb1dc56721259efdd479c56284673317f95b2bfc..f70df3826a494cc4db370c9d9cadd2d9063a20aa 100644
--- a/source/Lib/CommonLib/TypeDef.h
+++ b/source/Lib/CommonLib/TypeDef.h
@@ -50,6 +50,8 @@
 #include <assert.h>
 #include <cassert>
 
+#define JVET_M0303_IMPLICIT_MTS                           1 // Implicit transform selection (can be enabled with MTSImplicit encoder config parameter)
+
 #define JVET_M0471_LONG_DEBLOCKING_FILTERS                1 
 #define JVET_M0470                                        1 // Fixed GR/TU+EG-k transition point, use limited prefix length for escape codes
 
diff --git a/source/Lib/DecoderLib/VLCReader.cpp b/source/Lib/DecoderLib/VLCReader.cpp
index 94c056f8825fc470e949b7f7f9adbba23d19af54..ca13c0596da1d65b1a2025720e342a79d8c17256 100644
--- a/source/Lib/DecoderLib/VLCReader.cpp
+++ b/source/Lib/DecoderLib/VLCReader.cpp
@@ -798,13 +798,23 @@ void HLSyntaxReader::parseSPSNext( SPSNext& spsNext, const bool usePCM )
     READ_FLAG( symbol,  "sps_cclm_collocated_chroma_flag" );        spsNext.setCclmCollocatedChromaFlag( symbol != 0 );
   }
 #endif
+
+#if JVET_M0303_IMPLICIT_MTS
+  READ_FLAG( symbol,    "mts_enabled_flag" );                       spsNext.setUseMTS                 ( symbol != 0 );
+  if ( spsNext.getUseMTS() )
+  {
+#endif
 #if JVET_M0464_UNI_MTS
-  READ_FLAG( symbol,    "mts_intra_enabled_flag" );                 spsNext.setUseIntraMTS            ( symbol != 0 );
-  READ_FLAG( symbol,    "mts_inter_enabled_flag" );                 spsNext.setUseInterMTS            ( symbol != 0 );
+    READ_FLAG( symbol,    "mts_intra_enabled_flag" );               spsNext.setUseIntraMTS            ( symbol != 0 );
+    READ_FLAG( symbol,    "mts_inter_enabled_flag" );               spsNext.setUseInterMTS            ( symbol != 0 );
 #else
-  READ_FLAG( symbol,    "emt_intra_enabled_flag" );                 spsNext.setUseIntraEMT            ( symbol != 0 );
-  READ_FLAG( symbol,    "emt_inter_enabled_flag" );                 spsNext.setUseInterEMT            ( symbol != 0 );
+    READ_FLAG( symbol,    "emt_intra_enabled_flag" );               spsNext.setUseIntraEMT            ( symbol != 0 );
+    READ_FLAG( symbol,    "emt_inter_enabled_flag" );               spsNext.setUseInterEMT            ( symbol != 0 );
 #endif
+#if JVET_M0303_IMPLICIT_MTS
+  }
+#endif
+
   READ_FLAG( symbol,    "affine_flag" );                            spsNext.setUseAffine              ( symbol != 0 );
   if ( spsNext.getUseAffine() )
   {
diff --git a/source/Lib/EncoderLib/EncCfg.h b/source/Lib/EncoderLib/EncCfg.h
index bbfd74821a63dea93ca14b8dec8a7450abc75930..e9bf8e04771acc63e7a54b4e98a0ce8516ae44a7 100644
--- a/source/Lib/EncoderLib/EncCfg.h
+++ b/source/Lib/EncoderLib/EncCfg.h
@@ -214,6 +214,9 @@ protected:
   int       m_InterEMT;
   int       m_FastIntraEMT;
   int       m_FastInterEMT;
+#endif
+#if JVET_M0303_IMPLICIT_MTS
+  int       m_ImplicitMTS;
 #endif
   bool      m_LargeCTU;
   int       m_SubPuMvpMode;
@@ -735,9 +738,10 @@ public:
   void      setInterEMT                     ( bool b )       { m_InterEMT = b; }
   bool      getInterEMT                     ()         const { return m_InterEMT; }
 #endif
-
-
-
+#if JVET_M0303_IMPLICIT_MTS
+  void      setImplicitMTS                  ( bool b )       { m_ImplicitMTS = b; }
+  bool      getImplicitMTS                  ()         const { return m_ImplicitMTS; }
+#endif
 
   void      setUseCompositeRef              (bool b)         { m_compositeRefEnabled = b; }
   bool      getUseCompositeRef              ()         const { return m_compositeRefEnabled; }
diff --git a/source/Lib/EncoderLib/EncLib.cpp b/source/Lib/EncoderLib/EncLib.cpp
index 4d8506f0217d3292f6c752caf591887c6d7e76a7..a871a8ccfb8ca3f580d97ebd93110d6c9c4ad2bb 100644
--- a/source/Lib/EncoderLib/EncLib.cpp
+++ b/source/Lib/EncoderLib/EncLib.cpp
@@ -798,9 +798,17 @@ void EncLib::xInitSPS(SPS &sps)
   sps.setNoAmvrConstraintFlag(!m_bNoAmvrConstraintFlag);
   sps.setNoAffineMotionConstraintFlag(!m_Affine);
 #if JVET_M0464_UNI_MTS
+#if JVET_M0303_IMPLICIT_MTS
+  sps.setNoMtsConstraintFlag((m_IntraMTS || m_InterMTS || m_ImplicitMTS) ? false : true);
+#else
   sps.setNoMtsConstraintFlag((m_IntraMTS || m_InterMTS) ? false : true);
+#endif
+#else
+#if JVET_M0303_IMPLICIT_MTS
+  sps.setNoMtsConstraintFlag((m_IntraEMT || m_InterEMT || m_ImplicitMTS) ? false : true);
 #else
   sps.setNoMtsConstraintFlag((m_IntraEMT || m_InterEMT) ? false : true);
+#endif
 #endif
   sps.setNoLadfConstraintFlag(!m_LadfEnabled);
   sps.setNoDepQuantConstraintFlag(!m_DepQuantEnabledFlag);
@@ -867,9 +875,15 @@ void EncLib::xInitSPS(SPS &sps)
   sps.getSpsNext().setUseNextDQP            ( m_AltDQPCoding );
 #endif
 #if JVET_M0464_UNI_MTS
+#if JVET_M0303_IMPLICIT_MTS
+  sps.getSpsNext().setUseMTS                ( m_IntraMTS || m_InterMTS || m_ImplicitMTS );
+#endif
   sps.getSpsNext().setUseIntraMTS           ( m_IntraMTS );
   sps.getSpsNext().setUseInterMTS           ( m_InterMTS );
 #else
+#if JVET_M0303_IMPLICIT_MTS
+  sps.getSpsNext().setUseMTS                ( m_IntraEMT || m_InterEMT || m_ImplicitMTS );
+#endif
   sps.getSpsNext().setUseIntraEMT           ( m_IntraEMT );
   sps.getSpsNext().setUseInterEMT           ( m_InterEMT );
 #endif
diff --git a/source/Lib/EncoderLib/VLCWriter.cpp b/source/Lib/EncoderLib/VLCWriter.cpp
index 82300aae2c1bd65753949587c2561789de66badc..6697970fdd7b453826c8649715ca89a3951f5974 100644
--- a/source/Lib/EncoderLib/VLCWriter.cpp
+++ b/source/Lib/EncoderLib/VLCWriter.cpp
@@ -538,13 +538,23 @@ void HLSWriter::codeSPSNext( const SPSNext& spsNext, const bool usePCM )
     WRITE_FLAG( spsNext.getCclmCollocatedChromaFlag() ? 1 : 0,                                  "sps_cclm_collocated_chroma_flag" );
   }
 #endif
+
+#if JVET_M0303_IMPLICIT_MTS
+  WRITE_FLAG( spsNext.getUseMTS() ? 1 : 0,                                                      "mts_enabled_flag" );
+  if ( spsNext.getUseMTS() )
+  {
+#endif
 #if JVET_M0464_UNI_MTS
-  WRITE_FLAG( spsNext.getUseIntraMTS() ? 1 : 0,                                                 "mts_intra_enabled_flag" );
-  WRITE_FLAG( spsNext.getUseInterMTS() ? 1 : 0,                                                 "mts_inter_enabled_flag" );
+    WRITE_FLAG( spsNext.getUseIntraMTS() ? 1 : 0,                                               "mts_intra_enabled_flag" );
+    WRITE_FLAG( spsNext.getUseInterMTS() ? 1 : 0,                                               "mts_inter_enabled_flag" );
 #else
-  WRITE_FLAG( spsNext.getUseIntraEMT() ? 1 : 0,                                                 "emt_intra_enabled_flag" );
-  WRITE_FLAG( spsNext.getUseInterEMT() ? 1 : 0,                                                 "emt_inter_enabled_flag" );
+    WRITE_FLAG( spsNext.getUseIntraEMT() ? 1 : 0,                                               "emt_intra_enabled_flag" );
+    WRITE_FLAG( spsNext.getUseInterEMT() ? 1 : 0,                                               "emt_inter_enabled_flag" );
 #endif
+#if JVET_M0303_IMPLICIT_MTS
+  }
+#endif
+
   WRITE_FLAG( spsNext.getUseAffine() ? 1 : 0,                                                   "affine_flag" );
   if ( spsNext.getUseAffine() )
   {