diff --git a/source/App/EncoderApp/EncApp.cpp b/source/App/EncoderApp/EncApp.cpp index ee45301ed6a3a08c824e3d7b6e335e7a27d3546c..930308b27ef367a1c98f906f16a14a10ba171d9b 100644 --- a/source/App/EncoderApp/EncApp.cpp +++ b/source/App/EncoderApp/EncApp.cpp @@ -312,6 +312,20 @@ void EncApp::xInitLibCfg() // ADD_NEW_TOOL : (encoder app) add setting of tool enabling flags and associated parameters here +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + m_cEncLib.setLoopFilterAcrossVirtualBoundariesDisabledFlag ( m_loopFilterAcrossVirtualBoundariesDisabledFlag ); + m_cEncLib.setNumVerVirtualBoundaries ( m_numVerVirtualBoundaries ); + m_cEncLib.setNumHorVirtualBoundaries ( m_numHorVirtualBoundaries ); + for( unsigned i = 0; i < m_numVerVirtualBoundaries; i++ ) + { + m_cEncLib.setVirtualBoundariesPosX ( m_virtualBoundariesPosX[ i ], i ); + } + for( unsigned i = 0; i < m_numHorVirtualBoundaries; i++ ) + { + m_cEncLib.setVirtualBoundariesPosY ( m_virtualBoundariesPosY[ i ], i ); + } +#endif + m_cEncLib.setMaxCUWidth ( m_uiCTUSize ); m_cEncLib.setMaxCUHeight ( m_uiCTUSize ); m_cEncLib.setMaxCodingDepth ( m_uiMaxCodingDepth ); diff --git a/source/App/EncoderApp/EncAppCfg.cpp b/source/App/EncoderApp/EncAppCfg.cpp index 54c18bc7736e265e6cd01d94ce43e8e7512b3fc0..8c2fa2deab6f1d89cd76300957801cefc8a280c7 100644 --- a/source/App/EncoderApp/EncAppCfg.cpp +++ b/source/App/EncoderApp/EncAppCfg.cpp @@ -728,6 +728,10 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] ) const int defaultLadfIntervalLowerBound[2] = { 350, 833 }; SMultiValueInput<int> cfg_LadfQpOffset ( -MAX_QP, MAX_QP, 2, MAX_LADF_INTERVALS, defaultLadfQpOffset, 3 ); SMultiValueInput<int> cfg_LadfIntervalLowerBound ( 0, std::numeric_limits<int>::max(), 1, MAX_LADF_INTERVALS - 1, defaultLadfIntervalLowerBound, 2 ); +#endif +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + SMultiValueInput<unsigned> cfg_virtualBoundariesPosX (0, std::numeric_limits<uint32_t>::max(), 0, 3); + SMultiValueInput<unsigned> cfg_virtualBoundariesPosY (0, std::numeric_limits<uint32_t>::max(), 0, 3); #endif int warnUnknowParameter = 0; @@ -905,6 +909,13 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] ) ("WrapAroundOffset", m_wrapAroundOffset, 0u, "Offset in luma samples used for computing the horizontal wrap-around position") // ADD_NEW_TOOL : (encoder app) add parsing parameters here +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + ("LoopFilterAcrossVirtualBoundariesDisabledFlag", m_loopFilterAcrossVirtualBoundariesDisabledFlag, false, "Disable in-loop filtering operations across the virtual boundaries (0:off, 1:on) [default: off]") + ("NumVerVirtualBoundaries", m_numVerVirtualBoundaries, 0u, "Number of vertical virtual boundaries (0-3, inclusive)") + ("NumHorVirtualBoundaries", m_numHorVirtualBoundaries, 0u, "Number of horizontal virtual boundaries (0-3, inclusive)") + ("VirtualBoundariesPosX", cfg_virtualBoundariesPosX, cfg_virtualBoundariesPosX, "Locations of the vertical virtual boundaries in units of luma samples") + ("VirtualBoundariesPosY", cfg_virtualBoundariesPosY, cfg_virtualBoundariesPosY, "Locations of the horizontal virtual boundaries in units of luma samples") +#endif ("EncDbOpt", m_encDbOpt, false, "Encoder optimization with deblocking filter") ("LumaReshapeEnable", m_lumaReshapeEnable, false, "Enable Reshaping for Luma Channel") ("ReshapeSignalType", m_reshapeSignalType, 0u, "Input signal type: 0: SDR, 1:PQ, 2:HLG") @@ -1759,6 +1770,44 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] ) } #endif +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + if ( m_loopFilterAcrossVirtualBoundariesDisabledFlag ) + { + CHECK( m_numVerVirtualBoundaries > 3, "Number of vertical virtual boundaries must be comprised between 0 and 3 included" ); + CHECK( m_numHorVirtualBoundaries > 3, "Number of horizontal virtual boundaries must be comprised between 0 and 3 included" ); + CHECK( m_numVerVirtualBoundaries != cfg_virtualBoundariesPosX.values.size(), "Size of VirtualBoundariesPosX must be equal to NumVerVirtualBoundaries"); + CHECK( m_numHorVirtualBoundaries != cfg_virtualBoundariesPosY.values.size(), "Size of VirtualBoundariesPosY must be equal to NumHorVirtualBoundaries"); + m_virtualBoundariesPosX = cfg_virtualBoundariesPosX.values; + if (m_numVerVirtualBoundaries > 1) + { + sort(m_virtualBoundariesPosX.begin(), m_virtualBoundariesPosX.end()); + } + for (unsigned i = 0; i < m_numVerVirtualBoundaries; i++) + { + CHECK( m_virtualBoundariesPosX[i] == 0 || m_virtualBoundariesPosX[i] >= m_iSourceWidth, "The vertical virtual boundary must be within the picture" ); + CHECK( m_virtualBoundariesPosX[i] % 8, "The vertical virtual boundary must be a multiple of 8 luma samples" ); + if (i > 0) + { + CHECK( m_virtualBoundariesPosX[i] - m_virtualBoundariesPosX[i-1] < m_uiCTUSize, "The distance between any two vertical virtual boundaries shall be greater than or equal to the CTU size" ); + } + } + m_virtualBoundariesPosY = cfg_virtualBoundariesPosY.values; + if (m_numHorVirtualBoundaries > 1) + { + sort(m_virtualBoundariesPosY.begin(), m_virtualBoundariesPosY.end()); + } + for (unsigned i = 0; i < m_numHorVirtualBoundaries; i++) + { + CHECK( m_virtualBoundariesPosY[i] == 0 || m_virtualBoundariesPosY[i] >= m_iSourceHeight, "The horizontal virtual boundary must be within the picture" ); + CHECK( m_virtualBoundariesPosY[i] % 8, "The horizontal virtual boundary must be a multiple of 8 luma samples" ); + if (i > 0) + { + CHECK( m_virtualBoundariesPosY[i] - m_virtualBoundariesPosY[i-1] < m_uiCTUSize, "The distance between any two horizontal virtual boundaries shall be greater than or equal to the CTU size" ); + } + } + } +#endif + // reading external dQP description from file if ( !m_dQPFileName.empty() ) { @@ -3225,6 +3274,23 @@ void EncAppCfg::xPrintParameter() msg( VERBOSE, "WrapAroundOffset:%d ", m_wrapAroundOffset ); } // ADD_NEW_TOOL (add some output indicating the usage of tools) +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + msg(VERBOSE, "LoopFilterAcrossVirtualBoundaries:%d ", m_loopFilterAcrossVirtualBoundariesDisabledFlag); + if ( m_loopFilterAcrossVirtualBoundariesDisabledFlag ) + { + msg(VERBOSE, "vertical virtual boundaries:["); + for (unsigned i = 0; i < m_numVerVirtualBoundaries; i++) + { + msg(VERBOSE, " %d", m_virtualBoundariesPosX[i]); + } + msg(VERBOSE, " ] horizontal virtual boundaries:["); + for (unsigned i = 0; i < m_numHorVirtualBoundaries; i++) + { + msg(VERBOSE, " %d", m_virtualBoundariesPosY[i]); + } + msg(VERBOSE, " ] "); + } +#endif msg(VERBOSE, "Reshape:%d ", m_lumaReshapeEnable); if (m_lumaReshapeEnable) { diff --git a/source/App/EncoderApp/EncAppCfg.h b/source/App/EncoderApp/EncAppCfg.h index 69a21da6153ce4e009939b3dc7735e544f60177f..b79d0a14c4198c398450a5f0bb1270a1359a1704 100644 --- a/source/App/EncoderApp/EncAppCfg.h +++ b/source/App/EncoderApp/EncAppCfg.h @@ -295,6 +295,13 @@ protected: unsigned m_wrapAroundOffset; // ADD_NEW_TOOL : (encoder app) add tool enabling flags and associated parameters here +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + bool m_loopFilterAcrossVirtualBoundariesDisabledFlag; + unsigned m_numVerVirtualBoundaries; + unsigned m_numHorVirtualBoundaries; + std::vector<unsigned> m_virtualBoundariesPosX; + std::vector<unsigned> m_virtualBoundariesPosY; +#endif bool m_lumaReshapeEnable; uint32_t m_reshapeSignalType; uint32_t m_intraCMD; diff --git a/source/Lib/CommonLib/AdaptiveLoopFilter.cpp b/source/Lib/CommonLib/AdaptiveLoopFilter.cpp index 6a91be0868f59dc12918188a9c27b538b0690a89..d553b9ce879412ba8af7e7230b11ecc4074b35f0 100644 --- a/source/Lib/CommonLib/AdaptiveLoopFilter.cpp +++ b/source/Lib/CommonLib/AdaptiveLoopFilter.cpp @@ -72,6 +72,48 @@ AdaptiveLoopFilter::AdaptiveLoopFilter() #endif } +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND +bool AdaptiveLoopFilter::isCrossedByVirtualBoundaries( const int xPos, const int yPos, const int width, const int height, bool& clipTop, bool& clipBottom, bool& clipLeft, bool& clipRight, int& numHorSplit, int& numVerSplit, int horSplit[], int verSplit[], const PPS* pps) +{ + clipTop = false; clipBottom = false; clipLeft = false; clipRight = false; + numHorSplit = 0; numVerSplit = 0; + if( pps->getLoopFilterAcrossVirtualBoundariesDisabledFlag() ) + { + for( int i = 0; i < pps->getNumHorVirtualBoundaries(); i++ ) + { + if( pps->getVirtualBoundariesPosY(i) == yPos ) + { + clipTop = true; + } + else if( pps->getVirtualBoundariesPosY(i) == yPos + height ) + { + clipBottom = true; + } + else if( yPos < pps->getVirtualBoundariesPosY(i) && pps->getVirtualBoundariesPosY(i) < yPos + height ) + { + horSplit[numHorSplit++] = pps->getVirtualBoundariesPosY(i); + } + } + for( int i = 0; i < pps->getNumVerVirtualBoundaries(); i++ ) + { + if( pps->getVirtualBoundariesPosX(i) == xPos ) + { + clipLeft = true; + } + else if( pps->getVirtualBoundariesPosX(i) == xPos + width ) + { + clipRight = true; + } + else if( xPos < pps->getVirtualBoundariesPosX(i) && pps->getVirtualBoundariesPosX(i) < xPos + width ) + { + verSplit[numVerSplit++] = pps->getVirtualBoundariesPosX(i); + } + } + } + return numHorSplit > 0 || numVerSplit > 0 || clipTop || clipBottom || clipLeft || clipRight; +} +#endif + #if JVET_N0415_CTB_ALF #if JVET_N0242_NON_LINEAR_ALF const int AdaptiveLoopFilter::m_fixedFilterSetCoeff[ALF_FIXED_FILTER_NUM][MAX_NUM_ALF_LUMA_COEFF] = @@ -278,17 +320,190 @@ void AdaptiveLoopFilter::ALFProcess( CodingStructure& cs, AlfSliceParam& alfSlic const PreCalcValues& pcv = *cs.pcv; int ctuIdx = 0; +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + bool clipTop = false, clipBottom = false, clipLeft = false, clipRight = false; + int numHorSplit = 0, numVerSplit = 0; + int horSplit[] = { 0, 0, 0 }; + int verSplit[] = { 0, 0, 0 }; +#endif for( int yPos = 0; yPos < pcv.lumaHeight; yPos += pcv.maxCUHeight ) { for( int xPos = 0; xPos < pcv.lumaWidth; xPos += pcv.maxCUWidth ) { const int width = ( xPos + pcv.maxCUWidth > pcv.lumaWidth ) ? ( pcv.lumaWidth - xPos ) : pcv.maxCUWidth; const int height = ( yPos + pcv.maxCUHeight > pcv.lumaHeight ) ? ( pcv.lumaHeight - yPos ) : pcv.maxCUHeight; +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + bool ctuEnableFlag = m_ctuEnableFlag[COMPONENT_Y][ctuIdx]; + for( int compIdx = 1; compIdx < MAX_NUM_COMPONENT; compIdx++ ) + { + ctuEnableFlag |= m_ctuEnableFlag[compIdx][ctuIdx] > 0; + } + if( ctuEnableFlag && isCrossedByVirtualBoundaries( xPos, yPos, width, height, clipTop, clipBottom, clipLeft, clipRight, numHorSplit, numVerSplit, horSplit, verSplit, cs.slice->getPPS() ) ) + { + int yStart = yPos; + for( int i = 0; i <= numHorSplit; i++ ) + { + const int yEnd = i == numHorSplit ? yPos + height : horSplit[i]; + const int h = yEnd - yStart; + const bool clipT = ( i == 0 && clipTop ) || ( i > 0 ) || ( yStart == 0 ); + const bool clipB = ( i == numHorSplit && clipBottom ) || ( i < numHorSplit ) || ( yEnd == pcv.lumaHeight ); + + int xStart = xPos; + for( int j = 0; j <= numVerSplit; j++ ) + { + const int xEnd = j == numVerSplit ? xPos + width : verSplit[j]; + const int w = xEnd - xStart; + const bool clipL = ( j == 0 && clipLeft ) || ( j > 0 ) || ( xStart == 0 ); + const bool clipR = ( j == numVerSplit && clipRight ) || ( j < numVerSplit ) || ( xEnd == pcv.lumaWidth ); + + 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( tmpYuv.subBuf( UnitArea( cs.area.chromaFormat, Area( xStart - (clipL ? 0 : MAX_ALF_PADDING_SIZE), yStart - (clipT ? 0 : MAX_ALF_PADDING_SIZE), wBuf, hBuf ) ) ) ); + 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 ) ) ); + + if( m_ctuEnableFlag[COMPONENT_Y][ctuIdx] ) + { + const Area blkSrc( 0, 0, w, h ); + const Area blkDst( xStart, yStart, w, h ); + deriveClassification( m_classifier, buf.get(COMPONENT_Y), blkDst, blkSrc ); + const Area blkPCM( xStart, yStart, w, h ); + resetPCMBlkClassInfo( cs, m_classifier, buf.get(COMPONENT_Y), blkPCM ); +#if JVET_N0415_CTB_ALF + short filterSetIndex = alfCtuFilterIndex[ctuIdx]; + short *coeff; +#if JVET_N0242_NON_LINEAR_ALF + short *clip; +#endif + if (filterSetIndex >= NUM_FIXED_FILTER_SETS) + { + coeff = m_coeffApsLuma[filterSetIndex - NUM_FIXED_FILTER_SETS]; +#if JVET_N0242_NON_LINEAR_ALF + clip = m_clippApsLuma[filterSetIndex - NUM_FIXED_FILTER_SETS]; +#endif + } + else + { + coeff = m_fixedFilterSetCoeffDec[filterSetIndex]; +#if JVET_N0242_NON_LINEAR_ALF + clip = m_clipDefault; +#endif + } +#if JVET_N0180_ALF_LINE_BUFFER_REDUCTION +#if JVET_N0242_NON_LINEAR_ALF + m_filter7x7Blk(m_classifier, recYuv, buf, blkDst, blkSrc, COMPONENT_Y, coeff, clip, m_clpRngs.comp[COMPONENT_Y], cs + , m_alfVBLumaCTUHeight + , ((yPos + pcv.maxCUHeight >= pcv.lumaHeight) ? pcv.lumaHeight : m_alfVBLumaPos) + ); +#else + m_filter7x7Blk(m_classifier, recYuv, buf, blkDst, blkSrc, COMPONENT_Y, coeff, m_clpRngs.comp[COMPONENT_Y], cs + , m_alfVBLumaCTUHeight + , ((yPos + pcv.maxCUHeight >= pcv.lumaHeight) ? pcv.lumaHeight : m_alfVBLumaPos) + ); +#endif +#else +#if JVET_N0242_NON_LINEAR_ALF + m_filter7x7Blk(m_classifier, recYuv, buf, blkDst, blkSrc, COMPONENT_Y, coeff, clip, m_clpRngs.comp[COMPONENT_Y], cs); +#else + m_filter7x7Blk(m_classifier, recYuv, buf, blkDst, blkSrc, COMPONENT_Y, coeff, m_clpRngs.comp[COMPONENT_Y], cs); +#endif +#endif +#else +#if JVET_N0180_ALF_LINE_BUFFER_REDUCTION +#if JVET_N0242_NON_LINEAR_ALF + m_filter7x7Blk(m_classifier, recYuv, buf, blkDst, blkSrc, COMPONENT_Y, m_coeffFinal, m_clippFinal, m_clpRngs.comp[COMPONENT_Y], cs + , m_alfVBLumaCTUHeight + , ((yPos + pcv.maxCUHeight >= pcv.lumaHeight) ? pcv.lumaHeight : m_alfVBLumaPos) + ); +#else + m_filter7x7Blk(m_classifier, recYuv, buf, blkDst, blkSrc, COMPONENT_Y, m_coeffFinal, m_clpRngs.comp[COMPONENT_Y], cs + , m_alfVBLumaCTUHeight + , ((yPos + pcv.maxCUHeight >= pcv.lumaHeight) ? pcv.lumaHeight : m_alfVBLumaPos) + ); +#endif +#else +#if JVET_N0242_NON_LINEAR_ALF + m_filter7x7Blk(m_classifier, recYuv, buf, blkDst, blkSrc, COMPONENT_Y, m_coeffFinal, m_clippFinal, m_clpRngs.comp[COMPONENT_Y], cs); +#else + m_filter7x7Blk(m_classifier, recYuv, buf, blkDst, blkSrc, COMPONENT_Y, m_coeffFinal, m_clpRngs.comp[COMPONENT_Y], cs); +#endif +#endif +#endif + } + + for( int compIdx = 1; compIdx < MAX_NUM_COMPONENT; compIdx++ ) + { + ComponentID compID = ComponentID( compIdx ); + const int chromaScaleX = getComponentScaleX( compID, tmpYuv.chromaFormat ); + const int chromaScaleY = getComponentScaleY( compID, tmpYuv.chromaFormat ); + + if( m_ctuEnableFlag[compIdx][ctuIdx] ) + { + const Area blkSrc( 0, 0, w >> chromaScaleX, h >> chromaScaleY ); + const Area blkDst( xStart >> chromaScaleX, yStart >> chromaScaleY, w >> chromaScaleX, h >> chromaScaleY ); +#if JVET_N0180_ALF_LINE_BUFFER_REDUCTION +#if JVET_N0242_NON_LINEAR_ALF +#if JVET_N0415_CTB_ALF + m_filter5x5Blk(m_classifier, recYuv, buf, blkDst, blkSrc, compID, m_chromaCoeffFinal, m_chromaClippFinal, m_clpRngs.comp[compIdx], cs + , m_alfVBChmaCTUHeight + , ((yPos + pcv.maxCUHeight >= pcv.lumaHeight) ? pcv.lumaHeight : m_alfVBChmaPos)); +#else + m_filter5x5Blk(m_classifier, recYuv, buf, blkDst, blkSrc, compID, alfSliceParam.chromaCoeff, m_chromaClippFinal, m_clpRngs.comp[compIdx], cs + , m_alfVBChmaCTUHeight + , ((yPos + pcv.maxCUHeight >= pcv.lumaHeight) ? pcv.lumaHeight : m_alfVBChmaPos) + ); +#endif +#else +#if JVET_N0415_CTB_ALF + m_filter5x5Blk(m_classifier, recYuv, buf, blkDst, blkSrc, compID, m_chromaCoeffFinal, m_clpRngs.comp[compIdx], cs + , m_alfVBChmaCTUHeight + , ((yPos + pcv.maxCUHeight >= pcv.lumaHeight) ? pcv.lumaHeight : m_alfVBChmaPos) + ); +#else + m_filter5x5Blk(m_classifier, recYuv, buf, blkDst, blkSrc, compID, alfSliceParam.chromaCoeff, m_clpRngs.comp[compIdx], cs + , m_alfVBChmaCTUHeight + , ((yPos + pcv.maxCUHeight >= pcv.lumaHeight) ? pcv.lumaHeight : m_alfVBChmaPos) + ); +#endif +#endif +#else + +#if JVET_N0242_NON_LINEAR_ALF +#if JVET_N0415_CTB_ALF + m_filter5x5Blk(m_classifier, recYuv, buf, blkDst, blkSrc, compID, m_chromaCoeffFinal, m_chromaClippFinal, m_clpRngs.comp[compIdx], cs); +#else + m_filter5x5Blk(m_classifier, recYuv, buf, blkDst, blkSrc, compID, alfSliceParam.chromaCoeff, m_chromaClippFinal, m_clpRngs.comp[compIdx], cs); +#endif +#else +#if JVET_N0415_CTB_ALF + m_filter5x5Blk(m_classifier, recYuv, buf, blkDst, blkSrc, compID, m_chromaCoeffFinal, m_clpRngs.comp[compIdx], cs); +#else + m_filter5x5Blk(m_classifier, recYuv, buf, blkDst, blkSrc, compID, alfSliceParam.chromaCoeff, m_clpRngs.comp[compIdx], cs); +#endif +#endif +#endif + } + } + + xStart = xEnd; + } + + yStart = yEnd; + } + } + else + { +#endif const UnitArea area( cs.area.chromaFormat, Area( xPos, yPos, width, height ) ); if( m_ctuEnableFlag[COMPONENT_Y][ctuIdx] ) { Area blk( xPos, yPos, width, height ); +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + deriveClassification( m_classifier, tmpYuv.get( COMPONENT_Y ), blk, blk ); +#else deriveClassification( m_classifier, tmpYuv.get( COMPONENT_Y ), blk ); +#endif Area blkPCM(xPos, yPos, width, height); resetPCMBlkClassInfo(cs, m_classifier, tmpYuv.get(COMPONENT_Y), blkPCM); #if JVET_N0415_CTB_ALF @@ -313,43 +528,87 @@ void AdaptiveLoopFilter::ALFProcess( CodingStructure& cs, AlfSliceParam& alfSlic } #if JVET_N0180_ALF_LINE_BUFFER_REDUCTION #if JVET_N0242_NON_LINEAR_ALF +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + m_filter7x7Blk(m_classifier, recYuv, tmpYuv, blk, blk, COMPONENT_Y, coeff, clip, m_clpRngs.comp[COMPONENT_Y], cs + , m_alfVBLumaCTUHeight + , ((yPos + pcv.maxCUHeight >= pcv.lumaHeight) ? pcv.lumaHeight : m_alfVBLumaPos) + ); +#else m_filter7x7Blk(m_classifier, recYuv, tmpYuv, blk, COMPONENT_Y, coeff, clip, m_clpRngs.comp[COMPONENT_Y], cs , m_alfVBLumaCTUHeight , ((yPos + pcv.maxCUHeight >= pcv.lumaHeight) ? pcv.lumaHeight : m_alfVBLumaPos) ); +#endif +#else +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + m_filter7x7Blk(m_classifier, recYuv, tmpYuv, blk, blk, COMPONENT_Y, coeff, m_clpRngs.comp[COMPONENT_Y], cs + , m_alfVBLumaCTUHeight + , ((yPos + pcv.maxCUHeight >= pcv.lumaHeight) ? pcv.lumaHeight : m_alfVBLumaPos) + ); #else m_filter7x7Blk(m_classifier, recYuv, tmpYuv, blk, COMPONENT_Y, coeff, m_clpRngs.comp[COMPONENT_Y], cs , m_alfVBLumaCTUHeight , ((yPos + pcv.maxCUHeight >= pcv.lumaHeight) ? pcv.lumaHeight : m_alfVBLumaPos) ); #endif +#endif #else #if JVET_N0242_NON_LINEAR_ALF +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + m_filter7x7Blk(m_classifier, recYuv, tmpYuv, blk, blk, COMPONENT_Y, coeff, clip, m_clpRngs.comp[COMPONENT_Y], cs); +#else m_filter7x7Blk(m_classifier, recYuv, tmpYuv, blk, COMPONENT_Y, coeff, clip, m_clpRngs.comp[COMPONENT_Y], cs); +#endif +#else +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + m_filter7x7Blk(m_classifier, recYuv, tmpYuv, blk, blk, COMPONENT_Y, coeff, m_clpRngs.comp[COMPONENT_Y], cs); #else m_filter7x7Blk(m_classifier, recYuv, tmpYuv, blk, COMPONENT_Y, coeff, m_clpRngs.comp[COMPONENT_Y], cs); #endif #endif +#endif #else #if JVET_N0180_ALF_LINE_BUFFER_REDUCTION #if JVET_N0242_NON_LINEAR_ALF +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + m_filter7x7Blk(m_classifier, recYuv, tmpYuv, blk, blk, COMPONENT_Y, m_coeffFinal, m_clippFinal, m_clpRngs.comp[COMPONENT_Y], cs + , m_alfVBLumaCTUHeight + , ((yPos + pcv.maxCUHeight >= pcv.lumaHeight) ? pcv.lumaHeight : m_alfVBLumaPos) + ); +#else m_filter7x7Blk(m_classifier, recYuv, tmpYuv, blk, COMPONENT_Y, m_coeffFinal, m_clippFinal, m_clpRngs.comp[COMPONENT_Y], cs , m_alfVBLumaCTUHeight , ((yPos + pcv.maxCUHeight >= pcv.lumaHeight) ? pcv.lumaHeight : m_alfVBLumaPos) ); +#endif +#else +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + m_filter7x7Blk(m_classifier, recYuv, tmpYuv, blk, blk, COMPONENT_Y, m_coeffFinal, m_clpRngs.comp[COMPONENT_Y], cs + , m_alfVBLumaCTUHeight + , ((yPos + pcv.maxCUHeight >= pcv.lumaHeight) ? pcv.lumaHeight : m_alfVBLumaPos) + ); #else m_filter7x7Blk(m_classifier, recYuv, tmpYuv, blk, COMPONENT_Y, m_coeffFinal, m_clpRngs.comp[COMPONENT_Y], cs , m_alfVBLumaCTUHeight , ((yPos + pcv.maxCUHeight >= pcv.lumaHeight) ? pcv.lumaHeight : m_alfVBLumaPos) ); #endif +#endif #else #if JVET_N0242_NON_LINEAR_ALF +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + m_filter7x7Blk(m_classifier, recYuv, tmpYuv, blk, blk, COMPONENT_Y, m_coeffFinal, m_clippFinal, m_clpRngs.comp[COMPONENT_Y], cs); +#else m_filter7x7Blk(m_classifier, recYuv, tmpYuv, blk, COMPONENT_Y, m_coeffFinal, m_clippFinal, m_clpRngs.comp[COMPONENT_Y], cs); +#endif +#else +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + m_filter7x7Blk(m_classifier, recYuv, tmpYuv, blk, blk, COMPONENT_Y, m_coeffFinal, m_clpRngs.comp[COMPONENT_Y], cs); #else m_filter7x7Blk(m_classifier, recYuv, tmpYuv, blk, COMPONENT_Y, m_coeffFinal, m_clpRngs.comp[COMPONENT_Y], cs); #endif #endif +#endif #endif } @@ -362,6 +621,48 @@ void AdaptiveLoopFilter::ALFProcess( CodingStructure& cs, AlfSliceParam& alfSlic if( m_ctuEnableFlag[compIdx][ctuIdx] ) { Area blk( xPos >> chromaScaleX, yPos >> chromaScaleY, width >> chromaScaleX, height >> chromaScaleY ); +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND +#if JVET_N0180_ALF_LINE_BUFFER_REDUCTION +#if JVET_N0242_NON_LINEAR_ALF +#if JVET_N0415_CTB_ALF + m_filter5x5Blk(m_classifier, recYuv, tmpYuv, blk, blk, compID, m_chromaCoeffFinal, m_chromaClippFinal, m_clpRngs.comp[compIdx], cs + , m_alfVBChmaCTUHeight + , ((yPos + pcv.maxCUHeight >= pcv.lumaHeight) ? pcv.lumaHeight : m_alfVBChmaPos)); +#else + m_filter5x5Blk(m_classifier, recYuv, tmpYuv, blk, blk, compID, alfSliceParam.chromaCoeff, m_chromaClippFinal, m_clpRngs.comp[compIdx], cs + , m_alfVBChmaCTUHeight + , ((yPos + pcv.maxCUHeight >= pcv.lumaHeight) ? pcv.lumaHeight : m_alfVBChmaPos) + ); +#endif +#else +#if JVET_N0415_CTB_ALF + m_filter5x5Blk(m_classifier, recYuv, tmpYuv, blk, blk, compID, m_chromaCoeffFinal, m_clpRngs.comp[compIdx], cs + , m_alfVBChmaCTUHeight + , ((yPos + pcv.maxCUHeight >= pcv.lumaHeight) ? pcv.lumaHeight : m_alfVBChmaPos) + ); +#else + m_filter5x5Blk(m_classifier, recYuv, tmpYuv, blk, blk, compID, alfSliceParam.chromaCoeff, m_clpRngs.comp[compIdx], cs + , m_alfVBChmaCTUHeight + , ((yPos + pcv.maxCUHeight >= pcv.lumaHeight) ? pcv.lumaHeight : m_alfVBChmaPos) + ); +#endif +#endif +#else +#if JVET_N0242_NON_LINEAR_ALF +#if JVET_N0415_CTB_ALF + m_filter5x5Blk(m_classifier, recYuv, tmpYuv, blk, blk, compID, m_chromaCoeffFinal, m_chromaClippFinal, m_clpRngs.comp[compIdx], cs); +#else + m_filter5x5Blk( m_classifier, recYuv, tmpYuv, blk, blk, compID, alfSliceParam.chromaCoeff, m_chromaClippFinal, m_clpRngs.comp[compIdx], cs); +#endif +#else +#if JVET_N0415_CTB_ALF + m_filter5x5Blk(m_classifier, recYuv, tmpYuv, blk, blk, compID, m_chromaCoeffFinal, m_clpRngs.comp[compIdx], cs); +#else + m_filter5x5Blk( m_classifier, recYuv, tmpYuv, blk, blk, compID, alfSliceParam.chromaCoeff, m_clpRngs.comp[compIdx], cs); +#endif +#endif +#endif +#else #if JVET_N0180_ALF_LINE_BUFFER_REDUCTION #if JVET_N0242_NON_LINEAR_ALF #if JVET_N0415_CTB_ALF @@ -401,9 +702,13 @@ void AdaptiveLoopFilter::ALFProcess( CodingStructure& cs, AlfSliceParam& alfSlic m_filter5x5Blk( m_classifier, recYuv, tmpYuv, blk, compID, alfSliceParam.chromaCoeff, m_clpRngs.comp[compIdx], cs ); #endif #endif +#endif #endif } } +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + } +#endif ctuIdx++; } } @@ -641,6 +946,10 @@ void AdaptiveLoopFilter::create( const int picWidth, const int picHeight, const m_tempBuf.destroy(); m_tempBuf.create( format, Area( 0, 0, picWidth, picHeight ), maxCUWidth, MAX_ALF_FILTER_LENGTH >> 1, 0, false ); +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + m_tempBuf2.destroy(); + m_tempBuf2.create( format, Area( 0, 0, maxCUWidth + (MAX_ALF_PADDING_SIZE << 1), maxCUHeight + (MAX_ALF_PADDING_SIZE << 1) ), maxCUWidth, MAX_ALF_PADDING_SIZE, 0, false ); +#endif // Laplacian based activity for( int i = 0; i < NUM_DIRECTIONS; i++ ) @@ -735,13 +1044,20 @@ void AdaptiveLoopFilter::destroy() } m_tempBuf.destroy(); +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + m_tempBuf2.destroy(); +#endif #if JVET_N0415_CTB_ALF m_created = false; #endif } +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND +void AdaptiveLoopFilter::deriveClassification( AlfClassifier** classifier, const CPelBuf& srcLuma, const Area& blkDst, const Area& blk ) +#else void AdaptiveLoopFilter::deriveClassification( AlfClassifier** classifier, const CPelBuf& srcLuma, const Area& blk ) +#endif { int height = blk.pos().y + blk.height; int width = blk.pos().x + blk.width; @@ -753,15 +1069,25 @@ void AdaptiveLoopFilter::deriveClassification( AlfClassifier** classifier, const for( int j = blk.pos().x; j < width; j += m_CLASSIFICATION_BLK_SIZE ) { int nWidth = std::min( j + m_CLASSIFICATION_BLK_SIZE, width ) - j; -#if JVET_N0180_ALF_LINE_BUFFER_REDUCTION +#if JVET_N0180_ALF_LINE_BUFFER_REDUCTION +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + m_deriveClassificationBlk(classifier, m_laplacian, srcLuma, Area( j - blk.pos().x + blkDst.pos().x, i - blk.pos().y + blkDst.pos().y, nWidth, nHeight ), Area(j, i, nWidth, nHeight), m_inputBitDepth[CHANNEL_TYPE_LUMA] + 4 + , m_alfVBLumaCTUHeight + , ((i - blk.pos().y + blkDst.pos().y + nHeight >= m_picHeight) ? m_picHeight : m_alfVBLumaPos) + ); +#else m_deriveClassificationBlk(classifier, m_laplacian, srcLuma, Area(j, i, nWidth, nHeight), m_inputBitDepth[CHANNEL_TYPE_LUMA] + 4 , m_alfVBLumaCTUHeight , ((i + nHeight >= m_picHeight) ? m_picHeight : m_alfVBLumaPos) ); +#endif +#else +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + m_deriveClassificationBlk(classifier, m_laplacian, srcLuma, Area(j - blk.pos().x + blkDst.pos().x, i - blk.pos().y + blkDst.pos().y, nWidth, nHeight), Area(j, i, nWidth, nHeight), m_inputBitDepth[CHANNEL_TYPE_LUMA] + 4); #else m_deriveClassificationBlk(classifier, m_laplacian, srcLuma, Area(j, i, nWidth, nHeight), m_inputBitDepth[CHANNEL_TYPE_LUMA] + 4); #endif - +#endif } } } @@ -815,11 +1141,19 @@ void AdaptiveLoopFilter::resetPCMBlkClassInfo(CodingStructure & cs, AlfClassifi } } -#if JVET_N0180_ALF_LINE_BUFFER_REDUCTION +#if JVET_N0180_ALF_LINE_BUFFER_REDUCTION +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND +void AdaptiveLoopFilter::deriveClassificationBlk(AlfClassifier** classifier, int** laplacian[NUM_DIRECTIONS], const CPelBuf& srcLuma, const Area& blkDst, const Area& blk, const int shift, int vbCTUHeight, int vbPos) +#else void AdaptiveLoopFilter::deriveClassificationBlk(AlfClassifier** classifier, int** laplacian[NUM_DIRECTIONS], const CPelBuf& srcLuma, const Area& blk, const int shift, int vbCTUHeight, int vbPos) +#endif +#else +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND +void AdaptiveLoopFilter::deriveClassificationBlk(AlfClassifier** classifier, int** laplacian[NUM_DIRECTIONS], const CPelBuf& srcLuma, const Area& blkDst, const Area& blk, const int shift) #else void AdaptiveLoopFilter::deriveClassificationBlk(AlfClassifier** classifier, int** laplacian[NUM_DIRECTIONS], const CPelBuf& srcLuma, const Area& blk, const int shift) #endif +#endif { static const int th[16] = { 0, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4 }; const int stride = srcLuma.stride; @@ -846,12 +1180,20 @@ void AdaptiveLoopFilter::deriveClassificationBlk(AlfClassifier** classifier, int const Pel *src1 = &src[yoffset]; const Pel *src2 = &src[yoffset + stride]; const Pel *src3 = &src[yoffset + stride * 2]; -#if JVET_N0180_ALF_LINE_BUFFER_REDUCTION +#if JVET_N0180_ALF_LINE_BUFFER_REDUCTION +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + if (((blkDst.pos().y - 2 + i) > 0) && ((blkDst.pos().y - 2 + i) % vbCTUHeight) == (vbPos - 2)) +#else if (((posY - 2 + i) > 0) && ((posY - 2 + i) % vbCTUHeight) == (vbPos - 2)) +#endif { src3 = &src[yoffset + stride]; } +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + else if (((blkDst.pos().y - 2 + i) > 0) && ((blkDst.pos().y - 2 + i) % vbCTUHeight) == vbPos) +#else else if (((posY - 2 + i) > 0) && ((posY - 2 + i) % vbCTUHeight) == vbPos) +#endif { src0 = &src[yoffset]; } @@ -921,14 +1263,22 @@ void AdaptiveLoopFilter::deriveClassificationBlk(AlfClassifier** classifier, int { #if JVET_N0180_ALF_LINE_BUFFER_REDUCTION int sumV = 0; int sumH = 0; int sumD0 = 0; int sumD1 = 0; +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + if (((i + blkDst.pos().y) % vbCTUHeight) == (vbPos - 4)) +#else if (((i + posY) % vbCTUHeight) == (vbPos - 4)) +#endif { sumV = pYver[j] + pYver2[j] + pYver4[j]; sumH = pYhor[j] + pYhor2[j] + pYhor4[j]; sumD0 = pYdig0[j] + pYdig02[j] + pYdig04[j]; sumD1 = pYdig1[j] + pYdig12[j] + pYdig14[j]; } +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + else if (((i + blkDst.pos().y) % vbCTUHeight) == vbPos) +#else else if (((i + posY) % vbCTUHeight) == vbPos) +#endif { sumV = pYver2[j] + pYver4[j] + pYver6[j]; sumH = pYhor2[j] + pYhor4[j] + pYhor6[j]; @@ -952,7 +1302,11 @@ void AdaptiveLoopFilter::deriveClassificationBlk(AlfClassifier** classifier, int int tempAct = sumV + sumH; #if JVET_N0180_ALF_LINE_BUFFER_REDUCTION int activity = 0; +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + if ((((i + blkDst.pos().y) % vbCTUHeight) == (vbPos - 4)) || (((i + blkDst.pos().y) % vbCTUHeight) == vbPos)) +#else if ((((i + posY) % vbCTUHeight) == (vbPos - 4)) || (((i + posY) % vbCTUHeight) == vbPos)) +#endif { activity = (Pel)Clip3<int>(0, maxActivity, (tempAct * 96) >> shift); } @@ -1024,8 +1378,13 @@ void AdaptiveLoopFilter::deriveClassificationBlk(AlfClassifier** classifier, int static const int transposeTable[8] = { 0, 1, 0, 2, 2, 3, 1, 3 }; int transposeIdx = transposeTable[mainDirection * 2 + ( secondaryDirection >> 1 )]; +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + int yOffset = i + blkDst.pos().y; + int xOffset = j + blkDst.pos().x; +#else int yOffset = i + posY; int xOffset = j + posX; +#endif AlfClassifier *cl0 = classifier[yOffset] + xOffset; AlfClassifier *cl1 = classifier[yOffset + 1] + xOffset; @@ -1039,18 +1398,33 @@ void AdaptiveLoopFilter::deriveClassificationBlk(AlfClassifier** classifier, int template<AlfFilterType filtType> #if JVET_N0180_ALF_LINE_BUFFER_REDUCTION #if JVET_N0242_NON_LINEAR_ALF +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND +void AdaptiveLoopFilter::filterBlk(AlfClassifier** classifier, const PelUnitBuf &recDst, const CPelUnitBuf& recSrc, const Area& blkDst, const Area& blk, const ComponentID compId, short* filterSet, short* fClipSet, const ClpRng& clpRng, CodingStructure& cs, int vbCTUHeight, int vbPos) +#else void AdaptiveLoopFilter::filterBlk(AlfClassifier** classifier, const PelUnitBuf &recDst, const CPelUnitBuf& recSrc, const Area& blk, const ComponentID compId, short* filterSet, short* fClipSet, const ClpRng& clpRng, CodingStructure& cs, int vbCTUHeight, int vbPos) +#endif +#else +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND +void AdaptiveLoopFilter::filterBlk(AlfClassifier** classifier, const PelUnitBuf &recDst, const CPelUnitBuf& recSrc, const Area& blkDst, const Area& blk, const ComponentID compId, short* filterSet, const ClpRng& clpRng, CodingStructure& cs, int vbCTUHeight, int vbPos) #else void AdaptiveLoopFilter::filterBlk(AlfClassifier** classifier, const PelUnitBuf &recDst, const CPelUnitBuf& recSrc, const Area& blk, const ComponentID compId, short* filterSet, const ClpRng& clpRng, CodingStructure& cs, int vbCTUHeight, int vbPos) #endif +#endif #else #if JVET_N0242_NON_LINEAR_ALF +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND +void AdaptiveLoopFilter::filterBlk(AlfClassifier** classifier, const PelUnitBuf &recDst, const CPelUnitBuf& recSrc, const Area& blkDst, const Area& blk, const ComponentID compId, short* filterSet, short* fClipSet, const ClpRng& clpRng, CodingStructure& cs) +#else void AdaptiveLoopFilter::filterBlk(AlfClassifier** classifier, const PelUnitBuf &recDst, const CPelUnitBuf& recSrc, const Area& blk, const ComponentID compId, short* filterSet, short* fClipSet, const ClpRng& clpRng, CodingStructure& cs) +#endif +#else +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND +void AdaptiveLoopFilter::filterBlk(AlfClassifier** classifier, const PelUnitBuf &recDst, const CPelUnitBuf& recSrc, const Area& blkDst, const Area& blk, const ComponentID compId, short* filterSet, const ClpRng& clpRng, CodingStructure& cs) #else void AdaptiveLoopFilter::filterBlk(AlfClassifier** classifier, const PelUnitBuf &recDst, const CPelUnitBuf& recSrc, const Area& blk, const ComponentID compId, short* filterSet, const ClpRng& clpRng, CodingStructure& cs) #endif #endif - +#endif { const bool bChroma = isChroma( compId ); if( bChroma ) @@ -1074,7 +1448,11 @@ void AdaptiveLoopFilter::filterBlk(AlfClassifier** classifier, const PelUnitBuf const int endWidth = blk.x + blk.width; const Pel* src = srcLuma.buf; +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + Pel* dst = dstLuma.buf + blkDst.y * dstStride; +#else Pel* dst = dstLuma.buf + startHeight * dstStride; +#endif const Pel *pImgYPad0, *pImgYPad1, *pImgYPad2, *pImgYPad3, *pImgYPad4, *pImgYPad5, *pImgYPad6; const Pel *pImg0, *pImg1, *pImg2, *pImg3, *pImg4, *pImg5, *pImg6; @@ -1119,14 +1497,22 @@ void AdaptiveLoopFilter::filterBlk(AlfClassifier** classifier, const PelUnitBuf pImgYPad5 = pImgYPad3 + srcStride; pImgYPad6 = pImgYPad4 - srcStride; +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + Pel* pRec0 = dst + blkDst.x; +#else Pel* pRec0 = dst + startWidth; +#endif Pel* pRec1 = pRec0 + dstStride; for( int i = 0; i < endHeight - startHeight; i += clsSizeY ) { if( !bChroma ) { +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + pClass = classifier[blkDst.y + i] + blkDst.x; +#else pClass = classifier[startHeight + i] + startWidth; +#endif } for( int j = 0; j < endWidth - startWidth; j += clsSizeX ) @@ -1155,7 +1541,11 @@ void AdaptiveLoopFilter::filterBlk(AlfClassifier** classifier, const PelUnitBuf { for( blkX=0; blkX<4; blkX+=2 ) { +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + Position pos(j + blkDst.x + blkX, i + blkDst.y + blkY); +#else Position pos(j+startWidth+blkX, i+startHeight+blkY); +#endif CodingUnit* cu = isDualTree ? cs.getCU(pos, CH_C) : cs.getCU(recalcPosition(nChromaFormat, CH_C, CH_L, pos), CH_L); *flags++ = cu->ipcm ? 1 : 0; } @@ -1245,6 +1635,28 @@ void AdaptiveLoopFilter::filterBlk(AlfClassifier** classifier, const PelUnitBuf pRec1 = pRec0 + j + ii * dstStride; #if JVET_N0180_ALF_LINE_BUFFER_REDUCTION +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + if ((blkDst.y + i + ii) % vbCTUHeight < vbPos && ((blkDst.y + i + ii) % vbCTUHeight >= vbPos - (bChroma ? 2 : 4))) //above + { + pImg1 = ((blkDst.y + i + ii) % vbCTUHeight == vbPos - 1) ? pImg0 : pImg1; + pImg3 = ((blkDst.y + i + ii) % vbCTUHeight >= vbPos - 2) ? pImg1 : pImg3; + pImg5 = ((blkDst.y + i + ii) % vbCTUHeight >= vbPos - 3) ? pImg3 : pImg5; + + pImg2 = ((blkDst.y + i + ii) % vbCTUHeight == vbPos - 1) ? pImg0 : pImg2; + pImg4 = ((blkDst.y + i + ii) % vbCTUHeight >= vbPos - 2) ? pImg2 : pImg4; + pImg6 = ((blkDst.y + i + ii) % vbCTUHeight >= vbPos - 3) ? pImg4 : pImg6; + } + else if ((blkDst.y + i + ii) % vbCTUHeight >= vbPos && ((blkDst.y + i + ii) % vbCTUHeight <= vbPos + (bChroma ? 1 : 3))) //bottom + { + pImg2 = ((blkDst.y + i + ii) % vbCTUHeight == vbPos) ? pImg0 : pImg2; + pImg4 = ((blkDst.y + i + ii) % vbCTUHeight <= vbPos + 1) ? pImg2 : pImg4; + pImg6 = ((blkDst.y + i + ii) % vbCTUHeight <= vbPos + 2) ? pImg4 : pImg6; + + pImg1 = ((blkDst.y + i + ii) % vbCTUHeight == vbPos) ? pImg0 : pImg1; + pImg3 = ((blkDst.y + i + ii) % vbCTUHeight <= vbPos + 1) ? pImg1 : pImg3; + pImg5 = ((blkDst.y + i + ii) % vbCTUHeight <= vbPos + 2) ? pImg3 : pImg5; + } +#else if ((startHeight + i + ii) % vbCTUHeight < vbPos && ((startHeight + i + ii) % vbCTUHeight >= vbPos - (bChroma ? 2 : 4))) //above { pImg1 = ((startHeight + i + ii) % vbCTUHeight == vbPos - 1) ? pImg0 : pImg1; @@ -1265,6 +1677,7 @@ void AdaptiveLoopFilter::filterBlk(AlfClassifier** classifier, const PelUnitBuf pImg3 = ((startHeight + i + ii) % vbCTUHeight <= vbPos + 1) ? pImg1 : pImg3; pImg5 = ((startHeight + i + ii) % vbCTUHeight <= vbPos + 2) ? pImg3 : pImg5; } +#endif #endif for( int jj = 0; jj < clsSizeX; jj++ ) diff --git a/source/Lib/CommonLib/AdaptiveLoopFilter.h b/source/Lib/CommonLib/AdaptiveLoopFilter.h index b41fd6ff907271bd4b7a539a937de7fa4168d253..92df73d438e4773599de45f9135599b7f8e4c4c8 100644 --- a/source/Lib/CommonLib/AdaptiveLoopFilter.h +++ b/source/Lib/CommonLib/AdaptiveLoopFilter.h @@ -94,26 +94,51 @@ public: #endif void create( const int picWidth, const int picHeight, const ChromaFormat format, const int maxCUWidth, const int maxCUHeight, const int maxCUDepth, const int inputBitDepth[MAX_NUM_CHANNEL_TYPE] ); void destroy(); +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND +#if JVET_N0180_ALF_LINE_BUFFER_REDUCTION + static void deriveClassificationBlk(AlfClassifier** classifier, int** laplacian[NUM_DIRECTIONS], const CPelBuf& srcLuma, const Area& blkDst, const Area& blk, const int shift, int vbCTUHeight, int vbPos); +#else + static void deriveClassificationBlk(AlfClassifier** classifier, int** laplacian[NUM_DIRECTIONS], const CPelBuf& srcLuma, const Area& blkDst, const Area& blk, const int shift); +#endif + void deriveClassification( AlfClassifier** classifier, const CPelBuf& srcLuma, const Area& blkDst, const Area& blk ); +#else #if JVET_N0180_ALF_LINE_BUFFER_REDUCTION static void deriveClassificationBlk(AlfClassifier** classifier, int** laplacian[NUM_DIRECTIONS], const CPelBuf& srcLuma, const Area& blk, const int shift, int vbCTUHeight, int vbPos); #else static void deriveClassificationBlk(AlfClassifier** classifier, int** laplacian[NUM_DIRECTIONS], const CPelBuf& srcLuma, const Area& blk, const int shift); #endif void deriveClassification( AlfClassifier** classifier, const CPelBuf& srcLuma, const Area& blk ); +#endif void resetPCMBlkClassInfo(CodingStructure & cs, AlfClassifier** classifier, const CPelBuf& srcLuma, const Area& blk); template<AlfFilterType filtType> #if JVET_N0180_ALF_LINE_BUFFER_REDUCTION #if JVET_N0242_NON_LINEAR_ALF +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + static void filterBlk(AlfClassifier** classifier, const PelUnitBuf &recDst, const CPelUnitBuf& recSrc, const Area& blkDst, const Area& blk, const ComponentID compId, short* filterSet, short* fClipSet, const ClpRng& clpRng, CodingStructure& cs, int vbCTUHeight, int vbPos); +#else static void filterBlk(AlfClassifier** classifier, const PelUnitBuf &recDst, const CPelUnitBuf& recSrc, const Area& blk, const ComponentID compId, short* filterSet, short* fClipSet, const ClpRng& clpRng, CodingStructure& cs, int vbCTUHeight, int vbPos); +#endif +#else +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + static void filterBlk(AlfClassifier** classifier, const PelUnitBuf &recDst, const CPelUnitBuf& recSrc, const Area& blkDst, const Area& blk, const ComponentID compId, short* filterSet, const ClpRng& clpRng, CodingStructure& cs, int vbCTUHeight, int vbPos); #else static void filterBlk(AlfClassifier** classifier, const PelUnitBuf &recDst, const CPelUnitBuf& recSrc, const Area& blk, const ComponentID compId, short* filterSet, const ClpRng& clpRng, CodingStructure& cs, int vbCTUHeight, int vbPos); #endif +#endif #else #if JVET_N0242_NON_LINEAR_ALF +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + static void filterBlk(AlfClassifier** classifier, const PelUnitBuf &recDst, const CPelUnitBuf& recSrc, const Area& blkDst, const Area& blk, const ComponentID compId, short* filterSet, short* fClipSet, const ClpRng& clpRng, CodingStructure& cs); +#else static void filterBlk(AlfClassifier** classifier, const PelUnitBuf &recDst, const CPelUnitBuf& recSrc, const Area& blk, const ComponentID compId, short* filterSet, short* fClipSet, const ClpRng& clpRng, CodingStructure& cs); +#endif +#else +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + static void filterBlk(AlfClassifier** classifier, const PelUnitBuf &recDst, const CPelUnitBuf& recSrc, const Area& blkDst, const Area& blk, const ComponentID compId, short* filterSet, const ClpRng& clpRng, CodingStructure& cs); #else static void filterBlk(AlfClassifier** classifier, const PelUnitBuf &recDst, const CPelUnitBuf& recSrc, const Area& blk, const ComponentID compId, short* filterSet, const ClpRng& clpRng, CodingStructure& cs); #endif +#endif #endif inline static int getMaxGolombIdx( AlfFilterType filterType ) { @@ -121,28 +146,56 @@ public: } #if JVET_N0180_ALF_LINE_BUFFER_REDUCTION +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + void(*m_deriveClassificationBlk)(AlfClassifier** classifier, int** laplacian[NUM_DIRECTIONS], const CPelBuf& srcLuma, const Area& blkDst, const Area& blk, const int shift, int vbCTUHeight, int vbPos); +#else void(*m_deriveClassificationBlk)(AlfClassifier** classifier, int** laplacian[NUM_DIRECTIONS], const CPelBuf& srcLuma, const Area& blk, const int shift, int vbCTUHeight, int vbPos); +#endif +#else +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + void(*m_deriveClassificationBlk)(AlfClassifier** classifier, int** laplacian[NUM_DIRECTIONS], const CPelBuf& srcLuma, const Area& blkDst, const Area& blk, const int shift); #else void(*m_deriveClassificationBlk)(AlfClassifier** classifier, int** laplacian[NUM_DIRECTIONS], const CPelBuf& srcLuma, const Area& blk, const int shift); #endif +#endif #if JVET_N0180_ALF_LINE_BUFFER_REDUCTION #if JVET_N0242_NON_LINEAR_ALF +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + void(*m_filter5x5Blk)(AlfClassifier** classifier, const PelUnitBuf &recDst, const CPelUnitBuf& recSrc, const Area& blkDst, const Area& blk, const ComponentID compId, short* filterSet, short* fClipSet, const ClpRng& clpRng, CodingStructure& cs, int vbCTUHeight, int vbPos); + void(*m_filter7x7Blk)(AlfClassifier** classifier, const PelUnitBuf &recDst, const CPelUnitBuf& recSrc, const Area& blkDst, const Area& blk, const ComponentID compId, short* filterSet, short* fClipSet, const ClpRng& clpRng, CodingStructure& cs, int vbCTUHeight, int vbPos); +#else void(*m_filter5x5Blk)(AlfClassifier** classifier, const PelUnitBuf &recDst, const CPelUnitBuf& recSrc, const Area& blk, const ComponentID compId, short* filterSet, short* fClipSet, const ClpRng& clpRng, CodingStructure& cs, int vbCTUHeight, int vbPos); void(*m_filter7x7Blk)(AlfClassifier** classifier, const PelUnitBuf &recDst, const CPelUnitBuf& recSrc, const Area& blk, const ComponentID compId, short* filterSet, short* fClipSet, const ClpRng& clpRng, CodingStructure& cs, int vbCTUHeight, int vbPos); +#endif +#else +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + void(*m_filter5x5Blk)(AlfClassifier** classifier, const PelUnitBuf &recDst, const CPelUnitBuf& recSrc, const Area& blkDst, const Area& blk, const ComponentID compId, short* filterSet, const ClpRng& clpRng, CodingStructure& cs, int vbCTUHeight, int vbPos); + void(*m_filter7x7Blk)(AlfClassifier** classifier, const PelUnitBuf &recDst, const CPelUnitBuf& recSrc, const Area& blkDst, const Area& blk, const ComponentID compId, short* filterSet, const ClpRng& clpRng, CodingStructure& cs, int vbCTUHeight, int vbPos); #else void(*m_filter5x5Blk)(AlfClassifier** classifier, const PelUnitBuf &recDst, const CPelUnitBuf& recSrc, const Area& blk, const ComponentID compId, short* filterSet, const ClpRng& clpRng, CodingStructure& cs, int vbCTUHeight, int vbPos); void(*m_filter7x7Blk)(AlfClassifier** classifier, const PelUnitBuf &recDst, const CPelUnitBuf& recSrc, const Area& blk, const ComponentID compId, short* filterSet, const ClpRng& clpRng, CodingStructure& cs, int vbCTUHeight, int vbPos); #endif +#endif #else #if JVET_N0242_NON_LINEAR_ALF +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + void(*m_filter5x5Blk)(AlfClassifier** classifier, const PelUnitBuf &recDst, const CPelUnitBuf& recSrc, const Area& blkDst, const Area& blk, const ComponentID compId, short* filterSet, short* fClipSet, const ClpRng& clpRng, CodingStructure& cs); + void(*m_filter7x7Blk)(AlfClassifier** classifier, const PelUnitBuf &recDst, const CPelUnitBuf& recSrc, const Area& blkDst, const Area& blk, const ComponentID compId, short* filterSet, short* fClipSet, const ClpRng& clpRng, CodingStructure& cs); +#else void(*m_filter5x5Blk)(AlfClassifier** classifier, const PelUnitBuf &recDst, const CPelUnitBuf& recSrc, const Area& blk, const ComponentID compId, short* filterSet, short* fClipSet, const ClpRng& clpRng, CodingStructure& cs); void(*m_filter7x7Blk)(AlfClassifier** classifier, const PelUnitBuf &recDst, const CPelUnitBuf& recSrc, const Area& blk, const ComponentID compId, short* filterSet, short* fClipSet, const ClpRng& clpRng, CodingStructure& cs); +#endif +#else +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + void(*m_filter5x5Blk)(AlfClassifier** classifier, const PelUnitBuf &recDst, const CPelUnitBuf& recSrc, const Area& blkDst, const Area& blk, const ComponentID compId, short* filterSet, const ClpRng& clpRng, CodingStructure& cs); + void(*m_filter7x7Blk)(AlfClassifier** classifier, const PelUnitBuf &recDst, const CPelUnitBuf& recSrc, const Area& blkDst, const Area& blk, const ComponentID compId, short* filterSet, const ClpRng& clpRng, CodingStructure& cs); #else void(*m_filter5x5Blk)(AlfClassifier** classifier, const PelUnitBuf &recDst, const CPelUnitBuf& recSrc, const Area& blk, const ComponentID compId, short* filterSet, const ClpRng& clpRng, CodingStructure& cs); void(*m_filter7x7Blk)(AlfClassifier** classifier, const PelUnitBuf &recDst, const CPelUnitBuf& recSrc, const Area& blk, const ComponentID compId, short* filterSet, const ClpRng& clpRng, CodingStructure& cs); #endif #endif +#endif #ifdef TARGET_SIMD_X86 void initAdaptiveLoopFilterX86(); @@ -151,6 +204,9 @@ public: #endif protected: +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + bool isCrossedByVirtualBoundaries( const int xPos, const int yPos, const int width, const int height, bool& clipTop, bool& clipBottom, bool& clipLeft, bool& clipRight, int& numHorSplit, int& numVerSplit, int horSplit[], int verSplit[], const PPS* pps ); +#endif #if JVET_N0415_CTB_ALF static const int m_classToFilterMapping[NUM_FIXED_FILTER_SETS][MAX_NUM_ALF_CLASSES]; static const int m_fixedFilterSetCoeff[ALF_FIXED_FILTER_NUM][MAX_NUM_ALF_LUMA_COEFF]; @@ -176,6 +232,9 @@ protected: int** m_laplacian[NUM_DIRECTIONS]; uint8_t* m_ctuEnableFlag[MAX_NUM_COMPONENT]; PelStorage m_tempBuf; +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + PelStorage m_tempBuf2; +#endif int m_inputBitDepth[MAX_NUM_CHANNEL_TYPE]; int m_picWidth; int m_picHeight; diff --git a/source/Lib/CommonLib/LoopFilter.cpp b/source/Lib/CommonLib/LoopFilter.cpp index 60517cdc558cc2b1561e6bf466306b8a0cdeb44d..5cc285f94e425b9a77635cf92afe95079cac7320 100644 --- a/source/Lib/CommonLib/LoopFilter.cpp +++ b/source/Lib/CommonLib/LoopFilter.cpp @@ -271,6 +271,15 @@ void LoopFilter::xDeblockCU( CodingUnit& cu, const DeblockEdgeDir edgeDir ) const PreCalcValues& pcv = *cu.cs->pcv; const Area area = cu.Y().valid() ? cu.Y() : Area( recalcPosition( cu.chromaFormat, cu.chType, CHANNEL_TYPE_LUMA, cu.blocks[cu.chType].pos() ), recalcSize( cu.chromaFormat, cu.chType, CHANNEL_TYPE_LUMA, cu.blocks[cu.chType].size() ) ); +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + bool horEdgeFilter = false, verEdgeFilter = false; + int numHorVirBndry = 0, numVerVirBndry = 0; + int horVirBndryPos[] = { 0, 0, 0 }; + int verVirBndryPos[] = { 0, 0, 0 }; + + bool cuCrossedByVirtualBoundaries = isCrossedByVirtualBoundaries( area.x, area.y, area.width, area.height, numHorVirBndry, numVerVirBndry, horVirBndryPos, verVirBndryPos, cu.cs->slice->getPPS() ); +#endif + xSetLoopfilterParam( cu ); #if JVET_N0473_DEBLOCK_INTERNAL_TRANSFORM_BOUNDARIES static_vector<int, 2*MAX_CU_SIZE> edgeIdx; @@ -293,8 +302,19 @@ void LoopFilter::xDeblockCU( CodingUnit& cu, const DeblockEdgeDir edgeDir ) implicitTU = true; } #endif +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + verEdgeFilter = m_stLFCUParam.internalEdge; + horEdgeFilter = m_stLFCUParam.internalEdge; + if( cuCrossedByVirtualBoundaries ) + { + xDeriveEdgefilterParam( areaTu.x, areaTu.y, numVerVirBndry, numHorVirBndry, verVirBndryPos, horVirBndryPos, verEdgeFilter, horEdgeFilter ); + } + xSetEdgefilterMultiple( cu, EDGE_VER, areaTu, verEdgeFilter ); + xSetEdgefilterMultiple( cu, EDGE_HOR, areaTu, horEdgeFilter ); +#else xSetEdgefilterMultiple( cu, EDGE_VER, areaTu, m_stLFCUParam.internalEdge ); xSetEdgefilterMultiple( cu, EDGE_HOR, areaTu, m_stLFCUParam.internalEdge ); +#endif #if JVET_N0473_DEBLOCK_INTERNAL_TRANSFORM_BOUNDARIES xSetMaxFilterLengthPQFromTransformSizes( edgeDir, cu, currTU ); edgeIdx.push_back( ( edgeDir == EDGE_HOR ) ? ( currTU.blocks[cu.chType].y - cu.blocks[cu.chType].y ) / 4 : ( currTU.blocks[cu.chType].x - cu.blocks[cu.chType].x ) / 4 ); @@ -309,8 +329,20 @@ void LoopFilter::xDeblockCU( CodingUnit& cu, const DeblockEdgeDir edgeDir ) const bool xOff = currPU.blocks[cu.chType].x != cu.blocks[cu.chType].x; const bool yOff = currPU.blocks[cu.chType].y != cu.blocks[cu.chType].y; +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + verEdgeFilter = (xOff ? m_stLFCUParam.internalEdge : m_stLFCUParam.leftEdge); + horEdgeFilter = (yOff ? m_stLFCUParam.internalEdge : m_stLFCUParam.topEdge); + if( cuCrossedByVirtualBoundaries ) + { + xDeriveEdgefilterParam( areaPu.x, areaPu.y, numVerVirBndry, numHorVirBndry, verVirBndryPos, horVirBndryPos, verEdgeFilter, horEdgeFilter ); + } + + xSetEdgefilterMultiple( cu, EDGE_VER, areaPu, verEdgeFilter, xOff ); + xSetEdgefilterMultiple( cu, EDGE_HOR, areaPu, horEdgeFilter, yOff ); +#else xSetEdgefilterMultiple( cu, EDGE_VER, areaPu, (xOff ? m_stLFCUParam.internalEdge : m_stLFCUParam.leftEdge), xOff ); xSetEdgefilterMultiple( cu, EDGE_HOR, areaPu, (yOff ? m_stLFCUParam.internalEdge : m_stLFCUParam.topEdge), yOff ); +#endif #if JVET_N0473_DEBLOCK_INTERNAL_TRANSFORM_BOUNDARIES edgeIdx.push_back( ( edgeDir == EDGE_HOR ) ? ( currPU.blocks[cu.chType].y - cu.blocks[cu.chType].y ) / 4 : ( currPU.blocks[cu.chType].x - cu.blocks[cu.chType].x ) / 4 ); #endif @@ -323,7 +355,17 @@ void LoopFilter::xDeblockCU( CodingUnit& cu, const DeblockEdgeDir edgeDir ) for (uint32_t off = subBlockSize; off < areaPu.height; off += subBlockSize) { const Area mvBlockH(cu.Y().x, cu.Y().y + off, cu.Y().width, pcv.minCUHeight); +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + horEdgeFilter = m_stLFCUParam.internalEdge; + if( cuCrossedByVirtualBoundaries ) + { + xDeriveEdgefilterParam( mvBlockH.x, mvBlockH.y, 0, numHorVirBndry, verVirBndryPos, horVirBndryPos, verEdgeFilter, horEdgeFilter ); + } + + xSetEdgefilterMultiple(cu, EDGE_HOR, mvBlockH, horEdgeFilter, 1); +#else xSetEdgefilterMultiple(cu, EDGE_HOR, mvBlockH, m_stLFCUParam.internalEdge, 1); +#endif #if JVET_N0473_DEBLOCK_INTERNAL_TRANSFORM_BOUNDARIES edgeIdx.push_back( ( currPU.blocks[cu.chType].y + off - cu.blocks[cu.chType].y ) / 4 ); #endif @@ -334,7 +376,17 @@ void LoopFilter::xDeblockCU( CodingUnit& cu, const DeblockEdgeDir edgeDir ) for (uint32_t off = subBlockSize; off < areaPu.width; off += subBlockSize) { const Area mvBlockV(cu.Y().x + off, cu.Y().y, pcv.minCUWidth, cu.Y().height); +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + verEdgeFilter = m_stLFCUParam.internalEdge; + if( cuCrossedByVirtualBoundaries ) + { + xDeriveEdgefilterParam( mvBlockV.x, mvBlockV.y, numVerVirBndry, 0, verVirBndryPos, horVirBndryPos, verEdgeFilter, horEdgeFilter ); + } + + xSetEdgefilterMultiple(cu, EDGE_VER, mvBlockV, verEdgeFilter, 1); +#else xSetEdgefilterMultiple(cu, EDGE_VER, mvBlockV, m_stLFCUParam.internalEdge, 1); +#endif #if JVET_N0473_DEBLOCK_INTERNAL_TRANSFORM_BOUNDARIES edgeIdx.push_back( ( currPU.blocks[cu.chType].x + off - cu.blocks[cu.chType].x ) / 4 ); #endif @@ -360,7 +412,17 @@ void LoopFilter::xDeblockCU( CodingUnit& cu, const DeblockEdgeDir edgeDir ) for (uint32_t off = subBlockSize; off < area.width; off += subBlockSize) { const Area mvBlockV(cu.Y().x + off, cu.Y().y, pcv.minCUWidth, cu.Y().height); +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + verEdgeFilter = m_stLFCUParam.internalEdge; + if( cuCrossedByVirtualBoundaries ) + { + xDeriveEdgefilterParam( mvBlockV.x, mvBlockV.y, numVerVirBndry, 0, verVirBndryPos, horVirBndryPos, verEdgeFilter, horEdgeFilter ); + } + + xSetEdgefilterMultiple(cu, EDGE_VER, mvBlockV, verEdgeFilter, 1); +#else xSetEdgefilterMultiple(cu, EDGE_VER, mvBlockV, m_stLFCUParam.internalEdge, 1); +#endif #if JVET_N0473_DEBLOCK_INTERNAL_TRANSFORM_BOUNDARIES edgeIdx.push_back( off / 4 ); #endif @@ -373,7 +435,17 @@ void LoopFilter::xDeblockCU( CodingUnit& cu, const DeblockEdgeDir edgeDir ) for (uint32_t off = subBlockSize; off < area.height; off += subBlockSize) { const Area mvBlockH(cu.Y().x, cu.Y().y + off, cu.Y().width, pcv.minCUHeight); +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + horEdgeFilter = m_stLFCUParam.internalEdge; + if( cuCrossedByVirtualBoundaries ) + { + xDeriveEdgefilterParam( mvBlockH.x, mvBlockH.y, 0, numHorVirBndry, verVirBndryPos, horVirBndryPos, verEdgeFilter, horEdgeFilter ); + } + + xSetEdgefilterMultiple(cu, EDGE_HOR, mvBlockH, horEdgeFilter, 1); +#else xSetEdgefilterMultiple(cu, EDGE_HOR, mvBlockH, m_stLFCUParam.internalEdge, 1); +#endif #if JVET_N0473_DEBLOCK_INTERNAL_TRANSFORM_BOUNDARIES edgeIdx.push_back( off / 4 ); #endif @@ -547,6 +619,52 @@ void LoopFilter::xDeblockCU( CodingUnit& cu, const DeblockEdgeDir edgeDir ) #endif } +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND +inline bool LoopFilter::isCrossedByVirtualBoundaries(const int xPos, const int yPos, const int width, const int height, int& numHorVirBndry, int& numVerVirBndry, int horVirBndryPos[], int verVirBndryPos[], const PPS* pps) +{ + numHorVirBndry = 0; numVerVirBndry = 0; + if (pps->getLoopFilterAcrossVirtualBoundariesDisabledFlag()) + { + for (int i = 0; i < pps->getNumHorVirtualBoundaries(); i++) + { + if (yPos <= pps->getVirtualBoundariesPosY(i) && pps->getVirtualBoundariesPosY(i) < yPos + height) + { + horVirBndryPos[numHorVirBndry++] = pps->getVirtualBoundariesPosY(i); + } + } + for (int i = 0; i < pps->getNumVerVirtualBoundaries(); i++) + { + if (xPos <= pps->getVirtualBoundariesPosX(i) && pps->getVirtualBoundariesPosX(i) < xPos + width) + { + verVirBndryPos[numVerVirBndry++] = pps->getVirtualBoundariesPosX(i); + } + } + } + return numHorVirBndry > 0 || numVerVirBndry > 0; +} + +inline void LoopFilter::xDeriveEdgefilterParam( const int xPos, const int yPos, const int numVerVirBndry, const int numHorVirBndry, const int verVirBndryPos[], const int horVirBndryPos[], bool &verEdgeFilter, bool &horEdgeFilter ) +{ + for (int i = 0; i < numVerVirBndry; i++) + { + if (verVirBndryPos[i] == xPos) + { + verEdgeFilter = false; + break; + } + } + + for (int i = 0; i < numHorVirBndry; i++) + { + if (horVirBndryPos[i] == yPos) + { + horEdgeFilter = false; + break; + } + } +} +#endif + #if JVET_N0473_DEBLOCK_INTERNAL_TRANSFORM_BOUNDARIES void LoopFilter::xSetMaxFilterLengthPQFromTransformSizes( const DeblockEdgeDir edgeDir, const CodingUnit& cu, const TransformUnit& currTU ) { diff --git a/source/Lib/CommonLib/LoopFilter.h b/source/Lib/CommonLib/LoopFilter.h index a85f7b87ec05351b1f3feaad80b117e1ded87f02..b7e16d9ca5b371f36c2d4bea3c139572acc7bb55 100644 --- a/source/Lib/CommonLib/LoopFilter.h +++ b/source/Lib/CommonLib/LoopFilter.h @@ -104,6 +104,11 @@ private: inline unsigned BsSet(unsigned val, const ComponentID compIdx) const; inline unsigned BsGet(unsigned val, const ComponentID compIdx) const; +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + inline bool isCrossedByVirtualBoundaries ( const int xPos, const int yPos, const int width, const int height, int& numHorVirBndry, int& numVerVirBndry, int horVirBndryPos[], int verVirBndryPos[], const PPS* pps ); + inline void xDeriveEdgefilterParam ( const int xPos, const int yPos, const int numVerVirBndry, const int numHorVirBndry, const int verVirBndryPos[], const int horVirBndryPos[], bool &verEdgeFilter, bool &horEdgeFilter ); +#endif + inline int xCalcDP ( Pel* piSrc, const int iOffset ) const; inline int xCalcDQ ( Pel* piSrc, const int iOffset ) const; static const uint8_t sm_tcTable[MAX_QP + 3]; diff --git a/source/Lib/CommonLib/SampleAdaptiveOffset.cpp b/source/Lib/CommonLib/SampleAdaptiveOffset.cpp index 5339eb06fa854ac7b9ff0b96a77f1c43c2b1dffc..efcf45d71718a5f80494f82904cf42cf9aa10183 100644 --- a/source/Lib/CommonLib/SampleAdaptiveOffset.cpp +++ b/source/Lib/CommonLib/SampleAdaptiveOffset.cpp @@ -291,7 +291,11 @@ void SampleAdaptiveOffset::xReconstructBlkSAOParams(CodingStructure& cs, SAOBlkP void SampleAdaptiveOffset::offsetBlock(const int channelBitDepth, const ClpRng& clpRng, int typeIdx, int* offset , const Pel* srcBlk, Pel* resBlk, int srcStride, int resStride, int width, int height - , bool isLeftAvail, bool isRightAvail, bool isAboveAvail, bool isBelowAvail, bool isAboveLeftAvail, bool isAboveRightAvail, bool isBelowLeftAvail, bool isBelowRightAvail) + , bool isLeftAvail, bool isRightAvail, bool isAboveAvail, bool isBelowAvail, bool isAboveLeftAvail, bool isAboveRightAvail, bool isBelowLeftAvail, bool isBelowRightAvail +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + , bool isCTUCrossVirtualBoundaries, int horVirBndryPos[], int verVirBndryPos[], int numHorVirBndry, int numVerVirBndry +#endif + ) { int x,y, startX, startY, endX, endY, edgeType; int firstLineStartX, firstLineEndX, lastLineStartX, lastLineEndX; @@ -313,6 +317,13 @@ void SampleAdaptiveOffset::offsetBlock(const int channelBitDepth, const ClpRng& for (x=startX; x< endX; x++) { signRight = (int8_t)sgn(srcLine[x] - srcLine[x+1]); +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + if (isCTUCrossVirtualBoundaries && isProcessDisabled(x, y, numVerVirBndry, 0, verVirBndryPos, horVirBndryPos)) + { + signLeft = -signRight; + continue; + } +#endif edgeType = signRight + signLeft; signLeft = -signRight; @@ -351,6 +362,13 @@ void SampleAdaptiveOffset::offsetBlock(const int channelBitDepth, const ClpRng& for (x=0; x< width; x++) { signDown = (int8_t)sgn(srcLine[x] - srcLineBelow[x]); +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + if (isCTUCrossVirtualBoundaries && isProcessDisabled(x, y, 0, numHorVirBndry, verVirBndryPos, horVirBndryPos)) + { + signUpLine[x] = -signDown; + continue; + } +#endif edgeType = signDown + signUpLine[x]; signUpLine[x]= -signDown; @@ -386,6 +404,12 @@ void SampleAdaptiveOffset::offsetBlock(const int channelBitDepth, const ClpRng& firstLineEndX = isAboveAvail? endX: 1; for(x= firstLineStartX; x< firstLineEndX; x++) { +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + if (isCTUCrossVirtualBoundaries && isProcessDisabled(x, 0, numVerVirBndry, numHorVirBndry, verVirBndryPos, horVirBndryPos)) + { + continue; + } +#endif edgeType = sgn(srcLine[x] - srcLineAbove[x- 1]) - signUpLine[x+1]; resLine[x] = ClipPel<int>( srcLine[x] + offset[edgeType], clpRng); @@ -402,6 +426,13 @@ void SampleAdaptiveOffset::offsetBlock(const int channelBitDepth, const ClpRng& for (x=startX; x<endX; x++) { signDown = (int8_t)sgn(srcLine[x] - srcLineBelow[x+ 1]); +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + if (isCTUCrossVirtualBoundaries && isProcessDisabled(x, y, numVerVirBndry, numHorVirBndry, verVirBndryPos, horVirBndryPos)) + { + signDownLine[x + 1] = -signDown; + continue; + } +#endif edgeType = signDown + signUpLine[x]; resLine[x] = ClipPel<int>( srcLine[x] + offset[edgeType], clpRng); @@ -423,6 +454,12 @@ void SampleAdaptiveOffset::offsetBlock(const int channelBitDepth, const ClpRng& lastLineEndX = isBelowRightAvail ? width : (width -1); for(x= lastLineStartX; x< lastLineEndX; x++) { +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + if (isCTUCrossVirtualBoundaries && isProcessDisabled(x, height - 1, numVerVirBndry, numHorVirBndry, verVirBndryPos, horVirBndryPos)) + { + continue; + } +#endif edgeType = sgn(srcLine[x] - srcLineBelow[x+ 1]) + signUpLine[x]; resLine[x] = ClipPel<int>( srcLine[x] + offset[edgeType], clpRng); @@ -451,6 +488,12 @@ void SampleAdaptiveOffset::offsetBlock(const int channelBitDepth, const ClpRng& firstLineEndX = isAboveRightAvail ? width : (width-1); for(x= firstLineStartX; x< firstLineEndX; x++) { +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + if (isCTUCrossVirtualBoundaries && isProcessDisabled(x, 0, numVerVirBndry, numHorVirBndry, verVirBndryPos, horVirBndryPos)) + { + continue; + } +#endif edgeType = sgn(srcLine[x] - srcLineAbove[x+1]) -signUpLine[x-1]; resLine[x] = ClipPel<int>(srcLine[x] + offset[edgeType], clpRng); } @@ -465,6 +508,13 @@ void SampleAdaptiveOffset::offsetBlock(const int channelBitDepth, const ClpRng& for(x= startX; x< endX; x++) { signDown = (int8_t)sgn(srcLine[x] - srcLineBelow[x-1]); +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + if (isCTUCrossVirtualBoundaries && isProcessDisabled(x, y, numVerVirBndry, numHorVirBndry, verVirBndryPos, horVirBndryPos)) + { + signUpLine[x - 1] = -signDown; + continue; + } +#endif edgeType = signDown + signUpLine[x]; resLine[x] = ClipPel<int>(srcLine[x] + offset[edgeType], clpRng); signUpLine[x-1] = -signDown; @@ -480,6 +530,12 @@ void SampleAdaptiveOffset::offsetBlock(const int channelBitDepth, const ClpRng& lastLineEndX = isBelowAvail ? endX : 1; for(x= lastLineStartX; x< lastLineEndX; x++) { +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + if (isCTUCrossVirtualBoundaries && isProcessDisabled(x, height - 1, numVerVirBndry, numHorVirBndry, verVirBndryPos, horVirBndryPos)) + { + continue; + } +#endif edgeType = sgn(srcLine[x] - srcLineBelow[x-1]) + signUpLine[x]; resLine[x] = ClipPel<int>(srcLine[x] + offset[edgeType], clpRng); @@ -535,6 +591,12 @@ void SampleAdaptiveOffset::offsetCTU( const UnitArea& area, const CPelUnitBuf& s m_signLineBuf2.resize(lineBufferSize); } +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + int numHorVirBndry = 0, numVerVirBndry = 0; + int horVirBndryPos[] = { -1,-1,-1 }; + int verVirBndryPos[] = { -1,-1,-1 }; + bool isCTUCrossVirtualBoundaries = isCrossedVirtualBoundaries(area.Y().x, area.Y().y, area.Y().width, area.Y().height, numHorVirBndry, numVerVirBndry, horVirBndryPos, verVirBndryPos, cs.slice->getPPS()); +#endif for(int compIdx = 0; compIdx < numberOfComponents; compIdx++) { const ComponentID compID = ComponentID(compIdx); @@ -547,6 +609,16 @@ void SampleAdaptiveOffset::offsetCTU( const UnitArea& area, const CPelUnitBuf& s const Pel* srcBlk = src.get(compID).bufAt(compArea); int resStride = res.get(compID).stride; Pel* resBlk = res.get(compID).bufAt(compArea); +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + for (int i = 0; i < numHorVirBndry; i++) + { + horVirBndryPos[i] = (horVirBndryPos[i] >> ::getComponentScaleY(compID, area.chromaFormat)) - compArea.y; + } + for (int i = 0; i < numVerVirBndry; i++) + { + verVirBndryPos[i] = (verVirBndryPos[i] >> ::getComponentScaleX(compID, area.chromaFormat)) - compArea.x; + } +#endif offsetBlock( cs.sps->getBitDepth(toChannelType(compID)), cs.slice->clpRng(compID), @@ -556,6 +628,9 @@ void SampleAdaptiveOffset::offsetCTU( const UnitArea& area, const CPelUnitBuf& s , isAboveAvail, isBelowAvail , isAboveLeftAvail, isAboveRightAvail , isBelowLeftAvail, isBelowRightAvail +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + , isCTUCrossVirtualBoundaries, horVirBndryPos, verVirBndryPos, numHorVirBndry, numVerVirBndry +#endif ); } } //compIdx @@ -779,4 +854,28 @@ void SampleAdaptiveOffset::deriveLoopFilterBoundaryAvailibility(CodingStructure& } } +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND +bool SampleAdaptiveOffset::isCrossedVirtualBoundaries(const int xPos, const int yPos, const int width, const int height, int& numHorVirBndry, int& numVerVirBndry, int horVirBndryPos[], int verVirBndryPos[], const PPS* pps) +{ + numHorVirBndry = 0; numVerVirBndry = 0; + if (pps->getLoopFilterAcrossVirtualBoundariesDisabledFlag()) + { + for (int i = 0; i < pps->getNumHorVirtualBoundaries(); i++) + { + if (yPos <= pps->getVirtualBoundariesPosY(i) && pps->getVirtualBoundariesPosY(i) <= yPos + height) + { + horVirBndryPos[numHorVirBndry++] = pps->getVirtualBoundariesPosY(i); + } + } + for (int i = 0; i < pps->getNumVerVirtualBoundaries(); i++) + { + if (xPos <= pps->getVirtualBoundariesPosX(i) && pps->getVirtualBoundariesPosX(i) <= xPos + width) + { + verVirBndryPos[numVerVirBndry++] = pps->getVirtualBoundariesPosX(i); + } + } + } + return numHorVirBndry > 0 || numVerVirBndry > 0 ; +} +#endif //! \} diff --git a/source/Lib/CommonLib/SampleAdaptiveOffset.h b/source/Lib/CommonLib/SampleAdaptiveOffset.h index d3141d56ed63f1141f1eb9d08b7883691ef2364e..ff50a001a7ed5a76b1e5a93fb5bbed1200c7ac00 100644 --- a/source/Lib/CommonLib/SampleAdaptiveOffset.h +++ b/source/Lib/CommonLib/SampleAdaptiveOffset.h @@ -84,7 +84,11 @@ protected: ) const; void offsetBlock(const int channelBitDepth, const ClpRng& clpRng, int typeIdx, int* offset, const Pel* srcBlk, Pel* resBlk, int srcStride, int resStride, int width, int height - , bool isLeftAvail, bool isRightAvail, bool isAboveAvail, bool isBelowAvail, bool isAboveLeftAvail, bool isAboveRightAvail, bool isBelowLeftAvail, bool isBelowRightAvail); + , bool isLeftAvail, bool isRightAvail, bool isAboveAvail, bool isBelowAvail, bool isAboveLeftAvail, bool isAboveRightAvail, bool isBelowLeftAvail, bool isBelowRightAvail +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + , bool isCTUCrossVirtualBoundaries, int horVirBndryPos[], int verVirBndryPos[], int numHorVirBndry, int numVerVirBndry +#endif + ); void invertQuantOffsets(ComponentID compIdx, int typeIdc, int typeAuxInfo, int* dstOffsets, int* srcOffsets); void reconstructBlkSAOParam(SAOBlkParam& recParam, SAOBlkParam* mergeList[NUM_SAO_MERGE_TYPES]); int getMergeList(CodingStructure& cs, int ctuRsAddr, SAOBlkParam* blkParams, SAOBlkParam* mergeList[NUM_SAO_MERGE_TYPES]); @@ -93,6 +97,30 @@ protected: void xPCMCURestoration(CodingStructure& cs, const UnitArea &ctuArea); void xPCMSampleRestoration(CodingUnit& cu, const ComponentID compID); void xReconstructBlkSAOParams(CodingStructure& cs, SAOBlkParam* saoBlkParams); +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + bool isCrossedVirtualBoundaries(const int xPos, const int yPos, const int width, const int height, int& numHorVirBndry, int& numVerVirBndry, int horVirBndryPos[], int verVirBndryPos[], const PPS* pps); + inline bool isProcessDisabled(int xPos, int yPos, int numVerVirBndry, int numHorVirBndry, int verVirBndryPos[], int horVirBndryPos[]) + { + bool bDisabledFlag = false; + for (int i = 0; i < numVerVirBndry; i++) + { + if ((xPos == verVirBndryPos[i]) || (xPos == verVirBndryPos[i] - 1)) + { + bDisabledFlag = true; + break; + } + } + for (int i = 0; i < numHorVirBndry; i++) + { + if ((yPos == horVirBndryPos[i]) || (yPos == horVirBndryPos[i] - 1)) + { + bDisabledFlag = true; + break; + } + } + return bDisabledFlag; + } +#endif Reshape* m_pcReshape; protected: uint32_t m_offsetStepLog2[MAX_NUM_COMPONENT]; //offset step diff --git a/source/Lib/CommonLib/Slice.cpp b/source/Lib/CommonLib/Slice.cpp index a2915b64b65a8e46347840ec8582e99f6ae72b38..d4557c496bfe6469550374f74d52864026564581 100644 --- a/source/Lib/CommonLib/Slice.cpp +++ b/source/Lib/CommonLib/Slice.cpp @@ -1957,9 +1957,18 @@ PPS::PPS() , m_loopFilterAcrossSlicesEnabledFlag(false) , m_listsModificationPresentFlag (0) , m_numExtraSliceHeaderBits (0) +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND +, m_loopFilterAcrossVirtualBoundariesDisabledFlag(false) +, m_numVerVirtualBoundaries (0) +, m_numHorVirtualBoundaries (0) +#endif , m_ppsRangeExtension () , pcv (NULL) { +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + ::memset(m_virtualBoundariesPosX, 0, sizeof(m_virtualBoundariesPosX)); + ::memset(m_virtualBoundariesPosY, 0, sizeof(m_virtualBoundariesPosY)); +#endif } PPS::~PPS() diff --git a/source/Lib/CommonLib/Slice.h b/source/Lib/CommonLib/Slice.h index d014bb8ac2951ab442034177d467322e18ad77e2..248630679480233401d05d81cf6d45bfb0715bc2 100644 --- a/source/Lib/CommonLib/Slice.h +++ b/source/Lib/CommonLib/Slice.h @@ -1573,6 +1573,14 @@ private: uint32_t m_log2ParallelMergeLevelMinus2; int m_numExtraSliceHeaderBits; +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + bool m_loopFilterAcrossVirtualBoundariesDisabledFlag; + unsigned m_numVerVirtualBoundaries; + unsigned m_numHorVirtualBoundaries; + unsigned m_virtualBoundariesPosX[3]; + unsigned m_virtualBoundariesPosY[3]; +#endif + PPSRExt m_ppsRangeExtension; public: @@ -1698,6 +1706,19 @@ public: bool getSliceHeaderExtensionPresentFlag() const { return m_sliceHeaderExtensionPresentFlag; } void setSliceHeaderExtensionPresentFlag(bool val) { m_sliceHeaderExtensionPresentFlag = val; } +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + void setLoopFilterAcrossVirtualBoundariesDisabledFlag(bool b) { m_loopFilterAcrossVirtualBoundariesDisabledFlag = b; } + bool getLoopFilterAcrossVirtualBoundariesDisabledFlag() const { return m_loopFilterAcrossVirtualBoundariesDisabledFlag; } + void setNumVerVirtualBoundaries(unsigned u) { m_numVerVirtualBoundaries = u; } + unsigned getNumVerVirtualBoundaries() const { return m_numVerVirtualBoundaries; } + void setNumHorVirtualBoundaries(unsigned u) { m_numHorVirtualBoundaries = u; } + unsigned getNumHorVirtualBoundaries() const { return m_numHorVirtualBoundaries; } + void setVirtualBoundariesPosX(unsigned u, unsigned idx) { m_virtualBoundariesPosX[idx] = u; } + unsigned getVirtualBoundariesPosX(unsigned idx) const { return m_virtualBoundariesPosX[idx]; } + void setVirtualBoundariesPosY(unsigned u, unsigned idx) { m_virtualBoundariesPosY[idx] = u; } + unsigned getVirtualBoundariesPosY(unsigned idx) const { return m_virtualBoundariesPosY[idx]; } +#endif + const PPSRExt& getPpsRangeExtension() const { return m_ppsRangeExtension; } PPSRExt& getPpsRangeExtension() { return m_ppsRangeExtension; } }; diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h index e3f52d7ab02c97a85bf4270b464ba032c71b8d6c..a394dabbaeb9bbd9d684ab67430289ea941afaa6 100644 --- a/source/Lib/CommonLib/TypeDef.h +++ b/source/Lib/CommonLib/TypeDef.h @@ -77,6 +77,8 @@ #define JVET_N0168_AMVR_ME_MODIFICATION 1 // Correct the cost and bits calculation in encoder side +#define JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND 1 // loop filter disabled across virtual boundaries + #define JVET_N0068_AFFINE_MEM_BW 1 // memory bandwidth reduction for affine mode #define JVET_N0308_MAX_CU_SIZE_FOR_ISP 1 @@ -1584,6 +1586,9 @@ struct XUCache #define MAX_NUM_ALF_CHROMA_COEFF 7 #define MAX_ALF_FILTER_LENGTH 7 #define MAX_NUM_ALF_COEFF (MAX_ALF_FILTER_LENGTH * MAX_ALF_FILTER_LENGTH / 2 + 1) +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND +#define MAX_ALF_PADDING_SIZE 4 +#endif enum AlfFilterType { diff --git a/source/Lib/CommonLib/x86/AdaptiveLoopFilterX86.h b/source/Lib/CommonLib/x86/AdaptiveLoopFilterX86.h index d37946079a49a1a25fff14fad9d6964e4a586281..2105389a649feea265e9aa2182b9b61f8df6f2ef 100644 --- a/source/Lib/CommonLib/x86/AdaptiveLoopFilterX86.h +++ b/source/Lib/CommonLib/x86/AdaptiveLoopFilterX86.h @@ -48,11 +48,19 @@ #endif template<X86_VEXT vext> -#if JVET_N0180_ALF_LINE_BUFFER_REDUCTION +#if JVET_N0180_ALF_LINE_BUFFER_REDUCTION +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND +static void simdDeriveClassificationBlk(AlfClassifier** classifier, int** laplacian[NUM_DIRECTIONS], const CPelBuf& srcLuma, const Area& blkDst, const Area& blk, const int shift, int vbCTUHeight, int vbPos) +#else static void simdDeriveClassificationBlk(AlfClassifier** classifier, int** laplacian[NUM_DIRECTIONS], const CPelBuf& srcLuma, const Area& blk, const int shift, int vbCTUHeight, int vbPos) +#endif +#else +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND +static void simdDeriveClassificationBlk(AlfClassifier** classifier, int** laplacian[NUM_DIRECTIONS], const CPelBuf& srcLuma, const Area& blkDst, const Area& blk, const int shift) #else static void simdDeriveClassificationBlk(AlfClassifier** classifier, int** laplacian[NUM_DIRECTIONS], const CPelBuf& srcLuma, const Area& blk, const int shift) #endif +#endif { const int img_stride = srcLuma.stride; const Pel* srcExt = srcLuma.buf; @@ -82,11 +90,19 @@ static void simdDeriveClassificationBlk(AlfClassifier** classifier, int** laplac #if JVET_N0180_ALF_LINE_BUFFER_REDUCTION // pixel padding for gradient calculation +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + if (((blkDst.pos().y - 2 + i) > 0) && ((blkDst.pos().y - 2 + i) % vbCTUHeight) == (vbPos - 2)) +#else if (((posY - 2 + i) > 0) && ((posY - 2 + i) % vbCTUHeight) == (vbPos - 2)) +#endif { p_imgY_pad_up2 = &srcExt[yoffset + img_stride]; } +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + else if (((blkDst.pos().y - 2 + i) > 0) && ((blkDst.pos().y - 2 + i) % vbCTUHeight) == vbPos) +#else else if (((posY - 2 + i) > 0) && ((posY - 2 + i) % vbCTUHeight) == vbPos) +#endif { p_imgY_pad_down = &srcExt[yoffset]; } @@ -203,14 +219,22 @@ static void simdDeriveClassificationBlk(AlfClassifier** classifier, int** laplac { #if JVET_N0180_ALF_LINE_BUFFER_REDUCTION __m128i xmm0, xmm1, xmm2, xmm3; +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + if ((((i << 1) + blkDst.pos().y) % vbCTUHeight) == (vbPos - 4)) +#else if ((((i << 1) + posY) % vbCTUHeight) == (vbPos - 4)) +#endif { xmm0 = _mm_loadu_si128((__m128i*)(&(_temp[i + 0][j]))); xmm1 = _mm_loadu_si128((__m128i*)(&(_temp[i + 1][j]))); xmm2 = _mm_loadu_si128((__m128i*)(&(_temp[i + 2][j]))); xmm3 = mm_0; } +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + else if ((((i << 1) + blkDst.pos().y) % vbCTUHeight) == vbPos) +#else else if ((((i << 1) + posY) % vbCTUHeight) == vbPos) +#endif { xmm0 = mm_0; xmm1 = _mm_loadu_si128((__m128i*)(&(_temp[i + 1][j]))); @@ -247,7 +271,11 @@ static void simdDeriveClassificationBlk(AlfClassifier** classifier, int** laplac __m128i xmm10 = _mm_shuffle_epi32( xmm12, 0xB1 ); xmm12 = _mm_add_epi32( xmm10, xmm12 ); #if JVET_N0180_ALF_LINE_BUFFER_REDUCTION +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + if (((((i << 1) + blkDst.pos().y) % vbCTUHeight) == (vbPos - 4)) || ((((i << 1) + blkDst.pos().y) % vbCTUHeight) == vbPos)) +#else if (((((i << 1) + posY) % vbCTUHeight) == (vbPos - 4)) || ((((i << 1) + posY) % vbCTUHeight) == vbPos)) +#endif { xmm12 = _mm_srai_epi32(_mm_add_epi32(_mm_slli_epi32(xmm12, 5), _mm_slli_epi32(xmm12, 6)), shift); } @@ -350,8 +378,13 @@ static void simdDeriveClassificationBlk(AlfClassifier** classifier, int** laplac int classIdx0 = c0; int classIdx1 = c1; +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + const int yOffset = (i << 1) + blkDst.pos().y; + const int xOffset = j + blkDst.pos().x; +#else const int yOffset = ( i << 1 ) + posY; const int xOffset = j + posX; +#endif AlfClassifier *cl0 = classifier[yOffset] + xOffset; AlfClassifier *cl1 = classifier[yOffset + 1] + xOffset; @@ -372,17 +405,33 @@ static void simdDeriveClassificationBlk(AlfClassifier** classifier, int** laplac template<X86_VEXT vext> #if JVET_N0180_ALF_LINE_BUFFER_REDUCTION #if JVET_N0242_NON_LINEAR_ALF +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND +static void simdFilter5x5Blk(AlfClassifier** classifier, const PelUnitBuf &recDst, const CPelUnitBuf& recSrc, const Area& blkDst, const Area& blk, const ComponentID compId, short* filterSet, short* fClipSet, const ClpRng& clpRng, CodingStructure& cs, int vbCTUHeight, int vbPos) +#else static void simdFilter5x5Blk(AlfClassifier** classifier, const PelUnitBuf &recDst, const CPelUnitBuf& recSrc, const Area& blk, const ComponentID compId, short* filterSet, short* fClipSet, const ClpRng& clpRng, CodingStructure& cs, int vbCTUHeight, int vbPos) +#endif +#else +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND +static void simdFilter5x5Blk(AlfClassifier** classifier, const PelUnitBuf &recDst, const CPelUnitBuf& recSrc, const Area& blkDst, const Area& blk, const ComponentID compId, short* filterSet, const ClpRng& clpRng, CodingStructure& cs, int vbCTUHeight, int vbPos) #else static void simdFilter5x5Blk(AlfClassifier** classifier, const PelUnitBuf &recDst, const CPelUnitBuf& recSrc, const Area& blk, const ComponentID compId, short* filterSet, const ClpRng& clpRng, CodingStructure& cs, int vbCTUHeight, int vbPos) #endif +#endif #else #if JVET_N0242_NON_LINEAR_ALF +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND +static void simdFilter5x5Blk(AlfClassifier** classifier, const PelUnitBuf &recDst, const CPelUnitBuf& recSrc, const Area& blkDst, const Area& blk, const ComponentID compId, short* filterSet, short* fClipSet, const ClpRng& clpRng, CodingStructure& cs) +#else static void simdFilter5x5Blk(AlfClassifier** classifier, const PelUnitBuf &recDst, const CPelUnitBuf& recSrc, const Area& blk, const ComponentID compId, short* filterSet, short* fClipSet, const ClpRng& clpRng, CodingStructure& cs) +#endif +#else +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND +static void simdFilter5x5Blk(AlfClassifier** classifier, const PelUnitBuf &recDst, const CPelUnitBuf& recSrc, const Area& blkDst, const Area& blk, const ComponentID compId, short* filterSet, const ClpRng& clpRng, CodingStructure& cs) #else static void simdFilter5x5Blk(AlfClassifier** classifier, const PelUnitBuf &recDst, const CPelUnitBuf& recSrc, const Area& blk, const ComponentID compId, short* filterSet, const ClpRng& clpRng, CodingStructure& cs) #endif #endif +#endif { #if !JVET_N0242_NON_LINEAR_ALF static const unsigned char mask05[16] = { 8, 9, 6, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; @@ -423,7 +472,11 @@ static void simdFilter5x5Blk(AlfClassifier** classifier, const PelUnitBuf &recDs #if JVET_N0242_NON_LINEAR_ALF const Pel* src = srcLuma.buf; +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + Pel* dst = dstLuma.buf + blkDst.y * dstStride; +#else Pel* dst = dstLuma.buf + startHeight * dstStride; +#endif const Pel *pImgYPad0, *pImgYPad1, *pImgYPad2, *pImgYPad3, *pImgYPad4; const Pel *pImg0, *pImg1, *pImg2, *pImg3, *pImg4; @@ -434,7 +487,11 @@ static void simdFilter5x5Blk(AlfClassifier** classifier, const PelUnitBuf &recDs int transposeIdx[2] = {0, 0}; #else Pel* imgYRecPost = dst; +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + imgYRecPost += blkDst.y * dstStride; +#else imgYRecPost += startHeight * dstStride; +#endif int transposeIdx = 0; @@ -497,11 +554,19 @@ static void simdFilter5x5Blk(AlfClassifier** classifier, const PelUnitBuf &recDs #endif #if JVET_N0242_NON_LINEAR_ALF +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + Pel* pRec0 = dst + blkDst.x; +#else Pel* pRec0 = dst + startWidth; +#endif Pel* pRec1; +#else +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + pRec = imgYRecPost + blkDst.x; #else pRec = imgYRecPost + startWidth; #endif +#endif #if JVET_N0242_NON_LINEAR_ALF for( int i = 0; i < endHeight - startHeight; i += clsSizeY ) @@ -510,12 +575,20 @@ static void simdFilter5x5Blk(AlfClassifier** classifier, const PelUnitBuf &recDs #endif { #if !JVET_N0242_NON_LINEAR_ALF +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + pRec = imgYRecPost + blkDst.x + i * dstStride; +#else pRec = imgYRecPost + startWidth + i * dstStride; +#endif #endif if( !bChroma ) { +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + pClass = classifier[blkDst.y + i] + blkDst.x; +#else pClass = classifier[startHeight + i] + startWidth; +#endif } #if JVET_N0242_NON_LINEAR_ALF @@ -600,7 +673,11 @@ static void simdFilter5x5Blk(AlfClassifier** classifier, const PelUnitBuf &recDs { for( blkX=0; blkX<4; blkX+=2 ) { +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + Position pos(j + blkDst.x + blkX, i + blkDst.y + blkY); +#else Position pos(j+startWidth+blkX, i+startHeight+blkY); +#endif CodingUnit* cu = isDualTree ? cs.getCU(pos, CH_C) : cs.getCU(recalcPosition(nChromaFormat, CH_C, CH_L, pos), CH_L); *flags++ = cu->ipcm ? 1 : 0; @@ -667,7 +744,11 @@ static void simdFilter5x5Blk(AlfClassifier** classifier, const PelUnitBuf &recDs { for( blkX=0; blkX<8; blkX+=2 ) { +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + Position pos(j + blkDst.x + blkX, i + blkDst.y + blkY); +#else Position pos(j+startWidth+blkX, i+startHeight+blkY); +#endif CodingUnit* cu = isDualTree ? cs.getCU(pos, CH_C) : cs.getCU(recalcPosition(nChromaFormat, CH_C, CH_L, pos), CH_L); *flags++ = cu->ipcm ? 1 : 0; @@ -695,6 +776,24 @@ static void simdFilter5x5Blk(AlfClassifier** classifier, const PelUnitBuf &recDs pImg4 = pImgYPad4 + j + ii * srcStride; #endif #if JVET_N0180_ALF_LINE_BUFFER_REDUCTION +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + if ((blkDst.y + i + ii) % vbCTUHeight < vbPos && ((blkDst.y + i + ii) % vbCTUHeight >= vbPos - (bChroma ? 2 : 4))) //above + { + pImg1 = ((blkDst.y + i + ii) % vbCTUHeight == vbPos - 1) ? pImg0 : pImg1; + pImg3 = ((blkDst.y + i + ii) % vbCTUHeight >= vbPos - 2) ? pImg1 : pImg3; + + pImg2 = ((blkDst.y + i + ii) % vbCTUHeight == vbPos - 1) ? pImg0 : pImg2; + pImg4 = ((blkDst.y + i + ii) % vbCTUHeight >= vbPos - 2) ? pImg2 : pImg4; + } + else if ((blkDst.y + i + ii) % vbCTUHeight >= vbPos && ((blkDst.y + i + ii) % vbCTUHeight <= vbPos + (bChroma ? 1 : 3))) //bottom + { + pImg2 = ((blkDst.y + i + ii) % vbCTUHeight == vbPos) ? pImg0 : pImg2; + pImg4 = ((blkDst.y + i + ii) % vbCTUHeight <= vbPos + 1) ? pImg2 : pImg4; + + pImg1 = ((blkDst.y + i + ii) % vbCTUHeight == vbPos) ? pImg0 : pImg1; + pImg3 = ((blkDst.y + i + ii) % vbCTUHeight <= vbPos + 1) ? pImg1 : pImg3; + } +#else if ((startHeight + i + ii) % vbCTUHeight < vbPos && ((startHeight + i + ii) % vbCTUHeight >= vbPos - (bChroma ? 2 : 4))) //above { pImg1 = ((startHeight + i + ii) % vbCTUHeight == vbPos - 1) ? pImg0 : pImg1; @@ -711,6 +810,7 @@ static void simdFilter5x5Blk(AlfClassifier** classifier, const PelUnitBuf &recDs pImg1 = ((startHeight + i + ii) % vbCTUHeight == vbPos) ? pImg0 : pImg1; pImg3 = ((startHeight + i + ii) % vbCTUHeight <= vbPos + 1) ? pImg1 : pImg3; } +#endif #endif __m128i clipp, clipm; __m128i coeffa, coeffb; @@ -894,6 +994,26 @@ static void simdFilter5x5Blk(AlfClassifier** classifier, const PelUnitBuf &recDs pImg4 = pImgYPad4 + j + k * srcStride; #endif #if JVET_N0180_ALF_LINE_BUFFER_REDUCTION +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + if ((blkDst.y + i + k) % vbCTUHeight < vbPos && ((blkDst.y + i + k) % vbCTUHeight >= vbPos - (bChroma ? 2 : 4))) //above + { + pImg1 = ((blkDst.y + i + k) % vbCTUHeight == vbPos - 1) ? pImg0 : pImg1; + pImg3 = ((blkDst.y + i + k) % vbCTUHeight >= vbPos - 2) ? pImg1 : pImg3; + pImg5 = ((blkDst.y + i + k) % vbCTUHeight >= vbPos - 3) ? pImg3 : pImg5; + + pImg2 = ((blkDst.y + i + k) % vbCTUHeight == vbPos - 1) ? pImg0 : pImg2; + pImg4 = ((blkDst.y + i + k) % vbCTUHeight >= vbPos - 2) ? pImg2 : pImg4; + } + else if ((blkDst.y + i + k) % vbCTUHeight >= vbPos && ((blkDst.y + i + k) % vbCTUHeight <= vbPos + (bChroma ? 1 : 3))) //bottom + { + pImg2 = ((blkDst.y + i + k) % vbCTUHeight == vbPos) ? pImg0 : pImg2; + pImg4 = ((blkDst.y + i + k) % vbCTUHeight <= vbPos + 1) ? pImg2 : pImg4; + + pImg1 = ((blkDst.y + i + k) % vbCTUHeight == vbPos) ? pImg0 : pImg1; + pImg3 = ((blkDst.y + i + k) % vbCTUHeight <= vbPos + 1) ? pImg1 : pImg3; + pImg5 = ((blkDst.y + i + k) % vbCTUHeight <= vbPos + 2) ? pImg3 : pImg5; + } +#else if ((startHeight + i + k) % vbCTUHeight < vbPos && ((startHeight + i + k) % vbCTUHeight >= vbPos - (bChroma ? 2 : 4))) //above { pImg1 = ((startHeight + i + k) % vbCTUHeight == vbPos - 1) ? pImg0 : pImg1; @@ -912,6 +1032,7 @@ static void simdFilter5x5Blk(AlfClassifier** classifier, const PelUnitBuf &recDs pImg3 = ((startHeight + i + k) % vbCTUHeight <= vbPos + 1) ? pImg1 : pImg3; pImg5 = ((startHeight + i + k) % vbCTUHeight <= vbPos + 2) ? pImg3 : pImg5; } +#endif #endif __m128i xmm4 = _mm_lddqu_si128( ( __m128i* ) ( pImg4 ) ); __m128i xmm2 = _mm_lddqu_si128( ( __m128i* ) ( pImg2 - 1 ) ); @@ -1079,17 +1200,33 @@ static void simdFilter5x5Blk(AlfClassifier** classifier, const PelUnitBuf &recDs template<X86_VEXT vext> #if JVET_N0180_ALF_LINE_BUFFER_REDUCTION #if JVET_N0242_NON_LINEAR_ALF +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND +static void simdFilter7x7Blk(AlfClassifier** classifier, const PelUnitBuf &recDst, const CPelUnitBuf& recSrc, const Area& blkDst, const Area& blk, const ComponentID compId, short* filterSet, short* fClipSet, const ClpRng& clpRng, CodingStructure& cs, int vbCTUHeight, int vbPos) +#else static void simdFilter7x7Blk(AlfClassifier** classifier, const PelUnitBuf &recDst, const CPelUnitBuf& recSrc, const Area& blk, const ComponentID compId, short* filterSet, short* fClipSet, const ClpRng& clpRng, CodingStructure& cs, int vbCTUHeight, int vbPos) +#endif +#else +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND +static void simdFilter7x7Blk(AlfClassifier** classifier, const PelUnitBuf &recDst, const CPelUnitBuf& recSrc, const Area& blkDst, const Area& blk, const ComponentID compId, short* filterSet, const ClpRng& clpRng, CodingStructure& cs, int vbCTUHeight, int vbPos) #else static void simdFilter7x7Blk(AlfClassifier** classifier, const PelUnitBuf &recDst, const CPelUnitBuf& recSrc, const Area& blk, const ComponentID compId, short* filterSet, const ClpRng& clpRng, CodingStructure& cs, int vbCTUHeight, int vbPos) #endif +#endif #else #if JVET_N0242_NON_LINEAR_ALF +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND +static void simdFilter7x7Blk( AlfClassifier** classifier, const PelUnitBuf &recDst, const CPelUnitBuf& recSrc, const Area& blkDst, const Area& blk, const ComponentID compId, short* filterSet, short* fClipSet, const ClpRng& clpRng, CodingStructure& cs ) +#else static void simdFilter7x7Blk( AlfClassifier** classifier, const PelUnitBuf &recDst, const CPelUnitBuf& recSrc, const Area& blk, const ComponentID compId, short* filterSet, short* fClipSet, const ClpRng& clpRng, CodingStructure& cs ) +#endif +#else +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND +static void simdFilter7x7Blk( AlfClassifier** classifier, const PelUnitBuf &recDst, const CPelUnitBuf& recSrc, const Area& blkDst, const Area& blk, const ComponentID compId, short* filterSet, const ClpRng& clpRng, CodingStructure& cs ) #else static void simdFilter7x7Blk( AlfClassifier** classifier, const PelUnitBuf &recDst, const CPelUnitBuf& recSrc, const Area& blk, const ComponentID compId, short* filterSet, const ClpRng& clpRng, CodingStructure& cs ) #endif #endif +#endif { #if !JVET_N0242_NON_LINEAR_ALF static const unsigned char mask0[16] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 6, 7, 4, 5, 2, 3 }; @@ -1139,7 +1276,11 @@ static void simdFilter7x7Blk( AlfClassifier** classifier, const PelUnitBuf &recD #if JVET_N0242_NON_LINEAR_ALF const Pel* src = srcLuma.buf; +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + Pel* dst = dstLuma.buf + blkDst.y * dstStride; +#else Pel* dst = dstLuma.buf + startHeight * dstStride; +#endif const Pel *pImgYPad0, *pImgYPad1, *pImgYPad2, *pImgYPad3, *pImgYPad4, *pImgYPad5, *pImgYPad6; const Pel *pImg0, *pImg1, *pImg2, *pImg3, *pImg4, *pImg5, *pImg6; @@ -1150,7 +1291,11 @@ static void simdFilter7x7Blk( AlfClassifier** classifier, const PelUnitBuf &recD int transposeIdx[2] = {0, 0}; #else Pel* imgYRecPost = dst; +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + imgYRecPost += blkDst.y * dstStride; +#else imgYRecPost += startHeight * dstStride; +#endif int transposeIdx = 0; @@ -1209,11 +1354,19 @@ static void simdFilter7x7Blk( AlfClassifier** classifier, const PelUnitBuf &recD pImgYPad6 = pImgYPad4 - srcStride; #if JVET_N0242_NON_LINEAR_ALF +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + Pel* pRec0 = dst + blkDst.x; +#else Pel* pRec0 = dst + startWidth; +#endif Pel* pRec1; +#else +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + pRec = imgYRecPost + blkDst.x; #else pRec = imgYRecPost + startWidth; #endif +#endif #if JVET_N0242_NON_LINEAR_ALF for( int i = 0; i < endHeight - startHeight; i += clsSizeY ) @@ -1222,12 +1375,20 @@ static void simdFilter7x7Blk( AlfClassifier** classifier, const PelUnitBuf &recD #endif { #if !JVET_N0242_NON_LINEAR_ALF +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + pRec = imgYRecPost + blkDst.x + i * dstStride; +#else pRec = imgYRecPost + startWidth + i * dstStride; +#endif #endif if( !bChroma ) { +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + pClass = classifier[blkDst.y + i] + blkDst.x; +#else pClass = classifier[startHeight + i] + startWidth; +#endif } #if JVET_N0242_NON_LINEAR_ALF @@ -1312,7 +1473,11 @@ static void simdFilter7x7Blk( AlfClassifier** classifier, const PelUnitBuf &recD { for( blkX=0; blkX<4; blkX+=2 ) { +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + Position pos(j + blkDst.x + blkX, i + blkDst.y + blkY); +#else Position pos(j+startWidth+blkX, i+startHeight+blkY); +#endif CodingUnit* cu = isDualTree ? cs.getCU(pos, CH_C) : cs.getCU(recalcPosition(nChromaFormat, CH_C, CH_L, pos), CH_L); *flags++ = cu->ipcm ? 1 : 0; @@ -1395,7 +1560,11 @@ static void simdFilter7x7Blk( AlfClassifier** classifier, const PelUnitBuf &recD { for( blkX=0; blkX<8; blkX+=2 ) { +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + Position pos(j + blkDst.x + blkX, i + blkDst.y + blkY); +#else Position pos(j+startWidth+blkX, i+startHeight+blkY); +#endif CodingUnit* cu = isDualTree ? cs.getCU(pos, CH_C) : cs.getCU(recalcPosition(nChromaFormat, CH_C, CH_L, pos), CH_L); *flags++ = cu->ipcm ? 1 : 0; @@ -1423,6 +1592,28 @@ static void simdFilter7x7Blk( AlfClassifier** classifier, const PelUnitBuf &recD pImg4 = pImgYPad4 + j + ii * srcStride; pImg5 = pImgYPad5 + j + ii * srcStride; pImg6 = pImgYPad6 + j + ii * srcStride; +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + if ((blkDst.y + i + ii) % vbCTUHeight < vbPos && ((blkDst.y + i + ii) % vbCTUHeight >= vbPos - (bChroma ? 2 : 4))) //above + { + pImg1 = ((blkDst.y + i + ii) % vbCTUHeight == vbPos - 1) ? pImg0 : pImg1; + pImg3 = ((blkDst.y + i + ii) % vbCTUHeight >= vbPos - 2) ? pImg1 : pImg3; + pImg5 = ((blkDst.y + i + ii) % vbCTUHeight >= vbPos - 3) ? pImg3 : pImg5; + + pImg2 = ((blkDst.y + i + ii) % vbCTUHeight == vbPos - 1) ? pImg0 : pImg2; + pImg4 = ((blkDst.y + i + ii) % vbCTUHeight >= vbPos - 2) ? pImg2 : pImg4; + pImg6 = ((blkDst.y + i + ii) % vbCTUHeight >= vbPos - 3) ? pImg4 : pImg6; + } + else if ((blkDst.y + i + ii) % vbCTUHeight >= vbPos && ((blkDst.y + i + ii) % vbCTUHeight <= vbPos + (bChroma ? 1 : 3))) //bottom + { + pImg2 = ((blkDst.y + i + ii) % vbCTUHeight == vbPos) ? pImg0 : pImg2; + pImg4 = ((blkDst.y + i + ii) % vbCTUHeight <= vbPos + 1) ? pImg2 : pImg4; + pImg6 = ((blkDst.y + i + ii) % vbCTUHeight <= vbPos + 2) ? pImg4 : pImg6; + + pImg1 = ((blkDst.y + i + ii) % vbCTUHeight == vbPos) ? pImg0 : pImg1; + pImg3 = ((blkDst.y + i + ii) % vbCTUHeight <= vbPos + 1) ? pImg1 : pImg3; + pImg5 = ((blkDst.y + i + ii) % vbCTUHeight <= vbPos + 2) ? pImg3 : pImg5; + } +#else if ((startHeight + i + ii) % vbCTUHeight < vbPos && ((startHeight + i + ii) % vbCTUHeight >= vbPos - (bChroma ? 2 : 4))) //above { pImg1 = ((startHeight + i + ii) % vbCTUHeight == vbPos - 1) ? pImg0 : pImg1; @@ -1443,6 +1634,7 @@ static void simdFilter7x7Blk( AlfClassifier** classifier, const PelUnitBuf &recD pImg3 = ((startHeight + i + ii) % vbCTUHeight <= vbPos + 1) ? pImg1 : pImg3; pImg5 = ((startHeight + i + ii) % vbCTUHeight <= vbPos + 2) ? pImg3 : pImg5; } +#endif #endif __m128i clipp, clipm; __m128i coeffa, coeffb; @@ -1770,6 +1962,28 @@ static void simdFilter7x7Blk( AlfClassifier** classifier, const PelUnitBuf &recD pImg4 = pImgYPad4 + j + k * srcStride; pImg5 = pImgYPad5 + j + k * srcStride; pImg6 = pImgYPad6 + j + k * srcStride; +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + if ((blkDst.y + i + k) % vbCTUHeight < vbPos && ((blkDst.y + i + k) % vbCTUHeight >= vbPos - (bChroma ? 2 : 4))) //above + { + pImg1 = ((blkDst.y + i + k) % vbCTUHeight == vbPos - 1) ? pImg0 : pImg1; + pImg3 = ((blkDst.y + i + k) % vbCTUHeight >= vbPos - 2) ? pImg1 : pImg3; + pImg5 = ((blkDst.y + i + k) % vbCTUHeight >= vbPos - 3) ? pImg3 : pImg5; + + pImg2 = ((blkDst.y + i + k) % vbCTUHeight == vbPos - 1) ? pImg0 : pImg2; + pImg4 = ((blkDst.y + i + k) % vbCTUHeight >= vbPos - 2) ? pImg2 : pImg4; + pImg6 = ((blkDst.y + i + k) % vbCTUHeight >= vbPos - 3) ? pImg4 : pImg6; + } + else if ((blkDst.y + i + k) % vbCTUHeight >= vbPos && ((blkDst.y + i + k) % vbCTUHeight <= vbPos + (bChroma ? 1 : 3))) //bottom + { + pImg2 = ((blkDst.y + i + k) % vbCTUHeight == vbPos) ? pImg0 : pImg2; + pImg4 = ((blkDst.y + i + k) % vbCTUHeight <= vbPos + 1) ? pImg2 : pImg4; + pImg6 = ((blkDst.y + i + k) % vbCTUHeight <= vbPos + 2) ? pImg4 : pImg6; + + pImg1 = ((blkDst.y + i + k) % vbCTUHeight == vbPos) ? pImg0 : pImg1; + pImg3 = ((blkDst.y + i + k) % vbCTUHeight <= vbPos + 1) ? pImg1 : pImg3; + pImg5 = ((blkDst.y + i + k) % vbCTUHeight <= vbPos + 2) ? pImg3 : pImg5; + } +#else if ((startHeight + i + k) % vbCTUHeight < vbPos && ((startHeight + i + k) % vbCTUHeight >= vbPos - (bChroma ? 2 : 4))) //above { pImg1 = ((startHeight + i + k) % vbCTUHeight == vbPos - 1) ? pImg0 : pImg1; @@ -1790,6 +2004,7 @@ static void simdFilter7x7Blk( AlfClassifier** classifier, const PelUnitBuf &recD pImg3 = ((startHeight + i + k) % vbCTUHeight <= vbPos + 1) ? pImg1 : pImg3; pImg5 = ((startHeight + i + k) % vbCTUHeight <= vbPos + 2) ? pImg3 : pImg5; } +#endif #endif __m128i xmm6 = _mm_lddqu_si128( ( __m128i* ) pImg6 ); __m128i xmm4 = _mm_lddqu_si128( ( __m128i* ) ( pImg4 - 1 ) ); diff --git a/source/Lib/DecoderLib/DecLib.cpp b/source/Lib/DecoderLib/DecLib.cpp index 69c14d4c0565ee94d275a13237655c6d2fd05068..035fb36f57eec4ad223c49be1008b76ceabf022a 100644 --- a/source/Lib/DecoderLib/DecLib.cpp +++ b/source/Lib/DecoderLib/DecLib.cpp @@ -1481,7 +1481,11 @@ void DecLib::xDecodePPS( InputNALUnit& nalu ) { PPS* pps = new PPS(); m_HLSReader.setBitstream( &nalu.getBitstream() ); +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + m_HLSReader.parsePPS( pps, &m_parameterSetManager ); +#else m_HLSReader.parsePPS( pps ); +#endif m_parameterSetManager.storePPS( pps, nalu.getBitstream().getFifo() ); } diff --git a/source/Lib/DecoderLib/VLCReader.cpp b/source/Lib/DecoderLib/VLCReader.cpp index 195f1eb904a9d6a60d3558f97692aea0153e1409..104ea4fcc54e72ee1ba2e9489185fa8bb7f5687b 100644 --- a/source/Lib/DecoderLib/VLCReader.cpp +++ b/source/Lib/DecoderLib/VLCReader.cpp @@ -369,7 +369,11 @@ void HLSyntaxReader::parseShortTermRefPicSet( SPS* sps, ReferencePictureSet* rps rps->printDeltaPOC(); } +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND +void HLSyntaxReader::parsePPS( PPS* pcPPS, ParameterSetManager *parameterSetManager ) +#else void HLSyntaxReader::parsePPS( PPS* pcPPS ) +#endif { #if ENABLE_TRACING xTracePPSHeader (); @@ -500,6 +504,36 @@ void HLSyntaxReader::parsePPS( PPS* pcPPS ) READ_SVLC ( iCode, "pps_tc_offset_div2" ); pcPPS->setDeblockingFilterTcOffsetDiv2( iCode ); } } + +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + READ_FLAG( uiCode, "pps_loop_filter_across_virtual_boundaries_disabled_flag" ); pcPPS->setLoopFilterAcrossVirtualBoundariesDisabledFlag( uiCode != 0 ); + if( pcPPS->getLoopFilterAcrossVirtualBoundariesDisabledFlag() ) + { + READ_CODE( 2, uiCode, "pps_num_ver_virtual_boundaries"); pcPPS->setNumVerVirtualBoundaries( uiCode ); + int numBits = 1; + uint32_t picWidthDivBy8 = parameterSetManager->getSPS( pcPPS->getSPSId() )->getPicWidthInLumaSamples() >> 3; // pcPPS->getPicWidthInLumaSamples() >> 3; + while( picWidthDivBy8 >>= 1 ) + { + numBits++; + } + for( unsigned i = 0; i < pcPPS->getNumVerVirtualBoundaries(); i++ ) + { + READ_CODE( numBits, uiCode, "pps_virtual_boundaries_pos_x" ); pcPPS->setVirtualBoundariesPosX( uiCode << 3, i ); + } + READ_CODE( 2, uiCode, "pps_num_hor_virtual_boundaries"); pcPPS->setNumHorVirtualBoundaries( uiCode ); + numBits = 1; + uint32_t picHeightDivBy8 = parameterSetManager->getSPS( pcPPS->getSPSId() )->getPicHeightInLumaSamples() >> 3; // pcPPS->getPicHeightInLumaSamples() >> 3; + while( picHeightDivBy8 >>= 1 ) + { + numBits++; + } + for( unsigned i = 0; i < pcPPS->getNumHorVirtualBoundaries(); i++ ) + { + READ_CODE( numBits, uiCode, "pps_virtual_boundaries_pos_y" ); pcPPS->setVirtualBoundariesPosY( uiCode << 3, i ); + } + } +#endif + #if HEVC_USE_SCALING_LISTS READ_FLAG( uiCode, "pps_scaling_list_data_present_flag" ); pcPPS->setScalingListPresentFlag( uiCode ? true : false ); if(pcPPS->getScalingListPresentFlag ()) diff --git a/source/Lib/DecoderLib/VLCReader.h b/source/Lib/DecoderLib/VLCReader.h index cb4908840ad8e649136ca57c1af4a7f91cb97c39..35c774cc9675f9ed9b90b8b5a18f396350f01c0b 100644 --- a/source/Lib/DecoderLib/VLCReader.h +++ b/source/Lib/DecoderLib/VLCReader.h @@ -151,7 +151,11 @@ public: void parseVPS ( VPS* pcVPS ); #endif void parseSPS ( SPS* pcSPS ); +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + void parsePPS ( PPS* pcPPS, ParameterSetManager *parameterSetManager ); +#else void parsePPS ( PPS* pcPPS ); +#endif void parseAPS ( APS* pcAPS); void parseVUI ( VUI* pcVUI, SPS* pcSPS ); #if !JVET_M0101_HLS diff --git a/source/Lib/EncoderLib/EncAdaptiveLoopFilter.cpp b/source/Lib/EncoderLib/EncAdaptiveLoopFilter.cpp index 9e9acbb5766fd98b748f2195cea5b89bd276904f..211689dafe2e3dad0521af8df908f7337b0dc670 100644 --- a/source/Lib/EncoderLib/EncAdaptiveLoopFilter.cpp +++ b/source/Lib/EncoderLib/EncAdaptiveLoopFilter.cpp @@ -717,13 +717,78 @@ void EncAdaptiveLoopFilter::ALFProcess( CodingStructure& cs, const double *lambd // derive classification const CPelBuf& recLuma = recYuv.get( COMPONENT_Y ); +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + const PreCalcValues& pcv = *cs.pcv; + bool clipTop = false, clipBottom = false, clipLeft = false, clipRight = false; + int numHorSplit = 0, numVerSplit = 0; + int horSplit[] = { 0, 0, 0 }; + int verSplit[] = { 0, 0, 0 }; + for( int yPos = 0; yPos < pcv.lumaHeight; yPos += pcv.maxCUHeight ) + { + for( int xPos = 0; xPos < pcv.lumaWidth; xPos += pcv.maxCUWidth ) + { + const int width = ( xPos + pcv.maxCUWidth > pcv.lumaWidth ) ? ( pcv.lumaWidth - xPos ) : pcv.maxCUWidth; + const int height = ( yPos + pcv.maxCUHeight > pcv.lumaHeight ) ? ( pcv.lumaHeight - yPos ) : pcv.maxCUHeight; + + if( isCrossedByVirtualBoundaries( xPos, yPos, width, height, clipTop, clipBottom, clipLeft, clipRight, numHorSplit, numVerSplit, horSplit, verSplit, cs.slice->getPPS() ) ) + { + int yStart = yPos; + for( int i = 0; i <= numHorSplit; i++ ) + { + const int yEnd = i == numHorSplit ? yPos + height : horSplit[i]; + const int h = yEnd - yStart; + const bool clipT = ( i == 0 && clipTop ) || ( i > 0 ) || ( yStart == 0 ); + const bool clipB = ( i == numHorSplit && clipBottom ) || ( i < numHorSplit ) || ( yEnd == pcv.lumaHeight ); + + int xStart = xPos; + for( int j = 0; j <= numVerSplit; j++ ) + { + const int xEnd = j == numVerSplit ? xPos + width : verSplit[j]; + const int w = xEnd - xStart; + const bool clipL = ( j == 0 && clipLeft ) || ( j > 0 ) || ( xStart == 0 ); + const bool clipR = ( j == numVerSplit && clipRight ) || ( j < numVerSplit ) || ( xEnd == pcv.lumaWidth ); + + 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( recYuv.subBuf( UnitArea( cs.area.chromaFormat, Area( xStart - (clipL ? 0 : MAX_ALF_PADDING_SIZE), yStart - (clipT ? 0 : MAX_ALF_PADDING_SIZE), wBuf, hBuf ) ) ) ); + 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, yStart, w, h ); + deriveClassification( m_classifier, buf.get(COMPONENT_Y), blkDst, blkSrc ); + Area blkPCM( xStart, yStart, w, h ); + resetPCMBlkClassInfo( cs, m_classifier, buf.get(COMPONENT_Y), blkPCM ); + + xStart = xEnd; + } + + yStart = yEnd; + } + } + else + { + Area blk( xPos, yPos, width, height ); + deriveClassification( m_classifier, recLuma, blk, blk ); + Area blkPCM( xPos, yPos, width, height ); + resetPCMBlkClassInfo( cs, m_classifier, recLuma, blkPCM ); + } + } + } +#else Area blk( 0, 0, recLuma.width, recLuma.height ); deriveClassification( m_classifier, recLuma, blk ); Area blkPCM(0, 0, recLuma.width, recLuma.height); resetPCMBlkClassInfo(cs, m_classifier, recLuma, blkPCM); +#endif // get CTB stats for filtering +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + deriveStatsForFiltering( orgYuv, recYuv, cs ); +#else deriveStatsForFiltering( orgYuv, recYuv ); +#endif // derive filter (luma) alfEncoder( cs, alfSliceParam, orgYuv, recYuv, cs.getRecoBuf(), CHANNEL_TYPE_LUMA @@ -966,6 +1031,12 @@ void EncAdaptiveLoopFilter::alfEncoder( CodingStructure& cs, AlfSliceParam& alfS short* clipp = isLuma( compID ) ? m_clippFinal : m_chromaClippFinal; //alfSliceParam.chromaClipp; #endif +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + bool clipTop = false, clipBottom = false, clipLeft = false, clipRight = false; + int numHorSplit = 0, numVerSplit = 0; + int horSplit[] = { 0, 0, 0 }; + int verSplit[] = { 0, 0, 0 }; +#endif for( int yPos = 0; yPos < pcv.lumaHeight; yPos += pcv.maxCUHeight ) { for( int xPos = 0; xPos < pcv.lumaWidth; xPos += pcv.maxCUWidth ) @@ -976,27 +1047,134 @@ void EncAdaptiveLoopFilter::alfEncoder( CodingStructure& cs, AlfSliceParam& alfS if( m_ctuEnableFlag[compID][ctuIdx] ) { +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + if( isCrossedByVirtualBoundaries( xPos, yPos, width, height, clipTop, clipBottom, clipLeft, clipRight, numHorSplit, numVerSplit, horSplit, verSplit, cs.slice->getPPS() ) ) + { + int yStart = yPos; + for( int i = 0; i <= numHorSplit; i++ ) + { + const int yEnd = i == numHorSplit ? yPos + height : horSplit[i]; + const int h = yEnd - yStart; + const bool clipT = ( i == 0 && clipTop ) || ( i > 0 ) || ( yStart == 0 ); + const bool clipB = ( i == numHorSplit && clipBottom ) || ( i < numHorSplit ) || ( yEnd == pcv.lumaHeight ); + + int xStart = xPos; + for( int j = 0; j <= numVerSplit; j++ ) + { + const int xEnd = j == numVerSplit ? xPos + width : verSplit[j]; + const int w = xEnd - xStart; + const bool clipL = ( j == 0 && clipLeft ) || ( j > 0 ) || ( xStart == 0 ); + const bool clipR = ( j == numVerSplit && clipRight ) || ( j < numVerSplit ) || ( xEnd == pcv.lumaWidth ); + + 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( recExtBuf.subBuf( UnitArea( cs.area.chromaFormat, Area( xStart - (clipL ? 0 : MAX_ALF_PADDING_SIZE), yStart - (clipT ? 0 : MAX_ALF_PADDING_SIZE), wBuf, hBuf ) ) ) ); + 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 >> chromaScaleX, h >> chromaScaleY ); + const Area blkDst( xStart >> chromaScaleX, yStart >> chromaScaleY, w >> chromaScaleX, h >> chromaScaleY ); + if( filterType == ALF_FILTER_5 ) + { +#if JVET_N0180_ALF_LINE_BUFFER_REDUCTION +#if JVET_N0242_NON_LINEAR_ALF + m_filter5x5Blk(m_classifier, recBuf, buf, blkDst, blkSrc, compID, coeff, clipp, m_clpRngs.comp[compIdx], cs + , m_alfVBChmaCTUHeight + , ((yPos + pcv.maxCUHeight >= pcv.lumaHeight) ? pcv.lumaHeight : m_alfVBChmaPos) + ); +#else + m_filter5x5Blk(m_classifier, recBuf, buf, blkDst, blkSrc, compID, coeff, m_clpRngs.comp[compIdx], cs + , m_alfVBChmaCTUHeight + , ((yPos + pcv.maxCUHeight >= pcv.lumaHeight) ? pcv.lumaHeight : m_alfVBChmaPos) + ); +#endif +#else +#if JVET_N0242_NON_LINEAR_ALF + m_filter5x5Blk(m_classifier, recBuf, buf, blkDst, blkSrc, compID, coeff, clipp, m_clpRngs.comp[compIdx], cs); +#else + m_filter5x5Blk(m_classifier, recBuf, buf, blkDst, blkSrc, compID, coeff, m_clpRngs.comp[compIdx], cs); +#endif +#endif + } + else if( filterType == ALF_FILTER_7 ) + { +#if JVET_N0180_ALF_LINE_BUFFER_REDUCTION +#if JVET_N0242_NON_LINEAR_ALF + m_filter7x7Blk(m_classifier, recBuf, buf, blkDst, blkSrc, compID, coeff, clipp, m_clpRngs.comp[compIdx], cs + , m_alfVBLumaCTUHeight + , ((yPos + pcv.maxCUHeight >= pcv.lumaHeight) ? pcv.lumaHeight : m_alfVBLumaPos) + ); +#else + m_filter7x7Blk(m_classifier, recBuf, buf, blkDst, blkSrc, compID, coeff, m_clpRngs.comp[compIdx], cs + , m_alfVBLumaCTUHeight + , ((yPos + pcv.maxCUHeight >= pcv.lumaHeight) ? pcv.lumaHeight : m_alfVBLumaPos) + ); +#endif +#else +#if JVET_N0242_NON_LINEAR_ALF + m_filter7x7Blk(m_classifier, recBuf, buf, blkDst, blkSrc, compID, coeff, clipp, m_clpRngs.comp[compIdx], cs); +#else + m_filter7x7Blk(m_classifier, recBuf, buf, blkDst, blkSrc, compID, coeff, m_clpRngs.comp[compIdx], cs); +#endif +#endif + } + else + { + CHECK( 0, "Wrong ALF filter type" ); + } + + xStart = xEnd; + } + + yStart = yEnd; + } + } + else + { +#endif if( filterType == ALF_FILTER_5 ) { #if JVET_N0180_ALF_LINE_BUFFER_REDUCTION #if JVET_N0242_NON_LINEAR_ALF +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + m_filter5x5Blk(m_classifier, recBuf, recExtBuf, blk, blk, compID, coeff, clipp, m_clpRngs.comp[compIdx], cs + , m_alfVBChmaCTUHeight + , ((yPos + pcv.maxCUHeight >= pcv.lumaHeight) ? pcv.lumaHeight : m_alfVBChmaPos) + ); +#else m_filter5x5Blk(m_classifier, recBuf, recExtBuf, blk, compID, coeff, clipp, m_clpRngs.comp[compIdx], cs , m_alfVBChmaCTUHeight , ((yPos + pcv.maxCUHeight >= pcv.lumaHeight) ? pcv.lumaHeight : m_alfVBChmaPos) ); +#endif +#else +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + m_filter5x5Blk(m_classifier, recBuf, recExtBuf, blk, blk, compID, coeff, m_clpRngs.comp[compIdx], cs + , m_alfVBChmaCTUHeight + , ((yPos + pcv.maxCUHeight >= pcv.lumaHeight) ? pcv.lumaHeight : m_alfVBChmaPos) + ); #else m_filter5x5Blk(m_classifier, recBuf, recExtBuf, blk, compID, coeff, m_clpRngs.comp[compIdx], cs , m_alfVBChmaCTUHeight , ((yPos + pcv.maxCUHeight >= pcv.lumaHeight) ? pcv.lumaHeight : m_alfVBChmaPos) ); #endif +#endif #else #if JVET_N0242_NON_LINEAR_ALF +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + m_filter5x5Blk(m_classifier, recBuf, recExtBuf, blk, blk, compID, coeff, clipp, m_clpRngs.comp[compIdx], cs); +#else m_filter5x5Blk(m_classifier, recBuf, recExtBuf, blk, compID, coeff, clipp, m_clpRngs.comp[compIdx], cs); +#endif +#else +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + m_filter5x5Blk(m_classifier, recBuf, recExtBuf, blk, blk, compID, coeff, m_clpRngs.comp[compIdx], cs); #else m_filter5x5Blk(m_classifier, recBuf, recExtBuf, blk, compID, coeff, m_clpRngs.comp[compIdx], cs); #endif - +#endif #endif } @@ -1004,31 +1182,54 @@ void EncAdaptiveLoopFilter::alfEncoder( CodingStructure& cs, AlfSliceParam& alfS { #if JVET_N0180_ALF_LINE_BUFFER_REDUCTION #if JVET_N0242_NON_LINEAR_ALF +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + m_filter7x7Blk(m_classifier, recBuf, recExtBuf, blk, blk, compID, coeff, clipp, m_clpRngs.comp[compIdx], cs + , m_alfVBLumaCTUHeight + , ((yPos + pcv.maxCUHeight >= pcv.lumaHeight) ? pcv.lumaHeight : m_alfVBLumaPos) + ); +#else m_filter7x7Blk(m_classifier, recBuf, recExtBuf, blk, compID, coeff, clipp, m_clpRngs.comp[compIdx], cs , m_alfVBLumaCTUHeight , ((yPos + pcv.maxCUHeight >= pcv.lumaHeight) ? pcv.lumaHeight : m_alfVBLumaPos) ); +#endif +#else +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + m_filter7x7Blk(m_classifier, recBuf, recExtBuf, blk, blk, compID, coeff, m_clpRngs.comp[compIdx], cs + , m_alfVBLumaCTUHeight + , ((yPos + pcv.maxCUHeight >= pcv.lumaHeight) ? pcv.lumaHeight : m_alfVBLumaPos) + ); #else m_filter7x7Blk(m_classifier, recBuf, recExtBuf, blk, compID, coeff, m_clpRngs.comp[compIdx], cs , m_alfVBLumaCTUHeight , ((yPos + pcv.maxCUHeight >= pcv.lumaHeight) ? pcv.lumaHeight : m_alfVBLumaPos) ); #endif - +#endif #else #if JVET_N0242_NON_LINEAR_ALF +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + m_filter7x7Blk(m_classifier, recBuf, recExtBuf, blk, blk, compID, coeff, clipp, m_clpRngs.comp[compIdx], cs); +#else m_filter7x7Blk(m_classifier, recBuf, recExtBuf, blk, compID, coeff, clipp, m_clpRngs.comp[compIdx], cs); +#endif +#else +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + m_filter7x7Blk(m_classifier, recBuf, recExtBuf, blk, blk, compID, coeff, m_clpRngs.comp[compIdx], cs); #else m_filter7x7Blk(m_classifier, recBuf, recExtBuf, blk, compID, coeff, m_clpRngs.comp[compIdx], cs); #endif #endif - +#endif } else { CHECK( 0, "Wrong ALF filter type" ); } +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + } +#endif } ctuIdx++; } @@ -2515,7 +2716,11 @@ void EncAdaptiveLoopFilter::getFrameStat( AlfCovariance* frameCov, AlfCovariance } } +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND +void EncAdaptiveLoopFilter::deriveStatsForFiltering( PelUnitBuf& orgYuv, PelUnitBuf& recYuv, CodingStructure& cs ) +#else void EncAdaptiveLoopFilter::deriveStatsForFiltering( PelUnitBuf& orgYuv, PelUnitBuf& recYuv ) +#endif { int ctuRsAddr = 0; const int numberOfComponents = getNumberValidComponents( m_chromaFormat ); @@ -2562,12 +2767,111 @@ void EncAdaptiveLoopFilter::deriveStatsForFiltering( PelUnitBuf& orgYuv, PelUnit } } +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + const PreCalcValues& pcv = *cs.pcv; + bool clipTop = false, clipBottom = false, clipLeft = false, clipRight = false; + int numHorSplit = 0, numVerSplit = 0; + int horSplit[] = { 0, 0, 0 }; + int verSplit[] = { 0, 0, 0 }; +#endif 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; +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + if( isCrossedByVirtualBoundaries( xPos, yPos, width, height, clipTop, clipBottom, clipLeft, clipRight, numHorSplit, numVerSplit, horSplit, verSplit, cs.slice->getPPS() ) ) + { + int yStart = yPos; + for( int i = 0; i <= numHorSplit; i++ ) + { + const int yEnd = i == numHorSplit ? yPos + height : horSplit[i]; + const int h = yEnd - yStart; + const bool clipT = ( i == 0 && clipTop ) || ( i > 0 ) || ( yStart == 0 ); + const bool clipB = ( i == numHorSplit && clipBottom ) || ( i < numHorSplit ) || ( yEnd == pcv.lumaHeight ); + + int xStart = xPos; + for( int j = 0; j <= numVerSplit; j++ ) + { + const int xEnd = j == numVerSplit ? xPos + width : verSplit[j]; + const int w = xEnd - xStart; + const bool clipL = ( j == 0 && clipLeft ) || ( j > 0 ) || ( xStart == 0 ); + const bool clipR = ( j == numVerSplit && clipRight ) || ( j < numVerSplit ) || ( xEnd == pcv.lumaWidth ); + + 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 recBuf = m_tempBuf2.subBuf( UnitArea( cs.area.chromaFormat, Area( 0, 0, wBuf, hBuf ) ) ); + recBuf.copyFrom( recYuv.subBuf( UnitArea( cs.area.chromaFormat, Area( xStart - (clipL ? 0 : MAX_ALF_PADDING_SIZE), yStart - (clipT ? 0 : MAX_ALF_PADDING_SIZE), wBuf, hBuf ) ) ) ); + recBuf.extendBorderPel( MAX_ALF_PADDING_SIZE ); + recBuf = recBuf.subBuf( UnitArea ( cs.area.chromaFormat, Area( clipL ? 0 : MAX_ALF_PADDING_SIZE, clipT ? 0 : MAX_ALF_PADDING_SIZE, w, h ) ) ); + + const UnitArea area( m_chromaFormat, Area( 0, 0, w, h ) ); + const UnitArea areaDst( m_chromaFormat, Area( xStart, yStart, w, h ) ); + for( int compIdx = 0; compIdx < numberOfComponents; compIdx++ ) + { + const ComponentID compID = ComponentID( compIdx ); + const CompArea& compArea = area.block( compID ); + const CompArea& compAreaDst = areaDst.block( compID ); + + int recStride = recBuf.get( compID ).stride; + Pel* rec = recBuf.get( compID ).bufAt( compArea ); + + int orgStride = orgYuv.get(compID).stride; + Pel* org = orgYuv.get(compID).bufAt(xStart >> ::getComponentScaleX(compID, m_chromaFormat), yStart >> ::getComponentScaleY(compID, m_chromaFormat)); + + ChannelType chType = toChannelType( compID ); + + for( int shape = 0; shape != m_filterShapes[chType].size(); shape++ ) + { +#if JVET_N0180_ALF_LINE_BUFFER_REDUCTION +#if JVET_N0242_NON_LINEAR_ALF + getBlkStats(m_alfCovariance[compIdx][shape][ctuRsAddr], m_filterShapes[chType][shape], compIdx ? nullptr : m_classifier, org, orgStride, rec, recStride, compAreaDst, compArea, chType + , ((compIdx == 0) ? m_alfVBLumaCTUHeight : m_alfVBChmaCTUHeight) + , ((yPos + m_maxCUHeight >= m_picHeight) ? m_picHeight : ((compIdx == 0) ? m_alfVBLumaPos : m_alfVBChmaPos)) + ); +#else + getBlkStats(m_alfCovariance[compIdx][shape][ctuRsAddr], m_filterShapes[chType][shape], compIdx ? nullptr : m_classifier, org, orgStride, rec, recStride, compArea, compArea + , ((compIdx == 0) ? m_alfVBLumaCTUHeight : m_alfVBChmaCTUHeight) + , ((yPos + m_maxCUHeight >= m_picHeight) ? m_picHeight : ((compIdx == 0) ? m_alfVBLumaPos : m_alfVBChmaPos)) + ); +#endif +#else +#if JVET_N0242_NON_LINEAR_ALF + getBlkStats(m_alfCovariance[compIdx][shape][ctuRsAddr], m_filterShapes[chType][shape], compIdx ? nullptr : m_classifier, org, orgStride, rec, recStride, compAreaDst, compArea, chType); +#else + getBlkStats(m_alfCovariance[compIdx][shape][ctuRsAddr], m_filterShapes[chType][shape], compIdx ? nullptr : m_classifier, org, orgStride, rec, recStride, compAreaDst, compArea); +#endif +#endif + } + } + + xStart = xEnd; + } + + yStart = yEnd; + } + + for( int compIdx = 0; compIdx < numberOfComponents; compIdx++ ) + { + const ComponentID compID = ComponentID( compIdx ); + + ChannelType chType = toChannelType( compID ); + + for( int shape = 0; shape != m_filterShapes[chType].size(); shape++ ) + { + const int numClasses = isLuma( compID ) ? MAX_NUM_ALF_CLASSES : 1; + + for( int classIdx = 0; classIdx < numClasses; classIdx++ ) + { + m_alfCovarianceFrame[chType][shape][classIdx] += m_alfCovariance[compIdx][shape][ctuRsAddr][classIdx]; + } + } + } + } + else + { +#endif const UnitArea area( m_chromaFormat, Area( xPos, yPos, width, height ) ); for( int compIdx = 0; compIdx < numberOfComponents; compIdx++ ) @@ -2587,22 +2891,44 @@ void EncAdaptiveLoopFilter::deriveStatsForFiltering( PelUnitBuf& orgYuv, PelUnit { #if JVET_N0180_ALF_LINE_BUFFER_REDUCTION #if JVET_N0242_NON_LINEAR_ALF +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + getBlkStats(m_alfCovariance[compIdx][shape][ctuRsAddr], m_filterShapes[chType][shape], compIdx ? nullptr : m_classifier, org, orgStride, rec, recStride, compArea, compArea, chType + , ((compIdx == 0) ? m_alfVBLumaCTUHeight : m_alfVBChmaCTUHeight) + , ((yPos + m_maxCUHeight >= m_picHeight) ? m_picHeight : ((compIdx == 0) ? m_alfVBLumaPos : m_alfVBChmaPos)) + ); +#else getBlkStats(m_alfCovariance[compIdx][shape][ctuRsAddr], m_filterShapes[chType][shape], compIdx ? nullptr : m_classifier, org, orgStride, rec, recStride, compArea, chType , ((compIdx == 0) ? m_alfVBLumaCTUHeight : m_alfVBChmaCTUHeight) , ((yPos + m_maxCUHeight >= m_picHeight) ? m_picHeight : ((compIdx == 0) ? m_alfVBLumaPos : m_alfVBChmaPos)) ); +#endif +#else +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + getBlkStats(m_alfCovariance[compIdx][shape][ctuRsAddr], m_filterShapes[chType][shape], compIdx ? nullptr : m_classifier, org, orgStride, rec, recStride, compArea, compArea + , ((compIdx == 0) ? m_alfVBLumaCTUHeight : m_alfVBChmaCTUHeight) + , ((yPos + m_maxCUHeight >= m_picHeight) ? m_picHeight : ((compIdx == 0) ? m_alfVBLumaPos : m_alfVBChmaPos)) + ); #else getBlkStats(m_alfCovariance[compIdx][shape][ctuRsAddr], m_filterShapes[chType][shape], compIdx ? nullptr : m_classifier, org, orgStride, rec, recStride, compArea , ((compIdx == 0) ? m_alfVBLumaCTUHeight : m_alfVBChmaCTUHeight) , ((yPos + m_maxCUHeight >= m_picHeight) ? m_picHeight : ((compIdx == 0) ? m_alfVBLumaPos : m_alfVBChmaPos)) ); #endif +#endif #else #if JVET_N0242_NON_LINEAR_ALF +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + getBlkStats(m_alfCovariance[compIdx][shape][ctuRsAddr], m_filterShapes[chType][shape], compIdx ? nullptr : m_classifier, org, orgStride, rec, recStride, compArea, compArea, chType); +#else getBlkStats(m_alfCovariance[compIdx][shape][ctuRsAddr], m_filterShapes[chType][shape], compIdx ? nullptr : m_classifier, org, orgStride, rec, recStride, compArea, chType); +#endif +#else +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + getBlkStats(m_alfCovariance[compIdx][shape][ctuRsAddr], m_filterShapes[chType][shape], compIdx ? nullptr : m_classifier, org, orgStride, rec, recStride, compArea, compArea); #else getBlkStats(m_alfCovariance[compIdx][shape][ctuRsAddr], m_filterShapes[chType][shape], compIdx ? nullptr : m_classifier, org, orgStride, rec, recStride, compArea); #endif +#endif #endif @@ -2614,6 +2940,9 @@ void EncAdaptiveLoopFilter::deriveStatsForFiltering( PelUnitBuf& orgYuv, PelUnit } } } +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + } +#endif ctuRsAddr++; } } @@ -2621,18 +2950,33 @@ void EncAdaptiveLoopFilter::deriveStatsForFiltering( PelUnitBuf& orgYuv, PelUnit #if JVET_N0180_ALF_LINE_BUFFER_REDUCTION #if JVET_N0242_NON_LINEAR_ALF +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND +void EncAdaptiveLoopFilter::getBlkStats(AlfCovariance* alfCovariance, const AlfFilterShape& shape, AlfClassifier** classifier, Pel* org, const int orgStride, Pel* rec, const int recStride, const CompArea& areaDst, const CompArea& area, const ChannelType channel, int vbCTUHeight, int vbPos) +#else void EncAdaptiveLoopFilter::getBlkStats(AlfCovariance* alfCovariance, const AlfFilterShape& shape, AlfClassifier** classifier, Pel* org, const int orgStride, Pel* rec, const int recStride, const CompArea& area, const ChannelType channel, int vbCTUHeight, int vbPos) +#endif +#else +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND +void EncAdaptiveLoopFilter::getBlkStats(AlfCovariance* alfCovariace, const AlfFilterShape& shape, AlfClassifier** classifier, Pel* org, const int orgStride, Pel* rec, const int recStride, const CompArea& areaDst, const CompArea& area, int vbCTUHeight, int vbPos) #else void EncAdaptiveLoopFilter::getBlkStats(AlfCovariance* alfCovariace, const AlfFilterShape& shape, AlfClassifier** classifier, Pel* org, const int orgStride, Pel* rec, const int recStride, const CompArea& area, int vbCTUHeight, int vbPos) #endif +#endif #else #if JVET_N0242_NON_LINEAR_ALF +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND +void EncAdaptiveLoopFilter::getBlkStats(AlfCovariance* alfCovariance, const AlfFilterShape& shape, AlfClassifier** classifier, Pel* org, const int orgStride, Pel* rec, const int recStride, const CompArea& areaDst, const CompArea& area, const ChannelType channel) +#else void EncAdaptiveLoopFilter::getBlkStats(AlfCovariance* alfCovariance, const AlfFilterShape& shape, AlfClassifier** classifier, Pel* org, const int orgStride, Pel* rec, const int recStride, const CompArea& area, const ChannelType channel) +#endif +#else +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND +void EncAdaptiveLoopFilter::getBlkStats(AlfCovariance* alfCovariace, const AlfFilterShape& shape, AlfClassifier** classifier, Pel* org, const int orgStride, Pel* rec, const int recStride, const CompArea& areaDst, const CompArea& area) #else void EncAdaptiveLoopFilter::getBlkStats(AlfCovariance* alfCovariace, const AlfFilterShape& shape, AlfClassifier** classifier, Pel* org, const int orgStride, Pel* rec, const int recStride, const CompArea& area) #endif - +#endif #endif @@ -2651,11 +2995,19 @@ void EncAdaptiveLoopFilter::getBlkStats(AlfCovariance* alfCovariace, const AlfFi for( int i = 0; i < area.height; i++ ) { #if JVET_N0180_ALF_LINE_BUFFER_REDUCTION +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + int vbDistance = ((areaDst.y + i) % vbCTUHeight) - vbPos; +#else int vbDistance = (i % vbCTUHeight) - vbPos; +#endif #endif for( int j = 0; j < area.width; j++ ) { +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + if( classifier && classifier[areaDst.y + i][areaDst.x + j].classIdx == m_ALF_UNUSED_CLASSIDX && classifier[areaDst.y + i][areaDst.x + j].transposeIdx == m_ALF_UNUSED_TRANSPOSIDX ) +#else if( classifier && classifier[area.y + i][area.x + j].classIdx == m_ALF_UNUSED_CLASSIDX && classifier[area.y + i][area.x + j].transposeIdx == m_ALF_UNUSED_TRANSPOSIDX ) +#endif { continue; } @@ -2666,7 +3018,11 @@ void EncAdaptiveLoopFilter::getBlkStats(AlfCovariance* alfCovariace, const AlfFi #endif if( classifier ) { +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + AlfClassifier& cl = classifier[areaDst.y + i][areaDst.x + j]; +#else AlfClassifier& cl = classifier[area.y + i][area.x + j]; +#endif transposeIdx = cl.transposeIdx; classIdx = cl.classIdx; } @@ -3781,12 +4137,135 @@ void EncAdaptiveLoopFilter::alfReconstructor(CodingStructure& cs, const PelUnitB const PreCalcValues& pcv = *cs.pcv; int ctuIdx = 0; +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + bool clipTop = false, clipBottom = false, clipLeft = false, clipRight = false; + int numHorSplit = 0, numVerSplit = 0; + int horSplit[] = { 0, 0, 0 }; + int verSplit[] = { 0, 0, 0 }; +#endif for (int yPos = 0; yPos < pcv.lumaHeight; yPos += pcv.maxCUHeight) { for (int xPos = 0; xPos < pcv.lumaWidth; xPos += pcv.maxCUWidth) { const int width = (xPos + pcv.maxCUWidth > pcv.lumaWidth) ? (pcv.lumaWidth - xPos) : pcv.maxCUWidth; const int height = (yPos + pcv.maxCUHeight > pcv.lumaHeight) ? (pcv.lumaHeight - yPos) : pcv.maxCUHeight; + +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + bool ctuEnableFlag = m_ctuEnableFlag[COMPONENT_Y][ctuIdx]; + for (int compIdx = 1; compIdx < MAX_NUM_COMPONENT; compIdx++) + { + ctuEnableFlag |= m_ctuEnableFlag[compIdx][ctuIdx] > 0; + } + if (ctuEnableFlag && isCrossedByVirtualBoundaries(xPos, yPos, width, height, clipTop, clipBottom, clipLeft, clipRight, numHorSplit, numVerSplit, horSplit, verSplit, cs.slice->getPPS())) + { + int yStart = yPos; + for (int i = 0; i <= numHorSplit; i++) + { + const int yEnd = i == numHorSplit ? yPos + height : horSplit[i]; + const int h = yEnd - yStart; + const bool clipT = (i == 0 && clipTop) || (i > 0) || (yStart == 0); + const bool clipB = (i == numHorSplit && clipBottom) || (i < numHorSplit) || (yEnd == pcv.lumaHeight); + + int xStart = xPos; + for (int j = 0; j <= numVerSplit; j++) + { + const int xEnd = j == numVerSplit ? xPos + width : verSplit[j]; + const int w = xEnd - xStart; + const bool clipL = (j == 0 && clipLeft) || (j > 0) || (xStart == 0); + const bool clipR = (j == numVerSplit && clipRight) || (j < numVerSplit) || (xEnd == pcv.lumaWidth); + + 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(recExtBuf.subBuf(UnitArea(cs.area.chromaFormat, Area(xStart - (clipL ? 0 : MAX_ALF_PADDING_SIZE), yStart - (clipT ? 0 : MAX_ALF_PADDING_SIZE), wBuf, hBuf)))); + 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))); + + if (m_ctuEnableFlag[COMPONENT_Y][ctuIdx]) + { + const Area blkSrc(0, 0, w, h); + const Area blkDst(xStart, yStart, w, h); + short filterSetIndex = alfCtuFilterIndex[ctuIdx]; + short *coeff; +#if JVET_N0242_NON_LINEAR_ALF + short *clip; +#endif + if (filterSetIndex >= NUM_FIXED_FILTER_SETS) + { + coeff = m_coeffApsLuma[filterSetIndex - NUM_FIXED_FILTER_SETS]; +#if JVET_N0242_NON_LINEAR_ALF + clip = m_clippApsLuma[filterSetIndex - NUM_FIXED_FILTER_SETS]; +#endif + } + else + { + coeff = m_fixedFilterSetCoeffDec[filterSetIndex]; +#if JVET_N0242_NON_LINEAR_ALF + clip = m_clipDefault; +#endif + } +#if JVET_N0180_ALF_LINE_BUFFER_REDUCTION +#if JVET_N0242_NON_LINEAR_ALF + m_filter7x7Blk(m_classifier, recBuf, buf, blkDst, blkSrc, COMPONENT_Y, coeff, clip, m_clpRngs.comp[COMPONENT_Y], cs + , m_alfVBLumaCTUHeight + , ((yPos + pcv.maxCUHeight >= pcv.lumaHeight) ? pcv.lumaHeight : m_alfVBLumaPos) + ); +#else + m_filter7x7Blk(m_classifier, recBuf, buf, blkDst, blkSrc, COMPONENT_Y, coeff, m_clpRngs.comp[COMPONENT_Y], cs + , m_alfVBLumaCTUHeight + , ((yPos + pcv.maxCUHeight >= pcv.lumaHeight) ? pcv.lumaHeight : m_alfVBLumaPos) + ); +#endif +#else +#if JVET_N0242_NON_LINEAR_ALF + m_filter7x7Blk(m_classifier, recBuf, buf, blkDst, blkSrc, COMPONENT_Y, coeff, clip, m_clpRngs.comp[COMPONENT_Y], cs); +#else + m_filter7x7Blk(m_classifier, recBuf, buf, blkDst, blkSrc, COMPONENT_Y, coeff, m_clpRngs.comp[COMPONENT_Y], cs); +#endif +#endif + } + + for (int compIdx = 1; compIdx < MAX_NUM_COMPONENT; compIdx++) + { + ComponentID compID = ComponentID(compIdx); + const int chromaScaleX = getComponentScaleX(compID, recBuf.chromaFormat); + const int chromaScaleY = getComponentScaleY(compID, recBuf.chromaFormat); + if (m_ctuEnableFlag[compIdx][ctuIdx]) + { + const Area blkSrc(0, 0, w >> chromaScaleX, h >> chromaScaleY); + const Area blkDst(xStart >> chromaScaleX, yStart >> chromaScaleY, w >> chromaScaleX, h >> chromaScaleY); +#if JVET_N0180_ALF_LINE_BUFFER_REDUCTION +#if JVET_N0242_NON_LINEAR_ALF + m_filter5x5Blk(m_classifier, recBuf, buf, blkDst, blkSrc, compID, m_chromaCoeffFinal, m_chromaClippFinal, m_clpRngs.comp[compIdx], cs + , m_alfVBChmaCTUHeight + , ((yPos + pcv.maxCUHeight >= pcv.lumaHeight) ? pcv.lumaHeight : m_alfVBChmaPos) + ); +#else + m_filter5x5Blk(m_classifier, recBuf, buf, blkDst, blkSrc, compID, m_chromaCoeffFinal, m_clpRngs.comp[compIdx], cs + , m_alfVBChmaCTUHeight + , ((yPos + pcv.maxCUHeight >= pcv.lumaHeight) ? pcv.lumaHeight : m_alfVBChmaPos) + ); +#endif +#else +#if JVET_N0242_NON_LINEAR_ALF + m_filter5x5Blk(m_classifier, recBuf, buf, blkDst, blkSrc, compID, m_chromaCoeffFinal, m_chromaClippFinal, m_clpRngs.comp[compIdx], cs); +#else + m_filter5x5Blk(m_classifier, recBuf, buf, blkDst, blkSrc, compID, m_chromaCoeffFinal, m_clpRngs.comp[compIdx], cs); +#endif +#endif + } + } + + xStart = xEnd; + } + + yStart = yEnd; + } + } + else + { +#endif + const UnitArea area(cs.area.chromaFormat, Area(xPos, yPos, width, height)); if (m_ctuEnableFlag[COMPONENT_Y][ctuIdx]) { @@ -3810,6 +4289,27 @@ void EncAdaptiveLoopFilter::alfReconstructor(CodingStructure& cs, const PelUnitB clip = m_clipDefault; #endif } +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND +#if JVET_N0180_ALF_LINE_BUFFER_REDUCTION +#if JVET_N0242_NON_LINEAR_ALF + m_filter7x7Blk(m_classifier, recBuf, recExtBuf, blk, blk, COMPONENT_Y, coeff, clip, m_clpRngs.comp[COMPONENT_Y], cs + , m_alfVBLumaCTUHeight + , ((yPos + pcv.maxCUHeight >= pcv.lumaHeight) ? pcv.lumaHeight : m_alfVBLumaPos) + ); +#else + m_filter7x7Blk(m_classifier, recBuf, recExtBuf, blk, blk, COMPONENT_Y, coeff, m_clpRngs.comp[COMPONENT_Y], cs + , m_alfVBLumaCTUHeight + , ((yPos + pcv.maxCUHeight >= pcv.lumaHeight) ? pcv.lumaHeight : m_alfVBLumaPos) + ); +#endif +#else +#if JVET_N0242_NON_LINEAR_ALF + m_filter7x7Blk(m_classifier, recBuf, recExtBuf, blk, blk, COMPONENT_Y, coeff, clip, m_clpRngs.comp[COMPONENT_Y], cs); +#else + m_filter7x7Blk(m_classifier, recBuf, recExtBuf, blk, blk, COMPONENT_Y, coeff, m_clpRngs.comp[COMPONENT_Y], cs); +#endif +#endif +#else #if JVET_N0180_ALF_LINE_BUFFER_REDUCTION #if JVET_N0242_NON_LINEAR_ALF m_filter7x7Blk(m_classifier, recBuf, recExtBuf, blk, COMPONENT_Y, coeff, clip, m_clpRngs.comp[COMPONENT_Y], cs @@ -3828,6 +4328,7 @@ void EncAdaptiveLoopFilter::alfReconstructor(CodingStructure& cs, const PelUnitB #else m_filter7x7Blk(m_classifier, recBuf, recExtBuf, blk, COMPONENT_Y, coeff, m_clpRngs.comp[COMPONENT_Y], cs); #endif +#endif #endif } @@ -3839,6 +4340,27 @@ void EncAdaptiveLoopFilter::alfReconstructor(CodingStructure& cs, const PelUnitB if (m_ctuEnableFlag[compIdx][ctuIdx]) { Area blk(xPos >> chromaScaleX, yPos >> chromaScaleY, width >> chromaScaleX, height >> chromaScaleY); +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND +#if JVET_N0180_ALF_LINE_BUFFER_REDUCTION +#if JVET_N0242_NON_LINEAR_ALF + m_filter5x5Blk(m_classifier, recBuf, recExtBuf, blk, blk, compID, m_chromaCoeffFinal, m_chromaClippFinal, m_clpRngs.comp[compIdx], cs + , m_alfVBChmaCTUHeight + , ((yPos + pcv.maxCUHeight >= pcv.lumaHeight) ? pcv.lumaHeight : m_alfVBChmaPos) + ); +#else + m_filter5x5Blk(m_classifier, recBuf, recExtBuf, blk, blk, compID, m_chromaCoeffFinal, m_clpRngs.comp[compIdx], cs + , m_alfVBChmaCTUHeight + , ((yPos + pcv.maxCUHeight >= pcv.lumaHeight) ? pcv.lumaHeight : m_alfVBChmaPos) + ); +#endif +#else +#if JVET_N0242_NON_LINEAR_ALF + m_filter5x5Blk(m_classifier, recBuf, recExtBuf, blk, blk, compID, m_chromaCoeffFinal, m_chromaClippFinal, m_clpRngs.comp[compIdx], cs); +#else + m_filter5x5Blk(m_classifier, recBuf, recExtBuf, blk, blk, compID, m_chromaCoeffFinal, m_clpRngs.comp[compIdx], cs); +#endif +#endif +#else #if JVET_N0180_ALF_LINE_BUFFER_REDUCTION #if JVET_N0242_NON_LINEAR_ALF m_filter5x5Blk(m_classifier, recBuf, recExtBuf, blk, compID, m_chromaCoeffFinal, m_chromaClippFinal, m_clpRngs.comp[compIdx], cs @@ -3857,9 +4379,13 @@ void EncAdaptiveLoopFilter::alfReconstructor(CodingStructure& cs, const PelUnitB #else m_filter5x5Blk(m_classifier, recBuf, recExtBuf, blk, compID, m_chromaCoeffFinal, m_clpRngs.comp[compIdx], cs); #endif +#endif #endif } } +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + } +#endif ctuIdx++; } } diff --git a/source/Lib/EncoderLib/EncAdaptiveLoopFilter.h b/source/Lib/EncoderLib/EncAdaptiveLoopFilter.h index c2bdee5e445216af425dcd81cf25e0de7d1af5b3..7639d828186a4c2ae9545d593ea8b14f18f0ce7a 100644 --- a/source/Lib/EncoderLib/EncAdaptiveLoopFilter.h +++ b/source/Lib/EncoderLib/EncAdaptiveLoopFilter.h @@ -429,24 +429,44 @@ private: void getFrameStats( ChannelType channel, int iShapeIdx ); void getFrameStat( AlfCovariance* frameCov, AlfCovariance** ctbCov, uint8_t* ctbEnableFlags, const int numClasses ); +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + void deriveStatsForFiltering( PelUnitBuf& orgYuv, PelUnitBuf& recYuv, CodingStructure& cs ); +#else void deriveStatsForFiltering( PelUnitBuf& orgYuv, PelUnitBuf& recYuv ); +#endif #if JVET_N0180_ALF_LINE_BUFFER_REDUCTION #if JVET_N0242_NON_LINEAR_ALF +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + void getBlkStats(AlfCovariance* alfCovariace, const AlfFilterShape& shape, AlfClassifier** classifier, Pel* org, const int orgStride, Pel* rec, const int recStride, const CompArea& areaDst, const CompArea& area, const ChannelType channel, int vbCTUHeight, int vbPos); +#else void getBlkStats(AlfCovariance* alfCovariace, const AlfFilterShape& shape, AlfClassifier** classifier, Pel* org, const int orgStride, Pel* rec, const int recStride, const CompArea& area, const ChannelType channel, int vbCTUHeight, int vbPos); +#endif void calcCovariance(int ELocal[MAX_NUM_ALF_LUMA_COEFF][MaxAlfNumClippingValues], const Pel *rec, const int stride, const AlfFilterShape& shape, const int transposeIdx, const ChannelType channel, int vbDistance); void mergeClasses(const AlfFilterShape& alfShape, AlfCovariance* cov, AlfCovariance* covMerged, int clipMerged[MAX_NUM_ALF_CLASSES][MAX_NUM_ALF_CLASSES][MAX_NUM_ALF_LUMA_COEFF], const int numClasses, short filterIndices[MAX_NUM_ALF_CLASSES][MAX_NUM_ALF_CLASSES]); +#else +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + void getBlkStats(AlfCovariance* alfCovariace, const AlfFilterShape& shape, AlfClassifier** classifier, Pel* org, const int orgStride, Pel* rec, const int recStride, const CompArea& areaDst, const CompArea& area, int vbCTUHeight, int vbPos); #else void getBlkStats(AlfCovariance* alfCovariace, const AlfFilterShape& shape, AlfClassifier** classifier, Pel* org, const int orgStride, Pel* rec, const int recStride, const CompArea& area, int vbCTUHeight, int vbPos); +#endif void calcCovariance(int *ELocal, const Pel *rec, const int stride, const int *filterPattern, const int halfFilterLength, const int transposeIdx, int vbDistance); void mergeClasses(AlfCovariance* cov, AlfCovariance* covMerged, const int numClasses, short filterIndices[MAX_NUM_ALF_CLASSES][MAX_NUM_ALF_CLASSES]); #endif #else #if JVET_N0242_NON_LINEAR_ALF +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + void getBlkStats(AlfCovariance* alfCovariace, const AlfFilterShape& shape, AlfClassifier** classifier, Pel* org, const int orgStride, Pel* rec, const int recStride, const CompArea& areaDst, const CompArea& area, const ChannelType channel); +#else void getBlkStats(AlfCovariance* alfCovariace, const AlfFilterShape& shape, AlfClassifier** classifier, Pel* org, const int orgStride, Pel* rec, const int recStride, const CompArea& area, const ChannelType channel); +#endif void calcCovariance(int ELocal[MAX_NUM_ALF_LUMA_COEFF][MaxAlfNumClippingValues], const Pel *rec, const int stride, const AlfFilterShape& shape, const int transposeIdx, const ChannelType channel); void mergeClasses(const AlfFilterShape& alfShape, AlfCovariance* cov, AlfCovariance* covMerged, int clipMerged[MAX_NUM_ALF_CLASSES][MAX_NUM_ALF_CLASSES][MAX_NUM_ALF_LUMA_COEFF], const int numClasses, short filterIndices[MAX_NUM_ALF_CLASSES][MAX_NUM_ALF_CLASSES]); +#else +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + void getBlkStats(AlfCovariance* alfCovariace, const AlfFilterShape& shape, AlfClassifier** classifier, Pel* org, const int orgStride, Pel* rec, const int recStride, const CompArea& areaDst, const CompArea& area); #else void getBlkStats(AlfCovariance* alfCovariace, const AlfFilterShape& shape, AlfClassifier** classifier, Pel* org, const int orgStride, Pel* rec, const int recStride, const CompArea& area); +#endif void calcCovariance(int *ELocal, const Pel *rec, const int stride, const int *filterPattern, const int halfFilterLength, const int transposeIdx); void mergeClasses(AlfCovariance* cov, AlfCovariance* covMerged, const int numClasses, short filterIndices[MAX_NUM_ALF_CLASSES][MAX_NUM_ALF_CLASSES]); #endif diff --git a/source/Lib/EncoderLib/EncCfg.h b/source/Lib/EncoderLib/EncCfg.h index 14f87d08aadecbe495245ebf8d4fa3d8a4e09483..e80b104dbf1e75857e9b8344871a37997c707b08 100644 --- a/source/Lib/EncoderLib/EncCfg.h +++ b/source/Lib/EncoderLib/EncCfg.h @@ -268,6 +268,13 @@ protected: unsigned m_wrapAroundOffset; // ADD_NEW_TOOL : (encoder lib) add tool enabling flags and associated parameters here +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + bool m_loopFilterAcrossVirtualBoundariesDisabledFlag; + unsigned m_numVerVirtualBoundaries; + unsigned m_numHorVirtualBoundaries; + unsigned m_virtualBoundariesPosX[3]; + unsigned m_virtualBoundariesPosY[3]; +#endif bool m_lumaReshapeEnable; unsigned m_reshapeSignalType; unsigned m_intraCMD; @@ -834,6 +841,18 @@ public: unsigned getWrapAroundOffset () const { return m_wrapAroundOffset; } // ADD_NEW_TOOL : (encoder lib) add access functions here +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + void setLoopFilterAcrossVirtualBoundariesDisabledFlag( bool b ) { m_loopFilterAcrossVirtualBoundariesDisabledFlag = b; } + bool getLoopFilterAcrossVirtualBoundariesDisabledFlag() const { return m_loopFilterAcrossVirtualBoundariesDisabledFlag; } + void setNumVerVirtualBoundaries ( unsigned u ) { m_numVerVirtualBoundaries = u; } + unsigned getNumVerVirtualBoundaries () const { return m_numVerVirtualBoundaries; } + void setNumHorVirtualBoundaries ( unsigned u ) { m_numHorVirtualBoundaries = u; } + unsigned getNumHorVirtualBoundaries () const { return m_numHorVirtualBoundaries; } + void setVirtualBoundariesPosX ( unsigned u, unsigned idx ) { m_virtualBoundariesPosX[idx] = u; } + unsigned getVirtualBoundariesPosX ( unsigned idx ) const { return m_virtualBoundariesPosX[idx]; } + void setVirtualBoundariesPosY ( unsigned u, unsigned idx ) { m_virtualBoundariesPosY[idx] = u; } + unsigned getVirtualBoundariesPosY ( unsigned idx ) const { return m_virtualBoundariesPosY[idx]; } +#endif #if INCLUDE_ISP_CFG_FLAG void setUseISP ( bool b ) { m_ISP = b; } bool getUseISP () const { return m_ISP; } diff --git a/source/Lib/EncoderLib/EncLib.cpp b/source/Lib/EncoderLib/EncLib.cpp index 4512f3669da90bde8e2696cb483d13ce2873772d..ba165ab8af3ec9c0d9cbd92550a4fcc11883e8be 100644 --- a/source/Lib/EncoderLib/EncLib.cpp +++ b/source/Lib/EncoderLib/EncLib.cpp @@ -1539,6 +1539,20 @@ void EncLib::xInitPPS(PPS &pps, const SPS &sps) xInitPPSforTiles(pps); +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + pps.setLoopFilterAcrossVirtualBoundariesDisabledFlag( m_loopFilterAcrossVirtualBoundariesDisabledFlag ); + pps.setNumVerVirtualBoundaries ( m_numVerVirtualBoundaries ); + pps.setNumHorVirtualBoundaries ( m_numHorVirtualBoundaries ); + for( unsigned int i = 0; i < m_numVerVirtualBoundaries; i++ ) + { + pps.setVirtualBoundariesPosX ( m_virtualBoundariesPosX[i], i ); + } + for( unsigned int i = 0; i < m_numHorVirtualBoundaries; i++ ) + { + pps.setVirtualBoundariesPosY ( m_virtualBoundariesPosY[i], i ); + } +#endif + pps.pcv = new PreCalcValues( sps, pps, true ); } diff --git a/source/Lib/EncoderLib/EncSampleAdaptiveOffset.cpp b/source/Lib/EncoderLib/EncSampleAdaptiveOffset.cpp index c0e732998b842f376f42abf2dd56dc2faab96f2f..e0994413fdc15c9023edbcc8f121fdd26c52cd77 100644 --- a/source/Lib/EncoderLib/EncSampleAdaptiveOffset.cpp +++ b/source/Lib/EncoderLib/EncSampleAdaptiveOffset.cpp @@ -311,6 +311,13 @@ void EncSampleAdaptiveOffset::getStatistics(std::vector<SAOStatData**>& blkStats isBelowAvail = (yPos + pcv.maxCUHeight < pcv.lumaHeight); isAboveRightAvail = ((yPos > 0) && (isRightAvail)); +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + int numHorVirBndry = 0, numVerVirBndry = 0; + int horVirBndryPos[] = { -1,-1,-1 }; + int verVirBndryPos[] = { -1,-1,-1 }; + bool isCTUCrossVirtualBoundaries = isCrossedVirtualBoundaries(xPos, yPos, width, height, numHorVirBndry, numVerVirBndry, horVirBndryPos, verVirBndryPos, cs.slice->getPPS()); +#endif + for(int compIdx = 0; compIdx < numberOfComponents; compIdx++) { const ComponentID compID = ComponentID(compIdx); @@ -322,10 +329,24 @@ void EncSampleAdaptiveOffset::getStatistics(std::vector<SAOStatData**>& blkStats int orgStride = orgYuv.get(compID).stride; Pel* orgBlk = orgYuv.get(compID).bufAt( compArea ); +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + for (int i = 0; i < numHorVirBndry; i++) + { + horVirBndryPos[i] = (horVirBndryPos[i] >> ::getComponentScaleY(compID, area.chromaFormat)) - compArea.y; + } + for (int i = 0; i < numVerVirBndry; i++) + { + verVirBndryPos[i] = (verVirBndryPos[i] >> ::getComponentScaleX(compID, area.chromaFormat)) - compArea.x; + } +#endif + getBlkStats(compID, cs.sps->getBitDepth(toChannelType(compID)), blkStats[ctuRsAddr][compID] , srcBlk, orgBlk, srcStride, orgStride, compArea.width, compArea.height , isLeftAvail, isRightAvail, isAboveAvail, isBelowAvail, isAboveLeftAvail, isAboveRightAvail , isCalculatePreDeblockSamples +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + , isCTUCrossVirtualBoundaries, horVirBndryPos, verVirBndryPos, numHorVirBndry, numVerVirBndry +#endif ); } ctuRsAddr++; @@ -1135,6 +1156,9 @@ void EncSampleAdaptiveOffset::getBlkStats(const ComponentID compIdx, const int c , Pel* srcBlk, Pel* orgBlk, int srcStride, int orgStride, int width, int height , bool isLeftAvail, bool isRightAvail, bool isAboveAvail, bool isBelowAvail, bool isAboveLeftAvail, bool isAboveRightAvail , bool isCalculatePreDeblockSamples +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + , bool isCTUCrossVirtualBoundaries, int horVirBndryPos[], int verVirBndryPos[], int numHorVirBndry, int numVerVirBndry +#endif ) { int x,y, startX, startY, endX, endY, edgeType, firstLineStartX, firstLineEndX; @@ -1172,6 +1196,13 @@ void EncSampleAdaptiveOffset::getBlkStats(const ComponentID compIdx, const int c for (x=startX; x<endX; x++) { signRight = (int8_t)sgn(srcLine[x] - srcLine[x+1]); +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + if (isCTUCrossVirtualBoundaries && isProcessDisabled(x, y, numVerVirBndry, 0, verVirBndryPos, horVirBndryPos)) + { + signLeft = -signRight; + continue; + } +#endif edgeType = signRight + signLeft; signLeft = -signRight; @@ -1194,6 +1225,13 @@ void EncSampleAdaptiveOffset::getBlkStats(const ComponentID compIdx, const int c for (x=startX; x<endX; x++) { signRight = (int8_t)sgn(srcLine[x] - srcLine[x+1]); +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + if (isCTUCrossVirtualBoundaries && isProcessDisabled(x, endY + y, numVerVirBndry, 0, verVirBndryPos, horVirBndryPos)) + { + signLeft = -signRight; + continue; + } +#endif edgeType = signRight + signLeft; signLeft = -signRight; @@ -1241,6 +1279,13 @@ void EncSampleAdaptiveOffset::getBlkStats(const ComponentID compIdx, const int c for (x=startX; x<endX; x++) { signDown = (int8_t)sgn(srcLine[x] - srcLineBelow[x]); +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + if (isCTUCrossVirtualBoundaries && isProcessDisabled(x, y, 0, numHorVirBndry, verVirBndryPos, horVirBndryPos)) + { + signUpLine[x] = -signDown; + continue; + } +#endif edgeType = signDown + signUpLine[x]; signUpLine[x]= -signDown; @@ -1264,6 +1309,12 @@ void EncSampleAdaptiveOffset::getBlkStats(const ComponentID compIdx, const int c for (x=startX; x<endX; x++) { +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + if (isCTUCrossVirtualBoundaries && isProcessDisabled(x, y + endY, 0, numHorVirBndry, verVirBndryPos, horVirBndryPos)) + { + continue; + } +#endif edgeType = sgn(srcLine[x] - srcLineBelow[x]) + sgn(srcLine[x] - srcLineAbove[x]); diff [edgeType] += (orgLine[x] - srcLine[x]); count[edgeType] ++; @@ -1307,6 +1358,12 @@ void EncSampleAdaptiveOffset::getBlkStats(const ComponentID compIdx, const int c firstLineEndX = (!isCalculatePreDeblockSamples) ? (isAboveAvail ? endX : 1) : endX; for(x=firstLineStartX; x<firstLineEndX; x++) { +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + if (isCTUCrossVirtualBoundaries && isProcessDisabled(x, 0, numVerVirBndry, numHorVirBndry, verVirBndryPos, horVirBndryPos)) + { + continue; + } +#endif edgeType = sgn(srcLine[x] - srcLineAbove[x-1]) - signUpLine[x+1]; diff [edgeType] += (orgLine[x] - srcLine[x]); count[edgeType] ++; @@ -1323,6 +1380,13 @@ void EncSampleAdaptiveOffset::getBlkStats(const ComponentID compIdx, const int c for (x=startX; x<endX; x++) { signDown = (int8_t)sgn(srcLine[x] - srcLineBelow[x+1]); +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + if (isCTUCrossVirtualBoundaries && isProcessDisabled(x, y, numVerVirBndry, numHorVirBndry, verVirBndryPos, horVirBndryPos)) + { + signDownLine[x + 1] = -signDown; + continue; + } +#endif edgeType = signDown + signUpLine[x]; diff [edgeType] += (orgLine[x] - srcLine[x]); count[edgeType] ++; @@ -1352,6 +1416,12 @@ void EncSampleAdaptiveOffset::getBlkStats(const ComponentID compIdx, const int c for (x=startX; x< endX; x++) { +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + if (isCTUCrossVirtualBoundaries && isProcessDisabled(x, y + endY, numVerVirBndry, numHorVirBndry, verVirBndryPos, horVirBndryPos)) + { + continue; + } +#endif edgeType = sgn(srcLine[x] - srcLineBelow[x+1]) + sgn(srcLine[x] - srcLineAbove[x-1]); diff [edgeType] += (orgLine[x] - srcLine[x]); count[edgeType] ++; @@ -1395,6 +1465,12 @@ void EncSampleAdaptiveOffset::getBlkStats(const ComponentID compIdx, const int c ; for(x=firstLineStartX; x<firstLineEndX; x++) { +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + if (isCTUCrossVirtualBoundaries && isProcessDisabled(x, 0, numVerVirBndry, numHorVirBndry, verVirBndryPos, horVirBndryPos)) + { + continue; + } +#endif edgeType = sgn(srcLine[x] - srcLineAbove[x+1]) - signUpLine[x-1]; diff [edgeType] += (orgLine[x] - srcLine[x]); count[edgeType] ++; @@ -1411,6 +1487,13 @@ void EncSampleAdaptiveOffset::getBlkStats(const ComponentID compIdx, const int c for(x=startX; x<endX; x++) { signDown = (int8_t)sgn(srcLine[x] - srcLineBelow[x-1]); +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + if (isCTUCrossVirtualBoundaries && isProcessDisabled(x, y, numVerVirBndry, numHorVirBndry, verVirBndryPos, horVirBndryPos)) + { + signUpLine[x - 1] = -signDown; + continue; + } +#endif edgeType = signDown + signUpLine[x]; diff [edgeType] += (orgLine[x] - srcLine[x]); @@ -1436,6 +1519,12 @@ void EncSampleAdaptiveOffset::getBlkStats(const ComponentID compIdx, const int c for (x=startX; x<endX; x++) { +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + if (isCTUCrossVirtualBoundaries && isProcessDisabled(x, y + endY, numVerVirBndry, numHorVirBndry, verVirBndryPos, horVirBndryPos)) + { + continue; + } +#endif edgeType = sgn(srcLine[x] - srcLineBelow[x-1]) + sgn(srcLine[x] - srcLineAbove[x+1]); diff [edgeType] += (orgLine[x] - srcLine[x]); count[edgeType] ++; diff --git a/source/Lib/EncoderLib/EncSampleAdaptiveOffset.h b/source/Lib/EncoderLib/EncSampleAdaptiveOffset.h index 048f63db9e304a53d339d06a12201a94b219bd4f..58f1ca036f26e06e46362cd1bc0dbe5b79df252a 100644 --- a/source/Lib/EncoderLib/EncSampleAdaptiveOffset.h +++ b/source/Lib/EncoderLib/EncSampleAdaptiveOffset.h @@ -115,7 +115,11 @@ private: //methods #else const double saoEncodingRate, const double saoEncodingRateChroma ); #endif - void getBlkStats(const ComponentID compIdx, const int channelBitDepth, SAOStatData* statsDataTypes, Pel* srcBlk, Pel* orgBlk, int srcStride, int orgStride, int width, int height, bool isLeftAvail, bool isRightAvail, bool isAboveAvail, bool isBelowAvail, bool isAboveLeftAvail, bool isAboveRightAvail, bool isCalculatePreDeblockSamples); + void getBlkStats(const ComponentID compIdx, const int channelBitDepth, SAOStatData* statsDataTypes, Pel* srcBlk, Pel* orgBlk, int srcStride, int orgStride, int width, int height, bool isLeftAvail, bool isRightAvail, bool isAboveAvail, bool isBelowAvail, bool isAboveLeftAvail, bool isAboveRightAvail, bool isCalculatePreDeblockSamples +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + , bool isCTUCrossVirtualBoundaries, int horVirBndryPos[], int verVirBndryPos[], int numHorVirBndry, int numVerVirBndry +#endif + ); void deriveModeNewRDO(const BitDepths &bitDepths, int ctuRsAddr, SAOBlkParam* mergeList[NUM_SAO_MERGE_TYPES], bool* sliceEnabled, std::vector<SAOStatData**>& blkStats, SAOBlkParam& modeParam, double& modeNormCost ); void deriveModeMergeRDO(const BitDepths &bitDepths, int ctuRsAddr, SAOBlkParam* mergeList[NUM_SAO_MERGE_TYPES], bool* sliceEnabled, std::vector<SAOStatData**>& blkStats, SAOBlkParam& modeParam, double& modeNormCost ); int64_t getDistortion(const int channelBitDepth, int typeIdc, int typeAuxInfo, int* offsetVal, SAOStatData& statData); diff --git a/source/Lib/EncoderLib/VLCWriter.cpp b/source/Lib/EncoderLib/VLCWriter.cpp index 82dd1c93f5279894ebbca8832a11acc962bbf79a..d3f2b328b0a862cff0d0fa8f459276b4201010de 100644 --- a/source/Lib/EncoderLib/VLCWriter.cpp +++ b/source/Lib/EncoderLib/VLCWriter.cpp @@ -280,6 +280,36 @@ void HLSWriter::codePPS( const PPS* pcPPS ) WRITE_SVLC( pcPPS->getDeblockingFilterTcOffsetDiv2(), "pps_tc_offset_div2" ); } } + +#if JVET_N0438_LOOP_FILTER_DISABLED_ACROSS_VIR_BOUND + WRITE_FLAG( pcPPS->getLoopFilterAcrossVirtualBoundariesDisabledFlag() ? 1 : 0, "pps_loop_filter_across_virtual_boundaries_disabled_flag" ); + if( pcPPS->getLoopFilterAcrossVirtualBoundariesDisabledFlag() ) + { + WRITE_CODE( pcPPS->getNumVerVirtualBoundaries(), 2, "pps_num_ver_virtual_boundaries"); + int numBits = 1; + uint32_t picWidthDivBy8 = pcPPS->pcv->lumaWidth >> 3; + while( picWidthDivBy8 >>= 1 ) + { + numBits++; + } + for( unsigned i = 0; i < pcPPS->getNumVerVirtualBoundaries(); i++ ) + { + WRITE_CODE( pcPPS->getVirtualBoundariesPosX( i ) >> 3, numBits, "pps_virtual_boundaries_pos_x" ); + } + WRITE_CODE( pcPPS->getNumHorVirtualBoundaries(), 2, "pps_num_hor_virtual_boundaries"); + numBits = 1; + uint32_t picHeightDivBy8 = pcPPS->pcv->lumaHeight >> 3; + while( picHeightDivBy8 >>= 1 ) + { + numBits++; + } + for( unsigned i = 0; i < pcPPS->getNumHorVirtualBoundaries(); i++ ) + { + WRITE_CODE( pcPPS->getVirtualBoundariesPosY( i ) >> 3, numBits, "pps_virtual_boundaries_pos_y" ); + } + } +#endif + #if HEVC_USE_SCALING_LISTS WRITE_FLAG( pcPPS->getScalingListPresentFlag() ? 1 : 0, "pps_scaling_list_data_present_flag" ); if( pcPPS->getScalingListPresentFlag() )