blob: 46f60aad0e7e280311685cc16fcf3de2cc5ce374
1 | /* |
2 | * AVOptions |
3 | * Copyright (c) 2005 Michael Niedermayer <michaelni@gmx.at> |
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 | * AVOptions |
25 | * @author Michael Niedermayer <michaelni@gmx.at> |
26 | */ |
27 | |
28 | #include "avutil.h" |
29 | #include "avstring.h" |
30 | #include "channel_layout.h" |
31 | #include "common.h" |
32 | #include "opt.h" |
33 | #include "eval.h" |
34 | #include "dict.h" |
35 | #include "log.h" |
36 | #include "parseutils.h" |
37 | #include "pixdesc.h" |
38 | #include "mathematics.h" |
39 | #include "samplefmt.h" |
40 | |
41 | #include <float.h> |
42 | |
43 | #if FF_API_FIND_OPT |
44 | //FIXME order them and do a bin search |
45 | const AVOption *av_find_opt(void *v, const char *name, const char *unit, int mask, int flags) |
46 | { |
47 | const AVOption *o = NULL; |
48 | |
49 | while ((o = av_next_option(v, o))) { |
50 | if (!strcmp(o->name, name) && (!unit || (o->unit && !strcmp(o->unit, unit))) && (o->flags & mask) == flags) |
51 | return o; |
52 | } |
53 | return NULL; |
54 | } |
55 | #endif |
56 | |
57 | #if FF_API_OLD_AVOPTIONS |
58 | const AVOption *av_next_option(void *obj, const AVOption *last) |
59 | { |
60 | return av_opt_next(obj, last); |
61 | } |
62 | #endif |
63 | |
64 | const AVOption *av_opt_next(void *obj, const AVOption *last) |
65 | { |
66 | AVClass *class = *(AVClass**)obj; |
67 | if (!last && class && class->option && class->option[0].name) |
68 | return class->option; |
69 | if (last && last[1].name) |
70 | return ++last; |
71 | return NULL; |
72 | } |
73 | |
74 | static int read_number(const AVOption *o, void *dst, double *num, int *den, int64_t *intnum) |
75 | { |
76 | switch (o->type) { |
77 | case AV_OPT_TYPE_FLAGS: *intnum = *(unsigned int*)dst;return 0; |
78 | case AV_OPT_TYPE_PIXEL_FMT: |
79 | case AV_OPT_TYPE_SAMPLE_FMT: |
80 | case AV_OPT_TYPE_INT: *intnum = *(int *)dst;return 0; |
81 | case AV_OPT_TYPE_CHANNEL_LAYOUT: |
82 | case AV_OPT_TYPE_DURATION: |
83 | case AV_OPT_TYPE_INT64: *intnum = *(int64_t *)dst;return 0; |
84 | case AV_OPT_TYPE_FLOAT: *num = *(float *)dst;return 0; |
85 | case AV_OPT_TYPE_DOUBLE: *num = *(double *)dst;return 0; |
86 | case AV_OPT_TYPE_RATIONAL: *intnum = ((AVRational*)dst)->num; |
87 | *den = ((AVRational*)dst)->den; |
88 | return 0; |
89 | case AV_OPT_TYPE_CONST: *num = o->default_val.dbl; return 0; |
90 | } |
91 | return AVERROR(EINVAL); |
92 | } |
93 | |
94 | static int write_number(void *obj, const AVOption *o, void *dst, double num, int den, int64_t intnum) |
95 | { |
96 | if (o->type != AV_OPT_TYPE_FLAGS && |
97 | (o->max * den < num * intnum || o->min * den > num * intnum)) { |
98 | av_log(obj, AV_LOG_ERROR, "Value %f for parameter '%s' out of range [%g - %g]\n", |
99 | num*intnum/den, o->name, o->min, o->max); |
100 | return AVERROR(ERANGE); |
101 | } |
102 | if (o->type == AV_OPT_TYPE_FLAGS) { |
103 | double d = num*intnum/den; |
104 | if (d < -1.5 || d > 0xFFFFFFFF+0.5 || (llrint(d*256) & 255)) { |
105 | av_log(obj, AV_LOG_ERROR, |
106 | "Value %f for parameter '%s' is not a valid set of 32bit integer flags\n", |
107 | num*intnum/den, o->name); |
108 | return AVERROR(ERANGE); |
109 | } |
110 | } |
111 | |
112 | switch (o->type) { |
113 | case AV_OPT_TYPE_FLAGS: |
114 | case AV_OPT_TYPE_PIXEL_FMT: |
115 | case AV_OPT_TYPE_SAMPLE_FMT: |
116 | case AV_OPT_TYPE_INT: *(int *)dst= llrint(num/den)*intnum; break; |
117 | case AV_OPT_TYPE_DURATION: |
118 | case AV_OPT_TYPE_CHANNEL_LAYOUT: |
119 | case AV_OPT_TYPE_INT64: *(int64_t *)dst= llrint(num/den)*intnum; break; |
120 | case AV_OPT_TYPE_FLOAT: *(float *)dst= num*intnum/den; break; |
121 | case AV_OPT_TYPE_DOUBLE:*(double *)dst= num*intnum/den; break; |
122 | case AV_OPT_TYPE_RATIONAL: |
123 | if ((int)num == num) *(AVRational*)dst= (AVRational){num*intnum, den}; |
124 | else *(AVRational*)dst= av_d2q(num*intnum/den, 1<<24); |
125 | break; |
126 | default: |
127 | return AVERROR(EINVAL); |
128 | } |
129 | return 0; |
130 | } |
131 | |
132 | static const double const_values[] = { |
133 | M_PI, |
134 | M_E, |
135 | FF_QP2LAMBDA, |
136 | 0 |
137 | }; |
138 | |
139 | static const char * const const_names[] = { |
140 | "PI", |
141 | "E", |
142 | "QP2LAMBDA", |
143 | 0 |
144 | }; |
145 | |
146 | static int hexchar2int(char c) { |
147 | if (c >= '0' && c <= '9') return c - '0'; |
148 | if (c >= 'a' && c <= 'f') return c - 'a' + 10; |
149 | if (c >= 'A' && c <= 'F') return c - 'A' + 10; |
150 | return -1; |
151 | } |
152 | |
153 | static int set_string_binary(void *obj, const AVOption *o, const char *val, uint8_t **dst) |
154 | { |
155 | int *lendst = (int *)(dst + 1); |
156 | uint8_t *bin, *ptr; |
157 | int len = strlen(val); |
158 | |
159 | av_freep(dst); |
160 | *lendst = 0; |
161 | |
162 | if (len & 1) |
163 | return AVERROR(EINVAL); |
164 | len /= 2; |
165 | |
166 | ptr = bin = av_malloc(len); |
167 | while (*val) { |
168 | int a = hexchar2int(*val++); |
169 | int b = hexchar2int(*val++); |
170 | if (a < 0 || b < 0) { |
171 | av_free(bin); |
172 | return AVERROR(EINVAL); |
173 | } |
174 | *ptr++ = (a << 4) | b; |
175 | } |
176 | *dst = bin; |
177 | *lendst = len; |
178 | |
179 | return 0; |
180 | } |
181 | |
182 | static int set_string(void *obj, const AVOption *o, const char *val, uint8_t **dst) |
183 | { |
184 | av_freep(dst); |
185 | *dst = av_strdup(val); |
186 | return 0; |
187 | } |
188 | |
189 | #define DEFAULT_NUMVAL(opt) ((opt->type == AV_OPT_TYPE_INT64 || \ |
190 | opt->type == AV_OPT_TYPE_CONST || \ |
191 | opt->type == AV_OPT_TYPE_FLAGS || \ |
192 | opt->type == AV_OPT_TYPE_INT) ? \ |
193 | opt->default_val.i64 : opt->default_val.dbl) |
194 | |
195 | static int set_string_number(void *obj, void *target_obj, const AVOption *o, const char *val, void *dst) |
196 | { |
197 | int ret = 0, notfirst = 0; |
198 | for (;;) { |
199 | int i, den = 1; |
200 | char buf[256]; |
201 | int cmd = 0; |
202 | double d, num = 1; |
203 | int64_t intnum = 1; |
204 | |
205 | i = 0; |
206 | if (*val == '+' || *val == '-') { |
207 | if (o->type == AV_OPT_TYPE_FLAGS) |
208 | cmd = *(val++); |
209 | else if (!notfirst) |
210 | buf[i++] = *val; |
211 | } |
212 | |
213 | for (; i < sizeof(buf) - 1 && val[i] && val[i] != '+' && val[i] != '-'; i++) |
214 | buf[i] = val[i]; |
215 | buf[i] = 0; |
216 | |
217 | { |
218 | const AVOption *o_named = av_opt_find(target_obj, buf, o->unit, 0, 0); |
219 | if (o_named && o_named->type == AV_OPT_TYPE_CONST) |
220 | d = DEFAULT_NUMVAL(o_named); |
221 | else if (!strcmp(buf, "default")) d = DEFAULT_NUMVAL(o); |
222 | else if (!strcmp(buf, "max" )) d = o->max; |
223 | else if (!strcmp(buf, "min" )) d = o->min; |
224 | else if (!strcmp(buf, "none" )) d = 0; |
225 | else if (!strcmp(buf, "all" )) d = ~0; |
226 | else { |
227 | int res = av_expr_parse_and_eval(&d, buf, const_names, const_values, NULL, NULL, NULL, NULL, NULL, 0, obj); |
228 | if (res < 0) { |
229 | av_log(obj, AV_LOG_ERROR, "Unable to parse option value \"%s\"\n", val); |
230 | return res; |
231 | } |
232 | } |
233 | } |
234 | if (o->type == AV_OPT_TYPE_FLAGS) { |
235 | read_number(o, dst, NULL, NULL, &intnum); |
236 | if (cmd == '+') d = intnum | (int64_t)d; |
237 | else if (cmd == '-') d = intnum &~(int64_t)d; |
238 | } else { |
239 | read_number(o, dst, &num, &den, &intnum); |
240 | if (cmd == '+') d = notfirst*num*intnum/den + d; |
241 | else if (cmd == '-') d = notfirst*num*intnum/den - d; |
242 | } |
243 | |
244 | if ((ret = write_number(obj, o, dst, d, 1, 1)) < 0) |
245 | return ret; |
246 | val += i; |
247 | if (!*val) |
248 | return 0; |
249 | notfirst = 1; |
250 | } |
251 | |
252 | return 0; |
253 | } |
254 | |
255 | #if FF_API_OLD_AVOPTIONS |
256 | int av_set_string3(void *obj, const char *name, const char *val, int alloc, const AVOption **o_out) |
257 | { |
258 | const AVOption *o = av_opt_find(obj, name, NULL, 0, 0); |
259 | if (o_out) |
260 | *o_out = o; |
261 | return av_opt_set(obj, name, val, 0); |
262 | } |
263 | #endif |
264 | |
265 | int av_opt_set(void *obj, const char *name, const char *val, int search_flags) |
266 | { |
267 | int ret = 0; |
268 | void *dst, *target_obj; |
269 | const AVOption *o = av_opt_find2(obj, name, NULL, 0, search_flags, &target_obj); |
270 | if (!o || !target_obj) |
271 | return AVERROR_OPTION_NOT_FOUND; |
272 | if (!val && (o->type != AV_OPT_TYPE_STRING && |
273 | o->type != AV_OPT_TYPE_PIXEL_FMT && o->type != AV_OPT_TYPE_SAMPLE_FMT && |
274 | o->type != AV_OPT_TYPE_IMAGE_SIZE && o->type != AV_OPT_TYPE_VIDEO_RATE && |
275 | o->type != AV_OPT_TYPE_DURATION && o->type != AV_OPT_TYPE_COLOR && |
276 | o->type != AV_OPT_TYPE_CHANNEL_LAYOUT)) |
277 | return AVERROR(EINVAL); |
278 | |
279 | dst = ((uint8_t*)target_obj) + o->offset; |
280 | switch (o->type) { |
281 | case AV_OPT_TYPE_STRING: return set_string(obj, o, val, dst); |
282 | case AV_OPT_TYPE_BINARY: return set_string_binary(obj, o, val, dst); |
283 | case AV_OPT_TYPE_FLAGS: |
284 | case AV_OPT_TYPE_INT: |
285 | case AV_OPT_TYPE_INT64: |
286 | case AV_OPT_TYPE_FLOAT: |
287 | case AV_OPT_TYPE_DOUBLE: |
288 | case AV_OPT_TYPE_RATIONAL: return set_string_number(obj, target_obj, o, val, dst); |
289 | case AV_OPT_TYPE_IMAGE_SIZE: |
290 | if (!val || !strcmp(val, "none")) { |
291 | *(int *)dst = *((int *)dst + 1) = 0; |
292 | return 0; |
293 | } |
294 | ret = av_parse_video_size(dst, ((int *)dst) + 1, val); |
295 | if (ret < 0) |
296 | av_log(obj, AV_LOG_ERROR, "Unable to parse option value \"%s\" as image size\n", val); |
297 | return ret; |
298 | case AV_OPT_TYPE_VIDEO_RATE: |
299 | if (!val) { |
300 | ret = AVERROR(EINVAL); |
301 | } else { |
302 | ret = av_parse_video_rate(dst, val); |
303 | } |
304 | if (ret < 0) |
305 | av_log(obj, AV_LOG_ERROR, "Unable to parse option value \"%s\" as video rate\n", val); |
306 | return ret; |
307 | case AV_OPT_TYPE_PIXEL_FMT: |
308 | if (!val || !strcmp(val, "none")) { |
309 | ret = AV_PIX_FMT_NONE; |
310 | } else { |
311 | ret = av_get_pix_fmt(val); |
312 | if (ret == AV_PIX_FMT_NONE) { |
313 | char *tail; |
314 | ret = strtol(val, &tail, 0); |
315 | if (*tail || (unsigned)ret >= AV_PIX_FMT_NB) { |
316 | av_log(obj, AV_LOG_ERROR, "Unable to parse option value \"%s\" as pixel format\n", val); |
317 | return AVERROR(EINVAL); |
318 | } |
319 | } |
320 | } |
321 | *(enum AVPixelFormat *)dst = ret; |
322 | return 0; |
323 | case AV_OPT_TYPE_SAMPLE_FMT: |
324 | if (!val || !strcmp(val, "none")) { |
325 | ret = AV_SAMPLE_FMT_NONE; |
326 | } else { |
327 | ret = av_get_sample_fmt(val); |
328 | if (ret == AV_SAMPLE_FMT_NONE) { |
329 | char *tail; |
330 | ret = strtol(val, &tail, 0); |
331 | if (*tail || (unsigned)ret >= AV_SAMPLE_FMT_NB) { |
332 | av_log(obj, AV_LOG_ERROR, "Unable to parse option value \"%s\" as sample format\n", val); |
333 | return AVERROR(EINVAL); |
334 | } |
335 | } |
336 | } |
337 | *(enum AVSampleFormat *)dst = ret; |
338 | return 0; |
339 | case AV_OPT_TYPE_DURATION: |
340 | if (!val) { |
341 | *(int64_t *)dst = 0; |
342 | return 0; |
343 | } else { |
344 | if ((ret = av_parse_time(dst, val, 1)) < 0) |
345 | av_log(obj, AV_LOG_ERROR, "Unable to parse option value \"%s\" as duration\n", val); |
346 | return ret; |
347 | } |
348 | break; |
349 | case AV_OPT_TYPE_COLOR: |
350 | if (!val) { |
351 | return 0; |
352 | } else { |
353 | ret = av_parse_color(dst, val, -1, obj); |
354 | if (ret < 0) |
355 | av_log(obj, AV_LOG_ERROR, "Unable to parse option value \"%s\" as color\n", val); |
356 | return ret; |
357 | } |
358 | break; |
359 | case AV_OPT_TYPE_CHANNEL_LAYOUT: |
360 | if (!val || !strcmp(val, "none")) { |
361 | *(int64_t *)dst = 0; |
362 | } else { |
363 | #if FF_API_GET_CHANNEL_LAYOUT_COMPAT |
364 | int64_t cl = ff_get_channel_layout(val, 0); |
365 | #else |
366 | int64_t cl = av_get_channel_layout(val); |
367 | #endif |
368 | if (!cl) { |
369 | av_log(obj, AV_LOG_ERROR, "Unable to parse option value \"%s\" as channel layout\n", val); |
370 | ret = AVERROR(EINVAL); |
371 | } |
372 | *(int64_t *)dst = cl; |
373 | return ret; |
374 | } |
375 | break; |
376 | } |
377 | |
378 | av_log(obj, AV_LOG_ERROR, "Invalid option type.\n"); |
379 | return AVERROR(EINVAL); |
380 | } |
381 | |
382 | #define OPT_EVAL_NUMBER(name, opttype, vartype)\ |
383 | int av_opt_eval_ ## name(void *obj, const AVOption *o, const char *val, vartype *name ## _out)\ |
384 | {\ |
385 | if (!o || o->type != opttype)\ |
386 | return AVERROR(EINVAL);\ |
387 | return set_string_number(obj, obj, o, val, name ## _out);\ |
388 | } |
389 | |
390 | OPT_EVAL_NUMBER(flags, AV_OPT_TYPE_FLAGS, int) |
391 | OPT_EVAL_NUMBER(int, AV_OPT_TYPE_INT, int) |
392 | OPT_EVAL_NUMBER(int64, AV_OPT_TYPE_INT64, int64_t) |
393 | OPT_EVAL_NUMBER(float, AV_OPT_TYPE_FLOAT, float) |
394 | OPT_EVAL_NUMBER(double, AV_OPT_TYPE_DOUBLE, double) |
395 | OPT_EVAL_NUMBER(q, AV_OPT_TYPE_RATIONAL, AVRational) |
396 | |
397 | static int set_number(void *obj, const char *name, double num, int den, int64_t intnum, |
398 | int search_flags) |
399 | { |
400 | void *dst, *target_obj; |
401 | const AVOption *o = av_opt_find2(obj, name, NULL, 0, search_flags, &target_obj); |
402 | |
403 | if (!o || !target_obj) |
404 | return AVERROR_OPTION_NOT_FOUND; |
405 | |
406 | dst = ((uint8_t*)target_obj) + o->offset; |
407 | return write_number(obj, o, dst, num, den, intnum); |
408 | } |
409 | |
410 | #if FF_API_OLD_AVOPTIONS |
411 | const AVOption *av_set_double(void *obj, const char *name, double n) |
412 | { |
413 | const AVOption *o = av_opt_find(obj, name, NULL, 0, 0); |
414 | if (set_number(obj, name, n, 1, 1, 0) < 0) |
415 | return NULL; |
416 | return o; |
417 | } |
418 | |
419 | const AVOption *av_set_q(void *obj, const char *name, AVRational n) |
420 | { |
421 | const AVOption *o = av_opt_find(obj, name, NULL, 0, 0); |
422 | if (set_number(obj, name, n.num, n.den, 1, 0) < 0) |
423 | return NULL; |
424 | return o; |
425 | } |
426 | |
427 | const AVOption *av_set_int(void *obj, const char *name, int64_t n) |
428 | { |
429 | const AVOption *o = av_opt_find(obj, name, NULL, 0, 0); |
430 | if (set_number(obj, name, 1, 1, n, 0) < 0) |
431 | return NULL; |
432 | return o; |
433 | } |
434 | #endif |
435 | |
436 | int av_opt_set_int(void *obj, const char *name, int64_t val, int search_flags) |
437 | { |
438 | return set_number(obj, name, 1, 1, val, search_flags); |
439 | } |
440 | |
441 | int av_opt_set_double(void *obj, const char *name, double val, int search_flags) |
442 | { |
443 | return set_number(obj, name, val, 1, 1, search_flags); |
444 | } |
445 | |
446 | int av_opt_set_q(void *obj, const char *name, AVRational val, int search_flags) |
447 | { |
448 | return set_number(obj, name, val.num, val.den, 1, search_flags); |
449 | } |
450 | |
451 | int av_opt_set_bin(void *obj, const char *name, const uint8_t *val, int len, int search_flags) |
452 | { |
453 | void *target_obj; |
454 | const AVOption *o = av_opt_find2(obj, name, NULL, 0, search_flags, &target_obj); |
455 | uint8_t *ptr; |
456 | uint8_t **dst; |
457 | int *lendst; |
458 | |
459 | if (!o || !target_obj) |
460 | return AVERROR_OPTION_NOT_FOUND; |
461 | |
462 | if (o->type != AV_OPT_TYPE_BINARY) |
463 | return AVERROR(EINVAL); |
464 | |
465 | ptr = len ? av_malloc(len) : NULL; |
466 | if (len && !ptr) |
467 | return AVERROR(ENOMEM); |
468 | |
469 | dst = (uint8_t **)(((uint8_t *)target_obj) + o->offset); |
470 | lendst = (int *)(dst + 1); |
471 | |
472 | av_free(*dst); |
473 | *dst = ptr; |
474 | *lendst = len; |
475 | if (len) |
476 | memcpy(ptr, val, len); |
477 | |
478 | return 0; |
479 | } |
480 | |
481 | int av_opt_set_image_size(void *obj, const char *name, int w, int h, int search_flags) |
482 | { |
483 | void *target_obj; |
484 | const AVOption *o = av_opt_find2(obj, name, NULL, 0, search_flags, &target_obj); |
485 | |
486 | if (!o || !target_obj) |
487 | return AVERROR_OPTION_NOT_FOUND; |
488 | if (o->type != AV_OPT_TYPE_IMAGE_SIZE) { |
489 | av_log(obj, AV_LOG_ERROR, |
490 | "The value set by option '%s' is not an image size.\n", o->name); |
491 | return AVERROR(EINVAL); |
492 | } |
493 | if (w<0 || h<0) { |
494 | av_log(obj, AV_LOG_ERROR, |
495 | "Invalid negative size value %dx%d for size '%s'\n", w, h, o->name); |
496 | return AVERROR(EINVAL); |
497 | } |
498 | *(int *)(((uint8_t *)target_obj) + o->offset) = w; |
499 | *(int *)(((uint8_t *)target_obj+sizeof(int)) + o->offset) = h; |
500 | return 0; |
501 | } |
502 | |
503 | int av_opt_set_video_rate(void *obj, const char *name, AVRational val, int search_flags) |
504 | { |
505 | void *target_obj; |
506 | const AVOption *o = av_opt_find2(obj, name, NULL, 0, search_flags, &target_obj); |
507 | |
508 | if (!o || !target_obj) |
509 | return AVERROR_OPTION_NOT_FOUND; |
510 | if (o->type != AV_OPT_TYPE_VIDEO_RATE) { |
511 | av_log(obj, AV_LOG_ERROR, |
512 | "The value set by option '%s' is not a video rate.\n", o->name); |
513 | return AVERROR(EINVAL); |
514 | } |
515 | if (val.num <= 0 || val.den <= 0) |
516 | return AVERROR(EINVAL); |
517 | return set_number(obj, name, val.num, val.den, 1, search_flags); |
518 | } |
519 | |
520 | static int set_format(void *obj, const char *name, int fmt, int search_flags, |
521 | enum AVOptionType type, const char *desc, int nb_fmts) |
522 | { |
523 | void *target_obj; |
524 | const AVOption *o = av_opt_find2(obj, name, NULL, 0, |
525 | search_flags, &target_obj); |
526 | int min, max; |
527 | const AVClass *class = *(AVClass **)obj; |
528 | |
529 | if (!o || !target_obj) |
530 | return AVERROR_OPTION_NOT_FOUND; |
531 | if (o->type != type) { |
532 | av_log(obj, AV_LOG_ERROR, |
533 | "The value set by option '%s' is not a %s format", name, desc); |
534 | return AVERROR(EINVAL); |
535 | } |
536 | |
537 | #if LIBAVUTIL_VERSION_MAJOR < 53 |
538 | if (class->version && class->version < AV_VERSION_INT(52, 11, 100)) { |
539 | min = -1; |
540 | max = nb_fmts-1; |
541 | } else |
542 | #endif |
543 | { |
544 | min = FFMIN(o->min, -1); |
545 | max = FFMAX(o->max, nb_fmts-1); |
546 | } |
547 | if (fmt < min || fmt > max) { |
548 | av_log(obj, AV_LOG_ERROR, |
549 | "Value %d for parameter '%s' out of %s format range [%d - %d]\n", |
550 | fmt, name, desc, min, max); |
551 | return AVERROR(ERANGE); |
552 | } |
553 | *(int *)(((uint8_t *)target_obj) + o->offset) = fmt; |
554 | return 0; |
555 | } |
556 | |
557 | int av_opt_set_pixel_fmt(void *obj, const char *name, enum AVPixelFormat fmt, int search_flags) |
558 | { |
559 | return set_format(obj, name, fmt, search_flags, AV_OPT_TYPE_PIXEL_FMT, "pixel", AV_PIX_FMT_NB); |
560 | } |
561 | |
562 | int av_opt_set_sample_fmt(void *obj, const char *name, enum AVSampleFormat fmt, int search_flags) |
563 | { |
564 | return set_format(obj, name, fmt, search_flags, AV_OPT_TYPE_SAMPLE_FMT, "sample", AV_SAMPLE_FMT_NB); |
565 | } |
566 | |
567 | int av_opt_set_channel_layout(void *obj, const char *name, int64_t cl, int search_flags) |
568 | { |
569 | void *target_obj; |
570 | const AVOption *o = av_opt_find2(obj, name, NULL, 0, search_flags, &target_obj); |
571 | |
572 | if (!o || !target_obj) |
573 | return AVERROR_OPTION_NOT_FOUND; |
574 | if (o->type != AV_OPT_TYPE_CHANNEL_LAYOUT) { |
575 | av_log(obj, AV_LOG_ERROR, |
576 | "The value set by option '%s' is not a channel layout.\n", o->name); |
577 | return AVERROR(EINVAL); |
578 | } |
579 | *(int *)(((int64_t *)target_obj) + o->offset) = cl; |
580 | return 0; |
581 | } |
582 | |
583 | #if FF_API_OLD_AVOPTIONS |
584 | /** |
585 | * |
586 | * @param buf a buffer which is used for returning non string values as strings, can be NULL |
587 | * @param buf_len allocated length in bytes of buf |
588 | */ |
589 | const char *av_get_string(void *obj, const char *name, const AVOption **o_out, char *buf, int buf_len) |
590 | { |
591 | const AVOption *o = av_opt_find(obj, name, NULL, 0, AV_OPT_SEARCH_CHILDREN); |
592 | void *dst; |
593 | uint8_t *bin; |
594 | int len, i; |
595 | if (!o) |
596 | return NULL; |
597 | if (o->type != AV_OPT_TYPE_STRING && (!buf || !buf_len)) |
598 | return NULL; |
599 | |
600 | dst= ((uint8_t*)obj) + o->offset; |
601 | if (o_out) *o_out= o; |
602 | |
603 | switch (o->type) { |
604 | case AV_OPT_TYPE_FLAGS: snprintf(buf, buf_len, "0x%08X",*(int *)dst);break; |
605 | case AV_OPT_TYPE_INT: snprintf(buf, buf_len, "%d" , *(int *)dst);break; |
606 | case AV_OPT_TYPE_INT64: snprintf(buf, buf_len, "%"PRId64, *(int64_t*)dst);break; |
607 | case AV_OPT_TYPE_FLOAT: snprintf(buf, buf_len, "%f" , *(float *)dst);break; |
608 | case AV_OPT_TYPE_DOUBLE: snprintf(buf, buf_len, "%f" , *(double *)dst);break; |
609 | case AV_OPT_TYPE_RATIONAL: snprintf(buf, buf_len, "%d/%d", ((AVRational*)dst)->num, ((AVRational*)dst)->den);break; |
610 | case AV_OPT_TYPE_CONST: snprintf(buf, buf_len, "%f" , o->default_val.dbl);break; |
611 | case AV_OPT_TYPE_STRING: return *(void**)dst; |
612 | case AV_OPT_TYPE_BINARY: |
613 | len = *(int*)(((uint8_t *)dst) + sizeof(uint8_t *)); |
614 | if (len >= (buf_len + 1)/2) return NULL; |
615 | bin = *(uint8_t**)dst; |
616 | for (i = 0; i < len; i++) snprintf(buf + i*2, 3, "%02X", bin[i]); |
617 | break; |
618 | default: return NULL; |
619 | } |
620 | return buf; |
621 | } |
622 | #endif |
623 | |
624 | int av_opt_get(void *obj, const char *name, int search_flags, uint8_t **out_val) |
625 | { |
626 | void *dst, *target_obj; |
627 | const AVOption *o = av_opt_find2(obj, name, NULL, 0, search_flags, &target_obj); |
628 | uint8_t *bin, buf[128]; |
629 | int len, i, ret; |
630 | int64_t i64; |
631 | |
632 | if (!o || !target_obj || (o->offset<=0 && o->type != AV_OPT_TYPE_CONST)) |
633 | return AVERROR_OPTION_NOT_FOUND; |
634 | |
635 | dst = (uint8_t*)target_obj + o->offset; |
636 | |
637 | buf[0] = 0; |
638 | switch (o->type) { |
639 | case AV_OPT_TYPE_FLAGS: ret = snprintf(buf, sizeof(buf), "0x%08X", *(int *)dst);break; |
640 | case AV_OPT_TYPE_INT: ret = snprintf(buf, sizeof(buf), "%d" , *(int *)dst);break; |
641 | case AV_OPT_TYPE_INT64: ret = snprintf(buf, sizeof(buf), "%"PRId64, *(int64_t*)dst);break; |
642 | case AV_OPT_TYPE_FLOAT: ret = snprintf(buf, sizeof(buf), "%f" , *(float *)dst);break; |
643 | case AV_OPT_TYPE_DOUBLE: ret = snprintf(buf, sizeof(buf), "%f" , *(double *)dst);break; |
644 | case AV_OPT_TYPE_VIDEO_RATE: |
645 | case AV_OPT_TYPE_RATIONAL: ret = snprintf(buf, sizeof(buf), "%d/%d", ((AVRational*)dst)->num, ((AVRational*)dst)->den);break; |
646 | case AV_OPT_TYPE_CONST: ret = snprintf(buf, sizeof(buf), "%f" , o->default_val.dbl);break; |
647 | case AV_OPT_TYPE_STRING: |
648 | if (*(uint8_t**)dst) |
649 | *out_val = av_strdup(*(uint8_t**)dst); |
650 | else |
651 | *out_val = av_strdup(""); |
652 | return 0; |
653 | case AV_OPT_TYPE_BINARY: |
654 | len = *(int*)(((uint8_t *)dst) + sizeof(uint8_t *)); |
655 | if ((uint64_t)len*2 + 1 > INT_MAX) |
656 | return AVERROR(EINVAL); |
657 | if (!(*out_val = av_malloc(len*2 + 1))) |
658 | return AVERROR(ENOMEM); |
659 | bin = *(uint8_t**)dst; |
660 | for (i = 0; i < len; i++) |
661 | snprintf(*out_val + i*2, 3, "%02X", bin[i]); |
662 | return 0; |
663 | case AV_OPT_TYPE_IMAGE_SIZE: |
664 | ret = snprintf(buf, sizeof(buf), "%dx%d", ((int *)dst)[0], ((int *)dst)[1]); |
665 | break; |
666 | case AV_OPT_TYPE_PIXEL_FMT: |
667 | ret = snprintf(buf, sizeof(buf), "%s", (char *)av_x_if_null(av_get_pix_fmt_name(*(enum AVPixelFormat *)dst), "none")); |
668 | break; |
669 | case AV_OPT_TYPE_SAMPLE_FMT: |
670 | ret = snprintf(buf, sizeof(buf), "%s", (char *)av_x_if_null(av_get_sample_fmt_name(*(enum AVSampleFormat *)dst), "none")); |
671 | break; |
672 | case AV_OPT_TYPE_DURATION: |
673 | i64 = *(int64_t *)dst; |
674 | ret = snprintf(buf, sizeof(buf), "%"PRIi64"d:%02d:%02d.%06d", |
675 | i64 / 3600000000, (int)((i64 / 60000000) % 60), |
676 | (int)((i64 / 1000000) % 60), (int)(i64 % 1000000)); |
677 | break; |
678 | case AV_OPT_TYPE_COLOR: |
679 | ret = snprintf(buf, sizeof(buf), "0x%02x%02x%02x%02x", ((int *)dst)[0], ((int *)dst)[1], ((int *)dst)[2], ((int *)dst)[3]); |
680 | break; |
681 | case AV_OPT_TYPE_CHANNEL_LAYOUT: |
682 | i64 = *(int64_t *)dst; |
683 | ret = snprintf(buf, sizeof(buf), "0x%"PRIx64, i64); |
684 | break; |
685 | default: |
686 | return AVERROR(EINVAL); |
687 | } |
688 | |
689 | if (ret >= sizeof(buf)) |
690 | return AVERROR(EINVAL); |
691 | *out_val = av_strdup(buf); |
692 | return 0; |
693 | } |
694 | |
695 | static int get_number(void *obj, const char *name, const AVOption **o_out, double *num, int *den, int64_t *intnum, |
696 | int search_flags) |
697 | { |
698 | void *dst, *target_obj; |
699 | const AVOption *o = av_opt_find2(obj, name, NULL, 0, search_flags, &target_obj); |
700 | if (!o || !target_obj) |
701 | goto error; |
702 | |
703 | dst = ((uint8_t*)target_obj) + o->offset; |
704 | |
705 | if (o_out) *o_out= o; |
706 | |
707 | return read_number(o, dst, num, den, intnum); |
708 | |
709 | error: |
710 | *den=*intnum=0; |
711 | return -1; |
712 | } |
713 | |
714 | #if FF_API_OLD_AVOPTIONS |
715 | double av_get_double(void *obj, const char *name, const AVOption **o_out) |
716 | { |
717 | int64_t intnum=1; |
718 | double num=1; |
719 | int den=1; |
720 | |
721 | if (get_number(obj, name, o_out, &num, &den, &intnum, 0) < 0) |
722 | return NAN; |
723 | return num*intnum/den; |
724 | } |
725 | |
726 | AVRational av_get_q(void *obj, const char *name, const AVOption **o_out) |
727 | { |
728 | int64_t intnum=1; |
729 | double num=1; |
730 | int den=1; |
731 | |
732 | if (get_number(obj, name, o_out, &num, &den, &intnum, 0) < 0) |
733 | return (AVRational){0, 0}; |
734 | if (num == 1.0 && (int)intnum == intnum) |
735 | return (AVRational){intnum, den}; |
736 | else |
737 | return av_d2q(num*intnum/den, 1<<24); |
738 | } |
739 | |
740 | int64_t av_get_int(void *obj, const char *name, const AVOption **o_out) |
741 | { |
742 | int64_t intnum=1; |
743 | double num=1; |
744 | int den=1; |
745 | |
746 | if (get_number(obj, name, o_out, &num, &den, &intnum, 0) < 0) |
747 | return -1; |
748 | return num*intnum/den; |
749 | } |
750 | #endif |
751 | |
752 | int av_opt_get_int(void *obj, const char *name, int search_flags, int64_t *out_val) |
753 | { |
754 | int64_t intnum = 1; |
755 | double num = 1; |
756 | int ret, den = 1; |
757 | |
758 | if ((ret = get_number(obj, name, NULL, &num, &den, &intnum, search_flags)) < 0) |
759 | return ret; |
760 | *out_val = num*intnum/den; |
761 | return 0; |
762 | } |
763 | |
764 | int av_opt_get_double(void *obj, const char *name, int search_flags, double *out_val) |
765 | { |
766 | int64_t intnum = 1; |
767 | double num = 1; |
768 | int ret, den = 1; |
769 | |
770 | if ((ret = get_number(obj, name, NULL, &num, &den, &intnum, search_flags)) < 0) |
771 | return ret; |
772 | *out_val = num*intnum/den; |
773 | return 0; |
774 | } |
775 | |
776 | int av_opt_get_q(void *obj, const char *name, int search_flags, AVRational *out_val) |
777 | { |
778 | int64_t intnum = 1; |
779 | double num = 1; |
780 | int ret, den = 1; |
781 | |
782 | if ((ret = get_number(obj, name, NULL, &num, &den, &intnum, search_flags)) < 0) |
783 | return ret; |
784 | |
785 | if (num == 1.0 && (int)intnum == intnum) |
786 | *out_val = (AVRational){intnum, den}; |
787 | else |
788 | *out_val = av_d2q(num*intnum/den, 1<<24); |
789 | return 0; |
790 | } |
791 | |
792 | int av_opt_get_image_size(void *obj, const char *name, int search_flags, int *w_out, int *h_out) |
793 | { |
794 | void *dst, *target_obj; |
795 | const AVOption *o = av_opt_find2(obj, name, NULL, 0, search_flags, &target_obj); |
796 | if (!o || !target_obj) |
797 | return AVERROR_OPTION_NOT_FOUND; |
798 | if (o->type != AV_OPT_TYPE_IMAGE_SIZE) { |
799 | av_log(obj, AV_LOG_ERROR, |
800 | "The value for option '%s' is not an image size.\n", name); |
801 | return AVERROR(EINVAL); |
802 | } |
803 | |
804 | dst = ((uint8_t*)target_obj) + o->offset; |
805 | if (w_out) *w_out = *(int *)dst; |
806 | if (h_out) *h_out = *((int *)dst+1); |
807 | return 0; |
808 | } |
809 | |
810 | int av_opt_get_video_rate(void *obj, const char *name, int search_flags, AVRational *out_val) |
811 | { |
812 | int64_t intnum = 1; |
813 | double num = 1; |
814 | int ret, den = 1; |
815 | |
816 | if ((ret = get_number(obj, name, NULL, &num, &den, &intnum, search_flags)) < 0) |
817 | return ret; |
818 | |
819 | if (num == 1.0 && (int)intnum == intnum) |
820 | *out_val = (AVRational){intnum, den}; |
821 | else |
822 | *out_val = av_d2q(num*intnum/den, 1<<24); |
823 | return 0; |
824 | } |
825 | |
826 | static int get_format(void *obj, const char *name, int search_flags, int *out_fmt, |
827 | enum AVOptionType type, const char *desc) |
828 | { |
829 | void *dst, *target_obj; |
830 | const AVOption *o = av_opt_find2(obj, name, NULL, 0, search_flags, &target_obj); |
831 | if (!o || !target_obj) |
832 | return AVERROR_OPTION_NOT_FOUND; |
833 | if (o->type != type) { |
834 | av_log(obj, AV_LOG_ERROR, |
835 | "The value for option '%s' is not a %s format.\n", desc, name); |
836 | return AVERROR(EINVAL); |
837 | } |
838 | |
839 | dst = ((uint8_t*)target_obj) + o->offset; |
840 | *out_fmt = *(int *)dst; |
841 | return 0; |
842 | } |
843 | |
844 | int av_opt_get_pixel_fmt(void *obj, const char *name, int search_flags, enum AVPixelFormat *out_fmt) |
845 | { |
846 | return get_format(obj, name, search_flags, out_fmt, AV_OPT_TYPE_PIXEL_FMT, "pixel"); |
847 | } |
848 | |
849 | int av_opt_get_sample_fmt(void *obj, const char *name, int search_flags, enum AVSampleFormat *out_fmt) |
850 | { |
851 | return get_format(obj, name, search_flags, out_fmt, AV_OPT_TYPE_SAMPLE_FMT, "sample"); |
852 | } |
853 | |
854 | int av_opt_get_channel_layout(void *obj, const char *name, int search_flags, int64_t *cl) |
855 | { |
856 | void *dst, *target_obj; |
857 | const AVOption *o = av_opt_find2(obj, name, NULL, 0, search_flags, &target_obj); |
858 | if (!o || !target_obj) |
859 | return AVERROR_OPTION_NOT_FOUND; |
860 | if (o->type != AV_OPT_TYPE_CHANNEL_LAYOUT) { |
861 | av_log(obj, AV_LOG_ERROR, |
862 | "The value for option '%s' is not a channel layout.\n", name); |
863 | return AVERROR(EINVAL); |
864 | } |
865 | |
866 | dst = ((uint8_t*)target_obj) + o->offset; |
867 | *cl = *(int64_t *)dst; |
868 | return 0; |
869 | } |
870 | |
871 | int av_opt_flag_is_set(void *obj, const char *field_name, const char *flag_name) |
872 | { |
873 | const AVOption *field = av_opt_find(obj, field_name, NULL, 0, 0); |
874 | const AVOption *flag = av_opt_find(obj, flag_name, |
875 | field ? field->unit : NULL, 0, 0); |
876 | int64_t res; |
877 | |
878 | if (!field || !flag || flag->type != AV_OPT_TYPE_CONST || |
879 | av_opt_get_int(obj, field_name, 0, &res) < 0) |
880 | return 0; |
881 | return res & flag->default_val.i64; |
882 | } |
883 | |
884 | static void log_value(void *av_log_obj, int level, double d) |
885 | { |
886 | if (d == INT_MAX) { |
887 | av_log(av_log_obj, level, "INT_MAX"); |
888 | } else if (d == INT_MIN) { |
889 | av_log(av_log_obj, level, "INT_MIN"); |
890 | } else if (d == (double)INT64_MAX) { |
891 | av_log(av_log_obj, level, "I64_MAX"); |
892 | } else if (d == INT64_MIN) { |
893 | av_log(av_log_obj, level, "I64_MIN"); |
894 | } else if (d == FLT_MAX) { |
895 | av_log(av_log_obj, level, "FLT_MAX"); |
896 | } else if (d == FLT_MIN) { |
897 | av_log(av_log_obj, level, "FLT_MIN"); |
898 | } else { |
899 | av_log(av_log_obj, level, "%g", d); |
900 | } |
901 | } |
902 | |
903 | static void opt_list(void *obj, void *av_log_obj, const char *unit, |
904 | int req_flags, int rej_flags) |
905 | { |
906 | const AVOption *opt=NULL; |
907 | AVOptionRanges *r; |
908 | int i; |
909 | |
910 | while ((opt = av_opt_next(obj, opt))) { |
911 | if (!(opt->flags & req_flags) || (opt->flags & rej_flags)) |
912 | continue; |
913 | |
914 | /* Don't print CONST's on level one. |
915 | * Don't print anything but CONST's on level two. |
916 | * Only print items from the requested unit. |
917 | */ |
918 | if (!unit && opt->type==AV_OPT_TYPE_CONST) |
919 | continue; |
920 | else if (unit && opt->type!=AV_OPT_TYPE_CONST) |
921 | continue; |
922 | else if (unit && opt->type==AV_OPT_TYPE_CONST && strcmp(unit, opt->unit)) |
923 | continue; |
924 | else if (unit && opt->type == AV_OPT_TYPE_CONST) |
925 | av_log(av_log_obj, AV_LOG_INFO, " %-15s ", opt->name); |
926 | else |
927 | av_log(av_log_obj, AV_LOG_INFO, " %s%-17s ", |
928 | (opt->flags & AV_OPT_FLAG_FILTERING_PARAM) ? "" : "-", |
929 | opt->name); |
930 | |
931 | switch (opt->type) { |
932 | case AV_OPT_TYPE_FLAGS: |
933 | av_log(av_log_obj, AV_LOG_INFO, "%-12s ", "<flags>"); |
934 | break; |
935 | case AV_OPT_TYPE_INT: |
936 | av_log(av_log_obj, AV_LOG_INFO, "%-12s ", "<int>"); |
937 | break; |
938 | case AV_OPT_TYPE_INT64: |
939 | av_log(av_log_obj, AV_LOG_INFO, "%-12s ", "<int64>"); |
940 | break; |
941 | case AV_OPT_TYPE_DOUBLE: |
942 | av_log(av_log_obj, AV_LOG_INFO, "%-12s ", "<double>"); |
943 | break; |
944 | case AV_OPT_TYPE_FLOAT: |
945 | av_log(av_log_obj, AV_LOG_INFO, "%-12s ", "<float>"); |
946 | break; |
947 | case AV_OPT_TYPE_STRING: |
948 | av_log(av_log_obj, AV_LOG_INFO, "%-12s ", "<string>"); |
949 | break; |
950 | case AV_OPT_TYPE_RATIONAL: |
951 | av_log(av_log_obj, AV_LOG_INFO, "%-12s ", "<rational>"); |
952 | break; |
953 | case AV_OPT_TYPE_BINARY: |
954 | av_log(av_log_obj, AV_LOG_INFO, "%-12s ", "<binary>"); |
955 | break; |
956 | case AV_OPT_TYPE_IMAGE_SIZE: |
957 | av_log(av_log_obj, AV_LOG_INFO, "%-12s ", "<image_size>"); |
958 | break; |
959 | case AV_OPT_TYPE_VIDEO_RATE: |
960 | av_log(av_log_obj, AV_LOG_INFO, "%-12s ", "<video_rate>"); |
961 | break; |
962 | case AV_OPT_TYPE_PIXEL_FMT: |
963 | av_log(av_log_obj, AV_LOG_INFO, "%-12s ", "<pix_fmt>"); |
964 | break; |
965 | case AV_OPT_TYPE_SAMPLE_FMT: |
966 | av_log(av_log_obj, AV_LOG_INFO, "%-12s ", "<sample_fmt>"); |
967 | break; |
968 | case AV_OPT_TYPE_DURATION: |
969 | av_log(av_log_obj, AV_LOG_INFO, "%-12s ", "<duration>"); |
970 | break; |
971 | case AV_OPT_TYPE_COLOR: |
972 | av_log(av_log_obj, AV_LOG_INFO, "%-12s ", "<color>"); |
973 | break; |
974 | case AV_OPT_TYPE_CHANNEL_LAYOUT: |
975 | av_log(av_log_obj, AV_LOG_INFO, "%-12s ", "<channel_layout>"); |
976 | break; |
977 | case AV_OPT_TYPE_CONST: |
978 | default: |
979 | av_log(av_log_obj, AV_LOG_INFO, "%-12s ", ""); |
980 | break; |
981 | } |
982 | av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_ENCODING_PARAM) ? 'E' : '.'); |
983 | av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_DECODING_PARAM) ? 'D' : '.'); |
984 | av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_FILTERING_PARAM)? 'F' : '.'); |
985 | av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_VIDEO_PARAM ) ? 'V' : '.'); |
986 | av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_AUDIO_PARAM ) ? 'A' : '.'); |
987 | av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_SUBTITLE_PARAM) ? 'S' : '.'); |
988 | |
989 | if (opt->help) |
990 | av_log(av_log_obj, AV_LOG_INFO, " %s", opt->help); |
991 | |
992 | if (av_opt_query_ranges(&r, obj, opt->name, AV_OPT_SEARCH_FAKE_OBJ) >= 0) { |
993 | switch (opt->type) { |
994 | case AV_OPT_TYPE_INT: |
995 | case AV_OPT_TYPE_INT64: |
996 | case AV_OPT_TYPE_DOUBLE: |
997 | case AV_OPT_TYPE_FLOAT: |
998 | case AV_OPT_TYPE_RATIONAL: |
999 | for (i = 0; i < r->nb_ranges; i++) { |
1000 | av_log(av_log_obj, AV_LOG_INFO, " (from "); |
1001 | log_value(av_log_obj, AV_LOG_INFO, r->range[i]->value_min); |
1002 | av_log(av_log_obj, AV_LOG_INFO, " to "); |
1003 | log_value(av_log_obj, AV_LOG_INFO, r->range[i]->value_max); |
1004 | av_log(av_log_obj, AV_LOG_INFO, ")"); |
1005 | } |
1006 | break; |
1007 | } |
1008 | av_opt_freep_ranges(&r); |
1009 | } |
1010 | |
1011 | if (opt->type != AV_OPT_TYPE_CONST && |
1012 | opt->type != AV_OPT_TYPE_BINARY && |
1013 | !((opt->type == AV_OPT_TYPE_COLOR || |
1014 | opt->type == AV_OPT_TYPE_IMAGE_SIZE || |
1015 | opt->type == AV_OPT_TYPE_STRING || |
1016 | opt->type == AV_OPT_TYPE_VIDEO_RATE) && |
1017 | !opt->default_val.str)) { |
1018 | av_log(av_log_obj, AV_LOG_INFO, " (default "); |
1019 | switch (opt->type) { |
1020 | case AV_OPT_TYPE_FLAGS: |
1021 | av_log(av_log_obj, AV_LOG_INFO, "%"PRIX64, opt->default_val.i64); |
1022 | break; |
1023 | case AV_OPT_TYPE_DURATION: |
1024 | case AV_OPT_TYPE_INT: |
1025 | case AV_OPT_TYPE_INT64: |
1026 | log_value(av_log_obj, AV_LOG_INFO, opt->default_val.i64); |
1027 | break; |
1028 | case AV_OPT_TYPE_DOUBLE: |
1029 | case AV_OPT_TYPE_FLOAT: |
1030 | log_value(av_log_obj, AV_LOG_INFO, opt->default_val.dbl); |
1031 | break; |
1032 | case AV_OPT_TYPE_RATIONAL: { |
1033 | AVRational q = av_d2q(opt->default_val.dbl, INT_MAX); |
1034 | av_log(av_log_obj, AV_LOG_INFO, "%d/%d", q.num, q.den); } |
1035 | break; |
1036 | case AV_OPT_TYPE_PIXEL_FMT: |
1037 | av_log(av_log_obj, AV_LOG_INFO, "%s", (char *)av_x_if_null(av_get_pix_fmt_name(opt->default_val.i64), "none")); |
1038 | break; |
1039 | case AV_OPT_TYPE_SAMPLE_FMT: |
1040 | av_log(av_log_obj, AV_LOG_INFO, "%s", (char *)av_x_if_null(av_get_sample_fmt_name(opt->default_val.i64), "none")); |
1041 | break; |
1042 | case AV_OPT_TYPE_COLOR: |
1043 | case AV_OPT_TYPE_IMAGE_SIZE: |
1044 | case AV_OPT_TYPE_STRING: |
1045 | case AV_OPT_TYPE_VIDEO_RATE: |
1046 | av_log(av_log_obj, AV_LOG_INFO, "\"%s\"", opt->default_val.str); |
1047 | break; |
1048 | case AV_OPT_TYPE_CHANNEL_LAYOUT: |
1049 | av_log(av_log_obj, AV_LOG_INFO, "0x%"PRIx64, opt->default_val.i64); |
1050 | break; |
1051 | } |
1052 | av_log(av_log_obj, AV_LOG_INFO, ")"); |
1053 | } |
1054 | |
1055 | av_log(av_log_obj, AV_LOG_INFO, "\n"); |
1056 | if (opt->unit && opt->type != AV_OPT_TYPE_CONST) { |
1057 | opt_list(obj, av_log_obj, opt->unit, req_flags, rej_flags); |
1058 | } |
1059 | } |
1060 | } |
1061 | |
1062 | int av_opt_show2(void *obj, void *av_log_obj, int req_flags, int rej_flags) |
1063 | { |
1064 | if (!obj) |
1065 | return -1; |
1066 | |
1067 | av_log(av_log_obj, AV_LOG_INFO, "%s AVOptions:\n", (*(AVClass**)obj)->class_name); |
1068 | |
1069 | opt_list(obj, av_log_obj, NULL, req_flags, rej_flags); |
1070 | |
1071 | return 0; |
1072 | } |
1073 | |
1074 | void av_opt_set_defaults(void *s) |
1075 | { |
1076 | #if FF_API_OLD_AVOPTIONS |
1077 | av_opt_set_defaults2(s, 0, 0); |
1078 | } |
1079 | |
1080 | void av_opt_set_defaults2(void *s, int mask, int flags) |
1081 | { |
1082 | #endif |
1083 | const AVClass *class = *(AVClass **)s; |
1084 | const AVOption *opt = NULL; |
1085 | while ((opt = av_opt_next(s, opt)) != NULL) { |
1086 | #if FF_API_OLD_AVOPTIONS |
1087 | if ((opt->flags & mask) != flags) |
1088 | continue; |
1089 | #endif |
1090 | switch (opt->type) { |
1091 | case AV_OPT_TYPE_CONST: |
1092 | /* Nothing to be done here */ |
1093 | break; |
1094 | case AV_OPT_TYPE_FLAGS: |
1095 | case AV_OPT_TYPE_INT: |
1096 | case AV_OPT_TYPE_INT64: |
1097 | case AV_OPT_TYPE_DURATION: |
1098 | case AV_OPT_TYPE_CHANNEL_LAYOUT: |
1099 | av_opt_set_int(s, opt->name, opt->default_val.i64, 0); |
1100 | break; |
1101 | case AV_OPT_TYPE_DOUBLE: |
1102 | case AV_OPT_TYPE_FLOAT: { |
1103 | double val; |
1104 | val = opt->default_val.dbl; |
1105 | av_opt_set_double(s, opt->name, val, 0); |
1106 | } |
1107 | break; |
1108 | case AV_OPT_TYPE_RATIONAL: { |
1109 | AVRational val; |
1110 | val = av_d2q(opt->default_val.dbl, INT_MAX); |
1111 | av_opt_set_q(s, opt->name, val, 0); |
1112 | } |
1113 | break; |
1114 | case AV_OPT_TYPE_COLOR: |
1115 | case AV_OPT_TYPE_STRING: |
1116 | case AV_OPT_TYPE_IMAGE_SIZE: |
1117 | case AV_OPT_TYPE_VIDEO_RATE: |
1118 | av_opt_set(s, opt->name, opt->default_val.str, 0); |
1119 | break; |
1120 | case AV_OPT_TYPE_PIXEL_FMT: |
1121 | #if LIBAVUTIL_VERSION_MAJOR < 53 |
1122 | if (class->version && class->version < AV_VERSION_INT(52, 10, 100)) |
1123 | av_opt_set(s, opt->name, opt->default_val.str, 0); |
1124 | else |
1125 | #endif |
1126 | av_opt_set_pixel_fmt(s, opt->name, opt->default_val.i64, 0); |
1127 | break; |
1128 | case AV_OPT_TYPE_SAMPLE_FMT: |
1129 | #if LIBAVUTIL_VERSION_MAJOR < 53 |
1130 | if (class->version && class->version < AV_VERSION_INT(52, 10, 100)) |
1131 | av_opt_set(s, opt->name, opt->default_val.str, 0); |
1132 | else |
1133 | #endif |
1134 | av_opt_set_sample_fmt(s, opt->name, opt->default_val.i64, 0); |
1135 | break; |
1136 | case AV_OPT_TYPE_BINARY: |
1137 | /* Cannot set default for binary */ |
1138 | break; |
1139 | default: |
1140 | av_log(s, AV_LOG_DEBUG, "AVOption type %d of option %s not implemented yet\n", opt->type, opt->name); |
1141 | } |
1142 | } |
1143 | } |
1144 | |
1145 | /** |
1146 | * Store the value in the field in ctx that is named like key. |
1147 | * ctx must be an AVClass context, storing is done using AVOptions. |
1148 | * |
1149 | * @param buf the string to parse, buf will be updated to point at the |
1150 | * separator just after the parsed key/value pair |
1151 | * @param key_val_sep a 0-terminated list of characters used to |
1152 | * separate key from value |
1153 | * @param pairs_sep a 0-terminated list of characters used to separate |
1154 | * two pairs from each other |
1155 | * @return 0 if the key/value pair has been successfully parsed and |
1156 | * set, or a negative value corresponding to an AVERROR code in case |
1157 | * of error: |
1158 | * AVERROR(EINVAL) if the key/value pair cannot be parsed, |
1159 | * the error code issued by av_opt_set() if the key/value pair |
1160 | * cannot be set |
1161 | */ |
1162 | static int parse_key_value_pair(void *ctx, const char **buf, |
1163 | const char *key_val_sep, const char *pairs_sep) |
1164 | { |
1165 | char *key = av_get_token(buf, key_val_sep); |
1166 | char *val; |
1167 | int ret; |
1168 | |
1169 | if (!key) |
1170 | return AVERROR(ENOMEM); |
1171 | |
1172 | if (*key && strspn(*buf, key_val_sep)) { |
1173 | (*buf)++; |
1174 | val = av_get_token(buf, pairs_sep); |
1175 | if (!val) { |
1176 | av_freep(&key); |
1177 | return AVERROR(ENOMEM); |
1178 | } |
1179 | } else { |
1180 | av_log(ctx, AV_LOG_ERROR, "Missing key or no key/value separator found after key '%s'\n", key); |
1181 | av_free(key); |
1182 | return AVERROR(EINVAL); |
1183 | } |
1184 | |
1185 | av_log(ctx, AV_LOG_DEBUG, "Setting entry with key '%s' to value '%s'\n", key, val); |
1186 | |
1187 | ret = av_opt_set(ctx, key, val, AV_OPT_SEARCH_CHILDREN); |
1188 | if (ret == AVERROR_OPTION_NOT_FOUND) |
1189 | av_log(ctx, AV_LOG_ERROR, "Key '%s' not found.\n", key); |
1190 | |
1191 | av_free(key); |
1192 | av_free(val); |
1193 | return ret; |
1194 | } |
1195 | |
1196 | int av_set_options_string(void *ctx, const char *opts, |
1197 | const char *key_val_sep, const char *pairs_sep) |
1198 | { |
1199 | int ret, count = 0; |
1200 | |
1201 | if (!opts) |
1202 | return 0; |
1203 | |
1204 | while (*opts) { |
1205 | if ((ret = parse_key_value_pair(ctx, &opts, key_val_sep, pairs_sep)) < 0) |
1206 | return ret; |
1207 | count++; |
1208 | |
1209 | if (*opts) |
1210 | opts++; |
1211 | } |
1212 | |
1213 | return count; |
1214 | } |
1215 | |
1216 | #define WHITESPACES " \n\t" |
1217 | |
1218 | static int is_key_char(char c) |
1219 | { |
1220 | return (unsigned)((c | 32) - 'a') < 26 || |
1221 | (unsigned)(c - '0') < 10 || |
1222 | c == '-' || c == '_' || c == '/' || c == '.'; |
1223 | } |
1224 | |
1225 | /** |
1226 | * Read a key from a string. |
1227 | * |
1228 | * The key consists of is_key_char characters and must be terminated by a |
1229 | * character from the delim string; spaces are ignored. |
1230 | * |
1231 | * @return 0 for success (even with ellipsis), <0 for failure |
1232 | */ |
1233 | static int get_key(const char **ropts, const char *delim, char **rkey) |
1234 | { |
1235 | const char *opts = *ropts; |
1236 | const char *key_start, *key_end; |
1237 | |
1238 | key_start = opts += strspn(opts, WHITESPACES); |
1239 | while (is_key_char(*opts)) |
1240 | opts++; |
1241 | key_end = opts; |
1242 | opts += strspn(opts, WHITESPACES); |
1243 | if (!*opts || !strchr(delim, *opts)) |
1244 | return AVERROR(EINVAL); |
1245 | opts++; |
1246 | if (!(*rkey = av_malloc(key_end - key_start + 1))) |
1247 | return AVERROR(ENOMEM); |
1248 | memcpy(*rkey, key_start, key_end - key_start); |
1249 | (*rkey)[key_end - key_start] = 0; |
1250 | *ropts = opts; |
1251 | return 0; |
1252 | } |
1253 | |
1254 | int av_opt_get_key_value(const char **ropts, |
1255 | const char *key_val_sep, const char *pairs_sep, |
1256 | unsigned flags, |
1257 | char **rkey, char **rval) |
1258 | { |
1259 | int ret; |
1260 | char *key = NULL, *val; |
1261 | const char *opts = *ropts; |
1262 | |
1263 | if ((ret = get_key(&opts, key_val_sep, &key)) < 0 && |
1264 | !(flags & AV_OPT_FLAG_IMPLICIT_KEY)) |
1265 | return AVERROR(EINVAL); |
1266 | if (!(val = av_get_token(&opts, pairs_sep))) { |
1267 | av_free(key); |
1268 | return AVERROR(ENOMEM); |
1269 | } |
1270 | *ropts = opts; |
1271 | *rkey = key; |
1272 | *rval = val; |
1273 | return 0; |
1274 | } |
1275 | |
1276 | int av_opt_set_from_string(void *ctx, const char *opts, |
1277 | const char *const *shorthand, |
1278 | const char *key_val_sep, const char *pairs_sep) |
1279 | { |
1280 | int ret, count = 0; |
1281 | const char *dummy_shorthand = NULL; |
1282 | char *av_uninit(parsed_key), *av_uninit(value); |
1283 | const char *key; |
1284 | |
1285 | if (!opts) |
1286 | return 0; |
1287 | if (!shorthand) |
1288 | shorthand = &dummy_shorthand; |
1289 | |
1290 | while (*opts) { |
1291 | ret = av_opt_get_key_value(&opts, key_val_sep, pairs_sep, |
1292 | *shorthand ? AV_OPT_FLAG_IMPLICIT_KEY : 0, |
1293 | &parsed_key, &value); |
1294 | if (ret < 0) { |
1295 | if (ret == AVERROR(EINVAL)) |
1296 | av_log(ctx, AV_LOG_ERROR, "No option name near '%s'\n", opts); |
1297 | else |
1298 | av_log(ctx, AV_LOG_ERROR, "Unable to parse '%s': %s\n", opts, |
1299 | av_err2str(ret)); |
1300 | return ret; |
1301 | } |
1302 | if (*opts) |
1303 | opts++; |
1304 | if (parsed_key) { |
1305 | key = parsed_key; |
1306 | while (*shorthand) /* discard all remaining shorthand */ |
1307 | shorthand++; |
1308 | } else { |
1309 | key = *(shorthand++); |
1310 | } |
1311 | |
1312 | av_log(ctx, AV_LOG_DEBUG, "Setting '%s' to value '%s'\n", key, value); |
1313 | if ((ret = av_opt_set(ctx, key, value, 0)) < 0) { |
1314 | if (ret == AVERROR_OPTION_NOT_FOUND) |
1315 | av_log(ctx, AV_LOG_ERROR, "Option '%s' not found\n", key); |
1316 | av_free(value); |
1317 | av_free(parsed_key); |
1318 | return ret; |
1319 | } |
1320 | |
1321 | av_free(value); |
1322 | av_free(parsed_key); |
1323 | count++; |
1324 | } |
1325 | return count; |
1326 | } |
1327 | |
1328 | void av_opt_free(void *obj) |
1329 | { |
1330 | const AVOption *o = NULL; |
1331 | while ((o = av_opt_next(obj, o))) |
1332 | if (o->type == AV_OPT_TYPE_STRING || o->type == AV_OPT_TYPE_BINARY) |
1333 | av_freep((uint8_t *)obj + o->offset); |
1334 | } |
1335 | |
1336 | int av_opt_set_dict(void *obj, AVDictionary **options) |
1337 | { |
1338 | AVDictionaryEntry *t = NULL; |
1339 | AVDictionary *tmp = NULL; |
1340 | int ret = 0; |
1341 | |
1342 | while ((t = av_dict_get(*options, "", t, AV_DICT_IGNORE_SUFFIX))) { |
1343 | ret = av_opt_set(obj, t->key, t->value, 0); |
1344 | if (ret == AVERROR_OPTION_NOT_FOUND) |
1345 | av_dict_set(&tmp, t->key, t->value, 0); |
1346 | else if (ret < 0) { |
1347 | av_log(obj, AV_LOG_ERROR, "Error setting option %s to value %s.\n", t->key, t->value); |
1348 | break; |
1349 | } |
1350 | ret = 0; |
1351 | } |
1352 | av_dict_free(options); |
1353 | *options = tmp; |
1354 | return ret; |
1355 | } |
1356 | |
1357 | const AVOption *av_opt_find(void *obj, const char *name, const char *unit, |
1358 | int opt_flags, int search_flags) |
1359 | { |
1360 | return av_opt_find2(obj, name, unit, opt_flags, search_flags, NULL); |
1361 | } |
1362 | |
1363 | const AVOption *av_opt_find2(void *obj, const char *name, const char *unit, |
1364 | int opt_flags, int search_flags, void **target_obj) |
1365 | { |
1366 | const AVClass *c; |
1367 | const AVOption *o = NULL; |
1368 | |
1369 | if(!obj) |
1370 | return NULL; |
1371 | |
1372 | c= *(AVClass**)obj; |
1373 | |
1374 | if (!c) |
1375 | return NULL; |
1376 | |
1377 | if (search_flags & AV_OPT_SEARCH_CHILDREN) { |
1378 | if (search_flags & AV_OPT_SEARCH_FAKE_OBJ) { |
1379 | const AVClass *child = NULL; |
1380 | while (child = av_opt_child_class_next(c, child)) |
1381 | if (o = av_opt_find2(&child, name, unit, opt_flags, search_flags, NULL)) |
1382 | return o; |
1383 | } else { |
1384 | void *child = NULL; |
1385 | while (child = av_opt_child_next(obj, child)) |
1386 | if (o = av_opt_find2(child, name, unit, opt_flags, search_flags, target_obj)) |
1387 | return o; |
1388 | } |
1389 | } |
1390 | |
1391 | while (o = av_opt_next(obj, o)) { |
1392 | if (!strcmp(o->name, name) && (o->flags & opt_flags) == opt_flags && |
1393 | ((!unit && o->type != AV_OPT_TYPE_CONST) || |
1394 | (unit && o->type == AV_OPT_TYPE_CONST && o->unit && !strcmp(o->unit, unit)))) { |
1395 | if (target_obj) { |
1396 | if (!(search_flags & AV_OPT_SEARCH_FAKE_OBJ)) |
1397 | *target_obj = obj; |
1398 | else |
1399 | *target_obj = NULL; |
1400 | } |
1401 | return o; |
1402 | } |
1403 | } |
1404 | return NULL; |
1405 | } |
1406 | |
1407 | void *av_opt_child_next(void *obj, void *prev) |
1408 | { |
1409 | const AVClass *c = *(AVClass**)obj; |
1410 | if (c->child_next) |
1411 | return c->child_next(obj, prev); |
1412 | return NULL; |
1413 | } |
1414 | |
1415 | const AVClass *av_opt_child_class_next(const AVClass *parent, const AVClass *prev) |
1416 | { |
1417 | if (parent->child_class_next) |
1418 | return parent->child_class_next(prev); |
1419 | return NULL; |
1420 | } |
1421 | |
1422 | void *av_opt_ptr(const AVClass *class, void *obj, const char *name) |
1423 | { |
1424 | const AVOption *opt= av_opt_find2(&class, name, NULL, 0, AV_OPT_SEARCH_FAKE_OBJ, NULL); |
1425 | if(!opt) |
1426 | return NULL; |
1427 | return (uint8_t*)obj + opt->offset; |
1428 | } |
1429 | |
1430 | int av_opt_query_ranges(AVOptionRanges **ranges_arg, void *obj, const char *key, int flags) |
1431 | { |
1432 | const AVClass *c = *(AVClass**)obj; |
1433 | int (*callback)(AVOptionRanges **, void *obj, const char *key, int flags) = NULL; |
1434 | |
1435 | if (c->version > (52 << 16 | 11 << 8)) |
1436 | callback = c->query_ranges; |
1437 | |
1438 | if (!callback) |
1439 | callback = av_opt_query_ranges_default; |
1440 | |
1441 | return callback(ranges_arg, obj, key, flags); |
1442 | } |
1443 | |
1444 | int av_opt_query_ranges_default(AVOptionRanges **ranges_arg, void *obj, const char *key, int flags) |
1445 | { |
1446 | AVOptionRanges *ranges = av_mallocz(sizeof(*ranges)); |
1447 | AVOptionRange **range_array = av_mallocz(sizeof(void*)); |
1448 | AVOptionRange *range = av_mallocz(sizeof(*range)); |
1449 | const AVOption *field = av_opt_find(obj, key, NULL, 0, flags); |
1450 | int ret; |
1451 | |
1452 | *ranges_arg = NULL; |
1453 | |
1454 | if (!ranges || !range || !range_array || !field) { |
1455 | ret = AVERROR(ENOMEM); |
1456 | goto fail; |
1457 | } |
1458 | |
1459 | ranges->range = range_array; |
1460 | ranges->range[0] = range; |
1461 | ranges->nb_ranges = 1; |
1462 | range->is_range = 1; |
1463 | range->value_min = field->min; |
1464 | range->value_max = field->max; |
1465 | |
1466 | switch (field->type) { |
1467 | case AV_OPT_TYPE_INT: |
1468 | case AV_OPT_TYPE_INT64: |
1469 | case AV_OPT_TYPE_PIXEL_FMT: |
1470 | case AV_OPT_TYPE_SAMPLE_FMT: |
1471 | case AV_OPT_TYPE_FLOAT: |
1472 | case AV_OPT_TYPE_DOUBLE: |
1473 | case AV_OPT_TYPE_DURATION: |
1474 | case AV_OPT_TYPE_COLOR: |
1475 | case AV_OPT_TYPE_CHANNEL_LAYOUT: |
1476 | break; |
1477 | case AV_OPT_TYPE_STRING: |
1478 | range->component_min = 0; |
1479 | range->component_max = 0x10FFFF; // max unicode value |
1480 | range->value_min = -1; |
1481 | range->value_max = INT_MAX; |
1482 | break; |
1483 | case AV_OPT_TYPE_RATIONAL: |
1484 | range->component_min = INT_MIN; |
1485 | range->component_max = INT_MAX; |
1486 | break; |
1487 | case AV_OPT_TYPE_IMAGE_SIZE: |
1488 | range->component_min = 0; |
1489 | range->component_max = INT_MAX/128/8; |
1490 | range->value_min = 0; |
1491 | range->value_max = INT_MAX/8; |
1492 | break; |
1493 | case AV_OPT_TYPE_VIDEO_RATE: |
1494 | range->component_min = 1; |
1495 | range->component_max = INT_MAX; |
1496 | range->value_min = 1; |
1497 | range->value_max = INT_MAX; |
1498 | break; |
1499 | default: |
1500 | ret = AVERROR(ENOSYS); |
1501 | goto fail; |
1502 | } |
1503 | |
1504 | *ranges_arg = ranges; |
1505 | return 0; |
1506 | fail: |
1507 | av_free(ranges); |
1508 | av_free(range); |
1509 | av_free(range_array); |
1510 | return ret; |
1511 | } |
1512 | |
1513 | void av_opt_freep_ranges(AVOptionRanges **rangesp) |
1514 | { |
1515 | int i; |
1516 | AVOptionRanges *ranges = *rangesp; |
1517 | |
1518 | for (i = 0; i < ranges->nb_ranges; i++) { |
1519 | AVOptionRange *range = ranges->range[i]; |
1520 | av_freep(&range->str); |
1521 | av_freep(&ranges->range[i]); |
1522 | } |
1523 | av_freep(&ranges->range); |
1524 | av_freep(rangesp); |
1525 | } |
1526 | |
1527 | #ifdef TEST |
1528 | |
1529 | typedef struct TestContext |
1530 | { |
1531 | const AVClass *class; |
1532 | int num; |
1533 | int toggle; |
1534 | char *string; |
1535 | int flags; |
1536 | AVRational rational; |
1537 | AVRational video_rate; |
1538 | int w, h; |
1539 | enum AVPixelFormat pix_fmt; |
1540 | enum AVSampleFormat sample_fmt; |
1541 | int64_t duration; |
1542 | uint8_t color[4]; |
1543 | int64_t channel_layout; |
1544 | } TestContext; |
1545 | |
1546 | #define OFFSET(x) offsetof(TestContext, x) |
1547 | |
1548 | #define TEST_FLAG_COOL 01 |
1549 | #define TEST_FLAG_LAME 02 |
1550 | #define TEST_FLAG_MU 04 |
1551 | |
1552 | static const AVOption test_options[]= { |
1553 | {"num", "set num", OFFSET(num), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 100 }, |
1554 | {"toggle", "set toggle", OFFSET(toggle), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1 }, |
1555 | {"rational", "set rational", OFFSET(rational), AV_OPT_TYPE_RATIONAL, {.dbl = 0}, 0, 10 }, |
1556 | {"string", "set string", OFFSET(string), AV_OPT_TYPE_STRING, {.str = "default"}, CHAR_MIN, CHAR_MAX }, |
1557 | {"flags", "set flags", OFFSET(flags), AV_OPT_TYPE_FLAGS, {.i64 = 0}, 0, INT_MAX, 0, "flags" }, |
1558 | {"cool", "set cool flag ", 0, AV_OPT_TYPE_CONST, {.i64 = TEST_FLAG_COOL}, INT_MIN, INT_MAX, 0, "flags" }, |
1559 | {"lame", "set lame flag ", 0, AV_OPT_TYPE_CONST, {.i64 = TEST_FLAG_LAME}, INT_MIN, INT_MAX, 0, "flags" }, |
1560 | {"mu", "set mu flag ", 0, AV_OPT_TYPE_CONST, {.i64 = TEST_FLAG_MU}, INT_MIN, INT_MAX, 0, "flags" }, |
1561 | {"size", "set size", OFFSET(w), AV_OPT_TYPE_IMAGE_SIZE,{0}, 0, 0 }, |
1562 | {"pix_fmt", "set pixfmt", OFFSET(pix_fmt), AV_OPT_TYPE_PIXEL_FMT, {.i64 = AV_PIX_FMT_NONE}, -1, AV_PIX_FMT_NB-1}, |
1563 | {"sample_fmt", "set samplefmt", OFFSET(sample_fmt), AV_OPT_TYPE_SAMPLE_FMT, {.i64 = AV_SAMPLE_FMT_NONE}, -1, AV_SAMPLE_FMT_NB-1}, |
1564 | {"video_rate", "set videorate", OFFSET(video_rate), AV_OPT_TYPE_VIDEO_RATE, {.str = "25"}, 0, 0 }, |
1565 | {"duration", "set duration", OFFSET(duration), AV_OPT_TYPE_DURATION, {.i64 = 0}, 0, INT64_MAX}, |
1566 | {"color", "set color", OFFSET(color), AV_OPT_TYPE_COLOR, {.str = "pink"}, 0, 0}, |
1567 | {"cl", "set channel layout", OFFSET(channel_layout), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64 = AV_CH_LAYOUT_HEXAGONAL}, 0, INT64_MAX}, |
1568 | {NULL}, |
1569 | }; |
1570 | |
1571 | static const char *test_get_name(void *ctx) |
1572 | { |
1573 | return "test"; |
1574 | } |
1575 | |
1576 | static const AVClass test_class = { |
1577 | "TestContext", |
1578 | test_get_name, |
1579 | test_options |
1580 | }; |
1581 | |
1582 | int main(void) |
1583 | { |
1584 | int i; |
1585 | |
1586 | printf("\nTesting av_set_options_string()\n"); |
1587 | { |
1588 | TestContext test_ctx = { 0 }; |
1589 | static const char * const options[] = { |
1590 | "", |
1591 | ":", |
1592 | "=", |
1593 | "foo=:", |
1594 | ":=foo", |
1595 | "=foo", |
1596 | "foo=", |
1597 | "foo", |
1598 | "foo=val", |
1599 | "foo==val", |
1600 | "toggle=:", |
1601 | "string=:", |
1602 | "toggle=1 : foo", |
1603 | "toggle=100", |
1604 | "toggle==1", |
1605 | "flags=+mu-lame : num=42: toggle=0", |
1606 | "num=42 : string=blahblah", |
1607 | "rational=0 : rational=1/2 : rational=1/-1", |
1608 | "rational=-1/0", |
1609 | "size=1024x768", |
1610 | "size=pal", |
1611 | "size=bogus", |
1612 | "pix_fmt=yuv420p", |
1613 | "pix_fmt=2", |
1614 | "pix_fmt=bogus", |
1615 | "sample_fmt=s16", |
1616 | "sample_fmt=2", |
1617 | "sample_fmt=bogus", |
1618 | "video_rate=pal", |
1619 | "video_rate=25", |
1620 | "video_rate=30000/1001", |
1621 | "video_rate=30/1.001", |
1622 | "video_rate=bogus", |
1623 | "duration=bogus", |
1624 | "duration=123.45", |
1625 | "duration=1\\:23\\:45.67", |
1626 | "color=blue", |
1627 | "color=0x223300", |
1628 | "color=0x42FF07AA", |
1629 | "cl=stereo+downmix", |
1630 | "cl=foo", |
1631 | }; |
1632 | |
1633 | test_ctx.class = &test_class; |
1634 | av_opt_set_defaults(&test_ctx); |
1635 | |
1636 | av_log_set_level(AV_LOG_DEBUG); |
1637 | |
1638 | for (i=0; i < FF_ARRAY_ELEMS(options); i++) { |
1639 | av_log(&test_ctx, AV_LOG_DEBUG, "Setting options string '%s'\n", options[i]); |
1640 | if (av_set_options_string(&test_ctx, options[i], "=", ":") < 0) |
1641 | av_log(&test_ctx, AV_LOG_ERROR, "Error setting options string: '%s'\n", options[i]); |
1642 | printf("\n"); |
1643 | } |
1644 | av_opt_free(&test_ctx); |
1645 | } |
1646 | |
1647 | printf("\nTesting av_opt_set_from_string()\n"); |
1648 | { |
1649 | TestContext test_ctx = { 0 }; |
1650 | static const char * const options[] = { |
1651 | "", |
1652 | "5", |
1653 | "5:hello", |
1654 | "5:hello:size=pal", |
1655 | "5:size=pal:hello", |
1656 | ":", |
1657 | "=", |
1658 | " 5 : hello : size = pal ", |
1659 | "a_very_long_option_name_that_will_need_to_be_ellipsized_around_here=42" |
1660 | }; |
1661 | static const char * const shorthand[] = { "num", "string", NULL }; |
1662 | |
1663 | test_ctx.class = &test_class; |
1664 | av_opt_set_defaults(&test_ctx); |
1665 | |
1666 | av_log_set_level(AV_LOG_DEBUG); |
1667 | |
1668 | for (i=0; i < FF_ARRAY_ELEMS(options); i++) { |
1669 | av_log(&test_ctx, AV_LOG_DEBUG, "Setting options string '%s'\n", options[i]); |
1670 | if (av_opt_set_from_string(&test_ctx, options[i], shorthand, "=", ":") < 0) |
1671 | av_log(&test_ctx, AV_LOG_ERROR, "Error setting options string: '%s'\n", options[i]); |
1672 | printf("\n"); |
1673 | } |
1674 | av_opt_free(&test_ctx); |
1675 | } |
1676 | |
1677 | return 0; |
1678 | } |
1679 | |
1680 | #endif |
1681 |