• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <cassert>
18 
19 #include <SLES/OpenSLES.h>
20 #include <SLES/OpenSLES_Android.h>
21 
22 #include "oboe/AudioStreamBuilder.h"
23 #include "AudioInputStreamOpenSLES.h"
24 #include "AudioStreamOpenSLES.h"
25 #include "OpenSLESUtilities.h"
26 
27 using namespace oboe;
28 
OpenSLES_convertInputPreset(InputPreset oboePreset)29 static SLuint32 OpenSLES_convertInputPreset(InputPreset oboePreset) {
30     SLuint32 openslPreset = SL_ANDROID_RECORDING_PRESET_NONE;
31     switch(oboePreset) {
32         case InputPreset::Generic:
33             openslPreset =  SL_ANDROID_RECORDING_PRESET_GENERIC;
34             break;
35         case InputPreset::Camcorder:
36             openslPreset =  SL_ANDROID_RECORDING_PRESET_CAMCORDER;
37             break;
38         case InputPreset::VoiceRecognition:
39             openslPreset =  SL_ANDROID_RECORDING_PRESET_VOICE_RECOGNITION;
40             break;
41         case InputPreset::VoiceCommunication:
42             openslPreset =  SL_ANDROID_RECORDING_PRESET_VOICE_COMMUNICATION;
43             break;
44         case InputPreset::Unprocessed:
45             openslPreset =  SL_ANDROID_RECORDING_PRESET_UNPROCESSED;
46             break;
47         default:
48             break;
49     }
50     return openslPreset;
51 }
52 
AudioInputStreamOpenSLES(const AudioStreamBuilder & builder)53 AudioInputStreamOpenSLES::AudioInputStreamOpenSLES(const AudioStreamBuilder &builder)
54         : AudioStreamOpenSLES(builder) {
55 }
56 
~AudioInputStreamOpenSLES()57 AudioInputStreamOpenSLES::~AudioInputStreamOpenSLES() {
58 }
59 
60 // Calculate masks specific to INPUT streams.
channelCountToChannelMask(int channelCount) const61 SLuint32 AudioInputStreamOpenSLES::channelCountToChannelMask(int channelCount) const {
62     // Derived from internal sles_channel_in_mask_from_count(chanCount);
63     // in "frameworks/wilhelm/src/android/channels.cpp".
64     // Yes, it seems strange to use SPEAKER constants to describe inputs.
65     // But that is how OpenSL ES does it internally.
66     switch (channelCount) {
67         case 1:
68             return SL_SPEAKER_FRONT_LEFT;
69         case 2:
70             return SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT;
71         default:
72             return channelCountToChannelMaskDefault(channelCount);
73     }
74 }
75 
open()76 Result AudioInputStreamOpenSLES::open() {
77     logUnsupportedAttributes();
78 
79     SLAndroidConfigurationItf configItf = nullptr;
80 
81     if (getSdkVersion() < __ANDROID_API_M__ && mFormat == AudioFormat::Float){
82         // TODO: Allow floating point format on API <23 using float->int16 converter
83         return Result::ErrorInvalidFormat;
84     }
85 
86     // If audio format is unspecified then choose a suitable default.
87     // API 23+: FLOAT
88     // API <23: INT16
89     if (mFormat == AudioFormat::Unspecified){
90         mFormat = (getSdkVersion() < __ANDROID_API_M__) ?
91                   AudioFormat::I16 : AudioFormat::Float;
92     }
93 
94     Result oboeResult = AudioStreamOpenSLES::open();
95     if (Result::OK != oboeResult) return oboeResult;
96 
97     SLuint32 bitsPerSample = static_cast<SLuint32>(getBytesPerSample() * kBitsPerByte);
98 
99     // configure audio sink
100     SLDataLocator_AndroidSimpleBufferQueue loc_bufq = {
101             SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE,    // locatorType
102             static_cast<SLuint32>(kBufferQueueLength)};   // numBuffers
103 
104     // Define the audio data format.
105     SLDataFormat_PCM format_pcm = {
106             SL_DATAFORMAT_PCM,       // formatType
107             static_cast<SLuint32>(mChannelCount),           // numChannels
108             static_cast<SLuint32>(mSampleRate * kMillisPerSecond), // milliSamplesPerSec
109             bitsPerSample,                      // bitsPerSample
110             bitsPerSample,                      // containerSize;
111             channelCountToChannelMask(mChannelCount), // channelMask
112             getDefaultByteOrder(),
113     };
114 
115     SLDataSink audioSink = {&loc_bufq, &format_pcm};
116 
117     /**
118      * API 23 (Marshmallow) introduced support for floating-point data representation and an
119      * extended data format type: SLAndroidDataFormat_PCM_EX for recording streams (playback streams
120      * got this in API 21). If running on API 23+ use this newer format type, creating it from our
121      * original format.
122      */
123     SLAndroidDataFormat_PCM_EX format_pcm_ex;
124     if (getSdkVersion() >= __ANDROID_API_M__) {
125         SLuint32 representation = OpenSLES_ConvertFormatToRepresentation(getFormat());
126         // Fill in the format structure.
127         format_pcm_ex = OpenSLES_createExtendedFormat(format_pcm, representation);
128         // Use in place of the previous format.
129         audioSink.pFormat = &format_pcm_ex;
130     }
131 
132 
133     // configure audio source
134     SLDataLocator_IODevice loc_dev = {SL_DATALOCATOR_IODEVICE,
135                                       SL_IODEVICE_AUDIOINPUT,
136                                       SL_DEFAULTDEVICEID_AUDIOINPUT,
137                                       NULL};
138     SLDataSource audioSrc = {&loc_dev, NULL};
139 
140     SLresult result = EngineOpenSLES::getInstance().createAudioRecorder(&mObjectInterface,
141                                                                         &audioSrc,
142                                                                         &audioSink);
143 
144     if (SL_RESULT_SUCCESS != result) {
145         LOGE("createAudioRecorder() result:%s", getSLErrStr(result));
146         goto error;
147     }
148 
149     // Configure the stream.
150     result = (*mObjectInterface)->GetInterface(mObjectInterface,
151                                             SL_IID_ANDROIDCONFIGURATION,
152                                             &configItf);
153 
154     if (SL_RESULT_SUCCESS != result) {
155         LOGW("%s() GetInterface(SL_IID_ANDROIDCONFIGURATION) failed with %s",
156              __func__, getSLErrStr(result));
157     } else {
158         SLuint32 presetValue = OpenSLES_convertInputPreset(getInputPreset());
159         result = (*configItf)->SetConfiguration(configItf,
160                                          SL_ANDROID_KEY_RECORDING_PRESET,
161                                          &presetValue,
162                                          sizeof(SLuint32));
163         if (SL_RESULT_SUCCESS != result
164             && presetValue != SL_ANDROID_RECORDING_PRESET_VOICE_RECOGNITION) {
165             presetValue = SL_ANDROID_RECORDING_PRESET_VOICE_RECOGNITION;
166             mInputPreset = InputPreset::VoiceRecognition;
167             (*configItf)->SetConfiguration(configItf,
168                                              SL_ANDROID_KEY_RECORDING_PRESET,
169                                              &presetValue,
170                                              sizeof(SLuint32));
171         }
172 
173         result = configurePerformanceMode(configItf);
174         if (SL_RESULT_SUCCESS != result) {
175             goto error;
176         }
177     }
178 
179     result = (*mObjectInterface)->Realize(mObjectInterface, SL_BOOLEAN_FALSE);
180     if (SL_RESULT_SUCCESS != result) {
181         LOGE("Realize recorder object result:%s", getSLErrStr(result));
182         goto error;
183     }
184 
185     result = (*mObjectInterface)->GetInterface(mObjectInterface, SL_IID_RECORD, &mRecordInterface);
186     if (SL_RESULT_SUCCESS != result) {
187         LOGE("GetInterface RECORD result:%s", getSLErrStr(result));
188         goto error;
189     }
190 
191     result = AudioStreamOpenSLES::registerBufferQueueCallback();
192     if (SL_RESULT_SUCCESS != result) {
193         goto error;
194     }
195 
196     result = updateStreamParameters(configItf);
197     if (SL_RESULT_SUCCESS != result) {
198         goto error;
199     }
200 
201     oboeResult = configureBufferSizes(mSampleRate);
202     if (Result::OK != oboeResult) {
203         goto error;
204     }
205 
206     allocateFifo();
207 
208     setState(StreamState::Open);
209     return Result::OK;
210 
211 error:
212     return Result::ErrorInternal; // TODO convert error from SLES to OBOE
213 }
214 
close()215 Result AudioInputStreamOpenSLES::close() {
216     LOGD("AudioInputStreamOpenSLES::%s()", __func__);
217     mLock.lock();
218     Result result = Result::OK;
219     if (getState() == StreamState::Closed){
220         result = Result::ErrorClosed;
221     } else {
222         mLock.unlock(); // avoid recursive lock
223         requestStop();
224         mLock.lock();
225         // invalidate any interfaces
226         mRecordInterface = nullptr;
227         result = AudioStreamOpenSLES::close();
228     }
229     mLock.unlock(); // avoid recursive lock
230     return result;
231 }
232 
setRecordState_l(SLuint32 newState)233 Result AudioInputStreamOpenSLES::setRecordState_l(SLuint32 newState) {
234     LOGD("AudioInputStreamOpenSLES::%s(%u)", __func__, newState);
235     Result result = Result::OK;
236 
237     if (mRecordInterface == nullptr) {
238         LOGE("AudioInputStreamOpenSLES::%s() mRecordInterface is null", __func__);
239         return Result::ErrorInvalidState;
240     }
241     SLresult slResult = (*mRecordInterface)->SetRecordState(mRecordInterface, newState);
242     //LOGD("AudioInputStreamOpenSLES::%s(%u) returned %u", __func__, newState, slResult);
243     if (SL_RESULT_SUCCESS != slResult) {
244         LOGE("AudioInputStreamOpenSLES::%s(%u) returned error %s",
245                 __func__, newState, getSLErrStr(slResult));
246         result = Result::ErrorInternal; // TODO review
247     }
248     return result;
249 }
250 
requestStart()251 Result AudioInputStreamOpenSLES::requestStart() {
252     LOGD("AudioInputStreamOpenSLES(): %s() called", __func__);
253     std::lock_guard<std::mutex> lock(mLock);
254     StreamState initialState = getState();
255     switch (initialState) {
256         case StreamState::Starting:
257         case StreamState::Started:
258             return Result::OK;
259         case StreamState::Closed:
260             return Result::ErrorClosed;
261         default:
262             break;
263     }
264 
265     // We use a callback if the user requests one
266     // OR if we have an internal callback to fill the blocking IO buffer.
267     setDataCallbackEnabled(true);
268 
269     setState(StreamState::Starting);
270     Result result = setRecordState_l(SL_RECORDSTATE_RECORDING);
271     if (result == Result::OK) {
272         setState(StreamState::Started);
273         // Enqueue the first buffer to start the streaming.
274         // This does not call the callback function.
275         enqueueCallbackBuffer(mSimpleBufferQueueInterface);
276     } else {
277         setState(initialState);
278     }
279     return result;
280 }
281 
282 
requestPause()283 Result AudioInputStreamOpenSLES::requestPause() {
284     LOGW("AudioInputStreamOpenSLES::%s() is intentionally not implemented for input "
285          "streams", __func__);
286     return Result::ErrorUnimplemented; // Matches AAudio behavior.
287 }
288 
requestFlush()289 Result AudioInputStreamOpenSLES::requestFlush() {
290     LOGW("AudioInputStreamOpenSLES::%s() is intentionally not implemented for input "
291          "streams", __func__);
292     return Result::ErrorUnimplemented; // Matches AAudio behavior.
293 }
294 
requestStop()295 Result AudioInputStreamOpenSLES::requestStop() {
296     LOGD("AudioInputStreamOpenSLES(): %s() called", __func__);
297 
298     std::lock_guard<std::mutex> lock(mLock);
299     StreamState initialState = getState();
300     switch (initialState) {
301         case StreamState::Stopping:
302         case StreamState::Stopped:
303             return Result::OK;
304         case StreamState::Closed:
305             return Result::ErrorClosed;
306         default:
307             break;
308     }
309 
310     setState(StreamState::Stopping);
311 
312     Result result = setRecordState_l(SL_RECORDSTATE_STOPPED);
313     if (result == Result::OK) {
314         mPositionMillis.reset32(); // OpenSL ES resets its millisecond position when stopped.
315         setState(StreamState::Stopped);
316     } else {
317         setState(initialState);
318     }
319     return result;
320 }
321 
updateFramesWritten()322 void AudioInputStreamOpenSLES::updateFramesWritten() {
323     if (usingFIFO()) {
324         AudioStreamBuffered::updateFramesWritten();
325     } else {
326         mFramesWritten = getFramesProcessedByServer();
327     }
328 }
329 
updateServiceFrameCounter()330 Result AudioInputStreamOpenSLES::updateServiceFrameCounter() {
331     Result result = Result::OK;
332     // Avoid deadlock if another thread is trying to stop or close this stream
333     // and this is being called from a callback.
334     if (mLock.try_lock()) {
335 
336         if (mRecordInterface == nullptr) {
337             mLock.unlock();
338             return Result::ErrorNull;
339         }
340         SLmillisecond msec = 0;
341         SLresult slResult = (*mRecordInterface)->GetPosition(mRecordInterface, &msec);
342         if (SL_RESULT_SUCCESS != slResult) {
343             LOGW("%s(): GetPosition() returned %s", __func__, getSLErrStr(slResult));
344             // set result based on SLresult
345             result = Result::ErrorInternal;
346         } else {
347             mPositionMillis.update32(msec);
348         }
349         mLock.unlock();
350     }
351     return result;
352 }
353