blob: ddea87f6cb3d297e4daad334e26a8df808bad9a6 [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 Burk699e3aa2018-03-27 07:27:03 -070042 // OpenSL ES does not support device IDs. So overwrite value from builder.
43 mDeviceId = kUnspecified;
Don Turnerca6f91a2017-09-05 14:52:39 +010044}
45
Don Turner379e8e52017-11-29 15:49:29 +000046AudioStreamOpenSLES::~AudioStreamOpenSLES() {
Don Turnerca6f91a2017-09-05 14:52:39 +010047 delete[] mCallbackBuffer;
48}
49
Phil Burkc2243b12017-10-08 15:29:48 -070050static bool s_isLittleEndian() {
51 static uint32_t value = 1;
52 return *((uint8_t *) &value) == 1; // Does address point to LSB?
53}
54
Phil Burk9a147a12017-12-13 20:23:25 -080055SLuint32 AudioStreamOpenSLES::getDefaultByteOrder() {
Phil Burkc2243b12017-10-08 15:29:48 -070056 return s_isLittleEndian() ? SL_BYTEORDER_LITTLEENDIAN : SL_BYTEORDER_BIGENDIAN;
57}
58
Don Turner379e8e52017-11-29 15:49:29 +000059Result AudioStreamOpenSLES::open() {
Don Turnerca6f91a2017-09-05 14:52:39 +010060
Phil Burk9a147a12017-12-13 20:23:25 -080061 LOGI("AudioStreamOpenSLES::open(chans:%d, rate:%d)",
Don Turnerca6f91a2017-09-05 14:52:39 +010062 mChannelCount, mSampleRate);
63
Phil Burk09643562018-03-27 06:55:03 -070064 if (getSdkVersion() < __ANDROID_API_L__ && mFormat == AudioFormat::Float){
Don Turner2682fbd2017-09-12 16:25:58 +010065 // TODO: Allow floating point format on API <21 using float->int16 converter
Don Turner3bf32ae2017-11-27 13:25:05 +000066 return Result::ErrorInvalidFormat;
Don Turner2682fbd2017-09-12 16:25:58 +010067 }
68
Phil Burk7040a9d2017-12-15 10:54:38 -080069 SLresult result = EngineOpenSLES::getInstance().open();
Phil Burkd9703b02017-12-14 12:40:48 -080070 if (SL_RESULT_SUCCESS != result) {
71 return Result::ErrorInternal;
72 }
73
Don Turner2682fbd2017-09-12 16:25:58 +010074 // If audio format is unspecified then choose a suitable default.
75 // API 21+: FLOAT
76 // API <21: INT16
Don Turner3bf32ae2017-11-27 13:25:05 +000077 if (mFormat == AudioFormat::Unspecified){
Phil Burk09643562018-03-27 06:55:03 -070078 mFormat = (getSdkVersion() < __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
Phil Burk699e3aa2018-03-27 07:27:03 -070094 // Decide frames per burst based on hints from caller.
Phil Burkc2243b12017-10-08 15:29:48 -070095 // 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 Burka5d66372018-02-09 14:38:23 -0800111
112 if (!usingFIFO()) {
113 mBufferCapacityInFrames = mFramesPerBurst * kBufferQueueLength;
114 }
Don Turnerca6f91a2017-09-05 14:52:39 +0100115
Don Turner3bf32ae2017-11-27 13:25:05 +0000116 return Result::OK;
Don Turnerca6f91a2017-09-05 14:52:39 +0100117}
118
Don Turner379e8e52017-11-29 15:49:29 +0000119Result AudioStreamOpenSLES::close() {
Phil Burk477e01c2018-02-12 10:11:22 -0800120 if (mObjectInterface != nullptr) {
Phil Burk6d952912017-12-14 10:10:00 -0800121 (*mObjectInterface)->Destroy(mObjectInterface);
Phil Burk477e01c2018-02-12 10:11:22 -0800122 mObjectInterface = nullptr;
Phil Burk6d952912017-12-14 10:10:00 -0800123
124 }
Phil Burk477e01c2018-02-12 10:11:22 -0800125 mSimpleBufferQueueInterface = nullptr;
Phil Burk7040a9d2017-12-15 10:54:38 -0800126 EngineOpenSLES::getInstance().close();
Don Turner3bf32ae2017-11-27 13:25:05 +0000127 return Result::OK;
Don Turnerca6f91a2017-09-05 14:52:39 +0100128}
129
Phil Burk6d952912017-12-14 10:10:00 -0800130SLresult AudioStreamOpenSLES::enqueueCallbackBuffer(SLAndroidSimpleBufferQueueItf bq) {
131 return (*bq)->Enqueue(bq, mCallbackBuffer, mBytesPerCallback);
132}
133
134SLresult AudioStreamOpenSLES::processBufferCallback(SLAndroidSimpleBufferQueueItf bq) {
135 // Ask the callback to fill the output buffer with data.
Phil Burka5d66372018-02-09 14:38:23 -0800136 DataCallbackResult result = fireCallback(mCallbackBuffer, mFramesPerCallback);
137 if (result != DataCallbackResult::Continue) {
Phil Burk6d952912017-12-14 10:10:00 -0800138 LOGE("Oboe callback returned %d", result);
Phil Burka5d66372018-02-09 14:38:23 -0800139 return SL_RESULT_INTERNAL_ERROR; // TODO How should we stop OpenSL ES.
Phil Burk6d952912017-12-14 10:10:00 -0800140 } else {
Phil Burkf2a70532018-05-09 18:36:21 -0700141 updateServiceFrameCounter();
Phil Burk6d952912017-12-14 10:10:00 -0800142 // Pass the data to OpenSLES.
143 return enqueueCallbackBuffer(bq);
144 }
145}
146
147// this callback handler is called every time a buffer needs processing
148static void bqCallbackGlue(SLAndroidSimpleBufferQueueItf bq, void *context) {
149 ((AudioStreamOpenSLES *) context)->processBufferCallback(bq);
150}
151
152SLresult AudioStreamOpenSLES::registerBufferQueueCallback() {
153 // The BufferQueue
154 SLresult result = (*mObjectInterface)->GetInterface(mObjectInterface, SL_IID_ANDROIDSIMPLEBUFFERQUEUE,
155 &mSimpleBufferQueueInterface);
156 if (SL_RESULT_SUCCESS != result) {
Phil Burk7040a9d2017-12-15 10:54:38 -0800157 LOGE("get buffer queue interface:%p result:%s",
158 mSimpleBufferQueueInterface,
159 getSLErrStr(result));
Phil Burk6d952912017-12-14 10:10:00 -0800160 } else {
161 // Register the BufferQueue callback
162 result = (*mSimpleBufferQueueInterface)->RegisterCallback(mSimpleBufferQueueInterface,
163 bqCallbackGlue, this);
164 if (SL_RESULT_SUCCESS != result) {
165 LOGE("RegisterCallback result:%s", getSLErrStr(result));
166 }
167 }
168 return result;
169}
170
Don Turner379e8e52017-11-29 15:49:29 +0000171int32_t AudioStreamOpenSLES::getFramesPerBurst() {
Phil Burkc2243b12017-10-08 15:29:48 -0700172 return mFramesPerBurst;
Don Turnerca6f91a2017-09-05 14:52:39 +0100173}
Phil Burkb09eb332018-05-21 17:40:52 -0700174
175int64_t AudioStreamOpenSLES::getFramesProcessedByServer() const {
176 int64_t millis64 = mPositionMillis.get();
Phil Burk982d4fc2018-05-22 07:01:52 -0700177 int64_t framesProcessed = millis64 * getSampleRate() / kMillisPerSecond;
178 return framesProcessed;
Phil Burkb09eb332018-05-21 17:40:52 -0700179}