H.265中针对scc的工具 -- transformskip

       transformskip和intra block copy, palatte mode 一样,是针对screen content 的编码工具,该工具的提出是因为对于screen content,其经常包含尖锐边缘或者跳变,相关性极差,这种情况下进行正常的transform反而会带来负面影响,还不如跳过变换环节,直接对残差进行量化。下面来直接看代码:

 if (pcCU->getTransformSkip(uiAbsPartIdx, compID) != 0)//开启transformskip
      {
        xTransformSkip(pcResidual, uiStride, m_plTempCoeff, rTu, compID);
      }
      else.  //执行正常的transform
      {
        const Int channelBitDepth = pcCU->getSlice()->getSPS()->getBitDepth(toChannelType(compID));
        xT(channelBitDepth, rTu.useDST(compID), pcResidual, uiStride, m_plTempCoeff, uiWidth, uiHeight, pcCU->getSlice()->getSPS()->getMaxLog2TrDynamicRange(toChannelType(compID)));
      }

#if DEBUG_TRANSFORM_AND_QUANTISE
      std::cout << g_debugCounter << ": " << uiWidth << "x" << uiHeight << " channel " << compID << " TU between transform and quantiser\n";
      printBlock(m_plTempCoeff, uiWidth, uiHeight, uiWidth);
#endif // if DEBUG_TRANSFORM_AND_QUANTISE

      xQuant(rTu, m_plTempCoeff, rpcCoeff,

#if ADAPTIVE_QP_SELECTION
             pcArlCoeff,
#endif // if ADAPTIVE_QP_SELECTION
             uiAbsSum, compID, cQP);//执行量化
Void TComTrQuant::xTransformSkip(Pel *piBlkResi, UInt uiStride, TCoeff *psCoeff, TComTU &rTu, const ComponentID component)
{
  const TComRectangle &rect = rTu.getRect(component);
  const Int width = rect.width;
  const Int height = rect.height;
  const Int maxLog2TrDynamicRange = rTu.getCU()->getSlice()->getSPS()->getMaxLog2TrDynamicRange(toChannelType(component));
  const Int channelBitDepth = rTu.getCU()->getSlice()->getSPS()->getBitDepth(toChannelType(component));

  Int iTransformShift = getTransformShift(channelBitDepth, rTu.GetEquivalentLog2TrSize(component), maxLog2TrDynamicRange);
  //rTu.GetEquivalentLog2TrSize(component) always is 2.
  if (rTu.getCU()->getSlice()->getSPS()->getSpsRangeExtension().getExtendedPrecisionProcessingFlag())
  {
    iTransformShift = std::max<Int>(0, iTransformShift);//这个iTransformShift是因为在编码器里变换和量化融合在一起,量化步骤包含了变换步骤中乘以1/128的部分,所以在这里要先乘上128
  }

  const Bool rotateResidual = rTu.isNonTransformedResidualRotated(component);//对残差进行旋转,因为对于intra prediction来说,越远预测的越差,残差越大
  const UInt uiSizeMinus1 = (width * height) - 1;

  if (iTransformShift >= 0)
  {
    for (UInt y = 0, coefficientIndex = 0; y < height; y++)
    {
      for (UInt x = 0; x < width; x++, coefficientIndex++)
      {
        psCoeff[rotateResidual ? (uiSizeMinus1 - coefficientIndex) : coefficientIndex] = TCoeff(piBlkResi[(y * uiStride) + x]) << iTransformShift;
      }
    }
  }
  else // for very high bit depths
  {
    iTransformShift = -iTransformShift;
    const TCoeff offset = 1 << (iTransformShift - 1);

    for (UInt y = 0, coefficientIndex = 0; y < height; y++)
    {
      for (UInt x = 0; x < width; x++, coefficientIndex++)
      {
        psCoeff[rotateResidual ? (uiSizeMinus1 - coefficientIndex) : coefficientIndex] = (TCoeff(piBlkResi[(y * uiStride) + x]) + offset) >> iTransformShift;
      }
    }
  }
}

在h265中,对于每个CU来说是否开启transformskip完全有RDO来选择;

 for (Int modeId = firstCheckId; modeId < 2; modeId++)//第一次TransformSkip为false,第二次TransformSkip为true,通过rdcost来选择是否用TransformSkip;
      {
        DEBUG_STRING_NEW(sModeString)
        Int default0Save1Load2 = 0;
        singleDistTmpLuma = 0;

        if (modeId == firstCheckId)
        {
          default0Save1Load2 = 1;
        }
        else
        {
          default0Save1Load2 = 2;
        }

        pcCU->setTransformSkipSubParts(modeId, COMPONENT_Y, uiAbsPartIdx, totalAdjustedDepthChan);//把modeId赋值给m_puhTransformSkip,会导致在xIntraCodingTUBlock里使用xTransformskip 或者xT;
        xIntraCodingTUBlock(pcOrgYuv, pcPredYuv, pcResiYuv, resiLumaSingle, false, singleDistTmpLuma, COMPONENT_Y, rTu DEBUG_STRING_PASS_INTO(sModeString), default0Save1Load2);
        ......
}

 

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值