blob: c4ea4bbf02dd3fe68c43e1e24a385fe301d84355 [file] [log] [blame]
Phil Burk64c55f42017-12-13 18:36:53 -08001/*
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
Phil Burk9a147a12017-12-13 20:23:25 -080017#include <cassert>
18
19#include <SLES/OpenSLES.h>
20#include <SLES/OpenSLES_Android.h>
21
Phil Burk64c55f42017-12-13 18:36:53 -080022#include "oboe/AudioStreamBuilder.h"
23#include "AudioOutputStreamOpenSLES.h"
24#include "AudioStreamOpenSLES.h"
Phil Burk9a147a12017-12-13 20:23:25 -080025#include "OpenSLESUtilities.h"
Phil Burk420715b2017-12-14 12:26:38 -080026#include "OutputMixerOpenSLES.h"
Phil Burk64c55f42017-12-13 18:36:53 -080027
28using namespace oboe;
29
Phil Burk64c55f42017-12-13 18:36:53 -080030AudioOutputStreamOpenSLES::AudioOutputStreamOpenSLES(const AudioStreamBuilder &builder)
31 : AudioStreamOpenSLES(builder) {
32}
33
34AudioOutputStreamOpenSLES::~AudioOutputStreamOpenSLES() {
Phil Burk9a147a12017-12-13 20:23:25 -080035}
36
37// These will wind up in <SLES/OpenSLES_Android.h>
Phil Burk7040a9d2017-12-15 10:54:38 -080038constexpr int SL_ANDROID_SPEAKER_STEREO = (SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT);
Phil Burk9a147a12017-12-13 20:23:25 -080039
Phil Burk7040a9d2017-12-15 10:54:38 -080040constexpr int SL_ANDROID_SPEAKER_QUAD = (SL_ANDROID_SPEAKER_STEREO
41 | SL_SPEAKER_BACK_LEFT | SL_SPEAKER_BACK_RIGHT);
Phil Burk9a147a12017-12-13 20:23:25 -080042
Phil Burk7040a9d2017-12-15 10:54:38 -080043constexpr int SL_ANDROID_SPEAKER_5DOT1 = (SL_ANDROID_SPEAKER_QUAD
44 | SL_SPEAKER_FRONT_CENTER | SL_SPEAKER_LOW_FREQUENCY);
45
46constexpr int SL_ANDROID_SPEAKER_7DOT1 = (SL_ANDROID_SPEAKER_5DOT1 | SL_SPEAKER_SIDE_LEFT
47 | SL_SPEAKER_SIDE_RIGHT);
Phil Burk9a147a12017-12-13 20:23:25 -080048
49int AudioOutputStreamOpenSLES::chanCountToChanMask(int chanCount) {
50 int channelMask = 0;
51
52 switch (chanCount) {
53 case 1:
54 channelMask = SL_SPEAKER_FRONT_CENTER;
55 break;
56
57 case 2:
Phil Burk7040a9d2017-12-15 10:54:38 -080058 channelMask = SL_ANDROID_SPEAKER_STEREO;
Phil Burk9a147a12017-12-13 20:23:25 -080059 break;
60
61 case 4: // Quad
62 channelMask = SL_ANDROID_SPEAKER_QUAD;
63 break;
64
65 case 6: // 5.1
66 channelMask = SL_ANDROID_SPEAKER_5DOT1;
67 break;
68
69 case 8: // 7.1
70 channelMask = SL_ANDROID_SPEAKER_7DOT1;
71 break;
72 }
73 return channelMask;
74}
75
Phil Burk9a147a12017-12-13 20:23:25 -080076Result AudioOutputStreamOpenSLES::open() {
Phil Burk9a147a12017-12-13 20:23:25 -080077 Result oboeResult = AudioStreamOpenSLES::open();
78 if (Result::OK != oboeResult) return oboeResult;
79
Phil Burk7040a9d2017-12-15 10:54:38 -080080 SLresult result = OutputMixerOpenSL::getInstance().open();
Phil Burkd9703b02017-12-14 12:40:48 -080081 if (SL_RESULT_SUCCESS != result) {
82 AudioStreamOpenSLES::close();
83 return Result::ErrorInternal;
84 }
85
Phil Burk7040a9d2017-12-15 10:54:38 -080086 SLuint32 bitsPerSample = getBytesPerSample() * kBitsPerByte;
Phil Burk9a147a12017-12-13 20:23:25 -080087
88 // configure audio source
89 SLDataLocator_AndroidSimpleBufferQueue loc_bufq = {
90 SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, // locatorType
91 static_cast<SLuint32>(mBurstsPerBuffer)}; // numBuffers
92
93 // Define the audio data format.
94 SLDataFormat_PCM format_pcm = {
95 SL_DATAFORMAT_PCM, // formatType
96 (SLuint32) mChannelCount, // numChannels
97 (SLuint32) (mSampleRate * kMillisPerSecond), // milliSamplesPerSec
98 bitsPerSample, // bitsPerSample
99 bitsPerSample, // containerSize;
100 (SLuint32) chanCountToChanMask(mChannelCount), // channelMask
101 getDefaultByteOrder(),
102 };
103
104 SLDataSource audioSrc = {&loc_bufq, &format_pcm};
105
106 /**
107 * API 21 (Lollipop) introduced support for floating-point data representation and an extended
108 * data format type: SLAndroidDataFormat_PCM_EX. If running on API 21+ use this newer format
109 * type, creating it from our original format.
110 */
Phil Burk6d952912017-12-14 10:10:00 -0800111 SLAndroidDataFormat_PCM_EX format_pcm_ex;
Phil Burk9a147a12017-12-13 20:23:25 -0800112 if (__ANDROID_API__ >= __ANDROID_API_L__) {
113 SLuint32 representation = OpenSLES_ConvertFormatToRepresentation(getFormat());
Phil Burk6d952912017-12-14 10:10:00 -0800114 // Fill in the format structure.
115 format_pcm_ex = OpenSLES_createExtendedFormat(format_pcm, representation);
116 // Use in place of the previous format.
Phil Burk9a147a12017-12-13 20:23:25 -0800117 audioSrc.pFormat = &format_pcm_ex;
118 }
119
Phil Burk7040a9d2017-12-15 10:54:38 -0800120 result = OutputMixerOpenSL::getInstance().createAudioPlayer(&mObjectInterface,
Phil Burk9a147a12017-12-13 20:23:25 -0800121 &audioSrc);
122 if (SL_RESULT_SUCCESS != result) {
123 LOGE("createAudioPlayer() result:%s", getSLErrStr(result));
124 goto error;
125 }
126
Phil Burk6d952912017-12-14 10:10:00 -0800127 result = (*mObjectInterface)->Realize(mObjectInterface, SL_BOOLEAN_FALSE);
Phil Burk9a147a12017-12-13 20:23:25 -0800128 if (SL_RESULT_SUCCESS != result) {
129 LOGE("Realize player object result:%s", getSLErrStr(result));
130 goto error;
131 }
132
Phil Burk6d952912017-12-14 10:10:00 -0800133 result = (*mObjectInterface)->GetInterface(mObjectInterface, SL_IID_PLAY, &mPlayInterface);
Phil Burk9a147a12017-12-13 20:23:25 -0800134 if (SL_RESULT_SUCCESS != result) {
Phil Burk7040a9d2017-12-15 10:54:38 -0800135 LOGE("GetInterface PLAY result:%s", getSLErrStr(result));
Phil Burk9a147a12017-12-13 20:23:25 -0800136 goto error;
137 }
138
Phil Burk6d952912017-12-14 10:10:00 -0800139 result = AudioStreamOpenSLES::registerBufferQueueCallback();
Phil Burk9a147a12017-12-13 20:23:25 -0800140 if (SL_RESULT_SUCCESS != result) {
Phil Burk9a147a12017-12-13 20:23:25 -0800141 goto error;
142 }
143
Phil Burk373e6462018-02-07 20:37:17 -0800144 oboeResult = finishOpen();
145 if (oboeResult != oboe::Result::OK) {
146 goto error;
147 }
148
Phil Burk9a147a12017-12-13 20:23:25 -0800149 return Result::OK;
150error:
151 return Result::ErrorInternal; // TODO convert error from SLES to OBOE
152}
153
154Result AudioOutputStreamOpenSLES::close() {
155 requestPause();
Phil Burk6d952912017-12-14 10:10:00 -0800156 // invalidate any interfaces
157 mPlayInterface = NULL;
Phil Burk7040a9d2017-12-15 10:54:38 -0800158 OutputMixerOpenSL::getInstance().close();
Phil Burk9a147a12017-12-13 20:23:25 -0800159 return AudioStreamOpenSLES::close();
160}
161
162Result AudioOutputStreamOpenSLES::setPlayState(SLuint32 newState) {
163 Result result = Result::OK;
164 LOGD("AudioOutputStreamOpenSLES(): setPlayState()");
Phil Burk6d952912017-12-14 10:10:00 -0800165 if (mPlayInterface == NULL) {
Phil Burk9a147a12017-12-13 20:23:25 -0800166 return Result::ErrorInvalidState;
167 }
Phil Burk6d952912017-12-14 10:10:00 -0800168 SLresult slResult = (*mPlayInterface)->SetPlayState(mPlayInterface, newState);
Phil Burk9a147a12017-12-13 20:23:25 -0800169 if(SL_RESULT_SUCCESS != slResult) {
170 LOGD("AudioOutputStreamOpenSLES(): setPlayState() returned %s", getSLErrStr(slResult));
171 result = Result::ErrorInvalidState; // TODO review
172 } else {
173 setState(StreamState::Pausing);
174 }
175 return result;
176}
177
178Result AudioOutputStreamOpenSLES::requestStart() {
179 LOGD("AudioOutputStreamOpenSLES(): requestStart()");
180 Result result = setPlayState(SL_PLAYSTATE_PLAYING);
181 if(result != Result::OK) {
182 result = Result::ErrorInvalidState; // TODO review
183 } else {
Phil Burk6d952912017-12-14 10:10:00 -0800184 processBufferCallback(mSimpleBufferQueueInterface);
Phil Burk9a147a12017-12-13 20:23:25 -0800185 setState(StreamState::Starting);
186 }
187 return result;
188}
189
190Result AudioOutputStreamOpenSLES::requestPause() {
191 LOGD("AudioOutputStreamOpenSLES(): requestPause()");
192 Result result = setPlayState(SL_PLAYSTATE_PAUSED);
193 if(result != Result::OK) {
194 result = Result::ErrorInvalidState; // TODO review
195 } else {
196 setState(StreamState::Pausing);
197 }
198 return result;
199}
200
201Result AudioOutputStreamOpenSLES::requestFlush() {
202 LOGD("AudioOutputStreamOpenSLES(): requestFlush()");
Phil Burk6d952912017-12-14 10:10:00 -0800203 if (mPlayInterface == NULL) {
Phil Burk9a147a12017-12-13 20:23:25 -0800204 return Result::ErrorInvalidState;
205 }
206 return Result::ErrorUnimplemented; // TODO
207}
208
209Result AudioOutputStreamOpenSLES::requestStop() {
210 LOGD("AudioOutputStreamOpenSLES(): requestStop()");
211 Result result = setPlayState(SL_PLAYSTATE_STOPPED);
212 if(result != Result::OK) {
213 result = Result::ErrorInvalidState; // TODO review
214 } else {
215 setState(StreamState::Stopping);
216 }
217 return result;
218}
219
220Result AudioOutputStreamOpenSLES::waitForStateChange(StreamState currentState,
221 StreamState *nextState,
222 int64_t timeoutNanoseconds) {
223 LOGD("AudioOutputStreamOpenSLES::waitForStateChange()");
Phil Burk6d952912017-12-14 10:10:00 -0800224 if (mPlayInterface == NULL) {
Phil Burk9a147a12017-12-13 20:23:25 -0800225 return Result::ErrorInvalidState;
226 }
227 return Result::ErrorUnimplemented; // TODO
Phil Burk64c55f42017-12-13 18:36:53 -0800228}