• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • Examples
  • File List
  • Globals

libavutil/opt.c

Go to the documentation of this file.
00001 /*
00002  * AVOptions
00003  * Copyright (c) 2005 Michael Niedermayer <michaelni@gmx.at>
00004  *
00005  * This file is part of Libav.
00006  *
00007  * Libav is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public
00009  * License as published by the Free Software Foundation; either
00010  * version 2.1 of the License, or (at your option) any later version.
00011  *
00012  * Libav is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with Libav; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
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 //FIXME order them and do a bin search
00037 const AVOption *av_find_opt(void *v, const char *name, const char *unit, int mask, int flags)
00038 {
00039     AVClass *c= *(AVClass**)v; //FIXME silly way of storing AVClass
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         /* Don't print CONST's on level one.
00525          * Don't print anything but CONST's on level two.
00526          * Only print items from the requested unit.
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                 /* Nothing to be done here */
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                 /* Cannot set default for binary */
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
Generated on Sun Apr 22 2012 21:54:09 for Libav by doxygen 1.7.1