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 |