|
- /*
- * LGPL
- */
-
- /*
- * typical parsed command line:
- * msmpeg4:bitrate=720000:qmax=16
- *
- */
-
- #include "avcodec.h"
- #ifdef OPTS_MAIN
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #endif
-
- /*
- * todo - use for decoder options also
- */
-
- static int parse_bool(avc_config_t* c, char* s)
- {
- int b = 1; /* by default -on- when present */
- if (s) {
- if (!strcasecmp(s, "off") || !strcasecmp(s, "false")
- || !strcmp(s, "0"))
- b = 0;
- else if (!strcasecmp(s, "on") || !strcasecmp(s, "true")
- || !strcmp(s, "1"))
- b = 1;
- else
- return -1;
- }
-
- if (c && c->val)
- *(int*)(c->val) = b;
- return 0;
- }
-
- static int parse_double(avc_config_t* c, char* s)
- {
- double d;
- if (!s)
- return -1;
- d = atof(s);
- if (c->min != c->max) {
- if (d < c->min || d > c->max) {
- fprintf(stderr, "Option: %s double value: %f out of range <%f, %f>\n",
- c->name, d, c->min, c->max);
- return -1;
- }
- }
- if (c && c->val)
- *(double*)(c->val) = d;
- return 0;
- }
-
- static int parse_int(avc_config_t* c, char* s)
- {
- int i;
- if (!s)
- return -1;
- i = atoi(s);
- if (c->min != c->max) {
- if (i < (int)c->min || i > (int)c->max) {
- fprintf(stderr, "Option: %s integer value: %d out of range <%d, %d>\n",
- c->name, i, (int)c->min, (int)c->max);
- return -1;
- }
- }
- if (c && c->val)
- *(int*)(c->val) = i;
- return 0;
- }
-
- static int parse_string(AVCodecContext* avctx, avc_config_t* c, char* s)
- {
- if (!s)
- return -1;
-
- if (c->type == FF_CONF_TYPE_RCOVERIDE) {
- int sf, ef, qs;
- float qf;
- if (sscanf(s, "%d,%d,%d,%f", &sf, &ef, &qs, &qf) == 4 && sf < ef) {
- RcOverride* o;
- *((RcOverride**)c->val) =
- realloc(*((RcOverride**)c->val),
- sizeof(RcOverride) * (avctx->rc_override_count + 1));
- o = *((RcOverride**)c->val) + avctx->rc_override_count++;
- o->start_frame = sf;
- o->end_frame = ef;
- o->qscale = qs;
- o->quality_factor = qf;
-
- //printf("parsed Rc: %d,%d,%d,%f (%d)\n", sf,ef,qs,qf, avctx->rc_override_count);
- } else {
- printf("incorrect/unparsable Rc: \"%s\"\n", s);
- }
- } else
- (char*)(c->val) = strdup(s);
- return 0;
- }
-
- static int parse(AVCodecContext* avctx, avc_config_t* config, char* str)
- {
- while (str && *str) {
- avc_config_t* c = config;
- char* e = strchr(str, ':');
- char* p;
- if (e)
- *e++ = 0;
-
- p = strchr(str, '=');
- if (p)
- *p++ = 0;
-
- while (c->name) {
- if (!strcmp(c->name, str)) {
- switch (c->type & FF_CONF_TYPE_MASK) {
- case FF_CONF_TYPE_BOOL:
- parse_bool(c, p);
- break;
- case FF_CONF_TYPE_DOUBLE:
- parse_double(c, p);
- break;
- case FF_CONF_TYPE_INT:
- parse_int(c, p);
- break;
- case FF_CONF_TYPE_STRING:
- parse_string(avctx, c, p);
- break;
- default:
- abort();
- break;
- }
- }
- c++;
- }
- str = e;
- }
- return 0;
- }
-
- /**
- *
- * \param avctx where to store parsed results
- * \param str string with options for parsing
- * or selectional string (pick only options appliable
- * for codec - use ,msmpeg4, (with commas to avoid mismatch)
- * \param config allocated avc_config_t for external parsing
- * i.e. external program might learn about all available
- * options for given codec
- **/
- void avcodec_getopt(AVCodecContext* avctx, const char* str, avc_config_t** config)
- {
- AVCodecContext avctx_tmp;
- AVCodecContext* ctx = (avctx) ? avctx : &avctx_tmp;
- static const char* class_h263 = ",msmpeg4,";
- //"huffyuv,wmv1,msmpeg4v2,msmpeg4,mpeg4,mpeg1,mpeg1video,mjpeg,rv10,h263,h263p"
-
- avc_config_t cnf[] =
- {
- // FIXME: sorted by importance!!!
- // expert option should follow more common ones
- {
- "bitrate", "desired video bitrate",
- FF_CONF_TYPE_INT, &ctx->bit_rate, 4, 240000000, 800000, NULL, class_h263
- }, {
- "vhq", "very high quality",
- FF_CONF_TYPE_FLAG, &ctx->flags, 0, CODEC_FLAG_HQ, 0, NULL, class_h263
- }, {
- "ratetol", "number of bits the bitstream is allowed to diverge from the reference"
- "the reference can be CBR (for CBR pass1) or VBR (for pass2)",
- FF_CONF_TYPE_INT, &ctx->bit_rate_tolerance, 4, 240000000, 8000, NULL, class_h263
- }, {
- "qmin", "minimum quantizer", FF_CONF_TYPE_INT, &ctx->qmin, 1, 31, 2, NULL, class_h263
- }, {
- "qmax", "maximum qunatizer", FF_CONF_TYPE_INT, &ctx->qmax, 1, 31, 31, NULL, class_h263
- }, {
- "rc_eq", "rate control equation",
- FF_CONF_TYPE_STRING, &ctx->rc_eq, 0, 0, 0, "tex^qComp" /* FILLME options */, class_h263
- }, {
- "rc_minrate", "rate control minimum bitrate",
- FF_CONF_TYPE_INT, &ctx->rc_min_rate, 4, 24000000, 0, NULL, class_h263
- }, {
- "rc_maxrate", "rate control maximum bitrate",
- FF_CONF_TYPE_INT, &ctx->rc_max_rate, 4, 24000000, 0, NULL, class_h263
- }, {
- "psnr", "calculate PSNR of compressed frames",
- FF_CONF_TYPE_FLAG, &ctx->flags, 0, CODEC_FLAG_PSNR, 0, NULL, class_h263
- }, {
- "rc_override", "ratecontrol override (=startframe,endframe,qscale,quality_factor)",
- FF_CONF_TYPE_RCOVERIDE, &ctx->rc_override, 0, 0, 0, "0,0,0,0", class_h263
- },
-
- { NULL, NULL, 0, NULL, 0, 0, 0, NULL, NULL }
- };
-
- if (config) {
- *config = malloc(sizeof(cnf));
- if (*config) {
- avc_config_t* src = cnf;
- avc_config_t* dst = *config;
- while (src->name) {
- if (!str || !src->supported || strstr(src->supported, str))
- memcpy(dst++, src, sizeof(avc_config_t));
- src++;
- }
- memset(dst, 0, sizeof(avc_config_t));
- }
- } else if (str) {
- char* s = strdup(str);
- if (s) {
- parse(avctx, cnf, s);
- free(s);
- }
- }
- }
-
- #ifdef OPTS_MAIN
- /*
- * API test -
- * arg1: options
- * arg2: codec type
- *
- * compile standalone: make CFLAGS="-DOPTS_MAIN" opts
- */
- int main(int argc, char* argv[])
- {
- AVCodecContext avctx;
- avc_config_t* config;
- char* def = malloc(5000);
- const char* col = "";
- int i = 0;
-
- memset(&avctx, 0, sizeof(avctx));
- *def = 0;
- avcodec_getopt(&avctx, argv[1], NULL);
-
- avcodec_getopt(NULL, (argc > 2) ? argv[2] : NULL, &config);
- if (config)
- while (config->name) {
- int t = config->type & FF_CONF_TYPE_MASK;
- printf("Config %s %s\n", config->name,
- t == FF_CONF_TYPE_BOOL ? "bool" :
- t == FF_CONF_TYPE_DOUBLE ? "double" :
- t == FF_CONF_TYPE_INT ? "integer" :
- t == FF_CONF_TYPE_STRING ? "string" :
- "unknown??");
- switch (t) {
- case FF_CONF_TYPE_BOOL:
- i += sprintf(def + i, "%s%s=%s",
- col, config->name,
- config->defval != 0. ? "on" : "off");
- break;
- case FF_CONF_TYPE_DOUBLE:
- i += sprintf(def + i, "%s%s=%f",
- col, config->name, config->defval);
- break;
- case FF_CONF_TYPE_INT:
- i += sprintf(def + i, "%s%s=%d",
- col, config->name, (int) config->defval);
- break;
- case FF_CONF_TYPE_STRING:
- i += sprintf(def + i, "%s%s=%s",
- col, config->name, config->defstr);
- break;
- }
- col = ":";
- config++;
- }
-
- printf("Default Options: %s\n", def);
-
- return 0;
- }
- #endif
|