x265代碼閱讀:碼率控制(一)

x265中碼率控制算法貌似與x264的碼率控制算法基本相同,基本上是經驗性的,與ITU-T/MPEG各類標準推薦的碼率控制算法均不同。
x265的率控應該只是幀級率控,雖然有與CU相關的率控參數,但其實那是塊級的率失真優化技術,並非塊級率控。x265支持三種率控模式:

/* rate tolerance method */
typedef enum
{
    X265_RC_ABR, // average bit rate
    X265_RC_CQP, // constant QP
    X265_RC_CRF  // constant rate fator
} X265_RC_METHODS;

X265_RC_ABR應該就對應學界的CBR;CQP對應HM不開率控時的配置;X265_RC_CRF是“Quality-controlled VBR”,學界叫做consistent quality的碼率控制。在函數x265_param_default中設置的默認的碼率控制類型是X265_RC_CRF。在學界,CBR是碼率控制研究的重點;在x264/x265中,CRF模式是重點。

在輸入參數類型x265_param中定義了一個包含碼率控制輸入參數的成員rc,rc是一個定義在類型x265_param中的匿名結構體類型的對象。
下面是與計算QP有關的四個主要函數,它們被調用的順序與下面的列表排列順序相同:

    // to be called for each curFrame to process RateControl and set QP
    int rateControlStart(Frame* curFrame, RateControlEntry* rce, Encoder* enc);
    // main logic for calculating QP based on ABR
    double rateEstimateQscale(Frame* pic, RateControlEntry *rce);
    /* modify the bitrate curve from pass1 for one frame */
    double getQScale(RateControlEntry *rce, double rateFactor);
    double tuneAbrQScaleFromFeedback(double qScale);

函數rateControlStart中,CQP模式下QP的計算與幀類型有關:

    else // CQP
    {
        if (m_sliceType == B_SLICE && IS_REFERENCED(curFrame))
            m_qp = (m_qpConstant[B_SLICE] + m_qpConstant[P_SLICE]) / 2;
        else
            m_qp = m_qpConstant[m_sliceType];
        curEncData.m_avgQpAq = curEncData.m_avgQpRc = m_qp;

        x265_zone* zone = getZone();
        if (zone)
        {
            if (zone->bForceQp)
                m_qp += zone->qp - m_qpConstant[P_SLICE];
            else
                m_qp -= 6.0 * X265_LOG2(zone->bitrateFactor);
        }
    }

CRF和ABR模式時,B幀的QP由前後兩個參考的P幀的QP插值而來,I幀、P幀的QP主要用getQScale中的下面這條語句計算:

    if (m_param->rc.cuTree)
    {
        // Scale and units are obtained from rateNum and rateDenom for videos with fixed frame rates.
        double timescale = (double)m_param->fpsDenom / (2 * m_param->fpsNum);
        q = pow(BASE_FRAME_DURATION / CLIP_DURATION(2 * timescale), 1 - m_param->rc.qCompress);
    }
    else
        q = pow(rce->blurredComplexity, 1 - m_param->rc.qCompress);

上面的rc.qCompress默認是0.6,也就是說量化步長是blurredComplexity的0.4次冪,blurredComplexity越大,量化步長越大。blurredComplexity是圖像的預測殘差的SATD。
根據圖像複雜度初步計算出QScale後,還須除以ratefactor。CRF和ABR調用getQScale時給的rateFactor的參數不同,CBF時是常數,ABR等於m_wantedBitsWindow / m_cplxrSum,使得計算得到的QScale與已編碼視頻的複雜度成正比。代碼如下:

      if (m_param->rc.rateControlMode == X265_RC_CRF)
      {
          q = getQScale(rce, m_rateFactorConstant);
      }
      else
      {
          if (!m_param->rc.bStatRead)
              checkAndResetABR(rce, false);
          double initialQScale = getQScale(rce, m_wantedBitsWindow / m_cplxrSum);
          q = tuneAbrQScaleFromFeedback(initialQScale);
          overflow = q / initialQScale;
      }

變量overflow等於比特誤差除以abrBuffer,X265_RC_ABR模式下,getQScale還需要除以overflow;X265_RC_CRF模式下,“no overflow compensation is done”。
x265中的rc.cuTree,類似於x264中的MBTree,不是空域劃分的樹結構,而是時域的參考樹結構,在結構體對象rc中的定義和註釋如下:

    struct

    {
    ...
        /* Enable CUTree ratecontrol. This keeps track of the CUs that propagate temporally
         * across frames and assigns more bits to these CUs. Improves encode efficiency.
         * Default: enabled */
        int       cuTree;
        ...
    }

MBTree的百度百科:http://baike.baidu.com/item/Macroblock%20Tree

此外,在ABR模式下還可以設置爲二次編碼,CRF和CQP模式下不兼容二次編碼。設置編碼次數的命令如下:

--pass <integer>

客觀質量不是他們考慮的因素,他們考慮主觀質量,他們認爲CBR模式的主觀質量最好。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章