概述
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;
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偏移值;
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中的AQ模块代码学习所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复