Index: /branches/SHM-6-dev/cfg/layers.cfg
===================================================================
--- /branches/SHM-6-dev/cfg/layers.cfg	(revision 777)
+++ /branches/SHM-6-dev/cfg/layers.cfg	(revision 778)
@@ -41,2 +41,9 @@
 InitialQP1                    : 0           # Rate control: initial QP for layer 1
 RCForceIntraQP1               : 0           # Rate control: force intra QP to be equal to initial QP for layer 1
+
+
+NumLayerSets                  : 1
+NumLayerInIdList0             : 2
+LayerSetLayerIdList0          : 0 1
+
+NumAddLayerSets               : 0
Index: /branches/SHM-6-dev/source/App/TAppEncoder/TAppEncCfg.cpp
===================================================================
--- /branches/SHM-6-dev/source/App/TAppEncoder/TAppEncCfg.cpp	(revision 777)
+++ /branches/SHM-6-dev/source/App/TAppEncoder/TAppEncCfg.cpp	(revision 778)
@@ -492,4 +492,19 @@
 #endif
   }
+#if Q0078_ADD_LAYER_SETS
+  Int* cfg_numLayerInIdList[MAX_VPS_LAYER_SETS_PLUS1];
+  string cfg_layerSetLayerIdList[MAX_VPS_LAYER_SETS_PLUS1];
+  string* cfg_layerSetLayerIdListPtr[MAX_VPS_LAYER_SETS_PLUS1];
+  Int* cfg_numHighestLayerIdx[MAX_VPS_LAYER_SETS_PLUS1];
+  string cfg_highestLayerIdx[MAX_VPS_LAYER_SETS_PLUS1];
+  string* cfg_highestLayerIdxPtr[MAX_VPS_LAYER_SETS_PLUS1];
+  for (UInt i = 0; i < MAX_VPS_LAYER_SETS_PLUS1; i++)
+  {
+    cfg_numLayerInIdList[i] = &m_numLayerInIdList[i];
+    cfg_layerSetLayerIdListPtr[i] = &cfg_layerSetLayerIdList[i];
+    cfg_highestLayerIdxPtr[i] = &cfg_highestLayerIdx[i];
+    cfg_numHighestLayerIdx[i] = &m_numHighestLayerIdx[i];
+  }
+#endif
 #if AVC_BASE
   string  cfg_BLInputFile;
@@ -546,4 +561,12 @@
 #endif
   ("NumLayers",               m_numLayers, 1, "Number of layers to code")
+#if Q0078_ADD_LAYER_SETS
+  ("NumLayerSets",            m_numLayerSets, 0, "Number of layer sets")
+  ("NumLayerInIdList%d",      cfg_numLayerInIdList, 0, MAX_VPS_LAYER_ID_PLUS1, "Number of layers in the set")
+  ("LayerSetLayerIdList%d",   cfg_layerSetLayerIdListPtr, string(""), MAX_VPS_LAYER_ID_PLUS1, "Layer IDs for the set")
+  ("NumAddLayerSets",         m_numAddLayerSets, 0, "Number of additional layer sets")
+  ("NumHighestLayerIdx%d",    cfg_numHighestLayerIdx, 0, MAX_VPS_LAYER_ID_PLUS1, "Number of highest layer idx")
+  ("HighestLayerIdx%d",       cfg_highestLayerIdxPtr, string(""), MAX_VPS_LAYER_ID_PLUS1, "Highest layer idx for an additional layer set")
+#endif
 #if AUXILIARY_PICTURES
   ("InputChromaFormat%d",     cfg_tmpInputChromaFormat,  420, MAX_LAYERS, "InputChromaFormatIDC for layer %d")
@@ -1321,4 +1344,46 @@
   }
 #endif
+#if Q0078_ADD_LAYER_SETS
+  for (Int layerSet = 0; layerSet < m_numLayerSets; layerSet++)
+  {
+    if (m_numLayerInIdList[layerSet] > 0)
+    {
+      Char* layerSetLayerIdListDup = cfg_layerSetLayerIdList[layerSet].empty() ? NULL : strdup(cfg_layerSetLayerIdList[layerSet].c_str());
+      Int  i = 0;
+      char *layerId = strtok(layerSetLayerIdListDup, " ,-");
+      while (layerId != NULL)
+      {
+        if (i >= m_numLayerInIdList[layerSet])
+        {
+          printf("NumLayerInIdList%d: The number of layers in the set is larger than the allowed number of layers.\n", layerSet);
+          exit(EXIT_FAILURE);
+        }
+        m_layerSetLayerIdList[layerSet][i] = atoi(layerId);
+        layerId = strtok(NULL, " ,-");
+        i++;
+      }
+    }
+  }
+  for (Int addLayerSet = 0; addLayerSet < m_numAddLayerSets; addLayerSet++)
+  {
+    if (m_numHighestLayerIdx[addLayerSet] > 0)
+    {
+      Char* highestLayrIdxListDup = cfg_highestLayerIdx[addLayerSet].empty() ? NULL : strdup(cfg_highestLayerIdx[addLayerSet].c_str());
+      Int  i = 0;
+      char *layerIdx = strtok(highestLayrIdxListDup, " ,-");
+      while (layerIdx != NULL)
+      {
+        if (i >= m_numLayerInIdList[addLayerSet])
+        {
+          printf("NumLayerInIdList%d: The number of layer idx's in the highest layer idx list is larger than the allowed number of idx's.\n", addLayerSet);
+          exit(EXIT_FAILURE);
+        }
+        m_highestLayerIdx[addLayerSet][i] = atoi(layerIdx);
+        layerIdx = strtok(NULL, " ,-");
+        i++;
+      }
+    }
+  }
+#endif
 #endif //SVC_EXTENSION
   m_scalingListFile = cfg_ScalingListFile.empty() ? NULL : strdup(cfg_ScalingListFile.c_str());
Index: /branches/SHM-6-dev/source/App/TAppEncoder/TAppEncCfg.h
===================================================================
--- /branches/SHM-6-dev/source/App/TAppEncoder/TAppEncCfg.h	(revision 777)
+++ /branches/SHM-6-dev/source/App/TAppEncoder/TAppEncCfg.h	(revision 778)
@@ -74,4 +74,12 @@
 #endif
   Bool      m_maxTidRefPresentFlag; 
+#if Q0078_ADD_LAYER_SETS
+  Int       m_numLayerSets;
+  Int       m_numLayerInIdList[MAX_VPS_LAYER_SETS_PLUS1];
+  Int       m_layerSetLayerIdList[MAX_VPS_LAYER_SETS_PLUS1][MAX_VPS_LAYER_ID_PLUS1];
+  Int       m_numAddLayerSets;
+  Int       m_numHighestLayerIdx[MAX_VPS_LAYER_SETS_PLUS1];
+  Int       m_highestLayerIdx[MAX_VPS_LAYER_SETS_PLUS1][MAX_VPS_LAYER_ID_PLUS1];
+#endif
 #else
   Char*     m_pchInputFile;                                   ///< source file name
Index: /branches/SHM-6-dev/source/App/TAppEncoder/TAppEncTop.cpp
===================================================================
--- /branches/SHM-6-dev/source/App/TAppEncoder/TAppEncTop.cpp	(revision 777)
+++ /branches/SHM-6-dev/source/App/TAppEncoder/TAppEncTop.cpp	(revision 778)
@@ -632,4 +632,7 @@
     m_acTEncTop[layer].setCGSMaxYPartNumLog2( m_nCGSMaxYPartNumLog2 );
     m_acTEncTop[layer].setCGSLUTBit( m_nCGSLUTBit );
+#endif
+#if Q0078_ADD_LAYER_SETS
+    m_acTEncTop[layer].setNumAddLayerSets( m_numAddLayerSets );
 #endif
   }
@@ -1036,27 +1039,77 @@
   vps->setVpsExtensionFlag( m_numLayers > 1 ? true : false );
 
-  vps->setNumLayerSets(m_numLayers);
-  for(Int setId = 1; setId < vps->getNumLayerSets(); setId++)
-  {
-    for(Int layerId = 0; layerId <= vps->getMaxLayerId(); layerId++)
-    {
+#if Q0078_ADD_LAYER_SETS
+  if (m_numLayerSets > 0)
+  {
+    vps->setNumLayerSets(m_numLayerSets+1);
+    for (Int setId = 1; setId < vps->getNumLayerSets(); setId++)
+    {
+      for (Int layerId = 0; layerId <= vps->getMaxLayerId(); layerId++)
+      {
+        vps->setLayerIdIncludedFlag(false, setId, layerId);
+      }
+    }
+    for (Int setId = 1; setId < vps->getNumLayerSets(); setId++)
+    {
+      for (Int i = 0; i < m_numLayerInIdList[setId-1]; i++)
+      {
+        Int layerId = m_layerSetLayerIdList[setId-1][i];
+
 #if O0194_DIFFERENT_BITDEPTH_EL_BL
-      //4
-      g_bitDepthY = m_acLayerCfg[layerId].m_internalBitDepthY;
-      g_bitDepthC = m_acLayerCfg[layerId].m_internalBitDepthC;
-
-      g_uiPCMBitDepthLuma = m_bPCMInputBitDepthFlag ? m_acLayerCfg[layerId].m_inputBitDepthY : m_acLayerCfg[layerId].m_internalBitDepthY;
-      g_uiPCMBitDepthChroma = m_bPCMInputBitDepthFlag ? m_acLayerCfg[layerId].m_inputBitDepthC : m_acLayerCfg[layerId].m_internalBitDepthC;
-#endif
-      if( layerId <= setId )
-      {
+        //4
+        g_bitDepthY = m_acLayerCfg[layerId].m_internalBitDepthY;
+        g_bitDepthC = m_acLayerCfg[layerId].m_internalBitDepthC;
+
+        g_uiPCMBitDepthLuma = m_bPCMInputBitDepthFlag ? m_acLayerCfg[layerId].m_inputBitDepthY : m_acLayerCfg[layerId].m_internalBitDepthY;
+        g_uiPCMBitDepthChroma = m_bPCMInputBitDepthFlag ? m_acLayerCfg[layerId].m_inputBitDepthC : m_acLayerCfg[layerId].m_internalBitDepthC;
+#endif
+
         vps->setLayerIdIncludedFlag(true, setId, layerId);
       }
-      else
-      {
-        vps->setLayerIdIncludedFlag(false, setId, layerId);
-      }
-    }
-  }
+    }
+  }
+  else
+  {
+    // Default layer sets
+#endif
+    vps->setNumLayerSets(m_numLayers);
+    for (Int setId = 1; setId < vps->getNumLayerSets(); setId++)
+    {
+      for (Int layerId = 0; layerId <= vps->getMaxLayerId(); layerId++)
+      {
+#if O0194_DIFFERENT_BITDEPTH_EL_BL
+        //4
+        g_bitDepthY = m_acLayerCfg[layerId].m_internalBitDepthY;
+        g_bitDepthC = m_acLayerCfg[layerId].m_internalBitDepthC;
+
+        g_uiPCMBitDepthLuma = m_bPCMInputBitDepthFlag ? m_acLayerCfg[layerId].m_inputBitDepthY : m_acLayerCfg[layerId].m_internalBitDepthY;
+        g_uiPCMBitDepthChroma = m_bPCMInputBitDepthFlag ? m_acLayerCfg[layerId].m_inputBitDepthC : m_acLayerCfg[layerId].m_internalBitDepthC;
+#endif
+        if (layerId <= setId)
+        {
+          vps->setLayerIdIncludedFlag(true, setId, layerId);
+        }
+        else
+        {
+          vps->setLayerIdIncludedFlag(false, setId, layerId);
+        }
+      }
+    }
+#if Q0078_ADD_LAYER_SETS
+  }
+#endif
+#if Q0078_ADD_LAYER_SETS
+  vps->setNumAddLayerSets(m_numAddLayerSets);
+  if (m_numAddLayerSets > 0)
+  {
+    for (Int setId = 0; setId < m_numAddLayerSets; setId++)
+    {
+      for (Int j = 0; j < m_numHighestLayerIdx[setId]; j++)
+      {
+        vps->setHighestLayerIdxPlus1(setId, j + 1, m_highestLayerIdx[setId][j] + 1);
+      }
+    }
+  }
+#endif
 #if VPS_EXTN_MASK_AND_DIM_INFO
   UInt i = 0, dimIdLen = 0;
@@ -1347,4 +1400,8 @@
   }
 #endif
+#if Q0078_ADD_LAYER_SETS
+  vps->setPredictedLayerIds();
+  vps->setTreePartitionLayerIdList();
+#endif
 #endif
     vps->setMaxOneActiveRefLayerFlag(maxDirectRefLayers > 1 ? false : true);
@@ -1354,5 +1411,9 @@
       if( vps->getNumDirectRefLayers( vps->getLayerIdInNuh(i) ) == 0  )
       {
+#if Q0078_ADD_LAYER_SETS
+        vps->setPocLsbNotPresentFlag(i, true); // make independedent layers base-layer compliant
+#else
         vps->setPocLsbNotPresentFlag(i, false);
+#endif
       }
     }
Index: /branches/SHM-6-dev/source/App/utils/BLRewrite/BLRewrite.c
===================================================================
--- /branches/SHM-6-dev/source/App/utils/BLRewrite/BLRewrite.c	(revision 778)
+++ /branches/SHM-6-dev/source/App/utils/BLRewrite/BLRewrite.c	(revision 778)
@@ -0,0 +1,274 @@
+/* The copyright in this software is being made available under the BSD
+* License, included below. This software may be subject to other third party
+* and contributor rights, including patent rights, and no such rights are
+* granted under this license.
+*
+* Copyright (c) 2010-2014, ITU/ISO/IEC
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+*
+*  * Redistributions of source code must retain the above copyright notice,
+*    this list of conditions and the following disclaimer.
+*  * Redistributions in binary form must reproduce the above copyright notice,
+*    this list of conditions and the following disclaimer in the documentation
+*    and/or other materials provided with the distribution.
+*  * Neither the name of the ITU/ISO/IEC nor the names of its contributors may
+*    be used to endorse or promote products derived from this software without
+*    specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+* THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+
+
+enum NalUnitType
+{
+  NAL_UNIT_CODED_SLICE_TRAIL_N = 0,   // 0
+  NAL_UNIT_CODED_SLICE_TRAIL_R,   // 1
+
+  NAL_UNIT_CODED_SLICE_TSA_N,     // 2
+  NAL_UNIT_CODED_SLICE_TSA_R,       // 3
+
+  NAL_UNIT_CODED_SLICE_STSA_N,    // 4
+  NAL_UNIT_CODED_SLICE_STSA_R,    // 5
+
+  NAL_UNIT_CODED_SLICE_RADL_N,    // 6
+  NAL_UNIT_CODED_SLICE_RADL_R,      // 7
+
+  NAL_UNIT_CODED_SLICE_RASL_N,    // 8
+  NAL_UNIT_CODED_SLICE_RASL_R,      // 9
+
+  NAL_UNIT_RESERVED_VCL_N10,
+  NAL_UNIT_RESERVED_VCL_R11,
+  NAL_UNIT_RESERVED_VCL_N12,
+  NAL_UNIT_RESERVED_VCL_R13,
+  NAL_UNIT_RESERVED_VCL_N14,
+  NAL_UNIT_RESERVED_VCL_R15,
+
+  NAL_UNIT_CODED_SLICE_BLA_W_LP,    // 16
+  NAL_UNIT_CODED_SLICE_BLA_W_RADL,  // 17
+  NAL_UNIT_CODED_SLICE_BLA_N_LP,  // 18
+  NAL_UNIT_CODED_SLICE_IDR_W_RADL,  // 19
+  NAL_UNIT_CODED_SLICE_IDR_N_LP,  // 20
+  NAL_UNIT_CODED_SLICE_CRA,       // 21
+  NAL_UNIT_RESERVED_IRAP_VCL22,
+  NAL_UNIT_RESERVED_IRAP_VCL23,
+
+  NAL_UNIT_RESERVED_VCL24,
+  NAL_UNIT_RESERVED_VCL25,
+  NAL_UNIT_RESERVED_VCL26,
+  NAL_UNIT_RESERVED_VCL27,
+  NAL_UNIT_RESERVED_VCL28,
+  NAL_UNIT_RESERVED_VCL29,
+  NAL_UNIT_RESERVED_VCL30,
+  NAL_UNIT_RESERVED_VCL31,
+
+  NAL_UNIT_VPS,                   // 32
+  NAL_UNIT_SPS,                   // 33
+  NAL_UNIT_PPS,                   // 34
+  NAL_UNIT_ACCESS_UNIT_DELIMITER, // 35
+  NAL_UNIT_EOS,                   // 36
+  NAL_UNIT_EOB,                   // 37
+  NAL_UNIT_FILLER_DATA,           // 38
+  NAL_UNIT_PREFIX_SEI,              // 39
+  NAL_UNIT_SUFFIX_SEI,              // 40
+  NAL_UNIT_RESERVED_NVCL41,
+  NAL_UNIT_RESERVED_NVCL42,
+  NAL_UNIT_RESERVED_NVCL43,
+  NAL_UNIT_RESERVED_NVCL44,
+  NAL_UNIT_RESERVED_NVCL45,
+  NAL_UNIT_RESERVED_NVCL46,
+  NAL_UNIT_RESERVED_NVCL47,
+  NAL_UNIT_UNSPECIFIED_48,
+  NAL_UNIT_UNSPECIFIED_49,
+  NAL_UNIT_UNSPECIFIED_50,
+  NAL_UNIT_UNSPECIFIED_51,
+  NAL_UNIT_UNSPECIFIED_52,
+  NAL_UNIT_UNSPECIFIED_53,
+  NAL_UNIT_UNSPECIFIED_54,
+  NAL_UNIT_UNSPECIFIED_55,
+  NAL_UNIT_UNSPECIFIED_56,
+  NAL_UNIT_UNSPECIFIED_57,
+  NAL_UNIT_UNSPECIFIED_58,
+  NAL_UNIT_UNSPECIFIED_59,
+  NAL_UNIT_UNSPECIFIED_60,
+  NAL_UNIT_UNSPECIFIED_61,
+  NAL_UNIT_UNSPECIFIED_62,
+  NAL_UNIT_UNSPECIFIED_63,
+  NAL_UNIT_INVALID,
+};
+
+typedef struct NalUnitHeader_s
+{
+  int nalUnitType;
+  int nuhLayerId;
+  int nuhTemporalIdPlus1;
+} NalUnitHeader;
+
+
+int findStartCodePrefix(FILE *inFile, int *numStartCodeZeros)
+{
+  int numZeros = 0;
+  int currByte;
+  
+  while (1)
+  {
+    currByte = fgetc(inFile);
+    if (currByte == EOF)
+    {
+      return 0;
+    }
+
+    if (currByte == 0x01 && numZeros > 1)
+    {
+      *numStartCodeZeros = numZeros;
+      return 1;
+    }
+    else if (currByte == 0)
+    {
+      numZeros++;
+    }
+    else
+    {
+      numZeros = 0;
+    }
+  }
+}
+
+int parseNalUnitHeader(FILE *inFile, NalUnitHeader *nalu)
+{
+  int byte0, byte1;
+
+  byte0 = fgetc(inFile);
+  byte1 = fgetc(inFile);
+
+  if (byte0 == EOF || byte1 == EOF)
+  {
+    return 0;
+  }
+
+  nalu->nalUnitType = (byte0 >> 1) & 0x3f;
+  nalu->nuhLayerId  = (((byte0 << 8) | byte1) >> 3) & 0x3f;
+  nalu->nuhTemporalIdPlus1 = byte1 & 0x07;
+
+  return 1;
+}
+
+void writeStartCodePrefixAndNUH(FILE *outFile, int numStartCodeZeros, NalUnitHeader *nalu)
+{
+  int byte0, byte1;
+  int i;
+
+  /* Start code prefix */
+  if (numStartCodeZeros > 3)
+  {
+    numStartCodeZeros = 3;
+  }
+  for (i = 0; i < numStartCodeZeros; i++)
+  {
+    fputc(0, outFile);
+  }
+  fputc(0x01, outFile);
+
+  /* NAL unit header */
+  byte0 = ((nalu->nalUnitType << 6) | nalu->nuhLayerId) >> 5;
+  byte1 = ((nalu->nuhLayerId << 3) | nalu->nuhTemporalIdPlus1) & 0xff;
+  fputc(byte0, outFile);
+  fputc(byte1, outFile);
+}
+
+int main(int argc, char **argv)
+{
+  FILE *inFile;
+  FILE *outFile;
+  int assignedBaseLayerId;
+  NalUnitHeader nalu;
+  int numStartCodeZeros;
+  int isSpsPpsEosEob;
+
+  if (argc < 3)
+  {
+    printf("Usage: Splicer <infile> <outfile> <assigned base layer ID>\n", argv[0]);
+  }
+
+  inFile = fopen(argv[1], "rb");
+  if (inFile == NULL)
+  {
+    fprintf(stderr, "Cannot open input file %s\n", argv[1]);
+    exit(1);
+  }
+
+  outFile = fopen(argv[2], "wb");
+  if (outFile == NULL)
+  {
+    fprintf(stderr, "Cannot open output file %s\n", argv[2]);
+    exit(1);
+  }
+
+  assignedBaseLayerId = atoi(argv[3]);
+
+  while (1)
+  {
+    if (!findStartCodePrefix(inFile, &numStartCodeZeros))
+    {
+      break;
+    }
+    if (!parseNalUnitHeader(inFile, &nalu))
+    {
+      break;
+    }
+
+    printf("NAL unit type: %i,  NUH layer ID: %i,  NUH Temporal ID: %i\n", nalu.nalUnitType, nalu.nuhLayerId, nalu.nuhTemporalIdPlus1 - 1);
+
+    isSpsPpsEosEob = (nalu.nalUnitType == NAL_UNIT_SPS || nalu.nalUnitType == NAL_UNIT_PPS || nalu.nalUnitType == NAL_UNIT_EOS || nalu.nalUnitType == NAL_UNIT_EOB);
+
+    if ((isSpsPpsEosEob && nalu.nuhLayerId == 0) || (!isSpsPpsEosEob && nalu.nuhLayerId == assignedBaseLayerId))
+    {
+      /* Write current NAL unit to output bitstream */
+
+      long naluBytesStartPos;
+      long numNaluBytes;
+      long i;
+
+      nalu.nuhLayerId = 0;
+      writeStartCodePrefixAndNUH(outFile, numStartCodeZeros, &nalu);
+
+      naluBytesStartPos = ftell(inFile);
+      /* Find beginning of the next NAL unit to calculate length of the current unit */
+      if (findStartCodePrefix(inFile, &numStartCodeZeros))
+      {
+        numNaluBytes = ftell(inFile) - naluBytesStartPos - numStartCodeZeros - 1;
+      }
+      else
+      {
+        numNaluBytes = ftell(inFile) - naluBytesStartPos;
+      }
+      fseek(inFile, naluBytesStartPos, SEEK_SET);
+
+      for (i = 0; i < numNaluBytes; i++)
+      {
+        fputc(fgetc(inFile), outFile);
+      }
+    }
+  }
+
+  fclose(inFile);
+  fclose(outFile);
+
+
+  return 0;
+}
Index: /branches/SHM-6-dev/source/App/utils/BLRewrite/ReadMe.txt
===================================================================
--- /branches/SHM-6-dev/source/App/utils/BLRewrite/ReadMe.txt	(revision 778)
+++ /branches/SHM-6-dev/source/App/utils/BLRewrite/ReadMe.txt	(revision 778)
@@ -0,0 +1,17 @@
+
+This is a simple tool that extracts an independent non-base layer from a multi-layer bitstream, converts it to a base-layer bistream and writes it to a file. The tool is invoked as follows. 
+
+  BLRewrite <infile> <outfile> <layer ID of the extracted layer>
+
+The tool is based on the contribution JCTVC-Q0078 / JCTVC-R0042. Sub-bitstream extraction process done by the tool can be summarized as follows.
+
+- NAL units with nal_unit_type not equal to SPS_NUT, PPS_NUT, EOS_NUT and EOB_NUT and with nuh_layer_id not equal to the assignedBaseLayerId are removed from outBitstream.
+- NAL units with nal_unit_type equal to SPS_NUT, PPS_NUT, EOS_NUT or EOB_NUT with nuh_layer_id not equal to 0 are removed from outBitstream.
+- For each NAL unit, the following applies:
+   When nuh_layer_id is equal to assignedBaseLayerId, nuh_layer_id is set equal to 0.
+
+The resulting bitstream can be decoded with an HEVC/H.265 v1 compliant decoder as long as the extracted independent layer conform with v1 specification text. The tool removes VPS from the output bitstream so an HEVC/H.265 decoder should not expect it to be present.
+
+
+
+
Index: /branches/SHM-6-dev/source/Lib/TLibCommon/SEI.h
===================================================================
--- /branches/SHM-6-dev/source/Lib/TLibCommon/SEI.h	(revision 777)
+++ /branches/SHM-6-dev/source/Lib/TLibCommon/SEI.h	(revision 778)
@@ -37,4 +37,8 @@
 #include <cstring>
 
+#if Q0078_ADD_LAYER_SETS
+#include "TLibCommon/NAL.h"
+#endif
+
 //! \ingroup TLibCommon
 //! \{
@@ -94,4 +98,8 @@
 #if Q0074_SEI_COLOR_MAPPING
     COLOR_MAPPING_INFO                   = 143,
+#endif
+#if Q0078_ADD_LAYER_SETS
+    OUTPUT_LAYER_SET_NESTING             = 144,
+    VPS_REWRITING                        = 145,
 #endif
   };
@@ -606,3 +614,37 @@
 };
 
+#if Q0078_ADD_LAYER_SETS
+class SEIOutputLayerSetNesting : public SEI
+{
+public:
+  PayloadType payloadType() const { return OUTPUT_LAYER_SET_NESTING; }
+
+  SEIOutputLayerSetNesting() {}
+  virtual ~SEIOutputLayerSetNesting()
+  {
+    if (!m_callerOwnsSEIs)
+    {
+      deleteSEIs(m_nestedSEIs);
+    }
+  }
+
+  Bool m_olsFlag;
+  UInt m_numOlsIndicesMinus1;
+  UInt m_olsIdx[1024];
+  Bool  m_callerOwnsSEIs;
+  SEIMessages m_nestedSEIs;
+};
+
+class SEIVPSRewriting : public SEI
+{
+public:
+  PayloadType payloadType() const { return VPS_REWRITING; }
+
+  SEIVPSRewriting() {}
+  virtual ~SEIVPSRewriting() {}
+
+  NALUnit* nalu;
+};
+#endif
+
 //! \}
Index: /branches/SHM-6-dev/source/Lib/TLibCommon/TComRom.h
===================================================================
--- /branches/SHM-6-dev/source/Lib/TLibCommon/TComRom.h	(revision 777)
+++ /branches/SHM-6-dev/source/Lib/TLibCommon/TComRom.h	(revision 778)
@@ -159,5 +159,5 @@
 
 #ifndef ENC_DEC_TRACE
-# define ENC_DEC_TRACE 0
+# define ENC_DEC_TRACE 1
 #endif
 
Index: /branches/SHM-6-dev/source/Lib/TLibCommon/TComSlice.cpp
===================================================================
--- /branches/SHM-6-dev/source/Lib/TLibCommon/TComSlice.cpp	(revision 777)
+++ /branches/SHM-6-dev/source/Lib/TLibCommon/TComSlice.cpp	(revision 778)
@@ -2548,4 +2548,58 @@
     }
   }
+}
+#endif
+
+#if Q0078_ADD_LAYER_SETS
+Void TComVPS::setPredictedLayerIds()
+{
+  for (UInt i = 0; i < getMaxLayers() - 1; i++)
+  {
+    UInt iNuhLId = getLayerIdInNuh(i);
+    UInt predIdx = 0;
+    for (UInt j = iNuhLId + 1; j < 63; j++)
+    {
+      if (getRecursiveRefLayerFlag(j, iNuhLId))
+      {
+        setPredictedLayerId(i, predIdx, j);
+        predIdx++;
+      }
+    }
+    setNumPredictedLayers(iNuhLId, predIdx);
+  }
+}
+
+Void TComVPS::setTreePartitionLayerIdList()
+{
+  Bool countedLayerIdxFlag[MAX_NUM_LAYER_IDS];
+
+  for (UInt i = 0; i <= getMaxLayers() - 1; i++)
+  {
+    countedLayerIdxFlag[i] = false;
+  }
+
+  Int numIndependentLayers = 0;
+
+  for (UInt i = 0; i <= getMaxLayers() - 1; i++)
+  {
+    UInt iNuhLId = getLayerIdInNuh(i);
+    if (getNumDirectRefLayers(iNuhLId) == 0)
+    {
+      setTreePartitionLayerId(numIndependentLayers, 0, iNuhLId);
+      setNumLayersInTreePartition(numIndependentLayers, 1);
+      for (UInt j = 0; j < getNumPredictedLayers(iNuhLId); j++)
+      {
+        if (!countedLayerIdxFlag[getLayerIdInVps(iNuhLId)])
+        {
+          setTreePartitionLayerId(numIndependentLayers, getNumLayersInTreePartition(numIndependentLayers), getPredictedLayerId(iNuhLId, j));
+          setNumLayersInTreePartition(numIndependentLayers, getNumLayersInTreePartition(numIndependentLayers) + 1);
+          countedLayerIdxFlag[getLayerIdInVps(getPredictedLayerId(iNuhLId, j))] = true;
+        }
+      }
+      numIndependentLayers++;
+    }
+  }
+
+  setNumIndependentLayers(numIndependentLayers);
 }
 #endif
Index: /branches/SHM-6-dev/source/Lib/TLibCommon/TComSlice.h
===================================================================
--- /branches/SHM-6-dev/source/Lib/TLibCommon/TComSlice.h	(revision 777)
+++ /branches/SHM-6-dev/source/Lib/TLibCommon/TComSlice.h	(revision 778)
@@ -140,5 +140,8 @@
   
   Void  create  (Int numberOfEntries);
-  Void  destroy ();
+#if Q0078_ADD_LAYER_SETS
+  Void  copy(TComRPSList& a);
+#endif
+  Void  destroy();
 
 
@@ -495,5 +498,9 @@
   UInt        m_maxLayerId;
   UInt        m_numLayerSets;
+#if Q0078_ADD_LAYER_SETS
+  Bool        m_layerIdIncludedFlag[2*MAX_VPS_LAYER_SETS_PLUS1][MAX_VPS_LAYER_ID_PLUS1];
+#else
   Bool        m_layerIdIncludedFlag[MAX_VPS_LAYER_SETS_PLUS1][MAX_VPS_LAYER_ID_PLUS1];
+#endif
 #endif
 
@@ -661,4 +668,13 @@
   Bool       m_recursiveRefLayerFlag[MAX_NUM_LAYER_IDS][MAX_NUM_LAYER_IDS];  // flag to indicate if j-th layer is a direct or indirect reference layer of i-th layer
 #endif
+#if Q0078_ADD_LAYER_SETS
+  Int        m_numAddLayerSets;
+  UInt       m_highestLayerIdxPlus1[MAX_VPS_LAYER_SETS_PLUS1][MAX_NUM_LAYER_IDS];
+  UInt       m_predictedLayerId[MAX_NUM_LAYER_IDS][64];
+  UInt       m_numPredictedLayers[MAX_NUM_LAYER_IDS];
+  Int        m_numIndependentLayers;
+  Int        m_numLayersInTreePartition[MAX_NUM_LAYER_IDS];
+  UInt       m_treePartitionLayerIdList[MAX_NUM_LAYER_IDS][MAX_NUM_LAYER_IDS];
+#endif
 #if SPS_DPB_PARAMS
   Int        m_TolsIdx;
@@ -804,4 +820,22 @@
   Int     getNumRefLayers(Int currLayerId)                                       { return m_numberRefLayers[currLayerId];                  }
   Void    setNumRefLayers();
+#endif
+#if Q0078_ADD_LAYER_SETS
+  UInt    getNumAddLayerSets()                                                   { return m_numAddLayerSets; }
+  Void    setNumAddLayerSets(UInt x)                                             { m_numAddLayerSets = x; }
+  UInt    getHighestLayerIdxPlus1(UInt set, UInt idx)                             { return m_highestLayerIdxPlus1[set][idx]; }
+  Void    setHighestLayerIdxPlus1(UInt set, UInt idx, UInt layerIdx)              { m_highestLayerIdxPlus1[set][idx] = layerIdx; }
+  Void    setPredictedLayerIds();
+  UInt    getPredictedLayerId(UInt layerIdx, UInt predIdx)                       { return m_predictedLayerId[layerIdx][predIdx]; }
+  Void    setPredictedLayerId(UInt layerIdx, UInt predIdx, UInt x)               { m_predictedLayerId[layerIdx][predIdx] = x; }
+  UInt    getNumPredictedLayers(UInt layerId)                                    { return m_numPredictedLayers[layerId]; }
+  Void    setNumPredictedLayers(UInt layerId, UInt x)                            { m_numPredictedLayers[layerId] = x; }
+  Void    setTreePartitionLayerIdList();
+  Int     getNumIndependentLayers()                                              { return m_numIndependentLayers; }
+  Void    setNumIndependentLayers(Int x)                                         { m_numIndependentLayers = x; }
+  Int     getNumLayersInTreePartition(Int idx)                                   { return m_numLayersInTreePartition[idx]; }
+  Void    setNumLayersInTreePartition(Int idx, Int x)                            { m_numLayersInTreePartition[idx] = x; }
+  UInt    getTreePartitionLayerId(Int idx, Int layerIdx)                         { return m_treePartitionLayerIdList[idx][layerIdx]; }
+  Void    setTreePartitionLayerId(Int idx, Int layerIdx, UInt layerId)           { m_treePartitionLayerIdList[idx][layerIdx] = layerId; }
 #endif
 #if VPS_RENAME
@@ -2481,4 +2515,16 @@
   }
 
+#if Q0078_ADD_LAYER_SETS
+  Void removePS(Int psId)
+  {
+    assert(psId < m_maxId);
+    if (m_paramsetMap.find(psId) != m_paramsetMap.end())
+    {
+      m_paramsetMap.erase(psId);
+    }
+  }
+#endif
+
+
 private:
   std::map<Int,T *> m_paramsetMap;
@@ -2503,4 +2549,7 @@
   TComSPS* getSPS(Int spsId)  { return m_spsMap.getPS(spsId); };
   TComSPS* getFirstSPS()      { return m_spsMap.getFirstPS(); };
+#if Q0078_ADD_LAYER_SETS
+  Void     removeSPS(Int spsId) { m_spsMap.removePS(spsId); };
+#endif
 
   //! store picture parameter set and take ownership of it 
@@ -2509,4 +2558,7 @@
   TComPPS* getPPS(Int ppsId)  { return m_ppsMap.getPS(ppsId); };
   TComPPS* getFirstPPS()      { return m_ppsMap.getFirstPS(); };
+#if Q0078_ADD_LAYER_SETS
+  Void     removePPS(Int ppsId) { m_ppsMap.removePS(ppsId); };
+#endif
 
   //! activate a SPS from a active parameter sets SEI message
Index: /branches/SHM-6-dev/source/Lib/TLibCommon/TypeDef.h
===================================================================
--- /branches/SHM-6-dev/source/Lib/TLibCommon/TypeDef.h	(revision 777)
+++ /branches/SHM-6-dev/source/Lib/TLibCommon/TypeDef.h	(revision 778)
@@ -246,4 +246,6 @@
 #define Q0165_OUTPUT_LAYER_SET           1      ///< JCTVC-Q0165: add a constraint to disallow an empty output layer set
 #define Q0165_NUM_ADD_OUTPUT_LAYER_SETS  1      ///< JCTVC-Q0165: signal num_add_output_layer_set and default_target_output_layer_idc when vps_num_layer_sets_minus1 is greater than 0
+
+#define Q0078_ADD_LAYER_SETS             1      ///< JCTVC-Q0078: additional layer sets and layer set config
 
 #define VPS_DPB_SIZE_TABLE               1      ///< JCTVC-O0217: DPB operations: signaling DPB-related parameters
Index: /branches/SHM-6-dev/source/Lib/TLibDecoder/SEIread.cpp
===================================================================
--- /branches/SHM-6-dev/source/Lib/TLibDecoder/SEIread.cpp	(revision 777)
+++ /branches/SHM-6-dev/source/Lib/TLibDecoder/SEIread.cpp	(revision 778)
@@ -136,4 +136,12 @@
     break;
 #endif
+#if Q0078_ADD_LAYER_SETS
+  case SEI::OUTPUT_LAYER_SET_NESTING:
+    fprintf(g_hTrace, "=========== Output layer set nesting SEI message ===========\n");
+    break;
+  case SEI::VPS_REWRITING:
+    fprintf(g_hTrace, "=========== VPS rewriting SEI message ===========\n");
+    break;
+#endif
 #endif //SVC_EXTENSION
   default:
@@ -356,4 +364,18 @@
      sei = new SEIBspHrd;
      xParseSEIBspHrd((SEIBspHrd&) *sei, sps, *nestingSei);
+     break;
+#endif
+#if Q0078_ADD_LAYER_SETS
+   case SEI::OUTPUT_LAYER_SET_NESTING:
+     sei = new SEIOutputLayerSetNesting;
+#if LAYERS_NOT_PRESENT_SEI
+     xParseSEIOutputLayerSetNesting((SEIOutputLayerSetNesting&)*sei, nalUnitType, vps, sps);
+#else
+     xParseSEIOutputLayerSetNesting((SEIOutputLayerSetNesting&)*sei, nalUnitType, sps);
+#endif
+     break;
+   case SEI::VPS_REWRITING:
+     sei = new SEIVPSRewriting;
+     xParseSEIVPSRewriting((SEIVPSRewriting&)*sei);
      break;
 #endif
@@ -1393,4 +1415,57 @@
 #endif
 
+#if Q0078_ADD_LAYER_SETS
+
+#if LAYERS_NOT_PRESENT_SEI
+Void SEIReader::xParseSEIOutputLayerSetNesting(SEIOutputLayerSetNesting& sei, const NalUnitType nalUnitType, TComVPS *vps, TComSPS *sps)
+#else
+Void SEIReader::xParseSEIOutputLayerSetNesting(SEIOutputLayerSetNesting& sei, const NalUnitType nalUnitType, TComSPS *sps)
+#endif
+{
+  UInt uiCode;
+  SEIMessages seis;
+
+  READ_FLAG(uiCode, "ols_flag"); sei.m_olsFlag = uiCode;
+  READ_UVLC(uiCode, "num_ols_indices_minus1"); sei.m_numOlsIndicesMinus1 = uiCode;
+
+  for (Int i = 0; i <= sei.m_numOlsIndicesMinus1; i++)
+  {
+    READ_UVLC(uiCode, "ols_idx[i]"); sei.m_olsIdx[i] = uiCode;
+  }
+
+  // byte alignment
+  while (m_pcBitstream->getNumBitsRead() % 8 != 0)
+  {
+    UInt code;
+    READ_FLAG(code, "ols_nesting_zero_bit");
+  }
+
+  sei.m_callerOwnsSEIs = false;
+
+  // read nested SEI messages
+  do {
+#if O0164_MULTI_LAYER_HRD
+#if LAYERS_NOT_PRESENT_SEI
+    xReadSEImessage(sei.m_nestedSEIs, nalUnitType, vps, sps);
+#else
+    xReadSEImessage(sei.m_nestedSEIs, nalUnitType, sps);
+#endif
+#else
+#if LAYERS_NOT_PRESENT_SEI
+    xReadSEImessage(sei.m_nestedSEIs, nalUnitType, vps, sps);
+#else
+    xReadSEImessage(sei.m_nestedSEIs, nalUnitType, sps);
+#endif
+#endif
+  } while (m_pcBitstream->getNumBitsLeft() > 8);
+
+}
+
+Void SEIReader::xParseSEIVPSRewriting(SEIVPSRewriting &sei)
+{
+}
+
+#endif
+
 #endif //SVC_EXTENSION
 
Index: /branches/SHM-6-dev/source/Lib/TLibDecoder/SEIread.h
===================================================================
--- /branches/SHM-6-dev/source/Lib/TLibDecoder/SEIread.h	(revision 777)
+++ /branches/SHM-6-dev/source/Lib/TLibDecoder/SEIread.h	(revision 778)
@@ -119,4 +119,12 @@
   Void xParseHrdParameters(TComHRD *hrd, Bool commonInfPresentFlag, UInt maxNumSubLayersMinus1);
 #endif
+#if Q0078_ADD_LAYER_SETS
+#if LAYERS_NOT_PRESENT_SEI
+  Void xParseSEIOutputLayerSetNesting(SEIOutputLayerSetNesting& sei, const NalUnitType nalUnitType, TComVPS *vps, TComSPS *sps);
+#else
+  Void xParseSEIOutputLayerSetNesting(SEIOutputLayerSetNesting& sei, const NalUnitType nalUnitType, TComSPS *sps);
+#endif
+  Void xParseSEIVPSRewriting(SEIVPSRewriting &sei);
+#endif
   Void xParseByteAlign();
 };
Index: /branches/SHM-6-dev/source/Lib/TLibDecoder/TDecCAVLC.cpp
===================================================================
--- /branches/SHM-6-dev/source/Lib/TLibDecoder/TDecCAVLC.cpp	(revision 777)
+++ /branches/SHM-6-dev/source/Lib/TLibDecoder/TDecCAVLC.cpp	(revision 778)
@@ -1187,4 +1187,19 @@
   }
 #endif
+#if Q0078_ADD_LAYER_SETS
+#if O0092_0094_DEPENDENCY_CONSTRAINT // Moved here
+  vps->setNumRefLayers();
+
+  if (vps->getMaxLayers() > MAX_REF_LAYERS)
+  {
+    for (i = 1; i < vps->getMaxLayers(); i++)
+    {
+      assert(vps->getNumRefLayers(vps->getLayerIdInNuh(i)) <= MAX_REF_LAYERS);
+    }
+  }
+#endif
+  vps->setPredictedLayerIds();
+  vps->setTreePartitionLayerIdList();
+#endif
 #if VPS_TSLAYERS
   READ_FLAG( uiCode, "vps_sub_layers_max_minus1_present_flag"); vps->setMaxTSLayersPresentFlag(uiCode ? true : false);
@@ -1274,4 +1289,46 @@
 #endif
 
+#if Q0078_ADD_LAYER_SETS
+  if (vps->getNumIndependentLayers() > 1)
+  {
+    READ_UVLC(uiCode, "num_add_layer_sets"); vps->setNumAddLayerSets(uiCode);
+    for (Int i = 0; i < vps->getNumAddLayerSets(); i++)
+    {
+      for (Int j = 1; j < vps->getNumIndependentLayers(); j++)
+      {
+        int len = 1;
+        while ((1 << len) < (vps->getNumLayersInTreePartition(j) + 1))
+        {
+          len++;
+        }
+        READ_CODE(len, uiCode, "highest_layer_idx_plus1[i][j]"); vps->setHighestLayerIdxPlus1(i, j, uiCode);
+      }
+    }
+
+    for (Int i = 0; i < vps->getNumAddLayerSets(); i++)
+    {
+      for (Int j = 1; j < vps->getNumIndependentLayers(); j++)
+      {
+        Int layerNum = 0;
+        Int lsIdx = vps->getNumLayerSets() + i;
+        for (Int layerId = 0; layerId <= 62; layerId++)
+        {
+          vps->setLayerIdIncludedFlag(false, lsIdx, layerId);
+          for (Int treeIdx = 1; treeIdx < vps->getNumIndependentLayers(); treeIdx++)
+          {
+            for (Int layerCnt = 0; layerCnt < vps->getHighestLayerIdxPlus1(i, j); layerCnt++)
+            {
+              vps->setLayerSetLayerIdList(lsIdx, layerNum, vps->getTreePartitionLayerId(treeIdx, layerCnt));
+              vps->setLayerIdIncludedFlag(true, lsIdx, vps->getTreePartitionLayerId(treeIdx, layerCnt));
+              layerNum++;
+            }
+          }
+        }
+        vps->setNumLayersInIdList(lsIdx, layerNum);
+      }
+    }
+  }
+#endif
+
 #if !VPS_EXTN_UEV_CODING
   READ_FLAG( uiCode, "more_output_layer_sets_than_default_flag" ); vps->setMoreOutputLayerSetsThanDefaultFlag( uiCode ? true : false );
@@ -1676,5 +1733,6 @@
   }
 #endif
-#if O0092_0094_DEPENDENCY_CONSTRAINT
+#if !Q0078_ADD_LAYER_SETS
+#if O0092_0094_DEPENDENCY_CONSTRAINT // Moved up
   vps->setNumRefLayers();
 
@@ -1686,4 +1744,5 @@
     }
   }
+#endif
 #endif
 
Index: /branches/SHM-6-dev/source/Lib/TLibDecoder/TDecTop.cpp
===================================================================
--- /branches/SHM-6-dev/source/Lib/TLibDecoder/TDecTop.cpp	(revision 777)
+++ /branches/SHM-6-dev/source/Lib/TLibDecoder/TDecTop.cpp	(revision 778)
@@ -107,4 +107,36 @@
 TDecTop::~TDecTop()
 {
+#if Q0078_ADD_LAYER_SETS
+  for (Int psId = 0; psId < MAX_NUM_SPS; psId++)
+  {
+    TComSPS* sps = m_parameterSetManagerDecoder.getSPS(psId);
+    if (sps != NULL)
+    {
+      // Remove parameter set from other layers to prevent multiple deletes of the same object
+      for (Int lId = 0; lId < m_numLayer; lId++)
+      {
+        if (m_ppcTDecTop[lId] != this)
+        {
+          m_parameterSetManagerDecoder.removeSPS(psId);
+        }
+      }
+    }
+  }
+  for (Int psId = 0; psId < MAX_NUM_PPS; psId++)
+  {
+    TComPPS* pps = m_parameterSetManagerDecoder.getPPS(psId);
+    if (pps != NULL)
+    {
+      // Remove parameter set from other layers to prevent multiple deletes of the same object
+      for (Int lId = 0; lId < m_numLayer; lId++)
+      {
+        if (m_ppcTDecTop[lId] != this)
+        {
+          m_parameterSetManagerDecoder.removePPS(psId);
+        }
+      }
+    }
+  }
+#endif
 #if ENC_DEC_TRACE
   fclose( g_hTrace );
@@ -1886,4 +1918,14 @@
 #endif
   m_parameterSetManagerDecoder.storePrefetchedSPS(sps);
+#if Q0078_ADD_LAYER_SETS
+  // Store SPS for all layers
+  for (Int lId = 0; lId < m_numLayer; lId++)
+  {
+    if (m_ppcTDecTop[lId] != this)
+    {
+      m_ppcTDecTop[lId]->getParameterSetManager()->storePrefetchedSPS(sps);
+    }
+  }
+#endif
 #if !REPN_FORMAT_IN_VPS   // ILRP can only be initialized at activation  
   if(m_numLayer>0)
@@ -1916,4 +1958,14 @@
     );
   m_parameterSetManagerDecoder.storePrefetchedPPS( pps );
+#if Q0078_ADD_LAYER_SETS
+  // Store PPS for all layers
+  for (Int lId = 0; lId < m_numLayer; lId++)
+  {
+    if (m_ppcTDecTop[lId] != this)
+    {
+      m_ppcTDecTop[lId]->getParameterSetManager()->storePrefetchedPPS(pps);
+    }
+  }
+#endif
 
   if( pps->getDependentSliceSegmentsEnabledFlag() )
Index: /branches/SHM-6-dev/source/Lib/TLibEncoder/SEIwrite.cpp
===================================================================
--- /branches/SHM-6-dev/source/Lib/TLibEncoder/SEIwrite.cpp	(revision 777)
+++ /branches/SHM-6-dev/source/Lib/TLibEncoder/SEIwrite.cpp	(revision 778)
@@ -130,4 +130,12 @@
     break;
 #endif
+#if Q0078_ADD_LAYER_SETS
+  case SEI::OUTPUT_LAYER_SET_NESTING:
+    fprintf(g_hTrace, "=========== Output layer set nesting SEI message ===========\n");
+    break;
+  case SEI::VPS_REWRITING:
+    fprintf(g_hTrace, "=========== VPS rewriting SEI message ===========\n");
+    break;
+#endif
 #endif //SVC_EXTENSION
   default:
@@ -227,4 +235,12 @@
    case SEI::BSP_HRD:
      xWriteSEIBspHrd(*static_cast<const SEIBspHrd*>(&sei), sps, nestingSei);
+     break;
+#endif
+#if Q0078_ADD_LAYER_SETS
+   case SEI::OUTPUT_LAYER_SET_NESTING:
+     xWriteSEIOutputLayerSetNesting(bs, *static_cast<const SEIOutputLayerSetNesting*>(&sei), vps, sps);
+     break;
+   case SEI::VPS_REWRITING:
+     xWriteSEIVPSRewriting(*static_cast<const SEIVPSRewriting*>(&sei));
      break;
 #endif
@@ -1035,4 +1051,35 @@
 #endif
 
+#if Q0078_ADD_LAYER_SETS
+
+Void SEIWriter::xWriteSEIOutputLayerSetNesting(TComBitIf& bs, const SEIOutputLayerSetNesting &sei, TComVPS *vps, TComSPS *sps)
+{
+  WRITE_FLAG(sei.m_olsFlag, "ols_flag");
+  WRITE_UVLC(sei.m_numOlsIndicesMinus1, "num_ols_indices_minus1");
+
+  for (Int i = 0; i <= sei.m_numOlsIndicesMinus1; i++)
+  {
+    WRITE_UVLC(sei.m_olsIdx[i], "ols_idx[i]");
+  }
+
+  while (m_pcBitIf->getNumberOfWrittenBits() % 8 != 0)
+  {
+    WRITE_FLAG(0, "ols_nesting_zero_bit");
+  }
+
+  // write nested SEI messages
+  for (SEIMessages::const_iterator it = sei.m_nestedSEIs.begin(); it != sei.m_nestedSEIs.end(); it++)
+  {
+    writeSEImessage(bs, *(*it), vps, sps);
+  }
+}
+
+Void SEIWriter::xWriteSEIVPSRewriting(const SEIVPSRewriting &sei)
+{
+  //sei.nalu->
+}
+
+#endif
+
 #endif //SVC_EXTENSION
 
Index: /branches/SHM-6-dev/source/Lib/TLibEncoder/SEIwrite.h
===================================================================
--- /branches/SHM-6-dev/source/Lib/TLibEncoder/SEIwrite.h	(revision 777)
+++ /branches/SHM-6-dev/source/Lib/TLibEncoder/SEIwrite.h	(revision 778)
@@ -101,4 +101,8 @@
   Void xCodeHrdParameters( TComHRD *hrd, Bool commonInfPresentFlag, UInt maxNumSubLayersMinus1 );
 #endif
+#if Q0078_ADD_LAYER_SETS
+  Void xWriteSEIOutputLayerSetNesting(TComBitIf& bs, const SEIOutputLayerSetNesting &sei, TComVPS *vps, TComSPS *sps);
+  Void xWriteSEIVPSRewriting(const SEIVPSRewriting &sei);
+#endif
 #endif //SVC_EXTENSION
 };
Index: /branches/SHM-6-dev/source/Lib/TLibEncoder/TEncCavlc.cpp
===================================================================
--- /branches/SHM-6-dev/source/Lib/TLibEncoder/TEncCavlc.cpp	(revision 777)
+++ /branches/SHM-6-dev/source/Lib/TLibEncoder/TEncCavlc.cpp	(revision 778)
@@ -1000,4 +1000,23 @@
 #endif
 
+#if Q0078_ADD_LAYER_SETS
+  if (vps->getNumIndependentLayers() > 1)
+  {
+    WRITE_UVLC( vps->getNumAddLayerSets(), "num_add_layer_sets" );
+    for (Int i = 0; i < vps->getNumAddLayerSets(); i++)
+    {
+      for (Int j = 1; j < vps->getNumIndependentLayers(); j++)
+      {
+        int len = 1;
+        while ((1 << len) < (vps->getNumLayersInTreePartition(j) + 1))
+        {
+          len++;
+        }
+        WRITE_CODE(vps->getHighestLayerIdxPlus1(i, j), len, "highest_layer_idx_plus1[i][j]");
+      }
+    }
+  }
+#endif
+
 #if !VPS_EXTN_UEV_CODING
   Int numOutputLayerSets = vps->getNumOutputLayerSets() ;
Index: /branches/SHM-6-dev/source/Lib/TLibEncoder/TEncGOP.cpp
===================================================================
--- /branches/SHM-6-dev/source/Lib/TLibEncoder/TEncGOP.cpp	(revision 777)
+++ /branches/SHM-6-dev/source/Lib/TLibEncoder/TEncGOP.cpp	(revision 778)
@@ -2170,4 +2170,10 @@
       nalu = NALUnit(NAL_UNIT_SPS);
 #endif
+#if Q0078_ADD_LAYER_SETS
+      if (m_pcEncTop->getVPS()->getNumDirectRefLayers(m_layerId) == 0 && m_pcEncTop->getVPS()->getNumAddLayerSets() > 0)
+      {
+        nalu.m_layerId = 0; // For independent base layer rewriting
+      }
+#endif
       m_pcEntropyCoder->setBitstream(&nalu.m_Bitstream);
       if (m_bSeqFirst)
@@ -2207,4 +2213,10 @@
 #else
       nalu = NALUnit(NAL_UNIT_PPS);
+#endif
+#if Q0078_ADD_LAYER_SETS
+      if (m_pcEncTop->getVPS()->getNumDirectRefLayers(m_layerId) == 0 && m_pcEncTop->getVPS()->getNumAddLayerSets() > 0)
+      {
+        nalu.m_layerId = 0; // For independent base layer rewriting
+      }
 #endif
       m_pcEntropyCoder->setBitstream(&nalu.m_Bitstream);
Index: /branches/SHM-6-dev/source/Lib/TLibEncoder/TEncTop.cpp
===================================================================
--- /branches/SHM-6-dev/source/Lib/TLibEncoder/TEncTop.cpp	(revision 777)
+++ /branches/SHM-6-dev/source/Lib/TLibEncoder/TEncTop.cpp	(revision 778)
@@ -912,5 +912,16 @@
 {
 #if SVC_EXTENSION
+#if Q0078_ADD_LAYER_SETS
+  if (getNumDirectRefLayers() == 0 && getNumAddLayerSets() > 0)
+  {
+    m_cSPS.setLayerId(0); // layer ID 0 for independent layers
+  }
+  else
+  {
+    m_cSPS.setLayerId(m_layerId);
+  }
+#else
   m_cSPS.setLayerId(m_layerId);
+#endif
   m_cSPS.setNumScaledRefLayerOffsets(m_numScaledRefLayerOffsets);
   for(Int i = 0; i < m_cSPS.getNumScaledRefLayerOffsets(); i++)
@@ -1171,4 +1182,11 @@
 #endif
 
+#if Q0078_ADD_LAYER_SETS
+  if (getNumDirectRefLayers() == 0 && getNumAddLayerSets() > 0)
+  {
+    m_cPPS.setLayerId(0); // layer ID 0 for independent layers
+  }
+#endif
+
   if( m_layerId > 0 )
   {
Index: /branches/SHM-6-dev/source/Lib/TLibEncoder/TEncTop.h
===================================================================
--- /branches/SHM-6-dev/source/Lib/TLibEncoder/TEncTop.h	(revision 777)
+++ /branches/SHM-6-dev/source/Lib/TLibEncoder/TEncTop.h	(revision 778)
@@ -154,4 +154,7 @@
   Bool                    m_interLayerWeightedPredFlag;
 #endif
+#if Q0078_ADD_LAYER_SETS
+  int                     m_numAddLayerSets;
+#endif
 #endif //SVC_EXTENSION
 protected:
@@ -268,4 +271,8 @@
   Void setNoOutputOfPriorPicsFlags(Bool x)   { m_noOutputOfPriorPicsFlags = x;   }
 #endif
+#if Q0078_ADD_LAYER_SETS
+  Void setNumAddLayerSets(Int x)             { m_numAddLayerSets = x; }
+  Int  getNumAddLayerSets()                  { return m_numAddLayerSets; }
+#endif
 #else //SVC_EXTENSION
   Void encode( Bool bEos, TComPicYuv* pcPicYuvOrg, TComList<TComPicYuv*>& rcListPicYuvRecOut,
