Option -omaxfps: limit fps when encoding

Lower-fps content is left alone (NOT aligned to this fps); higher fps
content is decimated to this frame rate.
This commit is contained in:
Rudolf Polzer 2013-06-09 15:37:28 +02:00
parent 4af59abbb4
commit 0cbc75c083
5 changed files with 29 additions and 0 deletions

View File

@ -45,6 +45,11 @@ You can encode files from one format/codec to another using this facility.
specified - use --ofps or --oautofps to force CFR encoding in these
cases.
--omaxfps=<float value>
Specifies the minimum distance of adjacent frames (default: 0, which means
unset). Content of lower frame rate is not readjusted to this frame rate;
content of higher frame rate is decimated to this frame rate.
--oharddup
If set, the frame rate given by --ofps is attained not by skipping time
codes, but by duplicating frames (constant frame rate mode).

View File

@ -709,6 +709,7 @@ const m_option_t mp_opts[] = {
OPT_STRING("of", encode_output.format, CONF_GLOBAL),
OPT_STRINGLIST("ofopts*", encode_output.fopts, CONF_GLOBAL),
OPT_FLOATRANGE("ofps", encode_output.fps, CONF_GLOBAL, 0.0, 1000000.0),
OPT_FLOATRANGE("omaxfps", encode_output.maxfps, CONF_GLOBAL, 0.0, 1000000.0),
OPT_STRING("ovc", encode_output.vcodec, CONF_GLOBAL),
OPT_STRINGLIST("ovcopts*", encode_output.vopts, CONF_GLOBAL),
OPT_STRING("oac", encode_output.acodec, CONF_GLOBAL),

View File

@ -252,6 +252,7 @@ typedef struct MPOpts {
char *format;
char **fopts;
float fps;
float maxfps;
char *vcodec;
char **vopts;
char *acodec;

View File

@ -153,6 +153,7 @@ profile = enc-f-mp4
vf-add = dsize=480:360:0:2,scale=w=0:h=0,dsize=-1:-1 # native screen res, letterbox
ovcopts-add = maxrate=1500k,bufsize=1000k,rc_init_occupancy=900k,refs=1,profile=baseline
vf-add=noformat=444p,noformat=444p9,noformat=444p10,noformat=422p,noformat=422p9,noformat=422p10
omaxfps = 30
[enc-to-nok-n900]
profile-desc = "MP4 for Nokia N900"
@ -160,6 +161,7 @@ profile = enc-f-mp4
vf-add = dsize=800:480:0:2,scale=w=0:h=0:noup=1,scale=w=-1:h=-2:noup=1,scale=w=-2:h=-1:noup=1,dsize=-1:-1 # native screen res, letterbox
ovcopts-add = profile=baseline,level=30,maxrate=10000k,bufsize=10000k,rc_init_occupancy=9000k,refs=5
vf-add=noformat=444p,noformat=444p9,noformat=444p10,noformat=422p,noformat=422p9,noformat=422p10
omaxfps = 30
[enc-to-nok-6300]
profile-desc = "3GP for Nokia 6300"
@ -186,18 +188,22 @@ profile = enc-f-mp4
oautofps = yes # iphone supports 30fps max
ovcopts-add = maxrate=2500k,bufsize=1000k,rc_init_occupancy=900k,level=30,profile=baseline
vf-add=noformat=444p,noformat=444p9,noformat=444p10,noformat=422p,noformat=422p9,noformat=422p10
omaxfps = 30
[enc-to-iphone]
profile-desc = "MP4 for iPhone (480x320)"
profile = enc-to-iphone-noscale
vf-add = dsize=480:320:1:2,scale=w=0:h=0,dsize=-1:-1 # panscan
omaxfps = 30
[enc-to-iphone-4]
profile-desc = "MP4 for iPhone 4 (960x640)"
profile = enc-to-iphone-noscale
vf-add = dsize=960:480:1:2,scale=w=0:h=0,dsize=-1:-1 # panscan
omaxfps = 30
[enc-to-iphone-5]
profile-desc = "MP4 for iPhone 5 (1136x640)"
profile = enc-to-iphone-noscale
vf-add = dsize=1136:480:1:2,scale=w=0:h=0,dsize=-1:-1 # panscan
omaxfps = 30

View File

@ -48,6 +48,7 @@ struct priv {
double lastpts;
int64_t lastipts;
int64_t lastframeipts;
int64_t mindeltapts;
double expected_next_pts;
mp_image_t *lastimg;
int lastimg_wants_osd;
@ -317,6 +318,11 @@ static void draw_image(struct vo *vo, mp_image_t *mpi)
vc->worst_time_base = vc->stream->time_base;
vc->worst_time_base_is_stream = 1;
}
if (ectx->options->maxfps)
vc->mindeltapts = ceil(vc->worst_time_base.den /
(vc->worst_time_base.num * ectx->options->maxfps));
else
vc->mindeltapts = 0;
// NOTE: we use the following "axiom" of av_rescale_q:
// if time base A is worse than time base B, then
@ -394,6 +400,16 @@ static void draw_image(struct vo *vo, mp_image_t *mpi)
vc->lastpts = frameipts * timeunit - encode_lavc_getoffset(ectx, vc->stream);
}
// lastipts: pts of last vo frame
// frameipts: pts of current vo frame
// lastframeipts: pts of last ENCODED frame
// now we want to go forward in time until at least lastframeipts + mindeltapts
// so let's just assume this frame took place at this time or later
if (frameipts >= vc->lastframeipts && frameipts < vc->lastframeipts + vc->mindeltapts) {
frameipts = vc->lastframeipts + vc->mindeltapts;
vc->lastpts = frameipts * timeunit - encode_lavc_getoffset(ectx, vc->stream);
}
if (vc->lastipts != MP_NOPTS_VALUE) {
frame = avcodec_alloc_frame();