From c11c744998a28d582ec9d6139f2bf6c927000e3a Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Wed, 10 Jul 2013 19:24:28 +0200 Subject: ao_coreaudio: refactor chmap detection b2f9e0610 introduced this functionality with code that was quite 'monolithic'. Split the functionality over several functions and ose the new macros to get array properties. --- audio/out/ao_coreaudio.c | 99 +++++------------------------------------- audio/out/ao_coreaudio_utils.c | 81 ++++++++++++++++++++++++++++++++++ audio/out/ao_coreaudio_utils.h | 7 +-- 3 files changed, 96 insertions(+), 91 deletions(-) (limited to 'audio/out') diff --git a/audio/out/ao_coreaudio.c b/audio/out/ao_coreaudio.c index 48fc3a4779..ee0a042d2a 100644 --- a/audio/out/ao_coreaudio.c +++ b/audio/out/ao_coreaudio.c @@ -306,96 +306,18 @@ 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); + AudioChannelLayout *layouts; + size_t n_layouts; + err = CA_GET_ARY_O(selected_device, + kAudioDevicePropertyPreferredChannelLayout, + &layouts, &n_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; + uint32_t *bitmaps; + size_t n_bitmaps; - 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 + ca_bitmaps_from_layouts(layouts, n_layouts, &bitmaps, &n_bitmaps); + free(layouts); struct mp_chmap_sel chmap_sel = {0}; @@ -405,6 +327,8 @@ static int init(struct ao *ao, char *params) mp_chmap_sel_add_map(&chmap_sel, &chmap); } + talloc_free(bitmaps); + if (ao->channels.num < 3 || n_bitmaps < 1) // If the input is not surround or we could not get any usable // bitmap from the hardware, default to waveext... @@ -413,7 +337,6 @@ static int init(struct ao *ao, char *params) 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 diff --git a/audio/out/ao_coreaudio_utils.c b/audio/out/ao_coreaudio_utils.c index 221aeb4ddb..195d285b3e 100644 --- a/audio/out/ao_coreaudio_utils.c +++ b/audio/out/ao_coreaudio_utils.c @@ -340,3 +340,84 @@ bool ca_change_format(AudioStreamID stream, return format_set; } + +void ca_bitmaps_from_layouts(AudioChannelLayout *layouts, size_t n_layouts, + uint32_t **bitmaps, size_t *n_bitmaps) +{ + *n_bitmaps = 0; + *bitmaps = talloc_array_size(NULL, sizeof(uint32_t), n_layouts); + + for (int i=0; i < n_layouts; i++) { + uint32_t bitmap = 0; + + switch (layouts[i].mChannelLayoutTag) { + case kAudioChannelLayoutTag_UseChannelBitmap: + (*bitmaps)[(*n_bitmaps)++] = layouts[i].mChannelBitmap; + break; + + case kAudioChannelLayoutTag_UseChannelDescriptions: + if (ca_bitmap_from_ch_desc(&layouts[i], &bitmap)) + (*bitmaps)[(*n_bitmaps)++] = bitmap; + break; + + default: + if (ca_bitmap_from_ch_tag(&layouts[i], &bitmap)) + (*bitmaps)[(*n_bitmaps)++] = bitmap; + } + } +} + +bool ca_bitmap_from_ch_desc(AudioChannelLayout *layout, uint32_t *bitmap) +{ + // 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. + size_t ch_num = layout->mNumberChannelDescriptions; + bool all_channels_valid = true; + + for (int j=0; j < ch_num && all_channels_valid; j++) { + AudioChannelLabel label = layout->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); + } + } + + return all_channels_valid; +} + +bool ca_bitmap_from_ch_tag(AudioChannelLayout *layout, uint32_t *bitmap) +{ + // 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_size = sizeof(uint32_t); + + AudioChannelLayoutTag tag = layout->mChannelLayoutTag; + OSStatus 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); + return false; + } else { + return true; + } +} diff --git a/audio/out/ao_coreaudio_utils.h b/audio/out/ao_coreaudio_utils.h index b7f261088b..78e524fbd8 100644 --- a/audio/out/ao_coreaudio_utils.h +++ b/audio/out/ao_coreaudio_utils.h @@ -70,8 +70,9 @@ OSStatus ca_disable_device_listener(AudioDeviceID device, void *flag); bool ca_change_format(AudioStreamID stream, AudioStreamBasicDescription change_format); -bool ca_bitmap_from_ch_descriptions(AudioChannelLayout layout, - uint32_t *bitmap); -bool ca_bitmap_from_ch_tag(AudioChannelLayout layout, uint32_t *bitmap); +bool ca_bitmap_from_ch_desc(AudioChannelLayout *layout, uint32_t *bitmap); +bool ca_bitmap_from_ch_tag(AudioChannelLayout *layout, uint32_t *bitmap); +void ca_bitmaps_from_layouts(AudioChannelLayout *layouts, size_t n_layouts, + uint32_t **bitmaps, size_t *n_bitmaps); #endif /* MPV_COREAUDIO_UTILS_H */ -- cgit v1.2.3