| 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/metrics/histogram.h" | 9 #include "base/metrics/histogram.h" |
| 10 #include "base/task_runner_util.h" | 10 #include "base/task_runner_util.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/base/scoped_histogram_timer.h" | 14 #include "media/base/scoped_histogram_timer.h" |
| 15 | 15 |
| 16 using base::TimeDelta; | 16 using base::TimeDelta; |
| 17 | 17 |
| 18 namespace media { | 18 namespace media { |
| 19 | 19 |
| 20 #if defined(AUDIO_POWER_MONITORING) | |
| 21 // Time constant for AudioPowerMonitor. See AudioPowerMonitor ctor comments for | |
| 22 // semantics. This value was arbitrarily chosen, but seems to work well. | |
| 23 static const int kPowerMeasurementTimeConstantMillis = 10; | |
| 24 #endif | |
| 25 | |
| 26 AudioOutputController::AudioOutputController( | 20 AudioOutputController::AudioOutputController( |
| 27 AudioManager* audio_manager, | 21 AudioManager* audio_manager, |
| 28 EventHandler* handler, | 22 EventHandler* handler, |
| 29 const AudioParameters& params, | 23 const AudioParameters& params, |
| 30 const std::string& output_device_id, | 24 const std::string& output_device_id, |
| 31 SyncReader* sync_reader) | 25 SyncReader* sync_reader) |
| 32 : audio_manager_(audio_manager), | 26 : audio_manager_(audio_manager), |
| 33 params_(params), | 27 params_(params), |
| 34 handler_(handler), | 28 handler_(handler), |
| 35 output_device_id_(output_device_id), | 29 output_device_id_(output_device_id), |
| 36 stream_(NULL), | 30 stream_(NULL), |
| 37 diverting_to_stream_(NULL), | 31 diverting_to_stream_(NULL), |
| 38 volume_(1.0), | 32 volume_(1.0), |
| 39 state_(kEmpty), | 33 state_(kEmpty), |
| 40 sync_reader_(sync_reader), | 34 sync_reader_(sync_reader), |
| 41 message_loop_(audio_manager->GetTaskRunner()), | 35 message_loop_(audio_manager->GetTaskRunner()), |
| 42 #if defined(AUDIO_POWER_MONITORING) | |
| 43 power_monitor_( | 36 power_monitor_( |
| 44 params.sample_rate(), | 37 params.sample_rate(), |
| 45 TimeDelta::FromMilliseconds(kPowerMeasurementTimeConstantMillis)), | 38 TimeDelta::FromMilliseconds(kPowerMeasurementTimeConstantMillis)), |
| 46 #endif | |
| 47 on_more_io_data_called_(0) { | 39 on_more_io_data_called_(0) { |
| 48 DCHECK(audio_manager); | 40 DCHECK(audio_manager); |
| 49 DCHECK(handler_); | 41 DCHECK(handler_); |
| 50 DCHECK(sync_reader_); | 42 DCHECK(sync_reader_); |
| 51 DCHECK(message_loop_.get()); | 43 DCHECK(message_loop_.get()); |
| 52 } | 44 } |
| 53 | 45 |
| 54 AudioOutputController::~AudioOutputController() { | 46 AudioOutputController::~AudioOutputController() { |
| 55 DCHECK_EQ(kClosed, state_); | 47 DCHECK_EQ(kClosed, state_); |
| 56 } | 48 } |
| (...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 193 handler_->OnPlaying(); | 185 handler_->OnPlaying(); |
| 194 } | 186 } |
| 195 | 187 |
| 196 void AudioOutputController::StopStream() { | 188 void AudioOutputController::StopStream() { |
| 197 DCHECK(message_loop_->BelongsToCurrentThread()); | 189 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 198 | 190 |
| 199 if (state_ == kPlaying) { | 191 if (state_ == kPlaying) { |
| 200 wedge_timer_.reset(); | 192 wedge_timer_.reset(); |
| 201 stream_->Stop(); | 193 stream_->Stop(); |
| 202 | 194 |
| 203 #if defined(AUDIO_POWER_MONITORING) | |
| 204 // A stopped stream is silent, and power_montior_.Scan() is no longer being | 195 // A stopped stream is silent, and power_montior_.Scan() is no longer being |
| 205 // called; so we must reset the power monitor. | 196 // called; so we must reset the power monitor. |
| 206 power_monitor_.Reset(); | 197 power_monitor_.Reset(); |
| 207 #endif | |
| 208 | 198 |
| 209 state_ = kPaused; | 199 state_ = kPaused; |
| 210 } | 200 } |
| 211 } | 201 } |
| 212 | 202 |
| 213 void AudioOutputController::DoPause() { | 203 void AudioOutputController::DoPause() { |
| 214 DCHECK(message_loop_->BelongsToCurrentThread()); | 204 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 215 SCOPED_UMA_HISTOGRAM_TIMER("Media.AudioOutputController.PauseTime"); | 205 SCOPED_UMA_HISTOGRAM_TIMER("Media.AudioOutputController.PauseTime"); |
| 216 TRACE_EVENT0("audio", "AudioOutputController::DoPause"); | 206 TRACE_EVENT0("audio", "AudioOutputController::DoPause"); |
| 217 | 207 |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 299 // thread starts, its safe to compare and then increment. | 289 // thread starts, its safe to compare and then increment. |
| 300 if (base::AtomicRefCountIsZero(&on_more_io_data_called_)) | 290 if (base::AtomicRefCountIsZero(&on_more_io_data_called_)) |
| 301 base::AtomicRefCountInc(&on_more_io_data_called_); | 291 base::AtomicRefCountInc(&on_more_io_data_called_); |
| 302 | 292 |
| 303 sync_reader_->Read(dest); | 293 sync_reader_->Read(dest); |
| 304 | 294 |
| 305 const int frames = dest->frames(); | 295 const int frames = dest->frames(); |
| 306 sync_reader_->UpdatePendingBytes( | 296 sync_reader_->UpdatePendingBytes( |
| 307 buffers_state.total_bytes() + frames * params_.GetBytesPerFrame()); | 297 buffers_state.total_bytes() + frames * params_.GetBytesPerFrame()); |
| 308 | 298 |
| 309 #if defined(AUDIO_POWER_MONITORING) | 299 if (will_monitor_audio_levels()) |
| 310 power_monitor_.Scan(*dest, frames); | 300 power_monitor_.Scan(*dest, frames); |
| 311 #endif | |
| 312 | 301 |
| 313 return frames; | 302 return frames; |
| 314 } | 303 } |
| 315 | 304 |
| 316 void AudioOutputController::OnError(AudioOutputStream* stream) { | 305 void AudioOutputController::OnError(AudioOutputStream* stream) { |
| 317 // Handle error on the audio controller thread. | 306 // Handle error on the audio controller thread. |
| 318 message_loop_->PostTask(FROM_HERE, base::Bind( | 307 message_loop_->PostTask(FROM_HERE, base::Bind( |
| 319 &AudioOutputController::DoReportError, this)); | 308 &AudioOutputController::DoReportError, this)); |
| 320 } | 309 } |
| 321 | 310 |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 405 return; | 394 return; |
| 406 | 395 |
| 407 // Note: OnDeviceChange() will cause the existing stream (the consumer of the | 396 // Note: OnDeviceChange() will cause the existing stream (the consumer of the |
| 408 // diverted audio data) to be closed, and diverting_to_stream_ will be set | 397 // diverted audio data) to be closed, and diverting_to_stream_ will be set |
| 409 // back to NULL. | 398 // back to NULL. |
| 410 OnDeviceChange(); | 399 OnDeviceChange(); |
| 411 DCHECK(!diverting_to_stream_); | 400 DCHECK(!diverting_to_stream_); |
| 412 } | 401 } |
| 413 | 402 |
| 414 std::pair<float, bool> AudioOutputController::ReadCurrentPowerAndClip() { | 403 std::pair<float, bool> AudioOutputController::ReadCurrentPowerAndClip() { |
| 415 #if defined(AUDIO_POWER_MONITORING) | 404 DCHECK(will_monitor_audio_levels()); |
| 416 return power_monitor_.ReadCurrentPowerAndClip(); | 405 return power_monitor_.ReadCurrentPowerAndClip(); |
| 417 #else | |
| 418 NOTREACHED(); | |
| 419 return std::make_pair(AudioPowerMonitor::zero_power(), false); | |
| 420 #endif | |
| 421 } | 406 } |
| 422 | 407 |
| 423 void AudioOutputController::WedgeCheck() { | 408 void AudioOutputController::WedgeCheck() { |
| 424 DCHECK(message_loop_->BelongsToCurrentThread()); | 409 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 425 | 410 |
| 426 // If we should be playing and we haven't, that's a wedge. | 411 // If we should be playing and we haven't, that's a wedge. |
| 427 if (state_ == kPlaying) { | 412 if (state_ == kPlaying) { |
| 428 UMA_HISTOGRAM_BOOLEAN("Media.AudioOutputControllerPlaybackStartupSuccess", | 413 UMA_HISTOGRAM_BOOLEAN("Media.AudioOutputControllerPlaybackStartupSuccess", |
| 429 base::AtomicRefCountIsOne(&on_more_io_data_called_)); | 414 base::AtomicRefCountIsOne(&on_more_io_data_called_)); |
| 430 } | 415 } |
| 431 } | 416 } |
| 432 | 417 |
| 433 } // namespace media | 418 } // namespace media |
| OLD | NEW |