slesTestPlayUri2.cpp revision ee21d26b4b66d0f19b826685b3070497523994d5
1/* 2 * Copyright (C) 2010 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 "slesTestPlayUri" 19 20#ifdef ANDROID 21#include <utils/Log.h> 22#else 23#define LOGV printf 24#endif 25 26#include <getopt.h> 27#include <stdlib.h> 28#include <stdio.h> 29#include <string.h> 30#include <unistd.h> 31#include <sys/time.h> 32 33#include "SLES/OpenSLES.h" 34 35 36#define MAX_NUMBER_INTERFACES 3 37#define MAX_NUMBER_OUTPUT_DEVICES 6 38 39 40//----------------------------------------------------------------- 41/* Exits the application if an error is encountered */ 42void ExitOnError( SLresult result ) 43{ 44 if (SL_RESULT_SUCCESS != result) { 45 fprintf(stdout, "%lu error code encountered, exiting\n", result); 46 exit(1); 47 } 48} 49 50//----------------------------------------------------------------- 51/* PlayItf callback for an audio player */ 52void PlayEventCallback( SLPlayItf caller, void *pContext, SLuint32 event) 53{ 54 fprintf(stdout, "PlayEventCallback event = "); 55 if (event & SL_PLAYEVENT_HEADATEND) { 56 fprintf(stdout, "SL_PLAYEVENT_HEADATEND "); 57 } 58 if (event & SL_PLAYEVENT_HEADATMARKER) { 59 fprintf(stdout, "SL_PLAYEVENT_HEADATMARKER "); 60 } 61 if (event & SL_PLAYEVENT_HEADATNEWPOS) { 62 fprintf(stdout, "SL_PLAYEVENT_HEADATNEWPOS "); 63 } 64 if (event & SL_PLAYEVENT_HEADMOVING) { 65 fprintf(stdout, "SL_PLAYEVENT_HEADMOVING "); 66 } 67 if (event & SL_PLAYEVENT_HEADSTALLED) { 68 fprintf(stdout, "SL_PLAYEVENT_HEADSTALLED"); 69 } 70 fprintf(stdout, "\n"); 71} 72 73//----------------------------------------------------------------- 74 75/* Play two audio URIs, pan them left and right */ 76void TestPlayUri( SLObjectItf sl, const char* path, const char* path2) 77{ 78 SLresult result; 79 SLEngineItf EngineItf; 80 81 /* Objects this application uses: two players and an ouput mix */ 82 SLObjectItf player, player2, outputMix; 83 84 /* Source of audio data to play, we'll reuse the same source for two different players */ 85 SLDataSource audioSource; 86 SLDataLocator_URI uri; 87 SLDataFormat_MIME mime; 88 89 /* Data sinks for the two audio players */ 90 SLDataSink audioSink; 91 SLDataLocator_OutputMix locator_outputmix; 92 93 /* Play, Volume and PrefetchStatus interfaces for the audio players */ 94 SLPlayItf playItf, playItf2; 95 SLVolumeItf volItf, volItf2; 96 SLPrefetchStatusItf prefetchItf, prefetchItf2; 97 98 SLboolean required[MAX_NUMBER_INTERFACES]; 99 SLInterfaceID iidArray[MAX_NUMBER_INTERFACES]; 100 101 /* Get the SL Engine Interface which is implicit */ 102 result = (*sl)->GetInterface(sl, SL_IID_ENGINE, (void*)&EngineItf); 103 ExitOnError(result); 104 105 /* Initialize arrays required[] and iidArray[] */ 106 for (int i=0 ; i < MAX_NUMBER_INTERFACES ; i++) { 107 required[i] = SL_BOOLEAN_FALSE; 108 iidArray[i] = SL_IID_NULL; 109 } 110 /* Set arrays required[] and iidArray[] for SLVolumeItf and SLPrefetchStatusItf interfaces */ 111 /* (SLPlayItf is implicit) */ 112 required[0] = SL_BOOLEAN_TRUE; 113 iidArray[0] = SL_IID_VOLUME; 114 required[1] = SL_BOOLEAN_TRUE; 115 iidArray[1] = SL_IID_PREFETCHSTATUS; 116 117 /* ------------------------------------------------------ */ 118 /* Configuration of the output mix */ 119 120 /* Create Output Mix object to be used each player */ 121 result = (*EngineItf)->CreateOutputMix(EngineItf, &outputMix, 1, iidArray, required); 122 ExitOnError(result); 123 124 /* Realize the Output Mix object in synchronous mode */ 125 result = (*outputMix)->Realize(outputMix, SL_BOOLEAN_FALSE); 126 ExitOnError(result); 127 128 /* Setup the data sink structure */ 129 locator_outputmix.locatorType = SL_DATALOCATOR_OUTPUTMIX; 130 locator_outputmix.outputMix = outputMix; 131 audioSink.pLocator = (void *)&locator_outputmix; 132 audioSink.pFormat = NULL; 133 134 /* ------------------------------------------------------ */ 135 /* Configuration of the players */ 136 137 /* Setup the data source structure for the first URI */ 138 uri.locatorType = SL_DATALOCATOR_URI; 139 uri.URI = (SLchar*) path; 140 mime.formatType = SL_DATAFORMAT_MIME; 141 /* this is how ignored mime information is specified, according to OpenSL ES spec 142 * in 9.1.6 SLDataFormat_MIME and 8.23 SLMetadataTraversalItf GetChildInfo */ 143 mime.mimeType = (SLchar*)NULL; 144 mime.containerType = SL_CONTAINERTYPE_UNSPECIFIED; 145 146 audioSource.pFormat = (void *)&mime; 147 audioSource.pLocator = (void *)&uri; 148 149 /* Create the first audio player */ 150 result = (*EngineItf)->CreateAudioPlayer(EngineItf, &player, &audioSource, &audioSink, 2, 151 iidArray, required); 152 ExitOnError(result); 153 154 /* Create the second audio player with a different path for its data source */ 155 uri.URI = (SLchar*) path2; 156 audioSource.pLocator = (void *)&uri; 157 result = (*EngineItf)->CreateAudioPlayer(EngineItf, &player2, &audioSource, &audioSink, 2, 158 iidArray, required); 159 ExitOnError(result); 160 161 /* Realize the players in synchronous mode. */ 162 result = (*player)->Realize(player, SL_BOOLEAN_FALSE); ExitOnError(result); 163 result = (*player)->Realize(player2, SL_BOOLEAN_FALSE); ExitOnError(result); 164 //fprintf(stdout, "URI example: after Realize\n"); 165 166 /* Get the SLPlayItf, SLVolumeItf and SLPrefetchStatusItf interfaces for each player */ 167 result = (*player)->GetInterface(player, SL_IID_PLAY, (void*)&playItf); 168 ExitOnError(result); 169 result = (*player)->GetInterface(player2, SL_IID_PLAY, (void*)&playItf2); 170 ExitOnError(result); 171 172 result = (*player)->GetInterface(player, SL_IID_VOLUME, (void*)&volItf); 173 ExitOnError(result); 174 result = (*player2)->GetInterface(player2, SL_IID_VOLUME, (void*)&volItf2); 175 ExitOnError(result); 176 177 result = (*player)->GetInterface(player, SL_IID_PREFETCHSTATUS, (void*)&prefetchItf); 178 ExitOnError(result); 179 result = (*player2)->GetInterface(player2, SL_IID_PREFETCHSTATUS, (void*)&prefetchItf2); 180 ExitOnError(result); 181 182 /* Setup to receive playback events */ 183 result = (*playItf)->RegisterCallback(playItf, PlayEventCallback, &playItf); 184 ExitOnError(result); 185 result = (*playItf)->SetCallbackEventsMask(playItf, 186 SL_PLAYEVENT_HEADATEND| SL_PLAYEVENT_HEADATMARKER | SL_PLAYEVENT_HEADATNEWPOS 187 | SL_PLAYEVENT_HEADMOVING | SL_PLAYEVENT_HEADSTALLED); 188 ExitOnError(result); 189 190 /* Set the player volume */ 191 result = (*volItf)->SetVolumeLevel( volItf, -300); 192 ExitOnError(result); 193 /* Pan the first player to the left */ 194 result = (*volItf)->EnableStereoPosition( volItf, SL_BOOLEAN_TRUE); ExitOnError(result); 195 result = (*volItf)->SetStereoPosition( volItf, -1000); ExitOnError(result); 196 /* Pan the second player to the right */ 197 result = (*volItf2)->EnableStereoPosition( volItf2, SL_BOOLEAN_TRUE); ExitOnError(result); 198 result = (*volItf2)->SetStereoPosition( volItf2, 1000); ExitOnError(result); 199 200 /* ------------------------------------------------------ */ 201 /* Playback */ 202 203 /* Start the data prefetching by setting the players to the paused state */ 204 result = (*playItf)->SetPlayState( playItf, SL_PLAYSTATE_PAUSED ); 205 ExitOnError(result); 206 result = (*playItf2)->SetPlayState( playItf2, SL_PLAYSTATE_PAUSED ); 207 ExitOnError(result); 208 209 /* wait until there's data to play */ 210 SLuint32 prefetchStatus = SL_PREFETCHSTATUS_UNDERFLOW; 211 while (prefetchStatus != SL_PREFETCHSTATUS_SUFFICIENTDATA) { 212 usleep(100 * 1000); 213 (*prefetchItf)->GetPrefetchStatus(prefetchItf, &prefetchStatus); 214 } 215 prefetchStatus = SL_PREFETCHSTATUS_UNDERFLOW; 216 while (prefetchStatus != SL_PREFETCHSTATUS_SUFFICIENTDATA) { 217 usleep(100 * 1000); 218 (*prefetchItf2)->GetPrefetchStatus(prefetchItf2, &prefetchStatus); 219 } 220 221 result = (*playItf)->SetPlayState( playItf, SL_PLAYSTATE_PLAYING ); 222 ExitOnError(result); 223 224 /* Wait 2s before starting the second player */ 225 usleep(2000 * 1000); 226 fprintf(stdout, "URI example: starting to play %s\n", path2); 227 result = (*playItf2)->SetPlayState( playItf2, SL_PLAYSTATE_PLAYING ); 228 ExitOnError(result); 229 230 /* Display duration */ 231 SLmillisecond durationInMsec = SL_TIME_UNKNOWN; 232 result = (*playItf)->GetDuration(playItf, &durationInMsec); 233 ExitOnError(result); 234 if (durationInMsec == SL_TIME_UNKNOWN) { 235 fprintf(stdout, "Content duration of first URI is unknown\n"); 236 } else { 237 fprintf(stdout, "Content duration of first URI is %lu ms\n", durationInMsec); 238 } 239 240 /* Wait as long as the duration of the first URI + 2s before stopping */ 241 if (durationInMsec == SL_TIME_UNKNOWN) { 242 durationInMsec = 5000; /* arbitrary time when duration is unknown */ 243 } 244 usleep((durationInMsec + 2000) * 1000); 245 246 /* Make sure player is stopped */ 247 fprintf(stdout, "URI example: stopping playback\n"); 248 result = (*playItf)->SetPlayState(playItf, SL_PLAYSTATE_STOPPED); 249 ExitOnError(result); 250 result = (*playItf2)->SetPlayState(playItf2, SL_PLAYSTATE_STOPPED); 251 ExitOnError(result); 252 253 /* Destroy the players */ 254 (*player)->Destroy(player); 255 (*player2)->Destroy(player2); 256 257 /* Destroy Output Mix object */ 258 (*outputMix)->Destroy(outputMix); 259} 260 261//----------------------------------------------------------------- 262int main(int argc, char* const argv[]) 263{ 264 LOGV("Starting %s\n", argv[0]); 265 266 SLresult result; 267 SLObjectItf sl; 268 269 fprintf(stdout, "OpenSL ES test %s: exercises SLPlayItf, SLVolumeItf (incl. stereo position) ", 270 argv[0]); 271 fprintf(stdout, "and AudioPlayer with SLDataLocator_URI source / OutputMix sink\n"); 272 fprintf(stdout, "Plays two sounds (or twice the same) and pans them left and right."); 273 fprintf(stdout, "Stops after the end of the first + 2s\n"); 274 275 if (argc == 1) { 276 fprintf(stdout, "Usage: \n\t%s url1 url2 \n\t%s url\n", argv[0], argv[0]); 277 fprintf(stdout, "Example: \"%s /sdcard/my.mp3 http://blabla/my.wav\" ", argv[0]); 278 fprintf(stdout, "or \"%s file:///sdcard/my.mp3\"\n", argv[0]); 279 exit(1); 280 } 281 282 SLEngineOption EngineOption[] = { 283 {(SLuint32) SL_ENGINEOPTION_THREADSAFE, (SLuint32) SL_BOOLEAN_TRUE} 284 }; 285 286 result = slCreateEngine( &sl, 1, EngineOption, 0, NULL, NULL); 287 ExitOnError(result); 288 289 /* Realizing the SL Engine in synchronous mode. */ 290 result = (*sl)->Realize(sl, SL_BOOLEAN_FALSE); 291 ExitOnError(result); 292 293 if (argc == 2) { 294 TestPlayUri(sl, argv[1], argv[1]); 295 } else if (argc == 3) { 296 TestPlayUri(sl, argv[1], argv[2]); 297 } 298 299 /* Shutdown OpenSL ES */ 300 (*sl)->Destroy(sl); 301 exit(0); 302 303 return 0; 304} 305