changeset 1019:ef905ded19fe libavcodec

* code for parsing options now options have to be added... - see main for a simple usage example.
author kabi
date Mon, 20 Jan 2003 19:04:39 +0000
parents 696ccd81403e
children 617e3531d3fb
files avcodec.h opts.c
diffstat 2 files changed, 211 insertions(+), 10 deletions(-) [+]
line wrap: on
line diff
--- a/avcodec.h	Mon Jan 20 18:43:31 2003 +0000
+++ b/avcodec.h	Mon Jan 20 19:04:39 2003 +0000
@@ -1152,7 +1152,7 @@
     const char* supported;
 } avc_config_t;
 
-void avcodec_getopt(AVCodecContext* avctx, char* str, avc_config_t** config);
+void avcodec_getopt(AVCodecContext* avctx, const char* str, avc_config_t** config);
 
 /**
  * Interface for 0.5.0 version
--- a/opts.c	Mon Jan 20 18:43:31 2003 +0000
+++ b/opts.c	Mon Jan 20 19:04:39 2003 +0000
@@ -9,21 +9,150 @@
  */
 
 #include "avcodec.h"
+#ifdef OPTS_MAIN
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#endif
 
 /*
- * possible extension - use for decoder options
- *                    - for given codec names filter only correct
- *                      options given (could be passed with 'str')
+ * 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, char* str, avc_config_t** config)
+void avcodec_getopt(AVCodecContext* avctx, const char* str, avc_config_t** config)
 {
     AVCodecContext avctx_tmp;
     AVCodecContext* ctx = (avctx) ? avctx : &avctx_tmp;
@@ -62,16 +191,88 @@
 	    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, NULL, class_h263
+	    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)
-    {
+    if (config) {
 	*config = malloc(sizeof(cnf));
-	if (*config)
-            memcpy(*config, cnf, 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