Skip to content

4.8.0 - five reported fixes, unified playbackPhase, SW background audio

Choose a tag to compare

@superuser404notfound superuser404notfound released this 30 Jun 17:09

AetherEngine 4.8.0 bundles five reported fixes, the unified playback-status API (#85), software-path background audio on iOS, and two new diagnostic CLI tools.

Playback status: unified playbackPhase (#85)

A single published playbackPhase enum is now the source of truth for playback status, replacing the separate loading / rebuffering / seeking / stall signals hosts had to reconcile. It carries a typed .stalled(reconnecting:) case, and a typed onNetworkPhaseChanged reader callback feeds it from the native, software, and audio hosts, so a reader-level network stall surfaces consistently regardless of decode path. Thanks @reckloon.

Software-path background audio (iOS)

Software-decode playback (AV1 without hardware decode, VP9) now keeps audio playing when the iOS app backgrounds, via a background-audio-only demux loop and a wedge-safe keepalive policy. The new aetherctl bgaudio harness exercises it headlessly.

Fixes

  • Open-GOP and B-frame VOD corruption (#92). VOD segment cutting is now keyframe-gated in decode order, so the IRAP opens its own segment (like the live path and FFmpeg's hls muxer). Previously each packet was routed to a segment by its DTS against PTS-valued plan boundaries; under B-frame reorder a keyframe's DTS falls below its PTS, so the boundary IRAP fell into the previous segment and the next segment started mid-GOP, decode-dependent on its predecessor. A fresh decode at such a boundary (rebuffer recovery) showed transient blocky corruption. Verified with the new segverify tool against ffmpeg ground truth (1/8 to 8/8 segments independently decodable). Thanks @rrgomes.
  • MKV with an unreadable Cues index loaded 0 tracks (#91). A bunched keyframe index that spanned less than one target segment passed the gap check but produced a single whole-file segment, which AVPlayer rejected with TrackNotFound. The planner now also requires the index to span at least one target segment (a coverage witness alongside the gap witness), else it falls back to a uniform plan. Thanks @reckloon.
  • Software-path seek black flash (#90). The software path blanked the display on a seek and flashed black until the post-seek keyframe. It now holds the last displayed frame across the seek, matching the hardware path. Thanks @rrgomes.
  • Software-decode audio crackle (#89). The software AudioDecoder stamped PTS from container-quantized timestamps, producing a per-frame click on frame durations that do not land on integer-millisecond boundaries (for example 1536-sample AC-3 at 44.1 kHz). Buffers are now stamped from a gapless running sample clock. Thanks @rrgomes.
  • Multi-second PGS subtitle startup stall (#87). The subtitle side demuxer ran a full find_stream_info (a flat ~5 s analyze ceiling) at load. It now skips that, reads the codec from the header or PMT, and falls back to a bounded resolve only when needed. Thanks @rrgomes.
  • iOS HDR and Dolby Vision format label in Stats for Nerds is now correct.

Tooling

  • aetherctl segverify <url> decodes each loopback segment in isolation and reports how many are independently decodable. This is the segment-independence ground truth used to confirm #92.
  • aetherctl --throttle-kbps <n> caps serve / segverify bandwidth to simulate a slow CDN and reproduce backpressure and recovery behaviour.

Compatibility

Minor release: additive public API (playbackPhase, onNetworkPhaseChanged, the background-audio policy). No breaking changes.