Android音频架构总结


一.音频总体的架构:
 
 
二.Audio Policy
Stream 类型选择合适的 device :
音频管理策略管理音频的输入输出,它 决定各种类型的声音优先送往系统哪个输 出设备,或使用哪个输入设备进行采样。
比如,如果有蓝牙耳机或者耳机,将优 先使用他们作为输入输出设备。
创建 AudioTrack 的时候会传入一个 Stream 类型,根据这个类型获得 strategy, 然后根据 strategy 获得一个 device。
 
Stream 类型选择合适的 Strategy 类型 :
第一栏是流的类型,第二栏是音频策略
从表中可以看出,某些流可以使用相同 的音频策略进行输入或者输出。
 
Strategy 类型选择合适的 device :
第一栏是 Strategy 的类型,第二栏是 device
按照一定的优先级顺序,检查哪些可用的输入 输出设备,然后选择一个设备用来输入输出。
 
 
三. Audio 使用
比如音乐播放器,录音机 APK 进行录音或播放。
播放声音能够用 MediaPlayer AudioTrack MediaRecorder AudioRecord 进行录音。
MediaPlayer framework 层还是会创建 AudioTrack 把解码后的 PCM 数流传递给 AudioTrack。AudioTrack 再传递给  AudioFlinger 进行混音,然后才传递给硬件播放 , 所以是 MediaPlayer 包括了 AudioTrack
 
 
四. Audio播放流程
Android 的播放架构图

 
播放流程一般分为三个部分:
 
1. AudioTrack 构造;
Framework或者APP层通过JNI创建AudioTrack (JAVA)对象;
调用到android_media_AudioRecord_setup(JNI),然后创建一个AudioRecord(C++);
AudioRecord(C++)会调用getOutputForAttr,这个函数会调用到AudioPolicy,根据策略选择输出设备;
AudioTrack(C++)通过binder机制调用AudioFlingercreateTrack()创建Track,同时分配共享内存
AudioFlinger拥有多个工作线程,每一个线程拥有多个Track
每一个音频流对应着一个AudioTrack类的一个实例,每个AudioTrack会在创建时注册到 AudioFlinger中,由AudioFlinger把所有的AudioTrack进行混合(Mixer),然后输送到AudioHardware中进行播放。
目前Android同时最多可以创建32个音频流,也就是说,Mixer最多会同时处理32AudioTrack 的数据流
2. AudioTrack Start
Framework 或者 APP 层调用 AudioTrack(java) play() 进行音频播放的准备 ;
play() 会调用 jni native_start (), 对应的函数是 android_media_AudioTrack_start();
android_media_AudioTrack_start () 只是做了转发,最后会调用 AudioTrack (C++) start();
AudioTrack start() 进过转发 最后会调用 PlaybackThread start();
PlaybackThread start() 的又会调用 addTrack_l();
PlaybackTread addTrack_l 主要工作是添加 track mActiveTracks, 并激活沉睡的 PlaybackTread 线程
 
3. AudioTrack Write
Framework 或者 APP 层调用 AudioTrack(java) AudioTrack(java) write() 写入音频数据 ;
调用 jni android_media_AudioTrack_write_byte() ,主要是获取 java 传下来的数据,并调用 writeToTrack() 来向共享内存写入数据 ;
writeToTrack () 调用 AudioTrack(c++) write() AudioTrack(C++) 会使用 obtainBuffer 获取一块共享内存, 并写入数据,写完后用 releaseBuffer 释放共享内存。
服务端读取共享内存的音频数据是在 PlaybackThread threadLoop() 中进行的,调用 threadLoop_mix() 进行混音 ;
完成混音后,调用 threadLoop_write (), 它会调用 mOutput->stream->write() 写入,这里会调用到 HAL ;
HAL 层的调用 tiny_alsa pcm_open() 打开相应的录音设备,再通过 pcm_write() 写入音频数据到 linux 系统,再到硬件。

四.Audio录音流程
Android的录音架构图
 
 
1. AudioRecord 构造过程 :
Framework 或者 APP 层通过 JNI 创建 AudioRecord (JAVA) 对象 ;
调用到 android_media_AudioRecord_setup(JNI), 然后创建一个 AudioRecord(C++);
AudioRecord 会通过 AudioSystem::getInputForAttr ,这个函数会调用到 AudioPolicy ,根据策略选择输出设备 ;
AudioRecord 通过 binder 机制调用 AudioFlinger createRecordTrack_l() 创建 RecordTrack ,同时分配共享内存
 
2. AudioRecord Start :
Framework 或者 APP 层调用 AudioTrack(java) startRecording() 进行音频播放的准备 ;
startRecording() 会调用 jni native_start(), 对应的函数是 android_media_AudioRecord_start();
android_media_AudioRecord_start() 只是做了转发,最后会调用 AudioRecord(c++) start();
AudioRecord start 又会调用 TrackHandle( 服务端的 Track 代理 ) start, 最后会调用到 RecordThread start();
RecordThread start() 会激活沉睡的 RecordThread 。
3. AudioRecord Read :
Framework 或者 APP 层调用 AudioRecord(java) AudioTrack(java) read 读取音频数据 ;
调用 jni android_media_AudioRecord_readInByteArray ,调用 AudioTrack(c++) read 读取数据 ;
AudioTrack(C++) 会使用 obtainBuffer 获取一块共享内存, 并读取数据 ;
服务端读取共享内存的音频数据是在 RecordThread threadLoop() 中进行 ;
调用 mInput->stream->read 读取,这里会调用到 HAL ;
HAL 层的调用 tiny_alsa pcm_open 打开设备,然后通过 pcm_read() 读取相应设备数据。
 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM