diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h index 80371e5704dacce3dccfff3edc165b67b6b9a0bc..55bf7dc1589e42fc2d44b4f55ddc8834bb74e7f6 100644 --- a/source/Lib/CommonLib/TypeDef.h +++ b/source/Lib/CommonLib/TypeDef.h @@ -51,6 +51,7 @@ #include <cassert> //########### place macros to be removed in next cycle below this line ############### +#define JVET_R0327_ONE_PASS_CCALF 1 // JVET-R0327: One-pass CCALF #define JVET_R0271_SLICE_LEVEL_DQ_SDH_RRC 1 // JVET-R0271/R0155: Slice level DQ and SDH granularity for mixed lossy/lossless. diff --git a/source/Lib/EncoderLib/EncAdaptiveLoopFilter.cpp b/source/Lib/EncoderLib/EncAdaptiveLoopFilter.cpp index e7d06837ff7f6ce3d069d14efa0453328e8e88f1..e2332457d168faf8a183904903d1a95f4ef9a78f 100644 --- a/source/Lib/EncoderLib/EncAdaptiveLoopFilter.cpp +++ b/source/Lib/EncoderLib/EncAdaptiveLoopFilter.cpp @@ -1077,6 +1077,13 @@ void EncAdaptiveLoopFilter::ALFProcess(CodingStructure& cs, const double *lambda m_tempBuf.get(COMPONENT_Cr).copyFrom(cs.getRecoBuf().get(COMPONENT_Cr)); recYuv = m_tempBuf.getBuf(cs.area); recYuv.extendBorderPel(MAX_ALF_FILTER_LENGTH >> 1); + +#if JVET_R0327_ONE_PASS_CCALF + deriveStatsForCcAlfFiltering(orgYuv, recYuv, COMPONENT_Cb, m_numCTUsInWidth, (0 + 1), cs); + deriveStatsForCcAlfFiltering(orgYuv, recYuv, COMPONENT_Cr, m_numCTUsInWidth, (0 + 1), cs); + initDistortionCcalf(); +#endif + m_CABACEstimator->getCtx() = SubCtx(Ctx::CcAlfFilterControlFlag, ctxStartCcAlf); deriveCcAlfFilter(cs, COMPONENT_Cb, orgYuv, recYuv, cs.getRecoBuf()); m_CABACEstimator->getCtx() = SubCtx(Ctx::CcAlfFilterControlFlag, ctxStartCcAlf); @@ -2538,6 +2545,20 @@ void EncAdaptiveLoopFilter::initDistortion() } } } + +#if JVET_R0327_ONE_PASS_CCALF +void EncAdaptiveLoopFilter::initDistortionCcalf() +{ + for (int comp = 1; comp < MAX_NUM_COMPONENT; comp++) + { + for (int ctbIdx = 0; ctbIdx < m_numCTUsInPic; ctbIdx++) + { + m_ctbDistortionUnfilter[comp][ctbIdx] = m_alfCovarianceCcAlf[comp - 1][0][0][ctbIdx].pixAcc; + } + } +} +#endif + void EncAdaptiveLoopFilter::alfEncoderCtb(CodingStructure& cs, AlfParam& alfParamNewFilters #if ENABLE_QPA , const double lambdaChromaWeight @@ -3568,6 +3589,36 @@ std::vector<int> EncAdaptiveLoopFilter::getAvailableCcAlfApsIds(CodingStructure& return result; } +#if JVET_R0327_ONE_PASS_CCALF +void EncAdaptiveLoopFilter::getFrameStatsCcalf(ComponentID compIdx, int filterIdc) +{ + int ctuRsAddr = 0; + const int filterIdx = filterIdc - 1; + + // init Frame stats buffers + for (int shape = 0; shape != m_filterShapesCcAlf[compIdx - 1].size(); shape++) + { + m_alfCovarianceFrameCcAlf[compIdx - 1][shape][filterIdx].reset(); + } + + for (int yPos = 0; yPos < m_picHeight; yPos += m_maxCUHeight) + { + for (int xPos = 0; xPos < m_picWidth; xPos += m_maxCUWidth) + { + if (m_trainingCovControl[ctuRsAddr] == filterIdc) + { + for (int shape = 0; shape != m_filterShapesCcAlf[compIdx - 1].size(); shape++) + { + m_alfCovarianceFrameCcAlf[compIdx - 1][shape][filterIdx] += + m_alfCovarianceCcAlf[compIdx - 1][shape][0][ctuRsAddr]; + } + } + ctuRsAddr++; + } + } +} +#endif + void EncAdaptiveLoopFilter::deriveCcAlfFilter( CodingStructure& cs, ComponentID compID, const PelUnitBuf& orgYuv, const PelUnitBuf& tempDecYuvBuf, const PelUnitBuf& dstYuv ) { if (!cs.slice->getTileGroupAlfEnabledFlag(COMPONENT_Y)) @@ -3624,8 +3675,10 @@ void EncAdaptiveLoopFilter::deriveCcAlfFilter( CodingStructure& cs, ComponentID const Pel *unfiltered = dstYuv.get( compID ).bufAt(0,0); const int orgStride = orgYuv.get( compID ).stride; const int unfilteredStride = dstYuv.get( compID ).stride; +#if !JVET_R0327_ONE_PASS_CCALF const Pel *filtered = m_buf->bufAt(0,0); const int filteredStride = m_buf->stride; +#endif uint64_t unfilteredDistortion = 0; computeLog2BlockSizeDistortion(org, orgStride, unfiltered, unfilteredStride, m_buf->height, m_buf->width, m_unfilteredDistortion[0], m_numCTUsInWidth, cs.pcv->maxCUWidthLog2 - scaleX, @@ -3717,9 +3770,27 @@ void EncAdaptiveLoopFilter::deriveCcAlfFilter( CodingStructure& cs, ComponentID { if (!referencingExistingAps) { +#if JVET_R0327_ONE_PASS_CCALF + getFrameStatsCcalf(compID, (filterIdx + 1)); +#else deriveStatsForCcAlfFiltering(orgYuv, tempDecYuvBuf, compID, m_numCTUsInWidth, (filterIdx + 1), cs); +#endif deriveCcAlfFilterCoeff(compID, dstYuv, tempDecYuvBuf, ccAlfFilterCoeff, filterIdx); } +#if JVET_R0327_ONE_PASS_CCALF + const int numCoeff = m_filterShapesCcAlf[compID - 1][0].numCoeff - 1; + int log2BlockWidth = cs.pcv->maxCUWidthLog2 - scaleX; + int log2BlockHeight = cs.pcv->maxCUHeightLog2 - scaleY; + for (int y = 0; y < m_buf->height; y += (1 << log2BlockHeight)) + { + for (int x = 0; x < m_buf->width; x += (1 << log2BlockWidth)) + { + int ctuIdx = (y >> log2BlockHeight) * m_numCTUsInWidth + (x >> log2BlockWidth); + m_trainingDistortion[filterIdx][ctuIdx] = int(m_ctbDistortionUnfilter[compID][ctuIdx] + + m_alfCovarianceCcAlf[compID - 1][0][0][ctuIdx].calcErrorForCcAlfCoeffs((int*)(ccAlfFilterCoeff[filterIdx]), numCoeff, (m_scaleBits + 1))); + } + } +#else m_buf->copyFrom(dstYuv.get(compID)); applyCcAlfFilter(cs, compID, *m_buf, tempDecYuvBuf, nullptr, ccAlfFilterCoeff, filterIdx); @@ -3727,6 +3798,7 @@ void EncAdaptiveLoopFilter::deriveCcAlfFilter( CodingStructure& cs, ComponentID computeLog2BlockSizeDistortion( org, orgStride, filtered, filteredStride, m_buf->height, m_buf->width, m_trainingDistortion[filterIdx], m_numCTUsInWidth, cs.pcv->maxCUWidthLog2 - scaleX, cs.pcv->maxCUHeightLog2 - scaleY, distortion); +#endif } } @@ -3900,7 +3972,9 @@ void EncAdaptiveLoopFilter::deriveStatsForCcAlfFiltering(const PelUnitBuf &orgYu { for (int xPos = 0; xPos < m_picWidth; xPos += m_maxCUWidth) { +#if !JVET_R0327_ONE_PASS_CCALF if (m_trainingCovControl[ctuRsAddr] == filterIdc) +#endif { const int width = (xPos + m_maxCUWidth > m_picWidth) ? (m_picWidth - xPos) : m_maxCUWidth; const int height = (yPos + m_maxCUHeight > m_picHeight) ? (m_picHeight - yPos) : m_maxCUHeight; diff --git a/source/Lib/EncoderLib/EncAdaptiveLoopFilter.h b/source/Lib/EncoderLib/EncAdaptiveLoopFilter.h index 6aad7ca7a7e6952d1f0216cb0d420ea696362fee..aa399955e16d14b1f96c11675b49c6e83d082951 100644 --- a/source/Lib/EncoderLib/EncAdaptiveLoopFilter.h +++ b/source/Lib/EncoderLib/EncAdaptiveLoopFilter.h @@ -234,7 +234,7 @@ private: uint8_t* m_ctuEnableFlagTmp[MAX_NUM_COMPONENT]; uint8_t* m_ctuEnableFlagTmp2[MAX_NUM_COMPONENT]; uint8_t* m_ctuAlternativeTmp[MAX_NUM_COMPONENT]; - AlfCovariance*** m_alfCovarianceCcAlf[2]; // [compIdx-1][shapeIdx][ctbAddr][filterIdx] + AlfCovariance*** m_alfCovarianceCcAlf[2]; // [compIdx-1][shapeIdx][filterIdx][ctbAddr] AlfCovariance** m_alfCovarianceFrameCcAlf[2]; // [compIdx-1][shapeIdx][filterIdx] //for RDO @@ -378,6 +378,10 @@ private: void xSetupCcAlfAPS( CodingStructure& cs ); void countLumaSwingGreaterThanThreshold(const Pel* luma, int lumaStride, int height, int width, int log2BlockWidth, int log2BlockHeight, uint64_t* lumaSwingGreaterThanThresholdCount, int lumaCountStride); void countChromaSampleValueNearMidPoint(const Pel* chroma, int chromaStride, int height, int width, int log2BlockWidth, int log2BlockHeight, uint64_t* chromaSampleCountNearMidPoint, int chromaSampleCountNearMidPointStride); +#if JVET_R0327_ONE_PASS_CCALF + void getFrameStatsCcalf(ComponentID compIdx, int filterIdc); + void initDistortionCcalf(); +#endif };