diff --git a/source/App/EncoderApp/EncApp.cpp b/source/App/EncoderApp/EncApp.cpp index e7e6ee4e5e1296a6f7cbd9081f3033fda2d3864d..473ce233287a05c2f96ba93bbf0aba3568fc1493 100644 --- a/source/App/EncoderApp/EncApp.cpp +++ b/source/App/EncoderApp/EncApp.cpp @@ -273,7 +273,12 @@ void EncApp::xInitLibCfg() m_cEncLib.setPROF ( m_PROF ); m_cEncLib.setBIO (m_BIO); m_cEncLib.setUseLMChroma ( m_LMChroma ); +#if JVET_P0592_CHROMA_PHASE + m_cEncLib.setHorCollocatedChromaFlag ( m_horCollocatedChromaFlag ); + m_cEncLib.setVerCollocatedChromaFlag ( m_verCollocatedChromaFlag ); +#else m_cEncLib.setCclmCollocatedChromaFlag ( m_cclmCollocatedChromaFlag ); +#endif m_cEncLib.setIntraMTS ( m_MTS & 1 ); m_cEncLib.setInterMTS ( ( m_MTS >> 1 ) & 1 ); #if JVET_P0273_MTSIntraMaxCand diff --git a/source/App/EncoderApp/EncAppCfg.cpp b/source/App/EncoderApp/EncAppCfg.cpp index 635e0046c1945927ce77199380b433d2f07f2246..9852c85507fc3381b91cf4f3782faa648eabf45c 100644 --- a/source/App/EncoderApp/EncAppCfg.cpp +++ b/source/App/EncoderApp/EncAppCfg.cpp @@ -918,12 +918,12 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] ) ("DualITree", m_dualTree, false, "Use separate QTBT trees for intra slice luma and chroma channel types") ( "LFNST", m_LFNST, false, "Enable LFNST (0:off, 1:on) [default: off]" ) ( "FastLFNST", m_useFastLFNST, false, "Fast methods for LFNST" ) - ("SubPuMvp", m_SubPuMvpMode, 0, "Enable Sub-PU temporal motion vector prediction (0:off, 1:ATMVP, 2:STMVP, 3:ATMVP+STMVP) [default: off]") - ("MMVD", m_MMVD, true, "Enable Merge mode with Motion Vector Difference (0:off, 1:on) [default: 1]") - ("Affine", m_Affine, false, "Enable affine prediction (0:off, 1:on) [default: off]") - ("AffineType", m_AffineType, true, "Enable affine type prediction (0:off, 1:on) [default: on]" ) - ("PROF", m_PROF, false, "Enable Prediction refinement with optical flow for affine mode (0:off, 1:on) [default: off]") - ("BIO", m_BIO, false, "Enable bi-directional optical flow") + ("SubPuMvp", m_SubPuMvpMode, 0, "Enable Sub-PU temporal motion vector prediction (0:off, 1:ATMVP, 2:STMVP, 3:ATMVP+STMVP) [default: off]") + ("MMVD", m_MMVD, true, "Enable Merge mode with Motion Vector Difference (0:off, 1:on) [default: 1]") + ("Affine", m_Affine, false, "Enable affine prediction (0:off, 1:on) [default: off]") + ("AffineType", m_AffineType, true, "Enable affine type prediction (0:off, 1:on) [default: on]" ) + ("PROF", m_PROF, false, "Enable Prediction refinement with optical flow for affine mode (0:off, 1:on) [default: off]") + ("BIO", m_BIO, false, "Enable bi-directional optical flow") ("IMV", m_ImvMode, 1, "Adaptive MV precision Mode (IMV)\n" "\t0: disabled\n" "\t1: enabled (1/2-Pel, Full-Pel and 4-PEL)\n") @@ -931,9 +931,18 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] ) ("LMChroma", m_LMChroma, 1, " LMChroma prediction " "\t0: Disable LMChroma\n" "\t1: Enable LMChroma\n") +#if JVET_P0592_CHROMA_PHASE + ("HorCollocatedChroma", m_horCollocatedChromaFlag, true, "Specifies the location of the top-left downsampled luma sample in cross-component linear model intra prediction relative to the top-left luma sample\n" + "\t0: horizontally co-sited, vertically shifted by 0.5 units of luma samples\n" + "\t1: collocated\n") + ("VerCollocatedChroma", m_verCollocatedChromaFlag, false, "Specifies the location of the top-left downsampled luma sample in cross-component linear model intra prediction relative to the top-left luma sample\n" + "\t0: horizontally co-sited, vertically shifted by 0.5 units of luma samples\n" + "\t1: collocated\n") +#else ("CclmCollocatedChroma", m_cclmCollocatedChromaFlag, false, "Specifies the location of the top-left downsampled luma sample in cross-component linear model intra prediction relative to the top-left luma sample\n" "\t0: horizontally co-sited, vertically shifted by 0.5 units of luma samples\n" "\t1: collocated\n") +#endif ("MTS", m_MTS, 0, "Multiple Transform Set (MTS)\n" "\t0: Disable MTS\n" "\t1: Enable only Intra MTS\n" @@ -3648,10 +3657,15 @@ void EncAppCfg::xPrintParameter() msg( VERBOSE, "IMV:%d ", m_ImvMode ); msg( VERBOSE, "BIO:%d ", m_BIO ); msg( VERBOSE, "LMChroma:%d ", m_LMChroma ); +#if JVET_P0592_CHROMA_PHASE + msg( VERBOSE, "HorCollocatedChroma:%d ", m_horCollocatedChromaFlag ); + msg( VERBOSE, "VerCollocatedChroma:%d ", m_verCollocatedChromaFlag ); +#else if( m_LMChroma && m_chromaFormatIDC == CHROMA_420 ) { msg( VERBOSE, "CclmCollocatedChroma:%d ", m_cclmCollocatedChromaFlag ); } +#endif msg( VERBOSE, "MTS: %1d(intra) %1d(inter) ", m_MTS & 1, ( m_MTS >> 1 ) & 1 ); msg( VERBOSE, "SBT:%d ", m_SBT ); msg( VERBOSE, "ISP:%d ", m_ISP ); @@ -3736,11 +3750,11 @@ void EncAppCfg::xPrintParameter() if( m_rprEnabled ) { - msg( VERBOSE, "RPR:(%1.2lfx, %1.2lfx)|%d", m_scalingRatioHor, m_scalingRatioVer, m_switchPocPeriod ); + msg( VERBOSE, "RPR:(%1.2lfx, %1.2lfx)|%d ", m_scalingRatioHor, m_scalingRatioVer, m_switchPocPeriod ); } else { - msg( VERBOSE, "RPR:%d", 0 ); + msg( VERBOSE, "RPR:%d ", 0 ); } #if JVET_O0549_ENCODER_ONLY_FILTER msg(VERBOSE, "TemporalFilter:%d ", m_gopBasedTemporalFilterEnabled); diff --git a/source/App/EncoderApp/EncAppCfg.h b/source/App/EncoderApp/EncAppCfg.h index a59199b4876e32bfc509a3c2c64f1e157e702017..b56ddcbf42ec7f801c952682ad3c588208ac5ed7 100644 --- a/source/App/EncoderApp/EncAppCfg.h +++ b/source/App/EncoderApp/EncAppCfg.h @@ -274,7 +274,12 @@ protected: bool m_PROF; bool m_BIO; int m_LMChroma; +#if JVET_P0592_CHROMA_PHASE + bool m_horCollocatedChromaFlag; + bool m_verCollocatedChromaFlag; +#else bool m_cclmCollocatedChromaFlag; +#endif int m_MTS; ///< XZ: Multiple Transform Set int m_MTSIntraMaxCand; ///< XZ: Number of additional candidates to test int m_MTSInterMaxCand; ///< XZ: Number of additional candidates to test diff --git a/source/Lib/CommonLib/CommonDef.h b/source/Lib/CommonLib/CommonDef.h index b3894ed01e7ced2bcda3a0fef84685463d411724..76e6e5733ebfe37095577de1a9edb793b47b343a 100644 --- a/source/Lib/CommonLib/CommonDef.h +++ b/source/Lib/CommonLib/CommonDef.h @@ -475,7 +475,7 @@ static const int EPBIN_WEIGHT_FACTOR = 4; #endif static const int ENC_PPS_ID_RPR = 3; static const int SCALE_RATIO_BITS = 14; -static const int MAX_SCALING_RATIO = 8; // max scaling ratio allowed in the software, it is used to allocated an internla buffer in the rescaling +static const int MAX_SCALING_RATIO = 8; // max scaling ratio allowed in the software, it is used to allocate an internal buffer in the rescaling static const std::pair<int, int> SCALE_1X = std::pair<int, int>( 1 << SCALE_RATIO_BITS, 1 << SCALE_RATIO_BITS ); // scale ratio 1x // ==================================================================================================================== diff --git a/source/Lib/CommonLib/InterPrediction.cpp b/source/Lib/CommonLib/InterPrediction.cpp index eeb93d83eab0d294384adc98b971ef731d46e2fc..db8168f546cf4f3a79617aa09302cb965d4ed787 100644 --- a/source/Lib/CommonLib/InterPrediction.cpp +++ b/source/Lib/CommonLib/InterPrediction.cpp @@ -298,7 +298,11 @@ void InterPrediction::xSubPuMC( PredictionUnit& pu, PelUnitBuf& predBuf, const R int secStep = (!verMC ? puWidth : puHeight); pu.refIdx[0] = 0; pu.refIdx[1] = pu.cs->slice->getSliceType() == B_SLICE ? 0 : -1; +#if JVET_P0590_SCALING_WINDOW + bool scaled = pu.cu->slice->getScalingRatio( REF_PIC_LIST_0, pu.refIdx[0] ) != SCALE_1X || pu.cu->slice->getScalingRatio( REF_PIC_LIST_1, pu.refIdx[1] ) != SCALE_1X; +#else bool scaled = !PU::isRefPicSameSize( pu ); +#endif m_subPuMC = true; @@ -516,7 +520,11 @@ void InterPrediction::xPredInterBi(PredictionUnit& pu, PelUnitBuf &pcYuvPred, Pe bool dmvrApplied = false; dmvrApplied = (pu.mvRefine) && PU::checkDMVRCondition(pu); +#if JVET_P0590_SCALING_WINDOW + bool samePicSize = pu.cu->slice->getScalingRatio( REF_PIC_LIST_0, refIdx0 ) == SCALE_1X && pu.cu->slice->getScalingRatio( REF_PIC_LIST_1, refIdx1 ) == SCALE_1X; +#else bool samePicSize = PU::isRefPicSameSize( pu ); +#endif dmvrApplied = dmvrApplied && samePicSize; bioApplied = bioApplied && samePicSize; @@ -1669,7 +1677,12 @@ void InterPrediction::motionCompensation( PredictionUnit &pu, PelUnitBuf &predBu bioApplied = false; } } + +#if JVET_P0590_SCALING_WINDOW + bioApplied = ( pu.cu->slice->getScalingRatio( REF_PIC_LIST_0, refIdx0 ) == SCALE_1X && pu.cu->slice->getScalingRatio( REF_PIC_LIST_1, refIdx1 ) == SCALE_1X ) ? bioApplied : false; +#else bioApplied = PU::isRefPicSameSize( pu ) ? bioApplied : false; +#endif bool dmvrApplied = false; dmvrApplied = (pu.mvRefine) && PU::checkDMVRCondition(pu); if ((pu.lumaSize().width > MAX_BDOF_APPLICATION_REGION || pu.lumaSize().height > MAX_BDOF_APPLICATION_REGION) && pu.mergeType != MRG_TYPE_SUBPU_ATMVP && (bioApplied && !dmvrApplied)) @@ -2426,14 +2439,41 @@ bool InterPrediction::xPredInterBlkRPR( const std::pair<int, int>& scalingRatio, int offX = 1 << ( posShift - shiftHor - 1 ); int offY = 1 << ( posShift - shiftVer - 1 ); +#if JVET_P0590_SCALING_WINDOW +#if JVET_P0592_CHROMA_PHASE + int addX = isLuma( compID ) ? 0 : int( 1 - refPic->cs->sps->getHorCollocatedChromaFlag() ) * 8 * ( scalingRatio.first - SCALE_1X.first ); + int addY = isLuma( compID ) ? 0 : int( 1 - refPic->cs->sps->getVerCollocatedChromaFlag() ) * 8 * ( scalingRatio.second - SCALE_1X.second ); + + x0Int = ( ( ( blk.pos().x - pps.getScalingWindow().getWindowLeftOffset() ) << ( 4 + ::getComponentScaleX( compID, chFmt ) ) ) + mv.getHor() ) * (int64_t)scalingRatio.first + addX; + x0Int = SIGN( x0Int ) * ( ( llabs( x0Int ) + ( (long long)1 << ( 7 + ::getComponentScaleX( compID, chFmt ) ) ) ) >> ( 8 + ::getComponentScaleX( compID, chFmt ) ) ) + ( refPic->cs->pps->getScalingWindow().getWindowLeftOffset() << ( ( posShift - ::getComponentScaleX( compID, chFmt ) ) ) ); + + y0Int = ( ( ( blk.pos().y - pps.getScalingWindow().getWindowTopOffset() ) << ( 4 + ::getComponentScaleY( compID, chFmt ) ) ) + mv.getVer() ) * (int64_t)scalingRatio.second + addY; + y0Int = SIGN( y0Int ) * ( ( llabs( y0Int ) + ( (long long)1 << ( 7 + ::getComponentScaleY( compID, chFmt ) ) ) ) >> ( 8 + ::getComponentScaleY( compID, chFmt ) ) ) + ( refPic->cs->pps->getScalingWindow().getWindowTopOffset() << ( ( posShift - ::getComponentScaleY( compID, chFmt ) ) ) ); +#else + x0Int = ( ( ( blk.pos().x - pps.getScalingWindow().getWindowLeftOffset() ) << ( 4 + ::getComponentScaleX( compID, chFmt ) ) ) + mv.getHor() ) * (int64_t)scalingRatio.first; + x0Int = SIGN( x0Int ) * ( ( llabs( x0Int ) + ( (long long)1 << ( 7 + ::getComponentScaleX( compID, chFmt ) ) ) ) >> ( 8 + ::getComponentScaleX( compID, chFmt ) ) ) + ( refPic->cs->pps->getScalingWindow().getWindowLeftOffset() << ( ( posShift - ::getComponentScaleX( compID, chFmt ) ) ) ); + + y0Int = ( ( ( blk.pos().y - pps.getScalingWindow().getWindowTopOffset() ) << ( 4 + ::getComponentScaleY( compID, chFmt ) ) ) + mv.getVer() ) * (int64_t)scalingRatio.second; + y0Int = SIGN( y0Int ) * ( ( llabs( y0Int ) + ( (long long)1 << ( 7 + ::getComponentScaleY( compID, chFmt ) ) ) ) >> ( 8 + ::getComponentScaleY( compID, chFmt ) ) ) + ( refPic->cs->pps->getScalingWindow().getWindowTopOffset() << ( ( posShift - ::getComponentScaleY( compID, chFmt ) ) ) ); +#endif +#elif JVET_P0592_CHROMA_PHASE + int addX = isLuma( compID ) ? 0 : int( 1 - refPic->cs->sps->getHorCollocatedChromaFlag() ) * 8 * ( scalingRatio.first - SCALE_1X.first ); + int addY = isLuma( compID ) ? 0 : int( 1 - refPic->cs->sps->getVerCollocatedChromaFlag() ) * 8 * ( scalingRatio.second - SCALE_1X.second ); + + x0Int = ( ( blk.pos().x << ( 4 + ::getComponentScaleX( compID, chFmt ) ) ) + mv.getHor() )* (int64_t)scalingRatio.first + addX; + x0Int = SIGN( x0Int ) * ( ( llabs( x0Int ) + ( (long long)1 << ( 7 + ::getComponentScaleX( compID, chFmt ) ) ) ) >> ( 8 + ::getComponentScaleX( compID, chFmt ) ) ); + + y0Int = ( ( blk.pos().y << ( 4 + ::getComponentScaleY( compID, chFmt ) ) ) + mv.getVer() )* (int64_t)scalingRatio.second + addY; + y0Int = SIGN( y0Int ) * ( ( llabs( y0Int ) + ( (long long)1 << ( 7 + ::getComponentScaleY( compID, chFmt ) ) ) ) >> ( 8 + ::getComponentScaleY( compID, chFmt ) ) ); +#else x0Int = ( ( blk.pos().x << ( 4 + ::getComponentScaleX( compID, chFmt ) ) ) + mv.getHor() )* (int64_t)scalingRatio.first; x0Int = SIGN( x0Int ) * ( ( llabs( x0Int ) + ( (long long)1 << ( 7 + ::getComponentScaleX( compID, chFmt ) ) ) ) >> ( 8 + ::getComponentScaleX( compID, chFmt ) ) ); y0Int = ( ( blk.pos().y << ( 4 + ::getComponentScaleY( compID, chFmt ) ) ) + mv.getVer() )* (int64_t)scalingRatio.second; y0Int = SIGN( y0Int ) * ( ( llabs( y0Int ) + ( (long long)1 << ( 7 + ::getComponentScaleY( compID, chFmt ) ) ) ) >> ( 8 + ::getComponentScaleY( compID, chFmt ) ) ); +#endif const int extSize = isLuma( compID ) ? 1 : 2; - int vFilterSize = isLuma( compID ) ? NTAPS_LUMA : NTAPS_CHROMA; int yInt0 = ( (int32_t)y0Int + offY ) >> posShift; @@ -2443,15 +2483,12 @@ bool InterPrediction::xPredInterBlkRPR( const std::pair<int, int>& scalingRatio, xInt0 = std::min( std::max( -(NTAPS_LUMA / 2), xInt0 ), ( refPicWidth >> ::getComponentScaleX( compID, chFmt ) ) + (NTAPS_LUMA / 2) ); int refHeight = ((((int32_t)y0Int + (height-1) * stepY) + offY ) >> posShift) - ((((int32_t)y0Int + 0 * stepY) + offY ) >> posShift) + 1; - refHeight = std::max<int>( 1, refHeight ); CHECK( MAX_CU_SIZE * MAX_SCALING_RATIO < refHeight + vFilterSize - 1 + extSize, "Buffer size is not enough, increase MAX_SCALING_RATIO" ); Pel buffer[( MAX_CU_SIZE + 16 ) * ( MAX_CU_SIZE * MAX_SCALING_RATIO + 16 )]; - int tmpStride = width; - int xInt = 0, yInt = 0; for( col = 0; col < width; col++ ) @@ -2493,9 +2530,6 @@ bool InterPrediction::xPredInterBlkRPR( const std::pair<int, int>& scalingRatio, #endif JVET_J0090_SET_CACHE_ENABLE( true ); } - - Position offset = Position( xInt, yInt ); - refBuf = refPic->getRecoBuf( CompArea( compID, chFmt, offset, Size( 1, 1 ) ), wrapRef ); } return scaled; diff --git a/source/Lib/CommonLib/Picture.cpp b/source/Lib/CommonLib/Picture.cpp index 27145ddb20210bcbe7870daa269c076747b8b365..a4d71971e41ba3f0c3687c9c0f49bafcb8e92bbc 100644 --- a/source/Lib/CommonLib/Picture.cpp +++ b/source/Lib/CommonLib/Picture.cpp @@ -1228,7 +1228,151 @@ const TFilterCoeff DownsamplingFilterSRC[8][16][12] = } }; +#if JVET_P0590_SCALING_WINDOW +#if JVET_P0592_CHROMA_PHASE +void Picture::sampleRateConv( const std::pair<int, int> scalingRatio, const std::pair<int, int> compScale, + const CPelBuf& beforeScale, const int beforeScaleLeftOffset, const int beforeScaleTopOffset, + const PelBuf& afterScale, const int afterScaleLeftOffset, const int afterScaleTopOffset, + const int bitDepth, const bool useLumaFilter, const bool downsampling, + const bool horCollocatedPositionFlag, const bool verCollocatedPositionFlag ) +#else +void Picture::sampleRateConv( const std::pair<int, int> scalingRatio, + const CPelBuf& beforeScale, const int beforeScaleLeftOffset, const int beforeScaleTopOffset, + const PelBuf& afterScale, const int afterScaleLeftOffset, const int afterScaleTopOffset, + const int bitDepth, const bool useLumaFilter, const bool downsampling ) +#endif +{ + const Pel* orgSrc = beforeScale.buf; + const int orgWidth = beforeScale.width; + const int orgHeight = beforeScale.height; + const int orgStride = beforeScale.stride; + + Pel* scaledSrc = afterScale.buf; + const int scaledWidth = afterScale.width; + const int scaledHeight = afterScale.height; + const int scaledStride = afterScale.stride; + + if( orgWidth == scaledWidth && orgHeight == scaledHeight && scalingRatio == SCALE_1X && !beforeScaleLeftOffset && !beforeScaleTopOffset && !afterScaleLeftOffset && !afterScaleTopOffset ) + { + for( int j = 0; j < orgHeight; j++ ) + { + memcpy( scaledSrc + j * scaledStride, orgSrc + j * orgStride, sizeof( Pel ) * orgWidth ); + } + + return; + } + + const TFilterCoeff* filterHor = useLumaFilter ? &InterpolationFilter::m_lumaFilter[0][0] : &InterpolationFilter::m_chromaFilter[0][0]; + const TFilterCoeff* filterVer = useLumaFilter ? &InterpolationFilter::m_lumaFilter[0][0] : &InterpolationFilter::m_chromaFilter[0][0]; + const int numFracPositions = useLumaFilter ? 15 : 31; + const int numFracShift = useLumaFilter ? 4 : 5; + const int posShift = SCALE_RATIO_BITS - numFracShift; +#if JVET_P0592_CHROMA_PHASE + int addX = ( 1 << ( posShift - 1 ) ) + ( beforeScaleLeftOffset << posShift ) + ( ( int( 1 - horCollocatedPositionFlag ) * 8 * ( scalingRatio.first - SCALE_1X.first ) + ( 1 << ( 3 + compScale.first ) ) ) >> ( 4 + compScale.first ) ); + int addY = ( 1 << ( posShift - 1 ) ) + ( beforeScaleTopOffset << posShift ) + ( ( int( 1 - verCollocatedPositionFlag ) * 8 * ( scalingRatio.second - SCALE_1X.second ) + ( 1 << ( 3 + compScale.second ) ) ) >> ( 4 + compScale.second ) ); +#else + int addX = ( 1 << ( posShift - 1 ) ) + ( beforeScaleLeftOffset << posShift ); + int addY = ( 1 << ( posShift - 1 ) ) + ( beforeScaleTopOffset << posShift ); +#endif + + if( downsampling ) + { + int verFilter = 0; + int horFilter = 0; + + if( scalingRatio.first > ( 15 << SCALE_RATIO_BITS ) / 4 ) horFilter = 7; + else if( scalingRatio.first > ( 20 << SCALE_RATIO_BITS ) / 7 ) horFilter = 6; + else if( scalingRatio.first > ( 5 << SCALE_RATIO_BITS ) / 2 ) horFilter = 5; + else if( scalingRatio.first > ( 2 << SCALE_RATIO_BITS ) ) horFilter = 4; + else if( scalingRatio.first > ( 5 << SCALE_RATIO_BITS ) / 3 ) horFilter = 3; + else if( scalingRatio.first > ( 5 << SCALE_RATIO_BITS ) / 4 ) horFilter = 2; + else if( scalingRatio.first > ( 20 << SCALE_RATIO_BITS ) / 19 ) horFilter = 1; + + if( scalingRatio.second > ( 15 << SCALE_RATIO_BITS ) / 4 ) verFilter = 7; + else if( scalingRatio.second > ( 20 << SCALE_RATIO_BITS ) / 7 ) verFilter = 6; + else if( scalingRatio.second > ( 5 << SCALE_RATIO_BITS ) / 2 ) verFilter = 5; + else if( scalingRatio.second > ( 2 << SCALE_RATIO_BITS ) ) verFilter = 4; + else if( scalingRatio.second > ( 5 << SCALE_RATIO_BITS ) / 3 ) verFilter = 3; + else if( scalingRatio.second > ( 5 << SCALE_RATIO_BITS ) / 4 ) verFilter = 2; + else if( scalingRatio.second > ( 20 << SCALE_RATIO_BITS ) / 19 ) verFilter = 1; + + filterHor = &DownsamplingFilterSRC[horFilter][0][0]; + filterVer = &DownsamplingFilterSRC[verFilter][0][0]; + } + + const int filterLength = downsampling ? 12 : ( useLumaFilter ? NTAPS_LUMA : NTAPS_CHROMA ); + const int log2Norm = downsampling ? 14 : 12; + + int *buf = new int[orgHeight * scaledWidth]; + int maxVal = ( 1 << bitDepth ) - 1; + + CHECK( bitDepth > 17, "Overflow may happen!" ); + + for( int i = 0; i < scaledWidth; i++ ) + { + const Pel* org = orgSrc; + int refPos = ( ( i - afterScaleLeftOffset ) * scalingRatio.first + addX ) >> posShift; + int integer = refPos >> numFracShift; + int frac = refPos & numFracPositions; + int* tmp = buf + i; + + for( int j = 0; j < orgHeight; j++ ) + { + int sum = 0; + const TFilterCoeff* f = filterHor + frac * filterLength; + + for( int k = 0; k < filterLength; k++ ) + { + int xInt = std::min<int>( std::max( 0, integer + k - filterLength / 2 + 1 ), orgWidth - 1 ); + sum += f[k] * org[xInt]; // postpone horizontal filtering gain removal after vertical filtering + } + + *tmp = sum; + + tmp += scaledWidth; + org += orgStride; + } + } + + Pel* dst = scaledSrc; + + for( int j = 0; j < scaledHeight; j++ ) + { + int refPos = ( ( j - afterScaleTopOffset ) * scalingRatio.second + addY ) >> posShift; + int integer = refPos >> numFracShift; + int frac = refPos & numFracPositions; + + for( int i = 0; i < scaledWidth; i++ ) + { + int sum = 0; + int* tmp = buf + i; + const TFilterCoeff* f = filterVer + frac * filterLength; + + for( int k = 0; k < filterLength; k++ ) + { + int yInt = std::min<int>( std::max( 0, integer + k - filterLength / 2 + 1 ), orgHeight - 1 ); + sum += f[k] * tmp[yInt*scaledWidth]; + } + + dst[i] = std::min<int>( std::max( 0, ( sum + ( 1 << ( log2Norm - 1 ) ) ) >> log2Norm ), maxVal ); + } + + dst += scaledStride; + } + + delete[] buf; +} +#else +#if JVET_P0592_CHROMA_PHASE +void Picture::sampleRateConv( const std::pair<int, int> scalingRatio, const std::pair<int, int> compScale, + const Pel* orgSrc, SizeType orgWidth, SizeType orgHeight, SizeType orgStride, + Pel* scaledSrc, SizeType scaledWidth, SizeType scaledHeight, + SizeType paddedWidth, SizeType paddedHeight, SizeType scaledStride, + const int bitDepth, const bool useLumaFilter, const bool downsampling, + const bool horCollocatedPositionFlag, const bool verCollocatedPositionFlag ) +#else void Picture::sampleRateConv( const Pel* orgSrc, SizeType orgWidth, SizeType orgHeight, SizeType orgStride, Pel* scaledSrc, SizeType scaledWidth, SizeType scaledHeight, SizeType paddedWidth, SizeType paddedHeight, SizeType scaledStride, const int bitDepth, const bool useLumaFilter, const bool downsampling ) +#endif { if( orgWidth == scaledWidth && orgHeight == scaledHeight ) { @@ -1245,10 +1389,17 @@ void Picture::sampleRateConv( const Pel* orgSrc, SizeType orgWidth, SizeType org const int numFracPositions = useLumaFilter ? 15 : 31; const int numFracShift = useLumaFilter ? 4 : 5; +#if JVET_P0592_CHROMA_PHASE + const int posShift = SCALE_RATIO_BITS - numFracShift; + int addX = ( 1 << ( posShift - 1 ) ) + ( ( int( 1 - horCollocatedPositionFlag ) * 8 * ( scalingRatio.first - SCALE_1X.first ) + ( 1 << ( 3 + compScale.first ) ) ) >> ( 4 + compScale.first ) ); + int addY = ( 1 << ( posShift - 1 ) ) + ( ( int( 1 - verCollocatedPositionFlag ) * 8 * ( scalingRatio.second - SCALE_1X.second ) + ( 1 << ( 3 + compScale.second ) ) ) >> ( 4 + compScale.second ) ); +#endif + if( downsampling ) { int verFilter = 0; int horFilter = 0; + if( 4 * orgHeight > 15 * scaledHeight ) verFilter = 7; else if( 7 * orgHeight > 20 * scaledHeight ) verFilter = 6; else if( 2 * orgHeight > 5 * scaledHeight ) verFilter = 5; @@ -1280,8 +1431,14 @@ void Picture::sampleRateConv( const Pel* orgSrc, SizeType orgWidth, SizeType org for( int i = 0; i < paddedWidth; i++ ) { const Pel* org = orgSrc; +#if JVET_P0592_CHROMA_PHASE + int refPos = ( i * scalingRatio.first + addX ) >> posShift; + int integer = refPos >> numFracShift; + int frac = refPos & numFracPositions; +#else int integer = ( i * orgWidth ) / scaledWidth; int frac = ( ( i * orgWidth << numFracShift ) / scaledWidth ) & numFracPositions; +#endif int* tmp = buf + i; @@ -1307,8 +1464,14 @@ void Picture::sampleRateConv( const Pel* orgSrc, SizeType orgWidth, SizeType org for( int j = 0; j < paddedHeight; j++ ) { +#if JVET_P0592_CHROMA_PHASE + int refPos = ( j * scalingRatio.second + addY ) >> posShift; + int integer = refPos >> numFracShift; + int frac = refPos & numFracPositions; +#else int integer = ( j * orgHeight ) / scaledHeight; int frac = ( ( j * orgHeight << numFracShift ) / scaledHeight ) & numFracPositions; +#endif for( int i = 0; i < paddedWidth; i++ ) { @@ -1330,7 +1493,64 @@ void Picture::sampleRateConv( const Pel* orgSrc, SizeType orgWidth, SizeType org delete[] buf; } +#endif + +#if JVET_P0590_SCALING_WINDOW +void Picture::rescalePicture( const std::pair<int, int> scalingRatio, + const CPelUnitBuf& beforeScaling, const Window& scalingWindowBefore, + const PelUnitBuf& afterScaling, const Window& scalingWindowAfter, +#if JVET_P0592_CHROMA_PHASE + const ChromaFormat chromaFormatIDC, const BitDepths& bitDepths, const bool useLumaFilter, const bool downsampling, + const bool horCollocatedChromaFlag, const bool verCollocatedChromaFlag ) +#else + const ChromaFormat chromaFormatIDC, const BitDepths& bitDepths, const bool useLumaFilter, const bool downsampling ) +#endif +{ + for( int comp = 0; comp < ::getNumberValidComponents( chromaFormatIDC ); comp++ ) + { + ComponentID compID = ComponentID( comp ); + const CPelBuf& beforeScale = beforeScaling.get( compID ); + const PelBuf& afterScale = afterScaling.get( compID ); +#if JVET_P0592_CHROMA_PHASE + sampleRateConv( scalingRatio, std::pair<int, int>( ::getComponentScaleX( compID, chromaFormatIDC ), ::getComponentScaleY( compID, chromaFormatIDC ) ), + beforeScale, scalingWindowBefore.getWindowLeftOffset(), scalingWindowBefore.getWindowTopOffset(), + afterScale, scalingWindowAfter.getWindowLeftOffset(), scalingWindowAfter.getWindowTopOffset(), + bitDepths.recon[comp], downsampling || useLumaFilter ? true : isLuma( compID ), downsampling, + isLuma( compID ) ? 1 : horCollocatedChromaFlag, isLuma( compID ) ? 1 : verCollocatedChromaFlag ); +#else + Picture::sampleRateConv( scalingRatio, + beforeScale, scalingWindowBefore.getWindowLeftOffset(), scalingWindowBefore.getWindowTopOffset(), + afterScale, scalingWindowAfter.getWindowLeftOffset(), scalingWindowAfter.getWindowTopOffset(), + bitDepths.recon[comp], downsampling || useLumaFilter ? true : isLuma( compID ), downsampling ); +#endif + } +} +#elif JVET_P0592_CHROMA_PHASE +void Picture::rescalePicture( const std::pair<int, int> scalingRatio, + const CPelUnitBuf& beforeScaling, const Window& confBefore, + const PelUnitBuf& afterScaling, const Window& confAfter, + const ChromaFormat chromaFormatIDC, const BitDepths& bitDepths, const bool useLumaFilter, const bool downsampling, + const bool horCollocatedChromaFlag, const bool verCollocatedChromaFlag ) +{ + for( int comp = 0; comp < ::getNumberValidComponents( chromaFormatIDC ); comp++ ) + { + ComponentID compID = ComponentID( comp ); + const CPelBuf& beforeScale = beforeScaling.get( compID ); + const PelBuf& afterScale = afterScaling.get( compID ); + int widthBefore = beforeScale.width - ( ( ( confBefore.getWindowLeftOffset() + confBefore.getWindowRightOffset() ) * SPS::getWinUnitX( chromaFormatIDC ) ) >> getChannelTypeScaleX( (ChannelType)( comp > 0 ), chromaFormatIDC ) ); + int heightBefore = beforeScale.height - ( ( ( confBefore.getWindowTopOffset() + confBefore.getWindowBottomOffset() ) * SPS::getWinUnitY( chromaFormatIDC ) ) >> getChannelTypeScaleY( (ChannelType)( comp > 0 ), chromaFormatIDC ) ); + int widthAfter = afterScale.width - ( ( ( confAfter.getWindowLeftOffset() + confAfter.getWindowRightOffset() ) * SPS::getWinUnitX( chromaFormatIDC ) ) >> getChannelTypeScaleX( (ChannelType)( comp > 0 ), chromaFormatIDC ) ); + int heightAfter = afterScale.height - ( ( ( confAfter.getWindowTopOffset() + confAfter.getWindowBottomOffset() ) * SPS::getWinUnitY( chromaFormatIDC ) ) >> getChannelTypeScaleY( (ChannelType)( comp > 0 ), chromaFormatIDC ) ); + + sampleRateConv( scalingRatio, std::pair<int, int>( ::getComponentScaleX( compID, chromaFormatIDC ), ::getComponentScaleY( compID, chromaFormatIDC ) ), + beforeScale.buf, widthBefore, heightBefore, beforeScale.stride, + afterScale.buf, widthAfter, heightAfter, afterScale.width, afterScale.height, afterScale.stride, + bitDepths.recon[comp], downsampling || useLumaFilter ? true : isLuma( compID ), downsampling, + isLuma( compID ) ? 1 : horCollocatedChromaFlag, isLuma( compID ) ? 1 : verCollocatedChromaFlag ); + } +} +#else void Picture::rescalePicture( const CPelUnitBuf& beforeScaling, const Window& confBefore, const PelUnitBuf& afterScaling, const Window& confAfter, const ChromaFormat chromaFormatIDC, const BitDepths& bitDepths, const bool useLumaFilter, const bool downsampling ) { for( int comp = 0; comp < ::getNumberValidComponents( chromaFormatIDC ); comp++ ) @@ -1346,6 +1566,7 @@ void Picture::rescalePicture( const CPelUnitBuf& beforeScaling, const Window& co Picture::sampleRateConv( beforeScale.buf, widthBefore, heightBefore, beforeScale.stride, afterScale.buf, widthAfter, heightAfter, afterScale.width, afterScale.height, afterScale.stride, bitDepths.recon[comp], downsampling || useLumaFilter ? true : isLuma(compID), downsampling ); } } +#endif void Picture::extendPicBorder() { diff --git a/source/Lib/CommonLib/Picture.h b/source/Lib/CommonLib/Picture.h index e352118b9c7860092a3234e37a47457840544ff5..bcb8016eedeffbe6b60a9d802f6048fa6b0f9e2a 100644 --- a/source/Lib/CommonLib/Picture.h +++ b/source/Lib/CommonLib/Picture.h @@ -253,9 +253,46 @@ struct Picture : public UnitArea void setSpliceIdx(uint32_t idx, int poc) { m_spliceIdx[idx] = poc; } void createSpliceIdx(int nums); bool getSpliceFull(); - static void sampleRateConv( const Pel* orgSrc, SizeType orgWidth, SizeType orgHeight, SizeType orgStride, Pel* scaledSrc, SizeType scaledWidth, SizeType scaledHeight, SizeType paddedWidth, SizeType paddedHeight, SizeType scaledStride, const int bitDepth, const bool useLumaFilter, const bool downsampling = false ); +#if JVET_P0590_SCALING_WINDOW +#if JVET_P0592_CHROMA_PHASE + static void sampleRateConv( const std::pair<int, int> scalingRatio, const std::pair<int, int> compScale, + const CPelBuf& beforeScale, const int beforeScaleLeftOffset, const int beforeScaleTopOffset, + const PelBuf& afterScale, const int afterScaleLeftOffset, const int afterScaleTopOffset, + const int bitDepth, const bool useLumaFilter, const bool downsampling, + const bool horCollocatedPositionFlag, const bool verCollocatedPositionFlag ); +#else + static void sampleRateConv( const std::pair<int, int> scalingRatio, + const CPelBuf& beforeScale, const int beforeScaleLeftOffset, const int beforeScaleTopOffset, + const PelBuf& afterScale, const int afterScaleLeftOffset, const int afterScaleTopOffset, + const int bitDepth, const bool useLumaFilter, const bool downsampling = false ); +#endif + static void rescalePicture( const std::pair<int, int> scalingRatio, + const CPelUnitBuf& beforeScaling, const Window& scalingWindowBefore, + const PelUnitBuf& afterScaling, const Window& scalingWindowAfter, +#if JVET_P0592_CHROMA_PHASE + const ChromaFormat chromaFormatIDC, const BitDepths& bitDepths, const bool useLumaFilter, const bool downsampling, + const bool horCollocatedChromaFlag, const bool verCollocatedChromaFlag ); +#else + const ChromaFormat chromaFormatIDC, const BitDepths& bitDepths, const bool useLumaFilter, const bool downsampling = false ); +#endif +#elif JVET_P0592_CHROMA_PHASE + static void sampleRateConv( const std::pair<int, int> scalingRatio, const std::pair<int, int> compScale, + const Pel* orgSrc, SizeType orgWidth, SizeType orgHeight, SizeType orgStride, + Pel* scaledSrc, SizeType scaledWidth, SizeType scaledHeight, + SizeType paddedWidth, SizeType paddedHeight, SizeType scaledStride, + const int bitDepth, const bool useLumaFilter, const bool downsampling, + const bool horCollocatedPositionFlag, const bool verCollocatedPositionFlag ); + + static void rescalePicture( const std::pair<int, int> scalingRatio, + const CPelUnitBuf& beforeScaling, const Window& confBefore, + const PelUnitBuf& afterScaling, const Window& confAfter, + const ChromaFormat chromaFormatIDC, const BitDepths& bitDepths, const bool useLumaFilter, const bool downsampling, + const bool horCollocatedChromaFlag, const bool verCollocatedChromaFlag ); +#else + static void sampleRateConv( const Pel* orgSrc, SizeType orgWidth, SizeType orgHeight, SizeType orgStride, Pel* scaledSrc, SizeType scaledWidth, SizeType scaledHeight, SizeType paddedWidth, SizeType paddedHeight, SizeType scaledStride, const int bitDepth, const bool useLumaFilter, const bool downsampling = false ); static void rescalePicture(const CPelUnitBuf& beforeScaling, const Window& confBefore, const PelUnitBuf& afterScaling, const Window& confAfter, const ChromaFormat chromaFormatIDC, const BitDepths& bitDepths, const bool useLumaFilter, const bool downsampling = false); +#endif public: bool m_bIsBorderExtended; @@ -299,6 +336,9 @@ public: uint32_t m_picWidthInLumaSamples; uint32_t m_picHeightInLumaSamples; Window m_conformanceWindow; +#if JVET_P0590_SCALING_WINDOW + Window m_scalingWindow; +#endif void setPicWidthInLumaSamples( uint32_t u ) { m_picWidthInLumaSamples = u; } uint32_t getPicWidthInLumaSamples() const { return m_picWidthInLumaSamples; } @@ -308,6 +348,11 @@ public: Window& getConformanceWindow() { return m_conformanceWindow; } const Window& getConformanceWindow() const { return m_conformanceWindow; } void setConformanceWindow( Window& conformanceWindow ) { m_conformanceWindow = conformanceWindow; } +#if JVET_P0590_SCALING_WINDOW + Window& getScalingWindow() { return m_scalingWindow; } + const Window& getScalingWindow() const { return m_scalingWindow; } + void setScalingWindow( Window& scalingWindow ) { m_scalingWindow = scalingWindow; } +#endif void allocateNewSlice(); Slice *swapSliceObject(Slice * p, uint32_t i); diff --git a/source/Lib/CommonLib/Slice.cpp b/source/Lib/CommonLib/Slice.cpp index 0b607527abf8862924a2b6eefb7dddbe8c5d2f8d..7e985732456780d4c4ebe7b803cba520c8038d4b 100644 --- a/source/Lib/CommonLib/Slice.cpp +++ b/source/Lib/CommonLib/Slice.cpp @@ -1653,7 +1653,12 @@ SPS::SPS() , m_lumaReshapeEnable (false) , m_AMVREnabledFlag ( false ) , m_LMChroma ( false ) +#if JVET_P0592_CHROMA_PHASE +, m_horCollocatedChromaFlag ( true ) +, m_verCollocatedChromaFlag ( false ) +#else , m_cclmCollocatedChromaFlag ( false ) +#endif , m_IntraMTS ( false ) , m_InterMTS ( false ) , m_LFNST ( false ) @@ -1669,8 +1674,11 @@ SPS::SPS() , m_LadfIntervalLowerBound { 0 } #endif , m_MIP ( false ) - ,m_GDREnabledFlag (1) -, m_SubLayerCbpParametersPresentFlag (1) +, m_GDREnabledFlag ( true ) +, m_SubLayerCbpParametersPresentFlag ( true ) +#if JVET_P0590_SCALING_WINDOW +, m_rprEnabledFlag ( false ) +#endif { for(int ch=0; ch<MAX_NUM_CHANNEL_TYPE; ch++) @@ -2539,7 +2547,11 @@ void Slice::scaleRefPicList( Picture *scaledRefPic[ ], APS** apss, APS* lmcsAps, m_scalingRatio[refList][rIdx] = std::pair<int, int>( xScale, yScale ); #if JVET_P0206_TMVP_flags +#if JVET_P0590_SCALING_WINDOW + if( m_scalingRatio[refList][rIdx] == SCALE_1X && pps->getPicWidthInLumaSamples() == m_apcRefPicList[refList][rIdx]->getPicWidthInLumaSamples() && pps->getPicHeightInLumaSamples() == m_apcRefPicList[refList][rIdx]->getPicHeightInLumaSamples() ) +#else if( m_scalingRatio[refList][rIdx] == SCALE_1X ) +#endif { refPicIsSameRes = true; } @@ -2600,7 +2612,25 @@ void Slice::scaleRefPicList( Picture *scaledRefPic[ ], APS** apss, APS* lmcsAps, // rescale the reference picture const bool downsampling = m_apcRefPicList[refList][rIdx]->getRecoBuf().Y().width >= scaledRefPic[j]->getRecoBuf().Y().width && m_apcRefPicList[refList][rIdx]->getRecoBuf().Y().height >= scaledRefPic[j]->getRecoBuf().Y().height; +#if JVET_P0590_SCALING_WINDOW +#if JVET_P0592_CHROMA_PHASE + Picture::rescalePicture( m_scalingRatio[refList][rIdx], + m_apcRefPicList[refList][rIdx]->getRecoBuf(), m_apcRefPicList[refList][rIdx]->slices[0]->getPPS()->getScalingWindow(), + scaledRefPic[j]->getRecoBuf(), pps->getScalingWindow(), + sps->getChromaFormatIdc(), sps->getBitDepths(), true, downsampling, + sps->getHorCollocatedChromaFlag(), sps->getVerCollocatedChromaFlag() ); +#else + Picture::rescalePicture( m_scalingRatio[refList][rIdx], m_apcRefPicList[refList][rIdx]->getRecoBuf(), m_apcRefPicList[refList][rIdx]->slices[0]->getPPS()->getScalingWindow(), scaledRefPic[j]->getRecoBuf(), pps->getScalingWindow(), sps->getChromaFormatIdc(), sps->getBitDepths(), true, downsampling ); +#endif +#elif JVET_P0592_CHROMA_PHASE + Picture::rescalePicture( m_scalingRatio[refList][rIdx], m_apcRefPicList[refList][rIdx]->getRecoBuf(), + m_apcRefPicList[refList][rIdx]->slices[0]->getPPS()->getConformanceWindow(), + scaledRefPic[j]->getRecoBuf(), pps->getConformanceWindow(), + sps->getChromaFormatIdc(), sps->getBitDepths(), true, downsampling, + sps->getHorCollocatedChromaFlag(), sps->getVerCollocatedChromaFlag() ); +#else Picture::rescalePicture( m_apcRefPicList[refList][rIdx]->getRecoBuf(), m_apcRefPicList[refList][rIdx]->slices[0]->getPPS()->getConformanceWindow(), scaledRefPic[j]->getRecoBuf(), pps->getConformanceWindow(), sps->getChromaFormatIdc(), sps->getBitDepths(), true, downsampling ); +#endif scaledRefPic[j]->extendPicBorder(); m_scaledRefPicList[refList][rIdx] = scaledRefPic[j]; diff --git a/source/Lib/CommonLib/Slice.h b/source/Lib/CommonLib/Slice.h index dc98597b86cd5268ee8e00872f37ebf0c746c6d8..8860d038547afdd4bbaba997a212a4ecc645ff29 100644 --- a/source/Lib/CommonLib/Slice.h +++ b/source/Lib/CommonLib/Slice.h @@ -867,7 +867,12 @@ private: bool m_lumaReshapeEnable; bool m_AMVREnabledFlag; bool m_LMChroma; +#if JVET_P0592_CHROMA_PHASE + bool m_horCollocatedChromaFlag; + bool m_verCollocatedChromaFlag; +#else bool m_cclmCollocatedChromaFlag; +#endif bool m_MTS; bool m_IntraMTS; // 18 bool m_InterMTS; // 19 @@ -890,6 +895,10 @@ private: bool m_GDREnabledFlag; bool m_SubLayerCbpParametersPresentFlag; +#if JVET_P0590_SCALING_WINDOW + bool m_rprEnabledFlag; +#endif + public: SPS(); @@ -1086,8 +1095,16 @@ public: bool getUsePROF () const { return m_PROF; } void setUseLMChroma ( bool b ) { m_LMChroma = b; } bool getUseLMChroma () const { return m_LMChroma; } +#if JVET_P0592_CHROMA_PHASE + void setHorCollocatedChromaFlag( bool b ) { m_horCollocatedChromaFlag = b; } + bool getHorCollocatedChromaFlag() const { return m_horCollocatedChromaFlag; } + void setVerCollocatedChromaFlag( bool b ) { m_verCollocatedChromaFlag = b; } + bool getVerCollocatedChromaFlag() const { return m_verCollocatedChromaFlag; } + bool getCclmCollocatedChromaFlag() const { return m_verCollocatedChromaFlag; } +#else void setCclmCollocatedChromaFlag( bool b ) { m_cclmCollocatedChromaFlag = b; } bool getCclmCollocatedChromaFlag() const { return m_cclmCollocatedChromaFlag; } +#endif void setUseMTS ( bool b ) { m_MTS = b; } bool getUseMTS () const { return m_MTS; } bool getUseImplicitMTS () const { return m_MTS && !m_IntraMTS; } @@ -1131,6 +1148,11 @@ public: bool getGDREnabledFlag() const { return m_GDREnabledFlag; } void setSubLayerParametersPresentFlag(bool flag) { m_SubLayerCbpParametersPresentFlag = flag; } bool getSubLayerParametersPresentFlag() const { return m_SubLayerCbpParametersPresentFlag; } + +#if JVET_P0590_SCALING_WINDOW + bool getRprEnabledFlag() const { return m_rprEnabledFlag; } + void setRprEnabledFlag( bool flag ) { m_rprEnabledFlag = flag; } +#endif }; @@ -1270,6 +1292,9 @@ private: uint32_t m_picWidthInLumaSamples; uint32_t m_picHeightInLumaSamples; Window m_conformanceWindow; +#if JVET_P0590_SCALING_WINDOW + Window m_scalingWindow; +#endif PPSRExt m_ppsRangeExtension; @@ -1501,6 +1526,12 @@ public: Window& getConformanceWindow() { return m_conformanceWindow; } const Window& getConformanceWindow() const { return m_conformanceWindow; } void setConformanceWindow( Window& conformanceWindow ) { m_conformanceWindow = conformanceWindow; } + +#if JVET_P0590_SCALING_WINDOW + Window& getScalingWindow() { return m_scalingWindow; } + const Window& getScalingWindow() const { return m_scalingWindow; } + void setScalingWindow( Window& scalingWindow ) { m_scalingWindow = scalingWindow; } +#endif }; class APS diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h index 579b04df078b99fd9214e84a2ae3e8c90e2b9e85..958db053495e4af69b67217136697e132a5720f2 100644 --- a/source/Lib/CommonLib/TypeDef.h +++ b/source/Lib/CommonLib/TypeDef.h @@ -50,6 +50,9 @@ #include <assert.h> #include <cassert> +#define JVET_P0590_SCALING_WINDOW 1 // JVET-P0590: scaling window for RPR +#define JVET_P0592_CHROMA_PHASE 1 // JVET-P0592: chroma phase for RPR + #define JVET_P0641_REMOVE_2xN_CHROMA_INTRA 1 // JVET-P0641: removing 2xN chroma intra blocks #define JVET_P0206_TMVP_flags 1 // JVET-P0206: Signalling TMVP usage (remove pps TMVP idc and constraint when RPR is used) diff --git a/source/Lib/CommonLib/UnitTools.cpp b/source/Lib/CommonLib/UnitTools.cpp index 95141fe5bfba2f4255b414d800c0391218af6fe4..42b205bf59c3c03676a25a9b4304cdbdee3e8703 100644 --- a/source/Lib/CommonLib/UnitTools.cpp +++ b/source/Lib/CommonLib/UnitTools.cpp @@ -102,12 +102,22 @@ void CS::setRefinedMotionField(CodingStructure &cs) bool CU::getRprScaling( const SPS* sps, const PPS* curPPS, Picture* refPic, int& xScale, int& yScale ) { +#if JVET_P0590_SCALING_WINDOW + const Window& curScalingWindow = curPPS->getScalingWindow(); + int curPicWidth = curPPS->getPicWidthInLumaSamples() - curScalingWindow.getWindowLeftOffset() - curScalingWindow.getWindowRightOffset(); + int curPicHeight = curPPS->getPicHeightInLumaSamples() - curScalingWindow.getWindowTopOffset() - curScalingWindow.getWindowBottomOffset(); + + const Window& refScalingWindow = refPic->getScalingWindow(); + int refPicWidth = refPic->getPicWidthInLumaSamples() - refScalingWindow.getWindowLeftOffset() - refScalingWindow.getWindowRightOffset(); + int refPicHeight = refPic->getPicHeightInLumaSamples() - refScalingWindow.getWindowTopOffset() - refScalingWindow.getWindowBottomOffset(); +#else const Window& curConfWindow = curPPS->getConformanceWindow(); - int curPicWidth = curPPS->getPicWidthInLumaSamples() - (curConfWindow.getWindowLeftOffset() + curConfWindow.getWindowRightOffset()) * SPS::getWinUnitY(sps->getChromaFormatIdc()); + int curPicWidth = curPPS->getPicWidthInLumaSamples() - (curConfWindow.getWindowLeftOffset() + curConfWindow.getWindowRightOffset()) * SPS::getWinUnitX(sps->getChromaFormatIdc()); int curPicHeight = curPPS->getPicHeightInLumaSamples() - (curConfWindow.getWindowTopOffset() + curConfWindow.getWindowBottomOffset()) * SPS::getWinUnitY(sps->getChromaFormatIdc()); const Window& refConfWindow = refPic->getConformanceWindow(); - int refPicWidth = refPic->getPicWidthInLumaSamples() - (refConfWindow.getWindowLeftOffset() + refConfWindow.getWindowRightOffset()) * SPS::getWinUnitY(sps->getChromaFormatIdc()); + int refPicWidth = refPic->getPicWidthInLumaSamples() - (refConfWindow.getWindowLeftOffset() + refConfWindow.getWindowRightOffset()) * SPS::getWinUnitX(sps->getChromaFormatIdc()); int refPicHeight = refPic->getPicHeightInLumaSamples() - (refConfWindow.getWindowTopOffset() + refConfWindow.getWindowBottomOffset()) * SPS::getWinUnitY(sps->getChromaFormatIdc()); +#endif xScale = ( ( refPicWidth << SCALE_RATIO_BITS ) + ( curPicWidth >> 1 ) ) / curPicWidth; yScale = ( ( refPicHeight << SCALE_RATIO_BITS ) + ( curPicHeight >> 1 ) ) / curPicHeight; @@ -1376,7 +1386,11 @@ bool PU::checkDMVRCondition(const PredictionUnit& pu) && ((pu.lheight() * pu.lwidth()) >= 128) && (pu.cu->GBiIdx == GBI_DEFAULT) && ((!wp0[COMPONENT_Y].bPresentFlag) && (!wp1[COMPONENT_Y].bPresentFlag)) +#if JVET_P0590_SCALING_WINDOW + && pu.cu->slice->getScalingRatio( REF_PIC_LIST_0, refIdx0 ) == SCALE_1X && pu.cu->slice->getScalingRatio( REF_PIC_LIST_1, refIdx1 ) == SCALE_1X +#else && PU::isRefPicSameSize( pu ) +#endif ; } else @@ -3951,6 +3965,7 @@ bool allowLfnstWithMip(const Size& block) return false; } +#if !JVET_P0590_SCALING_WINDOW bool PU::isRefPicSameSize( const PredictionUnit& pu ) { bool samePicSize = true; @@ -3975,6 +3990,6 @@ bool PU::isRefPicSameSize( const PredictionUnit& pu ) return samePicSize; } - +#endif diff --git a/source/Lib/CommonLib/UnitTools.h b/source/Lib/CommonLib/UnitTools.h index 497679860c42c1483a8f7307c98f2ac1d29d9d3c..2d1d02d0d0ae00fd8748aba03c3be1af075e6540 100644 --- a/source/Lib/CommonLib/UnitTools.h +++ b/source/Lib/CommonLib/UnitTools.h @@ -190,7 +190,9 @@ namespace PU bool getDerivedBV(PredictionUnit &pu, const Mv& currentMv, Mv& derivedMv); bool checkDMVRCondition(const PredictionUnit& pu); +#if !JVET_P0590_SCALING_WINDOW bool isRefPicSameSize( const PredictionUnit& pu ); +#endif } // TU tools diff --git a/source/Lib/DecoderLib/DecLib.cpp b/source/Lib/DecoderLib/DecLib.cpp index 58b680f472034e721f325330d8228222af96004f..a6e8186ac570dbf9a19c8030dfafd644359a61f6 100644 --- a/source/Lib/DecoderLib/DecLib.cpp +++ b/source/Lib/DecoderLib/DecLib.cpp @@ -927,6 +927,10 @@ void DecLib::xActivateParameterSets() m_pcPic->setPicWidthInLumaSamples( pps->getPicWidthInLumaSamples() ); m_pcPic->setPicHeightInLumaSamples( pps->getPicHeightInLumaSamples() ); m_pcPic->setConformanceWindow( confWin ); +#if JVET_P0590_SCALING_WINDOW + Window scalingWindow = pps->getScalingWindow(); + m_pcPic->setScalingWindow( scalingWindow ); +#endif memcpy(m_pcPic->cs->alfApss, apss, sizeof(m_pcPic->cs->alfApss)); m_pcPic->cs->lmcsAps = lmcsAPS; @@ -1072,6 +1076,15 @@ void DecLib::xActivateParameterSets() CHECK( ( pps->getPicWidthInLumaSamples() % ( std::max( 8, int( sps->getMaxCUWidth() >> ( sps->getMaxCodingDepth() - 1 ) ) ) ) ) != 0, "Coded frame width must be a multiple of Max(8, the minimum unit size)" ); CHECK( ( pps->getPicHeightInLumaSamples() % ( std::max( 8, int( sps->getMaxCUHeight() >> ( sps->getMaxCodingDepth() - 1 ) ) ) ) ) != 0, "Coded frame height must be a multiple of Max(8, the minimum unit size)" ); +#if JVET_P0590_SCALING_WINDOW + if( !sps->getRprEnabledFlag() ) // subpics_present_flag is equal to 1 condition shall be added + { + CHECK( pps->getPicWidthInLumaSamples() != sps->getMaxPicWidthInLumaSamples(), "When subpics_present_flag is equal to 1 or ref_pic_resampling_enabled_flag equal to 0, the value of pic_width_in_luma_samples shall be equal to pic_width_max_in_luma_samples." ); + CHECK( pps->getPicHeightInLumaSamples() != sps->getMaxPicHeightInLumaSamples(), "When subpics_present_flag is equal to 1 or ref_pic_resampling_enabled_flag equal to 0, the value of pic_height_in_luma_samples shall be equal to pic_height_max_in_luma_samples." ); + } + + CHECK( !sps->getRprEnabledFlag() && pps->getScalingWindow().getWindowEnabledFlag(), "When ref_pic_resampling_enabled_flag is equal to 0, the value of scaling_window_flag shall be equal to 0." ); +#endif if( sps->getCTUSize() + 2 * ( 1 << sps->getLog2MinCodingBlockSize() ) > pps->getPicWidthInLumaSamples() ) { diff --git a/source/Lib/DecoderLib/VLCReader.cpp b/source/Lib/DecoderLib/VLCReader.cpp index 4a220e1062f85b24323fa7ef82c3e1778c19732e..4dfe5a89538bc53bc1b8930573ed4ab85223c3f4 100644 --- a/source/Lib/DecoderLib/VLCReader.cpp +++ b/source/Lib/DecoderLib/VLCReader.cpp @@ -381,6 +381,17 @@ void HLSyntaxReader::parsePPS( PPS* pcPPS, ParameterSetManager *parameterSetMana READ_UVLC( uiCode, "conf_win_bottom_offset" ); conf.setWindowBottomOffset( uiCode ); } +#if JVET_P0590_SCALING_WINDOW + READ_FLAG( uiCode, "scaling_window_flag" ); + if( uiCode != 0 ) + { + Window &scalingWindow = pcPPS->getScalingWindow(); + READ_UVLC( uiCode, "scaling_win_left_offset" ); scalingWindow.setWindowLeftOffset( uiCode ); + READ_UVLC( uiCode, "scaling_win_right_offset" ); scalingWindow.setWindowRightOffset( uiCode ); + READ_UVLC( uiCode, "scaling_win_top_offset" ); scalingWindow.setWindowTopOffset( uiCode ); + READ_UVLC( uiCode, "scaling_win_bottom_offset" ); scalingWindow.setWindowBottomOffset( uiCode ); + } +#endif READ_FLAG( uiCode, "output_flag_present_flag" ); pcPPS->setOutputFlagPresentFlag( uiCode==1 ); @@ -1176,13 +1187,15 @@ void HLSyntaxReader::parseSPS(SPS* pcSPS) READ_UVLC( uiCode, "chroma_format_idc" ); pcSPS->setChromaFormatIdc( ChromaFormat(uiCode) ); CHECK(uiCode > 3, "Invalid chroma format signalled"); - - if( pcSPS->getChromaFormatIdc() == CHROMA_444 ) { READ_FLAG( uiCode, "separate_colour_plane_flag"); CHECK(uiCode != 0, "Invalid code"); } +#if JVET_P0590_SCALING_WINDOW + READ_FLAG( uiCode, "ref_pic_resampling_enabled_flag" ); pcSPS->setRprEnabledFlag( uiCode ); +#endif + READ_UVLC( uiCode, "pic_width_max_in_luma_samples" ); pcSPS->setMaxPicWidthInLumaSamples( uiCode ); READ_UVLC( uiCode, "pic_height_max_in_luma_samples" ); pcSPS->setMaxPicHeightInLumaSamples( uiCode ); @@ -1426,10 +1439,18 @@ void HLSyntaxReader::parseSPS(SPS* pcSPS) READ_FLAG(uiCode, "sps_mmvd_enable_flag"); pcSPS->setUseMMVD(uiCode != 0); // KJS: sps_cclm_enabled_flag READ_FLAG( uiCode, "lm_chroma_enabled_flag" ); pcSPS->setUseLMChroma ( uiCode != 0 ); +#if JVET_P0592_CHROMA_PHASE + if( pcSPS->getChromaFormatIdc() == CHROMA_420 ) + { + READ_FLAG( uiCode, "sps_chroma_horizontal_collocated_flag" ); pcSPS->setHorCollocatedChromaFlag( uiCode != 0 ); + READ_FLAG( uiCode, "sps_chroma_vertical_collocated_flag" ); pcSPS->setVerCollocatedChromaFlag( uiCode != 0 ); + } +#else if ( pcSPS->getUseLMChroma() && pcSPS->getChromaFormatIdc() == CHROMA_420 ) { READ_FLAG( uiCode, "sps_cclm_collocated_chroma_flag" ); pcSPS->setCclmCollocatedChromaFlag( uiCode != 0 ); } +#endif READ_FLAG( uiCode, "mts_enabled_flag" ); pcSPS->setUseMTS ( uiCode != 0 ); if ( pcSPS->getUseMTS() ) diff --git a/source/Lib/EncoderLib/EncCfg.h b/source/Lib/EncoderLib/EncCfg.h index ed1aeefd96c10c3d63434693e68bcb3f20d412c9..5621a1deb3f30bca7afc7cef06bc87c69435afc4 100644 --- a/source/Lib/EncoderLib/EncCfg.h +++ b/source/Lib/EncoderLib/EncCfg.h @@ -273,7 +273,12 @@ protected: unsigned m_log2DiffMaxMinCodingBlockSize; int m_LMChroma; +#if JVET_P0592_CHROMA_PHASE + bool m_horCollocatedChromaFlag; + bool m_verCollocatedChromaFlag; +#else bool m_cclmCollocatedChromaFlag; +#endif int m_IntraMTS; int m_InterMTS; #if JVET_P0273_MTSIntraMaxCand @@ -865,8 +870,15 @@ public: void setUseLMChroma ( int n ) { m_LMChroma = n; } int getUseLMChroma() const { return m_LMChroma; } +#if JVET_P0592_CHROMA_PHASE + void setHorCollocatedChromaFlag( bool b ) { m_horCollocatedChromaFlag = b; } + bool getHorCollocatedChromaFlag() const { return m_horCollocatedChromaFlag; } + void setVerCollocatedChromaFlag( bool b ) { m_verCollocatedChromaFlag = b; } + bool getVerCollocatedChromaFlag() const { return m_verCollocatedChromaFlag; } +#else void setCclmCollocatedChromaFlag ( bool b ) { m_cclmCollocatedChromaFlag = b; } bool getCclmCollocatedChromaFlag () const { return m_cclmCollocatedChromaFlag; } +#endif void setSubPuMvpMode(int n) { m_SubPuMvpMode = n; } bool getSubPuMvpMode() const { return m_SubPuMvpMode; } diff --git a/source/Lib/EncoderLib/EncGOP.cpp b/source/Lib/EncoderLib/EncGOP.cpp index eb349662a354055268937183908290d59b040c32..2e6f7954dd2b1cde9f10e77c0f5b02e7824362d7 100644 --- a/source/Lib/EncoderLib/EncGOP.cpp +++ b/source/Lib/EncoderLib/EncGOP.cpp @@ -3709,9 +3709,32 @@ void EncGOP::xCalculateAddPSNR(Picture* pcPic, PelUnitBuf cPicD, const AccessUni { const CPelBuf& upscaledOrg = sps.getUseReshaper() ? pcPic->M_BUFS( 0, PIC_TRUE_ORIGINAL_INPUT).get( COMPONENT_Y ) : pcPic->M_BUFS( 0, PIC_ORIGINAL_INPUT).get( COMPONENT_Y ); upscaledRec.create( pic.chromaFormat, Area( Position(), upscaledOrg ) ); + +#if JVET_P0590_SCALING_WINDOW + int xScale, yScale; + // it is assumed that full resolution picture PPS has ppsId 0 + const PPS* pps = m_pcEncLib->getPPS(0); + CU::getRprScaling( &sps, pps, pcPic, xScale, yScale ); + std::pair<int, int> scalingRatio = std::pair<int, int>( xScale, yScale ); + +#if JVET_P0592_CHROMA_PHASE + Picture::rescalePicture( scalingRatio, picC, pcPic->getScalingWindow(), upscaledRec, pps->getScalingWindow(), format, sps.getBitDepths(), false, false, sps.getHorCollocatedChromaFlag(), sps.getVerCollocatedChromaFlag() ); +#else + Picture::rescalePicture( scalingRatio, picC, pcPic->getScalingWindow(), upscaledRec, pps->getScalingWindow(), format, sps.getBitDepths(), false ); +#endif +#elif JVET_P0592_CHROMA_PHASE + int xScale, yScale; + // it is assumed that full resolution picture PPS has ppsId 0 + const PPS* pps = m_pcEncLib->getPPS( 0 ); + CU::getRprScaling( &sps, pps, pcPic, xScale, yScale ); + std::pair<int, int> scalingRatio = std::pair<int, int>( xScale, yScale ); + + Picture::rescalePicture( scalingRatio, picC, pcPic->getConformanceWindow(), upscaledRec, m_pcEncLib->getConformanceWindow(), format, sps.getBitDepths(), false, false, sps.getHorCollocatedChromaFlag(), sps.getVerCollocatedChromaFlag() ); +#else // the input source picture has a conformance window derived at encoder Window& conformanceWindow = m_pcEncLib->getConformanceWindow(); Picture::rescalePicture( picC, pcPic->cs->pps->getConformanceWindow(), upscaledRec, conformanceWindow, format, sps.getBitDepths(), false ); +#endif } for (int comp = 0; comp < ::getNumberValidComponents(formatD); comp++) @@ -3723,8 +3746,25 @@ void EncGOP::xCalculateAddPSNR(Picture* pcPic, PelUnitBuf cPicD, const AccessUni CHECK(!( p.width == o.width), "Unspecified error"); CHECK(!( p.height == o.height), "Unspecified error"); +#if JVET_P0590_SCALING_WINDOW + int padX = m_pcEncLib->getPad( 0 ); + int padY = m_pcEncLib->getPad( 1 ); + + // when RPR is enabled, picture padding is picture specific due to possible different picture resoluitons, however only full resolution padding is stored in EncLib + // get per picture padding from the conformance window, in this case if conformance window is set not equal to the padding then PSNR results may be inaccurate + if( m_pcEncLib->isRPREnabled() ) + { + Window& conf = pcPic->getConformanceWindow(); + padX = conf.getWindowRightOffset() * SPS::getWinUnitX( format ); + padY = conf.getWindowBottomOffset() * SPS::getWinUnitY( format ); + } + + const uint32_t width = p.width - ( padX >> ::getComponentScaleX( compID, format ) ); + const uint32_t height = p.height - ( padY >> ( !!bPicIsField + ::getComponentScaleY( compID, format ) ) ); +#else const uint32_t width = p.width - (m_pcEncLib->getPad(0) >> ::getComponentScaleX(compID, format)); const uint32_t height = p.height - (m_pcEncLib->getPad(1) >> (!!bPicIsField+::getComponentScaleY(compID,format))); +#endif // create new buffers with correct dimensions const CPelBuf recPB(p.bufAt(0, 0), p.stride, width, height); @@ -3753,6 +3793,22 @@ void EncGOP::xCalculateAddPSNR(Picture* pcPic, PelUnitBuf cPicD, const AccessUni { const CPelBuf& upscaledOrg = sps.getUseReshaper() ? pcPic->M_BUFS( 0, PIC_TRUE_ORIGINAL_INPUT ).get( compID ) : pcPic->M_BUFS( 0, PIC_ORIGINAL_INPUT ).get( compID ); +#if JVET_P0590_SCALING_WINDOW + const uint32_t upscaledWidth = upscaledOrg.width - ( m_pcEncLib->getPad( 0 ) >> ::getComponentScaleX( compID, format ) ); + const uint32_t upscaledHeight = upscaledOrg.height - ( m_pcEncLib->getPad( 1 ) >> ( !!bPicIsField + ::getComponentScaleY( compID, format ) ) ); + + // create new buffers with correct dimensions + const CPelBuf upscaledRecPB( upscaledRec.get( compID ).bufAt( 0, 0 ), upscaledRec.get( compID ).stride, upscaledWidth, upscaledHeight ); + const CPelBuf upscaledOrgPB( upscaledOrg.bufAt( 0, 0 ), upscaledOrg.stride, upscaledWidth, upscaledHeight ); + +#if ENABLE_QPA + const uint64_t upscaledSSD = xFindDistortionPlane( upscaledRecPB, upscaledOrgPB, useWPSNR ? bitDepth : 0, ::getComponentScaleX( compID, format ) ); +#else + const uint64_t scaledSSD = xFindDistortionPlane( upsacledRecPB, upsacledOrgPB, 0 ); +#endif + + upscaledPSNR[comp] = upscaledSSD ? 10.0 * log10( (double)maxval * maxval * upscaledWidth * upscaledHeight / (double)upscaledSSD ) : 999.99; +#else #if ENABLE_QPA const uint64_t upscaledSSD = xFindDistortionPlane( upscaledRec.get( compID ), upscaledOrg, useWPSNR ? bitDepth : 0, ::getComponentScaleX( compID, format ), ::getComponentScaleY( compID, format ) ); #else @@ -3760,6 +3816,7 @@ void EncGOP::xCalculateAddPSNR(Picture* pcPic, PelUnitBuf cPicD, const AccessUni #endif upscaledPSNR[comp] = upscaledSSD ? 10.0 * log10( (double)maxval * maxval * upscaledOrg.width * upscaledOrg.height / (double)upscaledSSD ) : 999.99; +#endif } } diff --git a/source/Lib/EncoderLib/EncLib.cpp b/source/Lib/EncoderLib/EncLib.cpp index 37a1184f733c7ffe5f8d5803c6fdba2d37c5bdae..11e1a7d6ffc0ee435e5820fd2f3becbc28e45aca 100644 --- a/source/Lib/EncoderLib/EncLib.cpp +++ b/source/Lib/EncoderLib/EncLib.cpp @@ -266,13 +266,22 @@ void EncLib::init( bool isFieldCoding, AUWriterIf* auWriterIf ) if( m_rprEnabled ) { PPS &pps = *( m_ppsMap.allocatePS( ENC_PPS_ID_RPR ) ); +#if JVET_P0590_SCALING_WINDOW + Window& inputScalingWindow = pps0.getScalingWindow(); + int scaledWidth = int( ( pps0.getPicWidthInLumaSamples() - inputScalingWindow.getWindowLeftOffset() - inputScalingWindow.getWindowRightOffset() ) / m_scalingRatioHor ); +#else Window& inputConfWindow = pps0.getConformanceWindow(); int scaledWidth = int((pps0.getPicWidthInLumaSamples() - (inputConfWindow.getWindowLeftOffset() + inputConfWindow.getWindowRightOffset()) * SPS::getWinUnitX(sps0.getChromaFormatIdc())) / m_scalingRatioHor); +#endif int minSizeUnit = std::max(8, (int)(sps0.getMaxCUHeight() >> (sps0.getMaxCodingDepth() - 1))); int temp = scaledWidth / minSizeUnit; int width = ( scaledWidth - ( temp * minSizeUnit) > 0 ? temp + 1 : temp ) * minSizeUnit; +#if JVET_P0590_SCALING_WINDOW + int scaledHeight = int( ( pps0.getPicHeightInLumaSamples() - inputScalingWindow.getWindowTopOffset() - inputScalingWindow.getWindowBottomOffset() ) / m_scalingRatioVer ); +#else int scaledHeight = int((pps0.getPicHeightInLumaSamples() - (inputConfWindow.getWindowTopOffset() + inputConfWindow.getWindowBottomOffset()) * SPS::getWinUnitY(sps0.getChromaFormatIdc())) / m_scalingRatioVer); +#endif temp = scaledHeight / minSizeUnit; int height = ( scaledHeight - ( temp * minSizeUnit) > 0 ? temp + 1 : temp ) * minSizeUnit; @@ -280,11 +289,15 @@ void EncLib::init( bool isFieldCoding, AUWriterIf* auWriterIf ) pps.setPicHeightInLumaSamples( height ); Window conformanceWindow; - conformanceWindow.setWindow( 0, ( width - scaledWidth ) / SPS::getWinUnitX( sps0.getChromaFormatIdc() ), 0, ( height - scaledHeight ) / SPS::getWinUnitY( sps0.getChromaFormatIdc() ) ); - pps.setConformanceWindow( conformanceWindow ); +#if JVET_P0590_SCALING_WINDOW + Window scalingWindow; + scalingWindow.setWindow( 0, width - scaledWidth, 0, height - scaledHeight ); + pps.setScalingWindow( scalingWindow ); +#endif + xInitPPS( pps, sps0 ); // will allocate memory for and initialize pps.pcv inside } @@ -562,6 +575,10 @@ void EncLib::encode( bool flush, PelStorage* pcPicYuvOrg, PelStorage* cPicYuvTru picCurr->setPicWidthInLumaSamples( pps->getPicWidthInLumaSamples() ); picCurr->setPicHeightInLumaSamples( pps->getPicHeightInLumaSamples() ); picCurr->setConformanceWindow( confWin ); +#if JVET_P0590_SCALING_WINDOW + Window scalingWindow = pps->getScalingWindow(); + picCurr->setScalingWindow( scalingWindow ); +#endif picCurr->M_BUFS(0, PIC_ORIGINAL).copyFrom(m_cGOPEncoder.getPicBg()->getRecoBuf()); picCurr->finalInit( *sps, *pps, m_apss, m_lmcsAPS, m_scalinglistAPS ); @@ -617,8 +634,7 @@ void EncLib::encode( bool flush, PelStorage* pcPicYuvOrg, PelStorage* cPicYuvTru ppsID = 0; } } - xGetNewPicBuffer( rcListPicYuvRecOut, - pcPicCurr, ppsID ); + xGetNewPicBuffer( rcListPicYuvRecOut, pcPicCurr, ppsID ); { const PPS *pPPS=(ppsID<0) ? m_ppsMap.getFirstPS() : m_ppsMap.getPS(ppsID); @@ -628,6 +644,10 @@ void EncLib::encode( bool flush, PelStorage* pcPicYuvOrg, PelStorage* cPicYuvTru pcPicCurr->setPicWidthInLumaSamples( pPPS->getPicWidthInLumaSamples() ); pcPicCurr->setPicHeightInLumaSamples( pPPS->getPicHeightInLumaSamples() ); pcPicCurr->setConformanceWindow( confWin ); +#if JVET_P0590_SCALING_WINDOW + Window scalingWindow = pPPS->getScalingWindow(); + pcPicCurr->setScalingWindow( scalingWindow ); +#endif if( m_rprEnabled ) { @@ -642,8 +662,49 @@ void EncLib::encode( bool flush, PelStorage* pcPicYuvOrg, PelStorage* cPicYuvTru const ChromaFormat chromaFormatIDC = pSPS->getChromaFormatIdc(); const PPS *refPPS = m_ppsMap.getPS(0); +#if JVET_P0590_SCALING_WINDOW + const Window& curScalingWindow = pPPS->getScalingWindow(); + int curPicWidth = pPPS->getPicWidthInLumaSamples() - curScalingWindow.getWindowLeftOffset() - curScalingWindow.getWindowRightOffset(); + int curPicHeight = pPPS->getPicHeightInLumaSamples() - curScalingWindow.getWindowTopOffset() - curScalingWindow.getWindowBottomOffset(); + + const Window& refScalingWindow = refPPS->getScalingWindow(); + int refPicWidth = refPPS->getPicWidthInLumaSamples() - refScalingWindow.getWindowLeftOffset() - refScalingWindow.getWindowRightOffset(); + int refPicHeight = refPPS->getPicHeightInLumaSamples() - refScalingWindow.getWindowTopOffset() - refScalingWindow.getWindowBottomOffset(); + + int xScale = ( ( refPicWidth << SCALE_RATIO_BITS ) + ( curPicWidth >> 1 ) ) / curPicWidth; + int yScale = ( ( refPicHeight << SCALE_RATIO_BITS ) + ( curPicHeight >> 1 ) ) / curPicHeight; + std::pair<int, int> scalingRatio = std::pair<int, int>( xScale, yScale ); + +#if JVET_P0592_CHROMA_PHASE + Picture::rescalePicture( scalingRatio, *pcPicYuvOrg, refPPS->getScalingWindow(), pcPicCurr->getOrigBuf(), pPPS->getScalingWindow(), chromaFormatIDC, pSPS->getBitDepths(), true, true, + pSPS->getHorCollocatedChromaFlag(), pSPS->getVerCollocatedChromaFlag() ); + Picture::rescalePicture( scalingRatio, *cPicYuvTrueOrg, refPPS->getScalingWindow(), pcPicCurr->getTrueOrigBuf(), pPPS->getScalingWindow(), chromaFormatIDC, pSPS->getBitDepths(), true, true, + pSPS->getHorCollocatedChromaFlag(), pSPS->getVerCollocatedChromaFlag() ); +#else + Picture::rescalePicture( scalingRatio, *pcPicYuvOrg, refPPS->getScalingWindow(), pcPicCurr->getOrigBuf(), pPPS->getScalingWindow(), chromaFormatIDC, pSPS->getBitDepths(), true, true ); + Picture::rescalePicture( scalingRatio, *cPicYuvTrueOrg, refPPS->getScalingWindow(), pcPicCurr->getTrueOrigBuf(), pPPS->getScalingWindow(), chromaFormatIDC, pSPS->getBitDepths(), true, true ); +#endif +#elif JVET_P0592_CHROMA_PHASE + const Window& curWindow = pPPS->getConformanceWindow(); + int curPicWidth = pPPS->getPicWidthInLumaSamples() - ( curWindow.getWindowLeftOffset() + curWindow.getWindowRightOffset() ) * SPS::getWinUnitX( chromaFormatIDC ); + int curPicHeight = pPPS->getPicHeightInLumaSamples() - ( curWindow.getWindowTopOffset() + curWindow.getWindowBottomOffset() ) * SPS::getWinUnitY( chromaFormatIDC ); + + const Window& refWindow = refPPS->getConformanceWindow(); + int refPicWidth = refPPS->getPicWidthInLumaSamples() - ( refWindow.getWindowLeftOffset() + refWindow.getWindowRightOffset() ) * SPS::getWinUnitX( chromaFormatIDC ); + int refPicHeight = refPPS->getPicHeightInLumaSamples() - ( refWindow.getWindowTopOffset() + refWindow.getWindowBottomOffset() ) * SPS::getWinUnitY( chromaFormatIDC ); + + int xScale = ( ( refPicWidth << SCALE_RATIO_BITS ) + ( curPicWidth >> 1 ) ) / curPicWidth; + int yScale = ( ( refPicHeight << SCALE_RATIO_BITS ) + ( curPicHeight >> 1 ) ) / curPicHeight; + std::pair<int, int> scalingRatio = std::pair<int, int>( xScale, yScale ); + + Picture::rescalePicture( scalingRatio, *pcPicYuvOrg, refPPS->getConformanceWindow(), pcPicCurr->getOrigBuf(), pPPS->getConformanceWindow(), chromaFormatIDC, pSPS->getBitDepths(), true, true, + pSPS->getHorCollocatedChromaFlag(), pSPS->getVerCollocatedChromaFlag() ); + Picture::rescalePicture( scalingRatio, *cPicYuvTrueOrg, refPPS->getConformanceWindow(), pcPicCurr->getTrueOrigBuf(), pPPS->getConformanceWindow(), chromaFormatIDC, pSPS->getBitDepths(), true, true, + pSPS->getHorCollocatedChromaFlag(), pSPS->getVerCollocatedChromaFlag() ); +#else Picture::rescalePicture( *pcPicYuvOrg, refPPS->getConformanceWindow(), pcPicCurr->getOrigBuf(), pPPS->getConformanceWindow(), chromaFormatIDC, pSPS->getBitDepths(), true, true ); Picture::rescalePicture( *cPicYuvTrueOrg, refPPS->getConformanceWindow(), pcPicCurr->getTrueOrigBuf(), pPPS->getConformanceWindow(), chromaFormatIDC, pSPS->getBitDepths(), true, true ); +#endif } else { @@ -754,6 +815,10 @@ void EncLib::encode( bool flush, PelStorage* pcPicYuvOrg, PelStorage* pcPicYuvTr pcField->setPicWidthInLumaSamples( pPPS->getPicWidthInLumaSamples() ); pcField->setPicHeightInLumaSamples( pPPS->getPicHeightInLumaSamples() ); pcField->setConformanceWindow( confWin ); +#if JVET_P0590_SCALING_WINDOW + Window scalingWindow = pPPS->getScalingWindow(); + pcField->setScalingWindow( scalingWindow ); +#endif pcField->finalInit( *pSPS, *pPPS, m_apss, m_lmcsAPS, m_scalinglistAPS ); } @@ -991,7 +1056,12 @@ void EncLib::xInitSPS(SPS &sps) sps.setUseAffineType ( m_AffineType ); sps.setUsePROF ( m_PROF ); sps.setUseLMChroma ( m_LMChroma ? true : false ); +#if JVET_P0592_CHROMA_PHASE + sps.setHorCollocatedChromaFlag( m_horCollocatedChromaFlag ); + sps.setVerCollocatedChromaFlag( m_verCollocatedChromaFlag ); +#else sps.setCclmCollocatedChromaFlag( m_cclmCollocatedChromaFlag ); +#endif sps.setUseMTS ( m_IntraMTS || m_InterMTS || m_ImplicitMTS ); sps.setUseIntraMTS ( m_IntraMTS ); sps.setUseInterMTS ( m_InterMTS ); @@ -1141,8 +1211,14 @@ void EncLib::xInitSPS(SPS &sps) sps.getSpsRangeExtension().setPersistentRiceAdaptationEnabledFlag(m_persistentRiceAdaptationEnabledFlag); sps.getSpsRangeExtension().setCabacBypassAlignmentEnabledFlag(m_cabacBypassAlignmentEnabledFlag); - if (m_uiIntraPeriod < 0) - sps.setRPL1CopyFromRPL0Flag(true); + if( m_uiIntraPeriod < 0 ) + { + sps.setRPL1CopyFromRPL0Flag( true ); + } + +#if JVET_P0590_SCALING_WINDOW + sps.setRprEnabledFlag( m_rprEnabled ); +#endif } void EncLib::xInitHrdParameters(SPS &sps) diff --git a/source/Lib/EncoderLib/VLCWriter.cpp b/source/Lib/EncoderLib/VLCWriter.cpp index d5d10ce2706fb99d999f243a182079fd916e620c..72bf2b69bd27a2453dd220898de1a979c73e2379 100644 --- a/source/Lib/EncoderLib/VLCWriter.cpp +++ b/source/Lib/EncoderLib/VLCWriter.cpp @@ -223,6 +223,18 @@ void HLSWriter::codePPS( const PPS* pcPPS, const SPS* pcSPS ) WRITE_UVLC( conf.getWindowTopOffset(), "conf_win_top_offset" ); WRITE_UVLC( conf.getWindowBottomOffset(), "conf_win_bottom_offset" ); } +#if JVET_P0590_SCALING_WINDOW + Window scalingWindow = pcPPS->getScalingWindow(); + + WRITE_FLAG( scalingWindow.getWindowEnabledFlag(), "scaling_window_flag" ); + if( scalingWindow.getWindowEnabledFlag() ) + { + WRITE_UVLC( scalingWindow.getWindowLeftOffset(), "scaling_win_left_offset" ); + WRITE_UVLC( scalingWindow.getWindowRightOffset(), "scaling_win_right_offset" ); + WRITE_UVLC( scalingWindow.getWindowTopOffset(), "scaling_win_top_offset" ); + WRITE_UVLC( scalingWindow.getWindowBottomOffset(), "scaling_win_bottom_offset" ); + } +#endif WRITE_FLAG( pcPPS->getOutputFlagPresentFlag() ? 1 : 0, "output_flag_present_flag" ); WRITE_CODE( pcPPS->getNumExtraSliceHeaderBits(), 3, "num_extra_slice_header_bits"); @@ -719,6 +731,10 @@ void HLSWriter::codeSPS( const SPS* pcSPS ) WRITE_FLAG( 0, "separate_colour_plane_flag"); } +#if JVET_P0590_SCALING_WINDOW + WRITE_FLAG( pcSPS->getRprEnabledFlag(), "ref_pic_resampling_enabled_flag" ); +#endif + WRITE_UVLC( pcSPS->getMaxPicWidthInLumaSamples(), "pic_width_max_in_luma_samples" ); WRITE_UVLC( pcSPS->getMaxPicHeightInLumaSamples(), "pic_height_max_in_luma_samples" ); @@ -868,10 +884,19 @@ void HLSWriter::codeSPS( const SPS* pcSPS ) WRITE_FLAG(pcSPS->getUseMMVD() ? 1 : 0, "sps_mmvd_enable_flag"); // KJS: sps_cclm_enabled_flag WRITE_FLAG( pcSPS->getUseLMChroma() ? 1 : 0, "lm_chroma_enabled_flag" ); + +#if JVET_P0592_CHROMA_PHASE + if( pcSPS->getChromaFormatIdc() == CHROMA_420 ) + { + WRITE_FLAG( pcSPS->getHorCollocatedChromaFlag() ? 1 : 0, "sps_chroma_horizontal_collocated_flag" ); + WRITE_FLAG( pcSPS->getVerCollocatedChromaFlag() ? 1 : 0, "sps_chroma_vertical_collocated_flag" ); + } +#else if ( pcSPS->getUseLMChroma() && pcSPS->getChromaFormatIdc() == CHROMA_420 ) { WRITE_FLAG( pcSPS->getCclmCollocatedChromaFlag() ? 1 : 0, "sps_cclm_collocated_chroma_flag" ); } +#endif WRITE_FLAG( pcSPS->getUseMTS() ? 1 : 0, "mts_enabled_flag" ); if ( pcSPS->getUseMTS() ) diff --git a/source/Lib/Utilities/VideoIOYuv.cpp b/source/Lib/Utilities/VideoIOYuv.cpp index a320adf05ab11cfbb3ad22c3902866ee2eb04a07..0cbc8738a376d753964fd29ecd0fbc414a98be4e 100644 --- a/source/Lib/Utilities/VideoIOYuv.cpp +++ b/source/Lib/Utilities/VideoIOYuv.cpp @@ -1224,14 +1224,68 @@ bool VideoIOYuv::writeUpscaledPicture( const SPS& sps, const PPS& pps, const CPe ChromaFormat chromaFormatIDC = sps.getChromaFormatIdc(); bool ret = false; +#if JVET_P0590_SCALING_WINDOW + static Window confFullResolution; + static Window afterScaleWindowFullResolution; + + // decoder does not have information about upscaled picture scaling and conformance windows, store this information when full resolution picutre is encountered + if( sps.getMaxPicWidthInLumaSamples() == pps.getPicWidthInLumaSamples() && sps.getMaxPicHeightInLumaSamples() == pps.getPicHeightInLumaSamples() ) + { + afterScaleWindowFullResolution = pps.getScalingWindow(); + afterScaleWindowFullResolution = pps.getConformanceWindow(); + } +#endif + if( outputChoice && ( sps.getMaxPicWidthInLumaSamples() != pic.get( COMPONENT_Y ).width || sps.getMaxPicHeightInLumaSamples() != pic.get( COMPONENT_Y ).height ) ) { if( outputChoice == 2 ) { PelStorage upscaledPic; upscaledPic.create( chromaFormatIDC, Area( Position(), Size( sps.getMaxPicWidthInLumaSamples(), sps.getMaxPicHeightInLumaSamples() ) ) ); + +#if JVET_P0590_SCALING_WINDOW + int curPicWidth = sps.getMaxPicWidthInLumaSamples() - afterScaleWindowFullResolution.getWindowLeftOffset() - afterScaleWindowFullResolution.getWindowRightOffset(); + int curPicHeight = sps.getMaxPicHeightInLumaSamples() - afterScaleWindowFullResolution.getWindowTopOffset() - afterScaleWindowFullResolution.getWindowBottomOffset(); + + const Window& beforeScalingWindow = pps.getScalingWindow(); + int refPicWidth = pps.getPicWidthInLumaSamples() - beforeScalingWindow.getWindowLeftOffset() - beforeScalingWindow.getWindowRightOffset(); + int refPicHeight = pps.getPicHeightInLumaSamples() - beforeScalingWindow.getWindowTopOffset() - beforeScalingWindow.getWindowBottomOffset(); + + int xScale = ( ( refPicWidth << SCALE_RATIO_BITS ) + ( curPicWidth >> 1 ) ) / curPicWidth; + int yScale = ( ( refPicHeight << SCALE_RATIO_BITS ) + ( curPicHeight >> 1 ) ) / curPicHeight; + +#if JVET_P0592_CHROMA_PHASE + Picture::rescalePicture( std::pair<int, int>( xScale, yScale ), pic, pps.getScalingWindow(), upscaledPic, afterScaleWindowFullResolution, chromaFormatIDC, sps.getBitDepths(), false, false, sps.getHorCollocatedChromaFlag(), sps.getVerCollocatedChromaFlag() ); +#else + Picture::rescalePicture( std::pair<int, int>( xScale, yScale ), pic, pps.getScalingWindow(), upscaledPic, afterScaleWindowFullResolution, chromaFormatIDC, sps.getBitDepths(), false ); +#endif + + ret = write( sps.getMaxPicWidthInLumaSamples(), sps.getMaxPicHeightInLumaSamples(), upscaledPic, + ipCSC, + bPackedYUVOutputMode, + confFullResolution.getWindowLeftOffset() * SPS::getWinUnitX( chromaFormatIDC ), + confFullResolution.getWindowRightOffset() * SPS::getWinUnitX( chromaFormatIDC ), + confFullResolution.getWindowTopOffset() * SPS::getWinUnitY( chromaFormatIDC ), + confFullResolution.getWindowBottomOffset() * SPS::getWinUnitY( chromaFormatIDC ), + NUM_CHROMA_FORMAT, bClipToRec709 ); +#else const Window conf; + +#if JVET_P0592_CHROMA_PHASE + int curPicWidth = sps.getMaxPicWidthInLumaSamples() - ( conf.getWindowLeftOffset() + conf.getWindowRightOffset() ) * SPS::getWinUnitX( chromaFormatIDC ); + int curPicHeight = sps.getMaxPicHeightInLumaSamples() - ( conf.getWindowTopOffset() + conf.getWindowBottomOffset() ) * SPS::getWinUnitY( chromaFormatIDC ); + + const Window& beforeScalingWindow = pps.getConformanceWindow(); + int refPicWidth = pps.getPicWidthInLumaSamples() - ( beforeScalingWindow.getWindowLeftOffset() + beforeScalingWindow.getWindowRightOffset() ) * SPS::getWinUnitX( chromaFormatIDC ); + int refPicHeight = pps.getPicHeightInLumaSamples() - ( beforeScalingWindow.getWindowTopOffset() + beforeScalingWindow.getWindowBottomOffset() ) * SPS::getWinUnitY( chromaFormatIDC ); + + int xScale = ( ( refPicWidth << SCALE_RATIO_BITS ) + ( curPicWidth >> 1 ) ) / curPicWidth; + int yScale = ( ( refPicHeight << SCALE_RATIO_BITS ) + ( curPicHeight >> 1 ) ) / curPicHeight; + + Picture::rescalePicture( std::pair<int, int>( xScale, yScale ), pic, pps.getConformanceWindow(), upscaledPic, conf, chromaFormatIDC, sps.getBitDepths(), false, false, sps.getHorCollocatedChromaFlag(), sps.getVerCollocatedChromaFlag() ); +#else Picture::rescalePicture( pic, pps.getConformanceWindow(), upscaledPic, conf, chromaFormatIDC, sps.getBitDepths(), false ); +#endif ret = write( sps.getMaxPicWidthInLumaSamples(), sps.getMaxPicHeightInLumaSamples(), upscaledPic, ipCSC, @@ -1241,6 +1295,7 @@ bool VideoIOYuv::writeUpscaledPicture( const SPS& sps, const PPS& pps, const CPe conf.getWindowTopOffset() * SPS::getWinUnitY( chromaFormatIDC ), conf.getWindowBottomOffset() * SPS::getWinUnitY( chromaFormatIDC ), NUM_CHROMA_FORMAT, bClipToRec709 ); +#endif } else {