Skip to content

Commit 60eca92

Browse files
docs(readme): refresh for 1.1.0 (FFmpeg 8.1, DV codec tags, sourceTime, new API)
- FFmpegBuild bump 7.1 → 8.1 in the dependency table. - DV signaling: drop the obsolete `dvhe` mention; document the bare `dvh1.<profile>.<dvLevel>` tag for Profiles 5 / 8.1 / 8.4 on DV- capable displays and the hvc1 fallback for non-DV. Cross-link the AV1+DV `dav1` / `av01` + `dvvC` path. - Drop the "AV1+DV is theoretical" claim; native AV1+DV ships and AV1+Atmos is the actual rarity. - Quick Start: surface the 1.1.0 API additions hosts actually need (`setExternalMetadata`, `$currentAVPlayer`, `$sourceTime`, `reloadAtCurrentPosition`, `LoadOptions.matchContentEnabled`) and spell out the AVPlayer-clock vs source-PTS distinction so subtitle hosts know which clock to render against. - HDR10+ section notes the runtime `.hdr10 → .hdr10Plus` flip on first T.35 SEI detection. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent da3e8ac commit 60eca92

1 file changed

Lines changed: 23 additions & 5 deletions

File tree

README.md

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,14 @@ player.bind(view: surface)
6464

6565
try await player.load(url: videoURL) // or
6666
try await player.load(url: videoURL, startPosition: 347.5) // resume
67-
try await player.load(url: videoURL, options: .init(httpHeaders: headers)) // auth
67+
try await player.load(
68+
url: videoURL,
69+
options: .init(
70+
httpHeaders: headers, // attached to every demux + segment fetch
71+
matchContentEnabled: matchContent // tvOS Match Content master toggle
72+
)
73+
)
74+
try await player.reloadAtCurrentPosition() // background reopen, preserves options
6875

6976
player.play()
7077
player.pause()
@@ -74,13 +81,20 @@ player.stop()
7481

7582
// Observe (Combine @Published)
7683
player.$state // .idle, .loading, .playing, .paused, .seeking, .error
77-
player.$currentTime
84+
player.$currentTime // AVPlayer's HLS clock (use for transport / scrub / resume)
85+
player.$sourceTime // source PTS of the displayed frame (use for subtitle alignment)
7886
player.$duration
7987
player.$videoFormat // .sdr, .hdr10, .hdr10Plus, .dolbyVision, .hlg
88+
player.$currentAVPlayer // active AVPlayer, re-emitted on every reload (MPNowPlayingSession)
8089

8190
player.audioTracks // [TrackInfo]
8291
player.selectAudioTrack(index: trackID)
8392

93+
// tvOS info panel / Now Playing
94+
player.setExternalMetadata([
95+
AVMetadataItem(/* title, artwork, etc. */)
96+
])
97+
8498
// Subtitles, text and bitmap, one published list
8599
player.subtitleTracks // [TrackInfo] for the loaded source
86100
player.selectSubtitleTrack(index: streamID) // embedded, text or bitmap
@@ -91,6 +105,8 @@ player.$isSubtitleActive // host mirror gate
91105
player.$isLoadingSubtitles // sidecar fetch + decode in progress
92106
```
93107

108+
Subtitle cues land in raw source PTS. On the native path, AVPlayer's HLS clock sits at `source_pts - producer.videoShiftPts` (the producer applies a per-session shift to align the first segment's tfdt with the playlist origin, and the shift can change on every restart). Render the overlay against `player.sourceTime` so cues match the spoken audio regardless of which producer session is active.
109+
94110
Install via Swift Package Manager:
95111

96112
```swift
@@ -127,7 +143,7 @@ Source URL ──► Demuxer ──┬─► SoftwareVideoDecoder (dav1d) ──
127143
AVR / speakers
128144
```
129145

130-
AV1 sources in the wild almost never carry Dolby Vision (DV is HEVC-profile-driven) or Atmos (mastering runs in HEVC overwhelmingly), so the SW pipeline's lack of those capabilities is a theoretical limitation rather than a real one. The dispatch happens once at load time; hosts see a unified `@Published` state surface either way.
146+
AV1+DV (Profile 10.0 / 10.1 / 10.4) routes through the native path on hardware-AV1 hosts via the `dav1` / `av01` track type plus the source's `dvvC` box. AV1+Atmos is genuinely rare in the wild (mastering still runs in HEVC overwhelmingly), so the SW pipeline's lack of Atmos passthrough is a theoretical limitation rather than a real one. The dispatch happens once at load time; hosts see a unified `@Published` state surface either way.
131147

132148
Why HLS-fMP4 for the native path instead of feeding `AVPlayer` the source URL directly: AVPlayer's progressive-download path won't accept arbitrary MKV containers, and even for MP4 sources it's brittle around Dolby Vision sample-description quirks and EAC3 `dec3` box variants. The HLS-fMP4 wrapper is the most permissive surface AVPlayer exposes; libavformat's `hls` muxer produces bytes byte-identical to `ffmpeg -f hls -hls_segment_type fmp4`, which is what Apple's HLS spec is defined against.
133149

@@ -154,12 +170,14 @@ HDR-to-SDR mapping is handled by AVPlayer and the system compositor according to
154170

155171
### Dolby Vision signaling
156172

157-
For DV streams the demuxer surfaces the source's `AVDOVIDecoderConfigurationRecord`. `HLSVideoEngine` writes the matching ISO BMFF `dvcC` box into the HLS-fMP4 sample description and promotes the track type from `hvc1` to `dvh1` (Profile 5, no HDR10 base) or `dvhe` (Profile 8.1 / 8.4 with HDR10 / HLG backward-compatible base layer). Profile 5 plays only on DV-capable displays; profiles 8.1 / 8.4 fall back to their base layer when the TV doesn't advertise DV.
173+
For DV streams the demuxer surfaces the source's `AVDOVIDecoderConfigurationRecord`. On DV-capable displays, `HLSVideoEngine` writes the matching ISO BMFF `dvcC` box into the HLS-fMP4 sample description and emits a bare `dvh1.<profile>.<dvLevel>` codec tag for Profile 5, 8.1, and 8.4 so AVKit's auto-criteria reads `dvh1` from the sample entries and engages DV mode directly. On non-DV displays the engine downgrades to plain `hvc1`: Profile 5 is unplayable there (no HDR10 base), and Profiles 8.1 / 8.4 fall back to their HDR10 / HLG base layer with AVPlayer's tone-mapping path. AV1+DV (Profile 10.0 / 10.1 / 10.4) uses the parallel `dav1` / `av01` track type plus `dvvC` box on hardware-AV1 hosts.
158174

159175
### HDR10+ dynamic metadata
160176

161177
ST 2094-40 metadata stays attached to the HEVC bitstream as user-data-registered ITU-T T.35 SEI NALs. The HLS-fMP4 stream-copy preserves the SEI through to `AVPlayer`, which forwards it to the system compositor. HDR10+-capable TVs apply the per-scene tone-mapping curves; HDR10-only TVs fall back to the static HDR10 base.
162178

179+
The published `videoFormat` starts at `.hdr10` for any BT.2020 / PQ source and flips to `.hdr10Plus` the first time a packet's T.35 SEI signature is seen in the producer's scan. Debounced across producer restarts so a scrub doesn't re-fire. Hosts can drive an HDR10+ badge or analytics hook off the `$videoFormat` transition.
180+
163181
## Subtitles
164182

165183
Subtitle packets are routed through the same demux loop as audio and video. No second AVIO connection, no full-file scan. Each packet decodes inline through `avcodec_decode_subtitle2`, the result lands in a single `[SubtitleCue]` published list:
@@ -215,7 +233,7 @@ Sources/AetherEngine/
215233

216234
| Package | License | Purpose |
217235
| ------------------------------------------------------------------ | --------- | ------------------------------------------------------------------------ |
218-
| [FFmpegBuild](https://github.com/superuser404notfound/FFmpegBuild) | LGPL-3.0 | Slim FFmpeg 7.1 (avcodec / avformat / avutil / swresample / swscale) for demux + HLS-fMP4 mux + AudioBridge FLAC encode + SW-path dav1d decode + sws_scale YUV → NV12 / P010 |
236+
| [FFmpegBuild](https://github.com/superuser404notfound/FFmpegBuild) | LGPL-3.0 | Slim FFmpeg 8.1 (avcodec / avformat / avutil / swresample / swscale) for demux + HLS-fMP4 mux + AudioBridge FLAC encode + SW-path dav1d decode + sws_scale YUV → NV12 / P010 |
219237
| VideoToolbox | System | Native path video decode (HW where available, Apple's bundled SW dav1d on iOS / macOS) |
220238
| AVFoundation | System | AVPlayer + AVDisplayManager (native path); AVSampleBufferDisplayLayer + AVSampleBufferRenderSynchronizer (SW path) |
221239
| CoreMedia | System | Sample descriptions, format-description tagging, CMTimebase |

0 commit comments

Comments
 (0)