summaryrefslogtreecommitdiffstats
path: root/media
diff options
context:
space:
mode:
authorsergeyu@chromium.org <sergeyu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-11-30 00:05:48 +0000
committersergeyu@chromium.org <sergeyu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-11-30 00:05:48 +0000
commit5e943817161fbc16c4f8d2e4694aba6f02da1d0b (patch)
tree30aacb779a2e76659629c6c757414247e1473cd3 /media
parent5aed51cfab86781e2da97749629ed919e82ea35f (diff)
downloadchromium_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.cc8
-rw-r--r--media/audio/mac/audio_manager_mac.cc59
-rw-r--r--media/audio/mac/audio_manager_mac.h9
-rw-r--r--media/audio/win/audio_manager_win.cc28
-rw-r--r--media/audio/win/audio_manager_win.h7
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);
};