From d9f620a6887b9f7b037dc304efc5ad70c6b61517 Mon Sep 17 00:00:00 2001
From: Rickard Sjoberg <rickard.sjoberg@ericsson.com>
Date: Mon, 2 Mar 2020 10:12:03 +0100
Subject: [PATCH] JVET-P0978 Adding RPL related bitstream constraints

---
 source/App/DecoderApp/DecApp.cpp |   3 +
 source/Lib/CommonLib/Picture.h   |  10 +++
 source/Lib/CommonLib/Slice.cpp   | 133 +++++++++++++++++++++++++++++++
 source/Lib/CommonLib/Slice.h     |   7 ++
 source/Lib/CommonLib/TypeDef.h   |   2 +
 source/Lib/DecoderLib/DecLib.cpp |  33 +++++++-
 source/Lib/DecoderLib/DecLib.h   |   7 ++
 7 files changed, 194 insertions(+), 1 deletion(-)

diff --git a/source/App/DecoderApp/DecApp.cpp b/source/App/DecoderApp/DecApp.cpp
index b56261db8..95f599c85 100644
--- a/source/App/DecoderApp/DecApp.cpp
+++ b/source/App/DecoderApp/DecApp.cpp
@@ -247,6 +247,9 @@ uint32_t DecApp::decode()
 #endif
       }
 
+#if JVET_P0978_RPL_RESTRICTIONS
+      m_cDecLib.UpdateAssociatedIRAP();
+#endif
     }
     else if ( (bNewPicture || !bitstreamFile || nalu.m_nalUnitType == NAL_UNIT_EOS ) &&
 #if JVET_P0125_EOS_LAYER_SPECIFIC
diff --git a/source/Lib/CommonLib/Picture.h b/source/Lib/CommonLib/Picture.h
index 911786f94..65cb8790f 100644
--- a/source/Lib/CommonLib/Picture.h
+++ b/source/Lib/CommonLib/Picture.h
@@ -148,6 +148,12 @@ struct Picture : public UnitArea
   void finalInit( const VPS* vps, const SPS& sps, const PPS& pps, PicHeader *picHeader, APS** alfApss, APS* lmcsAps, APS* scalingListAps );
 
   int  getPOC()                               const { return poc; }
+#if JVET_P0978_RPL_RESTRICTIONS
+  int  getDecodingOrderNumber()               const { return m_decodingOrderNumber; }
+  void setDecodingOrderNumber(const int val)        { m_decodingOrderNumber = val;  }
+  NalUnitType getPictureType()                const { return m_PictureType;         }
+  void setPictureType(const NalUnitType val)        { m_PictureType = val;          }
+#endif
   void setBorderExtension( bool bFlag)              { m_bIsBorderExtended = bFlag;}
   Pel* getOrigin( const PictureType &type, const ComponentID compID ) const;
 
@@ -170,6 +176,10 @@ struct Picture : public UnitArea
 private:
   Window        m_conformanceWindow;
   Window        m_scalingWindow;
+#if JVET_P0978_RPL_RESTRICTIONS
+  int           m_decodingOrderNumber;
+  NalUnitType   m_PictureType;
+#endif
 
 public:
 #if JVET_O1143_MV_ACROSS_SUBPIC_BOUNDARY  
diff --git a/source/Lib/CommonLib/Slice.cpp b/source/Lib/CommonLib/Slice.cpp
index 1fe39dfaa..cbb479f07 100644
--- a/source/Lib/CommonLib/Slice.cpp
+++ b/source/Lib/CommonLib/Slice.cpp
@@ -594,7 +594,11 @@ void Slice::checkColRefIdx(uint32_t curSliceSegmentIdx, const Picture* pic)
   }
 }
 
+#if JVET_P0978_RPL_RESTRICTIONS
+void Slice::checkCRA(const ReferencePictureList* pRPL0, const ReferencePictureList* pRPL1, const int pocCRA, PicList& rcListPic)
+#else
 void Slice::checkCRA(const ReferencePictureList *pRPL0, const ReferencePictureList *pRPL1, int& pocCRA, NalUnitType& associatedIRAPType, PicList& rcListPic)
+#endif
 {
   if (pocCRA < MAX_UINT && getPOC() > pocCRA)
   {
@@ -637,6 +641,7 @@ void Slice::checkCRA(const ReferencePictureList *pRPL0, const ReferencePictureLi
       }
     }
   }
+#if !JVET_P0978_RPL_RESTRICTIONS
   if (getNalUnitType() == NAL_UNIT_CODED_SLICE_IDR_W_RADL || getNalUnitType() == NAL_UNIT_CODED_SLICE_IDR_N_LP) // IDR picture found
   {
     pocCRA = getPOC();
@@ -647,7 +652,135 @@ void Slice::checkCRA(const ReferencePictureList *pRPL0, const ReferencePictureLi
     pocCRA = getPOC();
     associatedIRAPType = getNalUnitType();
   }
+#endif
+}
+
+#if JVET_P0978_RPL_RESTRICTIONS
+void Slice::checkRPL(const ReferencePictureList* pRPL0, const ReferencePictureList* pRPL1, const int associatedIRAPDecodingOrderNumber, PicList& rcListPic)
+{
+  Picture* pcRefPic;
+  int refPicPOC;
+  int refPicDecodingOrderNumber;
+
+  int irapPOC = getAssociatedIRAPPOC();
+
+  int numEntriesL0 = pRPL0->getNumberOfShorttermPictures() + pRPL0->getNumberOfLongtermPictures() + pRPL0->getNumberOfInterLayerPictures();
+  int numEntriesL1 = pRPL1->getNumberOfShorttermPictures() + pRPL1->getNumberOfLongtermPictures() + pRPL1->getNumberOfInterLayerPictures();
+
+  int numActiveEntriesL0 = getNumRefIdx(REF_PIC_LIST_0);
+  int numActiveEntriesL1 = getNumRefIdx(REF_PIC_LIST_1);
+
+#if JVET_Q0042_VUI
+  bool fieldSeqFlag = getSPS()->getFieldSeqFlag();
+#else
+  bool fieldSeqFlag = getSPS()->getVuiParameters() && getSPS()->getVuiParameters()->getFieldSeqFlag();
+#endif
+
+  int current_picture_is_trailing = 0;
+  if (getPic()->getDecodingOrderNumber() > associatedIRAPDecodingOrderNumber)
+  {
+    switch (m_eNalUnitType)
+    {
+    case NAL_UNIT_CODED_SLICE_STSA:
+    case NAL_UNIT_CODED_SLICE_IDR_W_RADL:
+    case NAL_UNIT_CODED_SLICE_IDR_N_LP:
+    case NAL_UNIT_CODED_SLICE_CRA:
+    case NAL_UNIT_CODED_SLICE_RADL:
+    case NAL_UNIT_CODED_SLICE_RASL:
+      current_picture_is_trailing = 0;
+      break;
+    default:
+      current_picture_is_trailing = 1;
+    }
+  }
+
+  for (int i = 0; i < numEntriesL0; i++)
+  {
+    if (!pRPL0->isRefPicLongterm(i))
+    {
+      refPicPOC = getPOC() - pRPL0->getRefPicIdentifier(i);
+      pcRefPic = xGetRefPic(rcListPic, refPicPOC, m_pcPic->layerId);
+    }
+    else
+    {
+      pcRefPic = xGetLongTermRefPic(rcListPic, pRPL0->getRefPicIdentifier(i), pRPL0->getDeltaPocMSBPresentFlag(i), m_pcPic->layerId);
+      refPicPOC = pcRefPic->getPOC();
+    }
+    refPicDecodingOrderNumber = pcRefPic->getDecodingOrderNumber();
+
+    // Checking this: "When the current picture is a CRA picture, there shall be no entry in RefPicList[0] or RefPicList[1]
+    // that precedes, in output order or decoding order, any preceding IRAP picture in decoding order (when present)"
+    if (m_eNalUnitType == NAL_UNIT_CODED_SLICE_CRA)
+    {
+      CHECK(refPicPOC < irapPOC || refPicDecodingOrderNumber < associatedIRAPDecodingOrderNumber, "CRA picture detected that violate the rule that no entry in RefPicList[] shall precede, in output order or decoding order, any preceding IRAP picture in decoding order (when present).");
+    }
+
+    // Checking this: "When the current picture is a trailing picture that follows in both decoding orderand output order one
+    // or more leading pictures associated with the same IRAP picture, if any, there shall be no picture referred to by an
+    // entry in RefPicList[0] or RefPicList[1] that precedes the associated IRAP picture in output order or decoding order"
+    // Note that when not in field coding, we know that all leading pictures of an IRAP precedes all trailing pictures of the
+    // same IRAP picture.
+    if (current_picture_is_trailing && !fieldSeqFlag) // 
+    {
+      CHECK(refPicPOC < irapPOC || refPicDecodingOrderNumber < associatedIRAPDecodingOrderNumber, "Trailing picture detected that follows one or more leading pictures, if any, and violates the rule that no entry in RefPicList[] shall precede the associated IRAP picture in output order or decoding order.");
+    }
+
+    if (i < numActiveEntriesL0)
+    {
+      // Checking this "When the current picture is a trailing picture, there shall be no picture referred to by an active
+      // entry in RefPicList[ 0 ] or RefPicList[ 1 ] that precedes the associated IRAP picture in output order or decoding order"
+      if (current_picture_is_trailing)
+      {
+        CHECK(refPicPOC < irapPOC || refPicDecodingOrderNumber < associatedIRAPDecodingOrderNumber, "Trailing picture detected that violate the rule that no active entry in RefPicList[] shall precede the associated IRAP picture in output order or decoding order");
+      }
+
+      // Checking this: "When the current picture is a RADL picture, there shall be no active entry in RefPicList[ 0 ] or
+      // RefPicList[ 1 ] that is any of the following: A picture that precedes the associated IRAP picture in decoding order"
+      if (m_eNalUnitType == NAL_UNIT_CODED_SLICE_RADL)
+      {
+        CHECK(refPicDecodingOrderNumber < associatedIRAPDecodingOrderNumber, "RADL picture detected that violate the rule that no active entry in RefPicList[] shall precede the associated IRAP picture in decoding order");
+      }
+    }
+  }
+
+  for (int i = 0; i < numEntriesL1; i++)
+  {
+    if (!pRPL1->isRefPicLongterm(i))
+    {
+      refPicPOC = getPOC() - pRPL1->getRefPicIdentifier(i);
+      pcRefPic = xGetRefPic(rcListPic, refPicPOC, m_pcPic->layerId);
+    }
+    else
+    {
+      pcRefPic = xGetLongTermRefPic(rcListPic, pRPL0->getRefPicIdentifier(i), pRPL0->getDeltaPocMSBPresentFlag(i), m_pcPic->layerId);
+      refPicPOC = pcRefPic->getPOC();
+    }
+    refPicDecodingOrderNumber = pcRefPic->getDecodingOrderNumber();
+
+    if (m_eNalUnitType == NAL_UNIT_CODED_SLICE_CRA)
+    {
+      CHECK(refPicPOC < irapPOC || refPicDecodingOrderNumber < associatedIRAPDecodingOrderNumber, "CRA picture detected that violate the rule that no entry in RefPicList[] shall precede, in output order or decoding order, any preceding IRAP picture in decoding order (when present).");
+    }
+    if (current_picture_is_trailing && !fieldSeqFlag)
+    {
+      CHECK(refPicPOC < irapPOC || refPicDecodingOrderNumber < associatedIRAPDecodingOrderNumber, "Trailing picture detected that follows one or more leading pictures, if any, and violates the rule that no entry in RefPicList[] shall precede the associated IRAP picture in output order or decoding order.");
+    }
+
+    if (i < numActiveEntriesL1)
+    {
+      if (current_picture_is_trailing)
+      {
+        CHECK(refPicPOC < irapPOC || refPicDecodingOrderNumber < associatedIRAPDecodingOrderNumber, "Trailing picture detected that violate the rule that no active entry in RefPicList[] shall precede the associated IRAP picture in output order or decoding order");
+      }
+      if (m_eNalUnitType == NAL_UNIT_CODED_SLICE_RADL)
+      {
+        CHECK(refPicDecodingOrderNumber < associatedIRAPDecodingOrderNumber, "RADL picture detected that violate the rule that no active entry in RefPicList[] shall precede the associated IRAP picture in decoding order");
+      }
+    }
+  }
 }
+#endif
+
 
 void Slice::checkSTSA(PicList& rcListPic)
 {
diff --git a/source/Lib/CommonLib/Slice.h b/source/Lib/CommonLib/Slice.h
index 0749dfce9..2e566b941 100644
--- a/source/Lib/CommonLib/Slice.h
+++ b/source/Lib/CommonLib/Slice.h
@@ -3000,8 +3000,15 @@ public:
   bool                        isClvssPu() const                                      { return m_eNalUnitType >= NAL_UNIT_CODED_SLICE_IDR_W_RADL && m_eNalUnitType <= NAL_UNIT_CODED_SLICE_GDR && !m_pcPPS->getMixedNaluTypesInPicFlag() && m_pcPicHeader->getNoOutputBeforeRecoveryFlag(); }
 #endif
   bool                        isIDRorBLA() const { return (getNalUnitType() == NAL_UNIT_CODED_SLICE_IDR_W_RADL) || (getNalUnitType() == NAL_UNIT_CODED_SLICE_IDR_N_LP); }
+#if JVET_P0978_RPL_RESTRICTIONS
+  void                        checkCRA(const ReferencePictureList* pRPL0, const ReferencePictureList* pRPL1, const int pocCRA, PicList& rcListPic);
+#else
   void                        checkCRA(const ReferencePictureList *pRPL0, const ReferencePictureList *pRPL1, int& pocCRA, NalUnitType& associatedIRAPType, PicList& rcListPic);
+#endif
   void                        checkSTSA(PicList& rcListPic);
+#if JVET_P0978_RPL_RESTRICTIONS
+  void                        checkRPL(const ReferencePictureList* pRPL0, const ReferencePictureList* pRPL1, const int associatedIRAPDecodingOrderNumber, PicList& rcListPic);
+#endif
   void                        decodingRefreshMarking(int& pocCRA, bool& bRefreshPending, PicList& rcListPic, const bool bEfficientFieldIRAPEnabled);
   void                        setSliceType( SliceType e )                            { m_eSliceType        = e;                                      }
   void                        setSliceQp( int i )                                    { m_iSliceQp          = i;                                      }
diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h
index 5340766aa..914135e46 100644
--- a/source/Lib/CommonLib/TypeDef.h
+++ b/source/Lib/CommonLib/TypeDef.h
@@ -90,6 +90,8 @@
 
 #define JVET_P0116_POC_MSB                                1 // JVET-P0116: use POC MSB cycle signalling for independent layers,to support of mixed IRAP and non-IRAP pictures within an AU
 
+#define JVET_P0978_RPL_RESTRICTIONS                       1 // JVET-P0978: A set of RPL-related bitstream conformance restrictions
+
 #define JVET_Q0468_Q0469_MIN_LUMA_CB_AND_MIN_QT_FIX       1 // JVET-Q0468: add support of min Luma coding block size; JVET-Q0469: fix for signaling of Intra Chroma Min QT size
 
 #define JVET_Q0260_CONFORMANCE_WINDOW_IN_SPS              1 // JVET-Q0260: Conformance cropping window in the SPS that applies to the max picture size
diff --git a/source/Lib/DecoderLib/DecLib.cpp b/source/Lib/DecoderLib/DecLib.cpp
index d8ddbcc10..b552b76d0 100644
--- a/source/Lib/DecoderLib/DecLib.cpp
+++ b/source/Lib/DecoderLib/DecLib.cpp
@@ -426,6 +426,9 @@ bool tryDecodePicture( Picture* pcEncPic, const int expectedPoc, const std::stri
 DecLib::DecLib()
   : m_iMaxRefPicNum(0)
   , m_associatedIRAPType(NAL_UNIT_INVALID)
+#if JVET_P0978_RPL_RESTRICTIONS
+  , m_associatedIRAPDecodingOrderNumber(0)
+#endif
   , m_pocCRA(0)
   , m_pocRandomAccess(MAX_INT)
   , m_lastRasPoc(MAX_INT)
@@ -478,13 +481,14 @@ DecLib::DecLib()
   , m_vps( nullptr )
   , m_scalingListUpdateFlag(true)
   , m_PreScalingListAPSId(-1)
-
 #if JVET_Q0044_SLICE_IDX_WITH_SUBPICS
   , m_maxDecSubPicIdx(0)
   , m_maxDecSliceAddrInSubPic(-1)
 #endif
 #if JVET_Q0117_PARAMETER_SETS_CLEANUP
   , m_dci(NULL)
+#if JVET_P0978_RPL_RESTRICTIONS
+  , m_decodingOrderCounter(0)
 #endif
 {
 #if ENABLE_SIMD_OPT_BUFFER
@@ -2027,8 +2031,22 @@ bool DecLib::xDecodeSlice(InputNALUnit &nalu, int &iSkipFrame, int iPOCLastDispl
   m_pcPic->subLayerNonReferencePictureDueToSTSA = false;
 
 
+#if JVET_P0978_RPL_RESTRICTIONS
+  if (m_bFirstSliceInPicture)
+  {
+    m_pcPic->setDecodingOrderNumber(m_decodingOrderCounter);
+    m_decodingOrderCounter++;
+    m_pcPic->setPictureType(nalu.m_nalUnitType);
+  }
+
+  pcSlice->checkCRA(pcSlice->getRPL0(), pcSlice->getRPL1(), m_pocCRA, m_cListPic);
+#else
   pcSlice->checkCRA(pcSlice->getRPL0(), pcSlice->getRPL1(), m_pocCRA, m_associatedIRAPType, m_cListPic);
+#endif
   pcSlice->constructRefPicList(m_cListPic);
+#if JVET_P0978_RPL_RESTRICTIONS
+  pcSlice->checkRPL(pcSlice->getRPL0(), pcSlice->getRPL1(), m_associatedIRAPDecodingOrderNumber, m_cListPic);
+#endif
   pcSlice->checkSTSA(m_cListPic);
 
   pcSlice->scaleRefPicList( scaledRefPic, m_pcPic->cs->picHeader, m_parameterSetManager.getAPSs(), m_picHeader.getLmcsAPS(), m_picHeader.getScalingListAPS(), true );
@@ -2261,6 +2279,19 @@ bool DecLib::xDecodeSlice(InputNALUnit &nalu, int &iSkipFrame, int iPOCLastDispl
   return false;
 }
 
+#if JVET_P0978_RPL_RESTRICTIONS
+void DecLib::UpdateAssociatedIRAP()
+{
+  const NalUnitType pictureType = m_pcPic->getPictureType();
+  if (pictureType == NAL_UNIT_CODED_SLICE_IDR_W_RADL || pictureType == NAL_UNIT_CODED_SLICE_IDR_N_LP || pictureType == NAL_UNIT_CODED_SLICE_CRA)
+  {
+    m_associatedIRAPDecodingOrderNumber = m_pcPic->getDecodingOrderNumber();
+    m_pocCRA = m_pcPic->getPOC();
+    m_associatedIRAPType = pictureType;
+  }
+}
+#endif
+
 void DecLib::xDecodeVPS( InputNALUnit& nalu )
 {
   m_vps = new VPS();
diff --git a/source/Lib/DecoderLib/DecLib.h b/source/Lib/DecoderLib/DecLib.h
index 1edbe9cc3..64a891ad7 100644
--- a/source/Lib/DecoderLib/DecLib.h
+++ b/source/Lib/DecoderLib/DecLib.h
@@ -71,6 +71,10 @@ private:
   int                     m_iMaxRefPicNum;
 
   NalUnitType             m_associatedIRAPType; ///< NAL unit type of the associated IRAP picture
+#if JVET_P0978_RPL_RESTRICTIONS
+  int                     m_associatedIRAPDecodingOrderNumber; ///< Decoding order number of the associated IRAP picture
+  int                     m_decodingOrderCounter;
+#endif
   int                     m_pocCRA;            ///< POC number of the latest CRA picture
   int                     m_pocRandomAccess;   ///< POC number of the random access point (the first IDR or CRA picture)
   int                     m_lastRasPoc;
@@ -192,6 +196,9 @@ public:
   void  finishPictureLight(int& poc, PicList*& rpcListPic );
   void  checkNoOutputPriorPics (PicList* rpcListPic);
   void  checkNalUnitConstraints( uint32_t naluType );
+#if JVET_P0978_RPL_RESTRICTIONS
+  void UpdateAssociatedIRAP();
+#endif
 
 
   bool  getNoOutputPriorPicsFlag () const   { return m_isNoOutputPriorPics; }
-- 
GitLab