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