]> git.sesse.net Git - ffmpeg/blob - libavcodec/opts.c
Creative YUV (CYUV) decoder by (Mike Melanson <melanson at pcisys dot net>)
[ffmpeg] / libavcodec / opts.c
1 /*
2  * LGPL
3  */
4
5 /*
6  * typical parsed command line:
7  * msmpeg4:bitrate=720000:qmax=16
8  *
9  */
10
11 #include "avcodec.h"
12 #ifdef OPTS_MAIN
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #endif
17
18 /*
19  * todo - use for decoder options also
20  */
21
22 static int parse_bool(avc_config_t* c, char* s)
23 {
24     int b = 1; /* by default -on- when present */
25     if (s) {
26         if (!strcasecmp(s, "off") || !strcasecmp(s, "false")
27             || !strcmp(s, "0"))
28             b = 0;
29         else if (!strcasecmp(s, "on") || !strcasecmp(s, "true")
30                  || !strcmp(s, "1"))
31             b = 1;
32         else
33             return -1;
34     }
35
36     if (c && c->val)
37         *(int*)(c->val) = b;
38     return 0;
39 }
40
41 static int parse_double(avc_config_t* c, char* s)
42 {
43     double d;
44     if (!s)
45         return -1;
46     d = atof(s);
47     if (c->min != c->max) {
48         if (d < c->min || d > c->max) {
49             fprintf(stderr, "Option: %s double value: %f out of range <%f, %f>\n",
50                     c->name, d, c->min, c->max);
51             return -1;
52         }
53     }
54     if (c && c->val)
55         *(double*)(c->val) = d;
56     return 0;
57 }
58
59 static int parse_int(avc_config_t* c, char* s)
60 {
61     int i;
62     if (!s)
63         return -1;
64     i = atoi(s);
65     if (c->min != c->max) {
66         if (i < (int)c->min || i > (int)c->max) {
67             fprintf(stderr, "Option: %s integer value: %d out of range <%d, %d>\n",
68                     c->name, i, (int)c->min, (int)c->max);
69             return -1;
70         }
71     }
72     if (c && c->val)
73         *(int*)(c->val) = i;
74     return 0;
75 }
76
77 static int parse_string(AVCodecContext* avctx, avc_config_t* c, char* s)
78 {
79     if (!s)
80         return -1;
81
82     if (c->type == FF_CONF_TYPE_RCOVERIDE) {
83         int sf, ef, qs;
84         float qf;
85         if (sscanf(s, "%d,%d,%d,%f", &sf, &ef, &qs, &qf) == 4 && sf < ef) {
86             RcOverride* o;
87             *((RcOverride**)c->val) =
88                 realloc(*((RcOverride**)c->val),
89                         sizeof(RcOverride) * (avctx->rc_override_count + 1));
90             o = *((RcOverride**)c->val) + avctx->rc_override_count++;
91             o->start_frame = sf;
92             o->end_frame = ef;
93             o->qscale = qs;
94             o->quality_factor = qf;
95
96             //printf("parsed Rc:  %d,%d,%d,%f  (%d)\n", sf,ef,qs,qf, avctx->rc_override_count);
97         } else {
98             printf("incorrect/unparsable Rc: \"%s\"\n", s);
99         }
100     } else
101         (char*)(c->val) = strdup(s);
102     return 0;
103 }
104
105 static int parse(AVCodecContext* avctx, avc_config_t* config, char* str)
106 {
107     while (str && *str) {
108         avc_config_t* c = config;
109         char* e = strchr(str, ':');
110         char* p;
111         if (e)
112             *e++ = 0;
113
114         p = strchr(str, '=');
115         if (p)
116             *p++ = 0;
117
118         while (c->name) {
119             if (!strcmp(c->name, str)) {
120                 switch (c->type & FF_CONF_TYPE_MASK) {
121                 case FF_CONF_TYPE_BOOL:
122                     parse_bool(c, p);
123                     break;
124                 case FF_CONF_TYPE_DOUBLE:
125                     parse_double(c, p);
126                     break;
127                 case FF_CONF_TYPE_INT:
128                     parse_int(c, p);
129                     break;
130                 case FF_CONF_TYPE_STRING:
131                     parse_string(avctx, c, p);
132                     break;
133                 default:
134                     abort();
135                     break;
136                 }
137             }
138             c++;
139         }
140         str = e;
141     }
142     return 0;
143 }
144
145 /**
146  *
147  * \param avctx  where to store parsed results
148  * \param str    string with options for parsing
149  *               or selectional string (pick only options appliable
150  *               for codec - use  ,msmpeg4, (with commas to avoid mismatch)
151  * \param config allocated avc_config_t for external parsing
152  *               i.e. external program might learn about all available
153  *               options for given codec
154  **/
155 void avcodec_getopt(AVCodecContext* avctx, const char* str, avc_config_t** config)
156 {
157     AVCodecContext avctx_tmp;
158     AVCodecContext* ctx = (avctx) ? avctx : &avctx_tmp;
159     static const char* class_h263 = ",msmpeg4,";
160     //"huffyuv,wmv1,msmpeg4v2,msmpeg4,mpeg4,mpeg1,mpeg1video,mjpeg,rv10,h263,h263p"
161
162     avc_config_t cnf[] =
163     {
164         // FIXME: sorted by importance!!!
165         // expert option should follow more common ones
166         {
167             "bitrate", "desired video bitrate",
168             FF_CONF_TYPE_INT, &ctx->bit_rate, 4, 240000000, 800000, NULL, class_h263
169         }, {
170             "vhq", "very high quality",
171             FF_CONF_TYPE_FLAG, &ctx->flags, 0, CODEC_FLAG_HQ, 0, NULL, class_h263
172         }, {
173             "ratetol", "number of bits the bitstream is allowed to diverge from the reference"
174             "the reference can be CBR (for CBR pass1) or VBR (for pass2)",
175             FF_CONF_TYPE_INT, &ctx->bit_rate_tolerance, 4, 240000000, 8000, NULL, class_h263
176         }, {
177             "qmin", "minimum quantizer", FF_CONF_TYPE_INT, &ctx->qmin, 1, 31, 2, NULL, class_h263
178         }, {
179             "qmax", "maximum qunatizer", FF_CONF_TYPE_INT, &ctx->qmax, 1, 31, 31, NULL, class_h263
180         }, {
181             "rc_eq", "rate control equation",
182             FF_CONF_TYPE_STRING, &ctx->rc_eq, 0, 0, 0, "tex^qComp" /* FILLME options */, class_h263
183         }, {
184             "rc_minrate", "rate control minimum bitrate",
185             FF_CONF_TYPE_INT, &ctx->rc_min_rate, 4, 24000000, 0, NULL, class_h263
186         }, {
187             "rc_maxrate", "rate control maximum bitrate",
188             FF_CONF_TYPE_INT, &ctx->rc_max_rate, 4, 24000000, 0, NULL, class_h263
189         }, {
190             "psnr", "calculate PSNR of compressed frames",
191             FF_CONF_TYPE_FLAG, &ctx->flags, 0, CODEC_FLAG_PSNR, 0, NULL, class_h263
192         }, {
193             "rc_override", "ratecontrol override (=startframe,endframe,qscale,quality_factor)",
194             FF_CONF_TYPE_RCOVERIDE, &ctx->rc_override, 0, 0, 0, "0,0,0,0", class_h263
195         },
196
197         { NULL, NULL, 0, NULL, 0, 0, 0, NULL, NULL }
198     };
199
200     if (config) {
201         *config = malloc(sizeof(cnf));
202         if (*config) {
203             avc_config_t* src = cnf;
204             avc_config_t* dst = *config;
205             while (src->name) {
206                 if (!str || !src->supported || strstr(src->supported, str))
207                     memcpy(dst++, src, sizeof(avc_config_t));
208                 src++;
209             }
210             memset(dst, 0, sizeof(avc_config_t));
211         }
212     } else if (str) {
213         char* s = strdup(str);
214         if (s) {
215             parse(avctx, cnf, s);
216             free(s);
217         }
218     }
219 }
220
221 #ifdef OPTS_MAIN
222 /*
223  * API test -
224  * arg1: options
225  * arg2: codec type
226  *
227  * compile standalone: make CFLAGS="-DOPTS_MAIN" opts
228  */
229 int main(int argc, char* argv[])
230 {
231     AVCodecContext avctx;
232     avc_config_t* config;
233     char* def = malloc(5000);
234     const char* col = "";
235     int i = 0;
236
237     memset(&avctx, 0, sizeof(avctx));
238     *def = 0;
239     avcodec_getopt(&avctx, argv[1], NULL);
240
241     avcodec_getopt(NULL, (argc > 2) ? argv[2] : NULL, &config);
242     if (config)
243         while (config->name) {
244             int t = config->type & FF_CONF_TYPE_MASK;
245             printf("Config   %s  %s\n", config->name,
246                    t == FF_CONF_TYPE_BOOL ? "bool" :
247                    t == FF_CONF_TYPE_DOUBLE ? "double" :
248                    t == FF_CONF_TYPE_INT ? "integer" :
249                    t == FF_CONF_TYPE_STRING ? "string" :
250                    "unknown??");
251             switch (t) {
252             case FF_CONF_TYPE_BOOL:
253                 i += sprintf(def + i, "%s%s=%s",
254                              col, config->name,
255                              config->defval != 0. ? "on" : "off");
256                 break;
257             case FF_CONF_TYPE_DOUBLE:
258                 i += sprintf(def + i, "%s%s=%f",
259                              col, config->name, config->defval);
260                 break;
261             case FF_CONF_TYPE_INT:
262                 i += sprintf(def + i, "%s%s=%d",
263                              col, config->name, (int) config->defval);
264                 break;
265             case FF_CONF_TYPE_STRING:
266                 i += sprintf(def + i, "%s%s=%s",
267                              col, config->name, config->defstr);
268                 break;
269             }
270             col = ":";
271             config++;
272         }
273
274     printf("Default Options: %s\n", def);
275
276     return 0;
277 }
278 #endif