Android 音频框架之配置文件解析

这篇具有很好参考价值的文章主要介绍了Android 音频框架之配置文件解析。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。


理解Android 框架代码的一些基础,框架中操作的各种模块、设备、流、路由都是从哪里定义的?以及是怎么定义的?这个也是理解AAOS 中caraudioservice的基础,也是后续有关Audiopatch、AudioFlinger、Audiopolicy的基础。

本文从java层getDevice获取设备展开到框架中理解audio_policy_configuration的解析。

getDevice返回的信息

  • java 层

代码位置:

frameworks\base\media\java\android\media\AudioManager.java

首先通过mAudioManager.getDevices 获取的是AudioDeviceInfo,这个info是从
AudioManager.listAudioDevicePorts中获取到的ports构建出来的,从这边构建的port包含了所有的输入和输出的port,而在getDevices的时候根据flags 是输入还是输出来筛选出需要的port。listAudioDevicePorts是调用的
AudioSystem.listAudioPorts(newPorts, portGeneration) 来获取的

  • c++ 框架层

代码位置:

frameworks\av\services\audiopolicy\managerdefault\AudioPolicyManager.cpp

status_t AudioPolicyManager::listAudioPorts(audio_port_role_t role,
                                            audio_port_type_t type,
                                            unsigned int *num_ports,
                                            struct audio_port_v7 *ports,
                                            unsigned int *generation)

从java到框架都类似通过jni的这边就跳过。最后会调用到AudioPolicyManager::listAudioPorts 其传递的role和type 是AUDIO_PORT_TYPE_NONE、 AUDIO_PORT_ROLE_NONE这里面的实现是将
AudioPolicyManagerd的mAvailableOutputDevices 和 mAvailableInputDevices调用toAudioPort 转换为audio_port_v7的ports返回到AudioManager, AudioManager根据输入或者输出在进行筛选返回到应用层。

  • 了解audio_port_v7的结构体
struct audio_port_v7 {
    audio_port_handle_t      id;                 /* port unique ID */
    audio_port_role_t        role;               /* sink or source */
    audio_port_type_t        type;               /* device, mix ... */
    char                     name[AUDIO_PORT_MAX_NAME_LEN];
    unsigned int             num_audio_profiles; /* number of audio profiles in the following
                                                    array */
    struct audio_profile     audio_profiles[AUDIO_PORT_MAX_AUDIO_PROFILES];
    unsigned int             num_extra_audio_descriptors; /* number of extra audio descriptors in
                                                             the following array */
    struct audio_extra_audio_descriptor
            extra_audio_descriptors[AUDIO_PORT_MAX_EXTRA_AUDIO_DESCRIPTORS];
    unsigned int             num_gains;          /* number of gains in following array */
    struct audio_gain        gains[AUDIO_PORT_MAX_GAINS];
    struct audio_port_config active_config;      /* current audio port configuration */
    union {
        struct audio_port_device_ext  device;
        struct audio_port_mix_ext     mix;
        struct audio_port_session_ext session;
    } ext;
};

其中audio_port_device_ext为 这个在后续的audiopatch中会用到。

/* extension for audio port structure when the audio port is a hardware device */
struct audio_port_device_ext {
    audio_module_handle_t hw_module;    /* module the device is attached to */
    audio_devices_t       type;         /* device type (e.g AUDIO_DEVICE_OUT_SPEAKER) */
    char                  address[AUDIO_DEVICE_MAX_ADDRESS_LEN];
#ifndef AUDIO_NO_SYSTEM_DECLARATIONS
    uint32_t              encapsulation_modes;
    uint32_t              encapsulation_metadata_types;
#endif
};

在toAudioPort 的toAudioPortInternal 中 赋值了ext中的hw_module结构体,

    void toAudioPortInternal(T* port) const {
        DeviceDescriptorBase::toAudioPort(port);
        port->ext.device.hw_module = getModuleHandle();
    }

DeviceDescriptorBase::
    void toAudioPortInternal(T* port) const {
        AudioPort::toAudioPort(port);
        toAudioPortConfig(&port->active_config);
        port->id = mId;
        port->ext.device.type = mDeviceTypeAddr.mType;
        port->ext.device.encapsulation_modes = mEncapsulationModes;
        port->ext.device.encapsulation_metadata_types = mEncapsulationMetadataTypes;
        (void)audio_utils_strlcpy_zerofill(port->ext.device.address, mDeviceTypeAddr.getAddress());
    }

综上getDevice返回的是AudioPolicyManger中可用输入和输出的设备,其结构体中包含了id、role、type等等信息,那么这个mAvailableOutputDevices 和 mAvailableInputDevices是如何构造的呢?这就需要了解android音频配置文件的解析了。

audio_policy_configuration 的抽象成结构体

  • 代码位置:

frameworks\av\services\audiopolicy\managerdefault\AudioPolicyManager.cpp

frameworks\av\services\audiopolicy\common\managerdefinitions\src\Serializer.cpp

  • 解析流程

    解析这个xml是嵌套的, 首先是modules标签,每个modules 存储mixPorts、devicePort、routes。 第一个解析到的是modules标签,modules可以包含多个module,

    • module
      对应的是HwModule类,是属于嵌套的最顶层,包含后续的所有元素。

    • mixPorts
      对应的是IOProfile的类,解析name和role(role只能为source 或者 sink),然后解析mixports嵌套的profile,profile对应的是AudioProfileVector类,解析后将profile设置到IOProfile的mProfiles。profile存储的是format、channel、samplerate。

      解析完mixport之后根据role类型会设置到HwModule中的mOutputProfile/mInputProfiles中,同时也会加到HwModule中的(PolicyAudioPortVector)mPorts中。

    • devicePorts
      对应的类是DeviceDescriptor,首先解析tagName、type、role、address,role同样跟mixport一样可以是source或者sink, type是android定义的类型如OUT_BUS、IN_BUILTIN_MIC等等不同类型的设备。mixport 一样嵌套了profile, 其中还可能会多个gain这样的标签,对应的类是AudioGains(定义了音量调整db的范围和步长)。

      解析完设置HwModule中的mDeclaredDevices中,也会添加到HwModule中的mPorts中。

    • routes

      对应的类是AudioRoute,首先解析type(type有两种类型mix或者mux), 然后解析sink的名字,解析到名字后根据sink的名字从module的mPort(这个port是在上述解析mixport和deviceport中加入的)中找sinkport,找到后将sinkport设置到route中,同时将route设置到sinkport。source解析过程也是类似的,找到所有标签为sources的tag,将sources 设置到routes。一般来说sink这个port为deviceport,source是mixport简

      单的理解为routes 的sink包含了type为sink的mixport和deviceport, source包含了type为source的mixport和deviceport同样解析完设置HwModule中的mRoutes,并设置更新mOutputProfile/mInputProfiles的mSupportedDevices。

      更新的流程是对于mixport type 是source找 type为sink的deviceport。对于mixport type为sink的找type 为source 的deviceport。并将找到的deviceport设置到对应的mSupportedDevices。

      对应的实际的应用 如果是播放音频,那么一个route的mixport是source端 产生数据,deviceport是sink接收数据输出。

    • 解析attach device

      解析attachedDevices的标签, 这些device必须是deviceport中定义的,attachedDevices的device会添加到mOutputDevices 和mInputDevices 当中。

      mOutputDevices是通过audiopolicymanager的mOutputDevicesAll变量 传递进行赋值的。也就是mOutputDevices实际就是mOutputDevicesAll。

    • 解析defaultOutputDevice
      defaultOutputDevice解析之后会存储在mDefaultOutputDevice中。

  • 获取mAvailableOutputDevices 和 mAvailableInputDevices的流程

    • 有了前面的基础, 在获取到mixport(对应mOutputProfiles),attachDevice(对应mOutputDevicesAll),mixport对应的mSupportedDevices(在route中source 类型的mixport 对应的 sink类型的devicePort)之后.

    • 先遍历所有的mOutputProfiles,取出里面里面存储的deviceport,从这些deviceport 找出在attachdevice定义的,新建一个SwAudioOutputDescriptor来对deviceport进行操作。

    • 调用SwAudioOutputDescriptor的open函数打开deviceport(调用流程简单理解会调用的audioflinger 通过hal层 打开device打开成功后创建对应的读写线程)

    • 只有这边open返回成功的设备deviceport 才会加入到mAvailableOutputDevices, mAvailableInputDevices同理。打开成功的 SwAudioOutputDescriptor也会加入到mOutputs。

    • 处理的函数

      void AudioPolicyManager::onNewAudioModulesAvailableInt(DeviceVector *newDevices)

简单的例子

比如如下的xml文件,假定所有的设备通过hal都能够成功的打开,那么mAvailableOutputDevices就为Speaker,而mAvailableInputDevices为Built-In Mic。只分析输出mAvailableOutputDevices的情况,首先根据mixPorts的标签得到source类型的mixport为primary output(对应mOutputProfiles),然后通过route的标签可以知道连接到这个mixport的sink类型的deivce有Speaker、Wired Headset、Wired Headphones、Aux Digital、BT SCO、BT SCO Headset、BT SCO Car Kit(这些就是mixport对应的mSupportedDevices)。attachedDevices对应的是Speaker(对应的mOutputDevicesAll)。于是取mOutputDevicesAll 和mSupportedDevices交集也就是speaker。文章来源地址https://www.toymoban.com/news/detail-699244.html

<audioPolicyConfiguration version="7.0" xmlns:xi="http://www.w3.org/2001/XInclude">

    <globalConfiguration speaker_drc_enabled="false"/>

    <modules>
        <!-- Primary Audio HAL -->
        <module name="primary" halVersion="2.0">
            <attachedDevices>
                <item>Speaker</item>
                <item>Built-In 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>
                <mixPort name="primary input" role="sink">
                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
                             samplingRates="8000 11025 12000 16000 22050 24000 32000 44100 48000"
                             channelMasks="AUDIO_CHANNEL_IN_MONO"/>
                </mixPort>
            </mixPorts>
            <devicePorts>
                <!-- Output devices declaration, i.e. Sink DEVICE PORT -->
                <devicePort tagName="Speaker" role="sink" type="AUDIO_DEVICE_OUT_SPEAKER">
                </devicePort>
                <devicePort tagName="Wired Headset" type="AUDIO_DEVICE_OUT_WIRED_HEADSET" role="sink">
                </devicePort>
                <devicePort tagName="Wired Headphones" type="AUDIO_DEVICE_OUT_WIRED_HEADPHONE" role="sink">
                </devicePort>
                <devicePort tagName="BT SCO" type="AUDIO_DEVICE_OUT_BLUETOOTH_SCO" role="sink">
                </devicePort>
                <devicePort tagName="BT SCO Headset" type="AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET" role="sink">
                </devicePort>
                <devicePort tagName="BT SCO Car Kit" type="AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT" role="sink">
                </devicePort>
                <devicePort tagName="Aux Digital" type="AUDIO_DEVICE_OUT_AUX_DIGITAL" role="sink">
                </devicePort>

                <devicePort tagName="Built-In Mic" type="AUDIO_DEVICE_IN_BUILTIN_MIC" role="source">
                </devicePort>
                <devicePort tagName="Wired Headset Mic" type="AUDIO_DEVICE_IN_WIRED_HEADSET" role="source">
                </devicePort>
                <devicePort tagName="BT SCO Headset Mic" type="AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET" role="source">
                </devicePort>
            </devicePorts>
            <!-- route declaration, i.e. list all available sources for a given sink -->
            <routes>
                <route type="mix" sink="Speaker"
                       sources="primary output"/>
                <route type="mix" sink="Wired Headset"
                       sources="primary output"/>
                <route type="mix" sink="Wired Headphones"
                       sources="primary output"/>
                <route type="mix" sink="Aux Digital"
                       sources="primary output"/>
                <route type="mix" sink="BT SCO"
                       sources="primary output"/>
                <route type="mix" sink="BT SCO Headset"
                       sources="primary output"/>
                <route type="mix" sink="BT SCO Car Kit"
                       sources="primary output"/>
                <route type="mix" sink="primary input"
                       sources="Built-In Mic,Wired Headset Mic,BT SCO Headset Mic"/>
            </routes>

        </module>

        <!-- A2dp Input Audio HAL -->
        <xi:include href="a2dp_in_audio_policy_configuration_7_0.xml"/>

        <!-- Usb Audio HAL -->
        <xi:include href="usb_audio_policy_configuration.xml"/>

        <!-- Remote Submix Audio HAL -->
        <xi:include href="r_submix_audio_policy_configuration.xml"/>

        <!-- Bluetooth Audio HAL -->
        <xi:include href="bluetooth_audio_policy_configuration_7_0.xml"/>

    </modules>
    <!-- End of Modules section -->

    <!-- Volume section -->

    <xi:include href="audio_policy_volumes.xml"/>
    <xi:include href="default_volume_tables.xml"/>

    <!-- End of Volume section -->

</audioPolicyConfiguration>

到了这里,关于Android 音频框架之配置文件解析的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 音视频开发之旅——音频基础概念、交叉编译原理和实践(LAME的交叉编译)(Android)

    本文章已授权微信公众号郭霖(guolin_blog)转载。 本文主要讲解的是 音频基础概念 、 交叉编译原理和实践(LAME的交叉编译) ,是基于 Android平台 ,示例代码如下所示: AndroidAudioDemo 另外, iOS平台 也有相关的文章,如下所示: 音视频开发之旅——音频基础概念、交叉编译

    2024年04月25日
    浏览(35)
  • Android 计时器Chronometer 使用及源码分析(1),android音视频框架

    @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_textview_chronometer);//加载布局文件 initView(); } private void initView() { btn_start = findViewById(R.id.btn_start); btn_stop = findViewById(R.id.btn_stop); btn_reset = findViewById(R.id.btn_reset); chronome

    2024年04月14日
    浏览(38)
  • Android音视频——OpenMAX (OMX)框架

    本文分为两个部分进行讲解 Codec 部分中的 AwesomePlayer 到 OMX 服务 前面介绍了NuPlayer最终解码都会到达OMX框架,也就是 OpenMAX框架,本文开始分析编解码部分中的AwesomePlayer到OMX服务过程,也就是开启OpenMAX准备相关内容。Android系统中用OpenMAX来做编解码,Android向上抽象了一 层O

    2023年04月09日
    浏览(37)
  • Android 音频框架 基于android 12

    前言 Android 的音频是一个相当复杂的部分。从应用到框架、hal、kernel、最后到硬件,每个部分的知识点都相当的多。而android 这部分代码在版本之间改动很大、其中充斥着各种workaround的处理,让人看的云里雾里。网上相应的分析文章也很多,有些就贴大段的代码 是很不容易理

    2024年02月10日
    浏览(24)
  • 【音视频 | wav】wav音频文件格式详解——包含RIFF规范、完整的各个块解析、PCM转wav代码

    😁博客主页😁:🚀https://blog.csdn.net/wkd_007🚀 🤑博客内容🤑:🍭嵌入式开发、Linux、C语言、C++、数据结构、音视频🍭 🤣本文内容🤣:🍭介绍wav音频格式🍭 😎金句分享😎:🍭子曰:父母在,不远游,游必有方。 ——《论语·里仁篇》。意思是,父母还健在时,就不要

    2024年02月06日
    浏览(39)
  • 【学习】从零开发的Android音视频开发(13)——MediaCodec到OMX框架过程及其硬解码

    在讲NuPlayer时,NuPlayer解码部分会创建MediaCodec,并且最终到达OMX框架,先看MediaCodec的 init 函数 从init函数中可以看到,首先创建了 ACodec ,并且初始化了 ALooper 、 AMessage ,由于ACodec继承自 AHandler ,那么一套消息机制就有了。最后发送 kWhatInit 消息,收到消息的逻辑位于ACodec.

    2023年04月08日
    浏览(38)
  • Android13音频子系统分析(三)---音效算法集成框架

    目录 一、Android音效C/S架构 二、EffectHAL音效框架的初始化与使用 2.1音效框架初始化 2.2创建并加载音效算法 2.3执行音效算法 三、AudioFlinger对音效框架的二次封装 四、Device音效的绑定过程 4.1 DeviceHAL处理音效数据的方式 4.2 AudioFlinger处理音效数据的方式 五、Stream音效的绑定过程

    2024年02月03日
    浏览(30)
  • Android 9系统源码_音频管理(一)按键音效源码解析

    当用户点击Android智能设备的按钮的时候,如果伴随有按键音效的话,会给用户更好的交互体验。本期我们将会结合Android系统源码来具体分析一下控件是如何发出按键音效的。 1、在TV版的Android智能设备中,我们可以通过调节设置页面的开关来控制按键音效的有无,该设置页面

    2024年02月09日
    浏览(33)
  • android音频学习笔记之wav头文件

    如何存储和解析wav文件 定义:wav格式,就是微软开发的一种文件格式规范,文件分为两部分 (1)第一部分:文件头,记录重要的参数信息,对于音频而言,包括:采样率,通道数,位宽等等 (2)第二部分:数据块,也就是一帧一帧的二进制数据,对于音频而言,就是原始

    2023年04月08日
    浏览(28)
  • QMUI框架解析:一个介绍Android的全面框架

    随着移动应用的快速发展,开发者需要面对不断增长的需求和复杂的技术挑战。为了提高开发效率并保持应用的稳定性和一致性,许多开发者转向使用框架来构建和管理他们的Android应用程序。在这篇文章中,我们将介绍QMUI框架,它是一个功能强大的Android框架,旨在简化UI开

    2024年02月03日
    浏览(27)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包