linux下camera驱动分析_高通CamX(驱动部分)

  最近要上新平台了,默默看了下,哦豁,大发,Camera代码架构大改,跟之前相差了十万八千里,vendor下面的代码基本上用C++重写,之前放在HAL下面的代码也已经放在vendor下面了,现在除了kernel的代码是C写的,其它基本上走向了C++,而且下面的编译脚本和配置很多已经使用xml和Python控制,目前来看,以后C用的地方越来越少,C++,java,Python和可扩展标记语言将会在驱动上是趋势。由于架构的改动,实际上等于是重新撸一遍。(以下内容部分来自网络,部分来自本人工作中遇到的问题,仅供自娱自乐,欢迎查漏补缺)

1.概述

高通平台Camera HAL,android P之前,大部分采用的是Qcamera和mm-camera的架构,这个一个放在android hardware目录下,一个放在vendor proprietary mm-camera目录下,做高通平台的基本上对这个很熟悉了,为了更精细化控制底层硬件(sensor/ISP等),同时方便手机厂商自定义一些功能,高通搞出了CamX-CHI架构,基本上跟之前的架构没得一点毛的关系了,它将一些高度统一的功能性接口抽离出来放在CamX中,将可定制化的部分放在CHI中,供不同的厂商进行修改,实现各自独有的特色功能,这样设计的好处就是,即便对CamX不是很了解,依然可以很方便的加入自定义的功能,降低平台的耦合性,以供开发者更好的使用高通平台。

     先对CamX架构做一个直接的描述,如下图:

linux下camera驱动分析_高通CamX(驱动部分)_第1张图片

CamX的代码主要放在Z:\Code\EDA61K\LA.UM.8.15\LINUX\android\vendor\qcom\proprietary\camx和Z:\Code\EDA61K\LA.UM.8.15\LINUX\android\vendor\qcom\proprietary\chi-cdk目录下,来看camX目录下的主要分布:

linux下camera驱动分析_高通CamX(驱动部分)_第2张图片

core目录:用于存放camx的核心实现模块,其中还包含了主要用于实现HAL3接口的HAL目录,以及负责与CHI交互的chi目录。

csl目录:用于存放主要负责camx与cameradriver通信的模块,为camerax提供了统一的cameradriver控制接口。

hwl目录:用于存放自身具有独立运算能力的硬件node,该部分node受csl管理。

swl目录:用于存放自身并不具有独立运算能力的,必须依靠CPU才能实现的node

chi-cdk目录有如下:

     这部分的目录跟camera相关的主要在:

Z:\Code\EDA61K\LA.UM.8.15\LINUX\android\vendor\qcom\proprietary\chi-cdk\oem\qcom如下路径:

linux下camera驱动分析_高通CamX(驱动部分)_第3张图片

是不是跟之前的高通默认架构很像:

topology目录:用于存放用户自定义的Usecase xml配置文件(具体干啥的我还不知道)

actuator目录:用于存放不同对焦模块的配置信息

eeprom目录:存放eeprom外部存储模块的配置信息

fd目录:存放了人脸识别模块的配置信息

sensor目录:用于存放不同sensor的私有信息和寄存器配置参数(我们的驱动文件就是在这里配置的,已经告别了C语言的.c和.h文件的模式,改用xml配置了)

module目录:用于存放不同sensor的配置文件,该部分在初始化sensor的时候需要用到。(这个就类似于老架构的xxx_camera.xml文件,在那里面配置CSI等那些信息)

tuning目录:存放不同场景下的效果参数的配置文件(调试用到,好像是之前的chromatix目录?待考证)

node目录:用于存放用户自定义功能的node

flash目录:闪光灯模块的配置

OIS目录:光学防抖模块的配置

其它几个目录目前还没用到,也不知道具体做啥的,后期补充完整

2.基本组件:

2.1 UseCase 

         作为CamX-CHI中最大的抽象概念,其中包含了许多条实现特定功能的pipeline,具体实现是在CHI中通过Usecase类完成的,该类主要负责了其中的业务处理以及资源的管理。

     Usecase类提供了一系列的通用接口,作为现有的所有Usecase基类,其实现主要在如下路径:

Z:\Code\EDA61K\LA.UM.8.15\LINUX\android\vendor\qcom\proprietary\chi-cdk\core\chiusecase目录下,其中AdvancedCameraUsecase继承于CameraUsecaseBase,相机绝大部分场景会通过实例化AdvancedCameraUsecase来完成,它包括了几个主要接口:

     Create方法:该方法是静态方法,用于创建一个AdvancedCameraUsecase实例,在其构造方法中会获取XML中的相应的Usecase配置信息。

     ExetueCaptureRequest():该函数用于下发一次Request请求。

     ProcessResultCb():该函数会在创建session的过程中,作为回调方法注册到其中,一旦session数据处理完成的时候便会调用该方法将结果发送到AdvancedCameraUsecase中。

     ProcessDriverPartialCaptureResult():该函数会在创建Session的过程中,作为回调函数注册其中,一旦Session中产生了partial meta data,便会调用该方法将其发送到AdvancedCameraUsecase中

     ProcessMessageCb():该函数会在创建Session的过程中,作为回调函数注册,一旦session产生任何事件,便会调用该函数通知到AdvancedCameraUsecase中

     ExecuteFlush():该函数用于刷新AdvancedCameraUsecase

     Destroy():该函数用于安全销毁AdvancedCameraUsecase

这里只是简单说明各函数的作用,具体实现还需要看源码。

     Usecase可定制化部分被抽象出来放在了common_usecase.xml文件中,不同的项目可能设置的名字不一样,举个例子,比如我目前的项目用到的usecase文件有可能是这个(因为没有拿到主板和模组,只能盲调):

Z:\Code\EDA61K\LA.UM.8.15\LINUX\android\vendor\qcom\proprietary\chi-cdk\oem\qcom\topology\titan\kona\kona_usecase.xml

     打开这个文件会发现很多节点,有pipeline,Link,port等,跟之前的老版本的架构一样,都有source port这些配置。这里简单说明一下几个标签的含义:

     UsecaseName:代表了该usecase的名字,根据这个名字找到Usecase的定义

     Targets:用于表示输出的数据流的集合,其中包括了数据流的格式,数据的size的范围等

     Pipeline:用于定义该Usecase可以是使用的所有pipeline,这里必须定义一条pipeline

2.2 Feature

         代表了一个特定的功能,该功能需要多条pipeline组合起来实现,受Usecase统一管理,在CHI中通过Feature类进行实现,在XML中没有对应的定义,具体的Feature选取工作是在Usecase完成的,通过在创建Feature的时候,传入Usecase的实例的方式,来和Usecase进行访问各自的资源。

     以下是现有的Feature,其中Feature作为基类存在,定义了一系列通用的方法:

linux下camera驱动分析_高通CamX(驱动部分)_第4张图片

几个常用的Feature:

     FeatureHDR:用于实现HDR功能,它负责管理内部的一条或者几条pipeline的资源以及他们的流转,最终输出具有HDR效果的图像

     FeatureMFNR:用于实现MFNR功能,内部分为几个大的流程,分别包括Prefiltering,Blending,PostFilter以及最终的OfflineNoiseReproces,每一个小的功能中包含了各自的pipeline

     FeatureASD:用于AI功能的实现,在预览时,接收到每一帧数据,并且进行分析当前场景的AI识别输出结果,并其通过诸如到metadata方式给到上层,进行后续的处理。

2.3 Session

         跟老版本的session差不多一个意思,用于管理pipeline的抽象控制单元,一个session中至少拥有一个pipeline,并且控制着所有的硬件资源,管控着每一个内部的pipeline的request的流转以及数据的输入输出,它没有可定制化的部分,所以在CHI中的XML文件中并没有将Session作为一个独立的单元进行定义。

     代码路径Z:\Code\EDA61K\LA.UM.8.15\LINUX\android\vendor\qcom\proprietary\camx\src\core下的camxsession.cpp文件

     Session的实现主要通过CamX中的Session类,其主要接口如下:

     Initialize()函数:根据传入的参数SessionCreateData进行Session的初时化工作

     NotifyResult():内部的pipeline通过该接口将结果发送到session中

     ProcessCaptureRequest():该方法用户用户决定发送一个request到session中的时候调用

     StreamOn():通过传入的Pipeline句柄,开始硬件的数据传输

     StreamOff():通过传入的pipeline句柄,停止硬件的数据传输

2.4 pipeline

         应该很熟悉了,作为提供单一特定功能的所有资源的集合,维护着所有硬件资源以及数据的流转,每一个pipeline包裹了其中的Node/Link,在CamX中通过pipeline类进行实现,负责整条Pipeline的硬件资源的维护以及业务逻辑的处理,简单看下接口:

     代码路径:Z:\Code\EDA61K\LA.UM.8.15\LINUX\android\vendor\qcom\proprietary\camx\src\core下的camxpipeline.cpp文件

     create():该方法是一个静态方法,根据传入的pipelineCreateInputData信息来实例化一个pipeline对象

     StreamOn():通知pipeline开始硬件的数据传输

     StreamOff():t通知pipeline停止硬件的数据传输

     FinalizePipeline():用于完成pipeline的设置工作

     OpenRequest():open一个CSL用于流转的Request

     ProcessRequest():开始下发Request

     NotifyNodeMetadataDone():该方法是pipeline提供给Node,当Node内部生成了metadata,便会调用该方法类通知metadata已经完成,最后所有node都通知pipeline metadata已经完成,pipeline便会调用ProcessMetadataReuqestDone通知session

     NotifyNodePartialMetadataDone():该方法是pipeline提供给Node,当node内部生成了partialmetadata,便会调用该方法通知metadata已经完成,最后所有node都通知pipeline metadata已经完成,pipeline调用ProcessPartialRequestIdDone通知Session

     SinkPortFenceSignaled():用来通知Session,某个Sink Port的fence处于被触发的状态。

     NonSinkPortFenceSignaled():用来通知Session某个non sink port的fence处于被触发的状态

Pipeline中的node以及连接方式都在XML中被定义,主要包含了一下几个标签的定义:

     PipelineName:用来定义该条pipeline的名称

     NodeList:定义了该条pipeline的所有的node

     PortLinkages:定义了node上不同端口之间的连接关系

2.5 Node

         作为单个具有独立处理功能的抽象模块,可以是硬件单元,也可以是软件单元,关于node的实现是CamX中的Node类来完成的,跟上面一样,同级目录下的camnode.cpp文件,其中CamX-CHI中主要分为两个大类,一个是高通自身实现的Node,包括硬件node,另一个是CHI中提供给用户进行实现的Node,主要方法如下:

     Create():实例化一个Node对象

     ExecuteProcessRequest():该方法用于针对hwl node下发的request操作

     ProcessRequestIdDone():一旦该node当前的request已经处理完成,便会通过调用该方法通知pipeline

     ProcessMetadataDone():一旦该node的当前request的metadata已经生成,调用该方法通知到pipeline

     ProcessPartialMetadataDone():同上,数据是partialmetadata

     CreateImageBufferManager():创建ImageBufferManager

其可以定制化的部分作为标签在XML中进行定义:

     NodeName:用来定义Node的名称

     NodeId:用来指定该Node的ID,其中IPE为65538,IFE为65536,用户自定义为255

     NodeInstance:用于定义该Node的当前实例的名称

     NodeInstanceId:用于指定该node实例的ID

2.6 Link

         跟老版本的一样,用于定义不同port的连接,一个port可以根据需要建立多条与其它从属于不同Node的port连接,它通过标签来进行定义,其中包括了作为输入端口和输出端口。一个link中包含了一个SrcPort和一个DstPort,分别代表了输入端口和输出端口,bufferProperties用于表示两个端口之间的buffer配置

2.7 Port

         作为Node输入输出端口,在XML文件中,每一个Node都可以根据需要使用一个或者多个输入输出端口,使用OutpuPort以及InputPort结构体在代码中进行定义。标签含义如下:

     PortId:该端口的ID

     NodeName:该端口从属的Node名称

     NodeId:该端口从属的Node的ID

     NodeInstance:该端口从属的Node的实例名称

     NodeInstanceId:该端口从属的Node的实例的Id

3 组件的结构关系

     各组件基于各自的定位,按照各自独有的行为模式,按照约定俗成的一系列规则组合起来,共同完成框架某一特定的功能,它们之间的关系如下图:

linux下camera驱动分析_高通CamX(驱动部分)_第5张图片

由上图可知,Usecase包含feature,feature包含了Session,session又维护了内部pipeline的流转,而每一条pipeline中又通过link将所有Node都链接起来。下面解释一下这几种关系。

     一个Usecase代表了某个特定的图像采集场景,比如人像场景,在初始化的时候通过上层插入的一些具体信息来进行创建,这个过程中,一方面实例化了特定的Usecase,这个实例是用来管理整个场景中的所有资源,同时也负责了其中的业务处理逻辑,另一方面,获取了定义在XML中的特定Usecase,获取了用于实现某些特定功能的pipeline。

     在Usecase中,feature是一个可选项,如果当前用户选择了HDR模式或者需要在Zoom下进行拍照等特殊功能的话,在Usecase创建过程中,会根据需要创建一个或者多个feature,一般一个feature对应着一个特定的功能,如果场景中并不需要任何特定的功能,则也完全可以不使用也不创建任何Feature

     每一个Usecase或者Feature都可以包含一个或者多个session,每一个session都是直接管理并负责了内部的pipeline的数据流转,其中每一次的request都是Usecase或者feature通过session下发到内部的pipeline进行处理,数据处理完成之后也是通过session的方法将结果返回到CHI中,之后是直接给到上层还是将数据封装下再次下发到另一个session中进行后处理,这都是交由CHI来决定

     其中,Session和Pipeline是一对多的关系,通常一个session只包含了一条pipeline,用于某个特定的图像处理功能的实现,但也不是绝对,比如FeatureMFNR中包含的session就包括了三条pipeline,又比如后置人像预览,也是一个session中包含了两条分别用于主副双摄预览的pipeline。

     根据上述pipeline的定义,它内部都包含了一定数量的Node,并且实现的功能越复杂,所包含的Node就越多,同时Node之间的连接也就更错综复杂,比如后置人像预览虚化效果的实现就是将拿到的主副摄像头的图像通过RTBOfflinePreview这一条Pipeline将两帧图像合成一帧具有虚化效果的图像,从而完成了虚化功能。

     最后pipeline中的node的连接方式是通过XML文件中的Link来进行描述的,每一个Link定义了一个输入端和输出端,分别对应着不同Node上的输入输出端口,通过这种方式就将其中的一个Node的输出端与另外一个Node输入端,一个个串联起来,等到图像数据从pipeline的起始端开始输入的时候,便可以按照这种定义好的轨迹在一个个Node之间进行流转,而在流转的过程中每经过一个Node都会在内部对数据进行处理,这样等到数据从起始端一直流转到最后一个Node的输出端的时候,数据就经过了很多次处理,这些处理效果最后叠加在一起便是该pipeline所要实现的功能,比如,降噪,虚化等等。

你可能感兴趣的:(nvme通用驱动)