Home | History | Annotate | Download | only in sandbox
      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, 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]=%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