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