From c2de6fdf345b72a0f69f9b4b9618599a7287c2c8 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Mon, 8 Jul 2013 22:58:01 +0200 Subject: ao_coreaudio: set channel layout based on hardware query this is a wip --- audio/out/ao_coreaudio.c | 108 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 106 insertions(+), 2 deletions(-) (limited to 'audio') diff --git a/audio/out/ao_coreaudio.c b/audio/out/ao_coreaudio.c index 65e51bce7d..6c1cdb9150 100644 --- a/audio/out/ao_coreaudio.c +++ b/audio/out/ao_coreaudio.c @@ -313,11 +313,115 @@ static int init(struct ao *ao, char *params) } if (!supports_digital) { + uint32_t size; + AudioObjectPropertyAddress p_addr = (AudioObjectPropertyAddress) { + .mSelector = kAudioDevicePropertyPreferredChannelLayout, + .mScope = kAudioDevicePropertyScopeOutput, + .mElement = kAudioObjectPropertyElementMaster, + }; + + err = AudioObjectGetPropertyDataSize(selected_device, &p_addr, 0, NULL, + &size); + CHECK_CA_ERROR("could not get audio device prefered layouts size"); + size_t n_layouts = size / sizeof(AudioChannelLayout); + + AudioChannelLayout *layouts = (AudioChannelLayout *) malloc(size); + err = AudioObjectGetPropertyData(selected_device, &p_addr, 0, NULL, + &size, layouts); + CHECK_CA_ERROR("could not get audio device prefered layouts"); + + uint32_t bitmaps[n_layouts]; + size_t n_bitmaps = 0; + + for (int i=0; i < n_layouts; i++) { + ca_msg(MSGL_WARN, "channel layout %d:\n", i); + + switch (layouts[i].mChannelLayoutTag) { + case kAudioChannelLayoutTag_UseChannelBitmap: + // This is the best case. CoreAudio's representation of the + // layout is the same of what mpv uses internally. + ca_msg(MSGL_WARN, "channel layout !\n"); + bitmaps[n_bitmaps++] = layouts[i].mChannelBitmap; + case kAudioChannelLayoutTag_UseChannelDescriptions: { + // If the channel layout uses channel descriptions, from my + // exepriments there are there three possibile cases: + // * The description has a label kAudioChannelLabel_Unknown: + // Can't do anything about this (looks like non surround + // layouts are like this). + // * The description uses positional information: this in + // theory could be used but one would have to map spatial + // positions to labels which is not really feasible. + // * The description has a well known label which can be mapped + // to the waveextensible definition: this is the kind of + // descriptions we process here. + ca_msg(MSGL_WARN, "descriptions!\n"); + size_t ch_num = layouts[i].mNumberChannelDescriptions; + + uint32_t bitmap = 0; + bool all_channels_valid = true; + + for (int j=0; j < ch_num && all_channels_valid; j++) { + AudioChannelLabel label = + layouts[i].mChannelDescriptions[j].mChannelLabel; + + if (label == kAudioChannelLabel_UseCoordinates || + label == kAudioChannelLabel_Unknown || + label > kAudioChannelLabel_TopBackRight) { + ca_msg(MSGL_WARN, + "channel label=%d unusable to build channel " + "bitmap, skipping layout\n", label); + all_channels_valid = false; + } else { + bitmap |= 1ULL << (label - 1); + } + } + + if (all_channels_valid) + bitmaps[n_bitmaps++] = bitmap; + + break; + } + default: { + ca_msg(MSGL_WARN, "some tag!\n"); + // This layout is defined exclusively by it's tag. Use the Audio + // Format Services API to try and convert it to a bitmap that + // mpv can use. + uint32_t bitmap; + uint32_t bitmap_size = sizeof(uint32_t); + AudioChannelLayoutTag tag = layouts[i].mChannelLayoutTag; + err = AudioFormatGetProperty( + kAudioFormatProperty_BitmapForLayoutTag, + sizeof(AudioChannelLayoutTag), &tag, + &bitmap_size, &bitmap); + if (err != noErr) { + ca_msg(MSGL_WARN, + "channel layout tag=%d unusable to build channel " + "bitmap, skipping layout\n", tag); + } else { + bitmaps[n_bitmaps++] = bitmap; + } + } + } + } // closes for + struct mp_chmap_sel chmap_sel = {0}; - mp_chmap_sel_add_waveext(&chmap_sel); + + for (int i=0; i < n_bitmaps; i++) { + struct mp_chmap chmap = {0}; + mp_chmap_from_lavc(&chmap, bitmaps[i]); + mp_chmap_sel_add_map(&chmap_sel, &chmap); + } + + if (n_bitmaps < 1) + // Could not get from the hardware any usable bitmap, default to + // waveext... + mp_chmap_sel_add_waveext(&chmap_sel); + if (!ao_chmap_sel_adjust(ao, &chmap_sel, &ao->channels)) goto coreaudio_error; - } + + free(layouts); + } // closes if (!supports_digital) // Build ASBD for the input format AudioStreamBasicDescription asbd; -- cgit v1.2.3