x264 slicetype 选定中的x264_lowres_context_init函数分析
x264 slicetype 选定中的x264_lowres_context_init函数分析
貌似高手 发表于8个月前
x264 slicetype 选定中的x264_lowres_context_init函数分析
  • 发表于 8个月前
  • 阅读 38
  • 收藏 0
  • 点赞 0
  • 评论 0

腾讯云 新注册用户 域名抢购1元起>>>   

x264 的码率控制算法符合h264 标准:

               1,先通过线性回归的方法确定微调qp,然后推算出lambda(mode) ,lambda(motion) .

               2,从最近的已经确定slicetype 的last_none_B_frame 开始搜索 Lookahead+3 (default value is 40+3)  个没有确定slicetype 的待编码帧,确定后续的帧slicetype.

               3,slicetype 的确定是通过拉格朗日代价函数(拉格朗日乘数:求限制条件下的极值的代数方法,线代中

的梯度方向都是一个原理),平衡RDO(率失真优化).

               4,通过VBV等RC算法微调更新 RC信息,用于线性回归

 总结:lookahead 的slicetype决策过程可以简化为,构建庞大的cost_mv 表,cost_ref 表, cost_i4x4_mode 表 

,然后根据具体的qp,mv 查表,以及通过STAD估算残差编码的cost得出 RD 函数.

下面是slicetype 确定过程中的一个关键函数,这个函数初始化编码过程中mv_cost,mode_cost,ref_cost,residual_cost  等代价的,为了平衡计算量和准确性,x264中通过downscaling 获取原始帧1/2 的分辨率的像素进行cost计算.

x264_lowres_context_init( h, &a );

上述函数的调用者是:

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]

 

 

 

标签: x264 h264
共有 人打赏支持
粉丝 9
博文 48
码字总数 49208
×
貌似高手
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: