multithread.c revision b0ab2dee391dd2cb257faeaba252ee6ecccc5f03
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
27typedef struct {
28    SLuint32 mObjectID;
29    SLchar *mURI;
30    SLEngineItf mEngineEngine;
31    SLObjectItf mMixObject;
32    SLuint32 mCounter;
33} ThreadArgument;
34
35volatile int timeToExit = 0;
36#define MAX_THREAD 10
37pthread_t threads[MAX_THREAD];
38ThreadArgument thread_args[MAX_THREAD];
39
40pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
41
42void *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"};
103const char * const uris[4] = {"wav/frog.wav", "wav/frog.wav", "wav/frog.wav", "wav/frog.wav"};
104
105// Main program
106
107int main(int argc, char **argv)
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]=%lu ", 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]=%lu ", 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