diff --git a/source/Lib/CommonLib/ContextModelling.cpp b/source/Lib/CommonLib/ContextModelling.cpp index 4502c3d655f7ac5e2ee11f7fd618c7bdb7249a0b..aa3f10f470a911649261488912b47816bee58ce0 100644 --- a/source/Lib/CommonLib/ContextModelling.cpp +++ b/source/Lib/CommonLib/ContextModelling.cpp @@ -102,6 +102,12 @@ CoeffCodingContext::CoeffCodingContext(const TransformUnit& tu, ComponentID comp , m_sigFlagCtxSet { Ctx::SigFlag[m_chType], Ctx::SigFlag[m_chType+2], Ctx::SigFlag[m_chType+4] } , m_parFlagCtxSet ( Ctx::ParFlag[m_chType] ) , m_gtxFlagCtxSet { Ctx::GtxFlag[m_chType], Ctx::GtxFlag[m_chType+2] } +#if JVET_N0280_RESIDUAL_CODING_TS + , m_sigGroupCtxIdTS (-1) + , m_tsSigFlagCtxSet ( Ctx::TsSigFlag ) + , m_tsParFlagCtxSet ( Ctx::TsParFlag ) + , m_tsGtxFlagCtxSet ( Ctx::TsGtxFlag ) +#endif , m_sigCoeffGroupFlag () { // LOGTODO @@ -151,6 +157,11 @@ void CoeffCodingContext::initSubblock( int SubsetId, bool sigGroupFlag ) unsigned sigRight = unsigned( ( CGPosX + 1 ) < m_widthInGroups ? m_sigCoeffGroupFlag[ m_subSetPos + 1 ] : false ); unsigned sigLower = unsigned( ( CGPosY + 1 ) < m_heightInGroups ? m_sigCoeffGroupFlag[ m_subSetPos + m_widthInGroups ] : false ); m_sigGroupCtxId = Ctx::SigCoeffGroup[m_chType]( sigRight | sigLower ); +#if JVET_N0280_RESIDUAL_CODING_TS + unsigned sigLeft = unsigned( int( CGPosX - 1 ) > 0 ? m_sigCoeffGroupFlag[m_subSetPos - 1 ] : false ); + unsigned sigAbove = unsigned( int( CGPosY - 1 ) > 0 ? m_sigCoeffGroupFlag[m_subSetPos - m_widthInGroups] : false ); + m_sigGroupCtxIdTS = Ctx::TsSigCoeffGroup( sigLeft + sigAbove ); +#endif } diff --git a/source/Lib/CommonLib/ContextModelling.h b/source/Lib/CommonLib/ContextModelling.h index 7a2b496c3489814bbedca2bce31b4daa81dcb79f..f6e4946bfce367a302e5d74c943536d64e1f4079 100644 --- a/source/Lib/CommonLib/ContextModelling.h +++ b/source/Lib/CommonLib/ContextModelling.h @@ -61,6 +61,12 @@ public: public: void resetSigGroup () { m_sigCoeffGroupFlag.reset( m_subSetPos ); } void setSigGroup () { m_sigCoeffGroupFlag.set( m_subSetPos ); } +#if JVET_N0280_RESIDUAL_CODING_TS + bool noneSigGroup () { return m_sigCoeffGroupFlag.none(); } + int lastSubSet () { return ( maxNumCoeff() - 1 ) >> log2CGSize(); } + bool isLastSubSet () { return lastSubSet() == m_subSetId; } + bool only1stSigGroup () { return m_sigCoeffGroupFlag.count()-m_sigCoeffGroupFlag[lastSubSet()]==0; } +#endif void setScanPosLast ( int posLast ) { m_scanPosLast = posLast; } public: ComponentID compID () const { return m_compID; } @@ -96,7 +102,14 @@ public: unsigned maxLastPosY () const { return m_maxLastPosY; } unsigned lastXCtxId ( unsigned posLastX ) const { return m_CtxSetLastX( m_lastOffsetX + ( posLastX >> m_lastShiftX ) ); } unsigned lastYCtxId ( unsigned posLastY ) const { return m_CtxSetLastY( m_lastOffsetY + ( posLastY >> m_lastShiftY ) ); } +#if JVET_N0280_RESIDUAL_CODING_TS + bool isContextCoded () { return --m_remainingContextBins >= 0; } + int numCtxBins () const { return m_remainingContextBins; } + void setNumCtxBins ( int n ) { m_remainingContextBins = n; } + unsigned sigGroupCtxId ( bool ts = false ) const { return ts ? m_sigGroupCtxIdTS : m_sigGroupCtxId; } +#else unsigned sigGroupCtxId () const { return m_sigGroupCtxId; } +#endif unsigned sigCtxIdAbs( int scanPos, const TCoeff* coeff, const int state ) { @@ -189,6 +202,56 @@ public: #endif } +#if JVET_N0280_RESIDUAL_CODING_TS + unsigned sigCtxIdAbsTS( int scanPos, const TCoeff* coeff ) + { + const uint32_t posY = m_scan[scanPos].y; + const uint32_t posX = m_scan[scanPos].x; + const TCoeff* posC = coeff + posX + posY * m_width; + int numPos = 0; +#define UPDATE(x) {int a=abs(x);numPos+=!!a;} + if( posX > 0 ) + { + UPDATE( posC[-1] ); + } + if( posY > 0 ) + { + UPDATE( posC[-(int)m_width] ); + } +#undef UPDATE + + return m_tsSigFlagCtxSet( numPos ); + } + + unsigned parityCtxIdAbsTS () const { return m_tsParFlagCtxSet( 0 ); } + unsigned greaterXCtxIdAbsTS ( uint8_t offset ) const { return m_tsGtxFlagCtxSet( offset ); } + + unsigned templateAbsSumTS( int scanPos, const TCoeff* coeff ) + { + const uint32_t posY = m_scan[scanPos].y; + const uint32_t posX = m_scan[scanPos].x; + const TCoeff* posC = coeff + posX + posY * m_width; + int sum = 0; + if (posX > 0) + { + sum += abs(posC[-1]); + } + if (posY > 0) + { + sum += abs(posC[-(int)m_width]); + } + + const uint32_t auiGoRicePars[32] = + { + 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 2, 2, 2, 2, 2, 2, 2 + }; + + return auiGoRicePars[ std::min(sum, 31) ]; + } +#endif private: // constant @@ -235,6 +298,13 @@ private: CtxSet m_sigFlagCtxSet[3]; CtxSet m_parFlagCtxSet; CtxSet m_gtxFlagCtxSet[2]; +#if JVET_N0280_RESIDUAL_CODING_TS + unsigned m_sigGroupCtxIdTS; + CtxSet m_tsSigFlagCtxSet; + CtxSet m_tsParFlagCtxSet; + CtxSet m_tsGtxFlagCtxSet; + int m_remainingContextBins; +#endif std::bitset<MLS_GRP_NUM> m_sigCoeffGroupFlag; }; diff --git a/source/Lib/CommonLib/Contexts.cpp b/source/Lib/CommonLib/Contexts.cpp index 1d1d827602c995550e22c5a85c9b68037c032a45..48c8f7d981f7aef3a5ad5ae016340306f9e08807 100644 --- a/source/Lib/CommonLib/Contexts.cpp +++ b/source/Lib/CommonLib/Contexts.cpp @@ -813,6 +813,63 @@ const CtxSet ContextSetCfg::JointCbCrFlag = ContextSetCfg::addCtxSet }); #endif +#if JVET_N0280_RESIDUAL_CODING_TS +const CtxSet ContextSetCfg::TsSigCoeffGroup = +{ + ContextSetCfg::addCtxSet + ({ + { CNU, CNU, CNU, }, + { CNU, CNU, CNU, }, + { CNU, CNU, CNU, }, + { DWS, DWS, DWS, }, + }), +}; + +const CtxSet ContextSetCfg::TsSigFlag = +{ + ContextSetCfg::addCtxSet + ({ + { CNU, CNU, CNU, }, + { CNU, CNU, CNU, }, + { CNU, CNU, CNU, }, + { DWS, DWS, DWS, }, + }), +}; + +const CtxSet ContextSetCfg::TsParFlag = +{ + ContextSetCfg::addCtxSet + ({ + { CNU }, + { CNU }, + { CNU }, + { DWS }, + }), +}; + +const CtxSet ContextSetCfg::TsGtxFlag = +{ + ContextSetCfg::addCtxSet + ({ + { CNU, CNU, CNU, CNU, CNU, CNU, CNU, CNU, CNU, CNU, CNU, CNU, CNU, CNU, CNU, }, + { CNU, CNU, CNU, CNU, CNU, CNU, CNU, CNU, CNU, CNU, CNU, CNU, CNU, CNU, CNU, }, + { CNU, CNU, CNU, CNU, CNU, CNU, CNU, CNU, CNU, CNU, CNU, CNU, CNU, CNU, CNU, }, + { DWS, DWS, DWS, DWS, DWS, DWS, DWS, DWS, DWS, DWS, DWS, DWS, DWS, DWS, DWS, }, + }), +}; + +const CtxSet ContextSetCfg::TsResidualSign = +{ + ContextSetCfg::addCtxSet + ({ + { CNU, }, + { CNU, }, + { CNU, }, + { DWS, }, + }), +}; +#endif + const unsigned ContextSetCfg::NumberOfContexts = (unsigned)ContextSetCfg::sm_InitTables[0].size(); diff --git a/source/Lib/CommonLib/Contexts.h b/source/Lib/CommonLib/Contexts.h index a015dce3933c9727b55a572cd4abafa288e46b1f..9841ca34eb162d610a5a74e6de9fd1c9f8394b86 100644 --- a/source/Lib/CommonLib/Contexts.h +++ b/source/Lib/CommonLib/Contexts.h @@ -228,6 +228,13 @@ public: static const CtxSet SigFlag [6]; // [ ChannelType + State ] static const CtxSet ParFlag [2]; // [ ChannelType ] static const CtxSet GtxFlag [4]; // [ ChannelType + x ] +#if JVET_N0280_RESIDUAL_CODING_TS + static const CtxSet TsSigCoeffGroup; + static const CtxSet TsSigFlag; + static const CtxSet TsParFlag; + static const CtxSet TsGtxFlag; + static const CtxSet TsResidualSign; +#endif static const CtxSet MVPIdx; static const CtxSet SaoMergeFlag; static const CtxSet SaoTypeIdx; diff --git a/source/Lib/CommonLib/DepQuant.cpp b/source/Lib/CommonLib/DepQuant.cpp index 2fc1ab08566713fc491748cdafc1f20135d058fa..5331f35170ed9aee33fca88227beff634b9d0909 100644 --- a/source/Lib/CommonLib/DepQuant.cpp +++ b/source/Lib/CommonLib/DepQuant.cpp @@ -1656,7 +1656,11 @@ DepQuant::~DepQuant() void DepQuant::quant( TransformUnit &tu, const ComponentID &compID, const CCoeffBuf &pSrc, TCoeff &uiAbsSum, const QpParam &cQP, const Ctx& ctx ) { +#if JVET_N0280_RESIDUAL_CODING_TS + if( tu.cs->slice->getDepQuantEnabledFlag() && tu.mtsIdx != 1 ) +#else if( tu.cs->slice->getDepQuantEnabledFlag() ) +#endif { static_cast<DQIntern::DepQuant*>(p)->quant( tu, pSrc, compID, cQP, Quant::m_dLambda, ctx, uiAbsSum ); } @@ -1668,7 +1672,11 @@ void DepQuant::quant( TransformUnit &tu, const ComponentID &compID, const CCoeff void DepQuant::dequant( const TransformUnit &tu, CoeffBuf &dstCoeff, const ComponentID &compID, const QpParam &cQP ) { +#if JVET_N0280_RESIDUAL_CODING_TS + if( tu.cs->slice->getDepQuantEnabledFlag() && tu.mtsIdx != 1 ) +#else if( tu.cs->slice->getDepQuantEnabledFlag() ) +#endif { static_cast<DQIntern::DepQuant*>(p)->dequant( tu, dstCoeff, compID, cQP ); } diff --git a/source/Lib/CommonLib/QuantRDOQ.cpp b/source/Lib/CommonLib/QuantRDOQ.cpp index f0c880324ed192c26afa429e0e037ae94bc72a56..cdeea7d257e47cd513192cf38c8a93c2d5fdb963 100644 --- a/source/Lib/CommonLib/QuantRDOQ.cpp +++ b/source/Lib/CommonLib/QuantRDOQ.cpp @@ -555,7 +555,18 @@ void QuantRDOQ::quant(TransformUnit &tu, const ComponentID &compID, const CCoeff if (!m_useSelectiveRDOQ || xNeedRDOQ(tu, compID, piCoef, cQP)) { #endif +#if JVET_N0280_RESIDUAL_CODING_TS + if( isLuma( compID ) && useTransformSkip ) + { + xRateDistOptQuantTS( tu, compID, pSrc, uiAbsSum, cQP, ctx ); + } + else + { + xRateDistOptQuant( tu, compID, pSrc, uiAbsSum, cQP, ctx ); + } +#else xRateDistOptQuant( tu, compID, pSrc, uiAbsSum, cQP, ctx ); +#endif #if T0196_SELECTIVE_RDOQ } else @@ -1232,4 +1243,341 @@ void QuantRDOQ::xRateDistOptQuant(TransformUnit &tu, const ComponentID &compID, #endif } +#if JVET_N0280_RESIDUAL_CODING_TS +void QuantRDOQ::xRateDistOptQuantTS( TransformUnit &tu, const ComponentID &compID, const CCoeffBuf &coeffs, TCoeff &absSum, const QpParam &qp, const Ctx &ctx ) +{ + const FracBitsAccess& fracBits = ctx.getFracBitsAcess(); + + const SPS &sps = *tu.cs->sps; + const CompArea &rect = tu.blocks[compID]; + const uint32_t width = rect.width; + const uint32_t height = rect.height; + const ChannelType chType = toChannelType(compID); + const int channelBitDepth = sps.getBitDepth( chType ); + + const bool extendedPrecision = sps.getSpsRangeExtension().getExtendedPrecisionProcessingFlag(); + const int maxLog2TrDynamicRange = sps.getMaxLog2TrDynamicRange(chType); + + int transformShift = getTransformShift( channelBitDepth, rect.size(), maxLog2TrDynamicRange ); + + if( extendedPrecision ) + { + transformShift = std::max<int>( 0, transformShift ); + } + + double blockUncodedCost = 0; +#if HEVC_USE_SCALING_LISTS + const uint32_t log2BlockHeight = g_aucLog2[height]; +#endif + const uint32_t maxNumCoeff = rect.area(); + + CHECK( compID >= MAX_NUM_TBLOCKS, "Invalid component ID" ); + +#if HEVC_USE_SCALING_LISTS + int scalingListType = getScalingListType( tu.cu->predMode, compID ); + CHECK( scalingListType >= SCALING_LIST_NUM, "Invalid scaling list" ); +#endif + + const TCoeff *srcCoeff = coeffs.buf; + TCoeff *dstCoeff = tu.getCoeffs( compID ).buf; + + double *costCoeff = m_pdCostCoeff; + double *costSig = m_pdCostSig; + double *costCoeff0 = m_pdCostCoeff0; + + memset( m_pdCostCoeff, 0, sizeof( double ) * maxNumCoeff ); + memset( m_pdCostSig, 0, sizeof( double ) * maxNumCoeff ); + + const int qBits = QUANT_SHIFT + qp.per + transformShift; // Right shift of non-RDOQ quantizer; level = (coeff*uiQ + offset)>>q_bits + +#if HM_QTBT_AS_IN_JEM_QUANT + const int quantisationCoefficient = ( TU::needsSqrt2Scale( tu, compID ) ? ( g_quantScales[qp.rem] * 181 ) >> 7 : g_quantScales[qp.rem] ); + const double errorScale = xGetErrScaleCoeff( TU::needsSqrt2Scale( tu, compID ), width, height, qp.rem, maxLog2TrDynamicRange, channelBitDepth ); +#else + const double blkErrScale = ( TU::needsQP3Offset( tu, compID ) ? 2.0 : 1.0 ); + const int quantisationCoefficient = g_quantScales[qp.rem]; + const double errorScale = blkErrScale * xGetErrScaleCoeff( width, height, qp.rem, maxLog2TrDynamicRange, channelBitDepth ); +#endif + + const TCoeff entropyCodingMaximum = ( 1 << maxLog2TrDynamicRange ) - 1; + +#if HEVC_USE_SIGN_HIDING + CoeffCodingContext cctx( tu, compID, tu.cs->slice->getSignDataHidingEnabledFlag() ); +#else + CoeffCodingContext cctx( tu, compID ); +#endif + const int sbSizeM1 = ( 1 << cctx.log2CGSize() ) - 1; + double baseCost = 0; + uint32_t goRiceParam = 0; + + double *costSigSubBlock = m_pdCostCoeffGroupSig; + memset( costSigSubBlock, 0, ( maxNumCoeff >> cctx.log2CGSize() ) * sizeof( double ) ); + + const int sbNum = width * height >> cctx.log2CGSize(); + int scanPos; + coeffGroupRDStats rdStats; + + bool anySigCG = false; + + for( int sbId = 0; sbId < sbNum; sbId++ ) + { + cctx.initSubblock( sbId ); + + memset( &rdStats, 0, sizeof (coeffGroupRDStats)); + + for( int scanPosInSB = 0; scanPosInSB <= sbSizeM1; scanPosInSB++ ) + { + scanPos = cctx.minSubPos() + scanPosInSB; + //===== quantization ===== + uint32_t blkPos = cctx.blockPos( scanPos ); + + // set coeff + const int64_t tmpLevel = int64_t( abs( srcCoeff[blkPos] ) ) * quantisationCoefficient; + const Intermediate_Int levelDouble = (Intermediate_Int)std::min<int64_t>( tmpLevel, std::numeric_limits<Intermediate_Int>::max() - ( Intermediate_Int( 1 ) << ( qBits - 1 ) ) ); + uint32_t maxAbsLevel = std::min<uint32_t>( uint32_t( entropyCodingMaximum ), uint32_t( ( levelDouble + ( Intermediate_Int( 1 ) << ( qBits - 1 ) ) ) >> qBits ) ); + + const double err = double( levelDouble ); + costCoeff0[ scanPos ] = err * err * errorScale; + blockUncodedCost += costCoeff0[ scanPos ]; + dstCoeff[ blkPos ] = maxAbsLevel; + + //===== coefficient level estimation ===== + unsigned ctxIdSig = cctx.sigCtxIdAbsTS( scanPos, dstCoeff ); + uint32_t cLevel; + const BinFracBits fracBitsPar = fracBits.getFracBitsArray( cctx.parityCtxIdAbsTS() ); + + goRiceParam = cctx.templateAbsSumTS( scanPos, dstCoeff ); + const BinFracBits fracBitsSign = fracBits.getFracBitsArray( Ctx::TsResidualSign( toChannelType(compID) ) ); + const uint8_t sign = srcCoeff[ blkPos ] < 0 ? 1 : 0; + + DTRACE_COND( ( maxAbsLevel != 0 ), g_trace_ctx, D_RDOQ_MORE, " uiCtxSig=%d", ctxIdSig ); + + const BinFracBits fracBitsSig = fracBits.getFracBitsArray( ctxIdSig ); + cLevel = xGetCodedLevelTS( costCoeff[ scanPos ], costCoeff0[ scanPos ], costSig[ scanPos ], + levelDouble, maxAbsLevel, &fracBitsSig, fracBitsPar, cctx, fracBits, fracBitsSign, sign, goRiceParam, qBits, errorScale, 0, extendedPrecision, maxLog2TrDynamicRange ); + dstCoeff[ blkPos ] = cLevel; + baseCost += costCoeff[ scanPos ]; + rdStats.d64SigCost += costSig[ scanPos ]; + + if( scanPosInSB == 0 ) + { + rdStats.d64SigCost_0 = costSig[ scanPos ]; + } + if( dstCoeff[ blkPos ] ) + { + cctx.setSigGroup(); + rdStats.d64CodedLevelandDist += costCoeff [ scanPos ] - costSig[ scanPos ]; + rdStats.d64UncodedDist += costCoeff0[ scanPos ]; + if( scanPosInSB != 0 ) + { + rdStats.iNNZbeforePos0++; + } + } + } //end for (iScanPosinCG) + + if( !cctx.isSigGroup() ) + { + const BinFracBits fracBitsSigGroup = fracBits.getFracBitsArray( cctx.sigGroupCtxId( true ) ); + baseCost += xGetRateSigCoeffGroup( fracBitsSigGroup, 0 ) - rdStats.d64SigCost; + costSigSubBlock[cctx.subSetId()] = xGetRateSigCoeffGroup( fracBitsSigGroup, 0 ); + } + else if( sbId != sbSizeM1 || anySigCG ) + { + if( rdStats.iNNZbeforePos0 == 0 ) + { + baseCost -= rdStats.d64SigCost_0; + rdStats.d64SigCost -= rdStats.d64SigCost_0; + } + // rd-cost if SigCoeffGroupFlag = 0, initialization + double costZeroSB = baseCost; + + const BinFracBits fracBitsSigGroup = fracBits.getFracBitsArray( cctx.sigGroupCtxId( true ) ); + + baseCost += xGetRateSigCoeffGroup( fracBitsSigGroup, 1 ); + costZeroSB += xGetRateSigCoeffGroup( fracBitsSigGroup, 0 ); + costSigSubBlock[ cctx.subSetId() ] = xGetRateSigCoeffGroup( fracBitsSigGroup, 1 ); + + costZeroSB += rdStats.d64UncodedDist; // distortion for resetting non-zero levels to zero levels + costZeroSB -= rdStats.d64CodedLevelandDist; // distortion and level cost for keeping all non-zero levels + costZeroSB -= rdStats.d64SigCost; // sig cost for all coeffs, including zero levels and non-zerl levels + + if( costZeroSB < baseCost ) + { + cctx.resetSigGroup(); + baseCost = costZeroSB; + costSigSubBlock[ cctx.subSetId() ] = xGetRateSigCoeffGroup( fracBitsSigGroup, 0 ); + + for( int scanPosInSB = 0; scanPosInSB < sbSizeM1; scanPosInSB++ ) + { + scanPos = cctx.minSubPos() + scanPosInSB; + uint32_t blkPos = cctx.blockPos( scanPos ); + + if( dstCoeff[ blkPos ] ) + { + dstCoeff[ blkPos ] = 0; + costCoeff[ scanPos ] = costCoeff0[ scanPos ]; + costSig[ scanPos] = 0; + } + } + } + else + { + anySigCG = true; + } + } + } + + //===== estimate last position ===== + for( int scanPos = 0; scanPos < maxNumCoeff; scanPos++ ) + { + int blkPos = cctx.blockPos( scanPos ); + TCoeff level = dstCoeff[ blkPos ]; + absSum += level; + dstCoeff[ blkPos ] = ( level != 0 && srcCoeff[ blkPos ] < 0 ) ? -level : level; + } +} + +inline uint32_t QuantRDOQ::xGetCodedLevelTS( double& codedCost, + double& codedCost0, + double& codedCostSig, + Intermediate_Int levelDouble, + uint32_t maxAbsLevel, + const BinFracBits* fracBitsSig, + const BinFracBits& fracBitsPar, + const CoeffCodingContext& cctx, + const FracBitsAccess& fracBitsAccess, + const BinFracBits& fracBitsSign, + const uint8_t sign, + uint16_t ricePar, + int qBits, + double errorScale, + bool isLast, + bool useLimitedPrefixLength, + const int maxLog2TrDynamicRange + ) const +{ + double currCostSig = 0; + uint32_t bestAbsLevel = 0; + + if( !isLast && maxAbsLevel < 3 ) + { + codedCostSig = xGetRateSigCoef( *fracBitsSig, 0 ); + codedCost = codedCost0 + codedCostSig; + if( maxAbsLevel == 0 ) + { + return bestAbsLevel; + } + } + else + { + codedCost = MAX_DOUBLE; + } + + if( !isLast ) + { + currCostSig = xGetRateSigCoef( *fracBitsSig, 1 ); + } + + uint32_t minAbsLevel = ( maxAbsLevel > 1 ? maxAbsLevel - 1 : 1 ); + for( int absLevel = maxAbsLevel; absLevel >= minAbsLevel ; absLevel-- ) + { + double err = double( levelDouble - ( Intermediate_Int( absLevel ) << qBits ) ); + double currCost = err * err * errorScale + xGetICost( xGetICRateTS( absLevel, fracBitsPar, cctx, fracBitsAccess, fracBitsSign, sign, ricePar, useLimitedPrefixLength, maxLog2TrDynamicRange ) ); + currCost += currCostSig; + + if( currCost < codedCost ) + { + bestAbsLevel = absLevel; + codedCost = currCost; + codedCostSig = currCostSig; + } + } + + return bestAbsLevel; +} + +inline int QuantRDOQ::xGetICRateTS( const uint32_t absLevel, + const BinFracBits& fracBitsPar, + const CoeffCodingContext& cctx, + const FracBitsAccess& fracBitsAccess, + const BinFracBits& fracBitsSign, + const uint8_t sign, + const uint16_t ricePar, + const bool useLimitedPrefixLength, + const int maxLog2TrDynamicRange ) const +{ + int rate = fracBitsSign.intBits[sign]; + + const uint16_t ctxGt1 = cctx.greaterXCtxIdAbsTS( 0 ); + const BinFracBits &fracBitsGt1 = fracBitsAccess.getFracBitsArray( ctxGt1 ); + + if( absLevel > 1 ) + { + rate += fracBitsGt1.intBits[1]; + rate += fracBitsPar.intBits[( absLevel - 2 ) & 1]; + + int cutoffVal = 2; + const int numGtBins = 4; + for( int i = 0; i < numGtBins; i++ ) + { + if( absLevel >= cutoffVal ) + { + const uint16_t ctxGtX = cctx.greaterXCtxIdAbsTS( cutoffVal>>1 ); + const BinFracBits &fracBitsGtX = fracBitsAccess.getFracBitsArray( ctxGtX ); + unsigned gtX = ( absLevel >= ( cutoffVal + 2 ) ); + rate += fracBitsGtX.intBits[gtX]; + } + cutoffVal += 2; + } + + if( absLevel >= cutoffVal ) + { + uint32_t symbol = ( absLevel - cutoffVal ) >> 1; + uint32_t length; + const int threshold = COEF_REMAIN_BIN_REDUCTION; + if( symbol < ( threshold << ricePar ) ) + { + length = symbol >> ricePar; + rate += ( length + 1 + ricePar ) << SCALE_BITS; + } + else if( useLimitedPrefixLength ) + { + const uint32_t maximumPrefixLength = ( 32 - ( COEF_REMAIN_BIN_REDUCTION + maxLog2TrDynamicRange ) ); + + uint32_t prefixLength = 0; + uint32_t suffix = ( symbol >> ricePar ) - COEF_REMAIN_BIN_REDUCTION; + + while( ( prefixLength < maximumPrefixLength ) && ( suffix > ( ( 2 << prefixLength ) - 2 ) ) ) + { + prefixLength++; + } + + const uint32_t suffixLength = ( prefixLength == maximumPrefixLength ) ? ( maxLog2TrDynamicRange - ricePar ) : ( prefixLength + 1/*separator*/ ); + + rate += ( COEF_REMAIN_BIN_REDUCTION + prefixLength + suffixLength + ricePar ) << SCALE_BITS; + } + else + { + length = ricePar; + symbol = symbol - ( threshold << ricePar ); + while( symbol >= ( 1 << length ) ) + { + symbol -= ( 1 << ( length++ ) ); + } + rate += ( threshold + length + 1 - ricePar + length ) << SCALE_BITS; + } + } + } + else if( absLevel == 1 ) + { + rate += fracBitsGt1.intBits[0]; + } + else + { + rate = 0; + } + return rate; +} +#endif + //! \} diff --git a/source/Lib/CommonLib/QuantRDOQ.h b/source/Lib/CommonLib/QuantRDOQ.h index a51bdca698c3c03bada83ab39ef21562d4a4609c..7077e6ef426a37f3001aad689e4a2ca1fa615105 100644 --- a/source/Lib/CommonLib/QuantRDOQ.h +++ b/source/Lib/CommonLib/QuantRDOQ.h @@ -120,6 +120,37 @@ private: inline double xGetICost ( double dRate ) const; inline double xGetIEPRate ( ) const; +#if JVET_N0280_RESIDUAL_CODING_TS + void xRateDistOptQuantTS( TransformUnit &tu, const ComponentID &compID, const CCoeffBuf &coeffs, TCoeff &absSum, const QpParam &qp, const Ctx &ctx ); + + inline uint32_t xGetCodedLevelTS( double& codedCost, + double& codedCost0, + double& codedCostSig, + Intermediate_Int levelDouble, + uint32_t maxAbsLevel, + const BinFracBits* fracBitsSig, + const BinFracBits& fracBitsPar, + const CoeffCodingContext& cctx, + const FracBitsAccess& fracBitsAccess, + const BinFracBits& fracBitsSign, + const uint8_t sign, + uint16_t ricePar, + int qBits, + double errorScale, + bool isLast, + bool useLimitedPrefixLength, + const int maxLog2TrDynamicRange ) const; + + inline int xGetICRateTS ( const uint32_t absLevel, + const BinFracBits& fracBitsPar, + const CoeffCodingContext& cctx, + const FracBitsAccess& fracBitsAccess, + const BinFracBits& fracBitsSign, + const uint8_t sign, + const uint16_t ricePar, + const bool useLimitedPrefixLength, + const int maxLog2TrDynamicRange ) const; +#endif private: #if HEVC_USE_SCALING_LISTS bool m_isErrScaleListOwner; diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h index 67b78ab04afc85b4022751f9a8c292b9b54b429d..c93e20f3dcd158805d14135c887c0c91e7fe8413 100644 --- a/source/Lib/CommonLib/TypeDef.h +++ b/source/Lib/CommonLib/TypeDef.h @@ -50,6 +50,8 @@ #include <assert.h> #include <cassert> +#define JVET_N0280_RESIDUAL_CODING_TS 1 + #define JVET_N0103_CGSIZE_HARMONIZATION 1 // Chroma CG sizes aligned to luma CG sizes #define JVET_N0146_DMVR_BDOF_CONDITION 1 // JVET-N146/N0162/N0442/N0153/N0262/N0440/N0086 applicable condition of DMVR and BDOF @@ -61,7 +63,9 @@ #define JVET_N0843_BVP_SIMPLIFICATION 1 #define JVET_N0448_N0380 1 // When MaxNumMergeCand is 1, MMVD_BASE_MV_NUM is inferred to be 1. + #define JVET_N0266_SMALL_BLOCKS 1 // remove 4x4 uni-pred, 4x8/8x4 bi-pred from regular inter modes + #define JVET_N0054_JOINT_CHROMA 1 // Joint chroma residual coding mode #define JVET_N0317_ADD_ZERO_BV 1 diff --git a/source/Lib/DecoderLib/CABACReader.cpp b/source/Lib/DecoderLib/CABACReader.cpp index e4e9b6c9f44c8283add341a466c1f4a1080afeda..b06830023aa24aedb7733c3ab8366bf55a0f581e 100644 --- a/source/Lib/DecoderLib/CABACReader.cpp +++ b/source/Lib/DecoderLib/CABACReader.cpp @@ -2460,6 +2460,13 @@ void CABACReader::residual_coding( TransformUnit& tu, ComponentID compID ) mts_coding ( tu, compID ); explicit_rdpcm_mode( tu, compID ); +#if JVET_N0280_RESIDUAL_CODING_TS + if( isLuma( compID ) && tu.mtsIdx == 1 ) + { + residual_codingTS( tu, compID ); + return; + } +#endif #if HEVC_USE_SIGN_HIDING // determine sign hiding @@ -2871,6 +2878,197 @@ void CABACReader::residual_coding_subblock( CoeffCodingContext& cctx, TCoeff* co #endif } +#if JVET_N0280_RESIDUAL_CODING_TS +void CABACReader::residual_codingTS( TransformUnit& tu, ComponentID compID ) +{ + DTRACE( g_trace_ctx, D_SYNTAX, "residual_codingTS() etype=%d pos=(%d,%d) size=%dx%d\n", tu.blocks[compID].compID, tu.blocks[compID].x, tu.blocks[compID].y, tu.blocks[compID].width, tu.blocks[compID].height ); + + // init coeff coding context + CoeffCodingContext cctx ( tu, compID, false ); + TCoeff* coeff = tu.getCoeffs( compID ).buf; + + cctx.setNumCtxBins( 2 * tu.lwidth()*tu.lheight() ); + + for( int subSetId = 0; subSetId <= ( cctx.maxNumCoeff() - 1 ) >> cctx.log2CGSize(); subSetId++ ) + { + cctx.initSubblock ( subSetId ); + residual_coding_subblockTS( cctx, coeff ); + } +} + +void CABACReader::residual_coding_subblockTS( CoeffCodingContext& cctx, TCoeff* coeff ) +{ + // NOTE: All coefficients of the subblock must be set to zero before calling this function +#if RExt__DECODER_DEBUG_BIT_STATISTICS + CodingStatisticsClassType ctype_group ( STATS__CABAC_BITS__SIG_COEFF_GROUP_FLAG, cctx.width(), cctx.height(), cctx.compID() ); + CodingStatisticsClassType ctype_map ( STATS__CABAC_BITS__SIG_COEFF_MAP_FLAG, cctx.width(), cctx.height(), cctx.compID() ); + CodingStatisticsClassType ctype_par ( STATS__CABAC_BITS__PAR_FLAG, cctx.width(), cctx.height(), cctx.compID() ); + CodingStatisticsClassType ctype_gt1 ( STATS__CABAC_BITS__GT1_FLAG, cctx.width(), cctx.height(), cctx.compID() ); + CodingStatisticsClassType ctype_gt2 ( STATS__CABAC_BITS__GT2_FLAG, cctx.width(), cctx.height(), cctx.compID() ); + CodingStatisticsClassType ctype_escs ( STATS__CABAC_BITS__ESCAPE_BITS, cctx.width(), cctx.height(), cctx.compID() ); +#endif + + //===== init ===== + const int minSubPos = cctx.maxSubPos(); + int firstSigPos = cctx.minSubPos(); + int nextSigPos = firstSigPos; + unsigned signPattern = 0; + + //===== decode significant_coeffgroup_flag ===== + RExt__DECODER_DEBUG_BIT_STATISTICS_SET( ctype_group ); + bool sigGroup = cctx.isLastSubSet() && cctx.noneSigGroup(); + if( !sigGroup ) + { + if( cctx.isContextCoded() ) + { + sigGroup = m_BinDecoder.decodeBin( cctx.sigGroupCtxId( true ) ); + DTRACE( g_trace_ctx, D_SYNTAX_RESI, "ts_sigGroup() bin=%d ctx=%d\n", sigGroup, cctx.sigGroupCtxId() ); + } + else + { + sigGroup = m_BinDecoder.decodeBinEP( ); + DTRACE( g_trace_ctx, D_SYNTAX_RESI, "ts_sigGroup() EPbin=%d\n", sigGroup ); + } + } + if( sigGroup ) + { + cctx.setSigGroup(); + } + else + { + return; + } + + //===== decode absolute values ===== + const int inferSigPos = minSubPos; + int numNonZero = 0; + int sigBlkPos[ 1 << MLS_CG_SIZE ]; + + for( ; nextSigPos <= minSubPos; nextSigPos++ ) + { + int blkPos = cctx.blockPos( nextSigPos ); + unsigned sigFlag = ( !numNonZero && nextSigPos == inferSigPos ); + if( !sigFlag ) + { + RExt__DECODER_DEBUG_BIT_STATISTICS_SET( ctype_map ); + if( cctx.isContextCoded() ) + { + const unsigned sigCtxId = cctx.sigCtxIdAbsTS( nextSigPos, coeff ); + sigFlag = m_BinDecoder.decodeBin( sigCtxId ); + DTRACE( g_trace_ctx, D_SYNTAX_RESI, "ts_sig_bin() bin=%d ctx=%d\n", sigFlag, sigCtxId ); + } + else + { + sigFlag = m_BinDecoder.decodeBinEP( ); + DTRACE( g_trace_ctx, D_SYNTAX_RESI, "ts_sig_bin() EPbin=%d\n", sigFlag ); + } + } + + if( sigFlag ) + { + //===== decode sign's ===== + RExt__DECODER_DEBUG_BIT_STATISTICS_CREATE_SET_SIZE2( STATS__CABAC_BITS__SIGN_BIT, Size( cctx.width(), cctx.height() ), cctx.compID() ); + int sign; + if( cctx.isContextCoded() ) + { + sign = m_BinDecoder.decodeBin( Ctx::TsResidualSign( toChannelType( cctx.compID() ) ) ); + } + else + { + sign = m_BinDecoder.decodeBinEP( ); + } + + signPattern += ( sign << numNonZero ); + + sigBlkPos[numNonZero++] = blkPos; + + RExt__DECODER_DEBUG_BIT_STATISTICS_SET( ctype_gt1 ); + unsigned gt1Flag; + if( cctx.isContextCoded() ) + { + gt1Flag = m_BinDecoder.decodeBin( cctx.greaterXCtxIdAbsTS(0) ); + DTRACE( g_trace_ctx, D_SYNTAX_RESI, "ts_gt1_flag() bin=%d ctx=%d\n", gt1Flag, cctx.greaterXCtxIdAbsTS(0) ); + } + else + { + gt1Flag = m_BinDecoder.decodeBinEP( ); + DTRACE( g_trace_ctx, D_SYNTAX_RESI, "ts_gt1_flag() EPbin=%d\n", gt1Flag ); + } + + unsigned parFlag = 0; + if( gt1Flag ) + { + RExt__DECODER_DEBUG_BIT_STATISTICS_SET( ctype_par ); + if( cctx.isContextCoded() ) + { + parFlag = m_BinDecoder.decodeBin( cctx.parityCtxIdAbsTS() ); + DTRACE( g_trace_ctx, D_SYNTAX_RESI, "ts_par_flag() bin=%d ctx=%d\n", parFlag, cctx.parityCtxIdAbsTS() ); + } + else + { + parFlag = m_BinDecoder.decodeBinEP( ); + DTRACE( g_trace_ctx, D_SYNTAX_RESI, "ts_par_flag() EPbin=%d\n", parFlag ); + } + } + coeff[ blkPos ] += 1 + parFlag + gt1Flag; + } + } + + int cutoffVal = 2; + int numGtBins = 4; + + //===== 2nd PASS: gt2 ===== + for( int i = 0; i < numGtBins; i++ ) + { + for( int scanPos = firstSigPos; scanPos <= minSubPos; scanPos++ ) + { + TCoeff& tcoeff = coeff[cctx.blockPos( scanPos )]; + if( tcoeff >= cutoffVal ) + { + RExt__DECODER_DEBUG_BIT_STATISTICS_SET( ctype_gt2 ); + unsigned gt2Flag; + if( cctx.isContextCoded() ) + { + gt2Flag = m_BinDecoder.decodeBin( cctx.greaterXCtxIdAbsTS(cutoffVal>>1) ); + tcoeff += ( gt2Flag << 1 ); + DTRACE( g_trace_ctx, D_SYNTAX_RESI, "ts_gt%d_flag() bin=%d ctx=%d sp=%d coeff=%d\n", i, gt2Flag, cctx.greaterXCtxIdAbsTS(cutoffVal>>1), scanPos, tcoeff ); + } + else + { + gt2Flag = m_BinDecoder.decodeBinEP( ); + tcoeff += ( gt2Flag << 1 ); + DTRACE( g_trace_ctx, D_SYNTAX_RESI, "ts_gt%d_flag() EPbin=%d sp=%d coeff=%d\n", i, gt2Flag, scanPos, tcoeff ); + } + } + } + cutoffVal += 2; + } + + //===== 3rd PASS: Go-rice codes ===== + for( int scanPos = firstSigPos; scanPos <= minSubPos; scanPos++ ) + { + TCoeff& tcoeff = coeff[ cctx.blockPos( scanPos ) ]; + RExt__DECODER_DEBUG_BIT_STATISTICS_SET( ctype_escs ); + if( tcoeff >= cutoffVal ) + { + int rice = cctx.templateAbsSumTS( scanPos, coeff ); + int rem = m_BinDecoder.decodeRemAbsEP( rice, cctx.extPrec(), cctx.maxLog2TrDRange() ); + DTRACE( g_trace_ctx, D_SYNTAX_RESI, "ts_rem_val() bin=%d ctx=%d sp=%d\n", rem, rice, scanPos ); + tcoeff += ( rem << 1 ); + } + } + + //===== set final coefficents ===== + for( unsigned k = 0; k < numNonZero; k++ ) + { + int AbsCoeff = coeff[ sigBlkPos[ k ] ]; + coeff[ sigBlkPos[k] ] = ( signPattern & 1 ? -AbsCoeff : AbsCoeff ); + signPattern >>= 1; + } +} +#endif + + //================================================================================ // clause 7.3.8.12 //-------------------------------------------------------------------------------- diff --git a/source/Lib/DecoderLib/CABACReader.h b/source/Lib/DecoderLib/CABACReader.h index 2efdb3be744a3fd54c6c6d15b653a0beda931637..c8dd4878140edec5ea0e524119281a6cbf20d44b 100644 --- a/source/Lib/DecoderLib/CABACReader.h +++ b/source/Lib/DecoderLib/CABACReader.h @@ -130,6 +130,10 @@ public: void explicit_rdpcm_mode ( TransformUnit& tu, ComponentID compID ); int last_sig_coeff ( CoeffCodingContext& cctx, TransformUnit& tu, ComponentID compID ); void residual_coding_subblock ( CoeffCodingContext& cctx, TCoeff* coeff, const int stateTransTable, int& state ); +#if JVET_N0280_RESIDUAL_CODING_TS + void residual_codingTS ( TransformUnit& tu, ComponentID compID ); + void residual_coding_subblockTS( CoeffCodingContext& cctx, TCoeff* coeff ); +#endif #if JVET_N0054_JOINT_CHROMA void joint_cb_cr ( TransformUnit& tu ); #endif diff --git a/source/Lib/EncoderLib/CABACWriter.cpp b/source/Lib/EncoderLib/CABACWriter.cpp index f45f3189b12f8d1766e7a5f2d930e1fc6e6d860b..ce9c579f52f8d7d3e3c83c8fa61c924a1b32dbd1 100644 --- a/source/Lib/EncoderLib/CABACWriter.cpp +++ b/source/Lib/EncoderLib/CABACWriter.cpp @@ -2349,6 +2349,14 @@ void CABACWriter::residual_coding( const TransformUnit& tu, ComponentID compID ) mts_coding ( tu, compID ); explicit_rdpcm_mode( tu, compID ); +#if JVET_N0280_RESIDUAL_CODING_TS + if( isLuma( compID ) && tu.mtsIdx==1 ) + { + residual_codingTS( tu, compID ); + return; + } +#endif + #if HEVC_USE_SIGN_HIDING // determine sign hiding bool signHiding = ( cu.cs->slice->getSignDataHidingEnabledFlag() && !cu.transQuantBypass && tu.rdpcm[compID] == RDPCM_OFF ); @@ -2725,6 +2733,184 @@ void CABACWriter::residual_coding_subblock( CoeffCodingContext& cctx, const TCoe #endif } +#if JVET_N0280_RESIDUAL_CODING_TS +void CABACWriter::residual_codingTS( const TransformUnit& tu, ComponentID compID ) +{ + DTRACE( g_trace_ctx, D_SYNTAX, "residual_codingTS() etype=%d pos=(%d,%d) size=%dx%d\n", tu.blocks[compID].compID, tu.blocks[compID].x, tu.blocks[compID].y, tu.blocks[compID].width, tu.blocks[compID].height ); + + // init coeff coding context + CoeffCodingContext cctx ( tu, compID, false ); + const TCoeff* coeff = tu.getCoeffs( compID ).buf; + + cctx.setNumCtxBins( 2 * tu.lwidth()*tu.lheight() ); + + // determine and set last coeff position and sig group flags + std::bitset<MLS_GRP_NUM> sigGroupFlags; + for( int scanPos = 0; scanPos < cctx.maxNumCoeff(); scanPos++) + { + unsigned blkPos = cctx.blockPos( scanPos ); + if( coeff[blkPos] ) + { + sigGroupFlags.set( scanPos >> cctx.log2CGSize() ); + } + } + + // code subblocks + for( int subSetId = 0; subSetId <= ( cctx.maxNumCoeff() - 1 ) >> cctx.log2CGSize(); subSetId++ ) + { + cctx.initSubblock ( subSetId, sigGroupFlags[subSetId] ); + residual_coding_subblockTS( cctx, coeff ); + } +} + +void CABACWriter::residual_coding_subblockTS( CoeffCodingContext& cctx, const TCoeff* coeff ) +{ + //===== init ===== + const int minSubPos = cctx.maxSubPos(); + int firstSigPos = cctx.minSubPos(); + int nextSigPos = firstSigPos; + + //===== encode significant_coeffgroup_flag ===== + if( !cctx.isLastSubSet() || !cctx.only1stSigGroup() ) + { + if( cctx.isSigGroup() ) + { + if( cctx.isContextCoded() ) + { + m_BinEncoder.encodeBin( 1, cctx.sigGroupCtxId( true ) ); + DTRACE( g_trace_ctx, D_SYNTAX_RESI, "ts_sigGroup() bin=%d ctx=%d\n", 1, cctx.sigGroupCtxId() ); + } + else + { + m_BinEncoder.encodeBinEP( 1 ); + DTRACE( g_trace_ctx, D_SYNTAX_RESI, "ts_sigGroup() EPbin=%d\n", 1 ); + } + } + else + { + if( cctx.isContextCoded() ) + { + m_BinEncoder.encodeBin( 0, cctx.sigGroupCtxId( true ) ); + DTRACE( g_trace_ctx, D_SYNTAX_RESI, "ts_sigGroup() bin=%d ctx=%d\n", 0, cctx.sigGroupCtxId() ); + } + else + { + m_BinEncoder.encodeBinEP( 0 ); + DTRACE( g_trace_ctx, D_SYNTAX_RESI, "ts_sigGroup() EPbin=%d\n", 0 ); + } + return; + } + } + + //===== encode absolute values ===== + const int inferSigPos = minSubPos; + int remAbsLevel = -1; + int numNonZero = 0; + + for( ; nextSigPos <= minSubPos; nextSigPos++ ) + { + TCoeff Coeff = coeff[ cctx.blockPos( nextSigPos ) ]; + unsigned sigFlag = ( Coeff != 0 ); + if( numNonZero || nextSigPos != inferSigPos ) + { + if( cctx.isContextCoded() ) + { + const unsigned sigCtxId = cctx.sigCtxIdAbsTS( nextSigPos, coeff ); + m_BinEncoder.encodeBin( sigFlag, sigCtxId ); + DTRACE( g_trace_ctx, D_SYNTAX_RESI, "ts_sig_bin() bin=%d ctx=%d\n", sigFlag, sigCtxId ); + } + else + { + m_BinEncoder.encodeBinEP( sigFlag ); + DTRACE( g_trace_ctx, D_SYNTAX_RESI, "ts_sig_bin() EPbin=%d\n", sigFlag ); + } + } + + if( sigFlag ) + { + //===== encode sign's ===== + int sign = Coeff < 0; + if( cctx.isContextCoded() ) + { + m_BinEncoder.encodeBin( sign, Ctx::TsResidualSign( toChannelType( cctx.compID() ) ) ); + } + else + { + m_BinEncoder.encodeBinEP( sign ); + } + numNonZero++; + remAbsLevel = abs( Coeff ) - 1; + + unsigned gt1 = !!remAbsLevel; + if( cctx.isContextCoded() ) + { + m_BinEncoder.encodeBin( gt1, cctx.greaterXCtxIdAbsTS(0) ); + DTRACE( g_trace_ctx, D_SYNTAX_RESI, "ts_gt1_flag() bin=%d ctx=%d\n", gt1, cctx.greaterXCtxIdAbsTS(0) ); + } + else + { + m_BinEncoder.encodeBinEP( gt1 ); + DTRACE( g_trace_ctx, D_SYNTAX_RESI, "ts_gt1_flag() EPbin=%d\n", gt1 ); + } + + if( gt1 ) + { + remAbsLevel -= 1; + if( cctx.isContextCoded() ) + { + m_BinEncoder.encodeBin( remAbsLevel&1, cctx.parityCtxIdAbsTS() ); + DTRACE( g_trace_ctx, D_SYNTAX_RESI, "ts_par_flag() bin=%d ctx=%d\n", remAbsLevel&1, cctx.parityCtxIdAbsTS() ); + } + else + { + m_BinEncoder.encodeBinEP( remAbsLevel&1 ); + DTRACE( g_trace_ctx, D_SYNTAX_RESI, "ts_par_flag() EPbin=%d\n", remAbsLevel&1 ); + } + } + } + } + + int cutoffVal = 2; + int numGtBins = 4; + + for( int i = 0; i < numGtBins; i++ ) + { + for( int scanPos = firstSigPos; scanPos <= minSubPos; scanPos++ ) + { + unsigned absLevel = abs( coeff[cctx.blockPos( scanPos )] ); + if( absLevel >= cutoffVal ) + { + unsigned gt2 = ( absLevel >= ( cutoffVal + 2 ) ); + if( cctx.isContextCoded() ) + { + m_BinEncoder.encodeBin( gt2, cctx.greaterXCtxIdAbsTS( cutoffVal>>1 ) ); + DTRACE( g_trace_ctx, D_SYNTAX_RESI, "ts_gt%d_flag() bin=%d ctx=%d sp=%d coeff=%d\n", i, gt2, cctx.greaterXCtxIdAbsTS( cutoffVal>>1 ), scanPos, min<int>( absLevel, cutoffVal+2 ) ); + } + else + { + m_BinEncoder.encodeBinEP( gt2 ); + DTRACE( g_trace_ctx, D_SYNTAX_RESI, "ts_gt%d_flag() EPbin=%d sp=%d coeff=%d\n", i, gt2, scanPos, min<int>( absLevel, cutoffVal+2 ) ); + } + } + } + cutoffVal += 2; + } + + //===== coeff bypass ==== + for( int scanPos = firstSigPos; scanPos <= minSubPos; scanPos++ ) + { + TCoeff Coeff = coeff[ cctx.blockPos( scanPos ) ]; + unsigned absLevel = abs( Coeff ); + if( absLevel >= cutoffVal ) + { + int rice = cctx.templateAbsSumTS( scanPos, coeff ); + unsigned rem = ( absLevel - cutoffVal ) >> 1; + m_BinEncoder.encodeRemAbsEP( rem, rice, cctx.extPrec(), cctx.maxLog2TrDRange() ); + DTRACE( g_trace_ctx, D_SYNTAX_RESI, "ts_rem_val() bin=%d ctx=%d sp=%d\n", rem, rice, scanPos ); + } + } +} +#endif diff --git a/source/Lib/EncoderLib/CABACWriter.h b/source/Lib/EncoderLib/CABACWriter.h index 49c2f0a9cad7ce3f21279bde95189af281a7e409..59b513a48cfb17113a4a36396419fbf8c26f7731 100644 --- a/source/Lib/EncoderLib/CABACWriter.h +++ b/source/Lib/EncoderLib/CABACWriter.h @@ -144,6 +144,10 @@ public: void explicit_rdpcm_mode ( const TransformUnit& tu, ComponentID compID ); void last_sig_coeff ( CoeffCodingContext& cctx, const TransformUnit& tu, ComponentID compID ); void residual_coding_subblock ( CoeffCodingContext& cctx, const TCoeff* coeff, const int stateTransTable, int& state ); +#if JVET_N0280_RESIDUAL_CODING_TS + void residual_codingTS ( const TransformUnit& tu, ComponentID compID ); + void residual_coding_subblockTS( CoeffCodingContext& cctx, const TCoeff* coeff ); +#endif #if JVET_N0054_JOINT_CHROMA void joint_cb_cr ( const TransformUnit& tu ); #endif