x264 slicetype 選定中的x264_lowres_context_init函數分析

x264 的碼率控制算法符合h264 標準:算法

               1,先經過線性迴歸的方法肯定微調qp,而後推算出lambda(mode) ,lambda(motion) .express

               2,從最近的已經肯定slicetype 的last_none_B_frame 開始搜索 Lookahead+3 (default value is 40+3)  個沒有肯定slicetype 的待編碼幀,肯定後續的幀slicetype.c#

               3,slicetype 的肯定是經過拉格朗日代價函數(拉格朗日乘數:求限制條件下的極值的代數方法,線代中app

的梯度方向都是一個原理),平衡RDO(率失真優化).函數

               4,經過VBV等RC算法微調更新 RC信息,用於線性迴歸優化

 總結:lookahead 的slicetype決策過程能夠簡化爲,構建龐大的cost_mv 表,cost_ref 表, cost_i4x4_mode 表 ui

,而後根據具體的qp,mv 查表,以及經過STAD估算殘差編碼的cost得出 RD 函數.編碼

下面是slicetype 肯定過程當中的一個關鍵函數,這個函數初始化編碼過程當中mv_cost,mode_cost,ref_cost,residual_cost  等代價的,爲了平衡計算量和準確性,x264中經過downscaling 獲取原始幀1/2 的分辨率的像素進行cost計算.spa

x264_lowres_context_init( h, &a );

上述函數的調用者是:code

void x264_slicetype_analyse( x264_t *h, int intra_minigop )

具體的x264_slicetype_analyse調用堆棧是:

詳解一下/x264/encoder/slicetype.c :264_lowres_context_init( x264_t *h, x264_mb_analysis_t *a ) 

51  static void x264_lowres_context_init( x264_t *h, x264_mb_analysis_t *a )
52  {
53      a->i_qp = X264_LOOKAHEAD_QP;// 1,得到當前的肯定的qp
54      a->i_lambda = x264_lambda_tab[ a->i_qp ];//2,經過qp 查表獲得lambda
55      x264_mb_analyse_load_costs( h, a );// 3,加載編碼中固定的cost table,
56      if( h->param.analyse.i_subpel_refine > 1 )
57      {
58          h->mb.i_me_method = X264_MIN( X264_ME_HEX, h->param.analyse.i_me_method );
59          h->mb.i_subpel_refine = 4;
60      }
61      else
62      {
63          h->mb.i_me_method = X264_ME_DIA;
64          h->mb.i_subpel_refine = 2;
65      }
66      h->mb.b_chroma_me = 0;
67  }

 

詳解一下   a->i_lambda = x264_lambda_tab[ a->i_qp ];//2,經過qp 查表獲得lambda

源文件:x264/encoder/analyse.c#141

x264 中qp 和lamda 成指數關係,lambda(mode)和lambda(motion) 在intra 和 inter 下數量關係不一樣.

總結:  經過 RDO(i) = D(i) + lambda*R(i)  公式,把lambda*R(i) 做爲懲戒函數,咱們能夠看出h264 標準中在第i個MB  預測類型爲inter 的時候懲戒力度更小.鼓勵P,B 幀.

/* lambda = pow(2,qp/6-2) */
140  /* liyl add:h264 standard: if(intra) {lambda(motion) = lambda(mode)  }else {lambda(motion) = log2(lambda(mode))}*/
141  const uint16_t x264_lambda_tab[QP_MAX_MAX+1] =
142  {
143     1,   1,   1,   1,   1,   1,   1,   1, /*  0- 7 */
144     1,   1,   1,   1,   1,   1,   1,   1, /*  8-15 */
145     2,   2,   2,   2,   3,   3,   3,   4, /* 16-23 */
146     4,   4,   5,   6,   6,   7,   8,   9, /* 24-31 */
147    10,  11,  13,  14,  16,  18,  20,  23, /* 32-39 */
148    25,  29,  32,  36,  40,  45,  51,  57, /* 40-47 */
149    64,  72,  81,  91, 102, 114, 128, 144, /* 48-55 */
150   161, 181, 203, 228, 256, 287, 323, 362, /* 56-63 */
151   406, 456, 512, 575, 645, 724, 813, 912, /* 64-71 */
152  1024,1149,1290,1448,1625,1825,2048,2299, /* 72-79 */
153  2048,2299,                               /* 80-81 */
154  };
155  
156  /* lambda2 = pow(lambda,2) * .9 * 256 */
157  /* Capped to avoid overflow */
158  /* liyl add:h264 standard: lambda(mode) = 0.85*2^((q-12)/3) <==> lambda2 */
159  const int x264_lambda2_tab[QP_MAX_MAX+1] =
160  {
161         14,       18,       22,       28,       36,       45,      57,      72, /*  0- 7 */
162         91,      115,      145,      182,      230,      290,     365,     460, /*  8-15 */
163        580,      731,      921,     1161,     1462,     1843,    2322,    2925, /* 16-23 */
164       3686,     4644,     5851,     7372,     9289,    11703,   14745,   18578, /* 24-31 */
165      23407,    29491,    37156,    46814,    58982,    74313,   93628,  117964, /* 32-39 */
166     148626,   187257,   235929,   297252,   374514,   471859,  594505,  749029, /* 40-47 */
167     943718,  1189010,  1498059,  1887436,  2378021,  2996119, 3774873, 4756042, /* 48-55 */
168    5992238,  7549747,  9512085, 11984476, 15099494, 19024170,23968953,30198988, /* 56-63 */
169   38048341, 47937906, 60397977, 76096683, 95875813,120795955,                   /* 64-69 */
170  134217727,134217727,134217727,134217727,134217727,134217727,                   /* 70-75 */
171  134217727,134217727,134217727,134217727,134217727,134217727,                   /* 76-81 */
172  };

 

詳解x264_mb_analyse_load_costs( h, a );// 3,加載編碼中固定的cost table

x264/encoder/analyse.c#376

375  /* initialize an array of lambda*nbits for all possible mvs */
376  static void x264_mb_analyse_load_costs( x264_t *h, x264_mb_analysis_t *a )
377  {
378  	//cost_mv = lambda(motion)*Golomb_compress_rate[mv_length]
379      a->p_cost_mv = h->cost_mv[a->i_qp]; //1,得到不一樣mv SE()編碼以後的nbit*lambda(motion)
380      a->p_cost_ref[0] = x264_cost_ref[a->i_qp][x264_clip3(h->sh.i_num_ref_idx_l0_active-1,0,2)];
381      a->p_cost_ref[1] = x264_cost_ref[a->i_qp][x264_clip3(h->sh.i_num_ref_idx_l1_active-1,0,2)];
          //2, 得到先後參考幀index diff TE()編碼以後的nbit*lambda(motion) 
382  }
383  

 

1,詳談h->cost_mv[a->i_qp] 

379      a->p_cost_mv = h->cost_mv[a->i_qp];
x264/common/common.h#576
497  struct x264_t
498  {
       ....
575      /* mv/ref cost arrays. */
576      uint16_t *cost_mv[QP_MAX+1];
577      uint16_t *cost_mv_fpel[QP_MAX+1][4];

cost_mv 的初始化:

299  int x264_analyse_init_costs( x264_t *h, float *logs, int qp )
300  {
301      int lambda = x264_lambda_tab[qp];
302      if( h->cost_mv[qp] )
303          return 0;
304      /* factor of 4 from qpel, 2 from sign, and 2 because mv can be opposite from mvp */
305      CHECKED_MALLOC( h->cost_mv[qp], (4*4*2048 + 1) * sizeof(uint16_t) );
306      h->cost_mv[qp] += 2*4*2048;
307      for( int i = 0; i <= 2*4*2048; i++ )//分辨率爲2048x2048 * 4(1/4 pixel) * 2(mvh mvv) *2(p0,p1)
308      {
309          h->cost_mv[qp][-i] =
310          h->cost_mv[qp][i]  = X264_MIN( lambda * logs[i] + .5f, (1<<16)-1 );
311      }

logs[i] 是SE 的消耗的nbit

284  //init cost of SE() and UE()
285  float *x264_analyse_prepare_costs( x264_t *h )
286  {
287      float *logs = x264_malloc( (2*4*2048+1)*sizeof(float) );
288      if( !logs )
289          return NULL;
290      logs[0] = 0.718f;
291      for( int i = 1; i <= 2*4*2048; i++ )
292          logs[i] = log2f(i+1)*2 + 1.718f;
293  	//TODO FIXED ME:Speculation about the compression ratio of the Colombo encoding (the inverse function of the range of the expression of the Colombo code);
294  	//the range of the expression of the Colomb code is [2^(q+m)-2^m , 2^(q+m+1)-2^m-1]
295  
296      return logs;
297  }

 

2,詳談cost_ref

x264_cost_ref[a->i_qp][x264_clip3(h->sh.i_num_ref_idx_l0_active-1,0,2)
/x264/encoder/analyse.c
280  static uint16_t x264_cost_ref[QP_MAX+1][3][33];

 

 

初始化cost_mv,cost_ref,cost_i4x4_mode 這個方法是在x264_encoder_open() 的方法中調用初始化的.

 

encoder.c
1585 if( x264_analyse_init_costs( h, logs, X264_LOOKAHEAD_QP ) ) in x264_encoder_open() 

 

int x264_analyse_init_costs( x264_t *h, float *logs, int qp )
300  {
301      int lambda = x264_lambda_tab[qp]; //獲取lambda
302      if( h->cost_mv[qp] )
303          return 0;
304      /* factor of 4 from qpel, 2 from sign, and 2 because mv can be opposite from mvp */
305      CHECKED_MALLOC( h->cost_mv[qp], (4*4*2048 + 1) * sizeof(uint16_t) );
306      h->cost_mv[qp] += 2*4*2048;
307      for( int i = 0; i <= 2*4*2048; i++ )//分辨率爲2048x2048 * 4(1/4 pixel) * 2(mvh mvv) *2(p0,p1)
308      {
309          h->cost_mv[qp][-i] =
310          h->cost_mv[qp][i]  = X264_MIN( lambda * logs[i] + .5f, (1<<16)-1 );
311      }
312      x264_pthread_mutex_lock( &cost_ref_mutex );
313      for( int i = 0; i < 3; i++ )
314          for( int j = 0; j < 33; j++ )// list0,list1 中ref_index TE()編碼以後nbit*lambda
315              x264_cost_ref[qp][i][j] = X264_MIN( i ? lambda * bs_size_te( i, j ) : 0, (1<<16)-1 );
316      x264_pthread_mutex_unlock( &cost_ref_mutex );
317      if( h->param.analyse.i_me_method >= X264_ME_ESA && !h->cost_mv_fpel[qp][0] )
318      {
319          for( int j = 0; j < 4; j++ )
320          {
321              CHECKED_MALLOC( h->cost_mv_fpel[qp][j], (4*2048 + 1) * sizeof(uint16_t) );
322              h->cost_mv_fpel[qp][j] += 2*2048;
323              for( int i = -2*2048; i < 2*2048; i++ )
324                  h->cost_mv_fpel[qp][j][i] = h->cost_mv[qp][i*4+j];
325          }
326      }
327      uint16_t *cost_i4x4_mode = (uint16_t*)ALIGN((intptr_t)x264_cost_i4x4_mode,64) + qp*32;
328      for( int i = 0; i < 17; i++ )//cost_i4x4_mode= {0,0,0,0,0,0,0,0,3*lambda,...} 
329          cost_i4x4_mode[i] = 3*lambda*(i!=8);//TODO i==8==I_PRED_4x4_HU ????沒有搞明白
330      return 0;
331  fail:
332      return -1;
333  }
334  

cost_i4x4_mode  //TODO FIXED ME 

68  enum intra4x4_pred_e
69  {
70      I_PRED_4x4_V  = 0,
71      I_PRED_4x4_H  = 1,
72      I_PRED_4x4_DC = 2,
73      I_PRED_4x4_DDL= 3,
74      I_PRED_4x4_DDR= 4,
75      I_PRED_4x4_VR = 5,
76      I_PRED_4x4_HD = 6,
77      I_PRED_4x4_VL = 7,
78      I_PRED_4x4_HU = 8,
79  
80      I_PRED_4x4_DC_LEFT = 9,
81      I_PRED_4x4_DC_TOP  = 10,
82      I_PRED_4x4_DC_128  = 11,
83  };
84  static const int8_t x264_mb_pred_mode4x4_fix[13] =
85  {
86      -1,
87      I_PRED_4x4_V,   I_PRED_4x4_H,   I_PRED_4x4_DC,
88      I_PRED_4x4_DDL, I_PRED_4x4_DDR, I_PRED_4x4_VR,
89      I_PRED_4x4_HD,  I_PRED_4x4_VL,  I_PRED_4x4_HU,
90      I_PRED_4x4_DC,  I_PRED_4x4_DC,  I_PRED_4x4_DC
91  };
92  #define x264_mb_pred_mode4x4_fix(t) x264_mb_pred_mode4x4_fix[(t)+1]
相關文章
相關標籤/搜索