当前位置:文档之家› Android音频数据传输

Android音频数据传输

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;

相关主题