1/* 2 * Copyright (C) 2010 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/* Engine implementation */ 18 19#include <endian.h> 20#include "sles_allinclusive.h" 21 22 23/* Utility functions */ 24 25static SLresult initializeBufferQueueMembers(CAudioPlayer *ap) { 26 // inline allocation of circular mArray, up to a typical max 27 if (BUFFER_HEADER_TYPICAL >= ap->mBufferQueue.mNumBuffers) { 28 ap->mBufferQueue.mArray = ap->mBufferQueue.mTypical; 29 } else { 30 // Avoid possible integer overflow during multiplication; this arbitrary 31 // maximum is big enough to not interfere with real applications, but 32 // small enough to not overflow. 33 if (ap->mBufferQueue.mNumBuffers >= 256) { 34 return SL_RESULT_MEMORY_FAILURE; 35 } 36 ap->mBufferQueue.mArray = (BufferHeader *) 37 malloc((ap->mBufferQueue.mNumBuffers + 1) * sizeof(BufferHeader)); 38 if (NULL == ap->mBufferQueue.mArray) { 39 return SL_RESULT_MEMORY_FAILURE; 40 } 41 } 42 ap->mBufferQueue.mFront = ap->mBufferQueue.mArray; 43 ap->mBufferQueue.mRear = ap->mBufferQueue.mArray; 44 return SL_RESULT_SUCCESS; 45} 46 47#ifdef ANDROID 48static SLresult initializeAndroidBufferQueueMembers(CAudioPlayer *ap) { 49 // Avoid possible integer overflow during multiplication; this arbitrary 50 // maximum is big enough to not interfere with real applications, but 51 // small enough to not overflow. 52 if (ap->mAndroidBufferQueue.mNumBuffers >= 256) { 53 return SL_RESULT_MEMORY_FAILURE; 54 } 55 ap->mAndroidBufferQueue.mBufferArray = (AdvancedBufferHeader *) 56 malloc( (ap->mAndroidBufferQueue.mNumBuffers + 1) * sizeof(AdvancedBufferHeader)); 57 if (NULL == ap->mAndroidBufferQueue.mBufferArray) { 58 return SL_RESULT_MEMORY_FAILURE; 59 } else { 60 61 // initialize ABQ buffer type 62 // assert below has been checked in android_audioPlayer_checkSourceSink 63 assert(SL_DATAFORMAT_MIME == ap->mDataSource.mFormat.mFormatType); 64 switch (ap->mDataSource.mFormat.mMIME.containerType) { 65 case SL_CONTAINERTYPE_MPEG_TS: 66 ap->mAndroidBufferQueue.mBufferType = kAndroidBufferTypeMpeg2Ts; 67 break; 68 case SL_CONTAINERTYPE_AAC: 69 case SL_CONTAINERTYPE_RAW: { 70 const char* mime = (char*)ap->mDataSource.mFormat.mMIME.mimeType; 71 if ((mime != NULL) && !(strcasecmp(mime, (const char *)SL_ANDROID_MIME_AACADTS) && 72 strcasecmp(mime, ANDROID_MIME_AACADTS_ANDROID_FRAMEWORK))) { 73 ap->mAndroidBufferQueue.mBufferType = kAndroidBufferTypeAacadts; 74 } else { 75 ap->mAndroidBufferQueue.mBufferType = kAndroidBufferTypeInvalid; 76 SL_LOGE("CreateAudioPlayer: Invalid buffer type in Android Buffer Queue"); 77 return SL_RESULT_CONTENT_UNSUPPORTED; 78 } 79 } break; 80 default: 81 ap->mAndroidBufferQueue.mBufferType = kAndroidBufferTypeInvalid; 82 SL_LOGE("CreateAudioPlayer: Invalid buffer type in Android Buffer Queue"); 83 return SL_RESULT_CONTENT_UNSUPPORTED; 84 } 85 86 ap->mAndroidBufferQueue.mFront = ap->mAndroidBufferQueue.mBufferArray; 87 ap->mAndroidBufferQueue.mRear = ap->mAndroidBufferQueue.mBufferArray; 88 } 89 90 return SL_RESULT_SUCCESS; 91} 92#endif 93 94 95static SLresult IEngine_CreateLEDDevice(SLEngineItf self, SLObjectItf *pDevice, SLuint32 deviceID, 96 SLuint32 numInterfaces, const SLInterfaceID *pInterfaceIds, const SLboolean *pInterfaceRequired) 97{ 98 SL_ENTER_INTERFACE 99 100#if USE_PROFILES & USE_PROFILES_OPTIONAL 101 if ((NULL == pDevice) || (SL_DEFAULTDEVICEID_LED != deviceID)) { 102 result = SL_RESULT_PARAMETER_INVALID; 103 } else { 104 *pDevice = NULL; 105 unsigned exposedMask; 106 const ClassTable *pCLEDDevice_class = objectIDtoClass(SL_OBJECTID_LEDDEVICE); 107 if (NULL == pCLEDDevice_class) { 108 result = SL_RESULT_FEATURE_UNSUPPORTED; 109 } else { 110 result = checkInterfaces(pCLEDDevice_class, numInterfaces, pInterfaceIds, 111 pInterfaceRequired, &exposedMask, NULL); 112 } 113 if (SL_RESULT_SUCCESS == result) { 114 CLEDDevice *thiz = (CLEDDevice *) construct(pCLEDDevice_class, exposedMask, self); 115 if (NULL == thiz) { 116 result = SL_RESULT_MEMORY_FAILURE; 117 } else { 118 thiz->mDeviceID = deviceID; 119 IObject_Publish(&thiz->mObject); 120 // return the new LED object 121 *pDevice = &thiz->mObject.mItf; 122 } 123 } 124 } 125#else 126 result = SL_RESULT_FEATURE_UNSUPPORTED; 127#endif 128 129 SL_LEAVE_INTERFACE 130} 131 132 133static SLresult IEngine_CreateVibraDevice(SLEngineItf self, SLObjectItf *pDevice, SLuint32 deviceID, 134 SLuint32 numInterfaces, const SLInterfaceID *pInterfaceIds, const SLboolean *pInterfaceRequired) 135{ 136 SL_ENTER_INTERFACE 137 138#if USE_PROFILES & USE_PROFILES_OPTIONAL 139 if ((NULL == pDevice) || (SL_DEFAULTDEVICEID_VIBRA != deviceID)) { 140 result = SL_RESULT_PARAMETER_INVALID; 141 } else { 142 *pDevice = NULL; 143 unsigned exposedMask; 144 const ClassTable *pCVibraDevice_class = objectIDtoClass(SL_OBJECTID_VIBRADEVICE); 145 if (NULL == pCVibraDevice_class) { 146 result = SL_RESULT_FEATURE_UNSUPPORTED; 147 } else { 148 result = checkInterfaces(pCVibraDevice_class, numInterfaces, 149 pInterfaceIds, pInterfaceRequired, &exposedMask, NULL); 150 } 151 if (SL_RESULT_SUCCESS == result) { 152 CVibraDevice *thiz = (CVibraDevice *) construct(pCVibraDevice_class, exposedMask, self); 153 if (NULL == thiz) { 154 result = SL_RESULT_MEMORY_FAILURE; 155 } else { 156 thiz->mDeviceID = deviceID; 157 IObject_Publish(&thiz->mObject); 158 // return the new vibra object 159 *pDevice = &thiz->mObject.mItf; 160 } 161 } 162 } 163#else 164 result = SL_RESULT_FEATURE_UNSUPPORTED; 165#endif 166 167 SL_LEAVE_INTERFACE 168} 169 170 171static SLresult IEngine_CreateAudioPlayer(SLEngineItf self, SLObjectItf *pPlayer, 172 SLDataSource *pAudioSrc, SLDataSink *pAudioSnk, SLuint32 numInterfaces, 173 const SLInterfaceID *pInterfaceIds, const SLboolean *pInterfaceRequired) 174{ 175 SL_ENTER_INTERFACE 176 177 if (NULL == pPlayer) { 178 result = SL_RESULT_PARAMETER_INVALID; 179 } else { 180 *pPlayer = NULL; 181 unsigned exposedMask, requiredMask; 182 const ClassTable *pCAudioPlayer_class = objectIDtoClass(SL_OBJECTID_AUDIOPLAYER); 183 assert(NULL != pCAudioPlayer_class); 184 result = checkInterfaces(pCAudioPlayer_class, numInterfaces, 185 pInterfaceIds, pInterfaceRequired, &exposedMask, &requiredMask); 186 if (SL_RESULT_SUCCESS == result) { 187 188 // Construct our new AudioPlayer instance 189 CAudioPlayer *thiz = (CAudioPlayer *) construct(pCAudioPlayer_class, exposedMask, self); 190 if (NULL == thiz) { 191 result = SL_RESULT_MEMORY_FAILURE; 192 } else { 193 194 do { 195 196 // Initialize private fields not associated with an interface 197 198 // Default data source in case of failure in checkDataSource 199 thiz->mDataSource.mLocator.mLocatorType = SL_DATALOCATOR_NULL; 200 thiz->mDataSource.mFormat.mFormatType = SL_DATAFORMAT_NULL; 201 202 // Default data sink in case of failure in checkDataSink 203 thiz->mDataSink.mLocator.mLocatorType = SL_DATALOCATOR_NULL; 204 thiz->mDataSink.mFormat.mFormatType = SL_DATAFORMAT_NULL; 205 206 // Default is no per-channel mute or solo 207 thiz->mMuteMask = 0; 208 thiz->mSoloMask = 0; 209 210 // Will be set soon for PCM buffer queues, or later by platform-specific code 211 // during Realize or Prefetch 212 thiz->mNumChannels = UNKNOWN_NUMCHANNELS; 213 thiz->mSampleRateMilliHz = UNKNOWN_SAMPLERATE; 214 215 // More default values, in case destructor needs to be called early 216 thiz->mDirectLevel = 0; // no attenuation 217#ifdef USE_OUTPUTMIXEXT 218 thiz->mTrack = NULL; 219 thiz->mGains[0] = 1.0f; 220 thiz->mGains[1] = 1.0f; 221 thiz->mDestroyRequested = SL_BOOLEAN_FALSE; 222#endif 223#ifdef USE_SNDFILE 224 thiz->mSndFile.mPathname = NULL; 225 thiz->mSndFile.mSNDFILE = NULL; 226 memset(&thiz->mSndFile.mSfInfo, 0, sizeof(SF_INFO)); 227 memset(&thiz->mSndFile.mMutex, 0, sizeof(pthread_mutex_t)); 228 thiz->mSndFile.mEOF = SL_BOOLEAN_FALSE; 229 thiz->mSndFile.mWhich = 0; 230 memset(thiz->mSndFile.mBuffer, 0, sizeof(thiz->mSndFile.mBuffer)); 231#endif 232#ifdef ANDROID 233 // placement new (explicit constructor) 234 // FIXME unnecessary once those fields are encapsulated in one class, rather 235 // than a structure 236 //###(void) new (&thiz->mAudioTrack) android::sp<android::AudioTrack>(); 237 (void) new (&thiz->mTrackPlayer) android::sp<android::TrackPlayerBase>(); 238 (void) new (&thiz->mCallbackProtector) 239 android::sp<android::CallbackProtector>(); 240 (void) new (&thiz->mAuxEffect) android::sp<android::AudioEffect>(); 241 (void) new (&thiz->mAPlayer) android::sp<android::GenericPlayer>(); 242 // Android-specific POD fields are initialized in android_audioPlayer_create, 243 // and assume calloc or memset 0 during allocation 244#endif 245 246 // Check the source and sink parameters against generic constraints, 247 // and make a local copy of all parameters in case other application threads 248 // change memory concurrently. 249 250 result = checkDataSource("pAudioSrc", pAudioSrc, &thiz->mDataSource, 251 DATALOCATOR_MASK_URI | DATALOCATOR_MASK_ADDRESS | 252 DATALOCATOR_MASK_BUFFERQUEUE 253#ifdef ANDROID 254 | DATALOCATOR_MASK_ANDROIDFD | DATALOCATOR_MASK_ANDROIDSIMPLEBUFFERQUEUE 255 | DATALOCATOR_MASK_ANDROIDBUFFERQUEUE 256#endif 257 , DATAFORMAT_MASK_MIME | DATAFORMAT_MASK_PCM | DATAFORMAT_MASK_PCM_EX); 258 259 if (SL_RESULT_SUCCESS != result) { 260 break; 261 } 262 263 result = checkDataSink("pAudioSnk", pAudioSnk, &thiz->mDataSink, 264 DATALOCATOR_MASK_OUTPUTMIX // for playback 265#ifdef ANDROID 266 | DATALOCATOR_MASK_ANDROIDSIMPLEBUFFERQUEUE // for decode to a BQ 267 | DATALOCATOR_MASK_BUFFERQUEUE // for decode to a BQ 268#endif 269 , DATAFORMAT_MASK_NULL 270#ifdef ANDROID 271 | DATAFORMAT_MASK_PCM | DATAFORMAT_MASK_PCM_EX // for decode to PCM 272#endif 273 ); 274 if (SL_RESULT_SUCCESS != result) { 275 break; 276 } 277 278 // It would be unsafe to ever refer to the application pointers again 279 pAudioSrc = NULL; 280 pAudioSnk = NULL; 281 282 // Check that the requested interfaces are compatible with data source and sink 283 result = checkSourceSinkVsInterfacesCompatibility(&thiz->mDataSource, 284 &thiz->mDataSink, pCAudioPlayer_class, requiredMask); 285 if (SL_RESULT_SUCCESS != result) { 286 break; 287 } 288 289 // copy the buffer queue count from source locator (for playback) / from the 290 // sink locator (for decode on ANDROID build) to the buffer queue interface 291 // we have already range-checked the value down to a smaller width 292 SLuint16 nbBuffers = 0; 293 bool usesAdvancedBufferHeaders = false; 294 bool usesSimpleBufferQueue = false; 295 // creating an AudioPlayer which decodes AAC ADTS buffers to a PCM buffer queue 296 // will cause usesAdvancedBufferHeaders and usesSimpleBufferQueue to be true 297 switch (thiz->mDataSource.mLocator.mLocatorType) { 298 case SL_DATALOCATOR_BUFFERQUEUE: 299#ifdef ANDROID 300 case SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE: 301#endif 302 usesSimpleBufferQueue = true; 303 nbBuffers = (SLuint16) thiz->mDataSource.mLocator.mBufferQueue.numBuffers; 304 assert(SL_DATAFORMAT_PCM == thiz->mDataSource.mFormat.mFormatType 305 || SL_ANDROID_DATAFORMAT_PCM_EX 306 == thiz->mDataSource.mFormat.mFormatType); 307 thiz->mNumChannels = thiz->mDataSource.mFormat.mPCM.numChannels; 308 thiz->mSampleRateMilliHz = thiz->mDataSource.mFormat.mPCM.samplesPerSec; 309 break; 310#ifdef ANDROID 311 case SL_DATALOCATOR_ANDROIDBUFFERQUEUE: 312 usesAdvancedBufferHeaders = true; 313 nbBuffers = (SLuint16) thiz->mDataSource.mLocator.mABQ.numBuffers; 314 thiz->mAndroidBufferQueue.mNumBuffers = nbBuffers; 315 break; 316#endif 317 default: 318 nbBuffers = 0; 319 break; 320 } 321#ifdef ANDROID 322 switch (thiz->mDataSink.mLocator.mLocatorType) { 323 case SL_DATALOCATOR_BUFFERQUEUE: 324 case SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE: 325 usesSimpleBufferQueue = true; 326 nbBuffers = thiz->mDataSink.mLocator.mBufferQueue.numBuffers; 327 assert(SL_DATAFORMAT_PCM == thiz->mDataSink.mFormat.mFormatType 328 || SL_ANDROID_DATAFORMAT_PCM_EX 329 == thiz->mDataSink.mFormat.mFormatType); 330 // FIXME The values specified by the app are meaningless. We get the 331 // real values from the decoder. But the data sink checks currently require 332 // that the app specify these useless values. Needs doc/fix. 333 // Instead use the "unknown" values, as needed by prepare completion. 334 // thiz->mNumChannels = thiz->mDataSink.mFormat.mPCM.numChannels; 335 // thiz->mSampleRateMilliHz = thiz->mDataSink.mFormat.mPCM.samplesPerSec; 336 thiz->mNumChannels = UNKNOWN_NUMCHANNELS; 337 thiz->mSampleRateMilliHz = UNKNOWN_SAMPLERATE; 338 break; 339 default: 340 // leave nbBuffers unchanged 341 break; 342 } 343#endif 344 thiz->mBufferQueue.mNumBuffers = nbBuffers; 345 346 // check the audio source and sink parameters against platform support 347#ifdef ANDROID 348 result = android_audioPlayer_checkSourceSink(thiz); 349 if (SL_RESULT_SUCCESS != result) { 350 break; 351 } 352#endif 353 354#ifdef USE_SNDFILE 355 result = SndFile_checkAudioPlayerSourceSink(thiz); 356 if (SL_RESULT_SUCCESS != result) { 357 break; 358 } 359#endif 360 361#ifdef USE_OUTPUTMIXEXT 362 result = IOutputMixExt_checkAudioPlayerSourceSink(thiz); 363 if (SL_RESULT_SUCCESS != result) { 364 break; 365 } 366#endif 367 368 // Allocate memory for buffer queue 369 if (usesAdvancedBufferHeaders) { 370#ifdef ANDROID 371 // locator is SL_DATALOCATOR_ANDROIDBUFFERQUEUE 372 result = initializeAndroidBufferQueueMembers(thiz); 373#else 374 assert(false); 375#endif 376 } 377 378 if (usesSimpleBufferQueue) { 379 // locator is SL_DATALOCATOR_BUFFERQUEUE 380 // or SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE 381 result = initializeBufferQueueMembers(thiz); 382 } 383 384 // used to store the data source of our audio player 385 thiz->mDynamicSource.mDataSource = &thiz->mDataSource.u.mSource; 386 387 // platform-specific initialization 388#ifdef ANDROID 389 android_audioPlayer_create(thiz); 390#endif 391 392 } while (0); 393 394 if (SL_RESULT_SUCCESS != result) { 395 IObject_Destroy(&thiz->mObject.mItf); 396 } else { 397 IObject_Publish(&thiz->mObject); 398 // return the new audio player object 399 *pPlayer = &thiz->mObject.mItf; 400 } 401 402 } 403 } 404 405 } 406 407 SL_LEAVE_INTERFACE 408} 409 410 411static SLresult IEngine_CreateAudioRecorder(SLEngineItf self, SLObjectItf *pRecorder, 412 SLDataSource *pAudioSrc, SLDataSink *pAudioSnk, SLuint32 numInterfaces, 413 const SLInterfaceID *pInterfaceIds, const SLboolean *pInterfaceRequired) 414{ 415 SL_ENTER_INTERFACE 416 417#if (USE_PROFILES & USE_PROFILES_OPTIONAL) || defined(ANDROID) 418 if (NULL == pRecorder) { 419 result = SL_RESULT_PARAMETER_INVALID; 420 } else { 421 *pRecorder = NULL; 422 unsigned exposedMask; 423 const ClassTable *pCAudioRecorder_class = objectIDtoClass(SL_OBJECTID_AUDIORECORDER); 424 if (NULL == pCAudioRecorder_class) { 425 result = SL_RESULT_FEATURE_UNSUPPORTED; 426 } else { 427 result = checkInterfaces(pCAudioRecorder_class, numInterfaces, 428 pInterfaceIds, pInterfaceRequired, &exposedMask, NULL); 429 } 430 431 if (SL_RESULT_SUCCESS == result) { 432 433 // Construct our new AudioRecorder instance 434 CAudioRecorder *thiz = (CAudioRecorder *) construct(pCAudioRecorder_class, exposedMask, 435 self); 436 if (NULL == thiz) { 437 result = SL_RESULT_MEMORY_FAILURE; 438 } else { 439 440 do { 441 442 // Initialize fields not associated with any interface 443 444 // Default data source in case of failure in checkDataSource 445 thiz->mDataSource.mLocator.mLocatorType = SL_DATALOCATOR_NULL; 446 thiz->mDataSource.mFormat.mFormatType = SL_DATAFORMAT_NULL; 447 448 // Default data sink in case of failure in checkDataSink 449 thiz->mDataSink.mLocator.mLocatorType = SL_DATALOCATOR_NULL; 450 thiz->mDataSink.mFormat.mFormatType = SL_DATAFORMAT_NULL; 451 452 // These fields are set to real values by 453 // android_audioRecorder_checkSourceSink. Note that the data sink is 454 // always PCM buffer queue, so we know the channel count and sample rate early. 455 thiz->mNumChannels = UNKNOWN_NUMCHANNELS; 456 thiz->mSampleRateMilliHz = UNKNOWN_SAMPLERATE; 457#ifdef ANDROID 458 // placement new (explicit constructor) 459 // FIXME unnecessary once those fields are encapsulated in one class, rather 460 // than a structure 461 (void) new (&thiz->mAudioRecord) android::sp<android::AudioRecord>(); 462 (void) new (&thiz->mCallbackProtector) 463 android::sp<android::CallbackProtector>(); 464 thiz->mRecordSource = AUDIO_SOURCE_DEFAULT; 465#endif 466 467 // Check the source and sink parameters, and make a local copy of all parameters 468 result = checkDataSource("pAudioSrc", pAudioSrc, &thiz->mDataSource, 469 DATALOCATOR_MASK_IODEVICE, DATAFORMAT_MASK_NULL); 470 if (SL_RESULT_SUCCESS != result) { 471 break; 472 } 473 result = checkDataSink("pAudioSnk", pAudioSnk, &thiz->mDataSink, 474 DATALOCATOR_MASK_URI 475#ifdef ANDROID 476 | DATALOCATOR_MASK_ANDROIDSIMPLEBUFFERQUEUE 477#endif 478 , DATAFORMAT_MASK_MIME | DATAFORMAT_MASK_PCM | DATAFORMAT_MASK_PCM_EX 479 ); 480 if (SL_RESULT_SUCCESS != result) { 481 break; 482 } 483 484 // It would be unsafe to ever refer to the application pointers again 485 pAudioSrc = NULL; 486 pAudioSnk = NULL; 487 488 // check the audio source and sink parameters against platform support 489#ifdef ANDROID 490 result = android_audioRecorder_checkSourceSink(thiz); 491 if (SL_RESULT_SUCCESS != result) { 492 SL_LOGE("Cannot create AudioRecorder: invalid source or sink"); 493 break; 494 } 495#endif 496 497#ifdef ANDROID 498 // Allocate memory for buffer queue 499 SLuint32 locatorType = thiz->mDataSink.mLocator.mLocatorType; 500 if (locatorType == SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE) { 501 thiz->mBufferQueue.mNumBuffers = 502 thiz->mDataSink.mLocator.mBufferQueue.numBuffers; 503 // inline allocation of circular Buffer Queue mArray, up to a typical max 504 if (BUFFER_HEADER_TYPICAL >= thiz->mBufferQueue.mNumBuffers) { 505 thiz->mBufferQueue.mArray = thiz->mBufferQueue.mTypical; 506 } else { 507 // Avoid possible integer overflow during multiplication; this arbitrary 508 // maximum is big enough to not interfere with real applications, but 509 // small enough to not overflow. 510 if (thiz->mBufferQueue.mNumBuffers >= 256) { 511 result = SL_RESULT_MEMORY_FAILURE; 512 break; 513 } 514 thiz->mBufferQueue.mArray = (BufferHeader *) malloc((thiz->mBufferQueue. 515 mNumBuffers + 1) * sizeof(BufferHeader)); 516 if (NULL == thiz->mBufferQueue.mArray) { 517 result = SL_RESULT_MEMORY_FAILURE; 518 break; 519 } 520 } 521 thiz->mBufferQueue.mFront = thiz->mBufferQueue.mArray; 522 thiz->mBufferQueue.mRear = thiz->mBufferQueue.mArray; 523 } 524#endif 525 526 // platform-specific initialization 527#ifdef ANDROID 528 android_audioRecorder_create(thiz); 529#endif 530 531 } while (0); 532 533 if (SL_RESULT_SUCCESS != result) { 534 IObject_Destroy(&thiz->mObject.mItf); 535 } else { 536 IObject_Publish(&thiz->mObject); 537 // return the new audio recorder object 538 *pRecorder = &thiz->mObject.mItf; 539 } 540 } 541 542 } 543 544 } 545#else 546 result = SL_RESULT_FEATURE_UNSUPPORTED; 547#endif 548 549 SL_LEAVE_INTERFACE 550} 551 552 553static SLresult IEngine_CreateMidiPlayer(SLEngineItf self, SLObjectItf *pPlayer, 554 SLDataSource *pMIDISrc, SLDataSource *pBankSrc, SLDataSink *pAudioOutput, 555 SLDataSink *pVibra, SLDataSink *pLEDArray, SLuint32 numInterfaces, 556 const SLInterfaceID *pInterfaceIds, const SLboolean *pInterfaceRequired) 557{ 558 SL_ENTER_INTERFACE 559 560#if USE_PROFILES & (USE_PROFILES_GAME | USE_PROFILES_PHONE) 561 if ((NULL == pPlayer) || (NULL == pMIDISrc) || (NULL == pAudioOutput)) { 562 result = SL_RESULT_PARAMETER_INVALID; 563 } else { 564 *pPlayer = NULL; 565 unsigned exposedMask; 566 const ClassTable *pCMidiPlayer_class = objectIDtoClass(SL_OBJECTID_MIDIPLAYER); 567 if (NULL == pCMidiPlayer_class) { 568 result = SL_RESULT_FEATURE_UNSUPPORTED; 569 } else { 570 result = checkInterfaces(pCMidiPlayer_class, numInterfaces, 571 pInterfaceIds, pInterfaceRequired, &exposedMask, NULL); 572 } 573 if (SL_RESULT_SUCCESS == result) { 574 CMidiPlayer *thiz = (CMidiPlayer *) construct(pCMidiPlayer_class, exposedMask, self); 575 if (NULL == thiz) { 576 result = SL_RESULT_MEMORY_FAILURE; 577 } else { 578#if 0 579 "pMIDISrc", pMIDISrc, URI | MIDIBUFFERQUEUE, NONE 580 "pBankSrc", pBanksrc, NULL | URI | ADDRESS, NULL 581 "pAudioOutput", pAudioOutput, OUTPUTMIX, NULL 582 "pVibra", pVibra, NULL | IODEVICE, NULL 583 "pLEDArray", pLEDArray, NULL | IODEVICE, NULL 584#endif 585 // a fake value - why not use value from IPlay_init? what does CT check for? 586 thiz->mPlay.mDuration = 0; 587 IObject_Publish(&thiz->mObject); 588 // return the new MIDI player object 589 *pPlayer = &thiz->mObject.mItf; 590 } 591 } 592 } 593#else 594 result = SL_RESULT_FEATURE_UNSUPPORTED; 595#endif 596 597 SL_LEAVE_INTERFACE 598} 599 600 601static SLresult IEngine_CreateListener(SLEngineItf self, SLObjectItf *pListener, 602 SLuint32 numInterfaces, const SLInterfaceID *pInterfaceIds, const SLboolean *pInterfaceRequired) 603{ 604 SL_ENTER_INTERFACE 605 606#if USE_PROFILES & USE_PROFILES_GAME 607 if (NULL == pListener) { 608 result = SL_RESULT_PARAMETER_INVALID; 609 } else { 610 *pListener = NULL; 611 unsigned exposedMask; 612 const ClassTable *pCListener_class = objectIDtoClass(SL_OBJECTID_LISTENER); 613 if (NULL == pCListener_class) { 614 result = SL_RESULT_FEATURE_UNSUPPORTED; 615 } else { 616 result = checkInterfaces(pCListener_class, numInterfaces, 617 pInterfaceIds, pInterfaceRequired, &exposedMask, NULL); 618 } 619 if (SL_RESULT_SUCCESS == result) { 620 CListener *thiz = (CListener *) construct(pCListener_class, exposedMask, self); 621 if (NULL == thiz) { 622 result = SL_RESULT_MEMORY_FAILURE; 623 } else { 624 IObject_Publish(&thiz->mObject); 625 // return the new 3D listener object 626 *pListener = &thiz->mObject.mItf; 627 } 628 } 629 } 630#else 631 result = SL_RESULT_FEATURE_UNSUPPORTED; 632#endif 633 634 SL_LEAVE_INTERFACE 635} 636 637 638static SLresult IEngine_Create3DGroup(SLEngineItf self, SLObjectItf *pGroup, SLuint32 numInterfaces, 639 const SLInterfaceID *pInterfaceIds, const SLboolean *pInterfaceRequired) 640{ 641 SL_ENTER_INTERFACE 642 643#if USE_PROFILES & USE_PROFILES_GAME 644 if (NULL == pGroup) { 645 result = SL_RESULT_PARAMETER_INVALID; 646 } else { 647 *pGroup = NULL; 648 unsigned exposedMask; 649 const ClassTable *pC3DGroup_class = objectIDtoClass(SL_OBJECTID_3DGROUP); 650 if (NULL == pC3DGroup_class) { 651 result = SL_RESULT_FEATURE_UNSUPPORTED; 652 } else { 653 result = checkInterfaces(pC3DGroup_class, numInterfaces, 654 pInterfaceIds, pInterfaceRequired, &exposedMask, NULL); 655 } 656 if (SL_RESULT_SUCCESS == result) { 657 C3DGroup *thiz = (C3DGroup *) construct(pC3DGroup_class, exposedMask, self); 658 if (NULL == thiz) { 659 result = SL_RESULT_MEMORY_FAILURE; 660 } else { 661 thiz->mMemberMask = 0; 662 IObject_Publish(&thiz->mObject); 663 // return the new 3D group object 664 *pGroup = &thiz->mObject.mItf; 665 } 666 } 667 } 668#else 669 result = SL_RESULT_FEATURE_UNSUPPORTED; 670#endif 671 672 SL_LEAVE_INTERFACE 673} 674 675 676static SLresult IEngine_CreateOutputMix(SLEngineItf self, SLObjectItf *pMix, SLuint32 numInterfaces, 677 const SLInterfaceID *pInterfaceIds, const SLboolean *pInterfaceRequired) 678{ 679 SL_ENTER_INTERFACE 680 681 if (NULL == pMix) { 682 result = SL_RESULT_PARAMETER_INVALID; 683 } else { 684 *pMix = NULL; 685 unsigned exposedMask; 686 const ClassTable *pCOutputMix_class = objectIDtoClass(SL_OBJECTID_OUTPUTMIX); 687 assert(NULL != pCOutputMix_class); 688 result = checkInterfaces(pCOutputMix_class, numInterfaces, 689 pInterfaceIds, pInterfaceRequired, &exposedMask, NULL); 690 if (SL_RESULT_SUCCESS == result) { 691 COutputMix *thiz = (COutputMix *) construct(pCOutputMix_class, exposedMask, self); 692 if (NULL == thiz) { 693 result = SL_RESULT_MEMORY_FAILURE; 694 } else { 695#ifdef ANDROID 696 android_outputMix_create(thiz); 697#endif 698#ifdef USE_SDL 699 IEngine *thisEngine = &thiz->mObject.mEngine->mEngine; 700 interface_lock_exclusive(thisEngine); 701 bool unpause = false; 702 if (NULL == thisEngine->mOutputMix) { 703 thisEngine->mOutputMix = thiz; 704 unpause = true; 705 } 706 interface_unlock_exclusive(thisEngine); 707#endif 708 IObject_Publish(&thiz->mObject); 709#ifdef USE_SDL 710 if (unpause) { 711 // Enable SDL_callback to be called periodically by SDL's internal thread 712 SDL_PauseAudio(0); 713 } 714#endif 715 // return the new output mix object 716 *pMix = &thiz->mObject.mItf; 717 } 718 } 719 } 720 721 SL_LEAVE_INTERFACE 722} 723 724 725static SLresult IEngine_CreateMetadataExtractor(SLEngineItf self, SLObjectItf *pMetadataExtractor, 726 SLDataSource *pDataSource, SLuint32 numInterfaces, const SLInterfaceID *pInterfaceIds, 727 const SLboolean *pInterfaceRequired) 728{ 729 SL_ENTER_INTERFACE 730 731#if USE_PROFILES & (USE_PROFILES_GAME | USE_PROFILES_MUSIC) 732 if (NULL == pMetadataExtractor) { 733 result = SL_RESULT_PARAMETER_INVALID; 734 } else { 735 *pMetadataExtractor = NULL; 736 unsigned exposedMask; 737 const ClassTable *pCMetadataExtractor_class = 738 objectIDtoClass(SL_OBJECTID_METADATAEXTRACTOR); 739 if (NULL == pCMetadataExtractor_class) { 740 result = SL_RESULT_FEATURE_UNSUPPORTED; 741 } else { 742 result = checkInterfaces(pCMetadataExtractor_class, numInterfaces, 743 pInterfaceIds, pInterfaceRequired, &exposedMask, NULL); 744 } 745 if (SL_RESULT_SUCCESS == result) { 746 CMetadataExtractor *thiz = (CMetadataExtractor *) 747 construct(pCMetadataExtractor_class, exposedMask, self); 748 if (NULL == thiz) { 749 result = SL_RESULT_MEMORY_FAILURE; 750 } else { 751#if 0 752 "pDataSource", pDataSource, NONE, NONE 753#endif 754 IObject_Publish(&thiz->mObject); 755 // return the new metadata extractor object 756 *pMetadataExtractor = &thiz->mObject.mItf; 757 result = SL_RESULT_SUCCESS; 758 } 759 } 760 } 761#else 762 result = SL_RESULT_FEATURE_UNSUPPORTED; 763#endif 764 765 SL_LEAVE_INTERFACE 766} 767 768 769static SLresult IEngine_CreateExtensionObject(SLEngineItf self, SLObjectItf *pObject, 770 void *pParameters, SLuint32 objectID, SLuint32 numInterfaces, 771 const SLInterfaceID *pInterfaceIds, const SLboolean *pInterfaceRequired) 772{ 773 SL_ENTER_INTERFACE 774 775 if (NULL == pObject) { 776 result = SL_RESULT_PARAMETER_INVALID; 777 } else { 778 *pObject = NULL; 779 result = SL_RESULT_FEATURE_UNSUPPORTED; 780 } 781 782 SL_LEAVE_INTERFACE 783} 784 785 786static SLresult IEngine_QueryNumSupportedInterfaces(SLEngineItf self, 787 SLuint32 objectID, SLuint32 *pNumSupportedInterfaces) 788{ 789 SL_ENTER_INTERFACE 790 791 if (NULL == pNumSupportedInterfaces) { 792 result = SL_RESULT_PARAMETER_INVALID; 793 } else { 794 const ClassTable *clazz = objectIDtoClass(objectID); 795 if (NULL == clazz) { 796 result = SL_RESULT_FEATURE_UNSUPPORTED; 797 } else { 798 SLuint32 count = 0; 799 SLuint32 i; 800 for (i = 0; i < clazz->mInterfaceCount; ++i) { 801 switch (clazz->mInterfaces[i].mInterface) { 802 case INTERFACE_IMPLICIT: 803 case INTERFACE_IMPLICIT_PREREALIZE: 804 case INTERFACE_EXPLICIT: 805 case INTERFACE_EXPLICIT_PREREALIZE: 806 case INTERFACE_DYNAMIC: 807 ++count; 808 break; 809 case INTERFACE_UNAVAILABLE: 810 break; 811 default: 812 assert(false); 813 break; 814 } 815 } 816 *pNumSupportedInterfaces = count; 817 result = SL_RESULT_SUCCESS; 818 } 819 } 820 821 SL_LEAVE_INTERFACE; 822} 823 824 825static SLresult IEngine_QuerySupportedInterfaces(SLEngineItf self, 826 SLuint32 objectID, SLuint32 index, SLInterfaceID *pInterfaceId) 827{ 828 SL_ENTER_INTERFACE 829 830 if (NULL == pInterfaceId) { 831 result = SL_RESULT_PARAMETER_INVALID; 832 } else { 833 *pInterfaceId = NULL; 834 const ClassTable *clazz = objectIDtoClass(objectID); 835 if (NULL == clazz) { 836 result = SL_RESULT_FEATURE_UNSUPPORTED; 837 } else { 838 result = SL_RESULT_PARAMETER_INVALID; // will be reset later 839 SLuint32 i; 840 for (i = 0; i < clazz->mInterfaceCount; ++i) { 841 switch (clazz->mInterfaces[i].mInterface) { 842 case INTERFACE_IMPLICIT: 843 case INTERFACE_IMPLICIT_PREREALIZE: 844 case INTERFACE_EXPLICIT: 845 case INTERFACE_EXPLICIT_PREREALIZE: 846 case INTERFACE_DYNAMIC: 847 break; 848 case INTERFACE_UNAVAILABLE: 849 continue; 850 default: 851 assert(false); 852 break; 853 } 854 if (index == 0) { 855 *pInterfaceId = &SL_IID_array[clazz->mInterfaces[i].mMPH]; 856 result = SL_RESULT_SUCCESS; 857 break; 858 } 859 --index; 860 } 861 } 862 } 863 864 SL_LEAVE_INTERFACE 865}; 866 867 868static const char * const extensionNames[] = { 869#ifdef ANDROID 870#define _(n) #n 871#define __(n) _(n) 872 "ANDROID_SDK_LEVEL_" __(PLATFORM_SDK_VERSION), 873#undef _ 874#undef __ 875#else 876 "WILHELM_DESKTOP", 877#endif 878}; 879 880 881static SLresult IEngine_QueryNumSupportedExtensions(SLEngineItf self, SLuint32 *pNumExtensions) 882{ 883 SL_ENTER_INTERFACE 884 885 if (NULL == pNumExtensions) { 886 result = SL_RESULT_PARAMETER_INVALID; 887 } else { 888 *pNumExtensions = sizeof(extensionNames) / sizeof(extensionNames[0]); 889 result = SL_RESULT_SUCCESS; 890 } 891 892 SL_LEAVE_INTERFACE 893} 894 895 896static SLresult IEngine_QuerySupportedExtension(SLEngineItf self, 897 SLuint32 index, SLchar *pExtensionName, SLint16 *pNameLength) 898{ 899 SL_ENTER_INTERFACE 900 901 if (NULL == pNameLength) { 902 result = SL_RESULT_PARAMETER_INVALID; 903 } else { 904 size_t actualNameLength; 905 unsigned numExtensions = sizeof(extensionNames) / sizeof(extensionNames[0]); 906 if (index >= numExtensions) { 907 actualNameLength = 0; 908 result = SL_RESULT_PARAMETER_INVALID; 909 } else { 910 const char *extensionName = extensionNames[index]; 911 actualNameLength = strlen(extensionName) + 1; 912 if (NULL == pExtensionName) { 913 // application is querying the name length in order to allocate a buffer 914 result = SL_RESULT_SUCCESS; 915 } else { 916 SLint16 availableNameLength = *pNameLength; 917 if (0 >= availableNameLength) { 918 // there is not even room for the terminating NUL 919 result = SL_RESULT_BUFFER_INSUFFICIENT; 920 } else if (actualNameLength > (size_t) availableNameLength) { 921 // "no invalid strings are written. That is, the null-terminator always exists" 922 memcpy(pExtensionName, extensionName, (size_t) availableNameLength - 1); 923 pExtensionName[(size_t) availableNameLength - 1] = '\0'; 924 result = SL_RESULT_BUFFER_INSUFFICIENT; 925 } else { 926 memcpy(pExtensionName, extensionName, actualNameLength); 927 result = SL_RESULT_SUCCESS; 928 } 929 } 930 } 931 *pNameLength = actualNameLength; 932 } 933 934 SL_LEAVE_INTERFACE 935} 936 937 938static SLresult IEngine_IsExtensionSupported(SLEngineItf self, 939 const SLchar *pExtensionName, SLboolean *pSupported) 940{ 941 SL_ENTER_INTERFACE 942 943 if (NULL == pSupported) { 944 result = SL_RESULT_PARAMETER_INVALID; 945 } else { 946 SLboolean isSupported = SL_BOOLEAN_FALSE; 947 if (NULL == pExtensionName) { 948 result = SL_RESULT_PARAMETER_INVALID; 949 } else { 950 unsigned numExtensions = sizeof(extensionNames) / sizeof(extensionNames[0]); 951 unsigned i; 952 for (i = 0; i < numExtensions; ++i) { 953 if (!strcmp((const char *) pExtensionName, extensionNames[i])) { 954 isSupported = SL_BOOLEAN_TRUE; 955 break; 956 } 957 } 958 result = SL_RESULT_SUCCESS; 959 } 960 *pSupported = isSupported; 961 } 962 963 SL_LEAVE_INTERFACE 964} 965 966 967static const struct SLEngineItf_ IEngine_Itf = { 968 IEngine_CreateLEDDevice, 969 IEngine_CreateVibraDevice, 970 IEngine_CreateAudioPlayer, 971 IEngine_CreateAudioRecorder, 972 IEngine_CreateMidiPlayer, 973 IEngine_CreateListener, 974 IEngine_Create3DGroup, 975 IEngine_CreateOutputMix, 976 IEngine_CreateMetadataExtractor, 977 IEngine_CreateExtensionObject, 978 IEngine_QueryNumSupportedInterfaces, 979 IEngine_QuerySupportedInterfaces, 980 IEngine_QueryNumSupportedExtensions, 981 IEngine_QuerySupportedExtension, 982 IEngine_IsExtensionSupported 983}; 984 985void IEngine_init(void *self) 986{ 987 IEngine *thiz = (IEngine *) self; 988 thiz->mItf = &IEngine_Itf; 989 // mLossOfControlGlobal is initialized in slCreateEngine 990#ifdef USE_SDL 991 thiz->mOutputMix = NULL; 992#endif 993 thiz->mInstanceCount = 1; // ourself 994 thiz->mInstanceMask = 0; 995 thiz->mChangedMask = 0; 996 unsigned i; 997 for (i = 0; i < MAX_INSTANCE; ++i) { 998 thiz->mInstances[i] = NULL; 999 } 1000 thiz->mShutdown = SL_BOOLEAN_FALSE; 1001 thiz->mShutdownAck = SL_BOOLEAN_FALSE; 1002#if _BYTE_ORDER == _BIG_ENDIAN 1003 thiz->mNativeEndianness = SL_BYTEORDER_BIGENDIAN; 1004#else 1005 thiz->mNativeEndianness = SL_BYTEORDER_LITTLEENDIAN; 1006#endif 1007} 1008 1009void IEngine_deinit(void *self) 1010{ 1011} 1012 1013 1014// OpenMAX AL Engine 1015 1016 1017static XAresult IEngine_CreateCameraDevice(XAEngineItf self, XAObjectItf *pDevice, 1018 XAuint32 deviceID, XAuint32 numInterfaces, const XAInterfaceID *pInterfaceIds, 1019 const XAboolean *pInterfaceRequired) 1020{ 1021 XA_ENTER_INTERFACE 1022 1023 //IXAEngine *thiz = (IXAEngine *) self; 1024 result = SL_RESULT_FEATURE_UNSUPPORTED; 1025 1026 XA_LEAVE_INTERFACE 1027} 1028 1029 1030static XAresult IEngine_CreateRadioDevice(XAEngineItf self, XAObjectItf *pDevice, 1031 XAuint32 numInterfaces, const XAInterfaceID *pInterfaceIds, 1032 const XAboolean *pInterfaceRequired) 1033{ 1034 XA_ENTER_INTERFACE 1035 1036 //IXAEngine *thiz = (IXAEngine *) self; 1037 result = SL_RESULT_FEATURE_UNSUPPORTED; 1038 1039 XA_LEAVE_INTERFACE 1040} 1041 1042 1043static XAresult IXAEngine_CreateLEDDevice(XAEngineItf self, XAObjectItf *pDevice, XAuint32 deviceID, 1044 XAuint32 numInterfaces, const XAInterfaceID *pInterfaceIds, 1045 const XAboolean *pInterfaceRequired) 1046{ 1047 // forward to OpenSL ES 1048 return IEngine_CreateLEDDevice(&((CEngine *) ((IXAEngine *) self)->mThis)->mEngine.mItf, 1049 (SLObjectItf *) pDevice, deviceID, numInterfaces, (const SLInterfaceID *) pInterfaceIds, 1050 (const SLboolean *) pInterfaceRequired); 1051} 1052 1053 1054static XAresult IXAEngine_CreateVibraDevice(XAEngineItf self, XAObjectItf *pDevice, 1055 XAuint32 deviceID, XAuint32 numInterfaces, const XAInterfaceID *pInterfaceIds, 1056 const XAboolean *pInterfaceRequired) 1057{ 1058 // forward to OpenSL ES 1059 return IEngine_CreateVibraDevice(&((CEngine *) ((IXAEngine *) self)->mThis)->mEngine.mItf, 1060 (SLObjectItf *) pDevice, deviceID, numInterfaces, (const SLInterfaceID *) pInterfaceIds, 1061 (const SLboolean *) pInterfaceRequired); 1062} 1063 1064 1065static XAresult IEngine_CreateMediaPlayer(XAEngineItf self, XAObjectItf *pPlayer, 1066 XADataSource *pDataSrc, XADataSource *pBankSrc, XADataSink *pAudioSnk, 1067 XADataSink *pImageVideoSnk, XADataSink *pVibra, XADataSink *pLEDArray, 1068 XAuint32 numInterfaces, const XAInterfaceID *pInterfaceIds, 1069 const XAboolean *pInterfaceRequired) 1070{ 1071 XA_ENTER_INTERFACE 1072 1073 if (NULL == pPlayer) { 1074 result = XA_RESULT_PARAMETER_INVALID; 1075 } else { 1076 *pPlayer = NULL; 1077 unsigned exposedMask; 1078 const ClassTable *pCMediaPlayer_class = objectIDtoClass(XA_OBJECTID_MEDIAPLAYER); 1079 assert(NULL != pCMediaPlayer_class); 1080 result = checkInterfaces(pCMediaPlayer_class, numInterfaces, 1081 (const SLInterfaceID *) pInterfaceIds, pInterfaceRequired, &exposedMask, NULL); 1082 if (XA_RESULT_SUCCESS == result) { 1083 1084 // Construct our new MediaPlayer instance 1085 CMediaPlayer *thiz = (CMediaPlayer *) construct(pCMediaPlayer_class, exposedMask, 1086 &((CEngine *) ((IXAEngine *) self)->mThis)->mEngine.mItf); 1087 if (NULL == thiz) { 1088 result = XA_RESULT_MEMORY_FAILURE; 1089 } else { 1090 1091 do { 1092 1093 // Initialize private fields not associated with an interface 1094 1095 // Default data source in case of failure in checkDataSource 1096 thiz->mDataSource.mLocator.mLocatorType = SL_DATALOCATOR_NULL; 1097 thiz->mDataSource.mFormat.mFormatType = XA_DATAFORMAT_NULL; 1098 1099 // Default andio and image sink in case of failure in checkDataSink 1100 thiz->mAudioSink.mLocator.mLocatorType = XA_DATALOCATOR_NULL; 1101 thiz->mAudioSink.mFormat.mFormatType = XA_DATAFORMAT_NULL; 1102 thiz->mImageVideoSink.mLocator.mLocatorType = XA_DATALOCATOR_NULL; 1103 thiz->mImageVideoSink.mFormat.mFormatType = XA_DATAFORMAT_NULL; 1104 1105 // More default values, in case destructor needs to be called early 1106 thiz->mNumChannels = UNKNOWN_NUMCHANNELS; 1107 1108#ifdef ANDROID 1109 // placement new (explicit constructor) 1110 // FIXME unnecessary once those fields are encapsulated in one class, rather 1111 // than a structure 1112 (void) new (&thiz->mAVPlayer) android::sp<android::GenericPlayer>(); 1113 (void) new (&thiz->mCallbackProtector) 1114 android::sp<android::CallbackProtector>(); 1115 // Android-specific POD fields are initialized in android_Player_create, 1116 // and assume calloc or memset 0 during allocation 1117#endif 1118 1119 // Check the source and sink parameters against generic constraints 1120 1121 result = checkDataSource("pDataSrc", (const SLDataSource *) pDataSrc, 1122 &thiz->mDataSource, DATALOCATOR_MASK_URI 1123#ifdef ANDROID 1124 | DATALOCATOR_MASK_ANDROIDFD 1125 | DATALOCATOR_MASK_ANDROIDBUFFERQUEUE 1126#endif 1127 , DATAFORMAT_MASK_MIME); 1128 if (XA_RESULT_SUCCESS != result) { 1129 break; 1130 } 1131 1132 result = checkDataSource("pBankSrc", (const SLDataSource *) pBankSrc, 1133 &thiz->mBankSource, DATALOCATOR_MASK_NULL | DATALOCATOR_MASK_URI | 1134 DATALOCATOR_MASK_ADDRESS, DATAFORMAT_MASK_NULL); 1135 if (XA_RESULT_SUCCESS != result) { 1136 break; 1137 } 1138 1139 result = checkDataSink("pAudioSnk", (const SLDataSink *) pAudioSnk, 1140 &thiz->mAudioSink, DATALOCATOR_MASK_OUTPUTMIX, DATAFORMAT_MASK_NULL); 1141 if (XA_RESULT_SUCCESS != result) { 1142 break; 1143 } 1144 1145 result = checkDataSink("pImageVideoSnk", (const SLDataSink *) pImageVideoSnk, 1146 &thiz->mImageVideoSink, 1147 DATALOCATOR_MASK_NULL | DATALOCATOR_MASK_NATIVEDISPLAY, 1148 DATAFORMAT_MASK_NULL); 1149 if (XA_RESULT_SUCCESS != result) { 1150 break; 1151 } 1152 1153 result = checkDataSink("pVibra", (const SLDataSink *) pVibra, &thiz->mVibraSink, 1154 DATALOCATOR_MASK_NULL | DATALOCATOR_MASK_IODEVICE, 1155 DATAFORMAT_MASK_NULL); 1156 if (XA_RESULT_SUCCESS != result) { 1157 break; 1158 } 1159 1160 result = checkDataSink("pLEDArray", (const SLDataSink *) pLEDArray, 1161 &thiz->mLEDArraySink, DATALOCATOR_MASK_NULL | DATALOCATOR_MASK_IODEVICE, 1162 DATAFORMAT_MASK_NULL); 1163 if (XA_RESULT_SUCCESS != result) { 1164 break; 1165 } 1166 1167 // Unsafe to ever refer to application pointers again 1168 pDataSrc = NULL; 1169 pBankSrc = NULL; 1170 pAudioSnk = NULL; 1171 pImageVideoSnk = NULL; 1172 pVibra = NULL; 1173 pLEDArray = NULL; 1174 1175 // Check that the requested interfaces are compatible with the data source 1176 // FIXME implement 1177 1178 // check the source and sink parameters against platform support 1179#ifdef ANDROID 1180 result = android_Player_checkSourceSink(thiz); 1181 if (XA_RESULT_SUCCESS != result) { 1182 break; 1183 } 1184#endif 1185 1186#ifdef ANDROID 1187 // AndroidBufferQueue-specific initialization 1188 if (XA_DATALOCATOR_ANDROIDBUFFERQUEUE == 1189 thiz->mDataSource.mLocator.mLocatorType) { 1190 XAuint16 nbBuffers = (XAuint16) thiz->mDataSource.mLocator.mABQ.numBuffers; 1191 1192 // Avoid possible integer overflow during multiplication; this arbitrary 1193 // maximum is big enough to not interfere with real applications, but 1194 // small enough to not overflow. 1195 if (nbBuffers >= 256) { 1196 result = SL_RESULT_MEMORY_FAILURE; 1197 break; 1198 } 1199 1200 // initialize ABQ buffer type 1201 // assert below has been checked in android_audioPlayer_checkSourceSink 1202 assert(XA_DATAFORMAT_MIME == thiz->mDataSource.mFormat.mFormatType); 1203 if (XA_CONTAINERTYPE_MPEG_TS == 1204 thiz->mDataSource.mFormat.mMIME.containerType) { 1205 thiz->mAndroidBufferQueue.mBufferType = kAndroidBufferTypeMpeg2Ts; 1206 1207 // Set the container type for the StreamInformation interface 1208 XAMediaContainerInformation *containerInfo = 1209 (XAMediaContainerInformation*) 1210 // always storing container info at index 0, as per spec 1211 &thiz->mStreamInfo.mStreamInfoTable.itemAt(0).containerInfo; 1212 containerInfo->containerType = XA_CONTAINERTYPE_MPEG_TS; 1213 // there are no streams at this stage 1214 containerInfo->numStreams = 0; 1215 1216 } else { 1217 thiz->mAndroidBufferQueue.mBufferType = kAndroidBufferTypeInvalid; 1218 SL_LOGE("Invalid buffer type in Android Buffer Queue"); 1219 result = SL_RESULT_CONTENT_UNSUPPORTED; 1220 } 1221 1222 // initialize ABQ memory 1223 thiz->mAndroidBufferQueue.mBufferArray = (AdvancedBufferHeader *) 1224 malloc( (nbBuffers + 1) * sizeof(AdvancedBufferHeader)); 1225 if (NULL == thiz->mAndroidBufferQueue.mBufferArray) { 1226 result = SL_RESULT_MEMORY_FAILURE; 1227 break; 1228 } else { 1229 thiz->mAndroidBufferQueue.mFront = 1230 thiz->mAndroidBufferQueue.mBufferArray; 1231 thiz->mAndroidBufferQueue.mRear = 1232 thiz->mAndroidBufferQueue.mBufferArray; 1233 } 1234 1235 thiz->mAndroidBufferQueue.mNumBuffers = nbBuffers; 1236 1237 } 1238#endif 1239 1240 // used to store the data source of our audio player 1241 thiz->mDynamicSource.mDataSource = &thiz->mDataSource.u.mSource; 1242 1243 // platform-specific initialization 1244#ifdef ANDROID 1245 android_Player_create(thiz); 1246#endif 1247 1248 } while (0); 1249 1250 if (XA_RESULT_SUCCESS != result) { 1251 IObject_Destroy(&thiz->mObject.mItf); 1252 } else { 1253 IObject_Publish(&thiz->mObject); 1254 // return the new media player object 1255 *pPlayer = (XAObjectItf) &thiz->mObject.mItf; 1256 } 1257 1258 } 1259 } 1260 1261 } 1262 1263 XA_LEAVE_INTERFACE 1264} 1265 1266 1267static XAresult IEngine_CreateMediaRecorder(XAEngineItf self, XAObjectItf *pRecorder, 1268 XADataSource *pAudioSrc, XADataSource *pImageVideoSrc, 1269 XADataSink *pDataSnk, XAuint32 numInterfaces, const XAInterfaceID *pInterfaceIds, 1270 const XAboolean *pInterfaceRequired) 1271{ 1272 XA_ENTER_INTERFACE 1273 1274 //IXAEngine *thiz = (IXAEngine *) self; 1275 result = SL_RESULT_FEATURE_UNSUPPORTED; 1276 1277#if 0 1278 "pAudioSrc", pAudioSrc, 1279 "pImageVideoSrc", pImageVideoSrc, 1280 "pDataSink", pDataSnk, 1281#endif 1282 1283 XA_LEAVE_INTERFACE 1284} 1285 1286 1287static XAresult IXAEngine_CreateOutputMix(XAEngineItf self, XAObjectItf *pMix, 1288 XAuint32 numInterfaces, const XAInterfaceID *pInterfaceIds, 1289 const XAboolean *pInterfaceRequired) 1290{ 1291 // forward to OpenSL ES 1292 return IEngine_CreateOutputMix(&((CEngine *) ((IXAEngine *) self)->mThis)->mEngine.mItf, 1293 (SLObjectItf *) pMix, numInterfaces, (const SLInterfaceID *) pInterfaceIds, 1294 (const SLboolean *) pInterfaceRequired); 1295} 1296 1297 1298static XAresult IXAEngine_CreateMetadataExtractor(XAEngineItf self, XAObjectItf *pMetadataExtractor, 1299 XADataSource *pDataSource, XAuint32 numInterfaces, 1300 const XAInterfaceID *pInterfaceIds, const XAboolean *pInterfaceRequired) 1301{ 1302 // forward to OpenSL ES 1303 return IEngine_CreateMetadataExtractor(&((CEngine *) ((IXAEngine *) self)->mThis)->mEngine.mItf, 1304 (SLObjectItf *) pMetadataExtractor, (SLDataSource *) pDataSource, numInterfaces, 1305 (const SLInterfaceID *) pInterfaceIds, (const SLboolean *) pInterfaceRequired); 1306} 1307 1308 1309static XAresult IXAEngine_CreateExtensionObject(XAEngineItf self, XAObjectItf *pObject, 1310 void *pParameters, XAuint32 objectID, XAuint32 numInterfaces, 1311 const XAInterfaceID *pInterfaceIds, const XAboolean *pInterfaceRequired) 1312{ 1313 // forward to OpenSL ES 1314 return IEngine_CreateExtensionObject(&((CEngine *) ((IXAEngine *) self)->mThis)->mEngine.mItf, 1315 (SLObjectItf *) pObject, pParameters, objectID, numInterfaces, 1316 (const SLInterfaceID *) pInterfaceIds, (const SLboolean *) pInterfaceRequired); 1317} 1318 1319 1320static XAresult IEngine_GetImplementationInfo(XAEngineItf self, XAuint32 *pMajor, XAuint32 *pMinor, 1321 XAuint32 *pStep, /* XAuint32 nImplementationTextSize, */ const XAchar *pImplementationText) 1322{ 1323 XA_ENTER_INTERFACE 1324 1325 //IXAEngine *thiz = (IXAEngine *) self; 1326 result = SL_RESULT_FEATURE_UNSUPPORTED; 1327 1328 XA_LEAVE_INTERFACE 1329} 1330 1331 1332static XAresult IXAEngine_QuerySupportedProfiles(XAEngineItf self, XAint16 *pProfilesSupported) 1333{ 1334 XA_ENTER_INTERFACE 1335 1336 if (NULL == pProfilesSupported) { 1337 result = XA_RESULT_PARAMETER_INVALID; 1338 } else { 1339#if 1 1340 *pProfilesSupported = 0; 1341 // the code below was copied from OpenSL ES and needs to be adapted for OpenMAX AL. 1342#else 1343 // The generic implementation doesn't implement any of the profiles, they shouldn't be 1344 // declared as supported. Also exclude the fake profiles BASE and OPTIONAL. 1345 *pProfilesSupported = USE_PROFILES & 1346 (USE_PROFILES_GAME | USE_PROFILES_MUSIC | USE_PROFILES_PHONE); 1347#endif 1348 result = XA_RESULT_SUCCESS; 1349 } 1350 1351 XA_LEAVE_INTERFACE 1352} 1353 1354 1355static XAresult IXAEngine_QueryNumSupportedInterfaces(XAEngineItf self, XAuint32 objectID, 1356 XAuint32 *pNumSupportedInterfaces) 1357{ 1358 // forward to OpenSL ES 1359 return IEngine_QueryNumSupportedInterfaces( 1360 &((CEngine *) ((IXAEngine *) self)->mThis)->mEngine.mItf, objectID, 1361 pNumSupportedInterfaces); 1362} 1363 1364 1365static XAresult IXAEngine_QuerySupportedInterfaces(XAEngineItf self, XAuint32 objectID, 1366 XAuint32 index, XAInterfaceID *pInterfaceId) 1367{ 1368 // forward to OpenSL ES 1369 return IEngine_QuerySupportedInterfaces( 1370 &((CEngine *) ((IXAEngine *) self)->mThis)->mEngine.mItf, objectID, index, 1371 (SLInterfaceID *) pInterfaceId); 1372} 1373 1374 1375static XAresult IXAEngine_QueryNumSupportedExtensions(XAEngineItf self, XAuint32 *pNumExtensions) 1376{ 1377 // forward to OpenSL ES 1378 return IEngine_QueryNumSupportedExtensions( 1379 &((CEngine *) ((IXAEngine *) self)->mThis)->mEngine.mItf, pNumExtensions); 1380} 1381 1382 1383static XAresult IXAEngine_QuerySupportedExtension(XAEngineItf self, XAuint32 index, 1384 XAchar *pExtensionName, XAint16 *pNameLength) 1385{ 1386 // forward to OpenSL ES 1387 return IEngine_QuerySupportedExtension(&((CEngine *) ((IXAEngine *) self)->mThis)->mEngine.mItf, 1388 index, pExtensionName, (SLint16 *) pNameLength); 1389} 1390 1391 1392static XAresult IXAEngine_IsExtensionSupported(XAEngineItf self, const XAchar *pExtensionName, 1393 XAboolean *pSupported) 1394{ 1395 // forward to OpenSL ES 1396 return IEngine_IsExtensionSupported(&((CEngine *) ((IXAEngine *) self)->mThis)->mEngine.mItf, 1397 pExtensionName, pSupported); 1398} 1399 1400 1401static XAresult IXAEngine_QueryLEDCapabilities(XAEngineItf self, XAuint32 *pIndex, 1402 XAuint32 *pLEDDeviceID, XALEDDescriptor *pDescriptor) 1403{ 1404 // forward to OpenSL ES EngineCapabilities 1405 return (XAresult) IEngineCapabilities_QueryLEDCapabilities( 1406 &((CEngine *) ((IXAEngine *) self)->mThis)->mEngineCapabilities.mItf, pIndex, 1407 pLEDDeviceID, (SLLEDDescriptor *) pDescriptor); 1408} 1409 1410 1411static XAresult IXAEngine_QueryVibraCapabilities(XAEngineItf self, XAuint32 *pIndex, 1412 XAuint32 *pVibraDeviceID, XAVibraDescriptor *pDescriptor) 1413{ 1414 // forward to OpenSL ES EngineCapabilities 1415 return (XAresult) IEngineCapabilities_QueryVibraCapabilities( 1416 &((CEngine *) ((IXAEngine *) self)->mThis)->mEngineCapabilities.mItf, pIndex, 1417 pVibraDeviceID, (SLVibraDescriptor *) pDescriptor); 1418} 1419 1420 1421// OpenMAX AL engine v-table 1422 1423static const struct XAEngineItf_ IXAEngine_Itf = { 1424 IEngine_CreateCameraDevice, 1425 IEngine_CreateRadioDevice, 1426 IXAEngine_CreateLEDDevice, 1427 IXAEngine_CreateVibraDevice, 1428 IEngine_CreateMediaPlayer, 1429 IEngine_CreateMediaRecorder, 1430 IXAEngine_CreateOutputMix, 1431 IXAEngine_CreateMetadataExtractor, 1432 IXAEngine_CreateExtensionObject, 1433 IEngine_GetImplementationInfo, 1434 IXAEngine_QuerySupportedProfiles, 1435 IXAEngine_QueryNumSupportedInterfaces, 1436 IXAEngine_QuerySupportedInterfaces, 1437 IXAEngine_QueryNumSupportedExtensions, 1438 IXAEngine_QuerySupportedExtension, 1439 IXAEngine_IsExtensionSupported, 1440 IXAEngine_QueryLEDCapabilities, 1441 IXAEngine_QueryVibraCapabilities 1442}; 1443 1444 1445void IXAEngine_init(void *self) 1446{ 1447 IXAEngine *thiz = (IXAEngine *) self; 1448 thiz->mItf = &IXAEngine_Itf; 1449} 1450 1451 1452void IXAEngine_deinit(void *self) 1453{ 1454} 1455