分析AudioTrack之前先分析一下AudioTrack和MediaPlayer的區別:
-
AudioTrack 只能播放 pcm 原始數據,不能播放視頻。
-
MediaPlayer 可以播放視頻和音頻。
-
AudioTrack 只支持 pcm 原始音頻數據。
-
MediaPlayer 支持 mp3,wav,aac…
-
MediaPlayer 在底層會創建指定的格式的解碼器,將音頻數據轉化爲 pcm 然後再交給 pcm
去播放。MediaPlayer底層會創建 AudioTrack,將解碼後的數據交給 AudioTrack 播放。 -
每一個音頻流對應着一個AudioTrack類的一個實例,每個AudioTrack會在創建時註冊到
AudioFlinger中,由AudioFlinger把所有的AudioTrack進行混合(Mixer),然後輸送到AudioHardware中進行播放,目前Android同時最多可以創建32個音頻流,也就是說,Mixer最多會同時處理32個AudioTrack的數據流。
個人感覺AudioTrack梳理起來的過程是非常痛苦的,中間可能也有很多問題,參考了很多博客,還有實習師傅的指導,整理一篇Android P的AudioTrack流程初文出來,以後工作用的多了熟悉了,再修改。
AudioTrack的構造函數分析:
android\frameworks\base\media\java\android\media\AudioTrack.java
走private的構造函數。
獲取主線程的Looper,異步消息通信的機制。
獲取採樣率,聲道掩碼,編碼類型,然後驗證參數是否合法
調用native層的native_setup
native_setup()
android\frameworks\base\core\jni\android_media_AudioTrack.cpp
進入JNI層
創建native層的AudioTrack。
android\frameworks\av\media\libaudioclient\AudioTrack.cpp
進到lib層,通過set()方法將參數設置進去
status_t AudioTrack::set()
創建IAudioTrack.
獲取音頻策略服務。
frameworks\av\media\libaudioclient\AudioSystem.cpp
通過binder機制綁定服務。
android\frameworks\av\media\libaudioclient\AudioTrack.cpp
進入AudioFlinger
android\frameworks\av\services\audioflinger\AudioFlinger.cpp
依據播放線程ID號查找出相應的PlaybackThread,依據客戶端進程pid查找是否已經爲該客戶進程創建了Client對象。假設沒有,則創建一個Client對象。
依據進程pid。爲請求播放音頻的client創建一個Client對象。
AudioFlinger的成員變量mClients以鍵值對的形式保存pid和Client對象。這裏首先取出pid相應的Client對象,假設該對象爲空。則爲client進程創建一個新的Client對象。MemoryDealer是個工具類。用於分配共享內存。每個Client都擁有一個MemoryDealer對象,這就意味着每個client進程都是在自己獨有的內存空間中分配共享內存。
創建瞭如同所示的內存大小。
返回繼續看AudioFlinger::createTrack()
frameworks\av\services\audioflinger\Threads.cpp
創建Track對象
前面進行一系列的參數賦值,最後返回一個track對象。
進入Track的構造函數,由圖可見,繼承於TrackBase,因此先進入TrackBase的構造函數進行分析。
TrackBase()
thread,所屬播放線程,client所屬的客戶端,sampleRate,採樣率,format音頻格式,channelMask,聲道,frameCount,音頻幀個數。sharedBuffer,共享內存。
得到應用進程id
計算存放音頻的buffer大小。
Client不爲空。就通過Client來分配buffer,爲空,則通過mallc動態分配。
由此可見,TrackBase構造過程主要是爲音頻播放分配共享內存。
接着進入Track的構造函數進行分析。
爲0創建AudioTrackServerProxy代理對象,不爲0,創建StaticAudioTrackServerProxy代理對象;
接下來我們返回AudioFlinger的createTrack函數中,來看這個track對象到底做了什麼事情。
android\frameworks\av\services\audioflinger\AudioFlinger.cpp
創建Track的binder對象TrackHandle,Track由於需要通過binder返回給AudioTrack,因此是個binder對象,該對象會包含share buffer的信息。由於share buffer不止會在AudioFlinger這端被讀取,還會在AudioTrack這端被寫入,因此創建出來的Track需要被傳送回AudioTrack。而在binder間傳送對象只有binder對象,因此需要構建binder對象TrackHandle,返回給AudioTrack。
frameworks\av\services\audioflinger\Tracks.cpp
至此,createTrack_l在AudioFlinger這端的工作基本完成了。
ps:這裏我繞的不太清楚:可參考其他博客:[Android] createTrack_l
frameworks\av\media\libaudioclient\AudioTrack.cpp
返回AudioTrack.cpp中的creatTrack中。
實在走不到底層去,不知道哪裏走錯了或者沒有分析到
之後完全理清在修改是否有問題吧。
構造函數暫時分析至此。