summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2014-08-02 03:12:09 +0200
committerwm4 <wm4@nowhere>2014-08-02 03:12:33 +0200
commitd68a759fa4dea2701087039c58961757eb246b4f (patch)
tree07efabb3a1bf1bdcc0b80f6150f996aacf293ca6
parent0c6c2da8bcdb0f1523c0f10bc117c41057875e34 (diff)
downloadmpv-d68a759fa4dea2701087039c58961757eb246b4f.tar.bz2
mpv-d68a759fa4dea2701087039c58961757eb246b4f.tar.xz
Improve setting AVOptions
Use OPT_KEYVALUELIST() for all places where AVOptions are directly set from mpv command line options. This allows escaping values, better diagnostics (also no more "pal"), and somehow reduces code size. Remove the old crappy option parser (av_opts.c).
-rw-r--r--audio/decode/ad_lavc.c13
-rw-r--r--audio/filter/af_lavfi.c12
-rw-r--r--audio/filter/af_lavrresample.c10
-rw-r--r--common/av_common.c36
-rw-r--r--common/av_common.h3
-rw-r--r--common/av_opts.c55
-rw-r--r--common/av_opts.h30
-rw-r--r--demux/demux_lavf.c19
-rw-r--r--old-makefile1
-rw-r--r--stream/stream_lavf.c6
-rw-r--r--video/decode/vd_lavc.c14
-rw-r--r--video/filter/vf_lavfi.c15
-rw-r--r--wscript_build.py1
13 files changed, 66 insertions, 149 deletions
diff --git a/audio/decode/ad_lavc.c b/audio/decode/ad_lavc.c
index 4ff69c3f20..c4372ba4b3 100644
--- a/audio/decode/ad_lavc.c
+++ b/audio/decode/ad_lavc.c
@@ -33,7 +33,6 @@
#include "common/codecs.h"
#include "common/msg.h"
#include "options/options.h"
-#include "common/av_opts.h"
#include "ad.h"
#include "audio/fmt-conversion.h"
@@ -55,7 +54,7 @@ struct ad_lavc_params {
float ac3drc;
int downmix;
int threads;
- char *avopt;
+ char **avopts;
};
const struct m_sub_options ad_lavc_conf = {
@@ -63,7 +62,7 @@ const struct m_sub_options ad_lavc_conf = {
OPT_FLOATRANGE("ac3drc", ac3drc, 0, 0, 2),
OPT_FLAG("downmix", downmix, 0),
OPT_INTRANGE("threads", threads, 0, 1, 16),
- OPT_STRING("o", avopt, 0),
+ OPT_KEYVALUELIST("o", avopts, 0),
{0}
},
.size = sizeof(struct ad_lavc_params),
@@ -228,13 +227,7 @@ static int init(struct dec_audio *da, const char *decoder)
av_opt_set_double(lavc_context, "drc_scale", opts->ac3drc,
AV_OPT_SEARCH_CHILDREN);
- if (opts->avopt) {
- if (parse_avopts(lavc_context, opts->avopt) < 0) {
- MP_ERR(da, "setting AVOptions '%s' failed.\n", opts->avopt);
- uninit(da);
- return 0;
- }
- }
+ mp_set_avopts(da->log, lavc_context, opts->avopts);
lavc_context->codec_tag = sh->format;
lavc_context->sample_rate = sh_audio->samplerate;
diff --git a/audio/filter/af_lavfi.c b/audio/filter/af_lavfi.c
index a565e202f4..0b7a619e56 100644
--- a/audio/filter/af_lavfi.c
+++ b/audio/filter/af_lavfi.c
@@ -38,8 +38,9 @@
#include "audio/fmt-conversion.h"
#include "af.h"
+#include "common/av_common.h"
+
#include "options/m_option.h"
-#include "common/av_opts.h"
// FFmpeg and Libav have slightly different APIs, just enough to cause us
// unnecessary pain. <Expletive deleted.>
@@ -62,7 +63,7 @@ struct priv {
// options
char *cfg_graph;
- char *cfg_avopts;
+ char **cfg_avopts;
};
static void destroy_graph(struct af_instance *af)
@@ -90,11 +91,8 @@ static bool recreate_graph(struct af_instance *af, struct mp_audio *config)
if (!graph)
goto error;
- if (parse_avopts(graph, p->cfg_avopts) < 0) {
- MP_FATAL(af, "lavfi: could not set opts: '%s'\n",
- p->cfg_avopts);
+ if (mp_set_avopts(af->log, graph, p->cfg_avopts) < 0)
goto error;
- }
AVFilterInOut *outputs = avfilter_inout_alloc();
AVFilterInOut *inputs = avfilter_inout_alloc();
@@ -306,7 +304,7 @@ const struct af_info af_info_lavfi = {
.priv_size = sizeof(struct priv),
.options = (const struct m_option[]) {
OPT_STRING("graph", cfg_graph, 0),
- OPT_STRING("o", cfg_avopts, 0),
+ OPT_KEYVALUELIST("o", cfg_avopts, 0),
{0}
},
};
diff --git a/audio/filter/af_lavrresample.c b/audio/filter/af_lavrresample.c
index 8e33f3b23c..26bbd56de0 100644
--- a/audio/filter/af_lavrresample.c
+++ b/audio/filter/af_lavrresample.c
@@ -52,9 +52,9 @@
#error "config.h broken or no resampler found"
#endif
+#include "common/av_common.h"
#include "common/msg.h"
#include "options/m_option.h"
-#include "common/av_opts.h"
#include "audio/filter/af.h"
#include "audio/fmt-conversion.h"
@@ -74,7 +74,7 @@ struct af_resample_opts {
struct af_resample {
int allow_detach;
- char *avopts;
+ char **avopts;
struct AVAudioResampleContext *avrctx;
struct AVAudioResampleContext *avrctx_out; // for output channel reordering
struct af_resample_opts ctx; // opts in the context
@@ -164,10 +164,8 @@ static int configure_lavrr(struct af_instance *af, struct mp_audio *in,
av_opt_set_double(s->avrctx, "cutoff", s->ctx.cutoff, 0);
- if (parse_avopts(s->avrctx, s->avopts) < 0) {
- MP_FATAL(af, "af_lavrresample: could not set opts: '%s'\n", s->avopts);
+ if (mp_set_avopts(af->log, s->avrctx, s->avopts) < 0)
return AF_ERROR;
- }
struct mp_chmap map_in = in->channels;
struct mp_chmap map_out = out->channels;
@@ -402,7 +400,7 @@ const struct af_info af_info_lavrresample = {
OPT_FLAG("linear", opts.linear, 0),
OPT_DOUBLE("cutoff", opts.cutoff, M_OPT_RANGE, .min = 0, .max = 1),
OPT_FLAG("detach", allow_detach, 0),
- OPT_STRING("o", avopts, 0),
+ OPT_KEYVALUELIST("o", avopts, 0),
{0}
},
};
diff --git a/common/av_common.c b/common/av_common.c
index d090ccfc50..e0a5da7726 100644
--- a/common/av_common.c
+++ b/common/av_common.c
@@ -20,6 +20,8 @@
#include <libavutil/common.h>
#include <libavutil/log.h>
#include <libavutil/dict.h>
+#include <libavutil/opt.h>
+#include <libavutil/error.h>
#include <libavcodec/avcodec.h>
#include "common/common.h"
@@ -189,3 +191,37 @@ void mp_set_avdict(AVDictionary **dict, char **kv)
for (int n = 0; kv && kv[n * 2]; n++)
av_dict_set(dict, kv[n * 2 + 0], kv[n * 2 + 1], 0);
}
+
+// For use with libav* APIs that take AVDictionaries of options.
+// Print options remaining in the dict as unset.
+void mp_avdict_print_unset(struct mp_log *log, int msgl, AVDictionary *dict)
+{
+ AVDictionaryEntry *t = NULL;
+ while ((t = av_dict_get(dict, "", t, AV_DICT_IGNORE_SUFFIX)))
+ mp_msg(log, msgl, "Could not set AVOption %s='%s'\n", t->key, t->value);
+}
+
+// kv is in the format as by OPT_KEYVALUELIST(): kv[0]=key0, kv[1]=val0, ...
+// Set these options on given avobj (using av_opt_set..., meaning avobj must
+// point to a struct that has AVClass as first member).
+// Options which fail to set (error or not found) are printed to log.
+// Returns: >=0 success, <0 failed to set an option
+int mp_set_avopts(struct mp_log *log, void *avobj, char **kv)
+{
+ int success = 0;
+ for (int n = 0; kv && kv[n * 2]; n++) {
+ char *k = kv[n * 2 + 0];
+ char *v = kv[n * 2 + 1];
+ int r = av_opt_set(avobj, k, v, AV_OPT_SEARCH_CHILDREN);
+ if (r == AVERROR_OPTION_NOT_FOUND) {
+ mp_err(log, "AVOption '%s' not found.\n", k);
+ success = -1;
+ } else if (r < 0) {
+ char errstr[80];
+ av_strerror(r, errstr, sizeof(errstr));
+ mp_err(log, "Could not set AVOption %s='%s' (%s)\n", k, v, errstr);
+ success = -1;
+ }
+ }
+ return success;
+}
diff --git a/common/av_common.h b/common/av_common.h
index 4afebe6662..3168d5310d 100644
--- a/common/av_common.h
+++ b/common/av_common.h
@@ -27,6 +27,7 @@
struct mp_decoder_list;
struct demux_packet;
struct AVDictionary;
+struct mp_log;
int mp_lavc_set_extradata(AVCodecContext *avctx, void *ptr, int size);
void mp_copy_lav_codec_headers(AVCodecContext *avctx, AVCodecContext *st);
@@ -38,5 +39,7 @@ void mp_add_lavc_decoders(struct mp_decoder_list *list, enum AVMediaType type);
int mp_codec_to_av_codec_id(const char *codec);
const char *mp_codec_from_av_codec_id(int codec_id);
void mp_set_avdict(struct AVDictionary **dict, char **kv);
+void mp_avdict_print_unset(struct mp_log *log, int msgl, struct AVDictionary *d);
+int mp_set_avopts(struct mp_log *log, void *avobj, char **kv);
#endif
diff --git a/common/av_opts.c b/common/av_opts.c
deleted file mode 100644
index 777a1eec5a..0000000000
--- a/common/av_opts.c
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * AVOption parsing helper
- * Copyright (C) 2008 Michael Niedermayer
- *
- * This file is part of MPlayer.
- *
- * MPlayer is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * MPlayer is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with MPlayer; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include <stdlib.h>
-#include <string.h>
-
-#include <libavutil/opt.h>
-
-#include "av_opts.h"
-
-int parse_avopts(void *v, char *str){
- char *start;
-
- if (!str)
- return 0;
-
- start= str= strdup(str);
-
- while(str && *str){
- char *next_opt, *arg;
-
- next_opt= strchr(str, ',');
- if(next_opt) *next_opt++= 0;
-
- arg = strchr(str, '=');
- if(arg) *arg++= 0;
-
- if (av_opt_set(v, str, arg, AV_OPT_SEARCH_CHILDREN) < 0) {
- free(start);
- return -1;
- }
- str= next_opt;
- }
-
- free(start);
- return 0;
-}
diff --git a/common/av_opts.h b/common/av_opts.h
deleted file mode 100644
index 640443a352..0000000000
--- a/common/av_opts.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * AVOption parsing helper
- * Copyright (C) 2008 Michael Niedermayer
- *
- * This file is part of MPlayer.
- *
- * MPlayer is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * MPlayer is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with MPlayer; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#ifndef MPLAYER_AV_OPTS_H
-#define MPLAYER_AV_OPTS_H
-
-/**
- * Parses str and sets AVOptions in v accordingly.
- */
-int parse_avopts(void *v, char *str);
-
-#endif /* MPLAYER_AV_OPTS_H */
diff --git a/demux/demux_lavf.c b/demux/demux_lavf.c
index 3ccda55d8e..0987508a14 100644
--- a/demux/demux_lavf.c
+++ b/demux/demux_lavf.c
@@ -44,7 +44,6 @@
#include "options/options.h"
#include "common/msg.h"
#include "common/tags.h"
-#include "common/av_opts.h"
#include "common/av_common.h"
#include "bstr/bstr.h"
@@ -71,7 +70,7 @@ struct demux_lavf_opts {
int allow_mimetype;
char *format;
char *cryptokey;
- char *avopt;
+ char **avopts;
int genptsmode;
};
@@ -87,7 +86,7 @@ const struct m_sub_options demux_lavf_conf = {
OPT_STRING("cryptokey", cryptokey, 0),
OPT_CHOICE("genpts-mode", genptsmode, 0,
({"lavf", 1}, {"no", 0})),
- OPT_STRING("o", avopt, 0),
+ OPT_KEYVALUELIST("o", avopts, 0),
{0}
},
.size = sizeof(struct demux_lavf_opts),
@@ -674,14 +673,6 @@ static int demux_open_lavf(demuxer_t *demuxer, enum demux_check check)
"analyzeduration to %f\n", analyze_duration);
}
- if (lavfdopts->avopt) {
- if (parse_avopts(avfc, lavfdopts->avopt) < 0) {
- MP_ERR(demuxer, "Your options /%s/ look like gibberish to me pal\n",
- lavfdopts->avopt);
- return -1;
- }
- }
-
if ((priv->avif->flags & AVFMT_NOFILE) ||
demuxer->stream->type == STREAMTYPE_AVDEVICE)
{
@@ -715,15 +706,15 @@ static int demux_open_lavf(demuxer_t *demuxer, enum demux_check check)
av_dict_set(&dopts, "rtsp_transport", transport, 0);
}
+ mp_set_avdict(&dopts, lavfdopts->avopts);
+
if (avformat_open_input(&avfc, priv->filename, priv->avif, &dopts) < 0) {
MP_ERR(demuxer, "avformat_open_input() failed\n");
av_dict_free(&dopts);
return -1;
}
- t = NULL;
- while ((t = av_dict_get(dopts, "", t, AV_DICT_IGNORE_SUFFIX)))
- MP_VERBOSE(demuxer, "Could not set demux option %s=%s\n", t->key, t->value);
+ mp_avdict_print_unset(demuxer->log, MSGL_V, dopts);
av_dict_free(&dopts);
priv->avfc = avfc;
diff --git a/old-makefile b/old-makefile
index aac2379a3d..49078ea0e6 100644
--- a/old-makefile
+++ b/old-makefile
@@ -149,7 +149,6 @@ SOURCES = audio/audio.c \
bstr/bstr.c \
common/av_common.c \
common/av_log.c \
- common/av_opts.c \
common/codecs.c \
common/common.c \
common/msg.c \
diff --git a/stream/stream_lavf.c b/stream/stream_lavf.c
index 8d8ceb3f94..c84945eba7 100644
--- a/stream/stream_lavf.c
+++ b/stream/stream_lavf.c
@@ -229,11 +229,7 @@ static int open_f(stream_t *stream)
goto out;
}
- AVDictionaryEntry *t = NULL;
- while ((t = av_dict_get(dict, "", t, AV_DICT_IGNORE_SUFFIX))) {
- MP_VERBOSE(stream, "Could not set stream option %s=%s\n",
- t->key, t->value);
- }
+ mp_avdict_print_unset(stream->log, MSGL_V, dict);
if (avio->av_class) {
uint8_t *mt = NULL;
diff --git a/video/decode/vd_lavc.c b/video/decode/vd_lavc.c
index a59fffa790..75f66ce1f1 100644
--- a/video/decode/vd_lavc.c
+++ b/video/decode/vd_lavc.c
@@ -35,7 +35,6 @@
#include "common/msg.h"
#include "options/options.h"
#include "bstr/bstr.h"
-#include "common/av_opts.h"
#include "common/av_common.h"
#include "common/codecs.h"
@@ -79,7 +78,7 @@ struct vd_lavc_params {
int threads;
int bitexact;
int check_hw_profile;
- char *avopt;
+ char **avopts;
};
static const struct m_opt_choice_alternatives discard_names[] = {
@@ -105,7 +104,7 @@ const struct m_sub_options vd_lavc_conf = {
OPT_INTRANGE("threads", threads, 0, 0, 16),
OPT_FLAG("bitexact", bitexact, 0),
OPT_FLAG("check-hw-profile", check_hw_profile, 0),
- OPT_STRING("o", avopt, 0),
+ OPT_KEYVALUELIST("o", avopts, 0),
{0}
},
.size = sizeof(struct vd_lavc_params),
@@ -383,14 +382,7 @@ static void init_avctx(struct dec_video *vd, const char *decoder,
avctx->skip_idct = lavc_param->skip_idct;
avctx->skip_frame = lavc_param->skip_frame;
- if (lavc_param->avopt) {
- if (parse_avopts(avctx, lavc_param->avopt) < 0) {
- MP_ERR(vd, "Your options /%s/ look like gibberish to me pal\n",
- lavc_param->avopt);
- uninit_avctx(vd);
- return;
- }
- }
+ mp_set_avopts(vd->log, avctx, lavc_param->avopts);
// Do this after the above avopt handling in case it changes values
ctx->skip_frame = avctx->skip_frame;
diff --git a/video/filter/vf_lavfi.c b/video/filter/vf_lavfi.c
index c6f0783460..8f1ee243a2 100644
--- a/video/filter/vf_lavfi.c
+++ b/video/filter/vf_lavfi.c
@@ -37,9 +37,9 @@
#include <libavfilter/buffersink.h>
#include <libavfilter/buffersrc.h>
+#include "common/av_common.h"
#include "common/msg.h"
#include "options/m_option.h"
-#include "common/av_opts.h"
#include "common/tags.h"
#include "video/img_format.h"
@@ -78,7 +78,7 @@ struct vf_priv_s {
// options
char *cfg_graph;
int64_t cfg_sws_flags;
- char *cfg_avopts;
+ char **cfg_avopts;
};
static const struct vf_priv_s vf_priv_dflt = {
@@ -143,11 +143,8 @@ static bool recreate_graph(struct vf_instance *vf, int width, int height,
if (!graph)
goto error;
- if (parse_avopts(graph, p->cfg_avopts) < 0) {
- MP_FATAL(vf, "lavfi: could not set opts: '%s'\n",
- p->cfg_avopts);
+ if (mp_set_avopts(vf->log, graph, p->cfg_avopts) < 0)
goto error;
- }
AVFilterInOut *outputs = avfilter_inout_alloc();
AVFilterInOut *inputs = avfilter_inout_alloc();
@@ -426,7 +423,7 @@ static void print_help(struct mp_log *log)
static const m_option_t vf_opts_fields[] = {
OPT_STRING("graph", cfg_graph, M_OPT_MIN, .min = 1),
OPT_INT64("sws-flags", cfg_sws_flags, 0),
- OPT_STRING("o", cfg_avopts, 0),
+ OPT_KEYVALUELIST("o", cfg_avopts, 0),
{0}
};
@@ -445,7 +442,7 @@ const vf_info_t vf_info_lavfi = {
struct vf_lw_opts {
int enable;
int64_t sws_flags;
- char *avopts;
+ char **avopts;
};
#undef OPT_BASE_STRUCT
@@ -454,7 +451,7 @@ const struct m_sub_options vf_lw_conf = {
.opts = (const m_option_t[]) {
OPT_FLAG("lavfi", enable, 0),
OPT_INT64("lavfi-sws-flags", sws_flags, 0),
- OPT_STRING("lavfi-o", avopts, 0),
+ OPT_KEYVALUELIST("lavfi-o", avopts, 0),
{0}
},
.defaults = &(const struct vf_lw_opts){
diff --git a/wscript_build.py b/wscript_build.py
index 9496977340..87bf54de43 100644
--- a/wscript_build.py
+++ b/wscript_build.py
@@ -161,7 +161,6 @@ def build(ctx):
## Core
( "common/av_common.c" ),
( "common/av_log.c" ),
- ( "common/av_opts.c" ),
( "common/codecs.c" ),
( "common/encode_lavc.c", "encoding" ),
( "common/common.c" ),