AudioTrace工作原理
2016-05-13 19:47
645 查看
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。
相关文章推荐
- AudioTrace工作原理
- AudioTrace工作原理
- AudioTrace工作原理
- MVC DisplayTemplates and EdiotrTemplates.
- 埃森哲:物联网银行,下一个大趋势?
- Contiki教程——进程
- 浅析Alljoyn中设备的发现和连接
- 实用简介:MQTT协议及其在物联网中的应用
- IBM Watson物联网平台的两个MQTT工具
- bzoj3513 [MUTC2013]idiots
- 物联网学习资源整理
- 基于物联网的危险源智能监测平台
- IoT将如何改变我们与移动应用程序间的交互?
- IoT业界动态(即时更新)
- VisionMobile:2016年IoT大趋势(笔记)(六)物联网最热的商务模式
- VisionMobile:2016年IoT大趋势(笔记)(五)消费者和企业技术融合
- ESP8266 WIFI模块开发笔记一 NONRTOS开发
- 物联网兴起 嵌入式系统安全日益受关注
- 物联网【劲爆发现】免费云服务平台,AP透传,Web透传,ESP8266,Hex格式数据
- IoT嵌入式编程