介紹
音頻無非是把音頻數(shù)據(jù)放到指定的聲卡上進(jìn)行播放,音頻路由就是要解決把某種類型的音頻流,放到對應(yīng)的聲卡設(shè)備進(jìn)行播放的策略。包括配置音頻設(shè)備的采樣率,播放類型,音頻格式等。
音頻路由策略配置
音頻路由是通過配置audio_policy_configuration.xml文件進(jìn)行定制的。寫明了audio音頻部分有哪些設(shè)備、哪些流以及它們支持的編碼、格式以及通道存儲布局等。
| 節(jié)點 | 描述 |
|---|---|
| module | 音頻模塊,對應(yīng)hal層不同的音頻驅(qū)動程序。如module名稱為primary對應(yīng)的音頻驅(qū)動為:audio.primary.$(variant).so |
| attachedDevices | 所有的音頻設(shè)備列表 |
| defaultOutputDevice | 默認(rèn)音頻輸出設(shè)備 |
| mixPorts | 包含由音頻 HAL 提供的所有輸出聲音流和輸入聲音流的列表。每個 mixPort 實例都可被視為傳輸?shù)? Android AudioService 的物理聲音流。 |
| routes | 定義輸入和輸出設(shè)備之間或聲音流和設(shè)備之間可能存在的連接的列表。 |
| devicePorts | 包含可從此模塊訪問的所有輸入和輸出設(shè)備(包括永久連接的設(shè)備和可移除設(shè)備)的設(shè)備描述符列表。 |
| profile | 用來描述音頻設(shè)備支持的音頻格式,采樣率,聲道等。 |
| gain | 當(dāng)前音頻設(shè)備的增益 |
deviceport中的與車載平臺相關(guān)的設(shè)備類型:
| 設(shè)備類型 | 說明 |
|---|---|
| AUDIO_DEVICE_OUT_BUS | Android 的主要輸出(Android 的所有音頻均通過這種方式提供給車輛) |
| AUDIO_DEVICE_OUT_TELEPHONY_TX | 用于傳輸路由到手機無線裝置的音頻。 |
| AUDIO_DEVICE_IN_BUS | 用于尚未進(jìn)行分類的輸入。 |
| AUDIO_DEVICE_IN_FM_TUNER | 僅用于廣播無線裝置輸入 |
| AUDIO_DEVICE_IN_TV_TUNER | 用于電視設(shè)備(如果存在)。 |
| AUDIO_DEVICE_IN_LINE | 用于 AUX 輸入耳機插孔。 |
| AUDIO_DEVICE_IN_BLUETOOTH_A2DP | 通過藍(lán)牙接收到的音樂。 |
| AUDIO_DEVICE_IN_TELEPHONY_RX | 用于從手機無線裝置接收到的與通話相關(guān)聯(lián)的音頻。 |
audio_policy_configuration.xml 示例
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<audioPolicyConfiguration version="1.0" xmlns:xi="http://www.w3.org/2001/XInclude">
<globalConfiguration speaker_drc_enabled="true"/>
<modules>
<!-- Primary Audio HAL -->
<module name="primary" halVersion="3.0">
<attachedDevices>
<item>Speaker</item>
<item>Built-In Mic</item>
<item>Built-In Back Mic</item>
</attachedDevices>
<defaultOutputDevice>Speaker</defaultOutputDevice>
<mixPorts>
<mixPort name="primary output" role="source" flags="AUDIO_OUTPUT_FLAG_PRIMARY">
<profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
</mixPort>
<devicePorts>
<!-- Output devices declaration, i.e. Sink DEVICE PORT -->
<devicePort tagName="Earpiece" type="AUDIO_DEVICE_OUT_EARPIECE" role="sink">
<profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_MONO"/>
</devicePort>
</devicePorts>
<!-- route declaration, i.e. list all available sources for a given sink -->
<routes>
<route type="mix" sink="Earpiece"
sources="primary output,deep_buffer,BT SCO Headset Mic"/>
</routes>
</module>
</audioPolicyConfiguration>
結(jié)合節(jié)點及屬性我們可知,這個示例定義了:
1.定義了一個module,module中包含了一個音頻設(shè)備devicePort,一個混音處理器mixPort,一個路由route。
2.devicePort名稱為bus0_phone_out,在音頻分區(qū)配置的時候也是根據(jù)這個設(shè)備地址進(jìn)行關(guān)聯(lián)配置。指定數(shù)據(jù)格式為AUDIO_FORMAT_PCM_16_BIT。
3.type為“AUDIO_DEVICE_OUT_BUS”,代表這是一個輸出設(shè)備。
4.<route>表示將bus0_phone_out與mixport_bus0_phone_out鏈接,注意這倆個是一一對應(yīng)的。將bus0_phone_out設(shè)備的輸出流都傳遞到mixport_bus0_phone_out混音器中進(jìn)行混音后播放輸出。
car_audio_configuration.xml配置文件的加載
1.在AudioPolicyManager初始化的時候解析。
//frameworks/av/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
AudioPolicyManager::AudioPolicyManager(AudioPolicyClientInterface *clientInterface)
: AudioPolicyManager(clientInterface, false /*forTesting*/)
{
loadConfig();//加載配置
}
void AudioPolicyManager::loadConfig() {
if (deserializeAudioPolicyXmlConfig(getConfig()) != NO_ERROR) {//解析xml
ALOGE("could not load audio policy configuration file, setting defaults");
getConfig().setDefault();
}
}
static status_t deserializeAudioPolicyXmlConfig(AudioPolicyConfig &config) {
//判斷文件是否存在
if (std::string audioPolicyXmlConfigFile = audio_get_audio_policy_config_file();
!audioPolicyXmlConfigFile.empty()) {
status_t ret = deserializeAudioPolicyFile(audioPolicyXmlConfigFile.c_str(), &config);
if (ret == NO_ERROR) {
config.setSource(audioPolicyXmlConfigFile);
}
return ret;
}
return BAD_VALUE;
}
audio_get_audio_policy_config_file配置文件在audio_config.h中進(jìn)行了定義
system/media/audio/include/system/audio_config.h
static inline std::string audio_get_audio_policy_config_file() {
static constexpr const char *apmXmlConfigFileName = "audio_policy_configuration.xml";
...
return audioPolicyXmlConfigFile.empty() ?
audio_find_readable_configuration_file(apmXmlConfigFileName) : audioPolicyXmlConfigFile;
}