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
3 // found in the LICENSE file.
5 #include "media/audio/audio_input_controller.h"
8 #include "base/metrics/histogram_macros.h"
9 #include "base/single_thread_task_runner.h"
10 #include "base/strings/string_number_conversions.h"
11 #include "base/strings/stringprintf.h"
12 #include "base/thread_task_runner_handle.h"
13 #include "base/threading/thread_restrictions.h"
14 #include "base/time/time.h"
15 #include "media/base/user_input_monitor.h"
17 using base::TimeDelta
;
21 const int kMaxInputChannels
= 3;
23 // TODO(henrika): remove usage of timers and add support for proper
24 // notification of when the input device is removed. This was originally added
25 // to resolve http://crbug.com/79936 for Windows platforms. This then caused
26 // breakage (very hard to repro bugs!) on other platforms: See
27 // http://crbug.com/226327 and http://crbug.com/230972.
28 // See also that the timer has been disabled on Mac now due to
30 const int kTimerResetIntervalSeconds
= 1;
31 // We have received reports that the timer can be too trigger happy on some
32 // Mac devices and the initial timer interval has therefore been increased
33 // from 1 second to 5 seconds.
34 const int kTimerInitialIntervalSeconds
= 5;
36 #if defined(AUDIO_POWER_MONITORING)
37 // Time in seconds between two successive measurements of audio power levels.
38 const int kPowerMonitorLogIntervalSeconds
= 15;
40 // A warning will be logged when the microphone audio volume is below this
42 const int kLowLevelMicrophoneLevelPercent
= 10;
44 // Logs if the user has enabled the microphone mute or not. This is normally
45 // done by marking a checkbox in an audio-settings UI which is unique for each
46 // platform. Elements in this enum should not be added, deleted or rearranged.
47 enum MicrophoneMuteResult
{
48 MICROPHONE_IS_MUTED
= 0,
49 MICROPHONE_IS_NOT_MUTED
= 1,
50 MICROPHONE_MUTE_MAX
= MICROPHONE_IS_NOT_MUTED
53 void LogMicrophoneMuteResult(MicrophoneMuteResult result
) {
54 UMA_HISTOGRAM_ENUMERATION("Media.MicrophoneMuted",
56 MICROPHONE_MUTE_MAX
+ 1);
59 // Helper method which calculates the average power of an audio bus. Unit is in
60 // dBFS, where 0 dBFS corresponds to all channels and samples equal to 1.0.
61 float AveragePower(const media::AudioBus
& buffer
) {
62 const int frames
= buffer
.frames();
63 const int channels
= buffer
.channels();
64 if (frames
<= 0 || channels
<= 0)
67 // Scan all channels and accumulate the sum of squares for all samples.
68 float sum_power
= 0.0f
;
69 for (int ch
= 0; ch
< channels
; ++ch
) {
70 const float* channel_data
= buffer
.channel(ch
);
71 for (int i
= 0; i
< frames
; i
++) {
72 const float sample
= channel_data
[i
];
73 sum_power
+= sample
* sample
;
77 // Update accumulated average results, with clamping for sanity.
78 const float average_power
=
79 std::max(0.0f
, std::min(1.0f
, sum_power
/ (frames
* channels
)));
81 // Convert average power level to dBFS units, and pin it down to zero if it
82 // is insignificantly small.
83 const float kInsignificantPower
= 1.0e-10f
; // -100 dBFS
84 const float power_dbfs
= average_power
< kInsignificantPower
?
85 -std::numeric_limits
<float>::infinity() : 10.0f
* log10f(average_power
);
89 #endif // AUDIO_POWER_MONITORING
93 // Used to log the result of capture startup.
94 // This was previously logged as a boolean with only the no callback and OK
95 // options. The enum order is kept to ensure backwards compatibility.
96 // Elements in this enum should not be deleted or rearranged; the only
97 // permitted operation is to add new elements before CAPTURE_STARTUP_RESULT_MAX
98 // and update CAPTURE_STARTUP_RESULT_MAX.
99 enum CaptureStartupResult
{
100 CAPTURE_STARTUP_NO_DATA_CALLBACK
= 0,
101 CAPTURE_STARTUP_OK
= 1,
102 CAPTURE_STARTUP_CREATE_STREAM_FAILED
= 2,
103 CAPTURE_STARTUP_OPEN_STREAM_FAILED
= 3,
104 CAPTURE_STARTUP_RESULT_MAX
= CAPTURE_STARTUP_OPEN_STREAM_FAILED
107 void LogCaptureStartupResult(CaptureStartupResult result
) {
108 UMA_HISTOGRAM_ENUMERATION("Media.AudioInputControllerCaptureStartupSuccess",
110 CAPTURE_STARTUP_RESULT_MAX
+ 1);
117 AudioInputController::Factory
* AudioInputController::factory_
= NULL
;
119 AudioInputController::AudioInputController(EventHandler
* handler
,
120 SyncWriter
* sync_writer
,
121 UserInputMonitor
* user_input_monitor
,
122 const bool agc_is_enabled
)
123 : creator_task_runner_(base::ThreadTaskRunnerHandle::Get()),
126 data_is_active_(false),
128 sync_writer_(sync_writer
),
130 user_input_monitor_(user_input_monitor
),
131 agc_is_enabled_(agc_is_enabled
),
132 #if defined(AUDIO_POWER_MONITORING)
133 power_measurement_is_enabled_(false),
134 log_silence_state_(false),
135 silence_state_(SILENCE_STATE_NO_MEASUREMENT
),
137 prev_key_down_count_(0) {
138 DCHECK(creator_task_runner_
.get());
141 AudioInputController::~AudioInputController() {
142 DCHECK_EQ(state_
, CLOSED
);
146 scoped_refptr
<AudioInputController
> AudioInputController::Create(
147 AudioManager
* audio_manager
,
148 EventHandler
* event_handler
,
149 const AudioParameters
& params
,
150 const std::string
& device_id
,
151 UserInputMonitor
* user_input_monitor
) {
152 DCHECK(audio_manager
);
154 if (!params
.IsValid() || (params
.channels() > kMaxInputChannels
))
158 return factory_
->Create(
159 audio_manager
, event_handler
, params
, user_input_monitor
);
161 scoped_refptr
<AudioInputController
> controller(
162 new AudioInputController(event_handler
, NULL
, user_input_monitor
, false));
164 controller
->task_runner_
= audio_manager
->GetTaskRunner();
166 // Create and open a new audio input stream from the existing
167 // audio-device thread.
168 if (!controller
->task_runner_
->PostTask(
170 base::Bind(&AudioInputController::DoCreate
,
172 base::Unretained(audio_manager
),
182 scoped_refptr
<AudioInputController
> AudioInputController::CreateLowLatency(
183 AudioManager
* audio_manager
,
184 EventHandler
* event_handler
,
185 const AudioParameters
& params
,
186 const std::string
& device_id
,
187 SyncWriter
* sync_writer
,
188 UserInputMonitor
* user_input_monitor
,
189 const bool agc_is_enabled
) {
190 DCHECK(audio_manager
);
193 if (!params
.IsValid() || (params
.channels() > kMaxInputChannels
))
196 // Create the AudioInputController object and ensure that it runs on
197 // the audio-manager thread.
198 scoped_refptr
<AudioInputController
> controller(new AudioInputController(
199 event_handler
, sync_writer
, user_input_monitor
, agc_is_enabled
));
200 controller
->task_runner_
= audio_manager
->GetTaskRunner();
202 // Create and open a new audio input stream from the existing
203 // audio-device thread. Use the provided audio-input device.
204 if (!controller
->task_runner_
->PostTask(
206 base::Bind(&AudioInputController::DoCreateForLowLatency
,
208 base::Unretained(audio_manager
),
218 scoped_refptr
<AudioInputController
> AudioInputController::CreateForStream(
219 const scoped_refptr
<base::SingleThreadTaskRunner
>& task_runner
,
220 EventHandler
* event_handler
,
221 AudioInputStream
* stream
,
222 SyncWriter
* sync_writer
,
223 UserInputMonitor
* user_input_monitor
) {
227 // Create the AudioInputController object and ensure that it runs on
228 // the audio-manager thread.
229 scoped_refptr
<AudioInputController
> controller(new AudioInputController(
230 event_handler
, sync_writer
, user_input_monitor
, false));
231 controller
->task_runner_
= task_runner
;
233 // TODO(miu): See TODO at top of file. Until that's resolved, we need to
234 // disable the error auto-detection here (since the audio mirroring
235 // implementation will reliably report error and close events). Note, of
236 // course, that we're assuming CreateForStream() has been called for the audio
237 // mirroring use case only.
238 if (!controller
->task_runner_
->PostTask(
240 base::Bind(&AudioInputController::DoCreateForStream
,
249 void AudioInputController::Record() {
250 task_runner_
->PostTask(FROM_HERE
, base::Bind(
251 &AudioInputController::DoRecord
, this));
254 void AudioInputController::Close(const base::Closure
& closed_task
) {
255 DCHECK(!closed_task
.is_null());
256 DCHECK(creator_task_runner_
->BelongsToCurrentThread());
258 task_runner_
->PostTaskAndReply(
259 FROM_HERE
, base::Bind(&AudioInputController::DoClose
, this), closed_task
);
262 void AudioInputController::SetVolume(double volume
) {
263 task_runner_
->PostTask(FROM_HERE
, base::Bind(
264 &AudioInputController::DoSetVolume
, this, volume
));
267 void AudioInputController::DoCreate(AudioManager
* audio_manager
,
268 const AudioParameters
& params
,
269 const std::string
& device_id
) {
270 DCHECK(task_runner_
->BelongsToCurrentThread());
271 SCOPED_UMA_HISTOGRAM_TIMER("Media.AudioInputController.CreateTime");
273 handler_
->OnLog(this, "AIC::DoCreate");
275 #if defined(AUDIO_POWER_MONITORING)
276 // Disable power monitoring for streams that run without AGC enabled to
277 // avoid adding logs and UMA for non-WebRTC clients.
278 power_measurement_is_enabled_
= agc_is_enabled_
;
279 last_audio_level_log_time_
= base::TimeTicks::Now();
280 silence_state_
= SILENCE_STATE_NO_MEASUREMENT
;
283 // TODO(miu): See TODO at top of file. Until that's resolved, assume all
284 // platform audio input requires the |no_data_timer_| be used to auto-detect
285 // errors. In reality, probably only Windows needs to be treated as
287 DoCreateForStream(audio_manager
->MakeAudioInputStream(params
, device_id
));
290 void AudioInputController::DoCreateForLowLatency(AudioManager
* audio_manager
,
291 const AudioParameters
& params
,
292 const std::string
& device_id
) {
293 DCHECK(task_runner_
->BelongsToCurrentThread());
295 #if defined(AUDIO_POWER_MONITORING)
296 // We only log silence state UMA stats for low latency mode and if we use a
298 if (params
.format() != AudioParameters::AUDIO_FAKE
)
299 log_silence_state_
= true;
302 low_latency_create_time_
= base::TimeTicks::Now();
303 DoCreate(audio_manager
, params
, device_id
);
306 void AudioInputController::DoCreateForStream(
307 AudioInputStream
* stream_to_control
) {
308 DCHECK(task_runner_
->BelongsToCurrentThread());
311 stream_
= stream_to_control
;
315 handler_
->OnError(this, STREAM_CREATE_ERROR
);
316 LogCaptureStartupResult(CAPTURE_STARTUP_CREATE_STREAM_FAILED
);
320 if (stream_
&& !stream_
->Open()) {
324 handler_
->OnError(this, STREAM_OPEN_ERROR
);
325 LogCaptureStartupResult(CAPTURE_STARTUP_OPEN_STREAM_FAILED
);
329 DCHECK(!no_data_timer_
.get());
331 // Set AGC state using mode in |agc_is_enabled_| which can only be enabled in
332 // CreateLowLatency().
333 #if defined(AUDIO_POWER_MONITORING)
334 bool agc_is_supported
= false;
335 agc_is_supported
= stream_
->SetAutomaticGainControl(agc_is_enabled_
);
336 // Disable power measurements on platforms that does not support AGC at a
337 // lower level. AGC can fail on platforms where we don't support the
338 // functionality to modify the input volume slider. One such example is
340 power_measurement_is_enabled_
&= agc_is_supported
;
342 stream_
->SetAutomaticGainControl(agc_is_enabled_
);
345 // Create the data timer which will call FirstCheckForNoData(). The timer
346 // is started in DoRecord() and restarted in each DoCheckForNoData()
348 // The timer is enabled for logging purposes. The NO_DATA_ERROR triggered
349 // from the timer must be ignored by the EventHandler.
350 // TODO(henrika): remove usage of timer when it has been verified on Canary
351 // that we are safe doing so. Goal is to get rid of |no_data_timer_| and
352 // everything that is tied to it. crbug.com/357569.
353 no_data_timer_
.reset(new base::Timer(
354 FROM_HERE
, base::TimeDelta::FromSeconds(kTimerInitialIntervalSeconds
),
355 base::Bind(&AudioInputController::FirstCheckForNoData
,
356 base::Unretained(this)), false));
360 handler_
->OnCreated(this);
362 if (user_input_monitor_
) {
363 user_input_monitor_
->EnableKeyPressMonitoring();
364 prev_key_down_count_
= user_input_monitor_
->GetKeyPressCount();
368 void AudioInputController::DoRecord() {
369 DCHECK(task_runner_
->BelongsToCurrentThread());
370 SCOPED_UMA_HISTOGRAM_TIMER("Media.AudioInputController.RecordTime");
372 if (state_
!= CREATED
)
376 base::AutoLock
auto_lock(lock_
);
381 handler_
->OnLog(this, "AIC::DoRecord");
383 if (no_data_timer_
) {
384 // Start the data timer. Once |kTimerResetIntervalSeconds| have passed,
385 // a callback to FirstCheckForNoData() is made.
386 no_data_timer_
->Reset();
389 stream_
->Start(this);
391 handler_
->OnRecording(this);
394 void AudioInputController::DoClose() {
395 DCHECK(task_runner_
->BelongsToCurrentThread());
396 SCOPED_UMA_HISTOGRAM_TIMER("Media.AudioInputController.CloseTime");
398 if (state_
== CLOSED
)
401 // If this is a low-latency stream, log the total duration (since DoCreate)
402 // and add it to a UMA histogram.
403 if (!low_latency_create_time_
.is_null()) {
404 base::TimeDelta duration
=
405 base::TimeTicks::Now() - low_latency_create_time_
;
406 UMA_HISTOGRAM_LONG_TIMES("Media.InputStreamDuration", duration
);
408 std::string log_string
=
409 base::StringPrintf("AIC::DoClose: stream duration=");
410 log_string
+= base::Int64ToString(duration
.InSeconds());
411 log_string
+= " seconds";
412 handler_
->OnLog(this, log_string
);
416 // Delete the timer on the same thread that created it.
417 no_data_timer_
.reset();
419 DoStopCloseAndClearStream();
420 SetDataIsActive(false);
422 if (SharedMemoryAndSyncSocketMode())
423 sync_writer_
->Close();
425 if (user_input_monitor_
)
426 user_input_monitor_
->DisableKeyPressMonitoring();
428 #if defined(AUDIO_POWER_MONITORING)
429 // Send UMA stats if enabled.
430 if (log_silence_state_
)
431 LogSilenceState(silence_state_
);
432 log_silence_state_
= false;
438 void AudioInputController::DoReportError() {
439 DCHECK(task_runner_
->BelongsToCurrentThread());
441 handler_
->OnError(this, STREAM_ERROR
);
444 void AudioInputController::DoSetVolume(double volume
) {
445 DCHECK(task_runner_
->BelongsToCurrentThread());
446 DCHECK_GE(volume
, 0);
447 DCHECK_LE(volume
, 1.0);
449 if (state_
!= CREATED
&& state_
!= RECORDING
)
452 // Only ask for the maximum volume at first call and use cached value
453 // for remaining function calls.
455 max_volume_
= stream_
->GetMaxVolume();
458 if (max_volume_
== 0.0) {
459 DLOG(WARNING
) << "Failed to access input volume control";
463 // Set the stream volume and scale to a range matched to the platform.
464 stream_
->SetVolume(max_volume_
* volume
);
467 void AudioInputController::FirstCheckForNoData() {
468 DCHECK(task_runner_
->BelongsToCurrentThread());
469 LogCaptureStartupResult(GetDataIsActive() ?
471 CAPTURE_STARTUP_NO_DATA_CALLBACK
);
473 handler_
->OnLog(this, GetDataIsActive() ?
474 "AIC::FirstCheckForNoData => data is active" :
475 "AIC::FirstCheckForNoData => data is NOT active");
480 void AudioInputController::DoCheckForNoData() {
481 DCHECK(task_runner_
->BelongsToCurrentThread());
483 if (!GetDataIsActive()) {
484 // The data-is-active marker will be false only if it has been more than
485 // one second since a data packet was recorded. This can happen if a
486 // capture device has been removed or disabled.
488 handler_
->OnError(this, NO_DATA_ERROR
);
491 // Mark data as non-active. The flag will be re-enabled in OnData() each
492 // time a data packet is received. Hence, under normal conditions, the
493 // flag will only be disabled during a very short period.
494 SetDataIsActive(false);
496 // Restart the timer to ensure that we check the flag again in
497 // |kTimerResetIntervalSeconds|.
498 no_data_timer_
->Start(
499 FROM_HERE
, base::TimeDelta::FromSeconds(kTimerResetIntervalSeconds
),
500 base::Bind(&AudioInputController::DoCheckForNoData
,
501 base::Unretained(this)));
504 void AudioInputController::OnData(AudioInputStream
* stream
,
505 const AudioBus
* source
,
506 uint32 hardware_delay_bytes
,
508 // Mark data as active to ensure that the periodic calls to
509 // DoCheckForNoData() does not report an error to the event handler.
510 SetDataIsActive(true);
513 base::AutoLock
auto_lock(lock_
);
514 if (state_
!= RECORDING
)
518 bool key_pressed
= false;
519 if (user_input_monitor_
) {
520 size_t current_count
= user_input_monitor_
->GetKeyPressCount();
521 key_pressed
= current_count
!= prev_key_down_count_
;
522 prev_key_down_count_
= current_count
;
523 DVLOG_IF(6, key_pressed
) << "Detected keypress.";
526 // Use SharedMemory and SyncSocket if the client has created a SyncWriter.
527 // Used by all low-latency clients except WebSpeech.
528 if (SharedMemoryAndSyncSocketMode()) {
529 sync_writer_
->Write(source
, volume
, key_pressed
);
530 sync_writer_
->UpdateRecordedBytes(hardware_delay_bytes
);
532 #if defined(AUDIO_POWER_MONITORING)
533 // Only do power-level measurements if DoCreate() has been called. It will
534 // ensure that logging will mainly be done for WebRTC and WebSpeech
536 if (!power_measurement_is_enabled_
)
539 // Perform periodic audio (power) level measurements.
540 if ((base::TimeTicks::Now() - last_audio_level_log_time_
).InSeconds() >
541 kPowerMonitorLogIntervalSeconds
) {
542 // Calculate the average power of the signal, or the energy per sample.
543 const float average_power_dbfs
= AveragePower(*source
);
545 // Add current microphone volume to log and UMA histogram.
546 const int mic_volume_percent
= static_cast<int>(100.0 * volume
);
548 // Use event handler on the audio thread to relay a message to the ARIH
549 // in content which does the actual logging on the IO thread.
550 task_runner_
->PostTask(FROM_HERE
,
551 base::Bind(&AudioInputController::DoLogAudioLevels
,
554 mic_volume_percent
));
556 last_audio_level_log_time_
= base::TimeTicks::Now();
562 // TODO(henrika): Investigate if we can avoid the extra copy here.
563 // (see http://crbug.com/249316 for details). AFAIK, this scope is only
564 // active for WebSpeech clients.
565 scoped_ptr
<AudioBus
> audio_data
=
566 AudioBus::Create(source
->channels(), source
->frames());
567 source
->CopyTo(audio_data
.get());
569 // Ownership of the audio buffer will be with the callback until it is run,
570 // when ownership is passed to the callback function.
571 task_runner_
->PostTask(
574 &AudioInputController::DoOnData
, this, base::Passed(&audio_data
)));
577 void AudioInputController::DoOnData(scoped_ptr
<AudioBus
> data
) {
578 DCHECK(task_runner_
->BelongsToCurrentThread());
580 handler_
->OnData(this, data
.get());
583 void AudioInputController::DoLogAudioLevels(float level_dbfs
,
584 int microphone_volume_percent
) {
585 #if defined(AUDIO_POWER_MONITORING)
586 DCHECK(task_runner_
->BelongsToCurrentThread());
590 // Detect if the user has enabled hardware mute by pressing the mute
591 // button in audio settings for the selected microphone.
592 const bool microphone_is_muted
= stream_
->IsMuted();
593 if (microphone_is_muted
) {
594 LogMicrophoneMuteResult(MICROPHONE_IS_MUTED
);
595 handler_
->OnLog(this, "AIC::OnData: microphone is muted!");
596 // Return early if microphone is muted. No need to adding logs and UMA stats
597 // of audio levels if we know that the micropone is muted.
601 LogMicrophoneMuteResult(MICROPHONE_IS_NOT_MUTED
);
603 std::string log_string
= base::StringPrintf(
604 "AIC::OnData: average audio level=%.2f dBFS", level_dbfs
);
605 static const float kSilenceThresholdDBFS
= -72.24719896f
;
606 if (level_dbfs
< kSilenceThresholdDBFS
)
607 log_string
+= " <=> low audio input level!";
608 handler_
->OnLog(this, log_string
);
610 UpdateSilenceState(level_dbfs
< kSilenceThresholdDBFS
);
612 UMA_HISTOGRAM_PERCENTAGE("Media.MicrophoneVolume", microphone_volume_percent
);
613 log_string
= base::StringPrintf(
614 "AIC::OnData: microphone volume=%d%%", microphone_volume_percent
);
615 if (microphone_volume_percent
< kLowLevelMicrophoneLevelPercent
)
616 log_string
+= " <=> low microphone level!";
617 handler_
->OnLog(this, log_string
);
621 void AudioInputController::OnError(AudioInputStream
* stream
) {
622 // Handle error on the audio-manager thread.
623 task_runner_
->PostTask(FROM_HERE
, base::Bind(
624 &AudioInputController::DoReportError
, this));
627 void AudioInputController::DoStopCloseAndClearStream() {
628 DCHECK(task_runner_
->BelongsToCurrentThread());
630 // Allow calling unconditionally and bail if we don't have a stream to close.
631 if (stream_
!= NULL
) {
637 // The event handler should not be touched after the stream has been closed.
641 void AudioInputController::SetDataIsActive(bool enabled
) {
642 base::subtle::Release_Store(&data_is_active_
, enabled
);
645 bool AudioInputController::GetDataIsActive() {
646 return (base::subtle::Acquire_Load(&data_is_active_
) != false);
649 #if defined(AUDIO_POWER_MONITORING)
650 void AudioInputController::UpdateSilenceState(bool silence
) {
652 if (silence_state_
== SILENCE_STATE_NO_MEASUREMENT
) {
653 silence_state_
= SILENCE_STATE_ONLY_SILENCE
;
654 } else if (silence_state_
== SILENCE_STATE_ONLY_AUDIO
) {
655 silence_state_
= SILENCE_STATE_AUDIO_AND_SILENCE
;
657 DCHECK(silence_state_
== SILENCE_STATE_ONLY_SILENCE
||
658 silence_state_
== SILENCE_STATE_AUDIO_AND_SILENCE
);
661 if (silence_state_
== SILENCE_STATE_NO_MEASUREMENT
) {
662 silence_state_
= SILENCE_STATE_ONLY_AUDIO
;
663 } else if (silence_state_
== SILENCE_STATE_ONLY_SILENCE
) {
664 silence_state_
= SILENCE_STATE_AUDIO_AND_SILENCE
;
666 DCHECK(silence_state_
== SILENCE_STATE_ONLY_AUDIO
||
667 silence_state_
== SILENCE_STATE_AUDIO_AND_SILENCE
);
672 void AudioInputController::LogSilenceState(SilenceState value
) {
673 UMA_HISTOGRAM_ENUMERATION("Media.AudioInputControllerSessionSilenceReport",
675 SILENCE_STATE_MAX
+ 1);