summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--demux/demux.c22
-rw-r--r--demux/demux.h2
-rw-r--r--demux/demux_lavf.c13
3 files changed, 34 insertions, 3 deletions
diff --git a/demux/demux.c b/demux/demux.c
index cfea29b978..29e13f3344 100644
--- a/demux/demux.c
+++ b/demux/demux.c
@@ -1152,6 +1152,23 @@ static void demux_init_cuesheet(struct demuxer *demuxer)
}
}
+static void demux_maybe_replace_stream(struct demuxer *demuxer)
+{
+ struct demux_internal *in = demuxer->in;
+ assert(!in->threading && demuxer == in->d_user);
+
+ if (demuxer->fully_read) {
+ MP_VERBOSE(demuxer, "assuming demuxer read all data; closing stream\n");
+ free_stream(demuxer->stream);
+ demuxer->stream = open_memory_stream(NULL, 0); // dummy
+ in->d_thread->stream = demuxer->stream;
+ in->d_buffer->stream = demuxer->stream;
+
+ if (demuxer->desc->control)
+ demuxer->desc->control(in->d_thread, DEMUXER_CTRL_REPLACE_STREAM, NULL);
+ }
+}
+
static struct demuxer *open_given_type(struct mpv_global *global,
struct mp_log *log,
const struct demuxer_desc *desc,
@@ -1313,6 +1330,7 @@ done:
// Convenience function: open the stream, enable the cache (according to params
// and global opts.), open the demuxer.
// (use free_demuxer_and_stream() to free the underlying stream too)
+// Also for some reason may close the opened stream if it's not needed.
struct demuxer *demux_open_url(const char *url,
struct demuxer_params *params,
struct mp_cancel *cancel,
@@ -1331,7 +1349,9 @@ struct demuxer *demux_open_url(const char *url,
if (!params->disable_cache)
stream_enable_cache(&s, &opts->stream_cache);
struct demuxer *d = demux_open(s, params, global);
- if (!d) {
+ if (d) {
+ demux_maybe_replace_stream(d);
+ } else {
params->demuxer_failed = true;
free_stream(s);
}
diff --git a/demux/demux.h b/demux/demux.h
index c7d1b8ee1d..9978335cfd 100644
--- a/demux/demux.h
+++ b/demux/demux.h
@@ -43,6 +43,7 @@ enum demux_ctrl {
DEMUXER_CTRL_STREAM_CTRL,
DEMUXER_CTRL_GET_READER_STATE,
DEMUXER_CTRL_GET_BITRATE_STATS, // double[STREAM_TYPE_COUNT]
+ DEMUXER_CTRL_REPLACE_STREAM,
};
struct demux_ctrl_reader_state {
@@ -220,6 +221,7 @@ typedef struct demuxer {
// thread-safe, only the demuxer is allowed to access the stream directly.
// You can freely use demux_stream_control() to send STREAM_CTRLs, or use
// demux_pause() to get exclusive access to the stream.
+ // Also note that the stream can get replaced if fully_read is set.
struct stream *stream;
} demuxer_t;
diff --git a/demux/demux_lavf.c b/demux/demux_lavf.c
index 4b236ee2be..d7dbfe3ff1 100644
--- a/demux/demux_lavf.c
+++ b/demux/demux_lavf.c
@@ -162,6 +162,7 @@ static const struct format_hack format_hacks[] = {
typedef struct lavf_priv {
struct stream *stream;
+ bool own_stream;
char *filename;
struct format_hack format_hack;
AVInputFormat *avif;
@@ -290,8 +291,10 @@ static void convert_charset(struct demuxer *demuxer)
if (conv.start)
data = conv;
}
- if (data.start)
+ if (data.start) {
priv->stream = open_memory_stream(data.start, data.len);
+ priv->own_stream = true;
+ }
talloc_free(alloc);
}
@@ -1068,6 +1071,12 @@ redo:
av_seek_frame(priv->avfc, 0, stream_tell(priv->stream),
AVSEEK_FLAG_BYTE);
return DEMUXER_CTRL_OK;
+ case DEMUXER_CTRL_REPLACE_STREAM:
+ if (priv->own_stream)
+ free_stream(priv->stream);
+ priv->own_stream = false;
+ priv->stream = demuxer->stream;
+ return DEMUXER_CTRL_OK;
default:
return DEMUXER_CTRL_NOTIMPL;
}
@@ -1092,7 +1101,7 @@ static void demux_close_lavf(demuxer_t *demuxer)
#endif
}
}
- if (priv->stream != demuxer->stream)
+ if (priv->own_stream)
free_stream(priv->stream);
talloc_free(priv);
demuxer->priv = NULL;