audio_input_device.cc revision eb525c5499e34cc9c4b825d6d9e75bb07cc06ace
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/audio/audio_input_device.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/basictypes.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/message_loop.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/thread_restrictions.h"
11eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/audio/audio_manager_base.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/base/audio_bus.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace media {
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// The number of shared memory buffer segments indicated to browser process
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// in order to avoid data overwriting. This number can be any positive number,
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// dependent how fast the renderer process can pick up captured data from
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// shared memory.
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static const int kRequestedSharedMemoryCount = 10;
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Takes care of invoking the capture callback on the audio thread.
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// An instance of this class is created for each capture stream in
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// OnLowLatencyCreated().
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class AudioInputDevice::AudioThreadCallback
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : public AudioDeviceThread::Callback {
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AudioThreadCallback(const AudioParameters& audio_parameters,
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      base::SharedMemoryHandle memory,
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      int memory_length,
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                      int total_segments,
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      CaptureCallback* capture_callback);
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~AudioThreadCallback();
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void MapSharedMemory() OVERRIDE;
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Called whenever we receive notifications about pending data.
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void Process(int pending_data) OVERRIDE;
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int current_segment_id_;
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CaptureCallback* capture_callback_;
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<AudioBus> audio_bus_;
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(AudioThreadCallback);
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AudioInputDevice::AudioInputDevice(
49c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    scoped_ptr<AudioInputIPC> ipc,
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const scoped_refptr<base::MessageLoopProxy>& io_loop)
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : ScopedLoopObserver(io_loop),
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      callback_(NULL),
53c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      ipc_(ipc.Pass()),
54c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      state_(IDLE),
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      session_id_(0),
56c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      agc_is_enabled_(false),
57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      stopping_hack_(false) {
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(ipc_);
59c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // The correctness of the code depends on the relative values assigned in the
61c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // State enum.
62c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  COMPILE_ASSERT(IPC_CLOSED < IDLE, invalid_enum_value_assignment_0);
63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  COMPILE_ASSERT(IDLE < CREATING_STREAM, invalid_enum_value_assignment_1);
64c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  COMPILE_ASSERT(CREATING_STREAM < RECORDING, invalid_enum_value_assignment_2);
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AudioInputDevice::Initialize(const AudioParameters& params,
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  CaptureCallback* callback,
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                  int session_id) {
70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(params.IsValid());
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!callback_);
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK_EQ(0, session_id_);
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  audio_parameters_ = params;
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  callback_ = callback;
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_id_ = session_id;
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AudioInputDevice::Start() {
79c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(callback_) << "Initialize hasn't been called";
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << "Start()";
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  message_loop()->PostTask(FROM_HERE,
82c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      base::Bind(&AudioInputDevice::StartUpOnIOThread, this));
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AudioInputDevice::Stop() {
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << "Stop()";
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::AutoLock auto_lock(audio_thread_lock_);
90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    audio_thread_.Stop(base::MessageLoop::current());
91c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    stopping_hack_ = true;
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  message_loop()->PostTask(FROM_HERE,
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&AudioInputDevice::ShutDownOnIOThread, this));
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AudioInputDevice::SetVolume(double volume) {
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (volume < 0 || volume > 1.0) {
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DLOG(ERROR) << "Invalid volume value specified";
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  message_loop()->PostTask(FROM_HERE,
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&AudioInputDevice::SetVolumeOnIOThread, this, volume));
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AudioInputDevice::SetAutomaticGainControl(bool enabled) {
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << "SetAutomaticGainControl(enabled=" << enabled << ")";
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  message_loop()->PostTask(FROM_HERE,
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&AudioInputDevice::SetAutomaticGainControlOnIOThread,
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          this, enabled));
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AudioInputDevice::OnStreamCreated(
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::SharedMemoryHandle handle,
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::SyncSocket::Handle socket_handle,
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int length,
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int total_segments) {
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(message_loop()->BelongsToCurrentThread());
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(handle);
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(socket_handle);
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_GE(handle.fd, 0);
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_GE(socket_handle, 0);
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
128c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK_GT(length, 0);
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (state_ != CREATING_STREAM)
131c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::AutoLock auto_lock(audio_thread_lock_);
134c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // TODO(miu): See TODO in OnStreamCreated method for AudioOutputDevice.
135c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Interface changes need to be made; likely, after AudioInputDevice is merged
136c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // into AudioOutputDevice (http://crbug.com/179597).
137c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (stopping_hack_)
138c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(audio_thread_.IsStopped());
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  audio_callback_.reset(
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      new AudioInputDevice::AudioThreadCallback(
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          audio_parameters_, handle, length, total_segments, callback_));
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  audio_thread_.Start(audio_callback_.get(), socket_handle, "AudioInputDevice");
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
146c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  state_ = RECORDING;
147c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ipc_->RecordStream();
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AudioInputDevice::OnVolume(double volume) {
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NOTIMPLEMENTED();
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AudioInputDevice::OnStateChanged(
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AudioInputIPCDelegate::State state) {
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(message_loop()->BelongsToCurrentThread());
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Do nothing if the stream has been closed.
159c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (state_ < CREATING_STREAM)
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
162c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // TODO(miu): Clean-up inconsistent and incomplete handling here.
163c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // http://crbug.com/180640
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (state) {
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case AudioInputIPCDelegate::kStopped:
166c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      ShutDownOnIOThread();
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case AudioInputIPCDelegate::kRecording:
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NOTIMPLEMENTED();
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case AudioInputIPCDelegate::kError:
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DLOG(WARNING) << "AudioInputDevice::OnStateChanged(kError)";
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Don't dereference the callback object if the audio thread
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // is stopped or stopping.  That could mean that the callback
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // object has been deleted.
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // TODO(tommi): Add an explicit contract for clearing the callback
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // object.  Possibly require calling Initialize again or provide
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // a callback object via Start() and clear it in Stop().
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!audio_thread_.IsStopped())
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        callback_->OnCaptureError();
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NOTREACHED();
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AudioInputDevice::OnIPCClosed() {
189c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(message_loop()->BelongsToCurrentThread());
190c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  state_ = IPC_CLOSED;
191c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ipc_.reset();
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AudioInputDevice::~AudioInputDevice() {
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(henrika): The current design requires that the user calls
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Stop before deleting this class.
197c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(audio_thread_.IsStopped());
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
200c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void AudioInputDevice::StartUpOnIOThread() {
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(message_loop()->BelongsToCurrentThread());
202c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Make sure we don't call Start() more than once.
204c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (state_ != IDLE)
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (session_id_ <= 0) {
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DLOG(WARNING) << "Invalid session id for the input stream " << session_id_;
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
212c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  state_ = CREATING_STREAM;
213c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ipc_->CreateStream(this, session_id_, audio_parameters_,
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     agc_is_enabled_, kRequestedSharedMemoryCount);
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AudioInputDevice::ShutDownOnIOThread() {
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(message_loop()->BelongsToCurrentThread());
219c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
220c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Close the stream, if we haven't already.
221c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (state_ >= CREATING_STREAM) {
222c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    ipc_->CloseStream();
223c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    state_ = IDLE;
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    agc_is_enabled_ = false;
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We can run into an issue where ShutDownOnIOThread is called right after
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // OnStreamCreated is called in cases where Start/Stop are called before we
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // get the OnStreamCreated callback.  To handle that corner case, we call
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Stop(). In most cases, the thread will already be stopped.
231c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  //
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Another situation is when the IO thread goes away before Stop() is called
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // in which case, we cannot use the message loop to close the thread handle
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // and can't not rely on the main thread existing either.
235c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::AutoLock auto_lock_(audio_thread_lock_);
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::ThreadRestrictions::ScopedAllowIO allow_io;
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  audio_thread_.Stop(NULL);
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  audio_callback_.reset();
239c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  stopping_hack_ = false;
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AudioInputDevice::SetVolumeOnIOThread(double volume) {
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(message_loop()->BelongsToCurrentThread());
244c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (state_ >= CREATING_STREAM)
245c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    ipc_->SetVolume(volume);
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AudioInputDevice::SetAutomaticGainControlOnIOThread(bool enabled) {
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(message_loop()->BelongsToCurrentThread());
250c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
251c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (state_ >= CREATING_STREAM) {
252c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    DLOG(WARNING) << "The AGC state can not be modified after starting.";
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
254c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We simply store the new AGC setting here. This value will be used when
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // a new stream is initialized and by GetAutomaticGainControl().
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  agc_is_enabled_ = enabled;
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AudioInputDevice::WillDestroyCurrentMessageLoop() {
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LOG(ERROR) << "IO loop going away before the input device has been stopped";
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ShutDownOnIOThread();
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// AudioInputDevice::AudioThreadCallback
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AudioInputDevice::AudioThreadCallback::AudioThreadCallback(
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const AudioParameters& audio_parameters,
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::SharedMemoryHandle memory,
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int memory_length,
2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int total_segments,
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CaptureCallback* capture_callback)
2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : AudioDeviceThread::Callback(audio_parameters, memory, memory_length,
2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                  total_segments),
2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      current_segment_id_(0),
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      capture_callback_(capture_callback) {
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  audio_bus_ = AudioBus::Create(audio_parameters_);
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AudioInputDevice::AudioThreadCallback::~AudioThreadCallback() {
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AudioInputDevice::AudioThreadCallback::MapSharedMemory() {
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  shared_memory_.Map(memory_length_);
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AudioInputDevice::AudioThreadCallback::Process(int pending_data) {
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The shared memory represents parameters, size of the data buffer and the
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // actual data buffer containing audio data. Map the memory into this
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // structure and parse out parameters and the data area.
2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  uint8* ptr = static_cast<uint8*>(shared_memory_.memory());
2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ptr += current_segment_id_ * segment_length_;
2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AudioInputBuffer* buffer = reinterpret_cast<AudioInputBuffer*>(ptr);
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(buffer->params.size,
2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            segment_length_ - sizeof(AudioInputBufferParameters));
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  double volume = buffer->params.volume;
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int audio_delay_milliseconds = pending_data / bytes_per_ms_;
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int16* memory = reinterpret_cast<int16*>(&buffer->audio[0]);
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int bytes_per_sample = sizeof(memory[0]);
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (++current_segment_id_ >= total_segments_)
3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    current_segment_id_ = 0;
3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Deinterleave each channel and convert to 32-bit floating-point
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // with nominal range -1.0 -> +1.0.
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  audio_bus_->FromInterleaved(memory, audio_bus_->frames(), bytes_per_sample);
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Deliver captured data to the client in floating point format
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // and update the audio-delay measurement.
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  capture_callback_->Capture(audio_bus_.get(),
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             audio_delay_milliseconds, volume);
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace media
316