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