Index: /branches/SHM-2.1-dev/source/App/TAppEncoder/TAppEncCfg.cpp
===================================================================
--- /branches/SHM-2.1-dev/source/App/TAppEncoder/TAppEncCfg.cpp	(revision 211)
+++ /branches/SHM-2.1-dev/source/App/TAppEncoder/TAppEncCfg.cpp	(revision 212)
@@ -634,4 +634,7 @@
   ("CFM", m_bUseCbfFastMode, false, "Cbf fast mode setting")
   ("ESD", m_useEarlySkipDetection, false, "Early SKIP detection setting")
+#if FAST_INTRA_SHVC
+  ("FIS", m_useFastIntraScalable, false, "Fast Intra Decision for Scalable HEVC")
+#endif
 #if RATE_CONTROL_LAMBDA_DOMAIN
 #if RC_SHVC_HARMONIZATION
@@ -1957,4 +1960,7 @@
   printf("CFM:%d ", m_bUseCbfFastMode         );
   printf("ESD:%d ", m_useEarlySkipDetection  );
+#if FAST_INTRA_SHVC
+  printf("FIS:%d ", m_useFastIntraScalable  );
+#endif
   printf("RQT:%d ", 1     );
   printf("TransformSkip:%d ",     m_useTransformSkip              );
Index: /branches/SHM-2.1-dev/source/App/TAppEncoder/TAppEncCfg.h
===================================================================
--- /branches/SHM-2.1-dev/source/App/TAppEncoder/TAppEncCfg.h	(revision 211)
+++ /branches/SHM-2.1-dev/source/App/TAppEncoder/TAppEncCfg.h	(revision 212)
@@ -208,4 +208,7 @@
   Bool      m_bUseCbfFastMode;                              ///< flag for using Cbf Fast PU Mode Decision
   Bool      m_useEarlySkipDetection;                         ///< flag for using Early SKIP Detection
+#if FAST_INTRA_SHVC
+  Bool      m_useFastIntraScalable;                          ///< flag for using Fast Intra Decision for Scalable HEVC
+#endif
   Int       m_sliceMode;                                     ///< 0: no slice limits, 1 : max number of CTBs per slice, 2: max number of bytes per slice, 
                                                              ///< 3: max number of tiles per slice
Index: /branches/SHM-2.1-dev/source/App/TAppEncoder/TAppEncTop.cpp
===================================================================
--- /branches/SHM-2.1-dev/source/App/TAppEncoder/TAppEncTop.cpp	(revision 211)
+++ /branches/SHM-2.1-dev/source/App/TAppEncoder/TAppEncTop.cpp	(revision 212)
@@ -225,4 +225,7 @@
     m_acTEncTop[layer].setUseCbfFastMode               ( m_bUseCbfFastMode  );
     m_acTEncTop[layer].setUseEarlySkipDetection        ( m_useEarlySkipDetection );
+#if FAST_INTRA_SHVC
+    m_acTEncTop[layer].setUseFastIntraScalable         ( m_useFastIntraScalable );
+#endif
 
     m_acTEncTop[layer].setUseTransformSkip             ( m_useTransformSkip      );
@@ -555,4 +558,7 @@
   m_cTEncTop.setUseCbfFastMode            ( m_bUseCbfFastMode  );
   m_cTEncTop.setUseEarlySkipDetection            ( m_useEarlySkipDetection );
+#if FAST_INTRA_SHVC
+  m_cTEncTop.setUseFastIntraScalable            ( m_useFastIntraScalable );
+#endif
 
   m_cTEncTop.setUseTransformSkip             ( m_useTransformSkip      );
Index: /branches/SHM-2.1-dev/source/Lib/TLibCommon/TComDataCU.cpp
===================================================================
--- /branches/SHM-2.1-dev/source/Lib/TLibCommon/TComDataCU.cpp	(revision 211)
+++ /branches/SHM-2.1-dev/source/Lib/TLibCommon/TComDataCU.cpp	(revision 212)
@@ -1647,5 +1647,5 @@
   Int         iLeftIntraDir, iAboveIntraDir;
   Int         uiPredNum = 0;
-  
+
   // Get intra direction of left PU
   pcTempCU = getPULeft( uiTempPartIdx, m_uiAbsIdxInLCU + uiAbsPartIdx );
@@ -1738,4 +1738,65 @@
   return uiPredNum;
 }
+
+
+#if FAST_INTRA_SHVC
+/** generate limited set of remaining modes
+*\param   uiAbsPartIdx
+*\param   uiIntraDirPred  pointer to the array for MPM storage
+*\returns Number of intra coding modes (nb of remaining modes + 3 MPMs)
+*/
+Int TComDataCU::reduceSetOfIntraModes( UInt uiAbsPartIdx, Int* uiIntraDirPred, Int &fullSetOfModes )
+{
+  // check BL mode
+  UInt          uiCUAddrBase, uiAbsPartAddrBase;
+  TComDataCU*   pcTempCU = getBaseColCU( uiAbsPartIdx, uiCUAddrBase, uiAbsPartAddrBase );
+
+  if( pcTempCU->getPredictionMode( uiAbsPartAddrBase ) != MODE_INTRA )
+    return( NUM_INTRA_MODE-1 );
+
+  // compute set of enabled modes g_reducedSetIntraModes[...]
+  Int authorizedMode[NUM_INTRA_MODE-1]={1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};
+  Int nbModes;
+  for (nbModes=0; nbModes<3; nbModes++)  // add 3 MPMs 1st
+  {
+    g_reducedSetIntraModes[nbModes] = uiIntraDirPred[nbModes];
+    authorizedMode[ uiIntraDirPred[nbModes] ] = 0;
+  }
+
+  Int iColBaseDir = pcTempCU->getLumaIntraDir( uiAbsPartAddrBase );
+  if ( authorizedMode[iColBaseDir] )  //possibly add BL mode
+  {
+    g_reducedSetIntraModes[nbModes++] = iColBaseDir;
+    authorizedMode[ iColBaseDir ] = 0;
+  }
+
+  Int iRefMode = ( iColBaseDir > 1 ) ? iColBaseDir : uiIntraDirPred[0];
+  if ( iRefMode > 1 )    //add neighboring modes of refMode
+  {
+    UInt Left  = iRefMode;
+    UInt Right = iRefMode;
+    while ( nbModes < NB_REMAIN_MODES+3 )
+    {
+      Left = ((Left + 29) % 32) + 2;
+      Right = ((Right - 1 ) % 32) + 2;
+      if ( authorizedMode[Left] )   g_reducedSetIntraModes[nbModes++] = Left;
+      if ( authorizedMode[Right] )  g_reducedSetIntraModes[nbModes++] = Right;
+    }
+  }
+  else      //add pre-defined modes
+  {
+    Int  idx = 0;
+    while ( nbModes < NB_REMAIN_MODES+3 )
+    {
+      UInt mode = g_predefSetIntraModes[idx++];
+      if ( authorizedMode[mode] )   g_reducedSetIntraModes[nbModes++] = mode;
+    }
+  }
+
+  fullSetOfModes = 0;
+  return ( nbModes );
+}
+#endif
+
 
 UInt TComDataCU::getCtxSplitFlag( UInt uiAbsPartIdx, UInt uiDepth )
Index: /branches/SHM-2.1-dev/source/Lib/TLibCommon/TComDataCU.h
===================================================================
--- /branches/SHM-2.1-dev/source/Lib/TLibCommon/TComDataCU.h	(revision 211)
+++ /branches/SHM-2.1-dev/source/Lib/TLibCommon/TComDataCU.h	(revision 212)
@@ -533,4 +533,8 @@
 #endif  
 
+#if FAST_INTRA_SHVC
+  Int           reduceSetOfIntraModes              (  UInt   uiAbsPartIdx, Int* uiIntraDirPred, Int &fullSetOfModes );
+#endif
+
 #if REF_IDX_ME_ZEROMV
   Bool xCheckZeroMVILRMerge(UChar uhInterDir, TComMvField& cMvFieldL0, TComMvField& cMvFieldL1);
Index: /branches/SHM-2.1-dev/source/Lib/TLibCommon/TComRom.cpp
===================================================================
--- /branches/SHM-2.1-dev/source/Lib/TLibCommon/TComRom.cpp	(revision 211)
+++ /branches/SHM-2.1-dev/source/Lib/TLibCommon/TComRom.cpp	(revision 212)
@@ -99,4 +99,9 @@
 UInt g_auiPUOffset[8] = { 0, 8, 4, 4, 2, 10, 1, 5};
 
+#if FAST_INTRA_SHVC
+UInt g_reducedSetIntraModes[NUM_INTRA_MODE-1] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }; 
+UInt g_predefSetIntraModes[NUM_INTRA_MODE-1] = {26,10,18,34,2,22,14,30,6,24,12,28,8,20,16,32,4,17,19,15,21,13,23,11,25,9,27,7,29,5,31,3,33,0,2};
+#endif
+
 Void initZscanToRaster ( Int iMaxDepth, Int iDepth, UInt uiStartVal, UInt*& rpuiCurrIdx )
 {
Index: /branches/SHM-2.1-dev/source/Lib/TLibCommon/TComRom.h
===================================================================
--- /branches/SHM-2.1-dev/source/Lib/TLibCommon/TComRom.h	(revision 211)
+++ /branches/SHM-2.1-dev/source/Lib/TLibCommon/TComRom.h	(revision 212)
@@ -132,4 +132,9 @@
 
 extern const UChar  g_aucIntraModeNumFast[7];
+
+#if FAST_INTRA_SHVC
+extern       UInt  g_reducedSetIntraModes[NUM_INTRA_MODE-1];
+extern       UInt  g_predefSetIntraModes[NUM_INTRA_MODE-1];
+#endif
 
 // ====================================================================================================================
Index: /branches/SHM-2.1-dev/source/Lib/TLibCommon/TypeDef.h
===================================================================
--- /branches/SHM-2.1-dev/source/Lib/TLibCommon/TypeDef.h	(revision 211)
+++ /branches/SHM-2.1-dev/source/Lib/TLibCommon/TypeDef.h	(revision 212)
@@ -115,4 +115,9 @@
 #define ILP_DECODED_PICTURE              0
 #define SYNTAX_OUTPUT                    0
+#endif
+
+#define FAST_INTRA_SHVC                  1      ///< M0115: reduction number of intra modes in the EL (encoder only)
+#if FAST_INTRA_SHVC
+  #define NB_REMAIN_MODES                2      ///< nb of remaining modes (M0115)
 #endif
 
Index: /branches/SHM-2.1-dev/source/Lib/TLibEncoder/TEncCfg.h
===================================================================
--- /branches/SHM-2.1-dev/source/Lib/TLibEncoder/TEncCfg.h	(revision 211)
+++ /branches/SHM-2.1-dev/source/Lib/TLibEncoder/TEncCfg.h	(revision 212)
@@ -204,4 +204,7 @@
   Bool      m_bUseCbfFastMode;
   Bool      m_useEarlySkipDetection;
+#if FAST_INTRA_SHVC
+  Bool      m_useFastIntraScalable;
+#endif
   Bool      m_useTransformSkip;
   Bool      m_useTransformSkipFast;
@@ -507,4 +510,7 @@
   Void      setUseCbfFastMode            ( Bool  b )     { m_bUseCbfFastMode = b; }
   Void      setUseEarlySkipDetection        ( Bool  b )     { m_useEarlySkipDetection = b; }
+#if FAST_INTRA_SHVC
+  Void      setUseFastIntraScalable         ( Bool  b )     { m_useFastIntraScalable = b; }
+#endif
   Void      setUseConstrainedIntraPred      ( Bool  b )     { m_bUseConstrainedIntraPred = b; }
   Void      setPCMInputBitDepthFlag         ( Bool  b )     { m_bPCMInputBitDepthFlag = b; }
@@ -531,4 +537,7 @@
   Bool      getUseCbfFastMode           ()      { return m_bUseCbfFastMode; }
   Bool      getUseEarlySkipDetection        ()      { return m_useEarlySkipDetection; }
+#if FAST_INTRA_SHVC
+  Bool      getUseFastIntraScalable         ()      { return m_useFastIntraScalable; }
+#endif
   Bool      getUseConstrainedIntraPred      ()      { return m_bUseConstrainedIntraPred; }
   Bool      getPCMInputBitDepthFlag         ()      { return m_bPCMInputBitDepthFlag;   }
Index: /branches/SHM-2.1-dev/source/Lib/TLibEncoder/TEncSearch.cpp
===================================================================
--- /branches/SHM-2.1-dev/source/Lib/TLibEncoder/TEncSearch.cpp	(revision 211)
+++ /branches/SHM-2.1-dev/source/Lib/TLibEncoder/TEncSearch.cpp	(revision 212)
@@ -2506,4 +2506,25 @@
     {
       assert(numModesForFullRD < numModesAvailable);
+#if FAST_INTRA_SHVC
+      Int   uiPreds[3] = {-1, -1, -1};
+      Int   iMode = -1;
+      Bool  skipFastHAD = false;
+      Int numCand = pcCU->getIntraDirLumaPredictor( uiPartOffset, uiPreds, &iMode );
+
+      if ( m_pcEncCfg->getUseFastIntraScalable() )
+      {
+        if( pcCU->getLayerId() > 0 )
+        {
+          numModesAvailable = pcCU->reduceSetOfIntraModes(uiPartOffset, uiPreds, iMode );
+          if( numModesForFullRD > numModesAvailable ) //fast HAD can be skipped
+          {
+            skipFastHAD = true;
+            numModesForFullRD = numModesAvailable;
+            for( Int i=0; i < numModesForFullRD; i++ ) 
+              uiRdModeList[ i ] = g_reducedSetIntraModes[ i ];
+          }
+        }
+      }
+#endif
 
       for( Int i=0; i < numModesForFullRD; i++ ) 
@@ -2516,4 +2537,12 @@
       {
         UInt uiMode = modeIdx;
+#if FAST_INTRA_SHVC
+        if ( m_pcEncCfg->getUseFastIntraScalable() )
+        {
+          if( skipFastHAD )//indicates that fast HAD can be skipped
+            break;
+          uiMode = ( iMode==0 ) ? g_reducedSetIntraModes[modeIdx] : uiMode; //(iMode=0) indicates reduced set of modes
+        }
+#endif
 
         predIntraLumaAng( pcCU->getPattern(), uiMode, piPred, uiStride, uiWidth, uiHeight, bAboveAvail, bLeftAvail );
@@ -2529,7 +2558,9 @@
     
 #if FAST_UDI_USE_MPM
+#if FAST_INTRA_SHVC == 0
       Int uiPreds[3] = {-1, -1, -1};
       Int iMode = -1;
       Int numCand = pcCU->getIntraDirLumaPredictor( uiPartOffset, uiPreds, &iMode );
+#endif
       if( iMode >= 0 )
       {
