Mercurial > libavcodec.hg
comparison opts.c @ 1058:3c3da6edc9a1 libavcodec
* still unfinished code for Options
author | kabi |
---|---|
date | Mon, 10 Feb 2003 09:38:38 +0000 |
parents | ef905ded19fe |
children | 1e39f273ecd6 |
comparison
equal
deleted
inserted
replaced
1057:bb5de8a59da8 | 1058:3c3da6edc9a1 |
---|---|
7 * msmpeg4:bitrate=720000:qmax=16 | 7 * msmpeg4:bitrate=720000:qmax=16 |
8 * | 8 * |
9 */ | 9 */ |
10 | 10 |
11 #include "avcodec.h" | 11 #include "avcodec.h" |
12 #ifdef OPTS_MAIN | |
13 #include <stdio.h> | |
14 #include <stdlib.h> | |
15 #include <string.h> | |
16 #endif | |
17 | 12 |
18 /* | 13 extern const AVOption common_options[2]; |
19 * todo - use for decoder options also | |
20 */ | |
21 | 14 |
22 static int parse_bool(avc_config_t* c, char* s) | 15 const AVOption common_options[2] = { |
16 AVOPTION_CODEC_INT("common", "test", bit_rate, 0, 10, 0), | |
17 AVOPTION_END() | |
18 }; | |
19 | |
20 static int parse_bool(const AVOption *c, char *s, int *var) | |
23 { | 21 { |
24 int b = 1; /* by default -on- when present */ | 22 int b = 1; /* by default -on- when present */ |
25 if (s) { | 23 if (s) { |
26 if (!strcasecmp(s, "off") || !strcasecmp(s, "false") | 24 if (!strcasecmp(s, "off") || !strcasecmp(s, "false") |
27 || !strcmp(s, "0")) | 25 || !strcmp(s, "0")) |
31 b = 1; | 29 b = 1; |
32 else | 30 else |
33 return -1; | 31 return -1; |
34 } | 32 } |
35 | 33 |
36 if (c && c->val) | 34 *var = b; |
37 *(int*)(c->val) = b; | |
38 return 0; | 35 return 0; |
39 } | 36 } |
40 | 37 |
41 static int parse_double(avc_config_t* c, char* s) | 38 static int parse_double(const AVOption *c, char *s, double *var) |
42 { | 39 { |
43 double d; | 40 double d; |
44 if (!s) | 41 if (!s) |
45 return -1; | 42 return -1; |
46 d = atof(s); | 43 d = atof(s); |
49 fprintf(stderr, "Option: %s double value: %f out of range <%f, %f>\n", | 46 fprintf(stderr, "Option: %s double value: %f out of range <%f, %f>\n", |
50 c->name, d, c->min, c->max); | 47 c->name, d, c->min, c->max); |
51 return -1; | 48 return -1; |
52 } | 49 } |
53 } | 50 } |
54 if (c && c->val) | 51 *var = d; |
55 *(double*)(c->val) = d; | |
56 return 0; | 52 return 0; |
57 } | 53 } |
58 | 54 |
59 static int parse_int(avc_config_t* c, char* s) | 55 static int parse_int(const AVOption* c, char* s, int* var) |
60 { | 56 { |
61 int i; | 57 int i; |
62 if (!s) | 58 if (!s) |
63 return -1; | 59 return -1; |
64 i = atoi(s); | 60 i = atoi(s); |
67 fprintf(stderr, "Option: %s integer value: %d out of range <%d, %d>\n", | 63 fprintf(stderr, "Option: %s integer value: %d out of range <%d, %d>\n", |
68 c->name, i, (int)c->min, (int)c->max); | 64 c->name, i, (int)c->min, (int)c->max); |
69 return -1; | 65 return -1; |
70 } | 66 } |
71 } | 67 } |
72 if (c && c->val) | 68 *var = i; |
73 *(int*)(c->val) = i; | |
74 return 0; | 69 return 0; |
75 } | 70 } |
76 | 71 |
77 static int parse_string(AVCodecContext* avctx, avc_config_t* c, char* s) | 72 static int parse_string(const AVOption *c, char *s, AVCodecContext *avctx, char **var) |
78 { | 73 { |
79 if (!s) | 74 if (!s) |
80 return -1; | 75 return -1; |
81 | 76 |
82 if (c->type == FF_CONF_TYPE_RCOVERIDE) { | 77 if (c->type == FF_OPT_TYPE_RCOVERRIDE) { |
83 int sf, ef, qs; | 78 int sf, ef, qs; |
84 float qf; | 79 float qf; |
85 if (sscanf(s, "%d,%d,%d,%f", &sf, &ef, &qs, &qf) == 4 && sf < ef) { | 80 if (sscanf(s, "%d,%d,%d,%f", &sf, &ef, &qs, &qf) == 4 && sf < ef) { |
86 RcOverride* o; | 81 RcOverride *o; |
87 *((RcOverride**)c->val) = | 82 avctx->rc_override = av_realloc(avctx->rc_override, |
88 realloc(*((RcOverride**)c->val), | 83 sizeof(RcOverride) * (avctx->rc_override_count + 1)); |
89 sizeof(RcOverride) * (avctx->rc_override_count + 1)); | 84 o = avctx->rc_override + avctx->rc_override_count++; |
90 o = *((RcOverride**)c->val) + avctx->rc_override_count++; | |
91 o->start_frame = sf; | 85 o->start_frame = sf; |
92 o->end_frame = ef; | 86 o->end_frame = ef; |
93 o->qscale = qs; | 87 o->qscale = qs; |
94 o->quality_factor = qf; | 88 o->quality_factor = qf; |
95 | 89 |
96 //printf("parsed Rc: %d,%d,%d,%f (%d)\n", sf,ef,qs,qf, avctx->rc_override_count); | 90 //printf("parsed Rc: %d,%d,%d,%f (%d)\n", sf,ef,qs,qf, avctx->rc_override_count); |
97 } else { | 91 } else { |
98 printf("incorrect/unparsable Rc: \"%s\"\n", s); | 92 printf("incorrect/unparsable Rc: \"%s\"\n", s); |
99 } | 93 } |
100 } else | 94 } else |
101 (char*)(c->val) = strdup(s); | 95 *var = av_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; | 96 return 0; |
143 } | 97 } |
144 | 98 |
145 /** | 99 /** |
146 * | 100 * |
101 * \param codec codec for option parsing | |
102 * \param opts string with options for parsing | |
147 * \param avctx where to store parsed results | 103 * \param avctx where to store parsed results |
148 * \param str string with options for parsing | 104 */ |
149 * or selectional string (pick only options appliable | 105 int avcodec_parse(const AVCodec *codec, const char *opts, AVCodecContext *avctx) |
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 { | 106 { |
157 AVCodecContext avctx_tmp; | 107 int r = 0; |
158 AVCodecContext* ctx = (avctx) ? avctx : &avctx_tmp; | 108 char* dopts = av_strdup(opts); |
159 static const char* class_h263 = ",msmpeg4,"; | 109 if (dopts) { |
160 //"huffyuv,wmv1,msmpeg4v2,msmpeg4,mpeg4,mpeg1,mpeg1video,mjpeg,rv10,h263,h263p" | 110 char *str = dopts; |
161 | 111 |
162 avc_config_t cnf[] = | 112 while (str && *str && r == 0) { |
163 { | 113 const AVOption *stack[FF_OPT_MAX_DEPTH]; |
164 // FIXME: sorted by importance!!! | 114 int depth = 0; |
165 // expert option should follow more common ones | 115 const AVOption *c = codec->options; |
166 { | 116 char* e = strchr(str, ':'); |
167 "bitrate", "desired video bitrate", | 117 char* p; |
168 FF_CONF_TYPE_INT, &ctx->bit_rate, 4, 240000000, 800000, NULL, class_h263 | 118 if (e) |
169 }, { | 119 *e++ = 0; |
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 | 120 |
197 { NULL, NULL, 0, NULL, 0, 0, 0, NULL, NULL } | 121 p = strchr(str, '='); |
198 }; | 122 if (p) |
123 *p++ = 0; | |
199 | 124 |
200 if (config) { | 125 // going through option structures |
201 *config = malloc(sizeof(cnf)); | 126 for (;;) { |
202 if (*config) { | 127 if (!c->name) { |
203 avc_config_t* src = cnf; | 128 if (c->sub) { |
204 avc_config_t* dst = *config; | 129 stack[depth++] = c; |
205 while (src->name) { | 130 c = c->sub; |
206 if (!str || !src->supported || strstr(src->supported, str)) | 131 assert(depth > FF_OPT_MAX_DEPTH); |
207 memcpy(dst++, src, sizeof(avc_config_t)); | 132 } else { |
208 src++; | 133 if (depth == 0) |
134 break; // finished | |
135 c = stack[--depth]; | |
136 c++; | |
137 } | |
138 } else { | |
139 if (!strcmp(c->name, str)) { | |
140 void* ptr = (char*)avctx + c->offset; | |
141 | |
142 switch (c->type & FF_OPT_TYPE_MASK) { | |
143 case FF_OPT_TYPE_BOOL: | |
144 r = parse_bool(c, p, (int*)ptr); | |
145 break; | |
146 case FF_OPT_TYPE_DOUBLE: | |
147 r = parse_double(c, p, (double*)ptr); | |
148 break; | |
149 case FF_OPT_TYPE_INT: | |
150 r = parse_int(c, p, (int*)ptr); | |
151 break; | |
152 case FF_OPT_TYPE_STRING: | |
153 r = parse_string(c, p, avctx, (char**)ptr); | |
154 break; | |
155 default: | |
156 assert(0 == 1); | |
157 } | |
158 } | |
159 c++; | |
160 } | |
209 } | 161 } |
210 memset(dst, 0, sizeof(avc_config_t)); | 162 str = e; |
211 } | 163 } |
212 } else if (str) { | 164 av_free(dopts); |
213 char* s = strdup(str); | |
214 if (s) { | |
215 parse(avctx, cnf, s); | |
216 free(s); | |
217 } | |
218 } | 165 } |
166 return r; | |
219 } | 167 } |
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 |