From a7725e565721d1c82d65d21775808c3cc544e96c Mon Sep 17 00:00:00 2001 From: Hongtao Wang <hongtaow@qti.qualcomm.com> Date: Wed, 24 Jul 2019 16:09:08 -0700 Subject: [PATCH] JVET-O0122 CE7-3.10: Sign context, level mapping of TS residual coding --- source/Lib/CommonLib/ContextModelling.cpp | 4 + source/Lib/CommonLib/ContextModelling.h | 135 +++++++++++++++ source/Lib/CommonLib/Contexts.cpp | 25 +++ source/Lib/CommonLib/Contexts.h | 3 + source/Lib/CommonLib/QuantRDOQ.cpp | 190 ++++++++++++++++++++++ source/Lib/CommonLib/QuantRDOQ.h | 32 ++++ source/Lib/CommonLib/TypeDef.h | 2 + source/Lib/DecoderLib/CABACReader.cpp | 40 +++++ source/Lib/EncoderLib/CABACWriter.cpp | 41 +++++ 9 files changed, 472 insertions(+) diff --git a/source/Lib/CommonLib/ContextModelling.cpp b/source/Lib/CommonLib/ContextModelling.cpp index 4ef4a5522c..df2dd730a7 100644 --- a/source/Lib/CommonLib/ContextModelling.cpp +++ b/source/Lib/CommonLib/ContextModelling.cpp @@ -86,6 +86,10 @@ CoeffCodingContext::CoeffCodingContext( const TransformUnit& tu, ComponentID com , m_tsSigFlagCtxSet ( Ctx::TsSigFlag ) , m_tsParFlagCtxSet ( Ctx::TsParFlag ) , m_tsGtxFlagCtxSet ( Ctx::TsGtxFlag ) +#if JVET_O0122_TS_SIGN_LEVEL + , m_tsLrg1FlagCtxSet (Ctx::TsLrg1Flag) + , m_tsSignFlagCtxSet (Ctx::TsResidualSign) +#endif , m_sigCoeffGroupFlag () , m_bdpcm (bdpcm) { diff --git a/source/Lib/CommonLib/ContextModelling.h b/source/Lib/CommonLib/ContextModelling.h index 926efcd3b0..d361b0e379 100644 --- a/source/Lib/CommonLib/ContextModelling.h +++ b/source/Lib/CommonLib/ContextModelling.h @@ -205,6 +205,137 @@ public: unsigned parityCtxIdAbsTS () const { return m_tsParFlagCtxSet( 0 ); } unsigned greaterXCtxIdAbsTS ( uint8_t offset ) const { return m_tsGtxFlagCtxSet( offset ); } +#if JVET_O0122_TS_SIGN_LEVEL + unsigned lrg1CtxIdAbsTS(int scanPos, const TCoeff* coeff, int bdpcm) + { + 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 (bdpcm) + { + numPos = 3; + } + else + { + if (posX > 0) + { + UPDATE(posC[-1]); + } + if (posY > 0) + { + UPDATE(posC[-(int)m_width]); + } + } + +#undef UPDATE + return m_tsLrg1FlagCtxSet(numPos); + } +#endif + +#if JVET_O0122_TS_SIGN_LEVEL + unsigned signCtxIdAbsTS(int scanPos, const TCoeff* coeff, int bdpcm) + { + const uint32_t posY = m_scan[scanPos].y; + const uint32_t posX = m_scan[scanPos].x; + const TCoeff* pData = coeff + posX + posY * m_width; + + int rightSign = 0, belowSign = 0; + unsigned signCtx = 0; + + if (posX > 0) + { + rightSign = pData[-1]; + } + if (posY > 0) + { + belowSign = pData[-(int)m_width]; + } + + if ((rightSign == 0 && belowSign == 0) || ((rightSign*belowSign) < 0)) + { + signCtx = 0; + } + else if (rightSign >= 0 && belowSign >= 0) + { + signCtx = 1; + } + else + { + signCtx = 2; + } + if (bdpcm) + { + signCtx += 3; + } + return m_tsSignFlagCtxSet(signCtx); + } +#endif + +#if JVET_O0122_TS_SIGN_LEVEL + void neighTS(int &rightPixel, int &belowPixel, int scanPos, const TCoeff* coeff) + { + const uint32_t posY = m_scan[scanPos].y; + const uint32_t posX = m_scan[scanPos].x; + const TCoeff* data = coeff + posX + posY * m_width; + + rightPixel = belowPixel = 0; + + if (posX > 0) + { + rightPixel = data[-1]; + } + if (posY > 0) + { + belowPixel = data[-(int)m_width]; + } + } + + int deriveModCoeff(int rightPixel, int belowPixel, int absCoeff, int bdpcm = 0) + { + int pred1, absBelow = abs(belowPixel), absRight = abs(rightPixel); + + int absCoeffMod = absCoeff; + + if (bdpcm == 0) + { + pred1 = std::max(absBelow, absRight); + + if (absCoeff == pred1) + { + absCoeffMod = 1; + } + else + { + absCoeffMod = absCoeff < pred1 ? absCoeff + 1 : absCoeff; + } + } + + return(absCoeffMod); + } + + int decDeriveModCoeff(int rightPixel, int belowPixel, int absCoeff) + { + int pred1, absBelow = abs(belowPixel), absRight = abs(rightPixel); + pred1 = std::max(absBelow, absRight); + + int absCoeffMod; + + if (absCoeff == 1 && pred1 > 0) + { + absCoeffMod = pred1; + } + else + { + absCoeffMod = absCoeff - (absCoeff <= pred1); + } + return(absCoeffMod); + } +#endif + unsigned templateAbsSumTS( int scanPos, const TCoeff* coeff ) { const uint32_t posY = m_scan[scanPos].y; @@ -282,6 +413,10 @@ private: CtxSet m_tsSigFlagCtxSet; CtxSet m_tsParFlagCtxSet; CtxSet m_tsGtxFlagCtxSet; +#if JVET_O0122_TS_SIGN_LEVEL + CtxSet m_tsLrg1FlagCtxSet; + CtxSet m_tsSignFlagCtxSet; +#endif int m_remainingContextBins; std::bitset<MLS_GRP_NUM> m_sigCoeffGroupFlag; const bool m_bdpcm; diff --git a/source/Lib/CommonLib/Contexts.cpp b/source/Lib/CommonLib/Contexts.cpp index 7fd97af5e4..f8576396a0 100644 --- a/source/Lib/CommonLib/Contexts.cpp +++ b/source/Lib/CommonLib/Contexts.cpp @@ -840,6 +840,30 @@ const CtxSet ContextSetCfg::TsGtxFlag = ContextSetCfg::addCtxSet { 4, 1, 1, 1, 1, }, }); +#if JVET_O0122_TS_SIGN_LEVEL +const CtxSet ContextSetCfg::TsLrg1Flag = ContextSetCfg::addCtxSet +({ + { 139, 108, 124, 111 }, + { 122, 138, 139, 110 }, + { 123, 139, 110, 125 }, + { 4, 2, 1, 5 } + }); +#endif + +#if JVET_O0122_TS_SIGN_LEVEL + +const CtxSet ContextSetCfg::TsResidualSign = +{ + ContextSetCfg::addCtxSet + ({ + { 139, 92, 201, 139, 122, 171 }, + { 124, 77, 171, 169, 121, 187 }, + { 124, 61, 187, 154, 121, 187 }, + { 1, 4, 1, 5, 5, 5 } + }), +}; + +#else const CtxSet ContextSetCfg::TsResidualSign = { ContextSetCfg::addCtxSet @@ -850,6 +874,7 @@ const CtxSet ContextSetCfg::TsResidualSign = { 1, 2, }, }), }; +#endif // clang-format on 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 e68c790960..214ff17b13 100644 --- a/source/Lib/CommonLib/Contexts.h +++ b/source/Lib/CommonLib/Contexts.h @@ -235,6 +235,9 @@ public: static const CtxSet TsSigFlag; static const CtxSet TsParFlag; static const CtxSet TsGtxFlag; +#if JVET_O0122_TS_SIGN_LEVEL + static const CtxSet TsLrg1Flag; +#endif static const CtxSet TsResidualSign; static const CtxSet MVPIdx; static const CtxSet SaoMergeFlag; diff --git a/source/Lib/CommonLib/QuantRDOQ.cpp b/source/Lib/CommonLib/QuantRDOQ.cpp index 79195fe3e8..704d3ba871 100644 --- a/source/Lib/CommonLib/QuantRDOQ.cpp +++ b/source/Lib/CommonLib/QuantRDOQ.cpp @@ -1243,6 +1243,10 @@ void QuantRDOQ::xRateDistOptQuantTS( TransformUnit &tu, const ComponentID &compI memset( m_pdCostCoeff, 0, sizeof( double ) * maxNumCoeff ); memset( m_pdCostSig, 0, sizeof( double ) * maxNumCoeff ); +#if JVET_O0122_TS_SIGN_LEVEL + m_bdpcm = 0; +#endif + const bool needsSqrt2Scale = TU::needsSqrt2Scale( tu, compID ); // should always be false - transform-skipped blocks don't require sqrt(2) compensation. const int qBits = QUANT_SHIFT + qp.per + transformShift + (needsSqrt2Scale?-1:0); // Right shift of non-RDOQ quantizer; level = (coeff*uiQ + offset)>>q_bits const int quantisationCoefficient = g_quantScales[needsSqrt2Scale?1:0][qp.rem]; @@ -1250,6 +1254,11 @@ void QuantRDOQ::xRateDistOptQuantTS( TransformUnit &tu, const ComponentID &compI const TCoeff entropyCodingMaximum = ( 1 << maxLog2TrDynamicRange ) - 1; +#if JVET_O0122_TS_SIGN_LEVEL + uint32_t coeffLevels[3]; + double coeffLevelError[4]; +#endif + CoeffCodingContext cctx( tu, compID, tu.cs->slice->getSignDataHidingEnabledFlag() ); const int sbSizeM1 = ( 1 << cctx.log2CGSize() ) - 1; double baseCost = 0; @@ -1282,12 +1291,42 @@ void QuantRDOQ::xRateDistOptQuantTS( TransformUnit &tu, const ComponentID &compI // 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 ) ) ); + +#if JVET_O0122_TS_SIGN_LEVEL + uint32_t roundAbsLevel = std::min<uint32_t>(uint32_t(entropyCodingMaximum), uint32_t((levelDouble + (Intermediate_Int(1) << (qBits - 1))) >> qBits)); + uint32_t minAbsLevel = (roundAbsLevel > 1 ? roundAbsLevel - 1 : 1); + + uint32_t downAbsLevel = std::min<uint32_t>(uint32_t(entropyCodingMaximum), uint32_t(levelDouble >> qBits)); + uint32_t upAbsLevel = std::min<uint32_t>(uint32_t(entropyCodingMaximum), downAbsLevel + 1); + + m_testedLevels = 0; + coeffLevels[m_testedLevels++] = roundAbsLevel; + + if (minAbsLevel != roundAbsLevel) + coeffLevels[m_testedLevels++] = minAbsLevel; + + int rightPixel, belowPixel, predPixel; + + cctx.neighTS(rightPixel, belowPixel, scanPos, dstCoeff); + predPixel = cctx.deriveModCoeff(rightPixel, belowPixel, upAbsLevel, 0); + + if (upAbsLevel != roundAbsLevel && upAbsLevel != minAbsLevel && predPixel == 1) + coeffLevels[m_testedLevels++] = upAbsLevel; + + double dErr = double(levelDouble); + coeffLevelError[0] = dErr * dErr * errorScale; + + costCoeff0[scanPos] = coeffLevelError[0]; + blockUncodedCost += costCoeff0[ scanPos ]; + dstCoeff[blkPos] = coeffLevels[0]; +#else 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; +#endif //===== coefficient level estimation ===== unsigned ctxIdSig = cctx.sigCtxIdAbsTS( scanPos, dstCoeff ); @@ -1295,24 +1334,50 @@ void QuantRDOQ::xRateDistOptQuantTS( TransformUnit &tu, const ComponentID &compI const BinFracBits fracBitsPar = fracBits.getFracBitsArray( cctx.parityCtxIdAbsTS() ); goRiceParam = cctx.templateAbsSumTS( scanPos, dstCoeff ); +#if JVET_O0122_TS_SIGN_LEVEL + unsigned ctxIdSign = cctx.signCtxIdAbsTS(scanPos, dstCoeff, 0); + const BinFracBits fracBitsSign = fracBits.getFracBitsArray(ctxIdSign); +#else const BinFracBits fracBitsSign = fracBits.getFracBitsArray( Ctx::TsResidualSign( toChannelType(compID) ) ); +#endif const uint8_t sign = srcCoeff[ blkPos ] < 0 ? 1 : 0; +#if JVET_O0122_TS_SIGN_LEVEL + DTRACE_COND( ( coeffLevels[0] != 0 ), g_trace_ctx, D_RDOQ_MORE, " uiCtxSig=%d", ctxIdSig ); +#else DTRACE_COND( ( maxAbsLevel != 0 ), g_trace_ctx, D_RDOQ_MORE, " uiCtxSig=%d", ctxIdSig ); +#endif +#if JVET_O0122_TS_SIGN_LEVEL + unsigned gt1CtxId = cctx.lrg1CtxIdAbsTS(scanPos, dstCoeff, 0); + const BinFracBits fracBitsGr1 = fracBits.getFracBitsArray(gt1CtxId); + +#endif const BinFracBits fracBitsSig = fracBits.getFracBitsArray( ctxIdSig ); bool lastCoeff = false; // if (scanPosInSB == lastPosCoded && noCoeffCoded == 0) { lastCoeff = true; } +#if JVET_O0122_TS_SIGN_LEVEL + cLevel = xGetCodedLevelTSPred( costCoeff[ scanPos ], costCoeff0[ scanPos ], costSig[ scanPos ], levelDouble, qBits, errorScale, coeffLevels, coeffLevelError, + &fracBitsSig, fracBitsPar, cctx, fracBits, fracBitsSign, fracBitsGr1, sign, rightPixel, belowPixel, goRiceParam, lastCoeff, extendedPrecision, maxLog2TrDynamicRange); +#else cLevel = xGetCodedLevelTS( costCoeff[ scanPos ], costCoeff0[ scanPos ], costSig[ scanPos ], levelDouble, maxAbsLevel, &fracBitsSig, fracBitsPar, cctx, fracBits, fracBitsSign, sign, goRiceParam, qBits, errorScale, lastCoeff, extendedPrecision, maxLog2TrDynamicRange ); +#endif + if (cLevel > 0) { noCoeffCoded++; } + +#if JVET_O0122_TS_SIGN_LEVEL + TCoeff level = cLevel; + dstCoeff[blkPos] = (level != 0 && srcCoeff[blkPos] < 0) ? -level : level; +#else dstCoeff[ blkPos ] = cLevel; +#endif baseCost += costCoeff[ scanPos ]; rdStats.d64SigCost += costSig[ scanPos ]; @@ -1376,8 +1441,12 @@ void QuantRDOQ::xRateDistOptQuantTS( TransformUnit &tu, const ComponentID &compI { int blkPos = cctx.blockPos( scanPos ); TCoeff level = dstCoeff[ blkPos ]; +#if !JVET_O0122_TS_SIGN_LEVEL absSum += level; dstCoeff[ blkPos ] = ( level != 0 && srcCoeff[ blkPos ] < 0 ) ? -level : level; +#else + absSum += abs(level); +#endif } } @@ -1422,6 +1491,10 @@ void QuantRDOQ::forwardRDPCM( TransformUnit &tu, const ComponentID &compID, cons memset(m_pdCostSig, 0, sizeof(double) * maxNumCoeff); memset(m_fullCoeff, 0, sizeof(TCoeff) * maxNumCoeff); +#if JVET_O0122_TS_SIGN_LEVEL + m_bdpcm = dirMode; +#endif + const bool needsSqrt2Scale = TU::needsSqrt2Scale(tu, compID); // should always be false - transform-skipped blocks don't require sqrt(2) compensation. const int qBits = QUANT_SHIFT + qp.per + transformShift + (needsSqrt2Scale ? -1 : 0); // Right shift of non-RDOQ quantizer; level = (coeff*uiQ + offset)>>q_bits const int quantisationCoefficient = g_quantScales[needsSqrt2Scale ? 1 : 0][qp.rem]; @@ -1433,6 +1506,11 @@ void QuantRDOQ::forwardRDPCM( TransformUnit &tu, const ComponentID &compID, cons const TCoeff entropyCodingMaximum = (1 << maxLog2TrDynamicRange) - 1; +#if JVET_O0122_TS_SIGN_LEVEL + uint32_t coeffLevels[3]; + double coeffLevelError[4]; +#endif + CoeffCodingContext cctx(tu, compID, tu.cs->slice->getSignDataHidingEnabledFlag()); const int sbSizeM1 = (1 << cctx.log2CGSize()) - 1; double baseCost = 0; @@ -1471,12 +1549,30 @@ void QuantRDOQ::forwardRDPCM( TransformUnit &tu, const ComponentID &compID, cons // set coeff const int64_t tmpLevel = int64_t(abs(srcCoeff[blkPos] - predCoeff)) * quantisationCoefficient; const Intermediate_Int levelDouble = (Intermediate_Int)std::min<int64_t>(tmpLevel, std::numeric_limits<Intermediate_Int>::max() - (Intermediate_Int(1) << (qBits - 1))); +#if JVET_O0122_TS_SIGN_LEVEL + uint32_t roundAbsLevel = std::min<uint32_t>(uint32_t(entropyCodingMaximum), uint32_t((levelDouble + (Intermediate_Int(1) << (qBits - 1))) >> qBits)); + uint32_t minAbsLevel = (roundAbsLevel > 1 ? roundAbsLevel - 1 : 1); + + m_testedLevels = 0; + coeffLevels[m_testedLevels++] = roundAbsLevel; + + if (minAbsLevel != roundAbsLevel) + coeffLevels[m_testedLevels++] = minAbsLevel; + + double dErr = double(levelDouble); + coeffLevelError[0] = dErr * dErr * errorScale; + + costCoeff0[scanPos] = coeffLevelError[0]; + blockUncodedCost += costCoeff0[scanPos]; + dstCoeff[blkPos] = coeffLevels[0]; +#else 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; +#endif //===== coefficient level estimation ===== unsigned ctxIdSig = cctx.sigCtxIdAbsTS(scanPos, dstCoeff); @@ -1484,10 +1580,23 @@ void QuantRDOQ::forwardRDPCM( TransformUnit &tu, const ComponentID &compID, cons const BinFracBits fracBitsPar = fracBits.getFracBitsArray(cctx.parityCtxIdAbsTS()); goRiceParam = cctx.templateAbsSumTS(scanPos, dstCoeff); +#if JVET_O0122_TS_SIGN_LEVEL + unsigned ctxIdSign = cctx.signCtxIdAbsTS(scanPos, dstCoeff, dirMode); + const BinFracBits fracBitsSign = fracBits.getFracBitsArray(ctxIdSign); +#else const BinFracBits fracBitsSign = fracBits.getFracBitsArray(Ctx::TsResidualSign(1)); +#endif const uint8_t sign = srcCoeff[blkPos] - predCoeff < 0 ? 1 : 0; +#if JVET_O0122_TS_SIGN_LEVEL + unsigned gt1CtxId = cctx.lrg1CtxIdAbsTS(scanPos, dstCoeff, dirMode); + const BinFracBits fracBitsGr1 = fracBits.getFracBitsArray(gt1CtxId); +#endif +#if JVET_O0122_TS_SIGN_LEVEL + DTRACE_COND((dstCoeff[blkPos] != 0), g_trace_ctx, D_RDOQ_MORE, " uiCtxSig=%d", ctxIdSig); +#else DTRACE_COND((maxAbsLevel != 0), g_trace_ctx, D_RDOQ_MORE, " uiCtxSig=%d", ctxIdSig); +#endif const BinFracBits fracBitsSig = fracBits.getFracBitsArray(ctxIdSig); bool lastCoeff = false; // @@ -1495,8 +1604,16 @@ void QuantRDOQ::forwardRDPCM( TransformUnit &tu, const ComponentID &compID, cons { lastCoeff = true; } +#if JVET_O0122_TS_SIGN_LEVEL + int rightPixel, belowPixel; + cctx.neighTS(rightPixel, belowPixel, scanPos, dstCoeff); + cLevel = xGetCodedLevelTSPred(costCoeff[scanPos], costCoeff0[scanPos], costSig[scanPos], levelDouble, qBits, errorScale, coeffLevels, coeffLevelError, + &fracBitsSig, fracBitsPar, cctx, fracBits, fracBitsSign, fracBitsGr1, sign, rightPixel, belowPixel, goRiceParam, lastCoeff, extendedPrecision, maxLog2TrDynamicRange); +#else cLevel = xGetCodedLevelTS(costCoeff[scanPos], costCoeff0[scanPos], costSig[scanPos], levelDouble, maxAbsLevel, &fracBitsSig, fracBitsPar, cctx, fracBits, fracBitsSign, sign, goRiceParam, qBits, errorScale, lastCoeff, extendedPrecision, maxLog2TrDynamicRange); +#endif + if (cLevel > 0) { noCoeffCoded++; @@ -1596,6 +1713,73 @@ void QuantRDOQ::xDequantSample(TCoeff& pRes, TCoeff& coeff, const TrQuantParams& pRes = TCoeff((Intermediate_Int(coeff) * trQuantParams.qScale) << -trQuantParams.rightShift); } } + +#if JVET_O0122_TS_SIGN_LEVEL +inline uint32_t QuantRDOQ::xGetCodedLevelTSPred(double& rd64CodedCost, + double& rd64CodedCost0, + double& rd64CodedCostSig, + Intermediate_Int levelDouble, + int qBits, + double errorScale, + uint32_t coeffLevels[], + double coeffLevelError[], + const BinFracBits* fracBitsSig, + const BinFracBits& fracBitsPar, + CoeffCodingContext& cctx, + const FracBitsAccess& fracBitsAccess, + const BinFracBits& fracBitsSign, + const BinFracBits& fracBitsGt1, + const uint8_t sign, + int rightPixel, + int belowPixel, + uint16_t ricePar, + bool isLast, + bool useLimitedPrefixLength, + const int maxLog2TrDynamicRange +) const +{ + double currCostSig = 0; + uint32_t bestAbsLevel = 0; + if (!isLast && coeffLevels[0] < 3) + { + rd64CodedCostSig = xGetRateSigCoef(*fracBitsSig, 0); + rd64CodedCost = rd64CodedCost0 + rd64CodedCostSig; + if (coeffLevels[0] == 0) + { + return bestAbsLevel; + } + } + else + { + rd64CodedCost = MAX_DOUBLE; + } + + if (!isLast) + { + currCostSig = xGetRateSigCoef(*fracBitsSig, 1); + } + + for (int errorInd = 1; errorInd <= m_testedLevels; errorInd++) + { + int absLevel = coeffLevels[errorInd - 1]; + double dErr = 0.0; + dErr = double(levelDouble - (Intermediate_Int(absLevel) << qBits)); + coeffLevelError[errorInd] = dErr * dErr * errorScale; + int modAbsLevel = cctx.deriveModCoeff(rightPixel, belowPixel, absLevel, m_bdpcm); + double dCurrCost = coeffLevelError[errorInd] + xGetICost(xGetICRateTS(modAbsLevel, fracBitsPar, cctx, fracBitsAccess, fracBitsSign, fracBitsGt1, sign, ricePar, useLimitedPrefixLength, maxLog2TrDynamicRange)); + dCurrCost += currCostSig; + + if (dCurrCost < rd64CodedCost) + { + bestAbsLevel = absLevel; + rd64CodedCost = dCurrCost; + rd64CodedCostSig = currCostSig; + } + } + + return bestAbsLevel; +} +#else inline uint32_t QuantRDOQ::xGetCodedLevelTS( double& codedCost, double& codedCost0, double& codedCostSig, @@ -1654,12 +1838,16 @@ inline uint32_t QuantRDOQ::xGetCodedLevelTS( double& codedCost return bestAbsLevel; } +#endif inline int QuantRDOQ::xGetICRateTS( const uint32_t absLevel, const BinFracBits& fracBitsPar, const CoeffCodingContext& cctx, const FracBitsAccess& fracBitsAccess, const BinFracBits& fracBitsSign, +#if JVET_O0122_TS_SIGN_LEVEL + const BinFracBits& fracBitsGt1, +#endif const uint8_t sign, const uint16_t ricePar, const bool useLimitedPrefixLength, @@ -1667,8 +1855,10 @@ inline int QuantRDOQ::xGetICRateTS( const uint32_t absLevel, { int rate = fracBitsSign.intBits[sign]; +#if !JVET_O0122_TS_SIGN_LEVEL const uint16_t ctxGt1 = cctx.greaterXCtxIdAbsTS( 0 ); const BinFracBits &fracBitsGt1 = fracBitsAccess.getFracBitsArray( ctxGt1 ); +#endif if( absLevel > 1 ) { diff --git a/source/Lib/CommonLib/QuantRDOQ.h b/source/Lib/CommonLib/QuantRDOQ.h index 1f50f3663e..0010d40c10 100644 --- a/source/Lib/CommonLib/QuantRDOQ.h +++ b/source/Lib/CommonLib/QuantRDOQ.h @@ -122,6 +122,30 @@ private: void xRateDistOptQuantTS( TransformUnit &tu, const ComponentID &compID, const CCoeffBuf &coeffs, TCoeff &absSum, const QpParam &qp, const Ctx &ctx ); +#if JVET_O0122_TS_SIGN_LEVEL + inline uint32_t xGetCodedLevelTSPred(double& rd64CodedCost, + double& rd64CodedCost0, + double& rd64CodedCostSig, + Intermediate_Int levelDouble, + int qBits, + double errorScale, + uint32_t coeffLevels[], + double coeffLevelError[], + const BinFracBits* fracBitsSig, + const BinFracBits& fracBitsPar, + CoeffCodingContext& cctx, + const FracBitsAccess& fracBitsAccess, + const BinFracBits& fracBitsSign, + const BinFracBits& fracBitsGt1, + const uint8_t sign, + int rightPixel, + int belowPixel, + uint16_t ricePar, + bool isLast, + bool useLimitedPrefixLength, + const int maxLog2TrDynamicRange + ) const; +#else inline uint32_t xGetCodedLevelTS( double& codedCost, double& codedCost0, double& codedCostSig, @@ -139,12 +163,16 @@ private: bool isLast, bool useLimitedPrefixLength, const int maxLog2TrDynamicRange ) const; +#endif inline int xGetICRateTS ( const uint32_t absLevel, const BinFracBits& fracBitsPar, const CoeffCodingContext& cctx, const FracBitsAccess& fracBitsAccess, const BinFracBits& fracBitsSign, +#if JVET_O0122_TS_SIGN_LEVEL + const BinFracBits& fracBitsGt1, +#endif const uint8_t sign, const uint16_t ricePar, const bool useLimitedPrefixLength, @@ -164,6 +192,10 @@ private: int m_sigRateDelta [MAX_TB_SIZEY * MAX_TB_SIZEY]; TCoeff m_deltaU [MAX_TB_SIZEY * MAX_TB_SIZEY]; TCoeff m_fullCoeff [MAX_TB_SIZEY * MAX_TB_SIZEY]; +#if JVET_O0122_TS_SIGN_LEVEL + int m_bdpcm; + int m_testedLevels; +#endif };// END CLASS DEFINITION QuantRDOQ //! \} diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h index 51316ba78b..8bb29364a3 100644 --- a/source/Lib/CommonLib/TypeDef.h +++ b/source/Lib/CommonLib/TypeDef.h @@ -58,6 +58,8 @@ #define JVET_O0284_CONDITION_SMVD_MVDL1ZEROFLAG 1 // JVET-O0284: condition sym_mvd_flag on mvd_l1_zero_flag +#define JVET_O0122_TS_SIGN_LEVEL 1 // JVET-O0122: Sign context and level mapping of TS residual coding. + #define JVET_O0438_SPS_AFFINE_AMVR_FLAG 1 // JVET-O0438: affine AMVR control flag conditioned on affine control flag in SPS #define JVET_O0065_CABAC_INIT 0 // JVET-O0065: CABAC initialization diff --git a/source/Lib/DecoderLib/CABACReader.cpp b/source/Lib/DecoderLib/CABACReader.cpp index 3f56195fa7..46f1f83e01 100644 --- a/source/Lib/DecoderLib/CABACReader.cpp +++ b/source/Lib/DecoderLib/CABACReader.cpp @@ -3204,7 +3204,12 @@ void CABACReader::residual_coding_subblockTS( CoeffCodingContext& cctx, TCoeff* int sign; if( cctx.isContextCoded() ) { +#if JVET_O0122_TS_SIGN_LEVEL + const unsigned signCtxId = cctx.signCtxIdAbsTS(nextSigPos, coeff, cctx.bdpcm()); + sign = m_BinDecoder.decodeBin(signCtxId); +#else sign = m_BinDecoder.decodeBin( Ctx::TsResidualSign( cctx.bdpcm() ? 1 : 0 ) ); +#endif } else { @@ -3217,6 +3222,19 @@ void CABACReader::residual_coding_subblockTS( CoeffCodingContext& cctx, TCoeff* RExt__DECODER_DEBUG_BIT_STATISTICS_SET( ctype_gt1 ); unsigned gt1Flag; +#if JVET_O0122_TS_SIGN_LEVEL + const unsigned gt1CtxId = cctx.lrg1CtxIdAbsTS(nextSigPos, coeff, cctx.bdpcm()); + if( cctx.isContextCoded() ) + { + gt1Flag = m_BinDecoder.decodeBin(gt1CtxId); + DTRACE( g_trace_ctx, D_SYNTAX_RESI, "ts_gt1_flag() bin=%d ctx=%d\n", gt1Flag, gt1CtxId ); + } + else + { + gt1Flag = m_BinDecoder.decodeBinEP( ); + DTRACE( g_trace_ctx, D_SYNTAX_RESI, "ts_gt1_flag() EPbin=%d\n", gt1Flag ); + } +#else if( cctx.isContextCoded() ) { gt1Flag = m_BinDecoder.decodeBin( cctx.greaterXCtxIdAbsTS(0) ); @@ -3227,6 +3245,7 @@ void CABACReader::residual_coding_subblockTS( CoeffCodingContext& cctx, TCoeff* gt1Flag = m_BinDecoder.decodeBinEP( ); DTRACE( g_trace_ctx, D_SYNTAX_RESI, "ts_gt1_flag() EPbin=%d\n", gt1Flag ); } +#endif unsigned parFlag = 0; if( gt1Flag ) @@ -3243,7 +3262,11 @@ void CABACReader::residual_coding_subblockTS( CoeffCodingContext& cctx, TCoeff* DTRACE( g_trace_ctx, D_SYNTAX_RESI, "ts_par_flag() EPbin=%d\n", parFlag ); } } +#if JVET_O0122_TS_SIGN_LEVEL + coeff[ blkPos ] = (sign ? -1 : 1 ) * (1 + parFlag + gt1Flag); +#else coeff[ blkPos ] += 1 + parFlag + gt1Flag; +#endif } } @@ -3256,6 +3279,12 @@ void CABACReader::residual_coding_subblockTS( CoeffCodingContext& cctx, TCoeff* for( int scanPos = firstSigPos; scanPos <= minSubPos; scanPos++ ) { TCoeff& tcoeff = coeff[cctx.blockPos( scanPos )]; +#if JVET_O0122_TS_SIGN_LEVEL + if( tcoeff < 0) + { + tcoeff = -tcoeff; + } +#endif if( tcoeff >= cutoffVal ) { RExt__DECODER_DEBUG_BIT_STATISTICS_SET( ctype_gt2 ); @@ -3289,6 +3318,17 @@ void CABACReader::residual_coding_subblockTS( CoeffCodingContext& cctx, TCoeff* DTRACE( g_trace_ctx, D_SYNTAX_RESI, "ts_rem_val() bin=%d ctx=%d sp=%d\n", rem, rice, scanPos ); tcoeff += ( rem << 1 ); } +#if JVET_O0122_TS_SIGN_LEVEL + if (!cctx.bdpcm()) + { + if (tcoeff > 0) + { + int rightPixel, belowPixel; + cctx.neighTS(rightPixel, belowPixel, scanPos, coeff); + tcoeff = cctx.decDeriveModCoeff(rightPixel, belowPixel, tcoeff); + } + } +#endif } //===== set final coefficents ===== diff --git a/source/Lib/EncoderLib/CABACWriter.cpp b/source/Lib/EncoderLib/CABACWriter.cpp index 37ae687126..081a36d53b 100644 --- a/source/Lib/EncoderLib/CABACWriter.cpp +++ b/source/Lib/EncoderLib/CABACWriter.cpp @@ -3022,6 +3022,10 @@ void CABACWriter::residual_coding_subblockTS( CoeffCodingContext& cctx, const TC int remAbsLevel = -1; int numNonZero = 0; +#if JVET_O0122_TS_SIGN_LEVEL + int rightPixel, belowPixel, modAbsCoeff; +#endif + for( ; nextSigPos <= minSubPos; nextSigPos++ ) { TCoeff Coeff = coeff[ cctx.blockPos( nextSigPos ) ]; @@ -3047,16 +3051,40 @@ void CABACWriter::residual_coding_subblockTS( CoeffCodingContext& cctx, const TC int sign = Coeff < 0; if( cctx.isContextCoded() ) { +#if JVET_O0122_TS_SIGN_LEVEL + const unsigned signCtxId = cctx.signCtxIdAbsTS(nextSigPos, coeff, cctx.bdpcm()); + m_BinEncoder.encodeBin(sign, signCtxId); +#else m_BinEncoder.encodeBin( sign, Ctx::TsResidualSign( cctx.bdpcm() ? 1 : 0 ) ); +#endif } else { m_BinEncoder.encodeBinEP( sign ); } numNonZero++; +#if JVET_O0122_TS_SIGN_LEVEL + cctx.neighTS(rightPixel, belowPixel, nextSigPos, coeff); + modAbsCoeff = cctx.deriveModCoeff(rightPixel, belowPixel, abs(Coeff), cctx.bdpcm()); + remAbsLevel = modAbsCoeff - 1; +#else remAbsLevel = abs( Coeff ) - 1; +#endif unsigned gt1 = !!remAbsLevel; +#if JVET_O0122_TS_SIGN_LEVEL + const unsigned gt1CtxId = cctx.lrg1CtxIdAbsTS(nextSigPos, coeff, cctx.bdpcm()); + if (cctx.isContextCoded()) + { + m_BinEncoder.encodeBin(gt1, gt1CtxId); + DTRACE(g_trace_ctx, D_SYNTAX_RESI, "ts_gt1_flag() bin=%d ctx=%d\n", gt1, gt1CtxId); + } + else + { + m_BinEncoder.encodeBinEP(gt1); + DTRACE(g_trace_ctx, D_SYNTAX_RESI, "ts_gt1_flag() EPbin=%d\n", gt1); + } +#else if( cctx.isContextCoded() ) { m_BinEncoder.encodeBin( gt1, cctx.greaterXCtxIdAbsTS(0) ); @@ -3067,6 +3095,7 @@ void CABACWriter::residual_coding_subblockTS( CoeffCodingContext& cctx, const TC m_BinEncoder.encodeBinEP( gt1 ); DTRACE( g_trace_ctx, D_SYNTAX_RESI, "ts_gt1_flag() EPbin=%d\n", gt1 ); } +#endif if( gt1 ) { @@ -3092,7 +3121,13 @@ void CABACWriter::residual_coding_subblockTS( CoeffCodingContext& cctx, const TC { for( int scanPos = firstSigPos; scanPos <= minSubPos; scanPos++ ) { +#if JVET_O0122_TS_SIGN_LEVEL + unsigned absLevel; + cctx.neighTS(rightPixel, belowPixel, scanPos, coeff); + absLevel = cctx.deriveModCoeff(rightPixel, belowPixel, abs(coeff[cctx.blockPos(scanPos)]), cctx.bdpcm()); +#else unsigned absLevel = abs( coeff[cctx.blockPos( scanPos )] ); +#endif if( absLevel >= cutoffVal ) { unsigned gt2 = ( absLevel >= ( cutoffVal + 2 ) ); @@ -3114,8 +3149,14 @@ void CABACWriter::residual_coding_subblockTS( CoeffCodingContext& cctx, const TC //===== coeff bypass ==== for( int scanPos = firstSigPos; scanPos <= minSubPos; scanPos++ ) { +#if JVET_O0122_TS_SIGN_LEVEL + unsigned absLevel; + cctx.neighTS(rightPixel, belowPixel, scanPos, coeff); + absLevel = cctx.deriveModCoeff(rightPixel, belowPixel, abs(coeff[cctx.blockPos(scanPos)]), cctx.bdpcm()); +#else TCoeff Coeff = coeff[ cctx.blockPos( scanPos ) ]; unsigned absLevel = abs( Coeff ); +#endif if( absLevel >= cutoffVal ) { int rice = cctx.templateAbsSumTS( scanPos, coeff ); -- GitLab