| 
									
										
										
										
											2003-06-07 18:34:02 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * Various utilities for command line tools | 
					
						
							|  |  |  |  * Copyright (c) 2000-2003 Fabrice Bellard | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2006-10-07 15:30:46 +00:00
										 |  |  |  * This file is part of FFmpeg. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * FFmpeg is free software; you can redistribute it and/or | 
					
						
							| 
									
										
										
										
											2003-06-07 18:34:02 +00:00
										 |  |  |  * modify it under the terms of the GNU Lesser General Public | 
					
						
							|  |  |  |  * License as published by the Free Software Foundation; either | 
					
						
							| 
									
										
										
										
											2006-10-07 15:30:46 +00:00
										 |  |  |  * version 2.1 of the License, or (at your option) any later version. | 
					
						
							| 
									
										
										
										
											2003-06-07 18:34:02 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2006-10-07 15:30:46 +00:00
										 |  |  |  * FFmpeg is distributed in the hope that it will be useful, | 
					
						
							| 
									
										
										
										
											2003-06-07 18:34:02 +00:00
										 |  |  |  * 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 | 
					
						
							| 
									
										
										
										
											2006-10-07 15:30:46 +00:00
										 |  |  |  * License along with FFmpeg; if not, write to the Free Software | 
					
						
							| 
									
										
										
										
											2006-01-12 22:43:26 +00:00
										 |  |  |  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | 
					
						
							| 
									
										
										
										
											2003-06-07 18:34:02 +00:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2007-06-10 14:34:56 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-07-02 07:43:23 +00:00
										 |  |  | #include <string.h>
 | 
					
						
							| 
									
										
										
										
											2013-11-23 21:32:55 +01:00
										 |  |  | #include <stdint.h>
 | 
					
						
							| 
									
										
										
										
											2007-07-02 07:43:23 +00:00
										 |  |  | #include <stdlib.h>
 | 
					
						
							|  |  |  | #include <errno.h>
 | 
					
						
							| 
									
										
										
										
											2008-02-25 14:15:52 +00:00
										 |  |  | #include <math.h>
 | 
					
						
							| 
									
										
										
										
											2007-07-02 07:43:23 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-10-22 10:36:34 +00:00
										 |  |  | /* Include only the enabled headers since some compilers (namely, Sun
 | 
					
						
							|  |  |  |    Studio) will not omit unused inline functions and create undefined | 
					
						
							|  |  |  |    references to libraries that are not being built. */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-03-15 16:17:02 +00:00
										 |  |  | #include "config.h"
 | 
					
						
							| 
									
										
										
										
											2012-09-14 15:08:19 -04:00
										 |  |  | #include "compat/va_copy.h"
 | 
					
						
							| 
									
										
										
										
											2008-05-09 11:56:36 +00:00
										 |  |  | #include "libavformat/avformat.h"
 | 
					
						
							| 
									
										
										
										
											2008-08-29 18:25:14 +00:00
										 |  |  | #include "libswscale/swscale.h"
 | 
					
						
							| 
									
										
										
										
											2022-02-23 14:32:31 +02:00
										 |  |  | #include "libswscale/version.h"
 | 
					
						
							| 
									
										
										
										
											2011-12-22 03:09:58 +01:00
										 |  |  | #include "libswresample/swresample.h"
 | 
					
						
							| 
									
										
										
										
											2012-04-11 10:31:02 +02:00
										 |  |  | #include "libavutil/avassert.h"
 | 
					
						
							| 
									
										
										
										
											2008-05-09 11:56:36 +00:00
										 |  |  | #include "libavutil/avstring.h"
 | 
					
						
							| 
									
										
										
										
											2021-06-12 01:10:58 +02:00
										 |  |  | #include "libavutil/channel_layout.h"
 | 
					
						
							| 
									
										
										
										
											2015-05-03 23:49:16 +02:00
										 |  |  | #include "libavutil/display.h"
 | 
					
						
							| 
									
										
										
										
											2022-06-20 13:29:59 +03:00
										 |  |  | #include "libavutil/getenv_utf8.h"
 | 
					
						
							| 
									
										
										
										
											2011-07-17 11:19:35 +01:00
										 |  |  | #include "libavutil/mathematics.h"
 | 
					
						
							| 
									
										
										
										
											2012-05-30 07:57:59 +02:00
										 |  |  | #include "libavutil/imgutils.h"
 | 
					
						
							| 
									
										
										
										
											2015-05-05 11:49:44 +02:00
										 |  |  | #include "libavutil/libm.h"
 | 
					
						
							| 
									
										
										
										
											2011-02-16 08:52:36 +00:00
										 |  |  | #include "libavutil/parseutils.h"
 | 
					
						
							| 
									
										
										
										
											2010-06-09 21:28:53 +00:00
										 |  |  | #include "libavutil/eval.h"
 | 
					
						
							| 
									
										
										
										
											2011-05-25 16:42:41 +02:00
										 |  |  | #include "libavutil/dict.h"
 | 
					
						
							| 
									
										
										
										
											2011-02-03 14:58:59 +01:00
										 |  |  | #include "libavutil/opt.h"
 | 
					
						
							| 
									
										
										
										
											2003-06-07 18:34:02 +00:00
										 |  |  | #include "cmdutils.h"
 | 
					
						
							| 
									
										
										
										
											2022-06-20 13:29:59 +03:00
										 |  |  | #include "fopen_utf8.h"
 | 
					
						
							| 
									
										
										
										
											2022-03-09 12:11:09 +01:00
										 |  |  | #include "opt_common.h"
 | 
					
						
							| 
									
										
										
										
											2016-08-29 15:25:58 +02:00
										 |  |  | #ifdef _WIN32
 | 
					
						
							|  |  |  | #include <windows.h>
 | 
					
						
							| 
									
										
										
										
											2022-06-20 13:29:59 +03:00
										 |  |  | #include "compat/w32dlfcn.h"
 | 
					
						
							| 
									
										
										
										
											2016-08-29 15:25:58 +02:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2003-06-07 18:34:02 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-08 12:43:10 +02:00
										 |  |  | AVDictionary *sws_dict; | 
					
						
							| 
									
										
										
										
											2013-02-24 19:07:42 +01:00
										 |  |  | AVDictionary *swr_opts; | 
					
						
							| 
									
										
										
										
											2021-09-03 13:54:45 +02:00
										 |  |  | AVDictionary *format_opts, *codec_opts; | 
					
						
							| 
									
										
										
										
											2008-02-21 12:24:37 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-12-28 05:18:39 +01:00
										 |  |  | int hide_banner = 0; | 
					
						
							| 
									
										
										
										
											2011-12-08 14:42:24 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-02 08:44:33 +00:00
										 |  |  | void uninit_opts(void) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2013-02-24 19:07:42 +01:00
										 |  |  |     av_dict_free(&swr_opts); | 
					
						
							| 
									
										
										
										
											2015-08-08 12:43:10 +02:00
										 |  |  |     av_dict_free(&sws_dict); | 
					
						
							| 
									
										
										
										
											2011-05-25 16:42:41 +02:00
										 |  |  |     av_dict_free(&format_opts); | 
					
						
							| 
									
										
										
										
											2011-07-10 15:46:15 +02:00
										 |  |  |     av_dict_free(&codec_opts); | 
					
						
							| 
									
										
										
										
											2010-10-02 08:44:33 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-12-31 18:01:54 +05:30
										 |  |  | void log_callback_help(void *ptr, int level, const char *fmt, va_list vl) | 
					
						
							| 
									
										
										
										
											2010-09-20 21:48:03 +00:00
										 |  |  | { | 
					
						
							|  |  |  |     vfprintf(stdout, fmt, vl); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-08 15:27:41 +02:00
										 |  |  | void init_dynload(void) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2020-01-08 13:29:07 +02:00
										 |  |  | #if HAVE_SETDLLDIRECTORY && defined(_WIN32)
 | 
					
						
							| 
									
										
										
										
											2016-08-08 15:27:41 +02:00
										 |  |  |     /* Calling SetDllDirectory with the empty string (but not NULL) removes the
 | 
					
						
							|  |  |  |      * current working directory from the DLL search path as a security pre-caution. */ | 
					
						
							|  |  |  |     SetDllDirectory(""); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-12-15 08:50:26 +01:00
										 |  |  | int parse_number(const char *context, const char *numstr, enum OptionType type, | 
					
						
							| 
									
										
										
										
											2023-07-14 13:47:23 +02:00
										 |  |  |                  double min, double max, double *dst) | 
					
						
							| 
									
										
										
										
											2008-02-21 12:24:37 +00:00
										 |  |  | { | 
					
						
							|  |  |  |     char *tail; | 
					
						
							|  |  |  |     const char *error; | 
					
						
							| 
									
										
										
										
											2010-06-09 21:28:53 +00:00
										 |  |  |     double d = av_strtod(numstr, &tail); | 
					
						
							| 
									
										
										
										
											2008-02-21 12:24:37 +00:00
										 |  |  |     if (*tail) | 
					
						
							| 
									
										
										
										
											2011-12-31 18:01:54 +05:30
										 |  |  |         error = "Expected number for %s but found: %s\n"; | 
					
						
							| 
									
										
										
										
											2008-02-21 12:24:37 +00:00
										 |  |  |     else if (d < min || d > max) | 
					
						
							| 
									
										
										
										
											2011-12-31 18:01:54 +05:30
										 |  |  |         error = "The value for %s was %s which is not within %f - %f\n"; | 
					
						
							| 
									
										
										
										
											2023-12-15 08:50:26 +01:00
										 |  |  |     else if (type == OPT_TYPE_INT64 && (int64_t)d != d) | 
					
						
							| 
									
										
										
										
											2011-12-31 18:01:54 +05:30
										 |  |  |         error = "Expected int64 for %s but found %s\n"; | 
					
						
							| 
									
										
										
										
											2023-12-15 08:50:26 +01:00
										 |  |  |     else if (type == OPT_TYPE_INT && (int)d != d) | 
					
						
							| 
									
										
										
										
											2011-12-31 18:01:54 +05:30
										 |  |  |         error = "Expected int for %s but found %s\n"; | 
					
						
							| 
									
										
										
										
											2023-07-14 13:47:23 +02:00
										 |  |  |     else { | 
					
						
							|  |  |  |         *dst = d; | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-26 08:39:43 +02:00
										 |  |  |     av_log(NULL, AV_LOG_FATAL, error, context, numstr, min, max); | 
					
						
							| 
									
										
										
										
											2023-07-14 13:47:23 +02:00
										 |  |  |     return AVERROR(EINVAL); | 
					
						
							| 
									
										
										
										
											2008-02-21 12:24:37 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-11 19:45:30 +02:00
										 |  |  | void show_help_options(const OptionDef *options, const char *msg, int req_flags, | 
					
						
							| 
									
										
										
										
											2012-08-15 10:31:46 +02:00
										 |  |  |                        int rej_flags, int alt_flags) | 
					
						
							| 
									
										
										
										
											2003-06-07 18:34:02 +00:00
										 |  |  | { | 
					
						
							|  |  |  |     const OptionDef *po; | 
					
						
							| 
									
										
										
										
											2003-08-24 15:29:48 +00:00
										 |  |  |     int first; | 
					
						
							| 
									
										
										
										
											2003-06-07 18:34:02 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-08-24 15:29:48 +00:00
										 |  |  |     first = 1; | 
					
						
							| 
									
										
										
										
											2014-08-15 21:31:59 +02:00
										 |  |  |     for (po = options; po->name; po++) { | 
					
						
							| 
									
										
										
										
											2019-12-12 16:02:53 +08:00
										 |  |  |         char buf[128]; | 
					
						
							| 
									
										
										
										
											2012-08-11 19:45:30 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         if (((po->flags & req_flags) != req_flags) || | 
					
						
							| 
									
										
										
										
											2012-08-15 10:31:46 +02:00
										 |  |  |             (alt_flags && !(po->flags & alt_flags)) || | 
					
						
							| 
									
										
										
										
											2012-08-11 19:45:30 +02:00
										 |  |  |             (po->flags & rej_flags)) | 
					
						
							|  |  |  |             continue; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (first) { | 
					
						
							|  |  |  |             printf("%s\n", msg); | 
					
						
							|  |  |  |             first = 0; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         av_strlcpy(buf, po->name, sizeof(buf)); | 
					
						
							| 
									
										
										
										
											2012-08-13 20:06:25 +02:00
										 |  |  |         if (po->argname) { | 
					
						
							| 
									
										
										
										
											2012-08-11 19:45:30 +02:00
										 |  |  |             av_strlcat(buf, " ", sizeof(buf)); | 
					
						
							|  |  |  |             av_strlcat(buf, po->argname, sizeof(buf)); | 
					
						
							| 
									
										
										
										
											2003-06-07 18:34:02 +00:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2012-08-11 19:45:30 +02:00
										 |  |  |         printf("-%-17s  %s\n", buf, po->help); | 
					
						
							| 
									
										
										
										
											2003-06-07 18:34:02 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2012-08-11 19:33:27 +02:00
										 |  |  |     printf("\n"); | 
					
						
							| 
									
										
										
										
											2003-06-07 18:34:02 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-04 14:50:00 +02:00
										 |  |  | void show_help_children(const AVClass *class, int flags) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2020-05-27 15:25:38 +02:00
										 |  |  |     void *iter = NULL; | 
					
						
							|  |  |  |     const AVClass *child; | 
					
						
							| 
									
										
										
										
											2012-08-09 14:44:18 +02:00
										 |  |  |     if (class->option) { | 
					
						
							|  |  |  |         av_opt_show2(&class, NULL, flags, 0); | 
					
						
							|  |  |  |         printf("\n"); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2011-10-04 14:50:00 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-27 15:25:38 +02:00
										 |  |  |     while (child = av_opt_child_class_iterate(class, &iter)) | 
					
						
							| 
									
										
										
										
											2011-10-04 14:50:00 +02:00
										 |  |  |         show_help_children(child, flags); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-12-31 18:01:54 +05:30
										 |  |  | static const OptionDef *find_option(const OptionDef *po, const char *name) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2014-08-14 16:31:25 -04:00
										 |  |  |     while (po->name) { | 
					
						
							| 
									
										
										
										
											2021-02-24 07:41:27 +01:00
										 |  |  |         const char *end; | 
					
						
							|  |  |  |         if (av_strstart(name, po->name, &end) && (!*end || *end == ':')) | 
					
						
							| 
									
										
										
										
											2005-09-11 11:10:25 +00:00
										 |  |  |             break; | 
					
						
							|  |  |  |         po++; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return po; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-08-07 08:25:51 -03:00
										 |  |  | /* _WIN32 means using the windows libc - cygwin doesn't define that
 | 
					
						
							|  |  |  |  * by default. HAVE_COMMANDLINETOARGVW is true on cygwin, while | 
					
						
							|  |  |  |  * it doesn't provide the actual command line via GetCommandLineW(). */ | 
					
						
							|  |  |  | #if HAVE_COMMANDLINETOARGVW && defined(_WIN32)
 | 
					
						
							| 
									
										
										
										
											2012-07-07 13:46:26 -07:00
										 |  |  | #include <shellapi.h>
 | 
					
						
							| 
									
										
										
										
											2011-04-20 14:36:44 +03:00
										 |  |  | /* Will be leaked on exit */ | 
					
						
							|  |  |  | static char** win32_argv_utf8 = NULL; | 
					
						
							|  |  |  | static int win32_argc = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /**
 | 
					
						
							|  |  |  |  * Prepare command line arguments for executable. | 
					
						
							|  |  |  |  * For Windows - perform wide-char to UTF-8 conversion. | 
					
						
							|  |  |  |  * Input arguments should be main() function arguments. | 
					
						
							|  |  |  |  * @param argc_ptr Arguments number (including executable) | 
					
						
							|  |  |  |  * @param argv_ptr Arguments list. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | static void prepare_app_arguments(int *argc_ptr, char ***argv_ptr) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     char *argstr_flat; | 
					
						
							|  |  |  |     wchar_t **argv_w; | 
					
						
							|  |  |  |     int i, buffsize = 0, offset = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (win32_argv_utf8) { | 
					
						
							|  |  |  |         *argc_ptr = win32_argc; | 
					
						
							|  |  |  |         *argv_ptr = win32_argv_utf8; | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     win32_argc = 0; | 
					
						
							|  |  |  |     argv_w = CommandLineToArgvW(GetCommandLineW(), &win32_argc); | 
					
						
							|  |  |  |     if (win32_argc <= 0 || !argv_w) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* determine the UTF-8 buffer size (including NULL-termination symbols) */ | 
					
						
							|  |  |  |     for (i = 0; i < win32_argc; i++) | 
					
						
							|  |  |  |         buffsize += WideCharToMultiByte(CP_UTF8, 0, argv_w[i], -1, | 
					
						
							|  |  |  |                                         NULL, 0, NULL, NULL); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-12-31 18:01:54 +05:30
										 |  |  |     win32_argv_utf8 = av_mallocz(sizeof(char *) * (win32_argc + 1) + buffsize); | 
					
						
							|  |  |  |     argstr_flat     = (char *)win32_argv_utf8 + sizeof(char *) * (win32_argc + 1); | 
					
						
							| 
									
										
										
										
											2014-08-14 16:31:24 -04:00
										 |  |  |     if (!win32_argv_utf8) { | 
					
						
							| 
									
										
										
										
											2011-04-20 14:36:44 +03:00
										 |  |  |         LocalFree(argv_w); | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (i = 0; i < win32_argc; i++) { | 
					
						
							|  |  |  |         win32_argv_utf8[i] = &argstr_flat[offset]; | 
					
						
							|  |  |  |         offset += WideCharToMultiByte(CP_UTF8, 0, argv_w[i], -1, | 
					
						
							|  |  |  |                                       &argstr_flat[offset], | 
					
						
							|  |  |  |                                       buffsize - offset, NULL, NULL); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     win32_argv_utf8[i] = NULL; | 
					
						
							|  |  |  |     LocalFree(argv_w); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     *argc_ptr = win32_argc; | 
					
						
							|  |  |  |     *argv_ptr = win32_argv_utf8; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | static inline void prepare_app_arguments(int *argc_ptr, char ***argv_ptr) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     /* nothing to do */ | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2012-11-29 17:02:24 +02:00
										 |  |  | #endif /* HAVE_COMMANDLINETOARGVW */
 | 
					
						
							| 
									
										
										
										
											2011-04-20 14:36:44 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-12-15 08:24:14 +01:00
										 |  |  | static int opt_has_arg(const OptionDef *o) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2023-12-15 08:50:26 +01:00
										 |  |  |     if (o->type == OPT_TYPE_BOOL) | 
					
						
							| 
									
										
										
										
											2023-12-15 08:24:14 +01:00
										 |  |  |         return 0; | 
					
						
							| 
									
										
										
										
											2023-12-15 08:50:26 +01:00
										 |  |  |     if (o->type == OPT_TYPE_FUNC) | 
					
						
							| 
									
										
										
										
											2023-12-17 10:45:45 +01:00
										 |  |  |         return !!(o->flags & OPT_FUNC_ARG); | 
					
						
							| 
									
										
										
										
											2023-12-15 08:50:26 +01:00
										 |  |  |     return 1; | 
					
						
							| 
									
										
										
										
											2023-12-15 08:24:14 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-06-10 17:57:52 +02:00
										 |  |  | static int write_option(void *optctx, const OptionDef *po, const char *opt, | 
					
						
							| 
									
										
										
										
											2023-12-17 18:10:17 +01:00
										 |  |  |                         const char *arg, const OptionDef *defs) | 
					
						
							| 
									
										
										
										
											2003-06-07 18:34:02 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2011-08-29 08:11:03 +02:00
										 |  |  |     /* new-style options contain an offset into optctx, old-style address of
 | 
					
						
							|  |  |  |      * a global var*/ | 
					
						
							| 
									
										
										
										
											2023-12-17 11:47:33 +01:00
										 |  |  |     void *dst = po->flags & OPT_FLAG_OFFSET ? | 
					
						
							| 
									
										
										
										
											2012-06-10 17:57:52 +02:00
										 |  |  |                 (uint8_t *)optctx + po->u.off : po->u.dst_ptr; | 
					
						
							| 
									
										
										
										
											2023-12-17 14:42:38 +01:00
										 |  |  |     SpecifierOptList *sol = NULL; | 
					
						
							| 
									
										
										
										
											2023-07-14 13:47:23 +02:00
										 |  |  |     double num; | 
					
						
							| 
									
										
										
										
											2023-07-14 12:28:18 +02:00
										 |  |  |     int ret; | 
					
						
							| 
									
										
										
										
											2011-08-29 07:54:56 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-12-17 11:47:33 +01:00
										 |  |  |     if (po->flags & OPT_FLAG_SPEC) { | 
					
						
							| 
									
										
										
										
											2011-08-29 07:54:56 +02:00
										 |  |  |         char *p = strchr(opt, ':'); | 
					
						
							| 
									
										
										
										
											2014-12-17 14:53:45 +01:00
										 |  |  |         char *str; | 
					
						
							| 
									
										
										
										
											2011-08-29 07:54:56 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-12-17 14:42:38 +01:00
										 |  |  |         sol = dst; | 
					
						
							| 
									
										
										
										
											2023-12-17 14:20:57 +01:00
										 |  |  |         ret = GROW_ARRAY(sol->opt, sol->nb_opt); | 
					
						
							| 
									
										
										
										
											2023-07-14 12:28:18 +02:00
										 |  |  |         if (ret < 0) | 
					
						
							|  |  |  |             return ret; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-17 14:53:45 +01:00
										 |  |  |         str = av_strdup(p ? p + 1 : ""); | 
					
						
							|  |  |  |         if (!str) | 
					
						
							|  |  |  |             return AVERROR(ENOMEM); | 
					
						
							| 
									
										
										
										
											2023-12-17 14:20:57 +01:00
										 |  |  |         sol->opt[sol->nb_opt - 1].specifier = str; | 
					
						
							|  |  |  |         dst = &sol->opt[sol->nb_opt - 1].u; | 
					
						
							| 
									
										
										
										
											2011-08-29 07:54:56 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2011-08-29 08:11:03 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-12-15 08:50:26 +01:00
										 |  |  |     if (po->type == OPT_TYPE_STRING) { | 
					
						
							| 
									
										
										
										
											2011-08-29 08:11:03 +02:00
										 |  |  |         char *str; | 
					
						
							|  |  |  |         str = av_strdup(arg); | 
					
						
							| 
									
										
										
										
											2012-11-15 17:11:04 +02:00
										 |  |  |         av_freep(dst); | 
					
						
							| 
									
										
										
										
											2014-12-17 14:53:45 +01:00
										 |  |  |         if (!str) | 
					
						
							|  |  |  |             return AVERROR(ENOMEM); | 
					
						
							| 
									
										
										
										
											2011-12-31 18:01:54 +05:30
										 |  |  |         *(char **)dst = str; | 
					
						
							| 
									
										
										
										
											2023-12-15 08:50:26 +01:00
										 |  |  |     } else if (po->type == OPT_TYPE_BOOL || po->type == OPT_TYPE_INT) { | 
					
						
							|  |  |  |         ret = parse_number(opt, arg, OPT_TYPE_INT64, INT_MIN, INT_MAX, &num); | 
					
						
							| 
									
										
										
										
											2023-07-14 13:47:23 +02:00
										 |  |  |         if (ret < 0) | 
					
						
							|  |  |  |             return ret; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         *(int *)dst = num; | 
					
						
							| 
									
										
										
										
											2023-12-15 08:50:26 +01:00
										 |  |  |     } else if (po->type == OPT_TYPE_INT64) { | 
					
						
							|  |  |  |         ret = parse_number(opt, arg, OPT_TYPE_INT64, INT64_MIN, INT64_MAX, &num); | 
					
						
							| 
									
										
										
										
											2023-07-14 13:47:23 +02:00
										 |  |  |         if (ret < 0) | 
					
						
							|  |  |  |             return ret; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         *(int64_t *)dst = num; | 
					
						
							| 
									
										
										
										
											2023-12-15 08:50:26 +01:00
										 |  |  |     } else if (po->type == OPT_TYPE_TIME) { | 
					
						
							| 
									
										
										
										
											2023-07-14 16:37:19 +02:00
										 |  |  |         ret = av_parse_time(dst, arg, 1); | 
					
						
							|  |  |  |         if (ret < 0) { | 
					
						
							|  |  |  |             av_log(NULL, AV_LOG_ERROR, "Invalid duration for option %s: %s\n", | 
					
						
							|  |  |  |                    opt, arg); | 
					
						
							|  |  |  |             return ret; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2023-12-15 08:50:26 +01:00
										 |  |  |     } else if (po->type == OPT_TYPE_FLOAT) { | 
					
						
							|  |  |  |         ret = parse_number(opt, arg, OPT_TYPE_FLOAT, -INFINITY, INFINITY, &num); | 
					
						
							| 
									
										
										
										
											2023-07-14 13:47:23 +02:00
										 |  |  |         if (ret < 0) | 
					
						
							|  |  |  |             return ret; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         *(float *)dst = num; | 
					
						
							| 
									
										
										
										
											2023-12-15 08:50:26 +01:00
										 |  |  |     } else if (po->type == OPT_TYPE_DOUBLE) { | 
					
						
							|  |  |  |         ret = parse_number(opt, arg, OPT_TYPE_DOUBLE, -INFINITY, INFINITY, &num); | 
					
						
							| 
									
										
										
										
											2023-07-14 13:47:23 +02:00
										 |  |  |         if (ret < 0) | 
					
						
							|  |  |  |             return ret; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         *(double *)dst = num; | 
					
						
							| 
									
										
										
										
											2023-12-15 08:50:26 +01:00
										 |  |  |     } else { | 
					
						
							|  |  |  |         int ret; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         av_assert0(po->type == OPT_TYPE_FUNC && po->u.func_arg); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         ret = po->u.func_arg(optctx, opt, arg); | 
					
						
							| 
									
										
										
										
											2011-08-29 08:11:03 +02:00
										 |  |  |         if (ret < 0) { | 
					
						
							| 
									
										
										
										
											2011-12-31 18:01:54 +05:30
										 |  |  |             av_log(NULL, AV_LOG_ERROR, | 
					
						
							| 
									
										
										
										
											2013-03-10 15:36:20 +01:00
										 |  |  |                    "Failed to set value '%s' for option '%s': %s\n", | 
					
						
							|  |  |  |                    arg, opt, av_err2str(ret)); | 
					
						
							| 
									
										
										
										
											2011-08-29 08:11:03 +02:00
										 |  |  |             return ret; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (po->flags & OPT_EXIT) | 
					
						
							| 
									
										
										
										
											2023-07-14 18:15:27 +02:00
										 |  |  |         return AVERROR_EXIT; | 
					
						
							| 
									
										
										
										
											2012-06-10 17:57:52 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-12-17 18:10:17 +01:00
										 |  |  |     if (sol) { | 
					
						
							| 
									
										
										
										
											2023-12-17 14:42:38 +01:00
										 |  |  |         sol->type = po->type; | 
					
						
							| 
									
										
										
										
											2023-12-17 18:10:17 +01:00
										 |  |  |         sol->opt_canon = (po->flags & OPT_HAS_CANON) ? | 
					
						
							|  |  |  |                          find_option(defs, po->u1.name_canon) : po; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-12-17 14:42:38 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-06-10 17:57:52 +02:00
										 |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int parse_option(void *optctx, const char *opt, const char *arg, | 
					
						
							|  |  |  |                  const OptionDef *options) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2022-03-09 21:46:43 +01:00
										 |  |  |     static const OptionDef opt_avoptions = { | 
					
						
							|  |  |  |         .name       = "AVOption passthrough", | 
					
						
							| 
									
										
										
										
											2023-12-15 08:50:26 +01:00
										 |  |  |         .type       = OPT_TYPE_FUNC, | 
					
						
							| 
									
										
										
										
											2023-12-17 10:45:45 +01:00
										 |  |  |         .flags      = OPT_FUNC_ARG, | 
					
						
							| 
									
										
										
										
											2022-03-09 21:46:43 +01:00
										 |  |  |         .u.func_arg = opt_default, | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-06-10 17:57:52 +02:00
										 |  |  |     const OptionDef *po; | 
					
						
							|  |  |  |     int ret; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     po = find_option(options, opt); | 
					
						
							|  |  |  |     if (!po->name && opt[0] == 'n' && opt[1] == 'o') { | 
					
						
							|  |  |  |         /* handle 'no' bool option */ | 
					
						
							|  |  |  |         po = find_option(options, opt + 2); | 
					
						
							| 
									
										
										
										
											2023-12-15 08:50:26 +01:00
										 |  |  |         if ((po->name && po->type == OPT_TYPE_BOOL)) | 
					
						
							| 
									
										
										
										
											2012-06-10 17:57:52 +02:00
										 |  |  |             arg = "0"; | 
					
						
							| 
									
										
										
										
											2023-12-15 08:50:26 +01:00
										 |  |  |     } else if (po->type == OPT_TYPE_BOOL) | 
					
						
							| 
									
										
										
										
											2012-06-10 17:57:52 +02:00
										 |  |  |         arg = "1"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!po->name) | 
					
						
							| 
									
										
										
										
											2022-03-09 21:46:43 +01:00
										 |  |  |         po = &opt_avoptions; | 
					
						
							| 
									
										
										
										
											2012-06-10 17:57:52 +02:00
										 |  |  |     if (!po->name) { | 
					
						
							|  |  |  |         av_log(NULL, AV_LOG_ERROR, "Unrecognized option '%s'\n", opt); | 
					
						
							|  |  |  |         return AVERROR(EINVAL); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-12-15 08:24:14 +01:00
										 |  |  |     if (opt_has_arg(po) && !arg) { | 
					
						
							| 
									
										
										
										
											2012-06-10 17:57:52 +02:00
										 |  |  |         av_log(NULL, AV_LOG_ERROR, "Missing argument for option '%s'\n", opt); | 
					
						
							|  |  |  |         return AVERROR(EINVAL); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-12-17 18:10:17 +01:00
										 |  |  |     ret = write_option(optctx, po, opt, arg, options); | 
					
						
							| 
									
										
										
										
											2012-06-10 17:57:52 +02:00
										 |  |  |     if (ret < 0) | 
					
						
							|  |  |  |         return ret; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-12-15 08:24:14 +01:00
										 |  |  |     return opt_has_arg(po); | 
					
						
							| 
									
										
										
										
											2011-08-29 08:11:03 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-14 16:43:51 +02:00
										 |  |  | int parse_options(void *optctx, int argc, char **argv, const OptionDef *options, | 
					
						
							|  |  |  |                   int (*parse_arg_function)(void *, const char*)) | 
					
						
							| 
									
										
										
										
											2003-06-07 18:34:02 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2011-08-29 08:11:03 +02:00
										 |  |  |     const char *opt; | 
					
						
							|  |  |  |     int optindex, handleoptions = 1, ret; | 
					
						
							| 
									
										
										
										
											2003-06-07 18:34:02 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-20 14:36:44 +03:00
										 |  |  |     /* perform system-dependent conversions for arguments list */ | 
					
						
							|  |  |  |     prepare_app_arguments(&argc, &argv); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-06-07 18:34:02 +00:00
										 |  |  |     /* parse options */ | 
					
						
							|  |  |  |     optindex = 1; | 
					
						
							|  |  |  |     while (optindex < argc) { | 
					
						
							|  |  |  |         opt = argv[optindex++]; | 
					
						
							| 
									
										
										
										
											2005-12-17 18:14:38 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-11-27 12:37:43 +00:00
										 |  |  |         if (handleoptions && opt[0] == '-' && opt[1] != '\0') { | 
					
						
							| 
									
										
										
										
											2008-12-18 00:13:19 +00:00
										 |  |  |             if (opt[1] == '-' && opt[2] == '\0') { | 
					
						
							|  |  |  |                 handleoptions = 0; | 
					
						
							|  |  |  |                 continue; | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2009-12-14 23:47:22 +00:00
										 |  |  |             opt++; | 
					
						
							| 
									
										
										
										
											2011-08-29 08:11:03 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |             if ((ret = parse_option(optctx, opt, argv[optindex], options)) < 0) | 
					
						
							| 
									
										
										
										
											2023-07-14 16:43:51 +02:00
										 |  |  |                 return ret; | 
					
						
							| 
									
										
										
										
											2011-08-29 08:11:03 +02:00
										 |  |  |             optindex += ret; | 
					
						
							| 
									
										
										
										
											2003-06-07 18:34:02 +00:00
										 |  |  |         } else { | 
					
						
							| 
									
										
										
										
											2023-07-14 16:43:51 +02:00
										 |  |  |             if (parse_arg_function) { | 
					
						
							|  |  |  |                 ret = parse_arg_function(optctx, opt); | 
					
						
							|  |  |  |                 if (ret < 0) | 
					
						
							|  |  |  |                     return ret; | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2003-06-07 18:34:02 +00:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-07-14 16:43:51 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     return 0; | 
					
						
							| 
									
										
										
										
											2003-06-07 18:34:02 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-12-17 18:10:17 +01:00
										 |  |  | int parse_optgroup(void *optctx, OptionGroup *g, const OptionDef *defs) | 
					
						
							| 
									
										
										
										
											2012-06-10 20:46:30 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     int i, ret; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     av_log(NULL, AV_LOG_DEBUG, "Parsing a group of options: %s %s.\n", | 
					
						
							|  |  |  |            g->group_def->name, g->arg); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (i = 0; i < g->nb_opts; i++) { | 
					
						
							|  |  |  |         Option *o = &g->opts[i]; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-02-20 08:02:16 +01:00
										 |  |  |         if (g->group_def->flags && | 
					
						
							|  |  |  |             !(g->group_def->flags & o->opt->flags)) { | 
					
						
							|  |  |  |             av_log(NULL, AV_LOG_ERROR, "Option %s (%s) cannot be applied to " | 
					
						
							|  |  |  |                    "%s %s -- you are trying to apply an input option to an " | 
					
						
							|  |  |  |                    "output file or vice versa. Move this option before the " | 
					
						
							|  |  |  |                    "file it belongs to.\n", o->key, o->opt->help, | 
					
						
							|  |  |  |                    g->group_def->name, g->arg); | 
					
						
							|  |  |  |             return AVERROR(EINVAL); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-06-10 20:46:30 +02:00
										 |  |  |         av_log(NULL, AV_LOG_DEBUG, "Applying option %s (%s) with argument %s.\n", | 
					
						
							|  |  |  |                o->key, o->opt->help, o->val); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-12-17 18:10:17 +01:00
										 |  |  |         ret = write_option(optctx, o->opt, o->key, o->val, defs); | 
					
						
							| 
									
										
										
										
											2012-06-10 20:46:30 +02:00
										 |  |  |         if (ret < 0) | 
					
						
							|  |  |  |             return ret; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     av_log(NULL, AV_LOG_DEBUG, "Successfully parsed a group of options.\n"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-04 16:46:45 +01:00
										 |  |  | int locate_option(int argc, char **argv, const OptionDef *options, | 
					
						
							|  |  |  |                   const char *optname) | 
					
						
							| 
									
										
										
										
											2011-09-26 08:15:37 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     const OptionDef *po; | 
					
						
							|  |  |  |     int i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (i = 1; i < argc; i++) { | 
					
						
							|  |  |  |         const char *cur_opt = argv[i]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (*cur_opt++ != '-') | 
					
						
							|  |  |  |             continue; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         po = find_option(options, cur_opt); | 
					
						
							|  |  |  |         if (!po->name && cur_opt[0] == 'n' && cur_opt[1] == 'o') | 
					
						
							|  |  |  |             po = find_option(options, cur_opt + 2); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if ((!po->name && !strcmp(cur_opt, optname)) || | 
					
						
							|  |  |  |              (po->name && !strcmp(optname, po->name))) | 
					
						
							|  |  |  |             return i; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-12-15 08:24:14 +01:00
										 |  |  |         if (!po->name || opt_has_arg(po)) | 
					
						
							| 
									
										
										
										
											2011-09-26 08:15:37 +02:00
										 |  |  |             i++; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-09 12:11:09 +01:00
										 |  |  | static void dump_argument(FILE *report_file, const char *a) | 
					
						
							| 
									
										
										
										
											2011-12-08 14:42:24 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     const unsigned char *p; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (p = a; *p; p++) | 
					
						
							|  |  |  |         if (!((*p >= '+' && *p <= ':') || (*p >= '@' && *p <= 'Z') || | 
					
						
							|  |  |  |               *p == '_' || (*p >= 'a' && *p <= 'z'))) | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |     if (!*p) { | 
					
						
							|  |  |  |         fputs(a, report_file); | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     fputc('"', report_file); | 
					
						
							|  |  |  |     for (p = a; *p; p++) { | 
					
						
							|  |  |  |         if (*p == '\\' || *p == '"' || *p == '$' || *p == '`') | 
					
						
							|  |  |  |             fprintf(report_file, "\\%c", *p); | 
					
						
							|  |  |  |         else if (*p < ' ' || *p > '~') | 
					
						
							|  |  |  |             fprintf(report_file, "\\x%02x", *p); | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |             fputc(*p, report_file); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     fputc('"', report_file); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-09 13:07:21 +02:00
										 |  |  | static void check_options(const OptionDef *po) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     while (po->name) { | 
					
						
							|  |  |  |         if (po->flags & OPT_PERFILE) | 
					
						
							|  |  |  |             av_assert0(po->flags & (OPT_INPUT | OPT_OUTPUT)); | 
					
						
							| 
									
										
										
										
											2023-12-17 10:45:45 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-12-17 12:03:49 +01:00
										 |  |  |         if (po->type == OPT_TYPE_FUNC) | 
					
						
							|  |  |  |             av_assert0(!(po->flags & (OPT_FLAG_OFFSET | OPT_FLAG_SPEC))); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-12-17 10:45:45 +01:00
										 |  |  |         // OPT_FUNC_ARG can only be ser for OPT_TYPE_FUNC
 | 
					
						
							|  |  |  |         av_assert0((po->type == OPT_TYPE_FUNC) || !(po->flags & OPT_FUNC_ARG)); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-09 13:07:21 +02:00
										 |  |  |         po++; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-26 08:15:37 +02:00
										 |  |  | void parse_loglevel(int argc, char **argv, const OptionDef *options) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     int idx = locate_option(argc, argv, options, "loglevel"); | 
					
						
							| 
									
										
										
										
											2022-06-20 13:29:59 +03:00
										 |  |  |     char *env; | 
					
						
							| 
									
										
										
										
											2015-05-09 13:07:21 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     check_options(options); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-07 13:29:03 +01:00
										 |  |  |     if (!idx) | 
					
						
							|  |  |  |         idx = locate_option(argc, argv, options, "v"); | 
					
						
							| 
									
										
										
										
											2011-09-26 08:15:37 +02:00
										 |  |  |     if (idx && argv[idx + 1]) | 
					
						
							| 
									
										
										
										
											2012-08-29 14:37:22 +02:00
										 |  |  |         opt_loglevel(NULL, "loglevel", argv[idx + 1]); | 
					
						
							| 
									
										
										
										
											2011-12-08 14:42:24 +01:00
										 |  |  |     idx = locate_option(argc, argv, options, "report"); | 
					
						
							| 
									
										
										
										
											2022-06-20 13:29:59 +03:00
										 |  |  |     env = getenv_utf8("FFREPORT"); | 
					
						
							|  |  |  |     if (env || idx) { | 
					
						
							| 
									
										
										
										
											2022-03-09 12:11:09 +01:00
										 |  |  |         FILE *report_file = NULL; | 
					
						
							|  |  |  |         init_report(env, &report_file); | 
					
						
							| 
									
										
										
										
											2011-12-08 14:42:24 +01:00
										 |  |  |         if (report_file) { | 
					
						
							|  |  |  |             int i; | 
					
						
							|  |  |  |             fprintf(report_file, "Command line:\n"); | 
					
						
							|  |  |  |             for (i = 0; i < argc; i++) { | 
					
						
							| 
									
										
										
										
											2022-03-09 12:11:09 +01:00
										 |  |  |                 dump_argument(report_file, argv[i]); | 
					
						
							| 
									
										
										
										
											2011-12-08 14:42:24 +01:00
										 |  |  |                 fputc(i < argc - 1 ? ' ' : '\n', report_file); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             fflush(report_file); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-06-20 13:29:59 +03:00
										 |  |  |     freeenv_utf8(env); | 
					
						
							| 
									
										
										
										
											2013-12-28 05:18:39 +01:00
										 |  |  |     idx = locate_option(argc, argv, options, "hide_banner"); | 
					
						
							|  |  |  |     if (idx) | 
					
						
							|  |  |  |         hide_banner = 1; | 
					
						
							| 
									
										
										
										
											2011-09-26 08:15:37 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-08-28 00:12:18 +02:00
										 |  |  | static const AVOption *opt_find(void *obj, const char *name, const char *unit, | 
					
						
							|  |  |  |                             int opt_flags, int search_flags) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2013-08-30 10:39:27 +00:00
										 |  |  |     const AVOption *o = av_opt_find(obj, name, unit, opt_flags, search_flags); | 
					
						
							| 
									
										
										
										
											2013-08-28 00:12:18 +02:00
										 |  |  |     if(o && !o->flags) | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     return o; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-08 14:56:29 +02:00
										 |  |  | #define FLAGS (o->type == AV_OPT_TYPE_FLAGS && (arg[0]=='-' || arg[0]=='+')) ? AV_DICT_APPEND : 0
 | 
					
						
							| 
									
										
										
										
											2012-08-29 14:37:22 +02:00
										 |  |  | int opt_default(void *optctx, const char *opt, const char *arg) | 
					
						
							| 
									
										
										
										
											2011-05-25 16:42:41 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2012-05-30 14:40:28 +02:00
										 |  |  |     const AVOption *o; | 
					
						
							| 
									
										
										
										
											2012-10-18 01:56:48 +02:00
										 |  |  |     int consumed = 0; | 
					
						
							| 
									
										
										
										
											2011-07-28 16:47:38 +02:00
										 |  |  |     char opt_stripped[128]; | 
					
						
							|  |  |  |     const char *p; | 
					
						
							| 
									
										
										
										
											2012-10-29 18:00:14 +01:00
										 |  |  |     const AVClass *cc = avcodec_get_class(), *fc = avformat_get_class(); | 
					
						
							| 
									
										
										
										
											2015-09-19 10:20:26 -04:00
										 |  |  | #if CONFIG_SWSCALE
 | 
					
						
							|  |  |  |     const AVClass *sc = sws_get_class(); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | #if CONFIG_SWRESAMPLE
 | 
					
						
							|  |  |  |     const AVClass *swr_class = swr_get_class(); | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2011-07-28 16:47:38 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-12-20 02:15:40 +01:00
										 |  |  |     if (!strcmp(opt, "debug") || !strcmp(opt, "fdebug")) | 
					
						
							|  |  |  |         av_log_set_level(AV_LOG_DEBUG); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-28 16:47:38 +02:00
										 |  |  |     if (!(p = strchr(opt, ':'))) | 
					
						
							|  |  |  |         p = opt + strlen(opt); | 
					
						
							|  |  |  |     av_strlcpy(opt_stripped, opt, FFMIN(sizeof(opt_stripped), p - opt + 1)); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-08-28 00:12:18 +02:00
										 |  |  |     if ((o = opt_find(&cc, opt_stripped, NULL, 0, | 
					
						
							| 
									
										
										
										
											2011-12-31 18:01:54 +05:30
										 |  |  |                          AV_OPT_SEARCH_CHILDREN | AV_OPT_SEARCH_FAKE_OBJ)) || | 
					
						
							|  |  |  |         ((opt[0] == 'v' || opt[0] == 'a' || opt[0] == 's') && | 
					
						
							| 
									
										
										
										
											2013-08-28 00:12:18 +02:00
										 |  |  |          (o = opt_find(&cc, opt + 1, NULL, 0, AV_OPT_SEARCH_FAKE_OBJ)))) { | 
					
						
							| 
									
										
										
										
											2012-05-30 14:40:28 +02:00
										 |  |  |         av_dict_set(&codec_opts, opt, arg, FLAGS); | 
					
						
							| 
									
										
										
										
											2012-10-18 01:56:48 +02:00
										 |  |  |         consumed = 1; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2013-08-28 00:12:18 +02:00
										 |  |  |     if ((o = opt_find(&fc, opt, NULL, 0, | 
					
						
							| 
									
										
										
										
											2013-03-10 11:04:24 +01:00
										 |  |  |                          AV_OPT_SEARCH_CHILDREN | AV_OPT_SEARCH_FAKE_OBJ))) { | 
					
						
							| 
									
										
										
										
											2012-05-30 14:40:28 +02:00
										 |  |  |         av_dict_set(&format_opts, opt, arg, FLAGS); | 
					
						
							| 
									
										
										
										
											2013-03-10 11:04:24 +01:00
										 |  |  |         if (consumed) | 
					
						
							| 
									
										
										
										
											2013-03-10 11:05:32 +01:00
										 |  |  |             av_log(NULL, AV_LOG_VERBOSE, "Routing option %s to both codec and muxer layer\n", opt); | 
					
						
							| 
									
										
										
										
											2012-10-18 01:56:48 +02:00
										 |  |  |         consumed = 1; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2011-09-18 18:57:35 +02:00
										 |  |  | #if CONFIG_SWSCALE
 | 
					
						
							| 
									
										
										
										
											2015-08-08 12:43:10 +02:00
										 |  |  |     if (!consumed && (o = opt_find(&sc, opt, NULL, 0, | 
					
						
							|  |  |  |                          AV_OPT_SEARCH_CHILDREN | AV_OPT_SEARCH_FAKE_OBJ))) { | 
					
						
							| 
									
										
										
										
											2015-09-19 21:23:11 +02:00
										 |  |  |         if (!strcmp(opt, "srcw") || !strcmp(opt, "srch") || | 
					
						
							|  |  |  |             !strcmp(opt, "dstw") || !strcmp(opt, "dsth") || | 
					
						
							|  |  |  |             !strcmp(opt, "src_format") || !strcmp(opt, "dst_format")) { | 
					
						
							|  |  |  |             av_log(NULL, AV_LOG_ERROR, "Directly using swscale dimensions/format options is not supported, please use the -s or -pix_fmt options\n"); | 
					
						
							|  |  |  |             return AVERROR(EINVAL); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2015-08-08 12:43:10 +02:00
										 |  |  |         av_dict_set(&sws_dict, opt, arg, FLAGS); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-18 01:56:48 +02:00
										 |  |  |         consumed = 1; | 
					
						
							| 
									
										
										
										
											2011-05-25 16:42:41 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2014-06-29 17:01:39 +02:00
										 |  |  | #else
 | 
					
						
							|  |  |  |     if (!consumed && !strcmp(opt, "sws_flags")) { | 
					
						
							|  |  |  |         av_log(NULL, AV_LOG_WARNING, "Ignoring %s %s, due to disabled swscale\n", opt, arg); | 
					
						
							|  |  |  |         consumed = 1; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2011-09-18 18:57:35 +02:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2012-05-29 14:43:33 +00:00
										 |  |  | #if CONFIG_SWRESAMPLE
 | 
					
						
							| 
									
										
										
										
											2013-08-28 00:12:18 +02:00
										 |  |  |     if (!consumed && (o=opt_find(&swr_class, opt, NULL, 0, | 
					
						
							| 
									
										
										
										
											2013-02-24 19:07:42 +01:00
										 |  |  |                                     AV_OPT_SEARCH_CHILDREN | AV_OPT_SEARCH_FAKE_OBJ))) { | 
					
						
							|  |  |  |         av_dict_set(&swr_opts, opt, arg, FLAGS); | 
					
						
							| 
									
										
										
										
											2012-10-18 01:56:48 +02:00
										 |  |  |         consumed = 1; | 
					
						
							| 
									
										
										
										
											2012-04-11 13:46:02 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2012-05-29 14:43:33 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2011-05-25 16:42:41 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-18 01:56:48 +02:00
										 |  |  |     if (consumed) | 
					
						
							| 
									
										
										
										
											2011-05-25 16:42:41 +02:00
										 |  |  |         return 0; | 
					
						
							|  |  |  |     return AVERROR_OPTION_NOT_FOUND; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2011-04-19 12:57:46 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-06-10 20:46:30 +02:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * Check whether given option is a group separator. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * @return index of the group definition that matched or -1 if none | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2012-12-19 21:53:22 +01:00
										 |  |  | static int match_group_separator(const OptionGroupDef *groups, int nb_groups, | 
					
						
							|  |  |  |                                  const char *opt) | 
					
						
							| 
									
										
										
										
											2012-06-10 20:46:30 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2012-12-19 21:53:22 +01:00
										 |  |  |     int i; | 
					
						
							| 
									
										
										
										
											2012-06-10 20:46:30 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-12-19 21:53:22 +01:00
										 |  |  |     for (i = 0; i < nb_groups; i++) { | 
					
						
							|  |  |  |         const OptionGroupDef *p = &groups[i]; | 
					
						
							| 
									
										
										
										
											2012-06-10 20:46:30 +02:00
										 |  |  |         if (p->sep && !strcmp(p->sep, opt)) | 
					
						
							| 
									
										
										
										
											2012-12-19 21:53:22 +01:00
										 |  |  |             return i; | 
					
						
							| 
									
										
										
										
											2012-06-10 20:46:30 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return -1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Finish parsing an option group. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * @param group_idx which group definition should this group belong to | 
					
						
							|  |  |  |  * @param arg argument of the group delimiting option | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2023-07-14 12:28:18 +02:00
										 |  |  | static int finish_group(OptionParseContext *octx, int group_idx, | 
					
						
							|  |  |  |                         const char *arg) | 
					
						
							| 
									
										
										
										
											2012-06-10 20:46:30 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     OptionGroupList *l = &octx->groups[group_idx]; | 
					
						
							|  |  |  |     OptionGroup *g; | 
					
						
							| 
									
										
										
										
											2023-07-14 12:28:18 +02:00
										 |  |  |     int ret; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     ret = GROW_ARRAY(l->groups, l->nb_groups); | 
					
						
							|  |  |  |     if (ret < 0) | 
					
						
							|  |  |  |         return ret; | 
					
						
							| 
									
										
										
										
											2012-06-10 20:46:30 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     g = &l->groups[l->nb_groups - 1]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     *g             = octx->cur_group; | 
					
						
							|  |  |  |     g->arg         = arg; | 
					
						
							|  |  |  |     g->group_def   = l->group_def; | 
					
						
							| 
									
										
										
										
											2015-08-08 12:43:10 +02:00
										 |  |  |     g->sws_dict    = sws_dict; | 
					
						
							| 
									
										
										
										
											2012-12-20 02:38:02 +01:00
										 |  |  |     g->swr_opts    = swr_opts; | 
					
						
							| 
									
										
										
										
											2012-06-10 20:46:30 +02:00
										 |  |  |     g->codec_opts  = codec_opts; | 
					
						
							|  |  |  |     g->format_opts = format_opts; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     codec_opts  = NULL; | 
					
						
							|  |  |  |     format_opts = NULL; | 
					
						
							| 
									
										
										
										
											2015-08-08 12:43:10 +02:00
										 |  |  |     sws_dict    = NULL; | 
					
						
							| 
									
										
										
										
											2012-12-20 02:38:02 +01:00
										 |  |  |     swr_opts    = NULL; | 
					
						
							| 
									
										
										
										
											2012-06-10 20:46:30 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     memset(&octx->cur_group, 0, sizeof(octx->cur_group)); | 
					
						
							| 
									
										
										
										
											2023-07-14 12:28:18 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     return ret; | 
					
						
							| 
									
										
										
										
											2012-06-10 20:46:30 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Add an option instance to currently parsed group. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2023-07-14 12:28:18 +02:00
										 |  |  | static int add_opt(OptionParseContext *octx, const OptionDef *opt, | 
					
						
							|  |  |  |                    const char *key, const char *val) | 
					
						
							| 
									
										
										
										
											2012-06-10 20:46:30 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2023-12-17 11:47:33 +01:00
										 |  |  |     int global = !(opt->flags & OPT_PERFILE); | 
					
						
							| 
									
										
										
										
											2012-06-10 20:46:30 +02:00
										 |  |  |     OptionGroup *g = global ? &octx->global_opts : &octx->cur_group; | 
					
						
							| 
									
										
										
										
											2023-07-14 12:28:18 +02:00
										 |  |  |     int ret; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     ret = GROW_ARRAY(g->opts, g->nb_opts); | 
					
						
							|  |  |  |     if (ret < 0) | 
					
						
							|  |  |  |         return ret; | 
					
						
							| 
									
										
										
										
											2012-06-10 20:46:30 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     g->opts[g->nb_opts - 1].opt = opt; | 
					
						
							|  |  |  |     g->opts[g->nb_opts - 1].key = key; | 
					
						
							|  |  |  |     g->opts[g->nb_opts - 1].val = val; | 
					
						
							| 
									
										
										
										
											2023-07-14 12:28:18 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     return 0; | 
					
						
							| 
									
										
										
										
											2012-06-10 20:46:30 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-13 15:11:07 +02:00
										 |  |  | static int init_parse_context(OptionParseContext *octx, | 
					
						
							|  |  |  |                               const OptionGroupDef *groups, int nb_groups) | 
					
						
							| 
									
										
										
										
											2012-06-10 20:46:30 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     static const OptionGroupDef global_group = { "global" }; | 
					
						
							|  |  |  |     int i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     memset(octx, 0, sizeof(*octx)); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-04 07:37:21 +01:00
										 |  |  |     octx->groups    = av_calloc(nb_groups, sizeof(*octx->groups)); | 
					
						
							| 
									
										
										
										
											2012-06-10 20:46:30 +02:00
										 |  |  |     if (!octx->groups) | 
					
						
							| 
									
										
										
										
											2023-07-13 15:11:07 +02:00
										 |  |  |         return AVERROR(ENOMEM); | 
					
						
							| 
									
										
										
										
											2023-11-04 07:37:21 +01:00
										 |  |  |     octx->nb_groups = nb_groups; | 
					
						
							| 
									
										
										
										
											2012-06-10 20:46:30 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     for (i = 0; i < octx->nb_groups; i++) | 
					
						
							|  |  |  |         octx->groups[i].group_def = &groups[i]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     octx->global_opts.group_def = &global_group; | 
					
						
							|  |  |  |     octx->global_opts.arg       = ""; | 
					
						
							| 
									
										
										
										
											2023-07-13 15:11:07 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     return 0; | 
					
						
							| 
									
										
										
										
											2012-06-10 20:46:30 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void uninit_parse_context(OptionParseContext *octx) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     int i, j; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (i = 0; i < octx->nb_groups; i++) { | 
					
						
							|  |  |  |         OptionGroupList *l = &octx->groups[i]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         for (j = 0; j < l->nb_groups; j++) { | 
					
						
							|  |  |  |             av_freep(&l->groups[j].opts); | 
					
						
							|  |  |  |             av_dict_free(&l->groups[j].codec_opts); | 
					
						
							|  |  |  |             av_dict_free(&l->groups[j].format_opts); | 
					
						
							| 
									
										
										
										
											2015-08-08 12:43:10 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |             av_dict_free(&l->groups[j].sws_dict); | 
					
						
							| 
									
										
										
										
											2013-02-24 19:07:42 +01:00
										 |  |  |             av_dict_free(&l->groups[j].swr_opts); | 
					
						
							| 
									
										
										
										
											2012-06-10 20:46:30 +02:00
										 |  |  |         } | 
					
						
							|  |  |  |         av_freep(&l->groups); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     av_freep(&octx->groups); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     av_freep(&octx->cur_group.opts); | 
					
						
							|  |  |  |     av_freep(&octx->global_opts.opts); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     uninit_opts(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int split_commandline(OptionParseContext *octx, int argc, char *argv[], | 
					
						
							|  |  |  |                       const OptionDef *options, | 
					
						
							| 
									
										
										
										
											2012-12-19 21:53:22 +01:00
										 |  |  |                       const OptionGroupDef *groups, int nb_groups) | 
					
						
							| 
									
										
										
										
											2012-06-10 20:46:30 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2023-07-13 15:11:07 +02:00
										 |  |  |     int ret; | 
					
						
							| 
									
										
										
										
											2012-06-10 20:46:30 +02:00
										 |  |  |     int optindex = 1; | 
					
						
							| 
									
										
										
										
											2013-01-17 17:03:07 +01:00
										 |  |  |     int dashdash = -2; | 
					
						
							| 
									
										
										
										
											2012-06-10 20:46:30 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     /* perform system-dependent conversions for arguments list */ | 
					
						
							|  |  |  |     prepare_app_arguments(&argc, &argv); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-13 15:11:07 +02:00
										 |  |  |     ret = init_parse_context(octx, groups, nb_groups); | 
					
						
							|  |  |  |     if (ret < 0) | 
					
						
							|  |  |  |         return ret; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-06-10 20:46:30 +02:00
										 |  |  |     av_log(NULL, AV_LOG_DEBUG, "Splitting the commandline.\n"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     while (optindex < argc) { | 
					
						
							|  |  |  |         const char *opt = argv[optindex++], *arg; | 
					
						
							|  |  |  |         const OptionDef *po; | 
					
						
							|  |  |  |         int ret; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         av_log(NULL, AV_LOG_DEBUG, "Reading option '%s' ...", opt); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-17 17:03:07 +01:00
										 |  |  |         if (opt[0] == '-' && opt[1] == '-' && !opt[2]) { | 
					
						
							|  |  |  |             dashdash = optindex; | 
					
						
							|  |  |  |             continue; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2012-06-10 20:46:30 +02:00
										 |  |  |         /* unnamed group separators, e.g. output filename */ | 
					
						
							| 
									
										
										
										
											2013-01-17 17:03:07 +01:00
										 |  |  |         if (opt[0] != '-' || !opt[1] || dashdash+1 == optindex) { | 
					
						
							| 
									
										
										
										
											2023-07-14 12:28:18 +02:00
										 |  |  |             ret = finish_group(octx, 0, opt); | 
					
						
							|  |  |  |             if (ret < 0) | 
					
						
							|  |  |  |                 return ret; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-06-10 20:46:30 +02:00
										 |  |  |             av_log(NULL, AV_LOG_DEBUG, " matched as %s.\n", groups[0].name); | 
					
						
							|  |  |  |             continue; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         opt++; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define GET_ARG(arg)                                                           \
 | 
					
						
							|  |  |  | do {                                                                           \ | 
					
						
							|  |  |  |     arg = argv[optindex++];                                                    \ | 
					
						
							|  |  |  |     if (!arg) {                                                                \ | 
					
						
							|  |  |  |         av_log(NULL, AV_LOG_ERROR, "Missing argument for option '%s'.\n", opt);\ | 
					
						
							|  |  |  |         return AVERROR(EINVAL);                                                \ | 
					
						
							|  |  |  |     }                                                                          \ | 
					
						
							|  |  |  | } while (0) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         /* named group separators, e.g. -i */ | 
					
						
							| 
									
										
										
										
											2012-12-19 21:53:22 +01:00
										 |  |  |         if ((ret = match_group_separator(groups, nb_groups, opt)) >= 0) { | 
					
						
							| 
									
										
										
										
											2012-06-10 20:46:30 +02:00
										 |  |  |             GET_ARG(arg); | 
					
						
							| 
									
										
										
										
											2023-07-14 12:28:18 +02:00
										 |  |  |             ret = finish_group(octx, ret, arg); | 
					
						
							|  |  |  |             if (ret < 0) | 
					
						
							|  |  |  |                 return ret; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-06-10 20:46:30 +02:00
										 |  |  |             av_log(NULL, AV_LOG_DEBUG, " matched as %s with argument '%s'.\n", | 
					
						
							|  |  |  |                    groups[ret].name, arg); | 
					
						
							|  |  |  |             continue; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         /* normal options */ | 
					
						
							|  |  |  |         po = find_option(options, opt); | 
					
						
							|  |  |  |         if (po->name) { | 
					
						
							|  |  |  |             if (po->flags & OPT_EXIT) { | 
					
						
							|  |  |  |                 /* optional argument, e.g. -h */ | 
					
						
							|  |  |  |                 arg = argv[optindex++]; | 
					
						
							| 
									
										
										
										
											2023-12-15 08:24:14 +01:00
										 |  |  |             } else if (opt_has_arg(po)) { | 
					
						
							| 
									
										
										
										
											2012-06-10 20:46:30 +02:00
										 |  |  |                 GET_ARG(arg); | 
					
						
							|  |  |  |             } else { | 
					
						
							|  |  |  |                 arg = "1"; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-14 12:28:18 +02:00
										 |  |  |             ret = add_opt(octx, po, opt, arg); | 
					
						
							|  |  |  |             if (ret < 0) | 
					
						
							|  |  |  |                 return ret; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-06-10 20:46:30 +02:00
										 |  |  |             av_log(NULL, AV_LOG_DEBUG, " matched as option '%s' (%s) with " | 
					
						
							|  |  |  |                    "argument '%s'.\n", po->name, po->help, arg); | 
					
						
							|  |  |  |             continue; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         /* AVOptions */ | 
					
						
							|  |  |  |         if (argv[optindex]) { | 
					
						
							|  |  |  |             ret = opt_default(NULL, opt, argv[optindex]); | 
					
						
							|  |  |  |             if (ret >= 0) { | 
					
						
							|  |  |  |                 av_log(NULL, AV_LOG_DEBUG, " matched as AVOption '%s' with " | 
					
						
							|  |  |  |                        "argument '%s'.\n", opt, argv[optindex]); | 
					
						
							|  |  |  |                 optindex++; | 
					
						
							|  |  |  |                 continue; | 
					
						
							|  |  |  |             } else if (ret != AVERROR_OPTION_NOT_FOUND) { | 
					
						
							|  |  |  |                 av_log(NULL, AV_LOG_ERROR, "Error parsing option '%s' " | 
					
						
							|  |  |  |                        "with argument '%s'.\n", opt, argv[optindex]); | 
					
						
							|  |  |  |                 return ret; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         /* boolean -nofoo options */ | 
					
						
							|  |  |  |         if (opt[0] == 'n' && opt[1] == 'o' && | 
					
						
							|  |  |  |             (po = find_option(options, opt + 2)) && | 
					
						
							| 
									
										
										
										
											2023-12-15 08:50:26 +01:00
										 |  |  |             po->name && po->type == OPT_TYPE_BOOL) { | 
					
						
							| 
									
										
										
										
											2023-07-14 12:28:18 +02:00
										 |  |  |             ret = add_opt(octx, po, opt, "0"); | 
					
						
							|  |  |  |             if (ret < 0) | 
					
						
							|  |  |  |                 return ret; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-06-10 20:46:30 +02:00
										 |  |  |             av_log(NULL, AV_LOG_DEBUG, " matched as option '%s' (%s) with " | 
					
						
							|  |  |  |                    "argument 0.\n", po->name, po->help); | 
					
						
							|  |  |  |             continue; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         av_log(NULL, AV_LOG_ERROR, "Unrecognized option '%s'.\n", opt); | 
					
						
							|  |  |  |         return AVERROR_OPTION_NOT_FOUND; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-03 13:54:45 +02:00
										 |  |  |     if (octx->cur_group.nb_opts || codec_opts || format_opts) | 
					
						
							| 
									
										
										
										
											2019-09-27 12:19:24 -08:00
										 |  |  |         av_log(NULL, AV_LOG_WARNING, "Trailing option(s) found in the " | 
					
						
							|  |  |  |                "command: may be ignored.\n"); | 
					
						
							| 
									
										
										
										
											2012-06-10 20:46:30 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     av_log(NULL, AV_LOG_DEBUG, "Finished splitting the commandline.\n"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-06-07 18:34:02 +00:00
										 |  |  | void print_error(const char *filename, int err) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2022-10-04 16:40:06 +02:00
										 |  |  |     av_log(NULL, AV_LOG_ERROR, "%s: %s\n", filename, av_err2str(err)); | 
					
						
							| 
									
										
										
										
											2003-06-07 18:34:02 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2007-08-20 08:09:51 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-18 21:35:49 +00:00
										 |  |  | int read_yesno(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     int c = getchar(); | 
					
						
							| 
									
										
										
										
											2013-03-03 11:17:50 +01:00
										 |  |  |     int yesno = (av_toupper(c) == 'Y'); | 
					
						
							| 
									
										
										
										
											2009-03-18 21:35:49 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     while (c != '\n' && c != EOF) | 
					
						
							|  |  |  |         c = getchar(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return yesno; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2010-04-01 22:34:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-11-04 23:07:04 +00:00
										 |  |  | FILE *get_preset_file(char *filename, size_t filename_size, | 
					
						
							| 
									
										
										
										
											2011-12-31 18:01:54 +05:30
										 |  |  |                       const char *preset_name, int is_path, | 
					
						
							|  |  |  |                       const char *codec_name) | 
					
						
							| 
									
										
										
										
											2010-11-04 23:07:04 +00:00
										 |  |  | { | 
					
						
							|  |  |  |     FILE *f = NULL; | 
					
						
							|  |  |  |     int i; | 
					
						
							| 
									
										
										
										
											2022-06-20 13:29:59 +03:00
										 |  |  | #if HAVE_GETMODULEHANDLE && defined(_WIN32)
 | 
					
						
							|  |  |  |     char *datadir = NULL; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |     char *env_home = getenv_utf8("HOME"); | 
					
						
							|  |  |  |     char *env_ffmpeg_datadir = getenv_utf8("FFMPEG_DATADIR"); | 
					
						
							| 
									
										
										
										
											2022-06-30 12:40:35 +02:00
										 |  |  |     const char *base[3] = { env_ffmpeg_datadir, | 
					
						
							|  |  |  |                             env_home,   /* index=1(HOME) is special: search in a .ffmpeg subfolder */ | 
					
						
							| 
									
										
										
										
											2012-01-04 01:12:34 +01:00
										 |  |  |                             FFMPEG_DATADIR, }; | 
					
						
							| 
									
										
										
										
											2010-11-04 23:07:04 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (is_path) { | 
					
						
							|  |  |  |         av_strlcpy(filename, preset_name, filename_size); | 
					
						
							| 
									
										
										
										
											2022-06-20 13:29:59 +03:00
										 |  |  |         f = fopen_utf8(filename, "r"); | 
					
						
							| 
									
										
										
										
											2010-11-04 23:07:04 +00:00
										 |  |  |     } else { | 
					
						
							| 
									
										
										
										
											2020-01-08 13:29:07 +02:00
										 |  |  | #if HAVE_GETMODULEHANDLE && defined(_WIN32)
 | 
					
						
							| 
									
										
										
										
											2022-06-20 13:29:59 +03:00
										 |  |  |         wchar_t *datadir_w = get_module_filename(NULL); | 
					
						
							| 
									
										
										
										
											2011-05-21 03:36:26 +02:00
										 |  |  |         base[2] = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-20 13:29:59 +03:00
										 |  |  |         if (wchartoutf8(datadir_w, &datadir)) | 
					
						
							|  |  |  |             datadir = NULL; | 
					
						
							|  |  |  |         av_free(datadir_w); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (datadir) | 
					
						
							| 
									
										
										
										
											2011-05-21 03:36:26 +02:00
										 |  |  |         { | 
					
						
							| 
									
										
										
										
											2022-06-20 13:29:59 +03:00
										 |  |  |             char *ls; | 
					
						
							|  |  |  |             for (ls = datadir; *ls; ls++) | 
					
						
							| 
									
										
										
										
											2011-05-21 03:36:26 +02:00
										 |  |  |                 if (*ls == '\\') *ls = '/'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (ls = strrchr(datadir, '/')) | 
					
						
							|  |  |  |             { | 
					
						
							| 
									
										
										
										
											2022-06-20 13:29:59 +03:00
										 |  |  |                 ptrdiff_t datadir_len = ls - datadir; | 
					
						
							|  |  |  |                 size_t desired_size = datadir_len + strlen("/ffpresets") + 1; | 
					
						
							|  |  |  |                 char *new_datadir = av_realloc_array( | 
					
						
							|  |  |  |                     datadir, desired_size, sizeof *datadir); | 
					
						
							|  |  |  |                 if (new_datadir) { | 
					
						
							|  |  |  |                     datadir = new_datadir; | 
					
						
							|  |  |  |                     datadir[datadir_len] = 0; | 
					
						
							|  |  |  |                     strncat(datadir, "/ffpresets",  desired_size - 1 - datadir_len); | 
					
						
							|  |  |  |                     base[2] = datadir; | 
					
						
							|  |  |  |                 } | 
					
						
							| 
									
										
										
										
											2011-05-21 03:36:26 +02:00
										 |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2010-11-04 23:07:04 +00:00
										 |  |  |         for (i = 0; i < 3 && !f; i++) { | 
					
						
							|  |  |  |             if (!base[i]) | 
					
						
							|  |  |  |                 continue; | 
					
						
							| 
									
										
										
										
											2011-12-31 18:01:54 +05:30
										 |  |  |             snprintf(filename, filename_size, "%s%s/%s.ffpreset", base[i], | 
					
						
							| 
									
										
										
										
											2012-01-04 01:12:34 +01:00
										 |  |  |                      i != 1 ? "" : "/.ffmpeg", preset_name); | 
					
						
							| 
									
										
										
										
											2022-06-20 13:29:59 +03:00
										 |  |  |             f = fopen_utf8(filename, "r"); | 
					
						
							| 
									
										
										
										
											2010-11-04 23:07:04 +00:00
										 |  |  |             if (!f && codec_name) { | 
					
						
							|  |  |  |                 snprintf(filename, filename_size, | 
					
						
							| 
									
										
										
										
											2011-12-31 18:01:54 +05:30
										 |  |  |                          "%s%s/%s-%s.ffpreset", | 
					
						
							| 
									
										
										
										
											2012-03-18 23:12:35 +01:00
										 |  |  |                          base[i], i != 1 ? "" : "/.ffmpeg", codec_name, | 
					
						
							| 
									
										
										
										
											2011-12-31 18:01:54 +05:30
										 |  |  |                          preset_name); | 
					
						
							| 
									
										
										
										
											2022-06-20 13:29:59 +03:00
										 |  |  |                 f = fopen_utf8(filename, "r"); | 
					
						
							| 
									
										
										
										
											2010-11-04 23:07:04 +00:00
										 |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-20 13:29:59 +03:00
										 |  |  | #if HAVE_GETMODULEHANDLE && defined(_WIN32)
 | 
					
						
							|  |  |  |     av_free(datadir); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |     freeenv_utf8(env_ffmpeg_datadir); | 
					
						
							|  |  |  |     freeenv_utf8(env_home); | 
					
						
							| 
									
										
										
										
											2010-11-04 23:07:04 +00:00
										 |  |  |     return f; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-28 16:47:38 +02:00
										 |  |  | int check_stream_specifier(AVFormatContext *s, AVStream *st, const char *spec) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2012-07-18 11:41:13 +02:00
										 |  |  |     int ret = avformat_match_stream_specifier(s, st, spec); | 
					
						
							|  |  |  |     if (ret < 0) | 
					
						
							|  |  |  |         av_log(s, AV_LOG_ERROR, "Invalid stream specifier: %s.\n", spec); | 
					
						
							|  |  |  |     return ret; | 
					
						
							| 
									
										
										
										
											2011-07-28 16:47:38 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-14 17:19:28 +02:00
										 |  |  | int filter_codec_opts(const AVDictionary *opts, enum AVCodecID codec_id, | 
					
						
							|  |  |  |                       AVFormatContext *s, AVStream *st, const AVCodec *codec, | 
					
						
							|  |  |  |                       AVDictionary **dst) | 
					
						
							| 
									
										
										
										
											2011-07-10 15:46:15 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     AVDictionary    *ret = NULL; | 
					
						
							| 
									
										
										
										
											2021-10-18 15:27:01 -07:00
										 |  |  |     const AVDictionaryEntry *t = NULL; | 
					
						
							| 
									
										
										
										
											2011-12-31 18:01:54 +05:30
										 |  |  |     int            flags = s->oformat ? AV_OPT_FLAG_ENCODING_PARAM | 
					
						
							|  |  |  |                                       : AV_OPT_FLAG_DECODING_PARAM; | 
					
						
							| 
									
										
										
										
											2011-07-10 15:46:15 +02:00
										 |  |  |     char          prefix = 0; | 
					
						
							| 
									
										
										
										
											2011-08-23 07:43:54 +02:00
										 |  |  |     const AVClass    *cc = avcodec_get_class(); | 
					
						
							| 
									
										
										
										
											2011-07-10 15:46:15 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-06-30 01:28:02 +03:00
										 |  |  |     if (!codec) | 
					
						
							|  |  |  |         codec            = s->oformat ? avcodec_find_encoder(codec_id) | 
					
						
							|  |  |  |                                       : avcodec_find_decoder(codec_id); | 
					
						
							| 
									
										
										
										
											2011-07-10 15:46:15 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-01 16:48:45 +02:00
										 |  |  |     switch (st->codecpar->codec_type) { | 
					
						
							| 
									
										
										
										
											2011-12-31 18:01:54 +05:30
										 |  |  |     case AVMEDIA_TYPE_VIDEO: | 
					
						
							|  |  |  |         prefix  = 'v'; | 
					
						
							|  |  |  |         flags  |= AV_OPT_FLAG_VIDEO_PARAM; | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case AVMEDIA_TYPE_AUDIO: | 
					
						
							|  |  |  |         prefix  = 'a'; | 
					
						
							|  |  |  |         flags  |= AV_OPT_FLAG_AUDIO_PARAM; | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case AVMEDIA_TYPE_SUBTITLE: | 
					
						
							|  |  |  |         prefix  = 's'; | 
					
						
							|  |  |  |         flags  |= AV_OPT_FLAG_SUBTITLE_PARAM; | 
					
						
							|  |  |  |         break; | 
					
						
							| 
									
										
										
										
											2011-07-10 15:46:15 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-26 15:46:18 +01:00
										 |  |  |     while (t = av_dict_iterate(opts, t)) { | 
					
						
							| 
									
										
										
										
											2021-02-25 05:02:39 +01:00
										 |  |  |         const AVClass *priv_class; | 
					
						
							| 
									
										
										
										
											2011-07-28 16:47:38 +02:00
										 |  |  |         char *p = strchr(t->key, ':'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         /* check stream specification in opt name */ | 
					
						
							| 
									
										
										
										
											2023-07-14 17:19:28 +02:00
										 |  |  |         if (p) { | 
					
						
							|  |  |  |             int err = check_stream_specifier(s, st, p + 1); | 
					
						
							|  |  |  |             if (err < 0) { | 
					
						
							|  |  |  |                 av_dict_free(&ret); | 
					
						
							|  |  |  |                 return err; | 
					
						
							|  |  |  |             } else if (!err) | 
					
						
							|  |  |  |                 continue; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             *p = 0; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2011-07-28 16:47:38 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-08-23 07:43:54 +02:00
										 |  |  |         if (av_opt_find(&cc, t->key, NULL, flags, AV_OPT_SEARCH_FAKE_OBJ) || | 
					
						
							| 
									
										
										
										
											2014-03-28 16:03:33 +01:00
										 |  |  |             !codec || | 
					
						
							| 
									
										
										
										
											2021-02-25 05:02:39 +01:00
										 |  |  |             ((priv_class = codec->priv_class) && | 
					
						
							|  |  |  |              av_opt_find(&priv_class, t->key, NULL, flags, | 
					
						
							| 
									
										
										
										
											2011-12-31 18:01:54 +05:30
										 |  |  |                          AV_OPT_SEARCH_FAKE_OBJ))) | 
					
						
							| 
									
										
										
										
											2011-07-10 15:46:15 +02:00
										 |  |  |             av_dict_set(&ret, t->key, t->value, 0); | 
					
						
							| 
									
										
										
										
											2011-12-31 18:01:54 +05:30
										 |  |  |         else if (t->key[0] == prefix && | 
					
						
							|  |  |  |                  av_opt_find(&cc, t->key + 1, NULL, flags, | 
					
						
							|  |  |  |                              AV_OPT_SEARCH_FAKE_OBJ)) | 
					
						
							|  |  |  |             av_dict_set(&ret, t->key + 1, t->value, 0); | 
					
						
							| 
									
										
										
										
											2011-07-28 16:47:38 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         if (p) | 
					
						
							|  |  |  |             *p = ':'; | 
					
						
							| 
									
										
										
										
											2011-07-10 15:46:15 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-07-14 17:19:28 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     *dst = ret; | 
					
						
							|  |  |  |     return 0; | 
					
						
							| 
									
										
										
										
											2011-07-10 15:46:15 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-13 15:11:07 +02:00
										 |  |  | int setup_find_stream_info_opts(AVFormatContext *s, | 
					
						
							|  |  |  |                                 AVDictionary *codec_opts, | 
					
						
							|  |  |  |                                 AVDictionary ***dst) | 
					
						
							| 
									
										
										
										
											2011-05-25 16:59:51 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2023-07-14 17:19:28 +02:00
										 |  |  |     int ret; | 
					
						
							| 
									
										
										
										
											2011-05-25 16:59:51 +02:00
										 |  |  |     AVDictionary **opts; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-13 15:11:07 +02:00
										 |  |  |     *dst = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-05-25 16:59:51 +02:00
										 |  |  |     if (!s->nb_streams) | 
					
						
							| 
									
										
										
										
											2023-07-13 15:11:07 +02:00
										 |  |  |         return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-14 21:31:53 +02:00
										 |  |  |     opts = av_calloc(s->nb_streams, sizeof(*opts)); | 
					
						
							| 
									
										
										
										
											2022-08-27 15:41:16 +02:00
										 |  |  |     if (!opts) | 
					
						
							| 
									
										
										
										
											2023-07-13 15:11:07 +02:00
										 |  |  |         return AVERROR(ENOMEM); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-14 17:19:28 +02:00
										 |  |  |     for (int i = 0; i < s->nb_streams; i++) { | 
					
						
							|  |  |  |         ret = filter_codec_opts(codec_opts, s->streams[i]->codecpar->codec_id, | 
					
						
							|  |  |  |                                 s, s->streams[i], NULL, &opts[i]); | 
					
						
							|  |  |  |         if (ret < 0) | 
					
						
							|  |  |  |             goto fail; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-07-13 15:11:07 +02:00
										 |  |  |     *dst = opts; | 
					
						
							|  |  |  |     return 0; | 
					
						
							| 
									
										
										
										
											2023-07-14 17:19:28 +02:00
										 |  |  | fail: | 
					
						
							|  |  |  |     for (int i = 0; i < s->nb_streams; i++) | 
					
						
							|  |  |  |         av_dict_free(&opts[i]); | 
					
						
							|  |  |  |     av_freep(&opts); | 
					
						
							|  |  |  |     return ret; | 
					
						
							| 
									
										
										
										
											2011-05-25 16:59:51 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-14 12:28:18 +02:00
										 |  |  | int grow_array(void **array, int elem_size, int *size, int new_size) | 
					
						
							| 
									
										
										
										
											2011-08-29 07:11:57 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     if (new_size >= INT_MAX / elem_size) { | 
					
						
							|  |  |  |         av_log(NULL, AV_LOG_ERROR, "Array too big.\n"); | 
					
						
							| 
									
										
										
										
											2023-07-14 12:28:18 +02:00
										 |  |  |         return AVERROR(ERANGE); | 
					
						
							| 
									
										
										
										
											2011-08-29 07:11:57 +02:00
										 |  |  |     } | 
					
						
							|  |  |  |     if (*size < new_size) { | 
					
						
							| 
									
										
										
										
											2023-07-14 12:28:18 +02:00
										 |  |  |         uint8_t *tmp = av_realloc_array(*array, new_size, elem_size); | 
					
						
							| 
									
										
										
										
											2022-08-27 15:41:16 +02:00
										 |  |  |         if (!tmp) | 
					
						
							| 
									
										
										
										
											2023-07-14 12:28:18 +02:00
										 |  |  |             return AVERROR(ENOMEM); | 
					
						
							| 
									
										
										
										
											2011-08-29 07:11:57 +02:00
										 |  |  |         memset(tmp + *size*elem_size, 0, (new_size-*size) * elem_size); | 
					
						
							|  |  |  |         *size = new_size; | 
					
						
							| 
									
										
										
										
											2023-07-14 12:28:18 +02:00
										 |  |  |         *array = tmp; | 
					
						
							|  |  |  |         return 0; | 
					
						
							| 
									
										
										
										
											2011-08-29 07:11:57 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-07-14 12:28:18 +02:00
										 |  |  |     return 0; | 
					
						
							| 
									
										
										
										
											2011-08-29 07:11:57 +02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2014-08-07 00:45:26 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-03 13:12:39 +01:00
										 |  |  | void *allocate_array_elem(void *ptr, size_t elem_size, int *nb_elems) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2021-12-03 14:56:30 +01:00
										 |  |  |     void *new_elem; | 
					
						
							| 
									
										
										
										
											2021-12-03 13:12:39 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-03 14:56:30 +01:00
										 |  |  |     if (!(new_elem = av_mallocz(elem_size)) || | 
					
						
							| 
									
										
										
										
											2022-08-27 15:41:16 +02:00
										 |  |  |         av_dynarray_add_nofree(ptr, nb_elems, new_elem) < 0) | 
					
						
							| 
									
										
										
										
											2023-07-13 17:50:16 +02:00
										 |  |  |         return NULL; | 
					
						
							| 
									
										
										
										
											2021-12-03 14:34:47 +01:00
										 |  |  |     return new_elem; | 
					
						
							| 
									
										
										
										
											2021-12-03 13:12:39 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-13 18:39:11 +02:00
										 |  |  | double get_rotation(const int32_t *displaymatrix) | 
					
						
							| 
									
										
										
										
											2015-05-05 02:46:42 -03:00
										 |  |  | { | 
					
						
							|  |  |  |     double theta = 0; | 
					
						
							| 
									
										
											  
											
												avformat, ffmpeg: deprecate old rotation API
The old "API" that signaled rotation as a metadata value has been
replaced by DISPLAYMATRIX side data quite a while ago.
There is no reason to make muxers/demuxers/API users support both. In
addition, the metadata API is dangerous, as user tags could "leak" into
it, creating unintended features or bugs.
ffmpeg CLI has to be updated to use the new API. In particular, we must
not allow to leak the "rotate" tag into the muxer. Some muxers will
catch this properly (like mov), but others (like mkv) can add it as
generic tag. Note applications, which use libavformat and assume the
old rotate API, will interpret such "rotate" user tags as rotate
metadata (which it is not), and incorrectly rotate the video.
The ffmpeg/ffplay tools drop the use of the old API for muxing and
demuxing, as all muxers/demuxers support the new API. This will mean
that the tools will not mistakenly interpret per-track "rotate" user
tags as rotate metadata. It will _not_ be treated as regression.
Unfortunately, hacks have been added, that allow the user to override
rotation by setting metadata explicitly, e.g. via
  -metadata:s:v:0 rotate=0
See references to trac #4560. fate-filter-meta-4560-rotate0 tests this.
It's easier to adjust the hack for supporting it than arguing for its
removal, so ffmpeg CLI now explicitly catches this case, and essentially
replaces the "rotate" value with a display matrix side data. (It would
be easier for both user and implementation to create an explicit option
for rotation.)
When the code under FF_API_OLD_ROTATE_API is disabled, one FATE
reference file has to be updated (because "rotate" is not exported
anymore).
Tested-by: Michael Niedermayer <michael@niedermayer.cc>
Reviewed-by: Michael Niedermayer <michael@niedermayer.cc>
											
										 
											2017-03-21 08:02:58 +01:00
										 |  |  |     if (displaymatrix) | 
					
						
							| 
									
										
										
										
											2021-09-08 15:34:24 -03:00
										 |  |  |         theta = -round(av_display_rotation_get((int32_t*) displaymatrix)); | 
					
						
							| 
									
										
										
										
											2015-05-05 02:46:42 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  |     theta -= 360*floor(theta/360 + 0.9/360); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (fabs(theta - 90*round(theta/90)) > 2) | 
					
						
							| 
									
										
										
										
											2015-08-08 10:41:32 +02:00
										 |  |  |         av_log(NULL, AV_LOG_WARNING, "Odd rotation angle.\n" | 
					
						
							|  |  |  |                "If you want to help, upload a sample " | 
					
						
							| 
									
										
										
										
											2020-05-10 15:01:35 -04:00
										 |  |  |                "of this file to https://streams.videolan.org/upload/ " | 
					
						
							| 
									
										
										
										
											2015-08-08 10:41:32 +02:00
										 |  |  |                "and contact the ffmpeg-devel mailing list. (ffmpeg-devel@ffmpeg.org)"); | 
					
						
							| 
									
										
										
										
											2015-05-05 02:46:42 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  |     return theta; | 
					
						
							|  |  |  | } |