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