* code for parsing options
authorZdenek Kabelac <kabi@informatics.muni.cz>
Mon, 20 Jan 2003 19:04:39 +0000 (19:04 +0000)
committerZdenek Kabelac <kabi@informatics.muni.cz>
Mon, 20 Jan 2003 19:04:39 +0000 (19:04 +0000)
  now options have to be added...
  - see main for a simple usage example.

Originally committed as revision 1480 to svn://svn.ffmpeg.org/ffmpeg/trunk

libavcodec/avcodec.h
libavcodec/opts.c

index 72d6d32efb5c0df16ab1a9879d48df4e95ce5c1b..fee760c56c8b5225c4d05eaff98a4c682143648e 100644 (file)
@@ -1152,7 +1152,7 @@ typedef struct {
     const char* supported;
 } avc_config_t;
 
     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
 
 /**
  * Interface for 0.5.0 version
index bcefc40a3b7c7b7ffe56ab720c7b07af33c73621..01fddd7c8f95f75d72e0f81397351e53024a21df 100644 (file)
  */
 
 #include "avcodec.h"
  */
 
 #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
  * \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
  **/
  * \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;
 {
     AVCodecContext avctx_tmp;
     AVCodecContext* ctx = (avctx) ? avctx : &avctx_tmp;
@@ -62,16 +191,88 @@ void avcodec_getopt(AVCodecContext* avctx, char* str, avc_config_t** config)
            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_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 }
     };
 
        },
 
         { NULL, NULL, 0, NULL, 0, 0, 0, NULL, NULL }
     };
 
-    if (config)
-    {
+    if (config) {
        *config = malloc(sizeof(cnf));
        *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