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