android音频架构以及技术选型

一. android音频架构

Android 系统提供了四个层面的音频 API:

1.Java 层 MediaRecorder&MediaPlayer 系列;
2.Java 层 AudioTrack&AudioRecorder 系列;
3.Jni 层 opensles;
4.JNI 层 AAudio(Android O 引入)

下面先上这张经典的 Android 系统架构图:
android音频架构以及技术选型_第1张图片
从图上看 Andorid 整个系统层面从下到上分以下四层:
1.Linux Kernel
2.硬件适配层
3.Framework 层(可分为 Java 层与 C++层)
4.APP 层
我们上面介绍的四个层面的音频 API 实现均在 Framework 层,其他各层音频相关有哪些功能?当我们调用某一 API 时最终是怎么驱动硬件工作的呢?下面我们先看看系统各层音频相关模块及功能。
android音频架构以及技术选型_第2张图片
1.1 Java 层
Java 层提供了 android.media API 与音频硬件进行交互。在内部,此代码会调用相应的 JNI 类,以访问与音频硬件交互的原生代码。

-源代码目录:frameworks/base/media/java/android/media/

  • AudioManager:音频管理器,包括音量管理、AudioFocus 管理、音频设备管理、模式管理;
  • 录音:AudioRecord、MediaRecorder;
  • 播放:AudioTrack、MedaiPlayer、SoundPool、ToneGenerator;
  • 编解码:MediaCodec,音视频数据 编解码接口。

1.2 JNI 层
与 android.media 关联的 JNI 代码可调用较低级别的原生代码,以访问音频硬件。JNI 位于 frameworks/base/core/jni/ 和 frameworks/base/media/jni 中。
这里调用 AAudio 和 OpenSLES 接口。

1.3 Native framework 原生框架层
不管是 Java 层还是 JNI 层都只是对外提供的接口,真正的实现在原生框架层。原生框架可提供相当于 android.media 软件包的原生软件包,从而调用 Binder IPC 代理以访问媒体服务器的特定于音频的服务。原生框架代码位于 frameworks/av/media/libmedia 或frameworks/av/media/libaudioclient中(不同版本,位置有所改变)。

1.4 Binder IPC
Binder IPC 代理用于促进跨越进程边界的通信。代理位于 frameworks/av/media/libmedia或frameworks/av/media/libaudioclient 中,并以字母“I”开头。

1.5 Audio Server
Audio 系统在 Android 中负责音频方面的数据流传输和控制功能,也负责音频设备的管理。这个部分作为 Android 的 Audio 系统的输入/输出层次,一般负责播放 PCM 声音输出和从外部获取 PCM 声音,以及管理声音设备和设置(注意:解码功能不在这里实现,在 android 系统里音频视频的解码是 opencore 或 stagefright 完成的,在解码之后才调用音频系统的接口,创建音频流并播放)。Audio 服务在 Android N(7.0)之前存在于 mediaserver 中,Android N 开始以 audioserver 形式存在,这些音频服务是与 HAL 实现进行交互的实际代码。媒体服务器位于 frameworks/av/services/audioflinger 和frameworks/av/services/audiopolicy中。

Audio 服务包含 AudioFlinger 和 AudioPolicyService:

  • AudioFlinger:主要负责音频流设备的管理以及音频流数据的处理传输,⾳量计算,重采样、混⾳、⾳效等。
  • AudioPolicyService:主要负责⾳频策略相关,⾳量调节⽣效,设备选择,⾳频通路选择等。

1.6 HAL 层
HAL 定义了由音频服务调用且手机必须实现以确保音频硬件功能正常运行的标准接口。音频 HAL 接口位于 hardware/libhardware/include/hardware 中。详情可参阅 audio.h。

1.7 内核驱动层
音频驱动程序可与硬件和 HAL 实现进行交互。我们可以使用高级 Linux 音频架构 (ALSA)、开放声音系统 (OSS) 或自定义驱动程序(HAL 与驱动程序无关)。

注意:如果使用的是 ALSA,建议将 external/tinyalsa 用于驱动程序的用户部分,因为它具有兼容的许可(标准的用户模式库已获得 GPL 许可)。

二·.技术选型及其优缺点

Android 系统为开发者在 SDK 以及 NDK 层提供了多种音频渲染的方法,每一种渲染方法其实也是为不同的场景而设计的,我们必须要了解每一种方法的最佳实践是什么,这样在开发工作中才能如鱼得水地使用它们。

SDK 层的音频渲染

  • MediaPlayer:适合在后台长时间播放本地音乐文件或者在线的流式媒体文件,相当于是一个端到端的播放器,可以播放音频也可以播放视频,它的封装层次比较高,使用方式也比较简单。
  • SoundPool: 也是一个端到端的音频播放器,优点是:延时较低,比较适合有交互反馈音的场景,适合播放比较短的音频片段,比如游戏声音、按键声、铃声片段等,它可以同时播放多个音频。
  • AudioTrack:是直接面向 PCM 数据的音频渲染 API,所以也是一个更加底层的 API,提供了非常强大的控制能力,适合低延迟的播放、流媒体的音频渲染等场景,由于是直接面向 PCM 的数据进行渲染,所以一般情况下需要结合解码器来使用。

NDK 层的音频渲染
Android 系统在 NDK 层(Native 层提供的 API,即 C 或者 C++ 层可以调用的 API)提供了 2 套常用的音频渲染方法,分别是 OpenSL ES 和 AAudio,它们都是为 Android 的低延时场景(实时耳返、RTC、实时反馈交互)而设计的,下面我们一起来看一下。

  • OpenSL ES:是 Khronos Group 开发的 OpenSL ES API 规范的实现,专用于 Android 低延迟高性能的音频场景,API 接口设计会有一些晦涩、复杂,目前 Google 已经不推荐开发者把 OpenSL ES 用于新应用的开发了。但是在 Android8.0 系统以下以及一些碎片化的 Android 设备上它具有更好的兼容性,所以掌握这种音频渲染方法也是十分重要的。
  • AAudio:专门为低延迟、高性能音频应用而设计的,API 设计精简,是 Google 推荐的新应用构建音频的应用接口。掌握这种音频渲染方法,为现有应用中增加这种音频的渲染能力是十分有益的。但是它仅适合 Android 8.0 及以上版本,并且在一些品牌的特殊 Rom 版本中适配性不是特别好。

以下需要注意的点:

  1. NDK 层的这两套音频渲染方法适用于不同的 Android 版本,可以应用在不同的场景中。
  2. 里面最通用的渲染 PCM 的方法就是 AudioTrack。
  3. 由于 AudioTrack 是 Android SDK 层提供的最底层的音频播放 API,因此只允许输入 PCM 裸数据。与 MediaPlayer 相比,对于一个压缩的音频文件(比如 MP3、AAC 等文件),它需要开发者自己来实现解码操作和缓冲区控制。

你可能感兴趣的:(android,音视频,架构)