5.0.7
AetherEngine 5.0.7 fixes unknown-length HTTP sources entering seek-dependent paths and producing zero packets (#126), from an Emby device report. One additive API surface (AetherEngine.state now reports a fatal error for a zero-progress VOD source); every current caller is source-compatible.
Fixed
Unknown-length HTTP MP4 no longer enters a seek-dependent path and silently produces zero packets (#126)
When no size probe resolved a length (an origin answering Range: bytes=0- with 200/chunked and rejecting HEAD, e.g. Emby behind a buffering reverse proxy), the AVIO reader degraded to forward-only streaming mode but still advertised itself as seekable, both to FFmpeg and to the engine's routing layer. For a moov-at-end MP4 the mov demuxer far-forward-skipped to the tail moov (buffering the entire skipped mdat in RAM), parsed a sample index it could never rewind to (the streaming reader retains a 1 MB back-window), and every sample read died with partial file. The VOD segment producer exited with readError(-1) after zero packets, and since only live sessions react to that exit, the session died silently: the local playlist existed and reported playable, but no segment ever landed and AVPlayer parked in waitingToPlay until the host's first-frame timeout. The same URL played in VLC.
Three layers:
- Last-resort bounded range probe. After
bytes=0-and HEAD both fail to resolve a size, the reader probesbytes=0-1. Origins that honor real ranges but omit lengths on open-ended requests answer 206 with the total inContent-Range, restoring the normal fully seekable persistent path. This is the expected path for the reported setup. - Honest seekability. A VOD source that genuinely resolves no size now reports itself non-seekable (per the
AVIOProvidercontract) and clearsAVIOContext.seekable. moov-at-end files fail cleanly atengine.load()instead of parsing-then-starving, faststart files route to the sequential software path via the forward-only dispatch guard (previously custom-sources-only), and the unbounded RAM buffering of the forward skip is gone. - No silent zero-progress death. A VOD producer that exits on a read error having produced nothing (zero packets written, empty segment cache) now surfaces a fatal source failure through
AetherEngine.state(.error) instead of leaving the player waiting forever. The decision is pure and covered byVODPumpFatalExitTests.
Live sessions are exempt from all three layers by design: the live producer never seeks backward and owns its own reopen/recovery arms.
Thanks to @YangHanqing for the precise log capture and the VLC control test.