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.
5 #include "media/audio/android/opensles_input.h"
7 #include "base/logging.h"
8 #include "base/trace_event/trace_event.h"
9 #include "media/audio/android/audio_manager_android.h"
10 #include "media/base/audio_bus.h"
12 #define LOG_ON_FAILURE_AND_RETURN(op, ...) \
14 SLresult err = (op); \
15 if (err != SL_RESULT_SUCCESS) { \
16 DLOG(ERROR) << #op << " failed: " << err; \
23 OpenSLESInputStream::OpenSLESInputStream(AudioManagerAndroid
* audio_manager
,
24 const AudioParameters
& params
)
25 : audio_manager_(audio_manager
),
28 simple_buffer_queue_(NULL
),
29 active_buffer_index_(0),
30 buffer_size_bytes_(0),
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
;
46 NOTREACHED() << "Unsupported number of channels: " << format_
.numChannels
;
48 buffer_size_bytes_
= params
.GetBytesPerBuffer();
50 memset(&audio_data_
, 0, sizeof(audio_data_
));
53 OpenSLESInputStream::~OpenSLESInputStream() {
54 DVLOG(2) << __PRETTY_FUNCTION__
;
55 DCHECK(thread_checker_
.CalledOnValidThread());
56 DCHECK(!recorder_object_
.Get());
57 DCHECK(!engine_object_
.Get());
59 DCHECK(!simple_buffer_queue_
);
60 DCHECK(!audio_data_
[0]);
63 bool OpenSLESInputStream::Open() {
64 DVLOG(2) << __PRETTY_FUNCTION__
;
65 DCHECK(thread_checker_
.CalledOnValidThread());
66 if (engine_object_
.Get())
69 if (!CreateRecorder())
77 void OpenSLESInputStream::Start(AudioInputCallback
* callback
) {
78 DVLOG(2) << __PRETTY_FUNCTION__
;
79 DCHECK(thread_checker_
.CalledOnValidThread());
82 DCHECK(simple_buffer_queue_
);
86 base::AutoLock
lock(lock_
);
87 DCHECK(callback_
== NULL
|| callback_
== callback
);
89 active_buffer_index_
= 0;
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
) {
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
) {
120 void OpenSLESInputStream::Stop() {
121 DVLOG(2) << __PRETTY_FUNCTION__
;
122 DCHECK(thread_checker_
.CalledOnValidThread());
126 base::AutoLock
lock(lock_
);
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
));
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_
));
140 void OpenSLESInputStream::Close() {
141 DVLOG(2) << __PRETTY_FUNCTION__
;
142 DCHECK(thread_checker_
.CalledOnValidThread());
144 // Stop the stream if it is still recording.
147 // TODO(henrika): Do we need to hold the lock here?
148 base::AutoLock
lock(lock_
);
150 // Destroy the buffer queue recorder object and invalidate all associated
152 recorder_object_
.Reset();
153 simple_buffer_queue_
= NULL
;
156 // Destroy the engine object. We don't store any associated interface for
158 engine_object_
.Reset();
159 ReleaseAudioBuffer();
162 audio_manager_
->ReleaseInputStream(this);
165 double OpenSLESInputStream::GetMaxVolume() {
170 void OpenSLESInputStream::SetVolume(double volume
) {
174 double OpenSLESInputStream::GetVolume() {
179 bool OpenSLESInputStream::SetAutomaticGainControl(bool enabled
) {
184 bool OpenSLESInputStream::GetAutomaticGainControl() {
189 bool OpenSLESInputStream::IsMuted() {
194 bool OpenSLESInputStream::CreateRecorder() {
195 DCHECK(thread_checker_
.CalledOnValidThread());
196 DCHECK(!engine_object_
.Get());
197 DCHECK(!recorder_object_
.Get());
199 DCHECK(!simple_buffer_queue_
);
201 // Initializes the engine object with specific option. After working with the
202 // object, we need to free the object and its resources.
203 SLEngineOption option
[] = {
204 {SL_ENGINEOPTION_THREADSAFE
, static_cast<SLuint32
>(SL_BOOLEAN_TRUE
)}};
205 LOG_ON_FAILURE_AND_RETURN(
206 slCreateEngine(engine_object_
.Receive(), 1, option
, 0, NULL
, NULL
),
209 // Realize the SL engine object in synchronous mode.
210 LOG_ON_FAILURE_AND_RETURN(
211 engine_object_
->Realize(engine_object_
.Get(), SL_BOOLEAN_FALSE
), false);
213 // Get the SL engine interface which is implicit.
215 LOG_ON_FAILURE_AND_RETURN(engine_object_
->GetInterface(
216 engine_object_
.Get(), SL_IID_ENGINE
, &engine
),
219 // Audio source configuration.
220 SLDataLocator_IODevice mic_locator
= {
221 SL_DATALOCATOR_IODEVICE
, SL_IODEVICE_AUDIOINPUT
,
222 SL_DEFAULTDEVICEID_AUDIOINPUT
, NULL
};
223 SLDataSource audio_source
= {&mic_locator
, NULL
};
225 // Audio sink configuration.
226 SLDataLocator_AndroidSimpleBufferQueue buffer_queue
= {
227 SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE
,
228 static_cast<SLuint32
>(kMaxNumOfBuffersInQueue
)};
229 SLDataSink audio_sink
= {&buffer_queue
, &format_
};
231 // Create an audio recorder.
232 const SLInterfaceID interface_id
[] = {SL_IID_ANDROIDSIMPLEBUFFERQUEUE
,
233 SL_IID_ANDROIDCONFIGURATION
};
234 const SLboolean interface_required
[] = {SL_BOOLEAN_TRUE
, SL_BOOLEAN_TRUE
};
236 // Create AudioRecorder and specify SL_IID_ANDROIDCONFIGURATION.
237 LOG_ON_FAILURE_AND_RETURN(
238 (*engine
)->CreateAudioRecorder(engine
,
239 recorder_object_
.Receive(),
242 arraysize(interface_id
),
247 SLAndroidConfigurationItf recorder_config
;
248 LOG_ON_FAILURE_AND_RETURN(
249 recorder_object_
->GetInterface(recorder_object_
.Get(),
250 SL_IID_ANDROIDCONFIGURATION
,
254 // Uses the main microphone tuned for audio communications.
255 SLint32 stream_type
= SL_ANDROID_RECORDING_PRESET_VOICE_COMMUNICATION
;
256 LOG_ON_FAILURE_AND_RETURN(
257 (*recorder_config
)->SetConfiguration(recorder_config
,
258 SL_ANDROID_KEY_RECORDING_PRESET
,
263 // Realize the recorder object in synchronous mode.
264 LOG_ON_FAILURE_AND_RETURN(
265 recorder_object_
->Realize(recorder_object_
.Get(), SL_BOOLEAN_FALSE
),
268 // Get an implicit recorder interface.
269 LOG_ON_FAILURE_AND_RETURN(
270 recorder_object_
->GetInterface(
271 recorder_object_
.Get(), SL_IID_RECORD
, &recorder_
),
274 // Get the simple buffer queue interface.
275 LOG_ON_FAILURE_AND_RETURN(
276 recorder_object_
->GetInterface(recorder_object_
.Get(),
277 SL_IID_ANDROIDSIMPLEBUFFERQUEUE
,
278 &simple_buffer_queue_
),
281 // Register the input callback for the simple buffer queue.
282 // This callback will be called when receiving new data from the device.
283 LOG_ON_FAILURE_AND_RETURN(
284 (*simple_buffer_queue_
)->RegisterCallback(
285 simple_buffer_queue_
, SimpleBufferQueueCallback
, this),
291 void OpenSLESInputStream::SimpleBufferQueueCallback(
292 SLAndroidSimpleBufferQueueItf buffer_queue
,
294 OpenSLESInputStream
* stream
=
295 reinterpret_cast<OpenSLESInputStream
*>(instance
);
296 stream
->ReadBufferQueue();
299 void OpenSLESInputStream::ReadBufferQueue() {
300 base::AutoLock
lock(lock_
);
304 TRACE_EVENT0("audio", "OpenSLESOutputStream::ReadBufferQueue");
306 // Convert from interleaved format to deinterleaved audio bus format.
307 audio_bus_
->FromInterleaved(audio_data_
[active_buffer_index_
],
308 audio_bus_
->frames(),
309 format_
.bitsPerSample
/ 8);
311 // TODO(henrika): Investigate if it is possible to get an accurate
313 callback_
->OnData(this, audio_bus_
.get(), buffer_size_bytes_
, 0.0);
315 // Done with this buffer. Send it to device for recording.
317 (*simple_buffer_queue_
)->Enqueue(simple_buffer_queue_
,
318 audio_data_
[active_buffer_index_
],
320 if (SL_RESULT_SUCCESS
!= err
)
323 active_buffer_index_
= (active_buffer_index_
+ 1) % kMaxNumOfBuffersInQueue
;
326 void OpenSLESInputStream::SetupAudioBuffer() {
327 DCHECK(thread_checker_
.CalledOnValidThread());
328 DCHECK(!audio_data_
[0]);
329 for (int i
= 0; i
< kMaxNumOfBuffersInQueue
; ++i
) {
330 audio_data_
[i
] = new uint8
[buffer_size_bytes_
];
334 void OpenSLESInputStream::ReleaseAudioBuffer() {
335 DCHECK(thread_checker_
.CalledOnValidThread());
336 if (audio_data_
[0]) {
337 for (int i
= 0; i
< kMaxNumOfBuffersInQueue
; ++i
) {
338 delete[] audio_data_
[i
];
339 audio_data_
[i
] = NULL
;
344 void OpenSLESInputStream::HandleError(SLresult error
) {
345 DLOG(ERROR
) << "OpenSLES Input error " << error
;
347 callback_
->OnError(this);