fix(cache): retain software VOD read-ahead across cache-local seeks - #512
Conversation
…512) The forward-second limit was keyed on the coverage frontier, and both coverage models can stop answering. The H.264 successor model invalidates permanently on one presentation timestamp below its watermark; the duration model's containing span ends at the first hole and cannot grow past it while the clock sits behind it. With no frontier the seconds limit stopped existing and only the disk budget still bounded the producer. Measured over the real types with a 10 s window and a 400 kB budget: 283 packets read with clean timestamps, 1316 with a single late one. On the shipping budget that is a 40 second window turning into a whole-file prefetch, while `bufferedPosition` falls back to the cushion at the same moment, so nothing says it happened. The limit is measured on the reservoir instead, from the packet the consumer last took to the newest one stored. Two timestamps say it, a hole does not move it, and a late one moves it in the safe direction. The frontier keeps the job it is good at, which is `bufferedPosition`. Two more on the same subsystem: `isSourceSeekable` is true for a local open too, so a `file://` session wrote a second copy of its compressed stream into the temporary directory (14 MB in 25 s at the source bitrate) to save re-reads that are page-cache hits. A source libavformat opened itself has no AVIOProvider, and those sessions stay on the direct loop. The miss path reset the spool inside the seek. Reset removes every retained chunk one at a time: 4.5 ms at 64 MB, 18.9 ms at 256 MB, 60.9 ms at 512 MB, against a ceiling of 2 GiB, so a miss got slower the longer the session had been running. The producer is parked on `sourceRepositioning` until `endSeek` and takes `resetPending` before anything else, so the worker does it and no seek waits on it. Verified: 2759 swift-testing plus 605 XCTest green, the six standalone drivers pass, doc links resolve. Two of the four new tests fail on c9b8d63. On the same 600 s source over the same 16 Mbit origin, the 198 s backward seek is still a cache hit with no request behind it (landing 63 ms) and the published frontier is still the playhead plus the 40 s window; the `file://` arm now creates no spool directory at all. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014tQ8MerNbZQdWBpDStitoD
… how deep it is still stops (#512) Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014tQ8MerNbZQdWBpDStitoD
|
Merged in The measurement that decided it, on a 600 s H.264 source through a rate-limited 16 Mbit origin with
That is the AE#295 stutter signature on the seek path. The reservoir the software loop never had is worth as much again on its own: it read on renderer backpressure alone, which is 0.33 s to 0.36 s deep on real hardware, so any source hiccup longer than a frame interval was already a picture. Both runners green on the merge (2755 swift-testing, 605 XCTest), the six standalone drivers pass, and a 24 seek storm costs 3.6% more origin bytes than main with landings in the same class. Three things I changed afterwards rather than sending back. The forward-second limit failed open. A local path spooled for nothing. The miss path reset the spool inside the seek. One thing I left alone: the six drivers under Thanks for splitting the three submissions apart, it made this one reviewable on its own merits. The packet envelope, the lease handling and the separation of consumer generation from source epoch all held up under everything I pointed at them. |
|
Released in 6.74.0 ( |
Summary
Companion submissions, independently reviewable against main:
Give seekable software VOD a real compressed-packet read-ahead cache and a continuous selected A/V buffered frontier from startup. Retain packet chunks for cache-local forward/backward seeks instead of dropping the displayed frontier whenever the decoder repositions.
This is independent of the recovery-point routing and Matroska timestamp proposals. It does not change host progress-bar UI.
What changed
forwardBufferSegmentsand its existing session retention / volume-safety budget.AVPacket.duration, which may represent decode cadence instead of a VFR picture's display hold. Unknown/late timestamps and discontinuities never become guessed cached seconds.LiveTelemetry.softwareCacheSeekHits,softwareCacheSeekMisses,softwareCacheSourceEpoch; softwarecachedBytesreports compressed residency andbufferedPositionreports continuous cache coverage. NativeforwardBufferSecondsand decodeddisplayCushionSecondskeep their meanings.1af43f017ffca973e35f8fec1e700852f2953d55. Port combines the final accepted downstream cache state, not the earlier incomplete cache attempt. Downstream custom budget settings/public diagnostics were omitted; upstream's existing budget resolver is used. No UI, dependency pins, unrelated fork history or timestamp repair.Why packet duration was insufficient
An observed H.264 VFR window at time base 1/30000 had presentation slots separated by 16016 ticks while the corresponding packet duration was 1001. The renderer holds the previous picture until its successor; treating every packet duration as a presentation interval left a false hole at about 42.075 s. This patch changes only cache coverage accounting, not the packets or their timestamps.
Seeking within buffered content also used to clear the forward cache display. Consumer generation and producer source epoch now have separate ownership, so moving a retained cursor does not discard data already downloaded.
Test plan
9c045764bd2bfd4a8356866b768961723286a3e9, candidate 20260907131625. User verified cache progress from head, forward/backward cached seeks and an uncached seek.Risks / boundaries
The cache adds temporary disk I/O and compressed residency; the existing forward-window/volume budget remains the policy, with documented protected-record/chunk slack. H.264 successor accounting assumes its bounded picture reordering; late timestamps invalidate coverage rather than guessing. Other codecs use strict duration coverage. Live DVR and native resident-range APIs are not repurposed.
Private media, source paths/URLs, credentials, raw logs, device identifiers and screenshots are not included. No host UI changes are required.
Checklist
CHANGELOG.md, API and architecture docs updated