Skip to content
Snippets Groups Projects
CABACWriter.cpp 139 KiB
Newer Older
  • Learn to ignore specific revisions
  • Xiang Li's avatar
    Xiang Li committed
          CHECK( (horMvd % 4) != 0 && (verMvd % 4) != 0, "IMV: MVD is not a multiple of 16" );
    
      }
      unsigned  horAbs  = unsigned( horMvd < 0 ? -horMvd : horMvd );
      unsigned  verAbs  = unsigned( verMvd < 0 ? -verMvd : verMvd );
    
    
      // abs_mvd_greater0_flag[ 0 | 1 ]
      m_BinEncoder.encodeBin( (horAbs > 0), Ctx::Mvd() );
      m_BinEncoder.encodeBin( (verAbs > 0), Ctx::Mvd() );
    
      // abs_mvd_greater1_flag[ 0 | 1 ]
      if( horAbs > 0 )
      {
        m_BinEncoder.encodeBin( (horAbs > 1), Ctx::Mvd(1) );
      }
      if( verAbs > 0 )
      {
        m_BinEncoder.encodeBin( (verAbs > 1), Ctx::Mvd(1) );
      }
    
      // abs_mvd_minus2[ 0 | 1 ] and mvd_sign_flag[ 0 | 1 ]
      if( horAbs > 0 )
      {
        if( horAbs > 1 )
        {
          exp_golomb_eqprob( horAbs - 2, 1 );
        }
        m_BinEncoder.encodeBinEP( (horMvd < 0) );
      }
      if( verAbs > 0 )
      {
        if( verAbs > 1 )
        {
          exp_golomb_eqprob( verAbs - 2, 1 );
        }
        m_BinEncoder.encodeBinEP( (verMvd < 0) );
      }
    }
    
    
    
    
    //================================================================================
    //  clause 7.3.8.10
    //--------------------------------------------------------------------------------
    //    void  transform_unit      ( tu, cuCtx, chromaCbfs )
    //    void  cu_qp_delta         ( cu )
    //    void  cu_chroma_qp_offset ( cu )
    //================================================================================
    
    #if JVET_O0596_CBF_SIG_ALIGN_TO_SPEC
    void CABACWriter::transform_unit( const TransformUnit& tu, CUCtx& cuCtx, Partitioner& partitioner, const int subTuCounter)
    #else
    
    void CABACWriter::transform_unit( const TransformUnit& tu, CUCtx& cuCtx, ChromaCbfs& chromaCbfs )
    
    #if JVET_O0596_CBF_SIG_ALIGN_TO_SPEC
      const CodingStructure&  cs = *tu.cs;
      const CodingUnit&       cu = *tu.cu;
      const UnitArea&         area = partitioner.currArea();
      const unsigned          trDepth = partitioner.currTrDepth;
      const bool              chromaCbfISP = area.blocks[COMPONENT_Cb].valid() && cu.ispMode;
      ChromaCbfs              chromaCbfs;
      CHECK(tu.depth != trDepth, " transform unit should be not be futher partitioned");
    
      // cbf_cb & cbf_cr
    
    #if JVET_O0050_LOCAL_DUAL_TREE
      if (area.chromaFormat != CHROMA_400 && area.blocks[COMPONENT_Cb].valid() && (!cu.isSepTree() || partitioner.chType == CHANNEL_TYPE_CHROMA) && (!cu.ispMode || chromaCbfISP))
    #else
    
      if (area.chromaFormat != CHROMA_400 && area.blocks[COMPONENT_Cb].valid() && (!CS::isDualITree(cs) || partitioner.chType == CHANNEL_TYPE_CHROMA) && (!cu.ispMode || chromaCbfISP))
    
      {
        {
          unsigned cbfDepth = chromaCbfISP ? trDepth - 1 : trDepth;
          {
            chromaCbfs.Cb = TU::getCbfAtDepth(tu, COMPONENT_Cb, trDepth);
            //if (!(cu.sbtInfo && trDepth == 1))
            if (!(cu.sbtInfo && tu.noResidual))
              cbf_comp(cs, chromaCbfs.Cb, area.blocks[COMPONENT_Cb], cbfDepth);
          }
    
          {
            chromaCbfs.Cr = TU::getCbfAtDepth(tu, COMPONENT_Cr, trDepth);
            //if (!(cu.sbtInfo && trDepth == 1))
            if (!(cu.sbtInfo && tu.noResidual))
              cbf_comp(cs, chromaCbfs.Cr, area.blocks[COMPONENT_Cr], cbfDepth, chromaCbfs.Cb);
          }
        }
      }
    
    #if JVET_O0050_LOCAL_DUAL_TREE
      else if (cu.isSepTree())
    #else
    
      {
        chromaCbfs = ChromaCbfs(false);
      }
    
      if (!isChroma(partitioner.chType))
      {
        if (!CU::isIntra(cu) && trDepth == 0 && !chromaCbfs.sigChroma(area.chromaFormat))
        {
          CHECK(!TU::getCbfAtDepth(tu, COMPONENT_Y, trDepth), "Luma cbf must be true for inter units with no chroma coeffs");
        }
        else if (cu.sbtInfo && tu.noResidual)
        {
          CHECK(TU::getCbfAtDepth(tu, COMPONENT_Y, trDepth), "Luma cbf must be false for inter sbt no-residual tu");
        }
        else if (cu.sbtInfo && !chromaCbfs.sigChroma(area.chromaFormat))
        {
          assert(!tu.noResidual);
          CHECK(!TU::getCbfAtDepth(tu, COMPONENT_Y, trDepth), "Luma cbf must be true for inter sbt residual tu");
        }
        else
        {
          bool previousCbf = false;
          bool rootCbfSoFar = false;
          bool lastCbfIsInferred = false;
          if (cu.ispMode)
          {
            uint32_t nTus = cu.ispMode == HOR_INTRA_SUBPARTITIONS ? cu.lheight() >> g_aucLog2[tu.lheight()] : cu.lwidth() >> g_aucLog2[tu.lwidth()];
            if (subTuCounter == nTus - 1)
            {
              TransformUnit* tuPointer = cu.firstTU;
              for (int tuIdx = 0; tuIdx < subTuCounter; tuIdx++)
              {
                rootCbfSoFar |= TU::getCbfAtDepth(*tuPointer, COMPONENT_Y, trDepth);
                tuPointer = tuPointer->next;
              }
              if (!rootCbfSoFar)
              {
                lastCbfIsInferred = true;
              }
            }
            if (!lastCbfIsInferred)
            {
              previousCbf = TU::getPrevTuCbfAtDepth(tu, COMPONENT_Y, partitioner.currTrDepth);
            }
          }
          if (!lastCbfIsInferred)
          {
            cbf_comp(cs, TU::getCbfAtDepth(tu, COMPONENT_Y, trDepth), tu.Y(), trDepth, previousCbf, cu.ispMode);
          }
        }
      }
    #else
    
      bool        lumaOnly  = ( cu.chromaFormat == CHROMA_400 || !tu.blocks[COMPONENT_Cb].valid() );
      bool        cbf[3]    = { TU::getCbf( tu, COMPONENT_Y ), chromaCbfs.Cb, chromaCbfs.Cr };
      bool        cbfLuma   = ( cbf[ COMPONENT_Y ] != 0 );
      bool        cbfChroma = false;
    
    
      {
        if( tu.blocks[COMPONENT_Cb].valid() )
        {
          cbf   [ COMPONENT_Cb  ] = TU::getCbf( tu, COMPONENT_Cb );
          cbf   [ COMPONENT_Cr  ] = TU::getCbf( tu, COMPONENT_Cr );
        }
        cbfChroma = ( cbf[ COMPONENT_Cb ] || cbf[ COMPONENT_Cr ] );
      }
    
      if( ( cu.lwidth() > 64 || cu.lheight() > 64 || cbfLuma || cbfChroma ) &&
    
      if( ( cbfLuma || cbfChroma ) &&
    
    #if JVET_O0050_LOCAL_DUAL_TREE
    
    Yin Zhao's avatar
    Yin Zhao committed
        (!tu.cu->isSepTree() || isLuma(tu.chType)) )
    
        (!CS::isDualITree(*tu.cs) || isLuma(tu.chType)) )
    
      {
        if( cu.cs->pps->getUseDQP() && !cuCtx.isDQPCoded )
        {
    
          cu_qp_delta(cu, cuCtx.qp, cu.qp);
          cuCtx.qp = cu.qp;
          cuCtx.isDQPCoded = true;
    
    Yu Han's avatar
    Yu Han committed
    #if JVET_O1168_CU_CHROMA_QP_OFFSET
        if (cu.cs->slice->getUseChromaQpAdj() && cbfChroma && !cuCtx.isChromaQpAdjCoded)
    #else
    
        if( cu.cs->slice->getUseChromaQpAdj() && cbfChroma && !cu.transQuantBypass && !cuCtx.isChromaQpAdjCoded )
    
    Yu Han's avatar
    Yu Han committed
    #endif
    
        {
          cu_chroma_qp_offset( cu );
          cuCtx.isChromaQpAdjCoded = true;
        }
    
    
    #if JVET_O0105_ICT
      if( !lumaOnly )
      {
        joint_cb_cr( tu, ( cbf[COMPONENT_Cb] ? 2 : 0 ) + ( cbf[COMPONENT_Cr] ? 1 : 0 ) );
      }
    #endif
    
    
    #if JVET_O0094_LFNST_ZERO_PRIM_COEFFS || JVET_O0472_LFNST_SIGNALLING_LAST_SCAN_POS
    
    Mischa Siekmann's avatar
    Mischa Siekmann committed
          residual_coding( tu, COMPONENT_Y, &cuCtx );
    #else
    
    Mischa Siekmann's avatar
    Mischa Siekmann committed
    #endif
    
        }
        if( !lumaOnly )
        {
          for( ComponentID compID = COMPONENT_Cb; compID <= COMPONENT_Cr; compID = ComponentID( compID + 1 ) )
          {
            if( TU::hasCrossCompPredInfo( tu, compID ) )
            {
              cross_comp_pred( tu, compID );
            }
            if( cbf[ compID ] )
            {
    
    #if JVET_O0094_LFNST_ZERO_PRIM_COEFFS || JVET_O0472_LFNST_SIGNALLING_LAST_SCAN_POS
    
    Mischa Siekmann's avatar
    Mischa Siekmann committed
              residual_coding( tu, compID, &cuCtx );
    #else
    
    Mischa Siekmann's avatar
    Mischa Siekmann committed
    #endif
    
          }
        }
      }
    }
    
    void CABACWriter::cu_qp_delta( const CodingUnit& cu, int predQP, const int8_t qp )
    {
      CHECK(!( predQP != std::numeric_limits<int>::max()), "Unspecified error");
      int       DQp         = qp - predQP;
      int       qpBdOffsetY = cu.cs->sps->getQpBDOffset( CHANNEL_TYPE_LUMA );
      DQp                   = ( DQp + (MAX_QP + 1) + (MAX_QP + 1) / 2 + qpBdOffsetY + (qpBdOffsetY / 2)) % ((MAX_QP + 1) + qpBdOffsetY) - (MAX_QP + 1) / 2 - (qpBdOffsetY / 2);
      unsigned  absDQP      = unsigned( DQp < 0 ? -DQp : DQp );
      unsigned  unaryDQP    = std::min<unsigned>( absDQP, CU_DQP_TU_CMAX );
    
      unary_max_symbol( unaryDQP, Ctx::DeltaQP(), Ctx::DeltaQP(1), CU_DQP_TU_CMAX );
      if( absDQP >= CU_DQP_TU_CMAX )
      {
        exp_golomb_eqprob( absDQP - CU_DQP_TU_CMAX, CU_DQP_EG_k );
      }
      if( absDQP > 0 )
      {
        m_BinEncoder.encodeBinEP( DQp < 0 );
      }
    
      DTRACE_COND( ( isEncoding() ), g_trace_ctx, D_DQP, "x=%d, y=%d, d=%d, pred_qp=%d, DQp=%d, qp=%d\n", cu.blocks[cu.chType].lumaPos().x, cu.blocks[cu.chType].lumaPos().y, cu.qtDepth, predQP, DQp, qp );
    }
    
    
    void CABACWriter::cu_chroma_qp_offset( const CodingUnit& cu )
    {
      // cu_chroma_qp_offset_flag
      unsigned qpAdj = cu.chromaQpAdj;
      if( qpAdj == 0 )
      {
        m_BinEncoder.encodeBin( 0, Ctx::ChromaQpAdjFlag() );
      }
      else
      {
        m_BinEncoder.encodeBin( 1, Ctx::ChromaQpAdjFlag() );
        int length = cu.cs->pps->getPpsRangeExtension().getChromaQpOffsetListLen();
        if( length > 1 )
        {
          unary_max_symbol( qpAdj-1, Ctx::ChromaQpAdjIdc(), Ctx::ChromaQpAdjIdc(), length-1 );
        }
      }
    }
    
    
    
    
    
    //================================================================================
    //  clause 7.3.8.11
    //--------------------------------------------------------------------------------
    //    void        residual_coding         ( tu, compID )
    //    void        transform_skip_flag     ( tu, compID )
    //    void        explicit_rdpcm_mode     ( tu, compID )
    //    void        last_sig_coeff          ( coeffCtx )
    //    void        residual_coding_subblock( coeffCtx )
    //================================================================================
    
    
    #if JVET_O0105_ICT
    void CABACWriter::joint_cb_cr( const TransformUnit& tu, const int cbfMask )
    {
    
    #if JVET_O0376_SPS_JOINTCBCR_FLAG
      if ( !tu.cu->slice->getSPS()->getJointCbCrEnabledFlag() )
    
      CHECK( tu.jointCbCr && tu.jointCbCr != cbfMask, "wrong value of jointCbCr (" << (int)tu.jointCbCr << " vs " << (int)cbfMask << ")" );
    #if JVET_O0543_ICT_ICU_ONLY
      if( ( CU::isIntra( *tu.cu ) && cbfMask ) || ( cbfMask == 3 ) )
    #else
      if( cbfMask )
    #endif
      {
        m_BinEncoder.encodeBin( tu.jointCbCr ? 1 : 0, Ctx::JointCbCrFlag( cbfMask - 1 ) );
      }
    }
    #else
    
    void CABACWriter::joint_cb_cr( const TransformUnit& tu )
    {
      m_BinEncoder.encodeBin( tu.jointCbCr ? 1 : 0, Ctx::JointCbCrFlag( 0 ) );
    }
    
    #if JVET_O0094_LFNST_ZERO_PRIM_COEFFS || JVET_O0472_LFNST_SIGNALLING_LAST_SCAN_POS
    
    Mischa Siekmann's avatar
    Mischa Siekmann committed
    void CABACWriter::residual_coding( const TransformUnit& tu, ComponentID compID, CUCtx* cuCtx )
    #else
    void CABACWriter::residual_coding( const TransformUnit& tu, ComponentID compID)
    #endif
    
    {
      const CodingUnit& cu = *tu.cu;
      DTRACE( g_trace_ctx, D_SYNTAX, "residual_coding() etype=%d pos=(%d,%d) size=%dx%d predMode=%d\n", tu.blocks[compID].compID, tu.blocks[compID].x, tu.blocks[compID].y, tu.blocks[compID].width, tu.blocks[compID].height, cu.predMode );
    
    
    #if JVET_O0105_ICT
      if( compID == COMPONENT_Cr && tu.jointCbCr == 3 )
        return;
    #else
    
      // Joint Cb-Cr residual mode is signalled if both Cb and Cr cbfs are true
    
      if ( compID == COMPONENT_Cr && TU::getCbf( tu, COMPONENT_Cb ) )
      {
        joint_cb_cr( tu );
    
        // No Cr residual in bitstream in joint Cb-Cr residual mode
        if ( tu.jointCbCr )
          return;
      }
    
      // code transform skip and explicit rdpcm mode
    
    Tung Nguyen's avatar
    Tung Nguyen committed
      mts_coding         ( tu, compID );
    
      if( isLuma( compID ) && ( tu.mtsIdx == MTS_SKIP || tu.cu->bdpcmMode ) )
    
      {
        residual_codingTS( tu, compID );
        return;
      }
    
    
      // determine sign hiding
      bool signHiding  = ( cu.cs->slice->getSignDataHidingEnabledFlag() && !cu.transQuantBypass && tu.rdpcm[compID] == RDPCM_OFF );
    
      if(  signHiding && CU::isIntra(cu) && CU::isRDPCMEnabled(cu) && tu.mtsIdx==MTS_SKIP )
    
      {
        const ChannelType chType    = toChannelType( compID );
        const unsigned    intraMode = PU::getFinalIntraMode( *cu.cs->getPU( tu.blocks[compID].pos(), chType ), chType );
        if( intraMode == HOR_IDX || intraMode == VER_IDX )
        {
          signHiding = false;
        }
      }
    
      // init coeff coding context
      CoeffCodingContext  cctx    ( tu, compID, signHiding );
      const TCoeff*       coeff   = tu.getCoeffs( compID ).buf;
    
      // determine and set last coeff position and sig group flags
      int                      scanPosLast = -1;
      std::bitset<MLS_GRP_NUM> sigGroupFlags;
      for( int scanPos = 0; scanPos < cctx.maxNumCoeff(); scanPos++)
      {
        unsigned blkPos = cctx.blockPos( scanPos );
        if( coeff[blkPos] )
        {
          scanPosLast = scanPos;
          sigGroupFlags.set( scanPos >> cctx.log2CGSize() );
        }
      }
      CHECK( scanPosLast < 0, "Coefficient coding called for empty TU" );
      cctx.setScanPosLast(scanPosLast);
    
    
    #if JVET_O0094_LFNST_ZERO_PRIM_COEFFS
    
    Mischa Siekmann's avatar
    Mischa Siekmann committed
      if( cuCtx && tu.mtsIdx != MTS_SKIP && tu.blocks[ compID ].height >= 4 && tu.blocks[ compID ].width >= 4 )
      {
        const int maxLfnstPos = ((tu.blocks[compID].height == 4 && tu.blocks[compID].width == 4) || (tu.blocks[compID].height == 8 && tu.blocks[compID].width == 8)) ? 7 : 15;
        cuCtx->violatesLfnstConstrained[ toChannelType(compID) ] |= cctx.scanPosLast() > maxLfnstPos;
      }
    
    #endif
    #if JVET_O0472_LFNST_SIGNALLING_LAST_SCAN_POS
      if( cuCtx && tu.mtsIdx != MTS_SKIP && tu.blocks[ compID ].height >= 4 && tu.blocks[ compID ].width >= 4 )
      {
    
    Jason Jung's avatar
    Jason Jung committed
        const int lfnstLastScanPosTh = isLuma( compID ) ? LFNST_LAST_SIG_LUMA : LFNST_LAST_SIG_CHROMA;
        cuCtx->lfnstLastScanPos |= cctx.scanPosLast() >= lfnstLastScanPosTh;
    
    Mischa Siekmann's avatar
    Mischa Siekmann committed
    #endif
    
      last_sig_coeff( cctx, tu, compID );
    
    
      // code subblocks
      const int stateTab  = ( tu.cs->slice->getDepQuantEnabledFlag() ? 32040 : 0 );
      int       state     = 0;
    
    
    #if JVET_O0052_TU_LEVEL_CTX_CODED_BIN_CONSTRAINT
      int ctxBinSampleRatio = (compID == COMPONENT_Y) ? MAX_TU_LEVEL_CTX_CODED_BIN_CONSTRAINT_LUMA : MAX_TU_LEVEL_CTX_CODED_BIN_CONSTRAINT_CHROMA;
      cctx.regBinLimit = (tu.getTbAreaAfterCoefZeroOut(compID) * ctxBinSampleRatio) >> 4;
    #endif
    
    
      for( int subSetId = ( cctx.scanPosLast() >> cctx.log2CGSize() ); subSetId >= 0; subSetId--)
      {
        cctx.initSubblock       ( subSetId, sigGroupFlags[subSetId] );
    
        if( ( tu.mtsIdx > MTS_SKIP || ( tu.cu->sbtInfo != 0 && tu.blocks[ compID ].height <= 32 && tu.blocks[ compID ].width <= 32 ) ) && !tu.cu->transQuantBypass && compID == COMPONENT_Y )
    
        {
          if( ( tu.blocks[ compID ].height == 32 && cctx.cgPosY() >= ( 16 >> cctx.log2CGHeight() ) )
           || ( tu.blocks[ compID ].width  == 32 && cctx.cgPosX() >= ( 16 >> cctx.log2CGWidth()  ) ) )
          {
            continue;
          }
        }
        residual_coding_subblock( cctx, coeff, stateTab, state );
    
    Tung Nguyen's avatar
    Tung Nguyen committed
    void CABACWriter::mts_coding( const TransformUnit& tu, ComponentID compID )
    {
    
    Shelly Chiang's avatar
    Shelly Chiang committed
    #if !JVET_O0294_TRANSFORM_CLEANUP
    
    Tung Nguyen's avatar
    Tung Nguyen committed
      const CodingUnit  &cu = *tu.cu;
    
    Shelly Chiang's avatar
    Shelly Chiang committed
    #endif
    
    Tung Nguyen's avatar
    Tung Nguyen committed
      const bool  tsAllowed = TU::isTSAllowed ( tu, compID );
      const bool mtsAllowed = TU::isMTSAllowed( tu, compID );
    
      if( !mtsAllowed && !tsAllowed ) return;
    
      int symbol  = 0;
      int ctxIdx  = 0;
    
      if( tsAllowed )
      {
    
    Shelly Chiang's avatar
    Shelly Chiang committed
    #if JVET_O0294_TRANSFORM_CLEANUP
        symbol = (tu.mtsIdx == MTS_SKIP) ? 1 : 0;
    #else
    
        symbol = (tu.mtsIdx == MTS_SKIP) ? 0 : 1;
    
    Shelly Chiang's avatar
    Shelly Chiang committed
    #endif
    
    Tung Nguyen's avatar
    Tung Nguyen committed
        ctxIdx = 6;
        m_BinEncoder.encodeBin( symbol, Ctx::MTSIndex( ctxIdx ) );
      }
    
    
      if( tu.mtsIdx != MTS_SKIP )
    
    Tung Nguyen's avatar
    Tung Nguyen committed
      {
        if( mtsAllowed )
        {
    
          symbol = tu.mtsIdx != MTS_DCT2_DCT2 ? 1 : 0;
    
    Shelly Chiang's avatar
    Shelly Chiang committed
    #if JVET_O0294_TRANSFORM_CLEANUP
          ctxIdx = 0;
    #else
    
    Tung Nguyen's avatar
    Tung Nguyen committed
          ctxIdx = std::min( (int)cu.qtDepth, 5 );
    
    Shelly Chiang's avatar
    Shelly Chiang committed
    #endif
    
    Tung Nguyen's avatar
    Tung Nguyen committed
          m_BinEncoder.encodeBin( symbol, Ctx::MTSIndex( ctxIdx ) );
    
    Tung Nguyen's avatar
    Tung Nguyen committed
          if( symbol )
          {
            ctxIdx = 7;
            for( int i = 0; i < 3; i++, ctxIdx++ )
            {
    
              symbol = tu.mtsIdx > i + MTS_DST7_DST7 ? 1 : 0;
    
    Tung Nguyen's avatar
    Tung Nguyen committed
              m_BinEncoder.encodeBin( symbol, Ctx::MTSIndex( ctxIdx ) );
    
              if( !symbol )
              {
                break;
              }
            }
          }
        }
      }
    
    #if JVET_O0294_TRANSFORM_CLEANUP
      DTRACE( g_trace_ctx, D_SYNTAX, "mts_coding() etype=%d pos=(%d,%d) mtsIdx=%d\n", COMPONENT_Y, tu.cu->lx(), tu.cu->ly(), tu.mtsIdx);
    #else
    
    Tung Nguyen's avatar
    Tung Nguyen committed
      DTRACE( g_trace_ctx, D_SYNTAX, "mts_coding() etype=%d pos=(%d,%d) mtsIdx=%d\n", COMPONENT_Y, cu.lx(), cu.ly(), tu.mtsIdx );
    
    Tung Nguyen's avatar
    Tung Nguyen committed
    }
    
    void CABACWriter::isp_mode( const CodingUnit& cu )
    {
    
      if( !CU::isIntra( cu ) || !isLuma( cu.chType ) || cu.firstPU->multiRefIdx || cu.ipcm || !cu.cs->sps->getUseISP() || cu.bdpcmMode || !CU::canUseISP( cu, getFirstComponentOfChannel( cu.chType ) ) )
    
        CHECK( cu.ispMode != NOT_INTRA_SUBPARTITIONS, "cu.ispMode != 0" );
    
      {
        m_BinEncoder.encodeBin( 0, Ctx::ISPMode( 0 ) );
      }
      else
      {
        m_BinEncoder.encodeBin( 1, Ctx::ISPMode( 0 ) );
    
        m_BinEncoder.encodeBin( cu.ispMode - 1, Ctx::ISPMode( 1 ) );
    
      }
      DTRACE( g_trace_ctx, D_SYNTAX, "intra_subPartitions() etype=%d pos=(%d,%d) ispIdx=%d\n", cu.chType, cu.blocks[cu.chType].x, cu.blocks[cu.chType].y, (int)cu.ispMode );
    }
    
    
    void CABACWriter::explicit_rdpcm_mode( const TransformUnit& tu, ComponentID compID )
    {
      const CodingUnit& cu = *tu.cu;
    
      if( !CU::isIntra(cu) && CU::isRDPCMEnabled(cu) && ( tu.mtsIdx==MTS_SKIP || cu.transQuantBypass ) )
    
      {
        ChannelType chType = toChannelType( compID );
        switch( tu.rdpcm[compID] )
        {
        case RDPCM_VER:
          m_BinEncoder.encodeBin( 1, Ctx::RdpcmFlag(chType) );
          m_BinEncoder.encodeBin( 1, Ctx::RdpcmDir (chType) );
          break;
        case RDPCM_HOR:
          m_BinEncoder.encodeBin( 1, Ctx::RdpcmFlag(chType) );
          m_BinEncoder.encodeBin( 0, Ctx::RdpcmDir (chType) );
          break;
        default: // RDPCM_OFF
          m_BinEncoder.encodeBin( 0, Ctx::RdpcmFlag(chType) );
        }
      }
    }
    
    
    void CABACWriter::residual_lfnst_mode( const CodingUnit& cu, CUCtx& cuCtx )
    {
    
    #if JVET_O0213_RESTRICT_LFNST_TO_MAX_TB_SIZE
      int chIdx = CS::isDualITree( *cu.cs ) && cu.chType == CHANNEL_TYPE_CHROMA ? 1 : 0;
    #endif
    
      if( cu.ispMode != NOT_INTRA_SUBPARTITIONS ||
    
    #if JVET_O0925_MIP_SIMPLIFICATIONS
          (cu.cs->sps->getUseLFNST() && CU::isIntra(cu) && cu.mipFlag && !allowLfnstWithMip(cu.firstPU->lumaSize())) ||
    #else
          cu.mipFlag == true ||
    #endif
    
    #if JVET_O0050_LOCAL_DUAL_TREE
    
        ( cu.isSepTree() && cu.chType == CHANNEL_TYPE_CHROMA && std::min( cu.blocks[ 1 ].width, cu.blocks[ 1 ].height ) < 4 )
    
        ( CS::isDualITree( *cu.cs ) && cu.chType == CHANNEL_TYPE_CHROMA && std::min( cu.blocks[ 1 ].width, cu.blocks[ 1 ].height ) < 4 )
    
    #if JVET_O0213_RESTRICT_LFNST_TO_MAX_TB_SIZE
    
        || ( cu.blocks[ chIdx ].lumaSize().width > cu.cs->sps->getMaxTbSize() || cu.blocks[ chIdx ].lumaSize().height > cu.cs->sps->getMaxTbSize() )
    
        || ( cu.blocks[ chIdx ].lumaSize().width > MAX_TB_SIZEY || cu.blocks[ chIdx ].lumaSize().height > MAX_TB_SIZEY )
    
      {
        return;
      }
    
      if( cu.cs->sps->getUseLFNST() && CU::isIntra( cu ) && !CU::isLosslessCoded( cu ) )
      {
    
    #if JVET_O0050_LOCAL_DUAL_TREE
        const bool lumaFlag                   = cu.isSepTree() ? (   isLuma( cu.chType ) ? true : false ) : true;
        const bool chromaFlag                 = cu.isSepTree() ? ( isChroma( cu.chType ) ? true : false ) : true;
    #else
    
        const bool lumaFlag                   = CS::isDualITree( *cu.cs ) ? (   isLuma( cu.chType ) ? true : false ) : true;
        const bool chromaFlag                 = CS::isDualITree( *cu.cs ) ? ( isChroma( cu.chType ) ? true : false ) : true;
    
    #if !JVET_O0472_LFNST_SIGNALLING_LAST_SCAN_POS
    
    #endif
    
    #if JVET_O0094_LFNST_ZERO_PRIM_COEFFS
    
    Mischa Siekmann's avatar
    Mischa Siekmann committed
              bool nonZeroCoeffNonTsCorner8x8 = ( lumaFlag && cuCtx.violatesLfnstConstrained[CHANNEL_TYPE_LUMA] ) || (chromaFlag && cuCtx.violatesLfnstConstrained[CHANNEL_TYPE_CHROMA] );
    #else
    
              bool nonZeroCoeffNonTsCorner8x8 = CU::getNumNonZeroCoeffNonTsCorner8x8( cu, lumaFlag, chromaFlag ) > 0;
    
    Mischa Siekmann's avatar
    Mischa Siekmann committed
    #endif
    
    Jason Jung's avatar
    Jason Jung committed
    #if !JVET_O0472_LFNST_SIGNALLING_LAST_SCAN_POS
    
    #if JVET_O0050_LOCAL_DUAL_TREE
        const int  nonZeroCoeffThr            = cu.isSepTree() ? ( isLuma( cu.chType ) ? LFNST_SIG_NZ_LUMA : LFNST_SIG_NZ_CHROMA ) : LFNST_SIG_NZ_LUMA + LFNST_SIG_NZ_CHROMA;
    #else
    
        const int  nonZeroCoeffThr            = CS::isDualITree( *cu.cs ) ? ( isLuma( cu.chType ) ? LFNST_SIG_NZ_LUMA : LFNST_SIG_NZ_CHROMA ) : LFNST_SIG_NZ_LUMA + LFNST_SIG_NZ_CHROMA;
    
        cuCtx.numNonZeroCoeffNonTs            = CU::getNumNonZeroCoeffNonTs( cu, lumaFlag, chromaFlag );
        nonZeroCoeffNonTs                     = cuCtx.numNonZeroCoeffNonTs > nonZeroCoeffThr;
    
    #endif
    
    #if JVET_O0368_LFNST_WITH_DCT2_ONLY
        const bool isNonDCT2 = (TU::getCbf(*cu.firstTU, ComponentID(COMPONENT_Y)) && cu.firstTU->mtsIdx != MTS_DCT2_DCT2);
    
    #if JVET_O0472_LFNST_SIGNALLING_LAST_SCAN_POS
    
    Jason Jung's avatar
    Jason Jung committed
        if( !cuCtx.lfnstLastScanPos || nonZeroCoeffNonTsCorner8x8 || isNonDCT2 )
    
    #else
    
        if (!nonZeroCoeffNonTs || nonZeroCoeffNonTsCorner8x8 || isNonDCT2 )
    
    #endif
    #else
    #if JVET_O0472_LFNST_SIGNALLING_LAST_SCAN_POS
    
    Jason Jung's avatar
    Jason Jung committed
        if( !cuCtx.lfnstLastScanPos || nonZeroCoeffNonTsCorner8x8 )
    
        if( !nonZeroCoeffNonTs || nonZeroCoeffNonTsCorner8x8 )
    
    #endif
    
    #if JVET_O0050_LOCAL_DUAL_TREE
      if ( cu.isSepTree() ) cctx++;
    #else
    
    #if JVET_O0545_MAX_TB_SIGNALLING
    
    #if JVET_O0050_LOCAL_DUAL_TREE
      if( ( cu.firstTU->mtsIdx < MTS_DST7_DST7 || !TU::getCbf(*cu.firstTU, COMPONENT_Y) ) && cu.isSepTree() ) cctx++;
    #else
    
      if( ( cu.firstTU->mtsIdx < MTS_DST7_DST7 || !TU::getCbf(*cu.firstTU, COMPONENT_Y) ) && CS::isDualITree( *cu.cs ) ) cctx++;
    
    #if JVET_O0050_LOCAL_DUAL_TREE
      if( cu.firstTU->mtsIdx < MTS_DST7_DST7 && cu.isSepTree() ) cctx++;
    
      if( cu.firstTU->mtsIdx < MTS_DST7_DST7 && CS::isDualITree( *cu.cs ) ) cctx++;
    
    
      const uint32_t idxLFNST = cu.lfnstIdx;
      assert( idxLFNST < 3 );
    
      m_BinEncoder.encodeBin( idxLFNST ? 1 : 0, Ctx::LFNSTIdx( cctx ) );
    
        m_BinEncoder.encodeBinEP( ( idxLFNST - 1 ) ? 1 : 0 );
    
      }
    
      DTRACE( g_trace_ctx, D_SYNTAX, "residual_lfnst_mode() etype=%d pos=(%d,%d) mode=%d\n", COMPONENT_Y, cu.lx(), cu.ly(), ( int ) cu.lfnstIdx );
    }
    
    void CABACWriter::last_sig_coeff( CoeffCodingContext& cctx, const TransformUnit& tu, ComponentID compID )
    
    {
      unsigned blkPos = cctx.blockPos( cctx.scanPosLast() );
      unsigned posX, posY;
      {
        posY  = blkPos / cctx.width();
        posX  = blkPos - ( posY * cctx.width() );
      }
    
      unsigned CtxLast;
      unsigned GroupIdxX = g_uiGroupIdx[ posX ];
      unsigned GroupIdxY = g_uiGroupIdx[ posY ];
    
    
      unsigned maxLastPosX = cctx.maxLastPosX();
      unsigned maxLastPosY = cctx.maxLastPosY();
    
      if( ( tu.mtsIdx > MTS_SKIP || ( tu.cu->sbtInfo != 0 && tu.blocks[ compID ].width <= 32 && tu.blocks[ compID ].height <= 32 ) ) && !tu.cu->transQuantBypass && compID == COMPONENT_Y )
    
        maxLastPosX = ( tu.blocks[compID].width  == 32 ) ? g_uiGroupIdx[ 15 ] : maxLastPosX;
        maxLastPosY = ( tu.blocks[compID].height == 32 ) ? g_uiGroupIdx[ 15 ] : maxLastPosY;
    
      for( CtxLast = 0; CtxLast < GroupIdxX; CtxLast++ )
      {
        m_BinEncoder.encodeBin( 1, cctx.lastXCtxId( CtxLast ) );
      }
    
      if( GroupIdxX < maxLastPosX )
    
      {
        m_BinEncoder.encodeBin( 0, cctx.lastXCtxId( CtxLast ) );
      }
      for( CtxLast = 0; CtxLast < GroupIdxY; CtxLast++ )
      {
        m_BinEncoder.encodeBin( 1, cctx.lastYCtxId( CtxLast ) );
      }
    
      if( GroupIdxY < maxLastPosY )
    
      {
        m_BinEncoder.encodeBin( 0, cctx.lastYCtxId( CtxLast ) );
      }
      if( GroupIdxX > 3 )
      {
        posX -= g_uiMinInGroup[ GroupIdxX ];
        for (int i = ( ( GroupIdxX - 2 ) >> 1 ) - 1 ; i >= 0; i-- )
        {
          m_BinEncoder.encodeBinEP( ( posX >> i ) & 1 );
        }
      }
      if( GroupIdxY > 3 )
      {
        posY -= g_uiMinInGroup[ GroupIdxY ];
        for ( int i = ( ( GroupIdxY - 2 ) >> 1 ) - 1 ; i >= 0; i-- )
        {
          m_BinEncoder.encodeBinEP( ( posY >> i ) & 1 );
        }
      }
    }
    
    
    
    void CABACWriter::residual_coding_subblock( CoeffCodingContext& cctx, const TCoeff* coeff, const int stateTransTable, int& state )
    {
      //===== init =====
      const int   minSubPos   = cctx.minSubPos();
      const bool  isLast      = cctx.isLast();
      int         firstSigPos = ( isLast ? cctx.scanPosLast() : cctx.maxSubPos() );
      int         nextSigPos  = firstSigPos;
    
      //===== encode significant_coeffgroup_flag =====
      if( !isLast && cctx.isNotFirst() )
      {
        if( cctx.isSigGroup() )
        {
          m_BinEncoder.encodeBin( 1, cctx.sigGroupCtxId() );
        }
        else
        {
          m_BinEncoder.encodeBin( 0, cctx.sigGroupCtxId() );
          return;
        }
      }
    
      uint8_t   ctxOffset[16];
    
      //===== encode absolute values =====
      const int inferSigPos   = nextSigPos != cctx.scanPosLast() ? ( cctx.isNotFirst() ? minSubPos : -1 ) : nextSigPos;
      int       firstNZPos    = nextSigPos;
      int       lastNZPos     = -1;
      int       remAbsLevel   = -1;
      int       numNonZero    =  0;
      unsigned  signPattern   =  0;
    
    #if JVET_O0052_TU_LEVEL_CTX_CODED_BIN_CONSTRAINT
      int       remRegBins    = cctx.regBinLimit;
    #else
    
      bool      is2x2subblock = ( cctx.log2CGSize() == 2 );
    
      int       remRegBins    = ( is2x2subblock ? MAX_NUM_REG_BINS_2x2SUBBLOCK : MAX_NUM_REG_BINS_4x4SUBBLOCK );
    
      int       firstPosMode2 = minSubPos - 1;
    
      for( ; nextSigPos >= minSubPos && remRegBins >= 4; nextSigPos-- )
    
      {
        TCoeff    Coeff      = coeff[ cctx.blockPos( nextSigPos ) ];
        unsigned  sigFlag    = ( Coeff != 0 );
        if( numNonZero || nextSigPos != inferSigPos )
        {
          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 );
    
        else if( nextSigPos != cctx.scanPosLast() )
        {
          cctx.sigCtxIdAbs( nextSigPos, coeff, state ); // required for setting variables that are needed for gtx/par context selection
        }
    
    
        if( sigFlag )
        {
          uint8_t&  ctxOff  = ctxOffset[ nextSigPos - minSubPos ];
          ctxOff            = cctx.ctxOffsetAbs();
          numNonZero++;
          firstNZPos  = nextSigPos;
          lastNZPos   = std::max<int>( lastNZPos, nextSigPos );
          remAbsLevel = abs( Coeff ) - 1;
    
          if( nextSigPos != cctx.scanPosLast() ) signPattern <<= 1;
          if( Coeff < 0 )                        signPattern++;
    
    
          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--;
    
            unsigned gt2 = !!remAbsLevel;
            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));
            remRegBins--;
    
        }
    
        state = ( stateTransTable >> ((state<<2)+((Coeff&1)<<1)) ) & 3;
      }
    
    #if JVET_O0052_TU_LEVEL_CTX_CODED_BIN_CONSTRAINT
      cctx.regBinLimit = remRegBins;
    #endif
    
      //===== 2nd PASS: Go-rice codes =====
      unsigned ricePar = 0;
      for( int scanPos = firstSigPos; scanPos > firstPosMode2; scanPos-- )
    
        int       sumAll = cctx.templateAbsSum(scanPos, coeff, 4);
        ricePar = g_auiGoRiceParsCoeff[sumAll];
    
        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 );
        }
      }
    
      //===== 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, 0);
    
        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++;
    
          lastNZPos   = std::max<int>( lastNZPos, scanPos );
          signPattern <<= 1;
          if( Coeff < 0 ) signPattern++;
        }
      }
    
    
      //===== encode sign's =====
      unsigned numSigns = numNonZero;
      if( cctx.hideSign( firstNZPos, lastNZPos ) )
      {
        numSigns    --;
        signPattern >>= 1;
      }
      m_BinEncoder.encodeBinsEP( signPattern, numSigns );
    }
    
    
    void CABACWriter::residual_codingTS( const TransformUnit& tu, ComponentID compID )
    {
      DTRACE( g_trace_ctx, D_SYNTAX, "residual_codingTS() etype=%d pos=(%d,%d) size=%dx%d\n", tu.blocks[compID].compID, tu.blocks[compID].x, tu.blocks[compID].y, tu.blocks[compID].width, tu.blocks[compID].height );
    
      // init coeff coding context
    
      CoeffCodingContext  cctx    ( tu, compID, false, tu.cu->bdpcmMode );
    
      const TCoeff*       coeff   = tu.getCoeffs( compID ).buf;
    
      cctx.setNumCtxBins( 2 * tu.lwidth()*tu.lheight() );
    
      // determine and set last coeff position and sig group flags
      std::bitset<MLS_GRP_NUM> sigGroupFlags;
      for( int scanPos = 0; scanPos < cctx.maxNumCoeff(); scanPos++)
      {
        unsigned blkPos = cctx.blockPos( scanPos );
        if( coeff[blkPos] )
        {
          sigGroupFlags.set( scanPos >> cctx.log2CGSize() );
        }
      }
    
      // code subblocks
      for( int subSetId = 0; subSetId <= ( cctx.maxNumCoeff() - 1 ) >> cctx.log2CGSize(); subSetId++ )
      {
        cctx.initSubblock         ( subSetId, sigGroupFlags[subSetId] );
        residual_coding_subblockTS( cctx, coeff );
      }
    }
    
    void CABACWriter::residual_coding_subblockTS( CoeffCodingContext& cctx, const TCoeff* coeff )
    {
      //===== init =====
      const int   minSubPos   = cctx.maxSubPos();
      int         firstSigPos = cctx.minSubPos();
      int         nextSigPos  = firstSigPos;
    
      //===== encode significant_coeffgroup_flag =====
      if( !cctx.isLastSubSet() || !cctx.only1stSigGroup() )
      {
        if( cctx.isSigGroup() )
        {
    
    #if !JVET_O0409_EXCLUDE_CODED_SUB_BLK_FLAG_FROM_COUNT
    
          if( cctx.isContextCoded() )
          {
    
            m_BinEncoder.encodeBin( 1, cctx.sigGroupCtxId( true ) );
            DTRACE( g_trace_ctx, D_SYNTAX_RESI, "ts_sigGroup() bin=%d ctx=%d\n", 1, cctx.sigGroupCtxId() );
    
    #if !JVET_O0409_EXCLUDE_CODED_SUB_BLK_FLAG_FROM_COUNT
    
          }
          else
          {
            m_BinEncoder.encodeBinEP( 1 );
            DTRACE( g_trace_ctx, D_SYNTAX_RESI, "ts_sigGroup() EPbin=%d\n", 1 );
          }
    
    #if !JVET_O0409_EXCLUDE_CODED_SUB_BLK_FLAG_FROM_COUNT
    
          if( cctx.isContextCoded() )
          {
    
            m_BinEncoder.encodeBin( 0, cctx.sigGroupCtxId( true ) );
            DTRACE( g_trace_ctx, D_SYNTAX_RESI, "ts_sigGroup() bin=%d ctx=%d\n", 0, cctx.sigGroupCtxId() );
    
    #if !JVET_O0409_EXCLUDE_CODED_SUB_BLK_FLAG_FROM_COUNT
    
          }
          else
          {
            m_BinEncoder.encodeBinEP( 0 );
            DTRACE( g_trace_ctx, D_SYNTAX_RESI, "ts_sigGroup() EPbin=%d\n", 0 );
          }
    
          return;
        }
      }
    
      //===== encode absolute values =====
      const int inferSigPos   = minSubPos;
      int       remAbsLevel   = -1;
      int       numNonZero    =  0;
    
    
    #if JVET_O0122_TS_SIGN_LEVEL
      int rightPixel, belowPixel, modAbsCoeff;
    #endif
    
    
      for( ; nextSigPos <= minSubPos; nextSigPos++ )
      {
        TCoeff    Coeff      = coeff[ cctx.blockPos( nextSigPos ) ];
        unsigned  sigFlag    = ( Coeff != 0 );
        if( numNonZero || nextSigPos != inferSigPos )
        {
          if( cctx.isContextCoded() )
          {
            const unsigned sigCtxId = cctx.sigCtxIdAbsTS( nextSigPos, coeff );
            m_BinEncoder.encodeBin( sigFlag, sigCtxId );
            DTRACE( g_trace_ctx, D_SYNTAX_RESI, "ts_sig_bin() bin=%d ctx=%d\n", sigFlag, sigCtxId );
          }
          else
          {
            m_BinEncoder.encodeBinEP( sigFlag );
            DTRACE( g_trace_ctx, D_SYNTAX_RESI, "ts_sig_bin() EPbin=%d\n", sigFlag );
          }
        }
    
        if( sigFlag )
        {
          //===== encode sign's =====
          int sign = Coeff < 0;
          if( cctx.isContextCoded() )
          {
    
    #if JVET_O0122_TS_SIGN_LEVEL
            const unsigned signCtxId = cctx.signCtxIdAbsTS(nextSigPos, coeff, cctx.bdpcm());
            m_BinEncoder.encodeBin(sign, signCtxId);
    #else
    
            m_BinEncoder.encodeBin( sign, Ctx::TsResidualSign( cctx.bdpcm() ? 1 : 0 ) );
    
          }
          else
          {
            m_BinEncoder.encodeBinEP( sign );
          }
          numNonZero++;
    
    #if JVET_O0122_TS_SIGN_LEVEL
          cctx.neighTS(rightPixel, belowPixel, nextSigPos, coeff);
          modAbsCoeff = cctx.deriveModCoeff(rightPixel, belowPixel, abs(Coeff), cctx.bdpcm());
          remAbsLevel = modAbsCoeff - 1;
    #else
    
          remAbsLevel = abs( Coeff ) - 1;
    
    
          unsigned gt1 = !!remAbsLevel;
    
    #if JVET_O0122_TS_SIGN_LEVEL
          const unsigned gt1CtxId = cctx.lrg1CtxIdAbsTS(nextSigPos, coeff, cctx.bdpcm());
          if (cctx.isContextCoded())
          {
            m_BinEncoder.encodeBin(gt1, gt1CtxId);
            DTRACE(g_trace_ctx, D_SYNTAX_RESI, "ts_gt1_flag() bin=%d ctx=%d\n", gt1, gt1CtxId);
          }
          else
          {
            m_BinEncoder.encodeBinEP(gt1);
            DTRACE(g_trace_ctx, D_SYNTAX_RESI, "ts_gt1_flag() EPbin=%d\n", gt1);
          }
    #else
    
          if( cctx.isContextCoded() )
          {
            m_BinEncoder.encodeBin( gt1, cctx.greaterXCtxIdAbsTS(0) );
            DTRACE( g_trace_ctx, D_SYNTAX_RESI, "ts_gt1_flag() bin=%d ctx=%d\n", gt1, cctx.greaterXCtxIdAbsTS(0) );
          }
          else
          {
            m_BinEncoder.encodeBinEP( gt1 );
            DTRACE( g_trace_ctx, D_SYNTAX_RESI, "ts_gt1_flag() EPbin=%d\n", gt1 );
          }
    
    
          if( gt1 )
          {
            remAbsLevel  -= 1;
            if( cctx.isContextCoded() )
            {
              m_BinEncoder.encodeBin( remAbsLevel&1, cctx.parityCtxIdAbsTS() );
              DTRACE( g_trace_ctx, D_SYNTAX_RESI, "ts_par_flag() bin=%d ctx=%d\n", remAbsLevel&1, cctx.parityCtxIdAbsTS() );
            }