From ffe2c6a7760e9a34624399713853a95055a7e6e5 Mon Sep 17 00:00:00 2001 From: Brian Heng <brian.heng@broadcom.com> Date: Thu, 21 Nov 2019 14:40:05 +0100 Subject: [PATCH] JVET-P1006: Picture Header - Add picture header and related syntax changes. --- doc/software-manual.tex | 24 + source/App/DecoderApp/DecApp.cpp | 166 ++++ source/App/DecoderApp/DecApp.h | 3 + source/App/EncoderApp/EncApp.cpp | 9 + source/App/EncoderApp/EncAppCfg.cpp | 12 + source/App/EncoderApp/EncAppCfg.h | 6 + source/App/Parcat/parcat.cpp | 47 +- source/Lib/CommonLib/AdaptiveLoopFilter.cpp | 81 ++ source/Lib/CommonLib/AdaptiveLoopFilter.h | 4 + source/Lib/CommonLib/CodingStructure.cpp | 3 + source/Lib/CommonLib/CodingStructure.h | 3 + source/Lib/CommonLib/CommonDef.h | 3 + source/Lib/CommonLib/ContextModelling.cpp | 4 + source/Lib/CommonLib/DepQuant.cpp | 24 + source/Lib/CommonLib/InterPrediction.cpp | 8 + source/Lib/CommonLib/LoopFilter.cpp | 50 + source/Lib/CommonLib/LoopFilter.h | 4 + source/Lib/CommonLib/Picture.cpp | 15 + source/Lib/CommonLib/Picture.h | 4 + source/Lib/CommonLib/Quant.cpp | 28 +- source/Lib/CommonLib/QuantRDOQ.cpp | 16 + source/Lib/CommonLib/SampleAdaptiveOffset.cpp | 59 ++ source/Lib/CommonLib/SampleAdaptiveOffset.h | 4 + source/Lib/CommonLib/Slice.cpp | 322 +++++++ source/Lib/CommonLib/Slice.h | 403 +++++++- source/Lib/CommonLib/TypeDef.h | 2 + source/Lib/CommonLib/UnitPartitioner.cpp | 5 + source/Lib/CommonLib/UnitTools.cpp | 56 ++ source/Lib/DecoderLib/CABACReader.cpp | 60 ++ source/Lib/DecoderLib/DecCu.cpp | 46 + source/Lib/DecoderLib/DecLib.cpp | 176 ++++ source/Lib/DecoderLib/DecLib.h | 11 +- source/Lib/DecoderLib/DecSlice.cpp | 5 + source/Lib/DecoderLib/VLCReader.cpp | 866 +++++++++++++++++- source/Lib/DecoderLib/VLCReader.h | 5 + source/Lib/EncoderLib/CABACWriter.cpp | 60 ++ .../Lib/EncoderLib/EncAdaptiveLoopFilter.cpp | 12 + source/Lib/EncoderLib/EncCfg.h | 16 + source/Lib/EncoderLib/EncCu.cpp | 80 ++ source/Lib/EncoderLib/EncGOP.cpp | 269 ++++++ source/Lib/EncoderLib/EncGOP.h | 7 + source/Lib/EncoderLib/EncLib.cpp | 185 +++- source/Lib/EncoderLib/EncLib.h | 6 + source/Lib/EncoderLib/EncModeCtrl.cpp | 8 + .../EncoderLib/EncSampleAdaptiveOffset.cpp | 22 + source/Lib/EncoderLib/EncSlice.cpp | 49 + source/Lib/EncoderLib/EncSlice.h | 3 + source/Lib/EncoderLib/InterSearch.cpp | 100 ++ source/Lib/EncoderLib/IntraSearch.cpp | 52 ++ source/Lib/EncoderLib/VLCWriter.cpp | 666 ++++++++++++++ source/Lib/EncoderLib/VLCWriter.h | 3 + 51 files changed, 4061 insertions(+), 11 deletions(-) diff --git a/doc/software-manual.tex b/doc/software-manual.tex index 2f10b24f5..6f687cfb4 100755 --- a/doc/software-manual.tex +++ b/doc/software-manual.tex @@ -2220,6 +2220,30 @@ Enables signaling the below parameters either in PPS or for each slice according \end{tabular} \\ +\Option{SliceLevelRpl} & +%\ShortOption{\None} & +\Default{true} & +Code reference picture lists in slice headers rather than picture header. +\\ + +\Option{SliceLevelDblk} & +%\ShortOption{\None} & +\Default{true} & +Code deblocking filter parameters in slice headers rather than picture header. +\\ + +\Option{SliceLevelSao} & +%\ShortOption{\None} & +\Default{true} & +Code SAO parameters in slice headers rather than picture header. +\\ + +\Option{SliceLevelAlf} & +%\ShortOption{\None} & +\Default{true} & +Code ALF parameters in slice headers rather than picture header. +\\ + \Option{TransformSkip} & %\ShortOption{\None} & \Default{false} & diff --git a/source/App/DecoderApp/DecApp.cpp b/source/App/DecoderApp/DecApp.cpp index 25f95b3a6..c5ec40de6 100644 --- a/source/App/DecoderApp/DecApp.cpp +++ b/source/App/DecoderApp/DecApp.cpp @@ -118,6 +118,48 @@ uint32_t DecApp::decode() while (!!bitstreamFile) { +#if JVET_P1006_PICTURE_HEADER + InputNALUnit nalu; + nalu.m_nalUnitType = NAL_UNIT_INVALID; + + // determine if next NAL unit will be the first one from a new picture + bool bNewPicture = isNewPicture(&bitstreamFile, &bytestream); + if(!bNewPicture) + { + AnnexBStats stats = AnnexBStats(); + + // find next NAL unit in stream + byteStreamNALUnit(bytestream, nalu.getBitstream().getFifo(), stats); + if (nalu.getBitstream().getFifo().empty()) + { + /* this can happen if the following occur: + * - empty input file + * - two back-to-back start_code_prefixes + * - start_code_prefix immediately followed by EOF + */ + msg( ERROR, "Warning: Attempt to decode an empty NAL unit\n"); + } + else + { + // read NAL unit header + read(nalu); + + // flush output for first slice of an IDR picture + if(m_cDecLib.getFirstSliceInPicture() && + (nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_IDR_W_RADL || + nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_IDR_N_LP)) + { + xFlushOutput(pcListPic); + } + + // parse NAL unit syntax if within target decoding layer + if ((m_iMaxTemporalLayer < 0 || nalu.m_temporalId <= m_iMaxTemporalLayer) && isNaluWithinTargetDecLayerIdSet(&nalu) && isNaluTheTargetLayer(&nalu)) + { + m_cDecLib.decode(nalu, m_iSkipFrame, m_iPOCLastDisplay); + } + } + } +#else /* location serves to work around a design fault in the decoder, whereby * the process of reading a new slice that is the first slice of a new frame * requires the DecApp::decode() method to be called again with the same @@ -199,6 +241,7 @@ uint32_t DecApp::decode() } } +#endif if( ( bNewPicture || !bitstreamFile || nalu.m_nalUnitType == NAL_UNIT_EOS ) && !m_cDecLib.getFirstSliceInSequence() ) @@ -207,8 +250,10 @@ uint32_t DecApp::decode() { m_cDecLib.executeLoopFilters(); m_cDecLib.finishPicture( poc, pcListPic ); +#if !JVET_P1006_PICTURE_HEADER #if RExt__DECODER_DEBUG_TOOL_MAX_FRAME_STATS CodingStatistics::UpdateMaxStat(backupStats); +#endif #endif } loopFiltered = (nalu.m_nalUnitType == NAL_UNIT_EOS); @@ -287,8 +332,17 @@ uint32_t DecApp::decode() xWriteOutput( pcListPic, nalu.m_temporalId ); } } +#if JVET_P1006_PICTURE_HEADER + if(bNewPicture) + { + m_cDecLib.resetAccessUnitNals(); + m_cDecLib.resetAccessUnitApsNals(); + } +#endif +#if !JVET_P1006_PICTURE_HEADER #if RExt__DECODER_DEBUG_STATISTICS delete backupStats; +#endif #endif } @@ -311,6 +365,118 @@ uint32_t DecApp::decode() return nRet; } +#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 + */ +bool DecApp::isNewPicture(ifstream *bitstreamFile, class InputByteStream *bytestream) +{ + bool ret = false; + bool finished = false; + + // cannot be a new picture if there haven't been any slices yet + if(m_cDecLib.getFirstSliceInPicture()) + { + return false; + } + + // save stream position for backup +#if RExt__DECODER_DEBUG_STATISTICS + CodingStatistics::CodingStatisticsData* backupStats = new CodingStatistics::CodingStatisticsData(CodingStatistics::GetStatistics()); + streampos location = bitstreamFile->tellg() - streampos(bytestream->GetNumBufferedBytes()); +#else + streampos location = bitstreamFile->tellg(); +#endif + + // look ahead until picture start location is determined + while (!finished && !!(*bitstreamFile)) + { + AnnexBStats stats = AnnexBStats(); + InputNALUnit nalu; + byteStreamNALUnit(*bytestream, nalu.getBitstream().getFifo(), stats); + if (nalu.getBitstream().getFifo().empty()) + { + msg( ERROR, "Warning: Attempt to decode an empty NAL unit\n"); + } + else + { + // get next NAL unit type + read(nalu); + switch( nalu.m_nalUnitType ) { + + // NUT that indicate the start of a new picture + case NAL_UNIT_ACCESS_UNIT_DELIMITER: + case NAL_UNIT_DPS: + case NAL_UNIT_VPS: + case NAL_UNIT_SPS: + case NAL_UNIT_PPS: + case NAL_UNIT_PH: + ret = true; + finished = true; + break; + + // NUT that are not the start of a new picture + case NAL_UNIT_CODED_SLICE_TRAIL: + case NAL_UNIT_CODED_SLICE_STSA: + case NAL_UNIT_CODED_SLICE_RASL: + case NAL_UNIT_CODED_SLICE_RADL: + case NAL_UNIT_RESERVED_VCL_4: + case NAL_UNIT_RESERVED_VCL_5: + case NAL_UNIT_RESERVED_VCL_6: + case NAL_UNIT_CODED_SLICE_IDR_W_RADL: + case NAL_UNIT_CODED_SLICE_IDR_N_LP: + case NAL_UNIT_CODED_SLICE_CRA: + case NAL_UNIT_CODED_SLICE_GDR: + case NAL_UNIT_RESERVED_IRAP_VCL_11: + case NAL_UNIT_RESERVED_IRAP_VCL_12: + case NAL_UNIT_EOS: + case NAL_UNIT_EOB: +#if JVET_P0588_SUFFIX_APS + case NAL_UNIT_SUFFIX_APS: +#endif + case NAL_UNIT_SUFFIX_SEI: + case NAL_UNIT_FD: + ret = false; + finished = true; + break; + + // NUT that might indicate the start of a new picture - keep looking +#if JVET_P0588_SUFFIX_APS + case NAL_UNIT_PREFIX_APS: +#else + case NAL_UNIT_APS: +#endif + case NAL_UNIT_PREFIX_SEI: + case NAL_UNIT_RESERVED_NVCL_26: + case NAL_UNIT_RESERVED_NVCL_27: + case NAL_UNIT_UNSPECIFIED_28: + case NAL_UNIT_UNSPECIFIED_29: + case NAL_UNIT_UNSPECIFIED_30: + case NAL_UNIT_UNSPECIFIED_31: + default: + break; + } + } + } + + // restore previous stream location - minus 3 due to the need for the annexB parser to read three extra bytes +#if RExt__DECODER_DEBUG_BIT_STATISTICS + bitstreamFile->clear(); + bitstreamFile->seekg(location); + bytestream->reset(); + CodingStatistics::SetStatistics(*backupStats); + delete backupStats; +#else + bitstreamFile->clear(); + bitstreamFile->seekg(location-streamoff(3)); + bytestream->reset(); +#endif + + // return TRUE if next NAL unit is the start of a new picture + return ret; +} +#endif + // ==================================================================================================================== // Protected member functions // ==================================================================================================================== diff --git a/source/App/DecoderApp/DecApp.h b/source/App/DecoderApp/DecApp.h index a912738ca..f3108e7c7 100644 --- a/source/App/DecoderApp/DecApp.h +++ b/source/App/DecoderApp/DecApp.h @@ -91,6 +91,9 @@ private: #endif bool isNaluWithinTargetDecLayerIdSet ( InputNALUnit* nalu ); ///< check whether given Nalu is within targetDecLayerIdSet bool isNaluTheTargetLayer(InputNALUnit* nalu); ///< check whether given Nalu is within targetDecLayerIdSet +#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 +#endif }; //! \} diff --git a/source/App/EncoderApp/EncApp.cpp b/source/App/EncoderApp/EncApp.cpp index 8023735a7..a4fd3fbf1 100644 --- a/source/App/EncoderApp/EncApp.cpp +++ b/source/App/EncoderApp/EncApp.cpp @@ -572,6 +572,12 @@ void EncApp::xInitLibCfg() m_cEncLib.setLFCrossTileBoundaryFlag ( m_bLFCrossTileBoundaryFlag ); m_cEncLib.setEntropyCodingSyncEnabledFlag ( m_entropyCodingSyncEnabledFlag ); m_cEncLib.setTMVPModeId ( m_TMVPModeId ); +#if JVET_P1006_PICTURE_HEADER + m_cEncLib.setSliceLevelRpl ( m_sliceLevelRpl ); + m_cEncLib.setSliceLevelDblk ( m_sliceLevelDblk ); + m_cEncLib.setSliceLevelSao ( m_sliceLevelSao ); + m_cEncLib.setSliceLevelAlf ( m_sliceLevelAlf ); +#endif m_cEncLib.setConstantSliceHeaderParamsEnabledFlag ( m_constantSliceHeaderParamsEnabledFlag ); m_cEncLib.setPPSDepQuantEnabledIdc ( m_PPSDepQuantEnabledIdc ); m_cEncLib.setPPSRefPicListSPSIdc0 ( m_PPSRefPicListSPSIdc0 ); @@ -1181,6 +1187,9 @@ void EncApp::rateStatsAccum(const AccessUnit& au, const std::vector<uint32_t>& a case NAL_UNIT_VPS: case NAL_UNIT_SPS: case NAL_UNIT_PPS: +#if JVET_P1006_PICTURE_HEADER + case NAL_UNIT_PH: +#endif #if JVET_P0588_SUFFIX_APS case NAL_UNIT_PREFIX_APS: case NAL_UNIT_SUFFIX_APS: diff --git a/source/App/EncoderApp/EncAppCfg.cpp b/source/App/EncoderApp/EncAppCfg.cpp index d2fdacf3b..0164f4c63 100644 --- a/source/App/EncoderApp/EncAppCfg.cpp +++ b/source/App/EncoderApp/EncAppCfg.cpp @@ -855,7 +855,11 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] ) ("ConfWinRight", m_confWinRight, 0, "Right offset for window conformance mode 3") ("ConfWinTop", m_confWinTop, 0, "Top offset for window conformance mode 3") ("ConfWinBottom", m_confWinBottom, 0, "Bottom offset for window conformance mode 3") +#if JVET_P1006_PICTURE_HEADER + ("AccessUnitDelimiter", m_AccessUnitDelimiter, false, "Enable Access Unit Delimiter NALUs") +#else ("AccessUnitDelimiter", m_AccessUnitDelimiter, true, "Enable Access Unit Delimiter NALUs") +#endif ("FrameRate,-fr", m_iFrameRate, 0, "Frame rate") ("FrameSkip,-fs", m_FrameSkip, 0u, "Number of frames to skip at start of input YUV") ("TemporalSubsampleRatio,-ts", m_temporalSubsampleRatio, 1u, "Temporal sub-sample ratio when reading input YUV") @@ -1217,6 +1221,12 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] ) ("TMVPMode", m_TMVPModeId, 1, "TMVP mode 0: TMVP disable for all slices. 1: TMVP enable for all slices (default) 2: TMVP enable for certain slices only") ("PPSorSliceMode", m_PPSorSliceMode, 0, "Enable signalling certain parameters either in PPS or per slice\n" "\tmode 0: Always per slice (default), 1: RA settings, 2: LDB settings, 3: LDP settings") +#if JVET_P1006_PICTURE_HEADER + ("SliceLevelRpl", m_sliceLevelRpl, true, "Code reference picture lists in slice headers rather than picture header.") + ("SliceLevelDblk", m_sliceLevelDblk, true, "Code deblocking filter parameters in slice headers rather than picture header.") + ("SliceLevelSao", m_sliceLevelSao, true, "Code SAO parameters in slice headers rather than picture header.") + ("SliceLevelAlf", m_sliceLevelAlf, true, "Code ALF parameters in slice headers rather than picture header.") +#endif ("FEN", tmpFastInterSearchMode, int(FASTINTERSEARCH_DISABLED), "fast encoder setting") ("ECU", m_bUseEarlyCU, false, "Early CU setting") ("FDM", m_useFastDecisionForMerge, true, "Fast decision for Merge RD Cost") @@ -2189,10 +2199,12 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] ) } #endif +#if !JVET_P1006_PICTURE_HEADER if (m_AccessUnitDelimiter == false) { printf ("Warning: Access unit delimiters are disabled. VVC requires the presence of access unit delimiters\n"); } +#endif #if JVET_O0756_CONFIG_HDRMETRICS && !JVET_O0756_CALCULATE_HDRMETRICS if ( m_calculateHdrMetrics == true) diff --git a/source/App/EncoderApp/EncAppCfg.h b/source/App/EncoderApp/EncAppCfg.h index db0b21c07..69e59f2f1 100644 --- a/source/App/EncoderApp/EncAppCfg.h +++ b/source/App/EncoderApp/EncAppCfg.h @@ -542,6 +542,12 @@ protected: uint32_t m_maxNumTriangleCand; uint32_t m_maxNumIBCMergeCand; ///< Max number of IBC merge candidates +#if JVET_P1006_PICTURE_HEADER + bool m_sliceLevelRpl; ///< code reference picture lists in slice headers rather than picture header + bool m_sliceLevelDblk; ///< code deblocking filter parameters in slice headers rather than picture header + bool m_sliceLevelSao; ///< code SAO parameters in slice headers rather than picture header + bool m_sliceLevelAlf; ///< code ALF parameters in slice headers rather than picture header +#endif int m_TMVPModeId; int m_PPSorSliceMode; bool m_constantSliceHeaderParamsEnabledFlag; diff --git a/source/App/Parcat/parcat.cpp b/source/App/Parcat/parcat.cpp index f614dcc1a..4c2136582 100644 --- a/source/App/Parcat/parcat.cpp +++ b/source/App/Parcat/parcat.cpp @@ -48,9 +48,20 @@ class ParcatHLSyntaxReader : public VLCReader { public: +#if JVET_P1006_PICTURE_HEADER + void parseSliceHeaderUpToPoc ( ParameterSetManager *parameterSetManager ); +#else bool parseSliceHeaderUpToPoc ( ParameterSetManager *parameterSetManager, bool isRapPic ); +#endif }; +#if JVET_P1006_PICTURE_HEADER +void ParcatHLSyntaxReader::parseSliceHeaderUpToPoc ( ParameterSetManager *parameterSetManager ) +{ + // POC is first syntax element in slice header + return; +} +#else bool ParcatHLSyntaxReader::parseSliceHeaderUpToPoc ( ParameterSetManager *parameterSetManager, bool isRapPic ) { uint32_t uiCode; @@ -120,6 +131,7 @@ bool ParcatHLSyntaxReader::parseSliceHeaderUpToPoc ( ParameterSetManager *parame return firstSliceSegmentInPic; } +#endif /** Find the beginning and end of a NAL (Network Abstraction Layer) unit in a byte buffer containing H264 bitstream data. @@ -296,6 +308,9 @@ std::vector<uint8_t> filter_segment(const std::vector<uint8_t> & v, int idx, int int bits_for_poc = 8; bool skip_next_sei = false; +#if JVET_P1006_PICTURE_HEADER + bool first_slice_segment_in_pic_flag = false; +#endif while(find_nal_unit(p, sz, &nal_start, &nal_end) > 0) { @@ -342,19 +357,33 @@ std::vector<uint8_t> filter_segment(const std::vector<uint8_t> & v, int idx, int HLSReader.parsePPS( pps, ¶meterSetManager ); parameterSetManager.storePPS( pps, inp_nalu.getBitstream().getFifo() ); } +#if JVET_P1006_PICTURE_HEADER + if( inp_nalu.m_nalUnitType == NAL_UNIT_PH ) + { + first_slice_segment_in_pic_flag = true; + } +#endif if(nalu_type == NAL_UNIT_CODED_SLICE_IDR_W_RADL || nalu_type == NAL_UNIT_CODED_SLICE_IDR_N_LP) { poc = 0; new_poc = *poc_base + poc; +#if JVET_P1006_PICTURE_HEADER + first_slice_segment_in_pic_flag = false; +#endif } #if JVET_P0363_CLEANUP_NUT_TABLE - if((nalu_type < NAL_UNIT_CODED_SLICE_IDR_W_RADL) || (nalu_type > NAL_UNIT_CODED_SLICE_IDR_N_LP && nalu_type < NAL_UNIT_RESERVED_IRAP_VCL_12) ) + if((nalu_type < NAL_UNIT_CODED_SLICE_IDR_W_RADL) || (nalu_type > NAL_UNIT_CODED_SLICE_IDR_N_LP && nalu_type <= NAL_UNIT_RESERVED_IRAP_VCL_12) ) #else if((nalu_type < 7) || (nalu_type > 9 && nalu_type < 15) ) #endif { parcatHLSReader.setBitstream( &inp_nalu.getBitstream() ); +#if JVET_P1006_PICTURE_HEADER + + // beginning of slice header parsing, taken from VLCReader + parcatHLSReader.parseSliceHeaderUpToPoc( ¶meterSetManager ); +#else bool isRapPic = inp_nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_IDR_W_RADL || inp_nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_IDR_N_LP @@ -362,6 +391,7 @@ std::vector<uint8_t> filter_segment(const std::vector<uint8_t> & v, int idx, int // beginning of slice header parsing, taken from VLCReader bool first_slice_segment_in_pic_flag = parcatHLSReader.parseSliceHeaderUpToPoc( ¶meterSetManager, isRapPic); +#endif int num_bits_up_to_poc_lsb = parcatHLSReader.getBitstream()->getNumBitsRead(); int offset = num_bits_up_to_poc_lsb; @@ -376,7 +406,11 @@ std::vector<uint8_t> filter_segment(const std::vector<uint8_t> & v, int idx, int // int picOrderCntLSB = (pcSlice->getPOC()-pcSlice->getLastIDR()+(1<<pcSlice->getSPS()->getBitsForPOC())) & ((1<<pcSlice->getSPS()->getBitsForPOC())-1); unsigned picOrderCntLSB = (new_poc - *last_idr_poc +(1 << bits_for_poc)) & ((1<<bits_for_poc)-1); +#if JVET_P1006_PICTURE_HEADER + int low = data & ((1 << low_bits) - 1); +#else int low = data & ((1 << (low_bits + 1)) - 1); +#endif int hi = data >> (16 - hi_bits); data = (hi << (16 - hi_bits)) | (picOrderCntLSB << low_bits) | low; @@ -389,6 +423,9 @@ std::vector<uint8_t> filter_segment(const std::vector<uint8_t> & v, int idx, int std::cout << "Changed poc " << poc << " to " << new_poc << std::endl; #endif ++cnt; +#if JVET_P1006_PICTURE_HEADER + first_slice_segment_in_pic_flag = false; +#endif } } @@ -398,10 +435,18 @@ std::vector<uint8_t> filter_segment(const std::vector<uint8_t> & v, int idx, int idr_found = true; } +#if JVET_P1006_PICTURE_HEADER +#if JVET_P0588_SUFFIX_APS + if( ( idx > 1 && ( nalu_type == NAL_UNIT_CODED_SLICE_IDR_W_RADL || nalu_type == NAL_UNIT_CODED_SLICE_IDR_N_LP ) ) || ( ( idx > 1 && !idr_found ) && ( nalu_type == NAL_UNIT_DPS || nalu_type == NAL_UNIT_VPS || nalu_type == NAL_UNIT_SPS || nalu_type == NAL_UNIT_PPS || nalu_type == NAL_UNIT_PREFIX_APS || nalu_type == NAL_UNIT_SUFFIX_APS || nalu_type == NAL_UNIT_PH || nalu_type == NAL_UNIT_ACCESS_UNIT_DELIMITER ) ) +#else + if((idx > 1 && (nalu_type == NAL_UNIT_CODED_SLICE_IDR_W_RADL || nalu_type == NAL_UNIT_CODED_SLICE_IDR_N_LP)) || ((idx > 1 && !idr_found) && (nalu_type == NAL_UNIT_DPS || nalu_type == NAL_UNIT_VPS ||nalu_type == NAL_UNIT_SPS || nalu_type == NAL_UNIT_PPS || nalu_type == NAL_UNIT_APS || nalu_type == NAL_UNIT_PH || nalu_type == NAL_UNIT_ACCESS_UNIT_DELIMITER)) +#endif +#else #if JVET_P0588_SUFFIX_APS if( ( idx > 1 && ( nalu_type == NAL_UNIT_CODED_SLICE_IDR_W_RADL || nalu_type == NAL_UNIT_CODED_SLICE_IDR_N_LP ) ) || ( ( idx > 1 && !idr_found ) && ( nalu_type == NAL_UNIT_DPS || nalu_type == NAL_UNIT_VPS || nalu_type == NAL_UNIT_SPS || nalu_type == NAL_UNIT_PPS || nalu_type == NAL_UNIT_PREFIX_APS || nalu_type == NAL_UNIT_SUFFIX_APS || nalu_type == NAL_UNIT_ACCESS_UNIT_DELIMITER ) ) #else if((idx > 1 && (nalu_type == NAL_UNIT_CODED_SLICE_IDR_W_RADL || nalu_type == NAL_UNIT_CODED_SLICE_IDR_N_LP)) || ((idx > 1 && !idr_found) && (nalu_type == NAL_UNIT_DPS || nalu_type == NAL_UNIT_VPS ||nalu_type == NAL_UNIT_SPS || nalu_type == NAL_UNIT_PPS || nalu_type == NAL_UNIT_APS || nalu_type == NAL_UNIT_ACCESS_UNIT_DELIMITER)) +#endif #endif || (nalu_type == NAL_UNIT_SUFFIX_SEI && skip_next_sei)) { diff --git a/source/Lib/CommonLib/AdaptiveLoopFilter.cpp b/source/Lib/CommonLib/AdaptiveLoopFilter.cpp index 9c4659257..d8294c312 100644 --- a/source/Lib/CommonLib/AdaptiveLoopFilter.cpp +++ b/source/Lib/CommonLib/AdaptiveLoopFilter.cpp @@ -78,6 +78,9 @@ void AdaptiveLoopFilter::getAlfBoundary( const CodingStructure& cs, int posX, in { const Slice& slice = *( cs.slice ); const PPS& pps = *( cs.pps ); +#if JVET_P1006_PICTURE_HEADER + const PicHeader& picHeader = *( cs.picHeader ); +#endif int ctuSize = slice.getSPS()->getCTUSize(); const Position currCtuPos( posX, posY ); const CodingUnit *currCtu = cs.getCU( currCtuPos, CHANNEL_TYPE_LUMA ); @@ -91,7 +94,11 @@ void AdaptiveLoopFilter::getAlfBoundary( const CodingStructure& cs, int posX, in const Position prevCtuPos( posX, posY - ctuSize ); const CodingUnit *prevCtu = cs.getCU( prevCtuPos, CHANNEL_TYPE_LUMA ); +#if JVET_P1006_PICTURE_HEADER + if ( !pps.getLoopFilterAcrossSlicesEnabledFlag() && !CU::isSameSlice( *currCtu, *prevCtu ) ) +#else if ( !slice.getLFCrossSliceBoundaryFlag() && !CU::isSameSlice( *currCtu, *prevCtu ) ) +#endif { topBry = posY; } @@ -108,7 +115,11 @@ void AdaptiveLoopFilter::getAlfBoundary( const CodingStructure& cs, int posX, in const Position nextCtuPos( posX, posY + ctuSize ); const CodingUnit *nextCtu = cs.getCU( nextCtuPos, CHANNEL_TYPE_LUMA ); +#if JVET_P1006_PICTURE_HEADER + if ( !pps.getLoopFilterAcrossSlicesEnabledFlag() && !CU::isSameSlice( *currCtu, *nextCtu ) ) +#else if ( !slice.getLFCrossSliceBoundaryFlag() && !CU::isSameSlice( *currCtu, *nextCtu ) ) +#endif { botBry = posY + ctuSize; } @@ -125,7 +136,11 @@ void AdaptiveLoopFilter::getAlfBoundary( const CodingStructure& cs, int posX, in const Position prevCtuPos( posX - ctuSize, posY ); const CodingUnit *prevCtu = cs.getCU( prevCtuPos, CHANNEL_TYPE_LUMA ); +#if JVET_P1006_PICTURE_HEADER + if ( !pps.getLoopFilterAcrossSlicesEnabledFlag() && !CU::isSameSlice( *currCtu, *prevCtu ) ) +#else if ( !slice.getLFCrossSliceBoundaryFlag() && !CU::isSameSlice( *currCtu, *prevCtu ) ) +#endif { leftBry = posX; } @@ -142,7 +157,11 @@ void AdaptiveLoopFilter::getAlfBoundary( const CodingStructure& cs, int posX, in const Position nextCtuPos( posX + ctuSize, posY ); const CodingUnit *nextCtu = cs.getCU( nextCtuPos, CHANNEL_TYPE_LUMA ); +#if JVET_P1006_PICTURE_HEADER + if ( !pps.getLoopFilterAcrossSlicesEnabledFlag() && !CU::isSameSlice( *currCtu, *nextCtu ) ) +#else if ( !slice.getLFCrossSliceBoundaryFlag() && !CU::isSameSlice( *currCtu, *nextCtu ) ) +#endif { rightBry = posX + ctuSize; } @@ -153,6 +172,34 @@ void AdaptiveLoopFilter::getAlfBoundary( const CodingStructure& cs, int posX, in } } +#if JVET_P1006_PICTURE_HEADER + if( picHeader.getLoopFilterAcrossVirtualBoundariesDisabledFlag() ) + { + for( int i = 0; i < picHeader.getNumHorVirtualBoundaries(); i++ ) + { + if( picHeader.getVirtualBoundariesPosY( i ) == posY ) + { + topBry = posY; + } + else if( picHeader.getVirtualBoundariesPosY( i ) == posY + ctuSize ) + { + botBry = posY + ctuSize; + } + } + + for( int i = 0; i < picHeader.getNumVerVirtualBoundaries(); i++ ) + { + if( picHeader.getVirtualBoundariesPosX( i ) == posX ) + { + leftBry = posX; + } + else if( picHeader.getVirtualBoundariesPosX( i ) == posX + ctuSize ) + { + rightBry = posX + ctuSize; + } + } + } +#else if( pps.getLoopFilterAcrossVirtualBoundariesDisabledFlag() ) { for( int i = 0; i < pps.getNumHorVirtualBoundaries(); i++ ) @@ -179,8 +226,37 @@ void AdaptiveLoopFilter::getAlfBoundary( const CodingStructure& cs, int posX, in } } } +#endif } +#if JVET_P1006_PICTURE_HEADER +bool AdaptiveLoopFilter::isCrossedByVirtualBoundaries( const CodingStructure& cs, const int xPos, const int yPos, const int width, const int height, int &topBry, int &botBry, int &leftBry, int &rightBry, int& numHorVirBndry, int& numVerVirBndry, int horVirBndryPos[], int verVirBndryPos[], const PicHeader* picHeader) +{ + numHorVirBndry = 0; numVerVirBndry = 0; + + if( picHeader->getLoopFilterAcrossVirtualBoundariesDisabledFlag() ) + { + for( int i = 0; i < picHeader->getNumHorVirtualBoundaries(); i++ ) + { + if( yPos < picHeader->getVirtualBoundariesPosY(i) && picHeader->getVirtualBoundariesPosY(i) < yPos + height ) + { + horVirBndryPos[numHorVirBndry++] = picHeader->getVirtualBoundariesPosY(i); + } + } + for( int i = 0; i < picHeader->getNumVerVirtualBoundaries(); i++ ) + { + if( xPos < picHeader->getVirtualBoundariesPosX(i) && picHeader->getVirtualBoundariesPosX(i) < xPos + width ) + { + verVirBndryPos[numVerVirBndry++] = picHeader->getVirtualBoundariesPosX(i); + } + } + } + + getAlfBoundary( cs, xPos, yPos, topBry, botBry, leftBry, rightBry ); + + return numHorVirBndry > 0 || numVerVirBndry > 0 || ( topBry != ALF_NONE_BOUNDARY ) || ( botBry != ALF_NONE_BOUNDARY ) || ( leftBry != ALF_NONE_BOUNDARY ) || ( rightBry != ALF_NONE_BOUNDARY ); +} +#else bool AdaptiveLoopFilter::isCrossedByVirtualBoundaries( const CodingStructure& cs, const int xPos, const int yPos, const int width, const int height, int &topBry, int &botBry, int &leftBry, int &rightBry, int& numHorVirBndry, int& numVerVirBndry, int horVirBndryPos[], int verVirBndryPos[], const PPS* pps) { numHorVirBndry = 0; numVerVirBndry = 0; @@ -207,6 +283,7 @@ bool AdaptiveLoopFilter::isCrossedByVirtualBoundaries( const CodingStructure& cs return numHorVirBndry > 0 || numVerVirBndry > 0 || ( topBry != ALF_NONE_BOUNDARY ) || ( botBry != ALF_NONE_BOUNDARY ) || ( leftBry != ALF_NONE_BOUNDARY ) || ( rightBry != ALF_NONE_BOUNDARY ); } +#endif #else bool AdaptiveLoopFilter::isCrossedByVirtualBoundaries( const int xPos, const int yPos, const int width, const int height, bool& clipTop, bool& clipBottom, bool& clipLeft, bool& clipRight, int& numHorVirBndry, int& numVerVirBndry, int horVirBndryPos[], int verVirBndryPos[], const PPS* pps) { @@ -386,7 +463,11 @@ void AdaptiveLoopFilter::ALFProcess(CodingStructure& cs) ctuEnableFlag |= m_ctuEnableFlag[compIdx][ctuIdx] > 0; } #if JVET_O0625_ALF_PADDING +#if JVET_P1006_PICTURE_HEADER + if( ctuEnableFlag && isCrossedByVirtualBoundaries( cs, xPos, yPos, width, height, alfBryList[0], alfBryList[1], alfBryList[2], alfBryList[3], numHorVirBndry, numVerVirBndry, horVirBndryPos, verVirBndryPos, cs.picHeader ) ) +#else if( ctuEnableFlag && isCrossedByVirtualBoundaries( cs, xPos, yPos, width, height, alfBryList[0], alfBryList[1], alfBryList[2], alfBryList[3], numHorVirBndry, numVerVirBndry, horVirBndryPos, verVirBndryPos, cs.slice->getPPS() ) ) +#endif #else if( ctuEnableFlag && isCrossedByVirtualBoundaries( xPos, yPos, width, height, clipTop, clipBottom, clipLeft, clipRight, numHorVirBndry, numVerVirBndry, horVirBndryPos, verVirBndryPos, cs.slice->getPPS() ) ) #endif diff --git a/source/Lib/CommonLib/AdaptiveLoopFilter.h b/source/Lib/CommonLib/AdaptiveLoopFilter.h index 42ab5bf3d..71d114520 100644 --- a/source/Lib/CommonLib/AdaptiveLoopFilter.h +++ b/source/Lib/CommonLib/AdaptiveLoopFilter.h @@ -145,10 +145,14 @@ public: #endif protected: +#if JVET_P1006_PICTURE_HEADER + bool isCrossedByVirtualBoundaries( const CodingStructure& cs, const int xPos, const int yPos, const int width, const int height, int &topBry, int &botBry, int &leftBry, int &rightBry, int& numHorVirBndry, int& numVerVirBndry, int horVirBndryPos[], int verVirBndryPos[], const PicHeader* picHeader ); +#else #if JVET_O0625_ALF_PADDING bool isCrossedByVirtualBoundaries( const CodingStructure& cs, const int xPos, const int yPos, const int width, const int height, int &topBry, int &botBry, int &leftBry, int &rightBry, int& numHorVirBndry, int& numVerVirBndry, int horVirBndryPos[], int verVirBndryPos[], const PPS* pps ); #else bool isCrossedByVirtualBoundaries( const int xPos, const int yPos, const int width, const int height, bool& clipTop, bool& clipBottom, bool& clipLeft, bool& clipRight, int& numHorVirBndry, int& numVerVirBndry, int horVirBndryPos[], int verVirBndryPos[], const PPS* pps ); +#endif #endif static const int m_classToFilterMapping[NUM_FIXED_FILTER_SETS][MAX_NUM_ALF_CLASSES]; static const int m_fixedFilterSetCoeff[ALF_FIXED_FILTER_NUM][MAX_NUM_ALF_LUMA_COEFF]; diff --git a/source/Lib/CommonLib/CodingStructure.cpp b/source/Lib/CommonLib/CodingStructure.cpp index 93eb94142..c942c5828 100644 --- a/source/Lib/CommonLib/CodingStructure.cpp +++ b/source/Lib/CommonLib/CodingStructure.cpp @@ -1015,6 +1015,9 @@ void CodingStructure::initSubStructure( CodingStructure& subStruct, const Channe subStruct.sps = sps; subStruct.vps = vps; subStruct.pps = pps; +#if JVET_P1006_PICTURE_HEADER + subStruct.picHeader = picHeader; +#endif memcpy(subStruct.alfApss, alfApss, sizeof(alfApss)); subStruct.lmcsAps = lmcsAps; diff --git a/source/Lib/CommonLib/CodingStructure.h b/source/Lib/CommonLib/CodingStructure.h index 643b0b8d3..d017a250b 100644 --- a/source/Lib/CommonLib/CodingStructure.h +++ b/source/Lib/CommonLib/CodingStructure.h @@ -92,6 +92,9 @@ public: bool isLossless; const SPS *sps; const PPS *pps; +#if JVET_P1006_PICTURE_HEADER + PicHeader *picHeader; +#endif APS* alfApss[ALF_CTB_MAX_NUM_APS]; APS * lmcsAps; APS * scalinglistAps; diff --git a/source/Lib/CommonLib/CommonDef.h b/source/Lib/CommonLib/CommonDef.h index 1732b46ea..365e8f6d2 100644 --- a/source/Lib/CommonLib/CommonDef.h +++ b/source/Lib/CommonLib/CommonDef.h @@ -285,6 +285,9 @@ static const int LUMA_INTERPOLATION_FILTER_SUB_SAMPLE_POSITIONS_SIGNAL = 1 << MV static const int LUMA_INTERPOLATION_FILTER_SUB_SAMPLE_POSITIONS = 1 << MV_FRACTIONAL_BITS_INTERNAL; static const int CHROMA_INTERPOLATION_FILTER_SUB_SAMPLE_POSITIONS = 1 << (MV_FRACTIONAL_BITS_INTERNAL + 1); +#if JVET_P1006_PICTURE_HEADER +static const int MAX_NUM_SUB_PICS = 255; +#endif static const int MAX_NUM_LONG_TERM_REF_PICS = 33; static const int NUM_LONG_TERM_REF_PIC_SPS = 0; diff --git a/source/Lib/CommonLib/ContextModelling.cpp b/source/Lib/CommonLib/ContextModelling.cpp index 5a54b4bf7..f1cad5688 100644 --- a/source/Lib/CommonLib/ContextModelling.cpp +++ b/source/Lib/CommonLib/ContextModelling.cpp @@ -372,7 +372,11 @@ void MergeCtx::setMmvdMergeCandiInfo(PredictionUnit& pu, int candIdx) fPosStep = tempIdx / 4; fPosPosition = tempIdx - fPosStep * (4); int offset = refMvdCands[fPosStep]; +#if JVET_P1006_PICTURE_HEADER + if ( pu.cu->slice->getPicHeader()->getDisFracMMVD() ) +#else if ( pu.cu->slice->getDisFracMMVD() ) +#endif { offset <<= 2; } diff --git a/source/Lib/CommonLib/DepQuant.cpp b/source/Lib/CommonLib/DepQuant.cpp index c63ef3adf..9c30646d4 100644 --- a/source/Lib/CommonLib/DepQuant.cpp +++ b/source/Lib/CommonLib/DepQuant.cpp @@ -1618,7 +1618,11 @@ DepQuant::~DepQuant() void DepQuant::quant( TransformUnit &tu, const ComponentID &compID, const CCoeffBuf &pSrc, TCoeff &uiAbsSum, const QpParam &cQP, const Ctx& ctx ) { #if JVET_P0058_CHROMA_TS +#if JVET_P1006_PICTURE_HEADER + if ( tu.cs->picHeader->getDepQuantEnabledFlag() && (tu.mtsIdx[compID] != MTS_SKIP) ) +#else if ( tu.cs->slice->getDepQuantEnabledFlag() && (tu.mtsIdx[compID] != MTS_SKIP) ) +#endif #else #if JVET_P0059_CHROMA_BDPCM if ((tu.cs->slice->getDepQuantEnabledFlag() && (tu.mtsIdx != MTS_SKIP || !isLuma(compID))) && @@ -1650,14 +1654,22 @@ void DepQuant::quant( TransformUnit &tu, const ComponentID &compID, const CCoeff const uint32_t log2TrHeight = floorLog2(height); #if JVET_P0058_CHROMA_TS #if JVET_P0365_SCALING_MATRIX_LFNST +#if JVET_P1006_PICTURE_HEADER + const bool disableSMForLFNST = tu.cs->sps->getScalingListFlag() ? tu.cs->picHeader->getScalingListAPS()->getScalingList().getDisableScalingMatrixForLfnstBlks() : false; +#else const bool disableSMForLFNST = tu.cs->sps->getScalingListFlag() ? tu.cs->slice->getscalingListAPS()->getScalingList().getDisableScalingMatrixForLfnstBlks() : false; +#endif const bool enableScalingLists = getUseScalingList(width, height, (tu.mtsIdx[compID] == MTS_SKIP), tu.cu->lfnstIdx > 0, disableSMForLFNST); #else const bool enableScalingLists = getUseScalingList(width, height, (tu.mtsIdx[compID] == MTS_SKIP)); #endif #else #if JVET_P0365_SCALING_MATRIX_LFNST +#if JVET_P1006_PICTURE_HEADER + const bool disableSMForLFNST = tu.cs->sps->getScalingListFlag() ? tu.cs->picHeader->getScalingListAPS()->getScalingList().getDisableScalingMatrixForLfnstBlks() : false; +#else const bool disableSMForLFNST = tu.cs->sps->getScalingListFlag() ? tu.cs->slice->getscalingListAPS()->getScalingList().getDisableScalingMatrixForLfnstBlks() : false; +#endif const bool enableScalingLists = getUseScalingList(width, height, (tu.mtsIdx == MTS_SKIP && isLuma(compID)), tu.cu->lfnstIdx > 0, disableSMForLFNST); #else const bool enableScalingLists = getUseScalingList(width, height, (tu.mtsIdx == MTS_SKIP && isLuma(compID))); @@ -1674,7 +1686,11 @@ void DepQuant::quant( TransformUnit &tu, const ComponentID &compID, const CCoeff void DepQuant::dequant( const TransformUnit &tu, CoeffBuf &dstCoeff, const ComponentID &compID, const QpParam &cQP ) { #if JVET_P0058_CHROMA_TS +#if JVET_P1006_PICTURE_HEADER + if( tu.cs->picHeader->getDepQuantEnabledFlag() && (tu.mtsIdx[compID] != MTS_SKIP)) +#else if( tu.cs->slice->getDepQuantEnabledFlag() && (tu.mtsIdx[compID] != MTS_SKIP)) +#endif #else #if JVET_P0059_CHROMA_BDPCM if ((tu.cs->slice->getDepQuantEnabledFlag() && (tu.mtsIdx != MTS_SKIP || !isLuma(compID))) && @@ -1705,14 +1721,22 @@ void DepQuant::dequant( const TransformUnit &tu, CoeffBuf &dstCoeff, const Compo const uint32_t log2TrHeight = floorLog2(height); #if JVET_P0058_CHROMA_TS #if JVET_P0365_SCALING_MATRIX_LFNST +#if JVET_P1006_PICTURE_HEADER + const bool disableSMForLFNST = tu.cs->sps->getScalingListFlag() ? tu.cs->picHeader->getScalingListAPS()->getScalingList().getDisableScalingMatrixForLfnstBlks() : false; +#else const bool disableSMForLFNST = tu.cs->sps->getScalingListFlag() ? tu.cs->slice->getscalingListAPS()->getScalingList().getDisableScalingMatrixForLfnstBlks() : false; +#endif const bool enableScalingLists = getUseScalingList(width, height, (tu.mtsIdx[compID] == MTS_SKIP), tu.cu->lfnstIdx > 0, disableSMForLFNST); #else const bool enableScalingLists = getUseScalingList(width, height, (tu.mtsIdx[compID] == MTS_SKIP)); #endif #else #if JVET_P0365_SCALING_MATRIX_LFNST +#if JVET_P1006_PICTURE_HEADER + const bool disableSMForLFNST = tu.cs->sps->getScalingListFlag() ? tu.cs->picHeader->getScalingListAPS()->getScalingList().getDisableScalingMatrixForLfnstBlks() : false; +#else const bool disableSMForLFNST = tu.cs->sps->getScalingListFlag() ? tu.cs->slice->getscalingListAPS()->getScalingList().getDisableScalingMatrixForLfnstBlks() : false; +#endif const bool enableScalingLists = getUseScalingList(width, height, (tu.mtsIdx == MTS_SKIP && isLuma(compID)), tu.cu->lfnstIdx > 0, disableSMForLFNST); #else const bool enableScalingLists = getUseScalingList(width, height, (tu.mtsIdx == MTS_SKIP && isLuma(compID))); diff --git a/source/Lib/CommonLib/InterPrediction.cpp b/source/Lib/CommonLib/InterPrediction.cpp index e5f4322c9..da35d1054 100644 --- a/source/Lib/CommonLib/InterPrediction.cpp +++ b/source/Lib/CommonLib/InterPrediction.cpp @@ -492,7 +492,11 @@ void InterPrediction::xPredInterBi(PredictionUnit& pu, PelUnitBuf &pcYuvPred, Pe pu.cs->slice->getWpScaling(REF_PIC_LIST_1, refIdx1, wp1); bool bioApplied = false; +#if JVET_P1006_PICTURE_HEADER + if (pu.cs->sps->getBDOFEnabledFlag() && (!pu.cs->picHeader->getDisBdofDmvrFlag())) +#else if (pu.cs->sps->getBDOFEnabledFlag() && (!pu.cs->slice->getDisBdofDmvrFlag())) +#endif { if (pu.cu->affine || m_subPuMC) { @@ -1812,7 +1816,11 @@ void InterPrediction::motionCompensation( PredictionUnit &pu, PelUnitBuf &predBu pu.cs->slice->getWpScaling(REF_PIC_LIST_1, refIdx1, wp1); bool bioApplied = false; const Slice &slice = *pu.cs->slice; +#if JVET_P1006_PICTURE_HEADER + if (pu.cs->sps->getBDOFEnabledFlag() && (!pu.cs->picHeader->getDisBdofDmvrFlag())) +#else if (pu.cs->sps->getBDOFEnabledFlag() && (!pu.cs->slice->getDisBdofDmvrFlag())) +#endif { if (pu.cu->affine || m_subPuMC) diff --git a/source/Lib/CommonLib/LoopFilter.cpp b/source/Lib/CommonLib/LoopFilter.cpp index 64966452b..c75c3dff8 100644 --- a/source/Lib/CommonLib/LoopFilter.cpp +++ b/source/Lib/CommonLib/LoopFilter.cpp @@ -268,7 +268,11 @@ void LoopFilter::xDeblockCU( CodingUnit& cu, const DeblockEdgeDir edgeDir ) int horVirBndryPos[] = { 0, 0, 0 }; int verVirBndryPos[] = { 0, 0, 0 }; +#if JVET_P1006_PICTURE_HEADER + bool isCuCrossedByVirtualBoundaries = isCrossedByVirtualBoundaries( area.x, area.y, area.width, area.height, numHorVirBndry, numVerVirBndry, horVirBndryPos, verVirBndryPos, cu.cs->picHeader ); +#else bool isCuCrossedByVirtualBoundaries = isCrossedByVirtualBoundaries( area.x, area.y, area.width, area.height, numHorVirBndry, numVerVirBndry, horVirBndryPos, verVirBndryPos, cu.cs->slice->getPPS() ); +#endif xSetLoopfilterParam( cu ); static_vector<int, 2*MAX_CU_SIZE> edgeIdx; @@ -407,6 +411,30 @@ void LoopFilter::xDeblockCU( CodingUnit& cu, const DeblockEdgeDir edgeDir ) } } +#if JVET_P1006_PICTURE_HEADER +inline bool LoopFilter::isCrossedByVirtualBoundaries(const int xPos, const int yPos, const int width, const int height, int& numHorVirBndry, int& numVerVirBndry, int horVirBndryPos[], int verVirBndryPos[], const PicHeader* picHeader ) +{ + numHorVirBndry = 0; numVerVirBndry = 0; + if (picHeader->getLoopFilterAcrossVirtualBoundariesDisabledFlag()) + { + for (int i = 0; i < picHeader->getNumHorVirtualBoundaries(); i++) + { + if (yPos <= picHeader->getVirtualBoundariesPosY(i) && picHeader->getVirtualBoundariesPosY(i) < yPos + height) + { + horVirBndryPos[numHorVirBndry++] = picHeader->getVirtualBoundariesPosY(i); + } + } + for (int i = 0; i < picHeader->getNumVerVirtualBoundaries(); i++) + { + if (xPos <= picHeader->getVirtualBoundariesPosX(i) && picHeader->getVirtualBoundariesPosX(i) < xPos + width) + { + verVirBndryPos[numVerVirBndry++] = picHeader->getVirtualBoundariesPosX(i); + } + } + } + return numHorVirBndry > 0 || numVerVirBndry > 0; +} +#else inline bool LoopFilter::isCrossedByVirtualBoundaries(const int xPos, const int yPos, const int width, const int height, int& numHorVirBndry, int& numVerVirBndry, int horVirBndryPos[], int verVirBndryPos[], const PPS* pps) { numHorVirBndry = 0; numVerVirBndry = 0; @@ -429,6 +457,7 @@ inline bool LoopFilter::isCrossedByVirtualBoundaries(const int xPos, const int y } return numHorVirBndry > 0 || numVerVirBndry > 0; } +#endif inline void LoopFilter::xDeriveEdgefilterParam( const int xPos, const int yPos, const int numVerVirBndry, const int numHorVirBndry, const int verVirBndryPos[], const int horVirBndryPos[], bool &verEdgeFilter, bool &horEdgeFilter ) { @@ -671,8 +700,13 @@ void LoopFilter::xSetLoopfilterParam( const CodingUnit& cu ) const Position& pos = cu.blocks[cu.chType].pos(); m_stLFCUParam.internalEdge = true; +#if JVET_P1006_PICTURE_HEADER + m_stLFCUParam.leftEdge = ( 0 < pos.x ) && isAvailableLeft ( cu, *cu.cs->getCU( pos.offset( -1, 0 ), cu.chType ), !pps.getLoopFilterAcrossSlicesEnabledFlag(), !pps.getLoopFilterAcrossBricksEnabledFlag() ); + m_stLFCUParam.topEdge = ( 0 < pos.y ) && isAvailableAbove( cu, *cu.cs->getCU( pos.offset( 0, -1 ), cu.chType ), !pps.getLoopFilterAcrossSlicesEnabledFlag(), !pps.getLoopFilterAcrossBricksEnabledFlag() ); +#else m_stLFCUParam.leftEdge = ( 0 < pos.x ) && isAvailableLeft ( cu, *cu.cs->getCU( pos.offset( -1, 0 ), cu.chType ), !slice.getLFCrossSliceBoundaryFlag(), !pps.getLoopFilterAcrossBricksEnabledFlag() ); m_stLFCUParam.topEdge = ( 0 < pos.y ) && isAvailableAbove( cu, *cu.cs->getCU( pos.offset( 0, -1 ), cu.chType ), !slice.getLFCrossSliceBoundaryFlag(), !pps.getLoopFilterAcrossBricksEnabledFlag() ); +#endif } unsigned LoopFilter::xGetBoundaryStrengthSingle ( const CodingUnit& cu, const DeblockEdgeDir edgeDir, const Position& localPos ) const @@ -938,7 +972,11 @@ void LoopFilter::xEdgeFilterLuma( const CodingUnit& cu, const DeblockEdgeDir edg // Derive neighboring PU index if (edgeDir == EDGE_VER) { +#if JVET_P1006_PICTURE_HEADER + if (!isAvailableLeft(cu, cuP, !pps.getLoopFilterAcrossSlicesEnabledFlag(), !pps.getLoopFilterAcrossBricksEnabledFlag())) +#else if (!isAvailableLeft(cu, cuP, !slice.getLFCrossSliceBoundaryFlag(), !pps.getLoopFilterAcrossBricksEnabledFlag())) +#endif { m_aapucBS[edgeDir][uiBsAbsIdx] = uiBs = 0; continue; @@ -946,7 +984,11 @@ void LoopFilter::xEdgeFilterLuma( const CodingUnit& cu, const DeblockEdgeDir edg } else // (iDir == EDGE_HOR) { +#if JVET_P1006_PICTURE_HEADER + if (!isAvailableAbove(cu, cuP, !pps.getLoopFilterAcrossSlicesEnabledFlag(), !pps.getLoopFilterAcrossBricksEnabledFlag())) +#else if (!isAvailableAbove(cu, cuP, !slice.getLFCrossSliceBoundaryFlag(), !pps.getLoopFilterAcrossBricksEnabledFlag())) +#endif { m_aapucBS[edgeDir][uiBsAbsIdx] = uiBs = 0; continue; @@ -1213,11 +1255,19 @@ void LoopFilter::xEdgeFilterChroma(const CodingUnit& cu, const DeblockEdgeDir ed if (edgeDir == EDGE_VER) { +#if JVET_P1006_PICTURE_HEADER + CHECK(!isAvailableLeft(cu, cuP, !pps.getLoopFilterAcrossSlicesEnabledFlag(), !pps.getLoopFilterAcrossBricksEnabledFlag()), "Neighbour not available"); +#else CHECK(!isAvailableLeft(cu, cuP, !slice.getLFCrossSliceBoundaryFlag(), !pps.getLoopFilterAcrossBricksEnabledFlag()), "Neighbour not available"); +#endif } else // (iDir == EDGE_HOR) { +#if JVET_P1006_PICTURE_HEADER + CHECK(!isAvailableAbove(cu, cuP, !pps.getLoopFilterAcrossSlicesEnabledFlag(), !pps.getLoopFilterAcrossBricksEnabledFlag()), "Neighbour not available"); +#else CHECK(!isAvailableAbove(cu, cuP, !slice.getLFCrossSliceBoundaryFlag(), !pps.getLoopFilterAcrossBricksEnabledFlag()), "Neighbour not available"); +#endif } bPartPNoFilter = bPartQNoFilter = false; diff --git a/source/Lib/CommonLib/LoopFilter.h b/source/Lib/CommonLib/LoopFilter.h index 4191d7146..ed88c34bb 100644 --- a/source/Lib/CommonLib/LoopFilter.h +++ b/source/Lib/CommonLib/LoopFilter.h @@ -104,7 +104,11 @@ private: inline unsigned BsSet(unsigned val, const ComponentID compIdx) const; inline unsigned BsGet(unsigned val, const ComponentID compIdx) const; +#if JVET_P1006_PICTURE_HEADER + inline bool isCrossedByVirtualBoundaries ( const int xPos, const int yPos, const int width, const int height, int& numHorVirBndry, int& numVerVirBndry, int horVirBndryPos[], int verVirBndryPos[], const PicHeader* picHeader ); +#else inline bool isCrossedByVirtualBoundaries ( const int xPos, const int yPos, const int width, const int height, int& numHorVirBndry, int& numVerVirBndry, int horVirBndryPos[], int verVirBndryPos[], const PPS* pps ); +#endif inline void xDeriveEdgefilterParam ( const int xPos, const int yPos, const int numVerVirBndry, const int numHorVirBndry, const int verVirBndryPos[], const int horVirBndryPos[], bool &verEdgeFilter, bool &horEdgeFilter ); #if JVET_P0081_CHROMA_LONG_DEBLOCKING_FIX diff --git a/source/Lib/CommonLib/Picture.cpp b/source/Lib/CommonLib/Picture.cpp index b362b378c..8fbb337ca 100644 --- a/source/Lib/CommonLib/Picture.cpp +++ b/source/Lib/CommonLib/Picture.cpp @@ -953,7 +953,11 @@ const CPelUnitBuf Picture::getRecoBuf(const UnitArea &unit, bool wrap) const PelUnitBuf Picture::getRecoBuf(bool wrap) { return M_BUFS(scheduler.getSplitPicId(), wrap ? PIC_RECON_WRAP : PIC_RECONSTRUCTION); } const CPelUnitBuf Picture::getRecoBuf(bool wrap) const { return M_BUFS(scheduler.getSplitPicId(), wrap ? PIC_RECON_WRAP : PIC_RECONSTRUCTION); } +#if JVET_P1006_PICTURE_HEADER +void Picture::finalInit( const SPS& sps, const PPS& pps, PicHeader* picHeader, APS** alfApss, APS* lmcsAps, APS* scalingListAps ) +#else void Picture::finalInit( const SPS& sps, const PPS& pps, APS** alfApss, APS* lmcsAps, APS* scalingListAps ) +#endif { for( auto &sei : SEIs ) { @@ -987,6 +991,11 @@ void Picture::finalInit( const SPS& sps, const PPS& pps, APS** alfApss, APS* lmc 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; +#if JVET_P1006_PICTURE_HEADER + picHeader->setSPSId( sps.getSPSId() ); + picHeader->setPPSId( pps.getPPSId() ); + cs->picHeader = picHeader; +#endif memcpy(cs->alfApss, alfApss, sizeof(cs->alfApss)); cs->lmcsAps = lmcsAps; cs->scalinglistAps = scalingListAps; @@ -1009,8 +1018,10 @@ void Picture::allocateNewSlice() Slice& slice = *slices.back(); memcpy(slice.getAlfAPSs(), cs->alfApss, sizeof(cs->alfApss)); +#if !JVET_P1006_PICTURE_HEADER slice.setLmcsAPS(cs->lmcsAps); slice.setscalingListAPS( cs->scalinglistAps ); +#endif slice.setPPS( cs->pps); slice.setSPS( cs->sps); @@ -1027,10 +1038,12 @@ Slice *Picture::swapSliceObject(Slice * p, uint32_t i) p->setPPS(cs->pps); p->setAlfAPSs(cs->alfApss); +#if !JVET_P1006_PICTURE_HEADER if(cs->lmcsAps != nullptr) p->setLmcsAPS(cs->lmcsAps); if(cs->scalinglistAps != nullptr) p->setscalingListAPS( cs->scalinglistAps ); +#endif Slice * pTmp = slices[i]; slices[i] = p; @@ -1038,8 +1051,10 @@ Slice *Picture::swapSliceObject(Slice * p, uint32_t i) pTmp->setPPS(0); memset(pTmp->getAlfAPSs(), 0, sizeof(*pTmp->getAlfAPSs())*ALF_CTB_MAX_NUM_APS); +#if !JVET_P1006_PICTURE_HEADER pTmp->setLmcsAPS(0); pTmp->setscalingListAPS( 0 ); +#endif return pTmp; } diff --git a/source/Lib/CommonLib/Picture.h b/source/Lib/CommonLib/Picture.h index 57c1c4282..b9ad71b07 100644 --- a/source/Lib/CommonLib/Picture.h +++ b/source/Lib/CommonLib/Picture.h @@ -247,7 +247,11 @@ struct Picture : public UnitArea const CPelUnitBuf getBuf(const UnitArea &unit, const PictureType &type) const; void extendPicBorder(); +#if JVET_P1006_PICTURE_HEADER + void finalInit( const SPS& sps, const PPS& pps, PicHeader *picHeader, APS** alfApss, APS* lmcsAps, APS* scalingListAps ); +#else void finalInit( const SPS& sps, const PPS& pps, APS** alfApss, APS* lmcsAps, APS* scalingListAps ); +#endif int getPOC() const { return poc; } void setBorderExtension( bool bFlag) { m_bIsBorderExtended = bFlag;} diff --git a/source/Lib/CommonLib/Quant.cpp b/source/Lib/CommonLib/Quant.cpp index 1693a64be..27eb90af5 100644 --- a/source/Lib/CommonLib/Quant.cpp +++ b/source/Lib/CommonLib/Quant.cpp @@ -384,7 +384,11 @@ void Quant::dequant(const TransformUnit &tu, #endif #if JVET_P0365_SCALING_MATRIX_LFNST +#if JVET_P1006_PICTURE_HEADER + const bool disableSMForLFNST = tu.cs->sps->getScalingListFlag() ? tu.cs->picHeader->getScalingListAPS()->getScalingList().getDisableScalingMatrixForLfnstBlks() : false; +#else const bool disableSMForLFNST = tu.cs->sps->getScalingListFlag() ? tu.cs->slice->getscalingListAPS()->getScalingList().getDisableScalingMatrixForLfnstBlks() : false; +#endif const bool enableScalingLists = getUseScalingList(uiWidth, uiHeight, isTransformSkip, tu.cu->lfnstIdx > 0, disableSMForLFNST); #else const bool enableScalingLists = getUseScalingList(uiWidth, uiHeight, isTransformSkip); @@ -1074,7 +1078,11 @@ void Quant::quant(TransformUnit &tu, const ComponentID &compID, const CCoeffBuf const int maxLog2TrDynamicRange = sps.getMaxLog2TrDynamicRange(toChannelType(compID)); { +#if JVET_P1006_PICTURE_HEADER + CoeffCodingContext cctx(tu, compID, tu.cs->picHeader->getSignDataHidingEnabledFlag()); +#else CoeffCodingContext cctx(tu, compID, tu.cs->slice->getSignDataHidingEnabledFlag()); +#endif const TCoeff entropyCodingMinimum = -(1 << maxLog2TrDynamicRange); const TCoeff entropyCodingMaximum = (1 << maxLog2TrDynamicRange) - 1; @@ -1085,9 +1093,13 @@ void Quant::quant(TransformUnit &tu, const ComponentID &compID, const CCoeffBuf const uint32_t uiLog2TrWidth = floorLog2(uiWidth); const uint32_t uiLog2TrHeight = floorLog2(uiHeight); int *piQuantCoeff = getQuantCoeff(scalingListType, cQP.rem(useTransformSkip), uiLog2TrWidth, uiLog2TrHeight); - + #if JVET_P0365_SCALING_MATRIX_LFNST +#if JVET_P1006_PICTURE_HEADER + const bool disableSMForLFNST = tu.cs->sps->getScalingListFlag() ? tu.cs->picHeader->getScalingListAPS()->getScalingList().getDisableScalingMatrixForLfnstBlks() : false; +#else const bool disableSMForLFNST = tu.cs->sps->getScalingListFlag() ? tu.cs->slice->getscalingListAPS()->getScalingList().getDisableScalingMatrixForLfnstBlks() : false; +#endif const bool enableScalingLists = getUseScalingList(uiWidth, uiHeight, useTransformSkip, tu.cu->lfnstIdx > 0, disableSMForLFNST); #else const bool enableScalingLists = getUseScalingList(uiWidth, uiHeight, useTransformSkip); @@ -1175,9 +1187,13 @@ bool Quant::xNeedRDOQ(TransformUnit &tu, const ComponentID &compID, const CCoeff const uint32_t uiLog2TrWidth = floorLog2(uiWidth); const uint32_t uiLog2TrHeight = floorLog2(uiHeight); int *piQuantCoeff = getQuantCoeff(scalingListType, cQP.rem(useTransformSkip), uiLog2TrWidth, uiLog2TrHeight); - + #if JVET_P0365_SCALING_MATRIX_LFNST +#if JVET_P1006_PICTURE_HEADER + const bool disableSMForLFNST = tu.cs->sps->getScalingListFlag() ? tu.cs->picHeader->getScalingListAPS()->getScalingList().getDisableScalingMatrixForLfnstBlks() : false; +#else const bool disableSMForLFNST = tu.cs->sps->getScalingListFlag() ? tu.cs->slice->getscalingListAPS()->getScalingList().getDisableScalingMatrixForLfnstBlks() : false; +#endif const bool enableScalingLists = getUseScalingList(uiWidth, uiHeight, (useTransformSkip != 0), tu.cu->lfnstIdx > 0, disableSMForLFNST); #else const bool enableScalingLists = getUseScalingList(uiWidth, uiHeight, (useTransformSkip != 0)); @@ -1231,7 +1247,11 @@ void Quant::transformSkipQuantOneSample(TransformUnit &tu, const ComponentID &co const int iTransformShift = getTransformShift(channelBitDepth, rect.size(), maxLog2TrDynamicRange); const int scalingListType = getScalingListType(tu.cu->predMode, compID); #if JVET_P0365_SCALING_MATRIX_LFNST +#if JVET_P1006_PICTURE_HEADER + const bool disableSMForLFNST = tu.cs->sps->getScalingListFlag() ? tu.cs->picHeader->getScalingListAPS()->getScalingList().getDisableScalingMatrixForLfnstBlks() : false; +#else const bool disableSMForLFNST = tu.cs->sps->getScalingListFlag() ? tu.cs->slice->getscalingListAPS()->getScalingList().getDisableScalingMatrixForLfnstBlks() : false; +#endif const bool enableScalingLists = getUseScalingList(uiWidth, uiHeight, true, tu.cu->lfnstIdx > 0, disableSMForLFNST); #else const bool enableScalingLists = getUseScalingList(uiWidth, uiHeight, true); @@ -1313,7 +1333,11 @@ void Quant::invTrSkipDeQuantOneSample(TransformUnit &tu, const ComponentID &comp const int iTransformShift = getTransformShift(channelBitDepth, rect.size(), maxLog2TrDynamicRange); const int scalingListType = getScalingListType(tu.cu->predMode, compID); #if JVET_P0365_SCALING_MATRIX_LFNST +#if JVET_P1006_PICTURE_HEADER + const bool disableSMForLFNST = tu.cs->sps->getScalingListFlag() ? tu.cs->picHeader->getScalingListAPS()->getScalingList().getDisableScalingMatrixForLfnstBlks() : false; +#else const bool disableSMForLFNST = tu.cs->sps->getScalingListFlag() ? tu.cs->slice->getscalingListAPS()->getScalingList().getDisableScalingMatrixForLfnstBlks() : false; +#endif const bool enableScalingLists = getUseScalingList(uiWidth, uiHeight, true, tu.cu->lfnstIdx > 0, disableSMForLFNST); #else const bool enableScalingLists = getUseScalingList(uiWidth, uiHeight, true); diff --git a/source/Lib/CommonLib/QuantRDOQ.cpp b/source/Lib/CommonLib/QuantRDOQ.cpp index cc4c8ae6c..bc60e540b 100644 --- a/source/Lib/CommonLib/QuantRDOQ.cpp +++ b/source/Lib/CommonLib/QuantRDOQ.cpp @@ -668,7 +668,11 @@ void QuantRDOQ::xRateDistOptQuant(TransformUnit &tu, const ComponentID &compID, const double *const pdErrScale = xGetErrScaleCoeffSL(scalingListType, uiLog2BlockWidth, uiLog2BlockHeight, cQP.rem(isTransformSkip)); const int *const piQCoef = getQuantCoeff(scalingListType, cQP.rem(isTransformSkip), uiLog2BlockWidth, uiLog2BlockHeight); #if JVET_P0365_SCALING_MATRIX_LFNST +#if JVET_P1006_PICTURE_HEADER + const bool disableSMForLFNST = tu.cs->sps->getScalingListFlag() ? tu.cs->picHeader->getScalingListAPS()->getScalingList().getDisableScalingMatrixForLfnstBlks() : false; +#else const bool disableSMForLFNST = tu.cs->sps->getScalingListFlag() ? tu.cs->slice->getscalingListAPS()->getScalingList().getDisableScalingMatrixForLfnstBlks() : false; +#endif const bool enableScalingLists = getUseScalingList(uiWidth, uiHeight, isTransformSkip, tu.cu->lfnstIdx > 0, disableSMForLFNST); #else const bool enableScalingLists = getUseScalingList(uiWidth, uiHeight, isTransformSkip); @@ -681,7 +685,11 @@ void QuantRDOQ::xRateDistOptQuant(TransformUnit &tu, const ComponentID &compID, const TCoeff entropyCodingMinimum = -(1 << maxLog2TrDynamicRange); const TCoeff entropyCodingMaximum = (1 << maxLog2TrDynamicRange) - 1; +#if JVET_P1006_PICTURE_HEADER + CoeffCodingContext cctx(tu, compID, tu.cs->picHeader->getSignDataHidingEnabledFlag()); +#else CoeffCodingContext cctx(tu, compID, tu.cs->slice->getSignDataHidingEnabledFlag()); +#endif const int iCGSizeM1 = (1 << cctx.log2CGSize()) - 1; int iCGLastScanPos = -1; @@ -1286,7 +1294,11 @@ void QuantRDOQ::xRateDistOptQuantTS( TransformUnit &tu, const ComponentID &compI uint32_t coeffLevels[3]; double coeffLevelError[4]; +#if JVET_P1006_PICTURE_HEADER + CoeffCodingContext cctx( tu, compID, tu.cs->picHeader->getSignDataHidingEnabledFlag() ); +#else CoeffCodingContext cctx( tu, compID, tu.cs->slice->getSignDataHidingEnabledFlag() ); +#endif const int sbSizeM1 = ( 1 << cctx.log2CGSize() ) - 1; double baseCost = 0; uint32_t goRiceParam = 0; @@ -1548,7 +1560,11 @@ void QuantRDOQ::forwardRDPCM( TransformUnit &tu, const ComponentID &compID, cons uint32_t coeffLevels[3]; double coeffLevelError[4]; +#if JVET_P1006_PICTURE_HEADER + CoeffCodingContext cctx(tu, compID, tu.cs->picHeader->getSignDataHidingEnabledFlag()); +#else CoeffCodingContext cctx(tu, compID, tu.cs->slice->getSignDataHidingEnabledFlag()); +#endif const int sbSizeM1 = (1 << cctx.log2CGSize()) - 1; double baseCost = 0; uint32_t goRiceParam = 0; diff --git a/source/Lib/CommonLib/SampleAdaptiveOffset.cpp b/source/Lib/CommonLib/SampleAdaptiveOffset.cpp index ee5d84fbb..eb5a89edc 100644 --- a/source/Lib/CommonLib/SampleAdaptiveOffset.cpp +++ b/source/Lib/CommonLib/SampleAdaptiveOffset.cpp @@ -579,7 +579,11 @@ void SampleAdaptiveOffset::offsetCTU( const UnitArea& area, const CPelUnitBuf& s int verVirBndryPos[] = { -1,-1,-1 }; int horVirBndryPosComp[] = { -1,-1,-1 }; int verVirBndryPosComp[] = { -1,-1,-1 }; +#if JVET_P1006_PICTURE_HEADER + bool isCtuCrossedByVirtualBoundaries = isCrossedByVirtualBoundaries(area.Y().x, area.Y().y, area.Y().width, area.Y().height, numHorVirBndry, numVerVirBndry, horVirBndryPos, verVirBndryPos, cs.picHeader ); +#else bool isCtuCrossedByVirtualBoundaries = isCrossedByVirtualBoundaries(area.Y().x, area.Y().y, area.Y().width, area.Y().height, numHorVirBndry, numVerVirBndry, horVirBndryPos, verVirBndryPos, cs.slice->getPPS()); +#endif for(int compIdx = 0; compIdx < numberOfComponents; compIdx++) { const ComponentID compID = ComponentID(compIdx); @@ -733,7 +737,11 @@ void SampleAdaptiveOffset::xLosslessSampleRestoration(CodingUnit& cu, const Comp PelBuf dstBuf = cu.cs->getRecoBuf( currTU.block(compID) ); dstBuf.copyFrom( pcmBuf ); +#if JVET_P1006_PICTURE_HEADER + if (cu.slice->getPicHeader()->getLmcsEnabledFlag() && isLuma(compID)) +#else if (cu.slice->getLmcsEnabledFlag() && isLuma(compID)) +#endif { dstBuf.rspSignal(m_pcReshape->getInvLUT()); } @@ -768,6 +776,31 @@ void SampleAdaptiveOffset::deriveLoopFilterBoundaryAvailibility(CodingStructure& const CodingUnit* cuBelowRight = cs.getCU(pos.offset(width, height), CH_L); // check cross slice flags +#if JVET_P1006_PICTURE_HEADER + const bool isLoopFilterAcrossSlicePPS = cs.pps->getLoopFilterAcrossSlicesEnabledFlag(); + if (!isLoopFilterAcrossSlicePPS) + { + isLeftAvail = (cuLeft == NULL) ? false : CU::isSameSlice(*cuCurr, *cuLeft); + isAboveAvail = (cuAbove == NULL) ? false : CU::isSameSlice(*cuCurr, *cuAbove); + isRightAvail = (cuRight == NULL) ? false : CU::isSameSlice(*cuCurr, *cuRight); + isBelowAvail = (cuBelow == NULL) ? false : CU::isSameSlice(*cuCurr, *cuBelow); + isAboveLeftAvail = (cuAboveLeft == NULL) ? false : CU::isSameSlice(*cuCurr, *cuAboveLeft); + isAboveRightAvail = (cuAboveRight == NULL) ? false : CU::isSameSlice(*cuCurr, *cuAboveRight); + isBelowLeftAvail = (cuBelowLeft == NULL) ? false : CU::isSameSlice(*cuCurr, *cuBelowLeft); + isBelowRightAvail = (cuBelowRight == NULL) ? false : CU::isSameSlice(*cuCurr, *cuBelowRight); + } + else + { + isLeftAvail = (cuLeft != NULL); + isAboveAvail = (cuAbove != NULL); + isRightAvail = (cuRight != NULL); + isBelowAvail = (cuBelow != NULL); + isAboveLeftAvail = (cuAboveLeft != NULL); + isAboveRightAvail = (cuAboveRight != NULL); + isBelowLeftAvail = (cuBelowLeft != NULL); + isBelowRightAvail = (cuBelowRight != NULL); + } +#else { //left isLeftAvail = (cuLeft != NULL) ? ( !CU::isSameSlice(*cuCurr, *cuLeft) ? cuCurr->slice->getLFCrossSliceBoundaryFlag() : true ) : false; @@ -803,6 +836,7 @@ void SampleAdaptiveOffset::deriveLoopFilterBoundaryAvailibility(CodingStructure& isBelowLeftAvail = ( !CU::isSameSlice(*cuCurr, *cuBelowLeft) ) ? bLFCrossSliceBoundaryFlag : true; } } +#endif // check cross tile flags const bool isLoopFilterAcrossTilePPS = cs.pps->getLoopFilterAcrossBricksEnabledFlag(); @@ -819,6 +853,30 @@ void SampleAdaptiveOffset::deriveLoopFilterBoundaryAvailibility(CodingStructure& } } +#if JVET_P1006_PICTURE_HEADER +bool SampleAdaptiveOffset::isCrossedByVirtualBoundaries(const int xPos, const int yPos, const int width, const int height, int& numHorVirBndry, int& numVerVirBndry, int horVirBndryPos[], int verVirBndryPos[], const PicHeader* picHeader ) +{ + numHorVirBndry = 0; numVerVirBndry = 0; + if (picHeader->getLoopFilterAcrossVirtualBoundariesDisabledFlag()) + { + for (int i = 0; i < picHeader->getNumHorVirtualBoundaries(); i++) + { + if (yPos <= picHeader->getVirtualBoundariesPosY(i) && picHeader->getVirtualBoundariesPosY(i) <= yPos + height) + { + horVirBndryPos[numHorVirBndry++] = picHeader->getVirtualBoundariesPosY(i); + } + } + for (int i = 0; i < picHeader->getNumVerVirtualBoundaries(); i++) + { + if (xPos <= picHeader->getVirtualBoundariesPosX(i) && picHeader->getVirtualBoundariesPosX(i) <= xPos + width) + { + verVirBndryPos[numVerVirBndry++] = picHeader->getVirtualBoundariesPosX(i); + } + } + } + return numHorVirBndry > 0 || numVerVirBndry > 0 ; +} +#else bool SampleAdaptiveOffset::isCrossedByVirtualBoundaries(const int xPos, const int yPos, const int width, const int height, int& numHorVirBndry, int& numVerVirBndry, int horVirBndryPos[], int verVirBndryPos[], const PPS* pps) { numHorVirBndry = 0; numVerVirBndry = 0; @@ -841,4 +899,5 @@ bool SampleAdaptiveOffset::isCrossedByVirtualBoundaries(const int xPos, const in } return numHorVirBndry > 0 || numVerVirBndry > 0 ; } +#endif //! \} diff --git a/source/Lib/CommonLib/SampleAdaptiveOffset.h b/source/Lib/CommonLib/SampleAdaptiveOffset.h index e3e75f399..93b6fc384 100644 --- a/source/Lib/CommonLib/SampleAdaptiveOffset.h +++ b/source/Lib/CommonLib/SampleAdaptiveOffset.h @@ -95,7 +95,11 @@ protected: void xLosslessCURestoration(CodingStructure& cs, const UnitArea &ctuArea); void xLosslessSampleRestoration(CodingUnit& cu, const ComponentID compID); void xReconstructBlkSAOParams(CodingStructure& cs, SAOBlkParam* saoBlkParams); +#if JVET_P1006_PICTURE_HEADER + bool isCrossedByVirtualBoundaries(const int xPos, const int yPos, const int width, const int height, int& numHorVirBndry, int& numVerVirBndry, int horVirBndryPos[], int verVirBndryPos[], const PicHeader* picHeader); +#else bool isCrossedByVirtualBoundaries(const int xPos, const int yPos, const int width, const int height, int& numHorVirBndry, int& numVerVirBndry, int horVirBndryPos[], int verVirBndryPos[], const PPS* pps); +#endif inline bool isProcessDisabled(int xPos, int yPos, int numVerVirBndry, int numHorVirBndry, int verVirBndryPos[], int horVirBndryPos[]) { bool bDisabledFlag = false; diff --git a/source/Lib/CommonLib/Slice.cpp b/source/Lib/CommonLib/Slice.cpp index 8629d4c1d..a09e25920 100644 --- a/source/Lib/CommonLib/Slice.cpp +++ b/source/Lib/CommonLib/Slice.cpp @@ -47,9 +47,13 @@ //! \{ Slice::Slice() +#if !JVET_P1006_PICTURE_HEADER : m_iPPSId ( -1 ) , m_PicOutputFlag ( true ) , m_iPOC ( 0 ) +#else +: m_iPOC ( 0 ) +#endif , m_iLastIDR ( 0 ) , m_iAssociatedIRAP ( 0 ) , m_iAssociatedIRAPType ( NAL_UNIT_INVALID ) @@ -58,14 +62,18 @@ Slice::Slice() , m_eNalUnitType ( NAL_UNIT_CODED_SLICE_IDR_W_RADL ) , m_eSliceType ( I_SLICE ) , m_iSliceQp ( 0 ) +#if !JVET_P1006_PICTURE_HEADER , m_ChromaQpAdjEnabled ( false ) +#endif , m_deblockingFilterDisable ( false ) , m_deblockingFilterOverrideFlag ( false ) , m_deblockingFilterBetaOffsetDiv2( 0 ) , m_deblockingFilterTcOffsetDiv2 ( 0 ) , m_pendingRasInit ( false ) +#if !JVET_P1006_PICTURE_HEADER , m_depQuantEnabledFlag ( false ) , m_signDataHidingEnabledFlag ( false ) +#endif , m_bCheckLDC ( false ) , m_biDirPred ( false ) , m_iSliceQpDelta ( 0 ) @@ -75,16 +83,20 @@ Slice::Slice() , m_pcPPS ( NULL ) , m_pcPic ( NULL ) , m_colFromL0Flag ( true ) +#if !JVET_P1006_PICTURE_HEADER , m_noOutputPriorPicsFlag ( false ) +#endif , m_noIncorrectPicOutputFlag ( false ) , m_handleCraAsCvsStartFlag ( false ) , m_colRefIdx ( 0 ) +#if !JVET_P1006_PICTURE_HEADER , m_maxNumMergeCand ( 0 ) , m_maxNumAffineMergeCand ( 0 ) , m_maxNumTriangleCand ( 0 ) , m_maxNumIBCMergeCand ( 0 ) , m_disFracMMVD ( false ) , m_disBdofDmvrFlag ( false ) +#endif , m_uiTLayer ( 0 ) , m_bTLayerSwitchingFlag ( false ) , m_sliceMode ( NO_SLICES ) @@ -103,13 +115,16 @@ Slice::Slice() , m_bTestWeightBiPred ( false ) , m_substreamSizes ( ) , m_cabacInitFlag ( false ) +#if !JVET_P1006_PICTURE_HEADER , m_jointCbCrSignFlag ( false ) , m_bLMvdL1Zero ( false ) , m_LFCrossSliceBoundaryFlag ( false ) , m_enableTMVPFlag ( true ) +#endif , m_encCABACTableIdx (I_SLICE) , m_iProcessingStartTime ( 0 ) , m_dProcessingTime ( 0 ) +#if !JVET_P1006_PICTURE_HEADER , m_splitConsOverrideFlag ( false ) , m_uiMinQTSize ( 0 ) , m_uiMaxMTTHierarchyDepth ( 0 ) @@ -127,6 +142,7 @@ Slice::Slice() , m_scalingListAps ( nullptr ) , m_tileGroupscalingListPresentFlag ( false ) , m_nonReferencePicFlag ( 0 ) +#endif { for(uint32_t i=0; i<NUM_REF_PIC_LIST_01; i++) { @@ -195,18 +211,24 @@ void Slice::initSlice() } m_iSliceChromaQpDelta[JOINT_CbCr] = 0; +#if !JVET_P1006_PICTURE_HEADER m_maxNumMergeCand = MRG_MAX_NUM_CANDS; m_maxNumAffineMergeCand = AFFINE_MRG_MAX_NUM_CANDS; m_maxNumIBCMergeCand = IBC_MRG_MAX_NUM_CANDS; +#endif m_bFinalized=false; +#if !JVET_P1006_PICTURE_HEADER m_disFracMMVD = false; m_disBdofDmvrFlag = false; +#endif m_substreamSizes.clear(); m_cabacInitFlag = false; +#if !JVET_P1006_PICTURE_HEADER m_jointCbCrSignFlag = false; m_enableTMVPFlag = true; +#endif m_enableDRAPSEI = false; m_useLTforDRAP = false; m_isDRAP = false; @@ -214,6 +236,50 @@ void Slice::initSlice() resetTileGroupAlfEnabledFlag(); } +#if JVET_P1006_PICTURE_HEADER +void Slice::inheritFromPicHeader( PicHeader *picHeader, const PPS *pps, const SPS *sps ) +{ + if(picHeader->getPicRplPresentFlag()) + { + setRPL0idx( picHeader->getRPL0idx() ); + *getLocalRPL0() = *picHeader->getLocalRPL0(); + if(getRPL0idx() != -1) + { + setRPL0(sps->getRPLList0()->getReferencePictureList(getRPL0idx())); + } + else + { + setRPL0(getLocalRPL0()); + } + + setRPL1idx( picHeader->getRPL1idx() ); + *getLocalRPL1() = *picHeader->getLocalRPL1(); + if(getRPL1idx() != -1) + { + setRPL1(sps->getRPLList1()->getReferencePictureList(getRPL1idx())); + } + else + { + setRPL1(getLocalRPL1()); + } + } + + setDeblockingFilterDisable( picHeader->getDeblockingFilterDisable() ); + setDeblockingFilterBetaOffsetDiv2( picHeader->getDeblockingFilterBetaOffsetDiv2() ); + setDeblockingFilterTcOffsetDiv2( picHeader->getDeblockingFilterTcOffsetDiv2() ); + + setSaoEnabledFlag(CHANNEL_TYPE_LUMA, picHeader->getSaoEnabledFlag(CHANNEL_TYPE_LUMA)); + setSaoEnabledFlag(CHANNEL_TYPE_CHROMA, picHeader->getSaoEnabledFlag(CHANNEL_TYPE_CHROMA)); + + setTileGroupAlfEnabledFlag(COMPONENT_Y, picHeader->getAlfEnabledFlag(COMPONENT_Y)); + setTileGroupAlfEnabledFlag(COMPONENT_Cb, picHeader->getAlfEnabledFlag(COMPONENT_Cb)); + setTileGroupAlfEnabledFlag(COMPONENT_Cr, picHeader->getAlfEnabledFlag(COMPONENT_Cr)); + setTileGroupNumAps(picHeader->getNumAlfAps()); + setAlfAPSs(picHeader->getAlfAPSs()); + setTileGroupApsIdChroma(picHeader->getAlfApsIdChroma()); +} + +#endif void Slice::setDefaultClpRng( const SPS& sps ) { m_clpRngs.comp[COMPONENT_Y].min = m_clpRngs.comp[COMPONENT_Cb].min = m_clpRngs.comp[COMPONENT_Cr].min = 0; @@ -703,7 +769,9 @@ void Slice::copySliceInfo(Slice *pSrc, bool cpyAlmostAll) m_eSliceType = pSrc->m_eSliceType; m_iSliceQp = pSrc->m_iSliceQp; m_iSliceQpBase = pSrc->m_iSliceQpBase; +#if !JVET_P1006_PICTURE_HEADER m_ChromaQpAdjEnabled = pSrc->m_ChromaQpAdjEnabled; +#endif m_deblockingFilterDisable = pSrc->m_deblockingFilterDisable; m_deblockingFilterOverrideFlag = pSrc->m_deblockingFilterOverrideFlag; m_deblockingFilterBetaOffsetDiv2 = pSrc->m_deblockingFilterBetaOffsetDiv2; @@ -793,7 +861,9 @@ void Slice::copySliceInfo(Slice *pSrc, bool cpyAlmostAll) } m_cabacInitFlag = pSrc->m_cabacInitFlag; +#if !JVET_P1006_PICTURE_HEADER m_jointCbCrSignFlag = pSrc->m_jointCbCrSignFlag; +#endif memcpy(m_alfApss, pSrc->m_alfApss, sizeof(m_alfApss)); // this might be quite unsafe memcpy( m_tileGroupAlfEnabledFlag, pSrc->m_tileGroupAlfEnabledFlag, sizeof(m_tileGroupAlfEnabledFlag)); m_tileGroupNumAps = pSrc->m_tileGroupNumAps; @@ -801,6 +871,7 @@ void Slice::copySliceInfo(Slice *pSrc, bool cpyAlmostAll) m_tileGroupChromaApsId = pSrc->m_tileGroupChromaApsId; m_disableSATDForRd = pSrc->m_disableSATDForRd; +#if !JVET_P1006_PICTURE_HEADER m_bLMvdL1Zero = pSrc->m_bLMvdL1Zero; m_LFCrossSliceBoundaryFlag = pSrc->m_LFCrossSliceBoundaryFlag; m_enableTMVPFlag = pSrc->m_enableTMVPFlag; @@ -810,7 +881,9 @@ void Slice::copySliceInfo(Slice *pSrc, bool cpyAlmostAll) m_maxNumIBCMergeCand = pSrc->m_maxNumIBCMergeCand; m_disFracMMVD = pSrc->m_disFracMMVD; m_disBdofDmvrFlag = pSrc->m_disBdofDmvrFlag; +#endif if( cpyAlmostAll ) m_encCABACTableIdx = pSrc->m_encCABACTableIdx; +#if !JVET_P1006_PICTURE_HEADER m_splitConsOverrideFlag = pSrc->m_splitConsOverrideFlag; m_uiMinQTSize = pSrc->m_uiMinQTSize; m_uiMaxMTTHierarchyDepth = pSrc->m_uiMaxMTTHierarchyDepth; @@ -832,6 +905,7 @@ void Slice::copySliceInfo(Slice *pSrc, bool cpyAlmostAll) m_tileGroupscalingListPresentFlag = pSrc->m_tileGroupscalingListPresentFlag; m_scalingListAps = pSrc->m_scalingListAps; m_scalingListApsId = pSrc->m_scalingListApsId; +#endif for( int i = 0; i < NUM_REF_PIC_LIST_01; i ++ ) { for (int j = 0; j < MAX_NUM_REF_PICS; j ++ ) @@ -941,7 +1015,11 @@ void Slice::checkLeadingPictureRestrictions(PicList& rcListPic) const // Any picture that has PicOutputFlag equal to 1 that precedes an IRAP picture // in decoding order shall precede the IRAP picture in output order. // (Note that any picture following in output order would be present in the DPB) +#if JVET_P1006_PICTURE_HEADER + if(pcSlice->getPicHeader()->getPicOutputFlag() == 1 && !this->getPicHeader()->getNoOutputOfPriorPicsFlag()) +#else if(pcSlice->getPicOutputFlag() == 1 && !this->getNoOutputPriorPicsFlag()) +#endif { if (nalUnitType == NAL_UNIT_CODED_SLICE_CRA || nalUnitType == NAL_UNIT_CODED_SLICE_IDR_N_LP || @@ -954,7 +1032,11 @@ void Slice::checkLeadingPictureRestrictions(PicList& rcListPic) const // Any picture that has PicOutputFlag equal to 1 that precedes an IRAP picture // in decoding order shall precede any RADL picture associated with the IRAP // picture in output order. +#if JVET_P1006_PICTURE_HEADER + if(pcSlice->getPicHeader()->getPicOutputFlag() == 1) +#else if(pcSlice->getPicOutputFlag() == 1) +#endif { if (nalUnitType == NAL_UNIT_CODED_SLICE_RADL) { @@ -1681,6 +1763,173 @@ VPS::~VPS() { } +#if JVET_P1006_PICTURE_HEADER +// ------------------------------------------------------------------------------------------------ +// Picture Header +// ------------------------------------------------------------------------------------------------ + +PicHeader::PicHeader() +: m_valid ( 0 ) +, m_nonReferencePictureFlag ( 0 ) +, m_gdrPicFlag ( 0 ) +, m_noOutputOfPriorPicsFlag ( 0 ) +, m_recoveryPocCnt ( 0 ) +, m_spsId ( -1 ) +, m_ppsId ( -1 ) +, m_subPicIdSignallingPresentFlag ( 0 ) +, m_subPicIdLen ( 0 ) +, m_loopFilterAcrossVirtualBoundariesDisabledFlag ( 0 ) +, m_numVerVirtualBoundaries ( 0 ) +, m_numHorVirtualBoundaries ( 0 ) +, m_colourPlaneId ( 0 ) +, m_picOutputFlag ( true ) +, m_picRplPresentFlag ( 0 ) +, m_pRPL0 ( 0 ) +, m_pRPL1 ( 0 ) +, m_rpl0Idx ( 0 ) +, m_rpl1Idx ( 0 ) +, m_splitConsOverrideFlag ( 0 ) +, m_cuQpDeltaSubdivIntra ( 0 ) +, m_cuQpDeltaSubdivInter ( 0 ) +, m_cuChromaQpOffsetSubdivIntra ( 0 ) +, m_cuChromaQpOffsetSubdivInter ( 0 ) +, m_enableTMVPFlag ( true ) +, m_mvdL1ZeroFlag ( 0 ) +, m_maxNumMergeCand ( MRG_MAX_NUM_CANDS ) +, m_maxNumAffineMergeCand ( AFFINE_MRG_MAX_NUM_CANDS ) +, m_disFracMMVD ( 0 ) +, m_disBdofDmvrFlag ( 0 ) +, m_maxNumTriangleCand ( 0 ) +, m_maxNumIBCMergeCand ( IBC_MRG_MAX_NUM_CANDS ) +, m_jointCbCrSignFlag ( 0 ) +, m_saoEnabledPresentFlag ( 0 ) +, m_alfEnabledPresentFlag ( 0 ) +, m_numAlfAps ( 0 ) +, m_alfApsId ( 0 ) +, m_alfChromaApsId ( 0 ) +, m_depQuantEnabledFlag ( 0 ) +, m_signDataHidingEnabledFlag ( 0 ) +, m_deblockingFilterOverridePresentFlag ( 0 ) +, m_deblockingFilterOverrideFlag ( 0 ) +, m_deblockingFilterDisable ( 0 ) +, m_deblockingFilterBetaOffsetDiv2 ( 0 ) +, m_deblockingFilterTcOffsetDiv2 ( 0 ) +, m_lmcsEnabledFlag ( 0 ) +, m_lmcsApsId ( -1 ) +, m_lmcsAps ( nullptr ) +, m_lmcsChromaResidualScaleFlag ( 0 ) +, m_scalingListPresentFlag ( 0 ) +, m_scalingListApsId ( -1 ) +, m_scalingListAps ( nullptr ) +{ + memset(m_subPicId, 0, sizeof(m_subPicId)); + memset(m_virtualBoundariesPosX, 0, sizeof(m_virtualBoundariesPosX)); + memset(m_virtualBoundariesPosY, 0, sizeof(m_virtualBoundariesPosY)); + memset(m_saoEnabledFlag, 0, sizeof(m_saoEnabledFlag)); + memset(m_alfEnabledFlag, 0, sizeof(m_alfEnabledFlag)); + memset(m_minQT, 0, sizeof(m_minQT)); + memset(m_maxMTTHierarchyDepth, 0, sizeof(m_maxMTTHierarchyDepth)); + memset(m_maxBTSize, 0, sizeof(m_maxBTSize)); + memset(m_maxTTSize, 0, sizeof(m_maxTTSize)); + + m_localRPL0.setNumberOfActivePictures(0); + m_localRPL0.setNumberOfShorttermPictures(0); + m_localRPL0.setNumberOfLongtermPictures(0); + m_localRPL0.setLtrpInSliceHeaderFlag(0); + + m_localRPL1.setNumberOfActivePictures(0); + m_localRPL1.setNumberOfShorttermPictures(0); + m_localRPL1.setNumberOfLongtermPictures(0); + m_localRPL1.setLtrpInSliceHeaderFlag(0); + + m_alfApsId.resize(0); +} + +PicHeader::~PicHeader() +{ + m_alfApsId.resize(0); +} + +/** + - initialize picture header to defaut state + */ +void PicHeader::initPicHeader() +{ + m_valid = 0; + m_nonReferencePictureFlag = 0; + m_gdrPicFlag = 0; + m_noOutputOfPriorPicsFlag = 0; + m_recoveryPocCnt = 0; + m_spsId = -1; + m_ppsId = -1; + m_subPicIdSignallingPresentFlag = 0; + m_subPicIdLen = 0; + m_loopFilterAcrossVirtualBoundariesDisabledFlag = 0; + m_numVerVirtualBoundaries = 0; + m_numHorVirtualBoundaries = 0; + m_colourPlaneId = 0; + m_picOutputFlag = true; + m_picRplPresentFlag = 0; + m_pRPL0 = 0; + m_pRPL1 = 0; + m_rpl0Idx = 0; + m_rpl1Idx = 0; + m_splitConsOverrideFlag = 0; + m_cuQpDeltaSubdivIntra = 0; + m_cuQpDeltaSubdivInter = 0; + m_cuChromaQpOffsetSubdivIntra = 0; + m_cuChromaQpOffsetSubdivInter = 0; + m_enableTMVPFlag = true; + m_mvdL1ZeroFlag = 0; + m_maxNumMergeCand = MRG_MAX_NUM_CANDS; + m_maxNumAffineMergeCand = AFFINE_MRG_MAX_NUM_CANDS; + m_disFracMMVD = 0; + m_disBdofDmvrFlag = 0; + m_maxNumTriangleCand = 0; + m_maxNumIBCMergeCand = IBC_MRG_MAX_NUM_CANDS; + m_jointCbCrSignFlag = 0; + m_saoEnabledPresentFlag = 0; + m_alfEnabledPresentFlag = 0; + m_numAlfAps = 0; + m_alfChromaApsId = 0; + m_depQuantEnabledFlag = 0; + m_signDataHidingEnabledFlag = 0; + m_deblockingFilterOverridePresentFlag = 0; + m_deblockingFilterOverrideFlag = 0; + m_deblockingFilterDisable = 0; + m_deblockingFilterBetaOffsetDiv2 = 0; + m_deblockingFilterTcOffsetDiv2 = 0; + m_lmcsEnabledFlag = 0; + m_lmcsApsId = -1; + m_lmcsAps = nullptr; + m_lmcsChromaResidualScaleFlag = 0; + m_scalingListPresentFlag = 0; + m_scalingListApsId = -1; + m_scalingListAps = nullptr; + memset(m_subPicId, 0, sizeof(m_subPicId)); + memset(m_virtualBoundariesPosX, 0, sizeof(m_virtualBoundariesPosX)); + memset(m_virtualBoundariesPosY, 0, sizeof(m_virtualBoundariesPosY)); + memset(m_saoEnabledFlag, 0, sizeof(m_saoEnabledFlag)); + memset(m_alfEnabledFlag, 0, sizeof(m_alfEnabledFlag)); + memset(m_minQT, 0, sizeof(m_minQT)); + memset(m_maxMTTHierarchyDepth, 0, sizeof(m_maxMTTHierarchyDepth)); + memset(m_maxBTSize, 0, sizeof(m_maxBTSize)); + memset(m_maxTTSize, 0, sizeof(m_maxTTSize)); + + m_localRPL0.setNumberOfActivePictures(0); + m_localRPL0.setNumberOfShorttermPictures(0); + m_localRPL0.setNumberOfLongtermPictures(0); + m_localRPL0.setLtrpInSliceHeaderFlag(0); + + m_localRPL1.setNumberOfActivePictures(0); + m_localRPL1.setNumberOfShorttermPictures(0); + m_localRPL1.setNumberOfLongtermPictures(0); + m_localRPL1.setLtrpInSliceHeaderFlag(0); + + m_alfApsId.resize(0); +} + +#endif // ------------------------------------------------------------------------------------------------ // Sequence parameter set (SPS) // ------------------------------------------------------------------------------------------------ @@ -1713,10 +1962,19 @@ SPS::SPS() #endif , m_ISP ( false ) , m_chromaFormatIdc (CHROMA_420) +#if JVET_P1006_PICTURE_HEADER +, m_separateColourPlaneFlag(0) +#endif , m_uiMaxTLayers ( 1) // Structure , m_maxWidthInLumaSamples (352) , m_maxHeightInLumaSamples (288) +#if JVET_P1006_PICTURE_HEADER +, m_numSubPics(1) +, m_subPicIdPresentFlag(0) +, m_subPicIdSignallingPresentFlag(0) +, m_subPicIdLen(16) +#endif , m_log2MinCodingBlockSize ( 0) , m_log2DiffMaxMinCodingBlockSize(0) , m_CTUSize(0) @@ -1753,6 +2011,11 @@ SPS::SPS() , m_saoEnabledFlag (false) , m_bTemporalIdNestingFlag (false) , m_scalingListEnabledFlag (false) +#if JVET_P1006_PICTURE_HEADER +, m_loopFilterAcrossVirtualBoundariesDisabledFlag(0) +, m_numVerVirtualBoundaries(0) +, m_numHorVirtualBoundaries(0) +#endif , m_hrdParametersPresentFlag (false) , m_vuiParametersPresentFlag (false) , m_vuiParameters () @@ -1798,6 +2061,10 @@ SPS::SPS() ::memset(m_ltRefPicPocLsbSps, 0, sizeof(m_ltRefPicPocLsbSps)); ::memset(m_usedByCurrPicLtSPSFlag, 0, sizeof(m_usedByCurrPicLtSPSFlag)); +#if JVET_P1006_PICTURE_HEADER + ::memset(m_virtualBoundariesPosX, 0, sizeof(m_virtualBoundariesPosX)); + ::memset(m_virtualBoundariesPosY, 0, sizeof(m_virtualBoundariesPosY)); +#endif } SPS::~SPS() @@ -1935,15 +2202,24 @@ PPS::PPS() , m_useDQP (false) , m_bConstrainedIntraPred (false) , m_bSliceChromaQpFlag (false) +#if !JVET_P1006_PICTURE_HEADER , m_cuQpDeltaSubdiv (0) +#endif , m_chromaCbQpOffset (0) , m_chromaCrQpOffset (0) , m_chromaCbCrQpOffset (0) +#if !JVET_P1006_PICTURE_HEADER , m_cuChromaQpOffsetSubdiv (0) +#endif , m_chromaQpOffsetListLen (0) , m_numRefIdxL0DefaultActive (1) , m_numRefIdxL1DefaultActive (1) , m_rpl1IdxPresentFlag (false) +#if JVET_P1006_PICTURE_HEADER +, m_numSubPics (1) +, m_subPicIdSignallingPresentFlag (0) +, m_subPicIdLen (16) +#endif , m_TransquantBypassEnabledFlag (false) , m_log2MaxTransformSkipBlockSize (2) , m_entropyCodingSyncEnabledFlag (false) @@ -1977,13 +2253,18 @@ PPS::PPS() #endif , m_PPSMaxNumMergeCandMinusMaxNumTriangleCandPlus1 (0) , m_cabacInitPresentFlag (false) +#if JVET_P1006_PICTURE_HEADER +, m_pictureHeaderExtensionPresentFlag(0) +#endif , m_sliceHeaderExtensionPresentFlag (false) , m_loopFilterAcrossSlicesEnabledFlag(false) , m_listsModificationPresentFlag (0) , m_numExtraSliceHeaderBits (0) +#if !JVET_P1006_PICTURE_HEADER , m_loopFilterAcrossVirtualBoundariesDisabledFlag(false) , m_numVerVirtualBoundaries (0) , m_numHorVirtualBoundaries (0) +#endif , m_picWidthInLumaSamples( 352 ) , m_picHeightInLumaSamples( 288 ) , m_ppsRangeExtension () @@ -1992,8 +2273,10 @@ PPS::PPS() m_ChromaQpAdjTableIncludingNullEntry[0].u.comp.CbOffset = 0; // Array includes entry [0] for the null offset used when cu_chroma_qp_offset_flag=0. This is initialised here and never subsequently changed. m_ChromaQpAdjTableIncludingNullEntry[0].u.comp.CrOffset = 0; m_ChromaQpAdjTableIncludingNullEntry[0].u.comp.JointCbCrOffset = 0; +#if !JVET_P1006_PICTURE_HEADER ::memset(m_virtualBoundariesPosX, 0, sizeof(m_virtualBoundariesPosX)); ::memset(m_virtualBoundariesPosY, 0, sizeof(m_virtualBoundariesPosY)); +#endif } PPS::~PPS() @@ -2902,8 +3185,13 @@ uint32_t PreCalcValues::getValIdx( const Slice &slice, const ChannelType chType uint32_t PreCalcValues::getMaxBtDepth( const Slice &slice, const ChannelType chType ) const { +#if JVET_P1006_PICTURE_HEADER + if ( slice.getPicHeader()->getSplitConsOverrideFlag() ) + return slice.getPicHeader()->getMaxMTTHierarchyDepth( slice.getSliceType(), ISingleTree ? CHANNEL_TYPE_LUMA : chType); +#else if ( slice.getSplitConsOverrideFlag() ) return (!slice.isIntra() || isLuma(chType) || ISingleTree) ? slice.getMaxMTTHierarchyDepth() : slice.getMaxMTTHierarchyDepthIChroma(); +#endif else return maxBtDepth[getValIdx( slice, chType )]; } @@ -2915,8 +3203,13 @@ uint32_t PreCalcValues::getMinBtSize( const Slice &slice, const ChannelType chTy uint32_t PreCalcValues::getMaxBtSize( const Slice &slice, const ChannelType chType ) const { +#if JVET_P1006_PICTURE_HEADER + if (slice.getPicHeader()->getSplitConsOverrideFlag()) + return slice.getPicHeader()->getMaxBTSize( slice.getSliceType(), ISingleTree ? CHANNEL_TYPE_LUMA : chType); +#else if (slice.getSplitConsOverrideFlag()) return (!slice.isIntra() || isLuma(chType) || ISingleTree) ? slice.getMaxBTSize() : slice.getMaxBTSizeIChroma(); +#endif else return maxBtSize[getValIdx(slice, chType)]; } @@ -2928,20 +3221,34 @@ uint32_t PreCalcValues::getMinTtSize( const Slice &slice, const ChannelType chTy uint32_t PreCalcValues::getMaxTtSize( const Slice &slice, const ChannelType chType ) const { +#if JVET_P1006_PICTURE_HEADER + if (slice.getPicHeader()->getSplitConsOverrideFlag()) + return slice.getPicHeader()->getMaxTTSize( slice.getSliceType(), ISingleTree ? CHANNEL_TYPE_LUMA : chType); +#else if ( slice.getSplitConsOverrideFlag() ) return (!slice.isIntra() || isLuma(chType) || ISingleTree) ? slice.getMaxTTSize() : slice.getMaxTTSizeIChroma(); +#endif else return maxTtSize[getValIdx( slice, chType )]; } uint32_t PreCalcValues::getMinQtSize( const Slice &slice, const ChannelType chType ) const { +#if JVET_P1006_PICTURE_HEADER + if (slice.getPicHeader()->getSplitConsOverrideFlag()) + return slice.getPicHeader()->getMinQTSize( slice.getSliceType(), ISingleTree ? CHANNEL_TYPE_LUMA : chType); +#else if ( slice.getSplitConsOverrideFlag() ) return (!slice.isIntra() || isLuma(chType) || ISingleTree) ? slice.getMinQTSize() : slice.getMinQTSizeIChroma(); +#endif else return minQtSize[getValIdx( slice, chType )]; } +#if JVET_P1006_PICTURE_HEADER +void Slice::scaleRefPicList( Picture *scaledRefPic[ ], PicHeader *picHeader, APS** apss, APS* lmcsAps, APS* scalingListAps, const bool isDecoder ) +#else void Slice::scaleRefPicList( Picture *scaledRefPic[ ], APS** apss, APS* lmcsAps, APS* scalingListAps, const bool isDecoder ) +#endif { int i; const SPS* sps = getSPS(); @@ -3027,7 +3334,11 @@ void Slice::scaleRefPicList( Picture *scaledRefPic[ ], APS** apss, APS* lmcsAps, scaledRefPic[j]->reconstructed = false; scaledRefPic[j]->referenced = true; +#if JVET_P1006_PICTURE_HEADER + scaledRefPic[ j ]->finalInit( *sps, *pps, picHeader, apss, lmcsAps, scalingListAps ); +#else scaledRefPic[ j ]->finalInit( *sps, *pps, apss, lmcsAps, scalingListAps ); +#endif scaledRefPic[j]->poc = -1; @@ -3078,7 +3389,11 @@ void Slice::scaleRefPicList( Picture *scaledRefPic[ ], APS** apss, APS* lmcsAps, //Make sure that TMVP is disabled when there are no reference pictures with the same resolution if(!refPicIsSameRes) { +#if JVET_P1006_PICTURE_HEADER + CHECK(getPicHeader()->getEnableTMVPFlag() != 0, "TMVP cannot be enabled in pictures that have no reference pictures with the same resolution") +#else CHECK(m_enableTMVPFlag != 0, "TMVP cannot be enabled in slices that have no reference pictures with the same resolution") +#endif } #endif } @@ -3149,6 +3464,13 @@ void xTraceAPSHeader() DTRACE(g_trace_ctx, D_HEADER, "=========== Adaptation Parameter Set ===========\n"); } +#if JVET_P1006_PICTURE_HEADER +void xTracePictureHeader() +{ + DTRACE( g_trace_ctx, D_HEADER, "=========== Picture Header ===========\n" ); +} + +#endif void xTraceSliceHeader() { DTRACE( g_trace_ctx, D_HEADER, "=========== Slice ===========\n" ); diff --git a/source/Lib/CommonLib/Slice.h b/source/Lib/CommonLib/Slice.h index 83f12218c..358278cec 100644 --- a/source/Lib/CommonLib/Slice.h +++ b/source/Lib/CommonLib/Slice.h @@ -855,12 +855,22 @@ private: #endif bool m_ISP; ChromaFormat m_chromaFormatIdc; +#if JVET_P1006_PICTURE_HEADER + bool m_separateColourPlaneFlag; //!< separate colour plane flag +#endif uint32_t m_uiMaxTLayers; // maximum number of temporal layers // Structure uint32_t m_maxWidthInLumaSamples; uint32_t m_maxHeightInLumaSamples; +#if JVET_P1006_PICTURE_HEADER + uint8_t m_numSubPics; //!< number of sub-pictures used + bool m_subPicIdPresentFlag; //!< indicates the presence of sub-picture IDs + bool m_subPicIdSignallingPresentFlag; //!< indicates the presence of sub-picture ID signalling in the SPS + uint32_t m_subPicIdLen; //!< sub-picture ID length in bits + uint8_t m_subPicId[MAX_NUM_SUB_PICS]; //!< sub-picture ID for each sub-picture in the sequence +#endif int m_log2MinCodingBlockSize; int m_log2DiffMaxMinCodingBlockSize; @@ -919,6 +929,13 @@ private: bool m_bTemporalIdNestingFlag; // temporal_id_nesting_flag bool m_scalingListEnabledFlag; +#if JVET_P1006_PICTURE_HEADER + bool m_loopFilterAcrossVirtualBoundariesDisabledFlag; //!< disable loop filtering across virtual boundaries + unsigned m_numVerVirtualBoundaries; //!< number of vertical virtual boundaries + unsigned m_numHorVirtualBoundaries; //!< number of horizontal virtual boundaries + unsigned m_virtualBoundariesPosX[3]; //!< horizontal position of each vertical virtual boundary + unsigned m_virtualBoundariesPosY[3]; //!< vertical position of each horizontal virtual boundary +#endif uint32_t m_uiMaxDecPicBuffering[MAX_TLAYER]; uint32_t m_uiMaxLatencyIncreasePlus1[MAX_TLAYER]; @@ -980,6 +997,10 @@ public: int getDecodingParameterSetId() const { return m_decodingParameterSetId; } ChromaFormat getChromaFormatIdc () const { return m_chromaFormatIdc; } void setChromaFormatIdc (ChromaFormat i) { m_chromaFormatIdc = i; } + #if JVET_P1006_PICTURE_HEADER + void setSeparateColourPlaneFlag ( bool b ) { m_separateColourPlaneFlag = b; } + bool getSeparateColourPlaneFlag () const { return m_separateColourPlaneFlag; } +#endif static int getWinUnitX (int chromaFormatIdc) { CHECK(chromaFormatIdc < 0 || chromaFormatIdc >= NUM_CHROMA_FORMAT, "Invalid chroma format parameter"); return m_winUnitX[chromaFormatIdc]; } static int getWinUnitY (int chromaFormatIdc) { CHECK(chromaFormatIdc < 0 || chromaFormatIdc >= NUM_CHROMA_FORMAT, "Invalid chroma format parameter"); return m_winUnitY[chromaFormatIdc]; } @@ -989,6 +1010,18 @@ public: uint32_t getMaxPicWidthInLumaSamples() const { return m_maxWidthInLumaSamples; } void setMaxPicHeightInLumaSamples( uint32_t u ) { m_maxHeightInLumaSamples = u; } uint32_t getMaxPicHeightInLumaSamples() const { return m_maxHeightInLumaSamples; } +#if JVET_P1006_PICTURE_HEADER + void setNumSubPics( uint8_t u ) { m_numSubPics = u; } + uint8_t getNumSubPics( ) const { return m_numSubPics; } + void setSubPicIdPresentFlag( bool b ) { m_subPicIdPresentFlag = b; } + bool getSubPicIdPresentFlag() const { return m_subPicIdPresentFlag; } + void setSubPicIdSignallingPresentFlag( bool b ) { m_subPicIdSignallingPresentFlag = b; } + bool getSubPicIdSignallingPresentFlag() const { return m_subPicIdSignallingPresentFlag; } + void setSubPicIdLen( uint32_t u ) { m_subPicIdLen = u; } + uint32_t getSubPicIdLen() const { return m_subPicIdLen; } + void setSubPicId( int i, uint8_t u ) { CHECK( i >= MAX_NUM_SUB_PICS, "Sub-picture index exceeds valid range" ); m_subPicId[i] = u; } + uint8_t getSubPicId( int i ) const { CHECK( i >= MAX_NUM_SUB_PICS, "Sub-picture index exceeds valid range" ); return m_subPicId[i]; } +#endif uint32_t getNumLongTermRefPicSPS() const { return m_numLongTermRefPicSPS; } void setNumLongTermRefPicSPS(uint32_t val) { m_numLongTermRefPicSPS = val; } @@ -1032,6 +1065,12 @@ public: unsigned getMaxTTSize() const { return m_maxTTSize[1]; } unsigned getMaxTTSizeI() const { return m_maxTTSize[0]; } unsigned getMaxTTSizeIChroma() const { return m_maxTTSize[2]; } +#if JVET_P1006_PICTURE_HEADER + unsigned* getMinQTSizes() const { return (unsigned *)m_minQT; } + unsigned* getMaxMTTHierarchyDepths() const { return (unsigned *)m_maxMTTHierarchyDepth; } + unsigned* getMaxBTSizes() const { return (unsigned *)m_maxBTSize; } + unsigned* getMaxTTSizes() const { return (unsigned *)m_maxTTSize; } +#endif void setIDRRefParamListPresent(bool b) { m_idrRefParamList = b; } bool getIDRRefParamListPresent() const { return m_idrRefParamList; } void setUseDualITree(bool b) { m_dualITree = b; } @@ -1058,6 +1097,11 @@ public: int getNumReorderPics(uint32_t tlayer) const { return m_numReorderPics[tlayer]; } void createRPLList0(int numRPL); void createRPLList1(int numRPL); +#if JVET_P1006_PICTURE_HEADER + const RPLList* getRPLList( bool b ) const { return b==1 ? &m_RPLList1 : &m_RPLList0; } + RPLList* getRPLList( bool b ) { return b==1 ? &m_RPLList1 : &m_RPLList0; } + uint32_t getNumRPL( bool b ) const { return b==1 ? m_numRPL1 : m_numRPL0; } +#endif const RPLList* getRPLList0() const { return &m_RPLList0; } RPLList* getRPLList0() { return &m_RPLList0; } const RPLList* getRPLList1() const { return &m_RPLList1; } @@ -1118,6 +1162,18 @@ public: bool getScalingListFlag() const { return m_scalingListEnabledFlag; } void setScalingListFlag( bool b ) { m_scalingListEnabledFlag = b; } +#if JVET_P1006_PICTURE_HEADER + void setLoopFilterAcrossVirtualBoundariesDisabledFlag(bool b) { m_loopFilterAcrossVirtualBoundariesDisabledFlag = b; } + bool getLoopFilterAcrossVirtualBoundariesDisabledFlag() const { return m_loopFilterAcrossVirtualBoundariesDisabledFlag; } + void setNumVerVirtualBoundaries(unsigned u) { m_numVerVirtualBoundaries = u; } + unsigned getNumVerVirtualBoundaries() const { return m_numVerVirtualBoundaries; } + void setNumHorVirtualBoundaries(unsigned u) { m_numHorVirtualBoundaries = u; } + unsigned getNumHorVirtualBoundaries() const { return m_numHorVirtualBoundaries; } + void setVirtualBoundariesPosX(unsigned u, unsigned idx) { CHECK( idx >= 3, "vitrual boundary index exceeds valid range" ); m_virtualBoundariesPosX[idx] = u; } + unsigned getVirtualBoundariesPosX(unsigned idx) const { CHECK( idx >= 3, "vitrual boundary index exceeds valid range" ); return m_virtualBoundariesPosX[idx]; } + void setVirtualBoundariesPosY(unsigned u, unsigned idx) { CHECK( idx >= 3, "vitrual boundary index exceeds valid range" ); m_virtualBoundariesPosY[idx] = u; } + unsigned getVirtualBoundariesPosY(unsigned idx) const { CHECK( idx >= 3, "vitrual boundary index exceeds valid range" ); return m_virtualBoundariesPosY[idx]; } +#endif uint32_t getMaxDecPicBuffering(uint32_t tlayer) const { return m_uiMaxDecPicBuffering[tlayer]; } void setMaxDecPicBuffering( uint32_t ui, uint32_t tlayer ) { CHECK(tlayer >= MAX_TLAYER, "Invalid T-layer"); m_uiMaxDecPicBuffering[tlayer] = ui; } uint32_t getMaxLatencyIncreasePlus1(uint32_t tlayer) const { return m_uiMaxLatencyIncreasePlus1[tlayer]; } @@ -1264,7 +1320,9 @@ private: int m_temporalId; // access channel +#if !JVET_P1006_PICTURE_HEADER uint32_t m_cuQpDeltaSubdiv; // cu_qp_delta_subdiv +#endif int m_chromaCbQpOffset; int m_chromaCrQpOffset; @@ -1274,7 +1332,9 @@ private: int m_chromaCbCrQpOffset; // Chroma QP Adjustments +#if !JVET_P1006_PICTURE_HEADER int m_cuChromaQpOffsetSubdiv; +#endif int m_chromaQpOffsetListLen; // size (excludes the null entry used in the following array). ChromaQpAdj m_ChromaQpAdjTableIncludingNullEntry[1+MAX_QP_OFFSET_LIST_SIZE]; //!< Array includes entry [0] for the null offset used when cu_chroma_qp_offset_flag=0, and entries [cu_chroma_qp_offset_idx+1...] otherwise @@ -1286,6 +1346,12 @@ private: bool m_bUseWeightPred; //!< Use of Weighting Prediction (P_SLICE) bool m_useWeightedBiPred; //!< Use of Weighting Bi-Prediction (B_SLICE) bool m_OutputFlagPresentFlag; //!< Indicates the presence of output_flag in slice header +#if JVET_P1006_PICTURE_HEADER + uint8_t m_numSubPics; //!< number of sub-pictures used - must match SPS + bool m_subPicIdSignallingPresentFlag; //!< indicates the presence of sub-picture ID signalling in the PPS + uint32_t m_subPicIdLen; //!< sub-picture ID length in bits + uint8_t m_subPicId[MAX_NUM_SUB_PICS]; //!< sub-picture ID for each sub-picture in the sequence +#endif bool m_TransquantBypassEnabledFlag; //!< Indicates presence of cu_transquant_bypass_flag in CUs. int m_log2MaxTransformSkipBlockSize; bool m_entropyCodingSyncEnabledFlag; //!< Indicates the presence of wavefronts @@ -1336,6 +1402,9 @@ private: bool m_cabacInitPresentFlag; +#if JVET_P1006_PICTURE_HEADER + bool m_pictureHeaderExtensionPresentFlag; //< picture header extension flags present in picture headers or not +#endif bool m_sliceHeaderExtensionPresentFlag; bool m_loopFilterAcrossSlicesEnabledFlag; bool m_deblockingFilterControlPresentFlag; @@ -1347,11 +1416,13 @@ private: uint32_t m_log2ParallelMergeLevelMinus2; int m_numExtraSliceHeaderBits; +#if !JVET_P1006_PICTURE_HEADER bool m_loopFilterAcrossVirtualBoundariesDisabledFlag; unsigned m_numVerVirtualBoundaries; unsigned m_numHorVirtualBoundaries; unsigned m_virtualBoundariesPosX[3]; unsigned m_virtualBoundariesPosY[3]; +#endif uint32_t m_picWidthInLumaSamples; uint32_t m_picHeightInLumaSamples; @@ -1385,8 +1456,10 @@ public: bool getSliceChromaQpFlag() const { return m_bSliceChromaQpFlag; } void setSliceChromaQpFlag( bool b ) { m_bSliceChromaQpFlag = b; } +#if !JVET_P1006_PICTURE_HEADER void setCuQpDeltaSubdiv( uint32_t u ) { m_cuQpDeltaSubdiv = u; } uint32_t getCuQpDeltaSubdiv() const { return m_cuQpDeltaSubdiv; } +#endif #if JVET_P0667_QP_OFFSET_TABLE_SIGNALING_JCCR bool getJointCbCrQpOffsetPresentFlag() const { return m_chromaJointCbCrQpOffsetPresentFlag; } @@ -1417,9 +1490,11 @@ public: return (compID==COMPONENT_Y) ? 0 : (compID==COMPONENT_Cb ? m_chromaCbQpOffset : compID==COMPONENT_Cr ? m_chromaCrQpOffset : m_chromaCbCrQpOffset ); } +#if !JVET_P1006_PICTURE_HEADER uint32_t getCuChromaQpOffsetSubdiv () const { return m_cuChromaQpOffsetSubdiv; } void setCuChromaQpOffsetSubdiv ( uint32_t u ) { m_cuChromaQpOffsetSubdiv = u; } +#endif bool getCuChromaQpOffsetEnabledFlag() const { return getChromaQpOffsetListLen()>0; } int getChromaQpOffsetListLen() const { return m_chromaQpOffsetListLen; } void clearChromaQpOffsetList() { m_chromaQpOffsetListLen = 0; } @@ -1454,6 +1529,16 @@ public: void setOutputFlagPresentFlag( bool b ) { m_OutputFlagPresentFlag = b; } bool getOutputFlagPresentFlag() const { return m_OutputFlagPresentFlag; } +#if JVET_P1006_PICTURE_HEADER + void setNumSubPics( uint8_t u ) { m_numSubPics = u; } + uint8_t getNumSubPics( ) const { return m_numSubPics; } + void setSubPicIdSignallingPresentFlag( bool b ) { m_subPicIdSignallingPresentFlag = b; } + bool getSubPicIdSignallingPresentFlag() const { return m_subPicIdSignallingPresentFlag; } + void setSubPicIdLen( uint32_t u ) { m_subPicIdLen = u; } + uint32_t getSubPicIdLen() const { return m_subPicIdLen; } + void setSubPicId( int i, uint8_t u ) { CHECK( i >= MAX_NUM_SUB_PICS, "Sub-picture index exceeds valid range" ); m_subPicId[i] = u; } + uint8_t getSubPicId( int i ) const { CHECK( i >= MAX_NUM_SUB_PICS, "Sub-picture index exceeds valid range" ); return m_subPicId[i]; } +#endif void setTransquantBypassEnabledFlag( bool b ) { m_TransquantBypassEnabledFlag = b; } bool getTransquantBypassEnabledFlag() const { return m_TransquantBypassEnabledFlag; } @@ -1523,6 +1608,9 @@ public: void setConstantSliceHeaderParamsEnabledFlag(bool b) { m_constantSliceHeaderParamsEnabledFlag = b; } int getPPSDepQuantEnabledIdc() const { return m_PPSDepQuantEnabledIdc; } void setPPSDepQuantEnabledIdc(int u) { m_PPSDepQuantEnabledIdc = u; } +#if JVET_P1006_PICTURE_HEADER + int getPPSRefPicListSPSIdc( bool b ) const { return b==1 ? m_PPSRefPicListSPSIdc1: m_PPSRefPicListSPSIdc0; } +#endif int getPPSRefPicListSPSIdc0() const { return m_PPSRefPicListSPSIdc0; } void setPPSRefPicListSPSIdc0(int u) { m_PPSRefPicListSPSIdc0 = u; } int getPPSRefPicListSPSIdc1() const { return m_PPSRefPicListSPSIdc1; } @@ -1564,9 +1652,14 @@ public: void setNumExtraSliceHeaderBits(int i) { m_numExtraSliceHeaderBits = i; } void setLoopFilterAcrossSlicesEnabledFlag( bool bValue ) { m_loopFilterAcrossSlicesEnabledFlag = bValue; } bool getLoopFilterAcrossSlicesEnabledFlag() const { return m_loopFilterAcrossSlicesEnabledFlag; } +#if JVET_P1006_PICTURE_HEADER + bool getPictureHeaderExtensionPresentFlag() const { return m_pictureHeaderExtensionPresentFlag; } + void setPictureHeaderExtensionPresentFlag(bool val) { m_pictureHeaderExtensionPresentFlag = val; } +#endif bool getSliceHeaderExtensionPresentFlag() const { return m_sliceHeaderExtensionPresentFlag; } void setSliceHeaderExtensionPresentFlag(bool val) { m_sliceHeaderExtensionPresentFlag = val; } +#if !JVET_P1006_PICTURE_HEADER void setLoopFilterAcrossVirtualBoundariesDisabledFlag(bool b) { m_loopFilterAcrossVirtualBoundariesDisabledFlag = b; } bool getLoopFilterAcrossVirtualBoundariesDisabledFlag() const { return m_loopFilterAcrossVirtualBoundariesDisabledFlag; } void setNumVerVirtualBoundaries(unsigned u) { m_numVerVirtualBoundaries = u; } @@ -1577,6 +1670,7 @@ public: unsigned getVirtualBoundariesPosX(unsigned idx) const { return m_virtualBoundariesPosX[idx]; } void setVirtualBoundariesPosY(unsigned u, unsigned idx) { m_virtualBoundariesPosY[idx] = u; } unsigned getVirtualBoundariesPosY(unsigned idx) const { return m_virtualBoundariesPosY[idx]; } +#endif const PPSRExt& getPpsRangeExtension() const { return m_ppsRangeExtension; } PPSRExt& getPpsRangeExtension() { return m_ppsRangeExtension; } @@ -1647,6 +1741,242 @@ struct WPACDCParam int64_t iDC; }; +#if JVET_P1006_PICTURE_HEADER +// picture header class +class PicHeader +{ +private: + bool m_valid; //!< picture header is valid yet or not + Picture* m_pcPic; //!< pointer to picture structure + bool m_nonReferencePictureFlag; //!< non-reference picture flag + bool m_gdrPicFlag; //!< gradual decoding refresh picture flag + bool m_noOutputOfPriorPicsFlag; //!< no output of prior pictures flag + uint32_t m_recoveryPocCnt; //!< recovery POC count + int m_spsId; //!< sequence parameter set ID + int m_ppsId; //!< picture parameter set ID + bool m_subPicIdSignallingPresentFlag; //!< indicates the presence of sub-picture ID signalling in the SPS + uint32_t m_subPicIdLen; //!< sub-picture ID length in bits + uint8_t m_subPicId[MAX_NUM_SUB_PICS]; //!< sub-picture ID for each sub-picture in the sequence + bool m_loopFilterAcrossVirtualBoundariesDisabledFlag; //!< loop filtering across virtual boundaries disabled + unsigned m_numVerVirtualBoundaries; //!< number of vertical virtual boundaries + unsigned m_numHorVirtualBoundaries; //!< number of horizontal virtual boundaries + unsigned m_virtualBoundariesPosX[3]; //!< horizontal virtual boundary positions + unsigned m_virtualBoundariesPosY[3]; //!< vertical virtual boundary positions + unsigned m_colourPlaneId; //!< 4:4:4 colour plane ID + bool m_picOutputFlag; //!< picture output flag + bool m_picRplPresentFlag; //!< reference lists present in picture header or not + const ReferencePictureList* m_pRPL0; //!< pointer to RPL for L0, either in the SPS or the local RPS in the picture header + const ReferencePictureList* m_pRPL1; //!< pointer to RPL for L1, either in the SPS or the local RPS in the picture header + ReferencePictureList m_localRPL0; //!< RPL for L0 when present in picture header + ReferencePictureList m_localRPL1; //!< RPL for L1 when present in picture header + int m_rpl0Idx; //!< index of used RPL in the SPS or -1 for local RPL in the picture header + int m_rpl1Idx; //!< index of used RPL in the SPS or -1 for local RPL in the picture header + bool m_splitConsOverrideFlag; //!< partitioning constraint override flag + uint32_t m_cuQpDeltaSubdivIntra; //!< CU QP delta maximum subdivision for intra slices + uint32_t m_cuQpDeltaSubdivInter; //!< CU QP delta maximum subdivision for inter slices + uint32_t m_cuChromaQpOffsetSubdivIntra; //!< CU chroma QP offset maximum subdivision for intra slices + uint32_t m_cuChromaQpOffsetSubdivInter; //!< CU chroma QP offset maximum subdivision for inter slices + bool m_enableTMVPFlag; //!< enable temporal motion vector prediction + bool m_mvdL1ZeroFlag; //!< L1 MVD set to zero flag + uint32_t m_maxNumMergeCand; //!< max number of merge candidates + uint32_t m_maxNumAffineMergeCand; //!< max number of sub-block merge candidates + bool m_disFracMMVD; //!< fractional MMVD offsets disabled flag + bool m_disBdofDmvrFlag; //!< picture level BDOF/DMVR disable flag + uint32_t m_maxNumTriangleCand; //!< max number of triangle merge candidates + uint32_t m_maxNumIBCMergeCand; //!< max number of IBC merge candidates + bool m_jointCbCrSignFlag; //!< joint Cb/Cr residual sign flag + bool m_saoEnabledPresentFlag; //!< sao enabled flags present in the picture header + bool m_saoEnabledFlag[MAX_NUM_CHANNEL_TYPE]; //!< sao enabled flags for each channel + bool m_alfEnabledPresentFlag; //!< alf enabled flags present in the picture header + bool m_alfEnabledFlag[MAX_NUM_COMPONENT]; //!< alf enabled flags for each component + int m_numAlfAps; //!< number of alf aps active for the picture + std::vector<int> m_alfApsId; //!< list of alf aps for the picture + int m_alfChromaApsId; //!< chroma alf aps ID + bool m_depQuantEnabledFlag; //!< dependent quantization enabled flag + bool m_signDataHidingEnabledFlag; //!< sign data hiding enabled flag + bool m_deblockingFilterOverridePresentFlag; //!< deblocking filter override controls present in picture header + bool m_deblockingFilterOverrideFlag; //!< deblocking filter override controls enabled + bool m_deblockingFilterDisable; //!< deblocking filter disabled flag + int m_deblockingFilterBetaOffsetDiv2; //!< beta offset for deblocking filter + int m_deblockingFilterTcOffsetDiv2; //!< tc offset for deblocking filter + bool m_lmcsEnabledFlag; //!< lmcs enabled flag + int m_lmcsApsId; //!< lmcs APS ID + APS* m_lmcsAps; //!< lmcs APS + bool m_lmcsChromaResidualScaleFlag; //!< lmcs chroma residual scale flag + bool m_scalingListPresentFlag; //!< quantization scaling lists present + int m_scalingListApsId; //!< quantization scaling list APS ID + APS* m_scalingListAps; //!< quantization scaling list APS + unsigned m_minQT[3]; //!< minimum quad-tree size 0: I slice luma; 1: P/B slice; 2: I slice chroma + unsigned m_maxMTTHierarchyDepth[3]; //!< maximum MTT depth + unsigned m_maxBTSize[3]; //!< maximum BT size + unsigned m_maxTTSize[3]; //!< maximum TT size + +public: + PicHeader(); + virtual ~PicHeader(); + void initPicHeader(); + bool isValid() { return m_valid; } + void setValid() { m_valid = true; } + void setPic( Picture* p ) { m_pcPic = p; } + Picture* getPic() { return m_pcPic; } + const Picture* getPic() const { return m_pcPic; } + void setNonReferencePictureFlag( bool b ) { m_nonReferencePictureFlag = b; } + bool getNonReferencePictureFlag() const { return m_nonReferencePictureFlag; } + void setGdrPicFlag( bool b ) { m_gdrPicFlag = b; } + bool getGdrPicFlag() const { return m_gdrPicFlag; } + void setNoOutputOfPriorPicsFlag( bool b ) { m_noOutputOfPriorPicsFlag = b; } + bool getNoOutputOfPriorPicsFlag() const { return m_noOutputOfPriorPicsFlag; } + void setRecoveryPocCnt( uint32_t u ) { m_recoveryPocCnt = u; } + bool getRecoveryPocCnt() const { return m_recoveryPocCnt; } + void setSPSId( uint32_t u ) { m_spsId = u; } + uint32_t getSPSId() const { return m_spsId; } + void setPPSId( uint32_t u ) { m_ppsId = u; } + uint32_t getPPSId() const { return m_ppsId; } + void setSubPicIdSignallingPresentFlag( bool b ) { m_subPicIdSignallingPresentFlag = b; } + bool getSubPicIdSignallingPresentFlag() const { return m_subPicIdSignallingPresentFlag; } + void setSubPicIdLen( uint32_t u ) { m_subPicIdLen = u; } + uint32_t getSubPicIdLen() const { return m_subPicIdLen; } + void setSubPicId( int i, uint8_t u ) { CHECK( i >= MAX_NUM_SUB_PICS, "Sub-pic index exceeds valid range" ); m_subPicId[i] = u; } + uint8_t getSubPicId( int i ) const { CHECK( i >= MAX_NUM_SUB_PICS, "Sub-pic index exceeds valid range" ); return m_subPicId[i]; } + void setLoopFilterAcrossVirtualBoundariesDisabledFlag(bool b) { m_loopFilterAcrossVirtualBoundariesDisabledFlag = b; } + bool getLoopFilterAcrossVirtualBoundariesDisabledFlag() const { return m_loopFilterAcrossVirtualBoundariesDisabledFlag; } + void setNumVerVirtualBoundaries(unsigned u) { m_numVerVirtualBoundaries = u; } + unsigned getNumVerVirtualBoundaries() const { return m_numVerVirtualBoundaries; } + void setNumHorVirtualBoundaries(unsigned u) { m_numHorVirtualBoundaries = u; } + unsigned getNumHorVirtualBoundaries() const { return m_numHorVirtualBoundaries; } + void setVirtualBoundariesPosX(unsigned u, unsigned idx) { CHECK( idx >= 3, "boundary index exceeds valid range" ); m_virtualBoundariesPosX[idx] = u; } + unsigned getVirtualBoundariesPosX(unsigned idx) const { CHECK( idx >= 3, "boundary index exceeds valid range" ); return m_virtualBoundariesPosX[idx];} + void setVirtualBoundariesPosY(unsigned u, unsigned idx) { CHECK( idx >= 3, "boundary index exceeds valid range" ); m_virtualBoundariesPosY[idx] = u; } + unsigned getVirtualBoundariesPosY(unsigned idx) const { CHECK( idx >= 3, "boundary index exceeds valid range" ); return m_virtualBoundariesPosY[idx];} + void setColourPlaneId(unsigned u) { m_colourPlaneId = u; } + unsigned getColourPlaneId() const { return m_colourPlaneId; } + void setPicOutputFlag( bool b ) { m_picOutputFlag = b; } + bool getPicOutputFlag() const { return m_picOutputFlag; } + void setPicRplPresentFlag( bool b ) { m_picRplPresentFlag = b; } + bool getPicRplPresentFlag() const { return m_picRplPresentFlag; } + void setRPL( bool b, const ReferencePictureList *pcRPL) { if(b==1) { m_pRPL1 = pcRPL; } else { m_pRPL0 = pcRPL; } } + const ReferencePictureList* getRPL( bool b ) { return b==1 ? m_pRPL1 : m_pRPL0; } + ReferencePictureList* getLocalRPL( bool b ) { return b==1 ? &m_localRPL1 : &m_localRPL0; } + void setRPLIdx( bool b, int rplIdx) { if(b==1) { m_rpl1Idx = rplIdx; } else { m_rpl0Idx = rplIdx; } } + int getRPLIdx( bool b ) const { return b==1 ? m_rpl1Idx : m_rpl0Idx; } + void setRPL0(const ReferencePictureList *pcRPL) { m_pRPL0 = pcRPL; } + void setRPL1(const ReferencePictureList *pcRPL) { m_pRPL1 = pcRPL; } + const ReferencePictureList* getRPL0() { return m_pRPL0; } + const ReferencePictureList* getRPL1() { return m_pRPL1; } + ReferencePictureList* getLocalRPL0() { return &m_localRPL0; } + ReferencePictureList* getLocalRPL1() { return &m_localRPL1; } + void setRPL0idx(int rplIdx) { m_rpl0Idx = rplIdx; } + void setRPL1idx(int rplIdx) { m_rpl1Idx = rplIdx; } + int getRPL0idx() const { return m_rpl0Idx; } + int getRPL1idx() const { return m_rpl1Idx; } + void setSplitConsOverrideFlag( bool b ) { m_splitConsOverrideFlag = b; } + bool getSplitConsOverrideFlag() const { return m_splitConsOverrideFlag; } + void setCuQpDeltaSubdivIntra( uint32_t u ) { m_cuQpDeltaSubdivIntra = u; } + uint32_t getCuQpDeltaSubdivIntra() const { return m_cuQpDeltaSubdivIntra; } + void setCuQpDeltaSubdivInter( uint32_t u ) { m_cuQpDeltaSubdivInter = u; } + uint32_t getCuQpDeltaSubdivInter() const { return m_cuQpDeltaSubdivInter; } + void setCuChromaQpOffsetSubdivIntra( uint32_t u ) { m_cuChromaQpOffsetSubdivIntra = u; } + uint32_t getCuChromaQpOffsetSubdivIntra() const { return m_cuChromaQpOffsetSubdivIntra; } + void setCuChromaQpOffsetSubdivInter( uint32_t u ) { m_cuChromaQpOffsetSubdivInter = u; } + uint32_t getCuChromaQpOffsetSubdivInter() const { return m_cuChromaQpOffsetSubdivInter; } + void setEnableTMVPFlag( bool b ) { m_enableTMVPFlag = b; } + bool getEnableTMVPFlag() const { return m_enableTMVPFlag; } + void setMvdL1ZeroFlag( bool b ) { m_mvdL1ZeroFlag = b; } + bool getMvdL1ZeroFlag() const { return m_mvdL1ZeroFlag; } + void setMaxNumMergeCand(uint32_t val ) { m_maxNumMergeCand = val; } + uint32_t getMaxNumMergeCand() const { return m_maxNumMergeCand; } + void setMaxNumAffineMergeCand( uint32_t val ) { m_maxNumAffineMergeCand = val; } + uint32_t getMaxNumAffineMergeCand() const { return m_maxNumAffineMergeCand; } + void setDisFracMMVD( bool val ) { m_disFracMMVD = val; } + bool getDisFracMMVD() const { return m_disFracMMVD; } + void setDisBdofDmvrFlag(bool val) { m_disBdofDmvrFlag = val; } + bool getDisBdofDmvrFlag() const { return m_disBdofDmvrFlag; } + void setMaxNumTriangleCand(uint32_t b) { m_maxNumTriangleCand = b; } + uint32_t getMaxNumTriangleCand() const { return m_maxNumTriangleCand; } + void setMaxNumIBCMergeCand( uint32_t b ) { m_maxNumIBCMergeCand = b; } + uint32_t getMaxNumIBCMergeCand() const { return m_maxNumIBCMergeCand; } + void setJointCbCrSignFlag( bool b ) { m_jointCbCrSignFlag = b; } + bool getJointCbCrSignFlag() const { return m_jointCbCrSignFlag; } + void setSaoEnabledPresentFlag( bool b ) { m_saoEnabledPresentFlag = b; } + bool getSaoEnabledPresentFlag() const { return m_saoEnabledPresentFlag; } + void setSaoEnabledFlag(ChannelType chType, bool b) { m_saoEnabledFlag[chType] = b; } + bool getSaoEnabledFlag(ChannelType chType) const { return m_saoEnabledFlag[chType]; } + void setAlfEnabledPresentFlag( bool b ) { m_alfEnabledPresentFlag = b; } + bool getAlfEnabledPresentFlag() const { return m_alfEnabledPresentFlag; } + void setAlfEnabledFlag(ComponentID compId, bool b) { m_alfEnabledFlag[compId] = b; } + bool getAlfEnabledFlag(ComponentID compId) const { return m_alfEnabledFlag[compId]; } + void setNumAlfAps(int i) { m_numAlfAps = i; } + int getNumAlfAps() const { return m_numAlfAps; } + void setAlfApsIdChroma(int i) { m_alfChromaApsId = i; } + int getAlfApsIdChroma() const { return m_alfChromaApsId; } + void setDepQuantEnabledFlag( bool b ) { m_depQuantEnabledFlag = b; } + bool getDepQuantEnabledFlag() const { return m_depQuantEnabledFlag; } + void setSignDataHidingEnabledFlag( bool b ) { m_signDataHidingEnabledFlag = b; } + bool getSignDataHidingEnabledFlag() const { return m_signDataHidingEnabledFlag; } + void setDeblockingFilterOverridePresentFlag( bool b ) { m_deblockingFilterOverridePresentFlag = b; } + bool getDeblockingFilterOverridePresentFlag() const { return m_deblockingFilterOverridePresentFlag; } + void setDeblockingFilterOverrideFlag( bool b ) { m_deblockingFilterOverrideFlag = b; } + bool getDeblockingFilterOverrideFlag() const { return m_deblockingFilterOverrideFlag; } + void setDeblockingFilterDisable( bool b ) { m_deblockingFilterDisable= b; } + bool getDeblockingFilterDisable() const { return m_deblockingFilterDisable; } + void setDeblockingFilterBetaOffsetDiv2( int i ) { m_deblockingFilterBetaOffsetDiv2 = i; } + int getDeblockingFilterBetaOffsetDiv2()const { return m_deblockingFilterBetaOffsetDiv2; } + void setDeblockingFilterTcOffsetDiv2( int i ) { m_deblockingFilterTcOffsetDiv2 = i; } + int getDeblockingFilterTcOffsetDiv2() const { return m_deblockingFilterTcOffsetDiv2; } + void setLmcsEnabledFlag(bool b) { m_lmcsEnabledFlag = b; } + bool getLmcsEnabledFlag() { return m_lmcsEnabledFlag; } + const bool getLmcsEnabledFlag() const { return m_lmcsEnabledFlag; } + void setLmcsAPS(APS* aps) { m_lmcsAps = aps; m_lmcsApsId = (aps) ? aps->getAPSId() : -1; } + APS* getLmcsAPS() const { return m_lmcsAps; } + void setLmcsAPSId(int id) { m_lmcsApsId = id; } + int getLmcsAPSId() const { return m_lmcsApsId; } + void setLmcsChromaResidualScaleFlag(bool b) { m_lmcsChromaResidualScaleFlag = b; } + bool getLmcsChromaResidualScaleFlag() { return m_lmcsChromaResidualScaleFlag; } + const bool getLmcsChromaResidualScaleFlag() const { return m_lmcsChromaResidualScaleFlag; } + void setScalingListAPS( APS* aps ) { m_scalingListAps = aps; m_scalingListApsId = ( aps ) ? aps->getAPSId() : -1; } + APS* getScalingListAPS() const { return m_scalingListAps; } + void setScalingListAPSId( int id ) { m_scalingListApsId = id; } + int getScalingListAPSId() const { return m_scalingListApsId; } + void setScalingListPresentFlag( bool b ) { m_scalingListPresentFlag = b; } + bool getScalingListPresentFlag() { return m_scalingListPresentFlag; } + const bool getScalingListPresentFlag() const { return m_scalingListPresentFlag; } + + unsigned* getMinQTSizes() const { return (unsigned *)m_minQT; } + unsigned* getMaxMTTHierarchyDepths() const { return (unsigned *)m_maxMTTHierarchyDepth; } + unsigned* getMaxBTSizes() const { return (unsigned *)m_maxBTSize; } + unsigned* getMaxTTSizes() const { return (unsigned *)m_maxTTSize; } + + void setMinQTSize(unsigned idx, unsigned minQT) { m_minQT[idx] = minQT; } + void setMaxMTTHierarchyDepth(unsigned idx, unsigned maxMTT) { m_maxMTTHierarchyDepth[idx] = maxMTT; } + void setMaxBTSize(unsigned idx, unsigned maxBT) { m_maxBTSize[idx] = maxBT; } + void setMaxTTSize(unsigned idx, unsigned maxTT) { m_maxTTSize[idx] = maxTT; } + + void setMinQTSizes(unsigned* minQT) { m_minQT[0] = minQT[0]; m_minQT[1] = minQT[1]; m_minQT[2] = minQT[2]; } + void setMaxMTTHierarchyDepths(unsigned* maxMTT) { m_maxMTTHierarchyDepth[0] = maxMTT[0]; m_maxMTTHierarchyDepth[1] = maxMTT[1]; m_maxMTTHierarchyDepth[2] = maxMTT[2]; } + void setMaxBTSizes(unsigned* maxBT) { m_maxBTSize[0] = maxBT[0]; m_maxBTSize[1] = maxBT[1]; m_maxBTSize[2] = maxBT[2]; } + void setMaxTTSizes(unsigned* maxTT) { m_maxTTSize[0] = maxTT[0]; m_maxTTSize[1] = maxTT[1]; m_maxTTSize[2] = maxTT[2]; } + + unsigned getMinQTSize(SliceType slicetype, + ChannelType chType = CHANNEL_TYPE_LUMA) const { return slicetype == I_SLICE ? (chType == CHANNEL_TYPE_LUMA ? m_minQT[0] : m_minQT[2]) : m_minQT[1]; } + unsigned getMaxMTTHierarchyDepth(SliceType slicetype, + ChannelType chType = CHANNEL_TYPE_LUMA) const { return slicetype == I_SLICE ? (chType == CHANNEL_TYPE_LUMA ? m_maxMTTHierarchyDepth[0] : m_maxMTTHierarchyDepth[2]) : m_maxMTTHierarchyDepth[1]; } + unsigned getMaxBTSize(SliceType slicetype, + ChannelType chType = CHANNEL_TYPE_LUMA) const { return slicetype == I_SLICE ? (chType == CHANNEL_TYPE_LUMA ? m_maxBTSize[0] : m_maxBTSize[2]) : m_maxBTSize[1]; } + unsigned getMaxTTSize(SliceType slicetype, + ChannelType chType = CHANNEL_TYPE_LUMA) const { return slicetype == I_SLICE ? (chType == CHANNEL_TYPE_LUMA ? m_maxTTSize[0] : m_maxTTSize[2]) : m_maxTTSize[1]; } + + void setAlfAPSs(std::vector<int> apsIDs) { m_alfApsId.resize(m_numAlfAps); + for (int i = 0; i < m_numAlfAps; i++) + { + m_alfApsId[i] = apsIDs[i]; + } + } + + std::vector<int> getAlfAPSs() const { return m_alfApsId; } + +}; + +#endif /// slice header class class Slice { @@ -1654,8 +1984,10 @@ class Slice private: // Bitstream writing bool m_saoEnabledFlag[MAX_NUM_CHANNEL_TYPE]; +#if !JVET_P1006_PICTURE_HEADER int m_iPPSId; ///< picture parameter set ID bool m_PicOutputFlag; ///< pic_output_flag +#endif int m_iPOC; int m_iLastIDR; int m_iAssociatedIRAP; @@ -1674,7 +2006,9 @@ private: SliceType m_eSliceType; int m_iSliceQp; int m_iSliceQpBase; +#if !JVET_P1006_PICTURE_HEADER bool m_ChromaQpAdjEnabled; +#endif bool m_deblockingFilterDisable; bool m_deblockingFilterOverrideFlag; //< offsets for deblocking filter inherit from PPS int m_deblockingFilterBetaOffsetDiv2; //< beta offset for deblocking filter @@ -1683,8 +2017,10 @@ private: int m_aiNumRefIdx [NUM_REF_PIC_LIST_01]; // for multiple reference of current slice bool m_pendingRasInit; +#if !JVET_P1006_PICTURE_HEADER bool m_depQuantEnabledFlag; bool m_signDataHidingEnabledFlag; +#endif bool m_bCheckLDC; bool m_biDirPred; @@ -1707,19 +2043,26 @@ private: const SPS* m_pcSPS; const PPS* m_pcPPS; Picture* m_pcPic; +#if JVET_P1006_PICTURE_HEADER + const PicHeader* m_pcPicHeader; //!< pointer to picture header structure +#endif bool m_colFromL0Flag; // collocated picture from List0 flag +#if !JVET_P1006_PICTURE_HEADER bool m_noOutputPriorPicsFlag; +#endif bool m_noIncorrectPicOutputFlag; bool m_handleCraAsCvsStartFlag; uint32_t m_colRefIdx; +#if !JVET_P1006_PICTURE_HEADER uint32_t m_maxNumMergeCand; uint32_t m_maxNumAffineMergeCand; uint32_t m_maxNumTriangleCand; uint32_t m_maxNumIBCMergeCand; bool m_disFracMMVD; bool m_disBdofDmvrFlag; +#endif double m_lambdas[MAX_NUM_COMPONENT]; bool m_abEqualRef [NUM_REF_PIC_LIST_01][MAX_NUM_REF][MAX_NUM_REF]; @@ -1749,18 +2092,25 @@ private: bool m_cabacInitFlag; +#if !JVET_P1006_PICTURE_HEADER bool m_jointCbCrSignFlag; - +#endif + +#if !JVET_P1006_PICTURE_HEADER bool m_bLMvdL1Zero; bool m_LFCrossSliceBoundaryFlag; - +#endif + +#if !JVET_P1006_PICTURE_HEADER bool m_enableTMVPFlag; +#endif SliceType m_encCABACTableIdx; // Used to transmit table selection across slices. clock_t m_iProcessingStartTime; double m_dProcessingTime; +#if !JVET_P1006_PICTURE_HEADER bool m_splitConsOverrideFlag; uint32_t m_uiMinQTSize; uint32_t m_uiMaxMTTHierarchyDepth; @@ -1771,8 +2121,11 @@ private: uint32_t m_uiMaxBTSizeIChroma; uint32_t m_uiMaxTTSizeIChroma; uint32_t m_uiMaxBTSize; - +#endif + +#if !JVET_P1006_PICTURE_HEADER int m_recoveryPocCnt; +#endif int m_rpPicOrderCntVal; APS* m_alfApss[ALF_CTB_MAX_NUM_APS]; bool m_tileGroupAlfEnabledFlag[MAX_NUM_COMPONENT]; @@ -1780,6 +2133,7 @@ private: std::vector<int> m_tileGroupLumaApsId; int m_tileGroupChromaApsId; bool m_disableSATDForRd; +#if !JVET_P1006_PICTURE_HEADER int m_lmcsApsId; APS* m_lmcsAps; bool m_tileGroupLmcsEnabledFlag; @@ -1788,10 +2142,16 @@ private: APS* m_scalingListAps; bool m_tileGroupscalingListPresentFlag; bool m_nonReferencePicFlag; +#endif public: Slice(); virtual ~Slice(); void initSlice(); +#if JVET_P1006_PICTURE_HEADER + void inheritFromPicHeader( PicHeader *picHeader, const PPS *pps, const SPS *sps ); + void setPicHeader( const PicHeader* pcPicHeader ) { m_pcPicHeader = pcPicHeader; } + const PicHeader* getPicHeader() const { return m_pcPicHeader; } +#endif int getRefIdx4MVPair( RefPicList eCurRefPicList, int nCurRefIdx ); void setDPS( DPS* dps ) { m_dps = dps; } const DPS* getDPS() const { return m_dps; } @@ -1799,13 +2159,20 @@ public: void setSPS( const SPS* pcSPS ) { m_pcSPS = pcSPS; } const SPS* getSPS() const { return m_pcSPS; } +#if JVET_P1006_PICTURE_HEADER + void setPPS( const PPS* pcPPS ) { m_pcPPS = pcPPS; } +#else void setPPS( const PPS* pcPPS ) { m_pcPPS = pcPPS; m_iPPSId = (pcPPS) ? pcPPS->getPPSId() : -1; } +#endif const PPS* getPPS() const { return m_pcPPS; } +#if !JVET_P1006_PICTURE_HEADER void setPPSId( int PPSId ) { m_iPPSId = PPSId; } int getPPSId() const { return m_iPPSId; } +#endif void setAlfAPSs(APS** apss) { memcpy(m_alfApss, apss, sizeof(m_alfApss)); } APS** getAlfAPSs() { return m_alfApss; } +#if !JVET_P1006_PICTURE_HEADER void setLmcsAPS(APS* lmcsAps) { m_lmcsAps = lmcsAps; m_lmcsApsId = (lmcsAps) ? lmcsAps->getAPSId() : -1; } APS* getLmcsAPS() { return m_lmcsAps; } void setLmcsAPSId(int lmcsApsId) { m_lmcsApsId = lmcsApsId; } @@ -1825,6 +2192,7 @@ public: const bool getscalingListPresentFlag() const { return m_tileGroupscalingListPresentFlag; } void setPicOutputFlag( bool b ) { m_PicOutputFlag = b; } bool getPicOutputFlag() const { return m_PicOutputFlag; } +#endif void setSaoEnabledFlag(ChannelType chType, bool s) {m_saoEnabledFlag[chType] =s; } bool getSaoEnabledFlag(ChannelType chType) const { return m_saoEnabledFlag[chType]; } void setRPL0(const ReferencePictureList *pcRPL) { m_pRPL0 = pcRPL; } @@ -1849,7 +2217,9 @@ public: bool getUseWeightedPrediction() const { return( (m_eSliceType==P_SLICE && testWeightPred()) || (m_eSliceType==B_SLICE && testWeightBiPred()) ); } int getSliceQpDelta() const { return m_iSliceQpDelta; } int getSliceChromaQpDelta(ComponentID compID) const { return isLuma(compID) ? 0 : m_iSliceChromaQpDelta[compID]; } +#if !JVET_P1006_PICTURE_HEADER bool getUseChromaQpAdj() const { return m_ChromaQpAdjEnabled; } +#endif bool getDeblockingFilterDisable() const { return m_deblockingFilterDisable; } bool getDeblockingFilterOverrideFlag() const { return m_deblockingFilterOverrideFlag; } int getDeblockingFilterBetaOffsetDiv2()const { return m_deblockingFilterBetaOffsetDiv2; } @@ -1869,7 +2239,9 @@ public: bool getIsUsedAsLongTerm(int i, int j) const { return m_bIsUsedAsLongTerm[i][j]; } void setIsUsedAsLongTerm(int i, int j, bool value) { m_bIsUsedAsLongTerm[i][j] = value; } bool getCheckLDC() const { return m_bCheckLDC; } +#if !JVET_P1006_PICTURE_HEADER bool getMvdL1ZeroFlag() const { return m_bLMvdL1Zero; } +#endif int getList1IdxToList0Idx( int list1Idx ) const { return m_list1IdxToList0Idx[list1Idx]; } void setPOC( int i ) { m_iPOC = i; } void setNalUnitType( NalUnitType e ) { m_eNalUnitType = e; } @@ -1887,7 +2259,9 @@ public: void setSliceQp( int i ) { m_iSliceQp = i; } void setSliceQpDelta( int i ) { m_iSliceQpDelta = i; } void setSliceChromaQpDelta( ComponentID compID, int i ) { m_iSliceChromaQpDelta[compID] = isLuma(compID) ? 0 : i; } +#if !JVET_P1006_PICTURE_HEADER void setUseChromaQpAdj( bool b ) { m_ChromaQpAdjEnabled = b; } +#endif void setDeblockingFilterDisable( bool b ) { m_deblockingFilterDisable= b; } void setDeblockingFilterOverrideFlag( bool b ) { m_deblockingFilterOverrideFlag = b; } void setDeblockingFilterBetaOffsetDiv2( int i ) { m_deblockingFilterBetaOffsetDiv2 = i; } @@ -1903,7 +2277,9 @@ public: void setColFromL0Flag( bool colFromL0 ) { m_colFromL0Flag = colFromL0; } void setColRefIdx( uint32_t refIdx) { m_colRefIdx = refIdx; } void setCheckLDC( bool b ) { m_bCheckLDC = b; } +#if !JVET_P1006_PICTURE_HEADER void setMvdL1ZeroFlag( bool b) { m_bLMvdL1Zero = b; } +#endif void setBiDirPred( bool b, int refIdx0, int refIdx1 ) { m_biDirPred = b; m_symRefIdx[0] = refIdx0; m_symRefIdx[1] = refIdx1; } bool getBiDirPred() const { return m_biDirPred; } @@ -1929,6 +2305,7 @@ public: void setLambdas( const double lambdas[MAX_NUM_COMPONENT] ) { for (int component = 0; component < MAX_NUM_COMPONENT; component++) m_lambdas[component] = lambdas[component]; } const double* getLambdas() const { return m_lambdas; } +#if !JVET_P1006_PICTURE_HEADER void setSplitConsOverrideFlag(bool b) { m_splitConsOverrideFlag = b; } bool getSplitConsOverrideFlag() const { return m_splitConsOverrideFlag; } void setMinQTSize(int i) { m_uiMinQTSize = i; } @@ -1953,7 +2330,12 @@ public: bool getDepQuantEnabledFlag() const { return m_depQuantEnabledFlag; } void setSignDataHidingEnabledFlag( bool b ) { m_signDataHidingEnabledFlag = b; } bool getSignDataHidingEnabledFlag() const { return m_signDataHidingEnabledFlag; } +#endif +#if JVET_P1006_PICTURE_HEADER + uint32_t getCuQpDeltaSubdiv() const { return this->isIntra() ? m_pcPicHeader->getCuQpDeltaSubdivIntra() : m_pcPicHeader->getCuQpDeltaSubdivInter(); } + uint32_t getCuChromaQpOffsetSubdiv() const { return this->isIntra() ? m_pcPicHeader->getCuChromaQpOffsetSubdivIntra() : m_pcPicHeader->getCuChromaQpOffsetSubdivInter(); } +#endif void initEqualRef(); bool isEqualRef( RefPicList e, int iRefIdx1, int iRefIdx2 ) { @@ -1987,6 +2369,7 @@ public: bool isStepwiseTemporalLayerSwitchingPointCandidate( PicList& rcListPic ) const; int checkThatAllRefPicsAreAvailable(PicList& rcListPic, const ReferencePictureList *pRPL, int rplIdx, bool printErrors) const; void createExplicitReferencePictureSetFromReference(PicList& rcListPic, const ReferencePictureList *pRPL0, const ReferencePictureList *pRPL1); +#if !JVET_P1006_PICTURE_HEADER void setMaxNumMergeCand(uint32_t val ) { m_maxNumMergeCand = val; } uint32_t getMaxNumMergeCand() const { return m_maxNumMergeCand; } void setMaxNumAffineMergeCand( uint32_t val ) { m_maxNumAffineMergeCand = val; } @@ -2001,7 +2384,7 @@ public: bool getDisBdofDmvrFlag() const { return m_disBdofDmvrFlag; } void setNoOutputPriorPicsFlag( bool val ) { m_noOutputPriorPicsFlag = val; } bool getNoOutputPriorPicsFlag() const { return m_noOutputPriorPicsFlag; } - +#endif void setNoIncorrectPicOutputFlag(bool val) { m_noIncorrectPicOutputFlag = val; } bool getNoIncorrectPicOutputFlag() const { return m_noIncorrectPicOutputFlag; } @@ -2058,6 +2441,7 @@ public: void setCabacInitFlag( bool val ) { m_cabacInitFlag = val; } //!< set CABAC initial flag bool getCabacInitFlag() const { return m_cabacInitFlag; } //!< get CABAC initial flag +#if !JVET_P1006_PICTURE_HEADER void setJointCbCrSignFlag( bool b ) { m_jointCbCrSignFlag = b; } bool getJointCbCrSignFlag() const { return m_jointCbCrSignFlag; } @@ -2066,7 +2450,7 @@ public: void setEnableTMVPFlag( bool b ) { m_enableTMVPFlag = b; } bool getEnableTMVPFlag() const { return m_enableTMVPFlag; } - +#endif void setEncCABACTableIdx( SliceType idx ) { m_encCABACTableIdx = idx; } SliceType getEncCABACTableIdx() const { return m_encCABACTableIdx; } @@ -2102,16 +2486,22 @@ public: } void setDisableSATDForRD(bool b) { m_disableSATDForRd = b; } bool getDisableSATDForRD() { return m_disableSATDForRd; } +#if JVET_P1006_PICTURE_HEADER + void scaleRefPicList( Picture *scaledRefPic[ ], PicHeader *picHeader, APS** apss, APS* lmcsAps, APS* scalingListAps, const bool isDecoder ); +#else void scaleRefPicList( Picture *scaledRefPic[ ], APS** apss, APS* lmcsAps, APS* scalingListAps, const bool isDecoder ); +#endif void freeScaledRefPicList( Picture *scaledRefPic[] ); bool checkRPR(); const std::pair<int, int>& getScalingRatio( const RefPicList refPicList, const int refIdx ) const { return m_scalingRatio[refPicList][refIdx]; } +#if !JVET_P1006_PICTURE_HEADER void setRecoveryPocCnt(int value) { m_recoveryPocCnt = value; } int getRecoveryPocCnt() const { return m_recoveryPocCnt; } void setRpPicOrderCntVal(int value) { m_rpPicOrderCntVal = value; } int getRpPicOrderCntVal() const { return m_rpPicOrderCntVal; } void setNonRefPictFlag(bool value) { m_nonReferencePicFlag = value; } bool getNonRefPictFlag() const { return m_nonReferencePicFlag; } +#endif protected: #if JVET_N0278_FIXES @@ -2451,6 +2841,9 @@ void xTraceDPSHeader(); void xTraceSPSHeader(); void xTracePPSHeader(); void xTraceAPSHeader(); +#if JVET_P1006_PICTURE_HEADER +void xTracePictureHeader(); +#endif void xTraceSliceHeader(); void xTraceAccessUnitDelimiter(); #endif diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h index a9ae67945..ff2d0db3b 100644 --- a/source/Lib/CommonLib/TypeDef.h +++ b/source/Lib/CommonLib/TypeDef.h @@ -50,6 +50,8 @@ #include <assert.h> #include <cassert> +#define JVET_P1006_PICTURE_HEADER 1 // JVET-P1006: Add picture header and related syntax changes + #define JVET_P0365_SCALING_MATRIX_LFNST 1 // JVET-P0365: Signal flag to indicate whether scaling matrices are used for LFNST-coded blocks #define JVET_P0243_SINGLE_BIT_DEPTH 1 // JVET-P0243: Single bitdepth for luma and chroma diff --git a/source/Lib/CommonLib/UnitPartitioner.cpp b/source/Lib/CommonLib/UnitPartitioner.cpp index 68bf1fda1..7714d436e 100644 --- a/source/Lib/CommonLib/UnitPartitioner.cpp +++ b/source/Lib/CommonLib/UnitPartitioner.cpp @@ -348,8 +348,13 @@ void QTBTPartitioner::splitCurrArea( const PartSplit split, const CodingStructur currQtDepth++; currSubdiv++; } +#if JVET_P1006_PICTURE_HEADER + qgEnable &= (currSubdiv <= cs.slice->getCuQpDeltaSubdiv()); + qgChromaEnable &= (currSubdiv <= cs.slice->getCuChromaQpOffsetSubdiv()); +#else qgEnable &= (currSubdiv <= cs.pps->getCuQpDeltaSubdiv()); qgChromaEnable &= (currSubdiv <= cs.pps->getCuChromaQpOffsetSubdiv()); +#endif m_partStack.back().qgEnable = qgEnable; m_partStack.back().qgChromaEnable = qgChromaEnable; if (qgEnable) diff --git a/source/Lib/CommonLib/UnitTools.cpp b/source/Lib/CommonLib/UnitTools.cpp index 9b8d09b8a..cfd51e71e 100644 --- a/source/Lib/CommonLib/UnitTools.cpp +++ b/source/Lib/CommonLib/UnitTools.cpp @@ -726,7 +726,11 @@ void PU::getIBCMergeCandidates(const PredictionUnit &pu, MergeCtx& mrgCtx, const { const CodingStructure &cs = *pu.cs; const Slice &slice = *pu.cs->slice; +#if JVET_P1006_PICTURE_HEADER + const uint32_t maxNumMergeCand = slice.getPicHeader()->getMaxNumIBCMergeCand(); +#else const uint32_t maxNumMergeCand = slice.getMaxNumIBCMergeCand(); +#endif const bool canFastExit = pu.cs->pps->getLog2ParallelMergeLevelMinus2() == 0; for (uint32_t ui = 0; ui < maxNumMergeCand; ++ui) @@ -859,7 +863,11 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx, { const CodingStructure &cs = *pu.cs; const Slice &slice = *pu.cs->slice; +#if JVET_P1006_PICTURE_HEADER + const uint32_t maxNumMergeCand = slice.getPicHeader()->getMaxNumMergeCand(); +#else const uint32_t maxNumMergeCand = slice.getMaxNumMergeCand(); +#endif const bool canFastExit = pu.cs->pps->getLog2ParallelMergeLevelMinus2() == 0; @@ -1142,7 +1150,11 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx, return; } +#if JVET_P1006_PICTURE_HEADER + if (slice.getPicHeader()->getEnableTMVPFlag() && (pu.lumaSize().width + pu.lumaSize().height > 12)) +#else if (slice.getEnableTMVPFlag() && (pu.lumaSize().width + pu.lumaSize().height > 12)) +#endif { //>> MTK colocated-RightBottom // offset the pos to be sure to "point" to the same position the uiAbsPartIdx would've pointed to @@ -1347,7 +1359,11 @@ bool PU::checkDMVRCondition(const PredictionUnit& pu) int refIdx1 = pu.refIdx[REF_PIC_LIST_1]; pu.cu->slice->getWpScaling(REF_PIC_LIST_0, refIdx0, wp0); pu.cu->slice->getWpScaling(REF_PIC_LIST_1, refIdx1, wp1); +#if JVET_P1006_PICTURE_HEADER + if (pu.cs->sps->getUseDMVR() && (!pu.cs->picHeader->getDisBdofDmvrFlag())) +#else if (pu.cs->sps->getUseDMVR() && (!pu.cs->slice->getDisBdofDmvrFlag())) +#endif { return pu.mergeFlag && pu.mergeType == MRG_TYPE_DEFAULT_N @@ -1830,7 +1846,11 @@ void PU::fillMvpCand(PredictionUnit &pu, const RefPicList &eRefPicList, const in } } +#if JVET_P1006_PICTURE_HEADER + if (cs.picHeader->getEnableTMVPFlag() && pInfo->numCand < AMVP_MAX_NUM_CANDS && (pu.lumaSize().width + pu.lumaSize().height > 12)) +#else if (cs.slice->getEnableTMVPFlag() && pInfo->numCand < AMVP_MAX_NUM_CANDS && (pu.lumaSize().width + pu.lumaSize().height > 12)) +#endif { // Get Temporal Motion Predictor const int refIdx_Col = refIdx; @@ -2147,7 +2167,11 @@ void PU::fillAffineMvpCand(PredictionUnit &pu, const RefPicList &eRefPicList, co } // Get Temporal Motion Predictor +#if JVET_P1006_PICTURE_HEADER + if ( affiAMVPInfo.numCand < 2 && pu.cs->picHeader->getEnableTMVPFlag() ) +#else if ( affiAMVPInfo.numCand < 2 && pu.cs->slice->getEnableTMVPFlag() ) +#endif { const int refIdxCol = refIdx; @@ -2513,7 +2537,11 @@ void PU::getAffineMergeCand( const PredictionUnit &pu, AffineMergeCtx& affMrgCtx { const CodingStructure &cs = *pu.cs; const Slice &slice = *pu.cs->slice; +#if JVET_P1006_PICTURE_HEADER + const uint32_t maxNumAffineMergeCand = slice.getPicHeader()->getMaxNumAffineMergeCand(); +#else const uint32_t maxNumAffineMergeCand = slice.getMaxNumAffineMergeCand(); +#endif for ( int i = 0; i < maxNumAffineMergeCand; i++ ) { @@ -2533,7 +2561,11 @@ void PU::getAffineMergeCand( const PredictionUnit &pu, AffineMergeCtx& affMrgCtx bool enableSubPuMvp = slice.getSPS()->getSBTMVPEnabledFlag() && !(slice.getPOC() == slice.getRefPic(REF_PIC_LIST_0, 0)->getPOC() && slice.isIRAP()); bool isAvailableSubPu = false; +#if JVET_P1006_PICTURE_HEADER + if ( enableSubPuMvp && slice.getPicHeader()->getEnableTMVPFlag() ) +#else if ( enableSubPuMvp && slice.getEnableTMVPFlag() ) +#endif { MergeCtx mrgCtx = *affMrgCtx.mrgCtx; bool tmpLICFlag = false; @@ -2702,7 +2734,11 @@ void PU::getAffineMergeCand( const PredictionUnit &pu, AffineMergeCtx& affMrgCtx } // control point: RB +#if JVET_P1006_PICTURE_HEADER + if ( slice.getPicHeader()->getEnableTMVPFlag() ) +#else if ( slice.getEnableTMVPFlag() ) +#endif { //>> MTK colocated-RightBottom // offset the pos to be sure to "point" to the same position the uiAbsPartIdx would've pointed to @@ -3181,7 +3217,11 @@ void PU::applyImv( PredictionUnit& pu, MergeCtx &mrgCtx, InterPrediction *interP if (pu.interDir != 1 /* PRED_L0 */) { +#if JVET_P1006_PICTURE_HEADER + if( !( pu.cu->cs->picHeader->getMvdL1ZeroFlag() && pu.interDir == 3 ) && pu.cu->imv )/* PRED_BI */ +#else if( !( pu.cu->cs->slice->getMvdL1ZeroFlag() && pu.interDir == 3 ) && pu.cu->imv )/* PRED_BI */ +#endif { pu.mvd[1].changeTransPrecAmvr2Internal(pu.cu->imv); } @@ -3270,7 +3310,11 @@ void PU::getTriangleMergeCandidates( const PredictionUnit &pu, MergeCtx& triangl MergeCtx tmpMergeCtx; const Slice &slice = *pu.cs->slice; +#if JVET_P1006_PICTURE_HEADER + const uint32_t maxNumMergeCand = slice.getPicHeader()->getMaxNumMergeCand(); +#else const uint32_t maxNumMergeCand = slice.getMaxNumMergeCand(); +#endif triangleMrgCtx.numValidMergeCand = 0; @@ -3437,7 +3481,11 @@ bool CU::hasSubCUNonZeroMVd( const CodingUnit& cu ) } if( pu.interDir != 1 /* PRED_L0 */ ) { +#if JVET_P1006_PICTURE_HEADER + if( !pu.cu->cs->picHeader->getMvdL1ZeroFlag() || pu.interDir != 3 /* PRED_BI */ ) +#else if( !pu.cu->cs->slice->getMvdL1ZeroFlag() || pu.interDir != 3 /* PRED_BI */ ) +#endif { bNonZeroMvd |= pu.mvd[REF_PIC_LIST_1].getHor() != 0; bNonZeroMvd |= pu.mvd[REF_PIC_LIST_1].getVer() != 0; @@ -3473,7 +3521,11 @@ bool CU::hasSubCUNonZeroAffineMVd( const CodingUnit& cu ) if ( pu.interDir != 1 /* PRED_L0 */ ) { +#if JVET_P1006_PICTURE_HEADER + if ( !pu.cu->cs->picHeader->getMvdL1ZeroFlag() || pu.interDir != 3 /* PRED_BI */ ) +#else if ( !pu.cu->cs->slice->getMvdL1ZeroFlag() || pu.interDir != 3 /* PRED_BI */ ) +#endif { for ( int i = 0; i < ( cu.affineType == AFFINEMODEL_6PARAM ? 3 : 2 ); i++ ) { @@ -3867,7 +3919,11 @@ int TU::getICTMode( const TransformUnit& tu, int jointCbCr ) { jointCbCr = tu.jointCbCr; } +#if JVET_P1006_PICTURE_HEADER + return g_ictModes[ tu.cs->picHeader->getJointCbCrSignFlag() ][ jointCbCr ]; +#else return g_ictModes[ tu.cs->slice->getJointCbCrSignFlag() ][ jointCbCr ]; +#endif } bool TU::hasCrossCompPredInfo( const TransformUnit &tu, const ComponentID &compID ) diff --git a/source/Lib/DecoderLib/CABACReader.cpp b/source/Lib/DecoderLib/CABACReader.cpp index 265930594..3c22783a1 100644 --- a/source/Lib/DecoderLib/CABACReader.cpp +++ b/source/Lib/DecoderLib/CABACReader.cpp @@ -454,7 +454,11 @@ bool CABACReader::coding_tree( CodingStructure& cs, Partitioner& partitioner, CU cuCtx.qgStart = true; cuCtx.isDQPCoded = false; } +#if JVET_P1006_PICTURE_HEADER + if( pps.getCuChromaQpOffsetEnabledFlag() && partitioner.currQgChromaEnable() ) +#else if( cs.slice->getUseChromaQpAdj() && partitioner.currQgChromaEnable() ) +#endif { cuCtx.isChromaQpAdjCoded = false; } @@ -467,7 +471,11 @@ bool CABACReader::coding_tree( CodingStructure& cs, Partitioner& partitioner, CU pCuCtxChroma->qgStart = true; pCuCtxChroma->isDQPCoded = false; } +#if JVET_P1006_PICTURE_HEADER + if (pps.getCuChromaQpOffsetEnabledFlag() && pPartitionerChroma->currQgChromaEnable()) +#else if (cs.slice->getUseChromaQpAdj() && pPartitionerChroma->currQgChromaEnable()) +#endif { pCuCtxChroma->isChromaQpAdjCoded = false; } @@ -1752,7 +1760,11 @@ void CABACReader::cu_palette_info(CodingUnit& cu, ComponentID compBegin, uint32_ cuCtx.isDQPCoded = true; } } +#if JVET_P1006_PICTURE_HEADER + if (cu.useEscape[compBegin] && cu.cs->pps->getCuChromaQpOffsetEnabledFlag() && !cuCtx.isChromaQpAdjCoded) +#else if (cu.useEscape[compBegin] && cu.cs->slice->getUseChromaQpAdj() && !cuCtx.isChromaQpAdjCoded) +#endif { if (!cu.isSepTree() || isChroma(tu.chType)) { @@ -2295,7 +2307,11 @@ void CABACReader::prediction_unit( PredictionUnit& pu, MergeCtx& mrgCtx ) pu.cu->affine = false; pu.refIdx[REF_PIC_LIST_0] = MAX_NUM_REF; mvd_coding(pu.mvd[REF_PIC_LIST_0]); +#if JVET_P1006_PICTURE_HEADER + if ( pu.cu->slice->getPicHeader()->getMaxNumIBCMergeCand() == 1 ) +#else if ( pu.cu->slice->getMaxNumIBCMergeCand() == 1 ) +#endif { pu.mvpIdx[REF_PIC_LIST_0] = 0; } @@ -2332,7 +2348,11 @@ void CABACReader::prediction_unit( PredictionUnit& pu, MergeCtx& mrgCtx ) if ( pu.cu->smvdMode != 1 ) { ref_idx ( pu, REF_PIC_LIST_1 ); +#if JVET_P1006_PICTURE_HEADER + if( pu.cu->cs->picHeader->getMvdL1ZeroFlag() && pu.interDir == 3 /* PRED_BI */ ) +#else if( pu.cu->cs->slice->getMvdL1ZeroFlag() && pu.interDir == 3 /* PRED_BI */ ) +#endif { pu.mvd[ REF_PIC_LIST_1 ] = Mv(); pu.mvdAffi[REF_PIC_LIST_1][0] = Mv(); @@ -2399,7 +2419,11 @@ void CABACReader::subblock_merge_flag( CodingUnit& cu ) { cu.affine = false; +#if JVET_P1006_PICTURE_HEADER + if ( !cu.cs->slice->isIntra() && (cu.slice->getPicHeader()->getMaxNumAffineMergeCand() > 0) && cu.lumaSize().width >= 8 && cu.lumaSize().height >= 8 ) +#else if ( !cu.cs->slice->isIntra() && (cu.slice->getMaxNumAffineMergeCand() > 0) && cu.lumaSize().width >= 8 && cu.lumaSize().height >= 8 ) +#endif { RExt__DECODER_DEBUG_BIT_STATISTICS_CREATE_SET( STATS__CABAC_BITS__AFFINE_FLAG ); @@ -2468,7 +2492,11 @@ void CABACReader::merge_data( PredictionUnit& pu ) } RExt__DECODER_DEBUG_BIT_STATISTICS_CREATE_SET( STATS__CABAC_BITS__MERGE_FLAG ); +#if JVET_P1006_PICTURE_HEADER + const bool triangleAvailable = pu.cu->cs->slice->getSPS()->getUseTriangle() && pu.cu->cs->slice->isInterB() && pu.cu->cs->picHeader->getMaxNumTriangleCand() > 1; +#else const bool triangleAvailable = pu.cu->cs->slice->getSPS()->getUseTriangle() && pu.cu->cs->slice->isInterB() && pu.cu->cs->slice->getMaxNumTriangleCand() > 1; +#endif const bool ciipAvailable = pu.cs->sps->getUseMHIntra() && !pu.cu->skip && pu.cu->lwidth() < MAX_CU_SIZE && pu.cu->lheight() < MAX_CU_SIZE; if (pu.cu->lwidth() * pu.cu->lheight() >= 64 && (triangleAvailable || ciipAvailable)) @@ -2538,7 +2566,11 @@ void CABACReader::merge_idx( PredictionUnit& pu ) if ( pu.cu->affine ) { +#if JVET_P1006_PICTURE_HEADER + int numCandminus1 = int( pu.cs->picHeader->getMaxNumAffineMergeCand() ) - 1; +#else int numCandminus1 = int( pu.cs->slice->getMaxNumAffineMergeCand() ) - 1; +#endif pu.mergeIdx = 0; if ( numCandminus1 > 0 ) { @@ -2558,7 +2590,11 @@ void CABACReader::merge_idx( PredictionUnit& pu ) } else { +#if JVET_P1006_PICTURE_HEADER + int numCandminus1 = int( pu.cs->picHeader->getMaxNumMergeCand() ) - 1; +#else int numCandminus1 = int( pu.cs->slice->getMaxNumMergeCand() ) - 1; +#endif pu.mergeIdx = 0; if( pu.cu->triangle ) @@ -2585,7 +2621,11 @@ void CABACReader::merge_idx( PredictionUnit& pu ) } return decIdx; }; +#if JVET_P1006_PICTURE_HEADER + const int maxNumTriangleCand = pu.cs->picHeader->getMaxNumTriangleCand(); +#else const int maxNumTriangleCand = pu.cs->slice->getMaxNumTriangleCand(); +#endif CHECK(maxNumTriangleCand < 2, "Incorrect max number of triangle candidates"); candIdx0 = decodeOneIdx(maxNumTriangleCand - 1); candIdx1 = decodeOneIdx(maxNumTriangleCand - 2); @@ -2601,7 +2641,11 @@ void CABACReader::merge_idx( PredictionUnit& pu ) if (pu.cu->predMode == MODE_IBC) { +#if JVET_P1006_PICTURE_HEADER + numCandminus1 = int(pu.cs->picHeader->getMaxNumIBCMergeCand()) - 1; +#else numCandminus1 = int(pu.cs->slice->getMaxNumIBCMergeCand()) - 1; +#endif } if( numCandminus1 > 0 ) { @@ -2626,7 +2670,11 @@ void CABACReader::mmvd_merge_idx(PredictionUnit& pu) RExt__DECODER_DEBUG_BIT_STATISTICS_CREATE_SET(STATS__CABAC_BITS__MERGE_INDEX); int var0 = 0; +#if JVET_P1006_PICTURE_HEADER + if (pu.cs->picHeader->getMaxNumMergeCand() > 1) +#else if (pu.cs->slice->getMaxNumMergeCand() > 1) +#endif { static_assert(MMVD_BASE_MV_NUM == 2, ""); var0 = m_BinDecoder.decodeBin(Ctx::MmvdMergeIdx()); @@ -3081,7 +3129,11 @@ void CABACReader::transform_unit( TransformUnit& tu, CUCtx& cuCtx, Partitioner& SizeType channelWidth = !cu.isSepTree() ? cu.lwidth() : cu.chromaSize().width; SizeType channelHeight = !cu.isSepTree() ? cu.lheight() : cu.chromaSize().height; +#if JVET_P1006_PICTURE_HEADER + if (cu.cs->pps->getCuChromaQpOffsetEnabledFlag() && (channelWidth > 64 || channelHeight > 64 || cbfChroma) && !cuCtx.isChromaQpAdjCoded) +#else if (cu.cs->slice->getUseChromaQpAdj() && (channelWidth > 64 || channelHeight > 64 || cbfChroma) && !cuCtx.isChromaQpAdjCoded) +#endif { cu_chroma_qp_offset(cu); cuCtx.isChromaQpAdjCoded = true; @@ -3223,7 +3275,11 @@ void CABACReader::residual_coding( TransformUnit& tu, ComponentID compID, CUCtx& } // determine sign hiding +#if JVET_P1006_PICTURE_HEADER + bool signHiding = ( cu.cs->picHeader->getSignDataHidingEnabledFlag() && !cu.transQuantBypass && tu.rdpcm[compID] == RDPCM_OFF ); +#else bool signHiding = ( cu.cs->slice->getSignDataHidingEnabledFlag() && !cu.transQuantBypass && tu.rdpcm[compID] == RDPCM_OFF ); +#endif #if JVET_P0058_CHROMA_TS if( signHiding && CU::isIntra(cu) && CU::isRDPCMEnabled(cu) && tu.mtsIdx[compID] == MTS_SKIP ) #else @@ -3270,7 +3326,11 @@ void CABACReader::residual_coding( TransformUnit& tu, ComponentID compID, CUCtx& #endif // parse subblocks +#if JVET_P1006_PICTURE_HEADER + const int stateTransTab = ( tu.cs->picHeader->getDepQuantEnabledFlag() ? 32040 : 0 ); +#else const int stateTransTab = ( tu.cs->slice->getDepQuantEnabledFlag() ? 32040 : 0 ); +#endif int state = 0; int ctxBinSampleRatio = (compID == COMPONENT_Y) ? MAX_TU_LEVEL_CTX_CODED_BIN_CONSTRAINT_LUMA : MAX_TU_LEVEL_CTX_CODED_BIN_CONSTRAINT_CHROMA; diff --git a/source/Lib/DecoderLib/DecCu.cpp b/source/Lib/DecoderLib/DecCu.cpp index 5876716f4..59e452134 100644 --- a/source/Lib/DecoderLib/DecCu.cpp +++ b/source/Lib/DecoderLib/DecCu.cpp @@ -263,8 +263,13 @@ void DecCu::xIntraRecBlk( TransformUnit& tu, const ComponentID compID ) } } const Slice &slice = *cs.slice; +#if JVET_P1006_PICTURE_HEADER + bool flag = slice.getPicHeader()->getLmcsEnabledFlag() && (slice.isIntra() || (!slice.isIntra() && m_pcReshape->getCTUFlag())); + if (flag && slice.getPicHeader()->getLmcsChromaResidualScaleFlag() && (compID != COMPONENT_Y) && (tu.cbf[COMPONENT_Cb] || tu.cbf[COMPONENT_Cr])) +#else bool flag = slice.getLmcsEnabledFlag() && (slice.isIntra() || (!slice.isIntra() && m_pcReshape->getCTUFlag())); if (flag && slice.getLmcsChromaResidualScaleFlag() && (compID != COMPONENT_Y) && (tu.cbf[COMPONENT_Cb] || tu.cbf[COMPONENT_Cr])) +#endif { const Area area = tu.Y().valid() ? tu.Y() : Area(recalcPosition(tu.chromaFormat, tu.chType, CHANNEL_TYPE_LUMA, tu.blocks[tu.chType].pos()), recalcSize(tu.chromaFormat, tu.chType, CHANNEL_TYPE_LUMA, tu.blocks[tu.chType].size())); const CompArea &areaY = CompArea(COMPONENT_Y, tu.chromaFormat, area); @@ -305,7 +310,11 @@ void DecCu::xIntraRecBlk( TransformUnit& tu, const ComponentID compID ) //===== reconstruction ===== flag = flag && (tu.blocks[compID].width*tu.blocks[compID].height > 4); +#if JVET_P1006_PICTURE_HEADER + if (flag && (TU::getCbf(tu, compID) || tu.jointCbCr) && isChroma(compID) && slice.getPicHeader()->getLmcsChromaResidualScaleFlag()) +#else if (flag && (TU::getCbf(tu, compID) || tu.jointCbCr) && isChroma(compID) && slice.getLmcsChromaResidualScaleFlag()) +#endif { piResi.scaleSignal(tu.getChromaAdj(), 0, tu.cu->cs->slice->clpRng(compID)); } @@ -328,7 +337,11 @@ void DecCu::xIntraRecBlk( TransformUnit& tu, const ComponentID compID ) CompArea tmpArea(COMPONENT_Y, area.chromaFormat, Position(0, 0), area.size()); PelBuf tmpPred; #endif +#if JVET_P1006_PICTURE_HEADER + if (slice.getPicHeader()->getLmcsEnabledFlag() && (m_pcReshape->getCTUFlag() || slice.isIntra()) && compID == COMPONENT_Y) +#else if (slice.getLmcsEnabledFlag() && (m_pcReshape->getCTUFlag() || slice.isIntra()) && compID == COMPONENT_Y) +#endif { #if REUSE_CU_RESULTS { @@ -345,7 +358,11 @@ void DecCu::xIntraRecBlk( TransformUnit& tu, const ComponentID compID ) #if !KEEP_PRED_AND_RESI_SIGNALS pReco.copyFrom( piPred ); #endif +#if JVET_P1006_PICTURE_HEADER + if (slice.getPicHeader()->getLmcsEnabledFlag() && (m_pcReshape->getCTUFlag() || slice.isIntra()) && compID == COMPONENT_Y) +#else if (slice.getLmcsEnabledFlag() && (m_pcReshape->getCTUFlag() || slice.isIntra()) && compID == COMPONENT_Y) +#endif { #if REUSE_CU_RESULTS { @@ -571,7 +588,11 @@ void DecCu::xReconInter(CodingUnit &cu) if (cu.firstPU->mhIntraFlag) { +#if JVET_P1006_PICTURE_HEADER + if (cu.cs->picHeader->getLmcsEnabledFlag() && m_pcReshape->getCTUFlag()) +#else if (cu.cs->slice->getLmcsEnabledFlag() && m_pcReshape->getCTUFlag()) +#endif { cu.cs->getPredBuf(*cu.firstPU).Y().rspSignal(m_pcReshape->getFwdLUT()); } @@ -603,7 +624,11 @@ void DecCu::xReconInter(CodingUnit &cu) CompArea tmpArea(COMPONENT_Y, area.chromaFormat, Position(0, 0), area.size()); PelBuf tmpPred; #endif +#if JVET_P1006_PICTURE_HEADER + if (cs.picHeader->getLmcsEnabledFlag() && m_pcReshape->getCTUFlag()) +#else if (cs.slice->getLmcsEnabledFlag() && m_pcReshape->getCTUFlag()) +#endif { #if REUSE_CU_RESULTS if (cs.pcv->isEncoder) @@ -621,7 +646,11 @@ void DecCu::xReconInter(CodingUnit &cu) cs.getResiBuf( cu ).reconstruct( cs.getPredBuf( cu ), cs.getResiBuf( cu ), cs.slice->clpRngs() ); cs.getRecoBuf( cu ).copyFrom ( cs.getResiBuf( cu ) ); #endif +#if JVET_P1006_PICTURE_HEADER + if (cs.picHeader->getLmcsEnabledFlag() && m_pcReshape->getCTUFlag()) +#else if (cs.slice->getLmcsEnabledFlag() && m_pcReshape->getCTUFlag()) +#endif { #if REUSE_CU_RESULTS if (cs.pcv->isEncoder) @@ -634,7 +663,11 @@ void DecCu::xReconInter(CodingUnit &cu) else { cs.getRecoBuf(cu).copyClip(cs.getPredBuf(cu), cs.slice->clpRngs()); +#if JVET_P1006_PICTURE_HEADER + if (cs.picHeader->getLmcsEnabledFlag() && m_pcReshape->getCTUFlag() && !cu.firstPU->mhIntraFlag && !CU::isIBC(cu)) +#else if (cs.slice->getLmcsEnabledFlag() && m_pcReshape->getCTUFlag() && !cu.firstPU->mhIntraFlag && !CU::isIBC(cu)) +#endif { cs.getRecoBuf(cu).get(COMPONENT_Y).rspSignal(m_pcReshape->getFwdLUT()); } @@ -688,8 +721,13 @@ void DecCu::xDecodeInterTU( TransformUnit & currTU, const ComponentID compID ) //===== reconstruction ===== const Slice &slice = *cs.slice; +#if JVET_P1006_PICTURE_HEADER + if (slice.getPicHeader()->getLmcsEnabledFlag() && isChroma(compID) && (TU::getCbf(currTU, compID) || currTU.jointCbCr) + && slice.getPicHeader()->getLmcsChromaResidualScaleFlag() && currTU.blocks[compID].width * currTU.blocks[compID].height > 4) +#else if (slice.getLmcsEnabledFlag() && isChroma(compID) && (TU::getCbf(currTU, compID) || currTU.jointCbCr) && slice.getLmcsChromaResidualScaleFlag() && currTU.blocks[compID].width * currTU.blocks[compID].height > 4) +#endif { resiBuf.scaleSignal(currTU.getChromaAdj(), 0, currTU.cu->cs->slice->clpRng(compID)); } @@ -716,7 +754,11 @@ void DecCu::xDecodeInterTexture(CodingUnit &cu) { CodingStructure &cs = *cu.cs; const Slice &slice = *cs.slice; +#if JVET_P1006_PICTURE_HEADER + if (slice.getPicHeader()->getLmcsEnabledFlag() && slice.getPicHeader()->getLmcsChromaResidualScaleFlag() && (compID == COMPONENT_Y) && (currTU.cbf[COMPONENT_Cb] || currTU.cbf[COMPONENT_Cr])) +#else if (slice.getLmcsEnabledFlag() && slice.getLmcsChromaResidualScaleFlag() && (compID == COMPONENT_Y) && (currTU.cbf[COMPONENT_Cb] || currTU.cbf[COMPONENT_Cr])) +#endif { const CompArea &areaY = currTU.blocks[COMPONENT_Y]; int adj = m_pcReshape->calculateChromaAdjVpduNei(currTU, areaY); @@ -895,7 +937,11 @@ void DecCu::xDeriveCUMV( CodingUnit &cu ) { mvd.changeIbcPrecAmvr2Internal(pu.cu->imv); } +#if JVET_P1006_PICTURE_HEADER + if ( pu.cu->slice->getPicHeader()->getMaxNumIBCMergeCand() == 1 ) +#else if ( pu.cu->slice->getMaxNumIBCMergeCand() == 1 ) +#endif { CHECK( pu.mvpIdx[REF_PIC_LIST_0], "mvpIdx for IBC mode should be 0" ); } diff --git a/source/Lib/DecoderLib/DecLib.cpp b/source/Lib/DecoderLib/DecLib.cpp index 473455a21..ab2ac638d 100644 --- a/source/Lib/DecoderLib/DecLib.cpp +++ b/source/Lib/DecoderLib/DecLib.cpp @@ -615,7 +615,11 @@ void DecLib::finishPictureLight(int& poc, PicList*& rpcListPic ) { Slice* pcSlice = m_pcPic->cs->slice; +#if JVET_P1006_PICTURE_HEADER + m_pcPic->neededForOutput = (pcSlice->getPicHeader()->getPicOutputFlag() ? true : false); +#else m_pcPic->neededForOutput = (pcSlice->getPicOutputFlag() ? true : false); +#endif m_pcPic->reconstructed = true; Slice::sortPicList( m_cListPic ); // sorting for application output @@ -659,7 +663,11 @@ void DecLib::finishPicture(int& poc, PicList*& rpcListPic, MsgLevel msgl ) { const std::pair<int, int>& scaleRatio = pcSlice->getScalingRatio( RefPicList( iRefList ), iRefIndex ); +#if JVET_P1006_PICTURE_HEADER + if( pcSlice->getPicHeader()->getEnableTMVPFlag() && pcSlice->getColFromL0Flag() == bool(1 - iRefList) && pcSlice->getColRefIdx() == iRefIndex ) +#else if( pcSlice->getEnableTMVPFlag() && pcSlice->getColFromL0Flag() == bool(1 - iRefList) && pcSlice->getColRefIdx() == iRefIndex ) +#endif { if ( scaleRatio.first != 1 << SCALE_RATIO_BITS || scaleRatio.second != 1 << SCALE_RATIO_BITS ) msg( msgl, "%dc(%1.2lfx, %1.2lfx) ", pcSlice->getRefPOC( RefPicList( iRefList ), iRefIndex ), double( scaleRatio.first ) / ( 1 << SCALE_RATIO_BITS ), double( scaleRatio.second ) / ( 1 << SCALE_RATIO_BITS ) ); @@ -689,7 +697,11 @@ void DecLib::finishPicture(int& poc, PicList*& rpcListPic, MsgLevel msgl ) msg( msgl, "\n"); +#if JVET_P1006_PICTURE_HEADER + m_pcPic->neededForOutput = (pcSlice->getPicHeader()->getPicOutputFlag() ? true : false); +#else m_pcPic->neededForOutput = (pcSlice->getPicOutputFlag() ? true : false); +#endif m_pcPic->reconstructed = true; @@ -701,6 +713,9 @@ void DecLib::finishPicture(int& poc, PicList*& rpcListPic, MsgLevel msgl ) m_pcPic->destroyTempBuffers(); m_pcPic->cs->destroyCoeffs(); m_pcPic->cs->releaseIntermediateData(); +#if JVET_P1006_PICTURE_HEADER + m_pcPic->cs->picHeader->initPicHeader(); +#endif } void DecLib::checkNoOutputPriorPics (PicList* pcListPic) @@ -815,10 +830,16 @@ void DecLib::xCreateUnavailablePicture(int iUnavailablePoc, bool longTermFlag) cFillPic->referenced = true; cFillPic->longTerm = longTermFlag; cFillPic->slices[0]->setPOC(iUnavailablePoc); +#if !JVET_P1006_PICTURE_HEADER cFillPic->slices[0]->setPicOutputFlag(false); +#endif xUpdatePreviousTid0POC(cFillPic->slices[0]); cFillPic->reconstructed = true; +#if JVET_P1006_PICTURE_HEADER + cFillPic->neededForOutput = false; +#else cFillPic->neededForOutput = true; +#endif if (m_pocRandomAccess == MAX_INT) { m_pocRandomAccess = iUnavailablePoc; @@ -826,7 +847,11 @@ void DecLib::xCreateUnavailablePicture(int iUnavailablePoc, bool longTermFlag) } +#if JVET_P1006_PICTURE_HEADER +void activateAPS(PicHeader* picHeader, Slice* pSlice, ParameterSetManager& parameterSetManager, APS** apss, APS* lmcsAPS, APS* scalingListAPS) +#else void activateAPS(Slice* pSlice, ParameterSetManager& parameterSetManager, APS** apss, APS* lmcsAPS, APS* scalingListAPS) +#endif { //luma APSs if (pSlice->getTileGroupAlfEnabledFlag(COMPONENT_Y)) @@ -867,14 +892,27 @@ void activateAPS(Slice* pSlice, ParameterSetManager& parameterSetManager, APS** } } +#if JVET_P1006_PICTURE_HEADER + if (picHeader->getLmcsEnabledFlag() && lmcsAPS == nullptr) +#else if (pSlice->getLmcsEnabledFlag() && lmcsAPS == nullptr) +#endif { +#if JVET_P1006_PICTURE_HEADER + lmcsAPS = parameterSetManager.getAPS(picHeader->getLmcsAPSId(), LMCS_APS); +#else lmcsAPS = parameterSetManager.getAPS(pSlice->getLmcsAPSId(), LMCS_APS); +#endif CHECK(lmcsAPS == nullptr, "No LMCS APS present"); if (lmcsAPS) { +#if JVET_P1006_PICTURE_HEADER + parameterSetManager.clearAPSChangedFlag(picHeader->getLmcsAPSId(), LMCS_APS); + if (false == parameterSetManager.activateAPS(picHeader->getLmcsAPSId(), LMCS_APS)) +#else parameterSetManager.clearAPSChangedFlag(pSlice->getLmcsAPSId(), LMCS_APS); if (false == parameterSetManager.activateAPS(pSlice->getLmcsAPSId(), LMCS_APS)) +#endif { THROW("LMCS APS activation failed!"); } @@ -883,16 +921,33 @@ void activateAPS(Slice* pSlice, ParameterSetManager& parameterSetManager, APS** //ToDO: APS NAL unit containing the APS RBSP shall have nuh_layer_id either equal to the nuh_layer_id of a coded slice NAL unit that referrs it, or equal to the nuh_layer_id of a direct dependent layer of the layer containing a coded slice NAL unit that referrs it. } } +#if JVET_P1006_PICTURE_HEADER + picHeader->setLmcsAPS(lmcsAPS); +#else pSlice->setLmcsAPS(lmcsAPS); +#endif +#if JVET_P1006_PICTURE_HEADER + if( picHeader->getScalingListPresentFlag() && scalingListAPS == nullptr) +#else if( pSlice->getscalingListPresentFlag() && scalingListAPS == nullptr) +#endif { +#if JVET_P1006_PICTURE_HEADER + scalingListAPS = parameterSetManager.getAPS( picHeader->getScalingListAPSId(), SCALING_LIST_APS ); +#else scalingListAPS = parameterSetManager.getAPS( pSlice->getscalingListAPSId(), SCALING_LIST_APS ); +#endif CHECK( scalingListAPS == nullptr, "No SCALING LIST APS present" ); if( scalingListAPS ) { +#if JVET_P1006_PICTURE_HEADER + parameterSetManager.clearAPSChangedFlag( picHeader->getScalingListAPSId(), SCALING_LIST_APS ); + if( false == parameterSetManager.activateAPS( picHeader->getScalingListAPSId(), SCALING_LIST_APS ) ) +#else parameterSetManager.clearAPSChangedFlag( pSlice->getscalingListAPSId(), SCALING_LIST_APS ); if( false == parameterSetManager.activateAPS( pSlice->getscalingListAPSId(), SCALING_LIST_APS ) ) +#endif { THROW( "SCALING LIST APS activation failed!" ); } @@ -901,7 +956,11 @@ void activateAPS(Slice* pSlice, ParameterSetManager& parameterSetManager, APS** //ToDO: APS NAL unit containing the APS RBSP shall have nuh_layer_id either equal to the nuh_layer_id of a coded slice NAL unit that referrs it, or equal to the nuh_layer_id of a direct dependent layer of the layer containing a coded slice NAL unit that referrs it. } } +#if JVET_P1006_PICTURE_HEADER + picHeader->setScalingListAPS(scalingListAPS); +#else pSlice->setscalingListAPS(scalingListAPS); +#endif } #if JVET_N0278_FIXES @@ -914,7 +973,11 @@ void DecLib::xActivateParameterSets() { APS** apss = m_parameterSetManager.getAPSs(); memset(apss, 0, sizeof(*apss) * ALF_CTB_MAX_NUM_APS); +#if JVET_P1006_PICTURE_HEADER + const PPS *pps = m_parameterSetManager.getPPS(m_picHeader.getPPSId()); // this is a temporary PPS object. Do not store this value +#else const PPS *pps = m_parameterSetManager.getPPS(m_apcSlicePilot->getPPSId()); // this is a temporary PPS object. Do not store this value +#endif CHECK(pps == 0, "No PPS present"); const SPS *sps = m_parameterSetManager.getSPS(pps->getSPSId()); // this is a temporary SPS object. Do not store this value @@ -922,12 +985,20 @@ void DecLib::xActivateParameterSets() if (NULL == pps->pcv) { +#if JVET_P1006_PICTURE_HEADER + m_parameterSetManager.getPPS( m_picHeader.getPPSId() )->pcv = new PreCalcValues( *sps, *pps, false ); +#else m_parameterSetManager.getPPS( m_apcSlicePilot->getPPSId() )->pcv = new PreCalcValues( *sps, *pps, false ); +#endif } m_parameterSetManager.clearSPSChangedFlag(sps->getSPSId()); m_parameterSetManager.clearPPSChangedFlag(pps->getPPSId()); +#if JVET_P1006_PICTURE_HEADER + if (false == m_parameterSetManager.activatePPS(m_picHeader.getPPSId(),m_apcSlicePilot->isIRAP())) +#else if (false == m_parameterSetManager.activatePPS(m_apcSlicePilot->getPPSId(),m_apcSlicePilot->isIRAP())) +#endif { THROW("Parameter set activation failed!"); } @@ -942,7 +1013,11 @@ void DecLib::xActivateParameterSets() } APS* lmcsAPS = nullptr; APS* scalinglistAPS = nullptr; +#if JVET_P1006_PICTURE_HEADER + activateAPS(&m_picHeader, m_apcSlicePilot, m_parameterSetManager, apss, lmcsAPS, scalinglistAPS); +#else activateAPS(m_apcSlicePilot, m_parameterSetManager, apss, lmcsAPS, scalinglistAPS); +#endif xParsePrefixSEImessages(); @@ -961,8 +1036,16 @@ void DecLib::xActivateParameterSets() #endif m_apcSlicePilot->applyReferencePictureListBasedMarking(m_cListPic, m_apcSlicePilot->getRPL0(), m_apcSlicePilot->getRPL1()); +#if JVET_P1006_PICTURE_HEADER + m_pcPic->finalInit( *sps, *pps, &m_picHeader, apss, lmcsAPS, scalinglistAPS ); +#else m_pcPic->finalInit( *sps, *pps, apss, lmcsAPS, scalinglistAPS ); +#endif +#if JVET_P1006_PICTURE_HEADER + m_parameterSetManager.getPPS(m_picHeader.getPPSId())->setNumBricksInPic((int)m_pcPic->brickMap->bricks.size()); +#else m_parameterSetManager.getPPS(m_apcSlicePilot->getPPSId())->setNumBricksInPic((int)m_pcPic->brickMap->bricks.size()); +#endif m_pcPic->createTempBuffers( m_pcPic->cs->pps->pcv->maxCUWidth ); m_pcPic->cs->createCoeffs(); @@ -1052,8 +1135,13 @@ void DecLib::xActivateParameterSets() const SPS *sps = pSlice->getSPS(); const PPS *pps = pSlice->getPPS(); APS** apss = pSlice->getAlfAPSs(); +#if JVET_P1006_PICTURE_HEADER + APS *lmcsAPS = m_picHeader.getLmcsAPS(); + APS *scalinglistAPS = m_picHeader.getScalingListAPS(); +#else APS *lmcsAPS = pSlice->getLmcsAPS(); APS *scalinglistAPS = pSlice->getscalingListAPS(); +#endif // fix Parameter Sets, now that we have the real slice m_pcPic->cs->slice = pSlice; @@ -1092,7 +1180,11 @@ void DecLib::xActivateParameterSets() EXIT( "Error - a new SCALING LIST APS has been decoded while processing a picture" ); } +#if JVET_P1006_PICTURE_HEADER + activateAPS(&m_picHeader, pSlice, m_parameterSetManager, apss, lmcsAPS, scalinglistAPS); +#else activateAPS(pSlice, m_parameterSetManager, apss, lmcsAPS, scalinglistAPS); +#endif m_pcPic->cs->lmcsAps = lmcsAPS; m_pcPic->cs->scalinglistAps = scalinglistAPS; @@ -1158,9 +1250,23 @@ void DecLib::xParsePrefixSEImessages() } } +#if JVET_P1006_PICTURE_HEADER +void DecLib::xDecodePicHeader( InputNALUnit& nalu ) +{ + m_HLSReader.setBitstream( &nalu.getBitstream() ); + m_HLSReader.parsePictureHeader( &m_picHeader, &m_parameterSetManager); + m_picHeader.setValid(); +} +#endif bool DecLib::xDecodeSlice(InputNALUnit &nalu, int &iSkipFrame, int iPOCLastDisplay ) { +#if JVET_P1006_PICTURE_HEADER + if(m_picHeader.isValid() == false) { + return false; + } + m_apcSlicePilot->setPicHeader( &m_picHeader ); +#endif m_apcSlicePilot->initSlice(); // the slice pilot is an object to prepare for a new slice // it is not associated with picture, sps or pps structures. @@ -1201,7 +1307,11 @@ bool DecLib::xDecodeSlice(InputNALUnit &nalu, int &iSkipFrame, int iPOCLastDispl CHECK(nalu.m_temporalId != 0, "Current GDR picture has TemporalId not equal to 0"); m_HLSReader.setBitstream( &nalu.getBitstream() ); +#if JVET_P1006_PICTURE_HEADER + m_HLSReader.parseSliceHeader( m_apcSlicePilot, &m_picHeader, &m_parameterSetManager, m_prevTid0POC ); +#else m_HLSReader.parseSliceHeader( m_apcSlicePilot, &m_parameterSetManager, m_prevTid0POC ); +#endif // update independent slice index uint32_t uiIndependentSliceIdx = 0; @@ -1213,7 +1323,11 @@ bool DecLib::xDecodeSlice(InputNALUnit &nalu, int &iSkipFrame, int iPOCLastDispl m_apcSlicePilot->setIndependentSliceIdx(uiIndependentSliceIdx); #if K0149_BLOCK_STATISTICS +#if JVET_P1006_PICTURE_HEADER + PPS *pps = m_parameterSetManager.getPPS(m_picHeader.getPPSId()); +#else PPS *pps = m_parameterSetManager.getPPS(m_apcSlicePilot->getPPSId()); +#endif CHECK(pps == 0, "No PPS present"); SPS *sps = m_parameterSetManager.getSPS(pps->getSPSId()); CHECK(sps == 0, "No SPS present"); @@ -1253,12 +1367,20 @@ bool DecLib::xDecodeSlice(InputNALUnit &nalu, int &iSkipFrame, int iPOCLastDispl { if (m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_CRA || m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_GDR) { +#if JVET_P1006_PICTURE_HEADER + m_picHeader.setNoOutputOfPriorPicsFlag(true); +#else m_apcSlicePilot->setNoOutputPriorPicsFlag(true); +#endif } } else { +#if JVET_P1006_PICTURE_HEADER + m_picHeader.setNoOutputOfPriorPicsFlag(false); +#else m_apcSlicePilot->setNoOutputPriorPicsFlag(false); +#endif } if (m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_CRA || m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_GDR) @@ -1266,7 +1388,11 @@ bool DecLib::xDecodeSlice(InputNALUnit &nalu, int &iSkipFrame, int iPOCLastDispl m_lastNoIncorrectPicOutputFlag = m_apcSlicePilot->getNoIncorrectPicOutputFlag(); } } +#if JVET_P1006_PICTURE_HEADER + if ((m_apcSlicePilot->getRapPicFlag() || m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_GDR) && m_picHeader.getNoOutputOfPriorPicsFlag()) +#else if ((m_apcSlicePilot->getRapPicFlag() || m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_GDR) && m_apcSlicePilot->getNoOutputPriorPicsFlag()) +#endif { m_lastPOCNoOutputPriorPics = m_apcSlicePilot->getPOC(); m_isNoOutputPriorPics = true; @@ -1281,14 +1407,22 @@ bool DecLib::xDecodeSlice(InputNALUnit &nalu, int &iSkipFrame, int iPOCLastDispl { if (m_lastNoIncorrectPicOutputFlag) { +#if JVET_P1006_PICTURE_HEADER + m_picHeader.setPicOutputFlag(false); +#else m_apcSlicePilot->setPicOutputFlag(false); +#endif } } if ((m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_CRA || m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_GDR) && m_lastNoIncorrectPicOutputFlag) //Reset POC MSB when CRA or GDR has NoIncorrectPicOutputFlag equal to 1 { +#if JVET_P1006_PICTURE_HEADER + PPS *pps = m_parameterSetManager.getPPS(m_picHeader.getPPSId()); +#else PPS *pps = m_parameterSetManager.getPPS(m_apcSlicePilot->getPPSId()); +#endif CHECK(pps == 0, "No PPS present"); SPS *sps = m_parameterSetManager.getSPS(pps->getSPSId()); CHECK(sps == 0, "No SPS present"); @@ -1452,7 +1586,11 @@ bool DecLib::xDecodeSlice(InputNALUnit &nalu, int &iSkipFrame, int iPOCLastDispl pcSlice->checkSTSA(m_cListPic); #endif +#if JVET_P1006_PICTURE_HEADER + pcSlice->scaleRefPicList( scaledRefPic, m_pcPic->cs->picHeader, m_parameterSetManager.getAPSs(), m_picHeader.getLmcsAPS(), m_picHeader.getScalingListAPS(), true ); +#else pcSlice->scaleRefPicList( scaledRefPic, m_parameterSetManager.getAPSs(), pcSlice->getLmcsAPS(), pcSlice->getscalingListAPS(), true ); +#endif if (!pcSlice->isIntra()) { @@ -1482,7 +1620,11 @@ bool DecLib::xDecodeSlice(InputNALUnit &nalu, int &iSkipFrame, int iPOCLastDispl } if (pcSlice->getSPS()->getUseSMVD() && pcSlice->getCheckLDC() == false +#if JVET_P1006_PICTURE_HEADER + && pcSlice->getPicHeader()->getMvdL1ZeroFlag() == false +#else && pcSlice->getMvdL1ZeroFlag() == false +#endif ) { int currPOC = pcSlice->getPOC(); @@ -1580,9 +1722,17 @@ bool DecLib::xDecodeSlice(InputNALUnit &nalu, int &iSkipFrame, int iPOCLastDispl if( pcSlice->getSPS()->getScalingListFlag() ) { ScalingList scalingList; +#if JVET_P1006_PICTURE_HEADER + if( pcSlice->getPicHeader()->getScalingListPresentFlag() ) +#else if( pcSlice->getscalingListPresentFlag() ) +#endif { +#if JVET_P1006_PICTURE_HEADER + APS* scalingListAPS = pcSlice->getPicHeader()->getScalingListAPS(); +#else APS* scalingListAPS = pcSlice->getscalingListAPS(); +#endif scalingList = scalingListAPS->getScalingList(); } else @@ -1602,9 +1752,17 @@ bool DecLib::xDecodeSlice(InputNALUnit &nalu, int &iSkipFrame, int iPOCLastDispl { if (m_bFirstSliceInPicture) m_sliceLmcsApsId = -1; +#if JVET_P1006_PICTURE_HEADER + if (pcSlice->getPicHeader()->getLmcsEnabledFlag()) +#else if (pcSlice->getLmcsEnabledFlag()) +#endif { +#if JVET_P1006_PICTURE_HEADER + APS* lmcsAPS = pcSlice->getPicHeader()->getLmcsAPS(); +#else APS* lmcsAPS = pcSlice->getLmcsAPS(); +#endif if (m_sliceLmcsApsId == -1) { m_sliceLmcsApsId = lmcsAPS->getAPSId(); @@ -1622,8 +1780,13 @@ bool DecLib::xDecodeSlice(InputNALUnit &nalu, int &iSkipFrame, int iPOCLastDispl #if JVET_P0371_CHROMA_SCALING_OFFSET tInfo.chrResScalingOffset = sInfo.chrResScalingOffset; #endif +#if JVET_P1006_PICTURE_HEADER + tInfo.setUseSliceReshaper(pcSlice->getPicHeader()->getLmcsEnabledFlag()); + tInfo.setSliceReshapeChromaAdj(pcSlice->getPicHeader()->getLmcsChromaResidualScaleFlag()); +#else tInfo.setUseSliceReshaper(pcSlice->getLmcsEnabledFlag()); tInfo.setSliceReshapeChromaAdj(pcSlice->getLmcsChromaResidualScaleFlag()); +#endif tInfo.setSliceReshapeModelPresentFlag(true); } else @@ -1633,7 +1796,11 @@ bool DecLib::xDecodeSlice(InputNALUnit &nalu, int &iSkipFrame, int iPOCLastDispl tInfo.setSliceReshapeChromaAdj(false); tInfo.setSliceReshapeModelPresentFlag(false); } +#if JVET_P1006_PICTURE_HEADER + if (pcSlice->getPicHeader()->getLmcsEnabledFlag()) +#else if (pcSlice->getLmcsEnabledFlag()) +#endif { m_cReshaper.constructReshaper(); } @@ -1773,6 +1940,13 @@ bool DecLib::decode(InputNALUnit& nalu, int& iSkipFrame, int& iPOCLastDisplay) case NAL_UNIT_PPS: xDecodePPS( nalu ); return false; +#if JVET_P1006_PICTURE_HEADER + + case NAL_UNIT_PH: + xDecodePicHeader(nalu); + return !m_bFirstSliceInPicture; +#endif + #if JVET_P0588_SUFFIX_APS case NAL_UNIT_PREFIX_APS: case NAL_UNIT_SUFFIX_APS: @@ -1831,10 +2005,12 @@ bool DecLib::decode(InputNALUnit& nalu, int& iSkipFrame, int& iPOCLastDisplay) AUDReader audReader; uint32_t picType; audReader.parseAccessUnitDelimiter(&(nalu.getBitstream()),picType); +#if !JVET_P1006_PICTURE_HEADER // vectors clearing shall be moved to the right place if mandatory AUD starting an AU is removed m_accessUnitNals.clear(); m_accessUnitApsNals.clear(); m_accessUnitNals.push_back( std::pair<NalUnitType, int>( NAL_UNIT_ACCESS_UNIT_DELIMITER, nalu.m_temporalId ) ); +#endif return !m_bFirstSliceInPicture; } diff --git a/source/Lib/DecoderLib/DecLib.h b/source/Lib/DecoderLib/DecLib.h index 7e8cc5e0b..32d3a1d42 100644 --- a/source/Lib/DecoderLib/DecLib.h +++ b/source/Lib/DecoderLib/DecLib.h @@ -77,6 +77,9 @@ private: PicList m_cListPic; // Dynamic buffer ParameterSetManager m_parameterSetManager; // storage for parameter sets +#if JVET_P1006_PICTURE_HEADER + PicHeader m_picHeader; // picture header +#endif Slice* m_apcSlicePilot; @@ -173,6 +176,10 @@ public: void setDebugCTU( int debugCTU ) { m_debugCTU = debugCTU; } int getDebugPOC( ) const { return m_debugPOC; }; void setDebugPOC( int debugPOC ) { m_debugPOC = debugPOC; }; +#if JVET_P1006_PICTURE_HEADER + void resetAccessUnitNals() { m_accessUnitNals.clear(); } + void resetAccessUnitApsNals() { m_accessUnitApsNals.clear(); } +#endif #if JVET_N0278_FIXES const VPS* getVPS() { return m_vps; } @@ -192,7 +199,9 @@ protected: void xCreateUnavailablePicture(int iUnavailablePoc, bool longTermFlag); void xActivateParameterSets(); #endif - +#if JVET_P1006_PICTURE_HEADER + void xDecodePicHeader( InputNALUnit& nalu ); +#endif bool xDecodeSlice(InputNALUnit &nalu, int &iSkipFrame, int iPOCLastDisplay); void xDecodeVPS( InputNALUnit& nalu ); void xDecodeDPS( InputNALUnit& nalu ); diff --git a/source/Lib/DecoderLib/DecSlice.cpp b/source/Lib/DecoderLib/DecSlice.cpp index b4a5da395..ff0b2c915 100644 --- a/source/Lib/DecoderLib/DecSlice.cpp +++ b/source/Lib/DecoderLib/DecSlice.cpp @@ -87,8 +87,13 @@ void DecSlice::decompressSlice( Slice* slice, InputBitstream* bitstream, int deb cs.pps = slice->getPPS(); memcpy(cs.alfApss, slice->getAlfAPSs(), sizeof(cs.alfApss)); + #if JVET_P1006_PICTURE_HEADER + cs.lmcsAps = slice->getPicHeader()->getLmcsAPS(); + cs.scalinglistAps = slice->getPicHeader()->getScalingListAPS(); +#else cs.lmcsAps = slice->getLmcsAPS(); cs.scalinglistAps = slice->getscalingListAPS(); +#endif cs.pcv = slice->getPPS()->pcv; cs.chromaQpAdj = 0; diff --git a/source/Lib/DecoderLib/VLCReader.cpp b/source/Lib/DecoderLib/VLCReader.cpp index dd2dddafa..d4fc96565 100644 --- a/source/Lib/DecoderLib/VLCReader.cpp +++ b/source/Lib/DecoderLib/VLCReader.cpp @@ -388,6 +388,30 @@ void HLSyntaxReader::parsePPS( PPS* pcPPS, ParameterSetManager *parameterSetMana READ_FLAG( uiCode, "output_flag_present_flag" ); pcPPS->setOutputFlagPresentFlag( uiCode==1 ); +#if JVET_P1006_PICTURE_HEADER + READ_FLAG(uiCode, "pps_subpic_id_signalling_present_flag"); pcPPS->setSubPicIdSignallingPresentFlag( uiCode != 0 ); + if( pcPPS->getSubPicIdSignallingPresentFlag() ) + { + READ_UVLC( uiCode, "pps_num_subpics_minus1" ); pcPPS->setNumSubPics( uiCode + 1 ); + CHECK( uiCode > MAX_NUM_SUB_PICS-1, "Number of sub-pictures exceeds limit"); + + READ_UVLC( uiCode, "pps_subpic_id_len_minus1" ); pcPPS->setSubPicIdLen( uiCode + 1 ); + CHECK( uiCode > 15, "Invalid pps_subpic_id_len_minus1 signalled"); + + for( int picIdx = 0; picIdx < pcPPS->getNumSubPics( ); picIdx++ ) + { + READ_CODE( pcPPS->getSubPicIdLen( ), uiCode, "pps_subpic_id[i]" ); pcPPS->setSubPicId( picIdx, uiCode ); + } + } + else + { + for( int picIdx = 0; picIdx < MAX_NUM_SUB_PICS; picIdx++ ) + { + pcPPS->setSubPicId( picIdx, picIdx ); + } + } + +#endif READ_CODE(3, uiCode, "num_extra_slice_header_bits"); pcPPS->setNumExtraSliceHeaderBits(uiCode); @@ -446,6 +470,7 @@ void HLSyntaxReader::parsePPS( PPS* pcPPS, ParameterSetManager *parameterSetMana } READ_FLAG( uiCode, "cu_qp_delta_enabled_flag" ); pcPPS->setUseDQP( uiCode ? true : false ); +#if !JVET_P1006_PICTURE_HEADER if( pcPPS->getUseDQP() ) { READ_UVLC( uiCode, "cu_qp_delta_subdiv" ); @@ -455,6 +480,7 @@ void HLSyntaxReader::parsePPS( PPS* pcPPS, ParameterSetManager *parameterSetMana { pcPPS->setCuQpDeltaSubdiv( 0 ); } +#endif READ_SVLC( iCode, "pps_cb_qp_offset"); pcPPS->setQpOffset(COMPONENT_Cb, iCode); CHECK( pcPPS->getQpOffset(COMPONENT_Cb) < -12, "Invalid Cb QP offset" ); @@ -494,11 +520,15 @@ void HLSyntaxReader::parsePPS( PPS* pcPPS, ParameterSetManager *parameterSetMana if (uiCode == 0) { pcPPS->clearChromaQpOffsetList(); +#if !JVET_P1006_PICTURE_HEADER pcPPS->setCuChromaQpOffsetSubdiv(0); +#endif } else { +#if !JVET_P1006_PICTURE_HEADER READ_UVLC(uiCode, "cu_chroma_qp_offset_subdiv"); pcPPS->setCuChromaQpOffsetSubdiv(uiCode); +#endif uint32_t tableSizeMinus1 = 0; READ_UVLC(tableSizeMinus1, "chroma_qp_offset_list_len_minus1"); CHECK(tableSizeMinus1 >= MAX_QP_OFFSET_LIST_SIZE, "Table size exceeds maximum"); @@ -813,6 +843,7 @@ void HLSyntaxReader::parsePPS( PPS* pcPPS, ParameterSetManager *parameterSetMana } } +#if !JVET_P1006_PICTURE_HEADER READ_FLAG( uiCode, "pps_loop_filter_across_virtual_boundaries_disabled_flag" ); pcPPS->setLoopFilterAcrossVirtualBoundariesDisabledFlag( uiCode != 0 ); if( pcPPS->getLoopFilterAcrossVirtualBoundariesDisabledFlag() ) { @@ -827,12 +858,17 @@ void HLSyntaxReader::parsePPS( PPS* pcPPS, ParameterSetManager *parameterSetMana READ_CODE(13, uiCode, "pps_virtual_boundaries_pos_y"); pcPPS->setVirtualBoundariesPosY(uiCode << 3, i); } } +#endif READ_UVLC( uiCode, "log2_parallel_merge_level_minus2"); pcPPS->setLog2ParallelMergeLevelMinus2 (uiCode); +#if JVET_P1006_PICTURE_HEADER + READ_FLAG( uiCode, "picture_header_extension_present_flag"); + pcPPS->setPictureHeaderExtensionPresentFlag(uiCode); +#endif READ_FLAG( uiCode, "slice_segment_header_extension_present_flag"); pcPPS->setSliceHeaderExtensionPresentFlag(uiCode); @@ -1206,11 +1242,39 @@ void HLSyntaxReader::parseSPS(SPS* pcSPS) if( pcSPS->getChromaFormatIdc() == CHROMA_444 ) { READ_FLAG( uiCode, "separate_colour_plane_flag"); CHECK(uiCode != 0, "Invalid code"); +#if JVET_P1006_PICTURE_HEADER + pcSPS->setSeparateColourPlaneFlag( uiCode != 0 ); +#endif } READ_UVLC( uiCode, "pic_width_max_in_luma_samples" ); pcSPS->setMaxPicWidthInLumaSamples( uiCode ); READ_UVLC( uiCode, "pic_height_max_in_luma_samples" ); pcSPS->setMaxPicHeightInLumaSamples( uiCode ); +#if JVET_P1006_PICTURE_HEADER + pcSPS->setNumSubPics( 1 ); // TODO - need sub-picture syntax + READ_FLAG(uiCode, "sps_subpic_id_present_flag"); pcSPS->setSubPicIdPresentFlag( uiCode != 0 ); + if( pcSPS->getSubPicIdPresentFlag() ) + { + READ_FLAG(uiCode, "sps_subpic_id_signalling_present_flag"); pcSPS->setSubPicIdSignallingPresentFlag( uiCode != 0 ); + if( pcSPS->getSubPicIdSignallingPresentFlag() ) + { + READ_UVLC( uiCode, "sps_subpic_id_len_minus1" ); pcSPS->setSubPicIdLen( uiCode + 1 ); + CHECK( uiCode > 15, "Invalid sps_subpic_id_len_minus1 signalled"); + for( int picIdx = 0; picIdx < pcSPS->getNumSubPics( ); picIdx++ ) + { + READ_CODE( pcSPS->getSubPicIdLen( ), uiCode, "sps_subpic_id[i]" ); pcSPS->setSubPicId( picIdx, uiCode ); + } + } + } + if( pcSPS->getSubPicIdPresentFlag() == false || pcSPS->getSubPicIdSignallingPresentFlag() == false ) + { + for( int picIdx = 0; picIdx < pcSPS->getNumSubPics( ); picIdx++ ) + { + pcSPS->setSubPicId( picIdx, picIdx ); + } + } +#endif + #if JVET_P0243_SINGLE_BIT_DEPTH READ_UVLC( uiCode, "bit_depth_minus8" ); CHECK(uiCode > 8, "Invalid bit depth signalled"); @@ -1570,6 +1634,28 @@ void HLSyntaxReader::parseSPS(SPS* pcSPS) // KJS: remove scaling lists? READ_FLAG( uiCode, "scaling_list_enabled_flag" ); pcSPS->setScalingListFlag ( uiCode ); +#if JVET_P1006_PICTURE_HEADER + READ_FLAG( uiCode, "sps_loop_filter_across_virtual_boundaries_disabled_present_flag" ); pcSPS->setLoopFilterAcrossVirtualBoundariesDisabledFlag( uiCode != 0 ); + if( pcSPS->getLoopFilterAcrossVirtualBoundariesDisabledFlag() ) + { + READ_CODE( 2, uiCode, "sps_num_ver_virtual_boundaries"); pcSPS->setNumVerVirtualBoundaries( uiCode ); + for( unsigned i = 0; i < pcSPS->getNumVerVirtualBoundaries(); i++ ) + { + READ_CODE(13, uiCode, "sps_virtual_boundaries_pos_x"); pcSPS->setVirtualBoundariesPosX(uiCode << 3, i); + } + READ_CODE( 2, uiCode, "sps_num_hor_virtual_boundaries"); pcSPS->setNumHorVirtualBoundaries( uiCode ); + for( unsigned i = 0; i < pcSPS->getNumHorVirtualBoundaries(); i++ ) + { + READ_CODE(13, uiCode, "sps_virtual_boundaries_pos_y"); pcSPS->setVirtualBoundariesPosY(uiCode << 3, i); + } + } + else + { + pcSPS->setNumVerVirtualBoundaries( 0 ); + pcSPS->setNumHorVirtualBoundaries( 0 ); + } + +#endif TimingInfo *timingInfo = pcSPS->getTimingInfo(); READ_FLAG( uiCode, "general_hrd_parameters_present_flag"); pcSPS->setHrdParametersPresentFlag(uiCode); if( pcSPS->getHrdParametersPresentFlag() ) @@ -1713,7 +1799,676 @@ void HLSyntaxReader::parseVPS(VPS* pcVPS) xReadRbspTrailingBits(); } +#if JVET_P1006_PICTURE_HEADER +void HLSyntaxReader::parsePictureHeader( PicHeader* picHeader, ParameterSetManager *parameterSetManager ) +{ + uint32_t uiCode; + int iCode; + PPS* pps = NULL; + SPS* sps = NULL; + +#if ENABLE_TRACING + xTracePictureHeader(); +#endif + + READ_FLAG(uiCode, "non_reference_picture_flag"); picHeader->setNonReferencePictureFlag( uiCode != 0 ); + READ_FLAG(uiCode, "gdr_pic_flag"); picHeader->setGdrPicFlag( uiCode != 0 ); + READ_FLAG(uiCode, "no_output_of_prior_pics_flag"); picHeader->setNoOutputOfPriorPicsFlag( uiCode != 0 ); + if( picHeader->getGdrPicFlag() ) + { + READ_UVLC(uiCode, "recovery_poc_cnt"); picHeader->setRecoveryPocCnt( uiCode ); + } + else + { + picHeader->setRecoveryPocCnt( 0 ); + } + + // parameter sets + READ_UVLC(uiCode, "ph_pic_parameter_set_id"); + picHeader->setPPSId( uiCode ); + pps = parameterSetManager->getPPS(picHeader->getPPSId()); + CHECK(pps==0, "Invalid PPS"); + picHeader->setSPSId( pps->getSPSId() ); + sps = parameterSetManager->getSPS(picHeader->getSPSId()); + CHECK(sps==0, "Invalid SPS"); + + // sub-picture IDs + if( sps->getSubPicIdPresentFlag() ) + { + if( sps->getSubPicIdSignallingPresentFlag() ) + { + for( int picIdx = 0; picIdx < sps->getNumSubPics( ); picIdx++ ) + { + picHeader->setSubPicId( picIdx, sps->getSubPicId( picIdx ) ); + } + } + else + { + READ_FLAG(uiCode, "ph_subpic_id_signalling_present_flag"); picHeader->setSubPicIdSignallingPresentFlag( uiCode != 0 ); + if( picHeader->getSubPicIdSignallingPresentFlag() ) + { + READ_UVLC( uiCode, "ph_subpic_id_len_minus1" ); picHeader->setSubPicIdLen( uiCode + 1 ); + CHECK( uiCode > 15, "Invalid ph_subpic_id_len_minus1 signalled"); + for( int picIdx = 0; picIdx < sps->getNumSubPics( ); picIdx++ ) + { + READ_CODE( picHeader->getSubPicIdLen( ), uiCode, "ph_subpic_id[i]" ); picHeader->setSubPicId( picIdx, uiCode ); + } + } + else + { + for( int picIdx = 0; picIdx < sps->getNumSubPics( ); picIdx++ ) + { + picHeader->setSubPicId( picIdx, pps->getSubPicId( picIdx ) ); + } + } + } + } + else + { + for( int picIdx = 0; picIdx < sps->getNumSubPics( ); picIdx++ ) + { + picHeader->setSubPicId( picIdx, picIdx ); + } + } + + // virtual boundaries + if( !sps->getLoopFilterAcrossVirtualBoundariesDisabledFlag() ) + { + READ_FLAG( uiCode, "ph_loop_filter_across_virtual_boundaries_disabled_present_flag" ); picHeader->setLoopFilterAcrossVirtualBoundariesDisabledFlag( uiCode != 0 ); + if( picHeader->getLoopFilterAcrossVirtualBoundariesDisabledFlag() ) + { + READ_CODE( 2, uiCode, "ph_num_ver_virtual_boundaries"); picHeader->setNumVerVirtualBoundaries( uiCode ); + for( unsigned i = 0; i < picHeader->getNumVerVirtualBoundaries(); i++ ) + { + READ_CODE(13, uiCode, "ph_virtual_boundaries_pos_x"); picHeader->setVirtualBoundariesPosX(uiCode << 3, i); + } + READ_CODE( 2, uiCode, "ph_num_hor_virtual_boundaries"); picHeader->setNumHorVirtualBoundaries( uiCode ); + for( unsigned i = 0; i < picHeader->getNumHorVirtualBoundaries(); i++ ) + { + READ_CODE(13, uiCode, "ph_virtual_boundaries_pos_y"); picHeader->setVirtualBoundariesPosY(uiCode << 3, i); + } + } + else + { + picHeader->setNumVerVirtualBoundaries( 0 ); + picHeader->setNumHorVirtualBoundaries( 0 ); + } + } + else + { + picHeader->setLoopFilterAcrossVirtualBoundariesDisabledFlag( sps->getLoopFilterAcrossVirtualBoundariesDisabledFlag() ); + picHeader->setNumVerVirtualBoundaries( sps->getNumVerVirtualBoundaries() ); + picHeader->setNumHorVirtualBoundaries( sps->getNumHorVirtualBoundaries() ); + for( unsigned i = 0; i < 3; i++ ) + { + picHeader->setVirtualBoundariesPosX( sps->getVirtualBoundariesPosX(i), i ); + picHeader->setVirtualBoundariesPosY( sps->getVirtualBoundariesPosY(i), i ); + } + } + + // 4:4:4 colour plane ID + if( sps->getSeparateColourPlaneFlag() ) + { + READ_CODE( 2, uiCode, "colour_plane_id" ); picHeader->setColourPlaneId( uiCode ); + CHECK(uiCode > 2, "colour_plane_id exceeds valid range"); + } + else + { + picHeader->setColourPlaneId( 0 ); + } + + // picture output flag + if( pps->getOutputFlagPresentFlag() ) + { + READ_FLAG( uiCode, "pic_output_flag" ); picHeader->setPicOutputFlag( uiCode != 0 ); + } + else + { + picHeader->setPicOutputFlag( true ); + } + + // reference picture lists + READ_FLAG( uiCode, "pic_rpl_present_flag" ); picHeader->setPicRplPresentFlag( uiCode != 0 ); + if( picHeader->getPicRplPresentFlag() ) + { + // List0 and List1 + for(int listIdx = 0; listIdx < 2; listIdx++) + { + // copy L1 index from L0 index + if (listIdx == 1 && !pps->getRpl1IdxPresentFlag()) + { + picHeader->setRPL1idx(picHeader->getRPL0idx()); + uiCode = (picHeader->getRPL0idx() != -1); + } + // RPL in picture header or SPS + else if (sps->getNumRPL( listIdx ) == 0) + { + uiCode = 0; + } + else if (!pps->getPPSRefPicListSPSIdc( listIdx )) + { + READ_FLAG(uiCode, "pic_rpl_sps_flag[i]"); + } + else + { + uiCode = pps->getPPSRefPicListSPSIdc( listIdx ) - 1; + } + + // explicit RPL in picture header + if (!uiCode) + { + ReferencePictureList* rpl = picHeader->getLocalRPL( listIdx ); + (*rpl) = ReferencePictureList(); + parseRefPicList(sps, rpl); + picHeader->setRPLIdx(listIdx, -1); + picHeader->setRPL(listIdx, rpl); + } + // use list from SPS + else + { + if (listIdx == 1 && !pps->getRpl1IdxPresentFlag()) + { + picHeader->setRPL( listIdx, sps->getRPLList( listIdx )->getReferencePictureList(picHeader->getRPLIdx( listIdx ))); + } + else if (sps->getNumRPL( listIdx ) > 1) + { + int numBits = ceilLog2(sps->getNumRPL( listIdx )); + READ_CODE(numBits, uiCode, "pic_rpl_idx[i]"); + picHeader->setRPLIdx( listIdx, uiCode ); + picHeader->setRPL( listIdx, sps->getRPLList( listIdx )->getReferencePictureList(uiCode)); + } + else + { + picHeader->setRPLIdx( listIdx, 0 ); + picHeader->setRPL( listIdx, sps->getRPLList( listIdx )->getReferencePictureList(0)); + } + } + + // POC MSB cycle signalling for LTRP + for (int i = 0; i < picHeader->getRPL( listIdx )->getNumberOfLongtermPictures() + picHeader->getRPL( listIdx )->getNumberOfShorttermPictures(); i++) + { + picHeader->getLocalRPL( listIdx )->setDeltaPocMSBPresentFlag(i, false); + picHeader->getLocalRPL( listIdx )->setDeltaPocMSBCycleLT(i, 0); + } + if (picHeader->getRPL( listIdx )->getNumberOfLongtermPictures()) + { + for (int i = 0; i < picHeader->getRPL( listIdx )->getNumberOfLongtermPictures() + picHeader->getRPL( listIdx )->getNumberOfShorttermPictures(); i++) + { + if (picHeader->getRPL( listIdx )->isRefPicLongterm(i)) + { + if (picHeader->getRPL( listIdx )->getLtrpInSliceHeaderFlag()) + { + READ_CODE(sps->getBitsForPOC(), uiCode, "pic_poc_lsb_lt[i][j]"); + picHeader->getLocalRPL( listIdx )->setRefPicIdentifier(i, uiCode, true); + } + READ_FLAG(uiCode, "pic_delta_poc_msb_present_flag[i][j]"); + picHeader->getLocalRPL( listIdx )->setDeltaPocMSBPresentFlag(i, uiCode ? true : false); + if (uiCode) + { + READ_UVLC(uiCode, "pic_delta_poc_msb_cycle_lt[i][j]"); + picHeader->getLocalRPL( listIdx )->setDeltaPocMSBCycleLT(i, uiCode); + } + } + } + } + } + } + + // partitioning constraint overrides + if (sps->getSplitConsOverrideEnabledFlag()) + { + READ_FLAG(uiCode, "partition_constraints_override_flag"); picHeader->setSplitConsOverrideFlag( uiCode != 0 ); + if (picHeader->getSplitConsOverrideFlag()) + { + unsigned minQT[3] = { 0, 0, 0 }; + unsigned maxBTD[3] = { 0, 0, 0 }; + unsigned maxBTSize[3] = { 0, 0, 0 }; + unsigned maxTTSize[3] = { 0, 0, 0 }; + unsigned ctbLog2SizeY = floorLog2(sps->getCTUSize()); + + READ_UVLC(uiCode, "pic_log2_diff_min_qt_min_cb_intra_slice_luma"); + unsigned minQtLog2SizeIntraY = uiCode + sps->getLog2MinCodingBlockSize(); + minQT[0] = 1 << minQtLog2SizeIntraY; + READ_UVLC(uiCode, "pic_log2_diff_min_qt_min_cb_inter_slice"); + unsigned minQtLog2SizeInterY = uiCode + sps->getLog2MinCodingBlockSize(); + minQT[1] = 1 << minQtLog2SizeInterY; + READ_UVLC(uiCode, "pic_max_mtt_hierarchy_depth_inter_slice"); maxBTD[1] = uiCode; + READ_UVLC(uiCode, "pic_max_mtt_hierarchy_depth_intra_slice_luma"); maxBTD[0] = uiCode; + + maxTTSize[0] = maxBTSize[0] = minQT[0]; + if (maxBTD[0] != 0) + { + READ_UVLC(uiCode, "pic_log2_diff_max_bt_min_qt_intra_slice_luma"); maxBTSize[0] <<= uiCode; + CHECK(uiCode > ctbLog2SizeY - minQtLog2SizeIntraY, "Invalid code"); + READ_UVLC(uiCode, "pic_log2_diff_max_tt_min_qt_intra_slice_luma"); maxTTSize[0] <<= uiCode; + CHECK(uiCode > ctbLog2SizeY - minQtLog2SizeIntraY, "Invalid code"); + } + maxTTSize[1] = maxBTSize[1] = minQT[1]; + if (maxBTD[1] != 0) + { + READ_UVLC(uiCode, "pic_log2_diff_max_bt_min_qt_inter_slice"); maxBTSize[1] <<= uiCode; + CHECK(uiCode > ctbLog2SizeY - minQtLog2SizeInterY, "Invalid code"); + READ_UVLC(uiCode, "pic_log2_diff_max_tt_min_qt_inter_slice"); maxTTSize[1] <<= uiCode; + CHECK(uiCode > ctbLog2SizeY - minQtLog2SizeInterY, "Invalid code"); + } + if (sps->getUseDualITree()) + { + READ_UVLC(uiCode, "pic_log2_diff_min_qt_min_cb_intra_slice_chroma"); minQT[2] = 1 << (uiCode + sps->getLog2MinCodingBlockSize()); + READ_UVLC(uiCode, "pic_max_mtt_hierarchy_depth_intra_slice_chroma"); maxBTD[2] = uiCode; + maxTTSize[2] = maxBTSize[2] = minQT[2]; + if (maxBTD[2] != 0) + { + READ_UVLC(uiCode, "pic_log2_diff_max_bt_min_qt_intra_slice_chroma"); maxBTSize[2] <<= uiCode; + READ_UVLC(uiCode, "pic_log2_diff_max_tt_min_qt_intra_slice_chroma"); maxTTSize[2] <<= uiCode; + } + } + + picHeader->setMinQTSizes(minQT); + picHeader->setMaxMTTHierarchyDepths(maxBTD); + picHeader->setMaxBTSizes(maxBTSize); + picHeader->setMaxTTSizes(maxTTSize); + } + } + else + { + picHeader->setSplitConsOverrideFlag(0); + } + + // inherit constraint values from SPS + if (!sps->getSplitConsOverrideEnabledFlag() || !picHeader->getSplitConsOverrideFlag()) + { + picHeader->setMinQTSizes(sps->getMinQTSizes()); + picHeader->setMaxMTTHierarchyDepths(sps->getMaxMTTHierarchyDepths()); + picHeader->setMaxBTSizes(sps->getMaxBTSizes()); + picHeader->setMaxTTSizes(sps->getMaxTTSizes()); + } + + // delta quantization and chrom and chroma offset + if (pps->getUseDQP()) + { + READ_UVLC( uiCode, "pic_cu_qp_delta_subdiv_intra_slice" ); picHeader->setCuQpDeltaSubdivIntra( uiCode ); + READ_UVLC( uiCode, "pic_cu_qp_delta_subdiv_inter_slice" ); picHeader->setCuQpDeltaSubdivInter( uiCode ); + } + else + { + picHeader->setCuQpDeltaSubdivIntra( 0 ); + picHeader->setCuQpDeltaSubdivInter( 0 ); + } + if (pps->getCuChromaQpOffsetEnabledFlag()) + { + READ_UVLC( uiCode, "pic_cu_chroma_qp_offset_subdiv_intra_slice" ); picHeader->setCuChromaQpOffsetSubdivIntra( uiCode ); + READ_UVLC( uiCode, "pic_cu_chroma_qp_offset_subdiv_inter_slice" ); picHeader->setCuChromaQpOffsetSubdivInter( uiCode ); + } + else + { + picHeader->setCuChromaQpOffsetSubdivIntra( 0 ); + picHeader->setCuChromaQpOffsetSubdivInter( 0 ); + } + + // temporal motion vector prediction + if (sps->getSPSTemporalMVPEnabledFlag()) + { +#if JVET_P0206_TMVP_flags + READ_FLAG( uiCode, "pic_temporal_mvp_enabled_flag" ); + picHeader->setEnableTMVPFlag( uiCode != 0 ); +#else + if (!pps->getPPSTemporalMVPEnabledIdc()) + { + READ_FLAG( uiCode, "pic_temporal_mvp_enabled_flag" ); + picHeader->setEnableTMVPFlag( uiCode != 0 ); + } + else + { + pcSlice->setEnableTMVPFlag((pps->getPPSTemporalMVPEnabledIdc() - 1) == 1 ? true : false); + } +#endif + } + else + { + picHeader->setEnableTMVPFlag(false); + } + + // mvd L1 zero flag + if (!pps->getPPSMvdL1ZeroIdc()) + { + READ_FLAG(uiCode, "pic_mvd_l1_zero_flag"); + } + else + { + uiCode = pps->getPPSMvdL1ZeroIdc() - 1; + } + picHeader->setMvdL1ZeroFlag( uiCode != 0 ); + + // merge candidate list size + if (!pps->getPPSSixMinusMaxNumMergeCandPlus1()) + { + READ_UVLC(uiCode, "pic_six_minus_max_num_merge_cand"); + } + else + { + uiCode = pps->getPPSSixMinusMaxNumMergeCandPlus1() - 1; + } + CHECK(MRG_MAX_NUM_CANDS <= uiCode, "Incorrrect max number of merge candidates!"); + picHeader->setMaxNumMergeCand(MRG_MAX_NUM_CANDS - uiCode); + + // subblock merge candidate list size + if ( sps->getUseAffine() ) + { +#if JVET_P0152_REMOVE_PPS_NUM_SUBBLOCK_MERGE_CAND + READ_UVLC(uiCode, "pic_five_minus_max_num_subblock_merge_cand"); +#else + if (!pps->getPPSFiveMinusMaxNumSubblockMergeCandPlus1()) + { + READ_UVLC(uiCode, "five_minus_max_num_subblock_merge_cand"); + } + else + { + uiCode = pps->getPPSFiveMinusMaxNumSubblockMergeCandPlus1() - 1; + } +#endif + CHECK(AFFINE_MRG_MAX_NUM_CANDS < uiCode, "Incorrrect max number of affine merge candidates!"); + picHeader->setMaxNumAffineMergeCand( AFFINE_MRG_MAX_NUM_CANDS - uiCode ); + } + else + { + picHeader->setMaxNumAffineMergeCand( sps->getSBTMVPEnabledFlag() && picHeader->getEnableTMVPFlag() ); + } + + // full-pel MMVD flag + if (sps->getFpelMmvdEnabledFlag()) + { + READ_FLAG( uiCode, "pic_fpel_mmvd_enabled_flag" ); + picHeader->setDisFracMMVD( uiCode != 0 ); + } + else + { + picHeader->setDisFracMMVD(false); + } + + // picture level BDOF/DMVR/PROF disable flags + if (sps->getBdofDmvrSlicePresentFlag()) + { + READ_FLAG(uiCode, "pic_disable_bdof_dmvr_flag"); picHeader->setDisBdofDmvrFlag( uiCode != 0 ); + } + else + { + picHeader->setDisBdofDmvrFlag(0); + } + + // triangle merge candidate list size + if (sps->getUseTriangle() && picHeader->getMaxNumMergeCand() >= 2) + { + if (!pps->getPPSMaxNumMergeCandMinusMaxNumTriangleCandPlus1()) + { + READ_UVLC(uiCode, "pic_max_num_merge_cand_minus_max_num_triangle_cand"); + } + else + { + uiCode = pps->getPPSMaxNumMergeCandMinusMaxNumTriangleCandPlus1() - 1; + } + CHECK(picHeader->getMaxNumMergeCand() < uiCode, "Incorrrect max number of triangle candidates!"); + picHeader->setMaxNumTriangleCand((uint32_t)(picHeader->getMaxNumMergeCand() - uiCode)); + } + else + { + picHeader->setMaxNumTriangleCand(0); + } + + // ibc merge candidate list size + if (sps->getIBCFlag()) + { + READ_UVLC(uiCode, "pic_six_minus_max_num_ibc_merge_cand"); + CHECK(IBC_MRG_MAX_NUM_CANDS <= uiCode, "Incorrrect max number of IBC merge candidates!"); + picHeader->setMaxNumIBCMergeCand(IBC_MRG_MAX_NUM_CANDS - uiCode); + } + else + { + picHeader->setMaxNumIBCMergeCand(0); + } + + // joint Cb/Cr sign flag + if (sps->getJointCbCrEnabledFlag()) + { + READ_FLAG( uiCode, "pic_joint_cbcr_sign_flag" ); + picHeader->setJointCbCrSignFlag(uiCode != 0); + } + else + { + picHeader->setJointCbCrSignFlag(false); + } + + // sao enable flags + if(sps->getSAOEnabledFlag()) + { + READ_FLAG(uiCode, "pic_sao_enabled_present_flag"); + picHeader->setSaoEnabledPresentFlag(uiCode != 0); + + if (picHeader->getSaoEnabledPresentFlag()) + { + READ_FLAG(uiCode, "slice_sao_luma_flag"); + picHeader->setSaoEnabledFlag(CHANNEL_TYPE_LUMA, uiCode != 0); + + if (sps->getChromaFormatIdc() != CHROMA_400) + { + READ_FLAG(uiCode, "slice_sao_chroma_flag"); + picHeader->setSaoEnabledFlag(CHANNEL_TYPE_CHROMA, uiCode != 0); + } + } + else + { + picHeader->setSaoEnabledFlag(CHANNEL_TYPE_LUMA, true); + picHeader->setSaoEnabledFlag(CHANNEL_TYPE_CHROMA, sps->getChromaFormatIdc() != CHROMA_400); + } + } + else + { + picHeader->setSaoEnabledFlag(CHANNEL_TYPE_LUMA, false); + picHeader->setSaoEnabledFlag(CHANNEL_TYPE_CHROMA, false); + } + + // alf enable flags and aps IDs + if( sps->getALFEnabledFlag() ) + { + READ_FLAG(uiCode, "pic_alf_enabled_present_flag"); + picHeader->setAlfEnabledPresentFlag(uiCode != 0); + + if (picHeader->getAlfEnabledPresentFlag()) + { + READ_FLAG(uiCode, "pic_alf_enabled_flag"); + picHeader->setAlfEnabledFlag(COMPONENT_Y, uiCode); + + int alfChromaIdc = 0; + if (uiCode) + { + READ_CODE(3, uiCode, "pic_num_alf_aps_ids_luma"); + int numAps = uiCode; + picHeader->setNumAlfAps(numAps); + + std::vector<int> apsId(numAps, -1); + for (int i = 0; i < numAps; i++) + { + READ_CODE(3, uiCode, "pic_alf_aps_id_luma"); + apsId[i] = uiCode; + } + picHeader->setAlfAPSs(apsId); + + if (sps->getChromaFormatIdc() != CHROMA_400) + { + READ_CODE(2, uiCode, "pic_alf_chroma_idc"); + alfChromaIdc = uiCode; + } + else + { + alfChromaIdc = 0; + } + if (alfChromaIdc) + { + READ_CODE(3, uiCode, "pic_alf_aps_id_chroma"); + picHeader->setAlfApsIdChroma(uiCode); + } + } + else + { + picHeader->setNumAlfAps(0); + } + picHeader->setAlfEnabledFlag(COMPONENT_Cb, alfChromaIdc & 1); + picHeader->setAlfEnabledFlag(COMPONENT_Cr, alfChromaIdc >> 1); + } + else + { + picHeader->setAlfEnabledFlag(COMPONENT_Y, true); + picHeader->setAlfEnabledFlag(COMPONENT_Cb, true); + picHeader->setAlfEnabledFlag(COMPONENT_Cr, true); + } + } + else + { + picHeader->setAlfEnabledFlag(COMPONENT_Y, false); + picHeader->setAlfEnabledFlag(COMPONENT_Cb, false); + picHeader->setAlfEnabledFlag(COMPONENT_Cr, false); + } + + // dependent quantization + if (!pps->getPPSDepQuantEnabledIdc()) + { + READ_FLAG(uiCode, "pic_dep_quant_enabled_flag"); + } + else + { + uiCode = pps->getPPSDepQuantEnabledIdc() - 1; + } + picHeader->setDepQuantEnabledFlag( uiCode != 0 ); + + // sign data hiding + if( !picHeader->getDepQuantEnabledFlag() ) + { + READ_FLAG( uiCode, "pic_sign_data_hiding_enabled_flag" ); + picHeader->setSignDataHidingEnabledFlag( uiCode != 0 ); + } + else + { + picHeader->setSignDataHidingEnabledFlag(false); + } + + // deblocking filter controls + if (pps->getDeblockingFilterControlPresentFlag()) + { + if(pps->getDeblockingFilterOverrideEnabledFlag()) + { + READ_FLAG ( uiCode, "pic_deblocking_filter_override_present_flag" ); + picHeader->setDeblockingFilterOverridePresentFlag(uiCode != 0); + + if( picHeader->getDeblockingFilterOverridePresentFlag() ) + { + READ_FLAG ( uiCode, "pic_deblocking_filter_override_flag" ); + picHeader->setDeblockingFilterOverrideFlag(uiCode != 0); + } + else + { + picHeader->setDeblockingFilterOverrideFlag(false); + } + } + else + { + picHeader->setDeblockingFilterOverridePresentFlag(false); + picHeader->setDeblockingFilterOverrideFlag(false); + } + + if(picHeader->getDeblockingFilterOverrideFlag()) + { + READ_FLAG ( uiCode, "pic_deblocking_filter_disabled_flag" ); + picHeader->setDeblockingFilterDisable(uiCode != 0); + if(!picHeader->getDeblockingFilterDisable()) + { + READ_SVLC( iCode, "pic_beta_offset_div2" ); + picHeader->setDeblockingFilterBetaOffsetDiv2(iCode); + CHECK( picHeader->getDeblockingFilterBetaOffsetDiv2() < -6 && + picHeader->getDeblockingFilterBetaOffsetDiv2() > 6, "Invalid deblocking filter configuration"); + + READ_SVLC( iCode, "pic_tc_offset_div2" ); + picHeader->setDeblockingFilterTcOffsetDiv2(iCode); + CHECK (picHeader->getDeblockingFilterTcOffsetDiv2() < -6 && + picHeader->getDeblockingFilterTcOffsetDiv2() > 6, "Invalid deblocking filter configuration"); + } + } + else + { + picHeader->setDeblockingFilterDisable ( pps->getPPSDeblockingFilterDisabledFlag() ); + picHeader->setDeblockingFilterBetaOffsetDiv2( pps->getDeblockingFilterBetaOffsetDiv2() ); + picHeader->setDeblockingFilterTcOffsetDiv2 ( pps->getDeblockingFilterTcOffsetDiv2() ); + } + } + else + { + picHeader->setDeblockingFilterDisable ( false ); + picHeader->setDeblockingFilterBetaOffsetDiv2( 0 ); + picHeader->setDeblockingFilterTcOffsetDiv2 ( 0 ); + } + + // luma mapping / chroma scaling controls + if (sps->getUseReshaper()) + { + READ_FLAG(uiCode, "pic_lmcs_enabled_flag"); + picHeader->setLmcsEnabledFlag(uiCode != 0); + + if (picHeader->getLmcsEnabledFlag()) + { + READ_CODE(2, uiCode, "pic_lmcs_aps_id"); + picHeader->setLmcsAPSId(uiCode); + + if (sps->getChromaFormatIdc() != CHROMA_400) + { + READ_FLAG(uiCode, "pic_chroma_residual_scale_flag"); + picHeader->setLmcsChromaResidualScaleFlag(uiCode != 0); + } + else + { + picHeader->setLmcsChromaResidualScaleFlag(false); + } + } + } + else + { + picHeader->setLmcsEnabledFlag(false); + picHeader->setLmcsChromaResidualScaleFlag(false); + } + + // quantization scaling lists + if( sps->getScalingListFlag() ) + { + READ_FLAG( uiCode, "pic_scaling_list_present_flag" ); + picHeader->setScalingListPresentFlag( uiCode ); + if( picHeader->getScalingListPresentFlag() ) + { + READ_CODE( 3, uiCode, "pic_scaling_list_aps_id" ); + picHeader->setScalingListAPSId( uiCode ); + } + } + else + { + picHeader->setScalingListPresentFlag( false ); + } + + // picture header extension + if(pps->getPictureHeaderExtensionPresentFlag()) + { + READ_UVLC(uiCode,"pic_segment_header_extension_length"); + for(int i=0; i<uiCode; i++) + { + uint32_t ignore_; + READ_CODE(8,ignore_,"pic_segment_header_extension_data_byte"); + } + } + + xReadRbspTrailingBits(); +} +#endif + +#if JVET_P1006_PICTURE_HEADER +void HLSyntaxReader::parseSliceHeader (Slice* pcSlice, PicHeader* picHeader, ParameterSetManager *parameterSetManager, const int prevTid0POC) +#else void HLSyntaxReader::parseSliceHeader (Slice* pcSlice, ParameterSetManager *parameterSetManager, const int prevTid0POC) +#endif { uint32_t uiCode; int iCode; @@ -1724,9 +2479,15 @@ void HLSyntaxReader::parseSliceHeader (Slice* pcSlice, ParameterSetManager *para PPS* pps = NULL; SPS* sps = NULL; +#if JVET_P1006_PICTURE_HEADER + CHECK(picHeader==0, "Invalid Picture Header"); + CHECK(picHeader->isValid()==false, "Invalid Picture Header"); + pps = parameterSetManager->getPPS( picHeader->getPPSId() ); +#else READ_UVLC(uiCode, "slice_pic_parameter_set_id"); pcSlice->setPPSId(uiCode); pps = parameterSetManager->getPPS(uiCode); +#endif //!KS: need to add error handling code here, if PPS is not available CHECK(pps==0, "Invalid PPS"); sps = parameterSetManager->getSPS(pps->getSPSId()); @@ -1737,6 +2498,36 @@ void HLSyntaxReader::parseSliceHeader (Slice* pcSlice, ParameterSetManager *para const uint32_t numValidComp=getNumberValidComponents(chFmt); const bool bChroma=(chFmt!=CHROMA_400); +#if JVET_P1006_PICTURE_HEADER + // picture order count + READ_CODE(sps->getBitsForPOC(), uiCode, "slice_pic_order_cnt_lsb"); + if (pcSlice->getIdrPicFlag()) + { + pcSlice->setPOC(uiCode); + } + else + { + int iPOClsb = uiCode; + int iPrevPOC = prevTid0POC; + int iMaxPOClsb = 1 << sps->getBitsForPOC(); + int iPrevPOClsb = iPrevPOC & (iMaxPOClsb - 1); + int iPrevPOCmsb = iPrevPOC - iPrevPOClsb; + int iPOCmsb; + if ((iPOClsb < iPrevPOClsb) && ((iPrevPOClsb - iPOClsb) >= (iMaxPOClsb / 2))) + { + iPOCmsb = iPrevPOCmsb + iMaxPOClsb; + } + else if ((iPOClsb > iPrevPOClsb) && ((iPOClsb - iPrevPOClsb) > (iMaxPOClsb / 2))) + { + iPOCmsb = iPrevPOCmsb - iMaxPOClsb; + } + else + { + iPOCmsb = iPrevPOCmsb; + } + pcSlice->setPOC(iPOCmsb + iPOClsb); + } +#endif int bitsSliceAddress = 1; if (!pps->getRectSliceFlag()) { @@ -1797,15 +2588,24 @@ void HLSyntaxReader::parseSliceHeader (Slice* pcSlice, ParameterSetManager *para } pcSlice->setSliceCurStartCtuTsAddr(pcSlice->getSliceCurStartBrickIdx()); +#if !JVET_P1006_PICTURE_HEADER READ_FLAG(uiCode, "non_reference_picture_flag"); pcSlice->setNonRefPictFlag(uiCode); for (int i = 0; i < pps->getNumExtraSliceHeaderBits(); i++) { READ_FLAG(uiCode, "slice_reserved_flag[]"); // ignored } +#endif READ_UVLC ( uiCode, "slice_type" ); pcSlice->setSliceType((SliceType)uiCode); +#if JVET_P1006_PICTURE_HEADER + // inherit values from picture header + // set default values in case slice overrides are disabled + pcSlice->inheritFromPicHeader( picHeader, pps, sps ); +#endif + +#if !JVET_P1006_PICTURE_HEADER // if (separate_colour_plane_flag == 1) // read colour_plane_id // (separate_colour_plane_flag == 1) is not supported in this version of the standard. @@ -1858,8 +2658,20 @@ void HLSyntaxReader::parseSliceHeader (Slice* pcSlice, ParameterSetManager *para { pcSlice->setPicOutputFlag(true); } +#endif +#if JVET_P1006_PICTURE_HEADER + if( picHeader->getPicRplPresentFlag() ) + { + pcSlice->setRPL0(picHeader->getRPL0()); + pcSlice->setRPL1(picHeader->getRPL1()); + *pcSlice->getLocalRPL0() = *picHeader->getLocalRPL0(); + *pcSlice->getLocalRPL1() = *picHeader->getLocalRPL1(); + } + else if( pcSlice->getIdrPicFlag() && !(sps->getIDRRefParamListPresent()) ) +#else if( pcSlice->getIdrPicFlag() && !(sps->getIDRRefParamListPresent())) +#endif { ReferencePictureList* rpl0 = pcSlice->getLocalRPL0(); (*rpl0) = ReferencePictureList(); @@ -1867,8 +2679,10 @@ void HLSyntaxReader::parseSliceHeader (Slice* pcSlice, ParameterSetManager *para ReferencePictureList* rpl1 = pcSlice->getLocalRPL1(); (*rpl1) = ReferencePictureList(); pcSlice->setRPL1(rpl1); +#if !JVET_P1006_PICTURE_HEADER pcSlice->setNumRefIdx(REF_PIC_LIST_0, 0); pcSlice->setNumRefIdx(REF_PIC_LIST_1, 0); +#endif } else { @@ -1933,7 +2747,11 @@ void HLSyntaxReader::parseSliceHeader (Slice* pcSlice, ParameterSetManager *para pcSlice->getLocalRPL0()->setDeltaPocMSBPresentFlag(i, uiCode ? true : false); if (uiCode) { +#if JVET_P1006_PICTURE_HEADER + READ_UVLC(uiCode, "slice_delta_poc_msb_cycle_lt[i][j]"); +#else READ_FLAG(uiCode, "delta_poc_msb_cycle_lt[i][j]"); +#endif pcSlice->getLocalRPL0()->setDeltaPocMSBCycleLT(i, uiCode); } } @@ -2014,13 +2832,27 @@ void HLSyntaxReader::parseSliceHeader (Slice* pcSlice, ParameterSetManager *para pcSlice->getLocalRPL1()->setDeltaPocMSBPresentFlag(i, uiCode ? true : false); if (uiCode) { +#if JVET_P1006_PICTURE_HEADER + READ_UVLC(uiCode, "slice_delta_poc_msb_cycle_lt[i][j]"); +#else READ_FLAG(uiCode, "delta_poc_msb_cycle_lt[i][j]"); +#endif pcSlice->getLocalRPL1()->setDeltaPocMSBCycleLT(i, uiCode); } } } } +#if JVET_P1006_PICTURE_HEADER + } + if( !picHeader->getPicRplPresentFlag() && pcSlice->getIdrPicFlag() && !(sps->getIDRRefParamListPresent())) + { + pcSlice->setNumRefIdx(REF_PIC_LIST_0, 0); + pcSlice->setNumRefIdx(REF_PIC_LIST_1, 0); + } + else + { +#endif if ((!pcSlice->isIntra() && pcSlice->getRPL0()->getNumRefEntries() > 1) || (pcSlice->isInterB() && pcSlice->getRPL1()->getNumRefEntries() > 1) ) { @@ -2101,6 +2933,7 @@ void HLSyntaxReader::parseSliceHeader (Slice* pcSlice, ParameterSetManager *para CHECK(pcSlice->getNumRefIdx(REF_PIC_LIST_1) == 0, "Number of active entries in RPL1 of B picture shall be greater than 0"); } +#if !JVET_P1006_PICTURE_HEADER if ( sps->getSplitConsOverrideEnabledFlag() ) @@ -2192,6 +3025,7 @@ void HLSyntaxReader::parseSliceHeader (Slice* pcSlice, ParameterSetManager *para pcSlice->setMvdL1ZeroFlag( (uiCode ? true : false) ); } +#endif pcSlice->setCabacInitFlag( false ); // default if(pps->getCabacInitPresentFlag() && !pcSlice->isIntra()) @@ -2201,7 +3035,11 @@ void HLSyntaxReader::parseSliceHeader (Slice* pcSlice, ParameterSetManager *para pcSlice->setEncCABACTableIdx( pcSlice->getSliceType() == B_SLICE ? ( uiCode ? P_SLICE : B_SLICE ) : ( uiCode ? B_SLICE : P_SLICE ) ); } +#if JVET_P1006_PICTURE_HEADER + if ( pcSlice->getPicHeader()->getEnableTMVPFlag() ) +#else if ( pcSlice->getEnableTMVPFlag() ) +#endif { if ( pcSlice->getSliceType() == B_SLICE ) { @@ -2253,6 +3091,7 @@ void HLSyntaxReader::parseSliceHeader (Slice* pcSlice, ParameterSetManager *para } } +#if !JVET_P1006_PICTURE_HEADER if (!pcSlice->isIntra()) { if (!pps->getPPSSixMinusMaxNumMergeCandPlus1()) @@ -2336,6 +3175,7 @@ void HLSyntaxReader::parseSliceHeader (Slice* pcSlice, ParameterSetManager *para { pcSlice->setJointCbCrSignFlag(0); } +#endif READ_SVLC( iCode, "slice_qp_delta" ); pcSlice->setSliceQp (26 + pps->getPicInitQPMinus26() + iCode); @@ -2376,6 +3216,7 @@ void HLSyntaxReader::parseSliceHeader (Slice* pcSlice, ParameterSetManager *para } } +#if !JVET_P1006_PICTURE_HEADER if (pps->getCuChromaQpOffsetEnabledFlag()) { READ_FLAG(uiCode, "cu_chroma_qp_offset_enabled_flag"); pcSlice->setUseChromaQpAdj(uiCode != 0); @@ -2384,8 +3225,13 @@ void HLSyntaxReader::parseSliceHeader (Slice* pcSlice, ParameterSetManager *para { pcSlice->setUseChromaQpAdj(false); } +#endif +#if JVET_P1006_PICTURE_HEADER + if( sps->getSAOEnabledFlag() && !picHeader->getSaoEnabledPresentFlag() ) +#else if(sps->getSAOEnabledFlag()) +#endif { READ_FLAG(uiCode, "slice_sao_luma_flag"); pcSlice->setSaoEnabledFlag(CHANNEL_TYPE_LUMA, (bool)uiCode); @@ -2395,7 +3241,11 @@ void HLSyntaxReader::parseSliceHeader (Slice* pcSlice, ParameterSetManager *para } } +#if JVET_P1006_PICTURE_HEADER + if( sps->getALFEnabledFlag() && !picHeader->getAlfEnabledPresentFlag() ) +#else if( sps->getALFEnabledFlag() ) +#endif { READ_FLAG(uiCode, "slice_alf_enabled_flag"); pcSlice->setTileGroupAlfEnabledFlag(COMPONENT_Y, uiCode); @@ -2436,6 +3286,7 @@ void HLSyntaxReader::parseSliceHeader (Slice* pcSlice, ParameterSetManager *para pcSlice->setTileGroupAlfEnabledFlag(COMPONENT_Cr, alfChromaIdc >> 1); } +#if !JVET_P1006_PICTURE_HEADER if (!pps->getPPSDepQuantEnabledIdc()) { READ_FLAG(uiCode, "dep_quant_enabled_flag"); @@ -2455,12 +3306,17 @@ void HLSyntaxReader::parseSliceHeader (Slice* pcSlice, ParameterSetManager *para { pcSlice->setSignDataHidingEnabledFlag( 0 ); } +#endif if (pps->getDeblockingFilterControlPresentFlag()) { +#if JVET_P1006_PICTURE_HEADER + if( pps->getDeblockingFilterOverrideEnabledFlag() && !picHeader->getDeblockingFilterOverridePresentFlag() ) +#else if(pps->getDeblockingFilterOverrideEnabledFlag()) +#endif { - READ_FLAG ( uiCode, "deblocking_filter_override_flag" ); pcSlice->setDeblockingFilterOverrideFlag(uiCode ? true : false); + READ_FLAG ( uiCode, "slice_deblocking_filter_override_flag" ); pcSlice->setDeblockingFilterOverrideFlag(uiCode ? true : false); } else { @@ -2481,9 +3337,15 @@ void HLSyntaxReader::parseSliceHeader (Slice* pcSlice, ParameterSetManager *para } else { +#if JVET_P1006_PICTURE_HEADER + pcSlice->setDeblockingFilterDisable ( picHeader->getDeblockingFilterDisable() ); + pcSlice->setDeblockingFilterBetaOffsetDiv2( picHeader->getDeblockingFilterBetaOffsetDiv2() ); + pcSlice->setDeblockingFilterTcOffsetDiv2 ( picHeader->getDeblockingFilterTcOffsetDiv2() ); +#else pcSlice->setDeblockingFilterDisable ( pps->getPPSDeblockingFilterDisabledFlag() ); pcSlice->setDeblockingFilterBetaOffsetDiv2( pps->getDeblockingFilterBetaOffsetDiv2() ); pcSlice->setDeblockingFilterTcOffsetDiv2 ( pps->getDeblockingFilterTcOffsetDiv2() ); +#endif } } else @@ -2493,6 +3355,7 @@ void HLSyntaxReader::parseSliceHeader (Slice* pcSlice, ParameterSetManager *para pcSlice->setDeblockingFilterTcOffsetDiv2 ( 0 ); } +#if !JVET_P1006_PICTURE_HEADER bool isSAOEnabled = sps->getSAOEnabledFlag() && (pcSlice->getSaoEnabledFlag(CHANNEL_TYPE_LUMA) || (bChroma && pcSlice->getSaoEnabledFlag(CHANNEL_TYPE_CHROMA))); bool isDBFEnabled = (!pcSlice->getDeblockingFilterDisable()); @@ -2538,6 +3401,7 @@ void HLSyntaxReader::parseSliceHeader (Slice* pcSlice, ParameterSetManager *para READ_CODE( 3, uiCode, "slice_scaling_list_aps_id" ); pcSlice->setscalingListAPSId( uiCode ); } +#endif if( pcSlice->getSliceCurStartBrickIdx() == 0 ) { diff --git a/source/Lib/DecoderLib/VLCReader.h b/source/Lib/DecoderLib/VLCReader.h index 3b0c58719..74bea8b8e 100644 --- a/source/Lib/DecoderLib/VLCReader.h +++ b/source/Lib/DecoderLib/VLCReader.h @@ -158,7 +158,12 @@ public: void parseConstraintInfo (ConstraintInfo *cinfo); void parseProfileTierLevel ( ProfileTierLevel *ptl, int maxNumSubLayersMinus1); void parseHrdParameters ( HRDParameters *hrd, uint32_t firstSubLayer, uint32_t tempLevelHigh ); +#if JVET_P1006_PICTURE_HEADER + void parsePictureHeader ( PicHeader* picHeader, ParameterSetManager *parameterSetManager ); + void parseSliceHeader ( Slice* pcSlice, PicHeader* picHeader, ParameterSetManager *parameterSetManager, const int prevTid0POC ); +#else void parseSliceHeader ( Slice* pcSlice, ParameterSetManager *parameterSetManager, const int prevTid0POC ); +#endif void parseTerminatingBit ( uint32_t& ruiBit ); void parseRemainingBytes ( bool noTrailingBytesExpected ); diff --git a/source/Lib/EncoderLib/CABACWriter.cpp b/source/Lib/EncoderLib/CABACWriter.cpp index 7c3344497..3e01f3166 100644 --- a/source/Lib/EncoderLib/CABACWriter.cpp +++ b/source/Lib/EncoderLib/CABACWriter.cpp @@ -386,7 +386,11 @@ void CABACWriter::coding_tree(const CodingStructure& cs, Partitioner& partitione cuCtx.qgStart = true; cuCtx.isDQPCoded = false; } +#if JVET_P1006_PICTURE_HEADER + if( pps.getCuChromaQpOffsetEnabledFlag() && partitioner.currQgChromaEnable() ) +#else if( cs.slice->getUseChromaQpAdj() && partitioner.currQgChromaEnable() ) +#endif { cuCtx.isChromaQpAdjCoded = false; } @@ -398,7 +402,11 @@ void CABACWriter::coding_tree(const CodingStructure& cs, Partitioner& partitione pCuCtxChroma->qgStart = true; pCuCtxChroma->isDQPCoded = false; } +#if JVET_P1006_PICTURE_HEADER + if (pps.getCuChromaQpOffsetEnabledFlag() && pPartitionerChroma->currQgChromaEnable()) +#else if (cs.slice->getUseChromaQpAdj() && pPartitionerChroma->currQgChromaEnable()) +#endif { pCuCtxChroma->isChromaQpAdjCoded = false; } @@ -1481,7 +1489,11 @@ void CABACWriter::cu_palette_info(const CodingUnit& cu, ComponentID compBegin, u cuCtx.isDQPCoded = true; } } +#if JVET_P1006_PICTURE_HEADER + if (cu.useEscape[compBegin] && cu.cs->pps->getCuChromaQpOffsetEnabledFlag() && !cuCtx.isChromaQpAdjCoded) +#else if (cu.useEscape[compBegin] && cu.cs->slice->getUseChromaQpAdj() && !cuCtx.isChromaQpAdjCoded) +#endif { if (!CS::isDualITree(*tu.cs) || isChroma(tu.chType)) { @@ -1990,7 +2002,11 @@ void CABACWriter::prediction_unit( const PredictionUnit& pu ) Mv mvd = pu.mvd[REF_PIC_LIST_0]; mvd.changeIbcPrecInternal2Amvr(pu.cu->imv); mvd_coding(mvd, 0); // already changed to signaling precision +#if JVET_P1006_PICTURE_HEADER + if ( pu.cu->slice->getPicHeader()->getMaxNumIBCMergeCand() == 1 ) +#else if ( pu.cu->slice->getMaxNumIBCMergeCand() == 1 ) +#endif { CHECK( pu.mvpIdx[REF_PIC_LIST_0], "mvpIdx for IBC mode should be 0" ); } @@ -2033,7 +2049,11 @@ void CABACWriter::prediction_unit( const PredictionUnit& pu ) if ( pu.cu->smvdMode != 1 ) { ref_idx ( pu, REF_PIC_LIST_1 ); +#if JVET_P1006_PICTURE_HEADER + if( !pu.cs->picHeader->getMvdL1ZeroFlag() || pu.interDir != 3 /* PRED_BI */ ) +#else if( !pu.cs->slice->getMvdL1ZeroFlag() || pu.interDir != 3 /* PRED_BI */ ) +#endif { if ( pu.cu->affine ) { @@ -2083,7 +2103,11 @@ void CABACWriter::smvd_mode( const PredictionUnit& pu ) void CABACWriter::subblock_merge_flag( const CodingUnit& cu ) { + #if JVET_P1006_PICTURE_HEADER + if ( !cu.cs->slice->isIntra() && (cu.slice->getPicHeader()->getMaxNumAffineMergeCand() > 0) && cu.lumaSize().width >= 8 && cu.lumaSize().height >= 8 ) +#else if ( !cu.cs->slice->isIntra() && (cu.slice->getMaxNumAffineMergeCand() > 0) && cu.lumaSize().width >= 8 && cu.lumaSize().height >= 8 ) +#endif { unsigned ctxId = DeriveCtx::CtxAffineFlag( cu ); m_BinEncoder.encodeBin( cu.affine, Ctx::SubblockMergeFlag( ctxId ) ); @@ -2129,7 +2153,11 @@ void CABACWriter::merge_data(const PredictionUnit& pu) merge_idx(pu); return; } +#if JVET_P1006_PICTURE_HEADER + const bool triangleAvailable = pu.cu->cs->slice->getSPS()->getUseTriangle() && pu.cu->cs->slice->isInterB() && pu.cu->cs->picHeader->getMaxNumTriangleCand() > 1; +#else const bool triangleAvailable = pu.cu->cs->slice->getSPS()->getUseTriangle() && pu.cu->cs->slice->isInterB() && pu.cu->cs->slice->getMaxNumTriangleCand() > 1; +#endif const bool ciipAvailable = pu.cs->sps->getUseMHIntra() && !pu.cu->skip && pu.cu->lwidth() < MAX_CU_SIZE && pu.cu->lheight() < MAX_CU_SIZE; if (pu.cu->lwidth() * pu.cu->lheight() >= 64 && (triangleAvailable || ciipAvailable)) @@ -2232,7 +2260,11 @@ void CABACWriter::merge_idx( const PredictionUnit& pu ) if ( pu.cu->affine ) { +#if JVET_P1006_PICTURE_HEADER + int numCandminus1 = int( pu.cs->picHeader->getMaxNumAffineMergeCand() ) - 1; +#else int numCandminus1 = int( pu.cs->slice->getMaxNumAffineMergeCand() ) - 1; +#endif if ( numCandminus1 > 0 ) { if ( pu.mergeIdx == 0 ) @@ -2293,7 +2325,11 @@ void CABACWriter::merge_idx( const PredictionUnit& pu ) } }; m_BinEncoder.encodeBinEP(splitDir); +#if JVET_P1006_PICTURE_HEADER + const int maxNumTriangleCand = pu.cs->picHeader->getMaxNumTriangleCand(); +#else const int maxNumTriangleCand = pu.cs->slice->getMaxNumTriangleCand(); +#endif CHECK(maxNumTriangleCand < 2, "Incorrect max number of triangle candidates"); CHECK(candIdx0 >= maxNumTriangleCand, "Incorrect candIdx0"); CHECK(candIdx1 >= maxNumTriangleCand, "Incorrect candIdx1"); @@ -2303,9 +2339,17 @@ void CABACWriter::merge_idx( const PredictionUnit& pu ) } int numCandminus1; if (pu.cu->predMode == MODE_IBC) +#if JVET_P1006_PICTURE_HEADER + numCandminus1 = int(pu.cs->picHeader->getMaxNumIBCMergeCand()) - 1; +#else numCandminus1 = int(pu.cs->slice->getMaxNumIBCMergeCand()) - 1; +#endif else +#if JVET_P1006_PICTURE_HEADER + numCandminus1 = int(pu.cs->picHeader->getMaxNumMergeCand()) - 1; +#else numCandminus1 = int(pu.cs->slice->getMaxNumMergeCand()) - 1; +#endif if( numCandminus1 > 0 ) { if( pu.mergeIdx == 0 ) @@ -2338,7 +2382,11 @@ void CABACWriter::mmvd_merge_idx(const PredictionUnit& pu) var1 = (mvpIdx - (var0 * MMVD_MAX_REFINE_NUM)) / 4; var2 = mvpIdx - (var0 * MMVD_MAX_REFINE_NUM) - var1 * 4; +#if JVET_P1006_PICTURE_HEADER + if (pu.cs->picHeader->getMaxNumMergeCand() > 1) +#else if (pu.cs->slice->getMaxNumMergeCand() > 1) +#endif { static_assert(MMVD_BASE_MV_NUM == 2, ""); assert(var0 < 2); @@ -2780,7 +2828,11 @@ void CABACWriter::transform_unit( const TransformUnit& tu, CUCtx& cuCtx, Partiti SizeType channelWidth = !cu.isSepTree() ? cu.lwidth() : cu.chromaSize().width; SizeType channelHeight = !cu.isSepTree() ? cu.lheight() : cu.chromaSize().height; +#if JVET_P1006_PICTURE_HEADER + if (cu.cs->pps->getCuChromaQpOffsetEnabledFlag() && (channelWidth > 64 || channelHeight > 64 || cbfChroma) && !cuCtx.isChromaQpAdjCoded) +#else if (cu.cs->slice->getUseChromaQpAdj() && (channelWidth > 64 || channelHeight > 64 || cbfChroma) && !cuCtx.isChromaQpAdjCoded) +#endif { cu_chroma_qp_offset(cu); cuCtx.isChromaQpAdjCoded = true; @@ -2924,7 +2976,11 @@ void CABACWriter::residual_coding( const TransformUnit& tu, ComponentID compID, } // determine sign hiding +#if JVET_P1006_PICTURE_HEADER + bool signHiding = ( cu.cs->picHeader->getSignDataHidingEnabledFlag() && !cu.transQuantBypass && tu.rdpcm[compID] == RDPCM_OFF ); +#else bool signHiding = ( cu.cs->slice->getSignDataHidingEnabledFlag() && !cu.transQuantBypass && tu.rdpcm[compID] == RDPCM_OFF ); +#endif #if JVET_P0058_CHROMA_TS if( signHiding && CU::isIntra(cu) && CU::isRDPCMEnabled(cu) && tu.mtsIdx[compID] == MTS_SKIP) #else @@ -2987,7 +3043,11 @@ void CABACWriter::residual_coding( const TransformUnit& tu, ComponentID compID, last_sig_coeff( cctx, tu, compID ); // code subblocks +#if JVET_P1006_PICTURE_HEADER + const int stateTab = ( tu.cs->picHeader->getDepQuantEnabledFlag() ? 32040 : 0 ); +#else const int stateTab = ( tu.cs->slice->getDepQuantEnabledFlag() ? 32040 : 0 ); +#endif int state = 0; int ctxBinSampleRatio = (compID == COMPONENT_Y) ? MAX_TU_LEVEL_CTX_CODED_BIN_CONSTRAINT_LUMA : MAX_TU_LEVEL_CTX_CODED_BIN_CONSTRAINT_CHROMA; diff --git a/source/Lib/EncoderLib/EncAdaptiveLoopFilter.cpp b/source/Lib/EncoderLib/EncAdaptiveLoopFilter.cpp index f8f584b59..703b56ac7 100644 --- a/source/Lib/EncoderLib/EncAdaptiveLoopFilter.cpp +++ b/source/Lib/EncoderLib/EncAdaptiveLoopFilter.cpp @@ -722,7 +722,11 @@ void EncAdaptiveLoopFilter::ALFProcess(CodingStructure& cs, const double *lambda const int width = ( xPos + pcv.maxCUWidth > pcv.lumaWidth ) ? ( pcv.lumaWidth - xPos ) : pcv.maxCUWidth; const int height = ( yPos + pcv.maxCUHeight > pcv.lumaHeight ) ? ( pcv.lumaHeight - yPos ) : pcv.maxCUHeight; #if JVET_O0625_ALF_PADDING +#if JVET_P1006_PICTURE_HEADER + if( isCrossedByVirtualBoundaries( cs, xPos, yPos, width, height, alfBryList[0], alfBryList[1], alfBryList[2], alfBryList[3], numHorVirBndry, numVerVirBndry, horVirBndryPos, verVirBndryPos, cs.picHeader ) ) +#else if( isCrossedByVirtualBoundaries( cs, xPos, yPos, width, height, alfBryList[0], alfBryList[1], alfBryList[2], alfBryList[3], numHorVirBndry, numVerVirBndry, horVirBndryPos, verVirBndryPos, cs.slice->getPPS() ) ) +#endif #else if( isCrossedByVirtualBoundaries( xPos, yPos, width, height, clipTop, clipBottom, clipLeft, clipRight, numHorVirBndry, numVerVirBndry, horVirBndryPos, verVirBndryPos, cs.slice->getPPS() ) ) #endif @@ -1846,7 +1850,11 @@ void EncAdaptiveLoopFilter::deriveStatsForFiltering( PelUnitBuf& orgYuv, PelUnit const int width = ( xPos + m_maxCUWidth > m_picWidth ) ? ( m_picWidth - xPos ) : m_maxCUWidth; const int height = ( yPos + m_maxCUHeight > m_picHeight ) ? ( m_picHeight - yPos ) : m_maxCUHeight; #if JVET_O0625_ALF_PADDING +#if JVET_P1006_PICTURE_HEADER + if( isCrossedByVirtualBoundaries( cs, xPos, yPos, width, height, alfBryList[0], alfBryList[1], alfBryList[2], alfBryList[3], numHorVirBndry, numVerVirBndry, horVirBndryPos, verVirBndryPos, cs.picHeader ) ) +#else if( isCrossedByVirtualBoundaries( cs, xPos, yPos, width, height, alfBryList[0], alfBryList[1], alfBryList[2], alfBryList[3], numHorVirBndry, numVerVirBndry, horVirBndryPos, verVirBndryPos, cs.slice->getPPS() ) ) +#endif #else if( isCrossedByVirtualBoundaries( xPos, yPos, width, height, clipTop, clipBottom, clipLeft, clipRight, numHorVirBndry, numVerVirBndry, horVirBndryPos, verVirBndryPos, cs.slice->getPPS() ) ) #endif @@ -2934,7 +2942,11 @@ void EncAdaptiveLoopFilter::alfReconstructor(CodingStructure& cs, const PelUnitB ctuEnableFlag |= m_ctuEnableFlag[compIdx][ctuIdx] > 0; } #if JVET_O0625_ALF_PADDING +#if JVET_P1006_PICTURE_HEADER + if( isCrossedByVirtualBoundaries( cs, xPos, yPos, width, height, alfBryList[0], alfBryList[1], alfBryList[2], alfBryList[3], numHorVirBndry, numVerVirBndry, horVirBndryPos, verVirBndryPos, cs.picHeader ) ) +#else if( isCrossedByVirtualBoundaries( cs, xPos, yPos, width, height, alfBryList[0], alfBryList[1], alfBryList[2], alfBryList[3], numHorVirBndry, numVerVirBndry, horVirBndryPos, verVirBndryPos, cs.slice->getPPS() ) ) +#endif #else if (ctuEnableFlag && isCrossedByVirtualBoundaries(xPos, yPos, width, height, clipTop, clipBottom, clipLeft, clipRight, numHorVirBndry, numVerVirBndry, horVirBndryPos, verVirBndryPos, cs.slice->getPPS())) #endif diff --git a/source/Lib/EncoderLib/EncCfg.h b/source/Lib/EncoderLib/EncCfg.h index e03c78000..a3265ebcb 100644 --- a/source/Lib/EncoderLib/EncCfg.h +++ b/source/Lib/EncoderLib/EncCfg.h @@ -589,6 +589,12 @@ protected: uint32_t m_maxNumIBCMergeCand; ///< Max number of IBC merge candidates ScalingListMode m_useScalingListId; ///< Using quantization matrix i.e. 0=off, 1=default, 2=file. std::string m_scalingListFileName; ///< quantization matrix file name +#if JVET_P1006_PICTURE_HEADER + bool m_sliceLevelRpl; ///< code reference picture lists in slice headers rather than picture header + bool m_sliceLevelDblk; ///< code deblocking filter parameters in slice headers rather than picture header + bool m_sliceLevelSao; ///< code SAO parameters in slice headers rather than picture header + bool m_sliceLevelAlf; ///< code ALF parameters in slice headers rather than picture header +#endif #if JVET_P0365_SCALING_MATRIX_LFNST bool m_disableScalingMatrixForLfnstBlks; #endif @@ -1520,6 +1526,16 @@ public: ScalingListMode getUseScalingListId () { return m_useScalingListId; } void setScalingListFileName ( const std::string &s ) { m_scalingListFileName = s; } const std::string& getScalingListFileName () const { return m_scalingListFileName; } +#if JVET_P1006_PICTURE_HEADER + void setSliceLevelRpl ( bool b ) { m_sliceLevelRpl = b; } + bool getSliceLevelRpl () { return m_sliceLevelRpl; } + void setSliceLevelDblk ( bool b ) { m_sliceLevelDblk = b; } + bool getSliceLevelDblk () { return m_sliceLevelDblk; } + void setSliceLevelSao ( bool b ) { m_sliceLevelSao = b; } + bool getSliceLevelSao () { return m_sliceLevelSao; } + void setSliceLevelAlf ( bool b ) { m_sliceLevelAlf = b; } + bool getSliceLevelAlf () { return m_sliceLevelAlf; } +#endif #if JVET_P0365_SCALING_MATRIX_LFNST void setDisableScalingMatrixForLfnstBlks(bool u) { m_disableScalingMatrixForLfnstBlks = u; } bool getDisableScalingMatrixForLfnstBlks() const { return m_disableScalingMatrixForLfnstBlks; } diff --git a/source/Lib/EncoderLib/EncCu.cpp b/source/Lib/EncoderLib/EncCu.cpp index ae0beda4d..09508c8c8 100644 --- a/source/Lib/EncoderLib/EncCu.cpp +++ b/source/Lib/EncoderLib/EncCu.cpp @@ -689,11 +689,19 @@ void EncCu::xCompressCU( CodingStructure*& tempCS, CodingStructure*& bestCS, Par m_cuChromaQpOffsetIdxPlus1 = 0; +#if JVET_P1006_PICTURE_HEADER + if( pps.getCuChromaQpOffsetEnabledFlag() ) +#else if( slice.getUseChromaQpAdj() ) +#endif { // TODO M0133 : double check encoder decisions with respect to chroma QG detection and actual encode int lgMinCuSize = sps.getLog2MinCodingBlockSize() + +#if JVET_P1006_PICTURE_HEADER + std::max<int>( 0, sps.getLog2DiffMaxMinCodingBlockSize() - int( slice.getCuChromaQpOffsetSubdiv()/2 ) ); +#else std::max<int>( 0, sps.getLog2DiffMaxMinCodingBlockSize() - int( pps.getCuChromaQpOffsetSubdiv()/2 ) ); +#endif m_cuChromaQpOffsetIdxPlus1 = ( ( uiLPelX >> lgMinCuSize ) + ( uiTPelY >> lgMinCuSize ) ) % ( pps.getChromaQpOffsetListLen() + 1 ); } @@ -1290,7 +1298,11 @@ void EncCu::xCheckModeSplit(CodingStructure *&tempCS, CodingStructure *&bestCS, m_CABACEstimator->getCtx() = SubCtx( Ctx::ModeConsFlag, ctxStartMC ); if (cost > bestCS->cost + bestCS->costDbOffset #if ENABLE_QPA_SUB_CTU +#if JVET_P1006_PICTURE_HEADER + || (m_pcEncCfg->getUsePerceptQPA() && !m_pcEncCfg->getUseRateCtrl() && pps.getUseDQP() && (slice.getCuQpDeltaSubdiv() > 0) && (split == CU_HORZ_SPLIT || split == CU_VERT_SPLIT) && +#else || (m_pcEncCfg->getUsePerceptQPA() && !m_pcEncCfg->getUseRateCtrl() && pps.getUseDQP() && (pps.getCuQpDeltaSubdiv() > 0) && (split == CU_HORZ_SPLIT || split == CU_VERT_SPLIT) && +#endif (currDepth == 0)) // force quad-split or no split at CTU level #endif ) @@ -2218,7 +2230,11 @@ void EncCu::xFillPCMBuffer( CodingUnit &cu ) const CPelBuf source = tu.cs->getOrgBuf( compArea ); PelBuf destination = tu.getPcmbuf( compID ); +#if JVET_P1006_PICTURE_HEADER + if (tu.cs->picHeader->getLmcsEnabledFlag() && m_pcReshape->getCTUFlag() && compID == COMPONENT_Y) +#else if (tu.cs->slice->getLmcsEnabledFlag() && m_pcReshape->getCTUFlag() && compID == COMPONENT_Y) +#endif { CompArea tmpArea(COMPONENT_Y, compArea.chromaFormat, Position(0, 0), compArea.size()); PelBuf tempOrgBuf = m_tmpStorageLCU->getBuf(tmpArea); @@ -2530,20 +2546,32 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& m_pcIntraSearch->switchBuffer(pu, COMPONENT_Y, pu.cs->getPredBuf(pu).Y(), m_pcIntraSearch->getPredictorPtr2(COMPONENT_Y, intraCnt)); } pu.cs->getPredBuf(pu).copyFrom(acMergeTmpBuffer[mergeCand]); +#if JVET_P1006_PICTURE_HEADER + if (pu.cs->picHeader->getLmcsEnabledFlag() && m_pcReshape->getCTUFlag()) +#else if (pu.cs->slice->getLmcsEnabledFlag() && m_pcReshape->getCTUFlag()) +#endif { pu.cs->getPredBuf(pu).Y().rspSignal(m_pcReshape->getFwdLUT()); } m_pcIntraSearch->geneWeightedPred(COMPONENT_Y, pu.cs->getPredBuf(pu).Y(), pu, m_pcIntraSearch->getPredictorPtr2(COMPONENT_Y, intraCnt)); // calculate cost +#if JVET_P1006_PICTURE_HEADER + if (pu.cs->picHeader->getLmcsEnabledFlag() && m_pcReshape->getCTUFlag()) +#else if (pu.cs->slice->getLmcsEnabledFlag() && m_pcReshape->getCTUFlag()) +#endif { pu.cs->getPredBuf(pu).Y().rspSignal(m_pcReshape->getInvLUT()); } distParam.cur = pu.cs->getPredBuf(pu).Y(); Distortion sadValue = distParam.distFunc(distParam); +#if JVET_P1006_PICTURE_HEADER + if (pu.cs->picHeader->getLmcsEnabledFlag() && m_pcReshape->getCTUFlag()) +#else if (pu.cs->slice->getLmcsEnabledFlag() && m_pcReshape->getCTUFlag()) +#endif { pu.cs->getPredBuf(pu).Y().rspSignal(m_pcReshape->getFwdLUT()); } @@ -2761,7 +2789,11 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& uint32_t bufIdx = 0; PelBuf tmpBuf = tempCS->getPredBuf(pu).Y(); tmpBuf.copyFrom(acMergeTmpBuffer[uiMergeCand].Y()); +#if JVET_P1006_PICTURE_HEADER + if (pu.cs->picHeader->getLmcsEnabledFlag() && m_pcReshape->getCTUFlag()) +#else if (pu.cs->slice->getLmcsEnabledFlag() && m_pcReshape->getCTUFlag()) +#endif { tmpBuf.rspSignal(m_pcReshape->getFwdLUT()); } @@ -2867,7 +2899,11 @@ void EncCu::xCheckRDCostMergeTriangle2Nx2N( CodingStructure *&tempCS, CodingStru const Slice &slice = *tempCS->slice; const SPS &sps = *tempCS->sps; +#if JVET_P1006_PICTURE_HEADER + if (slice.getPicHeader()->getMaxNumTriangleCand() < 2) +#else if (slice.getMaxNumTriangleCand() < 2) +#endif return; CHECK( slice.getSliceType() != B_SLICE, "Triangle mode is only applied to B-slices" ); @@ -2887,7 +2923,11 @@ void EncCu::xCheckRDCostMergeTriangle2Nx2N( CodingStructure *&tempCS, CodingStru PelUnitBuf triangleWeightedBuffer[TRIANGLE_MAX_NUM_CANDS]; static_vector<uint8_t, TRIANGLE_MAX_NUM_CANDS> triangleRdModeList; static_vector<double, TRIANGLE_MAX_NUM_CANDS> tianglecandCostList; +#if JVET_P1006_PICTURE_HEADER + uint8_t numTriangleCandComb = slice.getPicHeader()->getMaxNumTriangleCand() * (slice.getPicHeader()->getMaxNumTriangleCand() - 1) * 2; +#else uint8_t numTriangleCandComb = slice.getMaxNumTriangleCand() * (slice.getMaxNumTriangleCand() - 1) * 2; +#endif DistParam distParam; @@ -2915,7 +2955,11 @@ void EncCu::xCheckRDCostMergeTriangle2Nx2N( CodingStructure *&tempCS, CodingStru pu.regularMergeFlag = false; PU::getTriangleMergeCandidates( pu, triangleMrgCtx ); +#if JVET_P1006_PICTURE_HEADER + const uint8_t maxNumTriangleCand = pu.cs->picHeader->getMaxNumTriangleCand(); +#else const uint8_t maxNumTriangleCand = pu.cs->slice->getMaxNumTriangleCand(); +#endif for (uint8_t mergeCand = 0; mergeCand < maxNumTriangleCand; mergeCand++) { triangleBuffer[mergeCand] = m_acMergeBuffer[mergeCand].getBuf(localUnitArea); @@ -3236,7 +3280,11 @@ void EncCu::xCheckRDCostAffineMerge2Nx2N( CodingStructure *&tempCS, CodingStruct Distortion uiSad = distParam.distFunc( distParam ); uint32_t uiBitsCand = uiMergeCand + 1; +#if JVET_P1006_PICTURE_HEADER + if ( uiMergeCand == tempCS->picHeader->getMaxNumAffineMergeCand() - 1 ) +#else if ( uiMergeCand == tempCS->slice->getMaxNumAffineMergeCand() - 1 ) +#endif { uiBitsCand--; } @@ -3470,7 +3518,11 @@ void EncCu::xCheckRDCostIBCModeMerge2Nx2N(CodingStructure *&tempCS, CodingStruct Picture* refPic = pu.cu->slice->getPic(); const CPelBuf refBuf = refPic->getRecoBuf(pu.blocks[COMPONENT_Y]); const Pel* piRefSrch = refBuf.buf; +#if JVET_P1006_PICTURE_HEADER + if (tempCS->picHeader->getLmcsEnabledFlag() && m_pcReshape->getCTUFlag() ) +#else if (tempCS->slice->getLmcsEnabledFlag() && m_pcReshape->getCTUFlag() ) +#endif { const CompArea &area = cu.blocks[COMPONENT_Y]; CompArea tmpArea(COMPONENT_Y, area.chromaFormat, Position(0, 0), area.size()); @@ -3508,7 +3560,11 @@ void EncCu::xCheckRDCostIBCModeMerge2Nx2N(CodingStructure *&tempCS, CodingStruct Distortion sad = distParam.distFunc(distParam); unsigned int bitsCand = mergeCand + 1; +#if JVET_P1006_PICTURE_HEADER + if (mergeCand == tempCS->picHeader->getMaxNumMergeCand() - 1) +#else if (mergeCand == tempCS->slice->getMaxNumMergeCand() - 1) +#endif { bitsCand--; } @@ -4093,7 +4149,11 @@ void EncCu::xCalDebCost( CodingStructure &cs, Partitioner &partitioner, bool cal //Copy current CU's reco to Deblock Pic Buffer const CompArea& curCompArea = currCsArea.block( compId ); picDbBuf.getBuf( curCompArea ).copyFrom( cs.getRecoBuf( curCompArea ) ); +#if JVET_P1006_PICTURE_HEADER + if (cs.picHeader->getLmcsEnabledFlag() && m_pcReshape->getSliceReshaperInfo().getUseSliceReshaper() && isLuma(compId)) +#else if (cs.slice->getLmcsEnabledFlag() && m_pcReshape->getSliceReshaperInfo().getUseSliceReshaper() && isLuma(compId)) +#endif { picDbBuf.getBuf( curCompArea ).rspSignal( m_pcReshape->getInvLUT() ); } @@ -4103,7 +4163,11 @@ void EncCu::xCalDebCost( CodingStructure &cs, Partitioner &partitioner, bool cal { const CompArea& compArea = areaLeft.block(compId); picDbBuf.getBuf( compArea ).copyFrom( cs.picture->getRecoBuf( compArea ) ); +#if JVET_P1006_PICTURE_HEADER + if (cs.picHeader->getLmcsEnabledFlag() && m_pcReshape->getSliceReshaperInfo().getUseSliceReshaper() && isLuma(compId)) +#else if (cs.slice->getLmcsEnabledFlag() && m_pcReshape->getSliceReshaperInfo().getUseSliceReshaper() && isLuma(compId)) +#endif { picDbBuf.getBuf( compArea ).rspSignal( m_pcReshape->getInvLUT() ); } @@ -4113,7 +4177,11 @@ void EncCu::xCalDebCost( CodingStructure &cs, Partitioner &partitioner, bool cal { const CompArea& compArea = areaTop.block( compId ); picDbBuf.getBuf( compArea ).copyFrom( cs.picture->getRecoBuf( compArea ) ); +#if JVET_P1006_PICTURE_HEADER + if (cs.picHeader->getLmcsEnabledFlag() && m_pcReshape->getSliceReshaperInfo().getUseSliceReshaper() && isLuma(compId)) +#else if (cs.slice->getLmcsEnabledFlag() && m_pcReshape->getSliceReshaperInfo().getUseSliceReshaper() && isLuma(compId)) +#endif { picDbBuf.getBuf( compArea ).rspSignal( m_pcReshape->getInvLUT() ); } @@ -4183,7 +4251,11 @@ Distortion EncCu::getDistortionDb( CodingStructure &cs, CPelBuf org, CPelBuf rec m_pcRdCost->setChromaFormat(cs.sps->getChromaFormatIdc()); CPelBuf orgLuma = cs.picture->getOrigBuf( cs.area.blocks[COMPONENT_Y] ); if ( m_pcEncCfg->getLumaLevelToDeltaQPMapping().isEnabled() || ( +#if JVET_P1006_PICTURE_HEADER + m_pcEncCfg->getReshaper() && (cs.picHeader->getLmcsEnabledFlag() && m_pcReshape->getCTUFlag()))) +#else m_pcEncCfg->getReshaper() && (cs.slice->getLmcsEnabledFlag() && m_pcReshape->getCTUFlag()))) +#endif { if ( compID == COMPONENT_Y && !afterDb && !m_pcEncCfg->getLumaLevelToDeltaQPMapping().isEnabled()) { @@ -4198,7 +4270,11 @@ Distortion EncCu::getDistortionDb( CodingStructure &cs, CPelBuf org, CPelBuf rec dist += m_pcRdCost->getDistPart( org, reco, cs.sps->getBitDepth( toChannelType( compID ) ), compID, DF_SSE_WTD, &orgLuma ); } } +#if JVET_P1006_PICTURE_HEADER + else if (m_pcEncCfg->getReshaper() && cs.picHeader->getLmcsEnabledFlag() && cs.slice->isIntra()) //intra slice +#else else if (m_pcEncCfg->getReshaper() && cs.slice->getLmcsEnabledFlag() && cs.slice->isIntra()) //intra slice +#endif { if ( compID == COMPONENT_Y && afterDb ) { @@ -4695,7 +4771,11 @@ void EncCu::xReuseCachedResult( CodingStructure *&tempCS, CodingStructure *&best #if WCG_EXT if (m_pcEncCfg->getLumaLevelToDeltaQPMapping().isEnabled() || ( +#if JVET_P1006_PICTURE_HEADER + m_pcEncCfg->getReshaper() && (tempCS->picHeader->getLmcsEnabledFlag() && m_pcReshape->getCTUFlag()))) +#else m_pcEncCfg->getReshaper() && (tempCS->slice->getLmcsEnabledFlag() && m_pcReshape->getCTUFlag()))) +#endif { const CPelBuf orgLuma = tempCS->getOrgBuf(tempCS->area.blocks[COMPONENT_Y]); if (compID == COMPONENT_Y && !(m_pcEncCfg->getLumaLevelToDeltaQPMapping().isEnabled())) diff --git a/source/Lib/EncoderLib/EncGOP.cpp b/source/Lib/EncoderLib/EncGOP.cpp index 2df410517..c3c4526fc 100644 --- a/source/Lib/EncoderLib/EncGOP.cpp +++ b/source/Lib/EncoderLib/EncGOP.cpp @@ -421,6 +421,18 @@ int EncGOP::xWriteParameterSets( AccessUnit &accessUnit, Slice *slice, const boo return actualTotalBits; } +#if JVET_P1006_PICTURE_HEADER +int EncGOP::xWritePicHeader( AccessUnit &accessUnit, PicHeader *picHeader ) +{ + OutputNALUnit nalu(NAL_UNIT_PH); + m_HLSWriter->setBitstream( &nalu.m_Bitstream ); + nalu.m_temporalId = accessUnit.temporalId; + m_HLSWriter->codePictureHeader( picHeader ); + accessUnit.push_back(new NALUnitEBSP(nalu)); + return (int)(accessUnit.back()->m_nalUnitData.str().size()) * 8; +} + +#endif void EncGOP::xWriteAccessUnitDelimiter (AccessUnit &accessUnit, Slice *slice) { AUDWriter audWriter; @@ -1546,8 +1558,12 @@ void trySkipOrDecodePicture( bool& decPic, bool& encPic, const EncCfg& cfg, Pict // patch IDR-slice to CRA-Intra-slice pcPic->slices[ i ]->setNalUnitType ( slice0.getNalUnitType() ); pcPic->slices[ i ]->setLastIDR ( slice0.getLastIDR() ); +#if JVET_P1006_PICTURE_HEADER + if ( pcPic->cs->picHeader->getEnableTMVPFlag() ) +#else pcPic->slices[ i ]->setEnableTMVPFlag ( slice0.getEnableTMVPFlag() ); if ( slice0.getEnableTMVPFlag() ) +#endif { pcPic->slices[ i ]->setColFromL0Flag( slice0.getColFromL0Flag() ); pcPic->slices[ i ]->setColRefIdx ( slice0.getColRefIdx() ); @@ -1776,7 +1792,11 @@ void EncGOP::xPicInitRateControl(int &estimatedBits, int gopId, double &lambda, m_pcSliceEncoder->resetQP( pic, sliceQP, lambda ); } +#if JVET_P1006_PICTURE_HEADER +void EncGOP::xPicInitLMCS(Picture *pic, PicHeader *picHeader, Slice *slice) +#else void EncGOP::xPicInitLMCS(Picture *pic, Slice *slice) +#endif { if (slice->getSPS()->getUseReshaper()) { @@ -1866,9 +1886,15 @@ void EncGOP::xPicInitLMCS(Picture *pic, Slice *slice) } } +#if JVET_P1006_PICTURE_HEADER + //set all necessary information in LMCS APS and picture header + picHeader->setLmcsEnabledFlag(m_pcReshaper->getSliceReshaperInfo().getUseSliceReshaper()); + picHeader->setLmcsChromaResidualScaleFlag(m_pcReshaper->getSliceReshaperInfo().getSliceReshapeChromaAdj() == 1); +#else //set all necessary information in LMCS APS and slice slice->setLmcsEnabledFlag(m_pcReshaper->getSliceReshaperInfo().getUseSliceReshaper()); slice->setLmcsChromaResidualScaleFlag(m_pcReshaper->getSliceReshaperInfo().getSliceReshapeChromaAdj() == 1); +#endif if (m_pcReshaper->getSliceReshaperInfo().getSliceReshapeModelPresentFlag()) { #if JVET_N0278_FIXES @@ -1876,8 +1902,13 @@ void EncGOP::xPicInitLMCS(Picture *pic, Slice *slice) #else int apsId = 0; #endif +#if JVET_P1006_PICTURE_HEADER + picHeader->setLmcsAPSId(apsId); + APS* lmcsAPS = picHeader->getLmcsAPS(); +#else slice->setLmcsAPSId(apsId); APS* lmcsAPS = slice->getLmcsAPS(); +#endif if (lmcsAPS == nullptr) { ParameterSetMap<APS> *apsMap = m_pcEncLib->getApsMap(); @@ -1888,7 +1919,11 @@ void EncGOP::xPicInitLMCS(Picture *pic, Slice *slice) lmcsAPS->setAPSId(apsId); lmcsAPS->setAPSType(LMCS_APS); } +#if JVET_P1006_PICTURE_HEADER + picHeader->setLmcsAPS(lmcsAPS); +#else slice->setLmcsAPS(lmcsAPS); +#endif } //m_pcReshaper->copySliceReshaperInfo(lmcsAPS->getReshaperAPSInfo(), m_pcReshaper->getSliceReshaperInfo()); SliceReshapeInfo& tInfo = lmcsAPS->getReshaperAPSInfo(); @@ -1904,14 +1939,22 @@ void EncGOP::xPicInitLMCS(Picture *pic, Slice *slice) } +#if JVET_P1006_PICTURE_HEADER + if (picHeader->getLmcsEnabledFlag()) +#else if (slice->getLmcsEnabledFlag()) +#endif { #if JVET_N0278_FIXES int apsId = std::min<int>( 3, m_pcEncLib->getLayerId() ); //VS: layerId should be converted to laeyrIdx #else int apsId = 0; #endif +#if JVET_P1006_PICTURE_HEADER + picHeader->setLmcsAPSId(apsId); +#else slice->setLmcsAPSId(apsId); +#endif } } else @@ -1935,6 +1978,9 @@ void EncGOP::compressGOP( int iPOCLast, int iNumPicRcvd, PicList& rcListPic, // TODO: Split this function up. Picture* pcPic = NULL; +#if JVET_P1006_PICTURE_HEADER + PicHeader* picHeader = NULL; +#endif Slice* pcSlice; OutputBitstream *pcBitstreamRedirect; pcBitstreamRedirect = new OutputBitstream; @@ -2028,6 +2074,10 @@ void EncGOP::compressGOP( int iPOCLast, int iNumPicRcvd, PicList& rcListPic, accessUnit.temporalId = m_pcCfg->getGOPEntry( iGOPid ).m_temporalId; xGetBuffer( rcListPic, rcListPicYuvRecOut, iNumPicRcvd, iTimeOffset, pcPic, pocCurr, isField ); +#if JVET_P1006_PICTURE_HEADER + picHeader = pcPic->cs->picHeader; + picHeader->setSplitConsOverrideFlag(false); +#endif #if ER_CHROMA_QP_WCG_PPS // th this is a hot fix for the choma qp control @@ -2083,8 +2133,10 @@ void EncGOP::compressGOP( int iPOCLast, int iNumPicRcvd, PicList& rcListPic, pcSlice->setLastIDR(m_iLastIDR); pcSlice->setIndependentSliceIdx(0); +#if !JVET_P1006_PICTURE_HEADER //set default slice level flag to the same as SPS level flag pcSlice->setLFCrossSliceBoundaryFlag( pcSlice->getPPS()->getLoopFilterAcrossSlicesEnabledFlag() ); +#endif if(pcSlice->getSliceType()==B_SLICE&&m_pcCfg->getGOPEntry(iGOPid).m_sliceType=='P') { @@ -2289,6 +2341,22 @@ void EncGOP::compressGOP( int iPOCLast, int iNumPicRcvd, PicList& rcListPic, if( refLayer >= 0 && m_uiNumBlk[refLayer] != 0 ) { +#if JVET_P1006_PICTURE_HEADER + picHeader->setSplitConsOverrideFlag(true); + double dBlkSize = sqrt( ( double ) m_uiBlkSize[refLayer] / m_uiNumBlk[refLayer] ); + if( dBlkSize < AMAXBT_TH32 || pcPic->cs->sps->getCTUSize()==32 ) + { + picHeader->setMaxBTSize( 1, 32 > MAX_BT_SIZE_INTER ? MAX_BT_SIZE_INTER : 32 ); + } + else if( dBlkSize < AMAXBT_TH64 || pcPic->cs->sps->getCTUSize()==64 ) + { + picHeader->setMaxBTSize( 1, 64 > MAX_BT_SIZE_INTER ? MAX_BT_SIZE_INTER : 64 ); + } + else + { + picHeader->setMaxBTSize( 1, 128 > MAX_BT_SIZE_INTER ? MAX_BT_SIZE_INTER : 128 ); + } +#else pcSlice->setSplitConsOverrideFlag(true); double dBlkSize = sqrt( ( double ) m_uiBlkSize[refLayer] / m_uiNumBlk[refLayer] ); if( dBlkSize < AMAXBT_TH32 ) @@ -2303,6 +2371,7 @@ void EncGOP::compressGOP( int iPOCLast, int iNumPicRcvd, PicList& rcListPic, { pcSlice->setMaxBTSize( 128 > MAX_BT_SIZE_INTER ? MAX_BT_SIZE_INTER : 128 ); } +#endif m_uiBlkSize[refLayer] = 0; m_uiNumBlk [refLayer] = 0; @@ -2381,12 +2450,20 @@ void EncGOP::compressGOP( int iPOCLast, int iNumPicRcvd, PicList& rcListPic, #endif if (iGOPid == 0) // first picture in SOP (i.e. forward B) { +#if JVET_P1006_PICTURE_HEADER + picHeader->setEnableTMVPFlag(0); +#else pcSlice->setEnableTMVPFlag(0); +#endif } else { // Note: pcSlice->getColFromL0Flag() is assumed to be always 0 and getcolRefIdx() is always 0. +#if JVET_P1006_PICTURE_HEADER + picHeader->setEnableTMVPFlag(1); +#else pcSlice->setEnableTMVPFlag(1); +#endif } } #if JVET_P0206_TMVP_flags @@ -2395,20 +2472,36 @@ void EncGOP::compressGOP( int iPOCLast, int iNumPicRcvd, PicList& rcListPic, else if (m_pcEncLib->getTMVPModeId() == 1 && m_pcEncLib->getPPSTemporalMVPEnabledIdc() != 1) #endif { +#if JVET_P1006_PICTURE_HEADER + picHeader->setEnableTMVPFlag(1); +#else pcSlice->setEnableTMVPFlag(1); +#endif } else { +#if JVET_P1006_PICTURE_HEADER + picHeader->setEnableTMVPFlag(0); +#else pcSlice->setEnableTMVPFlag(0); +#endif } // disable TMVP when current picture is the only ref picture if (pcSlice->isIRAP() && pcSlice->getSPS()->getIBCFlag()) { +#if JVET_P1006_PICTURE_HEADER + picHeader->setEnableTMVPFlag(0); +#else pcSlice->setEnableTMVPFlag(0); +#endif } +#if JVET_P1006_PICTURE_HEADER + if( pcSlice->getSliceType() != I_SLICE && picHeader->getEnableTMVPFlag() ) +#else if( pcSlice->getSliceType() != I_SLICE && pcSlice->getEnableTMVPFlag() ) +#endif { int colRefIdxL0 = -1, colRefIdxL1 = -1; @@ -2473,11 +2566,19 @@ void EncGOP::compressGOP( int iPOCLast, int iNumPicRcvd, PicList& rcListPic, } else { +#if JVET_P1006_PICTURE_HEADER + picHeader->setEnableTMVPFlag( 0 ); +#else pcSlice->setEnableTMVPFlag( 0 ); +#endif } } +#if JVET_P1006_PICTURE_HEADER + pcSlice->scaleRefPicList( scaledRefPic, pcPic->cs->picHeader, m_pcEncLib->getApss(), picHeader->getLmcsAPS(), picHeader->getScalingListAPS(), false ); +#else pcSlice->scaleRefPicList( scaledRefPic, m_pcEncLib->getApss(), pcSlice->getLmcsAPS(), pcSlice->getscalingListAPS(), false ); +#endif // set adaptive search range for non-intra-slices if (m_pcCfg->getUseASR() && !pcSlice->isIRAP()) @@ -2504,15 +2605,27 @@ void EncGOP::compressGOP( int iPOCLast, int iNumPicRcvd, PicList& rcListPic, } if(bGPBcheck) { +#if JVET_P1006_PICTURE_HEADER + picHeader->setMvdL1ZeroFlag(true); +#else pcSlice->setMvdL1ZeroFlag(true); +#endif } else { +#if JVET_P1006_PICTURE_HEADER + picHeader->setMvdL1ZeroFlag(false); +#else pcSlice->setMvdL1ZeroFlag(false); +#endif } if ( pcSlice->getSPS()->getUseSMVD() && pcSlice->getCheckLDC() == false +#if JVET_P1006_PICTURE_HEADER + && picHeader->getMvdL1ZeroFlag() == false +#else && pcSlice->getMvdL1ZeroFlag() == false +#endif ) { int currPOC = pcSlice->getPOC(); @@ -2616,7 +2729,11 @@ void EncGOP::compressGOP( int iPOCLast, int iNumPicRcvd, PicList& rcListPic, pcPic->m_uEnerHpCtu.resize (numberOfCtusInFrame); pcPic->m_iOffsetCtu.resize (numberOfCtusInFrame); #if ENABLE_QPA_SUB_CTU +#if JVET_P1006_PICTURE_HEADER + if (pcSlice->getPPS()->getUseDQP() && pcSlice->getCuQpDeltaSubdiv() > 0) +#else if (pcSlice->getPPS()->getUseDQP() && pcSlice->getPPS()->getCuQpDeltaSubdiv() > 0) +#endif { const PreCalcValues &pcv = *pcPic->cs->pcv; const unsigned mtsLog2 = (unsigned)floorLog2(std::min (pcPic->cs->sps->getMaxTbSize(), pcv.maxCUWidth)); @@ -2660,25 +2777,56 @@ void EncGOP::compressGOP( int iPOCLast, int iNumPicRcvd, PicList& rcListPic, m_pcSliceEncoder->setUpLambda(pcSlice, pcSlice->getLambdas()[0], pcSlice->getSliceQp()); } +#if JVET_P1006_PICTURE_HEADER + xPicInitLMCS(pcPic, picHeader, pcSlice); +#else xPicInitLMCS(pcPic, pcSlice); +#endif if( pcSlice->getSPS()->getScalingListFlag() && m_pcCfg->getUseScalingListId() == SCALING_LIST_FILE_READ ) { +#if JVET_P1006_PICTURE_HEADER + picHeader->setScalingListPresentFlag( true ); +#else pcSlice->setscalingListPresentFlag( true ); +#endif #if JVET_N0278_FIXES int apsId = std::min<int>( 7, m_pcEncLib->getLayerId() ); //VS: layerId should be converted to laeyrIdx #else int apsId = 0; #endif +#if JVET_P1006_PICTURE_HEADER + picHeader->setScalingListAPSId( apsId ); +#else pcSlice->setscalingListAPSId( apsId ); +#endif ParameterSetMap<APS> *apsMap = m_pcEncLib->getApsMap(); APS* scalingListAPS = apsMap->getPS( ( apsId << NUM_APS_TYPE_LEN ) + SCALING_LIST_APS ); assert( scalingListAPS != NULL ); +#if JVET_P1006_PICTURE_HEADER + picHeader->setScalingListAPS( scalingListAPS ); +#else pcSlice->setscalingListAPS( scalingListAPS ); +#endif } +#if JVET_P1006_PICTURE_HEADER + pcPic->cs->picHeader->setPic(pcPic); + pcPic->cs->picHeader->setValid(); + if(pcPic->cs->sps->getFpelMmvdEnabledFlag()) + { + // cannot set pic_fpel_mmvd_enabled_flag at slice level - need new picture-level version of checkDisFracMmvd algorithm? + // m_pcSliceEncoder->checkDisFracMmvd( pcPic, 0, numberOfCtusInFrame ); + bool useIntegerMVD = (pcPic->lwidth()*pcPic->lheight() > 1920 * 1080); + pcPic->cs->picHeader->setDisFracMMVD( useIntegerMVD ); + } + if (pcSlice->getSPS()->getJointCbCrEnabledFlag()) + { + m_pcSliceEncoder->setJointCbCrModes(*pcPic->cs, Position(0, 0), pcPic->cs->area.lumaSize()); + } +#endif if( encPic ) // now compress (trial encode) the various slice segments (slices, and dependent slices) { @@ -2736,7 +2884,11 @@ void EncGOP::compressGOP( int iPOCLast, int iNumPicRcvd, PicList& rcListPic, if (pcSlice->getSPS()->getUseReshaper() && m_pcReshaper->getSliceReshaperInfo().getUseSliceReshaper()) { +#if JVET_P1006_PICTURE_HEADER + picHeader->setLmcsEnabledFlag(true); +#else pcSlice->setLmcsEnabledFlag(true); +#endif #if JVET_N0278_FIXES int apsId = std::min<int>( 3, m_pcEncLib->getLayerId() ); //VS: layerId should be converted to laeyrIdx @@ -2744,6 +2896,9 @@ void EncGOP::compressGOP( int iPOCLast, int iNumPicRcvd, PicList& rcListPic, int apsId = 0; #endif +#if JVET_P1006_PICTURE_HEADER + picHeader->setLmcsAPSId(apsId); +#else pcSlice->setLmcsAPSId(apsId); for (int s = 0; s < uiNumSliceSegments; s++) { @@ -2755,6 +2910,7 @@ void EncGOP::compressGOP( int iPOCLast, int iNumPicRcvd, PicList& rcListPic, pcPic->slices[s]->setLmcsAPSId(pcSlice->getLmcsAPSId()); } } +#endif CHECK((m_pcReshaper->getRecReshaped() == false), "Rec picture is not reshaped!"); pcPic->getRecoBuf(COMPONENT_Y).rspSignal(m_pcReshaper->getInvLUT()); m_pcReshaper->setRecReshaped(false); @@ -2785,10 +2941,17 @@ void EncGOP::compressGOP( int iPOCLast, int iNumPicRcvd, PicList& rcListPic, if( pcSlice->getSPS()->getScalingListFlag() && m_pcCfg->getUseScalingListId() == SCALING_LIST_FILE_READ ) { +#if JVET_P1006_PICTURE_HEADER + picHeader->setScalingListPresentFlag(true); + int apsId = 0; + picHeader->setScalingListAPSId( apsId ); +#else pcSlice->setscalingListPresentFlag( true ); int apsId = 0; pcSlice->setscalingListAPSId( apsId ); +#endif } +#if !JVET_P1006_PICTURE_HEADER for( int s = 0; s < uiNumSliceSegments; s++ ) { pcPic->slices[ s ]->setscalingListPresentFlag( pcSlice->getscalingListPresentFlag() ); @@ -2797,6 +2960,7 @@ void EncGOP::compressGOP( int iPOCLast, int iNumPicRcvd, PicList& rcListPic, pcPic->slices[ s ]->setscalingListAPSId( pcSlice->getscalingListAPSId() ); } } +#endif // SAO parameter estimation using non-deblocked pixels for CTU bottom and right boundary areas if( pcSlice->getSPS()->getSAOEnabledFlag() && m_pcCfg->getSaoCtuBoundary() ) @@ -2966,7 +3130,11 @@ void EncGOP::compressGOP( int iPOCLast, int iNumPicRcvd, PicList& rcListPic, if (pcSlice->getSPS()->getUseReshaper()) { //only 1 LMCS data for 1 picture +#if JVET_P1006_PICTURE_HEADER + int apsId = picHeader->getLmcsAPSId(); +#else int apsId = pcSlice->getLmcsAPSId(); +#endif ParameterSetMap<APS> *apsMap = m_pcEncLib->getApsMap(); APS* aps = apsMap->getPS((apsId << NUM_APS_TYPE_LEN) + LMCS_APS); bool writeAPS = aps && apsMap->getChangedFlag((apsId << NUM_APS_TYPE_LEN) + LMCS_APS); @@ -2986,14 +3154,22 @@ void EncGOP::compressGOP( int iPOCLast, int iNumPicRcvd, PicList& rcListPic, #endif #endif apsMap->clearChangedFlag((apsId << NUM_APS_TYPE_LEN) + LMCS_APS); +#if JVET_P1006_PICTURE_HEADER + CHECK(aps != picHeader->getLmcsAPS(), "Wrong LMCS APS pointer in compressGOP"); +#else CHECK(aps != pcSlice->getLmcsAPS(), "Wrong LMCS APS pointer in compressGOP"); +#endif } } // only 1 SCALING LIST data for 1 picture if( pcSlice->getSPS()->getScalingListFlag() && ( m_pcCfg->getUseScalingListId() == SCALING_LIST_FILE_READ ) ) { +#if JVET_P1006_PICTURE_HEADER + int apsId = picHeader->getScalingListAPSId(); +#else int apsId = pcSlice->getscalingListAPSId(); +#endif ParameterSetMap<APS> *apsMap = m_pcEncLib->getApsMap(); APS* aps = apsMap->getPS( ( apsId << NUM_APS_TYPE_LEN ) + SCALING_LIST_APS ); bool writeAPS = aps && apsMap->getChangedFlag( ( apsId << NUM_APS_TYPE_LEN ) + SCALING_LIST_APS ); @@ -3013,7 +3189,11 @@ void EncGOP::compressGOP( int iPOCLast, int iNumPicRcvd, PicList& rcListPic, #endif #endif apsMap->clearChangedFlag( ( apsId << NUM_APS_TYPE_LEN ) + SCALING_LIST_APS ); +#if JVET_P1006_PICTURE_HEADER + CHECK( aps != picHeader->getScalingListAPS(), "Wrong SCALING LIST APS pointer in compressGOP" ); +#else CHECK( aps != pcSlice->getscalingListAPS(), "Wrong SCALING LIST APS pointer in compressGOP" ); +#endif } } @@ -3077,6 +3257,89 @@ void EncGOP::compressGOP( int iPOCLast, int iNumPicRcvd, PicList& rcListPic, pcSlice->setRPL0idx(pcPic->slices[0]->getRPL0idx()); pcSlice->setRPL1idx(pcPic->slices[0]->getRPL1idx()); +#if JVET_P1006_PICTURE_HEADER + pcSlice->setNoIncorrectPicOutputFlag(false); + if (pcSlice->isIRAP()) + { + if (pcSlice->getNalUnitType() >= NAL_UNIT_CODED_SLICE_IDR_W_RADL && pcSlice->getNalUnitType() <= NAL_UNIT_CODED_SLICE_IDR_N_LP) + { + pcSlice->setNoIncorrectPicOutputFlag(true); + } + //the inference for NoOutputPriorPicsFlag + // KJS: This cannot happen at the encoder + if (!m_bFirst && (pcSlice->isIRAP() || pcSlice->getNalUnitType() >= NAL_UNIT_CODED_SLICE_GDR) && pcSlice->getNoIncorrectPicOutputFlag()) + { + if (pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_CRA || pcSlice->getNalUnitType() >= NAL_UNIT_CODED_SLICE_GDR) + { + picHeader->setNoOutputOfPriorPicsFlag(true); + } + } + } + + // code picture header before first slice + if(sliceSegmentIdxCount == 0) + { + // code RPL in picture header or slice headers + if( !m_pcCfg->getSliceLevelRpl() && (!pcSlice->getIdrPicFlag() || pcSlice->getSPS()->getIDRRefParamListPresent()) ) + { + picHeader->setPicRplPresentFlag(true); + picHeader->setRPL0idx(pcSlice->getRPL0idx()); + picHeader->setRPL1idx(pcSlice->getRPL1idx()); + picHeader->setRPL0(pcSlice->getRPL0()); + picHeader->setRPL1(pcSlice->getRPL1()); + *picHeader->getLocalRPL0() = *pcSlice->getLocalRPL0(); + *picHeader->getLocalRPL1() = *pcSlice->getLocalRPL1(); + } + else { + picHeader->setPicRplPresentFlag(false); + } + + // code DBLK in picture header or slice headers + if( !m_pcCfg->getSliceLevelDblk() ) + { + picHeader->setDeblockingFilterOverridePresentFlag( true ); + picHeader->setDeblockingFilterOverrideFlag ( pcSlice->getDeblockingFilterOverrideFlag() ); + picHeader->setDeblockingFilterDisable ( pcSlice->getDeblockingFilterDisable() ); + picHeader->setDeblockingFilterBetaOffsetDiv2 ( pcSlice->getDeblockingFilterBetaOffsetDiv2() ); + picHeader->setDeblockingFilterTcOffsetDiv2 ( pcSlice->getDeblockingFilterTcOffsetDiv2() ); + } + else { + picHeader->setDeblockingFilterOverridePresentFlag( false ); + } + + // code SAO parameters in picture header or slice headers + if( !m_pcCfg->getSliceLevelSao() ) + { + picHeader->setSaoEnabledPresentFlag( true ); + picHeader->setSaoEnabledFlag(CHANNEL_TYPE_LUMA, pcSlice->getSaoEnabledFlag(CHANNEL_TYPE_LUMA )); + picHeader->setSaoEnabledFlag(CHANNEL_TYPE_CHROMA, pcSlice->getSaoEnabledFlag(CHANNEL_TYPE_CHROMA)); + } + else { + picHeader->setSaoEnabledPresentFlag( false ); + } + + // code ALF parameters in picture header or slice headers + if( !m_pcCfg->getSliceLevelAlf() ) + { + picHeader->setAlfEnabledPresentFlag( true ); + picHeader->setAlfEnabledFlag(COMPONENT_Y, pcSlice->getTileGroupAlfEnabledFlag(COMPONENT_Y ) ); + picHeader->setAlfEnabledFlag(COMPONENT_Cb, pcSlice->getTileGroupAlfEnabledFlag(COMPONENT_Cb) ); + picHeader->setAlfEnabledFlag(COMPONENT_Cr, pcSlice->getTileGroupAlfEnabledFlag(COMPONENT_Cr) ); + picHeader->setNumAlfAps(pcSlice->getTileGroupNumAps()); + picHeader->setAlfAPSs(pcSlice->getTileGroupApsIdLuma()); + picHeader->setAlfApsIdChroma(pcSlice->getTileGroupApsIdChroma()); + } + else { + picHeader->setAlfEnabledPresentFlag( false ); + } + + pcPic->cs->picHeader->setPic(pcPic); + pcPic->cs->picHeader->setValid(); + actualTotalBits += xWritePicHeader(accessUnit, pcPic->cs->picHeader); + } + pcSlice->setPicHeader( pcPic->cs->picHeader ); + +#endif for ( uint32_t ui = 0 ; ui < numSubstreams; ui++ ) { substreamsOut[ui].clear(); @@ -3090,6 +3353,7 @@ void EncGOP::compressGOP( int iPOCLast, int iNumPicRcvd, PicList& rcListPic, #endif m_HLSWriter->setBitstream( &nalu.m_Bitstream ); +#if !JVET_P1006_PICTURE_HEADER pcSlice->setNoIncorrectPicOutputFlag(false); if (pcSlice->isIRAP()) { @@ -3107,6 +3371,7 @@ void EncGOP::compressGOP( int iPOCLast, int iNumPicRcvd, PicList& rcListPic, } } } +#endif tmpBitsBeforeWriting = m_HLSWriter->getNumberOfWrittenBits(); m_HLSWriter->codeSliceHeader( pcSlice ); @@ -4122,7 +4387,11 @@ void EncGOP::xCalculateAddPSNR(Picture* pcPic, PelUnitBuf cPicD, const AccessUni { const std::pair<int, int>& scaleRatio = pcSlice->getScalingRatio( RefPicList( iRefList ), iRefIndex ); +#if JVET_P1006_PICTURE_HEADER + if( pcPic->cs->picHeader->getEnableTMVPFlag() && pcSlice->getColFromL0Flag() == bool(1 - iRefList) && pcSlice->getColRefIdx() == iRefIndex ) +#else if( pcSlice->getEnableTMVPFlag() && pcSlice->getColFromL0Flag() == bool(1 - iRefList) && pcSlice->getColRefIdx() == iRefIndex ) +#endif { if ( scaleRatio.first != 1 << SCALE_RATIO_BITS || scaleRatio.second != 1 << SCALE_RATIO_BITS ) msg( NOTICE, "%dc(%1.2lfx, %1.2lfx) ", pcSlice->getRefPOC( RefPicList( iRefList ), iRefIndex ), double( scaleRatio.first ) / ( 1 << SCALE_RATIO_BITS ), double( scaleRatio.second ) / ( 1 << SCALE_RATIO_BITS ) ); diff --git a/source/Lib/EncoderLib/EncGOP.h b/source/Lib/EncoderLib/EncGOP.h index f49e2c773..bec59665a 100644 --- a/source/Lib/EncoderLib/EncGOP.h +++ b/source/Lib/EncoderLib/EncGOP.h @@ -266,7 +266,11 @@ protected: ); void xPicInitHashME( Picture *pic, const PPS *pps, PicList &rcListPic ); void xPicInitRateControl(int &estimatedBits, int gopId, double &lambda, Picture *pic, Slice *slice); +#if JVET_P1006_PICTURE_HEADER + void xPicInitLMCS (Picture *pic, PicHeader *picHeader, Slice *slice); +#else void xPicInitLMCS (Picture *pic, Slice *slice); +#endif void xGetBuffer ( PicList& rcListPic, std::list<PelUnitBuf*>& rcListPicYuvRecOut, int iNumPicRcvd, int iTimeOffset, Picture*& rpcPic, int pocCurr, bool isField ); @@ -330,6 +334,9 @@ protected: int xWriteAPS( AccessUnit &accessUnit, APS *aps, const int layerId ); #endif int xWriteParameterSets (AccessUnit &accessUnit, Slice *slice, const bool bSeqFirst); +#if JVET_P1006_PICTURE_HEADER + int xWritePicHeader( AccessUnit &accessUnit, PicHeader *picHeader ); +#endif void applyDeblockingFilterMetric( Picture* pcPic, uint32_t uiNumSlices ); #if W0038_DB_OPT diff --git a/source/Lib/EncoderLib/EncLib.cpp b/source/Lib/EncoderLib/EncLib.cpp index c5bc99a5a..4e5512c2e 100644 --- a/source/Lib/EncoderLib/EncLib.cpp +++ b/source/Lib/EncoderLib/EncLib.cpp @@ -327,6 +327,9 @@ void EncLib::init( bool isFieldCoding, AUWriterIf* auWriterIf ) xInitPPS(pps2, sps0); xInitPPSforLT(pps2); } +#if JVET_P1006_PICTURE_HEADER + xInitPicHeader(m_picHeader, sps0, pps0); +#endif // initialize processing unit classes m_cGOPEncoder. init( this ); @@ -449,7 +452,11 @@ void EncLib::init( bool isFieldCoding, AUWriterIf* auWriterIf ) picBg->create( sps0.getChromaFormatIdc(), Size( pps0.getPicWidthInLumaSamples(), pps0.getPicHeightInLumaSamples() ), sps0.getMaxCUWidth(), sps0.getMaxCUWidth() + 16, false ); #endif picBg->getRecoBuf().fill(0); +#if JVET_P1006_PICTURE_HEADER + picBg->finalInit( sps0, pps0, &m_picHeader, m_apss, m_lmcsAPS, m_scalinglistAPS ); +#else picBg->finalInit( sps0, pps0, m_apss, m_lmcsAPS, m_scalinglistAPS ); +#endif pps0.setNumBricksInPic((int)picBg->brickMap->bricks.size()); picBg->allocateNewSlice(); picBg->createSpliceIdx(pps0.pcv->sizeInCtus); @@ -603,7 +610,11 @@ bool EncLib::encodePrep( bool flush, PelStorage* pcPicYuvOrg, PelStorage* cPicYu const SPS *sps = m_spsMap.getPS( pps->getSPSId() ); picCurr->M_BUFS( 0, PIC_ORIGINAL ).copyFrom( m_cGOPEncoder.getPicBg()->getRecoBuf() ); +#if JVET_P1006_PICTURE_HEADER + picCurr->finalInit( *sps, *pps, &m_picHeader, m_apss, m_lmcsAPS, m_scalinglistAPS ); +#else picCurr->finalInit( *sps, *pps, m_apss, m_lmcsAPS, m_scalinglistAPS ); +#endif picCurr->poc = m_iPOCLast - 1; m_iPOCLast -= 2; if( getUseAdaptiveQP() ) @@ -692,8 +703,11 @@ 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 + pcPicCurr->finalInit( *pSPS, *pPPS, &m_picHeader, m_apss, m_lmcsAPS, m_scalinglistAPS ); +#else pcPicCurr->finalInit( *pSPS, *pPPS, m_apss, m_lmcsAPS, m_scalinglistAPS ); +#endif PPS *ptrPPS = ( ppsID < 0 ) ? m_ppsMap.getFirstPS() : m_ppsMap.getPS( ppsID ); ptrPPS->setNumBricksInPic( (int)pcPicCurr->brickMap->bricks.size() ); @@ -790,7 +804,11 @@ void EncLib::encode( bool flush, PelStorage* pcPicYuvOrg, PelStorage* cPicYuvTru const SPS *sps = m_spsMap.getPS(pps->getSPSId()); picCurr->M_BUFS(0, PIC_ORIGINAL).copyFrom(m_cGOPEncoder.getPicBg()->getRecoBuf()); +#if JVET_P1006_PICTURE_HEADER + picCurr->finalInit( *sps, *pps, &m_picHeader, m_apss, m_lmcsAPS, m_scalinglistAPS ); +#else picCurr->finalInit( *sps, *pps, m_apss, m_lmcsAPS, m_scalinglistAPS ); +#endif picCurr->poc = m_iPOCLast - 1; m_iPOCLast -= 2; if (getUseAdaptiveQP()) @@ -873,7 +891,11 @@ void EncLib::encode( bool flush, PelStorage* pcPicYuvOrg, PelStorage* cPicYuvTru pcPicCurr->M_BUFS( 0, PIC_TRUE_ORIGINAL ).swap( *cPicYuvTrueOrg ); } +#if JVET_P1006_PICTURE_HEADER + pcPicCurr->finalInit( *pSPS, *pPPS, &m_picHeader, m_apss, m_lmcsAPS, m_scalinglistAPS ); +#else pcPicCurr->finalInit( *pSPS, *pPPS, m_apss, m_lmcsAPS, m_scalinglistAPS ); +#endif PPS *ptrPPS = ( ppsID < 0 ) ? m_ppsMap.getFirstPS() : m_ppsMap.getPS( ppsID ); ptrPPS->setNumBricksInPic( (int)pcPicCurr->brickMap->bricks.size() ); @@ -975,7 +997,11 @@ bool EncLib::encodePrep( bool flush, PelStorage* pcPicYuvOrg, PelStorage* pcPicY int ppsID = -1; // Use default PPS ID 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 + pcField->finalInit( *pSPS, *pPPS, &m_picHeader, m_apss, m_lmcsAPS, m_scalinglistAPS ); +#else pcField->finalInit( *pSPS, *pPPS, m_apss, m_lmcsAPS, m_scalinglistAPS ); +#endif } pcField->poc = m_iPOCLast; @@ -1063,7 +1089,11 @@ void EncLib::encode( bool flush, PelStorage* pcPicYuvOrg, PelStorage* pcPicYuvTr 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 + pcField->finalInit( *pSPS, *pPPS, &m_picHeader, m_apss, m_lmcsAPS, m_scalinglistAPS ); +#else pcField->finalInit( *pSPS, *pPPS, m_apss, m_lmcsAPS, m_scalinglistAPS ); +#endif } pcField->poc = m_iPOCLast; @@ -1183,7 +1213,11 @@ void EncLib::xGetNewPicBuffer ( std::list<PelUnitBuf*>& rcListPicYuvRecOut, Pict } if ( getUseAdaptiveQP() ) { +#if JVET_P1006_PICTURE_HEADER + const uint32_t iMaxDQPLayer = m_picHeader.getCuQpDeltaSubdivIntra()/2+1; +#else const uint32_t iMaxDQPLayer = pps.getCuQpDeltaSubdiv()/2+1; +#endif rpcPic->aqlayer.resize( iMaxDQPLayer ); for (uint32_t d = 0; d < iMaxDQPLayer; d++) { @@ -1479,6 +1513,28 @@ void EncLib::xInitSPS(SPS &sps) if (m_uiIntraPeriod < 0) sps.setRPL1CopyFromRPL0Flag(true); +#if JVET_P1006_PICTURE_HEADER + + sps.setNumSubPics(1); // TODO: modify for subpicture support + sps.setSubPicIdSignallingPresentFlag(false); + sps.setSubPicIdLen(16); + for(int picIdx=0; picIdx<MAX_NUM_SUB_PICS; picIdx++) + { + sps.setSubPicId(picIdx, picIdx); + } + + sps.setLoopFilterAcrossVirtualBoundariesDisabledFlag( m_loopFilterAcrossVirtualBoundariesDisabledFlag ); + sps.setNumVerVirtualBoundaries ( m_numVerVirtualBoundaries ); + sps.setNumHorVirtualBoundaries ( m_numHorVirtualBoundaries ); + for( unsigned int i = 0; i < m_numVerVirtualBoundaries; i++ ) + { + sps.setVirtualBoundariesPosX ( m_virtualBoundariesPosX[i], i ); + } + for( unsigned int i = 0; i < m_numHorVirtualBoundaries; i++ ) + { + sps.setVirtualBoundariesPosY ( m_virtualBoundariesPosY[i], i ); + } +#endif } void EncLib::xInitHrdParameters(SPS &sps) @@ -1512,6 +1568,15 @@ void EncLib::xInitPPS(PPS &pps, const SPS &sps) #endif pps.setPPSMaxNumMergeCandMinusMaxNumTriangleCandPlus1(getPPSMaxNumMergeCandMinusMaxNumTriangleCandPlus1()); +#if JVET_P1006_PICTURE_HEADER + pps.setNumSubPics(sps.getNumSubPics()); + pps.setSubPicIdSignallingPresentFlag(false); + pps.setSubPicIdLen(sps.getSubPicIdLen()); + for(int picIdx=0; picIdx<pps.getNumSubPics(); picIdx++) + { + pps.setSubPicId(picIdx, sps.getSubPicId(picIdx)); + } +#endif pps.setConstrainedIntraPred( m_bUseConstrainedIntraPred ); bool bUseDQP = (getCuQpDeltaSubdiv() > 0)? true : false; @@ -1543,29 +1608,39 @@ void EncLib::xInitPPS(PPS &pps, const SPS &sps) if ( m_RCEnableRateControl ) { pps.setUseDQP(true); +#if !JVET_P1006_PICTURE_HEADER pps.setCuQpDeltaSubdiv( 0 ); +#endif } else if(bUseDQP) { pps.setUseDQP(true); +#if !JVET_P1006_PICTURE_HEADER pps.setCuQpDeltaSubdiv( m_cuQpDeltaSubdiv ); +#endif } else { pps.setUseDQP(false); +#if !JVET_P1006_PICTURE_HEADER pps.setCuQpDeltaSubdiv( 0 ); +#endif } if ( m_cuChromaQpOffsetSubdiv >= 0 ) { +#if !JVET_P1006_PICTURE_HEADER pps.setCuChromaQpOffsetSubdiv(m_cuChromaQpOffsetSubdiv); +#endif pps.clearChromaQpOffsetList(); pps.setChromaQpOffsetListEntry(1, 6, 6, 6); /* todo, insert table entries from command line (NB, 0 should not be touched) */ } else { +#if !JVET_P1006_PICTURE_HEADER pps.setCuChromaQpOffsetSubdiv(0); +#endif pps.clearChromaQpOffsetList(); } pps.getPpsRangeExtension().setCrossComponentPredictionEnabledFlag(m_crossComponentPredictionEnabledFlag); @@ -1739,6 +1814,9 @@ void EncLib::xInitPPS(PPS &pps, const SPS &sps) xInitPPSforTiles(pps); +#if JVET_P1006_PICTURE_HEADER + pps.setPictureHeaderExtensionPresentFlag(false); +#else pps.setLoopFilterAcrossVirtualBoundariesDisabledFlag( m_loopFilterAcrossVirtualBoundariesDisabledFlag ); pps.setNumVerVirtualBoundaries ( m_numVerVirtualBoundaries ); pps.setNumHorVirtualBoundaries ( m_numHorVirtualBoundaries ); @@ -1750,11 +1828,116 @@ void EncLib::xInitPPS(PPS &pps, const SPS &sps) { pps.setVirtualBoundariesPosY ( m_virtualBoundariesPosY[i], i ); } +#endif pps.pcv = new PreCalcValues( sps, pps, true ); pps.setRpl1IdxPresentFlag(sps.getRPL1IdxPresentFlag()); } +#if JVET_P1006_PICTURE_HEADER +void EncLib::xInitPicHeader(PicHeader &picHeader, const SPS &sps, const PPS &pps) +{ + int i; + picHeader.initPicHeader(); + + // parameter sets + picHeader.setSPSId( sps.getSPSId() ); + picHeader.setPPSId( pps.getPPSId() ); + + // merge list sizes + picHeader.setMaxNumMergeCand ( getMaxNumMergeCand() ); + picHeader.setMaxNumAffineMergeCand( getMaxNumAffineMergeCand() ); + picHeader.setMaxNumTriangleCand ( getMaxNumTriangleCand() ); + picHeader.setMaxNumIBCMergeCand ( getMaxNumIBCMergeCand() ); + + // copy partitioning constraints from SPS + picHeader.setSplitConsOverrideFlag(false); + picHeader.setMinQTSizes( sps.getMinQTSizes() ); + picHeader.setMaxMTTHierarchyDepths( sps.getMaxMTTHierarchyDepths() ); + picHeader.setMaxBTSizes( sps.getMaxBTSizes() ); + picHeader.setMaxTTSizes( sps.getMaxTTSizes() ); + + // quantization + picHeader.setDepQuantEnabledFlag( getDepQuantEnabledFlag() ); + picHeader.setSignDataHidingEnabledFlag( getSignDataHidingEnabledFlag() ); + + bool bUseDQP = (getCuQpDeltaSubdiv() > 0)? true : false; + + if( (getMaxDeltaQP() != 0 )|| getUseAdaptiveQP() ) + { + bUseDQP = true; + } + +#if SHARP_LUMA_DELTA_QP + if( getLumaLevelToDeltaQPMapping().isEnabled() ) + { + bUseDQP = true; + } +#endif +#if ENABLE_QPA + if( getUsePerceptQPA() && !bUseDQP ) + { + CHECK( m_cuQpDeltaSubdiv != 0, "max. delta-QP subdiv must be zero!" ); + bUseDQP = (getBaseQP() < 38) && (getSourceWidth() > 512 || getSourceHeight() > 320); + } +#endif + + if( m_costMode==COST_SEQUENCE_LEVEL_LOSSLESS || m_costMode==COST_LOSSLESS_CODING ) + { + bUseDQP=false; + } + + if( m_RCEnableRateControl ) + { + picHeader.setCuQpDeltaSubdivIntra( 0 ); + picHeader.setCuQpDeltaSubdivInter( 0 ); + } + else if( bUseDQP ) + { + picHeader.setCuQpDeltaSubdivIntra( m_cuQpDeltaSubdiv ); + picHeader.setCuQpDeltaSubdivInter( m_cuQpDeltaSubdiv ); + } + else + { + picHeader.setCuQpDeltaSubdivIntra( 0 ); + picHeader.setCuQpDeltaSubdivInter( 0 ); + } + + if( m_cuChromaQpOffsetSubdiv >= 0 ) + { + picHeader.setCuChromaQpOffsetSubdivIntra(m_cuChromaQpOffsetSubdiv); + picHeader.setCuChromaQpOffsetSubdivInter(m_cuChromaQpOffsetSubdiv); + } + else + { + picHeader.setCuChromaQpOffsetSubdivIntra(0); + picHeader.setCuChromaQpOffsetSubdivInter(0); + } + + // sub-pictures + picHeader.setSubPicIdSignallingPresentFlag(sps.getSubPicIdSignallingPresentFlag()); + picHeader.setSubPicIdLen(sps.getSubPicIdLen()); + for(i=0; i<sps.getNumSubPics(); i++) { + picHeader.setSubPicId(i, sps.getSubPicId(i)); + } + + // virtual boundaries + picHeader.setLoopFilterAcrossVirtualBoundariesDisabledFlag(sps.getLoopFilterAcrossVirtualBoundariesDisabledFlag()); + picHeader.setNumVerVirtualBoundaries(sps.getNumVerVirtualBoundaries()); + picHeader.setNumHorVirtualBoundaries(sps.getNumHorVirtualBoundaries()); + for(i=0; i<3; i++) { + picHeader.setVirtualBoundariesPosX(sps.getVirtualBoundariesPosX(i), i); + picHeader.setVirtualBoundariesPosY(sps.getVirtualBoundariesPosY(i), i); + } + + // gradual decoder refresh flag + picHeader.setGdrPicFlag(false); + + // BDOF / DMVR / PROF + picHeader.setDisBdofDmvrFlag(false); +} + +#endif void EncLib::xInitAPS(APS &aps) { //Do nothing now diff --git a/source/Lib/EncoderLib/EncLib.h b/source/Lib/EncoderLib/EncLib.h index e477bb30d..8045eb45b 100644 --- a/source/Lib/EncoderLib/EncLib.h +++ b/source/Lib/EncoderLib/EncLib.h @@ -131,6 +131,9 @@ private: ParameterSetMap<SPS> m_spsMap; ///< SPS. This is the base value. This is copied to PicSym ParameterSetMap<PPS> m_ppsMap; ///< PPS. This is the base value. This is copied to PicSym ParameterSetMap<APS> m_apsMap; ///< APS. This is the base value. This is copied to PicSym +#endif +#if JVET_P1006_PICTURE_HEADER + PicHeader m_picHeader; ///< picture header #endif // RD cost computation #if ENABLE_SPLIT_PARALLELISM || ENABLE_WPP_PARALLELISM @@ -182,6 +185,9 @@ protected: void xInitDPS (DPS &dps, const SPS &sps, const int dpsId); ///< initialize DPS from encoder options void xInitSPS (SPS &sps); ///< initialize SPS from encoder options 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 +#endif void xInitAPS (APS &aps); ///< initialize APS from encoder options void xInitScalingLists ( SPS &sps, APS &aps ); ///< initialize scaling lists void xInitPPSforLT(PPS& pps); diff --git a/source/Lib/EncoderLib/EncModeCtrl.cpp b/source/Lib/EncoderLib/EncModeCtrl.cpp index 56da31c8c..cfc71f544 100644 --- a/source/Lib/EncoderLib/EncModeCtrl.cpp +++ b/source/Lib/EncoderLib/EncModeCtrl.cpp @@ -143,7 +143,11 @@ void EncModeCtrl::xGetMinMaxQP( int& minQP, int& maxQP, const CodingStructure& c const unsigned subdivIncr = (splitMode == CU_QUAD_SPLIT) ? 2 : (splitMode == CU_BT_SPLIT) ? 1 : 0; const bool qgEnable = partitioner.currQgEnable(); // QG possible at current level +#if JVET_P1006_PICTURE_HEADER + const bool qgEnableChildren = qgEnable && ((partitioner.currSubdiv + subdivIncr) <= cs.slice->getCuQpDeltaSubdiv()) && (subdivIncr > 0); // QG possible at next level +#else const bool qgEnableChildren = qgEnable && ((partitioner.currSubdiv + subdivIncr) <= pps.getCuQpDeltaSubdiv()) && (subdivIncr > 0); // QG possible at next level +#endif const bool isLeafQG = (qgEnable && !qgEnableChildren); if( isLeafQG ) // QG at deepest level @@ -1192,7 +1196,11 @@ void EncModeCtrlMTnoRQT::initCULevel( Partitioner &partitioner, const CodingStru baseQP = Clip3(-cs.sps->getQpBDOffset(CHANNEL_TYPE_LUMA), MAX_QP, baseQP + xComputeDQP(cs, partitioner)); } #if ENABLE_QPA_SUB_CTU +#if JVET_P1006_PICTURE_HEADER + else if (m_pcEncCfg->getUsePerceptQPA() && !m_pcEncCfg->getUseRateCtrl() && cs.pps->getUseDQP() && cs.slice->getCuQpDeltaSubdiv() > 0) +#else else if (m_pcEncCfg->getUsePerceptQPA() && !m_pcEncCfg->getUseRateCtrl() && cs.pps->getUseDQP() && cs.pps->getCuQpDeltaSubdiv() > 0) +#endif { const PreCalcValues &pcv = *cs.pcv; diff --git a/source/Lib/EncoderLib/EncSampleAdaptiveOffset.cpp b/source/Lib/EncoderLib/EncSampleAdaptiveOffset.cpp index 0574e3c50..4755f9c8a 100644 --- a/source/Lib/EncoderLib/EncSampleAdaptiveOffset.cpp +++ b/source/Lib/EncoderLib/EncSampleAdaptiveOffset.cpp @@ -309,7 +309,11 @@ void EncSampleAdaptiveOffset::getStatistics(std::vector<SAOStatData**>& blkStats int verVirBndryPos[] = { -1,-1,-1 }; int horVirBndryPosComp[] = { -1,-1,-1 }; int verVirBndryPosComp[] = { -1,-1,-1 }; +#if JVET_P1006_PICTURE_HEADER + bool isCtuCrossedByVirtualBoundaries = isCrossedByVirtualBoundaries(xPos, yPos, width, height, numHorVirBndry, numVerVirBndry, horVirBndryPos, verVirBndryPos, cs.picHeader ); +#else bool isCtuCrossedByVirtualBoundaries = isCrossedByVirtualBoundaries(xPos, yPos, width, height, numHorVirBndry, numVerVirBndry, horVirBndryPos, verVirBndryPos, cs.slice->getPPS()); +#endif for(int compIdx = 0; compIdx < numberOfComponents; compIdx++) { @@ -1541,6 +1545,9 @@ void EncSampleAdaptiveOffset::getBlkStats(const ComponentID compIdx, const int c void EncSampleAdaptiveOffset::deriveLoopFilterBoundaryAvailibility(CodingStructure& cs, const Position &pos, bool& isLeftAvail, bool& isAboveAvail, bool& isAboveLeftAvail) const { +#if JVET_P1006_PICTURE_HEADER + bool isLoopFiltAcrossSlicePPS = cs.pps->getLoopFilterAcrossSlicesEnabledFlag(); +#endif bool isLoopFiltAcrossTilePPS = cs.pps->getLoopFilterAcrossBricksEnabledFlag(); const int width = cs.pcv->maxCUWidth; @@ -1550,11 +1557,26 @@ void EncSampleAdaptiveOffset::deriveLoopFilterBoundaryAvailibility(CodingStructu const CodingUnit* cuAbove = cs.getCU(pos.offset(0, -height), CH_L); const CodingUnit* cuAboveLeft = cs.getCU(pos.offset(-width, -height), CH_L); +#if JVET_P1006_PICTURE_HEADER + if (!isLoopFiltAcrossSlicePPS) + { + isLeftAvail = (cuLeft == NULL) ? false : CU::isSameTile(*cuCurr, *cuLeft); + isAboveAvail = (cuAbove == NULL) ? false : CU::isSameTile(*cuCurr, *cuAbove); + isAboveLeftAvail = (cuAboveLeft == NULL) ? false : CU::isSameTile(*cuCurr, *cuAboveLeft); + } + else + { + isLeftAvail = (cuLeft != NULL); + isAboveAvail = (cuAbove != NULL); + isAboveLeftAvail = (cuAboveLeft != NULL); + } +#else { isLeftAvail = (cuLeft != NULL) ? ( !CU::isSameSlice(*cuCurr, *cuLeft) ? cuCurr->slice->getLFCrossSliceBoundaryFlag() : true ) : false; isAboveAvail = (cuAbove != NULL) ? ( !CU::isSameSlice(*cuCurr, *cuAbove) ? cuCurr->slice->getLFCrossSliceBoundaryFlag() : true ) : false; isAboveLeftAvail = (cuAboveLeft != NULL) ? ( !CU::isSameSlice(*cuCurr, *cuAboveLeft) ? cuCurr->slice->getLFCrossSliceBoundaryFlag() : true ) : false; } +#endif if (!isLoopFiltAcrossTilePPS) { diff --git a/source/Lib/EncoderLib/EncSlice.cpp b/source/Lib/EncoderLib/EncSlice.cpp index 99aa3691a..a0a043c41 100644 --- a/source/Lib/EncoderLib/EncSlice.cpp +++ b/source/Lib/EncoderLib/EncSlice.cpp @@ -329,24 +329,40 @@ void EncSlice::initEncSlice(Picture* pcPic, const int pocLast, const int pocCurr { double dQP; double dLambda; +#if JVET_P1006_PICTURE_HEADER + PicHeader *picHeader = pcPic->cs->picHeader; +#endif pcPic->cs->resetPrevPLT(pcPic->cs->prevPLT); rpcSlice = pcPic->slices[0]; rpcSlice->setSliceBits(0); rpcSlice->setPic( pcPic ); +#if JVET_P1006_PICTURE_HEADER + rpcSlice->setPicHeader( picHeader ); +#endif rpcSlice->initSlice(); int multipleFactor = m_pcCfg->getUseCompositeRef() ? 2 : 1; if (m_pcCfg->getUseCompositeRef() && isEncodeLtRef) { +#if JVET_P1006_PICTURE_HEADER + picHeader->setPicOutputFlag(false); +#else rpcSlice->setPicOutputFlag(false); +#endif } else { +#if JVET_P1006_PICTURE_HEADER + picHeader->setPicOutputFlag(true); +#else rpcSlice->setPicOutputFlag(true); +#endif } rpcSlice->setPOC( pocCurr ); +#if !JVET_P1006_PICTURE_HEADER rpcSlice->setDepQuantEnabledFlag( m_pcCfg->getDepQuantEnabledFlag() ); rpcSlice->setSignDataHidingEnabledFlag( m_pcCfg->getSignDataHidingEnabledFlag() ); +#endif #if SHARP_LUMA_DELTA_QP pcPic->fieldPic = isField; @@ -586,7 +602,9 @@ void EncSlice::initEncSlice(Picture* pcPic, const int pocLast, const int pocCurr rpcSlice->setSliceChromaQpDelta( COMPONENT_Cr, 0 ); rpcSlice->setSliceChromaQpDelta( JOINT_CbCr, 0 ); #endif +#if !JVET_P1006_PICTURE_HEADER rpcSlice->setUseChromaQpAdj( rpcSlice->getPPS()->getCuChromaQpOffsetEnabledFlag() ); +#endif rpcSlice->setNumRefIdx(REF_PIC_LIST_0, m_pcCfg->getRPLEntry(0, iGOPid).m_numRefPicsActive); rpcSlice->setNumRefIdx(REF_PIC_LIST_1, m_pcCfg->getRPLEntry(1, iGOPid).m_numRefPicsActive); @@ -632,6 +650,7 @@ void EncSlice::initEncSlice(Picture* pcPic, const int pocLast, const int pocCurr rpcSlice->setSliceMode ( m_pcCfg->getSliceMode() ); rpcSlice->setSliceArgument ( m_pcCfg->getSliceArgument() ); +#if !JVET_P1006_PICTURE_HEADER rpcSlice->setMaxNumMergeCand ( m_pcCfg->getMaxNumMergeCand() ); rpcSlice->setMaxNumAffineMergeCand( m_pcCfg->getMaxNumAffineMergeCand() ); rpcSlice->setMaxNumTriangleCand ( m_pcCfg->getMaxNumTriangleCand() ); @@ -648,6 +667,7 @@ void EncSlice::initEncSlice(Picture* pcPic, const int pocLast, const int pocCurr rpcSlice->setMaxBTSizeIChroma( rpcSlice->getSPS()->getMaxBTSizeIChroma() ); rpcSlice->setMaxTTSizeIChroma( rpcSlice->getSPS()->getMaxTTSizeIChroma() ); } +#endif rpcSlice->setDisableSATDForRD(false); if( ( m_pcCfg->getIBCHashSearch() && m_pcCfg->getIBCMode() ) || m_pcCfg->getAllowDisFracMMVD() ) @@ -931,7 +951,11 @@ static bool applyQPAdaptation (Picture* const pcPic, Slice* const pcSlice, pcPic->m_iOffsetCtu[ctuRsAddr] = (Pel)iQPAdapt; // adapted QPs #if ENABLE_QPA_SUB_CTU +#if JVET_P1006_PICTURE_HEADER + if (pcv.widthInCtus > 1 && pcSlice->getCuQpDeltaSubdiv() == 0) // reduce local DQP rate peaks +#else if (pcv.widthInCtus > 1 && pcSlice->getPPS()->getCuQpDeltaSubdiv() == 0) // reduce local DQP rate peaks +#endif #elif ENABLE_QPA_SUB_CTU if (pcv.widthInCtus > 1 && pcSlice->getPPS()->getMaxCuDQPDepth() == 0) // reduce local DQP rate peaks #else @@ -978,7 +1002,11 @@ static int applyQPAdaptationSubCtu (CodingStructure &cs, const UnitArea ctuArea, const int bitDepth = cs.slice->getSPS()->getBitDepth (CHANNEL_TYPE_LUMA); // overall image bit-depth const int adaptedCtuQP = pcPic ? pcPic->m_iOffsetCtu[ctuAddr] : cs.slice->getSliceQpBase(); +#if JVET_P1006_PICTURE_HEADER + if (!pcPic || cs.slice->getCuQpDeltaSubdiv() == 0) return adaptedCtuQP; +#else if (!pcPic || cs.pps->getCuQpDeltaSubdiv() == 0) return adaptedCtuQP; +#endif for (unsigned addr = 0; addr < cs.picture->m_subCtuQP.size(); addr++) { @@ -1384,16 +1412,31 @@ void EncSlice::checkDisFracMmvd( Picture* pcPic, uint32_t startCtuTsAddr, uint32 if ( hashRatio > totalCtu * hashThreshold ) { +#if JVET_P1006_PICTURE_HEADER + pcPic->cs->picHeader->setDisFracMMVD( true ); +#else pcSlice->setDisFracMMVD( true ); +#endif } +#if JVET_P1006_PICTURE_HEADER + if (!pcPic->cs->picHeader->getDisFracMMVD()) { + bool useIntegerMVD = (pcPic->lwidth()*pcPic->lheight() > 1920 * 1080); + pcPic->cs->picHeader->setDisFracMMVD( useIntegerMVD ); + } +#else if (!pcSlice->getDisFracMMVD()) { bool useIntegerMVD = (pcPic->lwidth()*pcPic->lheight() > 1920 * 1080); pcSlice->setDisFracMMVD( useIntegerMVD ); } +#endif } +#if JVET_P1006_PICTURE_HEADER +void EncSlice::setJointCbCrModes( CodingStructure& cs, const Position topLeftLuma, const Size sizeLuma ) +#else void setJointCbCrModes( CodingStructure& cs, const Position topLeftLuma, const Size sizeLuma ) +#endif { bool sgnFlag = true; @@ -1427,7 +1470,11 @@ void setJointCbCrModes( CodingStructure& cs, const Position topLeftLuma, const S sgnFlag = ( sumCbCr < 0 ); } +#if JVET_P1006_PICTURE_HEADER + cs.picHeader->setJointCbCrSignFlag( sgnFlag ); +#else cs.slice->setJointCbCrSignFlag( sgnFlag ); +#endif } @@ -1479,12 +1526,14 @@ void EncSlice::encodeCtus( Picture* pcPic, const bool bCompressEntireSlice, cons cs.slice->setDisableSATDForRD(hashBlkHitPerc > 59); } } +#if !JVET_P1006_PICTURE_HEADER checkDisFracMmvd( pcPic, startCtuTsAddr, boundingCtuTsAddr ); if (pcSlice->getSPS()->getJointCbCrEnabledFlag()) { setJointCbCrModes(cs, Position(0, 0), cs.area.lumaSize()); } +#endif // for every CTU in the slice segment (may terminate sooner if there is a byte limit on the slice-segment) uint32_t startSliceRsRow = tileMap.getCtuBsToRsAddrMap(startCtuTsAddr) / widthInCtus; diff --git a/source/Lib/EncoderLib/EncSlice.h b/source/Lib/EncoderLib/EncSlice.h index ecc52f4a6..07f157a91 100644 --- a/source/Lib/EncoderLib/EncSlice.h +++ b/source/Lib/EncoderLib/EncSlice.h @@ -139,6 +139,9 @@ public: #endif void encodeCtus ( Picture* pcPic, const bool bCompressEntireSlice, const bool bFastDeltaQP, uint32_t startCtuTsAddr, uint32_t boundingCtuTsAddr, EncLib* pcEncLib ); void checkDisFracMmvd ( Picture* pcPic, uint32_t startCtuTsAddr, uint32_t boundingCtuTsAddr ); +#if JVET_P1006_PICTURE_HEADER + void setJointCbCrModes( CodingStructure& cs, const Position topLeftLuma, const Size sizeLuma ); +#endif // misc. functions void setSearchRange ( Slice* pcSlice ); ///< set ME range adaptively diff --git a/source/Lib/EncoderLib/InterSearch.cpp b/source/Lib/EncoderLib/InterSearch.cpp index bb6ed55e6..d18b39381 100644 --- a/source/Lib/EncoderLib/InterSearch.cpp +++ b/source/Lib/EncoderLib/InterSearch.cpp @@ -1262,7 +1262,11 @@ void InterSearch::xIBCEstimation(PredictionUnit& pu, PelUnitBuf& origBuf, CPelBuf* pcPatternKey = &tmpPattern; PelBuf tmpOrgLuma; +#if JVET_P1006_PICTURE_HEADER + if ((pu.cs->picHeader->getLmcsEnabledFlag() && m_pcReshape->getCTUFlag())) +#else if ((pu.cs->slice->getLmcsEnabledFlag() && m_pcReshape->getCTUFlag())) +#endif { const CompArea &area = pu.blocks[COMPONENT_Y]; CompArea tmpArea(COMPONENT_Y, area.chromaFormat, Position(0, 0), area.size()); @@ -1454,7 +1458,11 @@ bool InterSearch::predIBCSearch(CodingUnit& cu, Partitioner& partitioner, const cMv.setZero(); Distortion cost = 0; +#if JVET_P1006_PICTURE_HEADER + if ( pu.cu->slice->getPicHeader()->getMaxNumIBCMergeCand() == 1 ) +#else if ( pu.cu->slice->getMaxNumIBCMergeCand() == 1 ) +#endif { iBvpNum = 1; cMvPred[1] = cMvPred[0]; @@ -2373,7 +2381,11 @@ void InterSearch::predInterSearch(CodingUnit& cu, Partitioner& partitioner) aaiMvpIdx[iRefList][iRefIdxTemp] = pu.mvpIdx[eRefPicList]; aaiMvpNum[iRefList][iRefIdxTemp] = pu.mvpNum[eRefPicList]; +#if JVET_P1006_PICTURE_HEADER + if(cs.picHeader->getMvdL1ZeroFlag() && iRefList==1 && biPDistTemp < bestBiPDist) +#else if(cs.slice->getMvdL1ZeroFlag() && iRefList==1 && biPDistTemp < bestBiPDist) +#endif { bestBiPDist = biPDistTemp; bestBiPMvpL1 = aaiMvpIdx[iRefList][iRefIdxTemp]; @@ -2468,7 +2480,11 @@ void InterSearch::predInterSearch(CodingUnit& cu, Partitioner& partitioner) uint32_t uiMotBits[2]; +#if JVET_P1006_PICTURE_HEADER + if(cs.picHeader->getMvdL1ZeroFlag()) +#else if(cs.slice->getMvdL1ZeroFlag()) +#endif { xCopyAMVPInfo(&aacAMVPInfo[1][bestBiPRefIdxL1], &amvp[REF_PIC_LIST_1]); aaiMvpIdxBi[1][bestBiPRefIdxL1] = bestBiPMvpL1; @@ -2527,7 +2543,11 @@ void InterSearch::predInterSearch(CodingUnit& cu, Partitioner& partitioner) int iNumIter = 4; // fast encoder setting: only one iteration +#if JVET_P1006_PICTURE_HEADER + if ( m_pcEncCfg->getFastInterSearchMode()==FASTINTERSEARCH_MODE1 || m_pcEncCfg->getFastInterSearchMode()==FASTINTERSEARCH_MODE2 || cs.picHeader->getMvdL1ZeroFlag() ) +#else if ( m_pcEncCfg->getFastInterSearchMode()==FASTINTERSEARCH_MODE1 || m_pcEncCfg->getFastInterSearchMode()==FASTINTERSEARCH_MODE2 || cs.slice->getMvdL1ZeroFlag() ) +#endif { iNumIter = 1; } @@ -2556,7 +2576,11 @@ void InterSearch::predInterSearch(CodingUnit& cu, Partitioner& partitioner) { iRefList = 0; } +#if JVET_P1006_PICTURE_HEADER + if ( iIter == 0 && !cs.picHeader->getMvdL1ZeroFlag()) +#else if ( iIter == 0 && !cs.slice->getMvdL1ZeroFlag()) +#endif { pu.mv [1 - iRefList] = cMv [1 - iRefList]; pu.refIdx[1 - iRefList] = iRefIdx[1 - iRefList]; @@ -2567,7 +2591,11 @@ void InterSearch::predInterSearch(CodingUnit& cu, Partitioner& partitioner) RefPicList eRefPicList = ( iRefList ? REF_PIC_LIST_1 : REF_PIC_LIST_0 ); +#if JVET_P1006_PICTURE_HEADER + if(cs.picHeader->getMvdL1ZeroFlag()) +#else if(cs.slice->getMvdL1ZeroFlag()) +#endif { iRefList = 0; eRefPicList = REF_PIC_LIST_0; @@ -2634,7 +2662,11 @@ void InterSearch::predInterSearch(CodingUnit& cu, Partitioner& partitioner) { xCopyAMVPInfo(&aacAMVPInfo[0][iRefIdxBi[0]], &amvp[REF_PIC_LIST_0]); xCheckBestMVP( REF_PIC_LIST_0, cMvBi[0], cMvPredBi[0][iRefIdxBi[0]], aaiMvpIdxBi[0][iRefIdxBi[0]], amvp[REF_PIC_LIST_0], uiBits[2], uiCostBi, pu.cu->imv); +#if JVET_P1006_PICTURE_HEADER + if(!cs.picHeader->getMvdL1ZeroFlag()) +#else if(!cs.slice->getMvdL1ZeroFlag()) +#endif { xCopyAMVPInfo(&aacAMVPInfo[1][iRefIdxBi[1]], &amvp[REF_PIC_LIST_1]); xCheckBestMVP( REF_PIC_LIST_1, cMvBi[1], cMvPredBi[1][iRefIdxBi[1]], aaiMvpIdxBi[1][iRefIdxBi[1]], amvp[REF_PIC_LIST_1], uiBits[2], uiCostBi, pu.cu->imv); @@ -4798,7 +4830,11 @@ void InterSearch::xPredAffineInterSearch( PredictionUnit& pu, } // GPB list 1, save the best MvpIdx, RefIdx and Cost +#if JVET_P1006_PICTURE_HEADER + if ( slice.getPicHeader()->getMvdL1ZeroFlag() && iRefList==1 && biPDistTemp < bestBiPDist ) +#else if ( slice.getMvdL1ZeroFlag() && iRefList==1 && biPDistTemp < bestBiPDist ) +#endif { bestBiPDist = biPDistTemp; bestBiPMvpL1 = aaiMvpIdx[iRefList][iRefIdxTemp]; @@ -4926,7 +4962,11 @@ void InterSearch::xPredAffineInterSearch( PredictionUnit& pu, uint32_t uiMotBits[2]; bool doBiPred = true; +#if JVET_P1006_PICTURE_HEADER + if ( slice.getPicHeader()->getMvdL1ZeroFlag() ) // GPB, list 1 only use Mvp +#else if ( slice.getMvdL1ZeroFlag() ) // GPB, list 1 only use Mvp +#endif { xCopyAffineAMVPInfo( aacAffineAMVPInfo[1][bestBiPRefIdxL1], affiAMVPInfoTemp[REF_PIC_LIST_1] ); pu.mvpIdx[REF_PIC_LIST_1] = bestBiPMvpL1; @@ -4992,7 +5032,11 @@ void InterSearch::xPredAffineInterSearch( PredictionUnit& pu, // 4-times iteration (default) int iNumIter = 4; // fast encoder setting or GPB: only one iteration +#if JVET_P1006_PICTURE_HEADER + if ( m_pcEncCfg->getFastInterSearchMode()==FASTINTERSEARCH_MODE1 || m_pcEncCfg->getFastInterSearchMode()==FASTINTERSEARCH_MODE2 || slice.getPicHeader()->getMvdL1ZeroFlag() ) +#else if ( m_pcEncCfg->getFastInterSearchMode()==FASTINTERSEARCH_MODE1 || m_pcEncCfg->getFastInterSearchMode()==FASTINTERSEARCH_MODE2 || slice.getMvdL1ZeroFlag() ) +#endif { iNumIter = 1; } @@ -5022,7 +5066,11 @@ void InterSearch::xPredAffineInterSearch( PredictionUnit& pu, } // First iterate, get prediction block of opposite direction +#if JVET_P1006_PICTURE_HEADER + if( iIter == 0 && !slice.getPicHeader()->getMvdL1ZeroFlag() ) +#else if( iIter == 0 && !slice.getMvdL1ZeroFlag() ) +#endif { PU::setAllAffineMv( pu, aacMv[1-iRefList][0], aacMv[1-iRefList][1], aacMv[1-iRefList][2], RefPicList(1-iRefList)); pu.refIdx[1-iRefList] = iRefIdx[1-iRefList]; @@ -5033,7 +5081,11 @@ void InterSearch::xPredAffineInterSearch( PredictionUnit& pu, RefPicList eRefPicList = ( iRefList ? REF_PIC_LIST_1 : REF_PIC_LIST_0 ); +#if JVET_P1006_PICTURE_HEADER + if ( slice.getPicHeader()->getMvdL1ZeroFlag() ) // GPB, fix List 1, search List 0 +#else if ( slice.getMvdL1ZeroFlag() ) // GPB, fix List 1, search List 0 +#endif { iRefList = 0; eRefPicList = REF_PIC_LIST_0; @@ -5105,7 +5157,11 @@ void InterSearch::xPredAffineInterSearch( PredictionUnit& pu, xCopyAffineAMVPInfo( aacAffineAMVPInfo[0][iRefIdxBi[0]], affiAMVPInfoTemp[REF_PIC_LIST_0] ); xCheckBestAffineMVP( pu, affiAMVPInfoTemp[REF_PIC_LIST_0], REF_PIC_LIST_0, cMvBi[0], cMvPredBi[0][iRefIdxBi[0]], aaiMvpIdxBi[0][iRefIdxBi[0]], uiBits[2], uiCostBi ); +#if JVET_P1006_PICTURE_HEADER + if ( !slice.getPicHeader()->getMvdL1ZeroFlag() ) +#else if ( !slice.getMvdL1ZeroFlag() ) +#endif { xCopyAffineAMVPInfo( aacAffineAMVPInfo[1][iRefIdxBi[1]], affiAMVPInfoTemp[REF_PIC_LIST_1] ); xCheckBestAffineMVP( pu, affiAMVPInfoTemp[REF_PIC_LIST_1], REF_PIC_LIST_1, cMvBi[1], cMvPredBi[1][iRefIdxBi[1]], aaiMvpIdxBi[1][iRefIdxBi[1]], uiBits[2], uiCostBi ); @@ -6513,7 +6569,11 @@ void InterSearch::xEstimateInterResidualQT(CodingStructure &cs, Partitioner &par tu.checkTuNoResidual( partitioner.currPartIdx() ); const Slice &slice = *cs.slice; +#if JVET_P1006_PICTURE_HEADER + if (slice.getPicHeader()->getLmcsEnabledFlag() && slice.getPicHeader()->getLmcsChromaResidualScaleFlag() && !(CS::isDualITree(cs) && slice.isIntra() && tu.cu->predMode==MODE_IBC )) +#else if (slice.getLmcsEnabledFlag() && slice.getLmcsChromaResidualScaleFlag() && !(CS::isDualITree(cs) && slice.isIntra() && tu.cu->predMode==MODE_IBC )) +#endif { const CompArea &areaY = tu.blocks[COMPONENT_Y]; int adj = m_pcReshape->calculateChromaAdjVpduNei(tu, areaY); @@ -6664,7 +6724,11 @@ void InterSearch::xEstimateInterResidualQT(CodingStructure &cs, Partitioner &par #if RDOQ_CHROMA_LAMBDA m_pcTrQuant->selectLambda(compID); #endif +#if JVET_P1006_PICTURE_HEADER + if (slice.getPicHeader()->getLmcsEnabledFlag() && isChroma(compID) && slice.getPicHeader()->getLmcsChromaResidualScaleFlag()) +#else if (slice.getLmcsEnabledFlag() && isChroma(compID) && slice.getLmcsChromaResidualScaleFlag()) +#endif { double cRescale = (double)(1 << CSCALE_FP_PREC) / (double)(tu.getChromaAdj()); m_pcTrQuant->setLambda(m_pcTrQuant->getLambda() / (cRescale*cRescale)); @@ -6687,7 +6751,11 @@ void InterSearch::xEstimateInterResidualQT(CodingStructure &cs, Partitioner &par PelBuf resiBuf = csFull->getResiBuf( compArea ); crossComponentPrediction( tu, compID, lumaResi, resiBuf, resiBuf, false ); } +#if JVET_P1006_PICTURE_HEADER + if (slice.getPicHeader()->getLmcsEnabledFlag() && isChroma(compID) && slice.getPicHeader()->getLmcsChromaResidualScaleFlag() && tu.blocks[compID].width*tu.blocks[compID].height > 4) +#else if (slice.getLmcsEnabledFlag() && isChroma(compID) && slice.getLmcsChromaResidualScaleFlag() && tu.blocks[compID].width*tu.blocks[compID].height > 4) +#endif { PelBuf resiBuf = csFull->getResiBuf(compArea); resiBuf.scaleSignal(tu.getChromaAdj(), 1, tu.cu->cs->slice->clpRng(compID)); @@ -6799,7 +6867,11 @@ void InterSearch::xEstimateInterResidualQT(CodingStructure &cs, Partitioner &par CPelBuf orgResiBuf = csFull->getOrgResiBuf(compArea); m_pcTrQuant->invTransformNxN(tu, compID, resiBuf, cQP); +#if JVET_P1006_PICTURE_HEADER + if (slice.getPicHeader()->getLmcsEnabledFlag() && isChroma(compID) && slice.getPicHeader()->getLmcsChromaResidualScaleFlag() && tu.blocks[compID].width*tu.blocks[compID].height > 4) +#else if (slice.getLmcsEnabledFlag() && isChroma(compID) && slice.getLmcsChromaResidualScaleFlag() && tu.blocks[compID].width*tu.blocks[compID].height > 4) +#endif { resiBuf.scaleSignal(tu.getChromaAdj(), 0, tu.cu->cs->slice->clpRng(compID)); } @@ -6895,7 +6967,11 @@ void InterSearch::xEstimateInterResidualQT(CodingStructure &cs, Partitioner &par const CompArea& crArea = tu.blocks[COMPONENT_Cr]; bool checkJointCbCr = (sps.getJointCbCrEnabledFlag()) && (!tu.noResidual) && (TU::getCbf(tu, COMPONENT_Cb) || TU::getCbf(tu, COMPONENT_Cr)); const int channelBitDepth = sps.getBitDepth(toChannelType(COMPONENT_Cb)); +#if JVET_P1006_PICTURE_HEADER + bool reshape = slice.getPicHeader()->getLmcsEnabledFlag() && slice.getPicHeader()->getLmcsChromaResidualScaleFlag() +#else bool reshape = slice.getLmcsEnabledFlag() && slice.getLmcsChromaResidualScaleFlag() +#endif && tu.blocks[COMPONENT_Cb].width * tu.blocks[COMPONENT_Cb].height > 4; double minCostCbCr = minCost[COMPONENT_Cb] + minCost[COMPONENT_Cr]; bool isLastBest = false; @@ -7230,7 +7306,11 @@ void InterSearch::encodeResAndCalcRdInterCU(CodingStructure &cs, Partitioner &pa cs.getResiBuf().fill(0); { cs.getRecoBuf().copyFrom(cs.getPredBuf() ); +#if JVET_P1006_PICTURE_HEADER + if (m_pcEncCfg->getReshaper() && (cs.picHeader->getLmcsEnabledFlag() && m_pcReshape->getCTUFlag()) && !cu.firstPU->mhIntraFlag && !CU::isIBC(cu)) +#else if (m_pcEncCfg->getReshaper() && (cs.slice->getLmcsEnabledFlag() && m_pcReshape->getCTUFlag()) && !cu.firstPU->mhIntraFlag && !CU::isIBC(cu)) +#endif { cs.getRecoBuf().Y().rspSignal(m_pcReshape->getFwdLUT()); } @@ -7252,7 +7332,11 @@ void InterSearch::encodeResAndCalcRdInterCU(CodingStructure &cs, Partitioner &pa CPelBuf org = cs.getOrgBuf (compID); #if WCG_EXT if (m_pcEncCfg->getLumaLevelToDeltaQPMapping().isEnabled() || ( +#if JVET_P1006_PICTURE_HEADER + m_pcEncCfg->getReshaper() && (cs.picHeader->getLmcsEnabledFlag() && m_pcReshape->getCTUFlag())) ) +#else m_pcEncCfg->getReshaper() && (cs.slice->getLmcsEnabledFlag() && m_pcReshape->getCTUFlag())) ) +#endif { const CPelBuf orgLuma = cs.getOrgBuf( cs.area.blocks[COMPONENT_Y] ); if (compID == COMPONENT_Y && !(m_pcEncCfg->getLumaLevelToDeltaQPMapping().isEnabled())) @@ -7295,7 +7379,11 @@ void InterSearch::encodeResAndCalcRdInterCU(CodingStructure &cs, Partitioner &pa if (luma) { cs.getResiBuf().bufs[0].copyFrom(cs.getOrgBuf().bufs[0]); +#if JVET_P1006_PICTURE_HEADER + if (cs.picHeader->getLmcsEnabledFlag() && m_pcReshape->getCTUFlag()) +#else if (cs.slice->getLmcsEnabledFlag() && m_pcReshape->getCTUFlag()) +#endif { const CompArea &areaY = cu.Y(); CompArea tmpArea(COMPONENT_Y, areaY.chromaFormat, Position(0, 0), areaY.size()); @@ -7397,7 +7485,11 @@ void InterSearch::encodeResAndCalcRdInterCU(CodingStructure &cs, Partitioner &pa if (luma) { +#if JVET_P1006_PICTURE_HEADER + if (cu.rootCbf && cs.picHeader->getLmcsEnabledFlag() && m_pcReshape->getCTUFlag()) +#else if (cu.rootCbf && cs.slice->getLmcsEnabledFlag() && m_pcReshape->getCTUFlag()) +#endif { const CompArea &areaY = cu.Y(); CompArea tmpArea(COMPONENT_Y, areaY.chromaFormat, Position(0, 0), areaY.size()); @@ -7412,7 +7504,11 @@ void InterSearch::encodeResAndCalcRdInterCU(CodingStructure &cs, Partitioner &pa else { cs.getRecoBuf().bufs[0].reconstruct(cs.getPredBuf().bufs[0], cs.getResiBuf().bufs[0], cs.slice->clpRngs().comp[0]); +#if JVET_P1006_PICTURE_HEADER + if (cs.picHeader->getLmcsEnabledFlag() && m_pcReshape->getCTUFlag() && !cu.firstPU->mhIntraFlag && !CU::isIBC(cu)) +#else if (cs.slice->getLmcsEnabledFlag() && m_pcReshape->getCTUFlag() && !cu.firstPU->mhIntraFlag && !CU::isIBC(cu)) +#endif { cs.getRecoBuf().bufs[0].rspSignal(m_pcReshape->getFwdLUT()); } @@ -7439,7 +7535,11 @@ void InterSearch::encodeResAndCalcRdInterCU(CodingStructure &cs, Partitioner &pa #if WCG_EXT if (m_pcEncCfg->getLumaLevelToDeltaQPMapping().isEnabled() || ( +#if JVET_P1006_PICTURE_HEADER + m_pcEncCfg->getReshaper() && (cs.picHeader->getLmcsEnabledFlag() && m_pcReshape->getCTUFlag()))) +#else m_pcEncCfg->getReshaper() && (cs.slice->getLmcsEnabledFlag() && m_pcReshape->getCTUFlag()))) +#endif { const CPelBuf orgLuma = cs.getOrgBuf( cs.area.blocks[COMPONENT_Y] ); if (compID == COMPONENT_Y && !(m_pcEncCfg->getLumaLevelToDeltaQPMapping().isEnabled()) ) diff --git a/source/Lib/EncoderLib/IntraSearch.cpp b/source/Lib/EncoderLib/IntraSearch.cpp index 4de25cec8..edfc7e944 100644 --- a/source/Lib/EncoderLib/IntraSearch.cpp +++ b/source/Lib/EncoderLib/IntraSearch.cpp @@ -504,7 +504,11 @@ bool IntraSearch::estIntraPredLumaQT( CodingUnit &cu, Partitioner &partitioner, DistParam distParamSad; DistParam distParamHad; +#if JVET_P1006_PICTURE_HEADER + if (cu.slice->getPicHeader()->getLmcsEnabledFlag() && m_pcReshape->getCTUFlag()) +#else if (cu.slice->getLmcsEnabledFlag() && m_pcReshape->getCTUFlag()) +#endif { CompArea tmpArea(COMPONENT_Y, area.chromaFormat, Position(0, 0), area.size()); PelBuf tmpOrg = m_tmpStorageLCU.getBuf(tmpArea); @@ -1703,7 +1707,11 @@ void IntraSearch::PLTSearch(CodingStructure &cs, Partitioner& partitioner, Compo m_orgCtxRD = PLTCtx(m_CABACEstimator->getCtx()); #endif +#if JVET_P1006_PICTURE_HEADER + if (m_pcEncCfg->getReshaper() && (cs.picHeader->getLmcsEnabledFlag() && m_pcReshape->getCTUFlag())) +#else if (m_pcEncCfg->getReshaper() && (cs.slice->getLmcsEnabledFlag() && m_pcReshape->getCTUFlag())) +#endif { cs.getPredBuf().copyFrom(cs.getOrgBuf()); cs.getPredBuf().Y().rspSignal(m_pcReshape->getFwdLUT()); @@ -1794,7 +1802,11 @@ void IntraSearch::PLTSearch(CodingStructure &cs, Partitioner& partitioner, Compo CPelBuf org = cs.getOrgBuf(compID); #if WCG_EXT if (m_pcEncCfg->getLumaLevelToDeltaQPMapping().isEnabled() || ( +#if JVET_P1006_PICTURE_HEADER + m_pcEncCfg->getReshaper() && (cs.picHeader->getLmcsEnabledFlag() && m_pcReshape->getCTUFlag()))) +#else m_pcEncCfg->getReshaper() && (cs.slice->getLmcsEnabledFlag() && m_pcReshape->getCTUFlag()))) +#endif { const CPelBuf orgLuma = cs.getOrgBuf(cs.area.blocks[COMPONENT_Y]); @@ -1873,7 +1885,11 @@ void IntraSearch::preCalcPLTIndexRD(CodingStructure& cs, Partitioner& partitione for (int comp = compBegin; comp < (compBegin + numComp); comp++) { CompArea area = cu.blocks[comp]; +#if JVET_P1006_PICTURE_HEADER + if (m_pcEncCfg->getReshaper() && (cs.picHeader->getLmcsEnabledFlag() && m_pcReshape->getCTUFlag())) +#else if (m_pcEncCfg->getReshaper() && (cs.slice->getLmcsEnabledFlag() && m_pcReshape->getCTUFlag())) +#endif { orgBuf[comp] = cs.getPredBuf(area); } @@ -2552,7 +2568,11 @@ void IntraSearch::calcPixelPred(CodingStructure& cs, Partitioner& partitioner, u for (int comp = compBegin; comp < (compBegin + numComp); comp++) { CompArea area = cu.blocks[comp]; +#if JVET_P1006_PICTURE_HEADER + if (m_pcEncCfg->getReshaper() && (cs.picHeader->getLmcsEnabledFlag() && m_pcReshape->getCTUFlag())) +#else if (m_pcEncCfg->getReshaper() && (cs.slice->getLmcsEnabledFlag() && m_pcReshape->getCTUFlag())) +#endif { orgBuf[comp] = cs.getPredBuf(area); } @@ -2628,7 +2648,11 @@ void IntraSearch::derivePLTLossy(CodingStructure& cs, Partitioner& partitioner, for (int comp = compBegin; comp < (compBegin + numComp); comp++) { CompArea area = cu.blocks[comp]; +#if JVET_P1006_PICTURE_HEADER + if (m_pcEncCfg->getReshaper() && (cs.picHeader->getLmcsEnabledFlag() && m_pcReshape->getCTUFlag())) +#else if (m_pcEncCfg->getReshaper() && (cs.slice->getLmcsEnabledFlag() && m_pcReshape->getCTUFlag())) +#endif { orgBuf[comp] = cs.getPredBuf(area); } @@ -3306,12 +3330,20 @@ void IntraSearch::xIntraCodingTUBlock(TransformUnit &tu, const ComponentID &comp //DTRACE_PEL_BUF( D_PRED, piPred, tu, tu.cu->predMode, COMPONENT_Y ); const Slice &slice = *cs.slice; +#if JVET_P1006_PICTURE_HEADER + bool flag = slice.getPicHeader()->getLmcsEnabledFlag() && (slice.isIntra() || (!slice.isIntra() && m_pcReshape->getCTUFlag())); +#else bool flag = slice.getLmcsEnabledFlag() && (slice.isIntra() || (!slice.isIntra() && m_pcReshape->getCTUFlag())); +#endif if (isLuma(compID)) { //===== get residual signal ===== piResi.copyFrom( piOrg ); +#if JVET_P1006_PICTURE_HEADER + if (slice.getPicHeader()->getLmcsEnabledFlag() && m_pcReshape->getCTUFlag() && compID == COMPONENT_Y) +#else if (slice.getLmcsEnabledFlag() && m_pcReshape->getCTUFlag() && compID == COMPONENT_Y) +#endif { CompArea tmpArea(COMPONENT_Y, area.chromaFormat, Position(0, 0), area.size()); PelBuf tmpPred = m_tmpStorageLCU.getBuf(tmpArea); @@ -3349,7 +3381,11 @@ void IntraSearch::xIntraCodingTUBlock(TransformUnit &tu, const ComponentID &comp #endif flag =flag && (tu.blocks[compID].width*tu.blocks[compID].height > 4); +#if JVET_P1006_PICTURE_HEADER + if (flag && isChroma(compID) && slice.getPicHeader()->getLmcsChromaResidualScaleFlag() ) +#else if (flag && isChroma(compID) && slice.getLmcsChromaResidualScaleFlag() ) +#endif { int cResScaleInv = tu.getChromaAdj(); double cResScale = (double)(1 << CSCALE_FP_PREC) / (double)cResScaleInv; @@ -3513,7 +3549,11 @@ void IntraSearch::xIntraCodingTUBlock(TransformUnit &tu, const ComponentID &comp } //===== reconstruction ===== +#if JVET_P1006_PICTURE_HEADER + if ( flag && uiAbsSum > 0 && isChroma(compID) && slice.getPicHeader()->getLmcsChromaResidualScaleFlag() ) +#else if ( flag && uiAbsSum > 0 && isChroma(compID) && slice.getLmcsChromaResidualScaleFlag() ) +#endif { piResi.scaleSignal(tu.getChromaAdj(), 0, tu.cu->cs->slice->clpRng(compID)); if( jointCbCr ) @@ -3530,7 +3570,11 @@ void IntraSearch::xIntraCodingTUBlock(TransformUnit &tu, const ComponentID &comp } } +#if JVET_P1006_PICTURE_HEADER + if (slice.getPicHeader()->getLmcsEnabledFlag() && m_pcReshape->getCTUFlag() && compID == COMPONENT_Y) +#else if (slice.getLmcsEnabledFlag() && m_pcReshape->getCTUFlag() && compID == COMPONENT_Y) +#endif { CompArea tmpArea(COMPONENT_Y, area.chromaFormat, Position(0,0), area.size()); PelBuf tmpPred = m_tmpStorageLCU.getBuf(tmpArea); @@ -3550,7 +3594,11 @@ void IntraSearch::xIntraCodingTUBlock(TransformUnit &tu, const ComponentID &comp //===== update distortion ===== #if WCG_EXT if (m_pcEncCfg->getLumaLevelToDeltaQPMapping().isEnabled() || (m_pcEncCfg->getReshaper() +#if JVET_P1006_PICTURE_HEADER + && slice.getPicHeader()->getLmcsEnabledFlag() && (m_pcReshape->getCTUFlag() || (isChroma(compID) && m_pcEncCfg->getReshapeIntraCMD())))) +#else && slice.getLmcsEnabledFlag() && (m_pcReshape->getCTUFlag() || (isChroma(compID) && m_pcEncCfg->getReshapeIntraCMD())))) +#endif { const CPelBuf orgLuma = cs.getOrgBuf( cs.area.blocks[COMPONENT_Y] ); if (compID == COMPONENT_Y && !(m_pcEncCfg->getLumaLevelToDeltaQPMapping().isEnabled())) @@ -4349,7 +4397,11 @@ ChromaCbfs IntraSearch::xRecurIntraChromaCodingQT( CodingStructure &cs, Partitio resiCr.subtract( piPredCr ); //----- get reshape parameter ---- +#if JVET_P1006_PICTURE_HEADER + bool doReshaping = ( cs.picHeader->getLmcsEnabledFlag() && cs.picHeader->getLmcsChromaResidualScaleFlag() +#else bool doReshaping = ( cs.slice->getLmcsEnabledFlag() && cs.slice->getLmcsChromaResidualScaleFlag() +#endif && (cs.slice->isIntra() || m_pcReshape->getCTUFlag()) && (cbArea.width * cbArea.height > 4) ); if( doReshaping ) { diff --git a/source/Lib/EncoderLib/VLCWriter.cpp b/source/Lib/EncoderLib/VLCWriter.cpp index 96a733bfc..0df55b342 100644 --- a/source/Lib/EncoderLib/VLCWriter.cpp +++ b/source/Lib/EncoderLib/VLCWriter.cpp @@ -229,6 +229,20 @@ void HLSWriter::codePPS( const PPS* pcPPS, const SPS* pcSPS ) } WRITE_FLAG( pcPPS->getOutputFlagPresentFlag() ? 1 : 0, "output_flag_present_flag" ); +#if JVET_P1006_PICTURE_HEADER + WRITE_FLAG(pcPPS->getSubPicIdSignallingPresentFlag(), "pps_subpic_id_signalling_present_flag"); + if( pcPPS->getSubPicIdSignallingPresentFlag() ) + { + WRITE_UVLC( pcPPS->getNumSubPics() - 1, "pps_num_subpics_minus1" ); + + WRITE_UVLC( pcPPS->getSubPicIdLen() - 1, "pps_subpic_id_len_minus1" ); + + for( int picIdx = 0; picIdx < pcPPS->getNumSubPics( ); picIdx++ ) + { + WRITE_CODE( pcPPS->getSubPicId(picIdx), pcPPS->getSubPicIdLen( ), "pps_subpic_id[i]" ); + } + } +#endif WRITE_CODE( pcPPS->getNumExtraSliceHeaderBits(), 3, "num_extra_slice_header_bits"); WRITE_FLAG( pcPPS->getCabacInitPresentFlag() ? 1 : 0, "cabac_init_present_flag" ); WRITE_UVLC( pcPPS->getNumRefIdxL0DefaultActive()-1, "num_ref_idx_l0_default_active_minus1"); @@ -259,10 +273,12 @@ void HLSWriter::codePPS( const PPS* pcPPS, const SPS* pcSPS ) WRITE_UVLC(pcPPS->getLog2MaxTransformSkipBlockSize() - 2, "log2_max_transform_skip_block_size_minus2"); } WRITE_FLAG( pcPPS->getUseDQP() ? 1 : 0, "cu_qp_delta_enabled_flag" ); +#if !JVET_P1006_PICTURE_HEADER if ( pcPPS->getUseDQP() ) { WRITE_UVLC( pcPPS->getCuQpDeltaSubdiv(), "cu_qp_delta_subdiv" ); } +#endif WRITE_SVLC( pcPPS->getQpOffset(COMPONENT_Cb), "pps_cb_qp_offset" ); WRITE_SVLC( pcPPS->getQpOffset(COMPONENT_Cr), "pps_cr_qp_offset" ); @@ -285,7 +301,9 @@ void HLSWriter::codePPS( const PPS* pcPPS, const SPS* pcSPS ) WRITE_FLAG(uint32_t(pcPPS->getCuChromaQpOffsetEnabledFlag()), "cu_chroma_qp_offset_enabled_flag" ); if (pcPPS->getCuChromaQpOffsetEnabledFlag()) { +#if !JVET_P1006_PICTURE_HEADER WRITE_UVLC(pcPPS->getCuChromaQpOffsetSubdiv(), "cu_chroma_qp_offset_subdiv"); +#endif WRITE_UVLC(pcPPS->getChromaQpOffsetListLen() - 1, "chroma_qp_offset_list_len_minus1"); /* skip zero index */ for (int cuChromaQpOffsetIdx = 0; cuChromaQpOffsetIdx < pcPPS->getChromaQpOffsetListLen(); cuChromaQpOffsetIdx++) @@ -437,6 +455,7 @@ void HLSWriter::codePPS( const PPS* pcPPS, const SPS* pcSPS ) } } +#if !JVET_P1006_PICTURE_HEADER WRITE_FLAG( pcPPS->getLoopFilterAcrossVirtualBoundariesDisabledFlag() ? 1 : 0, "pps_loop_filter_across_virtual_boundaries_disabled_flag" ); if( pcPPS->getLoopFilterAcrossVirtualBoundariesDisabledFlag() ) { @@ -451,8 +470,12 @@ void HLSWriter::codePPS( const PPS* pcPPS, const SPS* pcSPS ) WRITE_CODE(pcPPS->getVirtualBoundariesPosY(i) >> 3, 13, "pps_virtual_boundaries_pos_y"); } } +#endif WRITE_UVLC( pcPPS->getLog2ParallelMergeLevelMinus2(), "log2_parallel_merge_level_minus2"); +#if JVET_P1006_PICTURE_HEADER + WRITE_FLAG( pcPPS->getPictureHeaderExtensionPresentFlag() ? 1 : 0, "picture_header_extension_present_flag"); +#endif WRITE_FLAG( pcPPS->getSliceHeaderExtensionPresentFlag() ? 1 : 0, "slice_segment_header_extension_present_flag"); bool pps_extension_present_flag=false; @@ -746,6 +769,22 @@ void HLSWriter::codeSPS( const SPS* pcSPS ) WRITE_UVLC( pcSPS->getMaxPicWidthInLumaSamples(), "pic_width_max_in_luma_samples" ); WRITE_UVLC( pcSPS->getMaxPicHeightInLumaSamples(), "pic_height_max_in_luma_samples" ); +#if JVET_P1006_PICTURE_HEADER + WRITE_FLAG( pcSPS->getSubPicIdPresentFlag(), "sps_subpic_id_present_flag"); + if( pcSPS->getSubPicIdPresentFlag() ) + { + WRITE_FLAG(pcSPS->getSubPicIdSignallingPresentFlag(), "sps_subpic_id_signalling_present_flag"); + if( pcSPS->getSubPicIdSignallingPresentFlag() ) + { + WRITE_UVLC( pcSPS->getSubPicIdLen( ) - 1, "sps_subpic_id_len_minus1" ); + for( int picIdx = 0; picIdx < pcSPS->getNumSubPics( ); picIdx++ ) + { + WRITE_CODE( pcSPS->getSubPicId(picIdx), pcSPS->getSubPicIdLen( ), "sps_subpic_id[i]" ); + } + } + } + +#endif #if JVET_P0243_SINGLE_BIT_DEPTH WRITE_UVLC( pcSPS->getBitDepth(CHANNEL_TYPE_LUMA) - 8, "bit_depth_minus8" ); #else @@ -999,6 +1038,23 @@ void HLSWriter::codeSPS( const SPS* pcSPS ) // KJS: remove scaling lists? WRITE_FLAG( pcSPS->getScalingListFlag() ? 1 : 0, "scaling_list_enabled_flag" ); +#if JVET_P1006_PICTURE_HEADER + WRITE_FLAG( pcSPS->getLoopFilterAcrossVirtualBoundariesDisabledFlag(), "sps_loop_filter_across_virtual_boundaries_disabled_present_flag" ); + if( pcSPS->getLoopFilterAcrossVirtualBoundariesDisabledFlag() ) + { + WRITE_CODE( pcSPS->getNumVerVirtualBoundaries(), 2, "sps_num_ver_virtual_boundaries"); + for( unsigned i = 0; i < pcSPS->getNumVerVirtualBoundaries(); i++ ) + { + WRITE_CODE((pcSPS->getVirtualBoundariesPosX(i)>>3), 13, "sps_virtual_boundaries_pos_x"); + } + WRITE_CODE(pcSPS->getNumHorVirtualBoundaries(), 2, "sps_num_hor_virtual_boundaries"); + for( unsigned i = 0; i < pcSPS->getNumHorVirtualBoundaries(); i++ ) + { + WRITE_CODE((pcSPS->getVirtualBoundariesPosY(i)>>3), 13, "sps_virtual_boundaries_pos_y"); + } + } + +#endif const TimingInfo *timingInfo = pcSPS->getTimingInfo(); WRITE_FLAG(pcSPS->getHrdParametersPresentFlag(), "general_hrd_parameters_present_flag"); if( pcSPS->getHrdParametersPresentFlag() ) @@ -1120,6 +1176,543 @@ void HLSWriter::codeVPS(const VPS* pcVPS) xWriteRbspTrailingBits(); } +#if JVET_P1006_PICTURE_HEADER +void HLSWriter::codePictureHeader( PicHeader* picHeader ) +{ + const PPS* pps = NULL; + const SPS* sps = NULL; + +#if ENABLE_TRACING + xTracePictureHeader (); +#endif + + CodingStructure& cs = *picHeader->getPic()->cs; + + WRITE_FLAG(picHeader->getNonReferencePictureFlag(), "non_reference_picture_flag"); + WRITE_FLAG(picHeader->getGdrPicFlag(), "gdr_pic_flag"); + WRITE_FLAG(picHeader->getNoOutputOfPriorPicsFlag(), "no_output_of_prior_pics_flag"); + if( picHeader->getGdrPicFlag() ) + { + WRITE_UVLC(picHeader->getRecoveryPocCnt(), "recovery_poc_cnt"); + } + else + { + picHeader->setRecoveryPocCnt( 0 ); + } + + // parameter sets + WRITE_UVLC(picHeader->getPPSId(), "ph_pic_parameter_set_id"); + pps = cs.slice->getPPS(); + CHECK(pps==0, "Invalid PPS"); + sps = cs.slice->getSPS(); + CHECK(sps==0, "Invalid SPS"); + + // sub-picture IDs + if( sps->getSubPicIdPresentFlag() ) + { + if( sps->getSubPicIdSignallingPresentFlag() ) + { + for( int picIdx = 0; picIdx < sps->getNumSubPics( ); picIdx++ ) + { + picHeader->setSubPicId( picIdx, sps->getSubPicId( picIdx ) ); + } + } + else + { + WRITE_FLAG(picHeader->getSubPicIdSignallingPresentFlag(), "ph_subpic_id_signalling_present_flag"); + if( picHeader->getSubPicIdSignallingPresentFlag() ) + { + WRITE_UVLC( picHeader->getSubPicIdLen() - 1, "ph_subpic_id_len_minus1" ); + for( int picIdx = 0; picIdx < sps->getNumSubPics( ); picIdx++ ) + { + WRITE_CODE(picHeader->getSubPicId(picIdx), picHeader->getSubPicIdLen( ), "ph_subpic_id[i]" ); + } + } + else + { + for( int picIdx = 0; picIdx < pps->getNumSubPics( ); picIdx++ ) + { + picHeader->setSubPicId( picIdx, pps->getSubPicId( picIdx ) ); + } + } + } + } + else + { + for( int picIdx = 0; picIdx < sps->getNumSubPics( ); picIdx++ ) + { + picHeader->setSubPicId( picIdx, picIdx ); + } + } + + // virtual boundaries + if( !sps->getLoopFilterAcrossVirtualBoundariesDisabledFlag() ) + { + WRITE_FLAG( picHeader->getLoopFilterAcrossVirtualBoundariesDisabledFlag(), "ph_loop_filter_across_virtual_boundaries_disabled_present_flag" ); + if( picHeader->getLoopFilterAcrossVirtualBoundariesDisabledFlag() ) + { + WRITE_CODE(picHeader->getNumVerVirtualBoundaries(), 2, "ph_num_ver_virtual_boundaries"); + for( unsigned i = 0; i < picHeader->getNumVerVirtualBoundaries(); i++ ) + { + WRITE_CODE(picHeader->getVirtualBoundariesPosX(i) >> 3, 13, "ph_virtual_boundaries_pos_x"); + } + WRITE_CODE(picHeader->getNumHorVirtualBoundaries(), 2, "ph_num_hor_virtual_boundaries"); + for( unsigned i = 0; i < picHeader->getNumHorVirtualBoundaries(); i++ ) + { + WRITE_CODE(picHeader->getVirtualBoundariesPosY(i)>>3, 13, "ph_virtual_boundaries_pos_y"); + } + } + else + { + picHeader->setLoopFilterAcrossVirtualBoundariesDisabledFlag( 0 ); + picHeader->setNumVerVirtualBoundaries( 0 ); + picHeader->setNumHorVirtualBoundaries( 0 ); + } + } + else + { + picHeader->setLoopFilterAcrossVirtualBoundariesDisabledFlag( sps->getLoopFilterAcrossVirtualBoundariesDisabledFlag() ); + picHeader->setNumVerVirtualBoundaries( sps->getNumVerVirtualBoundaries() ); + picHeader->setNumHorVirtualBoundaries( sps->getNumHorVirtualBoundaries() ); + for( unsigned i = 0; i < 3; i++ ) + { + picHeader->setVirtualBoundariesPosX( sps->getVirtualBoundariesPosX(i), i ); + picHeader->setVirtualBoundariesPosY( sps->getVirtualBoundariesPosY(i), i ); + } + } + + // 4:4:4 colour plane ID + if( sps->getSeparateColourPlaneFlag() ) + { + WRITE_CODE( picHeader->getColourPlaneId(), 2, "colour_plane_id" ); + } + else + { + picHeader->setColourPlaneId( 0 ); + } + + // picture output flag + if( pps->getOutputFlagPresentFlag() ) + { + WRITE_FLAG( picHeader->getPicOutputFlag(), "pic_output_flag" ); + } + else + { + picHeader->setPicOutputFlag(true); + } + + // reference picture lists + WRITE_FLAG( picHeader->getPicRplPresentFlag(), "pic_rpl_present_flag" ); + if( picHeader->getPicRplPresentFlag() ) + { + // List0 and List1 + for(int listIdx = 0; listIdx < 2; listIdx++) + { + // copy L1 index from L0 index + if (listIdx == 1 && !pps->getRpl1IdxPresentFlag()) + { + picHeader->setRPL1idx(picHeader->getRPL0idx()); + } + // RPL in picture header or SPS + else if (sps->getNumRPL(listIdx) > 0) + { + if (!pps->getPPSRefPicListSPSIdc(listIdx)) + { + WRITE_FLAG(picHeader->getRPLIdx(listIdx) != -1 ? 1 : 0, "pic_rpl_sps_flag[i]"); + } + else if (pps->getPPSRefPicListSPSIdc( listIdx ) == 1) + { + picHeader->setRPLIdx( listIdx, -1); + } + } + else + { + picHeader->setRPLIdx( listIdx, -1 ); + } + + // use list from SPS + if (picHeader->getRPLIdx(listIdx) != -1) + { + if (listIdx == 1 && !pps->getRpl1IdxPresentFlag()) + { + } + else if (sps->getNumRPL( listIdx ) > 1) + { + int numBits = ceilLog2(sps->getNumRPL( listIdx )); + WRITE_CODE(picHeader->getRPLIdx(listIdx), numBits, "pic_rpl_idx[i]"); + } + else + { + picHeader->setRPLIdx( listIdx, 0 ); + } + picHeader->setRPL( listIdx, sps->getRPLList( listIdx )->getReferencePictureList(picHeader->getRPLIdx(listIdx))); + } + // explicit RPL in picture header + else + { + xCodeRefPicList( picHeader->getRPL(listIdx), sps->getLongTermRefsPresent(), sps->getBitsForPOC(), !sps->getUseWP() && !sps->getUseWPBiPred() ); + } + + // POC MSB cycle signalling for LTRP + if (picHeader->getRPL(listIdx)->getNumberOfLongtermPictures()) + { + for (int i = 0; i < picHeader->getRPL(listIdx)->getNumberOfLongtermPictures() + picHeader->getRPL(listIdx)->getNumberOfShorttermPictures(); i++) + { + if (picHeader->getRPL(listIdx)->isRefPicLongterm(i)) + { + if (picHeader->getRPL(listIdx)->getLtrpInSliceHeaderFlag()) + { + WRITE_CODE(picHeader->getRPL(listIdx)->getRefPicIdentifier(i), sps->getBitsForPOC(), + "pic_poc_lsb_lt[listIdx][rplsIdx][j]"); + } + WRITE_FLAG(picHeader->getLocalRPL(listIdx)->getDeltaPocMSBPresentFlag(i) ? 1 : 0, "pic_delta_poc_msb_present_flag[i][j]"); + if (picHeader->getLocalRPL(listIdx)->getDeltaPocMSBPresentFlag(i)) + { + WRITE_UVLC(picHeader->getLocalRPL(listIdx)->getDeltaPocMSBCycleLT(i), "pic_delta_poc_msb_cycle_lt[i][j]"); + } + } + } + } + } + } + + // partitioning constraint overrides + if (sps->getSplitConsOverrideEnabledFlag()) + { + WRITE_FLAG(picHeader->getSplitConsOverrideFlag(), "partition_constraints_override_flag"); + if (picHeader->getSplitConsOverrideFlag()) + { + WRITE_UVLC(floorLog2(picHeader->getMinQTSize(I_SLICE)) - sps->getLog2MinCodingBlockSize(), "pic_log2_diff_min_qt_min_cb_intra_slice_luma"); + WRITE_UVLC(floorLog2(picHeader->getMinQTSize(P_SLICE)) - sps->getLog2MinCodingBlockSize(), "pic_log2_diff_min_qt_min_cb_inter_slice"); + WRITE_UVLC(picHeader->getMaxMTTHierarchyDepth(P_SLICE), "pic_max_mtt_hierarchy_depth_inter_slice"); + WRITE_UVLC(picHeader->getMaxMTTHierarchyDepth(I_SLICE), "pic_max_mtt_hierarchy_depth_intra_slice_luma"); + if (picHeader->getMaxMTTHierarchyDepth(I_SLICE) != 0) + { + WRITE_UVLC(floorLog2(picHeader->getMaxBTSize(I_SLICE)) - floorLog2(picHeader->getMinQTSize(I_SLICE)), "pic_log2_diff_max_bt_min_qt_intra_slice_luma"); + WRITE_UVLC(floorLog2(picHeader->getMaxTTSize(I_SLICE)) - floorLog2(picHeader->getMinQTSize(I_SLICE)), "pic_log2_diff_max_tt_min_qt_intra_slice_luma"); + } + if (picHeader->getMaxMTTHierarchyDepth(P_SLICE) != 0) + { + WRITE_UVLC(floorLog2(picHeader->getMaxBTSize(P_SLICE)) - floorLog2(picHeader->getMinQTSize(P_SLICE)), "pic_log2_diff_max_bt_min_qt_inter_slice"); + WRITE_UVLC(floorLog2(picHeader->getMaxTTSize(P_SLICE)) - floorLog2(picHeader->getMinQTSize(P_SLICE)), "pic_log2_diff_max_tt_min_qt_inter_slice"); + } + if (sps->getUseDualITree()) + { + WRITE_UVLC(floorLog2(picHeader->getMinQTSize(I_SLICE, CHANNEL_TYPE_CHROMA)) - sps->getLog2MinCodingBlockSize(), "pic_log2_diff_min_qt_min_cb_intra_slice_chroma"); + WRITE_UVLC(picHeader->getMaxMTTHierarchyDepth(I_SLICE, CHANNEL_TYPE_CHROMA), "pic_max_mtt_hierarchy_depth_intra_slice_chroma"); + if (picHeader->getMaxMTTHierarchyDepth(I_SLICE, CHANNEL_TYPE_CHROMA) != 0) + { + WRITE_UVLC(floorLog2(picHeader->getMaxBTSize(I_SLICE, CHANNEL_TYPE_CHROMA)) - floorLog2(picHeader->getMinQTSize(I_SLICE, CHANNEL_TYPE_CHROMA)), "pic_log2_diff_max_bt_min_qt_intra_slice_chroma"); + WRITE_UVLC(floorLog2(picHeader->getMaxTTSize(I_SLICE, CHANNEL_TYPE_CHROMA)) - floorLog2(picHeader->getMinQTSize(I_SLICE, CHANNEL_TYPE_CHROMA)), "pic_log2_diff_max_tt_min_qt_intra_slice_chroma"); + } + } + } + } + else + { + picHeader->setSplitConsOverrideFlag(0); + } + + // inherit constraint values from SPS + if (!sps->getSplitConsOverrideEnabledFlag() || !picHeader->getSplitConsOverrideFlag()) + { + picHeader->setMinQTSizes(sps->getMinQTSizes()); + picHeader->setMaxMTTHierarchyDepths(sps->getMaxMTTHierarchyDepths()); + picHeader->setMaxBTSizes(sps->getMaxBTSizes()); + picHeader->setMaxTTSizes(sps->getMaxTTSizes()); + } + + // delta quantization and chrom and chroma offset + if (pps->getUseDQP()) + { + WRITE_UVLC( picHeader->getCuQpDeltaSubdivIntra(), "pic_cu_qp_delta_subdiv_intra_slice" ); + WRITE_UVLC( picHeader->getCuQpDeltaSubdivInter(), "pic_cu_qp_delta_subdiv_inter_slice" ); + } + else + { + picHeader->setCuQpDeltaSubdivIntra( 0 ); + picHeader->setCuQpDeltaSubdivInter( 0 ); + } + if (pps->getCuChromaQpOffsetEnabledFlag()) + { + WRITE_UVLC( picHeader->getCuChromaQpOffsetSubdivIntra(), "pic_cu_chroma_qp_offset_subdiv_intra_slice" ); + WRITE_UVLC( picHeader->getCuChromaQpOffsetSubdivInter(), "pic_cu_chroma_qp_offset_subdiv_inter_slice" ); + } + else + { + picHeader->setCuChromaQpOffsetSubdivIntra( 0 ); + picHeader->setCuChromaQpOffsetSubdivInter( 0 ); + } + + // temporal motion vector prediction + if (sps->getSPSTemporalMVPEnabledFlag()) + { + WRITE_FLAG( picHeader->getEnableTMVPFlag(), "pic_temporal_mvp_enabled_flag" ); + } + else + { + picHeader->setEnableTMVPFlag(false); + } + + // mvd L1 zero flag + if (!pps->getPPSMvdL1ZeroIdc()) + { + WRITE_FLAG(picHeader->getMvdL1ZeroFlag(), "pic_mvd_l1_zero_flag"); + } + else + { + picHeader->setMvdL1ZeroFlag( pps->getPPSMvdL1ZeroIdc() - 1 ); + } + + // merge candidate list size + if (!pps->getPPSSixMinusMaxNumMergeCandPlus1()) + { + CHECK(picHeader->getMaxNumMergeCand() > MRG_MAX_NUM_CANDS, "More merge candidates signalled than supported"); + WRITE_UVLC(MRG_MAX_NUM_CANDS - picHeader->getMaxNumMergeCand(), "pic_six_minus_max_num_merge_cand"); + } + else + { + picHeader->setMaxNumMergeCand(MRG_MAX_NUM_CANDS - (pps->getPPSSixMinusMaxNumMergeCandPlus1() - 1)); + } + + // subblock merge candidate list size + if ( sps->getUseAffine() ) + { + CHECK( picHeader->getMaxNumAffineMergeCand() > AFFINE_MRG_MAX_NUM_CANDS, "More affine merge candidates signalled than supported" ); + WRITE_UVLC(AFFINE_MRG_MAX_NUM_CANDS - picHeader->getMaxNumAffineMergeCand(), "pic_five_minus_max_num_subblock_merge_cand"); + } + else + { + picHeader->setMaxNumAffineMergeCand( sps->getSBTMVPEnabledFlag() && picHeader->getEnableTMVPFlag() ); + } + + // full-pel MMVD flag + if (sps->getFpelMmvdEnabledFlag()) + { + WRITE_FLAG( picHeader->getDisFracMMVD(), "pic_fpel_mmvd_enabled_flag" ); + } + else + { + picHeader->setDisFracMMVD(false); + } + + // picture level BDOF/DMVR/PROF disable flags + if (sps->getBdofDmvrSlicePresentFlag()) + { + WRITE_FLAG(picHeader->getDisBdofDmvrFlag(), "pic_disable_bdof_dmvr_flag"); + } + else + { + picHeader->setDisBdofDmvrFlag(0); + } + + // triangle merge candidate list size + if (sps->getUseTriangle() && picHeader->getMaxNumMergeCand() >= 2) + { + if (!pps->getPPSMaxNumMergeCandMinusMaxNumTriangleCandPlus1()) + { + CHECK(picHeader->getMaxNumMergeCand() < picHeader->getMaxNumTriangleCand(), "Incorrrect max number of triangle candidates!"); + WRITE_UVLC(picHeader->getMaxNumMergeCand() - picHeader->getMaxNumTriangleCand(), "pic_max_num_merge_cand_minus_max_num_triangle_cand"); + } + else + { + picHeader->setMaxNumTriangleCand((uint32_t)(picHeader->getMaxNumMergeCand() - (pps->getPPSMaxNumMergeCandMinusMaxNumTriangleCandPlus1() - 1))); + } + } + + // ibc merge candidate list size + if (sps->getIBCFlag()) + { + CHECK( picHeader->getMaxNumIBCMergeCand() > IBC_MRG_MAX_NUM_CANDS, "More IBC merge candidates signalled than supported" ); + WRITE_UVLC(IBC_MRG_MAX_NUM_CANDS - picHeader->getMaxNumIBCMergeCand(), "pic_six_minus_max_num_ibc_merge_cand"); + } + + // joint Cb/Cr sign flag + if (sps->getJointCbCrEnabledFlag()) + { + WRITE_FLAG( picHeader->getJointCbCrSignFlag(), "pic_joint_cbcr_sign_flag" ); + } + else + { + picHeader->setJointCbCrSignFlag(false); + } + + // sao enable flags + if(sps->getSAOEnabledFlag()) + { + WRITE_FLAG(picHeader->getSaoEnabledPresentFlag(), "pic_sao_enabled_present_flag"); + if (picHeader->getSaoEnabledPresentFlag()) + { + WRITE_FLAG(picHeader->getSaoEnabledFlag(CHANNEL_TYPE_LUMA), "slice_sao_luma_flag"); + if (sps->getChromaFormatIdc() != CHROMA_400) + { + WRITE_FLAG(picHeader->getSaoEnabledFlag(CHANNEL_TYPE_CHROMA), "slice_sao_chroma_flag"); + } + } + else + { + picHeader->setSaoEnabledFlag(CHANNEL_TYPE_LUMA, true); + picHeader->setSaoEnabledFlag(CHANNEL_TYPE_CHROMA, true); + } + } + else + { + picHeader->setSaoEnabledFlag(CHANNEL_TYPE_LUMA, false); + picHeader->setSaoEnabledFlag(CHANNEL_TYPE_CHROMA, false); + } + + // alf enable flags and aps IDs + if( sps->getALFEnabledFlag() ) + { + WRITE_FLAG(picHeader->getAlfEnabledPresentFlag(), "pic_alf_enabled_present_flag"); + if (picHeader->getAlfEnabledPresentFlag()) + { + WRITE_FLAG(picHeader->getAlfEnabledFlag(COMPONENT_Y), "pic_alf_enabled_flag"); + if (picHeader->getAlfEnabledFlag(COMPONENT_Y)) + { + WRITE_CODE(picHeader->getNumAlfAps(), 3, "pic_num_alf_aps_ids_luma"); + const std::vector<int>& apsId = picHeader->getAlfAPSs(); + for (int i = 0; i < picHeader->getNumAlfAps(); i++) + { + WRITE_CODE(apsId[i], 3, "pic_alf_aps_id_luma"); + } + + const int alfChromaIdc = picHeader->getAlfEnabledFlag(COMPONENT_Cb) + picHeader->getAlfEnabledFlag(COMPONENT_Cr) * 2 ; + if (sps->getChromaFormatIdc() != CHROMA_400) + { + WRITE_CODE(alfChromaIdc, 2, "pic_alf_chroma_idc"); + } + if (alfChromaIdc) + { + WRITE_CODE(picHeader->getAlfApsIdChroma(), 3, "pic_alf_aps_id_chroma"); + } + } + } + else + { + picHeader->setAlfEnabledFlag(COMPONENT_Y, true); + picHeader->setAlfEnabledFlag(COMPONENT_Cb, true); + picHeader->setAlfEnabledFlag(COMPONENT_Cr, true); + } + } + else + { + picHeader->setAlfEnabledFlag(COMPONENT_Y, false); + picHeader->setAlfEnabledFlag(COMPONENT_Cb, false); + picHeader->setAlfEnabledFlag(COMPONENT_Cr, false); + } + + // dependent quantization + if (!pps->getPPSDepQuantEnabledIdc()) + { + WRITE_FLAG(picHeader->getDepQuantEnabledFlag(), "pic_dep_quant_enabled_flag"); + } + else + { + picHeader->setDepQuantEnabledFlag( pps->getPPSDepQuantEnabledIdc() - 1 ); + } + + // sign data hiding + if( !picHeader->getDepQuantEnabledFlag() ) + { + WRITE_FLAG( picHeader->getSignDataHidingEnabledFlag(), "pic_sign_data_hiding_enabled_flag" ); + } + else + { + picHeader->setSignDataHidingEnabledFlag(false); + } + + // deblocking filter controls + if (pps->getDeblockingFilterControlPresentFlag()) + { + if(pps->getDeblockingFilterOverrideEnabledFlag()) + { + WRITE_FLAG ( picHeader->getDeblockingFilterOverridePresentFlag(), "pic_deblocking_filter_override_present_flag" ); + if( picHeader->getDeblockingFilterOverridePresentFlag() ) + { + WRITE_FLAG ( picHeader->getDeblockingFilterOverrideFlag(), "pic_deblocking_filter_override_flag" ); + } + else + { + picHeader->setDeblockingFilterOverrideFlag(false); + } + } + else + { + picHeader->setDeblockingFilterOverridePresentFlag(false); + picHeader->setDeblockingFilterOverrideFlag(false); + } + + if(picHeader->getDeblockingFilterOverrideFlag()) + { + WRITE_FLAG ( picHeader->getDeblockingFilterDisable(), "pic_deblocking_filter_disabled_flag" ); + if(!picHeader->getDeblockingFilterDisable()) + { + WRITE_SVLC( picHeader->getDeblockingFilterBetaOffsetDiv2(), "pic_beta_offset_div2" ); + WRITE_SVLC( picHeader->getDeblockingFilterTcOffsetDiv2(), "pic_tc_offset_div2" ); + } + } + else + { + picHeader->setDeblockingFilterDisable ( pps->getPPSDeblockingFilterDisabledFlag() ); + picHeader->setDeblockingFilterBetaOffsetDiv2( pps->getDeblockingFilterBetaOffsetDiv2() ); + picHeader->setDeblockingFilterTcOffsetDiv2 ( pps->getDeblockingFilterTcOffsetDiv2() ); + } + } + else + { + picHeader->setDeblockingFilterDisable ( false ); + picHeader->setDeblockingFilterBetaOffsetDiv2( 0 ); + picHeader->setDeblockingFilterTcOffsetDiv2 ( 0 ); + } + + // luma mapping / chroma scaling controls + if (sps->getUseReshaper()) + { + WRITE_FLAG(picHeader->getLmcsEnabledFlag(), "pic_lmcs_enabled_flag"); + if (picHeader->getLmcsEnabledFlag()) + { + WRITE_CODE(picHeader->getLmcsAPSId(), 2, "pic_lmcs_aps_id"); + if (sps->getChromaFormatIdc() != CHROMA_400) + { + WRITE_FLAG(picHeader->getLmcsChromaResidualScaleFlag(), "pic_chroma_residual_scale_flag"); + } + else + { + picHeader->setLmcsChromaResidualScaleFlag(false); + } + } + } + else + { + picHeader->setLmcsEnabledFlag(false); + picHeader->setLmcsChromaResidualScaleFlag(false); + } + + // quantization scaling lists + if( sps->getScalingListFlag() ) + { + WRITE_FLAG( picHeader->getScalingListPresentFlag(), "pic_scaling_list_present_flag" ); + if( picHeader->getScalingListPresentFlag() ) + { + WRITE_CODE( picHeader->getScalingListAPSId(), 3, "pic_scaling_list_aps_id" ); + } + } + else + { + picHeader->setScalingListPresentFlag( false ); + } + + // picture header extension + if(pps->getPictureHeaderExtensionPresentFlag()) + { + WRITE_UVLC(0,"pic_segment_header_extension_length"); + } + + xWriteRbspTrailingBits(); +} + +#endif void HLSWriter::codeSliceHeader ( Slice* pcSlice ) { #if ENABLE_TRACING @@ -1127,11 +1720,22 @@ void HLSWriter::codeSliceHeader ( Slice* pcSlice ) #endif CodingStructure& cs = *pcSlice->getPic()->cs; +#if JVET_P1006_PICTURE_HEADER + const PicHeader *picHeader = cs.picHeader; +#endif const ChromaFormat format = pcSlice->getSPS()->getChromaFormatIdc(); const uint32_t numberValidComponents = getNumberValidComponents(format); const bool chromaEnabled = isChromaEnabled(format); +#if JVET_P1006_PICTURE_HEADER + int pocBits = pcSlice->getSPS()->getBitsForPOC(); + int pocMask = (1 << pocBits) - 1; + WRITE_CODE(pcSlice->getPOC() & pocMask, pocBits, "slice_pic_order_cnt_lsb"); +#endif + +#if !JVET_P1006_PICTURE_HEADER WRITE_UVLC( pcSlice->getPPS()->getPPSId(), "slice_pic_parameter_set_id" ); +#endif int bitsSliceAddress = 1; if (!pcSlice->getPPS()->getRectSliceFlag()) { @@ -1170,16 +1774,19 @@ void HLSWriter::codeSliceHeader ( Slice* pcSlice ) WRITE_UVLC(pcSlice->getSliceNumBricks() - 1, "num_bricks_in_slice_minus1"); } +#if !JVET_P1006_PICTURE_HEADER WRITE_FLAG(pcSlice->getNonRefPictFlag() ? 1 : 0, "non_reference_picture_flag"); for( int i = 0; i < pcSlice->getPPS()->getNumExtraSliceHeaderBits(); i++ ) { WRITE_FLAG( 0, "slice_reserved_flag[]" ); } +#endif WRITE_UVLC( pcSlice->getSliceType(), "slice_type" ); +#if !JVET_P1006_PICTURE_HEADER int pocBits = pcSlice->getSPS()->getBitsForPOC(); int pocMask = (1 << pocBits) - 1; WRITE_CODE(pcSlice->getPOC() & pocMask, pocBits, "slice_pic_order_cnt_lsb"); @@ -1197,7 +1804,13 @@ void HLSWriter::codeSliceHeader ( Slice* pcSlice ) { WRITE_FLAG(pcSlice->getPicOutputFlag() ? 1 : 0, "pic_output_flag"); } +#endif + +#if JVET_P1006_PICTURE_HEADER + if( !picHeader->getPicRplPresentFlag() && (!pcSlice->getIdrPicFlag() || pcSlice->getSPS()->getIDRRefParamListPresent()) ) +#else if( !pcSlice->getIdrPicFlag() || pcSlice->getSPS()->getIDRRefParamListPresent()) +#endif { //Write L0 related syntax elements if (pcSlice->getSPS()->getNumRPL0() > 0) @@ -1299,7 +1912,12 @@ void HLSWriter::codeSliceHeader ( Slice* pcSlice ) } } } +#if JVET_P1006_PICTURE_HEADER + } + if( picHeader->getPicRplPresentFlag() || !pcSlice->getIdrPicFlag() || pcSlice->getSPS()->getIDRRefParamListPresent() ) + { +#endif //check if numrefidxes match the defaults. If not, override if ((!pcSlice->isIntra() && pcSlice->getRPL0()->getNumRefEntries() > 1) || @@ -1342,6 +1960,7 @@ void HLSWriter::codeSliceHeader ( Slice* pcSlice ) } } +#if !JVET_P1006_PICTURE_HEADER if ( pcSlice->getSPS()->getSplitConsOverrideEnabledFlag() ) @@ -1394,6 +2013,7 @@ void HLSWriter::codeSliceHeader ( Slice* pcSlice ) WRITE_FLAG( pcSlice->getMvdL1ZeroFlag() ? 1 : 0, "mvd_l1_zero_flag" ); } } +#endif if( !pcSlice->isIntra() ) { @@ -1407,7 +2027,11 @@ void HLSWriter::codeSliceHeader ( Slice* pcSlice ) } } +#if JVET_P1006_PICTURE_HEADER + if( pcSlice->getPicHeader()->getEnableTMVPFlag() ) +#else if( pcSlice->getEnableTMVPFlag() ) +#endif { if( pcSlice->getSliceType() == B_SLICE ) { @@ -1430,6 +2054,7 @@ void HLSWriter::codeSliceHeader ( Slice* pcSlice ) xCodePredWeightTable( pcSlice ); } +#if !JVET_P1006_PICTURE_HEADER if (!cs.slice->isIntra()) { CHECK(pcSlice->getMaxNumMergeCand() > MRG_MAX_NUM_CANDS, "More merge candidates signalled than supported"); @@ -1492,6 +2117,7 @@ void HLSWriter::codeSliceHeader ( Slice* pcSlice ) { WRITE_FLAG( pcSlice->getJointCbCrSignFlag() ? 1 : 0, "slice_joint_cbcr_sign_flag"); } +#endif int iCode = pcSlice->getSliceQp() - ( pcSlice->getPPS()->getPicInitQPMinus26() + 26 ); WRITE_SVLC( iCode, "slice_qp_delta" ); @@ -1512,12 +2138,18 @@ void HLSWriter::codeSliceHeader ( Slice* pcSlice ) CHECK(numberValidComponents < COMPONENT_Cr+1, "Too many valid components"); } +#if !JVET_P1006_PICTURE_HEADER if (pcSlice->getPPS()->getCuChromaQpOffsetEnabledFlag()) { WRITE_FLAG(pcSlice->getUseChromaQpAdj(), "cu_chroma_qp_offset_enabled_flag"); } +#endif +#if JVET_P1006_PICTURE_HEADER + if( pcSlice->getSPS()->getSAOEnabledFlag() && !picHeader->getSaoEnabledPresentFlag() ) +#else if( pcSlice->getSPS()->getSAOEnabledFlag() ) +#endif { WRITE_FLAG( pcSlice->getSaoEnabledFlag( CHANNEL_TYPE_LUMA ), "slice_sao_luma_flag" ); if( chromaEnabled ) @@ -1526,7 +2158,11 @@ void HLSWriter::codeSliceHeader ( Slice* pcSlice ) } } +#if JVET_P1006_PICTURE_HEADER + if( pcSlice->getSPS()->getALFEnabledFlag() && !picHeader->getAlfEnabledPresentFlag() ) +#else if( pcSlice->getSPS()->getALFEnabledFlag() ) +#endif { const int alfEnabled = pcSlice->getTileGroupAlfEnabledFlag(COMPONENT_Y); WRITE_FLAG(alfEnabled, "slice_alf_enabled_flag"); @@ -1552,6 +2188,7 @@ void HLSWriter::codeSliceHeader ( Slice* pcSlice ) } } +#if !JVET_P1006_PICTURE_HEADER if (!pcSlice->getPPS()->getPPSDepQuantEnabledIdc()) { WRITE_FLAG( pcSlice->getDepQuantEnabledFlag() ? 1 : 0, "dep_quant_enabled_flag" ); @@ -1564,12 +2201,23 @@ void HLSWriter::codeSliceHeader ( Slice* pcSlice ) { CHECK( pcSlice->getSignDataHidingEnabledFlag(), "sign data hiding not supported when dependent quantization is enabled" ); } +#endif if (pcSlice->getPPS()->getDeblockingFilterControlPresentFlag()) { +#if JVET_P1006_PICTURE_HEADER + if (pcSlice->getPPS()->getDeblockingFilterOverrideEnabledFlag() && !picHeader->getDeblockingFilterOverridePresentFlag()) +#else if (pcSlice->getPPS()->getDeblockingFilterOverrideEnabledFlag() ) +#endif { WRITE_FLAG(pcSlice->getDeblockingFilterOverrideFlag(), "deblocking_filter_override_flag"); } +#if JVET_P1006_PICTURE_HEADER + else + { + pcSlice->setDeblockingFilterOverrideFlag(0); + } +#endif if (pcSlice->getDeblockingFilterOverrideFlag()) { WRITE_FLAG(pcSlice->getDeblockingFilterDisable(), "slice_deblocking_filter_disabled_flag"); @@ -1579,8 +2227,25 @@ void HLSWriter::codeSliceHeader ( Slice* pcSlice ) WRITE_SVLC (pcSlice->getDeblockingFilterTcOffsetDiv2(), "slice_tc_offset_div2"); } } +#if JVET_P1006_PICTURE_HEADER + else + { + pcSlice->setDeblockingFilterDisable ( picHeader->getDeblockingFilterDisable() ); + pcSlice->setDeblockingFilterBetaOffsetDiv2( picHeader->getDeblockingFilterBetaOffsetDiv2() ); + pcSlice->setDeblockingFilterTcOffsetDiv2 ( picHeader->getDeblockingFilterTcOffsetDiv2() ); + } +#endif } +#if JVET_P1006_PICTURE_HEADER + else + { + pcSlice->setDeblockingFilterDisable ( false ); + pcSlice->setDeblockingFilterBetaOffsetDiv2( 0 ); + pcSlice->setDeblockingFilterTcOffsetDiv2 ( 0 ); + } +#endif +#if !JVET_P1006_PICTURE_HEADER bool isSAOEnabled = pcSlice->getSPS()->getSAOEnabledFlag() && (pcSlice->getSaoEnabledFlag(CHANNEL_TYPE_LUMA) || (chromaEnabled && pcSlice->getSaoEnabledFlag(CHANNEL_TYPE_CHROMA))); bool isDBFEnabled = (!pcSlice->getDeblockingFilterDisable()); @@ -1610,6 +2275,7 @@ void HLSWriter::codeSliceHeader ( Slice* pcSlice ) WRITE_CODE( pcSlice->getscalingListAPSId(), 3, "slice_scaling_list_aps_id" ); } } +#endif if(pcSlice->getPPS()->getSliceHeaderExtensionPresentFlag()) { WRITE_UVLC(0,"slice_segment_header_extension_length"); diff --git a/source/Lib/EncoderLib/VLCWriter.h b/source/Lib/EncoderLib/VLCWriter.h index 662c6f99c..5e4784796 100644 --- a/source/Lib/EncoderLib/VLCWriter.h +++ b/source/Lib/EncoderLib/VLCWriter.h @@ -131,6 +131,9 @@ public: void codeScalingListAps ( APS* pcAPS ); void codeVPS ( const VPS* pcVPS ); void codeDPS ( const DPS* dps ); +#if JVET_P1006_PICTURE_HEADER + void codePictureHeader ( PicHeader* picHeader ); +#endif void codeSliceHeader ( Slice* pcSlice ); void codeConstraintInfo ( const ConstraintInfo* cinfo ); void codeProfileTierLevel ( const ProfileTierLevel* ptl, int maxNumSubLayersMinus1 ); -- GitLab