mirror of https://github.com/mpv-player/mpv
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.
This commit is contained in:
parent
39bc954488
commit
451a502c1d
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue