| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "media/audio/audio_output_controller.h" | 5 #include "media/audio/audio_output_controller.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/debug/trace_event.h" | 8 #include "base/debug/trace_event.h" |
| 9 #include "base/message_loop/message_loop.h" | 9 #include "base/message_loop/message_loop.h" |
| 10 #include "base/metrics/histogram.h" | 10 #include "base/metrics/histogram.h" |
| 11 #include "base/threading/platform_thread.h" | 11 #include "base/threading/platform_thread.h" |
| 12 #include "base/time/time.h" | 12 #include "base/time/time.h" |
| 13 #include "build/build_config.h" | 13 #include "build/build_config.h" |
| 14 #include "media/audio/shared_memory_util.h" | |
| 15 #include "media/base/scoped_histogram_timer.h" | 14 #include "media/base/scoped_histogram_timer.h" |
| 16 | 15 |
| 17 using base::Time; | 16 using base::Time; |
| 18 using base::TimeDelta; | 17 using base::TimeDelta; |
| 19 | 18 |
| 20 namespace media { | 19 namespace media { |
| 21 | 20 |
| 22 #if defined(AUDIO_POWER_MONITORING) | 21 #if defined(AUDIO_POWER_MONITORING) |
| 23 // Time constant for AudioPowerMonitor. See AudioPowerMonitor ctor comments for | 22 // Time constant for AudioPowerMonitor. See AudioPowerMonitor ctor comments for |
| 24 // semantics. This value was arbitrarily chosen, but seems to work well. | 23 // semantics. This value was arbitrarily chosen, but seems to work well. |
| (...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 214 | 213 |
| 215 void AudioOutputController::DoPause() { | 214 void AudioOutputController::DoPause() { |
| 216 DCHECK(message_loop_->BelongsToCurrentThread()); | 215 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 217 SCOPED_UMA_HISTOGRAM_TIMER("Media.AudioOutputController.PauseTime"); | 216 SCOPED_UMA_HISTOGRAM_TIMER("Media.AudioOutputController.PauseTime"); |
| 218 | 217 |
| 219 StopStream(); | 218 StopStream(); |
| 220 | 219 |
| 221 if (state_ != kPaused) | 220 if (state_ != kPaused) |
| 222 return; | 221 return; |
| 223 | 222 |
| 224 // Send a special pause mark to the low-latency audio thread. | 223 // Let the renderer know we've stopped. Necessary to let PPAPI clients know |
| 225 sync_reader_->UpdatePendingBytes(kPauseMark); | 224 // audio has been shutdown. TODO(dalecurtis): This stinks. PPAPI should have |
| 225 // a better way to know when it should exit PPB_Audio_Shared::Run(). |
| 226 sync_reader_->UpdatePendingBytes(-1); |
| 226 | 227 |
| 227 #if defined(AUDIO_POWER_MONITORING) | 228 #if defined(AUDIO_POWER_MONITORING) |
| 228 // Paused means silence follows. | 229 // Paused means silence follows. |
| 229 handler_->OnPowerMeasured(AudioPowerMonitor::zero_power(), false); | 230 handler_->OnPowerMeasured(AudioPowerMonitor::zero_power(), false); |
| 230 #endif | 231 #endif |
| 231 | 232 |
| 232 handler_->OnPaused(); | 233 handler_->OnPaused(); |
| 233 } | 234 } |
| 234 | 235 |
| 235 void AudioOutputController::DoClose() { | 236 void AudioOutputController::DoClose() { |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 271 AudioBuffersState buffers_state) { | 272 AudioBuffersState buffers_state) { |
| 272 return OnMoreIOData(NULL, dest, buffers_state); | 273 return OnMoreIOData(NULL, dest, buffers_state); |
| 273 } | 274 } |
| 274 | 275 |
| 275 int AudioOutputController::OnMoreIOData(AudioBus* source, | 276 int AudioOutputController::OnMoreIOData(AudioBus* source, |
| 276 AudioBus* dest, | 277 AudioBus* dest, |
| 277 AudioBuffersState buffers_state) { | 278 AudioBuffersState buffers_state) { |
| 278 DisallowEntryToOnMoreIOData(); | 279 DisallowEntryToOnMoreIOData(); |
| 279 TRACE_EVENT0("audio", "AudioOutputController::OnMoreIOData"); | 280 TRACE_EVENT0("audio", "AudioOutputController::OnMoreIOData"); |
| 280 | 281 |
| 281 // The OS level audio APIs on Linux and Windows all have problems requesting | 282 sync_reader_->Read(source, dest); |
| 282 // data on a fixed interval. Sometimes they will issue calls back to back | |
| 283 // which can cause glitching, so wait until the renderer is ready. | |
| 284 // | |
| 285 // We also need to wait when diverting since the virtual stream will call this | |
| 286 // multiple times without waiting. | |
| 287 // | |
| 288 // NEVER wait on OSX unless a virtual stream is connected, otherwise we can | |
| 289 // end up hanging the entire OS. | |
| 290 // | |
| 291 // See many bugs for context behind this decision: http://crbug.com/170498, | |
| 292 // http://crbug.com/171651, http://crbug.com/174985, and more. | |
| 293 #if defined(OS_WIN) || defined(OS_LINUX) | |
| 294 const bool kShouldBlock = true; | |
| 295 #else | |
| 296 const bool kShouldBlock = diverting_to_stream_ != NULL; | |
| 297 #endif | |
| 298 | 283 |
| 299 const int frames = sync_reader_->Read(kShouldBlock, source, dest); | 284 const int frames = dest->frames(); |
| 300 DCHECK_LE(0, frames); | |
| 301 sync_reader_->UpdatePendingBytes( | 285 sync_reader_->UpdatePendingBytes( |
| 302 buffers_state.total_bytes() + frames * params_.GetBytesPerFrame()); | 286 buffers_state.total_bytes() + frames * params_.GetBytesPerFrame()); |
| 303 | 287 |
| 304 #if defined(AUDIO_POWER_MONITORING) | 288 #if defined(AUDIO_POWER_MONITORING) |
| 305 power_monitor_.Scan(*dest, frames); | 289 power_monitor_.Scan(*dest, frames); |
| 306 #endif | 290 #endif |
| 307 | 291 |
| 308 AllowEntryToOnMoreIOData(); | 292 AllowEntryToOnMoreIOData(); |
| 309 return frames; | 293 return frames; |
| 310 } | 294 } |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 410 DCHECK(base::AtomicRefCountIsZero(&num_allowed_io_)); | 394 DCHECK(base::AtomicRefCountIsZero(&num_allowed_io_)); |
| 411 base::AtomicRefCountInc(&num_allowed_io_); | 395 base::AtomicRefCountInc(&num_allowed_io_); |
| 412 } | 396 } |
| 413 | 397 |
| 414 void AudioOutputController::DisallowEntryToOnMoreIOData() { | 398 void AudioOutputController::DisallowEntryToOnMoreIOData() { |
| 415 const bool is_zero = !base::AtomicRefCountDec(&num_allowed_io_); | 399 const bool is_zero = !base::AtomicRefCountDec(&num_allowed_io_); |
| 416 DCHECK(is_zero); | 400 DCHECK(is_zero); |
| 417 } | 401 } |
| 418 | 402 |
| 419 } // namespace media | 403 } // namespace media |
| OLD | NEW |