From c0a12ea1285e7d909c243686c38f8991a1ef88f6 Mon Sep 17 00:00:00 2001 From: Frank Bossen <fbossen@gmail.com> Date: Wed, 29 Jan 2020 15:03:52 -0500 Subject: [PATCH] Fix #840: apply boundary rules in CCALF encoder The CCALF reconstruction function used by the encoder is separate from the one used by the decoder. !1280 addressed issues in the decoder. This commit addresses a similar issue in the encoder. --- source/Lib/CommonLib/AdaptiveLoopFilter.cpp | 83 ++++++++++++++++++--- 1 file changed, 72 insertions(+), 11 deletions(-) diff --git a/source/Lib/CommonLib/AdaptiveLoopFilter.cpp b/source/Lib/CommonLib/AdaptiveLoopFilter.cpp index d72a40f53..4d862ff95 100644 --- a/source/Lib/CommonLib/AdaptiveLoopFilter.cpp +++ b/source/Lib/CommonLib/AdaptiveLoopFilter.cpp @@ -294,20 +294,16 @@ void AdaptiveLoopFilter::applyCcAlfFilter(CodingStructure &cs, ComponentID compI const short filterSet[MAX_NUM_CC_ALF_FILTERS][MAX_NUM_CC_ALF_CHROMA_COEFF], const int selectedFilterIdx) { + bool clipTop = false, clipBottom = false, clipLeft = false, clipRight = false; + int numHorVirBndry = 0, numVerVirBndry = 0; + int horVirBndryPos[] = { 0, 0, 0 }; + int verVirBndryPos[] = { 0, 0, 0 }; + int ctuIdx = 0; for( int yPos = 0; yPos < m_picHeight; yPos += m_maxCUHeight ) { for( int xPos = 0; xPos < m_picWidth; xPos += m_maxCUWidth ) { - 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; - const UnitArea area( m_chromaFormat, Area( xPos, yPos, width, height ) ); - const int chromaScaleX = getComponentScaleX( compID, m_chromaFormat ); - const int chromaScaleY = getComponentScaleY( compID, m_chromaFormat ); - - Area blkDst(xPos >> chromaScaleX, yPos >> chromaScaleY, width >> chromaScaleX, height >> chromaScaleY); - Area blkSrc(xPos, yPos, width, height); - int filterIdx = (filterControl == nullptr) ? selectedFilterIdx @@ -320,8 +316,73 @@ void AdaptiveLoopFilter::applyCcAlfFilter(CodingStructure &cs, ComponentID compI const int16_t *filterCoeff = filterSet[filterIdx]; - m_filterCcAlf(dstBuf, recYuvExt, blkDst, blkSrc, compID, filterCoeff, m_clpRngs, cs, m_alfVBLumaCTUHeight, - m_alfVBLumaPos); + 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; + const int chromaScaleX = getComponentScaleX(compID, m_chromaFormat); + const int chromaScaleY = getComponentScaleY(compID, m_chromaFormat); + + int rasterSliceAlfPad = 0; + if (isCrossedByVirtualBoundaries(cs, xPos, yPos, width, height, clipTop, clipBottom, clipLeft, clipRight, + numHorVirBndry, numVerVirBndry, horVirBndryPos, verVirBndryPos, + rasterSliceAlfPad)) + { + int yStart = yPos; + for (int i = 0; i <= numHorVirBndry; i++) + { + const int yEnd = i == numHorVirBndry ? yPos + height : horVirBndryPos[i]; + const int h = yEnd - yStart; + const bool clipT = (i == 0 && clipTop) || (i > 0) || (yStart == 0); + const bool clipB = (i == numHorVirBndry && clipBottom) || (i < numHorVirBndry) || (yEnd == m_picHeight); + int xStart = xPos; + for (int j = 0; j <= numVerVirBndry; j++) + { + const int xEnd = j == numVerVirBndry ? xPos + width : verVirBndryPos[j]; + const int w = xEnd - xStart; + const bool clipL = (j == 0 && clipLeft) || (j > 0) || (xStart == 0); + const bool clipR = (j == numVerVirBndry && clipRight) || (j < numVerVirBndry) || (xEnd == m_picWidth); + const int wBuf = w + (clipL ? 0 : MAX_ALF_PADDING_SIZE) + (clipR ? 0 : MAX_ALF_PADDING_SIZE); + const int hBuf = h + (clipT ? 0 : MAX_ALF_PADDING_SIZE) + (clipB ? 0 : MAX_ALF_PADDING_SIZE); + PelUnitBuf buf = m_tempBuf2.subBuf(UnitArea(cs.area.chromaFormat, Area(0, 0, wBuf, hBuf))); + buf.copyFrom(recYuvExt.subBuf( + UnitArea(cs.area.chromaFormat, Area(xStart - (clipL ? 0 : MAX_ALF_PADDING_SIZE), + yStart - (clipT ? 0 : MAX_ALF_PADDING_SIZE), wBuf, hBuf)))); + // pad top-left unavailable samples for raster slice + if (xStart == xPos && yStart == yPos && (rasterSliceAlfPad & 1)) + { + buf.padBorderPel(MAX_ALF_PADDING_SIZE, 1); + } + + // pad bottom-right unavailable samples for raster slice + if (xEnd == xPos + width && yEnd == yPos + height && (rasterSliceAlfPad & 2)) + { + buf.padBorderPel(MAX_ALF_PADDING_SIZE, 2); + } + buf.extendBorderPel(MAX_ALF_PADDING_SIZE); + buf = buf.subBuf(UnitArea( + cs.area.chromaFormat, Area(clipL ? 0 : MAX_ALF_PADDING_SIZE, clipT ? 0 : MAX_ALF_PADDING_SIZE, w, h))); + + const Area blkSrc(0, 0, w, h); + + const Area blkDst(xStart >> chromaScaleX, yStart >> chromaScaleY, w >> chromaScaleX, h >> chromaScaleY); + m_filterCcAlf(dstBuf, buf, blkDst, blkSrc, compID, filterCoeff, m_clpRngs, cs, m_alfVBLumaCTUHeight, + m_alfVBLumaPos); + + xStart = xEnd; + } + + yStart = yEnd; + } + } + else + { + const UnitArea area(m_chromaFormat, Area(xPos, yPos, width, height)); + + Area blkDst(xPos >> chromaScaleX, yPos >> chromaScaleY, width >> chromaScaleX, height >> chromaScaleY); + Area blkSrc(xPos, yPos, width, height); + + m_filterCcAlf(dstBuf, recYuvExt, blkDst, blkSrc, compID, filterCoeff, m_clpRngs, cs, m_alfVBLumaCTUHeight, + m_alfVBLumaPos); + } } ctuIdx++; } -- GitLab