Android音频架构总结

一.音频总体的架构:
 
 
二.Audio Policy
Stream类型选择合适的device :
音频管理策略管理音频的输入输出,它决定各种类型的声音优先送往系统哪个输出设备,或使用哪个输入设备进行采样。
比如,如果有蓝牙耳机或者耳机,将优先使用他们作为输入输出设备。
创建AudioTrack的时候会传入一个Stream类型,根据这个类型获得strategy,然后根据strategy获得一个device。
 
Stream类型选择合适的Strategy类型 :
第一栏是流的类型,第二栏是音频策略
从表中可以看出,某些流可以使用相同的音频策略进行输入或者输出。
 
Strategy类型选择合适的device :
第一栏是Strategy的类型,第二栏是device
按照一定的优先级顺序,检查哪些可用的输入输出设备,然后选择一个设备用来输入输出。
 
 
三.Audio使用
比如音乐播放器,录音机APK进行录音或播放。
播放声音能够用MediaPlayerAudioTrackMediaRecorderAudioRecord进行录音。
MediaPlayerframework层还是会创建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.AudioTrackStart
Framework或者APP层调用AudioTrack(java)play()进行音频播放的准备;
play()会调用jninative_start(),对应的函数是android_media_AudioTrack_start();
android_media_AudioTrack_start()只是做了转发,最后会调用 AudioTrack(C++)start();
AudioTrackstart()进过转发最后会调用PlaybackThreadstart();
PlaybackThreadstart()的又会调用addTrack_l();
PlaybackTreadaddTrack_l主要工作是添加trackmActiveTracks, 并激活沉睡的PlaybackTread线程
 
3.AudioTrackWrite
Framework或者APP层调用AudioTrack(java)AudioTrack(java)write()写入音频数据;
调用jniandroid_media_AudioTrack_write_byte(),主要是获取java传下来的数据,并调用writeToTrack()来向共享内存写入数据;
writeToTrack()调用AudioTrack(c++)write()AudioTrack(C++)会使用obtainBuffer获取一块共享内存, 并写入数据,写完后用releaseBuffer释放共享内存。
服务端读取共享内存的音频数据是在PlaybackThreadthreadLoop()中进行的,调用threadLoop_mix()进行混音;
完成混音后,调用 threadLoop_write(),它会调用mOutput->stream->write()写入,这里会调用到HAL;
HAL层的调用tiny_alsapcm_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机制调用AudioFlingercreateRecordTrack_l()创建RecordTrack,同时分配共享内存
 
2.AudioRecordStart :
Framework或者APP层调用AudioTrack(java)startRecording()进行音频播放的准备;
startRecording()会调用jninative_start(),对应的函数是android_media_AudioRecord_start();
android_media_AudioRecord_start()只是做了转发,最后会调用 AudioRecord(c++)start();
AudioRecordstart又会调用TrackHandle(服务端的Track代理) start,最后会调用到RecordThreadstart();
RecordThreadstart()会激活沉睡的RecordThread 。
3.AudioRecordRead :
Framework或者APP层调用AudioRecord(java)AudioTrack(java)read读取音频数据;
调用jniandroid_media_AudioRecord_readInByteArray ,调用AudioTrack(c++)read读取数据;
AudioTrack(C++)会使用obtainBuffer获取一块共享内存, 并读取数据;
服务端读取共享内存的音频数据是在RecordThreadthreadLoop()中进行;
调用 mInput->stream->read读取,这里会调用到HAL;
HAL层的调用tiny_alsapcm_open打开设备,然后通过pcm_read()读取相应设备数据。
 
posted @ 2021-02-05 18:00  luoyuna  阅读(3938)  评论(0编辑  收藏  举报