opt.c
上传用户:wstnjxml
上传日期:2014-04-03
资源大小:7248k
文件大小:9k
源码类别:

Windows CE

开发平台:

C/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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  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 double av_parse_num(const char *name, char **tail){
  31.     double d;
  32.     d= strtod(name, tail);
  33.     if(*tail>name && (**tail=='/' || **tail==':'))
  34.         d/=strtod((*tail)+1, tail);
  35.     return d;
  36. }
  37. //FIXME order them and do a bin search
  38. static AVOption *find_opt(void *v, const char *name, const char *unit){
  39.     AVClass *c= *(AVClass**)v; //FIXME silly way of storing AVClass
  40.     AVOption *o= c->option;
  41.     
  42.     for(;o && o->name; o++){
  43.         if(!strcmp(o->name, name) && (!unit || !strcmp(o->unit, unit)) )
  44.             return o;
  45.     }
  46.     return NULL;
  47. }
  48. AVOption *av_next_option(void *obj, AVOption *last){
  49.     if(last && last[1].name) return ++last;
  50.     else if(last)            return NULL;
  51.     else                     return (*(AVClass**)obj)->option;
  52. }
  53. static AVOption *av_set_number(void *obj, const char *name, double num, int den, int64_t intnum){
  54.     AVOption *o= find_opt(obj, name, NULL);
  55.     void *dst;
  56.     if(!o || o->offset<=0) 
  57.         return NULL;
  58.     
  59.     if(o->max*den < num*intnum || o->min*den > num*intnum)
  60.         return NULL;
  61.         
  62.     dst= ((uint8_t*)obj) + o->offset;
  63.     switch(o->type){
  64.     case FF_OPT_TYPE_FLAGS:   
  65.     case FF_OPT_TYPE_INT:   *(int       *)dst= lrintf(num/den)*intnum; break;
  66.     case FF_OPT_TYPE_INT64: *(int64_t   *)dst= lrintf(num/den)*intnum; break;
  67.     case FF_OPT_TYPE_FLOAT: *(float     *)dst= num*intnum/den;         break;
  68.     case FF_OPT_TYPE_DOUBLE:*(double    *)dst= num*intnum/den;         break;
  69.     case FF_OPT_TYPE_RATIONAL:
  70.         if((int)num == num) *(AVRational*)dst= (AVRational){num*intnum, den};
  71.         else                *(AVRational*)dst= av_d2q(num*intnum/den, 1<<24);
  72.     default:
  73.         return NULL;
  74.     }
  75.     return o;
  76. }
  77. static AVOption *set_all_opt(void *v, const char *unit, double d){
  78.     AVClass *c= *(AVClass**)v; //FIXME silly way of storing AVClass
  79.     AVOption *o= c->option;
  80.     AVOption *ret=NULL;
  81.     
  82.     for(;o && o->name; o++){
  83.         if(o->type != FF_OPT_TYPE_CONST && o->unit && !strcmp(o->unit, unit)){
  84.             double tmp= d;
  85.             if(o->type == FF_OPT_TYPE_FLAGS)
  86.                 tmp= av_get_int(v, o->name, NULL) | (int64_t)d;
  87.             av_set_number(v, o->name, tmp, 1, 1);
  88.             ret= o;
  89.         }
  90.     }
  91.     return ret;
  92. }
  93. //FIXME use eval.c maybe?
  94. AVOption *av_set_string(void *obj, const char *name, const char *val){
  95.     AVOption *o= find_opt(obj, name, NULL);
  96.     if(o && o->offset==0 && o->type == FF_OPT_TYPE_CONST && o->unit){
  97.         return set_all_opt(obj, o->unit, o->default_val);
  98.     }
  99.     if(!o || !val || o->offset<=0) 
  100.         return NULL;
  101.     if(o->type != FF_OPT_TYPE_STRING){
  102.         for(;;){
  103.             int i;
  104.             char buf[256], *tail;
  105.             int cmd=0;
  106.             double d;
  107.             if(*val == '+' || *val == '-')
  108.                 cmd= *(val++);
  109.             
  110.             for(i=0; i<sizeof(buf)-1 && val[i] && val[i]!='+' && val[i]!='-'; i++)
  111.                 buf[i]= val[i];
  112.             buf[i]=0;
  113.             val+= i;
  114.             
  115.             d= av_parse_num(buf, &tail);
  116.             if(tail <= buf){
  117.                 AVOption *o_named= find_opt(obj, buf, o->unit);
  118.                 if(o_named && o_named->type == FF_OPT_TYPE_CONST) 
  119.                     d= o_named->default_val;
  120.                 else if(!strcmp(buf, "default")) d= o->default_val;
  121.                 else if(!strcmp(buf, "max"    )) d= o->max;
  122.                 else if(!strcmp(buf, "min"    )) d= o->min;
  123.                 else return NULL;
  124.             }
  125.             if(o->type == FF_OPT_TYPE_FLAGS){
  126.                 if     (cmd=='+') d= av_get_int(obj, name, NULL) | (int64_t)d;
  127.                 else if(cmd=='-') d= av_get_int(obj, name, NULL) &~(int64_t)d;
  128.             }else if(cmd=='-')
  129.                 d= -d;
  130.             av_set_number(obj, name, d, 1, 1);
  131.             if(!*val)
  132.                 return o;
  133.         }
  134.         return NULL;
  135.     }
  136.     
  137.     memcpy(((uint8_t*)obj) + o->offset, val, sizeof(val));
  138.     return o;
  139. }
  140. AVOption *av_set_double(void *obj, const char *name, double n){
  141.     return av_set_number(obj, name, n, 1, 1);
  142. }
  143. AVOption *av_set_q(void *obj, const char *name, AVRational n){
  144.     return av_set_number(obj, name, n.num, n.den, 1);
  145. }
  146. AVOption *av_set_int(void *obj, const char *name, int64_t n){
  147.     return av_set_number(obj, name, 1, 1, n);
  148. }
  149. /**
  150.  * 
  151.  * @param buf a buffer which is used for returning non string values as strings, can be NULL
  152.  * @param buf_len allocated length in bytes of buf
  153.  */
  154. const char *av_get_string(void *obj, const char *name, AVOption **o_out, char *buf, int buf_len){
  155.     AVOption *o= find_opt(obj, name, NULL);
  156.     void *dst;
  157.     if(!o || o->offset<=0)
  158.         return NULL;
  159.     if(o->type != FF_OPT_TYPE_STRING && (!buf || !buf_len))
  160.         return NULL;
  161.     dst= ((uint8_t*)obj) + o->offset;
  162.     if(o_out) *o_out= o;
  163.     
  164.     if(o->type == FF_OPT_TYPE_STRING)
  165.         return dst;
  166.     
  167.     switch(o->type){
  168.     case FF_OPT_TYPE_FLAGS:     snprintf(buf, buf_len, "0x%08X",*(int    *)dst);break;
  169.     case FF_OPT_TYPE_INT:       snprintf(buf, buf_len, "%d" , *(int    *)dst);break;
  170.     case FF_OPT_TYPE_INT64:     snprintf(buf, buf_len, "%Ld", *(int64_t*)dst);break;
  171.     case FF_OPT_TYPE_FLOAT:     snprintf(buf, buf_len, "%f" , *(float  *)dst);break;
  172.     case FF_OPT_TYPE_DOUBLE:    snprintf(buf, buf_len, "%f" , *(double *)dst);break;
  173.     case FF_OPT_TYPE_RATIONAL:  snprintf(buf, buf_len, "%d/%d", ((AVRational*)dst)->num, ((AVRational*)dst)->den);break;
  174.     default: return NULL;
  175.     }
  176.     return buf;
  177. }
  178. static int av_get_number(void *obj, const char *name, AVOption **o_out, double *num, int *den, int64_t *intnum){
  179.     AVOption *o= find_opt(obj, name, NULL);
  180.     void *dst;
  181.     if(!o || o->offset<=0)
  182.         goto error;
  183.     dst= ((uint8_t*)obj) + o->offset;
  184.     if(o_out) *o_out= o;
  185.     switch(o->type){
  186.     case FF_OPT_TYPE_FLAGS:   
  187.     case FF_OPT_TYPE_INT:       *intnum= *(int    *)dst;return 0;
  188.     case FF_OPT_TYPE_INT64:     *intnum= *(int64_t*)dst;return 0;
  189.     case FF_OPT_TYPE_FLOAT:     *num=    *(float  *)dst;return 0;
  190.     case FF_OPT_TYPE_DOUBLE:    *num=    *(double *)dst;return 0;
  191.     case FF_OPT_TYPE_RATIONAL:  *intnum= ((AVRational*)dst)->num; 
  192.                                 *den   = ((AVRational*)dst)->den;
  193.                                                         return 0;
  194.     }
  195. error:
  196.     *den=*intnum=0;
  197.     return -1;
  198. }
  199. double av_get_double(void *obj, const char *name, AVOption **o_out){
  200.     int64_t intnum=1;
  201.     double num=1;
  202.     int den=1;
  203.     av_get_number(obj, name, o_out, &num, &den, &intnum);
  204.     return num*intnum/den;
  205. }
  206. AVRational av_get_q(void *obj, const char *name, AVOption **o_out){
  207.     int64_t intnum=1;
  208.     double num=1;
  209.     int den=1;
  210.     av_get_number(obj, name, o_out, &num, &den, &intnum);
  211.     if(num == 1.0 && (int)intnum == intnum)
  212.         return (AVRational){intnum, den};
  213.     else
  214.         return av_d2q(num*intnum/den, 1<<24);
  215. }
  216. int64_t av_get_int(void *obj, const char *name, AVOption **o_out){
  217.     int64_t intnum=1;
  218.     double num=1;
  219.     int den=1;
  220.     av_get_number(obj, name, o_out, &num, &den, &intnum);
  221.     return num*intnum/den;
  222. }
  223. int av_opt_show(void *obj, void *av_log_obj){
  224.     AVOption *opt=NULL;
  225.     
  226.     if(!obj)
  227.         return -1;
  228.     av_log(av_log_obj, AV_LOG_INFO, "%s AVOptions:n", (*(AVClass**)obj)->class_name);
  229.     while((opt= av_next_option(obj, opt))){
  230.         if(!(opt->flags & (AV_OPT_FLAG_ENCODING_PARAM|AV_OPT_FLAG_DECODING_PARAM)))
  231.             continue;
  232.             
  233.         av_log(av_log_obj, AV_LOG_INFO, "-%-17s ", opt->name);
  234.         av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_ENCODING_PARAM) ? 'E' : '.');
  235.         av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_DECODING_PARAM) ? 'D' : '.');
  236.         av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_VIDEO_PARAM   ) ? 'V' : '.');
  237.         av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_AUDIO_PARAM   ) ? 'A' : '.');
  238.         av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_SUBTITLE_PARAM) ? 'S' : '.');
  239.         
  240.         if(opt->help)
  241.             av_log(av_log_obj, AV_LOG_INFO, " %s", opt->help);
  242.         av_log(av_log_obj, AV_LOG_INFO, "n");
  243.     }
  244.     return 0;
  245. }