diff --git a/source/App/SubpicMergeApp/SubpicMergeApp.cpp b/source/App/SubpicMergeApp/SubpicMergeApp.cpp
index 9c607eb0a1a2cb48993acda398640fe06eebe482..15d3c66683bea8eef6fdc3a55738eac4e8eb9a59 100644
--- a/source/App/SubpicMergeApp/SubpicMergeApp.cpp
+++ b/source/App/SubpicMergeApp/SubpicMergeApp.cpp
@@ -52,6 +52,9 @@
 #include "NALwrite.h"
 #include "AnnexBwrite.h"
 #include "SubpicMergeApp.h"
+#include "SEIread.h"
+#include "SEIEncoder.h"
+#include "SEIwrite.h"
 
 
  //! \ingroup SubpicMergeApp
@@ -82,6 +85,7 @@ struct Subpicture {
   PicHeader                            picHeader;
   std::vector<Slice>                   slices;
   std::vector<OutputBitstream>         sliceData;
+  SEI                                  *decodedPictureHashSei;
 };
 
 
@@ -297,6 +301,27 @@ void SubpicMergeApp::parseAPS(HLSyntaxReader &hlsReader, ParameterSetManager &ps
   msg( INFO, "  APS%i", apsId);
 }
 
+/**
+  - Parse SEI message
+*/
+void SubpicMergeApp::parseSEI(SEIReader &seiReader, InputNALUnit &nalu, const VPS *vps, const SPS *sps, SEI *&decodePictureHashSei)
+{
+  SEIMessages seis;
+  HRD hrd;
+
+  seiReader.parseSEImessage(seiReader.getBitstream(), seis, nalu.m_nalUnitType, nalu.m_nuhLayerId, nalu.m_temporalId, vps, sps, hrd, 0);
+
+  decodePictureHashSei = nullptr;
+  for (auto& s : seis)
+  {
+    if (s->payloadType() == SEI::DECODED_PICTURE_HASH)
+    {
+      decodePictureHashSei = s;
+      break;
+    }
+  }
+}
+
 /**
   - Parse picture header
 */
@@ -334,10 +359,12 @@ void SubpicMergeApp::parseSliceHeader(HLSyntaxReader &hlsReader, InputNALUnit &n
 /**
   - Decode NAL unit if it is parameter set or picture header, or decode slice header of VLC NAL unit
  */
-void SubpicMergeApp::decodeNalu(Subpicture &subpic, InputNALUnit &nalu)
+void SubpicMergeApp::decodeNalu(Subpicture &subpic, InputNALUnit &nalu, SEI *&decodePictureHashSei)
 {
   HLSyntaxReader hlsReader;
+  SEIReader seiReader;
   hlsReader.setBitstream(&nalu.getBitstream());
+  seiReader.setBitstream(&nalu.getBitstream());
   int apsId;
   int apsType;
 
@@ -361,7 +388,18 @@ void SubpicMergeApp::decodeNalu(Subpicture &subpic, InputNALUnit &nalu)
     break;
   case NAL_UNIT_PH:
     parsePictureHeader(hlsReader, subpic.picHeader, subpic.psManager);
-  break;
+    break;
+  case NAL_UNIT_SUFFIX_SEI:
+    parseSEI(seiReader, nalu, subpic.slices.front().getVPS(), subpic.slices.front().getSPS(), decodePictureHashSei);
+    if (decodePictureHashSei != nullptr)
+    {
+      msg( INFO, "  hash SEI");
+    }
+    else
+    {
+      msg( INFO, "  suffix SEI");
+    }
+    break;
   default:
     if (nalu.isVcl())
     {
@@ -371,11 +409,11 @@ void SubpicMergeApp::decodeNalu(Subpicture &subpic, InputNALUnit &nalu)
     }
     else if (nalu.isSei())
     {
-      msg( INFO, "  SEI");
+      msg( INFO, "  prefix SEI");
     }
     else
     {
-      msg( INFO, "  NNN");  // Any other NAL unit that is not handled above
+      msg( INFO, "  ignored NALU");  // Any other NAL unit that is not handled above
     }
     break;
   }
@@ -398,6 +436,7 @@ void SubpicMergeApp::parseSubpic(Subpicture &subpic, bool &morePictures)
   subpic.slices.clear();
   subpic.sliceData.clear();
   subpic.firstSliceInPicture = true;
+  subpic.decodedPictureHashSei = nullptr;
 
   bool eof = false;
 
@@ -426,7 +465,7 @@ void SubpicMergeApp::parseSubpic(Subpicture &subpic, bool &morePictures)
     }
 
     read(nalu);  // Convert nalu payload to RBSP and parse nalu header
-    decodeNalu(subpic, nalu);
+    decodeNalu(subpic, nalu, subpic.decodedPictureHashSei);
 
     if (nalu.isVcl())
     {
@@ -767,8 +806,8 @@ void SubpicMergeApp::updateSliceHeadersForMergedStream(ParameterSetManager &psMa
       // Update slice headers to use new SPSes and PPSes
       int ppsId = slice.getPPS()->getPPSId();
       int spsId = slice.getSPS()->getSPSId();
-      CHECK(!psManager.getSPS(spsId), "Invaldi SPS");
-      CHECK(!psManager.getSPS(ppsId), "Invaldi PPS");
+      CHECK(!psManager.getSPS(spsId), "Invalid SPS");
+      CHECK(!psManager.getSPS(ppsId), "Invalid PPS");
       slice.setSPS(psManager.getSPS(spsId));
       slice.setPPS(psManager.getPPS(ppsId));
 
@@ -965,9 +1004,6 @@ void SubpicMergeApp::generateMergedPic(ParameterSetManager &psManager, bool mixe
     }
   }
 
-  // Don't copy SEI NAL units - many of them would be incorrect for merged stream
-  //copyNalUnitsToAccessUnit(accessUnit, subpic.nalus, (int)NAL_UNIT_PREFIX_SEI);
-
   updateSliceHeadersForMergedStream(psManager);
 
   // Code merged stream prefix APS NAL units
@@ -1026,8 +1062,34 @@ void SubpicMergeApp::generateMergedPic(ParameterSetManager &psManager, bool mixe
     }
   }
 
-  // Don't copy SEIs - many of them would be incorrect for merged stream
-  // copyNalUnitsToAccessUnit(accessUnit, subpic.nalus, (int)NAL_UNIT_SUFFIX_SEI);
+  // Code Decoded picture hash SEI messages within Scalable nesting SEI messages
+  uint32_t layerId = m_subpics->at(0).slices[0].getNalUnitLayerId();
+  uint32_t temporalId = m_subpics->at(0).slices[0].getTLayer();
+  int subpicId = 0;
+  for (auto& subpic : *m_subpics)
+  {
+    if (subpic.decodedPictureHashSei != nullptr)
+    {
+      SEIEncoder seiEncoder;
+      SEIWriter seiWriter;
+      SEIMessages seiMessages;
+      SEIMessages nestedSEI;
+      HRD hrd;
+      nestedSEI.push_back(subpic.decodedPictureHashSei);
+      const std::vector<uint16_t> subPicIds = { (uint16_t)subpicId };
+      std::vector<int> targetOLS;
+      std::vector<int> targetLayers = { (int)subpic.nalus[0].m_nuhLayerId };
+      SEIScalableNesting *nestingSEI = new SEIScalableNesting();
+      seiEncoder.init(0, 0, 0);
+      seiEncoder.initSEIScalableNesting(nestingSEI, nestedSEI, targetOLS, targetLayers, subPicIds);
+      OutputNALUnit nalu( NAL_UNIT_SUFFIX_SEI, layerId, temporalId );
+      seiMessages.push_back(nestingSEI);
+      seiWriter.writeSEImessages(nalu.m_Bitstream, seiMessages, hrd, false, temporalId);
+      accessUnit.push_back(new NALUnitEBSP(nalu));
+    }
+    subpicId++;
+  }
+
   copyNalUnitsToAccessUnit(accessUnit, subpic0.nalus, (int)NAL_UNIT_EOS);
   copyNalUnitsToAccessUnit(accessUnit, subpic0.nalus, (int)NAL_UNIT_EOB);
 
diff --git a/source/App/SubpicMergeApp/SubpicMergeApp.h b/source/App/SubpicMergeApp/SubpicMergeApp.h
index adcc68c659ae0d6b34aaf8e515a9f2c8b567a052..2a5285e3a88c1fbb208c6fd31879c56ff88a5cef 100644
--- a/source/App/SubpicMergeApp/SubpicMergeApp.h
+++ b/source/App/SubpicMergeApp/SubpicMergeApp.h
@@ -56,6 +56,8 @@ struct SubpicParams {
 struct Subpicture;
 class InputByteStream;
 class HLSyntaxReader;
+class SEIReader;
+class SEI;
 class DCI;
 class ParameterSetManager;
 class PicHeader;
@@ -92,9 +94,10 @@ private:
   int parseSPS(HLSyntaxReader &hlsReader, ParameterSetManager &psManager);
   int parsePPS(HLSyntaxReader &hlsReader, ParameterSetManager &psManager);
   void parseAPS(HLSyntaxReader &hlsReader, ParameterSetManager &psManager, int &apsId, int &apsType);
+  void parseSEI(SEIReader& seiReader, InputNALUnit &nalu, const VPS *vps, const SPS *sps, SEI *&decodePictureHashSei);
   void parsePictureHeader(HLSyntaxReader &hlsReader, PicHeader &picHeader, ParameterSetManager &psManager);
   void parseSliceHeader(HLSyntaxReader &hlsReader, InputNALUnit &nalu, Slice &slice, PicHeader &picHeader, OutputBitstream &sliceData, ParameterSetManager &psManager, int prevTid0Poc);
-  void decodeNalu(Subpicture &subpic, InputNALUnit &nalu);
+  void decodeNalu(Subpicture &subpic, InputNALUnit &nalu, SEI *&decodePictureHashSei);
   void parseSubpic(Subpicture &subpic, bool &morePictures);
   void generateMergedStreamVPSes(std::vector<VPS*> &vpsList);
   int computeSubPicIdLen(int numSubpics);