IOutputMixExt.cpp revision 6a357b8fa57b0bc1557cd5ab9f9fb86aabaaa18c
1b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten/* 2b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten * Copyright (C) 2010 The Android Open Source Project 3b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten * 4b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten * Licensed under the Apache License, Version 2.0 (the "License"); 5b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten * you may not use this file except in compliance with the License. 6b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten * You may obtain a copy of the License at 7b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten * 8b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten * http://www.apache.org/licenses/LICENSE-2.0 9b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten * 10b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten * Unless required by applicable law or agreed to in writing, software 11b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten * distributed under the License is distributed on an "AS IS" BASIS, 12b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten * See the License for the specific language governing permissions and 14b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten * limitations under the License. 15b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten */ 16b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten 17b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten/* OutputMixExt implementation */ 18b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten 19b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten#include "sles_allinclusive.h" 20b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten 21b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten#ifdef USE_OUTPUTMIXEXT 22b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten 23276cab2d983b892d1b634474b6249f6bec400c76Glenn Kasten#include <math.h> 24276cab2d983b892d1b634474b6249f6bec400c76Glenn Kasten 25b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten// Used by SDL but not specific to or dependent on SDL 26b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten 27b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kastenstatic void IOutputMixExt_FillBuffer(SLOutputMixExtItf self, void *pBuffer, SLuint32 size) 28b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten{ 29b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten // Force to be a multiple of a frame, assumes stereo 16-bit PCM 30b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten size &= ~3; 31daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten IOutputMixExt *thisExt = (IOutputMixExt *) self; 32d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten IOutputMix *this = &((COutputMix *) InterfaceToIObject(thisExt))->mOutputMix; 33b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten unsigned activeMask = this->mActiveMask; 34b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten SLboolean mixBufferHasData = SL_BOOLEAN_FALSE; 35d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten while (activeMask) { 36d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten unsigned i = ctz(activeMask); 37d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten assert(MAX_TRACK > i); 38d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten activeMask &= ~(1 << i); 39d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten struct Track *track = &this->mTracks[i]; 40b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten // track is allocated 41276cab2d983b892d1b634474b6249f6bec400c76Glenn Kasten CAudioPlayer *audioPlayer = track->mAudioPlayer; 42276cab2d983b892d1b634474b6249f6bec400c76Glenn Kasten if (NULL == audioPlayer) 43b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten continue; 44b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten // track is initialized 45276cab2d983b892d1b634474b6249f6bec400c76Glenn Kasten if (SL_PLAYSTATE_PLAYING != audioPlayer->mPlay.mState) 46b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten continue; 47b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten // track is playing 48b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten void *dstWriter = pBuffer; 49b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten unsigned desired = size; 50b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten SLboolean trackContributedToMix = SL_BOOLEAN_FALSE; 513a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kasten IBufferQueue *bufferQueue = track->mBufferQueue; 52276cab2d983b892d1b634474b6249f6bec400c76Glenn Kasten // should compute elsewhere 53276cab2d983b892d1b634474b6249f6bec400c76Glenn Kasten double gains[2]; 546a357b8fa57b0bc1557cd5ab9f9fb86aabaaa18cGlenn Kasten if (audioPlayer->mVolume.mMute || !(~audioPlayer->mMuteSolo.mMuteMask & 3)) { 556a357b8fa57b0bc1557cd5ab9f9fb86aabaaa18cGlenn Kasten gains[0] = 0.0; 566a357b8fa57b0bc1557cd5ab9f9fb86aabaaa18cGlenn Kasten gains[1] = 0.0; 576a357b8fa57b0bc1557cd5ab9f9fb86aabaaa18cGlenn Kasten } else { 586a357b8fa57b0bc1557cd5ab9f9fb86aabaaa18cGlenn Kasten double playerVolume = pow(10.0, audioPlayer->mVolume.mLevel / 2000.0); 596a357b8fa57b0bc1557cd5ab9f9fb86aabaaa18cGlenn Kasten SLboolean enableStereoPosition = audioPlayer->mVolume.mEnableStereoPosition; 606a357b8fa57b0bc1557cd5ab9f9fb86aabaaa18cGlenn Kasten SLpermille stereoPosition = audioPlayer->mVolume.mStereoPosition; 616a357b8fa57b0bc1557cd5ab9f9fb86aabaaa18cGlenn Kasten if (audioPlayer->mMuteSolo.mMuteMask & 1) 626a357b8fa57b0bc1557cd5ab9f9fb86aabaaa18cGlenn Kasten gains[0] = 0.0; 636a357b8fa57b0bc1557cd5ab9f9fb86aabaaa18cGlenn Kasten else { 646a357b8fa57b0bc1557cd5ab9f9fb86aabaaa18cGlenn Kasten gains[0] = playerVolume; 656a357b8fa57b0bc1557cd5ab9f9fb86aabaaa18cGlenn Kasten if (enableStereoPosition && stereoPosition < 0) 666a357b8fa57b0bc1557cd5ab9f9fb86aabaaa18cGlenn Kasten gains[0] *= -stereoPosition / 1000.0; 676a357b8fa57b0bc1557cd5ab9f9fb86aabaaa18cGlenn Kasten } 686a357b8fa57b0bc1557cd5ab9f9fb86aabaaa18cGlenn Kasten if (audioPlayer->mMuteSolo.mMuteMask & 2) 696a357b8fa57b0bc1557cd5ab9f9fb86aabaaa18cGlenn Kasten gains[1] = 0.0; 706a357b8fa57b0bc1557cd5ab9f9fb86aabaaa18cGlenn Kasten else { 716a357b8fa57b0bc1557cd5ab9f9fb86aabaaa18cGlenn Kasten gains[1] = playerVolume; 726a357b8fa57b0bc1557cd5ab9f9fb86aabaaa18cGlenn Kasten if (enableStereoPosition && stereoPosition > 0) 736a357b8fa57b0bc1557cd5ab9f9fb86aabaaa18cGlenn Kasten gains[1] *= stereoPosition / 1000.0; 746a357b8fa57b0bc1557cd5ab9f9fb86aabaaa18cGlenn Kasten } 756a357b8fa57b0bc1557cd5ab9f9fb86aabaaa18cGlenn Kasten } 76b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten while (desired > 0) { 77d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten const BufferHeader *oldFront, *newFront, *rear; 78b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten unsigned actual = desired; 79b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten if (track->mAvail < actual) 80b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten actual = track->mAvail; 81b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten // force actual to be a frame multiple 82b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten if (actual > 0) { 836a357b8fa57b0bc1557cd5ab9f9fb86aabaaa18cGlenn Kasten // FIXME check for gain 0 in which case skip the input buffer processing 84b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten assert(NULL != track->mReader); 85276cab2d983b892d1b634474b6249f6bec400c76Glenn Kasten stereo *mixBuffer = (stereo *) dstWriter; 86276cab2d983b892d1b634474b6249f6bec400c76Glenn Kasten const stereo *source = (const stereo *) track->mReader; 87276cab2d983b892d1b634474b6249f6bec400c76Glenn Kasten unsigned j; 88b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten if (mixBufferHasData) { 89276cab2d983b892d1b634474b6249f6bec400c76Glenn Kasten for (j = 0; j < actual; j += sizeof(stereo), ++mixBuffer, ++source) { 90276cab2d983b892d1b634474b6249f6bec400c76Glenn Kasten mixBuffer->left += (short) (source->left * gains[0]); 91276cab2d983b892d1b634474b6249f6bec400c76Glenn Kasten mixBuffer->right += (short) (source->right * gains[1]); 92b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten } 936a357b8fa57b0bc1557cd5ab9f9fb86aabaaa18cGlenn Kasten } else if (gains[0] >= 0.999 && gains[1] >= 0.999) { 94276cab2d983b892d1b634474b6249f6bec400c76Glenn Kasten // no gain adjustment needed, so do a simple copy 95276cab2d983b892d1b634474b6249f6bec400c76Glenn Kasten memcpy(dstWriter, track->mReader, actual); 96276cab2d983b892d1b634474b6249f6bec400c76Glenn Kasten trackContributedToMix = SL_BOOLEAN_TRUE; 97b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten } else { 98daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten // apply gain during copy 99276cab2d983b892d1b634474b6249f6bec400c76Glenn Kasten for (j = 0; j < actual; j += sizeof(stereo), ++mixBuffer, ++source) { 100276cab2d983b892d1b634474b6249f6bec400c76Glenn Kasten mixBuffer->left = (short) (source->left * gains[0]); 101276cab2d983b892d1b634474b6249f6bec400c76Glenn Kasten mixBuffer->right = (short) (source->right * gains[1]); 102276cab2d983b892d1b634474b6249f6bec400c76Glenn Kasten } 103b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten trackContributedToMix = SL_BOOLEAN_TRUE; 104b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten } 105b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten dstWriter = (char *) dstWriter + actual; 106b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten desired -= actual; 107b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten track->mReader = (char *) track->mReader + actual; 108b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten track->mAvail -= actual; 109b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten if (track->mAvail == 0) { 110b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten if (NULL != bufferQueue) { 1113a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kasten interface_lock_exclusive(bufferQueue); 112b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten oldFront = bufferQueue->mFront; 113b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten rear = bufferQueue->mRear; 114b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten assert(oldFront != rear); 115b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten newFront = oldFront; 116d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten if (++newFront == &bufferQueue->mArray[bufferQueue->mNumBuffers + 1]) 117b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten newFront = bufferQueue->mArray; 118d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten bufferQueue->mFront = (BufferHeader *) newFront; 119b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten assert(0 < bufferQueue->mState.count); 120b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten --bufferQueue->mState.count; 121b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten // FIXME here or in Enqueue? 122b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten ++bufferQueue->mState.playIndex; 1233a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kasten interface_unlock_exclusive(bufferQueue); 124b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten // FIXME a good time to do an early warning 125b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten // callback depending on buffer count 126b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten } 127b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten } 128b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten continue; 129b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten } 130b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten // actual == 0 131b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten if (NULL != bufferQueue) { 1323a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kasten interface_lock_shared(bufferQueue); 133b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten oldFront = bufferQueue->mFront; 134b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten rear = bufferQueue->mRear; 135b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten if (oldFront != rear) { 136b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kastengot_one: 137b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten assert(0 < bufferQueue->mState.count); 138b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten track->mReader = oldFront->mBuffer; 139b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten track->mAvail = oldFront->mSize; 1403a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kasten interface_unlock_shared(bufferQueue); 141b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten continue; 142b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten } 143b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten // FIXME should be able to configure when to 144b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten // kick off the callback e.g. high/low water-marks etc. 145b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten // need data but none available, attempt a desperate callback 146b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten slBufferQueueCallback callback = bufferQueue->mCallback; 1473a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kasten void *context = bufferQueue->mContext; 1483a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kasten interface_unlock_shared(bufferQueue); 149b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten if (NULL != callback) { 1503a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kasten (*callback)((SLBufferQueueItf) bufferQueue, context); 151b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten // if lucky, the callback enqueued a buffer 1523a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kasten interface_lock_shared(bufferQueue); 153b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten if (rear != bufferQueue->mRear) 154b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten goto got_one; 1553a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kasten interface_unlock_shared(bufferQueue); 156b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten // unlucky, queue still empty, the callback failed 157b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten } 158b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten // here on underflow due to no callback, or failed callback 159b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten // FIXME underflow, send silence (or previous buffer?) 160b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten // we did a callback to try to kick start again but failed 161b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten // should log this 162b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten } 163b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten // no buffer queue or underflow, clear out rest of partial buffer 164b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten if (!mixBufferHasData && trackContributedToMix) 165b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten memset(dstWriter, 0, actual); 166b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten break; 167b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten } 168b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten if (trackContributedToMix) 169b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten mixBufferHasData = SL_BOOLEAN_TRUE; 170b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten } 171b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten // No active tracks, so output silence 172b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten if (!mixBufferHasData) 173b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten memset(pBuffer, 0, size); 174b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten} 175b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten 176b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kastenstatic const struct SLOutputMixExtItf_ IOutputMixExt_Itf = { 177b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten IOutputMixExt_FillBuffer 178b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten}; 179b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten 180b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kastenvoid IOutputMixExt_init(void *self) 181b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten{ 182b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten IOutputMixExt *this = (IOutputMixExt *) self; 183b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten this->mItf = &IOutputMixExt_Itf; 184b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten} 185b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten 186acd88797a1d3b8225bab888d29036e245f275be5Glenn KastenSLresult IOutputMixExt_checkAudioPlayerSourceSink(CAudioPlayer *this) 187daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten{ 188acd88797a1d3b8225bab888d29036e245f275be5Glenn Kasten const SLDataSink *pAudioSnk = &this->mDataSink.u.mSink; 189daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten struct Track *track = NULL; 190daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten switch (*(SLuint32 *)pAudioSnk->pLocator) { 191daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten case SL_DATALOCATOR_OUTPUTMIX: 192daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten { 193daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten // pAudioSnk->pFormat is ignored 194daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten IOutputMix *om = &((COutputMix *) ((SLDataLocator_OutputMix *) pAudioSnk->pLocator)->outputMix)->mOutputMix; 195daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten // allocate an entry within OutputMix for this track 196d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten interface_lock_exclusive(om); 197d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten unsigned availMask = ~om->mActiveMask; 198d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten if (!availMask) { 199d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten interface_unlock_exclusive(om); 200d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten // All track slots full in output mix 201daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten return SL_RESULT_MEMORY_FAILURE; 202daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten } 203d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten unsigned i = ctz(availMask); 204d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten assert(MAX_TRACK > i); 205d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten om->mActiveMask |= 1 << i; 206d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten track = &om->mTracks[i]; 207276cab2d983b892d1b634474b6249f6bec400c76Glenn Kasten track->mAudioPlayer = NULL; // only field that is accessed before full initialization 208d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten interface_unlock_exclusive(om); 209daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten } 210daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten break; 211daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten default: 212daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten return SL_RESULT_CONTENT_UNSUPPORTED; 213daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten } 214daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten 215d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten // FIXME Wrong place for this initialization; should first pre-allocate a track slot 216d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten // using OutputMixExt.mTrackCount, then initialize full audio player, then do track bit 217d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten // allocation, initialize rest of track, and doubly-link track to player (currently single). 218d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten assert(NULL != track); 219acd88797a1d3b8225bab888d29036e245f275be5Glenn Kasten track->mBufferQueue = &this->mBufferQueue; 220276cab2d983b892d1b634474b6249f6bec400c76Glenn Kasten track->mAudioPlayer = this; 221acd88797a1d3b8225bab888d29036e245f275be5Glenn Kasten track->mReader = NULL; 222acd88797a1d3b8225bab888d29036e245f275be5Glenn Kasten track->mAvail = 0; 2236a357b8fa57b0bc1557cd5ab9f9fb86aabaaa18cGlenn Kasten //track->mGains[0] = 0; 2246a357b8fa57b0bc1557cd5ab9f9fb86aabaaa18cGlenn Kasten //track->mGains[1] = 0; 225daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten return SL_RESULT_SUCCESS; 226daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten} 227daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten 228b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten#endif // USE_OUTPUTMIXEXT 229