x264中码率控制(二)x264_ratecontrol_start函数

在一帧的编码前就选择QP值。帧层码率控制,到这一步,一帧中所有宏块还是统一qp的 

void x264_ratecontrol_start( x264_t *h, int i_force_qp )
{
    x264_ratecontrol_t *rc = h->rc;
    ratecontrol_entry_t *rce = NULL;   //used for 2pass
    x264_zone_t *zone = get_zone( h, h->fenc->i_frame ); //找到当前要编码帧的位置
    float q;

    x264_emms();
    // 对于zone设置, 重新配置编码器
    if( zone && (!rc->prev_zone || zone->param != rc->prev_zone->param) )
        x264_encoder_reconfig( h, zone->param );
    rc->prev_zone = zone;

    rc->qp_force = i_force_qp;
    // 对于两阶段编码, stat 将被读取
    if( h->param.rc.b_stat_read )
    {
        int frame = h->fenc->i_frame;
        assert( frame >= 0 && frame < rc->num_entries );
        rce = h->rc->rce = &h->rc->entry[frame];// 获取该帧的码率控制相关内容

        if( h->sh.i_type == SLICE_TYPE_B
            && h->param.analyse.i_direct_mv_pred == X264_DIRECT_PRED_AUTO ) //直接空间预测
        {
            h->sh.b_direct_spatial_mv_pred = ( rce->direct_mode == 's' );
            h->mb.b_direct_auto_read = ( rce->direct_mode == 's' || rce->direct_mode == 't' );
        }
    }

    if( rc->b_vbv )
    {
        memset( h->fdec->i_row_bits, 0, h->sps->i_mb_height * sizeof(int) );
        rc->row_pred = &rc->row_preds[h->sh.i_type];
        update_vbv_plan( h );  根据当前所有帧预计的大小临时更新VBV,也即更新h->rc->buffer_fill,就是更新缓冲区 
    }

    if( h->sh.i_type != SLICE_TYPE_B )  //当前帧不是B帧,获取B帧数
    {
        rc->bframes = 0;
        while( h->frames.current[rc->bframes] && IS_X264_TYPE_B(h->frames.current[rc->bframes]->i_type) )
            rc->bframes++;
    }

	//根据不同的码率控制方式,计算出QP值
    if( i_force_qp )
    {
        q = i_force_qp - 1;
    }
    else if( rc->b_abr )
    {
        q = qscale2qp( rate_estimate_qscale( h ) );
    }
    else if( rc->b_2pass )
    {
        rce->new_qscale = rate_estimate_qscale( h );
        q = qscale2qp( rce->new_qscale );
    }
    else /* CQP */
    {
        // 对于cqp(constant qp)设置
        // 如果当前帧B帧, 则其qp取B帧类型的常qp和P帧类型的常qp的平均值
        // 否则,直接取该帧类型的常qp
        if( h->sh.i_type == SLICE_TYPE_B && h->fdec->b_kept_as_ref )
            q = ( rc->qp_constant[ SLICE_TYPE_B ] + rc->qp_constant[ SLICE_TYPE_P ] ) / 2;
        else
            q = rc->qp_constant[ h->sh.i_type ];

        if( zone )  // 对于有zone, 调整qp
        {
            if( zone->b_force_qp )
                q += zone->i_qp - rc->qp_constant[SLICE_TYPE_P];
            else
                q -= 6*log(zone->f_bitrate_factor)/log(2);
        }
    }

    rc->qpa_rc =
    rc->qpa_aq = 0;
    h->fdec->f_qp_avg_rc =
    h->fdec->f_qp_avg_aq =
    rc->qpm =
    rc->qp = x264_clip3( (int)(q + 0.5), 0, 51 );   //将求得的qp赋值给rc->qp
    rc->f_qpm = q;
    if( rce )
        rce->new_qp = rc->qp;

    /* accum_p_qp needs to be here so that future frames can benefit from the
     * data before this frame is done. but this only works because threading
     * guarantees to not re-encode any frames. so the non-threaded case does
     * accum_p_qp later. */
    if( h->param.i_threads > 1 )   //更新累计qp信息
        accum_p_qp_update( h, rc->qp );

    if( h->sh.i_type != SLICE_TYPE_B )   //如果当前帧不是B帧, 将帧类型赋值给rc->last_non_b_pict_type
        rc->last_non_b_pict_type = h->sh.i_type;
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值