码控-rate_estimate_qscale()

// update qscale for 1 frame based on actual bits used so far
/*
	基于当前实际使用的比特开销来确定当前帧的qscale

	过程:
		1.计算total_bits,即目前为止编码所有帧所耗费的比特开销总和
		2.计算qscale
			·B帧
				1.根据相邻的两个参考帧来推算当前帧的QP
				2.qp to qscale
				3.估算当前编码帧的体积
				4.将体积进行最大帧体积限制
			·I/P帧
				1.计算abr buffer和predicted_bits
				2.计算scale
					·2pass
					·1pass
						1.得到当前帧的satd
						2.更新cplxsum和cplcount
						3.计算blurred_complexity = cplxsum/cplxcount
						4.初始化ratecontrol_entry_t rce
						5.计算qscale
							·CRF	qscale = get_qscale(), where ratefactor = constant rate factor
							·ABR	
								1.qscale = get_qscale(), where ratefactor = wanted_bits_window/cplxr_sum
								2.计算播放到当前帧所需要的时间time_down
								3.根据time_down和理想的bitrate计算目前为止理想的比特开销wanted_bits
								4.根据理想比特开销wanted_bits和实际比特开销predicted_bits计算abr_buffer上下溢出情况
								5.根据abr_buffer上下溢出情况调整qscale
						6.做一些收尾工作:
							·若当前帧I且上个非B帧P,则通过P的QP和ip_factor来确定当前I帧的qscale
							  这么做个人觉得是防止I帧被调节的太狠而牺牲画质,进而影响后面帧
							·对qscale进行lmin和lmax限制,防止qscale波动大
							·上述1pass中的方法无法有效处理第一帧,故对第一帧单独设置初始化qscale
						7.进行vbv检验 clip_qscale()
				3.存储并更新qscale相关数据
				4.估算当前编码帧的体积
				5.将体积进行最大帧体积限制

*/
static float rate_estimate_qscale( x264_t *h )
{
    float q;
    x264_ratecontrol_t *rcc = h->rc;
    ratecontrol_entry_t rce = {0};
    int pict_type = h->sh.i_type;

	/*
		得到目前编码的总比特数,其中:
		i_frame_size[ SLICE_TYPE_I/ SLICE_TYPE_P/ SLICE_TYPE_B]分别表示各类型slice所编码的总比特数
	*/
    int64_t total_bits = 8*(h->stat.i_frame_size[SLICE_TYPE_I]
                          + h->stat.i_frame_size[SLICE_TYPE_P]
                          + h->stat.i_frame_size[SLICE_TYPE_B])
                       - rcc->filler_bits_sum;

    if( rcc->b_2pass )
    {
        rce = *rcc->rce;
        if( pict_type != rce.pict_type )
        {
            x264_log( h, X264_LOG_ERROR, "slice=%c but 2pass stats say %c\n",
                      slice_type_to_char[pict_type], slice_type_to_char[rce.pict_type] );
        }
    }

    if( pict_type == SLICE_TYPE_B )	//当前B帧
    {
        /* B-frames don't have independent ratecontrol, but rather get the
         * average QP of the two adjacent P-frames + an offset
		 * B帧不拥有独立的码率控制,而是通过其相邻的两个P帧的平均QP + offset来计算 */

        int i0 = IS_X264_TYPE_I(h->fref_nearest[0]->i_type);	//L0中最近的参考帧
        int i1 = IS_X264_TYPE_I(h->fref_nearest[1]->i_type);	//L1中最近的参考帧
        int dt0 = abs(h->fenc->i_poc - h->fref_nearest[0]->i_poc);	//该帧到L0最近的参考帧的距离
        int dt1 = abs(h->fenc->i_poc - h->fref_nearest[1]->i_poc);	//该帧到L1最近的参考帧的距离
        float q0 = h->fref_nearest[0]->f_qp_avg_rc;		//L0中最近参考帧通过码率控制得到的qp
        float q1 = h->fref_nearest[1]->f_qp_avg_rc;		//L1中最近参考帧通过码率控制得到的qp

		/*	检查该帧的两个参考帧是否存在BREF
			若L0L1最近的参考帧是BREF,则其qp减去一个offset	*/
        if( h->fref_nearest[0]->i_type == X264_TYPE_BREF )
            q0 -= rcc->pb_offset/2;
        if( h->fref_nearest[1]->i_type == X264_TYPE_BREF )
            q1 -= rcc->pb_offset/2;

		/*	检查该帧的两个最近参考帧是否存在I帧	*/
        if( i0 && i1 )	//L0L1中最近参考帧都是I帧
            q = (q0 + q1) / 2 + rcc->ip_offset;	//计算当前帧qp
        else if( i0 )	//只有L0中最近参考帧是I帧,L1中最近参考帧是P帧
            q = q1;
        else if( i1 )	//只有L1中最近参考帧是I帧,L0中最近参考帧是P帧
            q = q0;
        else			//L0L1中最近参考帧都不是I帧,即都是P
            q = (q0*dt1 + q1*dt0) / (dt0 + dt1);

		/*	若当前帧是否作为参考帧,
			若作为参考帧,则 + offset	*/
        if( h->fenc->b_kept_as_ref )
            q += rcc->pb_offset/2;
        else
            q += rcc->pb_offset;

		rcc->qp_novbv = q;	//当前帧在1pass中不使用vbv时的qp
        q = qp2qscale( q );	//qp to qscale

		/*	估算一下当前帧的体积 */
        if( rcc->b_2pass )	//2pass,根据tex_bits,mv_bits,misc_bits和qscale估算出当前帧体积
            rcc->frame_size_planned = qscale2bits( &rce, q );
        else	//1pass
			//predict_size(p,q,var)		(p->coeff*var + p->offset) / (q*p->count);
            rcc->frame_size_planned = predict_size( rcc->pred_b_from_p, q, h->fref[1][h->i_ref[1]-1]->i_satd );
       
		/* Limit planned size by MinCR 
		   MinCR (minimum compress rate) 最小压缩比
		   frame_size_maximum为最小压缩比限制下的最大帧体积大小 */
        if( rcc->b_vbv )
            rcc->frame_size_planned = X264_MIN( rcc->frame_size_planned, rcc->frame_size_maximum );

        h->rc->frame_size_estimated = rcc->frame_size_planned;

        /* For row SATDs */
        if( rcc->b_vbv )
            rcc->last_satd = x264_rc_analyse_slice( h );

		//返回qscale
        return q;
    }
    else	//当前I、P帧
    {
		//计算abr_buffer
        double abr_buffer = 2 * rcc->rate_tolerance * rcc->bitrate;
        
		//计算predicted_bits
		double predicted_bits = total_bits;
        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);
                predicted_bits += bits;
            }
        }

        if( rcc->b_2pass )	//是2pass
        {
            double lmin = rcc->lmin[pict_type];
            double lmax = rcc->lmax[pict_type];
            double diff;

            /* Adjust ABR buffer based on distance to the end of the video. */
            if( rcc->num_entries > h->i_frame )
            {
                double final_bits = rcc->entry_out[rcc->num_entries-1]->expected_bits;
                double video_pos = rce.expected_bits / final_bits;
                double scale_factor = sqrt( (1 - video_pos) * rcc->num_entries );
                abr_buffer *= 0.5 * X264_MAX( scale_factor, 0.5 );
            }

            diff = predicted_bits - rce.expected_bits;
            q = rce.new_qscale;
            q /= x264_clip3f((abr_buffer - diff) / abr_buffer, .5, 2);
            if( h->i_frame >= rcc->fps && rcc->expected_bits_sum >= 1 )
            {
                /* Adjust quant based on the difference between
                 * achieved and expected bitrate so far */
                double cur_time = (double)h->i_frame / rcc->num_entries;
                double w = x264_clip3f( cur_time*100, 0.0, 1.0 );
                q *= pow( (double)total_bits / rcc->expected_bits_sum, w );
            }
            rcc->qp_novbv = qscale2qp( q );
            if( rcc->b_vbv )
            {
                /* Do not overflow vbv */
                double expected_size = qscale2bits( &rce, q );
                double expected_vbv = rcc->buffer_fill + rcc->buffer_rate - expected_size;
                double expected_fullness = rce.expected_vbv / rcc->buffer_size;
                double qmax = q*(2 - expected_fullness);
                double size_constraint = 1 + expected_fullness;
                qmax = X264_MAX( qmax, rce.new_qscale );
                if( expected_fullness < .05 )
                    qmax = lmax;
                qmax = X264_MIN(qmax, lmax);
                while( ((expected_vbv < rce.expected_vbv/size_constraint) && (q < qmax)) ||
                        ((expected_vbv < 0) && (q < lmax)))
                {
                    q *= 1.05;
                    expected_size = qscale2bits(&rce, q);
                    expected_vbv = rcc->buffer_fill + rcc->buffer_rate - expected_size;
                }
                rcc->last_satd = x264_rc_analyse_slice( h );
            }
            q = x264_clip3f( q, lmin, lmax );
        }	// end of if( rcc->b_2pass )
        else /* 1pass */
        {
            /* Calculate the quantizer which would have produced the desired
             * average bitrate if it had been applied to all frames so far.
             * Then modulate that quant based on the current frame's complexity
             * relative to the average complexity so far (using the 2pass RCEQ).
             * Then bias the quant up or down if total size so far was far from
             * the target.
             * Result: Depending on the value of rate_tolerance, there is a
             * tradeoff between quality and bitrate precision. But at large
             * tolerances, the bit distribution approaches that of 2pass. 
			 *
			 * 先产生一个QP,该QP如果用于截至目前所有编码帧将会得到我们期望的平均比特率,
			 * 然后再根据 当前帧的复杂度 相对于 截至目前所有编码帧的平均复杂度 来调节QP,
			 * 最后基于 目前所有编码帧实际编码总比特开销 与 我们所期望的比特流开销 来调节QP */

            double wanted_bits, overflow = 1;

			//得到当前编码帧的satd
            rcc->last_satd = x264_rc_analyse_slice( h );

			/* 更新cplxsum (complexity sum) 和 cplcount (complexity count)
																 satd(n)
				cplxsum(n) = cplxsum(n-1) * 0.5 + -----------------------------------------
													frame duration / frame duration base

				cplxcount(n) = cplxcount(n-1) * 0.5 + 1 
			*/
            rcc->short_term_cplxsum *= 0.5;
            rcc->short_term_cplxcount *= 0.5;
            rcc->short_term_cplxsum += rcc->last_satd / (CLIP_DURATION(h->fenc->f_duration) / BASE_FRAME_DURATION);
            rcc->short_term_cplxcount ++;

			/*	计算blurred complexity
										 cplxsum
				blurred_complexity = ---------------
										cplxcount
			*/
            rce.blurred_complexity = rcc->short_term_cplxsum / rcc->short_term_cplxcount;

			/*
				初始化rce,用于后面
			*/
			rce.tex_bits = rcc->last_satd;	//残差系数bit开销
            rce.mv_bits = 0;				//mv ref mode 开销
            rce.p_count = rcc->nmb;		//mb宏块个数
            rce.i_count = 0;
            rce.s_count = 0;
            rce.qscale = 1;
            rce.pict_type = pict_type;
            rce.i_duration = h->fenc->i_duration;

			/* get qscale based on rate factor and rceq
							 rceq
				qscale = -------------
						  rate factor

				其中rceq是非线性化压缩后的blur_complexity:
									  (1-qcompress)
					rceq = blur_complexity 

				when method = CRF:
					rate factor = constant rate factor
				when method = ABR:
				                   wanted_bits_window
					rate factor = ---------------------
										cplxr_sum

				where
										  bits(n-1)					bits(n-2)						bits(0)
					cplxr_sum(n) = ----------------------- + ----------------------- + ... + -----------------------
								   qscale(n-1) * rceq(n-1)   qscale(n-2) * rceq(n-2)		   qscale(0) * rceq(0)
			*/
            if( h->param.rc.i_rc_method == X264_RC_CRF )	//若是CRF
			{	//rate factor = rate_factor_constant
                q = get_qscale( h, &rce, rcc->rate_factor_constant, h->fenc->i_frame );
            }	
            else	//ABR,使用abr_buffer
			{	//rate_factor = wanted_bits_window / cplxr_sum
                q = get_qscale( h, &rce, rcc->wanted_bits_window / rcc->cplxr_sum, h->fenc->i_frame );

                /* ABR code can potentially be counterproductive in CBR, so just don't bother.
                 * Don't run it if the frame complexity is zero either. */
                if( !rcc->b_vbv_min_rate && rcc->last_satd )
                {
                    // FIXME is it simpler to keep track of wanted_bits in ratecontrol_end?
                    int i_frame_done = h->i_frame;

					//播放到该帧所需要的时间
                    double time_done = i_frame_done / rcc->fps;
                    if( h->param.b_vfr_input && i_frame_done > 0 )	//variable frame rate
                        time_done = ((double)(h->fenc->i_reordered_pts - h->i_reordered_pts_delay)) * h->param.i_timebase_num / h->param.i_timebase_den;
                    
					//得到目前为止我们所期望的比特总开销:时间 * 期望bitrate = 期望bits
					wanted_bits = time_done * rcc->bitrate;
                    if( wanted_bits > 0 )
                    {
						//更新abr_buffer
                        abr_buffer *= X264_MAX( 1, sqrt( time_done ) );
						//计算abr_buffer的上溢下溢
                        overflow = x264_clip3f( 1.0 + (predicted_bits - wanted_bits) / abr_buffer, .5, 2 );
                        //根据abr_buffer的上溢下溢情况调整qscale
						q *= overflow;
                    }
                }
            }	// end of ABR

			/* 做一些收尾工作:
				·若当前帧I且上个非B帧P,则通过P的QP和ip_factor来确定当前I帧的qscale
				·对qscale进行lmin和lmax限制,防止qscale波动大
				·上述1pass中的方法无法有效处理第一帧,故对第一帧单独设置初始化qscale */
            if( pict_type == SLICE_TYPE_I && h->param.i_keyint_max > 1
                /* should test _next_ pict type, but that isn't decided yet */
                && rcc->last_non_b_pict_type != SLICE_TYPE_I )
            {	/* 若当前帧为I帧 && 最大关键帧距离>1 && 上一个非B帧是P帧
				   则通过得到P帧的qscale和ip_factor来计算当前I帧的 */
                q = qp2qscale( rcc->accum_p_qp / rcc->accum_p_norm );
                q /= fabs( h->param.rc.f_ip_factor );
            }
            else if( h->i_frame > 0 )	//非首帧
            {
                if( h->param.rc.i_rc_method != X264_RC_CRF )	//abr/cqp
                {
                    /* Asymmetric clipping, because symmetric would prevent
                     * overflow control in areas of rapidly oscillating complexity 
					 * 避免qscale波动太大,计算min和max限制qscale。
					 * 该min和max与上一个同类型帧的qscale和帧最大qscale改变率计算而得,
					 * 同时也与abr_buffer的上下溢出情况相关。 */
                    double lmin = rcc->last_qscale_for[pict_type] / rcc->lstep;
                    double lmax = rcc->last_qscale_for[pict_type] * rcc->lstep;
                    
					//根据abr_buffer的溢出情况再次调节lmin和lmax
					if( overflow > 1.1 && h->i_frame > 3 )
                        lmax *= rcc->lstep;
                    else if( overflow < 0.9 )
                        lmin /= rcc->lstep;

                    q = x264_clip3f(q, lmin, lmax);
                }
            }// 到这里的帧为首帧
            else if( h->param.rc.i_rc_method == X264_RC_CRF && rcc->qcompress != 1 )
            {	//若是CRF && qcomp!=1即各帧的rceq!=1
                q = qp2qscale( ABR_INIT_QP ) / fabs( h->param.rc.f_ip_factor );
            }
            rcc->qp_novbv = qscale2qp( q );

            //进行vbv检验,并对qscale进行clip
            q = clip_qscale( h, pict_type, q );
        }	// end of 1pass 


		/*到这里已经确定了qscale
		更新last_qscale_for[pict_type]和last_qscale */
        rcc->last_qscale_for[pict_type] =
        rcc->last_qscale = q;


        if( !(rcc->b_2pass && !rcc->b_vbv) && h->fenc->i_frame == 0 )
            rcc->last_qscale_for[SLICE_TYPE_P] = q * fabs( h->param.rc.f_ip_factor );

		/*	
			估算一下当前帧的体积 
		*/
        if( rcc->b_2pass )	//若是2pass,则基于tex_bits,mb_bits,misc_bits等来估算帧体积
            rcc->frame_size_planned = qscale2bits( &rce, q );
        else	//若是1pass,则根据satd估算帧体积
            rcc->frame_size_planned = predict_size( &rcc->pred[h->sh.i_type], q, rcc->last_satd );

        // Always use up the whole VBV in this case. 若使用单帧vbv,则将单帧vbv的最大帧率比特给帧体积
        if( rcc->single_frame_vbv )
            rcc->frame_size_planned = rcc->buffer_rate;
        // Limit planned size by MinCR	基于MinCR来限制帧体积
        if( rcc->b_vbv )
            rcc->frame_size_planned = X264_MIN( rcc->frame_size_planned, rcc->frame_size_maximum );

        h->rc->frame_size_estimated = rcc->frame_size_planned;

        return q;
    }	// end of I、P帧
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值