X265:HM_15.0量化部分代码理解

本文档记录了作者对X265编码器HM_15.0量化部分的代码理解,主要关注transformNxN()函数中的变换和量化过程。作者指出量化过程涉及xTransformSkip()、xT()以及xQuant()函数,并提到码率和失真的计算是通过查表完成的,但未能理解表中值的来源。虽然参考了书籍和网上资料,但量化参数的赋值与传递尚未深入研究。附有作者的个人学习笔记图片以辅助理解。
摘要由CSDN通过智能技术生成

最近刚接触X265,由于需要在265的量化部分进行一定的研究,因此最近把HM的量化部分代码仔细看了一遍,现在对HM中的量化部分有了一定的理解,将自己的理解写在了注释中,贴出来献丑一下。其中很多都是比较小白的注释,大神请忽略。另外由于刚接触不久,注释中肯定会有很多理解不对的地方,希望有大牛看了能随时批评与指正~~~~


HM中的变换量化函数是transformNxN(),其中先是调用xTransformSkip()或xT()进行变换,之后调用xQuant()进行量化:

Void TComTrQuant::xQuant( TComDataCU* pcCU, 
                          Int*        pSrc, 
                          TCoeff*     pDes, 
#if ADAPTIVE_QP_SELECTION
                          Int*&       pArlDes,
#endif
                          Int         iWidth, 
                          Int         iHeight, 
                          UInt&       uiAcSum, 
                          TextType    eTType, 
                          UInt        uiAbsPartIdx )
{
  Int*   piCoef    = pSrc;
  TCoeff* piQCoef   = pDes;
#if ADAPTIVE_QP_SELECTION
  Int*   piArlCCoef = pArlDes;
#endif
  Int   iAdd = 0;
 
  Bool useRDOQ = pcCU->getTransformSkip(uiAbsPartIdx,eTType) ? m_useRDOQTS:m_useRDOQ;
  if ( useRDOQ && (eTType == TEXT_LUMA || RDOQ_CHROMA))
  {
#if ADAPTIVE_QP_SELECTION
    xRateDistOptQuant( pcCU, piCoef, pDes, pArlDes, iWidth, iHeight, uiAcSum, eTType, uiAbsPartIdx );
#else
    xRateDistOptQuant( pcCU, piCoef, pDes, iWidth, iHeight, uiAcSum, eTType, uiAbsPartIdx );
#endif
  }
  else//标准量化???
  {
    const UInt   log2BlockSize   = g_aucConvertToBit[ iWidth ] + 2;//log2 N

    UInt scanIdx = pcCU->getCoefScanIdx(uiAbsPartIdx, iWidth, eTType==TEXT_LUMA, pcCU->isIntra(uiAbsPartIdx));//扫描索引
    const UInt *scan = g_auiSigLastScan[ scanIdx ][ log2BlockSize - 1 ];//光栅扫描与zig-zag扫描的位置对应表
    
    Int deltaU[32*32] ;

#if ADAPTIVE_QP_SELECTION
    QpParam cQpBase;
    Int iQpBase = pcCU->getSlice()->getSliceQpBase();//slice层的QP值   用来对实际QP值进行预测

    Int qpScaled;
    Int qpBDOffset = (eTType == TEXT_LUMA)? pcCU->getSlice()->getSPS()->getQpBDOffsetY() : pcCU->getSlice()->getSPS()->getQpBDOffsetC();

    if(eTType == TEXT_LUMA)//亮度分量的情况
    {
      qpScaled = iQpBase + qpBDOffset;//预测得出亮度块的QP
    }
    else//色度分量Cb Cr的情况
    {
      Int chromaQPOffset;
      if(eTType == TEXT_CHROMA_U)//U分量
      {
        chromaQPOffset = pcCU->getSlice()->getPPS()->getChromaCbQpOffset() + pcCU->getSlice()->getSliceQpDeltaCb();//得出色度块Cr的pps和slice层的偏移之和 pps_offset + slice_offset
      }
      else//V分量
      {
        chromaQPOffset = pcCU->getSlice()->getPPS()->getChromaCrQpOffset() + pcCU->getSlice()->getSliceQpDeltaCr();//得出色度块Cb的pps和slice层的偏移之和 pps_offset + slice_offset
      }
      iQpBase = iQpBase + chromaQPOffset;//QP(pred) + pps_offset + slice_offset
      
      qpScaled = Clip3( -qpBDOffset, 57, iQpBase);//使得 qpBDOffset <=  iQpBase  <=  57

      if(qpScaled < 0)
      {
        qpScaled = qpScaled +  qpBDOffset;//预测得到色度的QP: QP(pred) + pps_offset + slice_offset + QP(delta)
      }
      else
      {
        qpScaled = g_aucChromaScale[ qpScaled ] + qpBDOffset;//预测得到色度的QP: QP(pred) + pps_offset + slice_offset + QP(delta)
      }
    }
    cQpBase.setQpParam(qpScaled);//设置m_iQP  m_iPer  m_iRem的值
#endif

    UInt uiLog2TrSize = g_aucConvertToBit[ iWidth ] + 2;//log2 N
    Int scalingListType = (pcCU->isIntra(uiAbsPartIdx) ? 0 : 3) + g_eTTable[(Int)eTType];//扫描方式
    assert(scalingListType < SCALING_LIST_NUM);
    Int *piQuantCoeff = 0;
    piQuantCoeff = getQuantCoeff(scalingListType,m_cQP.m_iRem,uiLog2TrSize-2);//获取量化矩阵中的系数

    UInt uiBitDepth = eTType == TEXT_LUMA ? g_bitDepthY : g_bitDepthC;
    Int iTransformShift = MAX_TR_DYNAMIC_RANGE - uiBitDepth - uiLog2TrSize;  //之前的变换中的缩放比例 Represents scaling through forward transform

#if ADAPTIVE_QP_SELECTION
    Int iQBits = QUANT_SHIFT + cQpBase.m_iPer + iTransformShift;//非RDO量化器的右偏移量
    iAdd = (pcCU->getSlice()->getSliceType()==I_SLICE ? 171 : 85) << (iQBits-9);//用于计算f = 1/3(I) 或1/6(B/P)
    Int iQBitsC = QUANT_SHIFT + cQpBase.m_iPer + iTransformShift - ARL_C_PRECISION;  
    Int iAddC   = 1 << (iQBitsC-1);//用于计算f = 0.5
#else
    Int iQBits = QUANT_SHIFT + m_cQP.m_iPer + iTransformShift;                //非RDO量化器的右偏移量 Right shift of non-RDOQ quantizer;  level = (coeff*uiQ + offset)>>q_bits
    iAdd = (pcCU->getSlice()->getSliceType()==I_SLICE ? 171 : 85) << (iQBits-9);
#endif

    Int qBits8 = iQBits-8;
    for( Int n = 0; n < iWidth*iHeight; n++ )
    {
      Int iLevel;
      Int  iSign;
      UInt uiBlockPos = n;
      iLevel  = piCoef[uiBlockPos];//变换后的系数
      iSign   = (iLevel < 0 ? -1: 1);  //变换后的系数的符号    

#if ADAPTIVE_QP_SELECTION
      Int64 tmpLevel = (Int64)abs(iLevel) * piQuantCoeff[uiBlockPos];//QM:比例缩放
      if( m_bUseAdaptQpSelect )
      {
        piArlCCoef[uiBlockPos] = (Int)((tmpLevel + iAddC ) >> iQBitsC);
      }
      iLevel = (Int)((tmpLevel + iAdd ) >> iQBits);//计算量化后的系数  f = 1/3(I) 或1/6(B/P)
      deltaU[uiBlockPos] = (Int)((tmpLevel - (iLevel<<iQBits) )>> qBits8);//=  -iAdd >> qBits8
#else
      iLevel = ((Int64)abs(iLevel) * piQuantCoeff[uiBlockPos] + iAdd ) >> iQBits;
      deltaU[uiBlockPos] = (Int)( ((Int64)abs(piCoef[uiBlockPos]) * piQuantCoeff[uiBlockPos] - (iLevel<<iQBits) )>> qBits8 );
#endif
      uiAcSum += iLevel;//变换量化系数的绝对和 absolute sum of quantized transform coefficient
      iLevel *= iSign;        
      piQCoef[ui
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值