multithread.c revision 0a058cc3d720cdf3f0f8222472a862258482f34f
17126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten/*
27126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten * Copyright (C) 2010 The Android Open Source Project
37126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten *
47126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten * Licensed under the Apache License, Version 2.0 (the "License");
57126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten * you may not use this file except in compliance with the License.
67126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten * You may obtain a copy of the License at
77126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten *
87126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten *      http://www.apache.org/licenses/LICENSE-2.0
97126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten *
107126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten * Unless required by applicable law or agreed to in writing, software
117126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten * distributed under the License is distributed on an "AS IS" BASIS,
127126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
137126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten * See the License for the specific language governing permissions and
147126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten * limitations under the License.
157126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten */
167126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten
177126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten// Multiple threads create and destroy objects
187126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten
197126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten#include "SLES/OpenSLES.h"
207126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten#include <assert.h>
217126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten#include <pthread.h>
227126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten//#include <string.h>
237126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten#include <stdio.h>
247126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten#include <stdlib.h>
257126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten#include <unistd.h>
260a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten#include <utils/Log.h>
277126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten
287126c25d7c037e5086216cf540ecf40779c3585aGlenn Kastentypedef struct {
297126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    SLuint32 mObjectID;
307126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    SLchar *mURI;
317126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    SLEngineItf mEngineEngine;
327126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    SLObjectItf mMixObject;
337126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    SLuint32 mCounter;
347126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten} ThreadArgument;
357126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten
367126c25d7c037e5086216cf540ecf40779c3585aGlenn Kastenvolatile int timeToExit = 0;
377126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten#define MAX_THREAD 10
387126c25d7c037e5086216cf540ecf40779c3585aGlenn Kastenpthread_t threads[MAX_THREAD];
397126c25d7c037e5086216cf540ecf40779c3585aGlenn KastenThreadArgument thread_args[MAX_THREAD];
407126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten
417126c25d7c037e5086216cf540ecf40779c3585aGlenn Kastenpthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
427126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten
437126c25d7c037e5086216cf540ecf40779c3585aGlenn Kastenvoid *thread_start(void *param)
447126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten{
457126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    //pthread_mutex_lock(&mutex);
467126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    //pthread_mutex_unlock(&mutex);
477126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    ThreadArgument *ta = (ThreadArgument *) param;
487126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten
497126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    while (!timeToExit) {
507126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten        SLresult result;
517126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten
527126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten        ++ta->mCounter;
530a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten        //LOGE("mCounter %d", ta->mCounter);
547126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten        switch (ta->mObjectID) {
557126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten        case SL_OBJECTID_OUTPUTMIX:
567126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten            {
577126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten            SLObjectItf myMixObject;
587126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten            result = (*ta->mEngineEngine)->CreateOutputMix(ta->mEngineEngine, &myMixObject, 0, NULL,
597126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten                    NULL);
607126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten            assert(SL_RESULT_SUCCESS == result);
617126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten            result = (*myMixObject)->Realize(myMixObject, SL_BOOLEAN_FALSE);
627126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten            assert(SL_RESULT_SUCCESS == result);
637126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten            (*myMixObject)->Destroy(myMixObject);
647126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten            }
657126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten            break;
667126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten
677126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten        case SL_OBJECTID_AUDIOPLAYER:
687126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten            {
697126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten            SLDataLocator_URI locURI = {SL_DATALOCATOR_URI, ta->mURI};
707126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten            SLDataFormat_MIME dfMIME = {SL_DATAFORMAT_MIME, NULL, SL_CONTAINERTYPE_UNSPECIFIED};
717126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten            SLDataSource audioSrc = {&locURI, &dfMIME};
727126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten            SLDataLocator_OutputMix locOutputMix = {SL_DATALOCATOR_OUTPUTMIX, ta->mMixObject};
737126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten            SLDataSink audioSnk = {&locOutputMix, NULL};
747126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten            SLObjectItf myPlayerObject;
757126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten            result = (*ta->mEngineEngine)->CreateAudioPlayer(ta->mEngineEngine, &myPlayerObject,
767126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten                    &audioSrc, &audioSnk, 0, NULL, NULL);
777126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten            assert(SL_RESULT_SUCCESS == result);
787126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten            result = (*myPlayerObject)->Realize(myPlayerObject, SL_BOOLEAN_FALSE);
797126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten            assert(SL_RESULT_SUCCESS == result);
807126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten            SLPlayItf playerPlay;
817126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten            result = (*myPlayerObject)->GetInterface(myPlayerObject, SL_IID_PLAY, &playerPlay);
827126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten            assert(SL_RESULT_SUCCESS == result);
830a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten            result = (*playerPlay)->SetPlayState(playerPlay, SL_PLAYSTATE_PAUSED);
847126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten            assert(SL_RESULT_SUCCESS == result);
850a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten            usleep(1000 + (rand() & 0xFFF));
860a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten            //usleep(1000);
870a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten            //sleep(1);
887126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten            (*myPlayerObject)->Destroy(myPlayerObject);
897126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten            }
907126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten            break;
917126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten
927126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten        default:
937126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten            break;
947126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten
957126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten        }
967126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten        //usleep(100000);
970a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten        //break;
987126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    }
997126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten
1007126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    return NULL;
1017126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten}
1027126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten
1037126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten
1040a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten//const char * const uris[4] = {"wav/frog.wav", "wav/bach.wav", "wav/8days.wav", "wav/help16.wav"};
1050a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kastenconst char * const uris[4] = {"wav/frog.wav", "wav/frog.wav", "wav/frog.wav", "wav/frog.wav"};
1067126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten
1077126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten// Main program
1087126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten
1097126c25d7c037e5086216cf540ecf40779c3585aGlenn Kastenint main(int argc, char **argv)
1107126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten{
1117126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    SLresult result;
1127126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten
1137126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    // create engine
1147126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    SLObjectItf engineObject;
1157126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    result = slCreateEngine(&engineObject, 0, NULL, 0, NULL, NULL);
1167126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    assert(SL_RESULT_SUCCESS == result);
1177126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    result = (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE);
1187126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    assert(SL_RESULT_SUCCESS == result);
1197126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    SLEngineItf engineEngine;
1207126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    result = (*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, &engineEngine);
1217126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    assert(SL_RESULT_SUCCESS == result);
1227126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten
1237126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    // create output mix
1247126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    SLObjectItf mixObject;
1257126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    result = (*engineEngine)->CreateOutputMix(engineEngine, &mixObject, 0, NULL, NULL);
1267126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    assert(SL_RESULT_SUCCESS == result);
1277126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    result = (*mixObject)->Realize(mixObject, SL_BOOLEAN_FALSE);
1287126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    assert(SL_RESULT_SUCCESS == result);
1297126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten
1307126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    // create threads
1317126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    int i;
1327126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    int ok;
1337126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    for (i = 0; i < MAX_THREAD; ++i) {
1347126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten        ThreadArgument *ta = &thread_args[i];
1357126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten        int r = rand();
1367126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten        switch (r & 1) {
1377126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten#if 0
1387126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten        case 0:
1397126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten            ta->mObjectID = SL_OBJECTID_OUTPUTMIX;
1407126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten            ta->mURI = NULL;
1417126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten            ta->mEngineEngine = engineEngine;
1427126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten            ta->mMixObject = NULL;
1437126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten            ta->mCounter = 0;
1447126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten            break;
1457126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten        case 1:
1467126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten#endif
1477126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten        default:
1487126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten            ta->mObjectID = SL_OBJECTID_AUDIOPLAYER;
1497126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten            ta->mURI = (SLchar *) uris[(r >> 1) & 3];
1507126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten            ta->mEngineEngine = engineEngine;
1517126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten            ta->mMixObject = mixObject;
1527126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten            ta->mCounter = 0;
1537126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten            break;
1547126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten        }
1557126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten        //pthread_mutex_lock(&mutex);
1567126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten        //pthread_mutex_unlock(&mutex);
1577126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten        ok = pthread_create(&threads[i], (const pthread_attr_t *) NULL, thread_start,
1587126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten                &thread_args[i]);
1597126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten        assert(0 == ok);
1607126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    }
1617126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten
1627126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    // let it run for a while
1637126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    int j;
1640a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    for (j = 0; j < 100; ++j) {
1657126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten        sleep(1);
1667126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten        for (i = 0; i < MAX_THREAD; ++i) {
1677126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten            ThreadArgument *ta = &thread_args[i];
1687126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten            printf("[%d]=%lu ", j, ta->mCounter);
1697126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten        }
1707126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten        printf("\n");
1717126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    }
1727126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten
1737126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    // signal threads that they should exit
1747126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    timeToExit = 1;
1757126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten
1767126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    for (j = 0; j < 3; ++j) {
1777126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten        sleep(1);
1787126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten        for (i = 0; i < MAX_THREAD; ++i) {
1797126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten            ThreadArgument *ta = &thread_args[i];
1807126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten            printf("[%d]=%lu ", j, ta->mCounter);
1817126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten        }
1827126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten        printf("\n");
1837126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    }
1847126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten
1857126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    // now wait for the threads to actually exit
1867126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    for (i = 0; i < MAX_THREAD; ++i) {
1877126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten        ok = pthread_join(threads[i], NULL);
1887126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten        assert(0 == ok);
1897126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    }
1907126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten
1917126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    // tear down objects
1927126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    (*mixObject)->Destroy(mixObject);
1937126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    (*engineObject)->Destroy(engineObject);
1947126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten
1957126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    return EXIT_SUCCESS;
1967126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten}
197