x264 源码qcomp

qcomp参数对h264编码的码率控制主要有两方面,1 帧qscale计算 2 宏块qp调整

1 static double get_qscale(x264_t *h, ratecontrol_entry_t *rce, double rate_factor, int frame_num)
{
    x264_ratecontrol_t *rcc= h->rc;
    x264_zone_t *zone = get_zone( h, frame_num );
    double q;
    if( h->param.rc.b_mb_tree )
    {
        double timescale = (double)h->sps->vui.i_num_units_in_tick / h->sps->vui.i_time_scale;
        q = pow( BASE_FRAME_DURATION / CLIP_DURATION(rce->i_duration * timescale), 1 - h->param.rc.f_qcompress );
    }
    else
    {
        q = pow( rce->blurred_complexity, 1 - rcc->qcompress );
    }

} //目前我们都是开了宏块树码率控制的,宏块树记录了宏块间的参考关系,1 被参考多的宏块qp减小,反之增大。

这里q = pow( BASE_FRAME_DURATION / CLIP_DURATION(rce->i_duration * timescale), 1 - h->param.rc.f_qcompress ); 显然这个是个固定值,即qcomp一定的情况下,qscale固定了。

else条件中,q = pow( rce->blurred_complexity, 1 - rcc->qcompress ); blurred 是本帧所有的宏块satd带权和。

这里仅仅是初始的帧的qscale值。

后面还会通过clip_qscale,调整帧的qscale值,这个函数尝试左右浮动qscale求得最合适的值。

 

2 宏块级的影响

static void macroblock_tree_finish( x264_t *h, x264_frame_t *frame, float average_duration, int ref0_distance )
{
    int fps_factor = round( CLIP_DURATION(average_duration) / CLIP_DURATION(frame->f_duration) * 256 / MBTREE_PRECISION );
    float weightdelta = 0.0;
    if( ref0_distance && frame->f_weighted_cost_delta[ref0_distance-1] > 0 )
        weightdelta = (1.0 - frame->f_weighted_cost_delta[ref0_distance-1]);

    /* Allow the strength to be adjusted via qcompress, since the two
     * concepts are very similar. */
    float strength = 5.0f * (1.0f - h->param.rc.f_qcompress); //宏块码率控制中,宏块树的强度和qcomp成相反的关系,qcomp大,宏块树作用小。

 for( int mb_index = 0; mb_index < h->mb.i_mb_count; mb_index++ )
    {
        int intra_cost = (frame->i_intra_cost[mb_index] * frame->i_inv_qscale_factor[mb_index] + 128) >> 8;
        if( intra_cost )
        {
            int propagate_cost = (frame->i_propagate_cost[mb_index] * fps_factor + 128) >> 8;
            float log2_ratio = x264_log2(intra_cost + propagate_cost) - x264_log2(intra_cost) + weightdelta;
            frame->f_qp_offset[mb_index] = frame->f_qp_offset_aq[mb_index] - strength * log2_ratio;
        }
    }

    // 宏块树作用小,qp_offset调整幅度越大。

}从这个函数可有看出来,strength决定了宏块的cost对最终的qp_offset的影响,如果strength越大,则影响越大。这里qcomp和strength是反的关系,所以qcomp越小,宏块cost对最终的影响越大,qp_offset值越小。

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);
        qp += qp_offset;
    }
    return x264_clip3( qp + 0.5f, h->param.rc.i_qp_min, h->param.rc.i_qp_max );
}

在宏块qp调整中,qp_offset 直接对应的qcomp调节的值。

然后通过一定比例计算出调整的delta_qp值,得到最终的qp值。这里说明,qcomp越小,qp_offset 作为负值也越小,即绝对值越大。和当前qp相加后的结果越小,也就是说qcomp越小,qp会伴随cost大小变化幅度越大。失真就越小。

总的来说,就是qcomp会强调cost大的宏块。

你可能感兴趣的:(音视频)