Skip to content

Commit 2ccc8d3

Browse files
chore(release): prep 6.38.0 - an untimed frame is repaired before it is refused
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RbWZLwBVLGM1xUVXa9NeJ1
1 parent fd0b79c commit 2ccc8d3

3 files changed

Lines changed: 27 additions & 4 deletions

File tree

CHANGELOG.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,29 @@ the public-API contract.
1212

1313
_Nothing yet._
1414

15+
## [6.38.0] - 2026-08-24
16+
17+
### Fixed
18+
19+
- **A decoded frame with no timestamp of its own was refused rather than repaired (AE#407).** The
20+
software path had a drop for an untimed frame at two layers (the deinterlacer discards its own
21+
untimestamped output, `SampleBufferRenderer.enqueue` refuses a sample the render synchronizer
22+
cannot pace and whose NaN would reorder its neighbours) and no repair between them, so the only
23+
thing standing between an untimed picture and a dropped one was the demuxer's `+genpts`, one flag
24+
on one open. The direct path now reads `best_effort_timestamp` when the decoder set no PTS, which
25+
is libavcodec's own `guess_correct_pts(pts, pkt_dts)` and the reconstruction every other
26+
FFmpeg-based player consumes. It is placed directly after `avcodec_receive_frame`, so captions,
27+
the filter graph and the emit path all see one repaired timestamp rather than each reading the raw
28+
field separately, and a frame carrying neither value still falls through to the gate, because
29+
inventing a position is worse than losing a picture. Two shapes reach the decoder untimed on their
30+
own: Matroska `V_MS/VFW/FOURCC` tracks, where `matroskadec.c` writes the block time to DTS and
31+
leaves `pkt->pts` unset (which is how VC-1 and the legacy Microsoft codecs are stored), and live
32+
MPEG-TS, which delivers untimed pictures outright. Measured on a VC-1 Matroska fixture with
33+
`+genpts` suppressed: before, every frame was refused at the enqueue gate, no picture appeared and
34+
the demux loop ran a 58 s file dry in 2.5 s because nothing paced it; after, 25 enqueues per second
35+
on a 25 fps source and a clock that advances. With `+genpts` on, the repair never fires and nothing
36+
changes. Reported by @classicjazz.
37+
1538
## [6.37.0] - 2026-08-23
1639

1740
### Fixed

Examples/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ Three samples covering different audiences:
1818
```
1919
https://github.com/superuser404notfound/AetherEngine
2020
```
21-
Dependency Rule: Up to Next Major Version, starting from `6.37.0`. Add the `AetherEngine` library product to your app target.
21+
Dependency Rule: Up to Next Major Version, starting from `6.38.0`. Add the `AetherEngine` library product to your app target.
2222

2323
3. **Drop the file in.** Replace the Xcode template's default `App.swift` (or whatever the generated `@main` file is called) with the contents of [`MinimalPlayerApp.swift`](MinimalPlayer/MinimalPlayerApp.swift). The file is self-contained: it defines both the `@main App` struct and the `ContentView`.
2424

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -325,7 +325,7 @@ Subtitle cues land in raw source PTS; render the overlay against `player.sourceT
325325
Install via Swift Package Manager:
326326

327327
```swift
328-
.package(url: "https://github.com/superuser404notfound/AetherEngine", from: "6.37.0")
328+
.package(url: "https://github.com/superuser404notfound/AetherEngine", from: "6.38.0")
329329
```
330330

331331
Three samples ship in `Examples/`:
@@ -528,10 +528,10 @@ Browse all of this as a searchable site at **[aetherengine.superuser404.de](http
528528
AetherEngine uses [Semantic Versioning](https://semver.org). The public API surface, every `public` declaration in `Sources/AetherEngine/`, is the stability contract. **Major** removes / renames public symbols or breaks adopters; **Minor** adds public API or codec / format support; **Patch** fixes bugs with no public API change. `internal` types are not part of the contract.
529529

530530
```swift
531-
.package(url: "https://github.com/superuser404notfound/AetherEngine", from: "6.37.0")
531+
.package(url: "https://github.com/superuser404notfound/AetherEngine", from: "6.38.0")
532532
```
533533

534-
Pin to `.upToNextMinor(from: "6.37.0")` for stricter teams that prefer to opt into minor bumps explicitly.
534+
Pin to `.upToNextMinor(from: "6.38.0")` for stricter teams that prefer to opt into minor bumps explicitly.
535535

536536
## Requirements
537537

0 commit comments

Comments
 (0)