... | ... |
@@ -2345,22 +2345,13 @@ static int64_t getmaxrss(void) |
2345 | 2345 |
#endif |
2346 | 2346 |
} |
2347 | 2347 |
|
2348 |
-static void parse_cpuflags(int argc, char **argv, const OptionDef *options) |
|
2349 |
-{ |
|
2350 |
- int idx = locate_option(argc, argv, options, "cpuflags"); |
|
2351 |
- if (idx && argv[idx + 1]) |
|
2352 |
- opt_cpuflags(NULL, "cpuflags", argv[idx + 1]); |
|
2353 |
-} |
|
2354 |
- |
|
2355 | 2348 |
int main(int argc, char **argv) |
2356 | 2349 |
{ |
2357 |
- OptionsContext o = { 0 }; |
|
2350 |
+ int ret; |
|
2358 | 2351 |
int64_t ti; |
2359 | 2352 |
|
2360 | 2353 |
atexit(exit_program); |
2361 | 2354 |
|
2362 |
- reset_options(&o); |
|
2363 |
- |
|
2364 | 2355 |
av_log_set_flags(AV_LOG_SKIP_REPEATED); |
2365 | 2356 |
parse_loglevel(argc, argv, options); |
2366 | 2357 |
|
... | ... |
@@ -2374,10 +2365,10 @@ int main(int argc, char **argv) |
2374 | 2374 |
|
2375 | 2375 |
show_banner(); |
2376 | 2376 |
|
2377 |
- parse_cpuflags(argc, argv, options); |
|
2378 |
- |
|
2379 |
- /* parse options */ |
|
2380 |
- parse_options(&o, argc, argv, options, opt_output_file); |
|
2377 |
+ /* parse options and open all input/output files */ |
|
2378 |
+ ret = avconv_parse_options(argc, argv); |
|
2379 |
+ if (ret < 0) |
|
2380 |
+ exit(1); |
|
2381 | 2381 |
|
2382 | 2382 |
if (nb_output_files <= 0 && nb_input_files == 0) { |
2383 | 2383 |
show_usage(); |
... | ... |
@@ -67,6 +67,8 @@ typedef struct MetadataMap { |
67 | 67 |
} MetadataMap; |
68 | 68 |
|
69 | 69 |
typedef struct OptionsContext { |
70 |
+ OptionGroup *g; |
|
71 |
+ |
|
70 | 72 |
/* input/output options */ |
71 | 73 |
int64_t start_time; |
72 | 74 |
const char *format; |
... | ... |
@@ -361,4 +363,6 @@ int configure_output_filter(FilterGraph *fg, OutputFilter *ofilter, AVFilterInOu |
361 | 361 |
int ist_in_filtergraph(FilterGraph *fg, InputStream *ist); |
362 | 362 |
FilterGraph *init_simple_filtergraph(InputStream *ist, OutputStream *ost); |
363 | 363 |
|
364 |
+int avconv_parse_options(int argc, char **argv); |
|
365 |
+ |
|
364 | 366 |
#endif /* AVCONV_H */ |
... | ... |
@@ -78,7 +78,7 @@ static int intra_dc_precision = 8; |
78 | 78 |
static int using_stdin = 0; |
79 | 79 |
static int input_sync; |
80 | 80 |
|
81 |
-void reset_options(OptionsContext *o) |
|
81 |
+static void uninit_options(OptionsContext *o) |
|
82 | 82 |
{ |
83 | 83 |
const OptionDef *po = options; |
84 | 84 |
int i; |
... | ... |
@@ -107,19 +107,18 @@ void reset_options(OptionsContext *o) |
107 | 107 |
av_freep(&o->stream_maps); |
108 | 108 |
av_freep(&o->meta_data_maps); |
109 | 109 |
av_freep(&o->streamid_map); |
110 |
+} |
|
110 | 111 |
|
112 |
+static void init_options(OptionsContext *o) |
|
113 |
+{ |
|
111 | 114 |
memset(o, 0, sizeof(*o)); |
112 | 115 |
|
113 | 116 |
o->mux_max_delay = 0.7; |
114 | 117 |
o->recording_time = INT64_MAX; |
115 | 118 |
o->limit_filesize = UINT64_MAX; |
116 | 119 |
o->chapters_input_file = INT_MAX; |
117 |
- |
|
118 |
- uninit_opts(); |
|
119 |
- init_opts(); |
|
120 | 120 |
} |
121 | 121 |
|
122 |
- |
|
123 | 122 |
static double parse_frame_aspect_ratio(const char *arg) |
124 | 123 |
{ |
125 | 124 |
int x = 0, y = 0; |
... | ... |
@@ -449,7 +448,7 @@ static void add_input_streams(OptionsContext *o, AVFormatContext *ic) |
449 | 449 |
ist->file_index = nb_input_files; |
450 | 450 |
ist->discard = 1; |
451 | 451 |
st->discard = AVDISCARD_ALL; |
452 |
- ist->opts = filter_codec_opts(codec_opts, ist->st->codec->codec_id, ic, st, NULL); |
|
452 |
+ ist->opts = filter_codec_opts(o->g->codec_opts, ist->st->codec->codec_id, ic, st, NULL); |
|
453 | 453 |
|
454 | 454 |
ist->ts_scale = 1.0; |
455 | 455 |
MATCH_PER_STREAM_OPT(ts_scale, dbl, ist->ts_scale, ic, st); |
... | ... |
@@ -545,9 +544,8 @@ static void dump_attachment(AVStream *st, const char *filename) |
545 | 545 |
avio_close(out); |
546 | 546 |
} |
547 | 547 |
|
548 |
-static int opt_input_file(void *optctx, const char *opt, const char *filename) |
|
548 |
+static int open_input_file(OptionsContext *o, const char *filename) |
|
549 | 549 |
{ |
550 |
- OptionsContext *o = optctx; |
|
551 | 550 |
AVFormatContext *ic; |
552 | 551 |
AVInputFormat *file_iformat = NULL; |
553 | 552 |
int err, i, ret; |
... | ... |
@@ -577,7 +575,7 @@ static int opt_input_file(void *optctx, const char *opt, const char *filename) |
577 | 577 |
} |
578 | 578 |
if (o->nb_audio_sample_rate) { |
579 | 579 |
snprintf(buf, sizeof(buf), "%d", o->audio_sample_rate[o->nb_audio_sample_rate - 1].u.i); |
580 |
- av_dict_set(&format_opts, "sample_rate", buf, 0); |
|
580 |
+ av_dict_set(&o->g->format_opts, "sample_rate", buf, 0); |
|
581 | 581 |
} |
582 | 582 |
if (o->nb_audio_channels) { |
583 | 583 |
/* because we set audio_channels based on both the "ac" and |
... | ... |
@@ -588,7 +586,7 @@ static int opt_input_file(void *optctx, const char *opt, const char *filename) |
588 | 588 |
AV_OPT_SEARCH_FAKE_OBJ)) { |
589 | 589 |
snprintf(buf, sizeof(buf), "%d", |
590 | 590 |
o->audio_channels[o->nb_audio_channels - 1].u.i); |
591 |
- av_dict_set(&format_opts, "channels", buf, 0); |
|
591 |
+ av_dict_set(&o->g->format_opts, "channels", buf, 0); |
|
592 | 592 |
} |
593 | 593 |
} |
594 | 594 |
if (o->nb_frame_rates) { |
... | ... |
@@ -597,33 +595,33 @@ static int opt_input_file(void *optctx, const char *opt, const char *filename) |
597 | 597 |
if (file_iformat && file_iformat->priv_class && |
598 | 598 |
av_opt_find(&file_iformat->priv_class, "framerate", NULL, 0, |
599 | 599 |
AV_OPT_SEARCH_FAKE_OBJ)) { |
600 |
- av_dict_set(&format_opts, "framerate", |
|
600 |
+ av_dict_set(&o->g->format_opts, "framerate", |
|
601 | 601 |
o->frame_rates[o->nb_frame_rates - 1].u.str, 0); |
602 | 602 |
} |
603 | 603 |
} |
604 | 604 |
if (o->nb_frame_sizes) { |
605 |
- av_dict_set(&format_opts, "video_size", o->frame_sizes[o->nb_frame_sizes - 1].u.str, 0); |
|
605 |
+ av_dict_set(&o->g->format_opts, "video_size", o->frame_sizes[o->nb_frame_sizes - 1].u.str, 0); |
|
606 | 606 |
} |
607 | 607 |
if (o->nb_frame_pix_fmts) |
608 |
- av_dict_set(&format_opts, "pixel_format", o->frame_pix_fmts[o->nb_frame_pix_fmts - 1].u.str, 0); |
|
608 |
+ av_dict_set(&o->g->format_opts, "pixel_format", o->frame_pix_fmts[o->nb_frame_pix_fmts - 1].u.str, 0); |
|
609 | 609 |
|
610 | 610 |
ic->flags |= AVFMT_FLAG_NONBLOCK; |
611 | 611 |
ic->interrupt_callback = int_cb; |
612 | 612 |
|
613 | 613 |
/* open the input file with generic libav function */ |
614 |
- err = avformat_open_input(&ic, filename, file_iformat, &format_opts); |
|
614 |
+ err = avformat_open_input(&ic, filename, file_iformat, &o->g->format_opts); |
|
615 | 615 |
if (err < 0) { |
616 | 616 |
print_error(filename, err); |
617 | 617 |
exit(1); |
618 | 618 |
} |
619 |
- assert_avoptions(format_opts); |
|
619 |
+ assert_avoptions(o->g->format_opts); |
|
620 | 620 |
|
621 | 621 |
/* apply forced codec ids */ |
622 | 622 |
for (i = 0; i < ic->nb_streams; i++) |
623 | 623 |
choose_decoder(o, ic, ic->streams[i]); |
624 | 624 |
|
625 | 625 |
/* Set AVCodecContext options for avformat_find_stream_info */ |
626 |
- opts = setup_find_stream_info_opts(ic, codec_opts); |
|
626 |
+ opts = setup_find_stream_info_opts(ic, o->g->codec_opts); |
|
627 | 627 |
orig_nb_streams = ic->nb_streams; |
628 | 628 |
|
629 | 629 |
/* If not enough info to get the stream parameters, we decode the |
... | ... |
@@ -680,7 +678,6 @@ static int opt_input_file(void *optctx, const char *opt, const char *filename) |
680 | 680 |
av_dict_free(&opts[i]); |
681 | 681 |
av_freep(&opts); |
682 | 682 |
|
683 |
- reset_options(o); |
|
684 | 683 |
return 0; |
685 | 684 |
} |
686 | 685 |
|
... | ... |
@@ -777,7 +774,7 @@ static OutputStream *new_output_stream(OptionsContext *o, AVFormatContext *oc, e |
777 | 777 |
AVIOContext *s = NULL; |
778 | 778 |
char *buf = NULL, *arg = NULL, *preset = NULL; |
779 | 779 |
|
780 |
- ost->opts = filter_codec_opts(codec_opts, ost->enc->id, oc, st, ost->enc); |
|
780 |
+ ost->opts = filter_codec_opts(o->g->codec_opts, ost->enc->id, oc, st, ost->enc); |
|
781 | 781 |
|
782 | 782 |
MATCH_PER_STREAM_OPT(presets, str, preset, oc, st); |
783 | 783 |
if (preset && (!(ret = get_preset_file_2(preset, ost->enc->name, &s)))) { |
... | ... |
@@ -845,7 +842,7 @@ static OutputStream *new_output_stream(OptionsContext *o, AVFormatContext *oc, e |
845 | 845 |
if (oc->oformat->flags & AVFMT_GLOBALHEADER) |
846 | 846 |
st->codec->flags |= CODEC_FLAG_GLOBAL_HEADER; |
847 | 847 |
|
848 |
- av_opt_get_int(sws_opts, "sws_flags", 0, &ost->sws_flags); |
|
848 |
+ av_opt_get_int(o->g->sws_opts, "sws_flags", 0, &ost->sws_flags); |
|
849 | 849 |
|
850 | 850 |
ost->pix_fmts[0] = ost->pix_fmts[1] = AV_PIX_FMT_NONE; |
851 | 851 |
|
... | ... |
@@ -1169,9 +1166,8 @@ static int configure_complex_filters(void) |
1169 | 1169 |
return 0; |
1170 | 1170 |
} |
1171 | 1171 |
|
1172 |
-void opt_output_file(void *optctx, const char *filename) |
|
1172 |
+static int open_output_file(OptionsContext *o, const char *filename) |
|
1173 | 1173 |
{ |
1174 |
- OptionsContext *o = optctx; |
|
1175 | 1174 |
AVFormatContext *oc; |
1176 | 1175 |
int i, j, err; |
1177 | 1176 |
AVOutputFormat *file_oformat; |
... | ... |
@@ -1378,7 +1374,7 @@ loop_end: |
1378 | 1378 |
output_files[nb_output_files - 1]->start_time = o->start_time; |
1379 | 1379 |
output_files[nb_output_files - 1]->limit_filesize = o->limit_filesize; |
1380 | 1380 |
output_files[nb_output_files - 1]->shortest = o->shortest; |
1381 |
- av_dict_copy(&output_files[nb_output_files - 1]->opts, format_opts, 0); |
|
1381 |
+ av_dict_copy(&output_files[nb_output_files - 1]->opts, o->g->format_opts, 0); |
|
1382 | 1382 |
|
1383 | 1383 |
/* check filename in case of an image number is expected */ |
1384 | 1384 |
if (oc->oformat->flags & AVFMT_NEEDNUMBER) { |
... | ... |
@@ -1500,7 +1496,7 @@ loop_end: |
1500 | 1500 |
} |
1501 | 1501 |
} |
1502 | 1502 |
|
1503 |
- reset_options(o); |
|
1503 |
+ return 0; |
|
1504 | 1504 |
} |
1505 | 1505 |
|
1506 | 1506 |
static int opt_target(void *optctx, const char *opt, const char *arg) |
... | ... |
@@ -1858,6 +1854,94 @@ void show_usage(void) |
1858 | 1858 |
printf("\n"); |
1859 | 1859 |
} |
1860 | 1860 |
|
1861 |
+enum OptGroup { |
|
1862 |
+ GROUP_OUTFILE, |
|
1863 |
+ GROUP_INFILE, |
|
1864 |
+}; |
|
1865 |
+ |
|
1866 |
+static const OptionGroupDef groups[] = { |
|
1867 |
+ [GROUP_OUTFILE] = { "output file", NULL }, |
|
1868 |
+ [GROUP_INFILE] = { "input file", "i" }, |
|
1869 |
+ { 0 }, |
|
1870 |
+}; |
|
1871 |
+ |
|
1872 |
+static int open_files(OptionGroupList *l, const char *inout, |
|
1873 |
+ int (*open_file)(OptionsContext*, const char*)) |
|
1874 |
+{ |
|
1875 |
+ int i, ret; |
|
1876 |
+ |
|
1877 |
+ for (i = 0; i < l->nb_groups; i++) { |
|
1878 |
+ OptionGroup *g = &l->groups[i]; |
|
1879 |
+ OptionsContext o; |
|
1880 |
+ |
|
1881 |
+ init_options(&o); |
|
1882 |
+ o.g = g; |
|
1883 |
+ |
|
1884 |
+ ret = parse_optgroup(&o, g); |
|
1885 |
+ if (ret < 0) { |
|
1886 |
+ av_log(NULL, AV_LOG_ERROR, "Error parsing options for %s file " |
|
1887 |
+ "%s.\n", inout, g->arg); |
|
1888 |
+ return ret; |
|
1889 |
+ } |
|
1890 |
+ |
|
1891 |
+ av_log(NULL, AV_LOG_DEBUG, "Opening an %s file: %s.\n", inout, g->arg); |
|
1892 |
+ ret = open_file(&o, g->arg); |
|
1893 |
+ uninit_options(&o); |
|
1894 |
+ if (ret < 0) { |
|
1895 |
+ av_log(NULL, AV_LOG_ERROR, "Error opening %s file %s.\n", |
|
1896 |
+ inout, g->arg); |
|
1897 |
+ return ret; |
|
1898 |
+ } |
|
1899 |
+ av_log(NULL, AV_LOG_DEBUG, "Successfully openened the file.\n"); |
|
1900 |
+ } |
|
1901 |
+ |
|
1902 |
+ return 0; |
|
1903 |
+} |
|
1904 |
+ |
|
1905 |
+int avconv_parse_options(int argc, char **argv) |
|
1906 |
+{ |
|
1907 |
+ OptionParseContext octx; |
|
1908 |
+ uint8_t error[128]; |
|
1909 |
+ int ret; |
|
1910 |
+ |
|
1911 |
+ memset(&octx, 0, sizeof(octx)); |
|
1912 |
+ |
|
1913 |
+ /* split the commandline into an internal representation */ |
|
1914 |
+ ret = split_commandline(&octx, argc, argv, options, groups); |
|
1915 |
+ if (ret < 0) { |
|
1916 |
+ av_log(NULL, AV_LOG_FATAL, "Error splitting the argument list: "); |
|
1917 |
+ goto fail; |
|
1918 |
+ } |
|
1919 |
+ |
|
1920 |
+ /* apply global options */ |
|
1921 |
+ ret = parse_optgroup(NULL, &octx.global_opts); |
|
1922 |
+ if (ret < 0) { |
|
1923 |
+ av_log(NULL, AV_LOG_FATAL, "Error parsing global options: "); |
|
1924 |
+ goto fail; |
|
1925 |
+ } |
|
1926 |
+ |
|
1927 |
+ /* open input files */ |
|
1928 |
+ ret = open_files(&octx.groups[GROUP_INFILE], "input", open_input_file); |
|
1929 |
+ if (ret < 0) { |
|
1930 |
+ av_log(NULL, AV_LOG_FATAL, "Error opening input files: "); |
|
1931 |
+ goto fail; |
|
1932 |
+ } |
|
1933 |
+ |
|
1934 |
+ /* open output files */ |
|
1935 |
+ ret = open_files(&octx.groups[GROUP_OUTFILE], "output", open_output_file); |
|
1936 |
+ if (ret < 0) { |
|
1937 |
+ av_log(NULL, AV_LOG_FATAL, "Error opening output files: "); |
|
1938 |
+ goto fail; |
|
1939 |
+ } |
|
1940 |
+ |
|
1941 |
+fail: |
|
1942 |
+ uninit_parse_context(&octx); |
|
1943 |
+ if (ret < 0) { |
|
1944 |
+ av_strerror(ret, error, sizeof(error)); |
|
1945 |
+ av_log(NULL, AV_LOG_FATAL, "%s\n", error); |
|
1946 |
+ } |
|
1947 |
+ return ret; |
|
1948 |
+} |
|
1861 | 1949 |
|
1862 | 1950 |
#define OFFSET(x) offsetof(OptionsContext, x) |
1863 | 1951 |
const OptionDef options[] = { |
... | ... |
@@ -1865,8 +1949,6 @@ const OptionDef options[] = { |
1865 | 1865 |
#include "cmdutils_common_opts.h" |
1866 | 1866 |
{ "f", HAS_ARG | OPT_STRING | OPT_OFFSET, { .off = OFFSET(format) }, |
1867 | 1867 |
"force format", "fmt" }, |
1868 |
- { "i", HAS_ARG | OPT_PERFILE, { .func_arg = opt_input_file }, |
|
1869 |
- "input file name", "filename" }, |
|
1870 | 1868 |
{ "y", OPT_BOOL, { &file_overwrite }, |
1871 | 1869 |
"overwrite output files" }, |
1872 | 1870 |
{ "c", HAS_ARG | OPT_STRING | OPT_SPEC, { .off = OFFSET(codec_names) }, |
... | ... |
@@ -2048,7 +2130,5 @@ const OptionDef options[] = { |
2048 | 2048 |
{ "dcodec", HAS_ARG | OPT_DATA | OPT_PERFILE | OPT_EXPERT, { .func_arg = opt_data_codec }, |
2049 | 2049 |
"force data codec ('copy' to copy stream)", "codec" }, |
2050 | 2050 |
|
2051 |
- { "default", HAS_ARG | OPT_AUDIO | OPT_VIDEO | OPT_EXPERT, { .func_arg = opt_default }, |
|
2052 |
- "generic catch all option", "" }, |
|
2053 | 2051 |
{ NULL, }, |
2054 | 2052 |
}; |