diff --git a/cfg/sei/timing.cfg b/cfg/sei/timing.cfg new file mode 100755 index 0000000000000000000000000000000000000000..63f37a73919737867258e173f4c611176003d05d --- /dev/null +++ b/cfg/sei/timing.cfg @@ -0,0 +1,4 @@ +SEIBufferingPeriod: 1 +SEIPictureTiming: 1 +VuiParametersPresent: 1 +RCCpbSize: 2000 diff --git a/source/App/EncoderApp/EncAppCfg.cpp b/source/App/EncoderApp/EncAppCfg.cpp index 63377a35e5ff1daecbe7b44074ebdff5b3668227..cdce5d769cecca54ef35052237edbb5bffc88045 100644 --- a/source/App/EncoderApp/EncAppCfg.cpp +++ b/source/App/EncoderApp/EncAppCfg.cpp @@ -2603,6 +2603,8 @@ bool EncAppCfg::xCheckParameter() m_crossComponentPredictionEnabledFlag = false; } + xConfirmPara( m_bufferingPeriodSEIEnabled == true && m_RCCpbSize == 0, "RCCpbSize must be greater than zero, when buffering period SEI is enabled" ); + if ( m_CUTransquantBypassFlagForce && m_bUseHADME ) { msg( WARNING, "****************************************************************************\n"); diff --git a/source/Lib/CommonLib/HRD.h b/source/Lib/CommonLib/HRD.h index 3c70bdad9bb03fc4ef4da23bda1fc317f231ac36..3d3c672037ac6eb0de1714064d85c046e555eea8 100644 --- a/source/Lib/CommonLib/HRD.h +++ b/source/Lib/CommonLib/HRD.h @@ -36,6 +36,9 @@ #define __HRD__ #include "Common.h" +#if JVET_N0353_INDEP_BUFF_TIME_SEI +#include "SEI.h" +#endif class TimingInfo { @@ -92,14 +95,20 @@ private: bool m_subPicCpbParamsPresentFlag; uint32_t m_tickDivisorMinus2; uint32_t m_duCpbRemovalDelayLengthMinus1; +#if !JVET_N0353_INDEP_BUFF_TIME_SEI bool m_subPicCpbParamsInPicTimingSEIFlag; +#else + bool m_decodingUnitHrdParamsPresentFlag; +#endif uint32_t m_dpbOutputDelayDuLengthMinus1; uint32_t m_bitRateScale; uint32_t m_cpbSizeScale; uint32_t m_ducpbSizeScale; +#if !JVET_N0353_INDEP_BUFF_TIME_SEI uint32_t m_initialCpbRemovalDelayLengthMinus1; uint32_t m_cpbRemovalDelayLengthMinus1; uint32_t m_dpbOutputDelayLengthMinus1; +#endif HrdSubLayerInfo m_HRD[MAX_TLAYER]; public: @@ -109,13 +118,19 @@ public: ,m_subPicCpbParamsPresentFlag (false) ,m_tickDivisorMinus2 (0) ,m_duCpbRemovalDelayLengthMinus1 (0) +#if !JVET_N0353_INDEP_BUFF_TIME_SEI ,m_subPicCpbParamsInPicTimingSEIFlag (false) +#else + ,m_decodingUnitHrdParamsPresentFlag (false) +#endif ,m_dpbOutputDelayDuLengthMinus1 (0) ,m_bitRateScale (0) ,m_cpbSizeScale (0) +#if !JVET_N0353_INDEP_BUFF_TIME_SEI ,m_initialCpbRemovalDelayLengthMinus1(23) ,m_cpbRemovalDelayLengthMinus1 (23) ,m_dpbOutputDelayLengthMinus1 (23) +#endif {} virtual ~HRDParameters() {} @@ -135,8 +150,13 @@ public: void setDuCpbRemovalDelayLengthMinus1( uint32_t value ) { m_duCpbRemovalDelayLengthMinus1 = value; } uint32_t getDuCpbRemovalDelayLengthMinus1( ) const { return m_duCpbRemovalDelayLengthMinus1; } +#if !JVET_N0353_INDEP_BUFF_TIME_SEI void setSubPicCpbParamsInPicTimingSEIFlag( bool flag) { m_subPicCpbParamsInPicTimingSEIFlag = flag; } bool getSubPicCpbParamsInPicTimingSEIFlag( ) const { return m_subPicCpbParamsInPicTimingSEIFlag; } +#else + void setDecodingUnitHrdParamsPresentFlag( bool flag) { m_decodingUnitHrdParamsPresentFlag = flag; } + bool getDecodingUnitHrdParamsPresentFlag( ) const { return m_decodingUnitHrdParamsPresentFlag; } +#endif void setDpbOutputDelayDuLengthMinus1(uint32_t value ) { m_dpbOutputDelayDuLengthMinus1 = value; } uint32_t getDpbOutputDelayDuLengthMinus1( ) const { return m_dpbOutputDelayDuLengthMinus1; } @@ -149,6 +169,7 @@ public: void setDuCpbSizeScale( uint32_t value ) { m_ducpbSizeScale = value; } uint32_t getDuCpbSizeScale( ) const { return m_ducpbSizeScale; } +#if !JVET_N0353_INDEP_BUFF_TIME_SEI void setInitialCpbRemovalDelayLengthMinus1( uint32_t value ) { m_initialCpbRemovalDelayLengthMinus1 = value; } uint32_t getInitialCpbRemovalDelayLengthMinus1( ) const { return m_initialCpbRemovalDelayLengthMinus1; } @@ -157,6 +178,7 @@ public: void setDpbOutputDelayLengthMinus1( uint32_t value ) { m_dpbOutputDelayLengthMinus1 = value; } uint32_t getDpbOutputDelayLengthMinus1( ) const { return m_dpbOutputDelayLengthMinus1; } +#endif void setFixedPicRateFlag( int layer, bool flag ) { m_HRD[layer].fixedPicRateFlag = flag; } bool getFixedPicRateFlag( int layer ) const { return m_HRD[layer].fixedPicRateFlag; } @@ -192,6 +214,9 @@ class HRD { public: HRD() +#if JVET_N0353_INDEP_BUFF_TIME_SEI + :m_bufferingPeriodInitialized (false) +#endif {}; virtual ~HRD() @@ -205,9 +230,18 @@ public: TimingInfo getTimingInfo() const { return m_timingInfo; } const TimingInfo& getTimingInfo() { return m_timingInfo; } +#if JVET_N0353_INDEP_BUFF_TIME_SEI + void setBufferingPeriodSEI(const SEIBufferingPeriod* bp) { bp->copyTo(m_bufferingPeriodSEI); m_bufferingPeriodInitialized = true; } + const SEIBufferingPeriod* getBufferingPeriodSEI() const { return m_bufferingPeriodInitialized ? &m_bufferingPeriodSEI : nullptr; } +#endif + protected: HRDParameters m_hrdParams; TimingInfo m_timingInfo; +#if JVET_N0353_INDEP_BUFF_TIME_SEI + bool m_bufferingPeriodInitialized; + SEIBufferingPeriod m_bufferingPeriodSEI; +#endif }; #endif //__HRD__ \ No newline at end of file diff --git a/source/Lib/CommonLib/SEI.cpp b/source/Lib/CommonLib/SEI.cpp index 6f5b7366b5e395f8d86a30b23ccfe61e6b656378..933cff0bbf7c884a332e342235093bc326a4ae9d 100644 --- a/source/Lib/CommonLib/SEI.cpp +++ b/source/Lib/CommonLib/SEI.cpp @@ -96,21 +96,37 @@ void deleteSEIs (SEIMessages &seiList) seiList.clear(); } -void SEIBufferingPeriod::copyTo (SEIBufferingPeriod& target) +void SEIBufferingPeriod::copyTo (SEIBufferingPeriod& target) const { +#if !JVET_N0353_INDEP_BUFF_TIME_SEI target.m_bpSeqParameterSetId = m_bpSeqParameterSetId; target.m_rapCpbParamsPresentFlag = m_rapCpbParamsPresentFlag; +#else + target.m_bpNalCpbParamsPresentFlag = m_bpNalCpbParamsPresentFlag; + target.m_bpVclCpbParamsPresentFlag = m_bpVclCpbParamsPresentFlag; + target.m_initialCpbRemovalDelayLength = m_initialCpbRemovalDelayLength; + target.m_cpbRemovalDelayLength = m_cpbRemovalDelayLength; + target.m_dpbOutputDelayLength = m_dpbOutputDelayLength; + target.m_bpCpbCnt = m_bpCpbCnt; +#endif target.m_cpbDelayOffset = m_cpbDelayOffset; target.m_dpbDelayOffset = m_dpbDelayOffset; target.m_concatenationFlag = m_concatenationFlag; target.m_auCpbRemovalDelayDelta = m_auCpbRemovalDelayDelta; +#if !JVET_N0353_INDEP_BUFF_TIME_SEI ::memcpy(target.m_initialCpbRemovalDelay, m_initialCpbRemovalDelay, sizeof(m_initialCpbRemovalDelay)); ::memcpy(target.m_initialCpbRemovalDelayOffset, m_initialCpbRemovalDelayOffset, sizeof(m_initialCpbRemovalDelayOffset)); ::memcpy(target.m_initialAltCpbRemovalDelay, m_initialAltCpbRemovalDelay, sizeof(m_initialAltCpbRemovalDelay)); ::memcpy(target.m_initialAltCpbRemovalDelayOffset, m_initialAltCpbRemovalDelayOffset, sizeof(m_initialAltCpbRemovalDelayOffset)); +#else + target.m_initialCpbRemovalDelay[0] = m_initialCpbRemovalDelay [0]; + target.m_initialCpbRemovalDelay[1] = m_initialCpbRemovalDelay [1]; + target.m_initialCpbRemovalOffset[0] = m_initialCpbRemovalOffset [0]; + target.m_initialCpbRemovalOffset[1] = m_initialCpbRemovalOffset [1]; +#endif } -void SEIPictureTiming::copyTo (SEIPictureTiming& target) +void SEIPictureTiming::copyTo (SEIPictureTiming& target) const { target.m_picStruct = m_picStruct; target.m_sourceScanType = m_sourceScanType; diff --git a/source/Lib/CommonLib/SEI.h b/source/Lib/CommonLib/SEI.h index f678bc9461ef05ad1a51baa8dc0bd23317574682..e468057195ccc553727f309ec81f63c024f29aff 100644 --- a/source/Lib/CommonLib/SEI.h +++ b/source/Lib/CommonLib/SEI.h @@ -167,37 +167,63 @@ class SEIBufferingPeriod : public SEI { public: PayloadType payloadType() const { return BUFFERING_PERIOD; } - void copyTo (SEIBufferingPeriod& target); + void copyTo (SEIBufferingPeriod& target) const; SEIBufferingPeriod() +#if !JVET_N0353_INDEP_BUFF_TIME_SEI : m_bpSeqParameterSetId (0) , m_rapCpbParamsPresentFlag (false) +#else + : m_bpNalCpbParamsPresentFlag (false) + , m_bpVclCpbParamsPresentFlag (false) + , m_initialCpbRemovalDelayLength (0) + , m_cpbRemovalDelayLength (0) + , m_dpbOutputDelayLength (0) + , m_bpCpbCnt (0) +#endif , m_cpbDelayOffset (0) , m_dpbDelayOffset (0) { +#if !JVET_N0353_INDEP_BUFF_TIME_SEI ::memset(m_initialCpbRemovalDelay, 0, sizeof(m_initialCpbRemovalDelay)); ::memset(m_initialCpbRemovalDelayOffset, 0, sizeof(m_initialCpbRemovalDelayOffset)); ::memset(m_initialAltCpbRemovalDelay, 0, sizeof(m_initialAltCpbRemovalDelay)); ::memset(m_initialAltCpbRemovalDelayOffset, 0, sizeof(m_initialAltCpbRemovalDelayOffset)); +#endif } virtual ~SEIBufferingPeriod() {} +#if !JVET_N0353_INDEP_BUFF_TIME_SEI uint32_t m_bpSeqParameterSetId; bool m_rapCpbParamsPresentFlag; +#else + bool m_bpNalCpbParamsPresentFlag; + bool m_bpVclCpbParamsPresentFlag; + uint32_t m_initialCpbRemovalDelayLength; + uint32_t m_cpbRemovalDelayLength; + uint32_t m_dpbOutputDelayLength; + int m_bpCpbCnt; +#endif uint32_t m_cpbDelayOffset; uint32_t m_dpbDelayOffset; +#if !JVET_N0353_INDEP_BUFF_TIME_SEI uint32_t m_initialCpbRemovalDelay [MAX_CPB_CNT][2]; uint32_t m_initialCpbRemovalDelayOffset [MAX_CPB_CNT][2]; uint32_t m_initialAltCpbRemovalDelay [MAX_CPB_CNT][2]; uint32_t m_initialAltCpbRemovalDelayOffset[MAX_CPB_CNT][2]; +#else + std::vector<uint32_t> m_initialCpbRemovalDelay [2]; + std::vector<uint32_t> m_initialCpbRemovalOffset [2]; +#endif bool m_concatenationFlag; uint32_t m_auCpbRemovalDelayDelta; }; + class SEIPictureTiming : public SEI { public: PayloadType payloadType() const { return PICTURE_TIMING; } - void copyTo (SEIPictureTiming& target); + void copyTo (SEIPictureTiming& target) const; SEIPictureTiming() : m_picStruct (0) diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h index 30184a08fa438d7873fdaad6fea5f749f070a421..87b4b83cf11b700dbc0c382a4a16a73f58cf10ca 100644 --- a/source/Lib/CommonLib/TypeDef.h +++ b/source/Lib/CommonLib/TypeDef.h @@ -254,6 +254,8 @@ #define JVET_O0376_SPS_JOINTCBCR_FLAG 1 // JVET-O0376: add the JointCbCr control flag in SPS #define JVET_O0472_LFNST_SIGNALLING_LAST_SCAN_POS 1 // JVET-O0472: LFNST index signalling depends on the position of last significant coefficient +#define JVET_N0353_INDEP_BUFF_TIME_SEI 1 // JVET-N0353 independent parsing of buffering and timing info SEIs + #define FIX_DB_MAX_TRANSFORM_SIZE 1 #define MRG_SHARELIST_SHARSIZE 32 diff --git a/source/Lib/DecoderLib/DecLib.cpp b/source/Lib/DecoderLib/DecLib.cpp index d7a9718624ed783c11aa869f8386a38e7a68b094..db535c72ce98df953f9c0fb3dbecad5c95d17821 100644 --- a/source/Lib/DecoderLib/DecLib.cpp +++ b/source/Lib/DecoderLib/DecLib.cpp @@ -1092,7 +1092,7 @@ void DecLib::xParsePrefixSEImessages() while (!m_prefixSEINALUs.empty()) { InputNALUnit &nalu=*m_prefixSEINALUs.front(); - m_seiReader.parseSEImessage( &(nalu.getBitstream()), m_SEIs, nalu.m_nalUnitType, m_parameterSetManager.getActiveSPS(), m_pDecodedSEIOutputStream ); + m_seiReader.parseSEImessage( &(nalu.getBitstream()), m_SEIs, nalu.m_nalUnitType, m_parameterSetManager.getActiveSPS(), m_HRD, m_pDecodedSEIOutputStream ); delete m_prefixSEINALUs.front(); m_prefixSEINALUs.pop_front(); } @@ -1644,7 +1644,7 @@ bool DecLib::decode(InputNALUnit& nalu, int& iSkipFrame, int& iPOCLastDisplay) case NAL_UNIT_SUFFIX_SEI: if (m_pcPic) { - m_seiReader.parseSEImessage( &(nalu.getBitstream()), m_pcPic->SEIs, nalu.m_nalUnitType, m_parameterSetManager.getActiveSPS(), m_pDecodedSEIOutputStream ); + m_seiReader.parseSEImessage( &(nalu.getBitstream()), m_pcPic->SEIs, nalu.m_nalUnitType, m_parameterSetManager.getActiveSPS(), m_HRD, m_pDecodedSEIOutputStream ); } else { diff --git a/source/Lib/DecoderLib/DecLib.h b/source/Lib/DecoderLib/DecLib.h index bb1d06ddb1a1f25d7bf3ca0c11864918c5018bb0..737ae6db70f7d495c2a48c4d4b97eacf46c43b83 100644 --- a/source/Lib/DecoderLib/DecLib.h +++ b/source/Lib/DecoderLib/DecLib.h @@ -97,6 +97,9 @@ private: SampleAdaptiveOffset m_cSAO; AdaptiveLoopFilter m_cALF; Reshape m_cReshaper; ///< reshaper class +#if JVET_N0353_INDEP_BUFF_TIME_SEI + HRD m_HRD; +#endif // decoder side RD cost computation RdCost m_cRdCost; ///< RD cost computation class #if JVET_J0090_MEMORY_BANDWITH_MEASURE diff --git a/source/Lib/DecoderLib/SEIread.cpp b/source/Lib/DecoderLib/SEIread.cpp index aff18df69afedc3d58bf749329a613bd34482a0b..0228891e84cd9f6ebeaa34b651499255fd2c848f 100644 --- a/source/Lib/DecoderLib/SEIread.cpp +++ b/source/Lib/DecoderLib/SEIread.cpp @@ -104,14 +104,23 @@ static inline void output_sei_message_header(SEI &sei, std::ostream *pDecodedMes /** * unmarshal a single SEI message from bitstream bs */ +#if !JVET_N0353_INDEP_BUFF_TIME_SEI void SEIReader::parseSEImessage(InputBitstream* bs, SEIMessages& seis, const NalUnitType nalUnitType, const SPS *sps, std::ostream *pDecodedMessageOutputStream) +#else + // note: for independent parsing no parameter set should not be required here +void SEIReader::parseSEImessage(InputBitstream* bs, SEIMessages& seis, const NalUnitType nalUnitType, const SPS *sps, HRD &hrd, std::ostream *pDecodedMessageOutputStream) +#endif { setBitstream(bs); CHECK(m_pcBitstream->getNumBitsUntilByteAligned(), "Bitstream not aligned"); do { +#if JVET_N0353_INDEP_BUFF_TIME_SEI + xReadSEImessage(seis, nalUnitType, sps, hrd, pDecodedMessageOutputStream); +#else xReadSEImessage(seis, nalUnitType, sps, pDecodedMessageOutputStream); +#endif /* SEI messages are an integer number of bytes, something has failed * in the parsing if bitstream not byte-aligned */ @@ -122,7 +131,11 @@ void SEIReader::parseSEImessage(InputBitstream* bs, SEIMessages& seis, const Nal xReadRbspTrailingBits(); } +#if !JVET_N0353_INDEP_BUFF_TIME_SEI void SEIReader::xReadSEImessage(SEIMessages& seis, const NalUnitType nalUnitType, const SPS *sps, std::ostream *pDecodedMessageOutputStream) +#else +void SEIReader::xReadSEImessage(SEIMessages& seis, const NalUnitType nalUnitType, const SPS *sps, HRD &hrd, std::ostream *pDecodedMessageOutputStream) +#endif { #if ENABLE_TRACING xTraceSEIHeader(); @@ -184,6 +197,7 @@ void SEIReader::xReadSEImessage(SEIMessages& seis, const NalUnitType nalUnitType } break; case SEI::BUFFERING_PERIOD: +#if !JVET_N0353_INDEP_BUFF_TIME_SEI if (!sps) { msg( WARNING, "Warning: Found Buffering period SEI message, but no active SPS is available. Ignoring."); @@ -193,8 +207,14 @@ void SEIReader::xReadSEImessage(SEIMessages& seis, const NalUnitType nalUnitType sei = new SEIBufferingPeriod; xParseSEIBufferingPeriod((SEIBufferingPeriod&) *sei, payloadSize, sps, pDecodedMessageOutputStream); } +#else + sei = new SEIBufferingPeriod; + xParseSEIBufferingPeriod((SEIBufferingPeriod&) *sei, payloadSize, pDecodedMessageOutputStream); + hrd.setBufferingPeriodSEI((SEIBufferingPeriod*) sei); +#endif break; case SEI::PICTURE_TIMING: +#if !JVET_N0353_INDEP_BUFF_TIME_SEI if (!sps) { msg( WARNING, "Warning: Found Picture timing SEI message, but no active SPS is available. Ignoring."); @@ -204,6 +224,20 @@ void SEIReader::xReadSEImessage(SEIMessages& seis, const NalUnitType nalUnitType sei = new SEIPictureTiming; xParseSEIPictureTiming((SEIPictureTiming&)*sei, payloadSize, sps, pDecodedMessageOutputStream); } +#else + { + const SEIBufferingPeriod *bp= hrd.getBufferingPeriodSEI(); + if (!bp) + { + msg( WARNING, "Warning: Found Picture timing SEI message, but no active buffering period is available. Ignoring."); + } + else + { + sei = new SEIPictureTiming; + xParseSEIPictureTiming((SEIPictureTiming&)*sei, payloadSize, *bp, pDecodedMessageOutputStream); + } + } +#endif break; #if HEVC_SEI case SEI::RECOVERY_POINT: @@ -483,7 +517,11 @@ void SEIReader::xParseSEIDecodingUnitInfo(SEIDecodingUnitInfo& sei, uint32_t pay sei_read_uvlc( pDecodedMessageOutputStream, val, "decoding_unit_idx"); sei.m_decodingUnitIdx = val; +#if !JVET_N0353_INDEP_BUFF_TIME_SEI if(sps->getHrdParameters()->getSubPicCpbParamsInPicTimingSEIFlag()) +#else + if(sps->getHrdParameters()->getDecodingUnitHrdParamsPresentFlag()) +#endif { sei_read_code( pDecodedMessageOutputStream, ( sps->getHrdParameters()->getDuCpbRemovalDelayLengthMinus1() + 1 ), val, "du_spt_cpb_removal_delay_increment"); sei.m_duSptCpbRemovalDelay = val; @@ -500,15 +538,22 @@ void SEIReader::xParseSEIDecodingUnitInfo(SEIDecodingUnitInfo& sei, uint32_t pay } } +#if JVET_N0353_INDEP_BUFF_TIME_SEI +void SEIReader::xParseSEIBufferingPeriod(SEIBufferingPeriod& sei, uint32_t payloadSize, std::ostream *pDecodedMessageOutputStream) +#else void SEIReader::xParseSEIBufferingPeriod(SEIBufferingPeriod& sei, uint32_t payloadSize, const SPS *sps, std::ostream *pDecodedMessageOutputStream) +#endif { int i, nalOrVcl; uint32_t code; +#if !JVET_N0353_INDEP_BUFF_TIME_SEI const HRDParameters *pHRD = sps->getHrdParameters(); +#endif output_sei_message_header(sei, pDecodedMessageOutputStream, payloadSize); +#if !JVET_N0353_INDEP_BUFF_TIME_SEI sei_read_uvlc( pDecodedMessageOutputStream, code, "bp_seq_parameter_set_id" ); sei.m_bpSeqParameterSetId = code; if( !pHRD->getSubPicCpbParamsPresentFlag() ) { @@ -547,14 +592,57 @@ void SEIReader::xParseSEIBufferingPeriod(SEIBufferingPeriod& sei, uint32_t paylo } } } +#else + sei_read_flag( pDecodedMessageOutputStream, code, "bp_nal_hrd_parameters_present_flag" ); sei.m_bpNalCpbParamsPresentFlag = code; + sei_read_flag( pDecodedMessageOutputStream, code, "bp_vcl_hrd_parameters_present_flag" ); sei.m_bpVclCpbParamsPresentFlag = code; + + if (sei.m_bpNalCpbParamsPresentFlag || sei.m_bpVclCpbParamsPresentFlag) + { + sei_read_code( pDecodedMessageOutputStream, 5, code, "initial_cpb_removal_delay_length_minus1" ); sei.m_initialCpbRemovalDelayLength = code + 1; + sei_read_code( pDecodedMessageOutputStream, 5, code, "cpb_removal_delay_length_minus1" ); sei.m_cpbRemovalDelayLength = code + 1; + sei_read_code( pDecodedMessageOutputStream, 5, code, "dpb_output_delay_length_minus1" ); sei.m_dpbOutputDelayLength = code + 1; + } + + sei_read_flag( pDecodedMessageOutputStream, code, "concatenation_flag"); + sei.m_concatenationFlag = code; + sei_read_code( pDecodedMessageOutputStream, ( sei.m_cpbRemovalDelayLength ), code, "au_cpb_removal_delay_delta_minus1" ); + sei.m_auCpbRemovalDelayDelta = code + 1; + + sei_read_uvlc( pDecodedMessageOutputStream, code, "bp_cpb_cnt_minus1" ); sei.m_bpCpbCnt = code + 1; + + for( nalOrVcl = 0; nalOrVcl < 2; nalOrVcl ++ ) + { + if( ( ( nalOrVcl == 0 ) && ( sei.m_bpNalCpbParamsPresentFlag ) ) || + ( ( nalOrVcl == 1 ) && ( sei.m_bpVclCpbParamsPresentFlag ) ) ) + { + sei.m_initialCpbRemovalDelay[nalOrVcl].resize(sei.m_bpCpbCnt); + sei.m_initialCpbRemovalDelay[nalOrVcl].resize(sei.m_bpCpbCnt); + for( i = 0; i < ( sei.m_bpCpbCnt ); i ++ ) + { + sei_read_code( pDecodedMessageOutputStream, sei.m_initialCpbRemovalDelayLength, code, nalOrVcl ? "vcl_initial_cpb_removal_delay" : "nal_initial_cpb_removal_delay" ); + sei.m_initialCpbRemovalDelay[nalOrVcl][i] = code; + sei_read_code( pDecodedMessageOutputStream, sei.m_initialCpbRemovalDelayLength, code, nalOrVcl ? "vcl_initial_cpb_removal_offset" : "nal_initial_cpb_removal_offset" ); + sei.m_initialCpbRemovalDelay[nalOrVcl][i] = code; + } + } + } +#endif } +#if !JVET_N0353_INDEP_BUFF_TIME_SEI void SEIReader::xParseSEIPictureTiming(SEIPictureTiming& sei, uint32_t payloadSize, const SPS *sps, std::ostream *pDecodedMessageOutputStream) +#else +void SEIReader::xParseSEIPictureTiming(SEIPictureTiming& sei, uint32_t payloadSize, const SEIBufferingPeriod& bp, std::ostream *pDecodedMessageOutputStream) +#endif { +#if !JVET_N0353_INDEP_BUFF_TIME_SEI int i; +#endif uint32_t code; +#if !JVET_N0353_INDEP_BUFF_TIME_SEI const HRDParameters *hrd = sps->getHrdParameters(); +#endif output_sei_message_header(sei, pDecodedMessageOutputStream, payloadSize); { @@ -563,6 +651,7 @@ void SEIReader::xParseSEIPictureTiming(SEIPictureTiming& sei, uint32_t payloadSi sei_read_flag( pDecodedMessageOutputStream, code, "duplicate_flag" ); sei.m_duplicateFlag = (code == 1); } +#if !JVET_N0353_INDEP_BUFF_TIME_SEI if( hrd->getCpbDpbDelaysPresentFlag()) { sei_read_code( pDecodedMessageOutputStream, ( hrd->getCpbRemovalDelayLengthMinus1() + 1 ), code, "au_cpb_removal_delay_minus1" ); @@ -602,6 +691,13 @@ void SEIReader::xParseSEIPictureTiming(SEIPictureTiming& sei, uint32_t payloadSi } } } +#else + uint32_t symbol; + sei_read_code( pDecodedMessageOutputStream, bp.m_cpbRemovalDelayLength, symbol, "cpb_removal_delay_minus1" ); + sei.m_auCpbRemovalDelay = symbol + 1; + sei_read_code( pDecodedMessageOutputStream, bp.m_dpbOutputDelayLength, symbol, "dpb_output_delay" ); + sei.m_picDpbOutputDelay = symbol; +#endif } #if HEVC_SEI @@ -850,7 +946,8 @@ void SEIReader::xParseSEIScalableNesting(SEIScalableNesting& sei, const NalUnitT // read nested SEI messages do { - xReadSEImessage(sei.m_nestedSEIs, nalUnitType, sps, pDecodedMessageOutputStream); + HRD hrd; + xReadSEImessage(sei.m_nestedSEIs, nalUnitType, sps, hrd, pDecodedMessageOutputStream); } while (m_pcBitstream->getNumBitsLeft() > 8); if (pDecodedMessageOutputStream) diff --git a/source/Lib/DecoderLib/SEIread.h b/source/Lib/DecoderLib/SEIread.h index 49c6c124682c460bbc0b7b8aa46336dbd2b06c21..beb0783fe4acf70057a49eabb08e30fe320b9569 100644 --- a/source/Lib/DecoderLib/SEIread.h +++ b/source/Lib/DecoderLib/SEIread.h @@ -55,18 +55,31 @@ class SEIReader: public VLCReader public: SEIReader() {}; virtual ~SEIReader() {}; +#if !JVET_N0353_INDEP_BUFF_TIME_SEI void parseSEImessage(InputBitstream* bs, SEIMessages& seis, const NalUnitType nalUnitType, const SPS *sps, std::ostream *pDecodedMessageOutputStream); +#else + void parseSEImessage(InputBitstream* bs, SEIMessages& seis, const NalUnitType nalUnitType, const SPS *sps, HRD &hrd, std::ostream *pDecodedMessageOutputStream); +#endif protected: +#if !JVET_N0353_INDEP_BUFF_TIME_SEI void xReadSEImessage (SEIMessages& seis, const NalUnitType nalUnitType, const SPS *sps, std::ostream *pDecodedMessageOutputStream); +#else + void xReadSEImessage (SEIMessages& seis, const NalUnitType nalUnitType, const SPS *sps, HRD &hrd, std::ostream *pDecodedMessageOutputStream); +#endif #if HEVC_SEI void xParseSEIuserDataUnregistered (SEIuserDataUnregistered &sei, uint32_t payloadSize, std::ostream *pDecodedMessageOutputStream); void xParseSEIActiveParameterSets (SEIActiveParameterSets &sei, uint32_t payloadSize, std::ostream *pDecodedMessageOutputStream); #endif void xParseSEIDecodingUnitInfo (SEIDecodingUnitInfo& sei, uint32_t payloadSize, const SPS *sps, std::ostream *pDecodedMessageOutputStream); void xParseSEIDecodedPictureHash (SEIDecodedPictureHash& sei, uint32_t payloadSize, std::ostream *pDecodedMessageOutputStream); +#if JVET_N0353_INDEP_BUFF_TIME_SEI + void xParseSEIBufferingPeriod (SEIBufferingPeriod& sei, uint32_t payloadSize, std::ostream *pDecodedMessageOutputStream); + void xParseSEIPictureTiming (SEIPictureTiming& sei, uint32_t payloadSize, const SEIBufferingPeriod& bp, std::ostream *pDecodedMessageOutputStream); +#else void xParseSEIBufferingPeriod (SEIBufferingPeriod& sei, uint32_t payloadSize, const SPS *sps, std::ostream *pDecodedMessageOutputStream); void xParseSEIPictureTiming (SEIPictureTiming& sei, uint32_t payloadSize, const SPS *sps, std::ostream *pDecodedMessageOutputStream); +#endif #if HEVC_SEI void xParseSEIRecoveryPoint (SEIRecoveryPoint& sei, uint32_t payloadSize, std::ostream *pDecodedMessageOutputStream); void xParseSEIFramePacking (SEIFramePacking& sei, uint32_t payloadSize, std::ostream *pDecodedMessageOutputStream); diff --git a/source/Lib/DecoderLib/VLCReader.cpp b/source/Lib/DecoderLib/VLCReader.cpp index ee8adc7b12686de75c86a4249d670a19a775297c..92df3c89c883ffd4520744679a7e2666e7f5b489 100644 --- a/source/Lib/DecoderLib/VLCReader.cpp +++ b/source/Lib/DecoderLib/VLCReader.cpp @@ -1075,8 +1075,13 @@ void HLSyntaxReader::parseVUI(VUI* pcVUI, SPS *pcSPS) } +#if !JVET_N0353_INDEP_BUFF_TIME_SEI void HLSyntaxReader::parseHrdParameters(HRDParameters *hrd, bool commonInfPresentFlag, uint32_t maxNumSubLayersMinus1) +#else +void HLSyntaxReader::parseHrdParameters(HRDParameters *hrd, uint32_t firstSubLayer, uint32_t maxNumSubLayersMinus1) +#endif { +#if !JVET_N0353_INDEP_BUFF_TIME_SEI uint32_t uiCode; if( commonInfPresentFlag ) { @@ -1151,6 +1156,65 @@ void HLSyntaxReader::parseHrdParameters(HRDParameters *hrd, bool commonInfPresen } } } +#else + uint32_t symbol; + READ_FLAG( symbol, "general_nal_hrd_parameters_present_flag" ); hrd->setNalHrdParametersPresentFlag( symbol == 1 ? true : false ); + READ_FLAG( symbol, "general_vcl_hrd_parameters_present_flag" ); hrd->setVclHrdParametersPresentFlag( symbol == 1 ? true : false ); + if( hrd->getNalHrdParametersPresentFlag() || hrd->getVclHrdParametersPresentFlag() ) + { + READ_FLAG( symbol, "decoding_unit_hrd_params_present_flag" ); hrd->setSubPicCpbParamsPresentFlag( symbol == 1 ? true : false ); + + READ_CODE( 4, symbol, "bit_rate_scale" ); hrd->setBitRateScale( symbol ); + READ_CODE( 4, symbol, "cpb_size_scale" ); hrd->setCpbSizeScale( symbol ); + if( hrd->getSubPicCpbParamsPresentFlag() ) + { + READ_CODE( 4, symbol, "cpb_size_du_scale" ); hrd->setDuCpbSizeScale( symbol ); + } + } + + for( int i = firstSubLayer; i <= maxNumSubLayersMinus1; i ++ ) + { + READ_FLAG( symbol, "fixed_pic_rate_general_flag" ); hrd->setFixedPicRateFlag( i, symbol == 1 ? true : false ); + if( !hrd->getFixedPicRateFlag( i ) ) + { + READ_FLAG( symbol, "fixed_pic_rate_within_cvs_flag" ); hrd->setFixedPicRateWithinCvsFlag( i, symbol == 1 ? true : false ); + } + else + { + hrd->setFixedPicRateWithinCvsFlag( i, true ); + } + + hrd->setLowDelayHrdFlag( i, false ); // Inferred to be 0 when not present + hrd->setCpbCntMinus1 ( i, 0 ); // Inferred to be 0 when not present + + if( hrd->getFixedPicRateWithinCvsFlag( i ) ) + { + READ_UVLC( symbol, "elemental_duration_in_tc_minus1" ); hrd->setPicDurationInTcMinus1( i, symbol ); + } + else + { + READ_FLAG( symbol, "low_delay_hrd_flag" ); hrd->setLowDelayHrdFlag( i, symbol == 1 ? true : false ); + } + if (!hrd->getLowDelayHrdFlag( i )) + { + READ_UVLC( symbol, "cpb_cnt_minus1" ); hrd->setCpbCntMinus1( i, symbol ); + } + + for( int nalOrVcl = 0; nalOrVcl < 2; nalOrVcl ++ ) + { + if( ( ( nalOrVcl == 0 ) && ( hrd->getNalHrdParametersPresentFlag() ) ) || + ( ( nalOrVcl == 1 ) && ( hrd->getVclHrdParametersPresentFlag() ) ) ) + { + for( int j = 0; j <= ( hrd->getCpbCntMinus1( i ) ); j ++ ) + { + READ_UVLC( symbol, "bit_rate_value_minus1" ); hrd->setBitRateValueMinus1( i, j, nalOrVcl, symbol ); + READ_UVLC( symbol, "cpb_size_value_minus1" ); hrd->setCpbSizeValueMinus1( i, j, nalOrVcl, symbol ); + READ_FLAG( symbol, "cbr_flag" ); hrd->setCbrFlag( i, j, nalOrVcl, symbol == 1 ? true : false ); + } + } + } + } +#endif } diff --git a/source/Lib/DecoderLib/VLCReader.h b/source/Lib/DecoderLib/VLCReader.h index 9bf0f8a1cdb1e9ea44b959f286df110c76a5cc0e..b0f2e63f0cebe031b59e15b6dbcce63cbc2f6ac3 100644 --- a/source/Lib/DecoderLib/VLCReader.h +++ b/source/Lib/DecoderLib/VLCReader.h @@ -159,7 +159,11 @@ public: void parseVUI ( VUI* pcVUI, SPS* pcSPS ); void parseConstraintInfo (ConstraintInfo *cinfo); void parseProfileTierLevel ( ProfileTierLevel *ptl, int maxNumSubLayersMinus1); +#if !JVET_N0353_INDEP_BUFF_TIME_SEI void parseHrdParameters ( HRDParameters *hrd, bool cprms_present_flag, uint32_t tempLevelHigh ); +#else + void parseHrdParameters ( HRDParameters *hrd, uint32_t firstSubLayer, uint32_t tempLevelHigh ); +#endif void parseSliceHeader ( Slice* pcSlice, ParameterSetManager *parameterSetManager, const int prevTid0POC ); void parseTerminatingBit ( uint32_t& ruiBit ); void parseRemainingBytes ( bool noTrailingBytesExpected ); diff --git a/source/Lib/EncoderLib/EncGOP.cpp b/source/Lib/EncoderLib/EncGOP.cpp index 2f6fda9d1195ca3a76ee26b26e4501b969ce593f..1f101f4995f275fc1883fca1397c1a678f718fbf 100644 --- a/source/Lib/EncoderLib/EncGOP.cpp +++ b/source/Lib/EncoderLib/EncGOP.cpp @@ -212,6 +212,9 @@ void EncGOP::init ( EncLib* pcEncLib ) m_pcRateCtrl = pcEncLib->getRateCtrl(); m_lastBPSEI = 0; m_totalCoded = 0; +#if JVET_N0353_INDEP_BUFF_TIME_SEI + m_HRD = pcEncLib->getHRD(); +#endif m_AUWriterIf = pcEncLib->getAUWriterIf(); @@ -415,7 +418,11 @@ void EncGOP::xWriteSEI (NalUnitType naluType, SEIMessages& seiMessages, AccessUn return; } OutputNALUnit nalu(naluType, temporalId); +#if JVET_N0353_INDEP_BUFF_TIME_SEI + m_seiWriter.writeSEImessages(nalu.m_Bitstream, seiMessages, sps, *m_HRD, false); +#else m_seiWriter.writeSEImessages(nalu.m_Bitstream, seiMessages, sps, false); +#endif auPos = accessUnit.insert(auPos, new NALUnitEBSP(nalu)); auPos++; } @@ -432,7 +439,11 @@ void EncGOP::xWriteSEISeparately (NalUnitType naluType, SEIMessages& seiMessages SEIMessages tmpMessages; tmpMessages.push_back(*sei); OutputNALUnit nalu(naluType, temporalId); +#if JVET_N0353_INDEP_BUFF_TIME_SEI + m_seiWriter.writeSEImessages(nalu.m_Bitstream, tmpMessages, sps, *m_HRD, false); +#else m_seiWriter.writeSEImessages(nalu.m_Bitstream, tmpMessages, sps, false); +#endif auPos = accessUnit.insert(auPos, new NALUnitEBSP(nalu)); auPos++; } @@ -688,7 +699,10 @@ void EncGOP::xCreatePerPictureSEIMessages (int picInGOP, SEIMessages& seiMessage || ( slice->getSPS()->getHrdParameters()->getVclHrdParametersPresentFlag() ) ) ) { SEIBufferingPeriod *bufferingPeriodSEI = new SEIBufferingPeriod(); - m_seiEncoder.initSEIBufferingPeriod(bufferingPeriodSEI, slice); + m_seiEncoder.initSEIBufferingPeriod(bufferingPeriodSEI); +#if JVET_N0353_INDEP_BUFF_TIME_SEI + m_HRD->setBufferingPeriodSEI(bufferingPeriodSEI); +#endif seiMessages.push_back(bufferingPeriodSEI); m_bufferingPeriodSEIPresentInAU = true; @@ -794,7 +808,12 @@ void EncGOP::xCreatePictureTimingSEI (int IRAPGOPid, SEIMessages& seiMessages, pictureTimingSEI->m_numNalusInDuMinus1.resize( numDU ); pictureTimingSEI->m_duCpbRemovalDelayMinus1.resize( numDU ); } +#if JVET_N0353_INDEP_BUFF_TIME_SEI + const uint32_t cpbRemovalDelayLegth = m_HRD->getBufferingPeriodSEI()->m_cpbRemovalDelayLength; + pictureTimingSEI->m_auCpbRemovalDelay = std::min<int>(std::max<int>(1, m_totalCoded - m_lastBPSEI), static_cast<int>(pow(2, static_cast<double>(cpbRemovalDelayLegth)))); // Syntax element signalled as minus, hence the . +#else pictureTimingSEI->m_auCpbRemovalDelay = std::min<int>(std::max<int>(1, m_totalCoded - m_lastBPSEI), static_cast<int>(pow(2, static_cast<double>(hrd->getCpbRemovalDelayLengthMinus1()+1)))); // Syntax element signalled as minus, hence the . +#endif pictureTimingSEI->m_picDpbOutputDelay = slice->getSPS()->getNumReorderPics(slice->getSPS()->getMaxTLayers()-1) + slice->getPOC() - m_totalCoded; if(m_pcCfg->getEfficientFieldIRAPEnabled() && IRAPGOPid > 0 && IRAPGOPid < m_iGopSize) { diff --git a/source/Lib/EncoderLib/EncGOP.h b/source/Lib/EncoderLib/EncGOP.h index 68ee2eeaaa0bac78ac75e6b1fc52cf1f83c2905f..84e1411f964bb75d7219df1892a428178487bfce 100644 --- a/source/Lib/EncoderLib/EncGOP.h +++ b/source/Lib/EncoderLib/EncGOP.h @@ -60,6 +60,9 @@ #include "Analyze.h" #include "RateCtrl.h" #include <vector> +#if JVET_N0353_INDEP_BUFF_TIME_SEI +#include "EncHRD.h" +#endif #if JVET_O0756_CALCULATE_HDRMETRICS #include "HDRLib/inc/ConvertColorFormat.H" @@ -154,6 +157,10 @@ private: // indicate sequence first bool m_bSeqFirst; +#if JVET_N0353_INDEP_BUFF_TIME_SEI + EncHRD* m_HRD; +#endif + // clean decoding refresh bool m_bRefreshPending; int m_pocCRA; diff --git a/source/Lib/EncoderLib/EncHRD.cpp b/source/Lib/EncoderLib/EncHRD.cpp index 60c135a88a9f17076823c18a7b35a06d713df675..2e4c58ceaed385020e2bdabfbd69e88474ad7cb8 100644 --- a/source/Lib/EncoderLib/EncHRD.cpp +++ b/source/Lib/EncoderLib/EncHRD.cpp @@ -59,7 +59,9 @@ void EncHRD::initHRDParameters (EncCfg* encCfg) { bool useSubCpbParams = (encCfg->getSliceMode() > 0) || (encCfg->getSliceSegmentMode() > 0); int bitRate = encCfg->getTargetBitrate(); +#if !JVET_N0353_INDEP_BUFF_TIME_SEI bool isRandomAccess = encCfg->getIntraPeriod() > 0; +#endif # if U0132_TARGET_BITS_SATURATION int cpbSize = encCfg->getCpbSize(); CHECK(!(cpbSize!=0), "Unspecified error"); // CPB size may not be equal to zero. ToDo: have a better default and check for level constraints @@ -116,12 +118,20 @@ void EncHRD::initHRDParameters (EncCfg* encCfg) { m_hrdParams.setTickDivisorMinus2( 100 - 2 ); // m_hrdParams.setDuCpbRemovalDelayLengthMinus1( 7 ); // 8-bit precision ( plus 1 for last DU in AU ) +#if !JVET_N0353_INDEP_BUFF_TIME_SEI m_hrdParams.setSubPicCpbParamsInPicTimingSEIFlag( true ); +#else + m_hrdParams.setDecodingUnitHrdParamsPresentFlag( true ); +#endif m_hrdParams.setDpbOutputDelayDuLengthMinus1( 5 + 7 ); // With sub-clock tick factor of 100, at least 7 bits to have the same value as AU dpb delay } else { +#if !JVET_N0353_INDEP_BUFF_TIME_SEI m_hrdParams.setSubPicCpbParamsInPicTimingSEIFlag( false ); +#else + m_hrdParams.setDecodingUnitHrdParamsPresentFlag( false ); +#endif } #if U0132_TARGET_BITS_SATURATION @@ -149,6 +159,7 @@ void EncHRD::initHRDParameters (EncCfg* encCfg) m_hrdParams.setDuCpbSizeScale( 6 ); // in units of 2^( 4 + 6 ) = 1,024 bit +#if !JVET_N0353_INDEP_BUFF_TIME_SEI m_hrdParams.setInitialCpbRemovalDelayLengthMinus1(15); // assuming 0.5 sec, log2( 90,000 * 0.5 ) = 16-bit if( isRandomAccess ) { @@ -160,6 +171,7 @@ void EncHRD::initHRDParameters (EncCfg* encCfg) m_hrdParams.setCpbRemovalDelayLengthMinus1(9); // max. 2^10 m_hrdParams.setDpbOutputDelayLengthMinus1 (9); // max. 2^10 } +#endif // Note: parameters for all temporal layers are initialized with the same values int i, j; diff --git a/source/Lib/EncoderLib/EncLib.h b/source/Lib/EncoderLib/EncLib.h index 0aa443cd76c84300ad2cf52d03879a9f1b3990fe..4721510c11052b536b016d764cc3f4a27be442dd 100644 --- a/source/Lib/EncoderLib/EncLib.h +++ b/source/Lib/EncoderLib/EncLib.h @@ -217,6 +217,9 @@ public: EncAdaptiveLoopFilter* getALF () { return &m_cEncALF; } EncGOP* getGOPEncoder () { return &m_cGOPEncoder; } EncSlice* getSliceEncoder () { return &m_cSliceEncoder; } +#if JVET_N0353_INDEP_BUFF_TIME_SEI + EncHRD* getHRD () { return &m_encHRD; } +#endif #if ENABLE_SPLIT_PARALLELISM || ENABLE_WPP_PARALLELISM EncCu* getCuEncoder ( int jId = 0 ) { return &m_cCuEncoder[jId]; } #else diff --git a/source/Lib/EncoderLib/SEIEncoder.cpp b/source/Lib/EncoderLib/SEIEncoder.cpp index e02937192a3c32e7d03dfa3c20b487ef823ee9be..c8735dfe3bc4ec6e2c14093d5446c82ca526309c 100644 --- a/source/Lib/EncoderLib/SEIEncoder.cpp +++ b/source/Lib/EncoderLib/SEIEncoder.cpp @@ -200,13 +200,13 @@ void SEIEncoder::initSEISOPDescription(SEISOPDescription *sopDescriptionSEI, Sli } #endif -void SEIEncoder::initSEIBufferingPeriod(SEIBufferingPeriod *bufferingPeriodSEI, Slice *slice) +void SEIEncoder::initSEIBufferingPeriod(SEIBufferingPeriod *bufferingPeriodSEI) { - CHECK(!(m_isInitialized), "Unspecified error"); - CHECK(!(bufferingPeriodSEI != NULL), "Unspecified error"); - CHECK(!(slice != NULL), "Unspecified error"); + CHECK(!(m_isInitialized), "bufferingPeriodSEI already initialized"); + CHECK(!(bufferingPeriodSEI != nullptr), "Need a bufferingPeriodSEI for initialization (got nullptr)"); uint32_t uiInitialCpbRemovalDelay = (90000/2); // 0.5 sec +#if !JVET_N0353_INDEP_BUFF_TIME_SEI bufferingPeriodSEI->m_initialCpbRemovalDelay [0][0] = uiInitialCpbRemovalDelay; bufferingPeriodSEI->m_initialCpbRemovalDelayOffset[0][0] = uiInitialCpbRemovalDelay; bufferingPeriodSEI->m_initialCpbRemovalDelay [0][1] = uiInitialCpbRemovalDelay; @@ -218,6 +218,37 @@ void SEIEncoder::initSEIBufferingPeriod(SEIBufferingPeriod *bufferingPeriodSEI, bufferingPeriodSEI->m_initialAltCpbRemovalDelayOffset[0][1] = uiInitialCpbRemovalDelay; bufferingPeriodSEI->m_rapCpbParamsPresentFlag = 0; +#else + bufferingPeriodSEI->m_initialCpbRemovalDelay [0].resize(1); + bufferingPeriodSEI->m_initialCpbRemovalOffset [0].resize(1); + bufferingPeriodSEI->m_initialCpbRemovalDelay [1].resize(1); + bufferingPeriodSEI->m_initialCpbRemovalOffset [1].resize(1); + bufferingPeriodSEI->m_initialCpbRemovalDelay [0][0] = uiInitialCpbRemovalDelay; + bufferingPeriodSEI->m_initialCpbRemovalOffset[0][0] = uiInitialCpbRemovalDelay; + bufferingPeriodSEI->m_initialCpbRemovalDelay [1][0] = uiInitialCpbRemovalDelay; + bufferingPeriodSEI->m_initialCpbRemovalOffset[1][0] = uiInitialCpbRemovalDelay; + bufferingPeriodSEI->m_bpNalCpbParamsPresentFlag = true; + bufferingPeriodSEI->m_bpVclCpbParamsPresentFlag = true; + bufferingPeriodSEI->m_bpCpbCnt = 1; + + bufferingPeriodSEI->m_initialCpbRemovalDelayLength = 16; // assuming 0.5 sec, log2( 90,000 * 0.5 ) = 16-bit + // Note: The following parameters require some knowledge about the GOP structure. + // Using getIntraPeriod() should be avoided though, because it assumes certain GOP + // properties, which are only valid in CTC. + // Still copying this setting from HM for consistency, improvements welcome + bool isRandomAccess = m_pcCfg->getIntraPeriod() > 0; + if( isRandomAccess ) + { + bufferingPeriodSEI->m_cpbRemovalDelayLength = 6; // 32 = 2^5 (plus 1) + bufferingPeriodSEI->m_dpbOutputDelayLength = 6; // 32 + 3 = 2^6 + } + else + { + bufferingPeriodSEI->m_cpbRemovalDelayLength = 9; // max. 2^10 + bufferingPeriodSEI->m_dpbOutputDelayLength = 9; // max. 2^10 + } + +#endif //for the concatenation, it can be set to one during splicing. bufferingPeriodSEI->m_concatenationFlag = 0; //since the temporal layer HRDParameters is not ready, we assumed it is fixed diff --git a/source/Lib/EncoderLib/SEIEncoder.h b/source/Lib/EncoderLib/SEIEncoder.h index 0ea07ab0402d56d8603c414b8372716e5c861461..2f5c9c00147d04fc4f1372fbac58f4f2f9980590 100644 --- a/source/Lib/EncoderLib/SEIEncoder.h +++ b/source/Lib/EncoderLib/SEIEncoder.h @@ -76,7 +76,7 @@ public: void initSEIToneMappingInfo(SEIToneMappingInfo *sei); void initSEISOPDescription(SEISOPDescription *sei, Slice *slice, int picInGOP, int lastIdr, int currGOPSize); #endif - void initSEIBufferingPeriod(SEIBufferingPeriod *sei, Slice *slice); + void initSEIBufferingPeriod(SEIBufferingPeriod *sei); #if HEVC_SEI void initSEIScalableNesting(SEIScalableNesting *sei, SEIMessages &nestedSEIs); void initSEIRecoveryPoint(SEIRecoveryPoint *sei, Slice *slice); diff --git a/source/Lib/EncoderLib/SEIwrite.cpp b/source/Lib/EncoderLib/SEIwrite.cpp index 27f91f1c1def54aab43011072978d1b4e7aba3dd..5f70508f58f52160b57b0faa7a2fd4ee26dbc829 100644 --- a/source/Lib/EncoderLib/SEIwrite.cpp +++ b/source/Lib/EncoderLib/SEIwrite.cpp @@ -41,7 +41,11 @@ //! \ingroup EncoderLib //! \{ +#if !JVET_N0353_INDEP_BUFF_TIME_SEI void SEIWriter::xWriteSEIpayloadData(OutputBitstream& bs, const SEI& sei, const SPS *sps) +#else +void SEIWriter::xWriteSEIpayloadData(OutputBitstream& bs, const SEI& sei, const SPS *sps, HRD &hrd) +#endif { switch (sei.payloadType()) { @@ -60,10 +64,23 @@ void SEIWriter::xWriteSEIpayloadData(OutputBitstream& bs, const SEI& sei, const xWriteSEIDecodedPictureHash(*static_cast<const SEIDecodedPictureHash*>(&sei)); break; case SEI::BUFFERING_PERIOD: +#if !JVET_N0353_INDEP_BUFF_TIME_SEI xWriteSEIBufferingPeriod(*static_cast<const SEIBufferingPeriod*>(&sei), sps); +#else + xWriteSEIBufferingPeriod(*static_cast<const SEIBufferingPeriod*>(&sei)); + hrd.setBufferingPeriodSEI(static_cast<const SEIBufferingPeriod*>(&sei)); +#endif break; case SEI::PICTURE_TIMING: +#if !JVET_N0353_INDEP_BUFF_TIME_SEI xWriteSEIPictureTiming(*static_cast<const SEIPictureTiming*>(&sei), sps); +#else + { + const SEIBufferingPeriod *bp = hrd.getBufferingPeriodSEI(); + CHECK (bp == nullptr, "Buffering Period need to be initialized in HRD to allow writing of Picture Timing SEI"); + xWriteSEIPictureTiming(*static_cast<const SEIPictureTiming*>(&sei), *bp); + } +#endif break; #if HEVC_SEI case SEI::RECOVERY_POINT: @@ -133,7 +150,11 @@ void SEIWriter::xWriteSEIpayloadData(OutputBitstream& bs, const SEI& sei, const /** * marshal all SEI messages in provided list into one bitstream bs */ +#if JVET_N0353_INDEP_BUFF_TIME_SEI +void SEIWriter::writeSEImessages(OutputBitstream& bs, const SEIMessages &seiList, const SPS *sps, HRD &hrd, bool isNested) +#else void SEIWriter::writeSEImessages(OutputBitstream& bs, const SEIMessages &seiList, const SPS *sps, bool isNested) +#endif { #if ENABLE_TRACING if (g_HLSTraceEnable) @@ -153,7 +174,11 @@ void SEIWriter::writeSEImessages(OutputBitstream& bs, const SEIMessages &seiList bool traceEnable = g_HLSTraceEnable; g_HLSTraceEnable = false; #endif +#if JVET_N0353_INDEP_BUFF_TIME_SEI + xWriteSEIpayloadData(bs_count, **sei, sps, hrd); +#else xWriteSEIpayloadData(bs_count, **sei, sps); +#endif #if ENABLE_TRACING g_HLSTraceEnable = traceEnable; #endif @@ -181,7 +206,11 @@ void SEIWriter::writeSEImessages(OutputBitstream& bs, const SEIMessages &seiList xTraceSEIMessageType((*sei)->payloadType()); #endif +#if !JVET_N0353_INDEP_BUFF_TIME_SEI xWriteSEIpayloadData(bs, **sei, sps); +#else + xWriteSEIpayloadData(bs, **sei, sps, hrd); +#endif } if (!isNested) { @@ -252,7 +281,11 @@ void SEIWriter::xWriteSEIActiveParameterSets(const SEIActiveParameterSets& sei) void SEIWriter::xWriteSEIDecodingUnitInfo(const SEIDecodingUnitInfo& sei, const SPS *sps) { WRITE_UVLC(sei.m_decodingUnitIdx, "decoding_unit_idx"); +#if !JVET_N0353_INDEP_BUFF_TIME_SEI if(sps->getHrdParameters()->getSubPicCpbParamsInPicTimingSEIFlag()) +#else + if(sps->getHrdParameters()->getDecodingUnitHrdParamsPresentFlag()) +#endif { WRITE_CODE( sei.m_duSptCpbRemovalDelay, (sps->getHrdParameters()->getDuCpbRemovalDelayLengthMinus1() + 1), "du_spt_cpb_removal_delay_increment"); } @@ -263,9 +296,15 @@ void SEIWriter::xWriteSEIDecodingUnitInfo(const SEIDecodingUnitInfo& sei, const } } +#if !JVET_N0353_INDEP_BUFF_TIME_SEI void SEIWriter::xWriteSEIBufferingPeriod(const SEIBufferingPeriod& sei, const SPS *sps) +#else +void SEIWriter::xWriteSEIBufferingPeriod(const SEIBufferingPeriod& sei) +#endif { +#if !JVET_N0353_INDEP_BUFF_TIME_SEI int i, nalOrVcl; + const HRDParameters *hrd = sps->getHrdParameters(); WRITE_UVLC( sei.m_bpSeqParameterSetId, "bp_seq_parameter_set_id" ); @@ -297,11 +336,55 @@ void SEIWriter::xWriteSEIBufferingPeriod(const SEIBufferingPeriod& sei, const SP } } } +#else + WRITE_FLAG( sei.m_bpNalCpbParamsPresentFlag, "bp_nal_hrd_parameters_present_flag"); + WRITE_FLAG( sei.m_bpVclCpbParamsPresentFlag, "bp_vcl_hrd_parameters_present_flag"); + + if (sei.m_bpNalCpbParamsPresentFlag || sei.m_bpVclCpbParamsPresentFlag) + { + CHECK (sei.m_initialCpbRemovalDelayLength < 1, "sei.m_initialCpbRemovalDelayLength must be > 0"); + WRITE_CODE( sei.m_initialCpbRemovalDelayLength - 1, 5, "initial_cpb_removal_delay_length_minus1" ); + CHECK (sei.m_cpbRemovalDelayLength < 1, "sei.m_cpbRemovalDelayLength must be > 0"); + WRITE_CODE( sei.m_cpbRemovalDelayLength - 1, 5, "cpb_removal_delay_length_minus1" ); + CHECK (sei.m_dpbOutputDelayLength < 1, "sei.m_dpbOutputDelayLength must be > 0"); + WRITE_CODE( sei.m_dpbOutputDelayLength - 1, 5, "dpb_output_delay_length_minus1" ); + } + + WRITE_FLAG( sei.m_concatenationFlag, "concatenation_flag"); + + CHECK (sei.m_auCpbRemovalDelayDelta < 1, "sei.m_auCpbRemovalDelayDelta must be > 0"); + WRITE_CODE( sei.m_auCpbRemovalDelayDelta - 1, sei.m_cpbRemovalDelayLength, "au_cpb_removal_delay_delta_minus1" ); + + CHECK (sei.m_bpCpbCnt < 1, "sei.m_bpCpbCnt must be > 0"); + WRITE_UVLC( sei.m_bpCpbCnt - 1, "bp_cpb_cnt_minus1"); + + for( int nalOrVcl = 0; nalOrVcl < 2; nalOrVcl ++ ) + { + if( ( ( nalOrVcl == 0 ) && ( sei.m_bpNalCpbParamsPresentFlag ) ) || + ( ( nalOrVcl == 1 ) && ( sei.m_bpVclCpbParamsPresentFlag ) ) ) + { + CHECK (sei.m_initialCpbRemovalDelay[nalOrVcl].size() != sei.m_bpCpbCnt, "wrong number of values in m_initialCpbRemovalDelay"); + CHECK (sei.m_initialCpbRemovalOffset[nalOrVcl].size() != sei.m_bpCpbCnt, "wrong number of values in m_initialCpbRemovalOffset"); + for( int i = 0; i < sei.m_bpCpbCnt; i ++ ) + { + WRITE_CODE( sei.m_initialCpbRemovalDelay[nalOrVcl][i], sei.m_initialCpbRemovalDelayLength, nalOrVcl ? "vcl_initial_cpb_removal_delay" : "nal_initial_cpb_removal_delay" ); + WRITE_CODE( sei.m_initialCpbRemovalOffset[nalOrVcl][i], sei.m_initialCpbRemovalDelayLength, nalOrVcl ? "vcl_initial_cpb_removal_offset" : "nal_initial_cpb_removal_offset" ); + } + } + } + +#endif } +#if !JVET_N0353_INDEP_BUFF_TIME_SEI void SEIWriter::xWriteSEIPictureTiming(const SEIPictureTiming& sei, const SPS *sps) +#else +void SEIWriter::xWriteSEIPictureTiming(const SEIPictureTiming& sei, const SEIBufferingPeriod &bp) +#endif { +#if !JVET_N0353_INDEP_BUFF_TIME_SEI int i; const HRDParameters *hrd = sps->getHrdParameters(); +#endif { WRITE_CODE( sei.m_picStruct, 4, "pic_struct" ); @@ -309,6 +392,7 @@ void SEIWriter::xWriteSEIPictureTiming(const SEIPictureTiming& sei, const SPS *s WRITE_FLAG( sei.m_duplicateFlag ? 1 : 0, "duplicate_flag" ); } +#if !JVET_N0353_INDEP_BUFF_TIME_SEI if( hrd->getCpbDpbDelaysPresentFlag() ) { WRITE_CODE( sei.m_auCpbRemovalDelay - 1, ( hrd->getCpbRemovalDelayLengthMinus1() + 1 ), "au_cpb_removal_delay_minus1" ); @@ -335,6 +419,10 @@ void SEIWriter::xWriteSEIPictureTiming(const SEIPictureTiming& sei, const SPS *s } } } +#else + WRITE_CODE( sei.m_auCpbRemovalDelay - 1, bp.m_cpbRemovalDelayLength, "cpb_removal_delay_minus1" ); + WRITE_CODE( sei.m_picDpbOutputDelay, bp.m_dpbOutputDelayLength, "dpb_output_delay" ); +#endif } #if HEVC_SEI @@ -544,7 +632,12 @@ void SEIWriter::xWriteSEIScalableNesting(OutputBitstream& bs, const SEIScalableN } // write nested SEI messages +#if JVET_N0353_INDEP_BUFF_TIME_SEI + HRD hrd; + writeSEImessages(bs, sei.m_nestedSEIs, sps, hrd, true); +#else writeSEImessages(bs, sei.m_nestedSEIs, sps, true); +#endif } void SEIWriter::xWriteSEITempMotionConstrainedTileSets(const SEITempMotionConstrainedTileSets& sei) diff --git a/source/Lib/EncoderLib/SEIwrite.h b/source/Lib/EncoderLib/SEIwrite.h index d7517374c3cfb824eca6464dfd7e09078ed34c27..7c7fb5f7ee2f68368bfa2f2db713c350a6dd0f56 100644 --- a/source/Lib/EncoderLib/SEIwrite.h +++ b/source/Lib/EncoderLib/SEIwrite.h @@ -49,7 +49,11 @@ public: SEIWriter() {}; virtual ~SEIWriter() {}; +#if JVET_N0353_INDEP_BUFF_TIME_SEI + void writeSEImessages(OutputBitstream& bs, const SEIMessages &seiList, const SPS *sps, HRD &hrd, bool isNested); +#else void writeSEImessages(OutputBitstream& bs, const SEIMessages &seiList, const SPS *sps, bool isNested); +#endif protected: #if HEVC_SEI @@ -58,8 +62,13 @@ protected: #endif void xWriteSEIDecodingUnitInfo(const SEIDecodingUnitInfo& sei, const SPS *sps); void xWriteSEIDecodedPictureHash(const SEIDecodedPictureHash& sei); +#if !JVET_N0353_INDEP_BUFF_TIME_SEI void xWriteSEIBufferingPeriod(const SEIBufferingPeriod& sei, const SPS *sps); void xWriteSEIPictureTiming(const SEIPictureTiming& sei, const SPS *sps); +#else + void xWriteSEIBufferingPeriod(const SEIBufferingPeriod& sei); + void xWriteSEIPictureTiming(const SEIPictureTiming& sei, const SEIBufferingPeriod& bp); +#endif #if HEVC_SEI void xWriteSEIRecoveryPoint(const SEIRecoveryPoint& sei); void xWriteSEIFramePacking(const SEIFramePacking& sei); @@ -83,7 +92,11 @@ protected: void xWriteSEIGreenMetadataInfo(const SEIGreenMetadataInfo &sei); #endif +#if !JVET_N0353_INDEP_BUFF_TIME_SEI void xWriteSEIpayloadData(OutputBitstream& bs, const SEI& sei, const SPS *sps); +#else + void xWriteSEIpayloadData(OutputBitstream& bs, const SEI& sei, const SPS *sps, HRD &hrd); +#endif void xWriteByteAlign(); }; diff --git a/source/Lib/EncoderLib/VLCWriter.cpp b/source/Lib/EncoderLib/VLCWriter.cpp index ccefb18d04d134ad3a818c4c9feb9a47b231d6b9..1016374ade90bd791e8a1d2038a8ae47aead5fed 100644 --- a/source/Lib/EncoderLib/VLCWriter.cpp +++ b/source/Lib/EncoderLib/VLCWriter.cpp @@ -704,8 +704,13 @@ void HLSWriter::codeVUI( const VUI *pcVUI, const SPS* pcSPS ) } +#if !JVET_N0353_INDEP_BUFF_TIME_SEI void HLSWriter::codeHrdParameters( const HRDParameters *hrd, bool commonInfPresentFlag, uint32_t maxNumSubLayersMinus1 ) +#else +void HLSWriter::codeHrdParameters( const HRDParameters *hrd, const uint32_t firstSubLayer, const uint32_t maxNumSubLayersMinus1) +#endif { +#if !JVET_N0353_INDEP_BUFF_TIME_SEI if( commonInfPresentFlag ) { WRITE_FLAG( hrd->getNalHrdParametersPresentFlag() ? 1 : 0 , "nal_hrd_parameters_present_flag" ); @@ -773,6 +778,53 @@ void HLSWriter::codeHrdParameters( const HRDParameters *hrd, bool commonInfPrese } } } +#else + WRITE_FLAG( hrd->getNalHrdParametersPresentFlag() ? 1 : 0 , "general_nal_hrd_parameters_present_flag" ); + WRITE_FLAG( hrd->getVclHrdParametersPresentFlag() ? 1 : 0 , "general_vcl_hrd_parameters_present_flag" ); + if( hrd->getNalHrdParametersPresentFlag() || hrd->getVclHrdParametersPresentFlag() ) + { + WRITE_FLAG( hrd->getSubPicCpbParamsPresentFlag() ? 1 : 0, "decoding_unit_hrd_params_present_flag" ); + } + WRITE_CODE( hrd->getBitRateScale(), 4, "bit_rate_scale" ); + WRITE_CODE( hrd->getCpbSizeScale(), 4, "cpb_size_scale" ); + + for( int i = firstSubLayer; i <= maxNumSubLayersMinus1; i ++ ) + { + WRITE_FLAG( hrd->getFixedPicRateFlag( i ) ? 1 : 0, "fixed_pic_rate_general_flag"); + bool fixedPixRateWithinCvsFlag = true; + if( !hrd->getFixedPicRateFlag( i ) ) + { + fixedPixRateWithinCvsFlag = hrd->getFixedPicRateWithinCvsFlag( i ); + WRITE_FLAG( hrd->getFixedPicRateWithinCvsFlag( i ) ? 1 : 0, "fixed_pic_rate_within_cvs_flag"); + } + if( fixedPixRateWithinCvsFlag ) + { + WRITE_UVLC( hrd->getPicDurationInTcMinus1( i ), "elemental_duration_in_tc_minus1"); + } + else + { + WRITE_FLAG( hrd->getLowDelayHrdFlag( i ) ? 1 : 0, "low_delay_hrd_flag"); + } + if (!hrd->getLowDelayHrdFlag( i )) + { + WRITE_UVLC( hrd->getCpbCntMinus1( i ), "cpb_cnt_minus1"); + } + + for( int nalOrVcl = 0; nalOrVcl < 2; nalOrVcl ++ ) + { + if( ( ( nalOrVcl == 0 ) && ( hrd->getNalHrdParametersPresentFlag() ) ) || + ( ( nalOrVcl == 1 ) && ( hrd->getVclHrdParametersPresentFlag() ) ) ) + { + for( int j = 0; j <= ( hrd->getCpbCntMinus1( i ) ); j ++ ) + { + WRITE_UVLC( hrd->getBitRateValueMinus1( i, j, nalOrVcl ), "bit_rate_value_minus1"); + WRITE_UVLC( hrd->getCpbSizeValueMinus1( i, j, nalOrVcl ), "cpb_size_value_minus1"); + WRITE_FLAG( hrd->getCbrFlag( i, j, nalOrVcl ) ? 1 : 0, "cbr_flag"); + } + } + } + } +#endif } diff --git a/source/Lib/EncoderLib/VLCWriter.h b/source/Lib/EncoderLib/VLCWriter.h index e18ab25ff92d9efd14c8f31cb75e21629ac069c3..867dbcfc3c5c0470e14950fd6f4e6e8e56bfa953 100644 --- a/source/Lib/EncoderLib/VLCWriter.h +++ b/source/Lib/EncoderLib/VLCWriter.h @@ -140,7 +140,12 @@ public: void codeSliceHeader ( Slice* pcSlice ); void codeConstraintInfo ( const ConstraintInfo* cinfo ); void codeProfileTierLevel ( const ProfileTierLevel* ptl, int maxNumSubLayersMinus1 ); +#if !JVET_N0353_INDEP_BUFF_TIME_SEI void codeHrdParameters ( const HRDParameters *hrd, bool commonInfPresentFlag, uint32_t maxNumSubLayersMinus1 ); +#else + void codeHrdParameters ( const HRDParameters *hrd, const uint32_t firstSubLayer, const uint32_t maxNumSubLayersMinus1); +#endif + void codeTilesWPPEntryPoint ( Slice* pSlice ); void codeScalingList ( const ScalingList &scalingList );