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