blob: 80ef90db5f79b15eeb11d35e66241821a13cf5e8 [file] [log] [blame]
Phil Burkc2243b12017-10-08 15:29:48 -07001/* Copyright 2015 The Android Open Source Project
Don Turnerca6f91a2017-09-05 14:52:39 +01002 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15#include <sys/types.h>
16#include <cassert>
17#include <android/log.h>
18
19
20#include <SLES/OpenSLES.h>
21#include <SLES/OpenSLES_Android.h>
22
23#include "common/OboeDebug.h"
Don Turner379e8e52017-11-29 15:49:29 +000024#include "oboe/AudioStreamBuilder.h"
25#include "AudioStreamOpenSLES.h"
Don Turner2682fbd2017-09-12 16:25:58 +010026#include "OpenSLESUtilities.h"
Don Turnerca6f91a2017-09-05 14:52:39 +010027
28#ifndef NULL
29#define NULL 0
30#endif
31
Phil Burkc2243b12017-10-08 15:29:48 -070032#define DEFAULT_FRAMES_PER_CALLBACK 192 // 4 msec at 48000 Hz
33#define DEFAULT_SAMPLE_RATE 48000 // very common rate for mobile audio and video
34#define DEFAULT_CHANNEL_COUNT 2 // stereo
35
Phil Burk64c55f42017-12-13 18:36:53 -080036using namespace oboe;
Don Turner3bf32ae2017-11-27 13:25:05 +000037
Don Turner379e8e52017-11-29 15:49:29 +000038AudioStreamOpenSLES::AudioStreamOpenSLES(const AudioStreamBuilder &builder)
39 : AudioStreamBuffered(builder) {
Phil Burk6d952912017-12-14 10:10:00 -080040 mSimpleBufferQueueInterface = NULL;
Phil Burkc2243b12017-10-08 15:29:48 -070041 mFramesPerBurst = builder.getDefaultFramesPerBurst();
Phil Burk64c55f42017-12-13 18:36:53 -080042 LOGD("AudioStreamOpenSLES(): after OpenSLContext()");
Don Turnerca6f91a2017-09-05 14:52:39 +010043}
44
Don Turner379e8e52017-11-29 15:49:29 +000045AudioStreamOpenSLES::~AudioStreamOpenSLES() {
Don Turnerca6f91a2017-09-05 14:52:39 +010046 delete[] mCallbackBuffer;
47}
48
Phil Burkc2243b12017-10-08 15:29:48 -070049static bool s_isLittleEndian() {
50 static uint32_t value = 1;
51 return *((uint8_t *) &value) == 1; // Does address point to LSB?
52}
53
Phil Burk9a147a12017-12-13 20:23:25 -080054SLuint32 AudioStreamOpenSLES::getDefaultByteOrder() {
Phil Burkc2243b12017-10-08 15:29:48 -070055 return s_isLittleEndian() ? SL_BYTEORDER_LITTLEENDIAN : SL_BYTEORDER_BIGENDIAN;
56}
57
Don Turner379e8e52017-11-29 15:49:29 +000058Result AudioStreamOpenSLES::open() {
Don Turnerca6f91a2017-09-05 14:52:39 +010059
Phil Burk9a147a12017-12-13 20:23:25 -080060 LOGI("AudioStreamOpenSLES::open(chans:%d, rate:%d)",
Don Turnerca6f91a2017-09-05 14:52:39 +010061 mChannelCount, mSampleRate);
62
Don Turner3bf32ae2017-11-27 13:25:05 +000063 if (__ANDROID_API__ < __ANDROID_API_L__ && mFormat == AudioFormat::Float){
Don Turner2682fbd2017-09-12 16:25:58 +010064 // TODO: Allow floating point format on API <21 using float->int16 converter
Don Turner3bf32ae2017-11-27 13:25:05 +000065 return Result::ErrorInvalidFormat;
Don Turner2682fbd2017-09-12 16:25:58 +010066 }
67
Phil Burk7040a9d2017-12-15 10:54:38 -080068 SLresult result = EngineOpenSLES::getInstance().open();
Phil Burkd9703b02017-12-14 12:40:48 -080069 if (SL_RESULT_SUCCESS != result) {
70 return Result::ErrorInternal;
71 }
72
Don Turner2682fbd2017-09-12 16:25:58 +010073 // If audio format is unspecified then choose a suitable default.
74 // API 21+: FLOAT
75 // API <21: INT16
Don Turner3bf32ae2017-11-27 13:25:05 +000076 if (mFormat == AudioFormat::Unspecified){
Phil Burk373e6462018-02-07 20:37:17 -080077 // TODO use runtime check
Don Turner2682fbd2017-09-12 16:25:58 +010078 mFormat = (__ANDROID_API__ < __ANDROID_API_L__) ?
Don Turner3bf32ae2017-11-27 13:25:05 +000079 AudioFormat::I16 : AudioFormat::Float;
Don Turner2682fbd2017-09-12 16:25:58 +010080 }
81
Don Turner379e8e52017-11-29 15:49:29 +000082 Result oboeResult = AudioStreamBuffered::open();
Don Turner3bf32ae2017-11-27 13:25:05 +000083 if (oboeResult != Result::OK) {
Don Turnerca6f91a2017-09-05 14:52:39 +010084 return oboeResult;
85 }
86 // Convert to defaults if UNSPECIFIED
Don Turner3bf32ae2017-11-27 13:25:05 +000087 if (mSampleRate == kUnspecified) {
Phil Burkc2243b12017-10-08 15:29:48 -070088 mSampleRate = DEFAULT_SAMPLE_RATE;
Don Turnerca6f91a2017-09-05 14:52:39 +010089 }
Don Turner3bf32ae2017-11-27 13:25:05 +000090 if (mChannelCount == kUnspecified) {
Phil Burkc2243b12017-10-08 15:29:48 -070091 mChannelCount = DEFAULT_CHANNEL_COUNT;
Don Turnerca6f91a2017-09-05 14:52:39 +010092 }
Phil Burkc2243b12017-10-08 15:29:48 -070093
94 // Decide frames per burst based hints from caller.
95 // TODO Can we query this from OpenSL ES?
Don Turner3bf32ae2017-11-27 13:25:05 +000096 if (mFramesPerCallback != kUnspecified) {
Phil Burkc2243b12017-10-08 15:29:48 -070097 mFramesPerBurst = mFramesPerCallback;
Don Turner3bf32ae2017-11-27 13:25:05 +000098 } else if (mFramesPerBurst != kUnspecified) { // set from defaultFramesPerBurst
Phil Burkc2243b12017-10-08 15:29:48 -070099 mFramesPerCallback = mFramesPerBurst;
100 } else {
101 mFramesPerBurst = mFramesPerCallback = DEFAULT_FRAMES_PER_CALLBACK;
Don Turnerca6f91a2017-09-05 14:52:39 +0100102 }
103
104 mBytesPerCallback = mFramesPerCallback * getBytesPerFrame();
Phil Burkd9703b02017-12-14 12:40:48 -0800105 delete[] mCallbackBuffer; // to prevent memory leaks
Don Turnerca6f91a2017-09-05 14:52:39 +0100106 mCallbackBuffer = new uint8_t[mBytesPerCallback];
Don Turner379e8e52017-11-29 15:49:29 +0000107 LOGD("AudioStreamOpenSLES(): mFramesPerCallback = %d", mFramesPerCallback);
108 LOGD("AudioStreamOpenSLES(): mBytesPerCallback = %d", mBytesPerCallback);
Don Turnerca6f91a2017-09-05 14:52:39 +0100109
Don Turner3bf32ae2017-11-27 13:25:05 +0000110 mSharingMode = SharingMode::Shared;
Phil Burkc2243b12017-10-08 15:29:48 -0700111 mBufferCapacityInFrames = mFramesPerBurst * mBurstsPerBuffer;
Don Turnerca6f91a2017-09-05 14:52:39 +0100112
Don Turner3bf32ae2017-11-27 13:25:05 +0000113 return Result::OK;
Don Turnerca6f91a2017-09-05 14:52:39 +0100114}
115
Don Turner379e8e52017-11-29 15:49:29 +0000116Result AudioStreamOpenSLES::close() {
Phil Burk6d952912017-12-14 10:10:00 -0800117 if (mObjectInterface != NULL) {
118 (*mObjectInterface)->Destroy(mObjectInterface);
119 mObjectInterface = NULL;
120
121 }
122 mSimpleBufferQueueInterface = NULL;
Phil Burk7040a9d2017-12-15 10:54:38 -0800123 EngineOpenSLES::getInstance().close();
Don Turner3bf32ae2017-11-27 13:25:05 +0000124 return Result::OK;
Don Turnerca6f91a2017-09-05 14:52:39 +0100125}
126
Phil Burk6d952912017-12-14 10:10:00 -0800127SLresult AudioStreamOpenSLES::enqueueCallbackBuffer(SLAndroidSimpleBufferQueueItf bq) {
128 return (*bq)->Enqueue(bq, mCallbackBuffer, mBytesPerCallback);
129}
130
131SLresult AudioStreamOpenSLES::processBufferCallback(SLAndroidSimpleBufferQueueItf bq) {
132 // Ask the callback to fill the output buffer with data.
133 Result result = fireCallback(mCallbackBuffer, mFramesPerCallback);
134 if (result != Result::OK) {
135 LOGE("Oboe callback returned %d", result);
136 return SL_RESULT_INTERNAL_ERROR;
137 } else {
138 // Pass the data to OpenSLES.
139 return enqueueCallbackBuffer(bq);
140 }
141}
142
143// this callback handler is called every time a buffer needs processing
144static void bqCallbackGlue(SLAndroidSimpleBufferQueueItf bq, void *context) {
145 ((AudioStreamOpenSLES *) context)->processBufferCallback(bq);
146}
147
148SLresult AudioStreamOpenSLES::registerBufferQueueCallback() {
149 // The BufferQueue
150 SLresult result = (*mObjectInterface)->GetInterface(mObjectInterface, SL_IID_ANDROIDSIMPLEBUFFERQUEUE,
151 &mSimpleBufferQueueInterface);
152 if (SL_RESULT_SUCCESS != result) {
Phil Burk7040a9d2017-12-15 10:54:38 -0800153 LOGE("get buffer queue interface:%p result:%s",
154 mSimpleBufferQueueInterface,
155 getSLErrStr(result));
Phil Burk6d952912017-12-14 10:10:00 -0800156 } else {
157 // Register the BufferQueue callback
158 result = (*mSimpleBufferQueueInterface)->RegisterCallback(mSimpleBufferQueueInterface,
159 bqCallbackGlue, this);
160 if (SL_RESULT_SUCCESS != result) {
161 LOGE("RegisterCallback result:%s", getSLErrStr(result));
162 }
163 }
164 return result;
165}
166
Don Turner379e8e52017-11-29 15:49:29 +0000167int32_t AudioStreamOpenSLES::getFramesPerBurst() {
Phil Burkc2243b12017-10-08 15:29:48 -0700168 return mFramesPerBurst;
Don Turnerca6f91a2017-09-05 14:52:39 +0100169}