高通新的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