diff --git a/cfg/layers.cfg b/cfg/layers.cfg new file mode 100644 index 0000000000000000000000000000000000000000..f083583f89767ae10f384c6dab19ebcc4dc2e28a --- /dev/null +++ b/cfg/layers.cfg @@ -0,0 +1,19 @@ +#======== Layers =============== +MaxLayers : 2 +MaxSublayers : 1 +AllLayersSameNumSublayersFlag : 0 +AllIndependentLayersFlag : 0 +#======== OLSs =============== +EachLayerIsAnOlsFlag : 0 +OlsModeIdc : 2 +NumOutputLayerSets : 2 +OlsOutputLayer1 : 1 0 +#======== Layer-0 =============== +LayerId0 : 0 +#======== Layer-1 =============== +LayerId1 : 1 +NumRefLayers1 : 1 +RefLayerIdx1 : 0 + + + diff --git a/doc/software-manual.tex b/doc/software-manual.tex index f30cf26d0b4c2cc9d661e629e1d365b605a065cb..afc037028aca334dc91cba04bb633de3fef8bd0d 100755 --- a/doc/software-manual.tex +++ b/doc/software-manual.tex @@ -1788,7 +1788,18 @@ be encoded or decoded using one or more cores. \end{OptionTableNoShorthand} +%% +%% Slice/Sub-Picture coding parameters +%% +\begin{OptionTableNoShorthand}{Slice and Sub-Picture coding parameters}{tab:subpicture-coding} +\Option{EnableSubPicPartitioning} & +%\ShortOption{\None} & +\Default{1} & +Enable Sub Picture partitioning (0: single slice per sub-picture, 1: multiple slices per sub-picture can be used). +\\ + +\end{OptionTableNoShorthand} %% %% In-loop filtering parameters diff --git a/source/App/DecoderApp/DecApp.cpp b/source/App/DecoderApp/DecApp.cpp index c76e14ab78af6c738c9556e3c545a5bf89432d84..a0717b2fe9e77803b1e679c515b620e0e9f6c1bb 100644 --- a/source/App/DecoderApp/DecApp.cpp +++ b/source/App/DecoderApp/DecApp.cpp @@ -116,6 +116,10 @@ uint32_t DecApp::decode() #endif bool loopFiltered = false; +#if JVET_P1019_OUTPUT_LAYER_SET + bool bPicSkipped = false; +#endif + while (!!bitstreamFile) { #if JVET_P1006_PICTURE_HEADER @@ -150,14 +154,48 @@ uint32_t DecApp::decode() (nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_IDR_W_RADL || nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_IDR_N_LP)) { +#if JVET_N0278_FIXES + xFlushOutput(pcListPic, nalu.m_nuhLayerId); +#else xFlushOutput(pcListPic); +#endif } // parse NAL unit syntax if within target decoding layer +#if JVET_P1019_OUTPUT_LAYER_SET + if ((m_iMaxTemporalLayer < 0 || nalu.m_temporalId <= m_iMaxTemporalLayer) && isNaluWithinTargetDecLayerIdSet(&nalu)) +#else if ((m_iMaxTemporalLayer < 0 || nalu.m_temporalId <= m_iMaxTemporalLayer) && isNaluWithinTargetDecLayerIdSet(&nalu) && isNaluTheTargetLayer(&nalu)) +#endif { +#if JVET_P1019_OUTPUT_LAYER_SET + if (bPicSkipped) + { + if ((nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_TRAIL) || (nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_STSA) || (nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_RASL) || (nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_RADL) || (nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_IDR_W_RADL) || (nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_IDR_N_LP) || (nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_CRA) || (nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_GDR)) + { + if (m_cDecLib.isSliceNaluFirstInAU(true, nalu)) + { + m_cDecLib.resetAccessUnitNals(); + m_cDecLib.resetAccessUnitApsNals(); + } + bPicSkipped = false; + } + } +#endif m_cDecLib.decode(nalu, m_iSkipFrame, m_iPOCLastDisplay); +#if JVET_P1019_OUTPUT_LAYER_SET + if (nalu.m_nalUnitType == NAL_UNIT_VPS) + { + deriveOutputLayerSet(); + } +#endif } +#if JVET_P1019_OUTPUT_LAYER_SET + else + { + bPicSkipped = true; + } +#endif } } #else @@ -212,7 +250,11 @@ uint32_t DecApp::decode() #endif } +#if JVET_P1019_OUTPUT_LAYER_SET + if ((m_iMaxTemporalLayer >= 0 && nalu.m_temporalId > m_iMaxTemporalLayer) || !isNaluWithinTargetDecLayerIdSet(&nalu)) +#else if ((m_iMaxTemporalLayer >= 0 && nalu.m_temporalId > m_iMaxTemporalLayer) || !isNaluWithinTargetDecLayerIdSet(&nalu) || !isNaluTheTargetLayer(&nalu)) +#endif { bNewPicture = false; } @@ -248,7 +290,11 @@ uint32_t DecApp::decode() #endif - if( ( bNewPicture || !bitstreamFile || nalu.m_nalUnitType == NAL_UNIT_EOS ) && !m_cDecLib.getFirstSliceInSequence() ) +#if JVET_P1019_OUTPUT_LAYER_SET + if ((bNewPicture || !bitstreamFile || nalu.m_nalUnitType == NAL_UNIT_EOS) && !m_cDecLib.getFirstSliceInSequence() && !bPicSkipped) +#else + if ((bNewPicture || !bitstreamFile || nalu.m_nalUnitType == NAL_UNIT_EOS) && !m_cDecLib.getFirstSliceInSequence()) +#endif { if (!loopFiltered || bitstreamFile) { @@ -297,7 +343,11 @@ uint32_t DecApp::decode() #if JVET_N0278_FIXES std::string reconFileName = m_reconFileName; - if( m_reconFileName.compare( "/dev/null" ) && (m_cDecLib.getVPS() != nullptr) && (m_cDecLib.getVPS()->getMaxLayers() > 1) && (m_iTargetLayer == -1) ) +#if JVET_P1019_OUTPUT_LAYER_SET + if (m_reconFileName.compare("/dev/null") && (m_cDecLib.getVPS() != nullptr) && (m_cDecLib.getVPS()->getMaxLayers() > 1) && (isNaluWithinTargetOutputLayerIdSet(&nalu))) +#else + if (m_reconFileName.compare("/dev/null") && (m_cDecLib.getVPS() != nullptr) && (m_cDecLib.getVPS()->getMaxLayers() > 1) && (m_iTargetLayer == -1)) +#endif { size_t pos = reconFileName.find_last_of('.'); if (pos != string::npos) @@ -309,7 +359,10 @@ uint32_t DecApp::decode() reconFileName.append( std::to_string( nalu.m_nuhLayerId ) ); } } - m_cVideoIOYuvReconFile[nalu.m_nuhLayerId].open( reconFileName, true, m_outputBitDepth, m_outputBitDepth, bitDepths.recon ); // write mode +#if JVET_P1019_OUTPUT_LAYER_SET + if(((m_cDecLib.getVPS() != nullptr) && (m_cDecLib.getVPS()->getMaxLayers() > 1) && (isNaluWithinTargetOutputLayerIdSet(&nalu))) || (m_cDecLib.getVPS() == nullptr)) +#endif + m_cVideoIOYuvReconFile[nalu.m_nuhLayerId].open(reconFileName, true, m_outputBitDepth, m_outputBitDepth, bitDepths.recon); // write mode #else m_cVideoIOYuvReconFile.open( m_reconFileName, true, m_outputBitDepth, m_outputBitDepth, bitDepths.recon ); // write mode openedReconFile = true; @@ -369,6 +422,173 @@ uint32_t DecApp::decode() return nRet; } +#if JVET_P1019_OUTPUT_LAYER_SET +bool DecApp::deriveOutputLayerSet() +{ + int vps_max_layers_minus1 = m_cDecLib.getVPS()->getMaxLayers() - 1; + int TotalNumOlss = 0; + int each_layer_is_an_ols_flag = m_cDecLib.getVPS()->getEachLayerIsAnOlsFlag(); + int ols_mode_idc = m_cDecLib.getVPS()->getOlsModeIdc(); + int num_output_layer_sets_minus1 = m_cDecLib.getVPS()->getNumOutputLayerSets() - 1; + int i = 0, j = 0, k = 0, r = 0; + int* NumOutputLayersInOls; + int* NumLayersInOls; + int** OutputLayerIdInOls; + int** OutputLayerIdx; + int** layerIncludedInOlsFlag; + int** LayerIdInOls; + int** dependencyFlag; + int** RefLayerIdx; + int* NumRefLayers; + + if (vps_max_layers_minus1 == 0) + TotalNumOlss = 1; + else if (each_layer_is_an_ols_flag || ols_mode_idc == 0 || ols_mode_idc == 1) + TotalNumOlss = vps_max_layers_minus1 + 1; + else if (ols_mode_idc == 2) + TotalNumOlss = num_output_layer_sets_minus1 + 1; + + NumOutputLayersInOls = new int[m_cDecLib.getVPS()->getNumOutputLayerSets()]; + NumLayersInOls = new int[m_cDecLib.getVPS()->getNumOutputLayerSets()]; + OutputLayerIdInOls = new int*[TotalNumOlss]; + OutputLayerIdx = new int*[TotalNumOlss]; + layerIncludedInOlsFlag = new int*[TotalNumOlss]; + LayerIdInOls = new int*[TotalNumOlss]; + + for (i = 0; i < TotalNumOlss; i++) + { + OutputLayerIdInOls[i] = new int[vps_max_layers_minus1 + 1]; + OutputLayerIdx[i] = new int[vps_max_layers_minus1 + 1]; + layerIncludedInOlsFlag[i] = new int[vps_max_layers_minus1 + 1]; + LayerIdInOls[i] = new int[vps_max_layers_minus1 + 1]; + } + + dependencyFlag = new int*[vps_max_layers_minus1 + 1]; + RefLayerIdx = new int*[vps_max_layers_minus1 + 1]; + NumRefLayers = new int[vps_max_layers_minus1 + 1]; + + for (i = 0; i <= vps_max_layers_minus1; i++) + { + dependencyFlag[i] = new int[vps_max_layers_minus1 + 1]; + RefLayerIdx[i] = new int[vps_max_layers_minus1 + 1]; + } + + for (i = 0; i <= vps_max_layers_minus1; i++) { + for (j = 0; j <= vps_max_layers_minus1; j++) { + dependencyFlag[i][j] = m_cDecLib.getVPS()->getDirectRefLayerFlag(i, j); + for (k = 0; k < i; k++) + if (m_cDecLib.getVPS()->getDirectRefLayerFlag(i, k) && dependencyFlag[k][j]) + dependencyFlag[i][j] = 1; + } + } + for (i = 0; i <= vps_max_layers_minus1; i++) + { + for (j = 0, r = 0; j <= vps_max_layers_minus1; j++) + { + if (dependencyFlag[i][j]) + RefLayerIdx[i][r++] = j; + } + NumRefLayers[i] = r; + } + + NumOutputLayersInOls[0] = 1; + OutputLayerIdInOls[0][0] = m_cDecLib.getVPS()->getLayerId(0); + for (i = 1; i < TotalNumOlss; i++) + { + if (each_layer_is_an_ols_flag || ols_mode_idc == 0) + { + NumOutputLayersInOls[i] = 1; + OutputLayerIdInOls[i][0] = m_cDecLib.getVPS()->getLayerId(i); + } + else if (ols_mode_idc == 1) { + NumOutputLayersInOls[i] = i + 1; + for (j = 0; j < NumOutputLayersInOls[i]; j++) + OutputLayerIdInOls[i][j] = m_cDecLib.getVPS()->getLayerId(j); + } + else if (ols_mode_idc == 2) { + for (j = 0; j <= vps_max_layers_minus1; j++) + { + layerIncludedInOlsFlag[i][j] = 0; + } + for (k = 0, j = 0; k <= vps_max_layers_minus1; k++) + { + if (m_cDecLib.getVPS()->getOlsOutputLayerFlag(i, k)) + { + layerIncludedInOlsFlag[i][k] = 1; + OutputLayerIdx[i][j] = k; + OutputLayerIdInOls[i][j++] = m_cDecLib.getVPS()->getLayerId(k); + } + } + NumOutputLayersInOls[i] = j; + for (j = 0; j < NumOutputLayersInOls[i]; j++) + { + int idx = OutputLayerIdx[i][j]; + for (k = 0; k < NumRefLayers[idx]; k++) + layerIncludedInOlsFlag[i][RefLayerIdx[idx][k]] = 1; + } + } + } + + m_targetOutputLayerIdSet.clear(); + for (i = 0; i < NumOutputLayersInOls[m_iTargetOLS]; i++) + m_targetOutputLayerIdSet.push_back(OutputLayerIdInOls[m_iTargetOLS][i]); + + NumLayersInOls[0] = 1; + LayerIdInOls[0][0] = m_cDecLib.getVPS()->getLayerId(0); + for (i = 1; i < TotalNumOlss; i++) + { + if (each_layer_is_an_ols_flag) + { + NumLayersInOls[i] = 1; + LayerIdInOls[i][0] = m_cDecLib.getVPS()->getLayerId(i); + } + else if (ols_mode_idc == 0 || ols_mode_idc == 1) + { + NumLayersInOls[i] = i + 1; + for (j = 0; j < NumLayersInOls[i]; j++) + LayerIdInOls[i][j] = m_cDecLib.getVPS()->getLayerId(j); + } + else if (ols_mode_idc == 2) + { + for (k = 0, j = 0; k <= vps_max_layers_minus1; k++) + if (layerIncludedInOlsFlag[i][k]) + LayerIdInOls[i][j++] = m_cDecLib.getVPS()->getLayerId(k); + NumLayersInOls[i] = j; + } + } + + m_targetDecLayerIdSet.clear(); + for (i = 0; i < NumLayersInOls[m_iTargetOLS]; i++) + m_targetDecLayerIdSet.push_back(LayerIdInOls[m_iTargetOLS][i]); + + delete[] NumOutputLayersInOls; + delete[] NumLayersInOls; + delete[] NumRefLayers; + + for (i = 0; i < TotalNumOlss; i++) + { + delete[] OutputLayerIdInOls[i]; + delete[] OutputLayerIdx[i]; + delete[] layerIncludedInOlsFlag[i]; + delete[] LayerIdInOls[i]; + } + delete[] OutputLayerIdInOls; + delete[] OutputLayerIdx; + delete[] layerIncludedInOlsFlag; + delete[] LayerIdInOls; + + for (i = 0; i <= vps_max_layers_minus1; i++) + { + delete[] dependencyFlag[i]; + delete[] RefLayerIdx[i]; + } + delete[] dependencyFlag; + delete[] RefLayerIdx; + + return true; +} +#endif + #if JVET_P1006_PICTURE_HEADER /** - lookahead through next NAL units to determine if current NAL unit is the first NAL unit in a new picture @@ -593,7 +813,9 @@ void DecApp::xCreateDecLib() ); m_cDecLib.setDecodedPictureHashSEIEnabled(m_decodedPictureHashSEIEnabled); +#if !JVET_P1019_OUTPUT_LAYER_SET m_cDecLib.setTargetDecLayer(m_iTargetLayer); +#endif if (!m_outputDecodedSEIMessagesFilename.empty()) { @@ -1014,6 +1236,26 @@ bool DecApp::isNaluWithinTargetDecLayerIdSet( InputNALUnit* nalu ) return false; } +#if JVET_P1019_OUTPUT_LAYER_SET +/** \param nalu Input nalu to check whether its LayerId is within targetOutputLayerIdSet + */ +bool DecApp::isNaluWithinTargetOutputLayerIdSet(InputNALUnit* nalu) +{ + if (m_targetOutputLayerIdSet.size() == 0) // By default, the set is empty, meaning all LayerIds are allowed + { + return true; + } + for (std::vector<int>::iterator it = m_targetOutputLayerIdSet.begin(); it != m_targetOutputLayerIdSet.end(); it++) + { + if (nalu->m_nuhLayerId == (*it)) + { + return true; + } + } + return false; +} + +#else /** \param nalu Input nalu to check whether its LayerId is the specified target layer */ bool DecApp::isNaluTheTargetLayer(InputNALUnit* nalu) @@ -1023,5 +1265,6 @@ bool DecApp::isNaluTheTargetLayer(InputNALUnit* nalu) return false; } +#endif //! \} diff --git a/source/App/DecoderApp/DecApp.h b/source/App/DecoderApp/DecApp.h index 9abfb29193e429e5c8c07e3281d77e503f601fe8..1ff24433c87f189d6bf425f9ce3f538b3b7652a4 100644 --- a/source/App/DecoderApp/DecApp.h +++ b/source/App/DecoderApp/DecApp.h @@ -90,7 +90,12 @@ private: void xFlushOutput ( PicList* pcListPic ); ///< flush all remaining decoded pictures to file #endif bool isNaluWithinTargetDecLayerIdSet ( InputNALUnit* nalu ); ///< check whether given Nalu is within targetDecLayerIdSet +#if JVET_P1019_OUTPUT_LAYER_SET + bool isNaluWithinTargetOutputLayerIdSet(InputNALUnit* nalu); ///< check whether given Nalu is within targetOutputLayerIdSet + bool deriveOutputLayerSet(); ///< derive OLS and layer sets +#else bool isNaluTheTargetLayer(InputNALUnit* nalu); ///< check whether given Nalu is within targetDecLayerIdSet +#endif #if JVET_P1006_PICTURE_HEADER bool isNewPicture(ifstream *bitstreamFile, class InputByteStream *bytestream); ///< check if next NAL unit will be the first NAL unit from a new picture bool isNewAccessUnit(bool newPicture, ifstream *bitstreamFile, class InputByteStream *bytestream); ///< check if next NAL unit will be the first NAL unit from a new access unit diff --git a/source/App/DecoderApp/DecAppCfg.cpp b/source/App/DecoderApp/DecAppCfg.cpp index 42584a5fa8e63453d3faa2af06d5f409b6e893fd..7e5f3892c262df8bf2af220271b92b9132328376 100644 --- a/source/App/DecoderApp/DecAppCfg.cpp +++ b/source/App/DecoderApp/DecAppCfg.cpp @@ -87,7 +87,11 @@ bool DecAppCfg::parseCfg( int argc, char* argv[] ) ("OutputBitDepthC,d", m_outputBitDepth[CHANNEL_TYPE_CHROMA], 0, "bit depth of YUV output chroma component (default: use luma output bit-depth)") ("OutputColourSpaceConvert", outputColourSpaceConvert, string(""), "Colour space conversion to apply to input 444 video. Permitted values are (empty string=UNCHANGED) " + getListOfColourSpaceConverts(false)) ("MaxTemporalLayer,t", m_iMaxTemporalLayer, -1, "Maximum Temporal Layer to be decoded. -1 to decode all layers") - ("TargetLayer,p", m_iTargetLayer, -1, "Target bitstream Layer to be decoded.") +#if JVET_P1019_OUTPUT_LAYER_SET + ("TargetOutputLayerSet,p", m_iTargetOLS, -1, "Target output layer set.") +#else + ("TargetLayer,p", m_iTargetLayer, -1, "Target bitstream Layer to be decoded.") +#endif ("SEIDecodedPictureHash,-dph",m_decodedPictureHashSEIEnabled, 1, "Control handling of decoded picture hash SEI messages\n" "\t1: check hash in SEI messages if available in the bitstream\n" "\t0: ignore SEI message") @@ -224,7 +228,11 @@ DecAppCfg::DecAppCfg() , m_iSkipFrame(0) // m_outputBitDepth array initialised below , m_outputColourSpaceConvert(IPCOLOURSPACE_UNCHANGED) +#if JVET_P1019_OUTPUT_LAYER_SET +, m_iTargetOLS(0) +#else , m_iTargetLayer(0) +#endif , m_iMaxTemporalLayer(-1) , m_decodedPictureHashSEIEnabled(0) , m_decodedNoDisplaySEIEnabled(false) diff --git a/source/App/DecoderApp/DecAppCfg.h b/source/App/DecoderApp/DecAppCfg.h index 774d15dac52c133a4aff18b9dd49d67530bcd47f..692a1d04a0056299d38dc72bc58c04f892da38d8 100644 --- a/source/App/DecoderApp/DecAppCfg.h +++ b/source/App/DecoderApp/DecAppCfg.h @@ -61,8 +61,12 @@ protected: int m_iSkipFrame; ///< counter for frames prior to the random access point to skip int m_outputBitDepth[MAX_NUM_CHANNEL_TYPE]; ///< bit depth used for writing output InputColourSpaceConversion m_outputColourSpaceConvert; +#if JVET_P1019_OUTPUT_LAYER_SET + int m_iTargetOLS; ///< target output layer set + std::vector<int> m_targetOutputLayerIdSet; ///< set of LayerIds to be outputted +#else int m_iTargetLayer; ///< target stream layer to be decoded - +#endif int m_iMaxTemporalLayer; ///< maximum temporal layer to be decoded int m_decodedPictureHashSEIEnabled; ///< Checksum(3)/CRC(2)/MD5(1)/disable(0) acting on decoded picture hash SEI message bool m_decodedNoDisplaySEIEnabled; ///< Enable(true)/disable(false) writing only pictures that get displayed based on the no display SEI message diff --git a/source/App/EncoderApp/EncApp.cpp b/source/App/EncoderApp/EncApp.cpp index 43c82d21140547e62b038fc6ebfdd79e487f65e4..a535145b7150c22aa7c40c4111b42ff28185ded0 100644 --- a/source/App/EncoderApp/EncApp.cpp +++ b/source/App/EncoderApp/EncApp.cpp @@ -93,14 +93,110 @@ void EncApp::xInitLibCfg() VPS vps; #if JVET_N0278_FIXES - vps.setMaxLayers ( m_maxLayers ); + vps.setMaxLayers( m_maxLayers ); + +#if JVET_O1159_SCALABILITY + if (vps.getMaxLayers() > 1) + { + vps.setVPSId(1); //JVET_P0205 vps_video_parameter_set_id shall be greater than 0 for multi-layer coding + } + else + { + vps.setVPSId(0); + vps.setEachLayerIsAnOlsFlag(1); // If vps_max_layers_minus1 is equal to 0, + // the value of each_layer_is_an_ols_flag is inferred to be equal to 1. + // Otherwise, when vps_all_independent_layers_flag is equal to 0, + // the value of each_layer_is_an_ols_flag is inferred to be equal to 0. + } + vps.setMaxSubLayers(m_maxSublayers); + if (vps.getMaxLayers() > 1 && vps.getMaxSubLayers() > 1) + { + vps.setAllLayersSameNumSublayersFlag(m_allLayersSameNumSublayersFlag); + } + if (vps.getMaxLayers() > 1) + { + vps.setAllIndependentLayersFlag(m_allIndependentLayersFlag); + if (!vps.getAllIndependentLayersFlag()) + { + vps.setEachLayerIsAnOlsFlag(0); + } + } + + for (int i = 0; i < vps.getMaxLayers(); i++) + { + vps.setGeneralLayerIdx( m_layerId[i], i ); + vps.setLayerId(i, m_layerId[i]); + + if (i > 0 && !vps.getAllIndependentLayersFlag()) + { + vps.setIndependentLayerFlag( i, m_numRefLayers[i] ? false : true ); + + if (!vps.getIndependentLayerFlag(i)) + { + for (int j = 0, k = 0; j < i; j++) + { + if (m_refLayerIdxStr[i].find(to_string(j)) != std::string::npos) + { + vps.setDirectRefLayerFlag(i, j, true); + vps.setInterLayerRefIdc( i, j, k ); + vps.setDirectRefLayerIdx(i, k++, j); + } + else + { + vps.setDirectRefLayerFlag(i, j, false); + } + } + } + } + } + + + if (vps.getMaxLayers() > 1) + { + if (vps.getAllIndependentLayersFlag()) + { + vps.setEachLayerIsAnOlsFlag(m_eachLayerIsAnOlsFlag); + if (vps.getEachLayerIsAnOlsFlag() == 0) + { + vps.setOlsModeIdc(2); // When vps_all_independent_layers_flag is equal to 1 and each_layer_is_an_ols_flag is equal to 0, the value of ols_mode_idc is inferred to be equal to 2 + } + } + if (!vps.getEachLayerIsAnOlsFlag()) + { + if (!vps.getAllIndependentLayersFlag()) + { + vps.setOlsModeIdc(m_olsModeIdc); + } + if (vps.getOlsModeIdc() == 2) + { + vps.setNumOutputLayerSets(m_numOutputLayerSets); + for (int i = 1; i < vps.getNumOutputLayerSets(); i++) + { + for (int j = 0; j < vps.getMaxLayers(); j++) + { + if (m_olsOutputLayerStr[i].find(to_string(j)) != std::string::npos) + { + vps.setOlsOutputLayerFlag(i, j, 1); + } + else + { + vps.setOlsOutputLayerFlag(i, j, 0); + } + } + } + } + } + } +#endif #else vps.setMaxLayers ( 1 ); #endif +#if !JVET_O1159_SCALABILITY for(int i = 0; i < MAX_TLAYER; i++) { vps.setVPSIncludedLayerId ( 0, i ); } +#endif vps.setVPSExtensionFlag ( false ); m_cEncLib.setVPS(&vps); m_cEncLib.setProfile ( m_profile); @@ -483,6 +579,11 @@ void EncApp::xInitLibCfg() } m_cEncLib.setLFCrossSliceBoundaryFlag ( m_bLFCrossSliceBoundaryFlag ); #endif + +#if JVET_P1024_SINGLE_SLICE_PER_SUBPIC_FLAG + //====== Sub-picture and Slices ======== + m_cEncLib.setSingleSlicePerSubPicFlagFlag ( m_singleSlicePerSubPicFlag ); +#endif m_cEncLib.setUseSAO ( m_bUseSAO ); m_cEncLib.setTestSAODisableAtPictureLevel ( m_bTestSAODisableAtPictureLevel ); m_cEncLib.setSaoEncodingRate ( m_saoEncodingRate ); @@ -843,6 +944,9 @@ void EncApp::xInitLibCfg() #if JVET_O0549_ENCODER_ONLY_FILTER m_cEncLib.setGopBasedTemporalFilterEnabled(m_gopBasedTemporalFilterEnabled); #endif +#if JVET_O1159_SCALABILITY + m_cEncLib.setNumRefLayers ( m_numRefLayers ); +#endif } #if JVET_N0278_FIXES diff --git a/source/App/EncoderApp/EncAppCfg.cpp b/source/App/EncoderApp/EncAppCfg.cpp index 530dd088b543ff463a0a64891762e9fed418c88a..3c90bde664c6c0580953828033fdf571063a7ead 100644 --- a/source/App/EncoderApp/EncAppCfg.cpp +++ b/source/App/EncoderApp/EncAppCfg.cpp @@ -1331,6 +1331,9 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] ) "\t3: max number of tiles per slice") ("LFCrossSliceBoundaryFlag", m_bLFCrossSliceBoundaryFlag, true) +#endif +#if JVET_P1024_SINGLE_SLICE_PER_SUBPIC_FLAG + ("EnableSubPicPartitioning", m_subPicPartitionFlag, true, "Enable Sub-Picture partitioning (0: single slice per sub-picture, 1: multiple slices per sub-picture can be used)") #endif ("FastUDIUseMPMEnabled", m_bFastUDIUseMPMEnabled, true, "If enabled, adapt intra direction search, accounting for MPM") ("FastMEForGenBLowDelayEnabled", m_bFastMEForGenBLowDelayEnabled, true, "If enabled use a fast ME for generalised B Low Delay slices") @@ -1696,6 +1699,21 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] ) ( "UpscaledOutput", m_upscaledOutput, 0, "Output upscaled (2), decoded but in full resolution buffer (1) or decoded cropped (0, default) picture for RPR" ) #if JVET_N0278_FIXES ( "MaxLayers", m_maxLayers, 1, "Max number of layers" ) +#if JVET_O1159_SCALABILITY + + ; + opts.addOptions() + ( "MaxSublayers", m_maxSublayers, 1, "Max number of Sublayers") + ( "AllLayersSameNumSublayersFlag", m_allLayersSameNumSublayersFlag, true, "All layers same num sublayersflag") + ( "AllIndependentLayersFlag", m_allIndependentLayersFlag, true, "All layers are independent layer") + ( "LayerId%d", m_layerId, 0, MAX_VPS_LAYERS, "Max number of Sublayers") + ( "NumRefLayers%d", m_numRefLayers, 0, MAX_VPS_LAYERS, "Number of direct reference layer index of i-th layer") + ( "RefLayerIdx%d", m_refLayerIdxStr, string(""), MAX_VPS_LAYERS, "Reference layer index(es)") + ( "EachLayerIsAnOlsFlag", m_eachLayerIsAnOlsFlag, true, "Each layer is an OLS layer flag") + ( "OlsModeIdc", m_olsModeIdc, 0, "Output layer set mode") + ( "NumOutputLayerSets", m_numOutputLayerSets, 1, "Number of output layer sets") + ( "OlsOutputLayer%d", m_olsOutputLayerStr, string(""), MAX_VPS_LAYERS, "Output layer index of i-th OLS") +#endif #endif ; @@ -1979,7 +1997,16 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] ) { m_subProfile[i] = cfg_SubProfile.values[i]; } - +#if JVET_P1024_SINGLE_SLICE_PER_SUBPIC_FLAG + if (m_subPicPartitionFlag) + { + m_singleSlicePerSubPicFlag = false; + } + else + { + m_singleSlicePerSubPicFlag = true; + } +#endif #if !JVET_P1004_REMOVE_BRICKS if (m_tileUniformSpacingFlag) { diff --git a/source/App/EncoderApp/EncAppCfg.h b/source/App/EncoderApp/EncAppCfg.h index 7988628f531d5ca8228404560219ffd28e994a9b..132fcb6640e7c4caeddcba5a31c5f42892aeb3e9 100644 --- a/source/App/EncoderApp/EncAppCfg.h +++ b/source/App/EncoderApp/EncAppCfg.h @@ -475,6 +475,10 @@ protected: int m_uniformTileRowHeightMinus1; std::vector<int> m_tileColumnWidth; std::vector<int> m_tileRowHeight; +#endif +#if JVET_P1024_SINGLE_SLICE_PER_SUBPIC_FLAG + bool m_subPicPartitionFlag; + bool m_singleSlicePerSubPicFlag; #endif bool m_entropyCodingSyncEnabledFlag; @@ -797,6 +801,20 @@ protected: #if JVET_N0278_FIXES int m_maxLayers; + +#if JVET_O1159_SCALABILITY + int m_layerId[MAX_VPS_LAYERS]; + int m_layerIdx; + int m_maxSublayers; + bool m_allLayersSameNumSublayersFlag; + bool m_allIndependentLayersFlag; + int m_numRefLayers[MAX_VPS_LAYERS]; + std::string m_refLayerIdxStr[MAX_VPS_LAYERS]; + bool m_eachLayerIsAnOlsFlag; + int m_olsModeIdc; + int m_numOutputLayerSets; + std::string m_olsOutputLayerStr[MAX_VPS_LAYERS]; +#endif #endif #if EXTENSION_360_VIDEO diff --git a/source/App/StreamMergeApp/StreamMergeApp.cpp b/source/App/StreamMergeApp/StreamMergeApp.cpp index 4df1bad911969fda2a25d623bdeba36e4b3bf43a..7232956f0e82240fb7a432db098a146847842c07 100644 --- a/source/App/StreamMergeApp/StreamMergeApp.cpp +++ b/source/App/StreamMergeApp/StreamMergeApp.cpp @@ -279,9 +279,10 @@ uint32_t StreamMergeApp::mergeStreams() //set VPS which will be replicated for all layers but with differnt nul_layer_id vps.setMaxLayers(m_numInputStreams); +#if !JVET_O1159_SCALABILITY for (int i = 0; i < m_numInputStreams; i++) vps.setVPSIncludedLayerId(i < 63 ? i : i + 1, i); //value 63 is reserved - +#endif vps.setVPSExtensionFlag(false); //Loop all input bitstreams to interleave their NALUs diff --git a/source/Lib/CommonLib/CommonDef.h b/source/Lib/CommonLib/CommonDef.h index 0d09788b030a6117cade9d6288d73f0e7b031976..b18a1540b9fbbc1a3b86fc4645376ab77e3ed163 100644 --- a/source/Lib/CommonLib/CommonDef.h +++ b/source/Lib/CommonLib/CommonDef.h @@ -173,8 +173,15 @@ static const int MAX_NESTING_NUM_OPS = 1024; static const int MAX_NESTING_NUM_LAYER = 64; static const int MAX_VPS_NUM_HRD_PARAMETERS = 1; +#if JVET_O1159_SCALABILITY +static const int MAX_VPS_LAYERS = 64; +static const int MAX_VPS_SUBLAYERS = 7; +static const int MAX_NUM_REF_LAYERS = 7; +static const int MAX_NUM_OLSS = 256; +static const int MAX_VPS_OLS_MODE_IDC = 2; +#else static const int MAX_VPS_LAYERS = 256; - +#endif static const int MAXIMUM_INTRA_FILTERED_WIDTH = 16; static const int MAXIMUM_INTRA_FILTERED_HEIGHT = 16; diff --git a/source/Lib/CommonLib/InterPrediction.cpp b/source/Lib/CommonLib/InterPrediction.cpp index ce55a63dfb9a7ab6c45587d85c562916353f5000..3359acfcb199cbf5a50545c9b7a1b6c24dbb3a0b 100644 --- a/source/Lib/CommonLib/InterPrediction.cpp +++ b/source/Lib/CommonLib/InterPrediction.cpp @@ -315,7 +315,7 @@ void InterPrediction::xSubPuMC( PredictionUnit& pu, PelUnitBuf& predBuf, const R int fstStep = (!verMC ? puHeight : puWidth); int secStep = (!verMC ? puWidth : puHeight); -#if JVET_P0590_SCALING_WINDOW +#if JVET_P0590_SCALING_WINDOW || JVET_O1159_SCALABILITY bool scaled = pu.cu->slice->getScalingRatio( REF_PIC_LIST_0, 0 ) != SCALE_1X || ( pu.cs->slice->getSliceType() == B_SLICE ? pu.cu->slice->getScalingRatio( REF_PIC_LIST_1, 0 ) != SCALE_1X : false ); #else pu.refIdx[0] = 0; pu.refIdx[1] = pu.cs->slice->getSliceType() == B_SLICE ? 0 : -1; @@ -1942,7 +1942,7 @@ void InterPrediction::motionCompensation( PredictionUnit &pu, PelUnitBuf &predBu } } -#if JVET_P0590_SCALING_WINDOW +#if JVET_P0590_SCALING_WINDOW || JVET_O1159_SCALABILITY bioApplied = ( ( refIdx0 < 0 ? true : pu.cu->slice->getScalingRatio( REF_PIC_LIST_0, refIdx0 ) == SCALE_1X ) && ( refIdx1 < 0 ? true : pu.cu->slice->getScalingRatio( REF_PIC_LIST_1, refIdx1 ) == SCALE_1X ) ) ? bioApplied : false; #else bioApplied = PU::isRefPicSameSize( pu ) ? bioApplied : false; diff --git a/source/Lib/CommonLib/Picture.cpp b/source/Lib/CommonLib/Picture.cpp index 41d7de20e10b20c854550ddf8d249a22144fc96b..06c75687b3d12704ab7b0f2e9fa2f35d0c87041f 100644 --- a/source/Lib/CommonLib/Picture.cpp +++ b/source/Lib/CommonLib/Picture.cpp @@ -688,7 +688,11 @@ const CPelUnitBuf Picture::getRecoBuf(const UnitArea &unit, bool wrap) const const CPelUnitBuf Picture::getRecoBuf(bool wrap) const { return M_BUFS(scheduler.getSplitPicId(), wrap ? PIC_RECON_WRAP : PIC_RECONSTRUCTION); } #if JVET_P1006_PICTURE_HEADER +#if JVET_O1159_SCALABILITY +void Picture::finalInit( const VPS* vps, const SPS& sps, const PPS& pps, PicHeader *picHeader, APS** alfApss, APS* lmcsAps, APS* scalingListAps ) +#else void Picture::finalInit( const SPS& sps, const PPS& pps, PicHeader* picHeader, APS** alfApss, APS* lmcsAps, APS* scalingListAps ) +#endif #else void Picture::finalInit( const SPS& sps, const PPS& pps, APS** alfApss, APS* lmcsAps, APS* scalingListAps ) #endif @@ -724,6 +728,9 @@ void Picture::finalInit( const SPS& sps, const PPS& pps, APS** alfApss, APS* lmc cs->create(chromaFormatIDC, Area(0, 0, iWidth, iHeight), true, (bool)sps.getPLTMode()); } +#if JVET_O1159_SCALABILITY + cs->vps = vps; +#endif cs->picture = this; cs->slice = nullptr; // the slices for this picture have not been set at this point. update cs->slice after swapSliceObject() cs->pps = &pps; diff --git a/source/Lib/CommonLib/Picture.h b/source/Lib/CommonLib/Picture.h index a257ea5803b6ab04f423eb754c73513a4656447b..4505f3b7a67a5e9a91467a175f00f49ee6b13a38 100644 --- a/source/Lib/CommonLib/Picture.h +++ b/source/Lib/CommonLib/Picture.h @@ -219,7 +219,11 @@ struct Picture : public UnitArea void extendPicBorder(); #if JVET_P1006_PICTURE_HEADER +#if JVET_O1159_SCALABILITY + void finalInit( const VPS* vps, const SPS& sps, const PPS& pps, PicHeader *picHeader, APS** alfApss, APS* lmcsAps, APS* scalingListAps ); +#else void finalInit( const SPS& sps, const PPS& pps, PicHeader *picHeader, APS** alfApss, APS* lmcsAps, APS* scalingListAps ); +#endif #else void finalInit( const SPS& sps, const PPS& pps, APS** alfApss, APS* lmcsAps, APS* scalingListAps ); #endif diff --git a/source/Lib/CommonLib/SEI.cpp b/source/Lib/CommonLib/SEI.cpp index c0ac199862a7bebdb34658b00bf8feb0430805a1..85959f02e67df5fe79cc1f29fc0261480346ba39 100644 --- a/source/Lib/CommonLib/SEI.cpp +++ b/source/Lib/CommonLib/SEI.cpp @@ -113,7 +113,11 @@ void SEIBufferingPeriod::copyTo (SEIBufferingPeriod& target) const ::memcpy(target.m_initialCpbRemovalDelay, m_initialCpbRemovalDelay, sizeof(m_initialCpbRemovalDelay)); ::memcpy(target.m_initialCpbRemovalOffset, m_initialCpbRemovalOffset, sizeof(m_initialCpbRemovalOffset)); ::memcpy(target.m_cpbRemovalDelayDelta, m_cpbRemovalDelayDelta, sizeof(m_cpbRemovalDelayDelta)); +#if !JVET_P0446_BP_CPB_CNT_FIX ::memcpy(target.m_bpCpbCnt, m_bpCpbCnt, sizeof(m_bpCpbCnt)); +#else + target.m_bpCpbCnt = m_bpCpbCnt; +#endif #if JVET_P0202_P0203_FIX_HRD_RELATED_SEI target.m_bpDecodingUnitHrdParamsPresentFlag = m_bpDecodingUnitHrdParamsPresentFlag; target.m_decodingUnitCpbParamsInPicTimingSeiFlag = m_decodingUnitCpbParamsInPicTimingSeiFlag; @@ -121,6 +125,13 @@ void SEIBufferingPeriod::copyTo (SEIBufferingPeriod& target) const #if JVET_P0181 target.m_sublayerInitialCpbRemovalDelayPresentFlag = m_sublayerInitialCpbRemovalDelayPresentFlag; #endif +#if JVET_P0446_CONCATENATION + target.m_concatenationFlag = m_concatenationFlag; + target.m_maxInitialRemovalDelayForConcatenation = m_maxInitialRemovalDelayForConcatenation; +#endif +#if JVET_P0446_ALT_CPB + target.m_altCpbParamsPresentFlag = m_altCpbParamsPresentFlag; +#endif } void SEIPictureTiming::copyTo (SEIPictureTiming& target) const @@ -147,6 +158,13 @@ void SEIPictureTiming::copyTo (SEIPictureTiming& target) const target.m_numNalusInDuMinus1 = m_numNalusInDuMinus1; target.m_duCpbRemovalDelayMinus1 = m_duCpbRemovalDelayMinus1; +#if JVET_P0446_ALT_CPB + target.m_cpbAltTimingInfoPresentFlag = m_cpbAltTimingInfoPresentFlag; + target.m_cpbAltInitialCpbRemovalDelayDelta = m_cpbAltInitialCpbRemovalDelayDelta; + target.m_cpbAltInitialCpbRemovalOffsetDelta = m_cpbAltInitialCpbRemovalOffsetDelta; + target.m_cpbDelayOffset = m_cpbDelayOffset; + target.m_dpbDelayOffset = m_dpbDelayOffset; +#endif } // Static member diff --git a/source/Lib/CommonLib/SEI.h b/source/Lib/CommonLib/SEI.h index 331abd94bcac82da0bb869fef2e9bcaae3309996..6bb76936944967ac366652eef1edc90a4c5dc9dc 100644 --- a/source/Lib/CommonLib/SEI.h +++ b/source/Lib/CommonLib/SEI.h @@ -321,6 +321,9 @@ public: , m_initialCpbRemovalDelayLength (0) , m_cpbRemovalDelayLength (0) , m_dpbOutputDelayLength (0) +#if JVET_P0446_BP_CPB_CNT_FIX + , m_bpCpbCnt(0) +#endif , m_duCpbRemovalDelayIncrementLength (0) , m_dpbOutputDelayDuLength (0) , m_cpbRemovalDelayDeltasPresentFlag (false) @@ -332,12 +335,22 @@ public: #endif #if JVET_P0181 , m_sublayerInitialCpbRemovalDelayPresentFlag(false) +#endif +#if JVET_P0446_CONCATENATION + , m_additionalConcatenationInfoPresentFlag (false) + , m_maxInitialRemovalDelayForConcatenation (0) +#endif +#if JVET_P0446_ALT_CPB + , m_altCpbParamsPresentFlag (false) + , m_useAltCpbParamsFlag (false) #endif { ::memset(m_initialCpbRemovalDelay, 0, sizeof(m_initialCpbRemovalDelay)); ::memset(m_initialCpbRemovalOffset, 0, sizeof(m_initialCpbRemovalOffset)); ::memset(m_cpbRemovalDelayDelta, 0, sizeof(m_cpbRemovalDelayDelta)); +#if !JVET_P0446_BP_CPB_CNT_FIX ::memset(m_bpCpbCnt, 0, sizeof(m_bpCpbCnt)); +#endif } virtual ~SEIBufferingPeriod() {} @@ -350,7 +363,11 @@ public: uint32_t m_initialCpbRemovalDelayLength; uint32_t m_cpbRemovalDelayLength; uint32_t m_dpbOutputDelayLength; +#if !JVET_P0446_BP_CPB_CNT_FIX int m_bpCpbCnt[MAX_TLAYER]; +#else + int m_bpCpbCnt; +#endif uint32_t m_duCpbRemovalDelayIncrementLength; uint32_t m_dpbOutputDelayDuLength; uint32_t m_initialCpbRemovalDelay [MAX_TLAYER][MAX_CPB_CNT][2]; @@ -368,6 +385,14 @@ public: #if JVET_P0181 bool m_sublayerInitialCpbRemovalDelayPresentFlag; #endif +#if JVET_P0446_CONCATENATION + bool m_additionalConcatenationInfoPresentFlag; + uint32_t m_maxInitialRemovalDelayForConcatenation; +#endif +#if JVET_P0446_ALT_CPB + bool m_altCpbParamsPresentFlag; + bool m_useAltCpbParamsFlag; +#endif }; class SEIPictureTiming : public SEI @@ -382,6 +407,11 @@ public: , m_picDpbOutputDuDelay (0) , m_numDecodingUnitsMinus1 (0) , m_duCommonCpbRemovalDelayFlag (false) +#if JVET_P0446_ALT_CPB + , m_cpbAltTimingInfoPresentFlag (false) + , m_cpbDelayOffset (0) + , m_dpbDelayOffset (0) +#endif { ::memset(m_ptSubLayerDelaysPresentFlag, 0, sizeof(m_ptSubLayerDelaysPresentFlag)); ::memset(m_duCommonCpbRemovalDelayMinus1, 0, sizeof(m_duCommonCpbRemovalDelayMinus1)); @@ -397,6 +427,11 @@ public: , m_numDecodingUnitsMinus1 (0) , m_duCommonCpbRemovalDelayFlag (false) , m_duCommonCpbRemovalDelayMinus1 (0) +#if JVET_P0446_ALT_CPB + , m_cpbAltTimingInfoPresentFlag (false) + , m_cpbDelayOffset (0) + , m_dpbDelayOffset (0) +#endif { ::memset(m_subLayerDelaysPresentFlag, 0, sizeof(m_subLayerDelaysPresentFlag)); ::memset(m_cpbRemovalDelayDeltaEnabledFlag, 0, sizeof(m_cpbRemovalDelayDeltaEnabledFlag)); @@ -435,6 +470,13 @@ public: std::vector<uint32_t> m_numNalusInDuMinus1; std::vector<uint32_t> m_duCpbRemovalDelayMinus1; #endif +#if JVET_P0446_ALT_CPB + bool m_cpbAltTimingInfoPresentFlag; + std::vector<uint32_t> m_cpbAltInitialCpbRemovalDelayDelta; + std::vector<uint32_t> m_cpbAltInitialCpbRemovalOffsetDelta; + uint32_t m_cpbDelayOffset; + uint32_t m_dpbDelayOffset; +#endif }; class SEIDecodingUnitInfo : public SEI diff --git a/source/Lib/CommonLib/Slice.cpp b/source/Lib/CommonLib/Slice.cpp index b29dde17b0a1383cf880af3e7cc83ee278407d3f..7dccc3b23c4f745371add4ce66ff41721c28fa30 100644 --- a/source/Lib/CommonLib/Slice.cpp +++ b/source/Lib/CommonLib/Slice.cpp @@ -497,8 +497,24 @@ void Slice::constructRefPicList(PicList& rcListPic) uint32_t numOfActiveRef = 0; //construct L0 numOfActiveRef = getNumRefIdx(REF_PIC_LIST_0); +#if JVET_O1159_SCALABILITY + int layerIdx = m_pcPic->cs->vps == nullptr ? 0 : m_pcPic->cs->vps->getGeneralLayerIdx( m_pcPic->layerId ); +#endif + for (int ii = 0; ii < numOfActiveRef; ii++) { +#if JVET_O1159_SCALABILITY + if( m_pRPL0->isInterLayerRefPic( ii ) ) + { + CHECK( m_pRPL0->getInterLayerRefPicIdx( ii ) == NOT_VALID, "Wrong ILRP index" ); + + int refLayerIdx = m_pcPic->cs->vps->getDirectRefLayerIdx( layerIdx, m_pRPL0->getInterLayerRefPicIdx( ii ) ); + + pcRefPic = xGetRefPic( rcListPic, getPOC(), refLayerIdx ); + pcRefPic->longTerm = true; + } + else +#endif if (!m_pRPL0->isRefPicLongterm(ii)) { #if JVET_N0278_FIXES @@ -530,6 +546,18 @@ void Slice::constructRefPicList(PicList& rcListPic) numOfActiveRef = getNumRefIdx(REF_PIC_LIST_1); for (int ii = 0; ii < numOfActiveRef; ii++) { +#if JVET_O1159_SCALABILITY + if( m_pRPL1->isInterLayerRefPic( ii ) ) + { + CHECK( m_pRPL1->getInterLayerRefPicIdx( ii ) == NOT_VALID, "Wrong ILRP index" ); + + int refLayerIdx = m_pcPic->cs->vps->getDirectRefLayerIdx( layerIdx, m_pRPL1->getInterLayerRefPicIdx( ii ) ); + + pcRefPic = xGetRefPic( rcListPic, getPOC(), refLayerIdx ); + pcRefPic->longTerm = true; + } + else +#endif if (!m_pRPL1->isRefPicLongterm(ii)) { #if JVET_N0278_FIXES @@ -623,7 +651,11 @@ void Slice::checkCRA(const ReferencePictureList *pRPL0, const ReferencePictureLi { CHECK(getPOC() - pRPL1->getRefPicIdentifier(i) < pocCRA, "Invalid state"); } +#if JVET_O1159_SCALABILITY + else if( !pRPL1->isInterLayerRefPic( i ) ) +#else else +#endif { #if JVET_N0278_FIXES CHECK( xGetLongTermRefPic( rcListPic, pRPL1->getRefPicIdentifier( i ), pRPL1->getDeltaPocMSBPresentFlag( i ), m_pcPic->layerId )->getPOC() < pocCRA, "Invalid state" ); @@ -1148,7 +1180,11 @@ void Slice::checkLeadingPictureRestrictions(PicList& rcListPic) const //Function for applying picture marking based on the Reference Picture List +#if JVET_O1159_SCALABILITY +void Slice::applyReferencePictureListBasedMarking( PicList& rcListPic, const ReferencePictureList *pRPL0, const ReferencePictureList *pRPL1, const int layerId ) const +#else void Slice::applyReferencePictureListBasedMarking(PicList& rcListPic, const ReferencePictureList *pRPL0, const ReferencePictureList *pRPL1) const +#endif { int i, isReference; checkLeadingPictureRestrictions(rcListPic); @@ -1167,8 +1203,26 @@ void Slice::applyReferencePictureListBasedMarking(PicList& rcListPic, const Refe isReference = 0; // loop through all pictures in the Reference Picture Set // to see if the picture should be kept as reference picture - for (i = 0; isNeedToCheck && !isReference && i<pRPL0->getNumberOfShorttermPictures() + pRPL0->getNumberOfLongtermPictures(); i++) +#if JVET_O1159_SCALABILITY + for( i = 0; isNeedToCheck && !isReference && i < pRPL0->getNumberOfShorttermPictures() + pRPL0->getNumberOfLongtermPictures() + pRPL0->getNumberOfInterLayerPictures(); i++ ) + { + if( pRPL0->isInterLayerRefPic( i ) ) + { + // Diagonal inter-layer prediction is not allowed + CHECK( pRPL0->getRefPicIdentifier( i ), "ILRP identifier should be 0" ); + + if( pcPic->poc == m_iPOC ) + { + isReference = 1; + pcPic->longTerm = true; + } + } + else if (pcPic->layerId == layerId) + { +#else + for (i = 0; isNeedToCheck && !isReference && i < pRPL0->getNumberOfShorttermPictures() + pRPL0->getNumberOfLongtermPictures(); i++) { +#endif if (!(pRPL0->isRefPicLongterm(i))) { if (pcPic->poc == this->getPOC() - pRPL0->getRefPicIdentifier(i)) @@ -1187,9 +1241,31 @@ void Slice::applyReferencePictureListBasedMarking(PicList& rcListPic, const Refe pcPic->longTerm = true; } } +#if JVET_O1159_SCALABILITY + } +#endif } + +#if JVET_O1159_SCALABILITY + for( i = 0; isNeedToCheck && !isReference && i < pRPL1->getNumberOfShorttermPictures() + pRPL1->getNumberOfLongtermPictures() + pRPL1->getNumberOfInterLayerPictures(); i++ ) + { + if( pRPL1->isInterLayerRefPic( i ) ) + { + // Diagonal inter-layer prediction is not allowed + CHECK( pRPL1->getRefPicIdentifier( i ), "ILRP identifier should be 0" ); + + if( pcPic->poc == m_iPOC ) + { + isReference = 1; + pcPic->longTerm = true; + } + } + else if( pcPic->layerId == layerId ) + { +#else for (i = 0; isNeedToCheck && !isReference && i<pRPL1->getNumberOfShorttermPictures() + pRPL1->getNumberOfLongtermPictures(); i++) { +#endif if (!(pRPL1->isRefPicLongterm(i))) { if (pcPic->poc == this->getPOC() - pRPL1->getRefPicIdentifier(i)) @@ -1208,10 +1284,17 @@ void Slice::applyReferencePictureListBasedMarking(PicList& rcListPic, const Refe pcPic->longTerm = true; } } +#if JVET_O1159_SCALABILITY + } +#endif } // mark the picture as "unused for reference" if it is not in // the Reference Picture List +#if JVET_O1159_SCALABILITY + if( pcPic->layerId == layerId && pcPic->poc != m_iPOC && isReference == 0 ) +#else if (pcPic->poc != this->getPOC() && isReference == 0) +#endif { pcPic->referenced = false; pcPic->longTerm = false; @@ -1234,12 +1317,23 @@ int Slice::checkThatAllRefPicsAreAvailable(PicList& rcListPic, const ReferencePi if (this->isIDRorBLA()) return 0; //Assume that all pic in the DPB will be flushed anyway so no need to check. +#if JVET_O1159_SCALABILITY + int numberOfPictures = pRPL->getNumberOfLongtermPictures() + pRPL->getNumberOfShorttermPictures() + pRPL->getNumberOfInterLayerPictures(); +#else int numberOfPictures = pRPL->getNumberOfLongtermPictures() + pRPL->getNumberOfShorttermPictures(); +#endif //Check long term ref pics for (int ii = 0; pRPL->getNumberOfLongtermPictures() > 0 && ii < numberOfPictures; ii++) { +#if JVET_O1159_SCALABILITY + if( !pRPL->isRefPicLongterm( ii ) || pRPL->isInterLayerRefPic( ii ) ) + { + continue; + } +#else if (!pRPL->isRefPicLongterm(ii)) continue; +#endif notPresentPoc = pRPL->getRefPicIdentifier(ii); isAvailable = 0; @@ -1326,12 +1420,23 @@ int Slice::checkThatAllRefPicsAreAvailable(PicList& rcListPic, const ReferencePi if (this->isIDRorBLA()) return 0; //Assume that all pic in the DPB will be flushed anyway so no need to check. +#if JVET_O1159_SCALABILITY + int numberOfPictures = pRPL->getNumberOfLongtermPictures() + pRPL->getNumberOfShorttermPictures() + pRPL->getNumberOfInterLayerPictures(); +#else int numberOfPictures = pRPL->getNumberOfLongtermPictures() + pRPL->getNumberOfShorttermPictures(); +#endif //Check long term ref pics for (int ii = 0; pRPL->getNumberOfLongtermPictures() > 0 && ii < numberOfPictures; ii++) { +#if JVET_O1159_SCALABILITY + if( !pRPL->isRefPicLongterm( ii ) || pRPL->isInterLayerRefPic( ii ) ) + { + continue; + } +#else if (!pRPL->isRefPicLongterm(ii)) continue; +#endif notPresentPoc = pRPL->getRefPicIdentifier(ii); isAvailable = 0; @@ -1413,8 +1518,24 @@ int Slice::checkThatAllRefPicsAreAvailable(PicList& rcListPic, const ReferencePi bool Slice::isPOCInRefPicList(const ReferencePictureList *rpl, int poc ) { +#if JVET_O1159_SCALABILITY + for( int i = 0; i < rpl->getNumberOfLongtermPictures() + rpl->getNumberOfShorttermPictures() + rpl->getNumberOfInterLayerPictures(); i++ ) + { + if( rpl->isInterLayerRefPic( i ) ) + { + // Diagonal inter-layer prediction is not allowed + CHECK( rpl->getRefPicIdentifier( i ), "ILRP identifier should be 0" ); + + if( poc == m_iPOC ) + { + return true; + } + } + else +#else for (int i = 0; i < rpl->getNumberOfLongtermPictures() + rpl->getNumberOfShorttermPictures(); i++) { +#endif if (rpl->isRefPicLongterm(i)) { if (poc == rpl->getRefPicIdentifier(i)) @@ -1504,6 +1625,7 @@ void Slice::checkConformanceForDRAP( uint32_t temporalId ) } } +#if !JVET_O1159_SCALABILITY void Slice::createExplicitReferencePictureSetFromReference(PicList& rcListPic, const ReferencePictureList *pRPL0, const ReferencePictureList *pRPL1) { Picture* rpcPic; @@ -1678,6 +1800,7 @@ void Slice::createExplicitReferencePictureSetFromReference(PicList& rcListPic, c this->setRPL1idx(-1); this->setRPL1(pLocalRPL1); } +#endif //! get AC and DC values for weighted pred void Slice::getWpAcDcParam(const WPACDCParam *&wp) const @@ -1795,12 +1918,43 @@ unsigned Slice::getMinPictureDistance() const VPS::VPS() : m_VPSId(0) , m_uiMaxLayers(1) - , m_vpsExtensionFlag() +#if JVET_P0185 + , m_vpsMaxSubLayers(1) +#endif +#if JVET_O1159_SCALABILITY + , m_vpsAllLayersSameNumSubLayersFlag (true) + , m_vpsAllIndependentLayersFlag(true) + , m_vpsEachLayerIsAnOlsFlag (1) + , m_vpsOlsModeIdc (0) + , m_vpsNumOutputLayerSets (1) +#endif +, m_vpsExtensionFlag() { +#if JVET_O1159_SCALABILITY + for (int i = 0; i < MAX_VPS_LAYERS; i++) + { + m_vpsLayerId[i] = 0; + m_vpsIndependentLayerFlag[i] = 1; + for (int j = 0; j < MAX_VPS_LAYERS; j++) + { + m_vpsDirectRefLayerFlag[i][j] = 0; + m_directRefLayerIdx[i][j] = MAX_VPS_LAYERS; + m_interLayerRefIdx[i][i] = NOT_VALID; + } + } + for (int i = 0; i < MAX_NUM_OLSS; i++) + { + for (int j = 0; j < MAX_VPS_LAYERS; j++) + { + m_vpsOlsOutputLayerFlag[i][j] = 0; + } + } +#else for (int i = 0; i < MAX_VPS_LAYERS; i++) { m_vpsIncludedLayerId[i] = 0; } +#endif } VPS::~VPS() @@ -1886,11 +2040,17 @@ PicHeader::PicHeader() m_localRPL0.setNumberOfShorttermPictures(0); m_localRPL0.setNumberOfLongtermPictures(0); m_localRPL0.setLtrpInSliceHeaderFlag(0); +#if JVET_O1159_SCALABILITY + m_localRPL0.setNumberOfInterLayerPictures( 0 ); +#endif m_localRPL1.setNumberOfActivePictures(0); m_localRPL1.setNumberOfShorttermPictures(0); m_localRPL1.setNumberOfLongtermPictures(0); m_localRPL1.setLtrpInSliceHeaderFlag(0); +#if JVET_O1159_SCALABILITY + m_localRPL1.setNumberOfInterLayerPictures( 0 ); +#endif m_alfApsId.resize(0); } @@ -2344,6 +2504,9 @@ PPS::PPS() , m_numTileCols (1) , m_numTileRows (1) , m_rectSliceFlag (1) +#if JVET_P1024_SINGLE_SLICE_PER_SUBPIC_FLAG + , m_singleSlicePerSubPicFlag (0) +#endif , m_numSlicesInPic (1) , m_tileIdxDeltaPresentFlag (0) , m_loopFilterAcrossTilesEnabledFlag (1) @@ -2418,6 +2581,9 @@ PPS::PPS() m_tileRowBd.clear(); m_ctuToTileCol.clear(); m_ctuToTileRow.clear(); +#if JVET_P1024_SINGLE_SLICE_PER_SUBPIC_FLAG + m_ctuToSubPicIdx.clear(); +#endif m_rectSlices.clear(); m_sliceMap.clear(); #endif @@ -2432,6 +2598,9 @@ PPS::~PPS() m_tileRowBd.clear(); m_ctuToTileCol.clear(); m_ctuToTileRow.clear(); +#if JVET_P1024_SINGLE_SLICE_PER_SUBPIC_FLAG + m_ctuToSubPicIdx.clear(); +#endif m_rectSlices.clear(); m_sliceMap.clear(); @@ -2456,6 +2625,9 @@ void PPS::resetTileSliceInfo() m_tileRowBd.clear(); m_ctuToTileCol.clear(); m_ctuToTileRow.clear(); +#if JVET_P1024_SINGLE_SLICE_PER_SUBPIC_FLAG + m_ctuToSubPicIdx.clear(); +#endif m_rectSlices.clear(); m_sliceMap.clear(); } @@ -2565,7 +2737,24 @@ void PPS::initRectSliceMap() // allocate new memory for slice list CHECK(m_numSlicesInPic > MAX_SLICES, "Number of slices in picture exceeds valid range"); m_sliceMap.resize( m_numSlicesInPic ); - +#if JVET_P1024_SINGLE_SLICE_PER_SUBPIC_FLAG + if ((getNumSubPics() > 0) && getSingleSlicePerSubPicFlag()) + { + for (uint32_t i = 0; i <= getNumSubPics() - 1; i++) + { + m_sliceMap[i].initSliceMap(); + } + uint32_t picSizeInCtu = getPicWidthInCtu() * getPicHeightInCtu(); + uint32_t sliceIdx; + for (uint32_t i = 0; i < picSizeInCtu; i++) + { + sliceIdx = getCtuToSubPicIdx(i); + m_sliceMap[sliceIdx].pushToCtuAddrInSlice(i); + } + } + else + { +#endif // generate CTU maps for all rectangular slices in picture for( uint32_t i = 0; i < m_numSlicesInPic; i++ ) { @@ -2620,7 +2809,9 @@ void PPS::initRectSliceMap() ctuY, getTileRowBd( tileY + 1 ), m_picWidthInCtu); } } - +#if JVET_P1024_SINGLE_SLICE_PER_SUBPIC_FLAG + } +#endif // check for valid rectangular slice map checkSliceMap(); } @@ -2693,29 +2884,49 @@ APS::~APS() { } - +#if JVET_O1159_SCALABILITY +ReferencePictureList::ReferencePictureList( const bool interLayerPicPresentFlag ) +#else ReferencePictureList::ReferencePictureList() +#endif : m_numberOfShorttermPictures(0) , m_numberOfLongtermPictures(0) , m_numberOfActivePictures(MAX_INT) , m_ltrp_in_slice_header_flag(0) +#if JVET_O1159_SCALABILITY + , m_interLayerPresentFlag( interLayerPicPresentFlag ) + , m_numberOfInterLayerPictures( 0 ) +#endif { ::memset(m_isLongtermRefPic, 0, sizeof(m_isLongtermRefPic)); ::memset(m_refPicIdentifier, 0, sizeof(m_refPicIdentifier)); ::memset(m_POC, 0, sizeof(m_POC)); +#if JVET_O1159_SCALABILITY + ::memset( m_isInterLayerRefPic, 0, sizeof( m_isInterLayerRefPic ) ); + ::memset( m_interLayerRefPicIdx, 0, sizeof( m_interLayerRefPicIdx ) ); +#endif } ReferencePictureList::~ReferencePictureList() { } +#if JVET_O1159_SCALABILITY +void ReferencePictureList::setRefPicIdentifier( int idx, int identifier, bool isLongterm, bool isInterLayerRefPic, int interLayerIdx ) +#else void ReferencePictureList::setRefPicIdentifier(int idx, int identifier, bool isLongterm) +#endif { m_refPicIdentifier[idx] = identifier; m_isLongtermRefPic[idx] = isLongterm; m_deltaPocMSBPresentFlag[idx] = false; m_deltaPOCMSBCycleLT[idx] = 0; + +#if JVET_O1159_SCALABILITY + m_isInterLayerRefPic[idx] = isInterLayerRefPic; + m_interLayerRefPicIdx[idx] = interLayerIdx; +#endif } int ReferencePictureList::getRefPicIdentifier(int idx) const @@ -3500,9 +3711,16 @@ bool ParameterSetManager::activatePPS(int ppsId, bool isIRAP) } else { +#if JVET_P0185 + m_vpsMap.clear(); + m_vpsMap.allocatePS(0); + m_activeVPSId = 0; + m_vpsMap.setActive(0); +#else //No actual VPS m_activeVPSId = -1; m_vpsMap.clear(); +#endif } #endif @@ -3562,6 +3780,14 @@ void ParameterSetMap<SPS>::setID(SPS* parameterSet, const int psId) parameterSet->setSPSId(psId); } +#if JVET_P0185 +template <> +void ParameterSetMap<VPS>::setID(VPS* parameterSet, const int psId) +{ + parameterSet->setVPSId(psId); +} +#endif + ProfileTierLevel::ProfileTierLevel() : m_tierFlag (Level::MAIN) , m_profileIdc (Profile::NONE) @@ -3764,7 +3990,11 @@ void Slice::scaleRefPicList( Picture *scaledRefPic[ ], APS** apss, APS* lmcsAps, scaledRefPic[j]->referenced = true; #if JVET_P1006_PICTURE_HEADER - scaledRefPic[ j ]->finalInit( *sps, *pps, picHeader, apss, lmcsAps, scalingListAps ); +#if JVET_O1159_SCALABILITY + scaledRefPic[j]->finalInit( m_pcPic->cs->vps, *sps, *pps, picHeader, apss, lmcsAps, scalingListAps ); +#else + scaledRefPic[j]->finalInit( *sps, *pps, picHeader, apss, lmcsAps, scalingListAps ); +#endif #else scaledRefPic[ j ]->finalInit( *sps, *pps, apss, lmcsAps, scalingListAps ); #endif diff --git a/source/Lib/CommonLib/Slice.h b/source/Lib/CommonLib/Slice.h index 76ba94a57a03215bc2ed51e952a163e51f1d639f..a6f28708edc9c4f03c6707923a9c6bc5bb29df06 100644 --- a/source/Lib/CommonLib/Slice.h +++ b/source/Lib/CommonLib/Slice.h @@ -84,12 +84,26 @@ private: bool m_deltaPocMSBPresentFlag[MAX_NUM_REF_PICS]; int m_deltaPOCMSBCycleLT[MAX_NUM_REF_PICS]; bool m_ltrp_in_slice_header_flag; +#if JVET_O1159_SCALABILITY + bool m_interLayerPresentFlag; + bool m_isInterLayerRefPic[MAX_NUM_REF_PICS]; + int m_interLayerRefPicIdx[MAX_NUM_REF_PICS]; + int m_numberOfInterLayerPictures; +#endif public: +#if JVET_O1159_SCALABILITY + ReferencePictureList( const bool interLayerPicPresentFlag = false ); +#else ReferencePictureList(); +#endif virtual ~ReferencePictureList(); +#if JVET_O1159_SCALABILITY + void setRefPicIdentifier( int idx, int identifier, bool isLongterm, bool isInterLayerRefPic, int interLayerIdx ); +#else void setRefPicIdentifier(int idx, int identifier, bool isLongterm); +#endif int getRefPicIdentifier(int idx) const; bool isRefPicLongterm(int idx) const; @@ -102,7 +116,14 @@ public: void setLtrpInSliceHeaderFlag(bool flag) { m_ltrp_in_slice_header_flag = flag; } bool getLtrpInSliceHeaderFlag() const { return m_ltrp_in_slice_header_flag; } +#if JVET_O1159_SCALABILITY + void setNumberOfInterLayerPictures( const int numberOfIlrp ) { m_numberOfInterLayerPictures = numberOfIlrp; } + int getNumberOfInterLayerPictures() const { return m_numberOfInterLayerPictures; } + + int getNumRefEntries() const { return m_numberOfShorttermPictures + m_numberOfLongtermPictures + m_numberOfInterLayerPictures; } +#else int getNumRefEntries() const { return m_numberOfShorttermPictures + m_numberOfLongtermPictures; } +#endif void setPOC(int idx, int POC); int getPOC(int idx) const; @@ -116,6 +137,14 @@ public: void setDeltaPocMSBPresentFlag(int i, bool x) { m_deltaPocMSBPresentFlag[i] = x; } void printRefPicInfo() const; + +#if JVET_O1159_SCALABILITY + bool getInterLayerPresentFlag() const { return m_interLayerPresentFlag; } + void setInterLayerPresentFlag( bool b ) { m_interLayerPresentFlag = b; } + bool isInterLayerRefPic( int idx ) const { return m_isInterLayerRefPic[idx]; } + int getInterLayerRefPicIdx( int idx ) const { return m_interLayerRefPicIdx[idx]; } + void setInterLayerRefPicIdx( int idx, int layerIdc ) { m_interLayerRefPicIdx[idx] = layerIdc; } +#endif }; /// Reference Picture List set class @@ -452,7 +481,11 @@ class ProfileTierLevel ConstraintInfo m_constraintInfo; bool m_subLayerLevelPresentFlag[MAX_TLAYER - 1]; +#if JVET_P0217_PTL_SYNTAX_CLEANUP + Level::Name m_subLayerLevelIdc[MAX_TLAYER]; +#else Level::Name m_subLayerLevelIdc[MAX_TLAYER - 1]; +#endif public: ProfileTierLevel(); @@ -655,6 +688,9 @@ public: uint32_t getNumCtuInSlice() const { return m_numCtuInSlice; } std::vector<uint32_t> getCtuAddrList( ) const { return m_ctuAddrInSlice; } uint32_t getCtuAddrInSlice( int idx ) const { CHECK(idx >= m_ctuAddrInSlice.size(), "CTU index exceeds number of CTUs in slice."); return m_ctuAddrInSlice[idx]; } +#if JVET_P1024_SINGLE_SLICE_PER_SUBPIC_FLAG + void pushToCtuAddrInSlice( uint32_t u ) { m_ctuAddrInSlice.push_back(u); m_numCtuInSlice++;} +#endif void initSliceMap() { @@ -747,7 +783,27 @@ private: int m_VPSId; uint32_t m_uiMaxLayers; +#if JVET_P0185 + uint32_t m_vpsMaxSubLayers; +#endif +#if JVET_O1159_SCALABILITY + uint32_t m_vpsLayerId[MAX_VPS_LAYERS]; + bool m_vpsAllLayersSameNumSubLayersFlag; + bool m_vpsAllIndependentLayersFlag; + bool m_vpsIndependentLayerFlag[MAX_VPS_LAYERS]; + bool m_vpsDirectRefLayerFlag[MAX_VPS_LAYERS][MAX_VPS_LAYERS]; + bool m_vpsEachLayerIsAnOlsFlag; + uint32_t m_vpsOlsModeIdc; + uint32_t m_vpsNumOutputLayerSets; + bool m_vpsOlsOutputLayerFlag[MAX_NUM_OLSS][MAX_VPS_LAYERS]; + uint32_t m_directRefLayerIdx[MAX_VPS_LAYERS][MAX_VPS_LAYERS]; + uint32_t m_generalLayerIdx[MAX_VPS_LAYERS]; + + // stores index ( ilrp_idx within 0 .. NumDirectRefLayers ) of the dependent reference layers + uint32_t m_interLayerRefIdx[MAX_VPS_LAYERS][MAX_VPS_LAYERS]; +#else uint32_t m_vpsIncludedLayerId[MAX_VPS_LAYERS]; +#endif bool m_vpsExtensionFlag; public: @@ -761,11 +817,54 @@ public: uint32_t getMaxLayers() const { return m_uiMaxLayers; } void setMaxLayers(uint32_t l) { m_uiMaxLayers = l; } +#if JVET_P0185 + uint32_t getMaxSubLayers() const { return m_vpsMaxSubLayers; } + void setMaxSubLayers(uint32_t value) { m_vpsMaxSubLayers = value; } +#endif +#if JVET_O1159_SCALABILITY + bool getAllLayersSameNumSublayersFlag() const { return m_vpsAllLayersSameNumSubLayersFlag; } + void setAllLayersSameNumSublayersFlag(bool t) { m_vpsAllLayersSameNumSubLayersFlag = t; } + + uint32_t getLayerId(uint32_t layerIdx) const { return m_vpsLayerId[layerIdx]; } + void setLayerId(uint32_t layerIdx, uint32_t layerId) { m_vpsLayerId[layerIdx] = layerId; } + + bool getAllIndependentLayersFlag() const { return m_vpsAllIndependentLayersFlag; } + void setAllIndependentLayersFlag(bool t) { m_vpsAllIndependentLayersFlag = t; } + + bool getIndependentLayerFlag(uint32_t layerIdx) const { return m_vpsIndependentLayerFlag[layerIdx]; } + void setIndependentLayerFlag(uint32_t layerIdx, bool t) { m_vpsIndependentLayerFlag[layerIdx] = t; } + + bool getDirectRefLayerFlag(uint32_t layerIdx, uint32_t refLayerIdx) const { return m_vpsDirectRefLayerFlag[layerIdx][refLayerIdx]; } + void setDirectRefLayerFlag(uint32_t layerIdx, uint32_t refLayerIdx, bool t) { m_vpsDirectRefLayerFlag[layerIdx][refLayerIdx] = t; } + + uint32_t getDirectRefLayerIdx( uint32_t layerIdx, uint32_t refLayerIdc ) const { return m_directRefLayerIdx[layerIdx][refLayerIdc]; } + void setDirectRefLayerIdx( uint32_t layerIdx, uint32_t refLayerIdc, uint32_t refLayerIdx ) { m_directRefLayerIdx[layerIdx][refLayerIdc] = refLayerIdx; } + + uint32_t getInterLayerRefIdc( uint32_t layerIdx, uint32_t refLayerIdx ) const { return m_interLayerRefIdx[layerIdx][refLayerIdx]; } + void setInterLayerRefIdc( uint32_t layerIdx, uint32_t refLayerIdx, uint32_t refLayerIdc ) { m_interLayerRefIdx[layerIdx][refLayerIdx] = refLayerIdc; } + + uint32_t getGeneralLayerIdx(uint32_t layerId) const { return m_generalLayerIdx[layerId]; } + void setGeneralLayerIdx(uint32_t layerId, uint32_t layerIdc) { m_generalLayerIdx[layerId] = layerIdc; } + + bool getEachLayerIsAnOlsFlag() const { return m_vpsEachLayerIsAnOlsFlag; } + void setEachLayerIsAnOlsFlag(bool t) { m_vpsEachLayerIsAnOlsFlag = t; } + + uint32_t getOlsModeIdc() const { return m_vpsOlsModeIdc; } + void setOlsModeIdc(uint32_t t) { m_vpsOlsModeIdc = t; } + + uint32_t getNumOutputLayerSets() const { return m_vpsNumOutputLayerSets; } + void setNumOutputLayerSets(uint8_t t) { m_vpsNumOutputLayerSets = t; } + + bool getOlsOutputLayerFlag(uint32_t ols, uint32_t layer) const { return m_vpsOlsOutputLayerFlag[ols][layer]; } + void setOlsOutputLayerFlag(uint32_t ols, uint32_t layer, bool t) { m_vpsOlsOutputLayerFlag[ols][layer] = t; } +#else + void setVPSIncludedLayerId(uint32_t v, uint32_t layer) { m_vpsIncludedLayerId[layer] = v; } + uint32_t getVPSIncludedLayerId(uint32_t layer) const { return m_vpsIncludedLayerId[layer]; } +>>>>>>> BD/VVCSoftware_VTM-JVET-O1159_JVET-P1019 +#endif + bool getVPSExtensionFlag() const { return m_vpsExtensionFlag; } void setVPSExtensionFlag(bool t) { m_vpsExtensionFlag = t; } - - void setVPSIncludedLayerId(uint32_t v, uint32_t Layer) { m_vpsIncludedLayerId[Layer] = v; } - uint32_t getVPSIncludedLayerId(uint32_t Layer) const { return m_vpsIncludedLayerId[Layer]; } }; class Window @@ -1140,6 +1239,9 @@ private: #if JVET_P0590_SCALING_WINDOW bool m_rprEnabledFlag; #endif +#if JVET_O1159_SCALABILITY + bool m_interLayerPresentFlag; +#endif public: @@ -1480,9 +1582,14 @@ public: bool getSubLayerParametersPresentFlag() const { return m_SubLayerCbpParametersPresentFlag; } #if JVET_P0590_SCALING_WINDOW - bool getRprEnabledFlag() const { return m_rprEnabledFlag; } - void setRprEnabledFlag( bool flag ) { m_rprEnabledFlag = flag; } + bool getRprEnabledFlag() const { return m_rprEnabledFlag; } + void setRprEnabledFlag( bool flag ) { m_rprEnabledFlag = flag; } +#endif +#if JVET_O1159_SCALABILITY + bool getInterLayerPresentFlag() const { return m_interLayerPresentFlag; } + void setInterLayerPresentFlag( bool b ) { m_interLayerPresentFlag = b; } #endif + }; @@ -1580,6 +1687,10 @@ private: std::vector<uint32_t> m_ctuToTileCol; //!< mapping between CTU horizontal address and tile column index std::vector<uint32_t> m_ctuToTileRow; //!< mapping between CTU vertical address and tile row index bool m_rectSliceFlag; //!< rectangular slice flag +#if JVET_P1024_SINGLE_SLICE_PER_SUBPIC_FLAG + bool m_singleSlicePerSubPicFlag; //!< single slice per sub-picture flag + std::vector<uint32_t> m_ctuToSubPicIdx; //!< mapping between CTU and Sub-picture index +#endif uint32_t m_numSlicesInPic; //!< number of rectangular slices in the picture (raster-scan slice specified at slice level) bool m_tileIdxDeltaPresentFlag; //!< tile index delta present flag std::vector<RectSlice> m_rectSlices; //!< list of rectangular slice signalling parameters @@ -1817,6 +1928,11 @@ public: uint32_t getTileIdx( const Position& pos ) const { return getTileIdx( pos.x / m_ctuSize, pos.y / m_ctuSize ); } void setRectSliceFlag( bool b ) { m_rectSliceFlag = b; } bool getRectSliceFlag( ) const { return m_rectSliceFlag; } +#if JVET_P1024_SINGLE_SLICE_PER_SUBPIC_FLAG + void setSingleSlicePerSubPicFlag( bool b ) { m_singleSlicePerSubPicFlag = b; } + bool getSingleSlicePerSubPicFlag( ) const { return m_singleSlicePerSubPicFlag; } + uint32_t getCtuToSubPicIdx( int idx ) const { CHECK( idx >= m_ctuToSubPicIdx.size(), "CTU address index exceeds valid range" ); return m_ctuToSubPicIdx[idx]; } +#endif void setNumSlicesInPic( uint32_t u ) { CHECK( u > MAX_SLICES, "Number of slices in picture exceeds valid range" ); m_numSlicesInPic = u; } uint32_t getNumSlicesInPic( ) const { return m_numSlicesInPic; } void setTileIdxDeltaPresentFlag( bool b ) { m_tileIdxDeltaPresentFlag = b; } @@ -2711,11 +2827,18 @@ public: void checkLeadingPictureRestrictions( PicList& rcListPic ) const; int checkThatAllRefPicsAreAvailable(PicList& rcListPic, const ReferencePictureList* pRPL, int rplIdx, bool printErrors, int* refPicIndex) const; +#if JVET_O1159_SCALABILITY + void applyReferencePictureListBasedMarking( PicList& rcListPic, const ReferencePictureList *pRPL0, const ReferencePictureList *pRPL1, const int layerId ) const; +#else void applyReferencePictureListBasedMarking( PicList& rcListPic, const ReferencePictureList *pRPL0, const ReferencePictureList *pRPL1 ) const; +#endif bool isTemporalLayerSwitchingPoint( PicList& rcListPic ) const; bool isStepwiseTemporalLayerSwitchingPointCandidate( PicList& rcListPic ) const; int checkThatAllRefPicsAreAvailable(PicList& rcListPic, const ReferencePictureList *pRPL, int rplIdx, bool printErrors) const; +#if !JVET_O1159_SCALABILITY + // this is encoder only function void createExplicitReferencePictureSetFromReference(PicList& rcListPic, const ReferencePictureList *pRPL0, const ReferencePictureList *pRPL1); +#endif #if !JVET_P1006_PICTURE_HEADER void setMaxNumMergeCand(uint32_t val ) { m_maxNumMergeCand = val; } uint32_t getMaxNumMergeCand() const { return m_maxNumMergeCand; } @@ -3067,6 +3190,10 @@ public: ParameterSetManager(); virtual ~ParameterSetManager(); +#if JVET_O1159_SCALABILITY + void storeVPS(VPS *vps, const std::vector<uint8_t> &naluData) { m_vpsMap.storePS(vps->getVPSId(), vps, &naluData); } + VPS* getVPS( int vpsId ) { return m_vpsMap.getPS( vpsId ); }; +#endif void storeDPS(DPS *dps, const std::vector<uint8_t> &naluData) { m_dpsMap.storePS( dps->getDecodingParameterSetId(), dps, &naluData); }; //! get pointer to existing video parameter set diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h index 8fdbc670fd03e510024ed4dcb3ec7009a4230976..02a62ebbd226d94bc0a3e9e2d5f02fe8d24eae57 100644 --- a/source/Lib/CommonLib/TypeDef.h +++ b/source/Lib/CommonLib/TypeDef.h @@ -52,8 +52,12 @@ #define FIELD_CODING_FIX 1 // Fix field coding +#define JVET_P1024_SINGLE_SLICE_PER_SUBPIC_FLAG 1 // JVET-P1024: single_slice_per_subpic_flag in the PPS + #define JVET_P1038_ALF_PAD_RASTER_SLICE 1 // JVET-P1038, handle ALF padding in raster scan slice +#define JVET_P1019_OUTPUT_LAYER_SET 1 // JVET-P1019: Signaling of output layer set (OLS) and its output process + #define JVET_P0257_SCALING_LISTS_SPEEDUP_DEC 1 // JVET-P0257: Decoder speed-up for handling scaling matrices #define JVET_P2001_REMOVE_TRANSQUANT_BYPASS 1 // JVET-P2001: Remove transquant bypass - not supported in JVET-P2001 draft text @@ -149,6 +153,8 @@ #define JVET_N0278_FIXES 1 // Working draft 5 independent layers +#define JVET_O1159_SCALABILITY 1 // JVET-O1159: Scalability + #define JVET_P0325_CHANGE_MERGE_CANDIDATE_ORDER 1 // JVET-P0325: reorder the spatial merge candidates #define JVET_P0984_SEI_SUBPIC_LEVEL 1 // JVET-P0984: Subpicture level information SEI @@ -255,6 +261,13 @@ #define JVET_P0478_PTL_DPS 1 // JVET-P0478: allow multiple PTL in DPS +#define JVET_P0446_CONCATENATION 1 // concatenation info in BP SEI +#define JVET_P0446_ALT_CPB 1 // alternative CPB parameters +#define JVET_P0446_BP_CPB_CNT_FIX 1 // bp_cpb_cnt is not an array according to the spec text +#if JVET_P0446_ALT_CPB && !JVET_P0446_BP_CPB_CNT_FIX +#error JVET_P0446_BP_CPB_CNT_FIX must be enabled for JVET_P0446_ALT_CPB +#endif + #define JVET_M0497_MATRIX_MULT 0 // 0: Fast method; 1: Matrix multiplication #define JVET_P0181 1 // JVET-P0181 : Modifications to HRD information signalling @@ -270,13 +283,15 @@ #define JVET_P0171_SUBPICTURE_LAYOUT 1 //JVET-P0171: subpicture layout +#define JVET_P0185 1 // Infer vps_max_layers_minus1 to be equal to 0 when not present and also signal vps_max_sub_layers_minus1 + #define HEVC_SEI 0 // SEI messages that are defined in HEVC, but not in VVC typedef std::pair<int, bool> TrMode; typedef std::pair<int, int> TrCost; // clang-format off -#define REUSE_CU_RESULTS 1 +#define REUSE_CU_RESULTS 1 #if REUSE_CU_RESULTS #define REUSE_CU_RESULTS_WITH_MULTIPLE_TUS 1 #endif diff --git a/source/Lib/CommonLib/UnitTools.cpp b/source/Lib/CommonLib/UnitTools.cpp index b94a99e8303f2110e882e62b7894d702d7184a8b..906dde81f140f6db78da2f6c953d8d05c7d6ff1c 100644 --- a/source/Lib/CommonLib/UnitTools.cpp +++ b/source/Lib/CommonLib/UnitTools.cpp @@ -1404,7 +1404,7 @@ bool PU::checkDMVRCondition(const PredictionUnit& pu) && ((pu.lheight() * pu.lwidth()) >= 128) && (pu.cu->BcwIdx == BCW_DEFAULT) && ((!wp0[COMPONENT_Y].bPresentFlag) && (!wp1[COMPONENT_Y].bPresentFlag)) -#if JVET_P0590_SCALING_WINDOW +#if JVET_P0590_SCALING_WINDOW || JVET_O1159_SCALABILITY && ( refIdx0 < 0 ? true : pu.cu->slice->getScalingRatio( REF_PIC_LIST_0, refIdx0 ) == SCALE_1X ) && ( refIdx1 < 0 ? true : pu.cu->slice->getScalingRatio( REF_PIC_LIST_1, refIdx1 ) == SCALE_1X ) #else && PU::isRefPicSameSize( pu ) @@ -4080,7 +4080,7 @@ bool allowLfnstWithMip(const Size& block) return false; } -#if !JVET_P0590_SCALING_WINDOW +#if !JVET_P0590_SCALING_WINDOW && !JVET_O1159_SCALABILITY bool PU::isRefPicSameSize( const PredictionUnit& pu ) { bool samePicSize = true; diff --git a/source/Lib/CommonLib/UnitTools.h b/source/Lib/CommonLib/UnitTools.h index 756377f247639ea5cc6ea1ce6dc4b0b44a289717..35fe75ca62d41a60ad1f28860cf541c52a5560f1 100644 --- a/source/Lib/CommonLib/UnitTools.h +++ b/source/Lib/CommonLib/UnitTools.h @@ -196,7 +196,7 @@ namespace PU bool getDerivedBV(PredictionUnit &pu, const Mv& currentMv, Mv& derivedMv); bool checkDMVRCondition(const PredictionUnit& pu); -#if !JVET_P0590_SCALING_WINDOW +#if !JVET_P0590_SCALING_WINDOW && !JVET_O1159_SCALABILITY bool isRefPicSameSize( const PredictionUnit& pu ); #endif } diff --git a/source/Lib/DecoderLib/DecLib.cpp b/source/Lib/DecoderLib/DecLib.cpp index 006550aeedd2b457ad4f078a6c7a6ef79ee1d30c..7d9e41875f4903781003fcc39c2ec270bd7df661 100644 --- a/source/Lib/DecoderLib/DecLib.cpp +++ b/source/Lib/DecoderLib/DecLib.cpp @@ -443,10 +443,11 @@ DecLib::~DecLib() m_prefixSEINALUs.pop_front(); } -#if JVET_N0278_FIXES +#if JVET_N0278_FIXES && !JVET_O1159_SCALABILITY if( m_vps != nullptr ) { delete m_vps; + m_vps = nullptr; } #endif } @@ -698,6 +699,15 @@ void DecLib::finishPicture(int& poc, PicList*& rpcListPic, MsgLevel msgl ) else msg( msgl, "%d ", pcSlice->getRefPOC( RefPicList( iRefList ), iRefIndex ) ); } + +#if JVET_O1159_SCALABILITY + if( pcSlice->getRefPOC( RefPicList( iRefList ), iRefIndex ) == pcSlice->getPOC() ) + { + msg( msgl, ".%d", pcSlice->getRefPic( RefPicList( iRefList ), iRefIndex )->layerId ); + } +#endif + + msg( msgl, " " ); } msg( msgl, "] "); } @@ -1054,6 +1064,10 @@ void DecLib::xActivateParameterSets() const SPS *sps = m_parameterSetManager.getSPS(pps->getSPSId()); // this is a temporary SPS object. Do not store this value CHECK(sps == 0, "No SPS present"); +#if JVET_O1159_SCALABILITY + const VPS *vps = sps->getVPSId() ? m_parameterSetManager.getVPS( sps->getVPSId() ) : nullptr; +#endif + if (NULL == pps->pcv) { #if JVET_P1006_PICTURE_HEADER @@ -1106,9 +1120,17 @@ void DecLib::xActivateParameterSets() m_pcPic = xGetNewPicBuffer (*sps, *pps, m_apcSlicePilot->getTLayer()); #endif +#if JVET_O1159_SCALABILITY + m_apcSlicePilot->applyReferencePictureListBasedMarking( m_cListPic, m_apcSlicePilot->getRPL0(), m_apcSlicePilot->getRPL1(), layerId ); +#else m_apcSlicePilot->applyReferencePictureListBasedMarking(m_cListPic, m_apcSlicePilot->getRPL0(), m_apcSlicePilot->getRPL1()); +#endif #if JVET_P1006_PICTURE_HEADER +#if JVET_O1159_SCALABILITY + m_pcPic->finalInit( vps, *sps, *pps, &m_picHeader, apss, lmcsAPS, scalinglistAPS ); +#else m_pcPic->finalInit( *sps, *pps, &m_picHeader, apss, lmcsAPS, scalinglistAPS ); +#endif #else m_pcPic->finalInit( *sps, *pps, apss, lmcsAPS, scalinglistAPS ); #endif @@ -1138,6 +1160,9 @@ void DecLib::xActivateParameterSets() m_pcPic->cs->slice = pSlice; m_pcPic->cs->sps = sps; m_pcPic->cs->pps = pps; +#if JVET_O1159_SCALABILITY + m_pcPic->cs->vps = vps; +#endif memcpy(m_pcPic->cs->alfApss, apss, sizeof(m_pcPic->cs->alfApss)); m_pcPic->cs->lmcsAps = lmcsAPS; @@ -1959,15 +1984,22 @@ bool DecLib::xDecodeSlice(InputNALUnit &nalu, int &iSkipFrame, int iPOCLastDispl void DecLib::xDecodeVPS( InputNALUnit& nalu ) { #if JVET_N0278_FIXES +#if JVET_O1159_SCALABILITY + m_vps = new VPS(); +#else if( m_vps == nullptr ) { m_vps = new VPS(); } +#endif m_HLSReader.setBitstream( &nalu.getBitstream() ); CHECK( nalu.m_temporalId, "The value of TemporalId of VPS NAL units shall be equal to 0" ); m_HLSReader.parseVPS( m_vps ); +#if JVET_O1159_SCALABILITY + m_parameterSetManager.storeVPS( m_vps, nalu.getBitstream().getFifo()); +#endif #else VPS* vps = new VPS(); m_HLSReader.setBitstream( &nalu.getBitstream() ); @@ -2032,11 +2064,13 @@ bool DecLib::decode(InputNALUnit& nalu, int& iSkipFrame, int& iPOCLastDisplay) { bool ret; // ignore all NAL units of layers > 0 +#if !JVET_P1019_OUTPUT_LAYER_SET if (getTargetDecLayer() >= 0 && nalu.m_nuhLayerId != getTargetDecLayer()) //TBC: ignore bitstreams whose nuh_layer_id is not the target layer id { msg( WARNING, "Warning: found NAL unit with nuh_layer_id equal to %d. Ignoring.\n", nalu.m_nuhLayerId); return false; } +#endif m_accessUnitNals.push_back( std::pair<NalUnitType, int>( nalu.m_nalUnitType, nalu.m_temporalId ) ); diff --git a/source/Lib/DecoderLib/DecLib.h b/source/Lib/DecoderLib/DecLib.h index bf4c3f3ef97250efd0d407bc7df4c74fb5332110..113d421847faa0a5c0dfeeddbad53a0d6818b8dd 100644 --- a/source/Lib/DecoderLib/DecLib.h +++ b/source/Lib/DecoderLib/DecLib.h @@ -85,7 +85,9 @@ private: SEIMessages m_SEIs; ///< List of SEI messages that have been received before the first slice and between slices, excluding prefix SEIs... +#if !JVET_P1019_OUTPUT_LAYER_SET int m_iTargetLayer; ///< target stream layer to be decoded +#endif // functional classes IntraPrediction m_cIntraPred; @@ -173,8 +175,10 @@ public: void checkNalUnitConstraints( uint32_t naluType ); #endif - void setTargetDecLayer (int val) { m_iTargetLayer = val; } - int getTargetDecLayer() { return m_iTargetLayer; } +#if !JVET_P1019_OUTPUT_LAYER_SET + void setTargetDecLayer(int val) { m_iTargetLayer = val; } + int getTargetDecLayer() { return m_iTargetLayer; } +#endif bool getNoOutputPriorPicsFlag () const { return m_isNoOutputPriorPics; } void setNoOutputPriorPicsFlag (bool val) { m_isNoOutputPriorPics = val; } diff --git a/source/Lib/DecoderLib/SEIread.cpp b/source/Lib/DecoderLib/SEIread.cpp index ef4b1348e166eb1af96b31b88bac028ce45de77e..f8e813497a727385b1d7f68451adcdca12ae0ae1 100644 --- a/source/Lib/DecoderLib/SEIread.cpp +++ b/source/Lib/DecoderLib/SEIread.cpp @@ -670,6 +670,9 @@ void SEIReader::xParseSEIBufferingPeriod(SEIBufferingPeriod& sei, uint32_t paylo sei_read_code( pDecodedMessageOutputStream, 5, code, "initial_cpb_removal_delay_length_minus1" ); sei.m_initialCpbRemovalDelayLength = code + 1; sei_read_code( pDecodedMessageOutputStream, 5, code, "cpb_removal_delay_length_minus1" ); sei.m_cpbRemovalDelayLength = code + 1; sei_read_code( pDecodedMessageOutputStream, 5, code, "dpb_output_delay_length_minus1" ); sei.m_dpbOutputDelayLength = code + 1; +#if JVET_P0446_ALT_CPB + sei_read_flag( pDecodedMessageOutputStream, code, "alt_cpb_params_present_flag"); sei.m_altCpbParamsPresentFlag = code; +#endif sei_read_flag( pDecodedMessageOutputStream, code, "bp_decoding_unit_hrd_params_present_flag" ); sei.m_bpDecodingUnitHrdParamsPresentFlag = code; if( sei.m_bpDecodingUnitHrdParamsPresentFlag ) { @@ -700,6 +703,16 @@ void SEIReader::xParseSEIBufferingPeriod(SEIBufferingPeriod& sei, uint32_t paylo sei_read_flag( pDecodedMessageOutputStream, code, "concatenation_flag"); sei.m_concatenationFlag = code; +#if JVET_P0446_CONCATENATION + sei_read_flag ( pDecodedMessageOutputStream, code, "additional_concatenation_info_present_flag"); + sei.m_additionalConcatenationInfoPresentFlag = code; + if (sei.m_additionalConcatenationInfoPresentFlag) + { + sei_read_code( pDecodedMessageOutputStream, sei.m_initialCpbRemovalDelayLength, code, "max_initial_removal_delay_for_concatenation" ); + sei.m_maxInitialRemovalDelayForConcatenation = code; + } +#endif + sei_read_code( pDecodedMessageOutputStream, ( sei.m_cpbRemovalDelayLength ), code, "au_cpb_removal_delay_delta_minus1" ); sei.m_auCpbRemovalDelayDelta = code + 1; sei_read_flag( pDecodedMessageOutputStream, code, "cpb_removal_delay_deltas_present_flag" ); sei.m_cpbRemovalDelayDeltasPresentFlag = code; @@ -713,6 +726,9 @@ void SEIReader::xParseSEIBufferingPeriod(SEIBufferingPeriod& sei, uint32_t paylo } } sei_read_code( pDecodedMessageOutputStream, 3, code, "bp_max_sub_layers_minus1" ); sei.m_bpMaxSubLayers = code + 1; +#if JVET_P0446_BP_CPB_CNT_FIX + sei_read_uvlc( pDecodedMessageOutputStream, code, "bp_cpb_cnt_minus1" ); sei.m_bpCpbCnt = code + 1; +#endif #if JVET_P0181 sei_read_flag(pDecodedMessageOutputStream, code, "sublayer_initial_cpb_removal_delay_present_flag"); sei.m_sublayerInitialCpbRemovalDelayPresentFlag = code; @@ -721,13 +737,19 @@ void SEIReader::xParseSEIBufferingPeriod(SEIBufferingPeriod& sei, uint32_t paylo for (i = 0; i < sei.m_bpMaxSubLayers; i++) #endif { +#if !JVET_P0446_BP_CPB_CNT_FIX sei_read_uvlc( pDecodedMessageOutputStream, code, "bp_cpb_cnt_minus1[i]" ); sei.m_bpCpbCnt[i] = code + 1; +#endif for( nalOrVcl = 0; nalOrVcl < 2; nalOrVcl ++ ) { if( ( ( nalOrVcl == 0 ) && ( sei.m_bpNalCpbParamsPresentFlag ) ) || ( ( nalOrVcl == 1 ) && ( sei.m_bpVclCpbParamsPresentFlag ) ) ) { +#if JVET_P0446_BP_CPB_CNT_FIX + for( int j = 0; j < ( sei.m_bpCpbCnt ); j ++ ) +#else for( int j = 0; j < ( sei.m_bpCpbCnt[i] ); j ++ ) +#endif { sei_read_code( pDecodedMessageOutputStream, sei.m_initialCpbRemovalDelayLength, code, nalOrVcl ? "vcl_initial_cpb_removal_delay[i][j]" : "nal_initial_cpb_removal_delay[i][j]" ); sei.m_initialCpbRemovalDelay[i][j][nalOrVcl] = code; @@ -737,6 +759,13 @@ void SEIReader::xParseSEIBufferingPeriod(SEIBufferingPeriod& sei, uint32_t paylo } } } +#if JVET_P0446_ALT_CPB + if (sei.m_altCpbParamsPresentFlag) + { + sei_read_flag(pDecodedMessageOutputStream, code, "use_alt_cpb_params_flag"); sei.m_useAltCpbParamsFlag = code; + } +#endif + } #if JVET_P0202_P0203_FIX_HRD_RELATED_SEI @@ -755,6 +784,33 @@ void SEIReader::xParseSEIPictureTiming(SEIPictureTiming& sei, uint32_t payloadSi #if JVET_P0202_P0203_FIX_HRD_RELATED_SEI sei_read_code( pDecodedMessageOutputStream, bp.m_cpbRemovalDelayLength, symbol, "cpb_removal_delay_minus1[bp_max_sub_layers_minus1]" ); sei.m_auCpbRemovalDelay[bp.m_bpMaxSubLayers - 1] = symbol + 1; + +#if JVET_P0446_ALT_CPB + if( bp.m_altCpbParamsPresentFlag ) + { + sei_read_flag( pDecodedMessageOutputStream, symbol, "cpb_alt_timing_info_present_flag" ); sei.m_cpbAltTimingInfoPresentFlag = symbol; + if( sei.m_cpbAltTimingInfoPresentFlag ) + { + sei.m_cpbAltInitialCpbRemovalDelayDelta.resize(bp.m_bpCpbCnt); + sei.m_cpbAltInitialCpbRemovalOffsetDelta.resize(bp.m_bpCpbCnt); + for( int i = 0; i < bp.m_bpCpbCnt; i++ ) + { + sei_read_code( pDecodedMessageOutputStream, bp.m_initialCpbRemovalDelayLength, symbol, "cpb_alt_initial_cpb_removal_delay_delta[ i ]" ); + sei.m_cpbAltInitialCpbRemovalDelayDelta[i]= symbol; + sei_read_code( pDecodedMessageOutputStream, bp.m_initialCpbRemovalDelayLength, symbol, "cpb_alt_initial_cpb_removal_offset_delta[ i ]" ); + sei.m_cpbAltInitialCpbRemovalOffsetDelta[i]= symbol; + } + sei_read_code( pDecodedMessageOutputStream, bp.m_initialCpbRemovalDelayLength, sei.m_cpbDelayOffset, "cpb_delay_offset" ); + sei_read_code( pDecodedMessageOutputStream, bp.m_initialCpbRemovalDelayLength, sei.m_dpbDelayOffset, "dpb_delay_offset" ); + } + } + else + { + sei.m_cpbAltTimingInfoPresentFlag = false; + sei.m_cpbDelayOffset = sei.m_dpbDelayOffset = 0; + } +#endif + for( int i = temporalId; i < bp.m_bpMaxSubLayers - 1; i ++ ) { sei_read_flag( pDecodedMessageOutputStream, symbol, "pt_sub_layer_delays_present_flag[i]" ); sei.m_ptSubLayerDelaysPresentFlag[i] = (symbol == 1); diff --git a/source/Lib/DecoderLib/VLCReader.cpp b/source/Lib/DecoderLib/VLCReader.cpp index 563799eb0bf378d8f422f973d3999262ecc53fc8..237656a419f4d09f15cdd4e18fb036b083ad0e62 100644 --- a/source/Lib/DecoderLib/VLCReader.cpp +++ b/source/Lib/DecoderLib/VLCReader.cpp @@ -300,14 +300,27 @@ void HLSyntaxReader::copyRefPicList(SPS* sps, ReferencePictureList* source_rpl, { dest_rp->setNumberOfShorttermPictures(source_rpl->getNumberOfShorttermPictures()); - if (sps->getLongTermRefsPresent()) - dest_rp->setNumberOfLongtermPictures(dest_rp->getNumberOfLongtermPictures()); +#if JVET_O1159_SCALABILITY + dest_rp->setNumberOfInterLayerPictures( sps->getInterLayerPresentFlag() ? dest_rp->getNumberOfInterLayerPictures() : 0 ); +#endif + + if( sps->getLongTermRefsPresent() ) + { + dest_rp->setNumberOfLongtermPictures( dest_rp->getNumberOfLongtermPictures() ); + } else dest_rp->setNumberOfLongtermPictures(0); uint32_t numRefPic = dest_rp->getNumberOfShorttermPictures() + dest_rp->getNumberOfLongtermPictures(); - for (int ii = 0; ii < numRefPic; ii++) - dest_rp->setRefPicIdentifier(ii, source_rpl->getRefPicIdentifier(ii), source_rpl->isRefPicLongterm(ii)); + + for( int ii = 0; ii < numRefPic; ii++ ) + { +#if JVET_O1159_SCALABILITY + dest_rp->setRefPicIdentifier( ii, source_rpl->getRefPicIdentifier( ii ), source_rpl->isRefPicLongterm( ii ), source_rpl->isInterLayerRefPic( ii ), source_rpl->getInterLayerRefPicIdx( ii ) ); +#else + dest_rp->setRefPicIdentifier( ii, source_rpl->getRefPicIdentifier( ii ), source_rpl->isRefPicLongterm( ii ) ); +#endif + } } void HLSyntaxReader::parseRefPicList(SPS* sps, ReferencePictureList* rpl) @@ -317,6 +330,9 @@ void HLSyntaxReader::parseRefPicList(SPS* sps, ReferencePictureList* rpl) uint32_t numRefPic = code; uint32_t numStrp = 0; uint32_t numLtrp = 0; +#if JVET_O1159_SCALABILITY + uint32_t numIlrp = 0; +#endif if (sps->getLongTermRefsPresent()) { @@ -329,8 +345,30 @@ void HLSyntaxReader::parseRefPicList(SPS* sps, ReferencePictureList* rpl) int deltaValue = 0; bool firstSTRP = true; +#if JVET_O1159_SCALABILITY + rpl->setInterLayerPresentFlag( sps->getInterLayerPresentFlag() ); +#endif + for (int ii = 0; ii < numRefPic; ii++) { +#if JVET_O1159_SCALABILITY + uint32_t isInterLayerRefPic = 0; + + if( rpl->getInterLayerPresentFlag() ) + { + READ_FLAG( isInterLayerRefPic, "inter_layer_ref_pic_flag[ listIdx ][ rplsIdx ][ i ]" ); + + if( isInterLayerRefPic ) + { + READ_UVLC( code, "ilrp_idx[ listIdx ][ rplsIdx ][ i ]" ); + rpl->setRefPicIdentifier( ii, 0, true, true, code ); + numIlrp++; + } + } + + if( !isInterLayerRefPic ) + { +#endif isLongTerm = false; if (sps->getLongTermRefsPresent()) { @@ -363,19 +401,34 @@ void HLSyntaxReader::parseRefPicList(SPS* sps, ReferencePictureList* rpl) deltaValue = prevDelta + readValue; prevDelta = deltaValue; } + +#if JVET_O1159_SCALABILITY + rpl->setRefPicIdentifier( ii, deltaValue, isLongTerm, false, 0 ); +#else rpl->setRefPicIdentifier(ii, deltaValue, isLongTerm); +#endif numStrp++; } else { if (!rpl->getLtrpInSliceHeaderFlag()) READ_CODE(sps->getBitsForPOC(), code, "poc_lsb_lt[listIdx][rplsIdx][j]"); +#if JVET_O1159_SCALABILITY + rpl->setRefPicIdentifier( ii, deltaValue, isLongTerm, false, 0 ); +#else rpl->setRefPicIdentifier(ii, code, isLongTerm); +#endif numLtrp++; } +#if JVET_O1159_SCALABILITY + } +#endif } rpl->setNumberOfShorttermPictures(numStrp); rpl->setNumberOfLongtermPictures(numLtrp); +#if JVET_O1159_SCALABILITY + rpl->setNumberOfInterLayerPictures( numIlrp ); +#endif } void HLSyntaxReader::parsePPS( PPS* pcPPS, ParameterSetManager *parameterSetManager ) @@ -481,7 +534,15 @@ void HLSyntaxReader::parsePPS( PPS* pcPPS, ParameterSetManager *parameterSetMana // rectangular slice signalling READ_CODE(1, uiCode, "rect_slice_flag"); pcPPS->setRectSliceFlag( uiCode == 1 ); - if( pcPPS->getRectSliceFlag() ) +#if JVET_P1024_SINGLE_SLICE_PER_SUBPIC_FLAG + if (pcPPS->getRectSliceFlag()) + { + READ_FLAG(uiCode, "single_slice_per_subpic_flag"); pcPPS->setSingleSlicePerSubPicFlag(uiCode == 1); + } + if (pcPPS->getRectSliceFlag() & !(pcPPS->getSingleSlicePerSubPicFlag())) +#else + if (pcPPS->getRectSliceFlag()) +#endif { int32_t tileIdx = 0; @@ -1578,6 +1639,9 @@ void HLSyntaxReader::parseSPS(SPS* pcSPS) } READ_FLAG(uiCode, "long_term_ref_pics_flag"); pcSPS->setLongTermRefsPresent(uiCode); +#if JVET_O1159_SCALABILITY + READ_FLAG( uiCode, "inter_layer_ref_pics_present_flag" ); pcSPS->setInterLayerPresentFlag( uiCode ); +#endif #if JVET_P2001_SYNTAX_ORDER_MISMATCHES READ_FLAG( uiCode, "sps_idr_rpl_present_flag" ); pcSPS->setIDRRefParamListPresent( (bool) uiCode ); #endif @@ -2147,13 +2211,92 @@ void HLSyntaxReader::parseVPS(VPS* pcVPS) READ_CODE(4, uiCode, "vps_video_parameter_set_id"); pcVPS->setVPSId(uiCode); #endif +#if JVET_O1159_SCALABILITY + READ_CODE(6, uiCode, "vps_max_layers_minus1"); pcVPS->setMaxLayers(uiCode + 1); CHECK(uiCode + 1 > MAX_VPS_LAYERS, "Invalid code"); + if (pcVPS->getMaxLayers() - 1 == 0) + { + pcVPS->setEachLayerIsAnOlsFlag(1); + } + READ_CODE(3, uiCode, "vps_max_sublayers_minus1"); pcVPS->setMaxSubLayers(uiCode + 1); CHECK(uiCode + 1 > MAX_VPS_SUBLAYERS, "Invalid code"); + if( pcVPS->getMaxLayers() > 1 && pcVPS->getMaxSubLayers() > 1) + { + READ_FLAG(uiCode, "vps_all_layers_same_num_sublayers_flag"); pcVPS->setAllLayersSameNumSublayersFlag(uiCode); + } + else + { + pcVPS->setAllLayersSameNumSublayersFlag(1); + } + if( pcVPS->getMaxLayers() > 1 ) + { + READ_FLAG(uiCode, "vps_all_independent_layers_flag"); pcVPS->setAllIndependentLayersFlag(uiCode); + if (pcVPS->getAllIndependentLayersFlag() == 0) + { + pcVPS->setEachLayerIsAnOlsFlag(0); + } + } + for (uint32_t i = 0; i < pcVPS->getMaxLayers(); i++) + { + READ_CODE(6, uiCode, "vps_layer_id"); pcVPS->setLayerId(i, uiCode); + pcVPS->setGeneralLayerIdx(uiCode, i); + + if (i > 0 && !pcVPS->getAllIndependentLayersFlag()) + { + READ_FLAG(uiCode, "vps_independent_layer_flag"); pcVPS->setIndependentLayerFlag(i, uiCode); + if (!pcVPS->getIndependentLayerFlag(i)) + { + for (int j = 0, k = 0; j < i; j++) + { + READ_FLAG(uiCode, "vps_direct_dependency_flag"); pcVPS->setDirectRefLayerFlag(i, j, uiCode); + if( uiCode ) + { + pcVPS->setInterLayerRefIdc( i, j, k ); + pcVPS->setDirectRefLayerIdx( i, k++, j ); + } + } + } + } + } + + if (pcVPS->getMaxLayers() > 1) + { + if (pcVPS->getAllIndependentLayersFlag()) + { + READ_FLAG(uiCode, "vps_each_layer_is_an_ols_flag"); pcVPS->setEachLayerIsAnOlsFlag(uiCode); + if (pcVPS->getEachLayerIsAnOlsFlag() == 0) + { + pcVPS->setOlsModeIdc(2); + } + } + if (!pcVPS->getEachLayerIsAnOlsFlag()) + { + if (!pcVPS->getAllIndependentLayersFlag()) + { + READ_CODE(2, uiCode, "vps_ols_mode_idc"); pcVPS->setOlsModeIdc(uiCode); CHECK(uiCode > MAX_VPS_OLS_MODE_IDC, "Invalid code"); + } + if (pcVPS->getOlsModeIdc() == 2) + { + READ_CODE(8, uiCode, "num_output_layer_sets_minus1"); pcVPS->setNumOutputLayerSets(uiCode + 1); + for (uint32_t i = 1; i <= pcVPS->getNumOutputLayerSets() - 1; i++) + { + for (uint32_t j = 0; j < pcVPS->getMaxLayers(); j++) + { + READ_FLAG(uiCode, "vps_ols_output_layer_flag"); pcVPS->setOlsOutputLayerFlag(i, j, uiCode); + } + } + } + } + } +#else READ_CODE(8, uiCode, "vps_max_layers_minus1"); pcVPS->setMaxLayers(uiCode + 1); CHECK(uiCode + 1 > MAX_VPS_LAYERS, "Invalid code"); +#if JVET_P0185 + READ_CODE(3, uiCode, "vps_max_sub_layers_minus1"); pcVPS->setMaxSubLayers(uiCode + 1); +#endif for (uint32_t i = 0; i <= pcVPS->getMaxLayers() - 1; i++) { READ_CODE(7, uiCode, "vps_included_layer_id"); pcVPS->setVPSIncludedLayerId(uiCode, i); READ_FLAG(uiCode, "vps_reserved_zero_1bit"); } - +#endif READ_FLAG(uiCode, "vps_extension_flag"); if (uiCode) { @@ -2390,7 +2533,11 @@ void HLSyntaxReader::parsePictureHeader( PicHeader* picHeader, ParameterSetManag if (picHeader->getRPL( listIdx )->getLtrpInSliceHeaderFlag()) { READ_CODE(sps->getBitsForPOC(), uiCode, "pic_poc_lsb_lt[i][j]"); +#if JVET_O1159_SCALABILITY + picHeader->getLocalRPL( listIdx )->setRefPicIdentifier( i, uiCode, true, false, 0 ); +#else picHeader->getLocalRPL( listIdx )->setRefPicIdentifier(i, uiCode, true); +#endif } READ_FLAG(uiCode, "pic_delta_poc_msb_present_flag[i][j]"); picHeader->getLocalRPL( listIdx )->setDeltaPocMSBPresentFlag(i, uiCode ? true : false); @@ -3236,7 +3383,11 @@ void HLSyntaxReader::parseSliceHeader (Slice* pcSlice, ParameterSetManager *para if (pcSlice->getRPL0()->getLtrpInSliceHeaderFlag()) { READ_CODE(sps->getBitsForPOC(), uiCode, "slice_poc_lsb_lt[i][j]"); +#if JVET_O1159_SCALABILITY + pcSlice->getLocalRPL0()->setRefPicIdentifier( i, uiCode, true, false, 0 ); +#else pcSlice->getLocalRPL0()->setRefPicIdentifier(i, uiCode, true); +#endif } READ_FLAG(uiCode, "delta_poc_msb_present_flag[i][j]"); pcSlice->getLocalRPL0()->setDeltaPocMSBPresentFlag(i, uiCode ? true : false); @@ -3321,7 +3472,11 @@ void HLSyntaxReader::parseSliceHeader (Slice* pcSlice, ParameterSetManager *para if (pcSlice->getRPL1()->getLtrpInSliceHeaderFlag()) { READ_CODE(sps->getBitsForPOC(), uiCode, "slice_poc_lsb_lt[i][j]"); +#if JVET_O1159_SCALABILITY + pcSlice->getLocalRPL0()->setRefPicIdentifier( i, uiCode, true, false, 0 ); +#else pcSlice->getLocalRPL1()->setRefPicIdentifier(i, uiCode, true); +#endif } READ_FLAG(uiCode, "delta_poc_msb_present_flag[i][j]"); pcSlice->getLocalRPL1()->setDeltaPocMSBPresentFlag(i, uiCode ? true : false); diff --git a/source/Lib/EncoderLib/EncAdaptiveLoopFilter.cpp b/source/Lib/EncoderLib/EncAdaptiveLoopFilter.cpp index 445ff7e8bed8aa33e7c0b229cbc9f9d3e16f1d21..187e73f16ef13b6686daa624241378c2f3e87325 100644 --- a/source/Lib/EncoderLib/EncAdaptiveLoopFilter.cpp +++ b/source/Lib/EncoderLib/EncAdaptiveLoopFilter.cpp @@ -649,7 +649,11 @@ void EncAdaptiveLoopFilter::ALFProcess(CodingStructure& cs, const double *lambda ) { #if JVET_N0278_FIXES +#if JVET_O1159_SCALABILITY + int layerIdx = cs.vps == nullptr ? 0 : cs.vps->getGeneralLayerIdx( cs.slice->getPic()->layerId ); +#else int layerIdx = cs.slice->getPic()->layerId; //VS: layerId should be converted to layerIdx +#endif // IRAP AU is assumed if( !layerIdx && ( cs.slice->getPendingRasInit() || cs.slice->isIDRorBLA() ) ) diff --git a/source/Lib/EncoderLib/EncCfg.h b/source/Lib/EncoderLib/EncCfg.h index 9c89c5b391f8584b46097df24465af2e398d852f..6d555f0086fcccb6b3c7cdeeac726c7b5abe8246 100644 --- a/source/Lib/EncoderLib/EncCfg.h +++ b/source/Lib/EncoderLib/EncCfg.h @@ -522,7 +522,10 @@ protected: std::vector<int> m_tileColumnWidth; std::vector<int> m_tileRowHeight; #endif - +#if JVET_P1024_SINGLE_SLICE_PER_SUBPIC_FLAG + //====== Sub-picture and Slices ======== + bool m_singleSlicePerSubPicFlag; +#endif bool m_entropyCodingSyncEnabledFlag; #if !JVET_P1004_REMOVE_BRICKS @@ -850,6 +853,9 @@ protected: bool m_rprEnabled; int m_switchPocPeriod; int m_upscaledOutput; +#if JVET_O1159_SCALABILITY + int m_numRefLayers[MAX_VPS_LAYERS]; +#endif public: EncCfg() @@ -1498,7 +1504,11 @@ public: void setLFCrossSliceBoundaryFlag ( bool bValue ) { m_bLFCrossSliceBoundaryFlag = bValue; } bool getLFCrossSliceBoundaryFlag () { return m_bLFCrossSliceBoundaryFlag; } #endif - +#if JVET_P1024_SINGLE_SLICE_PER_SUBPIC_FLAG + //====== Sub-picture and Slices ======== + void setSingleSlicePerSubPicFlagFlag( bool b ) { m_singleSlicePerSubPicFlag = b; } + bool getSingleSlicePerSubPicFlagFlag( ) { return m_singleSlicePerSubPicFlag; } +#endif void setUseSAO (bool bVal) { m_bUseSAO = bVal; } bool getUseSAO () { return m_bUseSAO; } void setTestSAODisableAtPictureLevel (bool bVal) { m_bTestSAODisableAtPictureLevel = bVal; } @@ -2153,6 +2163,11 @@ public: void setSwitchPocPeriod( int p ) { m_switchPocPeriod = p;} void setUpscaledOutput( int b ) { m_upscaledOutput = b; } int getUpscaledOutput() const { return m_upscaledOutput; } + +#if JVET_O1159_SCALABILITY + void setNumRefLayers( int* numRefLayers ) { std::memcpy( m_numRefLayers, numRefLayers, sizeof( m_numRefLayers ) ); } + int getNumRefLayers( int layerIdx ) const { return m_numRefLayers[layerIdx]; } +#endif }; //! \} diff --git a/source/Lib/EncoderLib/EncGOP.cpp b/source/Lib/EncoderLib/EncGOP.cpp index a9b93ae60b55e9f43c688fe53b991a616b4355d7..a631486e03c1cf98bfadbc8dd6b3c4b74029659d 100644 --- a/source/Lib/EncoderLib/EncGOP.cpp +++ b/source/Lib/EncoderLib/EncGOP.cpp @@ -332,11 +332,17 @@ int EncGOP::xWriteDPS (AccessUnit &accessUnit, const DPS *dps) } } - +#if JVET_O1159_SCALABILITY +int EncGOP::xWriteSPS( AccessUnit &accessUnit, const SPS *sps, const int layerId ) +#else int EncGOP::xWriteSPS (AccessUnit &accessUnit, const SPS *sps) +#endif { OutputNALUnit nalu(NAL_UNIT_SPS); m_HLSWriter->setBitstream( &nalu.m_Bitstream ); +#if JVET_O1159_SCALABILITY + nalu.m_nuhLayerId = layerId; +#endif CHECK( nalu.m_temporalId, "The value of TemporalId of SPS NAL units shall be equal to 0" ); m_HLSWriter->codeSPS( sps ); accessUnit.push_back(new NALUnitEBSP(nalu)); @@ -396,7 +402,11 @@ int EncGOP::xWriteParameterSets( AccessUnit &accessUnit, Slice *slice, const boo if( m_pcEncLib->SPSNeedsWriting( slice->getSPS()->getSPSId() ) ) // Note this assumes that all changes to the SPS are made at the EncLib level prior to picture creation (EncLib::xGetNewPicBuffer). { CHECK( !( bSeqFirst ), "Unspecified error" ); // Implementations that use more than 1 SPS need to be aware of activation issues. +#if JVET_O1159_SCALABILITY + actualTotalBits += xWriteSPS( accessUnit, slice->getSPS(), m_pcEncLib->getLayerId() ); +#else actualTotalBits += xWriteSPS( accessUnit, slice->getSPS() ); +#endif } } @@ -441,6 +451,9 @@ int EncGOP::xWritePicHeader( AccessUnit &accessUnit, PicHeader *picHeader ) OutputNALUnit nalu(NAL_UNIT_PH); m_HLSWriter->setBitstream( &nalu.m_Bitstream ); nalu.m_temporalId = accessUnit.temporalId; +#if JVET_P1019_OUTPUT_LAYER_SET + nalu.m_nuhLayerId = m_pcEncLib->getLayerId(); +#endif m_HLSWriter->codePictureHeader( picHeader ); accessUnit.push_back(new NALUnitEBSP(nalu)); return (int)(accessUnit.back()->m_nalUnitData.str().size()) * 8; @@ -460,7 +473,11 @@ void EncGOP::xWriteAccessUnitDelimiter (AccessUnit &accessUnit, Slice *slice) } else { +#if JVET_O1159_SCALABILITY + nalu.m_nuhLayerId = slice->getVPS()->getLayerId(0); +#else nalu.m_nuhLayerId = slice->getVPS()->getVPSIncludedLayerId(0); +#endif } CHECK( nalu.m_temporalId != accessUnit.temporalId, "TemporalId shall be equal to the TemporalId of the AU containing the NAL unit" ); #else @@ -2086,7 +2103,11 @@ void EncGOP::xPicInitLMCS(Picture *pic, Slice *slice) if (m_pcReshaper->getSliceReshaperInfo().getSliceReshapeModelPresentFlag()) { #if JVET_N0278_FIXES +#if JVET_O1159_SCALABILITY + int apsId = std::min<int>( 3, m_pcEncLib->getVPS() == nullptr ? 0 : m_pcEncLib->getVPS()->getGeneralLayerIdx( m_pcEncLib->getLayerId() ) ); +#else int apsId = std::min<int>( 3, m_pcEncLib->getLayerId() ); //VS: layerId should be converted to laeyrIdx +#endif #else int apsId = 0; #endif @@ -2134,7 +2155,11 @@ void EncGOP::xPicInitLMCS(Picture *pic, Slice *slice) #endif { #if JVET_N0278_FIXES +#if JVET_O1159_SCALABILITY + int apsId = std::min<int>( 3, m_pcEncLib->getVPS() == nullptr ? 0 : m_pcEncLib->getVPS()->getGeneralLayerIdx( m_pcEncLib->getLayerId() ) ); +#else int apsId = std::min<int>( 3, m_pcEncLib->getLayerId() ); //VS: layerId should be converted to laeyrIdx +#endif #else int apsId = 0; #endif @@ -2434,12 +2459,24 @@ void EncGOP::compressGOP( int iPOCLast, int iNumPicRcvd, PicList& rcListPic, } if (pcSlice->checkThatAllRefPicsAreAvailable(rcListPic, pcSlice->getRPL0(), 0, false) != 0 || pcSlice->checkThatAllRefPicsAreAvailable(rcListPic, pcSlice->getRPL1(), 1, false) != 0 || - (m_pcEncLib->getDependentRAPIndicationSEIEnabled() && !pcSlice->isIRAP() && ( pcSlice->isDRAP() || !pcSlice->isPOCInRefPicList(pcSlice->getRPL0(), pcSlice->getAssociatedIRAPPOC())) )) + (m_pcEncLib->getDependentRAPIndicationSEIEnabled() && !pcSlice->isIRAP() && ( pcSlice->isDRAP() || !pcSlice->isPOCInRefPicList(pcSlice->getRPL0(), pcSlice->getAssociatedIRAPPOC())) ) +#if JVET_O1159_SCALABILITY + || ( !pcSlice->isIRAP() && pcSlice->getPic()->cs->vps && m_pcEncLib->getNumRefLayers( pcSlice->getPic()->cs->vps->getGeneralLayerIdx( m_pcEncLib->getLayerId() ) ) ) +#endif + ) { +#if JVET_O1159_SCALABILITY + xCreateExplicitReferencePictureSetFromReference( pcSlice, rcListPic, pcSlice->getRPL0(), pcSlice->getRPL1() ); +#else pcSlice->createExplicitReferencePictureSetFromReference(rcListPic, pcSlice->getRPL0(), pcSlice->getRPL1()); +#endif } +#if JVET_O1159_SCALABILITY + pcSlice->applyReferencePictureListBasedMarking( rcListPic, pcSlice->getRPL0(), pcSlice->getRPL1(), pcSlice->getPic()->layerId ); +#else pcSlice->applyReferencePictureListBasedMarking(rcListPic, pcSlice->getRPL0(), pcSlice->getRPL1()); +#endif if(pcSlice->getTLayer() > 0 && !(pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_RADL // Check if not a leading picture @@ -2449,6 +2486,14 @@ void EncGOP::compressGOP( int iPOCLast, int iNumPicRcvd, PicList& rcListPic, if (pcSlice->isStepwiseTemporalLayerSwitchingPointCandidate(rcListPic)) { bool isSTSA=true; + +#if JVET_O1159_SCALABILITY + if( !m_pcEncLib->getVPS()->getAllIndependentLayersFlag() && m_pcEncLib->getVPS()->getGeneralLayerIdx( m_pcEncLib->getLayerId() ) ) + { + isSTSA = false; + } +#endif + for(int ii=iGOPid+1;(ii<m_pcCfg->getGOPSize() && isSTSA==true);ii++) { int lTid = m_pcCfg->getRPLEntry(0, ii).m_temporalId; @@ -2993,7 +3038,11 @@ void EncGOP::compressGOP( int iPOCLast, int iNumPicRcvd, PicList& rcListPic, #endif #if JVET_N0278_FIXES +#if JVET_O1159_SCALABILITY + int apsId = std::min<int>( 7, m_pcEncLib->getVPS() == nullptr ? 0 : m_pcEncLib->getVPS()->getGeneralLayerIdx( m_pcEncLib->getLayerId() ) ); +#else int apsId = std::min<int>( 7, m_pcEncLib->getLayerId() ); //VS: layerId should be converted to laeyrIdx +#endif #else int apsId = 0; #endif @@ -3106,7 +3155,11 @@ void EncGOP::compressGOP( int iPOCLast, int iNumPicRcvd, PicList& rcListPic, #endif #if JVET_N0278_FIXES +#if JVET_O1159_SCALABILITY + int apsId = std::min<int>( 3, m_pcEncLib->getVPS() == nullptr ? 0 : m_pcEncLib->getVPS()->getGeneralLayerIdx( m_pcEncLib->getLayerId() ) ); +#else int apsId = std::min<int>( 3, m_pcEncLib->getLayerId() ); //VS: layerId should be converted to laeyrIdx +#endif #else int apsId = 0; #endif @@ -3313,7 +3366,11 @@ void EncGOP::compressGOP( int iPOCLast, int iNumPicRcvd, PicList& rcListPic, } #if JVET_N0278_FIXES +#if JVET_O1159_SCALABILITY + int layerIdx = m_pcEncLib->getVPS() == nullptr ? 0 : m_pcEncLib->getVPS()->getGeneralLayerIdx( m_pcEncLib->getLayerId() ); +#else int layerIdx = m_pcEncLib->getLayerId(); //VS: convert layerId to layerIdx after VPS is implemented +#endif // it is assumed that layerIdx equal to 0 is always present actualTotalBits += xWriteParameterSets( accessUnit, pcSlice, writePS && !layerIdx ); @@ -4689,6 +4746,15 @@ void EncGOP::xCalculateAddPSNR(Picture* pcPic, PelUnitBuf cPicD, const AccessUni else msg( NOTICE, "%d ", pcSlice->getRefPOC( RefPicList( iRefList ), iRefIndex ) ); } + +#if JVET_O1159_SCALABILITY + if( pcSlice->getRefPOC( RefPicList( iRefList ), iRefIndex ) == pcSlice->getPOC() ) + { + msg( NOTICE, ".%d", pcSlice->getRefPic( RefPicList( iRefList ), iRefIndex )->layerId ); + } +#endif + + msg( NOTICE, " " ); } msg( NOTICE, "]" ); } @@ -5493,4 +5559,275 @@ void EncGOP::applyDeblockingFilterParameterSelection( Picture* pcPic, const uint } } #endif + +#if JVET_O1159_SCALABILITY +void EncGOP::xCreateExplicitReferencePictureSetFromReference( Slice* slice, PicList& rcListPic, const ReferencePictureList *rpl0, const ReferencePictureList *rpl1 ) +{ + Picture* rpcPic; + int pocCycle = 0; + + Picture* pic = slice->getPic(); + const VPS* vps = slice->getPic()->cs->vps; + int layerIdx = vps == nullptr ? 0 : vps->getGeneralLayerIdx( pic->layerId ); + + ReferencePictureList* pLocalRPL0 = slice->getLocalRPL0(); + *pLocalRPL0 = ReferencePictureList( slice->getSPS()->getInterLayerPresentFlag() ); + + uint32_t numOfSTRPL0 = 0; + uint32_t numOfLTRPL0 = 0; + uint32_t numOfILRPL0 = 0; + uint32_t numOfRefPic = rpl0->getNumberOfShorttermPictures() + rpl0->getNumberOfLongtermPictures(); + uint32_t refPicIdxL0 = 0; + + for( int ii = 0; ii < numOfRefPic; ii++ ) + { + // loop through all pictures in the reference picture buffer + PicList::iterator iterPic = rcListPic.begin(); + bool isAvailable = false; + + pocCycle = 1 << ( slice->getSPS()->getBitsForPOC() ); + while( iterPic != rcListPic.end() ) + { + rpcPic = *( iterPic++ ); + + if( rpcPic->layerId == pic->layerId ) + { + if( !rpl0->isRefPicLongterm( ii ) && rpcPic->referenced && rpcPic->getPOC() == slice->getPOC() - rpl0->getRefPicIdentifier( ii ) && !slice->isPocRestrictedByDRAP( rpcPic->getPOC(), rpcPic->precedingDRAP ) ) + { + isAvailable = true; + break; + } + else if( rpl0->isRefPicLongterm( ii ) && rpcPic->referenced && ( rpcPic->getPOC() & ( pocCycle - 1 ) ) == rpl0->getRefPicIdentifier( ii ) && !slice->isPocRestrictedByDRAP( rpcPic->getPOC(), rpcPic->precedingDRAP ) ) + { + isAvailable = true; + break; + } + } + } + + if( isAvailable ) + { + pLocalRPL0->setRefPicIdentifier( refPicIdxL0, rpl0->getRefPicIdentifier( ii ), rpl0->isRefPicLongterm( ii ), false, NOT_VALID ); + refPicIdxL0++; + numOfSTRPL0 = numOfSTRPL0 + ( ( rpl0->isRefPicLongterm( ii ) ) ? 0 : 1 ); + numOfLTRPL0 += ( rpl0->isRefPicLongterm( ii ) && !rpl0->isInterLayerRefPic( ii ) ) ? 1 : 0; + isAvailable = false; + } + } + + // inter-layer reference pictures are added to the end of the reference picture list + if( layerIdx && vps && !vps->getAllIndependentLayersFlag() ) + { + numOfRefPic = rpl0->getNumberOfInterLayerPictures() ? rpl0->getNumberOfInterLayerPictures() : m_pcEncLib->getNumRefLayers( layerIdx ); + + for( int ii = 0; ii < numOfRefPic; ii++ ) + { + // loop through all pictures in the reference picture buffer + PicList::iterator iterPic = rcListPic.begin(); + + while( iterPic != rcListPic.end() ) + { + rpcPic = *( iterPic++ ); + int refLayerIdx = vps->getGeneralLayerIdx( rpcPic->layerId ); + + if( rpcPic->referenced && rpcPic->getPOC() == pic->getPOC() && vps->getDirectRefLayerFlag( layerIdx, refLayerIdx ) ) + { + pLocalRPL0->setRefPicIdentifier( refPicIdxL0, 0, true, true, vps->getInterLayerRefIdc( layerIdx, refLayerIdx ) ); + refPicIdxL0++; + numOfILRPL0++; + break; + } + } + } + } + + if( slice->getEnableDRAPSEI() ) + { + pLocalRPL0->setNumberOfShorttermPictures( numOfSTRPL0 ); + pLocalRPL0->setNumberOfLongtermPictures( numOfLTRPL0 ); + pLocalRPL0->setNumberOfInterLayerPictures( numOfILRPL0 ); + + if( !slice->isIRAP() && !slice->isPOCInRefPicList( pLocalRPL0, slice->getAssociatedIRAPPOC() ) ) + { + if( slice->getUseLTforDRAP() && !slice->isPOCInRefPicList( rpl1, slice->getAssociatedIRAPPOC() ) ) + { + // Adding associated IRAP as longterm picture + pLocalRPL0->setRefPicIdentifier( refPicIdxL0, slice->getAssociatedIRAPPOC(), true, false, 0 ); + refPicIdxL0++; + numOfLTRPL0++; + } + else + { + // Adding associated IRAP as shortterm picture + pLocalRPL0->setRefPicIdentifier( refPicIdxL0, slice->getPOC() - slice->getAssociatedIRAPPOC(), false, false, 0 ); + refPicIdxL0++; + numOfSTRPL0++; + } + } + } + + ReferencePictureList* pLocalRPL1 = slice->getLocalRPL1(); + *pLocalRPL1 = ReferencePictureList( slice->getSPS()->getInterLayerPresentFlag() ); + + uint32_t numOfSTRPL1 = 0; + uint32_t numOfLTRPL1 = 0; + uint32_t numOfILRPL1 = 0; + numOfRefPic = rpl1->getNumberOfShorttermPictures() + rpl1->getNumberOfLongtermPictures(); + uint32_t refPicIdxL1 = 0; + + for( int ii = 0; ii < numOfRefPic; ii++ ) + { + // loop through all pictures in the reference picture buffer + PicList::iterator iterPic = rcListPic.begin(); + bool isAvailable = false; + pocCycle = 1 << ( slice->getSPS()->getBitsForPOC() ); + while( iterPic != rcListPic.end() ) + { + rpcPic = *( iterPic++ ); + + if( rpcPic->layerId == pic->layerId ) + { + if( !rpl1->isRefPicLongterm( ii ) && rpcPic->referenced && rpcPic->getPOC() == slice->getPOC() - rpl1->getRefPicIdentifier( ii ) && !slice->isPocRestrictedByDRAP( rpcPic->getPOC(), rpcPic->precedingDRAP ) ) + { + isAvailable = true; + break; + } + else if( rpl1->isRefPicLongterm( ii ) && rpcPic->referenced && ( rpcPic->getPOC() & ( pocCycle - 1 ) ) == rpl1->getRefPicIdentifier( ii ) && !slice->isPocRestrictedByDRAP( rpcPic->getPOC(), rpcPic->precedingDRAP ) ) + { + isAvailable = true; + break; + } + } + } + + if( isAvailable ) + { + pLocalRPL1->setRefPicIdentifier( refPicIdxL1, rpl1->getRefPicIdentifier( ii ), rpl1->isRefPicLongterm( ii ), false, NOT_VALID ); + refPicIdxL1++; + numOfSTRPL1 = numOfSTRPL1 + ( ( rpl1->isRefPicLongterm( ii ) ) ? 0 : 1 ); + numOfLTRPL1 += ( rpl1->isRefPicLongterm( ii ) && !rpl1->isInterLayerRefPic( ii ) ) ? 1 : 0; + isAvailable = false; + } + } + + + // inter-layer reference pictures are added to the end of the reference picture list + if( layerIdx && vps && !vps->getAllIndependentLayersFlag() ) + { + numOfRefPic = rpl1->getNumberOfInterLayerPictures() ? rpl1->getNumberOfInterLayerPictures() : m_pcEncLib->getNumRefLayers( layerIdx ); + + for( int ii = 0; ii < numOfRefPic; ii++ ) + { + // loop through all pictures in the reference picture buffer + PicList::iterator iterPic = rcListPic.begin(); + + while( iterPic != rcListPic.end() ) + { + rpcPic = *( iterPic++ ); + int refLayerIdx = vps->getGeneralLayerIdx( rpcPic->layerId ); + + if( rpcPic->referenced && rpcPic->getPOC() == pic->getPOC() && vps->getDirectRefLayerFlag( layerIdx, refLayerIdx ) ) + { + pLocalRPL1->setRefPicIdentifier( refPicIdxL1, 0, true, true, vps->getInterLayerRefIdc( layerIdx, refLayerIdx ) ); + refPicIdxL1++; + numOfILRPL1++; + break; + } + } + } + } + + //Copy from L1 if we have less than active ref pic + int numOfNeedToFill = rpl0->getNumberOfActivePictures() - (numOfLTRPL0 + numOfSTRPL0); + bool isDisallowMixedRefPic = ( slice->getSPS()->getAllActiveRplEntriesHasSameSignFlag() ) ? true : false; + int originalL0StrpNum = numOfSTRPL0; + int originalL0LtrpNum = numOfLTRPL0; + int originalL0IlrpNum = numOfILRPL0; + + for( int ii = 0; numOfNeedToFill > 0 && ii < ( pLocalRPL1->getNumberOfLongtermPictures() + pLocalRPL1->getNumberOfShorttermPictures() + pLocalRPL1->getNumberOfInterLayerPictures() ); ii++ ) + { + if( ii <= ( numOfLTRPL1 + numOfSTRPL1 + numOfILRPL1 - 1 ) ) + { + //Make sure this copy is not already in L0 + bool canIncludeThis = true; + for( int jj = 0; jj < refPicIdxL0; jj++ ) + { + if( ( pLocalRPL1->getRefPicIdentifier( ii ) == pLocalRPL0->getRefPicIdentifier( jj ) ) && ( pLocalRPL1->isRefPicLongterm( ii ) == pLocalRPL0->isRefPicLongterm( jj ) ) && pLocalRPL1->getInterLayerRefPicIdx( ii ) == pLocalRPL0->getInterLayerRefPicIdx( jj ) ) + { + canIncludeThis = false; + } + + bool sameSign = ( pLocalRPL1->getRefPicIdentifier( ii ) > 0 ) == ( pLocalRPL0->getRefPicIdentifier( 0 ) > 0 ); + + if( isDisallowMixedRefPic && canIncludeThis && !pLocalRPL1->isRefPicLongterm( ii ) && !sameSign ) + { + canIncludeThis = false; + } + } + if( canIncludeThis ) + { + pLocalRPL0->setRefPicIdentifier( refPicIdxL0, pLocalRPL1->getRefPicIdentifier( ii ), pLocalRPL1->isRefPicLongterm( ii ), pLocalRPL1->isInterLayerRefPic( ii ), pLocalRPL1->getInterLayerRefPicIdx( ii ) ); + refPicIdxL0++; + numOfSTRPL0 = numOfSTRPL0 + ( ( pLocalRPL1->isRefPicLongterm( ii ) ) ? 0 : 1 ); + numOfLTRPL0 += ( pLocalRPL1->isRefPicLongterm( ii ) && !pLocalRPL1->isInterLayerRefPic( ii ) ) ? 1 : 0; + numOfILRPL0 += pLocalRPL1->isInterLayerRefPic( ii ) ? 1 : 0; + numOfNeedToFill--; + } + } + } + pLocalRPL0->setNumberOfLongtermPictures( numOfLTRPL0 ); + pLocalRPL0->setNumberOfShorttermPictures( numOfSTRPL0 ); + pLocalRPL0->setNumberOfInterLayerPictures( numOfILRPL0 ); + int numPics = numOfLTRPL0 + numOfSTRPL0; + + pLocalRPL0->setNumberOfActivePictures( ( numPics < rpl0->getNumberOfActivePictures() ? numPics : rpl0->getNumberOfActivePictures() ) + numOfILRPL0 ); + pLocalRPL0->setLtrpInSliceHeaderFlag( rpl0->getLtrpInSliceHeaderFlag() ); + slice->setRPL0idx( -1 ); + slice->setRPL0( pLocalRPL0 ); + + //Copy from L0 if we have less than active ref pic + numOfNeedToFill = pLocalRPL0->getNumberOfActivePictures() - ( numOfLTRPL1 + numOfSTRPL1 ); + + for( int ii = 0; numOfNeedToFill > 0 && ii < ( pLocalRPL0->getNumberOfLongtermPictures() + pLocalRPL0->getNumberOfShorttermPictures() + pLocalRPL0->getNumberOfInterLayerPictures() ); ii++ ) + { + if( ii <= ( originalL0StrpNum + originalL0LtrpNum + originalL0IlrpNum - 1 ) ) + { + //Make sure this copy is not already in L0 + bool canIncludeThis = true; + for( int jj = 0; jj < refPicIdxL1; jj++ ) + { + if( ( pLocalRPL0->getRefPicIdentifier( ii ) == pLocalRPL1->getRefPicIdentifier( jj ) ) && ( pLocalRPL0->isRefPicLongterm( ii ) == pLocalRPL1->isRefPicLongterm( jj ) ) && pLocalRPL0->getInterLayerRefPicIdx( ii ) == pLocalRPL1->getInterLayerRefPicIdx( jj ) ) + { + canIncludeThis = false; + } + + bool sameSign = ( pLocalRPL0->getRefPicIdentifier( ii ) > 0 ) == ( pLocalRPL1->getRefPicIdentifier( 0 ) > 0 ); + + if( isDisallowMixedRefPic && canIncludeThis && !pLocalRPL0->isRefPicLongterm( ii ) && !sameSign ) + { + canIncludeThis = false; + } + } + if( canIncludeThis ) + { + pLocalRPL1->setRefPicIdentifier( refPicIdxL1, pLocalRPL0->getRefPicIdentifier( ii ), pLocalRPL0->isRefPicLongterm( ii ), pLocalRPL0->isInterLayerRefPic( ii ), pLocalRPL0->getInterLayerRefPicIdx( ii ) ); + refPicIdxL1++; + numOfSTRPL1 = numOfSTRPL1 + ( ( pLocalRPL0->isRefPicLongterm( ii ) ) ? 0 : 1 ); + numOfLTRPL1 += ( pLocalRPL0->isRefPicLongterm( ii ) && !pLocalRPL0->isInterLayerRefPic( ii ) ) ? 1 : 0; + numOfLTRPL1 += pLocalRPL0->isInterLayerRefPic( ii ) ? 1 : 0; + numOfNeedToFill--; + } + } + } + pLocalRPL1->setNumberOfLongtermPictures( numOfLTRPL1 ); + pLocalRPL1->setNumberOfShorttermPictures( numOfSTRPL1 ); + pLocalRPL1->setNumberOfInterLayerPictures( numOfILRPL1 ); + numPics = numOfLTRPL1 + numOfSTRPL1; + + pLocalRPL1->setNumberOfActivePictures( ( isDisallowMixedRefPic ? numPics : ( numPics < rpl1->getNumberOfActivePictures() ? numPics : rpl1->getNumberOfActivePictures() ) ) + numOfILRPL1 ); + pLocalRPL1->setLtrpInSliceHeaderFlag( rpl1->getLtrpInSliceHeaderFlag() ); + slice->setRPL1idx( -1 ); + slice->setRPL1( pLocalRPL1 ); +} +#endif //! \} diff --git a/source/Lib/EncoderLib/EncGOP.h b/source/Lib/EncoderLib/EncGOP.h index 018e8273a1efa821ea4f8c009c9053c23a71b6ee..ea48063b958a0038fd91661184c6a106c2413cf0 100644 --- a/source/Lib/EncoderLib/EncGOP.h +++ b/source/Lib/EncoderLib/EncGOP.h @@ -330,7 +330,11 @@ protected: int xWriteVPS (AccessUnit &accessUnit, const VPS *vps); int xWriteDPS (AccessUnit &accessUnit, const DPS *dps); +#if JVET_O1159_SCALABILITY + int xWriteSPS( AccessUnit &accessUnit, const SPS *sps, const int layerId = 0 ); +#else int xWriteSPS (AccessUnit &accessUnit, const SPS *sps); +#endif int xWritePPS( AccessUnit &accessUnit, const PPS *pps, const SPS *sps, const int layerId = 0 ); #if JVET_P0588_SUFFIX_APS int xWriteAPS( AccessUnit &accessUnit, APS *aps, const int layerId, const bool isPrefixNUT ); @@ -346,6 +350,9 @@ protected: #if W0038_DB_OPT void applyDeblockingFilterParameterSelection( Picture* pcPic, const uint32_t numSlices, const int gopID ); #endif +#if JVET_O1159_SCALABILITY + void xCreateExplicitReferencePictureSetFromReference( Slice* slice, PicList& rcListPic, const ReferencePictureList *rpl0, const ReferencePictureList *rpl1 ); +#endif };// END CLASS DEFINITION EncGOP //! \} diff --git a/source/Lib/EncoderLib/EncLib.cpp b/source/Lib/EncoderLib/EncLib.cpp index 8bdfaaf10a2b1c0ad35d7fbf43040d08d364c054..dd965fa4a7d316e28bf5c97875da03a04b629245 100644 --- a/source/Lib/EncoderLib/EncLib.cpp +++ b/source/Lib/EncoderLib/EncLib.cpp @@ -243,8 +243,16 @@ void EncLib::init( bool isFieldCoding, AUWriterIf* auWriterIf ) aps0.setAPSType( SCALING_LIST_APS ); // initialize SPS +#if JVET_O1159_SCALABILITY + xInitSPS( sps0, m_cVPS ); +#else xInitSPS(sps0); +#endif +#if JVET_P0185 + xInitVPS(m_cVPS, sps0); +#else xInitVPS(m_cVPS); +#endif int dpsId = getDecodingParameterSetEnabled() ? 1 : 0; xInitDPS(m_dps, sps0, dpsId); @@ -465,7 +473,11 @@ void EncLib::init( bool isFieldCoding, AUWriterIf* auWriterIf ) #endif picBg->getRecoBuf().fill(0); #if JVET_P1006_PICTURE_HEADER +#if JVET_O1159_SCALABILITY + picBg->finalInit( &m_cVPS, sps0, pps0, &m_picHeader, m_apss, m_lmcsAPS, m_scalinglistAPS ); +#else picBg->finalInit( sps0, pps0, &m_picHeader, m_apss, m_lmcsAPS, m_scalinglistAPS ); +#endif #else picBg->finalInit( sps0, pps0, m_apss, m_lmcsAPS, m_scalinglistAPS ); #endif @@ -625,7 +637,11 @@ bool EncLib::encodePrep( bool flush, PelStorage* pcPicYuvOrg, PelStorage* cPicYu picCurr->M_BUFS( 0, PIC_ORIGINAL ).copyFrom( m_cGOPEncoder.getPicBg()->getRecoBuf() ); #if JVET_P1006_PICTURE_HEADER +#if JVET_O1159_SCALABILITY + picCurr->finalInit( &m_cVPS, *sps, *pps, &m_picHeader, m_apss, m_lmcsAPS, m_scalinglistAPS ); +#else picCurr->finalInit( *sps, *pps, &m_picHeader, m_apss, m_lmcsAPS, m_scalinglistAPS ); +#endif #else picCurr->finalInit( *sps, *pps, m_apss, m_lmcsAPS, m_scalinglistAPS ); #endif @@ -758,8 +774,12 @@ bool EncLib::encodePrep( bool flush, PelStorage* pcPicYuvOrg, PelStorage* cPicYu pcPicCurr->M_BUFS( 0, PIC_ORIGINAL ).swap( *pcPicYuvOrg ); pcPicCurr->M_BUFS( 0, PIC_TRUE_ORIGINAL ).swap( *cPicYuvTrueOrg ); } -#if JVET_P1006_PICTURE_HEADER +#if JVET_P1006_PICTURE_HEADER +#if JVET_O1159_SCALABILITY + pcPicCurr->finalInit( &m_cVPS, *pSPS, *pPPS, &m_picHeader, m_apss, m_lmcsAPS, m_scalinglistAPS ); +#else pcPicCurr->finalInit( *pSPS, *pPPS, &m_picHeader, m_apss, m_lmcsAPS, m_scalinglistAPS ); +#endif #else pcPicCurr->finalInit( *pSPS, *pPPS, m_apss, m_lmcsAPS, m_scalinglistAPS ); #endif @@ -1105,7 +1125,11 @@ bool EncLib::encodePrep( bool flush, PelStorage* pcPicYuvOrg, PelStorage* pcPicY const PPS *pPPS = ( ppsID < 0 ) ? m_ppsMap.getFirstPS() : m_ppsMap.getPS( ppsID ); const SPS *pSPS = m_spsMap.getPS( pPPS->getSPSId() ); #if JVET_P1006_PICTURE_HEADER +#if JVET_O1159_SCALABILITY + pcField->finalInit( &m_cVPS, *pSPS, *pPPS, &m_picHeader, m_apss, m_lmcsAPS, m_scalinglistAPS ); +#else pcField->finalInit( *pSPS, *pPPS, &m_picHeader, m_apss, m_lmcsAPS, m_scalinglistAPS ); +#endif #else pcField->finalInit( *pSPS, *pPPS, m_apss, m_lmcsAPS, m_scalinglistAPS ); #endif @@ -1392,18 +1416,26 @@ void EncLib::xGetNewPicBuffer ( std::list<PelUnitBuf*>& rcListPicYuvRecOut, Pict m_iNumPicRcvd++; } - -void EncLib::xInitVPS(VPS &vps) +#if JVET_P0185 +void EncLib::xInitVPS(VPS& vps, const SPS& sps) +#else +void EncLib::xInitVPS(VPS& vps) +#endif { // The SPS must have already been set up. // set the VPS profile information. #if !JVET_N0278_FIXES vps.setMaxLayers(1); #endif +#if !JVET_O1159_SCALABILITY for (uint32_t i = 0; i < vps.getMaxLayers(); i++) { vps.setVPSIncludedLayerId(0, i); } +#endif +#if JVET_P0185 + vps.setMaxSubLayers(sps.getMaxTLayers()); +#endif } void EncLib::xInitDPS(DPS &dps, const SPS &sps, const int dpsId) @@ -1422,8 +1454,11 @@ void EncLib::xInitDPS(DPS &dps, const SPS &sps, const int dpsId) #endif } - +#if JVET_O1159_SCALABILITY +void EncLib::xInitSPS( SPS& sps, VPS& vps ) +#else void EncLib::xInitSPS(SPS &sps) +#endif { ProfileTierLevel* profileTierLevel = sps.getProfileTierLevel(); ConstraintInfo* cinfo = profileTierLevel->getConstraintInfo(); @@ -1482,7 +1517,9 @@ void EncLib::xInitSPS(SPS &sps) /* XXX: should Main be marked as compatible with still picture? */ /* XXX: may be a good idea to refactor the above into a function * that chooses the actual compatibility based upon options */ - +#if JVET_O1159_SCALABILITY + sps.setVPSId(m_cVPS.getVPSId()); +#endif sps.setMaxPicWidthInLumaSamples( m_iSourceWidth ); sps.setMaxPicHeightInLumaSamples( m_iSourceHeight ); sps.setMaxCUWidth ( m_maxCUWidth ); @@ -1736,7 +1773,10 @@ void EncLib::xInitSPS(SPS &sps) } #endif -#if JVET_P0590_SCALING_WINDOW +#if JVET_O1159_SCALABILITY + sps.setInterLayerPresentFlag( vps.getMaxLayers() > 1 && !vps.getAllIndependentLayersFlag() ); + sps.setRprEnabledFlag( m_rprEnabled || sps.getInterLayerPresentFlag() ); +#elif JVET_P0590_SCALING_WINDOW sps.setRprEnabledFlag( m_rprEnabled ); #endif } @@ -2225,10 +2265,19 @@ void EncLib::xInitRPL(SPS &sps, bool isFieldCoding) rpl->setNumberOfLongtermPictures(0); //Hardcoded as 0 for now. need to update this when implementing LTRP rpl->setNumberOfActivePictures(ge.m_numRefPicsActive); rpl->setLtrpInSliceHeaderFlag(ge.m_ltrp_in_slice_header_flag); +#if JVET_O1159_SCALABILITY + rpl->setInterLayerPresentFlag( sps.getInterLayerPresentFlag() ); + // inter-layer reference picture is not signaled in SPS RPL, SPS is shared currently + rpl->setNumberOfInterLayerPictures( 0 ); +#endif for (int k = 0; k < ge.m_numRefPics; k++) { +#if JVET_O1159_SCALABILITY + rpl->setRefPicIdentifier( k, ge.m_deltaRefPics[k], 0, false, 0 ); +#else rpl->setRefPicIdentifier(k, ge.m_deltaRefPics[k], 0); +#endif } } } diff --git a/source/Lib/EncoderLib/EncLib.h b/source/Lib/EncoderLib/EncLib.h index 6bfa2db54c2fe68715839c8cdd789762f21b8e68..a7eebb41cbbd5da2d32e87344c51bebd2e3714ea 100644 --- a/source/Lib/EncoderLib/EncLib.h +++ b/source/Lib/EncoderLib/EncLib.h @@ -178,9 +178,17 @@ public: protected: void xGetNewPicBuffer ( std::list<PelUnitBuf*>& rcListPicYuvRecOut, Picture*& rpcPic, int ppsId ); ///< get picture buffer which will be processed. If ppsId<0, then the ppsMap will be queried for the first match. - void xInitVPS (VPS &vps); ///< initialize VPS from encoder options +#if JVET_P0185 + void xInitVPS(VPS& vps, const SPS& sps); ///< initialize VPS from encoder options +#else + void xInitVPS(VPS& vps); ///< initialize VPS from encoder options +#endif void xInitDPS (DPS &dps, const SPS &sps, const int dpsId); ///< initialize DPS from encoder options +#if JVET_O1159_SCALABILITY + void xInitSPS ( SPS& sps, VPS& vps ); ///< initialize SPS from encoder options +#else void xInitSPS (SPS &sps); ///< initialize SPS from encoder options +#endif void xInitPPS (PPS &pps, const SPS &sps); ///< initialize PPS from encoder options #if JVET_P1006_PICTURE_HEADER void xInitPicHeader (PicHeader &picHeader, const SPS &sps, const PPS &pps); ///< initialize Picture Header from encoder options diff --git a/source/Lib/EncoderLib/EncModeCtrl.cpp b/source/Lib/EncoderLib/EncModeCtrl.cpp index d4dd73a9293d915d30c8e5734fb446a0b62850ce..c629f0fc5b2dfac47354413341ffbd6ceb4bda9f 100644 --- a/source/Lib/EncoderLib/EncModeCtrl.cpp +++ b/source/Lib/EncoderLib/EncModeCtrl.cpp @@ -1991,7 +1991,6 @@ bool EncModeCtrlMTnoRQT::tryMode( const EncTestMode& encTestmode, const CodingSt else { CHECK( encTestmode.type != ETM_POST_DONT_SPLIT, "Unknown mode" ); - if ((cuECtx.get<double>(BEST_NO_IMV_COST) == (MAX_DOUBLE * .5) || cuECtx.get<bool>(IS_REUSING_CU)) && !slice.isIntra()) { unsigned idx1, idx2, idx3, idx4; @@ -2001,7 +2000,6 @@ bool EncModeCtrlMTnoRQT::tryMode( const EncTestMode& encTestmode, const CodingSt m_pcInterSearch->insertUniMvCands(partitioner.currArea().Y(), g_reusedUniMVs[idx1][idx2][idx3][idx4]); } } - if( !bestCS || ( bestCS && isModeSplit( bestMode ) ) ) { return false; diff --git a/source/Lib/EncoderLib/SEIEncoder.cpp b/source/Lib/EncoderLib/SEIEncoder.cpp index d89acc46eee5180fbde18800991b982cc5146882..973f83e18808d5d2fb96c40b4e51bb9a01e8ed06 100644 --- a/source/Lib/EncoderLib/SEIEncoder.cpp +++ b/source/Lib/EncoderLib/SEIEncoder.cpp @@ -211,10 +211,17 @@ void SEIEncoder::initSEIBufferingPeriod(SEIBufferingPeriod *bufferingPeriodSEI, bufferingPeriodSEI->m_bpNalCpbParamsPresentFlag = true; bufferingPeriodSEI->m_bpVclCpbParamsPresentFlag = true; bufferingPeriodSEI->m_bpMaxSubLayers = m_pcCfg->getMaxTempLayer() ; +#if JVET_P0446_BP_CPB_CNT_FIX + bufferingPeriodSEI->m_bpCpbCnt = 1; +#endif for(int i=0; i < bufferingPeriodSEI->m_bpMaxSubLayers; i++) { +#if !JVET_P0446_BP_CPB_CNT_FIX bufferingPeriodSEI->m_bpCpbCnt[i] = 1; for(int j=0; j < bufferingPeriodSEI->m_bpCpbCnt[i]; j++) +#else + for(int j=0; j < bufferingPeriodSEI->m_bpCpbCnt; j++) +#endif { bufferingPeriodSEI->m_initialCpbRemovalDelay[j][i][0] = uiInitialCpbRemovalDelay; bufferingPeriodSEI->m_initialCpbRemovalDelay[j][i][1] = uiInitialCpbRemovalDelay; @@ -222,6 +229,13 @@ void SEIEncoder::initSEIBufferingPeriod(SEIBufferingPeriod *bufferingPeriodSEI, bufferingPeriodSEI->m_initialCpbRemovalOffset[j][i][1] = uiInitialCpbRemovalDelay; } } +#if JVET_P0446_CONCATENATION + // We don't set concatenation_flag here. max_initial_removal_delay_for_concatenation depends on the usage scenario. + // The parameters could be added to config file, but as long as the initialisation of generic buffering parameters is + // not controllable, it does not seem to make sense to provide settings for these. + bufferingPeriodSEI->m_concatenationFlag = false; + bufferingPeriodSEI->m_maxInitialRemovalDelayForConcatenation = uiInitialCpbRemovalDelay; +#endif #if JVET_P0202_P0203_FIX_HRD_RELATED_SEI #if JVET_P1004_REMOVE_BRICKS @@ -312,6 +326,15 @@ void SEIEncoder::initSEIBufferingPeriod(SEIBufferingPeriod *bufferingPeriodSEI, break; } } +#if JVET_P0446_ALT_CPB + // A commercial encoder should track the buffer state for all layers and sub-layers + // to ensure CPB conformance. Such tracking is required for calculating alternative + // CPB parameters. + // Unfortunately VTM does not have such tracking. Thus we cannot encode alternative + // CPB parameters here. + bufferingPeriodSEI->m_altCpbParamsPresentFlag = false; + bufferingPeriodSEI->m_useAltCpbParamsFlag = false; +#endif } #if JVET_P0462_SEI360 diff --git a/source/Lib/EncoderLib/SEIwrite.cpp b/source/Lib/EncoderLib/SEIwrite.cpp index bfc46b817cb366f42d14f727f5e6d85fc1c854ea..5a300a5dd8435d093a383d5ae08ba785489d1de5 100644 --- a/source/Lib/EncoderLib/SEIwrite.cpp +++ b/source/Lib/EncoderLib/SEIwrite.cpp @@ -387,6 +387,9 @@ void SEIWriter::xWriteSEIBufferingPeriod(const SEIBufferingPeriod& sei, const SP WRITE_CODE( sei.m_cpbRemovalDelayLength - 1, 5, "cpb_removal_delay_length_minus1" ); CHECK (sei.m_dpbOutputDelayLength < 1, "sei.m_dpbOutputDelayLength must be > 0"); WRITE_CODE( sei.m_dpbOutputDelayLength - 1, 5, "dpb_output_delay_length_minus1" ); +#if JVET_P0446_ALT_CPB + WRITE_FLAG(sei.m_altCpbParamsPresentFlag, "alt_cpb_params_present_flag"); +#endif WRITE_FLAG( sei.m_bpDecodingUnitHrdParamsPresentFlag, "bp_decoding_unit_hrd_params_present_flag" ); if( sei.m_bpDecodingUnitHrdParamsPresentFlag ) { @@ -416,6 +419,13 @@ void SEIWriter::xWriteSEIBufferingPeriod(const SEIBufferingPeriod& sei, const SP #endif WRITE_FLAG( sei.m_concatenationFlag, "concatenation_flag"); +#if JVET_P0446_CONCATENATION + WRITE_FLAG( sei.m_additionalConcatenationInfoPresentFlag, "additional_concatenation_info_present_flag"); + if (sei.m_additionalConcatenationInfoPresentFlag) + { + WRITE_CODE( sei.m_maxInitialRemovalDelayForConcatenation, sei.m_initialCpbRemovalDelayLength, "max_initial_removal_delay_for_concatenation" ); + } +#endif CHECK (sei.m_auCpbRemovalDelayDelta < 1, "sei.m_auCpbRemovalDelayDelta must be > 0"); WRITE_CODE( sei.m_auCpbRemovalDelayDelta - 1, sei.m_cpbRemovalDelayLength, "au_cpb_removal_delay_delta_minus1" ); @@ -432,6 +442,10 @@ void SEIWriter::xWriteSEIBufferingPeriod(const SEIBufferingPeriod& sei, const SP CHECK (sei.m_bpMaxSubLayers < 1, "bp_max_sub_layers_minus1 must be > 0"); WRITE_CODE( sei.m_bpMaxSubLayers - 1, 3, "bp_max_sub_layers_minus1" ); } +#if JVET_P0446_BP_CPB_CNT_FIX + CHECK (sei.m_bpCpbCnt < 1, "sei.m_bpCpbCnt must be > 0"); + WRITE_UVLC( sei.m_bpCpbCnt - 1, "bp_cpb_cnt_minus1"); +#endif #if JVET_P0181 WRITE_FLAG(sei.m_sublayerInitialCpbRemovalDelayPresentFlag, "sublayer_initial_cpb_removal_delay_present_flag"); for (int i = (sei.m_sublayerInitialCpbRemovalDelayPresentFlag ? 0 : sei.m_bpMaxSubLayers - 1); i < sei.m_bpMaxSubLayers; i++) @@ -439,14 +453,20 @@ void SEIWriter::xWriteSEIBufferingPeriod(const SEIBufferingPeriod& sei, const SP for (int i = 0; i < sei.m_bpMaxSubLayers; i++) #endif { +#if !JVET_P0446_BP_CPB_CNT_FIX CHECK (sei.m_bpCpbCnt[i] < 1, "sei.m_bpCpbCnt[i] must be > 0"); WRITE_UVLC( sei.m_bpCpbCnt[i] - 1, "bp_cpb_cnt_minus1[i]"); +#endif for( int nalOrVcl = 0; nalOrVcl < 2; nalOrVcl ++ ) { if( ( ( nalOrVcl == 0 ) && ( sei.m_bpNalCpbParamsPresentFlag ) ) || ( ( nalOrVcl == 1 ) && ( sei.m_bpVclCpbParamsPresentFlag ) ) ) { +#if !JVET_P0446_BP_CPB_CNT_FIX for( int j = 0; j < sei.m_bpCpbCnt[i]; j ++ ) +#else + for( int j = 0; j < sei.m_bpCpbCnt; j ++ ) +#endif { WRITE_CODE( sei.m_initialCpbRemovalDelay[j][i][nalOrVcl], sei.m_initialCpbRemovalDelayLength, "initial_cpb_removal_delay[j][i][nalOrVcl]" ); WRITE_CODE( sei.m_initialCpbRemovalOffset[j][i][nalOrVcl], sei.m_initialCpbRemovalDelayLength, "initial_cpb_removal_delay_offset[j][i][nalOrVcl]" ); @@ -454,6 +474,13 @@ void SEIWriter::xWriteSEIBufferingPeriod(const SEIBufferingPeriod& sei, const SP } } } +#if JVET_P0446_ALT_CPB + if (sei.m_altCpbParamsPresentFlag) + { + WRITE_FLAG(sei.m_useAltCpbParamsFlag, "use_alt_cpb_params_flag"); + } +#endif + } #if JVET_P0202_P0203_FIX_HRD_RELATED_SEI @@ -465,6 +492,22 @@ void SEIWriter::xWriteSEIPictureTiming(const SEIPictureTiming& sei, const SPS *s #if JVET_P0202_P0203_FIX_HRD_RELATED_SEI WRITE_CODE( sei.m_auCpbRemovalDelay[bp.m_bpMaxSubLayers - 1] - 1, bp.m_cpbRemovalDelayLength, "cpb_removal_delay_minus1[bp_max_sub_layers_minus1]" ); +#if JVET_P0446_ALT_CPB + if( bp.m_altCpbParamsPresentFlag ) + { + WRITE_FLAG( sei.m_cpbAltTimingInfoPresentFlag, "cpb_alt_timing_info_present_flag" ); + if( sei.m_cpbAltTimingInfoPresentFlag ) + { + for( int i = 0; i < bp.m_bpCpbCnt; i++ ) + { + WRITE_CODE( sei.m_cpbAltInitialCpbRemovalDelayDelta[i], bp.m_initialCpbRemovalDelayLength, "cpb_alt_initial_cpb_removal_delay_delta[ i ]" ); + WRITE_CODE( sei.m_cpbAltInitialCpbRemovalOffsetDelta[i], bp.m_initialCpbRemovalDelayLength, "cpb_alt_initial_cpb_removal_offset_delta[ i ]" ); + } + WRITE_CODE( sei.m_cpbDelayOffset, bp.m_initialCpbRemovalDelayLength, "cpb_delay_offset" ); + WRITE_CODE( sei.m_dpbDelayOffset, bp.m_initialCpbRemovalDelayLength, "dpb_delay_offset" ); + } + } +#endif for( int i = temporalId; i < bp.m_bpMaxSubLayers - 1; i ++ ) { WRITE_FLAG( sei.m_ptSubLayerDelaysPresentFlag[i], "pt_sub_layer_delays_present_flag[i]" ); diff --git a/source/Lib/EncoderLib/VLCWriter.cpp b/source/Lib/EncoderLib/VLCWriter.cpp index 2b8341f36dd56ab4a60fa22650e354110b12e663..128572dec6bba59dbb1350506ce15c50eff55640 100644 --- a/source/Lib/EncoderLib/VLCWriter.cpp +++ b/source/Lib/EncoderLib/VLCWriter.cpp @@ -185,8 +185,14 @@ void AUDWriter::codeAUD(OutputBitstream& bs, const int pictureType) void HLSWriter::xCodeRefPicList( const ReferencePictureList* rpl, bool isLongTermPresent, uint32_t ltLsbBitsCount, const bool isForbiddenZeroDeltaPoc ) { +#if JVET_O1159_SCALABILITY + uint32_t numRefPic = rpl->getNumberOfShorttermPictures() + rpl->getNumberOfLongtermPictures() + rpl->getNumberOfInterLayerPictures(); + WRITE_UVLC( numRefPic, "num_ref_entries[ listIdx ][ rplsIdx ]" ); +#else WRITE_UVLC(rpl->getNumberOfShorttermPictures() + rpl->getNumberOfLongtermPictures(), "num_ref_entries[ listIdx ][ rplsIdx ]"); uint32_t numRefPic = rpl->getNumberOfShorttermPictures() + rpl->getNumberOfLongtermPictures(); +#endif + if (isLongTermPresent) { WRITE_FLAG(rpl->getLtrpInSliceHeaderFlag(), "ltrp_in_slice_header_flag[ listIdx ][ rplsIdx ]"); @@ -196,8 +202,26 @@ void HLSWriter::xCodeRefPicList( const ReferencePictureList* rpl, bool isLongTer bool firstSTRP = true; for (int ii = 0; ii < numRefPic; ii++) { - if (isLongTermPresent) - WRITE_FLAG(!rpl->isRefPicLongterm(ii), "st_ref_pic_flag[ listIdx ][ rplsIdx ][ i ]"); +#if JVET_O1159_SCALABILITY + if( rpl->getInterLayerPresentFlag() ) + { + WRITE_FLAG( rpl->isInterLayerRefPic( ii ), "inter_layer_ref_pic_flag[ listIdx ][ rplsIdx ][ i ]" ); + + if( rpl->isInterLayerRefPic( ii ) ) + { + CHECK( rpl->getInterLayerRefPicIdx( ii ) < 0, "Wrong inter-layer reference index" ); + WRITE_UVLC( rpl->getInterLayerRefPicIdx( ii ), "ilrp_idx[ listIdx ][ rplsIdx ][ i ]" ); + } + } + + if( !rpl->isInterLayerRefPic( ii ) ) + { +#endif + if( isLongTermPresent ) + { + WRITE_FLAG( !rpl->isRefPicLongterm( ii ), "st_ref_pic_flag[ listIdx ][ rplsIdx ][ i ]" ); + } + if (!rpl->isRefPicLongterm(ii)) { if (firstSTRP) @@ -225,6 +249,9 @@ void HLSWriter::xCodeRefPicList( const ReferencePictureList* rpl, bool isLongTer { WRITE_CODE(rpl->getRefPicIdentifier(ii), ltLsbBitsCount, "poc_lsb_lt[listIdx][rplsIdx][i]"); } +#if JVET_O1159_SCALABILITY + } +#endif } } @@ -307,7 +334,15 @@ void HLSWriter::codePPS( const PPS* pcPPS, const SPS* pcSPS ) // rectangular slice signalling WRITE_FLAG( pcPPS->getRectSliceFlag( ) ? 1 : 0, "rect_slice_flag"); - if( pcPPS->getRectSliceFlag() ) +#if JVET_P1024_SINGLE_SLICE_PER_SUBPIC_FLAG + if (pcPPS->getRectSliceFlag()) + { + WRITE_FLAG(pcPPS->getSingleSlicePerSubPicFlag( ) ? 1 : 0, "single_slice_per_subpic_flag"); + } + if (pcPPS->getRectSliceFlag() & !(pcPPS->getSingleSlicePerSubPicFlag())) +#else + if (pcPPS->getRectSliceFlag()) +#endif { WRITE_UVLC( pcPPS->getNumSlicesInPic( ) - 1, "num_slices_in_pic_minus1" ); WRITE_FLAG( pcPPS->getTileIdxDeltaPresentFlag( ) ? 1 : 0, "tile_idx_delta_present_flag"); @@ -1001,6 +1036,9 @@ void HLSWriter::codeSPS( const SPS* pcSPS ) } CHECK( pcSPS->getMaxCUWidth() != pcSPS->getMaxCUHeight(), "Rectangular CTUs not supported" ); WRITE_FLAG(pcSPS->getLongTermRefsPresent() ? 1 : 0, "long_term_ref_pics_flag"); +#if JVET_O1159_SCALABILITY + WRITE_FLAG( pcSPS->getInterLayerPresentFlag() ? 1 : 0, "inter_layer_ref_pics_present_flag" ); +#endif #if JVET_P2001_SYNTAX_ORDER_MISMATCHES WRITE_FLAG(pcSPS->getIDRRefParamListPresent() ? 1 : 0, "sps_idr_rpl_present_flag" ); #endif @@ -1445,13 +1483,68 @@ void HLSWriter::codeVPS(const VPS* pcVPS) xTraceVPSHeader(); #endif WRITE_CODE(pcVPS->getVPSId(), 4, "vps_video_parameter_set_id"); +#if JVET_O1159_SCALABILITY + WRITE_CODE(pcVPS->getMaxLayers() - 1, 6, "vps_max_layers_minus1"); + WRITE_CODE(pcVPS->getMaxSubLayers() - 1, 3, "vps_max_sublayers_minus1"); + if (pcVPS->getMaxLayers() > 1 && pcVPS->getMaxSubLayers() > 1) + { + WRITE_FLAG(pcVPS->getAllLayersSameNumSublayersFlag(), "vps_all_layers_same_num_sublayers_flag"); + } + if (pcVPS->getMaxLayers() > 1) + { + WRITE_FLAG(pcVPS->getAllIndependentLayersFlag(), "vps_all_independent_layers_flag"); + } + for (uint32_t i = 0; i < pcVPS->getMaxLayers(); i++) + { + WRITE_CODE(pcVPS->getLayerId(i), 6, "vps_layer_id"); + if (i > 0 && !pcVPS->getAllIndependentLayersFlag()) + { + WRITE_FLAG(pcVPS->getIndependentLayerFlag(i), "vps_independent_layer_flag"); + if (!pcVPS->getIndependentLayerFlag(i)) + { + for (int j = 0; j < i; j++) + { + WRITE_FLAG(pcVPS->getDirectRefLayerFlag(i, j), "vps_direct_dependency_flag"); + } + } + } + } + if( pcVPS->getMaxLayers() > 1 ) + { + if (pcVPS->getAllIndependentLayersFlag()) + { + WRITE_FLAG(pcVPS->getEachLayerIsAnOlsFlag(), "vps_each_layer_is_an_ols_flag"); + } + if (!pcVPS->getEachLayerIsAnOlsFlag()) + { + if (!pcVPS->getAllIndependentLayersFlag()) { + WRITE_CODE(pcVPS->getOlsModeIdc(), 2, "vps_ols_mode_idc"); + } + if (pcVPS->getOlsModeIdc() == 2) + { + WRITE_CODE(pcVPS->getNumOutputLayerSets() - 1, 8, "vps_num_output_layer_sets_minus1"); + for (uint32_t i = 1; i < pcVPS->getNumOutputLayerSets(); i++) + { + for (uint32_t j = 0; j < pcVPS->getMaxLayers(); j++) + { + WRITE_FLAG(pcVPS->getOlsOutputLayerFlag(i, j), "vps_ols_output_layer_flag"); + } + } + } + } + } +#else WRITE_CODE(pcVPS->getMaxLayers() - 1, 8, "vps_max_layers_minus1"); +#if JVET_P0185 + CHECK(pcVPS->getMaxSubLayers() < 1 || pcVPS->getMaxSubLayers() > 7, "vps_max_sub_layers_minus1 must be in range 0..6"); + WRITE_CODE(pcVPS->getMaxSubLayers() - 1, 3, "vps_max_sub_layers_minus1"); +#endif for (uint32_t i = 0; i <= pcVPS->getMaxLayers() - 1; i++) { WRITE_CODE(pcVPS->getVPSIncludedLayerId(i), 7, "vps_included_layer_id"); WRITE_FLAG(0, "vps_reserved_zero_1bit"); } - +#endif WRITE_FLAG(0, "vps_extension_flag"); //future extensions here.. diff --git a/source/Lib/Utilities/program_options_lite.h b/source/Lib/Utilities/program_options_lite.h index 23aa1803f25d985545e945edfe782e36ebf15323..8375a2aa77ef03ffc8d4a2119811ce654a3da501 100644 --- a/source/Lib/Utilities/program_options_lite.h +++ b/source/Lib/Utilities/program_options_lite.h @@ -232,7 +232,63 @@ namespace df parent.addOption(new Option<T>(name, storage, default_val, desc)); return *this; } +#if 1 //JVET_O1159_SCALABILITY + template<typename T> + OptionSpecific& + operator()(const std::string& name, T* storage, T default_val, unsigned uiMaxNum, const std::string& desc = "") + { + std::string cNameBuffer; + std::string cDescriptionBuffer; + + for (unsigned int uiK = 0; uiK < uiMaxNum; uiK++) + { + // it needs to be reset when extra digit is added, e.g. number 10 and above + cNameBuffer.resize(name.size() + 10); + cDescriptionBuffer.resize(desc.size() + 10); + + // isn't there are sprintf function for string?? + sprintf((char*)cNameBuffer.c_str(), name.c_str(), uiK, uiK); + sprintf((char*)cDescriptionBuffer.c_str(), desc.c_str(), uiK, uiK); + + size_t pos = cNameBuffer.find_first_of('\0'); + if (pos != std::string::npos) + { + cNameBuffer.resize(pos); + } + + parent.addOption(new Option<T>(cNameBuffer, (storage[uiK]), default_val, cDescriptionBuffer)); + } + + return *this; + } + template<typename T> + OptionSpecific& + operator()(const std::string& name, T** storage, T default_val, unsigned uiMaxNum, const std::string& desc = "") + { + std::string cNameBuffer; + std::string cDescriptionBuffer; + + for (unsigned int uiK = 0; uiK < uiMaxNum; uiK++) + { + // it needs to be reset when extra digit is added, e.g. number 10 and above + cNameBuffer.resize(name.size() + 10); + cDescriptionBuffer.resize(desc.size() + 10); + + // isn't there are sprintf function for string?? + sprintf((char*)cNameBuffer.c_str(), name.c_str(), uiK, uiK); + sprintf((char*)cDescriptionBuffer.c_str(), desc.c_str(), uiK, uiK); + + size_t pos = cNameBuffer.find_first_of('\0'); + if (pos != std::string::npos) + cNameBuffer.resize(pos); + + parent.addOption(new Option<T>(cNameBuffer, *(storage[uiK]), default_val, cDescriptionBuffer)); + } + + return *this; + } +#endif /** * Add option described by name to the parent Options list, * with desc as an optional help description