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/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 21d4da6018d45c47638d2f9c0e5d2e694a0e4fec..49bdad2c4452833e4cdb41a90687df8355493f26 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); @@ -848,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 6107fbd90ffe43d213bf96348d0d993406dc29be..3c90bde664c6c0580953828033fdf571063a7ead 100644 --- a/source/App/EncoderApp/EncAppCfg.cpp +++ b/source/App/EncoderApp/EncAppCfg.cpp @@ -1699,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 ; diff --git a/source/App/EncoderApp/EncAppCfg.h b/source/App/EncoderApp/EncAppCfg.h index b54e519a3e92a15f11e439ef313eb542057fcd76..132fcb6640e7c4caeddcba5a31c5f42892aeb3e9 100644 --- a/source/App/EncoderApp/EncAppCfg.h +++ b/source/App/EncoderApp/EncAppCfg.h @@ -801,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/Slice.cpp b/source/Lib/CommonLib/Slice.cpp index c9f7094d192d899eaad2258dc5714e2480ef7a52..6baa4e0837cc1e4933ab6e49234ef0b0f23f1953 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); } @@ -2716,29 +2876,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 @@ -3802,7 +3982,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 10445a769b60b0fc870b8f50c224fc1bdb907439..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 @@ -753,11 +782,28 @@ class VPS 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: @@ -774,13 +820,51 @@ public: #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 @@ -1155,6 +1239,9 @@ private: #if JVET_P0590_SCALING_WINDOW bool m_rprEnabledFlag; #endif +#if JVET_O1159_SCALABILITY + bool m_interLayerPresentFlag; +#endif public: @@ -1495,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 + }; @@ -2735,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; } @@ -3091,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 52230ea43ce8f6cb3fce2e55aefbf1ea535880cd..299054145413ef272c4804915bfba151b217e68d 100644 --- a/source/Lib/CommonLib/TypeDef.h +++ b/source/Lib/CommonLib/TypeDef.h @@ -54,6 +54,8 @@ #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 +151,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 @@ -285,7 +289,7 @@ 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/VLCReader.cpp b/source/Lib/DecoderLib/VLCReader.cpp index 713d78f38d51f17412fa0372d18943b0b053eaef..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 ) @@ -1586,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 @@ -2155,7 +2211,83 @@ void HLSyntaxReader::parseVPS(VPS* pcVPS) READ_CODE(4, uiCode, "vps_video_parameter_set_id"); pcVPS->setVPSId(uiCode); #endif - READ_CODE(8, uiCode, "vps_max_layers_minus1"); pcVPS->setMaxLayers(uiCode + 1); CHECK(uiCode + 1 > MAX_VPS_LAYERS, "Invalid code"); +#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 @@ -2164,7 +2296,7 @@ void HLSyntaxReader::parseVPS(VPS* pcVPS) 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) { @@ -2401,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); @@ -3247,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); @@ -3332,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 62d4a08aa8916773e969f5e8d63e6dd923c48e19..a73aabaad7e1a706bac77846dde4c536466df621 100644 --- a/source/Lib/EncoderLib/EncCfg.h +++ b/source/Lib/EncoderLib/EncCfg.h @@ -853,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() @@ -2156,6 +2159,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 4b92807dcc7c36414500c97d5c2a5e2e55de7cc2..1f5ab6eda8ae81e8a4d7daed06567e3f7a4b1610 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 } } @@ -415,6 +425,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; @@ -434,7 +447,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 @@ -2060,7 +2077,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 @@ -2108,7 +2129,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 @@ -2399,12 +2424,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 @@ -2414,6 +2451,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; @@ -2958,7 +3003,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 @@ -3071,7 +3120,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 @@ -3278,7 +3331,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 ); @@ -4650,6 +4707,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, "]" ); } @@ -5450,4 +5516,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 c38ef30789b736aaa92e9de29b432bd27d79711b..53c734c219f9122192aea730515251e92bcffd54 100644 --- a/source/Lib/EncoderLib/EncLib.cpp +++ b/source/Lib/EncoderLib/EncLib.cpp @@ -243,7 +243,11 @@ 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 @@ -469,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 @@ -629,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 @@ -762,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 @@ -1099,7 +1115,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 @@ -1338,7 +1358,6 @@ void EncLib::xGetNewPicBuffer ( std::list<PelUnitBuf*>& rcListPicYuvRecOut, Pict m_iNumPicRcvd++; } - #if JVET_P0185 void EncLib::xInitVPS(VPS& vps, const SPS& sps) #else @@ -1350,14 +1369,15 @@ void EncLib::xInitVPS(VPS& vps) #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) @@ -1376,8 +1396,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(); @@ -1436,7 +1459,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 ); @@ -1690,7 +1715,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 } @@ -2173,10 +2201,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 c5b338d5f5910878c6882445a93955a767e1e194..a7eebb41cbbd5da2d32e87344c51bebd2e3714ea 100644 --- a/source/Lib/EncoderLib/EncLib.h +++ b/source/Lib/EncoderLib/EncLib.h @@ -184,7 +184,11 @@ protected: 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/VLCWriter.cpp b/source/Lib/EncoderLib/VLCWriter.cpp index 8a4339e5da510adff848940ece9ec87e5af016c3..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 } } @@ -1009,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 @@ -1453,6 +1483,57 @@ 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"); @@ -1463,7 +1544,7 @@ void HLSWriter::codeVPS(const VPS* pcVPS) 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