| 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 CAPTURE_STARTUP_RESULT_MAX |
| 55 // and update CAPTURE_STARTUP_RESULT_MAX. |
| 56 enum CaptureStartupResult { |
| 57 CAPTURE_STARTUP_NO_DATA_CALLBACK = 0, |
| 58 CAPTURE_STARTUP_OK = 1, |
| 59 CAPTURE_STARTUP_CREATE_STREAM_FAILED = 2, |
| 60 CAPTURE_STARTUP_OPEN_STREAM_FAILED = 3, |
| 61 CAPTURE_STARTUP_RESULT_MAX = CAPTURE_STARTUP_OPEN_STREAM_FAILED |
| 62 }; |
| 63 |
| 64 void LogCaptureStartupResult(CaptureStartupResult result) { |
| 65 UMA_HISTOGRAM_ENUMERATION("Media.AudioInputControllerCaptureStartupSuccess", |
| 66 result, |
| 67 CAPTURE_STARTUP_RESULT_MAX + 1); |
| 68 |
| 69 } |
| 70 |
| 50 namespace media { | 71 namespace media { |
| 51 | 72 |
| 52 // static | 73 // static |
| 53 AudioInputController::Factory* AudioInputController::factory_ = NULL; | 74 AudioInputController::Factory* AudioInputController::factory_ = NULL; |
| 54 | 75 |
| 55 AudioInputController::AudioInputController(EventHandler* handler, | 76 AudioInputController::AudioInputController(EventHandler* handler, |
| 56 SyncWriter* sync_writer, | 77 SyncWriter* sync_writer, |
| 57 UserInputMonitor* user_input_monitor) | 78 UserInputMonitor* user_input_monitor) |
| 58 : creator_task_runner_(base::MessageLoopProxy::current()), | 79 : creator_task_runner_(base::MessageLoopProxy::current()), |
| 59 handler_(handler), | 80 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)); | 171 new AudioInputController(event_handler, sync_writer, user_input_monitor)); |
| 151 controller->task_runner_ = task_runner; | 172 controller->task_runner_ = task_runner; |
| 152 | 173 |
| 153 // TODO(miu): See TODO at top of file. Until that's resolved, we need to | 174 // 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 | 175 // disable the error auto-detection here (since the audio mirroring |
| 155 // implementation will reliably report error and close events). Note, of | 176 // implementation will reliably report error and close events). Note, of |
| 156 // course, that we're assuming CreateForStream() has been called for the audio | 177 // course, that we're assuming CreateForStream() has been called for the audio |
| 157 // mirroring use case only. | 178 // mirroring use case only. |
| 158 if (!controller->task_runner_->PostTask( | 179 if (!controller->task_runner_->PostTask( |
| 159 FROM_HERE, | 180 FROM_HERE, |
| 160 base::Bind(&AudioInputController::DoCreateForStream, controller, | 181 base::Bind(&AudioInputController::DoCreateForStream, |
| 161 stream, false))) { | 182 controller, |
| 183 stream))) { |
| 162 controller = NULL; | 184 controller = NULL; |
| 163 } | 185 } |
| 164 | 186 |
| 165 return controller; | 187 return controller; |
| 166 } | 188 } |
| 167 | 189 |
| 168 void AudioInputController::Record() { | 190 void AudioInputController::Record() { |
| 169 task_runner_->PostTask(FROM_HERE, base::Bind( | 191 task_runner_->PostTask(FROM_HERE, base::Bind( |
| 170 &AudioInputController::DoRecord, this)); | 192 &AudioInputController::DoRecord, this)); |
| 171 } | 193 } |
| (...skipping 30 matching lines...) Expand all Loading... |
| 202 audio_level_.reset(new media::AudioPowerMonitor( | 224 audio_level_.reset(new media::AudioPowerMonitor( |
| 203 params.sample_rate(), | 225 params.sample_rate(), |
| 204 TimeDelta::FromMilliseconds(kPowerMeasurementTimeConstantMilliseconds))); | 226 TimeDelta::FromMilliseconds(kPowerMeasurementTimeConstantMilliseconds))); |
| 205 audio_params_ = params; | 227 audio_params_ = params; |
| 206 #endif | 228 #endif |
| 207 | 229 |
| 208 // TODO(miu): See TODO at top of file. Until that's resolved, assume all | 230 // 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 | 231 // 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 | 232 // errors. In reality, probably only Windows needs to be treated as |
| 211 // unreliable here. | 233 // unreliable here. |
| 212 DoCreateForStream(audio_manager->MakeAudioInputStream(params, device_id), | 234 DoCreateForStream(audio_manager->MakeAudioInputStream(params, device_id)); |
| 213 true); | |
| 214 } | 235 } |
| 215 | 236 |
| 216 void AudioInputController::DoCreateForStream( | 237 void AudioInputController::DoCreateForStream( |
| 217 AudioInputStream* stream_to_control, bool enable_nodata_timer) { | 238 AudioInputStream* stream_to_control) { |
| 218 DCHECK(task_runner_->BelongsToCurrentThread()); | 239 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 219 | 240 |
| 220 DCHECK(!stream_); | 241 DCHECK(!stream_); |
| 221 stream_ = stream_to_control; | 242 stream_ = stream_to_control; |
| 222 | 243 |
| 223 if (!stream_) { | 244 if (!stream_) { |
| 224 if (handler_) | 245 if (handler_) |
| 225 handler_->OnError(this, STREAM_CREATE_ERROR); | 246 handler_->OnError(this, STREAM_CREATE_ERROR); |
| 247 LogCaptureStartupResult(CAPTURE_STARTUP_CREATE_STREAM_FAILED); |
| 226 return; | 248 return; |
| 227 } | 249 } |
| 228 | 250 |
| 229 if (stream_ && !stream_->Open()) { | 251 if (stream_ && !stream_->Open()) { |
| 230 stream_->Close(); | 252 stream_->Close(); |
| 231 stream_ = NULL; | 253 stream_ = NULL; |
| 232 if (handler_) | 254 if (handler_) |
| 233 handler_->OnError(this, STREAM_OPEN_ERROR); | 255 handler_->OnError(this, STREAM_OPEN_ERROR); |
| 256 LogCaptureStartupResult(CAPTURE_STARTUP_OPEN_STREAM_FAILED); |
| 234 return; | 257 return; |
| 235 } | 258 } |
| 236 | 259 |
| 237 DCHECK(!no_data_timer_.get()); | 260 DCHECK(!no_data_timer_.get()); |
| 238 | 261 |
| 262 // Create the data timer which will call FirstCheckForNoData(). The timer |
| 263 // is started in DoRecord() and restarted in each DoCheckForNoData() |
| 264 // callback. |
| 239 // The timer is enabled for logging purposes. The NO_DATA_ERROR triggered | 265 // The timer is enabled for logging purposes. The NO_DATA_ERROR triggered |
| 240 // from the timer must be ignored by the EventHandler. | 266 // from the timer must be ignored by the EventHandler. |
| 241 // TODO(henrika): remove usage of timer when it has been verified on Canary | 267 // 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 | 268 // 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. | 269 // everything that is tied to it. crbug.com/357569. |
| 244 enable_nodata_timer = true; | 270 no_data_timer_.reset(new base::Timer( |
| 245 | 271 FROM_HERE, base::TimeDelta::FromSeconds(kTimerInitialIntervalSeconds), |
| 246 if (enable_nodata_timer) { | 272 base::Bind(&AudioInputController::FirstCheckForNoData, |
| 247 // Create the data timer which will call FirstCheckForNoData(). The timer | 273 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 | 274 |
| 258 state_ = CREATED; | 275 state_ = CREATED; |
| 259 if (handler_) | 276 if (handler_) |
| 260 handler_->OnCreated(this); | 277 handler_->OnCreated(this); |
| 261 | 278 |
| 262 if (user_input_monitor_) { | 279 if (user_input_monitor_) { |
| 263 user_input_monitor_->EnableKeyPressMonitoring(); | 280 user_input_monitor_->EnableKeyPressMonitoring(); |
| 264 prev_key_down_count_ = user_input_monitor_->GetKeyPressCount(); | 281 prev_key_down_count_ = user_input_monitor_->GetKeyPressCount(); |
| 265 } | 282 } |
| 266 } | 283 } |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 345 | 362 |
| 346 // Ensure that the AGC state only can be modified before streaming starts. | 363 // Ensure that the AGC state only can be modified before streaming starts. |
| 347 if (state_ != CREATED) | 364 if (state_ != CREATED) |
| 348 return; | 365 return; |
| 349 | 366 |
| 350 stream_->SetAutomaticGainControl(enabled); | 367 stream_->SetAutomaticGainControl(enabled); |
| 351 } | 368 } |
| 352 | 369 |
| 353 void AudioInputController::FirstCheckForNoData() { | 370 void AudioInputController::FirstCheckForNoData() { |
| 354 DCHECK(task_runner_->BelongsToCurrentThread()); | 371 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 355 UMA_HISTOGRAM_BOOLEAN("Media.AudioInputControllerCaptureStartupSuccess", | 372 LogCaptureStartupResult(GetDataIsActive() ? |
| 356 GetDataIsActive()); | 373 CAPTURE_STARTUP_OK : |
| 374 CAPTURE_STARTUP_NO_DATA_CALLBACK); |
| 357 DoCheckForNoData(); | 375 DoCheckForNoData(); |
| 358 } | 376 } |
| 359 | 377 |
| 360 void AudioInputController::DoCheckForNoData() { | 378 void AudioInputController::DoCheckForNoData() { |
| 361 DCHECK(task_runner_->BelongsToCurrentThread()); | 379 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 362 | 380 |
| 363 if (!GetDataIsActive()) { | 381 if (!GetDataIsActive()) { |
| 364 // The data-is-active marker will be false only if it has been more than | 382 // 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 | 383 // one second since a data packet was recorded. This can happen if a |
| 366 // capture device has been removed or disabled. | 384 // capture device has been removed or disabled. |
| (...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 503 | 521 |
| 504 void AudioInputController::SetDataIsActive(bool enabled) { | 522 void AudioInputController::SetDataIsActive(bool enabled) { |
| 505 base::subtle::Release_Store(&data_is_active_, enabled); | 523 base::subtle::Release_Store(&data_is_active_, enabled); |
| 506 } | 524 } |
| 507 | 525 |
| 508 bool AudioInputController::GetDataIsActive() { | 526 bool AudioInputController::GetDataIsActive() { |
| 509 return (base::subtle::Acquire_Load(&data_is_active_) != false); | 527 return (base::subtle::Acquire_Load(&data_is_active_) != false); |
| 510 } | 528 } |
| 511 | 529 |
| 512 } // namespace media | 530 } // namespace media |
| OLD | NEW |