AetherEngine 1.4.1
Fixes
Gate play() on panel handshake settle
In an AVKit-sole-writer architecture (host sets appliesPreferredDisplayCriteriaAutomatically = true and passes LoadOptions(suppressDisplayCriteria: true)), AVKit writes preferredDisplayCriteria from the live AVPlayerItem.formatDescription after asset.load reaches readyToPlay. The HDMI handshake kicks off a beat later than the engine's synchronous pre-flight would have, and nativeHost?.play() was firing before the panel finished switching into the target dynamic range. On DV / HDR sources this surfaced as a first-frame stall on the cold path.
Two changes:
DisplayCriteriaController.waitForSwitchStage 1 grace extended from 200 ms to 1000 ms so the later-firing AVKit auto write is reliably caught by the gate's first-stage poll.await displayCriteria.waitForSwitch()inserted before everynativeHost?.play()call (initial load path + audio-track-reload path). The 1.4.0 two-stage poll's existing logic handles both "panel already in target mode" (early return viacurrentEDRHeadroom > 1.001) and "switch in progress, wait for completion".
The gate is path-agnostic. Engine-sole-writer architectures continue to use the engine's pre-flight + waitForSwitch. AVKit-sole-writer architectures now get the same handshake guarantee, just with AVKit driving the criteria write instead.
Docs
README now credits @DrHurt for the on-device DV / HDR matrix testing.
Acknowledgements
Once again, @DrHurt for the diagnosis on #4: "I don't know if readyToPlay waits for display switch. If not, we could possibly gate play() on waitForSwitch / isDisplayModeSwitchInProgress." That's exactly the contract this release implements.
Full changelog: 1.4.0...1.4.1