]> git.sesse.net Git - ffmpeg/blob - libavcodec/opt.c
10528e8ab41655a26b9c9067003e1ee2391b9fe2
[ffmpeg] / libavcodec / opt.c
1 /*
2  * AVOptions
3  * Copyright (c) 2005 Michael Niedermayer <michaelni@gmx.at>
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18  *
19  */
20
21 /**
22  * @file opt.c
23  * AVOptions
24  * @author Michael Niedermayer <michaelni@gmx.at>
25  */
26
27 #include "avcodec.h"
28 #include "opt.h"
29
30 static int8_t si_prefixes['z' - 'E' + 1]={
31     ['y'-'E']= -24,
32     ['z'-'E']= -21,
33     ['a'-'E']= -18,
34     ['f'-'E']= -15,
35     ['p'-'E']= -12,
36     ['n'-'E']= - 9,
37     ['u'-'E']= - 6,
38     ['m'-'E']= - 3,
39     ['c'-'E']= - 2,
40     ['d'-'E']= - 1,
41     ['h'-'E']=   2,
42     ['k'-'E']=   3,
43     ['K'-'E']=   3,
44     ['M'-'E']=   6,
45     ['G'-'E']=   9,
46     ['T'-'E']=  12,
47     ['P'-'E']=  15,
48     ['E'-'E']=  18,
49     ['Z'-'E']=  21,
50     ['Y'-'E']=  24,
51 };
52
53 /** strtod() function extended with 'k', 'M', 'G', 'ki', 'Mi', 'Gi' and 'B'
54  * postfixes.  This allows using f.e. kB, MiB, G and B as a postfix. This
55  * function assumes that the unit of numbers is bits not bytes.
56  */
57 double av_strtod(const char *name, char **tail) {
58     double d;
59     int p = 0;
60     char *next;
61     d = strtod(name, &next);
62     /* if parsing succeeded, check for and interpret postfixes */
63     if (next!=name) {
64
65         if(*next >= 'E' && *next <= 'z'){
66             int e= si_prefixes[*next - 'E'];
67             if(e){
68                 if(next[1] == 'i'){
69                     d*= pow( 2, e/0.3);
70                     next+=2;
71                 }else{
72                     d*= pow(10, e);
73                     next++;
74                 }
75             }
76         }
77
78         if(*next=='B') {
79             d*=8;
80             *next++;
81         }
82     }
83     /* if requested, fill in tail with the position after the last parsed
84        character */
85     if (tail)
86         *tail = next;
87     return d;
88 }
89
90 static double av_parse_num(const char *name, char **tail){
91     double d;
92     d= av_strtod(name, tail);
93     if(*tail>name && (**tail=='/' || **tail==':'))
94         d/=av_strtod((*tail)+1, tail);
95     return d;
96 }
97
98 //FIXME order them and do a bin search
99 static AVOption *find_opt(void *v, const char *name, const char *unit){
100     AVClass *c= *(AVClass**)v; //FIXME silly way of storing AVClass
101     AVOption *o= c->option;
102
103     for(;o && o->name; o++){
104         if(!strcmp(o->name, name) && (!unit || !strcmp(o->unit, unit)) )
105             return o;
106     }
107     return NULL;
108 }
109
110 AVOption *av_next_option(void *obj, AVOption *last){
111     if(last && last[1].name) return ++last;
112     else if(last)            return NULL;
113     else                     return (*(AVClass**)obj)->option;
114 }
115
116 static AVOption *av_set_number(void *obj, const char *name, double num, int den, int64_t intnum){
117     AVOption *o= find_opt(obj, name, NULL);
118     void *dst;
119     if(!o || o->offset<=0)
120         return NULL;
121
122     if(o->max*den < num*intnum || o->min*den > num*intnum) {
123         av_log(NULL, AV_LOG_ERROR, "Value %lf for parameter '%s' out of range.\n", num, name);
124         return NULL;
125     }
126
127     dst= ((uint8_t*)obj) + o->offset;
128
129     switch(o->type){
130     case FF_OPT_TYPE_FLAGS:
131     case FF_OPT_TYPE_INT:   *(int       *)dst= lrintf(num/den)*intnum; break;
132     case FF_OPT_TYPE_INT64: *(int64_t   *)dst= lrintf(num/den)*intnum; break;
133     case FF_OPT_TYPE_FLOAT: *(float     *)dst= num*intnum/den;         break;
134     case FF_OPT_TYPE_DOUBLE:*(double    *)dst= num*intnum/den;         break;
135     case FF_OPT_TYPE_RATIONAL:
136         if((int)num == num) *(AVRational*)dst= (AVRational){num*intnum, den};
137         else                *(AVRational*)dst= av_d2q(num*intnum/den, 1<<24);
138     default:
139         return NULL;
140     }
141     return o;
142 }
143
144 static AVOption *set_all_opt(void *v, const char *unit, double d){
145     AVClass *c= *(AVClass**)v; //FIXME silly way of storing AVClass
146     AVOption *o= c->option;
147     AVOption *ret=NULL;
148
149     for(;o && o->name; o++){
150         if(o->type != FF_OPT_TYPE_CONST && o->unit && !strcmp(o->unit, unit)){
151             double tmp= d;
152             if(o->type == FF_OPT_TYPE_FLAGS)
153                 tmp= av_get_int(v, o->name, NULL) | (int64_t)d;
154
155             av_set_number(v, o->name, tmp, 1, 1);
156             ret= o;
157         }
158     }
159     return ret;
160 }
161
162 //FIXME use eval.c maybe?
163 AVOption *av_set_string(void *obj, const char *name, const char *val){
164     AVOption *o= find_opt(obj, name, NULL);
165     if(o && o->offset==0 && o->type == FF_OPT_TYPE_CONST && o->unit){
166         return set_all_opt(obj, o->unit, o->default_val);
167     }
168     if(!o || !val || o->offset<=0)
169         return NULL;
170     if(o->type != FF_OPT_TYPE_STRING){
171         for(;;){
172             int i;
173             char buf[256], *tail;
174             int cmd=0;
175             double d;
176
177             if(*val == '+' || *val == '-')
178                 cmd= *(val++);
179
180             for(i=0; i<sizeof(buf)-1 && val[i] && val[i]!='+' && val[i]!='-'; i++)
181                 buf[i]= val[i];
182             buf[i]=0;
183             val+= i;
184
185             d= av_parse_num(buf, &tail);
186             if(tail <= buf){
187                 AVOption *o_named= find_opt(obj, buf, o->unit);
188                 if(o_named && o_named->type == FF_OPT_TYPE_CONST)
189                     d= o_named->default_val;
190                 else if(!strcmp(buf, "default")) d= o->default_val;
191                 else if(!strcmp(buf, "max"    )) d= o->max;
192                 else if(!strcmp(buf, "min"    )) d= o->min;
193                 else return NULL;
194             }
195             if(o->type == FF_OPT_TYPE_FLAGS){
196                 if     (cmd=='+') d= av_get_int(obj, name, NULL) | (int64_t)d;
197                 else if(cmd=='-') d= av_get_int(obj, name, NULL) &~(int64_t)d;
198             }else if(cmd=='-')
199                 d= -d;
200
201             av_set_number(obj, name, d, 1, 1);
202             if(!*val)
203                 return o;
204         }
205         return NULL;
206     }
207
208     memcpy(((uint8_t*)obj) + o->offset, val, sizeof(val));
209     return o;
210 }
211
212 AVOption *av_set_double(void *obj, const char *name, double n){
213     return av_set_number(obj, name, n, 1, 1);
214 }
215
216 AVOption *av_set_q(void *obj, const char *name, AVRational n){
217     return av_set_number(obj, name, n.num, n.den, 1);
218 }
219
220 AVOption *av_set_int(void *obj, const char *name, int64_t n){
221     return av_set_number(obj, name, 1, 1, n);
222 }
223
224 /**
225  *
226  * @param buf a buffer which is used for returning non string values as strings, can be NULL
227  * @param buf_len allocated length in bytes of buf
228  */
229 const char *av_get_string(void *obj, const char *name, AVOption **o_out, char *buf, int buf_len){
230     AVOption *o= find_opt(obj, name, NULL);
231     void *dst;
232     if(!o || o->offset<=0)
233         return NULL;
234     if(o->type != FF_OPT_TYPE_STRING && (!buf || !buf_len))
235         return NULL;
236
237     dst= ((uint8_t*)obj) + o->offset;
238     if(o_out) *o_out= o;
239
240     if(o->type == FF_OPT_TYPE_STRING)
241         return dst;
242
243     switch(o->type){
244     case FF_OPT_TYPE_FLAGS:     snprintf(buf, buf_len, "0x%08X",*(int    *)dst);break;
245     case FF_OPT_TYPE_INT:       snprintf(buf, buf_len, "%d" , *(int    *)dst);break;
246     case FF_OPT_TYPE_INT64:     snprintf(buf, buf_len, "%"PRId64, *(int64_t*)dst);break;
247     case FF_OPT_TYPE_FLOAT:     snprintf(buf, buf_len, "%f" , *(float  *)dst);break;
248     case FF_OPT_TYPE_DOUBLE:    snprintf(buf, buf_len, "%f" , *(double *)dst);break;
249     case FF_OPT_TYPE_RATIONAL:  snprintf(buf, buf_len, "%d/%d", ((AVRational*)dst)->num, ((AVRational*)dst)->den);break;
250     default: return NULL;
251     }
252     return buf;
253 }
254
255 static int av_get_number(void *obj, const char *name, AVOption **o_out, double *num, int *den, int64_t *intnum){
256     AVOption *o= find_opt(obj, name, NULL);
257     void *dst;
258     if(!o || o->offset<=0)
259         goto error;
260
261     dst= ((uint8_t*)obj) + o->offset;
262
263     if(o_out) *o_out= o;
264
265     switch(o->type){
266     case FF_OPT_TYPE_FLAGS:
267     case FF_OPT_TYPE_INT:       *intnum= *(int    *)dst;return 0;
268     case FF_OPT_TYPE_INT64:     *intnum= *(int64_t*)dst;return 0;
269     case FF_OPT_TYPE_FLOAT:     *num=    *(float  *)dst;return 0;
270     case FF_OPT_TYPE_DOUBLE:    *num=    *(double *)dst;return 0;
271     case FF_OPT_TYPE_RATIONAL:  *intnum= ((AVRational*)dst)->num;
272                                 *den   = ((AVRational*)dst)->den;
273                                                         return 0;
274     }
275 error:
276     *den=*intnum=0;
277     return -1;
278 }
279
280 double av_get_double(void *obj, const char *name, AVOption **o_out){
281     int64_t intnum=1;
282     double num=1;
283     int den=1;
284
285     av_get_number(obj, name, o_out, &num, &den, &intnum);
286     return num*intnum/den;
287 }
288
289 AVRational av_get_q(void *obj, const char *name, AVOption **o_out){
290     int64_t intnum=1;
291     double num=1;
292     int den=1;
293
294     av_get_number(obj, name, o_out, &num, &den, &intnum);
295     if(num == 1.0 && (int)intnum == intnum)
296         return (AVRational){intnum, den};
297     else
298         return av_d2q(num*intnum/den, 1<<24);
299 }
300
301 int64_t av_get_int(void *obj, const char *name, AVOption **o_out){
302     int64_t intnum=1;
303     double num=1;
304     int den=1;
305
306     av_get_number(obj, name, o_out, &num, &den, &intnum);
307     return num*intnum/den;
308 }
309
310 int av_opt_show(void *obj, void *av_log_obj){
311     AVOption *opt=NULL;
312
313     if(!obj)
314         return -1;
315
316     av_log(av_log_obj, AV_LOG_INFO, "%s AVOptions:\n", (*(AVClass**)obj)->class_name);
317
318     while((opt= av_next_option(obj, opt))){
319         if(!(opt->flags & (AV_OPT_FLAG_ENCODING_PARAM|AV_OPT_FLAG_DECODING_PARAM)))
320             continue;
321
322         av_log(av_log_obj, AV_LOG_INFO, "-%-17s ", opt->name);
323
324         switch( opt->type )
325         {
326             case FF_OPT_TYPE_FLAGS:
327                 av_log( av_log_obj, AV_LOG_INFO, "%-7s ", "<flags>" );
328                 break;
329             case FF_OPT_TYPE_INT:
330                 av_log( av_log_obj, AV_LOG_INFO, "%-7s ", "<int>" );
331                 break;
332             case FF_OPT_TYPE_INT64:
333                 av_log( av_log_obj, AV_LOG_INFO, "%-7s ", "<int64>" );
334                 break;
335             case FF_OPT_TYPE_DOUBLE:
336                 av_log( av_log_obj, AV_LOG_INFO, "%-7s ", "<double>" );
337                 break;
338             case FF_OPT_TYPE_FLOAT:
339                 av_log( av_log_obj, AV_LOG_INFO, "%-7s ", "<float>" );
340                 break;
341             case FF_OPT_TYPE_STRING:
342                 av_log( av_log_obj, AV_LOG_INFO, "%-7s ", "<string>" );
343                 break;
344             case FF_OPT_TYPE_RATIONAL:
345                 av_log( av_log_obj, AV_LOG_INFO, "%-7s ", "<rational>" );
346                 break;
347             case FF_OPT_TYPE_CONST:
348             default:
349                 av_log( av_log_obj, AV_LOG_INFO, "%-7s ", "" );
350                 break;
351         }
352         av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_ENCODING_PARAM) ? 'E' : '.');
353         av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_DECODING_PARAM) ? 'D' : '.');
354         av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_VIDEO_PARAM   ) ? 'V' : '.');
355         av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_AUDIO_PARAM   ) ? 'A' : '.');
356         av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_SUBTITLE_PARAM) ? 'S' : '.');
357
358         if(opt->help)
359             av_log(av_log_obj, AV_LOG_INFO, " %s", opt->help);
360         av_log(av_log_obj, AV_LOG_INFO, "\n");
361     }
362     return 0;
363 }
364
365 /** Set the values of the AVCodecContext or AVFormatContext structure.
366  * They are set to the defaults specified in the according AVOption options
367  * array default_val field.
368  *
369  * @param s AVCodecContext or AVFormatContext for which the defaults will be set
370  */
371 void av_opt_set_defaults(void *s)
372 {
373     AVOption *opt = NULL;
374     while ((opt = av_next_option(s, opt)) != NULL) {
375         switch(opt->type) {
376             case FF_OPT_TYPE_CONST:
377                 /* Nothing to be done here */
378             break;
379             case FF_OPT_TYPE_FLAGS:
380             case FF_OPT_TYPE_INT: {
381                 int val;
382                 val = opt->default_val;
383                 av_set_int(s, opt->name, val);
384             }
385             break;
386             case FF_OPT_TYPE_FLOAT: {
387                 double val;
388                 val = opt->default_val;
389                 av_set_double(s, opt->name, val);
390             }
391             break;
392             case FF_OPT_TYPE_RATIONAL: {
393                 AVRational val;
394                 val = av_d2q(opt->default_val, INT_MAX);
395                 av_set_q(s, opt->name, val);
396             }
397             break;
398             case FF_OPT_TYPE_STRING:
399                 /* Cannot set default for string as default_val is of type * double */
400             break;
401             default:
402                 av_log(s, AV_LOG_DEBUG, "AVOption type %d of option %s not implemented yet\n", opt->type, opt->name);
403         }
404     }
405 }
406