概述
/* Before encoding a frame, choose a QP for it
在一帧编码之前,进行帧级码率控制
过程:
1.若使用vbv
1.
2.根据profile和level得到最小压缩比MinCR
3.根据MinCR计算当前帧的最大体积限制
4.计算QP
·ABR
QP = rate_estimate_qscale()
·2pass
QP = rate_estimate_qscale()
·CQP
QP = qp_constant[slicetype]
·i_force_qp QP = i_force_qp - 1
5.clip QP
6.将得到的QP赋值给一些变量给后续使用
7.累计更新accum_p_qp和accum_p_norm
8.更新last_non_b_pict_type
*/
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 ); //得到该帧所属的zone
float q;
x264_emms();
if( h->param.rc.b_stat_read ) //若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 ) //若使用vbv
{
//初始化i_row_bits,f_row_qp,f_row_qscale
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 = rc->row_preds[h->sh.i_type];
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++;
/* 得到最小压缩比 minimum compress rate
用于计算帧的最大体积限制
蓝光最小压缩比为4 */
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.
根据i_level_idc和i_profile_idc计算帧最大体积限制 */
if( h->sps->i_profile_idc > PROFILE_HIGH ) //high profile没有限制
rc->frame_size_maximum = 1e9;
else //baseline、main、extended profile
{
/* The spec has a bizarre special case for the first frame. */
if( h->i_frame == 0 ) //第一帧
{
//384 * ( Max( PicSizeInMbs, fR * MaxMBPS ) + MaxMBPS * ( tr( 0 ) - tr,n( 0 ) ) ) / MinCR
double fr = 1. / (h->param.i_level_idc >= 60 ? 300 : 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
{
//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;
}
}
} //end of if( rc->b_vbv )
//若非B帧则得到该帧所伴随的连续B帧数量
if( h->sh.i_type != SLICE_TYPE_B )
rc->bframes = h->fenc->i_bframes;
/*
计算QP
*/
if( rc->b_abr )
//若是abr,得到qp
{
q = qscale2qp( rate_estimate_qscale( h ) );
}
else if( rc->b_2pass ) //若是2pass,得到qp
{
rce->new_qscale = rate_estimate_qscale( h );
q = qscale2qp( rce->new_qscale );
}
else // 若是CQP
{
/* 得到constant QP
若是BREF,则QP = (B_QP + P_QP)/2
其余取各自的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
{
if( zone->b_force_qp ) //zone使用QP
q += zone->i_qp - rc->qp_constant[SLICE_TYPE_P];
else //zone使用bitrate factor
q -= 6*log2f( zone->f_bitrate_factor );
}
}
//若QP_AUTO,则使用上面分析得到的QP,否则使用i_force_qp作为QP
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 );
/* 将得到的QP赋值给相应的变量 */
rc->qpa_rc = rc->qpa_rc_prev =
rc->qpa_aq = rc->qpa_aq_prev = 0;
h->fdec->f_qp_avg_rc =
h->fdec->f_qp_avg_aq =
rc->qpm = q;
if( rce )
rce->new_qp = q;
//累计更新accum_p_qp和accum_p_norm
accum_p_qp_update( h, rc->qpm );
//更新last_non_b_pict_type
if( h->sh.i_type != SLICE_TYPE_B )
rc->last_non_b_pict_type = h->sh.i_type;
}
其中关键函数rate_estimate_qscale()
最后
以上就是孤独未来为你收集整理的码控-x264_ratecontrol_start()的全部内容,希望文章能够帮你解决码控-x264_ratecontrol_start()所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复