| Index: media/audio/mac/audio_manager_mac.cc
|
| diff --git a/media/audio/mac/audio_manager_mac.cc b/media/audio/mac/audio_manager_mac.cc
|
| index cb2ac1f1f2f7b8fce551096508bcafee56560f7c..2e793681e1e09ee2921378759782c229a5bb193c 100644
|
| --- a/media/audio/mac/audio_manager_mac.cc
|
| +++ b/media/audio/mac/audio_manager_mac.cc
|
| @@ -310,16 +310,20 @@ static bool GetDeviceTotalChannelCount(AudioDeviceID device,
|
|
|
| UInt32 size;
|
| OSStatus result = AudioObjectGetPropertyDataSize(device, &pa, 0, 0, &size);
|
| - if (result != noErr || !size)
|
| + if (result != noErr || !size) {
|
| + OSSTATUS_LOG(ERROR, result) << "Failed to get property size... " << size;
|
| return false;
|
| + }
|
|
|
| std::unique_ptr<uint8_t[]> list_storage(new uint8_t[size]);
|
| AudioBufferList* buffer_list =
|
| reinterpret_cast<AudioBufferList*>(list_storage.get());
|
|
|
| result = AudioObjectGetPropertyData(device, &pa, 0, 0, &size, buffer_list);
|
| - if (result != noErr)
|
| + if (result != noErr) {
|
| + OSSTATUS_LOG(ERROR, result) << "Failed to get property...";
|
| return false;
|
| + }
|
|
|
| // Determine number of channels based on the AudioBufferList.
|
| // |mNumberBuffers] is the number of interleaved channels in the buffer.
|
| @@ -328,8 +332,8 @@ static bool GetDeviceTotalChannelCount(AudioDeviceID device,
|
| for (UInt32 i = 0; i < buffer_list->mNumberBuffers; ++i)
|
| *channels += buffer_list->mBuffers[i].mNumberChannels;
|
|
|
| - DVLOG(1) << (scope == kAudioDevicePropertyScopeInput ? "Input" : "Output")
|
| - << " total channels: " << *channels;
|
| + LOG(ERROR) << (scope == kAudioDevicePropertyScopeInput ? "Input" : "Output")
|
| + << " total channels: " << *channels;
|
| return true;
|
| }
|
|
|
| @@ -451,6 +455,7 @@ bool AudioManagerMac::GetDeviceChannels(AudioDeviceID device,
|
| if (GetDeviceTotalChannelCount(device, scope, &total_channel_count) &&
|
| total_channel_count > kMaxConcurrentChannels) {
|
| *channels = total_channel_count;
|
| + LOG(ERROR) << "Total count exceeds 8 channels, preferring total count.";
|
| return true;
|
| }
|
|
|
| @@ -458,15 +463,20 @@ bool AudioManagerMac::GetDeviceChannels(AudioDeviceID device,
|
| scope, kAudioObjectPropertyElementMaster};
|
| UInt32 size;
|
| OSStatus result = AudioObjectGetPropertyDataSize(device, &pa, 0, 0, &size);
|
| - if (result != noErr || !size)
|
| + if (result != noErr || !size) {
|
| + OSSTATUS_LOG(ERROR, result)
|
| + << "Failed to get property (2) size... " << size;
|
| return false;
|
| + }
|
|
|
| std::unique_ptr<uint8_t[]> layout_storage(new uint8_t[size]);
|
| AudioChannelLayout* layout =
|
| reinterpret_cast<AudioChannelLayout*>(layout_storage.get());
|
| result = AudioObjectGetPropertyData(device, &pa, 0, 0, &size, layout);
|
| - if (result != noErr)
|
| + if (result != noErr) {
|
| + OSSTATUS_LOG(ERROR, result) << "Failed to get property (2)... ";
|
| return false;
|
| + }
|
|
|
| // We don't want to have to know about all channel layout tags, so force OSX
|
| // to give us the channel descriptions from the bitmap or tag if necessary.
|
| @@ -484,8 +494,10 @@ bool AudioManagerMac::GetDeviceChannels(AudioDeviceID device,
|
| result = AudioFormatGetPropertyInfo(fa, sizeof(AudioChannelLayoutTag),
|
| &tag, &size);
|
| }
|
| - if (result != noErr || !size)
|
| + if (result != noErr || !size) {
|
| + OSSTATUS_LOG(ERROR, result) << "Failed to get af info... " << size;
|
| return false;
|
| + }
|
|
|
| layout_storage.reset(new uint8_t[size]);
|
| layout = reinterpret_cast<AudioChannelLayout*>(layout_storage.get());
|
| @@ -496,30 +508,83 @@ bool AudioManagerMac::GetDeviceChannels(AudioDeviceID device,
|
| result = AudioFormatGetProperty(fa, sizeof(AudioChannelLayoutTag), &tag,
|
| &size, layout);
|
| }
|
| - if (result != noErr)
|
| + if (result != noErr) {
|
| + OSSTATUS_LOG(ERROR, result) << "Failed to get af structure... ";
|
| return false;
|
| + }
|
| }
|
|
|
| - // There is no channel info for stereo, assume so for mono as well.
|
| - if (layout->mNumberChannelDescriptions <= 2) {
|
| - *channels = layout->mNumberChannelDescriptions;
|
| - } else {
|
| - *channels = 0;
|
| - for (UInt32 i = 0; i < layout->mNumberChannelDescriptions; ++i) {
|
| - if (layout->mChannelDescriptions[i].mChannelLabel !=
|
| - kAudioChannelLabel_Unknown)
|
| - (*channels)++;
|
| + bool is_au_based_retry = false;
|
| + do {
|
| + // There is no channel info for stereo, assume so for mono as well.
|
| + if (layout->mNumberChannelDescriptions <= 2) {
|
| + *channels = layout->mNumberChannelDescriptions;
|
| + } else {
|
| + *channels = 0;
|
| + for (UInt32 i = 0; i < layout->mNumberChannelDescriptions; ++i) {
|
| + if (layout->mChannelDescriptions[i].mChannelLabel !=
|
| + kAudioChannelLabel_Unknown)
|
| + (*channels)++;
|
| + }
|
| }
|
| - }
|
|
|
| - // If we still don't have a channel count, fall back to total channel count.
|
| - if (*channels == 0) {
|
| - DLOG(WARNING) << "Unable to use channel layout for channel count.";
|
| - *channels = total_channel_count;
|
| - }
|
| + // If we still don't have a channel count, fall back to total channel count.
|
| + if (*channels == 0 && !is_au_based_retry) {
|
| + is_au_based_retry = true;
|
| +
|
| + const AudioUnitScope au_scope =
|
| + scope == kAudioDevicePropertyScopeOutput ? 0 : 1;
|
| +
|
| + LOG(ERROR)
|
| + << "Unable to use channel layout for channel count, trying AU.";
|
| +
|
| + AudioComponentDescription desc = {kAudioUnitType_Output,
|
| + kAudioUnitSubType_HALOutput,
|
| + kAudioUnitManufacturer_Apple, 0, 0};
|
| + AudioComponent comp = AudioComponentFindNext(0, &desc);
|
| + if (!comp) {
|
| + LOG(ERROR) << "Failed to find component.";
|
| + return false;
|
| + }
|
| +
|
| + AudioUnit audio_unit;
|
| + result = AudioComponentInstanceNew(comp, &audio_unit);
|
| + if (result != noErr) {
|
| + OSSTATUS_LOG(ERROR, result) << "AudioComponentInstanceNew() failed.";
|
| + return false;
|
| + }
|
| +
|
| + Boolean writable;
|
| + result = AudioUnitGetPropertyInfo(
|
| + audio_unit, kAudioUnitProperty_AudioChannelLayout,
|
| + kAudioUnitScope_Output, au_scope, &size, &writable);
|
| + if (result != noErr) {
|
| + OSSTATUS_LOG(ERROR, result) << "AudioUnitGetPropertyInfo() failed.";
|
| + return false;
|
| + }
|
| +
|
| + layout_storage.reset(new uint8_t[size]);
|
| + layout = reinterpret_cast<AudioChannelLayout*>(layout_storage.get());
|
| +
|
| + result = AudioUnitGetProperty(
|
| + audio_unit, kAudioUnitProperty_AudioChannelLayout,
|
| + kAudioUnitScope_Output, au_scope, layout, &size);
|
| + if (result != noErr) {
|
| + OSSTATUS_LOG(ERROR, result) << "AudioUnitGetProperty() failed.";
|
| + return false;
|
| + }
|
| +
|
| + result = AudioUnitUninitialize(audio_unit);
|
| + OSSTATUS_LOG_IF(ERROR, result != noErr, result)
|
| + << "AudioUnitUninitialize() failed.";
|
| + result = AudioComponentInstanceDispose(audio_unit);
|
| + OSSTATUS_LOG_IF(ERROR, result != noErr, result)
|
| + << "AudioComponentInstanceDispose() failed.";
|
| + }
|
| + } while (*channels == 0 && is_au_based_retry);
|
|
|
| - DVLOG(1) << (scope == kAudioDevicePropertyScopeInput ? "Input" : "Output")
|
| - << " channels: " << *channels;
|
| + LOG(ERROR) << (scope == kAudioDevicePropertyScopeInput ? "Input" : "Output")
|
| + << " channels: " << *channels;
|
| return true;
|
| }
|
|
|
|
|