OpenHarmony 标准系统 HDF 框架音视频驱动开发
- 引言
- OpenHarmony 音频概述
- HDF 音频驱动框架概述
- HDF 音频驱动框架分析 —— 音频设备驱动
- HDF 音频驱动框架分析 —— supportlibs 实现
- HDF 音频驱动框架分析 —— hdi-passthrough 实现
- HDF 音频驱动框架分析 —— hdi-binder 实现
- HDF 音频驱动记载过程
- HDF 音频驱动播音流程
- HDF 音频驱动录音流程
- HDF 音频驱动实现总结
- 参考资料链接
引言
OpenHarmony 操作系统为了做到给千行百业提供全场景业务能力,达到设备快速互联、硬件互助、资源共享;统一 OS、一次开发多端弹性部署的目标。在此背景下 OpenHarmony 提出在传统的单设备系统能力基础上,基于同一套系统能力、适配多种终端形态的分布式理念,并且内核层、系统服务层、框架层和应用层做了全新的设计和开发。内核层作为 OpenHarmony 最底层设计,包括支持多内核以及全新硬件驱动框架(HDF)。同时随着手机被发明应用到如今的智能语音等等,音频应用的形态和场景也是越来越丰富。在这两大背景下,音频需要支撑从轻设备到富设备应用需求,所以 OpenHarmony 下基于 HDF 驱动框架的音频驱动实现存在多种方式:
- 轻设备直接驱动
- 富设备用户态驱动
- 富设备内核态驱动
OpenHarmony 音频概述
根据 OpenHarmony 系统的自下而上的层次结构划分:内核层、系统服务层、框架层和应用层。下面简要概述为实现 OpenHarmony 音频功能,各个层次做了哪些工作:
- 内核层包含两方面,内核子系统和驱动子系统。这层主要以 HDF 驱动框架为基础实现音频 codec 驱动,audio HDI 接口的封装。由于产品形态和解决方案的多样化,音频 codec 的驱动方式也分用户态驱动方式和内核态驱动方式来实现。音频 codec 驱动工作后需要对硬件资源进行统一抽象封装,对上层暴露统一的音频接口,这样做的目的就是符合音频规范化操作,保证生态良性发展
- 系统服务层主要通过 pulseaudio 框架对 audio HDI 的调用来获取音频驱动能力。之后基于 pulseaudio 框架实现 audiosystemmanager 和 audioserviceclient,前者对音频服务进行管理、对音频流进行管理。最后 napi 实现,并且 sa_main 会根据 sa_profile 会将音频 SA(system ability)拉起
- 框架层的 ability 框架和 ui 框架等就会根据系统层提供的音频能力进行相应的调用,实现应用 FA(feature ability)和 PA(particle ability)
- 应用层则是根据应用需求和场景调用相应的 FA 和 PA 进行打包生成 .hap 应用包
HDF 音频驱动框架概述
HDF 音频驱动框架的实现需要考虑符合 HDI-adapter 规范,保证生态良性演进。所以 HDF 音频驱动框架和 OpenHarmony 一样,实现过程也是遵循分层设计的。通过如下步骤完成 HDF 音频驱动框架的实现:
- 设备驱动的实现:设备驱动实现方式主要有用户态驱动和内核态驱动。用户态有通过 libusb 走私有协议完成驱动的;内核态有注册 HDF 服务驱动的,也有按照标准 alsa 框架的。以上不管是哪种方式,都是对 audio codec 的硬件配置,使能相应功能
- supportlibs:不同的设备驱动实现方式,用户态访问控制方式也会相应不一样。为了屏蔽访问控制的差异,在用户态实现一套统一的访问接口的接口集合,包括设备能力、启停控制、fifo 读写、音频属性设置获取等
- hdi_passthough:对 supportlibs 二次封装,将 audio codec 的能力接口集合抽象 adapter 并通过 adapter manager 进行管理,满足 HDI-adapter 的规范性,保证产品生态良性演进
- hdi-binder:首先实现 hdi_adapter_server 获取 adapter manager 并注册 HDF 服务,然后实现一个对应的 service porxy 对这个服务通过 binder 机制访问,最后传递给系统服务层 dlopen 的方式动态加载
HDF 音频驱动框架分析 —— 音频设备驱动
了解了 HDF 音频驱动的基本框架和实现技术路线后,下面遵循自下而上的分层设计 supportlibs、hdi_passthrough、hdi_binder 的实现逐一分析讲解对于设备驱动而言,这里大概描述 hi3516 和 rk3568 两个平台内核态实现的技术方式,
- HI3516 内核态注册多个 HDF driver,具体在 drivers/framework/model/audio/ 下会将 HI3516 的音频模型化和平台化,在 drivers/peripheral/audio/chipsets/ 会基于前面平台化驱动实现音频 codec 配置, DAI 驱动等。两部分实现内核态 HDF server 组成 HI3516 内核态完整音频设备驱动
- RK3568 的内核态驱动实现是完全遵循标准 Linux 的 alsa 框架,音频设备的驱动实现包含 codec 驱动、DAI 驱动、DMAMACHINE 驱动。一般的开发都是 codec 驱动的移植,剩下的 DAI 驱动和 DMAMACHINE 驱动都是验证性开发。
HDF 音频驱动框架分析 —— supportlibs 实现
前面 HDF 音频驱动框架概述有描述,supportlib 为了屏蔽声卡访问控制的差异,在用户态实现一套符合 hdi-adapter 规范的访问控制,如下图所示:
开发者根据对应音频设备的驱动能力和实现方式完成对应接口。比如 HI3516 平台通过调研 IO service 完成接口集合声明的 api,RK3568 是调研 tinyalsa 完成接口结合声明的 api
HDF 音频驱动框架分析 —— hdi-passthrough 实现
根据面向对象的编程思想,hdi-passthrough 层的实现思路是将声卡(片内声卡、usb 声卡、HDMI 声卡等)抽象成 adapter,每个 adapter 都包含 supportlibs 抽象的 audioRender 和 audiocapture,最后通过 audiomanager 管理 adapters。此实现方式进一步将音频 HDI 接口规范化封装。如下图所示:
HDF 音频驱动框架分析 —— hdi-binder 实现
hdi-binder 是处于 HDF 音频驱动框架最上层的封装,这一层分为 server 实现和 proxy 实现。server 实现是将声卡管理、声卡录播控制以 HDF ioservice 的方式绑定到 modulename 为 audio_hdi_adapter_server 的 HDF 驱动服务。根据这个驱动服务的 hcs 描述可知它是向用户态和内核态发布服务,并满足按需加载。
struct HdffDriverEntry g_hdiServerEntry = {
.moduleVersion = 1,
.moduleName = "audio_hdi_adapter_server",
.Bind = AudioHdiServerBind,
.Init = AudioHdiServerInit,
.Release = AudioHdiServerRelease,
}
HDF_INIT(g_hdiServerEntry);
hcs 配置文件如下:
device0 :: deviceNode {
policy = 2;
priority = 100;
moduleName = "libaudio_hdi_adapter_server.z.so";
serviceName = "audio_hdi_service";
}
Note:proxy 通过 serviceName 获取的该服务。proxy 的山西爱你首先是获取 server 实现时注册的 audio_hdi_service ,然后通过 ipc 机制获取声卡管理和声卡能力接口集后遵循 hdi-adapter 的规范对声卡进行系统框架层的应用。总结 hdi-binder 的 server 和 proxy 的相互调用实现,可以参考下图所示:
HDF 音频驱动记载过程
前面完整分析了 OpenHarmony HDF 音频驱动框架的分层实现,以及每个层次的组件如何依赖组合关系。至此虽然大概知道 HDF 音频驱动框架的实现,但是 hdi-binder 下实现的 audio_hdi_service 何时被拉起,整个过程简单分析:
- 系统在开机的时候 init 进程会拉起 hdf_devmgr,hdf_devmgr 会对 HDF 服务进行管理
- HdfDriverEntry 被实现时通过 HDF_INIT 放在一个特定的 section
- 当 proxy 被调用时,会调用 HDIServiceManager 类的 GetService(serviceName) 方法
- 匹配成功后就会执行 HdfDriverEntry 对应的 bind 和 init ,这时整个驱动服务被注册拉起成功
HDF 音频驱动播音流程
HDF 音频驱动录音流程
HDF 音频驱动实现总结
- HDF 音频驱动开发包含设备驱动开发,HDI 的实现封装
- HDF 音频驱动框架实现必须遵循当前的层次划分和 hdi-adapter 规范,方便演进和去差异化
- HDF 音频驱动框架的处理对象是 PCM,不能进行其他复杂音频业务,比如 AI 和音频分析
- HDF 音频驱动往系统服务层暴露的只有一个 HDF 服务,这个服务是动态按需拉取和注销的
- HDF 驱动框架提供了驱动加载、驱动服务管理和驱动消息机制三大驱动框架能力
参考资料链接
-
OpenHarmony官方 doc 文档:https://gitee.com/openharmony/docs#/openharmony/docs/blob/master/zh-cn/readme.md
-
OpenHarmony官网:https://www.openharmony.cn/mainPlay
-
课程链接:https://growing.openharmony.cn/mainPlay/learnPathMaps?id=49