码控-predict_size()/predict_row_size() / update_predictor()

x264中通过satd和qscale估计bits的模型为线性模型:
bits * qscale = A * satd + B
其中A即coeff,B即offset,则有
coeff = (bits * qscale - coeff) / satd
offset = bits * qscale - coeff * satd

bits估计模型结构体:

typedef struct
{
    float coeff_min;//系数A的下界
    float coeff;	//线性模型的系数A
    float count;	//
    float decay;	//衰变系数
    float offset;	//线性模型的偏移量B
} predictor_t;

帧级bits估计:predict_size()

/*
	根据帧的satd和qscale来估计帧的bits开销
	p:一组用于satd=>bits的参数
	q:qscale
	var:satd

	过程:
	bits = (coeff * satd +offset) / (qscale * count)
*/
static float predict_size( predictor_t *p, float q, float var )
{
    return (p->coeff*var + p->offset) / (q*p->count);
}

行级bits估计:predict_row_size()

/*
	根据qscale来预测第y行的bits开销

	过程:
		1.根据第y行的satd和qscale来预测行的bits开销pred_s
		2.调整
			·若是Islice,或当前帧行的qscale >= 前向参考帧行的qscale,则
				·若当前帧&&前向参考帧都Pslice,且两帧satd差 < 当前帧satd一半,则
					1.等coeff系数计算当前帧bits开销pred_t
					2.求pred_s和pred_t的平均,返回
				·若当前帧&&前向参考帧不都是Pslice,或两帧satd差 >= 当前帧satd一半,则直接返回pred_s
			·若P/Bslice,且当前帧行的qscale < 前向参考帧行的qscale,则
				1.单独根据行的帧内satd预测帧内的bits开销pred_intra
				2.返回pred_intra+pred_s
*/
static float predict_row_size( x264_t *h, int y, float qscale )
{
    /* average between two predictors:
     * absolute SATD, and scaled bit cost of the colocated row in the previous frame */
    x264_ratecontrol_t *rc = h->rc;

	//根据行bits预测参数结构体、qscale和行satd来预测当前行(第y行)的bits
    float pred_s = predict_size( &rc->row_pred[0], qscale, h->fdec->i_row_satd[y] );

    if( h->sh.i_type == SLICE_TYPE_I || qscale >= h->fref[0][0]->f_row_qscale[y] )
    {	//若是Islice,或当前帧qscale > 前向参考帧对应行的qscale
        if( h->sh.i_type == SLICE_TYPE_P
            && h->fref[0][0]->i_type == h->fdec->i_type
            && h->fref[0][0]->f_row_qscale[y] > 0
            && h->fref[0][0]->i_row_satd[y] > 0
            && (abs(h->fref[0][0]->i_row_satd[y] - h->fdec->i_row_satd[y]) < h->fdec->i_row_satd[y]/2))
        {	/*	前向参考帧与当前帧类型都为Pslice && 
				前向参考帧与当前帧对应行的satd之差在当前帧satd的一半以内
				则表明两帧对应行很相似,可以相似计算:

				 ref_bits * ref_qscale     cur_bits * cur_qscale
				----------------------- = ------------------- = coeff
				      ret_satd                  cur_satd

					          ref_bits * ref_qscale * cur_satd
			=>  cur_bits = ----------------------------------------
									ref_satd * cur_qscale					*/
            float pred_t = h->fref[0][0]->i_row_bits[y] * h->fdec->i_row_satd[y] / h->fref[0][0]->i_row_satd[y]
                         * h->fref[0][0]->f_row_qscale[y] / qscale;

			//取之前预测的bits 与 相似计算的bits 的均值
            return (pred_s + pred_t) * 0.5f;
        }
        return pred_s;
    }
    /* Our QP is lower than the reference! */
    else	//当前帧qscale < 前向参考帧对应行的qscale
    {
		//根据帧内的行satd、qscale来预测行尺寸
		//注意i_row_satd[y]包含行内所有的帧间/帧内satd,而i_row_satds[0][0][y]只包含行帧内satd
        float pred_intra = predict_size( &rc->row_pred[1], qscale, h->fdec->i_row_satds[0][0][y] );
        /* Sum: better to overestimate than underestimate by using only one of the two predictors. */
		//返回和,我不是很明白这个用意
        return pred_intra + pred_s;
    }
}

bits估计参数结构体更新:update_predictor()

/*
	更新predictor_t结构体内的数据,
	其中predictor_t p是一组通过帧satd来估计其bits开销所需的参数

	p:要更新的一组参数
	q:qscale
	var:satd
	bits:帧的bits开销
*/
static void update_predictor( predictor_t *p, float q, float var, float bits )
{
    float range = 1.5;
    if( var < 10 )
        return;
    float old_coeff = p->coeff / p->count;
    float old_offset = p->offset / p->count;

	/* 计算新的coeff,即 (bits*q - old_offset)/satd
	   新的coeff有一个下限,且其必须在旧coeff的一定范围内上下波动,不能波动太大  */
    float new_coeff = X264_MAX( (bits*q - old_offset) / var, p->coeff_min );
    float new_coeff_clipped = x264_clip3f( new_coeff, old_coeff/range, old_coeff*range );

	//计算新的offset,即 bits*q - offset*satd
    float new_offset = bits*q - new_coeff_clipped * var;
    if( new_offset >= 0 )
        new_coeff = new_coeff_clipped;
    else
        new_offset = 0;

	//count coeff offset先衰变
    p->count  *= p->decay;
    p->coeff  *= p->decay;
    p->offset *= p->decay;

	//count coeff offset再更新
    p->count  ++;
    p->coeff  += new_coeff;
    p->offset += new_offset;
}
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值