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