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/string_number_conversions.h" | 8 #include "base/strings/string_number_conversions.h" |
9 #include "base/strings/stringprintf.h" | 9 #include "base/strings/stringprintf.h" |
10 #include "base/threading/thread_restrictions.h" | 10 #include "base/threading/thread_restrictions.h" |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
110 | 110 |
111 } | 111 } |
112 | 112 |
113 namespace media { | 113 namespace media { |
114 | 114 |
115 // static | 115 // static |
116 AudioInputController::Factory* AudioInputController::factory_ = NULL; | 116 AudioInputController::Factory* AudioInputController::factory_ = NULL; |
117 | 117 |
118 AudioInputController::AudioInputController(EventHandler* handler, | 118 AudioInputController::AudioInputController(EventHandler* handler, |
119 SyncWriter* sync_writer, | 119 SyncWriter* sync_writer, |
120 UserInputMonitor* user_input_monitor) | 120 UserInputMonitor* user_input_monitor, |
| 121 const bool agc_is_enabled) |
121 : creator_task_runner_(base::MessageLoopProxy::current()), | 122 : creator_task_runner_(base::MessageLoopProxy::current()), |
122 handler_(handler), | 123 handler_(handler), |
123 stream_(NULL), | 124 stream_(NULL), |
124 data_is_active_(false), | 125 data_is_active_(false), |
125 state_(CLOSED), | 126 state_(CLOSED), |
126 sync_writer_(sync_writer), | 127 sync_writer_(sync_writer), |
127 max_volume_(0.0), | 128 max_volume_(0.0), |
128 user_input_monitor_(user_input_monitor), | 129 user_input_monitor_(user_input_monitor), |
| 130 agc_is_enabled_(agc_is_enabled), |
129 #if defined(AUDIO_POWER_MONITORING) | 131 #if defined(AUDIO_POWER_MONITORING) |
130 power_measurement_is_enabled_(false), | 132 power_measurement_is_enabled_(false), |
131 log_silence_state_(false), | 133 log_silence_state_(false), |
132 silence_state_(SILENCE_STATE_NO_MEASUREMENT), | 134 silence_state_(SILENCE_STATE_NO_MEASUREMENT), |
133 #endif | 135 #endif |
134 prev_key_down_count_(0) { | 136 prev_key_down_count_(0) { |
135 DCHECK(creator_task_runner_.get()); | 137 DCHECK(creator_task_runner_.get()); |
136 } | 138 } |
137 | 139 |
138 AudioInputController::~AudioInputController() { | 140 AudioInputController::~AudioInputController() { |
(...skipping 10 matching lines...) Expand all Loading... |
149 DCHECK(audio_manager); | 151 DCHECK(audio_manager); |
150 | 152 |
151 if (!params.IsValid() || (params.channels() > kMaxInputChannels)) | 153 if (!params.IsValid() || (params.channels() > kMaxInputChannels)) |
152 return NULL; | 154 return NULL; |
153 | 155 |
154 if (factory_) { | 156 if (factory_) { |
155 return factory_->Create( | 157 return factory_->Create( |
156 audio_manager, event_handler, params, user_input_monitor); | 158 audio_manager, event_handler, params, user_input_monitor); |
157 } | 159 } |
158 scoped_refptr<AudioInputController> controller( | 160 scoped_refptr<AudioInputController> controller( |
159 new AudioInputController(event_handler, NULL, user_input_monitor)); | 161 new AudioInputController(event_handler, NULL, user_input_monitor, false)); |
160 | 162 |
161 controller->task_runner_ = audio_manager->GetTaskRunner(); | 163 controller->task_runner_ = audio_manager->GetTaskRunner(); |
162 | 164 |
163 // Create and open a new audio input stream from the existing | 165 // Create and open a new audio input stream from the existing |
164 // audio-device thread. | 166 // audio-device thread. |
165 if (!controller->task_runner_->PostTask( | 167 if (!controller->task_runner_->PostTask( |
166 FROM_HERE, | 168 FROM_HERE, |
167 base::Bind(&AudioInputController::DoCreate, | 169 base::Bind(&AudioInputController::DoCreate, |
168 controller, | 170 controller, |
169 base::Unretained(audio_manager), | 171 base::Unretained(audio_manager), |
170 params, | 172 params, |
171 device_id))) { | 173 device_id))) { |
172 controller = NULL; | 174 controller = NULL; |
173 } | 175 } |
174 | 176 |
175 return controller; | 177 return controller; |
176 } | 178 } |
177 | 179 |
178 // static | 180 // static |
179 scoped_refptr<AudioInputController> AudioInputController::CreateLowLatency( | 181 scoped_refptr<AudioInputController> AudioInputController::CreateLowLatency( |
180 AudioManager* audio_manager, | 182 AudioManager* audio_manager, |
181 EventHandler* event_handler, | 183 EventHandler* event_handler, |
182 const AudioParameters& params, | 184 const AudioParameters& params, |
183 const std::string& device_id, | 185 const std::string& device_id, |
184 SyncWriter* sync_writer, | 186 SyncWriter* sync_writer, |
185 UserInputMonitor* user_input_monitor) { | 187 UserInputMonitor* user_input_monitor, |
| 188 const bool agc_is_enabled) { |
186 DCHECK(audio_manager); | 189 DCHECK(audio_manager); |
187 DCHECK(sync_writer); | 190 DCHECK(sync_writer); |
188 | 191 |
189 if (!params.IsValid() || (params.channels() > kMaxInputChannels)) | 192 if (!params.IsValid() || (params.channels() > kMaxInputChannels)) |
190 return NULL; | 193 return NULL; |
191 | 194 |
192 // Create the AudioInputController object and ensure that it runs on | 195 // Create the AudioInputController object and ensure that it runs on |
193 // the audio-manager thread. | 196 // the audio-manager thread. |
194 scoped_refptr<AudioInputController> controller( | 197 scoped_refptr<AudioInputController> controller(new AudioInputController( |
195 new AudioInputController(event_handler, sync_writer, user_input_monitor)); | 198 event_handler, sync_writer, user_input_monitor, agc_is_enabled)); |
196 controller->task_runner_ = audio_manager->GetTaskRunner(); | 199 controller->task_runner_ = audio_manager->GetTaskRunner(); |
197 | 200 |
198 // Create and open a new audio input stream from the existing | 201 // Create and open a new audio input stream from the existing |
199 // audio-device thread. Use the provided audio-input device. | 202 // audio-device thread. Use the provided audio-input device. |
200 if (!controller->task_runner_->PostTask( | 203 if (!controller->task_runner_->PostTask( |
201 FROM_HERE, | 204 FROM_HERE, |
202 base::Bind(&AudioInputController::DoCreateForLowLatency, | 205 base::Bind(&AudioInputController::DoCreateForLowLatency, |
203 controller, | 206 controller, |
204 base::Unretained(audio_manager), | 207 base::Unretained(audio_manager), |
205 params, | 208 params, |
206 device_id))) { | 209 device_id))) { |
207 controller = NULL; | 210 controller = NULL; |
208 } | 211 } |
209 | 212 |
210 return controller; | 213 return controller; |
211 } | 214 } |
212 | 215 |
213 // static | 216 // static |
214 scoped_refptr<AudioInputController> AudioInputController::CreateForStream( | 217 scoped_refptr<AudioInputController> AudioInputController::CreateForStream( |
215 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, | 218 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, |
216 EventHandler* event_handler, | 219 EventHandler* event_handler, |
217 AudioInputStream* stream, | 220 AudioInputStream* stream, |
218 SyncWriter* sync_writer, | 221 SyncWriter* sync_writer, |
219 UserInputMonitor* user_input_monitor) { | 222 UserInputMonitor* user_input_monitor) { |
220 DCHECK(sync_writer); | 223 DCHECK(sync_writer); |
221 DCHECK(stream); | 224 DCHECK(stream); |
222 | 225 |
223 // Create the AudioInputController object and ensure that it runs on | 226 // Create the AudioInputController object and ensure that it runs on |
224 // the audio-manager thread. | 227 // the audio-manager thread. |
225 scoped_refptr<AudioInputController> controller( | 228 scoped_refptr<AudioInputController> controller(new AudioInputController( |
226 new AudioInputController(event_handler, sync_writer, user_input_monitor)); | 229 event_handler, sync_writer, user_input_monitor, false)); |
227 controller->task_runner_ = task_runner; | 230 controller->task_runner_ = task_runner; |
228 | 231 |
229 // TODO(miu): See TODO at top of file. Until that's resolved, we need to | 232 // TODO(miu): See TODO at top of file. Until that's resolved, we need to |
230 // disable the error auto-detection here (since the audio mirroring | 233 // disable the error auto-detection here (since the audio mirroring |
231 // implementation will reliably report error and close events). Note, of | 234 // implementation will reliably report error and close events). Note, of |
232 // course, that we're assuming CreateForStream() has been called for the audio | 235 // course, that we're assuming CreateForStream() has been called for the audio |
233 // mirroring use case only. | 236 // mirroring use case only. |
234 if (!controller->task_runner_->PostTask( | 237 if (!controller->task_runner_->PostTask( |
235 FROM_HERE, | 238 FROM_HERE, |
236 base::Bind(&AudioInputController::DoCreateForStream, | 239 base::Bind(&AudioInputController::DoCreateForStream, |
(...skipping 16 matching lines...) Expand all Loading... |
253 | 256 |
254 task_runner_->PostTaskAndReply( | 257 task_runner_->PostTaskAndReply( |
255 FROM_HERE, base::Bind(&AudioInputController::DoClose, this), closed_task); | 258 FROM_HERE, base::Bind(&AudioInputController::DoClose, this), closed_task); |
256 } | 259 } |
257 | 260 |
258 void AudioInputController::SetVolume(double volume) { | 261 void AudioInputController::SetVolume(double volume) { |
259 task_runner_->PostTask(FROM_HERE, base::Bind( | 262 task_runner_->PostTask(FROM_HERE, base::Bind( |
260 &AudioInputController::DoSetVolume, this, volume)); | 263 &AudioInputController::DoSetVolume, this, volume)); |
261 } | 264 } |
262 | 265 |
263 void AudioInputController::SetAutomaticGainControl(bool enabled) { | |
264 task_runner_->PostTask(FROM_HERE, base::Bind( | |
265 &AudioInputController::DoSetAutomaticGainControl, this, enabled)); | |
266 } | |
267 | |
268 void AudioInputController::DoCreate(AudioManager* audio_manager, | 266 void AudioInputController::DoCreate(AudioManager* audio_manager, |
269 const AudioParameters& params, | 267 const AudioParameters& params, |
270 const std::string& device_id) { | 268 const std::string& device_id) { |
271 DCHECK(task_runner_->BelongsToCurrentThread()); | 269 DCHECK(task_runner_->BelongsToCurrentThread()); |
272 SCOPED_UMA_HISTOGRAM_TIMER("Media.AudioInputController.CreateTime"); | 270 SCOPED_UMA_HISTOGRAM_TIMER("Media.AudioInputController.CreateTime"); |
273 if (handler_) | 271 if (handler_) |
274 handler_->OnLog(this, "AIC::DoCreate"); | 272 handler_->OnLog(this, "AIC::DoCreate"); |
275 | 273 |
276 #if defined(AUDIO_POWER_MONITORING) | 274 #if defined(AUDIO_POWER_MONITORING) |
277 power_measurement_is_enabled_ = true; | 275 // Disable power monitoring for streams that run without AGC enabled to |
| 276 // avoid adding logs and UMA for non-WebRTC clients. |
| 277 power_measurement_is_enabled_ = agc_is_enabled_; |
278 last_audio_level_log_time_ = base::TimeTicks::Now(); | 278 last_audio_level_log_time_ = base::TimeTicks::Now(); |
279 silence_state_ = SILENCE_STATE_NO_MEASUREMENT; | 279 silence_state_ = SILENCE_STATE_NO_MEASUREMENT; |
280 #endif | 280 #endif |
281 | 281 |
282 // TODO(miu): See TODO at top of file. Until that's resolved, assume all | 282 // TODO(miu): See TODO at top of file. Until that's resolved, assume all |
283 // platform audio input requires the |no_data_timer_| be used to auto-detect | 283 // platform audio input requires the |no_data_timer_| be used to auto-detect |
284 // errors. In reality, probably only Windows needs to be treated as | 284 // errors. In reality, probably only Windows needs to be treated as |
285 // unreliable here. | 285 // unreliable here. |
286 DoCreateForStream(audio_manager->MakeAudioInputStream(params, device_id)); | 286 DoCreateForStream(audio_manager->MakeAudioInputStream(params, device_id)); |
287 } | 287 } |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
320 stream_->Close(); | 320 stream_->Close(); |
321 stream_ = NULL; | 321 stream_ = NULL; |
322 if (handler_) | 322 if (handler_) |
323 handler_->OnError(this, STREAM_OPEN_ERROR); | 323 handler_->OnError(this, STREAM_OPEN_ERROR); |
324 LogCaptureStartupResult(CAPTURE_STARTUP_OPEN_STREAM_FAILED); | 324 LogCaptureStartupResult(CAPTURE_STARTUP_OPEN_STREAM_FAILED); |
325 return; | 325 return; |
326 } | 326 } |
327 | 327 |
328 DCHECK(!no_data_timer_.get()); | 328 DCHECK(!no_data_timer_.get()); |
329 | 329 |
| 330 // Set AGC state using mode in |agc_is_enabled_| which can only be enabled in |
| 331 // CreateLowLatency(). |
| 332 stream_->SetAutomaticGainControl(agc_is_enabled_); |
| 333 |
330 // Create the data timer which will call FirstCheckForNoData(). The timer | 334 // Create the data timer which will call FirstCheckForNoData(). The timer |
331 // is started in DoRecord() and restarted in each DoCheckForNoData() | 335 // is started in DoRecord() and restarted in each DoCheckForNoData() |
332 // callback. | 336 // callback. |
333 // The timer is enabled for logging purposes. The NO_DATA_ERROR triggered | 337 // The timer is enabled for logging purposes. The NO_DATA_ERROR triggered |
334 // from the timer must be ignored by the EventHandler. | 338 // from the timer must be ignored by the EventHandler. |
335 // TODO(henrika): remove usage of timer when it has been verified on Canary | 339 // TODO(henrika): remove usage of timer when it has been verified on Canary |
336 // that we are safe doing so. Goal is to get rid of |no_data_timer_| and | 340 // that we are safe doing so. Goal is to get rid of |no_data_timer_| and |
337 // everything that is tied to it. crbug.com/357569. | 341 // everything that is tied to it. crbug.com/357569. |
338 no_data_timer_.reset(new base::Timer( | 342 no_data_timer_.reset(new base::Timer( |
339 FROM_HERE, base::TimeDelta::FromSeconds(kTimerInitialIntervalSeconds), | 343 FROM_HERE, base::TimeDelta::FromSeconds(kTimerInitialIntervalSeconds), |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
442 | 446 |
443 if (max_volume_ == 0.0) { | 447 if (max_volume_ == 0.0) { |
444 DLOG(WARNING) << "Failed to access input volume control"; | 448 DLOG(WARNING) << "Failed to access input volume control"; |
445 return; | 449 return; |
446 } | 450 } |
447 | 451 |
448 // Set the stream volume and scale to a range matched to the platform. | 452 // Set the stream volume and scale to a range matched to the platform. |
449 stream_->SetVolume(max_volume_ * volume); | 453 stream_->SetVolume(max_volume_ * volume); |
450 } | 454 } |
451 | 455 |
452 void AudioInputController::DoSetAutomaticGainControl(bool enabled) { | |
453 DCHECK(task_runner_->BelongsToCurrentThread()); | |
454 DCHECK_NE(state_, RECORDING); | |
455 | |
456 // Ensure that the AGC state only can be modified before streaming starts. | |
457 if (state_ != CREATED) | |
458 return; | |
459 | |
460 stream_->SetAutomaticGainControl(enabled); | |
461 } | |
462 | |
463 void AudioInputController::FirstCheckForNoData() { | 456 void AudioInputController::FirstCheckForNoData() { |
464 DCHECK(task_runner_->BelongsToCurrentThread()); | 457 DCHECK(task_runner_->BelongsToCurrentThread()); |
465 LogCaptureStartupResult(GetDataIsActive() ? | 458 LogCaptureStartupResult(GetDataIsActive() ? |
466 CAPTURE_STARTUP_OK : | 459 CAPTURE_STARTUP_OK : |
467 CAPTURE_STARTUP_NO_DATA_CALLBACK); | 460 CAPTURE_STARTUP_NO_DATA_CALLBACK); |
468 if (handler_) { | 461 if (handler_) { |
469 handler_->OnLog(this, GetDataIsActive() ? | 462 handler_->OnLog(this, GetDataIsActive() ? |
470 "AIC::FirstCheckForNoData => data is active" : | 463 "AIC::FirstCheckForNoData => data is active" : |
471 "AIC::FirstCheckForNoData => data is NOT active"); | 464 "AIC::FirstCheckForNoData => data is NOT active"); |
472 } | 465 } |
(...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
666 } | 659 } |
667 | 660 |
668 void AudioInputController::LogSilenceState(SilenceState value) { | 661 void AudioInputController::LogSilenceState(SilenceState value) { |
669 UMA_HISTOGRAM_ENUMERATION("Media.AudioInputControllerSessionSilenceReport", | 662 UMA_HISTOGRAM_ENUMERATION("Media.AudioInputControllerSessionSilenceReport", |
670 value, | 663 value, |
671 SILENCE_STATE_MAX + 1); | 664 SILENCE_STATE_MAX + 1); |
672 } | 665 } |
673 #endif | 666 #endif |
674 | 667 |
675 } // namespace media | 668 } // namespace media |
OLD | NEW |