diff --git a/cfg/sei_vui/display_overlays_info.cfg b/cfg/sei_vui/display_overlays_info.cfg
new file mode 100644
index 0000000000000000000000000000000000000000..38a38fe69ff3a5772ed8a2162d5925ec36f3938f
--- /dev/null
+++ b/cfg/sei_vui/display_overlays_info.cfg
@@ -0,0 +1,27 @@
+#========Display Overlays Information SEI message =====================
+
+SEIDOIEnabled:           	1       #Whether EOI SEI message will be generated.
+SEIDOIId:			0	#The Identifier of the DOI SEI message
+SEIDOICancelFlag:          	0       #Whether the SEI cancel persistence of previous SEI.
+SEIDOIPersistenceFlag:          1       #Does the SEI persist for one picture or till it is cancelled.
+SEIDOINumDisplayOverlaysMinus2: 0	#Number of display overlays for which information is signalled in the SEI message.
+SEIDOINuhLayerIdPresentFlag:	1	#Specifies that the doi_nuh_layer_id[ i ] syntax element is present in the SEI message.
+SEIDOITargetPicSizePresentFlag: 1	#specifies that the doi_target_pic_width_minus1 and doi_target_pic_width_minus1 syntax elements are present.
+SEIDOITargetPicWidthMinus1:	1279
+SEIDOITargetPicHeightMinus1:    719
+SEIDOIPicPartitionFlag:		1	#Specifies that display overlay components are coded as constituent rectangles/subpictures or in separated pictures.
+SEIDOIPartitionTypeFlag:	1	#Specifies that display overlay components are coded as constituent rectangle (1) or subpictures (0)
+SEIDOIPartitionIdLenMinus1:     3	#+1 specifies the length of doi partition syntax element
+SEIDOIOffsetParamsPresentFlag:  1 	#Specifies that offset parameters are present for the i-th display overlay.
+SEIDOIOffsetParamsLengthMinus1: 10	#Specifies the length minus 1 of the doi_top_left_x[ i ] and doi_top_left_y[ i ], syntax elements in bits.
+SEIDOIResamplingEnabledFlag:	0	#Specifies that display overlay components may be resampled in the target display picture.
+SEIDOINuhLayerId0:		0
+SEIDOIPartitionId0:		0
+SEIDOIAlphaPresentFlag0:	0
+SEIDOINuhLayerId1:		1
+SEIDOIPartitionId1:		0
+SEIDOIAlphaPresentFlag1:	1
+SEIDOIAlphaNuhLayerId1:		1
+SEIDOIAlphaPartitionId1:	1
+SEIDOITopLeftX1:		0
+SEIDOITopLeftY1:		500
\ No newline at end of file
diff --git a/doc/software-manual.tex b/doc/software-manual.tex
index 8ceafa60fcb327a67b26bada0ddf43a35b3aa2aa..aaaeae5f57a13d9ce343ea8e25da053c4f3df47c 100644
--- a/doc/software-manual.tex
+++ b/doc/software-manual.tex
@@ -4002,6 +4002,7 @@ The table below lists the SEI messages defined for Version 1 and Range-Extension
   TBD & Packed Regions Info                      & Table \ref{tab:sei-pri}\\
   TBD & Quality metric                           & Table \ref{tab:sei-qm}\\
   TBD & Bitdepth Range Info                      & Table \ref{tab:sei-bri}\\
+  TBD & Display Overlays Information             & Table \ref{tab:sei-doi}\\
 \end{SEIListTable}
 %%
 %% SEI messages
@@ -6179,6 +6180,109 @@ Specifies sii_num_units_in_shutter_interval for single entry.If multiple entries
   \\
 \end{OptionTableNoShorthand}
 
+\begin{OptionTableNoShorthand}{Display Overlays Information}{tab:sei-doi}
+  \Option{SEIDOIEnabled} &
+  \Default{false} &
+  Control generation of the Display Overlays Info SEI message.
+  \\
+  \Option{SEIDOIId} &
+  \Default{0} &
+  Specifies the identifier of the DOI SEI message.
+  \\
+  \Option{SEIDOICancelFlag} &
+  \Default{false} &
+  Specifies the persistence of any previous DOI SEI message in output order.
+  \\
+  \Option{SEIDOIPersistenceFlag} &
+  \Default{false} &
+  Specifies the persistence of the DOI SEI message for the current layer.
+  \\
+  \Option{SEIDOINumDisplayOverlaysMinus2} &
+  \Default{0} &
+  Specifies the number of display overlays minus 2 for which information is signalled in the SEI message.
+  \\
+  \Option{SEIDOINuhLayerIdPresentFlag} &
+  \Default{false} &
+  Specifies that the doi_nuh_layer_id[ i ] syntax element is present in the SEI message.
+  \\
+  \Option{SEIDOITargetPicSizePresentFlag} &
+  \Default{false} &
+  Specifies that the doi_target_pic_width_minus1 and doi_target_pic_width_minus1 syntax elements are present.
+  \\
+  \Option{SEIDOITargetPicWidthMinus1} &
+  \Default{0} &
+  Indicates the width minus 1 of the target picture.
+  \\
+  \Option{SEIDOITargetPicHeightMinus1} &
+  \Default{0} &
+  Indicates the height minus 1 of the target picture.
+  \\
+  \Option{SEIDOIPicPartitionFlag} &
+  \Default{false} &
+  Specifies that display overlay components are coded as constituent rectangles or subpictures.
+  \\
+  \Option{SEIDOIPartitionTypeFlag} &
+  \Default{false} &
+  Specifies that a display overlay component is coded as a constituent rectangle.
+  \\
+  \Option{SEIDOIPartitionIdLenMinus1} &
+  \Default{0} &
+  Specifies the length minus 1 of the doi_partition_id[ i ] syntax elements.
+  \\
+  \Option{SEIDOIOffsetParamsPresentFlag} &
+  \Default{false} &
+  Specifies that offset parameters are present for the i-th display overlay.
+  \\
+  \Option{SEIDOIOffsetParamsLengthMinus1} &
+  \Default{0} &
+  Specifies the length minus 1 of the doi_top_left_x[ i ] and doi_top_left_y[ i ], syntax elements in bits.
+  \\
+  \Option{SEIDOIResamplingEnabledFlag} &
+  \Default{false} &
+  Specifies that display overlay components may be resampled in the target display picture.
+  \\
+  \Option{SEIDOISizeParamLengthMinus1} &
+  \Default{0} &
+  Specifies the length minus 1 of the doi_width_minus1[ i ] and doi_height_minus1[ i ] syntax elements in bits.
+  \\
+  \Option{SEIDOINuhLayerId\emph{i}} &
+  \Default{0} &
+  Specifies the layer identifier of the texture component of the i-th display overlay.
+  \\
+  \Option{SEIDOIPartitionId\emph{i}} &
+  \Default{0} &
+  Specifies  that the texture component of the i-th display overlay is represented by the j-th constituent rectangle when cr_rect_id[ j ] equal doi_partition_id[ i ].
+  \\
+  \Option{SEIDOIAlphaPresentFlag\emph{i}} &
+  \Default{false} &
+  Specifies that an alpha component is provided for the i-th display overlay.
+  \\
+  \Option{SEIDOIAlphaNuhLayerId\emph{i}} &
+  \Default{0} &
+  Specifies the layer identifier value of the alpha component of the i-th display overlay.
+  \\
+  \Option{SEIDOIAlphaPartitionId\emph{i}} &
+  \Default{0} &
+  Specifies the cr_rect_id[ j ] of the alpha component of the i-th display overlay.
+  \\
+  \Option{SEIDOITopLeftX\emph{i}} &
+  \Default{0} &
+  Specifies the horizontal positions of the top left corner of the i-th display overlay in the target display picture, in luma samples.
+  \\
+  \Option{SEIDOITopLeftY\emph{i}} &
+  \Default{0} &
+  Specifies the vertical positions of the top left corner of the i-th display overlay in the target display picture, in luma samples.
+  \\
+  \Option{SEIDOIWidthMinus1\emph{i}} &
+  \Default{} &
+  Specifies the width minus 1 in luma samples arrays of the i-th display overlay in the target display picture.
+  \\
+  \Option{SEIDOIHeightMinus1\emph{i}} &
+  \Default{} &
+  Specifies the height minus 1 in luma samples arrays of the i-th display overlay in the target display picture.
+  \\
+\end{OptionTableNoShorthand}
+
 \begin{OptionTableNoShorthand}{Phase indication}{tab:sei-phase-indication}
 \Option{SEIPhaseIndicationFullResolution} &
 \Default{false} &
@@ -6907,6 +7011,18 @@ If no value is specified, the SEI message will not be output.
 Packed regions info output file name. If empty, no object information will be saved.
 \\
 
+\Option{SEIDOIId} &
+%\ShortOption{\None} &
+\Default{\NotSet} &
+Specifies the DOI SEI id which should be used to generate output picture with overlay embedded.
+\\
+
+\Option{SEIDOIFilename} &
+%\ShortOption{\None} &
+\Default{\NotSet} &
+DOI YUV output file name. If empty, no overlay is applied (ignore SEI message).
+\\
+
 \end{OptionTableNoShorthand}
 
 
diff --git a/source/App/DecoderApp/DecApp.cpp b/source/App/DecoderApp/DecApp.cpp
index bb940b8fc813fcc2a9ccf19cd74ecb08cabf9074..273eea48743d7d65b66bcfa53e7e32df146940a9 100644
--- a/source/App/DecoderApp/DecApp.cpp
+++ b/source/App/DecoderApp/DecApp.cpp
@@ -63,6 +63,11 @@ DecApp::DecApp()
   {
     m_newCLVS[i] = true;
   }
+#if JVET_AI0181
+  m_doiSEIPelY = nullptr;
+  m_doiSEIPelU = nullptr;
+  m_doiSEIPelV = nullptr;
+#endif
 }
 
 // ====================================================================================================================
@@ -81,6 +86,10 @@ uint32_t DecApp::decode()
 {
   int      poc;
   PicList *pcListPic = nullptr;
+
+#if JVET_AI0181
+  m_doiSEILastProcessedOverlay = -1;
+#endif
   
 #if GREEN_METADATA_SEI_ENABLED
   FeatureCounterStruct featureCounter;
@@ -1050,6 +1059,15 @@ void DecApp::xDestroyDecLib()
       recFile.second.close();
     }
   }
+#if JVET_AI0181
+  if (!m_SEIDOIFileName.empty())
+  {
+    for (auto& recFile: m_videoIOYuvSEIDOIFile)
+    {
+      recFile.second.close();
+    }
+  }
+#endif
 
   // destroy decoder class
   m_cDecLib.destroy();
@@ -1265,6 +1283,12 @@ void DecApp::xWriteOutput( PicList* pcListPic, uint32_t tId )
           }
         }
 
+#if JVET_AI0181
+        if (!m_SEIDOIFileName.empty())
+        {
+          xGenerateTargetPicture(pcPic);
+        }
+#endif
 
         if (!m_shutterIntervalPostFileName.empty() && getShutterFilterFlag())
         {
@@ -1527,6 +1551,13 @@ void DecApp::xFlushOutput( PicList* pcListPic, const int layerId )
             }
           }
 
+#if JVET_AI0181
+          if (!m_SEIDOIFileName.empty())
+          {
+            xGenerateTargetPicture(pcPic);
+          }
+#endif
+
           if (!m_shutterIntervalPostFileName.empty() && getShutterFilterFlag())
           {
             int blendingRatio = getBlendingRatio();
@@ -2156,3 +2187,289 @@ void DecApp::xUnpackOpacityLayer(Picture* pcPic)
 }
 #endif
 //! \}
+
+#if JVET_AI0181
+void DecApp::xGenerateTargetPicture(Picture* pcPic) 
+{
+  SEIMessages seiListDOI = getSeisByType(pcPic->SEIs, SEI::PayloadType::DISPLAY_OVERLAYS_INFO);
+  CHECK(seiListDOI.empty(), "No DOI SEI have been received");
+  bool        seiDoiPresent = false;
+  SEIMessages seiListCR     = getSeisByType(pcPic->SEIs, SEI::PayloadType::CONSTITUENT_RECTANGLES);
+  for (auto sei: seiListDOI)
+  {
+    auto doisei = (SEIDisplayOverlaysInfo*) sei;
+    if (doisei->m_doiSEIId == this->m_SEIDOIId)
+    {
+      seiDoiPresent       = true;
+      int numOverlays     = doisei->m_doiSEINumDisplayOverlaysMinus2 + 2;
+      int targetPicWidth  = doisei->m_doiSEITargetPicWidthMinus1 + 1;
+      int targetPicHeight = doisei->m_doiSEITargetPicHeightMinus1 + 1;
+      // Create internal buffers
+      if (m_doiSEIPelY == nullptr)
+      {
+        m_doiSEIPelY = new Pel[targetPicWidth * targetPicHeight];
+        m_doiSEIPelU = new Pel[(targetPicWidth >> 1) * (targetPicHeight >> 1)];
+        m_doiSEIPelV = new Pel[(targetPicWidth >> 1) * (targetPicHeight >> 1)];
+      }
+      for (int overlay_idx = this->m_doiSEILastProcessedOverlay + 1; overlay_idx < numOverlays; overlay_idx++)
+      {
+        if (doisei->m_doiSEIPicPartitionFlag == 1 && doisei->m_doiSEIPartitionTypeFlag == 1)
+        {
+          CHECK(seiListCR.empty(), "A constituent rectangles SEI is expected when doi_pic_partition_flag and "
+                                    "doi_pic_partition_type_flag are equal to 1");
+          CHECK(doisei->m_doiSEIResamplingEnabledFlag, "Resampling is not implemented for DOI SEI.");
+          CHECK(overlay_idx != this->m_doiSEILastProcessedOverlay + 1,
+                "Coding of an overlay have been skipped, please constraint overlay to be processed in layer "
+                "ascending order");
+
+          if (doisei->m_doiSEINuhLayerId[overlay_idx] == pcPic->layerId)
+          {
+            // check CR
+            bool                      noCRforLayerId = true;
+            SEIConstituentRectangles* doicr;
+            for (auto sei: seiListCR)
+            {
+              doicr = (SEIConstituentRectangles*) sei;
+              if ((int) doicr->m_layerId == pcPic->layerId)
+              {
+                noCRforLayerId = false;
+                break;
+              }
+            }
+            CHECK(noCRforLayerId, "No CR SEI has been found for the current processed layer.")
+
+            int cr_h = (doicr->m_rectSameSizeFlag
+                          ? pcPic->cs->pps->getPicHeightInLumaSamples() / (doicr->m_numRowsMinus1 + 1)
+                          : (1 << doicr->m_log2UnitSize)
+                              * (doicr->m_rectHeightInUnitsMinus1[doisei->m_doiSEIPartitionId[overlay_idx]] + 1));
+            int cr_w = (doicr->m_rectSameSizeFlag
+                          ? pcPic->getPicWidthInLumaSamples() / (doicr->m_numColsMinus1 + 1)
+                          : (1 << doicr->m_log2UnitSize)
+                              * (doicr->m_rectWidthInUnitsMinus1[doisei->m_doiSEIPartitionId[overlay_idx]] + 1));
+
+            int x0_t = (overlay_idx > 0 ? doisei->m_doiSEITopLeftX[overlay_idx] : 0);
+            int y0_t = (overlay_idx > 0 ? doisei->m_doiSEITopLeftY[overlay_idx] : 0);
+            int x0_o = (doicr->m_rectSameSizeFlag
+                          ? (doisei->m_doiSEIPartitionId[overlay_idx] % (doicr->m_numColsMinus1 + 1))
+                              * pcPic->cs->pps->getPicWidthInLumaSamples() / (doicr->m_numColsMinus1 + 1)
+                          : doicr->m_rectTopLeftInUnitsX[overlay_idx] * (1 << doicr->m_log2UnitSize));
+            int y0_o = (doicr->m_rectSameSizeFlag
+                          ? (doisei->m_doiSEIPartitionId[overlay_idx] / (doicr->m_numColsMinus1 + 1))
+                              * pcPic->cs->pps->getPicHeightInLumaSamples() / (doicr->m_numRowsMinus1 + 1)
+                          : doicr->m_rectTopLeftInUnitsY[overlay_idx] * (1 << doicr->m_log2UnitSize));
+            int x_o  = x0_o;
+            int y_o  = y0_o;
+            int x0_a = 0;
+            int y0_a = 0;
+            if (doisei->m_doiSEIAlphaPresentFlag[overlay_idx])
+            {
+              x0_a = (doicr->m_rectSameSizeFlag
+                        ? (doisei->m_doiSEIAlphaPartitionId[overlay_idx] % (doicr->m_numColsMinus1 + 1))
+                            * pcPic->cs->pps->getPicWidthInLumaSamples() / (doicr->m_numColsMinus1 + 1)
+                        : doicr->m_rectTopLeftInUnitsX[overlay_idx] * (1 << doicr->m_log2UnitSize));
+              y0_a = (doicr->m_rectSameSizeFlag
+                        ? (doisei->m_doiSEIAlphaPartitionId[overlay_idx] / (doicr->m_numColsMinus1 + 1))
+                            * pcPic->cs->pps->getPicHeightInLumaSamples() / (doicr->m_numRowsMinus1 + 1)
+                        : doicr->m_rectTopLeftInUnitsY[overlay_idx] * (1 << doicr->m_log2UnitSize));
+            }
+            int x_a = x0_a;
+            int y_a = y0_a;
+
+            // Overlay Y component
+            for (int h_idx = y0_t; (h_idx < targetPicHeight) && ((h_idx - y0_t) < cr_h); h_idx++)
+            {
+              x_a = x0_a;
+              x_o = x0_o;
+              for (int w_idx = x0_t; (w_idx < targetPicWidth) && ((w_idx - x0_t) < cr_w); w_idx++)
+              {
+                if (doisei->m_doiSEIAlphaPresentFlag[overlay_idx])
+                {
+                  CHECK(doisei->m_doiSEIAlphaNuhLayerId[overlay_idx] != doisei->m_doiSEINuhLayerId[overlay_idx],
+                        "Current implementation only sypports Texture and Alpha packed as two CR in the same "
+                        "layer");
+                  float alpha = (float) pcPic->getRecoBuf().get(COMPONENT_Y).at(Position(x_o, y_o))
+                                / (1 << pcPic->m_bitDepths[(ChannelType) ChannelType::LUMA]);
+                  float b = (float) pcPic->getRecoBuf().get(COMPONENT_Y).at(Position(x_o, y_o));
+                  float a = (float) m_doiSEIPelY[h_idx * targetPicWidth + w_idx];
+                  m_doiSEIPelY[h_idx * targetPicWidth + w_idx] = (uint16_t) (alpha * a + (1 - alpha) * b);
+                  x_a++;
+                  x_o++;
+                }
+                else
+                {
+                  m_doiSEIPelY[h_idx * targetPicWidth + w_idx] =
+                    pcPic->getRecoBuf().get(COMPONENT_Y).at(Position(x_o, y_o));
+                  x_o++;
+                }
+              }
+              y_a++;
+              y_o++;
+            }
+
+            // Overlay U component
+            x0_t = (overlay_idx > 0 ? (doisei->m_doiSEITopLeftX[overlay_idx] >> 1) : 0);
+            y0_t = (overlay_idx > 0 ? (doisei->m_doiSEITopLeftY[overlay_idx] >> 1) : 0);
+            x0_o = (doicr->m_rectSameSizeFlag
+                      ? (doisei->m_doiSEIPartitionId[overlay_idx] % (doicr->m_numColsMinus1 + 1))
+                          * (pcPic->cs->pps->getPicWidthInLumaSamples() >> 1) / (doicr->m_numColsMinus1 + 1)
+                      : doicr->m_rectTopLeftInUnitsX[overlay_idx] * (1 << doicr->m_log2UnitSize));
+            y0_o = (doicr->m_rectSameSizeFlag
+                      ? (doisei->m_doiSEIPartitionId[overlay_idx] / (doicr->m_numColsMinus1 + 1))
+                          * (pcPic->cs->pps->getPicHeightInLumaSamples() >> 1) / (doicr->m_numRowsMinus1 + 1)
+                      : doicr->m_rectTopLeftInUnitsY[overlay_idx] * (1 << doicr->m_log2UnitSize));
+            x0_a = 0;
+            y0_a = 0;
+            x_o  = x0_o;
+            y_o  = y0_o;
+            if (doisei->m_doiSEIAlphaPresentFlag[overlay_idx])
+            {
+              x0_a = (doicr->m_rectSameSizeFlag
+                        ? (doisei->m_doiSEIAlphaPartitionId[overlay_idx] % (doicr->m_numColsMinus1 + 1))
+                            * (pcPic->cs->pps->getPicWidthInLumaSamples() >> 1) / (doicr->m_numColsMinus1 + 1)
+                        : doicr->m_rectTopLeftInUnitsX[overlay_idx] * (1 << doicr->m_log2UnitSize));
+              y0_a = (doicr->m_rectSameSizeFlag
+                        ? (doisei->m_doiSEIAlphaPartitionId[overlay_idx] / (doicr->m_numColsMinus1 + 1))
+                            * (pcPic->cs->pps->getPicHeightInLumaSamples() >> 1) / (doicr->m_numRowsMinus1 + 1)
+                        : doicr->m_rectTopLeftInUnitsY[overlay_idx] * (1 << doicr->m_log2UnitSize));
+            }
+            x_a = x0_a;
+            y_a = y0_a;
+            for (int h_idx = y0_t; (h_idx < (targetPicHeight >> 1)) && ((h_idx - y0_t) < (cr_h >> 1)); h_idx++)
+            {
+              x_a = x0_a;
+              x_o = x0_o;
+              for (int w_idx = x0_t; (w_idx < (targetPicWidth >> 1)) && ((w_idx - x0_t) < (cr_w >> 1)); w_idx++)
+              {
+                if (doisei->m_doiSEIAlphaPresentFlag[overlay_idx])
+                {
+                  CHECK(doisei->m_doiSEIAlphaNuhLayerId[overlay_idx] != doisei->m_doiSEINuhLayerId[overlay_idx],
+                        "Current implementation only sypports Texture and Alpha packed as two CR in the same "
+                        "layer");
+                  float alpha = (float) pcPic->getRecoBuf().get(COMPONENT_Cb).at(Position(x_o, y_o))
+                                / (1 << pcPic->m_bitDepths[(ChannelType) ChannelType::CHROMA]);
+                  float b = (float) pcPic->getRecoBuf().get(COMPONENT_Cb).at(Position(x_o, y_o));
+                  float a = (float) m_doiSEIPelU[h_idx * (targetPicWidth >> 1) + w_idx];
+                  m_doiSEIPelU[h_idx * (targetPicWidth >> 1) + w_idx] = (uint16_t) (alpha * a + (1 - alpha) * b);
+                  x_a++;
+                  x_o++;
+                }
+                else
+                {
+                  m_doiSEIPelU[h_idx * (targetPicWidth >> 1) + w_idx] =
+                    pcPic->getRecoBuf().get(COMPONENT_Cb).at(Position(x_o, y_o));
+                  x_o++;
+                }
+              }
+              y_a++;
+              y_o++;
+            }
+
+            // Overlay V component
+            x0_t = (overlay_idx > 0 ? (doisei->m_doiSEITopLeftX[overlay_idx] >> 1) : 0);
+            y0_t = (overlay_idx > 0 ? (doisei->m_doiSEITopLeftY[overlay_idx] >> 1) : 0);
+            x0_o = (doicr->m_rectSameSizeFlag
+                      ? (doisei->m_doiSEIPartitionId[overlay_idx] % (doicr->m_numColsMinus1 + 1))
+                          * (pcPic->cs->pps->getPicWidthInLumaSamples() >> 1) / (doicr->m_numColsMinus1 + 1)
+                      : doicr->m_rectTopLeftInUnitsX[overlay_idx] * (1 << doicr->m_log2UnitSize));
+            y0_o = (doicr->m_rectSameSizeFlag
+                      ? (doisei->m_doiSEIPartitionId[overlay_idx] / (doicr->m_numColsMinus1 + 1))
+                          * (pcPic->cs->pps->getPicHeightInLumaSamples() >> 1) / (doicr->m_numRowsMinus1 + 1)
+                      : doicr->m_rectTopLeftInUnitsY[overlay_idx] * (1 << doicr->m_log2UnitSize));
+            x0_a = 0;
+            y0_a = 0;
+            x_o  = x0_o;
+            y_o  = y0_o;
+            if (doisei->m_doiSEIAlphaPresentFlag[overlay_idx])
+            {
+              x0_a = (doicr->m_rectSameSizeFlag
+                        ? (doisei->m_doiSEIAlphaPartitionId[overlay_idx] % (doicr->m_numColsMinus1 + 1))
+                            * (pcPic->cs->pps->getPicWidthInLumaSamples() >> 1) / (doicr->m_numColsMinus1 + 1)
+                        : doicr->m_rectTopLeftInUnitsX[overlay_idx] * (1 << doicr->m_log2UnitSize));
+              y0_a = (doicr->m_rectSameSizeFlag
+                        ? (doisei->m_doiSEIAlphaPartitionId[overlay_idx] / (doicr->m_numColsMinus1 + 1))
+                            * (pcPic->cs->pps->getPicHeightInLumaSamples() >> 1) / (doicr->m_numRowsMinus1 + 1)
+                        : doicr->m_rectTopLeftInUnitsY[overlay_idx] * (1 << doicr->m_log2UnitSize));
+            }
+            x_a = x0_a;
+            y_a = y0_a;
+
+            for (int h_idx = y0_t; (h_idx < (targetPicHeight >> 1)) && ((h_idx - y0_t) < (cr_h >> 1)); h_idx++)
+            {
+              x_a = x0_a;
+              x_o = x0_o;
+              for (int w_idx = x0_t; (w_idx < (targetPicWidth >> 1)) && ((w_idx - x0_t) < (cr_w >> 1)); w_idx++)
+              {
+                if (doisei->m_doiSEIAlphaPresentFlag[overlay_idx])
+                {
+                  CHECK(doisei->m_doiSEIAlphaNuhLayerId[overlay_idx] != doisei->m_doiSEINuhLayerId[overlay_idx],
+                        "Current implementation only sypports Texture and Alpha packed as two CR in the same "
+                        "layer");
+                  float alpha = (float) pcPic->getRecoBuf().get(COMPONENT_Cr).at(Position(x_o, y_o))
+                                / (1 << pcPic->m_bitDepths[(ChannelType) ChannelType::CHROMA]);
+                  float b = (float) pcPic->getRecoBuf().get(COMPONENT_Cr).at(Position(x_o, y_o));
+                  float a = (float) m_doiSEIPelV[h_idx * (targetPicWidth >> 1) + w_idx];
+                  m_doiSEIPelV[h_idx * (targetPicWidth >> 1) + w_idx] = (uint16_t) (alpha * a + (1 - alpha) * b);
+                  x_a++;
+                  x_o++;
+                }
+                else
+                {
+                  m_doiSEIPelV[h_idx * (targetPicWidth >> 1) + w_idx] =
+                    pcPic->getRecoBuf().get(COMPONENT_Cr).at(Position(x_o, y_o));
+                  x_o++;
+                }
+              }
+              y_a++;
+              y_o++;
+            }
+            this->m_doiSEILastProcessedOverlay = overlay_idx;
+          }
+        }
+        else
+        {
+          CHECK(true, "Only constituent rectangles are implemented for DOI SEI.");
+        }
+      }
+      if (this->m_doiSEILastProcessedOverlay == numOverlays - 1)
+      {
+        // Writing output file
+        FILE* fptr = fopen(m_SEIDOIFileName.c_str(), "ab+");
+        for (int r = 0; r < targetPicHeight; r++)
+        {
+          for (int c = 0; c < targetPicWidth; c++)
+          {
+            int16_t val = m_doiSEIPelY[r * targetPicWidth + c];
+            fwrite(&val, sizeof(int16_t), 1, fptr);
+          }
+        }
+        for (int r = 0; r < (targetPicHeight >> 1); r++)
+        {
+          for (int c = 0; c < (targetPicWidth >> 1); c++)
+          {
+            int16_t val = m_doiSEIPelU[r * (targetPicWidth >> 1) + c];
+            fwrite(&val, sizeof(int16_t), 1, fptr);
+          }
+        }
+        for (int r = 0; r < (targetPicHeight >> 1); r++)
+        {
+          for (int c = 0; c < (targetPicWidth >> 1); c++)
+          {
+            int16_t val = m_doiSEIPelV[r * (targetPicWidth >> 1) + c];
+            fwrite(&val, sizeof(int16_t), 1, fptr);
+          }
+        }
+        fclose(fptr);
+        delete m_doiSEIPelY;
+        delete m_doiSEIPelU;
+        delete m_doiSEIPelV;
+        m_doiSEIPelY                       = nullptr;
+        m_doiSEIPelU                       = nullptr;
+        m_doiSEIPelV                       = nullptr;
+        this->m_doiSEILastProcessedOverlay = -1;
+      }
+    }
+    break;
+  }
+  CHECK(seiDoiPresent == false, "No SEI DOI messages are present for the requested DOI id");
+}
+#endif
\ No newline at end of file
diff --git a/source/App/DecoderApp/DecApp.h b/source/App/DecoderApp/DecApp.h
index 59846858e24206da8ae938b0ad15b4a340af1ae8..9fdcc8f789fbb9f60c0669937df289fae1d725bf 100644
--- a/source/App/DecoderApp/DecApp.h
+++ b/source/App/DecoderApp/DecApp.h
@@ -63,6 +63,14 @@ private:
   std::unordered_map<int, VideoIOYuv>      m_cVideoIOYuvReconFile;        ///< reconstruction YUV class
   std::unordered_map<int, VideoIOYuv>      m_videoIOYuvSEIFGSFile;       ///< reconstruction YUV with FGS class
   std::unordered_map<int, VideoIOYuv>      m_cVideoIOYuvSEICTIFile;       ///< reconstruction YUV with CTI class
+#if JVET_AI0181
+  std::unordered_map<int, VideoIOYuv>      m_videoIOYuvSEIDOIFile;   ///< reconstruction YUV with DOI class
+  int                                      m_idxSEIDOI;               ///< Index of the SEI DOI to be processed 
+  int                                      m_doiSEILastProcessedOverlay;   ///< Index of the SEI DOI to be processed
+  Pel*                                     m_doiSEIPelY;
+  Pel*                                     m_doiSEIPelU;
+  Pel*                                     m_doiSEIPelV;
+#endif
 
   bool                                    m_ShutterFilterEnable;          ///< enable Post-processing with Shutter Interval SEI
   VideoIOYuv                              m_cTVideoIOYuvSIIPostFile;      ///< post-filtered YUV class
@@ -142,6 +150,9 @@ private:
   void xOutputPackedRegionsInfo(Picture* pcPic);
   void xOutputPackedRegionsInfoVector(FILE* fp, const char* paramName, const std::vector<uint32_t>& v);
 #endif
+#if JVET_AI0181
+  void xGenerateTargetPicture(Picture* pcPic);
+#endif
 };
 
 //! \}
diff --git a/source/App/DecoderApp/DecAppCfg.cpp b/source/App/DecoderApp/DecAppCfg.cpp
index 5a332537ff8263a225acb4ccd503497eebca7d79..117382ced85c3d29999af998d623d0b09b2f3826 100644
--- a/source/App/DecoderApp/DecAppCfg.cpp
+++ b/source/App/DecoderApp/DecAppCfg.cpp
@@ -114,6 +114,10 @@ bool DecAppCfg::parseCfg( int argc, char* argv[] )
 #endif
   ("ClipOutputVideoToRec709Range",      m_clipOutputVideoToRec709Range,  false,   "If true then clip output video to the Rec. 709 Range on saving")
   ("PYUV",                      m_packedYUVMode,                       false,      "If true then output 10-bit and 12-bit YUV data as 5-byte and 3-byte (respectively) packed YUV data. Ignored for interlaced output.")
+#if JVET_AI0181
+  ("SEIDOIId",                  m_SEIDOIId,                            -1,      "Specifies the DOI SEI id which should be used to generate output picture with overlay embedded.")
+  ("SEIDOIFilename",            m_SEIDOIFileName,                      std::string(""), "DOI YUV output file name. If empty, no overlay is applied (ignore SEI message).\n")
+#endif
 #if ENABLE_TRACING
   ("TraceChannelsList",         bTracingChannelsList,                  false,      "List all available tracing channels")
   ("TraceRule",                 sTracingRule,                          std::string(""), "Tracing rule (ex: \"D_CABAC:poc==8\" or \"D_REC_CB_LUMA:poc==8\")")
@@ -289,6 +293,10 @@ DecAppCfg::DecAppCfg()
   , m_packedYUVMode(false)
   , m_statMode(0)
   , m_mctsCheck(false)
+#if JVET_AI0181
+  , m_SEIDOIId(-1)
+  , m_SEIDOIFileName()
+#endif
 {
   m_outputBitDepth.fill(0);
 }
diff --git a/source/App/DecoderApp/DecAppCfg.h b/source/App/DecoderApp/DecAppCfg.h
index 5cdb8e3e8c51cfad17021a56c0b0253c75ce51ed..95911438a50b3c454dc015f3af551c8072d7298d 100644
--- a/source/App/DecoderApp/DecAppCfg.h
+++ b/source/App/DecoderApp/DecAppCfg.h
@@ -99,6 +99,10 @@ protected:
   std::string   m_cacheCfgFile;                       ///< Config file of cache model
   int           m_statMode;                           ///< Config statistic mode (0 - bit stat, 1 - tool stat, 3 - both)
   bool          m_mctsCheck;
+#if JVET_AI0181
+  int           m_SEIDOIId;      // If != -1, specifies the DOI SEI id (doi_id) that should be targeted to reconstruct output layer
+  std::string   m_SEIDOIFileName;   ///< output file name for reconstructed sequence with display overlays
+#endif
 #if GREEN_METADATA_SEI_ENABLED
   bool          m_GMFA;
   std::string   m_GMFAFile;
diff --git a/source/App/EncoderApp/EncApp.cpp b/source/App/EncoderApp/EncApp.cpp
index 88eaaaae3d108704451cc9cdd5d9c25f27d0c002..ec04ed318a49bbe7deb98e63169b70b53bd3bea2 100644
--- a/source/App/EncoderApp/EncApp.cpp
+++ b/source/App/EncoderApp/EncApp.cpp
@@ -1508,6 +1508,77 @@ void EncApp::xInitLibCfg( int layerIdx )
   m_cEncLib.setQmSEIMetricDescription(tmpMetricDescription);
 #endif
 
+#if JVET_AI0181
+  // Display overlays info
+  m_cEncLib.setDOISEIEnabled(m_doiSEIEnabled);
+  m_cEncLib.setDOISEIId(m_doiSEIId);
+  m_cEncLib.setDOISEICancelFlag(m_doiSEICancelFlag);
+  if (!m_doiSEICancelFlag)
+  {
+    m_cEncLib.setDOISEIPersistenceFlag(m_doiSEIPersistenceFlag);
+    m_cEncLib.setDOISEINumDisplayOverlaysMinus2(m_doiSEINumDisplayOverlaysMinus2);
+    m_cEncLib.setDOISEINuhLayerIdPresentFlag(m_doiSEINuhLayerIdPresentFlag);
+    m_cEncLib.setDOISEITargetPicSizePresentFlag(m_doiSEITargetPicSizePresentFlag);
+    if (m_doiSEITargetPicSizePresentFlag)
+    {
+      m_cEncLib.setDOISEITargetPicWidthMinus1(m_doiSEITargetPicWidthMinus1);
+      m_cEncLib.setDOISEITargetPicHeightMinus1(m_doiSEITargetPicHeightMinus1);
+    }
+    m_cEncLib.setDOISEIPicPartitionFlag(m_doiSEIPicPartitionFlag);
+    if (m_doiSEIPicPartitionFlag)
+    {
+      m_cEncLib.setDOISEIPartitionTypeFlag(m_doiSEIPartitionTypeFlag);
+      m_cEncLib.setDOISEIPartitionIdLenMinus1(m_doiSEIPartitionIdLenMinus1);
+    }
+    m_cEncLib.setDOISEIOffsetParamsPresentFlag(m_doiSEIOffsetParamsPresentFlag);
+    if (m_doiSEIOffsetParamsPresentFlag)
+    {
+      m_cEncLib.setDOISEIOffsetParamsLengthMinus1(m_doiSEIOffsetParamsLengthMinus1);
+    }
+    m_cEncLib.setDOISEIResamplingEnabledFlag(m_doiSEIResamplingEnabledFlag);
+    if (m_doiSEIResamplingEnabledFlag)
+    {
+      m_cEncLib.setDOISEISizeParamLengthMinus1(m_doiSEISizeParamLengthMinus1);
+    }
+    for (int i = 0; i < m_doiSEINumDisplayOverlaysMinus2 + 2; i++)
+    {
+      if (m_doiSEINuhLayerIdPresentFlag)
+      {
+        m_cEncLib.setDOISEINuhLayerId(m_doiSEINuhLayerId[i], i);
+      }
+      if (m_doiSEIPicPartitionFlag)
+      {
+        m_cEncLib.setDOISEIPartitionId(m_doiSEIPartitionId[i], i);
+      }
+      m_cEncLib.setDOISEIAlphaPresentFlag(m_doiSEIAlphaPresentFlag[i], i);
+      if (m_doiSEIAlphaPresentFlag[i])
+      {
+        if (m_doiSEINuhLayerIdPresentFlag)
+        {
+          m_cEncLib.setDOISEIAlphaNuhLayerId(m_doiSEIAlphaNuhLayerId[i], i);
+        }
+        if (m_doiSEIPicPartitionFlag)
+        {
+          m_cEncLib.setDOISEIAlphaPartitionId(m_doiSEIAlphaPartitionId[i], i);
+        }
+      }
+      if (i > 0)
+      {
+        if (m_doiSEIOffsetParamsPresentFlag)
+        {
+          m_cEncLib.setDOISEITopLeftX(m_doiSEITopLeftX[i], i);
+          m_cEncLib.setDOISEITopLeftY(m_doiSEITopLeftY[i], i);
+        }
+        if (m_doiSEIResamplingEnabledFlag)
+        {
+          m_cEncLib.setDOISEIWidthMinus1(m_doiSEIWidthMinus1[i], i);
+          m_cEncLib.setDOISEIHeightMinus1(m_doiSEIHeightMinus1[i], i);
+        }
+      }
+    }
+  }
+#endif
+
 #if JVET_AI0182_BITDEPTH_RANGE_INFORMATION_SEI
   m_cEncLib.setBriSEIEnabled(m_briSEIEnabled);
   m_cEncLib.setBriSEIOrigBitDepthMinus1(m_briSEIOrigBitDepthMinus1);
diff --git a/source/App/EncoderApp/EncAppCfg.cpp b/source/App/EncoderApp/EncAppCfg.cpp
index 231f7446b20c1c2c437af4b0b82686944102572b..56124fcd07f6c5c276e890c10904858b5ff5f5d1 100644
--- a/source/App/EncoderApp/EncAppCfg.cpp
+++ b/source/App/EncoderApp/EncAppCfg.cpp
@@ -1810,6 +1810,33 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] )
   ("SEIPRITargetRegionTopLeftX",                      cfg_priSEITargetRegionTopLeftX, cfg_priSEITargetRegionTopLeftX, "Specifies a list of horizontal top left postions in units of luma samples for the regions in reconstructed target picture")
   ("SEIPRITargetRegionTopLeftY",                      cfg_priSEITargetRegionTopLeftY, cfg_priSEITargetRegionTopLeftY, "Specifies a list of vertical top left postions in units of luma samples for the regions in reconstructed target picture")
 #endif
+#if JVET_AI0181
+  ("SEIDOIEnabled",                                   m_doiSEIEnabled,                                   false, "Control generation of the Display Overlays Info SEI message.")
+  ("SEIDOIId",                                        m_doiSEIId,                                           0u, "Specifies the identifier of the DOI SEI message.")
+  ("SEIDOICancelFlag",                                m_doiSEICancelFlag,                                false, "Specifies the persistence of any previous DOI SEI message in output order.")
+  ("SEIDOIPersistenceFlag",                           m_doiSEIPersistenceFlag,                           false, "Specifies the persistence of the DOI SEI message for the current layer.")
+  ("SEIDOINumDisplayOverlaysMinus2",                  m_doiSEINumDisplayOverlaysMinus2,                     0u, "Specifies the number of display overlays minus 2 for which information is signalled in the SEI message.")
+  ("SEIDOINuhLayerIdPresentFlag",                     m_doiSEINuhLayerIdPresentFlag,                     false, "Specifies that the doi_nuh_layer_id[ i ] syntax element is present in the SEI message.")
+  ("SEIDOITargetPicSizePresentFlag",                  m_doiSEITargetPicSizePresentFlag,                  false, "Specifies that the doi_target_pic_width_minus1 and doi_target_pic_width_minus1 syntax elements are present.")
+  ("SEIDOITargetPicWidthMinus1",                      m_doiSEITargetPicWidthMinus1,                         0u, "Indicates the width minus 1 of the target picture.")
+  ("SEIDOITargetPicHeightMinus1",                     m_doiSEITargetPicHeightMinus1,                        0u, "Indicates the height minus 1 of the target picture.")
+  ("SEIDOIPicPartitionFlag",                          m_doiSEIPicPartitionFlag,                          false, "Specifies that display overlay components are coded as constituent rectangles or subpictures.")
+  ("SEIDOIPartitionTypeFlag",                         m_doiSEIPartitionTypeFlag,                         false, "Specifies that a display overlay component is coded as a constituent rectangle.")
+  ("SEIDOIPartitionIdLenMinus1",                      m_doiSEIPartitionIdLenMinus1,                         0u, "Specifies the length minus 1 of the doi_partition_id[ i ] syntax elements.")
+  ("SEIDOIOffsetParamsPresentFlag",                   m_doiSEIOffsetParamsPresentFlag,                   false, "Specifies that offset parameters are present for the i-th display overlay.")
+  ("SEIDOIOffsetParamsLengthMinus1",                  m_doiSEIOffsetParamsLengthMinus1,                     0u, "Specifies the length minus 1 of the doi_top_left_x[ i ] and doi_top_left_y[ i ], syntax elements in bits.")
+  ("SEIDOIResamplingEnabledFlag",                     m_doiSEIResamplingEnabledFlag,                     false, "Specifies that display overlay components may be resampled in the target display picture.")
+  ("SEIDOISizeParamLengthMinus1",                     m_doiSEISizeParamLengthMinus1,                        0u, "Specifies the length minus 1 of the doi_width_minus1[ i ] and doi_height_minus1[ i ] syntax elements in bits.")
+  ("SEIDOINuhLayerId%d",                              m_doiSEINuhLayerId,                                    0, MAX_DISPLAY_OVERLAYS, "Specifies the layer identifier of the texture component of the i-th display overlay.")
+  ("SEIDOIPartitionId%d",                             m_doiSEIPartitionId,                                   0, MAX_DISPLAY_OVERLAYS, "Specifies  that the texture component of the i-th display overlay is represented by the j-th constituent rectangle when cr_rect_id[ j ] equal doi_partition_id[ i ].")
+  ("SEIDOIAlphaPresentFlag%d",                        m_doiSEIAlphaPresentFlag,                              0, MAX_DISPLAY_OVERLAYS, "Specifies that an alpha component is provided for the i-th display overlay.")
+  ("SEIDOIAlphaNuhLayerId%d",                         m_doiSEIAlphaNuhLayerId,                               0, MAX_DISPLAY_OVERLAYS, "Specifies the layer identifier value of the alpha component of the i-th display overlay.")
+  ("SEIDOIAlphaPartitionId%d",                        m_doiSEIAlphaPartitionId,                              0, MAX_DISPLAY_OVERLAYS, "Specifies the cr_rect_id[ j ] of the alpha component of the i-th display overlay.")
+  ("SEIDOITopLeftX%d",                                m_doiSEITopLeftX,                                      0, MAX_DISPLAY_OVERLAYS, "Specifies the horizontal positions of the top left corner of the i-th display overlay in the target display picture, in luma samples.")
+  ("SEIDOITopLeftY%d",                                m_doiSEITopLeftY,                                      0, MAX_DISPLAY_OVERLAYS, "Specifies the vertical positions of the top left corner of the i-th display overlay in the target display picture, in luma samples.")
+  ("SEIDOIWidthMinus1%d",                             m_doiSEIWidthMinus1,                                   0, MAX_DISPLAY_OVERLAYS, "Specifies the width minus 1 in luma samples arrays of the i-th display overlay in the target display picture.")
+  ("SEIDOIHeightMinus1%d",                            m_doiSEIHeightMinus1,                                  0, MAX_DISPLAY_OVERLAYS, "Specifies the height minus 1 in luma samples arrays of the i-th display overlay in the target display picture.")
+#endif
 
   ("DebugBitstream",                                  m_decodeBitstreams[0],             std::string( "" ), "Assume the frames up to POC DebugPOC will be the same as in this bitstream. Load those frames from the bitstream instead of encoding them." )
   ("DebugPOC",                                        m_switchPOC,                                 -1, "If DebugBitstream is present, load frames up to this POC from this bitstream. Starting with DebugPOC, return to normal encoding." )
diff --git a/source/App/EncoderApp/EncAppCfg.h b/source/App/EncoderApp/EncAppCfg.h
index fea11ff8442679e68fc859099062f95827287c55..c2ec29227c62ede60cb5ca5ac0312725f3ab5089 100644
--- a/source/App/EncoderApp/EncAppCfg.h
+++ b/source/App/EncoderApp/EncAppCfg.h
@@ -848,6 +848,35 @@ protected:
   std::string              m_crSEIRectTypeDescription[MAX_RECT_TYPE_DESCRIPTIONS];
 #endif
 
+#if JVET_AI0181
+  // Display overlays info
+  bool     m_doiSEIEnabled;
+  uint32_t m_doiSEIId;
+  bool     m_doiSEICancelFlag;
+  bool     m_doiSEIPersistenceFlag;
+  uint32_t m_doiSEINumDisplayOverlaysMinus2;
+  bool     m_doiSEINuhLayerIdPresentFlag;
+  bool     m_doiSEITargetPicSizePresentFlag;
+  uint32_t m_doiSEITargetPicWidthMinus1;
+  uint32_t m_doiSEITargetPicHeightMinus1;
+  bool     m_doiSEIPicPartitionFlag;
+  bool     m_doiSEIPartitionTypeFlag;
+  uint32_t m_doiSEIPartitionIdLenMinus1;
+  bool     m_doiSEIOffsetParamsPresentFlag;
+  uint32_t m_doiSEIOffsetParamsLengthMinus1;
+  bool     m_doiSEIResamplingEnabledFlag;
+  uint32_t m_doiSEISizeParamLengthMinus1;
+  int      m_doiSEINuhLayerId[MAX_DISPLAY_OVERLAYS];
+  int      m_doiSEIPartitionId[MAX_DISPLAY_OVERLAYS];
+  int      m_doiSEIAlphaPresentFlag[MAX_DISPLAY_OVERLAYS];
+  int      m_doiSEIAlphaNuhLayerId[MAX_DISPLAY_OVERLAYS];
+  int      m_doiSEIAlphaPartitionId[MAX_DISPLAY_OVERLAYS];
+  int      m_doiSEITopLeftX[MAX_DISPLAY_OVERLAYS];
+  int      m_doiSEITopLeftY[MAX_DISPLAY_OVERLAYS];
+  int      m_doiSEIWidthMinus1[MAX_DISPLAY_OVERLAYS];
+  int      m_doiSEIHeightMinus1[MAX_DISPLAY_OVERLAYS];
+#endif
+
   bool                  m_constrainedRaslEncoding;
 
   bool                  m_sampleAspectRatioInfoSEIEnabled;
diff --git a/source/Lib/CommonLib/CommonDef.h b/source/Lib/CommonLib/CommonDef.h
index 700d4520a98370a36abcb09dda0349309a644ac3..5b82d6d1e50de052f7fa7cbe658a9cfc96799aab 100644
--- a/source/Lib/CommonLib/CommonDef.h
+++ b/source/Lib/CommonLib/CommonDef.h
@@ -571,6 +571,9 @@ static constexpr int CBF_MASK_CBCR = CBF_MASK_CB | CBF_MASK_CR;
 // SEI and related constants
 // ====================================================================================================================
 
+#if JVET_AI0181
+static constexpr int MAX_DISPLAY_OVERLAYS = 32;
+#endif
 static const uint32_t MAX_NNPFA_ID =                               0xfffffffe; // Maximum supported nnpfa_id
 static const uint32_t MAX_NNPFC_ID =                               0xfffffffe; // Maximum supported nnpfc_id
 static constexpr double SII_PF_W2 =                                       0.6; // weight for current picture
diff --git a/source/Lib/CommonLib/SEI.cpp b/source/Lib/CommonLib/SEI.cpp
index f7e8a4b694413ef1a6f26d2958b576deaa0d16f5..4fd41f9408e3b547f1d0f8e5a6da97f65972e881 100644
--- a/source/Lib/CommonLib/SEI.cpp
+++ b/source/Lib/CommonLib/SEI.cpp
@@ -555,6 +555,9 @@ static const std::map<SEI::PayloadType, const char *> payloadTypeStrings = {
 #if JVET_AH0164_QUALITY_METRIC_SEI
   { SEI::PayloadType::QUALITY_METRIC, "Quality Metric" },
 #endif
+#if JVET_AI0181
+  { SEI::PayloadType::DISPLAY_OVERLAYS_INFO, "Display overlays info" },
+#endif
 #if JVET_AI0182_BITDEPTH_RANGE_INFORMATION_SEI
   { SEI::PayloadType::BITDEPTH_RANGE_INFO, "Bitdepth range information" },
 #endif
@@ -1404,6 +1407,37 @@ SEIQualityMetric::SEIQualityMetric(const SEIQualityMetric& sei)
 }
 #endif
 
+#if JVET_AI0181
+SEIDisplayOverlaysInfo::SEIDisplayOverlaysInfo(const SEIDisplayOverlaysInfo& sei)
+{
+  m_doiSEIId                       = sei.m_doiSEIId;
+  m_doiSEICancelFlag               = sei.m_doiSEICancelFlag;
+  m_doiSEIPersistenceFlag          = sei.m_doiSEIPersistenceFlag;
+  m_doiSEINumDisplayOverlaysMinus2 = sei.m_doiSEINumDisplayOverlaysMinus2;
+  m_doiSEINuhLayerIdPresentFlag    = sei.m_doiSEINuhLayerIdPresentFlag;
+  m_doiSEITargetPicSizePresentFlag = sei.m_doiSEITargetPicSizePresentFlag;
+  m_doiSEITargetPicWidthMinus1     = sei.m_doiSEITargetPicWidthMinus1;
+  m_doiSEITargetPicHeightMinus1    = sei.m_doiSEITargetPicHeightMinus1;
+  m_doiSEIPicPartitionFlag         = sei.m_doiSEIPicPartitionFlag;
+  m_doiSEIPartitionTypeFlag        = sei.m_doiSEIPartitionTypeFlag;
+  m_doiSEIPartitionIdLenMinus1     = sei.m_doiSEIPartitionIdLenMinus1;
+  m_doiSEIOffsetParamsPresentFlag  = sei.m_doiSEIOffsetParamsPresentFlag;
+  m_doiSEIOffsetParamsLengthMinus1 = sei.m_doiSEIOffsetParamsLengthMinus1;
+  m_doiSEIResamplingEnabledFlag    = sei.m_doiSEIResamplingEnabledFlag;
+  m_doiSEISizeParamLengthMinus1    = sei.m_doiSEISizeParamLengthMinus1;
+
+  std::memcpy(m_doiSEINuhLayerId, sei.m_doiSEINuhLayerId, sizeof(sei.m_doiSEINuhLayerId));
+  std::memcpy(m_doiSEIPartitionId, sei.m_doiSEIPartitionId, sizeof(sei.m_doiSEIPartitionId));
+  std::memcpy(m_doiSEIAlphaPresentFlag, sei.m_doiSEIAlphaPresentFlag, sizeof(sei.m_doiSEIAlphaPresentFlag));
+  std::memcpy(m_doiSEIAlphaNuhLayerId, sei.m_doiSEIAlphaNuhLayerId, sizeof(sei.m_doiSEIAlphaNuhLayerId));
+  std::memcpy(m_doiSEIAlphaPartitionId, sei.m_doiSEIAlphaPartitionId, sizeof(sei.m_doiSEIAlphaPartitionId));
+  std::memcpy(m_doiSEITopLeftX, sei.m_doiSEITopLeftX, sizeof(sei.m_doiSEITopLeftX));
+  std::memcpy(m_doiSEITopLeftY, sei.m_doiSEITopLeftY, sizeof(sei.m_doiSEITopLeftY));
+  std::memcpy(m_doiSEIWidthMinus1, sei.m_doiSEIWidthMinus1, sizeof(sei.m_doiSEIWidthMinus1));
+  std::memcpy(m_doiSEIHeightMinus1, sei.m_doiSEIHeightMinus1, sizeof(sei.m_doiSEIHeightMinus1));
+}
+#endif
+
 #if JVET_AI0182_BITDEPTH_RANGE_INFORMATION_SEI
 SEIBitdepthRangeInfo::SEIBitdepthRangeInfo(const SEIBitdepthRangeInfo& sei)
 {
diff --git a/source/Lib/CommonLib/SEI.h b/source/Lib/CommonLib/SEI.h
index fe14a64a60221699b3e039abb987a398a5fc6a1e..01f9ef39dbd8fe4ad761e5cd58c09a7899e79bd3 100644
--- a/source/Lib/CommonLib/SEI.h
+++ b/source/Lib/CommonLib/SEI.h
@@ -126,8 +126,11 @@ public:
 #if JVET_AH0164_QUALITY_METRIC_SEI
     QUALITY_METRIC, // payload_type value TBD
 #endif
+#if JVET_AI0181
+    DISPLAY_OVERLAYS_INFO,
+#endif 
 #if JVET_AI0182_BITDEPTH_RANGE_INFORMATION_SEI
-    BITDEPTH_RANGE_INFO, // payload_type value TBD
+    BITDEPTH_RANGE_INFO,   // payload_type value TBD
 #endif
   };
 
@@ -1609,6 +1612,9 @@ public:
     CR_EMPTY = 255
   };
 
+#if JVET_AI0181
+  uint8_t     m_layerId;
+#endif
   uint32_t    m_numRectsMinus1;
   bool        m_rectIdPresentFlag;
   uint8_t     m_rectIdLen;
@@ -1728,32 +1734,71 @@ public:
 };
 #endif
 
+#if JVET_AI0181
+class SEIDisplayOverlaysInfo : public SEI
+{
+public:
+  PayloadType payloadType() const { return PayloadType::DISPLAY_OVERLAYS_INFO; }
+  SEIDisplayOverlaysInfo()
+    : m_doiSEIId(false)
+    , m_doiSEICancelFlag(false)
+    , m_doiSEIPersistenceFlag(false)
+    , m_doiSEINumDisplayOverlaysMinus2(0)
+    , m_doiSEINuhLayerIdPresentFlag(false)
+    , m_doiSEIPicPartitionFlag(false)
+    , m_doiSEIPartitionTypeFlag(false)
+    , m_doiSEIPartitionIdLenMinus1(0)
+    , m_doiSEIOffsetParamsPresentFlag(false)
+    , m_doiSEIOffsetParamsLengthMinus1(0)
+  {}
+  SEIDisplayOverlaysInfo(const SEIDisplayOverlaysInfo& sei);
+
+  virtual ~SEIDisplayOverlaysInfo() {}
+  
+  uint32_t m_doiSEIId;
+  bool     m_doiSEICancelFlag;
+  bool     m_doiSEIPersistenceFlag;
+  uint32_t m_doiSEINumDisplayOverlaysMinus2;
+  bool     m_doiSEINuhLayerIdPresentFlag;
+  bool     m_doiSEITargetPicSizePresentFlag;
+  uint32_t m_doiSEITargetPicWidthMinus1;
+  uint32_t m_doiSEITargetPicHeightMinus1;
+  bool     m_doiSEIPicPartitionFlag;
+  bool     m_doiSEIPartitionTypeFlag;
+  uint32_t m_doiSEIPartitionIdLenMinus1;
+  bool     m_doiSEIOffsetParamsPresentFlag;
+  uint32_t m_doiSEIOffsetParamsLengthMinus1;
+  bool     m_doiSEIResamplingEnabledFlag;
+  uint32_t m_doiSEISizeParamLengthMinus1;
+  int      m_doiSEINuhLayerId[MAX_DISPLAY_OVERLAYS];
+  int      m_doiSEIPartitionId[MAX_DISPLAY_OVERLAYS];
+  int      m_doiSEIAlphaPresentFlag[MAX_DISPLAY_OVERLAYS];
+  int      m_doiSEIAlphaNuhLayerId[MAX_DISPLAY_OVERLAYS];
+  int      m_doiSEIAlphaPartitionId[MAX_DISPLAY_OVERLAYS];
+  int      m_doiSEITopLeftX[MAX_DISPLAY_OVERLAYS];
+  int      m_doiSEITopLeftY[MAX_DISPLAY_OVERLAYS];
+  int      m_doiSEIWidthMinus1[MAX_DISPLAY_OVERLAYS];
+  int      m_doiSEIHeightMinus1[MAX_DISPLAY_OVERLAYS];
+};
+#endif
+
 #if JVET_AI0182_BITDEPTH_RANGE_INFORMATION_SEI
 class SEIBitdepthRangeInfo : public SEI
 {
 public:
   PayloadType payloadType() const { return PayloadType::BITDEPTH_RANGE_INFO; }
 
-  SEIBitdepthRangeInfo()
-    : m_origBitDepthMinus1(9)
-    , m_numRangesMinus1(0)
-    , m_nuhLayerIdPresentFlag(false)
-    , m_picPartitionFlag(false)
-    , m_partitionTypeFlag(false)
-    , m_partitionIdLenMinus1(0)
-    , m_numBitsInRangeMinus1({9})
-    , m_bitOffset({0})
-  {}
+  SEIBitdepthRangeInfo() {}
   SEIBitdepthRangeInfo(const SEIBitdepthRangeInfo& sei);
 
   virtual ~SEIBitdepthRangeInfo() {}
 
-  uint32_t m_origBitDepthMinus1;
-  uint32_t m_numRangesMinus1;
-  bool m_nuhLayerIdPresentFlag;
-  bool m_picPartitionFlag;
-  bool m_partitionTypeFlag;
-  uint32_t m_partitionIdLenMinus1;
+  uint32_t              m_origBitDepthMinus1;
+  uint32_t              m_numRangesMinus1;
+  bool                  m_nuhLayerIdPresentFlag;
+  bool                  m_picPartitionFlag;
+  bool                  m_partitionTypeFlag;
+  uint32_t              m_partitionIdLenMinus1;
   std::vector<uint32_t> m_nuhLayerId;
   std::vector<uint32_t> m_partitionId;
   std::vector<uint32_t> m_numBitsInRangeMinus1;
diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h
index 13deb5ce29da61d59a7d014e03f79c447c15084f..012c8ed5f6b973ab3e27366c5bdec03da6c10b60 100644
--- a/source/Lib/CommonLib/TypeDef.h
+++ b/source/Lib/CommonLib/TypeDef.h
@@ -85,10 +85,13 @@
 
 #define JVET_AH0164_QUALITY_METRIC_SEI                    1
 
+#define JVET_AI0181   1   // JVET-AI0181: "AHG9: Display overlays information SEI"
+
 #define JVET_AI0182_BITDEPTH_RANGE_INFORMATION_SEI        1
 
 //########### place macros to be be kept below this line ###############
 
+
 #define GDR_ENABLED   1
 
 #if GDR_ENABLED
diff --git a/source/Lib/DecoderLib/SEIread.cpp b/source/Lib/DecoderLib/SEIread.cpp
index 5499dfc94b1293dbf23e8c84a816717a40ae463e..53ae3121380a2ae332f6908638ae4f6291fa563a 100644
--- a/source/Lib/DecoderLib/SEIread.cpp
+++ b/source/Lib/DecoderLib/SEIread.cpp
@@ -580,7 +580,11 @@ bool SEIReader::xReadSEImessage(SEIMessages& seis, const NalUnitType nalUnitType
 #if JVET_AH0162_CONSTITUENT_RECTANGLES
     case SEI::PayloadType::CONSTITUENT_RECTANGLES:
       sei = new SEIConstituentRectangles();
+#if JVET_AI0181
+      xParseSEIConstituentRectangles((SEIConstituentRectangles&) *sei,nuh_layer_id, payloadSize, pDecodedMessageOutputStream);
+#else
       xParseSEIConstituentRectangles((SEIConstituentRectangles&) *sei, payloadSize, pDecodedMessageOutputStream);
+#endif
       break;
 #endif
 #if JVET_AH0161_REGION_PACKING_INFORMATION_SEI
@@ -589,6 +593,12 @@ bool SEIReader::xReadSEImessage(SEIMessages& seis, const NalUnitType nalUnitType
       xParsePackedRegionsInfo((SEIPackedRegionsInfo &) *sei, payloadSize, pDecodedMessageOutputStream);
       break;
 #endif
+#if JVET_AI0181
+    case SEI::PayloadType::DISPLAY_OVERLAYS_INFO:
+      sei = new SEIDisplayOverlaysInfo;
+      xParseSEIDisplayOverlaysInfo((SEIDisplayOverlaysInfo&) *sei, payloadSize, pDecodedMessageOutputStream);
+      break;
+#endif
 #if JVET_AI0182_BITDEPTH_RANGE_INFORMATION_SEI
     case SEI::PayloadType::BITDEPTH_RANGE_INFO:
       sei = new SEIBitdepthRangeInfo;
@@ -3920,8 +3930,14 @@ void SEIReader::xParseSEIXmpMetadata(SEIXmpMetadata &sei, uint32_t payLoadSize,
 #endif
 
 #if JVET_AH0162_CONSTITUENT_RECTANGLES
+#if JVET_AI0181
+void SEIReader::xParseSEIConstituentRectangles(SEIConstituentRectangles& sei, int layerId, uint32_t payLoadSize,std::ostream* pDecodedMessageOutputStream)
+{
+  sei.m_layerId = layerId;
+#else
 void SEIReader::xParseSEIConstituentRectangles(SEIConstituentRectangles& sei, uint32_t payLoadSize, std::ostream* pDecodedMessageOutputStream)
 {
+#endif
   output_sei_message_header(sei, pDecodedMessageOutputStream, payLoadSize);
   uint32_t val;
   xReadCode(12, val, "cr_num_rects_minus1");
@@ -4270,6 +4286,129 @@ void SEIReader::xParseSEIQualityMetric(SEIQualityMetric& sei, uint32_t payLoadSi
 }
 #endif
 
+#if JVET_AI0181
+void SEIReader::xParseSEIDisplayOverlaysInfo(SEIDisplayOverlaysInfo& sei, uint32_t payloadSize,
+                                             std::ostream* pDecodedMessageOutputStream)
+{
+  uint32_t val;
+  output_sei_message_header(sei, pDecodedMessageOutputStream, payloadSize);
+
+  sei_read_code(pDecodedMessageOutputStream, 6, val, "doi_id");
+  sei.m_doiSEIId = val;
+
+  sei_read_flag(pDecodedMessageOutputStream, val, "doi_cancel_flag");
+  sei.m_doiSEICancelFlag = val;
+
+  if (!sei.m_doiSEICancelFlag)
+  {
+    sei_read_flag(pDecodedMessageOutputStream, val, "doi_persistence_flag");
+    sei.m_doiSEIPersistenceFlag = val;
+
+    sei_read_uvlc(pDecodedMessageOutputStream, val, "doi_num_display_overlays_minus2");
+    sei.m_doiSEINumDisplayOverlaysMinus2 = val;
+
+    sei_read_flag(pDecodedMessageOutputStream, val, "doi_nuh_layer_id_present_flag");
+    sei.m_doiSEINuhLayerIdPresentFlag = val;
+
+    sei_read_flag(pDecodedMessageOutputStream, val, "doi_target_pic_size_present_flag");
+    sei.m_doiSEITargetPicSizePresentFlag = val;
+
+    if (sei.m_doiSEITargetPicSizePresentFlag)
+    {
+      sei_read_code(pDecodedMessageOutputStream, 16, val, "doi_target_pic_width_minus1");
+      sei.m_doiSEITargetPicWidthMinus1 = val;
+
+      sei_read_code(pDecodedMessageOutputStream, 16, val, "doi_target_pic_height_minus1");
+      sei.m_doiSEITargetPicHeightMinus1 = val;
+    }
+
+    sei_read_flag(pDecodedMessageOutputStream, val, "doi_pic_partition_flag");
+    sei.m_doiSEIPicPartitionFlag = val;
+
+    if (sei.m_doiSEIPicPartitionFlag)
+    {
+      sei_read_flag(pDecodedMessageOutputStream, val, "doi_partition_type_flag");
+      sei.m_doiSEIPartitionTypeFlag = val;
+
+      sei_read_code(pDecodedMessageOutputStream, 4, val, "doi_partition_id_len_minus1");
+      sei.m_doiSEIPartitionIdLenMinus1 = val;
+    }
+
+    sei_read_flag(pDecodedMessageOutputStream, val, "doi_offset_params_present_flag");
+    sei.m_doiSEIOffsetParamsPresentFlag = val;
+
+    if (sei.m_doiSEIOffsetParamsPresentFlag)
+    {
+      sei_read_code(pDecodedMessageOutputStream, 4, val, "doi_offset_param_length_minus1");
+      sei.m_doiSEIOffsetParamsLengthMinus1 = val;
+    }
+
+    sei_read_flag(pDecodedMessageOutputStream, val, "doi_resampling_enabled_flag");
+    sei.m_doiSEIResamplingEnabledFlag = val;
+
+    if (sei.m_doiSEIResamplingEnabledFlag)
+    {
+      sei_read_code(pDecodedMessageOutputStream, 4, val, "doi_size_param_length_minus1");
+      sei.m_doiSEISizeParamLengthMinus1 = val;
+    }
+
+    for (int i = 0; i < sei.m_doiSEINumDisplayOverlaysMinus2 + 2; i++)
+    {
+      if (sei.m_doiSEINuhLayerIdPresentFlag)
+      {
+        sei_read_code(pDecodedMessageOutputStream, 6, val, "doi_nuh_layer_id[ i ]");
+        sei.m_doiSEINuhLayerId[i] = val;
+      }
+
+      if (sei.m_doiSEIPicPartitionFlag)
+      {
+        sei_read_uvlc(pDecodedMessageOutputStream, val, "doi_partition_id[ i ]");
+        sei.m_doiSEIPartitionId[i] = val;
+      }
+
+      sei_read_flag(pDecodedMessageOutputStream, val, "doi_alpha_present_flag[ i ]");
+      sei.m_doiSEIAlphaPresentFlag[i] = val;
+
+      if (sei.m_doiSEIAlphaPresentFlag[i])
+      {
+        if (sei.m_doiSEINuhLayerIdPresentFlag)
+        {
+          sei_read_code(pDecodedMessageOutputStream, 6, val, "doi_alpha_nuh_layer_id[ i ]");
+          sei.m_doiSEIAlphaNuhLayerId[i] = val;
+        }
+
+        if (sei.m_doiSEIPicPartitionFlag)
+        {
+          sei_read_uvlc(pDecodedMessageOutputStream, val, "doi_alpha_partition_id[ i ]");
+          sei.m_doiSEIAlphaPartitionId[i] = val;
+        }
+      }
+
+      if (i > 0)
+      {
+        if (sei.m_doiSEIOffsetParamsPresentFlag)
+        {
+          sei_read_uvlc(pDecodedMessageOutputStream, val, "doi_top_left_x[ i ]");
+          sei.m_doiSEITopLeftX[i] = val;
+
+          sei_read_uvlc(pDecodedMessageOutputStream, val, "doi_top_left_y[ i ]");
+          sei.m_doiSEITopLeftY[i] = val;
+        }
+
+        if (sei.m_doiSEIResamplingEnabledFlag)
+        {
+          sei_read_uvlc(pDecodedMessageOutputStream, val, "doi_width_minus1[ i ]");
+          sei.m_doiSEIWidthMinus1[i] = val;
+
+          sei_read_uvlc(pDecodedMessageOutputStream, val, "doi_height_minus1[ i ]");
+          sei.m_doiSEIHeightMinus1[i] = val;
+        }
+      }
+    }
+  }
+}
+#endif
+
 #if JVET_AI0182_BITDEPTH_RANGE_INFORMATION_SEI
 void SEIReader::xParseSEIBitdepthRangeInfo(SEIBitdepthRangeInfo& sei, const uint32_t nuhLayerId, uint32_t payLoadSize, std::ostream *pDecodedMessageOutputStream)
 {
diff --git a/source/Lib/DecoderLib/SEIread.h b/source/Lib/DecoderLib/SEIread.h
index f6f4d2c0cf633fcd41d126600410bd474165b05e..bc3ed52b74d1f07d569d8478069ef5c9ce243ec7 100644
--- a/source/Lib/DecoderLib/SEIread.h
+++ b/source/Lib/DecoderLib/SEIread.h
@@ -141,7 +141,15 @@ protected:
 #endif
 
 #if JVET_AH0162_CONSTITUENT_RECTANGLES
+#if JVET_AI0181
+  void xParseSEIConstituentRectangles(SEIConstituentRectangles& sei,int layerId, uint32_t payLoadSize,std::ostream* pDecodedMessageOutputStream);
+#else
   void xParseSEIConstituentRectangles(SEIConstituentRectangles& sei, uint32_t payLoadSize, std::ostream *pDecodedMessageOutputStream);
+  #endif
+#endif
+#if JVET_AI0181
+  void xParseSEIDisplayOverlaysInfo(SEIDisplayOverlaysInfo& sei, uint32_t payloadSize,
+                                    std::ostream* pDecodedMessageOutputStream);
 #endif
 
 #if JVET_AI0182_BITDEPTH_RANGE_INFORMATION_SEI
diff --git a/source/Lib/EncoderLib/EncCfg.h b/source/Lib/EncoderLib/EncCfg.h
index f38c90ee576f732d57073dbce745b3063f2e3ba0..d6edec90ccc71492b2b1f1b8fafc5a1258f012bb 100644
--- a/source/Lib/EncoderLib/EncCfg.h
+++ b/source/Lib/EncoderLib/EncCfg.h
@@ -1027,6 +1027,35 @@ protected:
   std::vector<std::array<uint32_t, 3>> m_qmSEIPicMetricValue;
 #endif
 
+#if JVET_AI0181
+  // Display overlays info
+  bool     m_doiSEIEnabled;
+  uint32_t m_doiSEIId;
+  bool     m_doiSEICancelFlag;
+  bool     m_doiSEIPersistenceFlag;
+  uint32_t m_doiSEINumDisplayOverlaysMinus2;
+  bool     m_doiSEINuhLayerIdPresentFlag;
+  bool     m_doiSEITargetPicSizePresentFlag;
+  uint32_t m_doiSEITargetPicWidthMinus1;
+  uint32_t m_doiSEITargetPicHeightMinus1;
+  bool     m_doiSEIPicPartitionFlag;
+  bool     m_doiSEIPartitionTypeFlag;
+  uint32_t m_doiSEIPartitionIdLenMinus1;
+  bool     m_doiSEIOffsetParamsPresentFlag;
+  uint32_t m_doiSEIOffsetParamsLengthMinus1;
+  bool     m_doiSEIResamplingEnabledFlag;
+  uint32_t m_doiSEISizeParamLengthMinus1;
+  int      m_doiSEINuhLayerId[MAX_DISPLAY_OVERLAYS];
+  int      m_doiSEIPartitionId[MAX_DISPLAY_OVERLAYS];
+  int      m_doiSEIAlphaPresentFlag[MAX_DISPLAY_OVERLAYS];
+  int      m_doiSEIAlphaNuhLayerId[MAX_DISPLAY_OVERLAYS];
+  int      m_doiSEIAlphaPartitionId[MAX_DISPLAY_OVERLAYS];
+  int      m_doiSEITopLeftX[MAX_DISPLAY_OVERLAYS];
+  int      m_doiSEITopLeftY[MAX_DISPLAY_OVERLAYS];
+  int      m_doiSEIWidthMinus1[MAX_DISPLAY_OVERLAYS];
+  int      m_doiSEIHeightMinus1[MAX_DISPLAY_OVERLAYS];
+#endif
+
 #if JVET_AI0182_BITDEPTH_RANGE_INFORMATION_SEI
   bool                  m_briSEIEnabled;
   uint32_t              m_briSEIOrigBitDepthMinus1;
@@ -2958,6 +2987,60 @@ public:
   void setQmSEIPicMetricValue(std::vector<std::array<uint32_t, 3>> b) { m_qmSEIPicMetricValue = b; }
 #endif
 
+#if JVET_AI0181
+  // Display overlays info
+  void     setDOISEIEnabled(bool b) { m_doiSEIEnabled = b; }
+  bool     getDOISEIEnabled() { return m_doiSEIEnabled; }
+  void     setDOISEIId(uint32_t v) { m_doiSEIId = v; }
+  uint32_t getDOISEIId() { return m_doiSEIId; }
+  void     setDOISEICancelFlag(bool b) { m_doiSEICancelFlag = b; }
+  bool     getDOISEICancelFlag() { return m_doiSEICancelFlag; }
+  void     setDOISEIPersistenceFlag(bool b) { m_doiSEIPersistenceFlag = b; }
+  bool     getDOISEIPersistenceFlag() { return m_doiSEIPersistenceFlag; }
+  void     setDOISEINumDisplayOverlaysMinus2(uint32_t v) { m_doiSEINumDisplayOverlaysMinus2 = v; }
+  uint32_t getDOISEINumDisplayOverlaysMinus2() { return m_doiSEINumDisplayOverlaysMinus2; }
+  void     setDOISEINuhLayerIdPresentFlag(bool b) { m_doiSEINuhLayerIdPresentFlag = b; }
+  bool     getDOISEINuhLayerIdPresentFlag() { return m_doiSEINuhLayerIdPresentFlag; }
+  void     setDOISEITargetPicSizePresentFlag(bool b) { m_doiSEITargetPicSizePresentFlag = b; }
+  bool     getDOISEITargetPicSizePresentFlag() { return m_doiSEITargetPicSizePresentFlag; }
+  void     setDOISEITargetPicWidthMinus1(uint32_t v) { m_doiSEITargetPicWidthMinus1 = v; }
+  uint32_t getDOISEITargetPicWidthMinus1() { return m_doiSEITargetPicWidthMinus1; }
+  void     setDOISEITargetPicHeightMinus1(uint32_t v) { m_doiSEITargetPicHeightMinus1 = v; }
+  uint32_t getDOISEITargetPicHeightMinus1() { return m_doiSEITargetPicHeightMinus1; }
+  void     setDOISEIPicPartitionFlag(bool b) { m_doiSEIPicPartitionFlag = b; }
+  bool     getDOISEIPicPartitionFlag() { return m_doiSEIPicPartitionFlag; }
+  void     setDOISEIPartitionTypeFlag(bool b) { m_doiSEIPartitionTypeFlag = b; }
+  bool     getDOISEIPartitionTypeFlag() { return m_doiSEIPartitionTypeFlag; }
+  void     setDOISEIPartitionIdLenMinus1(uint32_t v) { m_doiSEIPartitionIdLenMinus1 = v; }
+  uint32_t getDOISEIPartitionIdLenMinus1() { return m_doiSEIPartitionIdLenMinus1; }
+  void     setDOISEIOffsetParamsPresentFlag(bool b) { m_doiSEIOffsetParamsPresentFlag = b; }
+  bool     getDOISEIOffsetParamsPresentFlag() { return m_doiSEIOffsetParamsPresentFlag; }
+  void     setDOISEIOffsetParamsLengthMinus1(uint32_t v) { m_doiSEIOffsetParamsLengthMinus1 = v; }
+  uint32_t getDOISEIOffsetParamsLengthMinus1() { return m_doiSEIOffsetParamsLengthMinus1; }
+  void     setDOISEIResamplingEnabledFlag(bool b) { m_doiSEIResamplingEnabledFlag = b; }
+  bool     getDOISEIResamplingEnabledFlag() { return m_doiSEIResamplingEnabledFlag; }
+  void     setDOISEISizeParamLengthMinus1(uint32_t v) { m_doiSEISizeParamLengthMinus1 = v; }
+  uint32_t getDOISEISizeParamLengthMinus1() { return m_doiSEISizeParamLengthMinus1; }
+  void     setDOISEINuhLayerId(uint32_t v, int i) { m_doiSEINuhLayerId[i] = v; }
+  uint32_t getDOISEINuhLayerId(int i) { return m_doiSEINuhLayerId[i]; }
+  void     setDOISEIPartitionId(uint32_t v, int i) { m_doiSEIPartitionId[i] = v; }
+  uint32_t getDOISEIPartitionId(int i) { return m_doiSEIPartitionId[i]; }
+  void     setDOISEIAlphaPresentFlag(bool v, int i) { m_doiSEIAlphaPresentFlag[i] = v; }
+  bool     getDOISEIAlphaPresentFlag(int i) { return m_doiSEIAlphaPresentFlag[i]; }
+  void     setDOISEIAlphaNuhLayerId(uint32_t v, int i) { m_doiSEIAlphaNuhLayerId[i] = v; }
+  int      getDOISEIAlphaNuhLayerId(int i) { return m_doiSEIAlphaNuhLayerId[i]; }
+  void     setDOISEIAlphaPartitionId(int v, int i) { m_doiSEIAlphaPartitionId[i] = v; }
+  int      getDOISEIAlphaPartitionId(int i) { return m_doiSEIAlphaPartitionId[i]; }
+  void     setDOISEITopLeftX(int v, int i) { m_doiSEITopLeftX[i] = v; }
+  int      getDOISEITopLeftX(int i) { return m_doiSEITopLeftX[i]; }
+  void     setDOISEITopLeftY(int v, int i) { m_doiSEITopLeftY[i] = v; }
+  int      getDOISEITopLeftY(int i) { return m_doiSEITopLeftY[i]; }
+  void     setDOISEIWidthMinus1(int v, int i) { m_doiSEIWidthMinus1[i] = v; }
+  int      getDOISEIWidthMinus1(int i) { return m_doiSEIWidthMinus1[i]; }
+  void     setDOISEIHeightMinus1(int v, int i) { m_doiSEIHeightMinus1[i] = v; }
+  int      getDOISEIHeightMinus1(int i) { return m_doiSEIHeightMinus1[i]; }
+#endif
+
 #if JVET_AI0182_BITDEPTH_RANGE_INFORMATION_SEI
   bool getBriSEIEnabled() const { return m_briSEIEnabled; }
   void setBriSEIEnabled(bool b) { m_briSEIEnabled = b; }
diff --git a/source/Lib/EncoderLib/EncGOP.cpp b/source/Lib/EncoderLib/EncGOP.cpp
index f632242a375a43e3df0b163dddd80056b3624885..94b705e7be9296964ea99559708b04f9d4be93d2 100644
--- a/source/Lib/EncoderLib/EncGOP.cpp
+++ b/source/Lib/EncoderLib/EncGOP.cpp
@@ -1131,6 +1131,15 @@ void EncGOP::xCreatePerPictureSEIMessages (int picInGOP, SEIMessages& seiMessage
     seiMessages.push_back(jfifSEI);
   }
 #endif
+
+  #if JVET_AI0181
+  if (m_pcCfg->getDOISEIEnabled())
+  {
+    SEIDisplayOverlaysInfo* eoiSEI = new SEIDisplayOverlaysInfo;
+    m_seiEncoder.initSEIDisplayOverlaysInfo(eoiSEI);
+    seiMessages.push_back(eoiSEI);
+  }
+#endif
 }
 
 void EncGOP::xCreateNNPostFilterCharacteristicsSEIMessages(SEIMessages& seiMessages)
diff --git a/source/Lib/EncoderLib/SEIEncoder.cpp b/source/Lib/EncoderLib/SEIEncoder.cpp
index 27375bfcb7a45726994aa324b911d9bfcd35b53b..61fb7c2ffdd2c2e145c10b2826431559ea25e974 100644
--- a/source/Lib/EncoderLib/SEIEncoder.cpp
+++ b/source/Lib/EncoderLib/SEIEncoder.cpp
@@ -2058,6 +2058,106 @@ void SEIEncoder::initSEIPackedRegionsInfo(SEIPackedRegionsInfo* sei)
 }
 #endif
 
+#if JVET_AI0181
+
+void SEIEncoder::initSEIDisplayOverlaysInfo(SEIDisplayOverlaysInfo* sei)
+{
+  CHECK(!(m_isInitialized), "Unspecified error");
+  CHECK(!(sei != nullptr), "Unspecified error");
+  sei->m_doiSEIId         = m_pcCfg->getDOISEIId();
+  sei->m_doiSEICancelFlag = m_pcCfg->getDOISEICancelFlag();
+  if (!sei->m_doiSEICancelFlag)
+  {
+    sei->m_doiSEIPersistenceFlag = m_pcCfg->getDOISEIPersistenceFlag();
+
+    sei->m_doiSEINumDisplayOverlaysMinus2 = m_pcCfg->getDOISEINumDisplayOverlaysMinus2();
+
+    sei->m_doiSEINuhLayerIdPresentFlag = m_pcCfg->getDOISEINuhLayerIdPresentFlag();
+
+    sei->m_doiSEITargetPicSizePresentFlag = m_pcCfg->getDOISEITargetPicSizePresentFlag();
+
+    if (sei->m_doiSEITargetPicSizePresentFlag)
+    {
+      sei->m_doiSEITargetPicWidthMinus1 = m_pcCfg->getDOISEITargetPicWidthMinus1();
+
+      sei->m_doiSEITargetPicHeightMinus1 = m_pcCfg->getDOISEITargetPicHeightMinus1();
+    }
+
+    sei->m_doiSEIPicPartitionFlag = m_pcCfg->getDOISEIPicPartitionFlag();
+
+    CHECK((sei->m_doiSEINuhLayerIdPresentFlag == 0) && (sei->m_doiSEIPicPartitionFlag == 0),
+          "It is a requirement of bitstream conformance that at least one of doi_nuh_layer_id_present_flag or "
+          "doi_pic_partition_flag shall be equal to 1.");
+
+    if (sei->m_doiSEIPicPartitionFlag)
+    {
+      sei->m_doiSEIPartitionTypeFlag = m_pcCfg->getDOISEIPartitionTypeFlag();
+
+      sei->m_doiSEIPartitionIdLenMinus1 = m_pcCfg->getDOISEIPartitionIdLenMinus1();
+    }
+
+    sei->m_doiSEIOffsetParamsPresentFlag = m_pcCfg->getDOISEIOffsetParamsPresentFlag();
+
+    if (sei->m_doiSEIOffsetParamsPresentFlag)
+    {
+      sei->m_doiSEIOffsetParamsLengthMinus1 = m_pcCfg->getDOISEIOffsetParamsLengthMinus1();
+    }
+
+    sei->m_doiSEIResamplingEnabledFlag = m_pcCfg->getDOISEIResamplingEnabledFlag();
+
+    if (sei->m_doiSEIResamplingEnabledFlag)
+    {
+      sei->m_doiSEISizeParamLengthMinus1 = m_pcCfg->getDOISEISizeParamLengthMinus1();
+    }
+
+    for (int i = 0; i < sei->m_doiSEINumDisplayOverlaysMinus2 + 2; i++)
+    {
+      if (sei->m_doiSEINuhLayerIdPresentFlag)
+      {
+        sei->m_doiSEINuhLayerId[i] = m_pcCfg->getDOISEINuhLayerId(i);
+      }
+
+      if (sei->m_doiSEIPicPartitionFlag)
+      {
+        sei->m_doiSEIPartitionId[i] = m_pcCfg->getDOISEIPartitionId(i);
+      }
+
+      sei->m_doiSEIAlphaPresentFlag[i] = m_pcCfg->getDOISEIAlphaPresentFlag(i);
+
+      if (sei->m_doiSEIAlphaPresentFlag[i])
+      {
+        if (sei->m_doiSEINuhLayerIdPresentFlag)
+        {
+          sei->m_doiSEIAlphaNuhLayerId[i] = m_pcCfg->getDOISEIAlphaNuhLayerId(i);
+        }
+
+        if (sei->m_doiSEIPicPartitionFlag)
+        {
+          sei->m_doiSEIAlphaPartitionId[i] = m_pcCfg->getDOISEIAlphaPartitionId(i);
+        }
+      }
+
+      if (i > 0)
+      {
+        if (sei->m_doiSEIOffsetParamsPresentFlag)
+        {
+          sei->m_doiSEITopLeftX[i] = m_pcCfg->getDOISEITopLeftX(i);
+
+          sei->m_doiSEITopLeftY[i] = m_pcCfg->getDOISEITopLeftY(i);
+        }
+
+        if (sei->m_doiSEIResamplingEnabledFlag)
+        {
+          sei->m_doiSEIWidthMinus1[i] = m_pcCfg->getDOISEIWidthMinus1(i);
+
+          sei->m_doiSEIHeightMinus1[i] = m_pcCfg->getDOISEIHeightMinus1(i);
+        }
+      }
+    }
+  }
+}
+#endif
+
 #if JVET_AI0182_BITDEPTH_RANGE_INFORMATION_SEI
 void SEIEncoder::initSEIBitdepthRangeInfo(SEIBitdepthRangeInfo* sei)
 {
diff --git a/source/Lib/EncoderLib/SEIEncoder.h b/source/Lib/EncoderLib/SEIEncoder.h
index 5fd894e856066c8c7ba964ce9c1be104c20115cf..6d9bfbf56035c9e371721bfbe8b8f1df81fcc630 100644
--- a/source/Lib/EncoderLib/SEIEncoder.h
+++ b/source/Lib/EncoderLib/SEIEncoder.h
@@ -130,6 +130,9 @@ public:
 #if JVET_AH0164_QUALITY_METRIC_SEI
   void initSEIQualityMetric(SEIQualityMetric *sei);
 #endif
+#if JVET_AI0181
+  void initSEIDisplayOverlaysInfo(SEIDisplayOverlaysInfo* sei);
+#endif
 #if JVET_AI0182_BITDEPTH_RANGE_INFORMATION_SEI
   void initSEIBitdepthRangeInfo(SEIBitdepthRangeInfo *sei);
 #endif
diff --git a/source/Lib/EncoderLib/SEIwrite.cpp b/source/Lib/EncoderLib/SEIwrite.cpp
index f4981b81cf4a7eb7a2b698372e3aece6e0739270..c2c5a0d9fac599168d30029b552c91865d09bed4 100644
--- a/source/Lib/EncoderLib/SEIwrite.cpp
+++ b/source/Lib/EncoderLib/SEIwrite.cpp
@@ -198,6 +198,11 @@ void SEIWriter::xWriteSEIpayloadData(OutputBitstream &bs, const SEI &sei, HRD &h
     xWriteSEIQualityMetric(*static_cast<const SEIQualityMetric *>(&sei));
     break;
 #endif
+#if JVET_AI0181
+  case SEI::PayloadType::DISPLAY_OVERLAYS_INFO:
+    xWriteSEIDisplayOverlaysInfo(*static_cast<const SEIDisplayOverlaysInfo*>(&sei));
+    break;
+#endif
 #if JVET_AF0167_MULTI_PLANE_IMAGE_INFO_SEI
   case SEI::PayloadType::MULTIPLANE_IMAGE_INFO:
     xWriteSEIMultiplaneImageInfo(*static_cast<const SEIMultiplaneImageInfo*>(&sei));
@@ -2388,4 +2393,98 @@ void SEIWriter::xWriteSEIBitdepthRangeInfo(const SEIBitdepthRangeInfo& sei)
 }
 #endif
 
+#if JVET_AI0181
+void SEIWriter::xWriteSEIDisplayOverlaysInfo(const SEIDisplayOverlaysInfo& sei)
+{
+  xWriteCode(sei.m_doiSEIId, 6, "doi_id");
+
+  xWriteFlag(sei.m_doiSEICancelFlag, "doi_cancel_flag");
+
+  if (!sei.m_doiSEICancelFlag)
+  {
+    xWriteFlag(sei.m_doiSEIPersistenceFlag, "doi_persistence_flag");
+
+    xWriteUvlc(sei.m_doiSEINumDisplayOverlaysMinus2, "doi_num_display_overlays_minus2");
+
+    xWriteFlag(sei.m_doiSEINuhLayerIdPresentFlag, "doi_nuh_layer_id_present_flag");
+
+    xWriteFlag(sei.m_doiSEITargetPicSizePresentFlag, "doi_target_pic_size_present_flag");
+
+    if (sei.m_doiSEITargetPicSizePresentFlag)
+    {
+      xWriteCode(sei.m_doiSEITargetPicWidthMinus1, 16, "doi_target_pic_width_minus1");
+
+      xWriteCode(sei.m_doiSEITargetPicHeightMinus1, 16, "doi_target_pic_height_minus1");
+    }
+
+    xWriteFlag(sei.m_doiSEIPicPartitionFlag, "doi_pic_partition_flag");
+
+    if (sei.m_doiSEIPicPartitionFlag)
+    {
+      xWriteFlag(sei.m_doiSEIPartitionTypeFlag, "doi_partition_type_flag");
+
+      xWriteCode(sei.m_doiSEIPartitionIdLenMinus1, 4, "doi_partition_id_len_minus1");
+    }
+
+    xWriteFlag(sei.m_doiSEIOffsetParamsPresentFlag, "doi_offset_params_present_flag");
+
+    if (sei.m_doiSEIOffsetParamsPresentFlag)
+    {
+      xWriteCode(sei.m_doiSEIOffsetParamsLengthMinus1, 4, "doi_offset_param_length_minus1");
+    }
+
+    xWriteFlag(sei.m_doiSEIResamplingEnabledFlag, "doi_resampling_enabled_flag");
+
+    if (sei.m_doiSEIResamplingEnabledFlag)
+    {
+      xWriteCode(sei.m_doiSEISizeParamLengthMinus1, 4, "doi_size_param_length_minus1");
+    }
+
+    for (int i = 0; i < sei.m_doiSEINumDisplayOverlaysMinus2 + 2; i++)
+    {
+      if (sei.m_doiSEINuhLayerIdPresentFlag)
+      {
+        xWriteCode(sei.m_doiSEINuhLayerId[i], 6, "doi_nuh_layer_id[ i ]");
+      }
+
+      if (sei.m_doiSEIPicPartitionFlag)
+      {
+        xWriteUvlc(sei.m_doiSEIPartitionId[i], "doi_partition_id[ i ]");
+      }
+
+      xWriteFlag(sei.m_doiSEIAlphaPresentFlag[i], "doi_alpha_present_flag[ i ]");
+
+      if (sei.m_doiSEIAlphaPresentFlag[i])
+      {
+        if (sei.m_doiSEINuhLayerIdPresentFlag)
+        {
+          xWriteCode(sei.m_doiSEIAlphaNuhLayerId[i], 6, "doi_alpha_nuh_layer_id[ i ]");
+        }
+
+        if (sei.m_doiSEIPicPartitionFlag)
+        {
+          xWriteUvlc(sei.m_doiSEIAlphaPartitionId[i], "doi_alpha_partition_id[ i ]");
+        }
+      }
+
+      if (i > 0)
+      {
+        if (sei.m_doiSEIOffsetParamsPresentFlag)
+        {
+          xWriteUvlc(sei.m_doiSEITopLeftX[i], "doi_top_left_x[ i ]");
+
+          xWriteUvlc(sei.m_doiSEITopLeftY[i], "doi_top_left_y[ i ]");
+        }
+
+        if (sei.m_doiSEIResamplingEnabledFlag)
+        {
+          xWriteUvlc(sei.m_doiSEIWidthMinus1[i], "doi_width_minus1[ i ]");
+
+          xWriteUvlc(sei.m_doiSEIHeightMinus1[i], "doi_height_minus1[ i ]");
+        }
+      }
+    }
+  }
+}
+#endif
 //! \}
diff --git a/source/Lib/EncoderLib/SEIwrite.h b/source/Lib/EncoderLib/SEIwrite.h
index b33b8f457ee52a31d30bc0aa80283c83c987ff54..4cbebc81af8e349f82ae9bdd22d3a7e1f18c3b8b 100644
--- a/source/Lib/EncoderLib/SEIwrite.h
+++ b/source/Lib/EncoderLib/SEIwrite.h
@@ -138,6 +138,9 @@ protected:
 #if JVET_AH0164_QUALITY_METRIC_SEI
   void xWriteSEIQualityMetric(const SEIQualityMetric& sei);
 #endif
+#if JVET_AI0181
+  void xWriteSEIDisplayOverlaysInfo(const SEIDisplayOverlaysInfo& sei);
+#endif
 #if JVET_AI0182_BITDEPTH_RANGE_INFORMATION_SEI
   void xWriteSEIBitdepthRangeInfo(const SEIBitdepthRangeInfo& sei);
 #endif