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 |