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