This fixes #15584
Unified · Split
| @@ -277,22 +277,8 @@ static int init(struct ao *ao) · 276 unmodified lines | ||
| 277 | 277 | |
| 278 | 278 | AudioStreamBasicDescription asbd; |
| 279 | 279 | ca_fill_asbd(ao, &asbd); |
| 280 | − size_t layout_size = sizeof(AudioChannelLayout) | |
| 281 | − + (ao->channels.num - 1) * sizeof(AudioChannelDescription); | |
| 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); | |
| 280 | + size_t layout_size; | |
| 281 | + layout = ca_get_acl(ao, &layout_size); | |
| 296 | 282 | |
| 297 | 283 | OSStatus err; |
| 298 | 284 | if ((err = CMAudioFormatDescriptionCreate( |
| @@ -136,7 +136,7 @@ static int control(struct ao *ao, enum aocontrol cmd, void *arg) · 135 unmodified lines | ||
| 136 | 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 | 140 | static void init_physical_format(struct ao *ao); |
| 141 | 141 | static void reinit_latency(struct ao *ao); |
| 142 | 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 | 179 | AudioStreamBasicDescription asbd; |
| 180 | 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 | 188 | goto coreaudio_error; |
| 184 | 189 | |
| 185 | 190 | reinit_latency(ao); |
| @@ -273,7 +278,7 @@ coreaudio_error: · 87 unmodified lines | ||
| 273 | 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 | 283 | OSStatus err; |
| 279 | 284 | uint32_t size; |
| @@ -317,6 +322,13 @@ static bool init_audiounit(struct ao *ao, AudioStreamBasicDescription asbd) · 37 unmodified lines | ||
| 317 | 322 | CHECK_CA_ERROR_L(coreaudio_error_audiounit, |
| 318 | 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 | 332 | AURenderCallbackStruct render_cb = (AURenderCallbackStruct) { |
| 321 | 333 | .inputProc = render_cb_lpcm, |
| 322 | 334 | .inputProcRefCon = ao, |
| @@ -314,6 +314,30 @@ mismatch:; · 313 unmodified lines | ||
| 314 | 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 | 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 | 29 | #if HAVE_COREAUDIO || HAVE_AVFOUNDATION |
| 30 | 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 | 32 | void ca_log_layout(struct ao *ao, int l, AudioChannelLayout *layout); |
| 32 | 33 | bool ca_init_chmap(struct ao *ao, AudioDeviceID device); |
| 33 | 34 | void ca_get_active_chmap(struct ao *ao, AudioDeviceID device, int channel_count, |