📄 ratecontrol.c
字号:
rce->pict_type == B_TYPE ? (rce->f_code + rce->b_code)*0.5 : rce->f_code,
rce->i_count/mb_num,
rce->mc_mb_var_sum/mb_num,
rce->mb_var_sum/mb_num,
rce->pict_type == I_TYPE,
rce->pict_type == P_TYPE,
rce->pict_type == B_TYPE,
rcc->qscale_sum[pict_type] / (double)rcc->frame_count[pict_type],
a->qcompress,
/* rcc->last_qscale_for[I_TYPE],
rcc->last_qscale_for[P_TYPE],
rcc->last_qscale_for[B_TYPE],
rcc->next_non_b_qscale,*/
rcc->i_cplx_sum[I_TYPE] / (double)rcc->frame_count[I_TYPE],
rcc->i_cplx_sum[P_TYPE] / (double)rcc->frame_count[P_TYPE],
rcc->p_cplx_sum[P_TYPE] / (double)rcc->frame_count[P_TYPE],
rcc->p_cplx_sum[B_TYPE] / (double)rcc->frame_count[B_TYPE],
(rcc->i_cplx_sum[pict_type] + rcc->p_cplx_sum[pict_type]) / (double)rcc->frame_count[pict_type],
0
};
bits= ff_parse_eval(rcc->rc_eq_eval, const_values, rce);
if (isnan(bits)) {
av_log(s->avctx, AV_LOG_ERROR, "Error evaluating rc_eq \"%s\"\n", s->avctx->rc_eq);
return -1;
}
rcc->pass1_rc_eq_output_sum+= bits;
bits*=rate_factor;
if(bits<0.0) bits=0.0;
bits+= 1.0; //avoid 1/0 issues
/* user override */
for(i=0; i<s->avctx->rc_override_count; i++){
RcOverride *rco= s->avctx->rc_override;
if(rco[i].start_frame > frame_num) continue;
if(rco[i].end_frame < frame_num) continue;
if(rco[i].qscale)
bits= qp2bits(rce, rco[i].qscale); //FIXME move at end to really force it?
else
bits*= rco[i].quality_factor;
}
q= bits2qp(rce, bits);
/* I/B difference */
if (pict_type==I_TYPE && s->avctx->i_quant_factor<0.0)
q= -q*s->avctx->i_quant_factor + s->avctx->i_quant_offset;
else if(pict_type==B_TYPE && s->avctx->b_quant_factor<0.0)
q= -q*s->avctx->b_quant_factor + s->avctx->b_quant_offset;
if(q<1) q=1;
return q;
}
static double get_diff_limited_q(MpegEncContext *s, RateControlEntry *rce, double q){
RateControlContext *rcc= &s->rc_context;
AVCodecContext *a= s->avctx;
const int pict_type= rce->new_pict_type;
const double last_p_q = rcc->last_qscale_for[P_TYPE];
const double last_non_b_q= rcc->last_qscale_for[rcc->last_non_b_pict_type];
if (pict_type==I_TYPE && (a->i_quant_factor>0.0 || rcc->last_non_b_pict_type==P_TYPE))
q= last_p_q *FFABS(a->i_quant_factor) + a->i_quant_offset;
else if(pict_type==B_TYPE && a->b_quant_factor>0.0)
q= last_non_b_q* a->b_quant_factor + a->b_quant_offset;
if(q<1) q=1;
/* last qscale / qdiff stuff */
if(rcc->last_non_b_pict_type==pict_type || pict_type!=I_TYPE){
double last_q= rcc->last_qscale_for[pict_type];
const int maxdiff= FF_QP2LAMBDA * a->max_qdiff;
if (q > last_q + maxdiff) q= last_q + maxdiff;
else if(q < last_q - maxdiff) q= last_q - maxdiff;
}
rcc->last_qscale_for[pict_type]= q; //Note we cannot do that after blurring
if(pict_type!=B_TYPE)
rcc->last_non_b_pict_type= pict_type;
return q;
}
/**
* gets the qmin & qmax for pict_type
*/
static void get_qminmax(int *qmin_ret, int *qmax_ret, MpegEncContext *s, int pict_type){
int qmin= s->avctx->lmin;
int qmax= s->avctx->lmax;
assert(qmin <= qmax);
if(pict_type==B_TYPE){
qmin= (int)(qmin*FFABS(s->avctx->b_quant_factor)+s->avctx->b_quant_offset + 0.5);
qmax= (int)(qmax*FFABS(s->avctx->b_quant_factor)+s->avctx->b_quant_offset + 0.5);
}else if(pict_type==I_TYPE){
qmin= (int)(qmin*FFABS(s->avctx->i_quant_factor)+s->avctx->i_quant_offset + 0.5);
qmax= (int)(qmax*FFABS(s->avctx->i_quant_factor)+s->avctx->i_quant_offset + 0.5);
}
qmin= av_clip(qmin, 1, FF_LAMBDA_MAX);
qmax= av_clip(qmax, 1, FF_LAMBDA_MAX);
if(qmax<qmin) qmax= qmin;
*qmin_ret= qmin;
*qmax_ret= qmax;
}
static double modify_qscale(MpegEncContext *s, RateControlEntry *rce, double q, int frame_num){
RateControlContext *rcc= &s->rc_context;
int qmin, qmax;
double bits;
const int pict_type= rce->new_pict_type;
const double buffer_size= s->avctx->rc_buffer_size;
const double fps= 1/av_q2d(s->avctx->time_base);
const double min_rate= s->avctx->rc_min_rate / fps;
const double max_rate= s->avctx->rc_max_rate / fps;
get_qminmax(&qmin, &qmax, s, pict_type);
/* modulation */
if(s->avctx->rc_qmod_freq && frame_num%s->avctx->rc_qmod_freq==0 && pict_type==P_TYPE)
q*= s->avctx->rc_qmod_amp;
bits= qp2bits(rce, q);
//printf("q:%f\n", q);
/* buffer overflow/underflow protection */
if(buffer_size){
double expected_size= rcc->buffer_index;
double q_limit;
if(min_rate){
double d= 2*(buffer_size - expected_size)/buffer_size;
if(d>1.0) d=1.0;
else if(d<0.0001) d=0.0001;
q*= pow(d, 1.0/s->avctx->rc_buffer_aggressivity);
q_limit= bits2qp(rce, FFMAX((min_rate - buffer_size + rcc->buffer_index)*3, 1));
if(q > q_limit){
if(s->avctx->debug&FF_DEBUG_RC){
av_log(s->avctx, AV_LOG_DEBUG, "limiting QP %f -> %f\n", q, q_limit);
}
q= q_limit;
}
}
if(max_rate){
double d= 2*expected_size/buffer_size;
if(d>1.0) d=1.0;
else if(d<0.0001) d=0.0001;
q/= pow(d, 1.0/s->avctx->rc_buffer_aggressivity);
q_limit= bits2qp(rce, FFMAX(rcc->buffer_index/3, 1));
if(q < q_limit){
if(s->avctx->debug&FF_DEBUG_RC){
av_log(s->avctx, AV_LOG_DEBUG, "limiting QP %f -> %f\n", q, q_limit);
}
q= q_limit;
}
}
}
//printf("q:%f max:%f min:%f size:%f index:%d bits:%f agr:%f\n", q,max_rate, min_rate, buffer_size, rcc->buffer_index, bits, s->avctx->rc_buffer_aggressivity);
if(s->avctx->rc_qsquish==0.0 || qmin==qmax){
if (q<qmin) q=qmin;
else if(q>qmax) q=qmax;
}else{
double min2= log(qmin);
double max2= log(qmax);
q= log(q);
q= (q - min2)/(max2-min2) - 0.5;
q*= -4.0;
q= 1.0/(1.0 + exp(q));
q= q*(max2-min2) + min2;
q= exp(q);
}
return q;
}
//----------------------------------
// 1 Pass Code
static double predict_size(Predictor *p, double q, double var)
{
return p->coeff*var / (q*p->count);
}
/*
static double predict_qp(Predictor *p, double size, double var)
{
//printf("coeff:%f, count:%f, var:%f, size:%f//\n", p->coeff, p->count, var, size);
return p->coeff*var / (size*p->count);
}
*/
static void update_predictor(Predictor *p, double q, double var, double size)
{
double new_coeff= size*q / (var + 1);
if(var<10) return;
p->count*= p->decay;
p->coeff*= p->decay;
p->count++;
p->coeff+= new_coeff;
}
static void adaptive_quantization(MpegEncContext *s, double q){
int i;
const float lumi_masking= s->avctx->lumi_masking / (128.0*128.0);
const float dark_masking= s->avctx->dark_masking / (128.0*128.0);
const float temp_cplx_masking= s->avctx->temporal_cplx_masking;
const float spatial_cplx_masking = s->avctx->spatial_cplx_masking;
const float p_masking = s->avctx->p_masking;
const float border_masking = s->avctx->border_masking;
float bits_sum= 0.0;
float cplx_sum= 0.0;
float cplx_tab[s->mb_num];
float bits_tab[s->mb_num];
const int qmin= s->avctx->mb_lmin;
const int qmax= s->avctx->mb_lmax;
Picture * const pic= &s->current_picture;
const int mb_width = s->mb_width;
const int mb_height = s->mb_height;
for(i=0; i<s->mb_num; i++){
const int mb_xy= s->mb_index2xy[i];
float temp_cplx= sqrt(pic->mc_mb_var[mb_xy]); //FIXME merge in pow()
float spat_cplx= sqrt(pic->mb_var[mb_xy]);
const int lumi= pic->mb_mean[mb_xy];
float bits, cplx, factor;
int mb_x = mb_xy % s->mb_stride;
int mb_y = mb_xy / s->mb_stride;
int mb_distance;
float mb_factor = 0.0;
#if 0
if(spat_cplx < q/3) spat_cplx= q/3; //FIXME finetune
if(temp_cplx < q/3) temp_cplx= q/3; //FIXME finetune
#endif
if(spat_cplx < 4) spat_cplx= 4; //FIXME finetune
if(temp_cplx < 4) temp_cplx= 4; //FIXME finetune
if((s->mb_type[mb_xy]&CANDIDATE_MB_TYPE_INTRA)){//FIXME hq mode
cplx= spat_cplx;
factor= 1.0 + p_masking;
}else{
cplx= temp_cplx;
factor= pow(temp_cplx, - temp_cplx_masking);
}
factor*=pow(spat_cplx, - spatial_cplx_masking);
if(lumi>127)
factor*= (1.0 - (lumi-128)*(lumi-128)*lumi_masking);
else
factor*= (1.0 - (lumi-128)*(lumi-128)*dark_masking);
if(mb_x < mb_width/5){
mb_distance = mb_width/5 - mb_x;
mb_factor = (float)mb_distance / (float)(mb_width/5);
}else if(mb_x > 4*mb_width/5){
mb_distance = mb_x - 4*mb_width/5;
mb_factor = (float)mb_distance / (float)(mb_width/5);
}
if(mb_y < mb_height/5){
mb_distance = mb_height/5 - mb_y;
mb_factor = FFMAX(mb_factor, (float)mb_distance / (float)(mb_height/5));
}else if(mb_y > 4*mb_height/5){
mb_distance = mb_y - 4*mb_height/5;
mb_factor = FFMAX(mb_factor, (float)mb_distance / (float)(mb_height/5));
}
factor*= 1.0 - border_masking*mb_factor;
if(factor<0.00001) factor= 0.00001;
bits= cplx*factor;
cplx_sum+= cplx;
bits_sum+= bits;
cplx_tab[i]= cplx;
bits_tab[i]= bits;
}
/* handle qmin/qmax clipping */
if(s->flags&CODEC_FLAG_NORMALIZE_AQP){
float factor= bits_sum/cplx_sum;
for(i=0; i<s->mb_num; i++){
float newq= q*cplx_tab[i]/bits_tab[i];
newq*= factor;
if (newq > qmax){
bits_sum -= bits_tab[i];
cplx_sum -= cplx_tab[i]*q/qmax;
}
else if(newq < qmin){
bits_sum -= bits_tab[i];
cplx_sum -= cplx_tab[i]*q/qmin;
}
}
if(bits_sum < 0.001) bits_sum= 0.001;
if(cplx_sum < 0.001) cplx_sum= 0.001;
}
for(i=0; i<s->mb_num; i++){
const int mb_xy= s->mb_index2xy[i];
float newq= q*cplx_tab[i]/bits_tab[i];
int intq;
if(s->flags&CODEC_FLAG_NORMALIZE_AQP){
newq*= bits_sum/cplx_sum;
}
intq= (int)(newq + 0.5);
if (intq > qmax) intq= qmax;
else if(intq < qmin) intq= qmin;
//if(i%s->mb_width==0) printf("\n");
//printf("%2d%3d ", intq, ff_sqrt(s->mc_mb_var[i]));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -