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