OpenHarmony Camera组件架构分析以及拍照流程源码解析 原创 精华
作者:邵黎明
本文以OpenHarmony 3.1 Release - multimedia_camera_standard源码为基础进行分析。
概述
相机功能是现在智能设备一个非常重要的功能。OpenHarmony 相机组件支持相机业务的开发,开发者可以通过已开放的接口实现相机硬件的访问、操作和新功能开发,最常见的操作如:预览、拍照和录像等。
基本概念
拍照
此功能用于拍摄采集照片。
预览
此功能用于在开启相机后,在缓冲区内重复采集摄像帧,支持在拍照或录像前进行摄像帧预览显示。
录像
此功能用于在开始录像后和结束录像前的时间段内,在缓冲区内重复采集摄像帧,支持视频录制。
相机组件架构分析
OpenHarmony 相机组件从上层到下层依次可以分为:应用层 - 相机框架服务层 - 系统服务层(驱动框架服务)- 内核驱动。其实 OpenHarmony 的多数组件都和相机组件有同样架构层次。
代码仓库目录结构
Camera Standard 相关代码有两个仓库,相机框架层 OpenHarmony / multimedia_camera_standard 和 系统服务(驱动框架服务层) OpenHarmony / drivers_peripheral / camera。
相机框架层
代码结构
相机驱动框架服务层
代码结构
代码调用层级关系
OpenHarmony 应用层一般使用JS或者eTS语言进行开发,相机框架层 最外层对上提供NAPI JS接口,对下通过IPC方式调用其相机框架服务。相机框架服务通过IPC方式调用相机驱动框架服务。相机驱动框架服务调用实际的相机硬件驱动。代码调用层级关系参考下图。
关于上图的说明:
- 绿色部分代码在 OpenHarmony / multimedia_camera_standard,紫色部分代码在 OpenHarmony / drivers_peripheral / camera。
- 框中文字为其主要的C++类的名称。
- 相机组件整个流程中存在两次IPC调用,代码中IPC客户端类名为proxy,IPC服务端接口类名为stub。
相机框架层概念和流程
框架层把相机功能抽象为会话管理(管理生命周期、参数配置、输入管理、输出管理)、设备输入(设备查询、设备控制、设备监听)和数据输出(元数据输出、流输出和状态控制),其对应的类名依次为CaptureSession
、CameraInput
和CaptureOutput
。
其中数据输出CaptureOutput
根据实际业务功能又细分为预览输出PreviewOutput
、拍照输出PhotoOutput
和录像输出VideoOutput
。以上所有类都由相机管理类CameraManager
引出。
其相机功能(预览、拍照和录像)代码流程都可以使用如下伪代码进行描述。
其中创建输入需要指定摄像头设备,创建输出需要配置输出到什么地方。
相机框架层拍照流程解析
上节使用伪代码阐述了相机功能的主要流程,这一节详细讲一讲拍照这一操作在框架层的实际代码实现。
拍照流程图
拍照代码流程顺序如下图所示
拍照示例代码
-
创建缓冲区消费者端监听器(CaptureSurfaceListener)以保存图像
-
获取相机管理器实例并获取相机对象列表
-
使用相机对象创建相机输入来打开相机
-
创建采集会话
-
开始配置采集会话
-
将相机输入添加到采集会话
-
创建消费者Surface并注册监听器以监听缓冲区更新
-
使用上面创建的 Surface 创建拍照输出
-
将拍照输出添加到采集会话
-
将配置提交到采集会话。
-
拍摄照片。
-
释放采集会话资源。
-
释放相机输入关闭相机。
驱动框架层拍照流程源码解析
下图是驱动框架层层次结构图
1. 与CameraHost通信,获取CameraId
2. 根据CameraId打开摄像头获取CameraDevice
3. 根据CameraDevice获取流操作器 StreamOperator
4. 通过StreamOperator创建Stream
获取StreamOperator后会接着CreateStreams,这一步主要分析创建Stream之前的参数配置。
5. 通过StreamOperator提交Stream,并设置数据流回调函数
6. 拍一张照片
CommitConfig中环节中,会给HStreamCapture 传递一个StreamOperator。
操作streamOperator进行拍照。
7. 采集到的图像数据回调流程
系统通过 V4L2 或者 mpp 采集到的图像数据,通过 SourceNode 等一系列流程,最终到达 CommitStream() 环节中设置的回调函数 StreamBase::HandleResult() 的位置,以下是数据流转到Surface Buffer的过程。
数据流入Surface 的BufferQueue中,最终在 FlushBuffer 函数中会调用最上层设置的 surface的数据监听 listener。
总结
本文主要描述了OpenHarmony 多媒体子系统Camera组件从应用层到驱动层的架构,按照拍照的流程,分析了与之相关的两个仓库的主要流程的函数代码。
预览、录像与拍照的区别为前两者捕获的是连续的图像(按固定的帧率间隔,定时捕获1帧数据),拍照仅捕获一帧图像。
在相机框架层中,拍照使用的是HStreamCapture
进行单次捕获图像,预览和录像使用HStreamRepeat
类进行连续捕获。这两个类最终都是调用驱动层的StreamOperator::Capture()
函数,此函数根据参数区分是单次捕获还是连续捕获。
更多原创内容请关注:深开鸿技术团队
入门到精通、技巧到案例,系统化分享HarmonyOS开发技术,欢迎投稿和订阅,让我们一起携手前行共建鸿蒙生态。
感谢老师详细的讲解
不错不错,自己顶^_^
有camera设备驱动的skeleton驱动示例吗,如ISP、image sensor需要实现哪些接口,这部分接口的基本功能等