summaryrefslogtreecommitdiff
path: root/fftools
diff options
context:
space:
mode:
authorGyan Doshi <ffmpeg@gyani.pro>2021-02-01 18:19:18 +0530
committerGyan Doshi <ffmpeg@gyani.pro>2021-02-05 22:54:18 +0530
commitd99cc1782563672bcdb46fb5ec51135847db8c99 (patch)
treeef4abee116e19db63157615b85f1b7b508a0a3ea /fftools
parent6b8ef5119cab9e772c6afd23e474bbd543c47039 (diff)
ffmpeg: add -fpsmax to clamp output framerate
Useful when encoding in batch or with aberrant inputs.
Diffstat (limited to 'fftools')
-rw-r--r--fftools/ffmpeg.c7
-rw-r--r--fftools/ffmpeg.h3
-rw-r--r--fftools/ffmpeg_opt.c23
3 files changed, 29 insertions, 4 deletions
diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c
index d7c833be63..add5a3e505 100644
--- a/fftools/ffmpeg.c
+++ b/fftools/ffmpeg.c
@@ -3376,7 +3376,7 @@ static int init_output_stream_encode(OutputStream *ost, AVFrame *frame)
ost->frame_rate = ist->framerate;
if (ist && !ost->frame_rate.num)
ost->frame_rate = ist->st->r_frame_rate;
- if (ist && !ost->frame_rate.num) {
+ if (ist && !ost->frame_rate.num && !ost->max_frame_rate.num) {
ost->frame_rate = (AVRational){25, 1};
av_log(NULL, AV_LOG_WARNING,
"No information "
@@ -3386,6 +3386,11 @@ static int init_output_stream_encode(OutputStream *ost, AVFrame *frame)
ost->file_index, ost->index);
}
+ if (ost->max_frame_rate.num &&
+ (av_q2d(ost->frame_rate) > av_q2d(ost->max_frame_rate) ||
+ !ost->frame_rate.den))
+ ost->frame_rate = ost->max_frame_rate;
+
if (ost->enc->supported_framerates && !ost->force_fps) {
int idx = av_find_nearest_q_idx(ost->frame_rate, ost->enc->supported_framerates);
ost->frame_rate = ost->enc->supported_framerates[idx];
diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h
index 5aeceae6b7..423da071dc 100644
--- a/fftools/ffmpeg.h
+++ b/fftools/ffmpeg.h
@@ -108,6 +108,8 @@ typedef struct OptionsContext {
int nb_audio_sample_rate;
SpecifierOpt *frame_rates;
int nb_frame_rates;
+ SpecifierOpt *max_frame_rates;
+ int nb_max_frame_rates;
SpecifierOpt *frame_sizes;
int nb_frame_sizes;
SpecifierOpt *frame_pix_fmts;
@@ -479,6 +481,7 @@ typedef struct OutputStream {
/* video only */
AVRational frame_rate;
+ AVRational max_frame_rate;
int is_cfr;
int force_fps;
int top_field_first;
diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c
index 07308ccc8b..1cb601f7c7 100644
--- a/fftools/ffmpeg_opt.c
+++ b/fftools/ffmpeg_opt.c
@@ -55,6 +55,7 @@ static const char *const opt_name_codec_names[] = {"c", "codec", "
static const char *const opt_name_audio_channels[] = {"ac", NULL};
static const char *const opt_name_audio_sample_rate[] = {"ar", NULL};
static const char *const opt_name_frame_rates[] = {"r", NULL};
+static const char *const opt_name_max_frame_rates[] = {"fpsmax", NULL};
static const char *const opt_name_frame_sizes[] = {"s", NULL};
static const char *const opt_name_frame_pix_fmts[] = {"pix_fmt", NULL};
static const char *const opt_name_ts_scale[] = {"itsscale", NULL};
@@ -1688,7 +1689,7 @@ static OutputStream *new_video_stream(OptionsContext *o, AVFormatContext *oc, in
AVStream *st;
OutputStream *ost;
AVCodecContext *video_enc;
- char *frame_rate = NULL, *frame_aspect_ratio = NULL;
+ char *frame_rate = NULL, *max_frame_rate = NULL, *frame_aspect_ratio = NULL;
ost = new_output_stream(o, oc, AVMEDIA_TYPE_VIDEO, source_index);
st = ost->st;
@@ -1699,8 +1700,21 @@ static OutputStream *new_video_stream(OptionsContext *o, AVFormatContext *oc, in
av_log(NULL, AV_LOG_FATAL, "Invalid framerate value: %s\n", frame_rate);
exit_program(1);
}
- if (frame_rate && video_sync_method == VSYNC_PASSTHROUGH)
- av_log(NULL, AV_LOG_ERROR, "Using -vsync 0 and -r can produce invalid output files\n");
+
+ MATCH_PER_STREAM_OPT(max_frame_rates, str, max_frame_rate, oc, st);
+ if (max_frame_rate && av_parse_video_rate(&ost->max_frame_rate, max_frame_rate) < 0) {
+ av_log(NULL, AV_LOG_FATAL, "Invalid maximum framerate value: %s\n", max_frame_rate);
+ exit_program(1);
+ }
+
+ if (frame_rate && max_frame_rate) {
+ av_log(NULL, AV_LOG_ERROR, "Only one of -fpsmax and -r can be set for a stream.\n");
+ exit_program(1);
+ }
+
+ if ((frame_rate || max_frame_rate) &&
+ video_sync_method == VSYNC_PASSTHROUGH)
+ av_log(NULL, AV_LOG_ERROR, "Using -vsync 0 and -r/-fpsmax can produce invalid output files\n");
MATCH_PER_STREAM_OPT(frame_aspect_ratios, str, frame_aspect_ratio, oc, st);
if (frame_aspect_ratio) {
@@ -3599,6 +3613,9 @@ const OptionDef options[] = {
{ "r", OPT_VIDEO | HAS_ARG | OPT_STRING | OPT_SPEC |
OPT_INPUT | OPT_OUTPUT, { .off = OFFSET(frame_rates) },
"set frame rate (Hz value, fraction or abbreviation)", "rate" },
+ { "fpsmax", OPT_VIDEO | HAS_ARG | OPT_STRING | OPT_SPEC |
+ OPT_OUTPUT, { .off = OFFSET(max_frame_rates) },
+ "set max frame rate (Hz value, fraction or abbreviation)", "rate" },
{ "s", OPT_VIDEO | HAS_ARG | OPT_SUBTITLE | OPT_STRING | OPT_SPEC |
OPT_INPUT | OPT_OUTPUT, { .off = OFFSET(frame_sizes) },
"set frame size (WxH or abbreviation)", "size" },