diff --git a/audio/out/ao_avfoundation.m b/audio/out/ao_avfoundation.m index 94731a7670..f7f8aa6c43 100644 --- a/audio/out/ao_avfoundation.m +++ b/audio/out/ao_avfoundation.m @@ -277,22 +277,8 @@ static int init(struct ao *ao) AudioStreamBasicDescription asbd; ca_fill_asbd(ao, &asbd); - size_t layout_size = sizeof(AudioChannelLayout) - + (ao->channels.num - 1) * sizeof(AudioChannelDescription); - layout = talloc_size(ao, layout_size); - layout->mChannelLayoutTag = kAudioChannelLayoutTag_UseChannelDescriptions; - layout->mNumberChannelDescriptions = ao->channels.num; - for (int i = 0; i < ao->channels.num; ++i) { - AudioChannelDescription *desc = layout->mChannelDescriptions + i; - desc->mChannelFlags = kAudioChannelFlags_AllOff; - desc->mChannelLabel = mp_speaker_id_to_ca_label(ao->channels.speaker[i]); - } - - void *talloc_ctx = talloc_new(NULL); - AudioChannelLayout *std_layout = ca_find_standard_layout(talloc_ctx, layout); - memmove(layout, std_layout, sizeof(AudioChannelLayout)); - talloc_free(talloc_ctx); - ca_log_layout(ao, MSGL_V, layout); + size_t layout_size; + layout = ca_get_acl(ao, &layout_size); OSStatus err; if ((err = CMAudioFormatDescriptionCreate( diff --git a/audio/out/ao_coreaudio.c b/audio/out/ao_coreaudio.c index 14a04e6f99..0f5fff8005 100644 --- a/audio/out/ao_coreaudio.c +++ b/audio/out/ao_coreaudio.c @@ -136,7 +136,7 @@ static int control(struct ao *ao, enum aocontrol cmd, void *arg) return CONTROL_UNKNOWN; } -static bool init_audiounit(struct ao *ao, AudioStreamBasicDescription asbd); +static bool init_audiounit(struct ao *ao, AudioStreamBasicDescription asbd, AudioChannelLayout *layout, size_t layout_size); static void init_physical_format(struct ao *ao); static void reinit_latency(struct ao *ao); static bool register_hotplug_cb(struct ao *ao); @@ -178,8 +178,13 @@ static int init(struct ao *ao) AudioStreamBasicDescription asbd; ca_fill_asbd(ao, &asbd); + size_t layout_size; + AudioChannelLayout *layout = ca_get_acl(ao, &layout_size); - if (!init_audiounit(ao, asbd)) + bool r = init_audiounit(ao, asbd, layout, layout_size); + talloc_free(layout); + + if (!r) goto coreaudio_error; reinit_latency(ao); @@ -273,7 +278,7 @@ coreaudio_error: return; } -static bool init_audiounit(struct ao *ao, AudioStreamBasicDescription asbd) +static bool init_audiounit(struct ao *ao, AudioStreamBasicDescription asbd, AudioChannelLayout *layout, size_t layout_size) { OSStatus err; uint32_t size; @@ -317,6 +322,13 @@ static bool init_audiounit(struct ao *ao, AudioStreamBasicDescription asbd) CHECK_CA_ERROR_L(coreaudio_error_audiounit, "can't link audio unit to selected device"); + err = AudioUnitSetProperty(p->audio_unit, + kAudioOutputUnitProperty_ChannelMap, + kAudioUnitScope_Global, 0, layout, layout_size); + + CHECK_CA_ERROR_L(coreaudio_error_audiounit, + "unable to set the input channel layout on the audio unit"); + AURenderCallbackStruct render_cb = (AURenderCallbackStruct) { .inputProc = render_cb_lpcm, .inputProcRefCon = ao, diff --git a/audio/out/ao_coreaudio_chmap.c b/audio/out/ao_coreaudio_chmap.c index 93c5402c74..55e738382a 100644 --- a/audio/out/ao_coreaudio_chmap.c +++ b/audio/out/ao_coreaudio_chmap.c @@ -314,6 +314,30 @@ mismatch:; return s ? s : l; } +AudioChannelLayout *ca_get_acl(struct ao *ao, size_t *out_layout_size) +{ + size_t layout_size = sizeof(AudioChannelLayout) + + (ao->channels.num - 1) * sizeof(AudioChannelDescription); + AudioChannelLayout *layout = talloc_size(ao, layout_size); + layout->mChannelLayoutTag = kAudioChannelLayoutTag_UseChannelDescriptions; + layout->mNumberChannelDescriptions = ao->channels.num; + for (int i = 0; i < ao->channels.num; ++i) { + AudioChannelDescription *desc = layout->mChannelDescriptions + i; + desc->mChannelFlags = kAudioChannelFlags_AllOff; + desc->mChannelLabel = mp_speaker_id_to_ca_label(ao->channels.speaker[i]); + } + + void *talloc_ctx = talloc_new(NULL); + AudioChannelLayout *std_layout = ca_find_standard_layout(talloc_ctx, layout); + memmove(layout, std_layout, sizeof(AudioChannelLayout)); + talloc_free(talloc_ctx); + ca_log_layout(ao, MSGL_V, layout); + + if (out_layout_size) + *out_layout_size = layout_size; + return layout; +} + #define CHMAP(n, ...) &(struct mp_chmap) MP_CONCAT(MP_CHMAP, n) (__VA_ARGS__) diff --git a/audio/out/ao_coreaudio_chmap.h b/audio/out/ao_coreaudio_chmap.h index 5286f98e63..d8bdc59749 100644 --- a/audio/out/ao_coreaudio_chmap.h +++ b/audio/out/ao_coreaudio_chmap.h @@ -28,6 +28,7 @@ AudioChannelLabel mp_speaker_id_to_ca_label(int speaker_id); #if HAVE_COREAUDIO || HAVE_AVFOUNDATION AudioChannelLayout *ca_find_standard_layout(void *talloc_ctx, AudioChannelLayout *l); +AudioChannelLayout *ca_get_acl(struct ao *ao, size_t *out_layout_size); void ca_log_layout(struct ao *ao, int l, AudioChannelLayout *layout); bool ca_init_chmap(struct ao *ao, AudioDeviceID device); void ca_get_active_chmap(struct ao *ao, AudioDeviceID device, int channel_count,