diff --git a/source/App/EncoderApp/EncApp.cpp b/source/App/EncoderApp/EncApp.cpp index 615698d3e83724084c6ed690053b769605a26d53..b9604752aeb07d6c5e2c729485cee3357eaaa465 100644 --- a/source/App/EncoderApp/EncApp.cpp +++ b/source/App/EncoderApp/EncApp.cpp @@ -1925,20 +1925,21 @@ void EncApp::xWriteOutput(int numEncoded, std::list<PelUnitBuf *> &recBufList) int ppsID = layerId; if ((m_gopBasedRPREnabledFlag && (m_cEncLib.getBaseQP() >= m_cEncLib.getGOPBasedRPRQPThreshold())) || m_rprFunctionalityTestingEnabledFlag) { - const PPS& pps1 = *m_cEncLib.getPPS(ENC_PPS_ID_RPR); - const PPS& pps2 = *m_cEncLib.getPPS(ENC_PPS_ID_RPR2); - const PPS& pps3 = *m_cEncLib.getPPS(ENC_PPS_ID_RPR3); + const PPS& pps1 = *m_cEncLib.getPPS(ENC_PPS_ID_RPR + layerId); + const PPS& pps2 = *m_cEncLib.getPPS(ENC_PPS_ID_RPR2 + layerId); + const PPS& pps3 = *m_cEncLib.getPPS(ENC_PPS_ID_RPR3 + layerId); + if (pps1.getPicWidthInLumaSamples() == pcPicYuvRec->get(COMPONENT_Y).width && pps1.getPicHeightInLumaSamples() == pcPicYuvRec->get(COMPONENT_Y).height) { - ppsID = ENC_PPS_ID_RPR; + ppsID = ENC_PPS_ID_RPR + layerId; } else if (pps2.getPicWidthInLumaSamples() == pcPicYuvRec->get(COMPONENT_Y).width && pps2.getPicHeightInLumaSamples() == pcPicYuvRec->get(COMPONENT_Y).height) { - ppsID = ENC_PPS_ID_RPR2; + ppsID = ENC_PPS_ID_RPR2 + layerId; } else if (pps3.getPicWidthInLumaSamples() == pcPicYuvRec->get(COMPONENT_Y).width && pps3.getPicHeightInLumaSamples() == pcPicYuvRec->get(COMPONENT_Y).height) { - ppsID = ENC_PPS_ID_RPR3; + ppsID = ENC_PPS_ID_RPR3 + layerId; } else { @@ -1947,7 +1948,7 @@ void EncApp::xWriteOutput(int numEncoded, std::list<PelUnitBuf *> &recBufList) } else { - ppsID = (sps.getMaxPicWidthInLumaSamples() != pcPicYuvRec->get(COMPONENT_Y).width || sps.getMaxPicHeightInLumaSamples() != pcPicYuvRec->get(COMPONENT_Y).height) ? ENC_PPS_ID_RPR : layerId; + ppsID = (sps.getMaxPicWidthInLumaSamples() != pcPicYuvRec->get(COMPONENT_Y).width || sps.getMaxPicHeightInLumaSamples() != pcPicYuvRec->get(COMPONENT_Y).height) ? (ENC_PPS_ID_RPR + layerId) : layerId; } const PPS& pps = *m_cEncLib.getPPS(ppsID); if( m_cEncLib.isResChangeInClvsEnabled() && m_cEncLib.getUpscaledOutput() ) diff --git a/source/App/EncoderApp/EncAppCfg.cpp b/source/App/EncoderApp/EncAppCfg.cpp index 42e9bc5b052103be49e3c2f07266686a1245318f..4034a7076fb35eae95e30e97fdd93e1720c8904d 100644 --- a/source/App/EncoderApp/EncAppCfg.cpp +++ b/source/App/EncoderApp/EncAppCfg.cpp @@ -2380,6 +2380,25 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] ) } } + if ((m_maxLayers>2) && m_gopBasedRPREnabledFlag) + { + msg(ERROR, "*************************************************************************\n"); + msg(ERROR, "* GOP based RPR is only implemented for max two layers *\n"); + msg(ERROR, "*************************************************************************\n"); + m_gopBasedRPREnabledFlag = false; + m_scalingRatioHor = 1.0; + m_scalingRatioVer = 1.0; + m_resChangeInClvsEnabled = m_scalingRatioHor != 1.0 || m_scalingRatioVer != 1.0 || m_gopBasedRPREnabledFlag || m_rprFunctionalityTestingEnabledFlag; + } + if ((m_maxLayers > 2) && m_rprFunctionalityTestingEnabledFlag) + { + msg(ERROR, "*************************************************************************\n"); + msg(ERROR, "* RPR functionality testing is only implemented for max two layers *\n"); + msg(ERROR, "*************************************************************************\n"); + m_rprFunctionalityTestingEnabledFlag = false; + m_resChangeInClvsEnabled = m_scalingRatioHor != 1.0 || m_scalingRatioVer != 1.0 || m_gopBasedRPREnabledFlag || m_rprFunctionalityTestingEnabledFlag; + } + if (m_costMode != COST_LOSSLESS_CODING && m_mixedLossyLossless) { m_mixedLossyLossless = 0; diff --git a/source/Lib/CommonLib/CommonDef.h b/source/Lib/CommonLib/CommonDef.h index 52698cd9c704b9c8704768fb5794ff653f58c16d..c1b43982d793246f377b8d50008cf98ca3959a17 100644 --- a/source/Lib/CommonLib/CommonDef.h +++ b/source/Lib/CommonLib/CommonDef.h @@ -541,8 +541,9 @@ static constexpr int EPBIN_WEIGHT_FACTOR = 4; static constexpr int ENC_PPS_ID_RPR = 3; static constexpr int ENC_PPS_ID_RPR2 = 5; static constexpr int ENC_PPS_ID_RPR3 = 7; -static constexpr int NUM_RPR_PPS = 4; -static constexpr int RPR_PPS_ID[NUM_RPR_PPS] = { 0, ENC_PPS_ID_RPR3, ENC_PPS_ID_RPR2, ENC_PPS_ID_RPR }; +static constexpr int NUM_RPR_PPS = 8; +static constexpr int RPR_PPS_ID[NUM_RPR_PPS] = { 0, ENC_PPS_ID_RPR3, ENC_PPS_ID_RPR2, ENC_PPS_ID_RPR, ENC_PPS_ID_RPR3+1, ENC_PPS_ID_RPR2+1, ENC_PPS_ID_RPR+1, 1 }; + static constexpr int MAX_SCALING_RATIO = 2; // max downsampling ratio for RPR static constexpr ScalingRatio SCALE_1X = { 1 << ScalingRatio::BITS, 1 << ScalingRatio::BITS }; // scale ratio 1x diff --git a/source/Lib/CommonLib/InterPrediction.cpp b/source/Lib/CommonLib/InterPrediction.cpp index 31b57753c2bd8adcf8a22d5841e8992e9bc07e02..ca450592301b50a4fea7952d1940684a7e066bd6 100644 --- a/source/Lib/CommonLib/InterPrediction.cpp +++ b/source/Lib/CommonLib/InterPrediction.cpp @@ -1903,8 +1903,7 @@ void InterPrediction::xProcessDMVR(PredictionUnit &pu, PelUnitBuf &pcYuvDst, con // subblock boundary activity threshold // corresponds to encoding in 1/2 reduced resolution when GOP based RPR is used const int boundaryDiffThreshold = - pu.cu->slice->getPPS()->getPPSId() == ENC_PPS_ID_RPR && pu.cu->slice->getSPS()->getGOPBasedRPREnabledFlag() ? 5 - : 10; + pu.cu->slice->getPPS()->getPPSId() == (ENC_PPS_ID_RPR + pu.cu->slice->getNalUnitLayerId()) && pu.cu->slice->getSPS()->getGOPBasedRPREnabledFlag() ? 5 : 10; #endif int subPuIdx = 0; diff --git a/source/Lib/EncoderLib/EncGOP.cpp b/source/Lib/EncoderLib/EncGOP.cpp index 93a579a3088c244e01c643778a5d6605f69b0d96..56345cd5c2744cd5e8b4ade973647a6a9e464d46 100644 --- a/source/Lib/EncoderLib/EncGOP.cpp +++ b/source/Lib/EncoderLib/EncGOP.cpp @@ -5142,7 +5142,8 @@ void EncGOP::xCalculateAddPSNR(Picture* pcPic, PelUnitBuf cPicD, const AccessUni ScalingRatio scalingRatio; // it is assumed that full resolution picture PPS has ppsId 0 - const PPS* pps = m_pcEncLib->getPPS(0); + const PPS* pps = m_pcEncLib->getPPS(pcPic->layerId); + CU::getRprScaling(&sps, pps, pcPic, scalingRatio); bool rescaleForDisplay = true; diff --git a/source/Lib/EncoderLib/EncLib.cpp b/source/Lib/EncoderLib/EncLib.cpp index 87a23120543d2c898874e00bb28212b978e6127c..75b3a71222a36f131d32d1c60864c0074ccd4a7a 100644 --- a/source/Lib/EncoderLib/EncLib.cpp +++ b/source/Lib/EncoderLib/EncLib.cpp @@ -86,6 +86,8 @@ EncLib::EncLib(EncLibCommon *encLibCommon) m_layerId = NOT_VALID; m_picIdInGOP = NOT_VALID; + m_gopRprPpsId = 0; + } EncLib::~EncLib() @@ -207,7 +209,7 @@ void EncLib::init(AUWriterIf *auWriterIf) if (m_resChangeInClvsEnabled) { - PPS &pps = *( m_ppsMap.allocatePS( ENC_PPS_ID_RPR ) ); + PPS& pps = *(m_ppsMap.allocatePS(ENC_PPS_ID_RPR + m_layerId)); Window& inputScalingWindow = pps0.getScalingWindow(); int scaledWidth = int( ( pps0.getPicWidthInLumaSamples() - SPS::getWinUnitX( sps0.getChromaFormatIdc() ) * ( inputScalingWindow.getWindowLeftOffset() + inputScalingWindow.getWindowRightOffset() ) ) / m_scalingRatioHor ); int minSizeUnit = std::max(8, 1 << sps0.getLog2MinCodingBlockSize()); @@ -286,7 +288,7 @@ void EncLib::init(AUWriterIf *auWriterIf) } if (m_resChangeInClvsEnabled && ((m_gopBasedRPREnabledFlag && (m_iQP >= getGOPBasedRPRQPThreshold())) || m_rprFunctionalityTestingEnabledFlag)) { - PPS& pps = *(m_ppsMap.allocatePS(ENC_PPS_ID_RPR2)); + PPS& pps = *(m_ppsMap.allocatePS(ENC_PPS_ID_RPR2 + m_layerId)); Window& inputScalingWindow = pps0.getScalingWindow(); int scaledWidth = int((pps0.getPicWidthInLumaSamples() - SPS::getWinUnitX(sps0.getChromaFormatIdc()) * (inputScalingWindow.getWindowLeftOffset() + inputScalingWindow.getWindowRightOffset())) / m_scalingRatioHor2); int minSizeUnit = std::max(8, 1 << sps0.getLog2MinCodingBlockSize()); @@ -361,7 +363,7 @@ void EncLib::init(AUWriterIf *auWriterIf) } if (m_resChangeInClvsEnabled && ((m_gopBasedRPREnabledFlag && (m_iQP >= getGOPBasedRPRQPThreshold())) || m_rprFunctionalityTestingEnabledFlag)) { - PPS& pps = *(m_ppsMap.allocatePS(ENC_PPS_ID_RPR3)); + PPS& pps = *(m_ppsMap.allocatePS(ENC_PPS_ID_RPR3 + m_layerId)); Window& inputScalingWindow = pps0.getScalingWindow(); int scaledWidth = int((pps0.getPicWidthInLumaSamples() - SPS::getWinUnitX(sps0.getChromaFormatIdc()) * (inputScalingWindow.getWindowLeftOffset() + inputScalingWindow.getWindowRightOffset())) / m_scalingRatioHor3); int minSizeUnit = std::max(8, 1 << sps0.getLog2MinCodingBlockSize()); @@ -500,7 +502,7 @@ void EncLib::init(AUWriterIf *auWriterIf) } if (m_resChangeInClvsEnabled) { - xInitScalingLists(sps0, *m_apsMaps[ApsType::SCALING_LIST].getPS(ENC_PPS_ID_RPR)); + xInitScalingLists(sps0, *m_apsMaps[ApsType::SCALING_LIST].getPS(ENC_PPS_ID_RPR + m_layerId)); } if (getUseCompositeRef()) { @@ -613,9 +615,7 @@ void EncLib::deletePicBuffer() bool EncLib::encodePrep(bool flush, PelStorage *pcPicYuvOrg, PelStorage *cPicYuvTrueOrg, PelStorage *pcPicYuvFilteredOrg, PelStorage *pcPicYuvFilteredOrgForFG, const InputColourSpaceConversion snrCSC, std::list<PelUnitBuf *> &rcListPicYuvRecOut, - int &numEncoded - , PelStorage** ppcPicYuvRPR -) + int &numEncoded, PelStorage** ppcPicYuvRPR) { if (m_compositeRefEnabled && m_cGOPEncoder.getPicBg()->getSpliceFull() && m_pocLast >= 10 && m_receivedPicCount == 0 && m_cGOPEncoder.getEncodedLTRef() == false) @@ -689,15 +689,16 @@ bool EncLib::encodePrep(bool flush, PelStorage *pcPicYuvOrg, PelStorage *cPicYuv ScalingRatio downScalingRatio{ 32768, 32768 }; ScalingRatio upScalingRatio{ 8192, 8192 }; - const PPS* orgPPS = m_ppsMap.getPS(0); + const PPS* orgPPS = m_ppsMap.getPS(0 + m_layerId); const SPS* orgSPS = m_spsMap.getPS(orgPPS->getSPSId()); const ChromaFormat chFormatIdc = orgSPS->getChromaFormatIdc(); - const PPS* pTempPPS = m_ppsMap.getPS(ENC_PPS_ID_RPR); + const PPS* pTempPPS = m_ppsMap.getPS(ENC_PPS_ID_RPR + m_layerId); Picture::rescalePicture(downScalingRatio, *pcPicYuvOrg, orgPPS->getScalingWindow(), *ppcPicYuvRPR[1], pTempPPS->getScalingWindow(), chFormatIdc, orgSPS->getBitDepths(), true, true, orgSPS->getHorCollocatedChromaFlag(), orgSPS->getVerCollocatedChromaFlag()); Picture::rescalePicture(upScalingRatio, *ppcPicYuvRPR[1], orgPPS->getScalingWindow(), *ppcPicYuvRPR[0], pTempPPS->getScalingWindow(), chFormatIdc, orgSPS->getBitDepths(), true, false, orgSPS->getHorCollocatedChromaFlag(), orgSPS->getVerCollocatedChromaFlag()); + // Calculate PSNR const Pel* pSrc0 = pcPicYuvOrg->get(COMPONENT_Y).bufAt(0, 0); const Pel* pSrc1 = ppcPicYuvRPR[0]->get(COMPONENT_Y).bufAt(0, 0); @@ -723,23 +724,23 @@ bool EncLib::encodePrep(bool flush, PelStorage *pcPicYuvOrg, PelStorage *cPicYuv const int qpBias = 37; if ((m_psnrThresholdRPR - (m_iQP - qpBias) * 0.5) < upscaledPSNR) { - ppsID = ENC_PPS_ID_RPR; + ppsID = ENC_PPS_ID_RPR + m_layerId; } else { if ((m_psnrThresholdRPR2 - (m_iQP - qpBias) * 0.5) < upscaledPSNR) { - ppsID = ENC_PPS_ID_RPR2; + ppsID = ENC_PPS_ID_RPR2 + m_layerId; } else { if ((m_psnrThresholdRPR3 - (m_iQP - qpBias) * 0.5) < upscaledPSNR) { - ppsID = ENC_PPS_ID_RPR3; + ppsID = ENC_PPS_ID_RPR3 + m_layerId; } else { - ppsID = 0; + ppsID = m_layerId; } } } @@ -756,7 +757,7 @@ bool EncLib::encodePrep(bool flush, PelStorage *pcPicYuvOrg, PelStorage *cPicYuv const int poc = m_pocLast + (m_compositeRefEnabled ? 2 : 1); if (poc % m_rprSwitchingSegmentSize == 0) { - ppsID = 0; + ppsID = m_layerId; bool applyRpr = false; int currPoc = poc + m_frameSkip; int rprSegment = getRprSwitchingSegment(currPoc); @@ -764,7 +765,7 @@ bool EncLib::encodePrep(bool flush, PelStorage *pcPicYuvOrg, PelStorage *cPicYuv applyRpr = thePPSID != 0; if (applyRpr) { - ppsID = thePPSID; + ppsID = thePPSID + m_layerId; } m_gopRprPpsId = ppsID; } @@ -779,14 +780,14 @@ bool EncLib::encodePrep(bool flush, PelStorage *pcPicYuvOrg, PelStorage *cPicYuv if (poc / m_switchPocPeriod % 2) { - ppsID = ENC_PPS_ID_RPR; + ppsID = ENC_PPS_ID_RPR + m_layerId; } else { - ppsID = 0; + ppsID = m_layerId; } } - if( m_vps->getMaxLayers() > 1 ) + if ((m_vps->getMaxLayers() > 1) && !((m_gopBasedRPREnabledFlag && (m_iQP >= getGOPBasedRPRQPThreshold())) || m_rprFunctionalityTestingEnabledFlag)) { ppsID = m_vps->getGeneralLayerIdx( m_layerId ); } @@ -815,7 +816,7 @@ bool EncLib::encodePrep(bool flush, PelStorage *pcPicYuvOrg, PelStorage *cPicYuv const ChromaFormat chromaFormatIdc = pSPS->getChromaFormatIdc(); - const PPS *refPPS = m_ppsMap.getPS( 0 ); + const PPS* refPPS = m_ppsMap.getPS(m_layerId); const Window& curScalingWindow = pPPS->getScalingWindow(); const int curPicWidth = pPPS->getPicWidthInLumaSamples() @@ -1166,7 +1167,8 @@ void EncLib::xGetNewPicBuffer ( std::list<PelUnitBuf*>& rcListPicYuvRecOut, Pict if (m_resChangeInClvsEnabled) { - const PPS &pps0 = *m_ppsMap.getPS(0); + int thePPS = m_layerId; + const PPS& pps0 = *m_ppsMap.getPS(thePPS); rpcPic->M_BUFS(0, PIC_ORIGINAL_INPUT).create(sps.getChromaFormatIdc(), Area(Position(), Size(pps0.getPicWidthInLumaSamples(), pps0.getPicHeightInLumaSamples()))); rpcPic->M_BUFS(0, PIC_TRUE_ORIGINAL_INPUT).create(sps.getChromaFormatIdc(), Area(Position(), Size(pps0.getPicWidthInLumaSamples(), pps0.getPicHeightInLumaSamples()))); if (getGopBasedTemporalFilterEnabled()) @@ -1914,7 +1916,7 @@ void EncLib::xInitPPS(PPS &pps, const SPS &sps) bool isRprPPS = false; for (int nr = 0; nr < NUM_RPR_PPS; nr++) { - if ((pps.getPPSId() == RPR_PPS_ID[nr]) && (RPR_PPS_ID[nr] != 0)) + if ((pps.getPPSId() == RPR_PPS_ID[nr]) && (RPR_PPS_ID[nr] != m_layerId)) { isRprPPS = true; } @@ -2601,15 +2603,15 @@ int EncCfg::getQPForPicture(const uint32_t gopIndex, const Slice *pSlice) const } if (m_gopBasedRPREnabledFlag) { - if (pSlice->getPPS()->getPPSId() == ENC_PPS_ID_RPR) + if (pSlice->getPPS()->getPPSId() == (ENC_PPS_ID_RPR + pSlice->getNalUnitLayerId())) { qp += EncCfg::m_qpOffsetRPR; } - if (pSlice->getPPS()->getPPSId() == ENC_PPS_ID_RPR2) + if (pSlice->getPPS()->getPPSId() == (ENC_PPS_ID_RPR2 + pSlice->getNalUnitLayerId())) { qp += EncCfg::m_qpOffsetRPR2; } - if (pSlice->getPPS()->getPPSId() == ENC_PPS_ID_RPR3) + if (pSlice->getPPS()->getPPSId() == (ENC_PPS_ID_RPR3 + pSlice->getNalUnitLayerId())) { qp += EncCfg::m_qpOffsetRPR3; } diff --git a/source/Lib/EncoderLib/EncLib.h b/source/Lib/EncoderLib/EncLib.h index 37e61c75abd2408b952e0a1e88bd703184110711..d34c1ca5adfc4fb15cd2321caa3a2308209986a8 100644 --- a/source/Lib/EncoderLib/EncLib.h +++ b/source/Lib/EncoderLib/EncLib.h @@ -79,6 +79,7 @@ private: uint32_t m_codedPicCount; ///< number of coded pictures PicList& m_cListPic; ///< dynamic list of pictures int m_layerId; + int m_gopRprPpsId; // encoder search InterSearch m_cInterSearch; ///< encoder search class @@ -146,7 +147,6 @@ public: const RPLList *getRplList(RefPicList l) const { return &m_rplLists[l]; } RPLList *getRplList(RefPicList l) { return &m_rplLists[l]; } uint32_t getNumRpl(RefPicList l) const { return m_rplLists[l].getNumberOfReferencePictureLists(); } - int m_gopRprPpsId; bool m_rprPPSCodedAfterIntraList[NUM_RPR_PPS]; // 4 resolutions, full, 5/6, 2/3 and 1/2 bool m_refLayerRescaledAvailable; protected: diff --git a/source/Lib/EncoderLib/EncSlice.cpp b/source/Lib/EncoderLib/EncSlice.cpp index a7f3b182e1a5cbb1b413c63e08b989cc8d30ab92..d2d94f7ed8d63e9590b876b1fa71a280771fff10 100644 --- a/source/Lib/EncoderLib/EncSlice.cpp +++ b/source/Lib/EncoderLib/EncSlice.cpp @@ -549,17 +549,17 @@ void EncSlice::initEncSlice(Picture *pcPic, const int pocLast, const int pocCurr } else { - if (rpcSlice->getPPS()->getPPSId() == ENC_PPS_ID_RPR) // ScalingRatioHor/ScalingRatioVer + if (rpcSlice->getPPS()->getPPSId() == (ENC_PPS_ID_RPR + rpcSlice->getNalUnitLayerId())) // ScalingRatioHor/ScalingRatioVer { cbQP += mappedQpDelta(COMPONENT_Cb, m_pcCfg->getQpOffsetChromaRPR()); crQP += mappedQpDelta(COMPONENT_Cr, m_pcCfg->getQpOffsetChromaRPR()); } - else if (rpcSlice->getPPS()->getPPSId() == ENC_PPS_ID_RPR2) // ScalingRatioHor2/ScalingRatioVer2 + if (rpcSlice->getPPS()->getPPSId() == (ENC_PPS_ID_RPR2 + rpcSlice->getNalUnitLayerId())) // ScalingRatioHor/ScalingRatioVer { cbQP += mappedQpDelta(COMPONENT_Cb, m_pcCfg->getQpOffsetChromaRPR2()); crQP += mappedQpDelta(COMPONENT_Cr, m_pcCfg->getQpOffsetChromaRPR2()); } - else if (rpcSlice->getPPS()->getPPSId() == ENC_PPS_ID_RPR3) // ScalingRatioHor3/ScalingRatioVer3 + if (rpcSlice->getPPS()->getPPSId() == (ENC_PPS_ID_RPR3 + rpcSlice->getNalUnitLayerId())) // ScalingRatioHor/ScalingRatioVer { cbQP += mappedQpDelta(COMPONENT_Cb, m_pcCfg->getQpOffsetChromaRPR3()); crQP += mappedQpDelta(COMPONENT_Cr, m_pcCfg->getQpOffsetChromaRPR3());