Skip to content

5.0.7

Choose a tag to compare

@superuser404notfound superuser404notfound released this 15 Jul 18:11

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 probes bytes=0-1. Origins that honor real ranges but omit lengths on open-ended requests answer 206 with the total in Content-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 AVIOProvider contract) and clears AVIOContext.seekable. moov-at-end files fail cleanly at engine.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 by VODPumpFatalExitTests.

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.