AudioTrace工作原理

AudioTrack和AudioFlinger的交互

 

AudioTrack和AudioFlinger之间通过共享内存进行数据交互。共享内存可以从上层传下来,也能在TrackBase用共享内存创建。传下来的是static的。

创建代码如下:

if (sharedBuffer == 0) {

mAudioTrackServerProxy = newAudioTrackServerProxy(mCblk, mBuffer, frameCount, mFrameSize);

} else {

mAudioTrackServerProxy = newStaticAudioTrackServerProxy(mCblk, mBuffer, frameCount,

mFrameSize); }

mCblkMemory = client->heap()->allocate(size);

Track类可以认为是对共享内存Buffer的管理,主要的设计体现在TrackBase类里。这个Buffer是一个循环Buffer,如图所示



在AudioTrack的set函数里,AudioTrack调用createTrack_l,其中AF调用了createTrack,创建了一个Client,对于ToneGenerator来说,每个Client都被分配了1M的内存,支持32个tracks,每个track 8个4k的buffer。然后,根据output找到对应的playback线程,然后该线程调用了createTrack_l,创建track,并且存入playback线程的mTracks数组。track定义在PlaybackThread文件中,继承于TrackBase。在track的构造函数需要两个参数,其一client是调用者(也就是AudioTrack)的pid,其二thread是playbackThread,AF分配匿名共享内存。这个track被封装成TrackHandle。也就是说,一个AudioTrack对应Playback线程中一个track。TrackHandle继承于BnTrackHandle,是Track的接口。在AF的createTrack中,作为返回值传给IAudioFlinger,经过track= interface_cast<IAudioTrack>(reply.readStrongBinder()),变成IAudioTrack,asInterface后就是BpAudioTrack。从此AudioTrack和Playback建立了共享内存和BinderRPC。AudioTrack通过操作IAudioTrack来操作AF中的track。 另外,AudioTrack在start,stop,pause等时,实质上是操作mAudioTrackThread和IAudioTrack。比如mAudioTrack->start()时,操作的是IAudioTrack,实际上是BpAudioTrack的start,然后到BnAudioTrack的start,最终操作到track的start。

每次track创建的时候,也就是TrackBase创建的时候,此时分配共享内存。都要分配一块大小为 采样数*采样精度*声道数+sizeof(audio_track_cblk_t)的内存。mBuffer就是“采样数*采样精度*声道数”这部分,并作为参数去newAudioTrackServerProxy(mCblk, mBuffer, frameCount,mFrameSize),最终调到Proxy的构造函数并赋值mBuffers,mBuffers用于在obtainBuffer时返回当前需要写或读的地址。对cblk的操作使用了代理模式,一个cblk有一个ClientProxy和ServerProxy,ServerProxy被AF使用,ClientProxy被AT或AR或AF中的outputTrack使用,client和server分别实现了obtainBuffer,二者实现略有不同。这是一个经典生产者消费者问题, 在audio_track_cblk_t 中,有一个volatile int32_t mFutex, 这个是生产者消费者PV操作的关键,代码中注释是:event flag: down (P) by client,up (V) by server or binderDied() or interrupt()。ClientProxy是生产者,响应的PV操作是__futex_syscall4,类似于wait,ServerProxy是消费者,相应的PV操作是__futex_syscall3,类似于Signal。另外AudioTrackClientProxy::waitStreamEndDone和AudioTrackServerProxy::setStreamEndDone也会wait和signal这个信号量。

所以总之就是:AT和AF共享一段匿名共享内存,通过信号量来同步对这块内存的操作。

当共享Buffer中有效数据小于需要的数据,就会造成underrun,这是造成播放声音断续的主要原因。

Underun的时候,EVENT_MORE_DATA和EVENT_UNDERRUN都会上报,所以,很多上层应用选择不处理EVENT_UNDERRUN,只处理EVENT_MORE_DATA。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值