码控-clip_qscale()

// apply VBV constraints and clip qscale to between lmin and lmax
/*
	对qscale进行VBV检验,然后clip到lmin和lmax中

	过程:
		1.根据帧类型得到qscale的lmin和lmax
		2.若使用vbv,则进行vbv检查
			1.两个算法择一进行约束
				·lookahead vbv
					1.计算每一帧时间的最大buffer注入bits
					2.计算planned future frames中每一帧输出的估计bits
					3.持续步骤(1,2)步骤,模拟planned future frames所有帧输出结束
					  得到模拟输出后的buffer丰盈度buffer_fill_cur
					4.计算buffer_fill_cur所被允许界限
						·下限(不高于50%):若低于下限则调高qscale
						·上限(介于80%到100%之间):若高于上限则调低qscale
					5.重新(1,2,3,4,5),直到buffer_fill_cur满足target_fill
				·old purely-reactive algorithm
					1.若I/P,若buffer_fill低于一半,为了避免buffer下溢,则放大qscale减少当前帧的bits
					2.根据qscale估计当前帧的bits
					3.计算max_fill_factor,以buffer_fill为目标调整qscale
					4.计算min_fill_factoi,以buffer_rate为目标调整qscale
					5.约束新的qscale,不能低于未调整前的qscale
			2.若是P帧,则进行约束检查
				1.估计当前P帧的bits和其前面连续bframes个B帧的bits
				2.计算当前P帧和bframes个B帧的时间和,及该时间内以vbv_max_rate注入buffer的bits量
				3.若当前P帧和bframes个B帧的bits流失量>时间内bits的注入量,上调qscale减少当前P帧的bits
				4.为了保证P帧的画面质量,不能调的太狠,约束新qscale在旧qscale两倍以内
			3.基于新的qscale重新估计当前帧的bits
			4.计算帧bits上限frame_size_maximum,上调qscale将该帧的bits约束在frame_size_maximum以内
		3.将新的qscale约束在步骤1中的lmin和lmax内,返回
*/
static double clip_qscale( x264_t *h, int pict_type, double q )
{
    x264_ratecontrol_t *rcc = h->rc;

	//取该类型帧qscale的lmin和lmax
    double lmin = rcc->lmin[pict_type];
    double lmax = rcc->lmax[pict_type];

	/* 若有rate_factor_max_increment的限制
	   不懂为什么这里要QP+ratefactor_Incremnt?这两不是一个东西吧 */
    if( rcc->rate_factor_max_increment )
        lmax = X264_MIN( lmax, qp2qscale( rcc->qp_novbv + rcc->rate_factor_max_increment ) );
    double q0 = q;

    /* B-frames are not directly subject to VBV,
     * since they are controlled by the P-frames' QPs. 
	 * B帧不受vbv控制,因为他的QP只由相邻的参考帧计算而来 */

    if( rcc->b_vbv && rcc->last_satd > 0 )	//若使用VBV
    {
        double fenc_cpb_duration = (double)h->fenc->i_cpb_duration *
                                   h->sps->vui.i_num_units_in_tick / h->sps->vui.i_time_scale;
        /* Lookahead VBV: raise the quantizer as necessary such that no frames in
         * the lookahead overflow and such that the buffer is in a reasonable state
         * by the end of the lookahead. 
		 * lookahead VBV:使得lookahead中的各个帧都不会造成vbv溢出,
		 *且在lookahead结束前,vbv仍然处于一个合适的状态 */
        if( h->param.rc.i_lookahead )	//若使用了码率控制的lookahead
        {
            int terminate = 0;

            /* Avoid an infinite loop. 
				terminate = 0	=>	既没有进行qscale*=1.01,使得buffer上溢
									也没有进行qscale/=1.01,使得buffer下溢

				terminate = 1	=>	只进行了qscale*=1.01,使得buffer不断上溢

				terminate = 2	=>	只进行了qscale/=1.01,使得buffer不断下溢

				terminate = 3	=>	即进行了qscale*=1.01,使得buffer上溢
									又进行了qscale/=1.01,使得buffer下溢
									则结束。
			*/
            for( int iterations = 0; iterations < 1000 && terminate != 3; iterations++ )
            {
                double frame_q[3];

				//根据当前帧的satd和qscale估算编码当前帧所需的bits
                double cur_bits = predict_size( &rcc->pred[h->sh.i_type], q, rcc->last_satd );
				
				//当前编码帧流出
                double buffer_fill_cur = rcc->buffer_fill - cur_bits;

                double target_fill;
                double total_duration = 0;
                double last_duration = fenc_cpb_duration;

				//以当前帧的QP为基准,根据ip_factor和pb_factor来推算I/P/B三个类型帧的QP
                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;

                /* Loop over the planned future frames. 
				  遍历planned future frames中已经确定了帧类型的每一帧
				  将buffer_fill_cur限制在[0, buffer_size]之内
				  
				  一边buffer模拟以最大vbv允许速率进行fill,即
				  buffer_fill_cur += rcc->vbv_max_rate * last_duration;
				  另一边buffer以估计的帧bits进行drain,即
				  buffer_fill_cur -= predict_size(planned future frames[j]);

				  最后buffer_fill_cur即为planned future frames输出后buffer的丰盈度  */
                for( int j = 0; buffer_fill_cur >= 0 && buffer_fill_cur <= rcc->buffer_size; j++ )
                {
					//累计duration
                    total_duration += last_duration;

					//以vbv_max_rate速率持续last_duration时间填充bufffer后的buffer_fill_cur
					//模拟注入buffer
                    buffer_fill_cur += rcc->vbv_max_rate * last_duration;

					/*得到planned future frames[j]帧的type和satd*/
                    int i_type = h->fenc->i_planned_type[j];
                    int i_satd = h->fenc->i_planned_satd[j];
                    if( i_type == X264_TYPE_AUTO )
                        break;
                    i_type = IS_X264_TYPE_I( i_type ) ? SLICE_TYPE_I : IS_X264_TYPE_B( i_type ) ? SLICE_TYPE_B : SLICE_TYPE_P;
                   
					//根据type和satd预测编码planned future frames[j]所需要的bits
					cur_bits = predict_size( &rcc->pred[i_type], frame_q[i_type], i_satd );

					//buffer_fill_cur - 编码planned future frames[j]帧所推算出来的bits
					//模拟流出buffer
                    buffer_fill_cur -= cur_bits;

					//更新last_duration
                    last_duration = h->fenc->f_planned_cpb_duration[j];
                }

                /* Try to get to get the buffer at least 50% filled, but don't set an impossible goal. */
				//计算下限,下限不高于50%
                target_fill = X264_MIN( rcc->buffer_fill + total_duration * rcc->vbv_max_rate * 0.5, rcc->buffer_size * 0.5 );
                if( buffer_fill_cur < target_fill )
                {	/*	低于下限,表明buffer出水过大,
						则应该调高qscale使得帧的bits变小 */
                    q *= 1.01;		//上调qscale
                    terminate |= 1;	//标记
                    continue;
                }

                /* Try to get the buffer no more than 80% filled, but don't set an impossible goal. */
				//计算上限,上限只能在80%到100%之间
                target_fill = x264_clip3f( rcc->buffer_fill - total_duration * rcc->vbv_max_rate * 0.5, rcc->buffer_size * 0.8, rcc->buffer_size );
                if( rcc->b_vbv_min_rate && buffer_fill_cur > target_fill )
                {	/*	高于上限,表明buffer出水过小
						则应调低qscale使得帧的bits变大*/
                    q /= 1.01;		//下调qscale
                    terminate |= 2;	//标记
                    continue;
                }

				//若满足上述两个条件,则结束,停止qscale的调整
                break;
            }
        }	//end of lookahead vbv
		else	//Fallback to old purely-reactive algorithm: no lookahead
        {
            if( ( pict_type == SLICE_TYPE_P ||
                ( pict_type == SLICE_TYPE_I && rcc->last_non_b_pict_type == SLICE_TYPE_I ) ) &&
                rcc->buffer_fill/rcc->buffer_size < 0.5 )
            {	/* 当前P帧	|| (当前I帧 && 上一个非B帧也是I帧) && buffer_fill在一半以下
				   当前buffer_fill过低,且当前帧是I/P,即码率较高,输出后可能照成buffer下溢
				   即调高qscale,减少当前I/P帧的码率,避免下溢 */
                q /= x264_clip3f( 2.0*rcc->buffer_fill/rcc->buffer_size, 0.5, 1.0 );
            }

            /* Now a hard threshold to make sure the frame fits in VBV.
             * This one is mostly for I-frames. */

			//根据satd和qscale估算当前帧的bits开销
            double bits = predict_size( &rcc->pred[h->sh.i_type], q, rcc->last_satd );

            /* For small VBVs, allow the frame to use up the entire VBV. */
			//
            double max_fill_factor = h->param.rc.i_vbv_buffer_size >= 5*h->param.rc.i_vbv_max_bitrate / rcc->fps ? 2 : 1;
            
			/* For single-frame VBVs, request that the frame use up the entire VBV. */
            double min_fill_factor = rcc->single_frame_vbv ? 1 : 2;

            if( bits > rcc->buffer_fill/max_fill_factor )
            {	/* 若max_fill_factor * bits  > buffer_fill
				   则以buffer_fill为目标计算比例,将q放大和bits缩小 */
                double qf = x264_clip3f( rcc->buffer_fill/(max_fill_factor*bits), 0.2, 1.0 );
                q /= qf;
                bits *= qf;
            }
            if( bits < rcc->buffer_rate/min_fill_factor )
            {
				/* 若min_fill_factor * bits < buffer_rate
				   则以buffer_rate为目标计算比例,将q缩小,为什么不放大bits? */
                double qf = x264_clip3f( bits*min_fill_factor/rcc->buffer_rate, 0.001, 1.0 );
                q *= qf;
            }
            q = X264_MAX( q0, q );	//qscale只能比原来高  
        }	//end of old purely-reactive algorithm

        /* Check B-frame complexity, and use up any bits that would
         * overflow before the next P-frame. */
        if( h->sh.i_type == SLICE_TYPE_P && !rcc->single_frame_vbv )
        {	//若当前帧是P帧
            int nb = rcc->bframes;
			//估计当前P帧的bits
            double bits = predict_size( &rcc->pred[h->sh.i_type], q, rcc->last_satd );
			//pbbits = P帧+nb个B帧的bits和
            double pbbits = bits;
			//由当前P帧的satd估计其附属的B帧的bits
            double bbits = predict_size( rcc->pred_b_from_p, q * h->param.rc.f_pb_factor, rcc->last_satd );
            double space;
            double bframe_cpb_duration = 0;
            double minigop_cpb_duration;
			
			//计算所有B帧的duration总和
            for( int i = 0; i < nb; i++ )
                bframe_cpb_duration += h->fenc->f_planned_cpb_duration[i];

			/* 若nb个B帧的bits和流失量 > 这nb个B帧时间内进行vbv_max_rate注入量
			   则nb置0?? */
            if( bbits * nb > bframe_cpb_duration * rcc->vbv_max_rate )
                nb = 0;
            pbbits += nb * bbits;	//计算P帧及其前面连续B帧的bits和

			//计算P帧和nb个B帧的duration和
            minigop_cpb_duration = bframe_cpb_duration + fenc_cpb_duration;

			//计算minigop_cpb_duration时间内以最大速率填充buffer照成的溢出量space
            space = rcc->buffer_fill + minigop_cpb_duration*rcc->vbv_max_rate - rcc->buffer_size;

			/* 若P帧和nb个B帧的输出量 < 溢出量space,则会造成buffer上溢出
			   则下调 */
            if( pbbits < space )
            {	//下调qscale,给予帧更多的bits
                q *= X264_MAX( pbbits / space, bits / (0.5 * rcc->buffer_size) );
            }

			//限制qscale不能下调太多,最多一半,保证P帧画面质量,以及码率的稳定性
            q = X264_MAX( q0/2, q );
        }	//end of P-frames约束

        /* Apply MinCR and buffer fill restrictions */
		//重新基于修改后的qscale预测帧的bits
        double bits = predict_size( &rcc->pred[h->sh.i_type], q, rcc->last_satd );
		//计算帧最大所允许的大小frame_size_maximum
        double frame_size_maximum = X264_MIN( rcc->frame_size_maximum, X264_MAX( rcc->buffer_fill, 0.001 ) );
        //若超出帧最大允许大小,则等比例放大qscale,即缩小bits
		if( bits > frame_size_maximum )
            q *= bits / frame_size_maximum;
		     

        if( !rcc->b_vbv_min_rate )
            q = X264_MAX( q0, q );
    }	// end of (vbv && satd)

	//夹逼,返回qscale
    if( lmin==lmax )
        return lmin;
    else if( rcc->b_2pass )	//2pass
    {	//计算公式
        double min2 = log( lmin );
        double max2 = log( lmax );
        q = (log(q) - min2)/(max2-min2) - 0.5;
        q = 1.0/(1.0 + exp( -4*q ));
        q = q*(max2-min2) + min2;
        return exp( q );
    }
    else //将qscale限制在lmin和lmax中
        return x264_clip3f( q, lmin, lmax );
}

你可能感兴趣的:(X264)