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