xref: /aosp_15_r20/frameworks/wilhelm/tests/mimeUri/slesTestSlowDownUri.cpp (revision bebae9c0e76121f8312ccb50385c080b3a0b023c)
1*bebae9c0SAndroid Build Coastguard Worker /*
2*bebae9c0SAndroid Build Coastguard Worker  * Copyright (C) 2010 The Android Open Source Project
3*bebae9c0SAndroid Build Coastguard Worker  *
4*bebae9c0SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*bebae9c0SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*bebae9c0SAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*bebae9c0SAndroid Build Coastguard Worker  *
8*bebae9c0SAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*bebae9c0SAndroid Build Coastguard Worker  *
10*bebae9c0SAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*bebae9c0SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*bebae9c0SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*bebae9c0SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*bebae9c0SAndroid Build Coastguard Worker  * limitations under the License.
15*bebae9c0SAndroid Build Coastguard Worker  */
16*bebae9c0SAndroid Build Coastguard Worker 
17*bebae9c0SAndroid Build Coastguard Worker #include <assert.h>
18*bebae9c0SAndroid Build Coastguard Worker #include <pthread.h>
19*bebae9c0SAndroid Build Coastguard Worker #include <stdlib.h>
20*bebae9c0SAndroid Build Coastguard Worker #include <stdio.h>
21*bebae9c0SAndroid Build Coastguard Worker #include <string.h>
22*bebae9c0SAndroid Build Coastguard Worker #include <unistd.h>
23*bebae9c0SAndroid Build Coastguard Worker #include <sys/time.h>
24*bebae9c0SAndroid Build Coastguard Worker 
25*bebae9c0SAndroid Build Coastguard Worker #include <SLES/OpenSLES.h>
26*bebae9c0SAndroid Build Coastguard Worker 
27*bebae9c0SAndroid Build Coastguard Worker 
28*bebae9c0SAndroid Build Coastguard Worker #define MAX_NUMBER_INTERFACES 3
29*bebae9c0SAndroid Build Coastguard Worker 
30*bebae9c0SAndroid Build Coastguard Worker #define REPETITIONS 4  // 4 repetitions, but will stop the looping before the end
31*bebae9c0SAndroid Build Coastguard Worker 
32*bebae9c0SAndroid Build Coastguard Worker #define INITIAL_RATE 2000 // 2x normal playback speed
33*bebae9c0SAndroid Build Coastguard Worker 
34*bebae9c0SAndroid Build Coastguard Worker // These are extensions to OpenSL ES 1.0.1 values
35*bebae9c0SAndroid Build Coastguard Worker 
36*bebae9c0SAndroid Build Coastguard Worker #define SL_PREFETCHSTATUS_UNKNOWN 0
37*bebae9c0SAndroid Build Coastguard Worker #define SL_PREFETCHSTATUS_ERROR   ((SLuint32) -1)
38*bebae9c0SAndroid Build Coastguard Worker 
39*bebae9c0SAndroid Build Coastguard Worker // Mutex and condition shared with main program to protect prefetch_status
40*bebae9c0SAndroid Build Coastguard Worker 
41*bebae9c0SAndroid Build Coastguard Worker static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
42*bebae9c0SAndroid Build Coastguard Worker static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
43*bebae9c0SAndroid Build Coastguard Worker SLuint32 prefetch_status = SL_PREFETCHSTATUS_UNKNOWN;
44*bebae9c0SAndroid Build Coastguard Worker 
45*bebae9c0SAndroid Build Coastguard Worker /* used to detect errors likely to have occured when the OpenSL ES framework fails to open
46*bebae9c0SAndroid Build Coastguard Worker  * a resource, for instance because a file URI is invalid, or an HTTP server doesn't respond.
47*bebae9c0SAndroid Build Coastguard Worker  */
48*bebae9c0SAndroid Build Coastguard Worker #define PREFETCHEVENT_ERROR_CANDIDATE \
49*bebae9c0SAndroid Build Coastguard Worker         (SL_PREFETCHEVENT_STATUSCHANGE | SL_PREFETCHEVENT_FILLLEVELCHANGE)
50*bebae9c0SAndroid Build Coastguard Worker 
51*bebae9c0SAndroid Build Coastguard Worker //-----------------------------------------------------------------
52*bebae9c0SAndroid Build Coastguard Worker //* Exits the application if an error is encountered */
53*bebae9c0SAndroid Build Coastguard Worker #define CheckErr(x) ExitOnErrorFunc(x,__LINE__)
54*bebae9c0SAndroid Build Coastguard Worker 
ExitOnErrorFunc(SLresult result,int line)55*bebae9c0SAndroid Build Coastguard Worker void ExitOnErrorFunc( SLresult result , int line)
56*bebae9c0SAndroid Build Coastguard Worker {
57*bebae9c0SAndroid Build Coastguard Worker     if (SL_RESULT_SUCCESS != result) {
58*bebae9c0SAndroid Build Coastguard Worker         fprintf(stderr, "%u error code encountered at line %d, exiting\n", result, line);
59*bebae9c0SAndroid Build Coastguard Worker         exit(EXIT_FAILURE);
60*bebae9c0SAndroid Build Coastguard Worker     }
61*bebae9c0SAndroid Build Coastguard Worker }
62*bebae9c0SAndroid Build Coastguard Worker 
63*bebae9c0SAndroid Build Coastguard Worker //-----------------------------------------------------------------
64*bebae9c0SAndroid Build Coastguard Worker /* PlayItf callback for an audio player */
PlayEventCallback(SLPlayItf caller __unused,void * pContext,SLuint32 event)65*bebae9c0SAndroid Build Coastguard Worker void PlayEventCallback( SLPlayItf caller __unused, void *pContext, SLuint32 event)
66*bebae9c0SAndroid Build Coastguard Worker {
67*bebae9c0SAndroid Build Coastguard Worker     fprintf(stdout, "PlayEventCallback event = ");
68*bebae9c0SAndroid Build Coastguard Worker     if (event & SL_PLAYEVENT_HEADATEND) {
69*bebae9c0SAndroid Build Coastguard Worker         fprintf(stdout, "SL_PLAYEVENT_HEADATEND \n");
70*bebae9c0SAndroid Build Coastguard Worker         /* slow playback down by 2x for next loop,  if possible */
71*bebae9c0SAndroid Build Coastguard Worker         SLpermille minRate, maxRate, stepSize, rate = 1000;
72*bebae9c0SAndroid Build Coastguard Worker         SLuint32 capa;
73*bebae9c0SAndroid Build Coastguard Worker         assert(NULL != pContext);
74*bebae9c0SAndroid Build Coastguard Worker         SLPlaybackRateItf pRateItf = (SLPlaybackRateItf)pContext;
75*bebae9c0SAndroid Build Coastguard Worker         SLresult res = (*pRateItf)->GetRate(pRateItf, &rate); CheckErr(res);
76*bebae9c0SAndroid Build Coastguard Worker         res = (*pRateItf)->GetRateRange(pRateItf, 0, &minRate, &maxRate, &stepSize, &capa);
77*bebae9c0SAndroid Build Coastguard Worker         CheckErr(res);
78*bebae9c0SAndroid Build Coastguard Worker         fprintf(stdout, "old rate = %d, minRate=%d, maxRate=%d\n", rate, minRate, maxRate);
79*bebae9c0SAndroid Build Coastguard Worker         rate /= 2;
80*bebae9c0SAndroid Build Coastguard Worker         if (rate < minRate) {
81*bebae9c0SAndroid Build Coastguard Worker             rate = minRate;
82*bebae9c0SAndroid Build Coastguard Worker         }
83*bebae9c0SAndroid Build Coastguard Worker         fprintf(stdout, "new rate = %d\n", rate);
84*bebae9c0SAndroid Build Coastguard Worker         res = (*pRateItf)->SetRate(pRateItf, rate); CheckErr(res);
85*bebae9c0SAndroid Build Coastguard Worker         if (res == SL_RESULT_FEATURE_UNSUPPORTED) {
86*bebae9c0SAndroid Build Coastguard Worker             fprintf(stderr, "new playback rate %d per mille is unsupported\n", rate);
87*bebae9c0SAndroid Build Coastguard Worker         } else {
88*bebae9c0SAndroid Build Coastguard Worker             CheckErr(res);
89*bebae9c0SAndroid Build Coastguard Worker         }
90*bebae9c0SAndroid Build Coastguard Worker     }
91*bebae9c0SAndroid Build Coastguard Worker     if (event & SL_PLAYEVENT_HEADATMARKER) {
92*bebae9c0SAndroid Build Coastguard Worker         fprintf(stdout, "SL_PLAYEVENT_HEADATMARKER ");
93*bebae9c0SAndroid Build Coastguard Worker     }
94*bebae9c0SAndroid Build Coastguard Worker     if (event & SL_PLAYEVENT_HEADATNEWPOS) {
95*bebae9c0SAndroid Build Coastguard Worker         fprintf(stdout, "SL_PLAYEVENT_HEADATNEWPOS ");
96*bebae9c0SAndroid Build Coastguard Worker     }
97*bebae9c0SAndroid Build Coastguard Worker     if (event & SL_PLAYEVENT_HEADMOVING) {
98*bebae9c0SAndroid Build Coastguard Worker         fprintf(stdout, "SL_PLAYEVENT_HEADMOVING ");
99*bebae9c0SAndroid Build Coastguard Worker     }
100*bebae9c0SAndroid Build Coastguard Worker     if (event & SL_PLAYEVENT_HEADSTALLED) {
101*bebae9c0SAndroid Build Coastguard Worker         fprintf(stdout, "SL_PLAYEVENT_HEADSTALLED");
102*bebae9c0SAndroid Build Coastguard Worker     }
103*bebae9c0SAndroid Build Coastguard Worker     fprintf(stdout, "\n");
104*bebae9c0SAndroid Build Coastguard Worker }
105*bebae9c0SAndroid Build Coastguard Worker 
106*bebae9c0SAndroid Build Coastguard Worker //-----------------------------------------------------------------
107*bebae9c0SAndroid Build Coastguard Worker /* PrefetchStatusItf callback for an audio player */
PrefetchEventCallback(SLPrefetchStatusItf caller,void * pContext,SLuint32 event)108*bebae9c0SAndroid Build Coastguard Worker void PrefetchEventCallback( SLPrefetchStatusItf caller,  void *pContext, SLuint32 event)
109*bebae9c0SAndroid Build Coastguard Worker {
110*bebae9c0SAndroid Build Coastguard Worker     //fprintf(stdout, "\t\tPrefetchEventCallback: received event %u\n", event);
111*bebae9c0SAndroid Build Coastguard Worker     SLresult result;
112*bebae9c0SAndroid Build Coastguard Worker     assert(pContext == NULL);
113*bebae9c0SAndroid Build Coastguard Worker     SLpermille level = 0;
114*bebae9c0SAndroid Build Coastguard Worker     result = (*caller)->GetFillLevel(caller, &level);
115*bebae9c0SAndroid Build Coastguard Worker     CheckErr(result);
116*bebae9c0SAndroid Build Coastguard Worker     SLuint32 status;
117*bebae9c0SAndroid Build Coastguard Worker     result = (*caller)->GetPrefetchStatus(caller, &status);
118*bebae9c0SAndroid Build Coastguard Worker     CheckErr(result);
119*bebae9c0SAndroid Build Coastguard Worker     if (event & SL_PREFETCHEVENT_FILLLEVELCHANGE) {
120*bebae9c0SAndroid Build Coastguard Worker         fprintf(stdout, "\t\tPrefetchEventCallback: Buffer fill level is = %d\n", level);
121*bebae9c0SAndroid Build Coastguard Worker     }
122*bebae9c0SAndroid Build Coastguard Worker     if (event & SL_PREFETCHEVENT_STATUSCHANGE) {
123*bebae9c0SAndroid Build Coastguard Worker         fprintf(stdout, "\t\tPrefetchEventCallback: Prefetch Status is = %u\n", status);
124*bebae9c0SAndroid Build Coastguard Worker     }
125*bebae9c0SAndroid Build Coastguard Worker     SLuint32 new_prefetch_status;
126*bebae9c0SAndroid Build Coastguard Worker     if ((event & PREFETCHEVENT_ERROR_CANDIDATE) == PREFETCHEVENT_ERROR_CANDIDATE
127*bebae9c0SAndroid Build Coastguard Worker             && level == 0 && status == SL_PREFETCHSTATUS_UNDERFLOW) {
128*bebae9c0SAndroid Build Coastguard Worker         fprintf(stdout, "\t\tPrefetchEventCallback: Error while prefetching data, exiting\n");
129*bebae9c0SAndroid Build Coastguard Worker         new_prefetch_status = SL_PREFETCHSTATUS_ERROR;
130*bebae9c0SAndroid Build Coastguard Worker     } else if (event == SL_PREFETCHEVENT_STATUSCHANGE &&
131*bebae9c0SAndroid Build Coastguard Worker             status == SL_PREFETCHSTATUS_SUFFICIENTDATA) {
132*bebae9c0SAndroid Build Coastguard Worker         new_prefetch_status = status;
133*bebae9c0SAndroid Build Coastguard Worker     } else {
134*bebae9c0SAndroid Build Coastguard Worker         return;
135*bebae9c0SAndroid Build Coastguard Worker     }
136*bebae9c0SAndroid Build Coastguard Worker     int ok;
137*bebae9c0SAndroid Build Coastguard Worker     ok = pthread_mutex_lock(&mutex);
138*bebae9c0SAndroid Build Coastguard Worker     assert(ok == 0);
139*bebae9c0SAndroid Build Coastguard Worker     prefetch_status = new_prefetch_status;
140*bebae9c0SAndroid Build Coastguard Worker     ok = pthread_cond_signal(&cond);
141*bebae9c0SAndroid Build Coastguard Worker     assert(ok == 0);
142*bebae9c0SAndroid Build Coastguard Worker     ok = pthread_mutex_unlock(&mutex);
143*bebae9c0SAndroid Build Coastguard Worker     assert(ok == 0);
144*bebae9c0SAndroid Build Coastguard Worker }
145*bebae9c0SAndroid Build Coastguard Worker 
146*bebae9c0SAndroid Build Coastguard Worker // Display rate capabilities in a nicely formatted way
147*bebae9c0SAndroid Build Coastguard Worker 
printCapabilities(SLuint32 capabilities)148*bebae9c0SAndroid Build Coastguard Worker void printCapabilities(SLuint32 capabilities)
149*bebae9c0SAndroid Build Coastguard Worker {
150*bebae9c0SAndroid Build Coastguard Worker     bool needBar = false;
151*bebae9c0SAndroid Build Coastguard Worker     printf("0x%x (", capabilities);
152*bebae9c0SAndroid Build Coastguard Worker #define _(x)                             \
153*bebae9c0SAndroid Build Coastguard Worker     if (capabilities & SL_RATEPROP_##x) { \
154*bebae9c0SAndroid Build Coastguard Worker         if (needBar)                     \
155*bebae9c0SAndroid Build Coastguard Worker             printf("|");                 \
156*bebae9c0SAndroid Build Coastguard Worker         printf("SL_RATEPROP_" #x);        \
157*bebae9c0SAndroid Build Coastguard Worker         needBar = true;                  \
158*bebae9c0SAndroid Build Coastguard Worker         capabilities &= ~SL_RATEPROP_##x; \
159*bebae9c0SAndroid Build Coastguard Worker     }
160*bebae9c0SAndroid Build Coastguard Worker     _(SILENTAUDIO)
161*bebae9c0SAndroid Build Coastguard Worker     _(STAGGEREDAUDIO)
162*bebae9c0SAndroid Build Coastguard Worker     _(NOPITCHCORAUDIO)
163*bebae9c0SAndroid Build Coastguard Worker     _(PITCHCORAUDIO)
164*bebae9c0SAndroid Build Coastguard Worker     if (capabilities != 0) {
165*bebae9c0SAndroid Build Coastguard Worker         if (needBar)
166*bebae9c0SAndroid Build Coastguard Worker             printf("|");
167*bebae9c0SAndroid Build Coastguard Worker         printf("0x%x", capabilities);
168*bebae9c0SAndroid Build Coastguard Worker         needBar = true;
169*bebae9c0SAndroid Build Coastguard Worker     }
170*bebae9c0SAndroid Build Coastguard Worker     if (!needBar)
171*bebae9c0SAndroid Build Coastguard Worker         printf("N/A");
172*bebae9c0SAndroid Build Coastguard Worker     printf(")");
173*bebae9c0SAndroid Build Coastguard Worker }
174*bebae9c0SAndroid Build Coastguard Worker 
175*bebae9c0SAndroid Build Coastguard Worker //-----------------------------------------------------------------
176*bebae9c0SAndroid Build Coastguard Worker 
177*bebae9c0SAndroid Build Coastguard Worker /* Play some music from a URI  */
TestSlowDownUri(SLObjectItf sl,const char * path)178*bebae9c0SAndroid Build Coastguard Worker void TestSlowDownUri( SLObjectItf sl, const char* path)
179*bebae9c0SAndroid Build Coastguard Worker {
180*bebae9c0SAndroid Build Coastguard Worker     SLEngineItf                EngineItf;
181*bebae9c0SAndroid Build Coastguard Worker 
182*bebae9c0SAndroid Build Coastguard Worker     SLresult                   res;
183*bebae9c0SAndroid Build Coastguard Worker 
184*bebae9c0SAndroid Build Coastguard Worker     SLDataSource               audioSource;
185*bebae9c0SAndroid Build Coastguard Worker     SLDataLocator_URI          uri;
186*bebae9c0SAndroid Build Coastguard Worker     SLDataFormat_MIME          mime;
187*bebae9c0SAndroid Build Coastguard Worker 
188*bebae9c0SAndroid Build Coastguard Worker     SLDataSink                 audioSink;
189*bebae9c0SAndroid Build Coastguard Worker     SLDataLocator_OutputMix    locator_outputmix;
190*bebae9c0SAndroid Build Coastguard Worker 
191*bebae9c0SAndroid Build Coastguard Worker     SLObjectItf                player;
192*bebae9c0SAndroid Build Coastguard Worker     SLPlayItf                  playItf;
193*bebae9c0SAndroid Build Coastguard Worker     SLSeekItf                  seekItf;
194*bebae9c0SAndroid Build Coastguard Worker     SLPrefetchStatusItf        prefetchItf;
195*bebae9c0SAndroid Build Coastguard Worker     SLPlaybackRateItf          rateItf;
196*bebae9c0SAndroid Build Coastguard Worker 
197*bebae9c0SAndroid Build Coastguard Worker     SLObjectItf                OutputMix;
198*bebae9c0SAndroid Build Coastguard Worker 
199*bebae9c0SAndroid Build Coastguard Worker     SLboolean required[MAX_NUMBER_INTERFACES];
200*bebae9c0SAndroid Build Coastguard Worker     SLInterfaceID iidArray[MAX_NUMBER_INTERFACES];
201*bebae9c0SAndroid Build Coastguard Worker 
202*bebae9c0SAndroid Build Coastguard Worker     /* Get the SL Engine Interface which is implicit */
203*bebae9c0SAndroid Build Coastguard Worker     res = (*sl)->GetInterface(sl, SL_IID_ENGINE, (void*)&EngineItf);   CheckErr(res);
204*bebae9c0SAndroid Build Coastguard Worker 
205*bebae9c0SAndroid Build Coastguard Worker     /* Initialize arrays required[] and iidArray[] */
206*bebae9c0SAndroid Build Coastguard Worker     for (int i=0 ; i < MAX_NUMBER_INTERFACES ; i++) {
207*bebae9c0SAndroid Build Coastguard Worker         required[i] = SL_BOOLEAN_FALSE;
208*bebae9c0SAndroid Build Coastguard Worker         iidArray[i] = SL_IID_NULL;
209*bebae9c0SAndroid Build Coastguard Worker     }
210*bebae9c0SAndroid Build Coastguard Worker 
211*bebae9c0SAndroid Build Coastguard Worker     required[0] = SL_BOOLEAN_TRUE;
212*bebae9c0SAndroid Build Coastguard Worker     iidArray[0] = SL_IID_VOLUME;
213*bebae9c0SAndroid Build Coastguard Worker     // Create Output Mix object to be used by player
214*bebae9c0SAndroid Build Coastguard Worker     res = (*EngineItf)->CreateOutputMix(EngineItf, &OutputMix, 0,
215*bebae9c0SAndroid Build Coastguard Worker             iidArray, required);  CheckErr(res);
216*bebae9c0SAndroid Build Coastguard Worker 
217*bebae9c0SAndroid Build Coastguard Worker     // Realizing the Output Mix object in synchronous mode.
218*bebae9c0SAndroid Build Coastguard Worker     res = (*OutputMix)->Realize(OutputMix, SL_BOOLEAN_FALSE);  CheckErr(res);
219*bebae9c0SAndroid Build Coastguard Worker 
220*bebae9c0SAndroid Build Coastguard Worker     /* Setup the data source structure for the URI */
221*bebae9c0SAndroid Build Coastguard Worker     uri.locatorType = SL_DATALOCATOR_URI;
222*bebae9c0SAndroid Build Coastguard Worker     uri.URI         =  (SLchar*) path;
223*bebae9c0SAndroid Build Coastguard Worker     mime.formatType    = SL_DATAFORMAT_MIME;
224*bebae9c0SAndroid Build Coastguard Worker     mime.mimeType      = (SLchar*)NULL;
225*bebae9c0SAndroid Build Coastguard Worker     mime.containerType = SL_CONTAINERTYPE_UNSPECIFIED;
226*bebae9c0SAndroid Build Coastguard Worker 
227*bebae9c0SAndroid Build Coastguard Worker     audioSource.pFormat  = (void *)&mime;
228*bebae9c0SAndroid Build Coastguard Worker     audioSource.pLocator = (void *)&uri;
229*bebae9c0SAndroid Build Coastguard Worker 
230*bebae9c0SAndroid Build Coastguard Worker     /* Setup the data sink structure */
231*bebae9c0SAndroid Build Coastguard Worker     locator_outputmix.locatorType = SL_DATALOCATOR_OUTPUTMIX;
232*bebae9c0SAndroid Build Coastguard Worker     locator_outputmix.outputMix   = OutputMix;
233*bebae9c0SAndroid Build Coastguard Worker     audioSink.pLocator            = (void *)&locator_outputmix;
234*bebae9c0SAndroid Build Coastguard Worker     audioSink.pFormat             = NULL;
235*bebae9c0SAndroid Build Coastguard Worker 
236*bebae9c0SAndroid Build Coastguard Worker     /******************************************************/
237*bebae9c0SAndroid Build Coastguard Worker     /* Create the audio player */
238*bebae9c0SAndroid Build Coastguard Worker     required[0] = SL_BOOLEAN_TRUE;
239*bebae9c0SAndroid Build Coastguard Worker     iidArray[0] = SL_IID_SEEK;
240*bebae9c0SAndroid Build Coastguard Worker     required[1] = SL_BOOLEAN_TRUE;
241*bebae9c0SAndroid Build Coastguard Worker     iidArray[1] = SL_IID_PREFETCHSTATUS;
242*bebae9c0SAndroid Build Coastguard Worker     required[2] = SL_BOOLEAN_TRUE;
243*bebae9c0SAndroid Build Coastguard Worker     iidArray[2] = SL_IID_PLAYBACKRATE;
244*bebae9c0SAndroid Build Coastguard Worker     res = (*EngineItf)->CreateAudioPlayer(EngineItf, &player, &audioSource, &audioSink,
245*bebae9c0SAndroid Build Coastguard Worker             MAX_NUMBER_INTERFACES, iidArray, required); CheckErr(res);
246*bebae9c0SAndroid Build Coastguard Worker 
247*bebae9c0SAndroid Build Coastguard Worker     /* Realizing the player in synchronous mode. */
248*bebae9c0SAndroid Build Coastguard Worker     res = (*player)->Realize(player, SL_BOOLEAN_FALSE); CheckErr(res);
249*bebae9c0SAndroid Build Coastguard Worker     fprintf(stdout, "URI example: after Realize\n");
250*bebae9c0SAndroid Build Coastguard Worker 
251*bebae9c0SAndroid Build Coastguard Worker     /* Get interfaces */
252*bebae9c0SAndroid Build Coastguard Worker     res = (*player)->GetInterface(player, SL_IID_PLAY, (void*)&playItf);  CheckErr(res);
253*bebae9c0SAndroid Build Coastguard Worker 
254*bebae9c0SAndroid Build Coastguard Worker     res = (*player)->GetInterface(player, SL_IID_SEEK,  (void*)&seekItf);  CheckErr(res);
255*bebae9c0SAndroid Build Coastguard Worker 
256*bebae9c0SAndroid Build Coastguard Worker     res = (*player)->GetInterface(player, SL_IID_PLAYBACKRATE, (void*)&rateItf);  CheckErr(res);
257*bebae9c0SAndroid Build Coastguard Worker 
258*bebae9c0SAndroid Build Coastguard Worker     res = (*player)->GetInterface(player, SL_IID_PREFETCHSTATUS, (void*)&prefetchItf);
259*bebae9c0SAndroid Build Coastguard Worker     CheckErr(res);
260*bebae9c0SAndroid Build Coastguard Worker     res = (*prefetchItf)->RegisterCallback(prefetchItf, PrefetchEventCallback, NULL);
261*bebae9c0SAndroid Build Coastguard Worker     CheckErr(res);
262*bebae9c0SAndroid Build Coastguard Worker     res = (*prefetchItf)->SetCallbackEventsMask(prefetchItf,
263*bebae9c0SAndroid Build Coastguard Worker             SL_PREFETCHEVENT_FILLLEVELCHANGE | SL_PREFETCHEVENT_STATUSCHANGE);  CheckErr(res);
264*bebae9c0SAndroid Build Coastguard Worker 
265*bebae9c0SAndroid Build Coastguard Worker     /* Configure fill level updates every 5 percent */
266*bebae9c0SAndroid Build Coastguard Worker     (*prefetchItf)->SetFillUpdatePeriod(prefetchItf, 50);  CheckErr(res);
267*bebae9c0SAndroid Build Coastguard Worker 
268*bebae9c0SAndroid Build Coastguard Worker     /* Display duration */
269*bebae9c0SAndroid Build Coastguard Worker     SLmillisecond durationInMsec = SL_TIME_UNKNOWN;
270*bebae9c0SAndroid Build Coastguard Worker     res = (*playItf)->GetDuration(playItf, &durationInMsec);  CheckErr(res);
271*bebae9c0SAndroid Build Coastguard Worker     if (durationInMsec == SL_TIME_UNKNOWN) {
272*bebae9c0SAndroid Build Coastguard Worker         fprintf(stdout, "Content duration is unknown (before starting to prefetch)\n");
273*bebae9c0SAndroid Build Coastguard Worker     } else {
274*bebae9c0SAndroid Build Coastguard Worker         fprintf(stdout, "Content duration is %u ms (before starting to prefetch)\n",
275*bebae9c0SAndroid Build Coastguard Worker                 durationInMsec);
276*bebae9c0SAndroid Build Coastguard Worker     }
277*bebae9c0SAndroid Build Coastguard Worker 
278*bebae9c0SAndroid Build Coastguard Worker     /* Loop on the whole of the content */
279*bebae9c0SAndroid Build Coastguard Worker     res = (*seekItf)->SetLoop(seekItf, SL_BOOLEAN_TRUE, 0, SL_TIME_UNKNOWN);  CheckErr(res);
280*bebae9c0SAndroid Build Coastguard Worker 
281*bebae9c0SAndroid Build Coastguard Worker     /* Set up marker and position callbacks */
282*bebae9c0SAndroid Build Coastguard Worker     res = (*playItf)->RegisterCallback(playItf, PlayEventCallback, (void *) rateItf);
283*bebae9c0SAndroid Build Coastguard Worker             CheckErr(res);
284*bebae9c0SAndroid Build Coastguard Worker     res = (*playItf)->SetCallbackEventsMask(playItf,
285*bebae9c0SAndroid Build Coastguard Worker             SL_PLAYEVENT_HEADATEND | SL_PLAYEVENT_HEADATMARKER | SL_PLAYEVENT_HEADATNEWPOS);
286*bebae9c0SAndroid Build Coastguard Worker     res = (*playItf)->SetMarkerPosition(playItf, 1500); CheckErr(res);
287*bebae9c0SAndroid Build Coastguard Worker     res = (*playItf)->SetPositionUpdatePeriod(playItf, 500); CheckErr(res);
288*bebae9c0SAndroid Build Coastguard Worker 
289*bebae9c0SAndroid Build Coastguard Worker     /* Get the default rate */
290*bebae9c0SAndroid Build Coastguard Worker     SLpermille rate = 1234;
291*bebae9c0SAndroid Build Coastguard Worker     res = (*rateItf)->GetRate(rateItf, &rate); CheckErr(res);
292*bebae9c0SAndroid Build Coastguard Worker     printf("default rate = %d per mille\n", rate);
293*bebae9c0SAndroid Build Coastguard Worker     assert(1000 == rate);
294*bebae9c0SAndroid Build Coastguard Worker 
295*bebae9c0SAndroid Build Coastguard Worker     /* Get the default rate properties */
296*bebae9c0SAndroid Build Coastguard Worker     SLuint32 properties = 0;
297*bebae9c0SAndroid Build Coastguard Worker     res = (*rateItf)->GetProperties(rateItf, &properties); CheckErr(res);
298*bebae9c0SAndroid Build Coastguard Worker     printf("default rate properties: ");
299*bebae9c0SAndroid Build Coastguard Worker     printCapabilities(properties);
300*bebae9c0SAndroid Build Coastguard Worker     printf("\n");
301*bebae9c0SAndroid Build Coastguard Worker     assert(SL_RATEPROP_NOPITCHCORAUDIO == properties);
302*bebae9c0SAndroid Build Coastguard Worker 
303*bebae9c0SAndroid Build Coastguard Worker     /* Get all supported playback rate ranges */
304*bebae9c0SAndroid Build Coastguard Worker     SLuint8 index;
305*bebae9c0SAndroid Build Coastguard Worker     for (index = 0; ; ++index) {
306*bebae9c0SAndroid Build Coastguard Worker         SLpermille minRate, maxRate, stepSize;
307*bebae9c0SAndroid Build Coastguard Worker         SLuint32 capabilities;
308*bebae9c0SAndroid Build Coastguard Worker         res = (*rateItf)->GetRateRange(rateItf, index, &minRate, &maxRate, &stepSize,
309*bebae9c0SAndroid Build Coastguard Worker                 &capabilities);
310*bebae9c0SAndroid Build Coastguard Worker         if (res == SL_RESULT_PARAMETER_INVALID) {
311*bebae9c0SAndroid Build Coastguard Worker             if (index == 0) {
312*bebae9c0SAndroid Build Coastguard Worker                 fprintf(stderr, "implementation supports no rate ranges\n");
313*bebae9c0SAndroid Build Coastguard Worker             }
314*bebae9c0SAndroid Build Coastguard Worker             break;
315*bebae9c0SAndroid Build Coastguard Worker         }
316*bebae9c0SAndroid Build Coastguard Worker         CheckErr(res);
317*bebae9c0SAndroid Build Coastguard Worker         if (index == 255) {
318*bebae9c0SAndroid Build Coastguard Worker             fprintf(stderr, "implementation supports way too many rate ranges, I'm giving up\n");
319*bebae9c0SAndroid Build Coastguard Worker             break;
320*bebae9c0SAndroid Build Coastguard Worker         }
321*bebae9c0SAndroid Build Coastguard Worker         printf("range[%u]: min=%d, max=%d, capabilities=", index, minRate, maxRate);
322*bebae9c0SAndroid Build Coastguard Worker         printCapabilities(capabilities);
323*bebae9c0SAndroid Build Coastguard Worker         printf("\n");
324*bebae9c0SAndroid Build Coastguard Worker     }
325*bebae9c0SAndroid Build Coastguard Worker 
326*bebae9c0SAndroid Build Coastguard Worker     /* Change the playback rate before playback */
327*bebae9c0SAndroid Build Coastguard Worker     res = (*rateItf)->SetRate(rateItf, INITIAL_RATE);
328*bebae9c0SAndroid Build Coastguard Worker     if (res == SL_RESULT_FEATURE_UNSUPPORTED || res == SL_RESULT_PARAMETER_INVALID) {
329*bebae9c0SAndroid Build Coastguard Worker         fprintf(stderr, "initial playback rate %d per mille is unsupported\n", INITIAL_RATE);
330*bebae9c0SAndroid Build Coastguard Worker     } else {
331*bebae9c0SAndroid Build Coastguard Worker         CheckErr(res);
332*bebae9c0SAndroid Build Coastguard Worker     }
333*bebae9c0SAndroid Build Coastguard Worker 
334*bebae9c0SAndroid Build Coastguard Worker     /******************************************************/
335*bebae9c0SAndroid Build Coastguard Worker     /* Play the URI */
336*bebae9c0SAndroid Build Coastguard Worker     /*     first cause the player to prefetch the data */
337*bebae9c0SAndroid Build Coastguard Worker     res = (*playItf)->SetPlayState( playItf, SL_PLAYSTATE_PAUSED ); CheckErr(res);
338*bebae9c0SAndroid Build Coastguard Worker 
339*bebae9c0SAndroid Build Coastguard Worker     // wait for prefetch status callback to indicate either sufficient data or error
340*bebae9c0SAndroid Build Coastguard Worker     pthread_mutex_lock(&mutex);
341*bebae9c0SAndroid Build Coastguard Worker     while (prefetch_status == SL_PREFETCHSTATUS_UNKNOWN) {
342*bebae9c0SAndroid Build Coastguard Worker         pthread_cond_wait(&cond, &mutex);
343*bebae9c0SAndroid Build Coastguard Worker     }
344*bebae9c0SAndroid Build Coastguard Worker     pthread_mutex_unlock(&mutex);
345*bebae9c0SAndroid Build Coastguard Worker     if (prefetch_status == SL_PREFETCHSTATUS_ERROR) {
346*bebae9c0SAndroid Build Coastguard Worker         fprintf(stderr, "Error during prefetch, exiting\n");
347*bebae9c0SAndroid Build Coastguard Worker         goto destroyRes;
348*bebae9c0SAndroid Build Coastguard Worker     }
349*bebae9c0SAndroid Build Coastguard Worker 
350*bebae9c0SAndroid Build Coastguard Worker     /* Display duration again, */
351*bebae9c0SAndroid Build Coastguard Worker     res = (*playItf)->GetDuration(playItf, &durationInMsec); CheckErr(res);
352*bebae9c0SAndroid Build Coastguard Worker     if (durationInMsec == SL_TIME_UNKNOWN) {
353*bebae9c0SAndroid Build Coastguard Worker         fprintf(stdout, "Content duration is unknown (after prefetch completed)\n");
354*bebae9c0SAndroid Build Coastguard Worker     } else {
355*bebae9c0SAndroid Build Coastguard Worker         fprintf(stdout, "Content duration is %u ms (after prefetch completed)\n", durationInMsec);
356*bebae9c0SAndroid Build Coastguard Worker     }
357*bebae9c0SAndroid Build Coastguard Worker 
358*bebae9c0SAndroid Build Coastguard Worker     /* Start playing */
359*bebae9c0SAndroid Build Coastguard Worker     fprintf(stdout, "starting to play\n");
360*bebae9c0SAndroid Build Coastguard Worker     res = (*playItf)->SetPlayState( playItf, SL_PLAYSTATE_PLAYING ); CheckErr(res);
361*bebae9c0SAndroid Build Coastguard Worker 
362*bebae9c0SAndroid Build Coastguard Worker     /* Wait as long as the duration of the content, times the repetitions,
363*bebae9c0SAndroid Build Coastguard Worker      * before stopping the loop */
364*bebae9c0SAndroid Build Coastguard Worker #if 1
365*bebae9c0SAndroid Build Coastguard Worker     usleep( (REPETITIONS-1) * durationInMsec * 1100);
366*bebae9c0SAndroid Build Coastguard Worker #else
367*bebae9c0SAndroid Build Coastguard Worker     int ii;
368*bebae9c0SAndroid Build Coastguard Worker     for (ii = 0; ii < REPETITIONS; ++ii) {
369*bebae9c0SAndroid Build Coastguard Worker         usleep(durationInMsec * 1100);
370*bebae9c0SAndroid Build Coastguard Worker         PlayEventCallback(playItf, (void *) rateItf, SL_PLAYEVENT_HEADATEND);
371*bebae9c0SAndroid Build Coastguard Worker     }
372*bebae9c0SAndroid Build Coastguard Worker #endif
373*bebae9c0SAndroid Build Coastguard Worker 
374*bebae9c0SAndroid Build Coastguard Worker     res = (*seekItf)->SetLoop(seekItf, SL_BOOLEAN_FALSE, 0, SL_TIME_UNKNOWN); CheckErr(res);
375*bebae9c0SAndroid Build Coastguard Worker     fprintf(stdout, "As of now, stopped looping (sound shouldn't repeat from now on)\n");
376*bebae9c0SAndroid Build Coastguard Worker     /* wait some more to make sure it doesn't repeat */
377*bebae9c0SAndroid Build Coastguard Worker     usleep(durationInMsec * 1000);
378*bebae9c0SAndroid Build Coastguard Worker 
379*bebae9c0SAndroid Build Coastguard Worker     /* Stop playback */
380*bebae9c0SAndroid Build Coastguard Worker     fprintf(stdout, "stopping playback\n");
381*bebae9c0SAndroid Build Coastguard Worker     res = (*playItf)->SetPlayState(playItf, SL_PLAYSTATE_STOPPED); CheckErr(res);
382*bebae9c0SAndroid Build Coastguard Worker 
383*bebae9c0SAndroid Build Coastguard Worker destroyRes:
384*bebae9c0SAndroid Build Coastguard Worker 
385*bebae9c0SAndroid Build Coastguard Worker     /* Destroy the player */
386*bebae9c0SAndroid Build Coastguard Worker     (*player)->Destroy(player);
387*bebae9c0SAndroid Build Coastguard Worker 
388*bebae9c0SAndroid Build Coastguard Worker     /* Destroy Output Mix object */
389*bebae9c0SAndroid Build Coastguard Worker     (*OutputMix)->Destroy(OutputMix);
390*bebae9c0SAndroid Build Coastguard Worker }
391*bebae9c0SAndroid Build Coastguard Worker 
392*bebae9c0SAndroid Build Coastguard Worker //-----------------------------------------------------------------
main(int argc,char * const argv[])393*bebae9c0SAndroid Build Coastguard Worker int main(int argc, char* const argv[])
394*bebae9c0SAndroid Build Coastguard Worker {
395*bebae9c0SAndroid Build Coastguard Worker     SLresult    res;
396*bebae9c0SAndroid Build Coastguard Worker     SLObjectItf sl;
397*bebae9c0SAndroid Build Coastguard Worker 
398*bebae9c0SAndroid Build Coastguard Worker     fprintf(stdout, "OpenSL ES test %s: exercises SLPlayItf, SLSeekItf, SLPlaybackRateItf\n",
399*bebae9c0SAndroid Build Coastguard Worker             argv[0]);
400*bebae9c0SAndroid Build Coastguard Worker     fprintf(stdout, "and AudioPlayer with SLDataLocator_URI source / OutputMix sink\n");
401*bebae9c0SAndroid Build Coastguard Worker     fprintf(stdout, "Plays a sound and loops it %d times while changing the \n", REPETITIONS);
402*bebae9c0SAndroid Build Coastguard Worker     fprintf(stdout, "playback rate each time.\n\n");
403*bebae9c0SAndroid Build Coastguard Worker 
404*bebae9c0SAndroid Build Coastguard Worker     if (argc == 1) {
405*bebae9c0SAndroid Build Coastguard Worker         fprintf(stdout, "Usage: \n\t%s path \n\t%s url\n", argv[0], argv[0]);
406*bebae9c0SAndroid Build Coastguard Worker         fprintf(stdout, "Example: \"%s /sdcard/my.mp3\"  or \"%s file:///sdcard/my.mp3\"\n",
407*bebae9c0SAndroid Build Coastguard Worker                 argv[0], argv[0]);
408*bebae9c0SAndroid Build Coastguard Worker         return EXIT_FAILURE;
409*bebae9c0SAndroid Build Coastguard Worker     }
410*bebae9c0SAndroid Build Coastguard Worker 
411*bebae9c0SAndroid Build Coastguard Worker     SLEngineOption EngineOption[] = {
412*bebae9c0SAndroid Build Coastguard Worker             {(SLuint32) SL_ENGINEOPTION_THREADSAFE,
413*bebae9c0SAndroid Build Coastguard Worker             (SLuint32) SL_BOOLEAN_TRUE}};
414*bebae9c0SAndroid Build Coastguard Worker 
415*bebae9c0SAndroid Build Coastguard Worker     res = slCreateEngine( &sl, 1, EngineOption, 0, NULL, NULL);
416*bebae9c0SAndroid Build Coastguard Worker     CheckErr(res);
417*bebae9c0SAndroid Build Coastguard Worker     /* Realizing the SL Engine in synchronous mode. */
418*bebae9c0SAndroid Build Coastguard Worker     res = (*sl)->Realize(sl, SL_BOOLEAN_FALSE);
419*bebae9c0SAndroid Build Coastguard Worker     CheckErr(res);
420*bebae9c0SAndroid Build Coastguard Worker 
421*bebae9c0SAndroid Build Coastguard Worker     TestSlowDownUri(sl, argv[1]);
422*bebae9c0SAndroid Build Coastguard Worker 
423*bebae9c0SAndroid Build Coastguard Worker     /* Shutdown OpenSL ES */
424*bebae9c0SAndroid Build Coastguard Worker     (*sl)->Destroy(sl);
425*bebae9c0SAndroid Build Coastguard Worker 
426*bebae9c0SAndroid Build Coastguard Worker     return EXIT_SUCCESS;
427*bebae9c0SAndroid Build Coastguard Worker }
428