From f08451322d76444aafd3851469e78e4a721ef10d Mon Sep 17 00:00:00 2001 From: Mitsuru Katsumata <mitsuru.katsumata@sony.com> Date: Tue, 14 Jul 2020 15:59:14 +0900 Subject: [PATCH] JVET-S0071 --- source/App/EncoderApp/EncApp.cpp | 3 ++ source/App/EncoderApp/EncAppCfg.cpp | 59 ++++++++++++++++++++++- source/App/EncoderApp/EncAppCfg.h | 3 ++ source/Lib/CommonLib/Slice.cpp | 3 ++ source/Lib/CommonLib/Slice.h | 7 +++ source/Lib/CommonLib/TypeDef.h | 4 +- source/Lib/DecoderLib/VLCReader.cpp | 74 +++++++++++++++++++++++++++++ source/Lib/EncoderLib/EncCfg.h | 17 ++++++- source/Lib/EncoderLib/EncLib.cpp | 22 +++++++++ source/Lib/EncoderLib/VLCWriter.cpp | 32 +++++++++++++ 10 files changed, 219 insertions(+), 5 deletions(-) diff --git a/source/App/EncoderApp/EncApp.cpp b/source/App/EncoderApp/EncApp.cpp index 2d092e9b3..e328b7157 100644 --- a/source/App/EncoderApp/EncApp.cpp +++ b/source/App/EncoderApp/EncApp.cpp @@ -420,6 +420,9 @@ void EncApp::xInitLibCfg() if(m_subPicInfoPresentFlag) { m_cEncLib.setNumSubPics ( m_numSubPics ); +#if JVET_S0071_SAME_SIZE_SUBPIC_LAYOUT + m_cEncLib.setSubPicSameSizeFlag ( m_subPicSameSizeFlag ); +#endif m_cEncLib.setSubPicCtuTopLeftX ( m_subPicCtuTopLeftX ); m_cEncLib.setSubPicCtuTopLeftY ( m_subPicCtuTopLeftY ); m_cEncLib.setSubPicWidth ( m_subPicWidth ); diff --git a/source/App/EncoderApp/EncAppCfg.cpp b/source/App/EncoderApp/EncAppCfg.cpp index c6da6cf15..db190aea4 100644 --- a/source/App/EncoderApp/EncAppCfg.cpp +++ b/source/App/EncoderApp/EncAppCfg.cpp @@ -832,6 +832,9 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] ) ("Log2MinCuSize", m_log2MinCuSize, 2u, "Log2 min CU size") ("SubPicInfoPresentFlag", m_subPicInfoPresentFlag, false, "equal to 1 specifies that subpicture parameters are present in in the SPS RBSP syntax") ("NumSubPics", m_numSubPics, 0u, "specifies the number of subpictures") +#if JVET_S0071_SAME_SIZE_SUBPIC_LAYOUT + ("SubPicSameSizeFlag", m_subPicSameSizeFlag, false, "equal to 1 specifies that all subpictures in the CLVS have the same width specified by sps_subpic_width_minus1[ 0 ] and the same height specified by sps_subpic_height_minus1[ 0 ].") +#endif ("SubPicCtuTopLeftX", cfg_subPicCtuTopLeftX, cfg_subPicCtuTopLeftX, "specifies horizontal position of top left CTU of i-th subpicture in unit of CtbSizeY") ("SubPicCtuTopLeftY", cfg_subPicCtuTopLeftY, cfg_subPicCtuTopLeftY, "specifies vertical position of top left CTU of i-th subpicture in unit of CtbSizeY") ("SubPicWidth", cfg_subPicWidth, cfg_subPicWidth, "specifies the width of the i-th subpicture in units of CtbSizeY") @@ -1566,11 +1569,28 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] ) } if ( m_subPicInfoPresentFlag ) { - CHECK( m_numSubPics > MAX_NUM_SUB_PICS || m_numSubPics < 1, "Number of subpicture must be within 1 to 2^16" ); + CHECK( m_numSubPics > MAX_NUM_SUB_PICS || m_numSubPics < 1, "Number of subpicture must be within 1 to 2^16" ) +#if JVET_S0071_SAME_SIZE_SUBPIC_LAYOUT + if (!m_subPicSameSizeFlag) + { + CHECK(cfg_subPicCtuTopLeftX.values.size() != m_numSubPics, "Number of SubPicCtuTopLeftX values must be equal to NumSubPics"); + CHECK(cfg_subPicCtuTopLeftY.values.size() != m_numSubPics, "Number of SubPicCtuTopLeftY values must be equal to NumSubPics"); + CHECK(cfg_subPicWidth.values.size() != m_numSubPics, "Number of SubPicWidth values must be equal to NumSubPics"); + CHECK(cfg_subPicHeight.values.size() != m_numSubPics, "Number of SubPicHeight values must be equal to NumSubPics"); + } + else + { + CHECK(cfg_subPicCtuTopLeftX.values.size() != 0, "Number of SubPicCtuTopLeftX values must be equal to 0"); + CHECK(cfg_subPicCtuTopLeftY.values.size() != 0, "Number of SubPicCtuTopLeftY values must be equal to 0"); + CHECK(cfg_subPicWidth.values.size() != 1, "Number of SubPicWidth values must be equal to 1"); + CHECK(cfg_subPicHeight.values.size() != 1, "Number of SubPicHeight values must be equal to 1"); + } +#else CHECK( cfg_subPicCtuTopLeftX.values.size() != m_numSubPics, "Number of SubPicCtuTopLeftX values must be equal to NumSubPics"); CHECK( cfg_subPicCtuTopLeftY.values.size() != m_numSubPics, "Number of SubPicCtuTopLeftY values must be equal to NumSubPics"); CHECK( cfg_subPicWidth.values.size() != m_numSubPics, "Number of SubPicWidth values must be equal to NumSubPics"); CHECK( cfg_subPicHeight.values.size() != m_numSubPics, "Number of SubPicHeight values must be equal to NumSubPics"); +#endif CHECK( cfg_subPicTreatedAsPicFlag.values.size() != m_numSubPics, "Number of SubPicTreatedAsPicFlag values must be equal to NumSubPics"); CHECK( cfg_loopFilterAcrossSubpicEnabledFlag.values.size() != m_numSubPics, "Number of LoopFilterAcrossSubpicEnabledFlag values must be equal to NumSubPics"); if (m_subPicIdMappingExplicitlySignalledFlag) @@ -1590,11 +1610,31 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] ) m_subPicId[i] = cfg_subPicId.values[i]; } } +#if JVET_S0071_SAME_SIZE_SUBPIC_LAYOUT + uint32_t tmpWidthVal = (m_iSourceWidth + m_uiCTUSize - 1) / m_uiCTUSize; + uint32_t tmpHeightVal = (m_iSourceHeight + m_uiCTUSize - 1) / m_uiCTUSize; + if (!m_subPicSameSizeFlag) + { + for (int i = 0; i < m_numSubPics; i++) + { + CHECK(m_subPicCtuTopLeftX[i] + m_subPicWidth[i] > tmpWidthVal, "Subpicture must not exceed picture boundary"); + CHECK(m_subPicCtuTopLeftY[i] + m_subPicHeight[i] > tmpHeightVal, "Subpicture must not exceed picture boundary"); + } + } + else + { + uint32_t numSubpicCols = tmpWidthVal / m_subPicWidth[0]; + CHECK(tmpWidthVal % m_subPicWidth[0] != 0, "subpic_width_minus1[0] is invalid."); + CHECK(tmpHeightVal % m_subPicHeight[0] != 0, "subpic_height_minus1[0] is invalid."); + CHECK(numSubpicCols * (tmpHeightVal / m_subPicHeight[0]) != m_numSubPics, "when sps_subpic_same_size_flag is equal to, sps_num_subpics_minus1 is invalid"); + } +#else for(int i = 0; i < m_numSubPics; i++) { CHECK(m_subPicCtuTopLeftX[i] + m_subPicWidth[i] > (m_iSourceWidth + m_uiCTUSize - 1) / m_uiCTUSize, "Subpicture must not exceed picture boundary"); CHECK(m_subPicCtuTopLeftY[i] + m_subPicHeight[i] > (m_iSourceHeight + m_uiCTUSize - 1) / m_uiCTUSize, "Subpicture must not exceed picture boundary"); } +#endif // automatically determine subpicture ID lenght in case it is not specified if (m_subPicIdLen == 0) { @@ -3593,14 +3633,29 @@ void EncAppCfg::xPrintParameter() if (m_subPicInfoPresentFlag) { msg(DETAILS, "number of subpictures : %d\n", m_numSubPics); +#if JVET_S0071_SAME_SIZE_SUBPIC_LAYOUT + msg(DETAILS, "subpicture size same flag : %d\n", m_subPicSameSizeFlag); + if (m_subPicSameSizeFlag) + msg(DETAILS, "[0]th subpictures size :[%d %d]\n", m_subPicWidth[0], m_subPicHeight[0]); + for (int i = 0; i < m_numSubPics; i++) + { + if (!m_subPicSameSizeFlag) + { + msg(DETAILS, "[%d]th subpictures location :[%d %d]\n", i, m_subPicCtuTopLeftX[i], m_subPicCtuTopLeftY[i]); + msg(DETAILS, "[%d]th subpictures size :[%d %d]\n", i, m_subPicWidth[i], m_subPicHeight[i]); + } + msg(DETAILS, "[%d]th subpictures treated as picture flag :%d\n", i, m_subPicTreatedAsPicFlag[i]); + msg(DETAILS, "loop filter cross [%d]th subpictures enabled flag :%d\n", i, m_loopFilterAcrossSubpicEnabledFlag[i]); + } +#else for (int i = 0; i < m_numSubPics; i++) { msg(DETAILS, "[%d]th subpictures location :[%d %d]\n", i, m_subPicCtuTopLeftX[i], m_subPicCtuTopLeftY[i]); msg(DETAILS, "[%d]th subpictures size :[%d %d]\n", i, m_subPicWidth[i], m_subPicHeight[i]); msg(DETAILS, "[%d]th subpictures treated as picture flag :%d\n", i, m_subPicTreatedAsPicFlag[i]); msg(DETAILS, "loop filter cross [%d]th subpictures enabled flag :%d\n", i, m_loopFilterAcrossSubpicEnabledFlag[i]); - } +#endif } msg(DETAILS, "subpicture ID present flag : %d\n", m_subPicIdMappingExplicitlySignalledFlag); diff --git a/source/App/EncoderApp/EncAppCfg.h b/source/App/EncoderApp/EncAppCfg.h index 8de7603e3..76edb6523 100644 --- a/source/App/EncoderApp/EncAppCfg.h +++ b/source/App/EncoderApp/EncAppCfg.h @@ -278,6 +278,9 @@ protected: unsigned m_uiCTUSize; bool m_subPicInfoPresentFlag; unsigned m_numSubPics; +#if JVET_S0071_SAME_SIZE_SUBPIC_LAYOUT + bool m_subPicSameSizeFlag; +#endif std::vector<uint32_t> m_subPicCtuTopLeftX; std::vector<uint32_t> m_subPicCtuTopLeftY; std::vector<uint32_t> m_subPicWidth; diff --git a/source/Lib/CommonLib/Slice.cpp b/source/Lib/CommonLib/Slice.cpp index 9a4a634f8..7ec20d0fd 100644 --- a/source/Lib/CommonLib/Slice.cpp +++ b/source/Lib/CommonLib/Slice.cpp @@ -2701,6 +2701,9 @@ SPS::SPS() , m_subPicInfoPresentFlag (false) , m_numSubPics(1) , m_independentSubPicsFlag (false) +#if JVET_S0071_SAME_SIZE_SUBPIC_LAYOUT +, m_subPicSameSizeFlag (false) +#endif , m_subPicIdMappingExplicitlySignalledFlag ( false ) , m_subPicIdMappingInSpsFlag ( false ) , m_subPicIdLen(16) diff --git a/source/Lib/CommonLib/Slice.h b/source/Lib/CommonLib/Slice.h index 0cfaca12b..313f46e94 100644 --- a/source/Lib/CommonLib/Slice.h +++ b/source/Lib/CommonLib/Slice.h @@ -1288,6 +1288,9 @@ private: bool m_subPicInfoPresentFlag; // indicates the presence of sub-picture info uint32_t m_numSubPics; //!< number of sub-pictures used bool m_independentSubPicsFlag; +#if JVET_S0071_SAME_SIZE_SUBPIC_LAYOUT + bool m_subPicSameSizeFlag; +#endif std::vector<uint32_t> m_subPicCtuTopLeftX; std::vector<uint32_t> m_subPicCtuTopLeftY; std::vector<uint32_t> m_subPicWidth; @@ -1481,6 +1484,10 @@ public: } void setIndependentSubPicsFlag(bool b) { m_independentSubPicsFlag = b; } bool getIndependentSubPicsFlag() const { return m_independentSubPicsFlag; } +#if JVET_S0071_SAME_SIZE_SUBPIC_LAYOUT + void setSubPicSameSizeFlag(bool b) { m_subPicSameSizeFlag = b; } + bool getSubPicSameSizeFlag() const { return m_subPicSameSizeFlag; } +#endif uint32_t getNumSubPics( ) const { return m_numSubPics; } void setSubPicCtuTopLeftX( int i, uint32_t u ) { m_subPicCtuTopLeftX[i] = u; } uint32_t getSubPicCtuTopLeftX( int i ) const { return m_subPicCtuTopLeftX[i]; } diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h index acde67751..96fb1fcf4 100644 --- a/source/Lib/CommonLib/TypeDef.h +++ b/source/Lib/CommonLib/TypeDef.h @@ -53,7 +53,7 @@ //########### place macros to be removed in next cycle below this line ############### - +#define JVET_S0071_SAME_SIZE_SUBPIC_LAYOUT 1 // JVET-S0071 : shortcut when all subpictures have the same size //########### place macros to be be kept below this line ############### #define JVET_R0351_HIGH_BIT_DEPTH_SUPPORT 1 // JVET-R0351: high bit depth coding support (syntax changes, no mathematical differences for CTCs) @@ -109,7 +109,7 @@ typedef std::pair<int, int> TrCost; // ==================================================================================================================== #ifndef ENABLE_TRACING -#define ENABLE_TRACING 0 // DISABLE by default (enable only when debugging, requires 15% run-time in decoding) -- see documentation in 'doc/DTrace for NextSoftware.pdf' +#define ENABLE_TRACING 1 // DISABLE by default (enable only when debugging, requires 15% run-time in decoding) -- see documentation in 'doc/DTrace for NextSoftware.pdf' #endif #if ENABLE_TRACING diff --git a/source/Lib/DecoderLib/VLCReader.cpp b/source/Lib/DecoderLib/VLCReader.cpp index 276c3fd50..5e19ce944 100644 --- a/source/Lib/DecoderLib/VLCReader.cpp +++ b/source/Lib/DecoderLib/VLCReader.cpp @@ -1365,12 +1365,85 @@ void HLSyntaxReader::parseSPS(SPS* pcSPS) pcSPS->setSubPicHeight( 0, ( pcSPS->getMaxPicHeightInLumaSamples() + pcSPS->getCTUSize() - 1 ) >> floorLog2( pcSPS->getCTUSize() ) ); pcSPS->setIndependentSubPicsFlag(1); +#if JVET_S0071_SAME_SIZE_SUBPIC_LAYOUT + pcSPS->setSubPicSameSizeFlag(0); +#endif pcSPS->setSubPicTreatedAsPicFlag(0, 1); pcSPS->setLoopFilterAcrossSubpicEnabledFlag(0, 0); } else { +#if JVET_S0071_SAME_SIZE_SUBPIC_LAYOUT + READ_FLAG(uiCode, "sps_independent_subpics_flag"); pcSPS->setIndependentSubPicsFlag(uiCode != 0); + READ_FLAG(uiCode, "sps_subpic_same_size_flag"); pcSPS->setSubPicSameSizeFlag(uiCode); + uint32_t tmpWidthVal = (pcSPS->getMaxPicWidthInLumaSamples() + pcSPS->getCTUSize() - 1) / pcSPS->getCTUSize(); + uint32_t tmpHeightVal = (pcSPS->getMaxPicHeightInLumaSamples() + pcSPS->getCTUSize() - 1) / pcSPS->getCTUSize(); + uint32_t numSubpicCols = 1; + for (int picIdx = 0; picIdx < pcSPS->getNumSubPics(); picIdx++) + { + if (!pcSPS->getSubPicSameSizeFlag() || picIdx == 0) + { + if ((picIdx > 0) && (pcSPS->getMaxPicWidthInLumaSamples() > pcSPS->getCTUSize())) + { + READ_CODE(ceilLog2(tmpWidthVal), uiCode, "subpic_ctu_top_left_x[ i ]"); + pcSPS->setSubPicCtuTopLeftX(picIdx, uiCode); + } + else + { + pcSPS->setSubPicCtuTopLeftX(picIdx, 0); + } + if ((picIdx > 0) && (pcSPS->getMaxPicHeightInLumaSamples() > pcSPS->getCTUSize())) + { + READ_CODE(ceilLog2(tmpHeightVal), uiCode, "subpic_ctu_top_left_y[ i ]"); + pcSPS->setSubPicCtuTopLeftY(picIdx, uiCode); + } + else + { + pcSPS->setSubPicCtuTopLeftY(picIdx, 0); + } + if (picIdx <pcSPS->getNumSubPics() - 1 && pcSPS->getMaxPicWidthInLumaSamples() > pcSPS->getCTUSize()) + { + READ_CODE(ceilLog2(tmpWidthVal), uiCode, "subpic_width_minus1[ i ]"); + pcSPS->setSubPicWidth(picIdx, uiCode + 1); + } + else + { + pcSPS->setSubPicWidth(picIdx, tmpWidthVal - pcSPS->getSubPicCtuTopLeftX(picIdx)); + } + if (picIdx <pcSPS->getNumSubPics() - 1 && pcSPS->getMaxPicHeightInLumaSamples() > pcSPS->getCTUSize()) + { + READ_CODE(ceilLog2(tmpHeightVal), uiCode, "subpic_height_minus1[ i ]"); + pcSPS->setSubPicHeight(picIdx, uiCode + 1); + } + else + { + pcSPS->setSubPicHeight(picIdx, tmpHeightVal - pcSPS->getSubPicCtuTopLeftY(picIdx)); + } + if (pcSPS->getSubPicSameSizeFlag()) + { + numSubpicCols = tmpWidthVal / pcSPS->getSubPicWidth(0); + CHECK(!(tmpWidthVal % pcSPS->getSubPicWidth(0) == 0), "subpic_width_minus1[0] is invalid."); + CHECK(!(tmpHeightVal % pcSPS->getSubPicHeight(0) == 0), "subpic_height_minus1[0] is invalid."); + CHECK(!(numSubpicCols * (tmpHeightVal / pcSPS->getSubPicHeight(0)) == pcSPS->getNumSubPics()), "when sps_subpic_same_size_flag is equal to, sps_num_subpics_minus1 is invalid"); + } + } + else + { + pcSPS->setSubPicCtuTopLeftX(picIdx, (picIdx % numSubpicCols) * pcSPS->getSubPicWidth(0)); + pcSPS->setSubPicCtuTopLeftY(picIdx, (picIdx / numSubpicCols) * pcSPS->getSubPicHeight(0)); + pcSPS->setSubPicWidth(picIdx, pcSPS->getSubPicWidth(0)); + pcSPS->setSubPicHeight(picIdx, pcSPS->getSubPicHeight(0)); + } + if (!pcSPS->getIndependentSubPicsFlag()) + { + READ_FLAG(uiCode, "subpic_treated_as_pic_flag[ i ]"); + pcSPS->setSubPicTreatedAsPicFlag(picIdx, uiCode); + READ_FLAG(uiCode, "loop_filter_across_subpic_enabled_flag[ i ]"); + pcSPS->setLoopFilterAcrossSubpicEnabledFlag(picIdx, uiCode); + } + } +#else READ_FLAG(uiCode, "sps_independent_subpics_flag"); pcSPS->setIndependentSubPicsFlag(uiCode != 0); for (int picIdx = 0; picIdx < pcSPS->getNumSubPics(); picIdx++) { @@ -1418,6 +1491,7 @@ void HLSyntaxReader::parseSPS(SPS* pcSPS) pcSPS->setLoopFilterAcrossSubpicEnabledFlag(picIdx, uiCode); } } +#endif } READ_UVLC( uiCode, "sps_subpic_id_len_minus1" ); pcSPS->setSubPicIdLen( uiCode + 1 ); diff --git a/source/Lib/EncoderLib/EncCfg.h b/source/Lib/EncoderLib/EncCfg.h index 2547b7c62..abc860cca 100644 --- a/source/Lib/EncoderLib/EncCfg.h +++ b/source/Lib/EncoderLib/EncCfg.h @@ -278,6 +278,9 @@ protected: unsigned m_CTUSize; bool m_subPicInfoPresentFlag; uint32_t m_numSubPics; +#if JVET_S0071_SAME_SIZE_SUBPIC_LAYOUT + bool m_subPicSameSizeFlag; +#endif std::vector<uint32_t> m_subPicCtuTopLeftX; std::vector<uint32_t> m_subPicCtuTopLeftY; std::vector<uint32_t> m_subPicWidth; @@ -967,17 +970,26 @@ public: m_loopFilterAcrossSubpicEnabledFlag.resize(m_numSubPics); m_subPicId.resize(m_numSubPics); } +#if JVET_S0071_SAME_SIZE_SUBPIC_LAYOUT + void setSubPicSameSizeFlag (bool b) { m_subPicSameSizeFlag = b; } +#endif void setSubPicCtuTopLeftX (uint32_t u, int i) { m_subPicCtuTopLeftX[i] = u; } void setSubPicCtuTopLeftY (uint32_t u, int i) { m_subPicCtuTopLeftY[i] = u; } void setSubPicWidth (uint32_t u, int i) { m_subPicWidth[i] = u; } void setSubPicHeight (uint32_t u, int i) { m_subPicHeight[i] = u; } void setSubPicTreatedAsPicFlag (bool b, int i) { m_subPicTreatedAsPicFlag[i] = b; } void setLoopFilterAcrossSubpicEnabledFlag (bool b, int i) { m_loopFilterAcrossSubpicEnabledFlag[i] = b; } - +#if JVET_S0071_SAME_SIZE_SUBPIC_LAYOUT + void setSubPicCtuTopLeftX (const std::vector<uint32_t> &v) { CHECK(v.size() != (m_subPicSameSizeFlag ? 0 : m_numSubPics), "number of vector entries must be equal to numSubPics(subPicSameSize=0) or 0(subPicSameSize=1)"); m_subPicCtuTopLeftX = v; } + void setSubPicCtuTopLeftY (const std::vector<uint32_t> &v) { CHECK(v.size() != (m_subPicSameSizeFlag ? 0 : m_numSubPics), "number of vector entries must be equal to numSubPics(subPicSameSize=0) or 0(subPicSameSize=1)"); m_subPicCtuTopLeftY = v; } + void setSubPicWidth (const std::vector<uint32_t> &v) { CHECK(v.size() != (m_subPicSameSizeFlag ? 1 : m_numSubPics), "number of vector entries must be equal to numSubPics(subPicSameSize=0) or 1(subPicSameSize=1)"); m_subPicWidth = v; } + void setSubPicHeight (const std::vector<uint32_t> &v) { CHECK(v.size() != (m_subPicSameSizeFlag ? 1 : m_numSubPics), "number of vector entries must be equal to numSubPics(subPicSameSize=0) or 1(subPicSameSize=1)"); m_subPicHeight = v; } +#else void setSubPicCtuTopLeftX (const std::vector<uint32_t> &v) { CHECK(v.size()!=m_numSubPics, "number of vector entries must be equal to numSubPics") ;m_subPicCtuTopLeftX = v; } void setSubPicCtuTopLeftY (const std::vector<uint32_t> &v) { CHECK(v.size()!=m_numSubPics, "number of vector entries must be equal to numSubPics") ;m_subPicCtuTopLeftY = v; } void setSubPicWidth (const std::vector<uint32_t> &v) { CHECK(v.size()!=m_numSubPics, "number of vector entries must be equal to numSubPics") ;m_subPicWidth = v; } void setSubPicHeight (const std::vector<uint32_t> &v) { CHECK(v.size()!=m_numSubPics, "number of vector entries must be equal to numSubPics") ;m_subPicHeight = v; } +#endif void setSubPicTreatedAsPicFlag (const std::vector<bool> &v) { CHECK(v.size()!=m_numSubPics, "number of vector entries must be equal to numSubPics") ;m_subPicTreatedAsPicFlag = v; } void setLoopFilterAcrossSubpicEnabledFlag (const std::vector<bool> &v) { CHECK(v.size()!=m_numSubPics, "number of vector entries must be equal to numSubPics") ;m_loopFilterAcrossSubpicEnabledFlag = v; } @@ -988,6 +1000,9 @@ public: void setSubPicId (const std::vector<uint16_t> &v) { CHECK(v.size()!=m_numSubPics, "number of vector entries must be equal to numSubPics"); m_subPicId = v; } bool getSubPicInfoPresentFlag () { return m_subPicInfoPresentFlag; } +#if JVET_S0071_SAME_SIZE_SUBPIC_LAYOUT + bool getSubPicSameSizeFlag () { return m_subPicSameSizeFlag; } +#endif uint32_t getNumSubPics () { return m_numSubPics; } uint32_t getSubPicCtuTopLeftX (int i) { return m_subPicCtuTopLeftX[i]; } uint32_t getSubPicCtuTopLeftY (int i) { return m_subPicCtuTopLeftY[i]; } diff --git a/source/Lib/EncoderLib/EncLib.cpp b/source/Lib/EncoderLib/EncLib.cpp index 9a51e592a..30d8c8f68 100644 --- a/source/Lib/EncoderLib/EncLib.cpp +++ b/source/Lib/EncoderLib/EncLib.cpp @@ -1371,10 +1371,32 @@ void EncLib::xInitSPS( SPS& sps ) if (m_subPicInfoPresentFlag) { sps.setNumSubPics(m_numSubPics); +#if JVET_S0071_SAME_SIZE_SUBPIC_LAYOUT + sps.setSubPicSameSizeFlag(m_subPicSameSizeFlag); + if (m_subPicSameSizeFlag) + { + uint32_t numSubpicCols = (m_iSourceWidth + m_CTUSize - 1) / m_CTUSize / m_subPicWidth[0]; + for (unsigned int i = 0; i < m_numSubPics; i++) + { + sps.setSubPicCtuTopLeftX(i, (i % numSubpicCols) * m_subPicWidth[0]); + sps.setSubPicCtuTopLeftY(i, (i / numSubpicCols) * m_subPicHeight[0]); + sps.setSubPicWidth(i, m_subPicWidth[0]); + sps.setSubPicHeight(i, m_subPicHeight[0]); + } + } + else + { + sps.setSubPicCtuTopLeftX(m_subPicCtuTopLeftX); + sps.setSubPicCtuTopLeftY(m_subPicCtuTopLeftY); + sps.setSubPicWidth(m_subPicWidth); + sps.setSubPicHeight(m_subPicHeight); + } +#else sps.setSubPicCtuTopLeftX(m_subPicCtuTopLeftX); sps.setSubPicCtuTopLeftY(m_subPicCtuTopLeftY); sps.setSubPicWidth(m_subPicWidth); sps.setSubPicHeight(m_subPicHeight); +#endif sps.setSubPicTreatedAsPicFlag(m_subPicTreatedAsPicFlag); sps.setLoopFilterAcrossSubpicEnabledFlag(m_loopFilterAcrossSubpicEnabledFlag); sps.setSubPicIdLen(m_subPicIdLen); diff --git a/source/Lib/EncoderLib/VLCWriter.cpp b/source/Lib/EncoderLib/VLCWriter.cpp index 88afee44d..aef52cff4 100644 --- a/source/Lib/EncoderLib/VLCWriter.cpp +++ b/source/Lib/EncoderLib/VLCWriter.cpp @@ -816,6 +816,37 @@ void HLSWriter::codeSPS( const SPS* pcSPS ) WRITE_UVLC(pcSPS->getNumSubPics() - 1, "sps_num_subpics_minus1"); if( pcSPS->getNumSubPics() > 1 ) { +#if JVET_S0071_SAME_SIZE_SUBPIC_LAYOUT + WRITE_FLAG(pcSPS->getIndependentSubPicsFlag(), "sps_independent_subpics_flag"); + WRITE_FLAG(pcSPS->getSubPicSameSizeFlag(), "sps_subpic_same_size_flag"); + for (int picIdx = 0; picIdx < pcSPS->getNumSubPics(); picIdx++) + { + if (!pcSPS->getSubPicSameSizeFlag() || picIdx == 0) + { + if ((picIdx > 0) && (pcSPS->getMaxPicWidthInLumaSamples() > pcSPS->getCTUSize())) + { + WRITE_CODE(pcSPS->getSubPicCtuTopLeftX(picIdx), ceilLog2((pcSPS->getMaxPicWidthInLumaSamples() + pcSPS->getCTUSize() - 1) / pcSPS->getCTUSize()), "subpic_ctu_top_left_x[ i ]"); + } + if ((picIdx > 0) && (pcSPS->getMaxPicHeightInLumaSamples() > pcSPS->getCTUSize())) + { + WRITE_CODE(pcSPS->getSubPicCtuTopLeftY(picIdx), ceilLog2((pcSPS->getMaxPicHeightInLumaSamples() + pcSPS->getCTUSize() - 1) / pcSPS->getCTUSize()), "subpic_ctu_top_left_y[ i ]"); + } + if (picIdx<pcSPS->getNumSubPics() - 1 && pcSPS->getMaxPicWidthInLumaSamples() > pcSPS->getCTUSize()) + { + WRITE_CODE(pcSPS->getSubPicWidth(picIdx) - 1, ceilLog2((pcSPS->getMaxPicWidthInLumaSamples() + pcSPS->getCTUSize() - 1) / pcSPS->getCTUSize()), "subpic_width_minus1[ i ]"); + } + if (picIdx<pcSPS->getNumSubPics() - 1 && pcSPS->getMaxPicHeightInLumaSamples() > pcSPS->getCTUSize()) + { + WRITE_CODE(pcSPS->getSubPicHeight(picIdx) - 1, ceilLog2((pcSPS->getMaxPicHeightInLumaSamples() + pcSPS->getCTUSize() - 1) / pcSPS->getCTUSize()), "subpic_height_minus1[ i ]"); + } + if (!pcSPS->getIndependentSubPicsFlag()) + { + WRITE_FLAG(pcSPS->getSubPicTreatedAsPicFlag(picIdx), "subpic_treated_as_pic_flag[ i ]"); + WRITE_FLAG(pcSPS->getLoopFilterAcrossSubpicEnabledFlag(picIdx), "loop_filter_across_subpic_enabled_flag[ i ]"); + } + } + } +#else WRITE_FLAG(pcSPS->getIndependentSubPicsFlag(), "sps_independent_subpics_flag"); for (int picIdx = 0; picIdx < pcSPS->getNumSubPics(); picIdx++) { @@ -841,6 +872,7 @@ void HLSWriter::codeSPS( const SPS* pcSPS ) WRITE_FLAG( pcSPS->getLoopFilterAcrossSubpicEnabledFlag(picIdx), "loop_filter_across_subpic_enabled_flag[ i ]" ); } } +#endif } CHECK(pcSPS->getSubPicIdLen() < 1, "SPS: SubPicIdLen cannot be less than 1"); -- GitLab