From 3884249d4b3c303f8376412466f3dd5b58e9edb2 Mon Sep 17 00:00:00 2001
From: Jonatan Samuelsson <jonatan.samuelsson@divideon.com>
Date: Thu, 23 Jan 2020 10:54:46 +0100
Subject: [PATCH] Enable signalling of slice header in picture header

---
 source/App/DecoderApp/DecApp.cpp    | 13 ++++++++++++-
 source/Lib/CommonLib/TypeDef.h      |  4 ++++
 source/Lib/DecoderLib/DecLib.cpp    |  6 ++++++
 source/Lib/DecoderLib/NALread.cpp   |  8 ++++++++
 source/Lib/DecoderLib/NALread.h     |  4 +++-
 source/Lib/DecoderLib/VLCReader.cpp | 20 +++++++++++++++++++-
 source/Lib/DecoderLib/VLCReader.h   |  4 ++++
 source/Lib/EncoderLib/EncGOP.cpp    | 11 +++++++++++
 source/Lib/EncoderLib/VLCWriter.cpp | 23 ++++++++++++++++++++++-
 source/Lib/EncoderLib/VLCWriter.h   |  4 ++++
 10 files changed, 93 insertions(+), 4 deletions(-)

diff --git a/source/App/DecoderApp/DecApp.cpp b/source/App/DecoderApp/DecApp.cpp
index 69d4b1f7c4..af088ce082 100644
--- a/source/App/DecoderApp/DecApp.cpp
+++ b/source/App/DecoderApp/DecApp.cpp
@@ -492,8 +492,12 @@ bool DecApp::isNewPicture(ifstream *bitstreamFile, class InputByteStream *bytest
           ret = true;
           finished = true;
           break;
-        
+
+#if JVET_Q0775_PH_IN_SH
+        // NUT that may be the start of a new picture - check first bit in slice header
+#else
         // NUT that are not the start of a new picture
+#endif
         case NAL_UNIT_CODED_SLICE_TRAIL:
         case NAL_UNIT_CODED_SLICE_STSA:
         case NAL_UNIT_CODED_SLICE_RASL:
@@ -507,6 +511,13 @@ bool DecApp::isNewPicture(ifstream *bitstreamFile, class InputByteStream *bytest
         case NAL_UNIT_CODED_SLICE_GDR:
         case NAL_UNIT_RESERVED_IRAP_VCL_11:
         case NAL_UNIT_RESERVED_IRAP_VCL_12:
+#if JVET_Q0775_PH_IN_SH
+          ret = checkPictureHeaderInSliceHeaderFlag(nalu);
+          finished = true;
+          break;
+
+        // NUT that are not the start of a new picture
+#endif
         case NAL_UNIT_EOS:
         case NAL_UNIT_EOB:
         case NAL_UNIT_SUFFIX_APS:
diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h
index 6da12cd707..f4180e5be6 100644
--- a/source/Lib/CommonLib/TypeDef.h
+++ b/source/Lib/CommonLib/TypeDef.h
@@ -71,6 +71,10 @@
 #define JVET_Q0055_MTS_SIGNALLING                         1 // JVET-Q0055: Check for transform coefficients outside the 16x16 area
 #define JVET_Q0480_RASTER_RECT_SLICES                     1 // JVET-Q0480: Eliminate redundant slice height syntax when in raster rectangular slice mode (tile_idx_delta_present_flag == 0)
 
+<<<<<<< HEAD
+=======
+#define JVET_Q0775_PH_IN_SH                               1 // JVET-Q0755: Allow picture header in slice header
+>>>>>>> Enable signalling of slice header in picture header
 
 #define JVET_Q0433_MODIFIED_CHROMA_DIST_WEIGHT            1 // modification of chroma distortion weight (as agreed during presentation of JVET-Q0433)
 
diff --git a/source/Lib/DecoderLib/DecLib.cpp b/source/Lib/DecoderLib/DecLib.cpp
index 6b62da6341..1e31c73fe5 100644
--- a/source/Lib/DecoderLib/DecLib.cpp
+++ b/source/Lib/DecoderLib/DecLib.cpp
@@ -1205,15 +1205,21 @@ void DecLib::xParsePrefixSEImessages()
 void DecLib::xDecodePicHeader( InputNALUnit& nalu )
 {
   m_HLSReader.setBitstream( &nalu.getBitstream() );
+#if JVET_Q0775_PH_IN_SH
+  m_HLSReader.parsePictureHeader( &m_picHeader, &m_parameterSetManager, true );
+#else
   m_HLSReader.parsePictureHeader( &m_picHeader, &m_parameterSetManager);
+#endif
   m_picHeader.setValid();
 }
 
 bool DecLib::xDecodeSlice(InputNALUnit &nalu, int &iSkipFrame, int iPOCLastDisplay )
 {
+#if !JVET_Q0775_PH_IN_SH
   if(m_picHeader.isValid() == false) {
     return false;
   }
+#endif
   m_apcSlicePilot->setPicHeader( &m_picHeader );
   m_apcSlicePilot->initSlice(); // the slice pilot is an object to prepare for a new slice
                                 // it is not associated with picture, sps or pps structures.
diff --git a/source/Lib/DecoderLib/NALread.cpp b/source/Lib/DecoderLib/NALread.cpp
index 07dddd03f6..819bcc2518 100644
--- a/source/Lib/DecoderLib/NALread.cpp
+++ b/source/Lib/DecoderLib/NALread.cpp
@@ -167,4 +167,12 @@ void read(InputNALUnit& nalu)
   bitstream.resetToStart();
   readNalUnitHeader(nalu);
 }
+#if JVET_Q0775_PH_IN_SH
+bool checkPictureHeaderInSliceHeaderFlag(InputNALUnit& nalu)
+{
+  InputBitstream& bitstream = nalu.getBitstream();
+  CHECK(bitstream.getByteLocation() != 2, "The picture_header_in_slice_header_flag is the first bit after the NAL unit header");
+  return (bool)bitstream.read(1);
+}
+#endif
 //! \}
diff --git a/source/Lib/DecoderLib/NALread.h b/source/Lib/DecoderLib/NALread.h
index 1778dc5055..f807fbed75 100644
--- a/source/Lib/DecoderLib/NALread.h
+++ b/source/Lib/DecoderLib/NALread.h
@@ -67,7 +67,9 @@ class InputNALUnit : public NALUnit
 
 void read(InputNALUnit& nalu);
 void readNalUnitHeader(InputNALUnit& nalu);
-
+#if JVET_Q0775_PH_IN_SH
+bool checkPictureHeaderInSliceHeaderFlag(InputNALUnit & nalu);
+#endif
 //! \}
 
 #endif
diff --git a/source/Lib/DecoderLib/VLCReader.cpp b/source/Lib/DecoderLib/VLCReader.cpp
index 09400e0168..f2af42e183 100644
--- a/source/Lib/DecoderLib/VLCReader.cpp
+++ b/source/Lib/DecoderLib/VLCReader.cpp
@@ -1715,7 +1715,11 @@ void HLSyntaxReader::parseVPS(VPS* pcVPS)
   xReadRbspTrailingBits();
 }
 
+#if JVET_Q0775_PH_IN_SH
+void HLSyntaxReader::parsePictureHeader( PicHeader* picHeader, ParameterSetManager *parameterSetManager, bool readRbspTrailingBits )
+#else
 void HLSyntaxReader::parsePictureHeader( PicHeader* picHeader, ParameterSetManager *parameterSetManager )
+#endif
 {
   uint32_t  uiCode; 
   int       iCode;
@@ -2398,7 +2402,14 @@ void HLSyntaxReader::parsePictureHeader( PicHeader* picHeader, ParameterSetManag
     }
   }
 
+#if JVET_Q0775_PH_IN_SH
+  if( readRbspTrailingBits )
+  {
+    xReadRbspTrailingBits();
+  }
+#else
   xReadRbspTrailingBits();
+#endif
 }
 
 void HLSyntaxReader::parseSliceHeader (Slice* pcSlice, PicHeader* picHeader, ParameterSetManager *parameterSetManager, const int prevTid0POC)
@@ -2411,7 +2422,14 @@ void HLSyntaxReader::parseSliceHeader (Slice* pcSlice, PicHeader* picHeader, Par
 #endif
   PPS* pps = NULL;
   SPS* sps = NULL;
-
+#if JVET_Q0775_PH_IN_SH
+  READ_FLAG(uiCode, "picture_header_in_slice_header_flag");
+  if (uiCode)
+  {
+    parsePictureHeader(picHeader, parameterSetManager, false);
+    picHeader->setValid();
+  }
+#endif
   CHECK(picHeader==0, "Invalid Picture Header");
   CHECK(picHeader->isValid()==false, "Invalid Picture Header");
   pps = parameterSetManager->getPPS( picHeader->getPPSId() );
diff --git a/source/Lib/DecoderLib/VLCReader.h b/source/Lib/DecoderLib/VLCReader.h
index 69e3f479ca..67933c02e3 100644
--- a/source/Lib/DecoderLib/VLCReader.h
+++ b/source/Lib/DecoderLib/VLCReader.h
@@ -167,7 +167,11 @@ public:
   void  parseConstraintInfo   (ConstraintInfo *cinfo);
   void  parseProfileTierLevel ( ProfileTierLevel *ptl, int maxNumSubLayersMinus1);
   void  parseHrdParameters  ( HRDParameters *hrd, uint32_t firstSubLayer, uint32_t tempLevelHigh );
+#if JVET_Q0775_PH_IN_SH
+  void  parsePictureHeader  ( PicHeader* picHeader, ParameterSetManager *parameterSetManager, bool readRbspTrailingBits );
+#else
   void  parsePictureHeader  ( PicHeader* picHeader, ParameterSetManager *parameterSetManager );
+#endif
   void  parseSliceHeader    ( Slice* pcSlice, PicHeader* picHeader, ParameterSetManager *parameterSetManager, const int prevTid0POC );
   void  parseSliceHeaderToPoc ( Slice* pcSlice, PicHeader* picHeader, ParameterSetManager *parameterSetManager, const int prevTid0POC );
   void  parseTerminatingBit ( uint32_t& ruiBit );
diff --git a/source/Lib/EncoderLib/EncGOP.cpp b/source/Lib/EncoderLib/EncGOP.cpp
index 0bc3ea911b..194ba90a46 100644
--- a/source/Lib/EncoderLib/EncGOP.cpp
+++ b/source/Lib/EncoderLib/EncGOP.cpp
@@ -401,7 +401,11 @@ int EncGOP::xWritePicHeader( AccessUnit &accessUnit, PicHeader *picHeader )
   m_HLSWriter->setBitstream( &nalu.m_Bitstream );
   nalu.m_temporalId = accessUnit.temporalId;
   nalu.m_nuhLayerId = m_pcEncLib->getLayerId();
+#if JVET_Q0775_PH_IN_SH
+  m_HLSWriter->codePictureHeader( picHeader, true );
+#else
   m_HLSWriter->codePictureHeader( picHeader );
+#endif
   accessUnit.push_back(new NALUnitEBSP(nalu));
   return (int)(accessUnit.back()->m_nalUnitData.str().size()) * 8;
 }
@@ -3074,7 +3078,14 @@ void EncGOP::compressGOP( int iPOCLast, int iNumPicRcvd, PicList& rcListPic,
 
           pcPic->cs->picHeader->setPic(pcPic);
           pcPic->cs->picHeader->setValid();
+#if JVET_Q0775_PH_IN_SH
+          if (pcPic->cs->pps->getNumSlicesInPic() > 1)
+          {
+            actualTotalBits += xWritePicHeader(accessUnit, pcPic->cs->picHeader);
+          }
+#else
           actualTotalBits += xWritePicHeader(accessUnit, pcPic->cs->picHeader);
+#endif
         }
         pcSlice->setPicHeader( pcPic->cs->picHeader );
 
diff --git a/source/Lib/EncoderLib/VLCWriter.cpp b/source/Lib/EncoderLib/VLCWriter.cpp
index d00d64a669..728598cab2 100644
--- a/source/Lib/EncoderLib/VLCWriter.cpp
+++ b/source/Lib/EncoderLib/VLCWriter.cpp
@@ -1162,7 +1162,11 @@ void HLSWriter::codeVPS(const VPS* pcVPS)
   xWriteRbspTrailingBits();
 }
 
+#if JVET_Q0775_PH_IN_SH
+void HLSWriter::codePictureHeader( PicHeader* picHeader, bool writeRbspTrailingBits )
+#else
 void HLSWriter::codePictureHeader( PicHeader* picHeader )
+#endif
 {
   const PPS*  pps = NULL;
   const SPS*  sps = NULL;
@@ -1714,7 +1718,14 @@ void HLSWriter::codePictureHeader( PicHeader* picHeader )
     WRITE_UVLC(0,"pic_segment_header_extension_length");
   }
   
+#if JVET_Q0775_PH_IN_SH
+  if ( writeRbspTrailingBits )
+  {
+    xWriteRbspTrailingBits();
+  }
+#else
   xWriteRbspTrailingBits();
+#endif
 }
 
 void HLSWriter::codeSliceHeader         ( Slice* pcSlice )
@@ -1724,11 +1735,21 @@ void HLSWriter::codeSliceHeader         ( Slice* pcSlice )
 #endif
 
   CodingStructure& cs = *pcSlice->getPic()->cs;
+#if JVET_Q0775_PH_IN_SH
+  PicHeader *picHeader = cs.picHeader;
+#else
   const PicHeader *picHeader = cs.picHeader;
+#endif
   const ChromaFormat format                = pcSlice->getSPS()->getChromaFormatIdc();
   const uint32_t         numberValidComponents = getNumberValidComponents(format);
   const bool         chromaEnabled         = isChromaEnabled(format);
-
+#if JVET_Q0775_PH_IN_SH
+  WRITE_FLAG(cs.pps->getNumSlicesInPic() == 1 ? 1 : 0, "picture_header_in_slice_header_flag");
+  if (cs.pps->getNumSlicesInPic() == 1)
+  {
+    codePictureHeader(picHeader, false);
+  }
+#endif
   int pocBits = pcSlice->getSPS()->getBitsForPOC();
   int pocMask = (1 << pocBits) - 1;
   WRITE_CODE(pcSlice->getPOC() & pocMask, pocBits, "slice_pic_order_cnt_lsb");
diff --git a/source/Lib/EncoderLib/VLCWriter.h b/source/Lib/EncoderLib/VLCWriter.h
index 7816710363..5fb0ad3909 100644
--- a/source/Lib/EncoderLib/VLCWriter.h
+++ b/source/Lib/EncoderLib/VLCWriter.h
@@ -129,7 +129,11 @@ public:
   void  codeScalingListAps      ( APS* pcAPS );
   void  codeVPS                 ( const VPS* pcVPS );
   void  codeDPS                 ( const DPS* dps );
+#if JVET_Q0775_PH_IN_SH
+  void  codePictureHeader       ( PicHeader* picHeader, bool writeRbspTrailingBits );
+#else
   void  codePictureHeader       ( PicHeader* picHeader );
+#endif
   void  codeSliceHeader         ( Slice* pcSlice );
   void  codeConstraintInfo      ( const ConstraintInfo* cinfo );
   void  codeProfileTierLevel    ( const ProfileTierLevel* ptl, int maxNumSubLayersMinus1 );
-- 
GitLab