Home | History | Annotate | Download | only in mimeUri
      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 #include <stdlib.h>
     18 #include <stdio.h>
     19 #include <unistd.h>
     20 
     21 #include <SLES/OpenSLES.h>
     22 
     23 
     24 #define MAX_NUMBER_INTERFACES 3
     25 
     26 
     27 //-----------------------------------------------------------------
     28 /* Exits the application if an error is encountered */
     29 void ExitOnError( SLresult result )
     30 {
     31     if (SL_RESULT_SUCCESS != result) {
     32         fprintf(stdout, "%u error code encountered, exiting\n", result);
     33         exit(EXIT_FAILURE);
     34     }
     35 }
     36 
     37 //-----------------------------------------------------------------
     38 /* PlayItf callback for an audio player */
     39 void PlayEventCallback( SLPlayItf caller __unused,  void *pContext __unused, SLuint32 event)
     40 {
     41     fprintf(stdout, "PlayEventCallback event = ");
     42     if (event & SL_PLAYEVENT_HEADATEND) {
     43         fprintf(stdout, "SL_PLAYEVENT_HEADATEND ");
     44     }
     45     if (event & SL_PLAYEVENT_HEADATMARKER) {
     46         fprintf(stdout, "SL_PLAYEVENT_HEADATMARKER ");
     47     }
     48     if (event & SL_PLAYEVENT_HEADATNEWPOS) {
     49         fprintf(stdout, "SL_PLAYEVENT_HEADATNEWPOS ");
     50     }
     51     if (event & SL_PLAYEVENT_HEADMOVING) {
     52         fprintf(stdout, "SL_PLAYEVENT_HEADMOVING ");
     53     }
     54     if (event & SL_PLAYEVENT_HEADSTALLED) {
     55         fprintf(stdout, "SL_PLAYEVENT_HEADSTALLED");
     56     }
     57     fprintf(stdout, "\n");
     58 }
     59 
     60 //-----------------------------------------------------------------
     61 
     62 /* Play two audio URIs, pan them left and right  */
     63 void TestPlayUri( SLObjectItf sl, const char* path, const char* path2)
     64 {
     65     SLresult  result;
     66     SLEngineItf EngineItf;
     67 
     68     /* Objects this application uses: two players and an ouput mix */
     69     SLObjectItf  player, player2, outputMix;
     70 
     71     /* Source of audio data to play, we'll reuse the same source for two different players */
     72     SLDataSource      audioSource;
     73     SLDataLocator_URI uri;
     74     SLDataFormat_MIME mime;
     75 
     76     /* Data sinks for the two audio players */
     77     SLDataSink               audioSink;
     78     SLDataLocator_OutputMix  locator_outputmix;
     79 
     80     /* Play, Volume and PrefetchStatus interfaces for the audio players */
     81     SLPlayItf           playItf, playItf2;
     82     SLVolumeItf         volItf, volItf2;
     83     SLPrefetchStatusItf prefetchItf, prefetchItf2;
     84 
     85     SLboolean required[MAX_NUMBER_INTERFACES];
     86     SLInterfaceID iidArray[MAX_NUMBER_INTERFACES];
     87 
     88     /* Get the SL Engine Interface which is implicit */
     89     result = (*sl)->GetInterface(sl, SL_IID_ENGINE, (void*)&EngineItf);
     90     ExitOnError(result);
     91 
     92     /* Initialize arrays required[] and iidArray[] */
     93     for (int i=0 ; i < MAX_NUMBER_INTERFACES ; i++) {
     94         required[i] = SL_BOOLEAN_FALSE;
     95         iidArray[i] = SL_IID_NULL;
     96     }
     97     /* Set arrays required[] and iidArray[] for SLVolumeItf and SLPrefetchStatusItf interfaces */
     98     /*  (SLPlayItf is implicit) */
     99     required[0] = SL_BOOLEAN_TRUE;
    100     iidArray[0] = SL_IID_VOLUME;
    101     required[1] = SL_BOOLEAN_TRUE;
    102     iidArray[1] = SL_IID_PREFETCHSTATUS;
    103 
    104     /* ------------------------------------------------------ */
    105     /* Configuration of the output mix  */
    106 
    107     /* Create Output Mix object to be used each player */
    108      result = (*EngineItf)->CreateOutputMix(EngineItf, &outputMix, 0, iidArray, required);
    109      ExitOnError(result);
    110 
    111     /* Realize the Output Mix object in synchronous mode */
    112     result = (*outputMix)->Realize(outputMix, SL_BOOLEAN_FALSE);
    113     ExitOnError(result);
    114 
    115     /* Setup the data sink structure */
    116     locator_outputmix.locatorType = SL_DATALOCATOR_OUTPUTMIX;
    117     locator_outputmix.outputMix   = outputMix;
    118     audioSink.pLocator            = (void *)&locator_outputmix;
    119     audioSink.pFormat             = NULL;
    120 
    121     /* ------------------------------------------------------ */
    122     /* Configuration of the players  */
    123 
    124     /* Setup the data source structure for the first URI */
    125     uri.locatorType = SL_DATALOCATOR_URI;
    126     uri.URI         =  (SLchar*) path;
    127     mime.formatType    = SL_DATAFORMAT_MIME;
    128     /*     this is how ignored mime information is specified, according to OpenSL ES spec
    129      *     in 9.1.6 SLDataFormat_MIME and 8.23 SLMetadataTraversalItf GetChildInfo */
    130     mime.mimeType      = (SLchar*)NULL;
    131     mime.containerType = SL_CONTAINERTYPE_UNSPECIFIED;
    132 
    133     audioSource.pFormat      = (void *)&mime;
    134     audioSource.pLocator     = (void *)&uri;
    135 
    136     /* Create the first audio player */
    137     result = (*EngineItf)->CreateAudioPlayer(EngineItf, &player, &audioSource, &audioSink, 2,
    138             iidArray, required);
    139     ExitOnError(result);
    140 
    141     /* Create the second audio player with a different path for its data source */
    142     uri.URI =  (SLchar*) path2;
    143     audioSource.pLocator = (void *)&uri;
    144     result = (*EngineItf)->CreateAudioPlayer(EngineItf, &player2, &audioSource, &audioSink, 2,
    145             iidArray, required);
    146     ExitOnError(result);
    147 
    148     /* Realize the players in synchronous mode. */
    149     result = (*player)->Realize(player, SL_BOOLEAN_FALSE); ExitOnError(result);
    150     result = (*player)->Realize(player2, SL_BOOLEAN_FALSE); ExitOnError(result);
    151     //fprintf(stdout, "URI example: after Realize\n");
    152 
    153     /* Get the SLPlayItf, SLVolumeItf and SLPrefetchStatusItf interfaces for each player */
    154     result = (*player)->GetInterface(player, SL_IID_PLAY, (void*)&playItf);
    155     ExitOnError(result);
    156     result = (*player)->GetInterface(player2, SL_IID_PLAY, (void*)&playItf2);
    157     ExitOnError(result);
    158 
    159     result = (*player)->GetInterface(player, SL_IID_VOLUME, (void*)&volItf);
    160     ExitOnError(result);
    161     result = (*player2)->GetInterface(player2, SL_IID_VOLUME, (void*)&volItf2);
    162     ExitOnError(result);
    163 
    164     result = (*player)->GetInterface(player, SL_IID_PREFETCHSTATUS, (void*)&prefetchItf);
    165     ExitOnError(result);
    166     result = (*player2)->GetInterface(player2, SL_IID_PREFETCHSTATUS, (void*)&prefetchItf2);
    167     ExitOnError(result);
    168 
    169     /*  Setup to receive playback events */
    170     result = (*playItf)->RegisterCallback(playItf, PlayEventCallback, &playItf);
    171     ExitOnError(result);
    172     result = (*playItf)->SetCallbackEventsMask(playItf,
    173             SL_PLAYEVENT_HEADATEND| SL_PLAYEVENT_HEADATMARKER | SL_PLAYEVENT_HEADATNEWPOS
    174             | SL_PLAYEVENT_HEADMOVING | SL_PLAYEVENT_HEADSTALLED);
    175     ExitOnError(result);
    176 
    177     /* Set the player volume */
    178     result = (*volItf)->SetVolumeLevel( volItf, -300);
    179     ExitOnError(result);
    180     /* Pan the first player to the left */
    181     result = (*volItf)->EnableStereoPosition( volItf, SL_BOOLEAN_TRUE); ExitOnError(result);
    182     result = (*volItf)->SetStereoPosition( volItf, -1000); ExitOnError(result);
    183     /* Pan the second player to the right */
    184     result = (*volItf2)->EnableStereoPosition( volItf2, SL_BOOLEAN_TRUE); ExitOnError(result);
    185     result = (*volItf2)->SetStereoPosition( volItf2, 1000); ExitOnError(result);
    186 
    187     /* ------------------------------------------------------ */
    188     /* Playback */
    189 
    190     /* Start the data prefetching by setting the players to the paused state */
    191     result = (*playItf)->SetPlayState( playItf, SL_PLAYSTATE_PAUSED );
    192     ExitOnError(result);
    193     result = (*playItf2)->SetPlayState( playItf2, SL_PLAYSTATE_PAUSED );
    194     ExitOnError(result);
    195 
    196     /*     wait until there's data to play */
    197     SLuint32 prefetchStatus = SL_PREFETCHSTATUS_UNDERFLOW;
    198     while (prefetchStatus != SL_PREFETCHSTATUS_SUFFICIENTDATA) {
    199         usleep(100 * 1000);
    200         (*prefetchItf)->GetPrefetchStatus(prefetchItf, &prefetchStatus);
    201     }
    202     prefetchStatus = SL_PREFETCHSTATUS_UNDERFLOW;
    203     while (prefetchStatus != SL_PREFETCHSTATUS_SUFFICIENTDATA) {
    204         usleep(100 * 1000);
    205         (*prefetchItf2)->GetPrefetchStatus(prefetchItf2, &prefetchStatus);
    206     }
    207 
    208     result = (*playItf)->SetPlayState( playItf, SL_PLAYSTATE_PLAYING );
    209     ExitOnError(result);
    210 
    211     /* Wait 2s before starting the second player */
    212     usleep(2000 * 1000);
    213     fprintf(stdout, "URI example: starting to play %s\n", path2);
    214     result = (*playItf2)->SetPlayState( playItf2, SL_PLAYSTATE_PLAYING );
    215     ExitOnError(result);
    216 
    217     /* Display duration */
    218     SLmillisecond durationInMsec = SL_TIME_UNKNOWN;
    219     result = (*playItf)->GetDuration(playItf, &durationInMsec);
    220     ExitOnError(result);
    221     if (durationInMsec == SL_TIME_UNKNOWN) {
    222         fprintf(stdout, "Content duration of first URI is unknown\n");
    223     } else {
    224         fprintf(stdout, "Content duration of first URI is %u ms\n", durationInMsec);
    225     }
    226 
    227     /* Wait as long as the duration of the first URI + 2s before stopping */
    228     if (durationInMsec == SL_TIME_UNKNOWN) {
    229         durationInMsec = 5000; /* arbitrary time when duration is unknown */
    230     }
    231     usleep((durationInMsec + 2000) * 1000);
    232 
    233     /* Make sure player is stopped */
    234     fprintf(stdout, "URI example: stopping playback\n");
    235     result = (*playItf)->SetPlayState(playItf, SL_PLAYSTATE_STOPPED);
    236     ExitOnError(result);
    237     result = (*playItf2)->SetPlayState(playItf2, SL_PLAYSTATE_STOPPED);
    238     ExitOnError(result);
    239 
    240     /* Destroy the players */
    241     (*player)->Destroy(player);
    242     (*player2)->Destroy(player2);
    243 
    244     /* Destroy Output Mix object */
    245     (*outputMix)->Destroy(outputMix);
    246 }
    247 
    248 //-----------------------------------------------------------------
    249 int main(int argc, char* const argv[])
    250 {
    251     SLresult    result;
    252     SLObjectItf sl;
    253 
    254     fprintf(stdout, "OpenSL ES test %s: exercises SLPlayItf, SLVolumeItf (incl. stereo position) ",
    255             argv[0]);
    256     fprintf(stdout, "and AudioPlayer with SLDataLocator_URI source / OutputMix sink\n");
    257     fprintf(stdout, "Plays two sounds (or twice the same) and pans them left and right.");
    258     fprintf(stdout, "Stops after the end of the first + 2s\n");
    259 
    260     if (argc == 1) {
    261         fprintf(stdout, "Usage: \n\t%s url1 url2 \n\t%s url\n", argv[0], argv[0]);
    262         fprintf(stdout, "Example: \"%s /sdcard/my.mp3 http://blabla/my.wav\" ", argv[0]);
    263         fprintf(stdout, "or \"%s file:///sdcard/my.mp3\"\n", argv[0]);
    264         exit(EXIT_FAILURE);
    265     }
    266 
    267     SLEngineOption EngineOption[] = {
    268             {(SLuint32) SL_ENGINEOPTION_THREADSAFE, (SLuint32) SL_BOOLEAN_TRUE}
    269     };
    270 
    271     result = slCreateEngine( &sl, 1, EngineOption, 0, NULL, NULL);
    272     ExitOnError(result);
    273 
    274     /* Realizing the SL Engine in synchronous mode. */
    275     result = (*sl)->Realize(sl, SL_BOOLEAN_FALSE);
    276     ExitOnError(result);
    277 
    278     if (argc == 2) {
    279         TestPlayUri(sl, argv[1], argv[1]);
    280     } else if (argc == 3) {
    281         TestPlayUri(sl, argv[1], argv[2]);
    282     }
    283 
    284     /* Shutdown OpenSL ES */
    285     (*sl)->Destroy(sl);
    286 
    287     return EXIT_SUCCESS;
    288 }
    289