+
/*
* ffmpeg option parsing
*
#define DEFAULT_PASS_LOGFILENAME_PREFIX "ffmpeg2pass"
+#define SPECIFIER_OPT_FMT_str "%s"
+#define SPECIFIER_OPT_FMT_i "%i"
+#define SPECIFIER_OPT_FMT_i64 "%"PRId64
+#define SPECIFIER_OPT_FMT_ui64 "%"PRIu64
+#define SPECIFIER_OPT_FMT_f "%f"
+#define SPECIFIER_OPT_FMT_dbl "%lf"
+
+static const char *opt_name_codec_names[] = {"c", "codec", "acodec", "vcodec", "scodec", "dcodec", NULL};
+static const char *opt_name_audio_channels[] = {"ac", NULL};
+static const char *opt_name_audio_sample_rate[] = {"ar", NULL};
+static const char *opt_name_frame_rates[] = {"r", NULL};
+static const char *opt_name_frame_sizes[] = {"s", NULL};
+static const char *opt_name_frame_pix_fmts[] = {"pix_fmt", NULL};
+static const char *opt_name_ts_scale[] = {"itsscale", NULL};
+static const char *opt_name_hwaccels[] = {"hwaccel", NULL};
+static const char *opt_name_hwaccel_devices[] = {"hwaccel_device", NULL};
+static const char *opt_name_hwaccel_output_formats[] = {"hwaccel_output_format", NULL};
+static const char *opt_name_autorotate[] = {"autorotate", NULL};
+static const char *opt_name_max_frames[] = {"frames", "aframes", "vframes", "dframes", NULL};
+static const char *opt_name_bitstream_filters[] = {"bsf", "absf", "vbsf", NULL};
+static const char *opt_name_codec_tags[] = {"tag", "atag", "vtag", "stag", NULL};
+static const char *opt_name_sample_fmts[] = {"sample_fmt", NULL};
+static const char *opt_name_qscale[] = {"q", "qscale", NULL};
+static const char *opt_name_forced_key_frames[] = {"forced_key_frames", NULL};
+static const char *opt_name_force_fps[] = {"force_fps", NULL};
+static const char *opt_name_frame_aspect_ratios[] = {"aspect", NULL};
+static const char *opt_name_rc_overrides[] = {"rc_override", NULL};
+static const char *opt_name_intra_matrices[] = {"intra_matrix", NULL};
+static const char *opt_name_inter_matrices[] = {"inter_matrix", NULL};
+static const char *opt_name_chroma_intra_matrices[] = {"chroma_intra_matrix", NULL};
+static const char *opt_name_top_field_first[] = {"top", NULL};
+static const char *opt_name_presets[] = {"pre", "apre", "vpre", "spre", NULL};
+static const char *opt_name_copy_initial_nonkeyframes[] = {"copyinkfr", NULL};
+static const char *opt_name_copy_prior_start[] = {"copypriorss", NULL};
+static const char *opt_name_filters[] = {"filter", "af", "vf", NULL};
+static const char *opt_name_filter_scripts[] = {"filter_script", NULL};
+static const char *opt_name_reinit_filters[] = {"reinit_filter", NULL};
+static const char *opt_name_fix_sub_duration[] = {"fix_sub_duration", NULL};
+static const char *opt_name_canvas_sizes[] = {"canvas_size", NULL};
+static const char *opt_name_pass[] = {"pass", NULL};
+static const char *opt_name_passlogfiles[] = {"passlogfile", NULL};
+static const char *opt_name_max_muxing_queue_size[] = {"max_muxing_queue_size", NULL};
+static const char *opt_name_guess_layout_max[] = {"guess_layout_max", NULL};
+static const char *opt_name_apad[] = {"apad", NULL};
+static const char *opt_name_discard[] = {"discard", NULL};
+static const char *opt_name_disposition[] = {"disposition", NULL};
+static const char *opt_name_time_bases[] = {"time_base", NULL};
+static const char *opt_name_enc_time_bases[] = {"enc_time_base", NULL};
+
+#define WARN_MULTIPLE_OPT_USAGE(name, type, so, st)\
+{\
+ char namestr[128] = "";\
+ const char *spec = so->specifier && so->specifier[0] ? so->specifier : "";\
+ for (i = 0; opt_name_##name[i]; i++)\
+ av_strlcatf(namestr, sizeof(namestr), "-%s%s", opt_name_##name[i], opt_name_##name[i+1] ? (opt_name_##name[i+2] ? ", " : " or ") : "");\
+ av_log(NULL, AV_LOG_WARNING, "Multiple %s options specified for stream %d, only the last option '-%s%s%s "SPECIFIER_OPT_FMT_##type"' will be used.\n",\
+ namestr, st->index, opt_name_##name[0], spec[0] ? ":" : "", spec, so->u.type);\
+}
+
#define MATCH_PER_STREAM_OPT(name, type, outvar, fmtctx, st)\
{\
- int i, ret;\
+ int i, ret, matches = 0;\
+ SpecifierOpt *so;\
for (i = 0; i < o->nb_ ## name; i++) {\
char *spec = o->name[i].specifier;\
- if ((ret = check_stream_specifier(fmtctx, st, spec)) > 0)\
+ if ((ret = check_stream_specifier(fmtctx, st, spec)) > 0) {\
outvar = o->name[i].u.type;\
- else if (ret < 0)\
+ so = &o->name[i];\
+ matches++;\
+ } else if (ret < 0)\
exit_program(1);\
}\
+ if (matches > 1)\
+ WARN_MULTIPLE_OPT_USAGE(name, type, so, st);\
}
#define MATCH_PER_TYPE_OPT(name, type, outvar, fmtctx, mediatype)\
#endif
#if CONFIG_LIBMFX
{ "qsv", qsv_init, HWACCEL_QSV, AV_PIX_FMT_QSV },
-#endif
-#if CONFIG_CUVID
- { "cuvid", cuvid_init, HWACCEL_CUVID, AV_PIX_FMT_CUDA },
#endif
{ 0 },
};
static int show_hwaccels(void *optctx, const char *opt, const char *arg)
{
enum AVHWDeviceType type = AV_HWDEVICE_TYPE_NONE;
- int i;
printf("Hardware acceleration methods:\n");
while ((type = av_hwdevice_iterate_types(type)) !=
AV_HWDEVICE_TYPE_NONE)
printf("%s\n", av_hwdevice_get_type_name(type));
- for (i = 0; hwaccels[i].name; i++)
- printf("%s\n", hwaccels[i].name);
printf("\n");
return 0;
}
MATCH_PER_STREAM_OPT(top_field_first, i, ist->top_field_first, ic, st);
MATCH_PER_STREAM_OPT(hwaccels, str, hwaccel, ic, st);
+ MATCH_PER_STREAM_OPT(hwaccel_output_formats, str,
+ hwaccel_output_format, ic, st);
+
+ if (!hwaccel_output_format && hwaccel && !strcmp(hwaccel, "cuvid")) {
+ av_log(NULL, AV_LOG_WARNING,
+ "WARNING: defaulting hwaccel_output_format to cuda for compatibility "
+ "with old commandlines. This behaviour is DEPRECATED and will be removed "
+ "in the future. Please explicitly set \"-hwaccel_output_format cuda\".\n");
+ ist->hwaccel_output_format = AV_PIX_FMT_CUDA;
+ } else if (hwaccel_output_format) {
+ ist->hwaccel_output_format = av_get_pix_fmt(hwaccel_output_format);
+ if (ist->hwaccel_output_format == AV_PIX_FMT_NONE) {
+ av_log(NULL, AV_LOG_FATAL, "Unrecognised hwaccel output "
+ "format: %s", hwaccel_output_format);
+ }
+ } else {
+ ist->hwaccel_output_format = AV_PIX_FMT_NONE;
+ }
+
if (hwaccel) {
// The NVDEC hwaccels use a CUDA device, so remap the name here.
- if (!strcmp(hwaccel, "nvdec"))
+ if (!strcmp(hwaccel, "nvdec") || !strcmp(hwaccel, "cuvid"))
hwaccel = "cuda";
if (!strcmp(hwaccel, "none"))
AV_HWDEVICE_TYPE_NONE)
av_log(NULL, AV_LOG_FATAL, "%s ",
av_hwdevice_get_type_name(type));
- for (i = 0; hwaccels[i].name; i++)
- av_log(NULL, AV_LOG_FATAL, "%s ", hwaccels[i].name);
av_log(NULL, AV_LOG_FATAL, "\n");
exit_program(1);
}
exit_program(1);
}
- MATCH_PER_STREAM_OPT(hwaccel_output_formats, str,
- hwaccel_output_format, ic, st);
- if (hwaccel_output_format) {
- ist->hwaccel_output_format = av_get_pix_fmt(hwaccel_output_format);
- if (ist->hwaccel_output_format == AV_PIX_FMT_NONE) {
- av_log(NULL, AV_LOG_FATAL, "Unrecognised hwaccel output "
- "format: %s", hwaccel_output_format);
- }
- } else {
- ist->hwaccel_output_format = AV_PIX_FMT_NONE;
- }
-
ist->hwaccel_pix_fmt = AV_PIX_FMT_NONE;
break;
if (!file_overwrite) {
if (proto_name && !strcmp(proto_name, "file") && avio_check(filename, 0) == 0) {
if (stdin_interaction && !no_file_overwrite) {
- fprintf(stderr,"File '%s' already exists. Overwrite ? [y/N] ", filename);
+ fprintf(stderr,"File '%s' already exists. Overwrite? [y/N] ", filename);
fflush(stderr);
term_exit();
signal(SIGINT, SIG_DFL);
MATCH_PER_STREAM_OPT(filter_scripts, str, ost->filters_script, oc, st);
MATCH_PER_STREAM_OPT(filters, str, ost->filters, oc, st);
- if (o->nb_filters > 1)
- av_log(NULL, AV_LOG_ERROR, "Only '-vf %s' read, ignoring remaining -vf options: Use ',' to separate filters\n", ost->filters);
if (!ost->stream_copy) {
const char *p = NULL;
MATCH_PER_STREAM_OPT(filter_scripts, str, ost->filters_script, oc, st);
MATCH_PER_STREAM_OPT(filters, str, ost->filters, oc, st);
- if (o->nb_filters > 1)
- av_log(NULL, AV_LOG_ERROR, "Only '-af %s' read, ignoring remaining -af options: Use ',' to separate filters\n", ost->filters);
if (!ost->stream_copy) {
char *sample_fmt = NULL;
for (i = 0; i < nb_input_streams; i++) {
int new_area;
ist = input_streams[i];
- new_area = ist->st->codecpar->width * ist->st->codecpar->height + 100000000*!!ist->st->codec_info_nb_frames;
+ new_area = ist->st->codecpar->width * ist->st->codecpar->height + 100000000*!!ist->st->codec_info_nb_frames
+ + 5000000*!!(ist->st->disposition & AV_DISPOSITION_DEFAULT);
if (ist->user_set_discard == AVDISCARD_ALL)
continue;
if((qcr!=MKTAG('A', 'P', 'I', 'C')) && (ist->st->disposition & AV_DISPOSITION_ATTACHED_PIC))
for (i = 0; i < nb_input_streams; i++) {
int score;
ist = input_streams[i];
- score = ist->st->codecpar->channels + 100000000*!!ist->st->codec_info_nb_frames;
+ score = ist->st->codecpar->channels + 100000000*!!ist->st->codec_info_nb_frames
+ + 5000000*!!(ist->st->disposition & AV_DISPOSITION_DEFAULT);
if (ist->user_set_discard == AVDISCARD_ALL)
continue;
if (ist->st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
o->attachments[i]);
exit_program(1);
}
- if (!(attachment = av_malloc(len))) {
- av_log(NULL, AV_LOG_FATAL, "Attachment %s too large to fit into memory.\n",
+ if (len > INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE ||
+ !(attachment = av_malloc(len + AV_INPUT_BUFFER_PADDING_SIZE))) {
+ av_log(NULL, AV_LOG_FATAL, "Attachment %s too large.\n",
o->attachments[i]);
exit_program(1);
}
avio_read(pb, attachment, len);
+ memset(attachment + len, 0, AV_INPUT_BUFFER_PADDING_SIZE);
ost = new_attachment_stream(o, oc, -1);
ost->stream_copy = 0;
} else {
/* Try to determine PAL/NTSC by peeking in the input files */
if (nb_input_files) {
- int i, j, fr;
+ int i, j;
for (j = 0; j < nb_input_files; j++) {
for (i = 0; i < input_files[j]->nb_streams; i++) {
AVStream *st = input_files[j]->ctx->streams[i];
+ int64_t fr;
if (st->codecpar->codec_type != AVMEDIA_TYPE_VIDEO)
continue;
- fr = st->time_base.den * 1000 / st->time_base.num;
+ fr = st->time_base.den * 1000LL / st->time_base.num;
if (fr == 25000) {
norm = PAL;
break;
static int opt_old2new(void *optctx, const char *opt, const char *arg)
{
OptionsContext *o = optctx;
+ int ret;
char *s = av_asprintf("%s:%c", opt + 1, *opt);
- int ret = parse_option(o, s, arg, options);
+ if (!s)
+ return AVERROR(ENOMEM);
+ ret = parse_option(o, s, arg, options);
av_free(s);
return ret;
}
return parse_option(o, "q:v", arg, options);
}
s = av_asprintf("q%s", opt + 6);
+ if (!s)
+ return AVERROR(ENOMEM);
ret = parse_option(o, s, arg, options);
av_free(s);
return ret;
static int opt_timecode(void *optctx, const char *opt, const char *arg)
{
OptionsContext *o = optctx;
+ int ret;
char *tcr = av_asprintf("timecode=%s", arg);
- int ret = parse_option(o, "metadata:g", tcr, options);
+ if (!tcr)
+ return AVERROR(ENOMEM);
+ ret = parse_option(o, "metadata:g", tcr, options);
if (ret >= 0)
ret = av_dict_set(&o->g->codec_opts, "gop_timecode", arg, 0);
av_free(tcr);
" -h -- print basic options\n"
" -h long -- print more options\n"
" -h full -- print all options (including all format and codec specific options, very long)\n"
- " -h type=name -- print all options for the named decoder/encoder/demuxer/muxer/filter/bsf\n"
+ " -h type=name -- print all options for the named decoder/encoder/demuxer/muxer/filter/bsf/protocol\n"
" See man %s for detailed description of the options.\n"
"\n", program_name);
OPT_EXIT, 0, 0);
show_help_options(options, "Global options (affect whole program "
- "instead of just one file:",
+ "instead of just one file):",
0, per_file | OPT_EXIT | OPT_EXPERT, 0);
if (show_advanced)
show_help_options(options, "Advanced global options:", OPT_EXPERT,
if (ret < 0) {
av_log(NULL, AV_LOG_ERROR, "Error parsing options for %s file "
"%s.\n", inout, g->arg);
+ uninit_options(&o);
return ret;
}
{ "stdin", OPT_BOOL | OPT_EXPERT, { &stdin_interaction },
"enable or disable interaction on standard input" },
{ "timelimit", HAS_ARG | OPT_EXPERT, { .func_arg = opt_timelimit },
- "set max runtime in seconds", "limit" },
+ "set max runtime in seconds in CPU user time", "limit" },
{ "dump", OPT_BOOL | OPT_EXPERT, { &do_pkt_dump },
"dump each input packet" },
{ "hex", OPT_BOOL | OPT_EXPERT, { &do_hex_dump },