From 68f456222cbe25116995703d5f88eebc200acce6 Mon Sep 17 00:00:00 2001 From: Karsten Suehring <karsten.suehring@hhi.fraunhofer.de> Date: Wed, 15 Apr 2020 11:55:50 +0200 Subject: [PATCH] Refactor: convert static arrays into vectors - converts static arrays to vectors for subpicture related parameters - improved encoder parameter checking - mode automatic calculation of subpicture ID length at encoder - update theoretical limit of maximum number of subpictures --- doc/software-manual.tex | 1 + source/App/EncoderApp/EncApp.cpp | 36 ++++------- source/App/EncoderApp/EncAppCfg.cpp | 52 ++++++++++----- source/App/EncoderApp/EncAppCfg.h | 6 +- source/Lib/CommonLib/CommonDef.h | 2 +- source/Lib/CommonLib/Slice.cpp | 6 -- source/Lib/CommonLib/Slice.h | 99 ++++++++++++++++++----------- source/Lib/DecoderLib/VLCReader.cpp | 9 +-- source/Lib/EncoderLib/EncCfg.h | 37 ++++++++--- source/Lib/EncoderLib/EncLib.cpp | 29 +++------ source/Lib/EncoderLib/VLCWriter.cpp | 4 ++ 11 files changed, 156 insertions(+), 125 deletions(-) diff --git a/doc/software-manual.tex b/doc/software-manual.tex index 4a5521da6..1e948bbfe 100644 --- a/doc/software-manual.tex +++ b/doc/software-manual.tex @@ -2107,6 +2107,7 @@ Specifies wheter to signal the subpicture ID map in SPS or PPS. If SubPicIdMappi %\ShortOption{\None} & \Default{0} & Length of the subpicture IDs in bits. (1<<SubPicIdLen) must be bigger than the number of subpictures and the highes subpicture ID specifid in SubPicId. +If the value "0" is used, the encoder tries to determine the number of required bits from the number of subpictures or the highest subpicture ID. This mode should not be used, if merging of bistreams is intended. \\ \Option{SubPicId} & diff --git a/source/App/EncoderApp/EncApp.cpp b/source/App/EncoderApp/EncApp.cpp index 9af6405cb..80cf6c11d 100644 --- a/source/App/EncoderApp/EncApp.cpp +++ b/source/App/EncoderApp/EncApp.cpp @@ -425,38 +425,26 @@ void EncApp::xInitLibCfg() #endif { m_cEncLib.setNumSubPics ( m_numSubPics ); - for (int i = 0; i < m_numSubPics; i++) - { - m_cEncLib.setSubPicCtuTopLeftX ( m_subPicCtuTopLeftX[i], i ); - m_cEncLib.setSubPicCtuTopLeftY ( m_subPicCtuTopLeftY[i], i ); - m_cEncLib.setSubPicWidth ( m_subPicWidth[i], i ); - m_cEncLib.setSubPicHeight ( m_subPicHeight[i], i ); - m_cEncLib.setSubPicTreatedAsPicFlag ( m_subPicTreatedAsPicFlag[i], i ); - m_cEncLib.setLoopFilterAcrossSubpicEnabledFlag ( m_loopFilterAcrossSubpicEnabledFlag[i], i ); - } - } - -#if JVET_Q0119_CLEANUPS - m_cEncLib.setSubPicIdMappingExplicitlySignalledFlag ( m_subPicIdMappingExplicitlySignalledFlag ); - if (m_subPicIdMappingExplicitlySignalledFlag) - { + m_cEncLib.setSubPicCtuTopLeftX ( m_subPicCtuTopLeftX ); + m_cEncLib.setSubPicCtuTopLeftY ( m_subPicCtuTopLeftY ); + m_cEncLib.setSubPicWidth ( m_subPicWidth ); + m_cEncLib.setSubPicHeight ( m_subPicHeight ); + m_cEncLib.setSubPicTreatedAsPicFlag ( m_subPicTreatedAsPicFlag ); + m_cEncLib.setLoopFilterAcrossSubpicEnabledFlag ( m_loopFilterAcrossSubpicEnabledFlag ); m_cEncLib.setSubPicIdMappingInSpsFlag ( m_subPicIdMappingInSpsFlag ); - if(m_subPicIdMappingInSpsFlag) + m_cEncLib.setSubPicIdLen ( m_subPicIdLen ); +#if JVET_Q0119_CLEANUPS + m_cEncLib.setSubPicIdMappingExplicitlySignalledFlag ( m_subPicIdMappingExplicitlySignalledFlag ); + if (m_subPicIdMappingExplicitlySignalledFlag) #else - m_cEncLib.setSubPicIdPresentFlag ( m_subPicIdPresentFlag ); - if (m_subPicIdPresentFlag) - { m_cEncLib.setSubPicIdSignallingPresentFlag ( m_subPicIdSignallingPresentFlag ); if(m_subPicIdSignallingPresentFlag) #endif { - m_cEncLib.setSubPicIdLen ( m_subPicIdLen ); - for (int i = 0; i < m_numSubPics; i++) - { - m_cEncLib.setSubPicId ( m_subPicId[i], i ); - } + m_cEncLib.setSubPicId ( m_subPicId ); } } + m_cEncLib.setUseSplitConsOverride ( m_SplitConsOverrideEnabledFlag ); m_cEncLib.setMinQTSizes ( m_uiMinQT ); m_cEncLib.setMaxMTTHierarchyDepth ( m_uiMaxMTTHierarchyDepth, m_uiMaxMTTHierarchyDepthI, m_uiMaxMTTHierarchyDepthIChroma ); diff --git a/source/App/EncoderApp/EncAppCfg.cpp b/source/App/EncoderApp/EncAppCfg.cpp index 087269d5c..7470907d4 100644 --- a/source/App/EncoderApp/EncAppCfg.cpp +++ b/source/App/EncoderApp/EncAppCfg.cpp @@ -751,9 +751,9 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] ) SMultiValueInput<uint32_t> cfg_subPicCtuTopLeftY(0, std::numeric_limits<uint32_t>::max(), 0, MAX_NUM_SUB_PICS); SMultiValueInput<uint32_t> cfg_subPicWidth(1, std::numeric_limits<uint32_t>::max(), 0, MAX_NUM_SUB_PICS); SMultiValueInput<uint32_t> cfg_subPicHeight(1, std::numeric_limits<uint32_t>::max(), 0, MAX_NUM_SUB_PICS); - SMultiValueInput<uint32_t> cfg_subPicTreatedAsPicFlag(0, 1, 0, MAX_NUM_SUB_PICS); - SMultiValueInput<uint32_t> cfg_loopFilterAcrossSubpicEnabledFlag(0, 1, 0, MAX_NUM_SUB_PICS); - SMultiValueInput<uint32_t> cfg_subPicId(0, std::numeric_limits<uint32_t>::max(), 0, MAX_NUM_SUB_PICS); + SMultiValueInput<bool> cfg_subPicTreatedAsPicFlag(0, 1, 0, MAX_NUM_SUB_PICS); + SMultiValueInput<bool> cfg_loopFilterAcrossSubpicEnabledFlag(0, 1, 0, MAX_NUM_SUB_PICS); + SMultiValueInput<uint32_t> cfg_subPicId(0, std::numeric_limits<uint16_t>::max(), 0, MAX_NUM_SUB_PICS); #if JVET_SUBPIC_LEVEL_CFG SMultiValueInput<int> cfg_sliFractions(0, 100, 0, std::numeric_limits<int>::max()); @@ -1687,32 +1687,52 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] ) if ( m_subPicPresentFlag ) #endif { - CHECK( m_numSubPics > 255 || m_numSubPics < 1, "Number of subpicture must be within 1 to 255" ); + CHECK( m_numSubPics > MAX_NUM_SUB_PICS || m_numSubPics < 1, "Number of subpicture must be within 1 to 2^16" ); + 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"); + 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) + { + CHECK( cfg_subPicId.values.size() != m_numSubPics, "Number of SubPicId values must be equal to NumSubPics"); + } m_subPicCtuTopLeftX = cfg_subPicCtuTopLeftX.values; m_subPicCtuTopLeftY = cfg_subPicCtuTopLeftY.values; m_subPicWidth = cfg_subPicWidth.values; m_subPicHeight = cfg_subPicHeight.values; m_subPicTreatedAsPicFlag = cfg_subPicTreatedAsPicFlag.values; m_loopFilterAcrossSubpicEnabledFlag = cfg_loopFilterAcrossSubpicEnabledFlag.values; - m_subPicId = cfg_subPicId.values; - for(int i = 0; i < m_numSubPics; i++) + if (m_subPicIdMappingExplicitlySignalledFlag) { - 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"); + for (int i=0; i < m_numSubPics; i++) + { + m_subPicId[i] = cfg_subPicId.values[i]; + } } -#if JVET_Q0119_CLEANUPS - if (m_subPicIdMappingExplicitlySignalledFlag) + for(int i = 0; i < m_numSubPics; i++) { - if (m_subPicIdMappingInSpsFlag) -#else - if (m_subPicIdPresentFlag) + 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"); + } + // automatically determine subpicture ID lenght in case it is not specified + if (m_subPicIdLen == 0) { - if (m_subPicIdSignallingPresentFlag) -#endif + if (m_subPicIdMappingExplicitlySignalledFlag) { - CHECK( m_subPicIdLen > 16, "sibpic ID length must not exceed 16 bits" ); + // use the heighest specified ID + auto maxIdVal = std::max_element(m_subPicId.begin(),m_subPicId.end()); + m_subPicIdLen = ceilLog2(*maxIdVal); + } + else + { + // use the number of subpictures + m_subPicIdLen = ceilLog2(m_numSubPics); } } + + CHECK( m_subPicIdLen > 16, "SubPicIdLen must not exceed 16 bits" ); #if JVET_Q0043_RPR_and_Subpics CHECK( m_rprEnabled, "RPR and subpictures cannot be enabled together" ); #endif diff --git a/source/App/EncoderApp/EncAppCfg.h b/source/App/EncoderApp/EncAppCfg.h index 197ebafd8..0a82b669b 100644 --- a/source/App/EncoderApp/EncAppCfg.h +++ b/source/App/EncoderApp/EncAppCfg.h @@ -295,8 +295,8 @@ protected: std::vector<uint32_t> m_subPicCtuTopLeftY; std::vector<uint32_t> m_subPicWidth; std::vector<uint32_t> m_subPicHeight; - std::vector<uint32_t> m_subPicTreatedAsPicFlag; - std::vector<uint32_t> m_loopFilterAcrossSubpicEnabledFlag; + std::vector<bool> m_subPicTreatedAsPicFlag; + std::vector<bool> m_loopFilterAcrossSubpicEnabledFlag; #if JVET_Q0119_CLEANUPS bool m_subPicIdMappingExplicitlySignalledFlag; bool m_subPicIdMappingInSpsFlag; @@ -305,7 +305,7 @@ protected: bool m_subPicIdSignallingPresentFlag; #endif unsigned m_subPicIdLen; - std::vector<uint32_t> m_subPicId; + std::vector<uint16_t> m_subPicId; bool m_SplitConsOverrideEnabledFlag; unsigned m_uiMinQT[3]; // 0: I slice luma; 1: P/B slice; 2: I slice chroma unsigned m_uiMaxMTTHierarchyDepth; diff --git a/source/Lib/CommonLib/CommonDef.h b/source/Lib/CommonLib/CommonDef.h index 13997bbf0..834705078 100644 --- a/source/Lib/CommonLib/CommonDef.h +++ b/source/Lib/CommonLib/CommonDef.h @@ -287,7 +287,7 @@ static const int LUMA_INTERPOLATION_FILTER_SUB_SAMPLE_POSITIONS_SIGNAL = 1 << MV static const int LUMA_INTERPOLATION_FILTER_SUB_SAMPLE_POSITIONS = 1 << MV_FRACTIONAL_BITS_INTERNAL; static const int CHROMA_INTERPOLATION_FILTER_SUB_SAMPLE_POSITIONS = 1 << (MV_FRACTIONAL_BITS_INTERNAL + 1); -static const int MAX_NUM_SUB_PICS = 255; +static const int MAX_NUM_SUB_PICS = (1 << 16); static const int MAX_NUM_LONG_TERM_REF_PICS = 33; static const int NUM_LONG_TERM_REF_PIC_SPS = 0; diff --git a/source/Lib/CommonLib/Slice.cpp b/source/Lib/CommonLib/Slice.cpp index 8b4e46e7d..7ab3aabff 100644 --- a/source/Lib/CommonLib/Slice.cpp +++ b/source/Lib/CommonLib/Slice.cpp @@ -2774,12 +2774,6 @@ SPS::SPS() #if JVET_Q0179_SCALING_WINDOW_SIZE_CONSTRAINT ::memset(m_ppsValidFlag, 0, sizeof(m_ppsValidFlag)); #endif - ::memset(m_subPicCtuTopLeftX, 0, sizeof(m_subPicCtuTopLeftX)); - ::memset(m_subPicCtuTopLeftY, 0, sizeof(m_subPicCtuTopLeftY)); - ::memset(m_SubPicWidth, 0, sizeof(m_SubPicWidth)); - ::memset(m_SubPicHeight, 0, sizeof(m_SubPicHeight)); - ::memset(m_subPicTreatedAsPicFlag, 0, sizeof(m_subPicTreatedAsPicFlag)); - ::memset(m_loopFilterAcrossSubpicEnabledFlag, 0, sizeof(m_loopFilterAcrossSubpicEnabledFlag)); } SPS::~SPS() diff --git a/source/Lib/CommonLib/Slice.h b/source/Lib/CommonLib/Slice.h index 24cd03419..6254ec6d9 100644 --- a/source/Lib/CommonLib/Slice.h +++ b/source/Lib/CommonLib/Slice.h @@ -1337,13 +1337,13 @@ private: #else bool m_subPicPresentFlag; // indicates the presence of sub-pictures #endif - uint8_t m_numSubPics; //!< number of sub-pictures used - uint32_t m_subPicCtuTopLeftX[MAX_NUM_SUB_PICS]; - uint32_t m_subPicCtuTopLeftY[MAX_NUM_SUB_PICS]; - uint32_t m_SubPicWidth[MAX_NUM_SUB_PICS]; - uint32_t m_SubPicHeight[MAX_NUM_SUB_PICS]; - bool m_subPicTreatedAsPicFlag[MAX_NUM_SUB_PICS]; - bool m_loopFilterAcrossSubpicEnabledFlag[MAX_NUM_SUB_PICS]; + uint32_t m_numSubPics; //!< number of sub-pictures used + std::vector<uint32_t> m_subPicCtuTopLeftX; + std::vector<uint32_t> m_subPicCtuTopLeftY; + std::vector<uint32_t> m_subPicWidth; + std::vector<uint32_t> m_subPicHeight; + std::vector<bool> m_subPicTreatedAsPicFlag; + std::vector<bool> m_loopFilterAcrossSubpicEnabledFlag; #if JVET_Q0119_CLEANUPS bool m_subPicIdMappingExplicitlySignalledFlag; bool m_subPicIdMappingInSpsFlag; @@ -1352,7 +1352,7 @@ private: bool m_subPicIdSignallingPresentFlag; //!< indicates the presence of sub-picture ID signalling in the SPS #endif uint32_t m_subPicIdLen; //!< sub-picture ID length in bits - uint16_t m_subPicId[MAX_NUM_SUB_PICS]; //!< sub-picture ID for each sub-picture in the sequence + std::vector<uint16_t> m_subPicId; //!< sub-picture ID for each sub-picture in the sequence int m_log2MinCodingBlockSize; #if !JVET_Q0468_Q0469_MIN_LUMA_CB_AND_MIN_QT_FIX @@ -1571,27 +1571,45 @@ public: #endif #if JVET_Q0119_CLEANUPS - void setSubPicInfoPresentFlag(bool b) { m_subPicInfoPresentFlag = b; } - bool getSubPicInfoPresentFlag() const { return m_subPicInfoPresentFlag; } + void setSubPicInfoPresentFlag(bool b) { m_subPicInfoPresentFlag = b; } + bool getSubPicInfoPresentFlag() const { return m_subPicInfoPresentFlag; } #else - void setSubPicPresentFlag(bool b) { m_subPicPresentFlag = b; } - bool getSubPicPresentFlag() const { return m_subPicPresentFlag; } -#endif - - void setNumSubPics( uint8_t u ) { m_numSubPics = u; } - uint8_t getNumSubPics( ) const { return m_numSubPics; } - void setSubPicCtuTopLeftX( int i, uint32_t u ) { CHECK( i >= MAX_NUM_SUB_PICS, "Sub-picture index exceeds valid range" ); m_subPicCtuTopLeftX[i] = u; } - uint32_t getSubPicCtuTopLeftX( int i ) const { CHECK( i >= MAX_NUM_SUB_PICS, "Sub-picture index exceeds valid range" ); return m_subPicCtuTopLeftX[i]; } - void setSubPicCtuTopLeftY( int i, uint32_t u ) { CHECK( i >= MAX_NUM_SUB_PICS, "Sub-picture index exceeds valid range" ); m_subPicCtuTopLeftY[i] = u; } - uint32_t getSubPicCtuTopLeftY( int i ) const { CHECK( i >= MAX_NUM_SUB_PICS, "Sub-picture index exceeds valid range" ); return m_subPicCtuTopLeftY[i]; } - void setSubPicWidth( int i, uint32_t u ) { CHECK( i >= MAX_NUM_SUB_PICS, "Sub-picture index exceeds valid range" ); m_SubPicWidth[i] = u; } - uint32_t getSubPicWidth( int i ) const { CHECK( i >= MAX_NUM_SUB_PICS, "Sub-picture index exceeds valid range" ); return m_SubPicWidth[i]; } - void setSubPicHeight( int i, uint32_t u ) { CHECK( i >= MAX_NUM_SUB_PICS, "Sub-picture index exceeds valid range" ); m_SubPicHeight[i] = u; } - uint32_t getSubPicHeight( int i ) const { CHECK( i >= MAX_NUM_SUB_PICS, "Sub-picture index exceeds valid range" ); return m_SubPicHeight[i]; } - void setSubPicTreatedAsPicFlag( int i, bool u ) { CHECK( i >= MAX_NUM_SUB_PICS, "Sub-picture index exceeds valid range" ); m_subPicTreatedAsPicFlag[i] = u; } - bool getSubPicTreatedAsPicFlag( int i ) const { CHECK( i >= MAX_NUM_SUB_PICS, "Sub-picture index exceeds valid range" ); return m_subPicTreatedAsPicFlag[i]; } - void setLoopFilterAcrossSubpicEnabledFlag( int i, bool u ) { CHECK( i >= MAX_NUM_SUB_PICS, "Sub-picture index exceeds valid range" ); m_loopFilterAcrossSubpicEnabledFlag[i] = u; } - bool getLoopFilterAcrossSubpicEnabledFlag( int i ) const { CHECK( i >= MAX_NUM_SUB_PICS, "Sub-picture index exceeds valid range" ); return m_loopFilterAcrossSubpicEnabledFlag[i]; } + void setSubPicPresentFlag(bool b) { m_subPicPresentFlag = b; } + bool getSubPicPresentFlag() const { return m_subPicPresentFlag; } +#endif + + void setNumSubPics( uint32_t u ) { CHECK( u >= MAX_NUM_SUB_PICS, "Maximum number of subpictures exceeded" ); + m_numSubPics = u; + m_subPicCtuTopLeftX.resize(m_numSubPics); + m_subPicCtuTopLeftY.resize(m_numSubPics); + m_subPicWidth.resize(m_numSubPics); + m_subPicHeight.resize(m_numSubPics); + m_subPicTreatedAsPicFlag.resize(m_numSubPics); + m_loopFilterAcrossSubpicEnabledFlag.resize(m_numSubPics); + m_subPicId.resize(m_numSubPics); + } + 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]; } + void setSubPicCtuTopLeftY( int i, uint32_t u ) { m_subPicCtuTopLeftY[i] = u; } + uint32_t getSubPicCtuTopLeftY( int i ) const { return m_subPicCtuTopLeftY[i]; } + void setSubPicWidth( int i, uint32_t u ) { m_subPicWidth[i] = u; } + uint32_t getSubPicWidth( int i ) const { return m_subPicWidth[i]; } + void setSubPicHeight( int i, uint32_t u ) { m_subPicHeight[i] = u; } + uint32_t getSubPicHeight( int i ) const { return m_subPicHeight[i]; } + void setSubPicTreatedAsPicFlag( int i, bool u ) { m_subPicTreatedAsPicFlag[i] = u; } + bool getSubPicTreatedAsPicFlag( int i ) const { return m_subPicTreatedAsPicFlag[i]; } + void setLoopFilterAcrossSubpicEnabledFlag( int i, bool u ) { m_loopFilterAcrossSubpicEnabledFlag[i] = u; } + bool getLoopFilterAcrossSubpicEnabledFlag( int i ) const { return m_loopFilterAcrossSubpicEnabledFlag[i]; } + + 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; } + 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; } + + #if JVET_Q0119_CLEANUPS void setSubPicIdMappingExplicitlySignalledFlag( bool b ) { m_subPicIdMappingExplicitlySignalledFlag = b; } bool getSubPicIdMappingExplicitlySignalledFlag() const { return m_subPicIdMappingExplicitlySignalledFlag; } @@ -1605,8 +1623,9 @@ public: #endif void setSubPicIdLen( uint32_t u ) { m_subPicIdLen = u; } uint32_t getSubPicIdLen() const { return m_subPicIdLen; } - void setSubPicId( int i, uint16_t u ) { CHECK( i >= MAX_NUM_SUB_PICS, "Sub-picture index exceeds valid range" ); m_subPicId[i] = u; } - uint16_t getSubPicId( int i ) const { CHECK( i >= MAX_NUM_SUB_PICS, "Sub-picture index exceeds valid range" ); return m_subPicId[i]; } + void setSubPicId( int i, uint16_t u ) { m_subPicId[i] = u; } + uint16_t getSubPicId( int i ) const { return m_subPicId[i]; } + 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; } uint32_t getNumLongTermRefPicSPS() const { return m_numLongTermRefPicSPS; } void setNumLongTermRefPicSPS(uint32_t val) { m_numLongTermRefPicSPS = val; } @@ -2038,14 +2057,14 @@ private: bool m_bUseWeightPred; //!< Use of Weighting Prediction (P_SLICE) bool m_useWeightedBiPred; //!< Use of Weighting Bi-Prediction (B_SLICE) bool m_OutputFlagPresentFlag; //!< Indicates the presence of output_flag in slice header - uint8_t m_numSubPics; //!< number of sub-pictures used - must match SPS + uint32_t m_numSubPics; //!< number of sub-pictures used - must match SPS #if JVET_Q0119_CLEANUPS bool m_subPicIdMappingInPpsFlag; #else bool m_subPicIdSignallingPresentFlag; //!< indicates the presence of sub-picture ID signalling in the PPS #endif uint32_t m_subPicIdLen; //!< sub-picture ID length in bits - uint16_t m_subPicId[MAX_NUM_SUB_PICS]; //!< sub-picture ID for each sub-picture in the sequence + std::vector<uint16_t> m_subPicId; //!< sub-picture ID for each sub-picture in the sequence bool m_noPicPartitionFlag; //!< no picture partitioning flag - single slice, single tile uint8_t m_log2CtuSize; //!< log2 of the CTU size - required to match corresponding value in SPS uint8_t m_ctuSize; //!< CTU size @@ -2223,8 +2242,11 @@ public: void setOutputFlagPresentFlag( bool b ) { m_OutputFlagPresentFlag = b; } bool getOutputFlagPresentFlag() const { return m_OutputFlagPresentFlag; } - void setNumSubPics( uint8_t u ) { m_numSubPics = u; } - uint8_t getNumSubPics( ) const { return m_numSubPics; } + void setNumSubPics(uint32_t u ) { CHECK( u >= MAX_NUM_SUB_PICS, "Maximum number of subpictures exceeded" ); + m_numSubPics = u; + m_subPicId.resize(m_numSubPics); + } + uint32_t getNumSubPics( ) const { return m_numSubPics; } #if JVET_Q0119_CLEANUPS void setSubPicIdMappingInPpsFlag( bool b ) { m_subPicIdMappingInPpsFlag = b; } bool getSubPicIdMappingInPpsFlag() const { return m_subPicIdMappingInPpsFlag; } @@ -2234,8 +2256,9 @@ public: #endif void setSubPicIdLen( uint32_t u ) { m_subPicIdLen = u; } uint32_t getSubPicIdLen() const { return m_subPicIdLen; } - void setSubPicId( int i, uint16_t u ) { CHECK( i >= MAX_NUM_SUB_PICS, "Sub-picture index exceeds valid range" ); m_subPicId[i] = u; } - uint16_t getSubPicId( int i ) const { CHECK( i >= MAX_NUM_SUB_PICS, "Sub-picture index exceeds valid range" ); return m_subPicId[i]; } + void setSubPicId( int i, uint16_t u ) { m_subPicId[i] = u; } + 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; } + uint16_t getSubPicId( int i ) const { return m_subPicId[i]; } #if JVET_Q0044_SLICE_IDX_WITH_SUBPICS uint32_t getSubPicIdxFromSubPicId( uint32_t subPicId ) const; #endif @@ -2668,8 +2691,8 @@ public: bool getSubPicIdSignallingPresentFlag() const { return m_subPicIdSignallingPresentFlag; } void setSubPicIdLen( uint32_t u ) { m_subPicIdLen = u; } uint32_t getSubPicIdLen() const { return m_subPicIdLen; } - void setSubPicId( int i, uint16_t u ) { CHECK( i >= MAX_NUM_SUB_PICS, "Sub-pic index exceeds valid range" ); m_subPicId[i] = u; } - uint16_t getSubPicId( int i ) const { CHECK( i >= MAX_NUM_SUB_PICS, "Sub-pic index exceeds valid range" ); return m_subPicId[i]; } + void setSubPicId( int i, uint16_t u ) { m_subPicId[i] = u; } + uint16_t getSubPicId( int i ) const { return m_subPicId[i]; } #endif #if JVET_Q0246_VIRTUAL_BOUNDARY_ENABLE_FLAG void setVirtualBoundariesPresentFlag( bool b ) { m_virtualBoundariesPresentFlag = b; } diff --git a/source/Lib/DecoderLib/VLCReader.cpp b/source/Lib/DecoderLib/VLCReader.cpp index 519c336b6..12fb500dc 100644 --- a/source/Lib/DecoderLib/VLCReader.cpp +++ b/source/Lib/DecoderLib/VLCReader.cpp @@ -497,13 +497,6 @@ void HLSyntaxReader::parsePPS( PPS* pcPPS ) READ_CODE( pcPPS->getSubPicIdLen( ), uiCode, "pps_subpic_id[i]" ); pcPPS->setSubPicId( picIdx, uiCode ); } } - else - { - for( int picIdx = 0; picIdx < MAX_NUM_SUB_PICS; picIdx++ ) - { - pcPPS->setSubPicId( picIdx, picIdx ); - } - } READ_FLAG( uiCode, "no_pic_partition_flag" ); pcPPS->setNoPicPartitionFlag( uiCode == 1 ); if(!pcPPS->getNoPicPartitionFlag()) @@ -1775,7 +1768,7 @@ void HLSyntaxReader::parseSPS(SPS* pcSPS) #if JVET_Q0119_CLEANUPS READ_UVLC( uiCode, "sps_subpic_id_len_minus1" ); pcSPS->setSubPicIdLen( uiCode + 1 ); CHECK( uiCode > 15, "Invalid sps_subpic_id_len_minus1 value" ); - CHECK( (1 << (uiCode + 1)) < pcSPS->getNumSubPics() + 1, "Invalid sps_subpic_id_len_minus1 value" ); + CHECK( (1 << (uiCode + 1)) < pcSPS->getNumSubPics(), "Invalid sps_subpic_id_len_minus1 value" ); READ_FLAG( uiCode, "subpic_id_mapping_explicitly_signalled_flag" ); pcSPS->setSubPicIdMappingExplicitlySignalledFlag( uiCode != 0 ); if (pcSPS->getSubPicIdMappingExplicitlySignalledFlag()) { diff --git a/source/Lib/EncoderLib/EncCfg.h b/source/Lib/EncoderLib/EncCfg.h index d8969e265..f06b1c0eb 100644 --- a/source/Lib/EncoderLib/EncCfg.h +++ b/source/Lib/EncoderLib/EncCfg.h @@ -280,13 +280,13 @@ protected: #else bool m_subPicPresentFlag; #endif - unsigned m_numSubPics; - uint32_t m_subPicCtuTopLeftX[MAX_NUM_SUB_PICS]; - uint32_t m_subPicCtuTopLeftY[MAX_NUM_SUB_PICS]; - uint32_t m_subPicWidth[MAX_NUM_SUB_PICS]; - uint32_t m_subPicHeight[MAX_NUM_SUB_PICS]; - uint32_t m_subPicTreatedAsPicFlag[MAX_NUM_SUB_PICS]; - uint32_t m_loopFilterAcrossSubpicEnabledFlag[MAX_NUM_SUB_PICS]; + uint32_t m_numSubPics; + std::vector<uint32_t> m_subPicCtuTopLeftX; + std::vector<uint32_t> m_subPicCtuTopLeftY; + std::vector<uint32_t> m_subPicWidth; + std::vector<uint32_t> m_subPicHeight; + std::vector<bool> m_subPicTreatedAsPicFlag; + std::vector<bool> m_loopFilterAcrossSubpicEnabledFlag; #if JVET_Q0119_CLEANUPS bool m_subPicIdMappingExplicitlySignalledFlag; bool m_subPicIdMappingInSpsFlag; @@ -295,7 +295,7 @@ protected: bool m_subPicIdSignallingPresentFlag; #endif unsigned m_subPicIdLen; - uint32_t m_subPicId[MAX_NUM_SUB_PICS]; + std::vector<uint16_t> m_subPicId; bool m_useSplitConsOverride; unsigned m_uiMinQT[3]; //0: I slice; 1: P/B slice, 2: I slice chroma #if JVET_Q0330_BLOCK_PARTITION @@ -1006,13 +1006,29 @@ public: #else void setSubPicPresentFlag (bool b) { m_subPicPresentFlag = b; } #endif - void setNumSubPics (uint32_t u) { m_numSubPics = u; } + void setNumSubPics ( uint32_t u ) { CHECK( u >= MAX_NUM_SUB_PICS, "Maximum number of subpictures exceeded" ); + m_numSubPics = u; + m_subPicCtuTopLeftX.resize(m_numSubPics); + m_subPicCtuTopLeftY.resize(m_numSubPics); + m_subPicWidth.resize(m_numSubPics); + m_subPicHeight.resize(m_numSubPics); + m_subPicTreatedAsPicFlag.resize(m_numSubPics); + m_loopFilterAcrossSubpicEnabledFlag.resize(m_numSubPics); + m_subPicId.resize(m_numSubPics); + } 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 (uint32_t u, int i) { m_loopFilterAcrossSubpicEnabledFlag[i] = u; } + void setLoopFilterAcrossSubpicEnabledFlag (bool b, int i) { m_loopFilterAcrossSubpicEnabledFlag[i] = b; } + + 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; } + 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; } #if JVET_Q0119_CLEANUPS void setSubPicIdMappingExplicitlySignalledFlag (bool b) { m_subPicIdMappingExplicitlySignalledFlag = b; } @@ -1023,6 +1039,7 @@ public: #endif void setSubPicIdLen (uint32_t u) { m_subPicIdLen = u; } void setSubPicId (uint32_t b, int i) { m_subPicId[i] = b; } + 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; } #if JVET_Q0119_CLEANUPS bool getSubPicInfoPresentFlag () { return m_subPicInfoPresentFlag; } diff --git a/source/Lib/EncoderLib/EncLib.cpp b/source/Lib/EncoderLib/EncLib.cpp index e5c753713..f6585d391 100644 --- a/source/Lib/EncoderLib/EncLib.cpp +++ b/source/Lib/EncoderLib/EncLib.cpp @@ -1532,15 +1532,13 @@ void EncLib::xInitSPS( SPS& sps, VPS& vps ) #endif { sps.setNumSubPics(m_numSubPics); - for (int i = 0; i < m_numSubPics; i++) - { - sps.setSubPicCtuTopLeftX(i, m_subPicCtuTopLeftX[i] ); - sps.setSubPicCtuTopLeftY(i, m_subPicCtuTopLeftY[i]); - sps.setSubPicWidth(i, m_subPicWidth[i]); - sps.setSubPicHeight(i, m_subPicHeight[i]); - sps.setSubPicTreatedAsPicFlag(i, m_subPicTreatedAsPicFlag[i]); - sps.setLoopFilterAcrossSubpicEnabledFlag(i, m_loopFilterAcrossSubpicEnabledFlag[i]); - } + sps.setSubPicCtuTopLeftX(m_subPicCtuTopLeftX); + sps.setSubPicCtuTopLeftY(m_subPicCtuTopLeftY); + sps.setSubPicWidth(m_subPicWidth); + sps.setSubPicHeight(m_subPicHeight); + sps.setSubPicTreatedAsPicFlag(m_subPicTreatedAsPicFlag); + sps.setLoopFilterAcrossSubpicEnabledFlag(m_loopFilterAcrossSubpicEnabledFlag); + sps.setSubPicIdLen(m_subPicIdLen); } #if JVET_Q0044_SLICE_IDX_WITH_SUBPICS else //In that case, there is only one subpicture that contains the whole picture @@ -1552,6 +1550,7 @@ void EncLib::xInitSPS( SPS& sps, VPS& vps ) sps.setSubPicHeight(0, m_iSourceHeight); sps.setSubPicTreatedAsPicFlag(0, 1); sps.setLoopFilterAcrossSubpicEnabledFlag(0, 0); + sps.setSubPicIdLen(0); } #endif #if JVET_Q0119_CLEANUPS @@ -1561,11 +1560,7 @@ void EncLib::xInitSPS( SPS& sps, VPS& vps ) sps.setSubPicIdMappingInSpsFlag(m_subPicIdMappingInSpsFlag); if (m_subPicIdMappingInSpsFlag) { - sps.setSubPicIdLen(m_subPicIdLen); - for (int i = 0; i < m_numSubPics; i++) - { - sps.setSubPicId(i, m_subPicId[i]); - } + sps.setSubPicId(m_subPicId); } } #else @@ -1575,11 +1570,7 @@ void EncLib::xInitSPS( SPS& sps, VPS& vps ) sps.setSubPicIdSignallingPresentFlag(m_subPicIdSignallingPresentFlag); if (m_subPicIdSignallingPresentFlag) { - sps.setSubPicIdLen(m_subPicIdLen); - for (int i = 0; i < m_numSubPics; i++) - { - sps.setSubPicId(i, m_subPicId[i]); - } + sps.setSubPicId(m_subPicId); } } #endif diff --git a/source/Lib/EncoderLib/VLCWriter.cpp b/source/Lib/EncoderLib/VLCWriter.cpp index 303455d53..48108efb1 100644 --- a/source/Lib/EncoderLib/VLCWriter.cpp +++ b/source/Lib/EncoderLib/VLCWriter.cpp @@ -303,8 +303,10 @@ void HLSWriter::codePPS( const PPS* pcPPS ) if( pcPPS->getSubPicIdSignallingPresentFlag() ) #endif { + CHECK(pcPPS->getNumSubPics() < 1, "PPS: NumSubPics cannot be less than 1"); WRITE_UVLC( pcPPS->getNumSubPics() - 1, "pps_num_subpics_minus1" ); + CHECK(pcPPS->getSubPicIdLen() < 1, "PPS: SubPicIdLen cannot be less than 1"); WRITE_UVLC( pcPPS->getSubPicIdLen() - 1, "pps_subpic_id_len_minus1" ); #if JVET_Q0169_SUBPIC_LEN_CONFORM @@ -1079,6 +1081,7 @@ void HLSWriter::codeSPS( const SPS* pcSPS ) if(pcSPS->getSubPicPresentFlag()) #endif { + CHECK(pcSPS->getNumSubPics() < 1, "SPS: NumSubPics cannot be less than 1"); #if JVET_Q0119_CLEANUPS WRITE_UVLC(pcSPS->getNumSubPics() - 1, "sps_num_subpics_minus1"); #else @@ -1144,6 +1147,7 @@ void HLSWriter::codeSPS( const SPS* pcSPS ) #endif #if JVET_Q0119_CLEANUPS + CHECK(pcSPS->getSubPicIdLen() < 1, "SPS: SubPicIdLen cannot be less than 1"); WRITE_UVLC(pcSPS->getSubPicIdLen() - 1, "sps_subpic_id_len_minus1"); WRITE_FLAG(pcSPS->getSubPicIdMappingExplicitlySignalledFlag(), "subpic_id_mapping_explicitly_signalled_flag"); if (pcSPS->getSubPicIdMappingExplicitlySignalledFlag()) -- GitLab