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