74#include "libavformat/avformat.h"
75#include "libswscale/swscale.h"
76#include "libswresample/swresample.h"
77#include "libavutil/avassert.h"
78#include "libavutil/avstring.h"
79#include "libavutil/channel_layout.h"
80#include "libavutil/display.h"
81#include "libavutil/getenv_utf8.h"
82#include "libavutil/mathematics.h"
83#include "libavutil/imgutils.h"
84#include "libavutil/libm.h"
85#include "libavutil/parseutils.h"
86#include "libavutil/eval.h"
87#include "libavutil/dict.h"
88#include "libavutil/opt.h"
95#include "compat/w32dlfcn.h"
118#if HAVE_SETDLLDIRECTORY && defined(_WIN32)
144 double min,
double max)
148 double d = av_strtod(numstr, &tail);
150 error =
"Expected number for %s but found: %s\n";
151 else if (d < min || d > max)
152 error =
"The value for %s was %s which is not within %f - %f\n";
154 error =
"Expected int64 for %s but found %s\n";
156 error =
"Expected int for %s but found %s\n";
159 av_log(NULL, AV_LOG_FATAL, error, context, numstr, min, max);
168 if (av_parse_time(&us, timestr, is_duration) < 0) {
169 av_log(NULL, AV_LOG_FATAL,
"Invalid %s specification for %s: %s\n",
170 is_duration ?
"duration" :
"date", context, timestr);
177 int rej_flags,
int alt_flags)
183 for (po = options; po->
name; po++) {
186 if (((po->
flags & req_flags) != req_flags) ||
187 (alt_flags && !(po->
flags & alt_flags)) ||
188 (po->
flags & rej_flags))
195 av_strlcpy(buf, po->
name,
sizeof(buf));
197 av_strlcat(buf,
" ",
sizeof(buf));
198 av_strlcat(buf, po->
argname,
sizeof(buf));
208 const AVClass *child;
210 av_opt_show2(&
class, NULL, flags, 0);
214 while ((child = av_opt_child_class_iterate(
class, &iter)))
222 if (av_strstart(name, po->
name, &end) && (!*end || *end ==
':'))
232#if HAVE_COMMANDLINETOARGVW && defined(_WIN32)
235static char** win32_argv_utf8 = NULL;
236static int win32_argc = 0;
249 int i, buffsize = 0, offset = 0;
251 if (win32_argv_utf8) {
252 *argc_ptr = win32_argc;
253 *argv_ptr = win32_argv_utf8;
258 argv_w = CommandLineToArgvW(GetCommandLineW(), &win32_argc);
259 if (win32_argc <= 0 || !argv_w)
263 for (i = 0; i < win32_argc; i++)
264 buffsize += WideCharToMultiByte(CP_UTF8, 0, argv_w[i], -1,
265 NULL, 0, NULL, NULL);
267 win32_argv_utf8 = av_mallocz(
sizeof(
char *) * (win32_argc + 1) + buffsize);
268 argstr_flat = (
char *)win32_argv_utf8 +
sizeof(
char *) * (win32_argc + 1);
269 if (!win32_argv_utf8) {
274 for (i = 0; i < win32_argc; i++) {
275 win32_argv_utf8[i] = &argstr_flat[offset];
276 offset += WideCharToMultiByte(CP_UTF8, 0, argv_w[i], -1,
277 &argstr_flat[offset],
278 buffsize - offset, NULL, NULL);
280 win32_argv_utf8[i] = NULL;
283 *argc_ptr = win32_argc;
284 *argv_ptr = win32_argv_utf8;
304 char *p = strchr(opt,
':');
307 dstcount = (
int *)(so + 1);
308 *so =
grow_array(*so,
sizeof(**so), dstcount, *dstcount + 1);
309 str = av_strdup(p ? p + 1 :
"");
311 return AVERROR(ENOMEM);
312 (*so)[*dstcount - 1].specifier = str;
313 dst = &(*so)[*dstcount - 1].u;
318 str = av_strdup(arg);
321 return AVERROR(ENOMEM);
334 int ret = po->
u.
func_arg(optctx, opt, arg);
336 av_log(NULL, AV_LOG_ERROR,
337 "Failed to set value '%s' for option '%s': %s\n",
338 arg, opt, av_err2str(ret));
352 .
name =
"AVOption passthrough",
361 if (!po->
name && opt[0] ==
'n' && opt[1] ==
'o') {
372 av_log(NULL, AV_LOG_ERROR,
"Unrecognized option '%s'\n", opt);
373 return AVERROR(EINVAL);
376 av_log(NULL, AV_LOG_ERROR,
"Missing argument for option '%s'\n", opt);
377 return AVERROR(EINVAL);
388 void (*parse_arg_function)(
void *,
const char*))
391 int optindex, handleoptions = 1, ret;
398 while (optindex < argc) {
399 opt = argv[optindex++];
401 if (handleoptions && opt[0] ==
'-' && opt[1] !=
'\0') {
402 if (opt[1] ==
'-' && opt[2] ==
'\0') {
407 if (optindex >= argc) {
408 if ((ret =
parse_option(optctx, opt, NULL, options)) < 0)
411 if ((ret =
parse_option(optctx, opt, argv[optindex], options)) < 0)
416 if (parse_arg_function)
417 parse_arg_function(optctx, opt);
426 av_log(NULL, AV_LOG_DEBUG,
"Parsing a group of options: %s %s.\n",
429 for (i = 0; i < g->
nb_opts; i++) {
434 av_log(NULL, AV_LOG_ERROR,
"Option %s (%s) cannot be applied to "
435 "%s %s -- you are trying to apply an input option to an "
436 "output file or vice versa. Move this option before the "
437 "file it belongs to.\n", o->
key, o->
opt->
help,
439 return AVERROR(EINVAL);
442 av_log(NULL, AV_LOG_DEBUG,
"Applying option %s (%s) with argument %s.\n",
450 av_log(NULL, AV_LOG_DEBUG,
"Successfully parsed a group of options.\n");
461 for (i = 1; i < argc; i++) {
462 const char *cur_opt = argv[i];
464 if (*cur_opt++ !=
'-')
468 if (!po->
name && cur_opt[0] ==
'n' && cur_opt[1] ==
'o')
471 if ((!po->
name && !strcmp(cur_opt, optname)) ||
472 (po->
name && !strcmp(optname, po->
name)))
483 const unsigned char *p;
486 if (!((*p >=
'+' && *p <=
':') || (*p >=
'@' && *p <=
'Z') ||
487 *p ==
'_' || (*p >=
'a' && *p <=
'z')))
494 for (p = a; *p; p++) {
495 if (*p ==
'\\' || *p ==
'"' || *p ==
'$' || *p ==
'`')
497 else if (*p < ' ' || *p >
'~')
523 if (idx && (idx + 1 < argc) && argv[idx + 1])
526 env = getenv_utf8(
"FFREPORT");
533 for (i = 0; i < argc; i++) {
546static const AVOption *
opt_find(
void *obj,
const char *name,
const char *unit,
547 int opt_flags,
int search_flags)
549 const AVOption *o = av_opt_find(obj, name, unit, opt_flags, search_flags);
555#define FLAGS (o->type == AV_OPT_TYPE_FLAGS && (arg[0]=='-' || arg[0]=='+')) ? AV_DICT_APPEND : 0
560 char opt_stripped[128];
562 const AVClass *cc = avcodec_get_class(), *fc = avformat_get_class();
564 const AVClass *sc = sws_get_class();
567 const AVClass *swr_class = swr_get_class();
570 if (!strcmp(opt,
"debug") || !strcmp(opt,
"fdebug"))
571 av_log_set_level(AV_LOG_DEBUG);
573 if (!(p = strchr(opt,
':')))
574 p = opt + strlen(opt);
575 av_strlcpy(opt_stripped, opt, FFMIN(
sizeof(opt_stripped), p - opt + 1));
577 if ((o =
opt_find(&cc, opt_stripped, NULL, 0,
578 AV_OPT_SEARCH_CHILDREN | AV_OPT_SEARCH_FAKE_OBJ)) ||
579 ((opt[0] ==
'v' || opt[0] ==
'a' || opt[0] ==
's') &&
580 (o =
opt_find(&cc, opt + 1, NULL, 0, AV_OPT_SEARCH_FAKE_OBJ)))) {
584 if ((o =
opt_find(&fc, opt, NULL, 0,
585 AV_OPT_SEARCH_CHILDREN | AV_OPT_SEARCH_FAKE_OBJ))) {
588 av_log(NULL, AV_LOG_VERBOSE,
"Routing option %s to both codec and muxer layer\n", opt);
592 if (!consumed && (o =
opt_find(&sc, opt, NULL, 0,
593 AV_OPT_SEARCH_CHILDREN | AV_OPT_SEARCH_FAKE_OBJ))) {
594 if (!strcmp(opt,
"srcw") || !strcmp(opt,
"srch") ||
595 !strcmp(opt,
"dstw") || !strcmp(opt,
"dsth") ||
596 !strcmp(opt,
"src_format") || !strcmp(opt,
"dst_format")) {
597 av_log(NULL, AV_LOG_ERROR,
"Directly using swscale dimensions/format options is not supported, please use the -s or -pix_fmt options\n");
598 return AVERROR(EINVAL);
605 if (!consumed && !strcmp(opt,
"sws_flags")) {
606 av_log(NULL, AV_LOG_WARNING,
"Ignoring %s %s, due to disabled swscale\n", opt, arg);
611 if (!consumed && (o=
opt_find(&swr_class, opt, NULL, 0,
612 AV_OPT_SEARCH_CHILDREN | AV_OPT_SEARCH_FAKE_OBJ))) {
620 return AVERROR_OPTION_NOT_FOUND;
633 for (i = 0; i < nb_groups; i++) {
635 if (p->
sep && !strcmp(p->
sep, opt))
677 const char *key,
const char *val)
694 memset(octx, 0,
sizeof(*octx));
744 av_log(NULL, AV_LOG_DEBUG,
"Splitting the commandline.\n");
746 while (optindex < argc) {
747 const char *opt = argv[optindex++], *arg;
751 av_log(NULL, AV_LOG_DEBUG,
"Reading option '%s' ...", opt);
753 if (opt[0] ==
'-' && opt[1] ==
'-' && !opt[2]) {
758 if (opt[0] !=
'-' || !opt[1] || dashdash+1 == optindex) {
760 av_log(NULL, AV_LOG_DEBUG,
" matched as %s.\n",
groups[0].name);
765#define GET_ARG(arg) \
767 if (optindex < argc) { \
768 arg = argv[optindex++]; \
770 av_log(NULL, AV_LOG_ERROR, "Missing argument for option '%s'.\n", opt);\
771 return AVERROR(EINVAL); \
779 av_log(NULL, AV_LOG_DEBUG,
" matched as %s with argument '%s'.\n",
789 if (optindex < argc) {
790 arg = argv[optindex++];
801 av_log(NULL, AV_LOG_DEBUG,
" matched as option '%s' (%s) with "
802 "argument '%s'.\n", po->
name, po->
help, arg);
807 if ((optindex < argc) && argv[optindex]) {
810 av_log(NULL, AV_LOG_DEBUG,
" matched as AVOption '%s' with "
811 "argument '%s'.\n", opt, argv[optindex]);
814 }
else if (ret != AVERROR_OPTION_NOT_FOUND) {
815 av_log(NULL, AV_LOG_ERROR,
"Error parsing option '%s' "
816 "with argument '%s'.\n", opt, argv[optindex]);
822 if (opt[0] ==
'n' && opt[1] ==
'o' &&
826 av_log(NULL, AV_LOG_DEBUG,
" matched as option '%s' (%s) with "
827 "argument 0.\n", po->
name, po->
help);
831 av_log(NULL, AV_LOG_ERROR,
"Unrecognized option '%s'.\n", opt);
832 return AVERROR_OPTION_NOT_FOUND;
836 av_log(NULL, AV_LOG_WARNING,
"Trailing option(s) found in the "
837 "command: may be ignored.\n");
839 av_log(NULL, AV_LOG_DEBUG,
"Finished splitting the commandline.\n");
847 const char *errbuf_ptr = errbuf;
849 if (av_strerror(err, errbuf,
sizeof(errbuf)) < 0)
850 errbuf_ptr = strerror(AVUNERROR(err));
851 av_log(NULL, AV_LOG_ERROR,
"%s: %s\n", filename, errbuf_ptr);
857 int yesno = (av_toupper(c) ==
'Y');
859 while (c !=
'\n' && c != EOF)
866 const char *preset_name,
int is_path,
867 const char *codec_name)
871#if HAVE_GETMODULEHANDLE && defined(_WIN32)
872 char *datadir = NULL;
874 char *env_home = getenv_utf8(
"HOME");
875 char *env_ffmpeg_datadir = getenv_utf8(
"FFMPEG_DATADIR");
876 const char *base[3] = { env_ffmpeg_datadir,
881 av_strlcpy(filename, preset_name, filename_size);
884#if HAVE_GETMODULEHANDLE && defined(_WIN32)
885 wchar_t *datadir_w = get_module_filename(NULL);
888 if (wchartoutf8(datadir_w, &datadir))
895 for (ls = datadir; *ls; ls++)
896 if (*ls ==
'\\') *ls =
'/';
898 if (ls = strrchr(datadir,
'/'))
900 ptrdiff_t datadir_len = ls - datadir;
901 size_t desired_size = datadir_len + strlen(
"/ffpresets") + 1;
902 char *new_datadir = av_realloc_array(
903 datadir, desired_size,
sizeof *datadir);
905 datadir = new_datadir;
906 datadir[datadir_len] = 0;
907 strncat(datadir,
"/ffpresets", desired_size - 1 - datadir_len);
913 for (i = 0; i < 3 && !f; i++) {
916 snprintf(filename, filename_size,
"%s%s/%s.ffpreset", base[i],
917 i != 1 ?
"" :
"/.ffmpeg", preset_name);
919 if (!f && codec_name) {
920 snprintf(filename, filename_size,
921 "%s%s/%s-%s.ffpreset",
922 base[i], i != 1 ?
"" :
"/.ffmpeg", codec_name,
929#if HAVE_GETMODULEHANDLE && defined(_WIN32)
932 freeenv_utf8(env_ffmpeg_datadir);
933 freeenv_utf8(env_home);
939 int ret = avformat_match_stream_specifier(s, st, spec);
941 av_log(s, AV_LOG_ERROR,
"Invalid stream specifier: %s.\n", spec);
946 AVFormatContext *s, AVStream *st,
const AVCodec *codec)
948 AVDictionary *ret = NULL;
949 const AVDictionaryEntry *t = NULL;
950 int flags = s->oformat ? AV_OPT_FLAG_ENCODING_PARAM
951 : AV_OPT_FLAG_DECODING_PARAM;
953 const AVClass *cc = avcodec_get_class();
956 codec = s->oformat ? avcodec_find_encoder(codec_id)
957 : avcodec_find_decoder(codec_id);
959 switch (st->codecpar->codec_type) {
960 case AVMEDIA_TYPE_VIDEO:
962 flags |= AV_OPT_FLAG_VIDEO_PARAM;
964 case AVMEDIA_TYPE_AUDIO:
966 flags |= AV_OPT_FLAG_AUDIO_PARAM;
968 case AVMEDIA_TYPE_SUBTITLE:
970 flags |= AV_OPT_FLAG_SUBTITLE_PARAM;
974 while ((t = av_dict_get(opts,
"", t, AV_DICT_IGNORE_SUFFIX))) {
975 const AVClass *priv_class;
976 char *p = strchr(t->key,
':');
981 case 1: *p = 0;
break;
986 if (av_opt_find(&cc, t->key, NULL, flags, AV_OPT_SEARCH_FAKE_OBJ) ||
988 ((priv_class = codec->priv_class) &&
989 av_opt_find(&priv_class, t->key, NULL, flags,
990 AV_OPT_SEARCH_FAKE_OBJ)))
991 av_dict_set(&ret, t->key, t->value, 0);
992 else if (t->key[0] == prefix &&
993 av_opt_find(&cc, t->key + 1, NULL, flags,
994 AV_OPT_SEARCH_FAKE_OBJ))
995 av_dict_set(&ret, t->key + 1, t->value, 0);
1007 AVDictionary **opts;
1011 opts = av_calloc(s->nb_streams,
sizeof(*opts));
1013 av_log(NULL, AV_LOG_ERROR,
1014 "Could not alloc memory for stream options.\n");
1017 for (i = 0; i < s->nb_streams; i++)
1019 s, s->streams[i], NULL);
1023void *
grow_array(
void *array,
int elem_size,
int *size,
int new_size)
1025 if (new_size >= INT_MAX / elem_size) {
1026 av_log(NULL, AV_LOG_ERROR,
"Array too big.\n");
1029 if (*size < new_size) {
1030 uint8_t *tmp = av_realloc_array(array, new_size, elem_size);
1032 av_log(NULL, AV_LOG_ERROR,
"Could not alloc buffer.\n");
1035 memset(tmp + *size*elem_size, 0, (new_size-*size) * elem_size);
1046 if (!(new_elem = av_mallocz(elem_size)) ||
1047 av_dynarray_add_nofree(ptr, nb_elems, new_elem) < 0) {
1048 av_log(NULL, AV_LOG_ERROR,
"Could not alloc buffer.\n");
1058 theta = -round(av_display_rotation_get((int32_t*) displaymatrix));
1060 theta -= 360*floor(theta/360 + 0.9/360);
1062 if (fabs(theta - 90*round(theta/90)) > 2)
1063 av_log(NULL, AV_LOG_WARNING,
"Odd rotation angle.\n"
1064 "If you want to help, upload a sample "
1065 "of this file to https://streams.videolan.org/upload/ "
1066 "and contact the ffmpeg-devel mailing list. (ffmpeg-devel@ffmpeg.org)");
__thread jmp_buf ex_buf__
int(* func_arg)(void *, const char *, const char *)
const OptionGroupDef * group_def
AVDictionary * codec_opts
AVDictionary * format_opts
const OptionGroupDef * group_def