📄 ratecontrol.c
字号:
/*
* Rate control for video encoders
*
* Copyright (c) 2002-2004 Michael Niedermayer <michaelni@gmx.at>
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/**
* @file ratecontrol.c
* Rate control for video encoders.
*/
#include "avcodec.h"
#include "dsputil.h"
#include "ratecontrol.h"
#include "mpegvideo.h"
#include "eval.h"
#undef NDEBUG // Always check asserts, the speed effect is far too small to disable them.
#include <assert.h>
#ifndef M_E
#define M_E 2.718281828
#endif
static int init_pass2(MpegEncContext *s);
static double get_qscale(MpegEncContext *s, RateControlEntry *rce, double rate_factor, int frame_num);
void ff_write_pass1_stats(MpegEncContext *s){
snprintf(s->avctx->stats_out, 256, "in:%d out:%d type:%d q:%d itex:%d ptex:%d mv:%d misc:%d fcode:%d bcode:%d mc-var:%d var:%d icount:%d skipcount:%d hbits:%d;\n",
s->current_picture_ptr->display_picture_number, s->current_picture_ptr->coded_picture_number, s->pict_type,
s->current_picture.quality, s->i_tex_bits, s->p_tex_bits, s->mv_bits, s->misc_bits,
s->f_code, s->b_code, s->current_picture.mc_mb_var_sum, s->current_picture.mb_var_sum, s->i_count, s->skip_count, s->header_bits);
}
static inline double qp2bits(RateControlEntry *rce, double qp){
if(qp<=0.0){
av_log(NULL, AV_LOG_ERROR, "qp<=0.0\n");
}
return rce->qscale * (double)(rce->i_tex_bits + rce->p_tex_bits+1)/ qp;
}
static inline double bits2qp(RateControlEntry *rce, double bits){
if(bits<0.9){
av_log(NULL, AV_LOG_ERROR, "bits<0.9\n");
}
return rce->qscale * (double)(rce->i_tex_bits + rce->p_tex_bits+1)/ bits;
}
int ff_rate_control_init(MpegEncContext *s)
{
RateControlContext *rcc= &s->rc_context;
int i;
char *error = NULL;
static const char *const_names[]={
"PI",
"E",
"iTex",
"pTex",
"tex",
"mv",
"fCode",
"iCount",
"mcVar",
"var",
"isI",
"isP",
"isB",
"avgQP",
"qComp",
/* "lastIQP",
"lastPQP",
"lastBQP",
"nextNonBQP",*/
"avgIITex",
"avgPITex",
"avgPPTex",
"avgBPTex",
"avgTex",
NULL
};
static double (*func1[])(void *, double)={
(void *)bits2qp,
(void *)qp2bits,
NULL
};
static const char *func1_names[]={
"bits2qp",
"qp2bits",
NULL
};
emms_c();
rcc->rc_eq_eval = ff_parse(s->avctx->rc_eq, const_names, func1, func1_names, NULL, NULL, &error);
if (!rcc->rc_eq_eval) {
av_log(s->avctx, AV_LOG_ERROR, "Error parsing rc_eq \"%s\": %s\n", s->avctx->rc_eq, error? error : "");
return -1;
}
for(i=0; i<5; i++){
rcc->pred[i].coeff= FF_QP2LAMBDA * 7.0;
rcc->pred[i].count= 1.0;
rcc->pred[i].decay= 0.4;
rcc->i_cplx_sum [i]=
rcc->p_cplx_sum [i]=
rcc->mv_bits_sum[i]=
rcc->qscale_sum [i]=
rcc->frame_count[i]= 1; // 1 is better cuz of 1/0 and such
rcc->last_qscale_for[i]=FF_QP2LAMBDA * 5;
}
rcc->buffer_index= s->avctx->rc_initial_buffer_occupancy;
if(s->flags&CODEC_FLAG_PASS2){
int i;
char *p;
/* find number of pics */
p= s->avctx->stats_in;
for(i=-1; p; i++){
p= strchr(p+1, ';');
}
i+= s->max_b_frames;
if(i<=0 || i>=INT_MAX / sizeof(RateControlEntry))
return -1;
rcc->entry = (RateControlEntry*)av_mallocz(i*sizeof(RateControlEntry));
rcc->num_entries= i;
/* init all to skipped p frames (with b frames we might have a not encoded frame at the end FIXME) */
for(i=0; i<rcc->num_entries; i++){
RateControlEntry *rce= &rcc->entry[i];
rce->pict_type= rce->new_pict_type=P_TYPE;
rce->qscale= rce->new_qscale=FF_QP2LAMBDA * 2;
rce->misc_bits= s->mb_num + 10;
rce->mb_var_sum= s->mb_num*100;
}
/* read stats */
p= s->avctx->stats_in;
for(i=0; i<rcc->num_entries - s->max_b_frames; i++){
RateControlEntry *rce;
int picture_number;
int e;
char *next;
next= strchr(p, ';');
if(next){
(*next)=0; //sscanf in unbelievably slow on looong strings //FIXME copy / do not write
next++;
}
e= sscanf(p, " in:%d ", &picture_number);
assert(picture_number >= 0);
assert(picture_number < rcc->num_entries);
rce= &rcc->entry[picture_number];
e+=sscanf(p, " in:%*d out:%*d type:%d q:%f itex:%d ptex:%d mv:%d misc:%d fcode:%d bcode:%d mc-var:%d var:%d icount:%d skipcount:%d hbits:%d",
&rce->pict_type, &rce->qscale, &rce->i_tex_bits, &rce->p_tex_bits, &rce->mv_bits, &rce->misc_bits,
&rce->f_code, &rce->b_code, &rce->mc_mb_var_sum, &rce->mb_var_sum, &rce->i_count, &rce->skip_count, &rce->header_bits);
if(e!=14){
av_log(s->avctx, AV_LOG_ERROR, "statistics are damaged at line %d, parser out=%d\n", i, e);
return -1;
}
p= next;
}
if(init_pass2(s) < 0) return -1;
//FIXME maybe move to end
if((s->flags&CODEC_FLAG_PASS2) && s->avctx->rc_strategy == FF_RC_STRATEGY_XVID) {
#ifdef CONFIG_LIBXVID
return ff_xvid_rate_control_init(s);
#else
av_log(s->avctx, AV_LOG_ERROR, "XviD ratecontrol requires libavcodec compiled with XviD support\n");
return -1;
#endif
}
}
if(!(s->flags&CODEC_FLAG_PASS2)){
rcc->short_term_qsum=0.001;
rcc->short_term_qcount=0.001;
rcc->pass1_rc_eq_output_sum= 0.001;
rcc->pass1_wanted_bits=0.001;
if(s->avctx->qblur > 1.0){
av_log(s->avctx, AV_LOG_ERROR, "qblur too large\n");
return -1;
}
/* init stuff with the user specified complexity */
if(s->avctx->rc_initial_cplx){
for(i=0; i<60*30; i++){
double bits= s->avctx->rc_initial_cplx * (i/10000.0 + 1.0)*s->mb_num;
RateControlEntry rce;
double q;
if (i%((s->gop_size+3)/4)==0) rce.pict_type= I_TYPE;
else if(i%(s->max_b_frames+1)) rce.pict_type= B_TYPE;
else rce.pict_type= P_TYPE;
rce.new_pict_type= rce.pict_type;
rce.mc_mb_var_sum= bits*s->mb_num/100000;
rce.mb_var_sum = s->mb_num;
rce.qscale = FF_QP2LAMBDA * 2;
rce.f_code = 2;
rce.b_code = 1;
rce.misc_bits= 1;
if(s->pict_type== I_TYPE){
rce.i_count = s->mb_num;
rce.i_tex_bits= bits;
rce.p_tex_bits= 0;
rce.mv_bits= 0;
}else{
rce.i_count = 0; //FIXME we do know this approx
rce.i_tex_bits= 0;
rce.p_tex_bits= bits*0.9;
rce.mv_bits= bits*0.1;
}
rcc->i_cplx_sum [rce.pict_type] += rce.i_tex_bits*rce.qscale;
rcc->p_cplx_sum [rce.pict_type] += rce.p_tex_bits*rce.qscale;
rcc->mv_bits_sum[rce.pict_type] += rce.mv_bits;
rcc->frame_count[rce.pict_type] ++;
bits= rce.i_tex_bits + rce.p_tex_bits;
q= get_qscale(s, &rce, rcc->pass1_wanted_bits/rcc->pass1_rc_eq_output_sum, i);
rcc->pass1_wanted_bits+= s->bit_rate/(1/av_q2d(s->avctx->time_base)); //FIXME misbehaves a little for variable fps
}
}
}
return 0;
}
void ff_rate_control_uninit(MpegEncContext *s)
{
RateControlContext *rcc= &s->rc_context;
emms_c();
ff_eval_free(rcc->rc_eq_eval);
av_freep(&rcc->entry);
#ifdef CONFIG_LIBXVID
if((s->flags&CODEC_FLAG_PASS2) && s->avctx->rc_strategy == FF_RC_STRATEGY_XVID)
ff_xvid_rate_control_uninit(s);
#endif
}
int ff_vbv_update(MpegEncContext *s, int frame_size){
RateControlContext *rcc= &s->rc_context;
const double fps= 1/av_q2d(s->avctx->time_base);
const int buffer_size= s->avctx->rc_buffer_size;
const double min_rate= s->avctx->rc_min_rate/fps;
const double max_rate= s->avctx->rc_max_rate/fps;
//printf("%d %f %d %f %f\n", buffer_size, rcc->buffer_index, frame_size, min_rate, max_rate);
if(buffer_size){
int left;
rcc->buffer_index-= frame_size;
if(rcc->buffer_index < 0){
av_log(s->avctx, AV_LOG_ERROR, "rc buffer underflow\n");
rcc->buffer_index= 0;
}
left= buffer_size - rcc->buffer_index - 1;
rcc->buffer_index += av_clip(left, min_rate, max_rate);
if(rcc->buffer_index > buffer_size){
int stuffing= ceil((rcc->buffer_index - buffer_size)/8);
if(stuffing < 4 && s->codec_id == CODEC_ID_MPEG4)
stuffing=4;
rcc->buffer_index -= 8*stuffing;
if(s->avctx->debug & FF_DEBUG_RC)
av_log(s->avctx, AV_LOG_DEBUG, "stuffing %d bytes\n", stuffing);
return stuffing;
}
}
return 0;
}
/**
* modifies the bitrate curve from pass1 for one frame
*/
static double get_qscale(MpegEncContext *s, RateControlEntry *rce, double rate_factor, int frame_num){
RateControlContext *rcc= &s->rc_context;
AVCodecContext *a= s->avctx;
double q, bits;
const int pict_type= rce->new_pict_type;
const double mb_num= s->mb_num;
int i;
double const_values[]={
M_PI,
M_E,
rce->i_tex_bits*rce->qscale,
rce->p_tex_bits*rce->qscale,
(rce->i_tex_bits + rce->p_tex_bits)*(double)rce->qscale,
rce->mv_bits/mb_num,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -