Chinaunix首页 | 论坛 | 博客
  • 博客访问: 521178
  • 博文数量: 257
  • 博客积分: 1666
  • 博客等级: 上尉
  • 技术积分: 1535
  • 用 户 组: 普通用户
  • 注册时间: 2012-04-02 23:02
文章分类

全部博文(257)

文章存档

2013年(2)

2012年(255)

分类:

2012-08-10 12:29:22

原文地址:Android音频数据传输 作者:BENNYSNAKE

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) |
给主人留下些什么吧!~~