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