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;
}
Audio笔记之Track::attachAuxEffect
最新推荐文章于 2022-08-27 10:57:44 发布