Skip to content

3.4.1 — HE-AAC plays natively (no needless EAC3 bridge)

Choose a tag to compare

@superuser404notfound superuser404notfound released this 14 Jun 12:29
· 129 commits to main since this release

Fixed

HE-AAC no longer needlessly bridged to EAC3 (#33)

HE-AAC (SBR) and HE-AACv2 (PS) audio tracks were unconditionally routed through the audio bridge and re-encoded to EAC3, even from movie containers that AVPlayer decodes natively. Reported by DrHurt (#33), who confirmed a manual remux and a Jellyfin server-side remux both played fine.

Root cause. The HE-AAC detection (profile == AAC_HE / AAC_HE_V2, or an SBR frame_size of 2048) forced the bridge for every HE-AAC source. That was only ever justified for the live ADTS/MPEG-TS path, where the source carries no AudioSpecificConfig and prepareAACForFMP4 has to synthesize one. The synthesized ASC declares plain LC at the SBR output rate (e.g. mp4a.40.2 @ 48 kHz for a 24 kHz core), which AudioToolbox decodes as garbage (-11821). A movie container already ships a correct ASC in extradata, so fMP4 stream-copy preserves the SBR/PS signaling and plays natively.

Fix. The HE-AAC bridge decision now lives in a pure, unit-tested aacRequiresBridge(profile:frameSize:hasASC:) and is gated on the source lacking an ASC. With an ASC present the track stream-copies; without one (live) it still bridges, exactly as before.

Verified end-to-end with aetherctl serve on a real HE-AAC track (same file, before vs after):

before: audio: HE-AAC (profile=4 frameSize=2048) ... bridging instead  ->  audio=bridge, codec=...,ec-3
after:  audio: codec=aac -> stream-copy as `mp4a.40.2`                 ->  audio=stream-copy, codec=...,mp4a.40.2

Full test suite green (62 tests, incl. 6 new AACBridgeRoutingTests).


Full changelog: https://github.com/superuser404notfound/AetherEngine/blob/main/CHANGELOG.md