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"
 
247f4d1f
 #define DEFAULT_PASS_LOGFILENAME_PREFIX "ffmpeg2pass"
6d5d9246
 
f5e66827
 #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
a61c2115
 #if HAVE_DXVA2_LIB
35177ba7
     { "dxva2", dxva2_init, HWACCEL_DXVA2, AV_PIX_FMT_DXVA2_VLD },
 #endif
1839fafa
 #if CONFIG_VDA
11d923d4
     { "vda",   videotoolbox_init,   HWACCEL_VDA,   AV_PIX_FMT_VDA },
 #endif
 #if CONFIG_VIDEOTOOLBOX
     { "videotoolbox",   videotoolbox_init,   HWACCEL_VIDEOTOOLBOX,   AV_PIX_FMT_VIDEOTOOLBOX },
1839fafa
 #endif
fb472e1a
 #if CONFIG_LIBMFX
     { "qsv",   qsv_init,   HWACCEL_QSV,   AV_PIX_FMT_QSV },
 #endif
5d273d3e
 #if CONFIG_VAAPI
     { "vaapi", vaapi_decode_init, HWACCEL_VAAPI, AV_PIX_FMT_VAAPI },
 #endif
d865e74e
 #if CONFIG_CUVID
     { "cuvid", cuvid_init, HWACCEL_CUVID, AV_PIX_FMT_CUDA },
 #endif
07fd0a22
     { 0 },
 };
5d273d3e
 int hwaccel_lax_profile_check = 0;
 AVBufferRef *hw_device_ctx;
07fd0a22
 
f5e66827
 char *vstats_filename;
cc63da12
 char *sdp_filename;
f5e66827
 
 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;
77f326dc
 float frame_drop_threshold = 0;
f5e66827
 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;
315f9e92
 int start_at_zero     = 0;
11a1033c
 int copy_tb           = -1;
 int debug_ts          = 0;
f5e66827
 int exit_on_error     = 0;
ddc6bd8c
 int abort_on_flags    = 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;
 static int do_psnr            = 0;
f5e66827
 static int input_sync;
d1e8d4b0
 static int override_ffserver  = 0;
6a3833e1
 static int input_stream_potentially_available = 0;
a2aff269
 static int ignore_unknown_streams = 0;
18833daf
 static int copy_unknown_streams = 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;
f4ada6dc
     o->start_time_eof = 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
 }
 
da0e7695
 static int show_hwaccels(void *optctx, const char *opt, const char *arg)
 {
     int i;
 
     printf("Hardware acceleration methods:\n");
     for (i = 0; i < FF_ARRAY_ELEMS(hwaccels) - 1; i++) {
         printf("%s\n", hwaccels[i].name);
     }
     printf("\n");
     return 0;
 }
 
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;
 }
 
ddc6bd8c
 static int opt_abort_on(void *optctx, const char *opt, const char *arg)
 {
     static const AVOption opts[] = {
         { "abort_on"        , NULL, 0, AV_OPT_TYPE_FLAGS, { .i64 = 0 }, INT64_MIN, INT64_MAX, .unit = "flags" },
         { "empty_output"    , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = ABORT_ON_FLAG_EMPTY_OUTPUT     },    .unit = "flags" },
         { NULL },
     };
     static const AVClass class = {
         .class_name = "",
         .item_name  = av_default_item_name,
         .option     = opts,
         .version    = LIBAVUTIL_VERSION_INT,
     };
     const AVClass *pclass = &class;
 
     return av_opt_eval_flags(&pclass, &opts[0], arg, &abort_on_flags);
 }
 
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;
2375a85c
     char *allow_unused;
f5e66827
 
     if (*arg == '-') {
         negative = 1;
         arg++;
     }
     map = av_strdup(arg);
b1306823
     if (!map)
         return AVERROR(ENOMEM);
f5e66827
 
     /* 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 {
2375a85c
         if (allow_unused = strchr(map, '?'))
             *allow_unused = 0;
f5e66827
         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) {
2375a85c
         if (allow_unused) {
             av_log(NULL, AV_LOG_VERBOSE, "Stream map '%s' matches no streams; ignoring.\n", arg);
         } else {
             av_log(NULL, AV_LOG_FATAL, "Stream map '%s' matches no streams.\n"
                                        "To ignore this, add a trailing '?' to the map.\n", arg);
             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];
955b818c
     if (st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO) {
11a1033c
         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
     }
955b818c
     if (m->channel_idx < 0 || m->channel_idx >= st->codecpar->channels) {
11a1033c
         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;
 }
 
cc63da12
 static int opt_sdp_file(void *optctx, const char *opt, const char *arg)
 {
     av_free(sdp_filename);
     sdp_filename = av_strdup(arg);
     return 0;
 }
 
5d273d3e
 #if CONFIG_VAAPI
 static int opt_vaapi_device(void *optctx, const char *opt, const char *arg)
 {
     int err;
     err = vaapi_device_init(arg);
     if (err < 0)
         exit_program(1);
     return 0;
 }
 #endif
 
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);
ba6888c0
     if (!strftime(buf, sizeof(buf), "creation_time=%Y-%m-%dT%H:%M:%S%z", &time))
c0002ddb
         return -1;
11a1033c
     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) {
955b818c
         AVCodec *codec = find_codec_or_die(codec_name, st->codecpar->codec_type, 0);
         st->codecpar->codec_id = codec->id;
f5e66827
         return codec;
     } else
955b818c
         return avcodec_find_decoder(st->codecpar->codec_id);
f5e66827
 }
 
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)
 {
41776ba9
     int i, ret;
f5e66827
 
     for (i = 0; i < ic->nb_streams; i++) {
         AVStream *st = ic->streams[i];
955b818c
         AVCodecParameters *par = st->codecpar;
f5e66827
         InputStream *ist = av_mallocz(sizeof(*ist));
07fd0a22
         char *framerate = NULL, *hwaccel = NULL, *hwaccel_device = NULL;
5d273d3e
         char *hwaccel_output_format = NULL;
746dca48
         char *codec_tag = NULL;
         char *next;
01ef127b
         char *discard_str = NULL;
955b818c
         const AVClass *cc = avcodec_get_class();
         const AVOption *discard_opt = av_opt_find(&cc, "skip_frame", NULL, 0, 0);
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;
16b0c929
         ist->nb_samples = 0;
         ist->min_pts = INT64_MAX;
         ist->max_pts = INT64_MIN;
f5e66827
 
         ist->ts_scale = 1.0;
         MATCH_PER_STREAM_OPT(ts_scale, dbl, ist->ts_scale, ic, st);
 
16302246
         ist->autorotate = 1;
         MATCH_PER_STREAM_OPT(autorotate, i, ist->autorotate, 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);
955b818c
             st->codecpar->codec_tag = tag;
11a1033c
         }
 
f5e66827
         ist->dec = choose_decoder(o, ic, st);
955b818c
         ist->decoder_opts = filter_codec_opts(o->g->codec_opts, ist->st->codecpar->codec_id, ic, st, ist->dec);
f5e66827
 
3e0b29cc
         ist->reinit_filters = -1;
         MATCH_PER_STREAM_OPT(reinit_filters, i, ist->reinit_filters, ic, st);
 
01ef127b
         MATCH_PER_STREAM_OPT(discard, str, discard_str, ic, st);
         ist->user_set_discard = AVDISCARD_NONE;
955b818c
         if (discard_str && av_opt_eval_int(&cc, discard_opt, discard_str, &ist->user_set_discard) < 0) {
01ef127b
             av_log(NULL, AV_LOG_ERROR, "Error parsing discard %s.\n",
                     discard_str);
             exit_program(1);
         }
 
a9d97e1b
         ist->filter_in_rescale_delta_last = AV_NOPTS_VALUE;
 
41776ba9
         ist->dec_ctx = avcodec_alloc_context3(ist->dec);
         if (!ist->dec_ctx) {
             av_log(NULL, AV_LOG_ERROR, "Error allocating the decoder context.\n");
             exit_program(1);
         }
 
955b818c
         ret = avcodec_parameters_to_context(ist->dec_ctx, par);
41776ba9
         if (ret < 0) {
             av_log(NULL, AV_LOG_ERROR, "Error initializing the decoder context.\n");
             exit_program(1);
         }
 
955b818c
         switch (par->codec_type) {
f5e66827
         case AVMEDIA_TYPE_VIDEO:
11a1033c
             if(!ist->dec)
955b818c
                 ist->dec = avcodec_find_decoder(par->codec_id);
2fb593dc
 #if FF_API_EMU_EDGE
955b818c
             if (av_codec_get_lowres(st->codec)) {
                 av_codec_set_lowres(ist->dec_ctx, av_codec_get_lowres(st->codec));
                 ist->dec_ctx->width  = st->codec->width;
                 ist->dec_ctx->height = st->codec->height;
                 ist->dec_ctx->coded_width  = st->codec->coded_width;
                 ist->dec_ctx->coded_height = st->codec->coded_height;
                 ist->dec_ctx->flags |= CODEC_FLAG_EMU_EDGE;
11a1033c
             }
2fb593dc
 #endif
11a1033c
 
955b818c
             // avformat_find_stream_info() doesn't set this for us anymore.
             ist->dec_ctx->framerate = st->avg_frame_rate;
 
41776ba9
             ist->resample_height  = ist->dec_ctx->height;
             ist->resample_width   = ist->dec_ctx->width;
             ist->resample_pix_fmt = ist->dec_ctx->pix_fmt;
f5e66827
 
             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);
             }
5d273d3e
 
             MATCH_PER_STREAM_OPT(hwaccel_output_formats, str,
                                  hwaccel_output_format, ic, st);
             if (hwaccel_output_format) {
                 ist->hwaccel_output_format = av_get_pix_fmt(hwaccel_output_format);
                 if (ist->hwaccel_output_format == AV_PIX_FMT_NONE) {
                     av_log(NULL, AV_LOG_FATAL, "Unrecognised hwaccel output "
                            "format: %s", hwaccel_output_format);
                 }
             } else {
                 ist->hwaccel_output_format = AV_PIX_FMT_NONE;
             }
 
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);
 
41776ba9
             ist->resample_sample_fmt     = ist->dec_ctx->sample_fmt;
             ist->resample_sample_rate    = ist->dec_ctx->sample_rate;
             ist->resample_channels       = ist->dec_ctx->channels;
             ist->resample_channel_layout = ist->dec_ctx->channel_layout;
f5e66827
 
             break;
         case AVMEDIA_TYPE_DATA:
cb2bd914
         case AVMEDIA_TYPE_SUBTITLE: {
             char *canvas_size = NULL;
11a1033c
             if(!ist->dec)
955b818c
                 ist->dec = avcodec_find_decoder(par->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 &&
66b9e60a
                 av_parse_video_size(&ist->dec_ctx->width, &ist->dec_ctx->height, canvas_size) < 0) {
cb2bd914
                 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();
         }
955b818c
 
         ret = avcodec_parameters_from_context(par, ist->dec_ctx);
         if (ret < 0) {
             av_log(NULL, AV_LOG_ERROR, "Error initializing the decoder context.\n");
             exit_program(1);
         }
f5e66827
     }
 }
 
 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;
 
955b818c
     if (!st->codecpar->extradata_size) {
f5e66827
         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
     }
 
955b818c
     avio_write(out, st->codecpar->extradata, st->codecpar->extradata_size);
f5e66827
     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;
     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;
bb0344dc
     char *    data_codec_name = NULL;
e971eef8
     int scan_all_pmts_set = 0;
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) {
a0941c8a
         av_dict_set_int(&o->g->format_opts, "sample_rate", o->audio_sample_rate[o->nb_audio_sample_rate - 1].u.i, 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)) {
a0941c8a
             av_dict_set_int(&o->g->format_opts, "channels", o->audio_channels[o->nb_audio_channels - 1].u.i, 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");
80d278a9
     MATCH_PER_TYPE_OPT(codec_names, str,     data_codec_name, ic, "d");
bad953bc
 
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;
bb0344dc
     ic->data_codec_id    = data_codec_name ?
         find_codec_or_die(data_codec_name, AVMEDIA_TYPE_DATA, 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));
bb0344dc
     if (data_codec_name)
         av_format_set_data_codec(ic, find_codec_or_die(data_codec_name, AVMEDIA_TYPE_DATA, 0));
64327aab
 
f5e66827
     ic->flags |= AVFMT_FLAG_NONBLOCK;
     ic->interrupt_callback = int_cb;
 
e971eef8
     if (!av_dict_get(o->g->format_opts, "scan_all_pmts", NULL, AV_DICT_MATCH_CASE)) {
         av_dict_set(&o->g->format_opts, "scan_all_pmts", "1", AV_DICT_DONT_OVERWRITE);
         scan_all_pmts_set = 1;
     }
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);
3e886e73
         if (err == AVERROR_PROTOCOL_NOT_FOUND)
             av_log(NULL, AV_LOG_ERROR, "Did you mean file:%s?\n", filename);
eeddeb65
         exit_program(1);
f5e66827
     }
e971eef8
     if (scan_all_pmts_set)
         av_dict_set(&o->g->format_opts, "scan_all_pmts", NULL, AV_DICT_MATCH_CASE);
7d03732f
     remove_avoptions(&o->g->format_opts, o->g->codec_opts);
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);
eec55e62
         if (ic->nb_streams == 0) {
             avformat_close_input(&ic);
             exit_program(1);
         }
f5e66827
     }
 
0949869e
     if (o->start_time_eof != AV_NOPTS_VALUE) {
         if (ic->duration>0) {
             o->start_time = o->start_time_eof + ic->duration;
         } else
             av_log(NULL, AV_LOG_WARNING, "Cannot use -sseof, duration of %s not known\n", filename);
     }
56ee3f9d
     timestamp = (o->start_time == AV_NOPTS_VALUE) ? 0 : o->start_time;
f5e66827
     /* add the stream start time */
bac7084f
     if (!o->seek_timestamp && ic->start_time != AV_NOPTS_VALUE)
f5e66827
         timestamp += ic->start_time;
 
     /* if seeking requested, we execute it */
56ee3f9d
     if (o->start_time != AV_NOPTS_VALUE) {
b0322e4a
         int64_t seek_timestamp = timestamp;
 
         if (!(ic->iformat->flags & AVFMT_SEEK_TO_PTS)) {
             int dts_heuristic = 0;
             for (i=0; i<ic->nb_streams; i++) {
955b818c
                 const AVCodecParameters *par = ic->streams[i]->codecpar;
                 if (par->video_delay)
b0322e4a
                     dts_heuristic = 1;
             }
             if (dts_heuristic) {
                 seek_timestamp -= 3*AV_TIME_BASE / 23;
             }
         }
         ret = avformat_seek_file(ic, -1, INT64_MIN, seek_timestamp, seek_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;
315f9e92
     f->ts_offset  = o->input_ts_offset - (copy_ts ? (start_at_zero && ic->start_time != AV_NOPTS_VALUE ? ic->start_time : 0) : timestamp);
41d2008b
     f->nb_streams = ic->nb_streams;
     f->rate_emu   = o->rate_emu;
811bd078
     f->accurate_seek = o->accurate_seek;
16b0c929
     f->loop = o->loop;
     f->duration = 0;
     f->time_base = (AVRational){ 1, 1 };
508d6a23
 #if HAVE_PTHREADS
     f->thread_queue_size = o->thread_queue_size > 0 ? o->thread_queue_size : 8;
 #endif
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;
f3a6ad22
         while ((e = av_dict_get(input_streams[i]->decoder_opts, "", e,
e7553f4c
                                 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);
 
6a3833e1
     input_stream_potentially_available = 1;
 
f5e66827
     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;
 }
 
90944ee3
 static int choose_encoder(OptionsContext *o, AVFormatContext *s, OutputStream *ost)
f5e66827
 {
955b818c
     enum AVMediaType type = ost->st->codecpar->codec_type;
f5e66827
     char *codec_name = NULL;
 
90944ee3
     if (type == AVMEDIA_TYPE_VIDEO || type == AVMEDIA_TYPE_AUDIO || type == AVMEDIA_TYPE_SUBTITLE) {
         MATCH_PER_STREAM_OPT(codec_names, str, codec_name, s, ost->st);
         if (!codec_name) {
955b818c
             ost->st->codecpar->codec_id = av_guess_codec(s->oformat, NULL, s->filename,
                                                          NULL, ost->st->codecpar->codec_type);
             ost->enc = avcodec_find_encoder(ost->st->codecpar->codec_id);
90944ee3
             if (!ost->enc) {
                 av_log(NULL, AV_LOG_FATAL, "Automatic encoder selection failed for "
61da882c
                        "output stream #%d:%d. Default encoder for format %s (codec %s) is "
90944ee3
                        "probably disabled. Please choose an encoder manually.\n",
61da882c
                        ost->file_index, ost->index, s->oformat->name,
955b818c
                        avcodec_get_name(ost->st->codecpar->codec_id));
90944ee3
                 return AVERROR_ENCODER_NOT_FOUND;
             }
         } else if (!strcmp(codec_name, "copy"))
             ost->stream_copy = 1;
         else {
955b818c
             ost->enc = find_codec_or_die(codec_name, ost->st->codecpar->codec_type, 1);
             ost->st->codecpar->codec_id = ost->enc->id;
90944ee3
         }
         ost->encoding_needed = !ost->stream_copy;
     } else {
         /* no encoding supported for other media types */
         ost->stream_copy     = 1;
         ost->encoding_needed = 0;
f5e66827
     }
90944ee3
 
     return 0;
f5e66827
 }
 
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;
5ef19590
     const char *bsfs = NULL;
     char *next, *codec_tag = NULL;
f5e66827
     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;
955b818c
     st->codecpar->codec_type = type;
90944ee3
 
     ret = choose_encoder(o, oc, ost);
     if (ret < 0) {
         av_log(NULL, AV_LOG_FATAL, "Error selecting an encoder for stream "
                "%d:%d\n", ost->file_index, ost->index);
         exit_program(1);
     }
38313626
 
     ost->enc_ctx = avcodec_alloc_context3(ost->enc);
     if (!ost->enc_ctx) {
         av_log(NULL, AV_LOG_ERROR, "Error allocating the encoding context.\n");
         exit_program(1);
     }
     ost->enc_ctx->codec_type = type;
 
955b818c
     ost->ref_par = avcodec_parameters_alloc();
     if (!ost->ref_par) {
         av_log(NULL, AV_LOG_ERROR, "Error allocating the encoding parameters.\n");
         exit_program(1);
     }
 
f5e66827
     if (ost->enc) {
4e61a38a
         AVIOContext *s = NULL;
         char *buf = NULL, *arg = NULL, *preset = NULL;
 
9580818c
         ost->encoder_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;
9580818c
                 av_dict_set(&ost->encoder_opts, buf, arg, AV_DICT_DONT_OVERWRITE);
4e61a38a
                 av_free(buf);
             } while (!s->eof_reached);
558cef88
             avio_closep(&s);
4e61a38a
         }
         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 {
9580818c
         ost->encoder_opts = filter_codec_opts(o->g->codec_opts, AV_CODEC_ID_NONE, oc, st, NULL);
f5e66827
     }
 
     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);
 
5ef19590
     MATCH_PER_STREAM_OPT(bitstream_filters, str, bsfs, oc, st);
     while (bsfs && *bsfs) {
         const AVBitStreamFilter *filter;
         char *bsf, *bsf_options_str, *bsf_name;
 
         bsf = av_get_token(&bsfs, ",");
         if (!bsf)
             exit_program(1);
         bsf_name = av_strtok(bsf, "=", &bsf_options_str);
         if (!bsf_name)
             exit_program(1);
 
         filter = av_bsf_get_by_name(bsf_name);
         if (!filter) {
             av_log(NULL, AV_LOG_FATAL, "Unknown bitstream filter %s\n", bsf_name);
eeddeb65
             exit_program(1);
f5e66827
         }
5ef19590
 
         ost->bsf_ctx = av_realloc_array(ost->bsf_ctx,
                                         ost->nb_bitstream_filters + 1,
                                         sizeof(*ost->bsf_ctx));
         if (!ost->bsf_ctx)
             exit_program(1);
 
         ret = av_bsf_alloc(filter, &ost->bsf_ctx[ost->nb_bitstream_filters]);
         if (ret < 0) {
9083e044
             av_log(NULL, AV_LOG_ERROR, "Error allocating a bitstream filter context\n");
5ef19590
             exit_program(1);
         }
 
449dc25f
         ost->nb_bitstream_filters++;
 
5ef19590
         if (bsf_options_str && filter->priv_class) {
449dc25f
             const AVOption *opt = av_opt_next(ost->bsf_ctx[ost->nb_bitstream_filters-1]->priv_data, NULL);
5ef19590
             const char * shorthand[2] = {NULL};
 
             if (opt)
                 shorthand[0] = opt->name;
 
449dc25f
             ret = av_opt_set_from_string(ost->bsf_ctx[ost->nb_bitstream_filters-1]->priv_data, bsf_options_str, shorthand, "=", ":");
5ef19590
             if (ret < 0) {
                 av_log(NULL, AV_LOG_ERROR, "Error parsing options for bitstream filter %s\n", bsf_name);
a5fd3a1a
                 exit_program(1);
             }
5ef19590
         }
         av_freep(&bsf);
f5e66827
 
5ef19590
         if (*bsfs)
             bsfs++;
     }
     if (ost->nb_bitstream_filters) {
         ost->bsf_extradata_updated = av_mallocz_array(ost->nb_bitstream_filters, sizeof(*ost->bsf_extradata_updated));
         if (!ost->bsf_extradata_updated) {
             av_log(NULL, AV_LOG_FATAL, "Bitstream filter memory allocation failed\n");
             exit_program(1);
         }
f5e66827
     }
 
     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);
955b818c
         ost->st->codecpar->codec_tag =
38313626
         ost->enc_ctx->codec_tag = tag;
f5e66827
     }
 
     MATCH_PER_STREAM_OPT(qscale, dbl, qscale, oc, st);
fb722a90
     if (qscale >= 0) {
7c6eb0a1
         ost->enc_ctx->flags |= AV_CODEC_FLAG_QSCALE;
38313626
         ost->enc_ctx->global_quality = FF_QP2LAMBDA * qscale;
f5e66827
     }
 
85d7e02e
     MATCH_PER_STREAM_OPT(disposition, str, ost->disposition, oc, st);
     ost->disposition = av_strdup(ost->disposition);
 
398f015f
     ost->max_muxing_queue_size = 128;
     MATCH_PER_STREAM_OPT(max_muxing_queue_size, i, ost->max_muxing_queue_size, oc, st);
     ost->max_muxing_queue_size *= sizeof(AVPacket);
 
f5e66827
     if (oc->oformat->flags & AVFMT_GLOBALHEADER)
7c6eb0a1
         ost->enc_ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
f5e66827
 
6dbaeed6
     av_dict_copy(&ost->sws_dict, o->g->sws_dict, 0);
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;
01ef127b
         input_streams[source_index]->st->discard = input_streams[source_index]->user_set_discard;
11a1033c
     }
76d23f40
     ost->last_mux_dts = AV_NOPTS_VALUE;
f5e66827
 
398f015f
     ost->muxing_queue = av_fifo_alloc(8 * sizeof(AVPacket));
     if (!ost->muxing_queue)
         exit_program(1);
 
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
 
955b818c
     return av_strdup(st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO ?
a4208b9b
                      "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;
38313626
     video_enc = ost->enc_ctx;
f5e66827
 
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
     }
7a649e07
     if (frame_rate && video_sync_method == VSYNC_PASSTHROUGH)
         av_log(NULL, AV_LOG_ERROR, "Using -vsync 0 and -r can produce invalid output files\n");
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
             }
             video_enc->rc_override =
2d7fd4cc
                 av_realloc_array(video_enc->rc_override,
                                  i + 1, sizeof(RcOverride));
81688e68
             if (!video_enc->rc_override) {
                 av_log(NULL, AV_LOG_FATAL, "Could not (re)allocate memory for rc_override.\n");
7efabffc
                 exit_program(1);
81688e68
             }
f5e66827
             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;
 
11a1033c
         if (do_psnr)
94d68a41
             video_enc->flags|= AV_CODEC_FLAG_PSNR;
11a1033c
 
f5e66827
         /* two pass mode */
038c0b1e
         MATCH_PER_STREAM_OPT(pass, i, do_pass, oc, st);
f5e66827
         if (do_pass) {
11a1033c
             if (do_pass & 1) {
7c6eb0a1
                 video_enc->flags |= AV_CODEC_FLAG_PASS1;
d5ec1ddf
                 av_dict_set(&ost->encoder_opts, "flags", "+pass1", AV_DICT_APPEND);
11a1033c
             }
             if (do_pass & 2) {
7c6eb0a1
                 video_enc->flags |= AV_CODEC_FLAG_PASS2;
d5ec1ddf
                 av_dict_set(&ost->encoder_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
 
6d5d9246
         if (do_pass) {
             char logfilename[1024];
             FILE *f;
 
             snprintf(logfilename, sizeof(logfilename), "%s-%d.log",
                      ost->logfile_prefix ? ost->logfile_prefix :
                                            DEFAULT_PASS_LOGFILENAME_PREFIX,
                      i);
             if (!strcmp(ost->enc->name, "libx264")) {
                 av_dict_set(&ost->encoder_opts, "stats", logfilename, AV_DICT_DONT_OVERWRITE);
             } else {
94d68a41
                 if (video_enc->flags & AV_CODEC_FLAG_PASS2) {
bd2ab27c
                     char  *logbuffer = read_file(logfilename);
 
                     if (!logbuffer) {
6d5d9246
                         av_log(NULL, AV_LOG_FATAL, "Error reading log file '%s' for pass-2 encoding\n",
                                logfilename);
                         exit_program(1);
                     }
                     video_enc->stats_in = logbuffer;
                 }
94d68a41
                 if (video_enc->flags & AV_CODEC_FLAG_PASS1) {
247f4d1f
                     f = av_fopen_utf8(logfilename, "wb");
                     if (!f) {
                         av_log(NULL, AV_LOG_FATAL,
                                "Cannot write log file '%s' for pass-1 encoding: %s\n",
                                logfilename, strerror(errno));
                         exit_program(1);
                     }
                     ost->logfile = f;
                 }
6d5d9246
             }
         }
 
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;
 
38313626
     audio_enc = ost->enc_ctx;
f5e66827
     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];
8803b970
             if ((map->ofile_idx   == -1 || ost->file_index == map->ofile_idx) &&
11a1033c
                 (map->ostream_idx == -1 || ost->st->index  == map->ostream_idx)) {
8803b970
                 InputStream *ist;
 
                 if (map->channel_idx == -1) {
                     ist = NULL;
                 } else if (ost->source_index < 0) {
                     av_log(NULL, AV_LOG_FATAL, "Cannot determine input stream for channel mapping %d.%d\n",
11a1033c
                            ost->file_index, ost->st->index);
8803b970
                     continue;
                 } else {
                     ist = input_streams[ost->source_index];
                 }
 
                 if (!ist || (ist->file_index == map->file_idx && ist->st->index == map->stream_idx)) {
d3a22491
                     if (av_reallocp_array(&ost->audio_channels_map,
                                           ost->audio_channels_mapped + 1,
                                           sizeof(*ost->audio_channels_map)
                                           ) < 0 )
                         exit_program(1);
 
                     ost->audio_channels_map[ost->audio_channels_mapped++] = map->channel_idx;
8803b970
                 }
11a1033c
             }
         }
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;
 }
 
18833daf
 static OutputStream *new_unknown_stream(OptionsContext *o, AVFormatContext *oc, int source_index)
 {
     OutputStream *ost;
 
     ost = new_output_stream(o, oc, AVMEDIA_TYPE_UNKNOWN, source_index);
     if (!ost->stream_copy) {
         av_log(NULL, AV_LOG_FATAL, "Unknown stream encoding not supported yet (only streamcopy)\n");
         exit_program(1);
     }
 
     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;
38313626
     subtitle_enc = ost->enc_ctx;
f5e66827
 
     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;
3ff39901
         const char *enc_config;
11a1033c
 
955b818c
         codec = avcodec_find_encoder(ic->streams[i]->codecpar->codec_id);
e113692c
         if (!codec) {
955b818c
             av_log(s, AV_LOG_ERROR, "no encoder found for codec id %i\n", ic->streams[i]->codecpar->codec_id);
e113692c
             return AVERROR(EINVAL);
         }
2657f00d
         if (codec->type == AVMEDIA_TYPE_AUDIO)
             opt_audio_codec(o, "c:a", codec->name);
         else if (codec->type == AVMEDIA_TYPE_VIDEO)
             opt_video_codec(o, "c:v", codec->name);
11a1033c
         ost   = new_output_stream(o, s, codec->type, -1);
         st    = ost->st;
 
3ff39901
         avcodec_get_context_defaults3(st->codec, codec);
         enc_config = av_stream_get_recommended_encoder_configuration(ic->streams[i]);
         if (enc_config) {
             AVDictionary *opts = NULL;
             av_dict_parse_string(&opts, enc_config, "=", ",", 0);
             av_opt_set_dict2(st->codec, &opts, AV_OPT_SEARCH_CHILDREN);
             av_dict_free(&opts);
         }
11a1033c
 
955b818c
         if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && !ost->stream_copy)
11a1033c
             choose_sample_fmt(st, codec);
955b818c
         else if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && !ost->stream_copy)
             choose_pixel_fmt(st, st->codec, codec, st->codecpar->format);
3ff39901
         avcodec_copy_context(ost->enc_ctx, st->codec);
         if (enc_config)
             av_dict_parse_string(&ost->encoder_opts, enc_config, "=", ",", 0);
11a1033c
     }
 
     avformat_close_input(&ic);
f7c46d25
     return err;
11a1033c
 }
 
f5e66827
 static void init_output_filter(OutputFilter *ofilter, OptionsContext *o,
                                AVFormatContext *oc)
 {
     OutputStream *ost;
 
6d592fbd
     switch (ofilter->type) {
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
     avfilter_inout_free(&ofilter->out_tmp);
 }
 
6d592fbd
 static int init_complex_filters(void)
 {
     int i, ret = 0;
 
     for (i = 0; i < nb_filtergraphs; i++) {
         ret = init_complex_filtergraph(filtergraphs[i]);
         if (ret < 0)
             return ret;
     }
     return 0;
 }
 
f5e66827
 static int configure_complex_filters(void)
 {
     int i, ret = 0;
 
     for (i = 0; i < nb_filtergraphs; i++)
73c6ec6d
         if (!filtergraph_is_simple(filtergraphs[i]) &&
f5e66827
             (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
 
 
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) {
8c4ca4aa
             av_log(NULL, AV_LOG_ERROR, "-to value smaller than -ss; aborting.\n");
             exit_program(1);
1924a61a
         } 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;
 
6d592fbd
             switch (ofilter->type) {
f5e66827
             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];
955b818c
                 if(ist->st->codecpar->codec_type == ost->st->codecpar->codec_type){
11a1033c
                     ost->sync_ist= ist;
                     ost->source_index= i;
955b818c
                     if(ost->st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) ost->avfilter = av_strdup("anull");
                     if(ost->st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) ost->avfilter = av_strdup("null");
11a1033c
                     ist->discard = 0;
01ef127b
                     ist->st->discard = ist->user_set_discard;
11a1033c
                     break;
                 }
             }
             if(!ost->sync_ist){
955b818c
                 av_log(NULL, AV_LOG_FATAL, "Missing %s stream which is required by this ffm\n", av_get_media_type_string(ost->st->codecpar->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 */
956f4087
         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];
955b818c
                 new_area = ist->st->codecpar->width * ist->st->codecpar->height + 100000000*!!ist->st->codec_info_nb_frames;
de73ae6b
                 if((qcr!=MKTAG('A', 'P', 'I', 'C')) && (ist->st->disposition & AV_DISPOSITION_ATTACHED_PIC))
                     new_area = 1;
955b818c
                 if (ist->st->codecpar->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 */
956f4087
         if (!o->audio_disable && av_guess_codec(oc->oformat, NULL, filename, NULL, AVMEDIA_TYPE_AUDIO) != AV_CODEC_ID_NONE) {
ae2cb929
             int best_score = 0, idx = -1;
f5e66827
             for (i = 0; i < nb_input_streams; i++) {
ae2cb929
                 int score;
f5e66827
                 ist = input_streams[i];
955b818c
                 score = ist->st->codecpar->channels + 100000000*!!ist->st->codec_info_nb_frames;
                 if (ist->st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
ae2cb929
                     score > best_score) {
                     best_score = score;
f5e66827
                     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");
25bcf24d
         if (!o->subtitle_disable && (avcodec_find_encoder(oc->oformat->subtitle_codec) || subtitle_codec_name)) {
f5e66827
             for (i = 0; i < nb_input_streams; i++)
955b818c
                 if (input_streams[i]->st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE) {
7d585bc9
                     AVCodecDescriptor const *input_descriptor =
955b818c
                         avcodec_descriptor_get(input_streams[i]->st->codecpar->codec_id);
7d585bc9
                     AVCodecDescriptor const *output_descriptor = NULL;
                     AVCodec const *output_codec =
                         avcodec_find_encoder(oc->oformat->subtitle_codec);
                     int input_props = 0, output_props = 0;
                     if (output_codec)
                         output_descriptor = avcodec_descriptor_get(output_codec->id);
                     if (input_descriptor)
                         input_props = input_descriptor->props & (AV_CODEC_PROP_TEXT_SUB | AV_CODEC_PROP_BITMAP_SUB);
                     if (output_descriptor)
                         output_props = output_descriptor->props & (AV_CODEC_PROP_TEXT_SUB | AV_CODEC_PROP_BITMAP_SUB);
                     if (subtitle_codec_name ||
                         input_props & output_props ||
                         // Map dvb teletext which has neither property to any output subtitle encoder
                         input_descriptor && output_descriptor &&
                         (!input_descriptor->props ||
                          !output_descriptor->props)) {
                         new_subtitle_stream(o, oc, i);
                         break;
                     }
f5e66827
                 }
         }
bbb06345
         /* Data only if codec id match */
         if (!o->data_disable ) {
             enum AVCodecID codec_id = av_guess_codec(oc->oformat, NULL, filename, NULL, AVMEDIA_TYPE_DATA);
             for (i = 0; codec_id != AV_CODEC_ID_NONE && i < nb_input_streams; i++) {
955b818c
                 if (input_streams[i]->st->codecpar->codec_type == AVMEDIA_TYPE_DATA
                     && input_streams[i]->st->codecpar->codec_id == codec_id )
bbb06345
                     new_data_stream(o, oc, i);
             }
         }
f5e66827
     } 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];
955b818c
                 if(o->subtitle_disable && ist->st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE)
11a1033c
                     continue;
955b818c
                 if(o->   audio_disable && ist->st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)
11a1033c
                     continue;
955b818c
                 if(o->   video_disable && ist->st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
11a1033c
                     continue;
955b818c
                 if(o->    data_disable && ist->st->codecpar->codec_type == AVMEDIA_TYPE_DATA)
11a1033c
                     continue;
 
29cc0a17
                 ost = NULL;
955b818c
                 switch (ist->st->codecpar->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;
18833daf
                 case AVMEDIA_TYPE_UNKNOWN:
                     if (copy_unknown_streams) {
                         ost = new_unknown_stream   (o, oc, src_idx);
                         break;
                     }
f5e66827
                 default:
592b053c
                     av_log(NULL, ignore_unknown_streams ? AV_LOG_WARNING : AV_LOG_FATAL,
a2aff269
                            "Cannot map stream #%d:%d - unsupported type.\n",
f5e66827
                            map->file_index, map->stream_index);
100df10b
                     if (!ignore_unknown_streams) {
                         av_log(NULL, AV_LOG_FATAL,
0b9d6368
                                "If you want unsupported types ignored instead "
18833daf
                                "of failing, please use the -ignore_unknown option\n"
                                "If you want them copied, please use -copy_unknown\n");
a2aff269
                         exit_program(1);
100df10b
                     }
f5e66827
                 }
29cc0a17
                 if (ost)
                     ost->sync_ist = input_streams[  input_files[map->sync_file_index]->ist_index
                                                   + map->sync_stream_index];
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);
4a05d2ed
         ost->stream_copy               = 0;
f5e66827
         ost->attachment_filename       = o->attachments[i];
955b818c
         ost->st->codecpar->extradata      = attachment;
         ost->st->codecpar->extradata_size = len;
f5e66827
 
         p = strrchr(o->attachments[i], '/');
         av_dict_set(&ost->st->metadata, "filename", (p && *p) ? p + 1 : o->attachments[i], AV_DICT_DONT_OVERWRITE);
558cef88
         avio_closep(&pb);
f5e66827
     }
 
4a05d2ed
 #if FF_API_LAVF_AVCTX
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
     }
4a05d2ed
 #endif
951a03b3
 
1959351a
     if (!oc->nb_streams && !(oc->oformat->flags & AVFMT_NOSTREAMS)) {
         av_dump_format(oc, nb_output_files - 1, oc->filename, 1);
         av_log(NULL, AV_LOG_ERROR, "Output file #%d does not contain any stream\n", nb_output_files - 1);
         exit_program(1);
     }
 
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;
9580818c
         while ((e = av_dict_get(output_streams[i]->encoder_opts, "", e,
e7553f4c
                                 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);
11aab8d6
         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;
11aab8d6
 
 
e7553f4c
         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);
 
90944ee3
     /* set the decoding_needed flags and create simple filtergraphs */
59245e0c
     for (i = of->ost_index; i < nb_output_streams; i++) {
         OutputStream *ost = output_streams[i];
 
         if (ost->encoding_needed && ost->source_index >= 0) {
             InputStream *ist = input_streams[ost->source_index];
db3e12a8
             ist->decoding_needed |= DECODING_FOR_OST;
73c6ec6d
 
955b818c
             if (ost->st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO ||
                 ost->st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
73c6ec6d
                 err = init_simple_filtergraph(ist, ost);
                 if (err < 0) {
                     av_log(NULL, AV_LOG_ERROR,
                            "Error initializing a simple filtergraph between streams "
                            "%d:%d->%d:%d\n", ist->file_index, ost->source_index,
                            nb_output_files - 1, ost->st->index);
                     exit_program(1);
                 }
             }
59245e0c
         }
     }
 
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
         }
     }
 
6a3833e1
     if (!(oc->oformat->flags & AVFMT_NOSTREAMS) && !input_stream_potentially_available) {
         av_log(NULL, AV_LOG_ERROR,
                "No input streams but output needs an input stream\n");
         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) {
a0941c8a
         av_dict_set_int(&of->opts, "preload", o->mux_preload*AV_TIME_BASE, 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);
a1acae04
             if (!output_streams[i]->stream_copy) {
be2bbc52
                 av_dict_set(&output_streams[i]->st->metadata, "encoder", NULL, 0);
a1acae04
                 if (ist->autorotate)
                     av_dict_set(&output_streams[i]->st->metadata, "rotate", NULL, 0);
             }
f5e66827
         }
 
6e448fb9
     /* process manually set programs */
     for (i = 0; i < o->nb_program; i++) {
         const char *p = o->program[i].u.str;
         int progid = i+1;
         AVProgram *program;
 
         while(*p) {
             const char *p2 = av_get_token(&p, ":");
a25c5dbb
             const char *to_dealloc = p2;
6e448fb9
             char *key;
             if (!p2)
                 break;
a25c5dbb
 
6e448fb9
             if(*p) p++;
 
             key = av_get_token(&p2, "=");
a25c5dbb
             if (!key || !*p2) {
                 av_freep(&to_dealloc);
                 av_freep(&key);
6e448fb9
                 break;
a25c5dbb
             }
6e448fb9
             p2++;
 
             if (!strcmp(key, "program_num"))
                 progid = strtol(p2, NULL, 0);
a25c5dbb
             av_freep(&to_dealloc);
             av_freep(&key);
6e448fb9
         }
 
         program = av_new_program(oc, progid);
 
         p = o->program[i].u.str;
         while(*p) {
             const char *p2 = av_get_token(&p, ":");
a25c5dbb
             const char *to_dealloc = p2;
6e448fb9
             char *key;
             if (!p2)
                 break;
             if(*p) p++;
 
             key = av_get_token(&p2, "=");
             if (!key) {
                 av_log(NULL, AV_LOG_FATAL,
                        "No '=' character in program string %s.\n",
                        p2);
                 exit_program(1);
             }
             if (!*p2)
                 exit_program(1);
             p2++;
 
             if (!strcmp(key, "title")) {
                 av_dict_set(&program->metadata, "title", p2, 0);
             } else if (!strcmp(key, "program_num")) {
             } else if (!strcmp(key, "st")) {
                 int st_num = strtol(p2, NULL, 0);
                 av_program_add_stream_index(oc, progid, st_num);
             } else {
                 av_log(NULL, AV_LOG_FATAL, "Unknown program key %s.\n", key);
                 exit_program(1);
             }
a25c5dbb
             av_freep(&to_dealloc);
             av_freep(&key);
6e448fb9
         }
     }
 
f5e66827
     /* 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++) {
57e38043
                 ost = output_streams[nb_output_streams - oc->nb_streams + j];
f5e66827
                 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);
57e38043
                     if (!strcmp(o->metadata[i].u.str, "rotate")) {
                         ost->rotate_overridden = 1;
                     }
f5e66827
                 } 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;
74658a8b
             case 'p':
                 if (index < 0 || index >= oc->nb_programs) {
                     av_log(NULL, AV_LOG_FATAL, "Invalid program index %d in metadata specifier.\n", index);
                     exit_program(1);
                 }
                 m = &oc->programs[index]->metadata;
                 break;
f5e66827
             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++) {
955b818c
                     AVStream *st = input_files[j]->ctx->streams[i];
                     if (st->codecpar->codec_type != AVMEDIA_TYPE_VIDEO)
f5e66827
                         continue;
955b818c
                     fr = st->time_base.den * 1000 / st->time_base.num;
f5e66827
                     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);
7a67ab5c
         opt_default(NULL, "g", norm == PAL ? "15" : "18");
f5e66827
 
7a67ab5c
         opt_default(NULL, "b:v", "1150000");
2ce6e419
         opt_default(NULL, "maxrate:v", "1150000");
         opt_default(NULL, "minrate:v", "1150000");
         opt_default(NULL, "bufsize:v", "327680"); // 40*1024*8;
f5e66827
 
7a67ab5c
         opt_default(NULL, "b:a", "224000");
f5e66827
         parse_option(o, "ar", "44100", options);
         parse_option(o, "ac", "2", options);
 
7a67ab5c
         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);
7a67ab5c
         opt_default(NULL, "g", norm == PAL ? "15" : "18");
f5e66827
 
7a67ab5c
         opt_default(NULL, "b:v", "2040000");
2ce6e419
         opt_default(NULL, "maxrate:v", "2516000");
         opt_default(NULL, "minrate:v", "0"); // 1145000;
         opt_default(NULL, "bufsize:v", "1835008"); // 224*1024*8;
7a67ab5c
         opt_default(NULL, "scan_offset", "1");
f5e66827
 
7a67ab5c
         opt_default(NULL, "b:a", "224000");
f5e66827
         parse_option(o, "ar", "44100", options);
 
7a67ab5c
         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);
7a67ab5c
         opt_default(NULL, "g", norm == PAL ? "15" : "18");
f5e66827
 
7a67ab5c
         opt_default(NULL, "b:v", "6000000");
2ce6e419
         opt_default(NULL, "maxrate:v", "9000000");
         opt_default(NULL, "minrate:v", "0"); // 1500000;
         opt_default(NULL, "bufsize:v", "1835008"); // 224*1024*8;
f5e66827
 
7a67ab5c
         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
 
7a67ab5c
         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);
     }
f5245a9c
 
7a67ab5c
     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);
f5245a9c
 
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);
 
a9b2a511
     if (!today) { // maybe tomorrow
6cfaa51a
         av_log(NULL, AV_LOG_FATAL, "Unable to get current time: %s\n", strerror(errno));
a9b2a511
         exit_program(1);
     }
8e91d965
 
f5e66827
     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;
f02a4408
 
     if(!strcmp(opt, "ab")){
         av_dict_set(&o->g->codec_opts, "b:a", arg, 0);
         return 0;
     } else if(!strcmp(opt, "b")){
11a1033c
         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);
6a3833e1
 
     input_stream_potentially_available = 1;
 
a4208b9b
     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;
6a3833e1
 
     input_stream_potentially_available = 1;
 
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"
b5e4f393
            "    -h type=name -- print all options for the named decoder/encoder/demuxer/muxer/filter\n"
6e3857fa
            "    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[] = {
46cd1699
     [GROUP_OUTFILE] = { "output url",  NULL, OPT_OUTPUT },
     [GROUP_INFILE]  = { "input url",   "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;
     }
 
1f7d5860
     /* configure terminal and setup signal handlers */
     term_init();
 
77bd1bc7
     /* 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;
     }
 
be101bc1
     /* create the complex filtergraphs */
6d592fbd
     ret = init_complex_filters();
be101bc1
     if (ret < 0) {
6d592fbd
         av_log(NULL, AV_LOG_FATAL, "Error initializing complex filters.\n");
be101bc1
         goto fail;
     }
 
77bd1bc7
     /* 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;
     }
 
6d592fbd
     /* configure the complex filtergraphs */
     ret = configure_complex_filters();
     if (ret < 0) {
         av_log(NULL, AV_LOG_FATAL, "Error configuring complex filters.\n");
         goto fail;
     }
 
77bd1bc7
 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" },
a2aff269
     { "ignore_unknown", OPT_BOOL,                                    {              &ignore_unknown_streams },
         "Ignore unknown stream types" },
18833daf
     { "copy_unknown",   OPT_BOOL | OPT_EXPERT,                       {              &copy_unknown_streams },
         "Copy unknown stream types" },
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" },
f4ada6dc
     { "sseof",          HAS_ARG | OPT_TIME | OPT_OFFSET |
                         OPT_INPUT | OPT_OUTPUT,                      { .off = OFFSET(start_time_eof) },
         "set the start time offset relative to EOF", "time_off" },
bac7084f
     { "seek_timestamp", HAS_ARG | OPT_INT | OPT_OFFSET |
                         OPT_INPUT,                                   { .off = OFFSET(seek_timestamp) },
         "enable/disable seeking by timestamp with -ss" },
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" },
107e4da4
     { "timestamp",      HAS_ARG | OPT_PERFILE | OPT_OUTPUT,          { .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" },
8f948b62
     { "program",        HAS_ARG | OPT_STRING | OPT_SPEC | OPT_OUTPUT, { .off = OFFSET(program) },
         "add program with specified streams", "title=string:st=number..." },
9d3009c6
     { "dframes",        HAS_ARG | OPT_PERFILE | OPT_EXPERT |
                         OPT_OUTPUT,                                  { .func_arg = opt_data_frames },
37425fcb
         "set the number of data frames to output", "number" },
8fc83fb0
     { "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 },
a4188c9c
         "specify target file type (\"vcd\", \"svcd\", \"dvd\", \"dv\" or \"dv50\" "
         "with optional prefixes \"pal-\", \"ntsc-\" or \"film-\")", "type" },
4c96985a
     { "vsync",          HAS_ARG | OPT_EXPERT,                        { .func_arg = opt_vsync },
8fc83fb0
         "video sync method", "" },
77f326dc
     { "frame_drop_threshold", HAS_ARG | OPT_FLOAT | OPT_EXPERT,      { &frame_drop_threshold },
         "frame drop threshold", "" },
8fc83fb0
     { "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" },
315f9e92
     { "start_at_zero",  OPT_BOOL | OPT_EXPERT,                       { &start_at_zero },
         "shift input timestamps to start at 0 when using copyts" },
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" },
ddc6bd8c
     { "abort_on",       HAS_ARG | OPT_EXPERT,                        { .func_arg = opt_abort_on },
         "abort on the specified condition flags", "flags" },
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) },
37425fcb
         "set the number of frames to output", "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" },
dbb03b8e
     { "stream_loop", OPT_INT | HAS_ARG | OPT_EXPERT | OPT_INPUT |
16b0c929
                         OPT_OFFSET,                                  { .off = OFFSET(loop) }, "set number of times input stream shall be looped", "loop count" },
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." },
01ef127b
     { "discard",        OPT_STRING | HAS_ARG | OPT_SPEC |
                         OPT_INPUT,                                   { .off = OFFSET(discard) },
         "discard", "" },
85d7e02e
     { "disposition",    OPT_STRING | HAS_ARG | OPT_SPEC |
                         OPT_OUTPUT,                                  { .off = OFFSET(disposition) },
         "disposition", "" },
508d6a23
     { "thread_queue_size", HAS_ARG | OPT_INT | OPT_OFFSET | OPT_EXPERT | OPT_INPUT,
                                                                      { .off = OFFSET(thread_queue_size) },
         "set the maximum number of queued packets from the demuxer" },
f5e66827
 
     /* video options */
9d3009c6
     { "vframes",      OPT_VIDEO | HAS_ARG  | OPT_PERFILE | OPT_OUTPUT,           { .func_arg = opt_video_frames },
37425fcb
         "set the number of video frames to output", "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" },
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" },
4c96985a
     { "vstats",       OPT_VIDEO | OPT_EXPERT ,                                   { .func_arg = opt_vstats },
8fc83fb0
         "dump video coding statistics to file" },
4c96985a
     { "vstats_file",  OPT_VIDEO | HAS_ARG | OPT_EXPERT ,                         { .func_arg = opt_vstats_file },
8fc83fb0
         "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", "" },
9d3009c6
     { "vtag",         OPT_VIDEO | HAS_ARG | OPT_EXPERT  | OPT_PERFILE |
27565ace
                       OPT_INPUT | 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" },
f02a4408
     { "ab",           OPT_VIDEO | HAS_ARG | OPT_PERFILE | OPT_OUTPUT,            { .func_arg = opt_bitrate },
         "audio bitrate (please use -b:a)", "bitrate" },
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) },
b144008c
         "select a device for HW acceleration", "devicename" },
5d273d3e
     { "hwaccel_output_format", OPT_VIDEO | OPT_STRING | HAS_ARG | OPT_EXPERT |
172d3568
                           OPT_SPEC | OPT_INPUT,                                  { .off = OFFSET(hwaccel_output_formats) },
         "select output format used with HW accelerated decoding", "format" },
11d923d4
 #if CONFIG_VDA || CONFIG_VIDEOTOOLBOX
     { "videotoolbox_pixfmt", HAS_ARG | OPT_STRING | OPT_EXPERT, { &videotoolbox_pixfmt}, "" },
 #endif
da0e7695
     { "hwaccels",         OPT_EXIT,                                              { .func_arg = show_hwaccels },
         "show available HW acceleration methods" },
16302246
     { "autorotate",       HAS_ARG | OPT_BOOL | OPT_SPEC |
                           OPT_EXPERT | OPT_INPUT,                                { .off = OFFSET(autorotate) },
         "automatically insert correct rotate filters" },
5d273d3e
     { "hwaccel_lax_profile_check", OPT_BOOL | OPT_EXPERT,                        { &hwaccel_lax_profile_check},
         "attempt to decode anyway if HW accelerated decoder's supported profiles do not exactly match the stream" },
f5e66827
 
     /* audio options */
9d3009c6
     { "aframes",        OPT_AUDIO | HAS_ARG  | OPT_PERFILE | OPT_OUTPUT,           { .func_arg = opt_audio_frames },
37425fcb
         "set the number of audio frames to output", "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", "" },
4c96985a
     { "sdp_file", HAS_ARG | OPT_EXPERT | OPT_OUTPUT, { .func_arg = opt_sdp_file },
cc63da12
         "specify a file in which to print sdp information", "file" },
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
 
398f015f
     { "max_muxing_queue_size", HAS_ARG | OPT_INT | OPT_SPEC | OPT_EXPERT | OPT_OUTPUT, { .off = OFFSET(max_muxing_queue_size) },
         "maximum number of packets that can be buffered while waiting for all streams to initialize", "packets" },
 
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
 
5d273d3e
 #if CONFIG_VAAPI
     { "vaapi_device", HAS_ARG | OPT_EXPERT, { .func_arg = opt_vaapi_device },
         "set VAAPI hardware device (DRM path or X11 display name)", "device" },
 #endif
 
f5e66827
     { NULL, },
 };