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_input_controller.h" | 5 #include "media/audio/audio_input_controller.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/strings/stringprintf.h" | 8 #include "base/strings/stringprintf.h" |
| 9 #include "base/threading/thread_restrictions.h" | 9 #include "base/threading/thread_restrictions.h" |
| 10 #include "base/time/time.h" | 10 #include "base/time/time.h" |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 40 // A large smoothing factor corresponds to a faster filter response to input | 40 // A large smoothing factor corresponds to a faster filter response to input |
| 41 // changes since y(n)=alpha*x(n)+(1-alpha)*y(n-1), where x(n) is the input | 41 // changes since y(n)=alpha*x(n)+(1-alpha)*y(n-1), where x(n) is the input |
| 42 // and y(n) is the output. | 42 // and y(n) is the output. |
| 43 const int kPowerMeasurementTimeConstantMilliseconds = 10; | 43 const int kPowerMeasurementTimeConstantMilliseconds = 10; |
| 44 | 44 |
| 45 // Time in seconds between two successive measurements of audio power levels. | 45 // Time in seconds between two successive measurements of audio power levels. |
| 46 const int kPowerMonitorLogIntervalSeconds = 5; | 46 const int kPowerMonitorLogIntervalSeconds = 5; |
| 47 #endif | 47 #endif |
| 48 } | 48 } |
| 49 | 49 |
| 50 // Used to log the result of capture startup. | |
| 51 // This was previously logged as a boolean with only the no callback and OK | |
| 52 // options. The enum order is kept to ensure backwards compatibility. | |
| 53 // Elements in this enum should not be deleted or rearranged; the only | |
| 54 // permitted operation is to add new elements before NUM_STREAM_OPEN_RESULT. | |
|
Ilya Sherman
2014/08/12 17:30:48
nit: Please update the name "NUM_STREAM_OPEN_RESUL
Henrik Grunell
2014/08/13 12:31:30
Done.
| |
| 55 enum CaptureStartupResult { | |
| 56 CAPTURE_STARTUP_NO_DATA_CALLBACK = 0, | |
| 57 CAPTURE_STARTUP_OK = 1, | |
| 58 CAPTURE_STARTUP_CREATE_STREAM_FAILED = 2, | |
| 59 CAPTURE_STARTUP_OPEN_STREAM_FAILED = 3, | |
| 60 CAPTURE_STARTUP_RESULT_MAX = CAPTURE_STARTUP_OPEN_STREAM_FAILED | |
|
Ilya Sherman
2014/08/12 17:30:48
Optional nit: It's a little cleaner, IMO, to have
Henrik Grunell
2014/08/13 12:31:30
The presubmit check actually complained about that
| |
| 61 }; | |
| 62 | |
| 63 void LogStreamOpenResult(CaptureStartupResult result) { | |
| 64 UMA_HISTOGRAM_ENUMERATION("Media.AudioInputControllerCaptureStartupSuccess", | |
| 65 result, | |
| 66 CAPTURE_STARTUP_RESULT_MAX + 1); | |
| 67 | |
| 68 } | |
| 69 | |
| 50 namespace media { | 70 namespace media { |
| 51 | 71 |
| 52 // static | 72 // static |
| 53 AudioInputController::Factory* AudioInputController::factory_ = NULL; | 73 AudioInputController::Factory* AudioInputController::factory_ = NULL; |
| 54 | 74 |
| 55 AudioInputController::AudioInputController(EventHandler* handler, | 75 AudioInputController::AudioInputController(EventHandler* handler, |
| 56 SyncWriter* sync_writer, | 76 SyncWriter* sync_writer, |
| 57 UserInputMonitor* user_input_monitor) | 77 UserInputMonitor* user_input_monitor) |
| 58 : creator_task_runner_(base::MessageLoopProxy::current()), | 78 : creator_task_runner_(base::MessageLoopProxy::current()), |
| 59 handler_(handler), | 79 handler_(handler), |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 150 new AudioInputController(event_handler, sync_writer, user_input_monitor)); | 170 new AudioInputController(event_handler, sync_writer, user_input_monitor)); |
| 151 controller->task_runner_ = task_runner; | 171 controller->task_runner_ = task_runner; |
| 152 | 172 |
| 153 // TODO(miu): See TODO at top of file. Until that's resolved, we need to | 173 // TODO(miu): See TODO at top of file. Until that's resolved, we need to |
| 154 // disable the error auto-detection here (since the audio mirroring | 174 // disable the error auto-detection here (since the audio mirroring |
| 155 // implementation will reliably report error and close events). Note, of | 175 // implementation will reliably report error and close events). Note, of |
| 156 // course, that we're assuming CreateForStream() has been called for the audio | 176 // course, that we're assuming CreateForStream() has been called for the audio |
| 157 // mirroring use case only. | 177 // mirroring use case only. |
| 158 if (!controller->task_runner_->PostTask( | 178 if (!controller->task_runner_->PostTask( |
| 159 FROM_HERE, | 179 FROM_HERE, |
| 160 base::Bind(&AudioInputController::DoCreateForStream, controller, | 180 base::Bind(&AudioInputController::DoCreateForStream, |
| 161 stream, false))) { | 181 controller, |
| 182 stream))) { | |
| 162 controller = NULL; | 183 controller = NULL; |
| 163 } | 184 } |
| 164 | 185 |
| 165 return controller; | 186 return controller; |
| 166 } | 187 } |
| 167 | 188 |
| 168 void AudioInputController::Record() { | 189 void AudioInputController::Record() { |
| 169 task_runner_->PostTask(FROM_HERE, base::Bind( | 190 task_runner_->PostTask(FROM_HERE, base::Bind( |
| 170 &AudioInputController::DoRecord, this)); | 191 &AudioInputController::DoRecord, this)); |
| 171 } | 192 } |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 202 audio_level_.reset(new media::AudioPowerMonitor( | 223 audio_level_.reset(new media::AudioPowerMonitor( |
| 203 params.sample_rate(), | 224 params.sample_rate(), |
| 204 TimeDelta::FromMilliseconds(kPowerMeasurementTimeConstantMilliseconds))); | 225 TimeDelta::FromMilliseconds(kPowerMeasurementTimeConstantMilliseconds))); |
| 205 audio_params_ = params; | 226 audio_params_ = params; |
| 206 #endif | 227 #endif |
| 207 | 228 |
| 208 // TODO(miu): See TODO at top of file. Until that's resolved, assume all | 229 // TODO(miu): See TODO at top of file. Until that's resolved, assume all |
| 209 // platform audio input requires the |no_data_timer_| be used to auto-detect | 230 // platform audio input requires the |no_data_timer_| be used to auto-detect |
| 210 // errors. In reality, probably only Windows needs to be treated as | 231 // errors. In reality, probably only Windows needs to be treated as |
| 211 // unreliable here. | 232 // unreliable here. |
| 212 DoCreateForStream(audio_manager->MakeAudioInputStream(params, device_id), | 233 DoCreateForStream(audio_manager->MakeAudioInputStream(params, device_id)); |
| 213 true); | |
| 214 } | 234 } |
| 215 | 235 |
| 216 void AudioInputController::DoCreateForStream( | 236 void AudioInputController::DoCreateForStream( |
| 217 AudioInputStream* stream_to_control, bool enable_nodata_timer) { | 237 AudioInputStream* stream_to_control) { |
| 218 DCHECK(task_runner_->BelongsToCurrentThread()); | 238 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 219 | 239 |
| 220 DCHECK(!stream_); | 240 DCHECK(!stream_); |
| 221 stream_ = stream_to_control; | 241 stream_ = stream_to_control; |
| 222 | 242 |
| 223 if (!stream_) { | 243 if (!stream_) { |
| 224 if (handler_) | 244 if (handler_) |
| 225 handler_->OnError(this, STREAM_CREATE_ERROR); | 245 handler_->OnError(this, STREAM_CREATE_ERROR); |
| 246 LogStreamOpenResult(CAPTURE_STARTUP_CREATE_STREAM_FAILED); | |
| 226 return; | 247 return; |
| 227 } | 248 } |
| 228 | 249 |
| 229 if (stream_ && !stream_->Open()) { | 250 if (stream_ && !stream_->Open()) { |
| 230 stream_->Close(); | 251 stream_->Close(); |
| 231 stream_ = NULL; | 252 stream_ = NULL; |
| 232 if (handler_) | 253 if (handler_) |
| 233 handler_->OnError(this, STREAM_OPEN_ERROR); | 254 handler_->OnError(this, STREAM_OPEN_ERROR); |
| 255 LogStreamOpenResult(CAPTURE_STARTUP_OPEN_STREAM_FAILED); | |
| 234 return; | 256 return; |
| 235 } | 257 } |
| 236 | 258 |
| 237 DCHECK(!no_data_timer_.get()); | 259 DCHECK(!no_data_timer_.get()); |
| 238 | 260 |
| 261 // Create the data timer which will call FirstCheckForNoData(). The timer | |
| 262 // is started in DoRecord() and restarted in each DoCheckForNoData() | |
| 263 // callback. | |
| 239 // The timer is enabled for logging purposes. The NO_DATA_ERROR triggered | 264 // The timer is enabled for logging purposes. The NO_DATA_ERROR triggered |
| 240 // from the timer must be ignored by the EventHandler. | 265 // from the timer must be ignored by the EventHandler. |
| 241 // TODO(henrika): remove usage of timer when it has been verified on Canary | 266 // TODO(henrika): remove usage of timer when it has been verified on Canary |
| 242 // that we are safe doing so. Goal is to get rid of |no_data_timer_| and | 267 // that we are safe doing so. Goal is to get rid of |no_data_timer_| and |
| 243 // everything that is tied to it. crbug.com/357569. | 268 // everything that is tied to it. crbug.com/357569. |
| 244 enable_nodata_timer = true; | 269 no_data_timer_.reset(new base::Timer( |
| 245 | 270 FROM_HERE, base::TimeDelta::FromSeconds(kTimerInitialIntervalSeconds), |
| 246 if (enable_nodata_timer) { | 271 base::Bind(&AudioInputController::FirstCheckForNoData, |
| 247 // Create the data timer which will call FirstCheckForNoData(). The timer | 272 base::Unretained(this)), false)); |
| 248 // is started in DoRecord() and restarted in each DoCheckForNoData() | |
| 249 // callback. | |
| 250 no_data_timer_.reset(new base::Timer( | |
| 251 FROM_HERE, base::TimeDelta::FromSeconds(kTimerInitialIntervalSeconds), | |
| 252 base::Bind(&AudioInputController::FirstCheckForNoData, | |
| 253 base::Unretained(this)), false)); | |
| 254 } else { | |
| 255 DVLOG(1) << "Disabled: timer check for no data."; | |
| 256 } | |
| 257 | 273 |
| 258 state_ = CREATED; | 274 state_ = CREATED; |
| 259 if (handler_) | 275 if (handler_) |
| 260 handler_->OnCreated(this); | 276 handler_->OnCreated(this); |
| 261 | 277 |
| 262 if (user_input_monitor_) { | 278 if (user_input_monitor_) { |
| 263 user_input_monitor_->EnableKeyPressMonitoring(); | 279 user_input_monitor_->EnableKeyPressMonitoring(); |
| 264 prev_key_down_count_ = user_input_monitor_->GetKeyPressCount(); | 280 prev_key_down_count_ = user_input_monitor_->GetKeyPressCount(); |
| 265 } | 281 } |
| 266 } | 282 } |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 345 | 361 |
| 346 // Ensure that the AGC state only can be modified before streaming starts. | 362 // Ensure that the AGC state only can be modified before streaming starts. |
| 347 if (state_ != CREATED) | 363 if (state_ != CREATED) |
| 348 return; | 364 return; |
| 349 | 365 |
| 350 stream_->SetAutomaticGainControl(enabled); | 366 stream_->SetAutomaticGainControl(enabled); |
| 351 } | 367 } |
| 352 | 368 |
| 353 void AudioInputController::FirstCheckForNoData() { | 369 void AudioInputController::FirstCheckForNoData() { |
| 354 DCHECK(task_runner_->BelongsToCurrentThread()); | 370 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 355 UMA_HISTOGRAM_BOOLEAN("Media.AudioInputControllerCaptureStartupSuccess", | 371 LogStreamOpenResult(GetDataIsActive() ? |
| 356 GetDataIsActive()); | 372 CAPTURE_STARTUP_OK : |
| 373 CAPTURE_STARTUP_NO_DATA_CALLBACK); | |
| 357 DoCheckForNoData(); | 374 DoCheckForNoData(); |
| 358 } | 375 } |
| 359 | 376 |
| 360 void AudioInputController::DoCheckForNoData() { | 377 void AudioInputController::DoCheckForNoData() { |
| 361 DCHECK(task_runner_->BelongsToCurrentThread()); | 378 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 362 | 379 |
| 363 if (!GetDataIsActive()) { | 380 if (!GetDataIsActive()) { |
| 364 // The data-is-active marker will be false only if it has been more than | 381 // The data-is-active marker will be false only if it has been more than |
| 365 // one second since a data packet was recorded. This can happen if a | 382 // one second since a data packet was recorded. This can happen if a |
| 366 // capture device has been removed or disabled. | 383 // capture device has been removed or disabled. |
| (...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 503 | 520 |
| 504 void AudioInputController::SetDataIsActive(bool enabled) { | 521 void AudioInputController::SetDataIsActive(bool enabled) { |
| 505 base::subtle::Release_Store(&data_is_active_, enabled); | 522 base::subtle::Release_Store(&data_is_active_, enabled); |
| 506 } | 523 } |
| 507 | 524 |
| 508 bool AudioInputController::GetDataIsActive() { | 525 bool AudioInputController::GetDataIsActive() { |
| 509 return (base::subtle::Acquire_Load(&data_is_active_) != false); | 526 return (base::subtle::Acquire_Load(&data_is_active_) != false); |
| 510 } | 527 } |
| 511 | 528 |
| 512 } // namespace media | 529 } // namespace media |
| OLD | NEW |