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 |