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
thread_start(void * param)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
main(int argc __unused,char ** argv __unused)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