opt.c 29 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
/*
 * AVOptions
 * Copyright (c) 2005 Michael Niedermayer <michaelni@gmx.at>
 *
 * This file is part of FFmpeg.
 *
 * FFmpeg is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * FFmpeg is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with FFmpeg; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */

/**
 * @file
 * AVOptions
 * @author Michael Niedermayer <michaelni@gmx.at>
 */

#include "avutil.h"
29
#include "avstring.h"
30
#include "opt.h"
31
#include "eval.h"
32
#include "dict.h"
33
#include "log.h"
34
#include "parseutils.h"
35

36
#if FF_API_FIND_OPT
37
//FIXME order them and do a bin search
38 39
const AVOption *av_find_opt(void *v, const char *name, const char *unit, int mask, int flags)
{
40
    const AVOption *o = NULL;
41

42
    while ((o = av_next_option(v, o))) {
43
        if (!strcmp(o->name, name) && (!unit || (o->unit && !strcmp(o->unit, unit))) && (o->flags & mask) == flags)
44 45 46 47
            return o;
    }
    return NULL;
}
48
#endif
49

50
#if FF_API_OLD_AVOPTIONS
51
const AVOption *av_next_option(void *obj, const AVOption *last)
52 53 54 55 56 57
{
    return av_opt_next(obj, last);
}
#endif

const AVOption *av_opt_next(void *obj, const AVOption *last)
58
{
59 60 61 62
    AVClass *class = *(AVClass**)obj;
    if (!last && class->option[0].name) return class->option;
    if (last && last[1].name)           return ++last;
    return NULL;
63 64
}

65 66 67
static int read_number(const AVOption *o, void *dst, double *num, int *den, int64_t *intnum)
{
    switch (o->type) {
68 69 70 71 72 73
    case AV_OPT_TYPE_FLAGS:     *intnum = *(unsigned int*)dst;return 0;
    case AV_OPT_TYPE_INT:       *intnum = *(int         *)dst;return 0;
    case AV_OPT_TYPE_INT64:     *intnum = *(int64_t     *)dst;return 0;
    case AV_OPT_TYPE_FLOAT:     *num    = *(float       *)dst;return 0;
    case AV_OPT_TYPE_DOUBLE:    *num    = *(double      *)dst;return 0;
    case AV_OPT_TYPE_RATIONAL:  *intnum = ((AVRational*)dst)->num;
74 75
                                *den    = ((AVRational*)dst)->den;
                                                        return 0;
76
    case AV_OPT_TYPE_CONST:     *num    = o->default_val.dbl; return 0;
77 78 79 80
    }
    return AVERROR(EINVAL);
}

81
static int write_number(void *obj, const AVOption *o, void *dst, double num, int den, int64_t intnum)
82 83
{
    if (o->max*den < num*intnum || o->min*den > num*intnum) {
84
        av_log(obj, AV_LOG_ERROR, "Value %f for parameter '%s' out of range\n", num*intnum/den, o->name);
85 86 87
        return AVERROR(ERANGE);
    }

88
    switch (o->type) {
89 90 91 92 93 94
    case AV_OPT_TYPE_FLAGS:
    case AV_OPT_TYPE_INT:   *(int       *)dst= llrint(num/den)*intnum; break;
    case AV_OPT_TYPE_INT64: *(int64_t   *)dst= llrint(num/den)*intnum; break;
    case AV_OPT_TYPE_FLOAT: *(float     *)dst= num*intnum/den;         break;
    case AV_OPT_TYPE_DOUBLE:*(double    *)dst= num*intnum/den;         break;
    case AV_OPT_TYPE_RATIONAL:
95 96
        if ((int)num == num) *(AVRational*)dst= (AVRational){num*intnum, den};
        else                 *(AVRational*)dst= av_d2q(num*intnum/den, 1<<24);
97 98 99 100 101 102 103
        break;
    default:
        return AVERROR(EINVAL);
    }
    return 0;
}

104
static const double const_values[] = {
105 106 107 108 109 110
    M_PI,
    M_E,
    FF_QP2LAMBDA,
    0
};

111
static const char * const const_names[] = {
112 113 114 115 116 117 118 119 120 121 122 123 124
    "PI",
    "E",
    "QP2LAMBDA",
    0
};

static int hexchar2int(char c) {
    if (c >= '0' && c <= '9') return c - '0';
    if (c >= 'a' && c <= 'f') return c - 'a' + 10;
    if (c >= 'A' && c <= 'F') return c - 'A' + 10;
    return -1;
}

125
static int set_string_binary(void *obj, const AVOption *o, const char *val, uint8_t **dst)
126
{
127 128 129 130 131 132 133 134
    int *lendst = (int *)(dst + 1);
    uint8_t *bin, *ptr;
    int len = strlen(val);

    av_freep(dst);
    *lendst = 0;

    if (len & 1)
135
        return AVERROR(EINVAL);
136
    len /= 2;
137

138 139 140 141 142 143 144
    ptr = bin = av_malloc(len);
    while (*val) {
        int a = hexchar2int(*val++);
        int b = hexchar2int(*val++);
        if (a < 0 || b < 0) {
            av_free(bin);
            return AVERROR(EINVAL);
145
        }
146
        *ptr++ = (a << 4) | b;
147
    }
148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164
    *dst = bin;
    *lendst = len;

    return 0;
}

static int set_string(void *obj, const AVOption *o, const char *val, uint8_t **dst)
{
    av_freep(dst);
    *dst = av_strdup(val);
    return 0;
}

static int set_string_number(void *obj, const AVOption *o, const char *val, void *dst)
{
    int ret = 0, notfirst = 0;
    for (;;) {
165
        int i, den = 1;
166 167
        char buf[256];
        int cmd = 0;
168 169
        double d, num = 1;
        int64_t intnum = 1;
170 171 172 173 174 175 176 177 178 179

        if (*val == '+' || *val == '-')
            cmd = *(val++);

        for (i = 0; i < sizeof(buf) - 1 && val[i] && val[i] != '+' && val[i] != '-'; i++)
            buf[i] = val[i];
        buf[i] = 0;

        {
            const AVOption *o_named = av_opt_find(obj, buf, o->unit, 0, 0);
180
            if (o_named && o_named->type == AV_OPT_TYPE_CONST)
181 182 183 184 185 186 187 188 189 190 191
                d = o_named->default_val.dbl;
            else if (!strcmp(buf, "default")) d = o->default_val.dbl;
            else if (!strcmp(buf, "max"    )) d = o->max;
            else if (!strcmp(buf, "min"    )) d = o->min;
            else if (!strcmp(buf, "none"   )) d = 0;
            else if (!strcmp(buf, "all"    )) d = ~0;
            else {
                int res = av_expr_parse_and_eval(&d, buf, const_names, const_values, NULL, NULL, NULL, NULL, NULL, 0, obj);
                if (res < 0) {
                    av_log(obj, AV_LOG_ERROR, "Unable to parse option value \"%s\"\n", val);
                    return res;
192 193 194
                }
            }
        }
195
        if (o->type == AV_OPT_TYPE_FLAGS) {
196 197 198
            read_number(o, dst, NULL, NULL, &intnum);
            if      (cmd == '+') d = intnum | (int64_t)d;
            else if (cmd == '-') d = intnum &~(int64_t)d;
199
        } else {
200 201 202
            read_number(o, dst, &num, &den, &intnum);
            if      (cmd == '+') d = notfirst*num*intnum/den + d;
            else if (cmd == '-') d = notfirst*num*intnum/den - d;
203
        }
204

205
        if ((ret = write_number(obj, o, dst, d, 1, 1)) < 0)
206 207 208 209 210
            return ret;
        val += i;
        if (!*val)
            return 0;
        notfirst = 1;
211 212 213 214 215
    }

    return 0;
}

216
#if FF_API_OLD_AVOPTIONS
217 218
int av_set_string3(void *obj, const char *name, const char *val, int alloc, const AVOption **o_out)
{
219
    const AVOption *o = av_opt_find(obj, name, NULL, 0, 0);
220 221
    if (o_out)
        *o_out = o;
222 223 224 225 226 227
    return av_opt_set(obj, name, val, 0);
}
#endif

int av_opt_set(void *obj, const char *name, const char *val, int search_flags)
{
228
    int ret;
229 230 231
    void *dst, *target_obj;
    const AVOption *o = av_opt_find2(obj, name, NULL, 0, search_flags, &target_obj);
    if (!o || !target_obj)
232
        return AVERROR_OPTION_NOT_FOUND;
233
    if (!val && o->type != AV_OPT_TYPE_STRING)
234 235
        return AVERROR(EINVAL);

236
    dst = ((uint8_t*)target_obj) + o->offset;
237
    switch (o->type) {
238 239 240 241 242 243 244 245
    case AV_OPT_TYPE_STRING:   return set_string(obj, o, val, dst);
    case AV_OPT_TYPE_BINARY:   return set_string_binary(obj, o, val, dst);
    case AV_OPT_TYPE_FLAGS:
    case AV_OPT_TYPE_INT:
    case AV_OPT_TYPE_INT64:
    case AV_OPT_TYPE_FLOAT:
    case AV_OPT_TYPE_DOUBLE:
    case AV_OPT_TYPE_RATIONAL: return set_string_number(obj, o, val, dst);
246 247 248 249 250
    case AV_OPT_TYPE_IMAGE_SIZE:
        ret = av_parse_video_size(dst, ((int *)dst) + 1, val);
        if (ret < 0)
            av_log(obj, AV_LOG_ERROR, "Unable to parse option value \"%s\" as image size\n", val);
        return ret;
251 252
    }

253 254 255
    av_log(obj, AV_LOG_ERROR, "Invalid option type.\n");
    return AVERROR(EINVAL);
}
256

257 258 259 260 261 262 263 264
#define OPT_EVAL_NUMBER(name, opttype, vartype)\
    int av_opt_eval_ ## name(void *obj, const AVOption *o, const char *val, vartype *name ## _out)\
    {\
        if (!o || o->type != opttype)\
            return AVERROR(EINVAL);\
        return set_string_number(obj, o, val, name ## _out);\
    }

265 266 267 268 269 270
OPT_EVAL_NUMBER(flags,  AV_OPT_TYPE_FLAGS,    int)
OPT_EVAL_NUMBER(int,    AV_OPT_TYPE_INT,      int)
OPT_EVAL_NUMBER(int64,  AV_OPT_TYPE_INT64,    int64_t)
OPT_EVAL_NUMBER(float,  AV_OPT_TYPE_FLOAT,    float)
OPT_EVAL_NUMBER(double, AV_OPT_TYPE_DOUBLE,   double)
OPT_EVAL_NUMBER(q,      AV_OPT_TYPE_RATIONAL, AVRational)
271

272 273
static int set_number(void *obj, const char *name, double num, int den, int64_t intnum,
                                  int search_flags)
274
{
275 276
    void *dst, *target_obj;
    const AVOption *o = av_opt_find2(obj, name, NULL, 0, search_flags, &target_obj);
277

278 279
    if (!o || !target_obj)
        return AVERROR_OPTION_NOT_FOUND;
280

281 282
    dst = ((uint8_t*)target_obj) + o->offset;
    return write_number(obj, o, dst, num, den, intnum);
283 284
}

285
#if FF_API_OLD_AVOPTIONS
286 287
const AVOption *av_set_double(void *obj, const char *name, double n)
{
288 289 290 291
    const AVOption *o = av_opt_find(obj, name, NULL, 0, 0);
    if (set_number(obj, name, n, 1, 1, 0) < 0)
        return NULL;
    return o;
292 293
}

294 295
const AVOption *av_set_q(void *obj, const char *name, AVRational n)
{
296 297 298 299
    const AVOption *o = av_opt_find(obj, name, NULL, 0, 0);
    if (set_number(obj, name, n.num, n.den, 1, 0) < 0)
        return NULL;
    return o;
300 301
}

302 303
const AVOption *av_set_int(void *obj, const char *name, int64_t n)
{
304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323
    const AVOption *o = av_opt_find(obj, name, NULL, 0, 0);
    if (set_number(obj, name, 1, 1, n, 0) < 0)
        return NULL;
    return o;
}
#endif

int av_opt_set_int(void *obj, const char *name, int64_t val, int search_flags)
{
    return set_number(obj, name, 1, 1, val, search_flags);
}

int av_opt_set_double(void *obj, const char *name, double val, int search_flags)
{
    return set_number(obj, name, val, 1, 1, search_flags);
}

int av_opt_set_q(void *obj, const char *name, AVRational val, int search_flags)
{
    return set_number(obj, name, val.num, val.den, 1, search_flags);
324 325
}

326
#if FF_API_OLD_AVOPTIONS
327 328 329 330 331
/**
 *
 * @param buf a buffer which is used for returning non string values as strings, can be NULL
 * @param buf_len allocated length in bytes of buf
 */
332 333
const char *av_get_string(void *obj, const char *name, const AVOption **o_out, char *buf, int buf_len)
{
334
    const AVOption *o = av_opt_find(obj, name, NULL, 0, AV_OPT_SEARCH_CHILDREN);
335 336 337
    void *dst;
    uint8_t *bin;
    int len, i;
338
    if (!o)
339
        return NULL;
340
    if (o->type != AV_OPT_TYPE_STRING && (!buf || !buf_len))
341 342 343
        return NULL;

    dst= ((uint8_t*)obj) + o->offset;
344
    if (o_out) *o_out= o;
345

346
    switch (o->type) {
347 348 349 350 351 352
    case AV_OPT_TYPE_FLAGS:     snprintf(buf, buf_len, "0x%08X",*(int    *)dst);break;
    case AV_OPT_TYPE_INT:       snprintf(buf, buf_len, "%d" , *(int    *)dst);break;
    case AV_OPT_TYPE_INT64:     snprintf(buf, buf_len, "%"PRId64, *(int64_t*)dst);break;
    case AV_OPT_TYPE_FLOAT:     snprintf(buf, buf_len, "%f" , *(float  *)dst);break;
    case AV_OPT_TYPE_DOUBLE:    snprintf(buf, buf_len, "%f" , *(double *)dst);break;
    case AV_OPT_TYPE_RATIONAL:  snprintf(buf, buf_len, "%d/%d", ((AVRational*)dst)->num, ((AVRational*)dst)->den);break;
353
    case AV_OPT_TYPE_CONST:     snprintf(buf, buf_len, "%f" , o->default_val.dbl);break;
354 355
    case AV_OPT_TYPE_STRING:    return *(void**)dst;
    case AV_OPT_TYPE_BINARY:
356
        len = *(int*)(((uint8_t *)dst) + sizeof(uint8_t *));
357
        if (len >= (buf_len + 1)/2) return NULL;
358
        bin = *(uint8_t**)dst;
359
        for (i = 0; i < len; i++) snprintf(buf + i*2, 3, "%02X", bin[i]);
360 361 362 363 364
        break;
    default: return NULL;
    }
    return buf;
}
365
#endif
366

367
int av_opt_get(void *obj, const char *name, int search_flags, uint8_t **out_val)
368
{
369 370 371 372
    void *dst, *target_obj;
    const AVOption *o = av_opt_find2(obj, name, NULL, 0, search_flags, &target_obj);
    uint8_t *bin, buf[128];
    int len, i, ret;
373

374
    if (!o || !target_obj || (o->offset<=0 && o->type != AV_OPT_TYPE_CONST))
375
        return AVERROR_OPTION_NOT_FOUND;
376

377
    dst = (uint8_t*)target_obj + o->offset;
378

379
    buf[0] = 0;
380
    switch (o->type) {
381 382 383 384 385 386
    case AV_OPT_TYPE_FLAGS:     ret = snprintf(buf, sizeof(buf), "0x%08X",  *(int    *)dst);break;
    case AV_OPT_TYPE_INT:       ret = snprintf(buf, sizeof(buf), "%d" ,     *(int    *)dst);break;
    case AV_OPT_TYPE_INT64:     ret = snprintf(buf, sizeof(buf), "%"PRId64, *(int64_t*)dst);break;
    case AV_OPT_TYPE_FLOAT:     ret = snprintf(buf, sizeof(buf), "%f" ,     *(float  *)dst);break;
    case AV_OPT_TYPE_DOUBLE:    ret = snprintf(buf, sizeof(buf), "%f" ,     *(double *)dst);break;
    case AV_OPT_TYPE_RATIONAL:  ret = snprintf(buf, sizeof(buf), "%d/%d",   ((AVRational*)dst)->num, ((AVRational*)dst)->den);break;
387
    case AV_OPT_TYPE_CONST:     ret = snprintf(buf, sizeof(buf), "%f" ,     o->default_val.dbl);break;
388
    case AV_OPT_TYPE_STRING:
389 390 391 392 393
        if (*(uint8_t**)dst)
            *out_val = av_strdup(*(uint8_t**)dst);
        else
            *out_val = av_strdup("");
        return 0;
394
    case AV_OPT_TYPE_BINARY:
395 396 397 398 399 400 401 402 403
        len = *(int*)(((uint8_t *)dst) + sizeof(uint8_t *));
        if ((uint64_t)len*2 + 1 > INT_MAX)
            return AVERROR(EINVAL);
        if (!(*out_val = av_malloc(len*2 + 1)))
            return AVERROR(ENOMEM);
        bin = *(uint8_t**)dst;
        for (i = 0; i < len; i++)
            snprintf(*out_val + i*2, 3, "%02X", bin[i]);
        return 0;
404 405 406
    case AV_OPT_TYPE_IMAGE_SIZE:
        ret = snprintf(buf, sizeof(buf), "%dx%d", ((int *)dst)[0], ((int *)dst)[1]);
        break;
407 408
    default:
        return AVERROR(EINVAL);
409
    }
410 411 412 413 414 415 416 417 418 419 420 421 422

    if (ret >= sizeof(buf))
        return AVERROR(EINVAL);
    *out_val = av_strdup(buf);
    return 0;
}

static int get_number(void *obj, const char *name, const AVOption **o_out, double *num, int *den, int64_t *intnum,
                      int search_flags)
{
    void *dst, *target_obj;
    const AVOption *o = av_opt_find2(obj, name, NULL, 0, search_flags, &target_obj);
    if (!o || !target_obj)
423 424
        goto error;

425
    dst = ((uint8_t*)target_obj) + o->offset;
426

427
    if (o_out) *o_out= o;
428

429 430
    return read_number(o, dst, num, den, intnum);

431 432 433 434 435
error:
    *den=*intnum=0;
    return -1;
}

436
#if FF_API_OLD_AVOPTIONS
437 438
double av_get_double(void *obj, const char *name, const AVOption **o_out)
{
439 440 441 442
    int64_t intnum=1;
    double num=1;
    int den=1;

443
    if (get_number(obj, name, o_out, &num, &den, &intnum, 0) < 0)
444
        return NAN;
445 446 447
    return num*intnum/den;
}

448 449
AVRational av_get_q(void *obj, const char *name, const AVOption **o_out)
{
450 451 452 453
    int64_t intnum=1;
    double num=1;
    int den=1;

454
    if (get_number(obj, name, o_out, &num, &den, &intnum, 0) < 0)
455
        return (AVRational){0, 0};
456
    if (num == 1.0 && (int)intnum == intnum)
457 458 459 460 461
        return (AVRational){intnum, den};
    else
        return av_d2q(num*intnum/den, 1<<24);
}

462 463
int64_t av_get_int(void *obj, const char *name, const AVOption **o_out)
{
464 465 466 467
    int64_t intnum=1;
    double num=1;
    int den=1;

468
    if (get_number(obj, name, o_out, &num, &den, &intnum, 0) < 0)
469
        return -1;
470 471
    return num*intnum/den;
}
472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512
#endif

int av_opt_get_int(void *obj, const char *name, int search_flags, int64_t *out_val)
{
    int64_t intnum = 1;
    double     num = 1;
    int   ret, den = 1;

    if ((ret = get_number(obj, name, NULL, &num, &den, &intnum, search_flags)) < 0)
        return ret;
    *out_val = num*intnum/den;
    return 0;
}

int av_opt_get_double(void *obj, const char *name, int search_flags, double *out_val)
{
    int64_t intnum = 1;
    double     num = 1;
    int   ret, den = 1;

    if ((ret = get_number(obj, name, NULL, &num, &den, &intnum, search_flags)) < 0)
        return ret;
    *out_val = num*intnum/den;
    return 0;
}

int av_opt_get_q(void *obj, const char *name, int search_flags, AVRational *out_val)
{
    int64_t intnum = 1;
    double     num = 1;
    int   ret, den = 1;

    if ((ret = get_number(obj, name, NULL, &num, &den, &intnum, search_flags)) < 0)
        return ret;

    if (num == 1.0 && (int)intnum == intnum)
        *out_val = (AVRational){intnum, den};
    else
        *out_val = av_d2q(num*intnum/den, 1<<24);
    return 0;
}
513

514 515
int av_opt_flag_is_set(void *obj, const char *field_name, const char *flag_name)
{
516
    const AVOption *field = av_opt_find(obj, field_name, NULL, 0, 0);
517 518
    const AVOption *flag  = av_opt_find(obj, flag_name,
                                        field ? field->unit : NULL, 0, 0);
519
    int64_t res;
520

521
    if (!field || !flag || flag->type != AV_OPT_TYPE_CONST ||
522
        av_opt_get_int(obj, field_name, 0, &res) < 0)
523
        return 0;
524
    return res & (int) flag->default_val.dbl;
525 526
}

527 528 529 530 531
static void opt_list(void *obj, void *av_log_obj, const char *unit,
                     int req_flags, int rej_flags)
{
    const AVOption *opt=NULL;

532
    while ((opt = av_opt_next(obj, opt))) {
533 534 535 536 537 538 539
        if (!(opt->flags & req_flags) || (opt->flags & rej_flags))
            continue;

        /* Don't print CONST's on level one.
         * Don't print anything but CONST's on level two.
         * Only print items from the requested unit.
         */
540
        if (!unit && opt->type==AV_OPT_TYPE_CONST)
541
            continue;
542
        else if (unit && opt->type!=AV_OPT_TYPE_CONST)
543
            continue;
544
        else if (unit && opt->type==AV_OPT_TYPE_CONST && strcmp(unit, opt->unit))
545
            continue;
546
        else if (unit && opt->type == AV_OPT_TYPE_CONST)
547 548 549 550
            av_log(av_log_obj, AV_LOG_INFO, "   %-15s ", opt->name);
        else
            av_log(av_log_obj, AV_LOG_INFO, "-%-17s ", opt->name);

551
        switch (opt->type) {
552
            case AV_OPT_TYPE_FLAGS:
553
                av_log(av_log_obj, AV_LOG_INFO, "%-7s ", "<flags>");
554
                break;
555
            case AV_OPT_TYPE_INT:
556
                av_log(av_log_obj, AV_LOG_INFO, "%-7s ", "<int>");
557
                break;
558
            case AV_OPT_TYPE_INT64:
559
                av_log(av_log_obj, AV_LOG_INFO, "%-7s ", "<int64>");
560
                break;
561
            case AV_OPT_TYPE_DOUBLE:
562
                av_log(av_log_obj, AV_LOG_INFO, "%-7s ", "<double>");
563
                break;
564
            case AV_OPT_TYPE_FLOAT:
565
                av_log(av_log_obj, AV_LOG_INFO, "%-7s ", "<float>");
566
                break;
567
            case AV_OPT_TYPE_STRING:
568
                av_log(av_log_obj, AV_LOG_INFO, "%-7s ", "<string>");
569
                break;
570
            case AV_OPT_TYPE_RATIONAL:
571
                av_log(av_log_obj, AV_LOG_INFO, "%-7s ", "<rational>");
572
                break;
573
            case AV_OPT_TYPE_BINARY:
574
                av_log(av_log_obj, AV_LOG_INFO, "%-7s ", "<binary>");
575
                break;
576 577 578
            case AV_OPT_TYPE_IMAGE_SIZE:
                av_log(av_log_obj, AV_LOG_INFO, "%-7s ", "<image_size>");
                break;
579
            case AV_OPT_TYPE_CONST:
580
            default:
581
                av_log(av_log_obj, AV_LOG_INFO, "%-7s ", "");
582 583 584 585 586 587 588 589
                break;
        }
        av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_ENCODING_PARAM) ? 'E' : '.');
        av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_DECODING_PARAM) ? 'D' : '.');
        av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_VIDEO_PARAM   ) ? 'V' : '.');
        av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_AUDIO_PARAM   ) ? 'A' : '.');
        av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_SUBTITLE_PARAM) ? 'S' : '.');

590
        if (opt->help)
591 592
            av_log(av_log_obj, AV_LOG_INFO, " %s", opt->help);
        av_log(av_log_obj, AV_LOG_INFO, "\n");
593
        if (opt->unit && opt->type != AV_OPT_TYPE_CONST) {
594 595 596 597 598 599 600
            opt_list(obj, av_log_obj, opt->unit, req_flags, rej_flags);
        }
    }
}

int av_opt_show2(void *obj, void *av_log_obj, int req_flags, int rej_flags)
{
601
    if (!obj)
602 603 604 605 606 607 608 609 610
        return -1;

    av_log(av_log_obj, AV_LOG_INFO, "%s AVOptions:\n", (*(AVClass**)obj)->class_name);

    opt_list(obj, av_log_obj, NULL, req_flags, rej_flags);

    return 0;
}

611 612 613 614 615 616
void av_opt_set_defaults(void *s)
{
#if FF_API_OLD_AVOPTIONS
    av_opt_set_defaults2(s, 0, 0);
}

617 618
void av_opt_set_defaults2(void *s, int mask, int flags)
{
619
#endif
620
    const AVOption *opt = NULL;
621
    while ((opt = av_opt_next(s, opt)) != NULL) {
622
#if FF_API_OLD_AVOPTIONS
623
        if ((opt->flags & mask) != flags)
624
            continue;
625
#endif
626
        switch (opt->type) {
627
            case AV_OPT_TYPE_CONST:
628 629
                /* Nothing to be done here */
            break;
630 631
            case AV_OPT_TYPE_FLAGS:
            case AV_OPT_TYPE_INT: {
632
                int val;
633
                val = opt->default_val.dbl;
634
                av_opt_set_int(s, opt->name, val, 0);
635 636
            }
            break;
637
            case AV_OPT_TYPE_INT64:
638
                if ((double)(opt->default_val.dbl+0.6) == opt->default_val.dbl)
639
                    av_log(s, AV_LOG_DEBUG, "loss of precision in default of %s\n", opt->name);
640
                av_opt_set_int(s, opt->name, opt->default_val.dbl, 0);
641
            break;
642 643
            case AV_OPT_TYPE_DOUBLE:
            case AV_OPT_TYPE_FLOAT: {
644
                double val;
645
                val = opt->default_val.dbl;
646
                av_opt_set_double(s, opt->name, val, 0);
647 648
            }
            break;
649
            case AV_OPT_TYPE_RATIONAL: {
650
                AVRational val;
651
                val = av_d2q(opt->default_val.dbl, INT_MAX);
652
                av_opt_set_q(s, opt->name, val, 0);
653 654
            }
            break;
655
            case AV_OPT_TYPE_STRING:
656
            case AV_OPT_TYPE_IMAGE_SIZE:
657
                av_opt_set(s, opt->name, opt->default_val.str, 0);
658
                break;
659
            case AV_OPT_TYPE_BINARY:
660
                /* Cannot set default for binary */
661 662 663 664 665 666 667
            break;
            default:
                av_log(s, AV_LOG_DEBUG, "AVOption type %d of option %s not implemented yet\n", opt->type, opt->name);
        }
    }
}

668 669 670 671 672 673 674 675 676 677 678 679 680 681
/**
 * Store the value in the field in ctx that is named like key.
 * ctx must be an AVClass context, storing is done using AVOptions.
 *
 * @param buf the string to parse, buf will be updated to point at the
 * separator just after the parsed key/value pair
 * @param key_val_sep a 0-terminated list of characters used to
 * separate key from value
 * @param pairs_sep a 0-terminated list of characters used to separate
 * two pairs from each other
 * @return 0 if the key/value pair has been successfully parsed and
 * set, or a negative value corresponding to an AVERROR code in case
 * of error:
 * AVERROR(EINVAL) if the key/value pair cannot be parsed,
682
 * the error code issued by av_opt_set() if the key/value pair
683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700
 * cannot be set
 */
static int parse_key_value_pair(void *ctx, const char **buf,
                                const char *key_val_sep, const char *pairs_sep)
{
    char *key = av_get_token(buf, key_val_sep);
    char *val;
    int ret;

    if (*key && strspn(*buf, key_val_sep)) {
        (*buf)++;
        val = av_get_token(buf, pairs_sep);
    } else {
        av_log(ctx, AV_LOG_ERROR, "Missing key or no key/value separator found after key '%s'\n", key);
        av_free(key);
        return AVERROR(EINVAL);
    }

701
    av_log(ctx, AV_LOG_DEBUG, "Setting entry with key '%s' to value '%s'\n", key, val);
702

703
    ret = av_opt_set(ctx, key, val, 0);
704
    if (ret == AVERROR_OPTION_NOT_FOUND)
705 706 707 708 709 710 711 712 713 714 715 716
        av_log(ctx, AV_LOG_ERROR, "Key '%s' not found.\n", key);

    av_free(key);
    av_free(val);
    return ret;
}

int av_set_options_string(void *ctx, const char *opts,
                          const char *key_val_sep, const char *pairs_sep)
{
    int ret, count = 0;

717 718
    if (!opts)
        return 0;
719

720 721 722 723 724 725 726 727 728 729 730 731
    while (*opts) {
        if ((ret = parse_key_value_pair(ctx, &opts, key_val_sep, pairs_sep)) < 0)
            return ret;
        count++;

        if (*opts)
            opts++;
    }

    return count;
}

732 733 734
void av_opt_free(void *obj)
{
    const AVOption *o = NULL;
735
    while ((o = av_opt_next(obj, o)))
736
        if (o->type == AV_OPT_TYPE_STRING || o->type == AV_OPT_TYPE_BINARY)
737 738 739
            av_freep((uint8_t *)obj + o->offset);
}

740 741 742 743 744 745 746
int av_opt_set_dict(void *obj, AVDictionary **options)
{
    AVDictionaryEntry *t = NULL;
    AVDictionary    *tmp = NULL;
    int ret = 0;

    while ((t = av_dict_get(*options, "", t, AV_DICT_IGNORE_SUFFIX))) {
747
        ret = av_opt_set(obj, t->key, t->value, 0);
748 749 750 751 752 753 754 755 756 757 758 759 760
        if (ret == AVERROR_OPTION_NOT_FOUND)
            av_dict_set(&tmp, t->key, t->value, 0);
        else if (ret < 0) {
            av_log(obj, AV_LOG_ERROR, "Error setting option %s to value %s.\n", t->key, t->value);
            break;
        }
        ret = 0;
    }
    av_dict_free(options);
    *options = tmp;
    return ret;
}

761 762 763
const AVOption *av_opt_find(void *obj, const char *name, const char *unit,
                            int opt_flags, int search_flags)
{
764 765 766 767 768 769
    return av_opt_find2(obj, name, unit, opt_flags, search_flags, NULL);
}

const AVOption *av_opt_find2(void *obj, const char *name, const char *unit,
                             int opt_flags, int search_flags, void **target_obj)
{
770
    const AVClass  *c;
771 772
    const AVOption *o = NULL;

773 774 775 776 777
    if(!obj)
        return NULL;

    c= *(AVClass**)obj;

778 779 780 781 782 783 784 785 786 787 788 789 790
    if (search_flags & AV_OPT_SEARCH_CHILDREN) {
        if (search_flags & AV_OPT_SEARCH_FAKE_OBJ) {
            const AVClass *child = NULL;
            while (child = av_opt_child_class_next(c, child))
                if (o = av_opt_find2(&child, name, unit, opt_flags, search_flags, NULL))
                    return o;
        } else {
            void *child = NULL;
            while (child = av_opt_child_next(obj, child))
                if (o = av_opt_find2(child, name, unit, opt_flags, search_flags, target_obj))
                    return o;
        }
    }
791

792
    while (o = av_opt_next(obj, o)) {
793
        if (!strcmp(o->name, name) && (o->flags & opt_flags) == opt_flags &&
794
            ((!unit && o->type != AV_OPT_TYPE_CONST) ||
795
             (unit  && o->type == AV_OPT_TYPE_CONST && o->unit && !strcmp(o->unit, unit)))) {
796 797 798 799 800 801
            if (target_obj) {
                if (!(search_flags & AV_OPT_SEARCH_FAKE_OBJ))
                    *target_obj = obj;
                else
                    *target_obj = NULL;
            }
802
            return o;
803
        }
804 805 806 807
    }
    return NULL;
}

808 809 810 811 812 813 814 815 816 817 818 819 820 821 822
void *av_opt_child_next(void *obj, void *prev)
{
    const AVClass *c = *(AVClass**)obj;
    if (c->child_next)
        return c->child_next(obj, prev);
    return NULL;
}

const AVClass *av_opt_child_class_next(const AVClass *parent, const AVClass *prev)
{
    if (parent->child_class_next)
        return parent->child_class_next(prev);
    return NULL;
}

823 824
void *av_opt_ptr(const AVClass *class, void *obj, const char *name)
{
825
    const AVOption *opt= av_opt_find2(&class, name, NULL, 0, AV_OPT_SEARCH_FAKE_OBJ, NULL);
826 827 828 829 830
    if(!opt)
        return NULL;
    return (uint8_t*)obj + opt->offset;
}

831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851
#ifdef TEST

#undef printf

typedef struct TestContext
{
    const AVClass *class;
    int num;
    int toggle;
    char *string;
    int flags;
    AVRational rational;
} TestContext;

#define OFFSET(x) offsetof(TestContext, x)

#define TEST_FLAG_COOL 01
#define TEST_FLAG_LAME 02
#define TEST_FLAG_MU   04

static const AVOption test_options[]= {
852 853 854 855 856 857 858 859
{"num",      "set num",        OFFSET(num),      AV_OPT_TYPE_INT,      {0},              0,        100                 },
{"toggle",   "set toggle",     OFFSET(toggle),   AV_OPT_TYPE_INT,      {0},              0,        1                   },
{"rational", "set rational",   OFFSET(rational), AV_OPT_TYPE_RATIONAL, {0},              0,        10                  },
{"string",   "set string",     OFFSET(string),   AV_OPT_TYPE_STRING,   {0},              CHAR_MIN, CHAR_MAX            },
{"flags",    "set flags",      OFFSET(flags),    AV_OPT_TYPE_FLAGS,    {0},              0,        INT_MAX, 0, "flags" },
{"cool",     "set cool flag ", 0,                AV_OPT_TYPE_CONST,    {TEST_FLAG_COOL}, INT_MIN,  INT_MAX, 0, "flags" },
{"lame",     "set lame flag ", 0,                AV_OPT_TYPE_CONST,    {TEST_FLAG_LAME}, INT_MIN,  INT_MAX, 0, "flags" },
{"mu",       "set mu flag ",   0,                AV_OPT_TYPE_CONST,    {TEST_FLAG_MU},   INT_MIN,  INT_MAX, 0, "flags" },
860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903
{NULL},
};

static const char *test_get_name(void *ctx)
{
    return "test";
}

static const AVClass test_class = {
    "TestContext",
    test_get_name,
    test_options
};

int main(void)
{
    int i;

    printf("\nTesting av_set_options_string()\n");
    {
        TestContext test_ctx;
        const char *options[] = {
            "",
            ":",
            "=",
            "foo=:",
            ":=foo",
            "=foo",
            "foo=",
            "foo",
            "foo=val",
            "foo==val",
            "toggle=:",
            "string=:",
            "toggle=1 : foo",
            "toggle=100",
            "toggle==1",
            "flags=+mu-lame : num=42: toggle=0",
            "num=42 : string=blahblah",
            "rational=0 : rational=1/2 : rational=1/-1",
            "rational=-1/0",
        };

        test_ctx.class = &test_class;
904
        av_opt_set_defaults(&test_ctx);
905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920
        test_ctx.string = av_strdup("default");

        av_log_set_level(AV_LOG_DEBUG);

        for (i=0; i < FF_ARRAY_ELEMS(options); i++) {
            av_log(&test_ctx, AV_LOG_DEBUG, "Setting options string '%s'\n", options[i]);
            if (av_set_options_string(&test_ctx, options[i], "=", ":") < 0)
                av_log(&test_ctx, AV_LOG_ERROR, "Error setting options string: '%s'\n", options[i]);
            printf("\n");
        }
    }

    return 0;
}

#endif