Prefer codec specific options over global ones, allowing codec
authorBaptiste Coudurier <baptiste.coudurier@gmail.com>
Tue, 19 Apr 2011 19:57:46 +0000 (12:57 -0700)
committerBaptiste Coudurier <baptiste.coudurier@gmail.com>
Tue, 19 Apr 2011 20:12:24 +0000 (13:12 -0700)
to override global options.

cmdutils.c

index 7ff5986..64ed2b8 100644 (file)
@@ -79,12 +79,8 @@ void uninit_opts(void)
     av_freep(&sws_opts);
 #endif
     for (i = 0; i < opt_name_count; i++) {
-        //opt_values are only stored for codec-specific options in which case
-        //both the name and value are dup'd
-        if (opt_values[i]) {
-            av_freep(&opt_names[i]);
-            av_freep(&opt_values[i]);
-        }
+        av_freep(&opt_names[i]);
+        av_freep(&opt_values[i]);
     }
     av_freep(&opt_names);
     av_freep(&opt_values);
@@ -235,6 +231,23 @@ int opt_default(const char *opt, const char *arg){
     int ret= 0;
     const AVOption *o= NULL;
     int opt_types[]={AV_OPT_FLAG_VIDEO_PARAM, AV_OPT_FLAG_AUDIO_PARAM, 0, AV_OPT_FLAG_SUBTITLE_PARAM, 0};
+    AVCodec *p = NULL;
+    AVOutputFormat *oformat = NULL;
+
+    while ((p = av_codec_next(p))) {
+        AVClass *c = p->priv_class;
+        if (c && av_find_opt(&c, opt, NULL, 0, 0))
+            break;
+    }
+    if (p)
+        goto out;
+    while ((oformat = av_oformat_next(oformat))) {
+        const AVClass *c = oformat->priv_class;
+        if (c && av_find_opt(&c, opt, NULL, 0, 0))
+            break;
+    }
+    if (oformat)
+        goto out;
 
     for(type=0; *avcodec_opts && type<AVMEDIA_TYPE_NB && ret>= 0; type++){
         const AVOption *o2 = av_find_opt(avcodec_opts[0], opt, NULL, opt_types[type], opt_types[type]);
@@ -252,39 +265,25 @@ int opt_default(const char *opt, const char *arg){
             ret = av_set_string3(avcodec_opts[AVMEDIA_TYPE_VIDEO], opt+1, arg, 1, &o);
         else if(opt[0] == 's' && avcodec_opts[AVMEDIA_TYPE_SUBTITLE])
             ret = av_set_string3(avcodec_opts[AVMEDIA_TYPE_SUBTITLE], opt+1, arg, 1, &o);
+        if (ret >= 0)
+            opt += 1;
     }
     if (o && ret < 0) {
         fprintf(stderr, "Invalid value '%s' for option '%s'\n", arg, opt);
         exit(1);
     }
     if (!o) {
-        AVCodec *p = NULL;
-        AVOutputFormat *oformat = NULL;
-        while ((p=av_codec_next(p))){
-            AVClass *c= p->priv_class;
-            if(c && av_find_opt(&c, opt, NULL, 0, 0))
-                break;
-        }
-        if (!p) {
-            while ((oformat = av_oformat_next(oformat))) {
-                const AVClass *c = oformat->priv_class;
-                if (c && av_find_opt(&c, opt, NULL, 0, 0))
-                    break;
-            }
-        }
-        if(!p && !oformat){
-            fprintf(stderr, "Unrecognized option '%s'\n", opt);
-            exit(1);
-        }
+        fprintf(stderr, "Unrecognized option '%s'\n", opt);
+        exit(1);
     }
 
+ out:
 //    av_log(NULL, AV_LOG_ERROR, "%s:%s: %f 0x%0X\n", opt, arg, av_get_double(avcodec_opts, opt, NULL), (int)av_get_int(avcodec_opts, opt, NULL));
 
-    //FIXME we should always use avcodec_opts, ... for storing options so there will not be any need to keep track of what i set over this
     opt_values= av_realloc(opt_values, sizeof(void*)*(opt_name_count+1));
-    opt_values[opt_name_count]= o ? NULL : av_strdup(arg);
+    opt_values[opt_name_count] = av_strdup(arg);
     opt_names= av_realloc(opt_names, sizeof(void*)*(opt_name_count+1));
-    opt_names[opt_name_count++]= o ? o->name : av_strdup(opt);
+    opt_names[opt_name_count++] = av_strdup(opt);
 
     if ((*avcodec_opts && avcodec_opts[0]->debug) || (avformat_opts && avformat_opts->debug))
         av_log_set_level(AV_LOG_DEBUG);
@@ -358,16 +357,22 @@ void set_context_opts(void *ctx, void *opts_ctx, int flags, AVCodec *codec)
     for(i=0; i<opt_name_count; i++){
         char buf[256];
         const AVOption *opt;
-        const char *str= av_get_string(opts_ctx, opt_names[i], &opt, buf, sizeof(buf));
-        /* if an option with name opt_names[i] is present in opts_ctx then str is non-NULL */
-        if(str && ((opt->flags & flags) == flags))
-            av_set_string3(ctx, opt_names[i], str, 1, NULL);
-        /* We need to use a differnt system to pass options to the private context because
-           it is not known which codec and thus context kind that will be when parsing options
-           we thus use opt_values directly instead of opts_ctx */
-        if(!str && priv_ctx) {
-            if (av_find_opt(priv_ctx, opt_names[i], NULL, flags, flags))
-                av_set_string3(priv_ctx, opt_names[i], opt_values[i], 0, NULL);
+        const char *str;
+        if (priv_ctx) {
+            if (av_find_opt(priv_ctx, opt_names[i], NULL, flags, flags)) {
+                if (av_set_string3(priv_ctx, opt_names[i], opt_values[i], 0, NULL) < 0) {
+                    fprintf(stderr, "Invalid value '%s' for option '%s'\n",
+                            opt_names[i], opt_values[i]);
+                    exit(1);
+                }
+            } else
+                goto global;
+        } else {
+        global:
+            str = av_get_string(opts_ctx, opt_names[i], &opt, buf, sizeof(buf));
+            /* if an option with name opt_names[i] is present in opts_ctx then str is non-NULL */
+            if (str && ((opt->flags & flags) == flags))
+                av_set_string3(ctx, opt_names[i], str, 1, NULL);
         }
     }
 }