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 */ 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 */ 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 242 extern "C" void Java_android_media_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