博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
x264 slicetype 选定中的x264_lowres_context_init函数分析
阅读量:6257 次
发布时间:2019-06-22

本文共 5970 字,大约阅读时间需要 19 分钟。

hot3.png

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 表,  表 

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

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

( h, &a );

上述函数的调用者是:

void (  *h, int  )

具体的调用堆栈是:

122346_typV_269082.png

详解一下/// :( *h, *a ) 

static void (  *h,  *a ) {     a-> = ;// 1,获得当前的确定的qp     a-> = [ a-> ];//2,通过qp 查表得到lambda     ( h, a );// 3,加载编码中固定的cost table,     if( h->.. > 1 )     {         h->. = ( , h->.. );         h->. = 4;     }     else     {         h->. = ;         h->. = 2;     }     h->. = 0; }

 

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

 

详解( h, a );// 3,加载编码中固定的cost table

x264/encoder/analyse.c#376

 /* initialize an array of lambda*nbits for all possible mvs */static void (  *h,  *a ) { 	//cost_mv = lambda(motion)*Golomb_compress_rate[mv_length]     a-> = h->[a->]; //1,获得不同mv SE()编码之后的nbit*lambda(motion)     a->[0] = [a->][(h->.-1,0,2)];     a->[1] = [a->][(h->.-1,0,2)];          //2, 获得前后参考帧index diff TE()编码之后的nbit*lambda(motion)  } 

 

1,详谈h->cost_mv[a->i_qp] 

     a-> = h->[a->];
 struct  {       ....     /* / cost arrays. */      *[+1];      *[+1][4];

cost_mv 的初始化:

int (  *h, float *, int  ) {     int  = [];     if( h->[] )         return 0;     /* factor of 4 from qpel, 2 from sign, and 2 because mv can be opposite from mvp */     ( h->[], (4*4*2048 + 1) * sizeof() );     h->[] += 2*4*2048;     for( int i = 0; i <= 2*4*2048; i++ )//分辨率为2048x2048 * 4(1/4 pixel) * 2(mvh mvv) *2(p0,p1)     {         h->[][-i] =         h->[][i]  = (  * [i] + .5f, (1<<16)-1 );     }

[i] 是SE 的消耗的nbit

 //init cost of SE() and UE()float *(  *h ) {     float * = ( (2*4*2048+1)*sizeof(float) );     if( ! )         return ;     [0] = 0.718f;     for( int i = 1; i <= 2*4*2048; i++ )         [i] = (i+1)*2 + 1.718f; 	//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); 	//the range of the expression of the Colomb code is [2^(q+m)-2^m , 2^(q+m+1)-2^m-1]      return ; }

 

2,详谈cost_ref

[a->][(h->.-1,0,2)
/// static  [+1][3][33];

 

 

初始化,, 这个方法是在 的方法中调用初始化的.

 

  

 

int (  *h, float *, int  ) {     int  = []; //获取lambda     if( h->[] )         return 0;     /* factor of 4 from qpel, 2 from sign, and 2 because mv can be opposite from mvp */     ( h->[], (4*4*2048 + 1) * sizeof() );     h->[] += 2*4*2048;     for( int i = 0; i <= 2*4*2048; i++ )//分辨率为2048x2048 * 4(1/4 pixel) * 2(mvh mvv) *2(p0,p1)     {         h->[][-i] =         h->[][i]  = (  * [i] + .5f, (1<<16)-1 );     }     ( & );     for( int i = 0; i < 3; i++ )         for( int j = 0; j < 33; j++ )// list0,list1 中ref_index TE()编码之后nbit*lambda             [][i][j] = ( i ?  * ( i, j ) : 0, (1<<16)-1 );     ( & );     if( h->.. >=  && !h->[][0] )     {         for( int j = 0; j < 4; j++ )         {             ( h->[][j], (4*2048 + 1) * sizeof() );             h->[][j] += 2*2048;             for( int i = -2*2048; i < 2*2048; i++ )                 h->[][j][i] = h->[][i*4+j];         }     }      * = (*)((),64) + *32;     for( int i = 0; i < 17; i++ )//cost_i4x4_mode= {0,0,0,0,0,0,0,0,3*,...}          [i] = 3**(i!=8);//TODO i==8== ????没有搞明白     return 0; :     return -1; } 

  //TODO FIXED ME 

 enum  {       = 0,       = 1,      = 2,     = 3,     = 4,      = 5,      = 6,      = 7,      = 8,       = 9,       = 10,       = 11, }; static const  [13] = {     -1,     ,   ,   ,     , , ,     ,  ,  ,     ,  ,   }; #define (t) [(t)+1]

 

 

 

转载于:https://my.oschina.net/u/269082/blog/886661

你可能感兴趣的文章
05 继承
查看>>
弧度和角度的转换
查看>>
[leetcode]Unique Paths II @ Python
查看>>
nginx源码分析之hash的实现
查看>>
数据结构快速回顾——二叉树 解幂子集问题
查看>>
选择排序
查看>>
使用微软 URL Rewrite Module 开启IIS伪静态
查看>>
浅谈UML中类之间的五种关系及其在代码中的表现形式
查看>>
原创:CentOS6.4配置solr 4.7.2+IK分词器
查看>>
cocos2d(3.0)一些基础的东西
查看>>
jQuery动画animate方法使用介绍
查看>>
自适应网页设计(Responsive Web Design)
查看>>
[C#]Hosting Process (vshost.exe)
查看>>
spring beans源码解读之--bean definiton解析器
查看>>
mysql索引优化
查看>>
Async Performance: Understanding the Costs of Async and Await
查看>>
POJ3352Road Construction(构造双连通图)sdut2506完美网络
查看>>
[原]Android打包之跨平台打包
查看>>
Linq的Distinct方法的扩展
查看>>
Union-Find 检测无向图有无环路算法
查看>>