audio_input_controller.cc revision 03b57e008b61dfcb1fbad3aea950ae0e001748b0
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.
4
5#include "media/audio/audio_input_controller.h"
6
7#include "base/bind.h"
8#include "base/strings/stringprintf.h"
9#include "base/threading/thread_restrictions.h"
10#include "base/time/time.h"
11#include "media/audio/audio_parameters.h"
12#include "media/base/limits.h"
13#include "media/base/scoped_histogram_timer.h"
14#include "media/base/user_input_monitor.h"
15
16using base::TimeDelta;
17
18namespace {
19const int kMaxInputChannels = 3;
20
21// TODO(henrika): remove usage of timers and add support for proper
22// notification of when the input device is removed.  This was originally added
23// to resolve http://crbug.com/79936 for Windows platforms.  This then caused
24// breakage (very hard to repro bugs!) on other platforms: See
25// http://crbug.com/226327 and http://crbug.com/230972.
26// See also that the timer has been disabled on Mac now due to
27// crbug.com/357501.
28const int kTimerResetIntervalSeconds = 1;
29// We have received reports that the timer can be too trigger happy on some
30// Mac devices and the initial timer interval has therefore been increased
31// from 1 second to 5 seconds.
32const int kTimerInitialIntervalSeconds = 5;
33
34#if defined(AUDIO_POWER_MONITORING)
35// Time constant for AudioPowerMonitor.
36// The utilized smoothing factor (alpha) in the exponential filter is given
37// by 1-exp(-1/(fs*ts)), where fs is the sample rate in Hz and ts is the time
38// constant given by |kPowerMeasurementTimeConstantMilliseconds|.
39// Example: fs=44100, ts=10e-3 => alpha~0.022420
40//          fs=44100, ts=20e-3 => alpha~0.165903
41// A large smoothing factor corresponds to a faster filter response to input
42// changes since y(n)=alpha*x(n)+(1-alpha)*y(n-1), where x(n) is the input
43// and y(n) is the output.
44const int kPowerMeasurementTimeConstantMilliseconds = 10;
45
46// Time in seconds between two successive measurements of audio power levels.
47const int kPowerMonitorLogIntervalSeconds = 5;
48#endif
49}
50
51// Used to log the result of capture startup.
52// This was previously logged as a boolean with only the no callback and OK
53// options. The enum order is kept to ensure backwards compatibility.
54// Elements in this enum should not be deleted or rearranged; the only
55// permitted operation is to add new elements before CAPTURE_STARTUP_RESULT_MAX
56// and update CAPTURE_STARTUP_RESULT_MAX.
57enum CaptureStartupResult {
58  CAPTURE_STARTUP_NO_DATA_CALLBACK = 0,
59  CAPTURE_STARTUP_OK = 1,
60  CAPTURE_STARTUP_CREATE_STREAM_FAILED = 2,
61  CAPTURE_STARTUP_OPEN_STREAM_FAILED = 3,
62  CAPTURE_STARTUP_RESULT_MAX = CAPTURE_STARTUP_OPEN_STREAM_FAILED
63};
64
65void LogCaptureStartupResult(CaptureStartupResult result) {
66  UMA_HISTOGRAM_ENUMERATION("Media.AudioInputControllerCaptureStartupSuccess",
67                            result,
68                            CAPTURE_STARTUP_RESULT_MAX + 1);
69
70}
71
72namespace media {
73
74// static
75AudioInputController::Factory* AudioInputController::factory_ = NULL;
76
77AudioInputController::AudioInputController(EventHandler* handler,
78                                           SyncWriter* sync_writer,
79                                           UserInputMonitor* user_input_monitor)
80    : creator_task_runner_(base::MessageLoopProxy::current()),
81      handler_(handler),
82      stream_(NULL),
83      data_is_active_(false),
84      state_(CLOSED),
85      sync_writer_(sync_writer),
86      max_volume_(0.0),
87      user_input_monitor_(user_input_monitor),
88#if defined(AUDIO_POWER_MONITORING)
89      log_silence_state_(false),
90      silence_state_(SILENCE_STATE_NO_MEASUREMENT),
91#endif
92      prev_key_down_count_(0) {
93  DCHECK(creator_task_runner_.get());
94}
95
96AudioInputController::~AudioInputController() {
97  DCHECK_EQ(state_, CLOSED);
98}
99
100// static
101scoped_refptr<AudioInputController> AudioInputController::Create(
102    AudioManager* audio_manager,
103    EventHandler* event_handler,
104    const AudioParameters& params,
105    const std::string& device_id,
106    UserInputMonitor* user_input_monitor) {
107  DCHECK(audio_manager);
108
109  if (!params.IsValid() || (params.channels() > kMaxInputChannels))
110    return NULL;
111
112  if (factory_) {
113    return factory_->Create(
114        audio_manager, event_handler, params, user_input_monitor);
115  }
116  scoped_refptr<AudioInputController> controller(
117      new AudioInputController(event_handler, NULL, user_input_monitor));
118
119  controller->task_runner_ = audio_manager->GetTaskRunner();
120
121  // Create and open a new audio input stream from the existing
122  // audio-device thread.
123  if (!controller->task_runner_->PostTask(FROM_HERE,
124          base::Bind(&AudioInputController::DoCreate, controller,
125                     base::Unretained(audio_manager), params, device_id))) {
126    controller = NULL;
127  }
128
129  return controller;
130}
131
132// static
133scoped_refptr<AudioInputController> AudioInputController::CreateLowLatency(
134    AudioManager* audio_manager,
135    EventHandler* event_handler,
136    const AudioParameters& params,
137    const std::string& device_id,
138    SyncWriter* sync_writer,
139    UserInputMonitor* user_input_monitor) {
140  DCHECK(audio_manager);
141  DCHECK(sync_writer);
142
143  if (!params.IsValid() || (params.channels() > kMaxInputChannels))
144    return NULL;
145
146  // Create the AudioInputController object and ensure that it runs on
147  // the audio-manager thread.
148  scoped_refptr<AudioInputController> controller(
149      new AudioInputController(event_handler, sync_writer, user_input_monitor));
150  controller->task_runner_ = audio_manager->GetTaskRunner();
151
152  // Create and open a new audio input stream from the existing
153  // audio-device thread. Use the provided audio-input device.
154  if (!controller->task_runner_->PostTask(FROM_HERE,
155          base::Bind(&AudioInputController::DoCreateForLowLatency, controller,
156                     base::Unretained(audio_manager), params, device_id))) {
157    controller = NULL;
158  }
159
160  return controller;
161}
162
163// static
164scoped_refptr<AudioInputController> AudioInputController::CreateForStream(
165    const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
166    EventHandler* event_handler,
167    AudioInputStream* stream,
168    SyncWriter* sync_writer,
169    UserInputMonitor* user_input_monitor) {
170  DCHECK(sync_writer);
171  DCHECK(stream);
172
173  // Create the AudioInputController object and ensure that it runs on
174  // the audio-manager thread.
175  scoped_refptr<AudioInputController> controller(
176      new AudioInputController(event_handler, sync_writer, user_input_monitor));
177  controller->task_runner_ = task_runner;
178
179  // 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
181  // implementation will reliably report error and close events).  Note, of
182  // course, that we're assuming CreateForStream() has been called for the audio
183  // mirroring use case only.
184  if (!controller->task_runner_->PostTask(
185          FROM_HERE,
186          base::Bind(&AudioInputController::DoCreateForStream,
187                     controller,
188                     stream))) {
189    controller = NULL;
190  }
191
192  return controller;
193}
194
195void AudioInputController::Record() {
196  task_runner_->PostTask(FROM_HERE, base::Bind(
197      &AudioInputController::DoRecord, this));
198}
199
200void AudioInputController::Close(const base::Closure& closed_task) {
201  DCHECK(!closed_task.is_null());
202  DCHECK(creator_task_runner_->BelongsToCurrentThread());
203
204  task_runner_->PostTaskAndReply(
205      FROM_HERE, base::Bind(&AudioInputController::DoClose, this), closed_task);
206}
207
208void AudioInputController::SetVolume(double volume) {
209  task_runner_->PostTask(FROM_HERE, base::Bind(
210      &AudioInputController::DoSetVolume, this, volume));
211}
212
213void AudioInputController::SetAutomaticGainControl(bool enabled) {
214  task_runner_->PostTask(FROM_HERE, base::Bind(
215      &AudioInputController::DoSetAutomaticGainControl, this, enabled));
216}
217
218void AudioInputController::DoCreate(AudioManager* audio_manager,
219                                    const AudioParameters& params,
220                                    const std::string& device_id) {
221  DCHECK(task_runner_->BelongsToCurrentThread());
222  SCOPED_UMA_HISTOGRAM_TIMER("Media.AudioInputController.CreateTime");
223
224#if defined(AUDIO_POWER_MONITORING)
225  // 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
227  // layer to match AudioPowerMonitor::Scan().
228  // TODO(henrika): Remove use of extra AudioBus. See http://crbug.com/375155.
229  audio_level_.reset(new media::AudioPowerMonitor(
230      params.sample_rate(),
231      TimeDelta::FromMilliseconds(kPowerMeasurementTimeConstantMilliseconds)));
232  audio_params_ = params;
233  silence_state_ = SILENCE_STATE_NO_MEASUREMENT;
234#endif
235
236  // 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
238  // errors.  In reality, probably only Windows needs to be treated as
239  // unreliable here.
240  DoCreateForStream(audio_manager->MakeAudioInputStream(params, device_id));
241}
242
243void 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}
257
258void AudioInputController::DoCreateForStream(
259    AudioInputStream* stream_to_control) {
260  DCHECK(task_runner_->BelongsToCurrentThread());
261
262  DCHECK(!stream_);
263  stream_ = stream_to_control;
264
265  if (!stream_) {
266    if (handler_)
267      handler_->OnError(this, STREAM_CREATE_ERROR);
268    LogCaptureStartupResult(CAPTURE_STARTUP_CREATE_STREAM_FAILED);
269    return;
270  }
271
272  if (stream_ && !stream_->Open()) {
273    stream_->Close();
274    stream_ = NULL;
275    if (handler_)
276      handler_->OnError(this, STREAM_OPEN_ERROR);
277    LogCaptureStartupResult(CAPTURE_STARTUP_OPEN_STREAM_FAILED);
278    return;
279  }
280
281  DCHECK(!no_data_timer_.get());
282
283  // Create the data timer which will call FirstCheckForNoData(). The timer
284  // is started in DoRecord() and restarted in each DoCheckForNoData()
285  // callback.
286  // The timer is enabled for logging purposes. The NO_DATA_ERROR triggered
287  // from the timer must be ignored by the EventHandler.
288  // TODO(henrika): remove usage of timer when it has been verified on Canary
289  // that we are safe doing so. Goal is to get rid of |no_data_timer_| and
290  // everything that is tied to it. crbug.com/357569.
291  no_data_timer_.reset(new base::Timer(
292      FROM_HERE, base::TimeDelta::FromSeconds(kTimerInitialIntervalSeconds),
293      base::Bind(&AudioInputController::FirstCheckForNoData,
294                 base::Unretained(this)), false));
295
296  state_ = CREATED;
297  if (handler_)
298    handler_->OnCreated(this);
299
300  if (user_input_monitor_) {
301    user_input_monitor_->EnableKeyPressMonitoring();
302    prev_key_down_count_ = user_input_monitor_->GetKeyPressCount();
303  }
304}
305
306void AudioInputController::DoRecord() {
307  DCHECK(task_runner_->BelongsToCurrentThread());
308  SCOPED_UMA_HISTOGRAM_TIMER("Media.AudioInputController.RecordTime");
309
310  if (state_ != CREATED)
311    return;
312
313  {
314    base::AutoLock auto_lock(lock_);
315    state_ = RECORDING;
316  }
317
318  if (no_data_timer_) {
319    // Start the data timer. Once |kTimerResetIntervalSeconds| have passed,
320    // a callback to FirstCheckForNoData() is made.
321    no_data_timer_->Reset();
322  }
323
324  stream_->Start(this);
325  if (handler_)
326    handler_->OnRecording(this);
327}
328
329void AudioInputController::DoClose() {
330  DCHECK(task_runner_->BelongsToCurrentThread());
331  SCOPED_UMA_HISTOGRAM_TIMER("Media.AudioInputController.CloseTime");
332
333  if (state_ == CLOSED)
334    return;
335
336  // Delete the timer on the same thread that created it.
337  no_data_timer_.reset();
338
339  DoStopCloseAndClearStream();
340  SetDataIsActive(false);
341
342  if (SharedMemoryAndSyncSocketMode())
343    sync_writer_->Close();
344
345  if (user_input_monitor_)
346    user_input_monitor_->DisableKeyPressMonitoring();
347
348#if defined(AUDIO_POWER_MONITORING)
349  // Send UMA stats if enabled.
350  if (log_silence_state_)
351    LogSilenceState(silence_state_);
352  log_silence_state_ = false;
353#endif
354
355  state_ = CLOSED;
356}
357
358void AudioInputController::DoReportError() {
359  DCHECK(task_runner_->BelongsToCurrentThread());
360  if (handler_)
361    handler_->OnError(this, STREAM_ERROR);
362}
363
364void AudioInputController::DoSetVolume(double volume) {
365  DCHECK(task_runner_->BelongsToCurrentThread());
366  DCHECK_GE(volume, 0);
367  DCHECK_LE(volume, 1.0);
368
369  if (state_ != CREATED && state_ != RECORDING)
370    return;
371
372  // Only ask for the maximum volume at first call and use cached value
373  // for remaining function calls.
374  if (!max_volume_) {
375    max_volume_ = stream_->GetMaxVolume();
376  }
377
378  if (max_volume_ == 0.0) {
379    DLOG(WARNING) << "Failed to access input volume control";
380    return;
381  }
382
383  // Set the stream volume and scale to a range matched to the platform.
384  stream_->SetVolume(max_volume_ * volume);
385}
386
387void AudioInputController::DoSetAutomaticGainControl(bool enabled) {
388  DCHECK(task_runner_->BelongsToCurrentThread());
389  DCHECK_NE(state_, RECORDING);
390
391  // Ensure that the AGC state only can be modified before streaming starts.
392  if (state_ != CREATED)
393    return;
394
395  stream_->SetAutomaticGainControl(enabled);
396}
397
398void AudioInputController::FirstCheckForNoData() {
399  DCHECK(task_runner_->BelongsToCurrentThread());
400  LogCaptureStartupResult(GetDataIsActive() ?
401                          CAPTURE_STARTUP_OK :
402                          CAPTURE_STARTUP_NO_DATA_CALLBACK);
403  DoCheckForNoData();
404}
405
406void AudioInputController::DoCheckForNoData() {
407  DCHECK(task_runner_->BelongsToCurrentThread());
408
409  if (!GetDataIsActive()) {
410    // 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
412    // capture device has been removed or disabled.
413    if (handler_)
414      handler_->OnError(this, NO_DATA_ERROR);
415  }
416
417  // Mark data as non-active. The flag will be re-enabled in OnData() each
418  // time a data packet is received. Hence, under normal conditions, the
419  // flag will only be disabled during a very short period.
420  SetDataIsActive(false);
421
422  // Restart the timer to ensure that we check the flag again in
423  // |kTimerResetIntervalSeconds|.
424  no_data_timer_->Start(
425      FROM_HERE, base::TimeDelta::FromSeconds(kTimerResetIntervalSeconds),
426      base::Bind(&AudioInputController::DoCheckForNoData,
427      base::Unretained(this)));
428}
429
430void AudioInputController::OnData(AudioInputStream* stream,
431                                  const AudioBus* source,
432                                  uint32 hardware_delay_bytes,
433                                  double volume) {
434  // Mark data as active to ensure that the periodic calls to
435  // DoCheckForNoData() does not report an error to the event handler.
436  SetDataIsActive(true);
437
438  {
439    base::AutoLock auto_lock(lock_);
440    if (state_ != RECORDING)
441      return;
442  }
443
444  bool key_pressed = false;
445  if (user_input_monitor_) {
446    size_t current_count = user_input_monitor_->GetKeyPressCount();
447    key_pressed = current_count != prev_key_down_count_;
448    prev_key_down_count_ = current_count;
449    DVLOG_IF(6, key_pressed) << "Detected keypress.";
450  }
451
452  // Use SharedMemory and SyncSocket if the client has created a SyncWriter.
453  // Used by all low-latency clients except WebSpeech.
454  if (SharedMemoryAndSyncSocketMode()) {
455    sync_writer_->Write(source, volume, key_pressed);
456    sync_writer_->UpdateRecordedBytes(hardware_delay_bytes);
457
458#if defined(AUDIO_POWER_MONITORING)
459    // Only do power-level measurements if an AudioPowerMonitor object has
460    // been created. Done in DoCreate() but not DoCreateForStream(), hence
461    // logging will mainly be done for WebRTC and WebSpeech clients.
462    if (!audio_level_)
463      return;
464
465    // Perform periodic audio (power) level measurements.
466    if ((base::TimeTicks::Now() - last_audio_level_log_time_).InSeconds() >
467        kPowerMonitorLogIntervalSeconds) {
468      // Wrap data into an AudioBus to match AudioPowerMonitor::Scan.
469      // TODO(henrika): remove this section when capture side uses AudioBus.
470      // See http://crbug.com/375155 for details.
471      audio_level_->Scan(*source, source->frames());
472
473      // Get current average power level and add it to the log.
474      // Possible range is given by [-inf, 0] dBFS.
475      std::pair<float, bool> result = audio_level_->ReadCurrentPowerAndClip();
476
477      // Use event handler on the audio thread to relay a message to the ARIH
478      // in content which does the actual logging on the IO thread.
479      task_runner_->PostTask(
480          FROM_HERE,
481          base::Bind(
482              &AudioInputController::DoLogAudioLevel, this, result.first));
483
484      last_audio_level_log_time_ = base::TimeTicks::Now();
485
486      // Reset the average power level (since we don't log continuously).
487      audio_level_->Reset();
488    }
489#endif
490    return;
491  }
492
493  // TODO(henrika): Investigate if we can avoid the extra copy here.
494  // (see http://crbug.com/249316 for details). AFAIK, this scope is only
495  // active for WebSpeech clients.
496  scoped_ptr<AudioBus> audio_data =
497      AudioBus::Create(source->channels(), source->frames());
498  source->CopyTo(audio_data.get());
499
500  // Ownership of the audio buffer will be with the callback until it is run,
501  // when ownership is passed to the callback function.
502  task_runner_->PostTask(
503      FROM_HERE,
504      base::Bind(
505          &AudioInputController::DoOnData, this, base::Passed(&audio_data)));
506}
507
508void AudioInputController::DoOnData(scoped_ptr<AudioBus> data) {
509  DCHECK(task_runner_->BelongsToCurrentThread());
510  if (handler_)
511    handler_->OnData(this, data.get());
512}
513
514void AudioInputController::DoLogAudioLevel(float level_dbfs) {
515#if defined(AUDIO_POWER_MONITORING)
516  DCHECK(task_runner_->BelongsToCurrentThread());
517  if (!handler_)
518    return;
519
520  std::string log_string = base::StringPrintf(
521      "AIC::OnData: average audio level=%.2f dBFS", level_dbfs);
522  static const float kSilenceThresholdDBFS = -72.24719896f;
523  if (level_dbfs < kSilenceThresholdDBFS)
524    log_string += " <=> no audio input!";
525  handler_->OnLog(this, log_string);
526
527  UpdateSilenceState(level_dbfs < kSilenceThresholdDBFS);
528#endif
529}
530
531void AudioInputController::OnError(AudioInputStream* stream) {
532  // Handle error on the audio-manager thread.
533  task_runner_->PostTask(FROM_HERE, base::Bind(
534      &AudioInputController::DoReportError, this));
535}
536
537void AudioInputController::DoStopCloseAndClearStream() {
538  DCHECK(task_runner_->BelongsToCurrentThread());
539
540  // Allow calling unconditionally and bail if we don't have a stream to close.
541  if (stream_ != NULL) {
542    stream_->Stop();
543    stream_->Close();
544    stream_ = NULL;
545  }
546
547  // The event handler should not be touched after the stream has been closed.
548  handler_ = NULL;
549}
550
551void AudioInputController::SetDataIsActive(bool enabled) {
552  base::subtle::Release_Store(&data_is_active_, enabled);
553}
554
555bool AudioInputController::GetDataIsActive() {
556  return (base::subtle::Acquire_Load(&data_is_active_) != false);
557}
558
559#if defined(AUDIO_POWER_MONITORING)
560void AudioInputController::UpdateSilenceState(bool silence) {
561  if (silence) {
562    if (silence_state_ == SILENCE_STATE_NO_MEASUREMENT) {
563      silence_state_ = SILENCE_STATE_ONLY_SILENCE;
564    } else if (silence_state_ == SILENCE_STATE_ONLY_AUDIO) {
565      silence_state_ = SILENCE_STATE_AUDIO_AND_SILENCE;
566    } else {
567      DCHECK(silence_state_ == SILENCE_STATE_ONLY_SILENCE ||
568             silence_state_ == SILENCE_STATE_AUDIO_AND_SILENCE);
569    }
570  } else {
571    if (silence_state_ == SILENCE_STATE_NO_MEASUREMENT) {
572      silence_state_ = SILENCE_STATE_ONLY_AUDIO;
573    } else if (silence_state_ == SILENCE_STATE_ONLY_SILENCE) {
574      silence_state_ = SILENCE_STATE_AUDIO_AND_SILENCE;
575    } else {
576      DCHECK(silence_state_ == SILENCE_STATE_ONLY_AUDIO ||
577             silence_state_ == SILENCE_STATE_AUDIO_AND_SILENCE);
578    }
579  }
580}
581
582void AudioInputController::LogSilenceState(SilenceState value) {
583  UMA_HISTOGRAM_ENUMERATION("Media.AudioInputControllerSessionSilenceReport",
584                            value,
585                            SILENCE_STATE_MAX + 1);
586}
587#endif
588
589}  // namespace media
590