00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00028 #include "avutil.h"
00029 #include "avstring.h"
00030 #include "opt.h"
00031 #include "eval.h"
00032 #include "dict.h"
00033 #include "log.h"
00034
00035 #if FF_API_FIND_OPT
00036
00037 const AVOption *av_find_opt(void *v, const char *name, const char *unit, int mask, int flags)
00038 {
00039 AVClass *c= *(AVClass**)v;
00040 const AVOption *o= c->option;
00041
00042 for (; o && o->name; o++) {
00043 if (!strcmp(o->name, name) && (!unit || (o->unit && !strcmp(o->unit, unit))) && (o->flags & mask) == flags)
00044 return o;
00045 }
00046 return NULL;
00047 }
00048 #endif
00049
00050 #if FF_API_OLD_AVOPTIONS
00051 const AVOption *av_next_option(void *obj, const AVOption *last)
00052 {
00053 return av_opt_next(obj, last);
00054 }
00055 #endif
00056
00057 const AVOption *av_opt_next(void *obj, const AVOption *last)
00058 {
00059 AVClass *class = *(AVClass**)obj;
00060 if (!last && class->option && class->option[0].name)
00061 return class->option;
00062 if (last && last[1].name)
00063 return ++last;
00064 return NULL;
00065 }
00066
00067 static int read_number(const AVOption *o, void *dst, double *num, int *den, int64_t *intnum)
00068 {
00069 switch (o->type) {
00070 case AV_OPT_TYPE_FLAGS: *intnum = *(unsigned int*)dst;return 0;
00071 case AV_OPT_TYPE_INT: *intnum = *(int *)dst;return 0;
00072 case AV_OPT_TYPE_INT64: *intnum = *(int64_t *)dst;return 0;
00073 case AV_OPT_TYPE_FLOAT: *num = *(float *)dst;return 0;
00074 case AV_OPT_TYPE_DOUBLE: *num = *(double *)dst;return 0;
00075 case AV_OPT_TYPE_RATIONAL: *intnum = ((AVRational*)dst)->num;
00076 *den = ((AVRational*)dst)->den;
00077 return 0;
00078 }
00079 return AVERROR(EINVAL);
00080 }
00081
00082 static int write_number(void *obj, const AVOption *o, void *dst, double num, int den, int64_t intnum)
00083 {
00084 if (o->max*den < num*intnum || o->min*den > num*intnum) {
00085 av_log(obj, AV_LOG_ERROR, "Value %lf for parameter '%s' out of range\n", num, o->name);
00086 return AVERROR(ERANGE);
00087 }
00088
00089 switch (o->type) {
00090 case AV_OPT_TYPE_FLAGS:
00091 case AV_OPT_TYPE_INT: *(int *)dst= llrint(num/den)*intnum; break;
00092 case AV_OPT_TYPE_INT64: *(int64_t *)dst= llrint(num/den)*intnum; break;
00093 case AV_OPT_TYPE_FLOAT: *(float *)dst= num*intnum/den; break;
00094 case AV_OPT_TYPE_DOUBLE:*(double *)dst= num*intnum/den; break;
00095 case AV_OPT_TYPE_RATIONAL:
00096 if ((int)num == num) *(AVRational*)dst= (AVRational){num*intnum, den};
00097 else *(AVRational*)dst= av_d2q(num*intnum/den, 1<<24);
00098 break;
00099 default:
00100 return AVERROR(EINVAL);
00101 }
00102 return 0;
00103 }
00104
00105 static const double const_values[] = {
00106 M_PI,
00107 M_E,
00108 FF_QP2LAMBDA,
00109 0
00110 };
00111
00112 static const char * const const_names[] = {
00113 "PI",
00114 "E",
00115 "QP2LAMBDA",
00116 0
00117 };
00118
00119 static int hexchar2int(char c) {
00120 if (c >= '0' && c <= '9') return c - '0';
00121 if (c >= 'a' && c <= 'f') return c - 'a' + 10;
00122 if (c >= 'A' && c <= 'F') return c - 'A' + 10;
00123 return -1;
00124 }
00125
00126 static int set_string_binary(void *obj, const AVOption *o, const char *val, uint8_t **dst)
00127 {
00128 int *lendst = (int *)(dst + 1);
00129 uint8_t *bin, *ptr;
00130 int len = strlen(val);
00131
00132 av_freep(dst);
00133 *lendst = 0;
00134
00135 if (len & 1)
00136 return AVERROR(EINVAL);
00137 len /= 2;
00138
00139 ptr = bin = av_malloc(len);
00140 while (*val) {
00141 int a = hexchar2int(*val++);
00142 int b = hexchar2int(*val++);
00143 if (a < 0 || b < 0) {
00144 av_free(bin);
00145 return AVERROR(EINVAL);
00146 }
00147 *ptr++ = (a << 4) | b;
00148 }
00149 *dst = bin;
00150 *lendst = len;
00151
00152 return 0;
00153 }
00154
00155 static int set_string(void *obj, const AVOption *o, const char *val, uint8_t **dst)
00156 {
00157 av_freep(dst);
00158 *dst = av_strdup(val);
00159 return 0;
00160 }
00161
00162 static int set_string_number(void *obj, const AVOption *o, const char *val, void *dst)
00163 {
00164 int ret = 0, notfirst = 0;
00165 for (;;) {
00166 int i, den = 1;
00167 char buf[256];
00168 int cmd = 0;
00169 double d, num = 1;
00170 int64_t intnum = 1;
00171
00172 if (*val == '+' || *val == '-')
00173 cmd = *(val++);
00174
00175 for (i = 0; i < sizeof(buf) - 1 && val[i] && val[i] != '+' && val[i] != '-'; i++)
00176 buf[i] = val[i];
00177 buf[i] = 0;
00178
00179 {
00180 const AVOption *o_named = av_opt_find(obj, buf, o->unit, 0, 0);
00181 if (o_named && o_named->type == AV_OPT_TYPE_CONST)
00182 d = o_named->default_val.dbl;
00183 else if (!strcmp(buf, "default")) d = o->default_val.dbl;
00184 else if (!strcmp(buf, "max" )) d = o->max;
00185 else if (!strcmp(buf, "min" )) d = o->min;
00186 else if (!strcmp(buf, "none" )) d = 0;
00187 else if (!strcmp(buf, "all" )) d = ~0;
00188 else {
00189 int res = av_expr_parse_and_eval(&d, buf, const_names, const_values, NULL, NULL, NULL, NULL, NULL, 0, obj);
00190 if (res < 0) {
00191 av_log(obj, AV_LOG_ERROR, "Unable to parse option value \"%s\"\n", val);
00192 return res;
00193 }
00194 }
00195 }
00196 if (o->type == AV_OPT_TYPE_FLAGS) {
00197 read_number(o, dst, NULL, NULL, &intnum);
00198 if (cmd == '+') d = intnum | (int64_t)d;
00199 else if (cmd == '-') d = intnum &~(int64_t)d;
00200 } else {
00201 read_number(o, dst, &num, &den, &intnum);
00202 if (cmd == '+') d = notfirst*num*intnum/den + d;
00203 else if (cmd == '-') d = notfirst*num*intnum/den - d;
00204 }
00205
00206 if ((ret = write_number(obj, o, dst, d, 1, 1)) < 0)
00207 return ret;
00208 val += i;
00209 if (!*val)
00210 return 0;
00211 notfirst = 1;
00212 }
00213
00214 return 0;
00215 }
00216
00217 #if FF_API_OLD_AVOPTIONS
00218 int av_set_string3(void *obj, const char *name, const char *val, int alloc, const AVOption **o_out)
00219 {
00220 const AVOption *o = av_opt_find(obj, name, NULL, 0, 0);
00221 if (o_out)
00222 *o_out = o;
00223 return av_opt_set(obj, name, val, 0);
00224 }
00225 #endif
00226
00227 int av_opt_set(void *obj, const char *name, const char *val, int search_flags)
00228 {
00229 void *dst, *target_obj;
00230 const AVOption *o = av_opt_find2(obj, name, NULL, 0, search_flags, &target_obj);
00231 if (!o || !target_obj)
00232 return AVERROR_OPTION_NOT_FOUND;
00233 if (!val)
00234 return AVERROR(EINVAL);
00235
00236 dst = ((uint8_t*)target_obj) + o->offset;
00237 switch (o->type) {
00238 case AV_OPT_TYPE_STRING: return set_string(obj, o, val, dst);
00239 case AV_OPT_TYPE_BINARY: return set_string_binary(obj, o, val, dst);
00240 case AV_OPT_TYPE_FLAGS:
00241 case AV_OPT_TYPE_INT:
00242 case AV_OPT_TYPE_INT64:
00243 case AV_OPT_TYPE_FLOAT:
00244 case AV_OPT_TYPE_DOUBLE:
00245 case AV_OPT_TYPE_RATIONAL: return set_string_number(obj, o, val, dst);
00246 }
00247
00248 av_log(obj, AV_LOG_ERROR, "Invalid option type.\n");
00249 return AVERROR(EINVAL);
00250 }
00251
00252 #define OPT_EVAL_NUMBER(name, opttype, vartype)\
00253 int av_opt_eval_ ## name(void *obj, const AVOption *o, const char *val, vartype *name ## _out)\
00254 {\
00255 if (!o || o->type != opttype)\
00256 return AVERROR(EINVAL);\
00257 return set_string_number(obj, o, val, name ## _out);\
00258 }
00259
00260 OPT_EVAL_NUMBER(flags, AV_OPT_TYPE_FLAGS, int)
00261 OPT_EVAL_NUMBER(int, AV_OPT_TYPE_INT, int)
00262 OPT_EVAL_NUMBER(int64, AV_OPT_TYPE_INT64, int64_t)
00263 OPT_EVAL_NUMBER(float, AV_OPT_TYPE_FLOAT, float)
00264 OPT_EVAL_NUMBER(double, AV_OPT_TYPE_DOUBLE, double)
00265 OPT_EVAL_NUMBER(q, AV_OPT_TYPE_RATIONAL, AVRational)
00266
00267 static int set_number(void *obj, const char *name, double num, int den, int64_t intnum,
00268 int search_flags)
00269 {
00270 void *dst, *target_obj;
00271 const AVOption *o = av_opt_find2(obj, name, NULL, 0, search_flags, &target_obj);
00272
00273 if (!o || !target_obj)
00274 return AVERROR_OPTION_NOT_FOUND;
00275
00276 dst = ((uint8_t*)target_obj) + o->offset;
00277 return write_number(obj, o, dst, num, den, intnum);
00278 }
00279
00280 #if FF_API_OLD_AVOPTIONS
00281 const AVOption *av_set_double(void *obj, const char *name, double n)
00282 {
00283 const AVOption *o = av_opt_find(obj, name, NULL, 0, 0);
00284 if (set_number(obj, name, n, 1, 1, 0) < 0)
00285 return NULL;
00286 return o;
00287 }
00288
00289 const AVOption *av_set_q(void *obj, const char *name, AVRational n)
00290 {
00291 const AVOption *o = av_opt_find(obj, name, NULL, 0, 0);
00292 if (set_number(obj, name, n.num, n.den, 1, 0) < 0)
00293 return NULL;
00294 return o;
00295 }
00296
00297 const AVOption *av_set_int(void *obj, const char *name, int64_t n)
00298 {
00299 const AVOption *o = av_opt_find(obj, name, NULL, 0, 0);
00300 if (set_number(obj, name, 1, 1, n, 0) < 0)
00301 return NULL;
00302 return o;
00303 }
00304 #endif
00305
00306 int av_opt_set_int(void *obj, const char *name, int64_t val, int search_flags)
00307 {
00308 return set_number(obj, name, 1, 1, val, search_flags);
00309 }
00310
00311 int av_opt_set_double(void *obj, const char *name, double val, int search_flags)
00312 {
00313 return set_number(obj, name, val, 1, 1, search_flags);
00314 }
00315
00316 int av_opt_set_q(void *obj, const char *name, AVRational val, int search_flags)
00317 {
00318 return set_number(obj, name, val.num, val.den, 1, search_flags);
00319 }
00320
00321 #if FF_API_OLD_AVOPTIONS
00322
00327 const char *av_get_string(void *obj, const char *name, const AVOption **o_out, char *buf, int buf_len)
00328 {
00329 const AVOption *o = av_opt_find(obj, name, NULL, 0, 0);
00330 void *dst;
00331 uint8_t *bin;
00332 int len, i;
00333 if (!o)
00334 return NULL;
00335 if (o->type != AV_OPT_TYPE_STRING && (!buf || !buf_len))
00336 return NULL;
00337
00338 dst= ((uint8_t*)obj) + o->offset;
00339 if (o_out) *o_out= o;
00340
00341 switch (o->type) {
00342 case AV_OPT_TYPE_FLAGS: snprintf(buf, buf_len, "0x%08X",*(int *)dst);break;
00343 case AV_OPT_TYPE_INT: snprintf(buf, buf_len, "%d" , *(int *)dst);break;
00344 case AV_OPT_TYPE_INT64: snprintf(buf, buf_len, "%"PRId64, *(int64_t*)dst);break;
00345 case AV_OPT_TYPE_FLOAT: snprintf(buf, buf_len, "%f" , *(float *)dst);break;
00346 case AV_OPT_TYPE_DOUBLE: snprintf(buf, buf_len, "%f" , *(double *)dst);break;
00347 case AV_OPT_TYPE_RATIONAL: snprintf(buf, buf_len, "%d/%d", ((AVRational*)dst)->num, ((AVRational*)dst)->den);break;
00348 case AV_OPT_TYPE_STRING: return *(void**)dst;
00349 case AV_OPT_TYPE_BINARY:
00350 len = *(int*)(((uint8_t *)dst) + sizeof(uint8_t *));
00351 if (len >= (buf_len + 1)/2) return NULL;
00352 bin = *(uint8_t**)dst;
00353 for (i = 0; i < len; i++) snprintf(buf + i*2, 3, "%02X", bin[i]);
00354 break;
00355 default: return NULL;
00356 }
00357 return buf;
00358 }
00359 #endif
00360
00361 int av_opt_get(void *obj, const char *name, int search_flags, uint8_t **out_val)
00362 {
00363 void *dst, *target_obj;
00364 const AVOption *o = av_opt_find2(obj, name, NULL, 0, search_flags, &target_obj);
00365 uint8_t *bin, buf[128];
00366 int len, i, ret;
00367
00368 if (!o || !target_obj)
00369 return AVERROR_OPTION_NOT_FOUND;
00370
00371 dst = (uint8_t*)target_obj + o->offset;
00372
00373 buf[0] = 0;
00374 switch (o->type) {
00375 case AV_OPT_TYPE_FLAGS: ret = snprintf(buf, sizeof(buf), "0x%08X", *(int *)dst);break;
00376 case AV_OPT_TYPE_INT: ret = snprintf(buf, sizeof(buf), "%d" , *(int *)dst);break;
00377 case AV_OPT_TYPE_INT64: ret = snprintf(buf, sizeof(buf), "%"PRId64, *(int64_t*)dst);break;
00378 case AV_OPT_TYPE_FLOAT: ret = snprintf(buf, sizeof(buf), "%f" , *(float *)dst);break;
00379 case AV_OPT_TYPE_DOUBLE: ret = snprintf(buf, sizeof(buf), "%f" , *(double *)dst);break;
00380 case AV_OPT_TYPE_RATIONAL: ret = snprintf(buf, sizeof(buf), "%d/%d", ((AVRational*)dst)->num, ((AVRational*)dst)->den);break;
00381 case AV_OPT_TYPE_STRING:
00382 if (*(uint8_t**)dst)
00383 *out_val = av_strdup(*(uint8_t**)dst);
00384 else
00385 *out_val = av_strdup("");
00386 return 0;
00387 case AV_OPT_TYPE_BINARY:
00388 len = *(int*)(((uint8_t *)dst) + sizeof(uint8_t *));
00389 if ((uint64_t)len*2 + 1 > INT_MAX)
00390 return AVERROR(EINVAL);
00391 if (!(*out_val = av_malloc(len*2 + 1)))
00392 return AVERROR(ENOMEM);
00393 bin = *(uint8_t**)dst;
00394 for (i = 0; i < len; i++)
00395 snprintf(*out_val + i*2, 3, "%02X", bin[i]);
00396 return 0;
00397 default:
00398 return AVERROR(EINVAL);
00399 }
00400
00401 if (ret >= sizeof(buf))
00402 return AVERROR(EINVAL);
00403 *out_val = av_strdup(buf);
00404 return 0;
00405 }
00406
00407 static int get_number(void *obj, const char *name, const AVOption **o_out, double *num, int *den, int64_t *intnum,
00408 int search_flags)
00409 {
00410 void *dst, *target_obj;
00411 const AVOption *o = av_opt_find2(obj, name, NULL, 0, search_flags, &target_obj);
00412 if (!o || !target_obj)
00413 goto error;
00414
00415 dst = ((uint8_t*)target_obj) + o->offset;
00416
00417 if (o_out) *o_out= o;
00418
00419 return read_number(o, dst, num, den, intnum);
00420
00421 error:
00422 *den=*intnum=0;
00423 return -1;
00424 }
00425
00426 #if FF_API_OLD_AVOPTIONS
00427 double av_get_double(void *obj, const char *name, const AVOption **o_out)
00428 {
00429 int64_t intnum=1;
00430 double num=1;
00431 int den=1;
00432
00433 if (get_number(obj, name, o_out, &num, &den, &intnum, 0) < 0)
00434 return NAN;
00435 return num*intnum/den;
00436 }
00437
00438 AVRational av_get_q(void *obj, const char *name, const AVOption **o_out)
00439 {
00440 int64_t intnum=1;
00441 double num=1;
00442 int den=1;
00443
00444 if (get_number(obj, name, o_out, &num, &den, &intnum, 0) < 0)
00445 return (AVRational){0, 0};
00446 if (num == 1.0 && (int)intnum == intnum)
00447 return (AVRational){intnum, den};
00448 else
00449 return av_d2q(num*intnum/den, 1<<24);
00450 }
00451
00452 int64_t av_get_int(void *obj, const char *name, const AVOption **o_out)
00453 {
00454 int64_t intnum=1;
00455 double num=1;
00456 int den=1;
00457
00458 if (get_number(obj, name, o_out, &num, &den, &intnum, 0) < 0)
00459 return -1;
00460 return num*intnum/den;
00461 }
00462 #endif
00463
00464 int av_opt_get_int(void *obj, const char *name, int search_flags, int64_t *out_val)
00465 {
00466 int64_t intnum = 1;
00467 double num = 1;
00468 int ret, den = 1;
00469
00470 if ((ret = get_number(obj, name, NULL, &num, &den, &intnum, search_flags)) < 0)
00471 return ret;
00472 *out_val = num*intnum/den;
00473 return 0;
00474 }
00475
00476 int av_opt_get_double(void *obj, const char *name, int search_flags, double *out_val)
00477 {
00478 int64_t intnum = 1;
00479 double num = 1;
00480 int ret, den = 1;
00481
00482 if ((ret = get_number(obj, name, NULL, &num, &den, &intnum, search_flags)) < 0)
00483 return ret;
00484 *out_val = num*intnum/den;
00485 return 0;
00486 }
00487
00488 int av_opt_get_q(void *obj, const char *name, int search_flags, AVRational *out_val)
00489 {
00490 int64_t intnum = 1;
00491 double num = 1;
00492 int ret, den = 1;
00493
00494 if ((ret = get_number(obj, name, NULL, &num, &den, &intnum, search_flags)) < 0)
00495 return ret;
00496
00497 if (num == 1.0 && (int)intnum == intnum)
00498 *out_val = (AVRational){intnum, den};
00499 else
00500 *out_val = av_d2q(num*intnum/den, 1<<24);
00501 return 0;
00502 }
00503
00504 int av_opt_flag_is_set(void *obj, const char *field_name, const char *flag_name)
00505 {
00506 const AVOption *field = av_opt_find(obj, field_name, NULL, 0, 0);
00507 const AVOption *flag = av_opt_find(obj, flag_name,
00508 field ? field->unit : NULL, 0, 0);
00509 int64_t res;
00510
00511 if (!field || !flag || flag->type != AV_OPT_TYPE_CONST ||
00512 av_opt_get_int(obj, field_name, 0, &res) < 0)
00513 return 0;
00514 return res & (int) flag->default_val.dbl;
00515 }
00516
00517 static void opt_list(void *obj, void *av_log_obj, const char *unit,
00518 int req_flags, int rej_flags)
00519 {
00520 const AVOption *opt=NULL;
00521
00522 while ((opt = av_opt_next(obj, opt))) {
00523 if (!(opt->flags & req_flags) || (opt->flags & rej_flags))
00524 continue;
00525
00526
00527
00528
00529
00530 if (!unit && opt->type==AV_OPT_TYPE_CONST)
00531 continue;
00532 else if (unit && opt->type!=AV_OPT_TYPE_CONST)
00533 continue;
00534 else if (unit && opt->type==AV_OPT_TYPE_CONST && strcmp(unit, opt->unit))
00535 continue;
00536 else if (unit && opt->type == AV_OPT_TYPE_CONST)
00537 av_log(av_log_obj, AV_LOG_INFO, " %-15s ", opt->name);
00538 else
00539 av_log(av_log_obj, AV_LOG_INFO, "-%-17s ", opt->name);
00540
00541 switch (opt->type) {
00542 case AV_OPT_TYPE_FLAGS:
00543 av_log(av_log_obj, AV_LOG_INFO, "%-7s ", "<flags>");
00544 break;
00545 case AV_OPT_TYPE_INT:
00546 av_log(av_log_obj, AV_LOG_INFO, "%-7s ", "<int>");
00547 break;
00548 case AV_OPT_TYPE_INT64:
00549 av_log(av_log_obj, AV_LOG_INFO, "%-7s ", "<int64>");
00550 break;
00551 case AV_OPT_TYPE_DOUBLE:
00552 av_log(av_log_obj, AV_LOG_INFO, "%-7s ", "<double>");
00553 break;
00554 case AV_OPT_TYPE_FLOAT:
00555 av_log(av_log_obj, AV_LOG_INFO, "%-7s ", "<float>");
00556 break;
00557 case AV_OPT_TYPE_STRING:
00558 av_log(av_log_obj, AV_LOG_INFO, "%-7s ", "<string>");
00559 break;
00560 case AV_OPT_TYPE_RATIONAL:
00561 av_log(av_log_obj, AV_LOG_INFO, "%-7s ", "<rational>");
00562 break;
00563 case AV_OPT_TYPE_BINARY:
00564 av_log(av_log_obj, AV_LOG_INFO, "%-7s ", "<binary>");
00565 break;
00566 case AV_OPT_TYPE_CONST:
00567 default:
00568 av_log(av_log_obj, AV_LOG_INFO, "%-7s ", "");
00569 break;
00570 }
00571 av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_ENCODING_PARAM) ? 'E' : '.');
00572 av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_DECODING_PARAM) ? 'D' : '.');
00573 av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_VIDEO_PARAM ) ? 'V' : '.');
00574 av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_AUDIO_PARAM ) ? 'A' : '.');
00575 av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_SUBTITLE_PARAM) ? 'S' : '.');
00576
00577 if (opt->help)
00578 av_log(av_log_obj, AV_LOG_INFO, " %s", opt->help);
00579 av_log(av_log_obj, AV_LOG_INFO, "\n");
00580 if (opt->unit && opt->type != AV_OPT_TYPE_CONST) {
00581 opt_list(obj, av_log_obj, opt->unit, req_flags, rej_flags);
00582 }
00583 }
00584 }
00585
00586 int av_opt_show2(void *obj, void *av_log_obj, int req_flags, int rej_flags)
00587 {
00588 if (!obj)
00589 return -1;
00590
00591 av_log(av_log_obj, AV_LOG_INFO, "%s AVOptions:\n", (*(AVClass**)obj)->class_name);
00592
00593 opt_list(obj, av_log_obj, NULL, req_flags, rej_flags);
00594
00595 return 0;
00596 }
00597
00598 void av_opt_set_defaults(void *s)
00599 {
00600 #if FF_API_OLD_AVOPTIONS
00601 av_opt_set_defaults2(s, 0, 0);
00602 }
00603
00604 void av_opt_set_defaults2(void *s, int mask, int flags)
00605 {
00606 #endif
00607 const AVOption *opt = NULL;
00608 while ((opt = av_opt_next(s, opt)) != NULL) {
00609 #if FF_API_OLD_AVOPTIONS
00610 if ((opt->flags & mask) != flags)
00611 continue;
00612 #endif
00613 switch (opt->type) {
00614 case AV_OPT_TYPE_CONST:
00615
00616 break;
00617 case AV_OPT_TYPE_FLAGS:
00618 case AV_OPT_TYPE_INT: {
00619 int val;
00620 val = opt->default_val.dbl;
00621 av_opt_set_int(s, opt->name, val, 0);
00622 }
00623 break;
00624 case AV_OPT_TYPE_INT64:
00625 if ((double)(opt->default_val.dbl+0.6) == opt->default_val.dbl)
00626 av_log(s, AV_LOG_DEBUG, "loss of precision in default of %s\n", opt->name);
00627 av_opt_set_int(s, opt->name, opt->default_val.dbl, 0);
00628 break;
00629 case AV_OPT_TYPE_DOUBLE:
00630 case AV_OPT_TYPE_FLOAT: {
00631 double val;
00632 val = opt->default_val.dbl;
00633 av_opt_set_double(s, opt->name, val, 0);
00634 }
00635 break;
00636 case AV_OPT_TYPE_RATIONAL: {
00637 AVRational val;
00638 val = av_d2q(opt->default_val.dbl, INT_MAX);
00639 av_opt_set_q(s, opt->name, val, 0);
00640 }
00641 break;
00642 case AV_OPT_TYPE_STRING:
00643 av_opt_set(s, opt->name, opt->default_val.str, 0);
00644 break;
00645 case AV_OPT_TYPE_BINARY:
00646
00647 break;
00648 default:
00649 av_log(s, AV_LOG_DEBUG, "AVOption type %d of option %s not implemented yet\n", opt->type, opt->name);
00650 }
00651 }
00652 }
00653
00671 static int parse_key_value_pair(void *ctx, const char **buf,
00672 const char *key_val_sep, const char *pairs_sep)
00673 {
00674 char *key = av_get_token(buf, key_val_sep);
00675 char *val;
00676 int ret;
00677
00678 if (*key && strspn(*buf, key_val_sep)) {
00679 (*buf)++;
00680 val = av_get_token(buf, pairs_sep);
00681 } else {
00682 av_log(ctx, AV_LOG_ERROR, "Missing key or no key/value separator found after key '%s'\n", key);
00683 av_free(key);
00684 return AVERROR(EINVAL);
00685 }
00686
00687 av_log(ctx, AV_LOG_DEBUG, "Setting value '%s' for key '%s'\n", val, key);
00688
00689 ret = av_opt_set(ctx, key, val, 0);
00690 if (ret == AVERROR_OPTION_NOT_FOUND)
00691 av_log(ctx, AV_LOG_ERROR, "Key '%s' not found.\n", key);
00692
00693 av_free(key);
00694 av_free(val);
00695 return ret;
00696 }
00697
00698 int av_set_options_string(void *ctx, const char *opts,
00699 const char *key_val_sep, const char *pairs_sep)
00700 {
00701 int ret, count = 0;
00702
00703 if (!opts)
00704 return 0;
00705
00706 while (*opts) {
00707 if ((ret = parse_key_value_pair(ctx, &opts, key_val_sep, pairs_sep)) < 0)
00708 return ret;
00709 count++;
00710
00711 if (*opts)
00712 opts++;
00713 }
00714
00715 return count;
00716 }
00717
00718 void av_opt_free(void *obj)
00719 {
00720 const AVOption *o = NULL;
00721 while ((o = av_opt_next(obj, o)))
00722 if (o->type == AV_OPT_TYPE_STRING || o->type == AV_OPT_TYPE_BINARY)
00723 av_freep((uint8_t *)obj + o->offset);
00724 }
00725
00726 int av_opt_set_dict(void *obj, AVDictionary **options)
00727 {
00728 AVDictionaryEntry *t = NULL;
00729 AVDictionary *tmp = NULL;
00730 int ret = 0;
00731
00732 while ((t = av_dict_get(*options, "", t, AV_DICT_IGNORE_SUFFIX))) {
00733 ret = av_opt_set(obj, t->key, t->value, 0);
00734 if (ret == AVERROR_OPTION_NOT_FOUND)
00735 av_dict_set(&tmp, t->key, t->value, 0);
00736 else if (ret < 0) {
00737 av_log(obj, AV_LOG_ERROR, "Error setting option %s to value %s.\n", t->key, t->value);
00738 break;
00739 }
00740 ret = 0;
00741 }
00742 av_dict_free(options);
00743 *options = tmp;
00744 return ret;
00745 }
00746
00747 const AVOption *av_opt_find(void *obj, const char *name, const char *unit,
00748 int opt_flags, int search_flags)
00749 {
00750 return av_opt_find2(obj, name, unit, opt_flags, search_flags, NULL);
00751 }
00752
00753 const AVOption *av_opt_find2(void *obj, const char *name, const char *unit,
00754 int opt_flags, int search_flags, void **target_obj)
00755 {
00756 const AVClass *c = *(AVClass**)obj;
00757 const AVOption *o = NULL;
00758
00759 if (search_flags & AV_OPT_SEARCH_CHILDREN) {
00760 if (search_flags & AV_OPT_SEARCH_FAKE_OBJ) {
00761 const AVClass *child = NULL;
00762 while (child = av_opt_child_class_next(c, child))
00763 if (o = av_opt_find2(&child, name, unit, opt_flags, search_flags, NULL))
00764 return o;
00765 } else {
00766 void *child = NULL;
00767 while (child = av_opt_child_next(obj, child))
00768 if (o = av_opt_find2(child, name, unit, opt_flags, search_flags, target_obj))
00769 return o;
00770 }
00771 }
00772
00773 while (o = av_opt_next(obj, o)) {
00774 if (!strcmp(o->name, name) && (o->flags & opt_flags) == opt_flags &&
00775 ((!unit && o->type != AV_OPT_TYPE_CONST) ||
00776 (unit && o->unit && !strcmp(o->unit, unit)))) {
00777 if (target_obj) {
00778 if (!(search_flags & AV_OPT_SEARCH_FAKE_OBJ))
00779 *target_obj = obj;
00780 else
00781 *target_obj = NULL;
00782 }
00783 return o;
00784 }
00785 }
00786 return NULL;
00787 }
00788
00789 void *av_opt_child_next(void *obj, void *prev)
00790 {
00791 const AVClass *c = *(AVClass**)obj;
00792 if (c->child_next)
00793 return c->child_next(obj, prev);
00794 return NULL;
00795 }
00796
00797 const AVClass *av_opt_child_class_next(const AVClass *parent, const AVClass *prev)
00798 {
00799 if (parent->child_class_next)
00800 return parent->child_class_next(prev);
00801 return NULL;
00802 }
00803
00804 #ifdef TEST
00805
00806 #undef printf
00807
00808 typedef struct TestContext
00809 {
00810 const AVClass *class;
00811 int num;
00812 int toggle;
00813 char *string;
00814 int flags;
00815 AVRational rational;
00816 } TestContext;
00817
00818 #define OFFSET(x) offsetof(TestContext, x)
00819
00820 #define TEST_FLAG_COOL 01
00821 #define TEST_FLAG_LAME 02
00822 #define TEST_FLAG_MU 04
00823
00824 static const AVOption test_options[]= {
00825 {"num", "set num", OFFSET(num), AV_OPT_TYPE_INT, {0}, 0, 100 },
00826 {"toggle", "set toggle", OFFSET(toggle), AV_OPT_TYPE_INT, {0}, 0, 1 },
00827 {"rational", "set rational", OFFSET(rational), AV_OPT_TYPE_RATIONAL, {0}, 0, 10 },
00828 {"string", "set string", OFFSET(string), AV_OPT_TYPE_STRING, {0}, CHAR_MIN, CHAR_MAX },
00829 {"flags", "set flags", OFFSET(flags), AV_OPT_TYPE_FLAGS, {0}, 0, INT_MAX, 0, "flags" },
00830 {"cool", "set cool flag ", 0, AV_OPT_TYPE_CONST, {TEST_FLAG_COOL}, INT_MIN, INT_MAX, 0, "flags" },
00831 {"lame", "set lame flag ", 0, AV_OPT_TYPE_CONST, {TEST_FLAG_LAME}, INT_MIN, INT_MAX, 0, "flags" },
00832 {"mu", "set mu flag ", 0, AV_OPT_TYPE_CONST, {TEST_FLAG_MU}, INT_MIN, INT_MAX, 0, "flags" },
00833 {NULL},
00834 };
00835
00836 static const char *test_get_name(void *ctx)
00837 {
00838 return "test";
00839 }
00840
00841 static const AVClass test_class = {
00842 "TestContext",
00843 test_get_name,
00844 test_options
00845 };
00846
00847 int main(void)
00848 {
00849 int i;
00850
00851 printf("\nTesting av_set_options_string()\n");
00852 {
00853 TestContext test_ctx;
00854 const char *options[] = {
00855 "",
00856 ":",
00857 "=",
00858 "foo=:",
00859 ":=foo",
00860 "=foo",
00861 "foo=",
00862 "foo",
00863 "foo=val",
00864 "foo==val",
00865 "toggle=:",
00866 "string=:",
00867 "toggle=1 : foo",
00868 "toggle=100",
00869 "toggle==1",
00870 "flags=+mu-lame : num=42: toggle=0",
00871 "num=42 : string=blahblah",
00872 "rational=0 : rational=1/2 : rational=1/-1",
00873 "rational=-1/0",
00874 };
00875
00876 test_ctx.class = &test_class;
00877 av_opt_set_defaults(&test_ctx);
00878 test_ctx.string = av_strdup("default");
00879
00880 av_log_set_level(AV_LOG_DEBUG);
00881
00882 for (i=0; i < FF_ARRAY_ELEMS(options); i++) {
00883 av_log(&test_ctx, AV_LOG_DEBUG, "Setting options string '%s'\n", options[i]);
00884 if (av_set_options_string(&test_ctx, options[i], "=", ":") < 0)
00885 av_log(&test_ctx, AV_LOG_ERROR, "Error setting options string: '%s'\n", options[i]);
00886 printf("\n");
00887 }
00888 }
00889
00890 return 0;
00891 }
00892
00893 #endif