diff --git a/source/Lib/CommonLib/Picture.cpp b/source/Lib/CommonLib/Picture.cpp index 7ddff73e578b12ec49726ccbedbf3140cad96d46..8d05d1087dc164df5f93f59b9f73e3c71f8c885b 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 ee32fa54c7e92bbf22900e2a32caea5bcedeb748..7e9e44ffaece023e7bc78077b83b58d8d6de9de4 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 8ca78240a83105d14bb99a6a768fa90ef0324fc7..2be17962bac5651ca634e38c05d80c0b195b609b 100644 --- a/source/Lib/CommonLib/TypeDef.h +++ b/source/Lib/CommonLib/TypeDef.h @@ -59,6 +59,8 @@ #define JVET_S0049_ASPECT4 1 // JVET-S0049 aspect 4: Constrain the value of pps_alf_info_in_ph_flag to be equal to 0 when the PH is in the SH +#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_S0234_ACT_CRS_FIX 1 // JVET-S0234: perform chroma residual scaling in RGB domain when ACT is on diff --git a/source/Lib/CommonLib/UnitTools.cpp b/source/Lib/CommonLib/UnitTools.cpp index d77cea079700ba9873e40824ba0b831c4e7bba9a..8e11c1ec0e08881003b7b96e28c32a8e24e012b5 100644 --- a/source/Lib/CommonLib/UnitTools.cpp +++ b/source/Lib/CommonLib/UnitTools.cpp @@ -155,18 +155,46 @@ 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; 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++) { +#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 { isAllRefSameSubpicLayout = false; refList = numRefList; @@ -174,12 +202,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); @@ -187,6 +229,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 } } } @@ -199,8 +249,13 @@ 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++) { +#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 } } } diff --git a/source/Lib/DecoderLib/DecLib.cpp b/source/Lib/DecoderLib/DecLib.cpp index a94f901e0a2c76de844c3ce02af696bc9fc55ecc..e02bc98bade5df02c58960aa49f4a97afe5f2072 100644 --- a/source/Lib/DecoderLib/DecLib.cpp +++ b/source/Lib/DecoderLib/DecLib.cpp @@ -2223,6 +2223,14 @@ bool DecLib::xDecodeSlice(InputNALUnit &nalu, int &iSkipFrame, int iPOCLastDispl checkPicTypeAfterEos(); #endif // 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(); @@ -2235,6 +2243,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(); } @@ -2255,6 +2264,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. @@ -2301,6 +2311,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 f70fb73f55aaebae628dc795a19ed9f1daff5ef2..ed1b390a9a11f97ddbce1195a4803c81e77a236e 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 b4b2044981a358d33d06b42ad417d1b877244e2e..16d9fbf88a949ff697056d4351693ae1d2fdbc04 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); @@ -2801,7 +2810,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 8897f7e5e4b92565362ff59109e63325c0f083d8..0d71f608f7ede97f16d91eaaf70d7dc9e7890254 100644 --- a/source/Lib/EncoderLib/EncSlice.cpp +++ b/source/Lib/EncoderLib/EncSlice.cpp @@ -1553,7 +1553,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);