aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar wm4 <wm4@nowhere>2017-12-10 04:43:25 +0100
committerGravatar avih <avih@users.noreply.github.com>2017-12-10 06:37:49 +0200
commit451a502c1d15ad2c1b60a141c969be06fa10d152 (patch)
tree60f75d00e3a6929056ae6fef3efd91ebb21c8255
parent39bc954488c27e0de6168f827be2e9c68bbf1043 (diff)
demux: fix accounting for seekable ranges on track switches
This fixes missing audio when cycling through audio tracks with anything that uses nested demuxers, such as demux_timeline, which us used for EDL, --merge-files, ordered chapters, and youtube-dl pseudo DASH support. When this bug happened, reenabling an audio track would lead to silence for the duration of the readahead amount. The underlying reason is the incorrectly updated buffered range on track switch. It accidentally included the amount covered by the deselected stream. But the cause of the observed effect was that demux_timeline issued a refresh seek to the underlying slave demuxer, which in turn thought it could do a cache seek, because the seek range still included everything. update_stream_selection_state() calls update_seek_ranges() to update the seek ranges after a track switch. When reenabling the track, ds->eager was set to false during update_seek_ranges(), which made it think the stream was sparse, and thus it didn't restrict the current seek range (making later code think everything was buffered). Fix this by moving some code, so we first update the ds->eager flag, then the seek ranges. Also verbose log the low level stream selection calls.
-rw-r--r--demux/demux.c30
1 files changed, 16 insertions, 14 deletions
diff --git a/demux/demux.c b/demux/demux.c
index 5795111753..80f171b757 100644
--- a/demux/demux.c
+++ b/demux/demux.c
@@ -560,20 +560,6 @@ static void update_stream_selection_state(struct demux_internal *in,
ds_clear_reader_state(ds);
- // Make sure any stream reselection or addition is reflected in the seek
- // ranges, and also get rid of data that is not needed anymore (or
- // rather, which can't be kept consistent).
- for (int n = 0; n < in->num_ranges; n++) {
- struct demux_cached_range *range = in->ranges[n];
-
- if (!ds->selected)
- clear_queue(range->streams[ds->index]);
-
- update_seek_ranges(range);
- }
-
- free_empty_cached_ranges(in);
-
// We still have to go over the whole stream list to update ds->eager for
// other streams too, because they depend on other stream's selections.
@@ -597,6 +583,21 @@ static void update_stream_selection_state(struct demux_internal *in,
s->eager = false;
}
}
+
+ // Make sure any stream reselection or addition is reflected in the seek
+ // ranges, and also get rid of data that is not needed anymore (or
+ // rather, which can't be kept consistent). This has to happen after we've
+ // updated all the subtle state (like s->eager).
+ for (int n = 0; n < in->num_ranges; n++) {
+ struct demux_cached_range *range = in->ranges[n];
+
+ if (!ds->selected)
+ clear_queue(range->streams[ds->index]);
+
+ update_seek_ranges(range);
+ }
+
+ free_empty_cached_ranges(in);
}
void demux_set_ts_offset(struct demuxer *demuxer, double offset)
@@ -2474,6 +2475,7 @@ void demuxer_select_track(struct demuxer *demuxer, struct sh_stream *stream,
pthread_mutex_lock(&in->lock);
// don't flush buffers if stream is already selected / unselected
if (ds->selected != selected) {
+ MP_VERBOSE(in, "%sselect track %d\n", selected ? "" : "de", stream->index);
ds->selected = selected;
update_stream_selection_state(in, ds);
in->tracks_switched = true;