| OLD | NEW |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/renderer_host/audio_renderer_host.h" | 5 #include "chrome/browser/renderer_host/audio_renderer_host.h" |
| 6 | 6 |
| 7 #include "base/metrics/histogram.h" | 7 #include "base/metrics/histogram.h" |
| 8 #include "base/process.h" | 8 #include "base/process.h" |
| 9 #include "base/shared_memory.h" | 9 #include "base/shared_memory.h" |
| 10 #include "base/sys_info.h" | |
| 11 #include "chrome/browser/renderer_host/audio_sync_reader.h" | 10 #include "chrome/browser/renderer_host/audio_sync_reader.h" |
| 12 #include "chrome/common/render_messages.h" | 11 #include "chrome/common/render_messages.h" |
| 13 #include "chrome/common/render_messages_params.h" | 12 #include "chrome/common/render_messages_params.h" |
| 14 #include "ipc/ipc_logging.h" | 13 #include "ipc/ipc_logging.h" |
| 15 | 14 |
| 16 // The minimum number of samples in a hardware packet. | 15 // The minimum number of samples in a hardware packet. |
| 17 // This value is selected so that we can handle down to 5khz sample rate. | 16 // This value is selected so that we can handle down to 5khz sample rate. |
| 18 static const int kMinSamplesPerHardwarePacket = 1024; | 17 static const int kMinSamplesPerHardwarePacket = 1024; |
| 19 | 18 |
| 20 // The maximum number of samples in a hardware packet. | 19 // The maximum number of samples in a hardware packet. |
| 21 // This value is selected so that we can handle up to 192khz sample rate. | 20 // This value is selected so that we can handle up to 192khz sample rate. |
| 22 static const int kMaxSamplesPerHardwarePacket = 64 * 1024; | 21 static const int kMaxSamplesPerHardwarePacket = 64 * 1024; |
| 23 | 22 |
| 24 // This constant governs the hardware audio buffer size, this value should be | 23 // This constant governs the hardware audio buffer size, this value should be |
| 25 // chosen carefully. | 24 // chosen carefully. |
| 26 // This value is selected so that we have 8192 samples for 48khz streams. | 25 // This value is selected so that we have 8192 samples for 48khz streams. |
| 27 static const int kMillisecondsPerHardwarePacket = 170; | 26 static const int kMillisecondsPerHardwarePacket = 170; |
| 28 | 27 |
| 29 // We allow at most 50 concurrent audio streams in most case. This is a | |
| 30 // rather high limit that is practically hard to reach. | |
| 31 static const size_t kMaxStreams = 50; | |
| 32 | |
| 33 // By experiment the maximum number of audio streams allowed in Leopard | |
| 34 // is 18. But we put a slightly smaller number just to be safe. | |
| 35 static const size_t kMaxStreamsLeopard = 15; | |
| 36 | |
| 37 // Returns the number of audio streams allowed. This is a practical limit to | |
| 38 // prevent failure caused by too many audio streams opened. | |
| 39 static size_t GetMaxAudioStreamsAllowed() { | |
| 40 #if defined(OS_MACOSX) | |
| 41 // We are hitting a bug in Leopard where too many audio streams will cause | |
| 42 // a deadlock in the AudioQueue API when starting the stream. Unfortunately | |
| 43 // there's no way to detect it within the AudioQueue API, so we put a | |
| 44 // special hard limit only for Leopard. | |
| 45 // See bug: http://crbug.com/30242 | |
| 46 int32 major, minor, bugfix; | |
| 47 base::SysInfo::OperatingSystemVersionNumbers(&major, &minor, &bugfix); | |
| 48 if (major < 10 || (major == 10 && minor <= 5)) | |
| 49 return kMaxStreamsLeopard; | |
| 50 #endif | |
| 51 | |
| 52 // In OS other than OSX Leopard, the number of audio streams allowed is a | |
| 53 // lot more so we return a separate number. | |
| 54 return kMaxStreams; | |
| 55 } | |
| 56 | |
| 57 static uint32 SelectSamplesPerPacket(AudioParameters params) { | 28 static uint32 SelectSamplesPerPacket(AudioParameters params) { |
| 58 // Select the number of samples that can provide at least | 29 // Select the number of samples that can provide at least |
| 59 // |kMillisecondsPerHardwarePacket| worth of audio data. | 30 // |kMillisecondsPerHardwarePacket| worth of audio data. |
| 60 int samples = kMinSamplesPerHardwarePacket; | 31 int samples = kMinSamplesPerHardwarePacket; |
| 61 while (samples <= kMaxSamplesPerHardwarePacket && | 32 while (samples <= kMaxSamplesPerHardwarePacket && |
| 62 samples * base::Time::kMillisecondsPerSecond < | 33 samples * base::Time::kMillisecondsPerSecond < |
| 63 params.sample_rate * kMillisecondsPerHardwarePacket) { | 34 params.sample_rate * kMillisecondsPerHardwarePacket) { |
| 64 samples *= 2; | 35 samples *= 2; |
| 65 } | 36 } |
| 66 return samples; | 37 return samples; |
| (...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 330 } | 301 } |
| 331 return false; | 302 return false; |
| 332 } | 303 } |
| 333 | 304 |
| 334 void AudioRendererHost::OnCreateStream( | 305 void AudioRendererHost::OnCreateStream( |
| 335 const IPC::Message& msg, int stream_id, | 306 const IPC::Message& msg, int stream_id, |
| 336 const ViewHostMsg_Audio_CreateStream_Params& params, bool low_latency) { | 307 const ViewHostMsg_Audio_CreateStream_Params& params, bool low_latency) { |
| 337 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 308 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 338 DCHECK(LookupById(msg.routing_id(), stream_id) == NULL); | 309 DCHECK(LookupById(msg.routing_id(), stream_id) == NULL); |
| 339 | 310 |
| 340 // Limit the number of audio streams opened. This is to prevent using | |
| 341 // excessive resources for a large number of audio streams. More | |
| 342 // importantly it prevents instability on certain systems. | |
| 343 // See bug: http://crbug.com/30242 | |
| 344 if (audio_entries_.size() >= GetMaxAudioStreamsAllowed()) { | |
| 345 SendErrorMessage(msg.routing_id(), stream_id); | |
| 346 return; | |
| 347 } | |
| 348 | |
| 349 AudioParameters audio_params(params.params); | 311 AudioParameters audio_params(params.params); |
| 350 | 312 |
| 351 // Select the hardware packet size if not specified. | 313 // Select the hardware packet size if not specified. |
| 352 if (!audio_params.samples_per_packet) { | 314 if (!audio_params.samples_per_packet) { |
| 353 audio_params.samples_per_packet = SelectSamplesPerPacket(audio_params); | 315 audio_params.samples_per_packet = SelectSamplesPerPacket(audio_params); |
| 354 } | 316 } |
| 355 uint32 packet_size = audio_params.GetPacketSize(); | 317 uint32 packet_size = audio_params.GetPacketSize(); |
| 356 | 318 |
| 357 scoped_ptr<AudioEntry> entry(new AudioEntry()); | 319 scoped_ptr<AudioEntry> entry(new AudioEntry()); |
| 358 // Create the shared memory and share with the renderer process. | 320 // Create the shared memory and share with the renderer process. |
| (...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 580 | 542 |
| 581 // Iterate the map of entries. | 543 // Iterate the map of entries. |
| 582 // TODO(hclam): Implement a faster look up method. | 544 // TODO(hclam): Implement a faster look up method. |
| 583 for (AudioEntryMap::iterator i = audio_entries_.begin(); | 545 for (AudioEntryMap::iterator i = audio_entries_.begin(); |
| 584 i != audio_entries_.end(); ++i) { | 546 i != audio_entries_.end(); ++i) { |
| 585 if (controller == i->second->controller.get()) | 547 if (controller == i->second->controller.get()) |
| 586 return i->second; | 548 return i->second; |
| 587 } | 549 } |
| 588 return NULL; | 550 return NULL; |
| 589 } | 551 } |
| OLD | NEW |