展锐平台手机camera 软硬件架构

news2024/11/14 18:37:23

曾经在紫光展锐做过几年的camera驱动,经历过从2013 年最初的几人团队,每人独当一面,负责很多的模块的粗放,到后面的逐步的精细化,设计部门按照内核驱动,hal驱动,tuning效果,3A,效果算法等展开,个人和团组只需专注于某一层面的模块或者算法的反复迭代。现在虽然离开展锐已经数年,对其中软硬件开发过程中的映像还是比较深刻,对开发的规范执行和架构和feature实现的优化选择尤为感慨,这里做个对当时情景的分享回顾,让大家对手机里面的camera架构有个了解。

在这里插入图片描述
以上是当时展锐 camera系统的软硬件大致架构。最底下是展锐的isp 硬件系统和外部sensor。其上是内核层的各类对应驱动。再上面是内核层之上,hal层之下的hal 分层驱动,最上就是安卓自带的cameraserver,负责在camera的app 和 hal之间来调用传递帧和各类参量。

HW 层

HW这个对应的层级是硬件层,主要是芯片里面的isp 硬件系统,相机后处理模块cpp,csi /mipi,外部的各类典型的sensor。

这里isp 硬件系统包含了online 处理部分的DCAM 和offline的isp,不包括mipi csi controller和dphy,展锐对于isp硬件的定义和行业稍有差异,业内把所有从sensor 进入的mipi dphy 到最终输出到DDR buffer 之前的所有关于图像流处理的硬件系统都称之为isp,如上图虚线框内的这部分。

online 部分的DCAM 硬件接收从mipi csi controller 过来的数据流,实现预览录像和拍照的数据分流,还有其他的pdaf,vch 虚拟通道的解包分流等。预览拍照通路接受sensor过来的全尺寸图像,变换为最终输出的图像流的各种尺寸。在通路内部增加了不同的效果处理模块,online 主要关注raw 域的效果处理,这些模块会在后续展开。dcam 分流出来的通路最终会把图像帧吐到驱动设定的各个内部轮转的buffer内,给offline的isp 硬件做输入。
这里一个DCAM 硬件对应一个mipi csi controller 过来的数据流,也就是一个正在运行的sensor,如果是多个sensor 同时运行,那就有多个DCAM 接入到mipi csi controller 后面在运行,经典的isp 系统一般有两个主要的online的DCAM,支持大尺寸的sensor,1~2 个小的DCAM支持小尺寸的sensor。
offline部分的isp硬件只有1个,它接收各个DCAM送来的图像帧,在各路流的30fps的基础上做分时的预览/拍照/录像的帧的效果处理,最终输出YUV420 图像。一般来说,一个33ms内分成4个slot,按照预览/拍照/录像/拍照 这样的顺序做分时处理,之所以这样设计isp,是因为针对大尺寸的拍照图片,在online 的处理上带宽不容易满足,容易产生瓶颈导致堵塞整条通路。做成这种offline 处理后,将图像在宽度方向上按照2592 的最大切片宽度做分割,这样64M 或者上亿分辨率的大图像,在宽度方向上切割成几个slice切片,针对每个slice 做分别处理,在输出设置上做准确的配置,使isp输出在每个行buffer上对应的切片位置,最终得出完整的一帧处理后的大图像,绕开了超级大图带来带宽瓶颈。唯一的不足就是拍照牺牲了实时性。需要几帧的时间来完成大图的isp 处理。
对于预览和录像来说,没有这种切片需求,1个slot 内基本都能处理完毕。如果在运行期间没有拍照,那isp会调度把拍照这部分的带宽让出来优先处理正在运行的预览录像。
这样多个online 部分的DCAM 硬件,加上单个的isp组合,基本实现了各种场景尤其是双摄的典型应用了,同时可以降低zsl 拍照时的运行带宽。只有zsl 拍照时刻,DCAM 的拍照通道的大图才会被offline部分的isp硬件处理,而且是分割切片处理了各个slice。

cpp 这部分是相机的后处理模块,主要是关于图像的旋转和拉伸,拉伸主要用于在拍照过程中需要的输出320*240的thubmbnail 图,这样方便和大图一起合成最终的jpeg图,这样在PC 上能被正确的看到小图标。旋转主要是90,180,270 ,mirror,flip这类简单的翻转。

csi/phy 是关于mipi csi controller和dphy,cphy 这类,展锐有自己实现的这类模块,实现国产化的替代。csi/phy 也是对应一个sensor 一路,一般的isp 硬件系统有至少3路这样的mipi csi controller和phy。

sensor 就是手机上的各类sensor,包括前后摄像头,双摄的第2颗辅助摄像头,其他应用场景的摄像头等,都是用i2c来写入配置,产生mipi 总线上的图像流输出到ISP系统

kenerl 驱动层

对应于硬件上的结构设计, 在kernel 内部驱动也是做了相应的匹配设计。
展锐isp 的驱动在最早的版本上是实现了V4L2 框架的设计,后续为了方便支持双摄等场景,剥离了V4L2 ,采用了简单的类V4L2 接口的misc 设备节点,在对应V4L2 ioctl 命令的基础上增加了BIND/UNBIND 摄像头指定的dcam id这样的操作接口。这样不用大改user到HAL 这层的驱动,就能沿用上之前的框架。

isp 驱动最上层是dcam_core 这层接口,实现输入图像流尺寸,格式,输出各路图像的尺寸,格式,帧buffer的配置,最终启动streamon, 通过dequeue,queue 实现各路图像帧的完成上传和回收排队再次等待接收图像帧。或者streamoff 停止图像流的接收等,这一层完全是逻辑相关的,不涉及到任何的硬件操作。实现了对上的cmr_grab 的适配,对下的dcam_drv 和isp_drv 的调配。
dcam_core下面有dcam drv 和isp drv 这两种驱动模块,分别处理online 和offline 硬件部分,dcam drv主要是关于online的输入图像的接口模块的cap_top和各个输出通路的寄存器的配置,各类中断的响应,输出buffer的完成接收,给到dcam_core,上传给cmr_grab到和上层使用完毕,压回dcam_core到dcam drv 。还有关于各个效果模块的分别参数配置,3A信息帧的配置输出和回收配入,通道sof 等中断信息的发出。isp drv 是关于offline 分时调度的配置和大图slice 切割的配置,中间还是dcam 剩余的效果处理,比如full RGB域,YUV域的效果模块配置。

类似的cpp 也是这样分为cpp_core和cpp_drv 这样的分层处理,cpp_core是逻辑层的接口,主要识别是拉伸还是旋转的配置启动。在cpp_drv里面实现了具体的拉伸还是旋转的寄存器配置和完成通知。

sensor 驱动抽象了所有sensor的供电,配置clk,配置i2c 地址,传输配置参数这类共同的操作接口,还有就是mipi phy和controller的初始化装载和卸载。user 层sensor驱动只需要将具体的配置表(寄存器和值这样)和相关的reset,powerdown有效配置传入,kernel就能正确的驱动。

除此之外,kernel 还有你关于各个模块内需要的上下电接口pw,clk 配置接口等。

需要说明的是,展锐当时实现在了一个族的系列片最小的修改量,来支持不同系列的芯片项目,这样沿用一套完全相同的驱动框架,通过反复的软件迭代来保证项目的稳定。,如下图这样,将有不同的差异部分的操作抽象出来,实现在xxx_drv层的调用。
在这里插入图片描述

HAL层驱动

kernel 之上是user层的驱动,也就是HAL分层驱动。除了HAL 使用了安卓原生的c++之外,其他都是用标准c写的,增加了可移植性,同样的一套code,从HAL层以下都能方便的移植到其他的linux系统上去。

HAL层code 最早支持HAL1.0,中间也曾短暂搞过2.0,最终在展锐那会是HAL3.0 的框架,1.0,2.0 基本不再维护和使用。这部分code 是对安卓框架,尤其是java app 这边的功能支持,同时也要调用到sprd_oem 层里面。

sprd_oem 是综合场景的实现层,实现了最终各种场景的顶层设计。它可以调用其下各个模块来实现hal层需要的接口。
sprd_oem层下面的各个模块不能互相调用,只能由sprd_oem来调用实现完整流程。这模块提供接口或者回调函数指针,来实现往下的调用和往sprd_oem上层的信息传递。

cmr_preview 模块 是实现预览或者录像通路的完整配置和数据帧的流转。其中包含了设置输出帧的格式,大小,ion 管理的buffer 地址,输入帧的格式,大小等。
cmr_snapshot 模块是实现拍照通路的完整配置和数据帧的流转, 其中包含了设置输出帧的格式,大小,ion 管理的buffer 地址,输入帧的格式,大小等。 它的大小图生成和转化成合成的jpeg 输出的内存的分割由sprd_oem调用cmr_mem 来实现。
cmr_mem 是管理拍照的内存分割,如果按照拍照时需要各种类型的内存完全平铺来申请,那内存会耗的非常厉害,这里采用了优化的合并复用,来减少内存的开销。
cmr_grab 是HAL 分层驱动的最底层,是适配kernel 层的dcam core,来实现图像帧,统计帧的抓取,sof 各帧时间戳的获取等。

关于ISP效果类的配置和统计信息,cmr_grab 将会通过判断接收类型分发到isp mw层去。isp mw 会把3A 信息再传递给isp 3A alg,结合app这边给出的配置来决定3A的调配运行。同时isp tune 这层也会把app 这边给出来的配置通过isp mw ,cmr_grab ,下发到内核中配置硬件,实现效果的动态配置。

cmr_sensor 是关于各种支持sensor的驱动配置,具体的mipi类型,供电参数,powerdown,reset,供电电压,帧率,寄存器配置表等,通过内核sensor 驱动实现了最终的sensor的配置。同时isp 这边需要的3A 统计部分也有对sensor 这边的动态配置。

cmr_sensor 里面的sensor 配置和 isp tune的sensor 效果是一一对应的,展锐把sensor的驱动放到了cmr_sensor 层,把sensor对应的数据流ISP 调校放到了 isp tune,通过项目的编译xml 文件来生成对应的可配置。而且展锐还做了了按需生成项目需要sensor库和tuning库,防止了无关的sensor库和tuning库带来的尺寸开销和运行时遍历sensor带来的性能问题。
这部分可以参考 展锐平台的camera sensor驱动代码设计解析

关于图像帧的流转

在这里插入图片描述

对帧的流转,从dcam的online 到isp的offline,然后和hal层的传递回传,这里大致介绍下。

展锐的所有需要的应用需要的图像帧buffer 是在HAL分层驱动里面由ion 来申请的,然后通过QUEUE 这个ioctl 传入,在kernel转换成物理地址,刷入到camera IOMMU的一级页表中去。streamon 以后不再动态改动这个页表,在streamoff 的时候才会撤除。
内核需要的从dcam 输出传递到isp 输入的帧是内核层分配的,在streamon 前根据格式和尺寸预先分配好,然后也是变换成物理地址以及设置页表的camera 专用IOMMU中去。

具体流程这样,dcam 在sof中断到来的时候设置下一帧的buffer到寄存器中去,这帧地址在下一个sof到来才会真正的生效,是下一帧的图像存在这帧的buffer,同时当前帧buffer 地址截接收生效。streamon后 的第一帧buffer 不需要sof,需要强写一个立即生效位,硬件就把当前帧写入buffer。
如图,dcam 后面一共有4片buffer,A2 这片已经收完整帧,然后给isp 去做输入。下一帧buffer A3 在之前A2帧的sof 已经设置好,在A3的sof 触发时生效,等待硬件刷入整帧数据,刷完后也是和A2一样,在A2 后面输入给isp,后面的A0,A1 也是同样处理。A2这帧的buffer如果isp 处理完,那就把它还给DCAM,排队到A1后面,依次等待dcam 的使用和输出。这样形成online 到offline的内循环处理。中间如果系统发生瓶颈问题,所有帧都给了isp,但是都没有处理完成,为了防止dcam online 的误踩有效图像,破坏已有数据帧,给DCAM 一个reseve帧,这个帧只是空转,不会传递给isp。等isp 有帧返回给dcam 了,再接着使用这些有效帧循环。

isp 这边的帧是HAL 分层驱动传递过来的,也是类似的思路。ISP 只有dcam 给过来帧和HAL 给输出帧buffer都有了,才会做offline的转换,否则啥都不干,因为没有输入输出buffer可用。当前图上 ISP 的0 buffer已经完成,上传给HAL,HAL 传递到app 去处理。1 号buffer 接着对应下一帧dcam 的输入处理,1号buffer如果处理完,也是上传到HAL,然后app,后面2号也是同样。app 处理完的3 号buffer当前回传给isp,ISP会把它放到2之后依次处理,这样形成isp 这边的外循环。

这就是展锐当时的camera 内部的软硬件系统架构。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2154927.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

华为HarmonyOS地图服务 11 - 如何在地图上增加点注释?

场景介绍 本章节将向您介绍如何在地图的指定位置添加点注释以标识位置、商家、建筑等,并可以通过信息窗口展示详细信息。 点注释支持功能: 支持设置图标、文字、碰撞规则等。支持添加点击事件。 PointAnnotation有默认风格,同时也支持自定…

Diffusion Model Stable Diffusion(笔记)

参考资料: 文章目录 DDPM架构模型如何拥有产生逼真图片的能力Denoise模型功能Denoise模型如何训练考虑进文字 文生图流程(Stable Diffusion) DDPM架构 模型如何拥有产生逼真图片的能力 Denoise模型功能 通过Denoise将一个噪音图一步步生成为目标图像 Denoise实际…

Java | Leetcode Java题解之第415题字符串相加

题目: 题解: class Solution {public String addStrings(String num1, String num2) {int i num1.length() - 1, j num2.length() - 1, add 0;StringBuffer ans new StringBuffer();while (i > 0 || j > 0 || add ! 0) {int x i > 0 ? n…

Linux文件IO(八)-文件共享

什么是文件共享?所谓文件共享指的是同一个文件(譬如磁盘上的同一个文件,对应同一个 inode)被多个独立的读写体同时进行 IO 操作。多个独立的读写体大家可以将其简单地理解为对应于同一个文件的多个不同的文件描述符,譬…

大数据新视界 --大数据大厂之 Node.js 与大数据交互:实现高效数据处理

💖💖💖亲爱的朋友们,热烈欢迎你们来到 青云交的博客!能与你们在此邂逅,我满心欢喜,深感无比荣幸。在这个瞬息万变的时代,我们每个人都在苦苦追寻一处能让心灵安然栖息的港湾。而 我的…

ClickHouse-Kafka Engine 正确的使用方式

Kafka 是大数据领域非常流行的一款分布式消息中间件,是实时计算中必不可少的一环,同时一款 OLAP 系统能否对接 Kafka 也算是考量是否具备流批一体的衡量指标之一。ClickHouse 的 Kafka 表引擎能够直接与 Kafka 系统对接,进而订阅 Kafka 中的 …

RDKit|分子可视化,定制你的分子图

1 使用 RDKit 绘制 2D 分子结构 在化学信息学中,直观地展示分子的 2D 结构图是非常重要的。RDKit 提供了强大的工具来绘制和定制分子的 2D 结构图,使得科学家和工程师可以轻松地可视化分子的构造。本节将介绍如何使用 RDKit 绘制 2D 分子结构,并展示一些常用的绘图方法和技…

【管理文档】项目管理计划书(word原件套用2024)

本文档为XXX系统项目管理计划,本计划的主要目的是通过本方案明确本项目的项目管理体系。方案的主要内容包括:明确项目的目标及工作范围,明确项目的组织结构和人员分工,确立项目的沟通环境,确立项目进度管理方法&#x…

一个基于Vue3 + Arco Design + Vite3 + Pinia开箱即用的高质量中后台管理系统(附源码)

前言 随着业务的发展与复杂性的增加,现有的中后台管理系统面临着越来越多的挑战,如开发效率低下、系统性能瓶颈、项目扩展性差等问题。这些问题不仅影响了开发者的日常工作,还可能成为项目长期发展的障碍。那么,是否有一款软件能…

C语言 | Leetcode C语言题解之第424题替换后的最长重复字符

题目&#xff1a; 题解&#xff1a; int characterReplacement(char* s, int k) {int num[26];memset(num, 0, sizeof(num));int n strlen(s);int maxn 0;int left 0, right 0;while (right < n) {num[s[right] - A];maxn fmax(maxn, num[s[right] - A]);if (right - …

HCIA--实验十七:EASY IP的NAT实现

一、实验内容 1.需求/要求&#xff1a; 通过一台PC&#xff0c;一台交换机&#xff0c;两台路由器来成功实现内网访问外网。理解NAT的转换机制。 二、实验过程 1.拓扑图&#xff1a; 2.步骤&#xff1a; 1.PC1配置ip地址及网关&#xff1a; 2.AR1接口配置ip地址&#xff1…

ML 系列:机器学习和深度学习的深层次总结(06)— 提升数据质量

一、说明 在AI数据挖掘中&#xff0c;对原始数据的预处理是必须的技术手段&#xff0c;本篇将对数据预处理的一系列注意事项进行展示。 二、关于数据预处理 注意&#xff1a; 在本章中&#xff0c;讨论的技术和方法基于 Roy Jafari 的《Hands-On Data Preprocessing in Pyth…

洪涝洪水滑坡灾害数据集 灾害 2300张 带标注 voc yolo

洪涝洪水滑坡灾害数据集 灾害 2300张 带标注 voc yolo 洪涝洪水滑坡灾害数据集 数据集描述 该数据集是一个专门用于检测和识别洪涝、洪水和滑坡等自然灾害的数据集&#xff0c;旨在帮助研究人员和开发者训练和评估基于深度学习的目标检测模型。数据集涵盖了两种常见的自然灾害…

【shell脚本4】Shell脚本学习--字符串和数组

目录 字符串 拼接字符串 获取字符串长度 截取字符串 查找字符串 数组 总结 字符串 字符串是shell编程中最常用最有用的数据类型&#xff08;除了数字和字符串&#xff0c;也没啥其它类型好用了&#xff09;&#xff0c;字符串可以用单引号&#xff0c;也可以用双引号&am…

WinRAR技巧:如何高效制作RAR分卷压缩文件

RAR分卷压缩是一种将大文件分割成多个较小文件的技术&#xff0c;便于在存储空间有限或网络传输条件受限的情况下传输和存储。本文将详细介绍如何使用WinRAR压缩软件来制作RAR分卷压缩文件。 我们先将压缩包内的文件解压出来&#xff0c;然后查看一下&#xff0c;然后打开WinR…

OceanBase 的并发简述笔记

OceanBase的并发简述笔记一、并发说明 OceanBase的并发分为并发DDL、并发DML。并分为分区并行与分区内并行。 一个CPU 可以运行多个线程(时间片段)。 (租户)min_cpu*(集群)px_workers_per_cpu_quota 租户可拥有的线程数 二、数据分发与数据重分布 数据分发&#xff1a; Parti…

C++ | Leetcode C++题解之第413题等差数列划分

题目&#xff1a; 题解&#xff1a; class Solution { public:int numberOfArithmeticSlices(vector<int>& nums) {int n nums.size();if (n 1) {return 0;}int d nums[0] - nums[1], t 0;int ans 0;// 因为等差数列的长度至少为 3&#xff0c;所以可以从 i2 开…

ps学习。

有大量的图要扣&#xff0c;淘宝5-15块扣一个&#xff0c;尽管蛮便宜的&#xff0c;但是架不住量大啊&#xff0c;还是好好ps&#xff0c;也能省一大笔钱。 填充 在这里有个油漆桶&#xff0c;一开始也叫渐变色&#xff0c;堆放在一起了&#xff0c;我觉得这不是个好设计。。…

第100+25步 ChatGPT学习:概率校准 Histogram Binning

基于Python 3.9版本演示 一、写在前面 最近看了一篇在Lancet子刊《eClinicalMedicine》上发表的机器学习分类的文章&#xff1a;《Development of a novel dementia risk prediction model in the general population: A large, longitudinal, population-based machine-learn…

Dify 中的讯飞星火平台工具源码分析

本文主要对 Dify 中的讯飞星火平台工具 spark 进行了源码分析&#xff0c;该工具可根据用户的输入生成图片&#xff0c;由讯飞星火提供图片生成 API。通过本文学习可自行实现将第三方 API 封装为 Dify 中工具的能力。 源码位置&#xff1a;dify-0.6.14\api\core\tools\provide…