From 11510cbc12d61bf585c1fb981ba6bb622a385d7e Mon Sep 17 00:00:00 2001 From: Han Gao <han.gao@huawei.com> Date: Sun, 26 Jan 2020 18:26:36 +0100 Subject: [PATCH] JVET-Q0806 Geo related adoptions (JVET-Q0059, JVET-Q0077, JVET-Q0123, JVET-Q0188, JVET-Q0242_GEO, JVET-Q0309, JVET-Q0365 and JVET-Q0370) --- cfg/encoder_lowdelay_vtm.cfg | 2 +- cfg/encoder_randomaccess_vtm.cfg | 2 +- doc/software-manual.tex | 12 +- source/App/EncoderApp/EncApp.cpp | 16 + source/App/EncoderApp/EncAppCfg.cpp | 42 +++ source/App/EncoderApp/EncAppCfg.h | 16 + source/Lib/CommonLib/Buffer.cpp | 32 ++ source/Lib/CommonLib/Buffer.h | 19 + source/Lib/CommonLib/CodingStatistics.h | 10 + source/Lib/CommonLib/CommonDef.h | 18 + source/Lib/CommonLib/ContextModelling.cpp | 8 + source/Lib/CommonLib/InterPrediction.cpp | 89 +++++ source/Lib/CommonLib/InterPrediction.h | 11 + source/Lib/CommonLib/InterpolationFilter.cpp | 64 ++++ source/Lib/CommonLib/InterpolationFilter.h | 9 + source/Lib/CommonLib/RdCost.cpp | 78 ++++ source/Lib/CommonLib/RdCost.h | 29 +- source/Lib/CommonLib/Rom.cpp | 106 ++++++ source/Lib/CommonLib/Rom.h | 13 + source/Lib/CommonLib/Slice.cpp | 16 + source/Lib/CommonLib/Slice.h | 40 ++ source/Lib/CommonLib/TypeDef.h | 10 + source/Lib/CommonLib/Unit.cpp | 28 ++ source/Lib/CommonLib/Unit.h | 10 + source/Lib/CommonLib/UnitTools.cpp | 166 ++++++++ source/Lib/CommonLib/UnitTools.h | 5 + .../Lib/CommonLib/dtrace_blockstatistics.cpp | 14 + source/Lib/CommonLib/dtrace_blockstatistics.h | 12 + .../CommonLib/x86/InterpolationFilterX86.h | 228 +++++++++++ source/Lib/CommonLib/x86/RdCostX86.h | 95 +++++ source/Lib/DecoderLib/CABACReader.cpp | 70 ++++ source/Lib/DecoderLib/DecCu.cpp | 31 ++ source/Lib/DecoderLib/DecCu.h | 4 + source/Lib/DecoderLib/VLCReader.cpp | 37 ++ source/Lib/EncoderLib/CABACWriter.cpp | 49 +++ source/Lib/EncoderLib/EncCfg.h | 36 ++ source/Lib/EncoderLib/EncCu.cpp | 354 ++++++++++++++++++ source/Lib/EncoderLib/EncCu.h | 100 +++++ source/Lib/EncoderLib/EncLib.cpp | 16 + source/Lib/EncoderLib/EncModeCtrl.cpp | 28 ++ source/Lib/EncoderLib/EncModeCtrl.h | 8 + source/Lib/EncoderLib/VLCWriter.cpp | 29 ++ 42 files changed, 1956 insertions(+), 6 deletions(-) diff --git a/cfg/encoder_lowdelay_vtm.cfg b/cfg/encoder_lowdelay_vtm.cfg index 2b449a99e..40e344573 100644 --- a/cfg/encoder_lowdelay_vtm.cfg +++ b/cfg/encoder_lowdelay_vtm.cfg @@ -116,7 +116,7 @@ ALF : 1 BCW : 1 BcwFast : 1 CIIP : 1 -Triangle : 1 +Geo : 1 IBC : 0 # turned off in CTC AllowDisFracMMVD : 1 AffineAmvr : 0 diff --git a/cfg/encoder_randomaccess_vtm.cfg b/cfg/encoder_randomaccess_vtm.cfg index 47f57f957..87ea48f86 100644 --- a/cfg/encoder_randomaccess_vtm.cfg +++ b/cfg/encoder_randomaccess_vtm.cfg @@ -129,7 +129,7 @@ BCW : 1 BcwFast : 1 BIO : 1 CIIP : 1 -Triangle : 1 +Geo : 1 IBC : 0 # turned off in CTC AllowDisFracMMVD : 1 AffineAmvr : 1 diff --git a/doc/software-manual.tex b/doc/software-manual.tex index 582dcbe4f..3f6802993 100644 --- a/doc/software-manual.tex +++ b/doc/software-manual.tex @@ -1283,10 +1283,10 @@ $} Specifies the maximum number of merge candidates to use. \\ -\Option{MaxNumTriangleCand} & +\Option{MaxNumGeoCand} & %\ShortOption{\None} & \Default{5} & -Specifies the maximum number of triangle merge candidates to use. +Specifies the maximum number of geometric partitioning mode candidates to use. \\ \Option{MaxNumIBCMergeCand} & @@ -2158,7 +2158,7 @@ Enables signaling the below parameters either in PPS or for each slice according collocated_from_l0_flag & s & s & p & s \\ six_minus_max_num_merge_cand & s & p & p & p \\ five_minus_max_num_subblock_merge_cand & s & p & p & p \\ - max_num_merge_cand_minus_max_num_triangle_cand & s & p & p & s \\ + max_num_merge_cand_minus_max_num_geo_cand & s & p & p & s \\ \end{tabular} \\ @@ -2239,6 +2239,12 @@ Value shall be in the range 1..8. Enables or disables symmetric MVD mode. \\ +\Option{Geo} & +%\ShortOption{\None} & +\Default{false} & +Enables or disables geometric partitioning mode. +\\ + \Option{PLT} & %\ShortOption{\None} & \Default{false} & diff --git a/source/App/EncoderApp/EncApp.cpp b/source/App/EncoderApp/EncApp.cpp index 77f765178..9b9219401 100644 --- a/source/App/EncoderApp/EncApp.cpp +++ b/source/App/EncoderApp/EncApp.cpp @@ -226,7 +226,11 @@ void EncApp::xInitLibCfg() m_cEncLib.setNoIbcConstraintFlag ( m_IBCMode ? false : true ); m_cEncLib.setNoCiipConstraintFlag ( !m_ciip ); m_cEncLib.setNoFPelMmvdConstraintFlag ( !(m_MMVD && m_allowDisFracMMVD) ); +#if !JVET_Q0806 m_cEncLib.setNoTriangleConstraintFlag ( !m_Triangle ); +#else + m_cEncLib.setNoGeoConstraintFlag ( !m_Geo ); +#endif m_cEncLib.setNoLadfConstraintFlag ( !m_LadfEnabed ); m_cEncLib.setNoTransformSkipConstraintFlag ( !m_useTransformSkip ); m_cEncLib.setNoBDPCMConstraintFlag ( m_useBDPCM == 0 ); @@ -416,7 +420,11 @@ void EncApp::xInitLibCfg() } #endif m_cEncLib.setUseCiip ( m_ciip ); +#if !JVET_Q0806 m_cEncLib.setUseTriangle ( m_Triangle ); +#else + m_cEncLib.setUseGeo ( m_Geo ); +#endif m_cEncLib.setUseHashME ( m_HashME ); m_cEncLib.setAllowDisFracMMVD ( m_allowDisFracMMVD ); @@ -510,7 +518,11 @@ void EncApp::xInitLibCfg() m_cEncLib.setMaxNumMergeCand ( m_maxNumMergeCand ); m_cEncLib.setMaxNumAffineMergeCand ( m_maxNumAffineMergeCand ); +#if !JVET_Q0806 m_cEncLib.setMaxNumTriangleCand ( m_maxNumTriangleCand ); +#else + m_cEncLib.setMaxNumGeoCand ( m_maxNumGeoCand ); +#endif m_cEncLib.setMaxNumIBCMergeCand ( m_maxNumIBCMergeCand ); //====== Weighted Prediction ======== @@ -694,7 +706,11 @@ void EncApp::xInitLibCfg() m_cEncLib.setPPSMvdL1ZeroIdc ( m_PPSMvdL1ZeroIdc ); m_cEncLib.setPPSCollocatedFromL0Idc ( m_PPSCollocatedFromL0Idc ); m_cEncLib.setPPSSixMinusMaxNumMergeCandPlus1 ( m_PPSSixMinusMaxNumMergeCandPlus1 ); +#if !JVET_Q0806 m_cEncLib.setPPSMaxNumMergeCandMinusMaxNumTriangleCandPlus1 ( m_PPSMaxNumMergeCandMinusMaxNumTriangleCandPlus1 ); +#else + m_cEncLib.setPPSMaxNumMergeCandMinusMaxNumGeoCandPlus1 ( m_PPSMaxNumMergeCandMinusMaxNumGeoCandPlus1 ); +#endif m_cEncLib.setUseScalingListId ( m_useScalingListId ); m_cEncLib.setScalingListFileName ( m_scalingListFileName ); m_cEncLib.setDisableScalingMatrixForLfnstBlks ( m_disableScalingMatrixForLfnstBlks); diff --git a/source/App/EncoderApp/EncAppCfg.cpp b/source/App/EncoderApp/EncAppCfg.cpp index cdad7cff4..2feec71c6 100644 --- a/source/App/EncoderApp/EncAppCfg.cpp +++ b/source/App/EncoderApp/EncAppCfg.cpp @@ -101,7 +101,11 @@ EncAppCfg::EncAppCfg() , m_noIbcConstraintFlag(false) , m_bNoCiipConstraintFlag(false) , m_noFPelMmvdConstraintFlag(false) +#if !JVET_Q0806 , m_bNoTriangleConstraintFlag(false) +#else +, m_bNoGeoConstraintFlag(false) +#endif , m_bNoLadfConstraintFlag(false) , m_noTransformSkipConstraintFlag(false) , m_noBDPCMConstraintFlag(false) @@ -919,7 +923,11 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] ) ("LadfIntervalLowerBound", cfg_LadfIntervalLowerBound, cfg_LadfIntervalLowerBound, "LADF lower bound for 2nd lowest interval") #endif ("CIIP", m_ciip, false, "Enable CIIP mode") +#if !JVET_Q0806 ("Triangle", m_Triangle, false, "Enable triangular shape motion vector prediction (0:off, 1:on)") +#else + ("Geo", m_Geo, false, "Enable geometric partitioning mode (0:off, 1:on)") +#endif ("HashME", m_HashME, false, "Enable hash motion estimation (0:off, 1:on)") ("AllowDisFracMMVD", m_allowDisFracMMVD, false, "Disable fractional MVD in MMVD mode adaptively") @@ -1138,7 +1146,11 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] ) ("SignHideFlag,-SBH", m_signDataHidingEnabledFlag, false, "Enable sign hiding" ) ("MaxNumMergeCand", m_maxNumMergeCand, 5u, "Maximum number of merge candidates") ("MaxNumAffineMergeCand", m_maxNumAffineMergeCand, 5u, "Maximum number of affine merge candidates") +#if !JVET_Q0806 ("MaxNumTriangleCand", m_maxNumTriangleCand, 5u, "Maximum number of triangle candidates") +#else + ("MaxNumGeoCand", m_maxNumGeoCand, 5u, "Maximum number of geometric partitioning mode candidates") +#endif ("MaxNumIBCMergeCand", m_maxNumIBCMergeCand, 6u, "Maximum number of IBC merge candidates") /* Misc. */ ("SEIDecodedPictureHash,-dph", tmpDecodedPictureHashSEIMappedType, 0, "Control generation of decode picture hash SEI messages\n" @@ -2508,9 +2520,15 @@ bool EncAppCfg::xCheckParameter() xConfirmPara( m_log2MaxTbSize < 5, "Log2MaxTbSize must be 5 or greater." ); xConfirmPara( m_maxNumMergeCand < 1, "MaxNumMergeCand must be 1 or greater."); xConfirmPara( m_maxNumMergeCand > MRG_MAX_NUM_CANDS, "MaxNumMergeCand must be no more than MRG_MAX_NUM_CANDS." ); +#if !JVET_Q0806 xConfirmPara( m_maxNumTriangleCand > TRIANGLE_MAX_NUM_UNI_CANDS, "MaxNumTriangleCand must be no more than TRIANGLE_MAX_NUM_UNI_CANDS." ); xConfirmPara( m_maxNumTriangleCand > m_maxNumMergeCand, "MaxNumTriangleCand must be no more than MaxNumMergeCand." ); xConfirmPara( 0 < m_maxNumTriangleCand && m_maxNumTriangleCand < 2, "MaxNumTriangleCand must be no less than 2 unless MaxNumTriangleCand is 0." ); +#else + xConfirmPara( m_maxNumGeoCand > GEO_MAX_NUM_UNI_CANDS, "MaxNumGeoCand must be no more than GEO_MAX_NUM_UNI_CANDS." ); + xConfirmPara( m_maxNumGeoCand > m_maxNumMergeCand, "MaxNumGeoCand must be no more than MaxNumMergeCand." ); + xConfirmPara( 0 < m_maxNumGeoCand && m_maxNumGeoCand < 2, "MaxNumGeoCand must be no less than 2 unless MaxNumGeoCand is 0." ); +#endif xConfirmPara( m_maxNumIBCMergeCand < 1, "MaxNumIBCMergeCand must be 1 or greater." ); xConfirmPara( m_maxNumIBCMergeCand > IBC_MRG_MAX_NUM_CANDS, "MaxNumIBCMergeCand must be no more than IBC_MRG_MAX_NUM_CANDS." ); xConfirmPara( m_maxNumAffineMergeCand < 1, "MaxNumAffineMergeCand must be 1 or greater." ); @@ -3252,7 +3270,11 @@ bool EncAppCfg::xCheckParameter() m_PPSMvdL1ZeroIdc = 0; m_PPSCollocatedFromL0Idc = 0; m_PPSSixMinusMaxNumMergeCandPlus1 = 0; +#if !JVET_Q0806 m_PPSMaxNumMergeCandMinusMaxNumTriangleCandPlus1 = 0; +#else + m_PPSMaxNumMergeCandMinusMaxNumGeoCandPlus1 = 0; +#endif break; case 1: // RA setting m_constantSliceHeaderParamsEnabledFlag = 1; @@ -3262,7 +3284,11 @@ bool EncAppCfg::xCheckParameter() m_PPSMvdL1ZeroIdc = 0; m_PPSCollocatedFromL0Idc = 0; m_PPSSixMinusMaxNumMergeCandPlus1 = 6 - m_maxNumMergeCand + 1; +#if !JVET_Q0806 m_PPSMaxNumMergeCandMinusMaxNumTriangleCandPlus1 = m_maxNumMergeCand - m_maxNumTriangleCand + 1; +#else + m_PPSMaxNumMergeCandMinusMaxNumGeoCandPlus1 = m_maxNumMergeCand - m_maxNumGeoCand + 1; +#endif break; case 2: // LDB setting m_constantSliceHeaderParamsEnabledFlag = 1; @@ -3272,7 +3298,11 @@ bool EncAppCfg::xCheckParameter() m_PPSMvdL1ZeroIdc = 2; m_PPSCollocatedFromL0Idc = 1; m_PPSSixMinusMaxNumMergeCandPlus1 = 6 - m_maxNumMergeCand + 1; +#if !JVET_Q0806 m_PPSMaxNumMergeCandMinusMaxNumTriangleCandPlus1 = m_maxNumMergeCand - m_maxNumTriangleCand + 1; +#else + m_PPSMaxNumMergeCandMinusMaxNumGeoCandPlus1 = m_maxNumMergeCand - m_maxNumGeoCand + 1; +#endif break; case 3: // LDP setting m_constantSliceHeaderParamsEnabledFlag = 1; @@ -3282,7 +3312,11 @@ bool EncAppCfg::xCheckParameter() m_PPSMvdL1ZeroIdc = 0; m_PPSCollocatedFromL0Idc = 0; m_PPSSixMinusMaxNumMergeCandPlus1 = 6 - m_maxNumMergeCand + 1; +#if !JVET_Q0806 m_PPSMaxNumMergeCandMinusMaxNumTriangleCandPlus1 = 0; +#else + m_PPSMaxNumMergeCandMinusMaxNumGeoCandPlus1 = 0; +#endif break; default: THROW("Invalid value for PPSorSliceMode"); @@ -3572,7 +3606,11 @@ void EncAppCfg::xPrintParameter() msg( DETAILS, "Max Num Merge Candidates : %d\n", m_maxNumMergeCand ); msg( DETAILS, "Max Num Affine Merge Candidates : %d\n", m_maxNumAffineMergeCand ); +#if !JVET_Q0806 msg( DETAILS, "Max Num Triangle Merge Candidates : %d\n", m_maxNumTriangleCand ); +#else + msg( DETAILS, "Max Num Geo Merge Candidates : %d\n", m_maxNumGeoCand ); +#endif msg( DETAILS, "Max Num IBC Merge Candidates : %d\n", m_maxNumIBCMergeCand ); msg( DETAILS, "\n"); @@ -3643,7 +3681,11 @@ void EncAppCfg::xPrintParameter() msg( VERBOSE, "LADF:%d ", m_LadfEnabed ); #endif msg(VERBOSE, "CIIP:%d ", m_ciip); +#if !JVET_Q0806 msg( VERBOSE, "Triangle:%d ", m_Triangle ); +#else + msg( VERBOSE, "Geo:%d ", m_Geo ); +#endif m_allowDisFracMMVD = m_MMVD ? m_allowDisFracMMVD : false; if ( m_MMVD ) msg(VERBOSE, "AllowDisFracMMVD:%d ", m_allowDisFracMMVD); diff --git a/source/App/EncoderApp/EncAppCfg.h b/source/App/EncoderApp/EncAppCfg.h index 4ce37e402..0ccf3f246 100644 --- a/source/App/EncoderApp/EncAppCfg.h +++ b/source/App/EncoderApp/EncAppCfg.h @@ -151,7 +151,11 @@ protected: bool m_noIbcConstraintFlag; bool m_bNoCiipConstraintFlag; bool m_noFPelMmvdConstraintFlag; +#if !JVET_Q0806 bool m_bNoTriangleConstraintFlag; +#else + bool m_bNoGeoConstraintFlag; +#endif bool m_bNoLadfConstraintFlag; bool m_noTransformSkipConstraintFlag; bool m_noBDPCMConstraintFlag; @@ -305,7 +309,11 @@ protected: #endif bool m_ciip; +#if !JVET_Q0806 bool m_Triangle; +#else + bool m_Geo; +#endif bool m_HashME; bool m_allowDisFracMMVD; bool m_AffineAmvr; @@ -583,7 +591,11 @@ protected: uint32_t m_maxNumMergeCand; ///< Max number of merge candidates uint32_t m_maxNumAffineMergeCand; ///< Max number of affine merge candidates +#if !JVET_Q0806 uint32_t m_maxNumTriangleCand; +#else + uint32_t m_maxNumGeoCand; +#endif uint32_t m_maxNumIBCMergeCand; ///< Max number of IBC merge candidates bool m_sliceLevelRpl; ///< code reference picture lists in slice headers rather than picture header @@ -599,7 +611,11 @@ protected: int m_PPSMvdL1ZeroIdc; int m_PPSCollocatedFromL0Idc; uint32_t m_PPSSixMinusMaxNumMergeCandPlus1; +#if !JVET_Q0806 uint32_t m_PPSMaxNumMergeCandMinusMaxNumTriangleCandPlus1; +#else + uint32_t m_PPSMaxNumMergeCandMinusMaxNumGeoCandPlus1; +#endif bool m_depQuantEnabledFlag; bool m_signDataHidingEnabledFlag; bool m_RCEnableRateControl; ///< enable rate control or not diff --git a/source/Lib/CommonLib/Buffer.cpp b/source/Lib/CommonLib/Buffer.cpp index e1f967f14..c3d141071 100644 --- a/source/Lib/CommonLib/Buffer.cpp +++ b/source/Lib/CommonLib/Buffer.cpp @@ -553,6 +553,38 @@ void AreaBuf<Pel>::copyClip( const AreaBuf<const Pel> &src, const ClpRng& clpRng } } +#if JVET_Q0806 +template<> +void AreaBuf<Pel>::roundToOutputBitdepth( const AreaBuf<const Pel> &src, const ClpRng& clpRng ) +{ + const Pel* srcp = src.buf; + Pel* dest = buf; + const unsigned srcStride = src.stride; + const unsigned destStride = stride; + + const int32_t clipbd = clpRng.bd; + const int32_t shiftDefault = std::max<int>(2, (IF_INTERNAL_PREC - clipbd)); + const int32_t offsetDefault = (1<<(shiftDefault-1)) + IF_INTERNAL_OFFS; + + if( width == 1 ) + { + THROW( "Blocks of width = 1 not supported" ); + } + else + { +#define RND_OP( ADDR ) dest[ADDR] = ClipPel( rightShift( srcp[ADDR] + offsetDefault, shiftDefault), clpRng ) +#define RND_INC \ + srcp += srcStride; \ + dest += destStride; \ + + SIZE_AWARE_PER_EL_OP( RND_OP, RND_INC ); + +#undef RND_OP +#undef RND_INC + } +} +#endif + template<> void AreaBuf<Pel>::reconstruct( const AreaBuf<const Pel> &pred, const AreaBuf<const Pel> &resi, const ClpRng& clpRng ) diff --git a/source/Lib/CommonLib/Buffer.h b/source/Lib/CommonLib/Buffer.h index 9b461389d..3455dcea5 100644 --- a/source/Lib/CommonLib/Buffer.h +++ b/source/Lib/CommonLib/Buffer.h @@ -110,6 +110,9 @@ struct AreaBuf : public Size void memset ( const int val ); void copyFrom ( const AreaBuf<const T> &other ); +#if JVET_Q0806 + void roundToOutputBitdepth(const AreaBuf<const T> &src, const ClpRng& clpRng); +#endif void reconstruct ( const AreaBuf<const T> &pred, const AreaBuf<const T> &resi, const ClpRng& clpRng); void copyClip ( const AreaBuf<const T> &src, const ClpRng& clpRng); @@ -764,6 +767,9 @@ struct UnitBuf void fill ( const T &val ); void copyFrom ( const UnitBuf<const T> &other, const bool lumaOnly = false, const bool chromaOnly = false ); +#if JVET_Q0806 + void roundToOutputBitdepth(const UnitBuf<const T> &src, const ClpRngs& clpRngs); +#endif void reconstruct ( const UnitBuf<const T> &pred, const UnitBuf<const T> &resi, const ClpRngs& clpRngs ); void copyClip ( const UnitBuf<const T> &src, const ClpRngs& clpRngs, const bool lumaOnly = false, const bool chromaOnly = false ); void subtract ( const UnitBuf<const T> &other ); @@ -839,6 +845,19 @@ void UnitBuf<T>::copyClip(const UnitBuf<const T> &src, const ClpRngs &clpRngs, c } +#if JVET_Q0806 +template<typename T> +void UnitBuf<T>::roundToOutputBitdepth(const UnitBuf<const T> &src, const ClpRngs& clpRngs) +{ + CHECK(chromaFormat != src.chromaFormat, "Incompatible formats"); + + for (unsigned i = 0; i < bufs.size(); i++) + { + bufs[i].roundToOutputBitdepth(src.bufs[i], clpRngs.comp[i]); + } +} +#endif + template<typename T> void UnitBuf<T>::reconstruct(const UnitBuf<const T> &pred, const UnitBuf<const T> &resi, const ClpRngs& clpRngs) { diff --git a/source/Lib/CommonLib/CodingStatistics.h b/source/Lib/CommonLib/CodingStatistics.h index 375ed6ec2..08de32ce3 100644 --- a/source/Lib/CommonLib/CodingStatistics.h +++ b/source/Lib/CommonLib/CodingStatistics.h @@ -112,8 +112,13 @@ enum CodingStatisticsType STATS__CABAC_BITS__BCW_IDX, STATS__CABAC_BITS__SBT_MODE, STATS__CABAC_BITS__MH_INTRA_FLAG, +#if !JVET_Q0806 STATS__CABAC_BITS__TRIANGLE_FLAG, STATS__CABAC_BITS__TRIANGLE_INDEX, +#else + STATS__CABAC_BITS__GEO_FLAG, + STATS__CABAC_BITS__GEO_INDEX, +#endif STATS__CABAC_BITS__MULTI_REF_LINE, STATS__CABAC_BITS__SYMMVD_FLAG, STATS__CABAC_BITS__BDPCM_MODE, @@ -204,8 +209,13 @@ static inline const char* getName(CodingStatisticsType name) "CABAC_BITS__BCW_IDX", "CABAC_BITS__SBT_MODE", "CABAC_BITS__MH_INTRA_FLAG", +#if !JVET_Q0806 "CABAC_BITS__TRIANGLE_FLAG", "CABAC_BITS__TRIANGLE_INDEX", +#else + "CABAC_BITS__GEO_FLAG", + "CABAC_BITS__GEO_INDEX", +#endif "CABAC_BITS__MULTI_REF_LINE", "CABAC_BITS__SYMMVD_FLAG", "CABAC_BITS__BDPCM_MODE", diff --git a/source/Lib/CommonLib/CommonDef.h b/source/Lib/CommonLib/CommonDef.h index f24085c10..d186c637f 100644 --- a/source/Lib/CommonLib/CommonDef.h +++ b/source/Lib/CommonLib/CommonDef.h @@ -421,11 +421,29 @@ static const int MAX_LADF_INTERVALS = 5; /// max n static const int NTAPS_BILINEAR = 2; ///< Number of taps for bilinear filter static const int ATMVP_SUB_BLOCK_SIZE = 3; ///< sub-block size for ATMVP +#if !JVET_Q0806 static const int TRIANGLE_MAX_NUM_UNI_CANDS = 6; static const int TRIANGLE_MAX_NUM_CANDS_MEM = 7; static const int TRIANGLE_MAX_NUM_CANDS = TRIANGLE_MAX_NUM_UNI_CANDS * (TRIANGLE_MAX_NUM_UNI_CANDS - 1) * 2; static const int TRIANGLE_MAX_NUM_SATD_CANDS = 3; static const int TRIANGLE_MIN_SIZE = 8 * 8; +#else +static const int GEO_MAX_NUM_UNI_CANDS = 6; +static const int GEO_MAX_NUM_CANDS = GEO_MAX_NUM_UNI_CANDS * (GEO_MAX_NUM_UNI_CANDS - 1); +static const int GEO_MIN_CU_LOG2 = 3; +static const int GEO_MAX_CU_LOG2 = 6; +static const int GEO_MIN_CU_SIZE = 1 << GEO_MIN_CU_LOG2; +static const int GEO_MAX_CU_SIZE = 1 << GEO_MAX_CU_LOG2; +static const int GEO_NUM_CU_SIZE = ( GEO_MAX_CU_LOG2 - GEO_MIN_CU_LOG2 ) + 1; +static const int GEO_NUM_PARTITION_MODE = 64; +static const int GEO_NUM_ANGLES = 32; +static const int GEO_NUM_DISTANCES = 4; +static const int GEO_NUM_PRESTORED_MASK = 6; +static const int GEO_WEIGHT_MASK_SIZE = 3 * (GEO_MAX_CU_SIZE >> 3) * 2 + GEO_MAX_CU_SIZE; +static const int GEO_MV_MASK_SIZE = GEO_WEIGHT_MASK_SIZE >> 2; +static const int GEO_MAX_TRY_WEIGHTED_SAD = 60; +static const int GEO_MAX_TRY_WEIGHTED_SATD = 8; +#endif static const int SBT_MAX_SIZE = 64; ///< maximum CU size for using SBT static const int SBT_NUM_SL = 10; ///< maximum number of historical PU decision saved for a CU diff --git a/source/Lib/CommonLib/ContextModelling.cpp b/source/Lib/CommonLib/ContextModelling.cpp index a8cd73368..6913c4d54 100644 --- a/source/Lib/CommonLib/ContextModelling.cpp +++ b/source/Lib/CommonLib/ContextModelling.cpp @@ -320,11 +320,19 @@ unsigned DeriveCtx::CtxIBCFlag(const CodingUnit& cu) void MergeCtx::setMergeInfo( PredictionUnit& pu, int candIdx ) { CHECK( candIdx >= numValidMergeCand, "Merge candidate does not exist" ); +#if !JVET_Q0806 pu.regularMergeFlag = !(pu.ciipFlag || pu.cu->triangle); +#else + pu.regularMergeFlag = !(pu.ciipFlag || pu.cu->geoFlag); +#endif pu.mergeFlag = true; pu.mmvdMergeFlag = false; pu.interDir = interDirNeighbours[candIdx]; +#if !JVET_Q0806 pu.cu->imv = (!pu.cu->triangle && useAltHpelIf[candIdx]) ? IMV_HPEL : 0; +#else + pu.cu->imv = (!pu.cu->geoFlag && useAltHpelIf[candIdx]) ? IMV_HPEL : 0; +#endif pu.mergeIdx = candIdx; pu.mergeType = mrgTypeNeighbours[candIdx]; pu.mv [REF_PIC_LIST_0] = mvFieldNeighbours[(candIdx << 1) + 0].mv; diff --git a/source/Lib/CommonLib/InterPrediction.cpp b/source/Lib/CommonLib/InterPrediction.cpp index d749d78e9..ab4a35f8d 100644 --- a/source/Lib/CommonLib/InterPrediction.cpp +++ b/source/Lib/CommonLib/InterPrediction.cpp @@ -126,7 +126,12 @@ void InterPrediction::destroy() } } +#if !JVET_Q0806 m_triangleBuf.destroy(); +#else + m_geoPartBuf[0].destroy(); + m_geoPartBuf[1].destroy(); +#endif m_colorTransResiBuf[0].destroy(); m_colorTransResiBuf[1].destroy(); m_colorTransResiBuf[2].destroy(); @@ -192,7 +197,12 @@ void InterPrediction::init( RdCost* pcRdCost, ChromaFormat chromaFormatIDC, cons } } +#if !JVET_Q0806 m_triangleBuf.create(UnitArea(chromaFormatIDC, Area(0, 0, MAX_CU_SIZE, MAX_CU_SIZE))); +#else + m_geoPartBuf[0].create(UnitArea(chromaFormatIDC, Area(0, 0, MAX_CU_SIZE, MAX_CU_SIZE))); + m_geoPartBuf[1].create(UnitArea(chromaFormatIDC, Area(0, 0, MAX_CU_SIZE, MAX_CU_SIZE))); +#endif m_colorTransResiBuf[0].create(UnitArea(chromaFormatIDC, Area(0, 0, MAX_CU_SIZE, MAX_CU_SIZE))); m_colorTransResiBuf[1].create(UnitArea(chromaFormatIDC, Area(0, 0, MAX_CU_SIZE, MAX_CU_SIZE))); m_colorTransResiBuf[2].create(UnitArea(chromaFormatIDC, Area(0, 0, MAX_CU_SIZE, MAX_CU_SIZE))); @@ -629,7 +639,11 @@ void InterPrediction::xPredInterBi(PredictionUnit &pu, PelUnitBuf &pcYuvPred, co } else { +#if !JVET_Q0806 xPredInterUni( pu, eRefPicList, pcMbBuf, pu.cu->triangle +#else + xPredInterUni(pu, eRefPicList, pcMbBuf, pu.cu->geoFlag +#endif , bioApplied , luma, chroma ); @@ -644,13 +658,21 @@ void InterPrediction::xPredInterBi(PredictionUnit &pu, PelUnitBuf &pcYuvPred, co CPelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvPred[1][0], pcYuvPred.Y()), PelBuf(m_acYuvPred[1][1], pcYuvPred.Cb()), PelBuf(m_acYuvPred[1][2], pcYuvPred.Cr())) ); const bool lumaOnly = luma && !chroma; const bool chromaOnly = !luma && chroma; +#if !JVET_Q0806 if( !pu.cu->triangle && (!dmvrApplied) && (!bioApplied) && pps.getWPBiPred() && slice.getSliceType() == B_SLICE && pu.cu->BcwIdx==BCW_DEFAULT) +#else + if( !pu.cu->geoFlag && (!dmvrApplied) && (!bioApplied) && pps.getWPBiPred() && slice.getSliceType() == B_SLICE && pu.cu->BcwIdx == BCW_DEFAULT) +#endif { xWeightedPredictionBi( pu, srcPred0, srcPred1, pcYuvPred, m_maxCompIDToPred, lumaOnly, chromaOnly ); if (yuvPredTmp) yuvPredTmp->copyFrom(pcYuvPred); } +#if !JVET_Q0806 else if( !pu.cu->triangle && pps.getUseWP() && slice.getSliceType() == P_SLICE ) +#else + else if( !pu.cu->geoFlag && pps.getUseWP() && slice.getSliceType() == P_SLICE ) +#endif { xWeightedPredictionUni( pu, srcPred0, REF_PIC_LIST_0, pcYuvPred, -1, m_maxCompIDToPred, lumaOnly, chromaOnly ); if (yuvPredTmp) @@ -1453,22 +1475,38 @@ void InterPrediction::xWeightedAverage(const PredictionUnit& pu, const CPelUnitB } else if( iRefIdx0 >= 0 && iRefIdx1 < 0 ) { +#if !JVET_Q0806 if( pu.cu->triangle ) { pcYuvDst.copyFrom( pcYuvSrc0 ); } else +#else + if( pu.cu->geoFlag ) + { + pcYuvDst.copyFrom( pcYuvSrc0 ); + } + else +#endif pcYuvDst.copyClip( pcYuvSrc0, clpRngs, lumaOnly, chromaOnly ); if (yuvDstTmp) yuvDstTmp->copyFrom( pcYuvDst, lumaOnly, chromaOnly ); } else if( iRefIdx0 < 0 && iRefIdx1 >= 0 ) { +#if !JVET_Q0806 if( pu.cu->triangle ) { pcYuvDst.copyFrom( pcYuvSrc1 ); } else +#else + if( pu.cu->geoFlag ) + { + pcYuvDst.copyFrom( pcYuvSrc1 ); + } + else +#endif pcYuvDst.copyClip( pcYuvSrc1, clpRngs, lumaOnly, chromaOnly ); if (yuvDstTmp) yuvDstTmp->copyFrom(pcYuvDst, lumaOnly, chromaOnly); @@ -1655,6 +1693,7 @@ int InterPrediction::rightShiftMSB(int numer, int denom) return numer >> floorLog2(denom); } +#if !JVET_Q0806 void InterPrediction::motionCompensation4Triangle( CodingUnit &cu, MergeCtx &triangleMrgCtx, const bool splitDir, const uint8_t candIdx0, const uint8_t candIdx1 ) { for( auto &pu : CU::traversePUs( cu ) ) @@ -1706,7 +1745,57 @@ void InterPrediction::weightedTriangleBlk( PredictionUnit &pu, const bool splitD m_if.weightedTriangleBlk( pu, pu.chromaSize().width, pu.chromaSize().height, COMPONENT_Cr, splitDir, predDst, predSrc0, predSrc1 ); } } +#else +void InterPrediction::motionCompensationGeo( CodingUnit &cu, MergeCtx &geoMrgCtx ) +{ + const uint8_t splitDir = cu.firstPU->geoSplitDir; + const uint8_t candIdx0 = cu.firstPU->geoMergeIdx0; + const uint8_t candIdx1 = cu.firstPU->geoMergeIdx1; + for( auto &pu : CU::traversePUs( cu ) ) + { + const UnitArea localUnitArea( cu.cs->area.chromaFormat, Area( 0, 0, pu.lwidth(), pu.lheight() ) ); + PelUnitBuf tmpGeoBuf0 = m_geoPartBuf[0].getBuf( localUnitArea ); + PelUnitBuf tmpGeoBuf1 = m_geoPartBuf[1].getBuf( localUnitArea ); + PelUnitBuf predBuf = cu.cs->getPredBuf( pu ); + + geoMrgCtx.setMergeInfo( pu, candIdx0 ); + PU::spanMotionInfo( pu ); + motionCompensation(pu, tmpGeoBuf0, REF_PIC_LIST_X, true, isChromaEnabled(pu.chromaFormat)); + if( g_mctsDecCheckEnabled && !MCTSHelper::checkMvBufferForMCTSConstraint( pu, true ) ) + { + printf( "DECODER_GEO_PU: pu motion vector across tile boundaries (%d,%d,%d,%d)\n", pu.lx(), pu.ly(), pu.lwidth(), pu.lheight() ); + } + + geoMrgCtx.setMergeInfo( pu, candIdx1 ); + PU::spanMotionInfo( pu ); + motionCompensation(pu, tmpGeoBuf1, REF_PIC_LIST_X, true, isChromaEnabled(pu.chromaFormat)); + if( g_mctsDecCheckEnabled && !MCTSHelper::checkMvBufferForMCTSConstraint( pu, true ) ) + { + printf( "DECODER_GEO_PU: pu motion vector across tile boundaries (%d,%d,%d,%d)\n", pu.lx(), pu.ly(), pu.lwidth(), pu.lheight() ); + } + weightedGeoBlk(pu, splitDir, isChromaEnabled(pu.chromaFormat)? MAX_NUM_CHANNEL_TYPE : CHANNEL_TYPE_LUMA, predBuf, tmpGeoBuf0, tmpGeoBuf1); + } +} +void InterPrediction::weightedGeoBlk( PredictionUnit &pu, const uint8_t splitDir, int32_t channel, PelUnitBuf& predDst, PelUnitBuf& predSrc0, PelUnitBuf& predSrc1) +{ + if( channel == CHANNEL_TYPE_LUMA ) + { + m_if.weightedGeoBlk( pu, pu.lumaSize().width, pu.lumaSize().height, COMPONENT_Y, splitDir, predDst, predSrc0, predSrc1 ); + } + else if( channel == CHANNEL_TYPE_CHROMA ) + { + m_if.weightedGeoBlk( pu, pu.chromaSize().width, pu.chromaSize().height, COMPONENT_Cb, splitDir, predDst, predSrc0, predSrc1 ); + m_if.weightedGeoBlk( pu, pu.chromaSize().width, pu.chromaSize().height, COMPONENT_Cr, splitDir, predDst, predSrc0, predSrc1 ); + } + else + { + m_if.weightedGeoBlk( pu, pu.lumaSize().width, pu.lumaSize().height, COMPONENT_Y, splitDir, predDst, predSrc0, predSrc1 ); + m_if.weightedGeoBlk( pu, pu.chromaSize().width, pu.chromaSize().height, COMPONENT_Cb, splitDir, predDst, predSrc0, predSrc1 ); + m_if.weightedGeoBlk( pu, pu.chromaSize().width, pu.chromaSize().height, COMPONENT_Cr, splitDir, predDst, predSrc0, predSrc1 ); + } +} +#endif void InterPrediction::xPrefetch(PredictionUnit& pu, PelUnitBuf &pcPad, RefPicList refId, bool forLuma) { diff --git a/source/Lib/CommonLib/InterPrediction.h b/source/Lib/CommonLib/InterPrediction.h index 1bc16ff8d..a7455d461 100644 --- a/source/Lib/CommonLib/InterPrediction.h +++ b/source/Lib/CommonLib/InterPrediction.h @@ -81,7 +81,11 @@ protected: RdCost* m_pcRdCost; int m_iRefListIdx; +#if !JVET_Q0806 PelStorage m_triangleBuf; +#else + PelStorage m_geoPartBuf[2]; +#endif Mv* m_storedMv; /*buffers for bilinear Filter data for DMVR refinement*/ Pel* m_cYuvPredTempDMVRL0; @@ -138,7 +142,9 @@ protected: void xCalcBlkGradient (int sx, int sy, int *arraysGx2, int *arraysGxGy, int *arraysGxdI, int *arraysGy2, int *arraysGydI, int &sGx2, int &sGy2, int &sGxGy, int &sGxdI, int &sGydI, int width, int height, int unitSize); void xWeightedAverage ( const PredictionUnit& pu, const CPelUnitBuf& pcYuvSrc0, const CPelUnitBuf& pcYuvSrc1, PelUnitBuf& pcYuvDst, const BitDepths& clipBitDepths, const ClpRngs& clpRngs, const bool& bioApplied, const bool lumaOnly = false, const bool chromaOnly = false, PelUnitBuf* yuvDstTmp = NULL ); void xPredAffineBlk ( const ComponentID& compID, const PredictionUnit& pu, const Picture* refPic, const Mv* _mv, PelUnitBuf& dstPic, const bool& bi, const ClpRng& clpRng, const bool genChromaMv = false, const std::pair<int, int> scalingRatio = SCALE_1X ); +#if !JVET_Q0806 void xWeightedTriangleBlk ( const PredictionUnit &pu, const uint32_t width, const uint32_t height, const ComponentID compIdx, const bool splitDir, PelUnitBuf& predDst, PelUnitBuf& predSrc0, PelUnitBuf& predSrc1 ); +#endif static bool xCheckIdenticalMotion( const PredictionUnit& pu ); @@ -171,8 +177,13 @@ public: , const bool luma = true, const bool chroma = true ); +#if !JVET_Q0806 void motionCompensation4Triangle( CodingUnit &cu, MergeCtx &triangleMrgCtx, const bool splitDir, const uint8_t candIdx0, const uint8_t candIdx1 ); void weightedTriangleBlk ( PredictionUnit &pu, const bool splitDir, int32_t channel, PelUnitBuf& predDst, PelUnitBuf& predSrc0, PelUnitBuf& predSrc1 ); +#else + void motionCompensationGeo(CodingUnit &cu, MergeCtx &GeoMrgCtx); + void weightedGeoBlk(PredictionUnit &pu, const uint8_t splitDir, int32_t channel, PelUnitBuf& predDst, PelUnitBuf& predSrc0, PelUnitBuf& predSrc1); +#endif void xPrefetch(PredictionUnit& pu, PelUnitBuf &pcPad, RefPicList refId, bool forLuma); void xPad(PredictionUnit& pu, PelUnitBuf &pcPad, RefPicList refId); void xFinalPaddedMCForDMVR(PredictionUnit& pu, PelUnitBuf &pcYuvSrc0, PelUnitBuf &pcYuvSrc1, PelUnitBuf &pcPad0, PelUnitBuf &pcPad1, const bool bioApplied diff --git a/source/Lib/CommonLib/InterpolationFilter.cpp b/source/Lib/CommonLib/InterpolationFilter.cpp index 77f46edca..5fb66c384 100644 --- a/source/Lib/CommonLib/InterpolationFilter.cpp +++ b/source/Lib/CommonLib/InterpolationFilter.cpp @@ -371,7 +371,11 @@ InterpolationFilter::InterpolationFilter() m_filterCopy[1][0] = filterCopy<true, false>; m_filterCopy[1][1] = filterCopy<true, true>; +#if !JVET_Q0806 m_weightedTriangleBlk = xWeightedTriangleBlk; +#else + m_weightedGeoBlk = xWeightedGeoBlk; +#endif } @@ -888,6 +892,7 @@ void InterpolationFilter::filterVer(const ComponentID compID, Pel const *src, in } } +#if !JVET_Q0806 void InterpolationFilter::xWeightedTriangleBlk( const PredictionUnit &pu, const uint32_t width, const uint32_t height, const ComponentID compIdx, const bool splitDir, PelUnitBuf& predDst, PelUnitBuf& predSrc0, PelUnitBuf& predSrc1 ) { Pel* dst = predDst .get(compIdx).buf; @@ -983,6 +988,65 @@ void InterpolationFilter::weightedTriangleBlk(const PredictionUnit &pu, const ui { m_weightedTriangleBlk(pu, width, height, compIdx, splitDir, predDst, predSrc0, predSrc1); } +#else +void InterpolationFilter::weightedGeoBlk(const PredictionUnit &pu, const uint32_t width, const uint32_t height, const ComponentID compIdx, const uint8_t splitDir, PelUnitBuf& predDst, PelUnitBuf& predSrc0, PelUnitBuf& predSrc1) +{ + m_weightedGeoBlk(pu, width, height, compIdx, splitDir, predDst, predSrc0, predSrc1); +} + +void InterpolationFilter::xWeightedGeoBlk(const PredictionUnit &pu, const uint32_t width, const uint32_t height, const ComponentID compIdx, const uint8_t splitDir, PelUnitBuf& predDst, PelUnitBuf& predSrc0, PelUnitBuf& predSrc1) +{ + Pel* dst = predDst.get(compIdx).buf; + Pel* src0 = predSrc0.get(compIdx).buf; + Pel* src1 = predSrc1.get(compIdx).buf; + int32_t strideDst = predDst.get(compIdx).stride - width; + int32_t strideSrc0 = predSrc0.get(compIdx).stride - width; + int32_t strideSrc1 = predSrc1.get(compIdx).stride - width; + + const char log2WeightBase = 3; + const ClpRng clipRng = pu.cu->slice->clpRngs().comp[compIdx]; + const int32_t clipbd = clipRng.bd; + const int32_t shiftWeighted = std::max<int>(2, (IF_INTERNAL_PREC - clipbd)) + log2WeightBase; + const int32_t offsetWeighted = (1 << (shiftWeighted - 1)) + (IF_INTERNAL_OFFS << log2WeightBase); + const uint32_t scaleX = getComponentScaleX(compIdx, pu.chromaFormat); + const uint32_t scaleY = getComponentScaleY(compIdx, pu.chromaFormat); + + int16_t angle = g_GeoParams[splitDir][0]; + int16_t wIdx = floorLog2(pu.lwidth()) - GEO_MIN_CU_LOG2; + int16_t hIdx = floorLog2(pu.lheight()) - GEO_MIN_CU_LOG2; + int16_t stepX = 1 << scaleX; + int16_t stepY = 0; + int16_t* weight = nullptr; + if (g_angle2mirror[angle] == 2) + { + stepY = -(int)((GEO_WEIGHT_MASK_SIZE << scaleY) + pu.lwidth()); + weight = &g_globalGeoWeights[g_angle2mask[angle]][(GEO_WEIGHT_MASK_SIZE - 1 - g_weightOffset[splitDir][hIdx][wIdx][1]) * GEO_WEIGHT_MASK_SIZE + g_weightOffset[splitDir][hIdx][wIdx][0]]; + } + else if (g_angle2mirror[angle] == 1) + { + stepX = -1 << scaleX; + stepY = (GEO_WEIGHT_MASK_SIZE << scaleY) + pu.lwidth(); + weight = &g_globalGeoWeights[g_angle2mask[angle]][g_weightOffset[splitDir][hIdx][wIdx][1] * GEO_WEIGHT_MASK_SIZE + (GEO_WEIGHT_MASK_SIZE - 1 - g_weightOffset[splitDir][hIdx][wIdx][0])]; + } + else + { + stepY = (GEO_WEIGHT_MASK_SIZE << scaleY) - pu.lwidth(); + weight = &g_globalGeoWeights[g_angle2mask[angle]][g_weightOffset[splitDir][hIdx][wIdx][1] * GEO_WEIGHT_MASK_SIZE + g_weightOffset[splitDir][hIdx][wIdx][0]]; + } + for( int y = 0; y < height; y++ ) + { + for( int x = 0; x < width; x++ ) + { + *dst++ = ClipPel(rightShift((*weight*(*src0++) + ((8 - *weight) * (*src1++)) + offsetWeighted), shiftWeighted), clipRng); + weight += stepX; + } + dst += strideDst; + src0 += strideSrc0; + src1 += strideSrc1; + weight += stepY; + } +} +#endif /** * \brief turn on SIMD fuc diff --git a/source/Lib/CommonLib/InterpolationFilter.h b/source/Lib/CommonLib/InterpolationFilter.h index db2a08463..c166395af 100644 --- a/source/Lib/CommonLib/InterpolationFilter.h +++ b/source/Lib/CommonLib/InterpolationFilter.h @@ -83,8 +83,13 @@ public: template<int N> void filterVer(const ClpRng& clpRng, Pel const* src, int srcStride, Pel *dst, int dstStride, int width, int height, bool isFirst, bool isLast, TFilterCoeff const *coeff, bool biMCForDMVR); +#if !JVET_Q0806 static void xWeightedTriangleBlk(const PredictionUnit &pu, const uint32_t width, const uint32_t height, const ComponentID compIdx, const bool splitDir, PelUnitBuf& predDst, PelUnitBuf& predSrc0, PelUnitBuf& predSrc1); void weightedTriangleBlk(const PredictionUnit &pu, const uint32_t width, const uint32_t height, const ComponentID compIdx, const bool splitDir, PelUnitBuf& predDst, PelUnitBuf& predSrc0, PelUnitBuf& predSrc1); +#else + static void xWeightedGeoBlk(const PredictionUnit &pu, const uint32_t width, const uint32_t height, const ComponentID compIdx, const uint8_t splitDir, PelUnitBuf& predDst, PelUnitBuf& predSrc0, PelUnitBuf& predSrc1); + void weightedGeoBlk(const PredictionUnit &pu, const uint32_t width, const uint32_t height, const ComponentID compIdx, const uint8_t splitDir, PelUnitBuf& predDst, PelUnitBuf& predSrc0, PelUnitBuf& predSrc1); +#endif protected: #if JVET_J0090_MEMORY_BANDWITH_MEASURE static CacheModel* m_cacheModel; @@ -95,7 +100,11 @@ public: void( *m_filterHor[3][2][2] )( const ClpRng& clpRng, Pel const *src, int srcStride, Pel *dst, int dstStride, int width, int height, TFilterCoeff const *coeff, bool biMCForDMVR); void( *m_filterVer[3][2][2] )( const ClpRng& clpRng, Pel const *src, int srcStride, Pel *dst, int dstStride, int width, int height, TFilterCoeff const *coeff, bool biMCForDMVR); void( *m_filterCopy[2][2] ) ( const ClpRng& clpRng, Pel const *src, int srcStride, Pel *dst, int dstStride, int width, int height, bool biMCForDMVR); +#if !JVET_Q0806 void( *m_weightedTriangleBlk )(const PredictionUnit &pu, const uint32_t width, const uint32_t height, const ComponentID compIdx, const bool splitDir, PelUnitBuf& predDst, PelUnitBuf& predSrc0, PelUnitBuf& predSrc1); +#else + void( *m_weightedGeoBlk )(const PredictionUnit &pu, const uint32_t width, const uint32_t height, const ComponentID compIdx, const uint8_t splitDir, PelUnitBuf& predDst, PelUnitBuf& predSrc0, PelUnitBuf& predSrc1); +#endif void initInterpolationFilter( bool enable ); #ifdef TARGET_SIMD_X86 diff --git a/source/Lib/CommonLib/RdCost.cpp b/source/Lib/CommonLib/RdCost.cpp index 7f48f5d5e..e13492270 100644 --- a/source/Lib/CommonLib/RdCost.cpp +++ b/source/Lib/CommonLib/RdCost.cpp @@ -201,6 +201,10 @@ void RdCost::init() m_afpDistortFunc[DF_SAD_INTERMEDIATE_BITDEPTH] = RdCost::xGetSAD; +#if JVET_Q0806 + m_afpDistortFunc[DF_SAD_WITH_MASK] = RdCost::xGetSADwMask; +#endif + #if ENABLE_SIMD_OPT_DIST #ifdef TARGET_SIMD_X86 initRdCostX86(); @@ -314,6 +318,15 @@ void RdCost::setDistParam( DistParam &rcDP, const CPelBuf &org, const Pel* piRef rcDP.subShift = 1; } } +#if JVET_Q0806 + else if( subShiftMode == 3 ) + { + if (rcDP.org.height > 8 ) + { + rcDP.subShift = 1; + } + } +#endif } void RdCost::setDistParam( DistParam &rcDP, const CPelBuf &org, const CPelBuf &cur, int bitDepth, ComponentID compID, bool useHadamard ) @@ -3448,4 +3461,69 @@ Distortion RdCost::xGetMRHADs( const DistParam &rcDtParam ) return m_afpDistortFunc[DF_HAD]( modDistParam ); } + +#if JVET_Q0806 +void RdCost::setDistParam( DistParam &rcDP, const CPelBuf &org, const Pel* piRefY, int iRefStride, const Pel* mask, int iMaskStride, int stepX, int iMaskStride2, int bitDepth, ComponentID compID) +{ + rcDP.bitDepth = bitDepth; + rcDP.compID = compID; + + // set Original & Curr Pointer / Stride + rcDP.org = org; + rcDP.cur.buf = piRefY; + rcDP.cur.stride = iRefStride; + + // set Mask + rcDP.mask = mask; + rcDP.maskStride = iMaskStride; + rcDP.stepX = stepX; + rcDP.maskStride2 = iMaskStride2; + + // set Block Width / Height + rcDP.cur.width = org.width; + rcDP.cur.height = org.height; + rcDP.maximumDistortionForEarlyExit = std::numeric_limits<Distortion>::max(); + + // set Cost function for motion estimation with Mask + rcDP.distFunc = m_afpDistortFunc[ DF_SAD_WITH_MASK ]; +} + +Distortion RdCost::xGetSADwMask( const DistParam& rcDtParam ) +{ + if ( rcDtParam.applyWeight ) + { + return RdCostWeightPrediction::xGetSADw( rcDtParam ); + } + + const Pel* org = rcDtParam.org.buf; + const Pel* cur = rcDtParam.cur.buf; + const Pel* mask = rcDtParam.mask; + const int cols = rcDtParam.org.width; + int rows = rcDtParam.org.height; + const int subShift = rcDtParam.subShift; + const int subStep = ( 1 << subShift); + const int strideCur = rcDtParam.cur.stride * subStep; + const int strideOrg = rcDtParam.org.stride * subStep; + const int strideMask = rcDtParam.maskStride * subStep; + const int stepX = rcDtParam.stepX; + const int strideMask2 = rcDtParam.maskStride2; + const uint32_t distortionShift = DISTORTION_PRECISION_ADJUSTMENT(rcDtParam.bitDepth); + + Distortion sum = 0; + for (; rows != 0; rows -= subStep) + { + for (int n = 0; n < cols; n++) + { + sum += abs(org[n] - cur[n]) * *mask; + mask += stepX; + } + org += strideOrg; + cur += strideCur; + mask += strideMask; + mask += strideMask2; + } + sum <<= subShift; + return (sum >> distortionShift ); +} +#endif //! \} diff --git a/source/Lib/CommonLib/RdCost.h b/source/Lib/CommonLib/RdCost.h index a7aef6fa7..7d10e131a 100644 --- a/source/Lib/CommonLib/RdCost.h +++ b/source/Lib/CommonLib/RdCost.h @@ -71,6 +71,12 @@ public: CPelBuf cur; #if WCG_EXT CPelBuf orgLuma; +#endif +#if JVET_Q0806 + const Pel* mask; + int maskStride; + int stepX; + int maskStride2; #endif int step; FpDistFunc distFunc; @@ -90,7 +96,14 @@ public: int cShiftX; int cShiftY; DistParam() : - org(), cur(), step( 1 ), bitDepth( 0 ), useMR( false ), applyWeight( false ), isBiPred( false ), wpCur( nullptr ), compID( MAX_NUM_COMPONENT ), maximumDistortionForEarlyExit( std::numeric_limits<Distortion>::max() ), subShift( 0 ) + org(), cur(), +#if JVET_Q0806 + mask( nullptr ), + maskStride( 0 ), + stepX(0), + maskStride2(0), +#endif + step( 1 ), bitDepth( 0 ), useMR( false ), applyWeight( false ), isBiPred( false ), wpCur( nullptr ), compID( MAX_NUM_COMPONENT ), maximumDistortionForEarlyExit( std::numeric_limits<Distortion>::max() ), subShift( 0 ) , cShiftX(-1), cShiftY(-1) { } }; @@ -167,6 +180,9 @@ public: void setDistParam( DistParam &rcDP, const CPelBuf &org, const Pel* piRefY , int iRefStride, int bitDepth, ComponentID compID, int subShiftMode = 0, int step = 1, bool useHadamard = false ); void setDistParam( DistParam &rcDP, const CPelBuf &org, const CPelBuf &cur, int bitDepth, ComponentID compID, bool useHadamard = false ); void setDistParam( DistParam &rcDP, const Pel* pOrg, const Pel* piRefY, int iOrgStride, int iRefStride, int bitDepth, ComponentID compID, int width, int height, int subShiftMode = 0, int step = 1, bool useHadamard = false, bool bioApplied = false ); +#if JVET_Q0806 + void setDistParam( DistParam &rcDP, const CPelBuf &org, const Pel* piRefY, int iRefStride, const Pel* mask, int iMaskStride, int stepX, int iMaskStride2, int bitDepth, ComponentID compID); +#endif double getMotionLambda ( ) { return m_dLambdaMotionSAD; } void selectMotionLambda ( ) { m_motionLambda = getMotionLambda( ); } @@ -351,6 +367,9 @@ private: static Distortion xGetSAD48 ( const DistParam& pcDtParam ); static Distortion xGetSAD_full ( const DistParam& pcDtParam ); +#if JVET_Q0806 + static Distortion xGetSADwMask ( const DistParam& pcDtParam ); +#endif static Distortion xGetMRSAD ( const DistParam& pcDtParam ); static Distortion xGetMRSAD4 ( const DistParam& pcDtParam ); @@ -389,6 +408,11 @@ private: template<X86_VEXT vext> static Distortion xGetHADs_SIMD ( const DistParam& pcDtParam ); + +#if JVET_Q0806 + template< X86_VEXT vext > + static Distortion xGetSADwMask_SIMD( const DistParam& pcDtParam ); +#endif #endif public: @@ -399,6 +423,9 @@ public: Distortion getDistPart( const CPelBuf &org, const CPelBuf &cur, int bitDepth, const ComponentID compID, DFunc eDFunc ); #endif +#if JVET_Q0806 + Distortion getDistPart(const CPelBuf &org, const CPelBuf &cur, const Pel* mask, int bitDepth, const ComponentID compID, DFunc eDFunc); +#endif };// END CLASS DEFINITION RdCost //! \} diff --git a/source/Lib/CommonLib/Rom.cpp b/source/Lib/CommonLib/Rom.cpp index 5bc2f227a..5f8019a30 100644 --- a/source/Lib/CommonLib/Rom.cpp +++ b/source/Lib/CommonLib/Rom.cpp @@ -403,6 +403,7 @@ void initROM() } } +#if !JVET_Q0806 for( int idxH = MAX_CU_DEPTH - MIN_CU_LOG2; idxH >= 0; --idxH ) { for( int idxW = MAX_CU_DEPTH - MIN_CU_LOG2; idxW >= 0; --idxW ) @@ -446,6 +447,9 @@ void initROM() } } } +#else + initGeoTemplate(); +#endif ::memset(g_isReusedUniMVsFilled, 0, sizeof(g_isReusedUniMVsFilled)); } @@ -473,6 +477,7 @@ void destroyROM() delete gp_sizeIdxInfo; gp_sizeIdxInfo = nullptr; +#if !JVET_Q0806 for (int idxH = 0; idxH < MAX_CU_DEPTH - MIN_CU_LOG2 + 2; ++idxH) { for (int idxW = 0; idxW < MAX_CU_DEPTH - MIN_CU_LOG2 + 2; ++idxW) @@ -483,6 +488,21 @@ void destroyROM() g_triangleWeights[1][idxH][idxW] = nullptr; } } +#else + for( int modeIdx = 0; modeIdx < GEO_NUM_PARTITION_MODE; modeIdx++ ) + { + delete[] g_GeoParams[modeIdx]; + g_GeoParams[modeIdx] = nullptr; + } + delete[] g_GeoParams; + for( int i = 0; i < GEO_NUM_PRESTORED_MASK; i++ ) + { + delete[] g_globalGeoWeights [i]; + delete[] g_globalGeoEncSADmask[i]; + g_globalGeoWeights [i] = nullptr; + g_globalGeoEncSADmask[i] = nullptr; + } +#endif } // ==================================================================================================================== @@ -708,12 +728,98 @@ const uint32_t g_scalingListSize [SCALING_LIST_SIZE_NUM] = { 1, 4, 16, 64, 256, const uint32_t g_scalingListSizeX[SCALING_LIST_SIZE_NUM] = { 1, 2, 4, 8, 16, 32, 64, 128 }; +#if !JVET_Q0806 uint8_t g_triangleMvStorage[TRIANGLE_DIR_NUM][MAX_CU_DEPTH - MIN_CU_LOG2 + 1][MAX_CU_DEPTH - MIN_CU_LOG2 + 1][MAX_CU_SIZE >> MIN_CU_LOG2][MAX_CU_SIZE >> MIN_CU_LOG2]; int16_t *g_triangleWeights[TRIANGLE_DIR_NUM][MAX_CU_DEPTH - MIN_CU_LOG2 + 2][MAX_CU_DEPTH - MIN_CU_LOG2 + 2]; +#endif + Mv g_reusedUniMVs[32][32][8][8][2][33]; bool g_isReusedUniMVsFilled[32][32][8][8]; const uint8_t g_paletteQuant[52] = { 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 7, 7, 8, 9, 9, 10, 11, 12, 13, 14, 15, 16, 17, 19, 21, 22, 24, 23, 25, 26, 28, 29, 31, 32, 34, 36, 37, 39, 41, 42, 45 }; uint8_t g_paletteRunTopLut [5] = { 0, 1, 1, 2, 2 }; uint8_t g_paletteRunLeftLut[5] = { 0, 1, 2, 3, 4 }; + +#if JVET_Q0806 +void initGeoTemplate() +{ + g_GeoParams = new int16_t*[GEO_NUM_PARTITION_MODE]; + int modeIdx = 0; + for( int angleIdx = 0; angleIdx < GEO_NUM_ANGLES; angleIdx++ ) + { + for( int distanceIdx = 0; distanceIdx < GEO_NUM_DISTANCES; distanceIdx++ ) + { + if( (distanceIdx == 0 && angleIdx >= 16) + || ((distanceIdx == 2 || distanceIdx == 0) && (g_angle2mask[angleIdx] == 0 || g_angle2mask[angleIdx] == 5)) + || g_angle2mask[angleIdx] == -1 ) + continue; + g_GeoParams[modeIdx] = new int16_t[2]; + g_GeoParams[modeIdx][0] = (int16_t)angleIdx; + g_GeoParams[modeIdx][1] = (int16_t)distanceIdx; + modeIdx++; + } + } + for (int angleIdx = 0; angleIdx < (GEO_NUM_ANGLES >> 2) + 1; angleIdx++) + { + if (g_angle2mask[angleIdx] == -1) + continue; + g_globalGeoWeights[g_angle2mask[angleIdx]] = new int16_t[GEO_WEIGHT_MASK_SIZE * GEO_WEIGHT_MASK_SIZE]; + g_globalGeoEncSADmask[g_angle2mask[angleIdx]] = new int16_t[GEO_WEIGHT_MASK_SIZE * GEO_WEIGHT_MASK_SIZE]; + + int distanceX = angleIdx; + int distanceY = (distanceX + (GEO_NUM_ANGLES >> 2)) % GEO_NUM_ANGLES; + int16_t rho = (g_Dis[distanceX] << (GEO_MAX_CU_LOG2+1)) + (g_Dis[distanceY] << (GEO_MAX_CU_LOG2 + 1)); + static const int16_t maskOffset = (2*GEO_MAX_CU_SIZE - GEO_WEIGHT_MASK_SIZE) >> 1; + int index = 0; + for( int y = 0; y < GEO_WEIGHT_MASK_SIZE; y++ ) + { + int16_t lookUpY = (((y + maskOffset) << 1) + 1) * g_Dis[distanceY]; + for( int x = 0; x < GEO_WEIGHT_MASK_SIZE; x++, index++ ) + { + int16_t sx_i = ((x + maskOffset) << 1) + 1; + int16_t weightIdx = sx_i * g_Dis[distanceX] + lookUpY - rho; + int weightLinearIdx = 32 + weightIdx; + g_globalGeoWeights[g_angle2mask[angleIdx]][index] = Clip3(0, 8, (weightLinearIdx + 4) >> 3); + g_globalGeoEncSADmask[g_angle2mask[angleIdx]][index] = weightIdx > 0 ? 1 : 0; + } + } + } + + for( int hIdx = 0; hIdx < GEO_NUM_CU_SIZE; hIdx++ ) + { + int16_t height = 1 << ( hIdx + GEO_MIN_CU_LOG2); + for( int wIdx = 0; wIdx < GEO_NUM_CU_SIZE; wIdx++ ) + { + int16_t width = 1 << (wIdx + GEO_MIN_CU_LOG2); + for( int splitDir = 0; splitDir < GEO_NUM_PARTITION_MODE; splitDir++ ) + { + int16_t angle = g_GeoParams[splitDir][0]; + int16_t distance = g_GeoParams[splitDir][1]; + int16_t offsetX = (GEO_WEIGHT_MASK_SIZE - width) >> 1; + int16_t offsetY = (GEO_WEIGHT_MASK_SIZE - height) >> 1; + if( distance > 0 ) + { + if( angle % 16 == 8 || (angle % 16 != 0 && height >= width) ) + { + offsetY += angle < 16 ? ((distance * (int32_t)height) >> 3) : -((distance * (int32_t)height) >> 3); + } + else + { + offsetX += angle < 16 ? ((distance * (int32_t)width) >> 3) : -((distance * (int32_t)width) >> 3); + } + } + g_weightOffset[splitDir][hIdx][wIdx][0] = offsetX; + g_weightOffset[splitDir][hIdx][wIdx][1] = offsetY; + } + } + } +} +int16_t** g_GeoParams; +int16_t* g_globalGeoWeights [GEO_NUM_PRESTORED_MASK]; +int16_t* g_globalGeoEncSADmask[GEO_NUM_PRESTORED_MASK]; +int16_t g_weightOffset [GEO_NUM_PARTITION_MODE][GEO_NUM_CU_SIZE][GEO_NUM_CU_SIZE][2]; +int8_t g_angle2mask[GEO_NUM_ANGLES] = { 0, -1, 1, 2, 3, 4, -1, -1, 5, -1, -1, 4, 3, 2, 1, -1, 0, -1, 1, 2, 3, 4, -1, -1, 5, -1, -1, 4, 3, 2, 1, -1 }; +int8_t g_Dis[GEO_NUM_ANGLES] = { 8, 8, 8, 8, 4, 4, 2, 1, 0, -1, -2, -4, -4, -8, -8, -8, -8, -8, -8, -8, -4, -4, -2, -1, 0, 1, 2, 4, 4, 8, 8, 8 }; +int8_t g_angle2mirror[GEO_NUM_ANGLES] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 2 }; +#endif //! \} diff --git a/source/Lib/CommonLib/Rom.h b/source/Lib/CommonLib/Rom.h index 929a75547..010891cb1 100644 --- a/source/Lib/CommonLib/Rom.h +++ b/source/Lib/CommonLib/Rom.h @@ -205,9 +205,12 @@ constexpr uint8_t g_tbMax[257] = { 0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, //! \} +#if !JVET_Q0806 extern uint8_t g_triangleMvStorage[TRIANGLE_DIR_NUM][MAX_CU_DEPTH - MIN_CU_LOG2 + 1][MAX_CU_DEPTH - MIN_CU_LOG2 + 1][MAX_CU_SIZE >> MIN_CU_LOG2][MAX_CU_SIZE >> MIN_CU_LOG2]; // 7-tap/3-tap, direction, 2/4/8/16/32/64/128 extern int16_t *g_triangleWeights[TRIANGLE_DIR_NUM][MAX_CU_DEPTH - MIN_CU_LOG2 + 2][MAX_CU_DEPTH - MIN_CU_LOG2 + 2]; +#endif + extern bool g_mctsDecCheckEnabled; class Mv; @@ -220,5 +223,15 @@ extern uint8_t g_paletteRunLeftLut[5]; const int g_IBCBufferSize = 256 * 128; +#if JVET_Q0806 +void initGeoTemplate(); +extern int16_t** g_GeoParams; +extern int16_t* g_globalGeoWeights [GEO_NUM_PRESTORED_MASK]; +extern int16_t* g_globalGeoEncSADmask[GEO_NUM_PRESTORED_MASK]; +extern int16_t g_weightOffset [GEO_NUM_PARTITION_MODE][GEO_NUM_CU_SIZE][GEO_NUM_CU_SIZE][2]; +extern int8_t g_angle2mask [GEO_NUM_ANGLES]; +extern int8_t g_Dis[GEO_NUM_ANGLES]; +extern int8_t g_angle2mirror[GEO_NUM_ANGLES]; +#endif #endif //__TCOMROM__ diff --git a/source/Lib/CommonLib/Slice.cpp b/source/Lib/CommonLib/Slice.cpp index e923fdf52..cda889eed 100644 --- a/source/Lib/CommonLib/Slice.cpp +++ b/source/Lib/CommonLib/Slice.cpp @@ -1575,7 +1575,11 @@ PicHeader::PicHeader() , m_disBdofFlag ( 0 ) , m_disDmvrFlag ( 0 ) , m_disProfFlag ( 0 ) +#if !JVET_Q0806 , m_maxNumTriangleCand ( 0 ) +#else +, m_maxNumGeoCand ( 0 ) +#endif , m_maxNumIBCMergeCand ( IBC_MRG_MAX_NUM_CANDS ) , m_jointCbCrSignFlag ( 0 ) , m_saoEnabledPresentFlag ( 0 ) @@ -1665,7 +1669,11 @@ void PicHeader::initPicHeader() m_disBdofFlag = 0; m_disDmvrFlag = 0; m_disProfFlag = 0; +#if !JVET_Q0806 m_maxNumTriangleCand = 0; +#else + m_maxNumGeoCand = 0; +#endif m_maxNumIBCMergeCand = IBC_MRG_MAX_NUM_CANDS; m_jointCbCrSignFlag = 0; m_saoEnabledPresentFlag = 0; @@ -1805,7 +1813,11 @@ SPS::SPS() , m_AffineType ( false ) , m_PROF ( false ) , m_ciip ( false ) +#if !JVET_Q0806 , m_Triangle ( false ) +#else +, m_Geo ( false ) +#endif #if LUMA_ADAPTIVE_DEBLOCKING_FILTER_QP_OFFSET , m_LadfEnabled ( false ) , m_LadfNumIntervals ( 0 ) @@ -2020,7 +2032,11 @@ PPS::PPS() , m_PPSMvdL1ZeroIdc (0) , m_PPSCollocatedFromL0Idc (0) , m_PPSSixMinusMaxNumMergeCandPlus1 (0) +#if !JVET_Q0806 , m_PPSMaxNumMergeCandMinusMaxNumTriangleCandPlus1 (0) +#else +, m_PPSMaxNumMergeCandMinusMaxNumGeoCandPlus1 (0) +#endif , m_cabacInitPresentFlag (false) , m_pictureHeaderExtensionPresentFlag(0) , m_sliceHeaderExtensionPresentFlag (false) diff --git a/source/Lib/CommonLib/Slice.h b/source/Lib/CommonLib/Slice.h index b95485113..b46f2e01a 100644 --- a/source/Lib/CommonLib/Slice.h +++ b/source/Lib/CommonLib/Slice.h @@ -256,7 +256,11 @@ class ConstraintInfo bool m_noIbcConstraintFlag; bool m_noCiipConstraintFlag; bool m_noFPelMmvdConstraintFlag; +#if !JVET_Q0806 bool m_noTriangleConstraintFlag; +#else + bool m_noGeoConstraintFlag; +#endif bool m_noLadfConstraintFlag; bool m_noTransformSkipConstraintFlag; bool m_noBDPCMConstraintFlag; @@ -300,7 +304,11 @@ public: , m_noIbcConstraintFlag (false) , m_noCiipConstraintFlag (false) , m_noFPelMmvdConstraintFlag (false) +#if !JVET_Q0806 , m_noTriangleConstraintFlag (false) +#else + , m_noGeoConstraintFlag (false) +#endif , m_noLadfConstraintFlag (false) , m_noTransformSkipConstraintFlag(false) , m_noBDPCMConstraintFlag (false) @@ -383,8 +391,13 @@ public: void setNoCiipConstraintFlag(bool bVal) { m_noCiipConstraintFlag = bVal; } bool getNoFPelMmvdConstraintFlag() const { return m_noFPelMmvdConstraintFlag; } void setNoFPelMmvdConstraintFlag(bool bVal) { m_noFPelMmvdConstraintFlag = bVal; } +#if !JVET_Q0806 bool getNoTriangleConstraintFlag() const { return m_noTriangleConstraintFlag; } void setNoTriangleConstraintFlag(bool bVal) { m_noTriangleConstraintFlag = bVal; } +#else + bool getNoGeoConstraintFlag() const { return m_noGeoConstraintFlag; } + void setNoGeoConstraintFlag(bool bVal) { m_noGeoConstraintFlag = bVal; } +#endif bool getNoLadfConstraintFlag() const { return m_noLadfConstraintFlag; } void setNoLadfConstraintFlag(bool bVal) { m_noLadfConstraintFlag = bVal; } bool getNoTransformSkipConstraintFlag() const { return m_noTransformSkipConstraintFlag; } @@ -1150,7 +1163,11 @@ private: bool m_PROF; bool m_bcw; // bool m_ciip; +#if !JVET_Q0806 bool m_Triangle; +#else + bool m_Geo; +#endif #if LUMA_ADAPTIVE_DEBLOCKING_FILTER_QP_OFFSET bool m_LadfEnabled; int m_LadfNumIntervals; @@ -1445,8 +1462,13 @@ public: void setUseCiip ( bool b ) { m_ciip = b; } bool getUseCiip () const { return m_ciip; } +#if !JVET_Q0806 void setUseTriangle ( bool b ) { m_Triangle = b; } bool getUseTriangle () const { return m_Triangle; } +#else + void setUseGeo ( bool b ) { m_Geo = b; } + bool getUseGeo () const { return m_Geo; } +#endif void setUseMRL ( bool b ) { m_MRL = b; } bool getUseMRL () const { return m_MRL; } void setUseMIP ( bool b ) { m_MIP = b; } @@ -1577,7 +1599,11 @@ private: int m_PPSMvdL1ZeroIdc; int m_PPSCollocatedFromL0Idc; uint32_t m_PPSSixMinusMaxNumMergeCandPlus1; +#if !JVET_Q0806 uint32_t m_PPSMaxNumMergeCandMinusMaxNumTriangleCandPlus1; +#else + uint32_t m_PPSMaxNumMergeCandMinusMaxNumGeoCandPlus1; +#endif bool m_cabacInitPresentFlag; @@ -1785,8 +1811,13 @@ public: void setPPSCollocatedFromL0Idc(int u) { m_PPSCollocatedFromL0Idc = u; } uint32_t getPPSSixMinusMaxNumMergeCandPlus1() const { return m_PPSSixMinusMaxNumMergeCandPlus1; } void setPPSSixMinusMaxNumMergeCandPlus1(uint32_t u) { m_PPSSixMinusMaxNumMergeCandPlus1 = u; } +#if !JVET_Q0806 uint32_t getPPSMaxNumMergeCandMinusMaxNumTriangleCandPlus1() const { return m_PPSMaxNumMergeCandMinusMaxNumTriangleCandPlus1; } void setPPSMaxNumMergeCandMinusMaxNumTriangleCandPlus1(uint32_t u) { m_PPSMaxNumMergeCandMinusMaxNumTriangleCandPlus1 = u; } +#else + uint32_t getPPSMaxNumMergeCandMinusMaxNumGeoCandPlus1() const { return m_PPSMaxNumMergeCandMinusMaxNumGeoCandPlus1; } + void setPPSMaxNumMergeCandMinusMaxNumGeoCandPlus1(uint32_t u) { m_PPSMaxNumMergeCandMinusMaxNumGeoCandPlus1 = u; } +#endif void setCabacInitPresentFlag( bool flag ) { m_cabacInitPresentFlag = flag; } bool getCabacInitPresentFlag() const { return m_cabacInitPresentFlag; } @@ -1923,7 +1954,11 @@ private: bool m_disBdofFlag; //!< picture level BDOF disable flag bool m_disDmvrFlag; //!< picture level DMVR disable flag bool m_disProfFlag; //!< picture level PROF disable flag +#if !JVET_Q0806 uint32_t m_maxNumTriangleCand; //!< max number of triangle merge candidates +#else + uint32_t m_maxNumGeoCand; //!< max number of geometric merge candidates +#endif uint32_t m_maxNumIBCMergeCand; //!< max number of IBC merge candidates bool m_jointCbCrSignFlag; //!< joint Cb/Cr residual sign flag bool m_saoEnabledPresentFlag; //!< sao enabled flags present in the picture header @@ -2036,8 +2071,13 @@ public: bool getDisDmvrFlag() const { return m_disDmvrFlag; } void setDisProfFlag( bool val ) { m_disProfFlag = val; } bool getDisProfFlag() const { return m_disProfFlag; } +#if !JVET_Q0806 void setMaxNumTriangleCand(uint32_t b) { m_maxNumTriangleCand = b; } uint32_t getMaxNumTriangleCand() const { return m_maxNumTriangleCand; } +#else + void setMaxNumGeoCand(uint32_t b) { m_maxNumGeoCand = b; } + uint32_t getMaxNumGeoCand() const { return m_maxNumGeoCand; } +#endif void setMaxNumIBCMergeCand( uint32_t b ) { m_maxNumIBCMergeCand = b; } uint32_t getMaxNumIBCMergeCand() const { return m_maxNumIBCMergeCand; } void setJointCbCrSignFlag( bool b ) { m_jointCbCrSignFlag = b; } diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h index fbcf3e131..a643ffc40 100644 --- a/source/Lib/CommonLib/TypeDef.h +++ b/source/Lib/CommonLib/TypeDef.h @@ -78,6 +78,9 @@ #define JVET_Q0483_CLIP_TMVP 1 // JVET-Q0483: Clip TMVP when no scaling is applied #define JVET_Q0516_MTS_SIGNALLING_DC_ONLY_COND 1 // JVET-Q0516/Q0685: disable MTS when there is only DC coefficient + +#define JVET_Q0806 1 // Geo related adoptions (JVET-Q0059, JVET-Q0077, JVET-Q0123, JVET-Q0188, JVET-Q0242_GEO, JVET-Q0309, JVET-Q0365 and JVET-Q0370) + #define JVET_Q0055_MTS_SIGNALLING 1 // JVET-Q0055: Check for transform coefficients outside the 16x16 area #define JVET_Q0480_RASTER_RECT_SLICES 1 // JVET-Q0480: Eliminate redundant slice height syntax when in raster rectangular slice mode (tile_idx_delta_present_flag == 0) @@ -582,7 +585,12 @@ enum DFunc DF_SAD_INTERMEDIATE_BITDEPTH = 63, +#if JVET_Q0806 + DF_SAD_WITH_MASK = 64, + DF_TOTAL_FUNCTIONS = 65 +#else DF_TOTAL_FUNCTIONS = 64 +#endif }; /// motion vector predictor direction used in AMVP @@ -860,12 +868,14 @@ enum MergeType NUM_MRG_TYPE // 5 }; +#if !JVET_Q0806 enum TriangleSplit { TRIANGLE_DIR_135 = 0, TRIANGLE_DIR_45, TRIANGLE_DIR_NUM }; +#endif ////////////////////////////////////////////////////////////////////////// // Encoder modes to try out diff --git a/source/Lib/CommonLib/Unit.cpp b/source/Lib/CommonLib/Unit.cpp index 041b241b8..8a6d7c8d6 100644 --- a/source/Lib/CommonLib/Unit.cpp +++ b/source/Lib/CommonLib/Unit.cpp @@ -266,7 +266,11 @@ CodingUnit& CodingUnit::operator=( const CodingUnit& other ) affine = other.affine; affineType = other.affineType; colorTransform = other.colorTransform; +#if !JVET_Q0806 triangle = other.triangle; +#else + geoFlag = other.geoFlag; +#endif bdpcmMode = other.bdpcmMode; bdpcmModeChroma = other.bdpcmModeChroma; qp = other.qp; @@ -326,7 +330,11 @@ void CodingUnit::initData() affine = false; affineType = 0; colorTransform = false; +#if !JVET_Q0806 triangle = false; +#else + geoFlag = false; +#endif bdpcmMode = 0; bdpcmModeChroma = 0; qp = 0; @@ -458,10 +466,12 @@ const uint8_t CodingUnit::checkAllowedSbt() const { return 0; } +#if !JVET_Q0806 if( triangle ) { return 0; } +#endif uint8_t sbtAllowed = 0; int cuWidth = lwidth(); @@ -528,9 +538,15 @@ void PredictionUnit::initData() mergeFlag = false; regularMergeFlag = false; mergeIdx = MAX_UCHAR; +#if !JVET_Q0806 triangleSplitDir = MAX_UCHAR; triangleMergeIdx0 = MAX_UCHAR; triangleMergeIdx1 = MAX_UCHAR; +#else + geoSplitDir = MAX_UCHAR; + geoMergeIdx0 = MAX_UCHAR; + geoMergeIdx1 = MAX_UCHAR; +#endif mmvdMergeFlag = false; mmvdMergeIdx = MAX_UINT; interDir = MAX_UCHAR; @@ -579,9 +595,15 @@ PredictionUnit& PredictionUnit::operator=(const InterPredictionData& predData) mergeFlag = predData.mergeFlag; regularMergeFlag = predData.regularMergeFlag; mergeIdx = predData.mergeIdx; +#if !JVET_Q0806 triangleSplitDir = predData.triangleSplitDir ; triangleMergeIdx0 = predData.triangleMergeIdx0 ; triangleMergeIdx1 = predData.triangleMergeIdx1 ; +#else + geoSplitDir = predData.geoSplitDir; + geoMergeIdx0 = predData.geoMergeIdx0; + geoMergeIdx1 = predData.geoMergeIdx1; +#endif mmvdMergeFlag = predData.mmvdMergeFlag; mmvdMergeIdx = predData.mmvdMergeIdx; interDir = predData.interDir; @@ -625,9 +647,15 @@ PredictionUnit& PredictionUnit::operator=( const PredictionUnit& other ) mergeFlag = other.mergeFlag; regularMergeFlag = other.regularMergeFlag; mergeIdx = other.mergeIdx; +#if !JVET_Q0806 triangleSplitDir = other.triangleSplitDir ; triangleMergeIdx0 = other.triangleMergeIdx0 ; triangleMergeIdx1 = other.triangleMergeIdx1 ; +#else + geoSplitDir = other.geoSplitDir; + geoMergeIdx0 = other.geoMergeIdx0; + geoMergeIdx1 = other.geoMergeIdx1; +#endif mmvdMergeFlag = other.mmvdMergeFlag; mmvdMergeIdx = other.mmvdMergeIdx; interDir = other.interDir; diff --git a/source/Lib/CommonLib/Unit.h b/source/Lib/CommonLib/Unit.h index 91130a722..b8c2a30c7 100644 --- a/source/Lib/CommonLib/Unit.h +++ b/source/Lib/CommonLib/Unit.h @@ -309,7 +309,11 @@ struct CodingUnit : public UnitArea bool affine; int affineType; bool colorTransform; +#if !JVET_Q0806 bool triangle; +#else + bool geoFlag; +#endif int bdpcmMode; int bdpcmModeChroma; uint8_t imv; @@ -383,9 +387,15 @@ struct InterPredictionData bool mergeFlag; bool regularMergeFlag; uint8_t mergeIdx; +#if !JVET_Q0806 uint8_t triangleSplitDir; uint8_t triangleMergeIdx0; uint8_t triangleMergeIdx1; +#else + uint8_t geoSplitDir; + uint8_t geoMergeIdx0; + uint8_t geoMergeIdx1; +#endif bool mmvdMergeFlag; uint32_t mmvdMergeIdx; uint8_t interDir; diff --git a/source/Lib/CommonLib/UnitTools.cpp b/source/Lib/CommonLib/UnitTools.cpp index 95e59ed1e..13dfb3c8d 100644 --- a/source/Lib/CommonLib/UnitTools.cpp +++ b/source/Lib/CommonLib/UnitTools.cpp @@ -244,7 +244,11 @@ void CU::saveMotionInHMVP( const CodingUnit& cu, const bool isToBeDone ) { const PredictionUnit& pu = *cu.firstPU; +#if !JVET_Q0806 if (!cu.triangle && !cu.affine && !isToBeDone ) +#else + if (!cu.geoFlag && !cu.affine && !isToBeDone) +#endif { MotionInfo mi = pu.getMotionInfo(); @@ -3138,6 +3142,7 @@ void PU::restrictBiPredMergeCandsOne(PredictionUnit &pu) } } +#if !JVET_Q0806 void PU::getTriangleMergeCandidates( const PredictionUnit &pu, MergeCtx& triangleMrgCtx ) { MergeCtx tmpMergeCtx; @@ -3294,6 +3299,167 @@ int32_t PU::mappingRefPic( const PredictionUnit &pu, int32_t refPicPoc, bool tar } return -1; } +#else +void PU::getGeoMergeCandidates( const PredictionUnit &pu, MergeCtx& geoMrgCtx ) +{ + MergeCtx tmpMergeCtx; + + const Slice &slice = *pu.cs->slice; + const uint32_t maxNumMergeCand = slice.getPicHeader()->getMaxNumMergeCand(); + + geoMrgCtx.numValidMergeCand = 0; + + for (int32_t i = 0; i < GEO_MAX_NUM_UNI_CANDS; i++) + { + geoMrgCtx.BcwIdx[i] = BCW_DEFAULT; + geoMrgCtx.interDirNeighbours[i] = 0; + geoMrgCtx.mrgTypeNeighbours[i] = MRG_TYPE_DEFAULT_N; + geoMrgCtx.mvFieldNeighbours[(i << 1)].refIdx = NOT_VALID; + geoMrgCtx.mvFieldNeighbours[(i << 1) + 1].refIdx = NOT_VALID; + geoMrgCtx.mvFieldNeighbours[(i << 1)].mv = Mv(); + geoMrgCtx.mvFieldNeighbours[(i << 1) + 1].mv = Mv(); + geoMrgCtx.useAltHpelIf[i] = false; + } + + PU::getInterMergeCandidates(pu, tmpMergeCtx, 0); + + for (int32_t i = 0; i < maxNumMergeCand; i++) + { + int parity = i & 1; + if( tmpMergeCtx.interDirNeighbours[i] & (0x01 + parity) ) + { + geoMrgCtx.interDirNeighbours[geoMrgCtx.numValidMergeCand] = 1 + parity; + geoMrgCtx.mrgTypeNeighbours[geoMrgCtx.numValidMergeCand] = MRG_TYPE_DEFAULT_N; + geoMrgCtx.mvFieldNeighbours[(geoMrgCtx.numValidMergeCand << 1) + !parity].mv = Mv(0, 0); + geoMrgCtx.mvFieldNeighbours[(geoMrgCtx.numValidMergeCand << 1) + parity].mv = tmpMergeCtx.mvFieldNeighbours[(i << 1) + parity].mv; + geoMrgCtx.mvFieldNeighbours[(geoMrgCtx.numValidMergeCand << 1) + !parity].refIdx = -1; + geoMrgCtx.mvFieldNeighbours[(geoMrgCtx.numValidMergeCand << 1) + parity].refIdx = tmpMergeCtx.mvFieldNeighbours[(i << 1) + parity].refIdx; + geoMrgCtx.numValidMergeCand++; + if (geoMrgCtx.numValidMergeCand == GEO_MAX_NUM_UNI_CANDS) + { + return; + } + continue; + } + + if (tmpMergeCtx.interDirNeighbours[i] & (0x02 - parity)) + { + geoMrgCtx.interDirNeighbours[geoMrgCtx.numValidMergeCand] = 2 - parity; + geoMrgCtx.mrgTypeNeighbours[geoMrgCtx.numValidMergeCand] = MRG_TYPE_DEFAULT_N; + geoMrgCtx.mvFieldNeighbours[(geoMrgCtx.numValidMergeCand << 1) + !parity].mv = tmpMergeCtx.mvFieldNeighbours[(i << 1) + !parity].mv; + geoMrgCtx.mvFieldNeighbours[(geoMrgCtx.numValidMergeCand << 1) + parity].mv = Mv(0, 0); + geoMrgCtx.mvFieldNeighbours[(geoMrgCtx.numValidMergeCand << 1) + !parity].refIdx = tmpMergeCtx.mvFieldNeighbours[(i << 1) + !parity].refIdx; + geoMrgCtx.mvFieldNeighbours[(geoMrgCtx.numValidMergeCand << 1) + parity].refIdx = -1; + geoMrgCtx.numValidMergeCand++; + if (geoMrgCtx.numValidMergeCand == GEO_MAX_NUM_UNI_CANDS) + { + return; + } + } + } +} + +void PU::spanGeoMotionInfo( PredictionUnit &pu, MergeCtx &geoMrgCtx, const uint8_t splitDir, const uint8_t candIdx0, const uint8_t candIdx1) +{ + pu.geoSplitDir = splitDir; + pu.geoMergeIdx0 = candIdx0; + pu.geoMergeIdx1 = candIdx1; + MotionBuf mb = pu.getMotionBuf(); + + MotionInfo biMv; + biMv.isInter = true; + biMv.sliceIdx = pu.cs->slice->getIndependentSliceIdx(); + + if( geoMrgCtx.interDirNeighbours[candIdx0] == 1 && geoMrgCtx.interDirNeighbours[candIdx1] == 2 ) + { + biMv.interDir = 3; + biMv.mv[0] = geoMrgCtx.mvFieldNeighbours[ candIdx0 << 1 ].mv; + biMv.mv[1] = geoMrgCtx.mvFieldNeighbours[(candIdx1 << 1) + 1].mv; + biMv.refIdx[0] = geoMrgCtx.mvFieldNeighbours[ candIdx0 << 1 ].refIdx; + biMv.refIdx[1] = geoMrgCtx.mvFieldNeighbours[(candIdx1 << 1) + 1].refIdx; + } + else if( geoMrgCtx.interDirNeighbours[candIdx0] == 2 && geoMrgCtx.interDirNeighbours[candIdx1] == 1 ) + { + biMv.interDir = 3; + biMv.mv[0] = geoMrgCtx.mvFieldNeighbours[ candIdx1 << 1 ].mv; + biMv.mv[1] = geoMrgCtx.mvFieldNeighbours[(candIdx0 << 1) + 1].mv; + biMv.refIdx[0] = geoMrgCtx.mvFieldNeighbours[ candIdx1 << 1 ].refIdx; + biMv.refIdx[1] = geoMrgCtx.mvFieldNeighbours[(candIdx0 << 1) + 1].refIdx; + } + else if( geoMrgCtx.interDirNeighbours[candIdx0] == 1 && geoMrgCtx.interDirNeighbours[candIdx1] == 1 ) + { + biMv.interDir = 1; + biMv.mv[0] = geoMrgCtx.mvFieldNeighbours[candIdx1 << 1].mv; + biMv.mv[1] = Mv(0, 0); + biMv.refIdx[0] = geoMrgCtx.mvFieldNeighbours[candIdx1 << 1].refIdx; + biMv.refIdx[1] = -1; + } + else if( geoMrgCtx.interDirNeighbours[candIdx0] == 2 && geoMrgCtx.interDirNeighbours[candIdx1] == 2 ) + { + biMv.interDir = 2; + biMv.mv[0] = Mv(0, 0); + biMv.mv[1] = geoMrgCtx.mvFieldNeighbours[(candIdx1 << 1) + 1].mv; + biMv.refIdx[0] = -1; + biMv.refIdx[1] = geoMrgCtx.mvFieldNeighbours[(candIdx1 << 1) + 1].refIdx; + } + + int16_t angle = g_GeoParams[splitDir][0]; + int tpmMask = 0; + int lookUpY = 0, motionIdx = 0; + bool isFlip = angle >= 13 && angle <= 27; + int distanceIdx = g_GeoParams[splitDir][1]; + int distanceX = angle; + int distanceY = (distanceX + (GEO_NUM_ANGLES >> 2)) % GEO_NUM_ANGLES; + int offsetX = ( - (int)pu.lwidth()) >> 1; + int offsetY = ( - (int)pu.lheight()) >> 1; + if (distanceIdx > 0) + { + if (angle % 16 == 8 || (angle % 16 != 0 && pu.lheight() >= pu.lwidth())) + offsetY += angle < 16 ? ((distanceIdx * pu.lheight()) >> 3) : -(int)((distanceIdx * pu.lheight()) >> 3); + else + offsetX += angle < 16 ? ((distanceIdx * pu.lwidth()) >> 3) : -(int)((distanceIdx * pu.lwidth()) >> 3); + } + for (int y = 0; y < mb.height; y++) + { + lookUpY = (((4*y + offsetY) << 1) + 5) * g_Dis[distanceY]; + for (int x = 0; x < mb.width; x++) + { + motionIdx = (((4*x + offsetX) << 1) + 5) * g_Dis[distanceX] + lookUpY; + tpmMask = abs(motionIdx) < 32 ? 2 : ( motionIdx<=0 ? (1 - isFlip):isFlip); + if (tpmMask == 2) + { + mb.at(x, y).isInter = true; + mb.at(x, y).interDir = biMv.interDir; + mb.at(x, y).refIdx[0] = biMv.refIdx[0]; + mb.at(x, y).refIdx[1] = biMv.refIdx[1]; + mb.at(x, y).mv[0] = biMv.mv[0]; + mb.at(x, y).mv[1] = biMv.mv[1]; + mb.at(x, y).sliceIdx = biMv.sliceIdx; + } + else if (tpmMask == 0) + { + mb.at(x, y).isInter = true; + mb.at(x, y).interDir = geoMrgCtx.interDirNeighbours[candIdx0]; + mb.at(x, y).refIdx[0] = geoMrgCtx.mvFieldNeighbours[candIdx0 << 1].refIdx; + mb.at(x, y).refIdx[1] = geoMrgCtx.mvFieldNeighbours[(candIdx0 << 1) + 1].refIdx; + mb.at(x, y).mv[0] = geoMrgCtx.mvFieldNeighbours[candIdx0 << 1].mv; + mb.at(x, y).mv[1] = geoMrgCtx.mvFieldNeighbours[(candIdx0 << 1) + 1].mv; + mb.at(x, y).sliceIdx = biMv.sliceIdx; + } + else + { + mb.at(x, y).isInter = true; + mb.at(x, y).interDir = geoMrgCtx.interDirNeighbours[candIdx1]; + mb.at(x, y).refIdx[0] = geoMrgCtx.mvFieldNeighbours[candIdx1 << 1].refIdx; + mb.at(x, y).refIdx[1] = geoMrgCtx.mvFieldNeighbours[(candIdx1 << 1) + 1].refIdx; + mb.at(x, y).mv[0] = geoMrgCtx.mvFieldNeighbours[candIdx1 << 1].mv; + mb.at(x, y).mv[1] = geoMrgCtx.mvFieldNeighbours[(candIdx1 << 1) + 1].mv; + mb.at(x, y).sliceIdx = biMv.sliceIdx; + } + } + } +} +#endif bool CU::hasSubCUNonZeroMVd( const CodingUnit& cu ) { diff --git a/source/Lib/CommonLib/UnitTools.h b/source/Lib/CommonLib/UnitTools.h index 8cead3c5c..e13475ef6 100644 --- a/source/Lib/CommonLib/UnitTools.h +++ b/source/Lib/CommonLib/UnitTools.h @@ -168,9 +168,14 @@ namespace PU bool isLMCMode ( unsigned mode); bool isLMCModeEnabled (const PredictionUnit &pu, unsigned mode); bool isChromaIntraModeCrossCheckMode(const PredictionUnit &pu); +#if !JVET_Q0806 void getTriangleMergeCandidates (const PredictionUnit &pu, MergeCtx &triangleMrgCtx); void spanTriangleMotionInfo ( PredictionUnit &pu, MergeCtx &triangleMrgCtx, const bool splitDir, const uint8_t candIdx0, const uint8_t candIdx1); int32_t mappingRefPic (const PredictionUnit &pu, int32_t refPicPoc, bool targetRefPicList); +#else + void getGeoMergeCandidates (const PredictionUnit &pu, MergeCtx &GeoMrgCtx); + void spanGeoMotionInfo ( PredictionUnit &pu, MergeCtx &GeoMrgCtx, const uint8_t splitDir, const uint8_t candIdx0, const uint8_t candIdx1); +#endif bool isAddNeighborMv (const Mv& currMv, Mv* neighborMvs, int numNeighborMv); void getIbcMVPsEncOnly(PredictionUnit &pu, Mv* mvPred, int& nbPred); bool getDerivedBV(PredictionUnit &pu, const Mv& currentMv, Mv& derivedMv); diff --git a/source/Lib/CommonLib/dtrace_blockstatistics.cpp b/source/Lib/CommonLib/dtrace_blockstatistics.cpp index 8005a537f..4338f027a 100644 --- a/source/Lib/CommonLib/dtrace_blockstatistics.cpp +++ b/source/Lib/CommonLib/dtrace_blockstatistics.cpp @@ -271,6 +271,7 @@ void CDTrace::dtrace_polygon_vector(int k, int poc, const std::vector<Position> dtrace<false>(k, "BlockStat: POC %d @[%s] %s={%4d,%4d}\n", poc, polygonDescription.c_str(), stat_type.c_str(), val_x, val_y); } +#if !JVET_Q0806 void retrieveTriangularMvInfo(const PredictionUnit& pu, MotionInfo& mi0, MotionInfo& mi1) { int triangleDir = pu.triangleSplitDir; @@ -358,6 +359,7 @@ void retrieveTrianglePolygon(const PredictionUnit& pu, std::vector<Position>& tr CHECK(triangleDir != TRIANGLE_DIR_45 && triangleDir != TRIANGLE_DIR_135, "Unknown triangle type"); } } +#endif void writeBlockStatisticsHeader(const SPS *sps) { @@ -493,7 +495,11 @@ void writeAllData(const CodingStructure& cs, const UnitArea& ctuArea) DTRACE_BLOCK_SCALAR(g_trace_ctx, D_BLOCK_STATISTICS_ALL, pu, GetBlockStatisticName(BlockStatistic::MVPIdxL1), pu.mvpIdx[REF_PIC_LIST_1]); DTRACE_BLOCK_SCALAR(g_trace_ctx, D_BLOCK_STATISTICS_ALL, pu, GetBlockStatisticName(BlockStatistic::RefIdxL1), pu.refIdx[REF_PIC_LIST_1]); } +#if !JVET_Q0806 if (!pu.cu->affine && !pu.cu->triangle) +#else + if (!pu.cu->affine && !pu.cu->geoFlag) +#endif { if (pu.interDir != 2 /* PRED_L1 */) { @@ -518,6 +524,7 @@ void writeAllData(const CodingStructure& cs, const UnitArea& ctuArea) DTRACE_BLOCK_VECTOR(g_trace_ctx, D_BLOCK_STATISTICS_ALL, pu, GetBlockStatisticName(BlockStatistic::MVL1), mv.hor, mv.ver); } } +#if !JVET_Q0806 else if (pu.cu->triangle) { MotionInfo mi[2]; @@ -539,6 +546,7 @@ void writeAllData(const CodingStructure& cs, const UnitArea& ctuArea) } } } +#endif else { if (pu.interDir != 2 /* PRED_L1 */) @@ -864,7 +872,11 @@ void writeAllCodedData(const CodingStructure & cs, const UnitArea & ctuArea) DTRACE_BLOCK_SCALAR(g_trace_ctx, D_BLOCK_STATISTICS_CODED, pu, GetBlockStatisticName(BlockStatistic::MVPIdxL1), pu.mvpIdx[REF_PIC_LIST_1]); DTRACE_BLOCK_SCALAR(g_trace_ctx, D_BLOCK_STATISTICS_CODED, pu, GetBlockStatisticName(BlockStatistic::RefIdxL1), pu.refIdx[REF_PIC_LIST_1]); } +#if !JVET_Q0806 if (!pu.cu->affine && !pu.cu->triangle) +#else + if (!pu.cu->affine && !pu.cu->geoFlag) +#endif { if (pu.interDir != 2 /* PRED_L1 */) { @@ -889,6 +901,7 @@ void writeAllCodedData(const CodingStructure & cs, const UnitArea & ctuArea) DTRACE_BLOCK_VECTOR(g_trace_ctx, D_BLOCK_STATISTICS_CODED, pu, GetBlockStatisticName(BlockStatistic::MVL1), mv.hor, mv.ver); } } +#if !JVET_Q0806 else if (pu.cu->triangle) { MotionInfo mi[2]; @@ -910,6 +923,7 @@ void writeAllCodedData(const CodingStructure & cs, const UnitArea & ctuArea) } } } +#endif else { if (pu.interDir != 2 /* PRED_L1 */) diff --git a/source/Lib/CommonLib/dtrace_blockstatistics.h b/source/Lib/CommonLib/dtrace_blockstatistics.h index 2df8b9b3a..84c7fe18a 100644 --- a/source/Lib/CommonLib/dtrace_blockstatistics.h +++ b/source/Lib/CommonLib/dtrace_blockstatistics.h @@ -118,10 +118,16 @@ enum class BlockStatistic { MMVDMergeIdx, CiipFlag, SMVDFlag, +#if !JVET_Q0806 TrianglePartitioning, TriangleMVL0, //<< currently only uni-prediction enabled TriangleMVL1, //<< currently only uni-prediction enabled BCWIndex, +#else + GeoPartitioning, + GeoMVL0, //<< currently only uni-prediction enabled + GeoMVL1, //<< currently only uni-prediction enabled +#endif // for dual tree // general Depth_Chroma, @@ -212,10 +218,16 @@ static const std::map<BlockStatistic, std::tuple<std::string, BlockStatisticType { BlockStatistic::MMVDMergeIdx, std::tuple<std::string, BlockStatisticType, std::string>{"MMVDMergeIdx", BlockStatisticType::Integer, "[0, 1]"}}, { BlockStatistic::CiipFlag, std::tuple<std::string, BlockStatisticType, std::string>{"CiipFlag", BlockStatisticType::Flag, ""}}, { BlockStatistic::SMVDFlag, std::tuple<std::string, BlockStatisticType, std::string>{"SMVDFlag", BlockStatisticType::Flag, ""}}, +#if !JVET_Q0806 { BlockStatistic::TrianglePartitioning, std::tuple<std::string, BlockStatisticType, std::string>{"TrianglePartitioning", BlockStatisticType::Line, ""}}, { BlockStatistic::TriangleMVL0, std::tuple<std::string, BlockStatisticType, std::string>{"TriangleMVL0", BlockStatisticType::VectorPolygon, "Scale: 4"}}, { BlockStatistic::TriangleMVL1, std::tuple<std::string, BlockStatisticType, std::string>{"TriangleMVL1", BlockStatisticType::VectorPolygon, "Scale: 4"}}, { BlockStatistic::BCWIndex, std::tuple<std::string, BlockStatisticType, std::string>{"BCWIndex", BlockStatisticType::Integer, "[0, 4]"}}, +#else + { BlockStatistic::GeoPartitioning, std::tuple<std::string, BlockStatisticType, std::string>{"GeoPartitioning", BlockStatisticType::Line, ""} }, + { BlockStatistic::GeoMVL0, std::tuple<std::string, BlockStatisticType, std::string>{"GeoMVL0", BlockStatisticType::VectorPolygon, "Scale: 4"} }, + { BlockStatistic::GeoMVL1, std::tuple<std::string, BlockStatisticType, std::string>{"GeoMVL1", BlockStatisticType::VectorPolygon, "Scale: 4"} }, +#endif // for dual tree { BlockStatistic::Depth_Chroma, std::tuple<std::string, BlockStatisticType, std::string>{"Depth_Chroma", BlockStatisticType::Integer, "[0, 10]"}}, // todo: actual limits? { BlockStatistic::QT_Depth_Chroma, std::tuple<std::string, BlockStatisticType, std::string>{"QT_Depth_Chroma", BlockStatisticType::Integer, "[0, 10]"}}, // todo: actual limits? diff --git a/source/Lib/CommonLib/x86/InterpolationFilterX86.h b/source/Lib/CommonLib/x86/InterpolationFilterX86.h index 2b5bda2df..8ce78e808 100644 --- a/source/Lib/CommonLib/x86/InterpolationFilterX86.h +++ b/source/Lib/CommonLib/x86/InterpolationFilterX86.h @@ -1327,6 +1327,7 @@ static void simdFilter( const ClpRng& clpRng, Pel const *src, int srcStride, Pel } } +#if !JVET_Q0806 template< X86_VEXT vext > void xWeightedTriangleBlk_SSE(const PredictionUnit &pu, const uint32_t width, const uint32_t height, const ComponentID compIdx, const bool splitDir, PelUnitBuf& predDst, PelUnitBuf& predSrc0, PelUnitBuf& predSrc1) { @@ -1449,6 +1450,229 @@ void xWeightedTriangleBlk_SSE(const PredictionUnit &pu, const uint32_t width, co } } } +#else +template< X86_VEXT vext > +void xWeightedGeoBlk_SSE(const PredictionUnit &pu, const uint32_t width, const uint32_t height, const ComponentID compIdx, const uint8_t splitDir, PelUnitBuf& predDst, PelUnitBuf& predSrc0, PelUnitBuf& predSrc1) +{ + Pel* dst = predDst.get(compIdx).buf; + Pel* src0 = predSrc0.get(compIdx).buf; + Pel* src1 = predSrc1.get(compIdx).buf; + int32_t strideDst = predDst.get(compIdx).stride; + int32_t strideSrc0 = predSrc0.get(compIdx).stride; + int32_t strideSrc1 = predSrc1.get(compIdx).stride; + + const char log2WeightBase = 3; + const ClpRng clpRng = pu.cu->slice->clpRngs().comp[compIdx]; + const int32_t shiftWeighted = std::max<int>(2, (IF_INTERNAL_PREC - clpRng.bd)) + log2WeightBase; + const int32_t offsetWeighted = (1 << (shiftWeighted - 1)) + (IF_INTERNAL_OFFS << log2WeightBase); + + int16_t wIdx = floorLog2(pu.lwidth() ) - GEO_MIN_CU_LOG2; + int16_t hIdx = floorLog2(pu.lheight()) - GEO_MIN_CU_LOG2; + int16_t angle = g_GeoParams[splitDir][0]; + int16_t stepY = 0; + int16_t* weight = nullptr; + if (g_angle2mirror[angle] == 2) + { + stepY = -GEO_WEIGHT_MASK_SIZE; + weight = &g_globalGeoWeights[g_angle2mask[angle]][(GEO_WEIGHT_MASK_SIZE - 1 - g_weightOffset[splitDir][hIdx][wIdx][1]) * GEO_WEIGHT_MASK_SIZE + g_weightOffset[splitDir][hIdx][wIdx][0]]; + } + else if (g_angle2mirror[angle] == 1) + { + stepY = GEO_WEIGHT_MASK_SIZE; + weight = &g_globalGeoWeights[g_angle2mask[angle]][g_weightOffset[splitDir][hIdx][wIdx][1] * GEO_WEIGHT_MASK_SIZE + (GEO_WEIGHT_MASK_SIZE - 1 - g_weightOffset[splitDir][hIdx][wIdx][0])]; + } + else + { + stepY = GEO_WEIGHT_MASK_SIZE; + weight = &g_globalGeoWeights[g_angle2mask[angle]][g_weightOffset[splitDir][hIdx][wIdx][1] * GEO_WEIGHT_MASK_SIZE + g_weightOffset[splitDir][hIdx][wIdx][0]]; + } + + const __m128i mmEight = _mm_set1_epi16(8); + const __m128i mmOffset = _mm_set1_epi32(offsetWeighted); + const __m128i mmShift = _mm_cvtsi32_si128(shiftWeighted); + const __m128i mmMin = _mm_set1_epi16(clpRng.min); + const __m128i mmMax = _mm_set1_epi16(clpRng.max); + + if (compIdx != COMPONENT_Y && pu.chromaFormat== CHROMA_420) + stepY <<= 1; + if( width == 4 ) + { + // it will occur to chroma only + for( int y = 0; y < height; y++ ) + { + __m128i s0 = _mm_loadl_epi64((__m128i *) (src0)); + __m128i s1 = _mm_loadl_epi64((__m128i *) (src1)); + __m128i w0; + if (g_angle2mirror[angle] == 1) + { + w0 = _mm_loadu_si128((__m128i *) (weight - (8 - 1))); + const __m128i shuffle_mask = _mm_set_epi8(1, 0, 3, 2, 5, 4, 7, 6, 9, 8, 11, 10, 13, 12, 15, 14); + w0 = _mm_shuffle_epi8(w0, shuffle_mask); + } + else + { + w0 = _mm_loadu_si128((__m128i *) (weight)); + } + const __m128i mask = _mm_set_epi16(0, 1, 0, 1, 0, 1, 0, 1); + w0 = _mm_mullo_epi16(w0, mask); + w0 = _mm_packs_epi32(w0, _mm_setzero_si128()); + __m128i w1 = _mm_sub_epi16(mmEight, w0); + s0 = _mm_unpacklo_epi16(s0, s1); + w0 = _mm_unpacklo_epi16(w0, w1); + s0 = _mm_add_epi32(_mm_madd_epi16(s0, w0), mmOffset); + s0 = _mm_sra_epi32(s0, mmShift); + s0 = _mm_packs_epi32(s0, s0); + s0 = _mm_min_epi16(mmMax, _mm_max_epi16(s0, mmMin)); + _mm_storel_epi64((__m128i *) (dst), s0); + dst += strideDst; + src0 += strideSrc0; + src1 += strideSrc1; + weight += stepY; + } + } +#if USE_AVX2 + else if (width >= 16) + { + const __m256i mmEightAVX2 = _mm256_set1_epi16(8); + const __m256i mmOffsetAVX2 = _mm256_set1_epi32(offsetWeighted); + const __m256i mmMinAVX2 = _mm256_set1_epi16(clpRng.min); + const __m256i mmMaxAVX2 = _mm256_set1_epi16(clpRng.max); + for (int y = 0; y < height; y++) + { + for (int x = 0; x < width; x += 16) + { + __m256i s0 = _mm256_lddqu_si256((__m256i *) (src0 + x)); // why not aligned with 128/256 bit boundaries + __m256i s1 = _mm256_lddqu_si256((__m256i *) (src1 + x)); + + __m256i w0 = _mm256_lddqu_si256((__m256i *) (weight + x)); + if (compIdx != COMPONENT_Y && pu.chromaFormat != CHROMA_444) + { + const __m256i mask = _mm256_set_epi16(0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1); + __m256i w0p0, w0p1; + if (g_angle2mirror[angle] == 1) + { + w0p0 = _mm256_lddqu_si256((__m256i *) (weight - (x << 1) - (16 - 1))); // first sub-sample the required weights. + w0p1 = _mm256_lddqu_si256((__m256i *) (weight - (x << 1) - 16 - (16 - 1))); + const __m256i shuffle_mask = _mm256_set_epi8(1, 0, 3, 2, 5, 4, 7, 6, 9, 8, 11, 10, 13, 12, 15, 14, 1, 0, 3, 2, 5, 4, 7, 6, 9, 8, 11, 10, 13, 12, 15, 14); + w0p0 = _mm256_shuffle_epi8(w0p0, shuffle_mask); + w0p0 = _mm256_permute4x64_epi64(w0p0, _MM_SHUFFLE(1, 0, 3, 2)); + w0p1 = _mm256_shuffle_epi8(w0p1, shuffle_mask); + w0p1 = _mm256_permute4x64_epi64(w0p1, _MM_SHUFFLE(1, 0, 3, 2)); + } + else + { + w0p0 = _mm256_lddqu_si256((__m256i *) (weight + (x << 1))); // first sub-sample the required weights. + w0p1 = _mm256_lddqu_si256((__m256i *) (weight + (x << 1) + 16)); + } + w0p0 = _mm256_mullo_epi16(w0p0, mask); + w0p1 = _mm256_mullo_epi16(w0p1, mask); + w0 = _mm256_packs_epi16(w0p0, w0p1); + w0 = _mm256_permute4x64_epi64(w0, _MM_SHUFFLE(3, 1, 2, 0)); + } + else + { + if (g_angle2mirror[angle] == 1) + { + w0 = _mm256_lddqu_si256((__m256i *) (weight - x - (16 - 1))); + const __m256i shuffle_mask = _mm256_set_epi8(1, 0, 3, 2, 5, 4, 7, 6, 9, 8, 11, 10, 13, 12, 15, 14, 1, 0, 3, 2, 5, 4, 7, 6, 9, 8, 11, 10, 13, 12, 15, 14); + w0 = _mm256_shuffle_epi8(w0, shuffle_mask); + w0 = _mm256_permute4x64_epi64(w0, _MM_SHUFFLE(1, 0, 3, 2)); + } + else + { + w0 = _mm256_lddqu_si256((__m256i *) (weight + x)); + } + } + __m256i w1 = _mm256_sub_epi16(mmEightAVX2, w0); + + __m256i s0tmp = _mm256_unpacklo_epi16(s0, s1); + __m256i w0tmp = _mm256_unpacklo_epi16(w0, w1); + s0tmp = _mm256_add_epi32(_mm256_madd_epi16(s0tmp, w0tmp), mmOffsetAVX2); + s0tmp = _mm256_sra_epi32(s0tmp, mmShift); + + s0 = _mm256_unpackhi_epi16(s0, s1); + w0 = _mm256_unpackhi_epi16(w0, w1); + s0 = _mm256_add_epi32(_mm256_madd_epi16(s0, w0), mmOffsetAVX2); + s0 = _mm256_sra_epi32(s0, mmShift); + + s0 = _mm256_packs_epi32(s0tmp, s0); + s0 = _mm256_min_epi16(mmMaxAVX2, _mm256_max_epi16(s0, mmMinAVX2)); + _mm256_storeu_si256((__m256i *) (dst + x), s0); + } + dst += strideDst; + src0 += strideSrc0; + src1 += strideSrc1; + weight += stepY; + } + } +#endif + else + { + for( int y = 0; y < height; y++ ) + { + for( int x = 0; x < width; x += 8 ) + { + __m128i s0 = _mm_lddqu_si128 ((__m128i *) (src0 + x)); + __m128i s1 = _mm_lddqu_si128 ((__m128i *) (src1 + x)); + __m128i w0; + if (compIdx != COMPONENT_Y && pu.chromaFormat != CHROMA_444) + { + const __m128i mask = _mm_set_epi16(0, 1, 0, 1, 0, 1, 0, 1); + __m128i w0p0,w0p1; + if (g_angle2mirror[angle] == 1) + { + w0p0 = _mm_lddqu_si128 ((__m128i *) (weight - (x << 1) - (8 - 1))); // first sub-sample the required weights. + w0p1 = _mm_lddqu_si128 ((__m128i *) (weight - (x << 1) - 8 - (8 - 1))); + const __m128i shuffle_mask = _mm_set_epi8(1, 0, 3, 2, 5, 4, 7, 6, 9, 8, 11, 10, 13, 12, 15, 14); + w0p0 = _mm_shuffle_epi8(w0p0, shuffle_mask); + w0p1 = _mm_shuffle_epi8(w0p1, shuffle_mask); + } + else + { + w0p0 = _mm_lddqu_si128 ((__m128i *) (weight + (x << 1) ) ); // first sub-sample the required weights. + w0p1 = _mm_lddqu_si128 ((__m128i *) (weight + (x << 1) + 8) ); + } + w0p0 = _mm_mullo_epi16(w0p0, mask); + w0p1 = _mm_mullo_epi16(w0p1, mask); + w0 = _mm_packs_epi32(w0p0, w0p1); + } + else + { + if ( g_angle2mirror[angle] == 1) + { + w0 = _mm_lddqu_si128 ((__m128i *) (weight - x - (8 - 1) ) ); + const __m128i shuffle_mask = _mm_set_epi8(1, 0, 3, 2, 5, 4, 7, 6, 9, 8, 11, 10, 13, 12, 15, 14); + w0 = _mm_shuffle_epi8(w0, shuffle_mask); + } + else + { + w0 = _mm_lddqu_si128((__m128i *) (weight + x)); + } + } + __m128i w1 = _mm_sub_epi16(mmEight, w0); + + __m128i s0tmp = _mm_unpacklo_epi16(s0, s1); + __m128i w0tmp = _mm_unpacklo_epi16(w0, w1); + s0tmp = _mm_add_epi32(_mm_madd_epi16(s0tmp, w0tmp), mmOffset); + s0tmp = _mm_sra_epi32(s0tmp, mmShift); + + s0 = _mm_unpackhi_epi16(s0, s1); + w0 = _mm_unpackhi_epi16(w0, w1); + s0 = _mm_add_epi32(_mm_madd_epi16(s0, w0), mmOffset); + s0 = _mm_sra_epi32(s0, mmShift); + + s0 = _mm_packs_epi32(s0tmp, s0); + s0 = _mm_min_epi16(mmMax, _mm_max_epi16(s0, mmMin)); + _mm_storeu_si128((__m128i *) (dst + x), s0); + } + dst += strideDst; + src0 += strideSrc0; + src1 += strideSrc1; + weight += stepY; + } + } +} +#endif template <X86_VEXT vext> void InterpolationFilter::_initInterpolationFilterX86() @@ -1489,7 +1713,11 @@ void InterpolationFilter::_initInterpolationFilterX86() m_filterCopy[1][0] = simdFilterCopy<vext, true, false>; m_filterCopy[1][1] = simdFilterCopy<vext, true, true>; +#if !JVET_Q0806 m_weightedTriangleBlk = xWeightedTriangleBlk_SSE<vext>; +#else + m_weightedGeoBlk = xWeightedGeoBlk_SSE<vext>; +#endif } template void InterpolationFilter::_initInterpolationFilterX86<SIMDX86>(); diff --git a/source/Lib/CommonLib/x86/RdCostX86.h b/source/Lib/CommonLib/x86/RdCostX86.h index b5e3288be..3bdfec3f7 100644 --- a/source/Lib/CommonLib/x86/RdCostX86.h +++ b/source/Lib/CommonLib/x86/RdCostX86.h @@ -1973,6 +1973,97 @@ static uint32_t xCalcHAD8x16_AVX2( const Pel* piOrg, const Pel* piCur, const int return (sad); } +#if JVET_Q0806 +template< X86_VEXT vext > +Distortion RdCost::xGetSADwMask_SIMD( const DistParam &rcDtParam ) +{ + if (rcDtParam.org.width < 4 || rcDtParam.bitDepth > 10 || rcDtParam.applyWeight) + return RdCost::xGetSADwMask( rcDtParam ); + + const short* src1 = (const short*)rcDtParam.org.buf; + const short* src2 = (const short*)rcDtParam.cur.buf; + const short* weightMask = (const short*)rcDtParam.mask; + int rows = rcDtParam.org.height; + int cols = rcDtParam.org.width; + int subShift = rcDtParam.subShift; + int subStep = ( 1 << subShift); + const int strideSrc1 = rcDtParam.org.stride * subStep; + const int strideSrc2 = rcDtParam.cur.stride * subStep; + const int strideMask = rcDtParam.maskStride * subStep; + + Distortion sum = 0; + if( vext >= AVX2 && (cols & 15 ) == 0 ) + { +#ifdef USE_AVX2 + // Do for width that multiple of 16 + __m256i vzero = _mm256_setzero_si256(); + __m256i vsum32 = vzero; + for( int y = 0; y < rows; y+= subStep) + { + for( int x = 0; x < cols; x+=16 ) + { + __m256i vsrc1 = _mm256_lddqu_si256( ( __m256i* )( &src1[x] ) ); + __m256i vsrc2 = _mm256_lddqu_si256( ( __m256i* )( &src2[x] ) ); + __m256i vmask; + if ( rcDtParam.stepX == -1 ) + { + vmask = _mm256_lddqu_si256((__m256i*)((&weightMask[x]) - (x << 1) - (16 - 1))); + const __m256i shuffle_mask = _mm256_set_epi8(1, 0, 3, 2, 5, 4, 7, 6, 9, 8, 11, 10, 13, 12, 15, 14, 1, 0, 3, 2, 5, 4, 7, 6, 9, 8, 11, 10, 13, 12, 15, 14); + vmask = _mm256_shuffle_epi8(vmask, shuffle_mask); + vmask = _mm256_permute4x64_epi64 (vmask, _MM_SHUFFLE(1, 0, 3, 2)); + } + else + { + vmask = _mm256_lddqu_si256((__m256i*)(&weightMask[x])); + } + vsum32 = _mm256_add_epi32( vsum32, _mm256_madd_epi16( vmask, _mm256_abs_epi16( _mm256_sub_epi16( vsrc1, vsrc2 ) ) ) ); + } + src1 += strideSrc1; + src2 += strideSrc2; + weightMask += strideMask; + } + vsum32 = _mm256_hadd_epi32( vsum32, vzero ); + vsum32 = _mm256_hadd_epi32( vsum32, vzero ); + sum = _mm_cvtsi128_si32( _mm256_castsi256_si128( vsum32 ) ) + _mm_cvtsi128_si32( _mm256_castsi256_si128( _mm256_permute2x128_si256( vsum32, vsum32, 0x11 ) ) ); +#endif + } + else + { + // Do with step of 8 + __m128i vzero = _mm_setzero_si128(); + __m128i vsum32 = vzero; + for( int y = 0; y < rows; y+= subStep) + { + for( int x = 0; x < cols; x+=8 ) + { + __m128i vsrc1 = _mm_loadu_si128( ( const __m128i* )( &src1[x] ) ); + __m128i vsrc2 = _mm_lddqu_si128( ( const __m128i* )( &src2[x] ) ); + __m128i vmask; + if (rcDtParam.stepX == -1) + { + vmask = _mm_lddqu_si128((__m128i*)((&weightMask[x]) - (x << 1) - (8 - 1))); + const __m128i shuffle_mask = _mm_set_epi8(1, 0, 3, 2, 5, 4, 7, 6, 9, 8, 11, 10, 13, 12, 15, 14); + vmask = _mm_shuffle_epi8(vmask, shuffle_mask); + } + else + { + vmask = _mm_lddqu_si128((const __m128i*)(&weightMask[x])); + } + vsum32 = _mm_add_epi32( vsum32, _mm_madd_epi16( vmask, _mm_abs_epi16( _mm_sub_epi16( vsrc1, vsrc2 ) ) ) ); + } + src1 += strideSrc1; + src2 += strideSrc2; + weightMask += strideMask; + } + vsum32 = _mm_hadd_epi32( vsum32, vzero ); + vsum32 = _mm_hadd_epi32( vsum32, vzero ); + sum = _mm_cvtsi128_si32( vsum32 ); + } + sum <<= subShift; + + return sum >> DISTORTION_PRECISION_ADJUSTMENT(rcDtParam.bitDepth); +} +#endif template<X86_VEXT vext> Distortion RdCost::xGetHADs_SIMD( const DistParam &rcDtParam ) @@ -2150,6 +2241,10 @@ void RdCost::_initRdCostX86() m_afpDistortFunc[DF_HAD16N] = RdCost::xGetHADs_SIMD<vext>; m_afpDistortFunc[DF_SAD_INTERMEDIATE_BITDEPTH] = RdCost::xGetSAD_IBD_SIMD<vext>; + +#if JVET_Q0806 + m_afpDistortFunc[DF_SAD_WITH_MASK] = xGetSADwMask_SIMD<vext>; +#endif } template void RdCost::_initRdCostX86<SIMDX86>(); diff --git a/source/Lib/DecoderLib/CABACReader.cpp b/source/Lib/DecoderLib/CABACReader.cpp index 2b6e06881..12222b372 100644 --- a/source/Lib/DecoderLib/CABACReader.cpp +++ b/source/Lib/DecoderLib/CABACReader.cpp @@ -2107,10 +2107,20 @@ void CABACReader::merge_data( PredictionUnit& pu ) } RExt__DECODER_DEBUG_BIT_STATISTICS_CREATE_SET( STATS__CABAC_BITS__MERGE_FLAG ); + +#if JVET_Q0806 + const bool ciipAvailable = pu.cs->sps->getUseCiip() && !pu.cu->skip && pu.cu->lwidth() < MAX_CU_SIZE && pu.cu->lheight() < MAX_CU_SIZE && pu.cu->lwidth() * pu.cu->lheight() >= 64; + const bool geoAvailable = pu.cu->cs->slice->getSPS()->getUseGeo() && pu.cu->cs->slice->isInterB() && pu.cu->cs->picHeader->getMaxNumGeoCand() > 1 + && pu.cu->lwidth() >= GEO_MIN_CU_SIZE && pu.cu->lheight() >= GEO_MIN_CU_SIZE + && pu.cu->lwidth() <= GEO_MAX_CU_SIZE && pu.cu->lheight() <= GEO_MAX_CU_SIZE + && pu.cu->lwidth() < 8 * pu.cu->lheight() && pu.cu->lheight() < 8 * pu.cu->lwidth(); + if (geoAvailable || ciipAvailable) +#else const bool triangleAvailable = pu.cu->cs->slice->getSPS()->getUseTriangle() && pu.cu->cs->slice->isInterB() && pu.cu->cs->picHeader->getMaxNumTriangleCand() > 1; const bool ciipAvailable = pu.cs->sps->getUseCiip() && !pu.cu->skip && pu.cu->lwidth() < MAX_CU_SIZE && pu.cu->lheight() < MAX_CU_SIZE; if (pu.cu->lwidth() * pu.cu->lheight() >= 64 && (triangleAvailable || ciipAvailable)) +#endif { cu.firstPU->regularMergeFlag = m_BinDecoder.decodeBin(Ctx::RegularMergeFlag(cu.skip ? 0 : 1)); } @@ -2123,6 +2133,7 @@ void CABACReader::merge_data( PredictionUnit& pu ) if (cu.cs->slice->getSPS()->getUseMMVD()) { cu.firstPU->mmvdMergeFlag = m_BinDecoder.decodeBin(Ctx::MmvdFlag(0)); + DTRACE(g_trace_ctx, D_SYNTAX, "mmvd_merge_flag() mmvd_merge=%d pos=(%d,%d) size=%dx%d\n", pu.mmvdMergeFlag ? 1 : 0, pu.lumaPos().x, pu.lumaPos().y, pu.lumaSize().width, pu.lumaSize().height); } else { @@ -2137,6 +2148,7 @@ void CABACReader::merge_data( PredictionUnit& pu ) { pu.mmvdMergeFlag = false; pu.cu->mmvdSkip = false; +#if !JVET_Q0806 if (triangleAvailable && ciipAvailable) { Ciip_flag(pu); @@ -2158,6 +2170,29 @@ void CABACReader::merge_data( PredictionUnit& pu ) { pu.cu->triangle = true; } +#else + if (geoAvailable && ciipAvailable) + { + Ciip_flag(pu); + } + else if (ciipAvailable) + { + pu.ciipFlag = true; + } + else + { + pu.ciipFlag = false; + } + if (pu.ciipFlag) + { + pu.intraDir[0] = PLANAR_IDX; + pu.intraDir[1] = DM_CHROMA_IDX; + } + else + { + pu.cu->geoFlag = true; + } +#endif } } if (pu.mmvdMergeFlag || pu.cu->mmvdSkip) @@ -2200,6 +2235,7 @@ void CABACReader::merge_idx( PredictionUnit& pu ) int numCandminus1 = int( pu.cs->picHeader->getMaxNumMergeCand() ) - 1; pu.mergeIdx = 0; +#if !JVET_Q0806 if( pu.cu->triangle ) { RExt__DECODER_DEBUG_BIT_STATISTICS_CREATE_SET( STATS__CABAC_BITS__TRIANGLE_INDEX ); @@ -2237,6 +2273,40 @@ void CABACReader::merge_idx( PredictionUnit& pu ) pu.triangleMergeIdx1 = candIdx1; return; } +#else + if( pu.cu->geoFlag ) + { + RExt__DECODER_DEBUG_BIT_STATISTICS_CREATE_SET( STATS__CABAC_BITS__GEO_INDEX ); + uint32_t splitDir = 0; + xReadTruncBinCode(splitDir, GEO_NUM_PARTITION_MODE); + pu.geoSplitDir = splitDir; + const int maxNumGeoCand = pu.cs->picHeader->getMaxNumGeoCand(); + CHECK(maxNumGeoCand < 2, "Incorrect max number of geo candidates"); + CHECK(pu.cu->lheight() > 64 || pu.cu->lwidth() > 64, "Incorrect block size of geo flag"); + int numCandminus2 = maxNumGeoCand - 2; + pu.mergeIdx = 0; + int mergeCand0 = 0; + int mergeCand1 = 0; + if( m_BinDecoder.decodeBin( Ctx::MergeIdx() ) ) + { + mergeCand0 += unary_max_eqprob(numCandminus2) + 1;; + } + if (numCandminus2 > 0) + { + if (m_BinDecoder.decodeBin(Ctx::MergeIdx())) + { + mergeCand1 += unary_max_eqprob(numCandminus2 - 1) + 1;; + } + } + mergeCand1 += mergeCand1 >= mergeCand0 ? 1 : 0; + pu.geoMergeIdx0 = mergeCand0; + pu.geoMergeIdx1 = mergeCand1; + DTRACE( g_trace_ctx, D_SYNTAX, "merge_idx() geo_split_dir=%d\n", splitDir ); + DTRACE( g_trace_ctx, D_SYNTAX, "merge_idx() geo_idx0=%d\n", mergeCand0 ); + DTRACE( g_trace_ctx, D_SYNTAX, "merge_idx() geo_idx1=%d\n", mergeCand1 ); + return; + } +#endif if (pu.cu->predMode == MODE_IBC) { diff --git a/source/Lib/DecoderLib/DecCu.cpp b/source/Lib/DecoderLib/DecCu.cpp index 3b9612819..be16916a2 100644 --- a/source/Lib/DecoderLib/DecCu.cpp +++ b/source/Lib/DecoderLib/DecCu.cpp @@ -636,6 +636,7 @@ void DecCu::xFillPCMBuffer(CodingUnit &cu) void DecCu::xReconInter(CodingUnit &cu) { +#if !JVET_Q0806 if( cu.triangle ) { const bool splitDir = cu.firstPU->triangleSplitDir; @@ -645,13 +646,25 @@ void DecCu::xReconInter(CodingUnit &cu) PU::spanTriangleMotionInfo( *cu.firstPU, m_triangleMrgCtx, splitDir, candIdx0, candIdx1 ); } else +#else + if( cu.geoFlag ) + { + m_pcInterPred->motionCompensationGeo( cu, m_geoMrgCtx ); + PU::spanGeoMotionInfo( *cu.firstPU, m_geoMrgCtx, cu.firstPU->geoSplitDir, cu.firstPU->geoMergeIdx0, cu.firstPU->geoMergeIdx1 ); + } + else +#endif { m_pcIntraPred->geneIntrainterPred(cu); // inter prediction CHECK(CU::isIBC(cu) && cu.firstPU->ciipFlag, "IBC and Ciip cannot be used together"); CHECK(CU::isIBC(cu) && cu.affine, "IBC and Affine cannot be used together"); +#if !JVET_Q0806 CHECK(CU::isIBC(cu) && cu.triangle, "IBC and triangle cannot be used together"); +#else + CHECK(CU::isIBC(cu) && cu.geoFlag, "IBC and geo cannot be used together"); +#endif CHECK(CU::isIBC(cu) && cu.firstPU->mmvdMergeFlag, "IBC and MMVD cannot be used together"); const bool luma = cu.Y().valid(); const bool chroma = cu.Cb().valid(); @@ -883,11 +896,19 @@ void DecCu::xDeriveCUMV( CodingUnit &cu ) else { { +#if !JVET_Q0806 if( pu.cu->triangle ) { PU::getTriangleMergeCandidates( pu, m_triangleMrgCtx ); } else +#else + if( pu.cu->geoFlag ) + { + PU::getGeoMergeCandidates( pu, m_geoMrgCtx ); + } + else +#endif { if( pu.cu->affine ) { @@ -1031,6 +1052,7 @@ void DecCu::xDeriveCUMV( CodingUnit &cu ) PU::spanMotionInfo( pu, mrgCtx ); } } +#if !JVET_Q0806 if( !cu.triangle ) { if( g_mctsDecCheckEnabled && !MCTSHelper::checkMvBufferForMCTSConstraint( pu, true ) ) @@ -1038,6 +1060,15 @@ void DecCu::xDeriveCUMV( CodingUnit &cu ) printf( "DECODER: pu motion vector across tile boundaries (%d,%d,%d,%d)\n", pu.lx(), pu.ly(), pu.lwidth(), pu.lheight() ); } } +#else + if( !cu.geoFlag ) + { + if( g_mctsDecCheckEnabled && !MCTSHelper::checkMvBufferForMCTSConstraint( pu, true ) ) + { + printf( "DECODER: pu motion vector across tile boundaries (%d,%d,%d,%d)\n", pu.lx(), pu.ly(), pu.lwidth(), pu.lheight() ); + } + } +#endif if (CU::isIBC(cu)) { const int cuPelX = pu.Y().x; diff --git a/source/Lib/DecoderLib/DecCu.h b/source/Lib/DecoderLib/DecCu.h index 2cbb597a9..c6932f3e9 100644 --- a/source/Lib/DecoderLib/DecCu.h +++ b/source/Lib/DecoderLib/DecCu.h @@ -98,7 +98,11 @@ private: MotionInfo m_SubPuMiBuf[(MAX_CU_SIZE * MAX_CU_SIZE) >> (MIN_CU_LOG2 << 1)]; +#if !JVET_Q0806 MergeCtx m_triangleMrgCtx; +#else + MergeCtx m_geoMrgCtx; +#endif }; //! \} diff --git a/source/Lib/DecoderLib/VLCReader.cpp b/source/Lib/DecoderLib/VLCReader.cpp index fd516bb03..74caa3ae2 100644 --- a/source/Lib/DecoderLib/VLCReader.cpp +++ b/source/Lib/DecoderLib/VLCReader.cpp @@ -698,7 +698,11 @@ void HLSyntaxReader::parsePPS( PPS* pcPPS, ParameterSetManager *parameterSetMana READ_CODE( 2, uiCode, "pps_mvd_l1_zero_idc"); pcPPS->setPPSMvdL1ZeroIdc(uiCode); READ_CODE( 2, uiCode, "pps_collocated_from_l0_idc"); pcPPS->setPPSCollocatedFromL0Idc(uiCode); READ_UVLC( uiCode, "pps_six_minus_max_num_merge_cand_plus1"); pcPPS->setPPSSixMinusMaxNumMergeCandPlus1(uiCode); +#if !JVET_Q0806 READ_UVLC( uiCode, "pps_max_num_merge_cand_minus_max_num_triangle_cand_plus1");pcPPS->setPPSMaxNumMergeCandMinusMaxNumTriangleCandPlus1(uiCode); +#else + READ_UVLC(uiCode, "pps_max_num_merge_cand_minus_max_num_gpm_cand_plus1"); pcPPS->setPPSMaxNumMergeCandMinusMaxNumGeoCandPlus1(uiCode); +#endif } else { @@ -708,7 +712,11 @@ void HLSyntaxReader::parsePPS( PPS* pcPPS, ParameterSetManager *parameterSetMana pcPPS->setPPSMvdL1ZeroIdc(0); pcPPS->setPPSCollocatedFromL0Idc(0); pcPPS->setPPSSixMinusMaxNumMergeCandPlus1(0); +#if !JVET_Q0806 pcPPS->setPPSMaxNumMergeCandMinusMaxNumTriangleCandPlus1(0); +#else + pcPPS->setPPSMaxNumMergeCandMinusMaxNumGeoCandPlus1(0); +#endif } @@ -1449,7 +1457,11 @@ void HLSyntaxReader::parseSPS(SPS* pcSPS) READ_FLAG( uiCode, "sps_fpel_mmvd_enabled_flag" ); pcSPS->setFpelMmvdEnabledFlag ( uiCode != 0 ); } +#if !JVET_Q0806 READ_FLAG( uiCode, "triangle_flag" ); pcSPS->setUseTriangle ( uiCode != 0 ); +#else + READ_FLAG( uiCode, "sps_gpm_enabled_flag" ); pcSPS->setUseGeo ( uiCode != 0 ); +#endif READ_FLAG(uiCode, "sps_lmcs_enable_flag"); pcSPS->setUseLmcs(uiCode == 1); READ_FLAG( uiCode, "sps_lfnst_enabled_flag" ); pcSPS->setUseLFNST( uiCode != 0 ); @@ -2139,6 +2151,7 @@ void HLSyntaxReader::parsePictureHeader( PicHeader* picHeader, ParameterSetManag picHeader->setDisProfFlag(0); } +#if !JVET_Q0806 // triangle merge candidate list size if (sps->getUseTriangle() && picHeader->getMaxNumMergeCand() >= 2) { @@ -2157,6 +2170,26 @@ void HLSyntaxReader::parsePictureHeader( PicHeader* picHeader, ParameterSetManag { picHeader->setMaxNumTriangleCand(0); } +#else + // geometric merge candidate list size + if (sps->getUseGeo() && picHeader->getMaxNumMergeCand() >= 2) + { + if (!pps->getPPSMaxNumMergeCandMinusMaxNumGeoCandPlus1()) + { + READ_UVLC(uiCode, "pic_max_num_merge_cand_minus_max_num_gpm_cand"); + } + else + { + uiCode = pps->getPPSMaxNumMergeCandMinusMaxNumGeoCandPlus1() - 1; + } + CHECK(picHeader->getMaxNumMergeCand() < uiCode, "Incorrrect max number of gpm candidates!"); + picHeader->setMaxNumGeoCand((uint32_t)(picHeader->getMaxNumMergeCand() - uiCode)); + } + else + { + picHeader->setMaxNumGeoCand(0); + } +#endif // ibc merge candidate list size if (sps->getIBCFlag()) @@ -3146,7 +3179,11 @@ void HLSyntaxReader::parseConstraintInfo(ConstraintInfo *cinfo) READ_FLAG(symbol, "no_ibc_constraint_flag"); cinfo->setNoIbcConstraintFlag(symbol > 0 ? true : false); READ_FLAG(symbol, "no_ciip_constraint_flag"); cinfo->setNoCiipConstraintFlag(symbol > 0 ? true : false); READ_FLAG(symbol, "no_fpel_mmvd_constraint_flag"); cinfo->setNoFPelMmvdConstraintFlag(symbol > 0 ? true : false); +#if !JVET_Q0806 READ_FLAG(symbol, "no_triangle_constraint_flag"); cinfo->setNoTriangleConstraintFlag(symbol > 0 ? true : false); +#else + READ_FLAG(symbol, "no_gpm_constraint_flag"); cinfo->setNoGeoConstraintFlag(symbol > 0 ? true : false); +#endif READ_FLAG(symbol, "no_ladf_constraint_flag"); cinfo->setNoLadfConstraintFlag(symbol > 0 ? true : false); READ_FLAG(symbol, "no_transform_skip_constraint_flag"); cinfo->setNoTransformSkipConstraintFlag(symbol > 0 ? true : false); READ_FLAG(symbol, "no_bdpcm_constraint_flag"); cinfo->setNoBDPCMConstraintFlag(symbol > 0 ? true : false); diff --git a/source/Lib/EncoderLib/CABACWriter.cpp b/source/Lib/EncoderLib/CABACWriter.cpp index c814c521a..b4233271e 100644 --- a/source/Lib/EncoderLib/CABACWriter.cpp +++ b/source/Lib/EncoderLib/CABACWriter.cpp @@ -1864,10 +1864,19 @@ void CABACWriter::merge_data(const PredictionUnit& pu) merge_idx(pu); return; } +#if JVET_Q0806 + const bool ciipAvailable = pu.cs->sps->getUseCiip() && !pu.cu->skip && pu.cu->lwidth() < MAX_CU_SIZE && pu.cu->lheight() < MAX_CU_SIZE && pu.cu->lwidth() * pu.cu->lheight() >= 64; + const bool geoAvailable = pu.cu->cs->slice->getSPS()->getUseGeo() && pu.cu->cs->slice->isInterB() && pu.cu->cs->picHeader->getMaxNumGeoCand() > 1 + && pu.cu->lwidth() >= GEO_MIN_CU_SIZE && pu.cu->lheight() >= GEO_MIN_CU_SIZE + && pu.cu->lwidth() <= GEO_MAX_CU_SIZE && pu.cu->lheight() <= GEO_MAX_CU_SIZE + && pu.cu->lwidth() < 8 * pu.cu->lheight() && pu.cu->lheight() < 8 * pu.cu->lwidth(); + if (geoAvailable || ciipAvailable) +#else const bool triangleAvailable = pu.cu->cs->slice->getSPS()->getUseTriangle() && pu.cu->cs->slice->isInterB() && pu.cu->cs->picHeader->getMaxNumTriangleCand() > 1; const bool ciipAvailable = pu.cs->sps->getUseCiip() && !pu.cu->skip && pu.cu->lwidth() < MAX_CU_SIZE && pu.cu->lheight() < MAX_CU_SIZE; if (pu.cu->lwidth() * pu.cu->lheight() >= 64 && (triangleAvailable || ciipAvailable)) +#endif { m_BinEncoder.encodeBin(pu.regularMergeFlag, Ctx::RegularMergeFlag(pu.cu->skip ? 0 : 1)); } @@ -1889,10 +1898,17 @@ void CABACWriter::merge_data(const PredictionUnit& pu) } else { +#if !JVET_Q0806 if (triangleAvailable && ciipAvailable) { Ciip_flag(pu); } +#else + if (geoAvailable && ciipAvailable) + { + Ciip_flag(pu); + } +#endif merge_idx(pu); } } @@ -1993,6 +2009,7 @@ void CABACWriter::merge_idx( const PredictionUnit& pu ) } else { +#if !JVET_Q0806 if( pu.cu->triangle ) { bool splitDir = pu.triangleSplitDir; @@ -2036,6 +2053,38 @@ void CABACWriter::merge_idx( const PredictionUnit& pu ) encodeOneIdx(candIdx1, maxNumTriangleCand - 2); return; } +#else + if( pu.cu->geoFlag ) + { + uint8_t splitDir = pu.geoSplitDir; + uint8_t candIdx0 = pu.geoMergeIdx0; + uint8_t candIdx1 = pu.geoMergeIdx1; + DTRACE( g_trace_ctx, D_SYNTAX, "merge_idx() geo_split_dir=%d\n", splitDir ); + DTRACE( g_trace_ctx, D_SYNTAX, "merge_idx() geo_idx0=%d\n", candIdx0 ); + DTRACE( g_trace_ctx, D_SYNTAX, "merge_idx() geo_idx1=%d\n", candIdx1 ); + xWriteTruncBinCode(splitDir, GEO_NUM_PARTITION_MODE); + candIdx1 -= candIdx1 < candIdx0 ? 0 : 1; + const int maxNumGeoCand = pu.cs->picHeader->getMaxNumGeoCand(); + CHECK(maxNumGeoCand < 2, "Incorrect max number of geo candidates"); + CHECK(candIdx0 >= maxNumGeoCand, "Incorrect candIdx0"); + CHECK(candIdx1 >= maxNumGeoCand, "Incorrect candIdx1"); + int numCandminus2 = maxNumGeoCand - 2; + m_BinEncoder.encodeBin( candIdx0 == 0 ? 0 : 1, Ctx::MergeIdx() ); + if( candIdx0 > 0 ) + { + unary_max_eqprob(candIdx0 - 1, numCandminus2); + } + if (numCandminus2 > 0) + { + m_BinEncoder.encodeBin(candIdx1 == 0 ? 0 : 1, Ctx::MergeIdx()); + if (candIdx1 > 0) + { + unary_max_eqprob(candIdx1 - 1, numCandminus2 - 1); + } + } + return; + } +#endif int numCandminus1; if (pu.cu->predMode == MODE_IBC) numCandminus1 = int(pu.cs->picHeader->getMaxNumIBCMergeCand()) - 1; diff --git a/source/Lib/EncoderLib/EncCfg.h b/source/Lib/EncoderLib/EncCfg.h index f27bb3c10..673920133 100644 --- a/source/Lib/EncoderLib/EncCfg.h +++ b/source/Lib/EncoderLib/EncCfg.h @@ -185,7 +185,11 @@ protected: bool m_noIbcConstraintFlag; bool m_bNoCiipConstraintFlag; bool m_noFPelMmvdConstraintFlag; +#if !JVET_Q0806 bool m_bNoTriangleConstraintFlag; +#else + bool m_bNoGeoConstraintFlag; +#endif bool m_bNoLadfConstraintFlag; bool m_noTransformSkipConstraintFlag; bool m_noBDPCMConstraintFlag; @@ -298,7 +302,11 @@ protected: #endif bool m_ciip; +#if !JVET_Q0806 bool m_Triangle; +#else + bool m_Geo; +#endif bool m_allowDisFracMMVD; bool m_AffineAmvr; bool m_HashME; @@ -594,7 +602,11 @@ protected: WeightedPredictionMethod m_weightedPredictionMethod; uint32_t m_maxNumMergeCand; ///< Maximum number of merge candidates uint32_t m_maxNumAffineMergeCand; ///< Maximum number of affine merge candidates +#if !JVET_Q0806 uint32_t m_maxNumTriangleCand; +#else + uint32_t m_maxNumGeoCand; +#endif uint32_t m_maxNumIBCMergeCand; ///< Max number of IBC merge candidates ScalingListMode m_useScalingListId; ///< Using quantization matrix i.e. 0=off, 1=default, 2=file. std::string m_scalingListFileName; ///< quantization matrix file name @@ -611,7 +623,11 @@ protected: int m_PPSMvdL1ZeroIdc; int m_PPSCollocatedFromL0Idc; uint32_t m_PPSSixMinusMaxNumMergeCandPlus1; +#if !JVET_Q0806 uint32_t m_PPSMaxNumMergeCandMinusMaxNumTriangleCandPlus1; +#else + uint32_t m_PPSMaxNumMergeCandMinusMaxNumGeoCandPlus1; +#endif bool m_DepQuantEnabledFlag; bool m_SignDataHidingEnabledFlag; bool m_RCEnableRateControl; @@ -760,8 +776,13 @@ public: void setNoCiipConstraintFlag(bool bVal) { m_bNoCiipConstraintFlag = bVal; } bool getNoFPelMmvdConstraintFlag() const { return m_noFPelMmvdConstraintFlag; } void setNoFPelMmvdConstraintFlag(bool bVal) { m_noFPelMmvdConstraintFlag = bVal; } +#if !JVET_Q0806 bool getNoTriangleConstraintFlag() const { return m_bNoTriangleConstraintFlag; } void setNoTriangleConstraintFlag(bool bVal) { m_bNoTriangleConstraintFlag = bVal; } +#else + bool getNoGeoConstraintFlag() const { return m_bNoGeoConstraintFlag; } + void setNoGeoConstraintFlag(bool bVal) { m_bNoGeoConstraintFlag = bVal; } +#endif bool getNoLadfConstraintFlag() const { return m_bNoLadfConstraintFlag; } void setNoLadfConstraintFlag(bool bVal) { m_bNoLadfConstraintFlag = bVal; } bool getNoTransformSkipConstraintFlag() const { return m_noTransformSkipConstraintFlag; } @@ -969,8 +990,13 @@ public: void setUseCiip ( bool b ) { m_ciip = b; } bool getUseCiip () const { return m_ciip; } +#if !JVET_Q0806 void setUseTriangle ( bool b ) { m_Triangle = b; } bool getUseTriangle () const { return m_Triangle; } +#else + void setUseGeo ( bool b ) { m_Geo = b; } + bool getUseGeo () const { return m_Geo; } +#endif void setAllowDisFracMMVD ( bool b ) { m_allowDisFracMMVD = b; } bool getAllowDisFracMMVD () const { return m_allowDisFracMMVD; } void setUseHashME ( bool b ) { m_HashME = b; } @@ -1585,8 +1611,13 @@ public: uint32_t getMaxNumMergeCand () { return m_maxNumMergeCand; } void setMaxNumAffineMergeCand ( uint32_t u ) { m_maxNumAffineMergeCand = u; } uint32_t getMaxNumAffineMergeCand () { return m_maxNumAffineMergeCand; } +#if !JVET_Q0806 void setMaxNumTriangleCand ( uint32_t u ) { m_maxNumTriangleCand = u; } uint32_t getMaxNumTriangleCand () { return m_maxNumTriangleCand; } +#else + void setMaxNumGeoCand ( uint32_t u ) { m_maxNumGeoCand = u; } + uint32_t getMaxNumGeoCand () { return m_maxNumGeoCand; } +#endif void setMaxNumIBCMergeCand ( uint32_t u ) { m_maxNumIBCMergeCand = u; } uint32_t getMaxNumIBCMergeCand () { return m_maxNumIBCMergeCand; } void setUseScalingListId ( ScalingListMode u ) { m_useScalingListId = u; } @@ -1619,8 +1650,13 @@ public: int getPPSCollocatedFromL0Idc () { return m_PPSCollocatedFromL0Idc; } void setPPSSixMinusMaxNumMergeCandPlus1 ( uint32_t u ) { m_PPSSixMinusMaxNumMergeCandPlus1 = u; } uint32_t getPPSSixMinusMaxNumMergeCandPlus1 () { return m_PPSSixMinusMaxNumMergeCandPlus1; } +#if !JVET_Q0806 void setPPSMaxNumMergeCandMinusMaxNumTriangleCandPlus1 ( uint32_t u ) { m_PPSMaxNumMergeCandMinusMaxNumTriangleCandPlus1 = u; } uint32_t getPPSMaxNumMergeCandMinusMaxNumTriangleCandPlus1 () { return m_PPSMaxNumMergeCandMinusMaxNumTriangleCandPlus1; } +#else + void setPPSMaxNumMergeCandMinusMaxNumGeoCandPlus1 ( uint32_t u ) { m_PPSMaxNumMergeCandMinusMaxNumGeoCandPlus1 = u; } + uint32_t getPPSMaxNumMergeCandMinusMaxNumGeoCandPlus1 () { return m_PPSMaxNumMergeCandMinusMaxNumGeoCandPlus1; } +#endif WeightedPredictionMethod getWeightedPredictionMethod() const { return m_weightedPredictionMethod; } void setWeightedPredictionMethod( WeightedPredictionMethod m ) { m_weightedPredictionMethod = m; } void setDepQuantEnabledFlag( bool b ) { m_DepQuantEnabledFlag = b; } diff --git a/source/Lib/EncoderLib/EncCu.cpp b/source/Lib/EncoderLib/EncCu.cpp index 664375b90..f629e8482 100644 --- a/source/Lib/EncoderLib/EncCu.cpp +++ b/source/Lib/EncoderLib/EncCu.cpp @@ -59,6 +59,7 @@ //! \{ // ==================================================================================================================== +#if !JVET_Q0806 EncCu::EncCu() : m_triangleModeTest { TriangleMotionInfo( 0, 1, 0 ), TriangleMotionInfo( 1, 0, 1 ), TriangleMotionInfo( 1, 0, 2 ), TriangleMotionInfo( 0, 0, 1 ), TriangleMotionInfo( 0, 2, 0 ), @@ -71,6 +72,18 @@ EncCu::EncCu() : m_triangleModeTest TriangleMotionInfo( 0, 3, 1 ), TriangleMotionInfo( 0, 2, 4 ), TriangleMotionInfo( 1, 2, 4 ), TriangleMotionInfo( 0, 4, 2 ), TriangleMotionInfo( 0, 3, 4 ), } {} +#else +EncCu::EncCu() : m_GeoModeTest +{ + GeoMotionInfo(0, 1), GeoMotionInfo(1, 0),GeoMotionInfo(0, 2), GeoMotionInfo(1, 2), GeoMotionInfo(2, 0), + GeoMotionInfo(2, 1), GeoMotionInfo(0, 3),GeoMotionInfo(1, 3), GeoMotionInfo(2, 3), GeoMotionInfo(3, 0), + GeoMotionInfo(3, 1), GeoMotionInfo(3, 2),GeoMotionInfo(0, 4), GeoMotionInfo(1, 4), GeoMotionInfo(2, 4), + GeoMotionInfo(3, 4), GeoMotionInfo(4, 0),GeoMotionInfo(4, 1), GeoMotionInfo(4, 2), GeoMotionInfo(4, 3), + GeoMotionInfo(0, 5), GeoMotionInfo(1, 5),GeoMotionInfo(2, 5), GeoMotionInfo(3, 5), GeoMotionInfo(4, 5), + GeoMotionInfo(5, 0), GeoMotionInfo(5, 1),GeoMotionInfo(5, 2), GeoMotionInfo(5, 3), GeoMotionInfo(5, 4) +} +{} +#endif void EncCu::create( EncCfg* encCfg ) { @@ -138,6 +151,7 @@ void EncCu::create( EncCfg* encCfg ) m_acRealMergeBuffer[ui].create(chromaFormat, Area(0, 0, uiMaxWidth, uiMaxHeight)); m_acMergeTmpBuffer[ui].create(chromaFormat, Area(0, 0, uiMaxWidth, uiMaxHeight)); } +#if !JVET_Q0806 const unsigned maxNumTriangleCand = encCfg->getMaxNumTriangleCand(); for (unsigned i = 0; i < maxNumTriangleCand; i++) { @@ -174,6 +188,12 @@ void EncCu::create( EncCfg* encCfg ) { m_acTriangleWeightedBuffer[ui].create( chromaFormat, Area( 0, 0, uiMaxWidth, uiMaxHeight ) ); } +#else + for( unsigned ui = 0; ui < GEO_MAX_TRY_WEIGHTED_SAD; ui++ ) + { + m_acGeoWeightedBuffer[ui].create( chromaFormat, Area( 0, 0, uiMaxWidth, uiMaxHeight ) ); + } +#endif m_CtxBuffer.resize( maxDepth ); m_CurrCtx = 0; @@ -237,10 +257,17 @@ void EncCu::destroy() m_acRealMergeBuffer[ui].destroy(); m_acMergeTmpBuffer[ui].destroy(); } +#if !JVET_Q0806 for( unsigned ui = 0; ui < TRIANGLE_MAX_NUM_CANDS; ui++ ) { m_acTriangleWeightedBuffer[ui].destroy(); } +#else + for (unsigned ui = 0; ui < GEO_MAX_TRY_WEIGHTED_SAD; ui++) + { + m_acGeoWeightedBuffer[ui].destroy(); + } +#endif } @@ -270,6 +297,10 @@ void EncCu::init( EncLib* pcEncLib, const SPS& sps PARL_PARAM( const int tId ) ) m_dataId = tId; #endif m_pcLoopFilter = pcEncLib->getLoopFilter(); +#if JVET_Q0806 + m_GeoCostList.init(GEO_NUM_PARTITION_MODE, m_pcEncCfg->getMaxNumGeoCand()); + m_AFFBestSATDCost = MAX_DOUBLE; +#endif DecCu::init( m_pcTrQuant, m_pcIntraSearch, m_pcInterSearch ); @@ -790,10 +821,17 @@ void EncCu::xCompressCU( CodingStructure*& tempCS, CodingStructure*& bestCS, Par if (cu) cu->mmvdSkip = cu->skip == false ? false : cu->mmvdSkip; } +#if !JVET_Q0806 else if( currTestMode.type == ETM_MERGE_TRIANGLE ) { xCheckRDCostMergeTriangle2Nx2N( tempCS, bestCS, partitioner, currTestMode ); } +#else + else if( currTestMode.type == ETM_MERGE_GEO ) + { + xCheckRDCostMergeGeo2Nx2N( tempCS, bestCS, partitioner, currTestMode ); + } +#endif else if( currTestMode.type == ETM_INTRA ) { if (slice.getSPS()->getUseColorTrans() && !CS::isDualITree(*tempCS)) @@ -2389,7 +2427,11 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& cu.tileIdx = tempCS->pps->getTileIdx( tempCS->area.lumaPos() ); cu.skip = false; cu.mmvdSkip = false; +#if !JVET_Q0806 cu.triangle = false; +#else + cu.geoFlag = false; +#endif //cu.affine cu.predMode = MODE_INTER; //cu.LICFlag @@ -2648,7 +2690,11 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& cu.tileIdx = tempCS->pps->getTileIdx( tempCS->area.lumaPos() ); cu.skip = false; cu.mmvdSkip = false; +#if !JVET_Q0806 cu.triangle = false; +#else + cu.geoFlag = false; +#endif //cu.affine cu.predMode = MODE_INTER; //cu.LICFlag @@ -2810,6 +2856,7 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& } } +#if !JVET_Q0806 void EncCu::xCheckRDCostMergeTriangle2Nx2N( CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &partitioner, const EncTestMode& encTestMode ) { const Slice &slice = *tempCS->slice; @@ -3031,6 +3078,293 @@ void EncCu::xCheckRDCostMergeTriangle2Nx2N( CodingStructure *&tempCS, CodingStru xCalDebCost( *bestCS, partitioner ); } } +#else +void EncCu::xCheckRDCostMergeGeo2Nx2N(CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &pm, const EncTestMode& encTestMode) +{ + const Slice &slice = *tempCS->slice; + CHECK(slice.getSliceType() == I_SLICE, "Merge modes not available for I-slices"); + + tempCS->initStructData(encTestMode.qp); + + MergeCtx mergeCtx; + const SPS &sps = *tempCS->sps; + + if( sps.getSBTMVPEnabledFlag() ) + { + Size bufSize = g_miScaling.scale(tempCS->area.lumaSize()); + mergeCtx.subPuMvpMiBuf = MotionBuf(m_SubPuMiBuf, bufSize); + } + + CodingUnit &cu = tempCS->addCU(tempCS->area, pm.chType); + pm.setCUData(cu); + cu.predMode = MODE_INTER; + cu.slice = tempCS->slice; + cu.tileIdx = tempCS->pps->getTileIdx(tempCS->area.lumaPos()); + cu.qp = encTestMode.qp; + cu.affine = false; + cu.mtsFlag = false; + cu.BcwIdx = BCW_DEFAULT; + cu.geoFlag = true; + cu.imv = 0; + cu.mmvdSkip = false; + cu.skip = false; + cu.mipFlag = false; + cu.bdpcmMode = 0; + + PredictionUnit &pu = tempCS->addPU(cu, pm.chType); + pu.mergeFlag = true; + pu.regularMergeFlag = false; + PU::getGeoMergeCandidates(pu, mergeCtx); + + GeoComboCostList comboList; + int bitsCandTB = (int)std::floor(std::log2((double)GEO_NUM_PARTITION_MODE)); + PelUnitBuf geoBuffer[MRG_MAX_NUM_CANDS]; + PelUnitBuf geoTempBuf[MRG_MAX_NUM_CANDS]; + PelUnitBuf geoCombinations[GEO_MAX_TRY_WEIGHTED_SAD]; + DistParam distParam; + + const UnitArea localUnitArea(tempCS->area.chromaFormat, Area(0, 0, tempCS->area.Y().width, tempCS->area.Y().height)); + const double sqrtLambdaForFirstPass = m_pcRdCost->getMotionLambda( ); + + uint8_t maxNumMergeCandidates = cu.cs->picHeader->getMaxNumGeoCand(); + DistParam distParamWholeBlk; + m_pcRdCost->setDistParam(distParamWholeBlk, tempCS->getOrgBuf().Y(), m_acMergeBuffer[0].Y().buf, m_acMergeBuffer[0].Y().stride, sps.getBitDepth(CHANNEL_TYPE_LUMA), COMPONENT_Y); + Distortion bestWholeBlkSad = MAX_UINT64; + double bestWholeBlkCost = MAX_DOUBLE; + Distortion *uiSadWholeBlk; + uiSadWholeBlk = new Distortion[maxNumMergeCandidates]; + int *pocMrg; + Mv *MrgMv; + bool *isSkipThisCand; + pocMrg = new int[maxNumMergeCandidates]; + MrgMv = new Mv[maxNumMergeCandidates]; + isSkipThisCand = new bool[maxNumMergeCandidates]; + for( int i = 0; i < maxNumMergeCandidates; i++ ) + isSkipThisCand[i] = false; + for( uint8_t mergeCand = 0; mergeCand < maxNumMergeCandidates; mergeCand++ ) + { + geoBuffer[mergeCand] = m_acMergeBuffer[mergeCand].getBuf(localUnitArea); + mergeCtx.setMergeInfo(pu, mergeCand); + int MrgList = mergeCtx.mvFieldNeighbours[(mergeCand << 1) + 0].refIdx == -1 ? 1 : 0; + RefPicList MrgeRefPicList = (MrgList ? REF_PIC_LIST_1 : REF_PIC_LIST_0); + int MrgrefIdx = mergeCtx.mvFieldNeighbours[(mergeCand << 1) + MrgList].refIdx; + pocMrg[mergeCand] = tempCS->slice->getRefPic(MrgeRefPicList, MrgrefIdx)->getPOC(); + MrgMv[mergeCand] = mergeCtx.mvFieldNeighbours[(mergeCand << 1) + MrgList].mv; + if( mergeCand ) + { + for (int i = 0; i < mergeCand ; i++) + { + if (pocMrg[mergeCand] == pocMrg[i] && MrgMv[mergeCand] == MrgMv[i]) + { + isSkipThisCand[mergeCand] = true; + break; + } + } + } + PU::spanMotionInfo(pu, mergeCtx); + if (m_pcEncCfg->getMCTSEncConstraint() && (!(MCTSHelper::checkMvBufferForMCTSConstraint(pu)))) + { + tempCS->initStructData(encTestMode.qp); + return; + } + m_pcInterSearch->motionCompensation(pu, geoBuffer[mergeCand]); + geoTempBuf[mergeCand] = m_acMergeTmpBuffer[mergeCand].getBuf(localUnitArea); + geoTempBuf[mergeCand].Y().copyFrom(geoBuffer[mergeCand].Y()); + geoTempBuf[mergeCand].Y().roundToOutputBitdepth(geoTempBuf[mergeCand].Y(), cu.slice->clpRng(COMPONENT_Y)); + distParamWholeBlk.cur.buf = geoTempBuf[mergeCand].Y().buf; + distParamWholeBlk.cur.stride = geoTempBuf[mergeCand].Y().stride; + uiSadWholeBlk[mergeCand] = distParamWholeBlk.distFunc(distParamWholeBlk); + if( uiSadWholeBlk[mergeCand] < bestWholeBlkSad ) + { + bestWholeBlkSad = uiSadWholeBlk[mergeCand]; + int bitsCand = mergeCand + 1; + bestWholeBlkCost = (double)bestWholeBlkSad + (double)bitsCand * sqrtLambdaForFirstPass; + } + } + bool isGeo = true; + for( uint8_t mergeCand = 1; mergeCand < maxNumMergeCandidates; mergeCand++ ) + { + isGeo &= isSkipThisCand[mergeCand]; + } + if(isGeo) + { + return; + } + + int wIdx = floorLog2(cu.lwidth() ) - GEO_MIN_CU_LOG2; + int hIdx = floorLog2(cu.lheight()) - GEO_MIN_CU_LOG2; + for( int splitDir = 0; splitDir < GEO_NUM_PARTITION_MODE; splitDir++ ) + { + int maskStride = 0, maskStride2 = 0; + int stepX = 1; + Pel* SADmask; + int16_t angle = g_GeoParams[splitDir][0]; + if (g_angle2mirror[angle] == 2) + { + maskStride = - GEO_WEIGHT_MASK_SIZE; + maskStride2 = -(int)cu.lwidth(); + SADmask = &g_globalGeoEncSADmask[g_angle2mask[g_GeoParams[splitDir][0]]][(GEO_WEIGHT_MASK_SIZE - 1 - g_weightOffset[splitDir][hIdx][wIdx][1]) * GEO_WEIGHT_MASK_SIZE + g_weightOffset[splitDir][hIdx][wIdx][0]]; + } + else if (g_angle2mirror[angle] == 1) + { + stepX = -1; + maskStride2 = cu.lwidth(); + maskStride = GEO_WEIGHT_MASK_SIZE; + SADmask = &g_globalGeoEncSADmask[g_angle2mask[g_GeoParams[splitDir][0]]][g_weightOffset[splitDir][hIdx][wIdx][1] * GEO_WEIGHT_MASK_SIZE + (GEO_WEIGHT_MASK_SIZE - 1 - g_weightOffset[splitDir][hIdx][wIdx][0])]; + } + else + { + maskStride = GEO_WEIGHT_MASK_SIZE; + maskStride2 = -(int)cu.lwidth(); + SADmask = &g_globalGeoEncSADmask[g_angle2mask[g_GeoParams[splitDir][0]]][g_weightOffset[splitDir][hIdx][wIdx][1] * GEO_WEIGHT_MASK_SIZE + g_weightOffset[splitDir][hIdx][wIdx][0]]; + } + Distortion uiSadSmall = 0, uiSadLarge = 0; + for( uint8_t mergeCand = 0; mergeCand < maxNumMergeCandidates; mergeCand++ ) + { + int bitsCand = mergeCand + 1; + + m_pcRdCost->setDistParam(distParam, tempCS->getOrgBuf().Y(), geoTempBuf[mergeCand].Y().buf, geoTempBuf[mergeCand].Y().stride, SADmask, maskStride, stepX, maskStride2, sps.getBitDepth(CHANNEL_TYPE_LUMA), COMPONENT_Y); + uiSadLarge = distParam.distFunc(distParam); + m_GeoCostList.insert(splitDir, 0, mergeCand, (double)uiSadLarge + (double)bitsCand * sqrtLambdaForFirstPass); + uiSadSmall = uiSadWholeBlk[mergeCand] - uiSadLarge; + m_GeoCostList.insert(splitDir, 1, mergeCand, (double)uiSadSmall + (double)bitsCand * sqrtLambdaForFirstPass); + } + } + delete[] uiSadWholeBlk; + delete[] pocMrg; + delete[] MrgMv; + delete[] isSkipThisCand; + + for( int splitDir = 0; splitDir < GEO_NUM_PARTITION_MODE; splitDir++ ) + { + for (int GeoMotionIdx = 0; GeoMotionIdx < maxNumMergeCandidates * (maxNumMergeCandidates - 1); GeoMotionIdx++) + { + unsigned int mergeCand0 = m_GeoModeTest[GeoMotionIdx].m_candIdx0; + unsigned int mergeCand1 = m_GeoModeTest[GeoMotionIdx].m_candIdx1; + double tempCost = m_GeoCostList.singleDistList[0][splitDir][mergeCand0].cost + m_GeoCostList.singleDistList[1][splitDir][mergeCand1].cost; + if (tempCost > bestWholeBlkCost) + continue; + int bitsGeoPartNoPred = bitsCandTB; + if(splitDir >= (1 << (bitsCandTB + 1)) - GEO_NUM_PARTITION_MODE) + bitsGeoPartNoPred++; + tempCost = tempCost + (double)bitsGeoPartNoPred * sqrtLambdaForFirstPass; + comboList.list.push_back(GeoMergeCombo(splitDir, mergeCand0, mergeCand1, tempCost)); + } + } + if( comboList.list.empty() ) + return; + comboList.sortByCost(); + bool geocandHasNoResidual[GEO_MAX_TRY_WEIGHTED_SAD]; + for( int mergeCand = 0; mergeCand < GEO_MAX_TRY_WEIGHTED_SAD; mergeCand++ ) + { + geocandHasNoResidual[mergeCand] = false; + } + bool bestIsSkip = false; + int geoNumCobo = (int)comboList.list.size(); + static_vector<uint8_t, GEO_MAX_TRY_WEIGHTED_SAD> geoRdModeList; + static_vector<double, GEO_MAX_TRY_WEIGHTED_SAD> geocandCostList; + + DistParam distParamSAD2; + const bool useHadamard = !tempCS->slice->getDisableSATDForRD(); + m_pcRdCost->setDistParam(distParamSAD2, tempCS->getOrgBuf().Y(), m_acMergeBuffer[0].Y(), sps.getBitDepth(CHANNEL_TYPE_LUMA), COMPONENT_Y, useHadamard); + int geoNumMrgSATDCand = min(GEO_MAX_TRY_WEIGHTED_SATD, geoNumCobo); + + for( uint8_t candidateIdx = 0; candidateIdx < min(geoNumCobo, GEO_MAX_TRY_WEIGHTED_SAD); candidateIdx++ ) + { + int splitDir = comboList.list[candidateIdx].splitDir; + int mergeCand0 = comboList.list[candidateIdx].mergeIdx0; + int mergeCand1 = comboList.list[candidateIdx].mergeIdx1; + + geoCombinations[candidateIdx] = m_acGeoWeightedBuffer[candidateIdx].getBuf(localUnitArea); + m_pcInterSearch->weightedGeoBlk(pu, splitDir, CHANNEL_TYPE_LUMA, geoCombinations[candidateIdx], geoBuffer[mergeCand0], geoBuffer[mergeCand1]); + distParamSAD2.cur = geoCombinations[candidateIdx].Y(); + Distortion uiSad = distParamSAD2.distFunc(distParamSAD2); + int bitsGeoPartNoPred = bitsCandTB; + if (splitDir >= (1 << (bitsCandTB + 1)) - GEO_NUM_PARTITION_MODE) + bitsGeoPartNoPred++; + int mvBits = 2; + mergeCand1 -= mergeCand1 < mergeCand0 ? 0 : 1; + mvBits += mergeCand0; + mvBits += mergeCand1; + double updateCost = (double)uiSad + (double)(bitsGeoPartNoPred + mvBits) * sqrtLambdaForFirstPass; + comboList.list[candidateIdx].cost = updateCost; + updateCandList(candidateIdx, updateCost, geoRdModeList, geocandCostList, geoNumMrgSATDCand); + } + for( uint8_t i = 0; i < geoNumMrgSATDCand; i++ ) + { + if (geocandCostList[i] > MRG_FAST_RATIO * geocandCostList[0] || geocandCostList[i] > getMergeBestSATDCost() || geocandCostList[i] > getAFFBestSATDCost()) + { + geoNumMrgSATDCand = i; + break; + } + } + for (uint8_t i = 0; i < geoNumMrgSATDCand && isChromaEnabled(pu.chromaFormat); i++) + { + uint8_t candidateIdx = geoRdModeList[i]; + int splitDir = comboList.list[candidateIdx].splitDir; + int mergeCand0 = comboList.list[candidateIdx].mergeIdx0; + int mergeCand1 = comboList.list[candidateIdx].mergeIdx1; + geoCombinations[candidateIdx] = m_acGeoWeightedBuffer[candidateIdx].getBuf(localUnitArea); + m_pcInterSearch->weightedGeoBlk(pu, splitDir, CHANNEL_TYPE_CHROMA, geoCombinations[candidateIdx], geoBuffer[mergeCand0], geoBuffer[mergeCand1]); + } + + m_bestModeUpdated = tempCS->useDbCost = bestCS->useDbCost = false; + tempCS->initStructData(encTestMode.qp); + uint8_t iteration; + uint8_t iterationBegin = 0; + iteration = 2; + for (uint8_t noResidualPass = iterationBegin; noResidualPass < iteration; ++noResidualPass) + { + for (uint8_t mrgHADIdx = 0; mrgHADIdx < geoNumMrgSATDCand; mrgHADIdx++) + { + uint8_t candidateIdx = geoRdModeList[mrgHADIdx]; + if(((noResidualPass != 0) && geocandHasNoResidual[candidateIdx]) + || ((noResidualPass == 0) && bestIsSkip)) + { + continue; + } + CodingUnit &cu = tempCS->addCU(tempCS->area, pm.chType); + pm.setCUData(cu); + cu.predMode = MODE_INTER; + cu.slice = tempCS->slice; + cu.tileIdx = tempCS->pps->getTileIdx(tempCS->area.lumaPos()); + cu.qp = encTestMode.qp; + cu.affine = false; + cu.mtsFlag = false; + cu.BcwIdx = BCW_DEFAULT; + cu.geoFlag = true; + cu.imv = 0; + cu.mmvdSkip = false; + cu.skip = false; + cu.mipFlag = false; + cu.bdpcmMode = 0; + PredictionUnit &pu = tempCS->addPU(cu, pm.chType); + pu.mergeFlag = true; + pu.regularMergeFlag = false; + pu.geoSplitDir = comboList.list[candidateIdx].splitDir; + pu.geoMergeIdx0 = comboList.list[candidateIdx].mergeIdx0; + pu.geoMergeIdx1 = comboList.list[candidateIdx].mergeIdx1; + pu.mmvdMergeFlag = false; + pu.mmvdMergeIdx = MAX_UINT; + + PU::spanGeoMotionInfo(pu, mergeCtx, pu.geoSplitDir, pu.geoMergeIdx0, pu.geoMergeIdx1); + tempCS->getPredBuf().copyFrom(geoCombinations[candidateIdx]); + + xEncodeInterResidual(tempCS, bestCS, pm, encTestMode, noResidualPass, (noResidualPass == 0 ? &geocandHasNoResidual[candidateIdx] : NULL)); + + if( m_pcEncCfg->getUseFastDecisionForMerge() && !bestIsSkip ) + { + bestIsSkip = bestCS->getCU(pm.chType)->rootCbf == 0; + } + tempCS->initStructData(encTestMode.qp); + } + } + if ( m_bestModeUpdated && bestCS->cost != MAX_DOUBLE ) + { + xCalDebCost( *bestCS, pm ); + } +} +#endif void EncCu::xCheckRDCostAffineMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &partitioner, const EncTestMode& encTestMode ) { @@ -3053,6 +3387,10 @@ void EncCu::xCheckRDCostAffineMerge2Nx2N( CodingStructure *&tempCS, CodingStruct AffineMergeCtx affineMergeCtx; const SPS &sps = *tempCS->sps; +#if JVET_Q0806 + setAFFBestSATDCost(MAX_DOUBLE); +#endif + MergeCtx mrgCtx; if ( sps.getSBTMVPEnabledFlag() ) { @@ -3192,6 +3530,10 @@ void EncCu::xCheckRDCostAffineMerge2Nx2N( CodingStructure *&tempCS, CodingStruct } tempCS->initStructData( encTestMode.qp ); +#if JVET_Q0806 + setAFFBestSATDCost(candCostList[0]); +#endif + } else { @@ -3344,7 +3686,11 @@ void EncCu::xCheckRDCostIBCModeMerge2Nx2N(CodingStructure *&tempCS, CodingStruct cu.mmvdSkip = false; pu.mmvdMergeFlag = false; pu.regularMergeFlag = false; +#if !JVET_Q0806 cu.triangle = false; +#else + cu.geoFlag = false; +#endif PU::getIBCMergeCandidates(pu, mergeCtx); } @@ -3378,7 +3724,11 @@ void EncCu::xCheckRDCostIBCModeMerge2Nx2N(CodingStructure *&tempCS, CodingStruct cu.chromaQpAdj = m_cuChromaQpOffsetIdxPlus1; cu.qp = encTestMode.qp; cu.mmvdSkip = false; +#if !JVET_Q0806 cu.triangle = false; +#else + cu.geoFlag = false; +#endif DistParam distParam; const bool bUseHadamard = !cu.slice->getDisableSATDForRD(); PredictionUnit &pu = tempCS->addPU(cu, partitioner.chType); //tempCS->addPU(cu); @@ -3495,7 +3845,11 @@ void EncCu::xCheckRDCostIBCModeMerge2Nx2N(CodingStructure *&tempCS, CodingStruct cu.mmvdSkip = false; pu.mmvdMergeFlag = false; pu.regularMergeFlag = false; +#if !JVET_Q0806 cu.triangle = false; +#else + cu.geoFlag = false; +#endif mergeCtx.setMergeInfo(pu, mergeCand); PU::spanMotionInfo(pu, mergeCtx); diff --git a/source/Lib/EncoderLib/EncCu.h b/source/Lib/EncoderLib/EncCu.h index 18b99b00a..1e050c1b0 100644 --- a/source/Lib/EncoderLib/EncCu.h +++ b/source/Lib/EncoderLib/EncCu.h @@ -67,6 +67,7 @@ class EncSlice; // ==================================================================================================================== /// CU encoder class +#if !JVET_Q0806 struct TriangleMotionInfo { uint8_t m_splitDir; @@ -76,6 +77,87 @@ struct TriangleMotionInfo TriangleMotionInfo ( uint8_t splitDir, uint8_t candIdx0, uint8_t candIdx1 ): m_splitDir(splitDir), m_candIdx0(candIdx0), m_candIdx1(candIdx1) { } TriangleMotionInfo() { m_splitDir = m_candIdx0 = m_candIdx1 = 0; } }; +#else +struct GeoMergeCombo +{ + int splitDir; + int mergeIdx0; + int mergeIdx1; + double cost; + GeoMergeCombo() : splitDir(), mergeIdx0(-1), mergeIdx1(-1), cost(0.0) {}; + GeoMergeCombo(int _splitDir, int _mergeIdx0, int _mergeIdx1, double _cost) : splitDir(_splitDir), mergeIdx0(_mergeIdx0), mergeIdx1(_mergeIdx1), cost(_cost) {}; +}; +struct GeoMotionInfo +{ + uint8_t m_candIdx0; + uint8_t m_candIdx1; + + GeoMotionInfo(uint8_t candIdx0, uint8_t candIdx1) : m_candIdx0(candIdx0), m_candIdx1(candIdx1) { } + GeoMotionInfo() { m_candIdx0 = m_candIdx1 = 0; } +}; +struct smaller_than_combo_cost +{ + inline bool operator() (const GeoMergeCombo& first, const GeoMergeCombo& second) + { + return (first.cost < second.cost); + } +}; +class GeoComboCostList +{ +public: + GeoComboCostList() {}; + ~GeoComboCostList() {}; + std::vector<GeoMergeCombo> list; + void sortByCost() { std::sort(list.begin(), list.end(), smaller_than_combo_cost()); }; +}; +struct SingleGeoMergeEntry +{ + int mergeIdx; + double cost; + SingleGeoMergeEntry() : mergeIdx(0), cost(MAX_DOUBLE) {}; + SingleGeoMergeEntry(int _mergeIdx, double _cost) : mergeIdx(_mergeIdx), cost(_cost) {}; +}; +class FastGeoCostList +{ +public: + FastGeoCostList() { numGeoTemplatesInitialized = 0; }; + ~FastGeoCostList() + { + for (int partIdx = 0; partIdx < 2; partIdx++) + { + for (int splitDir = 0; splitDir < GEO_NUM_PARTITION_MODE; splitDir++) + { + delete[] singleDistList[partIdx][splitDir]; + } + delete[] singleDistList[partIdx]; + singleDistList[partIdx] = nullptr; + } + }; + SingleGeoMergeEntry** singleDistList[2]; + void init(int numTemplates, int maxNumGeoCand) + { + if (numGeoTemplatesInitialized == 0 || numGeoTemplatesInitialized < numTemplates) + { + for (int partIdx = 0; partIdx < 2; partIdx++) + { + singleDistList[partIdx] = new SingleGeoMergeEntry*[numTemplates]; + for (int splitDir = 0; splitDir < numTemplates; splitDir++) + { + singleDistList[partIdx][splitDir] = new SingleGeoMergeEntry[maxNumGeoCand]; + } + } + numGeoTemplatesInitialized = numTemplates; + } + } + void insert(int geoIdx, int partIdx, int mergeIdx, double cost) + { + assert(geoIdx < numGeoTemplatesInitialized); + singleDistList[partIdx][geoIdx][mergeIdx] = SingleGeoMergeEntry(mergeIdx, cost); + } + int numGeoTemplatesInitialized; +}; +#endif + class EncCu : DecCu { @@ -121,7 +203,13 @@ private: PelStorage m_acMergeBuffer[MMVD_MRG_MAX_RD_BUF_NUM]; PelStorage m_acRealMergeBuffer[MRG_MAX_NUM_CANDS]; PelStorage m_acMergeTmpBuffer[MRG_MAX_NUM_CANDS]; +#if !JVET_Q0806 PelStorage m_acTriangleWeightedBuffer[TRIANGLE_MAX_NUM_CANDS]; // to store weighted prediction pixles +#else + PelStorage m_acGeoWeightedBuffer[GEO_MAX_TRY_WEIGHTED_SAD]; // to store weighted prediction pixles + FastGeoCostList m_GeoCostList; + double m_AFFBestSATDCost; +#endif double m_mergeBestSATDCost; MotionInfo m_SubPuMiBuf [( MAX_CU_SIZE * MAX_CU_SIZE ) >> ( MIN_CU_LOG2 << 1 )]; @@ -132,8 +220,12 @@ private: #endif int m_bestBcwIdx[2]; double m_bestBcwCost[2]; +#if !JVET_Q0806 TriangleMotionInfo m_triangleModeTest[TRIANGLE_MAX_NUM_CANDS]; uint8_t m_triangleIdxBins[2][TRIANGLE_MAX_NUM_UNI_CANDS][TRIANGLE_MAX_NUM_UNI_CANDS]; +#else + GeoMotionInfo m_GeoModeTest[GEO_MAX_NUM_CANDS]; +#endif #if SHARP_LUMA_DELTA_QP || ENABLE_QPA_SUB_CTU void updateLambda ( Slice* slice, const int dQP, #if WCG_EXT && ER_CHROMA_QP_WCG_PPS @@ -163,6 +255,10 @@ public: void setMergeBestSATDCost(double cost) { m_mergeBestSATDCost = cost; } double getMergeBestSATDCost() { return m_mergeBestSATDCost; } +#if JVET_Q0806 + void setAFFBestSATDCost(double cost) { m_AFFBestSATDCost = cost; } + double getAFFBestSATDCost() { return m_AFFBestSATDCost; } +#endif IbcHashMap& getIbcHashMap() { return m_ibcHashMap; } EncCfg* getEncCfg() const { return m_pcEncCfg; } @@ -202,7 +298,11 @@ protected: void xCheckRDCostMerge2Nx2N ( CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &pm, const EncTestMode& encTestMode ); +#if !JVET_Q0806 void xCheckRDCostMergeTriangle2Nx2N( CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &pm, const EncTestMode& encTestMode ); +#else + void xCheckRDCostMergeGeo2Nx2N(CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &pm, const EncTestMode& encTestMode); +#endif void xEncodeInterResidual( CodingStructure *&tempCS , CodingStructure *&bestCS diff --git a/source/Lib/EncoderLib/EncLib.cpp b/source/Lib/EncoderLib/EncLib.cpp index 3eb5c0846..ac265e300 100644 --- a/source/Lib/EncoderLib/EncLib.cpp +++ b/source/Lib/EncoderLib/EncLib.cpp @@ -990,7 +990,11 @@ void EncLib::xInitSPS( SPS& sps, VPS& vps ) cinfo->setNoIbcConstraintFlag(m_noIbcConstraintFlag); cinfo->setNoCiipConstraintFlag(m_bNoCiipConstraintFlag); cinfo->setNoFPelMmvdConstraintFlag(m_noFPelMmvdConstraintFlag); +#if !JVET_Q0806 cinfo->setNoTriangleConstraintFlag(m_bNoTriangleConstraintFlag); +#else + cinfo->setNoGeoConstraintFlag(m_bNoGeoConstraintFlag); +#endif cinfo->setNoLadfConstraintFlag(m_bNoLadfConstraintFlag); cinfo->setNoTransformSkipConstraintFlag(m_noTransformSkipConstraintFlag); cinfo->setNoBDPCMConstraintFlag(m_noBDPCMConstraintFlag); @@ -1084,7 +1088,11 @@ void EncLib::xInitSPS( SPS& sps, VPS& vps ) #endif sps.setUseCiip ( m_ciip ); +#if !JVET_Q0806 sps.setUseTriangle ( m_Triangle ); +#else + sps.setUseGeo ( m_Geo ); +#endif sps.setUseMMVD ( m_MMVD ); sps.setFpelMmvdEnabledFlag (( m_MMVD ) ? m_allowDisFracMMVD : false); sps.setBdofControlPresentFlag(m_BIO); @@ -1285,7 +1293,11 @@ void EncLib::xInitPPS(PPS &pps, const SPS &sps) pps.setPPSMvdL1ZeroIdc(getPPSMvdL1ZeroIdc()); pps.setPPSCollocatedFromL0Idc(getPPSCollocatedFromL0Idc()); pps.setPPSSixMinusMaxNumMergeCandPlus1(getPPSSixMinusMaxNumMergeCandPlus1()); +#if !JVET_Q0806 pps.setPPSMaxNumMergeCandMinusMaxNumTriangleCandPlus1(getPPSMaxNumMergeCandMinusMaxNumTriangleCandPlus1()); +#else + pps.setPPSMaxNumMergeCandMinusMaxNumGeoCandPlus1(getPPSMaxNumMergeCandMinusMaxNumGeoCandPlus1()); +#endif pps.setNumSubPics(sps.getNumSubPics()); pps.setSubPicIdSignallingPresentFlag(false); @@ -1563,7 +1575,11 @@ void EncLib::xInitPicHeader(PicHeader &picHeader, const SPS &sps, const PPS &pps // merge list sizes picHeader.setMaxNumMergeCand ( getMaxNumMergeCand() ); picHeader.setMaxNumAffineMergeCand( getMaxNumAffineMergeCand() ); +#if !JVET_Q0806 picHeader.setMaxNumTriangleCand ( getMaxNumTriangleCand() ); +#else + picHeader.setMaxNumGeoCand ( getMaxNumGeoCand() ); +#endif picHeader.setMaxNumIBCMergeCand ( getMaxNumIBCMergeCand() ); // copy partitioning constraints from SPS diff --git a/source/Lib/EncoderLib/EncModeCtrl.cpp b/source/Lib/EncoderLib/EncModeCtrl.cpp index 922835d58..932a628fd 100644 --- a/source/Lib/EncoderLib/EncModeCtrl.cpp +++ b/source/Lib/EncoderLib/EncModeCtrl.cpp @@ -1364,10 +1364,17 @@ void EncModeCtrlMTnoRQT::initCULevel( Partitioner &partitioner, const CodingStru // add inter modes if( m_pcEncCfg->getUseEarlySkipDetection() ) { +#if !JVET_Q0806 if( cs.sps->getUseTriangle() && cs.slice->isInterB() ) { m_ComprCUCtxList.back().testModes.push_back( { ETM_MERGE_TRIANGLE, ETO_STANDARD, qp } ); } +#else + if( cs.sps->getUseGeo() && cs.slice->isInterB() ) + { + m_ComprCUCtxList.back().testModes.push_back( { ETM_MERGE_GEO, ETO_STANDARD, qp } ); + } +#endif m_ComprCUCtxList.back().testModes.push_back( { ETM_MERGE_SKIP, ETO_STANDARD, qp } ); if ( cs.sps->getUseAffine() || cs.sps->getSBTMVPEnabledFlag() ) { @@ -1378,10 +1385,17 @@ void EncModeCtrlMTnoRQT::initCULevel( Partitioner &partitioner, const CodingStru else { m_ComprCUCtxList.back().testModes.push_back( { ETM_INTER_ME, ETO_STANDARD, qp } ); +#if !JVET_Q0806 if( cs.sps->getUseTriangle() && cs.slice->isInterB() ) { m_ComprCUCtxList.back().testModes.push_back( { ETM_MERGE_TRIANGLE, ETO_STANDARD, qp } ); } +#else + if( cs.sps->getUseGeo() && cs.slice->isInterB() ) + { + m_ComprCUCtxList.back().testModes.push_back( { ETM_MERGE_GEO, ETO_STANDARD, qp } ); + } +#endif m_ComprCUCtxList.back().testModes.push_back( { ETM_MERGE_SKIP, ETO_STANDARD, qp } ); if ( cs.sps->getUseAffine() || cs.sps->getSBTMVPEnabledFlag() ) { @@ -1419,7 +1433,11 @@ bool EncModeCtrlMTnoRQT::tryMode( const EncTestMode& encTestmode, const CodingSt ComprCUCtx& cuECtx = m_ComprCUCtxList.back(); // Fast checks, partitioning depended +#if !JVET_Q0806 if (cuECtx.isHashPerfectMatch && encTestmode.type != ETM_MERGE_SKIP && encTestmode.type != ETM_INTER_ME && encTestmode.type != ETM_AFFINE && encTestmode.type != ETM_MERGE_TRIANGLE) +#else + if (cuECtx.isHashPerfectMatch && encTestmode.type != ETM_MERGE_SKIP && encTestmode.type != ETM_INTER_ME && encTestmode.type != ETM_AFFINE && encTestmode.type != ETM_MERGE_GEO) +#endif { return false; } @@ -1640,10 +1658,20 @@ bool EncModeCtrlMTnoRQT::tryMode( const EncTestMode& encTestmode, const CodingSt { return false; } +#if !JVET_Q0806 if( encTestmode.type == ETM_MERGE_TRIANGLE && ( partitioner.currArea().lumaSize().area() < TRIANGLE_MIN_SIZE || relatedCU.isIntra ) ) { return false; } +#else + if( encTestmode.type == ETM_MERGE_GEO && ( partitioner.currArea().lwidth() < GEO_MIN_CU_SIZE || partitioner.currArea().lheight() < GEO_MIN_CU_SIZE + || partitioner.currArea().lwidth() > GEO_MAX_CU_SIZE || partitioner.currArea().lheight() > GEO_MAX_CU_SIZE + || partitioner.currArea().lwidth() >= 8 * partitioner.currArea().lheight() + || partitioner.currArea().lheight() >= 8 * partitioner.currArea().lwidth() ) ) + { + return false; + } +#endif return true; } else if( isModeSplit( encTestmode ) ) diff --git a/source/Lib/EncoderLib/EncModeCtrl.h b/source/Lib/EncoderLib/EncModeCtrl.h index 3ab1b298b..f2b75071d 100644 --- a/source/Lib/EncoderLib/EncModeCtrl.h +++ b/source/Lib/EncoderLib/EncModeCtrl.h @@ -59,7 +59,11 @@ enum EncTestModeType ETM_MERGE_SKIP, ETM_INTER_ME, ETM_AFFINE, +#if !JVET_Q0806 ETM_MERGE_TRIANGLE, +#else + ETM_MERGE_GEO, +#endif ETM_INTRA, ETM_PALETTE, ETM_SPLIT_QT, @@ -138,7 +142,11 @@ inline bool isModeInter( const EncTestMode& encTestmode ) // perhaps remove return ( encTestmode.type == ETM_INTER_ME || encTestmode.type == ETM_MERGE_SKIP || encTestmode.type == ETM_AFFINE +#if !JVET_Q0806 || encTestmode.type == ETM_MERGE_TRIANGLE +#else + || encTestmode.type == ETM_MERGE_GEO +#endif || encTestmode.type == ETM_HASH_INTER ); } diff --git a/source/Lib/EncoderLib/VLCWriter.cpp b/source/Lib/EncoderLib/VLCWriter.cpp index 4a1fdcc80..25cb753ab 100644 --- a/source/Lib/EncoderLib/VLCWriter.cpp +++ b/source/Lib/EncoderLib/VLCWriter.cpp @@ -427,7 +427,11 @@ void HLSWriter::codePPS( const PPS* pcPPS, const SPS* pcSPS ) WRITE_CODE( pcPPS->getPPSMvdL1ZeroIdc(), 2, "pps_mvd_l1_zero_idc"); WRITE_CODE( pcPPS->getPPSCollocatedFromL0Idc(), 2, "pps_collocated_from_l0_idc"); WRITE_UVLC( pcPPS->getPPSSixMinusMaxNumMergeCandPlus1(), "pps_six_minus_max_num_merge_cand_plus1"); +#if !JVET_Q0806 WRITE_UVLC( pcPPS->getPPSMaxNumMergeCandMinusMaxNumTriangleCandPlus1(), "pps_max_num_merge_cand_minus_max_num_triangle_cand_plus1"); +#else + WRITE_UVLC(pcPPS->getPPSMaxNumMergeCandMinusMaxNumGeoCandPlus1(), "pps_max_num_merge_cand_minus_max_num_gpm_cand_plus1"); +#endif } @@ -959,7 +963,12 @@ void HLSWriter::codeSPS( const SPS* pcSPS ) { WRITE_FLAG( pcSPS->getFpelMmvdEnabledFlag() ? 1 : 0, "sps_fpel_mmvd_enabled_flag" ); } + +#if !JVET_Q0806 WRITE_FLAG( pcSPS->getUseTriangle() ? 1: 0, "sps_triangle_enabled_flag" ); +#else + WRITE_FLAG( pcSPS->getUseGeo() ? 1: 0, "sps_gpm_enabled_flag" ); +#endif WRITE_FLAG(pcSPS->getUseLmcs() ? 1 : 0, "sps_lmcs_enable_flag"); WRITE_FLAG( pcSPS->getUseLFNST() ? 1 : 0, "sps_lfnst_enabled_flag" ); @@ -1517,6 +1526,7 @@ void HLSWriter::codePictureHeader( PicHeader* picHeader ) picHeader->setDisProfFlag(0); } +#if !JVET_Q0806 // triangle merge candidate list size if (sps->getUseTriangle() && picHeader->getMaxNumMergeCand() >= 2) { @@ -1530,6 +1540,21 @@ void HLSWriter::codePictureHeader( PicHeader* picHeader ) picHeader->setMaxNumTriangleCand((uint32_t)(picHeader->getMaxNumMergeCand() - (pps->getPPSMaxNumMergeCandMinusMaxNumTriangleCandPlus1() - 1))); } } +#else + // geometric merge candidate list size + if (sps->getUseGeo() && picHeader->getMaxNumMergeCand() >= 2) + { + if (!pps->getPPSMaxNumMergeCandMinusMaxNumGeoCandPlus1()) + { + CHECK(picHeader->getMaxNumMergeCand() < picHeader->getMaxNumGeoCand(), "Incorrrect max number of gpm candidates!"); + WRITE_UVLC(picHeader->getMaxNumMergeCand() - picHeader->getMaxNumGeoCand(), "pic_max_num_merge_cand_minus_max_num_gpm_cand"); + } + else + { + picHeader->setMaxNumGeoCand((uint32_t)(picHeader->getMaxNumMergeCand() - (pps->getPPSMaxNumMergeCandMinusMaxNumGeoCandPlus1() - 1))); + } + } +#endif // ibc merge candidate list size if (sps->getIBCFlag()) @@ -2103,7 +2128,11 @@ void HLSWriter::codeConstraintInfo ( const ConstraintInfo* cinfo ) WRITE_FLAG(cinfo->getNoIbcConstraintFlag() ? 1 : 0, "no_ibc_constraint_flag"); WRITE_FLAG(cinfo->getNoCiipConstraintFlag() ? 1 : 0, "no_ciip_constraint_flag"); WRITE_FLAG(cinfo->getNoFPelMmvdConstraintFlag() ? 1 : 0, "no_fpel_mmvd_constraint_flag"); +#if !JVET_Q0806 WRITE_FLAG(cinfo->getNoTriangleConstraintFlag() ? 1 : 0, "no_triangle_constraint_flag"); +#else + WRITE_FLAG(cinfo->getNoGeoConstraintFlag() ? 1 : 0, "no_gpm_constraint_flag"); +#endif WRITE_FLAG(cinfo->getNoLadfConstraintFlag() ? 1 : 0, "no_ladf_constraint_flag"); WRITE_FLAG(cinfo->getNoTransformSkipConstraintFlag() ? 1 : 0, "no_transform_skip_constraint_flag"); WRITE_FLAG(cinfo->getNoBDPCMConstraintFlag() ? 1 : 0, "no_bdpcm_constraint_flag"); -- GitLab