xref: /aosp_15_r20/external/libdav1d/tools/dav1d_cli_parse.c (revision c09093415860a1c2373dacd84c4fde00c507cdfd)
1*c0909341SAndroid Build Coastguard Worker /*
2*c0909341SAndroid Build Coastguard Worker  * Copyright © 2018, VideoLAN and dav1d authors
3*c0909341SAndroid Build Coastguard Worker  * Copyright © 2018, Two Orioles, LLC
4*c0909341SAndroid Build Coastguard Worker  * All rights reserved.
5*c0909341SAndroid Build Coastguard Worker  *
6*c0909341SAndroid Build Coastguard Worker  * Redistribution and use in source and binary forms, with or without
7*c0909341SAndroid Build Coastguard Worker  * modification, are permitted provided that the following conditions are met:
8*c0909341SAndroid Build Coastguard Worker  *
9*c0909341SAndroid Build Coastguard Worker  * 1. Redistributions of source code must retain the above copyright notice, this
10*c0909341SAndroid Build Coastguard Worker  *    list of conditions and the following disclaimer.
11*c0909341SAndroid Build Coastguard Worker  *
12*c0909341SAndroid Build Coastguard Worker  * 2. Redistributions in binary form must reproduce the above copyright notice,
13*c0909341SAndroid Build Coastguard Worker  *    this list of conditions and the following disclaimer in the documentation
14*c0909341SAndroid Build Coastguard Worker  *    and/or other materials provided with the distribution.
15*c0909341SAndroid Build Coastguard Worker  *
16*c0909341SAndroid Build Coastguard Worker  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17*c0909341SAndroid Build Coastguard Worker  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18*c0909341SAndroid Build Coastguard Worker  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19*c0909341SAndroid Build Coastguard Worker  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
20*c0909341SAndroid Build Coastguard Worker  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21*c0909341SAndroid Build Coastguard Worker  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22*c0909341SAndroid Build Coastguard Worker  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23*c0909341SAndroid Build Coastguard Worker  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24*c0909341SAndroid Build Coastguard Worker  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25*c0909341SAndroid Build Coastguard Worker  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26*c0909341SAndroid Build Coastguard Worker  */
27*c0909341SAndroid Build Coastguard Worker 
28*c0909341SAndroid Build Coastguard Worker #include "config.h"
29*c0909341SAndroid Build Coastguard Worker #include "cli_config.h"
30*c0909341SAndroid Build Coastguard Worker 
31*c0909341SAndroid Build Coastguard Worker #include <getopt.h>
32*c0909341SAndroid Build Coastguard Worker #include <limits.h>
33*c0909341SAndroid Build Coastguard Worker #include <math.h>
34*c0909341SAndroid Build Coastguard Worker #include <stdarg.h>
35*c0909341SAndroid Build Coastguard Worker #include <stdio.h>
36*c0909341SAndroid Build Coastguard Worker #include <stdlib.h>
37*c0909341SAndroid Build Coastguard Worker #include <string.h>
38*c0909341SAndroid Build Coastguard Worker #if HAVE_UNISTD_H
39*c0909341SAndroid Build Coastguard Worker # include <unistd.h>
40*c0909341SAndroid Build Coastguard Worker #endif
41*c0909341SAndroid Build Coastguard Worker 
42*c0909341SAndroid Build Coastguard Worker #include "dav1d_cli_parse.h"
43*c0909341SAndroid Build Coastguard Worker #include "src/cpu.h"
44*c0909341SAndroid Build Coastguard Worker 
45*c0909341SAndroid Build Coastguard Worker static const char short_opts[] = "i:o:vql:s:";
46*c0909341SAndroid Build Coastguard Worker 
47*c0909341SAndroid Build Coastguard Worker enum {
48*c0909341SAndroid Build Coastguard Worker     ARG_DEMUXER = 256,
49*c0909341SAndroid Build Coastguard Worker     ARG_MUXER,
50*c0909341SAndroid Build Coastguard Worker     ARG_FRAME_TIMES,
51*c0909341SAndroid Build Coastguard Worker     ARG_REALTIME,
52*c0909341SAndroid Build Coastguard Worker     ARG_REALTIME_CACHE,
53*c0909341SAndroid Build Coastguard Worker     ARG_THREADS,
54*c0909341SAndroid Build Coastguard Worker     ARG_FRAME_DELAY,
55*c0909341SAndroid Build Coastguard Worker     ARG_VERIFY,
56*c0909341SAndroid Build Coastguard Worker     ARG_FILM_GRAIN,
57*c0909341SAndroid Build Coastguard Worker     ARG_OPPOINT,
58*c0909341SAndroid Build Coastguard Worker     ARG_ALL_LAYERS,
59*c0909341SAndroid Build Coastguard Worker     ARG_SIZE_LIMIT,
60*c0909341SAndroid Build Coastguard Worker     ARG_STRICT_STD_COMPLIANCE,
61*c0909341SAndroid Build Coastguard Worker     ARG_CPU_MASK,
62*c0909341SAndroid Build Coastguard Worker     ARG_NEG_STRIDE,
63*c0909341SAndroid Build Coastguard Worker     ARG_OUTPUT_INVISIBLE,
64*c0909341SAndroid Build Coastguard Worker     ARG_INLOOP_FILTERS,
65*c0909341SAndroid Build Coastguard Worker     ARG_DECODE_FRAME_TYPE,
66*c0909341SAndroid Build Coastguard Worker };
67*c0909341SAndroid Build Coastguard Worker 
68*c0909341SAndroid Build Coastguard Worker static const struct option long_opts[] = {
69*c0909341SAndroid Build Coastguard Worker     { "input",           1, NULL, 'i' },
70*c0909341SAndroid Build Coastguard Worker     { "output",          1, NULL, 'o' },
71*c0909341SAndroid Build Coastguard Worker     { "quiet",           0, NULL, 'q' },
72*c0909341SAndroid Build Coastguard Worker     { "demuxer",         1, NULL, ARG_DEMUXER },
73*c0909341SAndroid Build Coastguard Worker     { "muxer",           1, NULL, ARG_MUXER },
74*c0909341SAndroid Build Coastguard Worker     { "version",         0, NULL, 'v' },
75*c0909341SAndroid Build Coastguard Worker     { "frametimes",      1, NULL, ARG_FRAME_TIMES },
76*c0909341SAndroid Build Coastguard Worker     { "limit",           1, NULL, 'l' },
77*c0909341SAndroid Build Coastguard Worker     { "skip",            1, NULL, 's' },
78*c0909341SAndroid Build Coastguard Worker     { "realtime",        2, NULL, ARG_REALTIME },
79*c0909341SAndroid Build Coastguard Worker     { "realtimecache",   1, NULL, ARG_REALTIME_CACHE },
80*c0909341SAndroid Build Coastguard Worker     { "threads",         1, NULL, ARG_THREADS },
81*c0909341SAndroid Build Coastguard Worker     { "framedelay",      1, NULL, ARG_FRAME_DELAY },
82*c0909341SAndroid Build Coastguard Worker     { "verify",          1, NULL, ARG_VERIFY },
83*c0909341SAndroid Build Coastguard Worker     { "filmgrain",       1, NULL, ARG_FILM_GRAIN },
84*c0909341SAndroid Build Coastguard Worker     { "oppoint",         1, NULL, ARG_OPPOINT },
85*c0909341SAndroid Build Coastguard Worker     { "alllayers",       1, NULL, ARG_ALL_LAYERS },
86*c0909341SAndroid Build Coastguard Worker     { "sizelimit",       1, NULL, ARG_SIZE_LIMIT },
87*c0909341SAndroid Build Coastguard Worker     { "strict",          1, NULL, ARG_STRICT_STD_COMPLIANCE },
88*c0909341SAndroid Build Coastguard Worker     { "cpumask",         1, NULL, ARG_CPU_MASK },
89*c0909341SAndroid Build Coastguard Worker     { "negstride",       0, NULL, ARG_NEG_STRIDE },
90*c0909341SAndroid Build Coastguard Worker     { "outputinvisible", 1, NULL, ARG_OUTPUT_INVISIBLE },
91*c0909341SAndroid Build Coastguard Worker     { "inloopfilters",   1, NULL, ARG_INLOOP_FILTERS },
92*c0909341SAndroid Build Coastguard Worker     { "decodeframetype", 1, NULL, ARG_DECODE_FRAME_TYPE },
93*c0909341SAndroid Build Coastguard Worker     { NULL,              0, NULL, 0 },
94*c0909341SAndroid Build Coastguard Worker };
95*c0909341SAndroid Build Coastguard Worker 
96*c0909341SAndroid Build Coastguard Worker #if HAVE_XXHASH_H
97*c0909341SAndroid Build Coastguard Worker #define AVAILABLE_MUXERS "'md5', 'xxh3', 'yuv', 'yuv4mpeg2' or 'null'"
98*c0909341SAndroid Build Coastguard Worker #else
99*c0909341SAndroid Build Coastguard Worker #define AVAILABLE_MUXERS "'md5', 'yuv', 'yuv4mpeg2' or 'null'"
100*c0909341SAndroid Build Coastguard Worker #endif
101*c0909341SAndroid Build Coastguard Worker 
102*c0909341SAndroid Build Coastguard Worker #if ARCH_AARCH64 || ARCH_ARM
103*c0909341SAndroid Build Coastguard Worker #define ALLOWED_CPU_MASKS ", 'neon', 'dotprod' or 'i8mm'"
104*c0909341SAndroid Build Coastguard Worker #elif ARCH_LOONGARCH
105*c0909341SAndroid Build Coastguard Worker #define ALLOWED_CPU_MASKS ", 'lsx' or 'lasx'"
106*c0909341SAndroid Build Coastguard Worker #elif ARCH_PPC64LE
107*c0909341SAndroid Build Coastguard Worker #define ALLOWED_CPU_MASKS ", 'vsx' or 'pwr9'"
108*c0909341SAndroid Build Coastguard Worker #elif ARCH_RISCV
109*c0909341SAndroid Build Coastguard Worker #define ALLOWED_CPU_MASKS " or 'rvv'"
110*c0909341SAndroid Build Coastguard Worker #elif ARCH_X86
111*c0909341SAndroid Build Coastguard Worker #define ALLOWED_CPU_MASKS \
112*c0909341SAndroid Build Coastguard Worker     ", 'sse2', 'ssse3', 'sse41', 'avx2' or 'avx512icl'"
113*c0909341SAndroid Build Coastguard Worker #else
114*c0909341SAndroid Build Coastguard Worker #define ALLOWED_CPU_MASKS "not yet implemented for this architecture"
115*c0909341SAndroid Build Coastguard Worker #endif
116*c0909341SAndroid Build Coastguard Worker 
usage(const char * const app,const char * const reason,...)117*c0909341SAndroid Build Coastguard Worker static void usage(const char *const app, const char *const reason, ...) {
118*c0909341SAndroid Build Coastguard Worker     if (reason) {
119*c0909341SAndroid Build Coastguard Worker         va_list args;
120*c0909341SAndroid Build Coastguard Worker 
121*c0909341SAndroid Build Coastguard Worker         va_start(args, reason);
122*c0909341SAndroid Build Coastguard Worker         vfprintf(stderr, reason, args);
123*c0909341SAndroid Build Coastguard Worker         va_end(args);
124*c0909341SAndroid Build Coastguard Worker         fprintf(stderr, "\n\n");
125*c0909341SAndroid Build Coastguard Worker     }
126*c0909341SAndroid Build Coastguard Worker     fprintf(stderr, "Usage: %s [options]\n\n", app);
127*c0909341SAndroid Build Coastguard Worker     fprintf(stderr, "Supported options:\n"
128*c0909341SAndroid Build Coastguard Worker             " --input/-i $file:     input file\n"
129*c0909341SAndroid Build Coastguard Worker             " --output/-o $file:    output file (%%n, %%w or %%h will be filled in for per-frame files)\n"
130*c0909341SAndroid Build Coastguard Worker             " --demuxer $name:      force demuxer type ('ivf', 'section5' or 'annexb'; default: detect from content)\n"
131*c0909341SAndroid Build Coastguard Worker             " --muxer $name:        force muxer type (" AVAILABLE_MUXERS "; default: detect from extension)\n"
132*c0909341SAndroid Build Coastguard Worker             "                       use 'frame' as prefix to write per-frame files; if filename contains %%n, will default to writing per-frame files\n"
133*c0909341SAndroid Build Coastguard Worker             " --quiet/-q:           disable status messages\n"
134*c0909341SAndroid Build Coastguard Worker             " --frametimes $file:   dump frame times to file\n"
135*c0909341SAndroid Build Coastguard Worker             " --limit/-l $num:      stop decoding after $num frames\n"
136*c0909341SAndroid Build Coastguard Worker             " --skip/-s $num:       skip decoding of the first $num frames\n"
137*c0909341SAndroid Build Coastguard Worker             " --realtime [$fract]:  limit framerate, optional argument to override input framerate\n"
138*c0909341SAndroid Build Coastguard Worker             " --realtimecache $num: set the size of the cache in realtime mode (default: 0)\n"
139*c0909341SAndroid Build Coastguard Worker             " --version/-v:         print version and exit\n"
140*c0909341SAndroid Build Coastguard Worker             " --threads $num:       number of threads (default: 0)\n"
141*c0909341SAndroid Build Coastguard Worker             " --framedelay $num:    maximum frame delay, capped at $threads (default: 0);\n"
142*c0909341SAndroid Build Coastguard Worker             "                       set to 1 for low-latency decoding\n"
143*c0909341SAndroid Build Coastguard Worker             " --filmgrain $num:     enable film grain application (default: 1, except if muxer is md5 or xxh3)\n"
144*c0909341SAndroid Build Coastguard Worker             " --oppoint $num:       select an operating point of a scalable AV1 bitstream (0 - 31)\n"
145*c0909341SAndroid Build Coastguard Worker             " --alllayers $num:     output all spatial layers of a scalable AV1 bitstream (default: 1)\n"
146*c0909341SAndroid Build Coastguard Worker             " --sizelimit $num:     stop decoding if the frame size exceeds the specified limit\n"
147*c0909341SAndroid Build Coastguard Worker             " --strict $num:        whether to abort decoding on standard compliance violations\n"
148*c0909341SAndroid Build Coastguard Worker             "                       that don't affect bitstream decoding (default: 1)\n"
149*c0909341SAndroid Build Coastguard Worker             " --verify $md5:        verify decoded md5. implies --muxer md5, no output\n"
150*c0909341SAndroid Build Coastguard Worker             " --cpumask $mask:      restrict permitted CPU instruction sets (0" ALLOWED_CPU_MASKS "; default: -1)\n"
151*c0909341SAndroid Build Coastguard Worker             " --negstride:          use negative picture strides\n"
152*c0909341SAndroid Build Coastguard Worker             "                       this is mostly meant as a developer option\n"
153*c0909341SAndroid Build Coastguard Worker             " --outputinvisible $num: whether to output invisible (alt-ref) frames (default: 0)\n"
154*c0909341SAndroid Build Coastguard Worker             " --inloopfilters $str: which in-loop filters to enable (none, (no)deblock, (no)cdef, (no)restoration or all; default: all)\n"
155*c0909341SAndroid Build Coastguard Worker             " --decodeframetype $str: which frame types to decode (reference, intra, key or all; default: all)\n"
156*c0909341SAndroid Build Coastguard Worker             );
157*c0909341SAndroid Build Coastguard Worker     exit(1);
158*c0909341SAndroid Build Coastguard Worker }
159*c0909341SAndroid Build Coastguard Worker 
error(const char * const app,const char * const optarg,const int option,const char * const shouldbe)160*c0909341SAndroid Build Coastguard Worker static void error(const char *const app, const char *const optarg,
161*c0909341SAndroid Build Coastguard Worker                   const int option, const char *const shouldbe)
162*c0909341SAndroid Build Coastguard Worker {
163*c0909341SAndroid Build Coastguard Worker     char optname[256];
164*c0909341SAndroid Build Coastguard Worker     int n;
165*c0909341SAndroid Build Coastguard Worker 
166*c0909341SAndroid Build Coastguard Worker     for (n = 0; long_opts[n].name; n++)
167*c0909341SAndroid Build Coastguard Worker         if (long_opts[n].val == option)
168*c0909341SAndroid Build Coastguard Worker             break;
169*c0909341SAndroid Build Coastguard Worker     assert(long_opts[n].name);
170*c0909341SAndroid Build Coastguard Worker     if (long_opts[n].val < 256) {
171*c0909341SAndroid Build Coastguard Worker         sprintf(optname, "-%c/--%s", long_opts[n].val, long_opts[n].name);
172*c0909341SAndroid Build Coastguard Worker     } else {
173*c0909341SAndroid Build Coastguard Worker         sprintf(optname, "--%s", long_opts[n].name);
174*c0909341SAndroid Build Coastguard Worker     }
175*c0909341SAndroid Build Coastguard Worker 
176*c0909341SAndroid Build Coastguard Worker     usage(app, "Invalid argument \"%s\" for option %s; should be %s",
177*c0909341SAndroid Build Coastguard Worker           optarg, optname, shouldbe);
178*c0909341SAndroid Build Coastguard Worker }
179*c0909341SAndroid Build Coastguard Worker 
parse_unsigned(const char * const optarg,const int option,const char * const app)180*c0909341SAndroid Build Coastguard Worker static unsigned parse_unsigned(const char *const optarg, const int option,
181*c0909341SAndroid Build Coastguard Worker                                const char *const app)
182*c0909341SAndroid Build Coastguard Worker {
183*c0909341SAndroid Build Coastguard Worker     char *end;
184*c0909341SAndroid Build Coastguard Worker     const unsigned res = (unsigned) strtoul(optarg, &end, 0);
185*c0909341SAndroid Build Coastguard Worker     if (*end || end == optarg) error(app, optarg, option, "an integer");
186*c0909341SAndroid Build Coastguard Worker     return res;
187*c0909341SAndroid Build Coastguard Worker }
188*c0909341SAndroid Build Coastguard Worker 
parse_optional_fraction(const char * const optarg,const int option,const char * const app,double * value)189*c0909341SAndroid Build Coastguard Worker static int parse_optional_fraction(const char *const optarg, const int option,
190*c0909341SAndroid Build Coastguard Worker                                    const char *const app, double *value)
191*c0909341SAndroid Build Coastguard Worker {
192*c0909341SAndroid Build Coastguard Worker     if (optarg == NULL) return 0;
193*c0909341SAndroid Build Coastguard Worker     char *end;
194*c0909341SAndroid Build Coastguard Worker     *value = strtod(optarg, &end);
195*c0909341SAndroid Build Coastguard Worker     if (*end == '/' && end != optarg) {
196*c0909341SAndroid Build Coastguard Worker         const char *optarg2 = end + 1;
197*c0909341SAndroid Build Coastguard Worker         *value /= strtod(optarg2, &end);
198*c0909341SAndroid Build Coastguard Worker         if (*end || end == optarg2) error(app, optarg, option, "a fraction");
199*c0909341SAndroid Build Coastguard Worker     } else if (*end || end == optarg) {
200*c0909341SAndroid Build Coastguard Worker         error(app, optarg, option, "a fraction");
201*c0909341SAndroid Build Coastguard Worker     }
202*c0909341SAndroid Build Coastguard Worker     return 1;
203*c0909341SAndroid Build Coastguard Worker }
204*c0909341SAndroid Build Coastguard Worker 
205*c0909341SAndroid Build Coastguard Worker typedef struct EnumParseTable {
206*c0909341SAndroid Build Coastguard Worker     const char *str;
207*c0909341SAndroid Build Coastguard Worker     const int val;
208*c0909341SAndroid Build Coastguard Worker } EnumParseTable;
209*c0909341SAndroid Build Coastguard Worker 
210*c0909341SAndroid Build Coastguard Worker #if ARCH_X86
211*c0909341SAndroid Build Coastguard Worker enum CpuMask {
212*c0909341SAndroid Build Coastguard Worker     X86_CPU_MASK_SSE2      = DAV1D_X86_CPU_FLAG_SSE2,
213*c0909341SAndroid Build Coastguard Worker     X86_CPU_MASK_SSSE3     = DAV1D_X86_CPU_FLAG_SSSE3     | X86_CPU_MASK_SSE2,
214*c0909341SAndroid Build Coastguard Worker     X86_CPU_MASK_SSE41     = DAV1D_X86_CPU_FLAG_SSE41     | X86_CPU_MASK_SSSE3,
215*c0909341SAndroid Build Coastguard Worker     X86_CPU_MASK_AVX2      = DAV1D_X86_CPU_FLAG_AVX2      | X86_CPU_MASK_SSE41,
216*c0909341SAndroid Build Coastguard Worker     X86_CPU_MASK_AVX512ICL = DAV1D_X86_CPU_FLAG_AVX512ICL | X86_CPU_MASK_AVX2,
217*c0909341SAndroid Build Coastguard Worker };
218*c0909341SAndroid Build Coastguard Worker #elif ARCH_AARCH64 || ARCH_ARM
219*c0909341SAndroid Build Coastguard Worker enum CpuMask {
220*c0909341SAndroid Build Coastguard Worker     ARM_CPU_MASK_NEON      = DAV1D_ARM_CPU_FLAG_NEON,
221*c0909341SAndroid Build Coastguard Worker     ARM_CPU_MASK_DOTPROD   = DAV1D_ARM_CPU_FLAG_DOTPROD | ARM_CPU_MASK_NEON,
222*c0909341SAndroid Build Coastguard Worker     ARM_CPU_MASK_I8MM      = DAV1D_ARM_CPU_FLAG_I8MM    | ARM_CPU_MASK_DOTPROD,
223*c0909341SAndroid Build Coastguard Worker #if ARCH_AARCH64
224*c0909341SAndroid Build Coastguard Worker     // SVE doesn't imply DOTPROD or I8MM.
225*c0909341SAndroid Build Coastguard Worker     ARM_CPU_MASK_SVE       = DAV1D_ARM_CPU_FLAG_SVE     | ARM_CPU_MASK_NEON,
226*c0909341SAndroid Build Coastguard Worker     // SVE2 implies DOTPROD, but not I8MM.
227*c0909341SAndroid Build Coastguard Worker     ARM_CPU_MASK_SVE2      = DAV1D_ARM_CPU_FLAG_SVE2    | ARM_CPU_MASK_SVE | ARM_CPU_MASK_DOTPROD,
228*c0909341SAndroid Build Coastguard Worker #endif
229*c0909341SAndroid Build Coastguard Worker };
230*c0909341SAndroid Build Coastguard Worker #endif
231*c0909341SAndroid Build Coastguard Worker 
232*c0909341SAndroid Build Coastguard Worker #if ARCH_PPC64LE
233*c0909341SAndroid Build Coastguard Worker enum CpuMask {
234*c0909341SAndroid Build Coastguard Worker     PPC_CPU_MASK_VSX       = DAV1D_PPC_CPU_FLAG_VSX,
235*c0909341SAndroid Build Coastguard Worker     PPC_CPU_MASK_PWR9      = DAV1D_PPC_CPU_FLAG_VSX | DAV1D_PPC_CPU_FLAG_PWR9,
236*c0909341SAndroid Build Coastguard Worker };
237*c0909341SAndroid Build Coastguard Worker #endif
238*c0909341SAndroid Build Coastguard Worker 
239*c0909341SAndroid Build Coastguard Worker 
240*c0909341SAndroid Build Coastguard Worker static const EnumParseTable cpu_mask_tbl[] = {
241*c0909341SAndroid Build Coastguard Worker #if ARCH_AARCH64 || ARCH_ARM
242*c0909341SAndroid Build Coastguard Worker     { "neon",    ARM_CPU_MASK_NEON },
243*c0909341SAndroid Build Coastguard Worker     { "dotprod", ARM_CPU_MASK_DOTPROD },
244*c0909341SAndroid Build Coastguard Worker     { "i8mm",    ARM_CPU_MASK_I8MM },
245*c0909341SAndroid Build Coastguard Worker #if ARCH_AARCH64
246*c0909341SAndroid Build Coastguard Worker     { "sve",     ARM_CPU_MASK_SVE },
247*c0909341SAndroid Build Coastguard Worker     { "sve2",    ARM_CPU_MASK_SVE2 },
248*c0909341SAndroid Build Coastguard Worker #endif /* ARCH_AARCH64 */
249*c0909341SAndroid Build Coastguard Worker #elif ARCH_LOONGARCH
250*c0909341SAndroid Build Coastguard Worker     { "lsx", DAV1D_LOONGARCH_CPU_FLAG_LSX },
251*c0909341SAndroid Build Coastguard Worker     { "lasx", DAV1D_LOONGARCH_CPU_FLAG_LASX },
252*c0909341SAndroid Build Coastguard Worker #elif ARCH_PPC64LE
253*c0909341SAndroid Build Coastguard Worker     { "vsx",  PPC_CPU_MASK_VSX },
254*c0909341SAndroid Build Coastguard Worker     { "pwr9", PPC_CPU_MASK_PWR9 },
255*c0909341SAndroid Build Coastguard Worker #elif ARCH_RISCV
256*c0909341SAndroid Build Coastguard Worker     { "rvv", DAV1D_RISCV_CPU_FLAG_V },
257*c0909341SAndroid Build Coastguard Worker #elif ARCH_X86
258*c0909341SAndroid Build Coastguard Worker     { "sse2",      X86_CPU_MASK_SSE2 },
259*c0909341SAndroid Build Coastguard Worker     { "ssse3",     X86_CPU_MASK_SSSE3 },
260*c0909341SAndroid Build Coastguard Worker     { "sse41",     X86_CPU_MASK_SSE41 },
261*c0909341SAndroid Build Coastguard Worker     { "avx2",      X86_CPU_MASK_AVX2 },
262*c0909341SAndroid Build Coastguard Worker     { "avx512icl", X86_CPU_MASK_AVX512ICL },
263*c0909341SAndroid Build Coastguard Worker #endif
264*c0909341SAndroid Build Coastguard Worker     { "none",      0 },
265*c0909341SAndroid Build Coastguard Worker };
266*c0909341SAndroid Build Coastguard Worker 
267*c0909341SAndroid Build Coastguard Worker static const EnumParseTable inloop_filters_tbl[] = {
268*c0909341SAndroid Build Coastguard Worker     { "none",          DAV1D_INLOOPFILTER_NONE },
269*c0909341SAndroid Build Coastguard Worker     { "deblock",       DAV1D_INLOOPFILTER_DEBLOCK },
270*c0909341SAndroid Build Coastguard Worker     { "nodeblock",     DAV1D_INLOOPFILTER_ALL - DAV1D_INLOOPFILTER_DEBLOCK },
271*c0909341SAndroid Build Coastguard Worker     { "cdef",          DAV1D_INLOOPFILTER_CDEF },
272*c0909341SAndroid Build Coastguard Worker     { "nocdef",        DAV1D_INLOOPFILTER_ALL - DAV1D_INLOOPFILTER_CDEF },
273*c0909341SAndroid Build Coastguard Worker     { "restoration",   DAV1D_INLOOPFILTER_RESTORATION },
274*c0909341SAndroid Build Coastguard Worker     { "norestoration", DAV1D_INLOOPFILTER_ALL - DAV1D_INLOOPFILTER_RESTORATION },
275*c0909341SAndroid Build Coastguard Worker     { "all",           DAV1D_INLOOPFILTER_ALL },
276*c0909341SAndroid Build Coastguard Worker };
277*c0909341SAndroid Build Coastguard Worker 
278*c0909341SAndroid Build Coastguard Worker static const EnumParseTable decode_frame_type_tbl[] = {
279*c0909341SAndroid Build Coastguard Worker     { "all",           DAV1D_DECODEFRAMETYPE_ALL },
280*c0909341SAndroid Build Coastguard Worker     { "reference",     DAV1D_DECODEFRAMETYPE_REFERENCE },
281*c0909341SAndroid Build Coastguard Worker     { "intra",         DAV1D_DECODEFRAMETYPE_INTRA },
282*c0909341SAndroid Build Coastguard Worker     { "key",           DAV1D_DECODEFRAMETYPE_KEY },
283*c0909341SAndroid Build Coastguard Worker };
284*c0909341SAndroid Build Coastguard Worker 
285*c0909341SAndroid Build Coastguard Worker #define ARRAY_SIZE(n) (sizeof(n)/sizeof(*(n)))
286*c0909341SAndroid Build Coastguard Worker 
parse_enum(char * optarg,const EnumParseTable * const tbl,const int tbl_sz,const int option,const char * app)287*c0909341SAndroid Build Coastguard Worker static unsigned parse_enum(char *optarg, const EnumParseTable *const tbl,
288*c0909341SAndroid Build Coastguard Worker                            const int tbl_sz, const int option, const char *app)
289*c0909341SAndroid Build Coastguard Worker {
290*c0909341SAndroid Build Coastguard Worker     char str[1024];
291*c0909341SAndroid Build Coastguard Worker 
292*c0909341SAndroid Build Coastguard Worker     strcpy(str, "any of ");
293*c0909341SAndroid Build Coastguard Worker     for (int n = 0; n < tbl_sz; n++) {
294*c0909341SAndroid Build Coastguard Worker         if (!strcmp(tbl[n].str, optarg))
295*c0909341SAndroid Build Coastguard Worker             return tbl[n].val;
296*c0909341SAndroid Build Coastguard Worker 
297*c0909341SAndroid Build Coastguard Worker         if (n) {
298*c0909341SAndroid Build Coastguard Worker             if (n < tbl_sz - 1)
299*c0909341SAndroid Build Coastguard Worker                 strcat(str, ", ");
300*c0909341SAndroid Build Coastguard Worker             else
301*c0909341SAndroid Build Coastguard Worker                 strcat(str, " or ");
302*c0909341SAndroid Build Coastguard Worker         }
303*c0909341SAndroid Build Coastguard Worker         strcat(str, tbl[n].str);
304*c0909341SAndroid Build Coastguard Worker     }
305*c0909341SAndroid Build Coastguard Worker 
306*c0909341SAndroid Build Coastguard Worker     char *end;
307*c0909341SAndroid Build Coastguard Worker     unsigned res;
308*c0909341SAndroid Build Coastguard Worker     if (!strncmp(optarg, "0x", 2)) {
309*c0909341SAndroid Build Coastguard Worker         res = (unsigned) strtoul(&optarg[2], &end, 16);
310*c0909341SAndroid Build Coastguard Worker     } else {
311*c0909341SAndroid Build Coastguard Worker         res = (unsigned) strtoul(optarg, &end, 0);
312*c0909341SAndroid Build Coastguard Worker     }
313*c0909341SAndroid Build Coastguard Worker 
314*c0909341SAndroid Build Coastguard Worker     if (*end || end == optarg) {
315*c0909341SAndroid Build Coastguard Worker         strcat(str, ", a hexadecimal (starting with 0x), or an integer");
316*c0909341SAndroid Build Coastguard Worker         error(app, optarg, option, str);
317*c0909341SAndroid Build Coastguard Worker     }
318*c0909341SAndroid Build Coastguard Worker 
319*c0909341SAndroid Build Coastguard Worker     return res;
320*c0909341SAndroid Build Coastguard Worker }
321*c0909341SAndroid Build Coastguard Worker 
parse(const int argc,char * const * const argv,CLISettings * const cli_settings,Dav1dSettings * const lib_settings)322*c0909341SAndroid Build Coastguard Worker void parse(const int argc, char *const *const argv,
323*c0909341SAndroid Build Coastguard Worker            CLISettings *const cli_settings, Dav1dSettings *const lib_settings)
324*c0909341SAndroid Build Coastguard Worker {
325*c0909341SAndroid Build Coastguard Worker     int o;
326*c0909341SAndroid Build Coastguard Worker 
327*c0909341SAndroid Build Coastguard Worker     memset(cli_settings, 0, sizeof(*cli_settings));
328*c0909341SAndroid Build Coastguard Worker     dav1d_default_settings(lib_settings);
329*c0909341SAndroid Build Coastguard Worker     lib_settings->strict_std_compliance = 1; // override library default
330*c0909341SAndroid Build Coastguard Worker     int grain_specified = 0;
331*c0909341SAndroid Build Coastguard Worker 
332*c0909341SAndroid Build Coastguard Worker     while ((o = getopt_long(argc, argv, short_opts, long_opts, NULL)) != -1) {
333*c0909341SAndroid Build Coastguard Worker         switch (o) {
334*c0909341SAndroid Build Coastguard Worker         case 'o':
335*c0909341SAndroid Build Coastguard Worker             cli_settings->outputfile = optarg;
336*c0909341SAndroid Build Coastguard Worker             break;
337*c0909341SAndroid Build Coastguard Worker         case 'i':
338*c0909341SAndroid Build Coastguard Worker             cli_settings->inputfile = optarg;
339*c0909341SAndroid Build Coastguard Worker             break;
340*c0909341SAndroid Build Coastguard Worker         case 'q':
341*c0909341SAndroid Build Coastguard Worker             cli_settings->quiet = 1;
342*c0909341SAndroid Build Coastguard Worker             break;
343*c0909341SAndroid Build Coastguard Worker         case 'l':
344*c0909341SAndroid Build Coastguard Worker             cli_settings->limit = parse_unsigned(optarg, 'l', argv[0]);
345*c0909341SAndroid Build Coastguard Worker             break;
346*c0909341SAndroid Build Coastguard Worker         case 's':
347*c0909341SAndroid Build Coastguard Worker             cli_settings->skip = parse_unsigned(optarg, 's', argv[0]);
348*c0909341SAndroid Build Coastguard Worker             break;
349*c0909341SAndroid Build Coastguard Worker         case ARG_DEMUXER:
350*c0909341SAndroid Build Coastguard Worker             cli_settings->demuxer = optarg;
351*c0909341SAndroid Build Coastguard Worker             break;
352*c0909341SAndroid Build Coastguard Worker         case ARG_MUXER:
353*c0909341SAndroid Build Coastguard Worker             cli_settings->muxer = optarg;
354*c0909341SAndroid Build Coastguard Worker             break;
355*c0909341SAndroid Build Coastguard Worker         case ARG_FRAME_TIMES:
356*c0909341SAndroid Build Coastguard Worker             cli_settings->frametimes = optarg;
357*c0909341SAndroid Build Coastguard Worker             break;
358*c0909341SAndroid Build Coastguard Worker         case ARG_REALTIME:
359*c0909341SAndroid Build Coastguard Worker             // workaround to parse an optional argument of the form `--a b`
360*c0909341SAndroid Build Coastguard Worker             // (getopt only allows `--a=b`)
361*c0909341SAndroid Build Coastguard Worker             if (optarg == NULL && optind < argc && argv[optind] != NULL &&
362*c0909341SAndroid Build Coastguard Worker                 argv[optind][0] != '-')
363*c0909341SAndroid Build Coastguard Worker             {
364*c0909341SAndroid Build Coastguard Worker                 optarg = argv[optind];
365*c0909341SAndroid Build Coastguard Worker                 optind++;
366*c0909341SAndroid Build Coastguard Worker             }
367*c0909341SAndroid Build Coastguard Worker             cli_settings->realtime = 1 + parse_optional_fraction(optarg,
368*c0909341SAndroid Build Coastguard Worker                 ARG_REALTIME, argv[0], &cli_settings->realtime_fps);
369*c0909341SAndroid Build Coastguard Worker             break;
370*c0909341SAndroid Build Coastguard Worker         case ARG_REALTIME_CACHE:
371*c0909341SAndroid Build Coastguard Worker             cli_settings->realtime_cache =
372*c0909341SAndroid Build Coastguard Worker                 parse_unsigned(optarg, ARG_REALTIME_CACHE, argv[0]);
373*c0909341SAndroid Build Coastguard Worker             break;
374*c0909341SAndroid Build Coastguard Worker         case ARG_FRAME_DELAY:
375*c0909341SAndroid Build Coastguard Worker             lib_settings->max_frame_delay =
376*c0909341SAndroid Build Coastguard Worker                 parse_unsigned(optarg, ARG_FRAME_DELAY, argv[0]);
377*c0909341SAndroid Build Coastguard Worker             break;
378*c0909341SAndroid Build Coastguard Worker         case ARG_THREADS:
379*c0909341SAndroid Build Coastguard Worker             lib_settings->n_threads =
380*c0909341SAndroid Build Coastguard Worker                 parse_unsigned(optarg, ARG_THREADS, argv[0]);
381*c0909341SAndroid Build Coastguard Worker             break;
382*c0909341SAndroid Build Coastguard Worker         case ARG_VERIFY:
383*c0909341SAndroid Build Coastguard Worker             cli_settings->verify = optarg;
384*c0909341SAndroid Build Coastguard Worker             break;
385*c0909341SAndroid Build Coastguard Worker         case ARG_FILM_GRAIN:
386*c0909341SAndroid Build Coastguard Worker             lib_settings->apply_grain =
387*c0909341SAndroid Build Coastguard Worker                 !!parse_unsigned(optarg, ARG_FILM_GRAIN, argv[0]);
388*c0909341SAndroid Build Coastguard Worker             grain_specified = 1;
389*c0909341SAndroid Build Coastguard Worker             break;
390*c0909341SAndroid Build Coastguard Worker         case ARG_OPPOINT:
391*c0909341SAndroid Build Coastguard Worker             lib_settings->operating_point =
392*c0909341SAndroid Build Coastguard Worker                 parse_unsigned(optarg, ARG_OPPOINT, argv[0]);
393*c0909341SAndroid Build Coastguard Worker             break;
394*c0909341SAndroid Build Coastguard Worker         case ARG_ALL_LAYERS:
395*c0909341SAndroid Build Coastguard Worker             lib_settings->all_layers =
396*c0909341SAndroid Build Coastguard Worker                 !!parse_unsigned(optarg, ARG_ALL_LAYERS, argv[0]);
397*c0909341SAndroid Build Coastguard Worker             break;
398*c0909341SAndroid Build Coastguard Worker         case ARG_SIZE_LIMIT: {
399*c0909341SAndroid Build Coastguard Worker             char *arg = optarg, *end;
400*c0909341SAndroid Build Coastguard Worker             uint64_t res = strtoul(arg, &end, 0);
401*c0909341SAndroid Build Coastguard Worker             if (*end == 'x') // NxM
402*c0909341SAndroid Build Coastguard Worker                 res *= strtoul((arg = end + 1), &end, 0);
403*c0909341SAndroid Build Coastguard Worker             if (*end || end == arg || res >= UINT_MAX)
404*c0909341SAndroid Build Coastguard Worker                 error(argv[0], optarg, ARG_SIZE_LIMIT, "an integer or dimension");
405*c0909341SAndroid Build Coastguard Worker             lib_settings->frame_size_limit = (unsigned) res;
406*c0909341SAndroid Build Coastguard Worker             break;
407*c0909341SAndroid Build Coastguard Worker         }
408*c0909341SAndroid Build Coastguard Worker         case ARG_STRICT_STD_COMPLIANCE:
409*c0909341SAndroid Build Coastguard Worker             lib_settings->strict_std_compliance =
410*c0909341SAndroid Build Coastguard Worker                 parse_unsigned(optarg, ARG_STRICT_STD_COMPLIANCE, argv[0]);
411*c0909341SAndroid Build Coastguard Worker             break;
412*c0909341SAndroid Build Coastguard Worker         case 'v':
413*c0909341SAndroid Build Coastguard Worker             fprintf(stderr, "%s\n", dav1d_version());
414*c0909341SAndroid Build Coastguard Worker             exit(0);
415*c0909341SAndroid Build Coastguard Worker         case ARG_CPU_MASK:
416*c0909341SAndroid Build Coastguard Worker             dav1d_set_cpu_flags_mask(parse_enum(optarg, cpu_mask_tbl, ARRAY_SIZE(cpu_mask_tbl),
417*c0909341SAndroid Build Coastguard Worker                                                 ARG_CPU_MASK, argv[0]));
418*c0909341SAndroid Build Coastguard Worker             break;
419*c0909341SAndroid Build Coastguard Worker         case ARG_NEG_STRIDE:
420*c0909341SAndroid Build Coastguard Worker             cli_settings->neg_stride = 1;
421*c0909341SAndroid Build Coastguard Worker             break;
422*c0909341SAndroid Build Coastguard Worker         case ARG_OUTPUT_INVISIBLE:
423*c0909341SAndroid Build Coastguard Worker             lib_settings->output_invisible_frames =
424*c0909341SAndroid Build Coastguard Worker                 !!parse_unsigned(optarg, ARG_OUTPUT_INVISIBLE, argv[0]);
425*c0909341SAndroid Build Coastguard Worker             break;
426*c0909341SAndroid Build Coastguard Worker         case ARG_INLOOP_FILTERS:
427*c0909341SAndroid Build Coastguard Worker             lib_settings->inloop_filters =
428*c0909341SAndroid Build Coastguard Worker                 parse_enum(optarg, inloop_filters_tbl,
429*c0909341SAndroid Build Coastguard Worker                            ARRAY_SIZE(inloop_filters_tbl),ARG_INLOOP_FILTERS, argv[0]);
430*c0909341SAndroid Build Coastguard Worker             break;
431*c0909341SAndroid Build Coastguard Worker         case ARG_DECODE_FRAME_TYPE:
432*c0909341SAndroid Build Coastguard Worker             lib_settings->decode_frame_type =
433*c0909341SAndroid Build Coastguard Worker                 parse_enum(optarg, decode_frame_type_tbl,
434*c0909341SAndroid Build Coastguard Worker                            ARRAY_SIZE(decode_frame_type_tbl), ARG_DECODE_FRAME_TYPE, argv[0]);
435*c0909341SAndroid Build Coastguard Worker             break;
436*c0909341SAndroid Build Coastguard Worker         default:
437*c0909341SAndroid Build Coastguard Worker             usage(argv[0], NULL);
438*c0909341SAndroid Build Coastguard Worker         }
439*c0909341SAndroid Build Coastguard Worker     }
440*c0909341SAndroid Build Coastguard Worker 
441*c0909341SAndroid Build Coastguard Worker     if (optind < argc)
442*c0909341SAndroid Build Coastguard Worker         usage(argv[0], "Extra/unused arguments found, e.g. '%s'\n", argv[optind]);
443*c0909341SAndroid Build Coastguard Worker     if (cli_settings->verify) {
444*c0909341SAndroid Build Coastguard Worker         if (cli_settings->outputfile)
445*c0909341SAndroid Build Coastguard Worker             usage(argv[0], "Verification (--verify) requires output file (-o/--output) to not set");
446*c0909341SAndroid Build Coastguard Worker         if (cli_settings->muxer && strcmp(cli_settings->muxer, "md5") &&
447*c0909341SAndroid Build Coastguard Worker             strcmp(cli_settings->muxer, "xxh3"))
448*c0909341SAndroid Build Coastguard Worker         {
449*c0909341SAndroid Build Coastguard Worker             usage(argv[0], "Verification (--verify) requires a checksum muxer (md5 or xxh3)");
450*c0909341SAndroid Build Coastguard Worker         }
451*c0909341SAndroid Build Coastguard Worker 
452*c0909341SAndroid Build Coastguard Worker         cli_settings->outputfile = "-";
453*c0909341SAndroid Build Coastguard Worker         if (!cli_settings->muxer)
454*c0909341SAndroid Build Coastguard Worker             cli_settings->muxer = "md5";
455*c0909341SAndroid Build Coastguard Worker     }
456*c0909341SAndroid Build Coastguard Worker 
457*c0909341SAndroid Build Coastguard Worker     if (!grain_specified && cli_settings->muxer &&
458*c0909341SAndroid Build Coastguard Worker         (!strcmp(cli_settings->muxer, "md5") ||
459*c0909341SAndroid Build Coastguard Worker         !strcmp(cli_settings->muxer, "xxh3")))
460*c0909341SAndroid Build Coastguard Worker     {
461*c0909341SAndroid Build Coastguard Worker         lib_settings->apply_grain = 0;
462*c0909341SAndroid Build Coastguard Worker     }
463*c0909341SAndroid Build Coastguard Worker 
464*c0909341SAndroid Build Coastguard Worker     if (!cli_settings->inputfile)
465*c0909341SAndroid Build Coastguard Worker         usage(argv[0], "Input file (-i/--input) is required");
466*c0909341SAndroid Build Coastguard Worker     if ((!cli_settings->muxer || strcmp(cli_settings->muxer, "null")) &&
467*c0909341SAndroid Build Coastguard Worker         !cli_settings->outputfile)
468*c0909341SAndroid Build Coastguard Worker     {
469*c0909341SAndroid Build Coastguard Worker         usage(argv[0], "Output file (-o/--output) is required");
470*c0909341SAndroid Build Coastguard Worker     }
471*c0909341SAndroid Build Coastguard Worker }
472