cmdutils.c 34 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168
  1. /*
  2. * Various utilities for command line tools
  3. * Copyright (c) 2000-2003 Fabrice Bellard
  4. *
  5. * This file is part of FFmpeg.
  6. *
  7. * FFmpeg is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU Lesser General Public
  9. * License as published by the Free Software Foundation; either
  10. * version 2.1 of the License, or (at your option) any later version.
  11. *
  12. * FFmpeg is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * Lesser General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Lesser General Public
  18. * License along with FFmpeg; if not, write to the Free Software
  19. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  20. */
  21. #include <string.h>
  22. #include <stdint.h>
  23. #include <stdlib.h>
  24. #include <errno.h>
  25. #include <math.h>
  26. /* Include only the enabled headers since some compilers (namely, Sun
  27. Studio) will not omit unused inline functions and create undefined
  28. references to libraries that are not being built. */
  29. #include "config.h"
  30. #include "compat/va_copy.h"
  31. #include "libavformat/avformat.h"
  32. #include "libswscale/swscale.h"
  33. #include "libswresample/swresample.h"
  34. #include "libavutil/avassert.h"
  35. #include "libavutil/avstring.h"
  36. #include "libavutil/bprint.h"
  37. #include "libavutil/display.h"
  38. #include "libavutil/getenv_utf8.h"
  39. #include "libavutil/libm.h"
  40. #include "libavutil/mem.h"
  41. #include "libavutil/parseutils.h"
  42. #include "libavutil/eval.h"
  43. #include "libavutil/dict.h"
  44. #include "libavutil/opt.h"
  45. #include "cmdutils.h"
  46. #include "fopen_utf8.h"
  47. #include "opt_common.h"
  48. #ifdef _WIN32
  49. #include <windows.h>
  50. #include "compat/w32dlfcn.h"
  51. #endif
  52. AVDictionary *sws_dict;
  53. AVDictionary *swr_opts;
  54. AVDictionary *format_opts, *codec_opts;
  55. int hide_banner = 0;
  56. void uninit_opts(void)
  57. {
  58. av_dict_free(&swr_opts);
  59. av_dict_free(&sws_dict);
  60. av_dict_free(&format_opts);
  61. av_dict_free(&codec_opts);
  62. }
  63. void log_callback_help(void *ptr, int level, const char *fmt, va_list vl)
  64. {
  65. vfprintf(stdout, fmt, vl);
  66. }
  67. void init_dynload(void)
  68. {
  69. #if HAVE_SETDLLDIRECTORY && defined(_WIN32)
  70. /* Calling SetDllDirectory with the empty string (but not NULL) removes the
  71. * current working directory from the DLL search path as a security pre-caution. */
  72. SetDllDirectory("");
  73. #endif
  74. }
  75. int parse_number(const char *context, const char *numstr, enum OptionType type,
  76. double min, double max, double *dst)
  77. {
  78. char *tail;
  79. const char *error;
  80. double d = av_strtod(numstr, &tail);
  81. if (*tail)
  82. error = "Expected number for %s but found: %s\n";
  83. else if (d < min || d > max)
  84. error = "The value for %s was %s which is not within %f - %f\n";
  85. else if (type == OPT_TYPE_INT64 && (int64_t)d != d)
  86. error = "Expected int64 for %s but found %s\n";
  87. else if (type == OPT_TYPE_INT && (int)d != d)
  88. error = "Expected int for %s but found %s\n";
  89. else {
  90. *dst = d;
  91. return 0;
  92. }
  93. av_log(NULL, AV_LOG_FATAL, error, context, numstr, min, max);
  94. return AVERROR(EINVAL);
  95. }
  96. void show_help_options(const OptionDef *options, const char *msg, int req_flags,
  97. int rej_flags)
  98. {
  99. const OptionDef *po;
  100. int first;
  101. first = 1;
  102. for (po = options; po->name; po++) {
  103. char buf[128];
  104. if (((po->flags & req_flags) != req_flags) ||
  105. (po->flags & rej_flags))
  106. continue;
  107. if (first) {
  108. printf("%s\n", msg);
  109. first = 0;
  110. }
  111. av_strlcpy(buf, po->name, sizeof(buf));
  112. if (po->flags & OPT_FLAG_PERSTREAM)
  113. av_strlcat(buf, "[:<stream_spec>]", sizeof(buf));
  114. else if (po->flags & OPT_FLAG_SPEC)
  115. av_strlcat(buf, "[:<spec>]", sizeof(buf));
  116. if (po->argname)
  117. av_strlcatf(buf, sizeof(buf), " <%s>", po->argname);
  118. printf("-%-17s %s\n", buf, po->help);
  119. }
  120. printf("\n");
  121. }
  122. void show_help_children(const AVClass *class, int flags)
  123. {
  124. void *iter = NULL;
  125. const AVClass *child;
  126. if (class->option) {
  127. av_opt_show2(&class, NULL, flags, 0);
  128. printf("\n");
  129. }
  130. while (child = av_opt_child_class_iterate(class, &iter))
  131. show_help_children(child, flags);
  132. }
  133. static const OptionDef *find_option(const OptionDef *po, const char *name)
  134. {
  135. if (*name == '/')
  136. name++;
  137. while (po->name) {
  138. const char *end;
  139. if (av_strstart(name, po->name, &end) && (!*end || *end == ':'))
  140. break;
  141. po++;
  142. }
  143. return po;
  144. }
  145. /* _WIN32 means using the windows libc - cygwin doesn't define that
  146. * by default. HAVE_COMMANDLINETOARGVW is true on cygwin, while
  147. * it doesn't provide the actual command line via GetCommandLineW(). */
  148. #if HAVE_COMMANDLINETOARGVW && defined(_WIN32)
  149. #include <shellapi.h>
  150. /* Will be leaked on exit */
  151. static char** win32_argv_utf8 = NULL;
  152. static int win32_argc = 0;
  153. /**
  154. * Prepare command line arguments for executable.
  155. * For Windows - perform wide-char to UTF-8 conversion.
  156. * Input arguments should be main() function arguments.
  157. * @param argc_ptr Arguments number (including executable)
  158. * @param argv_ptr Arguments list.
  159. */
  160. static void prepare_app_arguments(int *argc_ptr, char ***argv_ptr)
  161. {
  162. char *argstr_flat;
  163. wchar_t **argv_w;
  164. int i, buffsize = 0, offset = 0;
  165. if (win32_argv_utf8) {
  166. *argc_ptr = win32_argc;
  167. *argv_ptr = win32_argv_utf8;
  168. return;
  169. }
  170. win32_argc = 0;
  171. argv_w = CommandLineToArgvW(GetCommandLineW(), &win32_argc);
  172. if (win32_argc <= 0 || !argv_w)
  173. return;
  174. /* determine the UTF-8 buffer size (including NULL-termination symbols) */
  175. for (i = 0; i < win32_argc; i++)
  176. buffsize += WideCharToMultiByte(CP_UTF8, 0, argv_w[i], -1,
  177. NULL, 0, NULL, NULL);
  178. win32_argv_utf8 = av_mallocz(sizeof(char *) * (win32_argc + 1) + buffsize);
  179. argstr_flat = (char *)win32_argv_utf8 + sizeof(char *) * (win32_argc + 1);
  180. if (!win32_argv_utf8) {
  181. LocalFree(argv_w);
  182. return;
  183. }
  184. for (i = 0; i < win32_argc; i++) {
  185. win32_argv_utf8[i] = &argstr_flat[offset];
  186. offset += WideCharToMultiByte(CP_UTF8, 0, argv_w[i], -1,
  187. &argstr_flat[offset],
  188. buffsize - offset, NULL, NULL);
  189. }
  190. win32_argv_utf8[i] = NULL;
  191. LocalFree(argv_w);
  192. *argc_ptr = win32_argc;
  193. *argv_ptr = win32_argv_utf8;
  194. }
  195. #else
  196. static inline void prepare_app_arguments(int *argc_ptr, char ***argv_ptr)
  197. {
  198. /* nothing to do */
  199. }
  200. #endif /* HAVE_COMMANDLINETOARGVW */
  201. static int opt_has_arg(const OptionDef *o)
  202. {
  203. if (o->type == OPT_TYPE_BOOL)
  204. return 0;
  205. if (o->type == OPT_TYPE_FUNC)
  206. return !!(o->flags & OPT_FUNC_ARG);
  207. return 1;
  208. }
  209. static int write_option(void *optctx, const OptionDef *po, const char *opt,
  210. const char *arg, const OptionDef *defs)
  211. {
  212. /* new-style options contain an offset into optctx, old-style address of
  213. * a global var*/
  214. void *dst = po->flags & OPT_FLAG_OFFSET ?
  215. (uint8_t *)optctx + po->u.off : po->u.dst_ptr;
  216. char *arg_allocated = NULL;
  217. SpecifierOptList *sol = NULL;
  218. double num;
  219. int ret = 0;
  220. if (*opt == '/') {
  221. opt++;
  222. if (po->type == OPT_TYPE_BOOL) {
  223. av_log(NULL, AV_LOG_FATAL,
  224. "Requested to load an argument from file for a bool option '%s'\n",
  225. po->name);
  226. return AVERROR(EINVAL);
  227. }
  228. arg_allocated = file_read(arg);
  229. if (!arg_allocated) {
  230. av_log(NULL, AV_LOG_FATAL,
  231. "Error reading the value for option '%s' from file: %s\n",
  232. opt, arg);
  233. return AVERROR(EINVAL);
  234. }
  235. arg = arg_allocated;
  236. }
  237. if (po->flags & OPT_FLAG_SPEC) {
  238. char *p = strchr(opt, ':');
  239. char *str;
  240. sol = dst;
  241. ret = GROW_ARRAY(sol->opt, sol->nb_opt);
  242. if (ret < 0)
  243. goto finish;
  244. str = av_strdup(p ? p + 1 : "");
  245. if (!str) {
  246. ret = AVERROR(ENOMEM);
  247. goto finish;
  248. }
  249. sol->opt[sol->nb_opt - 1].specifier = str;
  250. dst = &sol->opt[sol->nb_opt - 1].u;
  251. }
  252. if (po->type == OPT_TYPE_STRING) {
  253. char *str;
  254. if (arg_allocated) {
  255. str = arg_allocated;
  256. arg_allocated = NULL;
  257. } else
  258. str = av_strdup(arg);
  259. av_freep(dst);
  260. if (!str) {
  261. ret = AVERROR(ENOMEM);
  262. goto finish;
  263. }
  264. *(char **)dst = str;
  265. } else if (po->type == OPT_TYPE_BOOL || po->type == OPT_TYPE_INT) {
  266. ret = parse_number(opt, arg, OPT_TYPE_INT64, INT_MIN, INT_MAX, &num);
  267. if (ret < 0)
  268. goto finish;
  269. *(int *)dst = num;
  270. } else if (po->type == OPT_TYPE_INT64) {
  271. ret = parse_number(opt, arg, OPT_TYPE_INT64, INT64_MIN, (double)INT64_MAX, &num);
  272. if (ret < 0)
  273. goto finish;
  274. *(int64_t *)dst = num;
  275. } else if (po->type == OPT_TYPE_TIME) {
  276. ret = av_parse_time(dst, arg, 1);
  277. if (ret < 0) {
  278. av_log(NULL, AV_LOG_ERROR, "Invalid duration for option %s: %s\n",
  279. opt, arg);
  280. goto finish;
  281. }
  282. } else if (po->type == OPT_TYPE_FLOAT) {
  283. ret = parse_number(opt, arg, OPT_TYPE_FLOAT, -INFINITY, INFINITY, &num);
  284. if (ret < 0)
  285. goto finish;
  286. *(float *)dst = num;
  287. } else if (po->type == OPT_TYPE_DOUBLE) {
  288. ret = parse_number(opt, arg, OPT_TYPE_DOUBLE, -INFINITY, INFINITY, &num);
  289. if (ret < 0)
  290. goto finish;
  291. *(double *)dst = num;
  292. } else {
  293. av_assert0(po->type == OPT_TYPE_FUNC && po->u.func_arg);
  294. ret = po->u.func_arg(optctx, opt, arg);
  295. if (ret < 0) {
  296. av_log(NULL, AV_LOG_ERROR,
  297. "Failed to set value '%s' for option '%s': %s\n",
  298. arg, opt, av_err2str(ret));
  299. goto finish;
  300. }
  301. }
  302. if (po->flags & OPT_EXIT) {
  303. ret = AVERROR_EXIT;
  304. goto finish;
  305. }
  306. if (sol) {
  307. sol->type = po->type;
  308. sol->opt_canon = (po->flags & OPT_HAS_CANON) ?
  309. find_option(defs, po->u1.name_canon) : po;
  310. }
  311. finish:
  312. av_freep(&arg_allocated);
  313. return ret;
  314. }
  315. int parse_option(void *optctx, const char *opt, const char *arg,
  316. const OptionDef *options)
  317. {
  318. static const OptionDef opt_avoptions = {
  319. .name = "AVOption passthrough",
  320. .type = OPT_TYPE_FUNC,
  321. .flags = OPT_FUNC_ARG,
  322. .u.func_arg = opt_default,
  323. };
  324. const OptionDef *po;
  325. int ret;
  326. po = find_option(options, opt);
  327. if (!po->name && opt[0] == 'n' && opt[1] == 'o') {
  328. /* handle 'no' bool option */
  329. po = find_option(options, opt + 2);
  330. if ((po->name && po->type == OPT_TYPE_BOOL))
  331. arg = "0";
  332. } else if (po->type == OPT_TYPE_BOOL)
  333. arg = "1";
  334. if (!po->name)
  335. po = &opt_avoptions;
  336. if (!po->name) {
  337. av_log(NULL, AV_LOG_ERROR, "Unrecognized option '%s'\n", opt);
  338. return AVERROR(EINVAL);
  339. }
  340. if (opt_has_arg(po) && !arg) {
  341. av_log(NULL, AV_LOG_ERROR, "Missing argument for option '%s'\n", opt);
  342. return AVERROR(EINVAL);
  343. }
  344. ret = write_option(optctx, po, opt, arg, options);
  345. if (ret < 0)
  346. return ret;
  347. return opt_has_arg(po);
  348. }
  349. int parse_options(void *optctx, int argc, char **argv, const OptionDef *options,
  350. int (*parse_arg_function)(void *, const char*))
  351. {
  352. const char *opt;
  353. int optindex, handleoptions = 1, ret;
  354. /* perform system-dependent conversions for arguments list */
  355. prepare_app_arguments(&argc, &argv);
  356. /* parse options */
  357. optindex = 1;
  358. while (optindex < argc) {
  359. opt = argv[optindex++];
  360. if (handleoptions && opt[0] == '-' && opt[1] != '\0') {
  361. if (opt[1] == '-' && opt[2] == '\0') {
  362. handleoptions = 0;
  363. continue;
  364. }
  365. opt++;
  366. if ((ret = parse_option(optctx, opt, argv[optindex], options)) < 0)
  367. return ret;
  368. optindex += ret;
  369. } else {
  370. if (parse_arg_function) {
  371. ret = parse_arg_function(optctx, opt);
  372. if (ret < 0)
  373. return ret;
  374. }
  375. }
  376. }
  377. return 0;
  378. }
  379. int parse_optgroup(void *optctx, OptionGroup *g, const OptionDef *defs)
  380. {
  381. int i, ret;
  382. av_log(NULL, AV_LOG_DEBUG, "Parsing a group of options: %s %s.\n",
  383. g->group_def->name, g->arg);
  384. for (i = 0; i < g->nb_opts; i++) {
  385. Option *o = &g->opts[i];
  386. if (g->group_def->flags &&
  387. !(g->group_def->flags & o->opt->flags)) {
  388. av_log(NULL, AV_LOG_ERROR, "Option %s (%s) cannot be applied to "
  389. "%s %s -- you are trying to apply an input option to an "
  390. "output file or vice versa. Move this option before the "
  391. "file it belongs to.\n", o->key, o->opt->help,
  392. g->group_def->name, g->arg);
  393. return AVERROR(EINVAL);
  394. }
  395. av_log(NULL, AV_LOG_DEBUG, "Applying option %s (%s) with argument %s.\n",
  396. o->key, o->opt->help, o->val);
  397. ret = write_option(optctx, o->opt, o->key, o->val, defs);
  398. if (ret < 0)
  399. return ret;
  400. }
  401. av_log(NULL, AV_LOG_DEBUG, "Successfully parsed a group of options.\n");
  402. return 0;
  403. }
  404. int locate_option(int argc, char **argv, const OptionDef *options,
  405. const char *optname)
  406. {
  407. const OptionDef *po;
  408. int i;
  409. for (i = 1; i < argc; i++) {
  410. const char *cur_opt = argv[i];
  411. if (*cur_opt++ != '-')
  412. continue;
  413. po = find_option(options, cur_opt);
  414. if (!po->name && cur_opt[0] == 'n' && cur_opt[1] == 'o')
  415. po = find_option(options, cur_opt + 2);
  416. if ((!po->name && !strcmp(cur_opt, optname)) ||
  417. (po->name && !strcmp(optname, po->name)))
  418. return i;
  419. if (!po->name || opt_has_arg(po))
  420. i++;
  421. }
  422. return 0;
  423. }
  424. static void dump_argument(FILE *report_file, const char *a)
  425. {
  426. const unsigned char *p;
  427. for (p = a; *p; p++)
  428. if (!((*p >= '+' && *p <= ':') || (*p >= '@' && *p <= 'Z') ||
  429. *p == '_' || (*p >= 'a' && *p <= 'z')))
  430. break;
  431. if (!*p) {
  432. fputs(a, report_file);
  433. return;
  434. }
  435. fputc('"', report_file);
  436. for (p = a; *p; p++) {
  437. if (*p == '\\' || *p == '"' || *p == '$' || *p == '`')
  438. fprintf(report_file, "\\%c", *p);
  439. else if (*p < ' ' || *p > '~')
  440. fprintf(report_file, "\\x%02x", *p);
  441. else
  442. fputc(*p, report_file);
  443. }
  444. fputc('"', report_file);
  445. }
  446. static void check_options(const OptionDef *po)
  447. {
  448. while (po->name) {
  449. if (po->flags & OPT_PERFILE)
  450. av_assert0(po->flags & (OPT_INPUT | OPT_OUTPUT | OPT_DECODER));
  451. if (po->type == OPT_TYPE_FUNC)
  452. av_assert0(!(po->flags & (OPT_FLAG_OFFSET | OPT_FLAG_SPEC)));
  453. // OPT_FUNC_ARG can only be ser for OPT_TYPE_FUNC
  454. av_assert0((po->type == OPT_TYPE_FUNC) || !(po->flags & OPT_FUNC_ARG));
  455. po++;
  456. }
  457. }
  458. void parse_loglevel(int argc, char **argv, const OptionDef *options)
  459. {
  460. int idx = locate_option(argc, argv, options, "loglevel");
  461. char *env;
  462. check_options(options);
  463. if (!idx)
  464. idx = locate_option(argc, argv, options, "v");
  465. if (idx && argv[idx + 1])
  466. opt_loglevel(NULL, "loglevel", argv[idx + 1]);
  467. idx = locate_option(argc, argv, options, "report");
  468. env = getenv_utf8("FFREPORT");
  469. if (env || idx) {
  470. FILE *report_file = NULL;
  471. init_report(env, &report_file);
  472. if (report_file) {
  473. int i;
  474. fprintf(report_file, "Command line:\n");
  475. for (i = 0; i < argc; i++) {
  476. dump_argument(report_file, argv[i]);
  477. fputc(i < argc - 1 ? ' ' : '\n', report_file);
  478. }
  479. fflush(report_file);
  480. }
  481. }
  482. freeenv_utf8(env);
  483. idx = locate_option(argc, argv, options, "hide_banner");
  484. if (idx)
  485. hide_banner = 1;
  486. }
  487. static const AVOption *opt_find(void *obj, const char *name, const char *unit,
  488. int opt_flags, int search_flags)
  489. {
  490. const AVOption *o = av_opt_find(obj, name, unit, opt_flags, search_flags);
  491. if(o && !o->flags)
  492. return NULL;
  493. return o;
  494. }
  495. #define FLAGS ((o->type == AV_OPT_TYPE_FLAGS && (arg[0]=='-' || arg[0]=='+')) ? AV_DICT_APPEND : 0)
  496. int opt_default(void *optctx, const char *opt, const char *arg)
  497. {
  498. const AVOption *o;
  499. int consumed = 0;
  500. char opt_stripped[128];
  501. const char *p;
  502. const AVClass *cc = avcodec_get_class(), *fc = avformat_get_class();
  503. #if CONFIG_SWSCALE
  504. const AVClass *sc = sws_get_class();
  505. #endif
  506. #if CONFIG_SWRESAMPLE
  507. const AVClass *swr_class = swr_get_class();
  508. #endif
  509. if (!strcmp(opt, "debug") || !strcmp(opt, "fdebug"))
  510. av_log_set_level(AV_LOG_DEBUG);
  511. if (!(p = strchr(opt, ':')))
  512. p = opt + strlen(opt);
  513. av_strlcpy(opt_stripped, opt, FFMIN(sizeof(opt_stripped), p - opt + 1));
  514. if ((o = opt_find(&cc, opt_stripped, NULL, 0,
  515. AV_OPT_SEARCH_CHILDREN | AV_OPT_SEARCH_FAKE_OBJ)) ||
  516. ((opt[0] == 'v' || opt[0] == 'a' || opt[0] == 's') &&
  517. (o = opt_find(&cc, opt + 1, NULL, 0, AV_OPT_SEARCH_FAKE_OBJ)))) {
  518. av_dict_set(&codec_opts, opt, arg, FLAGS);
  519. consumed = 1;
  520. }
  521. if ((o = opt_find(&fc, opt, NULL, 0,
  522. AV_OPT_SEARCH_CHILDREN | AV_OPT_SEARCH_FAKE_OBJ))) {
  523. av_dict_set(&format_opts, opt, arg, FLAGS);
  524. if (consumed)
  525. av_log(NULL, AV_LOG_VERBOSE, "Routing option %s to both codec and muxer layer\n", opt);
  526. consumed = 1;
  527. }
  528. #if CONFIG_SWSCALE
  529. if (!consumed && (o = opt_find(&sc, opt, NULL, 0,
  530. AV_OPT_SEARCH_CHILDREN | AV_OPT_SEARCH_FAKE_OBJ))) {
  531. if (!strcmp(opt, "srcw") || !strcmp(opt, "srch") ||
  532. !strcmp(opt, "dstw") || !strcmp(opt, "dsth") ||
  533. !strcmp(opt, "src_format") || !strcmp(opt, "dst_format")) {
  534. av_log(NULL, AV_LOG_ERROR, "Directly using swscale dimensions/format options is not supported, please use the -s or -pix_fmt options\n");
  535. return AVERROR(EINVAL);
  536. }
  537. av_dict_set(&sws_dict, opt, arg, FLAGS);
  538. consumed = 1;
  539. }
  540. #else
  541. if (!consumed && !strcmp(opt, "sws_flags")) {
  542. av_log(NULL, AV_LOG_WARNING, "Ignoring %s %s, due to disabled swscale\n", opt, arg);
  543. consumed = 1;
  544. }
  545. #endif
  546. #if CONFIG_SWRESAMPLE
  547. if (!consumed && (o=opt_find(&swr_class, opt, NULL, 0,
  548. AV_OPT_SEARCH_CHILDREN | AV_OPT_SEARCH_FAKE_OBJ))) {
  549. av_dict_set(&swr_opts, opt, arg, FLAGS);
  550. consumed = 1;
  551. }
  552. #endif
  553. if (consumed)
  554. return 0;
  555. return AVERROR_OPTION_NOT_FOUND;
  556. }
  557. /*
  558. * Check whether given option is a group separator.
  559. *
  560. * @return index of the group definition that matched or -1 if none
  561. */
  562. static int match_group_separator(const OptionGroupDef *groups, int nb_groups,
  563. const char *opt)
  564. {
  565. int i;
  566. for (i = 0; i < nb_groups; i++) {
  567. const OptionGroupDef *p = &groups[i];
  568. if (p->sep && !strcmp(p->sep, opt))
  569. return i;
  570. }
  571. return -1;
  572. }
  573. /*
  574. * Finish parsing an option group.
  575. *
  576. * @param group_idx which group definition should this group belong to
  577. * @param arg argument of the group delimiting option
  578. */
  579. static int finish_group(OptionParseContext *octx, int group_idx,
  580. const char *arg)
  581. {
  582. OptionGroupList *l = &octx->groups[group_idx];
  583. OptionGroup *g;
  584. int ret;
  585. ret = GROW_ARRAY(l->groups, l->nb_groups);
  586. if (ret < 0)
  587. return ret;
  588. g = &l->groups[l->nb_groups - 1];
  589. *g = octx->cur_group;
  590. g->arg = arg;
  591. g->group_def = l->group_def;
  592. g->sws_dict = sws_dict;
  593. g->swr_opts = swr_opts;
  594. g->codec_opts = codec_opts;
  595. g->format_opts = format_opts;
  596. codec_opts = NULL;
  597. format_opts = NULL;
  598. sws_dict = NULL;
  599. swr_opts = NULL;
  600. memset(&octx->cur_group, 0, sizeof(octx->cur_group));
  601. return ret;
  602. }
  603. /*
  604. * Add an option instance to currently parsed group.
  605. */
  606. static int add_opt(OptionParseContext *octx, const OptionDef *opt,
  607. const char *key, const char *val)
  608. {
  609. int global = !(opt->flags & OPT_PERFILE);
  610. OptionGroup *g = global ? &octx->global_opts : &octx->cur_group;
  611. int ret;
  612. ret = GROW_ARRAY(g->opts, g->nb_opts);
  613. if (ret < 0)
  614. return ret;
  615. g->opts[g->nb_opts - 1].opt = opt;
  616. g->opts[g->nb_opts - 1].key = key;
  617. g->opts[g->nb_opts - 1].val = val;
  618. return 0;
  619. }
  620. static int init_parse_context(OptionParseContext *octx,
  621. const OptionGroupDef *groups, int nb_groups)
  622. {
  623. static const OptionGroupDef global_group = { "global" };
  624. int i;
  625. memset(octx, 0, sizeof(*octx));
  626. octx->groups = av_calloc(nb_groups, sizeof(*octx->groups));
  627. if (!octx->groups)
  628. return AVERROR(ENOMEM);
  629. octx->nb_groups = nb_groups;
  630. for (i = 0; i < octx->nb_groups; i++)
  631. octx->groups[i].group_def = &groups[i];
  632. octx->global_opts.group_def = &global_group;
  633. octx->global_opts.arg = "";
  634. return 0;
  635. }
  636. void uninit_parse_context(OptionParseContext *octx)
  637. {
  638. int i, j;
  639. for (i = 0; i < octx->nb_groups; i++) {
  640. OptionGroupList *l = &octx->groups[i];
  641. for (j = 0; j < l->nb_groups; j++) {
  642. av_freep(&l->groups[j].opts);
  643. av_dict_free(&l->groups[j].codec_opts);
  644. av_dict_free(&l->groups[j].format_opts);
  645. av_dict_free(&l->groups[j].sws_dict);
  646. av_dict_free(&l->groups[j].swr_opts);
  647. }
  648. av_freep(&l->groups);
  649. }
  650. av_freep(&octx->groups);
  651. av_freep(&octx->cur_group.opts);
  652. av_freep(&octx->global_opts.opts);
  653. uninit_opts();
  654. }
  655. int split_commandline(OptionParseContext *octx, int argc, char *argv[],
  656. const OptionDef *options,
  657. const OptionGroupDef *groups, int nb_groups)
  658. {
  659. int ret;
  660. int optindex = 1;
  661. int dashdash = -2;
  662. /* perform system-dependent conversions for arguments list */
  663. prepare_app_arguments(&argc, &argv);
  664. ret = init_parse_context(octx, groups, nb_groups);
  665. if (ret < 0)
  666. return ret;
  667. av_log(NULL, AV_LOG_DEBUG, "Splitting the commandline.\n");
  668. while (optindex < argc) {
  669. const char *opt = argv[optindex++], *arg;
  670. const OptionDef *po;
  671. int ret, group_idx;
  672. av_log(NULL, AV_LOG_DEBUG, "Reading option '%s' ...", opt);
  673. if (opt[0] == '-' && opt[1] == '-' && !opt[2]) {
  674. dashdash = optindex;
  675. continue;
  676. }
  677. /* unnamed group separators, e.g. output filename */
  678. if (opt[0] != '-' || !opt[1] || dashdash+1 == optindex) {
  679. ret = finish_group(octx, 0, opt);
  680. if (ret < 0)
  681. return ret;
  682. av_log(NULL, AV_LOG_DEBUG, " matched as %s.\n", groups[0].name);
  683. continue;
  684. }
  685. opt++;
  686. #define GET_ARG(arg) \
  687. do { \
  688. arg = argv[optindex++]; \
  689. if (!arg) { \
  690. av_log(NULL, AV_LOG_ERROR, "Missing argument for option '%s'.\n", opt);\
  691. return AVERROR(EINVAL); \
  692. } \
  693. } while (0)
  694. /* named group separators, e.g. -i */
  695. group_idx = match_group_separator(groups, nb_groups, opt);
  696. if (group_idx >= 0) {
  697. GET_ARG(arg);
  698. ret = finish_group(octx, group_idx, arg);
  699. if (ret < 0)
  700. return ret;
  701. av_log(NULL, AV_LOG_DEBUG, " matched as %s with argument '%s'.\n",
  702. groups[group_idx].name, arg);
  703. continue;
  704. }
  705. /* normal options */
  706. po = find_option(options, opt);
  707. if (po->name) {
  708. if (po->flags & OPT_EXIT) {
  709. /* optional argument, e.g. -h */
  710. arg = argv[optindex++];
  711. } else if (opt_has_arg(po)) {
  712. GET_ARG(arg);
  713. } else {
  714. arg = "1";
  715. }
  716. ret = add_opt(octx, po, opt, arg);
  717. if (ret < 0)
  718. return ret;
  719. av_log(NULL, AV_LOG_DEBUG, " matched as option '%s' (%s) with "
  720. "argument '%s'.\n", po->name, po->help, arg);
  721. continue;
  722. }
  723. /* AVOptions */
  724. if (argv[optindex]) {
  725. ret = opt_default(NULL, opt, argv[optindex]);
  726. if (ret >= 0) {
  727. av_log(NULL, AV_LOG_DEBUG, " matched as AVOption '%s' with "
  728. "argument '%s'.\n", opt, argv[optindex]);
  729. optindex++;
  730. continue;
  731. } else if (ret != AVERROR_OPTION_NOT_FOUND) {
  732. av_log(NULL, AV_LOG_ERROR, "Error parsing option '%s' "
  733. "with argument '%s'.\n", opt, argv[optindex]);
  734. return ret;
  735. }
  736. }
  737. /* boolean -nofoo options */
  738. if (opt[0] == 'n' && opt[1] == 'o' &&
  739. (po = find_option(options, opt + 2)) &&
  740. po->name && po->type == OPT_TYPE_BOOL) {
  741. ret = add_opt(octx, po, opt, "0");
  742. if (ret < 0)
  743. return ret;
  744. av_log(NULL, AV_LOG_DEBUG, " matched as option '%s' (%s) with "
  745. "argument 0.\n", po->name, po->help);
  746. continue;
  747. }
  748. av_log(NULL, AV_LOG_ERROR, "Unrecognized option '%s'.\n", opt);
  749. return AVERROR_OPTION_NOT_FOUND;
  750. }
  751. if (octx->cur_group.nb_opts || codec_opts || format_opts)
  752. av_log(NULL, AV_LOG_WARNING, "Trailing option(s) found in the "
  753. "command: may be ignored.\n");
  754. av_log(NULL, AV_LOG_DEBUG, "Finished splitting the commandline.\n");
  755. return 0;
  756. }
  757. int read_yesno(void)
  758. {
  759. int c = getchar();
  760. int yesno = (av_toupper(c) == 'Y');
  761. while (c != '\n' && c != EOF)
  762. c = getchar();
  763. return yesno;
  764. }
  765. FILE *get_preset_file(char *filename, size_t filename_size,
  766. const char *preset_name, int is_path,
  767. const char *codec_name)
  768. {
  769. FILE *f = NULL;
  770. int i;
  771. #if HAVE_GETMODULEHANDLE && defined(_WIN32)
  772. char *datadir = NULL;
  773. #endif
  774. char *env_home = getenv_utf8("HOME");
  775. char *env_ffmpeg_datadir = getenv_utf8("FFMPEG_DATADIR");
  776. const char *base[3] = { env_ffmpeg_datadir,
  777. env_home, /* index=1(HOME) is special: search in a .ffmpeg subfolder */
  778. FFMPEG_DATADIR, };
  779. if (is_path) {
  780. av_strlcpy(filename, preset_name, filename_size);
  781. f = fopen_utf8(filename, "r");
  782. } else {
  783. #if HAVE_GETMODULEHANDLE && defined(_WIN32)
  784. wchar_t *datadir_w = get_module_filename(NULL);
  785. base[2] = NULL;
  786. if (wchartoutf8(datadir_w, &datadir))
  787. datadir = NULL;
  788. av_free(datadir_w);
  789. if (datadir)
  790. {
  791. char *ls;
  792. for (ls = datadir; *ls; ls++)
  793. if (*ls == '\\') *ls = '/';
  794. if (ls = strrchr(datadir, '/'))
  795. {
  796. ptrdiff_t datadir_len = ls - datadir;
  797. size_t desired_size = datadir_len + strlen("/ffpresets") + 1;
  798. char *new_datadir = av_realloc_array(
  799. datadir, desired_size, sizeof *datadir);
  800. if (new_datadir) {
  801. datadir = new_datadir;
  802. datadir[datadir_len] = 0;
  803. strncat(datadir, "/ffpresets", desired_size - 1 - datadir_len);
  804. base[2] = datadir;
  805. }
  806. }
  807. }
  808. #endif
  809. for (i = 0; i < 3 && !f; i++) {
  810. if (!base[i])
  811. continue;
  812. snprintf(filename, filename_size, "%s%s/%s.ffpreset", base[i],
  813. i != 1 ? "" : "/.ffmpeg", preset_name);
  814. f = fopen_utf8(filename, "r");
  815. if (!f && codec_name) {
  816. snprintf(filename, filename_size,
  817. "%s%s/%s-%s.ffpreset",
  818. base[i], i != 1 ? "" : "/.ffmpeg", codec_name,
  819. preset_name);
  820. f = fopen_utf8(filename, "r");
  821. }
  822. }
  823. }
  824. #if HAVE_GETMODULEHANDLE && defined(_WIN32)
  825. av_free(datadir);
  826. #endif
  827. freeenv_utf8(env_ffmpeg_datadir);
  828. freeenv_utf8(env_home);
  829. return f;
  830. }
  831. int check_stream_specifier(AVFormatContext *s, AVStream *st, const char *spec)
  832. {
  833. int ret = avformat_match_stream_specifier(s, st, spec);
  834. if (ret < 0)
  835. av_log(s, AV_LOG_ERROR, "Invalid stream specifier: %s.\n", spec);
  836. return ret;
  837. }
  838. int filter_codec_opts(const AVDictionary *opts, enum AVCodecID codec_id,
  839. AVFormatContext *s, AVStream *st, const AVCodec *codec,
  840. AVDictionary **dst)
  841. {
  842. AVDictionary *ret = NULL;
  843. const AVDictionaryEntry *t = NULL;
  844. int flags = s->oformat ? AV_OPT_FLAG_ENCODING_PARAM
  845. : AV_OPT_FLAG_DECODING_PARAM;
  846. char prefix = 0;
  847. const AVClass *cc = avcodec_get_class();
  848. switch (st->codecpar->codec_type) {
  849. case AVMEDIA_TYPE_VIDEO:
  850. prefix = 'v';
  851. flags |= AV_OPT_FLAG_VIDEO_PARAM;
  852. break;
  853. case AVMEDIA_TYPE_AUDIO:
  854. prefix = 'a';
  855. flags |= AV_OPT_FLAG_AUDIO_PARAM;
  856. break;
  857. case AVMEDIA_TYPE_SUBTITLE:
  858. prefix = 's';
  859. flags |= AV_OPT_FLAG_SUBTITLE_PARAM;
  860. break;
  861. }
  862. while (t = av_dict_iterate(opts, t)) {
  863. const AVClass *priv_class;
  864. char *p = strchr(t->key, ':');
  865. /* check stream specification in opt name */
  866. if (p) {
  867. int err = check_stream_specifier(s, st, p + 1);
  868. if (err < 0) {
  869. av_dict_free(&ret);
  870. return err;
  871. } else if (!err)
  872. continue;
  873. *p = 0;
  874. }
  875. if (av_opt_find(&cc, t->key, NULL, flags, AV_OPT_SEARCH_FAKE_OBJ) ||
  876. !codec ||
  877. ((priv_class = codec->priv_class) &&
  878. av_opt_find(&priv_class, t->key, NULL, flags,
  879. AV_OPT_SEARCH_FAKE_OBJ)))
  880. av_dict_set(&ret, t->key, t->value, 0);
  881. else if (t->key[0] == prefix &&
  882. av_opt_find(&cc, t->key + 1, NULL, flags,
  883. AV_OPT_SEARCH_FAKE_OBJ))
  884. av_dict_set(&ret, t->key + 1, t->value, 0);
  885. if (p)
  886. *p = ':';
  887. }
  888. *dst = ret;
  889. return 0;
  890. }
  891. int setup_find_stream_info_opts(AVFormatContext *s,
  892. AVDictionary *codec_opts,
  893. AVDictionary ***dst)
  894. {
  895. int ret;
  896. AVDictionary **opts;
  897. *dst = NULL;
  898. if (!s->nb_streams)
  899. return 0;
  900. opts = av_calloc(s->nb_streams, sizeof(*opts));
  901. if (!opts)
  902. return AVERROR(ENOMEM);
  903. for (int i = 0; i < s->nb_streams; i++) {
  904. ret = filter_codec_opts(codec_opts, s->streams[i]->codecpar->codec_id,
  905. s, s->streams[i], NULL, &opts[i]);
  906. if (ret < 0)
  907. goto fail;
  908. }
  909. *dst = opts;
  910. return 0;
  911. fail:
  912. for (int i = 0; i < s->nb_streams; i++)
  913. av_dict_free(&opts[i]);
  914. av_freep(&opts);
  915. return ret;
  916. }
  917. int grow_array(void **array, int elem_size, int *size, int new_size)
  918. {
  919. if (new_size >= INT_MAX / elem_size) {
  920. av_log(NULL, AV_LOG_ERROR, "Array too big.\n");
  921. return AVERROR(ERANGE);
  922. }
  923. if (*size < new_size) {
  924. uint8_t *tmp = av_realloc_array(*array, new_size, elem_size);
  925. if (!tmp)
  926. return AVERROR(ENOMEM);
  927. memset(tmp + *size*elem_size, 0, (new_size-*size) * elem_size);
  928. *size = new_size;
  929. *array = tmp;
  930. return 0;
  931. }
  932. return 0;
  933. }
  934. void *allocate_array_elem(void *ptr, size_t elem_size, int *nb_elems)
  935. {
  936. void *new_elem;
  937. if (!(new_elem = av_mallocz(elem_size)) ||
  938. av_dynarray_add_nofree(ptr, nb_elems, new_elem) < 0)
  939. return NULL;
  940. return new_elem;
  941. }
  942. double get_rotation(const int32_t *displaymatrix)
  943. {
  944. double theta = 0;
  945. if (displaymatrix)
  946. theta = -round(av_display_rotation_get(displaymatrix));
  947. theta -= 360*floor(theta/360 + 0.9/360);
  948. if (fabs(theta - 90*round(theta/90)) > 2)
  949. av_log(NULL, AV_LOG_WARNING, "Odd rotation angle.\n"
  950. "If you want to help, upload a sample "
  951. "of this file to https://streams.videolan.org/upload/ "
  952. "and contact the ffmpeg-devel mailing list. (ffmpeg-devel@ffmpeg.org)");
  953. return theta;
  954. }
  955. /* read file contents into a string */
  956. char *file_read(const char *filename)
  957. {
  958. AVIOContext *pb = NULL;
  959. int ret = avio_open(&pb, filename, AVIO_FLAG_READ);
  960. AVBPrint bprint;
  961. char *str;
  962. if (ret < 0) {
  963. av_log(NULL, AV_LOG_ERROR, "Error opening file %s.\n", filename);
  964. return NULL;
  965. }
  966. av_bprint_init(&bprint, 0, AV_BPRINT_SIZE_UNLIMITED);
  967. ret = avio_read_to_bprint(pb, &bprint, SIZE_MAX);
  968. avio_closep(&pb);
  969. if (ret < 0) {
  970. av_bprint_finalize(&bprint, NULL);
  971. return NULL;
  972. }
  973. ret = av_bprint_finalize(&bprint, &str);
  974. if (ret < 0)
  975. return NULL;
  976. return str;
  977. }
  978. void remove_avoptions(AVDictionary **a, AVDictionary *b)
  979. {
  980. const AVDictionaryEntry *t = NULL;
  981. while ((t = av_dict_iterate(b, t))) {
  982. av_dict_set(a, t->key, NULL, AV_DICT_MATCH_CASE);
  983. }
  984. }
  985. int check_avoptions(AVDictionary *m)
  986. {
  987. const AVDictionaryEntry *t = av_dict_iterate(m, NULL);
  988. if (t) {
  989. av_log(NULL, AV_LOG_FATAL, "Option %s not found.\n", t->key);
  990. return AVERROR_OPTION_NOT_FOUND;
  991. }
  992. return 0;
  993. }