diff --git a/source/Lib/CommonLib/ContextModelling.h b/source/Lib/CommonLib/ContextModelling.h index 150796090b4fc175cbfa33351287b8fa75118be4..575b2aab4bde637496fb734b73e849ce80036b47 100644 --- a/source/Lib/CommonLib/ContextModelling.h +++ b/source/Lib/CommonLib/ContextModelling.h @@ -448,7 +448,10 @@ public: { violatesLfnstConstrained[CHANNEL_TYPE_LUMA ] = false; violatesLfnstConstrained[CHANNEL_TYPE_CHROMA] = false; - lfnstLastScanPos = false; + lfnstLastScanPos = false; +#if JVET_P1026_MTS_SIGNALLING + violatesMtsCoeffConstraint = false; +#endif } CUCtx(int _qp) : isDQPCoded(false), isChromaQpAdjCoded(false), qgStart(false), @@ -456,7 +459,10 @@ public: { violatesLfnstConstrained[CHANNEL_TYPE_LUMA ] = false; violatesLfnstConstrained[CHANNEL_TYPE_CHROMA] = false; - lfnstLastScanPos = false; + lfnstLastScanPos = false; +#if JVET_P1026_MTS_SIGNALLING + violatesMtsCoeffConstraint = false; +#endif } ~CUCtx() {} public: @@ -466,6 +472,9 @@ public: bool lfnstLastScanPos; int8_t qp; // used as a previous(last) QP and for QP prediction bool violatesLfnstConstrained[MAX_NUM_CHANNEL_TYPE]; +#if JVET_P1026_MTS_SIGNALLING + bool violatesMtsCoeffConstraint; +#endif }; class MergeCtx diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h index 0cb6d479bb92b9856ba0f768bcbd22d915d610aa..e626ef8e89ac44a4860af713b9a0ce0f17911e0f 100644 --- a/source/Lib/CommonLib/TypeDef.h +++ b/source/Lib/CommonLib/TypeDef.h @@ -49,6 +49,9 @@ #include <cstring> #include <assert.h> #include <cassert> + +#define JVET_P1026_MTS_SIGNALLING 1 // JVET-P1026: CU level MTS signalling + #define JVET_P0571_FIX_BS_BDPCM_CHROMA 1 // JVET-P0571: align boundary strength for Chroma BDPCM #define JVET_P0983_REMOVE_SPS_SBT_MAX_SIZE_FLAG 1 // JVET-P0983/JVET-P0391: Remove sps_sbt_max_size_64_flag diff --git a/source/Lib/CommonLib/Unit.cpp b/source/Lib/CommonLib/Unit.cpp index 4b2874848c1270845768df01e0d40798469ca896..af23619b5ea15f8fa304513b9faf7fca99d29e05 100644 --- a/source/Lib/CommonLib/Unit.cpp +++ b/source/Lib/CommonLib/Unit.cpp @@ -859,10 +859,15 @@ int TransformUnit::getTbAreaAfterCoefZeroOut(ComponentID compID) const int tbArea = blocks[compID].width * blocks[compID].height; int tbZeroOutWidth = blocks[compID].width; int tbZeroOutHeight = blocks[compID].height; + +#if JVET_P1026_MTS_SIGNALLING + if ( cs->sps->getUseMTS() && cu->sbtInfo != 0 && blocks[compID].width <= 32 && blocks[compID].height <= 32 && !cu->transQuantBypass && compID == COMPONENT_Y ) +#else #if JVET_P0058_CHROMA_TS if ((mtsIdx[compID] > MTS_SKIP || (cs->sps->getUseMTS() && cu->sbtInfo != 0 && blocks[compID].width <= 32 && blocks[compID].height <= 32)) && !cu->transQuantBypass && compID == COMPONENT_Y) #else if ((mtsIdx > MTS_SKIP || (cs->sps->getUseMTS() && cu->sbtInfo != 0 && blocks[compID].width <= 32 && blocks[compID].height <= 32)) && !cu->transQuantBypass && compID == COMPONENT_Y) +#endif #endif { tbZeroOutWidth = (blocks[compID].width == 32) ? 16 : tbZeroOutWidth; diff --git a/source/Lib/CommonLib/UnitTools.cpp b/source/Lib/CommonLib/UnitTools.cpp index dd49aed52a395140fc5d90784cec7693ebfb7cc8..95141fe5bfba2f4255b414d800c0391218af6fe4 100644 --- a/source/Lib/CommonLib/UnitTools.cpp +++ b/source/Lib/CommonLib/UnitTools.cpp @@ -3765,6 +3765,25 @@ bool CU::bdpcmAllowed( const CodingUnit& cu, const ComponentID compID ) return bdpcmAllowed; } + +#if JVET_P1026_MTS_SIGNALLING +bool CU::isMTSAllowed(const CodingUnit &cu, const ComponentID compID) +{ + SizeType tsMaxSize = 1 << cu.cs->pps->getLog2MaxTransformSkipBlockSize(); + const int maxSize = CU::isIntra( cu ) ? MTS_INTRA_MAX_CU_SIZE : MTS_INTER_MAX_CU_SIZE; + const int cuWidth = cu.blocks[0].lumaSize().width; + const int cuHeight = cu.blocks[0].lumaSize().height; + bool mtsAllowed = cu.chType == CHANNEL_TYPE_LUMA && compID == COMPONENT_Y; + + mtsAllowed &= CU::isIntra( cu ) ? cu.cs->sps->getUseIntraMTS() : cu.cs->sps->getUseInterMTS() && CU::isInter( cu ); + mtsAllowed &= cuWidth <= maxSize && cuHeight <= maxSize; + mtsAllowed &= !cu.ispMode; + mtsAllowed &= !cu.sbtInfo; + mtsAllowed &= !(cu.bdpcmMode && cuWidth <= tsMaxSize && cuHeight <= tsMaxSize); + return mtsAllowed; +} +#endif + // TU tools bool TU::isNonTransformedResidualRotated(const TransformUnit &tu, const ComponentID &compID) @@ -3822,6 +3841,7 @@ bool TU::isTSAllowed(const TransformUnit &tu, const ComponentID compID) return tsAllowed; } +#if !JVET_P1026_MTS_SIGNALLING bool TU::isMTSAllowed(const TransformUnit &tu, const ComponentID compID) { bool mtsAllowed = compID == COMPONENT_Y; @@ -3835,6 +3855,7 @@ bool TU::isMTSAllowed(const TransformUnit &tu, const ComponentID compID) mtsAllowed &= !( tu.cu->bdpcmMode && tu.lwidth() <= transformSkipMaxSize && tu.lheight() <= transformSkipMaxSize); return mtsAllowed; } +#endif int TU::getICTMode( const TransformUnit& tu, int jointCbCr ) { diff --git a/source/Lib/CommonLib/UnitTools.h b/source/Lib/CommonLib/UnitTools.h index a1c766ff382a35bb7b2a6ef16892523d363d5a5d..497679860c42c1483a8f7307c98f2ac1d29d9d3c 100644 --- a/source/Lib/CommonLib/UnitTools.h +++ b/source/Lib/CommonLib/UnitTools.h @@ -90,6 +90,9 @@ namespace CU void setGbiIdx (CodingUnit& cu, uint8_t uh); uint8_t deriveGbiIdx (uint8_t gbiLO, uint8_t gbiL1); bool bdpcmAllowed (const CodingUnit& cu, const ComponentID compID); +#if JVET_P1026_MTS_SIGNALLING + bool isMTSAllowed (const CodingUnit& cu, const ComponentID compID); +#endif bool divideTuInRows ( const CodingUnit &cu ); @@ -199,7 +202,9 @@ namespace TU bool getCbfAtDepth (const TransformUnit &tu, const ComponentID &compID, const unsigned &depth); void setCbfAtDepth ( TransformUnit &tu, const ComponentID &compID, const unsigned &depth, const bool &cbf); bool isTSAllowed (const TransformUnit &tu, const ComponentID compID); +#if !JVET_P1026_MTS_SIGNALLING bool isMTSAllowed (const TransformUnit &tu, const ComponentID compID); +#endif bool hasCrossCompPredInfo (const TransformUnit &tu, const ComponentID &compID); diff --git a/source/Lib/DecoderLib/CABACReader.cpp b/source/Lib/DecoderLib/CABACReader.cpp index 71321b20de47fecd3c0253ec760061f3cfde903a..daa3a7bc58b39492dcb3baf6c0b98e7da9b06a82 100644 --- a/source/Lib/DecoderLib/CABACReader.cpp +++ b/source/Lib/DecoderLib/CABACReader.cpp @@ -1510,7 +1510,10 @@ void CABACReader::cu_residual( CodingUnit& cu, Partitioner &partitioner, CUCtx& } cuCtx.violatesLfnstConstrained[CHANNEL_TYPE_LUMA] = false; cuCtx.violatesLfnstConstrained[CHANNEL_TYPE_CHROMA] = false; - cuCtx.lfnstLastScanPos = false; + cuCtx.lfnstLastScanPos = false; +#if JVET_P1026_MTS_SIGNALLING + cuCtx.violatesMtsCoeffConstraint = false; +#endif ChromaCbfs chromaCbfs; if( cu.ispMode && isLuma( partitioner.chType ) ) @@ -1522,7 +1525,11 @@ void CABACReader::cu_residual( CodingUnit& cu, Partitioner &partitioner, CUCtx& { transform_tree( *cu.cs, partitioner, cuCtx ); } + residual_lfnst_mode( cu, cuCtx ); +#if JVET_P1026_MTS_SIGNALLING + mts_idx ( cu, cuCtx ); +#endif } void CABACReader::rqt_root_cbf( CodingUnit& cu ) @@ -2911,7 +2918,11 @@ void CABACReader::residual_coding( TransformUnit& tu, ComponentID compID, CUCtx& return; // parse transform skip and explicit rdpcm mode +#if JVET_P1026_MTS_SIGNALLING + ts_flag ( tu, compID ); +#else mts_coding ( tu, compID ); +#endif explicit_rdpcm_mode( tu, compID ); #if JVET_P0058_CHROMA_TS @@ -2964,6 +2975,13 @@ void CABACReader::residual_coding( TransformUnit& tu, ComponentID compID, CUCtx& const int lfnstLastScanPosTh = isLuma( compID ) ? LFNST_LAST_SIG_LUMA : LFNST_LAST_SIG_CHROMA; cuCtx.lfnstLastScanPos |= cctx.scanPosLast() >= lfnstLastScanPosTh; } +#if JVET_P1026_MTS_SIGNALLING + if( isLuma(compID) && ( cctx.posX(cctx.scanPosLast()) >= 16 || cctx.posY(cctx.scanPosLast()) >= 16 ) ) + { + cuCtx.violatesMtsCoeffConstraint = true; + } +#endif + // parse subblocks const int stateTransTab = ( tu.cs->slice->getDepQuantEnabledFlag() ? 32040 : 0 ); int state = 0; @@ -2974,10 +2992,15 @@ void CABACReader::residual_coding( TransformUnit& tu, ComponentID compID, CUCtx& for( int subSetId = ( cctx.scanPosLast() >> cctx.log2CGSize() ); subSetId >= 0; subSetId--) { cctx.initSubblock ( subSetId ); + +#if JVET_P1026_MTS_SIGNALLING + if( tu.cs->sps->getUseMTS() && tu.cu->sbtInfo != 0 && tu.blocks[ compID ].height <= 32 && tu.blocks[ compID ].width <= 32 && !tu.cu->transQuantBypass && compID == COMPONENT_Y ) +#else #if JVET_P0058_CHROMA_TS if( ( tu.mtsIdx[compID] > MTS_SKIP || (tu.cs->sps->getUseMTS() && tu.cu->sbtInfo != 0 && tu.blocks[compID].height <= 32 && tu.blocks[compID].width <= 32)) && !tu.cu->transQuantBypass && compID == COMPONENT_Y) #else if( ( tu.mtsIdx > MTS_SKIP || ( tu.cs->sps->getUseMTS() && tu.cu->sbtInfo != 0 && tu.blocks[ compID ].height <= 32 && tu.blocks[ compID ].width <= 32 ) ) && !tu.cu->transQuantBypass && compID == COMPONENT_Y ) +#endif #endif { if( ( tu.blocks[ compID ].height == 32 && cctx.cgPosY() >= ( 16 >> cctx.log2CGHeight() ) ) || ( tu.blocks[ compID ].width == 32 && cctx.cgPosX() >= ( 16 >> cctx.log2CGWidth() ) ) ) @@ -2990,6 +3013,74 @@ void CABACReader::residual_coding( TransformUnit& tu, ComponentID compID, CUCtx& } +#if JVET_P1026_MTS_SIGNALLING +void CABACReader::ts_flag( TransformUnit& tu, ComponentID compID ) +{ +#if JVET_P0058_CHROMA_TS + int tsFlag = tu.cu->bdpcmMode && isLuma(compID) ? 1 : tu.mtsIdx[compID] == MTS_SKIP ? 1 : 0; + int ctxIdx = isLuma(compID) ? 6 : 11; +#else + int tsFlag = tu.cu->bdpcmMode ? 1 : tu.mtsIdx == MTS_SKIP ? 1 : 0; + int ctxIdx = 6; +#endif + + if( TU::isTSAllowed ( tu, compID ) ) + { + RExt__DECODER_DEBUG_BIT_STATISTICS_CREATE_SET_SIZE2( STATS__CABAC_BITS__MTS_FLAGS, tu.blocks[compID], compID ); + tsFlag = m_BinDecoder.decodeBin( Ctx::MTSIndex( ctxIdx ) ); + } + +#if JVET_P0058_CHROMA_TS + tu.mtsIdx[compID] = tsFlag ? MTS_SKIP : MTS_DCT2_DCT2; +#else + tu.mtsIdx = tsFlag ? MTS_SKIP : MTS_DCT2_DCT2; +#endif + + DTRACE(g_trace_ctx, D_SYNTAX, "ts_flag() etype=%d pos=(%d,%d) mtsIdx=%d\n", COMPONENT_Y, tu.cu->lx(), tu.cu->ly(), tsFlag); +} + +void CABACReader::mts_idx( CodingUnit& cu, CUCtx& cuCtx ) +{ + TransformUnit &tu = *cu.firstTU; +#if JVET_P0058_CHROMA_TS + int mtsIdx = tu.mtsIdx[COMPONENT_Y]; // Transform skip flag has already been decoded +#else + int mtsIdx = tu.mtsIdx; // Transform skip flag has already been decoded +#endif + + if( CU::isMTSAllowed( cu, COMPONENT_Y ) && !cuCtx.violatesMtsCoeffConstraint && + cu.lfnstIdx == 0 && mtsIdx != MTS_SKIP && TU::getCbf(tu, COMPONENT_Y) ) + { + RExt__DECODER_DEBUG_BIT_STATISTICS_CREATE_SET_SIZE2( STATS__CABAC_BITS__MTS_FLAGS, tu.blocks[COMPONENT_Y], COMPONENT_Y ); + int ctxIdx = 0; + int symbol = m_BinDecoder.decodeBin( Ctx::MTSIndex( ctxIdx ) ); + + if( symbol ) + { + ctxIdx = 7; + mtsIdx = MTS_DST7_DST7; // mtsIdx = 2 -- 4 + for( int i = 0; i < 3; i++, ctxIdx++ ) + { + symbol = m_BinDecoder.decodeBin( Ctx::MTSIndex( ctxIdx ) ); + mtsIdx += symbol; + + if( !symbol ) + { + break; + } + } + } + } + +#if JVET_P0058_CHROMA_TS + tu.mtsIdx[COMPONENT_Y] = mtsIdx; +#else + tu.mtsIdx = mtsIdx; +#endif + + DTRACE(g_trace_ctx, D_SYNTAX, "mts_idx() etype=%d pos=(%d,%d) mtsIdx=%d\n", COMPONENT_Y, tu.cu->lx(), tu.cu->ly(), mtsIdx); +} +#else void CABACReader::mts_coding( TransformUnit& tu, ComponentID compID ) { const bool tsAllowed = TU::isTSAllowed ( tu, compID ); @@ -3063,7 +3154,8 @@ void CABACReader::mts_coding( TransformUnit& tu, ComponentID compID ) DTRACE(g_trace_ctx, D_SYNTAX, "mts_coding() etype=%d pos=(%d,%d) mtsIdx=%d\n", COMPONENT_Y, tu.cu->lx(), tu.cu->ly(), tu.mtsIdx); #endif } - +#endif + void CABACReader::isp_mode( CodingUnit& cu ) { if( !CU::isIntra( cu ) || !isLuma( cu.chType ) || cu.firstPU->multiRefIdx || !cu.cs->sps->getUseISP() || cu.bdpcmMode || !CU::canUseISP( cu, getFirstComponentOfChannel( cu.chType ) ) ) @@ -3132,12 +3224,21 @@ void CABACReader::residual_lfnst_mode( CodingUnit& cu, CUCtx& cuCtx ) const bool lumaFlag = cu.isSepTree() ? ( isLuma( cu.chType ) ? true : false ) : true; const bool chromaFlag = cu.isSepTree() ? ( isChroma( cu.chType ) ? true : false ) : true; bool nonZeroCoeffNonTsCorner8x8 = ( lumaFlag && cuCtx.violatesLfnstConstrained[CHANNEL_TYPE_LUMA] ) || (chromaFlag && cuCtx.violatesLfnstConstrained[CHANNEL_TYPE_CHROMA] ); +#if JVET_P1026_MTS_SIGNALLING +#if JVET_P0058_CHROMA_TS + const bool isTrSkip = TU::getCbf(*cu.firstTU, COMPONENT_Y) && cu.firstTU->mtsIdx[COMPONENT_Y] == MTS_SKIP; +#else + const bool isTrSkip = TU::getCbf(*cu.firstTU, COMPONENT_Y) && cu.firstTU->mtsIdx == MTS_SKIP; +#endif + if( !cuCtx.lfnstLastScanPos || nonZeroCoeffNonTsCorner8x8 || isTrSkip ) +#else #if JVET_P0058_CHROMA_TS const bool isNonDCT2 = (TU::getCbf(*cu.firstTU, ComponentID(COMPONENT_Y)) && cu.firstTU->mtsIdx[COMPONENT_Y] != MTS_DCT2_DCT2); #else const bool isNonDCT2 = (TU::getCbf(*cu.firstTU, ComponentID(COMPONENT_Y)) && cu.firstTU->mtsIdx != MTS_DCT2_DCT2); #endif if( !cuCtx.lfnstLastScanPos || nonZeroCoeffNonTsCorner8x8 || isNonDCT2 ) +#endif { cu.lfnstIdx = 0; return; @@ -3171,10 +3272,14 @@ int CABACReader::last_sig_coeff( CoeffCodingContext& cctx, TransformUnit& tu, Co unsigned maxLastPosX = cctx.maxLastPosX(); unsigned maxLastPosY = cctx.maxLastPosY(); +#if JVET_P1026_MTS_SIGNALLING + if( tu.cs->sps->getUseMTS() && tu.cu->sbtInfo != 0 && tu.blocks[ compID ].width <= 32 && tu.blocks[ compID ].height <= 32 && !tu.cu->transQuantBypass && compID == COMPONENT_Y ) +#else #if JVET_P0058_CHROMA_TS if( ( tu.mtsIdx[compID] > MTS_SKIP || (tu.cs->sps->getUseMTS() && tu.cu->sbtInfo != 0 && tu.blocks[compID].width <= 32 && tu.blocks[compID].height <= 32)) && !tu.cu->transQuantBypass && compID == COMPONENT_Y) #else if( ( tu.mtsIdx > MTS_SKIP || ( tu.cs->sps->getUseMTS() && tu.cu->sbtInfo != 0 && tu.blocks[ compID ].width <= 32 && tu.blocks[ compID ].height <= 32 ) ) && !tu.cu->transQuantBypass && compID == COMPONENT_Y ) +#endif #endif { maxLastPosX = ( tu.blocks[ compID ].width == 32 ) ? g_uiGroupIdx[ 15 ] : maxLastPosX; diff --git a/source/Lib/DecoderLib/CABACReader.h b/source/Lib/DecoderLib/CABACReader.h index e6e1d6018b9a99d1ef72c474e4c9d76239ad557e..095bd04fc3f7f078982d3365fdd616fd5c8ebc89 100644 --- a/source/Lib/DecoderLib/CABACReader.h +++ b/source/Lib/DecoderLib/CABACReader.h @@ -132,7 +132,12 @@ public: // residual coding (clause 7.3.8.11) void residual_coding ( TransformUnit& tu, ComponentID compID, CUCtx& cuCtx ); +#if JVET_P1026_MTS_SIGNALLING + void ts_flag ( TransformUnit& tu, ComponentID compID ); + void mts_idx ( CodingUnit& cu, CUCtx& cuCtx ); +#else void mts_coding ( TransformUnit& tu, ComponentID compID ); +#endif void residual_lfnst_mode ( CodingUnit& cu, CUCtx& cuCtx ); void isp_mode ( CodingUnit& cu ); void explicit_rdpcm_mode ( TransformUnit& tu, ComponentID compID ); diff --git a/source/Lib/EncoderLib/CABACWriter.cpp b/source/Lib/EncoderLib/CABACWriter.cpp index bcaf7e21c3430334cd2022b9122aee7fcb02271b..1b736e54bf7eba965c525f8554e91bd821290f12 100644 --- a/source/Lib/EncoderLib/CABACWriter.cpp +++ b/source/Lib/EncoderLib/CABACWriter.cpp @@ -1275,7 +1275,10 @@ void CABACWriter::cu_residual( const CodingUnit& cu, Partitioner& partitioner, C cuCtx.violatesLfnstConstrained[CHANNEL_TYPE_LUMA] = false; cuCtx.violatesLfnstConstrained[CHANNEL_TYPE_CHROMA] = false; - cuCtx.lfnstLastScanPos = false; + cuCtx.lfnstLastScanPos = false; +#if JVET_P1026_MTS_SIGNALLING + cuCtx.violatesMtsCoeffConstraint = false; +#endif if( cu.ispMode && isLuma( partitioner.chType ) ) { @@ -1288,6 +1291,9 @@ void CABACWriter::cu_residual( const CodingUnit& cu, Partitioner& partitioner, C } residual_lfnst_mode( cu, cuCtx ); +#if JVET_P1026_MTS_SIGNALLING + mts_idx ( cu, cuCtx ); +#endif } void CABACWriter::rqt_root_cbf( const CodingUnit& cu ) @@ -2681,7 +2687,11 @@ void CABACWriter::residual_coding( const TransformUnit& tu, ComponentID compID, return; // code transform skip and explicit rdpcm mode +#if JVET_P1026_MTS_SIGNALLING + ts_flag ( tu, compID ); +#else mts_coding ( tu, compID ); +#endif explicit_rdpcm_mode( tu, compID ); #if JVET_P0058_CHROMA_TS @@ -2747,6 +2757,13 @@ void CABACWriter::residual_coding( const TransformUnit& tu, ComponentID compID, const int lfnstLastScanPosTh = isLuma( compID ) ? LFNST_LAST_SIG_LUMA : LFNST_LAST_SIG_CHROMA; cuCtx->lfnstLastScanPos |= cctx.scanPosLast() >= lfnstLastScanPosTh; } +#if JVET_P1026_MTS_SIGNALLING + if( cuCtx && isLuma(compID) && ( cctx.posX(cctx.scanPosLast()) >= 16 || cctx.posY(cctx.scanPosLast()) >= 16 ) ) + { + cuCtx->violatesMtsCoeffConstraint = true; + } +#endif + // code last coeff position last_sig_coeff( cctx, tu, compID ); @@ -2760,11 +2777,16 @@ void CABACWriter::residual_coding( const TransformUnit& tu, ComponentID compID, for( int subSetId = ( cctx.scanPosLast() >> cctx.log2CGSize() ); subSetId >= 0; subSetId--) { cctx.initSubblock ( subSetId, sigGroupFlags[subSetId] ); + +#if JVET_P1026_MTS_SIGNALLING + if( tu.cs->sps->getUseMTS() && tu.cu->sbtInfo != 0 && tu.blocks[ compID ].height <= 32 && tu.blocks[ compID ].width <= 32 && !tu.cu->transQuantBypass && compID == COMPONENT_Y ) +#else #if JVET_P0058_CHROMA_TS if( ( tu.mtsIdx[compID] > MTS_SKIP || (tu.cs->sps->getUseMTS() && tu.cu->sbtInfo != 0 && tu.blocks[compID].height <= 32 && tu.blocks[compID].width <= 32)) && !tu.cu->transQuantBypass && compID == COMPONENT_Y) #else if( ( tu.mtsIdx > MTS_SKIP || ( tu.cs->sps->getUseMTS() && tu.cu->sbtInfo != 0 && tu.blocks[ compID ].height <= 32 && tu.blocks[ compID ].width <= 32 ) ) && !tu.cu->transQuantBypass && compID == COMPONENT_Y ) -#endif +#endif +#endif { if( ( tu.blocks[ compID ].height == 32 && cctx.cgPosY() >= ( 16 >> cctx.log2CGHeight() ) ) || ( tu.blocks[ compID ].width == 32 && cctx.cgPosX() >= ( 16 >> cctx.log2CGWidth() ) ) ) @@ -2776,6 +2798,59 @@ void CABACWriter::residual_coding( const TransformUnit& tu, ComponentID compID, } } +#if JVET_P1026_MTS_SIGNALLING +void CABACWriter::ts_flag( const TransformUnit& tu, ComponentID compID ) +{ +#if JVET_P0058_CHROMA_TS + int tsFlag = tu.mtsIdx[compID] == MTS_SKIP ? 1 : 0; + int ctxIdx = isLuma(compID) ? 6 : 11; +#else + int tsFlag = tu.mtsIdx == MTS_SKIP ? 1 : 0; + int ctxIdx = 6; +#endif + + if( TU::isTSAllowed ( tu, compID ) ) + { + m_BinEncoder.encodeBin( tsFlag, Ctx::MTSIndex( ctxIdx ) ); + } + DTRACE( g_trace_ctx, D_SYNTAX, "ts_flag() etype=%d pos=(%d,%d) mtsIdx=%d\n", COMPONENT_Y, tu.cu->lx(), tu.cu->ly(), tsFlag ); +} + +void CABACWriter::mts_idx( const CodingUnit& cu, CUCtx& cuCtx ) +{ + TransformUnit &tu = *cu.firstTU; +#if JVET_P0058_CHROMA_TS + int mtsIdx = tu.mtsIdx[COMPONENT_Y]; +#else + int mtsIdx = tu.mtsIdx; +#endif + + if( CU::isMTSAllowed( cu, COMPONENT_Y ) && !cuCtx.violatesMtsCoeffConstraint && + cu.lfnstIdx == 0 && mtsIdx != MTS_SKIP && TU::getCbf(tu, COMPONENT_Y) ) + { + int symbol = mtsIdx != MTS_DCT2_DCT2 ? 1 : 0; + int ctxIdx = 0; + + m_BinEncoder.encodeBin( symbol, Ctx::MTSIndex( ctxIdx ) ); + + if( symbol ) + { + ctxIdx = 7; + for( int i = 0; i < 3; i++, ctxIdx++ ) + { + symbol = mtsIdx > i + MTS_DST7_DST7 ? 1 : 0; + m_BinEncoder.encodeBin( symbol, Ctx::MTSIndex( ctxIdx ) ); + + if( !symbol ) + { + break; + } + } + } + } + DTRACE( g_trace_ctx, D_SYNTAX, "mts_idx() etype=%d pos=(%d,%d) mtsIdx=%d\n", COMPONENT_Y, tu.cu->lx(), tu.cu->ly(), mtsIdx); +} +#else void CABACWriter::mts_coding( const TransformUnit& tu, ComponentID compID ) { const bool tsAllowed = TU::isTSAllowed ( tu, compID ); @@ -2844,6 +2919,7 @@ void CABACWriter::mts_coding( const TransformUnit& tu, ComponentID compID ) DTRACE( g_trace_ctx, D_SYNTAX, "mts_coding() etype=%d pos=(%d,%d) mtsIdx=%d\n", COMPONENT_Y, tu.cu->lx(), tu.cu->ly(), tu.mtsIdx); #endif } +#endif void CABACWriter::isp_mode( const CodingUnit& cu ) { @@ -2907,12 +2983,22 @@ void CABACWriter::residual_lfnst_mode( const CodingUnit& cu, CUCtx& cuCtx ) const bool lumaFlag = cu.isSepTree() ? ( isLuma( cu.chType ) ? true : false ) : true; const bool chromaFlag = cu.isSepTree() ? ( isChroma( cu.chType ) ? true : false ) : true; bool nonZeroCoeffNonTsCorner8x8 = ( lumaFlag && cuCtx.violatesLfnstConstrained[CHANNEL_TYPE_LUMA] ) || (chromaFlag && cuCtx.violatesLfnstConstrained[CHANNEL_TYPE_CHROMA] ); + +#if JVET_P1026_MTS_SIGNALLING +#if JVET_P0058_CHROMA_TS + const bool isTrSkip = TU::getCbf(*cu.firstTU, COMPONENT_Y) && cu.firstTU->mtsIdx[COMPONENT_Y] == MTS_SKIP; +#else + const bool isTrSkip = TU::getCbf(*cu.firstTU, COMPONENT_Y) && cu.firstTU->mtsIdx == MTS_SKIP; +#endif + if( !cuCtx.lfnstLastScanPos || nonZeroCoeffNonTsCorner8x8 || isTrSkip ) +#else #if JVET_P0058_CHROMA_TS const bool isNonDCT2 = (TU::getCbf(*cu.firstTU, ComponentID(COMPONENT_Y)) && cu.firstTU->mtsIdx[COMPONENT_Y] != MTS_DCT2_DCT2); #else const bool isNonDCT2 = (TU::getCbf(*cu.firstTU, ComponentID(COMPONENT_Y)) && cu.firstTU->mtsIdx != MTS_DCT2_DCT2); #endif if( !cuCtx.lfnstLastScanPos || nonZeroCoeffNonTsCorner8x8 || isNonDCT2 ) +#endif { return; } @@ -2954,10 +3040,14 @@ void CABACWriter::last_sig_coeff( CoeffCodingContext& cctx, const TransformUnit& unsigned maxLastPosX = cctx.maxLastPosX(); unsigned maxLastPosY = cctx.maxLastPosY(); +#if JVET_P1026_MTS_SIGNALLING + if( tu.cs->sps->getUseMTS() && tu.cu->sbtInfo != 0 && tu.blocks[ compID ].width <= 32 && tu.blocks[ compID ].height <= 32 && !tu.cu->transQuantBypass && compID == COMPONENT_Y ) +#else #if JVET_P0058_CHROMA_TS if ((tu.mtsIdx[compID] > MTS_SKIP || (tu.cs->sps->getUseMTS() && tu.cu->sbtInfo != 0 && tu.blocks[compID].width <= 32 && tu.blocks[compID].height <= 32)) && !tu.cu->transQuantBypass && compID == COMPONENT_Y) #else if( ( tu.mtsIdx > MTS_SKIP || ( tu.cs->sps->getUseMTS() && tu.cu->sbtInfo != 0 && tu.blocks[ compID ].width <= 32 && tu.blocks[ compID ].height <= 32 ) ) && !tu.cu->transQuantBypass && compID == COMPONENT_Y ) +#endif #endif { maxLastPosX = ( tu.blocks[compID].width == 32 ) ? g_uiGroupIdx[ 15 ] : maxLastPosX; diff --git a/source/Lib/EncoderLib/CABACWriter.h b/source/Lib/EncoderLib/CABACWriter.h index d1821b30a1e4e6eb17dfba6de2c0da93a6dd69d3..b18e45737a0062dc83337058494de56ed0de5b36 100644 --- a/source/Lib/EncoderLib/CABACWriter.h +++ b/source/Lib/EncoderLib/CABACWriter.h @@ -143,7 +143,12 @@ public: // residual coding (clause 7.3.8.11) void residual_coding ( const TransformUnit& tu, ComponentID compID, CUCtx* cuCtx = nullptr ); +#if JVET_P1026_MTS_SIGNALLING + void ts_flag ( const TransformUnit& tu, ComponentID compID ); + void mts_idx ( const CodingUnit& cu, CUCtx& cuCtx ); +#else void mts_coding ( const TransformUnit& tu, ComponentID compID ); +#endif void residual_lfnst_mode ( const CodingUnit& cu, CUCtx& cuCtx ); void isp_mode ( const CodingUnit& cu ); void explicit_rdpcm_mode ( const TransformUnit& tu, ComponentID compID ); diff --git a/source/Lib/EncoderLib/InterSearch.cpp b/source/Lib/EncoderLib/InterSearch.cpp index d676186951573d7be8a93f6ba38d258e7c39a4d4..bc7f0248d55c9de9d59615d867c69d4a862ef352 100644 --- a/source/Lib/EncoderLib/InterSearch.cpp +++ b/source/Lib/EncoderLib/InterSearch.cpp @@ -6569,7 +6569,12 @@ void InterSearch::xEstimateInterResidualQT(CodingStructure &cs, Partitioner &par #else const bool tsAllowed = TU::isTSAllowed ( tu, compID ); #endif +#if JVET_P1026_MTS_SIGNALLING + const bool mtsAllowed = CU::isMTSAllowed( *tu.cu, compID ); +#else const bool mtsAllowed = TU::isMTSAllowed( tu, compID ); +#endif + uint8_t nNumTransformCands = 1 + ( tsAllowed ? 1 : 0 ) + ( mtsAllowed ? 4 : 0 ); // DCT + TS + 4 MTS = 6 tests std::vector<TrMode> trModes; trModes.push_back( TrMode( 0, true ) ); //DCT2 diff --git a/source/Lib/EncoderLib/IntraSearch.cpp b/source/Lib/EncoderLib/IntraSearch.cpp index f42818d9a60301890ec12849eff39a2bd6cf951a..71202a6f7f3f80acbabc53b91ad023bacb7debbf 100644 --- a/source/Lib/EncoderLib/IntraSearch.cpp +++ b/source/Lib/EncoderLib/IntraSearch.cpp @@ -2175,6 +2175,15 @@ void IntraSearch::xEncCoeffQT( CodingStructure &cs, Partitioner &partitioner, co } if( TU::getCbf( currTU, compID ) ) { +#if JVET_P1026_MTS_SIGNALLING + if( isLuma(compID) ) + { + CUCtx cuCtx; + m_CABACEstimator->residual_coding( currTU, compID, &cuCtx ); + m_CABACEstimator->mts_idx( *currTU.cu, cuCtx ); + } + else +#endif m_CABACEstimator->residual_coding( currTU, compID ); } } @@ -2790,7 +2799,11 @@ bool IntraSearch::xRecurIntraCodingLumaQT( CodingStructure &cs, Partitioner &par tu.depth = currDepth; const bool tsAllowed = TU::isTSAllowed( tu, COMPONENT_Y ); +#if JVET_P1026_MTS_SIGNALLING + const bool mtsAllowed = CU::isMTSAllowed( cu, COMPONENT_Y ); +#else const bool mtsAllowed = TU::isMTSAllowed( tu, COMPONENT_Y ); +#endif std::vector<TrMode> trModes; if( sps.getUseLFNST() )