| 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_power_monitor.h" | |
| 15 #include "media/audio/audio_util.h" | 14 #include "media/audio/audio_util.h" |
| 16 #include "media/audio/shared_memory_util.h" | 15 #include "media/audio/shared_memory_util.h" |
| 17 #include "media/base/scoped_histogram_timer.h" | 16 #include "media/base/scoped_histogram_timer.h" |
| 18 | 17 |
| 19 using base::Time; | 18 using base::Time; |
| 20 using base::TimeDelta; | 19 using base::TimeDelta; |
| 21 | 20 |
| 22 namespace media { | 21 namespace media { |
| 23 | 22 |
| 24 // Time constant for AudioPowerMonitor. See AudioPowerMonitor ctor comments for | 23 // Time constant for AudioPowerMonitor. See AudioPowerMonitor ctor comments for |
| (...skipping 17 matching lines...) Expand all Loading... |
| 42 params_(params), | 41 params_(params), |
| 43 handler_(handler), | 42 handler_(handler), |
| 44 input_device_id_(input_device_id), | 43 input_device_id_(input_device_id), |
| 45 stream_(NULL), | 44 stream_(NULL), |
| 46 diverting_to_stream_(NULL), | 45 diverting_to_stream_(NULL), |
| 47 volume_(1.0), | 46 volume_(1.0), |
| 48 state_(kEmpty), | 47 state_(kEmpty), |
| 49 num_allowed_io_(0), | 48 num_allowed_io_(0), |
| 50 sync_reader_(sync_reader), | 49 sync_reader_(sync_reader), |
| 51 message_loop_(audio_manager->GetMessageLoop()), | 50 message_loop_(audio_manager->GetMessageLoop()), |
| 52 number_polling_attempts_left_(0) { | 51 number_polling_attempts_left_(0), |
| 52 power_monitor_( |
| 53 params.sample_rate(), |
| 54 TimeDelta::FromMilliseconds(kPowerMeasurementTimeConstantMillis)) { |
| 53 DCHECK(audio_manager); | 55 DCHECK(audio_manager); |
| 54 DCHECK(handler_); | 56 DCHECK(handler_); |
| 55 DCHECK(sync_reader_); | 57 DCHECK(sync_reader_); |
| 56 DCHECK(message_loop_.get()); | 58 DCHECK(message_loop_.get()); |
| 57 } | 59 } |
| 58 | 60 |
| 59 AudioOutputController::~AudioOutputController() { | 61 AudioOutputController::~AudioOutputController() { |
| 60 DCHECK_EQ(kClosed, state_); | 62 DCHECK_EQ(kClosed, state_); |
| 61 } | 63 } |
| 62 | 64 |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 149 | 151 |
| 150 // We can start from created or paused state. | 152 // We can start from created or paused state. |
| 151 if (state_ != kCreated && state_ != kPaused) | 153 if (state_ != kCreated && state_ != kPaused) |
| 152 return; | 154 return; |
| 153 | 155 |
| 154 // Ask for first packet. | 156 // Ask for first packet. |
| 155 sync_reader_->UpdatePendingBytes(0); | 157 sync_reader_->UpdatePendingBytes(0); |
| 156 | 158 |
| 157 state_ = kPlaying; | 159 state_ = kPlaying; |
| 158 | 160 |
| 159 // Start monitoring power levels and send an initial notification that we're | 161 power_monitor_.Reset(); |
| 160 // starting in silence. | 162 power_poll_callback_.Reset( |
| 161 handler_->OnPowerMeasured(AudioPowerMonitor::zero_power(), false); | 163 base::Bind(&AudioOutputController::ReportPowerMeasurementPeriodically, |
| 162 power_monitor_callback_.Reset( | 164 this)); |
| 163 base::Bind(&EventHandler::OnPowerMeasured, base::Unretained(handler_))); | 165 // Run the callback to send an initial notification that we're starting in |
| 164 power_monitor_.reset(new AudioPowerMonitor( | 166 // silence, and to schedule periodic callbacks. |
| 165 params_.sample_rate(), | 167 power_poll_callback_.callback().Run(); |
| 166 TimeDelta::FromMilliseconds(kPowerMeasurementTimeConstantMillis), | |
| 167 TimeDelta::FromSeconds(1) / kPowerMeasurementsPerSecond, | |
| 168 base::MessageLoop::current(), | |
| 169 power_monitor_callback_.callback())); | |
| 170 | 168 |
| 171 // We start the AudioOutputStream lazily. | 169 // We start the AudioOutputStream lazily. |
| 172 AllowEntryToOnMoreIOData(); | 170 AllowEntryToOnMoreIOData(); |
| 173 stream_->Start(this); | 171 stream_->Start(this); |
| 174 | 172 |
| 175 handler_->OnPlaying(); | 173 handler_->OnPlaying(); |
| 176 } | 174 } |
| 177 | 175 |
| 176 void AudioOutputController::ReportPowerMeasurementPeriodically() { |
| 177 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 178 handler_->OnPowerMeasured(power_monitor_.ReadCurrentPower(), |
| 179 power_monitor_.TestForClippingAndClear()); |
| 180 message_loop_->PostDelayedTask( |
| 181 FROM_HERE, power_poll_callback_.callback(), |
| 182 TimeDelta::FromSeconds(1) / kPowerMeasurementsPerSecond); |
| 183 } |
| 184 |
| 178 void AudioOutputController::StopStream() { | 185 void AudioOutputController::StopStream() { |
| 179 DCHECK(message_loop_->BelongsToCurrentThread()); | 186 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 180 | 187 |
| 181 if (state_ == kPlaying) { | 188 if (state_ == kPlaying) { |
| 182 stream_->Stop(); | 189 stream_->Stop(); |
| 183 DisallowEntryToOnMoreIOData(); | 190 DisallowEntryToOnMoreIOData(); |
| 184 | 191 |
| 185 // Stop monitoring power levels. By canceling power_monitor_callback_, any | 192 power_poll_callback_.Cancel(); |
| 186 // tasks posted to |message_loop_| by AudioPowerMonitor during the | |
| 187 // stream_->Stop() call above will not run. | |
| 188 power_monitor_.reset(); | |
| 189 power_monitor_callback_.Cancel(); | |
| 190 | 193 |
| 191 state_ = kPaused; | 194 state_ = kPaused; |
| 192 } | 195 } |
| 193 } | 196 } |
| 194 | 197 |
| 195 void AudioOutputController::DoPause() { | 198 void AudioOutputController::DoPause() { |
| 196 DCHECK(message_loop_->BelongsToCurrentThread()); | 199 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 197 SCOPED_UMA_HISTOGRAM_TIMER("Media.AudioOutputController.PauseTime"); | 200 SCOPED_UMA_HISTOGRAM_TIMER("Media.AudioOutputController.PauseTime"); |
| 198 | 201 |
| 199 StopStream(); | 202 StopStream(); |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 272 const bool kShouldBlock = true; | 275 const bool kShouldBlock = true; |
| 273 #else | 276 #else |
| 274 const bool kShouldBlock = diverting_to_stream_ != NULL; | 277 const bool kShouldBlock = diverting_to_stream_ != NULL; |
| 275 #endif | 278 #endif |
| 276 | 279 |
| 277 const int frames = sync_reader_->Read(kShouldBlock, source, dest); | 280 const int frames = sync_reader_->Read(kShouldBlock, source, dest); |
| 278 DCHECK_LE(0, frames); | 281 DCHECK_LE(0, frames); |
| 279 sync_reader_->UpdatePendingBytes( | 282 sync_reader_->UpdatePendingBytes( |
| 280 buffers_state.total_bytes() + frames * params_.GetBytesPerFrame()); | 283 buffers_state.total_bytes() + frames * params_.GetBytesPerFrame()); |
| 281 | 284 |
| 282 power_monitor_->Scan(*dest, frames); | 285 power_monitor_.Scan(*dest, frames); |
| 283 | 286 |
| 284 AllowEntryToOnMoreIOData(); | 287 AllowEntryToOnMoreIOData(); |
| 285 return frames; | 288 return frames; |
| 286 } | 289 } |
| 287 | 290 |
| 288 void AudioOutputController::OnError(AudioOutputStream* stream) { | 291 void AudioOutputController::OnError(AudioOutputStream* stream) { |
| 289 // Handle error on the audio controller thread. | 292 // Handle error on the audio controller thread. |
| 290 message_loop_->PostTask(FROM_HERE, base::Bind( | 293 message_loop_->PostTask(FROM_HERE, base::Bind( |
| 291 &AudioOutputController::DoReportError, this)); | 294 &AudioOutputController::DoReportError, this)); |
| 292 } | 295 } |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 386 DCHECK(base::AtomicRefCountIsZero(&num_allowed_io_)); | 389 DCHECK(base::AtomicRefCountIsZero(&num_allowed_io_)); |
| 387 base::AtomicRefCountInc(&num_allowed_io_); | 390 base::AtomicRefCountInc(&num_allowed_io_); |
| 388 } | 391 } |
| 389 | 392 |
| 390 void AudioOutputController::DisallowEntryToOnMoreIOData() { | 393 void AudioOutputController::DisallowEntryToOnMoreIOData() { |
| 391 const bool is_zero = !base::AtomicRefCountDec(&num_allowed_io_); | 394 const bool is_zero = !base::AtomicRefCountDec(&num_allowed_io_); |
| 392 DCHECK(is_zero); | 395 DCHECK(is_zero); |
| 393 } | 396 } |
| 394 | 397 |
| 395 } // namespace media | 398 } // namespace media |
| OLD | NEW |