From d4801363157a446794d661a4a9abfc81fadce317 Mon Sep 17 00:00:00 2001
From: Jeeva Raj A <jeeva.raj@ittiam.com>
Date: Fri, 13 May 2022 19:55:06 +0000
Subject: [PATCH] JVET-Z0120: SII SEI support and illustration of use case
 "Backwards-compatible HFR video"

---
 cfg/sei_vui/shutter_interval_info.cfg         |   7 +
 ...hutter_interval_info_mul_120fps_SA_180.cfg |   6 +
 ...hutter_interval_info_mul_120fps_SA_360.cfg |   6 +
 ...shutter_interval_info_mul_120fps_SA_90.cfg |   6 +
 ...shutter_interval_info_mul_60fps_SA_180.cfg |   6 +
 ...shutter_interval_info_mul_60fps_SA_360.cfg |   6 +
 .../shutter_interval_info_mul_60fps_SA_90.cfg |   6 +
 ...hutter_interval_info_mul_120fps_SA_180.cfg |   6 +
 ...hutter_interval_info_mul_120fps_SA_360.cfg |   6 +
 ...shutter_interval_info_mul_120fps_SA_90.cfg |   6 +
 ...shutter_interval_info_mul_60fps_SA_180.cfg |   6 +
 ...shutter_interval_info_mul_60fps_SA_360.cfg |   6 +
 .../shutter_interval_info_mul_60fps_SA_90.cfg |   6 +
 cfg/sei_vui/shutter_interval_info_fix.cfg     |   5 +
 .../shutter_interval_info_mul_gop16.cfg       |   6 +
 .../shutter_interval_info_mul_gop32.cfg       |   6 +
 doc/software-manual.tex                       |  15 +
 source/App/DecoderApp/DecApp.cpp              | 240 +++++++++++++++-
 source/App/DecoderApp/DecApp.h                |  22 ++
 source/App/DecoderApp/DecAppCfg.cpp           |   3 +
 source/App/DecoderApp/DecAppCfg.h             |   3 +
 source/App/EncoderApp/EncApp.cpp              |  30 ++
 source/App/EncoderApp/EncApp.h                |   3 +
 source/App/EncoderApp/EncAppCfg.cpp           | 106 ++++++++
 source/App/EncoderApp/EncAppCfg.h             |  15 +
 source/Lib/CommonLib/CodingStructure.h        |   3 +
 source/Lib/CommonLib/CommonDef.h              |   7 +
 source/Lib/CommonLib/Picture.cpp              | 257 ++++++++++++++++++
 source/Lib/CommonLib/Picture.h                |  17 ++
 source/Lib/CommonLib/SEI.cpp                  |   3 +
 source/Lib/CommonLib/SEI.h                    |  19 ++
 source/Lib/CommonLib/Slice.cpp                |   4 +
 source/Lib/CommonLib/TypeDef.h                |   7 +
 source/Lib/DecoderLib/DecLib.cpp              |  21 +-
 source/Lib/DecoderLib/DecLib.h                |   8 +
 source/Lib/DecoderLib/SEIread.cpp             |  31 +++
 source/Lib/DecoderLib/SEIread.h               |   3 +
 source/Lib/EncoderLib/EncCfg.h                |  32 +++
 source/Lib/EncoderLib/EncGOP.cpp              |   8 +
 source/Lib/EncoderLib/EncLib.cpp              |  37 ++-
 source/Lib/EncoderLib/SEIEncoder.cpp          |  22 ++
 source/Lib/EncoderLib/SEIEncoder.h            |   3 +
 source/Lib/EncoderLib/SEIwrite.cpp            |  25 ++
 source/Lib/EncoderLib/SEIwrite.h              |   3 +
 44 files changed, 1036 insertions(+), 7 deletions(-)
 create mode 100644 cfg/sei_vui/shutter_interval_info.cfg
 create mode 100644 cfg/sei_vui/shutter_interval_info_GOP16/shutter_interval_info_mul_120fps_SA_180.cfg
 create mode 100644 cfg/sei_vui/shutter_interval_info_GOP16/shutter_interval_info_mul_120fps_SA_360.cfg
 create mode 100644 cfg/sei_vui/shutter_interval_info_GOP16/shutter_interval_info_mul_120fps_SA_90.cfg
 create mode 100644 cfg/sei_vui/shutter_interval_info_GOP16/shutter_interval_info_mul_60fps_SA_180.cfg
 create mode 100644 cfg/sei_vui/shutter_interval_info_GOP16/shutter_interval_info_mul_60fps_SA_360.cfg
 create mode 100644 cfg/sei_vui/shutter_interval_info_GOP16/shutter_interval_info_mul_60fps_SA_90.cfg
 create mode 100644 cfg/sei_vui/shutter_interval_info_GOP32/shutter_interval_info_mul_120fps_SA_180.cfg
 create mode 100644 cfg/sei_vui/shutter_interval_info_GOP32/shutter_interval_info_mul_120fps_SA_360.cfg
 create mode 100644 cfg/sei_vui/shutter_interval_info_GOP32/shutter_interval_info_mul_120fps_SA_90.cfg
 create mode 100644 cfg/sei_vui/shutter_interval_info_GOP32/shutter_interval_info_mul_60fps_SA_180.cfg
 create mode 100644 cfg/sei_vui/shutter_interval_info_GOP32/shutter_interval_info_mul_60fps_SA_360.cfg
 create mode 100644 cfg/sei_vui/shutter_interval_info_GOP32/shutter_interval_info_mul_60fps_SA_90.cfg
 create mode 100644 cfg/sei_vui/shutter_interval_info_fix.cfg
 create mode 100644 cfg/sei_vui/shutter_interval_info_mul_gop16.cfg
 create mode 100644 cfg/sei_vui/shutter_interval_info_mul_gop32.cfg

diff --git a/cfg/sei_vui/shutter_interval_info.cfg b/cfg/sei_vui/shutter_interval_info.cfg
new file mode 100644
index 000000000..c12f050b6
--- /dev/null
+++ b/cfg/sei_vui/shutter_interval_info.cfg
@@ -0,0 +1,7 @@
+#======== Shutter Interval Info SEI message =====================
+SEIShutterIntervalEnabled                : 1
+SEISiiTimeScale                          : 27000000
+SEISiiInputNumUnitsInShutterInterval     : 1080000   # should have at least one entry. if only one entry, the value is assigned to sii_num_units_in_shutter_interval, 
+                                                     # if multiple entries, the values are set to sub_layer_num_units_in_shutter_interval[ ]
+
+													 
\ No newline at end of file
diff --git a/cfg/sei_vui/shutter_interval_info_GOP16/shutter_interval_info_mul_120fps_SA_180.cfg b/cfg/sei_vui/shutter_interval_info_GOP16/shutter_interval_info_mul_120fps_SA_180.cfg
new file mode 100644
index 000000000..93ea8ec9b
--- /dev/null
+++ b/cfg/sei_vui/shutter_interval_info_GOP16/shutter_interval_info_mul_120fps_SA_180.cfg
@@ -0,0 +1,6 @@
+#======== Shutter Interval Info SEI message =====================
+SEIShutterIntervalEnabled                : 1
+SEISiiTimeScale                          : 24000000
+SEISiiInputNumUnitsInShutterInterval     : 200000 200000 200000 200000 100000   	# multiple shutter intervals: multiple entries, the values are set to sub_layer_num_units_in_shutter_interval[ ].
+																					# here is one example with frame rate=120fps, encoder derives the actually values based on picture frame rate.
+																					# HFR_fps = 120, SFR_fps = 60 and shutterAngle = 180
\ No newline at end of file
diff --git a/cfg/sei_vui/shutter_interval_info_GOP16/shutter_interval_info_mul_120fps_SA_360.cfg b/cfg/sei_vui/shutter_interval_info_GOP16/shutter_interval_info_mul_120fps_SA_360.cfg
new file mode 100644
index 000000000..ececa5613
--- /dev/null
+++ b/cfg/sei_vui/shutter_interval_info_GOP16/shutter_interval_info_mul_120fps_SA_360.cfg
@@ -0,0 +1,6 @@
+#======== Shutter Interval Info SEI message =====================
+SEIShutterIntervalEnabled                : 1
+SEISiiTimeScale                          : 24000000
+SEISiiInputNumUnitsInShutterInterval     : 400000 400000 400000 400000 200000   	# multiple shutter intervals: multiple entries, the values are set to sub_layer_num_units_in_shutter_interval[ ].
+																					# here is one example with frame rate=120fps, encoder derives the actually values based on picture frame rate.
+																					# HFR_fps = 120, SFR_fps = 60 and shutterAngle = 360
\ No newline at end of file
diff --git a/cfg/sei_vui/shutter_interval_info_GOP16/shutter_interval_info_mul_120fps_SA_90.cfg b/cfg/sei_vui/shutter_interval_info_GOP16/shutter_interval_info_mul_120fps_SA_90.cfg
new file mode 100644
index 000000000..1e52eaeed
--- /dev/null
+++ b/cfg/sei_vui/shutter_interval_info_GOP16/shutter_interval_info_mul_120fps_SA_90.cfg
@@ -0,0 +1,6 @@
+#======== Shutter Interval Info SEI message =====================
+SEIShutterIntervalEnabled                : 1
+SEISiiTimeScale                          : 24000000
+SEISiiInputNumUnitsInShutterInterval     : 100000 100000 100000 100000 50000    	# multiple shutter intervals: multiple entries, the values are set to sub_layer_num_units_in_shutter_interval[ ].
+																					# here is one example with frame rate=120fps, encoder derives the actually values based on picture frame rate.
+																					# HFR_fps = 120, SFR_fps = 60 and shutterAngle = 90
\ No newline at end of file
diff --git a/cfg/sei_vui/shutter_interval_info_GOP16/shutter_interval_info_mul_60fps_SA_180.cfg b/cfg/sei_vui/shutter_interval_info_GOP16/shutter_interval_info_mul_60fps_SA_180.cfg
new file mode 100644
index 000000000..07d7f0f1c
--- /dev/null
+++ b/cfg/sei_vui/shutter_interval_info_GOP16/shutter_interval_info_mul_60fps_SA_180.cfg
@@ -0,0 +1,6 @@
+#======== Shutter Interval Info SEI message =====================
+SEIShutterIntervalEnabled                : 1
+SEISiiTimeScale                          : 24000000
+SEISiiInputNumUnitsInShutterInterval     : 400000 400000 400000 400000 200000   	# multiple shutter intervals: multiple entries, the values are set to sub_layer_num_units_in_shutter_interval[ ].
+																					# here is one example with frame rate=60fps, encoder derives the actually values based on picture frame rate.
+																					# HFR_fps = 60, SFR_fps = 30 and shutterAngle = 180
\ No newline at end of file
diff --git a/cfg/sei_vui/shutter_interval_info_GOP16/shutter_interval_info_mul_60fps_SA_360.cfg b/cfg/sei_vui/shutter_interval_info_GOP16/shutter_interval_info_mul_60fps_SA_360.cfg
new file mode 100644
index 000000000..931f2551c
--- /dev/null
+++ b/cfg/sei_vui/shutter_interval_info_GOP16/shutter_interval_info_mul_60fps_SA_360.cfg
@@ -0,0 +1,6 @@
+#======== Shutter Interval Info SEI message =====================
+SEIShutterIntervalEnabled                : 1
+SEISiiTimeScale                          : 24000000
+SEISiiInputNumUnitsInShutterInterval     : 800000 800000 800000 800000 400000   	# multiple shutter intervals: multiple entries, the values are set to sub_layer_num_units_in_shutter_interval[ ].
+																					# here is one example with frame rate=60fps, encoder derives the actually values based on picture frame rate.
+																					# HFR_fps = 60, SFR_fps = 30 and shutterAngle = 360
\ No newline at end of file
diff --git a/cfg/sei_vui/shutter_interval_info_GOP16/shutter_interval_info_mul_60fps_SA_90.cfg b/cfg/sei_vui/shutter_interval_info_GOP16/shutter_interval_info_mul_60fps_SA_90.cfg
new file mode 100644
index 000000000..7e3d93462
--- /dev/null
+++ b/cfg/sei_vui/shutter_interval_info_GOP16/shutter_interval_info_mul_60fps_SA_90.cfg
@@ -0,0 +1,6 @@
+#======== Shutter Interval Info SEI message =====================
+SEIShutterIntervalEnabled                : 1
+SEISiiTimeScale                          : 24000000
+SEISiiInputNumUnitsInShutterInterval     : 200000 200000 200000 200000 100000   	# multiple shutter intervals: multiple entries, the values are set to sub_layer_num_units_in_shutter_interval[ ].
+																					# here is one example with frame rate=60fps, encoder derives the actually values based on picture frame rate.
+																					# HFR_fps = 60, SFR_fps = 30 and shutterAngle = 90
\ No newline at end of file
diff --git a/cfg/sei_vui/shutter_interval_info_GOP32/shutter_interval_info_mul_120fps_SA_180.cfg b/cfg/sei_vui/shutter_interval_info_GOP32/shutter_interval_info_mul_120fps_SA_180.cfg
new file mode 100644
index 000000000..598da8d1b
--- /dev/null
+++ b/cfg/sei_vui/shutter_interval_info_GOP32/shutter_interval_info_mul_120fps_SA_180.cfg
@@ -0,0 +1,6 @@
+#======== Shutter Interval Info SEI message =====================
+SEIShutterIntervalEnabled                : 1
+SEISiiTimeScale                          : 24000000
+SEISiiInputNumUnitsInShutterInterval     : 200000 200000 200000 200000 200000 100000   	# multiple shutter intervals: multiple entries, the values are set to sub_layer_num_units_in_shutter_interval[ ].
+																					# here is one example with frame rate=120fps, encoder derives the actually values based on picture frame rate.
+																					# HFR_fps = 120, SFR_fps = 60 and shutterAngle = 180
\ No newline at end of file
diff --git a/cfg/sei_vui/shutter_interval_info_GOP32/shutter_interval_info_mul_120fps_SA_360.cfg b/cfg/sei_vui/shutter_interval_info_GOP32/shutter_interval_info_mul_120fps_SA_360.cfg
new file mode 100644
index 000000000..ce1386ab4
--- /dev/null
+++ b/cfg/sei_vui/shutter_interval_info_GOP32/shutter_interval_info_mul_120fps_SA_360.cfg
@@ -0,0 +1,6 @@
+#======== Shutter Interval Info SEI message =====================
+SEIShutterIntervalEnabled                : 1
+SEISiiTimeScale                          : 24000000
+SEISiiInputNumUnitsInShutterInterval     : 400000 400000 400000 400000 400000 200000   	# multiple shutter intervals: multiple entries, the values are set to sub_layer_num_units_in_shutter_interval[ ].
+																					# here is one example with frame rate=120fps, encoder derives the actually values based on picture frame rate.
+																					# HFR_fps = 120, SFR_fps = 60 and shutterAngle = 360
\ No newline at end of file
diff --git a/cfg/sei_vui/shutter_interval_info_GOP32/shutter_interval_info_mul_120fps_SA_90.cfg b/cfg/sei_vui/shutter_interval_info_GOP32/shutter_interval_info_mul_120fps_SA_90.cfg
new file mode 100644
index 000000000..b7c0ea51c
--- /dev/null
+++ b/cfg/sei_vui/shutter_interval_info_GOP32/shutter_interval_info_mul_120fps_SA_90.cfg
@@ -0,0 +1,6 @@
+#======== Shutter Interval Info SEI message =====================
+SEIShutterIntervalEnabled                : 1
+SEISiiTimeScale                          : 24000000
+SEISiiInputNumUnitsInShutterInterval     : 100000 100000 100000 100000 100000 50000    	# multiple shutter intervals: multiple entries, the values are set to sub_layer_num_units_in_shutter_interval[ ].
+																					# here is one example with frame rate=120fps, encoder derives the actually values based on picture frame rate.
+																					# HFR_fps = 120, SFR_fps = 60 and shutterAngle = 90
\ No newline at end of file
diff --git a/cfg/sei_vui/shutter_interval_info_GOP32/shutter_interval_info_mul_60fps_SA_180.cfg b/cfg/sei_vui/shutter_interval_info_GOP32/shutter_interval_info_mul_60fps_SA_180.cfg
new file mode 100644
index 000000000..5a5fe7025
--- /dev/null
+++ b/cfg/sei_vui/shutter_interval_info_GOP32/shutter_interval_info_mul_60fps_SA_180.cfg
@@ -0,0 +1,6 @@
+#======== Shutter Interval Info SEI message =====================
+SEIShutterIntervalEnabled                : 1
+SEISiiTimeScale                          : 24000000
+SEISiiInputNumUnitsInShutterInterval     : 400000 400000 400000 400000 400000 200000   	# multiple shutter intervals: multiple entries, the values are set to sub_layer_num_units_in_shutter_interval[ ].
+																					# here is one example with frame rate=60fps, encoder derives the actually values based on picture frame rate.
+																					# HFR_fps = 60, SFR_fps = 30 and shutterAngle = 180
\ No newline at end of file
diff --git a/cfg/sei_vui/shutter_interval_info_GOP32/shutter_interval_info_mul_60fps_SA_360.cfg b/cfg/sei_vui/shutter_interval_info_GOP32/shutter_interval_info_mul_60fps_SA_360.cfg
new file mode 100644
index 000000000..7e090f079
--- /dev/null
+++ b/cfg/sei_vui/shutter_interval_info_GOP32/shutter_interval_info_mul_60fps_SA_360.cfg
@@ -0,0 +1,6 @@
+#======== Shutter Interval Info SEI message =====================
+SEIShutterIntervalEnabled                : 1
+SEISiiTimeScale                          : 24000000
+SEISiiInputNumUnitsInShutterInterval     : 800000 800000 800000 800000 800000 400000   	# multiple shutter intervals: multiple entries, the values are set to sub_layer_num_units_in_shutter_interval[ ].
+																					# here is one example with frame rate=60fps, encoder derives the actually values based on picture frame rate.
+																					# HFR_fps = 60, SFR_fps = 30 and shutterAngle = 360
\ No newline at end of file
diff --git a/cfg/sei_vui/shutter_interval_info_GOP32/shutter_interval_info_mul_60fps_SA_90.cfg b/cfg/sei_vui/shutter_interval_info_GOP32/shutter_interval_info_mul_60fps_SA_90.cfg
new file mode 100644
index 000000000..ce4b38ca1
--- /dev/null
+++ b/cfg/sei_vui/shutter_interval_info_GOP32/shutter_interval_info_mul_60fps_SA_90.cfg
@@ -0,0 +1,6 @@
+#======== Shutter Interval Info SEI message =====================
+SEIShutterIntervalEnabled                : 1
+SEISiiTimeScale                          : 24000000
+SEISiiInputNumUnitsInShutterInterval     : 200000 200000 200000 200000 200000 100000   	# multiple shutter intervals: multiple entries, the values are set to sub_layer_num_units_in_shutter_interval[ ].
+																					# here is one example with frame rate=60fps, encoder derives the actually values based on picture frame rate.
+																					# HFR_fps = 60, SFR_fps = 30 and shutterAngle = 90
\ No newline at end of file
diff --git a/cfg/sei_vui/shutter_interval_info_fix.cfg b/cfg/sei_vui/shutter_interval_info_fix.cfg
new file mode 100644
index 000000000..03178caec
--- /dev/null
+++ b/cfg/sei_vui/shutter_interval_info_fix.cfg
@@ -0,0 +1,5 @@
+#======== Shutter Interval Info SEI message =====================
+SEIShutterIntervalEnabled                : 1
+SEISiiTimeScale                          : 24000000
+SEISiiInputNumUnitsInShutterInterval     : 200000   	# fixed shutter interval: only one entry, the value is assigned to sii_num_units_in_shutter_interval.
+														# here is one example with frame rate=120fps, encoder derives the actually value based on frame rate.
diff --git a/cfg/sei_vui/shutter_interval_info_mul_gop16.cfg b/cfg/sei_vui/shutter_interval_info_mul_gop16.cfg
new file mode 100644
index 000000000..b5c4e008b
--- /dev/null
+++ b/cfg/sei_vui/shutter_interval_info_mul_gop16.cfg
@@ -0,0 +1,6 @@
+#======== Shutter Interval Info SEI message =====================
+SEIShutterIntervalEnabled                : 1
+SEISiiTimeScale                          : 24000000
+SEISiiInputNumUnitsInShutterInterval     : 400000 400000 400000 400000 200000   	# multiple shutter intervals: multiple entries, the values are set to sub_layer_num_units_in_shutter_interval[ ].
+																					# here is one example with frame rate=120fps, encoder derives the actually values based on picture frame rate.
+													 
\ No newline at end of file
diff --git a/cfg/sei_vui/shutter_interval_info_mul_gop32.cfg b/cfg/sei_vui/shutter_interval_info_mul_gop32.cfg
new file mode 100644
index 000000000..e1fc71a8b
--- /dev/null
+++ b/cfg/sei_vui/shutter_interval_info_mul_gop32.cfg
@@ -0,0 +1,6 @@
+#======== Shutter Interval Info SEI message =====================
+SEIShutterIntervalEnabled                : 1
+SEISiiTimeScale                          : 24000000
+SEISiiInputNumUnitsInShutterInterval     : 400000 400000 400000 400000 400000 200000   	# multiple shutter intervals: multiple entries, the values are set to sub_layer_num_units_in_shutter_interval[ ].
+																					# here is one example with frame rate=120fps, encoder derives the actually values based on picture frame rate.
+													 
\ No newline at end of file
diff --git a/doc/software-manual.tex b/doc/software-manual.tex
index 2ab8c09e2..1b9d77d28 100644
--- a/doc/software-manual.tex
+++ b/doc/software-manual.tex
@@ -3730,6 +3730,7 @@ The table below lists the SEI messages defined for Version 1 and Range-Extension
   204 & Sample Aspect Ratio Information          & Table \ref{tab:sei-sari} \\  
   205 & Scalability Dimension Information        & Table \ref{tab:sei-sdi} \\
   207 & Constrained RASL encoding                & Table \ref{tab:sei-constrained-rasl-encoding} \\
+  209 & Shutter Interval Information             & Table \ref{tab:sei-sii} \\
 \end{SEIListTable}
 %%
 %% SEI messages
@@ -5307,6 +5308,20 @@ When true (non-zero), the SEI enables several restrictions for encoding RASL fra
 \\
 \end{OptionTableNoShorthand}
 
+\begin{OptionTableNoShorthand}{Shutter Interval Information SEI message encoder parameters}{tab:sei-sii}
+\Option{SEIShutterIntervalEnabled} &
+\Default{false} &
+Enables (true) or disables (false) the insertion of Shutter Interval Information SEI message.
+\\
+\Option{SEISiiTimeScale} &
+\Default{27000000} &
+Specifies sii_time_scale.
+\\
+\Option{SEISiiInputNumUnitsInShutterInterval} &
+\Default{false} &
+Specifies sii_num_units_in_shutter_interval for single entry.If multiple entries, the values are set to sub_layer_num_units_in_shutter_interval[ ] corresponding to each temporal sub layer starting from temporal layer id 0.
+\\
+\end{OptionTableNoShorthand}
 
 
 %\Option{SEITimeCode} &
diff --git a/source/App/DecoderApp/DecApp.cpp b/source/App/DecoderApp/DecApp.cpp
index b77983633..49b31e84f 100644
--- a/source/App/DecoderApp/DecApp.cpp
+++ b/source/App/DecoderApp/DecApp.cpp
@@ -138,6 +138,12 @@ uint32_t DecApp::decode()
 
   bool bPicSkipped = false;
 
+#if JVET_Z0120_SII_SEI_PROCESSING
+  bool openedPostFile = false;
+  setShutterFilterFlag(!m_shutterIntervalPostFileName.empty());   // not apply shutter interval SEI processing if filename is not specified.
+  m_cDecLib.setShutterFilterFlag(getShutterFilterFlag());
+#endif
+
   bool isEosPresentInPu = false;
   bool isEosPresentInLastPu = false;
 
@@ -515,6 +521,177 @@ uint32_t DecApp::decode()
       {
         xOutputAnnotatedRegions(pcListPic);
       }
+
+#if JVET_Z0120_SII_SEI_PROCESSING
+      PicList::iterator iterPic = pcListPic->begin();
+      Picture* pcPic = *(iterPic);
+      SEIMessages shutterIntervalInfo = getSeisByType(pcPic->SEIs, SEI::SHUTTER_INTERVAL_INFO);
+
+      if (!m_shutterIntervalPostFileName.empty())
+      {
+        int32_t hasValidSII = 1;
+        SEIShutterIntervalInfo *curSIIInfo = NULL;
+        if ((pcPic->getPictureType() == NAL_UNIT_CODED_SLICE_IDR_W_RADL ||
+          pcPic->getPictureType() == NAL_UNIT_CODED_SLICE_IDR_N_LP) && m_newCLVS[nalu.m_nuhLayerId])
+        {
+          IdrSiiInfo_s curSII;
+          curSII.m_picPoc = pcPic->getPOC();
+
+          curSII.m_isValidSii = 0;
+          curSII.m_siiInfo.m_siiEnabled = 0;
+          curSII.m_siiInfo.m_siiNumUnitsInShutterInterval = 0;
+          curSII.m_siiInfo.m_siiTimeScale = 0;
+          curSII.m_siiInfo.m_siiMaxSubLayersMinus1 = 0;
+          curSII.m_siiInfo.m_siiFixedSIwithinCLVS = 0;
+
+          if (shutterIntervalInfo.size() > 0) 
+          {
+            SEIShutterIntervalInfo *seiShutterIntervalInfo = (SEIShutterIntervalInfo*) *(shutterIntervalInfo.begin());
+            curSII.m_isValidSii = 1;
+
+            curSII.m_siiInfo.m_siiEnabled = seiShutterIntervalInfo->m_siiEnabled;
+            curSII.m_siiInfo.m_siiNumUnitsInShutterInterval = seiShutterIntervalInfo->m_siiNumUnitsInShutterInterval;
+            curSII.m_siiInfo.m_siiTimeScale = seiShutterIntervalInfo->m_siiTimeScale;
+            curSII.m_siiInfo.m_siiMaxSubLayersMinus1 = seiShutterIntervalInfo->m_siiMaxSubLayersMinus1;
+            curSII.m_siiInfo.m_siiFixedSIwithinCLVS = seiShutterIntervalInfo->m_siiFixedSIwithinCLVS;
+            curSII.m_siiInfo.m_siiSubLayerNumUnitsInSI.clear();
+            for (int i = 0; i < seiShutterIntervalInfo->m_siiSubLayerNumUnitsInSI.size(); i++)
+              curSII.m_siiInfo.m_siiSubLayerNumUnitsInSI.push_back(seiShutterIntervalInfo->m_siiSubLayerNumUnitsInSI[i]);
+
+            uint32_t tmpInfo = (uint32_t)(m_activeSiiInfo.size() + 1);
+            m_activeSiiInfo.insert(pair<uint32_t, IdrSiiInfo_s>(tmpInfo, curSII));
+            curSIIInfo = seiShutterIntervalInfo;
+          }
+          else 
+          {
+            curSII.m_isValidSii = 0;
+            hasValidSII = 0;
+            uint32_t tmpInfo = (uint32_t)(m_activeSiiInfo.size() + 1);
+            m_activeSiiInfo.insert(pair<uint32_t, IdrSiiInfo_s>(tmpInfo, curSII));
+          }
+        }
+        else 
+        {
+          if (m_activeSiiInfo.size() == 1) 
+          {
+            curSIIInfo = &(m_activeSiiInfo.begin()->second.m_siiInfo);
+          }
+          else 
+          {
+            uint8_t isLast = 1;
+            for (int i = 1; i < m_activeSiiInfo.size() + 1; i++) 
+            {
+              if (pcPic->getPOC() <= m_activeSiiInfo.at(i).m_picPoc) 
+              {
+                if (m_activeSiiInfo[i - 1].m_isValidSii) 
+                {
+                  curSIIInfo = &(m_activeSiiInfo.at(i - 1).m_siiInfo);
+                }
+                else 
+                {
+                  hasValidSII = 0;
+                }
+                isLast = 0;
+                break;
+              }
+            }
+            if (isLast) 
+            {
+              uint32_t tmpInfo = (uint32_t)(m_activeSiiInfo.size());
+              curSIIInfo = &(m_activeSiiInfo.at(tmpInfo).m_siiInfo);
+            }
+          }
+        }
+
+        if (hasValidSII)
+        {
+          if (!curSIIInfo->m_siiFixedSIwithinCLVS)
+          {
+            uint32_t siiMaxSubLayersMinus1 = curSIIInfo->m_siiMaxSubLayersMinus1;
+            uint32_t numUnitsLFR = curSIIInfo->m_siiSubLayerNumUnitsInSI[0];
+            uint32_t numUnitsHFR = curSIIInfo->m_siiSubLayerNumUnitsInSI[siiMaxSubLayersMinus1];
+
+            int blending_ratio = (numUnitsLFR / numUnitsHFR);
+            bool checkEqualValuesOfSFR = 1;
+            bool checkSubLayerSI = 0;
+            int i;
+
+            //supports only the case of SFR = HFR / 2
+            if (curSIIInfo->m_siiSubLayerNumUnitsInSI[siiMaxSubLayersMinus1] <
+                        curSIIInfo->m_siiSubLayerNumUnitsInSI[siiMaxSubLayersMinus1 - 1])
+            {
+              checkSubLayerSI = 1;
+            }
+            else
+            {
+              fprintf(stderr, "Warning: Shutter Interval SEI message processing is disabled due to SFR != (HFR / 2) \n");
+            }
+            //check shutter interval for all sublayer remains same for SFR pictures
+            for (i = 1; i < siiMaxSubLayersMinus1; i++)
+            {
+              if (curSIIInfo->m_siiSubLayerNumUnitsInSI[0] != curSIIInfo->m_siiSubLayerNumUnitsInSI[i])
+              {
+                checkEqualValuesOfSFR = 0;
+              }
+            }
+            if (!checkEqualValuesOfSFR)
+            {
+              fprintf(stderr, "Warning: Shutter Interval SEI message processing is disabled when shutter interval is not same for SFR sublayers \n");
+            }
+            if (checkSubLayerSI && checkEqualValuesOfSFR)
+            {
+              setShutterFilterFlag(numUnitsLFR == blending_ratio * numUnitsHFR);
+              setBlendingRatio(blending_ratio);
+            }
+            else
+            {
+              setShutterFilterFlag(false);
+            }
+
+            const SPS* activeSPS = pcListPic->front()->cs->sps;
+
+            if (numUnitsLFR == blending_ratio * numUnitsHFR && activeSPS->getMaxTLayers() == 1 && activeSPS->getMaxDecPicBuffering(0) == 1)
+            {
+              fprintf(stderr, "Warning: Shutter Interval SEI message processing is disabled for single TempLayer and single frame in DPB\n");
+              setShutterFilterFlag(false);
+            }
+          }
+          else
+          {
+            fprintf(stderr, "Warning: Shutter Interval SEI message processing is disabled for fixed shutter interval case\n");
+            setShutterFilterFlag(false);
+          }
+        }
+        else 
+        {
+          fprintf(stderr, "Warning: Shutter Interval information should be specified in SII-SEI message\n");
+          setShutterFilterFlag(false);
+        }
+      }
+
+
+      if ((!m_shutterIntervalPostFileName.empty()) && (!openedPostFile) && getShutterFilterFlag())
+      {
+        const BitDepths &bitDepths = pcListPic->front()->cs->sps->getBitDepths();
+        for (uint32_t channelType = 0; channelType < MAX_NUM_CHANNEL_TYPE; channelType++)
+        {
+          if (m_outputBitDepth[channelType] == 0)
+          {
+            m_outputBitDepth[channelType] = bitDepths.recon[channelType];
+          }
+        }
+
+        std::ofstream ofile(m_shutterIntervalPostFileName.c_str());
+        if (!ofile.good() || !ofile.is_open())
+        {
+          fprintf(stderr, "\nUnable to open file '%s' for writing shutter-interval-SEI video\n", m_shutterIntervalPostFileName.c_str());
+          exit(EXIT_FAILURE);
+        }
+        m_cTVideoIOYuvSIIPostFile.open(m_shutterIntervalPostFileName, true, m_outputBitDepth, m_outputBitDepth, bitDepths.recon); // write mode
+        openedPostFile = true;
+      }
+#endif
+
       // write reconstruction to file
       if( bNewPicture )
       {
@@ -586,6 +763,13 @@ uint32_t DecApp::decode()
 
   xFlushOutput( pcListPic );
 
+#if JVET_Z0120_SII_SEI_PROCESSING
+  if (!m_shutterIntervalPostFileName.empty() && getShutterFilterFlag())
+  {
+    m_cTVideoIOYuvSIIPostFile.close();
+  }
+#endif
+
   // get the number of checksum errors
   uint32_t nRet = m_cDecLib.getNumberOfChecksumErrorsDetected();
 
@@ -869,6 +1053,32 @@ void DecApp::xWriteOutput( PicList* pcListPic, uint32_t tId )
                                     NUM_CHROMA_FORMAT, m_bClipOutputVideoToRec709Range);
           }
         }
+
+
+#if JVET_Z0120_SII_SEI_PROCESSING
+        if (!m_shutterIntervalPostFileName.empty() && getShutterFilterFlag())
+        {
+          int blendingRatio = getBlendingRatio();
+          pcPic->xOutputPostFilteredPic(pcPic, pcListPic, blendingRatio);
+
+          const Window &conf = pcPic->getConformanceWindow();
+          const SPS* sps = pcPic->cs->sps;
+          ChromaFormat chromaFormatIDC = sps->getChromaFormatIdc();
+
+          m_cTVideoIOYuvSIIPostFile.write(
+            pcPic->getPostRecBuf().get(COMPONENT_Y).width,
+            pcPic->getPostRecBuf().get(COMPONENT_Y).height,
+            pcPic->getPostRecBuf(),
+            m_outputColourSpaceConvert,
+            m_packedYUVMode,
+            conf.getWindowLeftOffset() * SPS::getWinUnitX(chromaFormatIDC),
+            conf.getWindowRightOffset() * SPS::getWinUnitX(chromaFormatIDC),
+            conf.getWindowTopOffset() * SPS::getWinUnitY(chromaFormatIDC),
+            conf.getWindowBottomOffset() * SPS::getWinUnitY(chromaFormatIDC),
+            NUM_CHROMA_FORMAT, m_bClipOutputVideoToRec709Range);
+        }
+#endif
+
         // Perform CTI on decoded frame and write to output CTI file
         if (!m_SEICTIFileName.empty())
         {
@@ -1043,6 +1253,30 @@ void DecApp::xFlushOutput( PicList* pcListPic, const int layerId )
                                       NUM_CHROMA_FORMAT, m_bClipOutputVideoToRec709Range);
             }
           }
+
+#if JVET_Z0120_SII_SEI_PROCESSING
+          if (!m_shutterIntervalPostFileName.empty() && getShutterFilterFlag())
+          {
+            int blendingRatio = getBlendingRatio();
+            pcPic->xOutputPostFilteredPic(pcPic, pcListPic, blendingRatio);
+
+            const Window &conf = pcPic->getConformanceWindow();
+            const SPS* sps = pcPic->cs->sps;
+            ChromaFormat chromaFormatIDC = sps->getChromaFormatIdc();
+
+            m_cTVideoIOYuvSIIPostFile.write(
+              pcPic->getPostRecBuf().get(COMPONENT_Y).width,
+              pcPic->getPostRecBuf().get(COMPONENT_Y).height,
+              pcPic->getPostRecBuf(),
+              m_outputColourSpaceConvert, m_packedYUVMode,
+              conf.getWindowLeftOffset() * SPS::getWinUnitX(chromaFormatIDC),
+              conf.getWindowRightOffset() * SPS::getWinUnitX(chromaFormatIDC),
+              conf.getWindowTopOffset() * SPS::getWinUnitY(chromaFormatIDC),
+              conf.getWindowBottomOffset() * SPS::getWinUnitY(chromaFormatIDC),
+              NUM_CHROMA_FORMAT, m_bClipOutputVideoToRec709Range);
+          }
+#endif
+
           // Perform CTI on decoded frame and write to output CTI file
           if (!m_SEICTIFileName.empty())
           {
@@ -1075,7 +1309,11 @@ void DecApp::xFlushOutput( PicList* pcListPic, const int layerId )
         }
         pcPic->neededForOutput = false;
       }
-      if (pcPic != nullptr)
+#if JVET_Z0120_SII_SEI_PROCESSING
+      if (pcPic != nullptr && (m_shutterIntervalPostFileName.empty() || !getShutterFilterFlag()))
+#else
+      if(pcPic != nullptr)
+#endif
       {
         pcPic->destroy();
         delete pcPic;
diff --git a/source/App/DecoderApp/DecApp.h b/source/App/DecoderApp/DecApp.h
index d774ae761..6d83fcb47 100644
--- a/source/App/DecoderApp/DecApp.h
+++ b/source/App/DecoderApp/DecApp.h
@@ -64,6 +64,22 @@ private:
   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_Z0120_SII_SEI_PROCESSING
+  bool                                    m_ShutterFilterEnable;          ///< enable Post-processing with Shutter Interval SEI
+  VideoIOYuv                              m_cTVideoIOYuvSIIPostFile;      ///< post-filtered YUV class
+  int                                     m_SII_BlendingRatio;
+
+  typedef struct 
+  {
+    SEIShutterIntervalInfo m_siiInfo;
+    uint32_t               m_picPoc;
+    uint8_t                m_isValidSii;
+  }IdrSiiInfo_s;
+
+  std::map<uint32_t, IdrSiiInfo_s>      m_activeSiiInfo;
+
+#endif
+
   // for output control
   int             m_iPOCLastDisplay;              ///< last POC in display order
   std::ofstream   m_seiMessageFileStream;         ///< Used for outputing SEI messages.
@@ -85,6 +101,12 @@ public:
   virtual ~DecApp         ()  {}
 
   uint32_t  decode            (); ///< main decoding function
+#if JVET_Z0120_SII_SEI_PROCESSING
+  bool  getShutterFilterFlag()        const { return m_ShutterFilterEnable; }
+  void  setShutterFilterFlag(bool value) { m_ShutterFilterEnable = value; }
+  int   getBlendingRatio()             const { return m_SII_BlendingRatio; }
+  void  setBlendingRatio(int value) { m_SII_BlendingRatio = value; }
+#endif
 
 private:
   void  xCreateDecLib     (); ///< create internal classes
diff --git a/source/App/DecoderApp/DecAppCfg.cpp b/source/App/DecoderApp/DecAppCfg.cpp
index 908d585b8..8988da1f3 100644
--- a/source/App/DecoderApp/DecAppCfg.cpp
+++ b/source/App/DecoderApp/DecAppCfg.cpp
@@ -90,6 +90,9 @@ bool DecAppCfg::parseCfg( int argc, char* argv[] )
   ("OutputColourSpaceConvert",  outputColourSpaceConvert,              string(""), "Colour space conversion to apply to input 444 video. Permitted values are (empty string=UNCHANGED) " + getListOfColourSpaceConverts(false))
   ("MaxTemporalLayer,t",        m_iMaxTemporalLayer,                   500,    "Maximum Temporal Layer to be decoded. -1 to decode all layers")
   ("TargetOutputLayerSet,p",    m_targetOlsIdx,                        500,    "Target output layer set index")
+#if JVET_Z0120_SII_SEI_PROCESSING
+  ("SEIShutterIntervalPostFilename,-sii", m_shutterIntervalPostFileName, string(""), "Post Filtering with Shutter Interval SEI. If empty, no filtering is applied (ignore SEI message)\n")
+#endif
   ("SEIDecodedPictureHash,-dph",m_decodedPictureHashSEIEnabled,        1,          "Control handling of decoded picture hash SEI messages\n"
                                                                                    "\t1: check hash in SEI messages if available in the bitstream\n"
                                                                                    "\t0: ignore SEI message")
diff --git a/source/App/DecoderApp/DecAppCfg.h b/source/App/DecoderApp/DecAppCfg.h
index 810561223..f9af97fb6 100644
--- a/source/App/DecoderApp/DecAppCfg.h
+++ b/source/App/DecoderApp/DecAppCfg.h
@@ -81,6 +81,9 @@ protected:
   std::string   m_outputDecoded360SEIMessagesFilename;   ///< filename to output decoded 360 SEI messages to.
 #endif
 
+#if JVET_Z0120_SII_SEI_PROCESSING
+  std::string   m_shutterIntervalPostFileName;        ///< output Post Filtering file name
+#endif
 
   bool          m_bClipOutputVideoToRec709Range;      ///< If true, clip the output video to the Rec 709 range on saving.
   bool          m_packedYUVMode;                      ///< If true, output 10-bit and 12-bit YUV data as 5-byte and 3-byte (respectively) packed YUV data
diff --git a/source/App/EncoderApp/EncApp.cpp b/source/App/EncoderApp/EncApp.cpp
index d74bf535c..74ea378a6 100644
--- a/source/App/EncoderApp/EncApp.cpp
+++ b/source/App/EncoderApp/EncApp.cpp
@@ -1112,6 +1112,10 @@ void EncApp::xInitLibCfg()
   m_cEncLib.setDriSEIDisparityRefViewId                          (m_driSEIDisparityRefViewId);
   m_cEncLib.setDriSEINonlinearNumMinus1                          (m_driSEINonlinearNumMinus1);
   m_cEncLib.setDriSEINonlinearModel                              (m_driSEINonlinearModel);
+#if JVET_Z0120_SII_SEI_PROCESSING
+  m_cEncLib.setShutterFilterFlag(m_ShutterFilterEnable);
+  m_cEncLib.setBlendingRatioSII(m_SII_BlendingRatio);
+#endif
   m_cEncLib.setEntropyCodingSyncEnabledFlag                      ( m_entropyCodingSyncEnabledFlag );
   m_cEncLib.setEntryPointPresentFlag                             ( m_entryPointPresentFlag );
   m_cEncLib.setTMVPModeId                                        ( m_TMVPModeId );
@@ -1153,6 +1157,12 @@ void EncApp::xInitLibCfg()
   m_cEncLib.setTSRCdisableLL                                     ( m_TSRCdisableLL );
   m_cEncLib.setUseRecalculateQPAccordingToLambda                 ( m_recalculateQPAccordingToLambda );
   m_cEncLib.setDCIEnabled                                        ( m_DCIEnabled );
+#if JVET_Z0120_SHUTTER_INTERVAL_SEI
+  m_cEncLib.setSiiSEIEnabled(m_siiSEIEnabled);
+  m_cEncLib.setSiiSEINumUnitsInShutterInterval(m_siiSEINumUnitsInShutterInterval);
+  m_cEncLib.setSiiSEITimeScale(m_siiSEITimeScale);
+  m_cEncLib.setSiiSEISubLayerNumUnitsInSI(m_siiSEISubLayerNumUnitsInSI);
+#endif
   m_cEncLib.setVuiParametersPresentFlag                          ( m_vuiParametersPresentFlag );
   m_cEncLib.setSamePicTimingInAllOLS                             (m_samePicTimingInAllOLS);
   m_cEncLib.setAspectRatioInfoPresentFlag                        ( m_aspectRatioInfoPresentFlag);
@@ -1286,6 +1296,12 @@ void EncApp::xCreateLib( std::list<PelUnitBuf*>& recBufList, const int layerId )
     m_cVideoIOYuvReconFile.open( reconFileName, true, m_outputBitDepth, m_outputBitDepth, m_internalBitDepth );  // write mode
   }
 
+#if JVET_Z0120_SII_SEI_PROCESSING
+  if (m_ShutterFilterEnable && !m_shutterIntervalPreFileName.empty())
+  {
+    m_cTVideoIOYuvSIIPreFile.open(m_shutterIntervalPreFileName, true, m_outputBitDepth, m_outputBitDepth, m_internalBitDepth);  // write mode
+  }
+#endif
   // create the encoder
   m_cEncLib.create( layerId );
 
@@ -1301,6 +1317,12 @@ void EncApp::xDestroyLib()
   // Video I/O
   m_cVideoIOYuvInputFile.close();
   m_cVideoIOYuvReconFile.close();
+#if JVET_Z0120_SII_SEI_PROCESSING
+  if (m_ShutterFilterEnable && !m_shutterIntervalPreFileName.empty())
+  {
+    m_cTVideoIOYuvSIIPreFile.close();
+  }
+#endif
 
   // Neo Decoder
   m_cEncLib.destroy();
@@ -1505,6 +1527,14 @@ bool EncApp::encodePrep( bool& eos )
     keepDoing = m_cEncLib.encodePrep( eos, m_flush ? 0 : m_orgPic, m_flush ? 0 : m_trueOrgPic, m_flush ? 0 : m_filteredOrgPic, m_flush ? 0 : m_filteredOrgPicForFG, snrCSC, m_recBufList, m_numEncoded );
   }
 
+#if JVET_Z0120_SII_SEI_PROCESSING
+  if (m_ShutterFilterEnable && !m_shutterIntervalPreFileName.empty())
+  {
+    m_cTVideoIOYuvSIIPreFile.write(m_orgPic->get(COMPONENT_Y).width, m_orgPic->get(COMPONENT_Y).height, *m_orgPic, m_inputColourSpaceConvert, m_packedYUVMode,
+      m_confWinLeft, m_confWinRight, m_confWinTop, m_confWinBottom, NUM_CHROMA_FORMAT, m_bClipOutputVideoToRec709Range);
+  }
+#endif
+
   return keepDoing;
 }
 
diff --git a/source/App/EncoderApp/EncApp.h b/source/App/EncoderApp/EncApp.h
index d809bfb51..9775f8de0 100644
--- a/source/App/EncoderApp/EncApp.h
+++ b/source/App/EncoderApp/EncApp.h
@@ -71,6 +71,9 @@ private:
   EncLib            m_cEncLib;                    ///< encoder class
   VideoIOYuv        m_cVideoIOYuvInputFile;       ///< input YUV file
   VideoIOYuv        m_cVideoIOYuvReconFile;       ///< output reconstruction file
+#if JVET_Z0120_SII_SEI_PROCESSING
+  VideoIOYuv        m_cTVideoIOYuvSIIPreFile;      ///< output pre-filtered file
+#endif
   int               m_iFrameRcvd;                 ///< number of received frames
   uint32_t          m_essentialBytes;
   uint32_t          m_totalBytes;
diff --git a/source/App/EncoderApp/EncAppCfg.cpp b/source/App/EncoderApp/EncAppCfg.cpp
index b70573c47..6a1ddc3fb 100644
--- a/source/App/EncoderApp/EncAppCfg.cpp
+++ b/source/App/EncoderApp/EncAppCfg.cpp
@@ -738,6 +738,9 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] )
   SMultiValueInput<uint32_t>   cfg_FgcSEICompModelValueComp0              (0, 65535,  0, 256 * 6);
   SMultiValueInput<uint32_t>   cfg_FgcSEICompModelValueComp1              (0, 65535,  0, 256 * 6);
   SMultiValueInput<uint32_t>   cfg_FgcSEICompModelValueComp2              (0, 65535,  0, 256 * 6);
+#if JVET_Z0120_SHUTTER_INTERVAL_SEI
+  SMultiValueInput<unsigned>   cfg_siiSEIInputNumUnitsInSI(0, std::numeric_limits<uint32_t>::max(), 0, 7);
+#endif
 
 #if ENABLE_TRACING
   string sTracingRule;
@@ -765,6 +768,9 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] )
   ("InputPathPrefix,-ipp",                            inputPathPrefix,                             string(""), "pathname to prepend to input filename")
   ("BitstreamFile,b",                                 m_bitstreamFileName,                         string(""), "Bitstream output file name")
   ("ReconFile,o",                                     m_reconFileName,                             string(""), "Reconstructed YUV output file name")
+#if JVET_Z0120_SII_SEI_PROCESSING
+  ("SEIShutterIntervalPreFilename,-sii",              m_shutterIntervalPreFileName, string(""), "File name of Pre-Filtering video. If empty, not output video\n")
+#endif  
   ("SourceWidth,-wdt",                                m_sourceWidth,                                       0, "Source picture width")
   ("SourceHeight,-hgt",                               m_sourceHeight,                                      0, "Source picture height")
   ("InputBitDepth",                                   m_inputBitDepth[CHANNEL_TYPE_LUMA],                   8, "Bit-depth of input file")
@@ -1418,6 +1424,12 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] )
   ("SEISARISarWidth",                                 m_sariSarWidth,                           0, "Specifies the Sample Aspect Ratio Width of Sample Aspect Ratio Information SEI messages, if extended SAR is chosen.")
   ("SEISARISarHeight",                                m_sariSarHeight,                          0, "Specifies the Sample Aspect Ratio Height of Sample Aspect Ratio Information SEI messages, if extended SAR is chosen.")
   ("MCTSEncConstraint",                               m_MCTSEncConstraint,                               false, "For MCTS, constrain motion vectors at tile boundaries")
+#if JVET_Z0120_SHUTTER_INTERVAL_SEI
+  ("SEIShutterIntervalEnabled",                       m_siiSEIEnabled,                          false, "Controls if shutter interval information SEI message is enabled")
+  ("SEISiiTimeScale",                                 m_siiSEITimeScale,                        27000000u, "Specifies sii_time_scale")
+  ("SEISiiInputNumUnitsInShutterInterval",            cfg_siiSEIInputNumUnitsInSI,              cfg_siiSEIInputNumUnitsInSI, "Specifies sub_layer_num_units_in_shutter_interval")
+#endif
+
 #if ENABLE_TRACING
   ("TraceChannelsList",                               bTracingChannelsList,                              false, "List all available tracing channels")
   ("TraceRule",                                       sTracingRule,                               string( "" ), "Tracing rule (ex: \"D_CABAC:poc==8\" or \"D_REC_CB_LUMA:poc==8\")")
@@ -2988,6 +3000,86 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] )
 #endif // ENABLE_QPA
 
 
+#if JVET_Z0120_SII_SEI_PROCESSING
+  m_ShutterFilterEnable = false;
+#endif
+#if JVET_Z0120_SHUTTER_INTERVAL_SEI
+  if (m_siiSEIEnabled)
+  {
+    assert(m_siiSEITimeScale >= 0 && m_siiSEITimeScale <= MAX_UINT);
+    uint32_t sii_max_sub_layers = (uint32_t)cfg_siiSEIInputNumUnitsInSI.values.size();
+    assert(sii_max_sub_layers > 0);
+    if (sii_max_sub_layers > 1)
+    {
+      m_siiSEISubLayerNumUnitsInSI.resize(sii_max_sub_layers);
+      for (int32_t i = 0; i < sii_max_sub_layers; i++)
+      {
+        m_siiSEISubLayerNumUnitsInSI[i] = cfg_siiSEIInputNumUnitsInSI.values[i];
+        assert(m_siiSEISubLayerNumUnitsInSI[i] >= 0 && m_siiSEISubLayerNumUnitsInSI[i] <= MAX_UINT);
+      }
+    }
+    else
+    {
+      m_siiSEINumUnitsInShutterInterval = cfg_siiSEIInputNumUnitsInSI.values[0];
+      assert(m_siiSEINumUnitsInShutterInterval >= 0 && m_siiSEINumUnitsInShutterInterval <= MAX_UINT);
+    }
+#if JVET_Z0120_SII_SEI_PROCESSING
+    uint32_t siiMaxSubLayersMinus1 = sii_max_sub_layers - 1;
+    int blending_ratio = (m_siiSEISubLayerNumUnitsInSI[0] / m_siiSEISubLayerNumUnitsInSI[siiMaxSubLayersMinus1]);
+
+    if (sii_max_sub_layers > 1 && m_siiSEISubLayerNumUnitsInSI[0] ==
+                                (blending_ratio * m_siiSEISubLayerNumUnitsInSI[siiMaxSubLayersMinus1]))
+    {
+      m_ShutterFilterEnable = true;
+      double fpsHFR = (double)m_iFrameRate;
+      int32_t i;
+      bool checkEqualValuesOfSFR = 1;
+      bool checkSubLayerSI = 0;
+
+      double shutterAngleFactor = (fpsHFR * ((double)(m_siiSEISubLayerNumUnitsInSI[siiMaxSubLayersMinus1])))/((double)m_siiSEITimeScale);
+
+      // If shutterAngleFactor = 1 indicates that shutterAngle = 360  
+      // If shutterAngleFactor = 0.5 indicates that shutterAngle = 180
+      // If shutterAngleFactor = 0.25 indicates that shutterAngle = 90
+
+      if (shutterAngleFactor < 0.5)
+      {
+        for (int i = 0; i < siiMaxSubLayersMinus1; i++)
+        {
+          m_siiSEISubLayerNumUnitsInSI[i] = m_siiSEISubLayerNumUnitsInSI[siiMaxSubLayersMinus1];
+        }
+        m_ShutterFilterEnable = false;
+        printf("Warning: For the shutterAngle = %d, the blending can't be applied\n", (int)(shutterAngleFactor * 360));
+      }
+      // supports only the case of SFR = HFR / 2 
+      if (m_siiSEISubLayerNumUnitsInSI[siiMaxSubLayersMinus1] < m_siiSEISubLayerNumUnitsInSI[siiMaxSubLayersMinus1 - 1])
+      {
+        checkSubLayerSI = 1;
+      }
+      // check shutter interval for all sublayer remains same for LFR pictures
+      for (i = 1; i < siiMaxSubLayersMinus1; i++)
+      {
+        if (m_siiSEISubLayerNumUnitsInSI[0] != m_siiSEISubLayerNumUnitsInSI[i])
+        {
+          checkEqualValuesOfSFR = 0;
+        }
+      }
+      if (checkSubLayerSI && checkEqualValuesOfSFR)
+      {
+        setBlendingRatioSII(blending_ratio);
+      }
+      else
+      {
+        m_ShutterFilterEnable = false;
+      }
+    }
+    else
+    {
+      printf("Warning: SII-processing is applied for multiple shutter intervals and number of LFR units should be 2 times of number of HFR units\n");
+    }
+#endif
+  }
+#endif
 
 
   if( m_costMode == COST_LOSSLESS_CODING )
@@ -4368,6 +4460,14 @@ bool EncAppCfg::xCheckParameter()
       xConfirmPara( m_gcmpSEIGuardBandSamplesMinus1 < 0 || m_gcmpSEIGuardBandSamplesMinus1 > 15, "SEIGcmpGuardBandSamplesMinus1 must be in the range of 0 to 15");
     }
   }
+
+#if JVET_Z0120_SII_SEI_PROCESSING
+  if (m_siiSEIEnabled && m_ShutterFilterEnable)
+  {
+    xConfirmPara(m_maxTempLayer == 1 || m_maxDecPicBuffering[0] == 1,"Shutter Interval SEI message processing is disabled for single TempLayer and single frame in DPB\n");
+  }
+#endif
+
   xConfirmPara(m_log2ParallelMergeLevel < 2, "Log2ParallelMergeLevel should be larger than or equal to 2");
   xConfirmPara(m_log2ParallelMergeLevel > m_uiCTUSize, "Log2ParallelMergeLevel should be less than or equal to CTU size");
 #if U0033_ALTERNATIVE_TRANSFER_CHARACTERISTICS_SEI
@@ -4437,6 +4537,12 @@ void EncAppCfg::xPrintParameter()
   msg( DETAILS, "Input          File                    : %s\n", m_inputFileName.c_str() );
   msg( DETAILS, "Bitstream      File                    : %s\n", m_bitstreamFileName.c_str() );
   msg( DETAILS, "Reconstruction File                    : %s\n", m_reconFileName.c_str() );
+#if JVET_Z0120_SII_SEI_PROCESSING
+  if (m_ShutterFilterEnable && !m_shutterIntervalPreFileName.empty())
+  {
+    msg(DETAILS,"SII Pre-processed File                 : %s\n", m_shutterIntervalPreFileName.c_str());
+  }
+#endif
   msg( DETAILS, "Real     Format                        : %dx%d %gHz\n", m_sourceWidth - m_confWinLeft - m_confWinRight, m_sourceHeight - m_confWinTop - m_confWinBottom, (double)m_iFrameRate / m_temporalSubsampleRatio );
   msg( DETAILS, "Internal Format                        : %dx%d %gHz\n", m_sourceWidth, m_sourceHeight, (double)m_iFrameRate / m_temporalSubsampleRatio );
   msg( DETAILS, "Sequence PSNR output                   : %s\n", ( m_printMSEBasedSequencePSNR ? "Linear average, MSE-based" : "Linear average only" ) );
diff --git a/source/App/EncoderApp/EncAppCfg.h b/source/App/EncoderApp/EncAppCfg.h
index cb3b59c70..eaeafc49c 100644
--- a/source/App/EncoderApp/EncAppCfg.h
+++ b/source/App/EncoderApp/EncAppCfg.h
@@ -40,6 +40,8 @@
 
 #include "CommonLib/CommonDef.h"
 #include "EncoderLib/EncCfgParam.h"
+#include "CommonLib/Picture.h"
+#include "EncCfg.h"
 
 #include <map>
 template <class T1, class T2>
@@ -805,6 +807,19 @@ protected:
   int       m_ImvMode;                                        ///< imv mode
   int       m_Imv4PelFast;                                    ///< imv 4-Pel fast mode
 
+#if JVET_Z0120_SHUTTER_INTERVAL_SEI
+  bool      m_siiSEIEnabled;
+  uint32_t  m_siiSEINumUnitsInShutterInterval;
+  uint32_t  m_siiSEITimeScale;
+  std::vector<uint32_t>     m_siiSEISubLayerNumUnitsInSI;
+#endif
+#if JVET_Z0120_SII_SEI_PROCESSING
+  bool        m_ShutterFilterEnable;                          ///< enable Pre-Filtering with Shutter Interval SEI
+  std::string m_shutterIntervalPreFileName;                   ///< output Pre-Filtering video
+  int         m_SII_BlendingRatio;
+  void        setBlendingRatioSII(int value) { m_SII_BlendingRatio = value; }
+#endif
+
   std::string m_summaryOutFilename;                           ///< filename to use for producing summary output file.
   std::string m_summaryPicFilenameBase;                       ///< Base filename to use for producing summary picture output files. The actual filenames used will have I.txt, P.txt and B.txt appended.
   uint32_t        m_summaryVerboseness;                           ///< Specifies the level of the verboseness of the text output.
diff --git a/source/Lib/CommonLib/CodingStructure.h b/source/Lib/CommonLib/CodingStructure.h
index 9bb80f24c..988f2e21f 100644
--- a/source/Lib/CommonLib/CodingStructure.h
+++ b/source/Lib/CommonLib/CodingStructure.h
@@ -63,6 +63,9 @@ enum PictureType
   PIC_ORIGINAL_INPUT,
   PIC_TRUE_ORIGINAL_INPUT,
   PIC_FILTERED_ORIGINAL_INPUT,
+#if JVET_Z0120_SII_SEI_PROCESSING
+  PIC_YUV_POST_REC,
+#endif
   NUM_PIC_TYPES
 };
 extern XUCache g_globalUnitCache;
diff --git a/source/Lib/CommonLib/CommonDef.h b/source/Lib/CommonLib/CommonDef.h
index dd3224164..4401be276 100644
--- a/source/Lib/CommonLib/CommonDef.h
+++ b/source/Lib/CommonLib/CommonDef.h
@@ -492,6 +492,13 @@ static const int BLK_16 =                                        16;
 static const int BLK_32 =                                        32;
 static const int BIT_DEPTH_8 =                                    8;
 // ====================================================================================================================
+// SEI and related constants
+// ====================================================================================================================
+#if JVET_Z0120_SII_SEI_PROCESSING
+static const double SII_PF_W2 =                                       0.6; // weight for current picture
+static const double SII_PF_W1 =                                       0.4; // weight for previous picture , it must be equal to 1.0 - SII_PF_W2
+#endif
+// ====================================================================================================================
 // Macro functions
 // ====================================================================================================================
 
diff --git a/source/Lib/CommonLib/Picture.cpp b/source/Lib/CommonLib/Picture.cpp
index e33b36fa2..bb9bdad93 100644
--- a/source/Lib/CommonLib/Picture.cpp
+++ b/source/Lib/CommonLib/Picture.cpp
@@ -80,7 +80,11 @@ Picture::Picture()
   m_grainBuf            = nullptr;
 }
 
+#if JVET_Z0120_SII_SEI_PROCESSING
+void Picture::create( const ChromaFormat &_chromaFormat, const Size &size, const unsigned _maxCUSize, const unsigned _margin, const bool _decoder, const int _layerId, const bool enablePostFilteringForHFR, const bool gopBasedTemporalFilterEnabled, const bool fgcSEIAnalysisEnabled)
+#else
 void Picture::create( const ChromaFormat &_chromaFormat, const Size &size, const unsigned _maxCUSize, const unsigned _margin, const bool _decoder, const int _layerId, const bool gopBasedTemporalFilterEnabled, const bool fgcSEIAnalysisEnabled )
+#endif
 {
   layerId = _layerId;
   UnitArea::operator=( UnitArea( _chromaFormat, Area( Position{ 0, 0 }, size ) ) );
@@ -89,6 +93,13 @@ void Picture::create( const ChromaFormat &_chromaFormat, const Size &size, const
   M_BUFS( 0, PIC_RECONSTRUCTION ).create( _chromaFormat, a, _maxCUSize, margin, MEMORY_ALIGN_DEF_SIZE );
   M_BUFS( 0, PIC_RECON_WRAP ).create( _chromaFormat, a, _maxCUSize, margin, MEMORY_ALIGN_DEF_SIZE );
 
+#if JVET_Z0120_SII_SEI_PROCESSING
+  if (enablePostFilteringForHFR)
+  {
+    M_BUFS(0, PIC_YUV_POST_REC).create(_chromaFormat, a, _maxCUSize, margin, MEMORY_ALIGN_DEF_SIZE);
+  }
+#endif
+
   if( !_decoder )
   {
     M_BUFS( 0, PIC_ORIGINAL ).    create( _chromaFormat, a );
@@ -223,6 +234,11 @@ const CPelUnitBuf Picture::getRecoBuf(const UnitArea &unit, bool wrap)     const
        PelUnitBuf Picture::getRecoBuf(bool wrap)                                 { return M_BUFS(scheduler.getSplitPicId(), wrap ? PIC_RECON_WRAP : PIC_RECONSTRUCTION); }
 const CPelUnitBuf Picture::getRecoBuf(bool wrap)                           const { return M_BUFS(scheduler.getSplitPicId(), wrap ? PIC_RECON_WRAP : PIC_RECONSTRUCTION); }
 
+#if JVET_Z0120_SII_SEI_PROCESSING
+       PelUnitBuf Picture::getPostRecBuf()                           { return M_BUFS(scheduler.getSplitPicId(), PIC_YUV_POST_REC); }
+const CPelUnitBuf Picture::getPostRecBuf()                     const { return M_BUFS(scheduler.getSplitPicId(), PIC_YUV_POST_REC); }
+#endif
+
 void Picture::finalInit( const VPS* vps, const SPS& sps, const PPS& pps, PicHeader *picHeader, APS** alfApss, APS* lmcsAps, APS* scalingListAps )
 {
   for( auto &sei : SEIs )
@@ -1332,3 +1348,244 @@ PelUnitBuf Picture::getDisplayBuf()
 
   return *m_invColourTransfBuf;
 }
+
+
+#if JVET_Z0120_SII_SEI_PROCESSING
+void Picture::copyToPic(const SPS *sps, PelStorage *pcPicYuvSrc, PelStorage *pcPicYuvDst)
+{
+  const ChromaFormat chromaFormatIDC = sps->getChromaFormatIdc();
+  int numValidComponents = getNumberValidComponents(chromaFormatIDC);
+
+  Pel *srcPxl, *dstPxl;
+  int iSrcStride, iSrcHeight, iSrcWidth;
+  int iDstStride;
+
+  for (int comp = 0; comp < numValidComponents; comp++)
+  {
+
+    if (comp == COMPONENT_Y) {
+      srcPxl = pcPicYuvSrc->Y().buf;
+      dstPxl = pcPicYuvDst->Y().buf;
+      iSrcStride = pcPicYuvSrc->Y().stride;
+      iSrcHeight = pcPicYuvSrc->Y().height;
+      iSrcWidth = pcPicYuvSrc->Y().width;
+      iDstStride = pcPicYuvSrc->Y().stride;
+    }
+    else if (comp == COMPONENT_Cb) {
+      srcPxl = pcPicYuvSrc->Cb().buf;
+      dstPxl = pcPicYuvDst->Cb().buf;
+      iSrcStride = pcPicYuvSrc->Cb().stride;
+      iSrcHeight = pcPicYuvSrc->Cb().height;
+      iSrcWidth = pcPicYuvSrc->Cb().width;
+      iDstStride = pcPicYuvSrc->Cb().stride;
+    }
+    else {
+      srcPxl = pcPicYuvSrc->Cr().buf;
+      dstPxl = pcPicYuvDst->Cr().buf;
+      iSrcStride = pcPicYuvSrc->Cr().stride;
+      iSrcHeight = pcPicYuvSrc->Cr().height;
+      iSrcWidth = pcPicYuvSrc->Cr().width;
+      iDstStride = pcPicYuvSrc->Cr().stride;
+    }
+
+    if (iSrcStride == iDstStride)
+    {
+      ::memcpy(dstPxl, srcPxl, sizeof(Pel) * iSrcStride * iSrcHeight /*getTotalHeight(compId)*/);
+    }
+    else
+    {
+      for (int y = 0; y < iSrcHeight; y++, srcPxl += iSrcStride, dstPxl += iDstStride)
+      {
+        ::memcpy(dstPxl, srcPxl, iSrcWidth * sizeof(Pel));
+      }
+    }
+  }
+}
+
+Picture* Picture::findNextPicPOC(Picture* pcPic, PicList* pcListPic)
+{
+  Picture*  nextPic = NULL;
+  Picture*  listPic = NULL;
+  PicList::iterator  iterListPic = pcListPic->begin();
+  for (int i = 0; i < (int)(pcListPic->size()); i++)
+  {
+    listPic = *(iterListPic);
+    if (listPic->getPOC() == pcPic->getPOC() + 1)
+    {
+      nextPic = *(iterListPic);
+    }
+    iterListPic++;
+  }
+  return nextPic;
+}
+
+
+Picture* Picture::findPrevPicPOC(Picture* pcPic, PicList* pcListPic)
+{
+  Picture*  prevPic = NULL;
+  Picture*  listPic = NULL;
+  PicList::iterator  iterListPic = pcListPic->begin();
+  for (int i = 0; i < (int)(pcListPic->size()); i++)
+  {
+    listPic = *(iterListPic);
+    if (listPic->getPOC() == pcPic->getPOC() - 1)
+    {
+      prevPic = *(iterListPic);
+    }
+    iterListPic++;
+  }
+  return prevPic;
+}
+
+void Picture::xOutputPostFilteredPic(Picture* pcPic, PicList* pcListPic, int blendingRatio)
+{
+  const SPS *sps = pcPic->cs->sps;
+  const ChromaFormat chromaFormatIDC = sps->getChromaFormatIdc();
+
+  if ((pcPic->getPOC()) % blendingRatio != 0 || pcPic->getPOC() == 0)
+    pcPic->getPostRecBuf().copyFrom(pcPic->getRecoBuf());
+
+  if ((pcPic->getPOC() + 1) % blendingRatio == 0)
+  {
+    Picture* nextPic = findNextPicPOC(pcPic, pcListPic);
+    if (nextPic)
+    {
+#if DISABLE_PRE_POST_FILTER_FOR_IDR_CRA
+      if((nextPic->m_pictureType == NAL_UNIT_CODED_SLICE_IDR_W_RADL) ||
+        (nextPic->m_pictureType == NAL_UNIT_CODED_SLICE_IDR_N_LP) ||
+        (nextPic->m_pictureType == NAL_UNIT_CODED_SLICE_CRA))
+      {
+        nextPic->getPostRecBuf().copyFrom(nextPic->getRecoBuf());
+        return;
+      }
+#endif
+      PelUnitBuf currTmp = pcPic->getRecoBuf();
+      PelUnitBuf nextTmp = nextPic->getRecoBuf();
+      PelUnitBuf postTmp = nextPic->getPostRecBuf();
+
+      PelUnitBuf* currYuv = &currTmp;
+      PelUnitBuf* nextYuv = &nextTmp;
+      PelUnitBuf* postYuv = &postTmp;
+
+      int numValidComponents = getNumberValidComponents(chromaFormatIDC);
+      for (int chan = 0; chan < numValidComponents; chan++)
+      {
+        const ComponentID ch = ComponentID(chan);
+        const ChannelType cType = (ch == COMPONENT_Y) ? CHANNEL_TYPE_LUMA : CHANNEL_TYPE_CHROMA;
+        const int bitDepth = pcPic->cs->sps->getBitDepth(cType);
+        const int maxOutputValue = (1 << bitDepth) - 1;
+
+        Pel *currPxl, *nextPxl, *postPxl;
+        int iStride, iHeight, iWidth;
+        if (ch == COMPONENT_Y) {
+          currPxl = currYuv->Y().buf;
+          nextPxl = nextYuv->Y().buf;
+          postPxl = postYuv->Y().buf;
+          iStride = currYuv->Y().stride;
+          iHeight = currYuv->Y().height;
+          iWidth = currYuv->Y().width;
+        }
+        else if (ch == COMPONENT_Cb) {
+          nextPxl = nextYuv->Cb().buf;
+          currPxl = currYuv->Cb().buf;
+          postPxl = postYuv->Cb().buf;
+          iStride = currYuv->Cb().stride;
+          iHeight = currYuv->Cb().height;
+          iWidth = currYuv->Cb().width;
+        }
+        else {
+          nextPxl = nextYuv->Cr().buf;
+          currPxl = currYuv->Cr().buf;
+          postPxl = postYuv->Cr().buf;
+          iStride = currYuv->Cr().stride;
+          iHeight = currYuv->Cr().height;
+          iWidth = currYuv->Cr().width;
+        }
+        for (int y = 0; y < iHeight; y++)
+        {
+          for (int x = 0; x < iWidth; x++)
+          {
+#if ENABLE_USER_DEFINED_WEIGHTS
+            postPxl[x] = std::min(maxOutputValue, std::max(0, (int)(((nextPxl[x]) / SII_PF_W2) - ((currPxl[x] * SII_PF_W1) / SII_PF_W2))));
+#else
+            postPxl[x] = std::min(maxOutputValue, std::max(0, (((nextPxl[x] * (blendingRatio + 1)) / blendingRatio) - (currPxl[x] / blendingRatio))));
+#endif
+          }
+          currPxl += iStride;
+          nextPxl += iStride;
+          postPxl += iStride;
+        }
+      }
+    }
+  }
+}
+
+void Picture::xOutputPreFilteredPic(Picture* pcPic, PicList* pcListPic, int blendingRatio, int intraPeriod)
+{
+  const SPS *sps = pcPic->cs->sps;
+  const ChromaFormat chromaFormatIDC = sps->getChromaFormatIdc();
+#if DISABLE_PRE_POST_FILTER_FOR_IDR_CRA
+  if (pcPic->getPOC() == 0 ||
+    (pcPic->getPOC() % intraPeriod == 0))
+  {
+    return;
+  }
+#endif
+  if (pcPic->getPOC() % blendingRatio == 0)
+  {
+    Picture* prevPic = findPrevPicPOC(pcPic, pcListPic);
+    if (prevPic)
+    {
+      PelStorage* currYuv = &pcPic->m_bufs[PIC_ORIGINAL];
+      PelStorage* prevYuv = &prevPic->m_bufs[PIC_ORIGINAL];
+      int numValidComponents = getNumberValidComponents(chromaFormatIDC);
+      for (int chan = 0; chan < numValidComponents; chan++)
+      {
+        const ComponentID ch = ComponentID(chan);
+        const ChannelType cType = (ch == COMPONENT_Y) ? CHANNEL_TYPE_LUMA : CHANNEL_TYPE_CHROMA;
+        const int bitDepth = pcPic->cs->sps->getBitDepth(cType);
+        const int maxOutputValue = (1 << bitDepth) - 1;
+
+        Pel *currPxl, *prevPxl;
+        int iStride, iHeight, iWidth;
+        if (ch == COMPONENT_Y) {
+          currPxl = currYuv->Y().buf;
+          prevPxl = prevYuv->Y().buf;
+          iStride = currYuv->Y().stride;
+          iHeight = currYuv->Y().height;
+          iWidth = currYuv->Y().width;
+        }
+        else if (ch == COMPONENT_Cb) {
+          prevPxl = prevYuv->Cb().buf;
+          currPxl = currYuv->Cb().buf;
+          iStride = currYuv->Cb().stride;
+          iHeight = currYuv->Cb().height;
+          iWidth = currYuv->Cb().width;
+        }
+        else {
+          prevPxl = prevYuv->Cr().buf;
+          currPxl = currYuv->Cr().buf;
+          iStride = currYuv->Cr().stride;
+          iHeight = currYuv->Cr().height;
+          iWidth = currYuv->Cr().width;
+        }
+
+        for (int y = 0; y < iHeight; y++)
+        {
+          for (int x = 0; x < iWidth; x++)
+          {
+#if ENABLE_USER_DEFINED_WEIGHTS
+            currPxl[x] = std::min(maxOutputValue, std::max(0, (int)((currPxl[x] * SII_PF_W2) + (prevPxl[x] * SII_PF_W1));
+#else
+            currPxl[x] = std::min(maxOutputValue, std::max(0, (((currPxl[x] * blendingRatio) / (blendingRatio + 1)) + (prevPxl[x] / (blendingRatio + 1)))));
+#endif
+          }
+          currPxl += iStride;
+          prevPxl += iStride;
+        }
+      }
+    }
+  }
+}
+#endif
+
diff --git a/source/Lib/CommonLib/Picture.h b/source/Lib/CommonLib/Picture.h
index 84b89e693..0792db054 100644
--- a/source/Lib/CommonLib/Picture.h
+++ b/source/Lib/CommonLib/Picture.h
@@ -64,7 +64,11 @@ struct Picture : public UnitArea
   uint32_t margin;
   Picture();
 
+#if JVET_Z0120_SII_SEI_PROCESSING
+  void create(const ChromaFormat &_chromaFormat, const Size &size, const unsigned _maxCUSize, const unsigned margin, const bool bDecoder, const int layerId, const bool enablePostFilteringForHFR, const bool gopBasedTemporalFilterEnabled = false, const bool fgcSEIAnalysisEnabled = false);
+#else
   void create(const ChromaFormat &_chromaFormat, const Size &size, const unsigned _maxCUSize, const unsigned margin, const bool bDecoder, const int layerId, const bool gopBasedTemporalFilterEnabled = false, const bool fgcSEIAnalysisEnabled = false);
+#endif
   void destroy();
 
   void createTempBuffers( const unsigned _maxCUSize );
@@ -82,6 +86,14 @@ struct Picture : public UnitArea
   void              createColourTransfProcessor(bool firstPictureInSequence, SEIColourTransformApply* ctiCharacteristics, PelStorage* ctiBuf, int width, int height, ChromaFormat fmt, int bitDepth);
   PelUnitBuf        getDisplayBuf();
 
+#if JVET_Z0120_SII_SEI_PROCESSING
+  void copyToPic(const SPS *sps, PelStorage *pcPicYuvSrc, PelStorage *pcPicYuvDst);
+  Picture*  findPrevPicPOC(Picture* pcPic, PicList* pcListPic);
+  Picture*  findNextPicPOC(Picture* pcPic, PicList* pcListPic);
+  void  xOutputPostFilteredPic(Picture* pcPic, PicList* pcListPic, int blendingRatio);
+  void  xOutputPreFilteredPic(Picture* pcPic, PicList* pcListPic, int blendingRatio, int intraPeriod);
+#endif
+
          PelBuf     getOrigBuf(const CompArea &blk);
   const CPelBuf     getOrigBuf(const CompArea &blk) const;
          PelUnitBuf getOrigBuf(const UnitArea &unit);
@@ -128,6 +140,11 @@ struct Picture : public UnitArea
          PelUnitBuf getBuf(const UnitArea &unit,     const PictureType &type);
   const CPelUnitBuf getBuf(const UnitArea &unit,     const PictureType &type) const;
 
+#if JVET_Z0120_SII_SEI_PROCESSING
+        PelUnitBuf getPostRecBuf();
+  const CPelUnitBuf getPostRecBuf() const;
+#endif
+
   void extendPicBorder( const PPS *pps );
   void extendWrapBorder( const PPS *pps );
   void finalInit( const VPS* vps, const SPS& sps, const PPS& pps, PicHeader *picHeader, APS** alfApss, APS* lmcsAps, APS* scalingListAps );
diff --git a/source/Lib/CommonLib/SEI.cpp b/source/Lib/CommonLib/SEI.cpp
index dc5c10d26..778050f99 100644
--- a/source/Lib/CommonLib/SEI.cpp
+++ b/source/Lib/CommonLib/SEI.cpp
@@ -477,6 +477,9 @@ const char *SEI::getSEIMessageString(SEI::PayloadType payloadType)
     case SEI::EXTENDED_DRAP_INDICATION:             return "Extended DRAP indication";
     case SEI::CONSTRAINED_RASL_ENCODING:            return "Constrained RASL encoding";
     case SEI::VDI_SEI_ENVELOPE:                     return "Video decoding interface SEI envelope";
+#if JVET_Z0120_SHUTTER_INTERVAL_SEI
+    case SEI::SHUTTER_INTERVAL_INFO:                return "Shutter interval information";
+#endif
     default:                                        return "Unknown";
   }
 }
diff --git a/source/Lib/CommonLib/SEI.h b/source/Lib/CommonLib/SEI.h
index 51f16fb9e..0cb2f50e7 100644
--- a/source/Lib/CommonLib/SEI.h
+++ b/source/Lib/CommonLib/SEI.h
@@ -91,6 +91,9 @@ public:
     EXTENDED_DRAP_INDICATION             = 206,
     CONSTRAINED_RASL_ENCODING            = 207,
     VDI_SEI_ENVELOPE             = 208,
+#if JVET_Z0120_SHUTTER_INTERVAL_SEI
+    SHUTTER_INTERVAL_INFO                = 209,
+#endif
   };
 
   SEI() {}
@@ -101,6 +104,22 @@ public:
   virtual PayloadType payloadType() const = 0;
 };
 
+#if JVET_Z0120_SHUTTER_INTERVAL_SEI
+class SEIShutterIntervalInfo : public SEI
+{
+public:
+  PayloadType payloadType() const { return SHUTTER_INTERVAL_INFO; }
+  SEIShutterIntervalInfo() {}
+  virtual ~SEIShutterIntervalInfo() {}
+
+  bool                  m_siiEnabled;
+  unsigned              m_siiNumUnitsInShutterInterval;
+  unsigned              m_siiTimeScale;
+  unsigned              m_siiMaxSubLayersMinus1;
+  bool                  m_siiFixedSIwithinCLVS;
+  std::vector<unsigned> m_siiSubLayerNumUnitsInSI;
+};
+#endif
 
 class SEIEquirectangularProjection : public SEI
 {
diff --git a/source/Lib/CommonLib/Slice.cpp b/source/Lib/CommonLib/Slice.cpp
index 491a54036..282cc93d0 100644
--- a/source/Lib/CommonLib/Slice.cpp
+++ b/source/Lib/CommonLib/Slice.cpp
@@ -4470,7 +4470,11 @@ void Slice::scaleRefPicList( Picture *scaledRefPic[ ], PicHeader *picHeader, APS
 
             scaledRefPic[j]->poc = NOT_VALID;
 
+#if JVET_Z0120_SII_SEI_PROCESSING
+            scaledRefPic[j]->create( sps->getChromaFormatIdc(), Size( pps->getPicWidthInLumaSamples(), pps->getPicHeightInLumaSamples() ), sps->getMaxCUWidth(), sps->getMaxCUWidth() + 16, isDecoder, layerId, false);
+#else
             scaledRefPic[j]->create( sps->getChromaFormatIdc(), Size( pps->getPicWidthInLumaSamples(), pps->getPicHeightInLumaSamples() ), sps->getMaxCUWidth(), sps->getMaxCUWidth() + 16, isDecoder, layerId );
+#endif
           }
 
           scaledRefPic[j]->poc = poc;
diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h
index f6d058c43..e76c212af 100644
--- a/source/Lib/CommonLib/TypeDef.h
+++ b/source/Lib/CommonLib/TypeDef.h
@@ -56,6 +56,7 @@
 //########### place macros to be removed in next cycle below this line ###############
 #define JVET_Z0111_ADAPT_BYPASS_AFFINE_ME                 1 // JVET-Z0111 
 #define JVET_Z0046_Green_Metadata                         1 // JVET-Z0046
+#define JVET_Z0120_SHUTTER_INTERVAL_SEI                   1 // JVET-Z0120
 
 //########### place macros to be be kept below this line ###############
 #define JVET_X0143_ALF_APS_ID_OFFSET                      0 // A value between 0 to 7 inclusive. This macro should be kept, or to be defined as a configuration parameter if possible.
@@ -104,6 +105,12 @@ typedef std::pair<int, int>  TrCost;
 #define JVET_O0756_CALCULATE_HDRMETRICS                   1
 #endif
 
+#define JVET_Z0120_SII_SEI_PROCESSING                     1 // This is an example illustration of using SII SEI messages for backwards-compatible HFR video
+#if JVET_Z0120_SII_SEI_PROCESSING
+#define DISABLE_PRE_POST_FILTER_FOR_IDR_CRA               1
+#define ENABLE_USER_DEFINED_WEIGHTS                       0 // User can specify weights for both current and previous picture, such that their sum = 1
+#endif
+
 // clang-format on
 
 // ====================================================================================================================
diff --git a/source/Lib/DecoderLib/DecLib.cpp b/source/Lib/DecoderLib/DecLib.cpp
index 0cc95de27..6bef786dc 100644
--- a/source/Lib/DecoderLib/DecLib.cpp
+++ b/source/Lib/DecoderLib/DecLib.cpp
@@ -587,8 +587,12 @@ Picture* DecLib::xGetNewPicBuffer( const SPS &sps, const PPS &pps, const uint32_
   {
     pcPic = new Picture();
 
+#if JVET_Z0120_SII_SEI_PROCESSING
     pcPic->create(sps.getChromaFormatIdc(), Size(pps.getPicWidthInLumaSamples(), pps.getPicHeightInLumaSamples()),
-                  sps.getMaxCUWidth(), sps.getMaxCUWidth() + PIC_MARGIN, true, layerId);
+      sps.getMaxCUWidth(), sps.getMaxCUWidth() + PIC_MARGIN, true, layerId, getShutterFilterFlag() );
+#else
+    pcPic->create( sps.getChromaFormatIdc(), Size( pps.getPicWidthInLumaSamples(), pps.getPicHeightInLumaSamples() ), sps.getMaxCUWidth(), sps.getMaxCUWidth() + PIC_MARGIN, true, layerId );
+#endif
 
     m_cListPic.push_back( pcPic );
 
@@ -624,16 +628,23 @@ Picture* DecLib::xGetNewPicBuffer( const SPS &sps, const PPS &pps, const uint32_
 
     m_cListPic.push_back( pcPic );
 
-    pcPic->create(sps.getChromaFormatIdc(), Size(pps.getPicWidthInLumaSamples(), pps.getPicHeightInLumaSamples()),
-                  sps.getMaxCUWidth(), sps.getMaxCUWidth() + PIC_MARGIN, true, layerId);
+#if JVET_Z0120_SII_SEI_PROCESSING
+    pcPic->create(sps.getChromaFormatIdc(), Size(pps.getPicWidthInLumaSamples(), pps.getPicHeightInLumaSamples()), sps.getMaxCUWidth(), sps.getMaxCUWidth() + PIC_MARGIN, true, layerId, getShutterFilterFlag());
+#else
+    pcPic->create( sps.getChromaFormatIdc(), Size( pps.getPicWidthInLumaSamples(), pps.getPicHeightInLumaSamples() ), sps.getMaxCUWidth(), sps.getMaxCUWidth() + PIC_MARGIN, true, layerId );
+#endif
   }
   else
   {
     if( !pcPic->Y().Size::operator==( Size( pps.getPicWidthInLumaSamples(), pps.getPicHeightInLumaSamples() ) ) || pps.pcv->maxCUWidth != sps.getMaxCUWidth() || pps.pcv->maxCUHeight != sps.getMaxCUHeight() || pcPic->layerId != layerId )
     {
       pcPic->destroy();
-      pcPic->create(sps.getChromaFormatIdc(), Size(pps.getPicWidthInLumaSamples(), pps.getPicHeightInLumaSamples()),
-                    sps.getMaxCUWidth(), sps.getMaxCUWidth() + PIC_MARGIN, true, layerId);
+
+#if JVET_Z0120_SII_SEI_PROCESSING
+      pcPic->create( sps.getChromaFormatIdc(), Size( pps.getPicWidthInLumaSamples(), pps.getPicHeightInLumaSamples() ), sps.getMaxCUWidth(), sps.getMaxCUWidth() + PIC_MARGIN, true, layerId, getShutterFilterFlag());
+#else
+      pcPic->create( sps.getChromaFormatIdc(), Size( pps.getPicWidthInLumaSamples(), pps.getPicHeightInLumaSamples() ), sps.getMaxCUWidth(), sps.getMaxCUWidth() + PIC_MARGIN, true, layerId );
+#endif
     }
 #if GDR_ENABLED // picHeader should be deleted in case pcPic slot gets reused
     if (pcPic && pcPic->cs && pcPic->cs->picHeader)
diff --git a/source/Lib/DecoderLib/DecLib.h b/source/Lib/DecoderLib/DecLib.h
index 9edc78da0..61fd0c001 100644
--- a/source/Lib/DecoderLib/DecLib.h
+++ b/source/Lib/DecoderLib/DecLib.h
@@ -158,6 +158,9 @@ private:
   bool                    m_warningMessageSkipPicture;
 
   std::list<InputNALUnit*> m_prefixSEINALUs; /// Buffered up prefix SEI NAL Units.
+#if JVET_Z0120_SII_SEI_PROCESSING
+  bool                                m_ShutterFilterEnable;          ///< enable Post-processing with Shutter Interval SEI
+#endif
   int                     m_debugPOC;
   int                     m_debugCTU;
 
@@ -318,6 +321,11 @@ public:
 
   bool      getMixedNaluTypesInPicFlag();
 
+#if JVET_Z0120_SII_SEI_PROCESSING
+  bool  getShutterFilterFlag()        const { return m_ShutterFilterEnable; }
+  void  setShutterFilterFlag(bool value) { m_ShutterFilterEnable = value; }
+#endif
+
 protected:
   void  xUpdateRasInit(Slice* slice);
 
diff --git a/source/Lib/DecoderLib/SEIread.cpp b/source/Lib/DecoderLib/SEIread.cpp
index 9fceb6f98..c473b3a71 100644
--- a/source/Lib/DecoderLib/SEIread.cpp
+++ b/source/Lib/DecoderLib/SEIread.cpp
@@ -403,6 +403,12 @@ void SEIReader::xReadSEImessage(SEIMessages& seis, const NalUnitType nalUnitType
       sei = new SEIConstrainedRaslIndication;
       xParseSEIConstrainedRaslIndication((SEIConstrainedRaslIndication&) *sei, payloadSize, pDecodedMessageOutputStream);
       break;
+#if JVET_Z0120_SHUTTER_INTERVAL_SEI
+    case SEI::SHUTTER_INTERVAL_INFO:
+      sei = new SEIShutterIntervalInfo;
+      xParseSEIShutterInterval((SEIShutterIntervalInfo&)*sei, payloadSize, pDecodedMessageOutputStream);
+      break;
+#endif
     default:
       for (uint32_t i = 0; i < payloadSize; i++)
       {
@@ -533,6 +539,31 @@ void SEIReader::xParseSEIuserDataUnregistered(SEIuserDataUnregistered &sei, uint
   }
 }
 
+#if JVET_Z0120_SHUTTER_INTERVAL_SEI
+void SEIReader::xParseSEIShutterInterval(SEIShutterIntervalInfo& sei, uint32_t payloadSize, std::ostream *pDecodedMessageOutputStream)
+{
+  int32_t i;
+  uint32_t val;
+  output_sei_message_header(sei, pDecodedMessageOutputStream, payloadSize);
+  sei_read_code(pDecodedMessageOutputStream, 32, val, "sii_time_scale");                      sei.m_siiTimeScale = val;
+  sei_read_flag(pDecodedMessageOutputStream, val, "fixed_shutter_interval_within_clvs_flag"); sei.m_siiFixedSIwithinCLVS = val;
+  if (sei.m_siiFixedSIwithinCLVS)
+  {
+    sei_read_code(pDecodedMessageOutputStream, 32, val, "sii_num_units_in_shutter_interval");   sei.m_siiNumUnitsInShutterInterval = val;
+  }
+  else
+  {
+    sei_read_code(pDecodedMessageOutputStream, 3, val, "sii_max_sub_layers_minus1 ");          sei.m_siiMaxSubLayersMinus1 = val;
+    sei.m_siiSubLayerNumUnitsInSI.resize(sei.m_siiMaxSubLayersMinus1 + 1);
+    for (i = 0; i <= sei.m_siiMaxSubLayersMinus1; i++)
+    {
+      sei_read_code(pDecodedMessageOutputStream, 32, val, "sub_layer_num_units_in_shutter_interval[ i ]");
+      sei.m_siiSubLayerNumUnitsInSI[i] = val;
+    }
+  }
+}
+#endif
+
 /**
  * parse bitstream bs and unpack a decoded picture hash SEI message
  * of payloadSize bytes into sei.
diff --git a/source/Lib/DecoderLib/SEIread.h b/source/Lib/DecoderLib/SEIread.h
index 51495d9ca..80bce5755 100644
--- a/source/Lib/DecoderLib/SEIread.h
+++ b/source/Lib/DecoderLib/SEIread.h
@@ -103,6 +103,9 @@ protected:
   void xParseSEIExtendedDrapIndication        (SEIExtendedDrapIndication& sei,        uint32_t payloadSize,                     std::ostream *pDecodedMessageOutputStream);
   void xParseSEIColourTransformInfo           (SEIColourTransformInfo& sei, uint32_t payloadSize, std::ostream* pDecodedMessageOutputStream);
   void xParseSEIConstrainedRaslIndication     (SEIConstrainedRaslIndication& sei,     uint32_t payLoadSize,                     std::ostream *pDecodedMessageOutputStream);
+#if JVET_Z0120_SHUTTER_INTERVAL_SEI
+  void xParseSEIShutterInterval(SEIShutterIntervalInfo& sei, uint32_t payloadSize, std::ostream *pDecodedMessageOutputStream);
+#endif
 
   void sei_read_scode(std::ostream *pOS, uint32_t length, int& code, const char *pSymbolName);
   void sei_read_code(std::ostream *pOS, uint32_t length, uint32_t &ruiCode, const char *pSymbolName);
diff --git a/source/Lib/EncoderLib/EncCfg.h b/source/Lib/EncoderLib/EncCfg.h
index a80e3466c..bdaf7940e 100644
--- a/source/Lib/EncoderLib/EncCfg.h
+++ b/source/Lib/EncoderLib/EncCfg.h
@@ -180,6 +180,10 @@ protected:
   bool      m_printMSSSIM;
   bool      m_printWPSNR;
   bool      m_cabacZeroWordPaddingEnabled;
+#if JVET_Z0120_SII_SEI_PROCESSING
+  bool      m_ShutterFilterEnable;                          ///< enable Pre-Filtering with Shutter Interval SEI
+  int       m_SII_BlendingRatio;
+#endif
 
   bool      m_gciPresentFlag;
   bool      m_onePictureOnlyConstraintFlag;
@@ -654,6 +658,14 @@ protected:
   bool      m_alternativeTransferCharacteristicsSEIEnabled;
   uint8_t     m_preferredTransferCharacteristics;
 #endif
+
+#if JVET_Z0120_SHUTTER_INTERVAL_SEI
+  bool                    m_siiSEIEnabled;
+  uint32_t                m_siiSEINumUnitsInShutterInterval;
+  uint32_t                m_siiSEITimeScale;
+  std::vector<uint32_t>   m_siiSEISubLayerNumUnitsInSI;
+#endif
+
   // film grain characterstics sei
   bool      m_fgcSEIEnabled;
   bool      m_fgcSEICancelFlag;
@@ -1087,6 +1099,14 @@ public:
   bool      getCabacZeroWordPaddingEnabled()           const { return m_cabacZeroWordPaddingEnabled;  }
   void      setCabacZeroWordPaddingEnabled(bool value)       { m_cabacZeroWordPaddingEnabled = value; }
 
+#if JVET_Z0120_SII_SEI_PROCESSING
+  bool      getShutterFilterFlag()              const { return m_ShutterFilterEnable; }
+  void      setShutterFilterFlag(bool value) { m_ShutterFilterEnable = value; }
+
+  int       getBlendingRatioSII()             const { return m_SII_BlendingRatio; }
+  void      setBlendingRatioSII(int value) { m_SII_BlendingRatio = value; }
+#endif
+
   //====== Coding Structure ========
   void      setIntraPeriod                  (int   i)        { m_intraPeriod = i;                   }
   void      setDecodingRefreshType          ( int   i )      { m_decodingRefreshType = (uint32_t)i; }
@@ -1696,6 +1716,18 @@ public:
   void  setSubpicDecodedPictureHashType(HashType m)                  { m_subpicDecodedPictureHashType = m; }
   HashType getSubpicDecodedPictureHashType() const                   { return m_subpicDecodedPictureHashType; }
 
+#if JVET_Z0120_SHUTTER_INTERVAL_SEI
+  void     setSiiSEIEnabled(bool b) { m_siiSEIEnabled = b; }
+  bool     getSiiSEIEnabled() { return m_siiSEIEnabled; }
+  void     setSiiSEINumUnitsInShutterInterval(uint32_t value) { m_siiSEINumUnitsInShutterInterval = value; }
+  uint32_t getSiiSEINumUnitsInShutterInterval() { return m_siiSEINumUnitsInShutterInterval; }
+  void     setSiiSEITimeScale(uint32_t value) { m_siiSEITimeScale = value; }
+  uint32_t getSiiSEITimeScale() { return m_siiSEITimeScale; }
+  uint32_t getSiiSEIMaxSubLayersMinus1() { return uint32_t(std::max(1u, uint32_t(m_siiSEISubLayerNumUnitsInSI.size())) - 1); }
+  bool     getSiiSEIFixedSIwithinCLVS() { return m_siiSEISubLayerNumUnitsInSI.empty(); }
+  void     setSiiSEISubLayerNumUnitsInSI(const std::vector<uint32_t>& b) { m_siiSEISubLayerNumUnitsInSI = b; }
+  uint32_t getSiiSEISubLayerNumUnitsInSI(uint32_t idx) const { return m_siiSEISubLayerNumUnitsInSI[idx]; }
+#endif
   void  setBufferingPeriodSEIEnabled(bool b)                         { m_bufferingPeriodSEIEnabled = b; }
   bool  getBufferingPeriodSEIEnabled() const                         { return m_bufferingPeriodSEIEnabled; }
   void  setPictureTimingSEIEnabled(bool b)                           { m_pictureTimingSEIEnabled = b; }
diff --git a/source/Lib/EncoderLib/EncGOP.cpp b/source/Lib/EncoderLib/EncGOP.cpp
index df0356600..c12f5fac2 100644
--- a/source/Lib/EncoderLib/EncGOP.cpp
+++ b/source/Lib/EncoderLib/EncGOP.cpp
@@ -844,6 +844,14 @@ void EncGOP::xCreateIRAPLeadingSEIMessages (SEIMessages& seiMessages, const SPS
     SEIConstrainedRaslIndication* seiConstrainedRasl = new SEIConstrainedRaslIndication;
     seiMessages.push_back(seiConstrainedRasl);
   }
+#if JVET_Z0120_SHUTTER_INTERVAL_SEI
+  if (m_pcCfg->getSiiSEIEnabled())
+  {
+    SEIShutterIntervalInfo *seiShutterInterval = new SEIShutterIntervalInfo;
+    m_seiEncoder.initSEIShutterIntervalInfo(seiShutterInterval);
+    seiMessages.push_back(seiShutterInterval);
+  }
+#endif
 }
 
 void EncGOP::xCreatePerPictureSEIMessages (int picInGOP, SEIMessages& seiMessages, SEIMessages& nestedSeiMessages, Slice *slice)
diff --git a/source/Lib/EncoderLib/EncLib.cpp b/source/Lib/EncoderLib/EncLib.cpp
index 685c3aaee..2480c4aa4 100644
--- a/source/Lib/EncoderLib/EncLib.cpp
+++ b/source/Lib/EncoderLib/EncLib.cpp
@@ -487,6 +487,16 @@ bool EncLib::encodePrep( bool flush, PelStorage* pcPicYuvOrg, PelStorage* cPicYu
 #endif
     picCurr->poc = m_iPOCLast - 1;
     m_iPOCLast -= 2;
+
+#if JVET_Z0120_SII_SEI_PROCESSING
+    if (getShutterFilterFlag())
+    {
+      int blendingRatio = getBlendingRatioSII();
+      picCurr->xOutputPreFilteredPic(picCurr, &m_cListPic, blendingRatio, m_intraPeriod);
+      picCurr->copyToPic(sps, &picCurr->m_bufs[PIC_ORIGINAL], pcPicYuvOrg);
+    }
+#endif
+
     if( getUseAdaptiveQP() )
     {
       AQpPreanalyzer::preanalyze( picCurr );
@@ -620,6 +630,15 @@ bool EncLib::encodePrep( bool flush, PelStorage* pcPicYuvOrg, PelStorage* cPicYu
 
     pcPicCurr->poc = m_iPOCLast;
 
+#if JVET_Z0120_SII_SEI_PROCESSING
+    if (getShutterFilterFlag())
+    {
+      int blendingRatio = getBlendingRatioSII();
+      pcPicCurr->xOutputPreFilteredPic(pcPicCurr, &m_cListPic, blendingRatio, m_intraPeriod);
+      pcPicCurr->copyToPic(pSPS, &pcPicCurr->m_bufs[PIC_ORIGINAL], pcPicYuvOrg);
+    }
+#endif
+
     // compute image characteristics
     if( getUseAdaptiveQP() )
     {
@@ -776,6 +795,15 @@ bool EncLib::encodePrep( bool flush, PelStorage* pcPicYuvOrg, PelStorage* pcPicY
 
       pcField->topField = isTopField;                  // interlaced requirement
 
+#if JVET_Z0120_SII_SEI_PROCESSING
+      if (getShutterFilterFlag())
+      {
+        int blendingRatio = getBlendingRatioSII();
+        pcField->xOutputPreFilteredPic(pcField, &m_cListPic, blendingRatio, m_intraPeriod);
+        pcField->copyToPic(pSPS, &pcField->m_bufs[PIC_ORIGINAL], pcPicYuvOrg);
+      }
+#endif
+
       // compute image characteristics
       if( getUseAdaptiveQP() )
       {
@@ -890,9 +918,16 @@ void EncLib::xGetNewPicBuffer ( std::list<PelUnitBuf*>& rcListPicYuvRecOut, Pict
   if (rpcPic==0)
   {
     rpcPic = new Picture;
+
+#if JVET_Z0120_SII_SEI_PROCESSING
     rpcPic->create(sps.getChromaFormatIdc(), Size(pps.getPicWidthInLumaSamples(), pps.getPicHeightInLumaSamples()),
-                   sps.getMaxCUWidth(), sps.getMaxCUWidth() + PIC_MARGIN, false, m_layerId,
+      sps.getMaxCUWidth(), sps.getMaxCUWidth() + PIC_MARGIN, false, m_layerId, getShutterFilterFlag(),
                    getGopBasedTemporalFilterEnabled(), m_fgcSEIAnalysisEnabled);
+#else
+    rpcPic->create( sps.getChromaFormatIdc(), Size( pps.getPicWidthInLumaSamples(), pps.getPicHeightInLumaSamples() ), sps.getMaxCUWidth(), sps.getMaxCUWidth() + PIC_MARGIN, false, m_layerId, getGopBasedTemporalFilterEnabled()
+                   , m_fgcSEIAnalysisEnabled);
+#endif
+
     if (m_resChangeInClvsEnabled)
     {
       const PPS &pps0 = *m_ppsMap.getPS(0);
diff --git a/source/Lib/EncoderLib/SEIEncoder.cpp b/source/Lib/EncoderLib/SEIEncoder.cpp
index fe2e467a5..3422168f8 100644
--- a/source/Lib/EncoderLib/SEIEncoder.cpp
+++ b/source/Lib/EncoderLib/SEIEncoder.cpp
@@ -507,6 +507,28 @@ void SEIEncoder::initSEIExtendedDrapIndication(SEIExtendedDrapIndication *sei)
   }
 }
 
+#if JVET_Z0120_SHUTTER_INTERVAL_SEI
+void SEIEncoder::initSEIShutterIntervalInfo(SEIShutterIntervalInfo *seiShutterIntervalInfo)
+{
+  assert(m_isInitialized);
+  assert(seiShutterIntervalInfo != NULL);
+  seiShutterIntervalInfo->m_siiTimeScale = m_pcCfg->getSiiSEITimeScale();
+  seiShutterIntervalInfo->m_siiFixedSIwithinCLVS = m_pcCfg->getSiiSEIFixedSIwithinCLVS();
+  if (seiShutterIntervalInfo->m_siiFixedSIwithinCLVS == true)
+  {
+    seiShutterIntervalInfo->m_siiNumUnitsInShutterInterval = m_pcCfg->getSiiSEINumUnitsInShutterInterval();
+  }
+  else
+  {
+    seiShutterIntervalInfo->m_siiMaxSubLayersMinus1 = m_pcCfg->getSiiSEIMaxSubLayersMinus1();
+    seiShutterIntervalInfo->m_siiSubLayerNumUnitsInSI.resize(seiShutterIntervalInfo->m_siiMaxSubLayersMinus1 + 1);
+    for (int32_t i = 0; i <= seiShutterIntervalInfo->m_siiMaxSubLayersMinus1; i++)
+    {
+      seiShutterIntervalInfo->m_siiSubLayerNumUnitsInSI[i] = m_pcCfg->getSiiSEISubLayerNumUnitsInSI(i);
+    }
+  }
+}
+#endif
 
 template <typename T>
 static void readTokenValue(T            &returnedValue, /// value returned
diff --git a/source/Lib/EncoderLib/SEIEncoder.h b/source/Lib/EncoderLib/SEIEncoder.h
index 778455018..4382de86e 100644
--- a/source/Lib/EncoderLib/SEIEncoder.h
+++ b/source/Lib/EncoderLib/SEIEncoder.h
@@ -90,6 +90,9 @@ public:
   void initSEIColourTransformInfo(SEIColourTransformInfo* sei);
   void readAnnotatedRegionSEI(std::istream &fic, SEIAnnotatedRegions *seiAnnoRegion, bool &failed);
   void initSEIMultiviewViewPosition(SEIMultiviewViewPosition *sei);
+#if JVET_Z0120_SHUTTER_INTERVAL_SEI
+  void initSEIShutterIntervalInfo(SEIShutterIntervalInfo *sei);
+#endif
 private:
   EncCfg* m_pcCfg;
   EncLib* m_pcEncLib;
diff --git a/source/Lib/EncoderLib/SEIwrite.cpp b/source/Lib/EncoderLib/SEIwrite.cpp
index 4882067ef..fbceadccf 100644
--- a/source/Lib/EncoderLib/SEIwrite.cpp
+++ b/source/Lib/EncoderLib/SEIwrite.cpp
@@ -157,6 +157,11 @@ void SEIWriter::xWriteSEIpayloadData(OutputBitstream &bs, const SEI& sei, HRD &h
   case SEI::CONSTRAINED_RASL_ENCODING:
     xWriteSEIConstrainedRaslIndication(*static_cast<const SEIConstrainedRaslIndication*>(&sei));
     break;
+#if JVET_Z0120_SHUTTER_INTERVAL_SEI
+  case SEI::SHUTTER_INTERVAL_INFO:
+    xWriteSEIShutterInterval(*static_cast<const SEIShutterIntervalInfo*>(&sei));
+    break;
+#endif
   default:
     THROW("Trying to write unhandled SEI message");
     break;
@@ -1353,6 +1358,26 @@ void SEIWriter::xWriteSEIColourTransformInfo(const SEIColourTransformInfo& sei)
   }
 }
 
+#if JVET_Z0120_SHUTTER_INTERVAL_SEI
+void SEIWriter::xWriteSEIShutterInterval(const SEIShutterIntervalInfo &sei)
+{
+  WRITE_CODE(sei.m_siiTimeScale, 32, "sii_time_scale");
+  WRITE_FLAG(sei.m_siiFixedSIwithinCLVS, "fixed_shutter_interval_within_clvs_flag");
+  if (sei.m_siiFixedSIwithinCLVS)
+  {
+    WRITE_CODE(sei.m_siiNumUnitsInShutterInterval, 32, "sii_num_units_in_shutter_interval");
+  }
+  else
+  {
+    WRITE_CODE(sei.m_siiMaxSubLayersMinus1, 3, "sii_max_sub_layers_minus1");
+    for (unsigned i = 0; i <= sei.m_siiMaxSubLayersMinus1; i++)
+    {
+      WRITE_CODE(sei.m_siiSubLayerNumUnitsInSI[i], 32, "sub_layer_num_units_in_shutter_interval[ i ]");
+    }
+  }
+}
+#endif
+
 void SEIWriter::xWriteSEIConstrainedRaslIndication(const SEIConstrainedRaslIndication& /*sei*/)
 {
   // intentionally empty
diff --git a/source/Lib/EncoderLib/SEIwrite.h b/source/Lib/EncoderLib/SEIwrite.h
index 84dbc9139..1e7b07536 100644
--- a/source/Lib/EncoderLib/SEIwrite.h
+++ b/source/Lib/EncoderLib/SEIwrite.h
@@ -89,6 +89,9 @@ protected:
   void xWriteSEIContentColourVolume(const SEIContentColourVolume &sei);
   void xWriteSEIColourTransformInfo(const SEIColourTransformInfo& sei);
   void xWriteSEIAnnotatedRegions                  (const SEIAnnotatedRegions& sei);
+#if JVET_Z0120_SHUTTER_INTERVAL_SEI
+  void xWriteSEIShutterInterval(const SEIShutterIntervalInfo& sei);
+#endif
   void xWriteSEIpayloadData(OutputBitstream &bs, const SEI& sei, HRD &hrd, const uint32_t temporalId);
   void xWriteByteAlign();
 protected:
-- 
GitLab