1. 程式人生 > >4.0音訊系統HAL初探

4.0音訊系統HAL初探

轉載自:

昨天(2011-11-15)釋出了Android4.0的原始碼,今天download下來,開始挺進4.0時代。簡單看了一下,發現音訊系統方面與2.3的有較多地方不同,下面逐一描述。

一、程式碼模組位置

1、AudioFlinger

  1. frameworks/base/services/audioflinger/  
  2. +-- Android.mk  
  3. +-- AudioBufferProvider.h  
  4. +-- AudioFlinger.cpp  
  5. +-- AudioFlinger.h  
  6. +-- AudioMixer.cpp  
  7. +-- AudioMixer.h  
  8. +-- AudioPolicyService.cpp  
  9. +-- AudioPolicyService.h  
  10. +-- AudioResampler.cpp  
  11. +-- AudioResamplerCubic.cpp  
  12. +-- AudioResamplerCubic.h  
  13. +-- AudioResampler.h  
  14. +-- AudioResamplerSinc.cpp  
  15. +-- AudioResamplerSinc.h  
AudioFlinger相關程式碼,好像這部分與2.3相差不大,至少介面是相容的。值得注意的是:2.3位於這裡的還有AudioHardwareGeneric、AudioHardwareInterface、A2dpAudioInterface等一系列介面程式碼,現在都移除了。實際上,這些介面變更為legacy(有另外更好的實現方式,但也相容之前的方法),取而代之的是要實現hardware/libhardware/include/hardware/audio.h提供的介面,這是一個較大的變化。 兩種Audio Hardware HAL介面定義: 1/ legacy:hardware/libhardware_legacy/include/hardware_legacy/AudioHardwareInterface.h 2/ current:hardware/libhardware/include/hardware/audio.h

2、audio_hw

  1. hardware/libhardware_legacy/audio/  
  2. +-- A2dpAudioInterface.cpp  
  3. +-- A2dpAudioInterface.h  
  4. +-- Android.mk  
  5. +-- AudioDumpInterface.cpp  
  6. +-- AudioDumpInterface.h  
  7. +-- AudioHardwareGeneric.cpp  
  8. +-- AudioHardwareGeneric.h  
  9. +-- AudioHardwareInterface.cpp  
  10. +-- AudioHardwareStub.cpp  
  11. +-- AudioHardwareStub.h  
  12. +-- audio_hw_hal.cpp  
  13. +-- AudioPolicyCompatClient.cpp  
  14. +-- AudioPolicyCompatClient.h  
  15. +-- audio_policy_hal.cpp  
  16. +-- AudioPolicyManagerBase.cpp  
  17. +-- AudioPolicyManagerDefault.cpp  
  18. +-- AudioPolicyManagerDefault.h  
上面提及的AudioHardwareGeneric、AudioHardwareInterface、A2dpAudioInterface等都放到libhardware_legacy裡。 事實上legacy也要封裝成current中的audio.h,確切的說需要一個聯絡legacy interface和not legacy interface的中間層,這裡的audio_hw_hal.cpp就充當這樣的一個角色了。因此,我們其實也可以把2.3之前的alsa_sound這一套東西也搬過來。
  1. hardware/libhardware/modules/audio/  
  2. +-- Android.mk  
  3. +-- audio_hw.c  
  4. +-- audio_policy.c  
這是一個stub(類似於2.3中的AudioHardwareStub),大多數函式只是簡單的返回一個值,並沒有實際操作,只是保證Android能得到一個audio hardware hal例項,從而啟動執行,當然聲音沒有輸出到外設的。在底層音訊驅動或audio hardware hal還沒有實現好的情況下,可以使用這個stub device,先讓Android跑起來。
  1. device/samsung/tuna/audio/  
  2. +-- Android.mk  
  3. +-- audio_hw.c  
  4. +-- ril_interface.c  
  5. +-- ril_interface.h  
這是Samsung Tuna的音訊裝置抽象層,很有參考價值,計劃以後就在它的基礎上進行移植。它呼叫tinyalsa的介面,可見這個方案的底層音訊驅動是alsa。

3、tinyalsa

  1. external/tinyalsa/  
  2. +-- Android.mk  
  3. +-- include  
  4. |   +-- tinyalsa  
  5. |       +-- asoundlib.h  
  6. +-- mixer.c      ##類alsa-lib的control,作用音訊部件開關、音量調節等  
  7. +-- pcm.c        ##類alsa-lib的pcm,作用音訊pcm資料回放錄製  
  8. +-- README  
  9. +-- tinycap.c    ##類alsa_arecord  
  10. +-- tinymix.c    ##類alsa_amixer  
  11. +-- tinyplay.c   ##類alsa_aplay  
在2.3時代,Android還隱晦把它放在android2.3.1-gingerbread/device/samsung/crespo/libaudio,現在終於把alsa-lib一腳踢開,小三變正室了,正名tinyalsa。 這其實是歷史的必然了,alsa-lib太過複雜繁瑣了,我看得也很不爽;更重要的商業上面的考慮,必須移除被GNU GPL授權證所約束的部份,alsa-lib並不是個例。

注意:上面的hardware/libhardware_legacy/audio/、hardware/libhardware/modules/audio/、device/samsung/tuna/audio/是同層的。之一是legacy audio,用於相容2.2時代的alsa_sound;之二是stub audio介面;之三是Samsung Tuna的音訊抽象層實現。呼叫層次:AudioFlinger -> audio_hw -> tinyalsa。

二、Audio Hardware HAL載入

1、AudioFlinger

  1. //載入audio hardware hal
  2. staticint load_audio_interface(constchar *if_name, const hw_module_t **mod,  
  3.                                 audio_hw_device_t **dev)  
  4. {  
  5.     int rc;  
  6.     //根據classid和if_name找到指定的動態庫並載入,這裡載入的是音訊動態庫,如libaudio.primary.tuna.so
  7.     rc = hw_get_module_by_class(AUDIO_HARDWARE_MODULE_ID, if_name, mod);  
  8.     if (rc)  
  9.         goto out;  
  10.     //載入好的動態庫模組必有個open方法,呼叫open方法開啟音訊裝置模組
  11.     rc = audio_hw_device_open(*mod, dev);  
  12.     LOGE_IF(rc, "couldn't open audio hw device in %s.%s (%s)",  
  13.             AUDIO_HARDWARE_MODULE_ID, if_name, strerror(-rc));  
  14.     if (rc)  
  15.         goto out;  
  16.     return 0;  
  17. out:  
  18.     *mod = NULL;  
  19.     *dev = NULL;  
  20.     return rc;  
  21. }  
  22. //音訊裝置介面,hw_get_module_by_class需要根據這些字串找到相關的音訊模組庫
  23. staticconstchar *audio_interfaces[] = {  
  24.     "primary"//主音訊裝置,一般為本機codec
  25.     "a2dp",    //a2dp裝置,藍芽高保真音訊
  26.     "usb",     //usb-audio裝置,這個東東我2.3就考慮要實現了,現在終於支援了
  27. };  
  28. #define ARRAY_SIZE(x) (sizeof((x))/sizeof(((x)[0])))
  29. // ----------------------------------------------------------------------------
  30. AudioFlinger::AudioFlinger()  
  31.     : BnAudioFlinger(),  
  32.         mPrimaryHardwareDev(0), mMasterVolume(1.0f), mMasterMute(false), mNextUniqueId(1),  
  33.         mBtNrecIsOff(false)  
  34. {  
  35. }  
  36. void AudioFlinger::onFirstRef()  
  37. {  
  38.     int rc = 0;  
  39.     Mutex::Autolock _l(mLock);  
  40.     /* TODO: move all this work into an Init() function */
  41.     mHardwareStatus = AUDIO_HW_IDLE;  
  42.     //開啟audio_interfaces陣列定義的所有音訊裝置
  43.     for (size_t i = 0; i < ARRAY_SIZE(audio_interfaces); i++) {  
  44.         const hw_module_t *mod;  
  45.         audio_hw_device_t *dev;  
  46.         rc = load_audio_interface(audio_interfaces[i], &mod, &dev);  
  47.         if (rc)  
  48.             continue;  
  49.         LOGI("Loaded %s audio interface from %s (%s)", audio_interfaces[i],  
  50.              mod->name, mod->id);  
  51.         mAudioHwDevs.push(dev); //mAudioHwDevs是一個Vector,儲存已開啟的audio hw devices
  52.         if (!mPrimaryHardwareDev) {  
  53.             mPrimaryHardwareDev = dev;  
  54.             LOGI("Using '%s' (%s.%s) as the primary audio interface",  
  55.                  mod->name, mod->id, audio_interfaces[i]);  
  56.         }  
  57.     }  
  58.     mHardwareStatus = AUDIO_HW_INIT;  
  59.     if (!mPrimaryHardwareDev || mAudioHwDevs.size() == 0) {  
  60.         LOGE("Primary audio interface not found");  
  61.         return;  
  62.     }  
  63.     //對audio hw devices進行一些初始化,如mode、master volume的設定
  64.     for (size_t i = 0; i < mAudioHwDevs.size(); i++) {  
  65.         audio_hw_device_t *dev = mAudioHwDevs[i];  
  66.         mHardwareStatus = AUDIO_HW_INIT;  
  67.         rc = dev->init_check(dev);  
  68.         if (rc == 0) {  
  69.             AutoMutex lock(mHardwareLock);  
  70.             mMode = AUDIO_MODE_NORMAL;  
  71.             mHardwareStatus = AUDIO_HW_SET_MODE;  
  72.             dev->set_mode(dev, mMode);  
  73.             mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME;  
  74.             dev->set_master_volume(dev, 1.0f);  
  75.             mHardwareStatus = AUDIO_HW_IDLE;  
  76.         }  
  77.     }  
  78. }  

以上對AudioFlinger進行的分析,主要是通過hw_get_module_by_class()找到模組介面名字if_name相匹配的模組庫,載入,然後audio_hw_device_open()呼叫模組的open方法,完成音訊裝置模組的初始化。
留意AudioFlinger的建構函式只有簡單的私有變數的初始化操作了,把音訊裝置初始化放到onFirstRef(),Android終於改進了這一點,好的設計根本不應該把可能會失敗的操作放到建構函式中。onFirstRef是RefBase類的一個虛擬函式,在構造sp的時候就會被呼叫。因此,在構造sp<AudioFlinger>的時候就會觸發onFirstRef方法,從而完成音訊裝置模組初始化。

2、hw_get_module_by_class

我們接下來看看hw_get_module_by_class,實現在hardware/libhardware/ hardware.c中,它作用載入指定名字的模組庫(.so檔案),這個應該是用於載入所有硬體裝置相關的庫檔案,並不只是音訊裝置。
  1. int hw_get_module_by_class(constchar *class_id, constchar *inst,  
  2.                            conststruct hw_module_t **module)  
  3. {  
  4.     int status;  
  5.     int i;  
  6.     conststruct hw_module_t *hmi = NULL;  
  7.     char prop[PATH_MAX];  
  8.     char path[PATH_MAX];  
  9.     char name[PATH_MAX];  
  10.     if (inst)  
  11.         snprintf(name, PATH_MAX, "%s.%s", class_id, inst);  
  12.     else
  13.         strlcpy(name, class_id, PATH_MAX);  
  14.     //這裡我們以音訊庫為例,AudioFlinger呼叫到這個函式時,
  15. 相關推薦

    4.0音訊系統HAL初探

    轉載自: 昨天(2011-11-15)釋出了Android4.0的原始碼,今天download下來,開始挺進4.0時代。簡單看了一下,發現音訊系統方面與2.3的有較多地方不同,下面逐一描述。 一、程式碼模組位置 1、AudioFlinge

    android之4.0系統主題style修改android:Theme.Holo.Light

    1.修改主介面背景顏色 轉自http://www.dewen.io/q/9466 在AndroidMenifest.xml application 屬性設定時不使用系統的 android:theme="@android:style/Theme.Holo", 而是自定義的

    魅族4.0以上系統怎麽樣無root激活Xposed框架的方法

    root權限 激活 容易 https nag 安裝 fda jpg 一點 在越來越多單位的引流或者業務操作中,基本都需要使用安卓的強大XPOSED框架,近來,我們單位買來了一批新的魅族4.0以上系統,基本都都是基於7.0以上系統,基本都不能夠獲取ROOT權限,即便是小部分可

    OAuth2.0學習(4-4)關於系統中有多少個 authenticationManager

    imp lan 需要 o-c detail session oauth ref nag 文章參考: http://blog.csdn.net/foggysource/article/details/39456963 首先是http的配置,authentication-m

    基於ASP.NET 4.0開發的微商城系統OdnShop,開源發布

    如果 支付 程序 TP 選項 虛擬 字符串 如果能 均可 基於ASP.NET 4.0開發的開源微商城系統,我們的目標是構建一個核心完善而又輕量級的微商城平臺,目前基本的核心功能,包括微信登陸/支付,產品管理,購物車與訂單管理等,輕量級是為了更加便於理解源碼和二次開發。 使

    Unity 4.0 中的新動畫系統——MecAnim

    alt clas 講解 unit 組件 之一 new src align   分享一個文檔資料,關於動畫系統的,版本應該很老了,但是有借鑒意義的;     Unity 4.0 已於 2012 年 11 月 15 日正式發布,Unity 每一次版本的提升,都給遊戲開發者帶來

    基於ffmpeg-4.0 SDK的音訊重取樣

    /* * Copyright (c) 2012 Stefano Sabatini * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and a

    ubuntu16.04下編譯android-goldfish-3.4核心原始碼(android6.0.1系統原始碼)

    配置 筆者環境 系統: ubuntu 16.04 LTS 硬碟: 固態硬碟 筆者剛開始直接克隆的時候出現如下錯誤: error: RPC failed; curl 56 GnuTLS recv error (-9): A TLS packet with unexp

    Ubuntu14.04系統下安裝OpenCV 4.0.0開發環境全過程

    最近研究一個專案時需要用到OpenCV,於是自己嘗試在Ubuntu 14.04系統下安裝了這個開發環境。下面就將具體的過程記錄一下,便於後期查閱和同行分享。 〇、開發環境 首先介紹一下我的開發環境: 物理系統:Win 10 64位; 虛擬工具:Virtualbo

    Android 4 0 事件輸入 Event Input 系統

                     1. TouchScreen功能在Android4.0下不工作       原來在Android2.3.5下能正常工作的TouchScreen功能,移植到Android 4.0就不能正常工作了。憑直覺,Android4.0肯定有鬼。真是不看不知道,一看嚇一跳。在Android

    躺雨沒的學習筆記(4)——藍芽系統架構 (2.0 核心系統架構)

    Agenda: 2.0 核心系統架構 (181頁)藍芽核心系統包括一個主機,一個主要控制器和零到多個次要控制器。 2.0.1 藍芽BR/EDR最小系統 藍芽BR/EDR最小核心系統包括: 控制器中四個最底層,BR/EDR射頻物理層

    Windows系統安裝Redis 4.0

    一、Redis 4.0 Windows安裝檔案下載 下載地址:https://download.csdn.net/download/simple_bo/10753481 二、Redis 安裝 安裝步驟如下: 雙擊安裝檔案,點選next。 這裡勾選上accept,點選next

    MES系統與工業4.0: 概念和現實的有機融合

    首先,大規模定製產品的要求可能是工業4.0最重要的推動力。 實際上,並非所有現在生產的產品都會減少到一個生產批量,至少在不久的將來不會,但是MES能夠滿足大規模生產商品的要求,即使規格略有不同。應該也是一個非常搶手的要求。 只有允許存在動態市場的MES ,才能真

    工業4.0中的MES系統的預防糾正作用將如何發展?

    質量和維護是製造業中最重要的兩個功能區域。 自第一條裝配線建立以來,大規模生產的產品質量和車間裝置的及時維護始終是一項挑戰,關鍵點在於:實現最少的裝置故障並確保最大的正常執行時間。 當軟體在製造業中引入時,它最初的作用是管理物料資源,隨後MES出現,在流程執行中慢慢地轉向計劃和產品質

    Guns 旗艦版 v1.0 釋出:升級 bootstrap 4.0,更簡潔的管理系統

       大家好,這將是Guns2018年最後一個版,前端整體框架大升級,後端資料庫設計更規範合理,是這一年的嘔心瀝血之作!!兩年了,開源不易,感謝大家支援! Guns旗艦版v1.0 更新說明: 前端頁面風格和架構煥然一新,全面升級bootstrap 4.0,您現在擁有兩種介面

    spagobi 4.0 中文問題初探

             Spagobi4.0版本出來有一段時間了,之前忙於專案,沒有時間專門研究下新版的中文問題。聽有的網友說,新版本支援中文輸入了,但是中文顯示上還有些問題。於是,從官網上下載了最新版的 all in one包。解壓,啟動。進入登入介面,眼前一亮。新版本在登入介

    在Redhat9文本系統上安裝Qt Embedded 4.4.0

    Qt Embedded 直接依賴Framebuffer,無需X-Window。所以要開啟Linux系統的Framebuffer。開啟方法是通過BootLoader向核心傳遞引數: 對於grub,在grub.conf檔案的kernel 命令後面新增 vga=0x311 fb

    Android後臺保活4.0~8.0系統(一)

    一:前言 在談保活之前,我們應該知道隨著Android系統的不斷髮展,系統管控越來越嚴格,後臺保活將是一個偽命題了,後臺保活主要是和推送相關,隨著技術的發展,泰爾終端實驗室也制定了統一的推送標準,我想在後面Android會像Iphone一樣,使用統一系統服務進

    Apache OpenMeetings 4.0.7 釋出,視訊會議系統

       Apache OpenMeetings 4.0.7 釋出了,OpenMeetings 是一個多語言可定製的視訊會議和協作系統。它支援音訊、視訊,能讓你檢視每個與會者的桌面。OpenMeetings 還包含一個白板,通過白板可以匯入各種格式的圖片和塗鴉。 更新如下

    解決win系統無法安裝.NET Framework 4.0 4.6 原因是HRESULT0xc8000222

    1.開始----- 執行------- cmd ----- 鍵入net stop WuAuServ回車(停止windows update服務) 2.開始----- 執行----鍵入%windir%回車(開啟系統目錄)將SoftwareDistribution資料夾重新命名為SDold 3.開始-----