962
|
1 /*
|
|
2 * LGPL
|
|
3 */
|
|
4
|
|
5 /*
|
|
6 * typical parsed command line:
|
|
7 * msmpeg4:bitrate=720000:qmax=16
|
|
8 *
|
|
9 */
|
|
10
|
|
11 #include "avcodec.h"
|
1019
|
12 #ifdef OPTS_MAIN
|
|
13 #include <stdio.h>
|
|
14 #include <stdlib.h>
|
|
15 #include <string.h>
|
|
16 #endif
|
962
|
17
|
|
18 /*
|
1019
|
19 * todo - use for decoder options also
|
962
|
20 */
|
|
21
|
1019
|
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
|
962
|
145 /**
|
1019
|
146 *
|
962
|
147 * \param avctx where to store parsed results
|
|
148 * \param str string with options for parsing
|
1019
|
149 * or selectional string (pick only options appliable
|
|
150 * for codec - use ,msmpeg4, (with commas to avoid mismatch)
|
962
|
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 **/
|
1019
|
155 void avcodec_getopt(AVCodecContext* avctx, const char* str, avc_config_t** config)
|
962
|
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)",
|
1019
|
194 FF_CONF_TYPE_RCOVERIDE, &ctx->rc_override, 0, 0, 0, "0,0,0,0", class_h263
|
962
|
195 },
|
|
196
|
|
197 { NULL, NULL, 0, NULL, 0, 0, 0, NULL, NULL }
|
|
198 };
|
|
199
|
1019
|
200 if (config) {
|
962
|
201 *config = malloc(sizeof(cnf));
|
1019
|
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 }
|
962
|
218 }
|
|
219 }
|
1019
|
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
|