天天看點

X264 ratecontrol 碼率控制

最近由于項目需要,研究了下x264的碼控,發現網上這方面的資源很少!這方面據說也比較難,是x264中唯一一個數學模組化的子產品。

下面是我的學習筆記,拿出來和大家分享,有不對的地方希望有心人多多指正

x264中ratecontrol主要過程是;

1.根據前面已經編好的幀計算SATD值來預測目前幀的複雜度(第一幀I幀除外);

2.計算好複雜度之後,根據複雜度和線性量化控制參數(qcomp)來計算qpscale。qpscale會影響最終編碼是所用到qp。

3.根據目标碼率和之前編碼幀所用的比特數可以确定一個rate_factor,若之前編碼的比特數多與目标實際産生,則rate_factor小。

這個rate_factor是調整qpscale用的,還有overflow來對qpscale來做溢出補償處理來控制檔案的大小。

4.最後根據計算公式得到qp

主要的函數

1.

x264_ratecontrol_new()函數中的一些關鍵參數

rc->bitrate = h->param.rc.i_bitrate * 1000.; ///目标碼率

rc->rate_tolerance = h->param.rc.f_rate_tolerance; ///允許的誤差

rc->nmb = h->mb.i_mb_count; ///要編碼的宏塊數

rc->cplxr_sum = .01 * pow( 7.0e5, h->param.rc.f_qcompress ) * pow( h->mb.i_mb_count, 0.5 ); 

rc->wanted_bits_window = /*1.0 **/ rc->bitrate / rc->fps; 

///得到ratefactor

2.

在x264_encoder_encode這個函數裡面的x264_frame_init_lowres( h, fenc )是對目前幀進行一個下采樣,将cif格式的圖像下采樣為qcif格式。為後面計算SATD做好準備。

x264_ratecontrol_start()

|

rate_estimate_qscale()

rcc->last_satd = x264_stack_align( x264_rc_analyse_slice, h ); ///這個分析之前下采樣出來的SATD的函數

q = get_qscale( h, &rce, rcc->wanted_bits_window / rcc->cplxr_sum, h->fenc->i_frame ); ///根據前面已編好幀的比特數計算rate_factor來調整qpscale

qpscale2qp() ///将得到的qpscale轉換成qp

3.

encode--->Encode_frame--->x264_encoder_encode--->x264_slices_write--->x264_slice_write--->x264_ratecontrol_mb 

int b0 = predict_row_size_sum( h, y, rc->qpm );這裡是計算将要編碼幀的複雜度,此函數内部涉及到了SATD的計算還有一些和論文相符的複雜度計算

///細節沒看明白,但感覺是在編宏塊的時候調整QP之類的

4.

encode--->Encode_frame--->x264_encoder_encode--->x264_ratecontrol_end /////在編完一幀過後

x264_ratecontrol_end()函數

h->fdec->f_qp_avg_rc = rc->qpa_rc /= h->mb.i_mb_count; ///aq之前的qp 根據變量的字面意思應該根據宏塊的個數來計算qp的平均值

h->fdec->f_qp_avg_aq = rc->qpa_aq /= h->mb.i_mb_count; ///aq之後的qp aq是什麼?

if( rc->b_abr )

{

rc->cplxr_sum += bits * qp2qscale(rc->qpa_rc) / rc->last_rceq;

rc->cplxr_sum *= rc->cbr_decay;

rc->wanted_bits_window += rc->bitrate / rc->fps;

rc->wanted_bits_window *= rc->cbr_decay;

accum_p_qp_update( h, rc->qpa_rc );

}

////這一段應該是在統計已編好幀的bit數,為編下一幀的qp調整做好準備

5.

x264_ratecontrol_summary和x264_ratecontrol_delete這兩個函數不知道為什麼沒有走到,summary函數不知是做什麼用的,delete就很明顯是用來釋放rc開辟的空間的

未完成...

繼續閱讀