| 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/audio_util.h" | 14 #include "media/audio/audio_util.h" |
| 15 #include "media/audio/shared_memory_util.h" | |
| 16 #include "media/base/scoped_histogram_timer.h" | 15 #include "media/base/scoped_histogram_timer.h" |
| 17 | 16 |
| 18 using base::Time; | 17 using base::Time; |
| 19 using base::TimeDelta; | 18 using base::TimeDelta; |
| 20 | 19 |
| 21 namespace media { | 20 namespace media { |
| 22 | 21 |
| 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. |
| 25 static const int kPowerMeasurementTimeConstantMillis = 10; | 24 static const int kPowerMeasurementTimeConstantMillis = 10; |
| (...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 205 | 204 |
| 206 void AudioOutputController::DoPause() { | 205 void AudioOutputController::DoPause() { |
| 207 DCHECK(message_loop_->BelongsToCurrentThread()); | 206 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 208 SCOPED_UMA_HISTOGRAM_TIMER("Media.AudioOutputController.PauseTime"); | 207 SCOPED_UMA_HISTOGRAM_TIMER("Media.AudioOutputController.PauseTime"); |
| 209 | 208 |
| 210 StopStream(); | 209 StopStream(); |
| 211 | 210 |
| 212 if (state_ != kPaused) | 211 if (state_ != kPaused) |
| 213 return; | 212 return; |
| 214 | 213 |
| 215 // Send a special pause mark to the low-latency audio thread. | 214 // Let the renderer know we've stopped. Necessary to let PPAPI clients know |
| 216 sync_reader_->UpdatePendingBytes(kPauseMark); | 215 // audio has been shutdown. TODO(dalecurtis): This stinks. PPAPI should have |
| 216 // a better way to know when it should exit PPB_Audio_Shared::Run(). |
| 217 sync_reader_->UpdatePendingBytes(-1); |
| 217 | 218 |
| 218 // Paused means silence follows. | 219 // Paused means silence follows. |
| 219 handler_->OnPowerMeasured(AudioPowerMonitor::zero_power(), false); | 220 handler_->OnPowerMeasured(AudioPowerMonitor::zero_power(), false); |
| 220 | 221 |
| 221 handler_->OnPaused(); | 222 handler_->OnPaused(); |
| 222 } | 223 } |
| 223 | 224 |
| 224 void AudioOutputController::DoClose() { | 225 void AudioOutputController::DoClose() { |
| 225 DCHECK(message_loop_->BelongsToCurrentThread()); | 226 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 226 SCOPED_UMA_HISTOGRAM_TIMER("Media.AudioOutputController.CloseTime"); | 227 SCOPED_UMA_HISTOGRAM_TIMER("Media.AudioOutputController.CloseTime"); |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 260 AudioBuffersState buffers_state) { | 261 AudioBuffersState buffers_state) { |
| 261 return OnMoreIOData(NULL, dest, buffers_state); | 262 return OnMoreIOData(NULL, dest, buffers_state); |
| 262 } | 263 } |
| 263 | 264 |
| 264 int AudioOutputController::OnMoreIOData(AudioBus* source, | 265 int AudioOutputController::OnMoreIOData(AudioBus* source, |
| 265 AudioBus* dest, | 266 AudioBus* dest, |
| 266 AudioBuffersState buffers_state) { | 267 AudioBuffersState buffers_state) { |
| 267 DisallowEntryToOnMoreIOData(); | 268 DisallowEntryToOnMoreIOData(); |
| 268 TRACE_EVENT0("audio", "AudioOutputController::OnMoreIOData"); | 269 TRACE_EVENT0("audio", "AudioOutputController::OnMoreIOData"); |
| 269 | 270 |
| 270 // The OS level audio APIs on Linux and Windows all have problems requesting | 271 sync_reader_->Read(source, dest); |
| 271 // data on a fixed interval. Sometimes they will issue calls back to back | |
| 272 // which can cause glitching, so wait until the renderer is ready. | |
| 273 // | |
| 274 // We also need to wait when diverting since the virtual stream will call this | |
| 275 // multiple times without waiting. | |
| 276 // | |
| 277 // NEVER wait on OSX unless a virtual stream is connected, otherwise we can | |
| 278 // end up hanging the entire OS. | |
| 279 // | |
| 280 // See many bugs for context behind this decision: http://crbug.com/170498, | |
| 281 // http://crbug.com/171651, http://crbug.com/174985, and more. | |
| 282 #if defined(OS_WIN) || defined(OS_LINUX) | |
| 283 const bool kShouldBlock = true; | |
| 284 #else | |
| 285 const bool kShouldBlock = diverting_to_stream_ != NULL; | |
| 286 #endif | |
| 287 | 272 |
| 288 const int frames = sync_reader_->Read(kShouldBlock, source, dest); | 273 const int frames = dest->frames(); |
| 289 DCHECK_LE(0, frames); | |
| 290 sync_reader_->UpdatePendingBytes( | 274 sync_reader_->UpdatePendingBytes( |
| 291 buffers_state.total_bytes() + frames * params_.GetBytesPerFrame()); | 275 buffers_state.total_bytes() + frames * params_.GetBytesPerFrame()); |
| 292 | 276 |
| 293 power_monitor_.Scan(*dest, frames); | 277 power_monitor_.Scan(*dest, frames); |
| 294 | 278 |
| 295 AllowEntryToOnMoreIOData(); | 279 AllowEntryToOnMoreIOData(); |
| 296 return frames; | 280 return frames; |
| 297 } | 281 } |
| 298 | 282 |
| 299 void AudioOutputController::OnError(AudioOutputStream* stream) { | 283 void AudioOutputController::OnError(AudioOutputStream* stream) { |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 397 DCHECK(base::AtomicRefCountIsZero(&num_allowed_io_)); | 381 DCHECK(base::AtomicRefCountIsZero(&num_allowed_io_)); |
| 398 base::AtomicRefCountInc(&num_allowed_io_); | 382 base::AtomicRefCountInc(&num_allowed_io_); |
| 399 } | 383 } |
| 400 | 384 |
| 401 void AudioOutputController::DisallowEntryToOnMoreIOData() { | 385 void AudioOutputController::DisallowEntryToOnMoreIOData() { |
| 402 const bool is_zero = !base::AtomicRefCountDec(&num_allowed_io_); | 386 const bool is_zero = !base::AtomicRefCountDec(&num_allowed_io_); |
| 403 DCHECK(is_zero); | 387 DCHECK(is_zero); |
| 404 } | 388 } |
| 405 | 389 |
| 406 } // namespace media | 390 } // namespace media |
| OLD | NEW |