diff --git a/source/App/DecoderApp/DecApp.cpp b/source/App/DecoderApp/DecApp.cpp index 95d01efe9ab2824f77e0ae734e056c508fc7b5ba..1991d5e7f5b7d80021a02a3259fe77a1d6068739 100644 --- a/source/App/DecoderApp/DecApp.cpp +++ b/source/App/DecoderApp/DecApp.cpp @@ -129,6 +129,9 @@ uint32_t DecApp::decode() bool bPicSkipped = false; bool isEosPresentInPu = false; +#if JVET_S0078_NOOUTPUTPRIORPICFLAG + bool firstSliceInAU = true; +#endif bool outputPicturePresentInBitstream = false; auto setOutputPicturePresentInStream = [&]() @@ -186,7 +189,9 @@ uint32_t DecApp::decode() nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_IDR_N_LP)) { m_newCLVS[nalu.m_nuhLayerId] = true; // An IDR picture starts a new CLVS +#if !JVET_S0078_NOOUTPUTPRIORPICFLAG xFlushOutput(pcListPic, nalu.m_nuhLayerId); +#endif } if (m_cDecLib.getFirstSliceInPicture() && nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_CRA && isEosPresentInPu) { @@ -342,9 +347,47 @@ uint32_t DecApp::decode() #endif { setOutputPicturePresentInStream(); +#if JVET_S0078_NOOUTPUTPRIORPICFLAG + bool firstPicInCVSAUThatIsNotAU0 = false; + if (firstSliceInAU) + { + if (m_targetDecLayerIdSet.size() > 0) + { + if (m_cDecLib.getAudIrapOrGdrAuFlag()) + { + firstPicInCVSAUThatIsNotAU0 = true; + } + } + else + { + if (nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_IDR_W_RADL + || nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_IDR_N_LP + || (nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_CRA && isEosPresentInPu)) + { + firstPicInCVSAUThatIsNotAU0 = true; + } + } + } + if (firstPicInCVSAUThatIsNotAU0) + { + xFlushOutput(pcListPic, NOT_VALID, m_cDecLib.getNoOutputPriorPicsFlag()); + } + else + { + xWriteOutput(pcListPic, nalu.m_temporalId); + } +#else xWriteOutput( pcListPic, nalu.m_temporalId ); +#endif } } +#if JVET_S0078_NOOUTPUTPRIORPICFLAG + if ((nalu.m_nalUnitType >= NAL_UNIT_CODED_SLICE_TRAIL && nalu.m_nalUnitType <= NAL_UNIT_RESERVED_IRAP_VCL_12) + || (nalu.m_nalUnitType >= NAL_UNIT_CODED_SLICE_IDR_W_RADL && nalu.m_nalUnitType <= NAL_UNIT_CODED_SLICE_GDR)) + { + firstSliceInAU = false; + } +#endif if( bNewPicture ) { m_cDecLib.checkSeiInPictureUnit(); @@ -374,6 +417,9 @@ uint32_t DecApp::decode() m_cDecLib.resetAccessUnitNals(); m_cDecLib.resetAccessUnitApsNals(); m_cDecLib.resetAccessUnitPicInfo(); +#if JVET_S0078_NOOUTPUTPRIORPICFLAG + firstSliceInAU = true; +#endif } } // May need to check again one more time as in case one the bitstream has only one picture, the first check may miss it @@ -647,7 +693,11 @@ void DecApp::xWriteOutput( PicList* pcListPic, uint32_t tId ) /** \param pcListPic list of pictures to be written to file */ +#if JVET_S0078_NOOUTPUTPRIORPICFLAG +void DecApp::xFlushOutput( PicList *pcListPic, const int layerId, bool noOutputOfPriorPicsFlag) +#else void DecApp::xFlushOutput( PicList* pcListPic, const int layerId ) +#endif { if(!pcListPic || pcListPic->empty()) { @@ -676,13 +726,17 @@ void DecApp::xFlushOutput( PicList* pcListPic, const int layerId ) if ( pcPicTop->neededForOutput && pcPicBottom->neededForOutput && !(pcPicTop->getPOC()%2) && (pcPicBottom->getPOC() == pcPicTop->getPOC()+1) ) { - // write to file - if ( !m_reconFileName.empty() ) +#if JVET_S0078_NOOUTPUTPRIORPICFLAG + if (!noOutputOfPriorPicsFlag) { - const Window &conf = pcPicTop->cs->pps->getConformanceWindow(); - const bool isTff = pcPicTop->topField; +#endif + // write to file + if ( !m_reconFileName.empty() ) + { + const Window &conf = pcPicTop->cs->pps->getConformanceWindow(); + const bool isTff = pcPicTop->topField; - m_cVideoIOYuvReconFile[pcPicTop->layerId].write( pcPicTop->getRecoBuf(), pcPicBottom->getRecoBuf(), + m_cVideoIOYuvReconFile[pcPicTop->layerId].write( pcPicTop->getRecoBuf(), pcPicBottom->getRecoBuf(), m_outputColourSpaceConvert, false, // TODO: m_packedYUVMode, conf.getWindowLeftOffset() * SPS::getWinUnitX( pcPicTop->cs->sps->getChromaFormatIdc() ), @@ -690,9 +744,12 @@ void DecApp::xFlushOutput( PicList* pcListPic, const int layerId ) conf.getWindowTopOffset() * SPS::getWinUnitY( pcPicTop->cs->sps->getChromaFormatIdc() ), conf.getWindowBottomOffset() * SPS::getWinUnitY( pcPicTop->cs->sps->getChromaFormatIdc() ), NUM_CHROMA_FORMAT, isTff ); + } + writeLineToOutputLog(pcPicTop); + writeLineToOutputLog(pcPicBottom); +#if JVET_S0078_NOOUTPUTPRIORPICFLAG } - writeLineToOutputLog(pcPicTop); - writeLineToOutputLog(pcPicBottom); +#endif // update POC of display order m_iPOCLastDisplay = pcPicBottom->getPOC(); @@ -737,20 +794,23 @@ void DecApp::xFlushOutput( PicList* pcListPic, const int layerId ) if (pcPic->neededForOutput) { - // write to file - - if (!m_reconFileName.empty()) +#if JVET_S0078_NOOUTPUTPRIORPICFLAG + if (!noOutputOfPriorPicsFlag) { - const Window &conf = pcPic->getConformanceWindow(); - const SPS* sps = pcPic->cs->sps; - ChromaFormat chromaFormatIDC = sps->getChromaFormatIdc(); - if( m_upscaledOutput ) - { - m_cVideoIOYuvReconFile[pcPic->layerId].writeUpscaledPicture( *sps, *pcPic->cs->pps, pcPic->getRecoBuf(), m_outputColourSpaceConvert, m_packedYUVMode, m_upscaledOutput, NUM_CHROMA_FORMAT, m_bClipOutputVideoToRec709Range ); - } - else +#endif + // write to file + if (!m_reconFileName.empty()) { - m_cVideoIOYuvReconFile[pcPic->layerId].write( pcPic->getRecoBuf().get( COMPONENT_Y ).width, pcPic->getRecoBuf().get( COMPONENT_Y ).height, pcPic->getRecoBuf(), + const Window &conf = pcPic->getConformanceWindow(); + const SPS* sps = pcPic->cs->sps; + ChromaFormat chromaFormatIDC = sps->getChromaFormatIdc(); + if( m_upscaledOutput ) + { + m_cVideoIOYuvReconFile[pcPic->layerId].writeUpscaledPicture( *sps, *pcPic->cs->pps, pcPic->getRecoBuf(), m_outputColourSpaceConvert, m_packedYUVMode, m_upscaledOutput, NUM_CHROMA_FORMAT, m_bClipOutputVideoToRec709Range ); + } + else + { + m_cVideoIOYuvReconFile[pcPic->layerId].write( pcPic->getRecoBuf().get( COMPONENT_Y ).width, pcPic->getRecoBuf().get( COMPONENT_Y ).height, pcPic->getRecoBuf(), m_outputColourSpaceConvert, m_packedYUVMode, conf.getWindowLeftOffset() * SPS::getWinUnitX( chromaFormatIDC ), @@ -758,10 +818,12 @@ void DecApp::xFlushOutput( PicList* pcListPic, const int layerId ) conf.getWindowTopOffset() * SPS::getWinUnitY( chromaFormatIDC ), conf.getWindowBottomOffset() * SPS::getWinUnitY( chromaFormatIDC ), NUM_CHROMA_FORMAT, m_bClipOutputVideoToRec709Range ); - } + } + } + writeLineToOutputLog(pcPic); +#if JVET_S0078_NOOUTPUTPRIORPICFLAG } - writeLineToOutputLog(pcPic); - +#endif // update POC of display order m_iPOCLastDisplay = pcPic->getPOC(); diff --git a/source/App/DecoderApp/DecApp.h b/source/App/DecoderApp/DecApp.h index d5647fc2977e1221e472efc5bfaefbf5051e2547..11f88ed5ee82192c166f8b60967612d8d2b46705 100644 --- a/source/App/DecoderApp/DecApp.h +++ b/source/App/DecoderApp/DecApp.h @@ -85,7 +85,11 @@ private: void xCreateDecLib (); ///< create internal classes void xDestroyDecLib (); ///< destroy internal classes void xWriteOutput ( PicList* pcListPic , uint32_t tId); ///< write YUV to file +#if JVET_S0078_NOOUTPUTPRIORPICFLAG + void xFlushOutput( PicList *pcListPic, const int layerId = NOT_VALID, bool noOutputOfPriorPicsFlag = false ); ///< flush all remaining decoded pictures to file +#else void xFlushOutput( PicList* pcListPic, const int layerId = NOT_VALID ); ///< flush all remaining decoded pictures to file +#endif bool isNewPicture(ifstream *bitstreamFile, class InputByteStream *bytestream); ///< check if next NAL unit will be the first NAL unit from a new picture bool isNewAccessUnit(bool newPicture, ifstream *bitstreamFile, class InputByteStream *bytestream); ///< check if next NAL unit will be the first NAL unit from a new access unit diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h index 4a73aded09d06eaa9fb3105d205847186a8e8592..02acdee27334973df7f0faf9161f50a30ca2ebfd 100644 --- a/source/Lib/CommonLib/TypeDef.h +++ b/source/Lib/CommonLib/TypeDef.h @@ -51,6 +51,8 @@ #include <cassert> // clang-format off +#define JVET_S0078_NOOUTPUTPRIORPICFLAG 1 // JVET-S0078: Handling of NoOutputOfPriorPicsFlag in output process + //########### place macros to be removed in next cycle below this line ############### #define JVET_S0219_ASPECT1 1 // JVET-S0219 aspect1 : removal non-referred APS parameter set in the non-output layer. #define JVET_R0193 1 // JVET-R0193: signalling of the number of maximum sublayers used for inter-layer prediction for each layer diff --git a/source/Lib/DecoderLib/DecLib.h b/source/Lib/DecoderLib/DecLib.h index 1a9364287429359fe40b579bff50888b0193f147..b1ad6bb88e1f28ea9eb76b50f934c15ed87df3d8 100644 --- a/source/Lib/DecoderLib/DecLib.h +++ b/source/Lib/DecoderLib/DecLib.h @@ -230,6 +230,9 @@ public: void updatePrevGDRInSameLayer(); void updatePrevIRAPAndGDRSubpic(); +#if JVET_S0078_NOOUTPUTPRIORPICFLAG + bool getAudIrapOrGdrAuFlag() const { return m_audIrapOrGdrAuFlag; } +#endif bool getNoOutputPriorPicsFlag () const { return m_isNoOutputPriorPics; } void setNoOutputPriorPicsFlag (bool val) { m_isNoOutputPriorPics = val; } void setFirstSliceInPicture (bool val) { m_bFirstSliceInPicture = val; }