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 "avcodec.h" 29#include "opt.h" 30#include "eval.h" 31 32//FIXME order them and do a bin search 33const 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 44const 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 50static 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 81static 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 89static const double const_values[]={ 90 M_PI, 91 M_E, 92 FF_QP2LAMBDA, 93 0 94}; 95 96static const char * const const_names[]={ 97 "PI", 98 "E", 99 "QP2LAMBDA", 100 0 101}; 102 103static 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 110int 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 const char *error = NULL; 151 152 if(*val == '+' || *val == '-') 153 cmd= *(val++); 154 155 for(i=0; i<sizeof(buf)-1 && val[i] && val[i]!='+' && val[i]!='-'; i++) 156 buf[i]= val[i]; 157 buf[i]=0; 158 159 d = ff_parse_and_eval_expr(buf, const_values, const_names, NULL, NULL, NULL, NULL, NULL, &error); 160 if(isnan(d)) { 161 const AVOption *o_named= av_find_opt(obj, buf, o->unit, 0, 0); 162 if(o_named && o_named->type == FF_OPT_TYPE_CONST) 163 d= o_named->default_val; 164 else if(!strcmp(buf, "default")) d= o->default_val; 165 else if(!strcmp(buf, "max" )) d= o->max; 166 else if(!strcmp(buf, "min" )) d= o->min; 167 else if(!strcmp(buf, "none" )) d= 0; 168 else if(!strcmp(buf, "all" )) d= ~0; 169 else { 170 if (error) 171 av_log(obj, AV_LOG_ERROR, "Unable to parse option value \"%s\": %s\n", val, error); 172 return AVERROR(EINVAL); 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#if LIBAVCODEC_VERSION_MAJOR < 53 203const AVOption *av_set_string2(void *obj, const char *name, const char *val, int alloc){ 204 const AVOption *o; 205 if (av_set_string3(obj, name, val, alloc, &o) < 0) 206 return NULL; 207 return o; 208} 209 210const AVOption *av_set_string(void *obj, const char *name, const char *val){ 211 const AVOption *o; 212 if (av_set_string3(obj, name, val, 0, &o) < 0) 213 return NULL; 214 return o; 215} 216#endif 217 218const AVOption *av_set_double(void *obj, const char *name, double n){ 219 return av_set_number(obj, name, n, 1, 1); 220} 221 222const AVOption *av_set_q(void *obj, const char *name, AVRational n){ 223 return av_set_number(obj, name, n.num, n.den, 1); 224} 225 226const AVOption *av_set_int(void *obj, const char *name, int64_t n){ 227 return av_set_number(obj, name, 1, 1, n); 228} 229 230/** 231 * 232 * @param buf a buffer which is used for returning non string values as strings, can be NULL 233 * @param buf_len allocated length in bytes of buf 234 */ 235const char *av_get_string(void *obj, const char *name, const AVOption **o_out, char *buf, int buf_len){ 236 const AVOption *o= av_find_opt(obj, name, NULL, 0, 0); 237 void *dst; 238 uint8_t *bin; 239 int len, i; 240 if(!o || o->offset<=0) 241 return NULL; 242 if(o->type != FF_OPT_TYPE_STRING && (!buf || !buf_len)) 243 return NULL; 244 245 dst= ((uint8_t*)obj) + o->offset; 246 if(o_out) *o_out= o; 247 248 switch(o->type){ 249 case FF_OPT_TYPE_FLAGS: snprintf(buf, buf_len, "0x%08X",*(int *)dst);break; 250 case FF_OPT_TYPE_INT: snprintf(buf, buf_len, "%d" , *(int *)dst);break; 251 case FF_OPT_TYPE_INT64: snprintf(buf, buf_len, "%"PRId64, *(int64_t*)dst);break; 252 case FF_OPT_TYPE_FLOAT: snprintf(buf, buf_len, "%f" , *(float *)dst);break; 253 case FF_OPT_TYPE_DOUBLE: snprintf(buf, buf_len, "%f" , *(double *)dst);break; 254 case FF_OPT_TYPE_RATIONAL: snprintf(buf, buf_len, "%d/%d", ((AVRational*)dst)->num, ((AVRational*)dst)->den);break; 255 case FF_OPT_TYPE_STRING: return *(void**)dst; 256 case FF_OPT_TYPE_BINARY: 257 len = *(int*)(((uint8_t *)dst) + sizeof(uint8_t *)); 258 if(len >= (buf_len + 1)/2) return NULL; 259 bin = *(uint8_t**)dst; 260 for(i = 0; i < len; i++) snprintf(buf + i*2, 3, "%02X", bin[i]); 261 break; 262 default: return NULL; 263 } 264 return buf; 265} 266 267static int av_get_number(void *obj, const char *name, const AVOption **o_out, double *num, int *den, int64_t *intnum){ 268 const AVOption *o= av_find_opt(obj, name, NULL, 0, 0); 269 void *dst; 270 if(!o || o->offset<=0) 271 goto error; 272 273 dst= ((uint8_t*)obj) + o->offset; 274 275 if(o_out) *o_out= o; 276 277 switch(o->type){ 278 case FF_OPT_TYPE_FLAGS: *intnum= *(unsigned int*)dst;return 0; 279 case FF_OPT_TYPE_INT: *intnum= *(int *)dst;return 0; 280 case FF_OPT_TYPE_INT64: *intnum= *(int64_t*)dst;return 0; 281 case FF_OPT_TYPE_FLOAT: *num= *(float *)dst;return 0; 282 case FF_OPT_TYPE_DOUBLE: *num= *(double *)dst;return 0; 283 case FF_OPT_TYPE_RATIONAL: *intnum= ((AVRational*)dst)->num; 284 *den = ((AVRational*)dst)->den; 285 return 0; 286 } 287error: 288 *den=*intnum=0; 289 return -1; 290} 291 292double av_get_double(void *obj, const char *name, const AVOption **o_out){ 293 int64_t intnum=1; 294 double num=1; 295 int den=1; 296 297 av_get_number(obj, name, o_out, &num, &den, &intnum); 298 return num*intnum/den; 299} 300 301AVRational av_get_q(void *obj, const char *name, const 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 if(num == 1.0 && (int)intnum == intnum) 308 return (AVRational){intnum, den}; 309 else 310 return av_d2q(num*intnum/den, 1<<24); 311} 312 313int64_t av_get_int(void *obj, const char *name, const AVOption **o_out){ 314 int64_t intnum=1; 315 double num=1; 316 int den=1; 317 318 av_get_number(obj, name, o_out, &num, &den, &intnum); 319 return num*intnum/den; 320} 321 322static void opt_list(void *obj, void *av_log_obj, const char *unit) 323{ 324 const AVOption *opt=NULL; 325 326 while((opt= av_next_option(obj, opt))){ 327 if(!(opt->flags & (AV_OPT_FLAG_ENCODING_PARAM|AV_OPT_FLAG_DECODING_PARAM))) 328 continue; 329 330 /* Don't print CONST's on level one. 331 * Don't print anything but CONST's on level two. 332 * Only print items from the requested unit. 333 */ 334 if (!unit && opt->type==FF_OPT_TYPE_CONST) 335 continue; 336 else if (unit && opt->type!=FF_OPT_TYPE_CONST) 337 continue; 338 else if (unit && opt->type==FF_OPT_TYPE_CONST && strcmp(unit, opt->unit)) 339 continue; 340 else if (unit && opt->type == FF_OPT_TYPE_CONST) 341 av_log(av_log_obj, AV_LOG_INFO, " %-15s ", opt->name); 342 else 343 av_log(av_log_obj, AV_LOG_INFO, "-%-17s ", opt->name); 344 345 switch( opt->type ) 346 { 347 case FF_OPT_TYPE_FLAGS: 348 av_log( av_log_obj, AV_LOG_INFO, "%-7s ", "<flags>" ); 349 break; 350 case FF_OPT_TYPE_INT: 351 av_log( av_log_obj, AV_LOG_INFO, "%-7s ", "<int>" ); 352 break; 353 case FF_OPT_TYPE_INT64: 354 av_log( av_log_obj, AV_LOG_INFO, "%-7s ", "<int64>" ); 355 break; 356 case FF_OPT_TYPE_DOUBLE: 357 av_log( av_log_obj, AV_LOG_INFO, "%-7s ", "<double>" ); 358 break; 359 case FF_OPT_TYPE_FLOAT: 360 av_log( av_log_obj, AV_LOG_INFO, "%-7s ", "<float>" ); 361 break; 362 case FF_OPT_TYPE_STRING: 363 av_log( av_log_obj, AV_LOG_INFO, "%-7s ", "<string>" ); 364 break; 365 case FF_OPT_TYPE_RATIONAL: 366 av_log( av_log_obj, AV_LOG_INFO, "%-7s ", "<rational>" ); 367 break; 368 case FF_OPT_TYPE_BINARY: 369 av_log( av_log_obj, AV_LOG_INFO, "%-7s ", "<binary>" ); 370 break; 371 case FF_OPT_TYPE_CONST: 372 default: 373 av_log( av_log_obj, AV_LOG_INFO, "%-7s ", "" ); 374 break; 375 } 376 av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_ENCODING_PARAM) ? 'E' : '.'); 377 av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_DECODING_PARAM) ? 'D' : '.'); 378 av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_VIDEO_PARAM ) ? 'V' : '.'); 379 av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_AUDIO_PARAM ) ? 'A' : '.'); 380 av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_SUBTITLE_PARAM) ? 'S' : '.'); 381 382 if(opt->help) 383 av_log(av_log_obj, AV_LOG_INFO, " %s", opt->help); 384 av_log(av_log_obj, AV_LOG_INFO, "\n"); 385 if (opt->unit && opt->type != FF_OPT_TYPE_CONST) { 386 opt_list(obj, av_log_obj, opt->unit); 387 } 388 } 389} 390 391int av_opt_show(void *obj, void *av_log_obj){ 392 if(!obj) 393 return -1; 394 395 av_log(av_log_obj, AV_LOG_INFO, "%s AVOptions:\n", (*(AVClass**)obj)->class_name); 396 397 opt_list(obj, av_log_obj, NULL); 398 399 return 0; 400} 401 402/** Set the values of the AVCodecContext or AVFormatContext structure. 403 * They are set to the defaults specified in the according AVOption options 404 * array default_val field. 405 * 406 * @param s AVCodecContext or AVFormatContext for which the defaults will be set 407 */ 408void av_opt_set_defaults2(void *s, int mask, int flags) 409{ 410 const AVOption *opt = NULL; 411 while ((opt = av_next_option(s, opt)) != NULL) { 412 if((opt->flags & mask) != flags) 413 continue; 414 switch(opt->type) { 415 case FF_OPT_TYPE_CONST: 416 /* Nothing to be done here */ 417 break; 418 case FF_OPT_TYPE_FLAGS: 419 case FF_OPT_TYPE_INT: { 420 int val; 421 val = opt->default_val; 422 av_set_int(s, opt->name, val); 423 } 424 break; 425 case FF_OPT_TYPE_INT64: 426 if((double)(opt->default_val+0.6) == opt->default_val) 427 av_log(s, AV_LOG_DEBUG, "loss of precision in default of %s\n", opt->name); 428 av_set_int(s, opt->name, opt->default_val); 429 break; 430 case FF_OPT_TYPE_FLOAT: { 431 double val; 432 val = opt->default_val; 433 av_set_double(s, opt->name, val); 434 } 435 break; 436 case FF_OPT_TYPE_RATIONAL: { 437 AVRational val; 438 val = av_d2q(opt->default_val, INT_MAX); 439 av_set_q(s, opt->name, val); 440 } 441 break; 442 case FF_OPT_TYPE_STRING: 443 case FF_OPT_TYPE_BINARY: 444 /* Cannot set default for string as default_val is of type * double */ 445 break; 446 default: 447 av_log(s, AV_LOG_DEBUG, "AVOption type %d of option %s not implemented yet\n", opt->type, opt->name); 448 } 449 } 450} 451 452void av_opt_set_defaults(void *s){ 453 av_opt_set_defaults2(s, 0, 0); 454} 455 456