What happened?
A Dolby Vision Profile 8.1 MKV whose hvcC states general_level_idc = 156 (level 5.2) never plays on the master playlist. The DV master is refused, then the reduced HDR master too, with AVFoundationErrorDomain -11848 'Cannot Open' (underlying CoreMediaErrorDomain -15517). The readiness gate falls back to the media playlist, so the session plays the HDR10 base with the DV upgrade dropped, and videoFormat publishes .sdr.
The stream is really 1080p24; the encoder stamped level 5.2 on it. CodecRoutePolicy copies that level into the CODECS attribute (hvc1.2.4.L156). AVPlayer checks a master variant's declared level against the device and refuses 5.2, which is 2160p120 class. The same bytes decode fine on the media playlist, where nothing is declared, and in players that don't use HLS.
Capping the declared level at 5.1 (L153) fixes it. The DV master is accepted first time and the TV engages Dolby Vision (confirmed from the TV's picture-mode menu: Dolby Vision Bright).
This is not #667. There is no -11868 in the log, and the failure reproduces unchanged on an immediate replay with the panel already in Dolby Vision, so no mode switch is involved.
Steps to reproduce
- On an Apple TV 4K with Match Dynamic Range and Match Frame Rate on, connected to a Dolby Vision TV, load a DV Profile 8.1 HEVC MKV whose hvcC has
general_level_idc = 156.
- The master (
CODECS="hvc1.2.4.L156,ac-3", SUPPLEMENTAL-CODECS="dvh1.08.03/db1p") fails with -11848 / -15517 on both attempts, master_hdr.m3u8 fails the same way, and the media playlist plays.
- Change the declared level to 153 and reload: the master is accepted and DV engages.
AetherEngine version or commit SHA
7.22.2 (the same title also showed as SDR-clamped on 6.21.1, before logs were captured)
Host app
WonkoTV (personal NAS player, not published). AetherPlayerSurface with the engine as sole writer of display criteria, .custom IOReader source over NFS.
Platform
tvOS
OS version
tvOS 27.0
Device / chip
Apple TV 4K (3rd gen) → Sony BRAVIA XR-65X90L (advertises Dolby Vision, HDR10, HLG). Format 4K SDR, Match Dynamic Range and Match Frame Rate on.
Playback path
Native, loopback remux (fMP4/HLS → AVPlayer), master playlist.
Source media
MKV, HEVC Main10 1920×802 23.976, Dolby Vision Profile 8.1 (dvh1.08.03, BL compat 1), PQ / BT.2020, AC-3 5.1.
hvcC header: profile_idc 2, compat 0x20000000, constraint 90 00 00 00 00 00, level_idc 156.
Error codes / log lines
#EXT-X-STREAM-INF:BANDWIDTH=15179914,AVERAGE-BANDWIDTH=7589957,CODECS="hvc1.2.4.L156,ac-3",SUPPLEMENTAL-CODECS="dvh1.08.03/db1p",RESOLUTION=1920x802,FRAME-RATE=23.976,VIDEO-RANGE=PQ,AUDIO="aud",CLOSED-CAPTIONS=NONE
[DisplayCriteria] SET: format=dolbyVision codec=dvh1 rate=23.976 extensions=HDR
[DisplayCriteria] switch settled via modeSwitchEnd (... panel 23.976Hz, the requested rate)
[DisplayCriteria] panel unproven but HDR-eligible: serving the master and letting AVPlayer answer
[NativeAVPlayerHost] #1 item.status=failed err=AVFoundationErrorDomain/-11848 'Cannot Open'
[NativeAVPlayerHost] #1 item.error.underlying=CoreMediaErrorDomain/-15517
[NativeAVPlayerHost] #1 errorLog dump: 0 events
[AetherEngine] #35 readiness gate: master did not start (dead) after a panel switch; reloading the master (attempt 2/2)
[NativeAVPlayerHost] #2 item.status=failed err=AVFoundationErrorDomain/-11848 'Cannot Open'
[AetherEngine] #35 readiness gate: master never produced tracks; trying the HDR-preserving reduced master (subtitles preserved, DV dropped)
[NativeAVPlayerHost] #3 item.status=failed err=AVFoundationErrorDomain/-11848 'Cannot Open'
[AetherEngine] #35 readiness gate: master never produced tracks after 2 attempts; falling back to the media playlist (HDR10 base, DV upgrade dropped this session)
[NativeAVPlayerHost] #4 item.status=readyToPlay
Results with one change at a time:
| Title |
Declared CODECS |
Result |
| The Thing With Feathers (DV P8.1) |
hvc1.2.4.L153.90,ec-3 |
master accepted, Dolby Vision |
| Dune (DV P8.1), 7.22.2 as shipped |
hvc1.2.4.L156,ac-3 |
refused ×3, media fallback |
| Dune, constraint bytes restored |
hvc1.2.4.L156.90,ac-3 |
refused ×3, media fallback |
| Dune, level capped |
hvc1.2.4.L153.90,ac-3 |
master accepted, Dolby Vision |
Anything else
Suggested fix. Cap the declared level in the CODECS attribute. min(general_level_idc, 153) covers everything up to 2160p60. A tighter version would derive the level from resolution × frame rate and declare the lower of that and the stated level. The init segment's hvcC can stay as-is; the media-playlist path shows the decoder accepts it.
Related, not the cause here. The DV branches of resolveCodecRoute hardcode hvc1.2.4.L\(hevcLevel). That drops the constraint bytes the plain-HEVC branch has derived from the hvcC since AE#187, so the DV master declares hvc1.2.4.L156 against an init whose hvcC carries .90. Restoring it alone didn't help (row 3), but it's the same master/init disagreement AE#187 fixed, and routing those branches through plainHEVCCodecs(codecpar:fallbackLevel:) makes them consistent.
Both changes are in one commit on a fork, tested on the device above: https://github.com/gonkowonko/AetherEngine/commit/58fe14067f5e25689f5735af78a80b71ee61c123. Happy to open it as a PR if that's useful; I haven't added tests to the suite.
What happened?
A Dolby Vision Profile 8.1 MKV whose hvcC states
general_level_idc = 156(level 5.2) never plays on the master playlist. The DV master is refused, then the reduced HDR master too, withAVFoundationErrorDomain -11848 'Cannot Open'(underlyingCoreMediaErrorDomain -15517). The readiness gate falls back to the media playlist, so the session plays the HDR10 base with the DV upgrade dropped, andvideoFormatpublishes.sdr.The stream is really 1080p24; the encoder stamped level 5.2 on it.
CodecRoutePolicycopies that level into theCODECSattribute (hvc1.2.4.L156). AVPlayer checks a master variant's declared level against the device and refuses 5.2, which is 2160p120 class. The same bytes decode fine on the media playlist, where nothing is declared, and in players that don't use HLS.Capping the declared level at 5.1 (
L153) fixes it. The DV master is accepted first time and the TV engages Dolby Vision (confirmed from the TV's picture-mode menu: Dolby Vision Bright).This is not #667. There is no
-11868in the log, and the failure reproduces unchanged on an immediate replay with the panel already in Dolby Vision, so no mode switch is involved.Steps to reproduce
general_level_idc = 156.CODECS="hvc1.2.4.L156,ac-3",SUPPLEMENTAL-CODECS="dvh1.08.03/db1p") fails with -11848 / -15517 on both attempts,master_hdr.m3u8fails the same way, and the media playlist plays.AetherEngine version or commit SHA
7.22.2 (the same title also showed as SDR-clamped on 6.21.1, before logs were captured)
Host app
WonkoTV (personal NAS player, not published).
AetherPlayerSurfacewith the engine as sole writer of display criteria,.customIOReader source over NFS.Platform
tvOS
OS version
tvOS 27.0
Device / chip
Apple TV 4K (3rd gen) → Sony BRAVIA XR-65X90L (advertises Dolby Vision, HDR10, HLG). Format 4K SDR, Match Dynamic Range and Match Frame Rate on.
Playback path
Native, loopback remux (fMP4/HLS → AVPlayer), master playlist.
Source media
MKV, HEVC Main10 1920×802 23.976, Dolby Vision Profile 8.1 (
dvh1.08.03, BL compat 1), PQ / BT.2020, AC-3 5.1.hvcC header: profile_idc 2, compat
0x20000000, constraint90 00 00 00 00 00, level_idc 156.Error codes / log lines
Results with one change at a time:
hvc1.2.4.L153.90,ec-3hvc1.2.4.L156,ac-3hvc1.2.4.L156.90,ac-3hvc1.2.4.L153.90,ac-3Anything else
Suggested fix. Cap the declared level in the
CODECSattribute.min(general_level_idc, 153)covers everything up to 2160p60. A tighter version would derive the level from resolution × frame rate and declare the lower of that and the stated level. The init segment's hvcC can stay as-is; the media-playlist path shows the decoder accepts it.Related, not the cause here. The DV branches of
resolveCodecRoutehardcodehvc1.2.4.L\(hevcLevel). That drops the constraint bytes the plain-HEVC branch has derived from the hvcC since AE#187, so the DV master declareshvc1.2.4.L156against an init whose hvcC carries.90. Restoring it alone didn't help (row 3), but it's the same master/init disagreement AE#187 fixed, and routing those branches throughplainHEVCCodecs(codecpar:fallbackLevel:)makes them consistent.Both changes are in one commit on a fork, tested on the device above: https://github.com/gonkowonko/AetherEngine/commit/58fe14067f5e25689f5735af78a80b71ee61c123. Happy to open it as a PR if that's useful; I haven't added tests to the suite.