bool AudioFlinger::PlaybackThread::threadLoop()
{
Vector< sp<Track> > tracksToRemove;
standbyTime = systemTime();
// MIXER
nsecs_t lastWarning = 0;
// DUPLICATING
// FIXME could this be made local to while loop?
writeFrames = 0;
int lastGeneration = 0;
cacheParameters_l();
sleepTime = idleSleepTime;
if (mType == MIXER) {
sleepTimeShift = 0;
}
CpuStats cpuStats;
const String8 myName(String8::format("thread %p type %d TID %d", this, mType, gettid()));
acquireWakeLock();
// mNBLogWriter->log can only be called while thread mutex mLock is held.
// So if you need to log when mutex is unlocked, set logString to a non-NULL string,
// and then that string will be logged at the next convenient opportunity.
const char *logString = NULL;
checkSilentMode_l();
while (!exitPending())
{
cpuStats.sample(myName);
Vector< sp<EffectChain> > effectChains;
processConfigEvents();
{ // scope for mLock
Mutex::Autolock _l(mLock);
if (logString != NULL) {
mNBLogWriter->logTimestamp();
mNBLogWriter->log(logString);
logString = NULL;
}
if (mLatchDValid) {
mLatchQ = mLatchD;
mLatchDValid = false;
mLatchQValid = true;
}
//检查客户端设置的更新,客户端通过setParameters进行设置
if (checkForNewParameters_l()) {
cacheParameters_l();
}
saveOutputTracks();
//判断是否有track加入
if (mSignalPending) {
// A signal was raised while we were unlocked
mSignalPending = false;
} else if (waitingAsyncCallback_l()) {//offload时返回true
if (exitPending()) {
break;
}
releaseWakeLock_l();
mWakeLockUids.clear();
mActiveTracksGeneration++;
ALOGV("wait async completion");
mWaitWorkCV.wait(mLock);
ALOGV("async completion/wake");
acquireWakeLock_l();
standbyTime = systemTime() + standbyDelay;
sleepTime = 0;
continue;
}
//两种情况需要硬件进入standby
//第一:没有活跃音轨而且standbyTime过期
//第二:需要Suspend
if ((!mActiveTracks.size() && systemTime() > standbyTime) ||
isSuspended()) {
// put audio hardware into standby after short delay
if (shouldStandby_l()) {
threadLoop_standby();
mStandby = true;
}
//如果当前config event也为空,则进入阻塞状态
if (!mActiveTracks.size() && mConfigEvents.isEmpty()) {
// we're about to wait, flush the binder command buffer
IPCThreadState::self()->flushCommands();
clearOutputTracks();
if (exitPending()) {
break;
}
releaseWakeLock_l();
mWakeLockUids.clear();
mActiveTracksGeneration++;
// wait until we have something to do...
// 当前没有可供使用的active track,进程进入阻塞状态,
// 等待广播消息唤醒,包括配置参数、活跃音轨添加等消息
ALOGV("%s going to sleep", myName.string());
mWaitWorkCV.wait(mLock);
ALOGV("%s waking up", myName.string());
acquireWakeLock_l();
mMixerStatus = MIXER_IDLE;
mMixerStatusIgnoringFastTracks = MIXER_IDLE;
mBytesWritten = 0;
mBytesRemaining = 0;
checkSilentMode_l();
standbyTime = systemTime() + standbyDelay;
sleepTime = idleSleepTime;
if (mType == MIXER) {
sleepTimeShift = 0;
}
continue;
}
}
// mMixerStatusIgnoringFastTracks is also updated internally
// 准备音轨,为混音做准备
mMixerStatus = prepareTracks_l(&tracksToRemove);
// compare with previously applied list
if (lastGeneration != mActiveTracksGeneration) {
// update wakelock
updateWakeLockUids_l(mWakeLockUids);
lastGeneration = mActiveTracksGeneration;
}
// prevent any changes in effect chain list and in each effect chain
// during mixing and effect process as the audio buffers could be deleted
// or modified if an effect is created or deleted
lockEffectChains_l(effectChains);
} // mLock scope ends
//混音处理后数据全部写入Hal之后,会将mBytesRemaining置为0
//即表示当前可以进行新一轮的Mix操作
if (mBytesRemaining == 0) {
mCurrentWriteLength = 0;
if (mMixerStatus == MIXER_TRACKS_READY) {
// threadLoop_mix() sets mCurrentWriteLength
threadLoop_mix();
} else if ((mMixerStatus != MIXER_DRAIN_TRACK)
&& (mMixerStatus != MIXER_DRAIN_ALL)) {
// threadLoop_sleepTime sets sleepTime to 0 if data
// must be written to HAL
threadLoop_sleepTime();
if (sleepTime == 0) {
mCurrentWriteLength = mixBufferSize;
}
}
mBytesRemaining = mCurrentWriteLength;
if (isSuspended()) {
sleepTime = suspendSleepTimeUs();
// simulate write to HAL when suspended
mBytesWritten += mixBufferSize;
mBytesRemaining = 0;
}
// only process effects if we're going to write
// 进行音效处理,同时避免offload类型的输出重复处理
if (sleepTime == 0 && mType != OFFLOAD) {
for (size_t i = 0; i < effectChains.size(); i ++) {
effectChains[i]->process_l();
}
}
}
// Process effect chains for offloaded thread even if no audio
// was read from audio track: process only updates effect state
// and thus does have to be synchronized with audio writes but may have
// to be called while waiting for async write callback
// 当输出线程为offload类型时,即使没有读取track数据,
// 也需要对effect chain进行处理,更新effect状态
if (mType == OFFLOAD) {
for (size_t i = 0; i < effectChains.size(); i ++) {
effectChains[i]->process_l();
}
}
// enable changes in effect chain
unlockEffectChains(effectChains);
//需要对OffloadThread类型的输出进行条件判断,
//其它情况为true
if (!waitingAsyncCallback()) {
// sleepTime == 0 means we must write to audio hardware
//1、休眠时间为0,且MIX处理之后的数据不会空时,将数据写入到Hal,
// 返回写入的数据量,如果小于零,则直接将mBytesRemaining置0
// 其它情况则增加已写入数据量,减少Mix已处理量
&nbs
Audio笔记之PlaybackThread::threadLoop
最新推荐文章于 2025-07-16 22:32:53 发布