[FFmpeg-devel] [PATCH] ffmpeg: add option fps_mode

Gyan Doshi ffmpeg at gyani.pro
Thu Jun 9 22:09:53 EEST 2022



On 2022-06-10 12:14 am, Paul B Mahol wrote:
> On Thu, Jun 9, 2022 at 8:06 PM Gyan Doshi <ffmpeg at gyani.pro> wrote:
>
>> Plan to push in a day.
>>
> Is this a hack?

No.


>
>> On 2022-06-07 05:44 pm, Gyan Doshi wrote:
>>> fps_mode sets video sync per output stream. Overrides vsync for matching
>>> streams.
>>> ---
>>>    doc/ffmpeg.texi      |  8 +++++---
>>>    fftools/ffmpeg.c     |  9 +++++----
>>>    fftools/ffmpeg.h     |  3 +++
>>>    fftools/ffmpeg_mux.c |  2 +-
>>>    fftools/ffmpeg_opt.c | 41 ++++++++++++++++++++++++++++++-----------
>>>    5 files changed, 44 insertions(+), 19 deletions(-)
>>>
>>> diff --git a/doc/ffmpeg.texi b/doc/ffmpeg.texi
>>> index 0d7e1a479d..395ddc34ba 100644
>>> --- a/doc/ffmpeg.texi
>>> +++ b/doc/ffmpeg.texi
>>> @@ -1618,10 +1618,12 @@ it may cause packet loss.
>>>    It is useful for when flow speed of output packets is important, such
>> as live streaming.
>>>    @item -re (@emph{input})
>>>    Read input at native frame rate. This is equivalent to setting
>> @code{-readrate 1}.
>>> - at item -vsync @var{parameter}
>>> -Video sync method.
>>> + at item -vsync @var{parameter} (@emph{global})
>>> + at itemx -fps_mode[:@var{stream_specifier}] @var{parameter}
>> (@emph{output,per-stream})
>>> +Set video sync method / framerate mode. vsync is applied to all output
>> video streams
>>> +but can be overridden for a stream by setting fps_mode.
>>>
>>> -For compatibility reasons some of the values can be specified as
>> numbers (shown
>>> +For compatibility reasons some of the values for vsync can be specified
>> as numbers (shown
>>>    in parentheses in the following table). This is deprecated and will
>> stop working
>>>    in the future.
>>>
>>> diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c
>>> index 5ed287c522..2922a1e707 100644
>>> --- a/fftools/ffmpeg.c
>>> +++ b/fftools/ffmpeg.c
>>> @@ -3018,11 +3018,12 @@ static int
>> init_output_stream_encode(OutputStream *ost, AVFrame *frame)
>>>            if (!(enc_ctx->time_base.num && enc_ctx->time_base.den))
>>>                enc_ctx->time_base =
>> av_buffersink_get_time_base(ost->filter->filter);
>>> -        if (   av_q2d(enc_ctx->time_base) < 0.001 && video_sync_method
>> != VSYNC_PASSTHROUGH
>>> -           && (video_sync_method == VSYNC_CFR || video_sync_method ==
>> VSYNC_VSCFR ||
>>> -               (video_sync_method == VSYNC_AUTO && !(of->format->flags
>> & AVFMT_VARIABLE_FPS)))){
>>> +        if (   av_q2d(enc_ctx->time_base) < 0.001 && ost->vsync_method
>> != VSYNC_PASSTHROUGH
>>> +           && (ost->vsync_method == VSYNC_CFR || ost->vsync_method ==
>> VSYNC_VSCFR ||
>>> +               (ost->vsync_method == VSYNC_AUTO && !(of->format->flags
>> & AVFMT_VARIABLE_FPS)))){
>>>                av_log(oc, AV_LOG_WARNING, "Frame rate very high for a
>> muxer not efficiently supporting it.\n"
>>> -                                       "Please consider specifying a
>> lower framerate, a different muxer or -vsync 2\n");
>>> +                                       "Please consider specifying a
>> lower framerate, a different muxer or"
>>> +                                       "setting vsync or fps_mode to
>> vfr\n");
>>>            }
>>>
>>>            enc_ctx->width  = av_buffersink_get_w(ost->filter->filter);
>>> diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h
>>> index 7326193caf..69a368b8d1 100644
>>> --- a/fftools/ffmpeg.h
>>> +++ b/fftools/ffmpeg.h
>>> @@ -176,6 +176,8 @@ typedef struct OptionsContext {
>>>        int        nb_qscale;
>>>        SpecifierOpt *forced_key_frames;
>>>        int        nb_forced_key_frames;
>>> +    SpecifierOpt *fps_mode;
>>> +    int        nb_fps_mode;
>>>        SpecifierOpt *force_fps;
>>>        int        nb_force_fps;
>>>        SpecifierOpt *frame_aspect_ratios;
>>> @@ -489,6 +491,7 @@ typedef struct OutputStream {
>>>        AVRational max_frame_rate;
>>>        enum VideoSyncMethod vsync_method;
>>>        int is_cfr;
>>> +    const char *fps_mode;
>>>        int force_fps;
>>>        int top_field_first;
>>>        int rotate_overridden;
>>> diff --git a/fftools/ffmpeg_mux.c b/fftools/ffmpeg_mux.c
>>> index 794d580635..a55fd18f8f 100644
>>> --- a/fftools/ffmpeg_mux.c
>>> +++ b/fftools/ffmpeg_mux.c
>>> @@ -96,7 +96,7 @@ void of_write_packet(OutputFile *of, AVPacket *pkt,
>> OutputStream *ost,
>>>            return;
>>>        }
>>>
>>> -    if ((st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO &&
>> video_sync_method == VSYNC_DROP) ||
>>> +    if ((st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO &&
>> ost->vsync_method == VSYNC_DROP) ||
>>>            (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
>> audio_sync_method < 0))
>>>            pkt->pts = pkt->dts = AV_NOPTS_VALUE;
>>>
>>> diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c
>>> index 2c1b3bd0dd..0993985765 100644
>>> --- a/fftools/ffmpeg_opt.c
>>> +++ b/fftools/ffmpeg_opt.c
>>> @@ -81,6 +81,7 @@ static const char *const opt_name_codec_tags[]
>>          = {"tag", "atag",
>>>    static const char *const opt_name_sample_fmts[]               =
>> {"sample_fmt", NULL};
>>>    static const char *const opt_name_qscale[]                    = {"q",
>> "qscale", NULL};
>>>    static const char *const opt_name_forced_key_frames[]         =
>> {"forced_key_frames", NULL};
>>> +static const char *const opt_name_fps_mode[]                  =
>> {"fps_mode", NULL};
>>>    static const char *const opt_name_force_fps[]                 =
>> {"force_fps", NULL};
>>>    static const char *const opt_name_frame_aspect_ratios[]       =
>> {"aspect", NULL};
>>>    static const char *const opt_name_rc_overrides[]              =
>> {"rc_override", NULL};
>>> @@ -265,6 +266,26 @@ static AVDictionary *strip_specifiers(AVDictionary
>> *dict)
>>>        return ret;
>>>    }
>>>
>>> +static int parse_and_set_vsync(const char *arg, int *vsync_var, int
>> file_idx, int st_idx, int is_global)
>>> +{
>>> +    if      (!av_strcasecmp(arg, "cfr"))         *vsync_var = VSYNC_CFR;
>>> +    else if (!av_strcasecmp(arg, "vfr"))         *vsync_var = VSYNC_VFR;
>>> +    else if (!av_strcasecmp(arg, "passthrough")) *vsync_var =
>> VSYNC_PASSTHROUGH;
>>> +    else if (!av_strcasecmp(arg, "drop"))        *vsync_var =
>> VSYNC_DROP;
>>> +    else if (!is_global && !av_strcasecmp(arg, "auto"))  *vsync_var =
>> VSYNC_AUTO;
>>> +    else if (!is_global) {
>>> +        av_log(NULL, AV_LOG_FATAL, "Invalid value %s specified for
>> fps_mode of #%d:%d.\n", arg, file_idx, st_idx);
>>> +        exit_program(1);
>>> +    }
>>> +
>>> +    if (is_global && *vsync_var == VSYNC_AUTO) {
>>> +        video_sync_method = parse_number_or_die("vsync", arg, OPT_INT,
>> VSYNC_AUTO, VSYNC_VFR);
>>> +        av_log(NULL, AV_LOG_WARNING, "Passing a number to -vsync is
>> deprecated,"
>>> +               " use a string argument as described in the manual.\n");
>>> +    }
>>> +    return 0;
>>> +}
>>> +
>>>    static int opt_filter_threads(void *optctx, const char *opt, const
>> char *arg)
>>>    {
>>>        av_free(filter_nbthreads);
>>> @@ -1905,6 +1926,10 @@ static OutputStream
>> *new_video_stream(OptionsContext *o, AVFormatContext *oc, in
>>>            MATCH_PER_STREAM_OPT(top_field_first, i, ost->top_field_first,
>> oc, st);
>>>            ost->vsync_method = video_sync_method;
>>> +        MATCH_PER_STREAM_OPT(fps_mode, str, ost->fps_mode, oc, st);
>>> +        if (ost->fps_mode)
>>> +            parse_and_set_vsync(ost->fps_mode, &ost->vsync_method,
>> ost->file_index, ost->index, 0);
>>> +
>>>            if (ost->vsync_method == VSYNC_AUTO) {
>>>                if (!strcmp(oc->oformat->name, "avi")) {
>>>                    ost->vsync_method = VSYNC_VFR;
>>> @@ -3248,16 +3273,7 @@ static int opt_audio_filters(void *optctx, const
>> char *opt, const char *arg)
>>>    static int opt_vsync(void *optctx, const char *opt, const char *arg)
>>>    {
>>> -    if      (!av_strcasecmp(arg, "cfr"))         video_sync_method =
>> VSYNC_CFR;
>>> -    else if (!av_strcasecmp(arg, "vfr"))         video_sync_method =
>> VSYNC_VFR;
>>> -    else if (!av_strcasecmp(arg, "passthrough")) video_sync_method =
>> VSYNC_PASSTHROUGH;
>>> -    else if (!av_strcasecmp(arg, "drop"))        video_sync_method =
>> VSYNC_DROP;
>>> -
>>> -    if (video_sync_method == VSYNC_AUTO) {
>>> -        video_sync_method = parse_number_or_die("vsync", arg, OPT_INT,
>> VSYNC_AUTO, VSYNC_VFR);
>>> -        av_log(NULL, AV_LOG_WARNING, "Passing a number to -vsync is
>> deprecated,"
>>> -               " use a string argument as described in the manual.\n");
>>> -    }
>>> +    parse_and_set_vsync(arg, &video_sync_method, -1, -1, 1);
>>>        return 0;
>>>    }
>>>
>>> @@ -3620,7 +3636,7 @@ const OptionDef options[] = {
>>>            "specify target file type (\"vcd\", \"svcd\", \"dvd\", \"dv\"
>> or \"dv50\" "
>>>            "with optional prefixes \"pal-\", \"ntsc-\" or \"film-\")",
>> "type" },
>>>        { "vsync",          HAS_ARG | OPT_EXPERT,                        {
>> .func_arg = opt_vsync },
>>> -        "video sync method", "" },
>>> +        "set video sync method / fps_mode globally", "" },
>>>        { "frame_drop_threshold", HAS_ARG | OPT_FLOAT | OPT_EXPERT,      {
>> &frame_drop_threshold },
>>>            "frame drop threshold", "" },
>>>        { "async",          HAS_ARG | OPT_INT | OPT_EXPERT,              {
>> &audio_sync_method },
>>> @@ -3777,6 +3793,9 @@ const OptionDef options[] = {
>>>            "force video tag/fourcc", "fourcc/tag" },
>>>        { "qphist",       OPT_VIDEO | OPT_BOOL | OPT_EXPERT ,
>>            { &qp_hist },
>>>            "show QP histogram" },
>>> +    { "fps_mode",     OPT_VIDEO | HAS_ARG | OPT_STRING | OPT_EXPERT |
>>> +                      OPT_SPEC | OPT_OUTPUT,
>>           { .off = OFFSET(fps_mode) },
>>> +        "set framerate mode for matching video streams; overrides
>> vsync." },
>>>        { "force_fps",    OPT_VIDEO | OPT_BOOL | OPT_EXPERT  | OPT_SPEC |
>>>                          OPT_OUTPUT,
>>            { .off = OFFSET(force_fps) },
>>>            "force the selected framerate, disable the best supported
>> framerate selection" },
>>
>> _______________________________________________
>> 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".
>>
> _______________________________________________
> 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