Line | Branch | Exec | Source |
---|---|---|---|
1 | /* | ||
2 | * Copyright (c) 2002-2006 Michael Niedermayer <michaelni@gmx.at> | ||
3 | * Copyright (c) 2006 Oded Shimon <ods15@ods15.dyndns.org> | ||
4 | * | ||
5 | * This file is part of FFmpeg. | ||
6 | * | ||
7 | * FFmpeg is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU Lesser General Public | ||
9 | * License as published by the Free Software Foundation; either | ||
10 | * version 2.1 of the License, or (at your option) any later version. | ||
11 | * | ||
12 | * FFmpeg is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
15 | * Lesser General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU Lesser General Public | ||
18 | * License along with FFmpeg; if not, write to the Free Software | ||
19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
20 | */ | ||
21 | |||
22 | /** | ||
23 | * @file | ||
24 | * simple arithmetic expression evaluator. | ||
25 | * | ||
26 | * see http://joe.hotchkiss.com/programming/eval/eval.html | ||
27 | */ | ||
28 | |||
29 | #include <float.h> | ||
30 | #include "attributes.h" | ||
31 | #include "avutil.h" | ||
32 | #include "common.h" | ||
33 | #include "eval.h" | ||
34 | #include "ffmath.h" | ||
35 | #include "log.h" | ||
36 | #include "mathematics.h" | ||
37 | #include "mem.h" | ||
38 | #include "sfc64.h" | ||
39 | #include "time.h" | ||
40 | #include "avstring.h" | ||
41 | #include "reverse.h" | ||
42 | |||
43 | typedef struct Parser { | ||
44 | const AVClass *class; | ||
45 | int stack_index; | ||
46 | char *s; | ||
47 | const double *const_values; | ||
48 | const char * const *const_names; // NULL terminated | ||
49 | double (* const *funcs1)(void *, double a); // NULL terminated | ||
50 | const char * const *func1_names; // NULL terminated | ||
51 | double (* const *funcs2)(void *, double a, double b); // NULL terminated | ||
52 | const char * const *func2_names; // NULL terminated | ||
53 | void *opaque; | ||
54 | int log_offset; | ||
55 | void *log_ctx; | ||
56 | #define VARS 10 | ||
57 | double *var; | ||
58 | FFSFC64 *prng_state; | ||
59 | } Parser; | ||
60 | |||
61 | static const AVClass eval_class = { | ||
62 | .class_name = "Eval", | ||
63 | .item_name = av_default_item_name, | ||
64 | .option = NULL, | ||
65 | .version = LIBAVUTIL_VERSION_INT, | ||
66 | .log_level_offset_offset = offsetof(Parser, log_offset), | ||
67 | .parent_log_context_offset = offsetof(Parser, log_ctx), | ||
68 | }; | ||
69 | |||
70 | static const struct { | ||
71 | double bin_val; | ||
72 | double dec_val; | ||
73 | int8_t exp; | ||
74 | } si_prefixes['z' - 'E' + 1] = { | ||
75 | ['y'-'E']= { 8.271806125530276749e-25, 1e-24, -24 }, | ||
76 | ['z'-'E']= { 8.4703294725430034e-22, 1e-21, -21 }, | ||
77 | ['a'-'E']= { 8.6736173798840355e-19, 1e-18, -18 }, | ||
78 | ['f'-'E']= { 8.8817841970012523e-16, 1e-15, -15 }, | ||
79 | ['p'-'E']= { 9.0949470177292824e-13, 1e-12, -12 }, | ||
80 | ['n'-'E']= { 9.3132257461547852e-10, 1e-9, -9 }, | ||
81 | ['u'-'E']= { 9.5367431640625e-7, 1e-6, -6 }, | ||
82 | ['m'-'E']= { 9.765625e-4, 1e-3, -3 }, | ||
83 | ['c'-'E']= { 9.8431332023036951e-3, 1e-2, -2 }, | ||
84 | ['d'-'E']= { 9.921256574801246e-2, 1e-1, -1 }, | ||
85 | ['h'-'E']= { 1.0159366732596479e2, 1e2, 2 }, | ||
86 | ['k'-'E']= { 1.024e3, 1e3, 3 }, | ||
87 | ['K'-'E']= { 1.024e3, 1e3, 3 }, | ||
88 | ['M'-'E']= { 1.048576e6, 1e6, 6 }, | ||
89 | ['G'-'E']= { 1.073741824e9, 1e9, 9 }, | ||
90 | ['T'-'E']= { 1.099511627776e12, 1e12, 12 }, | ||
91 | ['P'-'E']= { 1.125899906842624e15, 1e15, 15 }, | ||
92 | ['E'-'E']= { 1.152921504606847e18, 1e18, 18 }, | ||
93 | ['Z'-'E']= { 1.1805916207174113e21, 1e21, 21 }, | ||
94 | ['Y'-'E']= { 1.2089258196146292e24, 1e24, 24 }, | ||
95 | }; | ||
96 | |||
97 | static const struct { | ||
98 | const char *name; | ||
99 | double value; | ||
100 | } constants[] = { | ||
101 | { "E", M_E }, | ||
102 | { "PI", M_PI }, | ||
103 | { "PHI", M_PHI }, | ||
104 | { "QP2LAMBDA", FF_QP2LAMBDA }, | ||
105 | }; | ||
106 | |||
107 | 133423 | double av_strtod(const char *numstr, char **tail) | |
108 | { | ||
109 | double d; | ||
110 | char *next; | ||
111 |
4/4✓ Branch 0 taken 33074 times.
✓ Branch 1 taken 100349 times.
✓ Branch 2 taken 139 times.
✓ Branch 3 taken 32935 times.
|
133423 | if(numstr[0]=='0' && (numstr[1]|0x20)=='x') { |
112 | 139 | d = strtoul(numstr, &next, 16); | |
113 | } else | ||
114 | 133284 | d = strtod(numstr, &next); | |
115 | /* if parsing succeeded, check for and interpret postfixes */ | ||
116 |
2/2✓ Branch 0 taken 93643 times.
✓ Branch 1 taken 39780 times.
|
133423 | if (next!=numstr) { |
117 |
3/4✓ Branch 0 taken 6 times.
✓ Branch 1 taken 93637 times.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
|
93643 | if (next[0] == 'd' && next[1] == 'B') { |
118 | /* treat dB as decibels instead of decibytes */ | ||
119 | 6 | d = ff_exp10(d / 20); | |
120 | 6 | next += 2; | |
121 |
3/4✓ Branch 0 taken 179 times.
✓ Branch 1 taken 93458 times.
✓ Branch 2 taken 179 times.
✗ Branch 3 not taken.
|
93637 | } else if (*next >= 'E' && *next <= 'z') { |
122 | 179 | int e= si_prefixes[*next - 'E'].exp; | |
123 |
2/2✓ Branch 0 taken 177 times.
✓ Branch 1 taken 2 times.
|
179 | if (e) { |
124 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 171 times.
|
177 | if (next[1] == 'i') { |
125 | 6 | d*= si_prefixes[*next - 'E'].bin_val; | |
126 | 6 | next+=2; | |
127 | } else { | ||
128 | 171 | d*= si_prefixes[*next - 'E'].dec_val; | |
129 | 171 | next++; | |
130 | } | ||
131 | } | ||
132 | } | ||
133 | |||
134 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 93642 times.
|
93643 | if (*next=='B') { |
135 | 1 | d*=8; | |
136 | 1 | next++; | |
137 | } | ||
138 | } | ||
139 | /* if requested, fill in tail with the position after the last parsed | ||
140 | character */ | ||
141 |
2/2✓ Branch 0 taken 133418 times.
✓ Branch 1 taken 5 times.
|
133423 | if (tail) |
142 | 133418 | *tail = next; | |
143 | 133423 | return d; | |
144 | } | ||
145 | |||
146 | #define IS_IDENTIFIER_CHAR(c) ((c) - '0' <= 9U || (c) - 'a' <= 25U || (c) - 'A' <= 25U || (c) == '_') | ||
147 | |||
148 | 463645 | static int strmatch(const char *s, const char *prefix) | |
149 | { | ||
150 | int i; | ||
151 |
2/2✓ Branch 0 taken 547257 times.
✓ Branch 1 taken 35796 times.
|
583053 | for (i=0; prefix[i]; i++) { |
152 |
2/2✓ Branch 0 taken 427849 times.
✓ Branch 1 taken 119408 times.
|
547257 | if (prefix[i] != s[i]) return 0; |
153 | } | ||
154 | /* return 1 only if the s identifier is terminated */ | ||
155 |
6/8✓ Branch 0 taken 35796 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 35770 times.
✓ Branch 3 taken 26 times.
✓ Branch 4 taken 35757 times.
✓ Branch 5 taken 13 times.
✓ Branch 6 taken 35757 times.
✗ Branch 7 not taken.
|
35796 | return !IS_IDENTIFIER_CHAR(s[i]); |
156 | } | ||
157 | |||
158 | struct AVExpr { | ||
159 | enum { | ||
160 | e_value, e_const, e_func0, e_func1, e_func2, | ||
161 | e_squish, e_gauss, e_ld, e_isnan, e_isinf, | ||
162 | e_mod, e_max, e_min, e_eq, e_gt, e_gte, e_lte, e_lt, | ||
163 | e_pow, e_mul, e_div, e_add, | ||
164 | e_last, e_st, e_while, e_taylor, e_root, e_floor, e_ceil, e_trunc, e_round, | ||
165 | e_sqrt, e_not, e_random, e_hypot, e_gcd, | ||
166 | e_if, e_ifnot, e_print, e_bitand, e_bitor, e_between, e_clip, e_atan2, e_lerp, | ||
167 | e_sgn, e_randomi | ||
168 | } type; | ||
169 | double value; // is sign in other types | ||
170 | int const_index; | ||
171 | union { | ||
172 | double (*func0)(double); | ||
173 | double (*func1)(void *, double); | ||
174 | double (*func2)(void *, double, double); | ||
175 | } a; | ||
176 | struct AVExpr *param[3]; | ||
177 | double *var; | ||
178 | FFSFC64 *prng_state; | ||
179 | }; | ||
180 | |||
181 | ✗ | static double etime(double v) | |
182 | { | ||
183 | ✗ | return av_gettime() * 0.000001; | |
184 | } | ||
185 | |||
186 | 207078474 | static double eval_expr(Parser *p, AVExpr *e) | |
187 | { | ||
188 |
25/29✓ Branch 0 taken 66649758 times.
✓ Branch 1 taken 38803675 times.
✓ Branch 2 taken 17334499 times.
✓ Branch 3 taken 280986 times.
✓ Branch 4 taken 6 times.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 1 times.
✓ Branch 7 taken 1695 times.
✓ Branch 8 taken 4 times.
✓ Branch 9 taken 3 times.
✓ Branch 10 taken 20 times.
✓ Branch 11 taken 2 times.
✓ Branch 12 taken 2 times.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✓ Branch 15 taken 2 times.
✓ Branch 16 taken 299 times.
✓ Branch 17 taken 32885 times.
✓ Branch 18 taken 4 times.
✓ Branch 19 taken 3 times.
✓ Branch 20 taken 1323198 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 1 times.
✓ Branch 23 taken 264913 times.
✗ Branch 24 not taken.
✓ Branch 25 taken 4 times.
✓ Branch 26 taken 2 times.
✓ Branch 27 taken 2 times.
✓ Branch 28 taken 82386509 times.
|
207078474 | switch (e->type) { |
189 | 66649758 | case e_value: return e->value; | |
190 | 38803675 | case e_const: return e->value * p->const_values[e->const_index]; | |
191 | 17334499 | case e_func0: return e->value * e->a.func0(eval_expr(p, e->param[0])); | |
192 | 280986 | case e_func1: return e->value * e->a.func1(p->opaque, eval_expr(p, e->param[0])); | |
193 | 6 | case e_func2: return e->value * e->a.func2(p->opaque, eval_expr(p, e->param[0]), eval_expr(p, e->param[1])); | |
194 | 1 | case e_squish: return 1/(1+exp(4*eval_expr(p, e->param[0]))); | |
195 | 1 | case e_gauss: { double d = eval_expr(p, e->param[0]); return exp(-d*d/2)/sqrt(2*M_PI); } | |
196 | 1695 | case e_ld: return e->value * p->var[av_clip(eval_expr(p, e->param[0]), 0, VARS-1)]; | |
197 |
2/2✓ Branch 1 taken 2 times.
✓ Branch 2 taken 2 times.
|
4 | case e_isnan: return e->value * !!isnan(eval_expr(p, e->param[0])); |
198 |
2/2✓ Branch 1 taken 1 times.
✓ Branch 2 taken 2 times.
|
3 | case e_isinf: return e->value * !!isinf(eval_expr(p, e->param[0])); |
199 | 20 | case e_floor: return e->value * floor(eval_expr(p, e->param[0])); | |
200 | 2 | case e_ceil : return e->value * ceil (eval_expr(p, e->param[0])); | |
201 | 2 | case e_trunc: return e->value * trunc(eval_expr(p, e->param[0])); | |
202 | ✗ | case e_round: return e->value * round(eval_expr(p, e->param[0])); | |
203 | ✗ | case e_sgn: return e->value * FFDIFFSIGN(eval_expr(p, e->param[0]), 0); | |
204 | 2 | case e_sqrt: return e->value * sqrt (eval_expr(p, e->param[0])); | |
205 |
2/2✓ Branch 1 taken 201 times.
✓ Branch 2 taken 98 times.
|
299 | case e_not: return e->value * (eval_expr(p, e->param[0]) == 0); |
206 |
2/2✓ Branch 1 taken 16391 times.
✓ Branch 2 taken 16494 times.
|
49379 | case e_if: return e->value * (eval_expr(p, e->param[0]) ? eval_expr(p, e->param[1]) : |
207 |
2/2✓ Branch 0 taken 16493 times.
✓ Branch 1 taken 1 times.
|
16494 | e->param[2] ? eval_expr(p, e->param[2]) : 0); |
208 |
2/2✓ Branch 1 taken 2 times.
✓ Branch 2 taken 2 times.
|
6 | case e_ifnot: return e->value * (!eval_expr(p, e->param[0]) ? eval_expr(p, e->param[1]) : |
209 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
|
2 | e->param[2] ? eval_expr(p, e->param[2]) : 0); |
210 | 3 | case e_clip: { | |
211 | 3 | double x = eval_expr(p, e->param[0]); | |
212 | 3 | double min = eval_expr(p, e->param[1]), max = eval_expr(p, e->param[2]); | |
213 |
6/8✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
|
3 | if (isnan(min) || isnan(max) || isnan(x) || min > max) |
214 | 3 | return NAN; | |
215 | ✗ | return e->value * av_clipd(eval_expr(p, e->param[0]), min, max); | |
216 | } | ||
217 | 1323198 | case e_between: { | |
218 | 1323198 | double d = eval_expr(p, e->param[0]); | |
219 |
4/4✓ Branch 1 taken 793893 times.
✓ Branch 2 taken 529305 times.
✓ Branch 3 taken 176442 times.
✓ Branch 4 taken 617451 times.
|
2117091 | return e->value * (d >= eval_expr(p, e->param[1]) && |
220 | 793893 | d <= eval_expr(p, e->param[2])); | |
221 | } | ||
222 | ✗ | case e_lerp: { | |
223 | ✗ | double v0 = eval_expr(p, e->param[0]); | |
224 | ✗ | double v1 = eval_expr(p, e->param[1]); | |
225 | ✗ | double f = eval_expr(p, e->param[2]); | |
226 | ✗ | return v0 + (v1 - v0) * f; | |
227 | } | ||
228 | 1 | case e_print: { | |
229 | 1 | double x = eval_expr(p, e->param[0]); | |
230 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | int level = e->param[1] ? av_clip(eval_expr(p, e->param[1]), INT_MIN, INT_MAX) : AV_LOG_INFO; |
231 | 1 | av_log(p, level, "%f\n", x); | |
232 | 1 | return x; | |
233 | } | ||
234 | |||
235 | #define COMPUTE_NEXT_RANDOM() \ | ||
236 | int idx = av_clip(eval_expr(p, e->param[0]), 0, VARS-1); \ | ||
237 | FFSFC64 *s = p->prng_state + idx; \ | ||
238 | uint64_t r; \ | ||
239 | \ | ||
240 | if (!s->counter) { \ | ||
241 | r = isnan(p->var[idx]) ? 0 : p->var[idx]; \ | ||
242 | ff_sfc64_init(s, r, r, r, 12); \ | ||
243 | } \ | ||
244 | r = ff_sfc64_get(s); \ | ||
245 | p->var[idx] = r; \ | ||
246 | |||
247 | 264913 | case e_random: { | |
248 |
3/4✓ Branch 1 taken 54 times.
✓ Branch 2 taken 264859 times.
✓ Branch 3 taken 54 times.
✗ Branch 4 not taken.
|
264913 | COMPUTE_NEXT_RANDOM(); |
249 | 264913 | return r * (1.0/UINT64_MAX); | |
250 | } | ||
251 | ✗ | case e_randomi: { | |
252 | ✗ | double min = eval_expr(p, e->param[1]); | |
253 | ✗ | double max = eval_expr(p, e->param[2]); | |
254 | ✗ | COMPUTE_NEXT_RANDOM(); | |
255 | ✗ | return min + (max - min) * r / UINT64_MAX; | |
256 | } | ||
257 | 4 | case e_while: { | |
258 | 4 | double d = NAN; | |
259 |
2/2✓ Branch 1 taken 210 times.
✓ Branch 2 taken 4 times.
|
214 | while (eval_expr(p, e->param[0])) |
260 | 210 | d=eval_expr(p, e->param[1]); | |
261 | 4 | return d; | |
262 | } | ||
263 | 2 | case e_taylor: { | |
264 | 2 | double t = 1, d = 0, v; | |
265 | 2 | double x = eval_expr(p, e->param[1]); | |
266 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
|
2 | int id = e->param[2] ? av_clip(eval_expr(p, e->param[2]), 0, VARS-1) : 0; |
267 | int i; | ||
268 | 2 | double var0 = p->var[id]; | |
269 |
1/2✓ Branch 0 taken 43 times.
✗ Branch 1 not taken.
|
43 | for(i=0; i<1000; i++) { |
270 | 43 | double ld = d; | |
271 | 43 | p->var[id] = i; | |
272 | 43 | v = eval_expr(p, e->param[0]); | |
273 | 43 | d += t*v; | |
274 |
4/4✓ Branch 0 taken 14 times.
✓ Branch 1 taken 29 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 12 times.
|
43 | if(ld==d && v) |
275 | 2 | break; | |
276 | 41 | t *= x / (i+1); | |
277 | } | ||
278 | 2 | p->var[id] = var0; | |
279 | 2 | return d; | |
280 | } | ||
281 | 2 | case e_root: { | |
282 | int i, j; | ||
283 | 2 | double low = -1, high = -1, v, low_v = -DBL_MAX, high_v = DBL_MAX; | |
284 | 2 | double var0 = p->var[0]; | |
285 | 2 | double x_max = eval_expr(p, e->param[1]); | |
286 |
1/2✓ Branch 0 taken 491 times.
✗ Branch 1 not taken.
|
491 | for(i=-1; i<1024; i++) { |
287 |
2/2✓ Branch 0 taken 315 times.
✓ Branch 1 taken 176 times.
|
491 | if(i<255) { |
288 | 315 | p->var[0] = ff_reverse[i&255]*x_max/255; | |
289 | } else { | ||
290 | 176 | p->var[0] = x_max*pow(0.9, i-255); | |
291 |
2/2✓ Branch 0 taken 88 times.
✓ Branch 1 taken 88 times.
|
176 | if (i&1) p->var[0] *= -1; |
292 |
2/2✓ Branch 0 taken 88 times.
✓ Branch 1 taken 88 times.
|
176 | if (i&2) p->var[0] += low; |
293 | 88 | else p->var[0] += high; | |
294 | } | ||
295 | 491 | v = eval_expr(p, e->param[0]); | |
296 |
4/4✓ Branch 0 taken 433 times.
✓ Branch 1 taken 58 times.
✓ Branch 2 taken 30 times.
✓ Branch 3 taken 403 times.
|
491 | if (v<=0 && v>low_v) { |
297 | 30 | low = p->var[0]; | |
298 | 30 | low_v = v; | |
299 | } | ||
300 |
4/4✓ Branch 0 taken 59 times.
✓ Branch 1 taken 432 times.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 53 times.
|
491 | if (v>=0 && v<high_v) { |
301 | 6 | high = p->var[0]; | |
302 | 6 | high_v = v; | |
303 | } | ||
304 |
4/4✓ Branch 0 taken 433 times.
✓ Branch 1 taken 58 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 431 times.
|
491 | if (low>=0 && high>=0){ |
305 |
1/2✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
|
48 | for (j=0; j<1000; j++) { |
306 | 48 | p->var[0] = (low+high)*0.5; | |
307 |
3/4✓ Branch 0 taken 46 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 46 times.
✗ Branch 3 not taken.
|
48 | if (low == p->var[0] || high == p->var[0]) |
308 | break; | ||
309 | 46 | v = eval_expr(p, e->param[0]); | |
310 |
2/2✓ Branch 0 taken 21 times.
✓ Branch 1 taken 25 times.
|
46 | if (v<=0) low = p->var[0]; |
311 |
2/2✓ Branch 0 taken 26 times.
✓ Branch 1 taken 20 times.
|
46 | if (v>=0) high= p->var[0]; |
312 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 46 times.
|
46 | if (isnan(v)) { |
313 | ✗ | low = high = v; | |
314 | ✗ | break; | |
315 | } | ||
316 | } | ||
317 | 2 | break; | |
318 | } | ||
319 | } | ||
320 | 2 | p->var[0] = var0; | |
321 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | return -low_v<high_v ? low : high; |
322 | } | ||
323 | 82386509 | default: { | |
324 | 82386509 | double d = eval_expr(p, e->param[0]); | |
325 | 82386509 | double d2 = eval_expr(p, e->param[1]); | |
326 |
18/20✓ Branch 0 taken 198 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 234 times.
✓ Branch 5 taken 1333 times.
✓ Branch 6 taken 1 times.
✓ Branch 7 taken 2 times.
✓ Branch 8 taken 216 times.
✓ Branch 9 taken 3458 times.
✓ Branch 10 taken 67680309 times.
✓ Branch 11 taken 3611058 times.
✓ Branch 12 taken 11088985 times.
✓ Branch 13 taken 243 times.
✓ Branch 14 taken 464 times.
✓ Branch 15 taken 1 times.
✗ Branch 16 not taken.
✓ Branch 17 taken 2 times.
✓ Branch 18 taken 1 times.
✗ Branch 19 not taken.
|
82386509 | switch (e->type) { |
327 |
1/2✓ Branch 0 taken 198 times.
✗ Branch 1 not taken.
|
198 | case e_mod: return e->value * (d - floor(d2 ? d / d2 : d * INFINITY) * d2); |
328 | 1 | case e_gcd: return e->value * av_gcd(d,d2); | |
329 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | case e_max: return e->value * (d > d2 ? d : d2); |
330 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | case e_min: return e->value * (d < d2 ? d : d2); |
331 |
2/2✓ Branch 0 taken 57 times.
✓ Branch 1 taken 177 times.
|
234 | case e_eq: return e->value * (d == d2 ? 1.0 : 0.0); |
332 |
2/2✓ Branch 0 taken 12 times.
✓ Branch 1 taken 1321 times.
|
1333 | case e_gt: return e->value * (d > d2 ? 1.0 : 0.0); |
333 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | case e_gte: return e->value * (d >= d2 ? 1.0 : 0.0); |
334 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
|
2 | case e_lt: return e->value * (d < d2 ? 1.0 : 0.0); |
335 |
2/2✓ Branch 0 taken 212 times.
✓ Branch 1 taken 4 times.
|
216 | case e_lte: return e->value * (d <= d2 ? 1.0 : 0.0); |
336 | 3458 | case e_pow: return e->value * pow(d, d2); | |
337 | 67680309 | case e_mul: return e->value * (d * d2); | |
338 |
2/2✓ Branch 0 taken 3611050 times.
✓ Branch 1 taken 8 times.
|
3611058 | case e_div: return e->value * (d2 ? (d / d2) : d * INFINITY); |
339 | 11088985 | case e_add: return e->value * (d + d2); | |
340 | 243 | case e_last:return e->value * d2; | |
341 | 464 | case e_st : { | |
342 | 464 | int index = av_clip(d, 0, VARS-1); | |
343 | 464 | p->prng_state[index].counter = 0; | |
344 | 464 | return e->value * (p->var[index]= d2); | |
345 | } | ||
346 | 1 | case e_hypot:return e->value * hypot(d, d2); | |
347 | ✗ | case e_atan2:return e->value * atan2(d, d2); | |
348 |
3/4✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
2 | case e_bitand: return isnan(d) || isnan(d2) ? NAN : e->value * ((long int)d & (long int)d2); |
349 |
2/4✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | case e_bitor: return isnan(d) || isnan(d2) ? NAN : e->value * ((long int)d | (long int)d2); |
350 | } | ||
351 | } | ||
352 | } | ||
353 | ✗ | return NAN; | |
354 | } | ||
355 | |||
356 | static int parse_expr(AVExpr **e, Parser *p); | ||
357 | |||
358 | 561233 | void av_expr_free(AVExpr *e) | |
359 | { | ||
360 |
2/2✓ Branch 0 taken 458813 times.
✓ Branch 1 taken 102420 times.
|
561233 | if (!e) return; |
361 | 102420 | av_expr_free(e->param[0]); | |
362 | 102420 | av_expr_free(e->param[1]); | |
363 | 102420 | av_expr_free(e->param[2]); | |
364 | 102420 | av_freep(&e->var); | |
365 | 102420 | av_freep(&e->prng_state); | |
366 | 102420 | av_freep(&e); | |
367 | } | ||
368 | |||
369 | 97032 | static int parse_primary(AVExpr **e, Parser *p) | |
370 | { | ||
371 | 97032 | AVExpr *d = av_mallocz(sizeof(AVExpr)); | |
372 | 97032 | char *next = p->s, *s0 = p->s; | |
373 | int ret, i; | ||
374 | |||
375 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 97032 times.
|
97032 | if (!d) |
376 | ✗ | return AVERROR(ENOMEM); | |
377 | |||
378 | /* number */ | ||
379 | 97032 | d->value = av_strtod(p->s, &next); | |
380 |
2/2✓ Branch 0 taken 57252 times.
✓ Branch 1 taken 39780 times.
|
97032 | if (next != p->s) { |
381 | 57252 | d->type = e_value; | |
382 | 57252 | p->s= next; | |
383 | 57252 | *e = d; | |
384 | 57252 | return 0; | |
385 | } | ||
386 | 39780 | d->value = 1; | |
387 | |||
388 | /* named constants */ | ||
389 |
4/4✓ Branch 0 taken 440869 times.
✓ Branch 1 taken 15 times.
✓ Branch 2 taken 436485 times.
✓ Branch 3 taken 4384 times.
|
440884 | for (i=0; p->const_names && p->const_names[i]; i++) { |
390 |
2/2✓ Branch 1 taken 35381 times.
✓ Branch 2 taken 401104 times.
|
436485 | if (strmatch(p->s, p->const_names[i])) { |
391 | 35381 | p->s+= strlen(p->const_names[i]); | |
392 | 35381 | d->type = e_const; | |
393 | 35381 | d->const_index = i; | |
394 | 35381 | *e = d; | |
395 | 35381 | return 0; | |
396 | } | ||
397 | } | ||
398 |
2/2✓ Branch 0 taken 17474 times.
✓ Branch 1 taken 4338 times.
|
21812 | for (i = 0; i < FF_ARRAY_ELEMS(constants); i++) { |
399 |
2/2✓ Branch 1 taken 61 times.
✓ Branch 2 taken 17413 times.
|
17474 | if (strmatch(p->s, constants[i].name)) { |
400 | 61 | p->s += strlen(constants[i].name); | |
401 | 61 | d->type = e_value; | |
402 | 61 | d->value = constants[i].value; | |
403 | 61 | *e = d; | |
404 | 61 | return 0; | |
405 | } | ||
406 | } | ||
407 | |||
408 | 4338 | p->s= strchr(p->s, '('); | |
409 |
2/2✓ Branch 0 taken 28 times.
✓ Branch 1 taken 4310 times.
|
4338 | if (!p->s) { |
410 | 28 | av_log(p, AV_LOG_ERROR, "Undefined constant or missing '(' in '%s'\n", s0); | |
411 | 28 | p->s= next; | |
412 | 28 | av_expr_free(d); | |
413 | 28 | return AVERROR(EINVAL); | |
414 | } | ||
415 | 4310 | p->s++; // "(" | |
416 |
2/2✓ Branch 0 taken 3990 times.
✓ Branch 1 taken 320 times.
|
4310 | if (*next == '(') { // special case do-nothing |
417 | 3990 | av_freep(&d); | |
418 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 3990 times.
|
3990 | if ((ret = parse_expr(&d, p)) < 0) |
419 | ✗ | return ret; | |
420 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3990 times.
|
3990 | if (p->s[0] != ')') { |
421 | ✗ | av_log(p, AV_LOG_ERROR, "Missing ')' in '%s'\n", s0); | |
422 | ✗ | av_expr_free(d); | |
423 | ✗ | return AVERROR(EINVAL); | |
424 | } | ||
425 | 3990 | p->s++; // ")" | |
426 | 3990 | *e = d; | |
427 | 3990 | return 0; | |
428 | } | ||
429 |
2/2✓ Branch 1 taken 4 times.
✓ Branch 2 taken 316 times.
|
320 | if ((ret = parse_expr(&(d->param[0]), p)) < 0) { |
430 | 4 | av_expr_free(d); | |
431 | 4 | return ret; | |
432 | } | ||
433 |
2/2✓ Branch 0 taken 108 times.
✓ Branch 1 taken 208 times.
|
316 | if (p->s[0]== ',') { |
434 | 108 | p->s++; // "," | |
435 | 108 | parse_expr(&d->param[1], p); | |
436 | } | ||
437 |
2/2✓ Branch 0 taken 29 times.
✓ Branch 1 taken 287 times.
|
316 | if (p->s[0]== ',') { |
438 | 29 | p->s++; // "," | |
439 | 29 | parse_expr(&d->param[2], p); | |
440 | } | ||
441 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 316 times.
|
316 | if (p->s[0] != ')') { |
442 | ✗ | av_log(p, AV_LOG_ERROR, "Missing ')' or too many args in '%s'\n", s0); | |
443 | ✗ | av_expr_free(d); | |
444 | ✗ | return AVERROR(EINVAL); | |
445 | } | ||
446 | 316 | p->s++; // ")" | |
447 | |||
448 | 316 | d->type = e_func0; | |
449 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 316 times.
|
316 | if (strmatch(next, "sinh" )) d->a.func0 = sinh; |
450 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 316 times.
|
316 | else if (strmatch(next, "cosh" )) d->a.func0 = cosh; |
451 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 316 times.
|
316 | else if (strmatch(next, "tanh" )) d->a.func0 = tanh; |
452 |
2/2✓ Branch 1 taken 28 times.
✓ Branch 2 taken 288 times.
|
316 | else if (strmatch(next, "sin" )) d->a.func0 = sin; |
453 |
2/2✓ Branch 1 taken 11 times.
✓ Branch 2 taken 277 times.
|
288 | else if (strmatch(next, "cos" )) d->a.func0 = cos; |
454 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 277 times.
|
277 | else if (strmatch(next, "tan" )) d->a.func0 = tan; |
455 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 277 times.
|
277 | else if (strmatch(next, "atan" )) d->a.func0 = atan; |
456 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 277 times.
|
277 | else if (strmatch(next, "asin" )) d->a.func0 = asin; |
457 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 277 times.
|
277 | else if (strmatch(next, "acos" )) d->a.func0 = acos; |
458 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 277 times.
|
277 | else if (strmatch(next, "exp" )) d->a.func0 = exp; |
459 |
2/2✓ Branch 1 taken 1 times.
✓ Branch 2 taken 276 times.
|
277 | else if (strmatch(next, "log" )) d->a.func0 = log; |
460 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 276 times.
|
276 | else if (strmatch(next, "abs" )) d->a.func0 = fabs; |
461 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 276 times.
|
276 | else if (strmatch(next, "time" )) d->a.func0 = etime; |
462 |
2/2✓ Branch 1 taken 1 times.
✓ Branch 2 taken 275 times.
|
276 | else if (strmatch(next, "squish")) d->type = e_squish; |
463 |
2/2✓ Branch 1 taken 1 times.
✓ Branch 2 taken 274 times.
|
275 | else if (strmatch(next, "gauss" )) d->type = e_gauss; |
464 |
2/2✓ Branch 1 taken 8 times.
✓ Branch 2 taken 266 times.
|
274 | else if (strmatch(next, "mod" )) d->type = e_mod; |
465 |
2/2✓ Branch 1 taken 2 times.
✓ Branch 2 taken 264 times.
|
266 | else if (strmatch(next, "max" )) d->type = e_max; |
466 |
2/2✓ Branch 1 taken 1 times.
✓ Branch 2 taken 263 times.
|
264 | else if (strmatch(next, "min" )) d->type = e_min; |
467 |
2/2✓ Branch 1 taken 11 times.
✓ Branch 2 taken 252 times.
|
263 | else if (strmatch(next, "eq" )) d->type = e_eq; |
468 |
2/2✓ Branch 1 taken 1 times.
✓ Branch 2 taken 251 times.
|
252 | else if (strmatch(next, "gte" )) d->type = e_gte; |
469 |
2/2✓ Branch 1 taken 5 times.
✓ Branch 2 taken 246 times.
|
251 | else if (strmatch(next, "gt" )) d->type = e_gt; |
470 |
2/2✓ Branch 1 taken 6 times.
✓ Branch 2 taken 240 times.
|
246 | else if (strmatch(next, "lte" )) d->type = e_lte; |
471 |
2/2✓ Branch 1 taken 2 times.
✓ Branch 2 taken 238 times.
|
240 | else if (strmatch(next, "lt" )) d->type = e_lt; |
472 |
2/2✓ Branch 1 taken 25 times.
✓ Branch 2 taken 213 times.
|
238 | else if (strmatch(next, "ld" )) d->type = e_ld; |
473 |
2/2✓ Branch 1 taken 4 times.
✓ Branch 2 taken 209 times.
|
213 | else if (strmatch(next, "isnan" )) d->type = e_isnan; |
474 |
2/2✓ Branch 1 taken 3 times.
✓ Branch 2 taken 206 times.
|
209 | else if (strmatch(next, "isinf" )) d->type = e_isinf; |
475 |
2/2✓ Branch 1 taken 16 times.
✓ Branch 2 taken 190 times.
|
206 | else if (strmatch(next, "st" )) d->type = e_st; |
476 |
2/2✓ Branch 1 taken 4 times.
✓ Branch 2 taken 186 times.
|
190 | else if (strmatch(next, "while" )) d->type = e_while; |
477 |
2/2✓ Branch 1 taken 2 times.
✓ Branch 2 taken 184 times.
|
186 | else if (strmatch(next, "taylor")) d->type = e_taylor; |
478 |
2/2✓ Branch 1 taken 2 times.
✓ Branch 2 taken 182 times.
|
184 | else if (strmatch(next, "root" )) d->type = e_root; |
479 |
2/2✓ Branch 1 taken 4 times.
✓ Branch 2 taken 178 times.
|
182 | else if (strmatch(next, "floor" )) d->type = e_floor; |
480 |
2/2✓ Branch 1 taken 2 times.
✓ Branch 2 taken 176 times.
|
178 | else if (strmatch(next, "ceil" )) d->type = e_ceil; |
481 |
2/2✓ Branch 1 taken 2 times.
✓ Branch 2 taken 174 times.
|
176 | else if (strmatch(next, "trunc" )) d->type = e_trunc; |
482 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 174 times.
|
174 | else if (strmatch(next, "round" )) d->type = e_round; |
483 |
2/2✓ Branch 1 taken 2 times.
✓ Branch 2 taken 172 times.
|
174 | else if (strmatch(next, "sqrt" )) d->type = e_sqrt; |
484 |
2/2✓ Branch 1 taken 13 times.
✓ Branch 2 taken 159 times.
|
172 | else if (strmatch(next, "not" )) d->type = e_not; |
485 |
2/2✓ Branch 1 taken 3 times.
✓ Branch 2 taken 156 times.
|
159 | else if (strmatch(next, "pow" )) d->type = e_pow; |
486 |
2/2✓ Branch 1 taken 1 times.
✓ Branch 2 taken 155 times.
|
156 | else if (strmatch(next, "print" )) d->type = e_print; |
487 |
2/2✓ Branch 1 taken 107 times.
✓ Branch 2 taken 48 times.
|
155 | else if (strmatch(next, "random")) d->type = e_random; |
488 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 48 times.
|
48 | else if (strmatch(next, "randomi")) d->type = e_randomi; |
489 |
2/2✓ Branch 1 taken 1 times.
✓ Branch 2 taken 47 times.
|
48 | else if (strmatch(next, "hypot" )) d->type = e_hypot; |
490 |
2/2✓ Branch 1 taken 1 times.
✓ Branch 2 taken 46 times.
|
47 | else if (strmatch(next, "gcd" )) d->type = e_gcd; |
491 |
2/2✓ Branch 1 taken 13 times.
✓ Branch 2 taken 33 times.
|
46 | else if (strmatch(next, "if" )) d->type = e_if; |
492 |
2/2✓ Branch 1 taken 4 times.
✓ Branch 2 taken 29 times.
|
33 | else if (strmatch(next, "ifnot" )) d->type = e_ifnot; |
493 |
2/2✓ Branch 1 taken 2 times.
✓ Branch 2 taken 27 times.
|
29 | else if (strmatch(next, "bitand")) d->type = e_bitand; |
494 |
2/2✓ Branch 1 taken 1 times.
✓ Branch 2 taken 26 times.
|
27 | else if (strmatch(next, "bitor" )) d->type = e_bitor; |
495 |
2/2✓ Branch 1 taken 12 times.
✓ Branch 2 taken 14 times.
|
26 | else if (strmatch(next, "between"))d->type = e_between; |
496 |
2/2✓ Branch 1 taken 3 times.
✓ Branch 2 taken 11 times.
|
14 | else if (strmatch(next, "clip" )) d->type = e_clip; |
497 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 11 times.
|
11 | else if (strmatch(next, "atan2" )) d->type = e_atan2; |
498 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 11 times.
|
11 | else if (strmatch(next, "lerp" )) d->type = e_lerp; |
499 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 11 times.
|
11 | else if (strmatch(next, "sgn" )) d->type = e_sgn; |
500 | else { | ||
501 |
3/4✓ Branch 0 taken 4 times.
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
|
11 | for (i=0; p->func1_names && p->func1_names[i]; i++) { |
502 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | if (strmatch(next, p->func1_names[i])) { |
503 | 4 | d->a.func1 = p->funcs1[i]; | |
504 | 4 | d->type = e_func1; | |
505 | 4 | d->const_index = i; | |
506 | 4 | *e = d; | |
507 | 4 | return 0; | |
508 | } | ||
509 | } | ||
510 | |||
511 |
3/4✓ Branch 0 taken 6 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
|
7 | for (i=0; p->func2_names && p->func2_names[i]; i++) { |
512 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | if (strmatch(next, p->func2_names[i])) { |
513 | 6 | d->a.func2 = p->funcs2[i]; | |
514 | 6 | d->type = e_func2; | |
515 | 6 | d->const_index = i; | |
516 | 6 | *e = d; | |
517 | 6 | return 0; | |
518 | } | ||
519 | } | ||
520 | |||
521 | 1 | av_log(p, AV_LOG_ERROR, "Unknown function in '%s'\n", s0); | |
522 | 1 | av_expr_free(d); | |
523 | 1 | return AVERROR(EINVAL); | |
524 | } | ||
525 | |||
526 | 305 | *e = d; | |
527 | 305 | return 0; | |
528 | } | ||
529 | |||
530 | 9378 | static AVExpr *make_eval_expr(int type, int value, AVExpr *p0, AVExpr *p1) | |
531 | { | ||
532 | 9378 | AVExpr *e = av_mallocz(sizeof(AVExpr)); | |
533 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9378 times.
|
9378 | if (!e) |
534 | ✗ | return NULL; | |
535 | 9378 | e->type =type ; | |
536 | 9378 | e->value =value ; | |
537 | 9378 | e->param[0] =p0 ; | |
538 | 9378 | e->param[1] =p1 ; | |
539 | 9378 | return e; | |
540 | } | ||
541 | |||
542 | 97029 | static int parse_pow(AVExpr **e, Parser *p, int *sign) | |
543 | { | ||
544 | 97029 | *sign= (*p->s == '+') - (*p->s == '-'); | |
545 | 97029 | p->s += *sign&1; | |
546 | 97029 | return parse_primary(e, p); | |
547 | } | ||
548 | |||
549 | 97032 | static int parse_dB(AVExpr **e, Parser *p, int *sign) | |
550 | { | ||
551 | /* do not filter out the negative sign when parsing a dB value. | ||
552 | for example, -3dB is not the same as -(3dB) */ | ||
553 |
2/2✓ Branch 0 taken 413 times.
✓ Branch 1 taken 96619 times.
|
97032 | if (*p->s == '-') { |
554 | char *next; | ||
555 | 413 | double av_unused ignored = strtod(p->s, &next); | |
556 |
5/6✓ Branch 0 taken 396 times.
✓ Branch 1 taken 17 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 393 times.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
|
413 | if (next != p->s && next[0] == 'd' && next[1] == 'B') { |
557 | 3 | *sign = 0; | |
558 | 3 | return parse_primary(e, p); | |
559 | } | ||
560 | } | ||
561 | 97029 | return parse_pow(e, p, sign); | |
562 | } | ||
563 | |||
564 | 96825 | static int parse_factor(AVExpr **e, Parser *p) | |
565 | { | ||
566 | int sign, sign2, ret; | ||
567 | AVExpr *e0, *e1, *e2; | ||
568 |
2/2✓ Branch 1 taken 33 times.
✓ Branch 2 taken 96792 times.
|
96825 | if ((ret = parse_dB(&e0, p, &sign)) < 0) |
569 | 33 | return ret; | |
570 |
2/2✓ Branch 0 taken 207 times.
✓ Branch 1 taken 96792 times.
|
193791 | while(p->s[0]=='^'){ |
571 | 207 | e1 = e0; | |
572 | 207 | p->s++; | |
573 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 207 times.
|
207 | if ((ret = parse_dB(&e2, p, &sign2)) < 0) { |
574 | ✗ | av_expr_free(e1); | |
575 | ✗ | return ret; | |
576 | } | ||
577 | 207 | e0 = make_eval_expr(e_pow, 1, e1, e2); | |
578 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 207 times.
|
207 | if (!e0) { |
579 | ✗ | av_expr_free(e1); | |
580 | ✗ | av_expr_free(e2); | |
581 | ✗ | return AVERROR(ENOMEM); | |
582 | } | ||
583 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 207 times.
|
207 | if (e0->param[1]) e0->param[1]->value *= (sign2|1); |
584 | } | ||
585 |
1/2✓ Branch 0 taken 96792 times.
✗ Branch 1 not taken.
|
96792 | if (e0) e0->value *= (sign|1); |
586 | |||
587 | 96792 | *e = e0; | |
588 | 96792 | return 0; | |
589 | } | ||
590 | |||
591 | 91974 | static int parse_term(AVExpr **e, Parser *p) | |
592 | { | ||
593 | int ret; | ||
594 | AVExpr *e0, *e1, *e2; | ||
595 |
2/2✓ Branch 1 taken 31 times.
✓ Branch 2 taken 91943 times.
|
91974 | if ((ret = parse_factor(&e0, p)) < 0) |
596 | 31 | return ret; | |
597 |
4/4✓ Branch 0 taken 4508 times.
✓ Branch 1 taken 92284 times.
✓ Branch 2 taken 343 times.
✓ Branch 3 taken 91941 times.
|
96792 | while (p->s[0]=='*' || p->s[0]=='/') { |
598 | 4851 | int c= *p->s++; | |
599 | 4851 | e1 = e0; | |
600 |
2/2✓ Branch 1 taken 2 times.
✓ Branch 2 taken 4849 times.
|
4851 | if ((ret = parse_factor(&e2, p)) < 0) { |
601 | 2 | av_expr_free(e1); | |
602 | 2 | return ret; | |
603 | } | ||
604 |
2/2✓ Branch 0 taken 4508 times.
✓ Branch 1 taken 341 times.
|
4849 | e0 = make_eval_expr(c == '*' ? e_mul : e_div, 1, e1, e2); |
605 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4849 times.
|
4849 | if (!e0) { |
606 | ✗ | av_expr_free(e1); | |
607 | ✗ | av_expr_free(e2); | |
608 | ✗ | return AVERROR(ENOMEM); | |
609 | } | ||
610 | } | ||
611 | 91941 | *e = e0; | |
612 | 91941 | return 0; | |
613 | } | ||
614 | |||
615 | 87669 | static int parse_subexpr(AVExpr **e, Parser *p) | |
616 | { | ||
617 | int ret; | ||
618 | AVExpr *e0, *e1, *e2; | ||
619 |
2/2✓ Branch 1 taken 32 times.
✓ Branch 2 taken 87637 times.
|
87669 | if ((ret = parse_term(&e0, p)) < 0) |
620 | 32 | return ret; | |
621 |
4/4✓ Branch 0 taken 4125 times.
✓ Branch 1 taken 87816 times.
✓ Branch 2 taken 180 times.
✓ Branch 3 taken 87636 times.
|
91941 | while (*p->s == '+' || *p->s == '-') { |
622 | 4305 | e1 = e0; | |
623 |
2/2✓ Branch 1 taken 1 times.
✓ Branch 2 taken 4304 times.
|
4305 | if ((ret = parse_term(&e2, p)) < 0) { |
624 | 1 | av_expr_free(e1); | |
625 | 1 | return ret; | |
626 | } | ||
627 | 4304 | e0 = make_eval_expr(e_add, 1, e1, e2); | |
628 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4304 times.
|
4304 | if (!e0) { |
629 | ✗ | av_expr_free(e1); | |
630 | ✗ | av_expr_free(e2); | |
631 | ✗ | return AVERROR(ENOMEM); | |
632 | } | ||
633 | }; | ||
634 | |||
635 | 87636 | *e = e0; | |
636 | 87636 | return 0; | |
637 | } | ||
638 | |||
639 | 87651 | static int parse_expr(AVExpr **e, Parser *p) | |
640 | { | ||
641 | int ret; | ||
642 | AVExpr *e0, *e1, *e2; | ||
643 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 87651 times.
|
87651 | if (p->stack_index <= 0) //protect against stack overflows |
644 | ✗ | return AVERROR(EINVAL); | |
645 | 87651 | p->stack_index--; | |
646 | |||
647 |
2/2✓ Branch 1 taken 33 times.
✓ Branch 2 taken 87618 times.
|
87651 | if ((ret = parse_subexpr(&e0, p)) < 0) |
648 | 33 | return ret; | |
649 |
2/2✓ Branch 0 taken 18 times.
✓ Branch 1 taken 87618 times.
|
87636 | while (*p->s == ';') { |
650 | 18 | p->s++; | |
651 | 18 | e1 = e0; | |
652 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 18 times.
|
18 | if ((ret = parse_subexpr(&e2, p)) < 0) { |
653 | ✗ | av_expr_free(e1); | |
654 | ✗ | return ret; | |
655 | } | ||
656 | 18 | e0 = make_eval_expr(e_last, 1, e1, e2); | |
657 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
|
18 | if (!e0) { |
658 | ✗ | av_expr_free(e1); | |
659 | ✗ | av_expr_free(e2); | |
660 | ✗ | return AVERROR(ENOMEM); | |
661 | } | ||
662 | }; | ||
663 | |||
664 | 87618 | p->stack_index++; | |
665 | 87618 | *e = e0; | |
666 | 87618 | return 0; | |
667 | } | ||
668 | |||
669 | 102372 | static int verify_expr(AVExpr *e) | |
670 | { | ||
671 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 102371 times.
|
102372 | if (!e) return 0; |
672 |
6/6✓ Branch 0 taken 92680 times.
✓ Branch 1 taken 208 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 19 times.
✓ Branch 4 taken 15 times.
✓ Branch 5 taken 9448 times.
|
102371 | switch (e->type) { |
673 | 92680 | case e_value: | |
674 | 92680 | case e_const: return 1; | |
675 | 208 | case e_func0: | |
676 | case e_func1: | ||
677 | case e_squish: | ||
678 | case e_ld: | ||
679 | case e_gauss: | ||
680 | case e_isnan: | ||
681 | case e_isinf: | ||
682 | case e_floor: | ||
683 | case e_ceil: | ||
684 | case e_trunc: | ||
685 | case e_round: | ||
686 | case e_sqrt: | ||
687 | case e_not: | ||
688 | case e_random: | ||
689 | case e_sgn: | ||
690 |
3/4✓ Branch 1 taken 208 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 207 times.
✓ Branch 4 taken 1 times.
|
208 | return verify_expr(e->param[0]) && !e->param[1]; |
691 | 1 | case e_print: | |
692 | 1 | return verify_expr(e->param[0]) | |
693 |
2/6✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
|
1 | && (!e->param[1] || verify_expr(e->param[1])); |
694 | 19 | case e_if: | |
695 | case e_ifnot: | ||
696 | case e_taylor: | ||
697 |
1/2✓ Branch 2 taken 19 times.
✗ Branch 3 not taken.
|
38 | return verify_expr(e->param[0]) && verify_expr(e->param[1]) |
698 |
4/6✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 14 times.
✓ Branch 3 taken 5 times.
✓ Branch 5 taken 14 times.
✗ Branch 6 not taken.
|
38 | && (!e->param[2] || verify_expr(e->param[2])); |
699 | 15 | case e_between: | |
700 | case e_clip: | ||
701 | case e_lerp: | ||
702 | case e_randomi: | ||
703 |
1/2✓ Branch 1 taken 15 times.
✗ Branch 2 not taken.
|
30 | return verify_expr(e->param[0]) && |
704 |
3/4✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 14 times.
✓ Branch 4 taken 1 times.
|
30 | verify_expr(e->param[1]) && |
705 | 15 | verify_expr(e->param[2]); | |
706 |
3/6✓ Branch 1 taken 9448 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 9448 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 9448 times.
✗ Branch 7 not taken.
|
9448 | default: return verify_expr(e->param[0]) && verify_expr(e->param[1]) && !e->param[2]; |
707 | } | ||
708 | } | ||
709 | |||
710 | 83204 | int av_expr_parse(AVExpr **expr, const char *s, | |
711 | const char * const *const_names, | ||
712 | const char * const *func1_names, double (* const *funcs1)(void *, double), | ||
713 | const char * const *func2_names, double (* const *funcs2)(void *, double, double), | ||
714 | int log_offset, void *log_ctx) | ||
715 | { | ||
716 | 83204 | Parser p = { 0 }; | |
717 | 83204 | AVExpr *e = NULL; | |
718 | 83204 | char *w = av_malloc(strlen(s) + 1); | |
719 | 83204 | char *wp = w; | |
720 | 83204 | const char *s0 = s; | |
721 | 83204 | int ret = 0; | |
722 | |||
723 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 83204 times.
|
83204 | if (!w) |
724 | ✗ | return AVERROR(ENOMEM); | |
725 | |||
726 |
2/2✓ Branch 0 taken 196440 times.
✓ Branch 1 taken 83204 times.
|
279644 | while (*s) |
727 |
2/2✓ Branch 0 taken 195997 times.
✓ Branch 1 taken 443 times.
|
196440 | if (!av_isspace(*s++)) *wp++ = s[-1]; |
728 | 83204 | *wp++ = 0; | |
729 | |||
730 | 83204 | p.class = &eval_class; | |
731 | 83204 | p.stack_index=100; | |
732 | 83204 | p.s= w; | |
733 | 83204 | p.const_names = const_names; | |
734 | 83204 | p.funcs1 = funcs1; | |
735 | 83204 | p.func1_names = func1_names; | |
736 | 83204 | p.funcs2 = funcs2; | |
737 | 83204 | p.func2_names = func2_names; | |
738 | 83204 | p.log_offset = log_offset; | |
739 | 83204 | p.log_ctx = log_ctx; | |
740 | |||
741 |
2/2✓ Branch 1 taken 29 times.
✓ Branch 2 taken 83175 times.
|
83204 | if ((ret = parse_expr(&e, &p)) < 0) |
742 | 29 | goto end; | |
743 |
2/2✓ Branch 0 taken 5 times.
✓ Branch 1 taken 83170 times.
|
83175 | if (*p.s) { |
744 | 5 | av_log(&p, AV_LOG_ERROR, "Invalid chars '%s' at the end of expression '%s'\n", p.s, s0); | |
745 | 5 | ret = AVERROR(EINVAL); | |
746 | 5 | goto end; | |
747 | } | ||
748 |
2/2✓ Branch 1 taken 2 times.
✓ Branch 2 taken 83168 times.
|
83170 | if (!verify_expr(e)) { |
749 | 2 | ret = AVERROR(EINVAL); | |
750 | 2 | goto end; | |
751 | } | ||
752 | 83168 | e->var= av_mallocz(sizeof(double) *VARS); | |
753 | 83168 | e->prng_state = av_mallocz(sizeof(*e->prng_state) *VARS); | |
754 |
2/4✓ Branch 0 taken 83168 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 83168 times.
|
83168 | if (!e->var || !e->prng_state) { |
755 | ✗ | ret = AVERROR(ENOMEM); | |
756 | ✗ | goto end; | |
757 | } | ||
758 | 83168 | *expr = e; | |
759 | 83168 | e = NULL; | |
760 | 83204 | end: | |
761 | 83204 | av_expr_free(e); | |
762 | 83204 | av_free(w); | |
763 | 83204 | return ret; | |
764 | } | ||
765 | |||
766 | 29826 | static int expr_count(AVExpr *e, unsigned *counter, int size, int type) | |
767 | { | ||
768 | int i; | ||
769 | |||
770 |
3/6✓ Branch 0 taken 29826 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 29826 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 29826 times.
|
29826 | if (!e || !counter || !size) |
771 | ✗ | return AVERROR(EINVAL); | |
772 | |||
773 |
5/6✓ Branch 0 taken 4594 times.
✓ Branch 1 taken 25244 times.
✓ Branch 2 taken 4594 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 12 times.
✓ Branch 5 taken 4582 times.
|
29838 | for (i = 0; e->type != type && i < 3 && e->param[i]; i++) |
774 | 12 | expr_count(e->param[i], counter, size, type); | |
775 | |||
776 |
3/4✓ Branch 0 taken 25244 times.
✓ Branch 1 taken 4582 times.
✓ Branch 2 taken 25244 times.
✗ Branch 3 not taken.
|
29826 | if (e->type == type && e->const_index < size) |
777 | 25244 | counter[e->const_index]++; | |
778 | |||
779 | 29826 | return 0; | |
780 | } | ||
781 | |||
782 | 29814 | int av_expr_count_vars(AVExpr *e, unsigned *counter, int size) | |
783 | { | ||
784 | 29814 | return expr_count(e, counter, size, e_const); | |
785 | } | ||
786 | |||
787 | ✗ | int av_expr_count_func(AVExpr *e, unsigned *counter, int size, int arg) | |
788 | { | ||
789 | ✗ | return expr_count(e, counter, size, ((int[]){e_const, e_func1, e_func2})[arg]); | |
790 | } | ||
791 | |||
792 | 20915933 | double av_expr_eval(AVExpr *e, const double *const_values, void *opaque) | |
793 | { | ||
794 | 20915933 | Parser p = { 0 }; | |
795 | 20915933 | p.var= e->var; | |
796 | 20915933 | p.prng_state= e->prng_state; | |
797 | |||
798 | 20915933 | p.const_values = const_values; | |
799 | 20915933 | p.opaque = opaque; | |
800 | 20915933 | return eval_expr(&p, e); | |
801 | } | ||
802 | |||
803 | 62139 | int av_expr_parse_and_eval(double *d, const char *s, | |
804 | const char * const *const_names, const double *const_values, | ||
805 | const char * const *func1_names, double (* const *funcs1)(void *, double), | ||
806 | const char * const *func2_names, double (* const *funcs2)(void *, double, double), | ||
807 | void *opaque, int log_offset, void *log_ctx) | ||
808 | { | ||
809 | 62139 | AVExpr *e = NULL; | |
810 | 62139 | int ret = av_expr_parse(&e, s, const_names, func1_names, funcs1, func2_names, funcs2, log_offset, log_ctx); | |
811 | |||
812 |
2/2✓ Branch 0 taken 36 times.
✓ Branch 1 taken 62103 times.
|
62139 | if (ret < 0) { |
813 | 36 | *d = NAN; | |
814 | 36 | return ret; | |
815 | } | ||
816 | 62103 | *d = av_expr_eval(e, const_values, opaque); | |
817 | 62103 | av_expr_free(e); | |
818 |
2/2✓ Branch 0 taken 9 times.
✓ Branch 1 taken 62094 times.
|
62103 | return isnan(*d) ? AVERROR(EINVAL) : 0; |
819 | } | ||
820 |