summaryrefslogtreecommitdiffstats
path: root/chrome/browser/renderer_host/audio_renderer_host.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/browser/renderer_host/audio_renderer_host.cc')
-rw-r--r--chrome/browser/renderer_host/audio_renderer_host.cc57
1 files changed, 50 insertions, 7 deletions
diff --git a/chrome/browser/renderer_host/audio_renderer_host.cc b/chrome/browser/renderer_host/audio_renderer_host.cc
index 8d0a91c..10e9c77 100644
--- a/chrome/browser/renderer_host/audio_renderer_host.cc
+++ b/chrome/browser/renderer_host/audio_renderer_host.cc
@@ -26,6 +26,7 @@
#include "base/lock.h"
#include "base/process.h"
#include "base/shared_memory.h"
+#include "base/sys_info.h"
#include "base/waitable_event.h"
#include "chrome/common/render_messages.h"
#include "ipc/ipc_logging.h"
@@ -34,22 +35,50 @@ namespace {
// This constant governs the hardware audio buffer size, this value should be
// choosen carefully and is platform specific.
-const int kSamplesPerHardwarePacket = 8192;
+static const int kSamplesPerHardwarePacket = 8192;
// If the size of the buffer is less than this number, then the low latency
// mode is to be used.
-const uint32 kLowLatencyPacketThreshold = 1025;
+static const uint32 kLowLatencyPacketThreshold = 1025;
-const uint32 kMegabytes = 1024 * 1024;
+static const uint32 kMegabytes = 1024 * 1024;
// The following parameters limit the request buffer and packet size from the
// renderer to avoid renderer from requesting too much memory.
-const uint32 kMaxDecodedPacketSize = 2 * kMegabytes;
-const uint32 kMaxBufferCapacity = 5 * kMegabytes;
+static const uint32 kMaxDecodedPacketSize = 2 * kMegabytes;
+static const uint32 kMaxBufferCapacity = 5 * kMegabytes;
static const int kMaxChannels = 32;
static const int kMaxBitsPerSample = 64;
static const int kMaxSampleRate = 192000;
+// We allow at most 50 concurrent audio streams in most case. This is a
+// rather high limit that is practically hard to reach.
+static const size_t kMaxStreams = 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.
+static const size_t kMaxStreamsLeopard = 15;
+
+// Returns the number of audio streams allowed. This is a practical limit to
+// prevent failure caused by too many audio streams opened.
+size_t GetMaxAudioStreamsAllowed() {
+#if defined(OS_MACOSX)
+ // 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 kMaxStreamsLeopard;
+#endif
+
+ // In OS other than OSX Leopard, the number of audio streams allowed is a
+ // lot more so we return a separate number.
+ return kMaxStreams;
+}
+
} // namespace
//-----------------------------------------------------------------------------
@@ -331,6 +360,13 @@ void AudioRendererHost::IPCAudioSource::NotifyPacketReady(
DCHECK(!shared_socket_.get());
AutoLock auto_lock(lock_);
+
+ // If we don't have an outstanding request, we should take the data.
+ if (!outstanding_request_) {
+ NOTREACHED() << "Received an audio packet while there was no such request";
+ return;
+ }
+
outstanding_request_ = false;
// If reported size is greater than capacity of the shared memory, we have
// an error.
@@ -468,6 +504,15 @@ void AudioRendererHost::OnCreateStream(
DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
DCHECK(Lookup(msg.routing_id(), stream_id) == 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 (sources_.size() >= GetMaxAudioStreamsAllowed()) {
+ SendErrorMessage(msg.routing_id(), stream_id);
+ return;
+ }
+
IPCAudioSource* source = IPCAudioSource::CreateIPCAudioSource(
this,
process_id_,
@@ -487,8 +532,6 @@ void AudioRendererHost::OnCreateStream(
sources_.insert(
std::make_pair(
SourceID(source->route_id(), source->stream_id()), source));
- } else {
- SendErrorMessage(msg.routing_id(), stream_id);
}
}