1 /* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 /* AAC ADTS Decode Test 18 19 First run the program from shell: 20 # slesTestDecodeAac /sdcard/myFile.adts 21 22 Expected output: 23 OpenSL ES test slesTestDecodeAac: decodes a file containing AAC ADTS data 24 Player created 25 Player realized 26 Enqueueing initial empty buffers to receive decoded PCM data 0 1 27 Enqueueing initial full buffers of encoded ADTS data 0 1 28 Starting to decode 29 Frame counters: encoded=4579 decoded=4579 30 31 These use adb on host to retrieve the decoded file: 32 % adb pull /sdcard/myFile.adts.raw myFile.raw 33 34 How to examine the output with Audacity: 35 Project / Import raw data 36 Select myFile.raw file, then click Open button 37 Choose these options: 38 Signed 16-bit PCM 39 Little-endian 40 1 Channel (Mono) / 2 Channels (Stereo) based on the PCM information obtained when decoding 41 Sample rate based on the PCM information obtained when decoding 42 Click Import button 43 44 */ 45 46 #define QUERY_METADATA 47 48 #include <assert.h> 49 #include <stdlib.h> 50 #include <stdio.h> 51 #include <string.h> 52 #include <unistd.h> 53 #include <sys/time.h> 54 #include <fcntl.h> 55 #include <pthread.h> 56 #include <sys/mman.h> 57 #include <sys/stat.h> 58 #include <unistd.h> 59 #include <cpustats/CentralTendencyStatistics.h> 60 61 #include <SLES/OpenSLES.h> 62 #include <SLES/OpenSLES_Android.h> 63 64 /* Explicitly requesting SL_IID_ANDROIDBUFFERQUEUE and SL_IID_ANDROIDSIMPLEBUFFERQUEUE 65 * on the AudioPlayer object for decoding, and 66 * SL_IID_METADATAEXTRACTION for retrieving the format of the decoded audio. 67 */ 68 #define NUM_EXPLICIT_INTERFACES_FOR_PLAYER 4 69 70 /* Number of decoded samples produced by one AAC frame; defined by the standard */ 71 #define SAMPLES_PER_AAC_FRAME 1024 72 /* Size of the encoded AAC ADTS buffer queue */ 73 #define NB_BUFFERS_IN_ADTS_QUEUE 2 // 2 to 4 is typical 74 75 /* Size of the decoded PCM buffer queue */ 76 #define NB_BUFFERS_IN_PCM_QUEUE 2 // 2 to 4 is typical 77 /* Size of each PCM buffer in the queue */ 78 #define BUFFER_SIZE_IN_BYTES (2*sizeof(short)*SAMPLES_PER_AAC_FRAME) 79 80 /* Local storage for decoded PCM audio data */ 81 int8_t pcmData[NB_BUFFERS_IN_PCM_QUEUE * BUFFER_SIZE_IN_BYTES]; 82 83 /* destination for decoded data */ 84 static FILE* outputFp; 85 86 #ifdef QUERY_METADATA 87 /* metadata key index for the PCM format information we want to retrieve */ 88 static int channelCountKeyIndex = -1; 89 static int sampleRateKeyIndex = -1; 90 static int bitsPerSampleKeyIndex = -1; 91 static int containerSizeKeyIndex = -1; 92 static int channelMaskKeyIndex = -1; 93 static int endiannessKeyIndex = -1; 94 /* size of the struct to retrieve the PCM format metadata values: the values we're interested in 95 * are SLuint32, but it is saved in the data field of a SLMetadataInfo, hence the larger size. 96 * Note that this size is queried and displayed at l.XXX for demonstration/test purposes. 97 * */ 98 #define PCM_METADATA_VALUE_SIZE 32 99 /* used to query metadata values */ 100 static SLMetadataInfo *pcmMetaData = NULL; 101 /* we only want to query / display the PCM format once */ 102 static bool formatQueried = false; 103 #endif 104 105 /* to signal to the test app that the end of the encoded ADTS stream has been reached */ 106 bool eos = false; 107 bool endOfEncodedStream = false; 108 109 void *ptr; 110 unsigned char *frame; 111 size_t filelen; 112 size_t encodedFrames = 0; 113 size_t encodedSamples = 0; 114 size_t decodedFrames = 0; 115 size_t decodedSamples = 0; 116 size_t totalEncodeCompletions = 0; // number of Enqueue completions received 117 CentralTendencyStatistics frameStats; 118 size_t pauseFrame = 0; // pause after this many decoded frames, zero means don't pause 119 SLboolean createRaw = SL_BOOLEAN_TRUE; // whether to create a .raw file containing PCM data 120 121 /* constant to identify a buffer context which is the end of the stream to decode */ 122 static const int kEosBufferCntxt = 1980; // a magic value we can compare against 123 124 /* protects shared variables */ 125 pthread_mutex_t eosLock = PTHREAD_MUTEX_INITIALIZER; 126 pthread_cond_t eosCondition = PTHREAD_COND_INITIALIZER; 127 128 // These are extensions to OpenMAX AL 1.0.1 values 129 130 #define PREFETCHSTATUS_UNKNOWN ((SLuint32) 0) 131 #define PREFETCHSTATUS_ERROR ((SLuint32) (-1)) 132 133 // Mutex and condition shared with main program to protect prefetch_status 134 135 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; 136 static pthread_cond_t cond = PTHREAD_COND_INITIALIZER; 137 SLuint32 prefetch_status = PREFETCHSTATUS_UNKNOWN; 138 139 /* used to detect errors likely to have occured when the OpenSL ES framework fails to open 140 * a resource, for instance because a file URI is invalid, or an HTTP server doesn't respond. 141 */ 142 #define PREFETCHEVENT_ERROR_CANDIDATE \ 143 (SL_PREFETCHEVENT_STATUSCHANGE | SL_PREFETCHEVENT_FILLLEVELCHANGE) 144 145 //----------------------------------------------------------------- 146 /* Exits the application if an error is encountered */ 147 #define ExitOnError(x) ExitOnErrorFunc(x,__LINE__) 148 149 void ExitOnErrorFunc( SLresult result , int line) 150 { 151 if (SL_RESULT_SUCCESS != result) { 152 fprintf(stderr, "Error code %u encountered at line %d, exiting\n", result, line); 153 exit(EXIT_FAILURE); 154 } 155 } 156 157 //----------------------------------------------------------------- 158 /* Callback for "prefetch" events, here used to detect audio resource opening errors */ 159 void PrefetchEventCallback(SLPrefetchStatusItf caller, void *pContext, SLuint32 event) 160 { 161 // pContext is unused here, so we pass NULL 162 assert(pContext == NULL); 163 SLpermille level = 0; 164 SLresult result; 165 result = (*caller)->GetFillLevel(caller, &level); 166 ExitOnError(result); 167 SLuint32 status; 168 result = (*caller)->GetPrefetchStatus(caller, &status); 169 ExitOnError(result); 170 printf("prefetch level=%d status=0x%x event=%d\n", level, status, event); 171 SLuint32 new_prefetch_status; 172 if ((PREFETCHEVENT_ERROR_CANDIDATE == (event & PREFETCHEVENT_ERROR_CANDIDATE)) 173 && (level == 0) && (status == SL_PREFETCHSTATUS_UNDERFLOW)) { 174 printf("PrefetchEventCallback: Error while prefetching data, exiting\n"); 175 new_prefetch_status = PREFETCHSTATUS_ERROR; 176 } else if (event == SL_PREFETCHEVENT_STATUSCHANGE) { 177 new_prefetch_status = status; 178 } else { 179 return; 180 } 181 int ok; 182 ok = pthread_mutex_lock(&mutex); 183 assert(ok == 0); 184 prefetch_status = new_prefetch_status; 185 ok = pthread_cond_signal(&cond); 186 assert(ok == 0); 187 ok = pthread_mutex_unlock(&mutex); 188 assert(ok == 0); 189 } 190 191 //----------------------------------------------------------------- 192 /* Structure for passing information to callback function */ 193 typedef struct CallbackCntxt_ { 194 #ifdef QUERY_METADATA 195 SLMetadataExtractionItf metaItf; 196 #endif 197 SLPlayItf playItf; 198 SLint8* pDataBase; // Base address of local audio data storage 199 SLint8* pData; // Current address of local audio data storage 200 } CallbackCntxt; 201 202 // used to notify when SL_PLAYEVENT_HEADATEND event is received 203 static pthread_mutex_t head_mutex = PTHREAD_MUTEX_INITIALIZER; 204 static pthread_cond_t head_cond = PTHREAD_COND_INITIALIZER; 205 static SLboolean head_atend = SL_BOOLEAN_FALSE; 206 207 //----------------------------------------------------------------- 208 /* Callback for SLPlayItf through which we receive the SL_PLAYEVENT_HEADATEND event */ 209 void PlayCallback(SLPlayItf caller, void *pContext, SLuint32 event) { 210 SLmillisecond position; 211 SLresult res = (*caller)->GetPosition(caller, &position); 212 ExitOnError(res); 213 if (event & SL_PLAYEVENT_HEADATMARKER) { 214 printf("SL_PLAYEVENT_HEADATMARKER position=%u ms\n", position); 215 } 216 if (event & SL_PLAYEVENT_HEADATNEWPOS) { 217 printf("SL_PLAYEVENT_HEADATNEWPOS position=%u ms\n", position); 218 } 219 if (event & SL_PLAYEVENT_HEADATEND) { 220 printf("SL_PLAYEVENT_HEADATEND position=%u ms, all decoded data has been received\n", 221 position); 222 pthread_mutex_lock(&head_mutex); 223 head_atend = SL_BOOLEAN_TRUE; 224 pthread_cond_signal(&head_cond); 225 pthread_mutex_unlock(&head_mutex); 226 } 227 } 228 229 //----------------------------------------------------------------- 230 /* Callback for AndroidBufferQueueItf through which we supply ADTS buffers */ 231 SLresult AndroidBufferQueueCallback( 232 SLAndroidBufferQueueItf caller, 233 void *pCallbackContext, /* input */ 234 void *pBufferContext, /* input */ 235 void *pBufferData, /* input */ 236 SLuint32 dataSize, /* input */ 237 SLuint32 dataUsed, /* input */ 238 const SLAndroidBufferItem *pItems,/* input */ 239 SLuint32 itemsLength /* input */) 240 { 241 // mutex on all global variables 242 pthread_mutex_lock(&eosLock); 243 SLresult res; 244 245 // for demonstration purposes: 246 // verify what type of information was enclosed in the processed buffer 247 if (NULL != pBufferContext) { 248 if (&kEosBufferCntxt == pBufferContext) { 249 fprintf(stdout, "EOS was processed\n"); 250 } 251 } 252 253 ++totalEncodeCompletions; 254 if (endOfEncodedStream) { 255 // we continue to receive acknowledgement after each buffer was processed 256 if (pBufferContext == (void *) &kEosBufferCntxt) { 257 printf("Received EOS completion after EOS\n"); 258 } else if (pBufferContext == NULL) { 259 printf("Received ADTS completion after EOS\n"); 260 } else { 261 fprintf(stderr, "Received acknowledgement after EOS with unexpected context %p\n", 262 pBufferContext); 263 } 264 } else if (filelen == 0) { 265 // signal EOS to the decoder rather than just starving it 266 printf("Enqueue EOS: encoded frames=%u, decoded frames=%u\n", encodedFrames, decodedFrames); 267 printf("You should now see %u ADTS completion%s followed by 1 EOS completion\n", 268 NB_BUFFERS_IN_ADTS_QUEUE - 1, NB_BUFFERS_IN_ADTS_QUEUE != 2 ? "s" : ""); 269 SLAndroidBufferItem msgEos; 270 msgEos.itemKey = SL_ANDROID_ITEMKEY_EOS; 271 msgEos.itemSize = 0; 272 // EOS message has no parameters, so the total size of the message is the size of the key 273 // plus the size of itemSize, both SLuint32 274 res = (*caller)->Enqueue(caller, (void *)&kEosBufferCntxt /*pBufferContext*/, 275 NULL /*pData*/, 0 /*dataLength*/, 276 &msgEos /*pMsg*/, 277 sizeof(SLuint32)*2 /*msgLength*/); 278 ExitOnError(res); 279 endOfEncodedStream = true; 280 // verify that we are at start of an ADTS frame 281 } else if (!(filelen < 7 || frame[0] != 0xFF || (frame[1] & 0xF0) != 0xF0)) { 282 if (pBufferContext != NULL) { 283 fprintf(stderr, "Received acknowledgement before EOS with unexpected context %p\n", 284 pBufferContext); 285 } 286 unsigned framelen = ((frame[3] & 3) << 11) | (frame[4] << 3) | (frame[5] >> 5); 287 if (framelen <= filelen) { 288 // push more data to the queue 289 res = (*caller)->Enqueue(caller, NULL /*pBufferContext*/, 290 frame, framelen, NULL, 0); 291 ExitOnError(res); 292 frame += framelen; 293 filelen -= framelen; 294 ++encodedFrames; 295 encodedSamples += SAMPLES_PER_AAC_FRAME; 296 frameStats.sample(framelen); 297 } else { 298 fprintf(stderr, 299 "partial ADTS frame at EOF discarded; offset=%u, framelen=%u, filelen=%u\n", 300 frame - (unsigned char *) ptr, framelen, filelen); 301 frame += filelen; 302 filelen = 0; 303 } 304 } else { 305 fprintf(stderr, "corrupt ADTS frame encountered; offset=%u, filelen=%u\n", 306 frame - (unsigned char *) ptr, filelen); 307 frame += filelen; 308 filelen = 0; 309 } 310 pthread_mutex_unlock(&eosLock); 311 312 return SL_RESULT_SUCCESS; 313 } 314 315 //----------------------------------------------------------------- 316 /* Callback for decoding buffer queue events */ 317 void DecPlayCallback( 318 SLAndroidSimpleBufferQueueItf queueItf, 319 void *pContext) 320 { 321 // mutex on all global variables 322 pthread_mutex_lock(&eosLock); 323 324 CallbackCntxt *pCntxt = (CallbackCntxt*)pContext; 325 326 /* Save the decoded data to output file */ 327 if (outputFp != NULL && fwrite(pCntxt->pData, 1, BUFFER_SIZE_IN_BYTES, outputFp) 328 < BUFFER_SIZE_IN_BYTES) { 329 fprintf(stderr, "Error writing to output file"); 330 } 331 332 /* Re-enqueue the now empty buffer */ 333 SLresult res; 334 res = (*queueItf)->Enqueue(queueItf, pCntxt->pData, BUFFER_SIZE_IN_BYTES); 335 ExitOnError(res); 336 337 /* Increase data pointer by buffer size, with circular wraparound */ 338 pCntxt->pData += BUFFER_SIZE_IN_BYTES; 339 if (pCntxt->pData >= pCntxt->pDataBase + (NB_BUFFERS_IN_PCM_QUEUE * BUFFER_SIZE_IN_BYTES)) { 340 pCntxt->pData = pCntxt->pDataBase; 341 } 342 343 // Note: adding a sleep here or any sync point is a way to slow down the decoding, or 344 // synchronize it with some other event, as the OpenSL ES framework will block until the 345 // buffer queue callback return to proceed with the decoding. 346 347 #ifdef QUERY_METADATA 348 /* Example: query of the decoded PCM format */ 349 if (!formatQueried) { 350 /* memory to receive the PCM format metadata */ 351 union { 352 SLMetadataInfo pcmMetaData; 353 char withData[PCM_METADATA_VALUE_SIZE]; 354 } u; 355 res = (*pCntxt->metaItf)->GetValue(pCntxt->metaItf, sampleRateKeyIndex, 356 PCM_METADATA_VALUE_SIZE, &u.pcmMetaData); ExitOnError(res); 357 // Note: here we could verify the following: 358 // u.pcmMetaData->encoding == SL_CHARACTERENCODING_BINARY 359 // u.pcmMetaData->size == sizeof(SLuint32) 360 // but the call was successful for the PCM format keys, so those conditions are implied 361 printf("sample rate = %d\n", *((SLuint32*)u.pcmMetaData.data)); 362 res = (*pCntxt->metaItf)->GetValue(pCntxt->metaItf, channelCountKeyIndex, 363 PCM_METADATA_VALUE_SIZE, &u.pcmMetaData); ExitOnError(res); 364 printf("channel count = %d\n", *((SLuint32*)u.pcmMetaData.data)); 365 res = (*pCntxt->metaItf)->GetValue(pCntxt->metaItf, bitsPerSampleKeyIndex, 366 PCM_METADATA_VALUE_SIZE, &u.pcmMetaData); ExitOnError(res); 367 printf("bits per sample = %d bits\n", *((SLuint32*)u.pcmMetaData.data)); 368 res = (*pCntxt->metaItf)->GetValue(pCntxt->metaItf, containerSizeKeyIndex, 369 PCM_METADATA_VALUE_SIZE, &u.pcmMetaData); ExitOnError(res); 370 printf("container size = %d bits\n", *((SLuint32*)u.pcmMetaData.data)); 371 res = (*pCntxt->metaItf)->GetValue(pCntxt->metaItf, channelMaskKeyIndex, 372 PCM_METADATA_VALUE_SIZE, &u.pcmMetaData); ExitOnError(res); 373 printf("channel mask = 0x%X (0x3=front left | front right, 0x4=front center)\n", 374 *((SLuint32*)u.pcmMetaData.data)); 375 res = (*pCntxt->metaItf)->GetValue(pCntxt->metaItf, endiannessKeyIndex, 376 PCM_METADATA_VALUE_SIZE, &u.pcmMetaData); ExitOnError(res); 377 printf("endianness = %d (1=big, 2=little)\n", *((SLuint32*)u.pcmMetaData.data)); 378 formatQueried = true; 379 } 380 #endif 381 382 ++decodedFrames; 383 decodedSamples += SAMPLES_PER_AAC_FRAME; 384 385 /* Periodically ask for position and duration */ 386 if ((decodedFrames % 1000 == 0) || endOfEncodedStream) { 387 SLmillisecond position; 388 res = (*pCntxt->playItf)->GetPosition(pCntxt->playItf, &position); 389 ExitOnError(res); 390 SLmillisecond duration; 391 res = (*pCntxt->playItf)->GetDuration(pCntxt->playItf, &duration); 392 ExitOnError(res); 393 if (duration == SL_TIME_UNKNOWN) { 394 printf("After %u encoded %u decoded frames: position is %u ms, duration is " 395 "unknown as expected\n", 396 encodedFrames, decodedFrames, position); 397 } else { 398 printf("After %u encoded %u decoded frames: position is %u ms, duration is " 399 "surprisingly %u ms\n", 400 encodedFrames, decodedFrames, position, duration); 401 } 402 } 403 404 if (endOfEncodedStream && decodedSamples >= encodedSamples) { 405 eos = true; 406 pthread_cond_signal(&eosCondition); 407 } 408 pthread_mutex_unlock(&eosLock); 409 } 410 411 //----------------------------------------------------------------- 412 413 /* Decode an audio path by opening a file descriptor on that path */ 414 void TestDecToBuffQueue( SLObjectItf sl, const char *path, int fd) 415 { 416 // check what kind of object it is 417 int ok; 418 struct stat statbuf; 419 ok = fstat(fd, &statbuf); 420 if (ok < 0) { 421 perror(path); 422 return; 423 } 424 425 // verify that's it is a file 426 if (!S_ISREG(statbuf.st_mode)) { 427 fprintf(stderr, "%s: not an ordinary file\n", path); 428 return; 429 } 430 431 // map file contents into memory to make it easier to access the ADTS frames directly 432 ptr = mmap(NULL, statbuf.st_size, PROT_READ, MAP_FILE | MAP_PRIVATE, fd, (off_t) 0); 433 if (ptr == MAP_FAILED) { 434 perror(path); 435 return; 436 } 437 frame = (unsigned char *) ptr; 438 filelen = statbuf.st_size; 439 440 // create PCM .raw file 441 if (createRaw) { 442 size_t len = strlen((const char *) path); 443 char* outputPath = (char*) malloc(len + 4 + 1); // save room to concatenate ".raw" 444 if (NULL == outputPath) { 445 ExitOnError(SL_RESULT_RESOURCE_ERROR); 446 } 447 memcpy(outputPath, path, len + 1); 448 strcat(outputPath, ".raw"); 449 outputFp = fopen(outputPath, "w"); 450 if (NULL == outputFp) { 451 // issue an error message, but continue the decoding anyway 452 perror(outputPath); 453 } 454 } else { 455 outputFp = NULL; 456 } 457 458 SLresult res; 459 SLEngineItf EngineItf; 460 461 /* Objects this application uses: one audio player */ 462 SLObjectItf player; 463 464 /* Interfaces for the audio player */ 465 SLPlayItf playItf; 466 #ifdef QUERY_METADATA 467 /* to retrieve the decoded PCM format */ 468 SLMetadataExtractionItf mdExtrItf; 469 #endif 470 /* to retrieve the PCM samples */ 471 SLAndroidSimpleBufferQueueItf decBuffQueueItf; 472 /* to queue the AAC data to decode */ 473 SLAndroidBufferQueueItf aacBuffQueueItf; 474 /* for prefetch status */ 475 SLPrefetchStatusItf prefetchItf; 476 477 SLboolean required[NUM_EXPLICIT_INTERFACES_FOR_PLAYER]; 478 SLInterfaceID iidArray[NUM_EXPLICIT_INTERFACES_FOR_PLAYER]; 479 480 /* Get the SL Engine Interface which is implicit */ 481 res = (*sl)->GetInterface(sl, SL_IID_ENGINE, (void*)&EngineItf); 482 ExitOnError(res); 483 484 /* Initialize arrays required[] and iidArray[] */ 485 unsigned int i; 486 for (i=0 ; i < NUM_EXPLICIT_INTERFACES_FOR_PLAYER ; i++) { 487 required[i] = SL_BOOLEAN_FALSE; 488 iidArray[i] = SL_IID_NULL; 489 } 490 491 /* ------------------------------------------------------ */ 492 /* Configuration of the player */ 493 494 /* Request the AndroidSimpleBufferQueue interface */ 495 required[0] = SL_BOOLEAN_TRUE; 496 iidArray[0] = SL_IID_ANDROIDSIMPLEBUFFERQUEUE; 497 /* Request the AndroidBufferQueue interface */ 498 required[1] = SL_BOOLEAN_TRUE; 499 iidArray[1] = SL_IID_ANDROIDBUFFERQUEUESOURCE; 500 /* Request the PrefetchStatus interface */ 501 required[2] = SL_BOOLEAN_TRUE; 502 iidArray[2] = SL_IID_PREFETCHSTATUS; 503 #ifdef QUERY_METADATA 504 /* Request the MetadataExtraction interface */ 505 required[3] = SL_BOOLEAN_TRUE; 506 iidArray[3] = SL_IID_METADATAEXTRACTION; 507 #endif 508 509 /* Setup the data source for queueing AAC buffers of ADTS data */ 510 SLDataLocator_AndroidBufferQueue loc_srcAbq = { 511 SL_DATALOCATOR_ANDROIDBUFFERQUEUE /*locatorType*/, 512 NB_BUFFERS_IN_ADTS_QUEUE /*numBuffers*/}; 513 SLDataFormat_MIME format_srcMime = { 514 SL_DATAFORMAT_MIME /*formatType*/, 515 SL_ANDROID_MIME_AACADTS /*mimeType*/, 516 SL_CONTAINERTYPE_RAW /*containerType*/}; 517 SLDataSource decSource = {&loc_srcAbq /*pLocator*/, &format_srcMime /*pFormat*/}; 518 519 /* Setup the data sink, a buffer queue for buffers of PCM data */ 520 SLDataLocator_AndroidSimpleBufferQueue loc_destBq = { 521 SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE/*locatorType*/, 522 NB_BUFFERS_IN_PCM_QUEUE /*numBuffers*/ }; 523 524 /* declare we're decoding to PCM, the parameters after that need to be valid, 525 but are ignored, the decoded format will match the source */ 526 SLDataFormat_PCM format_destPcm = { /*formatType*/ SL_DATAFORMAT_PCM, /*numChannels*/ 1, 527 /*samplesPerSec*/ SL_SAMPLINGRATE_8, /*pcm.bitsPerSample*/ SL_PCMSAMPLEFORMAT_FIXED_16, 528 /*/containerSize*/ 16, /*channelMask*/ SL_SPEAKER_FRONT_LEFT, 529 /*endianness*/ SL_BYTEORDER_LITTLEENDIAN }; 530 SLDataSink decDest = {&loc_destBq /*pLocator*/, &format_destPcm /*pFormat*/}; 531 532 /* Create the audio player */ 533 res = (*EngineItf)->CreateAudioPlayer(EngineItf, &player, &decSource, &decDest, 534 #ifdef QUERY_METADATA 535 NUM_EXPLICIT_INTERFACES_FOR_PLAYER, 536 #else 537 NUM_EXPLICIT_INTERFACES_FOR_PLAYER - 1, 538 #endif 539 iidArray, required); 540 ExitOnError(res); 541 printf("Player created\n"); 542 543 /* Realize the player in synchronous mode. */ 544 res = (*player)->Realize(player, SL_BOOLEAN_FALSE); 545 ExitOnError(res); 546 printf("Player realized\n"); 547 548 /* Get the play interface which is implicit */ 549 res = (*player)->GetInterface(player, SL_IID_PLAY, (void*)&playItf); 550 ExitOnError(res); 551 552 /* Enable callback when position passes through a marker (SL_PLAYEVENT_HEADATMARKER) */ 553 res = (*playItf)->SetMarkerPosition(playItf, 5000); 554 ExitOnError(res); 555 556 /* Enable callback for periodic position updates (SL_PLAYEVENT_HEADATNEWPOS) */ 557 res = (*playItf)->SetPositionUpdatePeriod(playItf, 3000); 558 ExitOnError(res); 559 560 /* Use the play interface to set up a callback for the SL_PLAYEVENT_HEAD* events */ 561 res = (*playItf)->SetCallbackEventsMask(playItf, 562 SL_PLAYEVENT_HEADATMARKER | SL_PLAYEVENT_HEADATNEWPOS | SL_PLAYEVENT_HEADATEND); 563 ExitOnError(res); 564 res = (*playItf)->RegisterCallback(playItf, PlayCallback /*callback*/, NULL /*pContext*/); 565 ExitOnError(res); 566 567 /* Get the position before prefetch; should be zero */ 568 SLmillisecond position; 569 res = (*playItf)->GetPosition(playItf, &position); 570 ExitOnError(res); 571 if (position == 0) { 572 printf("The position before prefetch is zero as expected\n"); 573 } else if (position == SL_TIME_UNKNOWN) { 574 printf("That's surprising the position before prefetch is unknown"); 575 } else { 576 printf("That's surprising the position before prefetch is %u ms\n", position); 577 } 578 579 /* Get the duration before prefetch; should be unknown */ 580 SLmillisecond duration; 581 res = (*playItf)->GetDuration(playItf, &duration); 582 ExitOnError(res); 583 if (duration == SL_TIME_UNKNOWN) { 584 printf("The duration before prefetch is unknown as expected\n"); 585 } else { 586 printf("That's surprising the duration before prefetch is %u ms\n", duration); 587 } 588 589 /* Get the buffer queue interface which was explicitly requested */ 590 res = (*player)->GetInterface(player, SL_IID_ANDROIDSIMPLEBUFFERQUEUE, (void*)&decBuffQueueItf); 591 ExitOnError(res); 592 593 /* Get the Android buffer queue interface which was explicitly requested */ 594 res = (*player)->GetInterface(player, SL_IID_ANDROIDBUFFERQUEUESOURCE, (void*)&aacBuffQueueItf); 595 ExitOnError(res); 596 597 /* Get the prefetch status interface which was explicitly requested */ 598 res = (*player)->GetInterface(player, SL_IID_PREFETCHSTATUS, (void*)&prefetchItf); 599 ExitOnError(res); 600 601 #ifdef QUERY_METADATA 602 /* Get the metadata extraction interface which was explicitly requested */ 603 res = (*player)->GetInterface(player, SL_IID_METADATAEXTRACTION, (void*)&mdExtrItf); 604 ExitOnError(res); 605 #endif 606 607 /* ------------------------------------------------------ */ 608 /* Initialize the callback and its context for the buffer queue of the decoded PCM */ 609 CallbackCntxt sinkCntxt; 610 sinkCntxt.playItf = playItf; 611 #ifdef QUERY_METADATA 612 sinkCntxt.metaItf = mdExtrItf; 613 #endif 614 sinkCntxt.pDataBase = (int8_t*)&pcmData; 615 sinkCntxt.pData = sinkCntxt.pDataBase; 616 res = (*decBuffQueueItf)->RegisterCallback(decBuffQueueItf, DecPlayCallback, &sinkCntxt); 617 ExitOnError(res); 618 619 /* Enqueue buffers to map the region of memory allocated to store the decoded data */ 620 printf("Enqueueing initial empty buffers to receive decoded PCM data"); 621 for(i = 0 ; i < NB_BUFFERS_IN_PCM_QUEUE ; i++) { 622 printf(" %d", i); 623 res = (*decBuffQueueItf)->Enqueue(decBuffQueueItf, sinkCntxt.pData, BUFFER_SIZE_IN_BYTES); 624 ExitOnError(res); 625 sinkCntxt.pData += BUFFER_SIZE_IN_BYTES; 626 if (sinkCntxt.pData >= sinkCntxt.pDataBase + 627 (NB_BUFFERS_IN_PCM_QUEUE * BUFFER_SIZE_IN_BYTES)) { 628 sinkCntxt.pData = sinkCntxt.pDataBase; 629 } 630 } 631 printf("\n"); 632 633 /* ------------------------------------------------------ */ 634 /* Initialize the callback for prefetch errors, if we can't open the resource to decode */ 635 res = (*prefetchItf)->RegisterCallback(prefetchItf, PrefetchEventCallback, NULL); 636 ExitOnError(res); 637 res = (*prefetchItf)->SetCallbackEventsMask(prefetchItf, PREFETCHEVENT_ERROR_CANDIDATE); 638 ExitOnError(res); 639 640 /* Initialize the callback for the Android buffer queue of the encoded data */ 641 res = (*aacBuffQueueItf)->RegisterCallback(aacBuffQueueItf, AndroidBufferQueueCallback, NULL); 642 ExitOnError(res); 643 644 /* Enqueue the content of our encoded data before starting to play, 645 we don't want to starve the player initially */ 646 printf("Enqueueing initial full buffers of encoded ADTS data"); 647 for (i=0 ; i < NB_BUFFERS_IN_ADTS_QUEUE ; i++) { 648 if (filelen < 7 || frame[0] != 0xFF || (frame[1] & 0xF0) != 0xF0) { 649 printf("\ncorrupt ADTS frame encountered; offset %zu bytes\n", 650 frame - (unsigned char *) ptr); 651 // Note that prefetch will detect this error soon when it gets a premature EOF 652 break; 653 } 654 unsigned framelen = ((frame[3] & 3) << 11) | (frame[4] << 3) | (frame[5] >> 5); 655 printf(" %d (%u bytes)", i, framelen); 656 res = (*aacBuffQueueItf)->Enqueue(aacBuffQueueItf, NULL /*pBufferContext*/, 657 frame, framelen, NULL, 0); 658 ExitOnError(res); 659 frame += framelen; 660 filelen -= framelen; 661 ++encodedFrames; 662 encodedSamples += SAMPLES_PER_AAC_FRAME; 663 frameStats.sample(framelen); 664 } 665 printf("\n"); 666 667 #ifdef QUERY_METADATA 668 /* ------------------------------------------------------ */ 669 /* Get and display the metadata key names for the decoder */ 670 // This is for test / demonstration purposes only where we discover the key and value sizes 671 // of a PCM decoder. An application that would want to directly get access to those values 672 // can make assumptions about the size of the keys and their matching values (all SLuint32), 673 // but it should not make assumptions about the key indices as these are subject to change. 674 // Note that we don't get the metadata values yet; that happens in the first decode callback. 675 SLuint32 itemCount; 676 res = (*mdExtrItf)->GetItemCount(mdExtrItf, &itemCount); 677 ExitOnError(res); 678 printf("itemCount=%u\n", itemCount); 679 SLuint32 keySize, valueSize; 680 SLMetadataInfo *keyInfo, *value; 681 for(i=0 ; i<itemCount ; i++) { 682 keyInfo = NULL; keySize = 0; 683 value = NULL; valueSize = 0; 684 res = (*mdExtrItf)->GetKeySize(mdExtrItf, i, &keySize); 685 ExitOnError(res); 686 res = (*mdExtrItf)->GetValueSize(mdExtrItf, i, &valueSize); 687 ExitOnError(res); 688 keyInfo = (SLMetadataInfo*) malloc(keySize); 689 if (NULL != keyInfo) { 690 res = (*mdExtrItf)->GetKey(mdExtrItf, i, keySize, keyInfo); 691 ExitOnError(res); 692 printf("key[%d] size=%d, name=%s \tvalue size=%d encoding=0x%X langCountry=%s\n", 693 i, keyInfo->size, keyInfo->data, valueSize, keyInfo->encoding, 694 keyInfo->langCountry); 695 /* find out the key index of the metadata we're interested in */ 696 if (!strcmp((char*)keyInfo->data, ANDROID_KEY_PCMFORMAT_NUMCHANNELS)) { 697 channelCountKeyIndex = i; 698 } else if (!strcmp((char*)keyInfo->data, ANDROID_KEY_PCMFORMAT_SAMPLERATE)) { 699 sampleRateKeyIndex = i; 700 } else if (!strcmp((char*)keyInfo->data, ANDROID_KEY_PCMFORMAT_BITSPERSAMPLE)) { 701 bitsPerSampleKeyIndex = i; 702 } else if (!strcmp((char*)keyInfo->data, ANDROID_KEY_PCMFORMAT_CONTAINERSIZE)) { 703 containerSizeKeyIndex = i; 704 } else if (!strcmp((char*)keyInfo->data, ANDROID_KEY_PCMFORMAT_CHANNELMASK)) { 705 channelMaskKeyIndex = i; 706 } else if (!strcmp((char*)keyInfo->data, ANDROID_KEY_PCMFORMAT_ENDIANNESS)) { 707 endiannessKeyIndex = i; 708 } else { 709 printf("Unknown key %s ignored\n", (char *)keyInfo->data); 710 } 711 free(keyInfo); 712 } 713 } 714 if (channelCountKeyIndex != -1) { 715 printf("Key %s is at index %d\n", 716 ANDROID_KEY_PCMFORMAT_NUMCHANNELS, channelCountKeyIndex); 717 } else { 718 fprintf(stderr, "Unable to find key %s\n", ANDROID_KEY_PCMFORMAT_NUMCHANNELS); 719 } 720 if (sampleRateKeyIndex != -1) { 721 printf("Key %s is at index %d\n", 722 ANDROID_KEY_PCMFORMAT_SAMPLERATE, sampleRateKeyIndex); 723 } else { 724 fprintf(stderr, "Unable to find key %s\n", ANDROID_KEY_PCMFORMAT_SAMPLERATE); 725 } 726 if (bitsPerSampleKeyIndex != -1) { 727 printf("Key %s is at index %d\n", 728 ANDROID_KEY_PCMFORMAT_BITSPERSAMPLE, bitsPerSampleKeyIndex); 729 } else { 730 fprintf(stderr, "Unable to find key %s\n", ANDROID_KEY_PCMFORMAT_BITSPERSAMPLE); 731 } 732 if (containerSizeKeyIndex != -1) { 733 printf("Key %s is at index %d\n", 734 ANDROID_KEY_PCMFORMAT_CONTAINERSIZE, containerSizeKeyIndex); 735 } else { 736 fprintf(stderr, "Unable to find key %s\n", ANDROID_KEY_PCMFORMAT_CONTAINERSIZE); 737 } 738 if (channelMaskKeyIndex != -1) { 739 printf("Key %s is at index %d\n", 740 ANDROID_KEY_PCMFORMAT_CHANNELMASK, channelMaskKeyIndex); 741 } else { 742 fprintf(stderr, "Unable to find key %s\n", ANDROID_KEY_PCMFORMAT_CHANNELMASK); 743 } 744 if (endiannessKeyIndex != -1) { 745 printf("Key %s is at index %d\n", 746 ANDROID_KEY_PCMFORMAT_ENDIANNESS, endiannessKeyIndex); 747 } else { 748 fprintf(stderr, "Unable to find key %s\n", ANDROID_KEY_PCMFORMAT_ENDIANNESS); 749 } 750 #endif 751 752 // set the player's state to paused, to start prefetching 753 printf("Setting play state to PAUSED\n"); 754 res = (*playItf)->SetPlayState(playItf, SL_PLAYSTATE_PAUSED); 755 ExitOnError(res); 756 757 // wait for prefetch status callback to indicate either sufficient data or error 758 printf("Awaiting prefetch complete\n"); 759 pthread_mutex_lock(&mutex); 760 while (prefetch_status == PREFETCHSTATUS_UNKNOWN) { 761 pthread_cond_wait(&cond, &mutex); 762 } 763 pthread_mutex_unlock(&mutex); 764 if (prefetch_status == PREFETCHSTATUS_ERROR) { 765 fprintf(stderr, "Error during prefetch, exiting\n"); 766 goto destroyRes; 767 } 768 printf("Prefetch is complete\n"); 769 770 /* ------------------------------------------------------ */ 771 /* Start decoding */ 772 printf("Starting to decode\n"); 773 res = (*playItf)->SetPlayState(playItf, SL_PLAYSTATE_PLAYING); 774 ExitOnError(res); 775 776 /* Decode until the end of the stream is reached */ 777 printf("Awaiting notification that all encoded buffers have been enqueued\n"); 778 pthread_mutex_lock(&eosLock); 779 while (!eos) { 780 if (pauseFrame > 0) { 781 if (decodedFrames >= pauseFrame) { 782 pauseFrame = 0; 783 printf("Pausing after decoded frame %u for 10 seconds\n", decodedFrames); 784 pthread_mutex_unlock(&eosLock); 785 res = (*playItf)->SetPlayState(playItf, SL_PLAYSTATE_PAUSED); 786 ExitOnError(res); 787 sleep(10); 788 printf("Resuming\n"); 789 res = (*playItf)->SetPlayState(playItf, SL_PLAYSTATE_PLAYING); 790 ExitOnError(res); 791 pthread_mutex_lock(&eosLock); 792 } else { 793 pthread_mutex_unlock(&eosLock); 794 usleep(10*1000); 795 pthread_mutex_lock(&eosLock); 796 } 797 } else { 798 pthread_cond_wait(&eosCondition, &eosLock); 799 } 800 } 801 pthread_mutex_unlock(&eosLock); 802 printf("All encoded buffers have now been enqueued, but there's still more to do\n"); 803 804 /* This just means done enqueueing; there may still more data in decode queue! */ 805 pthread_mutex_lock(&head_mutex); 806 while (!head_atend) { 807 pthread_cond_wait(&head_cond, &head_mutex); 808 } 809 pthread_mutex_unlock(&head_mutex); 810 printf("Decode is now finished\n"); 811 812 pthread_mutex_lock(&eosLock); 813 printf("Frame counters: encoded=%u decoded=%u\n", encodedFrames, decodedFrames); 814 printf("Sample counters: encoded=%u decoded=%u\n", encodedSamples, decodedSamples); 815 printf("Total encode completions received: actual=%u, expected=%u\n", 816 totalEncodeCompletions, encodedFrames+1/*EOS*/); 817 pthread_mutex_unlock(&eosLock); 818 819 /* Get the final position and duration */ 820 res = (*playItf)->GetPosition(playItf, &position); 821 ExitOnError(res); 822 res = (*playItf)->GetDuration(playItf, &duration); 823 ExitOnError(res); 824 if (duration == SL_TIME_UNKNOWN) { 825 printf("The final position is %u ms, duration is unknown\n", position); 826 } else { 827 printf("The final position is %u ms, duration is %u ms\n", position, duration); 828 } 829 830 printf("Frame length statistics:\n"); 831 printf(" n = %u frames\n", frameStats.n()); 832 printf(" mean = %.1f bytes\n", frameStats.mean()); 833 printf(" minimum = %.1f bytes\n", frameStats.minimum()); 834 printf(" maximum = %.1f bytes\n", frameStats.maximum()); 835 printf(" stddev = %.1f bytes\n", frameStats.stddev()); 836 837 /* ------------------------------------------------------ */ 838 /* End of decoding */ 839 840 destroyRes: 841 /* Destroy the AudioPlayer object */ 842 (*player)->Destroy(player); 843 844 if (outputFp != NULL) { 845 fclose(outputFp); 846 } 847 848 // unmap the ADTS AAC file from memory 849 ok = munmap(ptr, statbuf.st_size); 850 if (0 != ok) { 851 perror(path); 852 } 853 } 854 855 //----------------------------------------------------------------- 856 int main(int argc, char* const argv[]) 857 { 858 SLresult res; 859 SLObjectItf sl; 860 861 printf("OpenSL ES test %s: decodes a file containing AAC ADTS data\n", argv[0]); 862 863 if (argc != 2) { 864 printf("Usage: \t%s source_file\n", argv[0]); 865 printf("Example: \"%s /sdcard/myFile.adts\n", argv[0]); 866 exit(EXIT_FAILURE); 867 } 868 869 // open pathname of encoded ADTS AAC file to get a file descriptor 870 int fd; 871 fd = open(argv[1], O_RDONLY); 872 if (fd < 0) { 873 perror(argv[1]); 874 return EXIT_FAILURE; 875 } 876 877 SLEngineOption EngineOption[] = { 878 {(SLuint32) SL_ENGINEOPTION_THREADSAFE, (SLuint32) SL_BOOLEAN_TRUE} 879 }; 880 881 res = slCreateEngine( &sl, 1, EngineOption, 0, NULL, NULL); 882 ExitOnError(res); 883 884 /* Realizing the SL Engine in synchronous mode. */ 885 res = (*sl)->Realize(sl, SL_BOOLEAN_FALSE); 886 ExitOnError(res); 887 888 TestDecToBuffQueue(sl, argv[1], fd); 889 890 /* Shutdown OpenSL ES */ 891 (*sl)->Destroy(sl); 892 893 // close the file 894 (void) close(fd); 895 896 return EXIT_SUCCESS; 897 } 898