opt.c
Go to the documentation of this file.
1 /*
2  * AVOptions
3  * Copyright (c) 2005 Michael Niedermayer <michaelni@gmx.at>
4  *
5  * This file is part of Libav.
6  *
7  * Libav 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  * Libav 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 Libav; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21 
28 #include "avutil.h"
29 #include "avstring.h"
30 #include "opt.h"
31 #include "eval.h"
32 #include "dict.h"
33 #include "log.h"
34 
35 #if FF_API_FIND_OPT
36 //FIXME order them and do a bin search
37 const AVOption *av_find_opt(void *v, const char *name, const char *unit, int mask, int flags)
38 {
39  AVClass *c= *(AVClass**)v; //FIXME silly way of storing AVClass
40  const AVOption *o= c->option;
41 
42  for (; o && o->name; o++) {
43  if (!strcmp(o->name, name) && (!unit || (o->unit && !strcmp(o->unit, unit))) && (o->flags & mask) == flags)
44  return o;
45  }
46  return NULL;
47 }
48 #endif
49 
50 #if FF_API_OLD_AVOPTIONS
51 const AVOption *av_next_option(void *obj, const AVOption *last)
52 {
53  return av_opt_next(obj, last);
54 }
55 #endif
56 
57 const AVOption *av_opt_next(void *obj, const AVOption *last)
58 {
59  AVClass *class = *(AVClass**)obj;
60  if (!last && class->option[0].name) return class->option;
61  if (last && last[1].name) return ++last;
62  return NULL;
63 }
64 
65 static int read_number(const AVOption *o, void *dst, double *num, int *den, int64_t *intnum)
66 {
67  switch (o->type) {
68  case AV_OPT_TYPE_FLAGS: *intnum = *(unsigned int*)dst;return 0;
69  case AV_OPT_TYPE_INT: *intnum = *(int *)dst;return 0;
70  case AV_OPT_TYPE_INT64: *intnum = *(int64_t *)dst;return 0;
71  case AV_OPT_TYPE_FLOAT: *num = *(float *)dst;return 0;
72  case AV_OPT_TYPE_DOUBLE: *num = *(double *)dst;return 0;
73  case AV_OPT_TYPE_RATIONAL: *intnum = ((AVRational*)dst)->num;
74  *den = ((AVRational*)dst)->den;
75  return 0;
76  }
77  return AVERROR(EINVAL);
78 }
79 
80 static int write_number(void *obj, const AVOption *o, void *dst, double num, int den, int64_t intnum)
81 {
82  if (o->max*den < num*intnum || o->min*den > num*intnum) {
83  av_log(obj, AV_LOG_ERROR, "Value %lf for parameter '%s' out of range\n", num, o->name);
84  return AVERROR(ERANGE);
85  }
86 
87  switch (o->type) {
88  case AV_OPT_TYPE_FLAGS:
89  case AV_OPT_TYPE_INT: *(int *)dst= llrint(num/den)*intnum; break;
90  case AV_OPT_TYPE_INT64: *(int64_t *)dst= llrint(num/den)*intnum; break;
91  case AV_OPT_TYPE_FLOAT: *(float *)dst= num*intnum/den; break;
92  case AV_OPT_TYPE_DOUBLE:*(double *)dst= num*intnum/den; break;
94  if ((int)num == num) *(AVRational*)dst= (AVRational){num*intnum, den};
95  else *(AVRational*)dst= av_d2q(num*intnum/den, 1<<24);
96  break;
97  default:
98  return AVERROR(EINVAL);
99  }
100  return 0;
101 }
102 
103 static const double const_values[] = {
104  M_PI,
105  M_E,
106  FF_QP2LAMBDA,
107  0
108 };
109 
110 static const char * const const_names[] = {
111  "PI",
112  "E",
113  "QP2LAMBDA",
114  0
115 };
116 
117 static int hexchar2int(char c) {
118  if (c >= '0' && c <= '9') return c - '0';
119  if (c >= 'a' && c <= 'f') return c - 'a' + 10;
120  if (c >= 'A' && c <= 'F') return c - 'A' + 10;
121  return -1;
122 }
123 
124 static int set_string_binary(void *obj, const AVOption *o, const char *val, uint8_t **dst)
125 {
126  int *lendst = (int *)(dst + 1);
127  uint8_t *bin, *ptr;
128  int len = strlen(val);
129 
130  av_freep(dst);
131  *lendst = 0;
132 
133  if (len & 1)
134  return AVERROR(EINVAL);
135  len /= 2;
136 
137  ptr = bin = av_malloc(len);
138  while (*val) {
139  int a = hexchar2int(*val++);
140  int b = hexchar2int(*val++);
141  if (a < 0 || b < 0) {
142  av_free(bin);
143  return AVERROR(EINVAL);
144  }
145  *ptr++ = (a << 4) | b;
146  }
147  *dst = bin;
148  *lendst = len;
149 
150  return 0;
151 }
152 
153 static int set_string(void *obj, const AVOption *o, const char *val, uint8_t **dst)
154 {
155  av_freep(dst);
156  *dst = av_strdup(val);
157  return 0;
158 }
159 
160 static int set_string_number(void *obj, const AVOption *o, const char *val, void *dst)
161 {
162  int ret = 0, notfirst = 0;
163  for (;;) {
164  int i, den = 1;
165  char buf[256];
166  int cmd = 0;
167  double d, num = 1;
168  int64_t intnum = 1;
169 
170  if (*val == '+' || *val == '-')
171  cmd = *(val++);
172 
173  for (i = 0; i < sizeof(buf) - 1 && val[i] && val[i] != '+' && val[i] != '-'; i++)
174  buf[i] = val[i];
175  buf[i] = 0;
176 
177  {
178  const AVOption *o_named = av_opt_find(obj, buf, o->unit, 0, 0);
179  if (o_named && o_named->type == AV_OPT_TYPE_CONST)
180  d = o_named->default_val.dbl;
181  else if (!strcmp(buf, "default")) d = o->default_val.dbl;
182  else if (!strcmp(buf, "max" )) d = o->max;
183  else if (!strcmp(buf, "min" )) d = o->min;
184  else if (!strcmp(buf, "none" )) d = 0;
185  else if (!strcmp(buf, "all" )) d = ~0;
186  else {
187  int res = av_expr_parse_and_eval(&d, buf, const_names, const_values, NULL, NULL, NULL, NULL, NULL, 0, obj);
188  if (res < 0) {
189  av_log(obj, AV_LOG_ERROR, "Unable to parse option value \"%s\"\n", val);
190  return res;
191  }
192  }
193  }
194  if (o->type == AV_OPT_TYPE_FLAGS) {
195  read_number(o, dst, NULL, NULL, &intnum);
196  if (cmd == '+') d = intnum | (int64_t)d;
197  else if (cmd == '-') d = intnum &~(int64_t)d;
198  } else {
199  read_number(o, dst, &num, &den, &intnum);
200  if (cmd == '+') d = notfirst*num*intnum/den + d;
201  else if (cmd == '-') d = notfirst*num*intnum/den - d;
202  }
203 
204  if ((ret = write_number(obj, o, dst, d, 1, 1)) < 0)
205  return ret;
206  val += i;
207  if (!*val)
208  return 0;
209  notfirst = 1;
210  }
211 
212  return 0;
213 }
214 
215 #if FF_API_OLD_AVOPTIONS
216 int av_set_string3(void *obj, const char *name, const char *val, int alloc, const AVOption **o_out)
217 {
218  const AVOption *o = av_opt_find(obj, name, NULL, 0, 0);
219  if (o_out)
220  *o_out = o;
221  return av_opt_set(obj, name, val, 0);
222 }
223 #endif
224 
225 int av_opt_set(void *obj, const char *name, const char *val, int search_flags)
226 {
227  void *dst, *target_obj;
228  const AVOption *o = av_opt_find2(obj, name, NULL, 0, search_flags, &target_obj);
229  if (!o || !target_obj)
231  if (!val)
232  return AVERROR(EINVAL);
233 
234  dst = ((uint8_t*)target_obj) + o->offset;
235  switch (o->type) {
236  case AV_OPT_TYPE_STRING: return set_string(obj, o, val, dst);
237  case AV_OPT_TYPE_BINARY: return set_string_binary(obj, o, val, dst);
238  case AV_OPT_TYPE_FLAGS:
239  case AV_OPT_TYPE_INT:
240  case AV_OPT_TYPE_INT64:
241  case AV_OPT_TYPE_FLOAT:
242  case AV_OPT_TYPE_DOUBLE:
243  case AV_OPT_TYPE_RATIONAL: return set_string_number(obj, o, val, dst);
244  }
245 
246  av_log(obj, AV_LOG_ERROR, "Invalid option type.\n");
247  return AVERROR(EINVAL);
248 }
249 
250 #define OPT_EVAL_NUMBER(name, opttype, vartype)\
251  int av_opt_eval_ ## name(void *obj, const AVOption *o, const char *val, vartype *name ## _out)\
252  {\
253  if (!o || o->type != opttype)\
254  return AVERROR(EINVAL);\
255  return set_string_number(obj, o, val, name ## _out);\
256  }
257 
260 OPT_EVAL_NUMBER(int64, AV_OPT_TYPE_INT64, int64_t)
261 OPT_EVAL_NUMBER(float, AV_OPT_TYPE_FLOAT, float)
262 OPT_EVAL_NUMBER(double, AV_OPT_TYPE_DOUBLE, double)
264 
265 static int set_number(void *obj, const char *name, double num, int den, int64_t intnum,
266  int search_flags)
267 {
268  void *dst, *target_obj;
269  const AVOption *o = av_opt_find2(obj, name, NULL, 0, search_flags, &target_obj);
270 
271  if (!o || !target_obj)
273 
274  dst = ((uint8_t*)target_obj) + o->offset;
275  return write_number(obj, o, dst, num, den, intnum);
276 }
277 
278 #if FF_API_OLD_AVOPTIONS
279 const AVOption *av_set_double(void *obj, const char *name, double n)
280 {
281  const AVOption *o = av_opt_find(obj, name, NULL, 0, 0);
282  if (set_number(obj, name, n, 1, 1, 0) < 0)
283  return NULL;
284  return o;
285 }
286 
287 const AVOption *av_set_q(void *obj, const char *name, AVRational n)
288 {
289  const AVOption *o = av_opt_find(obj, name, NULL, 0, 0);
290  if (set_number(obj, name, n.num, n.den, 1, 0) < 0)
291  return NULL;
292  return o;
293 }
294 
295 const AVOption *av_set_int(void *obj, const char *name, int64_t n)
296 {
297  const AVOption *o = av_opt_find(obj, name, NULL, 0, 0);
298  if (set_number(obj, name, 1, 1, n, 0) < 0)
299  return NULL;
300  return o;
301 }
302 #endif
303 
304 int av_opt_set_int(void *obj, const char *name, int64_t val, int search_flags)
305 {
306  return set_number(obj, name, 1, 1, val, search_flags);
307 }
308 
309 int av_opt_set_double(void *obj, const char *name, double val, int search_flags)
310 {
311  return set_number(obj, name, val, 1, 1, search_flags);
312 }
313 
314 int av_opt_set_q(void *obj, const char *name, AVRational val, int search_flags)
315 {
316  return set_number(obj, name, val.num, val.den, 1, search_flags);
317 }
318 
319 #if FF_API_OLD_AVOPTIONS
320 
325 const char *av_get_string(void *obj, const char *name, const AVOption **o_out, char *buf, int buf_len)
326 {
327  const AVOption *o = av_opt_find(obj, name, NULL, 0, 0);
328  void *dst;
329  uint8_t *bin;
330  int len, i;
331  if (!o)
332  return NULL;
333  if (o->type != AV_OPT_TYPE_STRING && (!buf || !buf_len))
334  return NULL;
335 
336  dst= ((uint8_t*)obj) + o->offset;
337  if (o_out) *o_out= o;
338 
339  switch (o->type) {
340  case AV_OPT_TYPE_FLAGS: snprintf(buf, buf_len, "0x%08X",*(int *)dst);break;
341  case AV_OPT_TYPE_INT: snprintf(buf, buf_len, "%d" , *(int *)dst);break;
342  case AV_OPT_TYPE_INT64: snprintf(buf, buf_len, "%"PRId64, *(int64_t*)dst);break;
343  case AV_OPT_TYPE_FLOAT: snprintf(buf, buf_len, "%f" , *(float *)dst);break;
344  case AV_OPT_TYPE_DOUBLE: snprintf(buf, buf_len, "%f" , *(double *)dst);break;
345  case AV_OPT_TYPE_RATIONAL: snprintf(buf, buf_len, "%d/%d", ((AVRational*)dst)->num, ((AVRational*)dst)->den);break;
346  case AV_OPT_TYPE_STRING: return *(void**)dst;
347  case AV_OPT_TYPE_BINARY:
348  len = *(int*)(((uint8_t *)dst) + sizeof(uint8_t *));
349  if (len >= (buf_len + 1)/2) return NULL;
350  bin = *(uint8_t**)dst;
351  for (i = 0; i < len; i++) snprintf(buf + i*2, 3, "%02X", bin[i]);
352  break;
353  default: return NULL;
354  }
355  return buf;
356 }
357 #endif
358 
359 int av_opt_get(void *obj, const char *name, int search_flags, uint8_t **out_val)
360 {
361  void *dst, *target_obj;
362  const AVOption *o = av_opt_find2(obj, name, NULL, 0, search_flags, &target_obj);
363  uint8_t *bin, buf[128];
364  int len, i, ret;
365 
366  if (!o || !target_obj)
368 
369  dst = (uint8_t*)target_obj + o->offset;
370 
371  buf[0] = 0;
372  switch (o->type) {
373  case AV_OPT_TYPE_FLAGS: ret = snprintf(buf, sizeof(buf), "0x%08X", *(int *)dst);break;
374  case AV_OPT_TYPE_INT: ret = snprintf(buf, sizeof(buf), "%d" , *(int *)dst);break;
375  case AV_OPT_TYPE_INT64: ret = snprintf(buf, sizeof(buf), "%"PRId64, *(int64_t*)dst);break;
376  case AV_OPT_TYPE_FLOAT: ret = snprintf(buf, sizeof(buf), "%f" , *(float *)dst);break;
377  case AV_OPT_TYPE_DOUBLE: ret = snprintf(buf, sizeof(buf), "%f" , *(double *)dst);break;
378  case AV_OPT_TYPE_RATIONAL: ret = snprintf(buf, sizeof(buf), "%d/%d", ((AVRational*)dst)->num, ((AVRational*)dst)->den);break;
379  case AV_OPT_TYPE_STRING:
380  if (*(uint8_t**)dst)
381  *out_val = av_strdup(*(uint8_t**)dst);
382  else
383  *out_val = av_strdup("");
384  return 0;
385  case AV_OPT_TYPE_BINARY:
386  len = *(int*)(((uint8_t *)dst) + sizeof(uint8_t *));
387  if ((uint64_t)len*2 + 1 > INT_MAX)
388  return AVERROR(EINVAL);
389  if (!(*out_val = av_malloc(len*2 + 1)))
390  return AVERROR(ENOMEM);
391  bin = *(uint8_t**)dst;
392  for (i = 0; i < len; i++)
393  snprintf(*out_val + i*2, 3, "%02X", bin[i]);
394  return 0;
395  default:
396  return AVERROR(EINVAL);
397  }
398 
399  if (ret >= sizeof(buf))
400  return AVERROR(EINVAL);
401  *out_val = av_strdup(buf);
402  return 0;
403 }
404 
405 static int get_number(void *obj, const char *name, const AVOption **o_out, double *num, int *den, int64_t *intnum,
406  int search_flags)
407 {
408  void *dst, *target_obj;
409  const AVOption *o = av_opt_find2(obj, name, NULL, 0, search_flags, &target_obj);
410  if (!o || !target_obj)
411  goto error;
412 
413  dst = ((uint8_t*)target_obj) + o->offset;
414 
415  if (o_out) *o_out= o;
416 
417  return read_number(o, dst, num, den, intnum);
418 
419 error:
420  *den=*intnum=0;
421  return -1;
422 }
423 
424 #if FF_API_OLD_AVOPTIONS
425 double av_get_double(void *obj, const char *name, const AVOption **o_out)
426 {
427  int64_t intnum=1;
428  double num=1;
429  int den=1;
430 
431  if (get_number(obj, name, o_out, &num, &den, &intnum, 0) < 0)
432  return NAN;
433  return num*intnum/den;
434 }
435 
436 AVRational av_get_q(void *obj, const char *name, const AVOption **o_out)
437 {
438  int64_t intnum=1;
439  double num=1;
440  int den=1;
441 
442  if (get_number(obj, name, o_out, &num, &den, &intnum, 0) < 0)
443  return (AVRational){0, 0};
444  if (num == 1.0 && (int)intnum == intnum)
445  return (AVRational){intnum, den};
446  else
447  return av_d2q(num*intnum/den, 1<<24);
448 }
449 
450 int64_t av_get_int(void *obj, const char *name, const AVOption **o_out)
451 {
452  int64_t intnum=1;
453  double num=1;
454  int den=1;
455 
456  if (get_number(obj, name, o_out, &num, &den, &intnum, 0) < 0)
457  return -1;
458  return num*intnum/den;
459 }
460 #endif
461 
462 int av_opt_get_int(void *obj, const char *name, int search_flags, int64_t *out_val)
463 {
464  int64_t intnum = 1;
465  double num = 1;
466  int ret, den = 1;
467 
468  if ((ret = get_number(obj, name, NULL, &num, &den, &intnum, search_flags)) < 0)
469  return ret;
470  *out_val = num*intnum/den;
471  return 0;
472 }
473 
474 int av_opt_get_double(void *obj, const char *name, int search_flags, double *out_val)
475 {
476  int64_t intnum = 1;
477  double num = 1;
478  int ret, den = 1;
479 
480  if ((ret = get_number(obj, name, NULL, &num, &den, &intnum, search_flags)) < 0)
481  return ret;
482  *out_val = num*intnum/den;
483  return 0;
484 }
485 
486 int av_opt_get_q(void *obj, const char *name, int search_flags, AVRational *out_val)
487 {
488  int64_t intnum = 1;
489  double num = 1;
490  int ret, den = 1;
491 
492  if ((ret = get_number(obj, name, NULL, &num, &den, &intnum, search_flags)) < 0)
493  return ret;
494 
495  if (num == 1.0 && (int)intnum == intnum)
496  *out_val = (AVRational){intnum, den};
497  else
498  *out_val = av_d2q(num*intnum/den, 1<<24);
499  return 0;
500 }
501 
502 int av_opt_flag_is_set(void *obj, const char *field_name, const char *flag_name)
503 {
504  const AVOption *field = av_opt_find(obj, field_name, NULL, 0, 0);
505  const AVOption *flag = av_opt_find(obj, flag_name,
506  field ? field->unit : NULL, 0, 0);
507  int64_t res;
508 
509  if (!field || !flag || flag->type != AV_OPT_TYPE_CONST ||
510  av_opt_get_int(obj, field_name, 0, &res) < 0)
511  return 0;
512  return res & (int) flag->default_val.dbl;
513 }
514 
515 static void opt_list(void *obj, void *av_log_obj, const char *unit,
516  int req_flags, int rej_flags)
517 {
518  const AVOption *opt=NULL;
519 
520  while ((opt = av_opt_next(obj, opt))) {
521  if (!(opt->flags & req_flags) || (opt->flags & rej_flags))
522  continue;
523 
524  /* Don't print CONST's on level one.
525  * Don't print anything but CONST's on level two.
526  * Only print items from the requested unit.
527  */
528  if (!unit && opt->type==AV_OPT_TYPE_CONST)
529  continue;
530  else if (unit && opt->type!=AV_OPT_TYPE_CONST)
531  continue;
532  else if (unit && opt->type==AV_OPT_TYPE_CONST && strcmp(unit, opt->unit))
533  continue;
534  else if (unit && opt->type == AV_OPT_TYPE_CONST)
535  av_log(av_log_obj, AV_LOG_INFO, " %-15s ", opt->name);
536  else
537  av_log(av_log_obj, AV_LOG_INFO, "-%-17s ", opt->name);
538 
539  switch (opt->type) {
540  case AV_OPT_TYPE_FLAGS:
541  av_log(av_log_obj, AV_LOG_INFO, "%-7s ", "<flags>");
542  break;
543  case AV_OPT_TYPE_INT:
544  av_log(av_log_obj, AV_LOG_INFO, "%-7s ", "<int>");
545  break;
546  case AV_OPT_TYPE_INT64:
547  av_log(av_log_obj, AV_LOG_INFO, "%-7s ", "<int64>");
548  break;
549  case AV_OPT_TYPE_DOUBLE:
550  av_log(av_log_obj, AV_LOG_INFO, "%-7s ", "<double>");
551  break;
552  case AV_OPT_TYPE_FLOAT:
553  av_log(av_log_obj, AV_LOG_INFO, "%-7s ", "<float>");
554  break;
555  case AV_OPT_TYPE_STRING:
556  av_log(av_log_obj, AV_LOG_INFO, "%-7s ", "<string>");
557  break;
559  av_log(av_log_obj, AV_LOG_INFO, "%-7s ", "<rational>");
560  break;
561  case AV_OPT_TYPE_BINARY:
562  av_log(av_log_obj, AV_LOG_INFO, "%-7s ", "<binary>");
563  break;
564  case AV_OPT_TYPE_CONST:
565  default:
566  av_log(av_log_obj, AV_LOG_INFO, "%-7s ", "");
567  break;
568  }
569  av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_ENCODING_PARAM) ? 'E' : '.');
570  av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_DECODING_PARAM) ? 'D' : '.');
571  av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_VIDEO_PARAM ) ? 'V' : '.');
572  av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_AUDIO_PARAM ) ? 'A' : '.');
573  av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_SUBTITLE_PARAM) ? 'S' : '.');
574 
575  if (opt->help)
576  av_log(av_log_obj, AV_LOG_INFO, " %s", opt->help);
577  av_log(av_log_obj, AV_LOG_INFO, "\n");
578  if (opt->unit && opt->type != AV_OPT_TYPE_CONST) {
579  opt_list(obj, av_log_obj, opt->unit, req_flags, rej_flags);
580  }
581  }
582 }
583 
584 int av_opt_show2(void *obj, void *av_log_obj, int req_flags, int rej_flags)
585 {
586  if (!obj)
587  return -1;
588 
589  av_log(av_log_obj, AV_LOG_INFO, "%s AVOptions:\n", (*(AVClass**)obj)->class_name);
590 
591  opt_list(obj, av_log_obj, NULL, req_flags, rej_flags);
592 
593  return 0;
594 }
595 
596 void av_opt_set_defaults(void *s)
597 {
598 #if FF_API_OLD_AVOPTIONS
599  av_opt_set_defaults2(s, 0, 0);
600 }
601 
602 void av_opt_set_defaults2(void *s, int mask, int flags)
603 {
604 #endif
605  const AVOption *opt = NULL;
606  while ((opt = av_opt_next(s, opt)) != NULL) {
607 #if FF_API_OLD_AVOPTIONS
608  if ((opt->flags & mask) != flags)
609  continue;
610 #endif
611  switch (opt->type) {
612  case AV_OPT_TYPE_CONST:
613  /* Nothing to be done here */
614  break;
615  case AV_OPT_TYPE_FLAGS:
616  case AV_OPT_TYPE_INT: {
617  int val;
618  val = opt->default_val.dbl;
619  av_opt_set_int(s, opt->name, val, 0);
620  }
621  break;
622  case AV_OPT_TYPE_INT64:
623  if ((double)(opt->default_val.dbl+0.6) == opt->default_val.dbl)
624  av_log(s, AV_LOG_DEBUG, "loss of precision in default of %s\n", opt->name);
625  av_opt_set_int(s, opt->name, opt->default_val.dbl, 0);
626  break;
627  case AV_OPT_TYPE_DOUBLE:
628  case AV_OPT_TYPE_FLOAT: {
629  double val;
630  val = opt->default_val.dbl;
631  av_opt_set_double(s, opt->name, val, 0);
632  }
633  break;
634  case AV_OPT_TYPE_RATIONAL: {
635  AVRational val;
636  val = av_d2q(opt->default_val.dbl, INT_MAX);
637  av_opt_set_q(s, opt->name, val, 0);
638  }
639  break;
640  case AV_OPT_TYPE_STRING:
641  av_opt_set(s, opt->name, opt->default_val.str, 0);
642  break;
643  case AV_OPT_TYPE_BINARY:
644  /* Cannot set default for binary */
645  break;
646  default:
647  av_log(s, AV_LOG_DEBUG, "AVOption type %d of option %s not implemented yet\n", opt->type, opt->name);
648  }
649  }
650 }
651 
669 static int parse_key_value_pair(void *ctx, const char **buf,
670  const char *key_val_sep, const char *pairs_sep)
671 {
672  char *key = av_get_token(buf, key_val_sep);
673  char *val;
674  int ret;
675 
676  if (*key && strspn(*buf, key_val_sep)) {
677  (*buf)++;
678  val = av_get_token(buf, pairs_sep);
679  } else {
680  av_log(ctx, AV_LOG_ERROR, "Missing key or no key/value separator found after key '%s'\n", key);
681  av_free(key);
682  return AVERROR(EINVAL);
683  }
684 
685  av_log(ctx, AV_LOG_DEBUG, "Setting value '%s' for key '%s'\n", val, key);
686 
687  ret = av_opt_set(ctx, key, val, 0);
688  if (ret == AVERROR_OPTION_NOT_FOUND)
689  av_log(ctx, AV_LOG_ERROR, "Key '%s' not found.\n", key);
690 
691  av_free(key);
692  av_free(val);
693  return ret;
694 }
695 
696 int av_set_options_string(void *ctx, const char *opts,
697  const char *key_val_sep, const char *pairs_sep)
698 {
699  int ret, count = 0;
700 
701  if (!opts)
702  return 0;
703 
704  while (*opts) {
705  if ((ret = parse_key_value_pair(ctx, &opts, key_val_sep, pairs_sep)) < 0)
706  return ret;
707  count++;
708 
709  if (*opts)
710  opts++;
711  }
712 
713  return count;
714 }
715 
716 void av_opt_free(void *obj)
717 {
718  const AVOption *o = NULL;
719  while ((o = av_opt_next(obj, o)))
720  if (o->type == AV_OPT_TYPE_STRING || o->type == AV_OPT_TYPE_BINARY)
721  av_freep((uint8_t *)obj + o->offset);
722 }
723 
725 {
727  AVDictionary *tmp = NULL;
728  int ret = 0;
729 
730  while ((t = av_dict_get(*options, "", t, AV_DICT_IGNORE_SUFFIX))) {
731  ret = av_opt_set(obj, t->key, t->value, 0);
732  if (ret == AVERROR_OPTION_NOT_FOUND)
733  av_dict_set(&tmp, t->key, t->value, 0);
734  else if (ret < 0) {
735  av_log(obj, AV_LOG_ERROR, "Error setting option %s to value %s.\n", t->key, t->value);
736  break;
737  }
738  ret = 0;
739  }
740  av_dict_free(options);
741  *options = tmp;
742  return ret;
743 }
744 
745 const AVOption *av_opt_find(void *obj, const char *name, const char *unit,
746  int opt_flags, int search_flags)
747 {
748  return av_opt_find2(obj, name, unit, opt_flags, search_flags, NULL);
749 }
750 
751 const AVOption *av_opt_find2(void *obj, const char *name, const char *unit,
752  int opt_flags, int search_flags, void **target_obj)
753 {
754  const AVClass *c = *(AVClass**)obj;
755  const AVOption *o = NULL;
756 
757  if (search_flags & AV_OPT_SEARCH_CHILDREN) {
758  if (search_flags & AV_OPT_SEARCH_FAKE_OBJ) {
759  const AVClass *child = NULL;
760  while (child = av_opt_child_class_next(c, child))
761  if (o = av_opt_find2(&child, name, unit, opt_flags, search_flags, NULL))
762  return o;
763  } else {
764  void *child = NULL;
765  while (child = av_opt_child_next(obj, child))
766  if (o = av_opt_find2(child, name, unit, opt_flags, search_flags, target_obj))
767  return o;
768  }
769  }
770 
771  while (o = av_opt_next(obj, o)) {
772  if (!strcmp(o->name, name) && (o->flags & opt_flags) == opt_flags &&
773  ((!unit && o->type != AV_OPT_TYPE_CONST) ||
774  (unit && o->unit && !strcmp(o->unit, unit)))) {
775  if (target_obj) {
776  if (!(search_flags & AV_OPT_SEARCH_FAKE_OBJ))
777  *target_obj = obj;
778  else
779  *target_obj = NULL;
780  }
781  return o;
782  }
783  }
784  return NULL;
785 }
786 
787 void *av_opt_child_next(void *obj, void *prev)
788 {
789  const AVClass *c = *(AVClass**)obj;
790  if (c->child_next)
791  return c->child_next(obj, prev);
792  return NULL;
793 }
794 
795 const AVClass *av_opt_child_class_next(const AVClass *parent, const AVClass *prev)
796 {
797  if (parent->child_class_next)
798  return parent->child_class_next(prev);
799  return NULL;
800 }
801 
802 #ifdef TEST
803 
804 #undef printf
805 
806 typedef struct TestContext
807 {
808  const AVClass *class;
809  int num;
810  int toggle;
811  char *string;
812  int flags;
813  AVRational rational;
814 } TestContext;
815 
816 #define OFFSET(x) offsetof(TestContext, x)
817 
818 #define TEST_FLAG_COOL 01
819 #define TEST_FLAG_LAME 02
820 #define TEST_FLAG_MU 04
821 
822 static const AVOption test_options[]= {
823 {"num", "set num", OFFSET(num), AV_OPT_TYPE_INT, {0}, 0, 100 },
824 {"toggle", "set toggle", OFFSET(toggle), AV_OPT_TYPE_INT, {0}, 0, 1 },
825 {"rational", "set rational", OFFSET(rational), AV_OPT_TYPE_RATIONAL, {0}, 0, 10 },
826 {"string", "set string", OFFSET(string), AV_OPT_TYPE_STRING, {0}, CHAR_MIN, CHAR_MAX },
827 {"flags", "set flags", OFFSET(flags), AV_OPT_TYPE_FLAGS, {0}, 0, INT_MAX, 0, "flags" },
828 {"cool", "set cool flag ", 0, AV_OPT_TYPE_CONST, {TEST_FLAG_COOL}, INT_MIN, INT_MAX, 0, "flags" },
829 {"lame", "set lame flag ", 0, AV_OPT_TYPE_CONST, {TEST_FLAG_LAME}, INT_MIN, INT_MAX, 0, "flags" },
830 {"mu", "set mu flag ", 0, AV_OPT_TYPE_CONST, {TEST_FLAG_MU}, INT_MIN, INT_MAX, 0, "flags" },
831 {NULL},
832 };
833 
834 static const char *test_get_name(void *ctx)
835 {
836  return "test";
837 }
838 
839 static const AVClass test_class = {
840  "TestContext",
841  test_get_name,
842  test_options
843 };
844 
845 int main(void)
846 {
847  int i;
848 
849  printf("\nTesting av_set_options_string()\n");
850  {
851  TestContext test_ctx;
852  const char *options[] = {
853  "",
854  ":",
855  "=",
856  "foo=:",
857  ":=foo",
858  "=foo",
859  "foo=",
860  "foo",
861  "foo=val",
862  "foo==val",
863  "toggle=:",
864  "string=:",
865  "toggle=1 : foo",
866  "toggle=100",
867  "toggle==1",
868  "flags=+mu-lame : num=42: toggle=0",
869  "num=42 : string=blahblah",
870  "rational=0 : rational=1/2 : rational=1/-1",
871  "rational=-1/0",
872  };
873 
874  test_ctx.class = &test_class;
875  av_opt_set_defaults(&test_ctx);
876  test_ctx.string = av_strdup("default");
877 
879 
880  for (i=0; i < FF_ARRAY_ELEMS(options); i++) {
881  av_log(&test_ctx, AV_LOG_DEBUG, "Setting options string '%s'\n", options[i]);
882  if (av_set_options_string(&test_ctx, options[i], "=", ":") < 0)
883  av_log(&test_ctx, AV_LOG_ERROR, "Error setting options string: '%s'\n", options[i]);
884  printf("\n");
885  }
886  }
887 
888  return 0;
889 }
890 
891 #endif