avconv: use new options parser.
This commit is contained in:
parent
0ec1642b60
commit
77bd1bc73a
19
avconv.c
19
avconv.c
@ -2345,22 +2345,13 @@ static int64_t getmaxrss(void)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
av_log_set_flags(AV_LOG_SKIP_REPEATED);
|
av_log_set_flags(AV_LOG_SKIP_REPEATED);
|
||||||
parse_loglevel(argc, argv, options);
|
parse_loglevel(argc, argv, options);
|
||||||
|
|
||||||
@ -2374,10 +2365,10 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
show_banner();
|
show_banner();
|
||||||
|
|
||||||
parse_cpuflags(argc, argv, options);
|
/* parse options and open all input/output files */
|
||||||
|
ret = avconv_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();
|
||||||
|
4
avconv.h
4
avconv.h
@ -67,6 +67,8 @@ typedef struct MetadataMap {
|
|||||||
} MetadataMap;
|
} MetadataMap;
|
||||||
|
|
||||||
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;
|
||||||
@ -361,4 +363,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 avconv_parse_options(int argc, char **argv);
|
||||||
|
|
||||||
#endif /* AVCONV_H */
|
#endif /* AVCONV_H */
|
||||||
|
134
avconv_opt.c
134
avconv_opt.c
@ -78,7 +78,7 @@ static int intra_dc_precision = 8;
|
|||||||
static int using_stdin = 0;
|
static int using_stdin = 0;
|
||||||
static int input_sync;
|
static int input_sync;
|
||||||
|
|
||||||
void reset_options(OptionsContext *o)
|
static void uninit_options(OptionsContext *o)
|
||||||
{
|
{
|
||||||
const OptionDef *po = options;
|
const OptionDef *po = options;
|
||||||
int i;
|
int i;
|
||||||
@ -107,19 +107,18 @@ void reset_options(OptionsContext *o)
|
|||||||
av_freep(&o->stream_maps);
|
av_freep(&o->stream_maps);
|
||||||
av_freep(&o->meta_data_maps);
|
av_freep(&o->meta_data_maps);
|
||||||
av_freep(&o->streamid_map);
|
av_freep(&o->streamid_map);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void init_options(OptionsContext *o)
|
||||||
|
{
|
||||||
memset(o, 0, sizeof(*o));
|
memset(o, 0, sizeof(*o));
|
||||||
|
|
||||||
o->mux_max_delay = 0.7;
|
o->mux_max_delay = 0.7;
|
||||||
o->recording_time = INT64_MAX;
|
o->recording_time = INT64_MAX;
|
||||||
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 double parse_frame_aspect_ratio(const char *arg)
|
static double parse_frame_aspect_ratio(const char *arg)
|
||||||
{
|
{
|
||||||
int x = 0, y = 0;
|
int x = 0, y = 0;
|
||||||
@ -449,7 +448,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, NULL);
|
ist->opts = filter_codec_opts(o->g->codec_opts, ist->st->codec->codec_id, ic, st, NULL);
|
||||||
|
|
||||||
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);
|
||||||
@ -545,9 +544,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;
|
||||||
@ -577,7 +575,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
|
||||||
@ -588,7 +586,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) {
|
||||||
@ -597,33 +595,33 @@ 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);
|
||||||
|
|
||||||
ic->flags |= AVFMT_FLAG_NONBLOCK;
|
ic->flags |= AVFMT_FLAG_NONBLOCK;
|
||||||
ic->interrupt_callback = int_cb;
|
ic->interrupt_callback = int_cb;
|
||||||
|
|
||||||
/* open the input file with generic libav function */
|
/* open the input file with generic libav 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
|
||||||
@ -680,7 +678,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);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -777,7 +774,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)))) {
|
||||||
@ -845,7 +842,7 @@ 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);
|
||||||
|
|
||||||
ost->pix_fmts[0] = ost->pix_fmts[1] = AV_PIX_FMT_NONE;
|
ost->pix_fmts[0] = ost->pix_fmts[1] = AV_PIX_FMT_NONE;
|
||||||
|
|
||||||
@ -1169,9 +1166,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;
|
||||||
@ -1378,7 +1374,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) {
|
||||||
@ -1500,7 +1496,7 @@ loop_end:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
reset_options(o);
|
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)
|
||||||
@ -1858,6 +1854,94 @@ void show_usage(void)
|
|||||||
printf("\n");
|
printf("\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);
|
||||||
|
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);
|
||||||
|
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 avconv_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;
|
||||||
|
}
|
||||||
|
|
||||||
#define OFFSET(x) offsetof(OptionsContext, x)
|
#define OFFSET(x) offsetof(OptionsContext, x)
|
||||||
const OptionDef options[] = {
|
const OptionDef options[] = {
|
||||||
@ -1865,8 +1949,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" },
|
||||||
{ "c", HAS_ARG | OPT_STRING | OPT_SPEC, { .off = OFFSET(codec_names) },
|
{ "c", HAS_ARG | OPT_STRING | OPT_SPEC, { .off = OFFSET(codec_names) },
|
||||||
@ -2048,7 +2130,5 @@ const OptionDef options[] = {
|
|||||||
{ "dcodec", HAS_ARG | OPT_DATA | OPT_PERFILE | OPT_EXPERT, { .func_arg = opt_data_codec },
|
{ "dcodec", HAS_ARG | OPT_DATA | OPT_PERFILE | OPT_EXPERT, { .func_arg = opt_data_codec },
|
||||||
"force data codec ('copy' to copy stream)", "codec" },
|
"force data codec ('copy' to copy stream)", "codec" },
|
||||||
|
|
||||||
{ "default", HAS_ARG | OPT_AUDIO | OPT_VIDEO | OPT_EXPERT, { .func_arg = opt_default },
|
|
||||||
"generic catch all option", "" },
|
|
||||||
{ NULL, },
|
{ NULL, },
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user