Chromium Code Reviews| 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 4565bba54e0abce1525c33804e550c268aff24d0..da039ef3732c194b3185928a65cbc99880d424b8 100644 |
| --- a/media/audio/mac/audio_manager_mac.cc |
| +++ b/media/audio/mac/audio_manager_mac.cc |
| @@ -4,6 +4,7 @@ |
| #include <CoreAudio/AudioHardware.h> |
| +#include "base/sys_info.h" |
| #include "media/audio/fake_audio_input_stream.h" |
| #include "media/audio/fake_audio_output_stream.h" |
| #include "media/audio/mac/audio_input_mac.h" |
| @@ -12,8 +13,34 @@ |
| #include "media/base/limits.h" |
| namespace { |
| + |
| +// Maximum number of output streams that can be open simultaneously. |
| +const size_t kMaxOutputStreams = 50; |
| + |
| +// By experiment the maximum number of audio streams allowed in Leopard |
| +// is 18. But we put a slightly smaller number just to be safe. |
| +const size_t kMaxOutputStreamsLeopard = 15; |
| + |
| const int kMaxInputChannels = 2; |
| +// Returns the number of audio streams allowed. This is a practical limit to |
| +// prevent failure caused by too many audio streams opened. |
| +size_t GetMaxAudioOutputStreamsAllowed() { |
|
scherkus (not reviewing)
2010/11/29 22:42:13
what about caching the result as a static and lazy
Sergey Ulanov
2010/11/29 22:58:12
Done.
|
| + // We are hitting a bug in Leopard where too many audio streams will cause |
| + // a deadlock in the AudioQueue API when starting the stream. Unfortunately |
| + // there's no way to detect it within the AudioQueue API, so we put a |
| + // special hard limit only for Leopard. |
| + // See bug: http://crbug.com/30242 |
| + int32 major, minor, bugfix; |
| + base::SysInfo::OperatingSystemVersionNumbers(&major, &minor, &bugfix); |
| + if (major < 10 || (major == 10 && minor <= 5)) |
| + return kMaxOutputStreamsLeopard; |
| + |
| + // In OS other than OSX Leopard, the number of audio streams allowed is a |
| + // lot more so we return a separate number. |
| + return kMaxOutputStreams; |
| +} |
| + |
| bool HasAudioHardware(AudioObjectPropertySelector selector) { |
| AudioDeviceID output_device_id = kAudioObjectUnknown; |
| const AudioObjectPropertyAddress property_address = { |
| @@ -33,6 +60,11 @@ bool HasAudioHardware(AudioObjectPropertySelector selector) { |
| } |
| } // namespace |
| +AudioManagerMac::AudioManagerMac() |
| + : num_output_streams_(0), |
| + max_output_streams_(GetMaxAudioOutputStreamsAllowed()) { |
| +} |
| + |
| bool AudioManagerMac::HasAudioOutputDevices() { |
| return HasAudioHardware(kAudioHardwarePropertyDefaultOutputDevice); |
| } |
| @@ -43,10 +75,21 @@ bool AudioManagerMac::HasAudioInputDevices() { |
| AudioOutputStream* AudioManagerMac::MakeAudioOutputStream( |
| AudioParameters params) { |
| - if (params.format == AudioParameters::AUDIO_MOCK) |
| + if (params.format == AudioParameters::AUDIO_MOCK) { |
| return FakeAudioOutputStream::MakeFakeStream(params); |
| - else if (params.format != AudioParameters::AUDIO_PCM_LINEAR) |
| + } else if (params.format != AudioParameters::AUDIO_PCM_LINEAR) { |
| return NULL; |
| + } |
| + |
| + // Limit the number of audio streams opened. This is to prevent using |
| + // excessive resources for a large number of audio streams. More |
| + // importantly it prevents instability on certain systems. |
| + // See bug: http://crbug.com/30242 |
| + if (num_output_streams_ >= max_output_streams_) { |
| + return NULL; |
| + } |
| + |
| + num_output_streams_++; |
| return new PCMQueueOutAudioOutputStream(this, params); |
| } |
| @@ -74,6 +117,8 @@ void AudioManagerMac::UnMuteAll() { |
| // Called by the stream when it has been released by calling Close(). |
| void AudioManagerMac::ReleaseOutputStream( |
| PCMQueueOutAudioOutputStream* stream) { |
| + DCHECK(stream); |
| + num_output_streams_--; |
| delete stream; |
| } |