From ec5d4edbebcef7e01b7528b03844ac63b3f6a4e1 Mon Sep 17 00:00:00 2001
From: Vadim Seregin <vseregin@qti.qualcomm.com>
Date: Wed, 8 Jul 2020 20:01:43 -0700
Subject: [PATCH 1/3] Sub-picture constraints

---
 source/Lib/CommonLib/Picture.cpp   |  2 ++
 source/Lib/CommonLib/Picture.h     |  7 ++++
 source/Lib/CommonLib/TypeDef.h     |  2 ++
 source/Lib/CommonLib/UnitTools.cpp | 53 +++++++++++++++++++++++++++++-
 source/Lib/DecoderLib/DecLib.cpp   | 11 +++++++
 source/Lib/DecoderLib/DecSlice.cpp |  9 +++++
 source/Lib/EncoderLib/EncGOP.cpp   | 13 ++++++++
 source/Lib/EncoderLib/EncSlice.cpp |  5 +++
 8 files changed, 101 insertions(+), 1 deletion(-)

diff --git a/source/Lib/CommonLib/Picture.cpp b/source/Lib/CommonLib/Picture.cpp
index 7ddff73e57..8d05d1087d 100644
--- a/source/Lib/CommonLib/Picture.cpp
+++ b/source/Lib/CommonLib/Picture.cpp
@@ -193,7 +193,9 @@ Picture::Picture()
   m_spliceIdx = NULL;
   m_ctuNums = 0;
   layerId = NOT_VALID;
+#if !JVET_S0258_SUBPIC_CONSTRAINTS
   numSubpics = 1;
+#endif
   numSlices = 1;
 }
 
diff --git a/source/Lib/CommonLib/Picture.h b/source/Lib/CommonLib/Picture.h
index ee32fa54c7..7e9e44ffae 100644
--- a/source/Lib/CommonLib/Picture.h
+++ b/source/Lib/CommonLib/Picture.h
@@ -216,12 +216,17 @@ public:
   int  poc;
   uint32_t temporalId;
   int      layerId;
+#if JVET_S0258_SUBPIC_CONSTRAINTS
+  std::vector<SubPic> subPictures;
+  int numSlices;
+#else
   int  numSubpics;
   std::vector<int> subpicWidthInCTUs;
   std::vector<int> subpicHeightInCTUs;
   std::vector<int> subpicCtuTopLeftX;
   std::vector<int> subpicCtuTopLeftY;
   int numSlices;
+#endif
   std::vector<int> sliceSubpicIdx;
 
   bool subLayerNonReferencePictureDueToSTSA;
@@ -232,7 +237,9 @@ public:
   std::vector<bool> m_lossylosslessSliceArray;
   bool interLayerRefPicFlag;
 
+#if !JVET_S0258_SUBPIC_CONSTRAINTS
   std::vector<int> subPicIDs;
+#endif
 
 #if ENABLE_SPLIT_PARALLELISM
   PelStorage m_bufs[PARL_SPLIT_MAX_NUM_JOBS][NUM_PIC_TYPES];
diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h
index 4a8190ad9f..3324e449ae 100644
--- a/source/Lib/CommonLib/TypeDef.h
+++ b/source/Lib/CommonLib/TypeDef.h
@@ -52,6 +52,8 @@
 
 
 //########### place macros to be removed in next cycle below this line ###############
+#define JVET_S0258_SUBPIC_CONSTRAINTS                     1 // JVET-S0258: sub-picture constraints
+
 #define JVET_S0074_SPS_REORDER                            1 // JVET-S0074: aspect 1, rearrange some syntax elements in SPS
 
 #define JVET_S0132_HLS_REORDER                            1 // Rearrange syntax elements in SPS and PPS
diff --git a/source/Lib/CommonLib/UnitTools.cpp b/source/Lib/CommonLib/UnitTools.cpp
index 753a70c2c5..57546d9332 100644
--- a/source/Lib/CommonLib/UnitTools.cpp
+++ b/source/Lib/CommonLib/UnitTools.cpp
@@ -135,7 +135,28 @@ bool CU::getRprScaling( const SPS* sps, const PPS* curPPS, Picture* refPic, int&
 
 void CU::checkConformanceILRP(Slice *slice)
 {
-  const int numRefList = (slice->getSliceType() == B_SLICE) ? (2) : (1);
+  const int numRefList = slice->isInterB() ? 2 : 1;
+
+#if JVET_S0258_SUBPIC_CONSTRAINTS
+  int currentSubPicIdx = NOT_VALID;
+
+  // derive sub-picture index for the current slice
+  for( int subPicIdx = 0; subPicIdx < slice->getPic()->cs->sps->getNumSubPics(); subPicIdx++ )
+  {
+    if( slice->getPic()->cs->pps->getSubPic( subPicIdx ).getSubPicID() == slice->getSliceSubPicId() )
+    {
+      currentSubPicIdx = subPicIdx;
+      break;
+    }
+  }
+
+  CHECK( currentSubPicIdx == NOT_VALID, "Sub-picture was not found" );
+
+  if( !slice->getPic()->cs->sps->getSubPicTreatedAsPicFlag( currentSubPicIdx ) )
+  {
+    return;
+  }
+#endif
 
   //constraint 1: The picture referred to by each active entry in RefPicList[ 0 ] or RefPicList[ 1 ] has the same subpicture layout as the current picture 
   bool isAllRefSameSubpicLayout = true;
@@ -146,7 +167,11 @@ void CU::checkConformanceILRP(Slice *slice)
     {
       const Picture* refPic = slice->getRefPic(eRefPicList, refIdx)->unscaledPic;
 
+#if JVET_S0258_SUBPIC_CONSTRAINTS
+      if( refPic->subPictures.size() != slice->getPic()->cs->pps->getNumSubPics() )
+#else
       if (refPic->numSubpics != slice->getPic()->cs->pps->getNumSubPics())
+#endif
       {
         isAllRefSameSubpicLayout = false;
         refList = numRefList;
@@ -154,12 +179,26 @@ void CU::checkConformanceILRP(Slice *slice)
       }
       else
       {
+#if JVET_S0258_SUBPIC_CONSTRAINTS
+        for( int i = 0; i < refPic->subPictures.size(); i++ )
+        {
+          const SubPic& refSubPic = refPic->subPictures[i];
+          const SubPic& curSubPic = slice->getPic()->cs->pps->getSubPic( i );
+
+          if( refSubPic.getSubPicWidthInCTUs() != curSubPic.getSubPicWidthInCTUs()
+            || refSubPic.getSubPicHeightInCTUs() != curSubPic.getSubPicHeightInCTUs()
+            || refSubPic.getSubPicCtuTopLeftX() != curSubPic.getSubPicCtuTopLeftX()
+            || refSubPic.getSubPicCtuTopLeftY() != curSubPic.getSubPicCtuTopLeftY()
+            || ( refPic->layerId != slice->getPic()->layerId && refSubPic.getSubPicID() != curSubPic.getSubPicID() )
+            || refSubPic.getTreatedAsPicFlag() != curSubPic.getTreatedAsPicFlag())
+#else
         for (int i = 0; i < refPic->numSubpics; i++)
         {
           if (refPic->subpicWidthInCTUs[i] != slice->getPic()->cs->pps->getSubPic(i).getSubPicWidthInCTUs()
             || refPic->subpicHeightInCTUs[i] != slice->getPic()->cs->pps->getSubPic(i).getSubPicHeightInCTUs()
             || refPic->subpicCtuTopLeftX[i] != slice->getPic()->cs->pps->getSubPic(i).getSubPicCtuTopLeftX()
             || refPic->subpicCtuTopLeftY[i] != slice->getPic()->cs->pps->getSubPic(i).getSubPicCtuTopLeftY())
+#endif
           {
             isAllRefSameSubpicLayout = false;
             refIdx = slice->getNumRefIdx(eRefPicList);
@@ -167,6 +206,14 @@ void CU::checkConformanceILRP(Slice *slice)
             break;
           }
         }
+
+#if JVET_S0258_SUBPIC_CONSTRAINTS
+        // A picture with different sub-picture ID of the collocated sub-picture cannot be used as an active reference picture in the same layer
+        if( refPic->layerId == slice->getPic()->layerId )
+        {
+          isAllRefSameSubpicLayout = isAllRefSameSubpicLayout && refPic->subPictures[currentSubPicIdx].getSubPicID() == slice->getSliceSubPicId();
+        }
+#endif
       }
     }
   }
@@ -180,7 +227,11 @@ void CU::checkConformanceILRP(Slice *slice)
       for (int refIdx = 0; refIdx < slice->getNumRefIdx(eRefPicList); refIdx++)
       {
         const Picture* refPic = slice->getRefPic(eRefPicList, refIdx)->unscaledPic;
+#if JVET_S0258_SUBPIC_CONSTRAINTS
+        CHECK( refPic->layerId == slice->getPic()->layerId || refPic->subPictures.size() > 1, "The inter-layer reference shall contain a single subpicture or have same subpicture layout with the current picture" );
+#else
         CHECK(!(refPic->layerId != slice->getPic()->layerId && refPic->numSubpics == 1), "The inter-layer reference shall contain a single subpicture or have same subpicture layout with the current picture");
+#endif
       }
     }
   }
diff --git a/source/Lib/DecoderLib/DecLib.cpp b/source/Lib/DecoderLib/DecLib.cpp
index 13db0951a4..3d93fb2118 100644
--- a/source/Lib/DecoderLib/DecLib.cpp
+++ b/source/Lib/DecoderLib/DecLib.cpp
@@ -2163,6 +2163,14 @@ bool DecLib::xDecodeSlice(InputNALUnit &nalu, int &iSkipFrame, int iPOCLastDispl
     m_decodingOrderCounter++;
     m_pcPic->setPictureType(nalu.m_nalUnitType);
     // store sub-picture numbers, sizes, and locations with a picture
+#if JVET_S0258_SUBPIC_CONSTRAINTS
+    pcSlice->getPic()->subPictures.clear();
+
+    for( int subPicIdx = 0; subPicIdx < sps->getNumSubPics(); subPicIdx++ )
+    {
+      pcSlice->getPic()->subPictures.push_back( pps->getSubPic( subPicIdx ) );
+    }
+#else
     pcSlice->getPic()->numSubpics = sps->getNumSubPics();
     pcSlice->getPic()->subpicWidthInCTUs.clear();
     pcSlice->getPic()->subpicHeightInCTUs.clear();
@@ -2175,6 +2183,7 @@ bool DecLib::xDecodeSlice(InputNALUnit &nalu, int &iSkipFrame, int iPOCLastDispl
       pcSlice->getPic()->subpicCtuTopLeftX.push_back(pps->getSubPic(subPicIdx).getSubPicCtuTopLeftX());
       pcSlice->getPic()->subpicCtuTopLeftY.push_back(pps->getSubPic(subPicIdx).getSubPicCtuTopLeftY());
     }
+#endif
     pcSlice->getPic()->numSlices = pps->getNumSlicesInPic();
     pcSlice->getPic()->sliceSubpicIdx.clear();
   }
@@ -2195,6 +2204,7 @@ bool DecLib::xDecodeSlice(InputNALUnit &nalu, int &iSkipFrame, int iPOCLastDispl
 
   pcSlice->scaleRefPicList( scaledRefPic, m_pcPic->cs->picHeader, m_parameterSetManager.getAPSs(), m_picHeader.getLmcsAPS(), m_picHeader.getScalingListAPS(), true );
 
+#if !JVET_S0258_SUBPIC_CONSTRAINTS
   // For each value of i in the range of 0 to sps_num_subpics_minus1, inclusive, when the value of SubpicIdVal[ i ] of a current picture is not equal to the value of SubpicIdVal[ i ] of a reference picture,
   // the active entries of the RPLs of the coded slices in the i-th subpicture of the current picture shall not include that reference picture.
 
@@ -2241,6 +2251,7 @@ bool DecLib::xDecodeSlice(InputNALUnit &nalu, int &iSkipFrame, int iPOCLastDispl
       }
     }
   }
+#endif
 
     if (!pcSlice->isIntra())
     {
diff --git a/source/Lib/DecoderLib/DecSlice.cpp b/source/Lib/DecoderLib/DecSlice.cpp
index f70fb73f55..ed1b390a9a 100644
--- a/source/Lib/DecoderLib/DecSlice.cpp
+++ b/source/Lib/DecoderLib/DecSlice.cpp
@@ -127,7 +127,11 @@ void DecSlice::decompressSlice( Slice* slice, InputBitstream* bitstream, int deb
   DTRACE( g_trace_ctx, D_HEADER, "=========== POC: %d ===========\n", slice->getPOC() );
 
 
+#if JVET_S0258_SUBPIC_CONSTRAINTS
+  if( slice->getSliceType() != I_SLICE && slice->getRefPic( REF_PIC_LIST_0, 0 )->subPictures.size() > 1 )
+#else
   if (slice->getSliceType() != I_SLICE && slice->getRefPic(REF_PIC_LIST_0, 0)->numSubpics > 1)
+#endif
   {
     clipMv = clipMvInSubpic;
   }
@@ -166,7 +170,12 @@ void DecSlice::decompressSlice( Slice* slice, InputBitstream* bitstream, int deb
         for (int idx = 0; idx < n; idx++)
         {
           Picture *refPic = slice->getRefPic((RefPicList)rlist, idx);
+
+#if JVET_S0258_SUBPIC_CONSTRAINTS
+          if( !refPic->getSubPicSaved() && refPic->subPictures.size() > 1 )
+#else
           if (!refPic->getSubPicSaved() && refPic->numSubpics > 1)
+#endif
           {
             refPic->saveSubPicBorder(refPic->getPOC(), subPicX, subPicY, subPicWidth, subPicHeight);
             refPic->extendSubPicBorder(refPic->getPOC(), subPicX, subPicY, subPicWidth, subPicHeight);
diff --git a/source/Lib/EncoderLib/EncGOP.cpp b/source/Lib/EncoderLib/EncGOP.cpp
index 2ca92dcdce..6d5bb2e456 100644
--- a/source/Lib/EncoderLib/EncGOP.cpp
+++ b/source/Lib/EncoderLib/EncGOP.cpp
@@ -2265,6 +2265,14 @@ void EncGOP::compressGOP( int iPOCLast, int iNumPicRcvd, PicList& rcListPic,
     pcSlice->constructRefPicList(rcListPic);
 
     // store sub-picture numbers, sizes, and locations with a picture
+#if JVET_S0258_SUBPIC_CONSTRAINTS
+    pcSlice->getPic()->subPictures.clear();
+
+    for( int subPicIdx = 0; subPicIdx < pcPic->cs->pps->getNumSubPics(); subPicIdx++ )
+    {
+      pcSlice->getPic()->subPictures.push_back( pcPic->cs->pps->getSubPic( subPicIdx ) );
+    }
+#else
     pcSlice->getPic()->numSubpics = pcPic->cs->pps->getNumSubPics();
     pcSlice->getPic()->subpicWidthInCTUs.clear();
     pcSlice->getPic()->subpicHeightInCTUs.clear();
@@ -2277,6 +2285,7 @@ void EncGOP::compressGOP( int iPOCLast, int iNumPicRcvd, PicList& rcListPic,
       pcSlice->getPic()->subpicCtuTopLeftX.push_back(pcPic->cs->pps->getSubPic(subPicIdx).getSubPicCtuTopLeftX());
       pcSlice->getPic()->subpicCtuTopLeftY.push_back(pcPic->cs->pps->getSubPic(subPicIdx).getSubPicCtuTopLeftY());
     }
+#endif
 
     const VPS* vps = pcPic->cs->vps;
     int layerIdx = vps == nullptr ? 0 : vps->getGeneralLayerIdx(pcPic->layerId);
@@ -2756,7 +2765,11 @@ void EncGOP::compressGOP( int iPOCLast, int iNumPicRcvd, PicList& rcListPic,
         }
         m_pcSliceEncoder->setLosslessSlice(pcPic, isLossless);
 
+#if JVET_S0258_SUBPIC_CONSTRAINTS
+        if( pcSlice->getSliceType() != I_SLICE && pcSlice->getRefPic( REF_PIC_LIST_0, 0 )->subPictures.size() > 1 )
+#else
         if (pcSlice->getSliceType() != I_SLICE && pcSlice->getRefPic(REF_PIC_LIST_0, 0)->numSubpics > 1)
+#endif
         {
           clipMv = clipMvInSubpic;
           m_pcEncLib->getInterSearch()->setClipMvInSubPic(true);
diff --git a/source/Lib/EncoderLib/EncSlice.cpp b/source/Lib/EncoderLib/EncSlice.cpp
index 3ae1632bfe..b59fe3ad2e 100644
--- a/source/Lib/EncoderLib/EncSlice.cpp
+++ b/source/Lib/EncoderLib/EncSlice.cpp
@@ -1550,7 +1550,12 @@ void EncSlice::encodeCtus( Picture* pcPic, const bool bCompressEntireSlice, cons
         for (int idx = 0; idx < n; idx++)
         {
           Picture *refPic = pcSlice->getRefPic((RefPicList)rlist, idx);
+
+#if JVET_S0258_SUBPIC_CONSTRAINTS
+          if( !refPic->getSubPicSaved() && refPic->subPictures.size() > 1 )
+#else
           if (!refPic->getSubPicSaved() && refPic->numSubpics > 1)
+#endif
           {
             refPic->saveSubPicBorder(refPic->getPOC(), subPicX, subPicY, subPicWidth, subPicHeight);
             refPic->extendSubPicBorder(refPic->getPOC(), subPicX, subPicY, subPicWidth, subPicHeight);
-- 
GitLab


From b24639f0e2000ea856856795849f8420470bd9e2 Mon Sep 17 00:00:00 2001
From: Vadim Seregin <vseregin@qti.qualcomm.com>
Date: Thu, 9 Jul 2020 18:37:15 -0700
Subject: [PATCH 2/3] use non scaled ref pic

---
 source/Lib/CommonLib/UnitTools.cpp | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/source/Lib/CommonLib/UnitTools.cpp b/source/Lib/CommonLib/UnitTools.cpp
index 44004ea271..0b46b91630 100644
--- a/source/Lib/CommonLib/UnitTools.cpp
+++ b/source/Lib/CommonLib/UnitTools.cpp
@@ -163,13 +163,16 @@ void CU::checkConformanceILRP(Slice *slice)
   for (int refList = 0; refList < numRefList; refList++) // loop over l0 and l1
   {
     RefPicList  eRefPicList = (refList ? REF_PIC_LIST_1 : REF_PIC_LIST_0);
+
     for (int refIdx = 0; refIdx < slice->getNumRefIdx(eRefPicList); refIdx++)
     {
-      const Picture* refPic = slice->getRefPic(eRefPicList, refIdx)->unscaledPic;
-
 #if JVET_S0258_SUBPIC_CONSTRAINTS
+      const Picture* refPic = slice->getRefPic( eRefPicList, refIdx );
+
       if( refPic->subPictures.size() != slice->getPic()->cs->pps->getNumSubPics() )
 #else
+      const Picture* refPic = slice->getRefPic(eRefPicList, refIdx)->unscaledPic;
+
       if (refPic->numSubpics != slice->getPic()->cs->pps->getNumSubPics())
 #endif
       {
@@ -226,10 +229,11 @@ void CU::checkConformanceILRP(Slice *slice)
       RefPicList  eRefPicList = (refList ? REF_PIC_LIST_1 : REF_PIC_LIST_0);
       for (int refIdx = 0; refIdx < slice->getNumRefIdx(eRefPicList); refIdx++)
       {
-        const Picture* refPic = slice->getRefPic(eRefPicList, refIdx)->unscaledPic;
 #if JVET_S0258_SUBPIC_CONSTRAINTS
+        const Picture* refPic = slice->getRefPic( eRefPicList, refIdx );
         CHECK( refPic->layerId == slice->getPic()->layerId || refPic->subPictures.size() > 1, "The inter-layer reference shall contain a single subpicture or have same subpicture layout with the current picture" );
 #else
+        const Picture* refPic = slice->getRefPic(eRefPicList, refIdx)->unscaledPic;
         CHECK(!(refPic->layerId != slice->getPic()->layerId && refPic->numSubpics == 1), "The inter-layer reference shall contain a single subpicture or have same subpicture layout with the current picture");
 #endif
       }
-- 
GitLab


From 282e50775f77e6246f060c32083fdb544fce9010 Mon Sep 17 00:00:00 2001
From: Vadim Seregin <vseregin@qti.qualcomm.com>
Date: Sun, 19 Jul 2020 18:47:17 -0700
Subject: [PATCH 3/3] revert function return type

---
 source/Lib/CommonLib/UnitTools.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/source/Lib/CommonLib/UnitTools.h b/source/Lib/CommonLib/UnitTools.h
index 68805c4895..b73d2d5d77 100644
--- a/source/Lib/CommonLib/UnitTools.h
+++ b/source/Lib/CommonLib/UnitTools.h
@@ -121,7 +121,7 @@ namespace CU
   uint8_t numSbtModeRdo               (uint8_t sbtAllowed);
   bool    isSbtMode                   (const uint8_t sbtInfo);
   bool    isSameSbtSize               (const uint8_t sbtInfo1, const uint8_t sbtInfo2);
-  void    getRprScaling               ( const SPS* sps, const PPS* curPPS, Picture* refPic, int& xScale, int& yScale );
+  bool    getRprScaling               ( const SPS* sps, const PPS* curPPS, Picture* refPic, int& xScale, int& yScale );
   void    checkConformanceILRP        (Slice *slice);
 }
 // PU tools
-- 
GitLab