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/android/opensles_input.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "base/debug/trace_event.h" 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/audio/android/audio_manager_android.h" 106d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)#include "media/base/audio_bus.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#define LOG_ON_FAILURE_AND_RETURN(op, ...) \ 13d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) do { \ 14d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) SLresult err = (op); \ 15d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (err != SL_RESULT_SUCCESS) { \ 16eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch DLOG(ERROR) << #op << " failed: " << err; \ 17d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return __VA_ARGS__; \ 18d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } \ 19eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } while (0) 20eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace media { 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)OpenSLESInputStream::OpenSLESInputStream(AudioManagerAndroid* audio_manager, 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const AudioParameters& params) 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : audio_manager_(audio_manager), 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) callback_(NULL), 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) recorder_(NULL), 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) simple_buffer_queue_(NULL), 29d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) active_buffer_index_(0), 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buffer_size_bytes_(0), 316d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) started_(false), 326d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) audio_bus_(media::AudioBus::Create(params)) { 33a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DVLOG(2) << __PRETTY_FUNCTION__; 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) format_.formatType = SL_DATAFORMAT_PCM; 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) format_.numChannels = static_cast<SLuint32>(params.channels()); 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Provides sampling rate in milliHertz to OpenSLES. 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) format_.samplesPerSec = static_cast<SLuint32>(params.sample_rate() * 1000); 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) format_.bitsPerSample = params.bits_per_sample(); 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) format_.containerSize = params.bits_per_sample(); 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) format_.endianness = SL_BYTEORDER_LITTLEENDIAN; 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (format_.numChannels == 1) 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) format_.channelMask = SL_SPEAKER_FRONT_CENTER; 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else if (format_.numChannels == 2) 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) format_.channelMask = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT; 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED() << "Unsupported number of channels: " << format_.numChannels; 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buffer_size_bytes_ = params.GetBytesPerBuffer(); 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memset(&audio_data_, 0, sizeof(audio_data_)); 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)OpenSLESInputStream::~OpenSLESInputStream() { 54a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DVLOG(2) << __PRETTY_FUNCTION__; 55d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DCHECK(thread_checker_.CalledOnValidThread()); 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!recorder_object_.Get()); 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!engine_object_.Get()); 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!recorder_); 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!simple_buffer_queue_); 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!audio_data_[0]); 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool OpenSLESInputStream::Open() { 64a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DVLOG(2) << __PRETTY_FUNCTION__; 65d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DCHECK(thread_checker_.CalledOnValidThread()); 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (engine_object_.Get()) 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!CreateRecorder()) 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetupAudioBuffer(); 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void OpenSLESInputStream::Start(AudioInputCallback* callback) { 78a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DVLOG(2) << __PRETTY_FUNCTION__; 79d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DCHECK(thread_checker_.CalledOnValidThread()); 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(callback); 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(recorder_); 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(simple_buffer_queue_); 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (started_) 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 86d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) base::AutoLock lock(lock_); 87d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DCHECK(callback_ == NULL || callback_ == callback); 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) callback_ = callback; 89d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) active_buffer_index_ = 0; 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 91d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Enqueues kMaxNumOfBuffersInQueue zero buffers to get the ball rolling. 92d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // TODO(henrika): add support for Start/Stop/Start sequences when we are 93d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // able to clear the buffer queue. There is currently a bug in the OpenSLES 94d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // implementation which forces us to always call Stop() and Close() before 95d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // calling Start() again. 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SLresult err = SL_RESULT_UNKNOWN_ERROR; 97d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) for (int i = 0; i < kMaxNumOfBuffersInQueue; ++i) { 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) err = (*simple_buffer_queue_)->Enqueue( 99d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) simple_buffer_queue_, audio_data_[i], buffer_size_bytes_); 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (SL_RESULT_SUCCESS != err) { 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HandleError(err); 102d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) started_ = false; 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 107d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Start the recording by setting the state to SL_RECORDSTATE_RECORDING. 108d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // When the object is in the SL_RECORDSTATE_RECORDING state, adding buffers 109d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // will implicitly start the filling process. 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) err = (*recorder_)->SetRecordState(recorder_, SL_RECORDSTATE_RECORDING); 111d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (SL_RESULT_SUCCESS != err) { 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HandleError(err); 113d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) started_ = false; 114d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return; 115d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 116d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 117d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) started_ = true; 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void OpenSLESInputStream::Stop() { 121a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DVLOG(2) << __PRETTY_FUNCTION__; 122d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DCHECK(thread_checker_.CalledOnValidThread()); 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!started_) 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 126d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) base::AutoLock lock(lock_); 127d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 128d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Stop recording by setting the record state to SL_RECORDSTATE_STOPPED. 129eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch LOG_ON_FAILURE_AND_RETURN( 130d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) (*recorder_)->SetRecordState(recorder_, SL_RECORDSTATE_STOPPED)); 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Clear the buffer queue to get rid of old data when resuming recording. 133eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch LOG_ON_FAILURE_AND_RETURN( 134eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch (*simple_buffer_queue_)->Clear(simple_buffer_queue_)); 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) started_ = false; 1375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) callback_ = NULL; 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void OpenSLESInputStream::Close() { 141a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DVLOG(2) << __PRETTY_FUNCTION__; 142d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DCHECK(thread_checker_.CalledOnValidThread()); 143d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Stop the stream if it is still recording. 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Stop(); 146d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) { 1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // TODO(henrika): Do we need to hold the lock here? 148d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) base::AutoLock lock(lock_); 149d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 150d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Destroy the buffer queue recorder object and invalidate all associated 151d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // interfaces. 152d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) recorder_object_.Reset(); 153d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) simple_buffer_queue_ = NULL; 154d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) recorder_ = NULL; 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 156d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Destroy the engine object. We don't store any associated interface for 157d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // this object. 158d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) engine_object_.Reset(); 159d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) ReleaseAudioBuffer(); 160d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) audio_manager_->ReleaseInputStream(this); 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)double OpenSLESInputStream::GetMaxVolume() { 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTIMPLEMENTED(); 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0.0; 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 170a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void OpenSLESInputStream::SetVolume(double volume) { 171a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) NOTIMPLEMENTED(); 172a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)double OpenSLESInputStream::GetVolume() { 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTIMPLEMENTED(); 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0.0; 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void OpenSLESInputStream::SetAutomaticGainControl(bool enabled) { 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTIMPLEMENTED(); 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool OpenSLESInputStream::GetAutomaticGainControl() { 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTIMPLEMENTED(); 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool OpenSLESInputStream::CreateRecorder() { 189d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DCHECK(thread_checker_.CalledOnValidThread()); 190d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DCHECK(!engine_object_.Get()); 191d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DCHECK(!recorder_object_.Get()); 192d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DCHECK(!recorder_); 193d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DCHECK(!simple_buffer_queue_); 194d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Initializes the engine object with specific option. After working with the 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // object, we need to free the object and its resources. 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SLEngineOption option[] = { 198d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) {SL_ENGINEOPTION_THREADSAFE, static_cast<SLuint32>(SL_BOOLEAN_TRUE)}}; 199d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) LOG_ON_FAILURE_AND_RETURN( 200d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) slCreateEngine(engine_object_.Receive(), 1, option, 0, NULL, NULL), 201d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) false); 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Realize the SL engine object in synchronous mode. 204d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) LOG_ON_FAILURE_AND_RETURN( 205d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) engine_object_->Realize(engine_object_.Get(), SL_BOOLEAN_FALSE), false); 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Get the SL engine interface which is implicit. 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SLEngineItf engine; 209d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) LOG_ON_FAILURE_AND_RETURN(engine_object_->GetInterface( 210d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) engine_object_.Get(), SL_IID_ENGINE, &engine), 211eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch false); 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Audio source configuration. 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SLDataLocator_IODevice mic_locator = { 215d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) SL_DATALOCATOR_IODEVICE, SL_IODEVICE_AUDIOINPUT, 216d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) SL_DEFAULTDEVICEID_AUDIOINPUT, NULL}; 217d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) SLDataSource audio_source = {&mic_locator, NULL}; 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Audio sink configuration. 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SLDataLocator_AndroidSimpleBufferQueue buffer_queue = { 221d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, 222d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) static_cast<SLuint32>(kMaxNumOfBuffersInQueue)}; 223d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) SLDataSink audio_sink = {&buffer_queue, &format_}; 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create an audio recorder. 226d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const SLInterfaceID interface_id[] = {SL_IID_ANDROIDSIMPLEBUFFERQUEUE, 227d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) SL_IID_ANDROIDCONFIGURATION}; 228d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const SLboolean interface_required[] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE}; 229d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 230eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Create AudioRecorder and specify SL_IID_ANDROIDCONFIGURATION. 231eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch LOG_ON_FAILURE_AND_RETURN( 232eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch (*engine)->CreateAudioRecorder(engine, 233eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch recorder_object_.Receive(), 234eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch &audio_source, 235eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch &audio_sink, 236eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch arraysize(interface_id), 237eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch interface_id, 238eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch interface_required), 239eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch false); 240eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 241eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch SLAndroidConfigurationItf recorder_config; 242eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch LOG_ON_FAILURE_AND_RETURN( 243eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch recorder_object_->GetInterface(recorder_object_.Get(), 244eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch SL_IID_ANDROIDCONFIGURATION, 245eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch &recorder_config), 246eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch false); 247eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 248d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Uses the main microphone tuned for audio communications. 249eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch SLint32 stream_type = SL_ANDROID_RECORDING_PRESET_VOICE_COMMUNICATION; 250eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch LOG_ON_FAILURE_AND_RETURN( 251eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch (*recorder_config)->SetConfiguration(recorder_config, 252eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch SL_ANDROID_KEY_RECORDING_PRESET, 253d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) &stream_type, 254d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) sizeof(SLint32)), 255eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch false); 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Realize the recorder object in synchronous mode. 258eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch LOG_ON_FAILURE_AND_RETURN( 259d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) recorder_object_->Realize(recorder_object_.Get(), SL_BOOLEAN_FALSE), 260eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch false); 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Get an implicit recorder interface. 263eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch LOG_ON_FAILURE_AND_RETURN( 264d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) recorder_object_->GetInterface( 265d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) recorder_object_.Get(), SL_IID_RECORD, &recorder_), 266eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch false); 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Get the simple buffer queue interface. 269eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch LOG_ON_FAILURE_AND_RETURN( 270eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch recorder_object_->GetInterface(recorder_object_.Get(), 271eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch SL_IID_ANDROIDSIMPLEBUFFERQUEUE, 272eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch &simple_buffer_queue_), 273eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch false); 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Register the input callback for the simple buffer queue. 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This callback will be called when receiving new data from the device. 277eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch LOG_ON_FAILURE_AND_RETURN( 278d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) (*simple_buffer_queue_)->RegisterCallback( 279d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) simple_buffer_queue_, SimpleBufferQueueCallback, this), 280eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch false); 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 282eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return true; 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void OpenSLESInputStream::SimpleBufferQueueCallback( 286d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) SLAndroidSimpleBufferQueueItf buffer_queue, 287d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) void* instance) { 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OpenSLESInputStream* stream = 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<OpenSLESInputStream*>(instance); 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stream->ReadBufferQueue(); 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void OpenSLESInputStream::ReadBufferQueue() { 294d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) base::AutoLock lock(lock_); 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!started_) 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 298d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) TRACE_EVENT0("audio", "OpenSLESOutputStream::ReadBufferQueue"); 299d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 3006d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) // Convert from interleaved format to deinterleaved audio bus format. 3016d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) audio_bus_->FromInterleaved(audio_data_[active_buffer_index_], 3026d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) audio_bus_->frames(), 3036d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) format_.bitsPerSample / 8); 3046d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 305d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // TODO(henrika): Investigate if it is possible to get an accurate 306d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // delay estimation. 3076d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) callback_->OnData(this, audio_bus_.get(), buffer_size_bytes_, 0.0); 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 30990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Done with this buffer. Send it to device for recording. 310d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) SLresult err = 311d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) (*simple_buffer_queue_)->Enqueue(simple_buffer_queue_, 312d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) audio_data_[active_buffer_index_], 313d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) buffer_size_bytes_); 31490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (SL_RESULT_SUCCESS != err) 31590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) HandleError(err); 31690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 317d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) active_buffer_index_ = (active_buffer_index_ + 1) % kMaxNumOfBuffersInQueue; 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void OpenSLESInputStream::SetupAudioBuffer() { 321d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DCHECK(thread_checker_.CalledOnValidThread()); 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!audio_data_[0]); 323d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) for (int i = 0; i < kMaxNumOfBuffersInQueue; ++i) { 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) audio_data_[i] = new uint8[buffer_size_bytes_]; 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void OpenSLESInputStream::ReleaseAudioBuffer() { 329d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DCHECK(thread_checker_.CalledOnValidThread()); 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (audio_data_[0]) { 331d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) for (int i = 0; i < kMaxNumOfBuffersInQueue; ++i) { 332d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) delete[] audio_data_[i]; 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) audio_data_[i] = NULL; 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void OpenSLESInputStream::HandleError(SLresult error) { 339d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DLOG(ERROR) << "OpenSLES Input error " << error; 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (callback_) 3412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) callback_->OnError(this); 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace media 345