diff --git a/doc/software-manual.tex b/doc/software-manual.tex index 9dc7e8645e50ff81735c8ed8e1ddb4cdb3a95bdb..2573b671a424763b48eb520eb9d2d44c5b1e3995 100755 --- a/doc/software-manual.tex +++ b/doc/software-manual.tex @@ -1082,6 +1082,13 @@ picture. \end{tabular} \\ +\Option{DRAPPeriod} & +%\ShortOption{\None} & +\Default{0} & +Specifies the DRAP period in frames. +Dependent RAP indication SEI messages are disabled if DRAPPeriod is 0. +\\ + \Option{GOPSize (-g)} & %\ShortOption{-g} & \Default{1} & diff --git a/source/App/EncoderApp/EncApp.cpp b/source/App/EncoderApp/EncApp.cpp index 69c07bd758ee1aafa0cd891a79c89106a3449e9f..774f0a02caf1536bf95055042943ddf60708b581 100644 --- a/source/App/EncoderApp/EncApp.cpp +++ b/source/App/EncoderApp/EncApp.cpp @@ -160,6 +160,9 @@ void EncApp::xInitLibCfg() m_cEncLib.setIntraPeriod ( m_iIntraPeriod ); m_cEncLib.setDecodingRefreshType ( m_iDecodingRefreshType ); m_cEncLib.setGOPSize ( m_iGOPSize ); +#if JVET_N0494_DRAP + m_cEncLib.setDrapPeriod ( m_drapPeriod ); +#endif m_cEncLib.setReWriteParamSets ( m_rewriteParamSets ); m_cEncLib.setRPLList0 ( m_RPLList0); m_cEncLib.setRPLList1 ( m_RPLList1); @@ -458,6 +461,9 @@ void EncApp::xInitLibCfg() m_cEncLib.setDecodedPictureHashSEIType ( m_decodedPictureHashSEIType ); #if HEVC_SEI m_cEncLib.setRecoveryPointSEIEnabled ( m_recoveryPointSEIEnabled ); +#endif +#if JVET_N0494_DRAP + m_cEncLib.setDependentRAPIndicationSEIEnabled ( m_drapPeriod > 0 ); #endif m_cEncLib.setBufferingPeriodSEIEnabled ( m_bufferingPeriodSEIEnabled ); m_cEncLib.setPictureTimingSEIEnabled ( m_pictureTimingSEIEnabled ); diff --git a/source/App/EncoderApp/EncAppCfg.cpp b/source/App/EncoderApp/EncAppCfg.cpp index 4c9d04073453b29a59f0659637f9f5cd27680346..9c3f7f28279460eb710d748672e2cc44a6675e91 100644 --- a/source/App/EncoderApp/EncAppCfg.cpp +++ b/source/App/EncoderApp/EncAppCfg.cpp @@ -1017,6 +1017,9 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] ) ("IntraPeriod,-ip", m_iIntraPeriod, -1, "Intra period in frames, (-1: only first frame)") ("DecodingRefreshType,-dr", m_iDecodingRefreshType, 0, "Intra refresh type (0:none 1:CRA 2:IDR 3:RecPointSEI)") ("GOPSize,g", m_iGOPSize, 1, "GOP size of temporal structure") +#if JVET_N0494_DRAP + ("DRAPPeriod", m_drapPeriod, 0, "DRAP period in frames (0: disable Dependent RAP indication SEI messages)") +#endif ("ReWriteParamSets", m_rewriteParamSets, false, "Enable rewriting of Parameter sets before every (intra) random access point") //Alias with same name as in HM ("ReWriteParamSetsFlag", m_rewriteParamSets, false, "Alias for ReWriteParamSets") @@ -2571,6 +2574,9 @@ bool EncAppCfg::xCheckParameter() xConfirmPara( m_iGOPSize < 1 , "GOP Size must be greater or equal to 1" ); xConfirmPara( m_iGOPSize > 1 && m_iGOPSize % 2, "GOP Size must be a multiple of 2, if GOP Size is greater than 1" ); xConfirmPara( (m_iIntraPeriod > 0 && m_iIntraPeriod < m_iGOPSize) || m_iIntraPeriod == 0, "Intra period must be more than GOP size, or -1 , not 0" ); +#if JVET_N0494_DRAP + xConfirmPara( m_drapPeriod < 0, "DRAP period must be greater or equal to 0" ); +#endif xConfirmPara( m_iDecodingRefreshType < 0 || m_iDecodingRefreshType > 3, "Decoding Refresh Type must be comprised between 0 and 3 included" ); #if HEVC_SEI if(m_iDecodingRefreshType == 3) @@ -3347,6 +3353,10 @@ bool EncAppCfg::xCheckParameter() THROW("Invalid value for PPSorSliceMode"); } #endif +#if JVET_N0494_DRAP + xConfirmPara(m_drapPeriod > 0 && m_PPSRefPicListSPSIdc0 > 0, "PPSRefPicListSPSIdc0 shall be 0 when DRAP is used. This can be fixed by setting PPSorSliceMode=0."); + xConfirmPara(m_drapPeriod > 0 && m_PPSRefPicListSPSIdc1 > 0, "PPSRefPicListSPSIdc1 shall be 0 when DRAP is used. This can be fixed by setting PPSorSliceMode=0."); +#endif #if HEVC_SEI if (m_toneMappingInfoSEIEnabled) @@ -3535,6 +3545,9 @@ void EncAppCfg::xPrintParameter() msg( DETAILS, "Motion search range : %d\n", m_iSearchRange ); msg( DETAILS, "Intra period : %d\n", m_iIntraPeriod ); msg( DETAILS, "Decoding refresh type : %d\n", m_iDecodingRefreshType ); +#if JVET_N0494_DRAP + msg( DETAILS, "DRAP period : %d\n", m_drapPeriod ); +#endif #if QP_SWITCHING_FOR_PARALLEL if (m_qpIncrementAtSourceFrame.bPresent) { diff --git a/source/App/EncoderApp/EncAppCfg.h b/source/App/EncoderApp/EncAppCfg.h index 6867b7bfb094c0903833dac5ee212ed3ac979ab1..8f077ac89d1bcea11040647305d2683a4774598e 100644 --- a/source/App/EncoderApp/EncAppCfg.h +++ b/source/App/EncoderApp/EncAppCfg.h @@ -179,6 +179,9 @@ protected: int m_iIntraPeriod; ///< period of I-slice (random access period) int m_iDecodingRefreshType; ///< random access type int m_iGOPSize; ///< GOP size of hierarchical structure +#if JVET_N0494_DRAP + int m_drapPeriod; ///< period of dependent RAP pictures +#endif bool m_rewriteParamSets; ///< Flag to enable rewriting of parameter sets at random access points RPLEntry m_RPLList0[MAX_GOP]; ///< the RPL entries from the config file RPLEntry m_RPLList1[MAX_GOP]; ///< the RPL entries from the config file diff --git a/source/Lib/CommonLib/Picture.cpp b/source/Lib/CommonLib/Picture.cpp index 12ba8ea0342b52b7c91eb839c7179a8794bd495b..0d250e366451d013ea984adaf42d1b2f146ba9b2 100644 --- a/source/Lib/CommonLib/Picture.cpp +++ b/source/Lib/CommonLib/Picture.cpp @@ -738,6 +738,9 @@ Picture::Picture() layer = std::numeric_limits<uint32_t>::max(); fieldPic = false; topField = false; +#if JVET_N0494_DRAP + precedingDRAP = false; +#endif for( int i = 0; i < MAX_NUM_CHANNEL_TYPE; i++ ) { m_prevQP[i] = -1; diff --git a/source/Lib/CommonLib/Picture.h b/source/Lib/CommonLib/Picture.h index 85ccb3d4720799f5ecfb100582719ce3634c7484..7baba024b62ebcd5b166a6f598565ec145c8612e 100644 --- a/source/Lib/CommonLib/Picture.h +++ b/source/Lib/CommonLib/Picture.h @@ -271,6 +271,9 @@ public: bool topField; bool fieldPic; int m_prevQP[MAX_NUM_CHANNEL_TYPE]; +#if JVET_N0494_DRAP + bool precedingDRAP; // preceding a DRAP picture in decoding order +#endif int poc; uint32_t layer; diff --git a/source/Lib/CommonLib/SEI.cpp b/source/Lib/CommonLib/SEI.cpp index 0de07d6fe59e0c4ccb5272d4c61991322efda0f7..16e6f7e92f47ff5f6bf6b5eed13569aaa8b13935 100644 --- a/source/Lib/CommonLib/SEI.cpp +++ b/source/Lib/CommonLib/SEI.cpp @@ -179,6 +179,9 @@ const char *SEI::getSEIMessageString(SEI::PayloadType payloadType) case SEI::TEMPORAL_LEVEL0_INDEX: return "Temporal sub-layer zero index"; #endif case SEI::DECODED_PICTURE_HASH: return "Decoded picture hash"; +#if JVET_N0494_DRAP + case SEI::DEPENDENT_RAP_INDICATION: return "Dependent RAP indication"; +#endif #if HEVC_SEI case SEI::SCALABLE_NESTING: return "Scalable nesting"; case SEI::REGION_REFRESH_INFO: return "Region refresh information"; diff --git a/source/Lib/CommonLib/SEI.h b/source/Lib/CommonLib/SEI.h index 3a827fc944acffffadb9e7028c72c8195a475160..fd1ff2b91326c3eb587d6905f5895f5c5a4b6193 100644 --- a/source/Lib/CommonLib/SEI.h +++ b/source/Lib/CommonLib/SEI.h @@ -93,6 +93,11 @@ public: CHROMA_RESAMPLING_FILTER_HINT = 140, KNEE_FUNCTION_INFO = 141, COLOUR_REMAPPING_INFO = 142, +#endif +#if JVET_N0494_DRAP + DEPENDENT_RAP_INDICATION = 145, +#endif +#if HEVC_SEI #if U0033_ALTERNATIVE_TRANSFER_CHARACTERISTICS_SEI ALTERNATIVE_TRANSFER_CHARACTERISTICS = 182, #endif @@ -146,6 +151,17 @@ public: PictureHash m_pictureHash; }; +#if JVET_N0494_DRAP +class SEIDependentRAPIndication : public SEI +{ +public: + PayloadType payloadType() const { return DEPENDENT_RAP_INDICATION; } + SEIDependentRAPIndication() { } + + virtual ~SEIDependentRAPIndication() { } +}; +#endif + #if HEVC_SEI class SEIActiveParameterSets : public SEI { diff --git a/source/Lib/CommonLib/Slice.cpp b/source/Lib/CommonLib/Slice.cpp index 8e0e419ee40a16706b9b39b5462ca749177a7af2..42f06af1a4c8ec1ab3485563559d767d03dbfab2 100644 --- a/source/Lib/CommonLib/Slice.cpp +++ b/source/Lib/CommonLib/Slice.cpp @@ -220,6 +220,12 @@ void Slice::initSlice() m_jointCbCrSignFlag = false; #endif m_enableTMVPFlag = true; +#if JVET_N0494_DRAP + m_enableDRAPSEI = false; + m_useLTforDRAP = false; + m_isDRAP = false; + m_latestDRAPPOC = MAX_INT; +#endif #if JVET_O0090_ALF_CHROMA_FILTER_ALTERNATIVES_CTB resetTileGroupAlfEnabledFlag(); #endif @@ -1098,6 +1104,101 @@ int Slice::checkThatAllRefPicsAreAvailable(PicList& rcListPic, const ReferencePi return 0; } +#if JVET_N0494_DRAP +bool Slice::isPOCInRefPicList(const ReferencePictureList *rpl, int poc ) +{ + for (int i = 0; i < rpl->getNumberOfLongtermPictures() + rpl->getNumberOfShorttermPictures(); i++) + { + if (rpl->isRefPicLongterm(i)) + { + if (poc == rpl->getRefPicIdentifier(i)) + { + return true; + } + } + else + { + if (poc == getPOC() - rpl->getRefPicIdentifier(i)) + { + return true; + } + } + } + return false; +} + +bool Slice::isPocRestrictedByDRAP( int poc, bool precedingDRAPInDecodingOrder ) +{ + if (!getEnableDRAPSEI()) + { + return false; + } + return ( isDRAP() && poc != getAssociatedIRAPPOC() ) || + ( cvsHasPreviousDRAP() && getPOC() > getLatestDRAPPOC() && (precedingDRAPInDecodingOrder || poc < getLatestDRAPPOC()) ); +} + +void Slice::checkConformanceForDRAP( uint32_t temporalId ) +{ + if (!(isDRAP() || cvsHasPreviousDRAP())) + { + return; + } + + if (isDRAP()) + { + if (!(getNalUnitType() == NalUnitType::NAL_UNIT_CODED_SLICE_TRAIL || + getNalUnitType() == NalUnitType::NAL_UNIT_CODED_SLICE_STSA)) + { + msg( WARNING, "Warning, non-conforming bitstream. The DRAP picture should be a trailing picture.\n"); + } + if ( temporalId != 0) + { + msg( WARNING, "Warning, non-conforming bitstream. The DRAP picture shall have a temporal sublayer identifier equal to 0.\n"); + } + for (int i = 0; i < getNumRefIdx(REF_PIC_LIST_0); i++) + { + if (getRefPic(REF_PIC_LIST_0,i)->getPOC() != getAssociatedIRAPPOC()) + { + msg( WARNING, "Warning, non-conforming bitstream. The DRAP picture shall not include any pictures in the active " + "entries of its reference picture lists except the preceding IRAP picture in decoding order.\n"); + } + } + for (int i = 0; i < getNumRefIdx(REF_PIC_LIST_1); i++) + { + if (getRefPic(REF_PIC_LIST_1,i)->getPOC() != getAssociatedIRAPPOC()) + { + msg( WARNING, "Warning, non-conforming bitstream. The DRAP picture shall not include any pictures in the active " + "entries of its reference picture lists except the preceding IRAP picture in decoding order.\n"); + } + } + } + + if (cvsHasPreviousDRAP() && getPOC() > getLatestDRAPPOC()) + { + for (int i = 0; i < getNumRefIdx(REF_PIC_LIST_0); i++) + { + if (getRefPic(REF_PIC_LIST_0,i)->getPOC() < getLatestDRAPPOC() && getRefPic(REF_PIC_LIST_0,i)->getPOC() != getAssociatedIRAPPOC()) + { + msg( WARNING, "Warning, non-conforming bitstream. Any picture that follows the DRAP picture in both decoding order " + "and output order shall not include, in the active entries of its reference picture lists, any picture " + "that precedes the DRAP picture in decoding order or output order, with the exception of the preceding " + "IRAP picture in decoding order. Problem is POC %d in RPL0.\n", getRefPic(REF_PIC_LIST_0,i)->getPOC()); + } + } + for (int i = 0; i < getNumRefIdx(REF_PIC_LIST_1); i++) + { + if (getRefPic(REF_PIC_LIST_1,i)->getPOC() < getLatestDRAPPOC() && getRefPic(REF_PIC_LIST_1,i)->getPOC() != getAssociatedIRAPPOC()) + { + msg( WARNING, "Warning, non-conforming bitstream. Any picture that follows the DRAP picture in both decoding order " + "and output order shall not include, in the active entries of its reference picture lists, any picture " + "that precedes the DRAP picture in decoding order or output order, with the exception of the preceding " + "IRAP picture in decoding order. Problem is POC %d in RPL1", getRefPic(REF_PIC_LIST_1,i)->getPOC()); + } + } + } +} +#endif + void Slice::createExplicitReferencePictureSetFromReference(PicList& rcListPic, const ReferencePictureList *pRPL0, const ReferencePictureList *pRPL1) { Picture* rpcPic; @@ -1121,12 +1222,20 @@ void Slice::createExplicitReferencePictureSetFromReference(PicList& rcListPic, c while (iterPic != rcListPic.end()) { rpcPic = *(iterPic++); +#if JVET_N0494_DRAP + if (!pRPL0->isRefPicLongterm(ii) && rpcPic->referenced && rpcPic->getPOC() == this->getPOC() - pRPL0->getRefPicIdentifier(ii) && !isPocRestrictedByDRAP(rpcPic->getPOC(), rpcPic->precedingDRAP)) +#else if (!pRPL0->isRefPicLongterm(ii) && rpcPic->referenced && rpcPic->getPOC() == this->getPOC() - pRPL0->getRefPicIdentifier(ii)) +#endif { isAvailable = true; break; } +#if JVET_N0494_DRAP + else if (pRPL0->isRefPicLongterm(ii) && rpcPic->referenced && (rpcPic->getPOC() & (pocCycle - 1)) == pRPL0->getRefPicIdentifier(ii) && !isPocRestrictedByDRAP(rpcPic->getPOC(), rpcPic->precedingDRAP)) +#else else if (pRPL0->isRefPicLongterm(ii) && rpcPic->referenced && (rpcPic->getPOC() & (pocCycle - 1)) == pRPL0->getRefPicIdentifier(ii)) +#endif { isAvailable = true; break; @@ -1142,6 +1251,31 @@ void Slice::createExplicitReferencePictureSetFromReference(PicList& rcListPic, c } } +#if JVET_N0494_DRAP + if (getEnableDRAPSEI()) + { + pLocalRPL0->setNumberOfShorttermPictures(numOfSTRPL0); + pLocalRPL0->setNumberOfLongtermPictures(numOfLTRPL0); + if (!isIRAP() && !isPOCInRefPicList(pLocalRPL0, getAssociatedIRAPPOC())) + { + if (getUseLTforDRAP() && !isPOCInRefPicList(pRPL1, getAssociatedIRAPPOC())) + { + // Adding associated IRAP as longterm picture + pLocalRPL0->setRefPicIdentifier(refPicIdxL0, getAssociatedIRAPPOC(), true); + refPicIdxL0++; + numOfLTRPL0++; + } + else + { + // Adding associated IRAP as shortterm picture + pLocalRPL0->setRefPicIdentifier(refPicIdxL0, this->getPOC() - getAssociatedIRAPPOC(), false); + refPicIdxL0++; + numOfSTRPL0++; + } + } + } +#endif + ReferencePictureList* pLocalRPL1 = this->getLocalRPL1(); (*pLocalRPL1) = ReferencePictureList(); @@ -1158,12 +1292,20 @@ void Slice::createExplicitReferencePictureSetFromReference(PicList& rcListPic, c while (iterPic != rcListPic.end()) { rpcPic = *(iterPic++); +#if JVET_N0494_DRAP + if (!pRPL1->isRefPicLongterm(ii) && rpcPic->referenced && rpcPic->getPOC() == this->getPOC() - pRPL1->getRefPicIdentifier(ii) && !isPocRestrictedByDRAP(rpcPic->getPOC(), rpcPic->precedingDRAP)) +#else if (!pRPL1->isRefPicLongterm(ii) && rpcPic->referenced && rpcPic->getPOC() == this->getPOC() - pRPL1->getRefPicIdentifier(ii)) +#endif { isAvailable = true; break; } +#if JVET_N0494_DRAP + else if (pRPL1->isRefPicLongterm(ii) && rpcPic->referenced && (rpcPic->getPOC() & (pocCycle - 1)) == pRPL1->getRefPicIdentifier(ii) && !isPocRestrictedByDRAP(rpcPic->getPOC(), rpcPic->precedingDRAP)) +#else else if (pRPL1->isRefPicLongterm(ii) && rpcPic->referenced && (rpcPic->getPOC() & (pocCycle - 1)) == pRPL1->getRefPicIdentifier(ii)) +#endif { isAvailable = true; break; @@ -1238,9 +1380,13 @@ void Slice::createExplicitReferencePictureSetFromReference(PicList& rcListPic, c { pLocalRPL1->setRefPicIdentifier(refPicIdxL1, pLocalRPL0->getRefPicIdentifier(ii), pLocalRPL0->isRefPicLongterm(ii)); refPicIdxL1++; +#if JVET_N0494_DRAP + numOfSTRPL1 = numOfSTRPL1 + ((pLocalRPL0->isRefPicLongterm(ii)) ? 0 : 1); + numOfLTRPL1 = numOfLTRPL1 + ((pLocalRPL0->isRefPicLongterm(ii)) ? 1 : 0); +#else numOfSTRPL1 = numOfSTRPL1 + ((pRPL0->isRefPicLongterm(ii)) ? 0 : 1); numOfLTRPL1 = numOfLTRPL1 + ((pRPL0->isRefPicLongterm(ii)) ? 1 : 0); - +#endif numOfNeedToFill--; } } diff --git a/source/Lib/CommonLib/Slice.h b/source/Lib/CommonLib/Slice.h index 7e3887cb31c77144deebdf0eab1685fcb8f1067e..22ac7ed2d7745099d354ffeb455737b72edc6ff5 100644 --- a/source/Lib/CommonLib/Slice.h +++ b/source/Lib/CommonLib/Slice.h @@ -1641,6 +1641,12 @@ private: int m_iLastIDR; int m_iAssociatedIRAP; NalUnitType m_iAssociatedIRAPType; +#if JVET_N0494_DRAP + bool m_enableDRAPSEI; + bool m_useLTforDRAP; + bool m_isDRAP; + int m_latestDRAPPOC; +#endif const ReferencePictureList* m_pRPL0; //< pointer to RPL for L0, either in the SPS or the local RPS in the same slice header const ReferencePictureList* m_pRPL1; //< pointer to RPL for L1, either in the SPS or the local RPS in the same slice header ReferencePictureList m_localRPL0; //< RPL for L0 when present in slice header @@ -1908,6 +1914,21 @@ public: bool isInterB() const { return m_eSliceType == B_SLICE; } bool isInterP() const { return m_eSliceType == P_SLICE; } +#if JVET_N0494_DRAP + bool getEnableDRAPSEI () const { return m_enableDRAPSEI; } + void setEnableDRAPSEI ( bool b ) { m_enableDRAPSEI = b; } + bool getUseLTforDRAP () const { return m_useLTforDRAP; } + void setUseLTforDRAP ( bool b ) { m_useLTforDRAP = b; } + bool isDRAP () const { return m_isDRAP; } + void setDRAP ( bool b ) { m_isDRAP = b; } + void setLatestDRAPPOC ( int i ) { m_latestDRAPPOC = i; } + int getLatestDRAPPOC () const { return m_latestDRAPPOC; } + bool cvsHasPreviousDRAP() const { return m_latestDRAPPOC != MAX_INT; } + bool isPocRestrictedByDRAP( int poc, bool precedingDRAPinDecodingOrder ); + bool isPOCInRefPicList( const ReferencePictureList *rpl, int poc ); + void checkConformanceForDRAP( uint32_t temporalId ); +#endif + 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; } diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h index 153e17186e59207159079333ec376715204a1be7..aae385021c123c4de5d5a957cfe4dc4a5397adf8 100644 --- a/source/Lib/CommonLib/TypeDef.h +++ b/source/Lib/CommonLib/TypeDef.h @@ -50,6 +50,8 @@ #include <assert.h> #include <cassert> +#define JVET_N0494_DRAP 1 // JVET-N0494: Dependent random access point indication SEI + #define JVET_O0299_APS_SCALINGLIST 1 // JVET-O0299: Scaling List Matrices Support in APS #define JVET_O1164_RPR 1 // JVET-O1164: Reference picture resampling diff --git a/source/Lib/DecoderLib/DecLib.cpp b/source/Lib/DecoderLib/DecLib.cpp index a8eb7db2e8d141d6b8cc99e0fc22b8f017b4102e..e4d478d1cde6e677063a7efe364cdf9c6a2c2c1f 100644 --- a/source/Lib/DecoderLib/DecLib.cpp +++ b/source/Lib/DecoderLib/DecLib.cpp @@ -637,6 +637,10 @@ void DecLib::finishPicture(int& poc, PicList*& rpcListPic, MsgLevel msgl ) c += 32; // tolower } +#if JVET_N0494_DRAP + if (pcSlice->isDRAP()) c = 'D'; +#endif + //-- For time output for each slice msg( msgl, "POC %4d TId: %1d ( %c-SLICE, QP%3d ) ", pcSlice->getPOC(), pcSlice->getTLayer(), @@ -1544,6 +1548,16 @@ bool DecLib::xDecodeSlice(InputNALUnit &nalu, int &iSkipFrame, int iPOCLastDispl //--------------- pcSlice->setRefPOCList(); +#if JVET_N0494_DRAP + SEIMessages drapSEIs = getSeisByType(m_pcPic->SEIs, SEI::DEPENDENT_RAP_INDICATION ); + if (!drapSEIs.empty()) + { + msg( NOTICE, "Dependent RAP indication SEI decoded\n"); + pcSlice->setDRAP(true); + pcSlice->setLatestDRAPPOC(pcSlice->getPOC()); + } + pcSlice->checkConformanceForDRAP(nalu.m_temporalId); +#endif Quant *quant = m_cTrQuant.getQuant(); diff --git a/source/Lib/DecoderLib/SEIread.cpp b/source/Lib/DecoderLib/SEIread.cpp index 06246dc3ef9575a2b9736001b94ba7ec03308da2..eb88707a89582c1d14a71d8565f3f7d9971f0b2b 100644 --- a/source/Lib/DecoderLib/SEIread.cpp +++ b/source/Lib/DecoderLib/SEIread.cpp @@ -245,6 +245,12 @@ void SEIReader::xReadSEImessage(SEIMessages& seis, const NalUnitType nalUnitType xParseSEIFrameFieldinfo((SEIFrameFieldInfo&) *sei, payloadSize, pDecodedMessageOutputStream); break; #endif +#if JVET_N0494_DRAP + case SEI::DEPENDENT_RAP_INDICATION: + sei = new SEIDependentRAPIndication; + xParseSEIDependentRAPIndication((SEIDependentRAPIndication&) *sei, payloadSize, pDecodedMessageOutputStream); + break; +#endif #if HEVC_SEI case SEI::RECOVERY_POINT: sei = new SEIRecoveryPoint; @@ -748,6 +754,13 @@ void SEIReader::xParseSEIFrameFieldinfo(SEIFrameFieldInfo& sei, uint32_t payload } #endif +#if JVET_N0494_DRAP +void SEIReader::xParseSEIDependentRAPIndication( SEIDependentRAPIndication& sei, uint32_t payloadSize, std::ostream *pDecodedMessageOutputStream ) +{ + output_sei_message_header(sei, pDecodedMessageOutputStream, payloadSize); +} +#endif + #if HEVC_SEI void SEIReader::xParseSEIRecoveryPoint(SEIRecoveryPoint& sei, uint32_t payloadSize, std::ostream *pDecodedMessageOutputStream) diff --git a/source/Lib/DecoderLib/SEIread.h b/source/Lib/DecoderLib/SEIread.h index 9e9f016b8f15e799d3723bf3011e42b9218336d0..2e88714095b444debd46585c3736524cde2598bc 100644 --- a/source/Lib/DecoderLib/SEIread.h +++ b/source/Lib/DecoderLib/SEIread.h @@ -83,6 +83,9 @@ protected: #if JVET_O0041_FRAME_FIELD_SEI void xParseSEIFrameFieldinfo (SEIFrameFieldInfo& sei, uint32_t payloadSize, std::ostream *pDecodedMessageOutputStream); #endif +#if JVET_N0494_DRAP + void xParseSEIDependentRAPIndication (SEIDependentRAPIndication& sei, uint32_t payLoadSize, 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/EncoderLib/EncCfg.h b/source/Lib/EncoderLib/EncCfg.h index 5ab2f05db8e106a33f95789b3c97939479793f68..694c13f38b30ec9bae11813fbbf0392369e0df9c 100644 --- a/source/Lib/EncoderLib/EncCfg.h +++ b/source/Lib/EncoderLib/EncCfg.h @@ -258,6 +258,9 @@ protected: GOPEntry m_GOPList[MAX_GOP]; int m_maxDecPicBuffering[MAX_TLAYER]; int m_numReorderPics[MAX_TLAYER]; +#if JVET_N0494_DRAP + int m_drapPeriod; +#endif int m_iQP; // if (AdaptiveQP == OFF) #if JVET_O0650_SIGNAL_CHROMAQP_MAPPING_TABLE @@ -521,6 +524,9 @@ protected: #if JVET_O0041_FRAME_FIELD_SEI bool m_frameFieldInfoSEIEnabled; #endif +#if JVET_N0494_DRAP + bool m_dependentRAPIndicationSEIEnabled; +#endif #if HEVC_SEI bool m_recoveryPointSEIEnabled; bool m_toneMappingInfoSEIEnabled; @@ -868,6 +874,9 @@ public: void setEncodedFlag(uint32_t i, bool value) { m_RPLList0[i].m_isEncoded = value; m_RPLList1[i].m_isEncoded = value; } void setMaxDecPicBuffering ( uint32_t u, uint32_t tlayer ) { m_maxDecPicBuffering[tlayer] = u; } void setNumReorderPics ( int i, uint32_t tlayer ) { m_numReorderPics[tlayer] = i; } +#if JVET_N0494_DRAP + void setDrapPeriod (int drapPeriod) { m_drapPeriod = drapPeriod; } +#endif void setBaseQP ( int i ) { m_iQP = i; } #if X0038_LAMBDA_FROM_QP_CAPABILITY @@ -1165,6 +1174,9 @@ public: int getGOPSize () const { return m_iGOPSize; } int getMaxDecPicBuffering (uint32_t tlayer) { return m_maxDecPicBuffering[tlayer]; } int getNumReorderPics (uint32_t tlayer) { return m_numReorderPics[tlayer]; } +#if JVET_N0494_DRAP + int getDrapPeriod () { return m_drapPeriod; } +#endif #if X0038_LAMBDA_FROM_QP_CAPABILITY int getIntraQPOffset () const { return m_intraQPOffset; } int getLambdaFromQPEnable () const { return m_lambdaFromQPEnable; } @@ -1386,6 +1398,10 @@ public: void setFrameFieldInfoSEIEnabled(bool b) { m_frameFieldInfoSEIEnabled = b; } bool getFrameFieldInfoSEIEnabled() const { return m_frameFieldInfoSEIEnabled; } #endif +#if JVET_N0494_DRAP + void setDependentRAPIndicationSEIEnabled(bool b) { m_dependentRAPIndicationSEIEnabled = b; } + int getDependentRAPIndicationSEIEnabled() const { return m_dependentRAPIndicationSEIEnabled; } +#endif #if HEVC_SEI void setRecoveryPointSEIEnabled(bool b) { m_recoveryPointSEIEnabled = b; } bool getRecoveryPointSEIEnabled() const { return m_recoveryPointSEIEnabled; } diff --git a/source/Lib/EncoderLib/EncGOP.cpp b/source/Lib/EncoderLib/EncGOP.cpp index 034a4558b99e1c5d2363b116f4eefa8978684dba..57e526936d9081943cb507d4aaa6f470b42840ad 100644 --- a/source/Lib/EncoderLib/EncGOP.cpp +++ b/source/Lib/EncoderLib/EncGOP.cpp @@ -88,6 +88,9 @@ EncGOP::EncGOP() m_iNumPicCoded = 0; //Niko m_bFirst = true; m_iLastRecoveryPicPOC = 0; +#if JVET_N0494_DRAP + m_latestDRAPPOC = MAX_INT; +#endif m_lastRasPoc = MAX_INT; m_pcCfg = NULL; @@ -716,6 +719,15 @@ void EncGOP::xCreatePerPictureSEIMessages (int picInGOP, SEIMessages& seiMessage #endif } +#if JVET_N0494_DRAP + if (m_pcEncLib->getDependentRAPIndicationSEIEnabled() && slice->isDRAP()) + { + SEIDependentRAPIndication *dependentRAPIndicationSEI = new SEIDependentRAPIndication(); + m_seiEncoder.initSEIDependentRAPIndication(dependentRAPIndicationSEI); + seiMessages.push_back(dependentRAPIndicationSEI); + } +#endif + #if HEVC_SEI if (picInGOP ==0 && m_pcCfg->getSOPDescriptionSEIEnabled() ) // write SOP description SEI (if enabled) at the beginning of GOP { @@ -2048,7 +2060,50 @@ void EncGOP::compressGOP( int iPOCLast, int iNumPicRcvd, PicList& rcListPic, pcSlice->setAssociatedIRAPPOC(m_associatedIRAPPOC); } +#if JVET_N0494_DRAP + pcSlice->setEnableDRAPSEI(m_pcEncLib->getDependentRAPIndicationSEIEnabled()); + if (m_pcEncLib->getDependentRAPIndicationSEIEnabled()) + { + // Only mark the picture as DRAP if all of the following applies: + // 1) DRAP indication SEI messages are enabled + // 2) The current picture is not an intra picture + // 3) The current picture is in the DRAP period + // 4) The current picture is a trailing picture + pcSlice->setDRAP(m_pcEncLib->getDependentRAPIndicationSEIEnabled() && m_pcEncLib->getDrapPeriod() > 0 && !pcSlice->isIntra() && + pocCurr % m_pcEncLib->getDrapPeriod() == 0 && pocCurr > pcSlice->getAssociatedIRAPPOC()); + + if (pcSlice->isDRAP()) + { + int pocCycle = 1 << (pcSlice->getSPS()->getBitsForPOC()); + int deltaPOC = pocCurr > pcSlice->getAssociatedIRAPPOC() ? pocCurr - pcSlice->getAssociatedIRAPPOC() : pocCurr - ( pcSlice->getAssociatedIRAPPOC() & (pocCycle -1) ); + CHECK(deltaPOC > (pocCycle >> 1), "Use a greater value for POC wraparound to enable a POC distance between IRAP and DRAP of " << deltaPOC << "."); + m_latestDRAPPOC = pocCurr; + pcSlice->setTLayer(0); // Force DRAP picture to have temporal layer 0 + } + pcSlice->setLatestDRAPPOC(m_latestDRAPPOC); + pcSlice->setUseLTforDRAP(false); // When set, sets the associated IRAP as long-term in RPL0 at slice level, unless the associated IRAP is already included in RPL0 or RPL1 defined in SPS + + PicList::iterator iterPic = rcListPic.begin(); + Picture *rpcPic; + while (iterPic != rcListPic.end()) + { + rpcPic = *(iterPic++); + if ( pcSlice->isDRAP() && rpcPic->getPOC() != pocCurr ) + { + rpcPic->precedingDRAP = true; + } + else if ( !pcSlice->isDRAP() && rpcPic->getPOC() == pocCurr ) + { + rpcPic->precedingDRAP = false; + } + } + } + + if (pcSlice->checkThatAllRefPicsAreAvailable(rcListPic, pcSlice->getRPL0(), 0, false) != 0 || pcSlice->checkThatAllRefPicsAreAvailable(rcListPic, pcSlice->getRPL1(), 1, false) != 0 || + (m_pcEncLib->getDependentRAPIndicationSEIEnabled() && !pcSlice->isIRAP() && ( pcSlice->isDRAP() || !pcSlice->isPOCInRefPicList(pcSlice->getRPL0(), pcSlice->getAssociatedIRAPPOC())) )) +#else if (pcSlice->checkThatAllRefPicsAreAvailable(rcListPic, pcSlice->getRPL0(), 0, false) != 0 || pcSlice->checkThatAllRefPicsAreAvailable(rcListPic, pcSlice->getRPL1(), 1, false) != 0) +#endif { pcSlice->createExplicitReferencePictureSetFromReference(rcListPic, pcSlice->getRPL0(), pcSlice->getRPL1()); } @@ -3933,6 +3988,9 @@ void EncGOP::xCalculateAddPSNR(Picture* pcPic, PelUnitBuf cPicD, const AccessUni { c += 32; } +#if JVET_N0494_DRAP + if (m_pcCfg->getDependentRAPIndicationSEIEnabled() && pcSlice->isDRAP()) c = 'D'; +#endif if( g_verbosity >= NOTICE ) { diff --git a/source/Lib/EncoderLib/EncGOP.h b/source/Lib/EncoderLib/EncGOP.h index 7d62ba1c48781b4a4dc2cbf45d2a4ac2159ec647..792b4e4471e9bc1d8bb254e47c9ecf2fd5dd8f42 100644 --- a/source/Lib/EncoderLib/EncGOP.h +++ b/source/Lib/EncoderLib/EncGOP.h @@ -129,6 +129,9 @@ private: int m_iNumPicCoded; bool m_bFirst; int m_iLastRecoveryPicPOC; +#if JVET_N0494_DRAP + int m_latestDRAPPOC; +#endif int m_lastRasPoc; // Access channel diff --git a/source/Lib/EncoderLib/EncLib.cpp b/source/Lib/EncoderLib/EncLib.cpp index 025332cac9e28d9dcdd9179072164f8d51165273..de684c90252349f3131407a18847b50cbcc47cb2 100644 --- a/source/Lib/EncoderLib/EncLib.cpp +++ b/source/Lib/EncoderLib/EncLib.cpp @@ -266,7 +266,11 @@ void EncLib::init( bool isFieldCoding, AUWriterIf* auWriterIf ) omp_set_nested( true ); #endif +#if JVET_N0494_DRAP + if (getUseCompositeRef() || getDependentRAPIndicationSEIEnabled()) +#else if (getUseCompositeRef()) +#endif { sps0.setLongTermRefsPresent(true); } diff --git a/source/Lib/EncoderLib/SEIEncoder.cpp b/source/Lib/EncoderLib/SEIEncoder.cpp index c8735dfe3bc4ec6e2c14093d5446c82ca526309c..f3c5db87f4c903291e2c0c89450234dda44f4388 100644 --- a/source/Lib/EncoderLib/SEIEncoder.cpp +++ b/source/Lib/EncoderLib/SEIEncoder.cpp @@ -324,6 +324,14 @@ void SEIEncoder::initDecodedPictureHashSEI(SEIDecodedPictureHash *decodedPicture } } +#if JVET_N0494_DRAP +void SEIEncoder::initSEIDependentRAPIndication(SEIDependentRAPIndication *seiDependentRAPIndication) +{ + CHECK(!(m_isInitialized), "Unspecified error"); + CHECK(!(seiDependentRAPIndication!=NULL), "Unspecified error"); +} +#endif + #if HEVC_SEI void SEIEncoder::initTemporalLevel0IndexSEI(SEITemporalLevel0Index *temporalLevel0IndexSEI, Slice *slice) { diff --git a/source/Lib/EncoderLib/SEIEncoder.h b/source/Lib/EncoderLib/SEIEncoder.h index 2f5c9c00147d04fc4f1372fbac58f4f2f9980590..7a0ae83a107b722a37249ce0713b8454cfb21d09 100644 --- a/source/Lib/EncoderLib/SEIEncoder.h +++ b/source/Lib/EncoderLib/SEIEncoder.h @@ -77,6 +77,9 @@ public: void initSEISOPDescription(SEISOPDescription *sei, Slice *slice, int picInGOP, int lastIdr, int currGOPSize); #endif void initSEIBufferingPeriod(SEIBufferingPeriod *sei); +#if JVET_N0494_DRAP + void initSEIDependentRAPIndication(SEIDependentRAPIndication *sei); +#endif #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 dbd3675b861c34209349f2b0ce8812497cfbc94f..9a4386b62f95f09039f36c521a117a371b8833b7 100644 --- a/source/Lib/EncoderLib/SEIwrite.cpp +++ b/source/Lib/EncoderLib/SEIwrite.cpp @@ -87,6 +87,11 @@ void SEIWriter::xWriteSEIpayloadData(OutputBitstream& bs, const SEI& sei, const xWriteSEIFrameFieldInfo(*static_cast<const SEIFrameFieldInfo*>(&sei)); break; #endif +#if JVET_N0494_DRAP + case SEI::DEPENDENT_RAP_INDICATION: + xWriteSEIDependentRAPIndication(*static_cast<const SEIDependentRAPIndication*>(&sei)); + break; +#endif #if HEVC_SEI case SEI::RECOVERY_POINT: xWriteSEIRecoveryPoint(*static_cast<const SEIRecoveryPoint*>(&sei)); @@ -458,6 +463,12 @@ void SEIWriter::xWriteSEIFrameFieldInfo(const SEIFrameFieldInfo& sei) } #endif +#if JVET_N0494_DRAP +void SEIWriter::xWriteSEIDependentRAPIndication(const SEIDependentRAPIndication& /*sei*/) +{ + // intentionally empty +} +#endif #if HEVC_SEI void SEIWriter::xWriteSEIRecoveryPoint(const SEIRecoveryPoint& sei) diff --git a/source/Lib/EncoderLib/SEIwrite.h b/source/Lib/EncoderLib/SEIwrite.h index 498c5ea3af7e2c2d70e0677c4db3bea0cff6fa2e..da64eeae746f2f68fa0d656b3660eb5b6a818611 100644 --- a/source/Lib/EncoderLib/SEIwrite.h +++ b/source/Lib/EncoderLib/SEIwrite.h @@ -72,6 +72,9 @@ protected: #if JVET_O0041_FRAME_FIELD_SEI void xWriteSEIFrameFieldInfo(const SEIFrameFieldInfo& sei); #endif +#if JVET_N0494_DRAP + void xWriteSEIDependentRAPIndication(const SEIDependentRAPIndication& sei); +#endif #if HEVC_SEI void xWriteSEIRecoveryPoint(const SEIRecoveryPoint& sei); void xWriteSEIFramePacking(const SEIFramePacking& sei); diff --git a/source/Lib/EncoderLib/VLCWriter.cpp b/source/Lib/EncoderLib/VLCWriter.cpp index f2678b97cb353877f027faa23e39e9533bd2f4c7..4d85683fb976f5abfbbdc1df908ecbc4eff3ce7b 100644 --- a/source/Lib/EncoderLib/VLCWriter.cpp +++ b/source/Lib/EncoderLib/VLCWriter.cpp @@ -176,7 +176,11 @@ void HLSWriter::xCodeRefPicList(const ReferencePictureList* rpl, bool isLongTerm bool firstSTRP = true; for (int ii = 0; ii < numRefPic; ii++) { +#if JVET_N0494_DRAP + if (isLongTermPresent) +#else if (rpl->getNumberOfLongtermPictures() > 0) +#endif WRITE_FLAG(!rpl->isRefPicLongterm(ii), "st_ref_pic_flag[ listIdx ][ rplsIdx ][ i ]"); if (!rpl->isRefPicLongterm(ii)) {