status_t AudioTrack::createTrack_l(){ ..... //调用Flinger构造Track对象,关联track和NormChain,并返回TrackHand的句柄 sp<IAudioTrack> track = audioFlinger->createTrack(streamType, sampleRate, // AudioFlinger only sees 16-bit PCM format == AUDIO_FORMAT_PCM_8_BIT ? AUDIO_FORMAT_PCM_16_BIT : format, mChannelMask, frameCount, &trackFlags, sharedBuffer, output, tid, &mSessionId, mName, mClientUid, &status); mAuxEffectId = 0; //重置track和MixChain中的auxiliary effect对象之间的关联 mAudioTrack->attachAuxEffect(mAuxEffectId); ..... } //1、在所有线程中寻找包含AUDIO_SESSION_OUTPUT_MIX类型Chain的线程, // 传入的EffectId参数应该属于auxiliary类型的Effect,否则Attch会失败 //2、将该effect插入到该track所在的线程AUDIO_SESSION_OUTPUT_MIX类型Chain中 //3、当effectId==0时,相当于断开与该track关联的auxiliary effect,无音效 //4、auxiliary effect只存在于AUDIO_SESSION_OUTPUT_MIX类型的Chain中 //5、每个track的数据只会由一个auxiliary effect进行处理,之后会输出到MixBuff // 其对应关系: // Mix Chain(1)--(n)Auxiliary effect(1)--(1)Track //or Norm Chain(1)--(n)Inset effect(n)--(1)Track //数据流: // Track->AuxBuff->Mix Chain(Auxiliary Effect)->mMixBuff //or Track->NormBuff->Norm Chain(Insert Effect->Insert Effect)->mMixBuff status_t AudioFlinger::PlaybackThread::Track::attachAuxEffect(int EffectId) { status_t status = DEAD_OBJECT; sp<ThreadBase> thread = mThread.promote(); if (thread != 0) { //获得当前track所在的线程 PlaybackThread *playbackThread = (PlaybackThread *)thread.get(); sp<AudioFlinger> af = mClient->audioFlinger(); Mutex::Autolock _l(af->mLock); //遍历所有线程,获得sesstionId==AUDIO_SESSION_OUTPUT_MIX的EffectChain //由此可见EffectChain是通过sessionId和客户端对应,每个线程可以对应多个客户端 //每个客户端对应一个EffectChain,然后通过EffectId获得当前拥有该effect的线程, //具体表述为:thread(1)---(n)chain(1)--(n)track(n)--(1)thread sp<PlaybackThread> srcThread = af->getEffectThread_l(AUDIO_SESSION_OUTPUT_MIX, EffectId); //如果找到Mix类型的Chain,根据以下条件重新分配effect,即将effect从原来的线程移除, //添加到当前线程的EffectChain中 //1、当前EffectId不为0,track初始化时,会将EffectId设为0,此时该track的 // mAuxBuffer设为null,因此track初始化时不会关联auxiliary类型的effect // 由此可以看出本函数主要track运行中途进行effect切换的处理 //2、当前effect属于其他线程,否则无需移动effect //3、找到包含MIX类型Chain的线程 if (EffectId != 0 && srcThread != 0 && playbackThread != srcThread.get()) { Mutex::Autolock _dl(playbackThread->mLock); Mutex::Autolock _sl(srcThread->mLock); sp<EffectChain> chain = srcThread->getEffectChain_l(AUDIO_SESSION_OUTPUT_MIX); if (chain == 0) { return INVALID_OPERATION; } sp<EffectModule> effect = chain->getEffectFromId_l(EffectId); if (effect == 0) { return INVALID_OPERATION; } //1、将effect从源线程的EffectChain,其中session==0中移除,如果该EffectChain // 没有其它的effect了,将该EffectChain从该线程的EffectCains中移除 srcThread->removeEffect_l(effect); //2、将effect加入到当前线程中的EffectChain中,其sessionId==0,如果该EffectChain // 不存在,则新建一个,并加入到EffectChains中 status = playbackThread->addEffect_l(effect); if (status != NO_ERROR) { srcThread->addEffect_l(effect); return INVALID_OPERATION; } // removeEffect_l() has stopped the effect if it was active so it must be restarted if (effect->state() == EffectModule::ACTIVE || effect->state() == EffectModule::STOPPING) { effect->start(); } sp<EffectChain> dstChain = effect->chain().promote(); if (dstChain == 0) { srcThread->addEffect_l(effect); return INVALID_OPERATION; } AudioSystem::unregisterEffect(effect->id()); AudioSystem::registerEffect(&effect->desc(), srcThread->id(), dstChain->strategy(), AUDIO_SESSION_OUTPUT_MIX, effect->id()); AudioSystem::setEffectEnabled(effect->id(), effect->isEnabled()); } //以上步骤已经完成了Effect在不同线程中间的切换,接下来关联该track和effect, //数据流:track->mMainBuffer(InBuffer)->inter effect->OutBuffer //1、如果该effect是EFFECT_FLAG_TYPE_AUXILIARY类型,将其输入设置为 // 该track的mainBuffer,数据流:track->mAuxBuffer->auxiliary effect //2、否则属于无效操作 status = playbackThread->attachAuxEffect(this, EffectId); } return status; } void AudioFlinger::ThreadBase::removeEffect_l(const sp<EffectModule>& effect) { ALOGV("removeEffect_l() %p effect %p", this, effect.get()); effect_descriptor_t desc = effect->desc(); //1、确认此Effect为AUXILIARY类型 //2、重置与此Effect相关联的Track if ((desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) { detachAuxEffect_l(effect->id()); } sp<EffectChain> chain = effect->chain().promote(); if (chain != 0) { // remove effect chain if removing last effect //如果当前EffectChain中没有Effect了,则可以将该EffectChain删除 if (chain->removeEffect_l(effect) == 0) { removeEffectChain_l(chain); } } else { ALOGW("removeEffect_l() %p cannot promote chain for effect %p", this, effect.get()); } } //遍历本线程中所有Track,找到指向该Effect的Track,清除该track, //即将该track的mAuxBuffer置为null,mAuxEffectId设为0 void AudioFlinger::PlaybackThread::detachAuxEffect_l(int effectId) { for (size_t i = 0; i < mTracks.size(); ++i) { sp<Track> track = mTracks[i]; if (track->auxEffectId() == effectId) { attachAuxEffect_l(track, 0); } } } //0、判断当前Effect的状态,如果是活动或正在停止,则调用停止方法 //1、首先对EFFECT_FLAG_TYPE_AUXILIARY类型的effect进行处理, // 需要删除该Effect申请的内存空间 //2、其它类型,如果删除的是末端的Effect,则将EffectChain的Buffer赋值给倒数第二个Effect //3、将mEffects中的Effect进行移除 size_t AudioFlinger::EffectChain::removeEffect_l(const sp<EffectModule>& effect) { Mutex::Autolock _l(mLock); size_t size = mEffects.size(); uint32_t type = effect->desc().flags & EFFECT_FLAG_TYPE_MASK; for (size_t i = 0; i < size; i++) { if (effect == mEffects[i]) { // calling stop here will remove pre-processing effect from the audio HAL. // This is safe as we hold the EffectChain mutex which guarantees that we are not in // the middle of a read from audio HAL if (mEffects[i]->state() == EffectModule::ACTIVE || mEffects[i]->state() == EffectModule::STOPPING) { mEffects[i]->stop(); } //删除Effect创建的输入Buffer if (type == EFFECT_FLAG_TYPE_AUXILIARY) { delete[] effect->inBuffer(); } else {//如果删除的是末端的Effect,则将EffectChain的Buffer赋值给倒数第二个Effect if (i == size - 1 && i != 0) { mEffects[i - 1]->setOutBuffer(mOutBuffer); mEffects[i - 1]->configure(); } } mEffects.removeAt(i); ALOGV("removeEffect_l() effect %p, removed from chain %p at rank %d", effect.get(), this, i); break; } } return mEffects.size(); } //从EffectChains中删除该EffectChain,同时需要分离该EffectChain中的Effect, //不过个人觉得如果可以判断一下该EffectChain的大小,如果为0,则可以不用处理,直接删除即可 size_t AudioFlinger::PlaybackThread::removeEffectChain_l(const sp<EffectChain>& chain) { int session = chain->sessionId(); ALOGV("removeEffectChain_l() %p from thread %p for session %d", chain.get(), this, session); for (size_t i = 0; i < mEffectChains.size(); i++) { if (chain == mEffectChains[i]) { mEffectChains.removeAt(i); // detach all active tracks from the chain for (size_t i = 0 ; i < mActiveTracks.size() ; ++i) { sp<Track> track = mActiveTracks[i].promote(); if (track == 0) { continue; } if (session == track->sessionId()) { ALOGV("removeEffectChain_l(): stopping track on chain %p for session Id: %d", chain.get(), session); chain->decActiveTrackCnt(); } } // detach all tracks with same session ID from this chain // 将此类track的mMainBuffer指向由Chain的输入改为MixBuffer, // 即表示此类track后续将不会进行音效处理,直接将数据进行MIX处理 for (size_t i = 0; i < mTracks.size(); ++i) { sp<Track> track = mTracks[i]; if (session == track->sessionId()) { track->setMainBuffer(mMixBuffer); chain->decTrackCnt(); } } break; } } return mEffectChains.size(); } //1、通过effect的sessionId查找EffectChain,如果没有找到,则新建一个EffectChain //2、将EffectChain加入到线程的EffectChains中, //3、将effect加入到EffectChain中,如果失败则删除该EffectChain //4、设置effect的输入设备、输出设备、模式、数据源类型 status_t AudioFlinger::ThreadBase::addEffect_l(const sp<EffectModule>& effect) { // check for existing effect chain with the requested audio session int sessionId = effect->sessionId(); sp<EffectChain> chain = getEffectChain_l(sessionId); bool chainCreated = false; ALOGD_IF((mType == OFFLOAD) && !effect->isOffloadable(), "addEffect_l() on offloaded thread %p: effect %s does not support offload flags %x", this, effect->desc().name, effect->desc().flags); if (chain == 0) { // create a new chain for this session ALOGV("addEffect_l() new effect chain for session %d", sessionId); chain = new EffectChain(this, sessionId); addEffectChain_l(chain); chain->setStrategy(getStrategyForSession_l(sessionId)); chainCreated = true; } ALOGV("addEffect_l() %p chain %p effect %p", this, chain.get(), effect.get()); if (chain->getEffectFromId_l(effect->id()) != 0) { ALOGW("addEffect_l() %p effect %s already present in chain %p", this, effect->desc().name, chain.get()); return BAD_VALUE; } effect->setOffloaded(mType == OFFLOAD, mId); //将Effect加入到EffectChain中 status_t status = chain->addEffect_l(effect); if (status != NO_ERROR) { if (chainCreated) { removeEffectChain_l(chain); } return status; } effect->setDevice(mOutDevice); effect->setDevice(mInDevice); effect->setMode(mAudioFlinger->getMode()); effect->setAudioSource(mAudioSource); return NO_ERROR; } //1、将新建的EffectChain加入到线程的EffectChain中 //2、根据sessionId将track的mainBuffer设置为EffectChain的输入 //3、将线程的mixBuffer设置为EffectChain的输出, // 由此可以看出数据流向Track->EffectChain->AudioMix // DIRECT类型的数据流向AudioMix->EffectChain->AudioMix status_t AudioFlinger::PlaybackThread::addEffectChain_l(const sp<EffectChain>& chain) { int session = chain->sessionId(); int16_t *buffer = mMixBuffer; bool ownsBuffer = false; ALOGV("addEffectChain_l() %p on thread %p for session %d", chain.get(), this, session); //1、session > 0时,表示客户端线程为普通线程,需要调整Tracks输入输出Buffer和激活的Track数目,且 // Chain需要单独申请输入Buffer,该Buffer将会作为对应Track的mMainBuff //2、当session = 0时,表示客户端线程为AUDIO_SESSION_OUTPUT_MIX类型,Chain的输入输出都是mMixBuffer if (session > 0) { // Only one effect chain can be present in direct output thread and it uses // the mix buffer as input // 1、如果是DIRECT类型的线程,EffectChain会直接使用MixBuffer作为输入和输出Buff // 因为此时,只有一个Chain进行音效处理,无需考虑各Chain之间的处理顺序, // 可能都不需要音效处理,因为按照逻辑,同时作为输入和输出是没法进行数据处理的 // 特别是Insert Effect不会申请额外的内存空间来进行数据存储 // 2、其它类型的Chain会申请内存空间作为输入,获得Tracks的输出, // 会有多个EffectChain,每个EffectChain都会申请一段内存进行音效处理 if (mType != DIRECT) { size_t numSamples = mNormalFrameCount * mChannelCount; buffer = new int16_t[numSamples]; memset(buffer, 0, numSamples * sizeof(int16_t)); ALOGV("addEffectChain_l() creating new input buffer %p session %d", buffer, session); ownsBuffer = true; } // Attach all tracks with same session ID to this chain. // 将sessionId相同的track的mainBuffer设置为EffectChain的输入 // 由此该EffectChain可以对该类track进行处理,数据流向Tracks->EffectChain // 推广来说就是线程中的Tracks根据sessionId分成若干组,每组Tracks对应一个EffectChain // 而EffectChain中的Effects也是根据sessionId进行组织的,sessionId不同的Effect会分配 // 在不同的EffectChain中 for (size_t i = 0; i < mTracks.size(); ++i) { sp<Track> track = mTracks[i]; if (session == track->sessionId()) { ALOGV("addEffectChain_l() track->setMainBuffer track %p buffer %p", track.get(), buffer); track->setMainBuffer(buffer); chain->incTrackCnt(); } } // indicate all active tracks in the chain // 统计chain中已激活ActiveTrack的数目 for (size_t i = 0 ; i < mActiveTracks.size() ; ++i) { sp<Track> track = mActiveTracks[i].promote(); if (track == 0) { continue; } if (session == track->sessionId()) { ALOGV("addEffectChain_l() activating track %p on session %d", track.get(), session); chain->incActiveTrackCnt(); } } } chain->setInBuffer(buffer, ownsBuffer); chain->setOutBuffer(mMixBuffer); // Effect chain for session AUDIO_SESSION_OUTPUT_STAGE is inserted at end of effect // chains list in order to be processed last as it contains output stage effects // Effect chain for session AUDIO_SESSION_OUTPUT_MIX is inserted before // session AUDIO_SESSION_OUTPUT_STAGE to be processed // after track specific effects and before output stage // It is therefore mandatory that AUDIO_SESSION_OUTPUT_MIX == 0 and // that AUDIO_SESSION_OUTPUT_STAGE < AUDIO_SESSION_OUTPUT_MIX // Effect chain for other sessions are inserted at beginning of effect // chains list to be processed before output mix effects. Relative order between other // sessions is not important // 将chain按照sessionId的大小进行降序排练,sessionId越大,优先级越高, // 实际是主要是为了确保MIX=0类型的Chain优先级大于STAGE=-1类型的Chain, // 其它EffectChain的先后次序并不重要 size_t size = mEffectChains.size(); size_t i = 0; for (i = 0; i < size; i++) { if (mEffectChains[i]->sessionId() < session) { break; } } mEffectChains.insertAt(chain, i); checkSuspendOnAddEffectChain_l(chain); return NO_ERROR; } void AudioFlinger::ThreadBase::checkSuspendOnAddEffectChain_l(const sp<EffectChain>& chain) { ssize_t index = mSuspendedSessions.indexOfKey(chain->sessionId()); if (index < 0) { return; } const KeyedVector <int, sp<SuspendedSessionDesc> >& sessionEffects = mSuspendedSessions.valueAt(index); for (size_t i = 0; i < sessionEffects.size(); i++) { sp<SuspendedSessionDesc> desc = sessionEffects.valueAt(i); for (int j = 0; j < desc->mRefCount; j++) { if (sessionEffects.keyAt(i) == EffectChain::kKeyForSuspendAll) { chain->setEffectSuspendedAll_l(true); } else { ALOGV("checkSuspendOnAddEffectChain_l() suspending effects %08x", desc->mType.timeLow); chain->setEffectSuspended_l(&desc->mType, true); } } } } // status_t AudioFlinger::EffectChain::addEffect_l(const sp<EffectModule>& effect) { effect_descriptor_t desc = effect->desc(); uint32_t insertPref = desc.flags & EFFECT_FLAG_INSERT_MASK; //保存该Effect所属的线程和EffectChain信息 Mutex::Autolock _l(mLock); effect->setChain(this); sp<ThreadBase> thread = mThread.promote(); if (thread == 0) { return NO_INIT; } effect->setThread(thread); //此处根据effect的type进行不同的插入处理,特别是auxiliary和insert类型,其它类型 //直接插入Chain末尾 //1、如果属于auxiliary类型的effect,则将其插入Chain首部,并申请输入Buffer // 将Chain的输入作为该effect的输出,由此可见auxiliary类型的effect优先级大于 // insert类型的effect,其数据流向可以表示为: // auxiliary effect -> Chain(insert effect -> insert effect) if ((desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) { // Auxiliary effects are inserted at the beginning of mEffects vector as // they are processed first and accumulated in chain input buffer mEffects.insertAt(effect, 0); // the input buffer for auxiliary effect contains mono samples in // 32 bit format. This is to avoid saturation in AudoMixer // accumulation stage. Saturation is done in EffectModule::process() before // calling the process in effect engine size_t numSamples = thread->frameCount(); int32_t *buffer = new int32_t[numSamples]; memset(buffer, 0, numSamples * sizeof(int32_t)); effect->setInBuffer((int16_t *)buffer); // auxiliary effects output samples to chain input buffer for further processing // by insert effects effect->setOutBuffer(mInBuffer); } else { // Insert effects are inserted at the end of mEffects vector as they are processed // after track and auxiliary effects. // Insert effect order as a function of indicated preference: // if EFFECT_FLAG_INSERT_EXCLUSIVE, insert in first position or reject if // another effect is present // else if EFFECT_FLAG_INSERT_FIRST, insert in first position or after the // last effect claiming first position // else if EFFECT_FLAG_INSERT_LAST, insert in last position or before the // first effect claiming last position // else if EFFECT_FLAG_INSERT_ANY insert after first or before last // Reject insertion if an effect with EFFECT_FLAG_INSERT_EXCLUSIVE is // already present //将本effect与该线程中的其它effect逐个比较,从而选择插入位置 size_t size = mEffects.size(); size_t idx_insert = size; ssize_t idx_insert_first = -1; ssize_t idx_insert_last = -1; for (size_t i = 0; i < size; i++) { effect_descriptor_t d = mEffects[i]->desc(); uint32_t iMode = d.flags & EFFECT_FLAG_TYPE_MASK; uint32_t iPref = d.flags & EFFECT_FLAG_INSERT_MASK; if (iMode == EFFECT_FLAG_TYPE_INSERT) { // check invalid effect chaining combinations // 同一Chain中只能有一个EXCLUSIVE类型的effect,这个语句貌似有问题 // 按照逻辑是一个EXCLUSIVE类型的都不能插入??? if (insertPref == EFFECT_FLAG_INSERT_EXCLUSIVE || iPref == EFFECT_FLAG_INSERT_EXCLUSIVE) { ALOGW("addEffect_l() could not insert effect %s: exclusive conflict with %s", desc.name, d.name); return INVALID_OPERATION; } // remember position of first insert effect and by default // select this as insert position for new effect // 记录第一个insert标志的位置,作为默认插入位置 if (idx_insert == size) { idx_insert = i; } // remember position of last insert effect claiming // first position // 记录最后一个有First标志的位置 if (iPref == EFFECT_FLAG_INSERT_FIRST) { idx_insert_first = i; } // remember position of first insert effect claiming // last position // 记录第一个有last标志的位置 if (iPref == EFFECT_FLAG_INSERT_LAST && idx_insert_last == -1) { idx_insert_last = i; } } } // modify idx_insert from first position if needed // 1、该effect有last标志,如果记录了last标志的位置,则插入此处 // 否则将其插入最末端 // 2、如果保留了first位置,则插入此处 // 3、否则插入末端,或者插入到记录第一个insert标志的地方 if (insertPref == EFFECT_FLAG_INSERT_LAST) { if (idx_insert_last != -1) { idx_insert = idx_insert_last; } else { idx_insert = size; } } else { if (idx_insert_first != -1) { idx_insert = idx_insert_first + 1; } } // always read samples from chain input buffer // 统一设置Effect的输入为Chain的输入 effect->setInBuffer(mInBuffer); // if last effect in the chain, output samples to chain // output buffer, otherwise to chain input buffer // 插入该Effect之前,需要对当前Chain末端的Effect进行处理: // 1、将该Effect插入Chain的末端,调整chain的输入作为当前末端Effect的输出 // 将Chain的输出作为该Effect的输出 // 2、将Effect插入其它位置,将Chain的输入作为该Effect的输出 // 有上述数据流的安排,可以看出,Chain中的Effect逐个对Track中的数据 // 进行处理,直到最后一个Effect才将数据输出。 // 综合上述,其数据流为:ChainInput->Effect->ChainInput->... // ...->Effect->ChainInput->Effect->ChainOutpu if (idx_insert == size) { if (idx_insert != 0) { mEffects[idx_insert-1]->setOutBuffer(mInBuffer); mEffects[idx_insert-1]->configure(); } effect->setOutBuffer(mOutBuffer); } else { effect->setOutBuffer(mInBuffer); } mEffects.insertAt(effect, idx_insert); ALOGV("addEffect_l() effect %p, added in chain %p at rank %d", effect.get(), this, idx_insert); } //根据以上传入的参数进行effect配置,到目前为止effect已经获得了 //所在Thread、Chain、输入Buff、输出Buff effect->configure(); return NO_ERROR; } status_t AudioFlinger::EffectModule::configure() { status_t status; sp<ThreadBase> thread; uint32_t size; audio_channel_mask_t channelMask; if (mEffectInterface == NULL) { status = NO_INIT; goto exit; } thread = mThread.promote(); if (thread == 0) { status = DEAD_OBJECT; goto exit; } // TODO: handle configuration of effects replacing track process channelMask = thread->channelMask(); if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) { mConfig.inputCfg.channels = AUDIO_CHANNEL_OUT_MONO; } else { mConfig.inputCfg.channels = channelMask; } mConfig.outputCfg.channels = channelMask; mConfig.inputCfg.format = AUDIO_FORMAT_PCM_16_BIT; mConfig.outputCfg.format = AUDIO_FORMAT_PCM_16_BIT; mConfig.inputCfg.samplingRate = thread->sampleRate(); mConfig.outputCfg.samplingRate = mConfig.inputCfg.samplingRate; mConfig.inputCfg.bufferProvider.cookie = NULL; mConfig.inputCfg.bufferProvider.getBuffer = NULL; mConfig.inputCfg.bufferProvider.releaseBuffer = NULL; mConfig.outputCfg.bufferProvider.cookie = NULL; mConfig.outputCfg.bufferProvider.getBuffer = NULL; mConfig.outputCfg.bufferProvider.releaseBuffer = NULL; mConfig.inputCfg.accessMode = EFFECT_BUFFER_ACCESS_READ; // Insert effect: // - in session AUDIO_SESSION_OUTPUT_MIX or AUDIO_SESSION_OUTPUT_STAGE, // always overwrites output buffer: input buffer == output buffer // - in other sessions: // last effect in the chain accumulates in output buffer: input buffer != output buffer // other effect: overwrites output buffer: input buffer == output buffer // Auxiliary effect: // accumulates in output buffer: input buffer != output buffer // Therefore: accumulate <=> input buffer != output buffer // 对Insert effect和Auxiliary effect两种effect进行不同的处理 // 1、Insert effect类型: // 1.1、如果是在AUDIO_SESSION_OUTPUT_MIX或AUDIO_SESSION_OUTPUT_STAGE类型的Chain中 // 由于输入和输出同时使用MixBuff,所以其输出Buff将会被输入覆盖(overwrite) // 原因:对于这两种类型的Chain,将输入和输出都设置为MixBuff,所以其中的Insert effect // 使用的输入和输出时相同的 // 1.2、如果是在其它Chain中, // 最后一个effect的输入和输出使用的Buff不同,其输出数据将会在持续保存 // 其它effect的输入和输出使用的Buff相同,所以其输出Buff将会被输入覆盖(overwrite) // 原因:其它类型的Chain在创建时,会创建一个Buff作为InputBuff,Track将数据写入到InputBuff中, // 其它Insert effect同时将InputBuff作为输入和输出,而最后一个effect则不同, // 该effect将InputBuff作为输入,但是将MixBuff作为输出,所以最后一个effect // 对象的输入和输出是不同的 // 2、Auxiliary effect类型 // 2.1、由于输入和输出使用的Buff不同,所以其输出数据将会在持续保存 // 原因:Auxiliary effect构造时会创建一个Buff作为InputBuff,Track将数据写到InputBuff中, // 同时将MixBuff作为输出,所以其输入和输出是不相同的 //综上所述:当effect使用的输入和输出Buff不相同时,设置为ACCUMULATE模式, // 否则设置为WRITE模式 //注释:以上所谓的Chain类型,取决于其关联的sessionId,其中 // AUDIO_SESSION_OUTPUT_MIX == 0 // AUDIO_SESSION_OUTPUT_STAGE == -1 if (mConfig.inputCfg.buffer.raw != mConfig.outputCfg.buffer.raw) { mConfig.outputCfg.accessMode = EFFECT_BUFFER_ACCESS_ACCUMULATE; } else { mConfig.outputCfg.accessMode = EFFECT_BUFFER_ACCESS_WRITE; } mConfig.inputCfg.mask = EFFECT_CONFIG_ALL; mConfig.outputCfg.mask = EFFECT_CONFIG_ALL; mConfig.inputCfg.buffer.frameCount = thread->frameCount(); mConfig.outputCfg.buffer.frameCount = mConfig.inputCfg.buffer.frameCount; ALOGV("configure() %p thread %p buffer %p framecount %d", this, thread.get(), mConfig.inputCfg.buffer.raw, mConfig.inputCfg.buffer.frameCount); status_t cmdStatus; size = sizeof(int); status = (*mEffectInterface)->command(mEffectInterface, EFFECT_CMD_SET_CONFIG, sizeof(effect_config_t), &mConfig, &size, &cmdStatus); if (status == 0) { status = cmdStatus; } if (status == 0 && (memcmp(&mDescriptor.type, SL_IID_VISUALIZATION, sizeof(effect_uuid_t)) == 0)) { uint32_t buf32[sizeof(effect_param_t) / sizeof(uint32_t) + 2]; effect_param_t *p = (effect_param_t *)buf32; p->psize = sizeof(uint32_t); p->vsize = sizeof(uint32_t); size = sizeof(int); *(int32_t *)p->data = VISUALIZER_PARAM_LATENCY; uint32_t latency = 0; PlaybackThread *pbt = thread->mAudioFlinger->checkPlaybackThread_l(thread->mId); if (pbt != NULL) { latency = pbt->latency_l(); } *((int32_t *)p->data + 1)= latency; (*mEffectInterface)->command(mEffectInterface, EFFECT_CMD_SET_PARAM, sizeof(effect_param_t) + 8, &buf32, &size, &cmdStatus); } mMaxDisableWaitCnt = (MAX_DISABLE_TIME_MS * mConfig.outputCfg.samplingRate) / (1000 * mConfig.outputCfg.buffer.frameCount); exit: mStatus = status; return status; } status_t AudioPolicyManagerBase::unregisterEffect(int id) { ssize_t index = mEffects.indexOfKey(id); if (index < 0) { ALOGW("unregisterEffect() unknown effect ID %d", id); return INVALID_OPERATION; } EffectDescriptor *pDesc = mEffects.valueAt(index); setEffectEnabled(pDesc, false); if (mTotalEffectsMemory < pDesc->mDesc.memoryUsage) { ALOGW("unregisterEffect() memory %d too big for total %d", pDesc->mDesc.memoryUsage, mTotalEffectsMemory); pDesc->mDesc.memoryUsage = mTotalEffectsMemory; } mTotalEffectsMemory -= pDesc->mDesc.memoryUsage; ALOGV("unregisterEffect() effect %s, ID %d, memory %d total memory %d", pDesc->mDesc.name, id, pDesc->mDesc.memoryUsage, mTotalEffectsMemory); mEffects.removeItem(id); delete pDesc; return NO_ERROR; } status_t AudioPolicyManagerBase::registerEffect(const effect_descriptor_t *desc, audio_io_handle_t io, uint32_t strategy, int session, int id) { ssize_t index = mOutputs.indexOfKey(io); if (index < 0) { index = mInputs.indexOfKey(io); if (index < 0) { ALOGW("registerEffect() unknown io %d", io); return INVALID_OPERATION; } } if (mTotalEffectsMemory + desc->memoryUsage > getMaxEffectsMemory()) { ALOGW("registerEffect() memory limit exceeded for Fx %s, Memory %d KB", desc->name, desc->memoryUsage); return INVALID_OPERATION; } mTotalEffectsMemory += desc->memoryUsage; ALOGV("registerEffect() effect %s, io %d, strategy %d session %d id %d", desc->name, io, strategy, session, id); ALOGV("registerEffect() memory %d, total memory %d", desc->memoryUsage, mTotalEffectsMemory); EffectDescriptor *pDesc = new EffectDescriptor(); memcpy (&pDesc->mDesc, desc, sizeof(effect_descriptor_t)); pDesc->mIo = io; pDesc->mStrategy = (routing_strategy)strategy; pDesc->mSession = session; pDesc->mEnabled = false; mEffects.add(id, pDesc); return NO_ERROR; } status_t AudioFlinger::PlaybackThread::attachAuxEffect( const sp<AudioFlinger::PlaybackThread::Track> track, int EffectId) { Mutex::Autolock _l(mLock); return attachAuxEffect_l(track, EffectId); } //实际上AUDIO_SESSION_OUTPUT_MIX==0, //从sessionID==AUDIO_SESSION_OUTPUT_MIX的EffectChain中获得AUXILIBARY类型的Effect, //将其输入设置为track的mAuxBuffer,由此可见该类型的Effect实际上就是Chain中的第一个Effect, //这样后续数据流向为:Track->OUTPUT_MIX Chain(auxiliary Effect->Effect) //按照本函数的逻辑,Auxiliary类型的effects应该都 //放在session==AUDIO_SESSION_OUTPUT_MIX的EffectChain中 status_t AudioFlinger::PlaybackThread::attachAuxEffect_l( const sp<AudioFlinger::PlaybackThread::Track> track, int EffectId) { status_t status = NO_ERROR; if (EffectId == 0) {//Track初始化时,无Effect和该track进行关联 track->setAuxBuffer(0, NULL); } else { // Auxiliary effects are always in audio session AUDIO_SESSION_OUTPUT_MIX sp<EffectModule> effect = getEffect_l(AUDIO_SESSION_OUTPUT_MIX, EffectId); if (effect != 0) { if ((effect->desc().flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) { track->setAuxBuffer(EffectId, (int32_t *)effect->inBuffer()); } else { status = INVALID_OPERATION; } } else { status = BAD_VALUE; } } return status; } void AudioFlinger::PlaybackThread::Track::setAuxBuffer(int EffectId, int32_t *buffer) { mAuxEffectId = EffectId; mAuxBuffer = buffer; }