Merge commit '77bd1bc73a1946b0f0ce09a7cbb242a65e138d06'
authorMichael Niedermayer <michaelni@gmx.at>
Thu, 20 Dec 2012 01:38:02 +0000 (02:38 +0100)
committerMichael Niedermayer <michaelni@gmx.at>
Thu, 20 Dec 2012 01:38:02 +0000 (02:38 +0100)
* commit '77bd1bc73a1946b0f0ce09a7cbb242a65e138d06':
  avconv: use new options parser.

Conflicts:
ffmpeg.c
ffmpeg.h
ffmpeg_opt.c

Merged-by: Michael Niedermayer <michaelni@gmx.at>
1  2 
cmdutils.c
cmdutils.h
ffmpeg.c
ffmpeg.h
ffmpeg_opt.c

diff --cc cmdutils.c
@@@ -568,6 -477,6 +568,7 @@@ static void finish_group(OptionParseCon
  #if CONFIG_SWSCALE
      g->sws_opts    = sws_opts;
  #endif
++    g->swr_opts    = swr_opts;
      g->codec_opts  = codec_opts;
      g->format_opts = format_opts;
  
  #if CONFIG_SWSCALE
      sws_opts    = NULL;
  #endif
++    swr_opts    = NULL;
      init_opts();
  
      memset(&octx->cur_group, 0, sizeof(octx->cur_group));
@@@ -635,6 -544,6 +637,8 @@@ void uninit_parse_context(OptionParseCo
  #if CONFIG_SWSCALE
              sws_freeContext(l->groups[j].sws_opts);
  #endif
++            if(CONFIG_SWRESAMPLE)
++                swr_free(&l->groups[j].swr_opts);
          }
          av_freep(&l->groups);
      }
diff --cc cmdutils.h
@@@ -254,6 -236,6 +254,7 @@@ typedef struct OptionGroup 
      AVDictionary *codec_opts;
      AVDictionary *format_opts;
      struct SwsContext *sws_opts;
++    struct SwrContext *swr_opts;
  } OptionGroup;
  
  /**
diff --cc ffmpeg.c
+++ b/ffmpeg.c
@@@ -3148,28 -2345,13 +3148,19 @@@ static int64_t getmaxrss(void
  #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]);
- }
 +static void log_callback_null(void *ptr, int level, const char *fmt, va_list vl)
 +{
 +}
 +
  int main(int argc, char **argv)
  {
-     OptionsContext o = { 0 };
+     int ret;
      int64_t ti;
  
      atexit(exit_program);
  
-     reset_options(&o, 0);
 +    setvbuf(stderr,NULL,_IONBF,0); /* win32 runtime needs this */
 +
      av_log_set_flags(AV_LOG_SKIP_REPEATED);
      parse_loglevel(argc, argv, options);
  
      av_register_all();
      avformat_network_init();
  
 -    show_banner();
 +    show_banner(argc, argv, options);
 +
 +    term_init();
  
-     parse_cpuflags(argc, argv, options);
-     /* parse options */
-     parse_options(&o, argc, argv, options, opt_output_file);
+     /* parse options and open all input/output files */
 -    ret = avconv_parse_options(argc, argv);
++    ret = ffmpeg_parse_options(argc, argv);
+     if (ret < 0)
+         exit(1);
  
      if (nb_output_files <= 0 && nb_input_files == 0) {
          show_usage();
diff --cc ffmpeg.h
+++ b/ffmpeg.h
@@@ -65,12 -59,16 +65,14 @@@ typedef struct StreamMap 
      char *linklabel;       /* name of an output link, for mapping lavfi outputs */
  } StreamMap;
  
 -/* select an input file for an output file */
 -typedef struct MetadataMap {
 -    int  file;      // file index
 -    char type;      // type of metadata to copy -- (g)lobal, (s)tream, (c)hapter or (p)rogram
 -    int  index;     // stream/chapter/program number
 -} MetadataMap;
 +typedef struct {
 +    int  file_idx,  stream_idx,  channel_idx; // input
 +    int ofile_idx, ostream_idx;               // output
 +} AudioChannelMap;
  
  typedef struct OptionsContext {
+     OptionGroup *g;
      /* input/output options */
      int64_t start_time;
      const char *format;
@@@ -413,4 -363,6 +415,6 @@@ int configure_output_filter(FilterGrap
  int ist_in_filtergraph(FilterGraph *fg, InputStream *ist);
  FilterGraph *init_simple_filtergraph(InputStream *ist, OutputStream *ost);
  
 -int avconv_parse_options(int argc, char **argv);
++int ffmpeg_parse_options(int argc, char **argv);
 -#endif /* AVCONV_H */
 +#endif /* FFMPEG_H */
diff --cc ffmpeg_opt.c
@@@ -83,22 -71,16 +83,21 @@@ int debug_ts          = 0
  int exit_on_error     = 0;
  int print_stats       = 1;
  int qp_hist           = 0;
 +int stdin_interaction = 1;
 +int frame_bits_per_raw_sample = 0;
  
 +
 +static int intra_only         = 0;
  static int file_overwrite     = 0;
 +static int no_file_overwrite  = 0;
  static int video_discard      = 0;
  static int intra_dc_precision = 8;
 -static int using_stdin        = 0;
 +static int do_psnr            = 0;
  static int input_sync;
  
- void reset_options(OptionsContext *o, int is_input)
 -static void uninit_options(OptionsContext *o)
++static void uninit_options(OptionsContext *o, int is_input)
  {
      const OptionDef *po = options;
-     OptionsContext bak= *o;
      int i;
  
      /* all OPT_SPEC and OPT_STRING can be freed in generic way */
      for (i = 0; i < o->nb_stream_maps; i++)
          av_freep(&o->stream_maps[i].linklabel);
      av_freep(&o->stream_maps);
 -    av_freep(&o->meta_data_maps);
 +    av_freep(&o->audio_channel_maps);
      av_freep(&o->streamid_map);
 -static void init_options(OptionsContext *o)
 +
++    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));
  
-     if (is_input) {
 -    o->mux_max_delay  = 0.7;
++    if (!is_input) {
 +        o->recording_time = bak.recording_time;
 +        if (o->recording_time != INT64_MAX)
 +            av_log(NULL, AV_LOG_WARNING,
 +                   "-t is not an input option, keeping it for the next output;"
 +                   " consider fixing your command line.\n");
 +    } else
      o->recording_time = INT64_MAX;
 +    o->mux_max_delay  = 0.7;
      o->limit_filesize = UINT64_MAX;
      o->chapters_input_file = INT_MAX;
-     uninit_opts();
-     init_opts();
  }
  
 -static double parse_frame_aspect_ratio(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);
 +    return AVERROR(EINVAL);
 +}
 +
 +static int opt_pad(void *optctx, const char *opt, const char *arg)
  {
 -    int x = 0, y = 0;
 -    double ar = 0;
 -    const char *p;
 -    char *end;
 +    av_log(NULL, AV_LOG_FATAL, "Option '%s' has been removed, use the pad filter instead\n", opt);
 +    return -1;
 +}
  
 -    p = strchr(arg, ':');
 -    if (p) {
 -        x = strtol(arg, &end, 10);
 -        if (end == p)
 -            y = strtol(end + 1, &end, 10);
 -        if (x > 0 && y > 0)
 -            ar = (double)x / (double)y;
 -    } else
 -        ar = strtod(arg, NULL);
 +static int opt_sameq(void *optctx, const char *opt, const char *arg)
 +{
 +    av_log(NULL, AV_LOG_ERROR, "Option '%s' was removed. "
 +           "If you are looking for an option to preserve the quality (which is not "
 +           "what -%s was for), use -qscale 0 or an equivalent quality factor option.\n",
 +           opt, opt);
 +    return AVERROR(EINVAL);
 +}
  
 -    if (!ar) {
 -        av_log(NULL, AV_LOG_FATAL, "Incorrect aspect ratio specification.\n");
 -        exit(1);
 -    }
 -    return ar;
 +static int opt_video_channel(void *optctx, const char *opt, const char *arg)
 +{
 +    av_log(NULL, AV_LOG_WARNING, "This option is deprecated, use -channel.\n");
 +    return opt_default(optctx, "channel", arg);
 +}
 +
 +static int opt_video_standard(void *optctx, const char *opt, const char *arg)
 +{
 +    av_log(NULL, AV_LOG_WARNING, "This option is deprecated, use -standard.\n");
 +    return opt_default(optctx, "standard", arg);
  }
  
  static int opt_audio_codec(void *optctx, const char *opt, const char *arg)
@@@ -567,7 -448,7 +569,7 @@@ static void add_input_streams(OptionsCo
          ist->file_index = nb_input_files;
          ist->discard = 1;
          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, NULL);
++        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;
          MATCH_PER_STREAM_OPT(ts_scale, dbl, ist->ts_scale, ic, st);
@@@ -752,26 -600,16 +753,26 @@@ static int open_input_file(OptionsConte
          }
      }
      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)
-         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,    audio_codec_name, ic, "a");
 +    MATCH_PER_TYPE_OPT(codec_names, str, subtitle_codec_name, ic, "s");
 +
 +    ic->video_codec_id   = video_codec_name ?
 +        find_codec_or_die(video_codec_name   , AVMEDIA_TYPE_VIDEO   , 0)->id : AV_CODEC_ID_NONE;
 +    ic->audio_codec_id   = audio_codec_name ?
 +        find_codec_or_die(audio_codec_name   , AVMEDIA_TYPE_AUDIO   , 0)->id : AV_CODEC_ID_NONE;
 +    ic->subtitle_codec_id= subtitle_codec_name ?
 +        find_codec_or_die(subtitle_codec_name, AVMEDIA_TYPE_SUBTITLE, 0)->id : AV_CODEC_ID_NONE;
      ic->flags |= AVFMT_FLAG_NONBLOCK;
      ic->interrupt_callback = int_cb;
  
 -    /* open the input file with generic libav 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) {
          print_error(filename, err);
          exit(1);
@@@ -1008,17 -842,9 +1008,17 @@@ static OutputStream *new_output_stream(
      if (oc->oformat->flags & AVFMT_GLOBALHEADER)
          st->codec->flags |= CODEC_FLAG_GLOBAL_HEADER;
  
-     av_opt_get_int(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   (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_int(o->g->sws_opts, "sws_flags", 0, &ost->sws_flags);
++    av_opt_get_int   (o->g->swr_opts, "filter_type"  , 0, &ost->swr_filter_type);
++    av_opt_get_int   (o->g->swr_opts, "dither_method", 0, &ost->swr_dither_method);
++    av_opt_get_double(o->g->swr_opts, "dither_scale" , 0, &ost->swr_dither_scale);
  
 -    ost->pix_fmts[0] = ost->pix_fmts[1] = AV_PIX_FMT_NONE;
 +    ost->source_index = source_index;
 +    if (source_index >= 0) {
 +        ost->sync_ist = input_streams[source_index];
 +        input_streams[source_index]->discard = 0;
 +        input_streams[source_index]->st->discard = AVDISCARD_NONE;
 +    }
  
      return ost;
  }
@@@ -1614,18 -1326,6 +1613,18 @@@ loop_end
          }
      }
  
-             && (e = av_dict_get(codec_opts, "flags", NULL, AV_DICT_IGNORE_SUFFIX))
 +
 +    for (i = nb_output_streams - oc->nb_streams; i < nb_output_streams; i++) { //for all streams of this output file
 +        AVDictionaryEntry *e;
 +        ost = output_streams[i];
 +
 +        if (   ost->stream_copy
++            && (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)))
 +            if (av_opt_set(ost->st->codec, "flags", e->value, 0) < 0)
 +                exit(1);
 +    }
 +
      /* handle attached files */
      for (i = 0; i < o->nb_attachments; i++) {
          AVIOContext *pb;
@@@ -1853,22 -1551,22 +1852,23 @@@ static int opt_target(void *optctx, con
          opt_video_codec(o, "c:v", "mpeg1video");
          opt_audio_codec(o, "c:a", "mp2");
          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, "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");
 -        opt_default(NULL, "b", "1150000");
--        opt_default(NULL, "maxrate", "1150000");
--        opt_default(NULL, "minrate", "1150000");
--        opt_default(NULL, "bufsize", "327680"); // 40*1024*8;
++        av_dict_set(&o->g->codec_opts, "b:v", "1150000", 0);
++        av_dict_set(&o->g->codec_opts, "maxrate", "1150000", 0);
++        av_dict_set(&o->g->codec_opts, "minrate", "1150000", 0);
++        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, "ac", "2", options);
  
--        opt_default(NULL, "packetsize", "2324");
--        opt_default(NULL, "muxrate", "1411200"); // 2352 * 75 * 8;
++        av_dict_set(&o->g->format_opts, "packetsize", "2324", 0);
++        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.
             SCR starts at 36000, but the first two packs contain only padding
  
          parse_option(o, "s", norm == PAL ? "480x576" : "480x480", options);
          parse_option(o, "r", frame_rates[norm], options);
 -        opt_default(NULL, "g", norm == PAL ? "15" : "18");
 -
 -        opt_default(NULL, "b", "2040000");
 -        opt_default(NULL, "maxrate", "2516000");
 -        opt_default(NULL, "minrate", "0"); // 1145000;
 -        opt_default(NULL, "bufsize", "1835008"); // 224*1024*8;
 -        opt_default(NULL, "flags", "+scan_offset");
 +        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");
-         opt_default(NULL, "maxrate", "2516000");
-         opt_default(NULL, "minrate", "0"); // 1145000;
-         opt_default(NULL, "bufsize", "1835008"); // 224*1024*8;
-         opt_default(NULL, "scan_offset", "1");
++        av_dict_set(&o->g->codec_opts, "b:v", "2040000", 0);
++        av_dict_set(&o->g->codec_opts, "maxrate", "2516000", 0);
++        av_dict_set(&o->g->codec_opts, "minrate", "0", 0); // 1145000;
++        av_dict_set(&o->g->codec_opts, "bufsize", "1835008", 0); // 224*1024*8;
++        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);
  
--        opt_default(NULL, "packetsize", "2324");
++        av_dict_set(&o->g->format_opts, "packetsize", "2324", 0);
  
      } else if (!strcmp(arg, "dvd")) {
  
  
          parse_option(o, "s", norm == PAL ? "720x576" : "720x480", options);
          parse_option(o, "r", frame_rates[norm], options);
 -        opt_default(NULL, "g", norm == PAL ? "15" : "18");
 +        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");
 -        opt_default(NULL, "b", "6000000");
--        opt_default(NULL, "maxrate", "9000000");
--        opt_default(NULL, "minrate", "0"); // 1500000;
--        opt_default(NULL, "bufsize", "1835008"); // 224*1024*8;
++        av_dict_set(&o->g->codec_opts, "b:v", "6000000", 0);
++        av_dict_set(&o->g->codec_opts, "maxrate", "9000000", 0);
++        av_dict_set(&o->g->codec_opts, "minrate", "0", 0); // 1500000;
++        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.
--        opt_default(NULL, "muxrate", "10080000"); // from mplex project: data_rate = 1260000. mux_rate = data_rate * 8
++        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.
++        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);
  
      } else if (!strncmp(arg, "dv", 2)) {
@@@ -1975,97 -1672,22 +1975,120 @@@ static int opt_data_frames(void *optctx
      return parse_option(o, "frames:d", arg, options);
  }
  
 -static int opt_video_tag(void *optctx, const char *opt, const char *arg)
++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)
  {
      OptionsContext *o = optctx;
 -    return parse_option(o, "tag:v", arg, options);
 +    FILE *f=NULL;
 +    char filename[1000], line[1000], tmp_line[1000];
 +    const char *codec_name = NULL;
 +
 +    tmp_line[0] = *opt;
 +    tmp_line[1] = 0;
 +    MATCH_PER_TYPE_OPT(codec_names, str, codec_name, NULL, tmp_line);
 +
 +    if (!(f = get_preset_file(filename, sizeof(filename), arg, *opt == 'f', codec_name))) {
 +        if(!strncmp(arg, "libx264-lossless", strlen("libx264-lossless"))){
 +            av_log(NULL, AV_LOG_FATAL, "Please use -preset <speed> -qp 0\n");
 +        }else
 +            av_log(NULL, AV_LOG_FATAL, "File for preset '%s' not found\n", arg);
 +        exit(1);
- }
++    }
 +
 +    while (fgets(line, sizeof(line), f)) {
 +        char *key = tmp_line, *value, *endptr;
 +
 +        if (strcspn(line, "#\n\r") == 0)
 +            continue;
 +        strcpy(tmp_line, line);
 +        if (!av_strtok(key,   "=",    &value) ||
 +            !av_strtok(value, "\r\n", &endptr)) {
 +            av_log(NULL, AV_LOG_FATAL, "%s: Invalid syntax: '%s'\n", filename, line);
 +            exit(1);
 +        }
 +        av_log(NULL, AV_LOG_DEBUG, "ffpreset[%s]: set '%s' = '%s'\n", filename, key, value);
 +
 +        if      (!strcmp(key, "acodec")) opt_audio_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, "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",
 +                   filename, line, key, value);
 +            exit(1);
 +        }
 +    }
 +
 +    fclose(f);
 +
 +    return 0;
  }
  
 -static int opt_audio_tag(void *optctx, const char *opt, const char *arg)
 +static int opt_old2new(void *optctx, const char *opt, const char *arg)
  {
      OptionsContext *o = optctx;
 -    return parse_option(o, "tag:a", arg, options);
 +    char *s = av_asprintf("%s:%c", opt + 1, *opt);
 +    int ret = parse_option(o, s, arg, options);
 +    av_free(s);
 +    return ret;
  }
  
 -static int opt_subtitle_tag(void *optctx, const char *opt, const char *arg)
 +static int opt_bitrate(void *optctx, const char *opt, const char *arg)
  {
      OptionsContext *o = optctx;
 -    return parse_option(o, "tag:s", arg, options);
 +    if(!strcmp(opt, "b")){
 +        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)
 +{
 +    OptionsContext *o = optctx;
 +    char *s;
 +    int ret;
 +    if(!strcmp(opt, "qscale")){
 +        av_log(NULL, AV_LOG_WARNING, "Please use -q:a or -q:v, -qscale is ambiguous\n");
 +        return parse_option(o, "q:v", arg, options);
 +    }
 +    s = av_asprintf("q%s", opt + 6);
 +    ret = parse_option(o, s, arg, options);
 +    av_free(s);
 +    return ret;
 +}
 +
 +static int opt_profile(void *optctx, const char *opt, const char *arg)
 +{
 +    OptionsContext *o = optctx;
 +    if(!strcmp(opt, "profile")){
 +        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)
@@@ -2099,15 -1720,15 +2122,15 @@@ static int opt_deinterlace(void *optctx
      return 0;
  }
  
 -int opt_cpuflags(void *optctx, const char *opt, const char *arg)
 +static int opt_timecode(void *optctx, const char *opt, const char *arg)
  {
 -    int flags = av_parse_cpu_flags(arg);
 -
 -    if (flags < 0)
 -        return flags;
 -
 -    av_set_cpu_flags_mask(flags);
 +    OptionsContext *o = optctx;
 +    char *tcr = av_asprintf("timecode=%s", arg);
 +    int ret = parse_option(o, "metadata:g", tcr, options);
 +    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);
-     return ret;
+     return 0;
  }
  
  static int opt_channel_layout(void *optctx, const char *opt, const char *arg)
@@@ -2230,41 -1849,108 +2253,127 @@@ void show_help_default(const char *opt
  
  void show_usage(void)
  {
 -    printf("Hyper fast Audio and Video encoder\n");
 -    printf("usage: %s [options] [[infile options] -i infile]... {[outfile options] outfile}...\n", program_name);
 -    printf("\n");
 +    av_log(NULL, AV_LOG_INFO, "Hyper fast Audio and Video encoder\n");
 +    av_log(NULL, AV_LOG_INFO, "usage: %s [options] [[infile options] -i infile]... {[outfile options] outfile}...\n", program_name);
 +    av_log(NULL, AV_LOG_INFO, "\n");
  }
  
 -        init_options(&o);
+ 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;
 -        uninit_options(&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);
 -int avconv_parse_options(int argc, char **argv)
++        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)
 +{
 +    AVIOContext *avio = NULL;
 +    int ret;
 +
 +    if (!strcmp(arg, "-"))
 +        arg = "pipe:";
 +    ret = avio_open2(&avio, arg, AVIO_FLAG_WRITE, &int_cb, NULL);
 +    if (ret < 0) {
 +        av_log(NULL, AV_LOG_ERROR, "Failed to open progress URL \"%s\": %s\n",
 +               arg, av_err2str(ret));
 +        return ret;
 +    }
 +    progress_avio = avio;
 +    return 0;
 +}
 +
  #define OFFSET(x) offsetof(OptionsContext, x)
  const OptionDef options[] = {
      /* main options */
  #include "cmdutils_common_opts.h"
      { "f",              HAS_ARG | OPT_STRING | OPT_OFFSET,           { .off       = OFFSET(format) },
          "force format", "fmt" },
-     { "i",              HAS_ARG | OPT_PERFILE,                       { .func_arg = opt_input_file },
-         "input file name", "filename" },
      { "y",              OPT_BOOL,                                    {              &file_overwrite },
          "overwrite output files" },
 +    { "n",              OPT_BOOL,                                    {              &no_file_overwrite },
 +        "do not overwrite output files" },
      { "c",              HAS_ARG | OPT_STRING | OPT_SPEC,             { .off       = OFFSET(codec_names) },
          "codec name", "codec" },
      { "codec",          HAS_ARG | OPT_STRING | OPT_SPEC,             { .off       = OFFSET(codec_names) },
      /* data codec support */
      { "dcodec", HAS_ARG | OPT_DATA | OPT_PERFILE | OPT_EXPERT, { .func_arg = opt_data_codec },
          "force data codec ('copy' to copy stream)", "codec" },
 +    { "dn", OPT_BOOL | OPT_VIDEO | OPT_OFFSET, { .off = OFFSET(data_disable) },
 +        "disable data" },
  
-     { "default", HAS_ARG | OPT_AUDIO | OPT_VIDEO | OPT_EXPERT, { .func_arg = opt_default },
-         "generic catch all option", "" },
      { NULL, },
  };