1
mirror of https://github.com/mpv-player/mpv synced 2024-11-14 22:48:35 +01:00

ao_coreaudio: set channel layout based on hardware query

this is a wip
This commit is contained in:
Stefano Pigozzi 2013-07-08 22:58:01 +02:00
parent 9652245ef0
commit c2de6fdf34

View File

@ -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;