1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "media/audio/android/opensles_input.h"
6
7 #include "base/logging.h"
8 #include "base/stl_util.h"
9 #include "base/trace_event/trace_event.h"
10 #include "media/audio/android/audio_manager_android.h"
11 #include "media/base/audio_bus.h"
12
13 #define LOG_ON_FAILURE_AND_RETURN(op, ...) \
14 do { \
15 SLresult err = (op); \
16 if (err != SL_RESULT_SUCCESS) { \
17 DLOG(ERROR) << #op << " failed: " << err; \
18 return __VA_ARGS__; \
19 } \
20 } while (0)
21
22 namespace media {
23
OpenSLESInputStream(AudioManagerAndroid * audio_manager,const AudioParameters & params)24 OpenSLESInputStream::OpenSLESInputStream(AudioManagerAndroid* audio_manager,
25 const AudioParameters& params)
26 : audio_manager_(audio_manager),
27 callback_(nullptr),
28 recorder_(nullptr),
29 simple_buffer_queue_(nullptr),
30 active_buffer_index_(0),
31 buffer_size_bytes_(0),
32 started_(false),
33 audio_bus_(media::AudioBus::Create(params)),
34 no_effects_(params.effects() == AudioParameters::NO_EFFECTS) {
35 DVLOG(2) << __PRETTY_FUNCTION__;
36 DVLOG(1) << "Audio effects enabled: " << !no_effects_;
37
38 const SampleFormat kSampleFormat = kSampleFormatS16;
39
40 format_.formatType = SL_DATAFORMAT_PCM;
41 format_.numChannels = static_cast<SLuint32>(params.channels());
42 // Provides sampling rate in milliHertz to OpenSLES.
43 format_.samplesPerSec = static_cast<SLuint32>(params.sample_rate() * 1000);
44 format_.bitsPerSample = format_.containerSize =
45 SampleFormatToBitsPerChannel(kSampleFormat);
46 format_.endianness = SL_BYTEORDER_LITTLEENDIAN;
47 format_.channelMask = ChannelCountToSLESChannelMask(params.channels());
48
49 buffer_size_bytes_ = params.GetBytesPerBuffer(kSampleFormat);
50 hardware_delay_ = base::TimeDelta::FromSecondsD(
51 params.frames_per_buffer() / static_cast<double>(params.sample_rate()));
52
53 memset(&audio_data_, 0, sizeof(audio_data_));
54 }
55
~OpenSLESInputStream()56 OpenSLESInputStream::~OpenSLESInputStream() {
57 DVLOG(2) << __PRETTY_FUNCTION__;
58 DCHECK(thread_checker_.CalledOnValidThread());
59 DCHECK(!recorder_object_.Get());
60 DCHECK(!engine_object_.Get());
61 DCHECK(!recorder_);
62 DCHECK(!simple_buffer_queue_);
63 DCHECK(!audio_data_[0]);
64 }
65
Open()66 bool OpenSLESInputStream::Open() {
67 DVLOG(2) << __PRETTY_FUNCTION__;
68 DCHECK(thread_checker_.CalledOnValidThread());
69 if (engine_object_.Get())
70 return false;
71
72 if (!CreateRecorder())
73 return false;
74
75 SetupAudioBuffer();
76
77 return true;
78 }
79
Start(AudioInputCallback * callback)80 void OpenSLESInputStream::Start(AudioInputCallback* callback) {
81 DVLOG(2) << __PRETTY_FUNCTION__;
82 DCHECK(thread_checker_.CalledOnValidThread());
83 DCHECK(callback);
84 DCHECK(recorder_);
85 DCHECK(simple_buffer_queue_);
86 if (started_)
87 return;
88
89 base::AutoLock lock(lock_);
90 DCHECK(!callback_ || callback_ == callback);
91 callback_ = callback;
92 active_buffer_index_ = 0;
93
94 // Enqueues kMaxNumOfBuffersInQueue zero buffers to get the ball rolling.
95 // TODO(henrika): add support for Start/Stop/Start sequences when we are
96 // able to clear the buffer queue. There is currently a bug in the OpenSLES
97 // implementation which forces us to always call Stop() and Close() before
98 // calling Start() again.
99 SLresult err = SL_RESULT_UNKNOWN_ERROR;
100 for (int i = 0; i < kMaxNumOfBuffersInQueue; ++i) {
101 err = (*simple_buffer_queue_)->Enqueue(
102 simple_buffer_queue_, audio_data_[i], buffer_size_bytes_);
103 if (SL_RESULT_SUCCESS != err) {
104 HandleError(err);
105 started_ = false;
106 return;
107 }
108 }
109
110 // Start the recording by setting the state to SL_RECORDSTATE_RECORDING.
111 // When the object is in the SL_RECORDSTATE_RECORDING state, adding buffers
112 // will implicitly start the filling process.
113 err = (*recorder_)->SetRecordState(recorder_, SL_RECORDSTATE_RECORDING);
114 if (SL_RESULT_SUCCESS != err) {
115 HandleError(err);
116 started_ = false;
117 return;
118 }
119
120 started_ = true;
121 }
122
Stop()123 void OpenSLESInputStream::Stop() {
124 DVLOG(2) << __PRETTY_FUNCTION__;
125 DCHECK(thread_checker_.CalledOnValidThread());
126 if (!started_)
127 return;
128
129 base::AutoLock lock(lock_);
130
131 // Stop recording by setting the record state to SL_RECORDSTATE_STOPPED.
132 LOG_ON_FAILURE_AND_RETURN(
133 (*recorder_)->SetRecordState(recorder_, SL_RECORDSTATE_STOPPED));
134
135 // Clear the buffer queue to get rid of old data when resuming recording.
136 LOG_ON_FAILURE_AND_RETURN(
137 (*simple_buffer_queue_)->Clear(simple_buffer_queue_));
138
139 started_ = false;
140 callback_ = nullptr;
141 }
142
Close()143 void OpenSLESInputStream::Close() {
144 DVLOG(2) << __PRETTY_FUNCTION__;
145 DCHECK(thread_checker_.CalledOnValidThread());
146
147 // Stop the stream if it is still recording.
148 Stop();
149 {
150 // TODO(henrika): Do we need to hold the lock here?
151 base::AutoLock lock(lock_);
152
153 // Destroy the buffer queue recorder object and invalidate all associated
154 // interfaces.
155 recorder_object_.Reset();
156 simple_buffer_queue_ = nullptr;
157 recorder_ = nullptr;
158
159 // Destroy the engine object. We don't store any associated interface for
160 // this object.
161 engine_object_.Reset();
162 ReleaseAudioBuffer();
163 }
164
165 audio_manager_->ReleaseInputStream(this);
166 }
167
GetMaxVolume()168 double OpenSLESInputStream::GetMaxVolume() {
169 return 0.0;
170 }
171
SetVolume(double volume)172 void OpenSLESInputStream::SetVolume(double volume) {
173 }
174
GetVolume()175 double OpenSLESInputStream::GetVolume() {
176 return 0.0;
177 }
178
SetAutomaticGainControl(bool enabled)179 bool OpenSLESInputStream::SetAutomaticGainControl(bool enabled) {
180 return false;
181 }
182
GetAutomaticGainControl()183 bool OpenSLESInputStream::GetAutomaticGainControl() {
184 return false;
185 }
186
IsMuted()187 bool OpenSLESInputStream::IsMuted() {
188 return false;
189 }
190
SetOutputDeviceForAec(const std::string & output_device_id)191 void OpenSLESInputStream::SetOutputDeviceForAec(
192 const std::string& output_device_id) {
193 // Not supported. Do nothing.
194 }
195
CreateRecorder()196 bool OpenSLESInputStream::CreateRecorder() {
197 DCHECK(thread_checker_.CalledOnValidThread());
198 DCHECK(!engine_object_.Get());
199 DCHECK(!recorder_object_.Get());
200 DCHECK(!recorder_);
201 DCHECK(!simple_buffer_queue_);
202
203 // Initializes the engine object with specific option. After working with the
204 // object, we need to free the object and its resources.
205 SLEngineOption option[] = {
206 {SL_ENGINEOPTION_THREADSAFE, static_cast<SLuint32>(SL_BOOLEAN_TRUE)}};
207 LOG_ON_FAILURE_AND_RETURN(
208 slCreateEngine(engine_object_.Receive(), 1, option, 0, nullptr, nullptr),
209 false);
210
211 // Realize the SL engine object in synchronous mode.
212 LOG_ON_FAILURE_AND_RETURN(
213 engine_object_->Realize(engine_object_.Get(), SL_BOOLEAN_FALSE), false);
214
215 // Get the SL engine interface which is implicit.
216 SLEngineItf engine;
217 LOG_ON_FAILURE_AND_RETURN(engine_object_->GetInterface(
218 engine_object_.Get(), SL_IID_ENGINE, &engine),
219 false);
220
221 // Audio source configuration.
222 SLDataLocator_IODevice mic_locator = {SL_DATALOCATOR_IODEVICE,
223 SL_IODEVICE_AUDIOINPUT,
224 SL_DEFAULTDEVICEID_AUDIOINPUT, nullptr};
225 SLDataSource audio_source = {&mic_locator, nullptr};
226
227 // Audio sink configuration.
228 SLDataLocator_AndroidSimpleBufferQueue buffer_queue = {
229 SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE,
230 static_cast<SLuint32>(kMaxNumOfBuffersInQueue)};
231 SLDataSink audio_sink = {&buffer_queue, &format_};
232
233 // Create an audio recorder.
234 const SLInterfaceID interface_id[] = {SL_IID_ANDROIDSIMPLEBUFFERQUEUE,
235 SL_IID_ANDROIDCONFIGURATION};
236 const SLboolean interface_required[] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE};
237
238 // Create AudioRecorder and specify SL_IID_ANDROIDCONFIGURATION.
239 LOG_ON_FAILURE_AND_RETURN(
240 (*engine)->CreateAudioRecorder(
241 engine, recorder_object_.Receive(), &audio_source, &audio_sink,
242 base::size(interface_id), interface_id, interface_required),
243 false);
244
245 SLAndroidConfigurationItf recorder_config;
246 LOG_ON_FAILURE_AND_RETURN(
247 recorder_object_->GetInterface(recorder_object_.Get(),
248 SL_IID_ANDROIDCONFIGURATION,
249 &recorder_config),
250 false);
251
252 // Uses the main microphone tuned for audio communications if effects are
253 // enabled and disables all audio processing if effects are disabled.
254 SLint32 stream_type = no_effects_
255 ? SL_ANDROID_RECORDING_PRESET_CAMCORDER
256 : SL_ANDROID_RECORDING_PRESET_VOICE_COMMUNICATION;
257 LOG_ON_FAILURE_AND_RETURN(
258 (*recorder_config)->SetConfiguration(recorder_config,
259 SL_ANDROID_KEY_RECORDING_PRESET,
260 &stream_type,
261 sizeof(SLint32)),
262 false);
263
264 // Realize the recorder object in synchronous mode.
265 LOG_ON_FAILURE_AND_RETURN(
266 recorder_object_->Realize(recorder_object_.Get(), SL_BOOLEAN_FALSE),
267 false);
268
269 // Get an implicit recorder interface.
270 LOG_ON_FAILURE_AND_RETURN(
271 recorder_object_->GetInterface(
272 recorder_object_.Get(), SL_IID_RECORD, &recorder_),
273 false);
274
275 // Get the simple buffer queue interface.
276 LOG_ON_FAILURE_AND_RETURN(
277 recorder_object_->GetInterface(recorder_object_.Get(),
278 SL_IID_ANDROIDSIMPLEBUFFERQUEUE,
279 &simple_buffer_queue_),
280 false);
281
282 // Register the input callback for the simple buffer queue.
283 // This callback will be called when receiving new data from the device.
284 LOG_ON_FAILURE_AND_RETURN(
285 (*simple_buffer_queue_)->RegisterCallback(
286 simple_buffer_queue_, SimpleBufferQueueCallback, this),
287 false);
288
289 return true;
290 }
291
SimpleBufferQueueCallback(SLAndroidSimpleBufferQueueItf buffer_queue,void * instance)292 void OpenSLESInputStream::SimpleBufferQueueCallback(
293 SLAndroidSimpleBufferQueueItf buffer_queue,
294 void* instance) {
295 OpenSLESInputStream* stream =
296 reinterpret_cast<OpenSLESInputStream*>(instance);
297 stream->ReadBufferQueue();
298 }
299
ReadBufferQueue()300 void OpenSLESInputStream::ReadBufferQueue() {
301 base::AutoLock lock(lock_);
302 if (!started_)
303 return;
304
305 TRACE_EVENT0("audio", "OpenSLESOutputStream::ReadBufferQueue");
306
307 // Convert from interleaved format to deinterleaved audio bus format.
308 audio_bus_->FromInterleaved<SignedInt16SampleTypeTraits>(
309 reinterpret_cast<int16_t*>(audio_data_[active_buffer_index_]),
310 audio_bus_->frames());
311
312 // TODO(henrika): Investigate if it is possible to get an accurate
313 // delay estimation.
314 callback_->OnData(audio_bus_.get(), base::TimeTicks::Now() - hardware_delay_,
315 0.0);
316
317 // Done with this buffer. Send it to device for recording.
318 SLresult err =
319 (*simple_buffer_queue_)->Enqueue(simple_buffer_queue_,
320 audio_data_[active_buffer_index_],
321 buffer_size_bytes_);
322 if (SL_RESULT_SUCCESS != err)
323 HandleError(err);
324
325 active_buffer_index_ = (active_buffer_index_ + 1) % kMaxNumOfBuffersInQueue;
326 }
327
SetupAudioBuffer()328 void OpenSLESInputStream::SetupAudioBuffer() {
329 DCHECK(thread_checker_.CalledOnValidThread());
330 DCHECK(!audio_data_[0]);
331 for (int i = 0; i < kMaxNumOfBuffersInQueue; ++i) {
332 audio_data_[i] = new uint8_t[buffer_size_bytes_];
333 }
334 }
335
ReleaseAudioBuffer()336 void OpenSLESInputStream::ReleaseAudioBuffer() {
337 DCHECK(thread_checker_.CalledOnValidThread());
338 if (audio_data_[0]) {
339 for (int i = 0; i < kMaxNumOfBuffersInQueue; ++i) {
340 delete[] audio_data_[i];
341 audio_data_[i] = nullptr;
342 }
343 }
344 }
345
HandleError(SLresult error)346 void OpenSLESInputStream::HandleError(SLresult error) {
347 DLOG(ERROR) << "OpenSLES Input error " << error;
348 if (callback_)
349 callback_->OnError();
350 }
351
352 } // namespace media
353