Skip to content

[macOS / CoreAudio] Working HDMI Bitstream Passthrough for Dolby Atmos (E-AC-3 & TrueHD) on Apple Silicon via undocumented CoreAudio physical FormatIDs (cc+3, mtc+, mtct) #18783

Description

@ric-dicle

mpv Information

mpv v0.41.0 Copyright © 2000-2026 mpv/MPlayer/mplayer2 projects
libplacebo version: v7.351.0
FFmpeg version: 9.0.2
FFmpeg library versions:
   libavutil       61.1.102
   libavcodec      63.1.102
   libavformat     63.1.102

Other Information

mpv v0.41.0 Copyright © 2000-2026 mpv/MPlayer/mplayer2 projects
libplacebo version: v7.351.0
FFmpeg version: 9.0.2
FFmpeg library versions:
   libavutil       61.1.102
   libavcodec      63.1.102
   libavformat     63.1.102

Reproduction Steps

Run mpv on Apple Silicon macOS connected via HDMI / eARC to a Dolby Atmos soundbar/AVR with:
mpv --ao=coreaudio_exclusive --audio-exclusive=yes --audio-spdif=ac3,eac3,dts,dts-hd,truehd file_with_eac3_or_truehd_atmos.mkv

Expected Behavior

ao_coreaudio_exclusive should select the 192 kHz ('cc+3') or 768 kHz ('mtc+' / 'mtct') compressed physical formats advertised by macOS CoreAudio and pass E-AC-3 Atmos and TrueHD Atmos bitstreams to the HDMI sink.

Actual Behavior

ao_coreaudio_exclusive hardcodes 'cac3' (48 kHz) in ca_fill_asbd(), fails to match any 192 kHz or 768 kHz physical format, and falls back to 48 kHz or multichannel PCM.
(See full root cause analysis, CoreAudio format table, and working C patch below).

Log File

Summary

Contrary to the long-standing assumption that macOS / Apple Silicon blocks HDMI bitstream passthrough for Dolby Digital Plus (E-AC-3 + Dolby Atmos) and Dolby TrueHD (TrueHD + Dolby Atmos), we discovered that modern macOS CoreAudio HDMI drivers (IOAudio2 / Apple Silicon HDMI / DisplayPort-to-HDMI eARC) do expose native compressed IEC 61937 physical formats at 192 kHz and 768 kHz via kAudioStreamPropertyAvailablePhysicalFormats.

Currently, mpv (ao_coreaudio_exclusive + ao_coreaudio_utils.c + ad_spdif.c) only passes standard AC-3 / DTS (48 kHz) and fails on E-AC-3 and TrueHD because:

  1. ca_formatid_is_compressed() in audio/out/ao_coreaudio_utils.c only checks legacy 48 kHz FourCCs ('cac3', 'ac-3', 'iac3', 'IAC3').
  2. ca_fill_asbd() hardcodes asbd->mFormatID = kAudioFormat60958AC3 ('cac3') regardless of the SPDIF sample rate (48000, 192000, or 768000).
  3. In audio/decode/ad_spdif.c, AV_CODEC_ID_TRUEHD (and DTS-HD) configures the IEC 61937 HBR stream as 8 channels @ 192000 Hz (ALSA/WASAPI convention), whereas macOS CoreAudio exposes HDMI HBR (24.576 Mbps / 61440 bytes per packet) as 2 channels @ 768000 Hz (15360 frames per packet, 4 bytes per frame).

1. CoreAudio Physical Formats Exposed by macOS on HDMI / eARC

Querying kAudioStreamPropertyAvailablePhysicalFormats on macOS (tested on Apple Silicon MacBook Pro -> HDMI 2.1 monitor ASUS PG32UCDMR -> eARC Dolby Atmos Soundbar) reveals the following non-PCM physical formats (flags=0x4c, ch=2, bits=16, bpf=4):

FourCC (mFormatID) Hex Value mSampleRate mBytesPerPacket mFramesPerPacket Bitstream Format
'cac3' 0x63616333 48000 Hz 6144 1536 Standard AC-3 / DTS (5.1)
'cec3' 0x63656333 192000 Hz 24576 6144 E-AC-3 (Dolby Digital Plus without Atmos flag)
'cc+3' 0x63632b33 192000 Hz 24576 6144 E-AC-3 + Dolby Atmos (JOC)
'cd+3' 0x63642b33 192000 Hz 24576 6144 E-AC-3 + Dolby Atmos (alt)
'mtct' 0x6d746374 768000 Hz 61440 15360 Dolby TrueHD / MAT 2.0
'mtc+' 0x6d74632b 768000 Hz 61440 15360 Dolby TrueHD / MAT 2.0 + Dolby Atmos

Important Hardware Behavior Observed:

  • When feeding an ffmpeg -f spdif IEC 61937 E-AC-3 Atmos stream (192 kHz, 24576 bytes/burst) to CoreAudio in hog/exclusive mode:
    • Selecting 'cec3' (0x63656333) causes the AVR/Soundbar to detect plain Dolby Digital Plus (5.1/7.1) (HDMI InfoFrame does not signal Atmos/JOC).
    • Selecting 'cc+3' (0x63632b33) immediately triggers Dolby Atmos decoding on the AVR/Soundbar!
  • When feeding an ffmpeg -f spdif IEC 61937 TrueHD Atmos stream (61440 bytes/MAT burst, 3,072,000 bytes/sec) to CoreAudio in hog/exclusive mode:
    • Selecting 'mtc+' (0x6d74632b) or 'mtct' (0x6d746374) at 768000 Hz (2 ch, 16-bit) immediately triggers lossless Dolby TrueHD + Dolby Atmos on the AVR/Soundbar!

2. Proposed Patch for mpv

A. audio/out/ao_coreaudio_utils.c

Recognize the 192 kHz (cc+3, cd+3, cec3) and 768 kHz (mtc+, mtct) compressed FormatIDs and select the appropriate mFormatID in ca_fill_asbd() based on ao->samplerate:

bool ca_formatid_is_compressed(UInt32 formatid)
{
    switch (formatid) {
    case 'cac3':
    case 'ac-3':
    case 'iac3':
    case 'IAC3':
    case 'cc+3':
    case 'cd+3':
    case 'cec3':
    case 'mtc+':
    case 'mtct':
        return true;
    }
    return false;
}

And in ca_fill_asbd(struct ao *ao, AudioStreamBasicDescription *asbd):

    asbd->mSampleRate       = ao->samplerate;
    if (af_fmt_is_spdif(ao->format)) {
        if (ao->samplerate > 192000) {
            asbd->mFormatID = 'mtc+'; // 768 kHz TrueHD / MAT + Atmos
        } else if (ao->samplerate > 48000) {
            asbd->mFormatID = 'cc+3'; // 192 kHz E-AC-3 + Atmos
        } else {
            asbd->mFormatID = kAudioFormat60958AC3; // 48 kHz AC-3 / DTS ('cac3')
        }
    } else {
        asbd->mFormatID = kAudioFormatLinearPCM;
    }

(Note: ca_asbd_equals() should only normalize mFormatID when both descriptions share the same mSampleRate, or ca_find_best_asbd() can fall back across 'cc+3' -> 'cd+3' -> 'cec3' at 192 kHz and 'mtc+' -> 'mtct' at 768 kHz if a specific sink only advertises one variant).

B. audio/decode/ad_spdif.c

On macOS (__APPLE__), IEC 61937 HBR streams (AV_CODEC_ID_TRUEHD and AV_CODEC_ID_DTS HD-MA) must be exposed as 2 channels @ 768000 Hz (sstride = 4, 15360 frames * 4 bytes = 61440 bytes/packet) rather than 8 channels @ 192000 Hz, so that ao_coreaudio_exclusive matches CoreAudio's 768000 Hz 2ch physical stream format (mtc+ / mtct):

    case AV_CODEC_ID_TRUEHD:
#ifdef __APPLE__
        num_channels = 2;
        samplerate   = 768000;
#else
        num_channels = 8;
        samplerate   = 192000;
#endif
        sformat      = AF_FORMAT_S_TRUEHD;
        break;

3. Verification

Tested on macOS (Apple Silicon) with:

  1. E-AC-3 7.1 + Dolby Atmos JOC (Dolby ATMOS Helicopter.m2ts https://drive.google.com/file/d/0BwxFVkl63-lENElIcC1xTnF2Yk0/view?usp=sharing&resourcekey=0-1_ByUhiruAwxfSNqW4ryAQ Track 3) -> Soundbar switches to Dolby Atmos via 'cc+3' (192 kHz).
  2. Dolby TrueHD 7.1 + Dolby Atmos (Dolby ATMOS Helicopter.m2ts Track 1) -> Soundbar switches to Dolby Atmos (TrueHD) via 'mtc+' / 'mtct' (768 kHz).
  3. AC-3 5.1 (Dolby ATMOS Helicopter.m2ts Track 2) -> Soundbar switches to Dolby Digital via 'cac3' (48 kHz).

Sample Files

output.txt

here the atmos file

I carefully read all instruction and confirm that I did the following:

  • I tested and confirmed that the issue exists with the latest release version or newer.
  • I provided all required information including system and mpv version.
  • I produced the log file with the exact same set of files, parameters, and conditions used in "Reproduction Steps", with the addition of --log-file=output.txt.
  • I produced the log file while the behaviors described in "Actual Behavior" were actively observed.
  • I attached the full, untruncated log file.
  • I attached the backtrace in the case of a crash.

Activity

  1. added theissue type on Nov 8, 2026
  2. ric-dicle commented on Nov 9, 2026

    @ric-dicle
    Author

    Proposed Pull Request: Native macOS HDMI/eARC Bitstream Passthrough for Dolby Atmos (TrueHD & E-AC-3) and E-AC-3 5.1 (ao_coreaudio_exclusive)

    Motivation & Problem Statement

    Currently, ao_coreaudio_exclusive hardcodes all S/PDIF formats to kAudioFormat60958AC3 ('cac3' @ 48 kHz). As a result:

    1. Dolby TrueHD + Dolby Atmos fails or falls back to multi-channel LPCM (losing all spatial 3D height objects).
    2. Dolby Digital Plus (E-AC-3) streams cannot negotiate the higher-bandwidth IEC 61937 descriptors exposed by macOS CoreAudio on HDMI/eARC devices ('cc+3' / 'cec3').
    3. Software multi-channel LPCM fallback causes subwoofer/bass management loss on many eARC soundbars (e.g. Samsung, LG, Sonos), which require genuine Dolby bitstream to apply the standardized +10 dB LFE channel gain.

    Updated Git Diff (against master)

    diff --git a/audio/decode/ad_spdif.c b/audio/decode/ad_spdif.c
    index 0bce4c6..e169e5e 100644
    --- a/audio/decode/ad_spdif.c
    +++ b/audio/decode/ad_spdif.c
    @@ -316,8 +316,13 @@ static int init_filter(struct mp_filter *da)
             break;
         case AV_CODEC_ID_TRUEHD:
             sample_format                   = AF_FORMAT_S_TRUEHD;
    +#ifdef __APPLE__
    +        // macOS CoreAudio exposes TrueHD MAT 2.0 as 2 ch @ 768000 Hz ('mtc+' / 'mtct')
    +        // matching the 61,440 bytes/packet IEC 61937 descriptor (15,360 frames @ 4 B/frame).
    +        samplerate                      = 768000;
    +        num_channels                    = 2;
    +#else
             samplerate                      = 192000;
             num_channels                    = 8;
    +#endif
             break;
         default:
             abort();
    diff --git a/audio/out/ao_coreaudio_utils.c b/audio/out/ao_coreaudio_utils.c
    index 8ff76a8..8ef0bd5 100644
    --- a/audio/out/ao_coreaudio_utils.c
    +++ b/audio/out/ao_coreaudio_utils.c
    @@ -148,10 +148,20 @@ static void ca_fill_asbd_raw(AudioStreamBasicDescription *asbd, int mp_format,
                                  int samplerate, int num_channels)
     {
         asbd->mSampleRate       = samplerate;
    -    // Set "AC3" for other spdif formats too - unknown if that works.
    -    asbd->mFormatID         = af_fmt_is_spdif(mp_format) ?
    -                              kAudioFormat60958AC3 :
    -                              kAudioFormatLinearPCM;
    +    if (af_fmt_is_spdif(mp_format)) {
    +        if (samplerate > 192000) {
    +            // 768 kHz TrueHD / MAT 2.0 + Dolby Atmos
    +            asbd->mFormatID = 'mtc+';
    +        } else if (samplerate > 48000) {
    +            // 192 kHz Dolby Digital Plus (E-AC-3)
    +            // Note: 'cc+3' is used for E-AC-3 + Atmos (JOC), while 'cec3'
    +            // represents standard E-AC-3 without spatial metadata.
    +            asbd->mFormatID = (mp_format == AF_FORMAT_S_EAC3_ATMOS) ? 'cc+3' : 'cec3';
    +        } else {
    +            // 48 kHz standard AC-3 / DTS ('cac3')
    +            asbd->mFormatID = kAudioFormat60958AC3;
    +        }
    +    } else {
    +        asbd->mFormatID     = kAudioFormatLinearPCM;
    +    }
         asbd->mChannelsPerFrame = num_channels;
         asbd->mBitsPerChannel   = af_fmt_to_bytes(mp_format) * 8;
         asbd->mFormatFlags      = kAudioFormatFlagIsPacked;
    @@ -184,19 +194,40 @@ void ca_fill_asbd(struct ao *ao, AudioStreamBasicDescription *asbd)
     
     bool ca_formatid_is_compressed(uint32_t formatid)
     {
    -    switch (formatid)
    +    switch (formatid) {
         case 'IAC3':
         case 'iac3':
         case  kAudioFormat60958AC3:
         case  kAudioFormatAC3:
    +    case 'cc+3': // E-AC-3 + Dolby Atmos
    +    case 'cd+3': // E-AC-3 + Dolby Atmos alternate
    +    case 'cec3': // E-AC-3 standard
    +    case 'mtc+': // TrueHD + Dolby Atmos
    +    case 'mtct': // TrueHD standard
             return true;
    +    }
         return false;
     }
     
    -// Group compatible formats together for matching
     static uint32_t ca_normalize_formatid(uint32_t formatID)
     {
    -    return ca_formatid_is_compressed(formatID) ? kAudioFormat60958AC3 : formatID;
    +    switch (formatID) {
    +    case 'IAC3':
    +    case 'iac3':
    +    case kAudioFormat60958AC3:
    +    case kAudioFormatAC3:
    +        return kAudioFormat60958AC3;
    +    case 'cc+3':
    +    case 'cd+3':
    +        return 'cc+3';
    +    case 'cec3':
    +        return 'cec3';
    +    case 'mtc+':
    +    case 'mtct':
    +        return 'mtc+';
    +    default:
    +        return formatID;
    +    }
     }
     
     bool ca_asbd_equals(const AudioStreamBasicDescription *a,

    Detailed Technical Notes & Hardware Test Observations

    1. TrueHD MAT 2.0 on Apple Silicon (768 kHz 2ch)

    • CoreAudio Layout: macOS CoreAudio does not expose the Linux/Windows 8-channel @ 192 kHz HDMI layout for TrueHD. Instead, it exposes TrueHD as 2 channels @ 768000 Hz ('mtc+' / 'mtct'), with a packet size of 61,440 bytes (15,360 frames/packet, 4 bytes/frame).
    • Verification: Tested live on Apple Silicon (M3 Max) over HDMI 2.1 eARC into modern soundbars/receivers: bitstreaming TrueHD with this descriptor triggers native DOLBY ATMOS decoding reliably.

    2. E-AC-3 Atmos ('cc+3') vs Plain E-AC-3 5.1 ('cec3')

    • The Handshake Conflict: In CoreAudio, 'cc+3' explicitly announces spatial audio (Dolby Atmos JOC).
    • The Bug Observed: If 'cc+3' is unconditionally requested for standard E-AC-3 5.1 streams (lacking JOC metadata), the receiver/soundbar enters Atmos decoding mode, fails to locate the Atmos syncword in incoming frames, and periodically resets its input buffer (causing severe audio stuttering / continuous cut-offs every 200–500 ms, or playing bursts as raw static noise).
    • The Fix: Distinguishing between 'cc+3' (Atmos) and 'cec3' (standard E-AC-3) allows receivers to decode native Dolby Digital Plus 5.1 without glitching.

    3. Real-Time AC-3 5.1 Encoding Fallback (lavcac3enc) & Subwoofer LFE

    • Why Passthrough Matters for Subwoofers: Decoding multi-channel audio to software LPCM on macOS often results in muted, weak, or misrouted subwoofer bass because many consumer soundbars bypass their internal Dolby LFE (+10 dB) crossover matrix when fed uncompressed PCM.
    • Universal Robustness: When passing through legacy multi-channel audio, pairing audio-spdif=ac3,dts,dts-hd,truehd with af=lavcac3enc=yes:640:3 guarantees that any non-Atmos 5.1 stream is cleanly framed as studio-quality 640 kbps AC-3 (kAudioFormat60958AC3 @ 48 kHz 'cac3'), ensuring the soundbar's hardware Dolby decoder extracts full discrete LFE bass with zero jitter.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions