Android Audio:AudioTrack構造函數分析

分析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中。
在這裏插入圖片描述
實在走不到底層去,不知道哪裏走錯了或者沒有分析到在這裏插入圖片描述

之後完全理清在修改是否有問題吧。

構造函數暫時分析至此。
在這裏插入圖片描述

發佈了45 篇原創文章 · 獲贊 14 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章