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