现在的位置: 首页 > 综合 > 正文

Audio笔记之Track::attachAuxEffect

2017年11月10日 ⁄ 综合 ⁄ 共 25389字 ⁄ 字号 评论关闭
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;
} 

抱歉!评论已关闭.