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