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 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
67 result, | 67 result, |
68 CAPTURE_STARTUP_RESULT_MAX + 1); | 68 CAPTURE_STARTUP_RESULT_MAX + 1); |
69 | 69 |
70 } | 70 } |
71 | 71 |
72 namespace media { | 72 namespace media { |
73 | 73 |
74 // static | 74 // static |
75 AudioInputController::Factory* AudioInputController::factory_ = NULL; | 75 AudioInputController::Factory* AudioInputController::factory_ = NULL; |
76 | 76 |
77 AudioInputController::AudioInputController(EventHandler* handler, | 77 AudioInputController::AudioInputController(AudioManager* audio_manager, |
78 EventHandler* handler, | |
78 SyncWriter* sync_writer, | 79 SyncWriter* sync_writer, |
79 UserInputMonitor* user_input_monitor) | 80 UserInputMonitor* user_input_monitor) |
80 : creator_task_runner_(base::MessageLoopProxy::current()), | 81 : creator_task_runner_(base::MessageLoopProxy::current()), |
81 handler_(handler), | 82 handler_(handler), |
83 audio_manager_(audio_manager), | |
82 stream_(NULL), | 84 stream_(NULL), |
83 data_is_active_(false), | 85 data_is_active_(false), |
84 state_(CLOSED), | 86 state_(CLOSED), |
85 sync_writer_(sync_writer), | 87 sync_writer_(sync_writer), |
86 max_volume_(0.0), | 88 max_volume_(0.0), |
87 user_input_monitor_(user_input_monitor), | 89 user_input_monitor_(user_input_monitor), |
88 #if defined(AUDIO_POWER_MONITORING) | 90 #if defined(AUDIO_POWER_MONITORING) |
89 log_silence_state_(false), | 91 log_silence_state_(false), |
90 silence_state_(SILENCE_STATE_NO_MEASUREMENT), | 92 silence_state_(SILENCE_STATE_NO_MEASUREMENT), |
91 #endif | 93 #endif |
(...skipping 14 matching lines...) Expand all Loading... | |
106 UserInputMonitor* user_input_monitor) { | 108 UserInputMonitor* user_input_monitor) { |
107 DCHECK(audio_manager); | 109 DCHECK(audio_manager); |
108 | 110 |
109 if (!params.IsValid() || (params.channels() > kMaxInputChannels)) | 111 if (!params.IsValid() || (params.channels() > kMaxInputChannels)) |
110 return NULL; | 112 return NULL; |
111 | 113 |
112 if (factory_) { | 114 if (factory_) { |
113 return factory_->Create( | 115 return factory_->Create( |
114 audio_manager, event_handler, params, user_input_monitor); | 116 audio_manager, event_handler, params, user_input_monitor); |
115 } | 117 } |
116 scoped_refptr<AudioInputController> controller( | 118 scoped_refptr<AudioInputController> controller(new AudioInputController( |
117 new AudioInputController(event_handler, NULL, user_input_monitor)); | 119 audio_manager, event_handler, NULL, user_input_monitor)); |
118 | 120 |
119 controller->task_runner_ = audio_manager->GetTaskRunner(); | 121 controller->task_runner_ = audio_manager->GetTaskRunner(); |
120 | 122 |
121 // Create and open a new audio input stream from the existing | 123 // Create and open a new audio input stream from the existing |
122 // audio-device thread. | 124 // audio-device thread. |
123 if (!controller->task_runner_->PostTask(FROM_HERE, | 125 if (!controller->task_runner_->PostTask( |
124 base::Bind(&AudioInputController::DoCreate, controller, | 126 FROM_HERE, |
125 base::Unretained(audio_manager), params, device_id))) { | 127 base::Bind(&AudioInputController::DoCreate, |
128 controller, | |
129 params, | |
130 device_id))) { | |
126 controller = NULL; | 131 controller = NULL; |
127 } | 132 } |
128 | 133 |
129 return controller; | 134 return controller; |
130 } | 135 } |
131 | 136 |
132 // static | 137 // static |
133 scoped_refptr<AudioInputController> AudioInputController::CreateLowLatency( | 138 scoped_refptr<AudioInputController> AudioInputController::CreateLowLatency( |
134 AudioManager* audio_manager, | 139 AudioManager* audio_manager, |
135 EventHandler* event_handler, | 140 EventHandler* event_handler, |
136 const AudioParameters& params, | 141 const AudioParameters& params, |
137 const std::string& device_id, | 142 const std::string& device_id, |
138 SyncWriter* sync_writer, | 143 SyncWriter* sync_writer, |
139 UserInputMonitor* user_input_monitor) { | 144 UserInputMonitor* user_input_monitor) { |
140 DCHECK(audio_manager); | 145 DCHECK(audio_manager); |
141 DCHECK(sync_writer); | 146 DCHECK(sync_writer); |
142 | 147 |
143 if (!params.IsValid() || (params.channels() > kMaxInputChannels)) | 148 if (!params.IsValid() || (params.channels() > kMaxInputChannels)) |
144 return NULL; | 149 return NULL; |
145 | 150 |
146 // Create the AudioInputController object and ensure that it runs on | 151 // Create the AudioInputController object and ensure that it runs on |
147 // the audio-manager thread. | 152 // the audio-manager thread. |
148 scoped_refptr<AudioInputController> controller( | 153 scoped_refptr<AudioInputController> controller(new AudioInputController( |
149 new AudioInputController(event_handler, sync_writer, user_input_monitor)); | 154 audio_manager, event_handler, sync_writer, user_input_monitor)); |
150 controller->task_runner_ = audio_manager->GetTaskRunner(); | 155 controller->task_runner_ = audio_manager->GetTaskRunner(); |
151 | 156 |
152 // Create and open a new audio input stream from the existing | 157 // Create and open a new audio input stream from the existing |
153 // audio-device thread. Use the provided audio-input device. | 158 // audio-device thread. Use the provided audio-input device. |
154 if (!controller->task_runner_->PostTask(FROM_HERE, | 159 if (!controller->task_runner_->PostTask( |
155 base::Bind(&AudioInputController::DoCreateForLowLatency, controller, | 160 FROM_HERE, |
156 base::Unretained(audio_manager), params, device_id))) { | 161 base::Bind(&AudioInputController::DoCreate, |
162 controller, | |
163 params, | |
164 device_id))) { | |
157 controller = NULL; | 165 controller = NULL; |
158 } | 166 } |
159 | 167 |
160 return controller; | 168 return controller; |
161 } | 169 } |
162 | 170 |
163 // static | 171 // static |
164 scoped_refptr<AudioInputController> AudioInputController::CreateForStream( | 172 scoped_refptr<AudioInputController> AudioInputController::CreateForStream( |
165 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, | 173 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, |
166 EventHandler* event_handler, | 174 EventHandler* event_handler, |
167 AudioInputStream* stream, | 175 AudioInputStream* stream, |
168 SyncWriter* sync_writer, | 176 SyncWriter* sync_writer, |
169 UserInputMonitor* user_input_monitor) { | 177 UserInputMonitor* user_input_monitor) { |
170 DCHECK(sync_writer); | 178 DCHECK(sync_writer); |
171 DCHECK(stream); | 179 DCHECK(stream); |
172 | 180 |
173 // Create the AudioInputController object and ensure that it runs on | 181 // Create the AudioInputController object and ensure that it runs on |
174 // the audio-manager thread. | 182 // the audio-manager thread. |
175 scoped_refptr<AudioInputController> controller( | 183 scoped_refptr<AudioInputController> controller(new AudioInputController( |
176 new AudioInputController(event_handler, sync_writer, user_input_monitor)); | 184 NULL, event_handler, sync_writer, user_input_monitor)); |
177 controller->task_runner_ = task_runner; | 185 controller->task_runner_ = task_runner; |
178 | 186 |
179 // TODO(miu): See TODO at top of file. Until that's resolved, we need to | 187 // TODO(miu): See TODO at top of file. Until that's resolved, we need to |
180 // disable the error auto-detection here (since the audio mirroring | 188 // disable the error auto-detection here (since the audio mirroring |
181 // implementation will reliably report error and close events). Note, of | 189 // implementation will reliably report error and close events). Note, of |
182 // course, that we're assuming CreateForStream() has been called for the audio | 190 // course, that we're assuming CreateForStream() has been called for the audio |
183 // mirroring use case only. | 191 // mirroring use case only. |
184 if (!controller->task_runner_->PostTask( | 192 if (!controller->task_runner_->PostTask( |
185 FROM_HERE, | 193 FROM_HERE, |
186 base::Bind(&AudioInputController::DoCreateForStream, | 194 base::Bind(&AudioInputController::DoCreateForStream, |
(...skipping 21 matching lines...) Expand all Loading... | |
208 void AudioInputController::SetVolume(double volume) { | 216 void AudioInputController::SetVolume(double volume) { |
209 task_runner_->PostTask(FROM_HERE, base::Bind( | 217 task_runner_->PostTask(FROM_HERE, base::Bind( |
210 &AudioInputController::DoSetVolume, this, volume)); | 218 &AudioInputController::DoSetVolume, this, volume)); |
211 } | 219 } |
212 | 220 |
213 void AudioInputController::SetAutomaticGainControl(bool enabled) { | 221 void AudioInputController::SetAutomaticGainControl(bool enabled) { |
214 task_runner_->PostTask(FROM_HERE, base::Bind( | 222 task_runner_->PostTask(FROM_HERE, base::Bind( |
215 &AudioInputController::DoSetAutomaticGainControl, this, enabled)); | 223 &AudioInputController::DoSetAutomaticGainControl, this, enabled)); |
216 } | 224 } |
217 | 225 |
218 void AudioInputController::DoCreate(AudioManager* audio_manager, | 226 void AudioInputController::DoCreate(const AudioParameters& params, |
219 const AudioParameters& params, | |
220 const std::string& device_id) { | 227 const std::string& device_id) { |
221 DCHECK(task_runner_->BelongsToCurrentThread()); | 228 DCHECK(task_runner_->BelongsToCurrentThread()); |
222 SCOPED_UMA_HISTOGRAM_TIMER("Media.AudioInputController.CreateTime"); | 229 SCOPED_UMA_HISTOGRAM_TIMER("Media.AudioInputController.CreateTime"); |
230 if (handler_) { | |
231 handler_->OnLog(this, "AIC::DoCreate()"); | |
232 } | |
223 | 233 |
224 #if defined(AUDIO_POWER_MONITORING) | 234 #if defined(AUDIO_POWER_MONITORING) |
225 // Create the audio (power) level meter given the provided audio parameters. | 235 // Create the audio (power) level meter given the provided audio parameters. |
226 // An AudioBus is also needed to wrap the raw data buffer from the native | 236 // An AudioBus is also needed to wrap the raw data buffer from the native |
227 // layer to match AudioPowerMonitor::Scan(). | 237 // layer to match AudioPowerMonitor::Scan(). |
228 // TODO(henrika): Remove use of extra AudioBus. See http://crbug.com/375155. | 238 // TODO(henrika): Remove use of extra AudioBus. See http://crbug.com/375155. |
229 audio_level_.reset(new media::AudioPowerMonitor( | 239 audio_level_.reset(new media::AudioPowerMonitor( |
230 params.sample_rate(), | 240 params.sample_rate(), |
231 TimeDelta::FromMilliseconds(kPowerMeasurementTimeConstantMilliseconds))); | 241 TimeDelta::FromMilliseconds(kPowerMeasurementTimeConstantMilliseconds))); |
232 audio_params_ = params; | 242 audio_params_ = params; |
233 silence_state_ = SILENCE_STATE_NO_MEASUREMENT; | 243 silence_state_ = SILENCE_STATE_NO_MEASUREMENT; |
234 #endif | 244 #endif |
235 | 245 |
246 if (audio_manager_) | |
247 audio_manager_->AddStateChangeListener(this); | |
248 | |
236 // TODO(miu): See TODO at top of file. Until that's resolved, assume all | 249 // TODO(miu): See TODO at top of file. Until that's resolved, assume all |
237 // platform audio input requires the |no_data_timer_| be used to auto-detect | 250 // platform audio input requires the |no_data_timer_| be used to auto-detect |
238 // errors. In reality, probably only Windows needs to be treated as | 251 // errors. In reality, probably only Windows needs to be treated as |
239 // unreliable here. | 252 // unreliable here. |
240 DoCreateForStream(audio_manager->MakeAudioInputStream(params, device_id)); | 253 DoCreateForStream(audio_manager_->MakeAudioInputStream(params, device_id)); |
241 } | |
242 | |
243 void AudioInputController::DoCreateForLowLatency(AudioManager* audio_manager, | |
244 const AudioParameters& params, | |
245 const std::string& device_id) { | |
246 DCHECK(task_runner_->BelongsToCurrentThread()); | |
247 | |
248 #if defined(AUDIO_POWER_MONITORING) | |
249 // We only log silence state UMA stats for low latency mode and if we use a | |
250 // real device. | |
251 if (params.format() != AudioParameters::AUDIO_FAKE) | |
252 log_silence_state_ = true; | |
253 #endif | |
254 | |
255 DoCreate(audio_manager, params, device_id); | |
256 } | 254 } |
257 | 255 |
258 void AudioInputController::DoCreateForStream( | 256 void AudioInputController::DoCreateForStream( |
259 AudioInputStream* stream_to_control) { | 257 AudioInputStream* stream_to_control) { |
260 DCHECK(task_runner_->BelongsToCurrentThread()); | 258 DCHECK(task_runner_->BelongsToCurrentThread()); |
261 | 259 |
262 DCHECK(!stream_); | 260 DCHECK(!stream_); |
263 stream_ = stream_to_control; | 261 stream_ = stream_to_control; |
264 | 262 |
265 if (!stream_) { | 263 if (!stream_) { |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
308 SCOPED_UMA_HISTOGRAM_TIMER("Media.AudioInputController.RecordTime"); | 306 SCOPED_UMA_HISTOGRAM_TIMER("Media.AudioInputController.RecordTime"); |
309 | 307 |
310 if (state_ != CREATED) | 308 if (state_ != CREATED) |
311 return; | 309 return; |
312 | 310 |
313 { | 311 { |
314 base::AutoLock auto_lock(lock_); | 312 base::AutoLock auto_lock(lock_); |
315 state_ = RECORDING; | 313 state_ = RECORDING; |
316 } | 314 } |
317 | 315 |
316 if (handler_) | |
317 handler_->OnLog(this, "AIC::DoRecord"); | |
318 | |
318 if (no_data_timer_) { | 319 if (no_data_timer_) { |
319 // Start the data timer. Once |kTimerResetIntervalSeconds| have passed, | 320 // Start the data timer. Once |kTimerResetIntervalSeconds| have passed, |
320 // a callback to FirstCheckForNoData() is made. | 321 // a callback to FirstCheckForNoData() is made. |
321 no_data_timer_->Reset(); | 322 no_data_timer_->Reset(); |
322 } | 323 } |
323 | 324 |
324 stream_->Start(this); | 325 stream_->Start(this); |
325 if (handler_) | 326 if (handler_) |
326 handler_->OnRecording(this); | 327 handler_->OnRecording(this); |
327 } | 328 } |
328 | 329 |
329 void AudioInputController::DoClose() { | 330 void AudioInputController::DoClose() { |
330 DCHECK(task_runner_->BelongsToCurrentThread()); | 331 DCHECK(task_runner_->BelongsToCurrentThread()); |
331 SCOPED_UMA_HISTOGRAM_TIMER("Media.AudioInputController.CloseTime"); | 332 SCOPED_UMA_HISTOGRAM_TIMER("Media.AudioInputController.CloseTime"); |
332 | 333 |
333 if (state_ == CLOSED) | 334 if (state_ == CLOSED) |
334 return; | 335 return; |
335 | 336 |
337 if (handler_) | |
338 handler_->OnLog(this, "AIC::DoClose"); | |
339 | |
336 // Delete the timer on the same thread that created it. | 340 // Delete the timer on the same thread that created it. |
337 no_data_timer_.reset(); | 341 no_data_timer_.reset(); |
338 | 342 |
339 DoStopCloseAndClearStream(); | 343 DoStopCloseAndClearStream(); |
340 SetDataIsActive(false); | 344 SetDataIsActive(false); |
341 | 345 |
346 if (audio_manager_) | |
347 audio_manager_->RemoveStateChangeListener(this); | |
348 | |
342 if (SharedMemoryAndSyncSocketMode()) | 349 if (SharedMemoryAndSyncSocketMode()) |
343 sync_writer_->Close(); | 350 sync_writer_->Close(); |
344 | 351 |
345 if (user_input_monitor_) | 352 if (user_input_monitor_) |
346 user_input_monitor_->DisableKeyPressMonitoring(); | 353 user_input_monitor_->DisableKeyPressMonitoring(); |
347 | 354 |
348 #if defined(AUDIO_POWER_MONITORING) | 355 #if defined(AUDIO_POWER_MONITORING) |
349 // Send UMA stats if enabled. | 356 // Send UMA stats if enabled. |
350 if (log_silence_state_) | 357 if (log_silence_state_) |
351 LogSilenceState(silence_state_); | 358 LogSilenceState(silence_state_); |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
393 return; | 400 return; |
394 | 401 |
395 stream_->SetAutomaticGainControl(enabled); | 402 stream_->SetAutomaticGainControl(enabled); |
396 } | 403 } |
397 | 404 |
398 void AudioInputController::FirstCheckForNoData() { | 405 void AudioInputController::FirstCheckForNoData() { |
399 DCHECK(task_runner_->BelongsToCurrentThread()); | 406 DCHECK(task_runner_->BelongsToCurrentThread()); |
400 LogCaptureStartupResult(GetDataIsActive() ? | 407 LogCaptureStartupResult(GetDataIsActive() ? |
401 CAPTURE_STARTUP_OK : | 408 CAPTURE_STARTUP_OK : |
402 CAPTURE_STARTUP_NO_DATA_CALLBACK); | 409 CAPTURE_STARTUP_NO_DATA_CALLBACK); |
410 if (handler_) { | |
411 GetDataIsActive() | |
tommi (sloooow) - chröme
2014/08/26 11:42:30
instead of having two call sites for OnLog, do the
henrika (OOO until Aug 14)
2014/08/27 13:44:05
Done.
| |
412 ? handler_->OnLog(this, "AIC::FirstCheckForNoData => data is active") | |
413 : handler_->OnLog(this, | |
414 "AIC::FirstCheckForNoData => data is NOT active"); | |
415 } | |
403 DoCheckForNoData(); | 416 DoCheckForNoData(); |
404 } | 417 } |
405 | 418 |
406 void AudioInputController::DoCheckForNoData() { | 419 void AudioInputController::DoCheckForNoData() { |
407 DCHECK(task_runner_->BelongsToCurrentThread()); | 420 DCHECK(task_runner_->BelongsToCurrentThread()); |
408 | 421 |
409 if (!GetDataIsActive()) { | 422 if (!GetDataIsActive()) { |
410 // The data-is-active marker will be false only if it has been more than | 423 // The data-is-active marker will be false only if it has been more than |
411 // one second since a data packet was recorded. This can happen if a | 424 // one second since a data packet was recorded. This can happen if a |
412 // capture device has been removed or disabled. | 425 // capture device has been removed or disabled. |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
521 "AIC::OnData: average audio level=%.2f dBFS", level_dbfs); | 534 "AIC::OnData: average audio level=%.2f dBFS", level_dbfs); |
522 static const float kSilenceThresholdDBFS = -72.24719896f; | 535 static const float kSilenceThresholdDBFS = -72.24719896f; |
523 if (level_dbfs < kSilenceThresholdDBFS) | 536 if (level_dbfs < kSilenceThresholdDBFS) |
524 log_string += " <=> no audio input!"; | 537 log_string += " <=> no audio input!"; |
525 handler_->OnLog(this, log_string); | 538 handler_->OnLog(this, log_string); |
526 | 539 |
527 UpdateSilenceState(level_dbfs < kSilenceThresholdDBFS); | 540 UpdateSilenceState(level_dbfs < kSilenceThresholdDBFS); |
528 #endif | 541 #endif |
529 } | 542 } |
530 | 543 |
544 void AudioInputController::OnStateChange(const std::string& state) { | |
545 DCHECK(task_runner_->BelongsToCurrentThread()); | |
546 if (handler_) | |
547 handler_->OnLog(this, state); | |
548 } | |
549 | |
531 void AudioInputController::OnError(AudioInputStream* stream) { | 550 void AudioInputController::OnError(AudioInputStream* stream) { |
532 // Handle error on the audio-manager thread. | 551 // Handle error on the audio-manager thread. |
533 task_runner_->PostTask(FROM_HERE, base::Bind( | 552 task_runner_->PostTask(FROM_HERE, base::Bind( |
534 &AudioInputController::DoReportError, this)); | 553 &AudioInputController::DoReportError, this)); |
535 } | 554 } |
536 | 555 |
537 void AudioInputController::DoStopCloseAndClearStream() { | 556 void AudioInputController::DoStopCloseAndClearStream() { |
538 DCHECK(task_runner_->BelongsToCurrentThread()); | 557 DCHECK(task_runner_->BelongsToCurrentThread()); |
539 | 558 |
540 // Allow calling unconditionally and bail if we don't have a stream to close. | 559 // Allow calling unconditionally and bail if we don't have a stream to close. |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
580 } | 599 } |
581 | 600 |
582 void AudioInputController::LogSilenceState(SilenceState value) { | 601 void AudioInputController::LogSilenceState(SilenceState value) { |
583 UMA_HISTOGRAM_ENUMERATION("Media.AudioInputControllerSessionSilenceReport", | 602 UMA_HISTOGRAM_ENUMERATION("Media.AudioInputControllerSessionSilenceReport", |
584 value, | 603 value, |
585 SILENCE_STATE_MAX + 1); | 604 SILENCE_STATE_MAX + 1); |
586 } | 605 } |
587 #endif | 606 #endif |
588 | 607 |
589 } // namespace media | 608 } // namespace media |
OLD | NEW |