ffmpeg: add option fps_mode

fps_mode sets video sync per output stream. Overrides vsync for matching
streams.

vsync is deprecated.
release/5.1
Gyan Doshi 3 years ago
parent cb204f007b
commit 09c53a04c5
  1. 14
      doc/ffmpeg.texi
  2. 9
      fftools/ffmpeg.c
  3. 3
      fftools/ffmpeg.h
  4. 2
      fftools/ffmpeg_mux.c
  5. 42
      fftools/ffmpeg_opt.c

@ -1618,12 +1618,14 @@ it may cause packet loss.
It is useful for when flow speed of output packets is important, such as live streaming. It is useful for when flow speed of output packets is important, such as live streaming.
@item -re (@emph{input}) @item -re (@emph{input})
Read input at native frame rate. This is equivalent to setting @code{-readrate 1}. Read input at native frame rate. This is equivalent to setting @code{-readrate 1}.
@item -vsync @var{parameter} @item -vsync @var{parameter} (@emph{global})
Video sync method. @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
For compatibility reasons some of the values can be specified as numbers (shown but can be overridden for a stream by setting fps_mode. vsync is deprecated and will be
in parentheses in the following table). This is deprecated and will stop working removed in the future.
in the future.
For compatibility reasons some of the values for vsync can be specified as numbers (shown
in parentheses in the following table).
@table @option @table @option
@item passthrough (0) @item passthrough (0)

@ -3017,11 +3017,12 @@ static int init_output_stream_encode(OutputStream *ost, AVFrame *frame)
if (!(enc_ctx->time_base.num && enc_ctx->time_base.den)) if (!(enc_ctx->time_base.num && enc_ctx->time_base.den))
enc_ctx->time_base = av_buffersink_get_time_base(ost->filter->filter); 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 if ( av_q2d(enc_ctx->time_base) < 0.001 && ost->vsync_method != VSYNC_PASSTHROUGH
&& (video_sync_method == VSYNC_CFR || video_sync_method == VSYNC_VSCFR || && (ost->vsync_method == VSYNC_CFR || ost->vsync_method == VSYNC_VSCFR ||
(video_sync_method == VSYNC_AUTO && !(of->format->flags & AVFMT_VARIABLE_FPS)))){ (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" 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/fps_mode to vfr\n");
} }
enc_ctx->width = av_buffersink_get_w(ost->filter->filter); enc_ctx->width = av_buffersink_get_w(ost->filter->filter);

@ -176,6 +176,8 @@ typedef struct OptionsContext {
int nb_qscale; int nb_qscale;
SpecifierOpt *forced_key_frames; SpecifierOpt *forced_key_frames;
int nb_forced_key_frames; int nb_forced_key_frames;
SpecifierOpt *fps_mode;
int nb_fps_mode;
SpecifierOpt *force_fps; SpecifierOpt *force_fps;
int nb_force_fps; int nb_force_fps;
SpecifierOpt *frame_aspect_ratios; SpecifierOpt *frame_aspect_ratios;
@ -489,6 +491,7 @@ typedef struct OutputStream {
AVRational max_frame_rate; AVRational max_frame_rate;
enum VideoSyncMethod vsync_method; enum VideoSyncMethod vsync_method;
int is_cfr; int is_cfr;
const char *fps_mode;
int force_fps; int force_fps;
int top_field_first; int top_field_first;
int rotate_overridden; int rotate_overridden;

@ -96,7 +96,7 @@ void of_write_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost,
return; 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)) (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && audio_sync_method < 0))
pkt->pts = pkt->dts = AV_NOPTS_VALUE; pkt->pts = pkt->dts = AV_NOPTS_VALUE;

@ -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_sample_fmts[] = {"sample_fmt", NULL};
static const char *const opt_name_qscale[] = {"q", "qscale", 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_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_force_fps[] = {"force_fps", NULL};
static const char *const opt_name_frame_aspect_ratios[] = {"aspect", NULL}; static const char *const opt_name_frame_aspect_ratios[] = {"aspect", NULL};
static const char *const opt_name_rc_overrides[] = {"rc_override", NULL}; static const char *const opt_name_rc_overrides[] = {"rc_override", NULL};
@ -265,6 +266,26 @@ static AVDictionary *strip_specifiers(AVDictionary *dict)
return ret; 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) static int opt_filter_threads(void *optctx, const char *opt, const char *arg)
{ {
av_free(filter_nbthreads); 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); MATCH_PER_STREAM_OPT(top_field_first, i, ost->top_field_first, oc, st);
ost->vsync_method = video_sync_method; 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 (ost->vsync_method == VSYNC_AUTO) {
if (!strcmp(oc->oformat->name, "avi")) { if (!strcmp(oc->oformat->name, "avi")) {
ost->vsync_method = VSYNC_VFR; ost->vsync_method = VSYNC_VFR;
@ -3248,16 +3273,8 @@ 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) static int opt_vsync(void *optctx, const char *opt, const char *arg)
{ {
if (!av_strcasecmp(arg, "cfr")) video_sync_method = VSYNC_CFR; av_log(NULL, AV_LOG_WARNING, "-vsync is deprecated. Use -fps_mode\n");
else if (!av_strcasecmp(arg, "vfr")) video_sync_method = VSYNC_VFR; parse_and_set_vsync(arg, &video_sync_method, -1, -1, 1);
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");
}
return 0; return 0;
} }
@ -3620,7 +3637,7 @@ const OptionDef options[] = {
"specify target file type (\"vcd\", \"svcd\", \"dvd\", \"dv\" or \"dv50\" " "specify target file type (\"vcd\", \"svcd\", \"dvd\", \"dv\" or \"dv50\" "
"with optional prefixes \"pal-\", \"ntsc-\" or \"film-\")", "type" }, "with optional prefixes \"pal-\", \"ntsc-\" or \"film-\")", "type" },
{ "vsync", HAS_ARG | OPT_EXPERT, { .func_arg = opt_vsync }, { "vsync", HAS_ARG | OPT_EXPERT, { .func_arg = opt_vsync },
"video sync method", "" }, "set video sync method globally; deprecated, use -fps_mode", "" },
{ "frame_drop_threshold", HAS_ARG | OPT_FLOAT | OPT_EXPERT, { &frame_drop_threshold }, { "frame_drop_threshold", HAS_ARG | OPT_FLOAT | OPT_EXPERT, { &frame_drop_threshold },
"frame drop threshold", "" }, "frame drop threshold", "" },
{ "async", HAS_ARG | OPT_INT | OPT_EXPERT, { &audio_sync_method }, { "async", HAS_ARG | OPT_INT | OPT_EXPERT, { &audio_sync_method },
@ -3777,6 +3794,9 @@ const OptionDef options[] = {
"force video tag/fourcc", "fourcc/tag" }, "force video tag/fourcc", "fourcc/tag" },
{ "qphist", OPT_VIDEO | OPT_BOOL | OPT_EXPERT , { &qp_hist }, { "qphist", OPT_VIDEO | OPT_BOOL | OPT_EXPERT , { &qp_hist },
"show QP histogram" }, "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 | { "force_fps", OPT_VIDEO | OPT_BOOL | OPT_EXPERT | OPT_SPEC |
OPT_OUTPUT, { .off = OFFSET(force_fps) }, OPT_OUTPUT, { .off = OFFSET(force_fps) },
"force the selected framerate, disable the best supported framerate selection" }, "force the selected framerate, disable the best supported framerate selection" },

Loading…
Cancel
Save