Merge commit '77bd1bc73a1946b0f0ce09a7cbb242a65e138d06'

* commit '77bd1bc73a1946b0f0ce09a7cbb242a65e138d06':
  avconv: use new options parser.

Conflicts:
	ffmpeg.c
	ffmpeg.h
	ffmpeg_opt.c

Merged-by: Michael Niedermayer <michaelni@gmx.at>
This commit is contained in:
Michael Niedermayer 2012-12-20 02:38:02 +01:00
commit af4b1c02ac
5 changed files with 187 additions and 80 deletions

View File

@ -568,6 +568,7 @@ static void finish_group(OptionParseContext *octx, int group_idx,
#if CONFIG_SWSCALE #if CONFIG_SWSCALE
g->sws_opts = sws_opts; g->sws_opts = sws_opts;
#endif #endif
g->swr_opts = swr_opts;
g->codec_opts = codec_opts; g->codec_opts = codec_opts;
g->format_opts = format_opts; g->format_opts = format_opts;
@ -576,6 +577,7 @@ static void finish_group(OptionParseContext *octx, int group_idx,
#if CONFIG_SWSCALE #if CONFIG_SWSCALE
sws_opts = NULL; sws_opts = NULL;
#endif #endif
swr_opts = NULL;
init_opts(); init_opts();
memset(&octx->cur_group, 0, sizeof(octx->cur_group)); memset(&octx->cur_group, 0, sizeof(octx->cur_group));
@ -635,6 +637,8 @@ void uninit_parse_context(OptionParseContext *octx)
#if CONFIG_SWSCALE #if CONFIG_SWSCALE
sws_freeContext(l->groups[j].sws_opts); sws_freeContext(l->groups[j].sws_opts);
#endif #endif
if(CONFIG_SWRESAMPLE)
swr_free(&l->groups[j].swr_opts);
} }
av_freep(&l->groups); av_freep(&l->groups);
} }

View File

@ -254,6 +254,7 @@ typedef struct OptionGroup {
AVDictionary *codec_opts; AVDictionary *codec_opts;
AVDictionary *format_opts; AVDictionary *format_opts;
struct SwsContext *sws_opts; struct SwsContext *sws_opts;
struct SwrContext *swr_opts;
} OptionGroup; } OptionGroup;
/** /**

View File

@ -3152,22 +3152,13 @@ static void log_callback_null(void *ptr, int level, const char *fmt, va_list vl)
{ {
} }
static void parse_cpuflags(int argc, char **argv, const OptionDef *options)
{
int idx = locate_option(argc, argv, options, "cpuflags");
if (idx && argv[idx + 1])
opt_cpuflags(NULL, "cpuflags", argv[idx + 1]);
}
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
OptionsContext o = { 0 }; int ret;
int64_t ti; int64_t ti;
atexit(exit_program); atexit(exit_program);
reset_options(&o, 0);
setvbuf(stderr,NULL,_IONBF,0); /* win32 runtime needs this */ setvbuf(stderr,NULL,_IONBF,0); /* win32 runtime needs this */
av_log_set_flags(AV_LOG_SKIP_REPEATED); av_log_set_flags(AV_LOG_SKIP_REPEATED);
@ -3192,10 +3183,10 @@ int main(int argc, char **argv)
term_init(); term_init();
parse_cpuflags(argc, argv, options); /* parse options and open all input/output files */
ret = ffmpeg_parse_options(argc, argv);
/* parse options */ if (ret < 0)
parse_options(&o, argc, argv, options, opt_output_file); exit(1);
if (nb_output_files <= 0 && nb_input_files == 0) { if (nb_output_files <= 0 && nb_input_files == 0) {
show_usage(); show_usage();

View File

@ -71,6 +71,8 @@ typedef struct {
} AudioChannelMap; } AudioChannelMap;
typedef struct OptionsContext { typedef struct OptionsContext {
OptionGroup *g;
/* input/output options */ /* input/output options */
int64_t start_time; int64_t start_time;
const char *format; const char *format;
@ -413,4 +415,6 @@ int configure_output_filter(FilterGraph *fg, OutputFilter *ofilter, AVFilterInOu
int ist_in_filtergraph(FilterGraph *fg, InputStream *ist); int ist_in_filtergraph(FilterGraph *fg, InputStream *ist);
FilterGraph *init_simple_filtergraph(InputStream *ist, OutputStream *ost); FilterGraph *init_simple_filtergraph(InputStream *ist, OutputStream *ost);
int ffmpeg_parse_options(int argc, char **argv);
#endif /* FFMPEG_H */ #endif /* FFMPEG_H */

View File

@ -95,10 +95,9 @@ static int intra_dc_precision = 8;
static int do_psnr = 0; static int do_psnr = 0;
static int input_sync; static int input_sync;
void reset_options(OptionsContext *o, int is_input) static void uninit_options(OptionsContext *o, int is_input)
{ {
const OptionDef *po = options; const OptionDef *po = options;
OptionsContext bak= *o;
int i; int i;
/* all OPT_SPEC and OPT_STRING can be freed in generic way */ /* all OPT_SPEC and OPT_STRING can be freed in generic way */
@ -126,9 +125,16 @@ void reset_options(OptionsContext *o, int is_input)
av_freep(&o->audio_channel_maps); av_freep(&o->audio_channel_maps);
av_freep(&o->streamid_map); av_freep(&o->streamid_map);
if (!is_input)
o->recording_time = INT64_MAX;
}
static void init_options(OptionsContext *o, int is_input)
{
OptionsContext bak= *o;
memset(o, 0, sizeof(*o)); memset(o, 0, sizeof(*o));
if (is_input) { if (!is_input) {
o->recording_time = bak.recording_time; o->recording_time = bak.recording_time;
if (o->recording_time != INT64_MAX) if (o->recording_time != INT64_MAX)
av_log(NULL, AV_LOG_WARNING, av_log(NULL, AV_LOG_WARNING,
@ -139,12 +145,8 @@ void reset_options(OptionsContext *o, int is_input)
o->mux_max_delay = 0.7; o->mux_max_delay = 0.7;
o->limit_filesize = UINT64_MAX; o->limit_filesize = UINT64_MAX;
o->chapters_input_file = INT_MAX; o->chapters_input_file = INT_MAX;
uninit_opts();
init_opts();
} }
static int opt_frame_crop(void *optctx, const char *opt, const char *arg) static int opt_frame_crop(void *optctx, const char *opt, const char *arg)
{ {
av_log(NULL, AV_LOG_FATAL, "Option '%s' has been removed, use the crop filter instead\n", opt); av_log(NULL, AV_LOG_FATAL, "Option '%s' has been removed, use the crop filter instead\n", opt);
@ -567,7 +569,7 @@ static void add_input_streams(OptionsContext *o, AVFormatContext *ic)
ist->file_index = nb_input_files; ist->file_index = nb_input_files;
ist->discard = 1; ist->discard = 1;
st->discard = AVDISCARD_ALL; st->discard = AVDISCARD_ALL;
ist->opts = filter_codec_opts(codec_opts, ist->st->codec->codec_id, ic, st, choose_decoder(o, ic, st)); ist->opts = filter_codec_opts(o->g->codec_opts, ist->st->codec->codec_id, ic, st, choose_decoder(o, ic, st));
ist->ts_scale = 1.0; ist->ts_scale = 1.0;
MATCH_PER_STREAM_OPT(ts_scale, dbl, ist->ts_scale, ic, st); MATCH_PER_STREAM_OPT(ts_scale, dbl, ist->ts_scale, ic, st);
@ -692,9 +694,8 @@ static void dump_attachment(AVStream *st, const char *filename)
avio_close(out); avio_close(out);
} }
static int opt_input_file(void *optctx, const char *opt, const char *filename) static int open_input_file(OptionsContext *o, const char *filename)
{ {
OptionsContext *o = optctx;
AVFormatContext *ic; AVFormatContext *ic;
AVInputFormat *file_iformat = NULL; AVInputFormat *file_iformat = NULL;
int err, i, ret; int err, i, ret;
@ -727,7 +728,7 @@ static int opt_input_file(void *optctx, const char *opt, const char *filename)
} }
if (o->nb_audio_sample_rate) { if (o->nb_audio_sample_rate) {
snprintf(buf, sizeof(buf), "%d", o->audio_sample_rate[o->nb_audio_sample_rate - 1].u.i); snprintf(buf, sizeof(buf), "%d", o->audio_sample_rate[o->nb_audio_sample_rate - 1].u.i);
av_dict_set(&format_opts, "sample_rate", buf, 0); av_dict_set(&o->g->format_opts, "sample_rate", buf, 0);
} }
if (o->nb_audio_channels) { if (o->nb_audio_channels) {
/* because we set audio_channels based on both the "ac" and /* because we set audio_channels based on both the "ac" and
@ -738,7 +739,7 @@ static int opt_input_file(void *optctx, const char *opt, const char *filename)
AV_OPT_SEARCH_FAKE_OBJ)) { AV_OPT_SEARCH_FAKE_OBJ)) {
snprintf(buf, sizeof(buf), "%d", snprintf(buf, sizeof(buf), "%d",
o->audio_channels[o->nb_audio_channels - 1].u.i); o->audio_channels[o->nb_audio_channels - 1].u.i);
av_dict_set(&format_opts, "channels", buf, 0); av_dict_set(&o->g->format_opts, "channels", buf, 0);
} }
} }
if (o->nb_frame_rates) { if (o->nb_frame_rates) {
@ -747,15 +748,15 @@ static int opt_input_file(void *optctx, const char *opt, const char *filename)
if (file_iformat && file_iformat->priv_class && if (file_iformat && file_iformat->priv_class &&
av_opt_find(&file_iformat->priv_class, "framerate", NULL, 0, av_opt_find(&file_iformat->priv_class, "framerate", NULL, 0,
AV_OPT_SEARCH_FAKE_OBJ)) { AV_OPT_SEARCH_FAKE_OBJ)) {
av_dict_set(&format_opts, "framerate", av_dict_set(&o->g->format_opts, "framerate",
o->frame_rates[o->nb_frame_rates - 1].u.str, 0); o->frame_rates[o->nb_frame_rates - 1].u.str, 0);
} }
} }
if (o->nb_frame_sizes) { if (o->nb_frame_sizes) {
av_dict_set(&format_opts, "video_size", o->frame_sizes[o->nb_frame_sizes - 1].u.str, 0); av_dict_set(&o->g->format_opts, "video_size", o->frame_sizes[o->nb_frame_sizes - 1].u.str, 0);
} }
if (o->nb_frame_pix_fmts) if (o->nb_frame_pix_fmts)
av_dict_set(&format_opts, "pixel_format", o->frame_pix_fmts[o->nb_frame_pix_fmts - 1].u.str, 0); av_dict_set(&o->g->format_opts, "pixel_format", o->frame_pix_fmts[o->nb_frame_pix_fmts - 1].u.str, 0);
MATCH_PER_TYPE_OPT(codec_names, str, video_codec_name, ic, "v"); MATCH_PER_TYPE_OPT(codec_names, str, video_codec_name, ic, "v");
MATCH_PER_TYPE_OPT(codec_names, str, audio_codec_name, ic, "a"); MATCH_PER_TYPE_OPT(codec_names, str, audio_codec_name, ic, "a");
@ -771,19 +772,19 @@ static int opt_input_file(void *optctx, const char *opt, const char *filename)
ic->interrupt_callback = int_cb; ic->interrupt_callback = int_cb;
/* open the input file with generic avformat function */ /* open the input file with generic avformat function */
err = avformat_open_input(&ic, filename, file_iformat, &format_opts); err = avformat_open_input(&ic, filename, file_iformat, &o->g->format_opts);
if (err < 0) { if (err < 0) {
print_error(filename, err); print_error(filename, err);
exit(1); exit(1);
} }
assert_avoptions(format_opts); assert_avoptions(o->g->format_opts);
/* apply forced codec ids */ /* apply forced codec ids */
for (i = 0; i < ic->nb_streams; i++) for (i = 0; i < ic->nb_streams; i++)
choose_decoder(o, ic, ic->streams[i]); choose_decoder(o, ic, ic->streams[i]);
/* Set AVCodecContext options for avformat_find_stream_info */ /* Set AVCodecContext options for avformat_find_stream_info */
opts = setup_find_stream_info_opts(ic, codec_opts); opts = setup_find_stream_info_opts(ic, o->g->codec_opts);
orig_nb_streams = ic->nb_streams; orig_nb_streams = ic->nb_streams;
/* If not enough info to get the stream parameters, we decode the /* If not enough info to get the stream parameters, we decode the
@ -840,7 +841,6 @@ static int opt_input_file(void *optctx, const char *opt, const char *filename)
av_dict_free(&opts[i]); av_dict_free(&opts[i]);
av_freep(&opts); av_freep(&opts);
reset_options(o, 1);
return 0; return 0;
} }
@ -937,7 +937,7 @@ static OutputStream *new_output_stream(OptionsContext *o, AVFormatContext *oc, e
AVIOContext *s = NULL; AVIOContext *s = NULL;
char *buf = NULL, *arg = NULL, *preset = NULL; char *buf = NULL, *arg = NULL, *preset = NULL;
ost->opts = filter_codec_opts(codec_opts, ost->enc->id, oc, st, ost->enc); ost->opts = filter_codec_opts(o->g->codec_opts, ost->enc->id, oc, st, ost->enc);
MATCH_PER_STREAM_OPT(presets, str, preset, oc, st); MATCH_PER_STREAM_OPT(presets, str, preset, oc, st);
if (preset && (!(ret = get_preset_file_2(preset, ost->enc->name, &s)))) { if (preset && (!(ret = get_preset_file_2(preset, ost->enc->name, &s)))) {
@ -1008,10 +1008,10 @@ static OutputStream *new_output_stream(OptionsContext *o, AVFormatContext *oc, e
if (oc->oformat->flags & AVFMT_GLOBALHEADER) if (oc->oformat->flags & AVFMT_GLOBALHEADER)
st->codec->flags |= CODEC_FLAG_GLOBAL_HEADER; st->codec->flags |= CODEC_FLAG_GLOBAL_HEADER;
av_opt_get_int(sws_opts, "sws_flags", 0, &ost->sws_flags); av_opt_get_int(o->g->sws_opts, "sws_flags", 0, &ost->sws_flags);
av_opt_get_int (swr_opts, "filter_type" , 0, &ost->swr_filter_type); av_opt_get_int (o->g->swr_opts, "filter_type" , 0, &ost->swr_filter_type);
av_opt_get_int (swr_opts, "dither_method", 0, &ost->swr_dither_method); av_opt_get_int (o->g->swr_opts, "dither_method", 0, &ost->swr_dither_method);
av_opt_get_double(swr_opts, "dither_scale" , 0, &ost->swr_dither_scale); av_opt_get_double(o->g->swr_opts, "dither_scale" , 0, &ost->swr_dither_scale);
ost->source_index = source_index; ost->source_index = source_index;
if (source_index >= 0) { if (source_index >= 0) {
@ -1434,9 +1434,8 @@ static int configure_complex_filters(void)
return 0; return 0;
} }
void opt_output_file(void *optctx, const char *filename) static int open_output_file(OptionsContext *o, const char *filename)
{ {
OptionsContext *o = optctx;
AVFormatContext *oc; AVFormatContext *oc;
int i, j, err; int i, j, err;
AVOutputFormat *file_oformat; AVOutputFormat *file_oformat;
@ -1620,7 +1619,7 @@ loop_end:
ost = output_streams[i]; ost = output_streams[i];
if ( ost->stream_copy if ( ost->stream_copy
&& (e = av_dict_get(codec_opts, "flags", NULL, AV_DICT_IGNORE_SUFFIX)) && (e = av_dict_get(o->g->codec_opts, "flags", NULL, AV_DICT_IGNORE_SUFFIX))
&& (!e->key[5] || check_stream_specifier(oc, ost->st, e->key+6))) && (!e->key[5] || check_stream_specifier(oc, ost->st, e->key+6)))
if (av_opt_set(ost->st->codec, "flags", e->value, 0) < 0) if (av_opt_set(ost->st->codec, "flags", e->value, 0) < 0)
exit(1); exit(1);
@ -1673,7 +1672,7 @@ loop_end:
output_files[nb_output_files - 1]->start_time = o->start_time; output_files[nb_output_files - 1]->start_time = o->start_time;
output_files[nb_output_files - 1]->limit_filesize = o->limit_filesize; output_files[nb_output_files - 1]->limit_filesize = o->limit_filesize;
output_files[nb_output_files - 1]->shortest = o->shortest; output_files[nb_output_files - 1]->shortest = o->shortest;
av_dict_copy(&output_files[nb_output_files - 1]->opts, format_opts, 0); av_dict_copy(&output_files[nb_output_files - 1]->opts, o->g->format_opts, 0);
/* check filename in case of an image number is expected */ /* check filename in case of an image number is expected */
if (oc->oformat->flags & AVFMT_NEEDNUMBER) { if (oc->oformat->flags & AVFMT_NEEDNUMBER) {
@ -1798,7 +1797,7 @@ loop_end:
} }
} }
reset_options(o, 0); return 0;
} }
static int opt_target(void *optctx, const char *opt, const char *arg) static int opt_target(void *optctx, const char *opt, const char *arg)
@ -1853,22 +1852,23 @@ static int opt_target(void *optctx, const char *opt, const char *arg)
opt_video_codec(o, "c:v", "mpeg1video"); opt_video_codec(o, "c:v", "mpeg1video");
opt_audio_codec(o, "c:a", "mp2"); opt_audio_codec(o, "c:a", "mp2");
parse_option(o, "f", "vcd", options); parse_option(o, "f", "vcd", options);
av_dict_set(&o->g->codec_opts, "b:v", arg, 0);
parse_option(o, "s", norm == PAL ? "352x288" : "352x240", options); parse_option(o, "s", norm == PAL ? "352x288" : "352x240", options);
parse_option(o, "r", frame_rates[norm], options); parse_option(o, "r", frame_rates[norm], options);
opt_default(NULL, "g", norm == PAL ? "15" : "18"); av_dict_set(&o->g->codec_opts, "g", norm == PAL ? "15" : "18", 0);
opt_default(NULL, "b:v", "1150000"); av_dict_set(&o->g->codec_opts, "b:v", "1150000", 0);
opt_default(NULL, "maxrate", "1150000"); av_dict_set(&o->g->codec_opts, "maxrate", "1150000", 0);
opt_default(NULL, "minrate", "1150000"); av_dict_set(&o->g->codec_opts, "minrate", "1150000", 0);
opt_default(NULL, "bufsize", "327680"); // 40*1024*8; av_dict_set(&o->g->codec_opts, "bufsize", "327680", 0); // 40*1024*8;
opt_default(NULL, "b:a", "224000"); av_dict_set(&o->g->codec_opts, "b:a", "224000", 0);
parse_option(o, "ar", "44100", options); parse_option(o, "ar", "44100", options);
parse_option(o, "ac", "2", options); parse_option(o, "ac", "2", options);
opt_default(NULL, "packetsize", "2324"); av_dict_set(&o->g->format_opts, "packetsize", "2324", 0);
opt_default(NULL, "muxrate", "1411200"); // 2352 * 75 * 8; av_dict_set(&o->g->format_opts, "muxrate", "1411200", 0); // 2352 * 75 * 8;
/* We have to offset the PTS, so that it is consistent with the SCR. /* We have to offset the PTS, so that it is consistent with the SCR.
SCR starts at 36000, but the first two packs contain only padding SCR starts at 36000, but the first two packs contain only padding
@ -1885,18 +1885,18 @@ static int opt_target(void *optctx, const char *opt, const char *arg)
parse_option(o, "s", norm == PAL ? "480x576" : "480x480", options); parse_option(o, "s", norm == PAL ? "480x576" : "480x480", options);
parse_option(o, "r", frame_rates[norm], options); parse_option(o, "r", frame_rates[norm], options);
parse_option(o, "pix_fmt", "yuv420p", options); parse_option(o, "pix_fmt", "yuv420p", options);
opt_default(NULL, "g", norm == PAL ? "15" : "18"); av_dict_set(&o->g->codec_opts, "g", norm == PAL ? "15" : "18", 0);
opt_default(NULL, "b:v", "2040000"); av_dict_set(&o->g->codec_opts, "b:v", "2040000", 0);
opt_default(NULL, "maxrate", "2516000"); av_dict_set(&o->g->codec_opts, "maxrate", "2516000", 0);
opt_default(NULL, "minrate", "0"); // 1145000; av_dict_set(&o->g->codec_opts, "minrate", "0", 0); // 1145000;
opt_default(NULL, "bufsize", "1835008"); // 224*1024*8; av_dict_set(&o->g->codec_opts, "bufsize", "1835008", 0); // 224*1024*8;
opt_default(NULL, "scan_offset", "1"); av_dict_set(&o->g->codec_opts, "scan_offset", "1", 0);
opt_default(NULL, "b:a", "224000"); av_dict_set(&o->g->codec_opts, "b:a", "224000", 0);
parse_option(o, "ar", "44100", options); parse_option(o, "ar", "44100", options);
opt_default(NULL, "packetsize", "2324"); av_dict_set(&o->g->format_opts, "packetsize", "2324", 0);
} else if (!strcmp(arg, "dvd")) { } else if (!strcmp(arg, "dvd")) {
@ -1907,17 +1907,17 @@ static int opt_target(void *optctx, const char *opt, const char *arg)
parse_option(o, "s", norm == PAL ? "720x576" : "720x480", options); parse_option(o, "s", norm == PAL ? "720x576" : "720x480", options);
parse_option(o, "r", frame_rates[norm], options); parse_option(o, "r", frame_rates[norm], options);
parse_option(o, "pix_fmt", "yuv420p", options); parse_option(o, "pix_fmt", "yuv420p", options);
opt_default(NULL, "g", norm == PAL ? "15" : "18"); av_dict_set(&o->g->codec_opts, "g", norm == PAL ? "15" : "18", 0);
opt_default(NULL, "b:v", "6000000"); av_dict_set(&o->g->codec_opts, "b:v", "6000000", 0);
opt_default(NULL, "maxrate", "9000000"); av_dict_set(&o->g->codec_opts, "maxrate", "9000000", 0);
opt_default(NULL, "minrate", "0"); // 1500000; av_dict_set(&o->g->codec_opts, "minrate", "0", 0); // 1500000;
opt_default(NULL, "bufsize", "1835008"); // 224*1024*8; av_dict_set(&o->g->codec_opts, "bufsize", "1835008", 0); // 224*1024*8;
opt_default(NULL, "packetsize", "2048"); // from www.mpucoder.com: DVD sectors contain 2048 bytes of data, this is also the size of one pack. av_dict_set(&o->g->format_opts, "packetsize", "2048", 0); // from www.mpucoder.com: DVD sectors contain 2048 bytes of data, this is also the size of one pack.
opt_default(NULL, "muxrate", "10080000"); // from mplex project: data_rate = 1260000. mux_rate = data_rate * 8 av_dict_set(&o->g->format_opts, "muxrate", "10080000", 0); // from mplex project: data_rate = 1260000. mux_rate = data_rate * 8
opt_default(NULL, "b:a", "448000"); av_dict_set(&o->g->codec_opts, "b:a", "448000", 0);
parse_option(o, "ar", "48000", options); parse_option(o, "ar", "48000", options);
} else if (!strncmp(arg, "dv", 2)) { } else if (!strncmp(arg, "dv", 2)) {
@ -1975,6 +1975,26 @@ static int opt_data_frames(void *optctx, const char *opt, const char *arg)
return parse_option(o, "frames:d", arg, options); return parse_option(o, "frames:d", arg, options);
} }
static int opt_default_new(OptionsContext *o, const char *opt, const char *arg)
{
int ret;
AVCodecContext *cbak = codec_opts;
AVCodecContext *fbak = format_opts;
codec_opts = NULL;
format_opts = NULL;
ret = opt_default(NULL, opt, arg);
av_dict_copy(&o->g->codec_opts , codec_opts, 0);
av_dict_copy(&o->g->format_opts, format_opts, 0);
av_dict_free(&codec_opts);
av_dict_free(&format_opts);
codec_opts = cbak;
format_opts = fbak;
return ret;
}
static int opt_preset(void *optctx, const char *opt, const char *arg) static int opt_preset(void *optctx, const char *opt, const char *arg)
{ {
OptionsContext *o = optctx; OptionsContext *o = optctx;
@ -1992,7 +2012,7 @@ static int opt_preset(void *optctx, const char *opt, const char *arg)
}else }else
av_log(NULL, AV_LOG_FATAL, "File for preset '%s' not found\n", arg); av_log(NULL, AV_LOG_FATAL, "File for preset '%s' not found\n", arg);
exit(1); exit(1);
} }
while (fgets(line, sizeof(line), f)) { while (fgets(line, sizeof(line), f)) {
char *key = tmp_line, *value, *endptr; char *key = tmp_line, *value, *endptr;
@ -2011,7 +2031,7 @@ static int opt_preset(void *optctx, const char *opt, const char *arg)
else if (!strcmp(key, "vcodec")) opt_video_codec (o, key, value); else if (!strcmp(key, "vcodec")) opt_video_codec (o, key, value);
else if (!strcmp(key, "scodec")) opt_subtitle_codec(o, key, value); else if (!strcmp(key, "scodec")) opt_subtitle_codec(o, key, value);
else if (!strcmp(key, "dcodec")) opt_data_codec (o, key, value); else if (!strcmp(key, "dcodec")) opt_data_codec (o, key, value);
else if (opt_default(NULL, key, value) < 0) { else if (opt_default_new(o, key, value) < 0) {
av_log(NULL, AV_LOG_FATAL, "%s: Invalid option or argument: '%s', parsed as '%s' = '%s'\n", av_log(NULL, AV_LOG_FATAL, "%s: Invalid option or argument: '%s', parsed as '%s' = '%s'\n",
filename, line, key, value); filename, line, key, value);
exit(1); exit(1);
@ -2037,9 +2057,11 @@ static int opt_bitrate(void *optctx, const char *opt, const char *arg)
OptionsContext *o = optctx; OptionsContext *o = optctx;
if(!strcmp(opt, "b")){ if(!strcmp(opt, "b")){
av_log(NULL, AV_LOG_WARNING, "Please use -b:a or -b:v, -b is ambiguous\n"); av_log(NULL, AV_LOG_WARNING, "Please use -b:a or -b:v, -b is ambiguous\n");
return parse_option(o, "b:v", arg, options); av_dict_set(&o->g->codec_opts, "b:v", arg, 0);
return 0;
} }
return opt_default(optctx, opt, arg); av_dict_set(&o->g->codec_opts, opt, arg, 0);
return 0;
} }
static int opt_qscale(void *optctx, const char *opt, const char *arg) static int opt_qscale(void *optctx, const char *opt, const char *arg)
@ -2062,10 +2084,11 @@ static int opt_profile(void *optctx, const char *opt, const char *arg)
OptionsContext *o = optctx; OptionsContext *o = optctx;
if(!strcmp(opt, "profile")){ if(!strcmp(opt, "profile")){
av_log(NULL, AV_LOG_WARNING, "Please use -profile:a or -profile:v, -profile is ambiguous\n"); av_log(NULL, AV_LOG_WARNING, "Please use -profile:a or -profile:v, -profile is ambiguous\n");
return parse_option(o, "profile:v", arg, options); av_dict_set(&o->g->codec_opts, "profile:v", arg, 0);
return 0;
} }
return opt_default(optctx, opt, arg); av_dict_set(&o->g->codec_opts, opt, arg, 0);
return 0;
} }
static int opt_video_filters(void *optctx, const char *opt, const char *arg) static int opt_video_filters(void *optctx, const char *opt, const char *arg)
@ -2105,9 +2128,9 @@ static int opt_timecode(void *optctx, const char *opt, const char *arg)
char *tcr = av_asprintf("timecode=%s", arg); char *tcr = av_asprintf("timecode=%s", arg);
int ret = parse_option(o, "metadata:g", tcr, options); int ret = parse_option(o, "metadata:g", tcr, options);
if (ret >= 0) if (ret >= 0)
ret = opt_default(optctx, "gop_timecode", arg); ret = av_dict_set(&o->g->codec_opts, "gop_timecode", arg, 0);
av_free(tcr); av_free(tcr);
return ret; return 0;
} }
static int opt_channel_layout(void *optctx, const char *opt, const char *arg) static int opt_channel_layout(void *optctx, const char *opt, const char *arg)
@ -2235,6 +2258,94 @@ void show_usage(void)
av_log(NULL, AV_LOG_INFO, "\n"); av_log(NULL, AV_LOG_INFO, "\n");
} }
enum OptGroup {
GROUP_OUTFILE,
GROUP_INFILE,
};
static const OptionGroupDef groups[] = {
[GROUP_OUTFILE] = { "output file", NULL },
[GROUP_INFILE] = { "input file", "i" },
{ 0 },
};
static int open_files(OptionGroupList *l, const char *inout,
int (*open_file)(OptionsContext*, const char*))
{
int i, ret;
for (i = 0; i < l->nb_groups; i++) {
OptionGroup *g = &l->groups[i];
OptionsContext o;
init_options(&o, !strcmp(inout, "input"));
o.g = g;
ret = parse_optgroup(&o, g);
if (ret < 0) {
av_log(NULL, AV_LOG_ERROR, "Error parsing options for %s file "
"%s.\n", inout, g->arg);
return ret;
}
av_log(NULL, AV_LOG_DEBUG, "Opening an %s file: %s.\n", inout, g->arg);
ret = open_file(&o, g->arg);
uninit_options(&o, !strcmp(inout, "input"));
if (ret < 0) {
av_log(NULL, AV_LOG_ERROR, "Error opening %s file %s.\n",
inout, g->arg);
return ret;
}
av_log(NULL, AV_LOG_DEBUG, "Successfully openened the file.\n");
}
return 0;
}
int ffmpeg_parse_options(int argc, char **argv)
{
OptionParseContext octx;
uint8_t error[128];
int ret;
memset(&octx, 0, sizeof(octx));
/* split the commandline into an internal representation */
ret = split_commandline(&octx, argc, argv, options, groups);
if (ret < 0) {
av_log(NULL, AV_LOG_FATAL, "Error splitting the argument list: ");
goto fail;
}
/* apply global options */
ret = parse_optgroup(NULL, &octx.global_opts);
if (ret < 0) {
av_log(NULL, AV_LOG_FATAL, "Error parsing global options: ");
goto fail;
}
/* open input files */
ret = open_files(&octx.groups[GROUP_INFILE], "input", open_input_file);
if (ret < 0) {
av_log(NULL, AV_LOG_FATAL, "Error opening input files: ");
goto fail;
}
/* open output files */
ret = open_files(&octx.groups[GROUP_OUTFILE], "output", open_output_file);
if (ret < 0) {
av_log(NULL, AV_LOG_FATAL, "Error opening output files: ");
goto fail;
}
fail:
uninit_parse_context(&octx);
if (ret < 0) {
av_strerror(ret, error, sizeof(error));
av_log(NULL, AV_LOG_FATAL, "%s\n", error);
}
return ret;
}
static int opt_progress(void *optctx, const char *opt, const char *arg) static int opt_progress(void *optctx, const char *opt, const char *arg)
{ {
@ -2259,8 +2370,6 @@ const OptionDef options[] = {
#include "cmdutils_common_opts.h" #include "cmdutils_common_opts.h"
{ "f", HAS_ARG | OPT_STRING | OPT_OFFSET, { .off = OFFSET(format) }, { "f", HAS_ARG | OPT_STRING | OPT_OFFSET, { .off = OFFSET(format) },
"force format", "fmt" }, "force format", "fmt" },
{ "i", HAS_ARG | OPT_PERFILE, { .func_arg = opt_input_file },
"input file name", "filename" },
{ "y", OPT_BOOL, { &file_overwrite }, { "y", OPT_BOOL, { &file_overwrite },
"overwrite output files" }, "overwrite output files" },
{ "n", OPT_BOOL, { &no_file_overwrite }, { "n", OPT_BOOL, { &no_file_overwrite },
@ -2515,7 +2624,5 @@ const OptionDef options[] = {
{ "dn", OPT_BOOL | OPT_VIDEO | OPT_OFFSET, { .off = OFFSET(data_disable) }, { "dn", OPT_BOOL | OPT_VIDEO | OPT_OFFSET, { .off = OFFSET(data_disable) },
"disable data" }, "disable data" },
{ "default", HAS_ARG | OPT_AUDIO | OPT_VIDEO | OPT_EXPERT, { .func_arg = opt_default },
"generic catch all option", "" },
{ NULL, }, { NULL, },
}; };