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 const std::pair<float, bool>& reading = |
| 179 power_monitor_.ReadCurrentPowerAndClip(); |
| 180 handler_->OnPowerMeasured(reading.first, reading.second); |
| 181 message_loop_->PostDelayedTask( |
| 182 FROM_HERE, power_poll_callback_.callback(), |
| 183 TimeDelta::FromSeconds(1) / kPowerMeasurementsPerSecond); |
| 184 } |
| 185 |
178 void AudioOutputController::StopStream() { | 186 void AudioOutputController::StopStream() { |
179 DCHECK(message_loop_->BelongsToCurrentThread()); | 187 DCHECK(message_loop_->BelongsToCurrentThread()); |
180 | 188 |
181 if (state_ == kPlaying) { | 189 if (state_ == kPlaying) { |
182 stream_->Stop(); | 190 stream_->Stop(); |
183 DisallowEntryToOnMoreIOData(); | 191 DisallowEntryToOnMoreIOData(); |
184 | 192 |
185 // Stop monitoring power levels. By canceling power_monitor_callback_, any | 193 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 | 194 |
191 state_ = kPaused; | 195 state_ = kPaused; |
192 } | 196 } |
193 } | 197 } |
194 | 198 |
195 void AudioOutputController::DoPause() { | 199 void AudioOutputController::DoPause() { |
196 DCHECK(message_loop_->BelongsToCurrentThread()); | 200 DCHECK(message_loop_->BelongsToCurrentThread()); |
197 SCOPED_UMA_HISTOGRAM_TIMER("Media.AudioOutputController.PauseTime"); | 201 SCOPED_UMA_HISTOGRAM_TIMER("Media.AudioOutputController.PauseTime"); |
198 | 202 |
199 StopStream(); | 203 StopStream(); |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
272 const bool kShouldBlock = true; | 276 const bool kShouldBlock = true; |
273 #else | 277 #else |
274 const bool kShouldBlock = diverting_to_stream_ != NULL; | 278 const bool kShouldBlock = diverting_to_stream_ != NULL; |
275 #endif | 279 #endif |
276 | 280 |
277 const int frames = sync_reader_->Read(kShouldBlock, source, dest); | 281 const int frames = sync_reader_->Read(kShouldBlock, source, dest); |
278 DCHECK_LE(0, frames); | 282 DCHECK_LE(0, frames); |
279 sync_reader_->UpdatePendingBytes( | 283 sync_reader_->UpdatePendingBytes( |
280 buffers_state.total_bytes() + frames * params_.GetBytesPerFrame()); | 284 buffers_state.total_bytes() + frames * params_.GetBytesPerFrame()); |
281 | 285 |
282 power_monitor_->Scan(*dest, frames); | 286 power_monitor_.Scan(*dest, frames); |
283 | 287 |
284 AllowEntryToOnMoreIOData(); | 288 AllowEntryToOnMoreIOData(); |
285 return frames; | 289 return frames; |
286 } | 290 } |
287 | 291 |
288 void AudioOutputController::OnError(AudioOutputStream* stream) { | 292 void AudioOutputController::OnError(AudioOutputStream* stream) { |
289 // Handle error on the audio controller thread. | 293 // Handle error on the audio controller thread. |
290 message_loop_->PostTask(FROM_HERE, base::Bind( | 294 message_loop_->PostTask(FROM_HERE, base::Bind( |
291 &AudioOutputController::DoReportError, this)); | 295 &AudioOutputController::DoReportError, this)); |
292 } | 296 } |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
386 DCHECK(base::AtomicRefCountIsZero(&num_allowed_io_)); | 390 DCHECK(base::AtomicRefCountIsZero(&num_allowed_io_)); |
387 base::AtomicRefCountInc(&num_allowed_io_); | 391 base::AtomicRefCountInc(&num_allowed_io_); |
388 } | 392 } |
389 | 393 |
390 void AudioOutputController::DisallowEntryToOnMoreIOData() { | 394 void AudioOutputController::DisallowEntryToOnMoreIOData() { |
391 const bool is_zero = !base::AtomicRefCountDec(&num_allowed_io_); | 395 const bool is_zero = !base::AtomicRefCountDec(&num_allowed_io_); |
392 DCHECK(is_zero); | 396 DCHECK(is_zero); |
393 } | 397 } |
394 | 398 |
395 } // namespace media | 399 } // namespace media |
OLD | NEW |