[FFmpeg-devel] [PATCH v3] ffmpeg: add -fpsmax to clamp output framerate
Gyan Doshi
ffmpeg at gyani.pro
Fri Feb 5 19:27:46 EET 2021
Pushed as d99cc1782563672bcdb46fb5ec51135847db8c99
On 05-02-2021 09:39 am, Gyan Doshi wrote:
> Will push in 12h if no further changes.
>
> On 03-02-2021 07:42 pm, Gyan Doshi wrote:
>> Useful when encoding in batch or with aberrant inputs.
>> ---
>> doc/ffmpeg.texi | 7 +++++++
>> fftools/ffmpeg.c | 7 ++++++-
>> fftools/ffmpeg.h | 3 +++
>> fftools/ffmpeg_opt.c | 23 ++++++++++++++++++++---
>> 4 files changed, 36 insertions(+), 4 deletions(-)
>>
>> diff --git a/doc/ffmpeg.texi b/doc/ffmpeg.texi
>> index 8eb012b7c0..b0d1cf0710 100644
>> --- a/doc/ffmpeg.texi
>> +++ b/doc/ffmpeg.texi
>> @@ -759,6 +759,13 @@ If in doubt use @option{-framerate} instead of
>> the input option @option{-r}.
>> As an output option, duplicate or drop input frames to achieve
>> constant output
>> frame rate @var{fps}.
>> + at item -fpsmax[:@var{stream_specifier}] @var{fps}
>> (@emph{output,per-stream})
>> +Set maximum frame rate (Hz value, fraction or abbreviation).
>> +
>> +Clamps output frame rate when output framerate is auto-set and is
>> higher than this value.
>> +Useful in batch processing or when input framerate is wrongly
>> detected as very high.
>> +It cannot be set together with @code{-r}. It is ignored during
>> streamcopy.
>> +
>> @item -s[:@var{stream_specifier}] @var{size}
>> (@emph{input/output,per-stream})
>> Set frame size.
>> 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 bf2eb26246..805754953e 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) {
>> @@ -3596,6 +3610,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" },
>
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel at ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
> To unsubscribe, visit link above, or email
> ffmpeg-devel-request at ffmpeg.org with subject "unsubscribe".
More information about the ffmpeg-devel
mailing list