audio_input_device.cc revision 5821806d5e7f356e8fa4b058a389a808ea183019
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)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/message_loop.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/thread_restrictions.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/time.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/audio/audio_manager_base.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/base/audio_bus.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace media {
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AudioInputDevice::CaptureCallback::~CaptureCallback() {}
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AudioInputDevice::CaptureEventHandler::~CaptureEventHandler() {}
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Takes care of invoking the capture callback on the audio thread.
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// An instance of this class is created for each capture stream in
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// OnLowLatencyCreated().
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class AudioInputDevice::AudioThreadCallback
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : public AudioDeviceThread::Callback {
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AudioThreadCallback(const AudioParameters& audio_parameters,
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      base::SharedMemoryHandle memory,
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      int memory_length,
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      CaptureCallback* capture_callback);
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~AudioThreadCallback();
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void MapSharedMemory() OVERRIDE;
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Called whenever we receive notifications about pending data.
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void Process(int pending_data) OVERRIDE;
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CaptureCallback* capture_callback_;
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<AudioBus> audio_bus_;
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(AudioThreadCallback);
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AudioInputDevice::AudioInputDevice(
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AudioInputIPC* ipc,
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const scoped_refptr<base::MessageLoopProxy>& io_loop)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : ScopedLoopObserver(io_loop),
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      callback_(NULL),
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      event_handler_(NULL),
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ipc_(ipc),
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      stream_id_(0),
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      session_id_(0),
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pending_device_ready_(false),
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      agc_is_enabled_(false) {
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(ipc_);
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AudioInputDevice::Initialize(const AudioParameters& params,
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  CaptureCallback* callback,
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  CaptureEventHandler* event_handler) {
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!callback_);
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!event_handler_);
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  audio_parameters_ = params;
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  callback_ = callback;
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  event_handler_ = event_handler;
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AudioInputDevice::SetDevice(int session_id) {
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << "SetDevice (session_id=" << session_id << ")";
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  message_loop()->PostTask(FROM_HERE,
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&AudioInputDevice::SetSessionIdOnIOThread, this, session_id));
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AudioInputDevice::Start() {
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << "Start()";
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  message_loop()->PostTask(FROM_HERE,
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&AudioInputDevice::InitializeOnIOThread, this));
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AudioInputDevice::Stop() {
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << "Stop()";
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::AutoLock auto_lock(audio_thread_lock_);
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    audio_thread_.Stop(MessageLoop::current());
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  message_loop()->PostTask(FROM_HERE,
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&AudioInputDevice::ShutDownOnIOThread, this));
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AudioInputDevice::SetVolume(double volume) {
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (volume < 0 || volume > 1.0) {
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DLOG(ERROR) << "Invalid volume value specified";
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  message_loop()->PostTask(FROM_HERE,
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&AudioInputDevice::SetVolumeOnIOThread, this, volume));
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AudioInputDevice::SetAutomaticGainControl(bool enabled) {
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << "SetAutomaticGainControl(enabled=" << enabled << ")";
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  message_loop()->PostTask(FROM_HERE,
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&AudioInputDevice::SetAutomaticGainControlOnIOThread,
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          this, enabled));
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AudioInputDevice::OnStreamCreated(
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::SharedMemoryHandle handle,
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::SyncSocket::Handle socket_handle,
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int length) {
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(message_loop()->BelongsToCurrentThread());
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(handle);
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(socket_handle);
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_GE(handle.fd, 0);
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_GE(socket_handle, 0);
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(length);
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << "OnStreamCreated (stream_id=" << stream_id_ << ")";
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We should only get this callback if stream_id_ is valid.  If it is not,
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the IPC layer should have closed the shared memory and socket handles
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // for us and not invoked the callback.  The basic assertion is that when
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // stream_id_ is 0 the AudioInputDevice instance is not registered as a
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // delegate and hence it should not receive callbacks.
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(stream_id_);
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::AutoLock auto_lock(audio_thread_lock_);
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(audio_thread_.IsStopped());
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  audio_callback_.reset(
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new AudioInputDevice::AudioThreadCallback(audio_parameters_, handle,
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                length, callback_));
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  audio_thread_.Start(audio_callback_.get(), socket_handle, "AudioInputDevice");
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MessageLoop::current()->PostTask(FROM_HERE,
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&AudioInputDevice::StartOnIOThread, this));
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AudioInputDevice::OnVolume(double volume) {
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NOTIMPLEMENTED();
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AudioInputDevice::OnStateChanged(
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AudioInputIPCDelegate::State state) {
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(message_loop()->BelongsToCurrentThread());
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Do nothing if the stream has been closed.
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!stream_id_)
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (state) {
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case AudioInputIPCDelegate::kStopped:
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // TODO(xians): Should we just call ShutDownOnIOThread here instead?
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ipc_->RemoveDelegate(stream_id_);
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      audio_thread_.Stop(MessageLoop::current());
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      audio_callback_.reset();
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (event_handler_)
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        event_handler_->OnDeviceStopped();
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      stream_id_ = 0;
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pending_device_ready_ = false;
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case AudioInputIPCDelegate::kRecording:
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NOTIMPLEMENTED();
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case AudioInputIPCDelegate::kError:
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DLOG(WARNING) << "AudioInputDevice::OnStateChanged(kError)";
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Don't dereference the callback object if the audio thread
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // is stopped or stopping.  That could mean that the callback
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // object has been deleted.
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // TODO(tommi): Add an explicit contract for clearing the callback
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // object.  Possibly require calling Initialize again or provide
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // a callback object via Start() and clear it in Stop().
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!audio_thread_.IsStopped())
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        callback_->OnCaptureError();
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NOTREACHED();
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AudioInputDevice::OnDeviceReady(const std::string& device_id) {
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(message_loop()->BelongsToCurrentThread());
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << "OnDeviceReady (device_id=" << device_id << ")";
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Takes care of the case when Stop() is called before OnDeviceReady().
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!pending_device_ready_)
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If AudioInputDeviceManager returns an empty string, it means no device
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // is ready for start.
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (device_id.empty()) {
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ipc_->RemoveDelegate(stream_id_);
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    stream_id_ = 0;
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ipc_->CreateStream(stream_id_, audio_parameters_, device_id,
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       agc_is_enabled_);
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pending_device_ready_ = false;
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Notify the client that the device has been started.
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (event_handler_)
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    event_handler_->OnDeviceStarted(device_id);
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AudioInputDevice::OnIPCClosed() {
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ipc_ = NULL;
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AudioInputDevice::~AudioInputDevice() {
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(henrika): The current design requires that the user calls
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Stop before deleting this class.
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK_EQ(0, stream_id_);
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AudioInputDevice::InitializeOnIOThread() {
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(message_loop()->BelongsToCurrentThread());
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Make sure we don't call Start() more than once.
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(0, stream_id_);
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (stream_id_)
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  stream_id_ = ipc_->AddDelegate(this);
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If |session_id_| is not specified, it will directly create the stream;
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // otherwise it will send a AudioInputHostMsg_StartDevice msg to the browser
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // and create the stream when getting a OnDeviceReady() callback.
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!session_id_) {
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ipc_->CreateStream(stream_id_, audio_parameters_,
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        AudioManagerBase::kDefaultDeviceId, agc_is_enabled_);
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ipc_->StartDevice(stream_id_, session_id_);
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pending_device_ready_ = true;
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AudioInputDevice::SetSessionIdOnIOThread(int session_id) {
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(message_loop()->BelongsToCurrentThread());
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  session_id_ = session_id;
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AudioInputDevice::StartOnIOThread() {
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(message_loop()->BelongsToCurrentThread());
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (stream_id_)
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ipc_->RecordStream(stream_id_);
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AudioInputDevice::ShutDownOnIOThread() {
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(message_loop()->BelongsToCurrentThread());
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // NOTE: |completion| may be NULL.
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Make sure we don't call shutdown more than once.
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (stream_id_) {
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ipc_) {
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ipc_->CloseStream(stream_id_);
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ipc_->RemoveDelegate(stream_id_);
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    stream_id_ = 0;
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    session_id_ = 0;
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pending_device_ready_ = false;
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    agc_is_enabled_ = false;
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We can run into an issue where ShutDownOnIOThread is called right after
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // OnStreamCreated is called in cases where Start/Stop are called before we
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // get the OnStreamCreated callback.  To handle that corner case, we call
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Stop(). In most cases, the thread will already be stopped.
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Another situation is when the IO thread goes away before Stop() is called
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // in which case, we cannot use the message loop to close the thread handle
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // and can't not rely on the main thread existing either.
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::ThreadRestrictions::ScopedAllowIO allow_io;
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  audio_thread_.Stop(NULL);
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  audio_callback_.reset();
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AudioInputDevice::SetVolumeOnIOThread(double volume) {
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(message_loop()->BelongsToCurrentThread());
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (stream_id_)
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ipc_->SetVolume(stream_id_, volume);
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AudioInputDevice::SetAutomaticGainControlOnIOThread(bool enabled) {
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(message_loop()->BelongsToCurrentThread());
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(0, stream_id_) <<
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "The AGC state can not be modified while capturing is active.";
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (stream_id_)
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We simply store the new AGC setting here. This value will be used when
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // a new stream is initialized and by GetAutomaticGainControl().
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  agc_is_enabled_ = enabled;
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AudioInputDevice::WillDestroyCurrentMessageLoop() {
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LOG(ERROR) << "IO loop going away before the input device has been stopped";
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ShutDownOnIOThread();
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// AudioInputDevice::AudioThreadCallback
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AudioInputDevice::AudioThreadCallback::AudioThreadCallback(
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const AudioParameters& audio_parameters,
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::SharedMemoryHandle memory,
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int memory_length,
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CaptureCallback* capture_callback)
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : AudioDeviceThread::Callback(audio_parameters, 0, memory, memory_length),
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      capture_callback_(capture_callback) {
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  audio_bus_ = AudioBus::Create(audio_parameters_);
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AudioInputDevice::AudioThreadCallback::~AudioThreadCallback() {
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AudioInputDevice::AudioThreadCallback::MapSharedMemory() {
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  shared_memory_.Map(memory_length_);
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AudioInputDevice::AudioThreadCallback::Process(int pending_data) {
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The shared memory represents parameters, size of the data buffer and the
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // actual data buffer containing audio data. Map the memory into this
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // structure and parse out parameters and the data area.
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AudioInputBuffer* buffer =
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      reinterpret_cast<AudioInputBuffer*>(shared_memory_.memory());
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(buffer->params.size,
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            memory_length_ - sizeof(AudioInputBufferParameters));
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  double volume = buffer->params.volume;
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int audio_delay_milliseconds = pending_data / bytes_per_ms_;
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int16* memory = reinterpret_cast<int16*>(&buffer->audio[0]);
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int bytes_per_sample = sizeof(memory[0]);
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Deinterleave each channel and convert to 32-bit floating-point
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // with nominal range -1.0 -> +1.0.
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  audio_bus_->FromInterleaved(memory, audio_bus_->frames(), bytes_per_sample);
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Deliver captured data to the client in floating point format
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // and update the audio-delay measurement.
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  capture_callback_->Capture(audio_bus_.get(),
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             audio_delay_milliseconds, volume);
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace media
346