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