From 81e12266c817759d05a8cb33647fa68b2d4ec15f Mon Sep 17 00:00:00 2001 From: Vadim Seregin <vseregin@qti.qualcomm.com> Date: Thu, 14 Nov 2024 15:29:20 +0000 Subject: [PATCH] JVET-AJ0260: SBT corner mode (Test 4.3a) --- source/.DS_Store | Bin 6148 -> 0 bytes source/Lib/.DS_Store | Bin 6148 -> 0 bytes source/Lib/CommonLib/CommonDef.h | 4 + source/Lib/CommonLib/Contexts_ecm14.0.inl | 55 +++++++++++ source/Lib/CommonLib/TrQuant.cpp | 34 +++++++ source/Lib/CommonLib/TypeDef.h | 26 ++++- source/Lib/CommonLib/Unit.cpp | 103 ++++++++++++++++++-- source/Lib/CommonLib/Unit.h | 3 + source/Lib/CommonLib/UnitPartitioner.cpp | 95 ++++++++++++++++++ source/Lib/CommonLib/UnitPartitioner.h | 10 ++ source/Lib/CommonLib/UnitTools.cpp | 65 +++++++++++++ source/Lib/DecoderLib/CABACReader.cpp | 95 ++++++++++++++++++ source/Lib/EncoderLib/CABACWriter.cpp | 112 ++++++++++++++++++++++ source/Lib/EncoderLib/EncCu.cpp | 4 + source/Lib/EncoderLib/EncSlice.cpp | 11 +++ source/Lib/EncoderLib/InterSearch.cpp | 85 ++++++++++++++++ 16 files changed, 690 insertions(+), 12 deletions(-) delete mode 100644 source/.DS_Store delete mode 100644 source/Lib/.DS_Store diff --git a/source/.DS_Store b/source/.DS_Store deleted file mode 100644 index 00be350596ca0f4a0ee2086f58497b295d59e5c7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeHKPfNov6i?iA8AIqnK|BS#4%|9W!Aq(0=E;g4RA$SD7Hc!s&K|~~A3(p5AH>h& zdr1lodlqr;LGpWlljaA_AI2E>=i@$O4r5F}L*%H`2)b)S8#Wn{;~3dAN>l{aM>Msu zzYh5A4R*m|7DdJP?@!_^@AW?UMx(j8)e<ey5%<B9DuO)B=b0bQZqd3@Dv2sRjIQHJ zF>-d!RGNozI+^K$cszlWyPG&2tHM|Fbe!qhzyw5Fv`5bVVli+}y3##zmtDE&AEVLl zxr61hEp`tMPcKK$$xEu<451wO*0OD}f_G5tdR~KBnyB;<JXLm;MMw+~1H=F^u+9wF zQ$cjrnFLxpF+dE|GJyMogofx@EDh?d13J7uW4wuo0y@4W5T!-WVrdW}Al#G!no@3` z7~GVDU)ns+VrkHnGp=WbaqP_1<Av+l!7p_><DNn4i2-6@m4Sva9X$Wf;g_j><gb>H zMGO!F|BM0N90o%l7G=-YAIrnDRziD#hJtw|Dj=Y*TmrzrePmAuO<bZ5d7j16AdZ55 RT@FYW0Zj;X#K12w@CBw4NsIsh diff --git a/source/Lib/.DS_Store b/source/Lib/.DS_Store deleted file mode 100644 index 691e492705ea5cea1d548ce866399be2f4e2eb62..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeHK%}T>S5T0$TO(;SR3gRi?wP1fh1ur43H%~_Npi&!JG?->fo0>x@<N@@Bd=Q_< znca<8ss}G3cBagJv-6W>zm%OU00@6JXaYC@V4)J0Y#hE2ij%HL$#@8bdWM7q&LDy? z%vQ45@fR7OcV|NfB#iL)>HST|VJt(8zJ}vCnx>7$n<$kl8=F<DYSpaU;6Y|V+D~Uw zzdyOA*@cvGSlIpWG8$$*XS*Ylv>zqIi7JQ&Lrl53ijslMd^t-7Q&k)2fMr{D&)J*L z+pXie+d6D5>h8RGM3ZKt)m|)YYiIx9<h=J7j}rN;2^IL?Q?g~SfEP5r*xOSuNn)AY zW3;F&Dj1moW`G%34+hNXXVunYySz(gfEoA!19U#PsDz%uT%$TVaG=jeidP6p(5AZt zp=;1Hm}|rciqNHqx>T4ehS25ccTJvWFxRNdL8z7SIc8;HZYV;nj(%6AgYY!+$P6$8 z%M6tD)S>==`u+WXxrk@X05kBf7!Z|i(DiXkrnjzaj(V+&dWT9vdAY`q5;RmR#$0N} cyQoUg?~;M&8O$}J2ZcWb6b(Eu1Ha0^JF|^VEC2ui diff --git a/source/Lib/CommonLib/CommonDef.h b/source/Lib/CommonLib/CommonDef.h index bee99bcb2..459b4247f 100644 --- a/source/Lib/CommonLib/CommonDef.h +++ b/source/Lib/CommonLib/CommonDef.h @@ -1689,6 +1689,10 @@ static const int SBT_MAX_SIZE = 64; ///< maxi #endif static const int SBT_NUM_SL = 10; ///< maximum number of historical PU decision saved for a CU static const int SBT_NUM_RDO = 2; ///< maximum number of SBT mode tried for a PU +#if JVET_AJ0260_SBT_CORNER_MODE +static const int SBT_QUAD_MIN_BLOCK_SIZE = 8; +static const int SBT_QUARTER_MIN_BLOCK_SIZE = 16; +#endif #if JVET_AI0050_SBT_LFNST static const int NUM_SBT_LFNST_RDO = 2; #endif diff --git a/source/Lib/CommonLib/Contexts_ecm14.0.inl b/source/Lib/CommonLib/Contexts_ecm14.0.inl index 2498b51ef..826ca751f 100644 --- a/source/Lib/CommonLib/Contexts_ecm14.0.inl +++ b/source/Lib/CommonLib/Contexts_ecm14.0.inl @@ -5189,6 +5189,33 @@ const CtxSet ContextSetCfg::SbtFlag = ContextSetCfg::addCtxSet({ const CtxSet ContextSetCfg::SbtQuadFlag = ContextSetCfg::addCtxSet({ // ctx 1453 1453 +#if JVET_AJ0260_SBT_CORNER_MODE +// 0 - half/quarter flag +// 1 - rectangular +// 2 - quad +// 3 - quarter + + { 35, 35, 35, 35 }, + { 35, 35, 35, 35 }, + { 35, 35, 35, 35 }, + { 50, 50, 50, 50 }, + { 10, 10, 10, 10 }, + { 10, 10, 10, 10 }, + { 8, 8, 8, 8 }, + { 10, 10, 10, 10 }, + { 4, 4, 4, 4 }, + { 11, 11, 11, 11 }, + { 18, 18, 18, 18 }, + { 4, 4, 4, 4 }, + { 130, 130, 130, 130 }, + { 102, 102, 102, 102 }, + { 119, 119, 119, 119 }, + { 100, 100, 100, 100 }, + { 119, 119, 119, 119 }, + { 119, 119, 119, 119 }, + { 102, 102, 102, 102 }, + { 100, 100, 100, 100 }, +#else { 35 }, { 35 }, { 35 }, @@ -5209,6 +5236,7 @@ const CtxSet ContextSetCfg::SbtQuadFlag = ContextSetCfg::addCtxSet({ { 119 }, { 102 }, { 100 }, +#endif }); const CtxSet ContextSetCfg::SbtHorFlag = ContextSetCfg::addCtxSet({ @@ -5237,6 +5265,32 @@ const CtxSet ContextSetCfg::SbtHorFlag = ContextSetCfg::addCtxSet({ const CtxSet ContextSetCfg::SbtPosFlag = ContextSetCfg::addCtxSet({ // ctx 1457 1457 +#if JVET_AJ0260_SBT_CORNER_MODE +// 0 - rectangular mode (anchor) +// 1,2 - quad +// 3,4 - quarter + + { 28, 28, 28, 28, 28 }, + { 20, 20, 20, 20, 20 }, + { 35, 35, 35, 35, 35 }, + { 20, 20, 20, 20, 20 }, + { 13, 13, 13, 13, 13 }, + { 13, 13, 13, 13, 13 }, + { 8, 8, 8, 8, 8 }, + { 13, 13, 13, 13, 13 }, + { 11, 11, 11, 11, 11 }, + { 4, 4, 4, 4, 4 }, + { 18, 18, 18, 18, 18 }, + { 11, 11, 11, 11, 11 }, + { 84, 84, 84, 84, 84 }, + { 163, 163, 163, 163, 163 }, + { 83, 83, 83, 83, 83 }, + { 122, 122, 122, 122, 122 }, + { 119, 119, 119, 119, 119 }, + { 119, 119, 119, 119, 119 }, + { 83, 83, 83, 83, 83 }, + { 103, 103, 103, 103, 103 }, +#else { 28 }, { 20 }, { 35 }, @@ -5257,6 +5311,7 @@ const CtxSet ContextSetCfg::SbtPosFlag = ContextSetCfg::addCtxSet({ { 119 }, { 83 }, { 103 }, +#endif }); const CtxSet ContextSetCfg::ChromaQpAdjFlag = ContextSetCfg::addCtxSet({ diff --git a/source/Lib/CommonLib/TrQuant.cpp b/source/Lib/CommonLib/TrQuant.cpp index d10f3a8ba..fd9f01e03 100644 --- a/source/Lib/CommonLib/TrQuant.cpp +++ b/source/Lib/CommonLib/TrQuant.cpp @@ -1280,6 +1280,40 @@ void TrQuant::getTrTypes(const TransformUnit tu, const ComponentID compID, int & uint8_t sbtIdx = tu.cu->getSbtIdx(); uint8_t sbtPos = tu.cu->getSbtPos(); +#if JVET_AJ0260_SBT_CORNER_MODE + if( sbtIdx == SBT_QUAD || sbtIdx == SBT_QUARTER ) + { + if( tu.lwidth() > MTS_INTER_MAX_CU_SIZE || tu.lheight() > MTS_INTER_MAX_CU_SIZE ) + { + trTypeHor = trTypeVer = DCT2; + } + else if( sbtPos == 0 ) + { + trTypeHor = DCT8; + trTypeVer = DCT8; + } + else if( sbtPos == 1 ) + { + trTypeHor = DST7; + trTypeVer = DCT8; + } + else if( sbtPos == 2 ) + { + trTypeHor = DCT8; + trTypeVer = DST7; + } + else if( sbtPos == 3 ) + { + trTypeHor = DST7; + trTypeVer = DST7; + } + else + { + CHECK( true, "Wrong SBT QUAD position" ); + } + } + else +#endif if( sbtIdx == SBT_VER_HALF || sbtIdx == SBT_VER_QUAD ) { assert( tu.lwidth() <= MTS_INTER_MAX_CU_SIZE ); diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h index 3d4fabef4..fc5920dc1 100644 --- a/source/Lib/CommonLib/TypeDef.h +++ b/source/Lib/CommonLib/TypeDef.h @@ -52,6 +52,7 @@ #include <cstdint> + #define BASE_ENCODER 1 #define BASE_NORMATIVE 1 #define TOOLS 1 @@ -442,11 +443,12 @@ #define JVET_AE0125_SHIFT_QUANTIZATION_CENTER 1 // JVET-AE0125: Shifting quantization center #define JVET_AE0102_LFNST_CTX 1 // JVET-AE0102: Context modelling for transform coefficients for LFNST/NSPT #define JVET_AG0061_INTER_LFNST_NSPT 1 // JVET-AG0061: 3.3 Utilizing LFNST/NSPT for inter coding -#define JVET_AG0100_TRANSFORM_COEFFICIENT_CODING 1 // JVET_AG0100: 3.2b Transform coefficient coding -#define JVET_AG0143_INTER_INTRA 1 // JVET_AG0143: 3.1c CABAC inter/intra model switch -#define JVET_AH0103_LOW_DELAY_LFNST_NSPT 1 // JVET_AH0103: Low-delay configurations for LFNST/NSPT -#define JVET_AI0050_INTER_MTSS 1 // JVET_AI0050: Multiple LFNST/NSPT kernel set selection for GPM coded block -#define JVET_AI0050_SBT_LFNST 1 // JVET_AI0050: Enable LFNST/NSPT for SBT coded block +#define JVET_AG0100_TRANSFORM_COEFFICIENT_CODING 1 // JVET-AG0100: 3.2b Transform coefficient coding +#define JVET_AG0143_INTER_INTRA 1 // JVET-AG0143: 3.1c CABAC inter/intra model switch +#define JVET_AH0103_LOW_DELAY_LFNST_NSPT 1 // JVET-AH0103: Low-delay configurations for LFNST/NSPT +#define JVET_AI0050_INTER_MTSS 1 // JVET-AI0050: Multiple LFNST/NSPT kernel set selection for GPM coded block +#define JVET_AI0050_SBT_LFNST 1 // JVET-AI0050: Enable LFNST/NSPT for SBT coded block +#define JVET_AJ0260_SBT_CORNER_MODE 1 // JVET-AJ0260: Corner mode for SBT // Entropy Coding #define EC_HIGH_PRECISION 1 // CABAC high precision @@ -1002,6 +1004,10 @@ enum SbtIdx SBT_HOR_HALF = 2, SBT_VER_QUAD = 3, SBT_HOR_QUAD = 4, +#if JVET_AJ0260_SBT_CORNER_MODE + SBT_QUAD, + SBT_QUARTER, +#endif NUMBER_SBT_IDX, SBT_OFF_MTS, //note: must be after all SBT modes, only used in fast algorithm to discern the best mode is inter EMT }; @@ -1023,6 +1029,16 @@ enum SbtMode SBT_VER_Q1 = 5, SBT_HOR_Q0 = 6, SBT_HOR_Q1 = 7, +#if JVET_AJ0260_SBT_CORNER_MODE + SBT_Q0, + SBT_Q1, + SBT_Q2, + SBT_Q3, + SBT_QT0, + SBT_QT1, + SBT_QT2, + SBT_QT3, +#endif NUMBER_SBT_MODE }; diff --git a/source/Lib/CommonLib/Unit.cpp b/source/Lib/CommonLib/Unit.cpp index 8140f4f0d..83b66da48 100644 --- a/source/Lib/CommonLib/Unit.cpp +++ b/source/Lib/CommonLib/Unit.cpp @@ -1028,8 +1028,8 @@ const uint8_t CodingUnit::checkAllowedSbt() const uint8_t sbtAllowed = 0; int cuWidth = lwidth(); int cuHeight = lheight(); - bool allow_type[NUMBER_SBT_IDX]; - memset( allow_type, false, NUMBER_SBT_IDX * sizeof( bool ) ); + bool allowType[NUMBER_SBT_IDX]; + memset( allowType, false, NUMBER_SBT_IDX * sizeof( bool ) ); //parameter int maxSbtCUSize = cs->sps->getMaxTbSize(); @@ -1041,14 +1041,18 @@ const uint8_t CodingUnit::checkAllowedSbt() const return 0; } - allow_type[SBT_VER_HALF] = cuWidth >= minSbtCUSize; - allow_type[SBT_HOR_HALF] = cuHeight >= minSbtCUSize; - allow_type[SBT_VER_QUAD] = cuWidth >= ( minSbtCUSize << 1 ); - allow_type[SBT_HOR_QUAD] = cuHeight >= ( minSbtCUSize << 1 ); + allowType[SBT_VER_HALF] = cuWidth >= minSbtCUSize; + allowType[SBT_HOR_HALF] = cuHeight >= minSbtCUSize; + allowType[SBT_VER_QUAD] = cuWidth >= ( minSbtCUSize << 1 ); + allowType[SBT_HOR_QUAD] = cuHeight >= ( minSbtCUSize << 1 ); +#if JVET_AJ0260_SBT_CORNER_MODE + allowType[ SBT_QUAD ] = cuWidth >= minSbtCUSize && cuHeight >= minSbtCUSize && cuWidth >= SBT_QUAD_MIN_BLOCK_SIZE && cuHeight >= SBT_QUAD_MIN_BLOCK_SIZE; + allowType[ SBT_QUARTER ] = cuWidth >= minSbtCUSize && cuHeight >= minSbtCUSize && cuWidth >= SBT_QUARTER_MIN_BLOCK_SIZE && cuHeight >= SBT_QUARTER_MIN_BLOCK_SIZE; +#endif for( int i = 0; i < NUMBER_SBT_IDX; i++ ) { - sbtAllowed += (uint8_t)allow_type[i] << i; + sbtAllowed += (uint8_t)allowType[i] << i; } return sbtAllowed; @@ -1064,13 +1068,69 @@ uint8_t CodingUnit::getSbtTuSplit() const case SBT_HOR_HALF: sbtTuSplitType = ( getSbtPos() == SBT_POS0 ? 0 : 1 ) + SBT_HOR_HALF_POS0_SPLIT; break; case SBT_VER_QUAD: sbtTuSplitType = ( getSbtPos() == SBT_POS0 ? 0 : 1 ) + SBT_VER_QUAD_POS0_SPLIT; break; case SBT_HOR_QUAD: sbtTuSplitType = ( getSbtPos() == SBT_POS0 ? 0 : 1 ) + SBT_HOR_QUAD_POS0_SPLIT; break; +#if JVET_AJ0260_SBT_CORNER_MODE + case SBT_QUAD: sbtTuSplitType = getSbtPos() + SBT_QUAD_POSTL_SPLIT; break; + case SBT_QUARTER: sbtTuSplitType = getSbtPos() + SBT_QUARTER_POSTL_SPLIT; break; +#endif default: assert( 0 ); break; } +#if JVET_AJ0260_SBT_CORNER_MODE + CHECK( sbtTuSplitType < SBT_VER_HALF_POS0_SPLIT || sbtTuSplitType >= NUM_PART_SPLIT, "Wrong SBT split type" ); +#else assert( sbtTuSplitType <= SBT_HOR_QUAD_POS1_SPLIT && sbtTuSplitType >= SBT_VER_HALF_POS0_SPLIT ); +#endif return sbtTuSplitType; } + +#if JVET_AJ0260_SBT_CORNER_MODE +int CodingUnit::getSbtTuIdx() const +{ + int idx = 0; + + if( sbtInfo ) + { + const int sbtIdx = getSbtIdx(); + const int sbtPos = getSbtPos(); + + if( sbtIdx == SBT_QUAD ) + { + idx = sbtPos; + } + else if( sbtIdx == SBT_QUARTER ) + { + if( sbtPos == 0 ) + { + idx = 0; + } + else if( sbtPos == 1 ) + { + idx = 3; + } + else if( sbtPos == 2 ) + { + idx = 12; + } + else if( sbtPos == 3 ) + { + idx = 15; + } + else + { + CHECK( true, "Wrong SBT position" ); + } + } + else + { + idx = sbtPos; + } + } + + return idx; +} +#endif + // --------------------------------------------------------------------------- // prediction unit method definitions // --------------------------------------------------------------------------- @@ -2358,6 +2418,35 @@ void TransformUnit::checkTuNoResidual( unsigned idx ) { noResidual = true; } +#if JVET_AJ0260_SBT_CORNER_MODE + else if( CU::getSbtIdx( cu->sbtInfo ) == SBT_QUAD ) + { + noResidual = CU::getSbtPos( cu->sbtInfo ) != idx ? true : false; + } + else if( CU::getSbtIdx( cu->sbtInfo ) == SBT_QUARTER ) + { + if( CU::getSbtPos( cu->sbtInfo ) == 0 && idx == 0 ) + { + noResidual = false; + } + else if( CU::getSbtPos( cu->sbtInfo ) == 1 && idx == 3 ) + { + noResidual = false; + } + else if( CU::getSbtPos( cu->sbtInfo ) == 2 && idx == 12 ) + { + noResidual = false; + } + else if( CU::getSbtPos( cu->sbtInfo ) == 3 && idx == 15 ) + { + noResidual = false; + } + else + { + noResidual = true; + } + } +#endif } int TransformUnit::getTbAreaAfterCoefZeroOut(ComponentID compID) const diff --git a/source/Lib/CommonLib/Unit.h b/source/Lib/CommonLib/Unit.h index 2f54ebf44..26dfc9747 100644 --- a/source/Lib/CommonLib/Unit.h +++ b/source/Lib/CommonLib/Unit.h @@ -583,6 +583,9 @@ struct CodingUnit : public UnitArea const bool isConsInter() const { return modeType == MODE_TYPE_INTER; } const bool isConsIntra() const { return modeType == MODE_TYPE_INTRA; } #endif +#if JVET_AJ0260_SBT_CORNER_MODE + int getSbtTuIdx() const; +#endif }; // --------------------------------------------------------------------------- diff --git a/source/Lib/CommonLib/UnitPartitioner.cpp b/source/Lib/CommonLib/UnitPartitioner.cpp index 7f989dfb2..b20ef5877 100644 --- a/source/Lib/CommonLib/UnitPartitioner.cpp +++ b/source/Lib/CommonLib/UnitPartitioner.cpp @@ -339,6 +339,16 @@ void QTBTPartitioner::splitCurrArea( const PartSplit split, const CodingStructur case SBT_VER_QUAD_POS1_SPLIT: case SBT_HOR_QUAD_POS0_SPLIT: case SBT_HOR_QUAD_POS1_SPLIT: +#if JVET_AJ0260_SBT_CORNER_MODE + case SBT_QUAD_POSTL_SPLIT: + case SBT_QUAD_POSTR_SPLIT: + case SBT_QUAD_POSBL_SPLIT: + case SBT_QUAD_POSBR_SPLIT: + case SBT_QUARTER_POSTL_SPLIT: + case SBT_QUARTER_POSTR_SPLIT: + case SBT_QUARTER_POSBL_SPLIT: + case SBT_QUARTER_POSBR_SPLIT: +#endif m_partStack.push_back( PartLevel( split, PartitionerImpl::getSbtTuTiling( currArea(), cs, split ) ) ); break; default: @@ -356,7 +366,12 @@ void QTBTPartitioner::splitCurrArea( const PartSplit split, const CodingStructur { currTrDepth++; } + +#if JVET_AJ0260_SBT_CORNER_MODE + else if( split >= SBT_VER_HALF_POS0_SPLIT && split < NUM_PART_SPLIT ) +#else else if( split >= SBT_VER_HALF_POS0_SPLIT && split <= SBT_HOR_QUAD_POS1_SPLIT ) +#endif { currTrDepth++; } @@ -732,6 +747,16 @@ bool QTBTPartitioner::canSplit( const PartSplit split, const CodingStructure &cs case SBT_VER_QUAD_POS1_SPLIT: case SBT_HOR_QUAD_POS0_SPLIT: case SBT_HOR_QUAD_POS1_SPLIT: +#if JVET_AJ0260_SBT_CORNER_MODE + case SBT_QUAD_POSTL_SPLIT: + case SBT_QUAD_POSTR_SPLIT: + case SBT_QUAD_POSBL_SPLIT: + case SBT_QUAD_POSBR_SPLIT: + case SBT_QUARTER_POSTL_SPLIT: + case SBT_QUARTER_POSTR_SPLIT: + case SBT_QUARTER_POSBL_SPLIT: + case SBT_QUARTER_POSBR_SPLIT: +#endif return currTrDepth == 0; break; case CU_QUAD_SPLIT: @@ -866,7 +891,12 @@ void QTBTPartitioner::exitCurrSplit() CHECK( currTrDepth == 0, "TR depth is '0', although a TU split was performed" ); currTrDepth--; } + +#if JVET_AJ0260_SBT_CORNER_MODE + else if( currSplit >= SBT_VER_HALF_POS0_SPLIT && currSplit < NUM_PART_SPLIT ) +#else else if( currSplit >= SBT_VER_HALF_POS0_SPLIT && currSplit <= SBT_HOR_QUAD_POS1_SPLIT ) +#endif { CHECK( currTrDepth == 0, "TR depth is '0', although a TU split was performed" ); currTrDepth--; @@ -1365,6 +1395,71 @@ Partitioning PartitionerImpl::getSbtTuTiling( const UnitArea& cuArea, const Codi Partitioning ret; int numTiles = 2; int widthFactor, heightFactor, xOffsetFactor, yOffsetFactor; // y = (x * factor) >> 2; + +#if JVET_AJ0260_SBT_CORNER_MODE + CHECK( splitType < SBT_VER_HALF_POS0_SPLIT || splitType >= NUM_PART_SPLIT, "Wrong SBT split" ); + + if( splitType >= SBT_QUAD_POSTL_SPLIT && splitType <= SBT_QUAD_POSBR_SPLIT ) + { + // SBT QUAD restriction + CHECK( cuArea.lwidth() < SBT_QUAD_MIN_BLOCK_SIZE, "Width must be SBT_QUAD_MIN_BLOCK_SIZE or larger for SBT QUAD" ); + CHECK( cuArea.lheight() < SBT_QUAD_MIN_BLOCK_SIZE, "Height must be SBT_QUAD_MIN_BLOCK_SIZE or larger for SBT QUAD" ); + + numTiles = 4; + ret.resize( numTiles, cuArea ); + for( int i = 0; i < numTiles; i++ ) + { + widthFactor = heightFactor = 2; + xOffsetFactor = ( i % 2 ) * 2; + yOffsetFactor = ( i / 2 ) * 2; + + UnitArea& tile = ret[ i ]; + for( CompArea& comp : tile.blocks ) + { + if( !comp.valid() ) + { + continue; + } + + comp.x += ( comp.width * xOffsetFactor ) >> 2; + comp.y += ( comp.height * yOffsetFactor ) >> 2; + comp.width = ( comp.width * widthFactor ) >> 2; + comp.height = ( comp.height * heightFactor ) >> 2; + } + } + return ret; + } + else if( splitType >= SBT_QUARTER_POSTL_SPLIT && splitType <= SBT_QUARTER_POSBR_SPLIT ) + { + // SBT QUARTER restriction + CHECK( cuArea.lwidth() < SBT_QUARTER_MIN_BLOCK_SIZE, "Width must be SBT_QUARTER_MIN_BLOCK_SIZE or larger for SBT QUARTER" ); + CHECK( cuArea.lheight() < SBT_QUARTER_MIN_BLOCK_SIZE, "Height must be SBT_QUARTER_MIN_BLOCK_SIZE or larger for SBT QUARTER" ); + + numTiles = 16; + ret.resize( numTiles, cuArea ); + for( int i = 0; i < numTiles; i++ ) + { + const int x = i % 4; + const int y = i / 4; + + UnitArea& tile = ret[ i ]; + for( CompArea& comp : tile.blocks ) + { + if( !comp.valid() ) + { + continue; + } + + comp.x += ( comp.width * x ) >> 2; + comp.y += ( comp.height * y ) >> 2; + comp.width = comp.width >> 2; + comp.height = comp.height >> 2; + } + } + return ret; + } +#endif + assert( splitType >= SBT_VER_HALF_POS0_SPLIT && splitType <= SBT_HOR_QUAD_POS1_SPLIT ); ret.resize( numTiles, cuArea ); diff --git a/source/Lib/CommonLib/UnitPartitioner.h b/source/Lib/CommonLib/UnitPartitioner.h index 73ac1eb45..47503e2e7 100644 --- a/source/Lib/CommonLib/UnitPartitioner.h +++ b/source/Lib/CommonLib/UnitPartitioner.h @@ -74,6 +74,16 @@ enum PartSplit SBT_VER_QUAD_POS1_SPLIT, SBT_HOR_QUAD_POS0_SPLIT, SBT_HOR_QUAD_POS1_SPLIT, +#if JVET_AJ0260_SBT_CORNER_MODE + SBT_QUAD_POSTL_SPLIT, + SBT_QUAD_POSTR_SPLIT, + SBT_QUAD_POSBL_SPLIT, + SBT_QUAD_POSBR_SPLIT, + SBT_QUARTER_POSTL_SPLIT, + SBT_QUARTER_POSTR_SPLIT, + SBT_QUARTER_POSBL_SPLIT, + SBT_QUARTER_POSBR_SPLIT, +#endif NUM_PART_SPLIT, CU_MT_SPLIT = 1000, ///< dummy element to indicate the MT (multi-type-tree) split CU_BT_SPLIT = 1001, ///< dummy element to indicate the BT split diff --git a/source/Lib/CommonLib/UnitTools.cpp b/source/Lib/CommonLib/UnitTools.cpp index 64f18539c..3aaf19e2a 100644 --- a/source/Lib/CommonLib/UnitTools.cpp +++ b/source/Lib/CommonLib/UnitTools.cpp @@ -31942,6 +31942,10 @@ uint8_t CU::getSbtMode( uint8_t sbtIdx, uint8_t sbtPos ) case SBT_HOR_HALF: sbtMode = sbtPos + SBT_HOR_H0; break; case SBT_VER_QUAD: sbtMode = sbtPos + SBT_VER_Q0; break; case SBT_HOR_QUAD: sbtMode = sbtPos + SBT_HOR_Q0; break; +#if JVET_AJ0260_SBT_CORNER_MODE + case SBT_QUAD: sbtMode = sbtPos + SBT_Q0; break; + case SBT_QUARTER: sbtMode = sbtPos + SBT_QT0; break; +#endif default: assert( 0 ); } @@ -31967,6 +31971,16 @@ uint8_t CU::getSbtIdxFromSbtMode( uint8_t sbtMode ) { return SBT_HOR_QUAD; } +#if JVET_AJ0260_SBT_CORNER_MODE + else if( sbtMode <= SBT_Q3 ) + { + return SBT_QUAD; + } + else if( sbtMode <= SBT_QT3 ) + { + return SBT_QUARTER; + } +#endif else { assert( 0 ); @@ -31992,6 +32006,16 @@ uint8_t CU::getSbtPosFromSbtMode( uint8_t sbtMode ) { return sbtMode - SBT_HOR_Q0; } +#if JVET_AJ0260_SBT_CORNER_MODE + else if( sbtMode <= SBT_Q3 ) + { + return sbtMode - SBT_Q0; + } + else if( sbtMode <= SBT_QT3 ) + { + return sbtMode - SBT_QT0; + } +#endif else { assert( 0 ); @@ -32008,6 +32032,10 @@ uint8_t CU::targetSbtAllowed( uint8_t sbtIdx, uint8_t sbtAllowed ) case SBT_HOR_HALF: val = ( ( sbtAllowed >> SBT_HOR_HALF ) & 0x1 ); break; case SBT_VER_QUAD: val = ( ( sbtAllowed >> SBT_VER_QUAD ) & 0x1 ); break; case SBT_HOR_QUAD: val = ( ( sbtAllowed >> SBT_HOR_QUAD ) & 0x1 ); break; +#if JVET_AJ0260_SBT_CORNER_MODE + case SBT_QUAD: val = ( ( sbtAllowed >> SBT_QUAD ) & 0x1 ); break; + case SBT_QUARTER: val = ( ( sbtAllowed >> SBT_QUARTER ) & 0x1 ); break; +#endif default: CHECK( 1, "unknown SBT type" ); } return val; @@ -32019,15 +32047,29 @@ uint8_t CU::numSbtModeRdo( uint8_t sbtAllowed ) uint8_t sum = 0; num = targetSbtAllowed( SBT_VER_HALF, sbtAllowed ) + targetSbtAllowed( SBT_HOR_HALF, sbtAllowed ); sum += std::min( SBT_NUM_RDO, ( num << 1 ) ); + +#if JVET_AJ0260_SBT_CORNER_MODE + num = ( ( targetSbtAllowed( SBT_VER_QUAD, sbtAllowed ) + targetSbtAllowed( SBT_HOR_QUAD, sbtAllowed ) ) << 1 ) + ( CU::targetSbtAllowed( SBT_QUAD, sbtAllowed ) << 2 ); + sum += std::min<uint8_t>( SBT_NUM_RDO, num ); + + num = targetSbtAllowed( SBT_QUARTER, sbtAllowed ); + sum += std::min( SBT_NUM_RDO, ( num << 2 ) ); +#else num = targetSbtAllowed( SBT_VER_QUAD, sbtAllowed ) + targetSbtAllowed( SBT_HOR_QUAD, sbtAllowed ); sum += std::min( SBT_NUM_RDO, ( num << 1 ) ); +#endif + return sum; } bool CU::isSbtMode( const uint8_t sbtInfo ) { uint8_t sbtIdx = getSbtIdx( sbtInfo ); +#if JVET_AJ0260_SBT_CORNER_MODE + return sbtIdx >= SBT_VER_HALF && sbtIdx < NUMBER_SBT_IDX; +#else return sbtIdx >= SBT_VER_HALF && sbtIdx <= SBT_HOR_QUAD; +#endif } #if JVET_AI0050_SBT_LFNST void CU::getSBTPosAndSize(const CodingUnit &cu, Position& pos, Size& size, uint8_t sbtMode) @@ -32042,6 +32084,16 @@ void CU::getSBTPosAndSize(const CodingUnit &cu, Position& pos, Size& size, uint8 case SBT_VER_Q1: pos = Position((3 * cu.lwidth()) >> 2, 0); size = Size(cu.lwidth() >> 2, cu.lheight()); break; case SBT_HOR_Q0: pos = Position(0, 0); size = Size(cu.lwidth(), cu.lheight() >> 2); break; case SBT_HOR_Q1: pos = Position(0, (3 * cu.lheight()) >> 2); size = Size(cu.lwidth(), cu.lheight() >> 2); break; +#if JVET_AJ0260_SBT_CORNER_MODE + case SBT_Q0: pos = Position( 0, 0 ); size = Size( cu.lwidth() >> 1, cu.lheight() >> 1 ); break; + case SBT_Q1: pos = Position( cu.lwidth() >> 1, 0 ); size = Size( cu.lwidth() >> 1, cu.lheight() >> 1 ); break; + case SBT_Q2: pos = Position( 0, cu.lheight() >> 1 ); size = Size( cu.lwidth() >> 1, cu.lheight() >> 1 ); break; + case SBT_Q3: pos = Position( cu.lwidth() >> 1, cu.lheight() >> 1 ); size = Size( cu.lwidth() >> 1, cu.lheight() >> 1 ); break; + case SBT_QT0: pos = Position( 0, 0 ); size = Size( cu.lwidth() >> 2, cu.lheight() >> 2 ); break; + case SBT_QT1: pos = Position( 3 * cu.lwidth() >> 2, 0 ); size = Size( cu.lwidth() >> 2, cu.lheight() >> 2 ); break; + case SBT_QT2: pos = Position( 0, 3 * cu.lheight() >> 2 ); size = Size( cu.lwidth() >> 2, cu.lheight() >> 2 ); break; + case SBT_QT3: pos = Position( 3 * cu.lwidth() >> 2, 3 * cu.lheight() >> 2 ); size = Size( cu.lwidth() >> 2, cu.lheight() >> 2 ); break; +#endif default: assert(0); } } @@ -32054,10 +32106,23 @@ bool CU::isSameSbtSize( const uint8_t sbtInfo1, const uint8_t sbtInfo2 ) { return sbtIdx2 == SBT_HOR_HALF || sbtIdx2 == SBT_VER_HALF; } +#if JVET_AJ0260_SBT_CORNER_MODE + else if( sbtIdx1 == SBT_VER_QUAD || sbtIdx1 == SBT_HOR_QUAD || sbtIdx1 == SBT_QUAD ) + { + const bool isSame = sbtIdx2 == SBT_VER_QUAD || sbtIdx2 == SBT_HOR_QUAD || sbtIdx2 == SBT_QUAD; + + return isSame; + } + else if( sbtIdx1 == SBT_QUARTER ) + { + return sbtIdx2 == SBT_QUARTER; + } +#else else if( sbtIdx1 == SBT_HOR_QUAD || sbtIdx1 == SBT_VER_QUAD ) { return sbtIdx2 == SBT_HOR_QUAD || sbtIdx2 == SBT_VER_QUAD; } +#endif else { return false; diff --git a/source/Lib/DecoderLib/CABACReader.cpp b/source/Lib/DecoderLib/CABACReader.cpp index 03972d32e..75237a09a 100644 --- a/source/Lib/DecoderLib/CABACReader.cpp +++ b/source/Lib/DecoderLib/CABACReader.cpp @@ -3721,6 +3721,78 @@ void CABACReader::sbt_mode( CodingUnit& cu ) uint8_t sbtVerQuadAllow = CU::targetSbtAllowed( SBT_VER_QUAD, sbtAllowed ); uint8_t sbtHorQuadAllow = CU::targetSbtAllowed( SBT_HOR_QUAD, sbtAllowed ); +#if JVET_AJ0260_SBT_CORNER_MODE + const uint8_t sbtQuadModeAllowed = CU::targetSbtAllowed( SBT_QUAD, sbtAllowed ); + const uint8_t sbtQuarterModeAllowed = CU::targetSbtAllowed( SBT_QUARTER, sbtAllowed ); + + auto sbtQuadMode = [&]( const bool isLast, int& modeIdx ) + { + if( sbtQuadModeAllowed ) + { + modeIdx++; + + CHECK( !sbtVerHalfAllow && !sbtHorHalfAllow, "Wrong SBT QUAD setting"); + + // SBT QUAD restriction + CHECK( cuWidth < SBT_QUAD_MIN_BLOCK_SIZE, "Width must be SBT_QUAD_MIN_BLOCK_SIZE or larger for SBT QUAD" ); + CHECK( cuHeight < SBT_QUAD_MIN_BLOCK_SIZE, "Height must be SBT_QUAD_MIN_BLOCK_SIZE or larger for SBT QUAD" ); + + bool sbtQuad = isLast ? true : m_BinDecoder.decodeBin( Ctx::SbtQuadFlag( 2 ) ); + + if( sbtQuad ) + { + cu.setSbtIdx( SBT_QUAD ); + //pos + uint8_t horIdx = m_BinDecoder.decodeBin( Ctx::SbtPosFlag( 1 ) ); + uint8_t verIdx = m_BinDecoder.decodeBin( Ctx::SbtPosFlag( 2 ) ); + cu.setSbtPos( ( verIdx << 1 ) + horIdx ); + DTRACE( g_trace_ctx, D_SYNTAX, "sbt_mode() pos=(%d,%d) sbtInfo=%d\n", cu.lx(), cu.ly(), ( int ) cu.sbtInfo ); + return true; + } + } + + return false; + }; + + auto sbtQuarterMode = [&]( const bool isLast, int& modeIdx ) + { + if( sbtQuarterModeAllowed ) + { + modeIdx++; + + // SBT QUARTER restriction + CHECK( cuWidth < SBT_QUAD_MIN_BLOCK_SIZE, "Width must be SBT_QUAD_MIN_BLOCK_SIZE or larger for SBT QUAD" ); + CHECK( cuHeight < SBT_QUAD_MIN_BLOCK_SIZE, "Height must be SBT_QUAD_MIN_BLOCK_SIZE or larger for SBT QUAD" ); + + bool bSbtQuarter = isLast ? true : m_BinDecoder.decodeBin( Ctx::SbtQuadFlag( 3 ) ); + + if( bSbtQuarter ) + { + cu.setSbtIdx( SBT_QUARTER ); + //pos + uint8_t horIdx = m_BinDecoder.decodeBin( Ctx::SbtPosFlag( 3 ) ); + uint8_t verIdx = m_BinDecoder.decodeBin( Ctx::SbtPosFlag( 4 ) ); + cu.setSbtPos( ( verIdx << 1 ) + horIdx ); + DTRACE( g_trace_ctx, D_SYNTAX, "sbt_mode() pos=(%d,%d) sbtInfo=%d\n", cu.lx(), cu.ly(), ( int ) cu.sbtInfo ); + return true; + } + } + + return false; + }; + + auto sbtRectMode = [&]( const bool isLast, int& modeIdx ) + { + modeIdx++; + + const bool sbtRect = isLast ? true : m_BinDecoder.decodeBin( Ctx::SbtQuadFlag( 1 ) ); + + if( !sbtRect ) + { + return false; + } +#endif + //bin - type bool sbtQuadFlag = false; if( ( sbtHorHalfAllow || sbtVerHalfAllow ) && ( sbtHorQuadAllow || sbtVerQuadAllow ) ) @@ -3750,6 +3822,29 @@ void CABACReader::sbt_mode( CodingUnit& cu ) cu.setSbtPos( sbtPosFlag ? SBT_POS1 : SBT_POS0 ); DTRACE( g_trace_ctx, D_SYNTAX, "sbt_mode() pos=(%d,%d) sbt_info=%d\n", cu.lx(), cu.ly(), (int)cu.sbtInfo ); + +#if JVET_AJ0260_SBT_CORNER_MODE + return true; + + }; + + int numSbtModesM1 = 1 - ( ( sbtVerHalfAllow + sbtHorHalfAllow + sbtVerQuadAllow + sbtHorQuadAllow ) ? 1 : 0 ) + ( sbtQuadModeAllowed ? 1 : 0 ) + ( sbtQuarterModeAllowed ? 1 : 0 ); + + int modeIdx = 0; + + if( sbtRectMode( modeIdx == numSbtModesM1, modeIdx ) ) + { + return; + } + else if( sbtQuadMode( modeIdx == numSbtModesM1, modeIdx ) ) + { + return; + } + else if( sbtQuarterMode( modeIdx == numSbtModesM1, modeIdx ) ) + { + return; + } +#endif } diff --git a/source/Lib/EncoderLib/CABACWriter.cpp b/source/Lib/EncoderLib/CABACWriter.cpp index 137ebf1a8..e3bdcaa02 100644 --- a/source/Lib/EncoderLib/CABACWriter.cpp +++ b/source/Lib/EncoderLib/CABACWriter.cpp @@ -3558,6 +3558,94 @@ void CABACWriter::sbt_mode( const CodingUnit& cu ) uint8_t sbtHorHalfAllow = CU::targetSbtAllowed( SBT_HOR_HALF, sbtAllowed ); uint8_t sbtVerQuadAllow = CU::targetSbtAllowed( SBT_VER_QUAD, sbtAllowed ); uint8_t sbtHorQuadAllow = CU::targetSbtAllowed( SBT_HOR_QUAD, sbtAllowed ); + +#if JVET_AJ0260_SBT_CORNER_MODE + const uint8_t sbtQuadModeAllowed = CU::targetSbtAllowed( SBT_QUAD, sbtAllowed ); + const uint8_t sbtQuarterModeAllowed = CU::targetSbtAllowed( SBT_QUARTER, sbtAllowed ); + + auto sbtQuadMode = [&]( const bool isLast, int& modeIdx ) + { + if( sbtQuadModeAllowed ) + { + modeIdx++; + + const bool bSbtQuad = sbtIdx == SBT_QUAD; + + CHECK( !sbtVerHalfAllow && !sbtHorHalfAllow, "Wrong SBT QUAD setting" ); + + // SBT QUAD restriction + CHECK( cuWidth < SBT_QUAD_MIN_BLOCK_SIZE, "Width must be SBT_QUAD_MIN_BLOCK_SIZE or larger for SBT QUAD" ); + CHECK( cuHeight < SBT_QUAD_MIN_BLOCK_SIZE, "Height must be SBT_QUAD_MIN_BLOCK_SIZE or larger for SBT QUAD" ); + + if( !isLast ) + { + m_BinEncoder.encodeBin( bSbtQuad, Ctx::SbtQuadFlag( 2 ) ); + } + + if( bSbtQuad ) + { + //pos + uint8_t horIdx = ( sbtPos >> 0 ) & 0x1; + uint8_t verIdx = ( sbtPos >> 1 ) & 0x1; + m_BinEncoder.encodeBin( horIdx, Ctx::SbtPosFlag( 1 ) ); + m_BinEncoder.encodeBin( verIdx, Ctx::SbtPosFlag( 2 ) ); + DTRACE( g_trace_ctx, D_SYNTAX, "sbt_mode() pos=(%d,%d) sbtInfo=%d\n", cu.lx(), cu.ly(), ( int ) cu.sbtInfo ); + return true; + } + } + + return false; + }; + + auto sbtQuarterMode = [&]( const bool isLast, int& modeIdx ) + { + if( sbtQuarterModeAllowed ) + { + modeIdx++; + + const bool bSbtQuarter = sbtIdx == SBT_QUARTER; + + // SBT QUARTER restriction + CHECK( cuWidth < SBT_QUARTER_MIN_BLOCK_SIZE, "Width must be SBT_QUARTER_MIN_BLOCK_SIZE or larger for SBT QUARTER" ); + CHECK( cuHeight < SBT_QUARTER_MIN_BLOCK_SIZE, "Height must be SBT_QUARTER_MIN_BLOCK_SIZE or larger for SBT QUARTER" ); + + if( !isLast ) + { + m_BinEncoder.encodeBin( bSbtQuarter, Ctx::SbtQuadFlag( 3 ) ); + } + + if( bSbtQuarter ) + { + //pos + uint8_t horIdx = ( sbtPos >> 0 ) & 0x1; + uint8_t verIdx = ( sbtPos >> 1 ) & 0x1; + m_BinEncoder.encodeBin( horIdx, Ctx::SbtPosFlag( 3 ) ); + m_BinEncoder.encodeBin( verIdx, Ctx::SbtPosFlag( 4 ) ); + DTRACE( g_trace_ctx, D_SYNTAX, "sbt_mode() pos=(%d,%d) sbtInfo=%d\n", cu.lx(), cu.ly(), ( int ) cu.sbtInfo ); + return true; + } + } + + return false; + }; + + auto sbtRectMode = [&]( const bool isLast, int& modeIdx ) + { + modeIdx++; + + const bool sbtRect = sbtIdx <= SBT_HOR_QUAD; + + if( !isLast ) + { + m_BinEncoder.encodeBin( sbtRect, Ctx::SbtQuadFlag( 1 ) ); + } + + if( !sbtRect ) + { + return false; + } +#endif + //bin - type if( ( sbtHorHalfAllow || sbtVerHalfAllow ) && ( sbtHorQuadAllow || sbtVerQuadAllow ) ) { @@ -3583,6 +3671,29 @@ void CABACWriter::sbt_mode( const CodingUnit& cu ) m_BinEncoder.encodeBin( sbtPosFlag, Ctx::SbtPosFlag( 0 ) ); DTRACE( g_trace_ctx, D_SYNTAX, "sbt_mode() pos=(%d,%d) sbt_info=%d\n", cu.lx(), cu.ly(), (int)cu.sbtInfo ); + +#if JVET_AJ0260_SBT_CORNER_MODE + return true; + + }; + + int numSbtModesM1 = 1 - ( ( sbtVerHalfAllow + sbtHorHalfAllow + sbtVerQuadAllow + sbtHorQuadAllow ) ? 1 : 0 ) + ( sbtQuadModeAllowed ? 1 : 0 ) + ( sbtQuarterModeAllowed ? 1 : 0 ); + + int modeIdx = 0; + + if( sbtRectMode( modeIdx == numSbtModesM1, modeIdx ) ) + { + return; + } + else if( sbtQuadMode( modeIdx == numSbtModesM1, modeIdx ) ) + { + return; + } + else if( sbtQuarterMode( modeIdx == numSbtModesM1, modeIdx ) ) + { + return; + } +#endif } void CABACWriter::end_of_ctu( const CodingUnit& cu, CUCtx& cuCtx ) @@ -9476,6 +9587,7 @@ void CABACWriter::residual_lfnst_mode( const CodingUnit& cu, CUCtx& cuCtx ) { uint32_t idxLFNST = cu.lfnstIdx; assert(idxLFNST < 4); + m_BinEncoder.encodeBin(idxLFNST > 0, Ctx::InterLFNSTIdx(0)); if (idxLFNST > 0) { diff --git a/source/Lib/EncoderLib/EncCu.cpp b/source/Lib/EncoderLib/EncCu.cpp index 6e8558062..b826a8c45 100644 --- a/source/Lib/EncoderLib/EncCu.cpp +++ b/source/Lib/EncoderLib/EncCu.cpp @@ -25193,7 +25193,11 @@ void EncCu::xEncodeInterResidual( CodingStructure *&tempCS if (tempCS->cost < currBestCost) { currBestSbt = cu->sbtInfo; +#if JVET_AJ0260_SBT_CORNER_MODE + currBestTrs = tempCS->tus[cu->getSbtTuIdx()]->mtsIdx[COMPONENT_Y]; +#else currBestTrs = tempCS->tus[cu->sbtInfo ? cu->getSbtPos() : 0]->mtsIdx[COMPONENT_Y]; +#endif assert(currBestTrs == 0 || currBestTrs == 1); currBestCost = tempCS->cost; } diff --git a/source/Lib/EncoderLib/EncSlice.cpp b/source/Lib/EncoderLib/EncSlice.cpp index 305a7379e..95cbbf76a 100644 --- a/source/Lib/EncoderLib/EncSlice.cpp +++ b/source/Lib/EncoderLib/EncSlice.cpp @@ -2111,6 +2111,17 @@ void EncSlice::encodeCtus( Picture* pcPic, const bool bCompressEntireSlice, cons } } #endif +#if JVET_AJ0260_SBT_CORNER_MODE + if( m_pcCuEncoder->getEncCfg()->getUseSBT() ) + { + if( cs.slice->getPOC() == 0 || cs.slice->getSliceType() == I_SLICE ) // ensure sequential and parallel simulation generate same output + { + hashBlkHitPerc = hashBlkHitPerc == -1 ? m_pcCuEncoder->getIbcHashMap().calHashBlkMatchPerc( cs.area.Y() ) : hashBlkHitPerc; + bool isSCC = hashBlkHitPerc >= 20; + m_pcCuEncoder->getEncCfg()->setSBTFast64WidthTh( isSCC ? 1920 : 0 ); + } + } +#endif #if JVET_AJ0057_HL_INTRA_METHOD_CONTROL if (m_pcCuEncoder->getEncCfg()->getIntraToolControlMode() == 0) diff --git a/source/Lib/EncoderLib/InterSearch.cpp b/source/Lib/EncoderLib/InterSearch.cpp index 3adf360af..f4824391e 100644 --- a/source/Lib/EncoderLib/InterSearch.cpp +++ b/source/Lib/EncoderLib/InterSearch.cpp @@ -12891,10 +12891,17 @@ void InterSearch::calcMinDistSbt( CodingStructure &cs, const CodingUnit& cu, con // if this cost is larger than the best cost, no need to try a specific SBT mode int cuWidth = cu.lwidth(); int cuHeight = cu.lheight(); +#if JVET_AJ0260_SBT_CORNER_MODE + const int numPartX = cuWidth >= 8 ? 4 : 1; + const int numPartY = cuHeight >= 8 ? 4 : 1; + + std::vector<std::vector<Distortion>> dist( numPartY, std::vector<Distortion>( numPartX, 0 )); +#else int numPartX = cuWidth >= 16 ? 4 : ( cuWidth == 4 ? 1 : 2 ); int numPartY = cuHeight >= 16 ? 4 : ( cuHeight == 4 ? 1 : 2 ); Distortion dist[4][4]; memset( dist, 0, sizeof( Distortion ) * 16 ); +#endif for( uint32_t c = 0; c < getNumberValidTBlocks( *cs.pcv ); c++ ) { @@ -13027,6 +13034,48 @@ void InterSearch::calcMinDistSbt( CodingStructure &cs, const CodingUnit& cu, con m_estMinDistSbt[SBT_HOR_Q1] = m_estMinDistSbt[SBT_HOR_Q1] >> shift; } +#if JVET_AJ0260_SBT_CORNER_MODE + if( CU::targetSbtAllowed( SBT_QUAD, sbtAllowed ) ) + { + m_estMinDistSbt[ SBT_Q0 ] = m_estMinDistSbt[ SBT_Q1 ] = m_estMinDistSbt[ SBT_Q2 ] = m_estMinDistSbt[ SBT_Q3 ] = 0; + + for( int j = 0; j < numPartY / 2; j++ ) + { + for( int i = 0; i < numPartX / 2; i++ ) + { + m_estMinDistSbt[ SBT_Q0 ] += dist[ j ][ i ]; + m_estMinDistSbt[ SBT_Q1 ] += dist[ j ][ i + ( numPartX >> 1 ) ]; + m_estMinDistSbt[ SBT_Q2 ] += dist[ j + ( numPartY >> 1 ) ][ i ]; + m_estMinDistSbt[ SBT_Q3 ] += dist[ j + ( numPartY >> 1 ) ][ i + ( numPartX >> 1 ) ]; + } + } + m_estMinDistSbt[ SBT_Q0 ] = ( m_estMinDistSbt[ NUMBER_SBT_MODE ] - m_estMinDistSbt[ SBT_Q0 ] ) + ( m_estMinDistSbt[ SBT_Q0 ] >> shift ); + m_estMinDistSbt[ SBT_Q1 ] = ( m_estMinDistSbt[ NUMBER_SBT_MODE ] - m_estMinDistSbt[ SBT_Q1 ] ) + ( m_estMinDistSbt[ SBT_Q1 ] >> shift ); + m_estMinDistSbt[ SBT_Q2 ] = ( m_estMinDistSbt[ NUMBER_SBT_MODE ] - m_estMinDistSbt[ SBT_Q2 ] ) + ( m_estMinDistSbt[ SBT_Q2 ] >> shift ); + m_estMinDistSbt[ SBT_Q3 ] = ( m_estMinDistSbt[ NUMBER_SBT_MODE ] - m_estMinDistSbt[ SBT_Q3 ] ) + ( m_estMinDistSbt[ SBT_Q3 ] >> shift ); + } + + if( CU::targetSbtAllowed( SBT_QUARTER, sbtAllowed ) ) + { + m_estMinDistSbt[ SBT_QT0 ] = m_estMinDistSbt[ SBT_QT1 ] = m_estMinDistSbt[ SBT_QT2 ] = m_estMinDistSbt[ SBT_QT3 ] = 0; + + for( int j = 0; j < numPartY / 4; j++ ) + { + for( int i = 0; i < numPartX / 4; i++ ) + { + m_estMinDistSbt[ SBT_QT0 ] += dist[ j ][ i ]; + m_estMinDistSbt[ SBT_QT1 ] += dist[ j ][ i + ( 3 * numPartX >> 2 ) ]; + m_estMinDistSbt[ SBT_QT2 ] += dist[ j + ( 3 * numPartY >> 2 ) ][ i ]; + m_estMinDistSbt[ SBT_QT3 ] += dist[ j + ( 3 * numPartY >> 2 ) ][ i + ( 3 * numPartX >> 2 ) ]; + } + } + m_estMinDistSbt[ SBT_QT0 ] = ( m_estMinDistSbt[ NUMBER_SBT_MODE ] - m_estMinDistSbt[ SBT_QT0 ] ) + ( m_estMinDistSbt[ SBT_QT0 ] >> shift ); + m_estMinDistSbt[ SBT_QT1 ] = ( m_estMinDistSbt[ NUMBER_SBT_MODE ] - m_estMinDistSbt[ SBT_QT1 ] ) + ( m_estMinDistSbt[ SBT_QT1 ] >> shift ); + m_estMinDistSbt[ SBT_QT2 ] = ( m_estMinDistSbt[ NUMBER_SBT_MODE ] - m_estMinDistSbt[ SBT_QT2 ] ) + ( m_estMinDistSbt[ SBT_QT2 ] >> shift ); + m_estMinDistSbt[ SBT_QT3 ] = ( m_estMinDistSbt[ NUMBER_SBT_MODE ] - m_estMinDistSbt[ SBT_QT3 ] ) + ( m_estMinDistSbt[ SBT_QT3 ] >> shift ); + } +#endif + //SBT fast algorithm 5: try N SBT modes with the lowest distortion Distortion temp[NUMBER_SBT_MODE]; memcpy( temp, m_estMinDistSbt, sizeof( Distortion ) * NUMBER_SBT_MODE ); @@ -13049,13 +13098,29 @@ void InterSearch::calcMinDistSbt( CodingStructure &cs, const CodingUnit& cu, con } startIdx += numRDO; +#if JVET_AJ0260_SBT_CORNER_MODE + numRDO = ( ( CU::targetSbtAllowed( SBT_VER_QUAD, sbtAllowed ) + CU::targetSbtAllowed( SBT_HOR_QUAD, sbtAllowed ) ) << 1 ) + ( CU::targetSbtAllowed( SBT_QUAD, sbtAllowed ) << 2 ); + numRDO = std::min( numRDO, SBT_NUM_RDO ); +#else numRDO = CU::targetSbtAllowed( SBT_VER_QUAD, sbtAllowed ) + CU::targetSbtAllowed( SBT_HOR_QUAD, sbtAllowed ); numRDO = std::min( ( numRDO << 1 ), SBT_NUM_RDO ); +#endif + for( int i = startIdx; i < startIdx + numRDO; i++ ) { Distortion minDist = std::numeric_limits<uint64_t>::max(); + +#if JVET_AJ0260_SBT_CORNER_MODE + for( int n = SBT_VER_Q0; n < NUMBER_SBT_MODE; n++ ) + { + if( n >= SBT_QT0 && n <= SBT_QT3 ) + { + continue; + } +#else for( int n = SBT_VER_Q0; n <= SBT_HOR_Q1; n++ ) { +#endif if( temp[n] < minDist ) { minDist = temp[n]; @@ -13064,6 +13129,26 @@ void InterSearch::calcMinDistSbt( CodingStructure &cs, const CodingUnit& cu, con } temp[m_sbtRdoOrder[i]] = std::numeric_limits<uint64_t>::max(); } + +#if JVET_AJ0260_SBT_CORNER_MODE + startIdx += numRDO; + numRDO = CU::targetSbtAllowed( SBT_QUARTER, sbtAllowed ); + numRDO = std::min( ( numRDO << 2 ), SBT_NUM_RDO ); + + for( int i = startIdx; i < startIdx + numRDO; i++ ) + { + Distortion minDist = std::numeric_limits<uint64_t>::max(); + for( int n = SBT_QT0; n <= SBT_QT3; n++ ) + { + if( temp[ n ] < minDist ) + { + minDist = temp[ n ]; + m_sbtRdoOrder[ i ] = n; + } + } + temp[ m_sbtRdoOrder[ i ] ] = std::numeric_limits<uint64_t>::max(); + } +#endif } uint8_t InterSearch::skipSbtByRDCost( int width, int height, int mtDepth, uint8_t sbtIdx, uint8_t sbtPos, double bestCost, Distortion distSbtOff, double costSbtOff, bool rootCbfSbtOff ) -- GitLab