Skip to content

7.15.1 - A frontier with holes, a latch in the wrong window, a playhead read too early

Choose a tag to compare

@superuser404notfound superuser404notfound released this 23 Sep 12:47
· 119 commits to main since this release

Four fixes, no API change.

Fixed

The software VOD buffer frontier on HEVC, and after a long session (#613). HEVC kept the strict pts + duration packet coverage, which tolerates no gap. A Matroska file muxed with 41 ms durations against 41/42 ms deltas at 23.976 fps left a one-tick hole at every 42 ms step, so the frontier, bufferedPosition and cached-seek eligibility all ended at the next rounding hole. HEVC now takes the successor-timestamp model H.264 already used, under FFmpeg's own reorder bound (hevc/ps.c rejects sps_max_num_reorder_pics above 15, inside the 32-timestamp queue).

Separately, a coverage that reached its 4096-range cap stopped describing new packets (duration model) or invalidated itself (successor model), so every frontier after the cap was nil. It now forgets the ranges wholly behind the playhead first; a backward cached seek into forgotten history goes cold, which is correct.

  • Measured on a 4K HEVC Matroska fixture over an HTTP origin, aetherctl --sw: buffer 0.4 s ahead of the playhead before, 39.8 s after (the forward window).

A master refused while the display is ineligible for HDR no longer latches (#535). An audio route death right after a display mode switch opens a window in which the criteria readout reads matching=off hdrEligible=no. A session-preserving reload landing in it gets -11868 from AVPlayer, which is explained by the window and says nothing about whether the output configuration accepts an HDR master. The engine latched it anyway, so every later HDR title in the session went media-direct, and in a process that never backgrounds, the 7.10.1 clear (#588) never came. Measured by cmcpherson274 on an Apple TV 4K (tvOS 26.6): three of four such reloads latched, two in processes that never backgrounded.

The latch now also needs AVPlayer.eligibleForHDRPlayback to read true at the refusal. The item still takes its media fallback either way, and a refusal that is not latched says so in the log.

An audio-delay rebuild raised the moment one returned keeps the playhead (#464). rebuildPosition honoured the parked position only while state == .loading, but the autostart at the tail of load() writes .playing before the new host has published a position. For the next ~50 ms the clock still reads the zero load() wrote, so a correction raised in that window rebuilt the session at its head. setAudioDelay's own catch-up pass sits exactly there, and so does a second stepper press 50 to 90 ms after the first.

A playable session whose clock reads exactly the reset zero now answers with the parked position. An accepted seek retires the parked value, so a genuine seek to 0 is never overridden.

  • aetherctl, 300 s H.264 + AAC, two presses 50 to 90 ms apart: before, the rebuild mounted at 0.00s on every run; after, at 14.90s on every run. Control: load at 100 s, seek to 0, correct, and the rebuild mounts at 0.00s.

aetherctl builds in Release again (#610). The stallclock drill called stallRendererClockForTesting() and rendererClockRateForTesting unguarded, and both live inside #if DEBUG, so swift build -c release failed at every tag from 7.6.0 to 7.15.0. The library products were never affected and aetherctl is not a product. A Release binary now reports that the drill needs a DEBUG build, and CI builds aetherctl in Release so the gap cannot reopen unnoticed.

swift test: 3367 swift-testing tests in 455 suites and 629 XCTest tests pass.


Full notes: CHANGELOG · 7.15.0...7.15.1