x264 aq-strength

本文介绍了自适应量化对视频主观质量影响大,甚至决定编码器优劣。开启自适应量化对编码速度影响不大,对性能提升在主观质量上有细节改善。还给出了x264中的代码实现,展示了自适应量化的具体计算过程以及最终调整宏块qp的部分代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

       自适应量化对视频主观质量的影响是非常大,甚至决定了一个编码器的优劣,“编码器评测结果一次又一次的证明,没有自适应量化的编码器完全没法与具备的编码器相提并论。”开启自适应量化对编码速度的影响并不大;对性能的提升在PSNR上看并不明显,在主观质量上还是有一些细节改善,因此建议保持默认值。自适应量化强度决定码率偏向于低细节(ssd小)部分的强度。

看下x264中的代码实现:

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++ )
                    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 = ac_energy_mb( h, mb_x, mb_y, frame );// ssd - sum_ssd^2 >> shift;//计算ssd - sum_ssd ^ 2 >> shift;
                    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);// 这里strength 会放大 当前宏块计算出来的energy和平均ener插值

                  //如果这里qp_adj - avg_adj 大于0,energy 大的宏块的qp会被调整得更大。最终计算的qp_offset越大,复杂区域更模糊

                 //如果这里qp_adj - avg_adj小于0,strength越大,qp_offset 越小,最终qp也越小,平坦区域更清晰
                }
                else
                {
                    uint32_t energy = 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;//最终计算得到 q_qp_offset和 f_qp_offset_aq;
                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);
    }
}

//看最终调整宏块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_offset *= (QP_MAX - qp) / (QP_MAX - QP_MAX_SPEC); //通过f_qp_offset值按比例调整最终得到的qp值,
        qp += qp_offset;
    }
    return x264_clip3( qp + 0.5f, h->param.rc.i_qp_min, h->param.rc.i_qp_max );
}

这里可以看出来,aq-strength放大了,ssd 对当前宏块的qp值的影响。

### x264编码器中AQ(自适应量化)模式的使用方法及参数设置 x264编码器提供了多种模式来优化视频压缩质量,其中AQ(Adaptive Quantization,自适应量化)模式是一种通过调整量化参数(QP)以改善主观视觉质量的技术。以下是关于AQ模式的相关配置和使用方法: #### AQ模式的基本概念 AQ模式的核心思想是通过对复杂度较高的区域分配更多的比特率,从而提升这些区域的细节表现,同时减少对简单区域的比特率分配[^1]。这种技术可以显著提高视频的主观质量,尤其是在低比特率条件下。 #### AQ模式的类型 x264支持两种主要的AQ模式: 1. **AQ模式1(Variance-based AQ)**:基于宏块方差的AQ模式,它会根据图像块的复杂度调整量化参数。复杂的区域会被分配更高的比特率,而简单的区域则会被降低比特率。 2. **AQ模式2(Auto Variance AQ with bias to dark scenes)**:在AQ模式1的基础上增加了一个偏置项,特别关注暗场景的表现,以避免暗部细节丢失。 #### 参数设置 在使用FFmpeg调用x264编码器时,可以通过以下参数启用和配置AQ模式: - `--aq-mode` 或 `-aq_mode`:指定AQ模式的类型。取值范围为0到3,分别表示关闭、Variance-based AQ、Auto Variance AQ和Auto Variance AQ with bias to dark scenes[^1]。 - `--aq-strength` 或 `-aq_strength`:控制AQ的强度,取值范围为0到5,默认值为1。较大的值会增加量化参数的变化幅度,从而更明显地影响比特率分配[^1]。 #### 示例代码 以下是一个使用FFmpeg启用AQ模式的示例命令: ```bash ffmpeg -i input.mp4 -c:v libx264 -preset medium -crf 23 -aq_mode 2 -aq_strength 1 output.mp4 ``` - `-aq_mode 2`:启用Auto Variance AQ模式。 - `-aq_strength 1`:设置AQ强度为默认值。 #### 注意事项 - AQ模式通常与CRF(Constant Rate Factor)模式配合使用,因为CRF模式允许编码器根据目标质量动态调整比特率。 - 如果使用的是CBR(Constant Bitrate)或VBR(Variable Bitrate)模式,则需要仔细调整比特率和其他相关参数,以确保AQ的效果不会被限制的比特率所抵消。 ### 总结 AQ模式是x264编码器中一种重要的质量优化工具,能够有效改善视频的主观质量。通过合理配置AQ模式及其强度参数,可以在不同应用场景下获得更好的压缩效果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值