文档章节

x264 slicetype 选定中的x264_lowres_context_init函数分析

貌似高手
 貌似高手
发布于 2017/04/25 12:18
字数 1703
阅读 46
收藏 0
点赞 0
评论 0

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]

 

 

 

© 著作权归作者所有

共有 人打赏支持
貌似高手
粉丝 8
博文 60
码字总数 59033
作品 0
海淀
高级程序员
x264源代码简单分析:编码器主干部分-2

===================================================== H.264源代码分析文章列表: 【编码 - x264】 x264源代码简单分析:概述 x264源代码简单分析:x264命令行工具(x264.exe) x264源代码...

leixiaohua1020 ⋅ 2015/05/14 ⋅ 0

音视频技术--H.264代码与标准如何对应

总是有人说自己把代码和标准对应不起来。其实是因为你要么不知道标准各个章节讲的什么,要么不知道代码中各个函数的功能,或者两者都不知道。今天再以 X264 的帧内编码为例让大家体会一下读代...

技术小阿哥 ⋅ 2017/11/27 ⋅ 0

x264源代码简单分析:概述

===================================================== H.264源代码分析文章列表: 【编码 - x264】 x264源代码简单分析:概述 x264源代码简单分析:x264命令行工具(x264.exe) x264源代码...

leixiaohua1020 ⋅ 2015/05/06 ⋅ 0

x264源代码简单分析:编码器主干部分-1

===================================================== H.264源代码分析文章列表: 【编码 - x264】 x264源代码简单分析:概述 x264源代码简单分析:x264命令行工具(x264.exe) x264源代码...

leixiaohua1020 ⋅ 2015/05/11 ⋅ 0

x264源代码简单分析:宏块分析(Analysis)部分-帧内宏块(Intra)

===================================================== H.264源代码分析文章列表: 【编码 - x264】 x264源代码简单分析:概述 x264源代码简单分析:x264命令行工具(x264.exe) x264源代码...

leixiaohua1020 ⋅ 2015/05/22 ⋅ 0

x264源代码简单分析:宏块编码(Encode)部分

===================================================== H.264源代码分析文章列表: 【编码 - x264】 x264源代码简单分析:概述 x264源代码简单分析:x264命令行工具(x264.exe) x264源代码...

leixiaohua1020 ⋅ 2015/05/24 ⋅ 0

x264源代码简单分析:宏块分析(Analysis)部分-帧间宏块(Inter)

===================================================== H.264源代码分析文章列表: 【编码 - x264】 x264源代码简单分析:概述 x264源代码简单分析:x264命令行工具(x264.exe) x264源代码...

leixiaohua1020 ⋅ 2015/05/23 ⋅ 0

x264源代码简单分析:滤波(Filter)部分

===================================================== H.264源代码分析文章列表: 【编码 - x264】 x264源代码简单分析:概述 x264源代码简单分析:x264命令行工具(x264.exe) x264源代码...

leixiaohua1020 ⋅ 2015/05/20 ⋅ 0

x264源代码简单分析:x264命令行工具(x264.exe)

===================================================== H.264源代码分析文章列表: 【编码 - x264】 x264源代码简单分析:概述 x264源代码简单分析:x264命令行工具(x264.exe) x264源代码...

leixiaohua1020 ⋅ 2015/05/08 ⋅ 0

x264源代码简单分析:熵编码(Entropy Encoding)部分

===================================================== H.264源代码分析文章列表: 【编码 - x264】 x264源代码简单分析:概述 x264源代码简单分析:x264命令行工具(x264.exe) x264源代码...

leixiaohua1020 ⋅ 2015/05/24 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

RabbitMQ学习以及与Spring的集成(三)

本文介绍RabbitMQ与Spring的简单集成以及消息的发送和接收。 在RabbitMQ的Spring配置文件中,首先需要增加命名空间。 xmlns:rabbit="http://www.springframework.org/schema/rabbit" 其次是模...

onedotdot ⋅ 27分钟前 ⋅ 0

JAVA实现仿微信红包分配规则

最近过年发红包拜年成为一种新的潮流,作为程序猿对算法的好奇远远要大于对红包的好奇,这里介绍一种自己想到的一种随机红包分配策略,还请大家多多指教。 算法介绍 一、红包金额限制 对于微...

小致dad ⋅ 38分钟前 ⋅ 0

Python 数电表格格式化 xlutils xlwt xlrd的使用

需要安装 xlutils xlwt xlrd 格式化前 格式化后 代码 先copy读取的表格,然后按照一定的规则修改,将昵称中的学号提取出来替换昵称即可 from xlrd import open_workbookfrom xlutils.copy ...

阿豪boy ⋅ 今天 ⋅ 0

面试题:使用rand5()生成rand7()

前言 读研究生这3 年,思维与本科相比变化挺大的,这几年除了看论文、设计方案,更重要的是学会注重先思考、再实现,感觉更加成熟吧,不再像个小P孩,人年轻时总会心高气傲。有1 道面试题:给...

初雪之音 ⋅ 今天 ⋅ 0

Docker Toolbox Looks like something went wrong

Docker Toolbox 重新安装后提示错误:Looks like something went wrong in step ´Checking if machine default exists´ 控制面板-->程序与应用-->启用或关闭windows功能:找到Hyper-V,如果处......

随你疯 ⋅ 今天 ⋅ 0

Guacamole 远程桌面

本文将Apache的guacamole服务的部署和应用,http://guacamole.apache.org/doc/gug/ 该链接下有全部相关知识的英文文档,如果水平ok,可以去这里仔细查看。 一、简介 Apache Guacamole 是无客...

千里明月 ⋅ 今天 ⋅ 0

nagios 安装

Nagios简介:监控网络并排除网络故障的工具:nagios,Ntop,OpenVAS,OCS,OSSIM等开源监控工具。 可以实现对网络上的服务器进行全面的监控,包括服务(apache、mysql、ntp、ftp、disk、qmail和h...

寰宇01 ⋅ 今天 ⋅ 0

AngularDart注意事项

默认情况下创建Dart项目应出现以下列表: 有时会因为不知明的原因导致列表项缺失: 此时可以通过以下步骤解决: 1.创建项目涉及到的包:stagehand 2.执行pub global activate stagehand或pub...

scooplol ⋅ 今天 ⋅ 0

Java Web如何操作Cookie的添加修改和删除

创建Cookie对象 Cookie cookie = new Cookie("id", "1"); 修改Cookie值 cookie.setValue("2"); 设置Cookie有效期和删除Cookie cookie.setMaxAge(24*60*60); // Cookie有效时间 co......

二营长意大利炮 ⋅ 今天 ⋅ 0

【每天一个JQuery特效】淡入淡出显示或隐藏窗口

我是JQuery新手爱好者,有时间就练练代码,防止手生,争取每天一个JQuery练习,在这个博客记录下学习的笔记。 本特效主要采用fadeIn()和fadeOut()方法显示淡入淡出的显示效果显示或隐藏元...

Rhymo-Wu ⋅ 今天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部