天天看點

X264碼率控制流程分析

轉載自:http://blog.csdn.net/maopig/article/details/6718157

碼率控制的理論知識:

碼率控制的目的和意義:

圖像通信中碼率控制的目的:通過調節編碼參數,控制機關時間内的編碼視訊流的資料量,以使産生的比特流符合各種應用的需求。視訊壓縮的效率和視訊内容有很大的關系,對于變化多樣的畫面,視訊編碼的輸出的碼流變化較大,在信道環境不好的時候就容易導緻解碼端顯示的品質的不穩定。

率失真理論:

由于傳輸帶寬和存儲空間的限制,視訊應用對壓縮比有較高的要求。而無損編碼較低的壓縮比無法滿足視訊在實際應用中的需求。但如果給視訊引入一定程度的失真,通常可以獲得較高的壓縮比。

率失真理論對有損壓縮編碼下的失真和編碼性能之間的關系的描述,為碼率控制的研究提供了堅實的理論依據。率失真理論主旨是描述編碼失真度和編碼資料速率的關系。該理論建立在圖像是連續的基礎上的,在有限資料速率下,由于存在量化誤差,必然存在失真。當使用有損編碼方法時,重建圖像g(x,y)和原始圖像f(x,y)之間存在差異,失真度D的函數形式在理論上是可以根據需要自由選取的,在圖像編碼中,D常用均方差形式表示的,典型的率失真曲線。R(D)為D的凸減函數。

對于怎麼選擇哪個函數的率失真效果更好,則是比較哪個函數的率失真函數更為接近典型的率失真函數的曲線。

x264碼率控制方法:采用的碼率控制算法并沒有采用拉格朗日代價函數來控制編碼,而是使用一種更簡單的方法,即利用半精度幀的SATD(sum of absolute transformed difference)作為模式選擇的依據。SATD即将殘差經哈德曼變換的4×4塊的預測殘差絕對值總和,可以将其看作簡單的時頻變換,其值在一定程度上可以反映生成碼流的大小。SATD是将殘差經哈達曼變換4*4塊的預測殘差絕對值總和。自适應宏塊層碼率控制政策:X264的宏塊沒有任何碼率控制的機制,其在幀層得到一個QP後,屬于該幀的所有宏塊都用着統一的QP進行量化。

碼率控制性能測度:

1、比特率誤差|ABR-TBR|/TBR ,越小越好。

2、編碼器性能。

3、緩沖區滿度與TBL的比對程度。

4、跳幀數。

5、PSNR波動越小越好。

x264中碼率控制的流程(對于重點函數在下面有注釋):

1.在進行編碼時,Encode--->x264_encoder_open(主要是進行參數的修訂設定,進行初始化)---->x264_ratecontrol_new

2.encode--->Encode_frame--->x264_encoder_encode--->x264_ratecontrol_slice_type

3.encode--->Encode_frame--->x264_encoder_encode--->x264_ratecontrol_start**************

4.encode--->Encode_frame--->x264_encoder_encode--->x264_ratecontrol_qp

5.encode--->Encode_frame--->x264_encoder_encode--->x264_slices_write--->x264_slice_write

--->x264_ratecontrol_mb********************

6.encode--->Encode_frame--->x264_encoder_encode--->x264_ratecontrol_end(在編完一幀過後)

7.在編完過後,encode--->x264_encoder_close---->ratecontrol summary/x264_ratecontrol_delete

函數注釋:

在編碼中所用的編碼方式:

#define X264_RC_CQP                  0

#define X264_RC_CRF                  1

#define X264_RC_ABR                  2

1.

x264_ratecontrol_new( x264_t *h )

{   // 擷取RC方式,FPS,bitrate,rc->buffer_rate,rc->buffer_size

// 在碼率控制的時候會出現2pass,參數的初始化

rc = h->rc;

rc->b_abr = h->param.rc.i_rc_method != X264_RC_CQP && !h->param.rc.b_stat_read;

rc->b_2pass = h->param.rc.i_rc_method == X264_RC_ABR && h->param.rc.b_stat_read;

..........

if( h->param.rc.b_mb_tree )//這裡設定mb_tree

{

h->param.rc.f_pb_factor = 1;

rc->qcompress = 1;

}

else

rc->qcompress = h->param.rc.f_qcompress;

..............

rc->ip_offset = 6.0 * log(h->param.rc.f_ip_factor) / log(2.0);

rc->pb_offset = 6.0 * log(h->param.rc.f_pb_factor) / log(2.0);

rc->qp_constant[SLICE_TYPE_P] = h->param.rc.i_qp_constant;

rc->qp_constant[SLICE_TYPE_I] = x264_clip3( h->param.rc.i_qp_constant - rc->ip_offset + 0.5, 0, 51 );

rc->qp_constant[SLICE_TYPE_B] = x264_clip3( h->param.rc.i_qp_constant + rc->pb_offset + 0.5, 0, 51 );

}

2.

int x264_ratecontrol_slice_type( x264_t *h, int frame_num )

{

//根據不同類型來擷取不同的qp_constant

h->param.rc.i_qp_constant = (h->stat.i_frame_count[SLICE_TYPE_P] == 0) ? 24

: 1 + h->stat.f_frame_qp[SLICE_TYPE_P] / h->stat.i_frame_count[SLICE_TYPE_P];

rc->qp_constant[SLICE_TYPE_P] = x264_clip3( h->param.rc.i_qp_constant, 0, 51 );

rc->qp_constant[SLICE_TYPE_I] = x264_clip3( (int)( qscale2qp( qp2qscale( h->param.rc.i_qp_constant ) / fabs( h->param.rc.f_ip_factor )) + 0.5 ), 0, 51 );

rc->qp_constant[SLICE_TYPE_B] = x264_clip3( (int)( qscale2qp( qp2qscale( h->param.rc.i_qp_constant ) * fabs( h->param.rc.f_pb_factor )) + 0.5 ), 0, 51 );

}

3.

x264_ratecontrol_start( h, h->fenc->i_qpplus1, overhead*8 );

這個函數的目的就是在一幀的編碼前就選擇QP

x264_ratecontrol_start( h, h->fenc->i_qpplus1, overhead*8 );

對x264_ratecontrol_start函數的解析如下:

x264_zone_t *zone = get_zone( h, h->fenc->i_frame );//找到h->fenc->i_frame所在的zone

....................

//由各種不同的slice類型,vbv等等參數擷取的q值

if( i_force_qp )

{

q = i_force_qp - 1;//

}

else if( rc->b_abr )

{

q = qscale2qp( rate_estimate_qscale( h ) );//下面有注解

}

else if( rc->b_2pass )

{

rce->new_qscale = rate_estimate_qscale( h );

q = qscale2qp( rce->new_qscale );

}

else

{

if( h->sh.i_type == SLICE_TYPE_B && h->fdec->b_kept_as_ref )

q = ( rc->qp_constant[ SLICE_TYPE_B ] + rc->qp_constant[ SLICE_TYPE_P ] ) / 2;

else

q = rc->qp_constant[ h->sh.i_type ];

if( zone )

{

if( zone->b_force_qp )

q += zone->i_qp - rc->qp_constant[SLICE_TYPE_P];

else

q -= 6*log(zone->f_bitrate_factor)/log(2);

}

//

static inline double qp2qscale(double qp)

{

return 0.85 * pow(2.0, ( qp - 12.0 ) / 6.0);

}

static inline double qscale2qp(double qscale)

{

return 12.0 + 6.0 * log(qscale/0.85) / log(2.0);

}

rate_estimate_qscale( h )

// update qscale for 1 frame based on actual bits used so far(即根據所需BIT來計算qscale)

static float rate_estimate_qscale( x264_t *h )

{

//這裡是分别針對B,P幀分别進行,因為I幀是已經設定

if( pict_type == SLICE_TYPE_B )

{

//這裡B幀的q的大小是由參考幀求的

.....................

.....................

// 由predict_size獲得幀的size

rcc->frame_size_planned = predict_size( rcc->pred_b_from_p, q, h->fref1[h->i_ref1-1]->i_satd );

x264_ratecontrol_set_estimated_size(h, rcc->frame_size_planned);

//

void x264_ratecontrol_set_estimated_size( x264_t *h, int bits )

{

x264_pthread_mutex_lock( &h->fenc->mutex );

h->rc->frame_size_estimated = bits;//

int x264_ratecontrol_end( x264_t *h, int bits )

{

///統計ipb類型的Mb的個數,并計算平均QP

h->fdec->f_qp_avg_rc = rc->qpa_rc /= h->mb.i_mb_count;

h->fdec->f_qp_avg_aq = rc->qpa_aq /= h->mb.i_mb_count;

}

7.

void x264_ratecontrol_summary( x264_t *h )

{

x264_ratecontrol_t *rc = h->rc;

//ABR

if( rc->b_abr && h->param.rc.i_rc_method == X264_RC_ABR && rc->cbr_decay > .9999 )

{

double base_cplx = h->mb.i_mb_count * (h->param.i_bframe ? 120 : 80);

double mbtree_offset = h->param.rc.b_mb_tree ? (1.0-h->param.rc.f_qcompress)*13.5 : 0;

x264_log( h, X264_LOG_INFO, "final ratefactor: %.2f\n",

qscale2qp( pow( base_cplx, 1 - rc->qcompress )

* rc->cplxr_sum / rc->wanted_bits_window ) - mbtree_offset );

}

}

/

void x264_ratecontrol_delete( x264_t *h )///釋放RC開辟的空間

通過以上的流程總結x264碼率控制的過程基本是有以下三步:

1.對碼率控制的相關變量進行初始化,如,I,P,B的初始QP值,RC的方式,VBV的初始狀态等等;

2.擷取編碼幀的複雜度,x264用SATD表示,對于采用的不同參數的碼率控制的方式,由前面已編碼的Bits,複雜度,目标比特的設定等一些條件來擷取編碼目前幀的qp值。

3.在編碼過程中,由獲得qp值得到預測的bits;

實驗部分:

1.簡單參數設定:

參數設定:

--frames 10 --qp 26 -o test.264 F:\.......\akiyo_qcif.yuv 176x144

其他的參數采用預設設定(在預設設定時采用的碼率控制模型是X264_RC_CQP),所得的實驗結果:

x264 [info]: 176x144 @ 25.00 fps

x264 [info]: using cpu capabilities: MMX2 SSE2 Cache64 Slow_mod4_stack

x264 [info]: profile High, level 1.1

x264 [info]: frame I:1     Avg QP:23.00  size:  4189

x264 [info]: frame P:3     Avg QP:26.00  size:    62

x264 [info]: frame B:6     Avg QP:28.00  size:    38

x264 [info]: consecutive B-frames: 11.1%  0.0%  0.0% 88.9%

x264 [info]: mb I  I16..4:  3.0% 41.4% 55.6%

x264 [info]: mb P  I16..4:  0.0%  0.0%  0.0%  P16..4:  3.0%  1.3%  1.7%  0.0%  0

.0%    skip:93.9%

x264 [info]: mb B  I16..4:  0.0%  0.0%  0.0%  B16..8:  4.4%  0.2%  0.3%  direct:

0.7%  skip:94.4%  L0:56.0% L1:40.5% BI: 3.4%

x264 [info]: 8x8 transform intra:41.4% inter:25.9%

x264 [info]: coded y,uvDC,uvAC intra: 83.6% 81.8% 68.7% inter: 1.1% 0.1% 0.0%

x264 [info]: i16 v,h,dc,p: 100%  0%  0%  0%

x264 [info]: i8 v,h,dc,ddl,ddr,vr,hd,vl,hu: 25% 30% 15%  4%  4%  4%  7%  5%  6%

x264 [info]: i4 v,h,dc,ddl,ddr,vr,hd,vl,hu: 35% 18%  8%  5%  5% 10%  5%  8%  6%

x264 [info]: ref P L0: 88.9%  0.0% 11.1%

x264 [info]: kb/s:92.08

encoded 10 frames, 24.33 fps, 92.08 kb/s

2.改變碼率控制的模型:

--frames 10 --qp 26 --crf 2 -o test.264 F:\......\akiyo_qcif.yuv 176x144

x264 [info]: 176x144 @ 25.00 fps

x264 [info]: using cpu capabilities: MMX2 SSE2 Cache64 Slow_mod4_stack

x264 [info]: profile High, level 1.1

x264 [info]: frame I:1     Avg QP:10.00  size: 10246

x264 [info]: frame P:3     Avg QP:11.48  size:   847

x264 [info]: frame B:6     Avg QP:12.10  size:   172

x264 [info]: consecutive B-frames: 11.1%  0.0%  0.0% 88.9%

x264 [info]: mb I  I16..4:  1.0% 44.4% 54.5%

x264 [info]: mb P  I16..4:  0.0%  0.0%  0.0%  P16..4: 30.0%  3.0%  4.7%  0.0%  0

.0%    skip:62.3%

x264 [info]: mb B  I16..4:  0.0%  0.0%  0.0%  B16..8:  6.9%  1.0%  1.2%  direct:

4.0%  skip:86.9%  L0:34.7% L1:55.6% BI: 9.7%

x264 [info]: 8x8 transform intra:44.4% inter:34.8%

x264 [info]: coded y,uvDC,uvAC intra: 100.0% 99.0% 94.9% inter: 11.6% 7.6% 4.9%

x264 [info]: i16 v,h,dc,p: 100%  0%  0%  0%

x264 [info]: i8 v,h,dc,ddl,ddr,vr,hd,vl,hu: 30% 33% 16%  3%  2%  3%  4%  4%  5%

x264 [info]: i4 v,h,dc,ddl,ddr,vr,hd,vl,hu: 28% 12% 11%  5%  7% 11%  6% 12%  8%

x264 [info]: ref P L0: 95.8%  1.6%  2.7%

x264 [info]: ref B L0: 96.3%  3.7%

x264 [info]: kb/s:276.36

encoded 10 frames, 14.27 fps, 276.36 kb/s

針對1,2兩個實驗,所采用的RC模型不一樣,1:X264_RC_CQP,2:X264_RC_CRF,其他參數的設定一樣,從IPB的平均QP,編碼Bits可以看出和對于實際的應用來說,CRF的效果不如CQP。

3.

--frames 10 --qp 26 --pass 1 -o test.264 F:\.....\bin\akiyo_qcif.yuv 176x144

x264 [info]: 176x144 @ 25.00 fps

x264 [info]: using cpu capabilities: MMX2 SSE2 Cache64 Slow_mod4_stack

x264 [info]: profile Main, level 1.1

x264 [info]: frame I:1     Avg QP:23.00  size:  4068

x264 [info]: frame P:3     Avg QP:26.00  size:    59

x264 [info]: frame B:6     Avg QP:28.00  size:    31

x264 [info]: consecutive B-frames: 11.1%  0.0%  0.0% 88.9%

x264 [info]: mb I  I16..4: 15.2%  0.0% 84.8%

x264 [info]: mb P  I16..4:  0.0%  0.0%  0.0%  P16..4:  7.1%  0.0%  0.0%  0.0%  0

.0%    skip:92.9%

x264 [info]: mb B  I16..4:  0.0%  0.0%  0.0%  B16..8:  1.2%  0.0%  0.0%  direct:

1.5%  skip:97.3%  L0:100.0% L1: 0.0% BI: 0.0%

x264 [info]: coded y,uvDC,uvAC intra: 87.4% 77.8% 68.7% inter: 1.1% 0.1% 0.0%

x264 [info]: i16 v,h,dc,p: 47% 20% 27%  7%

x264 [info]: i4 v,h,dc,ddl,ddr,vr,hd,vl,hu: 29% 27% 10%  5%  4%  8%  5%  6%  5%

x264 [info]: kb/s:88.58

encoded 10 frames, 52.63 fps, 88.58 kb/s

4.

--frames 10 --qp 26 --pass 2 -o test.264 F:\.....\bin\akiyo_qcif.yuv 176x144

x264 [info]: 176x144 @ 25.00 fps

x264 [info]: using cpu capabilities: MMX2 SSE2 Cache64 Slow_mod4_stack

x264 [info]: profile High, level 1.1

x264 [info]: frame I:1     Avg QP:23.00  size:  4189

x264 [info]: frame P:3     Avg QP:26.00  size:    62

x264 [info]: frame B:6     Avg QP:28.00  size:    38

x264 [info]: consecutive B-frames: 11.1%  0.0%  0.0% 88.9%

x264 [info]: mb I  I16..4:  3.0% 41.4% 55.6%

x264 [info]: mb P  I16..4:  0.0%  0.0%  0.0%  P16..4:  3.0%  1.3%  1.7%  0.0%  0

.0%    skip:93.9%

x264 [info]: mb B  I16..4:  0.0%  0.0%  0.0%  B16..8:  4.4%  0.2%  0.3%  direct:

0.7%  skip:94.4%  L0:56.0% L1:40.5% BI: 3.4%

x264 [info]: 8x8 transform intra:41.4% inter:25.9%

x264 [info]: coded y,uvDC,uvAC intra: 83.6% 81.8% 68.7% inter: 1.1% 0.1% 0.0%

x264 [info]: i16 v,h,dc,p: 100%  0%  0%  0%

x264 [info]: i8 v,h,dc,ddl,ddr,vr,hd,vl,hu: 25% 30% 15%  4%  4%  4%  7%  5%  6%

x264 [info]: i4 v,h,dc,ddl,ddr,vr,hd,vl,hu: 35% 18%  8%  5%  5% 10%  5%  8%  6%

x264 [info]: ref P L0: 88.9%  0.0% 11.1%

x264 [info]: kb/s:92.08

encoded 10 frames, 27.70 fps, 92.08 kb/s

5.

--frames 10 --qp 26 --pass 3 -o test.264 F:\.....\bin\akiyo_qcif.yuv 176x144

x264 [info]: 176x144 @ 25.00 fps

x264 [info]: using cpu capabilities: MMX2 SSE2 Cache64 Slow_mod4_stack

x264 [info]: profile High, level 1.1

x264 [info]: frame I:1     Avg QP:23.00  size:  4189

x264 [info]: frame P:3     Avg QP:26.00  size:    62

x264 [info]: frame B:6     Avg QP:28.00  size:    38

x264 [info]: consecutive B-frames: 11.1%  0.0%  0.0% 88.9%

x264 [info]: mb I  I16..4:  3.0% 41.4% 55.6%

x264 [info]: mb P  I16..4:  0.0%  0.0%  0.0%  P16..4:  3.0%  1.3%  1.7%  0.0%  0

.0%    skip:93.9%

x264 [info]: mb B  I16..4:  0.0%  0.0%  0.0%  B16..8:  4.4%  0.2%  0.3%  direct:

0.7%  skip:94.4%  L0:56.0% L1:40.5% BI: 3.4%

x264 [info]: 8x8 transform intra:41.4% inter:25.9%

x264 [info]: coded y,uvDC,uvAC intra: 83.6% 81.8% 68.7% inter: 1.1% 0.1% 0.0%

x264 [info]: i16 v,h,dc,p: 100%  0%  0%  0%

x264 [info]: i8 v,h,dc,ddl,ddr,vr,hd,vl,hu: 25% 30% 15%  4%  4%  4%  7%  5%  6%

x264 [info]: i4 v,h,dc,ddl,ddr,vr,hd,vl,hu: 35% 18%  8%  5%  5% 10%  5%  8%  6%

x264 [info]: ref P L0: 88.9%  0.0% 11.1%

x264 [info]: kb/s:92.08

encoded 10 frames, 25.64 fps, 92.08 kb/s

對于3,4,5是關于Pass的實驗比較:

多次壓縮碼率控制

1:第一次壓縮,建立統計檔案

2:按建立的統計檔案壓縮并輸出,不覆寫統計檔案,

3:按建立的統計檔案壓縮,優化統計檔案

在想得到建好的效果的時候采用pass 2就可以了。

6.

--frames 10 --qp 26 --bitrate 64 -o test.264 F:\.....\bin\akiyo_qcif.yuv 176x144

x264 [info]: 176x144 @ 25.00 fps

x264 [info]: using cpu capabilities: MMX2 SSE2 Cache64 Slow_mod4_stack

x264 [info]: profile High, level 1.1

x264 [info]: frame I:1     Avg QP:38.31  size:  1461

x264 [info]: frame P:3     Avg QP:42.00  size:    18

x264 [info]: frame B:6     Avg QP:45.00  size:    14

x264 [info]: consecutive B-frames: 11.1%  0.0%  0.0% 88.9%

x264 [info]: mb I  I16..4: 15.2% 68.7% 16.2%

x264 [info]: mb P  I16..4:  0.0%  0.0%  0.0%  P16..4:  2.0%  0.0%  0.3%  0.0%  0

.0%    skip:97.6%

x264 [info]: mb B  I16..4:  0.0%  0.0%  0.0%  B16..8:  0.2%  0.0%  0.0%  direct:

0.0%  skip:99.8%  L0: 0.0% L1:100.0% BI: 0.0%

x264 [info]: final ratefactor: 31.50

x264 [info]: 8x8 transform intra:68.7%

x264 [info]: coded y,uvDC,uvAC intra: 48.0% 61.6% 32.3% inter: 0.0% 0.0% 0.0%

x264 [info]: i16 v,h,dc,p: 33% 47%  7% 13%

x264 [info]: i8 v,h,dc,ddl,ddr,vr,hd,vl,hu: 35% 17% 20%  3%  4%  7%  3%  7%  5%

x264 [info]: i4 v,h,dc,ddl,ddr,vr,hd,vl,hu: 50% 14%  8%  5%  5%  5%  3%  6%  4%

x264 [info]: kb/s:31.94

encoded 10 frames, 31.25 fps, 31.94 kb/s

7.

--frames 250 --qp 26 --bitrate 64 -o test.264 F:\.....\bin\akiyo_qcif.yuv 176x144

x264 [info]: 176x144 @ 25.00 fps

x264 [info]: using cpu capabilities: MMX2 SSE2 Cache64 Slow_mod4_stack

x264 [info]: profile High, level 1.1

x264 [info]: frame I:1     Avg QP:34.62  size:  1779

x264 [info]: frame P:92    Avg QP:19.81  size:   569

x264 [info]: frame B:157   Avg QP:26.76  size:    53

x264 [info]: consecutive B-frames: 15.7%  0.0%  2.4% 81.9%

x264 [info]: mb I  I16..4: 14.1% 61.6% 24.2%

x264 [info]: mb P  I16..4:  0.0%  0.0%  0.0%  P16..4: 25.8%  9.4%  9.9%  0.0%  0

.0%    skip:54.8%

x264 [info]: mb B  I16..4:  0.0%  0.0%  0.0%  B16..8: 13.9%  0.7%  1.4%  direct:

1.1%  skip:83.0%  L0:16.6% L1:72.1% BI:11.3%

x264 [info]: final ratefactor: 18.97

x264 [info]: 8x8 transform intra:61.5% inter:40.4%

x264 [info]: coded y,uvDC,uvAC intra: 61.3% 65.4% 34.6% inter: 8.6% 6.8% 2.8%

x264 [info]: i16 v,h,dc,p: 57% 43%  0%  0%

x264 [info]: i8 v,h,dc,ddl,ddr,vr,hd,vl,hu: 32% 22% 18%  4%  2%  7%  3%  7%  4%

x264 [info]: i4 v,h,dc,ddl,ddr,vr,hd,vl,hu: 45% 10% 10%  5%  6%  7%  6%  6%  5%

x264 [info]: ref P L0: 87.6%  7.6%  4.8%

x264 [info]: ref B L0: 95.0%  5.0%

x264 [info]: kb/s:49.92

encoded 250 frames, 16.74 fps, 49.92 kb/s

6,7是針對不同的編碼幀數來進行比較的,在編碼幀數越多,帶寬利用的效果就越好。

6,7是在設定了目标碼率64kp/s時,采用的是ABR的RC模型,在設定了目标碼率能夠根據目标碼率的大小改變QP大小,能夠控制碼率。

繼續閱讀