support for the new ratecontrol code

git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@7089 b3059339-0415-0410-9bf9-f77b7e298cf2
This commit is contained in:
michael 2002-08-25 21:43:22 +00:00
parent e52cb91a66
commit a2eebbfa2d
2 changed files with 211 additions and 25 deletions

View File

@ -12,8 +12,8 @@ vqmin 2-31 (minimum quantizer) for pass1/2
weird things: msmpeg4, h263 will be very low quality
ratecontrol will be confused -> lower quality
some decoders will not be able to decode it
2 is recommended for normal mpeg4/mpeg1video encoding
3 is recommended for h263(p)/msmpeg4 (default)
2 is recommended for normal mpeg4/mpeg1video encoding (default)
3 is recommended for h263(p)/msmpeg4
the reason for 3 instead of 2 is that 2 could lead to overflows
(this will be fixed for h263(p) by changing the quanizer per MB in
the future, but msmpeg4 doesnt support that so it cant be fixed for
@ -26,7 +26,7 @@ vqscale 1-31 quantizer for constant quantizer / constant quality encoding
see vqmin
vqmax 1-31 (maximum quantizer) for pass1/2
15 default
31 default
10-31 should be a sane range
vqdiff 1-31 (maximum quantizer difference between I or P frames) for pass1/2
@ -34,6 +34,7 @@ vqdiff 1-31 (maximum quantizer difference between I or P frames) for pass1/2
vmax_b_frames 0-4 (maximum number of B frames between non B frames)
0 no b frames (default)
0-2 is a sane range for mpeg4
vme 0-5 (motion estimation)
0 none (not recommanded, very lq)
@ -60,6 +61,7 @@ keyint 0-300 (maximum interval between keyframes)
0 no keyframes
>300 is not recommended as the quality might be bad (depends upon
decoder, encoder and luck)
for strict mpeg1/2/4 compliance this would have to be <=132
vb_strategy 0-1 for pass 2
0 allways use the max number of B frames (default)
@ -81,28 +83,89 @@ vratetol (filesize tolerance in kbit) for pass1/2
1000-100000 is a sane range
8000 is default
vb_qfactor (1.0-31.0) for pass1/2
(B-Frame quantizer = IP-Frame quantizer * vb_qfactor)
2.0 is default
vrc_maxrate (maximum bitrate in kbit/sec) for pass1/2
vrc_minrate (minimum bitrate in kbit/sec) for pass1/2
vrc_buf_size (buffer size in kbit) for pass1/2
this is for stuff like VCD
VCD: FIXME
SVCD: ...
DVD: ...
Note: vratetol should not be too large during the 2.pass or there might
be problems if vrc_(min|max)rate is used
vb_qfactor (-31.0-31.0) for pass1/2
1.25 is default
vi_qfactor (-31.0-31.0) for pass1/2
0.8 is default
vb_qoffset (-31.0-31.0) for pass1/2
1.25 is default
vi_qoffset (-31.0-31.0) for pass1/2
0.0 is default
if v{b|i}_qfactor > 0
I/B-Frame quantizer = P-Frame quantizer * v{b|i}_qfactor + v{b|i}_qoffset
else
do normal ratecontrol (dont lock to next P frame quantizer) and
set q= -q * v{b|i}_qfactor + v{b|i}_qoffset
tip: to do constant quantizer encoding with different quantizers for
I/P and B frames you can use:
vqmin=<ip_quant>:vqmax=<ip_quant>:vb_qfactor=<b_quant/ip_quant>
vqblur (0.0-1.0) quantizer blur (only for pass1)
vqblur (0.0-1.0) quantizer blur (pass1)
0.0 qblur disabled
0.5 is the default
1.0 average the quantizer over all previous frames
larger values will average the quantizer more over time so that it will
be changed slower
vqblur (0.0-99.0) quantizer blur (pass2)
gaussian blur (gaussian blur cant be done during pass 1 as the future quantizers arent known)
0.5 is the default
larger values will average the quantizer more over time so that it will
be changed slower
vqcomp (0.0-1.0) quantizer compression (for pass1/2)
0.0 constant bitrate encoding, so fast motion frames will get as many
bits as low motion (high motion scenes look bad)
0.5 (default)
1.0 constant quantizer encoding (low motion scenes look bad)
vqcomp quantizer compression (for pass1/2)
depends upon vrc_eq
vrc_strategy (0,1,2)
FIXME (different rate control strategies)
vrc_eq the main ratecontrol equation (for pass1/2)
1 constant bitrate
tex constant quality
1+(tex/avgTex-1)*qComp approximately the equation of the old ratecontrol code
tex^qComp with qcomp 0.5 or something like that (default)
infix operators: +,-,*,/,^
variables:
tex texture complexity
iTex,pTex intra, non intra texture complexity
avgTex average texture complexity
avgIITex average intra texture complexity in I frames
avgPITex average intra texture complexity in P frames
avgPPTex average non intra texture complexity in P frames
avgBPTex average non intra texture complexity in B frames
mv bits used for MVs
fCode maximum length of MV in log2 scale
iCount number of intra MBs / number of MBs
var spatial complexity
mcVar temporal complexity
qComp qcomp from the command line
isI, isP, isB is 1 if picture type is I/P/B else 0
Pi,E see ur favorite math book
functions:
max(a,b),min(a,b) maximum / minimum
gt(a,b) is 1 if a>b, 0 otherwise
lt(a,b) is 1 if a<b, 0 otherwise
eq(a,b) is 1 if a==b,0 otherwise
sin,cos,tan,sinh,cosh,tanh,exp,log,abs
vrc_override user specified quality for specific parts (ending credits ...) (for pass1/2)
<start-frame>,<end-frame>,<quality>[/<start-frame>,<end-frame>,<quality>[/...]]
quality 2..31 -> quantizer
quality -500..0 -> quality correcture in %
vrc_init_cplx (0-1000) initial complexity for pass1
vqsquish (0 or 1) for pass1/2 how to keep the quantizer between qmin & qmax
0 use cliping
1 use a nice differentiable function (default)
vlelim (-1000-1000) single coefficient elimination threshold for luminance
0 disabled (default)
@ -163,7 +226,7 @@ FAQ: Q: Why is the filesize much too small?
with the libavcodec encode.
If you want to fix it read DOCS/tech/patches.txt and send a patch.
Q: What provides better error recovery while keeping the filesize low?
Should I increase data partitioning or the number of video packets?
Should I use data partitioning or increase the number of video packets?
A: Data partitioning is better in this case.
Glossary:
@ -171,6 +234,9 @@ MB Macroblock (16x16 luminance and 8x8 chrominance samples)
MV Motion vector
ME Motion estimation
MC Motion compensation
RC Rate control
DCT Discrete Cosine Transform
IDCT Inverse Discrete Cosine Transform
JVT Joint Video Team Standard -- http://www.itu.int/ITU-T/news/jvtpro.html
Examples:

View File

@ -39,23 +39,29 @@ extern int pass;
#error your version of libavcodec is too old, get a newer one, and dont send a bugreport, THIS IS NO BUG
#endif
#if LIBAVCODEC_BUILD < 4620
#warning your version of libavcodec is old, u might want to get a newer one
#endif
extern int avcodec_inited;
/* video options */
static char *lavc_param_vcodec = NULL;
static int lavc_param_vbitrate = -1;
static int lavc_param_vrate_tolerance = 1024*8;
static int lavc_param_vrate_tolerance = 1000*8;
static int lavc_param_vhq = 0; /* default is realtime encoding */
static int lavc_param_v4mv = 0;
static int lavc_param_vme = 4;
static int lavc_param_vqscale = 0;
static int lavc_param_vqmin = 3;
static int lavc_param_vqmax = 15;
static int lavc_param_vqmin = 2;
static int lavc_param_vqmax = 31;
static int lavc_param_vqdiff = 3;
static float lavc_param_vqcompress = 0.5;
static float lavc_param_vqblur = 0.5;
static float lavc_param_vb_qfactor = 2.0;
static float lavc_param_vb_qoffset = 0.0;
static float lavc_param_vb_qfactor = 1.25;
static float lavc_param_vb_qoffset = 1.25;
static float lavc_param_vi_qfactor = 0.8;
static float lavc_param_vi_qoffset = 0.0;
static int lavc_param_vmax_b_frames = 0;
static int lavc_param_keyint = -1;
static int lavc_param_vpass = 0;
@ -67,6 +73,16 @@ static int lavc_param_packet_size= 0;
static int lavc_param_strict= 0;
static int lavc_param_data_partitioning= 0;
static int lavc_param_gray=0;
static float lavc_param_rc_qsquish=1.0;
static float lavc_param_rc_qmod_amp=0;
static int lavc_param_rc_qmod_freq=0;
static char *lavc_param_rc_override_string=NULL;
static char *lavc_param_rc_eq="tex^qComp";
static int lavc_param_rc_buffer_size=0;
static float lavc_param_rc_buffer_aggressivity=1.0;
static int lavc_param_rc_max_rate=0;
static int lavc_param_rc_min_rate=0;
static float lavc_param_rc_initial_cplx=0;
static int lavc_param_mpeg_quant=0;
#include "cfgparser.h"
@ -85,10 +101,12 @@ struct config lavcopts_conf[]={
{"vqdiff", &lavc_param_vqdiff, CONF_TYPE_INT, CONF_RANGE, 1, 31, NULL},
{"vqcomp", &lavc_param_vqcompress, CONF_TYPE_FLOAT, CONF_RANGE, 0.0, 1.0, NULL},
{"vqblur", &lavc_param_vqblur, CONF_TYPE_FLOAT, CONF_RANGE, 0.0, 1.0, NULL},
{"vb_qfactor", &lavc_param_vb_qfactor, CONF_TYPE_FLOAT, CONF_RANGE, 0.0, 31.0, NULL},
{"vb_qfactor", &lavc_param_vb_qfactor, CONF_TYPE_FLOAT, CONF_RANGE, -31.0, 31.0, NULL},
{"vmax_b_frames", &lavc_param_vmax_b_frames, CONF_TYPE_INT, CONF_RANGE, 0, FF_MAX_B_FRAMES, NULL},
{"vpass", &lavc_param_vpass, CONF_TYPE_INT, CONF_RANGE, 0, 2, NULL},
#if LIBAVCODEC_BUILD < 4620
{"vrc_strategy", &lavc_param_vrc_strategy, CONF_TYPE_INT, CONF_RANGE, 0, 2, NULL},
#endif
{"vb_strategy", &lavc_param_vb_strategy, CONF_TYPE_INT, CONF_RANGE, 0, 1, NULL},
#ifdef CODEC_FLAG_PART
{"vb_qoffset", &lavc_param_vb_qoffset, CONF_TYPE_FLOAT, CONF_RANGE, 0.0, 31.0, NULL},
@ -104,6 +122,20 @@ struct config lavcopts_conf[]={
#endif
#if LIBAVCODEC_BUILD >= 4619
{"mpeg_quant", &lavc_param_mpeg_quant, CONF_TYPE_FLAG, 0, 0, 1, NULL},
#endif
#if LIBAVCODEC_BUILD >= 4620
{"vi_qfactor", &lavc_param_vi_qfactor, CONF_TYPE_FLOAT, CONF_RANGE, -31.0, 31.0, NULL},
{"vi_qoffset", &lavc_param_vi_qoffset, CONF_TYPE_FLOAT, CONF_RANGE, 0.0, 31.0, NULL},
{"vqsquish", &lavc_param_rc_qsquish, CONF_TYPE_FLOAT, CONF_RANGE, 0.0, 99.0, NULL},
{"vqmod_amp", &lavc_param_rc_qmod_amp, CONF_TYPE_FLOAT, CONF_RANGE, 0.0, 99.0, NULL},
{"vqmod_freq", &lavc_param_rc_qmod_freq, CONF_TYPE_INT, 0, 0, 0, NULL},
{"vrc_eq", &lavc_param_rc_eq, CONF_TYPE_STRING, 0, 0, 0, NULL},
{"vrc_override", &lavc_param_rc_override_string, CONF_TYPE_STRING, 0, 0, 0, NULL},
{"vrc_maxrate", &lavc_param_rc_max_rate, CONF_TYPE_INT, CONF_RANGE, 4, 24000000, NULL},
{"vrc_minrate", &lavc_param_rc_min_rate, CONF_TYPE_INT, CONF_RANGE, 4, 24000000, NULL},
{"vrc_buf_size", &lavc_param_rc_min_rate, CONF_TYPE_INT, CONF_RANGE, 4, 24000000, NULL},
{"vrc_buf_aggressivity", &lavc_param_rc_buffer_aggressivity, CONF_TYPE_FLOAT, CONF_RANGE, 0.0, 99.0, NULL},
{"vrc_init_cplx", &lavc_param_rc_initial_cplx, CONF_TYPE_FLOAT, CONF_RANGE, 0.0, 9999999.0, NULL},
#endif
{NULL, NULL, 0, 0, 0, 0, NULL}
};
@ -113,15 +145,19 @@ struct vf_priv_s {
aviwrite_stream_t* mux;
AVCodecContext context;
AVCodec *codec;
FILE *stats_file;
};
#define stats_file (vf->priv->stats_file)
#define mux_v (vf->priv->mux)
#define lavc_venc_context (vf->priv->context)
static int config(struct vf_instance_s* vf,
int width, int height, int d_width, int d_height,
unsigned int flags, unsigned int outfmt){
int size, i;
void *p;
mux_v->bih->biWidth=width;
mux_v->bih->biHeight=height;
mux_v->bih->biSizeImage=mux_v->bih->biWidth*mux_v->bih->biHeight*(mux_v->bih->biBitCount/8);
@ -160,6 +196,44 @@ static int config(struct vf_instance_s* vf,
if(lavc_param_packet_size )lavc_venc_context.rtp_mode=1;
lavc_venc_context.strict_std_compliance= lavc_param_strict;
#endif
#if LIBAVCODEC_BUILD >= 4620
lavc_venc_context.i_quant_factor= lavc_param_vi_qfactor;
lavc_venc_context.i_quant_offset= lavc_param_vi_qoffset;
lavc_venc_context.rc_qsquish= lavc_param_rc_qsquish;
lavc_venc_context.rc_qmod_amp= lavc_param_rc_qmod_amp;
lavc_venc_context.rc_qmod_freq= lavc_param_rc_qmod_freq;
lavc_venc_context.rc_eq= lavc_param_rc_eq;
lavc_venc_context.rc_max_rate= lavc_param_rc_max_rate*1000;
lavc_venc_context.rc_min_rate= lavc_param_rc_min_rate*1000;
lavc_venc_context.rc_buffer_size= lavc_param_rc_buffer_size*1000;
lavc_venc_context.rc_buffer_aggressivity= lavc_param_rc_buffer_aggressivity;
lavc_venc_context.rc_initial_cplx= lavc_param_rc_initial_cplx;
p= lavc_param_rc_override_string;
for(i=0; p; i++){
int start, end, q;
int e=sscanf(p, "%d,%d,%d", &start, &end, &q);
if(e!=3){
mp_msg(MSGT_MENCODER,MSGL_ERR,"error parsing vrc_q\n");
return 0;
}
lavc_venc_context.rc_override=
realloc(lavc_venc_context.rc_override, sizeof(RcOverride)*(i+1));
lavc_venc_context.rc_override[i].start_frame= start;
lavc_venc_context.rc_override[i].end_frame = end;
if(q>0){
lavc_venc_context.rc_override[i].qscale= q;
lavc_venc_context.rc_override[i].quality_factor= 1.0;
}
else{
lavc_venc_context.rc_override[i].qscale= 0;
lavc_venc_context.rc_override[i].quality_factor= -q/100.0;
}
p= strchr(p, '/');
if(p) p++;
}
lavc_venc_context.rc_override_count=i;
#endif
#if LIBAVCODEC_BUILD >= 4619
lavc_venc_context.mpeg_quant=lavc_param_mpeg_quant;
#endif
@ -199,8 +273,34 @@ static int config(struct vf_instance_s* vf,
#else
switch(lavc_param_vpass?lavc_param_vpass:pass){
#endif
case 1: lavc_venc_context.flags|= CODEC_FLAG_PASS1; break;
case 2: lavc_venc_context.flags|= CODEC_FLAG_PASS2; break;
case 1:
lavc_venc_context.flags|= CODEC_FLAG_PASS1;
stats_file= fopen(passtmpfile, "w");
if(stats_file==NULL){
mp_msg(MSGT_MENCODER,MSGL_ERR,"2pass failed: filename=%s\n", passtmpfile);
return 0;
}
break;
case 2:
lavc_venc_context.flags|= CODEC_FLAG_PASS2;
stats_file= fopen(passtmpfile, "r");
if(stats_file==NULL){
mp_msg(MSGT_MENCODER,MSGL_ERR,"2pass failed: filename=%s\n", passtmpfile);
return 0;
}
fseek(stats_file, 0, SEEK_END);
size= ftell(stats_file);
fseek(stats_file, 0, SEEK_SET);
lavc_venc_context.stats_in= malloc(size + 1);
lavc_venc_context.stats_in[size]=0;
if(fread(lavc_venc_context.stats_in, size, 1, stats_file)<1){
mp_msg(MSGT_MENCODER,MSGL_ERR,"2pass failed: reading from filename=%s\n", passtmpfile);
return 0;
}
break;
}
#ifdef ME_ZERO
@ -249,7 +349,13 @@ static int config(struct vf_instance_s* vf,
mp_msg(MSGT_MENCODER,MSGL_ERR,"avcodec init failed (ctx->codec->encode == NULL)!\n");
return 0;
}
#if LIBAVCODEC_BUILD >= 4620
/* free second pass buffer, its not needed anymore */
if(lavc_venc_context.stats_in) free(lavc_venc_context.stats_in);
lavc_venc_context.stats_in= NULL;
#endif
return 1;
}
@ -306,10 +412,24 @@ static void put_image(struct vf_instance_s* vf, mp_image_t *mpi){
}
mencoder_write_chunk(mux_v,out_size,lavc_venc_context.key_frame?0x10:0);
#if LIBAVCODEC_BUILD >= 4620
/* store stats if there are any */
if(lavc_venc_context.stats_out && stats_file)
fprintf(stats_file, "%s", lavc_venc_context.stats_out);
#endif
}
static void uninit(struct vf_instance_s* vf){
avcodec_close(&lavc_venc_context);
if(stats_file) fclose(stats_file);
#if LIBAVCODEC_BUILD >= 4620
/* free rc_override */
if(lavc_venc_context.rc_override) free(lavc_venc_context.rc_override);
lavc_venc_context.rc_override= NULL;
#endif
}
//===========================================================================//