LCOV - code coverage report
Current view: top level - media/libav/libavutil - opt.c (source / functions) Hit Total Coverage
Test: output.info Lines: 0 408 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 38 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * AVOptions
       3             :  * Copyright (c) 2005 Michael Niedermayer <michaelni@gmx.at>
       4             :  *
       5             :  * This file is part of Libav.
       6             :  *
       7             :  * Libav is free software; you can redistribute it and/or
       8             :  * modify it under the terms of the GNU Lesser General Public
       9             :  * License as published by the Free Software Foundation; either
      10             :  * version 2.1 of the License, or (at your option) any later version.
      11             :  *
      12             :  * Libav is distributed in the hope that it will be useful,
      13             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      15             :  * Lesser General Public License for more details.
      16             :  *
      17             :  * You should have received a copy of the GNU Lesser General Public
      18             :  * License along with Libav; if not, write to the Free Software
      19             :  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
      20             :  */
      21             : 
      22             : /**
      23             :  * @file
      24             :  * AVOptions
      25             :  * @author Michael Niedermayer <michaelni@gmx.at>
      26             :  */
      27             : 
      28             : #include "avutil.h"
      29             : #include "avstring.h"
      30             : #include "common.h"
      31             : #include "opt.h"
      32             : #include "eval.h"
      33             : #include "dict.h"
      34             : #include "log.h"
      35             : #include "mathematics.h"
      36             : 
      37           0 : const AVOption *av_opt_next(void *obj, const AVOption *last)
      38             : {
      39           0 :     AVClass *class = *(AVClass**)obj;
      40           0 :     if (!last && class->option && class->option[0].name)
      41           0 :         return class->option;
      42           0 :     if (last && last[1].name)
      43           0 :         return ++last;
      44           0 :     return NULL;
      45             : }
      46             : 
      47           0 : static int read_number(const AVOption *o, void *dst, double *num, int *den, int64_t *intnum)
      48             : {
      49           0 :     switch (o->type) {
      50           0 :     case AV_OPT_TYPE_FLAGS:     *intnum = *(unsigned int*)dst;return 0;
      51           0 :     case AV_OPT_TYPE_INT:       *intnum = *(int         *)dst;return 0;
      52           0 :     case AV_OPT_TYPE_INT64:     *intnum = *(int64_t     *)dst;return 0;
      53           0 :     case AV_OPT_TYPE_FLOAT:     *num    = *(float       *)dst;return 0;
      54           0 :     case AV_OPT_TYPE_DOUBLE:    *num    = *(double      *)dst;return 0;
      55           0 :     case AV_OPT_TYPE_RATIONAL:  *intnum = ((AVRational*)dst)->num;
      56           0 :                                 *den    = ((AVRational*)dst)->den;
      57           0 :                                                         return 0;
      58             :     }
      59           0 :     return AVERROR(EINVAL);
      60             : }
      61             : 
      62           0 : static int write_number(void *obj, const AVOption *o, void *dst, double num, int den, int64_t intnum)
      63             : {
      64           0 :     if (o->type != AV_OPT_TYPE_FLAGS &&
      65           0 :         (o->max * den < num * intnum || o->min * den > num * intnum)) {
      66           0 :         av_log(obj, AV_LOG_ERROR, "Value %f for parameter '%s' out of range\n",
      67           0 :                num*intnum/den, o->name);
      68           0 :         return AVERROR(ERANGE);
      69             :     }
      70             : 
      71           0 :     switch (o->type) {
      72             :     case AV_OPT_TYPE_FLAGS:
      73           0 :     case AV_OPT_TYPE_INT:   *(int       *)dst= llrint(num/den)*intnum; break;
      74           0 :     case AV_OPT_TYPE_INT64: *(int64_t   *)dst= llrint(num/den)*intnum; break;
      75           0 :     case AV_OPT_TYPE_FLOAT: *(float     *)dst= num*intnum/den;         break;
      76           0 :     case AV_OPT_TYPE_DOUBLE:*(double    *)dst= num*intnum/den;         break;
      77             :     case AV_OPT_TYPE_RATIONAL:
      78           0 :         if ((int)num == num) *(AVRational*)dst= (AVRational){num*intnum, den};
      79           0 :         else                 *(AVRational*)dst= av_d2q(num*intnum/den, 1<<24);
      80           0 :         break;
      81             :     default:
      82           0 :         return AVERROR(EINVAL);
      83             :     }
      84           0 :     return 0;
      85             : }
      86             : 
      87             : static const double const_values[] = {
      88             :     M_PI,
      89             :     M_E,
      90             :     FF_QP2LAMBDA,
      91             :     0
      92             : };
      93             : 
      94             : static const char * const const_names[] = {
      95             :     "PI",
      96             :     "E",
      97             :     "QP2LAMBDA",
      98             :     0
      99             : };
     100             : 
     101           0 : static int hexchar2int(char c) {
     102           0 :     if (c >= '0' && c <= '9') return c - '0';
     103           0 :     if (c >= 'a' && c <= 'f') return c - 'a' + 10;
     104           0 :     if (c >= 'A' && c <= 'F') return c - 'A' + 10;
     105           0 :     return -1;
     106             : }
     107             : 
     108           0 : static int set_string_binary(void *obj, const AVOption *o, const char *val, uint8_t **dst)
     109             : {
     110           0 :     int *lendst = (int *)(dst + 1);
     111             :     uint8_t *bin, *ptr;
     112           0 :     int len = strlen(val);
     113             : 
     114           0 :     av_freep(dst);
     115           0 :     *lendst = 0;
     116             : 
     117           0 :     if (len & 1)
     118           0 :         return AVERROR(EINVAL);
     119           0 :     len /= 2;
     120             : 
     121           0 :     ptr = bin = av_malloc(len);
     122           0 :     if (!ptr)
     123           0 :         return AVERROR(ENOMEM);
     124           0 :     while (*val) {
     125           0 :         int a = hexchar2int(*val++);
     126           0 :         int b = hexchar2int(*val++);
     127           0 :         if (a < 0 || b < 0) {
     128           0 :             av_free(bin);
     129           0 :             return AVERROR(EINVAL);
     130             :         }
     131           0 :         *ptr++ = (a << 4) | b;
     132             :     }
     133           0 :     *dst = bin;
     134           0 :     *lendst = len;
     135             : 
     136           0 :     return 0;
     137             : }
     138             : 
     139           0 : static int set_string(void *obj, const AVOption *o, const char *val, uint8_t **dst)
     140             : {
     141           0 :     av_freep(dst);
     142           0 :     *dst = av_strdup(val);
     143           0 :     return 0;
     144             : }
     145             : 
     146             : #define DEFAULT_NUMVAL(opt) ((opt->type == AV_OPT_TYPE_INT64 || \
     147             :                               opt->type == AV_OPT_TYPE_CONST || \
     148             :                               opt->type == AV_OPT_TYPE_FLAGS || \
     149             :                               opt->type == AV_OPT_TYPE_INT) ? \
     150             :                              opt->default_val.i64 : opt->default_val.dbl)
     151             : 
     152           0 : static int set_string_number(void *obj, void *target_obj, const AVOption *o, const char *val, void *dst)
     153             : {
     154           0 :     int ret = 0, notfirst = 0;
     155           0 :     for (;;) {
     156           0 :         int i, den = 1;
     157             :         char buf[256];
     158           0 :         int cmd = 0;
     159           0 :         double d, num = 1;
     160           0 :         int64_t intnum = 1;
     161             : 
     162           0 :         i = 0;
     163           0 :         if (*val == '+' || *val == '-') {
     164           0 :             if (o->type == AV_OPT_TYPE_FLAGS)
     165           0 :                 cmd = *(val++);
     166           0 :             else if (!notfirst)
     167           0 :                 buf[i++] = *val;
     168             :         }
     169             : 
     170           0 :         for (; i < sizeof(buf) - 1 && val[i] && val[i] != '+' && val[i] != '-'; i++)
     171           0 :             buf[i] = val[i];
     172           0 :         buf[i] = 0;
     173             : 
     174             :         {
     175           0 :             const AVOption *o_named = av_opt_find(target_obj, buf, o->unit, 0, 0);
     176           0 :             if (o_named && o_named->type == AV_OPT_TYPE_CONST)
     177           0 :                 d = DEFAULT_NUMVAL(o_named);
     178           0 :             else if (!strcmp(buf, "default")) d = DEFAULT_NUMVAL(o);
     179           0 :             else if (!strcmp(buf, "max"    )) d = o->max;
     180           0 :             else if (!strcmp(buf, "min"    )) d = o->min;
     181           0 :             else if (!strcmp(buf, "none"   )) d = 0;
     182           0 :             else if (!strcmp(buf, "all"    )) d = ~0;
     183             :             else {
     184           0 :                 int res = av_expr_parse_and_eval(&d, buf, const_names, const_values, NULL, NULL, NULL, NULL, NULL, 0, obj);
     185           0 :                 if (res < 0) {
     186           0 :                     av_log(obj, AV_LOG_ERROR, "Unable to parse option value \"%s\"\n", val);
     187           0 :                     return res;
     188             :                 }
     189             :             }
     190             :         }
     191           0 :         if (o->type == AV_OPT_TYPE_FLAGS) {
     192           0 :             read_number(o, dst, NULL, NULL, &intnum);
     193           0 :             if      (cmd == '+') d = intnum | (int64_t)d;
     194           0 :             else if (cmd == '-') d = intnum &~(int64_t)d;
     195             :         } else {
     196           0 :             read_number(o, dst, &num, &den, &intnum);
     197           0 :             if      (cmd == '+') d = notfirst*num*intnum/den + d;
     198           0 :             else if (cmd == '-') d = notfirst*num*intnum/den - d;
     199             :         }
     200             : 
     201           0 :         if ((ret = write_number(obj, o, dst, d, 1, 1)) < 0)
     202           0 :             return ret;
     203           0 :         val += i;
     204           0 :         if (!*val)
     205           0 :             return 0;
     206           0 :         notfirst = 1;
     207             :     }
     208             : 
     209             :     return 0;
     210             : }
     211             : 
     212           0 : int av_opt_set(void *obj, const char *name, const char *val, int search_flags)
     213             : {
     214             :     void *dst, *target_obj;
     215           0 :     const AVOption *o = av_opt_find2(obj, name, NULL, 0, search_flags, &target_obj);
     216           0 :     if (!o || !target_obj)
     217           0 :         return AVERROR_OPTION_NOT_FOUND;
     218           0 :     if (!val || o->flags & AV_OPT_FLAG_READONLY)
     219           0 :         return AVERROR(EINVAL);
     220             : 
     221           0 :     dst = ((uint8_t*)target_obj) + o->offset;
     222           0 :     switch (o->type) {
     223           0 :     case AV_OPT_TYPE_STRING:   return set_string(obj, o, val, dst);
     224           0 :     case AV_OPT_TYPE_BINARY:   return set_string_binary(obj, o, val, dst);
     225             :     case AV_OPT_TYPE_FLAGS:
     226             :     case AV_OPT_TYPE_INT:
     227             :     case AV_OPT_TYPE_INT64:
     228             :     case AV_OPT_TYPE_FLOAT:
     229             :     case AV_OPT_TYPE_DOUBLE:
     230           0 :     case AV_OPT_TYPE_RATIONAL: return set_string_number(obj, target_obj, o, val, dst);
     231             :     }
     232             : 
     233           0 :     av_log(obj, AV_LOG_ERROR, "Invalid option type.\n");
     234           0 :     return AVERROR(EINVAL);
     235             : }
     236             : 
     237             : #define OPT_EVAL_NUMBER(name, opttype, vartype)\
     238             :     int av_opt_eval_ ## name(void *obj, const AVOption *o, const char *val, vartype *name ## _out)\
     239             :     {\
     240             :         if (!o || o->type != opttype || o->flags & AV_OPT_FLAG_READONLY)\
     241             :             return AVERROR(EINVAL);\
     242             :         return set_string_number(obj, obj, o, val, name ## _out);\
     243             :     }
     244             : 
     245           0 : OPT_EVAL_NUMBER(flags,  AV_OPT_TYPE_FLAGS,    int)
     246           0 : OPT_EVAL_NUMBER(int,    AV_OPT_TYPE_INT,      int)
     247           0 : OPT_EVAL_NUMBER(int64,  AV_OPT_TYPE_INT64,    int64_t)
     248           0 : OPT_EVAL_NUMBER(float,  AV_OPT_TYPE_FLOAT,    float)
     249           0 : OPT_EVAL_NUMBER(double, AV_OPT_TYPE_DOUBLE,   double)
     250           0 : OPT_EVAL_NUMBER(q,      AV_OPT_TYPE_RATIONAL, AVRational)
     251             : 
     252           0 : static int set_number(void *obj, const char *name, double num, int den, int64_t intnum,
     253             :                                   int search_flags)
     254             : {
     255             :     void *dst, *target_obj;
     256           0 :     const AVOption *o = av_opt_find2(obj, name, NULL, 0, search_flags, &target_obj);
     257             : 
     258           0 :     if (!o || !target_obj)
     259           0 :         return AVERROR_OPTION_NOT_FOUND;
     260             : 
     261           0 :     if (o->flags & AV_OPT_FLAG_READONLY)
     262           0 :         return AVERROR(EINVAL);
     263             : 
     264           0 :     dst = ((uint8_t*)target_obj) + o->offset;
     265           0 :     return write_number(obj, o, dst, num, den, intnum);
     266             : }
     267             : 
     268           0 : int av_opt_set_int(void *obj, const char *name, int64_t val, int search_flags)
     269             : {
     270           0 :     return set_number(obj, name, 1, 1, val, search_flags);
     271             : }
     272             : 
     273           0 : int av_opt_set_double(void *obj, const char *name, double val, int search_flags)
     274             : {
     275           0 :     return set_number(obj, name, val, 1, 1, search_flags);
     276             : }
     277             : 
     278           0 : int av_opt_set_q(void *obj, const char *name, AVRational val, int search_flags)
     279             : {
     280           0 :     return set_number(obj, name, val.num, val.den, 1, search_flags);
     281             : }
     282             : 
     283           0 : int av_opt_set_bin(void *obj, const char *name, const uint8_t *val, int len, int search_flags)
     284             : {
     285             :     void *target_obj;
     286           0 :     const AVOption *o = av_opt_find2(obj, name, NULL, 0, search_flags, &target_obj);
     287             :     uint8_t *ptr;
     288             :     uint8_t **dst;
     289             :     int *lendst;
     290             : 
     291           0 :     if (!o || !target_obj)
     292           0 :         return AVERROR_OPTION_NOT_FOUND;
     293             : 
     294           0 :     if (o->type != AV_OPT_TYPE_BINARY || o->flags & AV_OPT_FLAG_READONLY)
     295           0 :         return AVERROR(EINVAL);
     296             : 
     297           0 :     ptr = av_malloc(len);
     298           0 :     if (!ptr)
     299           0 :         return AVERROR(ENOMEM);
     300             : 
     301           0 :     dst = (uint8_t **)(((uint8_t *)target_obj) + o->offset);
     302           0 :     lendst = (int *)(dst + 1);
     303             : 
     304           0 :     av_free(*dst);
     305           0 :     *dst = ptr;
     306           0 :     *lendst = len;
     307           0 :     memcpy(ptr, val, len);
     308             : 
     309           0 :     return 0;
     310             : }
     311             : 
     312           0 : int av_opt_set_dict_val(void *obj, const char *name, const AVDictionary *val, int search_flags)
     313             : {
     314             :     void *target_obj;
     315             :     AVDictionary **dst;
     316           0 :     const AVOption *o = av_opt_find2(obj, name, NULL, 0, search_flags, &target_obj);
     317             : 
     318           0 :     if (!o || !target_obj)
     319           0 :         return AVERROR_OPTION_NOT_FOUND;
     320           0 :     if (o->flags & AV_OPT_FLAG_READONLY)
     321           0 :         return AVERROR(EINVAL);
     322             : 
     323           0 :     dst = (AVDictionary **)(((uint8_t *)target_obj) + o->offset);
     324           0 :     av_dict_free(dst);
     325           0 :     av_dict_copy(dst, val, 0);
     326             : 
     327           0 :     return 0;
     328             : }
     329             : 
     330           0 : int av_opt_get(void *obj, const char *name, int search_flags, uint8_t **out_val)
     331             : {
     332             :     void *dst, *target_obj;
     333           0 :     const AVOption *o = av_opt_find2(obj, name, NULL, 0, search_flags, &target_obj);
     334             :     uint8_t *bin, buf[128];
     335             :     int len, i, ret;
     336             : 
     337           0 :     if (!o || !target_obj)
     338           0 :         return AVERROR_OPTION_NOT_FOUND;
     339             : 
     340           0 :     dst = (uint8_t*)target_obj + o->offset;
     341             : 
     342           0 :     buf[0] = 0;
     343           0 :     switch (o->type) {
     344           0 :     case AV_OPT_TYPE_FLAGS:     ret = snprintf(buf, sizeof(buf), "0x%08X",  *(int    *)dst);break;
     345           0 :     case AV_OPT_TYPE_INT:       ret = snprintf(buf, sizeof(buf), "%d" ,     *(int    *)dst);break;
     346           0 :     case AV_OPT_TYPE_INT64:     ret = snprintf(buf, sizeof(buf), "%"PRId64, *(int64_t*)dst);break;
     347           0 :     case AV_OPT_TYPE_FLOAT:     ret = snprintf(buf, sizeof(buf), "%f" ,     *(float  *)dst);break;
     348           0 :     case AV_OPT_TYPE_DOUBLE:    ret = snprintf(buf, sizeof(buf), "%f" ,     *(double *)dst);break;
     349           0 :     case AV_OPT_TYPE_RATIONAL:  ret = snprintf(buf, sizeof(buf), "%d/%d",   ((AVRational*)dst)->num, ((AVRational*)dst)->den);break;
     350             :     case AV_OPT_TYPE_STRING:
     351           0 :         if (*(uint8_t**)dst)
     352           0 :             *out_val = av_strdup(*(uint8_t**)dst);
     353             :         else
     354           0 :             *out_val = av_strdup("");
     355           0 :         return 0;
     356             :     case AV_OPT_TYPE_BINARY:
     357           0 :         len = *(int*)(((uint8_t *)dst) + sizeof(uint8_t *));
     358           0 :         if ((uint64_t)len*2 + 1 > INT_MAX)
     359           0 :             return AVERROR(EINVAL);
     360           0 :         if (!(*out_val = av_malloc(len*2 + 1)))
     361           0 :             return AVERROR(ENOMEM);
     362           0 :         bin = *(uint8_t**)dst;
     363           0 :         for (i = 0; i < len; i++)
     364           0 :             snprintf(*out_val + i*2, 3, "%02X", bin[i]);
     365           0 :         return 0;
     366             :     default:
     367           0 :         return AVERROR(EINVAL);
     368             :     }
     369             : 
     370           0 :     if (ret >= sizeof(buf))
     371           0 :         return AVERROR(EINVAL);
     372           0 :     *out_val = av_strdup(buf);
     373           0 :     return 0;
     374             : }
     375             : 
     376           0 : static int get_number(void *obj, const char *name, double *num, int *den, int64_t *intnum,
     377             :                       int search_flags)
     378             : {
     379             :     void *dst, *target_obj;
     380           0 :     const AVOption *o = av_opt_find2(obj, name, NULL, 0, search_flags, &target_obj);
     381           0 :     if (!o || !target_obj)
     382             :         goto error;
     383             : 
     384           0 :     dst = ((uint8_t*)target_obj) + o->offset;
     385             : 
     386           0 :     return read_number(o, dst, num, den, intnum);
     387             : 
     388             : error:
     389           0 :     *den=*intnum=0;
     390           0 :     return -1;
     391             : }
     392             : 
     393           0 : int av_opt_get_int(void *obj, const char *name, int search_flags, int64_t *out_val)
     394             : {
     395           0 :     int64_t intnum = 1;
     396           0 :     double     num = 1;
     397           0 :     int   ret, den = 1;
     398             : 
     399           0 :     if ((ret = get_number(obj, name, &num, &den, &intnum, search_flags)) < 0)
     400           0 :         return ret;
     401           0 :     *out_val = num*intnum/den;
     402           0 :     return 0;
     403             : }
     404             : 
     405           0 : int av_opt_get_double(void *obj, const char *name, int search_flags, double *out_val)
     406             : {
     407           0 :     int64_t intnum = 1;
     408           0 :     double     num = 1;
     409           0 :     int   ret, den = 1;
     410             : 
     411           0 :     if ((ret = get_number(obj, name, &num, &den, &intnum, search_flags)) < 0)
     412           0 :         return ret;
     413           0 :     *out_val = num*intnum/den;
     414           0 :     return 0;
     415             : }
     416             : 
     417           0 : int av_opt_get_q(void *obj, const char *name, int search_flags, AVRational *out_val)
     418             : {
     419           0 :     int64_t intnum = 1;
     420           0 :     double     num = 1;
     421           0 :     int   ret, den = 1;
     422             : 
     423           0 :     if ((ret = get_number(obj, name, &num, &den, &intnum, search_flags)) < 0)
     424           0 :         return ret;
     425             : 
     426           0 :     if (num == 1.0 && (int)intnum == intnum)
     427           0 :         *out_val = (AVRational){intnum, den};
     428             :     else
     429           0 :         *out_val = av_d2q(num*intnum/den, 1<<24);
     430           0 :     return 0;
     431             : }
     432             : 
     433           0 : int av_opt_get_dict_val(void *obj, const char *name, int search_flags, AVDictionary **out_val)
     434             : {
     435             :     void *target_obj;
     436             :     AVDictionary *src;
     437           0 :     const AVOption *o = av_opt_find2(obj, name, NULL, 0, search_flags, &target_obj);
     438             : 
     439           0 :     if (!o || !target_obj)
     440           0 :         return AVERROR_OPTION_NOT_FOUND;
     441           0 :     if (o->type != AV_OPT_TYPE_DICT)
     442           0 :         return AVERROR(EINVAL);
     443             : 
     444           0 :     src = *(AVDictionary **)(((uint8_t *)target_obj) + o->offset);
     445           0 :     av_dict_copy(out_val, src, 0);
     446             : 
     447           0 :     return 0;
     448             : }
     449             : 
     450           0 : int av_opt_flag_is_set(void *obj, const char *field_name, const char *flag_name)
     451             : {
     452           0 :     const AVOption *field = av_opt_find(obj, field_name, NULL, 0, 0);
     453           0 :     const AVOption *flag  = av_opt_find(obj, flag_name,
     454             :                                         field ? field->unit : NULL, 0, 0);
     455             :     int64_t res;
     456             : 
     457           0 :     if (!field || !flag || flag->type != AV_OPT_TYPE_CONST ||
     458           0 :         av_opt_get_int(obj, field_name, 0, &res) < 0)
     459           0 :         return 0;
     460           0 :     return res & flag->default_val.i64;
     461             : }
     462             : 
     463           0 : static void opt_list(void *obj, void *av_log_obj, const char *unit,
     464             :                      int req_flags, int rej_flags)
     465             : {
     466           0 :     const AVOption *opt=NULL;
     467             : 
     468           0 :     while ((opt = av_opt_next(obj, opt))) {
     469           0 :         if (!(opt->flags & req_flags) || (opt->flags & rej_flags))
     470           0 :             continue;
     471             : 
     472             :         /* Don't print CONST's on level one.
     473             :          * Don't print anything but CONST's on level two.
     474             :          * Only print items from the requested unit.
     475             :          */
     476           0 :         if (!unit && opt->type==AV_OPT_TYPE_CONST)
     477           0 :             continue;
     478           0 :         else if (unit && opt->type!=AV_OPT_TYPE_CONST)
     479           0 :             continue;
     480           0 :         else if (unit && opt->type==AV_OPT_TYPE_CONST && strcmp(unit, opt->unit))
     481           0 :             continue;
     482           0 :         else if (unit && opt->type == AV_OPT_TYPE_CONST)
     483           0 :             av_log(av_log_obj, AV_LOG_INFO, "   %-15s ", opt->name);
     484             :         else
     485           0 :             av_log(av_log_obj, AV_LOG_INFO, "-%-17s ", opt->name);
     486             : 
     487           0 :         switch (opt->type) {
     488             :             case AV_OPT_TYPE_FLAGS:
     489           0 :                 av_log(av_log_obj, AV_LOG_INFO, "%-7s ", "<flags>");
     490           0 :                 break;
     491             :             case AV_OPT_TYPE_INT:
     492           0 :                 av_log(av_log_obj, AV_LOG_INFO, "%-7s ", "<int>");
     493           0 :                 break;
     494             :             case AV_OPT_TYPE_INT64:
     495           0 :                 av_log(av_log_obj, AV_LOG_INFO, "%-7s ", "<int64>");
     496           0 :                 break;
     497             :             case AV_OPT_TYPE_DOUBLE:
     498           0 :                 av_log(av_log_obj, AV_LOG_INFO, "%-7s ", "<double>");
     499           0 :                 break;
     500             :             case AV_OPT_TYPE_FLOAT:
     501           0 :                 av_log(av_log_obj, AV_LOG_INFO, "%-7s ", "<float>");
     502           0 :                 break;
     503             :             case AV_OPT_TYPE_STRING:
     504           0 :                 av_log(av_log_obj, AV_LOG_INFO, "%-7s ", "<string>");
     505           0 :                 break;
     506             :             case AV_OPT_TYPE_RATIONAL:
     507           0 :                 av_log(av_log_obj, AV_LOG_INFO, "%-7s ", "<rational>");
     508           0 :                 break;
     509             :             case AV_OPT_TYPE_BINARY:
     510           0 :                 av_log(av_log_obj, AV_LOG_INFO, "%-7s ", "<binary>");
     511           0 :                 break;
     512             :             case AV_OPT_TYPE_CONST:
     513             :             default:
     514           0 :                 av_log(av_log_obj, AV_LOG_INFO, "%-7s ", "");
     515           0 :                 break;
     516             :         }
     517           0 :         av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_ENCODING_PARAM) ? 'E' : '.');
     518           0 :         av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_DECODING_PARAM) ? 'D' : '.');
     519           0 :         av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_VIDEO_PARAM   ) ? 'V' : '.');
     520           0 :         av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_AUDIO_PARAM   ) ? 'A' : '.');
     521           0 :         av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_SUBTITLE_PARAM) ? 'S' : '.');
     522           0 :         av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_EXPORT)         ? 'X' : '.');
     523           0 :         av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_READONLY)       ? 'R' : '.');
     524             : 
     525           0 :         if (opt->help)
     526           0 :             av_log(av_log_obj, AV_LOG_INFO, " %s", opt->help);
     527           0 :         av_log(av_log_obj, AV_LOG_INFO, "\n");
     528           0 :         if (opt->unit && opt->type != AV_OPT_TYPE_CONST) {
     529           0 :             opt_list(obj, av_log_obj, opt->unit, req_flags, rej_flags);
     530             :         }
     531             :     }
     532           0 : }
     533             : 
     534           0 : int av_opt_show2(void *obj, void *av_log_obj, int req_flags, int rej_flags)
     535             : {
     536           0 :     if (!obj)
     537           0 :         return -1;
     538             : 
     539           0 :     av_log(av_log_obj, AV_LOG_INFO, "%s AVOptions:\n", (*(AVClass**)obj)->class_name);
     540             : 
     541           0 :     opt_list(obj, av_log_obj, NULL, req_flags, rej_flags);
     542             : 
     543           0 :     return 0;
     544             : }
     545             : 
     546           0 : void av_opt_set_defaults(void *s)
     547             : {
     548           0 :     const AVOption *opt = NULL;
     549           0 :     while ((opt = av_opt_next(s, opt))) {
     550           0 :         if (opt->flags & AV_OPT_FLAG_READONLY)
     551           0 :             continue;
     552             : 
     553           0 :         switch (opt->type) {
     554             :             case AV_OPT_TYPE_CONST:
     555             :                 /* Nothing to be done here */
     556           0 :             break;
     557             :             case AV_OPT_TYPE_FLAGS:
     558             :             case AV_OPT_TYPE_INT:
     559             :             case AV_OPT_TYPE_INT64:
     560           0 :                 av_opt_set_int(s, opt->name, opt->default_val.i64, 0);
     561           0 :             break;
     562             :             case AV_OPT_TYPE_DOUBLE:
     563             :             case AV_OPT_TYPE_FLOAT: {
     564             :                 double val;
     565           0 :                 val = opt->default_val.dbl;
     566           0 :                 av_opt_set_double(s, opt->name, val, 0);
     567             :             }
     568           0 :             break;
     569             :             case AV_OPT_TYPE_RATIONAL: {
     570             :                 AVRational val;
     571           0 :                 val = av_d2q(opt->default_val.dbl, INT_MAX);
     572           0 :                 av_opt_set_q(s, opt->name, val, 0);
     573             :             }
     574           0 :             break;
     575             :             case AV_OPT_TYPE_STRING:
     576           0 :                 av_opt_set(s, opt->name, opt->default_val.str, 0);
     577           0 :                 break;
     578             :             case AV_OPT_TYPE_BINARY:
     579             :             case AV_OPT_TYPE_DICT:
     580             :                 /* Cannot set defaults for these types */
     581           0 :             break;
     582             :             default:
     583           0 :                 av_log(s, AV_LOG_DEBUG, "AVOption type %d of option %s not implemented yet\n", opt->type, opt->name);
     584             :         }
     585             :     }
     586           0 : }
     587             : 
     588             : /**
     589             :  * Store the value in the field in ctx that is named like key.
     590             :  * ctx must be an AVClass context, storing is done using AVOptions.
     591             :  *
     592             :  * @param buf the string to parse, buf will be updated to point at the
     593             :  * separator just after the parsed key/value pair
     594             :  * @param key_val_sep a 0-terminated list of characters used to
     595             :  * separate key from value
     596             :  * @param pairs_sep a 0-terminated list of characters used to separate
     597             :  * two pairs from each other
     598             :  * @return 0 if the key/value pair has been successfully parsed and
     599             :  * set, or a negative value corresponding to an AVERROR code in case
     600             :  * of error:
     601             :  * AVERROR(EINVAL) if the key/value pair cannot be parsed,
     602             :  * the error code issued by av_opt_set() if the key/value pair
     603             :  * cannot be set
     604             :  */
     605           0 : static int parse_key_value_pair(void *ctx, const char **buf,
     606             :                                 const char *key_val_sep, const char *pairs_sep)
     607             : {
     608           0 :     char *key = av_get_token(buf, key_val_sep);
     609             :     char *val;
     610             :     int ret;
     611             : 
     612           0 :     if (!key)
     613           0 :         return AVERROR(ENOMEM);
     614             : 
     615           0 :     if (*key && strspn(*buf, key_val_sep)) {
     616           0 :         (*buf)++;
     617           0 :         val = av_get_token(buf, pairs_sep);
     618           0 :         if (!val) {
     619           0 :             av_freep(&key);
     620           0 :             return AVERROR(ENOMEM);
     621             :         }
     622             :     } else {
     623           0 :         av_log(ctx, AV_LOG_ERROR, "Missing key or no key/value separator found after key '%s'\n", key);
     624           0 :         av_free(key);
     625           0 :         return AVERROR(EINVAL);
     626             :     }
     627             : 
     628           0 :     av_log(ctx, AV_LOG_DEBUG, "Setting value '%s' for key '%s'\n", val, key);
     629             : 
     630           0 :     ret = av_opt_set(ctx, key, val, AV_OPT_SEARCH_CHILDREN);
     631           0 :     if (ret == AVERROR_OPTION_NOT_FOUND)
     632           0 :         av_log(ctx, AV_LOG_ERROR, "Key '%s' not found.\n", key);
     633             : 
     634           0 :     av_free(key);
     635           0 :     av_free(val);
     636           0 :     return ret;
     637             : }
     638             : 
     639           0 : int av_set_options_string(void *ctx, const char *opts,
     640             :                           const char *key_val_sep, const char *pairs_sep)
     641             : {
     642           0 :     int ret, count = 0;
     643             : 
     644           0 :     if (!opts)
     645           0 :         return 0;
     646             : 
     647           0 :     while (*opts) {
     648           0 :         if ((ret = parse_key_value_pair(ctx, &opts, key_val_sep, pairs_sep)) < 0)
     649           0 :             return ret;
     650           0 :         count++;
     651             : 
     652           0 :         if (*opts)
     653           0 :             opts++;
     654             :     }
     655             : 
     656           0 :     return count;
     657             : }
     658             : 
     659           0 : void av_opt_free(void *obj)
     660             : {
     661           0 :     const AVOption *o = NULL;
     662           0 :     while ((o = av_opt_next(obj, o))) {
     663           0 :         switch (o->type) {
     664             :         case AV_OPT_TYPE_STRING:
     665             :         case AV_OPT_TYPE_BINARY:
     666           0 :             av_freep((uint8_t *)obj + o->offset);
     667           0 :             break;
     668             : 
     669             :         case AV_OPT_TYPE_DICT:
     670           0 :             av_dict_free((AVDictionary **)(((uint8_t *)obj) + o->offset));
     671           0 :             break;
     672             : 
     673             :         default:
     674           0 :             break;
     675             :         }
     676             :     }
     677           0 : }
     678             : 
     679           0 : int av_opt_set_dict(void *obj, AVDictionary **options)
     680             : {
     681           0 :     AVDictionaryEntry *t = NULL;
     682           0 :     AVDictionary    *tmp = NULL;
     683           0 :     int ret = 0;
     684             : 
     685           0 :     while ((t = av_dict_get(*options, "", t, AV_DICT_IGNORE_SUFFIX))) {
     686           0 :         ret = av_opt_set(obj, t->key, t->value, 0);
     687           0 :         if (ret == AVERROR_OPTION_NOT_FOUND)
     688           0 :             av_dict_set(&tmp, t->key, t->value, 0);
     689           0 :         else if (ret < 0) {
     690           0 :             av_log(obj, AV_LOG_ERROR, "Error setting option %s to value %s.\n", t->key, t->value);
     691           0 :             break;
     692             :         }
     693           0 :         ret = 0;
     694             :     }
     695           0 :     av_dict_free(options);
     696           0 :     *options = tmp;
     697           0 :     return ret;
     698             : }
     699             : 
     700           0 : const AVOption *av_opt_find(void *obj, const char *name, const char *unit,
     701             :                             int opt_flags, int search_flags)
     702             : {
     703           0 :     return av_opt_find2(obj, name, unit, opt_flags, search_flags, NULL);
     704             : }
     705             : 
     706           0 : const AVOption *av_opt_find2(void *obj, const char *name, const char *unit,
     707             :                              int opt_flags, int search_flags, void **target_obj)
     708             : {
     709           0 :     const AVClass  *c = *(AVClass**)obj;
     710           0 :     const AVOption *o = NULL;
     711             : 
     712           0 :     if (!c)
     713           0 :         return NULL;
     714             : 
     715           0 :     if (search_flags & AV_OPT_SEARCH_CHILDREN) {
     716           0 :         if (search_flags & AV_OPT_SEARCH_FAKE_OBJ) {
     717           0 :             const AVClass *child = NULL;
     718           0 :             while (child = av_opt_child_class_next(c, child))
     719           0 :                 if (o = av_opt_find2(&child, name, unit, opt_flags, search_flags, NULL))
     720           0 :                     return o;
     721             :         } else {
     722           0 :             void *child = NULL;
     723           0 :             while (child = av_opt_child_next(obj, child))
     724           0 :                 if (o = av_opt_find2(child, name, unit, opt_flags, search_flags, target_obj))
     725           0 :                     return o;
     726             :         }
     727             :     }
     728             : 
     729           0 :     while (o = av_opt_next(obj, o)) {
     730           0 :         if (!strcmp(o->name, name) && (o->flags & opt_flags) == opt_flags &&
     731           0 :             ((!unit && o->type != AV_OPT_TYPE_CONST) ||
     732           0 :              (unit  && o->unit && !strcmp(o->unit, unit)))) {
     733           0 :             if (target_obj) {
     734           0 :                 if (!(search_flags & AV_OPT_SEARCH_FAKE_OBJ))
     735           0 :                     *target_obj = obj;
     736             :                 else
     737           0 :                     *target_obj = NULL;
     738             :             }
     739           0 :             return o;
     740             :         }
     741             :     }
     742           0 :     return NULL;
     743             : }
     744             : 
     745           0 : void *av_opt_child_next(void *obj, void *prev)
     746             : {
     747           0 :     const AVClass *c = *(AVClass**)obj;
     748           0 :     if (c->child_next)
     749           0 :         return c->child_next(obj, prev);
     750           0 :     return NULL;
     751             : }
     752             : 
     753           0 : const AVClass *av_opt_child_class_next(const AVClass *parent, const AVClass *prev)
     754             : {
     755           0 :     if (parent->child_class_next)
     756           0 :         return parent->child_class_next(prev);
     757           0 :     return NULL;
     758             : }
     759             : 
     760             : #ifdef TEST
     761             : 
     762             : typedef struct TestContext
     763             : {
     764             :     const AVClass *class;
     765             :     int num;
     766             :     int toggle;
     767             :     char *string;
     768             :     int flags;
     769             :     AVRational rational;
     770             : } TestContext;
     771             : 
     772             : #define OFFSET(x) offsetof(TestContext, x)
     773             : 
     774             : #define TEST_FLAG_COOL 01
     775             : #define TEST_FLAG_LAME 02
     776             : #define TEST_FLAG_MU   04
     777             : 
     778             : static const AVOption test_options[]= {
     779             : {"num",      "set num",        OFFSET(num),      AV_OPT_TYPE_INT,      {.i64 = 0},       0,        100                 },
     780             : {"toggle",   "set toggle",     OFFSET(toggle),   AV_OPT_TYPE_INT,      {.i64 = 0},       0,        1                   },
     781             : {"rational", "set rational",   OFFSET(rational), AV_OPT_TYPE_RATIONAL, {.dbl = 0},  0,        10                  },
     782             : {"string",   "set string",     OFFSET(string),   AV_OPT_TYPE_STRING,   {0},              CHAR_MIN, CHAR_MAX            },
     783             : {"flags",    "set flags",      OFFSET(flags),    AV_OPT_TYPE_FLAGS,    {.i64 = 0},       0,        INT_MAX, 0, "flags" },
     784             : {"cool",     "set cool flag ", 0,                AV_OPT_TYPE_CONST,    {.i64 = TEST_FLAG_COOL}, INT_MIN,  INT_MAX, 0, "flags" },
     785             : {"lame",     "set lame flag ", 0,                AV_OPT_TYPE_CONST,    {.i64 = TEST_FLAG_LAME}, INT_MIN,  INT_MAX, 0, "flags" },
     786             : {"mu",       "set mu flag ",   0,                AV_OPT_TYPE_CONST,    {.i64 = TEST_FLAG_MU},   INT_MIN,  INT_MAX, 0, "flags" },
     787             : {NULL},
     788             : };
     789             : 
     790             : static const char *test_get_name(void *ctx)
     791             : {
     792             :     return "test";
     793             : }
     794             : 
     795             : static const AVClass test_class = {
     796             :     "TestContext",
     797             :     test_get_name,
     798             :     test_options
     799             : };
     800             : 
     801             : int main(void)
     802             : {
     803             :     int i;
     804             : 
     805             :     printf("\nTesting av_set_options_string()\n");
     806             :     {
     807             :         TestContext test_ctx;
     808             :         const char *options[] = {
     809             :             "",
     810             :             ":",
     811             :             "=",
     812             :             "foo=:",
     813             :             ":=foo",
     814             :             "=foo",
     815             :             "foo=",
     816             :             "foo",
     817             :             "foo=val",
     818             :             "foo==val",
     819             :             "toggle=:",
     820             :             "string=:",
     821             :             "toggle=1 : foo",
     822             :             "toggle=100",
     823             :             "toggle==1",
     824             :             "flags=+mu-lame : num=42: toggle=0",
     825             :             "num=42 : string=blahblah",
     826             :             "rational=0 : rational=1/2 : rational=1/-1",
     827             :             "rational=-1/0",
     828             :         };
     829             : 
     830             :         test_ctx.class = &test_class;
     831             :         av_opt_set_defaults(&test_ctx);
     832             :         test_ctx.string = av_strdup("default");
     833             : 
     834             :         av_log_set_level(AV_LOG_DEBUG);
     835             : 
     836             :         for (i=0; i < FF_ARRAY_ELEMS(options); i++) {
     837             :             av_log(&test_ctx, AV_LOG_DEBUG, "Setting options string '%s'\n", options[i]);
     838             :             if (av_set_options_string(&test_ctx, options[i], "=", ":") < 0)
     839             :                 av_log(&test_ctx, AV_LOG_ERROR, "Error setting options string: '%s'\n", options[i]);
     840             :             printf("\n");
     841             :         }
     842             :     }
     843             : 
     844             :     return 0;
     845             : }
     846             : 
     847             : #endif

Generated by: LCOV version 1.13