/* * ffmpeg option parsing * * This file is part of FFmpeg. * * FFmpeg is free software; you can redistribute it and/or * 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. * * FFmpeg is distributed in the hope that it will be useful, * 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 * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include <stdint.h> #include "ffmpeg.h"#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"#include "libavutil/channel_layout.h"#include "libavutil/intreadwrite.h"#include "libavutil/fifo.h"#include "libavutil/mathematics.h"#include "libavutil/opt.h"#include "libavutil/parseutils.h"#include "libavutil/pixdesc.h"#include "libavutil/pixfmt.h" #define DEFAULT_PASS_LOGFILENAME_PREFIX "ffmpeg2pass" #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)\ exit_program(1);\ }\} #define MATCH_PER_TYPE_OPT(name, type, outvar, fmtctx, mediatype)\{\ int i;\ for (i = 0; i < o->nb_ ## name; i++) {\ char *spec = o->name[i].specifier;\ if (!strcmp(spec, mediatype))\ outvar = o->name[i].u.type;\ }\} const HWAccel hwaccels[] = {#if HAVE_VDPAU_X11 { "vdpau", vdpau_init, HWACCEL_VDPAU, AV_PIX_FMT_VDPAU },#endif#if HAVE_DXVA2_LIB { "dxva2", dxva2_init, HWACCEL_DXVA2, AV_PIX_FMT_DXVA2_VLD },#endif#if CONFIG_VDA { "vda", videotoolbox_init, HWACCEL_VDA, AV_PIX_FMT_VDA },#endif#if CONFIG_VIDEOTOOLBOX { "videotoolbox", videotoolbox_init, HWACCEL_VIDEOTOOLBOX, AV_PIX_FMT_VIDEOTOOLBOX },#endif#if CONFIG_LIBMFX { "qsv", qsv_init, HWACCEL_QSV, AV_PIX_FMT_QSV },#endif#if CONFIG_VAAPI { "vaapi", vaapi_decode_init, HWACCEL_VAAPI, AV_PIX_FMT_VAAPI },#endif#if CONFIG_CUVID { "cuvid", cuvid_init, HWACCEL_CUVID, AV_PIX_FMT_CUDA },#endif { 0 },};int hwaccel_lax_profile_check = 0;AVBufferRef *hw_device_ctx; char *vstats_filename;char *sdp_filename; float audio_drift_threshold = 0.1;float dts_delta_threshold = 10;float dts_error_threshold = 3600*30; int audio_volume = 256;int audio_sync_method = 0;int video_sync_method = VSYNC_AUTO;float frame_drop_threshold = 0;int do_deinterlace = 0;int do_benchmark = 0;int do_benchmark_all = 0;int do_hex_dump = 0;int do_pkt_dump = 0;int copy_ts = 0;int start_at_zero = 0;int copy_tb = -1;int debug_ts = 0;int exit_on_error = 0;int abort_on_flags = 0;int print_stats = -1;int qp_hist = 0;int stdin_interaction = 1;int frame_bits_per_raw_sample = 0;float max_error_rate = 2.0/3;int filter_nbthreads = 0;int filter_complex_nbthreads = 0;int vstats_version = 2; static int intra_only = 0;static int file_overwrite = 0;static int no_file_overwrite = 0;static int do_psnr = 0;static int input_sync;static int override_ffserver = 0;static int input_stream_potentially_available = 0;static int ignore_unknown_streams = 0;static int copy_unknown_streams = 0; static void uninit_options(OptionsContext *o){ 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); av_freep(&o->audio_channel_maps); av_freep(&o->streamid_map); av_freep(&o->attachments);} static void init_options(OptionsContext *o){ memset(o, 0, sizeof(*o)); o->stop_time = INT64_MAX; o->mux_max_delay = 0.7; o->start_time = AV_NOPTS_VALUE; o->start_time_eof = AV_NOPTS_VALUE; o->recording_time = INT64_MAX; o->limit_filesize = UINT64_MAX; o->chapters_input_file = INT_MAX; o->accurate_seek = 1;} 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;} /* 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;} 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);} static int opt_sameq(void *optctx, const char *opt, const char *arg){ av_log(NULL, AV_LOG_ERROR, "Option '%s' was removed. " "If you are looking for an option to preserve the quality (which is not " "what -%s was for), use -qscale 0 or an equivalent quality factor option.\n", opt, opt); return AVERROR(EINVAL);} static int opt_video_channel(void *optctx, const char *opt, const char *arg){ av_log(NULL, AV_LOG_WARNING, "This option is deprecated, use -channel.\n"); return opt_default(optctx, "channel", arg);} static int opt_video_standard(void *optctx, const char *opt, const char *arg){ av_log(NULL, AV_LOG_WARNING, "This option is deprecated, use -standard.\n"); return opt_default(optctx, "standard", arg);} static int opt_audio_codec(void *optctx, const char *opt, const char *arg){ OptionsContext *o = optctx; return parse_option(o, "codec:a", arg, options);} static int opt_video_codec(void *optctx, const char *opt, const char *arg){ OptionsContext *o = optctx; return parse_option(o, "codec:v", arg, options);} static int opt_subtitle_codec(void *optctx, const char *opt, const char *arg){ OptionsContext *o = optctx; return parse_option(o, "codec:s", arg, options);} static int opt_data_codec(void *optctx, const char *opt, const char *arg){ OptionsContext *o = optctx; return parse_option(o, "codec:d", arg, options);} static int opt_map(void *optctx, const char *opt, const char *arg){ OptionsContext *o = optctx; StreamMap *m = NULL; int i, negative = 0, file_idx; int sync_file_idx = -1, sync_stream_idx = 0; char *p, *sync; char *map; char *allow_unused; if (*arg == '-') { negative = 1; arg++; } map = av_strdup(arg); if (!map) return AVERROR(ENOMEM); /* 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); exit_program(1); } 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); exit_program(1); } } if (map[0] == '[') { /* this mapping refers to lavfi output */ const char *c = map + 1; GROW_ARRAY(o->stream_maps, o->nb_stream_maps); 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); exit_program(1); } } else { if (allow_unused = strchr(map, '?')) *allow_unused = 0; 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); exit_program(1); } 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; GROW_ARRAY(o->stream_maps, o->nb_stream_maps); 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) { 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); } } av_freep(&map); return 0;} static int opt_attach(void *optctx, const char *opt, const char *arg){ OptionsContext *o = optctx; GROW_ARRAY(o->attachments, o->nb_attachments); o->attachments[o->nb_attachments - 1] = arg; return 0;} static int opt_map_channel(void *optctx, const char *opt, const char *arg){ OptionsContext *o = optctx; int n; AVStream *st; AudioChannelMap *m; GROW_ARRAY(o->audio_channel_maps, o->nb_audio_channel_maps); 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"); exit_program(1); } 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); exit_program(1); } 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); exit_program(1); } st = input_files[m->file_idx]->ctx->streams[m->stream_idx]; if (st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO) { av_log(NULL, AV_LOG_FATAL, "mapchan: stream #%d.%d is not an audio stream.\n", m->file_idx, m->stream_idx); exit_program(1); } if (m->channel_idx < 0 || m->channel_idx >= st->codecpar->channels) { av_log(NULL, AV_LOG_FATAL, "mapchan: invalid audio channel #%d.%d.%d\n", m->file_idx, m->stream_idx, m->channel_idx); exit_program(1); } return 0;} static int opt_sdp_file(void *optctx, const char *opt, const char *arg){ av_free(sdp_filename); sdp_filename = av_strdup(arg); return 0;} #if CONFIG_VAAPIstatic 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 /** * Parse a metadata specifier passed as 'arg' parameter. * @param arg metadata string to parse * @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); exit_program(1); } *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); exit_program(1); } } else *type = 'g';} static int copy_metadata(char *outspec, char *inspec, AVFormatContext *oc, AVFormatContext *ic, OptionsContext *o)Lines 1–500 of 3705. Load more
/* * ffmpeg option parsing * * This file is part of FFmpeg. * * FFmpeg is free software; you can redistribute it and/or * 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. * * FFmpeg is distributed in the hope that it will be useful, * 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 * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include <stdint.h> #include "ffmpeg.h" #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" #include "libavutil/channel_layout.h" #include "libavutil/intreadwrite.h" #include "libavutil/fifo.h" #include "libavutil/mathematics.h" #include "libavutil/opt.h" #include "libavutil/parseutils.h" #include "libavutil/pixdesc.h" #include "libavutil/pixfmt.h" #define DEFAULT_PASS_LOGFILENAME_PREFIX "ffmpeg2pass" #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)\ exit_program(1);\ }\ } #define MATCH_PER_TYPE_OPT(name, type, outvar, fmtctx, mediatype)\ {\ int i;\ for (i = 0; i < o->nb_ ## name; i++) {\ char *spec = o->name[i].specifier;\ if (!strcmp(spec, mediatype))\ outvar = o->name[i].u.type;\ }\ } const HWAccel hwaccels[] = { #if HAVE_VDPAU_X11 { "vdpau", vdpau_init, HWACCEL_VDPAU, AV_PIX_FMT_VDPAU }, #endif #if HAVE_DXVA2_LIB { "dxva2", dxva2_init, HWACCEL_DXVA2, AV_PIX_FMT_DXVA2_VLD }, #endif #if CONFIG_VDA { "vda", videotoolbox_init, HWACCEL_VDA, AV_PIX_FMT_VDA }, #endif #if CONFIG_VIDEOTOOLBOX { "videotoolbox", videotoolbox_init, HWACCEL_VIDEOTOOLBOX, AV_PIX_FMT_VIDEOTOOLBOX }, #endif #if CONFIG_LIBMFX { "qsv", qsv_init, HWACCEL_QSV, AV_PIX_FMT_QSV }, #endif #if CONFIG_VAAPI { "vaapi", vaapi_decode_init, HWACCEL_VAAPI, AV_PIX_FMT_VAAPI }, #endif #if CONFIG_CUVID { "cuvid", cuvid_init, HWACCEL_CUVID, AV_PIX_FMT_CUDA }, #endif { 0 }, }; int hwaccel_lax_profile_check = 0; AVBufferRef *hw_device_ctx; char *vstats_filename; char *sdp_filename; float audio_drift_threshold = 0.1; float dts_delta_threshold = 10; float dts_error_threshold = 3600*30; int audio_volume = 256; int audio_sync_method = 0; int video_sync_method = VSYNC_AUTO; float frame_drop_threshold = 0; int do_deinterlace = 0; int do_benchmark = 0; int do_benchmark_all = 0; int do_hex_dump = 0; int do_pkt_dump = 0; int copy_ts = 0; int start_at_zero = 0; int copy_tb = -1; int debug_ts = 0; int exit_on_error = 0; int abort_on_flags = 0; int print_stats = -1; int qp_hist = 0; int stdin_interaction = 1; int frame_bits_per_raw_sample = 0; float max_error_rate = 2.0/3; int filter_nbthreads = 0; int filter_complex_nbthreads = 0; int vstats_version = 2; static int intra_only = 0; static int file_overwrite = 0; static int no_file_overwrite = 0; static int do_psnr = 0; static int input_sync; static int override_ffserver = 0; static int input_stream_potentially_available = 0; static int ignore_unknown_streams = 0; static int copy_unknown_streams = 0; static void uninit_options(OptionsContext *o) { 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); av_freep(&o->audio_channel_maps); av_freep(&o->streamid_map); av_freep(&o->attachments); } static void init_options(OptionsContext *o) { memset(o, 0, sizeof(*o)); o->stop_time = INT64_MAX; o->mux_max_delay = 0.7; o->start_time = AV_NOPTS_VALUE; o->start_time_eof = AV_NOPTS_VALUE; o->recording_time = INT64_MAX; o->limit_filesize = UINT64_MAX; o->chapters_input_file = INT_MAX; o->accurate_seek = 1; } 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; } /* 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; } 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); } static int opt_sameq(void *optctx, const char *opt, const char *arg) { av_log(NULL, AV_LOG_ERROR, "Option '%s' was removed. " "If you are looking for an option to preserve the quality (which is not " "what -%s was for), use -qscale 0 or an equivalent quality factor option.\n", opt, opt); return AVERROR(EINVAL); } static int opt_video_channel(void *optctx, const char *opt, const char *arg) { av_log(NULL, AV_LOG_WARNING, "This option is deprecated, use -channel.\n"); return opt_default(optctx, "channel", arg); } static int opt_video_standard(void *optctx, const char *opt, const char *arg) { av_log(NULL, AV_LOG_WARNING, "This option is deprecated, use -standard.\n"); return opt_default(optctx, "standard", arg); } static int opt_audio_codec(void *optctx, const char *opt, const char *arg) { OptionsContext *o = optctx; return parse_option(o, "codec:a", arg, options); } static int opt_video_codec(void *optctx, const char *opt, const char *arg) { OptionsContext *o = optctx; return parse_option(o, "codec:v", arg, options); } static int opt_subtitle_codec(void *optctx, const char *opt, const char *arg) { OptionsContext *o = optctx; return parse_option(o, "codec:s", arg, options); } static int opt_data_codec(void *optctx, const char *opt, const char *arg) { OptionsContext *o = optctx; return parse_option(o, "codec:d", arg, options); } static int opt_map(void *optctx, const char *opt, const char *arg) { OptionsContext *o = optctx; StreamMap *m = NULL; int i, negative = 0, file_idx; int sync_file_idx = -1, sync_stream_idx = 0; char *p, *sync; char *map; char *allow_unused; if (*arg == '-') { negative = 1; arg++; } map = av_strdup(arg); if (!map) return AVERROR(ENOMEM); /* 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); exit_program(1); } 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); exit_program(1); } } if (map[0] == '[') { /* this mapping refers to lavfi output */ const char *c = map + 1; GROW_ARRAY(o->stream_maps, o->nb_stream_maps); 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); exit_program(1); } } else { if (allow_unused = strchr(map, '?')) *allow_unused = 0; 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); exit_program(1); } 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; GROW_ARRAY(o->stream_maps, o->nb_stream_maps); 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) { 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); } } av_freep(&map); return 0; } static int opt_attach(void *optctx, const char *opt, const char *arg) { OptionsContext *o = optctx; GROW_ARRAY(o->attachments, o->nb_attachments); o->attachments[o->nb_attachments - 1] = arg; return 0; } static int opt_map_channel(void *optctx, const char *opt, const char *arg) { OptionsContext *o = optctx; int n; AVStream *st; AudioChannelMap *m; GROW_ARRAY(o->audio_channel_maps, o->nb_audio_channel_maps); 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"); exit_program(1); } 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); exit_program(1); } 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); exit_program(1); } st = input_files[m->file_idx]->ctx->streams[m->stream_idx]; if (st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO) { av_log(NULL, AV_LOG_FATAL, "mapchan: stream #%d.%d is not an audio stream.\n", m->file_idx, m->stream_idx); exit_program(1); } if (m->channel_idx < 0 || m->channel_idx >= st->codecpar->channels) { av_log(NULL, AV_LOG_FATAL, "mapchan: invalid audio channel #%d.%d.%d\n", m->file_idx, m->stream_idx, m->channel_idx); exit_program(1); } return 0; } static int opt_sdp_file(void *optctx, const char *opt, const char *arg) { av_free(sdp_filename); sdp_filename = av_strdup(arg); return 0; } #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 /** * Parse a metadata specifier passed as 'arg' parameter. * @param arg metadata string to parse * @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); exit_program(1); } *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); exit_program(1); } } else *type = 'g'; } static int copy_metadata(char *outspec, char *inspec, AVFormatContext *oc, AVFormatContext *ic, OptionsContext *o)