我是靠谱客的博主 鲤鱼大船,这篇文章主要介绍x264中的AQ模块代码学习,现在分享给大家,希望可以做个参考。

x264中的AQ:

简述:

   有四种aq模式,分别为:

 - 0: Disabled

 - 1: Variance AQ (complexity mask)

 - 2: Auto-variance AQ

 - 3: Auto-variance AQ with bias to dark scenes

  实际aq的应用不仅与aq-mode的设置有关,还与aq-strength有关,aq-strength决定是了实施aq-mode的强度,aq-strength

的取值范围在(0,3),值越大应用aq的强度越大;

    与aq相关的主要函数为x264_adaptive_quant_frame,在该函数中,根据不同的aq模式完成每个宏块的qp偏移值,计算过程使用到宏块的方差信息与aq-strength;

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
void x264_adaptive_quant_frame( x264_t *h, x264_frame_t *frame, float *quant_offsets ) { /* Initialize frame stats */ for( int i = 0; i < 3; i++ ) { frame->i_pixel_sum[i] = 0; frame->i_pixel_ssd[i] = 0; } /* Degenerate cases */ if( h->param.rc.i_aq_mode == X264_AQ_NONE || h->param.rc.f_aq_strength == 0 ) { /* Need to init it anyways for MB tree */ if( h->param.rc.i_aq_mode && h->param.rc.f_aq_strength == 0 ) { if( quant_offsets ) { for( int mb_xy = 0; mb_xy < h->mb.i_mb_count; mb_xy++ ) frame->f_qp_offset[mb_xy] = frame->f_qp_offset_aq[mb_xy] = quant_offsets[mb_xy]; if( h->frames.b_have_lowres ) for( int mb_xy = 0; mb_xy < h->mb.i_mb_count; mb_xy++ ) frame->i_inv_qscale_factor[mb_xy] = x264_exp2fix8( frame->f_qp_offset[mb_xy] ); } else { memset( frame->f_qp_offset, 0, h->mb.i_mb_count * sizeof(float) ); memset( frame->f_qp_offset_aq, 0, h->mb.i_mb_count * sizeof(float) ); if( h->frames.b_have_lowres ) for( int mb_xy = 0; mb_xy < h->mb.i_mb_count; mb_xy++ ) frame->i_inv_qscale_factor[mb_xy] = 256; } } /* Need variance data for weighted prediction */ if( h->param.analyse.i_weighted_pred ) { for( int mb_y = 0; mb_y < h->mb.i_mb_height; mb_y++ ) for( int mb_x = 0; mb_x < h->mb.i_mb_width; mb_x++ ) x264_ac_energy_mb( h, mb_x, mb_y, frame ); } else return; } /* Actual adaptive quantization */ else { /* constants chosen to result in approximately the same overall bitrate as without AQ. * FIXME: while they're written in 5 significant digits, they're only tuned to 2. */ float strength; float avg_adj = 0.f; float bias_strength = 0.f; if( h->param.rc.i_aq_mode == X264_AQ_AUTOVARIANCE || h->param.rc.i_aq_mode == X264_AQ_AUTOVARIANCE_BIASED ) { float bit_depth_correction = 1.f / (1 << (2*(BIT_DEPTH-8))); float avg_adj_pow2 = 0.f; for( int mb_y = 0; mb_y < h->mb.i_mb_height; mb_y++ ) for( int mb_x = 0; mb_x < h->mb.i_mb_width; mb_x++ ) { uint32_t energy = x264_ac_energy_mb( h, mb_x, mb_y, frame ); float qp_adj = powf( energy * bit_depth_correction + 1, 0.125f ); frame->f_qp_offset[mb_x + mb_y*h->mb.i_mb_stride] = qp_adj; avg_adj += qp_adj; avg_adj_pow2 += qp_adj * qp_adj; } avg_adj /= h->mb.i_mb_count; avg_adj_pow2 /= h->mb.i_mb_count; strength = h->param.rc.f_aq_strength * avg_adj; avg_adj = avg_adj - 0.5f * (avg_adj_pow2 - 14.f) / avg_adj; bias_strength = h->param.rc.f_aq_strength; } else strength = h->param.rc.f_aq_strength * 1.0397f; for( int mb_y = 0; mb_y < h->mb.i_mb_height; mb_y++ ) for( int mb_x = 0; mb_x < h->mb.i_mb_width; mb_x++ ) { float qp_adj; int mb_xy = mb_x + mb_y*h->mb.i_mb_stride; if( h->param.rc.i_aq_mode == X264_AQ_AUTOVARIANCE_BIASED ) { qp_adj = frame->f_qp_offset[mb_xy]; qp_adj = strength * (qp_adj - avg_adj) + bias_strength * (1.f - 14.f / (qp_adj * qp_adj)); } else if( h->param.rc.i_aq_mode == X264_AQ_AUTOVARIANCE ) { qp_adj = frame->f_qp_offset[mb_xy]; qp_adj = strength * (qp_adj - avg_adj); } else { uint32_t energy = x264_ac_energy_mb( h, mb_x, mb_y, frame ); qp_adj = strength * (x264_log2( X264_MAX(energy, 1) ) - (14.427f + 2*(BIT_DEPTH-8))); } if( quant_offsets ) qp_adj += quant_offsets[mb_xy]; frame->f_qp_offset[mb_xy] = frame->f_qp_offset_aq[mb_xy] = qp_adj; if( h->frames.b_have_lowres ) frame->i_inv_qscale_factor[mb_xy] = x264_exp2fix8(qp_adj); } } /* Remove mean from SSD calculation */ for( int i = 0; i < 3; i++ ) { uint64_t ssd = frame->i_pixel_ssd[i]; uint64_t sum = frame->i_pixel_sum[i]; int width = 16*h->mb.i_mb_width >> (i && CHROMA_H_SHIFT); int height = 16*h->mb.i_mb_height >> (i && CHROMA_V_SHIFT); frame->i_pixel_ssd[i] = ssd - (sum * sum + width * height / 2) / (width * height); } }

aq偏移值的应用主要在x264_ratecontrol_mb_qp函数中完成,在该函数中,对每个宏块在原先的qp基础上再加上x264_adaptive_quant_frame计算出来的qp偏移值;

   

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
int x264_ratecontrol_mb_qp( x264_t *h ) { x264_emms(); float qp = h->rc->qpm; if( h->param.rc.i_aq_mode ) { /* MB-tree currently doesn't adjust quantizers in unreferenced frames. */ float qp_offset = h->fdec->b_kept_as_ref ? h->fenc->f_qp_offset[h->mb.i_mb_xy] : h->fenc->f_qp_offset_aq[h->mb.i_mb_xy]; /* Scale AQ's effect towards zero in emergency mode. */ if( qp > QP_MAX_SPEC )//QP_MAX_SPEC = 51 qp_offset *= (QP_MAX - qp) / (QP_MAX - QP_MAX_SPEC); qp += qp_offset; } return x264_clip3( qp + 0.5f, h->param.rc.i_qp_min, h->param.rc.i_qp_max ); }

      

 

 

最后

以上就是鲤鱼大船最近收集整理的关于x264中的AQ模块代码学习的全部内容,更多相关x264中内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(89)

评论列表共有 0 条评论

立即
投稿
返回
顶部