diff --git a/source/App/BitstreamExtractorApp/BitstreamExtractorApp.cpp b/source/App/BitstreamExtractorApp/BitstreamExtractorApp.cpp index 998482946fcca60775f9be513738ebfa23277730..8515d99c5eab994abe3e11086091f518ec7813fc 100644 --- a/source/App/BitstreamExtractorApp/BitstreamExtractorApp.cpp +++ b/source/App/BitstreamExtractorApp/BitstreamExtractorApp.cpp @@ -183,6 +183,21 @@ void BitstreamExtractorApp::xRewriteSPS (SPS &targetSPS, const SPS &sourceSPS, S targetSPS.setSubPicId(0, subPic.getSubPicID()); targetSPS.setMaxPicWidthInLumaSamples(subPic.getSubPicWidthInLumaSample()); targetSPS.setMaxPicHeightInLumaSamples(subPic.getSubPicHeightInLumaSample()); + +#if JVET_R0093_SUBPICS_AND_CONF_WINDOW + // Set the new conformance window + Window& conf = targetSPS.getConformanceWindow(); + int subpicConfWinLeftOffset = (subPic.getSubPicCtuTopLeftX() == 0) ? conf.getWindowLeftOffset() : 0; + int subpicConfWinRightOffset = ((subPic.getSubPicCtuTopLeftX() + subPic.getSubPicWidthInCTUs()) * sourceSPS.getCTUSize() >= sourceSPS.getMaxPicWidthInLumaSamples()) ? + conf.getWindowRightOffset() : 0; + int subpicConfWinTopOffset = (subPic.getSubPicCtuTopLeftY() == 0) ? conf.getWindowTopOffset() : 0; + int subpicConfWinBottomOffset = ((subPic.getSubPicCtuTopLeftY() + subPic.getSubPicHeightInCTUs()) * sourceSPS.getCTUSize() >= sourceSPS.getMaxPicHeightInLumaSamples()) ? + conf.getWindowBottomOffset() : 0; + conf.setWindowLeftOffset(subpicConfWinLeftOffset); + conf.setWindowRightOffset(subpicConfWinRightOffset); + conf.setWindowTopOffset(subpicConfWinTopOffset); + conf.setWindowBottomOffset(subpicConfWinBottomOffset); +#endif } diff --git a/source/App/EncoderApp/EncAppCfg.cpp b/source/App/EncoderApp/EncAppCfg.cpp index 6f9c6a55b6a2ac8aa22d3fd17c29a38263066cd0..5e8337aeba5626e13e8dd72082162fd021e60fd4 100644 --- a/source/App/EncoderApp/EncAppCfg.cpp +++ b/source/App/EncoderApp/EncAppCfg.cpp @@ -1866,6 +1866,22 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] ) } } +#if JVET_R0093_SUBPICS_AND_CONF_WINDOW + if( m_conformanceWindowMode > 0 && m_subPicInfoPresentFlag ) + { + for(int i = 0; i < m_numSubPics; i++) + { + CHECK( (m_subPicCtuTopLeftX[i] * m_uiCTUSize) >= (m_iSourceWidth - m_confWinRight * SPS::getWinUnitX(m_chromaFormatIDC)), + "No subpicture can be located completely outside of the conformance cropping window"); + CHECK( ((m_subPicCtuTopLeftX[i] + m_subPicWidth[i]) * m_uiCTUSize) <= (m_confWinLeft * SPS::getWinUnitX(m_chromaFormatIDC)), + "No subpicture can be located completely outside of the conformance cropping window" ); + CHECK( (m_subPicCtuTopLeftY[i] * m_uiCTUSize) >= (m_iSourceHeight - m_confWinBottom * SPS::getWinUnitY(m_chromaFormatIDC)), + "No subpicture can be located completely outside of the conformance cropping window"); + CHECK( ((m_subPicCtuTopLeftY[i] + m_subPicHeight[i]) * m_uiCTUSize) <= (m_confWinTop * SPS::getWinUnitY(m_chromaFormatIDC)), + "No subpicture can be located completely outside of the conformance cropping window"); + } + } +#endif if (tmpDecodedPictureHashSEIMappedType<0 || tmpDecodedPictureHashSEIMappedType>=int(NUMBER_OF_HASHTYPES)) { diff --git a/source/Lib/CommonLib/Slice.cpp b/source/Lib/CommonLib/Slice.cpp index 4901051d25b7be42cb3e03ffa05cbfe3485f96fc..571f485cc5f7014046ccd9975043002a98cfa14a 100644 --- a/source/Lib/CommonLib/Slice.cpp +++ b/source/Lib/CommonLib/Slice.cpp @@ -3346,6 +3346,24 @@ void PPS::initSubPic(const SPS &sps) CHECK(getNumSubPics() > MAX_NUM_SUB_PICS, "Number of sub-pictures in picture exceeds valid range"); m_subPics.resize(getNumSubPics()); + +#if JVET_R0093_SUBPICS_AND_CONF_WINDOW + // Check that no subpicture is specified outside of the conformance cropping window + for(int i = 0; i < sps.getNumSubPics(); i++) + { + CHECK( (sps.getSubPicCtuTopLeftX(i) * sps.getCTUSize()) >= + (sps.getMaxPicWidthInLumaSamples() - sps.getConformanceWindow().getWindowRightOffset() * SPS::getWinUnitX(sps.getChromaFormatIdc())), + "No subpicture can be located completely outside of the conformance cropping window"); + CHECK( ((sps.getSubPicCtuTopLeftX(i) + sps.getSubPicWidth(i)) * sps.getCTUSize()) <= (sps.getConformanceWindow().getWindowLeftOffset() * SPS::getWinUnitX(sps.getChromaFormatIdc())), + "No subpicture can be located completely outside of the conformance cropping window" ); + CHECK( (sps.getSubPicCtuTopLeftY(i) * sps.getCTUSize()) >= + (sps.getMaxPicHeightInLumaSamples() - sps.getConformanceWindow().getWindowBottomOffset() * SPS::getWinUnitY(sps.getChromaFormatIdc())), + "No subpicture can be located completely outside of the conformance cropping window"); + CHECK( ((sps.getSubPicCtuTopLeftY(i) + sps.getSubPicHeight(i)) * sps.getCTUSize()) <= (sps.getConformanceWindow().getWindowTopOffset() * SPS::getWinUnitY(sps.getChromaFormatIdc())), + "No subpicture can be located completely outside of the conformance cropping window"); + } +#endif + // m_ctuSize, m_picWidthInCtu, and m_picHeightInCtu might not be initialized yet. if (m_ctuSize == 0 || m_picWidthInCtu == 0 || m_picHeightInCtu == 0) { diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h index 516deaedc0469bd1cfe301eefad980d09bdfdafb..6bb10b32899faf8dd1f84454d75d651abfce69a9 100644 --- a/source/Lib/CommonLib/TypeDef.h +++ b/source/Lib/CommonLib/TypeDef.h @@ -71,6 +71,8 @@ #define JVET_S0155_EOS_NALU_CHECK 1 // JVET-S0155: Constraints on EOS NAL units +#define JVET_R0093_SUBPICS_AND_CONF_WINDOW 1 // JVET-R0093 and JVET-R0294: Constraint on subpictures and conformance cropping window, and rewriting of conformance cropping window in subpicture extraction + #define JVET_S0160_ASPECT1_ASPECT9 1 // JVET-S0160: Aspect 1 Infer the value of pps_loop_filter_across_tiles_enabled_flag to be equal to 0 (instead of 1) when not present // Aspect 9 The value of ph_poc_msb_cycle_present_flag is required to be equal to 0 when vps_independent_layer_flag[GeneralLayerIdx[nuh_layer_id]] is equal to 0 and there is an ILRP entry in RefPicList[0] or RefPicList[1] of a slice of the current picture