码控-x264_ratecontrol_start()

/* 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()

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值