ffmpeg_opt.c
f5e66827
 /*
11a1033c
  * ffmpeg option parsing
f5e66827
  *
11a1033c
  * This file is part of FFmpeg.
f5e66827
  *
11a1033c
  * FFmpeg is free software; you can redistribute it and/or
f5e66827
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation; either
  * version 2.1 of the License, or (at your option) any later version.
  *
11a1033c
  * FFmpeg is distributed in the hope that it will be useful,
f5e66827
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * Lesser General Public License for more details.
  *
  * You should have received a copy of the GNU Lesser General Public
11a1033c
  * License along with FFmpeg; if not, write to the Free Software
f5e66827
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
 #include <stdint.h>
 
11a1033c
 #include "ffmpeg.h"
f5e66827
 #include "cmdutils.h"
 
 #include "libavformat/avformat.h"
 
 #include "libavcodec/avcodec.h"
 
 #include "libavfilter/avfilter.h"
 
 #include "libavutil/avassert.h"
 #include "libavutil/avstring.h"
 #include "libavutil/avutil.h"
a903f8f0
 #include "libavutil/channel_layout.h"
f5e66827
 #include "libavutil/intreadwrite.h"
 #include "libavutil/fifo.h"
 #include "libavutil/mathematics.h"
 #include "libavutil/opt.h"
 #include "libavutil/parseutils.h"
 #include "libavutil/pixdesc.h"
 #include "libavutil/pixfmt.h"
 
 #define MATCH_PER_STREAM_OPT(name, type, outvar, fmtctx, st)\
 {\
     int i, ret;\
     for (i = 0; i < o->nb_ ## name; i++) {\
         char *spec = o->name[i].specifier;\
         if ((ret = check_stream_specifier(fmtctx, st, spec)) > 0)\
             outvar = o->name[i].u.type;\
         else if (ret < 0)\
eeddeb65
             exit_program(1);\
f5e66827
     }\
 }
 
bad953bc
 #define MATCH_PER_TYPE_OPT(name, type, outvar, fmtctx, mediatype)\
 {\
eb949544
     int i;\
bad953bc
     for (i = 0; i < o->nb_ ## name; i++) {\
         char *spec = o->name[i].specifier;\
a4271f3d
         if (!strcmp(spec, mediatype))\
bad953bc
             outvar = o->name[i].u.type;\
     }\
 }
62e10c37
 
07fd0a22
 const HWAccel hwaccels[] = {
7671dd7c
 #if HAVE_VDPAU_X11
     { "vdpau", vdpau_init, HWACCEL_VDPAU, AV_PIX_FMT_VDPAU },
 #endif
07fd0a22
     { 0 },
 };
 
f5e66827
 char *vstats_filename;
 
 float audio_drift_threshold = 0.1;
 float dts_delta_threshold   = 10;
11a1033c
 float dts_error_threshold   = 3600*30;
f5e66827
 
 int audio_volume      = 256;
 int audio_sync_method = 0;
 int video_sync_method = VSYNC_AUTO;
 int do_deinterlace    = 0;
 int do_benchmark      = 0;
11a1033c
 int do_benchmark_all  = 0;
f5e66827
 int do_hex_dump       = 0;
 int do_pkt_dump       = 0;
 int copy_ts           = 0;
11a1033c
 int copy_tb           = -1;
 int debug_ts          = 0;
f5e66827
 int exit_on_error     = 0;
9af8179c
 int print_stats       = -1;
f5e66827
 int qp_hist           = 0;
11a1033c
 int stdin_interaction = 1;
 int frame_bits_per_raw_sample = 0;
b6b9c150
 float max_error_rate  = 2.0/3;
f5e66827
 
11a1033c
 
 static int intra_only         = 0;
f5e66827
 static int file_overwrite     = 0;
11a1033c
 static int no_file_overwrite  = 0;
f5e66827
 static int video_discard      = 0;
 static int intra_dc_precision = 8;
11a1033c
 static int do_psnr            = 0;
f5e66827
 static int input_sync;
d1e8d4b0
 static int override_ffserver  = 0;
f5e66827
 
6d77279e
 static void uninit_options(OptionsContext *o)
f5e66827
 {
     const OptionDef *po = options;
     int i;
 
     /* all OPT_SPEC and OPT_STRING can be freed in generic way */
     while (po->name) {
         void *dst = (uint8_t*)o + po->u.off;
 
         if (po->flags & OPT_SPEC) {
             SpecifierOpt **so = dst;
             int i, *count = (int*)(so + 1);
             for (i = 0; i < *count; i++) {
                 av_freep(&(*so)[i].specifier);
                 if (po->flags & OPT_STRING)
                     av_freep(&(*so)[i].u.str);
             }
             av_freep(so);
             *count = 0;
         } else if (po->flags & OPT_OFFSET && po->flags & OPT_STRING)
             av_freep(dst);
         po++;
     }
 
     for (i = 0; i < o->nb_stream_maps; i++)
         av_freep(&o->stream_maps[i].linklabel);
     av_freep(&o->stream_maps);
11a1033c
     av_freep(&o->audio_channel_maps);
f5e66827
     av_freep(&o->streamid_map);
0cecaa9e
     av_freep(&o->attachments);
77bd1bc7
 }
f5e66827
 
6d77279e
 static void init_options(OptionsContext *o)
77bd1bc7
 {
f5e66827
     memset(o, 0, sizeof(*o));
 
2d704468
     o->stop_time = INT64_MAX;
11a1033c
     o->mux_max_delay  = 0.7;
56ee3f9d
     o->start_time     = AV_NOPTS_VALUE;
6d77279e
     o->recording_time = INT64_MAX;
f5e66827
     o->limit_filesize = UINT64_MAX;
     o->chapters_input_file = INT_MAX;
811bd078
     o->accurate_seek  = 1;
f5e66827
 }
 
e7553f4c
 /* return a copy of the input with the stream specifiers removed from the keys */
 static AVDictionary *strip_specifiers(AVDictionary *dict)
 {
     AVDictionaryEntry *e = NULL;
     AVDictionary    *ret = NULL;
 
     while ((e = av_dict_get(dict, "", e, AV_DICT_IGNORE_SUFFIX))) {
         char *p = strchr(e->key, ':');
 
         if (p)
             *p = 0;
         av_dict_set(&ret, e->key, e->value, 0);
         if (p)
             *p = ':';
     }
     return ret;
 }
 
e47ab0b2
 static int opt_sameq(void *optctx, const char *opt, const char *arg)
 {
a6224267
     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);
e47ab0b2
 }
 
98298eb1
 static int opt_video_channel(void *optctx, const char *opt, const char *arg)
11a1033c
 {
     av_log(NULL, AV_LOG_WARNING, "This option is deprecated, use -channel.\n");
98298eb1
     return opt_default(optctx, "channel", arg);
032ba74e
 }
11a1033c
 
98298eb1
 static int opt_video_standard(void *optctx, const char *opt, const char *arg)
11a1033c
 {
     av_log(NULL, AV_LOG_WARNING, "This option is deprecated, use -standard.\n");
98298eb1
     return opt_default(optctx, "standard", arg);
f5e66827
 }
 
d3810c47
 static int opt_audio_codec(void *optctx, const char *opt, const char *arg)
f5e66827
 {
d3810c47
     OptionsContext *o = optctx;
f5e66827
     return parse_option(o, "codec:a", arg, options);
 }
 
d3810c47
 static int opt_video_codec(void *optctx, const char *opt, const char *arg)
f5e66827
 {
d3810c47
     OptionsContext *o = optctx;
f5e66827
     return parse_option(o, "codec:v", arg, options);
 }
 
d3810c47
 static int opt_subtitle_codec(void *optctx, const char *opt, const char *arg)
f5e66827
 {
d3810c47
     OptionsContext *o = optctx;
f5e66827
     return parse_option(o, "codec:s", arg, options);
 }
 
d3810c47
 static int opt_data_codec(void *optctx, const char *opt, const char *arg)
f5e66827
 {
d3810c47
     OptionsContext *o = optctx;
f5e66827
     return parse_option(o, "codec:d", arg, options);
 }
 
d3810c47
 static int opt_map(void *optctx, const char *opt, const char *arg)
f5e66827
 {
d3810c47
     OptionsContext *o = optctx;
f5e66827
     StreamMap *m = NULL;
     int i, negative = 0, file_idx;
11a1033c
     int sync_file_idx = -1, sync_stream_idx = 0;
f5e66827
     char *p, *sync;
     char *map;
 
     if (*arg == '-') {
         negative = 1;
         arg++;
     }
     map = av_strdup(arg);
 
     /* parse sync stream first, just pick first matching stream */
     if (sync = strchr(map, ',')) {
         *sync = 0;
         sync_file_idx = strtol(sync + 1, &sync, 0);
         if (sync_file_idx >= nb_input_files || sync_file_idx < 0) {
             av_log(NULL, AV_LOG_FATAL, "Invalid sync file index: %d.\n", sync_file_idx);
eeddeb65
             exit_program(1);
f5e66827
         }
         if (*sync)
             sync++;
         for (i = 0; i < input_files[sync_file_idx]->nb_streams; i++)
             if (check_stream_specifier(input_files[sync_file_idx]->ctx,
                                        input_files[sync_file_idx]->ctx->streams[i], sync) == 1) {
                 sync_stream_idx = i;
                 break;
             }
         if (i == input_files[sync_file_idx]->nb_streams) {
             av_log(NULL, AV_LOG_FATAL, "Sync stream specification in map %s does not "
                                        "match any streams.\n", arg);
eeddeb65
             exit_program(1);
f5e66827
         }
     }
 
 
     if (map[0] == '[') {
         /* this mapping refers to lavfi output */
         const char *c = map + 1;
10bca661
         GROW_ARRAY(o->stream_maps, o->nb_stream_maps);
f5e66827
         m = &o->stream_maps[o->nb_stream_maps - 1];
         m->linklabel = av_get_token(&c, "]");
         if (!m->linklabel) {
             av_log(NULL, AV_LOG_ERROR, "Invalid output link label: %s.\n", map);
eeddeb65
             exit_program(1);
f5e66827
         }
     } else {
         file_idx = strtol(map, &p, 0);
         if (file_idx >= nb_input_files || file_idx < 0) {
             av_log(NULL, AV_LOG_FATAL, "Invalid input file index: %d.\n", file_idx);
eeddeb65
             exit_program(1);
f5e66827
         }
         if (negative)
             /* disable some already defined maps */
             for (i = 0; i < o->nb_stream_maps; i++) {
                 m = &o->stream_maps[i];
                 if (file_idx == m->file_index &&
                     check_stream_specifier(input_files[m->file_index]->ctx,
                                            input_files[m->file_index]->ctx->streams[m->stream_index],
                                            *p == ':' ? p + 1 : p) > 0)
                     m->disabled = 1;
             }
         else
             for (i = 0; i < input_files[file_idx]->nb_streams; i++) {
                 if (check_stream_specifier(input_files[file_idx]->ctx, input_files[file_idx]->ctx->streams[i],
                             *p == ':' ? p + 1 : p) <= 0)
                     continue;
10bca661
                 GROW_ARRAY(o->stream_maps, o->nb_stream_maps);
f5e66827
                 m = &o->stream_maps[o->nb_stream_maps - 1];
 
                 m->file_index   = file_idx;
                 m->stream_index = i;
 
                 if (sync_file_idx >= 0) {
                     m->sync_file_index   = sync_file_idx;
                     m->sync_stream_index = sync_stream_idx;
                 } else {
                     m->sync_file_index   = file_idx;
                     m->sync_stream_index = i;
                 }
             }
     }
 
     if (!m) {
         av_log(NULL, AV_LOG_FATAL, "Stream map '%s' matches no streams.\n", arg);
eeddeb65
         exit_program(1);
f5e66827
     }
 
     av_freep(&map);
     return 0;
 }
 
d3810c47
 static int opt_attach(void *optctx, const char *opt, const char *arg)
f5e66827
 {
d3810c47
     OptionsContext *o = optctx;
10bca661
     GROW_ARRAY(o->attachments, o->nb_attachments);
f5e66827
     o->attachments[o->nb_attachments - 1] = arg;
     return 0;
 }
 
949938d1
 static int opt_map_channel(void *optctx, const char *opt, const char *arg)
11a1033c
 {
949938d1
     OptionsContext *o = optctx;
11a1033c
     int n;
     AVStream *st;
     AudioChannelMap *m;
 
cb0881c7
     GROW_ARRAY(o->audio_channel_maps, o->nb_audio_channel_maps);
11a1033c
     m = &o->audio_channel_maps[o->nb_audio_channel_maps - 1];
 
     /* muted channel syntax */
     n = sscanf(arg, "%d:%d.%d", &m->channel_idx, &m->ofile_idx, &m->ostream_idx);
     if ((n == 1 || n == 3) && m->channel_idx == -1) {
         m->file_idx = m->stream_idx = -1;
         if (n == 1)
             m->ofile_idx = m->ostream_idx = -1;
         return 0;
     }
 
     /* normal syntax */
     n = sscanf(arg, "%d.%d.%d:%d.%d",
                &m->file_idx,  &m->stream_idx, &m->channel_idx,
                &m->ofile_idx, &m->ostream_idx);
 
     if (n != 3 && n != 5) {
         av_log(NULL, AV_LOG_FATAL, "Syntax error, mapchan usage: "
                "[file.stream.channel|-1][:syncfile:syncstream]\n");
eeddeb65
         exit_program(1);
11a1033c
     }
 
     if (n != 5) // only file.stream.channel specified
         m->ofile_idx = m->ostream_idx = -1;
 
     /* check input */
     if (m->file_idx < 0 || m->file_idx >= nb_input_files) {
         av_log(NULL, AV_LOG_FATAL, "mapchan: invalid input file index: %d\n",
                m->file_idx);
eeddeb65
         exit_program(1);
11a1033c
     }
     if (m->stream_idx < 0 ||
         m->stream_idx >= input_files[m->file_idx]->nb_streams) {
         av_log(NULL, AV_LOG_FATAL, "mapchan: invalid input file stream index #%d.%d\n",
                m->file_idx, m->stream_idx);
eeddeb65
         exit_program(1);
11a1033c
     }
     st = input_files[m->file_idx]->ctx->streams[m->stream_idx];
     if (st->codec->codec_type != AVMEDIA_TYPE_AUDIO) {
         av_log(NULL, AV_LOG_FATAL, "mapchan: stream #%d.%d is not an audio stream.\n",
                m->file_idx, m->stream_idx);
eeddeb65
         exit_program(1);
11a1033c
     }
     if (m->channel_idx < 0 || m->channel_idx >= st->codec->channels) {
         av_log(NULL, AV_LOG_FATAL, "mapchan: invalid audio channel #%d.%d.%d\n",
                m->file_idx, m->stream_idx, m->channel_idx);
eeddeb65
         exit_program(1);
11a1033c
     }
     return 0;
 }
 
f5e66827
 /**
c1ef30a6
  * Parse a metadata specifier passed as 'arg' parameter.
02e42751
  * @param arg  metadata string to parse
f5e66827
  * @param type metadata type is written here -- g(lobal)/s(tream)/c(hapter)/p(rogram)
  * @param index for type c/p, chapter/program index is written here
  * @param stream_spec for type s, the stream specifier is written here
  */
 static void parse_meta_type(char *arg, char *type, int *index, const char **stream_spec)
 {
     if (*arg) {
         *type = *arg;
         switch (*arg) {
         case 'g':
             break;
         case 's':
             if (*(++arg) && *arg != ':') {
                 av_log(NULL, AV_LOG_FATAL, "Invalid metadata specifier %s.\n", arg);
eeddeb65
                 exit_program(1);
f5e66827
             }
             *stream_spec = *arg == ':' ? arg + 1 : "";
             break;
         case 'c':
         case 'p':
             if (*(++arg) == ':')
                 *index = strtol(++arg, NULL, 0);
             break;
         default:
             av_log(NULL, AV_LOG_FATAL, "Invalid metadata type %c.\n", *arg);
eeddeb65
             exit_program(1);
f5e66827
         }
     } else
         *type = 'g';
 }
 
 static int copy_metadata(char *outspec, char *inspec, AVFormatContext *oc, AVFormatContext *ic, OptionsContext *o)
 {
     AVDictionary **meta_in = NULL;
11a1033c
     AVDictionary **meta_out = NULL;
f5e66827
     int i, ret = 0;
     char type_in, type_out;
     const char *istream_spec = NULL, *ostream_spec = NULL;
     int idx_in = 0, idx_out = 0;
 
     parse_meta_type(inspec,  &type_in,  &idx_in,  &istream_spec);
     parse_meta_type(outspec, &type_out, &idx_out, &ostream_spec);
 
11a1033c
     if (!ic) {
         if (type_out == 'g' || !*outspec)
             o->metadata_global_manual = 1;
         if (type_out == 's' || !*outspec)
             o->metadata_streams_manual = 1;
         if (type_out == 'c' || !*outspec)
             o->metadata_chapters_manual = 1;
         return 0;
     }
 
f5e66827
     if (type_in == 'g' || type_out == 'g')
         o->metadata_global_manual = 1;
     if (type_in == 's' || type_out == 's')
         o->metadata_streams_manual = 1;
     if (type_in == 'c' || type_out == 'c')
         o->metadata_chapters_manual = 1;
 
a119c64e
     /* ic is NULL when just disabling automatic mappings */
     if (!ic)
         return 0;
 
f5e66827
 #define METADATA_CHECK_INDEX(index, nb_elems, desc)\
     if ((index) < 0 || (index) >= (nb_elems)) {\
         av_log(NULL, AV_LOG_FATAL, "Invalid %s index %d while processing metadata maps.\n",\
                 (desc), (index));\
eeddeb65
         exit_program(1);\
f5e66827
     }
 
 #define SET_DICT(type, meta, context, index)\
         switch (type) {\
         case 'g':\
             meta = &context->metadata;\
             break;\
         case 'c':\
             METADATA_CHECK_INDEX(index, context->nb_chapters, "chapter")\
             meta = &context->chapters[index]->metadata;\
             break;\
         case 'p':\
             METADATA_CHECK_INDEX(index, context->nb_programs, "program")\
             meta = &context->programs[index]->metadata;\
             break;\
469f8b1d
         case 's':\
4632abc7
             break; /* handled separately below */ \
f5e66827
         default: av_assert0(0);\
         }\
 
     SET_DICT(type_in, meta_in, ic, idx_in);
     SET_DICT(type_out, meta_out, oc, idx_out);
 
     /* for input streams choose first matching stream */
     if (type_in == 's') {
         for (i = 0; i < ic->nb_streams; i++) {
             if ((ret = check_stream_specifier(ic, ic->streams[i], istream_spec)) > 0) {
                 meta_in = &ic->streams[i]->metadata;
                 break;
             } else if (ret < 0)
eeddeb65
                 exit_program(1);
f5e66827
         }
         if (!meta_in) {
             av_log(NULL, AV_LOG_FATAL, "Stream specifier %s does not match  any streams.\n", istream_spec);
eeddeb65
             exit_program(1);
f5e66827
         }
     }
 
     if (type_out == 's') {
         for (i = 0; i < oc->nb_streams; i++) {
             if ((ret = check_stream_specifier(oc, oc->streams[i], ostream_spec)) > 0) {
                 meta_out = &oc->streams[i]->metadata;
                 av_dict_copy(meta_out, *meta_in, AV_DICT_DONT_OVERWRITE);
             } else if (ret < 0)
eeddeb65
                 exit_program(1);
f5e66827
         }
     } else
         av_dict_copy(meta_out, *meta_in, AV_DICT_DONT_OVERWRITE);
 
     return 0;
 }
 
949938d1
 static int opt_recording_timestamp(void *optctx, const char *opt, const char *arg)
11a1033c
 {
949938d1
     OptionsContext *o = optctx;
11a1033c
     char buf[128];
     int64_t recording_timestamp = parse_time_or_die(opt, arg, 0) / 1E6;
     struct tm time = *gmtime((time_t*)&recording_timestamp);
     strftime(buf, sizeof(buf), "creation_time=%FT%T%z", &time);
     parse_option(o, "metadata", buf, options);
 
     av_log(NULL, AV_LOG_WARNING, "%s is deprecated, set the 'creation_time' metadata "
                                  "tag instead.\n", opt);
     return 0;
 }
 
f5e66827
 static AVCodec *find_codec_or_die(const char *name, enum AVMediaType type, int encoder)
 {
db4766ad
     const AVCodecDescriptor *desc;
f5e66827
     const char *codec_string = encoder ? "encoder" : "decoder";
     AVCodec *codec;
 
     codec = encoder ?
         avcodec_find_encoder_by_name(name) :
         avcodec_find_decoder_by_name(name);
db4766ad
 
     if (!codec && (desc = avcodec_descriptor_get_by_name(name))) {
         codec = encoder ? avcodec_find_encoder(desc->id) :
                           avcodec_find_decoder(desc->id);
         if (codec)
             av_log(NULL, AV_LOG_VERBOSE, "Matched %s '%s' for codec '%s'.\n",
                    codec_string, codec->name, desc->name);
     }
 
f5e66827
     if (!codec) {
         av_log(NULL, AV_LOG_FATAL, "Unknown %s '%s'\n", codec_string, name);
eeddeb65
         exit_program(1);
f5e66827
     }
     if (codec->type != type) {
         av_log(NULL, AV_LOG_FATAL, "Invalid %s type '%s'\n", codec_string, name);
eeddeb65
         exit_program(1);
f5e66827
     }
     return codec;
 }
 
 static AVCodec *choose_decoder(OptionsContext *o, AVFormatContext *s, AVStream *st)
 {
     char *codec_name = NULL;
 
     MATCH_PER_STREAM_OPT(codec_names, str, codec_name, s, st);
     if (codec_name) {
         AVCodec *codec = find_codec_or_die(codec_name, st->codec->codec_type, 0);
         st->codec->codec_id = codec->id;
         return codec;
     } else
         return avcodec_find_decoder(st->codec->codec_id);
 }
 
c1ef30a6
 /* Add all the streams from the given input file to the global
  * list of input streams. */
f5e66827
 static void add_input_streams(OptionsContext *o, AVFormatContext *ic)
 {
     int i;
 
     for (i = 0; i < ic->nb_streams; i++) {
         AVStream *st = ic->streams[i];
         AVCodecContext *dec = st->codec;
         InputStream *ist = av_mallocz(sizeof(*ist));
07fd0a22
         char *framerate = NULL, *hwaccel = NULL, *hwaccel_device = NULL;
746dca48
         char *codec_tag = NULL;
         char *next;
f5e66827
 
         if (!ist)
eeddeb65
             exit_program(1);
f5e66827
 
10bca661
         GROW_ARRAY(input_streams, nb_input_streams);
f5e66827
         input_streams[nb_input_streams - 1] = ist;
 
         ist->st = st;
         ist->file_index = nb_input_files;
         ist->discard = 1;
         st->discard  = AVDISCARD_ALL;
 
         ist->ts_scale = 1.0;
         MATCH_PER_STREAM_OPT(ts_scale, dbl, ist->ts_scale, ic, st);
 
11a1033c
         MATCH_PER_STREAM_OPT(codec_tags, str, codec_tag, ic, st);
         if (codec_tag) {
             uint32_t tag = strtol(codec_tag, &next, 0);
             if (*next)
                 tag = AV_RL32(codec_tag);
             st->codec->codec_tag = tag;
         }
 
f5e66827
         ist->dec = choose_decoder(o, ic, st);
e82cb79a
         ist->opts = filter_codec_opts(o->g->codec_opts, ist->st->codec->codec_id, ic, st, ist->dec);
f5e66827
 
3e0b29cc
         ist->reinit_filters = -1;
         MATCH_PER_STREAM_OPT(reinit_filters, i, ist->reinit_filters, ic, st);
 
a9d97e1b
         ist->filter_in_rescale_delta_last = AV_NOPTS_VALUE;
 
f5e66827
         switch (dec->codec_type) {
         case AVMEDIA_TYPE_VIDEO:
11a1033c
             if(!ist->dec)
                 ist->dec = avcodec_find_decoder(dec->codec_id);
4d5d905e
             if (av_codec_get_lowres(dec)) {
11a1033c
                 dec->flags |= CODEC_FLAG_EMU_EDGE;
             }
 
f5e66827
             ist->resample_height  = dec->height;
             ist->resample_width   = dec->width;
             ist->resample_pix_fmt = dec->pix_fmt;
 
             MATCH_PER_STREAM_OPT(frame_rates, str, framerate, ic, st);
             if (framerate && av_parse_video_rate(&ist->framerate,
                                                  framerate) < 0) {
                 av_log(NULL, AV_LOG_ERROR, "Error parsing framerate %s.\n",
                        framerate);
eeddeb65
                 exit_program(1);
f5e66827
             }
 
11a1033c
             ist->top_field_first = -1;
             MATCH_PER_STREAM_OPT(top_field_first, i, ist->top_field_first, ic, st);
 
07fd0a22
             MATCH_PER_STREAM_OPT(hwaccels, str, hwaccel, ic, st);
             if (hwaccel) {
                 if (!strcmp(hwaccel, "none"))
                     ist->hwaccel_id = HWACCEL_NONE;
                 else if (!strcmp(hwaccel, "auto"))
                     ist->hwaccel_id = HWACCEL_AUTO;
                 else {
                     int i;
                     for (i = 0; hwaccels[i].name; i++) {
                         if (!strcmp(hwaccels[i].name, hwaccel)) {
                             ist->hwaccel_id = hwaccels[i].id;
                             break;
                         }
                     }
 
                     if (!ist->hwaccel_id) {
                         av_log(NULL, AV_LOG_FATAL, "Unrecognized hwaccel: %s.\n",
                                hwaccel);
                         av_log(NULL, AV_LOG_FATAL, "Supported hwaccels: ");
                         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);
                     }
                 }
             }
 
             MATCH_PER_STREAM_OPT(hwaccel_devices, str, hwaccel_device, ic, st);
             if (hwaccel_device) {
                 ist->hwaccel_device = av_strdup(hwaccel_device);
                 if (!ist->hwaccel_device)
                     exit_program(1);
             }
c255f0b0
             ist->hwaccel_pix_fmt = AV_PIX_FMT_NONE;
07fd0a22
 
f5e66827
             break;
         case AVMEDIA_TYPE_AUDIO:
fccd8c21
             ist->guess_layout_max = INT_MAX;
             MATCH_PER_STREAM_OPT(guess_layout_max, i, ist->guess_layout_max, ic, st);
f5e66827
             guess_input_channel_layout(ist);
 
             ist->resample_sample_fmt     = dec->sample_fmt;
             ist->resample_sample_rate    = dec->sample_rate;
             ist->resample_channels       = dec->channels;
             ist->resample_channel_layout = dec->channel_layout;
 
             break;
         case AVMEDIA_TYPE_DATA:
cb2bd914
         case AVMEDIA_TYPE_SUBTITLE: {
             char *canvas_size = NULL;
11a1033c
             if(!ist->dec)
                 ist->dec = avcodec_find_decoder(dec->codec_id);
0cad101e
             MATCH_PER_STREAM_OPT(fix_sub_duration, i, ist->fix_sub_duration, ic, st);
cb2bd914
             MATCH_PER_STREAM_OPT(canvas_sizes, str, canvas_size, ic, st);
             if (canvas_size &&
                 av_parse_video_size(&dec->width, &dec->height, canvas_size) < 0) {
                 av_log(NULL, AV_LOG_FATAL, "Invalid canvas size: %s.\n", canvas_size);
eeddeb65
                 exit_program(1);
cb2bd914
             }
11a1033c
             break;
cb2bd914
         }
f5e66827
         case AVMEDIA_TYPE_ATTACHMENT:
         case AVMEDIA_TYPE_UNKNOWN:
             break;
         default:
             abort();
         }
     }
 }
 
 static void assert_file_overwrite(const char *filename)
 {
4f07fcd3
     if (file_overwrite && no_file_overwrite) {
7748dd41
         fprintf(stderr, "Error, both -y and -n supplied. Exiting.\n");
         exit_program(1);
     }
 
2b17c768
     if (!file_overwrite) {
         const char *proto_name = avio_find_protocol_name(filename);
         if (proto_name && !strcmp(proto_name, "file") && avio_check(filename, 0) == 0) {
4f07fcd3
             if (stdin_interaction && !no_file_overwrite) {
f5e66827
                 fprintf(stderr,"File '%s' already exists. Overwrite ? [y/N] ", filename);
                 fflush(stderr);
11a1033c
                 term_exit();
                 signal(SIGINT, SIG_DFL);
f5e66827
                 if (!read_yesno()) {
11a1033c
                     av_log(NULL, AV_LOG_FATAL, "Not overwriting - exiting\n");
eeddeb65
                     exit_program(1);
f5e66827
                 }
11a1033c
                 term_init();
f5e66827
             }
             else {
11a1033c
                 av_log(NULL, AV_LOG_FATAL, "File '%s' already exists. Exiting.\n", filename);
eeddeb65
                 exit_program(1);
f5e66827
             }
         }
     }
 }
 
 static void dump_attachment(AVStream *st, const char *filename)
 {
     int ret;
     AVIOContext *out = NULL;
     AVDictionaryEntry *e;
 
     if (!st->codec->extradata_size) {
         av_log(NULL, AV_LOG_WARNING, "No extradata to dump in stream #%d:%d.\n",
                nb_input_files - 1, st->index);
         return;
     }
     if (!*filename && (e = av_dict_get(st->metadata, "filename", NULL, 0)))
         filename = e->value;
     if (!*filename) {
         av_log(NULL, AV_LOG_FATAL, "No filename specified and no 'filename' tag"
                "in stream #%d:%d.\n", nb_input_files - 1, st->index);
eeddeb65
         exit_program(1);
f5e66827
     }
 
     assert_file_overwrite(filename);
 
     if ((ret = avio_open2(&out, filename, AVIO_FLAG_WRITE, &int_cb, NULL)) < 0) {
         av_log(NULL, AV_LOG_FATAL, "Could not open file %s for writing.\n",
                filename);
eeddeb65
         exit_program(1);
f5e66827
     }
 
     avio_write(out, st->codec->extradata, st->codec->extradata_size);
     avio_flush(out);
     avio_close(out);
 }
 
77bd1bc7
 static int open_input_file(OptionsContext *o, const char *filename)
f5e66827
 {
41d2008b
     InputFile *f;
f5e66827
     AVFormatContext *ic;
     AVInputFormat *file_iformat = NULL;
     int err, i, ret;
     int64_t timestamp;
     uint8_t buf[128];
     AVDictionary **opts;
e7553f4c
     AVDictionary *unused_opts = NULL;
     AVDictionaryEntry *e = NULL;
f5e66827
     int orig_nb_streams;                     // number of streams before avformat_find_stream_info
bad953bc
     char *   video_codec_name = NULL;
     char *   audio_codec_name = NULL;
     char *subtitle_codec_name = NULL;
f5e66827
 
     if (o->format) {
         if (!(file_iformat = av_find_input_format(o->format))) {
             av_log(NULL, AV_LOG_FATAL, "Unknown input format: '%s'\n", o->format);
eeddeb65
             exit_program(1);
f5e66827
         }
     }
 
     if (!strcmp(filename, "-"))
         filename = "pipe:";
 
11a1033c
     stdin_interaction &= strncmp(filename, "pipe:", 5) &&
                          strcmp(filename, "/dev/stdin");
f5e66827
 
     /* get default parameters from command line */
     ic = avformat_alloc_context();
     if (!ic) {
         print_error(filename, AVERROR(ENOMEM));
eeddeb65
         exit_program(1);
f5e66827
     }
     if (o->nb_audio_sample_rate) {
         snprintf(buf, sizeof(buf), "%d", o->audio_sample_rate[o->nb_audio_sample_rate - 1].u.i);
77bd1bc7
         av_dict_set(&o->g->format_opts, "sample_rate", buf, 0);
f5e66827
     }
     if (o->nb_audio_channels) {
         /* because we set audio_channels based on both the "ac" and
          * "channel_layout" options, we need to check that the specified
          * demuxer actually has the "channels" option before setting it */
         if (file_iformat && file_iformat->priv_class &&
             av_opt_find(&file_iformat->priv_class, "channels", NULL, 0,
                         AV_OPT_SEARCH_FAKE_OBJ)) {
             snprintf(buf, sizeof(buf), "%d",
                      o->audio_channels[o->nb_audio_channels - 1].u.i);
77bd1bc7
             av_dict_set(&o->g->format_opts, "channels", buf, 0);
f5e66827
         }
     }
     if (o->nb_frame_rates) {
         /* set the format-level framerate option;
          * this is important for video grabbers, e.g. x11 */
         if (file_iformat && file_iformat->priv_class &&
             av_opt_find(&file_iformat->priv_class, "framerate", NULL, 0,
                         AV_OPT_SEARCH_FAKE_OBJ)) {
77bd1bc7
             av_dict_set(&o->g->format_opts, "framerate",
f5e66827
                         o->frame_rates[o->nb_frame_rates - 1].u.str, 0);
         }
     }
     if (o->nb_frame_sizes) {
77bd1bc7
         av_dict_set(&o->g->format_opts, "video_size", o->frame_sizes[o->nb_frame_sizes - 1].u.str, 0);
f5e66827
     }
     if (o->nb_frame_pix_fmts)
77bd1bc7
         av_dict_set(&o->g->format_opts, "pixel_format", o->frame_pix_fmts[o->nb_frame_pix_fmts - 1].u.str, 0);
f5e66827
 
bad953bc
     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");
 
11a1033c
     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;
64327aab
 
     if (video_codec_name)
         av_format_set_video_codec   (ic, find_codec_or_die(video_codec_name   , AVMEDIA_TYPE_VIDEO   , 0));
     if (audio_codec_name)
         av_format_set_audio_codec   (ic, find_codec_or_die(audio_codec_name   , AVMEDIA_TYPE_AUDIO   , 0));
     if (subtitle_codec_name)
         av_format_set_subtitle_codec(ic, find_codec_or_die(subtitle_codec_name, AVMEDIA_TYPE_SUBTITLE, 0));
 
f5e66827
     ic->flags |= AVFMT_FLAG_NONBLOCK;
     ic->interrupt_callback = int_cb;
 
11a1033c
     /* open the input file with generic avformat function */
77bd1bc7
     err = avformat_open_input(&ic, filename, file_iformat, &o->g->format_opts);
f5e66827
     if (err < 0) {
         print_error(filename, err);
eeddeb65
         exit_program(1);
f5e66827
     }
77bd1bc7
     assert_avoptions(o->g->format_opts);
f5e66827
 
     /* apply forced codec ids */
     for (i = 0; i < ic->nb_streams; i++)
         choose_decoder(o, ic, ic->streams[i]);
 
     /* Set AVCodecContext options for avformat_find_stream_info */
77bd1bc7
     opts = setup_find_stream_info_opts(ic, o->g->codec_opts);
f5e66827
     orig_nb_streams = ic->nb_streams;
 
     /* If not enough info to get the stream parameters, we decode the
        first frames to get it. (used in mpeg case for example) */
     ret = avformat_find_stream_info(ic, opts);
     if (ret < 0) {
         av_log(NULL, AV_LOG_FATAL, "%s: could not find codec parameters\n", filename);
         avformat_close_input(&ic);
eeddeb65
         exit_program(1);
f5e66827
     }
 
56ee3f9d
     timestamp = (o->start_time == AV_NOPTS_VALUE) ? 0 : o->start_time;
f5e66827
     /* add the stream start time */
     if (ic->start_time != AV_NOPTS_VALUE)
         timestamp += ic->start_time;
 
     /* if seeking requested, we execute it */
56ee3f9d
     if (o->start_time != AV_NOPTS_VALUE) {
b684f744
         ret = avformat_seek_file(ic, -1, INT64_MIN, timestamp, timestamp, 0);
f5e66827
         if (ret < 0) {
             av_log(NULL, AV_LOG_WARNING, "%s: could not seek to position %0.3f\n",
                    filename, (double)timestamp / AV_TIME_BASE);
         }
     }
 
     /* update the current parameters so that they match the one of the input stream */
     add_input_streams(o, ic);
 
     /* dump the file content */
     av_dump_format(ic, nb_input_files, filename, 0);
 
10bca661
     GROW_ARRAY(input_files, nb_input_files);
41d2008b
     f = av_mallocz(sizeof(*f));
     if (!f)
eeddeb65
         exit_program(1);
41d2008b
     input_files[nb_input_files - 1] = f;
f5e66827
 
41d2008b
     f->ctx        = ic;
     f->ist_index  = nb_input_streams - ic->nb_streams;
811bd078
     f->start_time = o->start_time;
488a0fa6
     f->recording_time = o->recording_time;
d7ebeba8
     f->input_ts_offset = o->input_ts_offset;
41d2008b
     f->ts_offset  = o->input_ts_offset - (copy_ts ? 0 : timestamp);
     f->nb_streams = ic->nb_streams;
     f->rate_emu   = o->rate_emu;
811bd078
     f->accurate_seek = o->accurate_seek;
f5e66827
 
e7553f4c
     /* check if all codec options have been used */
     unused_opts = strip_specifiers(o->g->codec_opts);
     for (i = f->ist_index; i < nb_input_streams; i++) {
         e = NULL;
         while ((e = av_dict_get(input_streams[i]->opts, "", e,
                                 AV_DICT_IGNORE_SUFFIX)))
             av_dict_set(&unused_opts, e->key, NULL, 0);
     }
 
     e = NULL;
     while ((e = av_dict_get(unused_opts, "", e, AV_DICT_IGNORE_SUFFIX))) {
         const AVClass *class = avcodec_get_class();
         const AVOption *option = av_opt_find(&class, e->key, NULL, 0,
                                              AV_OPT_SEARCH_CHILDREN | AV_OPT_SEARCH_FAKE_OBJ);
8a1714ad
         const AVClass *fclass = avformat_get_class();
         const AVOption *foption = av_opt_find(&fclass, e->key, NULL, 0,
                                              AV_OPT_SEARCH_CHILDREN | AV_OPT_SEARCH_FAKE_OBJ);
         if (!option || foption)
e7553f4c
             continue;
8a1714ad
 
 
e7553f4c
         if (!(option->flags & AV_OPT_FLAG_DECODING_PARAM)) {
             av_log(NULL, AV_LOG_ERROR, "Codec AVOption %s (%s) specified for "
                    "input file #%d (%s) is not a decoding option.\n", e->key,
                    option->help ? option->help : "", nb_input_files - 1,
                    filename);
eeddeb65
             exit_program(1);
e7553f4c
         }
 
         av_log(NULL, AV_LOG_WARNING, "Codec AVOption %s (%s) specified for "
                "input file #%d (%s) has not been used for any stream. The most "
                "likely reason is either wrong type (e.g. a video option with "
                "no video streams) or that it is a private option of some decoder "
                "which was not actually used for any stream.\n", e->key,
                option->help ? option->help : "", nb_input_files - 1, filename);
     }
     av_dict_free(&unused_opts);
 
f5e66827
     for (i = 0; i < o->nb_dump_attachment; i++) {
         int j;
 
         for (j = 0; j < ic->nb_streams; j++) {
             AVStream *st = ic->streams[j];
 
             if (check_stream_specifier(ic, st, o->dump_attachment[i].specifier) == 1)
                 dump_attachment(st, o->dump_attachment[i].u.str);
         }
     }
 
     for (i = 0; i < orig_nb_streams; i++)
         av_dict_free(&opts[i]);
     av_freep(&opts);
 
     return 0;
 }
 
 static uint8_t *get_line(AVIOContext *s)
 {
     AVIOContext *line;
     uint8_t *buf;
     char c;
 
     if (avio_open_dyn_buf(&line) < 0) {
         av_log(NULL, AV_LOG_FATAL, "Could not alloc buffer for reading preset.\n");
eeddeb65
         exit_program(1);
f5e66827
     }
 
     while ((c = avio_r8(s)) && c != '\n')
         avio_w8(line, c);
     avio_w8(line, 0);
     avio_close_dyn_buf(line, &buf);
 
     return buf;
 }
 
 static int get_preset_file_2(const char *preset_name, const char *codec_name, AVIOContext **s)
 {
774239be
     int i, ret = -1;
f5e66827
     char filename[1000];
     const char *base[3] = { getenv("AVCONV_DATADIR"),
                             getenv("HOME"),
                             AVCONV_DATADIR,
                             };
 
774239be
     for (i = 0; i < FF_ARRAY_ELEMS(base) && ret < 0; i++) {
f5e66827
         if (!base[i])
             continue;
         if (codec_name) {
             snprintf(filename, sizeof(filename), "%s%s/%s-%s.avpreset", base[i],
                      i != 1 ? "" : "/.avconv", codec_name, preset_name);
             ret = avio_open2(s, filename, AVIO_FLAG_READ, &int_cb, NULL);
         }
774239be
         if (ret < 0) {
f5e66827
             snprintf(filename, sizeof(filename), "%s%s/%s.avpreset", base[i],
                      i != 1 ? "" : "/.avconv", preset_name);
             ret = avio_open2(s, filename, AVIO_FLAG_READ, &int_cb, NULL);
         }
     }
     return ret;
 }
 
 static void choose_encoder(OptionsContext *o, AVFormatContext *s, OutputStream *ost)
 {
     char *codec_name = NULL;
 
     MATCH_PER_STREAM_OPT(codec_names, str, codec_name, s, ost->st);
     if (!codec_name) {
         ost->st->codec->codec_id = av_guess_codec(s->oformat, NULL, s->filename,
                                                   NULL, ost->st->codec->codec_type);
         ost->enc = avcodec_find_encoder(ost->st->codec->codec_id);
     } else if (!strcmp(codec_name, "copy"))
         ost->stream_copy = 1;
     else {
         ost->enc = find_codec_or_die(codec_name, ost->st->codec->codec_type, 1);
         ost->st->codec->codec_id = ost->enc->id;
     }
 }
 
11a1033c
 static OutputStream *new_output_stream(OptionsContext *o, AVFormatContext *oc, enum AVMediaType type, int source_index)
f5e66827
 {
     OutputStream *ost;
     AVStream *st = avformat_new_stream(oc, NULL);
     int idx      = oc->nb_streams - 1, ret = 0;
     char *bsf = NULL, *next, *codec_tag = NULL;
     AVBitStreamFilterContext *bsfc, *bsfc_prev = NULL;
     double qscale = -1;
4bcb75cc
     int i;
f5e66827
 
     if (!st) {
         av_log(NULL, AV_LOG_FATAL, "Could not alloc stream.\n");
eeddeb65
         exit_program(1);
f5e66827
     }
 
     if (oc->nb_streams - 1 < o->nb_streamid_map)
         st->id = o->streamid_map[oc->nb_streams - 1];
 
10bca661
     GROW_ARRAY(output_streams, nb_output_streams);
f5e66827
     if (!(ost = av_mallocz(sizeof(*ost))))
eeddeb65
         exit_program(1);
f5e66827
     output_streams[nb_output_streams - 1] = ost;
 
3d624420
     ost->file_index = nb_output_files - 1;
f5e66827
     ost->index      = idx;
     ost->st         = st;
     st->codec->codec_type = type;
     choose_encoder(o, oc, ost);
     if (ost->enc) {
4e61a38a
         AVIOContext *s = NULL;
         char *buf = NULL, *arg = NULL, *preset = NULL;
 
77bd1bc7
         ost->opts  = filter_codec_opts(o->g->codec_opts, ost->enc->id, oc, st, ost->enc);
4e61a38a
 
         MATCH_PER_STREAM_OPT(presets, str, preset, oc, st);
         if (preset && (!(ret = get_preset_file_2(preset, ost->enc->name, &s)))) {
             do  {
                 buf = get_line(s);
                 if (!buf[0] || buf[0] == '#') {
                     av_free(buf);
                     continue;
                 }
                 if (!(arg = strchr(buf, '='))) {
                     av_log(NULL, AV_LOG_FATAL, "Invalid line found in the preset file.\n");
eeddeb65
                     exit_program(1);
4e61a38a
                 }
                 *arg++ = 0;
                 av_dict_set(&ost->opts, buf, arg, AV_DICT_DONT_OVERWRITE);
                 av_free(buf);
             } while (!s->eof_reached);
             avio_close(s);
         }
         if (ret) {
             av_log(NULL, AV_LOG_FATAL,
                    "Preset %s specified for stream %d:%d, but could not be opened.\n",
                    preset, ost->file_index, ost->index);
eeddeb65
             exit_program(1);
4e61a38a
         }
df0229a7
     } else {
         ost->opts = filter_codec_opts(o->g->codec_opts, AV_CODEC_ID_NONE, oc, st, NULL);
f5e66827
     }
 
     avcodec_get_context_defaults3(st->codec, ost->enc);
     st->codec->codec_type = type; // XXX hack, avcodec_get_context_defaults2() sets type to unknown for stream copy
 
     ost->max_frames = INT64_MAX;
     MATCH_PER_STREAM_OPT(max_frames, i64, ost->max_frames, oc, st);
4bcb75cc
     for (i = 0; i<o->nb_max_frames; i++) {
         char *p = o->max_frames[i].specifier;
         if (!*p && type != AVMEDIA_TYPE_VIDEO) {
             av_log(NULL, AV_LOG_WARNING, "Applying unspecific -frames to non video streams, maybe you meant -vframes ?\n");
             break;
         }
     }
f5e66827
 
65f7aee6
     ost->copy_prior_start = -1;
     MATCH_PER_STREAM_OPT(copy_prior_start, i, ost->copy_prior_start, oc ,st);
 
f5e66827
     MATCH_PER_STREAM_OPT(bitstream_filters, str, bsf, oc, st);
     while (bsf) {
         if (next = strchr(bsf, ','))
             *next++ = 0;
         if (!(bsfc = av_bitstream_filter_init(bsf))) {
             av_log(NULL, AV_LOG_FATAL, "Unknown bitstream filter %s\n", bsf);
eeddeb65
             exit_program(1);
f5e66827
         }
         if (bsfc_prev)
             bsfc_prev->next = bsfc;
         else
             ost->bitstream_filters = bsfc;
 
         bsfc_prev = bsfc;
         bsf       = next;
     }
 
     MATCH_PER_STREAM_OPT(codec_tags, str, codec_tag, oc, st);
     if (codec_tag) {
         uint32_t tag = strtol(codec_tag, &next, 0);
         if (*next)
             tag = AV_RL32(codec_tag);
         st->codec->codec_tag = tag;
     }
 
     MATCH_PER_STREAM_OPT(qscale, dbl, qscale, oc, st);
fb722a90
     if (qscale >= 0) {
f5e66827
         st->codec->flags |= CODEC_FLAG_QSCALE;
         st->codec->global_quality = FF_QP2LAMBDA * qscale;
     }
 
     if (oc->oformat->flags & AVFMT_GLOBALHEADER)
         st->codec->flags |= CODEC_FLAG_GLOBAL_HEADER;
 
77bd1bc7
     av_opt_get_int(o->g->sws_opts, "sws_flags", 0, &ost->sws_flags);
ad899522
 
     av_dict_copy(&ost->swr_opts, o->g->swr_opts, 0);
a260c797
     if (ost->enc && av_get_exact_bits_per_sample(ost->enc->id) == 24)
ad899522
         av_dict_set(&ost->swr_opts, "output_sample_bits", "24", 0);
11a1033c
 
5c7db097
     av_dict_copy(&ost->resample_opts, o->g->resample_opts, 0);
 
11a1033c
     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;
     }
76d23f40
     ost->last_mux_dts = AV_NOPTS_VALUE;
f5e66827
 
     return ost;
 }
 
 static void parse_matrix_coeffs(uint16_t *dest, const char *str)
 {
     int i;
     const char *p = str;
     for (i = 0;; i++) {
         dest[i] = atoi(p);
         if (i == 63)
             break;
         p = strchr(p, ',');
         if (!p) {
             av_log(NULL, AV_LOG_FATAL, "Syntax error in matrix \"%s\" at coeff %d\n", str, i);
eeddeb65
             exit_program(1);
f5e66827
         }
         p++;
     }
 }
 
a4208b9b
 /* read file contents into a string */
 static uint8_t *read_file(const char *filename)
 {
     AVIOContext *pb      = NULL;
     AVIOContext *dyn_buf = NULL;
     int ret = avio_open(&pb, filename, AVIO_FLAG_READ);
     uint8_t buf[1024], *str;
 
     if (ret < 0) {
         av_log(NULL, AV_LOG_ERROR, "Error opening file %s.\n", filename);
         return NULL;
     }
 
     ret = avio_open_dyn_buf(&dyn_buf);
     if (ret < 0) {
         avio_closep(&pb);
         return NULL;
     }
     while ((ret = avio_read(pb, buf, sizeof(buf))) > 0)
         avio_write(dyn_buf, buf, ret);
     avio_w8(dyn_buf, 0);
     avio_closep(&pb);
 
     ret = avio_close_dyn_buf(dyn_buf, &str);
     if (ret < 0)
         return NULL;
     return str;
 }
 
 static char *get_ost_filters(OptionsContext *o, AVFormatContext *oc,
                              OutputStream *ost)
 {
     AVStream *st = ost->st;
 
0f8bdfe3
     if (ost->filters_script && ost->filters) {
a4208b9b
         av_log(NULL, AV_LOG_ERROR, "Both -filter and -filter_script set for "
                "output stream #%d:%d.\n", nb_output_files, st->index);
eeddeb65
         exit_program(1);
a4208b9b
     }
 
0f8bdfe3
     if (ost->filters_script)
         return read_file(ost->filters_script);
     else if (ost->filters)
         return av_strdup(ost->filters);
a4208b9b
 
     return av_strdup(st->codec->codec_type == AVMEDIA_TYPE_VIDEO ?
                      "null" : "anull");
 }
 
535d5895
 static void check_streamcopy_filters(OptionsContext *o, AVFormatContext *oc,
                                      const OutputStream *ost, enum AVMediaType type)
 {
0f8bdfe3
     if (ost->filters_script || ost->filters) {
535d5895
         av_log(NULL, AV_LOG_ERROR,
f591ba60
                "%s '%s' was defined for %s output stream %d:%d but codec copy was selected.\n"
535d5895
                "Filtering and streamcopy cannot be used together.\n",
f591ba60
                ost->filters ? "Filtergraph" : "Filtergraph script",
                ost->filters ? ost->filters : ost->filters_script,
                av_get_media_type_string(type), ost->file_index, ost->index);
535d5895
         exit_program(1);
     }
 }
 
11a1033c
 static OutputStream *new_video_stream(OptionsContext *o, AVFormatContext *oc, int source_index)
f5e66827
 {
     AVStream *st;
     OutputStream *ost;
     AVCodecContext *video_enc;
b1cc12d0
     char *frame_rate = NULL, *frame_aspect_ratio = NULL;
f5e66827
 
11a1033c
     ost = new_output_stream(o, oc, AVMEDIA_TYPE_VIDEO, source_index);
f5e66827
     st  = ost->st;
     video_enc = st->codec;
 
11a1033c
     MATCH_PER_STREAM_OPT(frame_rates, str, frame_rate, oc, st);
     if (frame_rate && av_parse_video_rate(&ost->frame_rate, frame_rate) < 0) {
         av_log(NULL, AV_LOG_FATAL, "Invalid framerate value: %s\n", frame_rate);
eeddeb65
         exit_program(1);
11a1033c
     }
 
b1cc12d0
     MATCH_PER_STREAM_OPT(frame_aspect_ratios, str, frame_aspect_ratio, oc, st);
     if (frame_aspect_ratio) {
         AVRational q;
         if (av_parse_ratio(&q, frame_aspect_ratio, 255, 0, NULL) < 0 ||
             q.num <= 0 || q.den <= 0) {
             av_log(NULL, AV_LOG_FATAL, "Invalid aspect ratio: %s\n", frame_aspect_ratio);
eeddeb65
             exit_program(1);
b1cc12d0
         }
         ost->frame_aspect_ratio = q;
     }
 
0f8bdfe3
     MATCH_PER_STREAM_OPT(filter_scripts, str, ost->filters_script, oc, st);
     MATCH_PER_STREAM_OPT(filters,        str, ost->filters,        oc, st);
 
f5e66827
     if (!ost->stream_copy) {
         const char *p = NULL;
11a1033c
         char *frame_size = NULL;
b1cc12d0
         char *frame_pix_fmt = NULL;
f5e66827
         char *intra_matrix = NULL, *inter_matrix = NULL;
3e70c702
         char *chroma_intra_matrix = NULL;
038c0b1e
         int do_pass = 0;
f5e66827
         int i;
 
         MATCH_PER_STREAM_OPT(frame_sizes, str, frame_size, oc, st);
         if (frame_size && av_parse_video_size(&video_enc->width, &video_enc->height, frame_size) < 0) {
             av_log(NULL, AV_LOG_FATAL, "Invalid frame size: %s.\n", frame_size);
eeddeb65
             exit_program(1);
f5e66827
         }
 
11a1033c
         video_enc->bits_per_raw_sample = frame_bits_per_raw_sample;
f5e66827
         MATCH_PER_STREAM_OPT(frame_pix_fmts, str, frame_pix_fmt, oc, st);
11a1033c
         if (frame_pix_fmt && *frame_pix_fmt == '+') {
             ost->keep_pix_fmt = 1;
             if (!*++frame_pix_fmt)
                 frame_pix_fmt = NULL;
         }
716d413c
         if (frame_pix_fmt && (video_enc->pix_fmt = av_get_pix_fmt(frame_pix_fmt)) == AV_PIX_FMT_NONE) {
f5e66827
             av_log(NULL, AV_LOG_FATAL, "Unknown pixel format requested: %s.\n", frame_pix_fmt);
eeddeb65
             exit_program(1);
f5e66827
         }
         st->sample_aspect_ratio = video_enc->sample_aspect_ratio;
 
11a1033c
         if (intra_only)
             video_enc->gop_size = 0;
f5e66827
         MATCH_PER_STREAM_OPT(intra_matrices, str, intra_matrix, oc, st);
         if (intra_matrix) {
             if (!(video_enc->intra_matrix = av_mallocz(sizeof(*video_enc->intra_matrix) * 64))) {
                 av_log(NULL, AV_LOG_FATAL, "Could not allocate memory for intra matrix.\n");
eeddeb65
                 exit_program(1);
f5e66827
             }
             parse_matrix_coeffs(video_enc->intra_matrix, intra_matrix);
         }
3e70c702
         MATCH_PER_STREAM_OPT(chroma_intra_matrices, str, chroma_intra_matrix, oc, st);
         if (chroma_intra_matrix) {
             uint16_t *p = av_mallocz(sizeof(*video_enc->chroma_intra_matrix) * 64);
             if (!p) {
                 av_log(NULL, AV_LOG_FATAL, "Could not allocate memory for intra matrix.\n");
                 exit_program(1);
             }
             av_codec_set_chroma_intra_matrix(video_enc, p);
             parse_matrix_coeffs(p, chroma_intra_matrix);
         }
f5e66827
         MATCH_PER_STREAM_OPT(inter_matrices, str, inter_matrix, oc, st);
         if (inter_matrix) {
             if (!(video_enc->inter_matrix = av_mallocz(sizeof(*video_enc->inter_matrix) * 64))) {
                 av_log(NULL, AV_LOG_FATAL, "Could not allocate memory for inter matrix.\n");
eeddeb65
                 exit_program(1);
f5e66827
             }
             parse_matrix_coeffs(video_enc->inter_matrix, inter_matrix);
         }
 
         MATCH_PER_STREAM_OPT(rc_overrides, str, p, oc, st);
         for (i = 0; p; i++) {
             int start, end, q;
             int e = sscanf(p, "%d,%d,%d", &start, &end, &q);
             if (e != 3) {
                 av_log(NULL, AV_LOG_FATAL, "error parsing rc_override\n");
eeddeb65
                 exit_program(1);
f5e66827
             }
11a1033c
             /* FIXME realloc failure */
f5e66827
             video_enc->rc_override =
                 av_realloc(video_enc->rc_override,
                            sizeof(RcOverride) * (i + 1));
             video_enc->rc_override[i].start_frame = start;
             video_enc->rc_override[i].end_frame   = end;
             if (q > 0) {
                 video_enc->rc_override[i].qscale         = q;
                 video_enc->rc_override[i].quality_factor = 1.0;
             }
             else {
                 video_enc->rc_override[i].qscale         = 0;
                 video_enc->rc_override[i].quality_factor = -q/100.0;
             }
             p = strchr(p, '/');
             if (p) p++;
         }
         video_enc->rc_override_count = i;
         video_enc->intra_dc_precision = intra_dc_precision - 8;
 
11a1033c
         if (do_psnr)
             video_enc->flags|= CODEC_FLAG_PSNR;
 
f5e66827
         /* two pass mode */
038c0b1e
         MATCH_PER_STREAM_OPT(pass, i, do_pass, oc, st);
f5e66827
         if (do_pass) {
11a1033c
             if (do_pass & 1) {
f5e66827
                 video_enc->flags |= CODEC_FLAG_PASS1;
ccf9dd00
                 av_dict_set(&ost->opts, "flags", "+pass1", AV_DICT_APPEND);
11a1033c
             }
             if (do_pass & 2) {
f5e66827
                 video_enc->flags |= CODEC_FLAG_PASS2;
ccf9dd00
                 av_dict_set(&ost->opts, "flags", "+pass2", AV_DICT_APPEND);
f5e66827
             }
         }
 
bbcedade
         MATCH_PER_STREAM_OPT(passlogfiles, str, ost->logfile_prefix, oc, st);
         if (ost->logfile_prefix &&
             !(ost->logfile_prefix = av_strdup(ost->logfile_prefix)))
eeddeb65
             exit_program(1);
bbcedade
 
f5e66827
         MATCH_PER_STREAM_OPT(forced_key_frames, str, ost->forced_keyframes, oc, st);
         if (ost->forced_keyframes)
             ost->forced_keyframes = av_strdup(ost->forced_keyframes);
 
         MATCH_PER_STREAM_OPT(force_fps, i, ost->force_fps, oc, st);
 
         ost->top_field_first = -1;
         MATCH_PER_STREAM_OPT(top_field_first, i, ost->top_field_first, oc, st);
 
a4208b9b
 
         ost->avfilter = get_ost_filters(o, oc, ost);
         if (!ost->avfilter)
eeddeb65
             exit_program(1);
f5e66827
     } else {
         MATCH_PER_STREAM_OPT(copy_initial_nonkeyframes, i, ost->copy_initial_nonkeyframes, oc ,st);
     }
 
535d5895
     if (ost->stream_copy)
         check_streamcopy_filters(o, oc, ost, AVMEDIA_TYPE_VIDEO);
 
f5e66827
     return ost;
 }
 
11a1033c
 static OutputStream *new_audio_stream(OptionsContext *o, AVFormatContext *oc, int source_index)
f5e66827
 {
11a1033c
     int n;
f5e66827
     AVStream *st;
     OutputStream *ost;
     AVCodecContext *audio_enc;
 
11a1033c
     ost = new_output_stream(o, oc, AVMEDIA_TYPE_AUDIO, source_index);
f5e66827
     st  = ost->st;
 
     audio_enc = st->codec;
     audio_enc->codec_type = AVMEDIA_TYPE_AUDIO;
 
0f8bdfe3
     MATCH_PER_STREAM_OPT(filter_scripts, str, ost->filters_script, oc, st);
     MATCH_PER_STREAM_OPT(filters,        str, ost->filters,        oc, st);
 
f5e66827
     if (!ost->stream_copy) {
         char *sample_fmt = NULL;
 
         MATCH_PER_STREAM_OPT(audio_channels, i, audio_enc->channels, oc, st);
 
         MATCH_PER_STREAM_OPT(sample_fmts, str, sample_fmt, oc, st);
         if (sample_fmt &&
             (audio_enc->sample_fmt = av_get_sample_fmt(sample_fmt)) == AV_SAMPLE_FMT_NONE) {
             av_log(NULL, AV_LOG_FATAL, "Invalid sample format '%s'\n", sample_fmt);
eeddeb65
             exit_program(1);
f5e66827
         }
 
         MATCH_PER_STREAM_OPT(audio_sample_rate, i, audio_enc->sample_rate, oc, st);
 
33ff943f
         MATCH_PER_STREAM_OPT(apad, str, ost->apad, oc, st);
         ost->apad = av_strdup(ost->apad);
 
a4208b9b
         ost->avfilter = get_ost_filters(o, oc, ost);
         if (!ost->avfilter)
eeddeb65
             exit_program(1);
11a1033c
 
         /* check for channel mapping for this audio stream */
         for (n = 0; n < o->nb_audio_channel_maps; n++) {
             AudioChannelMap *map = &o->audio_channel_maps[n];
             InputStream *ist = input_streams[ost->source_index];
             if ((map->channel_idx == -1 || (ist->file_index == map->file_idx && ist->st->index == map->stream_idx)) &&
                 (map->ofile_idx   == -1 || ost->file_index == map->ofile_idx) &&
                 (map->ostream_idx == -1 || ost->st->index  == map->ostream_idx)) {
                 if (ost->audio_channels_mapped < FF_ARRAY_ELEMS(ost->audio_channels_map))
                     ost->audio_channels_map[ost->audio_channels_mapped++] = map->channel_idx;
                 else
                     av_log(NULL, AV_LOG_FATAL, "Max channel mapping for output %d.%d reached\n",
                            ost->file_index, ost->st->index);
             }
         }
f5e66827
     }
 
535d5895
     if (ost->stream_copy)
         check_streamcopy_filters(o, oc, ost, AVMEDIA_TYPE_AUDIO);
 
f5e66827
     return ost;
 }
 
11a1033c
 static OutputStream *new_data_stream(OptionsContext *o, AVFormatContext *oc, int source_index)
f5e66827
 {
     OutputStream *ost;
 
11a1033c
     ost = new_output_stream(o, oc, AVMEDIA_TYPE_DATA, source_index);
f5e66827
     if (!ost->stream_copy) {
         av_log(NULL, AV_LOG_FATAL, "Data stream encoding not supported yet (only streamcopy)\n");
eeddeb65
         exit_program(1);
f5e66827
     }
 
     return ost;
 }
 
11a1033c
 static OutputStream *new_attachment_stream(OptionsContext *o, AVFormatContext *oc, int source_index)
f5e66827
 {
11a1033c
     OutputStream *ost = new_output_stream(o, oc, AVMEDIA_TYPE_ATTACHMENT, source_index);
f5e66827
     ost->stream_copy = 1;
3e175a2a
     ost->finished    = 1;
f5e66827
     return ost;
 }
 
11a1033c
 static OutputStream *new_subtitle_stream(OptionsContext *o, AVFormatContext *oc, int source_index)
f5e66827
 {
     AVStream *st;
     OutputStream *ost;
     AVCodecContext *subtitle_enc;
 
11a1033c
     ost = new_output_stream(o, oc, AVMEDIA_TYPE_SUBTITLE, source_index);
f5e66827
     st  = ost->st;
     subtitle_enc = st->codec;
 
     subtitle_enc->codec_type = AVMEDIA_TYPE_SUBTITLE;
 
11a1033c
     MATCH_PER_STREAM_OPT(copy_initial_nonkeyframes, i, ost->copy_initial_nonkeyframes, oc, st);
 
e4f4d99d
     if (!ost->stream_copy) {
         char *frame_size = NULL;
 
         MATCH_PER_STREAM_OPT(frame_sizes, str, frame_size, oc, st);
         if (frame_size && av_parse_video_size(&subtitle_enc->width, &subtitle_enc->height, frame_size) < 0) {
             av_log(NULL, AV_LOG_FATAL, "Invalid frame size: %s.\n", frame_size);
eeddeb65
             exit_program(1);
e4f4d99d
         }
     }
 
f5e66827
     return ost;
 }
 
 /* arg format is "output-stream-index:streamid-value". */
d3810c47
 static int opt_streamid(void *optctx, const char *opt, const char *arg)
f5e66827
 {
d3810c47
     OptionsContext *o = optctx;
f5e66827
     int idx;
     char *p;
     char idx_str[16];
 
     av_strlcpy(idx_str, arg, sizeof(idx_str));
     p = strchr(idx_str, ':');
     if (!p) {
         av_log(NULL, AV_LOG_FATAL,
                "Invalid value '%s' for option '%s', required syntax is 'index:value'\n",
                arg, opt);
eeddeb65
         exit_program(1);
f5e66827
     }
     *p++ = '\0';
11a1033c
     idx = parse_number_or_die(opt, idx_str, OPT_INT, 0, MAX_STREAMS-1);
f5e66827
     o->streamid_map = grow_array(o->streamid_map, sizeof(*o->streamid_map), &o->nb_streamid_map, idx+1);
     o->streamid_map[idx] = parse_number_or_die(opt, p, OPT_INT, 0, INT_MAX);
     return 0;
 }
 
 static int copy_chapters(InputFile *ifile, OutputFile *ofile, int copy_metadata)
 {
     AVFormatContext *is = ifile->ctx;
     AVFormatContext *os = ofile->ctx;
18ff4d20
     AVChapter **tmp;
f5e66827
     int i;
 
50b54776
     tmp = av_realloc_f(os->chapters, is->nb_chapters + os->nb_chapters, sizeof(*os->chapters));
18ff4d20
     if (!tmp)
         return AVERROR(ENOMEM);
     os->chapters = tmp;
 
f5e66827
     for (i = 0; i < is->nb_chapters; i++) {
         AVChapter *in_ch = is->chapters[i], *out_ch;
56ee3f9d
         int64_t start_time = (ofile->start_time == AV_NOPTS_VALUE) ? 0 : ofile->start_time;
         int64_t ts_off   = av_rescale_q(start_time - ifile->ts_offset,
f5e66827
                                        AV_TIME_BASE_Q, in_ch->time_base);
         int64_t rt       = (ofile->recording_time == INT64_MAX) ? INT64_MAX :
                            av_rescale_q(ofile->recording_time, AV_TIME_BASE_Q, in_ch->time_base);
 
 
         if (in_ch->end < ts_off)
             continue;
         if (rt != INT64_MAX && in_ch->start > rt + ts_off)
             break;
 
         out_ch = av_mallocz(sizeof(AVChapter));
         if (!out_ch)
             return AVERROR(ENOMEM);
 
         out_ch->id        = in_ch->id;
         out_ch->time_base = in_ch->time_base;
         out_ch->start     = FFMAX(0,  in_ch->start - ts_off);
         out_ch->end       = FFMIN(rt, in_ch->end   - ts_off);
 
         if (copy_metadata)
             av_dict_copy(&out_ch->metadata, in_ch->metadata, 0);
 
18ff4d20
         os->chapters[os->nb_chapters++] = out_ch;
f5e66827
     }
     return 0;
 }
 
11a1033c
 static int read_ffserver_streams(OptionsContext *o, AVFormatContext *s, const char *filename)
 {
     int i, err;
     AVFormatContext *ic = avformat_alloc_context();
 
     ic->interrupt_callback = int_cb;
     err = avformat_open_input(&ic, filename, NULL, NULL);
     if (err < 0)
         return err;
     /* copy stream format */
     for(i=0;i<ic->nb_streams;i++) {
         AVStream *st;
         OutputStream *ost;
         AVCodec *codec;
         AVCodecContext *avctx;
 
         codec = avcodec_find_encoder(ic->streams[i]->codec->codec_id);
         ost   = new_output_stream(o, s, codec->type, -1);
         st    = ost->st;
         avctx = st->codec;
         ost->enc = codec;
 
         // FIXME: a more elegant solution is needed
         memcpy(st, ic->streams[i], sizeof(AVStream));
         st->cur_dts = 0;
         st->info = av_malloc(sizeof(*st->info));
         memcpy(st->info, ic->streams[i]->info, sizeof(*st->info));
         st->codec= avctx;
         avcodec_copy_context(st->codec, ic->streams[i]->codec);
 
         if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO && !ost->stream_copy)
             choose_sample_fmt(st, codec);
         else if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO && !ost->stream_copy)
             choose_pixel_fmt(st, codec, st->codec->pix_fmt);
     }
 
     avformat_close_input(&ic);
f7c46d25
     return err;
11a1033c
 }
 
f5e66827
 static void init_output_filter(OutputFilter *ofilter, OptionsContext *o,
                                AVFormatContext *oc)
 {
     OutputStream *ost;
 
     switch (avfilter_pad_get_type(ofilter->out_tmp->filter_ctx->output_pads,
                                   ofilter->out_tmp->pad_idx)) {
11a1033c
     case AVMEDIA_TYPE_VIDEO: ost = new_video_stream(o, oc, -1); break;
     case AVMEDIA_TYPE_AUDIO: ost = new_audio_stream(o, oc, -1); break;
f5e66827
     default:
         av_log(NULL, AV_LOG_FATAL, "Only video and audio filters are supported "
                "currently.\n");
eeddeb65
         exit_program(1);
f5e66827
     }
 
     ost->source_index = -1;
     ost->filter       = ofilter;
 
     ofilter->ost      = ost;
 
     if (ost->stream_copy) {
         av_log(NULL, AV_LOG_ERROR, "Streamcopy requested for output stream %d:%d, "
                "which is fed from a complex filtergraph. Filtering and streamcopy "
                "cannot be used together.\n", ost->file_index, ost->index);
eeddeb65
         exit_program(1);
f5e66827
     }
 
0f8bdfe3
     if (ost->avfilter && (ost->filters || ost->filters_script)) {
f591ba60
         const char *opt = ost->filters ? "-vf/-af/-filter" : "-filter_script";
         av_log(NULL, AV_LOG_ERROR,
                "%s '%s' was specified through the %s option "
                "for output stream %d:%d, which is fed from a complex filtergraph.\n"
                "%s and -filter_complex cannot be used together for the same stream.\n",
                ost->filters ? "Filtergraph" : "Filtergraph script",
                ost->filters ? ost->filters : ost->filters_script,
                opt, ost->file_index, ost->index, opt);
         exit_program(1);
535d5895
     }
 
f5e66827
     if (configure_output_filter(ofilter->graph, ofilter, ofilter->out_tmp) < 0) {
         av_log(NULL, AV_LOG_FATAL, "Error configuring filter.\n");
eeddeb65
         exit_program(1);
f5e66827
     }
     avfilter_inout_free(&ofilter->out_tmp);
 }
 
 static int configure_complex_filters(void)
 {
     int i, ret = 0;
 
     for (i = 0; i < nb_filtergraphs; i++)
         if (!filtergraphs[i]->graph &&
             (ret = configure_filtergraph(filtergraphs[i])) < 0)
             return ret;
     return 0;
 }
 
77bd1bc7
 static int open_output_file(OptionsContext *o, const char *filename)
f5e66827
 {
     AVFormatContext *oc;
     int i, j, err;
     AVOutputFormat *file_oformat;
1da54e90
     OutputFile *of;
f5e66827
     OutputStream *ost;
     InputStream  *ist;
e7553f4c
     AVDictionary *unused_opts = NULL;
     AVDictionaryEntry *e = NULL;
f5e66827
 
     if (configure_complex_filters() < 0) {
         av_log(NULL, AV_LOG_FATAL, "Error configuring filters.\n");
eeddeb65
         exit_program(1);
f5e66827
     }
 
1924a61a
     if (o->stop_time != INT64_MAX && o->recording_time != INT64_MAX) {
         o->stop_time = INT64_MAX;
         av_log(NULL, AV_LOG_WARNING, "-t and -to cannot be used together; using -t.\n");
     }
 
     if (o->stop_time != INT64_MAX && o->recording_time == INT64_MAX) {
3fa72de8
         int64_t start_time = o->start_time == AV_NOPTS_VALUE ? 0 : o->start_time;
         if (o->stop_time <= start_time) {
1924a61a
             av_log(NULL, AV_LOG_WARNING, "-to value smaller than -ss; ignoring -to.\n");
             o->stop_time = INT64_MAX;
         } else {
3fa72de8
             o->recording_time = o->stop_time - start_time;
1924a61a
         }
     }
 
3d624420
     GROW_ARRAY(output_files, nb_output_files);
     of = av_mallocz(sizeof(*of));
     if (!of)
eeddeb65
         exit_program(1);
3d624420
     output_files[nb_output_files - 1] = of;
 
     of->ost_index      = nb_output_streams;
     of->recording_time = o->recording_time;
     of->start_time     = o->start_time;
     of->limit_filesize = o->limit_filesize;
     of->shortest       = o->shortest;
     av_dict_copy(&of->opts, o->g->format_opts, 0);
 
f5e66827
     if (!strcmp(filename, "-"))
         filename = "pipe:";
 
11a1033c
     err = avformat_alloc_output_context2(&oc, NULL, o->format, filename);
f5e66827
     if (!oc) {
11a1033c
         print_error(filename, err);
eeddeb65
         exit_program(1);
f5e66827
     }
1924a61a
 
3d624420
     of->ctx = oc;
     if (o->recording_time != INT64_MAX)
         oc->duration = o->recording_time;
f5e66827
 
11a1033c
     file_oformat= oc->oformat;
f5e66827
     oc->interrupt_callback = int_cb;
 
     /* create streams for all unlabeled output pads */
     for (i = 0; i < nb_filtergraphs; i++) {
         FilterGraph *fg = filtergraphs[i];
         for (j = 0; j < fg->nb_outputs; j++) {
             OutputFilter *ofilter = fg->outputs[j];
 
             if (!ofilter->out_tmp || ofilter->out_tmp->name)
                 continue;
 
             switch (avfilter_pad_get_type(ofilter->out_tmp->filter_ctx->output_pads,
                                           ofilter->out_tmp->pad_idx)) {
             case AVMEDIA_TYPE_VIDEO:    o->video_disable    = 1; break;
             case AVMEDIA_TYPE_AUDIO:    o->audio_disable    = 1; break;
             case AVMEDIA_TYPE_SUBTITLE: o->subtitle_disable = 1; break;
             }
             init_output_filter(ofilter, o, oc);
         }
     }
 
d7fbe926
     /* ffserver seeking with date=... needs a date reference */
     if (!strcmp(file_oformat->name, "ffm") &&
         av_strstart(filename, "http:", NULL)) {
         int err = parse_option(o, "metadata", "creation_time=now", options);
         if (err < 0) {
             print_error(filename, err);
             exit_program(1);
         }
     }
 
d1e8d4b0
     if (!strcmp(file_oformat->name, "ffm") && !override_ffserver &&
11a1033c
         av_strstart(filename, "http:", NULL)) {
         int j;
         /* special case for files sent to ffserver: we get the stream
            parameters from ffserver */
         int err = read_ffserver_streams(o, oc, filename);
         if (err < 0) {
             print_error(filename, err);
eeddeb65
             exit_program(1);
11a1033c
         }
         for(j = nb_output_streams - oc->nb_streams; j < nb_output_streams; j++) {
             ost = output_streams[j];
             for (i = 0; i < nb_input_streams; i++) {
                 ist = input_streams[i];
                 if(ist->st->codec->codec_type == ost->st->codec->codec_type){
                     ost->sync_ist= ist;
                     ost->source_index= i;
                     if(ost->st->codec->codec_type == AVMEDIA_TYPE_AUDIO) ost->avfilter = av_strdup("anull");
                     if(ost->st->codec->codec_type == AVMEDIA_TYPE_VIDEO) ost->avfilter = av_strdup("null");
                     ist->discard = 0;
                     ist->st->discard = AVDISCARD_NONE;
                     break;
                 }
             }
             if(!ost->sync_ist){
                 av_log(NULL, AV_LOG_FATAL, "Missing %s stream which is required by this ffm\n", av_get_media_type_string(ost->st->codec->codec_type));
eeddeb65
                 exit_program(1);
11a1033c
             }
f5e66827
         }
11a1033c
     } else if (!o->nb_stream_maps) {
8ccb56ab
         char *subtitle_codec_name = NULL;
11a1033c
         /* pick the "best" stream of each type */
f5e66827
 
         /* video: highest resolution */
588e7226
         if (!o->video_disable && av_guess_codec(oc->oformat, NULL, filename, NULL, AVMEDIA_TYPE_VIDEO) != AV_CODEC_ID_NONE) {
f5e66827
             int area = 0, idx = -1;
22d804b7
             int qcr = avformat_query_codec(oc->oformat, oc->oformat->video_codec, 0);
f5e66827
             for (i = 0; i < nb_input_streams; i++) {
a7b48395
                 int new_area;
f5e66827
                 ist = input_streams[i];
a7b48395
                 new_area = ist->st->codec->width * ist->st->codec->height;
de73ae6b
                 if((qcr!=MKTAG('A', 'P', 'I', 'C')) && (ist->st->disposition & AV_DISPOSITION_ATTACHED_PIC))
                     new_area = 1;
f5e66827
                 if (ist->st->codec->codec_type == AVMEDIA_TYPE_VIDEO &&
a7b48395
                     new_area > area) {
22d804b7
                     if((qcr==MKTAG('A', 'P', 'I', 'C')) && !(ist->st->disposition & AV_DISPOSITION_ATTACHED_PIC))
                         continue;
a7b48395
                     area = new_area;
f5e66827
                     idx = i;
                 }
             }
11a1033c
             if (idx >= 0)
                 new_video_stream(o, oc, idx);
f5e66827
         }
 
         /* audio: most channels */
588e7226
         if (!o->audio_disable && av_guess_codec(oc->oformat, NULL, filename, NULL, AVMEDIA_TYPE_AUDIO) != AV_CODEC_ID_NONE) {
f5e66827
             int channels = 0, idx = -1;
             for (i = 0; i < nb_input_streams; i++) {
                 ist = input_streams[i];
                 if (ist->st->codec->codec_type == AVMEDIA_TYPE_AUDIO &&
                     ist->st->codec->channels > channels) {
                     channels = ist->st->codec->channels;
                     idx = i;
                 }
             }
11a1033c
             if (idx >= 0)
                 new_audio_stream(o, oc, idx);
f5e66827
         }
 
         /* subtitles: pick first */
8ccb56ab
         MATCH_PER_TYPE_OPT(codec_names, str, subtitle_codec_name, oc, "s");
48609236
         if (!o->subtitle_disable && (avcodec_find_encoder(oc->oformat->subtitle_codec) || subtitle_codec_name)) {
f5e66827
             for (i = 0; i < nb_input_streams; i++)
                 if (input_streams[i]->st->codec->codec_type == AVMEDIA_TYPE_SUBTITLE) {
11a1033c
                     new_subtitle_stream(o, oc, i);
f5e66827
                     break;
                 }
         }
         /* do something with data? */
     } else {
         for (i = 0; i < o->nb_stream_maps; i++) {
             StreamMap *map = &o->stream_maps[i];
 
             if (map->disabled)
                 continue;
 
             if (map->linklabel) {
                 FilterGraph *fg;
                 OutputFilter *ofilter = NULL;
                 int j, k;
 
                 for (j = 0; j < nb_filtergraphs; j++) {
                     fg = filtergraphs[j];
                     for (k = 0; k < fg->nb_outputs; k++) {
                         AVFilterInOut *out = fg->outputs[k]->out_tmp;
                         if (out && !strcmp(out->name, map->linklabel)) {
                             ofilter = fg->outputs[k];
                             goto loop_end;
                         }
                     }
                 }
 loop_end:
                 if (!ofilter) {
                     av_log(NULL, AV_LOG_FATAL, "Output with label '%s' does not exist "
10a92775
                            "in any defined filter graph, or was already used elsewhere.\n", map->linklabel);
eeddeb65
                     exit_program(1);
f5e66827
                 }
                 init_output_filter(ofilter, o, oc);
             } else {
449704b4
                 int src_idx = input_files[map->file_index]->ist_index + map->stream_index;
 
f5e66827
                 ist = input_streams[input_files[map->file_index]->ist_index + map->stream_index];
11a1033c
                 if(o->subtitle_disable && ist->st->codec->codec_type == AVMEDIA_TYPE_SUBTITLE)
                     continue;
                 if(o->   audio_disable && ist->st->codec->codec_type == AVMEDIA_TYPE_AUDIO)
                     continue;
                 if(o->   video_disable && ist->st->codec->codec_type == AVMEDIA_TYPE_VIDEO)
                     continue;
                 if(o->    data_disable && ist->st->codec->codec_type == AVMEDIA_TYPE_DATA)
                     continue;
 
f5e66827
                 switch (ist->st->codec->codec_type) {
11a1033c
                 case AVMEDIA_TYPE_VIDEO:      ost = new_video_stream     (o, oc, src_idx); break;
                 case AVMEDIA_TYPE_AUDIO:      ost = new_audio_stream     (o, oc, src_idx); break;
                 case AVMEDIA_TYPE_SUBTITLE:   ost = new_subtitle_stream  (o, oc, src_idx); break;
                 case AVMEDIA_TYPE_DATA:       ost = new_data_stream      (o, oc, src_idx); break;
                 case AVMEDIA_TYPE_ATTACHMENT: ost = new_attachment_stream(o, oc, src_idx); break;
f5e66827
                 default:
                     av_log(NULL, AV_LOG_FATAL, "Cannot map stream #%d:%d - unsupported type.\n",
                            map->file_index, map->stream_index);
eeddeb65
                     exit_program(1);
f5e66827
                 }
             }
         }
     }
 
     /* handle attached files */
     for (i = 0; i < o->nb_attachments; i++) {
         AVIOContext *pb;
         uint8_t *attachment;
         const char *p;
         int64_t len;
 
         if ((err = avio_open2(&pb, o->attachments[i], AVIO_FLAG_READ, &int_cb, NULL)) < 0) {
             av_log(NULL, AV_LOG_FATAL, "Could not open attachment file %s.\n",
                    o->attachments[i]);
eeddeb65
             exit_program(1);
f5e66827
         }
         if ((len = avio_size(pb)) <= 0) {
             av_log(NULL, AV_LOG_FATAL, "Could not get size of the attachment %s.\n",
                    o->attachments[i]);
eeddeb65
             exit_program(1);
f5e66827
         }
         if (!(attachment = av_malloc(len))) {
             av_log(NULL, AV_LOG_FATAL, "Attachment %s too large to fit into memory.\n",
                    o->attachments[i]);
eeddeb65
             exit_program(1);
f5e66827
         }
         avio_read(pb, attachment, len);
 
11a1033c
         ost = new_attachment_stream(o, oc, -1);
f5e66827
         ost->stream_copy               = 0;
         ost->attachment_filename       = o->attachments[i];
69a1667b
         ost->finished                  = 1;
f5e66827
         ost->st->codec->extradata      = attachment;
         ost->st->codec->extradata_size = len;
 
         p = strrchr(o->attachments[i], '/');
         av_dict_set(&ost->st->metadata, "filename", (p && *p) ? p + 1 : o->attachments[i], AV_DICT_DONT_OVERWRITE);
         avio_close(pb);
     }
 
951a03b3
     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];
 
5bab99ba
         if ((ost->stream_copy || ost->attachment_filename)
951a03b3
             && (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)
eeddeb65
                 exit_program(1);
951a03b3
     }
 
e7553f4c
     /* check if all codec options have been used */
     unused_opts = strip_specifiers(o->g->codec_opts);
     for (i = of->ost_index; i < nb_output_streams; i++) {
         e = NULL;
         while ((e = av_dict_get(output_streams[i]->opts, "", e,
                                 AV_DICT_IGNORE_SUFFIX)))
             av_dict_set(&unused_opts, e->key, NULL, 0);
     }
 
     e = NULL;
     while ((e = av_dict_get(unused_opts, "", e, AV_DICT_IGNORE_SUFFIX))) {
         const AVClass *class = avcodec_get_class();
         const AVOption *option = av_opt_find(&class, e->key, NULL, 0,
                                              AV_OPT_SEARCH_CHILDREN | AV_OPT_SEARCH_FAKE_OBJ);
         if (!option)
             continue;
         if (!(option->flags & AV_OPT_FLAG_ENCODING_PARAM)) {
             av_log(NULL, AV_LOG_ERROR, "Codec AVOption %s (%s) specified for "
                    "output file #%d (%s) is not an encoding option.\n", e->key,
                    option->help ? option->help : "", nb_output_files - 1,
                    filename);
eeddeb65
             exit_program(1);
e7553f4c
         }
 
d0a79339
         // gop_timecode is injected by generic code but not always used
         if (!strcmp(e->key, "gop_timecode"))
             continue;
 
e7553f4c
         av_log(NULL, AV_LOG_WARNING, "Codec AVOption %s (%s) specified for "
                "output file #%d (%s) has not been used for any stream. The most "
                "likely reason is either wrong type (e.g. a video option with "
                "no video streams) or that it is a private option of some encoder "
                "which was not actually used for any stream.\n", e->key,
                option->help ? option->help : "", nb_output_files - 1, filename);
     }
     av_dict_free(&unused_opts);
 
f5e66827
     /* check filename in case of an image number is expected */
     if (oc->oformat->flags & AVFMT_NEEDNUMBER) {
         if (!av_filename_number_test(oc->filename)) {
             print_error(oc->filename, AVERROR(EINVAL));
eeddeb65
             exit_program(1);
f5e66827
         }
     }
 
     if (!(oc->oformat->flags & AVFMT_NOFILE)) {
         /* test if it already exists to avoid losing precious files */
         assert_file_overwrite(filename);
 
         /* open the file */
         if ((err = avio_open2(&oc->pb, filename, AVIO_FLAG_WRITE,
                               &oc->interrupt_callback,
1da54e90
                               &of->opts)) < 0) {
f5e66827
             print_error(filename, err);
eeddeb65
             exit_program(1);
f5e66827
         }
e2427f04
     } else if (strcmp(oc->oformat->name, "image2")==0 && !av_filename_number_test(filename))
         assert_file_overwrite(filename);
f5e66827
 
     if (o->mux_preload) {
         uint8_t buf[64];
         snprintf(buf, sizeof(buf), "%d", (int)(o->mux_preload*AV_TIME_BASE));
1da54e90
         av_dict_set(&of->opts, "preload", buf, 0);
f5e66827
     }
     oc->max_delay = (int)(o->mux_max_delay * AV_TIME_BASE);
 
     /* copy metadata */
     for (i = 0; i < o->nb_metadata_map; i++) {
         char *p;
         int in_file_index = strtol(o->metadata_map[i].u.str, &p, 0);
 
         if (in_file_index >= nb_input_files) {
             av_log(NULL, AV_LOG_FATAL, "Invalid input file index %d while processing metadata maps\n", in_file_index);
eeddeb65
             exit_program(1);
f5e66827
         }
a119c64e
         copy_metadata(o->metadata_map[i].specifier, *p ? p + 1 : p, oc,
                       in_file_index >= 0 ?
                       input_files[in_file_index]->ctx : NULL, o);
f5e66827
     }
 
     /* copy chapters */
     if (o->chapters_input_file >= nb_input_files) {
         if (o->chapters_input_file == INT_MAX) {
             /* copy chapters from the first input file that has them*/
             o->chapters_input_file = -1;
             for (i = 0; i < nb_input_files; i++)
                 if (input_files[i]->ctx->nb_chapters) {
                     o->chapters_input_file = i;
                     break;
                 }
         } else {
             av_log(NULL, AV_LOG_FATAL, "Invalid input file index %d in chapter mapping.\n",
                    o->chapters_input_file);
eeddeb65
             exit_program(1);
f5e66827
         }
     }
     if (o->chapters_input_file >= 0)
1da54e90
         copy_chapters(input_files[o->chapters_input_file], of,
f5e66827
                       !o->metadata_chapters_manual);
 
     /* copy global metadata by default */
11a1033c
     if (!o->metadata_global_manual && nb_input_files){
f5e66827
         av_dict_copy(&oc->metadata, input_files[0]->ctx->metadata,
                      AV_DICT_DONT_OVERWRITE);
11a1033c
         if(o->recording_time != INT64_MAX)
             av_dict_set(&oc->metadata, "duration", NULL, 0);
         av_dict_set(&oc->metadata, "creation_time", NULL, 0);
     }
f5e66827
     if (!o->metadata_streams_manual)
1da54e90
         for (i = of->ost_index; i < nb_output_streams; i++) {
f5e66827
             InputStream *ist;
             if (output_streams[i]->source_index < 0)         /* this is true e.g. for attached files */
                 continue;
             ist = input_streams[output_streams[i]->source_index];
             av_dict_copy(&output_streams[i]->st->metadata, ist->st->metadata, AV_DICT_DONT_OVERWRITE);
         }
 
     /* process manually set metadata */
     for (i = 0; i < o->nb_metadata; i++) {
         AVDictionary **m;
         char type, *val;
         const char *stream_spec;
11a1033c
         int index = 0, j, ret = 0;
f5e66827
 
         val = strchr(o->metadata[i].u.str, '=');
         if (!val) {
             av_log(NULL, AV_LOG_FATAL, "No '=' character in metadata string %s.\n",
                    o->metadata[i].u.str);
eeddeb65
             exit_program(1);
f5e66827
         }
         *val++ = 0;
 
         parse_meta_type(o->metadata[i].specifier, &type, &index, &stream_spec);
         if (type == 's') {
             for (j = 0; j < oc->nb_streams; j++) {
                 if ((ret = check_stream_specifier(oc, oc->streams[j], stream_spec)) > 0) {
                     av_dict_set(&oc->streams[j]->metadata, o->metadata[i].u.str, *val ? val : NULL, 0);
                 } else if (ret < 0)
eeddeb65
                     exit_program(1);
f5e66827
             }
         }
         else {
             switch (type) {
             case 'g':
                 m = &oc->metadata;
                 break;
             case 'c':
                 if (index < 0 || index >= oc->nb_chapters) {
                     av_log(NULL, AV_LOG_FATAL, "Invalid chapter index %d in metadata specifier.\n", index);
eeddeb65
                     exit_program(1);
f5e66827
                 }
                 m = &oc->chapters[index]->metadata;
                 break;
             default:
                 av_log(NULL, AV_LOG_FATAL, "Invalid metadata specifier %s.\n", o->metadata[i].specifier);
eeddeb65
                 exit_program(1);
f5e66827
             }
             av_dict_set(m, o->metadata[i].u.str, *val ? val : NULL, 0);
         }
     }
 
77bd1bc7
     return 0;
f5e66827
 }
 
d3810c47
 static int opt_target(void *optctx, const char *opt, const char *arg)
f5e66827
 {
d3810c47
     OptionsContext *o = optctx;
f5e66827
     enum { PAL, NTSC, FILM, UNKNOWN } norm = UNKNOWN;
     static const char *const frame_rates[] = { "25", "30000/1001", "24000/1001" };
 
     if (!strncmp(arg, "pal-", 4)) {
         norm = PAL;
         arg += 4;
     } else if (!strncmp(arg, "ntsc-", 5)) {
         norm = NTSC;
         arg += 5;
     } else if (!strncmp(arg, "film-", 5)) {
         norm = FILM;
         arg += 5;
     } else {
         /* Try to determine PAL/NTSC by peeking in the input files */
         if (nb_input_files) {
             int i, j, fr;
             for (j = 0; j < nb_input_files; j++) {
                 for (i = 0; i < input_files[j]->nb_streams; i++) {
                     AVCodecContext *c = input_files[j]->ctx->streams[i]->codec;
b20a8ad6
                     if (c->codec_type != AVMEDIA_TYPE_VIDEO ||
                         !c->time_base.num)
f5e66827
                         continue;
                     fr = c->time_base.den * 1000 / c->time_base.num;
                     if (fr == 25000) {
                         norm = PAL;
                         break;
                     } else if ((fr == 29970) || (fr == 23976)) {
                         norm = NTSC;
                         break;
                     }
                 }
                 if (norm != UNKNOWN)
                     break;
             }
         }
         if (norm != UNKNOWN)
             av_log(NULL, AV_LOG_INFO, "Assuming %s for target.\n", norm == PAL ? "PAL" : "NTSC");
     }
 
     if (norm == UNKNOWN) {
         av_log(NULL, AV_LOG_FATAL, "Could not determine norm (PAL/NTSC/NTSC-Film) for target.\n");
         av_log(NULL, AV_LOG_FATAL, "Please prefix target with \"pal-\", \"ntsc-\" or \"film-\",\n");
         av_log(NULL, AV_LOG_FATAL, "or set a framerate with \"-r xxx\".\n");
eeddeb65
         exit_program(1);
f5e66827
     }
 
     if (!strcmp(arg, "vcd")) {
         opt_video_codec(o, "c:v", "mpeg1video");
         opt_audio_codec(o, "c:a", "mp2");
         parse_option(o, "f", "vcd", options);
 
         parse_option(o, "s", norm == PAL ? "352x288" : "352x240", options);
         parse_option(o, "r", frame_rates[norm], options);
48111861
         opt_default(NULL, "g", norm == PAL ? "15" : "18");
f5e66827
 
48111861
         opt_default(NULL, "b:v", "1150000");
         opt_default(NULL, "maxrate", "1150000");
         opt_default(NULL, "minrate", "1150000");
         opt_default(NULL, "bufsize", "327680"); // 40*1024*8;
f5e66827
 
48111861
         opt_default(NULL, "b:a", "224000");
f5e66827
         parse_option(o, "ar", "44100", options);
         parse_option(o, "ac", "2", options);
 
48111861
         opt_default(NULL, "packetsize", "2324");
         opt_default(NULL, "muxrate", "1411200"); // 2352 * 75 * 8;
f5e66827
 
         /* 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
            and the first pack from the other stream, respectively, may also have
            been written before.
            So the real data starts at SCR 36000+3*1200. */
         o->mux_preload = (36000 + 3 * 1200) / 90000.0; // 0.44
     } else if (!strcmp(arg, "svcd")) {
 
         opt_video_codec(o, "c:v", "mpeg2video");
         opt_audio_codec(o, "c:a", "mp2");
         parse_option(o, "f", "svcd", options);
 
         parse_option(o, "s", norm == PAL ? "480x576" : "480x480", options);
         parse_option(o, "r", frame_rates[norm], options);
11a1033c
         parse_option(o, "pix_fmt", "yuv420p", options);
48111861
         opt_default(NULL, "g", norm == PAL ? "15" : "18");
f5e66827
 
48111861
         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");
f5e66827
 
48111861
         opt_default(NULL, "b:a", "224000");
f5e66827
         parse_option(o, "ar", "44100", options);
 
48111861
         opt_default(NULL, "packetsize", "2324");
f5e66827
 
     } else if (!strcmp(arg, "dvd")) {
 
         opt_video_codec(o, "c:v", "mpeg2video");
         opt_audio_codec(o, "c:a", "ac3");
         parse_option(o, "f", "dvd", options);
 
         parse_option(o, "s", norm == PAL ? "720x576" : "720x480", options);
         parse_option(o, "r", frame_rates[norm], options);
11a1033c
         parse_option(o, "pix_fmt", "yuv420p", options);
48111861
         opt_default(NULL, "g", norm == PAL ? "15" : "18");
f5e66827
 
48111861
         opt_default(NULL, "b:v", "6000000");
         opt_default(NULL, "maxrate", "9000000");
         opt_default(NULL, "minrate", "0"); // 1500000;
         opt_default(NULL, "bufsize", "1835008"); // 224*1024*8;
f5e66827
 
48111861
         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
f5e66827
 
48111861
         opt_default(NULL, "b:a", "448000");
f5e66827
         parse_option(o, "ar", "48000", options);
 
     } else if (!strncmp(arg, "dv", 2)) {
 
         parse_option(o, "f", "dv", options);
 
         parse_option(o, "s", norm == PAL ? "720x576" : "720x480", options);
         parse_option(o, "pix_fmt", !strncmp(arg, "dv50", 4) ? "yuv422p" :
                           norm == PAL ? "yuv420p" : "yuv411p", options);
         parse_option(o, "r", frame_rates[norm], options);
 
         parse_option(o, "ar", "48000", options);
         parse_option(o, "ac", "2", options);
 
     } else {
         av_log(NULL, AV_LOG_ERROR, "Unknown target: %s\n", arg);
         return AVERROR(EINVAL);
     }
f7395926
 
48111861
     av_dict_copy(&o->g->codec_opts,  codec_opts, AV_DICT_DONT_OVERWRITE);
     av_dict_copy(&o->g->format_opts, format_opts, AV_DICT_DONT_OVERWRITE);
f7395926
 
f5e66827
     return 0;
 }
 
11d957fb
 static int opt_vstats_file(void *optctx, const char *opt, const char *arg)
f5e66827
 {
     av_free (vstats_filename);
     vstats_filename = av_strdup (arg);
     return 0;
 }
 
11d957fb
 static int opt_vstats(void *optctx, const char *opt, const char *arg)
f5e66827
 {
     char filename[40];
     time_t today2 = time(NULL);
     struct tm *today = localtime(&today2);
 
     snprintf(filename, sizeof(filename), "vstats_%02d%02d%02d.log", today->tm_hour, today->tm_min,
              today->tm_sec);
11d957fb
     return opt_vstats_file(NULL, opt, filename);
f5e66827
 }
 
d3810c47
 static int opt_video_frames(void *optctx, const char *opt, const char *arg)
f5e66827
 {
d3810c47
     OptionsContext *o = optctx;
f5e66827
     return parse_option(o, "frames:v", arg, options);
 }
 
d3810c47
 static int opt_audio_frames(void *optctx, const char *opt, const char *arg)
f5e66827
 {
d3810c47
     OptionsContext *o = optctx;
f5e66827
     return parse_option(o, "frames:a", arg, options);
 }
 
d3810c47
 static int opt_data_frames(void *optctx, const char *opt, const char *arg)
f5e66827
 {
d3810c47
     OptionsContext *o = optctx;
f5e66827
     return parse_option(o, "frames:d", arg, options);
 }
 
af4b1c02
 static int opt_default_new(OptionsContext *o, const char *opt, const char *arg)
 {
     int ret;
a46c5657
     AVDictionary *cbak = codec_opts;
     AVDictionary *fbak = format_opts;
af4b1c02
     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;
 }
 
949938d1
 static int opt_preset(void *optctx, const char *opt, const char *arg)
11a1033c
 {
949938d1
     OptionsContext *o = optctx;
11a1033c
     FILE *f=NULL;
     char filename[1000], line[1000], tmp_line[1000];
3db4c88a
     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);
11a1033c
 
     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);
eeddeb65
         exit_program(1);
af4b1c02
     }
11a1033c
 
     while (fgets(line, sizeof(line), f)) {
         char *key = tmp_line, *value, *endptr;
 
         if (strcspn(line, "#\n\r") == 0)
             continue;
bd03afb5
         av_strlcpy(tmp_line, line, sizeof(tmp_line));
11a1033c
         if (!av_strtok(key,   "=",    &value) ||
             !av_strtok(value, "\r\n", &endptr)) {
             av_log(NULL, AV_LOG_FATAL, "%s: Invalid syntax: '%s'\n", filename, line);
eeddeb65
             exit_program(1);
11a1033c
         }
         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);
af4b1c02
         else if (opt_default_new(o, key, value) < 0) {
11a1033c
             av_log(NULL, AV_LOG_FATAL, "%s: Invalid option or argument: '%s', parsed as '%s' = '%s'\n",
                    filename, line, key, value);
eeddeb65
             exit_program(1);
11a1033c
         }
     }
 
     fclose(f);
 
     return 0;
 }
 
949938d1
 static int opt_old2new(void *optctx, const char *opt, const char *arg)
11a1033c
 {
949938d1
     OptionsContext *o = optctx;
11a1033c
     char *s = av_asprintf("%s:%c", opt + 1, *opt);
     int ret = parse_option(o, s, arg, options);
     av_free(s);
     return ret;
f5e66827
 }
 
949938d1
 static int opt_bitrate(void *optctx, const char *opt, const char *arg)
f5e66827
 {
949938d1
     OptionsContext *o = optctx;
11a1033c
     if(!strcmp(opt, "b")){
         av_log(NULL, AV_LOG_WARNING, "Please use -b:a or -b:v, -b is ambiguous\n");
af4b1c02
         av_dict_set(&o->g->codec_opts, "b:v", arg, 0);
         return 0;
11a1033c
     }
af4b1c02
     av_dict_set(&o->g->codec_opts, opt, arg, 0);
     return 0;
f5e66827
 }
 
949938d1
 static int opt_qscale(void *optctx, const char *opt, const char *arg)
f5e66827
 {
949938d1
     OptionsContext *o = optctx;
11a1033c
     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;
 }
 
949938d1
 static int opt_profile(void *optctx, const char *opt, const char *arg)
11a1033c
 {
949938d1
     OptionsContext *o = optctx;
11a1033c
     if(!strcmp(opt, "profile")){
         av_log(NULL, AV_LOG_WARNING, "Please use -profile:a or -profile:v, -profile is ambiguous\n");
af4b1c02
         av_dict_set(&o->g->codec_opts, "profile:v", arg, 0);
         return 0;
11a1033c
     }
af4b1c02
     av_dict_set(&o->g->codec_opts, opt, arg, 0);
     return 0;
f5e66827
 }
 
d3810c47
 static int opt_video_filters(void *optctx, const char *opt, const char *arg)
f5e66827
 {
d3810c47
     OptionsContext *o = optctx;
f5e66827
     return parse_option(o, "filter:v", arg, options);
 }
 
d3810c47
 static int opt_audio_filters(void *optctx, const char *opt, const char *arg)
f5e66827
 {
d3810c47
     OptionsContext *o = optctx;
f5e66827
     return parse_option(o, "filter:a", arg, options);
 }
 
11d957fb
 static int opt_vsync(void *optctx, const char *opt, const char *arg)
f5e66827
 {
     if      (!av_strcasecmp(arg, "cfr"))         video_sync_method = VSYNC_CFR;
     else if (!av_strcasecmp(arg, "vfr"))         video_sync_method = VSYNC_VFR;
     else if (!av_strcasecmp(arg, "passthrough")) video_sync_method = VSYNC_PASSTHROUGH;
11a1033c
     else if (!av_strcasecmp(arg, "drop"))        video_sync_method = VSYNC_DROP;
f5e66827
 
     if (video_sync_method == VSYNC_AUTO)
         video_sync_method = parse_number_or_die("vsync", arg, OPT_INT, VSYNC_AUTO, VSYNC_VFR);
     return 0;
 }
 
949938d1
 static int opt_timecode(void *optctx, const char *opt, const char *arg)
f5e66827
 {
949938d1
     OptionsContext *o = optctx;
11a1033c
     char *tcr = av_asprintf("timecode=%s", arg);
     int ret = parse_option(o, "metadata:g", tcr, options);
     if (ret >= 0)
af4b1c02
         ret = av_dict_set(&o->g->codec_opts, "gop_timecode", arg, 0);
11a1033c
     av_free(tcr);
f5e66827
     return 0;
 }
 
d3810c47
 static int opt_channel_layout(void *optctx, const char *opt, const char *arg)
f5e66827
 {
d3810c47
     OptionsContext *o = optctx;
f5e66827
     char layout_str[32];
     char *stream_str;
     char *ac_str;
     int ret, channels, ac_str_size;
     uint64_t layout;
 
     layout = av_get_channel_layout(arg);
     if (!layout) {
         av_log(NULL, AV_LOG_ERROR, "Unknown channel layout: %s\n", arg);
         return AVERROR(EINVAL);
     }
     snprintf(layout_str, sizeof(layout_str), "%"PRIu64, layout);
5a67e30b
     ret = opt_default_new(o, opt, layout_str);
f5e66827
     if (ret < 0)
         return ret;
 
     /* set 'ac' option based on channel layout */
     channels = av_get_channel_layout_nb_channels(layout);
     snprintf(layout_str, sizeof(layout_str), "%d", channels);
     stream_str = strchr(opt, ':');
     ac_str_size = 3 + (stream_str ? strlen(stream_str) : 0);
     ac_str = av_mallocz(ac_str_size);
     if (!ac_str)
         return AVERROR(ENOMEM);
     av_strlcpy(ac_str, "ac", 3);
     if (stream_str)
         av_strlcat(ac_str, stream_str, ac_str_size);
     ret = parse_option(o, ac_str, layout_str, options);
     av_free(ac_str);
 
     return ret;
 }
 
d3810c47
 static int opt_audio_qscale(void *optctx, const char *opt, const char *arg)
f5e66827
 {
d3810c47
     OptionsContext *o = optctx;
f5e66827
     return parse_option(o, "q:a", arg, options);
 }
 
11d957fb
 static int opt_filter_complex(void *optctx, const char *opt, const char *arg)
f5e66827
 {
10bca661
     GROW_ARRAY(filtergraphs, nb_filtergraphs);
f5e66827
     if (!(filtergraphs[nb_filtergraphs - 1] = av_mallocz(sizeof(*filtergraphs[0]))))
         return AVERROR(ENOMEM);
a4208b9b
     filtergraphs[nb_filtergraphs - 1]->index      = nb_filtergraphs - 1;
     filtergraphs[nb_filtergraphs - 1]->graph_desc = av_strdup(arg);
     if (!filtergraphs[nb_filtergraphs - 1]->graph_desc)
         return AVERROR(ENOMEM);
     return 0;
 }
 
 static int opt_filter_complex_script(void *optctx, const char *opt, const char *arg)
 {
     uint8_t *graph_desc = read_file(arg);
     if (!graph_desc)
         return AVERROR(EINVAL);
 
     GROW_ARRAY(filtergraphs, nb_filtergraphs);
     if (!(filtergraphs[nb_filtergraphs - 1] = av_mallocz(sizeof(*filtergraphs[0]))))
         return AVERROR(ENOMEM);
     filtergraphs[nb_filtergraphs - 1]->index      = nb_filtergraphs - 1;
     filtergraphs[nb_filtergraphs - 1]->graph_desc = graph_desc;
f5e66827
     return 0;
 }
 
a3ad68d3
 void show_help_default(const char *opt, const char *arg)
f5e66827
 {
f9fada27
     /* per-file options have at least one of those set */
11d957fb
     const int per_file = OPT_SPEC | OPT_OFFSET | OPT_PERFILE;
6e3857fa
     int show_advanced = 0, show_avoptions = 0;
 
8d09d39a
     if (opt && *opt) {
6e3857fa
         if (!strcmp(opt, "long"))
             show_advanced = 1;
         else if (!strcmp(opt, "full"))
             show_advanced = show_avoptions = 1;
         else
             av_log(NULL, AV_LOG_ERROR, "Unknown help option '%s'.\n", opt);
     }
a3ad68d3
 
f5e66827
     show_usage();
6e3857fa
 
     printf("Getting help:\n"
            "    -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"
            "    See man %s for detailed description of the options.\n"
            "\n", program_name);
 
f8b1e665
     show_help_options(options, "Print help / information / capabilities:",
f9fada27
                       OPT_EXIT, 0, 0);
 
     show_help_options(options, "Global options (affect whole program "
                       "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,
                           per_file | OPT_EXIT, 0);
 
     show_help_options(options, "Per-file main options:", 0,
                       OPT_EXPERT | OPT_AUDIO | OPT_VIDEO | OPT_SUBTITLE |
                       OPT_EXIT, per_file);
6e3857fa
     if (show_advanced)
f9fada27
         show_help_options(options, "Advanced per-file options:",
                           OPT_EXPERT, OPT_AUDIO | OPT_VIDEO | OPT_SUBTITLE, per_file);
6e3857fa
 
dc4c24a3
     show_help_options(options, "Video options:",
f9fada27
                       OPT_VIDEO, OPT_EXPERT | OPT_AUDIO, 0);
6e3857fa
     if (show_advanced)
         show_help_options(options, "Advanced Video options:",
f9fada27
                           OPT_EXPERT | OPT_VIDEO, OPT_AUDIO, 0);
6e3857fa
 
dc4c24a3
     show_help_options(options, "Audio options:",
f9fada27
                       OPT_AUDIO, OPT_EXPERT | OPT_VIDEO, 0);
6e3857fa
     if (show_advanced)
         show_help_options(options, "Advanced Audio options:",
f9fada27
                           OPT_EXPERT | OPT_AUDIO, OPT_VIDEO, 0);
dc4c24a3
     show_help_options(options, "Subtitle options:",
f9fada27
                       OPT_SUBTITLE, 0, 0);
f5e66827
     printf("\n");
6e3857fa
 
     if (show_avoptions) {
         int flags = AV_OPT_FLAG_DECODING_PARAM | AV_OPT_FLAG_ENCODING_PARAM;
         show_help_children(avcodec_get_class(), flags);
         show_help_children(avformat_get_class(), flags);
c6552169
 #if CONFIG_SWSCALE
6e3857fa
         show_help_children(sws_get_class(), flags);
c6552169
 #endif
bb3ed3ba
         show_help_children(swr_get_class(), AV_OPT_FLAG_AUDIO_PARAM);
f81a8e89
         show_help_children(avfilter_get_class(), AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_FILTERING_PARAM);
6e3857fa
     }
f5e66827
 }
 
 void show_usage(void)
 {
11a1033c
     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");
f5e66827
 }
 
77bd1bc7
 enum OptGroup {
     GROUP_OUTFILE,
     GROUP_INFILE,
 };
 
 static const OptionGroupDef groups[] = {
9d3009c6
     [GROUP_OUTFILE] = { "output file",  NULL, OPT_OUTPUT },
     [GROUP_INFILE]  = { "input file",   "i",  OPT_INPUT },
77bd1bc7
 };
 
 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;
 
6d77279e
         init_options(&o);
77bd1bc7
         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);
6d77279e
         uninit_options(&o);
77bd1bc7
         if (ret < 0) {
             av_log(NULL, AV_LOG_ERROR, "Error opening %s file %s.\n",
                    inout, g->arg);
             return ret;
         }
c4738c31
         av_log(NULL, AV_LOG_DEBUG, "Successfully opened the file.\n");
77bd1bc7
     }
 
     return 0;
 }
 
af4b1c02
 int ffmpeg_parse_options(int argc, char **argv)
77bd1bc7
 {
     OptionParseContext octx;
     uint8_t error[128];
     int ret;
 
     memset(&octx, 0, sizeof(octx));
 
     /* split the commandline into an internal representation */
c661cb66
     ret = split_commandline(&octx, argc, argv, options, groups,
                             FF_ARRAY_ELEMS(groups));
77bd1bc7
     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;
 }
f5e66827
 
98298eb1
 static int opt_progress(void *optctx, const char *opt, const char *arg)
11a1033c
 {
     AVIOContext *avio = NULL;
     int ret;
 
     if (!strcmp(arg, "-"))
         arg = "pipe:";
     ret = avio_open2(&avio, arg, AVIO_FLAG_WRITE, &int_cb, NULL);
     if (ret < 0) {
0efcf16a
         av_log(NULL, AV_LOG_ERROR, "Failed to open progress URL \"%s\": %s\n",
11a1033c
                arg, av_err2str(ret));
         return ret;
     }
     progress_avio = avio;
     return 0;
 }
 
f5e66827
 #define OFFSET(x) offsetof(OptionsContext, x)
 const OptionDef options[] = {
     /* main options */
 #include "cmdutils_common_opts.h"
9d3009c6
     { "f",              HAS_ARG | OPT_STRING | OPT_OFFSET |
                         OPT_INPUT | OPT_OUTPUT,                      { .off       = OFFSET(format) },
8fc83fb0
         "force format", "fmt" },
     { "y",              OPT_BOOL,                                    {              &file_overwrite },
         "overwrite output files" },
c5af0680
     { "n",              OPT_BOOL,                                    {              &no_file_overwrite },
7748dd41
         "never overwrite output files" },
9d3009c6
     { "c",              HAS_ARG | OPT_STRING | OPT_SPEC |
                         OPT_INPUT | OPT_OUTPUT,                      { .off       = OFFSET(codec_names) },
8fc83fb0
         "codec name", "codec" },
9d3009c6
     { "codec",          HAS_ARG | OPT_STRING | OPT_SPEC |
                         OPT_INPUT | OPT_OUTPUT,                      { .off       = OFFSET(codec_names) },
8fc83fb0
         "codec name", "codec" },
9d3009c6
     { "pre",            HAS_ARG | OPT_STRING | OPT_SPEC |
                         OPT_OUTPUT,                                  { .off       = OFFSET(presets) },
8fc83fb0
         "preset name", "preset" },
9d3009c6
     { "map",            HAS_ARG | OPT_EXPERT | OPT_PERFILE |
                         OPT_OUTPUT,                                  { .func_arg = opt_map },
8fc83fb0
         "set input stream mapping",
         "[-]input_file_id[:stream_specifier][,sync_file_id[:stream_specifier]]" },
5743095c
     { "map_channel",    HAS_ARG | OPT_EXPERT | OPT_PERFILE | OPT_OUTPUT, { .func_arg = opt_map_channel },
c5af0680
         "map an audio channel from one stream to another", "file.stream.channel[:syncfile.syncstream]" },
9d3009c6
     { "map_metadata",   HAS_ARG | OPT_STRING | OPT_SPEC |
                         OPT_OUTPUT,                                  { .off       = OFFSET(metadata_map) },
8fc83fb0
         "set metadata information of outfile from infile",
         "outfile[,metadata]:infile[,metadata]" },
9d3009c6
     { "map_chapters",   HAS_ARG | OPT_INT | OPT_EXPERT | OPT_OFFSET |
                         OPT_OUTPUT,                                  { .off = OFFSET(chapters_input_file) },
8fc83fb0
         "set chapters mapping", "input_file_index" },
488a0fa6
     { "t",              HAS_ARG | OPT_TIME | OPT_OFFSET |
                         OPT_INPUT | OPT_OUTPUT,                      { .off = OFFSET(recording_time) },
8fc83fb0
         "record or transcode \"duration\" seconds of audio/video",
         "duration" },
da397173
     { "to",             HAS_ARG | OPT_TIME | OPT_OFFSET | OPT_OUTPUT,  { .off = OFFSET(stop_time) },
2d704468
         "record or transcode stop time", "time_stop" },
9d3009c6
     { "fs",             HAS_ARG | OPT_INT64 | OPT_OFFSET | OPT_OUTPUT, { .off = OFFSET(limit_filesize) },
8fc83fb0
         "set the limit file size in bytes", "limit_size" },
9d3009c6
     { "ss",             HAS_ARG | OPT_TIME | OPT_OFFSET |
                         OPT_INPUT | OPT_OUTPUT,                      { .off = OFFSET(start_time) },
8fc83fb0
         "set the start time offset", "time_off" },
811bd078
     { "accurate_seek",  OPT_BOOL | OPT_OFFSET | OPT_EXPERT |
                         OPT_INPUT,                                   { .off = OFFSET(accurate_seek) },
         "enable/disable accurate seeking with -ss" },
9d3009c6
     { "itsoffset",      HAS_ARG | OPT_TIME | OPT_OFFSET |
                         OPT_EXPERT | OPT_INPUT,                      { .off = OFFSET(input_ts_offset) },
8fc83fb0
         "set the input ts offset", "time_off" },
9d3009c6
     { "itsscale",       HAS_ARG | OPT_DOUBLE | OPT_SPEC |
                         OPT_EXPERT | OPT_INPUT,                      { .off = OFFSET(ts_scale) },
8fc83fb0
         "set the input ts scale", "scale" },
98298eb1
     { "timestamp",      HAS_ARG | OPT_PERFILE,                       { .func_arg = opt_recording_timestamp },
c5af0680
         "set the recording timestamp ('now' to set the current time)", "time" },
9d3009c6
     { "metadata",       HAS_ARG | OPT_STRING | OPT_SPEC | OPT_OUTPUT, { .off = OFFSET(metadata) },
8fc83fb0
         "add metadata", "string=string" },
9d3009c6
     { "dframes",        HAS_ARG | OPT_PERFILE | OPT_EXPERT |
                         OPT_OUTPUT,                                  { .func_arg = opt_data_frames },
8fc83fb0
         "set the number of data frames to record", "number" },
     { "benchmark",      OPT_BOOL | OPT_EXPERT,                       { &do_benchmark },
         "add timings for benchmarking" },
c5af0680
     { "benchmark_all",  OPT_BOOL | OPT_EXPERT,                       { &do_benchmark_all },
11a1033c
       "add timings for each task" },
c5af0680
     { "progress",       HAS_ARG | OPT_EXPERT,                        { .func_arg = opt_progress },
11a1033c
       "write program-readable progress information", "url" },
c5af0680
     { "stdin",          OPT_BOOL | OPT_EXPERT,                       { &stdin_interaction },
11a1033c
       "enable or disable interaction on standard input" },
602b1898
     { "timelimit",      HAS_ARG | OPT_EXPERT,                        { .func_arg = opt_timelimit },
8fc83fb0
         "set max runtime in seconds", "limit" },
     { "dump",           OPT_BOOL | OPT_EXPERT,                       { &do_pkt_dump },
         "dump each input packet" },
     { "hex",            OPT_BOOL | OPT_EXPERT,                       { &do_hex_dump },
         "when dumping packets, also dump the payload" },
9d3009c6
     { "re",             OPT_BOOL | OPT_EXPERT | OPT_OFFSET |
                         OPT_INPUT,                                   { .off = OFFSET(rate_emu) },
8fc83fb0
         "read input at native frame rate", "" },
9d3009c6
     { "target",         HAS_ARG | OPT_PERFILE | OPT_OUTPUT,          { .func_arg = opt_target },
8fc83fb0
         "specify target file type (\"vcd\", \"svcd\", \"dvd\","
         " \"dv\", \"dv50\", \"pal-vcd\", \"ntsc-svcd\", ...)", "type" },
     { "vsync",          HAS_ARG | OPT_EXPERT,                        { opt_vsync },
         "video sync method", "" },
     { "async",          HAS_ARG | OPT_INT | OPT_EXPERT,              { &audio_sync_method },
         "audio sync method", "" },
     { "adrift_threshold", HAS_ARG | OPT_FLOAT | OPT_EXPERT,          { &audio_drift_threshold },
         "audio drift threshold", "threshold" },
     { "copyts",         OPT_BOOL | OPT_EXPERT,                       { &copy_ts },
         "copy timestamps" },
c5af0680
     { "copytb",         HAS_ARG | OPT_INT | OPT_EXPERT,              { &copy_tb },
         "copy input stream time base when stream copying", "mode" },
9d3009c6
     { "shortest",       OPT_BOOL | OPT_EXPERT | OPT_OFFSET |
                         OPT_OUTPUT,                                  { .off = OFFSET(shortest) },
8fc83fb0
         "finish encoding within shortest input" },
33ff943f
     { "apad",           OPT_STRING | HAS_ARG | OPT_SPEC |
                         OPT_OUTPUT,                                  { .off = OFFSET(apad) },
         "audio pad", "" },
8fc83fb0
     { "dts_delta_threshold", HAS_ARG | OPT_FLOAT | OPT_EXPERT,       { &dts_delta_threshold },
         "timestamp discontinuity delta threshold", "threshold" },
c5af0680
     { "dts_error_threshold", HAS_ARG | OPT_FLOAT | OPT_EXPERT,       { &dts_error_threshold },
         "timestamp error delta threshold", "threshold" },
602b1898
     { "xerror",         OPT_BOOL | OPT_EXPERT,                       { &exit_on_error },
8fc83fb0
         "exit on error", "error" },
9d3009c6
     { "copyinkf",       OPT_BOOL | OPT_EXPERT | OPT_SPEC |
                         OPT_OUTPUT,                                  { .off = OFFSET(copy_initial_nonkeyframes) },
8fc83fb0
         "copy initial non-keyframes" },
5743095c
     { "copypriorss",    OPT_INT | HAS_ARG | OPT_EXPERT | OPT_SPEC | OPT_OUTPUT,   { .off = OFFSET(copy_prior_start) },
65f7aee6
         "copy or discard frames before start time" },
9d3009c6
     { "frames",         OPT_INT64 | HAS_ARG | OPT_SPEC | OPT_OUTPUT, { .off = OFFSET(max_frames) },
8fc83fb0
         "set the number of frames to record", "number" },
9d3009c6
     { "tag",            OPT_STRING | HAS_ARG | OPT_SPEC |
746dca48
                         OPT_EXPERT | OPT_OUTPUT | OPT_INPUT,         { .off = OFFSET(codec_tags) },
8fc83fb0
         "force codec tag/fourcc", "fourcc/tag" },
9d3009c6
     { "q",              HAS_ARG | OPT_EXPERT | OPT_DOUBLE |
                         OPT_SPEC | OPT_OUTPUT,                       { .off = OFFSET(qscale) },
8fc83fb0
         "use fixed quality scale (VBR)", "q" },
5743095c
     { "qscale",         HAS_ARG | OPT_EXPERT | OPT_PERFILE |
                         OPT_OUTPUT,                                  { .func_arg = opt_qscale },
8fc83fb0
         "use fixed quality scale (VBR)", "q" },
5743095c
     { "profile",        HAS_ARG | OPT_EXPERT | OPT_PERFILE | OPT_OUTPUT, { .func_arg = opt_profile },
c5af0680
         "set profile", "profile" },
9d3009c6
     { "filter",         HAS_ARG | OPT_STRING | OPT_SPEC | OPT_OUTPUT, { .off = OFFSET(filters) },
89ef5868
         "set stream filtergraph", "filter_graph" },
a4208b9b
     { "filter_script",  HAS_ARG | OPT_STRING | OPT_SPEC | OPT_OUTPUT, { .off = OFFSET(filter_scripts) },
         "read stream filtergraph description from a file", "filename" },
bd93f3c5
     { "reinit_filter",  HAS_ARG | OPT_INT | OPT_SPEC | OPT_INPUT,    { .off = OFFSET(reinit_filters) },
3e0b29cc
         "reinit filtergraph on input parameter changes", "" },
8fc83fb0
     { "filter_complex", HAS_ARG | OPT_EXPERT,                        { .func_arg = opt_filter_complex },
         "create a complex filtergraph", "graph_description" },
40ea006b
     { "lavfi",          HAS_ARG | OPT_EXPERT,                        { .func_arg = opt_filter_complex },
         "create a complex filtergraph", "graph_description" },
a4208b9b
     { "filter_complex_script", HAS_ARG | OPT_EXPERT,                 { .func_arg = opt_filter_complex_script },
         "read complex filtergraph description from a file", "filename" },
8fc83fb0
     { "stats",          OPT_BOOL,                                    { &print_stats },
         "print progress report during encoding", },
9d3009c6
     { "attach",         HAS_ARG | OPT_PERFILE | OPT_EXPERT |
                         OPT_OUTPUT,                                  { .func_arg = opt_attach },
8fc83fb0
         "add an attachment to the output file", "filename" },
9d3009c6
     { "dump_attachment", HAS_ARG | OPT_STRING | OPT_SPEC |
                          OPT_EXPERT | OPT_INPUT,                     { .off = OFFSET(dump_attachment) },
8fc83fb0
         "extract an attachment into a file", "filename" },
c5af0680
     { "debug_ts",       OPT_BOOL | OPT_EXPERT,                       { &debug_ts },
         "print timestamp debugging info" },
b6b9c150
     { "max_error_rate",  HAS_ARG | OPT_FLOAT,                        { &max_error_rate },
         "maximum error rate", "ratio of errors (0.0: no errors, 1.0: 100% errors) above which ffmpeg returns an error instead of success." },
f5e66827
 
     /* video options */
9d3009c6
     { "vframes",      OPT_VIDEO | HAS_ARG  | OPT_PERFILE | OPT_OUTPUT,           { .func_arg = opt_video_frames },
8fc83fb0
         "set the number of video frames to record", "number" },
9d3009c6
     { "r",            OPT_VIDEO | HAS_ARG  | OPT_STRING | OPT_SPEC |
                       OPT_INPUT | OPT_OUTPUT,                                    { .off = OFFSET(frame_rates) },
8fc83fb0
         "set frame rate (Hz value, fraction or abbreviation)", "rate" },
5743095c
     { "s",            OPT_VIDEO | HAS_ARG | OPT_SUBTITLE | OPT_STRING | OPT_SPEC |
9d3009c6
                       OPT_INPUT | OPT_OUTPUT,                                    { .off = OFFSET(frame_sizes) },
8fc83fb0
         "set frame size (WxH or abbreviation)", "size" },
9d3009c6
     { "aspect",       OPT_VIDEO | HAS_ARG  | OPT_STRING | OPT_SPEC |
                       OPT_OUTPUT,                                                { .off = OFFSET(frame_aspect_ratios) },
8fc83fb0
         "set aspect ratio (4:3, 16:9 or 1.3333, 1.7777)", "aspect" },
9d3009c6
     { "pix_fmt",      OPT_VIDEO | HAS_ARG | OPT_EXPERT  | OPT_STRING | OPT_SPEC |
                       OPT_INPUT | OPT_OUTPUT,                                    { .off = OFFSET(frame_pix_fmts) },
8fc83fb0
         "set pixel format", "format" },
c5af0680
     { "bits_per_raw_sample", OPT_VIDEO | OPT_INT | HAS_ARG,                      { &frame_bits_per_raw_sample },
         "set the number of bits per raw sample", "number" },
     { "intra",        OPT_VIDEO | OPT_BOOL | OPT_EXPERT,                         { &intra_only },
         "deprecated use -g 1" },
5743095c
     { "vn",           OPT_VIDEO | OPT_BOOL  | OPT_OFFSET | OPT_INPUT | OPT_OUTPUT,{ .off = OFFSET(video_disable) },
8fc83fb0
         "disable video" },
     { "vdt",          OPT_VIDEO | OPT_INT | HAS_ARG | OPT_EXPERT ,               { &video_discard },
         "discard threshold", "n" },
9d3009c6
     { "rc_override",  OPT_VIDEO | HAS_ARG | OPT_EXPERT  | OPT_STRING | OPT_SPEC |
                       OPT_OUTPUT,                                                { .off = OFFSET(rc_overrides) },
8fc83fb0
         "rate control override for specific intervals", "override" },
9d3009c6
     { "vcodec",       OPT_VIDEO | HAS_ARG  | OPT_PERFILE | OPT_INPUT |
                       OPT_OUTPUT,                                                { .func_arg = opt_video_codec },
8fc83fb0
         "force video codec ('copy' to copy stream)", "codec" },
e47ab0b2
     { "sameq",        OPT_VIDEO | OPT_EXPERT ,                                   { .func_arg = opt_sameq },
         "Removed" },
     { "same_quant",   OPT_VIDEO | OPT_EXPERT ,                                   { .func_arg = opt_sameq },
         "Removed" },
5743095c
     { "timecode",     OPT_VIDEO | HAS_ARG | OPT_PERFILE | OPT_OUTPUT,            { .func_arg = opt_timecode },
c5af0680
         "set initial TimeCode value.", "hh:mm:ss[:;.]ff" },
9d3009c6
     { "pass",         OPT_VIDEO | HAS_ARG | OPT_SPEC | OPT_INT | OPT_OUTPUT,     { .off = OFFSET(pass) },
98298eb1
         "select the pass number (1 to 3)", "n" },
9d3009c6
     { "passlogfile",  OPT_VIDEO | HAS_ARG | OPT_STRING | OPT_EXPERT | OPT_SPEC |
                       OPT_OUTPUT,                                                { .off = OFFSET(passlogfiles) },
8fc83fb0
         "select two pass log file name prefix", "prefix" },
4257b804
     { "deinterlace",  OPT_VIDEO | OPT_BOOL | OPT_EXPERT,                         { &do_deinterlace },
8fc83fb0
         "this option is deprecated, use the yadif filter instead" },
c5af0680
     { "psnr",         OPT_VIDEO | OPT_BOOL | OPT_EXPERT,                         { &do_psnr },
         "calculate PSNR of compressed frames" },
8fc83fb0
     { "vstats",       OPT_VIDEO | OPT_EXPERT ,                                   { &opt_vstats },
         "dump video coding statistics to file" },
     { "vstats_file",  OPT_VIDEO | HAS_ARG | OPT_EXPERT ,                         { opt_vstats_file },
         "dump video coding statistics to file", "file" },
9d3009c6
     { "vf",           OPT_VIDEO | HAS_ARG  | OPT_PERFILE | OPT_OUTPUT,           { .func_arg = opt_video_filters },
89ef5868
         "set video filters", "filter_graph" },
9d3009c6
     { "intra_matrix", OPT_VIDEO | HAS_ARG | OPT_EXPERT  | OPT_STRING | OPT_SPEC |
                       OPT_OUTPUT,                                                { .off = OFFSET(intra_matrices) },
8fc83fb0
         "specify intra matrix coeffs", "matrix" },
9d3009c6
     { "inter_matrix", OPT_VIDEO | HAS_ARG | OPT_EXPERT  | OPT_STRING | OPT_SPEC |
                       OPT_OUTPUT,                                                { .off = OFFSET(inter_matrices) },
8fc83fb0
         "specify inter matrix coeffs", "matrix" },
3e70c702
     { "chroma_intra_matrix", OPT_VIDEO | HAS_ARG | OPT_EXPERT  | OPT_STRING | OPT_SPEC |
                       OPT_OUTPUT,                                                { .off = OFFSET(chroma_intra_matrices) },
         "specify intra matrix coeffs", "matrix" },
9d3009c6
     { "top",          OPT_VIDEO | HAS_ARG | OPT_EXPERT  | OPT_INT| OPT_SPEC |
5743095c
                       OPT_INPUT | OPT_OUTPUT,                                    { .off = OFFSET(top_field_first) },
8fc83fb0
         "top=1/bottom=0/auto=-1 field first", "" },
     { "dc",           OPT_VIDEO | OPT_INT | HAS_ARG | OPT_EXPERT ,               { &intra_dc_precision },
         "intra_dc_precision", "precision" },
9d3009c6
     { "vtag",         OPT_VIDEO | HAS_ARG | OPT_EXPERT  | OPT_PERFILE |
5743095c
                       OPT_OUTPUT,                                                { .func_arg = opt_old2new },
8fc83fb0
         "force video tag/fourcc", "fourcc/tag" },
     { "qphist",       OPT_VIDEO | OPT_BOOL | OPT_EXPERT ,                        { &qp_hist },
         "show QP histogram" },
9d3009c6
     { "force_fps",    OPT_VIDEO | OPT_BOOL | OPT_EXPERT  | OPT_SPEC |
                       OPT_OUTPUT,                                                { .off = OFFSET(force_fps) },
8fc83fb0
         "force the selected framerate, disable the best supported framerate selection" },
9d3009c6
     { "streamid",     OPT_VIDEO | HAS_ARG | OPT_EXPERT | OPT_PERFILE |
                       OPT_OUTPUT,                                                { .func_arg = opt_streamid },
8fc83fb0
         "set the value of an outfile streamid", "streamIndex:value" },
9d3009c6
     { "force_key_frames", OPT_VIDEO | OPT_STRING | HAS_ARG | OPT_EXPERT |
                           OPT_SPEC | OPT_OUTPUT,                                 { .off = OFFSET(forced_key_frames) },
c5af0680
         "force key frames at specified timestamps", "timestamps" },
5743095c
     { "b",            OPT_VIDEO | HAS_ARG | OPT_PERFILE | OPT_OUTPUT,            { .func_arg = opt_bitrate },
c5af0680
         "video bitrate (please use -b:v)", "bitrate" },
07fd0a22
     { "hwaccel",          OPT_VIDEO | OPT_STRING | HAS_ARG | OPT_EXPERT |
                           OPT_SPEC | OPT_INPUT,                                  { .off = OFFSET(hwaccels) },
         "use HW accelerated decoding", "hwaccel name" },
     { "hwaccel_device",   OPT_VIDEO | OPT_STRING | HAS_ARG | OPT_EXPERT |
                           OPT_SPEC | OPT_INPUT,                                  { .off = OFFSET(hwaccel_devices) },
         "select a device for HW acceleration" "devicename" },
f5e66827
 
     /* audio options */
9d3009c6
     { "aframes",        OPT_AUDIO | HAS_ARG  | OPT_PERFILE | OPT_OUTPUT,           { .func_arg = opt_audio_frames },
8fc83fb0
         "set the number of audio frames to record", "number" },
9d3009c6
     { "aq",             OPT_AUDIO | HAS_ARG  | OPT_PERFILE | OPT_OUTPUT,           { .func_arg = opt_audio_qscale },
8fc83fb0
         "set audio quality (codec-specific)", "quality", },
9d3009c6
     { "ar",             OPT_AUDIO | HAS_ARG  | OPT_INT | OPT_SPEC |
                         OPT_INPUT | OPT_OUTPUT,                                    { .off = OFFSET(audio_sample_rate) },
8fc83fb0
         "set audio sampling rate (in Hz)", "rate" },
9d3009c6
     { "ac",             OPT_AUDIO | HAS_ARG  | OPT_INT | OPT_SPEC |
                         OPT_INPUT | OPT_OUTPUT,                                    { .off = OFFSET(audio_channels) },
8fc83fb0
         "set number of audio channels", "channels" },
5743095c
     { "an",             OPT_AUDIO | OPT_BOOL | OPT_OFFSET | OPT_INPUT | OPT_OUTPUT,{ .off = OFFSET(audio_disable) },
8fc83fb0
         "disable audio" },
9d3009c6
     { "acodec",         OPT_AUDIO | HAS_ARG  | OPT_PERFILE |
                         OPT_INPUT | OPT_OUTPUT,                                    { .func_arg = opt_audio_codec },
8fc83fb0
         "force audio codec ('copy' to copy stream)", "codec" },
9d3009c6
     { "atag",           OPT_AUDIO | HAS_ARG  | OPT_EXPERT | OPT_PERFILE |
5743095c
                         OPT_OUTPUT,                                                { .func_arg = opt_old2new },
8fc83fb0
         "force audio tag/fourcc", "fourcc/tag" },
     { "vol",            OPT_AUDIO | HAS_ARG  | OPT_INT,                            { &audio_volume },
         "change audio volume (256=normal)" , "volume" },
9d3009c6
     { "sample_fmt",     OPT_AUDIO | HAS_ARG  | OPT_EXPERT | OPT_SPEC |
                         OPT_STRING | OPT_INPUT | OPT_OUTPUT,                       { .off = OFFSET(sample_fmts) },
8fc83fb0
         "set sample format", "format" },
9d3009c6
     { "channel_layout", OPT_AUDIO | HAS_ARG  | OPT_EXPERT | OPT_PERFILE |
                         OPT_INPUT | OPT_OUTPUT,                                    { .func_arg = opt_channel_layout },
8fc83fb0
         "set channel layout", "layout" },
9d3009c6
     { "af",             OPT_AUDIO | HAS_ARG  | OPT_PERFILE | OPT_OUTPUT,           { .func_arg = opt_audio_filters },
89ef5868
         "set audio filters", "filter_graph" },
0eb56a08
     { "guess_layout_max", OPT_AUDIO | HAS_ARG | OPT_INT | OPT_SPEC | OPT_EXPERT | OPT_INPUT, { .off = OFFSET(guess_layout_max) },
fccd8c21
       "set the maximum number of channels to try to guess the channel layout" },
f5e66827
 
     /* subtitle options */
5743095c
     { "sn",     OPT_SUBTITLE | OPT_BOOL | OPT_OFFSET | OPT_INPUT | OPT_OUTPUT, { .off = OFFSET(subtitle_disable) },
8fc83fb0
         "disable subtitle" },
9d3009c6
     { "scodec", OPT_SUBTITLE | HAS_ARG  | OPT_PERFILE | OPT_INPUT | OPT_OUTPUT, { .func_arg = opt_subtitle_codec },
8fc83fb0
         "force subtitle codec ('copy' to copy stream)", "codec" },
5743095c
     { "stag",   OPT_SUBTITLE | HAS_ARG  | OPT_EXPERT  | OPT_PERFILE | OPT_OUTPUT, { .func_arg = opt_old2new }
8fc83fb0
         , "force subtitle tag/fourcc", "fourcc/tag" },
639a9e21
     { "fix_sub_duration", OPT_BOOL | OPT_EXPERT | OPT_SUBTITLE | OPT_SPEC | OPT_INPUT, { .off = OFFSET(fix_sub_duration) },
c5af0680
         "fix subtitles duration" },
639a9e21
     { "canvas_size", OPT_SUBTITLE | HAS_ARG | OPT_STRING | OPT_SPEC | OPT_INPUT, { .off = OFFSET(canvas_sizes) },
cb2bd914
         "set canvas size (WxH or abbreviation)", "size" },
f5e66827
 
     /* grab options */
67a6dac7
     { "vc", HAS_ARG | OPT_EXPERT | OPT_VIDEO, { .func_arg = opt_video_channel },
c5af0680
         "deprecated, use -channel", "channel" },
67a6dac7
     { "tvstd", HAS_ARG | OPT_EXPERT | OPT_VIDEO, { .func_arg = opt_video_standard },
c5af0680
         "deprecated, use -standard", "standard" },
79600a83
     { "isync", OPT_BOOL | OPT_EXPERT, { &input_sync }, "this option is deprecated and does nothing", "" },
f5e66827
 
     /* muxer options */
9d3009c6
     { "muxdelay",   OPT_FLOAT | HAS_ARG | OPT_EXPERT | OPT_OFFSET | OPT_OUTPUT, { .off = OFFSET(mux_max_delay) },
8fc83fb0
         "set the maximum demux-decode delay", "seconds" },
9d3009c6
     { "muxpreload", OPT_FLOAT | HAS_ARG | OPT_EXPERT | OPT_OFFSET | OPT_OUTPUT, { .off = OFFSET(mux_preload) },
8fc83fb0
         "set the initial demux-decode delay", "seconds" },
d1e8d4b0
     { "override_ffserver", OPT_BOOL | OPT_EXPERT | OPT_OUTPUT, { &override_ffserver },
         "override the options from ffserver", "" },
f5e66827
 
9d3009c6
     { "bsf", HAS_ARG | OPT_STRING | OPT_SPEC | OPT_EXPERT | OPT_OUTPUT, { .off = OFFSET(bitstream_filters) },
8fc83fb0
         "A comma-separated list of bitstream filters", "bitstream_filters" },
5743095c
     { "absf", HAS_ARG | OPT_AUDIO | OPT_EXPERT| OPT_PERFILE | OPT_OUTPUT, { .func_arg = opt_old2new },
c5af0680
         "deprecated", "audio bitstream_filters" },
5743095c
     { "vbsf", OPT_VIDEO | HAS_ARG | OPT_EXPERT| OPT_PERFILE | OPT_OUTPUT, { .func_arg = opt_old2new },
c5af0680
         "deprecated", "video bitstream_filters" },
 
5743095c
     { "apre", HAS_ARG | OPT_AUDIO | OPT_EXPERT| OPT_PERFILE | OPT_OUTPUT,    { .func_arg = opt_preset },
c5af0680
         "set the audio options to the indicated preset", "preset" },
5743095c
     { "vpre", OPT_VIDEO | HAS_ARG | OPT_EXPERT| OPT_PERFILE | OPT_OUTPUT,    { .func_arg = opt_preset },
c5af0680
         "set the video options to the indicated preset", "preset" },
5743095c
     { "spre", HAS_ARG | OPT_SUBTITLE | OPT_EXPERT| OPT_PERFILE | OPT_OUTPUT, { .func_arg = opt_preset },
c5af0680
         "set the subtitle options to the indicated preset", "preset" },
5743095c
     { "fpre", HAS_ARG | OPT_EXPERT| OPT_PERFILE | OPT_OUTPUT,                { .func_arg = opt_preset },
c5af0680
         "set options from indicated preset file", "filename" },
f5e66827
     /* data codec support */
9d3009c6
     { "dcodec", HAS_ARG | OPT_DATA | OPT_PERFILE | OPT_EXPERT | OPT_INPUT | OPT_OUTPUT, { .func_arg = opt_data_codec },
8fc83fb0
         "force data codec ('copy' to copy stream)", "codec" },
5743095c
     { "dn", OPT_BOOL | OPT_VIDEO | OPT_OFFSET | OPT_INPUT | OPT_OUTPUT, { .off = OFFSET(data_disable) },
c5af0680
         "disable data" },
f5e66827
 
     { NULL, },
 };