4.2.1
AetherEngine 4.2.1 is a patch release that hardens the remote-HTTP read path. It fixes two interacting failure modes on the persistent AVIOReader, both reported and diagnosed in detail by reckloon, who also validated the fix across remote files from roughly 820 MB up to 67 GB (MP4 and MKV).
No public API changes.
Fixed
Reconnect storm on a non-faststart / coarsely-interleaved remote MP4 (#69)
A remote MP4 with a trailing moov and track data tens of MB apart makes the demuxer ping-pong across distant file regions during avformat_find_stream_info / index parse. The persistent reader used to tear down and reopen its HTTP connection on every such non-sequential read, so the parse storm drove the origin into a 429 and playback never started. A fast-start file from the same origin played fine.
Those random-access parse reads now go through the existing pooled, keep-alive session instead of reconnecting, cached as 4 MB aligned blocks in a small LRU (8 blocks, roughly 32 MB, VOD sources only). The single long-lived streaming connection stays anchored, the parse ping-pong becomes cache hits, and the reconnect storm collapses to the two legitimate reconnects (the initial open plus the one seek to the trailing moov).
Properties that keep it safe:
- The sequential playback fast path never enters the cache, so steady playback carries no overhead and no behavior change.
- Only full-length blocks are cached. A truncated range response is served once but not cached, so it cannot shadow the re-fetch of its own uncovered tail.
- Once detour reads turn sequential past 8 MB the streaming connection re-anchors there, so sustained playback and large backward scrubs return to the cheap sliding-window path.
- Live and unknown-size sources are gated out and keep the unchanged reconnect path.
Reconnect loop under a sustained 429 (#71)
When an origin rate-limited essentially every request, the reader looped reconnecting (gen=N climbing) instead of failing cleanly. Two causes: a 429 carried no Retry-After, so the backoff was zero; and the random-access parse seeks kept resetting the unproductive-reconnect streak before it reached the give-up cap.
A 429/503 now drives a separate rate-limit streak that the seek-driven reconnects do not reset and that only real read progress clears. A throttled origin gives up cleanly after a bounded number of attempts, with exponential backoff that grows even when no Retry-After is present. The detour cache's miss-under-429 fallback backs off in place and retries the pooled fetch rather than opening a fresh connection, so it cannot re-enter the churn the cache exists to remove. A healthy origin reads successfully, keeping the streak at zero, so normal playback is unaffected.
Thanks
Thanks to reckloon for the thorough diagnosis, the proposed detour-cache design, and validating it on real remote sources before this shipped.