From e8147843fc072c5056d99b6c162216d82f1eedc7 Mon Sep 17 00:00:00 2001 From: wm4 Date: Fri, 7 Jun 2019 17:09:22 +0200 Subject: [PATCH] demux: really disable cache for sub-demuxers It seems the so called demuxer cache wasn't really disabled for sub-demuxers (timeline stuff). This was relatively harmless, since the actual packet data was shared anyway via refcounting. But with the addition of a mmap cache backend, this may change a lot. So strictly disable any caching for sub-demuxers. This assumes that users of sub-demuxers (only demux_timeline.c by now?) strictly use demux_read_any_packet(), since demux_read_packet_async() will require some minor read-ahead if a low level packet read returned a packet for a different stream. This requires some awkward messing with this fucking heap of trash. The thing that is really wrong here is that the demuxer API mixes different concepts, and sub-demuxers get the same API as decoders, and use the cache code. --- demux/demux.c | 15 ++++++++++----- demux/demux.h | 1 + player/loadfile.c | 5 ++++- 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/demux/demux.c b/demux/demux.c index 775d95b187..882e8e605f 100644 --- a/demux/demux.c +++ b/demux/demux.c @@ -2923,21 +2923,26 @@ static struct demuxer *open_given_type(struct mpv_global *global, seekable = 1; } in->seekable_cache = seekable == 1; + struct demuxer *sub = NULL; if (!(params && params->disable_timeline)) { struct timeline *tl = timeline_load(global, log, demuxer); if (tl) { struct demuxer_params params2 = {0}; params2.timeline = tl; - struct demuxer *sub = + params2.is_top_level = params && params->is_top_level; + sub = open_given_type(global, log, &demuxer_desc_timeline, demuxer->stream, ¶ms2, DEMUX_CHECK_FORCE); - if (sub) { - demuxer = sub; - } else { + if (!sub) timeline_destroy(tl); - } } } + if (!(params && params->is_top_level) || sub) { + in->seekable_cache = false; + in->min_secs = 0; + in->max_bytes = 1; + } + demuxer = sub ? sub : demuxer; // Let this demuxer free demuxer->stream. Timeline sub-demuxers can // share a stream, and in these cases the demux_timeline instance // should own the stream, as it frees the sub demuxers first. diff --git a/demux/demux.h b/demux/demux.h index da315adebb..63897c342d 100644 --- a/demux/demux.h +++ b/demux/demux.h @@ -158,6 +158,7 @@ typedef struct demux_attachment } demux_attachment_t; struct demuxer_params { + bool is_top_level; // if true, it's not a sub-demuxer (enables cache etc.) char *force_format; int matroska_num_wanted_uids; struct matroska_segment_uid *matroska_wanted_uids; diff --git a/player/loadfile.c b/player/loadfile.c index c730d2e8f8..69cccb2c5c 100644 --- a/player/loadfile.c +++ b/player/loadfile.c @@ -724,7 +724,9 @@ int mp_add_external_file(struct MPContext *mpctx, char *filename, if (strncmp(disp_filename, "memory://", 9) == 0) disp_filename = "memory://"; // avoid noise - struct demuxer_params params = {0}; + struct demuxer_params params = { + .is_top_level = true, + }; switch (filter) { case STREAM_SUB: @@ -968,6 +970,7 @@ static void *open_demux_thread(void *ctx) .force_format = mpctx->open_format, .stream_flags = mpctx->open_url_flags, .stream_record = true, + .is_top_level = true, }; mpctx->open_res_demuxer = demux_open_url(mpctx->open_url, &p, mpctx->open_cancel, mpctx->global);