Android Audio System(2)

2018-11-27 17:15

return u - s; } else {

Mutex::Autolock _l(lock); if (loopCount >= 0) {

return (loopEnd - loopStart)*loopCount + u - s; } else {

return UINT_MAX; } } } else {

return s - u; } }

我们看看下面的示意图:

_____________________________________________ ^ ^ ^ ^

buffer_start server(s) user(u) buffer_end

很明显,frameReady = u - s,frameAvalible = frameCount - frameReady = frameCount - u + s

可能有人会问,应为这是一个环形的buffer,一旦user越过了buffer_end以后,应该会发生下面的情况:

_____________________________________________ ^ ^ ^ ^

buffer_start user(u) server(s) buffer_end

这时候u在s的前面,用上面的公式计算就会错误,但是android使用了一些技巧,保证了上述公式一直成立。我们先看完下面三个函数的代码再分析: [c-sharp] view plaincopy

uint32_t audio_track_cblk_t::stepUser(uint32_t frameCount) {

uint32_t u = this->user; u += frameCount; ......

if (u >= userBase + this->frameCount) { userBase += this->frameCount; }

this->user = u; ...... return u; }

[c-sharp] view plaincopy

bool audio_track_cblk_t::stepServer(uint32_t frameCount) {

6

// the code below simulates lock-with-timeout

// we MUST do this to protect the AudioFlinger server // as this lock is shared with the client. status_t err;

err = lock.tryLock();

if (err == -EBUSY) { // just wait a bit usleep(1000);

err = lock.tryLock(); }

if (err != NO_ERROR) {

// probably, the client just died. return false; }

uint32_t s = this->server; s += frameCount; // 省略部分代码 // ......

if (s >= serverBase + this->frameCount) { serverBase += this->frameCount; }

this->server = s; cv.signal(); lock.unlock(); return true; }

[c-sharp] view plaincopy

void* audio_track_cblk_t::buffer(uint32_t offset) const {

return (int8_t *)this->buffers + (offset - userBase) * this->frameSize; }

stepUser()和stepServer的作用是调整当前偏移的位置,可以看到,他们仅仅是把成员变量user或server的值加上需要移动的数量,user和server的值并不考虑FIFO的边界问题,随着数据的不停写入和读出,user和server的值不断增加,只要处理得当,user总是出现在server的后面,因此frameAvalible()和

frameReady()中的算法才会一直成立。根据这种算法,user和server的值都可能大于FIFO的大小:framCount,那么,如何确定真正的写指针的位置呢?这里需要用到userBase这一成员变量,在stepUser()中,每当user的值越过

(userBase+frameCount),userBase就会增加frameCount,这样,映射到FIFO中的偏移总是可以通过(user-userBase)获得。因此,获得当前FIFO的写地址指针可以通过成员函数buffer()返回: p = mClbk->buffer(mclbk->user);

7

在AudioTrack中,封装了两个函数:obtainBuffer()和releaseBuffer()操作FIFO,obtainBuffer()获得当前可写的数量和写指针的位置,releaseBuffer()则在写入数据后被调用,它其实就是简单地调用stepUser()来调整偏移的位置。

IMemory接口

在createTrack的过程中,AudioFlinger会根据传入的frameCount参数,申请一块内存,AudioTrack可以通过IAudioTrack接口的getCblk()函数获得指向该内存块的IMemory接口,然后AudioTrack通过该IMemory接口的pointer()函数获得指向该内存块的指针,这块内存的开始部分就是audio_track_cblk_t结构,紧接着是大小为frameSize的FIFO内存。

IMemory->pointer() ---->|_______________________________________________________ |__audio_track_cblk_t__|_______buffer of FIFO(size==frameCount)____|

看看AudioTrack的createTrack()的代码就明白了: [c-sharp] view plaincopy

sp track = audioFlinger->createTrack(getpid(), streamType,

sampleRate,

format, channelCount,

frameCount,

((uint16_t)flags) << 16,

sharedBuffer,

output, &status); // 得到IMemory接口

sp cblk = track->getCblk(); mAudioTrack.clear(); mAudioTrack = track; mCblkMemory.clear(); mCblkMemory = cblk;

// 得到audio_track_cblk_t结构

mCblk = static_cast(cblk->pointer()); // 该FIFO用于输出

8

mCblk->out = 1; // Update buffer size in case it has been limited by AudioFlinger during track creation

mFrameCount = mCblk->frameCount; if (sharedBuffer == 0) { // 给FIFO的起始地址赋值 mCblk->buffers = (char*)mCblk + sizeof(audio_track_cblk_t); } else {

.......... }

1.Android Audio System 之二:AudioFlinger 引言 AudioFlinger是Android音频系统的两大服务之一,另一个服务是

AudioPolicyService,这两大服务都在系统启动时有MediaSever加载,加载的代码位于:frameworks/base/media/mediaserver/main_mediaserver.cpp。

AudioPolicyService的相关内容请参考另一编文章:《Android Audio System 之三: AudioPolicyService 和 AudioPolicyManager 》

http://blog.csdn.net/DroidPhone/archive/2010/10/18/5949280.aspx

本文主要介绍AudioFlinger,AudioFlinger向下访问AudioHardware,实现输出音频数据,控制音频参数。同时,AudioFlinger向上通过IAudioFinger接口提供服务。所以,AudioFlinger在Android的音频系统框架中起着承上启下的作用,地位相当重要。AudioFlinger的相关代码主要在:frameworks/base/libs/audioflinger,也有部分相关的代码在frameworks/base/media/libmedia里。 AudioFlinger的类结构

下面的图示描述了AudioFlinger类的内部结构和关系:

9

图一 AudioFlinger的类结构

不知道各位是否和我一样,第一次看到AudioFlinger类的定义的时候都很郁闷--这个类实在是庞大和臃肿,可是当你理清他的关系以后,你会觉得相当合理。下面我们一一展开讨论。 IAudioFlinger接口

这是AudioFlinger向外提供服务的接口,例如openOutput,openInput,createTrack,openRecord等等,应用程序或者其他service通过

ServiceManager可以获得该接口。该接口通过继承BnAudioFlinger得到。 ThreadBase

10


Android Audio System(2).doc 将本文的Word文档下载到电脑 下载失败或者文档不完整,请联系客服人员解决!

下一篇:工作表现鉴定材料

相关阅读
本类排行
× 注册会员免费下载(下载后可以自由复制和排版)

马上注册会员

注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信: QQ: