MediaPlayer那边就不看了,从AudioTrack开始研究。 1、AudioTrack::write函数 调用函数obtainBuffer获取到一块buffer,然后把传入的数据copy到获取的buffer中。 2、AudioTrack::obtainBuffer函数 该函数的主要功能就是对传入的audioBuffer进行赋值。 看看audioBuffer的类型: class Buffer { public: enum { MUTE = 0x00000001 }; uint32_t flags; int channelCount; int format; size_t frameCount; size_t size; union { void* raw; short* i16; int8_t* i8; }; }; 其中存放数据的是下面这个东东: union { void* raw; short* i16; int8_t* i8; }; 对这块东东赋值的代码如下: audioBuffer->raw = (int8_t *)cblk->buffer(u); 先看其中cblk的来历: audio_track_cblk_t* cblk = mCblk; mCblk的赋值在函数AudioTrack::createTrack中: mCblk = static_cast(cblk->pointer()); cblk的由来: sp cblk = track->getCblk(); track的由来: sp track = audioFlinger->createTrack(getpid(), streamType, sampleRate, format, channelCount, frameCount, ((uint16_t)flags) << 16, sharedBuffer, output, &mSessionId, &status); 函数AudioFlinger::createTrack返回的是一个TrackHandle对象: trackHandle = new TrackHandle(track); return trackHandle; track的由来: track = thread->createTrack_l(client, streamType, sampleRate, format, channelCount, frameCount, sharedBuffer, lSessionId, &lStatus); 函数AudioFlinger::PlaybackThread::createTrack_l返回的是一个Track对象: track = new Track(this, client, streamType, sampleRate, format, channelCount, frameCount, sharedBuffer, sessionId); return track; 看看函数TrackHandle::getCblk() : return mTrack->getCblk(); mTrack就是作为构造函数传入的track对象。 函数AudioFlinger::ThreadBase::TrackBase::getCblk() 的实现: return mCblkMemory; mCblkMemory的赋值在构造函数AudioFlinger::ThreadBase::TrackBase::TrackBase中: mCblkMemory = client->heap()->allocate(size); mCblk = static_cast(mCblkMemory->pointer()); // 这个成员变量也很重要 client是构造函数参数: const sp& client 函数AudioFlinger::Client::heap: return mMemoryDealer; mMemoryDealer的赋值在函数AudioFlinger::Client::Client中: mMemoryDealer(new MemoryDealer(1024*1024, "AudioFlinger::Client")) 看看函数MemoryDealer::allocate: sp MemoryDealer::allocate(size_t size) { sp memory; // allocator()直接返回mAllocator // mAllocator的赋值在构造函数中:mAllocator(new SimpleBestFitAllocator(size)) /× 函数SimpleBestFitAllocator::allocate的实现: size_t SimpleBestFitAllocator::allocate(size_t size, uint32_t flags) { Mutex::Autolock _l(mLock); // 暂止 ssize_t offset = alloc(size, flags); return offset; } ×/ const ssize_t offset = allocator()->allocate(size); if (offset >= 0) { // heap()直接返回mHeap // mHeap的赋值在构造函数中:mHeap(new MemoryHeapBase(size, 0, name)) memory = new Allocation(this, heap(), offset, size); } return memory; } 可见前面的mCblkMemory其实就是一个Allocation对象。 可见AudioTrack的成员变量mCblk和AudioFlinger::ThreadBase::TrackBase的成员变量mCblk的值相同, 都是:static_cast(mCblkMemory->pointer())。 函数IMemory::pointer的实现: void* IMemory::pointer() const { ssize_t offset; sp heap = getMemory(&offset); void* const base = heap!=0 ? heap->base() : MAP_FAILED; if (base == MAP_FAILED) return 0; return static_cast(base) + offset; } 回头过去,看看函数audio_track_cblk_t::buffer: return (int8_t *)this->buffers + (offset - userBase) * this->frameSize; 可见audio_track_cblk_t的主要作用是申请了一块内存空间。 调用函数AudioTrack::write的时候,会先将数据写到这个内存空间中。 3、数据写入到了audio_track_cblk_t中,谁又会来使用这些数据呢? 看代码可知,函数AudioTrack::obtainBuffer中会先调用audio_track_cblk_t::framesAvailable。 同时,我们发现还有一个函数audio_track_cblk_t::framesReady。 单从字面上也可以看出来,这是告诉用户准备好了多少数据。 搜搜哪儿调用了函数audio_track_cblk_t::framesReady吧。 搜了下,发现有三个函数中调用了它,分别是: AudioFlinger::MixerThread::prepareTracks_l函数 AudioFlinger::DirectOutputThread::threadLoop函数 AudioFlinger::PlaybackThread::Track::getNextBuffer函数 4、先看看函数AudioFlinger::MixerThread::prepareTracks_l函数。 字面上看,应该是准备提供数据的Tracks。 果然不错,函数中调用AudioMixer::setBufferProvider将Track设置到mAudioMixer(AudioMixer)中。 函数AudioMixer::setBufferProvider实现: status_t AudioMixer::setBufferProvider(AudioBufferProvider* buffer) { mState.tracks[ mActiveTrack ].bufferProvider = buffer; return NO_ERROR; } 然后调用函数AudioMixer::setParameter将Track的main buffer也设置到mAudioMixer(AudioMixer)中。 函数AudioMixer::setParameter中与main buffer相关的部分代码: if (name == MAIN_BUFFER) { if (mState.tracks[ mActiveTrack ].mainBuffer != valueBuf) { mState.tracks[ mActiveTrack ].mainBuffer = valueBuf; LOGV("setParameter(TRACK, MAIN_BUFFER, %p)", valueBuf); invalidateState(1<
}
return NO_ERROR;
}
类函数AudioMixer中是如何来使用bufferProvider的呢?
AudioMixer中的以process__为前缀的几个函数都是有到了bufferProvider。
但从数据传输上来说,这几个函数是类似的。
我们只看其中的AudioMixer::process__OneTrack16BitsStereoNoResampling函数。
函数中有代码:
t.bufferProvider->getNextBuffer(&b);
我们知道,bufferProvider其实就是Track,而我们探讨的是音频播放,所以就跳到了函数:AudioFlinger::PlaybackThread::Track::getNextBuffer,
也就是前面我们搜到的,调用audio_track_cblk_t::framesReady的三个函数之一。
函数AudioFlinger::PlaybackThread::Track::getNextBuffer是从audio_track_cblk_t中取得已准备好的音频数据,
写到什么地方去,下面我们开始研究。
回到函数process__OneTrack16BitsStereoNoResampling中,我们知道,调用AudioFlinger::PlaybackThread::Track::getNextBuffer获取的地址赋值给了in:
int16_t const *in = b.i16;
后来取in的数据给了rl:
uint32_t rl = *reinterpret_cast(in);
然后将rl赋值给out:
*out++ = (r<<16) | (l & 0xFFFF);
由此可见,我们刚才疑惑的“写到什么地方去”,其实就是写到out里了。
out的来历:
int32_t* out = t.mainBuffer;
这不就是函数AudioMixer::setParameter中赋值的main buffer么???
搞了一圈,原来AudioMixer的功能就是将Track里audio_track_cblk_t中的数据,赋值给Track里的mainBuffer。
下面好好看看这个main buffer的来历吧。
由前面的分析可知,调用函数AudioMixer::setParameter,来设置main buffer的地方是函数AudioFlinger::MixerThread::prepareTracks_l。
回过去看看对函数AudioMixer::setParameter的调用:
mAudioMixer->setParameter(
AudioMixer::TRACK,
AudioMixer::MAIN_BUFFER, (void *)track->mainBuffer());
函数mainBuffer()实现:
return mMainBuffer;
mMainBuffer的赋值在函数setMainBuffer中:
setMainBuffer(int16_t *buffer) { mMainBuffer = buffer; }
看看谁调用了函数setMainBuffer吧。
有三个地方调用了函数setMainBuffer:
a、AudioFlinger::PlaybackThread::createTrack_l函数
b、AudioFlinger::PlaybackThread::addEffectChain_l函数
c、AudioFlinger::PlaybackThread::removeEffectChain_l函数
b和c类似,都是将PlaybackThread的mMixBuffer赋值给了main buffer。
先看看a.
track->setMainBuffer(chain->inBuffer());
作为main buffer的是chain->inBuffer()这个东东。
inBuffer()函数实现:return mInBuffer;
mInBuffer中函数setInBuffer中被赋值:
mInBuffer = buffer;
看看调用setInBuffer函数的地方:
AudioFlinger::PlaybackThread::addEffectChain_l函数
AudioFlinger::EffectChain::addEffect_l函数
先看看AudioFlinger::PlaybackThread::addEffectChain_l函数中的处理,
函数中根据是否为DIRECT output thread,有两种处理方式:
一种是处理direct output thread:
调用函数setMainBuffer将PlaybackThread的mMixBuffer告诉给Track,即告诉Track,在AudioMixer中往PlaybackThread的mMixBuffer中copy数据。
然后将effect chain的input buffer和output buffer都设置为PlaybackThread的mMixBuffer。
(目的是让该effect chain不起作用?存在注释“Only one effect chain can be present in direct output thread and it usesthe mix buffer as input”)
另一种是处理非direct output thread:
new一段buffer出来。
调用函数setMainBuffer将新buffer告诉给Track,即告诉Track,在AudioMixer中往新buffer中copy数据。
调用函数setInBuffer来实装chain的input buffer。(发现函数AudioFlinger::PlaybackThread::createTrack_l中其实有将chain的input buffer赋值给Track的main buffer)。
然后将PlaybackThread的mMixBuffer赋值给chain的output buffer。
也就是说,Track将数据copy到自己的main buffer(即effect chain的input buffer),
effect chain对数据进行处理,然后将处理过的数据赋值给自己的output buffer(即PlaybackThread的mMixBuffer)
mMixBuffer是如何被使用的呢?
函数AudioFlinger::MixerThread::threadLoop中调用函数AudioStreamOutALSA::write(HAL侧)。
函数AudioStreamOutALSA::write中调用了函数snd_pcm_mmap_writei或者snd_pcm_writei。
函数snd_pcm_mmap_writei或者snd_pcm_writei将mMixBuffer中的数据写入到底层。
阅读(678) | 评论(0) | 转发(0) |