|author||wm4 <wm4@nowhere>||2017-11-09 09:53:46 +0100|
|committer||wm4 <wm4@nowhere>||2017-11-09 10:23:57 +0100|
demux: support multiple seekable cached ranges
Until now, the demuxer cache was limited to a single range. Extend this to multiple range. Should be useful for slow network streams. This commit changes a lot in the internal demuxer cache logic, so there's a lot of room for bugs and regressions. The logic without demuxer cache is mostly untouched, but also involved with the code changes. Or in other words, this commit probably fucks up shit. There are two things which makes multiple cached ranges rather hard: 1. the need to resume the demuxer at the end of a cached range when seeking to it 2. joining two adjacent ranges when the lowe range "grows" into it (and resuming the demuxer at the end of the new joined range) "Resuming" the demuxer means that we perform a low level seek to the end of a cached range, and properly append new packets to it, without adding packets multiple times or creating holes due to missing packets. Since audio and video never line up exactly, there is no clean "cut" possible, at which you could resume the demuxer cleanly (for 1.) or which you could use to detect that two ranges are perfectly adjacent (for 2.). The way how the demuxer interleaves multiple streams is also unpredictable. Typically you will have to expect that it randomly allows one of the streams to be ahead by a bit, and so on. To deal with this, we have heuristics in place to detect when one packet equals or is "behind" a packet that was demuxed earlier. We reuse the refresh seek logic (used to "reread" packets into the demuxer cache when enabling a track), which checks for certain packet invariants. Currently, it observes whether either the raw packet position, or the packet DTS is strictly monotonically increasing. If none of them are true, we discard old ranges when creating a new one. This heavily depends on the file format and the demuxer behavior. For example, not all file formats have DTS, and the packet position can be unset due to libavformat not always setting it (e.g. when parsers are used). At the same time, we must deal with all the complicated state used to track prefetching and seek ranges. In some complicated corner cases, we just give up and discard other seek ranges, even if the previously mentioned packet invariants are fulfilled. To handle joining, we're being particularly dumb, and require a small overlap to be confident that two ranges join perfectly. (This could be done incrementally with as little overlap as 1 packet, but corner cases would eat us: each stream needs to be joined separately, and the cache pruning logic could remove overlapping packets for other streams again.) Another restriction is that switching the cached range will always trigger an asynchronous low level seek to resume demuxing at the new range. Some users might find this annoying. Dealing with interleaved subtitles is not fully handled yet. It will clamp the seekable range to where subtitle packets are.
Diffstat (limited to 'DOCS')
2 files changed, 7 insertions, 6 deletions
diff --git a/DOCS/man/input.rst b/DOCS/man/input.rst
index 987e369a15..2b3e2a3795 100644
@@ -1264,9 +1264,9 @@ Property list
Each entry in ``seekable-ranges`` represents a region in the demuxer cache
that can be seeked to. If there are multiple demuxers active, this only
returns information about the "main" demuxer, but might be changed in
- future to return unified information about all demuxers. There is currently
- only at most 1 range. Should the player implement caching for multiple
- ranges, the order of the ranges will be unspecified and arbitrary.
+ future to return unified information about all demuxers. The ranges are in
+ arbitrary order. Often, ranges will overlap for a bit, before being joined.
+ In broken corner cases, ranges may overlap all over the place.
The end of a seek range is usually smaller than the value returned by the
``demuxer-cache-time`` property, because that property returns the guessed
diff --git a/DOCS/man/options.rst b/DOCS/man/options.rst
index 7dd1dc6af9..490b815415 100644
@@ -2879,11 +2879,12 @@ Demuxer
enabled, short seek offsets will not trigger a low level demuxer seek
(which means for example that slow network round trips or FFmpeg seek bugs
can be avoided). If a seek cannot happen within the cached range, a low
- level seek will be triggered. Seeking outside of the cache will always
- discard the full cache.
+ level seek will be triggered. Seeking outside of the cache will start a new
+ cached range, but can discard the old cache range if the demuxer exhibits
+ certain unsupported behavior.
Keep in mind that some events can flush the cache or force a low level
- seek anyway, such as switching tracks, or attmepting to seek before the
+ seek anyway, such as switching tracks, or attempting to seek before the
start or after the end of the file. This option is experimental - thus
disabled, and bugs are to be expected.