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 /* OpenSL ES private and global functions not associated with an interface or class */
18
19 #include "sles_allinclusive.h"
20
21
22 /** \brief Return true if the specified interface exists and has been initialized for this object.
23 * Returns false if the class does not support this kind of interface, or the class supports the
24 * interface but this particular object has not had the interface exposed at object creation time
25 * or by DynamicInterface::AddInterface. Note that the return value is not affected by whether
26 * the application has requested access to the interface with Object::GetInterface. Assumes on
27 * entry that the object is locked for either shared or exclusive access.
28 */
29
IsInterfaceInitialized(IObject * thiz,unsigned MPH)30 bool IsInterfaceInitialized(IObject *thiz, unsigned MPH)
31 {
32 assert(NULL != thiz);
33 assert( /* (MPH_MIN <= MPH) && */ (MPH < (unsigned) MPH_MAX));
34 const ClassTable *clazz = thiz->mClass;
35 assert(NULL != clazz);
36 int index;
37 if (0 > (index = clazz->mMPH_to_index[MPH])) {
38 return false;
39 }
40 assert(MAX_INDEX >= clazz->mInterfaceCount);
41 assert(clazz->mInterfaceCount > (unsigned) index);
42 switch (thiz->mInterfaceStates[index]) {
43 case INTERFACE_EXPOSED:
44 case INTERFACE_ADDED:
45 return true;
46 default:
47 return false;
48 }
49 }
50
51
52 /** \brief Map an IObject to it's "object ID" (which is really a class ID) */
53
IObjectToObjectID(IObject * thiz)54 SLuint32 IObjectToObjectID(IObject *thiz)
55 {
56 assert(NULL != thiz);
57 // Note this returns the OpenSL ES object ID in preference to the OpenMAX AL if both available
58 const ClassTable *clazz = thiz->mClass;
59 assert(NULL != clazz);
60 SLuint32 id = clazz->mSLObjectID;
61 if (!id) {
62 id = clazz->mXAObjectID;
63 }
64 return id;
65 }
66
67
68 /** \brief Acquire a strong reference to an object.
69 * Check that object has the specified "object ID" (which is really a class ID) and is in the
70 * realized state. If so, then acquire a strong reference to it and return true.
71 * Otherwise return false.
72 */
73
AcquireStrongRef(IObject * object,SLuint32 expectedObjectID)74 SLresult AcquireStrongRef(IObject *object, SLuint32 expectedObjectID)
75 {
76 if (NULL == object) {
77 return SL_RESULT_PARAMETER_INVALID;
78 }
79 // NTH additional validity checks on address here
80 SLresult result;
81 object_lock_exclusive(object);
82 SLuint32 actualObjectID = IObjectToObjectID(object);
83 if (expectedObjectID != actualObjectID) {
84 SL_LOGE("object %p has object ID %u but expected %u", object, actualObjectID,
85 expectedObjectID);
86 result = SL_RESULT_PARAMETER_INVALID;
87 } else if (SL_OBJECT_STATE_REALIZED != object->mState) {
88 SL_LOGE("object %p with object ID %u is not realized", object, actualObjectID);
89 result = SL_RESULT_PRECONDITIONS_VIOLATED;
90 } else {
91 ++object->mStrongRefCount;
92 result = SL_RESULT_SUCCESS;
93 }
94 object_unlock_exclusive(object);
95 return result;
96 }
97
98
99 /** \brief Release a strong reference to an object.
100 * Entry condition: the object is locked.
101 * Exit condition: the object is unlocked.
102 * Finishes the destroy if needed.
103 */
104
ReleaseStrongRefAndUnlockExclusive(IObject * object)105 void ReleaseStrongRefAndUnlockExclusive(IObject *object)
106 {
107 #ifdef USE_DEBUG
108 assert(pthread_equal(pthread_self(), object->mOwner));
109 #endif
110 assert(0 < object->mStrongRefCount);
111 if ((0 == --object->mStrongRefCount) && (SL_OBJECT_STATE_DESTROYING == object->mState)) {
112 // FIXME do the destroy here - merge with IDestroy
113 // but can't do this until we move Destroy to the sync thread
114 // as Destroy is now a blocking operation, and to avoid a race
115 } else {
116 object_unlock_exclusive(object);
117 }
118 }
119
120
121 /** \brief Release a strong reference to an object.
122 * Entry condition: the object is unlocked.
123 * Exit condition: the object is unlocked.
124 * Finishes the destroy if needed.
125 */
126
ReleaseStrongRef(IObject * object)127 void ReleaseStrongRef(IObject *object)
128 {
129 assert(NULL != object);
130 object_lock_exclusive(object);
131 ReleaseStrongRefAndUnlockExclusive(object);
132 }
133
134
135 /** \brief Convert POSIX pthread error code to OpenSL ES result code */
136
err_to_result(int err)137 SLresult err_to_result(int err)
138 {
139 if (EAGAIN == err || ENOMEM == err) {
140 return SL_RESULT_RESOURCE_ERROR;
141 }
142 if (0 != err) {
143 return SL_RESULT_INTERNAL_ERROR;
144 }
145 return SL_RESULT_SUCCESS;
146 }
147
148
149 /** \brief Check the interface IDs passed into a Create operation */
150
checkInterfaces(const ClassTable * clazz,SLuint32 numInterfaces,const SLInterfaceID * pInterfaceIds,const SLboolean * pInterfaceRequired,unsigned * pExposedMask,unsigned * pRequiredMask)151 SLresult checkInterfaces(const ClassTable *clazz, SLuint32 numInterfaces,
152 const SLInterfaceID *pInterfaceIds, const SLboolean *pInterfaceRequired,
153 unsigned *pExposedMask, unsigned *pRequiredMask)
154 {
155 assert(NULL != clazz && NULL != pExposedMask);
156 // Initially no interfaces are exposed
157 unsigned exposedMask = 0;
158 unsigned requiredMask = 0;
159 const struct iid_vtable *interfaces = clazz->mInterfaces;
160 SLuint32 interfaceCount = clazz->mInterfaceCount;
161 SLuint32 i;
162 // Expose all implicit interfaces
163 for (i = 0; i < interfaceCount; ++i) {
164 switch (interfaces[i].mInterface) {
165 case INTERFACE_IMPLICIT:
166 case INTERFACE_IMPLICIT_PREREALIZE:
167 // there must be an initialization hook present
168 if (NULL != MPH_init_table[interfaces[i].mMPH].mInit) {
169 exposedMask |= 1 << i;
170 }
171 break;
172 case INTERFACE_EXPLICIT:
173 case INTERFACE_DYNAMIC:
174 case INTERFACE_UNAVAILABLE:
175 case INTERFACE_EXPLICIT_PREREALIZE:
176 break;
177 default:
178 assert(false);
179 break;
180 }
181 }
182 if (0 < numInterfaces) {
183 if (NULL == pInterfaceIds || NULL == pInterfaceRequired) {
184 return SL_RESULT_PARAMETER_INVALID;
185 }
186 bool anyRequiredButUnsupported = false;
187 // Loop for each requested interface
188 for (i = 0; i < numInterfaces; ++i) {
189 SLInterfaceID iid = pInterfaceIds[i];
190 if (NULL == iid) {
191 return SL_RESULT_PARAMETER_INVALID;
192 }
193 SLboolean isRequired = pInterfaceRequired[i];
194 int MPH, index;
195 if ((0 > (MPH = IID_to_MPH(iid))) ||
196 // there must be an initialization hook present
197 (NULL == MPH_init_table[MPH].mInit) ||
198 (0 > (index = clazz->mMPH_to_index[MPH])) ||
199 (INTERFACE_UNAVAILABLE == interfaces[index].mInterface)) {
200 // Here if interface was not found, or is not available for this object type
201 if (isRequired) {
202 // Application said it required the interface, so give up
203 SL_LOGE("class %s interface %u required but unavailable MPH=%d",
204 clazz->mName, i, MPH);
205 anyRequiredButUnsupported = true;
206 }
207 // Application said it didn't really need the interface, so ignore with warning
208 SL_LOGW("class %s interface %u requested but unavailable MPH=%d",
209 clazz->mName, i, MPH);
210 continue;
211 }
212 if (isRequired) {
213 requiredMask |= (1 << index);
214 }
215 // The requested interface was both found and available, so expose it
216 exposedMask |= (1 << index);
217 // Note that we ignore duplicate requests, including equal and aliased IDs
218 }
219 if (anyRequiredButUnsupported) {
220 return SL_RESULT_FEATURE_UNSUPPORTED;
221 }
222 }
223 *pExposedMask = exposedMask;
224 if (NULL != pRequiredMask) {
225 *pRequiredMask = requiredMask;
226 }
227 return SL_RESULT_SUCCESS;
228 }
229
230
231 /* Interface initialization hooks */
232
233 extern void
234 I3DCommit_init(void *),
235 I3DDoppler_init(void *),
236 I3DGrouping_init(void *),
237 I3DLocation_init(void *),
238 I3DMacroscopic_init(void *),
239 I3DSource_init(void *),
240 IAndroidConfiguration_init(void *),
241 IAndroidEffect_init(void *),
242 IAndroidEffectCapabilities_init(void *),
243 IAndroidEffectSend_init(void *),
244 IAndroidBufferQueue_init(void *),
245 IAudioDecoderCapabilities_init(void *),
246 IAudioEncoder_init(void *),
247 IAudioEncoderCapabilities_init(void *),
248 IAudioIODeviceCapabilities_init(void *),
249 IBassBoost_init(void *),
250 IBufferQueue_init(void *),
251 IDeviceVolume_init(void *),
252 IDynamicInterfaceManagement_init(void *),
253 IDynamicSource_init(void *),
254 IEffectSend_init(void *),
255 IEngine_init(void *),
256 IEngineCapabilities_init(void *),
257 IEnvironmentalReverb_init(void *),
258 IEqualizer_init(void *),
259 ILEDArray_init(void *),
260 IMIDIMessage_init(void *),
261 IMIDIMuteSolo_init(void *),
262 IMIDITempo_init(void *),
263 IMIDITime_init(void *),
264 IMetadataExtraction_init(void *),
265 IMetadataTraversal_init(void *),
266 IMuteSolo_init(void *),
267 IObject_init(void *),
268 IOutputMix_init(void *),
269 IOutputMixExt_init(void *),
270 IPitch_init(void *),
271 IPlay_init(void *),
272 IPlaybackRate_init(void *),
273 IPrefetchStatus_init(void *),
274 IPresetReverb_init(void *),
275 IRatePitch_init(void *),
276 IRecord_init(void *),
277 ISeek_init(void *),
278 IThreadSync_init(void *),
279 IVibra_init(void *),
280 IVirtualizer_init(void *),
281 IVisualization_init(void *),
282 IVolume_init(void *);
283
284 extern void
285 I3DGrouping_deinit(void *),
286 IAndroidEffect_deinit(void *),
287 IAndroidEffectCapabilities_deinit(void *),
288 IAndroidBufferQueue_deinit(void *),
289 IBassBoost_deinit(void *),
290 IBufferQueue_deinit(void *),
291 IEngine_deinit(void *),
292 IEnvironmentalReverb_deinit(void *),
293 IEqualizer_deinit(void *),
294 IObject_deinit(void *),
295 IPresetReverb_deinit(void *),
296 IThreadSync_deinit(void *),
297 IVirtualizer_deinit(void *);
298
299 extern bool
300 IAndroidEffectCapabilities_Expose(void *),
301 IBassBoost_Expose(void *),
302 IEnvironmentalReverb_Expose(void *),
303 IEqualizer_Expose(void *),
304 IPresetReverb_Expose(void *),
305 IVirtualizer_Expose(void *);
306
307 extern void
308 IXAEngine_init(void *),
309 IStreamInformation_init(void*),
310 IVideoDecoderCapabilities_init(void *);
311
312 extern void
313 IXAEngine_deinit(void *),
314 IStreamInformation_deinit(void *),
315 IVideoDecoderCapabilities_deinit(void *);
316
317 extern bool
318 IVideoDecoderCapabilities_expose(void *);
319
320 #if !(USE_PROFILES & USE_PROFILES_MUSIC)
321 #define IDynamicSource_init NULL
322 #define IMetadataTraversal_init NULL
323 #define IVisualization_init NULL
324 #endif
325
326 #if !(USE_PROFILES & USE_PROFILES_GAME)
327 #define I3DCommit_init NULL
328 #define I3DDoppler_init NULL
329 #define I3DGrouping_init NULL
330 #define I3DLocation_init NULL
331 #define I3DMacroscopic_init NULL
332 #define I3DSource_init NULL
333 #define IMIDIMessage_init NULL
334 #define IMIDIMuteSolo_init NULL
335 #define IMIDITempo_init NULL
336 #define IMIDITime_init NULL
337 #define IPitch_init NULL
338 #define IRatePitch_init NULL
339 #define I3DGrouping_deinit NULL
340 #endif
341
342 #if !(USE_PROFILES & USE_PROFILES_BASE)
343 #define IAudioDecoderCapabilities_init NULL
344 #define IAudioEncoderCapabilities_init NULL
345 #define IAudioEncoder_init NULL
346 #define IAudioIODeviceCapabilities_init NULL
347 #define IDeviceVolume_init NULL
348 #define IEngineCapabilities_init NULL
349 #define IThreadSync_init NULL
350 #define IThreadSync_deinit NULL
351 #endif
352
353 #if !(USE_PROFILES & USE_PROFILES_OPTIONAL)
354 #define ILEDArray_init NULL
355 #define IVibra_init NULL
356 #endif
357
358 #ifndef ANDROID
359 #define IAndroidConfiguration_init NULL
360 #define IAndroidEffect_init NULL
361 #define IAndroidEffectCapabilities_init NULL
362 #define IAndroidEffectSend_init NULL
363 #define IAndroidEffect_deinit NULL
364 #define IAndroidEffectCapabilities_deinit NULL
365 #define IAndroidEffectCapabilities_Expose NULL
366 #define IAndroidBufferQueue_init NULL
367 #define IStreamInformation_init NULL
368 #define IAndroidBufferQueue_deinit NULL
369 #define IStreamInformation_deinit NULL
370 #endif
371
372 #ifndef USE_OUTPUTMIXEXT
373 #define IOutputMixExt_init NULL
374 #endif
375
376
377 /*static*/ const struct MPH_init MPH_init_table[MPH_MAX] = {
378 { /* MPH_3DCOMMIT, */ I3DCommit_init, NULL, NULL, NULL, NULL },
379 { /* MPH_3DDOPPLER, */ I3DDoppler_init, NULL, NULL, NULL, NULL },
380 { /* MPH_3DGROUPING, */ I3DGrouping_init, NULL, I3DGrouping_deinit, NULL, NULL },
381 { /* MPH_3DLOCATION, */ I3DLocation_init, NULL, NULL, NULL, NULL },
382 { /* MPH_3DMACROSCOPIC, */ I3DMacroscopic_init, NULL, NULL, NULL, NULL },
383 { /* MPH_3DSOURCE, */ I3DSource_init, NULL, NULL, NULL, NULL },
384 { /* MPH_AUDIODECODERCAPABILITIES, */ IAudioDecoderCapabilities_init, NULL, NULL, NULL, NULL },
385 { /* MPH_AUDIOENCODER, */ IAudioEncoder_init, NULL, NULL, NULL, NULL },
386 { /* MPH_AUDIOENCODERCAPABILITIES, */ IAudioEncoderCapabilities_init, NULL, NULL, NULL, NULL },
387 { /* MPH_AUDIOIODEVICECAPABILITIES, */ IAudioIODeviceCapabilities_init, NULL, NULL, NULL,
388 NULL },
389 { /* MPH_BASSBOOST, */ IBassBoost_init, NULL, IBassBoost_deinit, IBassBoost_Expose, NULL },
390 { /* MPH_BUFFERQUEUE, */ IBufferQueue_init, NULL, IBufferQueue_deinit, NULL, NULL },
391 { /* MPH_DEVICEVOLUME, */ IDeviceVolume_init, NULL, NULL, NULL, NULL },
392 { /* MPH_DYNAMICINTERFACEMANAGEMENT, */ IDynamicInterfaceManagement_init, NULL, NULL, NULL,
393 NULL },
394 { /* MPH_DYNAMICSOURCE, */ IDynamicSource_init, NULL, NULL, NULL, NULL },
395 { /* MPH_EFFECTSEND, */ IEffectSend_init, NULL, NULL, NULL, NULL },
396 { /* MPH_ENGINE, */ IEngine_init, NULL, IEngine_deinit, NULL, NULL },
397 { /* MPH_ENGINECAPABILITIES, */ IEngineCapabilities_init, NULL, NULL, NULL, NULL },
398 { /* MPH_ENVIRONMENTALREVERB, */ IEnvironmentalReverb_init, NULL, IEnvironmentalReverb_deinit,
399 IEnvironmentalReverb_Expose, NULL },
400 { /* MPH_EQUALIZER, */ IEqualizer_init, NULL, IEqualizer_deinit, IEqualizer_Expose, NULL },
401 { /* MPH_LED, */ ILEDArray_init, NULL, NULL, NULL, NULL },
402 { /* MPH_METADATAEXTRACTION, */ IMetadataExtraction_init, NULL, NULL, NULL, NULL },
403 { /* MPH_METADATATRAVERSAL, */ IMetadataTraversal_init, NULL, NULL, NULL, NULL },
404 { /* MPH_MIDIMESSAGE, */ IMIDIMessage_init, NULL, NULL, NULL, NULL },
405 { /* MPH_MIDITIME, */ IMIDITime_init, NULL, NULL, NULL, NULL },
406 { /* MPH_MIDITEMPO, */ IMIDITempo_init, NULL, NULL, NULL, NULL },
407 { /* MPH_MIDIMUTESOLO, */ IMIDIMuteSolo_init, NULL, NULL, NULL, NULL },
408 { /* MPH_MUTESOLO, */ IMuteSolo_init, NULL, NULL, NULL, NULL },
409 { /* MPH_NULL, */ NULL, NULL, NULL, NULL, NULL },
410 { /* MPH_OBJECT, */ IObject_init, NULL, IObject_deinit, NULL, NULL },
411 { /* MPH_OUTPUTMIX, */ IOutputMix_init, NULL, NULL, NULL, NULL },
412 { /* MPH_PITCH, */ IPitch_init, NULL, NULL, NULL, NULL },
413 { /* MPH_PLAY, */ IPlay_init, NULL, NULL, NULL, NULL },
414 { /* MPH_PLAYBACKRATE, */ IPlaybackRate_init, NULL, NULL, NULL, NULL },
415 { /* MPH_PREFETCHSTATUS, */ IPrefetchStatus_init, NULL, NULL, NULL, NULL },
416 { /* MPH_PRESETREVERB, */ IPresetReverb_init, NULL, IPresetReverb_deinit,
417 IPresetReverb_Expose, NULL },
418 { /* MPH_RATEPITCH, */ IRatePitch_init, NULL, NULL, NULL, NULL },
419 { /* MPH_RECORD, */ IRecord_init, NULL, NULL, NULL, NULL },
420 { /* MPH_SEEK, */ ISeek_init, NULL, NULL, NULL, NULL },
421 { /* MPH_THREADSYNC, */ IThreadSync_init, NULL, IThreadSync_deinit, NULL, NULL },
422 { /* MPH_VIBRA, */ IVibra_init, NULL, NULL, NULL, NULL },
423 { /* MPH_VIRTUALIZER, */ IVirtualizer_init, NULL, IVirtualizer_deinit, IVirtualizer_Expose,
424 NULL },
425 { /* MPH_VISUALIZATION, */ IVisualization_init, NULL, NULL, NULL, NULL },
426 { /* MPH_VOLUME, */ IVolume_init, NULL, NULL, NULL, NULL },
427 // Wilhelm desktop extended interfaces
428 { /* MPH_OUTPUTMIXEXT, */ IOutputMixExt_init, NULL, NULL, NULL, NULL },
429 // Android API level 9 extended interfaces
430 { /* MPH_ANDROIDEFFECT */ IAndroidEffect_init, NULL, IAndroidEffect_deinit, NULL, NULL },
431 { /* MPH_ANDROIDEFFECTCAPABILITIES */ IAndroidEffectCapabilities_init, NULL,
432 IAndroidEffectCapabilities_deinit, IAndroidEffectCapabilities_Expose, NULL },
433 { /* MPH_ANDROIDEFFECTSEND */ IAndroidEffectSend_init, NULL, NULL, NULL, NULL },
434 { /* MPH_ANDROIDCONFIGURATION */ IAndroidConfiguration_init, NULL, NULL, NULL, NULL },
435 { /* MPH_ANDROIDSIMPLEBUFFERQUEUE */ IBufferQueue_init /* alias */, NULL, NULL, NULL, NULL },
436 // Android API level 10 extended interfaces
437 { /* MPH_ANDROIDBUFFERQUEUESOURCE */ IAndroidBufferQueue_init, NULL, IAndroidBufferQueue_deinit,
438 NULL, NULL },
439 // OpenMAX AL 1.0.1 interfaces
440 { /* MPH_XAAUDIODECODERCAPABILITIES */ NULL, NULL, NULL, NULL, NULL },
441 { /* MPH_XAAUDIOENCODER */ NULL, NULL, NULL, NULL, NULL },
442 { /* MPH_XAAUDIOENCODERCAPABILITIES */ NULL, NULL, NULL, NULL, NULL },
443 { /* MPH_XAAUDIOIODEVICECAPABILITIES */ NULL, NULL, NULL, NULL, NULL },
444 { /* MPH_XACAMERA */ NULL, NULL, NULL, NULL, NULL },
445 { /* MPH_XACAMERACAPABILITIES */ NULL, NULL, NULL, NULL, NULL },
446 { /* MPH_XACONFIGEXTENSION */ NULL, NULL, NULL, NULL, NULL },
447 { /* MPH_XADEVICEVOLUME */ NULL, NULL, NULL, NULL, NULL },
448 { /* MPH_XADYNAMICINTERFACEMANAGEMENT 59 */ NULL, NULL, NULL, NULL, NULL },
449 { /* MPH_XADYNAMICSOURCE */ NULL, NULL, NULL, NULL, NULL },
450 { /* MPH_XAENGINE */ IXAEngine_init, NULL, IXAEngine_deinit, NULL, NULL },
451 { /* MPH_XAEQUALIZER */ NULL, NULL, NULL, NULL, NULL },
452 { /* MPH_XAIMAGECONTROLS */ NULL, NULL, NULL, NULL, NULL },
453 { /* MPH_XAIMAGEDECODERCAPABILITIES */ NULL, NULL, NULL, NULL, NULL },
454 { /* MPH_XAIMAGEEFFECTS */ NULL, NULL, NULL, NULL, NULL },
455 { /* MPH_XAIMAGEENCODER */ NULL, NULL, NULL, NULL, NULL },
456 { /* MPH_XAIMAGEENCODERCAPABILITIES */ NULL, NULL, NULL, NULL, NULL },
457 { /* MPH_XALED */ NULL, NULL, NULL, NULL, NULL },
458 { /* MPH_XAMETADATAEXTRACTION */ NULL, NULL, NULL, NULL, NULL },
459 { /* MPH_XAMETADATAINSERTION */ NULL, NULL, NULL, NULL, NULL },
460 { /* MPH_XAMETADATATRAVERSAL */ NULL, NULL, NULL, NULL, NULL },
461 // { /* MPH_XANULL */ NULL, NULL, NULL, NULL, NULL },
462 { /* MPH_XAOBJECT */ IObject_init, NULL, IObject_deinit, NULL, NULL },
463 { /* MPH_XAOUTPUTMIX */ NULL, NULL, NULL, NULL, NULL },
464 { /* MPH_XAPLAY */ IPlay_init, NULL, NULL, NULL, NULL },
465 { /* MPH_XAPLAYBACKRATE */ NULL, NULL, NULL, NULL, NULL },
466 { /* MPH_XAPREFETCHSTATUS, */ IPrefetchStatus_init, NULL, NULL, NULL, NULL },
467 { /* MPH_XARADIO */ NULL, NULL, NULL, NULL, NULL },
468 { /* MPH_XARDS */ NULL, NULL, NULL, NULL, NULL },
469 { /* MPH_XARECORD */ NULL, NULL, NULL, NULL, NULL },
470 { /* MPH_XASEEK */ ISeek_init, NULL, NULL, NULL, NULL },
471 { /* MPH_XASNAPSHOT */ NULL, NULL, NULL, NULL, NULL },
472 { /* MPH_XASTREAMINFORMATION */ IStreamInformation_init, NULL, IStreamInformation_deinit,
473 NULL, NULL },
474 { /* MPH_XATHREADSYNC */ NULL, NULL, NULL, NULL, NULL },
475 { /* MPH_XAVIBRA */ NULL, NULL, NULL, NULL, NULL },
476 { /* MPH_XAVIDEODECODERCAPABILITIES */ IVideoDecoderCapabilities_init, NULL,
477 IVideoDecoderCapabilities_deinit, IVideoDecoderCapabilities_expose, NULL },
478 { /* MPH_XAVIDEOENCODER */ NULL, NULL, NULL, NULL, NULL },
479 { /* MPH_XAVIDEOENCODERCAPABILITIES */ NULL, NULL, NULL, NULL, NULL },
480 { /* MPH_XAVIDEOPOSTPROCESSING */ NULL, NULL, NULL, NULL, NULL },
481 { /* MPH_XAVOLUME, */ IVolume_init, NULL, NULL, NULL, NULL },
482 };
483
484
485 /** \brief Construct a new instance of the specified class, exposing selected interfaces */
486
construct(const ClassTable * clazz,unsigned exposedMask,SLEngineItf engine)487 IObject *construct(const ClassTable *clazz, unsigned exposedMask, SLEngineItf engine)
488 {
489 IObject *thiz;
490 // Do not change this to malloc; we depend on the object being memset to zero
491 thiz = (IObject *) calloc(1, clazz->mSize);
492 if (NULL != thiz) {
493 SL_LOGV("construct %s at %p", clazz->mName, thiz);
494 unsigned lossOfControlMask = 0;
495 // a NULL engine means we are constructing the engine
496 IEngine *thisEngine = (IEngine *) engine;
497 if (NULL == thisEngine) {
498 // thisEngine = &((CEngine *) thiz)->mEngine;
499 thiz->mEngine = (CEngine *) thiz;
500 } else {
501 thiz->mEngine = (CEngine *) thisEngine->mThis;
502 interface_lock_exclusive(thisEngine);
503 if (MAX_INSTANCE <= thisEngine->mInstanceCount) {
504 SL_LOGE("Too many objects");
505 interface_unlock_exclusive(thisEngine);
506 free(thiz);
507 return NULL;
508 }
509 // pre-allocate a pending slot, but don't assign bit from mInstanceMask yet
510 ++thisEngine->mInstanceCount;
511 assert(((unsigned) ~0) != thisEngine->mInstanceMask);
512 interface_unlock_exclusive(thisEngine);
513 // const, no lock needed
514 if (thisEngine->mLossOfControlGlobal) {
515 lossOfControlMask = ~0;
516 }
517 }
518 thiz->mLossOfControlMask = lossOfControlMask;
519 thiz->mClass = clazz;
520 const struct iid_vtable *x = clazz->mInterfaces;
521 SLuint8 *interfaceStateP = thiz->mInterfaceStates;
522 SLuint32 index;
523 for (index = 0; index < clazz->mInterfaceCount; ++index, ++x, exposedMask >>= 1) {
524 SLuint8 state;
525 // initialize all interfaces with init hooks, even if not exposed
526 const struct MPH_init *mi = &MPH_init_table[x->mMPH];
527 VoidHook init = mi->mInit;
528 if (NULL != init) {
529 void *self = (char *) thiz + x->mOffset;
530 // IObject does not have an mThis, so [1] is not always defined
531 if (index) {
532 ((IObject **) self)[1] = thiz;
533 }
534 // call the initialization hook
535 (*init)(self);
536 // IObject does not require a call to GetInterface
537 if (index) {
538 // This trickery invalidates the v-table until GetInterface
539 ((size_t *) self)[0] ^= ~0;
540 }
541 // if interface is exposed, also call the optional expose hook
542 BoolHook expose;
543 state = (exposedMask & 1) && ((NULL == (expose = mi->mExpose)) || (*expose)(self)) ?
544 INTERFACE_EXPOSED : INTERFACE_INITIALIZED;
545 // FIXME log or report to application if an expose hook on a
546 // required explicit interface fails at creation time
547 } else {
548 state = INTERFACE_UNINITIALIZED;
549 }
550 *interfaceStateP++ = state;
551 }
552 // note that the new object is not yet published; creator must call IObject_Publish
553 }
554 return thiz;
555 }
556