diff options
author | sergeyu@chromium.org <sergeyu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-11-30 00:05:48 +0000 |
---|---|---|
committer | sergeyu@chromium.org <sergeyu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-11-30 00:05:48 +0000 |
commit | 5e943817161fbc16c4f8d2e4694aba6f02da1d0b (patch) | |
tree | 30aacb779a2e76659629c6c757414247e1473cd3 /media | |
parent | 5aed51cfab86781e2da97749629ed919e82ea35f (diff) | |
download | chromium_src-5e943817161fbc16c4f8d2e4694aba6f02da1d0b.zip chromium_src-5e943817161fbc16c4f8d2e4694aba6f02da1d0b.tar.gz chromium_src-5e943817161fbc16c4f8d2e4694aba6f02da1d0b.tar.bz2 |
Move audio output number limit to AudioManager.
BUG=39825
TEST=None
Review URL: http://codereview.chromium.org/5350003
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@67618 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'media')
-rw-r--r-- | media/audio/linux/audio_manager_linux.cc | 8 | ||||
-rw-r--r-- | media/audio/mac/audio_manager_mac.cc | 59 | ||||
-rw-r--r-- | media/audio/mac/audio_manager_mac.h | 9 | ||||
-rw-r--r-- | media/audio/win/audio_manager_win.cc | 28 | ||||
-rw-r--r-- | media/audio/win/audio_manager_win.h | 7 |
5 files changed, 97 insertions, 14 deletions
diff --git a/media/audio/linux/audio_manager_linux.cc b/media/audio/linux/audio_manager_linux.cc index 73f4ace..c875c08 100644 --- a/media/audio/linux/audio_manager_linux.cc +++ b/media/audio/linux/audio_manager_linux.cc @@ -17,6 +17,9 @@ namespace { +// Maximum number of output streams that can be open simultaneously. +const size_t kMaxOutputStreams = 50; + const int kMaxInputChannels = 2; } // namespace @@ -44,6 +47,11 @@ AudioOutputStream* AudioManagerLinux::MakeAudioOutputStream( return NULL; } + // Don't allow opening more than |kMaxOutputStreams| streams. + if (active_streams_.size() >= kMaxOutputStreams) { + return NULL; + } + std::string device_name = AlsaPcmOutputStream::kAutoSelectDevice; if (CommandLine::ForCurrentProcess()->HasSwitch( switches::kAlsaOutputDevice)) { diff --git a/media/audio/mac/audio_manager_mac.cc b/media/audio/mac/audio_manager_mac.cc index 4565bba..48df6ab 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,42 @@ #include "media/base/limits.h" namespace { + const int kMaxInputChannels = 2; +// 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; + +// Initialized to ether |kMaxOutputStreams| or |kMaxOutputStreamsLeopard|. +size_t g_max_output_streams = 0; + +// 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() { + if (g_max_output_streams == 0) { + // 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)) { + g_max_output_streams = kMaxOutputStreamsLeopard; + } else { + // In OS other than OSX Leopard, the number of audio streams + // allowed is a lot more. + g_max_output_streams = kMaxOutputStreams; + } + } + + return g_max_output_streams; +} + bool HasAudioHardware(AudioObjectPropertySelector selector) { AudioDeviceID output_device_id = kAudioObjectUnknown; const AudioObjectPropertyAddress property_address = { @@ -33,6 +68,13 @@ bool HasAudioHardware(AudioObjectPropertySelector selector) { } } // namespace +AudioManagerMac::AudioManagerMac() + : num_output_streams_(0) { +} + +AudioManagerMac::~AudioManagerMac() { +} + bool AudioManagerMac::HasAudioOutputDevices() { return HasAudioHardware(kAudioHardwarePropertyDefaultOutputDevice); } @@ -43,10 +85,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_ >= GetMaxAudioOutputStreamsAllowed()) { + return NULL; + } + + num_output_streams_++; return new PCMQueueOutAudioOutputStream(this, params); } @@ -74,6 +127,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; } diff --git a/media/audio/mac/audio_manager_mac.h b/media/audio/mac/audio_manager_mac.h index 31f6de2..d2fc3f3 100644 --- a/media/audio/mac/audio_manager_mac.h +++ b/media/audio/mac/audio_manager_mac.h @@ -16,7 +16,7 @@ class PCMQueueOutAudioOutputStream; // the AudioManager class. class AudioManagerMac : public AudioManagerBase { public: - AudioManagerMac() {}; + AudioManagerMac(); // Implementation of AudioManager. virtual bool HasAudioOutputDevices(); @@ -33,8 +33,11 @@ class AudioManagerMac : public AudioManagerBase { void ReleaseInputStream(PCMQueueInAudioInputStream* stream); private: - friend void DestroyAudioManagerMac(void*); - virtual ~AudioManagerMac() {}; + virtual ~AudioManagerMac(); + + // Number of currently open output streams. + size_t num_output_streams_; + DISALLOW_COPY_AND_ASSIGN(AudioManagerMac); }; diff --git a/media/audio/win/audio_manager_win.cc b/media/audio/win/audio_manager_win.cc index 4a36172..dee14c5 100644 --- a/media/audio/win/audio_manager_win.cc +++ b/media/audio/win/audio_manager_win.cc @@ -34,6 +34,9 @@ DEFINE_GUID(AM_KSCATEGORY_AUDIO, 0x6994ad04, 0x93ef, 0x11d0, namespace { +// Maximum number of output streams that can be open simultaneously. +const size_t kMaxOutputStreams = 50; + // Up to 8 channels can be passed to the driver. // This should work, given the right drivers, but graceful error handling is // needed. @@ -91,6 +94,13 @@ string16 GetDeviceAndDriverInfo(HDEVINFO device_info, } // namespace +AudioManagerWin::AudioManagerWin() + : num_output_streams_(0) { +} + +AudioManagerWin::~AudioManagerWin() { +} + bool AudioManagerWin::HasAudioOutputDevices() { return (::waveOutGetNumDevs() != 0); } @@ -108,11 +118,18 @@ AudioOutputStream* AudioManagerWin::MakeAudioOutputStream( if (!params.IsValid() || (params.channels > kWinMaxChannels)) return NULL; + // Limit the number of audio streams opened. + if (num_output_streams_ >= kMaxOutputStreams) { + return NULL; + } + if (params.format == AudioParameters::AUDIO_MOCK) { return FakeAudioOutputStream::MakeFakeStream(params); } else if (params.format == AudioParameters::AUDIO_PCM_LINEAR) { + num_output_streams_++; return new PCMWaveOutAudioOutputStream(this, params, 3, WAVE_MAPPER); } else if (params.format == AudioParameters::AUDIO_PCM_LOW_LATENCY) { + num_output_streams_++; // TODO(cpu): waveout cannot hit 20ms latency. Use other method. return new PCMWaveOutAudioOutputStream(this, params, 2, WAVE_MAPPER); } @@ -135,13 +152,13 @@ AudioInputStream* AudioManagerWin::MakeAudioInputStream( } void AudioManagerWin::ReleaseOutputStream(PCMWaveOutAudioOutputStream* stream) { - if (stream) - delete stream; + DCHECK(stream); + num_output_streams_--; + delete stream; } void AudioManagerWin::ReleaseInputStream(PCMWaveInAudioInputStream* stream) { - if (stream) - delete stream; + delete stream; } void AudioManagerWin::MuteAll() { @@ -150,9 +167,6 @@ void AudioManagerWin::MuteAll() { void AudioManagerWin::UnMuteAll() { } -AudioManagerWin::~AudioManagerWin() { -} - string16 AudioManagerWin::GetAudioInputDeviceModel() { // Get the default audio capture device and its device interface name. DWORD device_id = 0; diff --git a/media/audio/win/audio_manager_win.h b/media/audio/win/audio_manager_win.h index 05c80e4..d6ff37f 100644 --- a/media/audio/win/audio_manager_win.h +++ b/media/audio/win/audio_manager_win.h @@ -18,7 +18,7 @@ class PCMWaveOutAudioOutputStream; // the AudioManager class. class AudioManagerWin : public AudioManagerBase { public: - AudioManagerWin() {} + AudioManagerWin(); // Implementation of AudioManager. virtual bool HasAudioOutputDevices(); virtual bool HasAudioInputDevices(); @@ -36,8 +36,11 @@ class AudioManagerWin : public AudioManagerBase { void ReleaseInputStream(PCMWaveInAudioInputStream* stream); private: - friend void DestroyAudioManagerWin(void *); virtual ~AudioManagerWin(); + + // Number of currently open output streams. + int num_output_streams_; + DISALLOW_COPY_AND_ASSIGN(AudioManagerWin); }; |