diff --git a/source/Lib/CommonLib/Slice.h b/source/Lib/CommonLib/Slice.h index aa0dc49eee663cd61e40609f2d80873a8dcddd8f..cdad3208b2aa6bc5325b128828c3a8d41814c815 100644 --- a/source/Lib/CommonLib/Slice.h +++ b/source/Lib/CommonLib/Slice.h @@ -1549,11 +1549,11 @@ public: void setSubPicId( int i, uint8_t u ) { CHECK( i >= MAX_NUM_SUB_PICS, "Sub-picture index exceeds valid range" ); m_subPicId[i] = u; } uint8_t getSubPicId( int i ) const { CHECK( i >= MAX_NUM_SUB_PICS, "Sub-picture index exceeds valid range" ); return m_subPicId[i]; } - uint32_t getNumLongTermRefPicSPS() const { return m_numLongTermRefPicSPS; } - void setNumLongTermRefPicSPS(uint32_t val) { m_numLongTermRefPicSPS = val; } + uint32_t getNumLongTermRefPicSPS() const { return m_numLongTermRefPicSPS; } + void setNumLongTermRefPicSPS(uint32_t val) { m_numLongTermRefPicSPS = val; } - uint32_t getLtRefPicPocLsbSps(uint32_t index) const { CHECK( index >= MAX_NUM_LONG_TERM_REF_PICS, "Index exceeds boundary" ); return m_ltRefPicPocLsbSps[index]; } - void setLtRefPicPocLsbSps(uint32_t index, uint32_t val) { CHECK( index >= MAX_NUM_LONG_TERM_REF_PICS, "Index exceeds boundary" ); m_ltRefPicPocLsbSps[index] = val; } + uint32_t getLtRefPicPocLsbSps(uint32_t index) const { CHECK( index >= MAX_NUM_LONG_TERM_REF_PICS, "Index exceeds boundary" ); return m_ltRefPicPocLsbSps[index]; } + void setLtRefPicPocLsbSps(uint32_t index, uint32_t val) { CHECK( index >= MAX_NUM_LONG_TERM_REF_PICS, "Index exceeds boundary" ); m_ltRefPicPocLsbSps[index] = val; } bool getUsedByCurrPicLtSPSFlag(int i) const { CHECK( i >= MAX_NUM_LONG_TERM_REF_PICS, "Index exceeds boundary" ); return m_usedByCurrPicLtSPSFlag[i]; } void setUsedByCurrPicLtSPSFlag(int i, bool x) { CHECK( i >= MAX_NUM_LONG_TERM_REF_PICS, "Index exceeds boundary" ); m_usedByCurrPicLtSPSFlag[i] = x; } diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h index f546431cd5e39ab6c3167f59acf11efc485b9895..1eb6c6fc8ce98ef2167211a9c4edc6f8d87f46ae 100644 --- a/source/Lib/CommonLib/TypeDef.h +++ b/source/Lib/CommonLib/TypeDef.h @@ -52,6 +52,7 @@ #define JVET_Q0798_SPS_NUMBER_MERGE_CANDIDATE 1 // JVET-Q0798: signal the number of merge candidates in SPS +#define JVET_Q0157_SUBPICTURE_REORDERING_CONSTRAINT 1 //JVET-Q0157: subpicture reordering constraint #define JVET_Q0371_DEBLOCKING_CLEANUP 1 //JVET_Q0371: cleanup on deblocking across subpicture boundaries diff --git a/source/Lib/DecoderLib/DecLib.cpp b/source/Lib/DecoderLib/DecLib.cpp index e854cb56fd0ff0151c27b42495804b24eb6ae724..56e44261c1da3563879f643d35e42a70a53e3eb7 100644 --- a/source/Lib/DecoderLib/DecLib.cpp +++ b/source/Lib/DecoderLib/DecLib.cpp @@ -1590,6 +1590,52 @@ void DecLib::xCheckParameterSetConstraints(const int layerId) CHECK(levelIdcSps > maxLevelIdxDci, "max level signaled in the DCI shall not be less than the level signaled in the SPS"); } #endif + +#if JVET_Q0157_SUBPICTURE_REORDERING_CONSTRAINT + // When the current picture is not the first picture of the CLVS, if the value of SubpicId[ i ] is not equal to the value of SubpicId[ i ] of previous picture in decoding order in the same layer, + // the nal_unit_type for all coded slice NAL units of the the subpicture with subpicture index i shall be in the range of IDR_W_RADL to CRA_NUT, inclusive. + if( sps->getSubPicInfoPresentFlag() ) + { + static std::unordered_map<int, std::vector<int>> previousSubPicIds; + + if( m_firstSliceInSequence[layerId] ) + { + for( int subPicIdx = 0; subPicIdx < sps->getNumSubPics(); subPicIdx++ ) + { + previousSubPicIds[layerId].push_back( pps->getSubPic( subPicIdx ).getSubPicID() ); + } + } + else + { + int currentSubPicIdx = NOT_VALID; + for( int subPicIdx = 0; subPicIdx < sps->getNumSubPics(); subPicIdx++ ) + { + if( pps->getSubPic( subPicIdx ).getSubPicID() == slice->getSliceSubPicId() ) + { + currentSubPicIdx = subPicIdx; + break; + } + } + + CHECK( currentSubPicIdx == NOT_VALID, "Sub-picture was not found" ); + CHECK( !previousSubPicIds.count( layerId ), "Sub-picture information of the previously decoded picture was not stored" ); + + if( previousSubPicIds[layerId][currentSubPicIdx] != slice->getSliceSubPicId() ) + { + CHECK( !slice->isIRAP(), "For reordered sub-pictures, the slice NAL shall be in the range of IDR_W_RADL to CRA_NUT, inclusive" ) + } + + // store PPS ID to have sub-picture info for the next pictures when last rectangular slice in the picture is encountered + if( slice->getSliceID() + 1 == pps->getNumSlicesInPic() ) + { + for( int subPicIdx = 0; subPicIdx < sps->getNumSubPics(); subPicIdx++ ) + { + previousSubPicIds[layerId].push_back( pps->getSubPic( subPicIdx ).getSubPicID() ); + } + } + } + } +#endif } diff --git a/source/Lib/EncoderLib/EncGOP.cpp b/source/Lib/EncoderLib/EncGOP.cpp index 9fc6e1feb4fb2ce910da463e8b657792f6832c7e..777172787f3f829dcd60d88df381713a1d42598c 100644 --- a/source/Lib/EncoderLib/EncGOP.cpp +++ b/source/Lib/EncoderLib/EncGOP.cpp @@ -2813,21 +2813,24 @@ void EncGOP::compressGOP( int iPOCLast, int iNumPicRcvd, PicList& rcListPic, { pcSlice->setSliceMap( pcPic->cs->pps->getSliceMap( sliceIdx ) ); #if JVET_Q0044_SLICE_IDX_WITH_SUBPICS - if( pcPic->cs->pps->getRectSliceFlag() ) - { + if( pcPic->cs->pps->getRectSliceFlag() ) + { Position firstCtu; firstCtu.x = pcSlice->getFirstCtuRsAddrInSlice() % pcPic->cs->pps->getPicWidthInCtu(); firstCtu.y = pcSlice->getFirstCtuRsAddrInSlice() / pcPic->cs->pps->getPicWidthInCtu(); - int subPicIdx = 0; - for(int sp = 0; sp < pcPic->cs->pps->getNumSubPics(); sp++) + int subPicIdx = NOT_VALID; + for( int sp = 0; sp < pcPic->cs->pps->getNumSubPics(); sp++ ) { - if(pcPic->cs->pps->getSubPic(sp).containsCtu(firstCtu)) + if( pcPic->cs->pps->getSubPic( sp ).containsCtu( firstCtu ) ) { subPicIdx = sp; + break; } } - pcSlice->setSliceSubPicId( pcPic->cs->pps->getSubPic(subPicIdx).getSubPicID() ); - } + CHECK( subPicIdx == NOT_VALID, "Sub-picture was not found" ); + + pcSlice->setSliceSubPicId( pcPic->cs->pps->getSubPic( subPicIdx ).getSubPicID() ); + } #endif m_pcSliceEncoder->precompressSlice( pcPic ); m_pcSliceEncoder->compressSlice ( pcPic, false, false );