summaryrefslogtreecommitdiffstats
path: root/audio/out/ao_coreaudio_utils.c
diff options
context:
space:
mode:
Diffstat (limited to 'audio/out/ao_coreaudio_utils.c')
-rw-r--r--audio/out/ao_coreaudio_utils.c81
1 files changed, 81 insertions, 0 deletions
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;
+ }
+}