Index: /branches/SHM-3.1-dev/source/App/TAppEncoder/TAppEncCfg.cpp
===================================================================
--- /branches/SHM-3.1-dev/source/App/TAppEncoder/TAppEncCfg.cpp	(revision 434)
+++ /branches/SHM-3.1-dev/source/App/TAppEncoder/TAppEncCfg.cpp	(revision 435)
@@ -457,4 +457,7 @@
 #if AVC_SYNTAX
   string  cfg_BLSyntaxFile;
+#endif
+#if N0383_IL_CONSTRAINED_TILE_SETS_SEI
+  string  cfg_tileSets;
 #endif
 #else
@@ -849,4 +852,9 @@
   ("AdaptiveResolutionChange",     m_adaptiveResolutionChange, 0, "Adaptive resolution change frame number. Should coincide with EL RAP picture. (0: disable)")
 #endif
+#if N0383_IL_CONSTRAINED_TILE_SETS_SEI
+  ("SEIInterLayerConstrainedTileSets", m_interLayerConstrainedTileSetsSEIEnabled, false, "Control generation of inter layer constrained tile sets SEI message")
+  ("IlNumSetsInMessage",               m_ilNumSetsInMessage,                         0u, "Number of inter layer constrained tile sets")
+  ("TileSetsArray",                    cfg_tileSets,                         string(""), "Array containing tile sets params (TopLeftTileIndex, BottonRightTileIndex and ilcIdc for each set) ")
+#endif
   ;
   
@@ -1355,4 +1363,48 @@
     }
   }
+#if N0383_IL_CONSTRAINED_TILE_SETS_SEI
+  if (m_interLayerConstrainedTileSetsSEIEnabled)
+  {
+    if (m_iNumColumnsMinus1 == 0 && m_iNumRowsMinus1 == 0)
+    {
+      printf( "Tiles are not defined (needed for inter-layer comnstrained tile sets SEI).\n" );
+      exit( EXIT_FAILURE );
+    }
+    Char* pTileSets = cfg_tileSets.empty() ? NULL : strdup(cfg_tileSets.c_str());
+    int i = 0;
+    char *topLeftTileIndex = strtok(pTileSets, " ,");
+    while(topLeftTileIndex != NULL)
+    {
+      if( i >= m_ilNumSetsInMessage )
+      {
+        printf( "The number of tile sets is larger than defined by IlNumSetsInMessage.\n" );
+        exit( EXIT_FAILURE );
+      }
+      *( m_topLeftTileIndex + i ) = atoi( topLeftTileIndex );
+      char *bottonRightTileIndex = strtok(NULL, " ,");
+      if( bottonRightTileIndex == NULL )
+      {
+        printf( "BottonRightTileIndex is missing in the tile sets.\n" );
+        exit( EXIT_FAILURE );
+      }
+      *( m_bottomRightTileIndex + i ) = atoi( bottonRightTileIndex );
+      char *ilcIdc = strtok(NULL, " ,");
+      if( ilcIdc == NULL )
+      {
+        printf( "IlcIdc is missing in the tile sets.\n" );
+        exit( EXIT_FAILURE );
+      }
+      *( m_ilcIdc + i ) = atoi( ilcIdc );
+      topLeftTileIndex = strtok(NULL, " ,");
+      i++;
+    }
+    if( i < m_ilNumSetsInMessage )
+    {
+      printf( "The number of tile sets is smaller than defined by IlNumSetsInMessage.\n" );
+      exit( EXIT_FAILURE );
+    }
+    m_skippedTileSetPresentFlag = false;
+  }
+#endif
   // check validity of input parameters
   xCheckParameter();
Index: /branches/SHM-3.1-dev/source/App/TAppEncoder/TAppEncCfg.h
===================================================================
--- /branches/SHM-3.1-dev/source/App/TAppEncoder/TAppEncCfg.h	(revision 434)
+++ /branches/SHM-3.1-dev/source/App/TAppEncoder/TAppEncCfg.h	(revision 435)
@@ -367,4 +367,12 @@
   RepFormatCfg m_repFormatCfg[16];                            ///< Rep_format structures
 #endif
+#if N0383_IL_CONSTRAINED_TILE_SETS_SEI
+  Bool      m_interLayerConstrainedTileSetsSEIEnabled;
+  UInt      m_ilNumSetsInMessage;
+  Bool      m_skippedTileSetPresentFlag;
+  UInt      m_topLeftTileIndex[1024];
+  UInt      m_bottomRightTileIndex[1024];
+  UInt      m_ilcIdc[1024];
+#endif
 public:
   TAppEncCfg();
Index: /branches/SHM-3.1-dev/source/App/TAppEncoder/TAppEncTop.cpp
===================================================================
--- /branches/SHM-3.1-dev/source/App/TAppEncoder/TAppEncTop.cpp	(revision 434)
+++ /branches/SHM-3.1-dev/source/App/TAppEncoder/TAppEncTop.cpp	(revision 435)
@@ -463,4 +463,12 @@
     m_acTEncTop[layer].setSOPDescriptionSEIEnabled( m_SOPDescriptionSEIEnabled );
     m_acTEncTop[layer].setScalableNestingSEIEnabled( m_scalableNestingSEIEnabled );
+#if N0383_IL_CONSTRAINED_TILE_SETS_SEI
+    m_acTEncTop[layer].setInterLayerConstrainedTileSetsSEIEnabled( m_interLayerConstrainedTileSetsSEIEnabled );
+    m_acTEncTop[layer].setIlNumSetsInMessage( m_ilNumSetsInMessage );
+    m_acTEncTop[layer].setSkippedTileSetPresentFlag( m_skippedTileSetPresentFlag );
+    m_acTEncTop[layer].setTopLeftTileIndex( m_topLeftTileIndex );
+    m_acTEncTop[layer].setBottomRightTileIndex( m_bottomRightTileIndex );
+    m_acTEncTop[layer].setIlcIdc( m_ilcIdc );
+#endif
     m_acTEncTop[layer].setUniformSpacingIdr          ( m_iUniformSpacingIdr );
     m_acTEncTop[layer].setNumColumnsMinus1           ( m_iNumColumnsMinus1 );
Index: /branches/SHM-3.1-dev/source/Lib/TLibCommon/SEI.h
===================================================================
--- /branches/SHM-3.1-dev/source/Lib/TLibCommon/SEI.h	(revision 434)
+++ /branches/SHM-3.1-dev/source/Lib/TLibCommon/SEI.h	(revision 435)
@@ -75,4 +75,7 @@
     LAYERS_PRESENT                       = 137,
 #endif
+#if N0383_IL_CONSTRAINED_TILE_SETS_SEI
+    INTER_LAYER_CONSTRAINED_TILE_SETS    = 138
+#endif
   };
   
@@ -381,4 +384,28 @@
 };
 
+#if N0383_IL_CONSTRAINED_TILE_SETS_SEI
+class SEIInterLayerConstrainedTileSets : public SEI
+{
+public:
+  PayloadType payloadType() const { return INTER_LAYER_CONSTRAINED_TILE_SETS; }
+
+  SEIInterLayerConstrainedTileSets() {}
+  virtual ~SEIInterLayerConstrainedTileSets() {}
+
+  Bool m_ilAllTilesExactSampleValueMatchFlag;
+  Bool m_ilOneTilePerTileSetFlag;
+  UInt m_ilNumSetsInMessageMinus1;
+  Bool m_skippedTileSetPresentFlag;
+  UInt m_ilctsId[256];
+  UInt m_ilNumTileRectsInSetMinus1[256];
+  UInt m_ilTopLeftTileIndex[256][440];
+  UInt m_ilBottomRightTileIndex[256][440];
+  UInt m_ilcIdc[256];
+  Bool m_ilExactSampleValueMatchFlag[256];
+  UInt m_allTilesIlcIdc;
+};
+#endif
+
+
 typedef std::list<SEI*> SEIMessages;
 
Index: /branches/SHM-3.1-dev/source/Lib/TLibCommon/TComPicSym.cpp
===================================================================
--- /branches/SHM-3.1-dev/source/Lib/TLibCommon/TComPicSym.cpp	(revision 434)
+++ /branches/SHM-3.1-dev/source/Lib/TLibCommon/TComPicSym.cpp	(revision 435)
@@ -115,4 +115,9 @@
   m_puiCUOrderMap = new UInt[m_uiNumCUsInFrame+1];
   m_puiTileIdxMap = new UInt[m_uiNumCUsInFrame];
+#if N0383_IL_CONSTRAINED_TILE_SETS_SEI
+  m_piTileSetIdxMap = new Int[m_uiNumCUsInFrame];
+  m_pucTileSetType = new UChar[m_uiNumCUsInFrame];
+  m_pbSkippedTileSetFlag = new Bool[m_uiNumCUsInFrame];
+#endif
   m_puiInverseCUOrderMap = new UInt[m_uiNumCUsInFrame+1];
 
@@ -166,4 +171,12 @@
   delete [] m_puiTileIdxMap;
   m_puiTileIdxMap = NULL;
+#if N0383_IL_CONSTRAINED_TILE_SETS_SEI
+  delete [] m_piTileSetIdxMap;
+  m_piTileSetIdxMap = NULL;
+  delete [] m_pucTileSetType;
+  m_pucTileSetType = NULL;
+  delete [] m_pbSkippedTileSetFlag;
+  m_pbSkippedTileSetFlag = NULL;
+#endif
 
   delete [] m_puiInverseCUOrderMap;
Index: /branches/SHM-3.1-dev/source/Lib/TLibCommon/TComPicSym.h
===================================================================
--- /branches/SHM-3.1-dev/source/Lib/TLibCommon/TComPicSym.h	(revision 434)
+++ /branches/SHM-3.1-dev/source/Lib/TLibCommon/TComPicSym.h	(revision 435)
@@ -105,4 +105,9 @@
   UInt*         m_puiCUOrderMap;       //the map of LCU raster scan address relative to LCU encoding order 
   UInt*         m_puiTileIdxMap;       //the map of the tile index relative to LCU raster scan address 
+#if N0383_IL_CONSTRAINED_TILE_SETS_SEI
+  Int*          m_piTileSetIdxMap;     //the map of the tile set index relative to LCU raster scan address
+  UChar*        m_pucTileSetType;
+  Bool*         m_pbSkippedTileSetFlag;
+#endif
   UInt*         m_puiInverseCUOrderMap;
 
@@ -143,4 +148,15 @@
   UInt         getCUOrderMap( Int encCUOrder )                       { return *(m_puiCUOrderMap + (encCUOrder>=m_uiNumCUsInFrame ? m_uiNumCUsInFrame : encCUOrder)); }
   UInt         getTileIdxMap( Int i )                                { return *(m_puiTileIdxMap + i); }
+#if N0383_IL_CONSTRAINED_TILE_SETS_SEI
+  Void         setTileSetIdxMap( Int i, Int tileSetIdx, UChar setType, Bool skipFlag )
+  {
+    m_piTileSetIdxMap[i]       = tileSetIdx;
+    m_pucTileSetType[i]        = setType;
+    m_pbSkippedTileSetFlag[i]  = skipFlag;
+  }
+  Int          getTileSetIdxMap( Int i )                             { return *(m_piTileSetIdxMap + i); }
+  UChar        getTileSetType( Int i )                               { return *(m_pucTileSetType + i); }
+  Bool         getSkippedTileSetFlag( Int i )                        { return *(m_pbSkippedTileSetFlag + i); }
+#endif
   Void         setInverseCUOrderMap( Int cuAddr, Int encCUOrder )    { *(m_puiInverseCUOrderMap + cuAddr) = encCUOrder; }
   UInt         getInverseCUOrderMap( Int cuAddr )                    { return *(m_puiInverseCUOrderMap + (cuAddr>=m_uiNumCUsInFrame ? m_uiNumCUsInFrame : cuAddr)); }
Index: /branches/SHM-3.1-dev/source/Lib/TLibCommon/TypeDef.h
===================================================================
--- /branches/SHM-3.1-dev/source/Lib/TLibCommon/TypeDef.h	(revision 434)
+++ /branches/SHM-3.1-dev/source/Lib/TLibCommon/TypeDef.h	(revision 435)
@@ -157,4 +157,5 @@
 #define VIEW_ID_RELATED_SIGNALING        1      ///< Introduce syntax elements view_id_len_minus1 and view_id_val
 #define M0043_LAYERS_PRESENT_SEI         0      ///< JCTVC-M0043: add layers present SEI. Macro shall be equal to 0 according to the JCTVC-N0174 discussion. The code is to be removed.
+#define N0383_IL_CONSTRAINED_TILE_SETS_SEI  1
 #else
 #define SYNTAX_OUTPUT                    0
Index: /branches/SHM-3.1-dev/source/Lib/TLibDecoder/SEIread.cpp
===================================================================
--- /branches/SHM-3.1-dev/source/Lib/TLibDecoder/SEIread.cpp	(revision 434)
+++ /branches/SHM-3.1-dev/source/Lib/TLibDecoder/SEIread.cpp	(revision 435)
@@ -101,4 +101,9 @@
     fprintf( g_hTrace, "=========== SOP Description SEI message ===========\n");
     break;
+#if N0383_IL_CONSTRAINED_TILE_SETS_SEI
+  case SEI::INTER_LAYER_CONSTRAINED_TILE_SETS:
+    fprintf( g_hTrace, "=========== Inter Layer Constrained Tile Sets SEI message ===========\n");
+    break;
+#endif
   case SEI::SCALABLE_NESTING:
     fprintf( g_hTrace, "=========== Scalable Nesting SEI message ===========\n");
@@ -266,4 +271,10 @@
       xParseSEISOPDescription((SEISOPDescription&) *sei, payloadSize);
       break;
+#if N0383_IL_CONSTRAINED_TILE_SETS_SEI
+    case SEI::INTER_LAYER_CONSTRAINED_TILE_SETS:
+      sei = new SEIInterLayerConstrainedTileSets;
+      xParseSEIInterLayerConstrainedTileSets((SEIInterLayerConstrainedTileSets&) *sei, payloadSize);
+      break;
+#endif
     case SEI::SCALABLE_NESTING:
       sei = new SEIScalableNesting;
@@ -775,4 +786,48 @@
 }
 
+#if N0383_IL_CONSTRAINED_TILE_SETS_SEI
+Void SEIReader::xParseSEIInterLayerConstrainedTileSets (SEIInterLayerConstrainedTileSets &sei, UInt payloadSize)
+{
+  UInt uiCode;
+
+  READ_FLAG( uiCode, "il_all_tiles_exact_sample_value_match_flag"   ); sei.m_ilAllTilesExactSampleValueMatchFlag = uiCode;
+  READ_FLAG( uiCode, "il_one_tile_per_tile_set_flag"                ); sei.m_ilOneTilePerTileSetFlag = uiCode;
+  if( !sei.m_ilOneTilePerTileSetFlag )
+  {
+    READ_UVLC( uiCode, "il_num_sets_in_message_minus1"                ); sei.m_ilNumSetsInMessageMinus1 = uiCode;
+    if( sei.m_ilNumSetsInMessageMinus1 )
+    {
+      READ_FLAG( uiCode, "skipped_tile_set_present_flag"                ); sei.m_skippedTileSetPresentFlag = uiCode;
+    }
+    else
+    {
+      sei.m_skippedTileSetPresentFlag = false;
+    }
+    UInt numSignificantSets = sei.m_ilNumSetsInMessageMinus1 + (sei.m_skippedTileSetPresentFlag ? 1 : 0) + 1;
+    for( UInt i = 0; i <= numSignificantSets; i++ )
+    {
+      READ_UVLC( uiCode, "ilcts_id"                                     ); sei.m_ilctsId[i] = uiCode;
+      READ_UVLC( uiCode, "il_num_tile_rects_in_set_minus1"              ) ;sei.m_ilNumTileRectsInSetMinus1[i] = uiCode;
+      for( UInt j = 0; j <= sei.m_ilNumTileRectsInSetMinus1[i]; j++ )
+      {
+        READ_UVLC( uiCode, "il_top_left_tile_index"                       ); sei.m_ilTopLeftTileIndex[i][j] = uiCode;
+        READ_UVLC( uiCode, "il_bottom_right_tile_index"                   ); sei.m_ilBottomRightTileIndex[i][j] = uiCode;
+      }
+      READ_CODE( 2, uiCode, "ilc_idc"                                   ); sei.m_ilcIdc[i] = uiCode;
+      if( sei.m_ilAllTilesExactSampleValueMatchFlag )
+      {
+        READ_FLAG( uiCode, "il_exact_sample_value_match_flag"             ); sei.m_ilExactSampleValueMatchFlag[i] = uiCode;
+      }
+    }
+  }
+  else
+  {
+    READ_CODE( 2, uiCode, "all_tiles_ilc_idc"                         ); sei.m_allTilesIlcIdc = uiCode;
+  }
+
+  xParseByteAlign();
+}
+#endif
+
 #if M0043_LAYERS_PRESENT_SEI
 Void SEIReader::xParseSEIScalableNesting(SEIScalableNesting& sei, const NalUnitType nalUnitType, UInt payloadSize, TComVPS *vps, TComSPS *sps)
Index: /branches/SHM-3.1-dev/source/Lib/TLibDecoder/SEIread.h
===================================================================
--- /branches/SHM-3.1-dev/source/Lib/TLibDecoder/SEIread.h	(revision 434)
+++ /branches/SHM-3.1-dev/source/Lib/TLibDecoder/SEIread.h	(revision 435)
@@ -80,4 +80,7 @@
   Void xParseSEIToneMappingInfo       (SEIToneMappingInfo& sei, UInt payloadSize);
   Void xParseSEISOPDescription        (SEISOPDescription &sei, UInt payloadSize);
+#if N0383_IL_CONSTRAINED_TILE_SETS_SEI
+  Void xParseSEIInterLayerConstrainedTileSets (SEIInterLayerConstrainedTileSets &sei, UInt payloadSize);
+#endif
 #if M0043_LAYERS_PRESENT_SEI
   Void xParseSEILayersPresent         (SEILayersPresent &sei, UInt payloadSize, TComVPS *vps);
Index: /branches/SHM-3.1-dev/source/Lib/TLibEncoder/SEIwrite.cpp
===================================================================
--- /branches/SHM-3.1-dev/source/Lib/TLibEncoder/SEIwrite.cpp	(revision 434)
+++ /branches/SHM-3.1-dev/source/Lib/TLibEncoder/SEIwrite.cpp	(revision 435)
@@ -95,4 +95,9 @@
     fprintf( g_hTrace, "=========== SOP Description SEI message ===========\n");
     break;
+#if N0383_IL_CONSTRAINED_TILE_SETS_SEI
+  case SEI::INTER_LAYER_CONSTRAINED_TILE_SETS:
+    fprintf( g_hTrace, "=========== Inter Layer Constrained Tile Sets SEI message ===========\n");
+    break;
+#endif
   case SEI::SCALABLE_NESTING:
     fprintf( g_hTrace, "=========== Scalable Nesting SEI message ===========\n");
@@ -153,4 +158,9 @@
     xWriteSEISOPDescription(*static_cast<const SEISOPDescription*>(&sei));
     break;
+#if N0383_IL_CONSTRAINED_TILE_SETS_SEI
+  case SEI::INTER_LAYER_CONSTRAINED_TILE_SETS:
+    xWriteSEIInterLayerConstrainedTileSets(*static_cast<const SEIInterLayerConstrainedTileSets*>(&sei));
+    break;
+#endif
   case SEI::SCALABLE_NESTING:
     xWriteSEIScalableNesting(bs, *static_cast<const SEIScalableNesting*>(&sei), sps);
@@ -559,4 +569,42 @@
 }
 
+#if N0383_IL_CONSTRAINED_TILE_SETS_SEI
+Void SEIWriter::xWriteSEIInterLayerConstrainedTileSets(const SEIInterLayerConstrainedTileSets& sei)
+{
+  WRITE_FLAG( sei.m_ilAllTilesExactSampleValueMatchFlag,  "il_all_tiles_exact_sample_value_match_flag"   );
+  WRITE_FLAG( sei.m_ilOneTilePerTileSetFlag,              "il_one_tile_per_tile_set_flag"                );
+  if( !sei.m_ilOneTilePerTileSetFlag )
+  {
+    WRITE_UVLC( sei.m_ilNumSetsInMessageMinus1,             "il_num_sets_in_message_minus1"                );
+    if( sei.m_ilNumSetsInMessageMinus1 )
+    {
+      WRITE_FLAG( sei.m_skippedTileSetPresentFlag,            "skipped_tile_set_present_flag"                );
+    }
+    UInt numSignificantSets = sei.m_ilNumSetsInMessageMinus1 + (sei.m_skippedTileSetPresentFlag ? 1 : 0) + 1;
+    for( UInt i = 0; i <= numSignificantSets; i++ )
+    {
+      WRITE_UVLC( sei.m_ilctsId[i],                           "ilcts_id"                                     );
+      WRITE_UVLC( sei.m_ilNumTileRectsInSetMinus1[i],         "il_num_tile_rects_in_set_minus1"              );
+      for( UInt j = 0; j <= sei.m_ilNumTileRectsInSetMinus1[i]; j++ )
+      {
+        WRITE_UVLC( sei.m_ilTopLeftTileIndex[i][j],             "il_top_left_tile_index"                       );
+        WRITE_UVLC( sei.m_ilBottomRightTileIndex[i][j],         "il_bottom_right_tile_index"                   );
+      }
+      WRITE_CODE( sei.m_ilcIdc[i], 2,                         "ilc_idc"                                      );
+      if( sei.m_ilAllTilesExactSampleValueMatchFlag )
+      {
+        WRITE_FLAG( sei.m_ilExactSampleValueMatchFlag[i],        "il_exact_sample_value_match_flag"            );
+      }
+    }
+  }
+  else
+  {
+    WRITE_CODE( sei.m_allTilesIlcIdc, 2,                    "all_tiles_ilc_idc"                          );
+  }
+
+  xWriteByteAlign();
+}
+#endif
+
 Void SEIWriter::xWriteSEIScalableNesting(TComBitIf& bs, const SEIScalableNesting& sei, TComSPS *sps)
 {
Index: /branches/SHM-3.1-dev/source/Lib/TLibEncoder/SEIwrite.h
===================================================================
--- /branches/SHM-3.1-dev/source/Lib/TLibEncoder/SEIwrite.h	(revision 434)
+++ /branches/SHM-3.1-dev/source/Lib/TLibEncoder/SEIwrite.h	(revision 435)
@@ -68,4 +68,7 @@
 #endif
   Void xWriteSEISOPDescription(const SEISOPDescription& sei);
+#if N0383_IL_CONSTRAINED_TILE_SETS_SEI
+  Void xWriteSEIInterLayerConstrainedTileSets(const SEIInterLayerConstrainedTileSets& sei);
+#endif
   Void xWriteSEIScalableNesting(TComBitIf& bs, const SEIScalableNesting& sei, TComSPS *sps);
   Void xWriteByteAlign();
Index: /branches/SHM-3.1-dev/source/Lib/TLibEncoder/TEncCfg.h
===================================================================
--- /branches/SHM-3.1-dev/source/Lib/TLibEncoder/TEncCfg.h	(revision 434)
+++ /branches/SHM-3.1-dev/source/Lib/TLibEncoder/TEncCfg.h	(revision 435)
@@ -318,4 +318,12 @@
   Int       m_SOPDescriptionSEIEnabled;
   Int       m_scalableNestingSEIEnabled;
+#if N0383_IL_CONSTRAINED_TILE_SETS_SEI
+  Bool      m_interLayerConstrainedTileSetsSEIEnabled;
+  UInt      m_ilNumSetsInMessage;
+  Bool      m_skippedTileSetPresentFlag;
+  UInt      m_topLeftTileIndex[1024];
+  UInt      m_bottomRightTileIndex[1024];
+  UInt      m_ilcIdc[1024];
+#endif
   //====== Weighted Prediction ========
   Bool      m_useWeightedPred;       //< Use of Weighting Prediction (P_SLICE)
@@ -757,4 +765,36 @@
   Void  setScalableNestingSEIEnabled(Int b)                { m_scalableNestingSEIEnabled = b; }
   Int   getScalableNestingSEIEnabled()                     { return m_scalableNestingSEIEnabled; }
+#if N0383_IL_CONSTRAINED_TILE_SETS_SEI
+  Void  setInterLayerConstrainedTileSetsSEIEnabled(Bool b) { m_interLayerConstrainedTileSetsSEIEnabled = b; }
+  Bool  getInterLayerConstrainedTileSetsSEIEnabled()       { return m_interLayerConstrainedTileSetsSEIEnabled; }
+  Void  setIlNumSetsInMessage(UInt b)                      { m_ilNumSetsInMessage = b; }
+  Int   getIlNumSetsInMessage()                            { return m_ilNumSetsInMessage; }
+  Void  setSkippedTileSetPresentFlag(Bool b)               { m_skippedTileSetPresentFlag = b; }
+  Bool  getSkippedTileSetPresentFlag()                     { return m_skippedTileSetPresentFlag; }
+  Void  setTopLeftTileIndex(UInt *b)
+  {
+    for (UInt i = 0; i < m_ilNumSetsInMessage; i++)
+    {
+      m_topLeftTileIndex[i] = b[i];
+    }
+  }
+  UInt  getTopLeftTileIndex(UInt b)                        { return m_topLeftTileIndex[b]; }
+  Void  setBottomRightTileIndex(UInt *b)
+  {
+    for (UInt i = 0; i < m_ilNumSetsInMessage; i++)
+    {
+      m_bottomRightTileIndex[i] = b[i];
+    }
+  }
+  UInt  getBottomRightTileIndex(UInt b)                    { return m_bottomRightTileIndex[b]; }
+  Void  setIlcIdc(UInt *b)
+  {
+    for (UInt i = 0; i < m_ilNumSetsInMessage; i++)
+    {
+      m_ilcIdc[i] = b[i];
+    }
+  }
+  UInt  getIlcIdc(UInt b)                                  { return m_ilcIdc[b]; }
+#endif
   Void      setUseWP               ( Bool b )    { m_useWeightedPred   = b;    }
   Void      setWPBiPred            ( Bool b )    { m_useWeightedBiPred = b;    }
Index: /branches/SHM-3.1-dev/source/Lib/TLibEncoder/TEncGOP.cpp
===================================================================
--- /branches/SHM-3.1-dev/source/Lib/TLibEncoder/TEncGOP.cpp	(revision 434)
+++ /branches/SHM-3.1-dev/source/Lib/TLibEncoder/TEncGOP.cpp	(revision 435)
@@ -307,4 +307,43 @@
 }
 
+#if N0383_IL_CONSTRAINED_TILE_SETS_SEI
+SEIInterLayerConstrainedTileSets* TEncGOP::xCreateSEIInterLayerConstrainedTileSets()
+{
+  SEIInterLayerConstrainedTileSets *seiInterLayerConstrainedTileSets = new SEIInterLayerConstrainedTileSets();
+  seiInterLayerConstrainedTileSets->m_ilAllTilesExactSampleValueMatchFlag = false;
+  seiInterLayerConstrainedTileSets->m_ilOneTilePerTileSetFlag = false;
+  if (!seiInterLayerConstrainedTileSets->m_ilOneTilePerTileSetFlag)
+  {
+    seiInterLayerConstrainedTileSets->m_ilNumSetsInMessageMinus1 = m_pcCfg->getIlNumSetsInMessage() - 1;
+    if (seiInterLayerConstrainedTileSets->m_ilNumSetsInMessageMinus1)
+    {
+      seiInterLayerConstrainedTileSets->m_skippedTileSetPresentFlag = m_pcCfg->getSkippedTileSetPresentFlag();
+    }
+    else
+    {
+      seiInterLayerConstrainedTileSets->m_skippedTileSetPresentFlag = false;
+    }
+    UInt numSignificantSets = seiInterLayerConstrainedTileSets->m_ilNumSetsInMessageMinus1 - (seiInterLayerConstrainedTileSets->m_skippedTileSetPresentFlag ? 1 : 0) + 1;
+    for (UInt i = 0; i < numSignificantSets; i++)
+    {
+      seiInterLayerConstrainedTileSets->m_ilctsId[i] = i;
+      seiInterLayerConstrainedTileSets->m_ilNumTileRectsInSetMinus1[i] = 0;
+      for( UInt j = 0; j <= seiInterLayerConstrainedTileSets->m_ilNumTileRectsInSetMinus1[i]; j++)
+      {
+        seiInterLayerConstrainedTileSets->m_ilTopLeftTileIndex[i][j]     = m_pcCfg->getTopLeftTileIndex(i);
+        seiInterLayerConstrainedTileSets->m_ilBottomRightTileIndex[i][j] = m_pcCfg->getBottomRightTileIndex(i);
+      }
+      seiInterLayerConstrainedTileSets->m_ilcIdc[i] = m_pcCfg->getIlcIdc(i);
+      if (seiInterLayerConstrainedTileSets->m_ilAllTilesExactSampleValueMatchFlag)
+      {
+        seiInterLayerConstrainedTileSets->m_ilExactSampleValueMatchFlag[i] = false;
+      }
+    }
+  }
+
+  return seiInterLayerConstrainedTileSets;
+}
+#endif
+
 Void TEncGOP::xCreateLeadingSEIMessages (/*SEIMessages seiMessages,*/ AccessUnit &accessUnit, TComSPS *sps)
 {
@@ -369,4 +408,17 @@
     delete sei;
   }
+#if N0383_IL_CONSTRAINED_TILE_SETS_SEI
+  if(m_pcCfg->getInterLayerConstrainedTileSetsSEIEnabled())
+  {
+    SEIInterLayerConstrainedTileSets *sei = xCreateSEIInterLayerConstrainedTileSets ();
+
+    nalu = NALUnit(NAL_UNIT_PREFIX_SEI, 0, m_pcCfg->getNumLayer()-1); // For highest layer
+    m_pcEntropyCoder->setBitstream(&nalu.m_Bitstream);
+    m_seiWriter.writeSEImessage(nalu.m_Bitstream, *sei, sps); 
+    writeRBSPTrailingBits(nalu.m_Bitstream);
+    accessUnit.push_back(new NALUnitEBSP(nalu));
+    delete sei;
+  }
+#endif
 }
 
@@ -1472,4 +1524,11 @@
     pcPic->getPicSym()->xInitTiles();
 
+#if N0383_IL_CONSTRAINED_TILE_SETS_SEI
+    if (m_pcCfg->getInterLayerConstrainedTileSetsSEIEnabled())
+    {
+      xBuildTileSetsMap(pcPic->getPicSym());
+    }
+#endif
+
     // Allocate some coders, now we know how many tiles there are.
     Int iNumSubstreams = pcSlice->getPPS()->getNumSubstreams();
@@ -3448,4 +3507,46 @@
 }
 
+#if N0383_IL_CONSTRAINED_TILE_SETS_SEI
+Void TEncGOP::xBuildTileSetsMap(TComPicSym* picSym)
+{
+  Int numCUs = picSym->getFrameWidthInCU() * picSym->getFrameHeightInCU();
+
+  for (Int i = 0; i < numCUs; i++)
+  {
+    picSym->setTileSetIdxMap(i, -1, 0, false);
+  }
+
+  for (Int i = 0; i < m_pcCfg->getIlNumSetsInMessage(); i++)
+  {
+    TComTile* topLeftTile     = picSym->getTComTile(m_pcCfg->getTopLeftTileIndex(i));
+    TComTile* bottomRightTile = picSym->getTComTile(m_pcCfg->getBottomRightTileIndex(i));
+    Int tileSetLeftEdgePosInCU = topLeftTile->getRightEdgePosInCU() - topLeftTile->getTileWidth() + 1;
+    Int tileSetRightEdgePosInCU = bottomRightTile->getRightEdgePosInCU();
+    Int tileSetTopEdgePosInCU = topLeftTile->getBottomEdgePosInCU() - topLeftTile->getTileHeight() + 1;
+    Int tileSetBottomEdgePosInCU = bottomRightTile->getBottomEdgePosInCU();
+    assert(tileSetLeftEdgePosInCU < tileSetRightEdgePosInCU && tileSetTopEdgePosInCU < tileSetBottomEdgePosInCU);
+    for (Int j = tileSetTopEdgePosInCU; j <= tileSetBottomEdgePosInCU; j++)
+    {
+      for (Int k = tileSetLeftEdgePosInCU; k <= tileSetRightEdgePosInCU; k++)
+      {
+        picSym->setTileSetIdxMap(j * picSym->getFrameWidthInCU() + k, i, m_pcCfg->getIlcIdc(i), false);
+      }
+    }
+  }
+  
+  if (m_pcCfg->getSkippedTileSetPresentFlag())
+  {
+    Int skippedTileSetIdx = m_pcCfg->getIlNumSetsInMessage();
+    for (Int i = 0; i < numCUs; i++)
+    {
+      if (picSym->getTileSetIdxMap(i) < 0)
+      {
+        picSym->setTileSetIdxMap(i, skippedTileSetIdx, 0, true);
+      }
+    }
+  }
+}
+#endif
+
 Void TEncGOP::dblMetric( TComPic* pcPic, UInt uiNumSlices )
 {
Index: /branches/SHM-3.1-dev/source/Lib/TLibEncoder/TEncGOP.h
===================================================================
--- /branches/SHM-3.1-dev/source/Lib/TLibEncoder/TEncGOP.h	(revision 434)
+++ /branches/SHM-3.1-dev/source/Lib/TLibEncoder/TEncGOP.h	(revision 435)
@@ -189,4 +189,8 @@
   SEIToneMappingInfo*     xCreateSEIToneMappingInfo();
 
+#if N0383_IL_CONSTRAINED_TILE_SETS_SEI
+  SEIInterLayerConstrainedTileSets* xCreateSEIInterLayerConstrainedTileSets();
+#endif
+
   Void xCreateLeadingSEIMessages (/*SEIMessages seiMessages,*/ AccessUnit &accessUnit, TComSPS *sps);
   Int xGetFirstSeiLocation (AccessUnit &accessUnit);
@@ -202,4 +206,7 @@
     m_nestedPictureTimingSEIPresentInAU      = false;
   }
+#if N0383_IL_CONSTRAINED_TILE_SETS_SEI
+  Void xBuildTileSetsMap(TComPicSym* picSym);
+#endif
   Void dblMetric( TComPic* pcPic, UInt uiNumSlices );
 #if M0457_COL_PICTURE_SIGNALING && !REMOVE_COL_PICTURE_SIGNALING
Index: /branches/SHM-3.1-dev/source/Lib/TLibEncoder/TEncSearch.cpp
===================================================================
--- /branches/SHM-3.1-dev/source/Lib/TLibEncoder/TEncSearch.cpp	(revision 434)
+++ /branches/SHM-3.1-dev/source/Lib/TLibEncoder/TEncSearch.cpp	(revision 435)
@@ -3221,4 +3221,38 @@
   Int numValidMergeCand = 0 ;
 
+#if N0383_IL_CONSTRAINED_TILE_SETS_SEI
+  Bool disableILP = false;
+  if (pcCU->getPic()->getLayerId() > 0 && m_pcEncCfg->getInterLayerConstrainedTileSetsSEIEnabled() && pcCU->getPic()->getPicSym()->getTileIdxMap(pcCU->getAddr()) >= 0)
+  {
+    if (pcCU->getPic()->getPicSym()->getTileSetType(pcCU->getAddr()) == 2)
+    {
+      disableILP = true;
+    }
+    if (pcCU->getPic()->getPicSym()->getTileSetType(pcCU->getAddr()) == 1)
+    {
+      Int currCUaddr = pcCU->getAddr();
+      Int frameWitdhInCU  = pcCU->getPic()->getPicSym()->getFrameWidthInCU();
+      Int frameHeightInCU = pcCU->getPic()->getPicSym()->getFrameHeightInCU();
+      Bool leftCUExists   = (currCUaddr % frameWitdhInCU) > 0;
+      Bool aboveCUExists  = (currCUaddr / frameWitdhInCU) > 0;
+      Bool rightCUExists  = (currCUaddr % frameWitdhInCU) < (frameWitdhInCU - 1);
+      Bool belowCUExists  = (currCUaddr / frameWitdhInCU) < (frameHeightInCU - 1);
+      Int currTileSetIdx  = pcCU->getPic()->getPicSym()->getTileIdxMap(currCUaddr);
+      // Check if CU is at tile set boundary
+      if ( (leftCUExists && pcCU->getPic()->getPicSym()->getTileIdxMap(currCUaddr-1) != currTileSetIdx) ||
+           (leftCUExists && aboveCUExists && pcCU->getPic()->getPicSym()->getTileIdxMap(currCUaddr-frameWitdhInCU-1) != currTileSetIdx) ||
+           (aboveCUExists && pcCU->getPic()->getPicSym()->getTileIdxMap(currCUaddr-frameWitdhInCU) != currTileSetIdx) ||
+           (aboveCUExists && rightCUExists && pcCU->getPic()->getPicSym()->getTileIdxMap(currCUaddr-frameWitdhInCU+1) != currTileSetIdx) ||
+           (rightCUExists && pcCU->getPic()->getPicSym()->getTileIdxMap(currCUaddr+1) != currTileSetIdx) ||
+           (rightCUExists && belowCUExists && pcCU->getPic()->getPicSym()->getTileIdxMap(currCUaddr+frameWitdhInCU+1) != currTileSetIdx) ||
+           (belowCUExists && pcCU->getPic()->getPicSym()->getTileIdxMap(currCUaddr+frameWitdhInCU) != currTileSetIdx) ||
+           (belowCUExists && leftCUExists && pcCU->getPic()->getPicSym()->getTileIdxMap(currCUaddr+frameWitdhInCU-1) != currTileSetIdx) )
+      {
+        disableILP = true;  // Disable ILP in tile set boundary CU
+      }
+    }
+  }
+#endif
+
   for ( Int iPartIdx = 0; iPartIdx < iNumPart; iPartIdx++ )
   {
@@ -3270,4 +3304,10 @@
       for ( Int iRefIdxTemp = 0; iRefIdxTemp < pcCU->getSlice()->getNumRefIdx(eRefPicList); iRefIdxTemp++ )
       {
+#if N0383_IL_CONSTRAINED_TILE_SETS_SEI
+        if (pcCU->getSlice()->getRefPic( eRefPicList, iRefIdxTemp )->isILR(pcCU->getLayerId()) && disableILP)
+        {
+          continue;
+        }
+#endif
 #if (ENCODER_FAST_MODE)
         TComPic* pcPic    = pcCU->getSlice()->getRefPic( eRefPicList, iRefIdxTemp );
@@ -3488,4 +3528,10 @@
           testIter = false;  //the fixed part is ILR, skip this iteration       
         }
+#if N0383_IL_CONSTRAINED_TILE_SETS_SEI
+        if (pcPic->isILR(pcCU->getLayerId()) && disableILP)
+        {
+          testIter = false;
+        }
+#endif
         if(testIter)
         {
@@ -3503,4 +3549,10 @@
             testRefIdx = false;  //the refined part is ILR, skip this reference pic           
           }
+#if N0383_IL_CONSTRAINED_TILE_SETS_SEI
+          if (pcPic->isILR(pcCU->getLayerId()) && disableILP)
+          {
+            testRefIdx = false;
+          }
+#endif
           if(testRefIdx)
           {
