1022
|
1 /*
|
|
2 * AVOptions
|
|
3 * Copyright (c) 2005 Michael Niedermayer <michaelni@gmx.at>
|
|
4 *
|
|
5 * This file is part of FFmpeg.
|
|
6 *
|
|
7 * FFmpeg 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 * FFmpeg 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 FFmpeg; 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 "opt.h"
|
|
30 #include "libavutil/eval.h"
|
|
31
|
|
32 //FIXME order them and do a bin search
|
|
33 const AVOption *av_find_opt(void *v, const char *name, const char *unit, int mask, int flags){
|
|
34 AVClass *c= *(AVClass**)v; //FIXME silly way of storing AVClass
|
|
35 const AVOption *o= c->option;
|
|
36
|
|
37 for(;o && o->name; o++){
|
|
38 if(!strcmp(o->name, name) && (!unit || (o->unit && !strcmp(o->unit, unit))) && (o->flags & mask) == flags )
|
|
39 return o;
|
|
40 }
|
|
41 return NULL;
|
|
42 }
|
|
43
|
|
44 const AVOption *av_next_option(void *obj, const AVOption *last){
|
|
45 if(last && last[1].name) return ++last;
|
|
46 else if(last) return NULL;
|
|
47 else return (*(AVClass**)obj)->option;
|
|
48 }
|
|
49
|
|
50 static int av_set_number2(void *obj, const char *name, double num, int den, int64_t intnum, const AVOption **o_out){
|
|
51 const AVOption *o= av_find_opt(obj, name, NULL, 0, 0);
|
|
52 void *dst;
|
|
53 if(o_out)
|
|
54 *o_out= o;
|
|
55 if(!o || o->offset<=0)
|
|
56 return AVERROR(ENOENT);
|
|
57
|
|
58 if(o->max*den < num*intnum || o->min*den > num*intnum) {
|
|
59 av_log(obj, AV_LOG_ERROR, "Value %lf for parameter '%s' out of range\n", num, name);
|
|
60 return AVERROR(ERANGE);
|
|
61 }
|
|
62
|
|
63 dst= ((uint8_t*)obj) + o->offset;
|
|
64
|
|
65 switch(o->type){
|
|
66 case FF_OPT_TYPE_FLAGS:
|
|
67 case FF_OPT_TYPE_INT: *(int *)dst= llrint(num/den)*intnum; break;
|
|
68 case FF_OPT_TYPE_INT64: *(int64_t *)dst= llrint(num/den)*intnum; break;
|
|
69 case FF_OPT_TYPE_FLOAT: *(float *)dst= num*intnum/den; break;
|
|
70 case FF_OPT_TYPE_DOUBLE:*(double *)dst= num*intnum/den; break;
|
|
71 case FF_OPT_TYPE_RATIONAL:
|
|
72 if((int)num == num) *(AVRational*)dst= (AVRational){num*intnum, den};
|
|
73 else *(AVRational*)dst= av_d2q(num*intnum/den, 1<<24);
|
|
74 break;
|
|
75 default:
|
|
76 return AVERROR(EINVAL);
|
|
77 }
|
|
78 return 0;
|
|
79 }
|
|
80
|
|
81 static const AVOption *av_set_number(void *obj, const char *name, double num, int den, int64_t intnum){
|
|
82 const AVOption *o = NULL;
|
|
83 if (av_set_number2(obj, name, num, den, intnum, &o) < 0)
|
|
84 return NULL;
|
|
85 else
|
|
86 return o;
|
|
87 }
|
|
88
|
|
89 static const double const_values[]={
|
|
90 M_PI,
|
|
91 M_E,
|
|
92 FF_QP2LAMBDA,
|
|
93 0
|
|
94 };
|
|
95
|
|
96 static const char * const const_names[]={
|
|
97 "PI",
|
|
98 "E",
|
|
99 "QP2LAMBDA",
|
|
100 0
|
|
101 };
|
|
102
|
|
103 static int hexchar2int(char c) {
|
|
104 if (c >= '0' && c <= '9') return c - '0';
|
|
105 if (c >= 'a' && c <= 'f') return c - 'a' + 10;
|
|
106 if (c >= 'A' && c <= 'F') return c - 'A' + 10;
|
|
107 return -1;
|
|
108 }
|
|
109
|
|
110 int av_set_string3(void *obj, const char *name, const char *val, int alloc, const AVOption **o_out){
|
|
111 int ret;
|
|
112 const AVOption *o= av_find_opt(obj, name, NULL, 0, 0);
|
|
113 if (o_out)
|
|
114 *o_out = o;
|
|
115 if(!o)
|
|
116 return AVERROR(ENOENT);
|
|
117 if(!val || o->offset<=0)
|
|
118 return AVERROR(EINVAL);
|
|
119
|
|
120 if(o->type == FF_OPT_TYPE_BINARY){
|
|
121 uint8_t **dst = (uint8_t **)(((uint8_t*)obj) + o->offset);
|
|
122 int *lendst = (int *)(dst + 1);
|
|
123 uint8_t *bin, *ptr;
|
|
124 int len = strlen(val);
|
|
125 av_freep(dst);
|
|
126 *lendst = 0;
|
|
127 if (len & 1) return AVERROR(EINVAL);
|
|
128 len /= 2;
|
|
129 ptr = bin = av_malloc(len);
|
|
130 while (*val) {
|
|
131 int a = hexchar2int(*val++);
|
|
132 int b = hexchar2int(*val++);
|
|
133 if (a < 0 || b < 0) {
|
|
134 av_free(bin);
|
|
135 return AVERROR(EINVAL);
|
|
136 }
|
|
137 *ptr++ = (a << 4) | b;
|
|
138 }
|
|
139 *dst = bin;
|
|
140 *lendst = len;
|
|
141 return 0;
|
|
142 }
|
|
143 if(o->type != FF_OPT_TYPE_STRING){
|
|
144 int notfirst=0;
|
|
145 for(;;){
|
|
146 int i;
|
|
147 char buf[256];
|
|
148 int cmd=0;
|
|
149 double d;
|
|
150
|
|
151 if(*val == '+' || *val == '-')
|
|
152 cmd= *(val++);
|
|
153
|
|
154 for(i=0; i<sizeof(buf)-1 && val[i] && val[i]!='+' && val[i]!='-'; i++)
|
|
155 buf[i]= val[i];
|
|
156 buf[i]=0;
|
|
157
|
|
158 {
|
|
159 const AVOption *o_named= av_find_opt(obj, buf, o->unit, 0, 0);
|
|
160 if(o_named && o_named->type == FF_OPT_TYPE_CONST)
|
|
161 d= o_named->default_val;
|
|
162 else if(!strcmp(buf, "default")) d= o->default_val;
|
|
163 else if(!strcmp(buf, "max" )) d= o->max;
|
|
164 else if(!strcmp(buf, "min" )) d= o->min;
|
|
165 else if(!strcmp(buf, "none" )) d= 0;
|
|
166 else if(!strcmp(buf, "all" )) d= ~0;
|
|
167 else {
|
|
168 int res = av_parse_and_eval_expr(&d, buf, const_names, const_values, NULL, NULL, NULL, NULL, NULL, 0, obj);
|
|
169 if (res < 0) {
|
|
170 av_log(obj, AV_LOG_ERROR, "Unable to parse option value \"%s\"\n", val);
|
|
171 return res;
|
|
172 }
|
|
173 }
|
|
174 }
|
|
175 if(o->type == FF_OPT_TYPE_FLAGS){
|
|
176 if (cmd=='+') d= av_get_int(obj, name, NULL) | (int64_t)d;
|
|
177 else if(cmd=='-') d= av_get_int(obj, name, NULL) &~(int64_t)d;
|
|
178 }else{
|
|
179 if (cmd=='+') d= notfirst*av_get_double(obj, name, NULL) + d;
|
|
180 else if(cmd=='-') d= notfirst*av_get_double(obj, name, NULL) - d;
|
|
181 }
|
|
182
|
|
183 if ((ret = av_set_number2(obj, name, d, 1, 1, o_out)) < 0)
|
|
184 return ret;
|
|
185 val+= i;
|
|
186 if(!*val)
|
|
187 return 0;
|
|
188 notfirst=1;
|
|
189 }
|
|
190 return AVERROR(EINVAL);
|
|
191 }
|
|
192
|
|
193 if(alloc){
|
|
194 av_free(*(void**)(((uint8_t*)obj) + o->offset));
|
|
195 val= av_strdup(val);
|
|
196 }
|
|
197
|
|
198 memcpy(((uint8_t*)obj) + o->offset, &val, sizeof(val));
|
|
199 return 0;
|
|
200 }
|
|
201
|
|
202 const AVOption *av_set_double(void *obj, const char *name, double n){
|
|
203 return av_set_number(obj, name, n, 1, 1);
|
|
204 }
|
|
205
|
|
206 const AVOption *av_set_q(void *obj, const char *name, AVRational n){
|
|
207 return av_set_number(obj, name, n.num, n.den, 1);
|
|
208 }
|
|
209
|
|
210 const AVOption *av_set_int(void *obj, const char *name, int64_t n){
|
|
211 return av_set_number(obj, name, 1, 1, n);
|
|
212 }
|
|
213
|
|
214 /**
|
|
215 *
|
|
216 * @param buf a buffer which is used for returning non string values as strings, can be NULL
|
|
217 * @param buf_len allocated length in bytes of buf
|
|
218 */
|
|
219 const char *av_get_string(void *obj, const char *name, const AVOption **o_out, char *buf, int buf_len){
|
|
220 const AVOption *o= av_find_opt(obj, name, NULL, 0, 0);
|
|
221 void *dst;
|
|
222 uint8_t *bin;
|
|
223 int len, i;
|
|
224 if(!o || o->offset<=0)
|
|
225 return NULL;
|
|
226 if(o->type != FF_OPT_TYPE_STRING && (!buf || !buf_len))
|
|
227 return NULL;
|
|
228
|
|
229 dst= ((uint8_t*)obj) + o->offset;
|
|
230 if(o_out) *o_out= o;
|
|
231
|
|
232 switch(o->type){
|
|
233 case FF_OPT_TYPE_FLAGS: snprintf(buf, buf_len, "0x%08X",*(int *)dst);break;
|
|
234 case FF_OPT_TYPE_INT: snprintf(buf, buf_len, "%d" , *(int *)dst);break;
|
|
235 case FF_OPT_TYPE_INT64: snprintf(buf, buf_len, "%"PRId64, *(int64_t*)dst);break;
|
|
236 case FF_OPT_TYPE_FLOAT: snprintf(buf, buf_len, "%f" , *(float *)dst);break;
|
|
237 case FF_OPT_TYPE_DOUBLE: snprintf(buf, buf_len, "%f" , *(double *)dst);break;
|
|
238 case FF_OPT_TYPE_RATIONAL: snprintf(buf, buf_len, "%d/%d", ((AVRational*)dst)->num, ((AVRational*)dst)->den);break;
|
|
239 case FF_OPT_TYPE_STRING: return *(void**)dst;
|
|
240 case FF_OPT_TYPE_BINARY:
|
|
241 len = *(int*)(((uint8_t *)dst) + sizeof(uint8_t *));
|
|
242 if(len >= (buf_len + 1)/2) return NULL;
|
|
243 bin = *(uint8_t**)dst;
|
|
244 for(i = 0; i < len; i++) snprintf(buf + i*2, 3, "%02X", bin[i]);
|
|
245 break;
|
|
246 default: return NULL;
|
|
247 }
|
|
248 return buf;
|
|
249 }
|
|
250
|
|
251 static int av_get_number(void *obj, const char *name, const AVOption **o_out, double *num, int *den, int64_t *intnum){
|
|
252 const AVOption *o= av_find_opt(obj, name, NULL, 0, 0);
|
|
253 void *dst;
|
|
254 if(!o || o->offset<=0)
|
|
255 goto error;
|
|
256
|
|
257 dst= ((uint8_t*)obj) + o->offset;
|
|
258
|
|
259 if(o_out) *o_out= o;
|
|
260
|
|
261 switch(o->type){
|
|
262 case FF_OPT_TYPE_FLAGS: *intnum= *(unsigned int*)dst;return 0;
|
|
263 case FF_OPT_TYPE_INT: *intnum= *(int *)dst;return 0;
|
|
264 case FF_OPT_TYPE_INT64: *intnum= *(int64_t*)dst;return 0;
|
|
265 case FF_OPT_TYPE_FLOAT: *num= *(float *)dst;return 0;
|
|
266 case FF_OPT_TYPE_DOUBLE: *num= *(double *)dst;return 0;
|
|
267 case FF_OPT_TYPE_RATIONAL: *intnum= ((AVRational*)dst)->num;
|
|
268 *den = ((AVRational*)dst)->den;
|
|
269 return 0;
|
|
270 }
|
|
271 error:
|
|
272 *den=*intnum=0;
|
|
273 return -1;
|
|
274 }
|
|
275
|
|
276 double av_get_double(void *obj, const char *name, const AVOption **o_out){
|
|
277 int64_t intnum=1;
|
|
278 double num=1;
|
|
279 int den=1;
|
|
280
|
|
281 av_get_number(obj, name, o_out, &num, &den, &intnum);
|
|
282 return num*intnum/den;
|
|
283 }
|
|
284
|
|
285 AVRational av_get_q(void *obj, const char *name, const AVOption **o_out){
|
|
286 int64_t intnum=1;
|
|
287 double num=1;
|
|
288 int den=1;
|
|
289
|
|
290 av_get_number(obj, name, o_out, &num, &den, &intnum);
|
|
291 if(num == 1.0 && (int)intnum == intnum)
|
|
292 return (AVRational){intnum, den};
|
|
293 else
|
|
294 return av_d2q(num*intnum/den, 1<<24);
|
|
295 }
|
|
296
|
|
297 int64_t av_get_int(void *obj, const char *name, const AVOption **o_out){
|
|
298 int64_t intnum=1;
|
|
299 double num=1;
|
|
300 int den=1;
|
|
301
|
|
302 av_get_number(obj, name, o_out, &num, &den, &intnum);
|
|
303 return num*intnum/den;
|
|
304 }
|
|
305
|
|
306 static void opt_list(void *obj, void *av_log_obj, const char *unit,
|
|
307 int req_flags, int rej_flags)
|
|
308 {
|
|
309 const AVOption *opt=NULL;
|
|
310
|
|
311 while((opt= av_next_option(obj, opt))){
|
|
312 if (!(opt->flags & req_flags) || (opt->flags & rej_flags))
|
|
313 continue;
|
|
314
|
|
315 /* Don't print CONST's on level one.
|
|
316 * Don't print anything but CONST's on level two.
|
|
317 * Only print items from the requested unit.
|
|
318 */
|
|
319 if (!unit && opt->type==FF_OPT_TYPE_CONST)
|
|
320 continue;
|
|
321 else if (unit && opt->type!=FF_OPT_TYPE_CONST)
|
|
322 continue;
|
|
323 else if (unit && opt->type==FF_OPT_TYPE_CONST && strcmp(unit, opt->unit))
|
|
324 continue;
|
|
325 else if (unit && opt->type == FF_OPT_TYPE_CONST)
|
|
326 av_log(av_log_obj, AV_LOG_INFO, " %-15s ", opt->name);
|
|
327 else
|
|
328 av_log(av_log_obj, AV_LOG_INFO, "-%-17s ", opt->name);
|
|
329
|
|
330 switch( opt->type )
|
|
331 {
|
|
332 case FF_OPT_TYPE_FLAGS:
|
|
333 av_log( av_log_obj, AV_LOG_INFO, "%-7s ", "<flags>" );
|
|
334 break;
|
|
335 case FF_OPT_TYPE_INT:
|
|
336 av_log( av_log_obj, AV_LOG_INFO, "%-7s ", "<int>" );
|
|
337 break;
|
|
338 case FF_OPT_TYPE_INT64:
|
|
339 av_log( av_log_obj, AV_LOG_INFO, "%-7s ", "<int64>" );
|
|
340 break;
|
|
341 case FF_OPT_TYPE_DOUBLE:
|
|
342 av_log( av_log_obj, AV_LOG_INFO, "%-7s ", "<double>" );
|
|
343 break;
|
|
344 case FF_OPT_TYPE_FLOAT:
|
|
345 av_log( av_log_obj, AV_LOG_INFO, "%-7s ", "<float>" );
|
|
346 break;
|
|
347 case FF_OPT_TYPE_STRING:
|
|
348 av_log( av_log_obj, AV_LOG_INFO, "%-7s ", "<string>" );
|
|
349 break;
|
|
350 case FF_OPT_TYPE_RATIONAL:
|
|
351 av_log( av_log_obj, AV_LOG_INFO, "%-7s ", "<rational>" );
|
|
352 break;
|
|
353 case FF_OPT_TYPE_BINARY:
|
|
354 av_log( av_log_obj, AV_LOG_INFO, "%-7s ", "<binary>" );
|
|
355 break;
|
|
356 case FF_OPT_TYPE_CONST:
|
|
357 default:
|
|
358 av_log( av_log_obj, AV_LOG_INFO, "%-7s ", "" );
|
|
359 break;
|
|
360 }
|
|
361 av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_ENCODING_PARAM) ? 'E' : '.');
|
|
362 av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_DECODING_PARAM) ? 'D' : '.');
|
|
363 av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_VIDEO_PARAM ) ? 'V' : '.');
|
|
364 av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_AUDIO_PARAM ) ? 'A' : '.');
|
|
365 av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_SUBTITLE_PARAM) ? 'S' : '.');
|
|
366
|
|
367 if(opt->help)
|
|
368 av_log(av_log_obj, AV_LOG_INFO, " %s", opt->help);
|
|
369 av_log(av_log_obj, AV_LOG_INFO, "\n");
|
|
370 if (opt->unit && opt->type != FF_OPT_TYPE_CONST) {
|
|
371 opt_list(obj, av_log_obj, opt->unit, req_flags, rej_flags);
|
|
372 }
|
|
373 }
|
|
374 }
|
|
375
|
|
376 int av_opt_show2(void *obj, void *av_log_obj, int req_flags, int rej_flags)
|
|
377 {
|
|
378 if(!obj)
|
|
379 return -1;
|
|
380
|
|
381 av_log(av_log_obj, AV_LOG_INFO, "%s AVOptions:\n", (*(AVClass**)obj)->class_name);
|
|
382
|
|
383 opt_list(obj, av_log_obj, NULL, req_flags, rej_flags);
|
|
384
|
|
385 return 0;
|
|
386 }
|
|
387
|
|
388 /** Set the values of the AVCodecContext or AVFormatContext structure.
|
|
389 * They are set to the defaults specified in the according AVOption options
|
|
390 * array default_val field.
|
|
391 *
|
|
392 * @param s AVCodecContext or AVFormatContext for which the defaults will be set
|
|
393 */
|
|
394 void av_opt_set_defaults2(void *s, int mask, int flags)
|
|
395 {
|
|
396 const AVOption *opt = NULL;
|
|
397 while ((opt = av_next_option(s, opt)) != NULL) {
|
|
398 if((opt->flags & mask) != flags)
|
|
399 continue;
|
|
400 switch(opt->type) {
|
|
401 case FF_OPT_TYPE_CONST:
|
|
402 /* Nothing to be done here */
|
|
403 break;
|
|
404 case FF_OPT_TYPE_FLAGS:
|
|
405 case FF_OPT_TYPE_INT: {
|
|
406 int val;
|
|
407 val = opt->default_val;
|
|
408 av_set_int(s, opt->name, val);
|
|
409 }
|
|
410 break;
|
|
411 case FF_OPT_TYPE_INT64:
|
|
412 if((double)(opt->default_val+0.6) == opt->default_val)
|
|
413 av_log(s, AV_LOG_DEBUG, "loss of precision in default of %s\n", opt->name);
|
|
414 av_set_int(s, opt->name, opt->default_val);
|
|
415 break;
|
|
416 case FF_OPT_TYPE_FLOAT: {
|
|
417 double val;
|
|
418 val = opt->default_val;
|
|
419 av_set_double(s, opt->name, val);
|
|
420 }
|
|
421 break;
|
|
422 case FF_OPT_TYPE_RATIONAL: {
|
|
423 AVRational val;
|
|
424 val = av_d2q(opt->default_val, INT_MAX);
|
|
425 av_set_q(s, opt->name, val);
|
|
426 }
|
|
427 break;
|
|
428 case FF_OPT_TYPE_STRING:
|
|
429 case FF_OPT_TYPE_BINARY:
|
|
430 /* Cannot set default for string as default_val is of type * double */
|
|
431 break;
|
|
432 default:
|
|
433 av_log(s, AV_LOG_DEBUG, "AVOption type %d of option %s not implemented yet\n", opt->type, opt->name);
|
|
434 }
|
|
435 }
|
|
436 }
|
|
437
|
|
438 void av_opt_set_defaults(void *s){
|
|
439 av_opt_set_defaults2(s, 0, 0);
|
|
440 }
|
|
441
|