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 // Multiple threads create and destroy objects 18 19 #include <SLES/OpenSLES.h> 20 #include <assert.h> 21 #include <pthread.h> 22 //#include <string.h> 23 #include <stdio.h> 24 #include <stdlib.h> 25 #include <unistd.h> 26 27 typedef struct { 28 SLuint32 mObjectID; 29 SLchar *mURI; 30 SLEngineItf mEngineEngine; 31 SLObjectItf mMixObject; 32 SLuint32 mCounter; 33 } ThreadArgument; 34 35 volatile int timeToExit = 0; 36 #define MAX_THREAD 10 37 pthread_t threads[MAX_THREAD]; 38 ThreadArgument thread_args[MAX_THREAD]; 39 40 pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; 41 42 void *thread_start(void *param) 43 { 44 //pthread_mutex_lock(&mutex); 45 //pthread_mutex_unlock(&mutex); 46 ThreadArgument *ta = (ThreadArgument *) param; 47 48 while (!timeToExit) { 49 SLresult result; 50 51 ++ta->mCounter; 52 switch (ta->mObjectID) { 53 case SL_OBJECTID_OUTPUTMIX: 54 { 55 SLObjectItf myMixObject; 56 result = (*ta->mEngineEngine)->CreateOutputMix(ta->mEngineEngine, &myMixObject, 0, NULL, 57 NULL); 58 assert(SL_RESULT_SUCCESS == result); 59 result = (*myMixObject)->Realize(myMixObject, SL_BOOLEAN_FALSE); 60 assert(SL_RESULT_SUCCESS == result); 61 (*myMixObject)->Destroy(myMixObject); 62 } 63 break; 64 65 case SL_OBJECTID_AUDIOPLAYER: 66 { 67 SLDataLocator_URI locURI = {SL_DATALOCATOR_URI, ta->mURI}; 68 SLDataFormat_MIME dfMIME = {SL_DATAFORMAT_MIME, NULL, SL_CONTAINERTYPE_UNSPECIFIED}; 69 SLDataSource audioSrc = {&locURI, &dfMIME}; 70 SLDataLocator_OutputMix locOutputMix = {SL_DATALOCATOR_OUTPUTMIX, ta->mMixObject}; 71 SLDataSink audioSnk = {&locOutputMix, NULL}; 72 SLObjectItf myPlayerObject; 73 result = (*ta->mEngineEngine)->CreateAudioPlayer(ta->mEngineEngine, &myPlayerObject, 74 &audioSrc, &audioSnk, 0, NULL, NULL); 75 assert(SL_RESULT_SUCCESS == result); 76 result = (*myPlayerObject)->Realize(myPlayerObject, SL_BOOLEAN_FALSE); 77 assert(SL_RESULT_SUCCESS == result); 78 SLPlayItf playerPlay; 79 result = (*myPlayerObject)->GetInterface(myPlayerObject, SL_IID_PLAY, &playerPlay); 80 assert(SL_RESULT_SUCCESS == result); 81 result = (*playerPlay)->SetPlayState(playerPlay, SL_PLAYSTATE_PAUSED); 82 assert(SL_RESULT_SUCCESS == result); 83 usleep(1000 + (rand() & 0xFFF)); 84 //usleep(1000); 85 //sleep(1); 86 (*myPlayerObject)->Destroy(myPlayerObject); 87 } 88 break; 89 90 default: 91 break; 92 93 } 94 //usleep(100000); 95 //break; 96 } 97 98 return NULL; 99 } 100 101 102 //const char * const uris[4] = {"wav/frog.wav", "wav/bach.wav", "wav/8days.wav", "wav/help16.wav"}; 103 const char * const uris[4] = {"wav/frog.wav", "wav/frog.wav", "wav/frog.wav", "wav/frog.wav"}; 104 105 // Main program 106 107 int main(int argc __unused, char **argv __unused) 108 { 109 SLresult result; 110 111 // create engine 112 SLObjectItf engineObject; 113 result = slCreateEngine(&engineObject, 0, NULL, 0, NULL, NULL); 114 assert(SL_RESULT_SUCCESS == result); 115 result = (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE); 116 assert(SL_RESULT_SUCCESS == result); 117 SLEngineItf engineEngine; 118 result = (*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, &engineEngine); 119 assert(SL_RESULT_SUCCESS == result); 120 121 // create output mix 122 SLObjectItf mixObject; 123 result = (*engineEngine)->CreateOutputMix(engineEngine, &mixObject, 0, NULL, NULL); 124 assert(SL_RESULT_SUCCESS == result); 125 result = (*mixObject)->Realize(mixObject, SL_BOOLEAN_FALSE); 126 assert(SL_RESULT_SUCCESS == result); 127 128 // create threads 129 int i; 130 int ok; 131 for (i = 0; i < MAX_THREAD; ++i) { 132 ThreadArgument *ta = &thread_args[i]; 133 int r = rand(); 134 switch (r & 1) { 135 #if 0 136 case 0: 137 ta->mObjectID = SL_OBJECTID_OUTPUTMIX; 138 ta->mURI = NULL; 139 ta->mEngineEngine = engineEngine; 140 ta->mMixObject = NULL; 141 ta->mCounter = 0; 142 break; 143 case 1: 144 #endif 145 default: 146 ta->mObjectID = SL_OBJECTID_AUDIOPLAYER; 147 ta->mURI = (SLchar *) uris[(r >> 1) & 3]; 148 ta->mEngineEngine = engineEngine; 149 ta->mMixObject = mixObject; 150 ta->mCounter = 0; 151 break; 152 } 153 //pthread_mutex_lock(&mutex); 154 //pthread_mutex_unlock(&mutex); 155 ok = pthread_create(&threads[i], (const pthread_attr_t *) NULL, thread_start, 156 &thread_args[i]); 157 assert(0 == ok); 158 } 159 160 // let it run for a while 161 int j; 162 for (j = 0; j < 100; ++j) { 163 sleep(1); 164 for (i = 0; i < MAX_THREAD; ++i) { 165 ThreadArgument *ta = &thread_args[i]; 166 printf("[%d]=%u ", j, ta->mCounter); 167 } 168 printf("\n"); 169 } 170 171 // signal threads that they should exit 172 timeToExit = 1; 173 174 for (j = 0; j < 3; ++j) { 175 sleep(1); 176 for (i = 0; i < MAX_THREAD; ++i) { 177 ThreadArgument *ta = &thread_args[i]; 178 printf("[%d]=%u ", j, ta->mCounter); 179 } 180 printf("\n"); 181 } 182 183 // now wait for the threads to actually exit 184 for (i = 0; i < MAX_THREAD; ++i) { 185 ok = pthread_join(threads[i], NULL); 186 assert(0 == ok); 187 } 188 189 // tear down objects 190 (*mixObject)->Destroy(mixObject); 191 (*engineObject)->Destroy(engineObject); 192 193 return EXIT_SUCCESS; 194 } 195