ANDROID2.3音頻系統HAL

從大的方面來說,Android2.3的音頻系統架構與Android2.2相比並沒有太多的改變。對2.2的音頻架構分析依然適用於2.3,之前很多人已經對這方面進行非常詳盡的闡述,這裏就不重複了。各模塊文件的存放位置有所變更,這點倒是要了解的。

1、有個較大的改進的是引入了mixable audio effects系統。我草草翻了翻代碼,應該是opensles實現的。opensles也是2.3新引入的一個音頻庫,這使得Android的音效變得更強大。但應該會犧牲一些性能,比方說之前Android Framework層固定audio sample rate爲44.1khz,對音頻流進行resample(AudioResampler.cpp),這使得audio相關線程CPU佔用率非常高。

Android給我的感覺就是太照顧開發者了。縱然是底層都有很多地方使用跨平臺軟件方法,儘量減少HAL,如mixer、equalizer等。mixer還算好,起碼在AudioHardwareInterface.h有提供接口供HAL實現,聲音特效如equalizer就只是軟件實現了。有關HAL的實現參考hardware和device這兩個目錄的文件;對於audio,android2.3.1-gingerbread/device/samsung/crespo/libaudio是極具價值的,我估計就算移植另一個平臺,對於這部分的改動都是非常少的。

2、Android2.2時代還保留opencore多媒體框架,雖然只使用了omx-component,其他默認情況下選擇了stagefright。而2.3則完全使用了stagefright,opencore也從android中移除了。有關opencore和stagefright的介紹見:http://blogold.chinaunix.net/u2/61880/showart.php?id=2339481

與opencore同一命運的是alsa-lib。開始時我挺吃驚的,opencore可以用stagefright來替代,但是有什麼音頻底層庫可以替代alsa-lib?看到android2.3.1-gingerbread/device/samsung/crespo/libaudio才釋然,原來其中的alsa_pcm.c和alsa_mixer.c實現了一個迷你的alsa-lib。

我想在今後的版本中,Google可能還會繼續幹同樣的事,不斷移除一些開源庫,而實現自己的一套,顯得更簡潔。以我個人來說是不大喜歡這個做法。開源庫往往功能更強大,接口也標準,現在開發者又要多花稍許時間去熟悉android閹割版的接口--或許多慮了,畢竟開發者很少會去改動framework層;還有就是開源庫還會不斷更新修正,Google能不能跟上也難說。

 


--------------------------------------------------------------------------------

4/9 2011

稍微分析一下Audio HAL即audioflinger以下,因爲看了網上幾篇文章,看起來有些錯誤或許闡述得不夠清晰。

首先AudioFlinger.cpp:

AudioFlinger::AudioFlinger()
    : BnAudioFlinger(),
        mAudioHardware(0), mMasterVolume(1.0f), mMasterMute(false), mNextUniqueId(1)
{
    mHardwareStatus = AUDIO_HW_IDLE;

    mAudioHardware = AudioHardwareInterface::create();

    mHardwareStatus = AUDIO_HW_INIT;
    if (mAudioHardware->initCheck() == NO_ERROR) {
        // open 16-bit output stream for s/w mixer
        mMode = AudioSystem::MODE_NORMAL;
        setMode(mMode);

        setMasterVolume(1.0f);
        setMasterMute(false);
    } else {
        LOGE("Couldn't even initialize the stubbed audio hardware!");
    }
#ifdef LVMX
    LifeVibes::init();
    mLifeVibesClientPid = -1;
#endif

可以看到紅色部分是通過AudioHardwareInterface.create來創建一個audio hardware接口,我們追溯到AudioHardwareInterface.cpp:

AudioHardwareInterface* AudioHardwareInterface::create()
{
    /*
     * FIXME: This code needs to instantiate the correct audio device
     * interface. For now - we use compile-time switches.
     */
    AudioHardwareInterface* hw = 0;
    char value[PROPERTY_VALUE_MAX];

#ifdef GENERIC_AUDIO
    hw = new AudioHardwareGeneric();
#else
    // if running in emulation - use the emulator driver
    if (property_get("ro.kernel.qemu", value, 0)) {
        LOGD("Running in emulation - using generic audio driver");
        hw = new AudioHardwareGeneric();
    }
    else {
        LOGV("Creating Vendor Specific AudioHardware");
        hw = createAudioHardware();
    }
#endif
    if (hw->initCheck() != NO_ERROR) {
        LOGW("Using stubbed audio hardware. No sound will be produced.");
        delete hw;
        hw = new AudioHardwareStub();
    }
   
#ifdef WITH_A2DP
    hw = new A2dpAudioInterface(hw);
#endif

#ifdef ENABLE_AUDIO_DUMP
    // This code adds a record of buffers in a file to write calls made by AudioFlinger.
    // It replaces the current AudioHardwareInterface object by an intermediate one which
    // will record buffers in a file (after sending them to hardware) for testing purpose.
    // This feature is enabled by defining symbol ENABLE_AUDIO_DUMP.
    // The output file is set with setParameters("test_cmd_file_name=<name>"). Pause are not recorded in the file.
    LOGV("opening PCM dump interface");
    hw = new AudioDumpInterface(hw);    // replace interface
#endif
    return hw;
}

以不同的顏色區分,這裏可以支持6種audio接口,分別爲:

1、Generic Audio:是Android默認選中的audio hardware,操作底層設備節點是/dev/eac,具體見AudioHardwareGeneric.cpp。我沒深入瞭解這個接口對應的底層驅動。

2、Emulator Audio:也是用Generic Audio。

3、Vendor Specific Audio:廠商自定義audio hardware接口,這是我們的重點,一般來說我們需要實現的就是這個接口,稍後重點分析一下。

4、A2DP Audio:藍牙音頻,沒有深入瞭解。

5、Stubbed Audio:實現方法在AudioHardwareStub.cpp,可以看到大多數函數只是返回一個值,並沒有實際操作。它只是保證Android最起碼能得到一個audio hardware實例,從而使其啓動運行,當然是沒有聲音的。

6、Dump Audio:詳細見註釋,主要用來調試上層音頻程序,將上層record的聲音保存到一個文件中,方便分析。

Vendor Specific Audio

一般我們只需要實現hardware/libhardware_legacy/include/hardware_legacy/AudioHardwareInterface.h提供的接口就可以了,然後extern "C" AudioHardwareInterface* createAudioHardware(void);方便AudioHardwareInterface* AudioHardwareInterface::create()調用。

以samsung的crespo爲例,device/samsung/crespo/libaudio/AudioHardware.cpp,它實現一個AudioHardware的類,其方法也是根據AudioHardwareInterface.h提供的純虛函數接口來實現的。

extern "C" AudioHardwareInterface* createAudioHardware(void) {
    return new AudioHardware();
}

注:如開篇所說,Android2.3已經去掉了alsa-lib,這裏其實調用到底層還是alsa-driver,它實現了一個mini alsa-lib,有興趣的可以看看。當然根據需要也可以用其他的音頻驅動架構如OSS或許廠商自己的固件(不開源的,想來Android HAL也是這個目的)。

BoardConfig

板配置選項文件見build/target/board/generic/BoardConfig.mk,默認下定義:

BOARD_USES_GENERIC_AUDIO := true

這是使用Generic Audio接口。

如果要使用vendor specific audio接口,可以修改:

HAVE_HTC_AUDIO_DRIVER := false
BOARD_USES_GENERIC_AUDIO := false

然後添加:

BOARD_USES_VENDOR_SPECIFIC_AUDIO := true

BOARD_USES_VENDOR_SPECIFIC_AUDIO要根據自己板子的Android.mk來定。


本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/sepnic/archive/2011/03/11/6241019.aspx

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章