diff --git a/cmdutils.c b/cmdutils.c index 7ff5986b51..64ed2b8051 100644 --- a/cmdutils.c +++ b/cmdutils.c @@ -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= 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; iflags & 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); } } }