1688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi/* 2688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi * Copyright (C) 2011 The Android Open Source Project 3688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi * 4688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi * Licensed under the Apache License, Version 2.0 (the "License"); 5688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi * you may not use this file except in compliance with the License. 6688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi * You may obtain a copy of the License at 7688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi * 8688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi * http://www.apache.org/licenses/LICENSE-2.0 9688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi * 10688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi * Unless required by applicable law or agreed to in writing, software 11688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi * distributed under the License is distributed on an "AS IS" BASIS, 12688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi * See the License for the specific language governing permissions and 14688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi * limitations under the License. 15688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi */ 16688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi 17688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi/* AAC ADTS Decode Test 18688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi 19688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel TriviFirst run the program from shell: 20688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi # slesTestDecodeAac /sdcard/myFile.adts 21688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi 2233af4f47406b64af73e9e42e209c36320ea55410Glenn KastenExpected output: 2333af4f47406b64af73e9e42e209c36320ea55410Glenn Kasten OpenSL ES test slesTestDecodeAac: decodes a file containing AAC ADTS data 2433af4f47406b64af73e9e42e209c36320ea55410Glenn Kasten Player created 2533af4f47406b64af73e9e42e209c36320ea55410Glenn Kasten Player realized 2633af4f47406b64af73e9e42e209c36320ea55410Glenn Kasten Enqueueing initial empty buffers to receive decoded PCM data 0 1 2733af4f47406b64af73e9e42e209c36320ea55410Glenn Kasten Enqueueing initial full buffers of encoded ADTS data 0 1 2833af4f47406b64af73e9e42e209c36320ea55410Glenn Kasten Starting to decode 2933af4f47406b64af73e9e42e209c36320ea55410Glenn Kasten Frame counters: encoded=4579 decoded=4579 3033af4f47406b64af73e9e42e209c36320ea55410Glenn Kasten 31688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel TriviThese use adb on host to retrieve the decoded file: 32688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi % adb pull /sdcard/myFile.adts.raw myFile.raw 33688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi 34688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel TriviHow to examine the output with Audacity: 35688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi Project / Import raw data 36688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi Select myFile.raw file, then click Open button 37688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi Choose these options: 38688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi Signed 16-bit PCM 39688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi Little-endian 40688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi 1 Channel (Mono) / 2 Channels (Stereo) based on the PCM information obtained when decoding 41688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi Sample rate based on the PCM information obtained when decoding 42688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi Click Import button 43688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi 44688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi*/ 45688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi 46688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi#define QUERY_METADATA 47688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi 48e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kasten#include <assert.h> 49688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi#include <stdlib.h> 50688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi#include <stdio.h> 51688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi#include <string.h> 52688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi#include <unistd.h> 53688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi#include <sys/time.h> 54688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi#include <fcntl.h> 55688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi#include <pthread.h> 56688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi#include <sys/mman.h> 57688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi#include <sys/stat.h> 58688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi#include <unistd.h> 59e5cba3cbd006f0082af290cb34af8551c2710a03Glenn Kasten#include <cpustats/CentralTendencyStatistics.h> 60688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi 61688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi#include <SLES/OpenSLES.h> 62688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi#include <SLES/OpenSLES_Android.h> 63688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi 64688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi/* Explicitly requesting SL_IID_ANDROIDBUFFERQUEUE and SL_IID_ANDROIDSIMPLEBUFFERQUEUE 65688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi * on the AudioPlayer object for decoding, and 66688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi * SL_IID_METADATAEXTRACTION for retrieving the format of the decoded audio. 67688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi */ 68e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kasten#define NUM_EXPLICIT_INTERFACES_FOR_PLAYER 4 69688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi 70688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi/* Number of decoded samples produced by one AAC frame; defined by the standard */ 71688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi#define SAMPLES_PER_AAC_FRAME 1024 72688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi/* Size of the encoded AAC ADTS buffer queue */ 73688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi#define NB_BUFFERS_IN_ADTS_QUEUE 2 // 2 to 4 is typical 74688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi 75688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi/* Size of the decoded PCM buffer queue */ 76688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi#define NB_BUFFERS_IN_PCM_QUEUE 2 // 2 to 4 is typical 77688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi/* Size of each PCM buffer in the queue */ 78688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi#define BUFFER_SIZE_IN_BYTES (2*sizeof(short)*SAMPLES_PER_AAC_FRAME) 79688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi 80688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi/* Local storage for decoded PCM audio data */ 81688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Triviint8_t pcmData[NB_BUFFERS_IN_PCM_QUEUE * BUFFER_SIZE_IN_BYTES]; 82688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi 83688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi/* destination for decoded data */ 84688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivistatic FILE* outputFp; 85688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi 86688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi#ifdef QUERY_METADATA 87688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi/* metadata key index for the PCM format information we want to retrieve */ 88688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivistatic int channelCountKeyIndex = -1; 89688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivistatic int sampleRateKeyIndex = -1; 9033af4f47406b64af73e9e42e209c36320ea55410Glenn Kastenstatic int bitsPerSampleKeyIndex = -1; 9133af4f47406b64af73e9e42e209c36320ea55410Glenn Kastenstatic int containerSizeKeyIndex = -1; 9233af4f47406b64af73e9e42e209c36320ea55410Glenn Kastenstatic int channelMaskKeyIndex = -1; 9333af4f47406b64af73e9e42e209c36320ea55410Glenn Kastenstatic int endiannessKeyIndex = -1; 94688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi/* size of the struct to retrieve the PCM format metadata values: the values we're interested in 95688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi * are SLuint32, but it is saved in the data field of a SLMetadataInfo, hence the larger size. 96688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi * Note that this size is queried and displayed at l.XXX for demonstration/test purposes. 97688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi * */ 98688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi#define PCM_METADATA_VALUE_SIZE 32 99688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi/* used to query metadata values */ 100688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivistatic SLMetadataInfo *pcmMetaData = NULL; 101688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi/* we only want to query / display the PCM format once */ 102688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivistatic bool formatQueried = false; 103688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi#endif 104688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi 105688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi/* to signal to the test app that the end of the encoded ADTS stream has been reached */ 106688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivibool eos = false; 107688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivibool endOfEncodedStream = false; 108688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi 109688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivivoid *ptr; 110688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Triviunsigned char *frame; 111688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivisize_t filelen; 112688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivisize_t encodedFrames = 0; 113688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivisize_t encodedSamples = 0; 114688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivisize_t decodedFrames = 0; 115688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivisize_t decodedSamples = 0; 116e5cba3cbd006f0082af290cb34af8551c2710a03Glenn Kastensize_t totalEncodeCompletions = 0; // number of Enqueue completions received 117e5cba3cbd006f0082af290cb34af8551c2710a03Glenn KastenCentralTendencyStatistics frameStats; 118e5cba3cbd006f0082af290cb34af8551c2710a03Glenn Kastensize_t pauseFrame = 0; // pause after this many decoded frames, zero means don't pause 119e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn KastenSLboolean createRaw = SL_BOOLEAN_TRUE; // whether to create a .raw file containing PCM data 120688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi 1215760ef34bd7f50060fd8fbda10e359f8a830bfbcJean-Michel Trivi/* constant to identify a buffer context which is the end of the stream to decode */ 1225760ef34bd7f50060fd8fbda10e359f8a830bfbcJean-Michel Trivistatic const int kEosBufferCntxt = 1980; // a magic value we can compare against 1235760ef34bd7f50060fd8fbda10e359f8a830bfbcJean-Michel Trivi 124688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi/* protects shared variables */ 125688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivipthread_mutex_t eosLock = PTHREAD_MUTEX_INITIALIZER; 126688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivipthread_cond_t eosCondition = PTHREAD_COND_INITIALIZER; 127688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi 128e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kasten// These are extensions to OpenMAX AL 1.0.1 values 129e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kasten 130e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kasten#define PREFETCHSTATUS_UNKNOWN ((SLuint32) 0) 131e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kasten#define PREFETCHSTATUS_ERROR ((SLuint32) (-1)) 132e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kasten 133e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kasten// Mutex and condition shared with main program to protect prefetch_status 134e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kasten 135e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kastenstatic pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; 136e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kastenstatic pthread_cond_t cond = PTHREAD_COND_INITIALIZER; 137e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn KastenSLuint32 prefetch_status = PREFETCHSTATUS_UNKNOWN; 138e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kasten 139e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kasten/* used to detect errors likely to have occured when the OpenSL ES framework fails to open 140e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kasten * a resource, for instance because a file URI is invalid, or an HTTP server doesn't respond. 141e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kasten */ 142e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kasten#define PREFETCHEVENT_ERROR_CANDIDATE \ 143e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kasten (SL_PREFETCHEVENT_STATUSCHANGE | SL_PREFETCHEVENT_FILLLEVELCHANGE) 144e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kasten 145688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi//----------------------------------------------------------------- 146688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi/* Exits the application if an error is encountered */ 147688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi#define ExitOnError(x) ExitOnErrorFunc(x,__LINE__) 148688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi 149688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivivoid ExitOnErrorFunc( SLresult result , int line) 150688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi{ 151688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi if (SL_RESULT_SUCCESS != result) { 152688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi fprintf(stderr, "Error code %u encountered at line %d, exiting\n", result, line); 153688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi exit(EXIT_FAILURE); 154688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi } 155688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi} 156688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi 157688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi//----------------------------------------------------------------- 158e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kasten/* Callback for "prefetch" events, here used to detect audio resource opening errors */ 159e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kastenvoid PrefetchEventCallback(SLPrefetchStatusItf caller, void *pContext, SLuint32 event) 160e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kasten{ 161e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kasten // pContext is unused here, so we pass NULL 162e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kasten assert(pContext == NULL); 163e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kasten SLpermille level = 0; 164e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kasten SLresult result; 165e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kasten result = (*caller)->GetFillLevel(caller, &level); 166e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kasten ExitOnError(result); 167e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kasten SLuint32 status; 168e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kasten result = (*caller)->GetPrefetchStatus(caller, &status); 169e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kasten ExitOnError(result); 170e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kasten printf("prefetch level=%d status=0x%x event=%d\n", level, status, event); 171e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kasten SLuint32 new_prefetch_status; 172e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kasten if ((PREFETCHEVENT_ERROR_CANDIDATE == (event & PREFETCHEVENT_ERROR_CANDIDATE)) 173e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kasten && (level == 0) && (status == SL_PREFETCHSTATUS_UNDERFLOW)) { 174e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kasten printf("PrefetchEventCallback: Error while prefetching data, exiting\n"); 175e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kasten new_prefetch_status = PREFETCHSTATUS_ERROR; 176e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kasten } else if (event == SL_PREFETCHEVENT_STATUSCHANGE) { 177e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kasten new_prefetch_status = status; 178e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kasten } else { 179e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kasten return; 180e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kasten } 181e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kasten int ok; 182e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kasten ok = pthread_mutex_lock(&mutex); 183e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kasten assert(ok == 0); 184e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kasten prefetch_status = new_prefetch_status; 185e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kasten ok = pthread_cond_signal(&cond); 186e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kasten assert(ok == 0); 187e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kasten ok = pthread_mutex_unlock(&mutex); 188e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kasten assert(ok == 0); 189e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kasten} 190e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kasten 191e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kasten//----------------------------------------------------------------- 192688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi/* Structure for passing information to callback function */ 193688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivitypedef struct CallbackCntxt_ { 194688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi#ifdef QUERY_METADATA 195688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi SLMetadataExtractionItf metaItf; 196688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi#endif 19733af4f47406b64af73e9e42e209c36320ea55410Glenn Kasten SLPlayItf playItf; 198688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi SLint8* pDataBase; // Base address of local audio data storage 199688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi SLint8* pData; // Current address of local audio data storage 200688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi} CallbackCntxt; 201688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi 202e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kasten// used to notify when SL_PLAYEVENT_HEADATEND event is received 203e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kastenstatic pthread_mutex_t head_mutex = PTHREAD_MUTEX_INITIALIZER; 204e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kastenstatic pthread_cond_t head_cond = PTHREAD_COND_INITIALIZER; 205e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kastenstatic SLboolean head_atend = SL_BOOLEAN_FALSE; 206e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kasten 207688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi//----------------------------------------------------------------- 208113a9f14ea680a441540436b342f5008605aba27Jean-Michel Trivi/* Callback for SLPlayItf through which we receive the SL_PLAYEVENT_HEADATEND event */ 209113a9f14ea680a441540436b342f5008605aba27Jean-Michel Trivivoid PlayCallback(SLPlayItf caller, void *pContext, SLuint32 event) { 210e5cba3cbd006f0082af290cb34af8551c2710a03Glenn Kasten SLmillisecond position; 211e5cba3cbd006f0082af290cb34af8551c2710a03Glenn Kasten SLresult res = (*caller)->GetPosition(caller, &position); 212e5cba3cbd006f0082af290cb34af8551c2710a03Glenn Kasten ExitOnError(res); 213e5cba3cbd006f0082af290cb34af8551c2710a03Glenn Kasten if (event & SL_PLAYEVENT_HEADATMARKER) { 214e5cba3cbd006f0082af290cb34af8551c2710a03Glenn Kasten printf("SL_PLAYEVENT_HEADATMARKER position=%u ms\n", position); 215e5cba3cbd006f0082af290cb34af8551c2710a03Glenn Kasten } 216e5cba3cbd006f0082af290cb34af8551c2710a03Glenn Kasten if (event & SL_PLAYEVENT_HEADATNEWPOS) { 217e5cba3cbd006f0082af290cb34af8551c2710a03Glenn Kasten printf("SL_PLAYEVENT_HEADATNEWPOS position=%u ms\n", position); 218e5cba3cbd006f0082af290cb34af8551c2710a03Glenn Kasten } 219113a9f14ea680a441540436b342f5008605aba27Jean-Michel Trivi if (event & SL_PLAYEVENT_HEADATEND) { 220e5cba3cbd006f0082af290cb34af8551c2710a03Glenn Kasten printf("SL_PLAYEVENT_HEADATEND position=%u ms, all decoded data has been received\n", 221e5cba3cbd006f0082af290cb34af8551c2710a03Glenn Kasten position); 222e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kasten pthread_mutex_lock(&head_mutex); 223e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kasten head_atend = SL_BOOLEAN_TRUE; 224e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kasten pthread_cond_signal(&head_cond); 225e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kasten pthread_mutex_unlock(&head_mutex); 226113a9f14ea680a441540436b342f5008605aba27Jean-Michel Trivi } 227113a9f14ea680a441540436b342f5008605aba27Jean-Michel Trivi} 228113a9f14ea680a441540436b342f5008605aba27Jean-Michel Trivi 229113a9f14ea680a441540436b342f5008605aba27Jean-Michel Trivi//----------------------------------------------------------------- 230688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi/* Callback for AndroidBufferQueueItf through which we supply ADTS buffers */ 231688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel TriviSLresult AndroidBufferQueueCallback( 232688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi SLAndroidBufferQueueItf caller, 233688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi void *pCallbackContext, /* input */ 234688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi void *pBufferContext, /* input */ 235688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi void *pBufferData, /* input */ 236688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi SLuint32 dataSize, /* input */ 237688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi SLuint32 dataUsed, /* input */ 238688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi const SLAndroidBufferItem *pItems,/* input */ 239688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi SLuint32 itemsLength /* input */) 240688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi{ 241688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi // mutex on all global variables 242688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi pthread_mutex_lock(&eosLock); 243688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi SLresult res; 244688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi 2455760ef34bd7f50060fd8fbda10e359f8a830bfbcJean-Michel Trivi // for demonstration purposes: 2465760ef34bd7f50060fd8fbda10e359f8a830bfbcJean-Michel Trivi // verify what type of information was enclosed in the processed buffer 2475760ef34bd7f50060fd8fbda10e359f8a830bfbcJean-Michel Trivi if (NULL != pBufferContext) { 248e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kasten if (&kEosBufferCntxt == pBufferContext) { 2495760ef34bd7f50060fd8fbda10e359f8a830bfbcJean-Michel Trivi fprintf(stdout, "EOS was processed\n"); 2505760ef34bd7f50060fd8fbda10e359f8a830bfbcJean-Michel Trivi } 2515760ef34bd7f50060fd8fbda10e359f8a830bfbcJean-Michel Trivi } 2525760ef34bd7f50060fd8fbda10e359f8a830bfbcJean-Michel Trivi 253e5cba3cbd006f0082af290cb34af8551c2710a03Glenn Kasten ++totalEncodeCompletions; 254688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi if (endOfEncodedStream) { 255688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi // we continue to receive acknowledgement after each buffer was processed 256e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kasten if (pBufferContext == (void *) &kEosBufferCntxt) { 257e5cba3cbd006f0082af290cb34af8551c2710a03Glenn Kasten printf("Received EOS completion after EOS\n"); 258e5cba3cbd006f0082af290cb34af8551c2710a03Glenn Kasten } else if (pBufferContext == NULL) { 259e5cba3cbd006f0082af290cb34af8551c2710a03Glenn Kasten printf("Received ADTS completion after EOS\n"); 260e5cba3cbd006f0082af290cb34af8551c2710a03Glenn Kasten } else { 261e5cba3cbd006f0082af290cb34af8551c2710a03Glenn Kasten fprintf(stderr, "Received acknowledgement after EOS with unexpected context %p\n", 262e5cba3cbd006f0082af290cb34af8551c2710a03Glenn Kasten pBufferContext); 263e5cba3cbd006f0082af290cb34af8551c2710a03Glenn Kasten } 264688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi } else if (filelen == 0) { 265688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi // signal EOS to the decoder rather than just starving it 266e5cba3cbd006f0082af290cb34af8551c2710a03Glenn Kasten printf("Enqueue EOS: encoded frames=%u, decoded frames=%u\n", encodedFrames, decodedFrames); 267e5cba3cbd006f0082af290cb34af8551c2710a03Glenn Kasten printf("You should now see %u ADTS completion%s followed by 1 EOS completion\n", 268e5cba3cbd006f0082af290cb34af8551c2710a03Glenn Kasten NB_BUFFERS_IN_ADTS_QUEUE - 1, NB_BUFFERS_IN_ADTS_QUEUE != 2 ? "s" : ""); 269688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi SLAndroidBufferItem msgEos; 270688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi msgEos.itemKey = SL_ANDROID_ITEMKEY_EOS; 271688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi msgEos.itemSize = 0; 272688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi // EOS message has no parameters, so the total size of the message is the size of the key 273688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi // plus the size of itemSize, both SLuint32 2745760ef34bd7f50060fd8fbda10e359f8a830bfbcJean-Michel Trivi res = (*caller)->Enqueue(caller, (void *)&kEosBufferCntxt /*pBufferContext*/, 275688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi NULL /*pData*/, 0 /*dataLength*/, 276688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi &msgEos /*pMsg*/, 277688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi sizeof(SLuint32)*2 /*msgLength*/); 278688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi ExitOnError(res); 279688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi endOfEncodedStream = true; 280688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi // verify that we are at start of an ADTS frame 281688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi } else if (!(filelen < 7 || frame[0] != 0xFF || (frame[1] & 0xF0) != 0xF0)) { 282e5cba3cbd006f0082af290cb34af8551c2710a03Glenn Kasten if (pBufferContext != NULL) { 283e5cba3cbd006f0082af290cb34af8551c2710a03Glenn Kasten fprintf(stderr, "Received acknowledgement before EOS with unexpected context %p\n", 284e5cba3cbd006f0082af290cb34af8551c2710a03Glenn Kasten pBufferContext); 285e5cba3cbd006f0082af290cb34af8551c2710a03Glenn Kasten } 286688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi unsigned framelen = ((frame[3] & 3) << 11) | (frame[4] << 3) | (frame[5] >> 5); 287688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi if (framelen <= filelen) { 288688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi // push more data to the queue 289688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi res = (*caller)->Enqueue(caller, NULL /*pBufferContext*/, 290688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi frame, framelen, NULL, 0); 291688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi ExitOnError(res); 292688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi frame += framelen; 293688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi filelen -= framelen; 294688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi ++encodedFrames; 295688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi encodedSamples += SAMPLES_PER_AAC_FRAME; 296e5cba3cbd006f0082af290cb34af8551c2710a03Glenn Kasten frameStats.sample(framelen); 297688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi } else { 298688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi fprintf(stderr, 299688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi "partial ADTS frame at EOF discarded; offset=%u, framelen=%u, filelen=%u\n", 300688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi frame - (unsigned char *) ptr, framelen, filelen); 301688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi frame += filelen; 302688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi filelen = 0; 303688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi } 304688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi } else { 305688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi fprintf(stderr, "corrupt ADTS frame encountered; offset=%u, filelen=%u\n", 306688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi frame - (unsigned char *) ptr, filelen); 307688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi frame += filelen; 308688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi filelen = 0; 309688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi } 310688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi pthread_mutex_unlock(&eosLock); 311688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi 312688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi return SL_RESULT_SUCCESS; 313688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi} 314688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi 315688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi//----------------------------------------------------------------- 316688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi/* Callback for decoding buffer queue events */ 317688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivivoid DecPlayCallback( 318688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi SLAndroidSimpleBufferQueueItf queueItf, 319688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi void *pContext) 320688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi{ 321688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi // mutex on all global variables 322688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi pthread_mutex_lock(&eosLock); 323688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi 324688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi CallbackCntxt *pCntxt = (CallbackCntxt*)pContext; 325688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi 326688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi /* Save the decoded data to output file */ 327e5cba3cbd006f0082af290cb34af8551c2710a03Glenn Kasten if (outputFp != NULL && fwrite(pCntxt->pData, 1, BUFFER_SIZE_IN_BYTES, outputFp) 328e5cba3cbd006f0082af290cb34af8551c2710a03Glenn Kasten < BUFFER_SIZE_IN_BYTES) { 329688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi fprintf(stderr, "Error writing to output file"); 330688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi } 331688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi 332688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi /* Re-enqueue the now empty buffer */ 333688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi SLresult res; 334688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi res = (*queueItf)->Enqueue(queueItf, pCntxt->pData, BUFFER_SIZE_IN_BYTES); 335688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi ExitOnError(res); 336688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi 337688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi /* Increase data pointer by buffer size, with circular wraparound */ 338688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi pCntxt->pData += BUFFER_SIZE_IN_BYTES; 339688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi if (pCntxt->pData >= pCntxt->pDataBase + (NB_BUFFERS_IN_PCM_QUEUE * BUFFER_SIZE_IN_BYTES)) { 340688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi pCntxt->pData = pCntxt->pDataBase; 341688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi } 342688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi 343688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi // Note: adding a sleep here or any sync point is a way to slow down the decoding, or 344688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi // synchronize it with some other event, as the OpenSL ES framework will block until the 345688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi // buffer queue callback return to proceed with the decoding. 346688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi 347688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi#ifdef QUERY_METADATA 348688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi /* Example: query of the decoded PCM format */ 349688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi if (!formatQueried) { 350688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi /* memory to receive the PCM format metadata */ 351688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi union { 352688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi SLMetadataInfo pcmMetaData; 353688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi char withData[PCM_METADATA_VALUE_SIZE]; 354688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi } u; 355688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi res = (*pCntxt->metaItf)->GetValue(pCntxt->metaItf, sampleRateKeyIndex, 356688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi PCM_METADATA_VALUE_SIZE, &u.pcmMetaData); ExitOnError(res); 357688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi // Note: here we could verify the following: 358688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi // u.pcmMetaData->encoding == SL_CHARACTERENCODING_BINARY 359688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi // u.pcmMetaData->size == sizeof(SLuint32) 360688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi // but the call was successful for the PCM format keys, so those conditions are implied 36133af4f47406b64af73e9e42e209c36320ea55410Glenn Kasten printf("sample rate = %d\n", *((SLuint32*)u.pcmMetaData.data)); 362688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi res = (*pCntxt->metaItf)->GetValue(pCntxt->metaItf, channelCountKeyIndex, 363688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi PCM_METADATA_VALUE_SIZE, &u.pcmMetaData); ExitOnError(res); 36433af4f47406b64af73e9e42e209c36320ea55410Glenn Kasten printf("channel count = %d\n", *((SLuint32*)u.pcmMetaData.data)); 36533af4f47406b64af73e9e42e209c36320ea55410Glenn Kasten res = (*pCntxt->metaItf)->GetValue(pCntxt->metaItf, bitsPerSampleKeyIndex, 36633af4f47406b64af73e9e42e209c36320ea55410Glenn Kasten PCM_METADATA_VALUE_SIZE, &u.pcmMetaData); ExitOnError(res); 36733af4f47406b64af73e9e42e209c36320ea55410Glenn Kasten printf("bits per sample = %d bits\n", *((SLuint32*)u.pcmMetaData.data)); 36833af4f47406b64af73e9e42e209c36320ea55410Glenn Kasten res = (*pCntxt->metaItf)->GetValue(pCntxt->metaItf, containerSizeKeyIndex, 36933af4f47406b64af73e9e42e209c36320ea55410Glenn Kasten PCM_METADATA_VALUE_SIZE, &u.pcmMetaData); ExitOnError(res); 37033af4f47406b64af73e9e42e209c36320ea55410Glenn Kasten printf("container size = %d bits\n", *((SLuint32*)u.pcmMetaData.data)); 37133af4f47406b64af73e9e42e209c36320ea55410Glenn Kasten res = (*pCntxt->metaItf)->GetValue(pCntxt->metaItf, channelMaskKeyIndex, 37233af4f47406b64af73e9e42e209c36320ea55410Glenn Kasten PCM_METADATA_VALUE_SIZE, &u.pcmMetaData); ExitOnError(res); 37333af4f47406b64af73e9e42e209c36320ea55410Glenn Kasten printf("channel mask = 0x%X (0x3=front left | front right, 0x4=front center)\n", 37433af4f47406b64af73e9e42e209c36320ea55410Glenn Kasten *((SLuint32*)u.pcmMetaData.data)); 37533af4f47406b64af73e9e42e209c36320ea55410Glenn Kasten res = (*pCntxt->metaItf)->GetValue(pCntxt->metaItf, endiannessKeyIndex, 37633af4f47406b64af73e9e42e209c36320ea55410Glenn Kasten PCM_METADATA_VALUE_SIZE, &u.pcmMetaData); ExitOnError(res); 37733af4f47406b64af73e9e42e209c36320ea55410Glenn Kasten printf("endianness = %d (1=big, 2=little)\n", *((SLuint32*)u.pcmMetaData.data)); 378688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi formatQueried = true; 379688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi } 380688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi#endif 381688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi 382688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi ++decodedFrames; 383688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi decodedSamples += SAMPLES_PER_AAC_FRAME; 384688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi 38533af4f47406b64af73e9e42e209c36320ea55410Glenn Kasten /* Periodically ask for position and duration */ 38633af4f47406b64af73e9e42e209c36320ea55410Glenn Kasten if ((decodedFrames % 1000 == 0) || endOfEncodedStream) { 38733af4f47406b64af73e9e42e209c36320ea55410Glenn Kasten SLmillisecond position; 38833af4f47406b64af73e9e42e209c36320ea55410Glenn Kasten res = (*pCntxt->playItf)->GetPosition(pCntxt->playItf, &position); 38933af4f47406b64af73e9e42e209c36320ea55410Glenn Kasten ExitOnError(res); 39033af4f47406b64af73e9e42e209c36320ea55410Glenn Kasten SLmillisecond duration; 39133af4f47406b64af73e9e42e209c36320ea55410Glenn Kasten res = (*pCntxt->playItf)->GetDuration(pCntxt->playItf, &duration); 39233af4f47406b64af73e9e42e209c36320ea55410Glenn Kasten ExitOnError(res); 39333af4f47406b64af73e9e42e209c36320ea55410Glenn Kasten if (duration == SL_TIME_UNKNOWN) { 394e5cba3cbd006f0082af290cb34af8551c2710a03Glenn Kasten printf("After %u encoded %u decoded frames: position is %u ms, duration is " 395e5cba3cbd006f0082af290cb34af8551c2710a03Glenn Kasten "unknown as expected\n", 396e5cba3cbd006f0082af290cb34af8551c2710a03Glenn Kasten encodedFrames, decodedFrames, position); 39733af4f47406b64af73e9e42e209c36320ea55410Glenn Kasten } else { 398e5cba3cbd006f0082af290cb34af8551c2710a03Glenn Kasten printf("After %u encoded %u decoded frames: position is %u ms, duration is " 399e5cba3cbd006f0082af290cb34af8551c2710a03Glenn Kasten "surprisingly %u ms\n", 400e5cba3cbd006f0082af290cb34af8551c2710a03Glenn Kasten encodedFrames, decodedFrames, position, duration); 40133af4f47406b64af73e9e42e209c36320ea55410Glenn Kasten } 40233af4f47406b64af73e9e42e209c36320ea55410Glenn Kasten } 40333af4f47406b64af73e9e42e209c36320ea55410Glenn Kasten 404688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi if (endOfEncodedStream && decodedSamples >= encodedSamples) { 405688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi eos = true; 406688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi pthread_cond_signal(&eosCondition); 407688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi } 408688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi pthread_mutex_unlock(&eosLock); 409688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi} 410688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi 411688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi//----------------------------------------------------------------- 412688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi 413688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi/* Decode an audio path by opening a file descriptor on that path */ 414688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivivoid TestDecToBuffQueue( SLObjectItf sl, const char *path, int fd) 415688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi{ 416688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi // check what kind of object it is 417688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi int ok; 418688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi struct stat statbuf; 419688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi ok = fstat(fd, &statbuf); 420688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi if (ok < 0) { 421688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi perror(path); 422688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi return; 423688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi } 424688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi 425688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi // verify that's it is a file 426688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi if (!S_ISREG(statbuf.st_mode)) { 427688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi fprintf(stderr, "%s: not an ordinary file\n", path); 428688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi return; 429688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi } 430688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi 431688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi // map file contents into memory to make it easier to access the ADTS frames directly 432688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi ptr = mmap(NULL, statbuf.st_size, PROT_READ, MAP_FILE | MAP_PRIVATE, fd, (off_t) 0); 433688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi if (ptr == MAP_FAILED) { 434688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi perror(path); 435688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi return; 436688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi } 437688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi frame = (unsigned char *) ptr; 438688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi filelen = statbuf.st_size; 439688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi 440688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi // create PCM .raw file 441e5cba3cbd006f0082af290cb34af8551c2710a03Glenn Kasten if (createRaw) { 442e5cba3cbd006f0082af290cb34af8551c2710a03Glenn Kasten size_t len = strlen((const char *) path); 443e5cba3cbd006f0082af290cb34af8551c2710a03Glenn Kasten char* outputPath = (char*) malloc(len + 4 + 1); // save room to concatenate ".raw" 444e5cba3cbd006f0082af290cb34af8551c2710a03Glenn Kasten if (NULL == outputPath) { 445e5cba3cbd006f0082af290cb34af8551c2710a03Glenn Kasten ExitOnError(SL_RESULT_RESOURCE_ERROR); 446e5cba3cbd006f0082af290cb34af8551c2710a03Glenn Kasten } 447e5cba3cbd006f0082af290cb34af8551c2710a03Glenn Kasten memcpy(outputPath, path, len + 1); 448e5cba3cbd006f0082af290cb34af8551c2710a03Glenn Kasten strcat(outputPath, ".raw"); 449e5cba3cbd006f0082af290cb34af8551c2710a03Glenn Kasten outputFp = fopen(outputPath, "w"); 450e5cba3cbd006f0082af290cb34af8551c2710a03Glenn Kasten if (NULL == outputFp) { 451e5cba3cbd006f0082af290cb34af8551c2710a03Glenn Kasten // issue an error message, but continue the decoding anyway 452e5cba3cbd006f0082af290cb34af8551c2710a03Glenn Kasten perror(outputPath); 453e5cba3cbd006f0082af290cb34af8551c2710a03Glenn Kasten } 454e5cba3cbd006f0082af290cb34af8551c2710a03Glenn Kasten } else { 455e5cba3cbd006f0082af290cb34af8551c2710a03Glenn Kasten outputFp = NULL; 456688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi } 457688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi 458688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi SLresult res; 459688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi SLEngineItf EngineItf; 460688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi 461688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi /* Objects this application uses: one audio player */ 462688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi SLObjectItf player; 463688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi 464688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi /* Interfaces for the audio player */ 465688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi SLPlayItf playItf; 466688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi#ifdef QUERY_METADATA 467688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi /* to retrieve the decoded PCM format */ 468688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi SLMetadataExtractionItf mdExtrItf; 469688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi#endif 470688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi /* to retrieve the PCM samples */ 471688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi SLAndroidSimpleBufferQueueItf decBuffQueueItf; 472688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi /* to queue the AAC data to decode */ 473688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi SLAndroidBufferQueueItf aacBuffQueueItf; 474e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kasten /* for prefetch status */ 475e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kasten SLPrefetchStatusItf prefetchItf; 476688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi 477688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi SLboolean required[NUM_EXPLICIT_INTERFACES_FOR_PLAYER]; 478688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi SLInterfaceID iidArray[NUM_EXPLICIT_INTERFACES_FOR_PLAYER]; 479688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi 480688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi /* Get the SL Engine Interface which is implicit */ 481688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi res = (*sl)->GetInterface(sl, SL_IID_ENGINE, (void*)&EngineItf); 482688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi ExitOnError(res); 483688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi 484688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi /* Initialize arrays required[] and iidArray[] */ 485688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi unsigned int i; 486688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi for (i=0 ; i < NUM_EXPLICIT_INTERFACES_FOR_PLAYER ; i++) { 487688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi required[i] = SL_BOOLEAN_FALSE; 488688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi iidArray[i] = SL_IID_NULL; 489688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi } 490688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi 491688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi /* ------------------------------------------------------ */ 492688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi /* Configuration of the player */ 493688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi 494688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi /* Request the AndroidSimpleBufferQueue interface */ 495688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi required[0] = SL_BOOLEAN_TRUE; 496688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi iidArray[0] = SL_IID_ANDROIDSIMPLEBUFFERQUEUE; 497688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi /* Request the AndroidBufferQueue interface */ 498688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi required[1] = SL_BOOLEAN_TRUE; 499c3b82a293ed06001ba6d50f111608160c6065ef2Glenn Kasten iidArray[1] = SL_IID_ANDROIDBUFFERQUEUESOURCE; 500e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kasten /* Request the PrefetchStatus interface */ 501e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kasten required[2] = SL_BOOLEAN_TRUE; 502e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kasten iidArray[2] = SL_IID_PREFETCHSTATUS; 503688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi#ifdef QUERY_METADATA 504688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi /* Request the MetadataExtraction interface */ 505e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kasten required[3] = SL_BOOLEAN_TRUE; 506e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kasten iidArray[3] = SL_IID_METADATAEXTRACTION; 507688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi#endif 508688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi 509688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi /* Setup the data source for queueing AAC buffers of ADTS data */ 510688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi SLDataLocator_AndroidBufferQueue loc_srcAbq = { 511688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi SL_DATALOCATOR_ANDROIDBUFFERQUEUE /*locatorType*/, 512688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi NB_BUFFERS_IN_ADTS_QUEUE /*numBuffers*/}; 513688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi SLDataFormat_MIME format_srcMime = { 514688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi SL_DATAFORMAT_MIME /*formatType*/, 515c3b82a293ed06001ba6d50f111608160c6065ef2Glenn Kasten SL_ANDROID_MIME_AACADTS /*mimeType*/, 516688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi SL_CONTAINERTYPE_RAW /*containerType*/}; 517688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi SLDataSource decSource = {&loc_srcAbq /*pLocator*/, &format_srcMime /*pFormat*/}; 518688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi 519688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi /* Setup the data sink, a buffer queue for buffers of PCM data */ 520688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi SLDataLocator_AndroidSimpleBufferQueue loc_destBq = { 521688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE/*locatorType*/, 522688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi NB_BUFFERS_IN_PCM_QUEUE /*numBuffers*/ }; 523688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi 524688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi /* declare we're decoding to PCM, the parameters after that need to be valid, 525688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi but are ignored, the decoded format will match the source */ 526688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi SLDataFormat_PCM format_destPcm = { /*formatType*/ SL_DATAFORMAT_PCM, /*numChannels*/ 1, 527688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi /*samplesPerSec*/ SL_SAMPLINGRATE_8, /*pcm.bitsPerSample*/ SL_PCMSAMPLEFORMAT_FIXED_16, 528688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi /*/containerSize*/ 16, /*channelMask*/ SL_SPEAKER_FRONT_LEFT, 529688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi /*endianness*/ SL_BYTEORDER_LITTLEENDIAN }; 530688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi SLDataSink decDest = {&loc_destBq /*pLocator*/, &format_destPcm /*pFormat*/}; 531688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi 532688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi /* Create the audio player */ 533688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi res = (*EngineItf)->CreateAudioPlayer(EngineItf, &player, &decSource, &decDest, 534688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi#ifdef QUERY_METADATA 535688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi NUM_EXPLICIT_INTERFACES_FOR_PLAYER, 536688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi#else 537688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi NUM_EXPLICIT_INTERFACES_FOR_PLAYER - 1, 538688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi#endif 539688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi iidArray, required); 540688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi ExitOnError(res); 541688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi printf("Player created\n"); 542688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi 543688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi /* Realize the player in synchronous mode. */ 544688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi res = (*player)->Realize(player, SL_BOOLEAN_FALSE); 545688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi ExitOnError(res); 546688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi printf("Player realized\n"); 547688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi 548688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi /* Get the play interface which is implicit */ 549688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi res = (*player)->GetInterface(player, SL_IID_PLAY, (void*)&playItf); 550688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi ExitOnError(res); 551688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi 552e5cba3cbd006f0082af290cb34af8551c2710a03Glenn Kasten /* Enable callback when position passes through a marker (SL_PLAYEVENT_HEADATMARKER) */ 553e5cba3cbd006f0082af290cb34af8551c2710a03Glenn Kasten res = (*playItf)->SetMarkerPosition(playItf, 5000); 554e5cba3cbd006f0082af290cb34af8551c2710a03Glenn Kasten ExitOnError(res); 555e5cba3cbd006f0082af290cb34af8551c2710a03Glenn Kasten 556e5cba3cbd006f0082af290cb34af8551c2710a03Glenn Kasten /* Enable callback for periodic position updates (SL_PLAYEVENT_HEADATNEWPOS) */ 557e5cba3cbd006f0082af290cb34af8551c2710a03Glenn Kasten res = (*playItf)->SetPositionUpdatePeriod(playItf, 3000); 558e5cba3cbd006f0082af290cb34af8551c2710a03Glenn Kasten ExitOnError(res); 559e5cba3cbd006f0082af290cb34af8551c2710a03Glenn Kasten 560e5cba3cbd006f0082af290cb34af8551c2710a03Glenn Kasten /* Use the play interface to set up a callback for the SL_PLAYEVENT_HEAD* events */ 561e5cba3cbd006f0082af290cb34af8551c2710a03Glenn Kasten res = (*playItf)->SetCallbackEventsMask(playItf, 562e5cba3cbd006f0082af290cb34af8551c2710a03Glenn Kasten SL_PLAYEVENT_HEADATMARKER | SL_PLAYEVENT_HEADATNEWPOS | SL_PLAYEVENT_HEADATEND); 563113a9f14ea680a441540436b342f5008605aba27Jean-Michel Trivi ExitOnError(res); 564113a9f14ea680a441540436b342f5008605aba27Jean-Michel Trivi res = (*playItf)->RegisterCallback(playItf, PlayCallback /*callback*/, NULL /*pContext*/); 565113a9f14ea680a441540436b342f5008605aba27Jean-Michel Trivi ExitOnError(res); 566113a9f14ea680a441540436b342f5008605aba27Jean-Michel Trivi 56733af4f47406b64af73e9e42e209c36320ea55410Glenn Kasten /* Get the position before prefetch; should be zero */ 56833af4f47406b64af73e9e42e209c36320ea55410Glenn Kasten SLmillisecond position; 56933af4f47406b64af73e9e42e209c36320ea55410Glenn Kasten res = (*playItf)->GetPosition(playItf, &position); 57033af4f47406b64af73e9e42e209c36320ea55410Glenn Kasten ExitOnError(res); 57133af4f47406b64af73e9e42e209c36320ea55410Glenn Kasten if (position == 0) { 57233af4f47406b64af73e9e42e209c36320ea55410Glenn Kasten printf("The position before prefetch is zero as expected\n"); 57333af4f47406b64af73e9e42e209c36320ea55410Glenn Kasten } else if (position == SL_TIME_UNKNOWN) { 57433af4f47406b64af73e9e42e209c36320ea55410Glenn Kasten printf("That's surprising the position before prefetch is unknown"); 57533af4f47406b64af73e9e42e209c36320ea55410Glenn Kasten } else { 57633af4f47406b64af73e9e42e209c36320ea55410Glenn Kasten printf("That's surprising the position before prefetch is %u ms\n", position); 57733af4f47406b64af73e9e42e209c36320ea55410Glenn Kasten } 57833af4f47406b64af73e9e42e209c36320ea55410Glenn Kasten 57933af4f47406b64af73e9e42e209c36320ea55410Glenn Kasten /* Get the duration before prefetch; should be unknown */ 58033af4f47406b64af73e9e42e209c36320ea55410Glenn Kasten SLmillisecond duration; 58133af4f47406b64af73e9e42e209c36320ea55410Glenn Kasten res = (*playItf)->GetDuration(playItf, &duration); 58233af4f47406b64af73e9e42e209c36320ea55410Glenn Kasten ExitOnError(res); 58333af4f47406b64af73e9e42e209c36320ea55410Glenn Kasten if (duration == SL_TIME_UNKNOWN) { 58433af4f47406b64af73e9e42e209c36320ea55410Glenn Kasten printf("The duration before prefetch is unknown as expected\n"); 58533af4f47406b64af73e9e42e209c36320ea55410Glenn Kasten } else { 58633af4f47406b64af73e9e42e209c36320ea55410Glenn Kasten printf("That's surprising the duration before prefetch is %u ms\n", duration); 58733af4f47406b64af73e9e42e209c36320ea55410Glenn Kasten } 58833af4f47406b64af73e9e42e209c36320ea55410Glenn Kasten 589688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi /* Get the buffer queue interface which was explicitly requested */ 590688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi res = (*player)->GetInterface(player, SL_IID_ANDROIDSIMPLEBUFFERQUEUE, (void*)&decBuffQueueItf); 591688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi ExitOnError(res); 592688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi 593688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi /* Get the Android buffer queue interface which was explicitly requested */ 594c3b82a293ed06001ba6d50f111608160c6065ef2Glenn Kasten res = (*player)->GetInterface(player, SL_IID_ANDROIDBUFFERQUEUESOURCE, (void*)&aacBuffQueueItf); 595688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi ExitOnError(res); 596688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi 597e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kasten /* Get the prefetch status interface which was explicitly requested */ 598e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kasten res = (*player)->GetInterface(player, SL_IID_PREFETCHSTATUS, (void*)&prefetchItf); 599e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kasten ExitOnError(res); 600e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kasten 601688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi#ifdef QUERY_METADATA 602688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi /* Get the metadata extraction interface which was explicitly requested */ 603688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi res = (*player)->GetInterface(player, SL_IID_METADATAEXTRACTION, (void*)&mdExtrItf); 604688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi ExitOnError(res); 605688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi#endif 606688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi 607688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi /* ------------------------------------------------------ */ 608688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi /* Initialize the callback and its context for the buffer queue of the decoded PCM */ 609688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi CallbackCntxt sinkCntxt; 61033af4f47406b64af73e9e42e209c36320ea55410Glenn Kasten sinkCntxt.playItf = playItf; 611688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi#ifdef QUERY_METADATA 612688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi sinkCntxt.metaItf = mdExtrItf; 613688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi#endif 614688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi sinkCntxt.pDataBase = (int8_t*)&pcmData; 615688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi sinkCntxt.pData = sinkCntxt.pDataBase; 616688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi res = (*decBuffQueueItf)->RegisterCallback(decBuffQueueItf, DecPlayCallback, &sinkCntxt); 617688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi ExitOnError(res); 618688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi 619688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi /* Enqueue buffers to map the region of memory allocated to store the decoded data */ 620688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi printf("Enqueueing initial empty buffers to receive decoded PCM data"); 621688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi for(i = 0 ; i < NB_BUFFERS_IN_PCM_QUEUE ; i++) { 622688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi printf(" %d", i); 623688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi res = (*decBuffQueueItf)->Enqueue(decBuffQueueItf, sinkCntxt.pData, BUFFER_SIZE_IN_BYTES); 624688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi ExitOnError(res); 625688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi sinkCntxt.pData += BUFFER_SIZE_IN_BYTES; 626688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi if (sinkCntxt.pData >= sinkCntxt.pDataBase + 627688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi (NB_BUFFERS_IN_PCM_QUEUE * BUFFER_SIZE_IN_BYTES)) { 628688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi sinkCntxt.pData = sinkCntxt.pDataBase; 629688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi } 630688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi } 631688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi printf("\n"); 632688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi 633e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kasten /* ------------------------------------------------------ */ 634e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kasten /* Initialize the callback for prefetch errors, if we can't open the resource to decode */ 635e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kasten res = (*prefetchItf)->RegisterCallback(prefetchItf, PrefetchEventCallback, NULL); 636e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kasten ExitOnError(res); 637e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kasten res = (*prefetchItf)->SetCallbackEventsMask(prefetchItf, PREFETCHEVENT_ERROR_CANDIDATE); 638e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kasten ExitOnError(res); 639e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kasten 640688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi /* Initialize the callback for the Android buffer queue of the encoded data */ 641688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi res = (*aacBuffQueueItf)->RegisterCallback(aacBuffQueueItf, AndroidBufferQueueCallback, NULL); 642688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi ExitOnError(res); 643688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi 644688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi /* Enqueue the content of our encoded data before starting to play, 645688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi we don't want to starve the player initially */ 646688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi printf("Enqueueing initial full buffers of encoded ADTS data"); 647688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi for (i=0 ; i < NB_BUFFERS_IN_ADTS_QUEUE ; i++) { 648e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kasten if (filelen < 7 || frame[0] != 0xFF || (frame[1] & 0xF0) != 0xF0) { 649e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kasten printf("\ncorrupt ADTS frame encountered; offset %zu bytes\n", 650e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kasten frame - (unsigned char *) ptr); 651e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kasten // Note that prefetch will detect this error soon when it gets a premature EOF 652688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi break; 653e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kasten } 654688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi unsigned framelen = ((frame[3] & 3) << 11) | (frame[4] << 3) | (frame[5] >> 5); 655e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kasten printf(" %d (%u bytes)", i, framelen); 656688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi res = (*aacBuffQueueItf)->Enqueue(aacBuffQueueItf, NULL /*pBufferContext*/, 657688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi frame, framelen, NULL, 0); 658688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi ExitOnError(res); 659688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi frame += framelen; 660688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi filelen -= framelen; 66133af4f47406b64af73e9e42e209c36320ea55410Glenn Kasten ++encodedFrames; 66233af4f47406b64af73e9e42e209c36320ea55410Glenn Kasten encodedSamples += SAMPLES_PER_AAC_FRAME; 663e5cba3cbd006f0082af290cb34af8551c2710a03Glenn Kasten frameStats.sample(framelen); 664688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi } 665688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi printf("\n"); 666688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi 667688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi#ifdef QUERY_METADATA 668688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi /* ------------------------------------------------------ */ 669e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kasten /* Get and display the metadata key names for the decoder */ 670688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi // This is for test / demonstration purposes only where we discover the key and value sizes 671688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi // of a PCM decoder. An application that would want to directly get access to those values 672e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kasten // can make assumptions about the size of the keys and their matching values (all SLuint32), 673e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kasten // but it should not make assumptions about the key indices as these are subject to change. 674e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kasten // Note that we don't get the metadata values yet; that happens in the first decode callback. 675688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi SLuint32 itemCount; 676688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi res = (*mdExtrItf)->GetItemCount(mdExtrItf, &itemCount); 677688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi ExitOnError(res); 678688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi printf("itemCount=%u\n", itemCount); 679688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi SLuint32 keySize, valueSize; 680688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi SLMetadataInfo *keyInfo, *value; 681688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi for(i=0 ; i<itemCount ; i++) { 682688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi keyInfo = NULL; keySize = 0; 683688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi value = NULL; valueSize = 0; 684688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi res = (*mdExtrItf)->GetKeySize(mdExtrItf, i, &keySize); 685688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi ExitOnError(res); 686688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi res = (*mdExtrItf)->GetValueSize(mdExtrItf, i, &valueSize); 687688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi ExitOnError(res); 688688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi keyInfo = (SLMetadataInfo*) malloc(keySize); 689688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi if (NULL != keyInfo) { 690688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi res = (*mdExtrItf)->GetKey(mdExtrItf, i, keySize, keyInfo); 691688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi ExitOnError(res); 692688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi printf("key[%d] size=%d, name=%s \tvalue size=%d encoding=0x%X langCountry=%s\n", 693688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi i, keyInfo->size, keyInfo->data, valueSize, keyInfo->encoding, 694688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi keyInfo->langCountry); 695688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi /* find out the key index of the metadata we're interested in */ 696688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi if (!strcmp((char*)keyInfo->data, ANDROID_KEY_PCMFORMAT_NUMCHANNELS)) { 697688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi channelCountKeyIndex = i; 6980f92f48017588949daf7d24a339423e149bb2555Glenn Kasten } else if (!strcmp((char*)keyInfo->data, ANDROID_KEY_PCMFORMAT_SAMPLERATE)) { 699688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi sampleRateKeyIndex = i; 70033af4f47406b64af73e9e42e209c36320ea55410Glenn Kasten } else if (!strcmp((char*)keyInfo->data, ANDROID_KEY_PCMFORMAT_BITSPERSAMPLE)) { 70133af4f47406b64af73e9e42e209c36320ea55410Glenn Kasten bitsPerSampleKeyIndex = i; 70233af4f47406b64af73e9e42e209c36320ea55410Glenn Kasten } else if (!strcmp((char*)keyInfo->data, ANDROID_KEY_PCMFORMAT_CONTAINERSIZE)) { 70333af4f47406b64af73e9e42e209c36320ea55410Glenn Kasten containerSizeKeyIndex = i; 70433af4f47406b64af73e9e42e209c36320ea55410Glenn Kasten } else if (!strcmp((char*)keyInfo->data, ANDROID_KEY_PCMFORMAT_CHANNELMASK)) { 70533af4f47406b64af73e9e42e209c36320ea55410Glenn Kasten channelMaskKeyIndex = i; 70633af4f47406b64af73e9e42e209c36320ea55410Glenn Kasten } else if (!strcmp((char*)keyInfo->data, ANDROID_KEY_PCMFORMAT_ENDIANNESS)) { 70733af4f47406b64af73e9e42e209c36320ea55410Glenn Kasten endiannessKeyIndex = i; 70833af4f47406b64af73e9e42e209c36320ea55410Glenn Kasten } else { 70933af4f47406b64af73e9e42e209c36320ea55410Glenn Kasten printf("Unknown key %s ignored\n", (char *)keyInfo->data); 710688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi } 711688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi free(keyInfo); 712688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi } 713688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi } 714688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi if (channelCountKeyIndex != -1) { 715688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi printf("Key %s is at index %d\n", 716688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi ANDROID_KEY_PCMFORMAT_NUMCHANNELS, channelCountKeyIndex); 717688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi } else { 718688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi fprintf(stderr, "Unable to find key %s\n", ANDROID_KEY_PCMFORMAT_NUMCHANNELS); 719688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi } 720688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi if (sampleRateKeyIndex != -1) { 721688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi printf("Key %s is at index %d\n", 7220f92f48017588949daf7d24a339423e149bb2555Glenn Kasten ANDROID_KEY_PCMFORMAT_SAMPLERATE, sampleRateKeyIndex); 723688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi } else { 7240f92f48017588949daf7d24a339423e149bb2555Glenn Kasten fprintf(stderr, "Unable to find key %s\n", ANDROID_KEY_PCMFORMAT_SAMPLERATE); 725688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi } 72633af4f47406b64af73e9e42e209c36320ea55410Glenn Kasten if (bitsPerSampleKeyIndex != -1) { 72733af4f47406b64af73e9e42e209c36320ea55410Glenn Kasten printf("Key %s is at index %d\n", 72833af4f47406b64af73e9e42e209c36320ea55410Glenn Kasten ANDROID_KEY_PCMFORMAT_BITSPERSAMPLE, bitsPerSampleKeyIndex); 72933af4f47406b64af73e9e42e209c36320ea55410Glenn Kasten } else { 73033af4f47406b64af73e9e42e209c36320ea55410Glenn Kasten fprintf(stderr, "Unable to find key %s\n", ANDROID_KEY_PCMFORMAT_BITSPERSAMPLE); 73133af4f47406b64af73e9e42e209c36320ea55410Glenn Kasten } 73233af4f47406b64af73e9e42e209c36320ea55410Glenn Kasten if (containerSizeKeyIndex != -1) { 73333af4f47406b64af73e9e42e209c36320ea55410Glenn Kasten printf("Key %s is at index %d\n", 73433af4f47406b64af73e9e42e209c36320ea55410Glenn Kasten ANDROID_KEY_PCMFORMAT_CONTAINERSIZE, containerSizeKeyIndex); 73533af4f47406b64af73e9e42e209c36320ea55410Glenn Kasten } else { 73633af4f47406b64af73e9e42e209c36320ea55410Glenn Kasten fprintf(stderr, "Unable to find key %s\n", ANDROID_KEY_PCMFORMAT_CONTAINERSIZE); 73733af4f47406b64af73e9e42e209c36320ea55410Glenn Kasten } 73833af4f47406b64af73e9e42e209c36320ea55410Glenn Kasten if (channelMaskKeyIndex != -1) { 73933af4f47406b64af73e9e42e209c36320ea55410Glenn Kasten printf("Key %s is at index %d\n", 74033af4f47406b64af73e9e42e209c36320ea55410Glenn Kasten ANDROID_KEY_PCMFORMAT_CHANNELMASK, channelMaskKeyIndex); 74133af4f47406b64af73e9e42e209c36320ea55410Glenn Kasten } else { 74233af4f47406b64af73e9e42e209c36320ea55410Glenn Kasten fprintf(stderr, "Unable to find key %s\n", ANDROID_KEY_PCMFORMAT_CHANNELMASK); 74333af4f47406b64af73e9e42e209c36320ea55410Glenn Kasten } 74433af4f47406b64af73e9e42e209c36320ea55410Glenn Kasten if (endiannessKeyIndex != -1) { 74533af4f47406b64af73e9e42e209c36320ea55410Glenn Kasten printf("Key %s is at index %d\n", 74633af4f47406b64af73e9e42e209c36320ea55410Glenn Kasten ANDROID_KEY_PCMFORMAT_ENDIANNESS, endiannessKeyIndex); 74733af4f47406b64af73e9e42e209c36320ea55410Glenn Kasten } else { 74833af4f47406b64af73e9e42e209c36320ea55410Glenn Kasten fprintf(stderr, "Unable to find key %s\n", ANDROID_KEY_PCMFORMAT_ENDIANNESS); 74933af4f47406b64af73e9e42e209c36320ea55410Glenn Kasten } 750688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi#endif 751688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi 752e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kasten // set the player's state to paused, to start prefetching 753e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kasten printf("Setting play state to PAUSED\n"); 754e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kasten res = (*playItf)->SetPlayState(playItf, SL_PLAYSTATE_PAUSED); 755e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kasten ExitOnError(res); 756e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kasten 757e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kasten // wait for prefetch status callback to indicate either sufficient data or error 758e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kasten printf("Awaiting prefetch complete\n"); 759e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kasten pthread_mutex_lock(&mutex); 760e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kasten while (prefetch_status == PREFETCHSTATUS_UNKNOWN) { 761e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kasten pthread_cond_wait(&cond, &mutex); 762e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kasten } 763e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kasten pthread_mutex_unlock(&mutex); 764e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kasten if (prefetch_status == PREFETCHSTATUS_ERROR) { 765e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kasten fprintf(stderr, "Error during prefetch, exiting\n"); 766e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kasten goto destroyRes; 767e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kasten } 768e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kasten printf("Prefetch is complete\n"); 769e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kasten 770688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi /* ------------------------------------------------------ */ 771688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi /* Start decoding */ 772688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi printf("Starting to decode\n"); 773688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi res = (*playItf)->SetPlayState(playItf, SL_PLAYSTATE_PLAYING); 774688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi ExitOnError(res); 775688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi 776688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi /* Decode until the end of the stream is reached */ 777e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kasten printf("Awaiting notification that all encoded buffers have been enqueued\n"); 778688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi pthread_mutex_lock(&eosLock); 779688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi while (!eos) { 780e5cba3cbd006f0082af290cb34af8551c2710a03Glenn Kasten if (pauseFrame > 0) { 781e5cba3cbd006f0082af290cb34af8551c2710a03Glenn Kasten if (decodedFrames >= pauseFrame) { 782e5cba3cbd006f0082af290cb34af8551c2710a03Glenn Kasten pauseFrame = 0; 783e5cba3cbd006f0082af290cb34af8551c2710a03Glenn Kasten printf("Pausing after decoded frame %u for 10 seconds\n", decodedFrames); 784e5cba3cbd006f0082af290cb34af8551c2710a03Glenn Kasten pthread_mutex_unlock(&eosLock); 785e5cba3cbd006f0082af290cb34af8551c2710a03Glenn Kasten res = (*playItf)->SetPlayState(playItf, SL_PLAYSTATE_PAUSED); 786e5cba3cbd006f0082af290cb34af8551c2710a03Glenn Kasten ExitOnError(res); 787e5cba3cbd006f0082af290cb34af8551c2710a03Glenn Kasten sleep(10); 788e5cba3cbd006f0082af290cb34af8551c2710a03Glenn Kasten printf("Resuming\n"); 789e5cba3cbd006f0082af290cb34af8551c2710a03Glenn Kasten res = (*playItf)->SetPlayState(playItf, SL_PLAYSTATE_PLAYING); 790e5cba3cbd006f0082af290cb34af8551c2710a03Glenn Kasten ExitOnError(res); 791e5cba3cbd006f0082af290cb34af8551c2710a03Glenn Kasten pthread_mutex_lock(&eosLock); 792e5cba3cbd006f0082af290cb34af8551c2710a03Glenn Kasten } else { 793e5cba3cbd006f0082af290cb34af8551c2710a03Glenn Kasten pthread_mutex_unlock(&eosLock); 794e5cba3cbd006f0082af290cb34af8551c2710a03Glenn Kasten usleep(10*1000); 795e5cba3cbd006f0082af290cb34af8551c2710a03Glenn Kasten pthread_mutex_lock(&eosLock); 796e5cba3cbd006f0082af290cb34af8551c2710a03Glenn Kasten } 797e5cba3cbd006f0082af290cb34af8551c2710a03Glenn Kasten } else { 798e5cba3cbd006f0082af290cb34af8551c2710a03Glenn Kasten pthread_cond_wait(&eosCondition, &eosLock); 799e5cba3cbd006f0082af290cb34af8551c2710a03Glenn Kasten } 800688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi } 801688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi pthread_mutex_unlock(&eosLock); 802e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kasten printf("All encoded buffers have now been enqueued, but there's still more to do\n"); 803688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi 804688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi /* This just means done enqueueing; there may still more data in decode queue! */ 805e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kasten pthread_mutex_lock(&head_mutex); 806e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kasten while (!head_atend) { 807e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kasten pthread_cond_wait(&head_cond, &head_mutex); 808e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kasten } 809e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kasten pthread_mutex_unlock(&head_mutex); 810e5ce0bdb3aca8976465b9e2e55b1267e48aef44dGlenn Kasten printf("Decode is now finished\n"); 811688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi 812688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi pthread_mutex_lock(&eosLock); 813688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi printf("Frame counters: encoded=%u decoded=%u\n", encodedFrames, decodedFrames); 81433af4f47406b64af73e9e42e209c36320ea55410Glenn Kasten printf("Sample counters: encoded=%u decoded=%u\n", encodedSamples, decodedSamples); 815e5cba3cbd006f0082af290cb34af8551c2710a03Glenn Kasten printf("Total encode completions received: actual=%u, expected=%u\n", 816e5cba3cbd006f0082af290cb34af8551c2710a03Glenn Kasten totalEncodeCompletions, encodedFrames+1/*EOS*/); 817688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi pthread_mutex_unlock(&eosLock); 818688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi 81933af4f47406b64af73e9e42e209c36320ea55410Glenn Kasten /* Get the final position and duration */ 82033af4f47406b64af73e9e42e209c36320ea55410Glenn Kasten res = (*playItf)->GetPosition(playItf, &position); 82133af4f47406b64af73e9e42e209c36320ea55410Glenn Kasten ExitOnError(res); 82233af4f47406b64af73e9e42e209c36320ea55410Glenn Kasten res = (*playItf)->GetDuration(playItf, &duration); 82333af4f47406b64af73e9e42e209c36320ea55410Glenn Kasten ExitOnError(res); 82433af4f47406b64af73e9e42e209c36320ea55410Glenn Kasten if (duration == SL_TIME_UNKNOWN) { 82533af4f47406b64af73e9e42e209c36320ea55410Glenn Kasten printf("The final position is %u ms, duration is unknown\n", position); 82633af4f47406b64af73e9e42e209c36320ea55410Glenn Kasten } else { 82733af4f47406b64af73e9e42e209c36320ea55410Glenn Kasten printf("The final position is %u ms, duration is %u ms\n", position, duration); 82833af4f47406b64af73e9e42e209c36320ea55410Glenn Kasten } 82933af4f47406b64af73e9e42e209c36320ea55410Glenn Kasten 830e5cba3cbd006f0082af290cb34af8551c2710a03Glenn Kasten printf("Frame length statistics:\n"); 831e5cba3cbd006f0082af290cb34af8551c2710a03Glenn Kasten printf(" n = %u frames\n", frameStats.n()); 832e5cba3cbd006f0082af290cb34af8551c2710a03Glenn Kasten printf(" mean = %.1f bytes\n", frameStats.mean()); 833e5cba3cbd006f0082af290cb34af8551c2710a03Glenn Kasten printf(" minimum = %.1f bytes\n", frameStats.minimum()); 834e5cba3cbd006f0082af290cb34af8551c2710a03Glenn Kasten printf(" maximum = %.1f bytes\n", frameStats.maximum()); 835e5cba3cbd006f0082af290cb34af8551c2710a03Glenn Kasten printf(" stddev = %.1f bytes\n", frameStats.stddev()); 836e5cba3cbd006f0082af290cb34af8551c2710a03Glenn Kasten 837688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi /* ------------------------------------------------------ */ 838688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi /* End of decoding */ 839688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi 840688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel TrividestroyRes: 841688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi /* Destroy the AudioPlayer object */ 842688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi (*player)->Destroy(player); 843688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi 844e5cba3cbd006f0082af290cb34af8551c2710a03Glenn Kasten if (outputFp != NULL) { 845e5cba3cbd006f0082af290cb34af8551c2710a03Glenn Kasten fclose(outputFp); 846e5cba3cbd006f0082af290cb34af8551c2710a03Glenn Kasten } 847688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi 848688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi // unmap the ADTS AAC file from memory 849688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi ok = munmap(ptr, statbuf.st_size); 850688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi if (0 != ok) { 851688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi perror(path); 852688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi } 853688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi} 854688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi 855688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi//----------------------------------------------------------------- 856688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Triviint main(int argc, char* const argv[]) 857688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi{ 858688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi SLresult res; 859688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi SLObjectItf sl; 860688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi 861688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi printf("OpenSL ES test %s: decodes a file containing AAC ADTS data\n", argv[0]); 862688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi 863688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi if (argc != 2) { 864688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi printf("Usage: \t%s source_file\n", argv[0]); 865688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi printf("Example: \"%s /sdcard/myFile.adts\n", argv[0]); 866688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi exit(EXIT_FAILURE); 867688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi } 868688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi 869688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi // open pathname of encoded ADTS AAC file to get a file descriptor 870688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi int fd; 871688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi fd = open(argv[1], O_RDONLY); 872688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi if (fd < 0) { 873688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi perror(argv[1]); 874688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi return EXIT_FAILURE; 875688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi } 876688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi 877688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi SLEngineOption EngineOption[] = { 878688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi {(SLuint32) SL_ENGINEOPTION_THREADSAFE, (SLuint32) SL_BOOLEAN_TRUE} 879688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi }; 880688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi 881688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi res = slCreateEngine( &sl, 1, EngineOption, 0, NULL, NULL); 882688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi ExitOnError(res); 883688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi 884688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi /* Realizing the SL Engine in synchronous mode. */ 885688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi res = (*sl)->Realize(sl, SL_BOOLEAN_FALSE); 886688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi ExitOnError(res); 887688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi 888688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi TestDecToBuffQueue(sl, argv[1], fd); 889688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi 890688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi /* Shutdown OpenSL ES */ 891688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi (*sl)->Destroy(sl); 892688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi 893688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi // close the file 894688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi (void) close(fd); 895688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi 896688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi return EXIT_SUCCESS; 897688178c51666cf7df5814e7eac3a01fc3e076c0fJean-Michel Trivi} 898