AudioFlinger::PlaybackThread::threadLoop()
{
…
if (!waitingAsyncCallback()) {
// sleepTime == 0 means we mustwrite to audio hardware
if (sleepTime == 0) {
if (mBytesRemaining) {
ssize_tret = threadLoop_write();
if (ret < 0) {
mBytesRemaining = 0;
} else {
mBytesWritten += ret;
mBytesRemaining -= ret;
}
} else if ((mMixerStatus ==MIXER_DRAIN_TRACK) ||
(mMixerStatus ==MIXER_DRAIN_ALL)) {
threadLoop_drain();
}
…
}
AudioFlinger 是android 多媒体模块Audio模块的两大服务之一。音频相关的数据必须通过它来传递到底层,所以它就会有一个音频数据的处理过程。这里主要就是分析音频数据从编码器出来之后,怎么流向驱动的。
从audoFlinger的代码中很容易发现,数据写到驱动的处理是在函数
AudioFlinger::PlaybackThread::threadLoop_write()中。这个threadLoop_write 函数在AudioFlinger::PlaybackThread::threadLoop()函数中调用,很显然audioFlinger的数据处理都会在这个线程函数中处理。那么数据的出口是这样实现
那么数据的入口在哪里呢?
通过分析,发现PlaybackThread::threadLoop() 函数主要做三件事,prepareTracks_l(), threadLoop_mix(),threadLoop_write().
prepareTracks_l() 函数主要的工作就是检查是否有track 的状态,并做相应的处理,比如track准备好了,就把它添加到队列中区,还做一些处理比如
// XXX: these things DON'T need to be done each time
mAudioMixer->setBufferProvider(name, track);
mAudioMixer->enable(name);
mAudioMixer->setParameter(name, param, AudioMixer::VOLUME0, (void*)vl);
mAudioMixer->setParameter(name, param, AudioMixer::VOLUME1, (void*)vr);
mAudioMixer->setParameter(name, param, AudioMixer::AUXLEVEL, (void*)va);
mAudioMixer->setParameter(
name,
AudioMixer::TRACK,
AudioMixer::FORMAT, (void*)track->format());
mAudioMixer->setParameter(
name,
AudioMixer::TRACK,
AudioMixer::CHANNEL_MASK, (void*)track->channelMask());
设置参数到AudioMixer。这个很关键,会影响后面混音的结果和处理。
prepareTracks_l() 之后就是混音处理了,处理函数就是threadLoop_mix()。混音,顾名思义,就是将几种声音混到一起,实际上就是将同时处于active状态的track进行混音,每一路音频对应一个track实例。目前android 最多支持32路混音,在类AudioMixer中有相应的定义: static const uint32_tMAX_NUM_TRACKS = 32;
threadLoop_write 是数据的出口,prepareTracks_l只是准备tracks,那么很显然,数据的入口也只有threadLoop_mix 了,混音必须要对数据处理,如果没有数据怎么混音,此时将数据拉进来时最好的时机,事实上也是在threadLoop_mix 的处理过程中数据进入到
AudioFlinger服务中。下面来分析threadLoop_mix。
voidAudioFlinger::MixerThread::threadLoop_mix()
{
// obtain the presentation timestamp of the next output buffer
int64_t pts;
status_t status = INVALID_OPERATION;
if (mNormalSink != 0) {
status = mNormalSink->getNextWriteTimestamp(&pts);
}else {
status = mOutputSink->getNextWriteTimestamp(&pts);
}
if (status != NO_ERROR) {
pts = AudioBufferProvider::kInvalidPTS;
}
// mix buffers...
mAudioMixer->process(pts);
mCurrentWriteLength = mixBufferSize;
if ((sleepTime == 0) && (sleepTimeShift > 0)) {
sleepTimeShift--;
}
sleepTime = 0;
standbyTime = systemTime() + standbyDelay;
//TODO: delay standby when effects have a tail
}
从函数中发现,
mAudioMixe