高通新的camera驱动架构设计发生了一些变化,借用互联网上经常使用的一种结构,大体的原理如此:将camera的全部功能划分为不一样的模块,让模块本身来决定本身的事情(高内聚,低耦合),模块须要有统一的接口和格式。模块中有端口,经过端口把模块链接起来,又把模块挂在总线上。每个端口的链接就是一个流,把这些流用pipeline来管理。每次启动一个camera就建立一个会话,由这个会话来管理此camera的一切事物。对于每个会话,模块是共享的,它能够是camera的硬件资源也能够是其它资源(如一些软件算法等资源)。node
那么如何来定义这个模块的结构呢?
1.端口——端口属于模块,若是这个模块只有source端口,那么它就是一个src模块;若是只有sink端口就是sink模块,若是都有就是中间模块。没有端口的模块是不能链接到流中的,但他能够完成一些其余的功能,好比接收引擎的设置,报告事件到bus等。链接到流中的端口,也就是说流事件(set/get)主要经过端口来处理。而来自于引擎的(set/get)经过模块来处理,固然端口也能够把事件交给模块来处理。模块内部的端口能够经过模块来创建关系,也能够创建内部的链接,端口有关get/set process。
2.模块线程——每一个模块能够有一个线程来处理模块的事情。一个线程对应一个队列,线程就是从队列中取出数据处理,而后应答回去。
3.总线回调——挡一个模块向总线注册时,总线向其提供一个回调函数,当模块有事件发生时,调用这个函数向bus发消息,而后总线把这个消息提交给管道,管道把这个消息顺着流发下去。
4.模块的get、set以及process。算法
管道、引擎与会话
管道有两端,一端用于读,一端用于写。camera引擎负责对管道的监控,而会话管理camera引擎。后端
从代码结构上来看这种新的驱动架构,高通的camera deamon代码放置在vendor\qcom\proprietary\mm-camera目录下,而此目录下的mm-camera2就是新的camera架构位置,进入里面能够看到media-controller、server-imaging、server-tuning及其它几个目录,咱们这里须要关注的就是media-controller目录。数组
media-controller
|- mct——应该就是camera的引擎?里面包含了引擎、pipiline、bus、module、stream及event等定义及封装。
|- modules——这里面就是划分好的一些模块代码,各模块大体功能以下
|- sensor —— sensor 的驱动模块? —— src模块
|- iface —— ISP interface模块 —— inter模块
|- isp —— 主要是ISP的处理,其内部又包含了众多的模块 —— inter模块
|- stats —— 一些统计算法模块,如3A,ASD,AFD,IS,GRRO等数据统计的处理 —— sink模块
|- pproc —— post process处理 —— inter模块
|- imglib —— 主要是图片的一些后端处理,如HDR等 —— sink模块session
以上各模块内部又包含了众多的模块,具体须要看代码分析。数据结构
高通camera daemon进程架构
1.概述
高通在Android的camera架构中,依旧沿用了其传统的方式,将其自身的一些处理放在一个daemon进程中。这部份内容出于应用于driver之间,是为了保护自身及硬件厂商的利益而专门弄出来的一个东东。其它各家平台也采用相似的方式将这部分的处理放在HAL层处理。dom
2.进程的入口socket
daemon 进程做为单一进程,main 函数的入口,位置以下:
/vendor/qcom/proprietary/mm-camera/mm-camera2/server-imaging/server.c
/vendor/qcom/proprietary/mm-camera/mm-camera2/serverimaging/server_process.c函数
在vendor\qcom\proprietary\mm-camera\mm-camera2\server-imaging\server.c文件中能够看到这个main函数。在这个函数中主要作了如下几件事情:
1.找到服务节点的名字并打开此节点
get_server_node_name(serv_hal_node_name)
......
hal_fd->fd[0] = open(dev_name, O_RDWR | O_NONBLOCK); //这里dev_name为节点名如"/dev/serv_hal_node_name"
2.初始化模块。目前有sensor、iface、isp、stats、pproc及imglib六个模块(见笔记一)
server_process_module_init();
3.进入主循环来处理来自HAL及MCT的事件及消息,处理完以后的结果反馈给kernel(msm.c)
RD_FD_HAL
----> server_process_hal_event(&event)。此函数若是返回真,表示事件消息已经传给了MCT,这时不须要发送CMD ACK给kernel,由于MCT处理结束后会发出通知。若是返回假,表示没有传到MCT,此时须要当即发送CMD ACK到kernel,以便HAL发送此消息的线程阻塞住。
RD_DS_FD_HAL —— 经过domain socket传自HAL的消息
----> server_process_hal_ds_packet(fd_info->fd
RD_PIPE_FD_MCT —— 来自media controller的消息
media controller线程
1.概述
MCT线程是camera新架构的引擎部分,负责对管道的监控,由此来完成一个camera设备的控制运转。
它运行在daemon进程空间,由MSM_CAMERA_NEW_SESSION事件来开启,具体开启函数为mct_controller_new()。
2.mct_controller_new()函数
此函数建立一个新的MCT引擎,这将对应一个事务的pipeline。咱们知道上层能够建立多个事务,每一个对应一个camera,也对应本身的MCT及pipeline等。所以这个函数的主要完成如下几件事情:
1.mct_pipeline_new()
---->建立一个Pipeline及其bus,并完成pipeline函数的映射。
2.mct_pipeline_start_session()
---->开启camera的全部模块并查询其能力
3.pthread_create(..., mct_controller_thread_run, ...)
---->建立mct线程并开始执行
4.pthread_create(..., mct_bus_handler_thread_run, ...)
---->建立bus处理线程
3.mct_list_traverse()函数
此函数在整个mct线程中大量使用,主要用来遍历全部模块并执行一些处理工做。结合前面所讲,camera各模块都具备统一的接口,经过流来链接,模块中又包含模块,根据这种特性高通使用链表结构来保存这些模块并设计了此函数用来完成遍历操做。
1.先来看看此链表的节点结构。链表的节点其实也是一个链表,整个链表就好像是一串串同级的节点搭建而成,整个数据结构组成一颗树结构。
struct _mct_list {
void *data; // 节点数据
mct_list_t *prev; // 上一个节点地址
mct_list_t **next; // 下一个节点节点元素数组首地址
uint32_t next_num; // 下一个节点节点元素数,大部分状况下为1
}mct_list_t;
2.经过递归的深度优先算法来遍历整棵树。
4.MCT线程运行
MCT整个引擎部分主要处理server及bus两类事情,对应前面提到的MCT及bus两个线程。MCT线程主要用来处理来自image server的消息,先pop MCT queue,查看是否有消息,若是有则执行mct_controller_proc_serv_msg_internal()函数来处理。
mct_controller_proc_serv_msg_internal函数用来处理来自image server的消息,并返回类型MCT_PROCESS_RET_SERVER_MSG。这里处理的消息类型主要有SERV_MSG_DS与SERV_MSG_HAL两种,分别在pipline中给出了相应的处理函数,具体查看源码可知。
5.bus线程运行
bus线程跟MCT线程流程同样。从代码上咱们看到两个线程都是从同一个queue上面pop消息,他们是经过各自的线程条件变量来进行区分,完成线程的阻塞及运行工做。MCT的条件变量mctl_cond能够看到是在server_process.c文件中标记的,而bus的条件变量mctl_bus_handle_cond未在源码中找到标志的位置?
sensor模块
1.概述
sensor模块是众多模块中的一个,主要是由模组的各个硬件模块组成,包括sensor、Flash、Af、EEprom、OIS、CSI等。这个模块主要描述了模组硬件的一些工做原理及部分驱动相关部分。
Probe 函数在 sensor_init.c 文件中,主要调用流程为:先去 probe eebin,再去 probe sensor,最后解析其 OTP 的具体信息。
其 probe 函数位于 module_sensor.c 的 module_sensor_init( )。
2.module_sensor_init()函数
在前面讲到的server process中提到,服务进程开始后会初始化各个模块,其中就包括sensor模块,sensor初始化入口函数即为module_sensor_init(...)。这个函数将建立sensor模块并返回其指针,另外将建立它的端口,填充一些功能函数等。它的主要执行流程以下:
1.建立sensor的MCT module。 —— mct_module_create(name)
建立完以后填充set mode、query mode、start session、stop session及set session data五个接口函数。
2.建立module_sensro_ctrl_t结构体,此结构体包含bundle信息,用来构建前面提到的模块树(方便添加、遍历等操做)。
3.sensor模块是source模块,因此其numsinkports应该设置为0。
4.eebin相关的操做
5.sensor的探测操做,用来探测有效的sensor。
6.填入全部已探测到sensor的信息。
7.填入因此sensor的其它信息(Actuator,Flash,CSID,OIS等)。
8.初始化sensor模块。
9.建立基于CID info的端口
10.初始化eeprom