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