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 <string.h>
     20 #include <unistd.h>
     21 #include <sys/time.h>
     22 
     23 #include "SLES/OpenSLES.h"
     24 #ifdef ANDROID
     25 #include "SLES/OpenSLES_Android.h"
     26 #include "SLES/OpenSLES_AndroidConfiguration.h"
     27 #endif
     28 
     29 
     30 #define MAX_NUMBER_INTERFACES 2
     31 
     32 
     33 //-----------------------------------------------------------------
     34 /* Exits the application if an error is encountered */
     35 #define ExitOnError(x) ExitOnErrorFunc(x,__LINE__)
     36 
     37 void ExitOnErrorFunc( SLresult result , int line)
     38 {
     39     if (SL_RESULT_SUCCESS != result) {
     40         fprintf(stdout, "%lu error code encountered at line %d, exiting\n", result, line);
     41         exit(EXIT_FAILURE);
     42     }
     43 }
     44 
     45 
     46 //-----------------------------------------------------------------
     47 
     48 /* Play an audio URIs on the given stream type  */
     49 void TestStreamTypeConfiguration( SLObjectItf sl, const char* path, const SLint32 type)
     50 {
     51     SLresult  result;
     52     SLEngineItf EngineItf;
     53 
     54     /* Objects this application uses: one player and an ouput mix */
     55     SLObjectItf  player, outputMix;
     56 
     57     /* Source of audio data to play */
     58     SLDataSource      audioSource;
     59     SLDataLocator_URI uri;
     60     SLDataFormat_MIME mime;
     61 
     62     /* Data sinks for the audio player */
     63     SLDataSink               audioSink;
     64     SLDataLocator_OutputMix  locator_outputmix;
     65 
     66     /* Play, Volume and AndroidStreamType interfaces for the audio player */
     67     SLPlayItf              playItf;
     68     SLPrefetchStatusItf    prefetchItf;
     69 #ifdef ANDROID
     70     SLAndroidConfigurationItf configItf;
     71 #endif
     72 
     73     SLboolean required[MAX_NUMBER_INTERFACES];
     74     SLInterfaceID iidArray[MAX_NUMBER_INTERFACES];
     75 
     76     /* Get the SL Engine Interface which is implicit */
     77     result = (*sl)->GetInterface(sl, SL_IID_ENGINE, (void*)&EngineItf);
     78     ExitOnError(result);
     79 
     80     /* Initialize arrays required[] and iidArray[] */
     81     for (int i=0 ; i < MAX_NUMBER_INTERFACES ; i++) {
     82         required[i] = SL_BOOLEAN_FALSE;
     83         iidArray[i] = SL_IID_NULL;
     84     }
     85 
     86     /* ------------------------------------------------------ */
     87     /* Configuration of the output mix  */
     88 
     89     /* Create Output Mix object to be used by the player */
     90      result = (*EngineItf)->CreateOutputMix(EngineItf, &outputMix, 0, iidArray, required);
     91      ExitOnError(result);
     92 
     93     /* Realize the Output Mix object in synchronous mode */
     94     result = (*outputMix)->Realize(outputMix, SL_BOOLEAN_FALSE);
     95     ExitOnError(result);
     96 
     97     /* Setup the data sink structure */
     98     locator_outputmix.locatorType = SL_DATALOCATOR_OUTPUTMIX;
     99     locator_outputmix.outputMix   = outputMix;
    100     audioSink.pLocator            = (void*)&locator_outputmix;
    101     audioSink.pFormat             = NULL;
    102 
    103     /* ------------------------------------------------------ */
    104     /* Configuration of the player  */
    105 
    106     /* Set arrays required[] and iidArray[] for SLAndroidConfigurationItf interfaces */
    107     /*  (SLPlayItf is implicit) */
    108     required[0] = SL_BOOLEAN_TRUE;
    109     iidArray[0] = SL_IID_PREFETCHSTATUS;
    110 #ifdef ANDROID
    111     required[1] = SL_BOOLEAN_TRUE;
    112     iidArray[1] = SL_IID_ANDROIDCONFIGURATION;
    113 #endif
    114 
    115 
    116     /* Setup the data source structure for the URI */
    117     uri.locatorType = SL_DATALOCATOR_URI;
    118     uri.URI         =  (SLchar*) path;
    119     mime.formatType = SL_DATAFORMAT_MIME;
    120     /*     this is how ignored mime information is specified, according to OpenSL ES spec
    121      *     in 9.1.6 SLDataFormat_MIME and 8.23 SLMetadataTraversalItf GetChildInfo */
    122     mime.mimeType      = (SLchar*)NULL;
    123     mime.containerType = SL_CONTAINERTYPE_UNSPECIFIED;
    124 
    125     audioSource.pFormat  = (void*)&mime;
    126     audioSource.pLocator = (void*)&uri;
    127 
    128     /* Create the audio player */
    129     result = (*EngineItf)->CreateAudioPlayer(EngineItf, &player, &audioSource, &audioSink,
    130             MAX_NUMBER_INTERFACES, iidArray, required);
    131     ExitOnError(result);
    132 
    133     /* Retrieve the configuration interface before the player is realized so its resources
    134      * can be configured.
    135      */
    136 #ifdef ANDROID
    137     result = (*player)->GetInterface(player, SL_IID_ANDROIDCONFIGURATION, (void*)&configItf);
    138     ExitOnError(result);
    139 
    140     /* Set the Android audio stream type on the player */
    141     result = (*configItf)->SetConfiguration(configItf,
    142             SL_ANDROID_KEY_STREAM_TYPE, &type, sizeof(SLint32));
    143     ExitOnError(result);
    144 #endif
    145 
    146     /* Realize the player in synchronous mode. */
    147     result = (*player)->Realize(player, SL_BOOLEAN_FALSE); ExitOnError(result);
    148     fprintf(stdout, "URI example: after Realize\n");
    149 
    150     /* Get the SLPlayItf, SLPrefetchStatusItf and SLAndroidConfigurationItf interfaces for player */
    151     result = (*player)->GetInterface(player, SL_IID_PLAY, (void*)&playItf);
    152     ExitOnError(result);
    153 
    154     result = (*player)->GetInterface(player, SL_IID_PREFETCHSTATUS, (void*)&prefetchItf);
    155     ExitOnError(result);
    156 
    157     fprintf(stdout, "Player configured\n");
    158 
    159     /* ------------------------------------------------------ */
    160     /* Playback and test */
    161 
    162     /* Start the data prefetching by setting the player to the paused state */
    163     result = (*playItf)->SetPlayState( playItf, SL_PLAYSTATE_PAUSED );
    164     ExitOnError(result);
    165 
    166     /* Wait until there's data to play */
    167     SLuint32 prefetchStatus = SL_PREFETCHSTATUS_UNDERFLOW;
    168     while (prefetchStatus != SL_PREFETCHSTATUS_SUFFICIENTDATA) {
    169         usleep(100 * 1000);
    170         (*prefetchItf)->GetPrefetchStatus(prefetchItf, &prefetchStatus);
    171         ExitOnError(result);
    172     }
    173 
    174     /* Get duration */
    175     SLmillisecond durationInMsec = SL_TIME_UNKNOWN;
    176     result = (*playItf)->GetDuration(playItf, &durationInMsec);
    177     ExitOnError(result);
    178     if (durationInMsec == SL_TIME_UNKNOWN) {
    179         durationInMsec = 5000;
    180     }
    181 
    182     /* Start playback */
    183     result = (*playItf)->SetPlayState( playItf, SL_PLAYSTATE_PLAYING );
    184     ExitOnError(result);
    185 
    186     usleep((durationInMsec/2) * 1000);
    187 
    188 #ifdef ANDROID
    189     /* Get the stream type during playback  */
    190     SLint32 currentType = -1;
    191     SLuint32 valueSize = sizeof(SLint32) * 2; // trying too big on purpose
    192     result = (*configItf)->GetConfiguration(configItf,
    193             SL_ANDROID_KEY_STREAM_TYPE, &valueSize, NULL);
    194     ExitOnError(result);
    195     if (valueSize != sizeof(SLint32)) {
    196         fprintf(stderr, "ERROR: size for stream type is %lu, should be %u\n",
    197                 valueSize, sizeof(SLint32));
    198     }
    199     result = (*configItf)->GetConfiguration(configItf,
    200                 SL_ANDROID_KEY_STREAM_TYPE, &valueSize, &currentType);
    201     ExitOnError(result);
    202     if (currentType != type) {
    203         fprintf(stderr, "ERROR: stream type is %lu, should be %lu\n", currentType, type);
    204     }
    205 #endif
    206 
    207     usleep((durationInMsec/2) * 1000);
    208 
    209     /* Make sure player is stopped */
    210     fprintf(stdout, "Stopping playback\n");
    211     result = (*playItf)->SetPlayState(playItf, SL_PLAYSTATE_STOPPED);
    212     ExitOnError(result);
    213 
    214 #ifdef ANDROID
    215     /* Try again to get the stream type, just in case it changed behind our back */
    216     result = (*configItf)->GetConfiguration(configItf,
    217             SL_ANDROID_KEY_STREAM_TYPE, &valueSize, &currentType);
    218     ExitOnError(result);
    219     if (currentType != type) {
    220         fprintf(stderr, "ERROR: stream type is %lu, should be %lu\n", currentType, type);
    221     }
    222 #endif
    223 
    224     /* Destroy the player */
    225     (*player)->Destroy(player);
    226 
    227     /* Destroy Output Mix object */
    228     (*outputMix)->Destroy(outputMix);
    229 }
    230 
    231 //-----------------------------------------------------------------
    232 int main(int argc, char* const argv[])
    233 {
    234     SLresult    result;
    235     SLObjectItf sl;
    236 
    237     fprintf(stdout, "OpenSL ES test %s: exercises SLPlayItf, SLAndroidConfigurationItf\n",
    238             argv[0]);
    239     fprintf(stdout, "and AudioPlayer with SLDataLocator_URI source / OutputMix sink\n");
    240     fprintf(stdout, "Plays a sound on the specified android stream type\n");
    241 
    242     if (argc < 3) {
    243         fprintf(stdout, "Usage: \t%s url stream_type\n", argv[0]);
    244         fprintf(stdout, " where stream_type is one of the SL_ANDROID_STREAM_ constants.\n");
    245         fprintf(stdout, "Example: \"%s /sdcard/my.mp3 3\" \n", argv[0]);
    246         return EXIT_FAILURE;
    247     }
    248 
    249     SLEngineOption EngineOption[] = {
    250             {(SLuint32) SL_ENGINEOPTION_THREADSAFE, (SLuint32) SL_BOOLEAN_TRUE}
    251     };
    252 
    253     result = slCreateEngine( &sl, 1, EngineOption, 0, NULL, NULL);
    254     ExitOnError(result);
    255 
    256     /* Realizing the SL Engine in synchronous mode. */
    257     result = (*sl)->Realize(sl, SL_BOOLEAN_FALSE);
    258     ExitOnError(result);
    259 
    260     TestStreamTypeConfiguration(sl, argv[1], (SLint32)atoi(argv[2]));
    261 
    262     /* Shutdown OpenSL ES */
    263     (*sl)->Destroy(sl);
    264 
    265     return EXIT_SUCCESS;
    266 }
    267