x264 码率控制

q = qp2qscale( ABR_INIT_QP ) / fabs( h->param.rc.f_ip_factor ); //qscale = qp2qscale ,将初始化的qp转换成qp值。

#define ABR_INIT_QP (( h->param.rc.i_rc_method == X264_RC_CRF ? h->param.rc.f_rf_constant : 24 ) + QP_BD_OFFSET) //CRF模式,QP初始化值为CRF值

 

q = clip_qscale( h, pict_type, q );// 传入初始qscale值开始调整,直至predict_size符合vbv 码率控制。

 

vbv-buffersize 码率控制,实现主循环

Int terminate = 0;

For (int iterations = 0; iterations < 1000 && terminate != 3; iterations ++)

{

Double frame_q[3];

 

frame_q[0] = h->sh.i_type == SLICE_TYPE_I ? q * h->param.rc.f_ip_factor : q;

frame_q[1] = frame_q[0] * h->param.rc.f_pb_factor;

frame_q[2] = frame_q[0] / h->param.rc.f_ip_factor;

//初始化不同帧类型qp

Double cur_bits = predict_size( &rcc->pred[h->sh.i_type], q, rcc->last_satd);

 

/* Loop over the planned future frames. */

int j = 0;

double acc_cost = cur_cost;

for( j = 0; buffer_fill_cur >= 0 && buffer_fill_cur <= rcc->buffer_size; j++ )

{

total_duration += last_duration;

    buffer_fill_cur += rcc->vbv_max_rate * last_duration;

    int i_type = h->fenc->i_planned_type[j];// 每一帧帧类型

    int i_satd = h->fenc->i_planned_satd[j]; //每一帧的satd

    if( i_type == X264_TYPE_AUTO )// slice type 未确定

        break;

    i_type = IS_X264_TYPE_I( i_type ) ? SLICE_TYPE_I : IS_X264_TYPE_B( i_type ) ? SLICE_TYPE_B : SLICE_TYPE_P;

    cur_bits = predict_size( &rcc->pred[i_type],  frame_q[i_type],  i_satd ); //不同的帧类型,选用不同的qp值, pred[i_type] 预测因子

    acc_cost += h->fenc->i_planned_cost[j];// acc cost

    buffer_fill_cur -= cur_bits;

    last_duration = h->fenc->f_planned_cpb_duration[j]; //在当前bufsize下预测 duration

}

cur_avg_cost = acc_cost/(j + 1);

 

target_fill = X264_MIN( rcc->buffer_fill + total_duration * rcc->vbv_max_rate * 0.5, rcc->buffer_size * buffer_used_ration );

if( buffer_fill_cur < target_fill )//和预期的duration 消耗bits对比

{

    q *= 1.01;

    terminate |= 1;

    continue;

}

/* Try to get the buffer no more than 80% filled, but don't set an impossible goal. */

target_fill = x264_clip3f( rcc->buffer_fill - total_duration * rcc->vbv_max_rate * 0.5, rcc->buffer_size * 0.8, rcc->buffer_size ); //按照预测的时长计算的 fill size

if( rcc->b_vbv_min_rate && buffer_fill_cur > target_fill )

{

    q /= 1.01;

    terminate |= 2;

    continue;

}

break;

}

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