| 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/lock.h" | 7 #include "base/lock.h" |
| 8 #include "base/metrics/histogram.h" | 8 #include "base/metrics/histogram.h" |
| 9 #include "base/process.h" | 9 #include "base/process.h" |
| 10 #include "base/shared_memory.h" | 10 #include "base/shared_memory.h" |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 48 base::SysInfo::OperatingSystemVersionNumbers(&major, &minor, &bugfix); | 48 base::SysInfo::OperatingSystemVersionNumbers(&major, &minor, &bugfix); |
| 49 if (major < 10 || (major == 10 && minor <= 5)) | 49 if (major < 10 || (major == 10 && minor <= 5)) |
| 50 return kMaxStreamsLeopard; | 50 return kMaxStreamsLeopard; |
| 51 #endif | 51 #endif |
| 52 | 52 |
| 53 // In OS other than OSX Leopard, the number of audio streams allowed is a | 53 // In OS other than OSX Leopard, the number of audio streams allowed is a |
| 54 // lot more so we return a separate number. | 54 // lot more so we return a separate number. |
| 55 return kMaxStreams; | 55 return kMaxStreams; |
| 56 } | 56 } |
| 57 | 57 |
| 58 static uint32 SelectHardwarePacketSize(AudioParameters params) { | 58 static uint32 SelectSamplesPerPacket(AudioParameters params) { |
| 59 // Select the number of samples that can provide at least | 59 // Select the number of samples that can provide at least |
| 60 // |kMillisecondsPerHardwarePacket| worth of audio data. | 60 // |kMillisecondsPerHardwarePacket| worth of audio data. |
| 61 int samples = kMinSamplesPerHardwarePacket; | 61 int samples = kMinSamplesPerHardwarePacket; |
| 62 while (samples <= kMaxSamplesPerHardwarePacket && | 62 while (samples <= kMaxSamplesPerHardwarePacket && |
| 63 samples * base::Time::kMillisecondsPerSecond < | 63 samples * base::Time::kMillisecondsPerSecond < |
| 64 params.sample_rate * kMillisecondsPerHardwarePacket) { | 64 params.sample_rate * kMillisecondsPerHardwarePacket) { |
| 65 samples *= 2; | 65 samples *= 2; |
| 66 } | 66 } |
| 67 return params.channels * samples * params.bits_per_sample / 8; | 67 return samples; |
| 68 } | 68 } |
| 69 | 69 |
| 70 AudioRendererHost::AudioEntry::AudioEntry() | 70 AudioRendererHost::AudioEntry::AudioEntry() |
| 71 : render_view_id(0), | 71 : render_view_id(0), |
| 72 stream_id(0), | 72 stream_id(0), |
| 73 pending_buffer_request(false), | 73 pending_buffer_request(false), |
| 74 pending_close(false) { | 74 pending_close(false) { |
| 75 } | 75 } |
| 76 | 76 |
| 77 AudioRendererHost::AudioEntry::~AudioEntry() {} | 77 AudioRendererHost::AudioEntry::~AudioEntry() {} |
| (...skipping 262 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 340 | 340 |
| 341 // Limit the number of audio streams opened. This is to prevent using | 341 // Limit the number of audio streams opened. This is to prevent using |
| 342 // excessive resources for a large number of audio streams. More | 342 // excessive resources for a large number of audio streams. More |
| 343 // importantly it prevents instability on certain systems. | 343 // importantly it prevents instability on certain systems. |
| 344 // See bug: http://crbug.com/30242 | 344 // See bug: http://crbug.com/30242 |
| 345 if (audio_entries_.size() >= GetMaxAudioStreamsAllowed()) { | 345 if (audio_entries_.size() >= GetMaxAudioStreamsAllowed()) { |
| 346 SendErrorMessage(msg.routing_id(), stream_id); | 346 SendErrorMessage(msg.routing_id(), stream_id); |
| 347 return; | 347 return; |
| 348 } | 348 } |
| 349 | 349 |
| 350 // Select the hardwaer packet size if not specified. | 350 AudioParameters audio_params(params.params); |
| 351 uint32 hardware_packet_size = params.packet_size; | 351 |
| 352 if (!hardware_packet_size) { | 352 // Select the hardware packet size if not specified. |
| 353 hardware_packet_size = SelectHardwarePacketSize(params.params); | 353 if (!audio_params.samples_per_packet) { |
| 354 audio_params.samples_per_packet = SelectSamplesPerPacket(audio_params); |
| 354 } | 355 } |
| 356 uint32 packet_size = audio_params.samples_per_packet * |
| 357 audio_params.channels * audio_params.bits_per_sample / 8; |
| 355 | 358 |
| 356 scoped_ptr<AudioEntry> entry(new AudioEntry()); | 359 scoped_ptr<AudioEntry> entry(new AudioEntry()); |
| 357 // Create the shared memory and share with the renderer process. | 360 // Create the shared memory and share with the renderer process. |
| 358 if (!entry->shared_memory.CreateAndMapAnonymous(hardware_packet_size)) { | 361 if (!entry->shared_memory.CreateAndMapAnonymous(packet_size)) { |
| 359 // If creation of shared memory failed then send an error message. | 362 // If creation of shared memory failed then send an error message. |
| 360 SendErrorMessage(msg.routing_id(), stream_id); | 363 SendErrorMessage(msg.routing_id(), stream_id); |
| 361 return; | 364 return; |
| 362 } | 365 } |
| 363 | 366 |
| 364 if (low_latency) { | 367 if (low_latency) { |
| 365 // If this is the low latency mode, we need to construct a SyncReader first. | 368 // If this is the low latency mode, we need to construct a SyncReader first. |
| 366 scoped_ptr<AudioSyncReader> reader( | 369 scoped_ptr<AudioSyncReader> reader( |
| 367 new AudioSyncReader(&entry->shared_memory)); | 370 new AudioSyncReader(&entry->shared_memory)); |
| 368 | 371 |
| 369 // Then try to initialize the sync reader. | 372 // Then try to initialize the sync reader. |
| 370 if (!reader->Init()) { | 373 if (!reader->Init()) { |
| 371 SendErrorMessage(msg.routing_id(), stream_id); | 374 SendErrorMessage(msg.routing_id(), stream_id); |
| 372 return; | 375 return; |
| 373 } | 376 } |
| 374 | 377 |
| 375 // If we have successfully created the SyncReader then assign it to the | 378 // If we have successfully created the SyncReader then assign it to the |
| 376 // entry and construct an AudioOutputController. | 379 // entry and construct an AudioOutputController. |
| 377 entry->reader.reset(reader.release()); | 380 entry->reader.reset(reader.release()); |
| 378 entry->controller = | 381 entry->controller = |
| 379 media::AudioOutputController::CreateLowLatency( | 382 media::AudioOutputController::CreateLowLatency(this, audio_params, |
| 380 this, params.params, | 383 entry->reader.get()); |
| 381 hardware_packet_size, | |
| 382 entry->reader.get()); | |
| 383 } else { | 384 } else { |
| 384 // The choice of buffer capacity is based on experiment. | 385 // The choice of buffer capacity is based on experiment. |
| 385 entry->controller = | 386 entry->controller = |
| 386 media::AudioOutputController::Create(this, params.params, | 387 media::AudioOutputController::Create(this, audio_params, |
| 387 hardware_packet_size, | 388 3 * packet_size); |
| 388 3 * hardware_packet_size); | |
| 389 } | 389 } |
| 390 | 390 |
| 391 if (!entry->controller) { | 391 if (!entry->controller) { |
| 392 SendErrorMessage(msg.routing_id(), stream_id); | 392 SendErrorMessage(msg.routing_id(), stream_id); |
| 393 return; | 393 return; |
| 394 } | 394 } |
| 395 | 395 |
| 396 // If we have created the controller successfully create a entry and add it | 396 // If we have created the controller successfully create a entry and add it |
| 397 // to the map. | 397 // to the map. |
| 398 entry->render_view_id = msg.routing_id(); | 398 entry->render_view_id = msg.routing_id(); |
| (...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 582 | 582 |
| 583 // Iterate the map of entries. | 583 // Iterate the map of entries. |
| 584 // TODO(hclam): Implement a faster look up method. | 584 // TODO(hclam): Implement a faster look up method. |
| 585 for (AudioEntryMap::iterator i = audio_entries_.begin(); | 585 for (AudioEntryMap::iterator i = audio_entries_.begin(); |
| 586 i != audio_entries_.end(); ++i) { | 586 i != audio_entries_.end(); ++i) { |
| 587 if (controller == i->second->controller.get()) | 587 if (controller == i->second->controller.get()) |
| 588 return i->second; | 588 return i->second; |
| 589 } | 589 } |
| 590 return NULL; | 590 return NULL; |
| 591 } | 591 } |
| OLD | NEW |