Chromium Code Reviews| 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 |