summaryrefslogtreecommitdiffstats
path: root/audio/out/ao_coreaudio.c
diff options
context:
space:
mode:
authorStefano Pigozzi <stefano.pigozzi@gmail.com>2014-12-26 14:53:37 +0100
committerStefano Pigozzi <stefano.pigozzi@gmail.com>2014-12-26 15:04:36 +0100
commit9317071bc309dfe22cf3b295de20e18ae9b80c26 (patch)
treee69d22a3d07c2cad73f1f62d8e673111c6d705a1 /audio/out/ao_coreaudio.c
parentb164e8c2fef9da7d6749aaeecf0b755bf5b6bcaf (diff)
downloadmpv-9317071bc309dfe22cf3b295de20e18ae9b80c26.tar.bz2
mpv-9317071bc309dfe22cf3b295de20e18ae9b80c26.tar.xz
ao_coreaudio: fix AudioChannelLayout allocations
AudioChannelLayout uses a trailing variable sized array so we need to query CoreAudio for the size of the struct it is going to need (or the conversion of that particular layout would fail). Fixes #1366
Diffstat (limited to 'audio/out/ao_coreaudio.c')
-rw-r--r--audio/out/ao_coreaudio.c80
1 files changed, 46 insertions, 34 deletions
diff --git a/audio/out/ao_coreaudio.c b/audio/out/ao_coreaudio.c
index 7ccc2c212a..493979b462 100644
--- a/audio/out/ao_coreaudio.c
+++ b/audio/out/ao_coreaudio.c
@@ -373,52 +373,62 @@ static void ca_log_layout(struct ao *ao, AudioChannelLayout *layout)
}
}
-bool ca_layout_to_mp_chmap(struct ao *ao, AudioChannelLayout *layout,
- struct mp_chmap *chmap)
+static AudioChannelLayout *ca_layout_to_custom_layout(
+ struct ao *ao, void *talloc_ctx, AudioChannelLayout *l)
{
- AudioChannelLayoutTag tag = layout->mChannelLayoutTag;
- uint32_t layout_size = sizeof(layout);
+ AudioChannelLayoutTag tag = l->mChannelLayoutTag;
+ AudioChannelLayout *r;
OSStatus err;
if (tag == kAudioChannelLayoutTag_UseChannelBitmap) {
- err = AudioFormatGetProperty(kAudioFormatProperty_ChannelLayoutForBitmap,
- sizeof(uint32_t),
- &layout->mChannelBitmap,
- &layout_size,
- layout);
- CHECK_CA_ERROR("failed to convert channel bitmap to descriptions");
+ uint32_t psize;
+ err = AudioFormatGetPropertyInfo(
+ kAudioFormatProperty_ChannelLayoutForBitmap,
+ sizeof(uint32_t), &l->mChannelBitmap, &psize);
+ CHECK_CA_ERROR("failed to convert channel bitmap to descriptions (info)");
+ r = talloc_size(NULL, psize);
+ err = AudioFormatGetProperty(
+ kAudioFormatProperty_ChannelLayoutForBitmap,
+ sizeof(uint32_t), &l->mChannelBitmap, &psize, r);
+ CHECK_CA_ERROR("failed to convert channel bitmap to descriptions (get)");
} else if (tag != kAudioChannelLayoutTag_UseChannelDescriptions) {
- err = AudioFormatGetProperty(kAudioFormatProperty_ChannelLayoutForTag,
- sizeof(AudioChannelLayoutTag),
- &layout->mChannelLayoutTag,
- &layout_size,
- layout);
- CHECK_CA_ERROR("failed to convert channel tag to descriptions");
+ uint32_t psize;
+ err = AudioFormatGetPropertyInfo(
+ kAudioFormatProperty_ChannelLayoutForTag,
+ sizeof(AudioChannelLayoutTag), &l->mChannelLayoutTag, &psize);
+ r = talloc_size(NULL, psize);
+ CHECK_CA_ERROR("failed to convert channel tag to descriptions (info)");
+ err = AudioFormatGetProperty(
+ kAudioFormatProperty_ChannelLayoutForTag,
+ sizeof(AudioChannelLayoutTag), &l->mChannelLayoutTag, &psize, r);
+ CHECK_CA_ERROR("failed to convert channel tag to descriptions (get)");
+ } else {
+ r = l;
}
- ca_log_layout(ao, layout);
+ return r;
+coreaudio_error:
+ return NULL;
+}
+
+bool ca_layout_to_mp_chmap(struct ao *ao, AudioChannelLayout *layout,
+ struct mp_chmap *chmap)
+{
+ void *talloc_ctx = talloc_new(NULL);
+ AudioChannelLayout *l = ca_layout_to_custom_layout(ao, talloc_ctx, layout);
+ if (!l)
+ goto coreaudio_error;
+
+ ca_log_layout(ao, l);
- // If the channel layout uses channel descriptions, from my
- // experiments 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.
-
- if (layout->mNumberChannelDescriptions > MP_NUM_CHANNELS) {
+ if (l->mNumberChannelDescriptions > MP_NUM_CHANNELS) {
MP_VERBOSE(ao, "layout has too many descriptions (%u, max: %d)\n",
- (unsigned) layout->mNumberChannelDescriptions,
- MP_NUM_CHANNELS);
+ (unsigned) l->mNumberChannelDescriptions, MP_NUM_CHANNELS);
return false;
}
- for (int n = 0; n < layout->mNumberChannelDescriptions; n++) {
- AudioChannelLabel label = layout->mChannelDescriptions[n].mChannelLabel;
+ for (int n = 0; n < l->mNumberChannelDescriptions; n++) {
+ AudioChannelLabel label = l->mChannelDescriptions[n].mChannelLabel;
uint8_t speaker = ca_label_to_mp_speaker_id(label);
if (speaker < 0) {
MP_VERBOSE(ao, "channel label=%u unusable to build channel "
@@ -436,9 +446,11 @@ bool ca_layout_to_mp_chmap(struct ao *ao, AudioChannelLayout *layout,
if (mp_chmap_is_unknown(chmap) && chmap->num < 3)
mp_chmap_from_channels(chmap, chmap->num);
+ talloc_free(talloc_ctx);
return chmap->num > 0;
coreaudio_error:
ca_log_layout(ao, layout);
+ talloc_free(talloc_ctx);
return false;
}