summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--DOCS/man/options.rst12
-rw-r--r--demux/demux_lavf.c31
2 files changed, 41 insertions, 2 deletions
diff --git a/DOCS/man/options.rst b/DOCS/man/options.rst
index 6a73ac7a85..aaabed7696 100644
--- a/DOCS/man/options.rst
+++ b/DOCS/man/options.rst
@@ -3127,6 +3127,18 @@ Demuxer
the first song in the stream. Well, you won't get anything useful either
way if the seek is outside of mpv's cache.
+``--demuxer-lavf-propagate-opts=<yes|no>``
+ Propagate FFmpeg-level options to recursively opened connections (default:
+ yes). This is needed because FFmpeg will apply these settings to nested
+ AVIO contexts automatically. On the other hand, this could break in certain
+ situations - it's the FFmpeg API, you just can't win.
+
+ This affects in particular the ``--timeout`` option and anything passed
+ with ``--demuxer-lavf-o``.
+
+ If this option is deemed unnecessary at some point in the future, it will
+ be removed without notice.
+
``--demuxer-mkv-subtitle-preroll=<yes|index|no>``, ``--mkv-subtitle-preroll``
Try harder to show embedded soft subtitles when seeking somewhere. Normally,
it can happen that the subtitle at the seek target is not shown due to how
diff --git a/demux/demux_lavf.c b/demux/demux_lavf.c
index 5153bfe42f..5f9d5a3781 100644
--- a/demux/demux_lavf.c
+++ b/demux/demux_lavf.c
@@ -79,6 +79,7 @@ struct demux_lavf_opts {
char *sub_cp;
int rtsp_transport;
int linearize_ts;
+ int propagate_opts;
};
const struct m_sub_options demux_lavf_conf = {
@@ -104,6 +105,7 @@ const struct m_sub_options demux_lavf_conf = {
{"http", 3})),
OPT_CHOICE("demuxer-lavf-linearize-timestamps", linearize_ts, 0,
({"no", 0}, {"auto", -1}, {"yes", 1})),
+ OPT_FLAG("demuxer-lavf-propagate-opts", propagate_opts, 0),
{0}
},
.size = sizeof(struct demux_lavf_opts),
@@ -118,6 +120,7 @@ const struct m_sub_options demux_lavf_conf = {
.sub_cp = "auto",
.rtsp_transport = 2,
.linearize_ts = -1,
+ .propagate_opts = 1,
},
};
@@ -232,6 +235,8 @@ typedef struct lavf_priv {
int linearize_ts;
bool any_ts_fixed;
+ AVDictionary *av_opts;
+
// Proxying nested streams.
struct nested_stream *nested;
int num_nested;
@@ -851,8 +856,27 @@ static int nested_io_open(struct AVFormatContext *s, AVIOContext **pb,
struct demuxer *demuxer = s->opaque;
lavf_priv_t *priv = demuxer->priv;
+ if (priv->opts->propagate_opts) {
+ // Copy av_opts to options, but only entries that are not present in
+ // options. (Hope this will break less by not overwriting important
+ // settings.)
+ AVDictionaryEntry *cur = NULL;
+ while ((cur = av_dict_get(priv->av_opts, "", cur, AV_DICT_IGNORE_SUFFIX)))
+ {
+ if (!*options || !av_dict_get(*options, cur->key, NULL, 0)) {
+ MP_TRACE(demuxer, "Nested option: '%s'='%s'\n",
+ cur->key, cur->value);
+ av_dict_set(options, cur->key, cur->value, 0);
+ } else {
+ MP_TRACE(demuxer, "Skipping nested option: '%s'\n", cur->key);
+ }
+ }
+ }
+
int r = priv->default_io_open(s, pb, url, flags, options);
if (r >= 0) {
+ if (options)
+ mp_avdict_print_unset(demuxer->log, MSGL_TRACE, *options);
struct nested_stream nest = {
.id = *pb,
};
@@ -972,16 +996,19 @@ static int demux_open_lavf(demuxer_t *demuxer, enum demux_check check)
if (demuxer->access_references) {
priv->default_io_open = avfc->io_open;
priv->default_io_close = avfc->io_close;
-#if !HAVE_FFMPEG_STRICT_ABI
avfc->io_open = nested_io_open;
avfc->io_close = nested_io_close;
-#endif
} else {
avfc->io_open = block_io_open;
}
mp_set_avdict(&dopts, lavfdopts->avopts);
+ if (av_dict_copy(&priv->av_opts, dopts, 0) < 0) {
+ av_dict_free(&dopts);
+ return -1;
+ }
+
if (avformat_open_input(&avfc, priv->filename, priv->avif, &dopts) < 0) {
MP_ERR(demuxer, "avformat_open_input() failed\n");
av_dict_free(&dopts);