• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2011 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 /* Audio Decode Test
18 
19 First run the program from shell:
20   # slesTest_decodeToBuffQueue /sdcard/myFile.mp3 4
21 
22 These use adb on host to retrieve the decoded file:
23   % adb pull /sdcard/myFile.mp3.raw myFile.raw
24 
25 How to examine the output with Audacity:
26  Project / Import raw data
27  Select myFile.raw file, then click Open button
28  Choose these options:
29   Signed 16-bit PCM
30   Little-endian
31   1 Channel (Mono) / 2 Channels (Stereo) based on the selected file
32   Sample rate same as the selected file
33  Click Import button
34 
35 */
36 
37 
38 #include <stdlib.h>
39 #include <stdio.h>
40 #include <string.h>
41 #include <unistd.h>
42 #include <sys/time.h>
43 #include <fcntl.h>
44 #include <utils/threads.h>
45 
46 #include <SLES/OpenSLES.h>
47 #include <SLES/OpenSLES_Android.h>
48 
49 /* Explicitly requesting SL_IID_ANDROIDSIMPLEBUFFERQUEUE and SL_IID_PREFETCHSTATUS
50  * on the AudioPlayer object for decoding, SL_IID_METADATAEXTRACTION for retrieving the
51  * format of the decoded audio */
52 #define NUM_EXPLICIT_INTERFACES_FOR_PLAYER 3
53 
54 /* Size of the decode buffer queue */
55 #define NB_BUFFERS_IN_QUEUE 4
56 /* Size of each buffer in the queue */
57 #define BUFFER_SIZE_IN_SAMPLES 1152 // number of samples per MP3 frame
58 #define BUFFER_SIZE_IN_BYTES   (2*BUFFER_SIZE_IN_SAMPLES)
59 
60 /* Local storage for decoded audio data */
61 int8_t pcmData[NB_BUFFERS_IN_QUEUE * BUFFER_SIZE_IN_BYTES];
62 
63 /* destination for decoded data */
64 static FILE* gFp;
65 
66 /* to display the number of decode iterations */
67 static int counter=0;
68 
69 /* metadata key index for the PCM format information we want to retrieve */
70 static int channelCountKeyIndex = -1;
71 static int sampleRateKeyIndex = -1;
72 /* size of the struct to retrieve the PCM format metadata values: the values we're interested in
73  * are SLuint32, but it is saved in the data field of a SLMetadataInfo, hence the larger size.
74  * Nate that this size is queried and displayed at l.452 for demonstration/test purposes.
75  *  */
76 #define PCM_METADATA_VALUE_SIZE 32
77 /* used to query metadata values */
78 static SLMetadataInfo *pcmMetaData = NULL;
79 /* we only want to query / display the PCM format once */
80 static bool formatQueried = false;
81 
82 /* to signal to the test app the end of the stream to decode has been reached */
83 bool eos = false;
84 android::Mutex eosLock;
85 android::Condition eosCondition;
86 
87 /* used to detect errors likely to have occured when the OpenSL ES framework fails to open
88  * a resource, for instance because a file URI is invalid, or an HTTP server doesn't respond.
89  */
90 #define PREFETCHEVENT_ERROR_CANDIDATE \
91         (SL_PREFETCHEVENT_STATUSCHANGE | SL_PREFETCHEVENT_FILLLEVELCHANGE)
92 
93 //-----------------------------------------------------------------
94 /* Exits the application if an error is encountered */
95 #define ExitOnError(x) ExitOnErrorFunc(x,__LINE__)
96 
ExitOnErrorFunc(SLresult result,int line)97 void ExitOnErrorFunc( SLresult result , int line)
98 {
99     if (SL_RESULT_SUCCESS != result) {
100         fprintf(stderr, "Error code %u encountered at line %d, exiting\n", result, line);
101         exit(EXIT_FAILURE);
102     }
103 }
104 
105 /* Used to signal prefetching failures */
106 bool prefetchError = false;
107 
108 //-----------------------------------------------------------------
109 /* Structure for passing information to callback function */
110 typedef struct CallbackCntxt_ {
111     SLPlayItf playItf;
112     SLMetadataExtractionItf metaItf;
113     SLuint32  size;
114     SLint8*   pDataBase;    // Base address of local audio data storage
115     SLint8*   pData;        // Current address of local audio data storage
116 } CallbackCntxt;
117 
118 //-----------------------------------------------------------------
SignalEos()119 void SignalEos() {
120     android::Mutex::Autolock autoLock(eosLock);
121     eos = true;
122     eosCondition.signal();
123 }
124 
125 //-----------------------------------------------------------------
126 /* Callback for "prefetch" events, here used to detect audio resource opening errors */
PrefetchEventCallback(SLPrefetchStatusItf caller,void * pContext __unused,SLuint32 event)127 void PrefetchEventCallback( SLPrefetchStatusItf caller,  void *pContext __unused, SLuint32 event)
128 {
129     SLpermille level = 0;
130     SLresult result;
131     result = (*caller)->GetFillLevel(caller, &level);
132     ExitOnError(result);
133     SLuint32 status;
134     //fprintf(stdout, "PrefetchEventCallback: received event %u\n", event);
135     result = (*caller)->GetPrefetchStatus(caller, &status);
136     ExitOnError(result);
137     if ((PREFETCHEVENT_ERROR_CANDIDATE == (event & PREFETCHEVENT_ERROR_CANDIDATE))
138             && (level == 0) && (status == SL_PREFETCHSTATUS_UNDERFLOW)) {
139         fprintf(stdout, "PrefetchEventCallback: Error while prefetching data, exiting\n");
140         prefetchError = true;
141         SignalEos();
142     }
143 }
144 
145 /* Callback for "playback" events, i.e. event happening during decoding */
DecProgressCallback(SLPlayItf caller,void * pContext __unused,SLuint32 event)146 void DecProgressCallback(
147         SLPlayItf caller,
148         void *pContext __unused,
149         SLuint32 event)
150 {
151     SLresult result;
152     SLmillisecond msec;
153     result = (*caller)->GetPosition(caller, &msec);
154     ExitOnError(result);
155 
156     if (SL_PLAYEVENT_HEADATEND & event) {
157         fprintf(stdout, "SL_PLAYEVENT_HEADATEND current position=%u ms\n", msec);
158         SignalEos();
159     }
160 
161     if (SL_PLAYEVENT_HEADATNEWPOS & event) {
162         fprintf(stdout, "SL_PLAYEVENT_HEADATNEWPOS current position=%u ms\n", msec);
163     }
164 
165     if (SL_PLAYEVENT_HEADATMARKER & event) {
166         fprintf(stdout, "SL_PLAYEVENT_HEADATMARKER current position=%u ms\n", msec);
167     }
168 }
169 
170 //-----------------------------------------------------------------
171 /* Callback for decoding buffer queue events */
DecPlayCallback(SLAndroidSimpleBufferQueueItf queueItf,void * pContext)172 void DecPlayCallback(
173         SLAndroidSimpleBufferQueueItf queueItf,
174         void *pContext)
175 {
176     counter++;
177 
178     CallbackCntxt *pCntxt = (CallbackCntxt*)pContext;
179 
180     if (counter % 1000 == 0) {
181         SLmillisecond msec;
182         SLresult result = (*pCntxt->playItf)->GetPosition(pCntxt->playItf, &msec);
183         ExitOnError(result);
184         printf("DecPlayCallback called (iteration %d): current position=%u ms\n", counter, msec);
185     }
186 
187     /* Save the decoded data  */
188     if (fwrite(pCntxt->pDataBase, 1, BUFFER_SIZE_IN_BYTES, gFp) < BUFFER_SIZE_IN_BYTES) {
189         fprintf(stdout, "Error writing to output file, signaling EOS\n");
190         SignalEos();
191         return;
192     }
193 
194     /* Increase data pointer by buffer size */
195     pCntxt->pData += BUFFER_SIZE_IN_BYTES;
196 
197     if (pCntxt->pData >= pCntxt->pDataBase + (NB_BUFFERS_IN_QUEUE * BUFFER_SIZE_IN_BYTES)) {
198         pCntxt->pData = pCntxt->pDataBase;
199     }
200 
201     ExitOnError( (*queueItf)->Enqueue(queueItf, pCntxt->pDataBase, BUFFER_SIZE_IN_BYTES) );
202     // Note: adding a sleep here or any sync point is a way to slow down the decoding, or
203     //  synchronize it with some other event, as the OpenSL ES framework will block until the
204     //  buffer queue callback return to proceed with the decoding.
205 
206 #if 0
207     /* Example: buffer queue state display */
208     SLAndroidSimpleBufferQueueState decQueueState;
209     ExitOnError( (*queueItf)->GetState(queueItf, &decQueueState) );
210 
211     fprintf(stderr, "\DecBufferQueueCallback now has pCntxt->pData=%p queue: "
212             "count=%u playIndex=%u\n",
213             pCntxt->pData, decQueueState.count, decQueueState.index);
214 #endif
215 
216 #if 0
217     /* Example: display duration in callback where we use the callback context for the SLPlayItf*/
218     SLmillisecond durationInMsec = SL_TIME_UNKNOWN;
219     SLresult result = (*pCntxt->playItf)->GetDuration(pCntxt->playItf, &durationInMsec);
220     ExitOnError(result);
221     if (durationInMsec == SL_TIME_UNKNOWN) {
222         fprintf(stdout, "Content duration is unknown (in dec callback)\n");
223     } else {
224         fprintf(stdout, "Content duration is %ums (in dec callback)\n",
225                 durationInMsec);
226     }
227 #endif
228 
229 #if 0
230     /* Example: display position in callback where we use the callback context for the SLPlayItf*/
231     SLmillisecond posMsec = SL_TIME_UNKNOWN;
232     SLresult result = (*pCntxt->playItf)->GetPosition(pCntxt->playItf, &posMsec);
233     ExitOnError(result);
234     if (posMsec == SL_TIME_UNKNOWN) {
235         fprintf(stdout, "Content position is unknown (in dec callback)\n");
236     } else {
237         fprintf(stdout, "Content position is %ums (in dec callback)\n",
238                 posMsec);
239     }
240 #endif
241 
242     /* Example: query of the decoded PCM format */
243     if (formatQueried) {
244         return;
245     }
246     SLresult res = (*pCntxt->metaItf)->GetValue(pCntxt->metaItf, sampleRateKeyIndex,
247             PCM_METADATA_VALUE_SIZE, pcmMetaData);  ExitOnError(res);
248     // Note: here we could verify the following:
249     //         pcmMetaData->encoding == SL_CHARACTERENCODING_BINARY
250     //         pcmMetaData->size == sizeof(SLuint32)
251     //       but the call was successful for the PCM format keys, so those conditions are implied
252     fprintf(stdout, "sample rate = %dHz, ", *((SLuint32*)pcmMetaData->data));
253     res = (*pCntxt->metaItf)->GetValue(pCntxt->metaItf, channelCountKeyIndex,
254             PCM_METADATA_VALUE_SIZE, pcmMetaData);  ExitOnError(res);
255     fprintf(stdout, " channel count = %d\n", *((SLuint32*)pcmMetaData->data));
256     formatQueried = true;
257 }
258 
259 //-----------------------------------------------------------------
260 
261 /* Decode an audio path by opening a file descriptor on that path  */
TestDecToBuffQueue(SLObjectItf sl,const char * path)262 void TestDecToBuffQueue( SLObjectItf sl, const char* path)
263 {
264     size_t len = strlen((const char *) path);
265     char* outputPath = (char*) malloc(len + 4 + 1); // save room to concatenate ".raw"
266     if (NULL == outputPath) {
267         ExitOnError(SL_RESULT_RESOURCE_ERROR);
268     }
269     memcpy(outputPath, path, len + 1);
270     strcat(outputPath, ".raw");
271     gFp = fopen(outputPath, "w");
272     if (NULL == gFp) {
273         ExitOnError(SL_RESULT_RESOURCE_ERROR);
274     }
275 
276     SLresult  result;
277     SLEngineItf EngineItf;
278 
279     /* Objects this application uses: one audio player */
280     SLObjectItf  player;
281 
282     /* Interfaces for the audio player */
283     SLAndroidSimpleBufferQueueItf decBuffQueueItf;
284     SLPrefetchStatusItf           prefetchItf;
285     SLPlayItf                     playItf;
286     SLMetadataExtractionItf       mdExtrItf;
287 
288     /* Source of audio data for the decoding */
289     SLDataSource      decSource;
290     SLDataLocator_URI decUri;
291     SLDataFormat_MIME decMime;
292 
293     /* Data sink for decoded audio */
294     SLDataSink                decDest;
295     SLDataLocator_AndroidSimpleBufferQueue decBuffQueue;
296     SLDataFormat_PCM          pcm;
297 
298     SLboolean required[NUM_EXPLICIT_INTERFACES_FOR_PLAYER];
299     SLInterfaceID iidArray[NUM_EXPLICIT_INTERFACES_FOR_PLAYER];
300 
301     /* Get the SL Engine Interface which is implicit */
302     result = (*sl)->GetInterface(sl, SL_IID_ENGINE, (void*)&EngineItf);
303     ExitOnError(result);
304 
305     /* Initialize arrays required[] and iidArray[] */
306     for (int i=0 ; i < NUM_EXPLICIT_INTERFACES_FOR_PLAYER ; i++) {
307         required[i] = SL_BOOLEAN_FALSE;
308         iidArray[i] = SL_IID_NULL;
309     }
310 
311     /* allocate memory to receive the PCM format metadata */
312     if (!pcmMetaData) {
313         pcmMetaData = (SLMetadataInfo*) malloc(PCM_METADATA_VALUE_SIZE);
314     }
315 
316     formatQueried = false;
317 
318     /* ------------------------------------------------------ */
319     /* Configuration of the player  */
320 
321     /* Request the AndroidSimpleBufferQueue interface */
322     required[0] = SL_BOOLEAN_TRUE;
323     iidArray[0] = SL_IID_ANDROIDSIMPLEBUFFERQUEUE;
324     /* Request the PrefetchStatus interface */
325     required[1] = SL_BOOLEAN_TRUE;
326     iidArray[1] = SL_IID_PREFETCHSTATUS;
327     /* Request the PrefetchStatus interface */
328     required[2] = SL_BOOLEAN_TRUE;
329     iidArray[2] = SL_IID_METADATAEXTRACTION;
330 
331     /* Setup the data source */
332     decUri.locatorType = SL_DATALOCATOR_URI;
333     decUri.URI = (SLchar*)path;
334     decMime.formatType = SL_DATAFORMAT_MIME;
335     /*     this is how ignored mime information is specified, according to OpenSL ES spec
336      *     in 9.1.6 SLDataFormat_MIME and 8.23 SLMetadataTraversalItf GetChildInfo */
337     decMime.mimeType      = (SLchar*)NULL;
338     decMime.containerType = SL_CONTAINERTYPE_UNSPECIFIED;
339     decSource.pLocator = (void *) &decUri;
340     decSource.pFormat  = (void *) &decMime;
341 
342     /* Setup the data sink */
343     decBuffQueue.locatorType = SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE;
344     decBuffQueue.numBuffers = NB_BUFFERS_IN_QUEUE;
345     /*    set up the format of the data in the buffer queue */
346     pcm.formatType = SL_DATAFORMAT_PCM;
347     // FIXME valid value required but currently ignored
348     pcm.numChannels = 1;
349     pcm.samplesPerSec = SL_SAMPLINGRATE_8;
350     pcm.bitsPerSample = SL_PCMSAMPLEFORMAT_FIXED_16;
351     pcm.containerSize = 16;
352     pcm.channelMask = SL_SPEAKER_FRONT_LEFT;
353     pcm.endianness = SL_BYTEORDER_LITTLEENDIAN;
354 
355     decDest.pLocator = (void *) &decBuffQueue;
356     decDest.pFormat = (void * ) &pcm;
357 
358     /* Create the audio player */
359     result = (*EngineItf)->CreateAudioPlayer(EngineItf, &player, &decSource, &decDest,
360             NUM_EXPLICIT_INTERFACES_FOR_PLAYER, iidArray, required);
361     ExitOnError(result);
362     fprintf(stdout, "Player created\n");
363 
364     /* Realize the player in synchronous mode. */
365     result = (*player)->Realize(player, SL_BOOLEAN_FALSE);
366     ExitOnError(result);
367     fprintf(stdout, "Player realized\n");
368 
369     /* Get the play interface which is implicit */
370     result = (*player)->GetInterface(player, SL_IID_PLAY, (void*)&playItf);
371     ExitOnError(result);
372 
373     /* Set up the player callback to get events during the decoding */
374     // FIXME currently ignored
375     result = (*playItf)->SetMarkerPosition(playItf, 2000);
376     ExitOnError(result);
377     result = (*playItf)->SetPositionUpdatePeriod(playItf, 500);
378     ExitOnError(result);
379     result = (*playItf)->SetCallbackEventsMask(playItf,
380             SL_PLAYEVENT_HEADATMARKER | SL_PLAYEVENT_HEADATNEWPOS | SL_PLAYEVENT_HEADATEND);
381     ExitOnError(result);
382     result = (*playItf)->RegisterCallback(playItf, DecProgressCallback, NULL);
383     ExitOnError(result);
384     fprintf(stdout, "Play callback registered\n");
385 
386     /* Get the buffer queue interface which was explicitly requested */
387     result = (*player)->GetInterface(player, SL_IID_ANDROIDSIMPLEBUFFERQUEUE,
388             (void*)&decBuffQueueItf);
389     ExitOnError(result);
390 
391     /* Get the prefetch status interface which was explicitly requested */
392     result = (*player)->GetInterface(player, SL_IID_PREFETCHSTATUS, (void*)&prefetchItf);
393     ExitOnError(result);
394 
395     /* Get the metadata extraction interface which was explicitly requested */
396     result = (*player)->GetInterface(player, SL_IID_METADATAEXTRACTION, (void*)&mdExtrItf);
397     ExitOnError(result);
398 
399     /* ------------------------------------------------------ */
400     /* Initialize the callback and its context for the decoding buffer queue */
401     CallbackCntxt cntxt;
402     cntxt.playItf = playItf;
403     cntxt.metaItf = mdExtrItf;
404     cntxt.pDataBase = (int8_t*)&pcmData;
405     cntxt.pData = cntxt.pDataBase;
406     cntxt.size = sizeof(pcmData);
407     result = (*decBuffQueueItf)->RegisterCallback(decBuffQueueItf, DecPlayCallback, &cntxt);
408     ExitOnError(result);
409 
410     /* Enqueue buffers to map the region of memory allocated to store the decoded data */
411     fprintf(stdout,"Enqueueing buffer ");
412     for(int i = 0 ; i < NB_BUFFERS_IN_QUEUE ; i++) {
413         fprintf(stdout,"%d ", i);
414         result = (*decBuffQueueItf)->Enqueue(decBuffQueueItf, cntxt.pData, BUFFER_SIZE_IN_BYTES);
415         ExitOnError(result);
416         cntxt.pData += BUFFER_SIZE_IN_BYTES;
417     }
418     fprintf(stdout,"\n");
419     cntxt.pData = cntxt.pDataBase;
420 
421     /* ------------------------------------------------------ */
422     /* Initialize the callback for prefetch errors, if we can't open the resource to decode */
423     result = (*prefetchItf)->RegisterCallback(prefetchItf, PrefetchEventCallback, &prefetchItf);
424     ExitOnError(result);
425     result = (*prefetchItf)->SetCallbackEventsMask(prefetchItf, PREFETCHEVENT_ERROR_CANDIDATE);
426     ExitOnError(result);
427 
428     /* ------------------------------------------------------ */
429     /* Prefetch the data so we can get information about the format before starting to decode */
430     /*     1/ cause the player to prefetch the data */
431     result = (*playItf)->SetPlayState( playItf, SL_PLAYSTATE_PAUSED );
432     ExitOnError(result);
433     /*     2/ block until data has been prefetched */
434     SLuint32 prefetchStatus = SL_PREFETCHSTATUS_UNDERFLOW;
435     SLuint32 timeOutIndex = 50; // time out prefetching after 5s
436     while ((prefetchStatus != SL_PREFETCHSTATUS_SUFFICIENTDATA) && (timeOutIndex > 0) &&
437             !prefetchError) {
438         usleep(10 * 1000);
439         (*prefetchItf)->GetPrefetchStatus(prefetchItf, &prefetchStatus);
440         timeOutIndex--;
441     }
442     if (timeOutIndex == 0 || prefetchError) {
443         fprintf(stderr, "Failure to prefetch data in time, exiting\n");
444         ExitOnError(SL_RESULT_CONTENT_NOT_FOUND);
445     }
446 
447     /* ------------------------------------------------------ */
448     /* Display duration */
449     SLmillisecond durationInMsec = SL_TIME_UNKNOWN;
450     result = (*playItf)->GetDuration(playItf, &durationInMsec);
451     ExitOnError(result);
452     if (durationInMsec == SL_TIME_UNKNOWN) {
453         fprintf(stdout, "Content duration is unknown\n");
454     } else {
455         fprintf(stdout, "Content duration is %ums\n", durationInMsec);
456     }
457 
458     /* ------------------------------------------------------ */
459     /* Display the metadata obtained from the decoder */
460     //   This is for test / demonstration purposes only where we discover the key and value sizes
461     //   of a PCM decoder. An application that would want to directly get access to those values
462     //   can make assumptions about the size of the keys and their matching values (all SLuint32)
463     SLuint32 itemCount;
464     result = (*mdExtrItf)->GetItemCount(mdExtrItf, &itemCount);
465     SLuint32 i, keySize, valueSize;
466     SLMetadataInfo *keyInfo, *value;
467     for(i=0 ; i<itemCount ; i++) {
468         keyInfo = NULL; keySize = 0;
469         value = NULL;   valueSize = 0;
470         result = (*mdExtrItf)->GetKeySize(mdExtrItf, i, &keySize);
471         ExitOnError(result);
472         result = (*mdExtrItf)->GetValueSize(mdExtrItf, i, &valueSize);
473         ExitOnError(result);
474         keyInfo = (SLMetadataInfo*) malloc(keySize);
475         if (NULL != keyInfo) {
476             result = (*mdExtrItf)->GetKey(mdExtrItf, i, keySize, keyInfo);
477             ExitOnError(result);
478             fprintf(stdout, "key[%d] size=%d, name=%s \tvalue size=%d \n",
479                     i, keyInfo->size, keyInfo->data, valueSize);
480             /* find out the key index of the metadata we're interested in */
481             if (!strcmp((char*)keyInfo->data, ANDROID_KEY_PCMFORMAT_NUMCHANNELS)) {
482                 channelCountKeyIndex = i;
483             } else if (!strcmp((char*)keyInfo->data, ANDROID_KEY_PCMFORMAT_SAMPLERATE)) {
484                 sampleRateKeyIndex = i;
485             }
486             free(keyInfo);
487         }
488     }
489     if (channelCountKeyIndex != -1) {
490         fprintf(stdout, "Key %s is at index %d\n",
491                 ANDROID_KEY_PCMFORMAT_NUMCHANNELS, channelCountKeyIndex);
492     } else {
493         fprintf(stderr, "Unable to find key %s\n", ANDROID_KEY_PCMFORMAT_NUMCHANNELS);
494     }
495     if (sampleRateKeyIndex != -1) {
496         fprintf(stdout, "Key %s is at index %d\n",
497                 ANDROID_KEY_PCMFORMAT_SAMPLERATE, sampleRateKeyIndex);
498     } else {
499         fprintf(stderr, "Unable to find key %s\n", ANDROID_KEY_PCMFORMAT_SAMPLERATE);
500     }
501 
502     /* ------------------------------------------------------ */
503     /* Start decoding */
504     result = (*playItf)->SetPlayState(playItf, SL_PLAYSTATE_PLAYING);
505     ExitOnError(result);
506     fprintf(stdout, "Starting to decode\n");
507 
508     /* Decode until the end of the stream is reached */
509     {
510         android::Mutex::Autolock autoLock(eosLock);
511         while (!eos) {
512             eosCondition.wait(eosLock);
513         }
514     }
515     fprintf(stdout, "EOS signaled\n");
516 
517     /* ------------------------------------------------------ */
518     /* End of decoding */
519 
520     /* Stop decoding */
521     result = (*playItf)->SetPlayState(playItf, SL_PLAYSTATE_STOPPED);
522     ExitOnError(result);
523     fprintf(stdout, "Stopped decoding\n");
524 
525     /* Destroy the AudioPlayer object */
526     (*player)->Destroy(player);
527 
528     fclose(gFp);
529 
530     free(pcmMetaData);
531     pcmMetaData = NULL;
532 }
533 
534 //-----------------------------------------------------------------
main(int argc,char * const argv[])535 int main(int argc, char* const argv[])
536 {
537     SLresult    result;
538     SLObjectItf sl;
539 
540     fprintf(stdout, "OpenSL ES test %s: exercises SLPlayItf and SLAndroidSimpleBufferQueueItf ",
541             argv[0]);
542     fprintf(stdout, "on an AudioPlayer object to decode a URI to PCM\n");
543 
544     if (argc != 2) {
545         fprintf(stdout, "Usage: \t%s source_file\n", argv[0]);
546         fprintf(stdout, "Example: \"%s /sdcard/myFile.mp3\n", argv[0]);
547         exit(EXIT_FAILURE);
548     }
549 
550     SLEngineOption EngineOption[] = {
551             {(SLuint32) SL_ENGINEOPTION_THREADSAFE, (SLuint32) SL_BOOLEAN_TRUE}
552     };
553 
554     result = slCreateEngine( &sl, 1, EngineOption, 0, NULL, NULL);
555     ExitOnError(result);
556 
557     /* Realizing the SL Engine in synchronous mode. */
558     result = (*sl)->Realize(sl, SL_BOOLEAN_FALSE);
559     ExitOnError(result);
560 
561     TestDecToBuffQueue(sl, argv[1]);
562 
563     /* Shutdown OpenSL ES */
564     (*sl)->Destroy(sl);
565 
566     return EXIT_SUCCESS;
567 }
568