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模式的主觀質量最好。