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.h" | 9 #include "base/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.h" | 12 #include "base/time.h" |
13 #include "build/build_config.h" | 13 #include "build/build_config.h" |
14 #include "media/audio/audio_silence_detector.h" | 14 #include "media/audio/audio_power_monitor.h" |
15 #include "media/audio/audio_util.h" | 15 #include "media/audio/audio_util.h" |
16 #include "media/audio/shared_memory_util.h" | 16 #include "media/audio/shared_memory_util.h" |
17 | 17 |
18 using base::Time; | 18 using base::Time; |
19 using base::TimeDelta; | 19 using base::TimeDelta; |
20 | 20 |
21 namespace media { | 21 namespace media { |
22 | 22 |
23 // Amount of contiguous time where all audio is silent before considering the | 23 // Amount of time between calls to EventHandler::OnPowerMeasured() to report |
24 // stream to have transitioned and EventHandler::OnAudible() should be called. | 24 // current power levels in the audio signal. |
25 static const int kQuestionableSilencePeriodMillis = 50; | 25 static const float kPowerMeasurementPeriodSeconds = 50.0f / 1000.0f; |
DaleCurtis
2013/05/16 18:24:45
Confusing, this doesn't look like it's in seconds?
miu
2013/05/16 21:44:11
Doh! I had already fixed that before requesting t
| |
26 | |
27 // Sample value range below which audio is considered indistinguishably silent. | |
28 // | |
29 // TODO(miu): This value should be specified in dbFS units rather than full | |
30 // scale. See TODO in audio_silence_detector.h. | |
31 static const float kIndistinguishableSilenceThreshold = | |
32 1.0f / 4096.0f; // Note: This is approximately -72 dbFS. | |
33 | 26 |
34 // Polling-related constants. | 27 // Polling-related constants. |
35 const int AudioOutputController::kPollNumAttempts = 3; | 28 const int AudioOutputController::kPollNumAttempts = 3; |
36 const int AudioOutputController::kPollPauseInMilliseconds = 3; | 29 const int AudioOutputController::kPollPauseInMilliseconds = 3; |
37 | 30 |
38 AudioOutputController::AudioOutputController(AudioManager* audio_manager, | 31 AudioOutputController::AudioOutputController(AudioManager* audio_manager, |
39 EventHandler* handler, | 32 EventHandler* handler, |
40 const AudioParameters& params, | 33 const AudioParameters& params, |
41 SyncReader* sync_reader) | 34 SyncReader* sync_reader) |
42 : audio_manager_(audio_manager), | 35 : audio_manager_(audio_manager), |
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
182 base::Bind(&AudioOutputController::PollAndStartIfDataReady, | 175 base::Bind(&AudioOutputController::PollAndStartIfDataReady, |
183 weak_this_.GetWeakPtr()), | 176 weak_this_.GetWeakPtr()), |
184 TimeDelta::FromMilliseconds(kPollPauseInMilliseconds)); | 177 TimeDelta::FromMilliseconds(kPollPauseInMilliseconds)); |
185 } | 178 } |
186 } | 179 } |
187 | 180 |
188 void AudioOutputController::StartStream() { | 181 void AudioOutputController::StartStream() { |
189 DCHECK(message_loop_->BelongsToCurrentThread()); | 182 DCHECK(message_loop_->BelongsToCurrentThread()); |
190 state_ = kPlaying; | 183 state_ = kPlaying; |
191 | 184 |
192 silence_detector_.reset(new AudioSilenceDetector( | 185 // Start monitoring power levels and send an initial notification that we're |
186 // starting in silence. | |
187 handler_->OnPowerMeasured(AudioPowerMonitor::kZeroPowerDBFS); | |
188 power_monitor_.reset(new AudioPowerMonitor( | |
193 params_.sample_rate(), | 189 params_.sample_rate(), |
194 TimeDelta::FromMilliseconds(kQuestionableSilencePeriodMillis), | 190 TimeDelta::FromMilliseconds(kPowerMeasurementPeriodSeconds), |
195 kIndistinguishableSilenceThreshold)); | 191 MessageLoop::current(), |
192 base::Bind(&EventHandler::OnPowerMeasured, base::Unretained(handler_)))); | |
196 | 193 |
197 // We start the AudioOutputStream lazily. | 194 // We start the AudioOutputStream lazily. |
198 AllowEntryToOnMoreIOData(); | 195 AllowEntryToOnMoreIOData(); |
199 stream_->Start(this); | 196 stream_->Start(this); |
200 | 197 |
201 // Tell the event handler that we are now playing, and also start the silence | |
202 // detection notifications. | |
203 handler_->OnPlaying(); | 198 handler_->OnPlaying(); |
204 silence_detector_->Start( | |
205 base::Bind(&EventHandler::OnAudible, base::Unretained(handler_))); | |
206 } | 199 } |
207 | 200 |
208 void AudioOutputController::StopStream() { | 201 void AudioOutputController::StopStream() { |
209 DCHECK(message_loop_->BelongsToCurrentThread()); | 202 DCHECK(message_loop_->BelongsToCurrentThread()); |
210 | 203 |
211 if (state_ == kStarting) { | 204 if (state_ == kStarting) { |
212 // Cancel in-progress polling start. | 205 // Cancel in-progress polling start. |
213 weak_this_.InvalidateWeakPtrs(); | 206 weak_this_.InvalidateWeakPtrs(); |
214 state_ = kPaused; | 207 state_ = kPaused; |
215 } else if (state_ == kPlaying) { | 208 } else if (state_ == kPlaying) { |
216 stream_->Stop(); | 209 stream_->Stop(); |
217 DisallowEntryToOnMoreIOData(); | 210 DisallowEntryToOnMoreIOData(); |
218 silence_detector_->Stop(true); | 211 power_monitor_.reset(); |
219 silence_detector_.reset(); | 212 // Send a final notification that we're ending in silence. |
213 handler_->OnPowerMeasured(AudioPowerMonitor::kZeroPowerDBFS); | |
220 state_ = kPaused; | 214 state_ = kPaused; |
221 } | 215 } |
222 } | 216 } |
223 | 217 |
224 void AudioOutputController::DoPause() { | 218 void AudioOutputController::DoPause() { |
225 DCHECK(message_loop_->BelongsToCurrentThread()); | 219 DCHECK(message_loop_->BelongsToCurrentThread()); |
226 | 220 |
227 StopStream(); | 221 StopStream(); |
228 | 222 |
229 if (state_ != kPaused) | 223 if (state_ != kPaused) |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
289 // http://crbug.com/171651, http://crbug.com/174985, and more. | 283 // http://crbug.com/171651, http://crbug.com/174985, and more. |
290 #if defined(OS_WIN) || defined(OS_LINUX) | 284 #if defined(OS_WIN) || defined(OS_LINUX) |
291 WaitTillDataReady(); | 285 WaitTillDataReady(); |
292 #endif | 286 #endif |
293 | 287 |
294 const int frames = sync_reader_->Read(source, dest); | 288 const int frames = sync_reader_->Read(source, dest); |
295 DCHECK_LE(0, frames); | 289 DCHECK_LE(0, frames); |
296 sync_reader_->UpdatePendingBytes( | 290 sync_reader_->UpdatePendingBytes( |
297 buffers_state.total_bytes() + frames * params_.GetBytesPerFrame()); | 291 buffers_state.total_bytes() + frames * params_.GetBytesPerFrame()); |
298 | 292 |
299 silence_detector_->Scan(dest, frames); | 293 power_monitor_->Scan(dest, frames); |
300 | 294 |
301 AllowEntryToOnMoreIOData(); | 295 AllowEntryToOnMoreIOData(); |
302 return frames; | 296 return frames; |
303 } | 297 } |
304 | 298 |
305 void AudioOutputController::WaitTillDataReady() { | 299 void AudioOutputController::WaitTillDataReady() { |
306 // Most of the time the data is ready already. | 300 // Most of the time the data is ready already. |
307 if (sync_reader_->DataReady()) | 301 if (sync_reader_->DataReady()) |
308 return; | 302 return; |
309 | 303 |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
436 DCHECK(base::AtomicRefCountIsZero(&num_allowed_io_)); | 430 DCHECK(base::AtomicRefCountIsZero(&num_allowed_io_)); |
437 base::AtomicRefCountInc(&num_allowed_io_); | 431 base::AtomicRefCountInc(&num_allowed_io_); |
438 } | 432 } |
439 | 433 |
440 void AudioOutputController::DisallowEntryToOnMoreIOData() { | 434 void AudioOutputController::DisallowEntryToOnMoreIOData() { |
441 const bool is_zero = !base::AtomicRefCountDec(&num_allowed_io_); | 435 const bool is_zero = !base::AtomicRefCountDec(&num_allowed_io_); |
442 DCHECK(is_zero); | 436 DCHECK(is_zero); |
443 } | 437 } |
444 | 438 |
445 } // namespace media | 439 } // namespace media |
OLD | NEW |