Qcom camera hal简介

Qcom camera hal简介Qcomcameraha 简介 高通 node

大家好,欢迎来到IT知识分享网。

目录

背景

Android相机软件框架

Qcom HAL主要包括Camx和Chi两部分

Camx中Pipeline 和 node

下图是简单模型的pipeline (sensor –> IFE –> IPE –> SinkTarget)

Pipeline中的buffer管理

IFE output port的buffer在Camx中申请

IPE output port使用的buffer来自上层传入, IPE input port使用IFE的output port的buffer.

get_number_of_cameras

创建HAL工作的Environment

枚举物理camera (ProbeImageSensorModules)

解析相机信息表, 创建各种Camera ID的映射关系, 向上层返回FwCameraNums

cameraId的最终使用过程

四个文件的使用

devicetree中的xxx_camera-sensor.dtsi文件

cameraModuleData文件

sensorDriverData文件

枚举物理camera的过程 (ProbeImageSensorModules)

logicalcamerainfo文件(相机信息表)

生成 logicalCameraId

根据position使用冒泡算法进行排序

logicalcameraId 最终顺序

多个 REAR_AUX camera的排序

RoleId和fwkcameraId的对应关系

为了方便操作, fwkCameraId和logicalCameraId的对应关系会记录在全局数组m_cameraIdxToFwkId中

疑问: 最终目的是操作物理camera, 通过fwkCameraId也可以找到物理camera, 为什么还需要logicalCameraId ?

Open 接口

configure_streams

ImageBufferManager管理模型

MetdataBuffer 管理

TAG和 MetdataBuffer

Qcom Camera HAL使用了两套MetadataBuffer管理接口

Qcom的MetadataBuffer管理.

Metadata buffer的简单使用模型:

关键处理接口.

申请Buffer:

copy和merge的区别

关键数据结构

CHI中的实现

ChiMetadataManager

camx中的实现

MetaBuffer

MetadataPool

Request在Camx中的处理

Camx中node的dependency.

pipeline使用DRQ来管理Node.

简单模型的完整处理过程

代码执行过程:

Node::SetupRequest的实现

Node::SetDependencies

DRQ::AddDeferredNode

DRQ::AddDependencyEntry

DRQ::UpdateDependency

DRQ中的状态机.

DependencyUnit 结构体

Dependency结构体.

Request在Chi中的处理

Chi中的dependency.

Chi中通过FetureGraph来管理Feature.

Camx中的DRQ和Chi中的FeatureGraph管理模型的对比

相较于Qcom以前的Chi架构, Feature2有如下优势:

使用RTBayer2YUV这个FeatureGraph完成单帧拍照

代码执行过程如下:

Feature处理的状态机:

FeatureGraph中的关键处理

上行获取Feature的dependency

Camx中result返回后的处理

对上行Feature分发多个Request.

小结 


背景

比较简单的整理一下Qcom Camera HAL中的主要模块和流程, 包括如下内容:

  1. Android相机软件框架 :Qcom HAL主要包括Camx和Chi.
  2. get_number_of_cameras :创建HAL的Environment, 枚举物理camera, 解析相机信息表. 建立cameraId映射关系。
  3. Open接口 :cameraId映射关系的使用,创建HAL Device
  4. configure_streams :根据场景, 配置stream. 创建pipeline, 申请ImageBuffer和metadataBuffer.
  5. ImageBuffer管理 :保存图像数据的buffer, 使用MemPoolMgr(内存池)和ImagebufferManger两部分管理.
  6. MetadataBuffer管理 :保存TAG的buffer, 使用ChiMetadataManager(相当于内存池)和camx中MetadataPool两部分管理
  7. request 过程 :Request在Camx中处理, Request在Chi中的处理

Android相机软件框架

Camera HAL3是个per-frame Request的模型, 用一个Request来描述上层希望底层如何处理某一帧, 基本的处理框架如下所示:

调用关系: APP –> Frameworks –> cameraservice –> provider–> OEM HAL –> Qcom HAL.

Qcom camera hal简介

Qcom HAL主要包括Camx和Chi两部分

  1. Camx中完成一条pipeline的处理, 通过DRQ完成Request在Node中的调度.
  2. Chi中客制化一些Usecase, Feature, 使用Camx中的一条或者多条pipeline来实现.

Camx中Pipeline 和 node

  1. 高通将功能模块抽象成Node来管理. 将Node串联, 形成Pipeline. Pipeline 的输入是srcTarget, 输出是SinkTarget。
  2. Node有多个Port口, 使用Link, 通过Port口将Node与Node, Node与SrcTarget, Node与SinkTarget连接起来.

下图是简单模型的pipeline (sensor –> IFE –> IPE –> SinkTarget)

  1. 这条pipeline包括sensor, ife, ipe三个node, 没有3A node, 仅用于调试使用.
  2. Sensor输出Raw数据的信号, 经IFE处理转为YUV数据, 经IPE降噪裁剪输出到SinkTarget buffer.

Qcom camera hal简介

Pipeline中的buffer管理

IFE output port的buffer在Camx中申请
  1. Node的non sink output port的buffer在Camx中申请.
IPE output port使用的buffer来自上层传入, IPE input port使用IFE的output port的buffer.
  1. Node的sink output port的buffer上层传入.
  2. Node的input port使用父node(上行) 的output port的buffer.

下面整理一些关键函数和模块的实现

get_number_of_cameras

获取当前设备中相机的总和, 包括单摄, 多摄, 虚拟Camera. 在provider启动的时候调用, 主要完成三件事, 流程如下:

Qcom camera hal简介

创建HAL工作的Environment

  1. 在Camx中创建HAL3Module, HwEnvironment.
  2. 在Chi中创建ExtensionModule.
  3. 在这个过程中, 创建了一些线程, 创建了很多static类型的数据, 相机退出的时候不会销毁.

枚举物理camera (ProbeImageSensorModules)

通过CameraModuleData和SendorDriverData文件, 结合devicetree中的sensor信息, 枚举物理camera

解析相机信息表, 创建各种Camera ID的映射关系, 向上层返回FwCameraNums

  1. 每个设备都有相机信息表, 描述当前设备中的单摄, 多摄, 虚拟Camera等信息
  2. 将fwkCameraId和物理camera的对应关系保存到全局数据区中.
  3. HAL中为camera定义了RoleId, 创建RoleId和fwkCameraId的map关系, 返回给APP.

HAL中定义了多种CameraId, CameraId之间会有对应的映射关系, 先总结一下CameraId的最终使用。

cameraId的最终使用过程

App中通过RoleId, 找到对应fwkCameraId, open的时候下发给HAL.

HAL中通过fwkCameraId找到logicalCameraId, 然后通过logicalCameraId找到物理cameraId, 然后操作对应的物理设备.

四个文件的使用

在get_number_of_cameras流程中, 涉及四个文件, 下面分析四个文件的使用,

重点关注相机信息表和cameraID映射关系的建立.

devicetree中的xxx_camera-sensor.dtsi文件

代码路径: vendor/qcom/proprietary/devicetree/qcom/camera/renoir-sm7350-camera-sensor.dtsi

每个camera在dtsi文件中都有对应的配置信息.

在KMD中 probe sensor的driver时候解析, 其中用cell-index标识具体的物理camera. 假如手机有4个camera, cell-index依次为0, 1, 2, 3

// wide camera qcom,cam-sensor0 { cell-index = <0>; compatible = "qcom,cam-sensor"; csiphy-sd-index = <1>; sensor-position-roll = <90>; sensor-position-pitch = <0>; sensor-position-yaw = <180>; eeprom-src = <&eeprom_wide>; actuator-src = <&actuator_wide>; led-flash-src = <&led_flash_wide>; cam_vio-supply = <&L5I>; cam_vdig-supply = <&L1I>; cam_vana-supply = <&L6I>; cam_vaf-supply = <&L3I>; cam_clk-supply = <&cam_cc_titan_top_gdsc>; regulator-names = "cam_vio", "cam_vdig", "cam_vana", "cam_vaf", "cam_clk"; };

其中,cell-index = <0>; 是重点。

cameraModuleData文件

代码路径: vendor/qcom/proprietary/chi-cdk/oem/qcom/module/renoir_module/renoir_ofilm_s5kgw3_wide_module.xml

每个模组都有对应的cameraModuleData文件, 模组中包括sensor, eeprom, flash等模块的信息.

文件中的cameraId和dtsi文件中的cell-index一样, 标识具体的物理camera. 如果是同一camera, 这两个值必须一样.

通过sensorName可以找到对应的sensorDriverData.

<cameraModuleData <!--Module group can contain either 1 module or 2 modules Dual camera, stereo camera use cases contain 2 modules in the group --> <moduleGroup> <!--Module configuration --> <moduleConfiguration description="Module configuration"> <!--CameraId is the id to which DTSI node is mapped. Typically CameraId is the slot Id for non combo mode. --> <cameraId>0</cameraId> <!--Name of the sensor in the image sensor module --> <sensorName>renoir_ofilm_s5kgw3_wide</sensorName> <!--Name of the module integrator --> <moduleName>renoir</moduleName> <!--Actuator name in the image sensor module This is an optional element. Skip this element if actuator is not present --> <actuatorName>renoir_ofilm_s5kgw3_dw9800_wide</actuatorName> <!--EEPROM name in the image sensor module This is an optional element. Skip this element if EEPROM is not present --> <eepromName>renoir_ofilm_s5kgw3_gt24p128e_wide_eeprom</eepromName> <!--Flash name is used to used to open binary. Binary name is of form flashName_flash.bin Ex:- pmic_flash.bin --> <position>REAR</position> <!--CSI Information --> </moduleConfiguration> </moduleGroup> </cameraModuleData>

重点:

 <cameraId>0</cameraId> <!--Name of the sensor in the image sensor module --> <sensorName>renoir_ofilm_s5kgw3_wide</sensorName>

sensorDriverData文件

代码目录: chi-cdk/oem/qcom/sensor/renoir_sensor/renoir_ofilm_s5kgw3_wide_sensor/gedit s5kgw3_sensor.xml

sensorDriverData文件中定义了camera sensor的I2C slaveAddress 和 sensorId等信息.

枚举物理camera的过程 (ProbeImageSensorModules)
  1. 传入slaveAddress, 通过I2C读取sensorId对应的寄存器,
  2. 读出的值与文件中的sensorId值匹配, 如果相同, 则probe sensor成功.
  3. probe成功的个数就是物理camera的个数.
<sensorDriverData xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../api/sensor/camxsensordriver.xsd"> <module_version major_revision="1" minor_revision="0" incr_revision="0"/> <!--Sensor slave information --> <slaveInfo> <!--Name of the sensor --> <sensorName>renoir_ofilm_s5kgw3_wide</sensorName> <!--8-bit or 10-bit write slave address --> <slaveAddress>0x20</slaveAddress> <!--Register address / data size in bytes --> <regAddrType range="[1,4]">2</regAddrType> <!--Register address / data size in bytes --> <regDataType range="[1,4]">2</regDataType> <!--Register address for sensor Id --> <sensorIdRegAddr>0x0000</sensorIdRegAddr> <!--Sensor Id --> <sensorId>0x7309</sensorId> <!--Mask for sensor id. Sensor Id may only be few bits --> <sensorIdMask>0xFFFFFFFF</sensorIdMask> <!--I2C frequency mode of slave

logicalcamerainfo文件(相机信息表)

路径: vendor/qcom/proprietary/chi-cdk/oem/qcom/multicamera/logicalcamerainfo/renoir/renoir.xml

每个手机都有对应的logicalcamerainfo文件, 例如K9使用renoir.xml, 文件中定义了当前手机中相机情况,

  1. 包括有几个单摄, 几个多摄和VT camera, 各个相机的功能是什么, 使用的fwkCameraId是什么, 对应的物理camera是什么.
  2. 文件中的 slotId 和 ‘cameraModuleData文件中的cameraId’, 以及 ‘dtsi文件中的cell-index’ 一样, 标识具体的物理sensor.
  3. 文件中的cameraId其实是返回给APP的fwkCameraId.
    1. name=“RearPhysicalCam” slotId=”0″ cameraId=”0″, 表示后置摄像头, 物理cameraId是0, fwkCameraId是0
    2. “MultiCamera”用于SAT, 它fwkCameraId是4, 使用Ultra (slotId 为3) 和 Rear (slotId 为0)两个摄像头.
  4. 在BuildLogicalCameraInfo阶段, 会将文件中的信息整理保存到全局数据区m_logicalCameraInfo中.
  5. 文件中定义的相机的总数, 就是get_number_of_cameras返回给APP的FwkCameraNums.
<Devices <PhysicalDevice name="RearPhysicalCam" slotId="0" cameraId="0"/> <PhysicalDevice name="FrontPhysicalCam" slotId="1" cameraId="1"/> <PhysicalDevice name="MacroPhysicalCam" slotId="2" cameraId="2"/> <PhysicalDevice name="UltraPhysicalCam" slotId="3" cameraId="3"/> <LogicalDevice name="MultiCamera" cameraId="4" primaryCamName="RearPhysicalCam"> <PhysicalDeviceRef>UltraPhysicalCam</PhysicalDeviceRef> <PhysicalDeviceRef>RearPhysicalCam</PhysicalDeviceRef> </LogicalDevice> <LogicalDevice name="bokeh" cameraId="5" primaryCamName="RearPhysicalCam"> <PhysicalDeviceRef>UltraPhysicalCam</PhysicalDeviceRef> <PhysicalDeviceRef>RearPhysicalCam</PhysicalDeviceRef> </LogicalDevice> <LogicalDevice name="VTCamera" cameraId="6" primaryCamName="RearPhysicalCam"> <PhysicalDeviceRef>RearPhysicalCam</PhysicalDeviceRef> <PhysicalDeviceRef>UltraPhysicalCam</PhysicalDeviceRef> <PhysicalDeviceRef>MacroPhysicalCam</PhysicalDeviceRef> </LogicalDevice> <LogicalDevice name="VTCameraFront" cameraId="7" primaryCamName="FrontPhysicalCam"> <PhysicalDeviceRef>FrontPhysicalCam</PhysicalDeviceRef> <PhysicalDeviceRef>RearPhysicalCam</PhysicalDeviceRef> </LogicalDevice> </Devices>

生成 logicalCameraId

上述分析, 得到了fwkCameraId, 物理cameraId. 我们在HAL中实际使用的是logicalCameraId, 这个logicalCameraId怎么来?

把全局数组m_logicalCameraInfo的下标当做logicalcameraId.

为了统一管理, HAL中会根据camera的position的顺序, 对m_logicalCameraInfo数组进行排序.

/// @brief camera sensor role/type typedef enum ChiSensorPositionType { NONE = 0, /// not part of multicamera REAR = 1, /// Rear main camera FRONT = 2, /// Front main camera REAR_AUX = 3, /// Rear Aux Camera FRONT_AUX = 4, /// Front aux camera } CHISENSORPOSITIONTYPE;

根据position使用冒泡算法进行排序
SortSensorDataObjects() { for (UINT i = 0; i < m_numberOfDataObjs; i++) { for (UINT j = 0; j< m_numberOfDataObjs - i - 1; j++) { m_ppDataObjs[j]->GetCameraPosition(&tmpPosition0); m_ppDataObjs[j+1]->GetCameraPosition(&tmpPosition1); if (tmpPosition0 > tmpPosition1) { pTmpImageSensorModuleData = m_ppDataObjs[j]; m_ppDataObjs[j] = m_ppDataObjs[j + 1]; m_ppDataObjs[j + 1] = pTmpImageSensorModuleData; } } } } 

logicalcameraId 最终顺序
  • 多摄ID按照logicalcamerainfo文件中定义的顺序.
  • 单摄ID顺序为: REAR (cameraId 0) — > FRONT (cameraId 1) –> REAR_AUX(cameraId 2) –> FRONT_AUX (cameraId 3)

多个 REAR_AUX camera情况, 比如有macro和ultra, 他们的position相同 , 他们的logicalcameraId怎么确定?

多个 REAR_AUX camera的排序
  1. 由HAL读取cameraModuleData的bin文件的顺序决定, 先被读到的排在前面.
  2. bin文件的读取顺序跟d_off的属性相关. 不同的rom版本中的bin文件的d_off属性不同, logicalCameraId的顺序也会不同.

排序只影响了logicalCameraId, 并不影响frameworkId和CameraId的对应关系.

RoleId和fwkcameraId的对应关系

HAL为相机定义了RoleId的概念, 并且建立了fwkcameraId 和 RoleId的对应关系, 如下所示:

然后将这个对应关系以TAG的形式传递给APP.

fwkcameraId RoleId std::map<UINT32, UINT32> CameraConfigFwr2RoleId = { {0, RoleIdRearWide }, {1, RoleIdFront }, {2, RoleIdRearMacro2x}, {3, RoleIdRearUltra }, {4, RoleIdRearSat }, {5, RoleIdRearBokeh }, {6, RoleIdRearVt }, {7, RoleIdFrontVt }, };

enum CameraRoleId { RoleIdTypeNone = -1, // used for diagcheck RoleIdRearWide = 0, RoleIdFront = 1, RoleIdRearTele = 20, RoleIdRearUltra = 21, RoleIdRearMacro = 22, RoleIdRearTele4x = 23, RoleIdRearMacro2x = 24, };

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/157586.html

(0)
上一篇 2025-01-29 17:26
下一篇 2025-01-29 17:33

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信