From c24e9154a6ce486320f77534f324438e123e4b1d Mon Sep 17 00:00:00 2001 From: Heiko Schwarz <heiko.schwarz@hhi.fraunhofer.de> Date: Wed, 17 Oct 2018 19:13:54 +0200 Subject: [PATCH] integration of JVET-L0274 "Transform coefficient coding with reduced number of regular coded bins", version CE-7.1.3b (with modified binarization), including restrictions for chroma 2x2 subblocks. --- source/Lib/CommonLib/CommonDef.h | 6 + source/Lib/CommonLib/ContextModelling.h | 36 ++- source/Lib/CommonLib/Contexts.cpp | 85 +++++++ source/Lib/CommonLib/DepQuant.cpp | 302 ++++++++++++++++++++++++ source/Lib/CommonLib/QuantRDOQ.cpp | 158 +++++++++++++ source/Lib/CommonLib/QuantRDOQ.h | 10 + source/Lib/CommonLib/Rom.cpp | 13 + source/Lib/CommonLib/Rom.h | 5 + source/Lib/CommonLib/TypeDef.h | 2 + source/Lib/DecoderLib/CABACReader.cpp | 113 +++++++++ source/Lib/EncoderLib/CABACWriter.cpp | 111 +++++++++ 11 files changed, 840 insertions(+), 1 deletion(-) diff --git a/source/Lib/CommonLib/CommonDef.h b/source/Lib/CommonLib/CommonDef.h index 55c0bd395..ca19bff85 100644 --- a/source/Lib/CommonLib/CommonDef.h +++ b/source/Lib/CommonLib/CommonDef.h @@ -291,6 +291,12 @@ static const int AFFINE_MAX_NUM_V2 = 2; ///< max static const int AFFINE_MAX_NUM_COMB = 12; ///< max number of combined motion candidates static const int AFFINE_MIN_BLOCK_SIZE = 4; ///< Minimum affine MC block size +#if JVET_L0274 +static const int MAX_NUM_REG_BINS_4x4SUBBLOCK = 32; ///< max number of context-coded bins (incl. gt2 bins) per 4x4 subblock +static const int MAX_NUM_GT2_BINS_4x4SUBBLOCK = 4; ///< max number of gt2 bins per 4x4 subblock +static const int MAX_NUM_REG_BINS_2x2SUBBLOCK = 8; ///< max number of context-coded bins (incl. gt2 bins) per 2x2 subblock (chroma) +static const int MAX_NUM_GT2_BINS_2x2SUBBLOCK = 2; ///< max number of gt2 bins per 2x2 subblock (chroma) +#endif #if W0038_DB_OPT static const int MAX_ENCODER_DEBLOCKING_QUALITY_LAYERS = 8 ; diff --git a/source/Lib/CommonLib/ContextModelling.h b/source/Lib/CommonLib/ContextModelling.h index 681631922..b85e926b7 100644 --- a/source/Lib/CommonLib/ContextModelling.h +++ b/source/Lib/CommonLib/ContextModelling.h @@ -107,7 +107,11 @@ public: const int diag = posX + posY; int numPos = 0; int sumAbs = 0; +#if JVET_L0274 +#define UPDATE(x) {int a=abs(x);sumAbs+=std::min(2+(a&1),a);numPos+=!!a;} +#else #define UPDATE(x) {int a=abs(x);sumAbs+=std::min(4-(a&1),a);numPos+=!!a;} +#endif if( posX < m_width-1 ) { UPDATE( pData[1] ); @@ -154,6 +158,36 @@ public: unsigned greater1CtxIdAbs ( uint8_t offset ) const { return m_gtxFlagCtxSet[1]( offset ); } unsigned greater2CtxIdAbs ( uint8_t offset ) const { return m_gtxFlagCtxSet[0]( offset ); } +#if JVET_L0274 + unsigned templateAbsSum( int scanPos, const TCoeff* coeff ) + { + const uint32_t posY = m_scanPosY[scanPos]; + const uint32_t posX = m_scanPosX[scanPos]; + const TCoeff* pData = coeff + posX + posY * m_width; + int sum = 0; + if (posX < m_width - 1) + { + sum += abs(pData[1]); + if (posX < m_width - 2) + { + sum += abs(pData[2]); + } + if (posY < m_height - 1) + { + sum += abs(pData[m_width + 1]); + } + } + if (posY < m_height - 1) + { + sum += abs(pData[m_width]); + if (posY < m_height - 2) + { + sum += abs(pData[m_width << 1]); + } + } + return std::min(sum, 31); + } +#else unsigned GoRiceParAbs( int scanPos, const TCoeff* coeff ) const { #define UPDATE(x) sum+=abs(x)-!!x @@ -185,7 +219,7 @@ public: int r = g_auiGoRicePars[ std::min( sum, 31 ) ]; return r; } - +#endif unsigned emtNumSigCoeff() const { return m_emtNumSigCoeff; } void setEmtNumSigCoeff( unsigned val ) { m_emtNumSigCoeff = val; } diff --git a/source/Lib/CommonLib/Contexts.cpp b/source/Lib/CommonLib/Contexts.cpp index 2313dda61..a447307f3 100644 --- a/source/Lib/CommonLib/Contexts.cpp +++ b/source/Lib/CommonLib/Contexts.cpp @@ -447,6 +447,44 @@ const CtxSet ContextSetCfg::SigCoeffGroup[] = const CtxSet ContextSetCfg::SigFlag[] = { +#if JVET_L0274 + ContextSetCfg::addCtxSet + ({ + { 120, 152, 167, 153, 168, 169, 119, 167, 197, 183, 183, 170, 209, 213, 183, 183, 169, 185, }, + { 149, 152, 167, 168, 183, 140, 149, 182, 168, 183, 169, 170, 195, 213, 183, 198, 184, 156, }, + { 120, 138, 153, 154, 140, 126, 120, 139, 154, 155, 155, 142, 137, 185, 169, 185, 171, 159, }, + }), + ContextSetCfg::addCtxSet + ({ + { 148, 167, 153, 139, 154, 140, 166, 199, 183, 184, 184, 157, }, + { 134, 168, 168, 139, 169, 155, 166, 229, 198, 229, 185, 157, }, + { 119, 168, 153, 140, 140, 141, 167, 200, 155, 172, 142, 158, }, + }), + ContextSetCfg::addCtxSet + ({ + { 152, 127, 173, 201, 187, 173, 226, 188, 188, 217, 188, 174, 182, 223, 223, 223, 223, 223, }, + { 123, 142, 202, 172, 157, 203, 138, 173, 218, 188, 173, 175, 168, 223, 223, 223, 223, 223, }, + { 108, 157, 173, 173, 218, 189, 123, 175, 159, 175, 190, 251, 79, 223, 223, 223, 223, 223, }, + }), + ContextSetCfg::addCtxSet + ({ + { 196, 156, 143, 158, 172, 216, 168, 223, 223, 223, 191, 223, }, + { 182, 141, 158, 186, 142, 173, 183, 223, 223, 223, 222, 223, }, + { 152, 158, 157, 187, 204, 175, 170, 223, 223, 237, 223, 223, }, + }), + ContextSetCfg::addCtxSet + ({ + { 137, 142, 189, 173, 187, 174, 241, 175, 175, 174, 174, 204, 210, 223, 223, 223, 223, 223, }, + { 123, 172, 175, 158, 158, 233, 138, 175, 190, 175, 188, 175, 196, 223, 223, 223, 223, 223, }, + { 107, 143, 219, 188, 233, 190, 63, 250, 205, 252, 220, 251, 63, 223, 223, 223, 223, 253, }, + }), + ContextSetCfg::addCtxSet + ({ + { 167, 185, 159, 158, 159, 189, 196, 223, 223, 223, 223, 223, }, + { 167, 141, 175, 143, 172, 159, 182, 223, 223, 223, 223, 223, }, + { 166, 159, 158, 232, 158, 174, 183, 238, 223, 223, 223, 223, }, + }), +#else ContextSetCfg::addCtxSet ({ { 106, 167, 182, 124, 139, 169, 134, 167, 197, 183, 183, 184, 209, 198, 168, 168, 183, 170, CNU, CNU, }, @@ -483,9 +521,55 @@ const CtxSet ContextSetCfg::SigFlag[] = { 167, 155, 159, 157, 157, 158, 182, 223, 223, 223, 223, 223, }, { 181, 159, 143, 232, 143, 173, 169, 237, 223, 223, 238, 253, }, }), +#endif }; +#if JVET_L0274 +const CtxSet ContextSetCfg::ParFlag[] = +{ + ContextSetCfg::addCtxSet + ({ + { 105, 119, 151, 152, 153, 153, 135, 152, 182, 153, 168, 136, 182, 153, 168, 139, 166, 168, 139, 168, 154, }, + { 120, 119, 151, 167, 138, 168, 135, 152, 153, 153, 139, 136, 153, 153, 168, 139, 137, 168, 168, 139, 139, }, + { 135, 150, 152, 138, 153, 153, 151, 123, 153, 168, 139, 152, 153, 153, 139, 139, 138, 168, 139, 154, 139, }, + }), + ContextSetCfg::addCtxSet + ({ + { 105, 135, 152, 167, 153, 124, 151, 168, 169, 153, 124, }, + { 134, 150, 152, 153, 153, 153, 166, 168, 168, 139, 139, }, + { 135, 121, 167, 168, 138, 153, 167, 139, 154, 139, 154, }, + }), +}; + +const CtxSet ContextSetCfg::GtxFlag[] = +{ + ContextSetCfg::addCtxSet + ({ + { 73, 0, 58, 119, 150, 137, 42, 73, 120, 136, 123, 58, 149, 151, 152, 153, 134, 136, 152, 153, 125, }, + { 88, 0, 102, 104, 150, 122, 101, 89, 150, 151, 138, 88, 120, 122, 152, 153, 105, 107, 123, 153, 154, }, + { 134, 161, 149, 121, 122, 138, 88, 120, 107, 108, 109, 105, 107, 123, 109, 124, 151, 138, 139, 154, 140, }, + }), + ContextSetCfg::addCtxSet + ({ + { 87, 57, 90, 107, 107, 63, 119, 91, 152, 124, 140, }, + { 101, 0, 105, 121, 107, 93, 118, 106, 108, 124, 154, }, + { 179, 72, 90, 121, 122, 123, 75, 76, 123, 139, 170, }, + }), + ContextSetCfg::addCtxSet + ({ + { 89, 103, 121, 137, 138, 139, 119, 137, 138, 139, 125, 135, 167, 168, 154, 140, 136, 153, 183, 155, 185, }, + { 118, 0, 136, 152, 153, 154, 134, 152, 153, 139, 140, 150, 138, 139, 154, 155, 151, 153, 169, 140, 200, }, + { 164, 149, 137, 153, 124, 125, 151, 138, 139, 125, 125, 152, 139, 140, 140, 111, 153, 154, 155, 170, 127, }, + }), + ContextSetCfg::addCtxSet + ({ + { 27, 149, 137, 153, 139, 125, 151, 154, 170, 127, 127, }, + { 132, 135, 152, 139, 139, 125, 151, 154, 155, 141, 142, }, + { 165, 121, 138, 139, 139, 125, 138, 154, 156, 171, 127, }, + }), +}; +#else const CtxSet ContextSetCfg::ParFlag[] = { ContextSetCfg::addCtxSet @@ -529,6 +613,7 @@ const CtxSet ContextSetCfg::GtxFlag[] = { 147, 73, 164, 151, 107, 109, 120, 152, 140, 185, 111, }, }), }; +#endif const CtxSet ContextSetCfg::LastX[] = { diff --git a/source/Lib/CommonLib/DepQuant.cpp b/source/Lib/CommonLib/DepQuant.cpp index 8e146f018..63a11cedc 100644 --- a/source/Lib/CommonLib/DepQuant.cpp +++ b/source/Lib/CommonLib/DepQuant.cpp @@ -64,7 +64,12 @@ namespace DQIntern }; struct CoeffFracBits { +#if JVET_L0274 + int32_t bits[6]; +#else int32_t bits[7]; +#endif + }; @@ -463,12 +468,20 @@ namespace DQIntern int32_t par0 = (1<<SCALE_BITS) + int32_t(fbPar.intBits[0]); int32_t par1 = (1<<SCALE_BITS) + int32_t(fbPar.intBits[1]); cb.bits[0] = 0; +#if JVET_L0274 + cb.bits[1] = fbGt1.intBits[0] + (1 << SCALE_BITS); + cb.bits[2] = fbGt1.intBits[1] + par0 + fbGt2.intBits[0]; + cb.bits[3] = fbGt1.intBits[1] + par1 + fbGt2.intBits[0]; + cb.bits[4] = fbGt1.intBits[1] + par0 + fbGt2.intBits[1]; + cb.bits[5] = fbGt1.intBits[1] + par1 + fbGt2.intBits[1]; +#else cb.bits[1] = par0 + fbGt1.intBits[0]; cb.bits[2] = par1 + fbGt1.intBits[0]; cb.bits[3] = par0 + fbGt1.intBits[1] + fbGt2.intBits[0]; cb.bits[4] = par1 + fbGt1.intBits[1] + fbGt2.intBits[0]; cb.bits[5] = par0 + fbGt1.intBits[1] + fbGt2.intBits[1]; cb.bits[6] = par1 + fbGt1.intBits[1] + fbGt2.intBits[1]; +#endif } } @@ -496,10 +509,15 @@ namespace DQIntern int insidePos; int nextInsidePos; NbInfoSbb nextNbInfoSbb; +#if JVET_L0274 + bool eosbb; + ScanPosType spt; +#else bool sosbb; bool eosbb; bool socsbb; bool eocsbb; +#endif int sbbPos; int nextSbbRight; int nextSbbBelow; @@ -536,10 +554,19 @@ namespace DQIntern sbbPos = m_rateEst.sbbPos ( scanIdx ); lastOffset = m_rateEst.lastOffset ( scanIdx ); insidePos = scanIdx & m_sbbMask; +#if JVET_L0274 + eosbb = ( insidePos == 0 ); + spt = SCAN_ISCSBB; + if( insidePos == m_sbbMask && scanIdx > sbbSize && scanIdx < m_numCoeffMinus1 ) + spt = SCAN_SOCSBB; + else if( eosbb && scanIdx > 0 && scanIdx < m_numCoeffMinusSbb ) + spt = SCAN_EOCSBB; +#else sosbb = ( insidePos == m_sbbMask ); eosbb = ( insidePos == 0 ); socsbb = ( sosbb && scanIdx > sbbSize && scanIdx < m_numCoeffMinus1 ); eocsbb = ( eosbb && scanIdx > 0 && scanIdx < m_numCoeffMinusSbb ); +#endif if( scanIdx ) { const int nextScanIdx = scanIdx - 1; @@ -848,6 +875,16 @@ namespace DQIntern uint8_t m_memory[ 8 * ( MAX_TU_SIZE * MAX_TU_SIZE + MLS_GRP_NUM ) ]; }; +#if JVET_L0274 +#define RICEMAX 32 + const int32_t g_goRiceBits[4][RICEMAX] = + { + { 32768, 65536, 98304, 131072, 163840, 196608, 229376, 294912, 294912, 360448, 360448, 360448, 360448, 425984, 425984, 425984, 425984, 425984, 425984, 425984, 425984, 491520, 491520, 491520, 491520, 491520, 491520, 491520, 491520, 491520, 491520, 491520 }, + { 65536, 65536, 98304, 98304, 131072, 131072, 163840, 163840, 196608, 196608, 229376, 229376, 294912, 294912, 294912, 294912, 360448, 360448, 360448, 360448, 360448, 360448, 360448, 360448, 425984, 425984, 425984, 425984, 425984, 425984, 425984, 425984 }, + { 98304, 98304, 98304, 98304, 131072, 131072, 131072, 131072, 163840, 163840, 163840, 163840, 196608, 196608, 196608, 196608, 229376, 229376, 229376, 229376, 262144, 262144, 262144, 262144, 294912, 294912, 294912, 294912, 360448, 360448, 360448, 360448 }, + { 131072, 131072, 131072, 131072, 131072, 131072, 131072, 131072, 163840, 163840, 163840, 163840, 163840, 163840, 163840, 163840, 196608, 196608, 196608, 196608, 196608, 196608, 196608, 196608, 229376, 229376, 229376, 229376, 229376, 229376, 229376, 229376 } + }; +#endif class State { @@ -864,12 +901,90 @@ namespace DQIntern { m_rdCost = std::numeric_limits<int64_t>::max()>>1; m_numSigSbb = 0; +#if JVET_L0274 + m_remRegBins = 3; // just large enough for last scan pos +#endif m_refSbbCtxId = -1; m_sigFracBits = m_sigFracBitsArray[ 0 ]; m_coeffFracBits = m_gtxFracBitsArray[ 0 ]; m_goRicePar = 0; +#if JVET_L0274 + m_goRiceZero = 0; +#endif } +#if JVET_L0274 + void checkRdCosts( const ScanPosType spt, const PQData& pqDataA, const PQData& pqDataB, Decision& decisionA, Decision& decisionB) const + { + const int32_t* goRiceTab = g_goRiceBits[m_goRicePar]; + int64_t rdCostA = m_rdCost + pqDataA.deltaDist; + int64_t rdCostB = m_rdCost + pqDataB.deltaDist; + int64_t rdCostZ = m_rdCost; + if( m_remRegBins >= 3 ) + { + if( pqDataA.absLevel < 4 ) + rdCostA += m_coeffFracBits.bits[pqDataA.absLevel]; + else + { + const unsigned value = (pqDataA.absLevel - 4) >> 1; + rdCostA += m_coeffFracBits.bits[pqDataA.absLevel - (value << 1)] + goRiceTab[value<RICEMAX ? value : RICEMAX-1]; + } + if( pqDataB.absLevel < 4 ) + rdCostB += m_coeffFracBits.bits[pqDataB.absLevel]; + else + { + const unsigned value = (pqDataB.absLevel - 4) >> 1; + rdCostB += m_coeffFracBits.bits[pqDataB.absLevel - (value << 1)] + goRiceTab[value<RICEMAX ? value : RICEMAX-1]; + } + if( spt == SCAN_ISCSBB ) + { + rdCostA += m_sigFracBits.intBits[1]; + rdCostB += m_sigFracBits.intBits[1]; + rdCostZ += m_sigFracBits.intBits[0]; + } + else if( spt == SCAN_SOCSBB ) + { + rdCostA += m_sbbFracBits.intBits[1] + m_sigFracBits.intBits[1]; + rdCostB += m_sbbFracBits.intBits[1] + m_sigFracBits.intBits[1]; + rdCostZ += m_sbbFracBits.intBits[1] + m_sigFracBits.intBits[0]; + } + else if( m_numSigSbb ) + { + rdCostA += m_sigFracBits.intBits[1]; + rdCostB += m_sigFracBits.intBits[1]; + rdCostZ += m_sigFracBits.intBits[0]; + } + else + { + rdCostZ = decisionA.rdCost; + } + } + else + { + rdCostA += (1 << SCALE_BITS) + goRiceTab[pqDataA.absLevel <= m_goRiceZero ? pqDataA.absLevel - 1 : (pqDataA.absLevel<RICEMAX ? pqDataA.absLevel : RICEMAX-1)]; + rdCostB += (1 << SCALE_BITS) + goRiceTab[pqDataB.absLevel <= m_goRiceZero ? pqDataB.absLevel - 1 : (pqDataB.absLevel<RICEMAX ? pqDataB.absLevel : RICEMAX-1)]; + rdCostZ += goRiceTab[m_goRiceZero]; + } + if( rdCostA < decisionA.rdCost ) + { + decisionA.rdCost = rdCostA; + decisionA.absLevel = pqDataA.absLevel; + decisionA.prevId = m_stateId; + } + if( rdCostZ < decisionA.rdCost ) + { + decisionA.rdCost = rdCostZ; + decisionA.absLevel = 0; + decisionA.prevId = m_stateId; + } + if( rdCostB < decisionB.rdCost ) + { + decisionB.rdCost = rdCostB; + decisionB.absLevel = pqDataB.absLevel; + decisionB.prevId = m_stateId; + } + } +#else template<ScanPosType spt> inline void checkRdCostZero(Decision &decision) const { int64_t rdCost = m_rdCost; @@ -943,10 +1058,24 @@ namespace DQIntern decision.prevId = m_stateId; } } +#endif inline void checkRdCostStart(int32_t lastOffset, const PQData &pqData, Decision &decision) const { +#if JVET_L0274 + int64_t rdCost = pqData.deltaDist + lastOffset; + if (pqData.absLevel < 4) + { + rdCost += m_coeffFracBits.bits[pqData.absLevel]; + } + else + { + const unsigned value = (pqData.absLevel - 4) >> 1; + rdCost += m_coeffFracBits.bits[pqData.absLevel - (value << 1)] + g_goRiceBits[m_goRicePar][value < RICEMAX ? value : RICEMAX-1]; + } +#else int64_t rdCost = pqData.deltaDist + lastOffset + getLevelBits( pqData.absLevel ); +#endif if( rdCost < decision.rdCost ) { decision.rdCost = rdCost; @@ -969,15 +1098,30 @@ namespace DQIntern private: int64_t m_rdCost; uint16_t m_absLevelsAndCtxInit[24]; // 16x8bit for abs levels + 16x16bit for ctx init id +#if JVET_L0274 + int8_t m_numSigSbb; + int8_t m_remRegBins; + int8_t m_refSbbCtxId; +#else int32_t m_numSigSbb; int32_t m_refSbbCtxId; +#endif BinFracBits m_sbbFracBits; BinFracBits m_sigFracBits; CoeffFracBits m_coeffFracBits; +#if JVET_L0274 + int8_t m_goRicePar; + int8_t m_goRiceZero; + const int8_t m_stateId; +#else int m_goRicePar; const int m_stateId; +#endif const BinFracBits*const m_sigFracBitsArray; const CoeffFracBits*const m_gtxFracBitsArray; +#if JVET_L0274 + const uint32_t*const m_goRiceZeroArray; +#endif CommonCtx& m_commonCtx; }; @@ -987,6 +1131,9 @@ namespace DQIntern , m_stateId ( stateId ) , m_sigFracBitsArray( rateEst.sigFlagBits(stateId) ) , m_gtxFracBitsArray( rateEst.gtxFracBits(stateId) ) +#if JVET_L0274 + , m_goRiceZeroArray ( g_auiGoRicePosCoeff0[std::max(0,stateId-1)] ) +#endif , m_commonCtx ( commonCtx ) { } @@ -1003,18 +1150,124 @@ namespace DQIntern m_numSigSbb = prvState->m_numSigSbb + !!decision.absLevel; m_refSbbCtxId = prvState->m_refSbbCtxId; m_sbbFracBits = prvState->m_sbbFracBits; +#if JVET_L0274 + m_remRegBins = prvState->m_remRegBins - 1; + m_goRicePar = prvState->m_goRicePar; + if( m_remRegBins >= 3 ) + { + TCoeff rem = (decision.absLevel - 4) >> 1; + if( m_goRicePar < 3 && rem > (3<<m_goRicePar)-1 ) + { + m_goRicePar++; + } + m_remRegBins -= std::min<TCoeff>( decision.absLevel, 2 ); + } +#endif ::memcpy( m_absLevelsAndCtxInit, prvState->m_absLevelsAndCtxInit, 48*sizeof(uint8_t) ); } else { m_numSigSbb = 1; m_refSbbCtxId = -1; +#if JVET_L0274 + if ( scanInfo.sbbSize == 4 ) + { + m_remRegBins = MAX_NUM_REG_BINS_2x2SUBBLOCK - MAX_NUM_GT2_BINS_2x2SUBBLOCK - std::min<TCoeff>( decision.absLevel, 2 ); + } + else + { + m_remRegBins = MAX_NUM_REG_BINS_4x4SUBBLOCK - MAX_NUM_GT2_BINS_4x4SUBBLOCK - std::min<TCoeff>( decision.absLevel, 2 ); + } + m_goRicePar = ( ((decision.absLevel - 4) >> 1) > (3<<0)-1 ? 1 : 0 ); +#endif ::memset( m_absLevelsAndCtxInit, 0, 48*sizeof(uint8_t) ); } uint8_t* levels = reinterpret_cast<uint8_t*>(m_absLevelsAndCtxInit); levels[ scanInfo.insidePos ] = (uint8_t)std::min<TCoeff>( 255, decision.absLevel ); +#if JVET_L0274 + if (m_remRegBins >= 3) + { + TCoeff tinit = m_absLevelsAndCtxInit[8 + scanInfo.nextInsidePos]; + TCoeff sumAbs1 = (tinit >> 3) & 31; + TCoeff sumNum = tinit & 7; +#define UPDATE(k) {TCoeff t=levels[scanInfo.nextNbInfoSbb.inPos[k]]; sumAbs1+=std::min<TCoeff>(2+(t&1),t); sumNum+=!!t; } + if (numIPos == 1) + { + UPDATE(0); + } + else if (numIPos == 2) + { + UPDATE(0); + UPDATE(1); + } + else if (numIPos == 3) + { + UPDATE(0); + UPDATE(1); + UPDATE(2); + } + else if (numIPos == 4) + { + UPDATE(0); + UPDATE(1); + UPDATE(2); + UPDATE(3); + } + else if (numIPos == 5) + { + UPDATE(0); + UPDATE(1); + UPDATE(2); + UPDATE(3); + UPDATE(4); + } +#undef UPDATE + TCoeff sumGt1 = sumAbs1 - sumNum; + m_sigFracBits = m_sigFracBitsArray[scanInfo.sigCtxOffsetNext + (sumAbs1 < 5 ? sumAbs1 : 5)]; + m_coeffFracBits = m_gtxFracBitsArray[scanInfo.gtxCtxOffsetNext + (sumGt1 < 4 ? sumGt1 : 4)]; + } + else + { + TCoeff sumAbs = m_absLevelsAndCtxInit[8 + scanInfo.nextInsidePos] >> 8; +#define UPDATE(k) {TCoeff t=levels[scanInfo.nextNbInfoSbb.inPos[k]]; sumAbs+=t; } + if (numIPos == 1) + { + UPDATE(0); + } + else if (numIPos == 2) + { + UPDATE(0); + UPDATE(1); + } + else if (numIPos == 3) + { + UPDATE(0); + UPDATE(1); + UPDATE(2); + } + else if (numIPos == 4) + { + UPDATE(0); + UPDATE(1); + UPDATE(2); + UPDATE(3); + } + else if (numIPos == 5) + { + UPDATE(0); + UPDATE(1); + UPDATE(2); + UPDATE(3); + UPDATE(4); + } +#undef UPDATE + sumAbs = std::min(31, sumAbs); + m_goRicePar = g_auiGoRiceParsCoeff[sumAbs]; + m_goRiceZero = m_goRiceZeroArray[sumAbs]; + } +#else TCoeff tinit = m_absLevelsAndCtxInit[ 8 + scanInfo.nextInsidePos ]; TCoeff sumAbs = tinit >> 8; TCoeff sumAbs1 = ( tinit >> 3 ) & 31; @@ -1056,6 +1309,7 @@ namespace DQIntern m_sigFracBits = m_sigFracBitsArray[ scanInfo.sigCtxOffsetNext + ( sumAbs1 < 5 ? sumAbs1 : 5 ) ]; m_coeffFracBits = m_gtxFracBitsArray[ scanInfo.gtxCtxOffsetNext + ( sumGt1 < 4 ? sumGt1 : 4 ) ]; m_goRicePar = g_auiGoRicePars [ sumAbs < 31 ? sumAbs : 31 ]; +#endif } } @@ -1084,11 +1338,17 @@ namespace DQIntern TCoeff tinit = m_absLevelsAndCtxInit[ 8 + scanInfo.nextInsidePos ]; TCoeff sumNum = tinit & 7; TCoeff sumAbs1 = ( tinit >> 3 ) & 31; +#if JVET_L0274 +#else TCoeff sumAbs = ( tinit >> 8 ) - sumNum; +#endif TCoeff sumGt1 = sumAbs1 - sumNum; m_sigFracBits = m_sigFracBitsArray[ scanInfo.sigCtxOffsetNext + ( sumAbs1 < 5 ? sumAbs1 : 5 ) ]; m_coeffFracBits = m_gtxFracBitsArray[ scanInfo.gtxCtxOffsetNext + ( sumGt1 < 4 ? sumGt1 : 4 ) ]; +#if JVET_L0274 +#else m_goRicePar = g_auiGoRicePars [ sumAbs < 31 ? sumAbs : 31 ]; +#endif } } @@ -1112,6 +1372,17 @@ namespace DQIntern const int sigNSbb = ( ( scanInfo.nextSbbRight ? sbbFlags[ scanInfo.nextSbbRight ] : false ) || ( scanInfo.nextSbbBelow ? sbbFlags[ scanInfo.nextSbbBelow ] : false ) ? 1 : 0 ); currState.m_numSigSbb = 0; +#if JVET_L0274 + if (scanInfo.sbbSize == 4) + { + currState.m_remRegBins = MAX_NUM_REG_BINS_2x2SUBBLOCK - MAX_NUM_GT2_BINS_2x2SUBBLOCK; + } + else + { + currState.m_remRegBins = MAX_NUM_REG_BINS_4x4SUBBLOCK - MAX_NUM_GT2_BINS_4x4SUBBLOCK; + } +#endif + currState.m_goRicePar = 0; currState.m_refSbbCtxId = currState.m_stateId; currState.m_sbbFracBits = m_sbbFlagBits[ sigNSbb ]; @@ -1124,7 +1395,11 @@ namespace DQIntern if( nbOut->num ) { TCoeff sumAbs = 0, sumAbs1 = 0, sumNum = 0; +#if JVET_L0274 +#define UPDATE(k) {TCoeff t=absLevels[nbOut->outPos[k]]; sumAbs+=t; sumAbs1+=std::min<TCoeff>(2+(t&1),t); sumNum+=!!t; } +#else #define UPDATE(k) {TCoeff t=absLevels[nbOut->outPos[k]]; sumAbs+=t; sumAbs1+=std::min<TCoeff>(4-(t&1),t); sumNum+=!!t; } +#endif UPDATE(0); if( nbOut->num > 1 ) { @@ -1171,8 +1446,12 @@ namespace DQIntern private: void xDecideAndUpdate ( const TCoeff absCoeff, const ScanInfo& scanInfo ); +#if JVET_L0274 + void xDecide ( const ScanPosType spt, const TCoeff absCoeff, const int lastOffset, Decision* decisions ); +#else template<ScanPosType spt> void xDecide ( const TCoeff absCoeff, int32_t lastOffset, Decision* decisions ); +#endif private: CommonCtx m_commonCtx; @@ -1210,13 +1489,23 @@ namespace DQIntern #undef DINIT +#if JVET_L0274 + void DepQuant::xDecide( const ScanPosType spt, const TCoeff absCoeff, const int lastOffset, Decision* decisions) +#else template<ScanPosType spt> void DepQuant::xDecide( const TCoeff absCoeff, int32_t lastOffset, Decision* decisions ) +#endif { ::memcpy( decisions, startDec, 8*sizeof(Decision) ); PQData pqData[4]; m_quant.preQuantCoeff( absCoeff, pqData ); +#if JVET_L0274 + m_prevStates[0].checkRdCosts( spt, pqData[0], pqData[2], decisions[0], decisions[2]); + m_prevStates[1].checkRdCosts( spt, pqData[0], pqData[2], decisions[2], decisions[0]); + m_prevStates[2].checkRdCosts( spt, pqData[3], pqData[1], decisions[1], decisions[3]); + m_prevStates[3].checkRdCosts( spt, pqData[3], pqData[1], decisions[3], decisions[1]); +#else m_prevStates[0].checkRdCostNonZero<spt> ( pqData[0], decisions[0] ); m_prevStates[0].checkRdCostNonZero<spt> ( pqData[2], decisions[2] ); m_prevStates[0].checkRdCostZero<spt> ( decisions[0] ); @@ -1229,6 +1518,7 @@ namespace DQIntern m_prevStates[3].checkRdCostNonZero<spt> ( pqData[1], decisions[1] ); m_prevStates[3].checkRdCostNonZero<spt> ( pqData[3], decisions[3] ); m_prevStates[3].checkRdCostZero<spt> ( decisions[3] ); +#endif if( spt==SCAN_EOCSBB ) { m_skipStates[0].checkRdCostSkipSbb( decisions[0] ); @@ -1246,9 +1536,13 @@ namespace DQIntern std::swap( m_prevStates, m_currStates ); +#if JVET_L0274 + xDecide( scanInfo.spt, absCoeff, lastOffset(scanInfo.scanIdx), decisions); +#else if ( scanInfo.socsbb ) { xDecide<SCAN_SOCSBB>( absCoeff, scanInfo.lastOffset, decisions ); } else if( scanInfo.eocsbb ) { xDecide<SCAN_EOCSBB>( absCoeff, scanInfo.lastOffset, decisions ); } else { xDecide<SCAN_ISCSBB>( absCoeff, scanInfo.lastOffset, decisions ); } +#endif if( scanInfo.scanIdx ) { @@ -1303,7 +1597,11 @@ namespace DQIntern } } +#if JVET_L0274 + if( scanInfo.spt == SCAN_SOCSBB ) +#else if( scanInfo.socsbb ) +#endif { std::swap( m_prevStates, m_skipStates ); } @@ -1313,6 +1611,10 @@ namespace DQIntern void DepQuant::quant( TransformUnit& tu, const CCoeffBuf& srcCoeff, const ComponentID compID, const QpParam& cQP, const double lambda, const Ctx& ctx, TCoeff& absSum ) { +#if JVET_L0274 + CHECKD( tu.cs->sps->getSpsRangeExtension().getExtendedPrecisionProcessingFlag(), "ext precision is not supported" ); +#endif + //===== reset / pre-init ===== RateEstimator::initBlock ( tu, compID ); m_quant.initQuantBlock ( tu, compID, cQP, lambda ); diff --git a/source/Lib/CommonLib/QuantRDOQ.cpp b/source/Lib/CommonLib/QuantRDOQ.cpp index bae190c97..9105165a1 100644 --- a/source/Lib/CommonLib/QuantRDOQ.cpp +++ b/source/Lib/CommonLib/QuantRDOQ.cpp @@ -112,6 +112,11 @@ inline uint32_t QuantRDOQ::xGetCodedLevel( double& rd64CodedCost, const BinFracBits& fracBitsPar, const BinFracBits& fracBitsGt1, const BinFracBits& fracBitsGt2, +#if JVET_L0274 + const int remGt2Bins, + const int remRegBins, + unsigned goRiceZero, +#endif uint16_t ui16AbsGoRice, int iQBits, double errorScale, @@ -146,7 +151,11 @@ inline uint32_t QuantRDOQ::xGetCodedLevel( double& rd64CodedCost, for( int uiAbsLevel = uiMaxAbsLevel; uiAbsLevel >= uiMinAbsLevel ; uiAbsLevel-- ) { double dErr = double( lLevelDouble - ( Intermediate_Int(uiAbsLevel) << iQBits ) ); +#if JVET_L0274 + double dCurrCost = dErr * dErr * errorScale + xGetICost( xGetICRate( uiAbsLevel, fracBitsPar, fracBitsGt1, fracBitsGt2, remGt2Bins, remRegBins, goRiceZero, ui16AbsGoRice, useLimitedPrefixLength, maxLog2TrDynamicRange ) ); +#else double dCurrCost = dErr * dErr * errorScale + xGetICost( xGetICRate( uiAbsLevel, fracBitsPar, fracBitsGt1, fracBitsGt2, ui16AbsGoRice, useLimitedPrefixLength, maxLog2TrDynamicRange ) ); +#endif dCurrCost += dCurrCostSig; if( dCurrCost < rd64CodedCost ) @@ -175,15 +184,68 @@ inline int QuantRDOQ::xGetICRate( const uint32_t uiAbsLevel, const BinFracBits& fracBitsPar, const BinFracBits& fracBitsGt1, const BinFracBits& fracBitsGt2, +#if JVET_L0274 + const int remGt2Bins, + const int remRegBins, + unsigned goRiceZero, +#endif const uint16_t ui16AbsGoRice, const bool useLimitedPrefixLength, const int maxLog2TrDynamicRange ) const { +#if JVET_L0274 + if( remRegBins < 3 ) + { + int iRate = int( xGetIEPRate() ); // cost of sign bit + uint32_t symbol = ( uiAbsLevel == 0 ? goRiceZero : uiAbsLevel <= goRiceZero ? uiAbsLevel-1 : uiAbsLevel ); + uint32_t length; + const int threshold = g_auiGoRiceRange[ui16AbsGoRice]; + if( symbol < ( threshold << ui16AbsGoRice ) ) + { + length = symbol >> ui16AbsGoRice; + iRate += ( length + 1 + ui16AbsGoRice ) << SCALE_BITS; + } + else if( useLimitedPrefixLength ) + { + const uint32_t maximumPrefixLength = ( 32 - ( COEF_REMAIN_BIN_REDUCTION + maxLog2TrDynamicRange ) ); + + uint32_t prefixLength = 0; + uint32_t suffix = ( symbol >> ui16AbsGoRice ) - COEF_REMAIN_BIN_REDUCTION; + + while( ( prefixLength < maximumPrefixLength ) && ( suffix > ( ( 2 << prefixLength ) - 2 ) ) ) + { + prefixLength++; + } + + const uint32_t suffixLength = ( prefixLength == maximumPrefixLength ) ? ( maxLog2TrDynamicRange - ui16AbsGoRice ) : ( prefixLength + 1/*separator*/ ); + + iRate += ( COEF_REMAIN_BIN_REDUCTION + prefixLength + suffixLength + ui16AbsGoRice ) << SCALE_BITS; + } + else + { + length = ui16AbsGoRice; + symbol = symbol - ( threshold << ui16AbsGoRice ); + while( symbol >= ( 1 << length ) ) + { + symbol -= ( 1 << ( length++ ) ); + } + iRate += ( threshold + length + 1 - ui16AbsGoRice + length ) << SCALE_BITS; + } + return iRate; + } + + int iRate = int( xGetIEPRate() ); // cost of sign bit + const uint32_t cthres = ( remGt2Bins ? 4 : 2 ); + if( uiAbsLevel >= cthres ) + { + uint32_t symbol = ( uiAbsLevel - cthres ) >> 1; +#else int iRate = int( xGetIEPRate() ); // cost of sign bit if( uiAbsLevel >= 5 ) { uint32_t symbol = ( uiAbsLevel - 5 ) >> 1; +#endif uint32_t length; const int threshold = g_auiGoRiceRange[ui16AbsGoRice]; if( symbol < ( threshold << ui16AbsGoRice ) ) @@ -218,32 +280,60 @@ inline int QuantRDOQ::xGetICRate( const uint32_t uiAbsLevel, iRate += ( threshold + length + 1 - ui16AbsGoRice + length ) << SCALE_BITS; } +#if JVET_L0274 + iRate += fracBitsGt1.intBits[1]; + iRate += fracBitsPar.intBits[( uiAbsLevel - 2 ) & 1]; + if( remGt2Bins ) + { + iRate += fracBitsGt2.intBits[1]; + } +#else iRate += fracBitsPar.intBits[( uiAbsLevel - 1 ) & 1]; iRate += fracBitsGt1.intBits[1]; iRate += fracBitsGt2.intBits[1]; +#endif } else if( uiAbsLevel == 1 ) { +#if JVET_L0274 + iRate += fracBitsGt1.intBits[0]; +#else iRate += fracBitsPar.intBits[0]; iRate += fracBitsGt1.intBits[0]; +#endif } else if( uiAbsLevel == 2 ) { +#if JVET_L0274 + iRate += fracBitsGt1.intBits[1]; + iRate += fracBitsPar.intBits[0]; + iRate += fracBitsGt2.intBits[0]; +#else iRate += fracBitsPar.intBits[1]; iRate += fracBitsGt1.intBits[0]; +#endif } else if( uiAbsLevel == 3 ) { +#if JVET_L0274 + iRate += fracBitsGt1.intBits[1]; + iRate += fracBitsPar.intBits[1]; + iRate += fracBitsGt2.intBits[0]; +#else iRate += fracBitsPar.intBits[0]; iRate += fracBitsGt1.intBits[1]; iRate += fracBitsGt2.intBits[0]; +#endif } +#if JVET_L0274 +#else else if( uiAbsLevel == 4 ) { iRate += fracBitsPar.intBits[1]; iRate += fracBitsGt1.intBits[1]; iRate += fracBitsGt2.intBits[0]; } +#endif else { iRate = 0; @@ -641,6 +731,12 @@ void QuantRDOQ::xRateDistOptQuant(TransformUnit &tu, const ComponentID &compID, double d64BaseCost = 0; int iLastScanPos = -1; +#if JVET_L0274 + bool is2x2subblock = ( iCGSizeM1 == 3 ); + int remGt2Bins = ( is2x2subblock ? MAX_NUM_GT2_BINS_2x2SUBBLOCK : MAX_NUM_GT2_BINS_4x4SUBBLOCK ); + int remRegBins = ( is2x2subblock ? MAX_NUM_REG_BINS_2x2SUBBLOCK : MAX_NUM_REG_BINS_4x4SUBBLOCK ) - remGt2Bins; + uint32_t goRiceParam = 0; +#endif double *pdCostCoeffGroupSig = m_pdCostCoeffGroupSig; memset( pdCostCoeffGroupSig, 0, ( uiMaxNumCoeff >> cctx.log2CGSize() ) * sizeof( double ) ); @@ -714,7 +810,17 @@ void QuantRDOQ::xRateDistOptQuant(TransformUnit &tu, const ComponentID &compID, uint32_t uiParCtx = cctx.parityCtxIdAbs ( ctxOffset ); uint32_t uiGt1Ctx = cctx.greater1CtxIdAbs ( ctxOffset ); uint32_t uiGt2Ctx = cctx.greater2CtxIdAbs ( ctxOffset ); +#if JVET_L0274 + uint32_t goRiceZero = 0; + if( remRegBins < 3 ) + { + unsigned sumAbs = cctx.templateAbsSum( iScanPos, piDstCoeff ); + goRiceParam = g_auiGoRiceParsCoeff [ sumAbs ]; + goRiceZero = g_auiGoRicePosCoeff0[0][ sumAbs ]; + } +#else uint32_t uiGoRiceParam = cctx.GoRiceParAbs ( iScanPos, piDstCoeff ); +#endif const BinFracBits fracBitsPar = fracBits.getFracBitsArray( uiParCtx ); const BinFracBits fracBitsGt1 = fracBits.getFracBitsArray( uiGt1Ctx ); @@ -722,18 +828,31 @@ void QuantRDOQ::xRateDistOptQuant(TransformUnit &tu, const ComponentID &compID, if( iScanPos == iLastScanPos ) { +#if JVET_L0274 + uiLevel = xGetCodedLevel( pdCostCoeff[ iScanPos ], pdCostCoeff0[ iScanPos ], pdCostSig[ iScanPos ], + lLevelDouble, uiMaxAbsLevel, nullptr, fracBitsPar, fracBitsGt1, fracBitsGt2, remGt2Bins, remRegBins, goRiceZero, goRiceParam, iQBits, errorScale, 1, extendedPrecision, maxLog2TrDynamicRange ); +#else uiLevel = xGetCodedLevel( pdCostCoeff[ iScanPos ], pdCostCoeff0[ iScanPos ], pdCostSig[ iScanPos ], lLevelDouble, uiMaxAbsLevel, nullptr, fracBitsPar, fracBitsGt1, fracBitsGt2, uiGoRiceParam, iQBits, errorScale, 1, extendedPrecision, maxLog2TrDynamicRange ); +#endif } else { DTRACE_COND( ( uiMaxAbsLevel != 0 ), g_trace_ctx, D_RDOQ_MORE, " uiCtxSig=%d", ctxIdSig ); const BinFracBits fracBitsSig = fracBits.getFracBitsArray( ctxIdSig ); +#if JVET_L0274 + uiLevel = xGetCodedLevel( pdCostCoeff[ iScanPos ], pdCostCoeff0[ iScanPos ], pdCostSig[ iScanPos ], + lLevelDouble, uiMaxAbsLevel, &fracBitsSig, fracBitsPar, fracBitsGt1, fracBitsGt2, remGt2Bins, remRegBins, goRiceZero, goRiceParam, iQBits, errorScale, 0, extendedPrecision, maxLog2TrDynamicRange ); +#if HEVC_USE_SIGN_HIDING + sigRateDelta[ uiBlkPos ] = ( remRegBins < 3 ? 0 : fracBitsSig.intBits[1] - fracBitsSig.intBits[0] ); +#endif +#else uiLevel = xGetCodedLevel( pdCostCoeff[ iScanPos ], pdCostCoeff0[ iScanPos ], pdCostSig[ iScanPos ], lLevelDouble, uiMaxAbsLevel, &fracBitsSig, fracBitsPar, fracBitsGt1, fracBitsGt2, uiGoRiceParam, iQBits, errorScale, 0, extendedPrecision, maxLog2TrDynamicRange ); #if HEVC_USE_SIGN_HIDING sigRateDelta[ uiBlkPos ] = fracBitsSig.intBits[1] - fracBitsSig.intBits[0]; +#endif #endif } @@ -746,18 +865,57 @@ void QuantRDOQ::xRateDistOptQuant(TransformUnit &tu, const ComponentID &compID, if( uiLevel > 0 ) { +#if JVET_L0274 + int rateNow = xGetICRate( uiLevel, fracBitsPar, fracBitsGt1, fracBitsGt2, remGt2Bins, remRegBins, goRiceZero, goRiceParam, extendedPrecision, maxLog2TrDynamicRange ); + rateIncUp [ uiBlkPos ] = xGetICRate( uiLevel+1, fracBitsPar, fracBitsGt1, fracBitsGt2, remGt2Bins, remRegBins, goRiceZero, goRiceParam, extendedPrecision, maxLog2TrDynamicRange ) - rateNow; + rateIncDown [ uiBlkPos ] = xGetICRate( uiLevel-1, fracBitsPar, fracBitsGt1, fracBitsGt2, remGt2Bins, remRegBins, goRiceZero, goRiceParam, extendedPrecision, maxLog2TrDynamicRange ) - rateNow; +#else int rateNow = xGetICRate( uiLevel, fracBitsPar, fracBitsGt1, fracBitsGt2, uiGoRiceParam, extendedPrecision, maxLog2TrDynamicRange ); rateIncUp [ uiBlkPos ] = xGetICRate( uiLevel+1, fracBitsPar, fracBitsGt1, fracBitsGt2, uiGoRiceParam, extendedPrecision, maxLog2TrDynamicRange ) - rateNow; rateIncDown [ uiBlkPos ] = xGetICRate( uiLevel-1, fracBitsPar, fracBitsGt1, fracBitsGt2, uiGoRiceParam, extendedPrecision, maxLog2TrDynamicRange ) - rateNow; +#endif } else // uiLevel == 0 { +#if JVET_L0274 + if( remRegBins < 3 ) + { + int rateNow = xGetICRate( uiLevel, fracBitsPar, fracBitsGt1, fracBitsGt2, remGt2Bins, remRegBins, goRiceZero, goRiceParam, extendedPrecision, maxLog2TrDynamicRange ); + rateIncUp [ uiBlkPos ] = xGetICRate( uiLevel+1, fracBitsPar, fracBitsGt1, fracBitsGt2, remGt2Bins, remRegBins, goRiceZero, goRiceParam, extendedPrecision, maxLog2TrDynamicRange ) - rateNow; + } + else + { + rateIncUp [ uiBlkPos ] = fracBitsGt1.intBits[ 0 ]; + } +#else rateIncUp [ uiBlkPos ] = fracBitsPar.intBits[ 0 ] + fracBitsGt1.intBits[ 0 ]; +#endif } #endif piDstCoeff[ uiBlkPos ] = uiLevel; d64BaseCost += pdCostCoeff [ iScanPos ]; +#if JVET_L0274 + if( ( (iScanPos & iCGSizeM1) == 0 ) && ( iScanPos > 0 ) ) + { + remGt2Bins = ( is2x2subblock ? MAX_NUM_GT2_BINS_2x2SUBBLOCK : MAX_NUM_GT2_BINS_4x4SUBBLOCK ); + remRegBins = ( is2x2subblock ? MAX_NUM_REG_BINS_2x2SUBBLOCK : MAX_NUM_REG_BINS_4x4SUBBLOCK ) - remGt2Bins; + goRiceParam = 0; + } + else if( remRegBins >= 3 ) + { + const uint32_t baseLevel = ( remGt2Bins ? 4 : 2 ); + if( goRiceParam < 3 && ((uiLevel-baseLevel)>>1) > (3<<goRiceParam)-1 ) + { + goRiceParam++; + } + if( uiLevel >= 2 && remGt2Bins ) + { + remGt2Bins--; + } + remRegBins -= std::min<int>( uiLevel, 2 ) + (iScanPos != iLastScanPos); + } +#endif } else { diff --git a/source/Lib/CommonLib/QuantRDOQ.h b/source/Lib/CommonLib/QuantRDOQ.h index 71cccd5a5..e3e242ac6 100644 --- a/source/Lib/CommonLib/QuantRDOQ.h +++ b/source/Lib/CommonLib/QuantRDOQ.h @@ -91,6 +91,11 @@ private: const BinFracBits& fracBitsPar, const BinFracBits& fracBitsGt1, const BinFracBits& fracBitsGt2, +#if JVET_L0274 + const int remGt2Bins, + const int remRegBins, + unsigned goRiceZero, +#endif uint16_t ui16AbsGoRice, int iQBits, double errorScale, @@ -101,6 +106,11 @@ private: const BinFracBits& fracBitsPar, const BinFracBits& fracBitsGt1, const BinFracBits& fracBitsGt2, +#if JVET_L0274 + const int remGt2Bins, + const int remRegBins, + unsigned goRiceZero, +#endif const uint16_t ui16AbsGoRice, const bool useLimitedPrefixLength, const int maxLog2TrDynamicRange ) const; diff --git a/source/Lib/CommonLib/Rom.cpp b/source/Lib/CommonLib/Rom.cpp index e2f8ccaca..9faa20264 100644 --- a/source/Lib/CommonLib/Rom.cpp +++ b/source/Lib/CommonLib/Rom.cpp @@ -596,6 +596,18 @@ const uint32_t g_uiMinInGroup[LAST_SIGNIFICANT_GROUPS] = { 0,1,2,3,4,6,8,12,16,2 const uint32_t g_uiGroupIdx[MAX_TU_SIZE] = { 0,1,2,3,4,4,5,5,6,6,6,6,7,7,7,7,8,8,8,8,8,8,8,8,9,9,9,9,9,9,9,9, 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11 ,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12 ,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13 }; +#if JVET_L0274 +const uint32_t g_auiGoRiceParsCoeff[32] = +{ + 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3 +}; +const uint32_t g_auiGoRicePosCoeff0[3][32] = +{ + {0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 8, 8, 8, 8, 8}, + {1, 1, 1, 1, 2, 3, 4, 4, 4, 6, 6, 6, 8, 8, 8, 8, 8, 8, 12, 12, 12, 12, 12, 12, 12, 12, 16, 16, 16, 16, 16, 16}, + {1, 1, 2, 2, 2, 3, 4, 4, 4, 6, 6, 6, 8, 8, 8, 8, 8, 8, 12, 12, 12, 12, 12, 12, 12, 16, 16, 16, 16, 16, 16, 16} +}; +#else const uint32_t g_auiGoRicePars[ 32 ] = { 0, 0, 0, 0, @@ -603,6 +615,7 @@ const uint32_t g_auiGoRicePars[ 32 ] = 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2 }; +#endif const uint32_t g_auiGoRiceRange[MAX_GR_ORDER_RESIDUAL] = { 6, 5, 6, COEF_REMAIN_BIN_REDUCTION, COEF_REMAIN_BIN_REDUCTION, COEF_REMAIN_BIN_REDUCTION, COEF_REMAIN_BIN_REDUCTION, COEF_REMAIN_BIN_REDUCTION, COEF_REMAIN_BIN_REDUCTION, COEF_REMAIN_BIN_REDUCTION diff --git a/source/Lib/CommonLib/Rom.h b/source/Lib/CommonLib/Rom.h index e8c0c5acb..2087f54d4 100644 --- a/source/Lib/CommonLib/Rom.h +++ b/source/Lib/CommonLib/Rom.h @@ -90,7 +90,12 @@ extern const uint32_t ctxIndMap4x4[4*4]; extern const uint32_t g_uiGroupIdx[ MAX_TU_SIZE ]; extern const uint32_t g_uiMinInGroup[ LAST_SIGNIFICANT_GROUPS ]; +#if JVET_L0274 +extern const uint32_t g_auiGoRiceParsCoeff [ 32 ]; +extern const uint32_t g_auiGoRicePosCoeff0[ 3 ][ 32 ]; +#else extern const uint32_t g_auiGoRicePars [ 32 ]; +#endif extern const uint32_t g_auiGoRiceRange[ MAX_GR_ORDER_RESIDUAL ]; //!< maximum value coded with Rice codes // ==================================================================================================================== diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h index 167b00da9..3d5996b0f 100644 --- a/source/Lib/CommonLib/TypeDef.h +++ b/source/Lib/CommonLib/TypeDef.h @@ -60,6 +60,8 @@ #define JVET_L0194_ONE_CTX_FOR_MRG_IDX 1 // one context for full-block Merge index +#define JVET_L0274 1 + #define REUSE_CU_RESULTS 1 #define REMOVE_MV_ADAPT_PREC 1 // remove the high precision flag in the MV class diff --git a/source/Lib/DecoderLib/CABACReader.cpp b/source/Lib/DecoderLib/CABACReader.cpp index 7886c7b18..8a251b897 100644 --- a/source/Lib/DecoderLib/CABACReader.cpp +++ b/source/Lib/DecoderLib/CABACReader.cpp @@ -2161,7 +2161,10 @@ void CABACReader::residual_coding_subblock( CoeffCodingContext& cctx, TCoeff* co } uint8_t ctxOffset[16]; +#if JVET_L0274 +#else unsigned nextPass = 0; +#endif //===== decode absolute values ===== const int inferSigPos = nextSigPos != cctx.scanPosLast() ? ( cctx.isNotFirst() ? minSubPos : -1 ) : nextSigPos; @@ -2170,9 +2173,20 @@ void CABACReader::residual_coding_subblock( CoeffCodingContext& cctx, TCoeff* co int lastNZPos = -1; #endif int numNonZero = 0; +#if JVET_L0274 + bool is2x2subblock = ( cctx.log2CGSize() == 2 ); + int remGt2Bins = ( is2x2subblock ? MAX_NUM_GT2_BINS_2x2SUBBLOCK : MAX_NUM_GT2_BINS_4x4SUBBLOCK ); + int remRegBins = ( is2x2subblock ? MAX_NUM_REG_BINS_2x2SUBBLOCK : MAX_NUM_REG_BINS_4x4SUBBLOCK ) - remGt2Bins; + int firstPosMode2 = minSubPos - 1; + int firstPosMode1 = minSubPos - 1; +#endif int sigBlkPos[ 1 << MLS_CG_SIZE ]; +#if JVET_L0274 + for( ; nextSigPos >= minSubPos && remRegBins >= 3; nextSigPos-- ) +#else for( ; nextSigPos >= minSubPos; nextSigPos-- ) +#endif { int blkPos = cctx.blockPos( nextSigPos ); unsigned sigFlag = ( !numNonZero && nextSigPos == inferSigPos ); @@ -2182,6 +2196,9 @@ void CABACReader::residual_coding_subblock( CoeffCodingContext& cctx, TCoeff* co const unsigned sigCtxId = cctx.sigCtxIdAbs( nextSigPos, coeff, state ); sigFlag = m_BinDecoder.decodeBin( sigCtxId ); DTRACE( g_trace_ctx, D_SYNTAX_RESI, "sig_bin() bin=%d ctx=%d\n", sigFlag, sigCtxId ); +#if JVET_L0274 + remRegBins--; +#endif } if( sigFlag ) @@ -2194,6 +2211,27 @@ void CABACReader::residual_coding_subblock( CoeffCodingContext& cctx, TCoeff* co lastNZPos = std::max<int>( lastNZPos, nextSigPos ); #endif +#if JVET_L0274 + RExt__DECODER_DEBUG_BIT_STATISTICS_SET( ctype_gt1 ); + unsigned gt1Flag = m_BinDecoder.decodeBin( cctx.greater1CtxIdAbs(ctxOff) ); + DTRACE( g_trace_ctx, D_SYNTAX_RESI, "gt1_flag() bin=%d ctx=%d\n", gt1Flag, cctx.greater1CtxIdAbs(ctxOff) ); + remRegBins--; + + unsigned parFlag = 0; + if( gt1Flag ) + { + RExt__DECODER_DEBUG_BIT_STATISTICS_SET( ctype_par ); + parFlag = m_BinDecoder.decodeBin( cctx.parityCtxIdAbs( ctxOff ) ); + DTRACE( g_trace_ctx, D_SYNTAX_RESI, "par_flag() bin=%d ctx=%d\n", parFlag, cctx.parityCtxIdAbs( ctxOff ) ); + + remRegBins--; + if( remGt2Bins && !--remGt2Bins ) + { + firstPosMode1 = nextSigPos - 1; + } + } + coeff[ blkPos ] += 1 + parFlag + gt1Flag; +#else RExt__DECODER_DEBUG_BIT_STATISTICS_SET( ctype_par ); unsigned parFlag = m_BinDecoder.decodeBin( cctx.parityCtxIdAbs(ctxOff) ); DTRACE( g_trace_ctx, D_SYNTAX_RESI, "par_flag() bin=%d ctx=%d\n", parFlag, cctx.parityCtxIdAbs(ctxOff) ); @@ -2203,11 +2241,85 @@ void CABACReader::residual_coding_subblock( CoeffCodingContext& cctx, TCoeff* co DTRACE( g_trace_ctx, D_SYNTAX_RESI, "gt1_flag() bin=%d ctx=%d\n", gt1Flag, cctx.greater1CtxIdAbs(ctxOff) ); coeff[blkPos] += 1+parFlag+(gt1Flag<<1); nextPass |= gt1Flag; +#endif } state = ( stateTransTable >> ((state<<2)+((coeff[blkPos]&1)<<1)) ) & 3; } +#if JVET_L0274 + firstPosMode2 = nextSigPos; + firstPosMode1 = ( firstPosMode1 > firstPosMode2 ? firstPosMode1 : firstPosMode2 ); +#endif +#if JVET_L0274 + //===== 2nd PASS: gt2 ===== + for( int scanPos = firstSigPos; scanPos > firstPosMode1; scanPos-- ) + { + TCoeff& tcoeff = coeff[ cctx.blockPos( scanPos ) ]; + if( tcoeff >= 2 ) + { + RExt__DECODER_DEBUG_BIT_STATISTICS_SET( ctype_gt2 ); + uint8_t& ctxOff = ctxOffset[ scanPos - minSubPos ]; + unsigned gt2Flag = m_BinDecoder.decodeBin( cctx.greater2CtxIdAbs(ctxOff) ); + DTRACE( g_trace_ctx, D_SYNTAX_RESI, "gt2_flag() bin=%d ctx=%d\n", gt2Flag, cctx.greater2CtxIdAbs(ctxOff) ); + tcoeff += (gt2Flag<<1); + } + } + + //===== 3rd PASS: Go-rice codes ===== + unsigned ricePar = 0; + for( int scanPos = firstSigPos; scanPos > firstPosMode1; scanPos-- ) + { + TCoeff& tcoeff = coeff[ cctx.blockPos( scanPos ) ]; + if( tcoeff >= 4 ) + { + RExt__DECODER_DEBUG_BIT_STATISTICS_SET( ctype_escs ); + int rem = m_BinDecoder.decodeRemAbsEP( ricePar, cctx.extPrec(), cctx.maxLog2TrDRange() ); + DTRACE( g_trace_ctx, D_SYNTAX_RESI, "rem_val() bin=%d ctx=%d\n", rem, ricePar ); + tcoeff += (rem<<1); + if( ricePar < 3 && rem > (3<<ricePar)-1 ) + { + ricePar++; + } + } + } + for( int scanPos = firstPosMode1; scanPos > firstPosMode2; scanPos-- ) + { + TCoeff& tcoeff = coeff[ cctx.blockPos( scanPos ) ]; + if( tcoeff >= 2 ) + { + RExt__DECODER_DEBUG_BIT_STATISTICS_SET( ctype_escs ); + int rem = m_BinDecoder.decodeRemAbsEP( ricePar, cctx.extPrec(), cctx.maxLog2TrDRange() ); + DTRACE( g_trace_ctx, D_SYNTAX_RESI, "rem_val() bin=%d ctx=%d\n", rem, ricePar ); + tcoeff += (rem<<1); + if( ricePar < 3 && rem > (3<<ricePar)-1 ) + { + ricePar++; + } + } + } + + //===== coeff bypass ==== + for( int scanPos = firstPosMode2; scanPos >= minSubPos; scanPos-- ) + { + int sumAll = cctx.templateAbsSum(scanPos, coeff); + int rice = g_auiGoRiceParsCoeff [sumAll]; + int pos0 = g_auiGoRicePosCoeff0[std::max(0, state - 1)][sumAll]; + int rem = m_BinDecoder.decodeRemAbsEP( rice, cctx.extPrec(), cctx.maxLog2TrDRange() ); + DTRACE( g_trace_ctx, D_SYNTAX_RESI, "rem_val() bin=%d ctx=%d\n", rem, rice ); + TCoeff tcoeff = ( rem == pos0 ? 0 : rem < pos0 ? rem+1 : rem ); + state = ( stateTransTable >> ((state<<2)+((tcoeff&1)<<1)) ) & 3; + if( tcoeff ) + { + int blkPos = cctx.blockPos( scanPos ); + sigBlkPos[ numNonZero++ ] = blkPos; +#if HEVC_USE_SIGN_HIDING + lastNZPos = std::max<int>( lastNZPos, scanPos ); +#endif + coeff[blkPos] = tcoeff; + } + } +#else //===== 2nd PASS: gt2 ===== if( nextPass ) { @@ -2243,6 +2355,7 @@ void CABACReader::residual_coding_subblock( CoeffCodingContext& cctx, TCoeff* co } } } +#endif //===== decode sign's ===== RExt__DECODER_DEBUG_BIT_STATISTICS_CREATE_SET_SIZE2( STATS__CABAC_BITS__SIGN_BIT, Size( cctx.width(), cctx.height() ), cctx.compID() ); diff --git a/source/Lib/EncoderLib/CABACWriter.cpp b/source/Lib/EncoderLib/CABACWriter.cpp index c2fe809d7..c9e5c14f5 100644 --- a/source/Lib/EncoderLib/CABACWriter.cpp +++ b/source/Lib/EncoderLib/CABACWriter.cpp @@ -2063,7 +2063,10 @@ void CABACWriter::residual_coding_subblock( CoeffCodingContext& cctx, const TCoe } uint8_t ctxOffset[16]; +#if JVET_L0274 +#else unsigned nextPass = 0; +#endif //===== encode absolute values ===== const int inferSigPos = nextSigPos != cctx.scanPosLast() ? ( cctx.isNotFirst() ? minSubPos : -1 ) : nextSigPos; @@ -2074,8 +2077,19 @@ void CABACWriter::residual_coding_subblock( CoeffCodingContext& cctx, const TCoe int remAbsLevel = -1; int numNonZero = 0; unsigned signPattern = 0; +#if JVET_L0274 + bool is2x2subblock = ( cctx.log2CGSize() == 2 ); + int remGt2Bins = ( is2x2subblock ? MAX_NUM_GT2_BINS_2x2SUBBLOCK : MAX_NUM_GT2_BINS_4x4SUBBLOCK ); + int remRegBins = ( is2x2subblock ? MAX_NUM_REG_BINS_2x2SUBBLOCK : MAX_NUM_REG_BINS_4x4SUBBLOCK ) - remGt2Bins; + int firstPosMode2 = minSubPos - 1; + int firstPosMode1 = minSubPos - 1; +#endif +#if JVET_L0274 + for( ; nextSigPos >= minSubPos && remRegBins >= 3; nextSigPos-- ) +#else for( ; nextSigPos >= minSubPos; nextSigPos-- ) +#endif { TCoeff Coeff = coeff[ cctx.blockPos( nextSigPos ) ]; unsigned sigFlag = ( Coeff != 0 ); @@ -2084,6 +2098,9 @@ void CABACWriter::residual_coding_subblock( CoeffCodingContext& cctx, const TCoe const unsigned sigCtxId = cctx.sigCtxIdAbs( nextSigPos, coeff, state ); m_BinEncoder.encodeBin( sigFlag, sigCtxId ); DTRACE( g_trace_ctx, D_SYNTAX_RESI, "sig_bin() bin=%d ctx=%d\n", sigFlag, sigCtxId ); +#if JVET_L0274 + remRegBins--; +#endif } if( sigFlag ) @@ -2100,6 +2117,26 @@ void CABACWriter::residual_coding_subblock( CoeffCodingContext& cctx, const TCoe if( nextSigPos != cctx.scanPosLast() ) signPattern <<= 1; if( Coeff < 0 ) signPattern++; +#if JVET_L0274 + unsigned gt1 = !!remAbsLevel; + m_BinEncoder.encodeBin( gt1, cctx.greater1CtxIdAbs(ctxOff) ); + DTRACE( g_trace_ctx, D_SYNTAX_RESI, "gt1_flag() bin=%d ctx=%d\n", gt1, cctx.greater1CtxIdAbs(ctxOff) ); + remRegBins--; + + if( gt1 ) + { + remAbsLevel -= 1; + m_BinEncoder.encodeBin( remAbsLevel&1, cctx.parityCtxIdAbs( ctxOff ) ); + DTRACE( g_trace_ctx, D_SYNTAX_RESI, "par_flag() bin=%d ctx=%d\n", remAbsLevel&1, cctx.parityCtxIdAbs( ctxOff ) ); + remAbsLevel >>= 1; + + remRegBins--; + if( remGt2Bins && !--remGt2Bins ) + { + firstPosMode1 = nextSigPos - 1; + } + } +#else m_BinEncoder.encodeBin( remAbsLevel&1, cctx.parityCtxIdAbs(ctxOff) ); DTRACE( g_trace_ctx, D_SYNTAX_RESI, "par_flag() bin=%d ctx=%d\n", remAbsLevel&1, cctx.parityCtxIdAbs(ctxOff) ); remAbsLevel >>= 1; @@ -2108,12 +2145,85 @@ void CABACWriter::residual_coding_subblock( CoeffCodingContext& cctx, const TCoe m_BinEncoder.encodeBin( gt1, cctx.greater1CtxIdAbs(ctxOff) ); DTRACE( g_trace_ctx, D_SYNTAX_RESI, "gt1_flag() bin=%d ctx=%d\n", gt1, cctx.greater1CtxIdAbs(ctxOff) ); nextPass |= gt1; +#endif } state = ( stateTransTable >> ((state<<2)+((Coeff&1)<<1)) ) & 3; } +#if JVET_L0274 + firstPosMode2 = nextSigPos; + firstPosMode1 = ( firstPosMode1 > firstPosMode2 ? firstPosMode1 : firstPosMode2 ); +#endif +#if JVET_L0274 + //===== 2nd PASS: gt2 ===== + for( int scanPos = firstSigPos; scanPos > firstPosMode1; scanPos-- ) + { + unsigned absLevel = abs( coeff[ cctx.blockPos( scanPos ) ] ); + if( absLevel >= 2 ) + { + uint8_t& ctxOff = ctxOffset[ scanPos - minSubPos ]; + unsigned gt2 = ( absLevel >= 4 ); + m_BinEncoder.encodeBin( gt2, cctx.greater2CtxIdAbs(ctxOff) ); + DTRACE( g_trace_ctx, D_SYNTAX_RESI, "gt2_flag() bin=%d ctx=%d\n", gt2, cctx.greater2CtxIdAbs(ctxOff) ); + } + } + + //===== 3rd PASS: Go-rice codes ===== + unsigned ricePar = 0; + for( int scanPos = firstSigPos; scanPos > firstPosMode1; scanPos-- ) + { + unsigned absLevel = abs( coeff[ cctx.blockPos( scanPos ) ] ); + if( absLevel >= 4 ) + { + unsigned rem = ( absLevel - 4 ) >> 1; + m_BinEncoder.encodeRemAbsEP( rem, ricePar, cctx.extPrec(), cctx.maxLog2TrDRange() ); + DTRACE( g_trace_ctx, D_SYNTAX_RESI, "rem_val() bin=%d ctx=%d\n", rem, ricePar ); + if( ricePar < 3 && rem > (3<<ricePar)-1 ) + { + ricePar++; + } + } + } + for( int scanPos = firstPosMode1; scanPos > firstPosMode2; scanPos-- ) + { + unsigned absLevel = abs( coeff[ cctx.blockPos( scanPos ) ] ); + if( absLevel >= 2 ) + { + unsigned rem = ( absLevel - 2 ) >> 1; + m_BinEncoder.encodeRemAbsEP( rem, ricePar, cctx.extPrec(), cctx.maxLog2TrDRange() ); + DTRACE( g_trace_ctx, D_SYNTAX_RESI, "rem_val() bin=%d ctx=%d\n", rem, ricePar ); + if( ricePar < 3 && rem > (3<<ricePar)-1 ) + { + ricePar++; + } + } + } + + //===== coeff bypass ==== + for( int scanPos = firstPosMode2; scanPos >= minSubPos; scanPos-- ) + { + TCoeff Coeff = coeff[ cctx.blockPos( scanPos ) ]; + unsigned absLevel = abs( Coeff ); + int sumAll = cctx.templateAbsSum(scanPos, coeff); + int rice = g_auiGoRiceParsCoeff [sumAll]; + int pos0 = g_auiGoRicePosCoeff0[std::max(0, state - 1)][sumAll]; + unsigned rem = ( absLevel == 0 ? pos0 : absLevel <= pos0 ? absLevel-1 : absLevel ); + m_BinEncoder.encodeRemAbsEP( rem, rice, cctx.extPrec(), cctx.maxLog2TrDRange() ); + DTRACE( g_trace_ctx, D_SYNTAX_RESI, "rem_val() bin=%d ctx=%d\n", rem, rice ); + state = ( stateTransTable >> ((state<<2)+((absLevel&1)<<1)) ) & 3; + if( absLevel ) + { + numNonZero++; +#if HEVC_USE_SIGN_HIDING + lastNZPos = std::max<int>( lastNZPos, scanPos ); +#endif + signPattern <<= 1; + if( Coeff < 0 ) signPattern++; + } + } +#else //===== 2nd PASS: gt2 ===== if( nextPass ) { @@ -2147,6 +2257,7 @@ void CABACWriter::residual_coding_subblock( CoeffCodingContext& cctx, const TCoe } } } +#endif //===== encode sign's ===== #if HEVC_USE_SIGN_HIDING -- GitLab