diff --git a/source/App/EncoderApp/EncApp.cpp b/source/App/EncoderApp/EncApp.cpp index c0f2a3c5e6c44a7d65d02876755ef06cd699272b..3bf06398eb079f23e22f33c22346461781352e97 100644 --- a/source/App/EncoderApp/EncApp.cpp +++ b/source/App/EncoderApp/EncApp.cpp @@ -904,6 +904,9 @@ void EncApp::rateStatsAccum(const AccessUnit& au, const std::vector<uint32_t>& a #endif case NAL_UNIT_SPS: case NAL_UNIT_PPS: +#if JVET_M0132 + case NAL_UNIT_APS: +#endif m_essentialBytes += *it_stats; break; default: @@ -920,7 +923,11 @@ void EncApp::printRateSummary() msg( DETAILS,"Bytes written to file: %u (%.3f kbps)\n", m_totalBytes, 0.008 * m_totalBytes / time ); if (m_summaryVerboseness > 0) { +#if JVET_M0132 + msg(DETAILS, "Bytes for SPS/PPS/APS/Slice (Incl. Annex B): %u (%.3f kbps)\n", m_essentialBytes, 0.008 * m_essentialBytes / time); +#else msg( DETAILS,"Bytes for SPS/PPS/Slice (Incl. Annex B): %u (%.3f kbps)\n", m_essentialBytes, 0.008 * m_essentialBytes / time ); +#endif } } diff --git a/source/App/Parcat/parcat.cpp b/source/App/Parcat/parcat.cpp index e6443eaf190ba9614243af216fa32a4572162f77..2480310f5264da07eb77ebf6dcbc33910cdebc75 100644 --- a/source/App/Parcat/parcat.cpp +++ b/source/App/Parcat/parcat.cpp @@ -221,6 +221,9 @@ const char * NALU_TYPE[] = #endif "SPS_NUT", "PPS_NUT", +#if JVET_M0132 + "APS_NUT", +#endif "AUD_NUT", "EOS_NUT", "EOB_NUT", diff --git a/source/Lib/CommonLib/CodingStructure.h b/source/Lib/CommonLib/CodingStructure.h index 6dace0a709eef2bb55ed451856bd234dc5b13bcb..69f265d051f1beab6b764084e55a27616a5b6bbf 100644 --- a/source/Lib/CommonLib/CodingStructure.h +++ b/source/Lib/CommonLib/CodingStructure.h @@ -101,6 +101,9 @@ public: bool isLossless; const SPS *sps; const PPS *pps; +#if JVET_M0132 + APS * aps; +#endif #if HEVC_VPS const VPS *vps; #endif diff --git a/source/Lib/CommonLib/CommonDef.h b/source/Lib/CommonLib/CommonDef.h index ea525d0bacfa5ef980ea5712ce36c9630b98ddfe..d00a9c0e68ac065b823410941fe1774e84b4eae5 100644 --- a/source/Lib/CommonLib/CommonDef.h +++ b/source/Lib/CommonLib/CommonDef.h @@ -192,6 +192,9 @@ static const int C2FLAG_NUMBER = 1; ///< maxi static const int MAX_NUM_VPS = 16; static const int MAX_NUM_SPS = 16; static const int MAX_NUM_PPS = 64; +#if JVET_M0132 +static const int MAX_NUM_APS = 32; //Currently APS ID has 5 bits +#endif static const int MLS_GRP_NUM = 1024; ///< Max number of coefficient groups, max(16, 256) diff --git a/source/Lib/CommonLib/Picture.cpp b/source/Lib/CommonLib/Picture.cpp index 2b8f46593b255789956d72dac002c75ba4d659a0..286810db34d7c2fbc60ffd3463b0ee56201a63fe 100644 --- a/source/Lib/CommonLib/Picture.cpp +++ b/source/Lib/CommonLib/Picture.cpp @@ -881,7 +881,11 @@ const CPelUnitBuf Picture::getRecoBuf(const UnitArea &unit) const { return g PelUnitBuf Picture::getRecoBuf() { return M_BUFS(scheduler.getSplitPicId(), PIC_RECONSTRUCTION); } const CPelUnitBuf Picture::getRecoBuf() const { return M_BUFS(scheduler.getSplitPicId(), PIC_RECONSTRUCTION); } +#if JVET_M0132 +void Picture::finalInit(const SPS& sps, const PPS& pps, APS& aps) +#else void Picture::finalInit( const SPS& sps, const PPS& pps ) +#endif { for( auto &sei : SEIs ) { @@ -917,6 +921,9 @@ void Picture::finalInit( const SPS& sps, const PPS& pps ) 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_M0132 + cs->aps = &aps; +#endif #if HEVC_VPS cs->vps = nullptr; #endif @@ -939,6 +946,9 @@ void Picture::allocateNewSlice() slices.push_back(new Slice); Slice& slice = *slices.back(); +#if JVET_M0132 + slice.setAPS(cs->aps); +#endif slice.setPPS( cs->pps); slice.setSPS( cs->sps); if(slices.size()>=2) @@ -952,11 +962,17 @@ Slice *Picture::swapSliceObject(Slice * p, uint32_t i) { p->setSPS(cs->sps); p->setPPS(cs->pps); +#if JVET_M0132 + p->setAPS(cs->aps); +#endif Slice * pTmp = slices[i]; slices[i] = p; pTmp->setSPS(0); pTmp->setPPS(0); +#if JVET_M0132 + pTmp->setAPS(0); +#endif return pTmp; } diff --git a/source/Lib/CommonLib/Picture.h b/source/Lib/CommonLib/Picture.h index fd014dcb58987ca7901c3504d16849588c259c18..e9c3a2c625141c8dc15f8e270bd00eee1d7c555d 100644 --- a/source/Lib/CommonLib/Picture.h +++ b/source/Lib/CommonLib/Picture.h @@ -233,7 +233,11 @@ struct Picture : public UnitArea const CPelUnitBuf getBuf(const UnitArea &unit, const PictureType &type) const; void extendPicBorder(); +#if JVET_M0132 + void finalInit(const SPS& sps, const PPS& pps, APS& aps); +#else void finalInit( const SPS& sps, const PPS& pps ); +#endif int getPOC() const { return poc; } void setBorderExtension( bool bFlag) { m_bIsBorderExtended = bFlag;} diff --git a/source/Lib/CommonLib/Rom.cpp b/source/Lib/CommonLib/Rom.cpp index 2e159e83d95600a8943011f128319f1e38e19250..76d36f27f48ebf3f75a89a67881600aba5bf372b 100644 --- a/source/Lib/CommonLib/Rom.cpp +++ b/source/Lib/CommonLib/Rom.cpp @@ -86,6 +86,9 @@ const char* nalUnitTypeToString(NalUnitType type) #endif case NAL_UNIT_SPS: return "SPS"; case NAL_UNIT_PPS: return "PPS"; +#if JVET_M0132 + case NAL_UNIT_APS: return "APS"; +#endif case NAL_UNIT_ACCESS_UNIT_DELIMITER: return "AUD"; case NAL_UNIT_EOS: return "EOS"; case NAL_UNIT_EOB: return "EOB"; diff --git a/source/Lib/CommonLib/Slice.cpp b/source/Lib/CommonLib/Slice.cpp index ec8f544c1703f9f5d6d9f9e69ff2b2c211b3ea29..4279429f0c8e4525dcdc70ebf6cae6d5c660cc00 100644 --- a/source/Lib/CommonLib/Slice.cpp +++ b/source/Lib/CommonLib/Slice.cpp @@ -138,6 +138,10 @@ Slice::Slice() , m_uiMaxBTSizeIChroma ( 0 ) , m_uiMaxTTSizeIChroma ( 0 ) , m_uiMaxBTSize ( 0 ) +#if JVET_M0132 +, m_apsId ( -1 ) +, m_aps (NULL) +#endif { for(uint32_t i=0; i<NUM_REF_PIC_LIST_01; i++) { @@ -1932,6 +1936,16 @@ PPS::~PPS() delete pcv; } +#if JVET_M0132 +APS::APS() +: m_APSId(0) +{ +} + +APS::~APS() +{ +} +#endif ReferencePictureSet::ReferencePictureSet() : m_numberOfPictures (0) , m_numberOfNegativePictures (0) @@ -2410,6 +2424,9 @@ ParameterSetManager::ParameterSetManager() : m_spsMap(MAX_NUM_SPS) #endif , m_ppsMap(MAX_NUM_PPS) +#if JVET_M0132 +, m_apsMap(MAX_NUM_APS) +#endif #if HEVC_VPS , m_activeVPSId(-1) #endif @@ -2520,6 +2537,28 @@ bool ParameterSetManager::activatePPS(int ppsId, bool isIRAP) return false; } +#if JVET_M0132 +bool ParameterSetManager::activateAPS(int apsId) +{ + APS *aps = m_apsMap.getPS(apsId); + if (aps) + { + m_apsMap.setActive(apsId); + return true; + } + else + { + msg(WARNING, "Warning: tried to activate non-existing APS."); + } + return false; +} + +template <> +void ParameterSetMap<APS>::setID(APS* parameterSet, const int psId) +{ + parameterSet->setAPSId(psId); +} +#endif template <> void ParameterSetMap<PPS>::setID(PPS* parameterSet, const int psId) { @@ -2645,6 +2684,13 @@ void xTracePPSHeader() DTRACE( g_trace_ctx, D_HEADER, "=========== Picture Parameter Set ===========\n" ); } +#if JVET_M0132 +void xTraceAPSHeader() +{ + DTRACE(g_trace_ctx, D_HEADER, "=========== Adaptation Parameter Set ===========\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 aed91d3018085d9b0673273f51819a524a1a1676..00133d319b2883453a4f73f11d12ba18854187f1 100644 --- a/source/Lib/CommonLib/Slice.h +++ b/source/Lib/CommonLib/Slice.h @@ -1563,6 +1563,24 @@ public: PPSRExt& getPpsRangeExtension() { return m_ppsRangeExtension; } }; +#if JVET_M0132 +class APS +{ +private: + int m_APSId; // adaptation_parameter_set_id + AlfSliceParam m_alfAPSParam; + +public: + APS(); + virtual ~APS(); + + int getAPSId() const { return m_APSId; } + void setAPSId(int i) { m_APSId = i; } + + void setAlfAPSParam(AlfSliceParam& alfAPSParam) { m_alfAPSParam = alfAPSParam; } + AlfSliceParam getAlfAPSParam() { return m_alfAPSParam; } +}; +#endif struct WPScalingParam { // Explicit weighted prediction parameters parsed in slice header, @@ -1719,6 +1737,10 @@ private: uint32_t m_uiMaxTTSizeIChroma; uint32_t m_uiMaxBTSize; +#if JVET_M0132 + int m_apsId; + APS* m_aps; +#endif AlfSliceParam m_alfSliceParam; #if JVET_M0427_INLOOP_RESHAPER SliceReshapeInfo m_sliceReshapeInfo; @@ -1740,6 +1762,12 @@ public: void setPPSId( int PPSId ) { m_iPPSId = PPSId; } int getPPSId() const { return m_iPPSId; } +#if JVET_M0132 + void setAPS(APS* aps) { m_aps = aps; m_apsId = (aps) ? aps->getAPSId() : -1; } + APS* getAPS() { return m_aps; } + void setAPSId(int apsId) { m_apsId = apsId; } + int getAPSId() const { return m_apsId; } +#endif void setPicOutputFlag( bool b ) { m_PicOutputFlag = b; } bool getPicOutputFlag() const { return m_PicOutputFlag; } void setSaoEnabledFlag(ChannelType chType, bool s) {m_saoEnabledFlag[chType] =s; } @@ -2197,6 +2225,14 @@ public: //! \returns true, if activation is successful bool activatePPS(int ppsId, bool isIRAP); +#if JVET_M0132 + void storeAPS(APS *aps, const std::vector<uint8_t> &naluData) { m_apsMap.storePS(aps->getAPSId(), aps, &naluData); }; + APS* getAPS(int apsId) { return m_apsMap.getPS(apsId); }; + bool getAPSChangedFlag(int apsId) const { return m_apsMap.getChangedFlag(apsId); } + void clearAPSChangedFlag(int apsId) { m_apsMap.clearChangedFlag(apsId); } + APS* getFirstAPS() { return m_apsMap.getFirstPS(); }; + bool activateAPS(int apsId); +#endif #if HEVC_VPS const VPS* getActiveVPS()const { return m_vpsMap.getPS(m_activeVPSId); }; #endif @@ -2208,6 +2244,9 @@ protected: #endif ParameterSetMap<SPS> m_spsMap; ParameterSetMap<PPS> m_ppsMap; +#if JVET_M0132 + ParameterSetMap<APS> m_apsMap; +#endif #if HEVC_VPS int m_activeVPSId; // -1 for nothing active @@ -2302,6 +2341,9 @@ void xTraceVPSHeader(); #endif void xTraceSPSHeader(); void xTracePPSHeader(); +#if JVET_M0132 +void xTraceAPSHeader(); +#endif void xTraceSliceHeader(); void xTraceAccessUnitDelimiter(); #endif diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h index e91a15bd65e45e43c14e26cea62bf94aa6f2fd80..64da37c58ff250291d083dadef6877493bc6f2f9 100644 --- a/source/Lib/CommonLib/TypeDef.h +++ b/source/Lib/CommonLib/TypeDef.h @@ -332,6 +332,7 @@ typedef std::pair<int, int> TrCost; #define X0038_LAMBDA_FROM_QP_CAPABILITY 1 ///< This approach derives lambda from QP+QPoffset+QPoffset2. QPoffset2 is derived from QP+QPoffset using a linear model that is clipped between 0 and 3. // To use this capability enable config parameter LambdaFromQpEnable +#define JVET_M0132 1 // ==================================================================================================================== // Tool Switches // ==================================================================================================================== @@ -977,6 +978,9 @@ enum NalUnitType #endif NAL_UNIT_SPS, // 33 NAL_UNIT_PPS, // 34 +#if JVET_M0132 + NAL_UNIT_APS, //NAL unit type number needs to be reaaranged. +#endif NAL_UNIT_ACCESS_UNIT_DELIMITER, // 35 NAL_UNIT_EOS, // 36 NAL_UNIT_EOB, // 37 diff --git a/source/Lib/DecoderLib/DecLib.cpp b/source/Lib/DecoderLib/DecLib.cpp index aaaf094cb4e429137a02681275fd9db31e812f75..977b832307c0edcc3c0c9ef326dc496c4ed89a04 100644 --- a/source/Lib/DecoderLib/DecLib.cpp +++ b/source/Lib/DecoderLib/DecLib.cpp @@ -738,6 +738,13 @@ void DecLib::xActivateParameterSets() { if (m_bFirstSliceInPicture) { +#if JVET_M0132 + APS *aps = m_parameterSetManager.getAPS(m_apcSlicePilot->getAPSId()); // this is a temporary APS object. Do not store this value + if (m_apcSlicePilot->getAPSId() != -1) + { + CHECK(aps == 0, "No APS present"); + } +#endif const PPS *pps = m_parameterSetManager.getPPS(m_apcSlicePilot->getPPSId()); // this is a temporary PPS object. Do not store this value CHECK(pps == 0, "No PPS present"); @@ -751,6 +758,11 @@ void DecLib::xActivateParameterSets() m_parameterSetManager.clearSPSChangedFlag(sps->getSPSId()); m_parameterSetManager.clearPPSChangedFlag(pps->getPPSId()); +#if JVET_M0132 //Hendry + if (aps != 0) + m_parameterSetManager.clearAPSChangedFlag(aps->getAPSId()); +#endif + if (false == m_parameterSetManager.activatePPS(m_apcSlicePilot->getPPSId(),m_apcSlicePilot->isIRAP())) { THROW("Parameter set activation failed!"); @@ -770,7 +782,11 @@ void DecLib::xActivateParameterSets() m_apcSlicePilot->applyReferencePictureSet(m_cListPic, m_apcSlicePilot->getRPS()); +#if JVET_M0132 + m_pcPic->finalInit(*sps, *pps, *aps); +#else m_pcPic->finalInit( *sps, *pps ); +#endif m_pcPic->createTempBuffers( m_pcPic->cs->pps->pcv->maxCUWidth ); m_pcPic->cs->createCoeffs(); @@ -784,6 +800,9 @@ void DecLib::xActivateParameterSets() Slice *pSlice = m_pcPic->slices[m_uiSliceSegmentIdx]; // Update the PPS and SPS pointers with the ones of the picture. +#if JVET_M0132 + aps= pSlice->getAPS(); +#endif pps=pSlice->getPPS(); sps=pSlice->getSPS(); @@ -791,6 +810,9 @@ void DecLib::xActivateParameterSets() m_pcPic->cs->slice = pSlice; m_pcPic->cs->sps = sps; m_pcPic->cs->pps = pps; +#if JVET_M0132 + m_pcPic->cs->aps = aps; +#endif #if HEVC_VPS m_pcPic->cs->vps = pSlice->getVPS(); #endif @@ -866,11 +888,16 @@ void DecLib::xActivateParameterSets() const SPS *sps = pSlice->getSPS(); const PPS *pps = pSlice->getPPS(); - +#if JVET_M0132 + APS *aps = pSlice->getAPS(); +#endif // fix Parameter Sets, now that we have the real slice m_pcPic->cs->slice = pSlice; m_pcPic->cs->sps = sps; m_pcPic->cs->pps = pps; +#if JVET_M0132 + m_pcPic->cs->aps = aps; +#endif #if HEVC_VPS m_pcPic->cs->vps = pSlice->getVPS(); #endif @@ -885,6 +912,12 @@ void DecLib::xActivateParameterSets() { EXIT("Error - a new PPS has been decoded while processing a picture"); } +#if JVET_M0132 + if (aps && m_parameterSetManager.getAPSChangedFlag(aps->getAPSId())) + { + EXIT("Error - a new APS has been decoded while processing a picture"); + } +#endif xParsePrefixSEImessages(); @@ -1049,6 +1082,13 @@ bool DecLib::xDecodeSlice(InputNALUnit &nalu, int &iSkipFrame, int iPOCLastDispl int iMaxPOClsb = 1 << sps->getBitsForPOC(); m_apcSlicePilot->setPOC( m_apcSlicePilot->getPOC() & (iMaxPOClsb - 1) ); xUpdatePreviousTid0POC(m_apcSlicePilot); +#if JVET_M0132 + if (m_apcSlicePilot->getAPSId() != -1) + { + APS *aps = m_parameterSetManager.getAPS(m_apcSlicePilot->getAPSId()); + CHECK(aps == 0, "No APS present"); + } +#endif } // Skip pictures due to random access @@ -1403,6 +1443,15 @@ void DecLib::xDecodePPS( InputNALUnit& nalu ) m_parameterSetManager.storePPS( pps, nalu.getBitstream().getFifo() ); } +#if JVET_M0132 +void DecLib::xDecodeAPS(InputNALUnit& nalu) +{ + APS* aps = new APS(); + m_HLSReader.setBitstream(&nalu.getBitstream()); + m_HLSReader.parseAPS(aps); + m_parameterSetManager.storeAPS(aps, nalu.getBitstream().getFifo()); +} +#endif bool DecLib::decode(InputNALUnit& nalu, int& iSkipFrame, int& iPOCLastDisplay) { bool ret; @@ -1428,6 +1477,11 @@ bool DecLib::decode(InputNALUnit& nalu, int& iSkipFrame, int& iPOCLastDisplay) case NAL_UNIT_PPS: xDecodePPS( nalu ); return false; +#if JVET_M0132 + case NAL_UNIT_APS: + xDecodeAPS(nalu); + return false; +#endif case NAL_UNIT_PREFIX_SEI: // Buffer up prefix SEI messages until SPS of associated VCL is known. diff --git a/source/Lib/DecoderLib/DecLib.h b/source/Lib/DecoderLib/DecLib.h index ae94530450e6a9402275be64a23afaf6454dd2ba..9eea5fb986d367da97528a3547482fceaa4e5b68 100644 --- a/source/Lib/DecoderLib/DecLib.h +++ b/source/Lib/DecoderLib/DecLib.h @@ -184,6 +184,9 @@ protected: #endif void xDecodeSPS( InputNALUnit& nalu ); void xDecodePPS( InputNALUnit& nalu ); +#if JVET_M0132 + void xDecodeAPS(InputNALUnit& nalu); +#endif void xUpdatePreviousTid0POC( Slice *pSlice ) { if ((pSlice->getTLayer()==0) && (pSlice->isReferenceNalu() && (pSlice->getNalUnitType()!=NAL_UNIT_CODED_SLICE_RASL_R)&& (pSlice->getNalUnitType()!=NAL_UNIT_CODED_SLICE_RADL_R))) { m_prevTid0POC=pSlice->getPOC(); } } void xParsePrefixSEImessages(); void xParsePrefixSEIsForUnknownVCLNal(); diff --git a/source/Lib/DecoderLib/DecSlice.cpp b/source/Lib/DecoderLib/DecSlice.cpp index fe569ddae0d692b105b2783bfa425125bd911e83..0ffac78e941435d56b0731ab19c2a50981553872 100644 --- a/source/Lib/DecoderLib/DecSlice.cpp +++ b/source/Lib/DecoderLib/DecSlice.cpp @@ -91,6 +91,9 @@ void DecSlice::decompressSlice( Slice* slice, InputBitstream* bitstream ) cs.slice = slice; cs.sps = sps; cs.pps = slice->getPPS(); +#if JVET_M0132 + cs.aps = slice->getAPS(); +#endif #if HEVC_VPS cs.vps = slice->getVPS(); #endif diff --git a/source/Lib/DecoderLib/VLCReader.cpp b/source/Lib/DecoderLib/VLCReader.cpp index 32afc7e3f1bb73bc860be7b9be7b07e00d662689..99118d9270cd188d238d9689a539bc97797d3a45 100644 --- a/source/Lib/DecoderLib/VLCReader.cpp +++ b/source/Lib/DecoderLib/VLCReader.cpp @@ -607,6 +607,52 @@ void HLSyntaxReader::parsePPS( PPS* pcPPS ) xReadRbspTrailingBits(); } +#if JVET_M0132 +void HLSyntaxReader::parseAPS(APS* aps) +{ +#if ENABLE_TRACING + xTraceAPSHeader(); +#endif + + uint32_t code; + + READ_CODE(5, code, "adaptation_parameter_set_id"); + aps->setAPSId(code); + + AlfSliceParam param = aps->getAlfAPSParam(); + param.enabledFlag[COMPONENT_Y] = true; + + int alfChromaIdc = truncatedUnaryEqProb(3); //alf_chroma_idc + param.enabledFlag[COMPONENT_Cb] = alfChromaIdc >> 1; + param.enabledFlag[COMPONENT_Cr] = alfChromaIdc & 1; + + xReadTruncBinCode(code, MAX_NUM_ALF_CLASSES); //number_of_filters_minus1 + param.numLumaFilters = code + 1; + if (param.numLumaFilters > 1) + { + for (int i = 0; i < MAX_NUM_ALF_CLASSES; i++) + { + xReadTruncBinCode(code, param.numLumaFilters); + param.filterCoeffDeltaIdx[i] = code; + } + } + else + { + memset(param.filterCoeffDeltaIdx, 0, sizeof(param.filterCoeffDeltaIdx)); + } + + alfFilter(param, false); + + if (alfChromaIdc) + { + alfFilter(param, true); + } + aps->setAlfAPSParam(param); + + xReadRbspTrailingBits(); +} +#endif + void HLSyntaxReader::parseVUI(VUI* pcVUI, SPS *pcSPS) { #if ENABLE_TRACING @@ -1601,7 +1647,26 @@ void HLSyntaxReader::parseSliceHeader (Slice* pcSlice, ParameterSetManager *para if( sps->getALFEnabledFlag() ) { +#if JVET_M0132 + READ_FLAG(uiCode, "tile_group_alf_enabled_flag"); + if (uiCode) + { + READ_CODE(5, uiCode, "tile_group_aps_id"); + pcSlice->setAPSId(uiCode); + pcSlice->setAPS(parameterSetManager->getAPS(uiCode)); + AlfSliceParam alfParam = pcSlice->getAPS()->getAlfAPSParam(); + pcSlice->setAlfSliceParam(alfParam); + pcSlice->getAlfSliceParam().enabledFlag[COMPONENT_Y] = true; + } + else + { + pcSlice->getAlfSliceParam().enabledFlag[COMPONENT_Y] = false; + pcSlice->getAlfSliceParam().enabledFlag[COMPONENT_Cb] = false; + pcSlice->getAlfSliceParam().enabledFlag[COMPONENT_Cr] = false; + } +#else alf( pcSlice->getAlfSliceParam() ); +#endif } if (pcSlice->getIdrPicFlag()) @@ -2426,6 +2491,7 @@ bool HLSyntaxReader::xMoreRbspData() return (cnt>0); } +#if !JVET_M0132 void HLSyntaxReader::alf( AlfSliceParam& alfSliceParam ) { uint32_t code; @@ -2464,6 +2530,7 @@ void HLSyntaxReader::alf( AlfSliceParam& alfSliceParam ) alfFilter( alfSliceParam, true ); } } +#endif int HLSyntaxReader::alfGolombDecode( const int k ) { diff --git a/source/Lib/DecoderLib/VLCReader.h b/source/Lib/DecoderLib/VLCReader.h index b8fa2d66a90a105247e1f3e3cc17bfe53e499de4..a7d47899b2511823fd7e0e01dcad6e99b4236160 100644 --- a/source/Lib/DecoderLib/VLCReader.h +++ b/source/Lib/DecoderLib/VLCReader.h @@ -149,6 +149,9 @@ public: #endif void parseSPS ( SPS* pcSPS ); void parsePPS ( PPS* pcPPS ); +#if JVET_M0132 + void parseAPS ( APS* pcAPS); +#endif void parseVUI ( VUI* pcVUI, SPS* pcSPS ); void parsePTL ( PTL *rpcPTL, bool profilePresentFlag, int maxNumSubLayersMinus1 ); void parseProfileTier ( ProfileTierLevel *ptl, const bool bIsSubLayer ); @@ -165,7 +168,9 @@ public: #if JVET_M0427_INLOOP_RESHAPER void parseReshaper ( SliceReshapeInfo& sliceReshaperInfo, const SPS* pcSPS, const bool isIntra ); #endif +#if !JVET_M0132 void alf( AlfSliceParam& alfSliceParam ); +#endif void alfFilter( AlfSliceParam& alfSliceParam, const bool isChroma ); private: diff --git a/source/Lib/EncoderLib/EncGOP.cpp b/source/Lib/EncoderLib/EncGOP.cpp index ca313995e1f63b8c4474f1cd1bfecef584eb6f0a..850f0148f875035e4d7e8ae6acb55d545d1fd6eb 100644 --- a/source/Lib/EncoderLib/EncGOP.cpp +++ b/source/Lib/EncoderLib/EncGOP.cpp @@ -237,6 +237,16 @@ int EncGOP::xWritePPS (AccessUnit &accessUnit, const PPS *pps) return (int)(accessUnit.back()->m_nalUnitData.str().size()) * 8; } +#if JVET_M0132 +int EncGOP::xWriteAPS(AccessUnit &accessUnit, APS *aps) +{ + OutputNALUnit nalu(NAL_UNIT_APS); + m_HLSWriter->setBitstream(&nalu.m_Bitstream); + m_HLSWriter->codeAPS(aps); + accessUnit.push_back(new NALUnitEBSP(nalu)); + return (int)(accessUnit.back()->m_nalUnitData.str().size()) * 8; +} +#endif int EncGOP::xWriteParameterSets (AccessUnit &accessUnit, Slice *slice, const bool bSeqFirst) { @@ -2549,6 +2559,14 @@ void EncGOP::compressGOP( int iPOCLast, int iNumPicRcvd, PicList& rcListPic, { xWriteAccessUnitDelimiter(accessUnit, pcSlice); } +#if JVET_M0132 + if (pcSlice->getSPS()->getALFEnabledFlag() && pcSlice->getAlfSliceParam().enabledFlag[COMPONENT_Y]) + { + pcSlice->setAPSId(pcSlice->getAPS()->getAPSId()); + pcSlice->getAPS()->setAlfAPSParam(pcSlice->getAlfSliceParam()); + actualTotalBits += xWriteAPS(accessUnit, pcSlice->getAPS()); + } +#endif // reset presence of BP SEI indication m_bufferingPeriodSEIPresentInAU = false; diff --git a/source/Lib/EncoderLib/EncGOP.h b/source/Lib/EncoderLib/EncGOP.h index e2c11c170105b077021b497b661030ac06930798..975609f7b29f92a5dded3f48bada224ae0565a0e 100644 --- a/source/Lib/EncoderLib/EncGOP.h +++ b/source/Lib/EncoderLib/EncGOP.h @@ -281,6 +281,9 @@ protected: #endif int xWriteSPS (AccessUnit &accessUnit, const SPS *sps); int xWritePPS (AccessUnit &accessUnit, const PPS *pps); +#if JVET_M0132 + int xWriteAPS(AccessUnit &accessUnit, APS *aps); +#endif int xWriteParameterSets (AccessUnit &accessUnit, Slice *slice, const bool bSeqFirst); void applyDeblockingFilterMetric( Picture* pcPic, uint32_t uiNumSlices ); diff --git a/source/Lib/EncoderLib/EncLib.cpp b/source/Lib/EncoderLib/EncLib.cpp index e62fedc1c3a0b48504df6fe83c39b7be27aa749c..51b54e0632ff493eaf0625e3af963efe2c0aea5c 100644 --- a/source/Lib/EncoderLib/EncLib.cpp +++ b/source/Lib/EncoderLib/EncLib.cpp @@ -60,6 +60,9 @@ EncLib::EncLib() : m_spsMap( MAX_NUM_SPS ) , m_ppsMap( MAX_NUM_PPS ) +#if JVET_M0132 + , m_apsMap( MAX_NUM_APS ) +#endif , m_AUWriterIf( nullptr ) #if JVET_J0090_MEMORY_BANDWITH_MEASURE , m_cacheModel() @@ -214,6 +217,9 @@ void EncLib::init( bool isFieldCoding, AUWriterIf* auWriterIf ) SPS &sps0=*(m_spsMap.allocatePS(0)); // NOTE: implementations that use more than 1 SPS need to be aware of activation issues. PPS &pps0=*(m_ppsMap.allocatePS(0)); +#if JVET_M0132 + APS &aps0=*(m_apsMap.allocatePS(0)); +#endif // initialize SPS xInitSPS(sps0); @@ -251,6 +257,10 @@ void EncLib::init( bool isFieldCoding, AUWriterIf* auWriterIf ) // initialize PPS xInitPPS(pps0, sps0); +#if JVET_M0132 + // initialize APS + xInitAPS(aps0); +#endif xInitRPS(sps0, isFieldCoding); #if ER_CHROMA_QP_WCG_PPS @@ -385,7 +395,11 @@ void EncLib::init( bool isFieldCoding, AUWriterIf* auWriterIf ) Picture *picBg = new Picture; picBg->create(sps0.getChromaFormatIdc(), Size(sps0.getPicWidthInLumaSamples(), sps0.getPicHeightInLumaSamples()), sps0.getMaxCUWidth(), sps0.getMaxCUWidth() + 16, false); picBg->getRecoBuf().fill(0); +#if JVET_M0132 + picBg->finalInit(sps0, pps0, aps0); +#else picBg->finalInit(sps0, pps0); +#endif picBg->allocateNewSlice(); picBg->createSpliceIdx(pps0.pcv->sizeInCtus); m_cGOPEncoder.setPicBg(picBg); @@ -536,7 +550,12 @@ 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_M0132 + APS *aps = m_apsMap.getPS(0); + picCurr->finalInit(*sps, *pps, *aps); +#else picCurr->finalInit(*sps, *pps); +#endif picCurr->poc = m_iPOCLast - 1; m_iPOCLast -= 2; if (getUseAdaptiveQP()) @@ -587,7 +606,12 @@ void EncLib::encode( bool flush, PelStorage* pcPicYuvOrg, PelStorage* cPicYuvTru pcPicCurr->M_BUFS( 0, PIC_TRUE_ORIGINAL).swap(*cPicYuvTrueOrg); #endif +#if JVET_M0132 + APS *pAPS = m_apsMap.getPS(0); + pcPicCurr->finalInit(*pSPS, *pPPS, *pAPS); +#else pcPicCurr->finalInit( *pSPS, *pPPS ); +#endif } pcPicCurr->poc = m_iPOCLast; @@ -682,7 +706,12 @@ 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_M0132 + APS *pAPS = m_apsMap.getPS(0); + pcField->finalInit(*pSPS, *pPPS, *pAPS); +#else pcField->finalInit( *pSPS, *pPPS ); +#endif } pcField->poc = m_iPOCLast; @@ -1487,6 +1516,12 @@ void EncLib::xInitPPS(PPS &pps, const SPS &sps) pps.pcv = new PreCalcValues( sps, pps, true ); } +#if JVET_M0132 +void EncLib::xInitAPS(APS &aps) +{ + //Do nothing now +} +#endif //Function for initializing m_RPSList, a list of ReferencePictureSet, based on the GOPEntry objects read from the config file. void EncLib::xInitRPS(SPS &sps, bool isFieldCoding) { @@ -1859,6 +1894,14 @@ void EncLib::setParamSetChanged(int spsId, int ppsId) m_spsMap.setChangedFlag(spsId); } #endif +#if JVET_M0132 +bool EncLib::APSNeedsWriting(int apsId) +{ + bool isChanged = m_apsMap.getChangedFlag(apsId); + m_apsMap.clearChangedFlag(apsId); + return isChanged; +} +#endif bool EncLib::PPSNeedsWriting(int ppsId) { diff --git a/source/Lib/EncoderLib/EncLib.h b/source/Lib/EncoderLib/EncLib.h index d143e79b28d3d2554017022d95bfe44d2e293f89..9d70ff9db60e626c5eea678933a4bde13fd6eb84 100644 --- a/source/Lib/EncoderLib/EncLib.h +++ b/source/Lib/EncoderLib/EncLib.h @@ -116,6 +116,9 @@ private: // SPS 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 +#if JVET_M0132 + ParameterSetMap<APS> m_apsMap; ///< APS. This is the base value. This is copied to PicSym +#endif // RD cost computation #if ENABLE_SPLIT_PARALLELISM || ENABLE_WPP_PARALLELISM RdCost *m_cRdCost; ///< RD cost computation class @@ -150,6 +153,9 @@ protected: #endif void xInitSPS (SPS &sps); ///< initialize SPS from encoder options void xInitPPS (PPS &pps, const SPS &sps); ///< initialize PPS from encoder options +#if JVET_M0132 + void xInitAPS (APS &aps); ///< initialize APS from encoder options +#endif #if HEVC_USE_SCALING_LISTS void xInitScalingLists (SPS &sps, PPS &pps); ///< initialize scaling lists #endif @@ -219,10 +225,16 @@ public: #if JCTVC_Y0038_PARAMS void setParamSetChanged(int spsId, int ppsId); +#endif +#if JVET_M0132 + bool APSNeedsWriting(int apsId); #endif bool PPSNeedsWriting(int ppsId); bool SPSNeedsWriting(int spsId); const PPS* getPPS( int Id ) { return m_ppsMap.getPS( Id); } +#if JVET_M0132 + const APS* getAPS(int Id) { return m_apsMap.getPS(Id); } +#endif #if ENABLE_SPLIT_PARALLELISM || ENABLE_WPP_PARALLELISM void setNumCuEncStacks( int n ) { m_numCuEncStacks = n; } diff --git a/source/Lib/EncoderLib/VLCWriter.cpp b/source/Lib/EncoderLib/VLCWriter.cpp index 9b94251dfa2f724c4d71ebfda9beb330f8d0d598..1affff3383d009e4173123cbd7142a8fc0522985 100644 --- a/source/Lib/EncoderLib/VLCWriter.cpp +++ b/source/Lib/EncoderLib/VLCWriter.cpp @@ -365,6 +365,37 @@ void HLSWriter::codePPS( const PPS* pcPPS ) xWriteRbspTrailingBits(); } +#if JVET_M0132 +void HLSWriter::codeAPS( APS* pcAPS) +{ +#if ENABLE_TRACING + xTraceAPSHeader(); +#endif + + AlfSliceParam param = pcAPS->getAlfAPSParam(); + WRITE_CODE(pcAPS->getAPSId(), 5, "adaptation_parameter_set_id"); + + const int alfChromaIdc = param.enabledFlag[COMPONENT_Cb] * 2 + param.enabledFlag[COMPONENT_Cr]; + truncatedUnaryEqProb(alfChromaIdc, 3); // alf_chroma_idc + + xWriteTruncBinCode(param.numLumaFilters - 1, MAX_NUM_ALF_CLASSES); //number_of_filters_minus1 + if (param.numLumaFilters > 1) + { + for (int i = 0; i < MAX_NUM_ALF_CLASSES; i++) + { + xWriteTruncBinCode((uint32_t)param.filterCoeffDeltaIdx[i], param.numLumaFilters); //filter_coeff_delta[i] + } + } + + alfFilter(param, false); + + if (alfChromaIdc) + { + alfFilter(param, true); + } + xWriteRbspTrailingBits(); +} +#endif void HLSWriter::codeVUI( const VUI *pcVUI, const SPS* pcSPS ) { #if ENABLE_TRACING @@ -1179,7 +1210,15 @@ void HLSWriter::codeSliceHeader ( Slice* pcSlice ) if( pcSlice->getSPS()->getALFEnabledFlag() ) { +#if JVET_M0132 + WRITE_FLAG(pcSlice->getAlfSliceParam().enabledFlag[COMPONENT_Y], "tile_group_alf_enabled_flag"); + if (pcSlice->getAlfSliceParam().enabledFlag[COMPONENT_Y]) + { + WRITE_CODE(pcSlice->getAPSId(), 5, "tile_group_aps_id"); + } +#else alf( pcSlice->getAlfSliceParam() ); +#endif } //check if numrefidxes match the defaults. If not, override @@ -1729,6 +1768,7 @@ bool HLSWriter::xFindMatchingLTRP(Slice* pcSlice, uint32_t *ltrpsIndex, int ltrp return false; } +#if !JVET_M0132 void HLSWriter::alf( const AlfSliceParam& alfSliceParam ) { WRITE_FLAG( alfSliceParam.enabledFlag[COMPONENT_Y], "tile_group_alf_enabled_flag" ); @@ -1756,6 +1796,7 @@ void HLSWriter::alf( const AlfSliceParam& alfSliceParam ) alfFilter( alfSliceParam, true ); } } +#endif void HLSWriter::alfGolombEncode( int coeff, int k ) { diff --git a/source/Lib/EncoderLib/VLCWriter.h b/source/Lib/EncoderLib/VLCWriter.h index b3866e8ab3a78c22f66574ec4eda016167dc362d..e1e3fd853e7c866b0306e94b1cf4785f03198bd2 100644 --- a/source/Lib/EncoderLib/VLCWriter.h +++ b/source/Lib/EncoderLib/VLCWriter.h @@ -122,6 +122,9 @@ public: void codeVUI ( const VUI *pcVUI, const SPS* pcSPS ); void codeSPS ( const SPS* pcSPS ); void codePPS ( const PPS* pcPPS ); +#if JVET_M0132 + void codeAPS ( APS* pcAPS); +#endif #if HEVC_VPS void codeVPS ( const VPS* pcVPS ); #endif @@ -136,7 +139,9 @@ public: void codeScalingList ( const ScalingList &scalingList ); #endif +#if !JVET_M0132 void alf( const AlfSliceParam& alfSliceParam ); +#endif void alfFilter( const AlfSliceParam& alfSliceParam, const bool isChroma ); private: