概述
// 在编码一帧前,为该帧选择qp
/* Before encoding a frame, choose a QP for it */
void x264_ratecontrol_start( x264_t *h, int i_force_qp, int overhead )
{
x264_ratecontrol_t *rc = h->rc;
ratecontrol_entry_t *rce = NULL;
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_apply( h, zone->param );
rc->prev_zone = zone;
// 对于两阶段编码, stat 将被读取
if( h->param.rc.b_stat_read )
{
// 获得编码帧的序号
int frame = h->fenc->i_frame;
assert( frame >= 0 && frame < rc->num_entries );
// 获取该帧的rce条目
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 )
{
// rc vbv 使能
// 初始化重构帧的row变量
memset( h->fdec->i_row_bits, 0, h->mb.i_mb_height * sizeof(int) );
memset( h->fdec->f_row_qp, 0, h->mb.i_mb_height * sizeof(float) );
memset( h->fdec->f_row_qscale, 0, h->mb.i_mb_height * sizeof(float) );
// 将rc row_pred 指向当前帧类型的row_pred
rc->row_pred = &rc->row_preds[h->sh.i_type];
// 重新计算rc 的 buffer_rate
rc->buffer_rate = h->fenc->i_cpb_duration * rc->vbv_max_rate * h->sps->vui.i_num_units_in_tick / h->sps->vui.i_time_scale;
// 计算缓冲区预计大小
update_vbv_plan( h, overhead );
const x264_level_t *l = x264_levels;
while( l->level_idc != 0 && l->level_idc != h->param.i_level_idc )
l++;
// 获得对应level的mincr
int mincr = l->mincr;
if( h->param.b_bluray_compat )
mincr = 4;
/* Profiles above High don't require minCR, so just set the maximum to a large value. */
// 对于 profile_idc 大于 PROFILE_HIGH,直接设置rc->frame_size_maximum
if( h->sps->i_profile_idc > PROFILE_HIGH )
rc->frame_size_maximum = 1e9;
else
{
/* The spec has a bizarre special case for the first frame. */
if( h->i_frame == 0 )
{
// 对于第一帧, 计算rc->frame_size_maximum
//384 * ( Max( PicSizeInMbs, fR * MaxMBPS ) + MaxMBPS * ( tr( 0 ) - tr,n( 0 ) ) ) / MinCR
double fr = 1. / 172;
int pic_size_in_mbs = h->mb.i_mb_width * h->mb.i_mb_height;
rc->frame_size_maximum = 384 * BIT_DEPTH * X264_MAX( pic_size_in_mbs, fr*l->mbps ) / mincr;
}
else
{
// 对于其他帧, 计算rc->frame_size_maximum
// 384 * MaxMBPS * ( tr( n ) - tr( n - 1 ) ) / MinCR
rc->frame_size_maximum = 384 * BIT_DEPTH * ((double)h->fenc->i_cpb_duration * h->sps->vui.i_num_units_in_tick / h->sps->vui.i_time_scale) * l->mbps / mincr;
}
}
}
// 当前帧不是B帧, 获取当前帧的B帧数
if( h->sh.i_type != SLICE_TYPE_B )
rc->bframes = h->fenc->i_bframes;
// 如果自适应码率控制
if( rc->b_abr )
{
// 估计qscale, 然后转换为qp
q = qscale2qp( rate_estimate_qscale( h ) );
}
else if( rc->b_2pass )
{
// 对于两阶段,同样估计qscale, 然后转换为qp
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 ];
// 对于有zone, 调整qp
if( zone )
{
if( zone->b_force_qp )
q += zone->i_qp - rc->qp_constant[SLICE_TYPE_P];
else
q -= 6*log2f( zone->f_bitrate_factor );
}
}
if( i_force_qp != X264_QP_AUTO )
q = i_force_qp - 1;
// 裁减 qp
q = x264_clip3f( q, h->param.rc.i_qp_min, h->param.rc.i_qp_max );
rc->qpa_rc = rc->qpa_rc_prev =
rc->qpa_aq = rc->qpa_aq_prev = 0;
// 将求得的qp赋值给rc->qp
rc->qp = x264_clip3( q + 0.5f, 0, QP_MAX );
// 将求得的qp赋值给重构帧的平均qp_avg_rc
// 和qp_avg_aq, 和rc->qpm
h->fdec->f_qp_avg_rc =
h->fdec->f_qp_avg_aq =
rc->qpm = q;
// 两阶段
if( rce )
rce->new_qp = rc->qp;
// 更新累计qp信息, 见accm_p_qp_update
accum_p_qp_update( h, rc->qpm );
// 如果当前帧不是B帧, 将帧类型
// 赋值给rc->last_non_b_pict_type
if( h->sh.i_type != SLICE_TYPE_B )
rc->last_non_b_pict_type = h->sh.i_type;
}
// provisionally update VBV according to the planned size of all frames currently in progress
// 计算缓冲区预计大小
static void update_vbv_plan( x264_t *h, int overhead )
{
x264_ratecontrol_t *rcc = h->rc;
rcc->buffer_fill = h->thread[0]->rc->buffer_fill_final / h->sps->vui.i_time_scale;
if( h->i_thread_frames > 1 )
{
int j = h->rc - h->thread[0]->rc;
for( int i = 1; i < h->i_thread_frames; i++ )
{
x264_t *t = h->thread[ (j+i)%h->i_thread_frames ];
double bits = t->rc->frame_size_planned;
if( !t->b_thread_active )
continue;
bits = X264_MAX(bits, t->rc->frame_size_estimated);
rcc->buffer_fill -= bits;
rcc->buffer_fill = X264_MAX( rcc->buffer_fill, 0 );
rcc->buffer_fill += t->rc->buffer_rate;
rcc->buffer_fill = X264_MIN( rcc->buffer_fill, rcc->buffer_size );
}
}
rcc->buffer_fill = X264_MIN( rcc->buffer_fill, rcc->buffer_size );
rcc->buffer_fill -= overhead;
}
static void accum_p_qp_update( x264_t *h, float qp )
{
x264_ratecontrol_t *rc = h->rc;
rc->accum_p_qp *= .95;
rc->accum_p_norm *= .95;
rc->accum_p_norm += 1;
if( h->sh.i_type == SLICE_TYPE_I )
rc->accum_p_qp += qp + rc->ip_offset;
else
rc->accum_p_qp += qp;
}
最后
以上就是帅气发箍为你收集整理的x264 - x264_ratecontrol_start的全部内容,希望文章能够帮你解决x264 - x264_ratecontrol_start所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复