From e561f2d16087ff338f88634d67212f6dd1bbe32b Mon Sep 17 00:00:00 2001
From: Kammachi Sreedhar <kashyap.kammachi-sreedhar@nokia.com>
Date: Wed, 10 Apr 2019 12:02:26 +0300
Subject: [PATCH] JVET_N0067_NALU_Header_v1

---
 source/App/DecoderApp/DecApp.cpp           |  5 +++
 source/App/Parcat/parcat.cpp               | 39 +++++++++++++++++
 source/App/SEIRemovalApp/SEIRemovalApp.cpp | 22 ++++++++++
 source/Lib/CommonLib/NAL.h                 | 35 ++++++++++++++++
 source/Lib/CommonLib/Rom.cpp               | 22 ++++++++++
 source/Lib/CommonLib/Slice.cpp             |  5 +++
 source/Lib/CommonLib/Slice.h               |  5 +++
 source/Lib/CommonLib/TypeDef.h             | 42 +++++++++++++++++++
 source/Lib/DecoderLib/DecLib.cpp           | 18 ++++++++
 source/Lib/DecoderLib/NALread.cpp          | 49 +++++++++++++++++++++-
 source/Lib/EncoderLib/NALwrite.cpp         | 13 +++++-
 source/Lib/EncoderLib/NALwrite.h           |  7 ++++
 12 files changed, 259 insertions(+), 3 deletions(-)

diff --git a/source/App/DecoderApp/DecApp.cpp b/source/App/DecoderApp/DecApp.cpp
index 7735309af..3e15f4a72 100644
--- a/source/App/DecoderApp/DecApp.cpp
+++ b/source/App/DecoderApp/DecApp.cpp
@@ -252,10 +252,15 @@ uint32_t DecApp::decode()
         m_cDecLib.setFirstSliceInPicture (false);
       }
       // write reconstruction to file -- for additional bumping as defined in C.5.2.3
+#if JVET_N0067_NAL_Unit_Header
+      if (!bNewPicture && ((nalu.m_nalUnitType >= NAL_UNIT_CODED_SLICE_TRAIL && nalu.m_nalUnitType <= NAL_UNIT_RESERVED_VCL_15)
+        || (nalu.m_nalUnitType >= NAL_UNIT_CODED_SLICE_IDR_W_RADL && nalu.m_nalUnitType <= NAL_UNIT_CODED_SLICE_GRA)))
+#else
 #if !JVET_M0101_HLS
       if(!bNewPicture && nalu.m_nalUnitType >= NAL_UNIT_CODED_SLICE_TRAIL_N && nalu.m_nalUnitType <= NAL_UNIT_RESERVED_VCL31)
 #else
       if (!bNewPicture && nalu.m_nalUnitType >= NAL_UNIT_CODED_SLICE_TRAIL && nalu.m_nalUnitType <= NAL_UNIT_RESERVED_VCL15)
+#endif
 #endif
       {
         xWriteOutput( pcListPic, nalu.m_temporalId );
diff --git a/source/App/Parcat/parcat.cpp b/source/App/Parcat/parcat.cpp
index d85c356d8..aadd68f64 100644
--- a/source/App/Parcat/parcat.cpp
+++ b/source/App/Parcat/parcat.cpp
@@ -102,6 +102,40 @@ const bool verbose = false;
 
 const char * NALU_TYPE[] =
 {
+#if JVET_N0067_NAL_Unit_Header
+    "NAL_UNIT_PPS",
+    "NAL_UNIT_ACCESS_UNIT_DELIMITER",
+    "NAL_UNIT_PREFIX_SEI",
+    "NAL_UNIT_SUFFIX_SEI",
+    "NAL_UNIT_APS",
+    "NAL_UNIT_RESERVED_NVCL_5",
+    "NAL_UNIT_RESERVED_NVCL_6",
+    "NAL_UNIT_RESERVED_NVCL_7",
+    "NAL_UNIT_CODED_SLICE_TRAIL",
+    "NAL_UNIT_CODED_SLICE_STSA",
+    "NAL_UNIT_CODED_SLICE_RADL",
+    "NAL_UNIT_CODED_SLICE_RASL",
+    "NAL_UNIT_RESERVED_VCL_12",
+    "NAL_UNIT_RESERVED_VCL_13",
+    "NAL_UNIT_RESERVED_VCL_14",
+    "NAL_UNIT_RESERVED_VCL_15",
+    "NAL_UNIT_DPS",
+    "NAL_UNIT_SPS",
+    "NAL_UNIT_EOS",
+    "NAL_UNIT_EOB",
+    "NAL_UNIT_VPS",
+    "NAL_UNIT_RESERVED_NVCL_21",
+    "NAL_UNIT_RESERVED_NVCL_22",
+    "NAL_UNIT_RESERVED_NVCL_23",
+    "NAL_UNIT_CODED_SLICE_IDR_W_RADL",
+    "NAL_UNIT_CODED_SLICE_IDR_N_LP",
+    "NAL_UNIT_CODED_SLICE_CRA",
+    "NAL_UNIT_CODED_SLICE_GRA",
+    "NAL_UNIT_UNSPECIFIED_28",
+    "NAL_UNIT_UNSPECIFIED_29",
+    "NAL_UNIT_UNSPECIFIED_30",
+    "NAL_UNIT_UNSPECIFIED_31"
+#else
 #if !JVET_M0101_HLS
     "TRAIL_N",
     "TRAIL_R",
@@ -196,6 +230,7 @@ const char * NALU_TYPE[] =
     "NAL_UNIT_UNSPECIFIED_30",
     "NAL_UNIT_UNSPECIFIED_31"
 #endif
+#endif
 };
 
 int calc_poc(int iPOClsb, int prevTid0POC, int getBitsForPOC, int nalu_type)
@@ -280,10 +315,14 @@ std::vector<uint8_t> filter_segment(const std::vector<uint8_t> & v, int idx, int
       int offset = 16;
 
       offset += 1; //first_slice_segment_in_pic_flag
+#if JVET_N0067_NAL_Unit_Header
+      if (nalu_type >= NAL_UNIT_CODED_SLICE_IDR_W_RADL && nalu_type <= NAL_UNIT_CODED_SLICE_CRA)
+#else
 #if !JVET_M0101_HLS
       if (nalu_type >= NAL_UNIT_CODED_SLICE_BLA_W_LP && nalu_type <= NAL_UNIT_RESERVED_IRAP_VCL23)
 #else
       if (nalu_type >= NAL_UNIT_CODED_SLICE_IDR_W_RADL && nalu_type <= NAL_UNIT_RESERVED_IRAP_VCL13)
+#endif
 #endif
       {
         offset += 1; //no_output_of_prior_pics_flag
diff --git a/source/App/SEIRemovalApp/SEIRemovalApp.cpp b/source/App/SEIRemovalApp/SEIRemovalApp.cpp
index dd22baa52..c4d21a4bd 100644
--- a/source/App/SEIRemovalApp/SEIRemovalApp.cpp
+++ b/source/App/SEIRemovalApp/SEIRemovalApp.cpp
@@ -72,11 +72,33 @@ void read2(InputNALUnit& nalu)
 {
   InputBitstream& bs = nalu.getBitstream();
 
+  #if JVET_N0067_NAL_Unit_Header
+  nalu.m_zeroTidRequiredFlag = bs.read(1);            // zero_tid_required_flag
+  nalu.m_temporalId = bs.read(3) - 1;                 // nuh_temporal_id_plus1
+  if(nalu.m_temporalId < 0) {
+    THROW( "Temporal ID is negative." );
+  }
+  //When zero_tid_required_flag is equal to 1, the value of nuh_temporal_id_plus1 shall be equal to 1.
+  if((nalu.m_zeroTidRequiredFlag == 1) && (nalu.m_temporalId != 0)) {
+    THROW( "Temporal ID is not '0' when zero tid is required." );
+  }
+  uint32_t m_nalUnitTypeLsb = bs.read(4);             // nal_unit_type_lsb
+  nalu.m_nalUnitType = (NalUnitType) ((nalu.m_zeroTidRequiredFlag << 4) + m_nalUnitTypeLsb);
+  nalu.m_nuhLayerId = bs.read(7);                     // nuh_layer_id
+  if((nalu.m_nuhLayerId < 0) || (nalu.m_nuhLayerId > 126)) {
+    THROW( "Layer ID out of range" );
+  }
+  uint32_t nuh_reserved_zero_bit = bs.read(1);        // nuh_reserved_zero_bit
+  if(nuh_reserved_zero_bit != 0) {
+    THROW( "Reserved zero bit is not '0'" );
+  }
+#else
   bool forbidden_zero_bit = bs.read(1);           // forbidden_zero_bit
   if(forbidden_zero_bit != 0) { THROW( "Forbidden zero-bit not '0'" );}
   nalu.m_nalUnitType = (NalUnitType) bs.read(6);  // nal_unit_type
   nalu.m_nuhLayerId = bs.read(6);                 // nuh_layer_id
   nalu.m_temporalId = bs.read(3) - 1;             // nuh_temporal_id_plus1
+#endif
 }
 
 uint32_t SEIRemovalApp::decode()
diff --git a/source/Lib/CommonLib/NAL.h b/source/Lib/CommonLib/NAL.h
index 57f98f781..7d074fde8 100644
--- a/source/Lib/CommonLib/NAL.h
+++ b/source/Lib/CommonLib/NAL.h
@@ -48,20 +48,32 @@ class OutputBitstream;
 struct NALUnit
 {
   NalUnitType m_nalUnitType; ///< nal_unit_type
+#if JVET_N0067_NAL_Unit_Header
+  uint32_t        m_zeroTidRequiredFlag;  ///< zero_tid_required_flag
+#endif
   uint32_t        m_temporalId;  ///< temporal_id
   uint32_t        m_nuhLayerId;  ///< nuh_layer_id
 
   NALUnit(const NALUnit &src)
   :m_nalUnitType (src.m_nalUnitType)
+#if JVET_N0067_NAL_Unit_Header
+  ,m_zeroTidRequiredFlag (src.m_zeroTidRequiredFlag)
+#endif
   ,m_temporalId  (src.m_temporalId)
   ,m_nuhLayerId  (src.m_nuhLayerId)
   { }
   /** construct an NALunit structure with given header values. */
   NALUnit(
     NalUnitType nalUnitType,
+#if JVET_N0067_NAL_Unit_Header
+    int         zeroTidRequiredFlag = 0,
+#endif
     int         temporalId = 0,
     int         nuhLayerId = 0)
     :m_nalUnitType (nalUnitType)
+#if JVET_N0067_NAL_Unit_Header
+    ,m_zeroTidRequiredFlag (zeroTidRequiredFlag)
+#endif
     ,m_temporalId  (temporalId)
     ,m_nuhLayerId  (nuhLayerId)
   {}
@@ -74,6 +86,16 @@ struct NALUnit
   /** returns true if the NALunit is a slice NALunit */
   bool isSlice()
   {
+#if JVET_N0067_NAL_Unit_Header
+    return m_nalUnitType == NAL_UNIT_CODED_SLICE_TRAIL
+        || m_nalUnitType == NAL_UNIT_CODED_SLICE_STSA
+        || m_nalUnitType == NAL_UNIT_CODED_SLICE_IDR_W_RADL
+        || m_nalUnitType == NAL_UNIT_CODED_SLICE_IDR_N_LP
+        || m_nalUnitType == NAL_UNIT_CODED_SLICE_CRA
+        || m_nalUnitType == NAL_UNIT_CODED_SLICE_GRA
+        || m_nalUnitType == NAL_UNIT_CODED_SLICE_RADL
+        || m_nalUnitType == NAL_UNIT_CODED_SLICE_RASL;
+#else
 #if JVET_M0101_HLS
     return m_nalUnitType == NAL_UNIT_CODED_SLICE_TRAIL
         || m_nalUnitType == NAL_UNIT_CODED_SLICE_STSA
@@ -99,6 +121,7 @@ struct NALUnit
         || m_nalUnitType == NAL_UNIT_CODED_SLICE_RADL_R
         || m_nalUnitType == NAL_UNIT_CODED_SLICE_RASL_N
         || m_nalUnitType == NAL_UNIT_CODED_SLICE_RASL_R;
+#endif
 #endif
   }
   bool isSei()
@@ -109,7 +132,19 @@ struct NALUnit
 
   bool isVcl()
   {
+#if JVET_N0067_NAL_Unit_Header
+    return m_nalUnitType == NAL_UNIT_CODED_SLICE_TRAIL
+        || m_nalUnitType == NAL_UNIT_CODED_SLICE_STSA
+        || m_nalUnitType == NAL_UNIT_CODED_SLICE_RADL
+        || m_nalUnitType == NAL_UNIT_CODED_SLICE_RASL
+        || m_nalUnitType == NAL_UNIT_CODED_SLICE_IDR_W_RADL
+        || m_nalUnitType == NAL_UNIT_CODED_SLICE_IDR_N_LP
+        || m_nalUnitType == NAL_UNIT_CODED_SLICE_CRA
+        || m_nalUnitType == NAL_UNIT_CODED_SLICE_GRA;
+
+#else
     return ( (uint32_t)m_nalUnitType < 32 );
+#endif
   }
 };
 
diff --git a/source/Lib/CommonLib/Rom.cpp b/source/Lib/CommonLib/Rom.cpp
index 93f56a948..3caa639c9 100644
--- a/source/Lib/CommonLib/Rom.cpp
+++ b/source/Lib/CommonLib/Rom.cpp
@@ -63,6 +63,27 @@ const char* nalUnitTypeToString(NalUnitType type)
 {
   switch (type)
   {
+#if JVET_N0067_NAL_Unit_Header
+  case NAL_UNIT_PPS:                    return "PPS";
+  case NAL_UNIT_ACCESS_UNIT_DELIMITER:  return "AUD";
+  case NAL_UNIT_PREFIX_SEI:             return "Prefix SEI";
+  case NAL_UNIT_SUFFIX_SEI:             return "Suffix SEI";
+  case NAL_UNIT_APS:                    return "APS";
+  case NAL_UNIT_CODED_SLICE_TRAIL:      return "TRAIL";
+  case NAL_UNIT_CODED_SLICE_STSA:       return "STSA";
+  case NAL_UNIT_CODED_SLICE_RADL:       return "RADL";
+  case NAL_UNIT_CODED_SLICE_RASL:       return "RASL";
+  case NAL_UNIT_DPS:                    return "DPS";
+  case NAL_UNIT_SPS:                    return "SPS";
+  case NAL_UNIT_EOS:                    return "EOS";
+  case NAL_UNIT_EOB:                    return "EOB";
+  case NAL_UNIT_VPS:                    return "VPS";
+  case NAL_UNIT_CODED_SLICE_IDR_W_RADL: return "IDR_W_RADL";
+  case NAL_UNIT_CODED_SLICE_IDR_N_LP:   return "IDR_N_LP";
+  case NAL_UNIT_CODED_SLICE_CRA:        return "CRA"; 
+  case NAL_UNIT_CODED_SLICE_GRA:        return "GRA";
+  default:                              return "UNK";
+#else
 #if JVET_M0101_HLS
   case NAL_UNIT_CODED_SLICE_TRAIL:      return "TRAIL";
   case NAL_UNIT_CODED_SLICE_STSA:       return "STSA";
@@ -114,6 +135,7 @@ const char* nalUnitTypeToString(NalUnitType type)
   case NAL_UNIT_PREFIX_SEI:             return "Prefix SEI";
   case NAL_UNIT_SUFFIX_SEI:             return "Suffix SEI";
   default:                              return "UNK";
+#endif
 #endif
   }
 }
diff --git a/source/Lib/CommonLib/Slice.cpp b/source/Lib/CommonLib/Slice.cpp
index 2e3d9d158..3a6589db6 100644
--- a/source/Lib/CommonLib/Slice.cpp
+++ b/source/Lib/CommonLib/Slice.cpp
@@ -929,12 +929,17 @@ void Slice::checkLeadingPictureRestrictions(PicList& rcListPic) const
   if(this->getAssociatedIRAPPOC() > this->getPOC())
   {
     // Do not check IRAP pictures since they may get a POC lower than their associated IRAP
+#if JVET_N0067_NAL_Unit_Header
+    if (nalUnitType < NAL_UNIT_CODED_SLICE_IDR_W_RADL ||
+        nalUnitType > NAL_UNIT_CODED_SLICE_CRA)
+#else
 #if !JVET_M0101_HLS
     if(nalUnitType < NAL_UNIT_CODED_SLICE_BLA_W_LP ||
        nalUnitType > NAL_UNIT_RESERVED_IRAP_VCL23)
 #else
     if (nalUnitType < NAL_UNIT_CODED_SLICE_IDR_W_RADL ||
         nalUnitType > NAL_UNIT_RESERVED_IRAP_VCL13)
+#endif
 #endif
     {
 #if !JVET_M0101_HLS
diff --git a/source/Lib/CommonLib/Slice.h b/source/Lib/CommonLib/Slice.h
index c69de4f1f..950be8544 100644
--- a/source/Lib/CommonLib/Slice.h
+++ b/source/Lib/CommonLib/Slice.h
@@ -1949,12 +1949,17 @@ public:
   NalUnitType                 getNalUnitType() const                                 { return m_eNalUnitType;                                        }
   bool                        getRapPicFlag() const;
   bool                        getIdrPicFlag() const                                  { return getNalUnitType() == NAL_UNIT_CODED_SLICE_IDR_W_RADL || getNalUnitType() == NAL_UNIT_CODED_SLICE_IDR_N_LP; }
+#if JVET_N0067_NAL_Unit_Header
+  bool                        isIRAP() const { return (getNalUnitType() >= NAL_UNIT_CODED_SLICE_IDR_W_RADL) && (getNalUnitType() <= NAL_UNIT_CODED_SLICE_CRA); }
+  bool                        isIDRorBLA() const { return (getNalUnitType() == NAL_UNIT_CODED_SLICE_IDR_W_RADL) || (getNalUnitType() == NAL_UNIT_CODED_SLICE_IDR_N_LP); }
+#else
 #if !JVET_M0101_HLS
   bool                        isIRAP() const                                         { return (getNalUnitType() >= 16) && (getNalUnitType() <= 23);  }
   bool                        isIDRorBLA() const                                      { return (getNalUnitType() >= 16) && (getNalUnitType() <= 20);  }
 #else
   bool                        isIRAP() const { return (getNalUnitType() >= NAL_UNIT_CODED_SLICE_IDR_W_RADL) && (getNalUnitType() <= NAL_UNIT_RESERVED_IRAP_VCL13); }
   bool                        isIDRorBLA() const { return (getNalUnitType() >= NAL_UNIT_CODED_SLICE_IDR_W_RADL) && (getNalUnitType() <= NAL_UNIT_CODED_SLICE_IDR_N_LP); }
+#endif
 #endif
   void                        checkCRA(const ReferencePictureSet *pReferencePictureSet, int& pocCRA, NalUnitType& associatedIRAPType, PicList& rcListPic);
   void                        decodingRefreshMarking(int& pocCRA, bool& bRefreshPending, PicList& rcListPic, const bool bEfficientFieldIRAPEnabled);
diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h
index d9c1d8b03..c104ad0e4 100644
--- a/source/Lib/CommonLib/TypeDef.h
+++ b/source/Lib/CommonLib/TypeDef.h
@@ -50,6 +50,9 @@
 #include <assert.h>
 #include <cassert>
 
+#define JVET_N0067_NAL_Unit_Header                        1 // NAL Unit Header 
+
+
 #define JVET_N0068_AFFINE_MEM_BW                          1 // memory bandwidth reduction for affine mode
 
 #define JVET_N0308_MAX_CU_SIZE_FOR_ISP                    1
@@ -58,6 +61,9 @@
 
 #define JVET_N0103_CGSIZE_HARMONIZATION                   1 // Chroma CG sizes aligned to luma CG sizes
 
+
+
+
 #define JVET_N0146_DMVR_BDOF_CONDITION                    1 // JVET-N146/N0162/N0442/N0153/N0262/N0440/N0086 applicable condition of DMVR and BDOF
 
 #define JVET_N0470_SMVD_FIX                               1 // remove mvd_l1_zero_flag condition, align to spec text.
@@ -887,6 +893,41 @@ enum PPSExtensionFlagIndex
 //       effort can be done without use of macros to alter the names used to indicate the different NAL unit types.
 enum NalUnitType
 {
+ #if JVET_N0067_NAL_Unit_Header
+  NAL_UNIT_PPS = 0,                     // 0 
+  NAL_UNIT_ACCESS_UNIT_DELIMITER,       // 1
+  NAL_UNIT_PREFIX_SEI,                  // 2
+  NAL_UNIT_SUFFIX_SEI,                  // 3
+  NAL_UNIT_APS,                         // 4
+  NAL_UNIT_RESERVED_NVCL_5,             // 5
+  NAL_UNIT_RESERVED_NVCL_6,             // 6
+  NAL_UNIT_RESERVED_NVCL_7,             // 7
+  NAL_UNIT_CODED_SLICE_TRAIL,           // 8
+  NAL_UNIT_CODED_SLICE_STSA,            // 9
+  NAL_UNIT_CODED_SLICE_RADL,            // 10
+  NAL_UNIT_CODED_SLICE_RASL,            // 11
+  NAL_UNIT_RESERVED_VCL_12,             // 12
+  NAL_UNIT_RESERVED_VCL_13,             // 13
+  NAL_UNIT_RESERVED_VCL_14,             // 14
+  NAL_UNIT_RESERVED_VCL_15,             // 15
+  NAL_UNIT_DPS,                         // 16
+  NAL_UNIT_SPS,                         // 17
+  NAL_UNIT_EOS,                         // 18
+  NAL_UNIT_EOB,                         // 19
+  NAL_UNIT_VPS,                         // 20
+  NAL_UNIT_RESERVED_NVCL_21,            // 21
+  NAL_UNIT_RESERVED_NVCL_22,            // 22
+  NAL_UNIT_RESERVED_NVCL_23,            // 23
+  NAL_UNIT_CODED_SLICE_IDR_W_RADL,      // 24
+  NAL_UNIT_CODED_SLICE_IDR_N_LP,        // 25
+  NAL_UNIT_CODED_SLICE_CRA,             // 26
+  NAL_UNIT_CODED_SLICE_GRA,             // 27
+  NAL_UNIT_UNSPECIFIED_28,              // 29              
+  NAL_UNIT_UNSPECIFIED_29,              // 30
+  NAL_UNIT_UNSPECIFIED_30,              // 31
+  NAL_UNIT_UNSPECIFIED_31,              // 32
+  NAL_UNIT_INVALID
+#else
 #if JVET_M0101_HLS
   NAL_UNIT_CODED_SLICE_TRAIL = 0, // 0
   NAL_UNIT_CODED_SLICE_STSA,      // 1
@@ -1016,6 +1057,7 @@ enum NalUnitType
   NAL_UNIT_UNSPECIFIED_63,
   NAL_UNIT_INVALID,
 #endif
+#endif
 };
 
 #if SHARP_LUMA_DELTA_QP
diff --git a/source/Lib/DecoderLib/DecLib.cpp b/source/Lib/DecoderLib/DecLib.cpp
index 7bec8e65e..0d6c67733 100644
--- a/source/Lib/DecoderLib/DecLib.cpp
+++ b/source/Lib/DecoderLib/DecLib.cpp
@@ -1512,6 +1512,7 @@ bool DecLib::decode(InputNALUnit& nalu, int& iSkipFrame, int& iPOCLastDisplay)
     case NAL_UNIT_EOB:
       return false;
 
+#if !JVET_N0067_NAL_Unit_Header
     case NAL_UNIT_FILLER_DATA:
       {
         FDReader fdReader;
@@ -1520,6 +1521,13 @@ bool DecLib::decode(InputNALUnit& nalu, int& iSkipFrame, int& iPOCLastDisplay)
         msg( NOTICE, "Note: found NAL_UNIT_FILLER_DATA with %u bytes payload.\n", size);
         return false;
       }
+#endif
+#if JVET_N0067_NAL_Unit_Header
+    case NAL_UNIT_RESERVED_VCL_12:
+    case NAL_UNIT_RESERVED_VCL_13:
+    case NAL_UNIT_RESERVED_VCL_14:
+    case NAL_UNIT_RESERVED_VCL_15:
+#else
 #if !JVET_M0101_HLS
     case NAL_UNIT_RESERVED_VCL_N10:
     case NAL_UNIT_RESERVED_VCL_R11:
@@ -1556,10 +1564,19 @@ bool DecLib::decode(InputNALUnit& nalu, int& iSkipFrame, int& iPOCLastDisplay)
 #if !HEVC_VPS
     case NAL_UNIT_RESERVED_VCL15:
 #endif
+#endif
 #endif
       msg( NOTICE, "Note: found reserved VCL NAL unit.\n");
       xParsePrefixSEIsForUnknownVCLNal();
       return false;
+#if JVET_N0067_NAL_Unit_Header
+    case NAL_UNIT_RESERVED_NVCL_5:
+    case NAL_UNIT_RESERVED_NVCL_6:
+    case NAL_UNIT_RESERVED_NVCL_7:
+    case NAL_UNIT_RESERVED_NVCL_21:
+    case NAL_UNIT_RESERVED_NVCL_22:
+    case NAL_UNIT_RESERVED_NVCL_23:
+#else
 #if !JVET_M0101_HLS
     case NAL_UNIT_RESERVED_NVCL41:
     case NAL_UNIT_RESERVED_NVCL42:
@@ -1572,6 +1589,7 @@ bool DecLib::decode(InputNALUnit& nalu, int& iSkipFrame, int& iPOCLastDisplay)
     case NAL_UNIT_RESERVED_NVCL16:
     case NAL_UNIT_RESERVED_NVCL26:
     case NAL_UNIT_RESERVED_NVCL27:
+#endif
 #endif
       msg( NOTICE, "Note: found reserved NAL unit.\n");
       return false;
diff --git a/source/Lib/DecoderLib/NALread.cpp b/source/Lib/DecoderLib/NALread.cpp
index 7b507b99f..3f32f8cfb 100644
--- a/source/Lib/DecoderLib/NALread.cpp
+++ b/source/Lib/DecoderLib/NALread.cpp
@@ -110,11 +110,18 @@ static void convertPayloadToRBSP(vector<uint8_t>& nalUnitBuf, InputBitstream *bi
 static void xTraceNalUnitHeader(InputNALUnit& nalu)
 {
   DTRACE( g_trace_ctx, D_NALUNITHEADER, "*********** NAL UNIT (%s) ***********\n", nalUnitTypeToString(nalu.m_nalUnitType) );
-
+  #if JVET_N0067_NAL_Unit_Header
+  DTRACE( g_trace_ctx, D_NALUNITHEADER, "%-50s u(%d)  : %u\n", "zero_tid_required_flag", 1, nalu.m_zeroTidRequiredFlag );
+  DTRACE( g_trace_ctx, D_NALUNITHEADER, "%-50s u(%d)  : %u\n", "nuh_temporal_id_plus1", 3, nalu.m_temporalId + 1 );
+  DTRACE( g_trace_ctx, D_NALUNITHEADER, "%-50s u(%d)  : %u\n", "nal_unit_type_lsb", 4, (nalu.m_nalUnitType) - (nalu.m_zeroTidRequiredFlag << 4));
+  DTRACE( g_trace_ctx, D_NALUNITHEADER, "%-50s u(%d)  : %u\n", "nuh_layer_id", 7, nalu.m_nuhLayerId );
+  DTRACE( g_trace_ctx, D_NALUNITHEADER, "%-50s u(%d)  : %u\n", "nuh_reserved_zero_bit", 1, 0 );
+  #else
   DTRACE( g_trace_ctx, D_NALUNITHEADER, "%-50s u(%d)  : %u\n", "forbidden_zero_bit", 1, 0 );
   DTRACE( g_trace_ctx, D_NALUNITHEADER, "%-50s u(%d)  : %u\n", "nal_unit_type", 6, nalu.m_nalUnitType );
   DTRACE( g_trace_ctx, D_NALUNITHEADER, "%-50s u(%d)  : %u\n", "nuh_layer_id", 6, nalu.m_nuhLayerId );
   DTRACE( g_trace_ctx, D_NALUNITHEADER, "%-50s u(%d)  : %u\n", "nuh_temporal_id_plus1", 3, nalu.m_temporalId + 1 );
+  #endif
 }
 #endif
 
@@ -122,14 +129,41 @@ void readNalUnitHeader(InputNALUnit& nalu)
 {
   InputBitstream& bs = nalu.getBitstream();
 
+#if JVET_N0067_NAL_Unit_Header
+  nalu.m_zeroTidRequiredFlag = bs.read(1);            // zero_tid_required_flag
+  nalu.m_temporalId = bs.read(3) - 1;                 // nuh_temporal_id_plus1
+  if(nalu.m_temporalId < 0) { 
+    THROW( "Temporal ID is negative." );
+  }
+  //When zero_tid_required_flag is equal to 1, the value of nuh_temporal_id_plus1 shall be equal to 1.
+  if((nalu.m_zeroTidRequiredFlag == 1) && (nalu.m_temporalId != 0)) { 
+    THROW( "Temporal ID is not '0' when zero tid is required." );
+  }
+  uint32_t m_nalUnitTypeLsb = bs.read(4);             // nal_unit_type_lsb
+  nalu.m_nalUnitType = (NalUnitType) ((nalu.m_zeroTidRequiredFlag << 4) + m_nalUnitTypeLsb);
+  nalu.m_nuhLayerId = bs.read(7);                     // nuh_layer_id 
+  if((nalu.m_nuhLayerId < 0) || (nalu.m_nuhLayerId > 126)) { 
+    THROW( "Layer ID out of range" );
+  }
+  uint32_t nuh_reserved_zero_bit = bs.read(1);        // nuh_reserved_zero_bit
+  if(nuh_reserved_zero_bit != 0) { 
+    THROW( "Reserved zero bit is not '0'" );
+  }
+#else
   bool forbidden_zero_bit = bs.read(1);           // forbidden_zero_bit
   if(forbidden_zero_bit != 0) { THROW( "Forbidden zero-bit not '0'" );}
   nalu.m_nalUnitType = (NalUnitType) bs.read(6);  // nal_unit_type
   nalu.m_nuhLayerId = bs.read(6);                 // nuh_layer_id
   nalu.m_temporalId = bs.read(3) - 1;             // nuh_temporal_id_plus1
+#endif
+
 #if RExt__DECODER_DEBUG_BIT_STATISTICS
+#if JVET_N0067_NAL_Unit_Header
+  CodingStatistics::IncrementStatisticEP(STATS__NAL_UNIT_HEADER_BITS, 1+3+4+7+1, 0);
+#else
   CodingStatistics::IncrementStatisticEP(STATS__NAL_UNIT_HEADER_BITS, 1+6+6+3, 0);
 #endif
+#endif
 
 #if ENABLE_TRACING
   xTraceNalUnitHeader(nalu);
@@ -140,6 +174,12 @@ void readNalUnitHeader(InputNALUnit& nalu)
   {
     if ( nalu.m_temporalId )
     {
+#if JVET_N0067_NAL_Unit_Header
+      CHECK(  
+           (uint32_t)nalu.m_nalUnitType >= 16
+        && (uint32_t)nalu.m_nalUnitType <= 31
+            , "Invalid NAL type" );
+#else
 #if HEVC_VPS
 #if !JVET_M0101_HLS
       CHECK(  nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_BLA_W_LP
@@ -185,10 +225,14 @@ void readNalUnitHeader(InputNALUnit& nalu)
          , "Invalid NAL type");
 #endif
 #endif
-
+#endif
     }
     else
     {
+#if JVET_N0067_NAL_Unit_Header
+      CHECK(nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_STSA
+         , "Invalid NAL type");
+#else
 #if !JVET_M0101_HLS
       CHECK(  nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_TSA_R
            || nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_TSA_N
@@ -198,6 +242,7 @@ void readNalUnitHeader(InputNALUnit& nalu)
 #else
       CHECK(nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_STSA
          , "Invalid NAL type");
+#endif
 #endif
     }
   }
diff --git a/source/Lib/EncoderLib/NALwrite.cpp b/source/Lib/EncoderLib/NALwrite.cpp
index 93b09b4d9..1cf976ebe 100644
--- a/source/Lib/EncoderLib/NALwrite.cpp
+++ b/source/Lib/EncoderLib/NALwrite.cpp
@@ -49,12 +49,23 @@ static const uint8_t emulation_prevention_three_byte = 3;
 void writeNalUnitHeader(ostream& out, OutputNALUnit& nalu)       // nal_unit_header()
 {
 OutputBitstream bsNALUHeader;
+#if JVET_N0067_NAL_Unit_Header
+  if((nalu.m_nalUnitType >= 16) && (nalu.m_nalUnitType <= 31)) {
+    nalu.m_zeroTidRequiredFlag = 1;
+  }
+  bsNALUHeader.write(nalu.m_zeroTidRequiredFlag, 1);    // zero_tid_required_flag
+  bsNALUHeader.write(nalu.m_temporalId+1, 3);           // nuh_temporal_id_plus1
+  uint32_t m_nalUnitTypeLsb = (nalu.m_nalUnitType) - (nalu.m_zeroTidRequiredFlag << 4);
+  bsNALUHeader.write(m_nalUnitTypeLsb, 4);              // nal_unit_type_lsb
+  bsNALUHeader.write(nalu.m_nuhLayerId, 7);             // nuh_layer_id
+  bsNALUHeader.write(0, 1);                             // nuh_reserved_zero_bit
 
+#else
   bsNALUHeader.write(0,1);                    // forbidden_zero_bit
   bsNALUHeader.write(nalu.m_nalUnitType, 6);  // nal_unit_type
   bsNALUHeader.write(nalu.m_nuhLayerId, 6);   // nuh_layer_id
   bsNALUHeader.write(nalu.m_temporalId+1, 3); // nuh_temporal_id_plus1
-
+#endif
   out.write(reinterpret_cast<const char*>(bsNALUHeader.getByteStream()), bsNALUHeader.getByteStreamLength());
 }
 /**
diff --git a/source/Lib/EncoderLib/NALwrite.h b/source/Lib/EncoderLib/NALwrite.h
index b107a2f4c..57d777032 100644
--- a/source/Lib/EncoderLib/NALwrite.h
+++ b/source/Lib/EncoderLib/NALwrite.h
@@ -58,9 +58,16 @@ struct OutputNALUnit : public NALUnit
    */
   OutputNALUnit(
     NalUnitType nalUnitType,
+#if JVET_N0067_NAL_Unit_Header
+    uint32_t zeroTidRequiredFlag = 0,
+    uint32_t temporalID = 0,
+    uint32_t nuhLayerId = 0)
+  : NALUnit(nalUnitType, zeroTidRequiredFlag, temporalID, nuhLayerId)
+#else
     uint32_t temporalID = 0,
     uint32_t reserved_zero_6bits = 0)
   : NALUnit(nalUnitType, temporalID, reserved_zero_6bits)
+#endif
   , m_Bitstream()
   {}
 
-- 
GitLab