This fixes #15584
Unified · Split
| @@ -277,22 +277,8 @@ static int init(struct ao *ao) · 276 unmodified lines | |||
| 277 | 277 | ||
| 278 | AudioStreamBasicDescription asbd; | 278 | AudioStreamBasicDescription asbd; |
| 279 | ca_fill_asbd(ao, &asbd); | 279 | ca_fill_asbd(ao, &asbd); |
| 280 | size_t layout_size = sizeof(AudioChannelLayout) | 280 | size_t layout_size; |
| 281 | + (ao->channels.num - 1) * sizeof(AudioChannelDescription); | 281 | layout = ca_get_acl(ao, &layout_size); |
| 282 | layout = talloc_size(ao, layout_size); | ||
| 283 | layout->mChannelLayoutTag = kAudioChannelLayoutTag_UseChannelDescriptions; | ||
| 284 | layout->mNumberChannelDescriptions = ao->channels.num; | ||
| 285 | for (int i = 0; i < ao->channels.num; ++i) { | ||
| 286 | AudioChannelDescription *desc = layout->mChannelDescriptions + i; | ||
| 287 | desc->mChannelFlags = kAudioChannelFlags_AllOff; | ||
| 288 | desc->mChannelLabel = mp_speaker_id_to_ca_label(ao->channels.speaker[i]); | ||
| 289 | } | ||
| 290 | |||
| 291 | void *talloc_ctx = talloc_new(NULL); | ||
| 292 | AudioChannelLayout *std_layout = ca_find_standard_layout(talloc_ctx, layout); | ||
| 293 | memmove(layout, std_layout, sizeof(AudioChannelLayout)); | ||
| 294 | talloc_free(talloc_ctx); | ||
| 295 | ca_log_layout(ao, MSGL_V, layout); | ||
| 296 | 282 | ||
| 297 | OSStatus err; | 283 | OSStatus err; |
| 298 | if ((err = CMAudioFormatDescriptionCreate( | 284 | if ((err = CMAudioFormatDescriptionCreate( |
| @@ -136,7 +136,7 @@ static int control(struct ao *ao, enum aocontrol cmd, void *arg) · 135 unmodified lines | |||
| 136 | return CONTROL_UNKNOWN; | 136 | return CONTROL_UNKNOWN; |
| 137 | } | 137 | } |
| 138 | 138 | ||
| 139 | static bool init_audiounit(struct ao *ao, AudioStreamBasicDescription asbd); | 139 | static bool init_audiounit(struct ao *ao, AudioStreamBasicDescription asbd, AudioChannelLayout *layout, size_t layout_size); |
| 140 | static void init_physical_format(struct ao *ao); | 140 | static void init_physical_format(struct ao *ao); |
| 141 | static void reinit_latency(struct ao *ao); | 141 | static void reinit_latency(struct ao *ao); |
| 142 | static bool register_hotplug_cb(struct ao *ao); | 142 | static bool register_hotplug_cb(struct ao *ao); |
| @@ -178,8 +178,13 @@ static int init(struct ao *ao) · 35 unmodified lines | |||
| 178 | 178 | ||
| 179 | AudioStreamBasicDescription asbd; | 179 | AudioStreamBasicDescription asbd; |
| 180 | ca_fill_asbd(ao, &asbd); | 180 | ca_fill_asbd(ao, &asbd); |
| 181 | size_t layout_size; | ||
| 182 | AudioChannelLayout *layout = ca_get_acl(ao, &layout_size); | ||
| 181 | 183 | ||
| 182 | if (!init_audiounit(ao, asbd)) | 184 | bool r = init_audiounit(ao, asbd, layout, layout_size); |
| 185 | talloc_free(layout); | ||
| 186 | |||
| 187 | if (!r) | ||
| 183 | goto coreaudio_error; | 188 | goto coreaudio_error; |
| 184 | 189 | ||
| 185 | reinit_latency(ao); | 190 | reinit_latency(ao); |
| @@ -273,7 +278,7 @@ coreaudio_error: · 87 unmodified lines | |||
| 273 | return; | 278 | return; |
| 274 | } | 279 | } |
| 275 | 280 | ||
| 276 | static bool init_audiounit(struct ao *ao, AudioStreamBasicDescription asbd) | 281 | static bool init_audiounit(struct ao *ao, AudioStreamBasicDescription asbd, AudioChannelLayout *layout, size_t layout_size) |
| 277 | { | 282 | { |
| 278 | OSStatus err; | 283 | OSStatus err; |
| 279 | uint32_t size; | 284 | uint32_t size; |
| @@ -317,6 +322,13 @@ static bool init_audiounit(struct ao *ao, AudioStreamBasicDescription asbd) · 37 unmodified lines | |||
| 317 | CHECK_CA_ERROR_L(coreaudio_error_audiounit, | 322 | CHECK_CA_ERROR_L(coreaudio_error_audiounit, |
| 318 | "can't link audio unit to selected device"); | 323 | "can't link audio unit to selected device"); |
| 319 | 324 | ||
| 325 | err = AudioUnitSetProperty(p->audio_unit, | ||
| 326 | kAudioOutputUnitProperty_ChannelMap, | ||
| 327 | kAudioUnitScope_Global, 0, layout, layout_size); | ||
| 328 | |||
| 329 | CHECK_CA_ERROR_L(coreaudio_error_audiounit, | ||
| 330 | "unable to set the input channel layout on the audio unit"); | ||
| 331 | |||
| 320 | AURenderCallbackStruct render_cb = (AURenderCallbackStruct) { | 332 | AURenderCallbackStruct render_cb = (AURenderCallbackStruct) { |
| 321 | .inputProc = render_cb_lpcm, | 333 | .inputProc = render_cb_lpcm, |
| 322 | .inputProcRefCon = ao, | 334 | .inputProcRefCon = ao, |
| @@ -314,6 +314,30 @@ mismatch:; · 313 unmodified lines | |||
| 314 | return s ? s : l; | 314 | return s ? s : l; |
| 315 | } | 315 | } |
| 316 | 316 | ||
| 317 | AudioChannelLayout *ca_get_acl(struct ao *ao, size_t *out_layout_size) | ||
| 318 | { | ||
| 319 | size_t layout_size = sizeof(AudioChannelLayout) | ||
| 320 | + (ao->channels.num - 1) * sizeof(AudioChannelDescription); | ||
| 321 | AudioChannelLayout *layout = talloc_size(ao, layout_size); | ||
| 322 | layout->mChannelLayoutTag = kAudioChannelLayoutTag_UseChannelDescriptions; | ||
| 323 | layout->mNumberChannelDescriptions = ao->channels.num; | ||
| 324 | for (int i = 0; i < ao->channels.num; ++i) { | ||
| 325 | AudioChannelDescription *desc = layout->mChannelDescriptions + i; | ||
| 326 | desc->mChannelFlags = kAudioChannelFlags_AllOff; | ||
| 327 | desc->mChannelLabel = mp_speaker_id_to_ca_label(ao->channels.speaker[i]); | ||
| 328 | } | ||
| 329 | |||
| 330 | void *talloc_ctx = talloc_new(NULL); | ||
| 331 | AudioChannelLayout *std_layout = ca_find_standard_layout(talloc_ctx, layout); | ||
| 332 | memmove(layout, std_layout, sizeof(AudioChannelLayout)); | ||
| 333 | talloc_free(talloc_ctx); | ||
| 334 | ca_log_layout(ao, MSGL_V, layout); | ||
| 335 | |||
| 336 | if (out_layout_size) | ||
| 337 | *out_layout_size = layout_size; | ||
| 338 | return layout; | ||
| 339 | } | ||
| 340 | |||
| 317 | 341 | ||
| 318 | #define CHMAP(n, ...) &(struct mp_chmap) MP_CONCAT(MP_CHMAP, n) (__VA_ARGS__) | 342 | #define CHMAP(n, ...) &(struct mp_chmap) MP_CONCAT(MP_CHMAP, n) (__VA_ARGS__) |
| 319 | 343 | ||
| @@ -28,6 +28,7 @@ AudioChannelLabel mp_speaker_id_to_ca_label(int speaker_id); · 27 unmodified lines | |||
| 28 | 28 | ||
| 29 | #if HAVE_COREAUDIO || HAVE_AVFOUNDATION | 29 | #if HAVE_COREAUDIO || HAVE_AVFOUNDATION |
| 30 | AudioChannelLayout *ca_find_standard_layout(void *talloc_ctx, AudioChannelLayout *l); | 30 | AudioChannelLayout *ca_find_standard_layout(void *talloc_ctx, AudioChannelLayout *l); |
| 31 | AudioChannelLayout *ca_get_acl(struct ao *ao, size_t *out_layout_size); | ||
| 31 | void ca_log_layout(struct ao *ao, int l, AudioChannelLayout *layout); | 32 | void ca_log_layout(struct ao *ao, int l, AudioChannelLayout *layout); |
| 32 | bool ca_init_chmap(struct ao *ao, AudioDeviceID device); | 33 | bool ca_init_chmap(struct ao *ao, AudioDeviceID device); |
| 33 | void ca_get_active_chmap(struct ao *ao, AudioDeviceID device, int channel_count, | 34 | void ca_get_active_chmap(struct ao *ao, AudioDeviceID device, int channel_count, |