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 "common.h"
00031 #include "opt.h"
00032 #include "eval.h"
00033 #include "dict.h"
00034 #include "log.h"
00035 #include "parseutils.h"
00036 #include "pixdesc.h"
00037 #include "mathematics.h"
00038 #include "samplefmt.h"
00039
00040 #include <float.h>
00041
00042 #if FF_API_FIND_OPT
00043
00044 const AVOption *av_find_opt(void *v, const char *name, const char *unit, int mask, int flags)
00045 {
00046 const AVOption *o = NULL;
00047
00048 while ((o = av_next_option(v, o))) {
00049 if (!strcmp(o->name, name) && (!unit || (o->unit && !strcmp(o->unit, unit))) && (o->flags & mask) == flags)
00050 return o;
00051 }
00052 return NULL;
00053 }
00054 #endif
00055
00056 #if FF_API_OLD_AVOPTIONS
00057 const AVOption *av_next_option(void *obj, const AVOption *last)
00058 {
00059 return av_opt_next(obj, last);
00060 }
00061 #endif
00062
00063 const AVOption *av_opt_next(void *obj, const AVOption *last)
00064 {
00065 AVClass *class = *(AVClass**)obj;
00066 if (!last && class->option && class->option[0].name)
00067 return class->option;
00068 if (last && last[1].name) return ++last;
00069 return NULL;
00070 }
00071
00072 static int read_number(const AVOption *o, void *dst, double *num, int *den, int64_t *intnum)
00073 {
00074 switch (o->type) {
00075 case AV_OPT_TYPE_FLAGS: *intnum = *(unsigned int*)dst;return 0;
00076 case AV_OPT_TYPE_PIXEL_FMT:
00077 case AV_OPT_TYPE_SAMPLE_FMT:
00078 case AV_OPT_TYPE_INT: *intnum = *(int *)dst;return 0;
00079 case AV_OPT_TYPE_INT64: *intnum = *(int64_t *)dst;return 0;
00080 case AV_OPT_TYPE_FLOAT: *num = *(float *)dst;return 0;
00081 case AV_OPT_TYPE_DOUBLE: *num = *(double *)dst;return 0;
00082 case AV_OPT_TYPE_RATIONAL: *intnum = ((AVRational*)dst)->num;
00083 *den = ((AVRational*)dst)->den;
00084 return 0;
00085 case AV_OPT_TYPE_CONST: *num = o->default_val.dbl; return 0;
00086 }
00087 return AVERROR(EINVAL);
00088 }
00089
00090 static int write_number(void *obj, const AVOption *o, void *dst, double num, int den, int64_t intnum)
00091 {
00092 if (o->max*den < num*intnum || o->min*den > num*intnum) {
00093 av_log(obj, AV_LOG_ERROR, "Value %f for parameter '%s' out of range [%g - %g]\n",
00094 num*intnum/den, o->name, o->min, o->max);
00095 return AVERROR(ERANGE);
00096 }
00097
00098 switch (o->type) {
00099 case AV_OPT_TYPE_FLAGS:
00100 case AV_OPT_TYPE_PIXEL_FMT:
00101 case AV_OPT_TYPE_SAMPLE_FMT:
00102 case AV_OPT_TYPE_INT: *(int *)dst= llrint(num/den)*intnum; break;
00103 case AV_OPT_TYPE_INT64: *(int64_t *)dst= llrint(num/den)*intnum; break;
00104 case AV_OPT_TYPE_FLOAT: *(float *)dst= num*intnum/den; break;
00105 case AV_OPT_TYPE_DOUBLE:*(double *)dst= num*intnum/den; break;
00106 case AV_OPT_TYPE_RATIONAL:
00107 if ((int)num == num) *(AVRational*)dst= (AVRational){num*intnum, den};
00108 else *(AVRational*)dst= av_d2q(num*intnum/den, 1<<24);
00109 break;
00110 default:
00111 return AVERROR(EINVAL);
00112 }
00113 return 0;
00114 }
00115
00116 static const double const_values[] = {
00117 M_PI,
00118 M_E,
00119 FF_QP2LAMBDA,
00120 0
00121 };
00122
00123 static const char * const const_names[] = {
00124 "PI",
00125 "E",
00126 "QP2LAMBDA",
00127 0
00128 };
00129
00130 static int hexchar2int(char c) {
00131 if (c >= '0' && c <= '9') return c - '0';
00132 if (c >= 'a' && c <= 'f') return c - 'a' + 10;
00133 if (c >= 'A' && c <= 'F') return c - 'A' + 10;
00134 return -1;
00135 }
00136
00137 static int set_string_binary(void *obj, const AVOption *o, const char *val, uint8_t **dst)
00138 {
00139 int *lendst = (int *)(dst + 1);
00140 uint8_t *bin, *ptr;
00141 int len = strlen(val);
00142
00143 av_freep(dst);
00144 *lendst = 0;
00145
00146 if (len & 1)
00147 return AVERROR(EINVAL);
00148 len /= 2;
00149
00150 ptr = bin = av_malloc(len);
00151 while (*val) {
00152 int a = hexchar2int(*val++);
00153 int b = hexchar2int(*val++);
00154 if (a < 0 || b < 0) {
00155 av_free(bin);
00156 return AVERROR(EINVAL);
00157 }
00158 *ptr++ = (a << 4) | b;
00159 }
00160 *dst = bin;
00161 *lendst = len;
00162
00163 return 0;
00164 }
00165
00166 static int set_string(void *obj, const AVOption *o, const char *val, uint8_t **dst)
00167 {
00168 av_freep(dst);
00169 *dst = av_strdup(val);
00170 return 0;
00171 }
00172
00173 #define DEFAULT_NUMVAL(opt) ((opt->type == AV_OPT_TYPE_INT64 || \
00174 opt->type == AV_OPT_TYPE_CONST || \
00175 opt->type == AV_OPT_TYPE_FLAGS || \
00176 opt->type == AV_OPT_TYPE_INT) ? \
00177 opt->default_val.i64 : opt->default_val.dbl)
00178
00179 static int set_string_number(void *obj, const AVOption *o, const char *val, void *dst)
00180 {
00181 int ret = 0, notfirst = 0;
00182 for (;;) {
00183 int i, den = 1;
00184 char buf[256];
00185 int cmd = 0;
00186 double d, num = 1;
00187 int64_t intnum = 1;
00188
00189 i = 0;
00190 if (*val == '+' || *val == '-') {
00191 if (o->type == AV_OPT_TYPE_FLAGS)
00192 cmd = *(val++);
00193 else if (!notfirst)
00194 buf[i++] = *val;
00195 }
00196
00197 for (; i < sizeof(buf) - 1 && val[i] && val[i] != '+' && val[i] != '-'; i++)
00198 buf[i] = val[i];
00199 buf[i] = 0;
00200
00201 {
00202 const AVOption *o_named = av_opt_find(obj, buf, o->unit, 0, 0);
00203 if (o_named && o_named->type == AV_OPT_TYPE_CONST)
00204 d = DEFAULT_NUMVAL(o_named);
00205 else if (!strcmp(buf, "default")) d = DEFAULT_NUMVAL(o);
00206 else if (!strcmp(buf, "max" )) d = o->max;
00207 else if (!strcmp(buf, "min" )) d = o->min;
00208 else if (!strcmp(buf, "none" )) d = 0;
00209 else if (!strcmp(buf, "all" )) d = ~0;
00210 else {
00211 int res = av_expr_parse_and_eval(&d, buf, const_names, const_values, NULL, NULL, NULL, NULL, NULL, 0, obj);
00212 if (res < 0) {
00213 av_log(obj, AV_LOG_ERROR, "Unable to parse option value \"%s\"\n", val);
00214 return res;
00215 }
00216 }
00217 }
00218 if (o->type == AV_OPT_TYPE_FLAGS) {
00219 read_number(o, dst, NULL, NULL, &intnum);
00220 if (cmd == '+') d = intnum | (int64_t)d;
00221 else if (cmd == '-') d = intnum &~(int64_t)d;
00222 } else {
00223 read_number(o, dst, &num, &den, &intnum);
00224 if (cmd == '+') d = notfirst*num*intnum/den + d;
00225 else if (cmd == '-') d = notfirst*num*intnum/den - d;
00226 }
00227
00228 if ((ret = write_number(obj, o, dst, d, 1, 1)) < 0)
00229 return ret;
00230 val += i;
00231 if (!*val)
00232 return 0;
00233 notfirst = 1;
00234 }
00235
00236 return 0;
00237 }
00238
00239 #if FF_API_OLD_AVOPTIONS
00240 int av_set_string3(void *obj, const char *name, const char *val, int alloc, const AVOption **o_out)
00241 {
00242 const AVOption *o = av_opt_find(obj, name, NULL, 0, 0);
00243 if (o_out)
00244 *o_out = o;
00245 return av_opt_set(obj, name, val, 0);
00246 }
00247 #endif
00248
00249 int av_opt_set(void *obj, const char *name, const char *val, int search_flags)
00250 {
00251 int ret;
00252 void *dst, *target_obj;
00253 const AVOption *o = av_opt_find2(obj, name, NULL, 0, search_flags, &target_obj);
00254 if (!o || !target_obj)
00255 return AVERROR_OPTION_NOT_FOUND;
00256 if (!val && (o->type != AV_OPT_TYPE_STRING &&
00257 o->type != AV_OPT_TYPE_PIXEL_FMT && o->type != AV_OPT_TYPE_SAMPLE_FMT &&
00258 o->type != AV_OPT_TYPE_IMAGE_SIZE))
00259 return AVERROR(EINVAL);
00260
00261 dst = ((uint8_t*)target_obj) + o->offset;
00262 switch (o->type) {
00263 case AV_OPT_TYPE_STRING: return set_string(obj, o, val, dst);
00264 case AV_OPT_TYPE_BINARY: return set_string_binary(obj, o, val, dst);
00265 case AV_OPT_TYPE_FLAGS:
00266 case AV_OPT_TYPE_INT:
00267 case AV_OPT_TYPE_INT64:
00268 case AV_OPT_TYPE_FLOAT:
00269 case AV_OPT_TYPE_DOUBLE:
00270 case AV_OPT_TYPE_RATIONAL: return set_string_number(obj, o, val, dst);
00271 case AV_OPT_TYPE_IMAGE_SIZE:
00272 if (!val || !strcmp(val, "none")) {
00273 *(int *)dst = *((int *)dst + 1) = 0;
00274 return 0;
00275 }
00276 ret = av_parse_video_size(dst, ((int *)dst) + 1, val);
00277 if (ret < 0)
00278 av_log(obj, AV_LOG_ERROR, "Unable to parse option value \"%s\" as image size\n", val);
00279 return ret;
00280 case AV_OPT_TYPE_PIXEL_FMT:
00281 if (!val || !strcmp(val, "none")) {
00282 ret = AV_PIX_FMT_NONE;
00283 } else {
00284 ret = av_get_pix_fmt(val);
00285 if (ret == AV_PIX_FMT_NONE) {
00286 char *tail;
00287 ret = strtol(val, &tail, 0);
00288 if (*tail || (unsigned)ret >= AV_PIX_FMT_NB) {
00289 av_log(obj, AV_LOG_ERROR, "Unable to parse option value \"%s\" as pixel format\n", val);
00290 return AVERROR(EINVAL);
00291 }
00292 }
00293 }
00294 *(enum AVPixelFormat *)dst = ret;
00295 return 0;
00296 case AV_OPT_TYPE_SAMPLE_FMT:
00297 if (!val || !strcmp(val, "none")) {
00298 ret = AV_SAMPLE_FMT_NONE;
00299 } else {
00300 ret = av_get_sample_fmt(val);
00301 if (ret == AV_SAMPLE_FMT_NONE) {
00302 char *tail;
00303 ret = strtol(val, &tail, 0);
00304 if (*tail || (unsigned)ret >= AV_SAMPLE_FMT_NB) {
00305 av_log(obj, AV_LOG_ERROR, "Unable to parse option value \"%s\" as sample format\n", val);
00306 return AVERROR(EINVAL);
00307 }
00308 }
00309 }
00310 *(enum AVSampleFormat *)dst = ret;
00311 return 0;
00312 }
00313
00314 av_log(obj, AV_LOG_ERROR, "Invalid option type.\n");
00315 return AVERROR(EINVAL);
00316 }
00317
00318 #define OPT_EVAL_NUMBER(name, opttype, vartype)\
00319 int av_opt_eval_ ## name(void *obj, const AVOption *o, const char *val, vartype *name ## _out)\
00320 {\
00321 if (!o || o->type != opttype)\
00322 return AVERROR(EINVAL);\
00323 return set_string_number(obj, o, val, name ## _out);\
00324 }
00325
00326 OPT_EVAL_NUMBER(flags, AV_OPT_TYPE_FLAGS, int)
00327 OPT_EVAL_NUMBER(int, AV_OPT_TYPE_INT, int)
00328 OPT_EVAL_NUMBER(int64, AV_OPT_TYPE_INT64, int64_t)
00329 OPT_EVAL_NUMBER(float, AV_OPT_TYPE_FLOAT, float)
00330 OPT_EVAL_NUMBER(double, AV_OPT_TYPE_DOUBLE, double)
00331 OPT_EVAL_NUMBER(q, AV_OPT_TYPE_RATIONAL, AVRational)
00332
00333 static int set_number(void *obj, const char *name, double num, int den, int64_t intnum,
00334 int search_flags)
00335 {
00336 void *dst, *target_obj;
00337 const AVOption *o = av_opt_find2(obj, name, NULL, 0, search_flags, &target_obj);
00338
00339 if (!o || !target_obj)
00340 return AVERROR_OPTION_NOT_FOUND;
00341
00342 dst = ((uint8_t*)target_obj) + o->offset;
00343 return write_number(obj, o, dst, num, den, intnum);
00344 }
00345
00346 #if FF_API_OLD_AVOPTIONS
00347 const AVOption *av_set_double(void *obj, const char *name, double n)
00348 {
00349 const AVOption *o = av_opt_find(obj, name, NULL, 0, 0);
00350 if (set_number(obj, name, n, 1, 1, 0) < 0)
00351 return NULL;
00352 return o;
00353 }
00354
00355 const AVOption *av_set_q(void *obj, const char *name, AVRational n)
00356 {
00357 const AVOption *o = av_opt_find(obj, name, NULL, 0, 0);
00358 if (set_number(obj, name, n.num, n.den, 1, 0) < 0)
00359 return NULL;
00360 return o;
00361 }
00362
00363 const AVOption *av_set_int(void *obj, const char *name, int64_t n)
00364 {
00365 const AVOption *o = av_opt_find(obj, name, NULL, 0, 0);
00366 if (set_number(obj, name, 1, 1, n, 0) < 0)
00367 return NULL;
00368 return o;
00369 }
00370 #endif
00371
00372 int av_opt_set_int(void *obj, const char *name, int64_t val, int search_flags)
00373 {
00374 return set_number(obj, name, 1, 1, val, search_flags);
00375 }
00376
00377 int av_opt_set_double(void *obj, const char *name, double val, int search_flags)
00378 {
00379 return set_number(obj, name, val, 1, 1, search_flags);
00380 }
00381
00382 int av_opt_set_q(void *obj, const char *name, AVRational val, int search_flags)
00383 {
00384 return set_number(obj, name, val.num, val.den, 1, search_flags);
00385 }
00386
00387 int av_opt_set_bin(void *obj, const char *name, const uint8_t *val, int len, int search_flags)
00388 {
00389 void *target_obj;
00390 const AVOption *o = av_opt_find2(obj, name, NULL, 0, search_flags, &target_obj);
00391 uint8_t *ptr;
00392 uint8_t **dst;
00393 int *lendst;
00394
00395 if (!o || !target_obj)
00396 return AVERROR_OPTION_NOT_FOUND;
00397
00398 if (o->type != AV_OPT_TYPE_BINARY)
00399 return AVERROR(EINVAL);
00400
00401 ptr = av_malloc(len);
00402 if (!ptr)
00403 return AVERROR(ENOMEM);
00404
00405 dst = (uint8_t **)(((uint8_t *)target_obj) + o->offset);
00406 lendst = (int *)(dst + 1);
00407
00408 av_free(*dst);
00409 *dst = ptr;
00410 *lendst = len;
00411 memcpy(ptr, val, len);
00412
00413 return 0;
00414 }
00415
00416 int av_opt_set_image_size(void *obj, const char *name, int w, int h, int search_flags)
00417 {
00418 void *target_obj;
00419 const AVOption *o = av_opt_find2(obj, name, NULL, 0, search_flags, &target_obj);
00420
00421 if (!o || !target_obj)
00422 return AVERROR_OPTION_NOT_FOUND;
00423 if (o->type != AV_OPT_TYPE_IMAGE_SIZE) {
00424 av_log(obj, AV_LOG_ERROR,
00425 "The value set by option '%s' is not an image size.\n", o->name);
00426 return AVERROR(EINVAL);
00427 }
00428 if (w<0 || h<0) {
00429 av_log(obj, AV_LOG_ERROR,
00430 "Invalid negative size value %dx%d for size '%s'\n", w, h, o->name);
00431 return AVERROR(EINVAL);
00432 }
00433 *(int *)(((uint8_t *)target_obj) + o->offset) = w;
00434 *(int *)(((uint8_t *)target_obj+sizeof(int)) + o->offset) = h;
00435 return 0;
00436 }
00437
00438 static int set_format(void *obj, const char *name, int fmt, int search_flags,
00439 enum AVOptionType type, const char *desc, int nb_fmts)
00440 {
00441 void *target_obj;
00442 const AVOption *o = av_opt_find2(obj, name, NULL, 0,
00443 search_flags, &target_obj);
00444 int min, max;
00445 const AVClass *class = *(AVClass **)obj;
00446
00447 if (!o || !target_obj)
00448 return AVERROR_OPTION_NOT_FOUND;
00449 if (o->type != type) {
00450 av_log(obj, AV_LOG_ERROR,
00451 "The value set by option '%s' is not a %s format", name, desc);
00452 return AVERROR(EINVAL);
00453 }
00454
00455 #if LIBAVUTIL_VERSION_MAJOR < 53
00456 if (class->version && class->version < AV_VERSION_INT(52, 11, 100)) {
00457 min = -1;
00458 max = nb_fmts-1;
00459 } else
00460 #endif
00461 {
00462 min = FFMIN(o->min, -1);
00463 max = FFMAX(o->max, nb_fmts-1);
00464 }
00465 if (fmt < min || fmt > max) {
00466 av_log(obj, AV_LOG_ERROR,
00467 "Value %d for parameter '%s' out of %s format range [%d - %d]\n",
00468 fmt, name, desc, min, max);
00469 return AVERROR(ERANGE);
00470 }
00471 *(int *)(((uint8_t *)target_obj) + o->offset) = fmt;
00472 return 0;
00473 }
00474
00475 int av_opt_set_pixel_fmt(void *obj, const char *name, enum AVPixelFormat fmt, int search_flags)
00476 {
00477 return set_format(obj, name, fmt, search_flags, AV_OPT_TYPE_PIXEL_FMT, "pixel", AV_PIX_FMT_NB);
00478 }
00479
00480 int av_opt_set_sample_fmt(void *obj, const char *name, enum AVSampleFormat fmt, int search_flags)
00481 {
00482 return set_format(obj, name, fmt, search_flags, AV_OPT_TYPE_SAMPLE_FMT, "sample", AV_SAMPLE_FMT_NB);
00483 }
00484
00485 #if FF_API_OLD_AVOPTIONS
00486
00491 const char *av_get_string(void *obj, const char *name, const AVOption **o_out, char *buf, int buf_len)
00492 {
00493 const AVOption *o = av_opt_find(obj, name, NULL, 0, AV_OPT_SEARCH_CHILDREN);
00494 void *dst;
00495 uint8_t *bin;
00496 int len, i;
00497 if (!o)
00498 return NULL;
00499 if (o->type != AV_OPT_TYPE_STRING && (!buf || !buf_len))
00500 return NULL;
00501
00502 dst= ((uint8_t*)obj) + o->offset;
00503 if (o_out) *o_out= o;
00504
00505 switch (o->type) {
00506 case AV_OPT_TYPE_FLAGS: snprintf(buf, buf_len, "0x%08X",*(int *)dst);break;
00507 case AV_OPT_TYPE_INT: snprintf(buf, buf_len, "%d" , *(int *)dst);break;
00508 case AV_OPT_TYPE_INT64: snprintf(buf, buf_len, "%"PRId64, *(int64_t*)dst);break;
00509 case AV_OPT_TYPE_FLOAT: snprintf(buf, buf_len, "%f" , *(float *)dst);break;
00510 case AV_OPT_TYPE_DOUBLE: snprintf(buf, buf_len, "%f" , *(double *)dst);break;
00511 case AV_OPT_TYPE_RATIONAL: snprintf(buf, buf_len, "%d/%d", ((AVRational*)dst)->num, ((AVRational*)dst)->den);break;
00512 case AV_OPT_TYPE_CONST: snprintf(buf, buf_len, "%f" , o->default_val.dbl);break;
00513 case AV_OPT_TYPE_STRING: return *(void**)dst;
00514 case AV_OPT_TYPE_BINARY:
00515 len = *(int*)(((uint8_t *)dst) + sizeof(uint8_t *));
00516 if (len >= (buf_len + 1)/2) return NULL;
00517 bin = *(uint8_t**)dst;
00518 for (i = 0; i < len; i++) snprintf(buf + i*2, 3, "%02X", bin[i]);
00519 break;
00520 default: return NULL;
00521 }
00522 return buf;
00523 }
00524 #endif
00525
00526 int av_opt_get(void *obj, const char *name, int search_flags, uint8_t **out_val)
00527 {
00528 void *dst, *target_obj;
00529 const AVOption *o = av_opt_find2(obj, name, NULL, 0, search_flags, &target_obj);
00530 uint8_t *bin, buf[128];
00531 int len, i, ret;
00532
00533 if (!o || !target_obj || (o->offset<=0 && o->type != AV_OPT_TYPE_CONST))
00534 return AVERROR_OPTION_NOT_FOUND;
00535
00536 dst = (uint8_t*)target_obj + o->offset;
00537
00538 buf[0] = 0;
00539 switch (o->type) {
00540 case AV_OPT_TYPE_FLAGS: ret = snprintf(buf, sizeof(buf), "0x%08X", *(int *)dst);break;
00541 case AV_OPT_TYPE_INT: ret = snprintf(buf, sizeof(buf), "%d" , *(int *)dst);break;
00542 case AV_OPT_TYPE_INT64: ret = snprintf(buf, sizeof(buf), "%"PRId64, *(int64_t*)dst);break;
00543 case AV_OPT_TYPE_FLOAT: ret = snprintf(buf, sizeof(buf), "%f" , *(float *)dst);break;
00544 case AV_OPT_TYPE_DOUBLE: ret = snprintf(buf, sizeof(buf), "%f" , *(double *)dst);break;
00545 case AV_OPT_TYPE_RATIONAL: ret = snprintf(buf, sizeof(buf), "%d/%d", ((AVRational*)dst)->num, ((AVRational*)dst)->den);break;
00546 case AV_OPT_TYPE_CONST: ret = snprintf(buf, sizeof(buf), "%f" , o->default_val.dbl);break;
00547 case AV_OPT_TYPE_STRING:
00548 if (*(uint8_t**)dst)
00549 *out_val = av_strdup(*(uint8_t**)dst);
00550 else
00551 *out_val = av_strdup("");
00552 return 0;
00553 case AV_OPT_TYPE_BINARY:
00554 len = *(int*)(((uint8_t *)dst) + sizeof(uint8_t *));
00555 if ((uint64_t)len*2 + 1 > INT_MAX)
00556 return AVERROR(EINVAL);
00557 if (!(*out_val = av_malloc(len*2 + 1)))
00558 return AVERROR(ENOMEM);
00559 bin = *(uint8_t**)dst;
00560 for (i = 0; i < len; i++)
00561 snprintf(*out_val + i*2, 3, "%02X", bin[i]);
00562 return 0;
00563 case AV_OPT_TYPE_IMAGE_SIZE:
00564 ret = snprintf(buf, sizeof(buf), "%dx%d", ((int *)dst)[0], ((int *)dst)[1]);
00565 break;
00566 case AV_OPT_TYPE_PIXEL_FMT:
00567 ret = snprintf(buf, sizeof(buf), "%s", (char *)av_x_if_null(av_get_pix_fmt_name(*(enum AVPixelFormat *)dst), "none"));
00568 break;
00569 case AV_OPT_TYPE_SAMPLE_FMT:
00570 ret = snprintf(buf, sizeof(buf), "%s", (char *)av_x_if_null(av_get_sample_fmt_name(*(enum AVSampleFormat *)dst), "none"));
00571 break;
00572 default:
00573 return AVERROR(EINVAL);
00574 }
00575
00576 if (ret >= sizeof(buf))
00577 return AVERROR(EINVAL);
00578 *out_val = av_strdup(buf);
00579 return 0;
00580 }
00581
00582 static int get_number(void *obj, const char *name, const AVOption **o_out, double *num, int *den, int64_t *intnum,
00583 int search_flags)
00584 {
00585 void *dst, *target_obj;
00586 const AVOption *o = av_opt_find2(obj, name, NULL, 0, search_flags, &target_obj);
00587 if (!o || !target_obj)
00588 goto error;
00589
00590 dst = ((uint8_t*)target_obj) + o->offset;
00591
00592 if (o_out) *o_out= o;
00593
00594 return read_number(o, dst, num, den, intnum);
00595
00596 error:
00597 *den=*intnum=0;
00598 return -1;
00599 }
00600
00601 #if FF_API_OLD_AVOPTIONS
00602 double av_get_double(void *obj, const char *name, const AVOption **o_out)
00603 {
00604 int64_t intnum=1;
00605 double num=1;
00606 int den=1;
00607
00608 if (get_number(obj, name, o_out, &num, &den, &intnum, 0) < 0)
00609 return NAN;
00610 return num*intnum/den;
00611 }
00612
00613 AVRational av_get_q(void *obj, const char *name, const AVOption **o_out)
00614 {
00615 int64_t intnum=1;
00616 double num=1;
00617 int den=1;
00618
00619 if (get_number(obj, name, o_out, &num, &den, &intnum, 0) < 0)
00620 return (AVRational){0, 0};
00621 if (num == 1.0 && (int)intnum == intnum)
00622 return (AVRational){intnum, den};
00623 else
00624 return av_d2q(num*intnum/den, 1<<24);
00625 }
00626
00627 int64_t av_get_int(void *obj, const char *name, const AVOption **o_out)
00628 {
00629 int64_t intnum=1;
00630 double num=1;
00631 int den=1;
00632
00633 if (get_number(obj, name, o_out, &num, &den, &intnum, 0) < 0)
00634 return -1;
00635 return num*intnum/den;
00636 }
00637 #endif
00638
00639 int av_opt_get_int(void *obj, const char *name, int search_flags, int64_t *out_val)
00640 {
00641 int64_t intnum = 1;
00642 double num = 1;
00643 int ret, den = 1;
00644
00645 if ((ret = get_number(obj, name, NULL, &num, &den, &intnum, search_flags)) < 0)
00646 return ret;
00647 *out_val = num*intnum/den;
00648 return 0;
00649 }
00650
00651 int av_opt_get_double(void *obj, const char *name, int search_flags, double *out_val)
00652 {
00653 int64_t intnum = 1;
00654 double num = 1;
00655 int ret, den = 1;
00656
00657 if ((ret = get_number(obj, name, NULL, &num, &den, &intnum, search_flags)) < 0)
00658 return ret;
00659 *out_val = num*intnum/den;
00660 return 0;
00661 }
00662
00663 int av_opt_get_q(void *obj, const char *name, int search_flags, AVRational *out_val)
00664 {
00665 int64_t intnum = 1;
00666 double num = 1;
00667 int ret, den = 1;
00668
00669 if ((ret = get_number(obj, name, NULL, &num, &den, &intnum, search_flags)) < 0)
00670 return ret;
00671
00672 if (num == 1.0 && (int)intnum == intnum)
00673 *out_val = (AVRational){intnum, den};
00674 else
00675 *out_val = av_d2q(num*intnum/den, 1<<24);
00676 return 0;
00677 }
00678
00679 int av_opt_get_image_size(void *obj, const char *name, int search_flags, int *w_out, int *h_out)
00680 {
00681 void *dst, *target_obj;
00682 const AVOption *o = av_opt_find2(obj, name, NULL, 0, search_flags, &target_obj);
00683 if (!o || !target_obj)
00684 return AVERROR_OPTION_NOT_FOUND;
00685 if (o->type != AV_OPT_TYPE_IMAGE_SIZE) {
00686 av_log(obj, AV_LOG_ERROR,
00687 "The value for option '%s' is not an image size.\n", name);
00688 return AVERROR(EINVAL);
00689 }
00690
00691 dst = ((uint8_t*)target_obj) + o->offset;
00692 if (w_out) *w_out = *(int *)dst;
00693 if (h_out) *h_out = *((int *)dst+1);
00694 return 0;
00695 }
00696
00697 static int get_format(void *obj, const char *name, int search_flags, int *out_fmt,
00698 enum AVOptionType type, const char *desc)
00699 {
00700 void *dst, *target_obj;
00701 const AVOption *o = av_opt_find2(obj, name, NULL, 0, search_flags, &target_obj);
00702 if (!o || !target_obj)
00703 return AVERROR_OPTION_NOT_FOUND;
00704 if (o->type != type) {
00705 av_log(obj, AV_LOG_ERROR,
00706 "The value for option '%s' is not a %s format.\n", desc, name);
00707 return AVERROR(EINVAL);
00708 }
00709
00710 dst = ((uint8_t*)target_obj) + o->offset;
00711 *out_fmt = *(int *)dst;
00712 return 0;
00713 }
00714
00715 int av_opt_get_pixel_fmt(void *obj, const char *name, int search_flags, enum AVPixelFormat *out_fmt)
00716 {
00717 return get_format(obj, name, search_flags, out_fmt, AV_OPT_TYPE_PIXEL_FMT, "pixel");
00718 }
00719
00720 int av_opt_get_sample_fmt(void *obj, const char *name, int search_flags, enum AVSampleFormat *out_fmt)
00721 {
00722 return get_format(obj, name, search_flags, out_fmt, AV_OPT_TYPE_SAMPLE_FMT, "sample");
00723 }
00724
00725 int av_opt_flag_is_set(void *obj, const char *field_name, const char *flag_name)
00726 {
00727 const AVOption *field = av_opt_find(obj, field_name, NULL, 0, 0);
00728 const AVOption *flag = av_opt_find(obj, flag_name,
00729 field ? field->unit : NULL, 0, 0);
00730 int64_t res;
00731
00732 if (!field || !flag || flag->type != AV_OPT_TYPE_CONST ||
00733 av_opt_get_int(obj, field_name, 0, &res) < 0)
00734 return 0;
00735 return res & flag->default_val.i64;
00736 }
00737
00738 static void log_value(void *av_log_obj, int level, double d)
00739 {
00740 if (d == INT_MAX) {
00741 av_log(av_log_obj, level, "INT_MAX");
00742 } else if (d == INT_MIN) {
00743 av_log(av_log_obj, level, "INT_MIN");
00744 } else if (d == (double)INT64_MAX) {
00745 av_log(av_log_obj, level, "I64_MAX");
00746 } else if (d == INT64_MIN) {
00747 av_log(av_log_obj, level, "I64_MIN");
00748 } else if (d == FLT_MAX) {
00749 av_log(av_log_obj, level, "FLT_MAX");
00750 } else if (d == FLT_MIN) {
00751 av_log(av_log_obj, level, "FLT_MIN");
00752 } else {
00753 av_log(av_log_obj, level, "%g", d);
00754 }
00755 }
00756
00757 static void opt_list(void *obj, void *av_log_obj, const char *unit,
00758 int req_flags, int rej_flags)
00759 {
00760 const AVOption *opt=NULL;
00761 AVOptionRanges *r;
00762 int i;
00763
00764 while ((opt = av_opt_next(obj, opt))) {
00765 if (!(opt->flags & req_flags) || (opt->flags & rej_flags))
00766 continue;
00767
00768
00769
00770
00771
00772 if (!unit && opt->type==AV_OPT_TYPE_CONST)
00773 continue;
00774 else if (unit && opt->type!=AV_OPT_TYPE_CONST)
00775 continue;
00776 else if (unit && opt->type==AV_OPT_TYPE_CONST && strcmp(unit, opt->unit))
00777 continue;
00778 else if (unit && opt->type == AV_OPT_TYPE_CONST)
00779 av_log(av_log_obj, AV_LOG_INFO, " %-15s ", opt->name);
00780 else
00781 av_log(av_log_obj, AV_LOG_INFO, "-%-17s ", opt->name);
00782
00783 switch (opt->type) {
00784 case AV_OPT_TYPE_FLAGS:
00785 av_log(av_log_obj, AV_LOG_INFO, "%-12s ", "<flags>");
00786 break;
00787 case AV_OPT_TYPE_INT:
00788 av_log(av_log_obj, AV_LOG_INFO, "%-12s ", "<int>");
00789 break;
00790 case AV_OPT_TYPE_INT64:
00791 av_log(av_log_obj, AV_LOG_INFO, "%-12s ", "<int64>");
00792 break;
00793 case AV_OPT_TYPE_DOUBLE:
00794 av_log(av_log_obj, AV_LOG_INFO, "%-12s ", "<double>");
00795 break;
00796 case AV_OPT_TYPE_FLOAT:
00797 av_log(av_log_obj, AV_LOG_INFO, "%-12s ", "<float>");
00798 break;
00799 case AV_OPT_TYPE_STRING:
00800 av_log(av_log_obj, AV_LOG_INFO, "%-12s ", "<string>");
00801 break;
00802 case AV_OPT_TYPE_RATIONAL:
00803 av_log(av_log_obj, AV_LOG_INFO, "%-12s ", "<rational>");
00804 break;
00805 case AV_OPT_TYPE_BINARY:
00806 av_log(av_log_obj, AV_LOG_INFO, "%-12s ", "<binary>");
00807 break;
00808 case AV_OPT_TYPE_IMAGE_SIZE:
00809 av_log(av_log_obj, AV_LOG_INFO, "%-12s ", "<image_size>");
00810 break;
00811 case AV_OPT_TYPE_PIXEL_FMT:
00812 av_log(av_log_obj, AV_LOG_INFO, "%-12s ", "<pix_fmt>");
00813 break;
00814 case AV_OPT_TYPE_SAMPLE_FMT:
00815 av_log(av_log_obj, AV_LOG_INFO, "%-12s ", "<sample_fmt>");
00816 break;
00817 case AV_OPT_TYPE_CONST:
00818 default:
00819 av_log(av_log_obj, AV_LOG_INFO, "%-12s ", "");
00820 break;
00821 }
00822 av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_ENCODING_PARAM) ? 'E' : '.');
00823 av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_DECODING_PARAM) ? 'D' : '.');
00824 av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_FILTERING_PARAM)? 'F' : '.');
00825 av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_VIDEO_PARAM ) ? 'V' : '.');
00826 av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_AUDIO_PARAM ) ? 'A' : '.');
00827 av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_SUBTITLE_PARAM) ? 'S' : '.');
00828
00829 if (opt->help)
00830 av_log(av_log_obj, AV_LOG_INFO, " %s", opt->help);
00831
00832 if (av_opt_query_ranges(&r, obj, opt->name, AV_OPT_SEARCH_FAKE_OBJ) >= 0) {
00833 switch (opt->type) {
00834 case AV_OPT_TYPE_INT:
00835 case AV_OPT_TYPE_INT64:
00836 case AV_OPT_TYPE_DOUBLE:
00837 case AV_OPT_TYPE_FLOAT:
00838 case AV_OPT_TYPE_RATIONAL:
00839 for (i = 0; i < r->nb_ranges; i++) {
00840 av_log(av_log_obj, AV_LOG_INFO, " (from ");
00841 log_value(av_log_obj, AV_LOG_INFO, r->range[i]->value_min);
00842 av_log(av_log_obj, AV_LOG_INFO, " to ");
00843 log_value(av_log_obj, AV_LOG_INFO, r->range[i]->value_max);
00844 av_log(av_log_obj, AV_LOG_INFO, ")");
00845 }
00846 break;
00847 }
00848 av_opt_freep_ranges(&r);
00849 }
00850
00851 av_log(av_log_obj, AV_LOG_INFO, "\n");
00852 if (opt->unit && opt->type != AV_OPT_TYPE_CONST) {
00853 opt_list(obj, av_log_obj, opt->unit, req_flags, rej_flags);
00854 }
00855 }
00856 }
00857
00858 int av_opt_show2(void *obj, void *av_log_obj, int req_flags, int rej_flags)
00859 {
00860 if (!obj)
00861 return -1;
00862
00863 av_log(av_log_obj, AV_LOG_INFO, "%s AVOptions:\n", (*(AVClass**)obj)->class_name);
00864
00865 opt_list(obj, av_log_obj, NULL, req_flags, rej_flags);
00866
00867 return 0;
00868 }
00869
00870 void av_opt_set_defaults(void *s)
00871 {
00872 #if FF_API_OLD_AVOPTIONS
00873 av_opt_set_defaults2(s, 0, 0);
00874 }
00875
00876 void av_opt_set_defaults2(void *s, int mask, int flags)
00877 {
00878 #endif
00879 const AVClass *class = *(AVClass **)s;
00880 const AVOption *opt = NULL;
00881 while ((opt = av_opt_next(s, opt)) != NULL) {
00882 #if FF_API_OLD_AVOPTIONS
00883 if ((opt->flags & mask) != flags)
00884 continue;
00885 #endif
00886 switch (opt->type) {
00887 case AV_OPT_TYPE_CONST:
00888
00889 break;
00890 case AV_OPT_TYPE_FLAGS:
00891 case AV_OPT_TYPE_INT:
00892 case AV_OPT_TYPE_INT64:
00893 av_opt_set_int(s, opt->name, opt->default_val.i64, 0);
00894 break;
00895 case AV_OPT_TYPE_DOUBLE:
00896 case AV_OPT_TYPE_FLOAT: {
00897 double val;
00898 val = opt->default_val.dbl;
00899 av_opt_set_double(s, opt->name, val, 0);
00900 }
00901 break;
00902 case AV_OPT_TYPE_RATIONAL: {
00903 AVRational val;
00904 val = av_d2q(opt->default_val.dbl, INT_MAX);
00905 av_opt_set_q(s, opt->name, val, 0);
00906 }
00907 break;
00908 case AV_OPT_TYPE_STRING:
00909 case AV_OPT_TYPE_IMAGE_SIZE:
00910 av_opt_set(s, opt->name, opt->default_val.str, 0);
00911 break;
00912 case AV_OPT_TYPE_PIXEL_FMT:
00913 #if LIBAVUTIL_VERSION_MAJOR < 53
00914 if (class->version && class->version < AV_VERSION_INT(52, 10, 100))
00915 av_opt_set(s, opt->name, opt->default_val.str, 0);
00916 else
00917 #endif
00918 av_opt_set_pixel_fmt(s, opt->name, opt->default_val.i64, 0);
00919 break;
00920 case AV_OPT_TYPE_SAMPLE_FMT:
00921 #if LIBAVUTIL_VERSION_MAJOR < 53
00922 if (class->version && class->version < AV_VERSION_INT(52, 10, 100))
00923 av_opt_set(s, opt->name, opt->default_val.str, 0);
00924 else
00925 #endif
00926 av_opt_set_sample_fmt(s, opt->name, opt->default_val.i64, 0);
00927 break;
00928 case AV_OPT_TYPE_BINARY:
00929
00930 break;
00931 default:
00932 av_log(s, AV_LOG_DEBUG, "AVOption type %d of option %s not implemented yet\n", opt->type, opt->name);
00933 }
00934 }
00935 }
00936
00954 static int parse_key_value_pair(void *ctx, const char **buf,
00955 const char *key_val_sep, const char *pairs_sep)
00956 {
00957 char *key = av_get_token(buf, key_val_sep);
00958 char *val;
00959 int ret;
00960
00961 if (*key && strspn(*buf, key_val_sep)) {
00962 (*buf)++;
00963 val = av_get_token(buf, pairs_sep);
00964 } else {
00965 av_log(ctx, AV_LOG_ERROR, "Missing key or no key/value separator found after key '%s'\n", key);
00966 av_free(key);
00967 return AVERROR(EINVAL);
00968 }
00969
00970 av_log(ctx, AV_LOG_DEBUG, "Setting entry with key '%s' to value '%s'\n", key, val);
00971
00972 ret = av_opt_set(ctx, key, val, 0);
00973 if (ret == AVERROR_OPTION_NOT_FOUND)
00974 av_log(ctx, AV_LOG_ERROR, "Key '%s' not found.\n", key);
00975
00976 av_free(key);
00977 av_free(val);
00978 return ret;
00979 }
00980
00981 int av_set_options_string(void *ctx, const char *opts,
00982 const char *key_val_sep, const char *pairs_sep)
00983 {
00984 int ret, count = 0;
00985
00986 if (!opts)
00987 return 0;
00988
00989 while (*opts) {
00990 if ((ret = parse_key_value_pair(ctx, &opts, key_val_sep, pairs_sep)) < 0)
00991 return ret;
00992 count++;
00993
00994 if (*opts)
00995 opts++;
00996 }
00997
00998 return count;
00999 }
01000
01001 #define WHITESPACES " \n\t"
01002
01003 static int is_key_char(char c)
01004 {
01005 return (unsigned)((c | 32) - 'a') < 26 ||
01006 (unsigned)(c - '0') < 10 ||
01007 c == '-' || c == '_' || c == '/' || c == '.';
01008 }
01009
01018 static int get_key(const char **ropts, const char *delim, char **rkey)
01019 {
01020 const char *opts = *ropts;
01021 const char *key_start, *key_end;
01022
01023 key_start = opts += strspn(opts, WHITESPACES);
01024 while (is_key_char(*opts))
01025 opts++;
01026 key_end = opts;
01027 opts += strspn(opts, WHITESPACES);
01028 if (!*opts || !strchr(delim, *opts))
01029 return AVERROR(EINVAL);
01030 opts++;
01031 if (!(*rkey = av_malloc(key_end - key_start + 1)))
01032 return AVERROR(ENOMEM);
01033 memcpy(*rkey, key_start, key_end - key_start);
01034 (*rkey)[key_end - key_start] = 0;
01035 *ropts = opts;
01036 return 0;
01037 }
01038
01039 int av_opt_get_key_value(const char **ropts,
01040 const char *key_val_sep, const char *pairs_sep,
01041 unsigned flags,
01042 char **rkey, char **rval)
01043 {
01044 int ret;
01045 char *key = NULL, *val;
01046 const char *opts = *ropts;
01047
01048 if ((ret = get_key(&opts, key_val_sep, &key)) < 0 &&
01049 !(flags & AV_OPT_FLAG_IMPLICIT_KEY))
01050 return AVERROR(EINVAL);
01051 if (!(val = av_get_token(&opts, pairs_sep))) {
01052 av_free(key);
01053 return AVERROR(ENOMEM);
01054 }
01055 *ropts = opts;
01056 *rkey = key;
01057 *rval = val;
01058 return 0;
01059 }
01060
01061 int av_opt_set_from_string(void *ctx, const char *opts,
01062 const char *const *shorthand,
01063 const char *key_val_sep, const char *pairs_sep)
01064 {
01065 int ret, count = 0;
01066 const char *dummy_shorthand = NULL;
01067 char *av_uninit(parsed_key), *av_uninit(value);
01068 const char *key;
01069
01070 if (!opts)
01071 return 0;
01072 if (!shorthand)
01073 shorthand = &dummy_shorthand;
01074
01075 while (*opts) {
01076 ret = av_opt_get_key_value(&opts, key_val_sep, pairs_sep,
01077 *shorthand ? AV_OPT_FLAG_IMPLICIT_KEY : 0,
01078 &parsed_key, &value);
01079 if (ret < 0) {
01080 if (ret == AVERROR(EINVAL))
01081 av_log(ctx, AV_LOG_ERROR, "No option name near '%s'\n", opts);
01082 else
01083 av_log(ctx, AV_LOG_ERROR, "Unable to parse '%s': %s\n", opts,
01084 av_err2str(ret));
01085 return ret;
01086 }
01087 if (*opts)
01088 opts++;
01089 if (parsed_key) {
01090 key = parsed_key;
01091 while (*shorthand)
01092 shorthand++;
01093 } else {
01094 key = *(shorthand++);
01095 }
01096
01097 av_log(ctx, AV_LOG_DEBUG, "Setting '%s' to value '%s'\n", key, value);
01098 if ((ret = av_opt_set(ctx, key, value, 0)) < 0) {
01099 if (ret == AVERROR_OPTION_NOT_FOUND)
01100 av_log(ctx, AV_LOG_ERROR, "Option '%s' not found\n", key);
01101 av_free(value);
01102 av_free(parsed_key);
01103 return ret;
01104 }
01105
01106 av_free(value);
01107 av_free(parsed_key);
01108 count++;
01109 }
01110 return count;
01111 }
01112
01113 void av_opt_free(void *obj)
01114 {
01115 const AVOption *o = NULL;
01116 while ((o = av_opt_next(obj, o)))
01117 if (o->type == AV_OPT_TYPE_STRING || o->type == AV_OPT_TYPE_BINARY)
01118 av_freep((uint8_t *)obj + o->offset);
01119 }
01120
01121 int av_opt_set_dict(void *obj, AVDictionary **options)
01122 {
01123 AVDictionaryEntry *t = NULL;
01124 AVDictionary *tmp = NULL;
01125 int ret = 0;
01126
01127 while ((t = av_dict_get(*options, "", t, AV_DICT_IGNORE_SUFFIX))) {
01128 ret = av_opt_set(obj, t->key, t->value, 0);
01129 if (ret == AVERROR_OPTION_NOT_FOUND)
01130 av_dict_set(&tmp, t->key, t->value, 0);
01131 else if (ret < 0) {
01132 av_log(obj, AV_LOG_ERROR, "Error setting option %s to value %s.\n", t->key, t->value);
01133 break;
01134 }
01135 ret = 0;
01136 }
01137 av_dict_free(options);
01138 *options = tmp;
01139 return ret;
01140 }
01141
01142 const AVOption *av_opt_find(void *obj, const char *name, const char *unit,
01143 int opt_flags, int search_flags)
01144 {
01145 return av_opt_find2(obj, name, unit, opt_flags, search_flags, NULL);
01146 }
01147
01148 const AVOption *av_opt_find2(void *obj, const char *name, const char *unit,
01149 int opt_flags, int search_flags, void **target_obj)
01150 {
01151 const AVClass *c;
01152 const AVOption *o = NULL;
01153
01154 if(!obj)
01155 return NULL;
01156
01157 c= *(AVClass**)obj;
01158
01159 if (search_flags & AV_OPT_SEARCH_CHILDREN) {
01160 if (search_flags & AV_OPT_SEARCH_FAKE_OBJ) {
01161 const AVClass *child = NULL;
01162 while (child = av_opt_child_class_next(c, child))
01163 if (o = av_opt_find2(&child, name, unit, opt_flags, search_flags, NULL))
01164 return o;
01165 } else {
01166 void *child = NULL;
01167 while (child = av_opt_child_next(obj, child))
01168 if (o = av_opt_find2(child, name, unit, opt_flags, search_flags, target_obj))
01169 return o;
01170 }
01171 }
01172
01173 while (o = av_opt_next(obj, o)) {
01174 if (!strcmp(o->name, name) && (o->flags & opt_flags) == opt_flags &&
01175 ((!unit && o->type != AV_OPT_TYPE_CONST) ||
01176 (unit && o->type == AV_OPT_TYPE_CONST && o->unit && !strcmp(o->unit, unit)))) {
01177 if (target_obj) {
01178 if (!(search_flags & AV_OPT_SEARCH_FAKE_OBJ))
01179 *target_obj = obj;
01180 else
01181 *target_obj = NULL;
01182 }
01183 return o;
01184 }
01185 }
01186 return NULL;
01187 }
01188
01189 void *av_opt_child_next(void *obj, void *prev)
01190 {
01191 const AVClass *c = *(AVClass**)obj;
01192 if (c->child_next)
01193 return c->child_next(obj, prev);
01194 return NULL;
01195 }
01196
01197 const AVClass *av_opt_child_class_next(const AVClass *parent, const AVClass *prev)
01198 {
01199 if (parent->child_class_next)
01200 return parent->child_class_next(prev);
01201 return NULL;
01202 }
01203
01204 void *av_opt_ptr(const AVClass *class, void *obj, const char *name)
01205 {
01206 const AVOption *opt= av_opt_find2(&class, name, NULL, 0, AV_OPT_SEARCH_FAKE_OBJ, NULL);
01207 if(!opt)
01208 return NULL;
01209 return (uint8_t*)obj + opt->offset;
01210 }
01211
01212 int av_opt_query_ranges(AVOptionRanges **ranges_arg, void *obj, const char *key, int flags)
01213 {
01214 const AVClass *c = *(AVClass**)obj;
01215 int (*callback)(AVOptionRanges **, void *obj, const char *key, int flags) = NULL;
01216
01217 if (c->version > (52 << 16 | 11 << 8))
01218 callback = c->query_ranges;
01219
01220 if (!callback)
01221 callback = av_opt_query_ranges_default;
01222
01223 return callback(ranges_arg, obj, key, flags);
01224 }
01225
01226 int av_opt_query_ranges_default(AVOptionRanges **ranges_arg, void *obj, const char *key, int flags)
01227 {
01228 AVOptionRanges *ranges = av_mallocz(sizeof(*ranges));
01229 AVOptionRange **range_array = av_mallocz(sizeof(void*));
01230 AVOptionRange *range = av_mallocz(sizeof(*range));
01231 const AVOption *field = av_opt_find(obj, key, NULL, 0, flags);
01232 int ret;
01233
01234 *ranges_arg = NULL;
01235
01236 if (!ranges || !range || !range_array || !field) {
01237 ret = AVERROR(ENOMEM);
01238 goto fail;
01239 }
01240
01241 ranges->range = range_array;
01242 ranges->range[0] = range;
01243 ranges->nb_ranges = 1;
01244 range->is_range = 1;
01245 range->value_min = field->min;
01246 range->value_max = field->max;
01247
01248 switch (field->type) {
01249 case AV_OPT_TYPE_INT:
01250 case AV_OPT_TYPE_INT64:
01251 case AV_OPT_TYPE_PIXEL_FMT:
01252 case AV_OPT_TYPE_SAMPLE_FMT:
01253 case AV_OPT_TYPE_FLOAT:
01254 case AV_OPT_TYPE_DOUBLE:
01255 break;
01256 case AV_OPT_TYPE_STRING:
01257 range->component_min = 0;
01258 range->component_max = 0x10FFFF;
01259 range->value_min = -1;
01260 range->value_max = INT_MAX;
01261 break;
01262 case AV_OPT_TYPE_RATIONAL:
01263 range->component_min = INT_MIN;
01264 range->component_max = INT_MAX;
01265 break;
01266 case AV_OPT_TYPE_IMAGE_SIZE:
01267 range->component_min = 0;
01268 range->component_max = INT_MAX/128/8;
01269 range->value_min = 0;
01270 range->value_max = INT_MAX/8;
01271 break;
01272 default:
01273 ret = AVERROR(ENOSYS);
01274 goto fail;
01275 }
01276
01277 *ranges_arg = ranges;
01278 return 0;
01279 fail:
01280 av_free(ranges);
01281 av_free(range);
01282 av_free(range_array);
01283 return ret;
01284 }
01285
01286 void av_opt_freep_ranges(AVOptionRanges **rangesp)
01287 {
01288 int i;
01289 AVOptionRanges *ranges = *rangesp;
01290
01291 for (i = 0; i < ranges->nb_ranges; i++) {
01292 AVOptionRange *range = ranges->range[i];
01293 av_freep(&range->str);
01294 av_freep(&ranges->range[i]);
01295 }
01296 av_freep(&ranges->range);
01297 av_freep(rangesp);
01298 }
01299
01300 #ifdef TEST
01301
01302 typedef struct TestContext
01303 {
01304 const AVClass *class;
01305 int num;
01306 int toggle;
01307 char *string;
01308 int flags;
01309 AVRational rational;
01310 int w, h;
01311 enum AVPixelFormat pix_fmt;
01312 enum AVSampleFormat sample_fmt;
01313 } TestContext;
01314
01315 #define OFFSET(x) offsetof(TestContext, x)
01316
01317 #define TEST_FLAG_COOL 01
01318 #define TEST_FLAG_LAME 02
01319 #define TEST_FLAG_MU 04
01320
01321 static const AVOption test_options[]= {
01322 {"num", "set num", OFFSET(num), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 100 },
01323 {"toggle", "set toggle", OFFSET(toggle), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1 },
01324 {"rational", "set rational", OFFSET(rational), AV_OPT_TYPE_RATIONAL, {.dbl = 0}, 0, 10 },
01325 {"string", "set string", OFFSET(string), AV_OPT_TYPE_STRING, {0}, CHAR_MIN, CHAR_MAX },
01326 {"flags", "set flags", OFFSET(flags), AV_OPT_TYPE_FLAGS, {.i64 = 0}, 0, INT_MAX, 0, "flags" },
01327 {"cool", "set cool flag ", 0, AV_OPT_TYPE_CONST, {.i64 = TEST_FLAG_COOL}, INT_MIN, INT_MAX, 0, "flags" },
01328 {"lame", "set lame flag ", 0, AV_OPT_TYPE_CONST, {.i64 = TEST_FLAG_LAME}, INT_MIN, INT_MAX, 0, "flags" },
01329 {"mu", "set mu flag ", 0, AV_OPT_TYPE_CONST, {.i64 = TEST_FLAG_MU}, INT_MIN, INT_MAX, 0, "flags" },
01330 {"size", "set size", OFFSET(w), AV_OPT_TYPE_IMAGE_SIZE,{0}, 0, 0 },
01331 {"pix_fmt", "set pixfmt", OFFSET(pix_fmt), AV_OPT_TYPE_PIXEL_FMT, {.i64 = AV_PIX_FMT_NONE}, -1, AV_PIX_FMT_NB-1},
01332 {"sample_fmt", "set samplefmt", OFFSET(sample_fmt), AV_OPT_TYPE_SAMPLE_FMT, {.i64 = AV_SAMPLE_FMT_NONE}, -1, AV_SAMPLE_FMT_NB-1},
01333 {NULL},
01334 };
01335
01336 static const char *test_get_name(void *ctx)
01337 {
01338 return "test";
01339 }
01340
01341 static const AVClass test_class = {
01342 "TestContext",
01343 test_get_name,
01344 test_options
01345 };
01346
01347 int main(void)
01348 {
01349 int i;
01350
01351 printf("\nTesting av_set_options_string()\n");
01352 {
01353 TestContext test_ctx = { 0 };
01354 const char *options[] = {
01355 "",
01356 ":",
01357 "=",
01358 "foo=:",
01359 ":=foo",
01360 "=foo",
01361 "foo=",
01362 "foo",
01363 "foo=val",
01364 "foo==val",
01365 "toggle=:",
01366 "string=:",
01367 "toggle=1 : foo",
01368 "toggle=100",
01369 "toggle==1",
01370 "flags=+mu-lame : num=42: toggle=0",
01371 "num=42 : string=blahblah",
01372 "rational=0 : rational=1/2 : rational=1/-1",
01373 "rational=-1/0",
01374 "size=1024x768",
01375 "size=pal",
01376 "size=bogus",
01377 "pix_fmt=yuv420p",
01378 "pix_fmt=2",
01379 "pix_fmt=bogus",
01380 "sample_fmt=s16",
01381 "sample_fmt=2",
01382 "sample_fmt=bogus",
01383 };
01384
01385 test_ctx.class = &test_class;
01386 av_opt_set_defaults(&test_ctx);
01387 test_ctx.string = av_strdup("default");
01388
01389 av_log_set_level(AV_LOG_DEBUG);
01390
01391 for (i=0; i < FF_ARRAY_ELEMS(options); i++) {
01392 av_log(&test_ctx, AV_LOG_DEBUG, "Setting options string '%s'\n", options[i]);
01393 if (av_set_options_string(&test_ctx, options[i], "=", ":") < 0)
01394 av_log(&test_ctx, AV_LOG_ERROR, "Error setting options string: '%s'\n", options[i]);
01395 printf("\n");
01396 }
01397 av_freep(&test_ctx.string);
01398 }
01399
01400 printf("\nTesting av_opt_set_from_string()\n");
01401 {
01402 TestContext test_ctx = { 0 };
01403 const char *options[] = {
01404 "",
01405 "5",
01406 "5:hello",
01407 "5:hello:size=pal",
01408 "5:size=pal:hello",
01409 ":",
01410 "=",
01411 " 5 : hello : size = pal ",
01412 "a_very_long_option_name_that_will_need_to_be_ellipsized_around_here=42"
01413 };
01414 const char *shorthand[] = { "num", "string", NULL };
01415
01416 test_ctx.class = &test_class;
01417 av_opt_set_defaults(&test_ctx);
01418 test_ctx.string = av_strdup("default");
01419
01420 av_log_set_level(AV_LOG_DEBUG);
01421
01422 for (i=0; i < FF_ARRAY_ELEMS(options); i++) {
01423 av_log(&test_ctx, AV_LOG_DEBUG, "Setting options string '%s'\n", options[i]);
01424 if (av_opt_set_from_string(&test_ctx, options[i], shorthand, "=", ":") < 0)
01425 av_log(&test_ctx, AV_LOG_ERROR, "Error setting options string: '%s'\n", options[i]);
01426 printf("\n");
01427 }
01428 av_freep(&test_ctx.string);
01429 }
01430
01431 return 0;
01432 }
01433
01434 #endif