diff --git a/source/Lib/CommonLib/QuantRDOQ.cpp b/source/Lib/CommonLib/QuantRDOQ.cpp
index a258d766..58b1bf23 100644
--- a/source/Lib/CommonLib/QuantRDOQ.cpp
+++ b/source/Lib/CommonLib/QuantRDOQ.cpp
@@ -533,7 +533,11 @@ void QuantRDOQ::quant(TransformUnit &tu, const ComponentID &compID, const CCoeff
     if (!m_useSelectiveRDOQ || xNeedRDOQ(tu, compID, piCoef, cQP))
     {
 #endif
+#if ALI_FIX_RDOQ_TS_BUG
+      if (useTransformSkip && !tu.cs->slice->getTSResidualCodingDisabledFlag())
+#else
       if( useTransformSkip )
+#endif
       {
         if( (tu.cu->bdpcmMode && isLuma(compID)) || (isChroma(compID) && tu.cu->bdpcmModeChroma ) )
         {
@@ -546,6 +550,11 @@ void QuantRDOQ::quant(TransformUnit &tu, const ComponentID &compID, const CCoeff
       }
       else
       {
+#if ALI_FIX_RDOQ_TS_BUG
+        if ((tu.cu->bdpcmMode && isLuma(compID)) || (isChroma(compID) && tu.cu->bdpcmModeChroma))
+          forwardRDPCMRRC(tu, compID, pSrc, uiAbsSum, cQP, ctx);
+        else
+#endif
         xRateDistOptQuant( tu, compID, pSrc, uiAbsSum, cQP, ctx );
       }
 #if T0196_SELECTIVE_RDOQ
@@ -637,9 +646,15 @@ void QuantRDOQ::xRateDistOptQuant(TransformUnit &tu, const ComponentID &compID,
   const bool   enableScalingLists = getUseScalingList(uiWidth, uiHeight, isTransformSkip, tu.cu->lfnstIdx > 0, disableSMForLFNST);
 #endif
   const int    defaultQuantisationCoefficient = g_quantScales[ needSqrtAdjustment ?1:0][cQP.rem(isTransformSkip)];
+  
+#if  ALI_FIX_RDOQ_TS_BUG
+  const double defaultErrorScale = isTransformSkip ? xGetErrScaleCoeff(TU::needsSqrt2Scale(tu, compID), uiWidth, uiHeight, cQP.rem(isTransformSkip), maxLog2TrDynamicRange, channelBitDepth, isTransformSkip)
+    : (xGetErrScaleCoeffNoScalingList(scalingListType, uiLog2BlockWidth, uiLog2BlockHeight, cQP.rem(isTransformSkip)));
+  const int iQBits = QUANT_SHIFT + cQP.per(isTransformSkip) + (isTransformSkip ? 0 : iTransformShift) + (needSqrtAdjustment ? -1 : 0);                   // Right shift of non-RDOQ quantizer;  level = (coeff*uiQ + offset)>>q_bits
+#else
   const double defaultErrorScale              = xGetErrScaleCoeffNoScalingList(scalingListType, uiLog2BlockWidth, uiLog2BlockHeight, cQP.rem(isTransformSkip));
   const int iQBits = QUANT_SHIFT + cQP.per(isTransformSkip) + iTransformShift + (needSqrtAdjustment?-1:0);                   // Right shift of non-RDOQ quantizer;  level = (coeff*uiQ + offset)>>q_bits
-
+#endif 
 
   const TCoeff entropyCodingMinimum = -(1 << maxLog2TrDynamicRange);
   const TCoeff entropyCodingMaximum =  (1 << maxLog2TrDynamicRange) - 1;
@@ -1047,7 +1062,12 @@ void QuantRDOQ::xRateDistOptQuant(TransformUnit &tu, const ComponentID &compID,
 
   if( cctx.signHiding() && uiAbsSum>=2)
   {
+    
+#if  ALI_FIX_RDOQ_TS_BUG
+    const double inverseQuantScale = double(g_invQuantScales[needSqrtAdjustment ? 1 : 0][cQP.rem(isTransformSkip)]);
+#else
     const double inverseQuantScale = double(g_invQuantScales[0][cQP.rem(isTransformSkip)]);
+#endif
     int64_t rdFactor = (int64_t)(inverseQuantScale * inverseQuantScale * (1 << (2 * cQP.per(isTransformSkip))) / m_dLambda / 16
                                   / (1 << (2 * DISTORTION_PRECISION_ADJUSTMENT(channelBitDepth)))
                              + 0.5);
@@ -1626,7 +1646,247 @@ void QuantRDOQ::forwardRDPCM( TransformUnit &tu, const ComponentID &compID, cons
     absSum += abs(level);
   }
 }
+#if ALI_FIX_RDOQ_TS_BUG
+
+void QuantRDOQ::forwardRDPCMRRC(TransformUnit &tu, const ComponentID &compID, const CCoeffBuf &coeffs, TCoeff &absSum, const QpParam &qp, const Ctx &ctx)
+{
+  const FracBitsAccess& fracBits = ctx.getFracBitsAcess();
+
+  const SPS &sps = *tu.cs->sps;
+  const CompArea &rect = tu.blocks[compID];
+  const uint32_t width = rect.width;
+  const uint32_t height = rect.height;
+  const ChannelType chType = toChannelType(compID);
+  const int channelBitDepth = sps.getBitDepth(chType);
+
+  const bool extendedPrecision = sps.getSpsRangeExtension().getExtendedPrecisionProcessingFlag();
+  const int  maxLog2TrDynamicRange = sps.getMaxLog2TrDynamicRange(chType);
+  const int  dirMode = isLuma(compID) ? tu.cu->bdpcmMode : tu.cu->bdpcmModeChroma;
+  int transformShift = getTransformShift(channelBitDepth, rect.size(), maxLog2TrDynamicRange);
+
+  if (extendedPrecision)
+  {
+    transformShift = std::max<int>(0, transformShift);
+  }
+
+  double   blockUncodedCost = 0;
+  const uint32_t maxNumCoeff = rect.area();
+
+  CHECK(compID >= MAX_NUM_TBLOCKS, "Invalid component ID");
+
+  int scalingListType = getScalingListType(tu.cu->predMode, compID);
+  CHECK(scalingListType >= SCALING_LIST_NUM, "Invalid scaling list");
+
+  const TCoeff *srcCoeff = coeffs.buf;
+  TCoeff *dstCoeff = tu.getCoeffs(compID).buf;
+
+  double *costCoeff = m_pdCostCoeff;
+  double *costSig = m_pdCostSig;
+  double *costCoeff0 = m_pdCostCoeff0;
+
+  memset(m_pdCostCoeff, 0, sizeof(double) *  maxNumCoeff);
+  memset(m_pdCostSig, 0, sizeof(double) *  maxNumCoeff);
+  memset(m_fullCoeff, 0, sizeof(TCoeff) * maxNumCoeff);
+
+  m_bdpcm = dirMode;
+
+  const bool   needsSqrt2Scale = TU::needsSqrt2Scale(tu, compID);  // should always be false - transform-skipped blocks don't require sqrt(2) compensation.
+  const bool   isTransformSkip = (tu.mtsIdx[compID] == MTS_SKIP);
+  const int    qBits = QUANT_SHIFT + qp.per(isTransformSkip) + (isTransformSkip ? 0 : transformShift) + (needsSqrt2Scale ? -1 : 0);  // Right shift of non-RDOQ quantizer;  level = (coeff*uiQ + offset)>>q_bits
+  const int    quantisationCoefficient = g_quantScales[needsSqrt2Scale ? 1 : 0][qp.rem(isTransformSkip)];
+  const double errorScale = xGetErrScaleCoeff(TU::needsSqrt2Scale(tu, compID), width, height, qp.rem(isTransformSkip), maxLog2TrDynamicRange, channelBitDepth, isTransformSkip);
+  TrQuantParams trQuantParams;
+  trQuantParams.rightShift = (IQUANT_SHIFT - ((isTransformSkip ? 0 : transformShift) + qp.per(isTransformSkip)));
+  trQuantParams.qScale = g_invQuantScales[needsSqrt2Scale ? 1 : 0][qp.rem(isTransformSkip)];
+
+  const TCoeff entropyCodingMaximum = (1 << maxLog2TrDynamicRange) - 1;
+
+  uint32_t coeffLevels[3];
+  double   coeffLevelError[4];
+
+  CoeffCodingContext cctx(tu, compID, tu.cs->picHeader->getSignDataHidingEnabledFlag(), true);
+
+
+  const int sbSizeM1 = (1 << cctx.log2CGSize()) - 1;
+  double    baseCost = 0;
+  uint32_t  goRiceParam = 0;
+  uint16_t  goRiceZero = 0;
+
+
+  double *costSigSubBlock = m_pdCostCoeffGroupSig;
+  memset(costSigSubBlock, 0, (maxNumCoeff >> cctx.log2CGSize()) * sizeof(double));
+
+  const int sbNum = width * height >> cctx.log2CGSize();
+  int scanPos;
+  coeffGroupRDStats rdStats;
+
+  bool anySigCG = false;
 
+  int maxCtxBins = (cctx.maxNumCoeff() * 7) >> 2;
+  cctx.setNumCtxBins(maxCtxBins);
+
+  for (int sbId = 0; sbId < sbNum; sbId++)
+  {
+    cctx.initSubblock(sbId);
+
+    int noCoeffCoded = 0;
+    baseCost = 0.0;
+    memset(&rdStats, 0, sizeof(coeffGroupRDStats));
+    rdStats.iNumSbbCtxBins = 0;
+
+    for (int scanPosInSB = 0; scanPosInSB <= sbSizeM1; scanPosInSB++)
+    {
+      int lastPosCoded = sbSizeM1;
+      scanPos = cctx.minSubPos() + scanPosInSB;
+      //===== quantization =====
+      uint32_t blkPos = cctx.blockPos(scanPos);
+
+      const int posX = cctx.posX(scanPos);
+      const int posY = cctx.posY(scanPos);
+      const int posS = (1 == dirMode) ? posX : posY;
+      const int posNb = (1 == dirMode) ? (posX - 1) + posY * coeffs.stride : posX + (posY - 1) * coeffs.stride;
+      TCoeff predCoeff = (0 != posS) ? m_fullCoeff[posNb] : 0;
+
+      // set coeff
+      const int64_t          tmpLevel = int64_t(abs(srcCoeff[blkPos] - predCoeff)) * quantisationCoefficient;
+      const Intermediate_Int levelDouble = (Intermediate_Int)std::min<int64_t>(tmpLevel, std::numeric_limits<Intermediate_Int>::max() - (Intermediate_Int(1) << (qBits - 1)));
+      uint32_t roundAbsLevel = std::min<uint32_t>(uint32_t(entropyCodingMaximum), uint32_t((levelDouble + (Intermediate_Int(1) << (qBits - 1))) >> qBits));
+      uint32_t minAbsLevel = (roundAbsLevel > 1 ? roundAbsLevel - 1 : 1);
+
+      m_testedLevels = 0;
+      coeffLevels[m_testedLevels++] = roundAbsLevel;
+
+      if (minAbsLevel != roundAbsLevel)
+        coeffLevels[m_testedLevels++] = minAbsLevel;
+
+      double dErr = double(levelDouble);
+      coeffLevelError[0] = dErr * dErr * errorScale;
+
+      costCoeff0[scanPos] = coeffLevelError[0];
+      blockUncodedCost += costCoeff0[scanPos];
+      dstCoeff[blkPos] = coeffLevels[0];
+
+
+      //===== coefficient level estimation =====
+      unsigned    ctxIdSig = cctx.sigCtxIdAbsTS(scanPos, dstCoeff);
+      uint32_t    cLevel;
+      const BinFracBits fracBitsPar = fracBits.getFracBitsArray(cctx.parityCtxIdAbsTS());
+
+      goRiceParam = cctx.templateAbsSumTS(scanPos, dstCoeff);
+      goRiceZero = g_auiGoRicePosCoeff0(0, goRiceParam);
+      const uint8_t     sign = srcCoeff[blkPos] - predCoeff < 0 ? 1 : 0;
+      unsigned gt1CtxId = cctx.lrg1CtxIdAbsTS(scanPos, dstCoeff, dirMode);
+      const BinFracBits fracBitsGr1 = fracBits.getFracBitsArray(gt1CtxId);
+
+      const BinFracBits fracBitsGr2 = fracBits.getFracBitsArray(gt1CtxId); // need to implement
+
+      DTRACE_COND((dstCoeff[blkPos] != 0), g_trace_ctx, D_RDOQ_MORE, " uiCtxSig=%d", ctxIdSig);
+
+      const BinFracBits fracBitsSig = fracBits.getFracBitsArray(ctxIdSig);
+
+
+
+
+      bool lastCoeff = false; //
+      if (scanPosInSB == lastPosCoded && noCoeffCoded == 0)
+      {
+        lastCoeff = true;
+      }
+      int rightPixel, belowPixel;
+      cctx.neighTS(rightPixel, belowPixel, scanPos, dstCoeff);
+      int numUsedCtxBins = 0;
+      cLevel = xGetCodedLevelTSPredRRC(costCoeff[scanPos], costCoeff0[scanPos], costSig[scanPos], levelDouble, qBits, errorScale, coeffLevels, coeffLevelError,
+        &fracBitsSig, fracBitsPar, cctx, fracBits, fracBitsGr1, fracBitsGr2, goRiceZero, goRiceParam, lastCoeff, extendedPrecision, maxLog2TrDynamicRange, numUsedCtxBins);
+      cctx.decimateNumCtxBins(numUsedCtxBins);
+      rdStats.iNumSbbCtxBins += numUsedCtxBins;
+      if (cLevel > 0)
+      {
+        noCoeffCoded++;
+      }
+      dstCoeff[blkPos] = cLevel;
+
+      if (sign)
+      {
+        dstCoeff[blkPos] = -dstCoeff[blkPos];
+      }
+      xDequantSample(m_fullCoeff[blkPos], dstCoeff[blkPos], trQuantParams);
+      m_fullCoeff[blkPos] += predCoeff;
+
+      baseCost += costCoeff[scanPos];
+      rdStats.d64SigCost += costSig[scanPos];
+
+      if (dstCoeff[blkPos])
+      {
+        cctx.setSigGroup();
+        rdStats.d64CodedLevelandDist += costCoeff[scanPos] - costSig[scanPos];
+        rdStats.d64UncodedDist += costCoeff0[scanPos];
+      }
+    } //end for (iScanPosinCG)
+
+    if (!cctx.isSigGroup())
+    {
+      const BinFracBits fracBitsSigGroup = fracBits.getFracBitsArray(cctx.sigGroupCtxId(true));
+      baseCost += xGetRateSigCoeffGroup(fracBitsSigGroup, 0) - rdStats.d64SigCost;
+      costSigSubBlock[cctx.subSetId()] = xGetRateSigCoeffGroup(fracBitsSigGroup, 0);
+      cctx.increaseNumCtxBins(rdStats.iNumSbbCtxBins); // skip sub-block
+    }
+    else if (sbId != sbNum - 1 || anySigCG)
+    {
+      // rd-cost if SigCoeffGroupFlag = 0, initialization
+      double costZeroSB = baseCost;
+      const BinFracBits fracBitsSigGroup = fracBits.getFracBitsArray(cctx.sigGroupCtxId(true));
+
+      baseCost += xGetRateSigCoeffGroup(fracBitsSigGroup, 1);
+      costZeroSB += xGetRateSigCoeffGroup(fracBitsSigGroup, 0);
+      costSigSubBlock[cctx.subSetId()] = xGetRateSigCoeffGroup(fracBitsSigGroup, 1);
+
+      costZeroSB += rdStats.d64UncodedDist;         // distortion for resetting non-zero levels to zero levels
+      costZeroSB -= rdStats.d64CodedLevelandDist;   // distortion and level cost for keeping all non-zero levels
+      costZeroSB -= rdStats.d64SigCost;             // sig cost for all coeffs, including zero levels and non-zerl levels
+
+      if (costZeroSB < baseCost)
+      {
+        cctx.resetSigGroup();
+        baseCost = costZeroSB;
+        costSigSubBlock[cctx.subSetId()] = xGetRateSigCoeffGroup(fracBitsSigGroup, 0);
+        cctx.increaseNumCtxBins(rdStats.iNumSbbCtxBins); // skip sub-block
+
+        for (int scanPosInSB = 0; scanPosInSB <= sbSizeM1; scanPosInSB++)
+        {
+          scanPos = cctx.minSubPos() + scanPosInSB;
+          uint32_t blkPos = cctx.blockPos(scanPos);
+
+          const int posX = cctx.posX(scanPos);
+          const int posY = cctx.posY(scanPos);
+          const int posS = (1 == dirMode) ? posX : posY;
+          const int posNb = (1 == dirMode) ? (posX - 1) + posY * coeffs.stride : posX + (posY - 1) * coeffs.stride;
+          m_fullCoeff[scanPos] = (0 != posS) ? m_fullCoeff[posNb] : 0;
+
+          if (dstCoeff[blkPos])
+          {
+            dstCoeff[blkPos] = 0;
+            costCoeff[scanPos] = costCoeff0[scanPos];
+            costSig[scanPos] = 0;
+          }
+        }
+      }
+      else
+      {
+        anySigCG = true;
+      }
+    }
+  }
+
+  //===== estimate last position =====
+  for (int scanPos = 0; scanPos < maxNumCoeff; scanPos++)
+  {
+    int blkPos = cctx.blockPos(scanPos);
+    TCoeff level = dstCoeff[blkPos];
+    absSum += abs(level);
+  }
+}
+
+#endif
 void QuantRDOQ::xDequantSample(TCoeff& pRes, TCoeff& coeff, const TrQuantParams& trQuantParams)
 {
   // xDequant
@@ -1928,4 +2188,221 @@ inline int QuantRDOQ::xGetICRateTS( const uint32_t            absLevel,
   return rate;
 }
 
+#if ALI_FIX_RDOQ_TS_BUG
+inline uint32_t QuantRDOQ::xGetCodedLevelTSPredRRC(double&            rd64CodedCost,
+  double&            rd64CodedCost0,
+  double&            rd64CodedCostSig,
+  Intermediate_Int    levelDouble,
+  int                 qBits,
+  double              errorScale,
+  uint32_t coeffLevels[],
+  double coeffLevelError[],
+  const BinFracBits* fracBitsSig,
+  const BinFracBits& fracBitsPar,
+  CoeffCodingContext& cctx,
+  const FracBitsAccess& fracBitsAccess,
+  // const BinFracBits& fracBitsSign,
+  const BinFracBits& fracBitsGt1,
+  const BinFracBits& fracBitsGt2,
+  //  const uint8_t      sign,
+   // int                rightPixel,
+   // int                belowPixel,
+  uint16_t      goRiceZero,
+  uint16_t           ricePar,
+  bool               isLast,
+  bool               useLimitedPrefixLength,
+  const int          maxLog2TrDynamicRange
+  , int&               numUsedCtxBins
+) const
+{
+  double currCostSig = 0;
+  uint32_t   bestAbsLevel = 0;
+  numUsedCtxBins = 0;
+  int numBestCtxBin = 0;
+  if (!isLast && coeffLevels[0] < 3)
+  {
+    if (cctx.numCtxBins() >= 4)
+      rd64CodedCostSig = xGetRateSigCoef(*fracBitsSig, 0);
+    else
+      rd64CodedCostSig = xGetICost(1 << SCALE_BITS);
+    rd64CodedCost = rd64CodedCost0 + rd64CodedCostSig;
+    if (cctx.numCtxBins() >= 4)
+      numUsedCtxBins++;
+    if (coeffLevels[0] == 0)
+    {
+      return bestAbsLevel;
+    }
+  }
+  else
+  {
+    rd64CodedCost = MAX_DOUBLE;
+  }
+
+  if (!isLast)
+  {
+    if (cctx.numCtxBins() >= 4)
+      currCostSig = xGetRateSigCoef(*fracBitsSig, 1);
+    else
+      currCostSig = xGetICost(1 << SCALE_BITS);
+    if (coeffLevels[0] >= 3 && cctx.numCtxBins() >= 4)
+      numUsedCtxBins++;
+  }
+
+  for (int errorInd = 1; errorInd <= m_testedLevels; errorInd++)
+  {
+    int absLevel = coeffLevels[errorInd - 1];
+    double dErr = 0.0;
+    dErr = double(levelDouble - (Intermediate_Int(absLevel) << qBits));
+    coeffLevelError[errorInd] = dErr * dErr * errorScale;
+    int modAbsLevel = absLevel;
+    int numCtxBins = 0;
+    double dCurrCost = coeffLevelError[errorInd] + xGetICost(xGetICRateTSRRC(modAbsLevel, fracBitsPar, cctx, fracBitsAccess, fracBitsGt1, fracBitsGt2, numCtxBins, goRiceZero, ricePar, useLimitedPrefixLength, maxLog2TrDynamicRange));
+
+    if (cctx.numCtxBins() >= 4)
+      dCurrCost += currCostSig; // if cctx.numCtxBins < 4, xGetICRateTS return rate including sign cost. dont need to add any more
+
+    if (dCurrCost < rd64CodedCost)
+    {
+      bestAbsLevel = absLevel;
+      rd64CodedCost = dCurrCost;
+      rd64CodedCostSig = currCostSig;
+      numBestCtxBin = numCtxBins;
+    }
+  }
+  numUsedCtxBins += numBestCtxBin;
+  return bestAbsLevel;
+}
+
+inline int QuantRDOQ::xGetICRateTSRRC(const uint32_t            absLevel,
+  const BinFracBits&        fracBitsPar,
+  const CoeffCodingContext& cctx,
+  const FracBitsAccess&     fracBitsAccess,
+  const BinFracBits&        fracBitsGt1,
+  const BinFracBits&        fracBitsGt2,
+  int&                      numCtxBins,
+  const uint16_t            goRiceZero,
+  const uint16_t            ricePar,
+  const bool                useLimitedPrefixLength,
+  const int                 maxLog2TrDynamicRange) const
+{
+
+  if (cctx.numCtxBins() < 4) // Full by-pass coding 
+  {
+    int rate = absLevel ? (1 << SCALE_BITS) : 0; // 1 bit to signal sign of non-zero 
+
+    uint32_t  symbol = (absLevel == 0 ? goRiceZero : absLevel <= goRiceZero ? absLevel - 1 : absLevel);
+
+
+    uint32_t length;
+    const int threshold = COEF_REMAIN_BIN_REDUCTION;
+    if (symbol < (threshold << ricePar))
+    {
+      length = symbol >> ricePar;
+      rate += (length + 1 + ricePar) << SCALE_BITS;
+    }
+    else if (useLimitedPrefixLength)
+    {
+      const uint32_t maximumPrefixLength = (32 - (COEF_REMAIN_BIN_REDUCTION + maxLog2TrDynamicRange));
+
+      uint32_t prefixLength = 0;
+      uint32_t suffix = (symbol >> ricePar) - COEF_REMAIN_BIN_REDUCTION;
+
+      while ((prefixLength < maximumPrefixLength) && (suffix > ((2 << prefixLength) - 2)))
+      {
+        prefixLength++;
+      }
+
+      const uint32_t suffixLength = (prefixLength == maximumPrefixLength) ? (maxLog2TrDynamicRange - ricePar) : (prefixLength + 1/*separator*/);
+
+      rate += (COEF_REMAIN_BIN_REDUCTION + prefixLength + suffixLength + ricePar) << SCALE_BITS;
+    }
+    else
+    {
+      length = ricePar;
+      symbol = symbol - (threshold << ricePar);
+      while (symbol >= (1 << length))
+      {
+        symbol -= (1 << (length++));
+      }
+      rate += (threshold + length + 1 - ricePar + length) << SCALE_BITS;
+    }
+
+    return rate;
+  }
+
+
+  int iRate = int(xGetIEPRate()); // cost of sign bit
+  const uint32_t cthres = 4;
+  if (absLevel >= cthres)
+  {
+    uint32_t symbol = (absLevel - cthres) >> 1;
+    uint32_t length;
+    const int threshold = COEF_REMAIN_BIN_REDUCTION;
+    if (symbol < (threshold << ricePar))
+    {
+      length = symbol >> ricePar;
+      iRate += (length + 1 + ricePar) << SCALE_BITS;
+    }
+    else if (useLimitedPrefixLength)
+    {
+      const uint32_t maximumPrefixLength = (32 - (COEF_REMAIN_BIN_REDUCTION + maxLog2TrDynamicRange));
+
+      uint32_t prefixLength = 0;
+      uint32_t suffix = (symbol >> ricePar) - COEF_REMAIN_BIN_REDUCTION;
+
+      while ((prefixLength < maximumPrefixLength) && (suffix > ((2 << prefixLength) - 2)))
+      {
+        prefixLength++;
+      }
+
+      const uint32_t suffixLength = (prefixLength == maximumPrefixLength) ? (maxLog2TrDynamicRange - ricePar) : (prefixLength + 1/*separator*/);
+
+      iRate += (COEF_REMAIN_BIN_REDUCTION + prefixLength + suffixLength + ricePar) << SCALE_BITS;
+    }
+    else
+    {
+      length = ricePar;
+      symbol = symbol - (threshold << ricePar);
+      while (symbol >= (1 << length))
+      {
+        symbol -= (1 << (length++));
+      }
+      iRate += (threshold + length + 1 - ricePar + length) << SCALE_BITS;
+    }
+
+    iRate += fracBitsGt1.intBits[1];
+    iRate += fracBitsPar.intBits[(absLevel - 2) & 1];
+    iRate += fracBitsGt2.intBits[1];
+
+    numCtxBins += 3;
+  }
+  else if (absLevel == 1)
+  {
+    iRate += fracBitsGt1.intBits[0];
+    numCtxBins++;
+  }
+  else if (absLevel == 2)
+  {
+    iRate += fracBitsGt1.intBits[1];
+    iRate += fracBitsPar.intBits[0];
+    iRate += fracBitsGt2.intBits[0];
+    numCtxBins += 3;
+  }
+  else if (absLevel == 3)
+  {
+    iRate += fracBitsGt1.intBits[1];
+    iRate += fracBitsPar.intBits[1];
+    iRate += fracBitsGt2.intBits[0];
+    numCtxBins += 3;
+  }
+  else
+  {
+    iRate = 0;
+  }
+  return  iRate;
+}
+
+
+
+#endif
 //! \}
diff --git a/source/Lib/CommonLib/QuantRDOQ.h b/source/Lib/CommonLib/QuantRDOQ.h
index ec3ca1c6..0b031875 100644
--- a/source/Lib/CommonLib/QuantRDOQ.h
+++ b/source/Lib/CommonLib/QuantRDOQ.h
@@ -66,7 +66,9 @@ public:
   // quantization
   void quant                ( TransformUnit &tu, const ComponentID &compID, const CCoeffBuf &pSrc, TCoeff &uiAbsSum, const QpParam &cQP, const Ctx& ctx );
   void forwardRDPCM         ( TransformUnit &tu, const ComponentID &compID, const CCoeffBuf &pSrc, TCoeff &uiAbsSum, const QpParam &cQP, const Ctx &ctx );
-
+#if ALI_FIX_RDOQ_TS_BUG
+  void forwardRDPCMRRC(TransformUnit &tu, const ComponentID &compID, const CCoeffBuf &pSrc, TCoeff &uiAbsSum, const QpParam &cQP, const Ctx &ctx);
+#endif
 private:
   double* xGetErrScaleCoeffSL            ( uint32_t list, uint32_t sizeX, uint32_t sizeY, int qp ) { return m_errScale[sizeX][sizeY][list][qp]; };  //!< get Error Scale Coefficent
   double  xGetErrScaleCoeff              ( const bool needsSqrt2, SizeType width, SizeType height, int qp, const int maxLog2TrDynamicRange, const int channelBitDepth, bool bTransformSkip);
@@ -151,6 +153,50 @@ private:
                               const uint16_t            ricePar,
                               const bool                useLimitedPrefixLength,
                               const int                 maxLog2TrDynamicRange  ) const;
+
+
+#if ALI_FIX_RDOQ_TS_BUG
+  inline uint32_t xGetCodedLevelTSPredRRC(double&            rd64CodedCost,
+    double&            rd64CodedCost0,
+    double&            rd64CodedCostSig,
+    Intermediate_Int    levelDouble,
+    int                 qBits,
+    double              errorScale,
+    uint32_t coeffLevels[],
+    double coeffLevelError[],
+    const BinFracBits* fracBitsSig,
+    const BinFracBits& fracBitsPar,
+    CoeffCodingContext& cctx,
+    const FracBitsAccess& fracBitsAccess,
+    //    const BinFracBits& fracBitsSign,
+    const BinFracBits& fracBitsGt1,
+    const BinFracBits& fracBitsGt2,
+    //    const uint8_t      sign,
+    //    int                rightPixel,
+    //    int                belowPixel,
+    uint16_t      goRiceZero,
+    uint16_t           ricePar,
+    bool               isLast,
+    bool               useLimitedPrefixLength,
+    const int          maxLog2TrDynamicRange
+    , int&               numUsedCtxBins
+  ) const;
+
+  inline int xGetICRateTSRRC(const uint32_t            absLevel,
+    const BinFracBits&        fracBitsPar,
+    const CoeffCodingContext& cctx,
+    const FracBitsAccess&     fracBitsAccess,
+    const BinFracBits&        fracBitsGt1,
+    const BinFracBits&        fracBitsGt2,
+    int&                      numCtxBins,
+    const uint16_t             goRiceZero,
+    const uint16_t            ricePar,
+    const bool                useLimitedPrefixLength,
+    const int                 maxLog2TrDynamicRange) const;
+
+
+#endif
+
 private:
   bool    m_isErrScaleListOwner;
 
diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h
index 4a811c8e..9dbd7f9c 100644
--- a/source/Lib/CommonLib/TypeDef.h
+++ b/source/Lib/CommonLib/TypeDef.h
@@ -50,6 +50,10 @@
 #include <assert.h>
 #include <cassert>
 
+#define ALI_ALWAYS_USE_REGULAR_RESIDUAL_CODING            1
+#define ALI_FIX_RDOQ_TS_BUG                               1
+
+
 #define CABAC_RETRAIN                                     1 // CABAC retraining based on VTM8rc1
 
 #define JVET_Q0044_SLICE_IDX_WITH_SUBPICS                 1 // JVET-Q0044: slice index with subpictures
diff --git a/source/Lib/EncoderLib/EncSlice.cpp b/source/Lib/EncoderLib/EncSlice.cpp
index 2521811f..33314cf7 100644
--- a/source/Lib/EncoderLib/EncSlice.cpp
+++ b/source/Lib/EncoderLib/EncSlice.cpp
@@ -344,6 +344,9 @@ void EncSlice::initEncSlice(Picture* pcPic, const int pocLast, const int pocCurr
   }
   rpcSlice->setPOC( pocCurr );
 #if JVET_Q0089_SLICE_LOSSLESS_CODING_CHROMA_BDPCM
+#if ALI_ALWAYS_USE_REGULAR_RESIDUAL_CODING
+  rpcSlice->setTSResidualCodingDisabledFlag(true);
+#else
   if( m_pcCfg->getCostMode() == COST_LOSSLESS_CODING )
   {
     rpcSlice->setTSResidualCodingDisabledFlag(true);
@@ -353,6 +356,7 @@ void EncSlice::initEncSlice(Picture* pcPic, const int pocLast, const int pocCurr
     rpcSlice->setTSResidualCodingDisabledFlag(false);
   }
 #endif
+#endif
 
 #if SHARP_LUMA_DELTA_QP
   pcPic->fieldPic = isField;
