1 /*
2 * Copyright (C) 2015 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 //#define LOG_NDEBUG 0
18 #define LOG_TAG "OpenSL-ES-Test-B-1-1-Buffer-Queue"
19
20 #include "sl-utils.h"
21
22 /*
23 * See https://www.khronos.org/registry/sles/specs/OpenSL_ES_Specification_1.0.1.pdf
24 * Appendix B.1.1 sample code.
25 *
26 * Minor edits made to conform to Android coding style.
27 *
28 * Correction to code: SL_IID_VOLUME is now made optional for the mixer.
29 * It isn't supported on the standard Android mixer, but it is supported on the player.
30 */
31
32 #define MAX_NUMBER_INTERFACES 3
33
34 /* Local storage for Audio data in 16 bit words */
35 #define AUDIO_DATA_STORAGE_SIZE 4096
36
37 #define AUDIO_DATA_SEGMENTS 8
38
39 /* Audio data buffer size in 16 bit words. 8 data segments are used in
40 this simple example */
41 #define AUDIO_DATA_BUFFER_SIZE (AUDIO_DATA_STORAGE_SIZE / AUDIO_DATA_SEGMENTS)
42
43 /* Structure for passing information to callback function */
44 typedef struct {
45 SLPlayItf playItf;
46 SLint16 *pDataBase; // Base address of local audio data storage
47 SLint16 *pData; // Current address of local audio data storage
48 SLuint32 size;
49 } CallbackCntxt;
50
51 /* Local storage for Audio data */
52 static SLint16 pcmData[AUDIO_DATA_STORAGE_SIZE];
53
54 /* Callback for Buffer Queue events */
BufferQueueCallback(SLBufferQueueItf queueItf,void * pContext)55 static void BufferQueueCallback(
56 SLBufferQueueItf queueItf,
57 void *pContext)
58 {
59 SLresult res;
60 CallbackCntxt *pCntxt = (CallbackCntxt*)pContext;
61 if (pCntxt->pData < (pCntxt->pDataBase + pCntxt->size)) {
62 res = (*queueItf)->Enqueue(queueItf, (void *)pCntxt->pData,
63 sizeof(SLint16) * AUDIO_DATA_BUFFER_SIZE); /* Size given in bytes. */
64 ALOGE_IF(res != SL_RESULT_SUCCESS, "error: %s", android::getSLErrStr(res));
65 /* Increase data pointer by buffer size */
66 pCntxt->pData += AUDIO_DATA_BUFFER_SIZE;
67 }
68 }
69
70 /* Play some music from a buffer queue */
TestPlayMusicBufferQueue(SLObjectItf sl)71 static void TestPlayMusicBufferQueue(SLObjectItf sl)
72 {
73 SLEngineItf EngineItf;
74
75 SLresult res;
76
77 SLDataSource audioSource;
78 SLDataLocator_BufferQueue bufferQueue;
79 SLDataFormat_PCM pcm;
80
81 SLDataSink audioSink;
82 SLDataLocator_OutputMix locator_outputmix;
83
84 SLObjectItf player;
85 SLPlayItf playItf;
86 SLBufferQueueItf bufferQueueItf;
87 SLBufferQueueState state;
88
89 SLObjectItf OutputMix;
90 SLVolumeItf volumeItf;
91
92 int i;
93
94 SLboolean required[MAX_NUMBER_INTERFACES];
95 SLInterfaceID iidArray[MAX_NUMBER_INTERFACES];
96
97 /* Callback context for the buffer queue callback function */
98 CallbackCntxt cntxt;
99
100 /* Get the SL Engine Interface which is implicit */
101 res = (*sl)->GetInterface(sl, SL_IID_ENGINE, (void *)&EngineItf);
102 CheckErr(res);
103
104 /* Initialize arrays required[] and iidArray[] */
105 for (i = 0; i < MAX_NUMBER_INTERFACES; i++) {
106 required[i] = SL_BOOLEAN_FALSE;
107 iidArray[i] = SL_IID_NULL;
108 }
109
110 // Set arrays required[] and iidArray[] for VOLUME interface
111 required[0] = SL_BOOLEAN_FALSE; // ANDROID: we don't require this interface
112 iidArray[0] = SL_IID_VOLUME;
113
114 #if 0
115 const unsigned interfaces = 1;
116 #else
117
118 /* FIXME: Android doesn't properly support optional interfaces (required == false).
119 [3.1.6] When an application requests explicit interfaces during object creation,
120 it can flag any interface as required. If an implementation is unable to satisfy
121 the request for an interface that is not flagged as required (i.e. it is not required),
122 this will not cause the object to fail creation. On the other hand, if the interface
123 is flagged as required and the implementation is unable to satisfy the request
124 for the interface, the object will not be created.
125 */
126 const unsigned interfaces = 0;
127 #endif
128 // Create Output Mix object to be used by player
129 res = (*EngineItf)->CreateOutputMix(EngineItf, &OutputMix, interfaces,
130 iidArray, required);
131 CheckErr(res);
132
133 // Realizing the Output Mix object in synchronous mode.
134 res = (*OutputMix)->Realize(OutputMix, SL_BOOLEAN_FALSE);
135 CheckErr(res);
136
137 volumeItf = NULL; // ANDROID: Volume interface on mix object may not be supported
138 res = (*OutputMix)->GetInterface(OutputMix, SL_IID_VOLUME,
139 (void *)&volumeItf);
140
141 /* Setup the data source structure for the buffer queue */
142 bufferQueue.locatorType = SL_DATALOCATOR_BUFFERQUEUE;
143 bufferQueue.numBuffers = 4; /* Four buffers in our buffer queue */
144
145 /* Setup the format of the content in the buffer queue */
146 pcm.formatType = SL_DATAFORMAT_PCM;
147 pcm.numChannels = 2;
148 pcm.samplesPerSec = SL_SAMPLINGRATE_44_1;
149 pcm.bitsPerSample = SL_PCMSAMPLEFORMAT_FIXED_16;
150 pcm.containerSize = 16;
151 pcm.channelMask = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT;
152 pcm.endianness = SL_BYTEORDER_LITTLEENDIAN;
153 audioSource.pFormat = (void *)&pcm;
154 audioSource.pLocator = (void *)&bufferQueue;
155
156 /* Setup the data sink structure */
157 locator_outputmix.locatorType = SL_DATALOCATOR_OUTPUTMIX;
158 locator_outputmix.outputMix = OutputMix;
159 audioSink.pLocator = (void *)&locator_outputmix;
160 audioSink.pFormat = NULL;
161
162 /* Initialize the context for Buffer queue callbacks */
163 cntxt.pDataBase = pcmData;
164 cntxt.pData = cntxt.pDataBase;
165 cntxt.size = sizeof(pcmData) / sizeof(pcmData[0]); // ANDROID: Bug
166
167 /* Set arrays required[] and iidArray[] for SEEK interface
168 (PlayItf is implicit) */
169 required[0] = SL_BOOLEAN_TRUE;
170 iidArray[0] = SL_IID_BUFFERQUEUE;
171
172 /* Create the music player */
173
174 res = (*EngineItf)->CreateAudioPlayer(EngineItf, &player,
175 &audioSource, &audioSink, 1, iidArray, required);
176 CheckErr(res);
177
178 /* Realizing the player in synchronous mode. */
179 res = (*player)->Realize(player, SL_BOOLEAN_FALSE);
180 CheckErr(res);
181
182 /* Get seek and play interfaces */
183 res = (*player)->GetInterface(player, SL_IID_PLAY, (void *)&playItf);
184 CheckErr(res);
185 res = (*player)->GetInterface(player, SL_IID_BUFFERQUEUE,
186 (void *)&bufferQueueItf);
187 CheckErr(res);
188
189 /* Setup to receive buffer queue event callbacks */
190 res = (*bufferQueueItf)->RegisterCallback(bufferQueueItf,
191 BufferQueueCallback, &cntxt /* BUG, was NULL */);
192 CheckErr(res);
193
194 /* Before we start set volume to -3dB (-300mB) */
195 if (volumeItf != NULL) { // ANDROID: Volume interface may not be supported.
196 res = (*volumeItf)->SetVolumeLevel(volumeItf, -300);
197 CheckErr(res);
198 }
199
200 /* Enqueue a few buffers to get the ball rolling */
201 res = (*bufferQueueItf)->Enqueue(bufferQueueItf, cntxt.pData,
202 sizeof(SLint16) * AUDIO_DATA_BUFFER_SIZE); /* Size given in bytes. */
203 CheckErr(res);
204 cntxt.pData += AUDIO_DATA_BUFFER_SIZE;
205 res = (*bufferQueueItf)->Enqueue(bufferQueueItf, cntxt.pData,
206 sizeof(SLint16) * AUDIO_DATA_BUFFER_SIZE); /* Size given in bytes. */
207 CheckErr(res);
208 cntxt.pData += AUDIO_DATA_BUFFER_SIZE;
209 res = (*bufferQueueItf)->Enqueue(bufferQueueItf, cntxt.pData,
210 sizeof(SLint16) * AUDIO_DATA_BUFFER_SIZE); /* Size given in bytes. */
211 CheckErr(res);
212 cntxt.pData += AUDIO_DATA_BUFFER_SIZE;
213
214 /* Play the PCM samples using a buffer queue */
215 res = (*playItf)->SetPlayState(playItf, SL_PLAYSTATE_PLAYING);
216 CheckErr(res);
217
218 /* Wait until the PCM data is done playing, the buffer queue callback
219 will continue to queue buffers until the entire PCM data has been
220 played. This is indicated by waiting for the count member of the
221 SLBufferQueueState to go to zero.
222 */
223 res = (*bufferQueueItf)->GetState(bufferQueueItf, &state);
224 CheckErr(res);
225
226 while (state.count) {
227 usleep(5 * 1000 /* usec */); // ANDROID: avoid busy waiting
228 (*bufferQueueItf)->GetState(bufferQueueItf, &state);
229 }
230
231 /* Make sure player is stopped */
232 res = (*playItf)->SetPlayState(playItf, SL_PLAYSTATE_STOPPED);
233 CheckErr(res);
234
235 /* Destroy the player */
236 (*player)->Destroy(player);
237
238 /* Destroy Output Mix object */
239 (*OutputMix)->Destroy(OutputMix);
240 }
241
Java_android_media_audio_cts_AudioNativeTest_nativeAppendixBBufferQueue(JNIEnv *,jclass)242 extern "C" void Java_android_media_audio_cts_AudioNativeTest_nativeAppendixBBufferQueue(
243 JNIEnv * /* env */, jclass /* clazz */)
244 {
245 SLObjectItf engineObject = android::OpenSLEngine();
246 LOG_ALWAYS_FATAL_IF(engineObject == NULL, "cannot open OpenSL ES engine");
247
248 TestPlayMusicBufferQueue(engineObject);
249 android::CloseSLEngine(engineObject);
250 }
251