summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2017-12-10 05:07:36 +0100
committeravih <avih@users.noreply.github.com>2017-12-10 06:37:49 +0200
commitb782c901809a47dddadc33368d66d88d1bd9e9b9 (patch)
treef6fba66eff401aebf21c681c4982419667e42eff
parent451a502c1d15ad2c1b60a141c969be06fa10d152 (diff)
downloadmpv-b782c901809a47dddadc33368d66d88d1bd9e9b9.tar.bz2
mpv-b782c901809a47dddadc33368d66d88d1bd9e9b9.tar.xz
demux_timeline: disable pointless packet cache for sub-demuxers
It seems like there's nothing stopping from sub-demuxers from keeping packets in the cache, even if it's completely pointless. The top-most demuxer (demux_timeline) already takes care of caching, so sub-demuxers only waste space and time with this. Add a function that can disable the packet cache even at runtime and after packets are read. (It's not clear whether it really can happen that packets are read before demux_timeline gets the sub-demuxers, but there's no reason to make it too fragile.) Call it on all sub-demuxers. For this to work, it seems we have to move the code for setting the seekable_cache flag to before demux_timeline is potentially initialized, because otherwise the cache would be reenabled if the demuxer triggering timeline support is a timeline segment itself (e.g. ordered chapters).
-rw-r--r--demux/demux.c34
-rw-r--r--demux/demux.h2
-rw-r--r--demux/demux_timeline.c7
3 files changed, 35 insertions, 8 deletions
diff --git a/demux/demux.c b/demux/demux.c
index 80f171b757..5a052fc787 100644
--- a/demux/demux.c
+++ b/demux/demux.c
@@ -520,7 +520,7 @@ static void free_empty_cached_ranges(struct demux_internal *in)
for (int n = in->num_ranges - 2; n >= 0; n--) {
struct demux_cached_range *range = in->ranges[n];
- if (range->seek_start == MP_NOPTS_VALUE) {
+ if (range->seek_start == MP_NOPTS_VALUE || !in->seekable_cache) {
clear_cached_range(in, range);
MP_TARRAY_REMOVE_AT(in->ranges, in->num_ranges, n);
} else {
@@ -2006,6 +2006,13 @@ static struct demuxer *open_given_type(struct mpv_global *global,
demux_update(demuxer);
stream_control(demuxer->stream, STREAM_CTRL_SET_READAHEAD,
&(int){params ? params->initial_readahead : false});
+ int seekable = opts->seekable_cache;
+ if (demuxer->is_network || stream->caching) {
+ in->min_secs = MPMAX(in->min_secs, opts->min_secs_cache);
+ if (seekable < 0)
+ seekable = 1;
+ }
+ in->seekable_cache = seekable == 1;
if (!(params && params->disable_timeline)) {
struct timeline *tl = timeline_load(global, log, demuxer);
if (tl) {
@@ -2021,13 +2028,6 @@ static struct demuxer *open_given_type(struct mpv_global *global,
}
}
}
- int seekable = opts->seekable_cache;
- if (demuxer->is_network || stream->caching) {
- in->min_secs = MPMAX(in->min_secs, opts->min_secs_cache);
- if (seekable < 0)
- seekable = 1;
- }
- in->seekable_cache = seekable == 1;
return demuxer;
}
@@ -2560,6 +2560,24 @@ int demuxer_add_chapter(demuxer_t *demuxer, char *name,
return demuxer->num_chapters - 1;
}
+void demux_disable_cache(demuxer_t *demuxer)
+{
+ struct demux_internal *in = demuxer->in;
+ assert(demuxer == in->d_user);
+
+ pthread_mutex_lock(&in->lock);
+ if (in->seekable_cache) {
+ MP_VERBOSE(demuxer, "disabling persistent packet cache\n");
+ in->seekable_cache = false;
+
+ // Get rid of potential buffered ranges floating around.
+ free_empty_cached_ranges(in);
+ // Get rid of potential old packets in the current range.
+ prune_old_packets(in);
+ }
+ pthread_mutex_unlock(&in->lock);
+}
+
// must be called not locked
static void update_cache(struct demux_internal *in)
{
diff --git a/demux/demux.h b/demux/demux.h
index 9224ca3a98..aeabd36e99 100644
--- a/demux/demux.h
+++ b/demux/demux.h
@@ -298,6 +298,8 @@ int demux_stream_control(demuxer_t *demuxer, int ctrl, void *arg);
void demux_changed(demuxer_t *demuxer, int events);
void demux_update(demuxer_t *demuxer);
+void demux_disable_cache(demuxer_t *demuxer);
+
struct sh_stream *demuxer_stream_by_demuxer_id(struct demuxer *d,
enum stream_type t, int id);
diff --git a/demux/demux_timeline.c b/demux/demux_timeline.c
index 288e9f750a..4b9b3124fa 100644
--- a/demux/demux_timeline.c
+++ b/demux/demux_timeline.c
@@ -170,6 +170,8 @@ static void reopen_lazy_segments(struct demuxer *demuxer)
demuxer->stream->cancel, demuxer->global);
if (!p->current->d && !demux_cancel_test(demuxer))
MP_ERR(demuxer, "failed to load segment\n");
+ if (p->current->d)
+ demux_disable_cache(p->current->d);
associate_streams(demuxer, p->current);
}
@@ -385,6 +387,11 @@ static int d_open(struct demuxer *demuxer, enum demux_check check)
struct timeline_part *part = &p->tl->parts[n];
struct timeline_part *next = &p->tl->parts[n + 1];
+ // demux_timeline already does caching, doing it for the sub-demuxers
+ // would be pointless and wasteful.
+ if (part->source)
+ demux_disable_cache(part->source);
+
struct segment *seg = talloc_ptrtype(p, seg);
*seg = (struct segment){
.d = part->source,