Android Camera MSM HAL


        高通新的camera驅動架構設計發生了一些變化,借用互聯網上常用的一種結構,大致的原理如此:將camera的所有功能划分為不同的模塊,讓模塊自己來決定自己的事情(高內聚,低耦合),模塊需要有統一的接口和格式。模塊中有端口,通過端口把模塊連接起來,又把模塊掛在總線上。每一個端口的連接就是一個流,把這些流用pipeline來管理。每次啟動一個camera就創建一個會話,由這個會話來管理此camera的一切事物。對於每一個會話,模塊是共享的,它可以是camera的硬件資源也可以是其它資源(如一些軟件算法等資源)。

那么如何來定義這個模塊的結構呢?
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模塊

以上各模塊內部又包含了眾多的模塊,具體需要看代碼分析。

高通camera daemon進程

1.概述
高通在Android的camera架構中,依舊沿用了其傳統的方式,將其自身的一些處理放在一個daemon進程中。這部分內容出於應用於driver之間,是為了保護自身及硬件廠商的利益而專門弄出來的一個東東。其它各家平台也采用類似的方式將這部分的處理放在HAL層處理。

2.進程的入口

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線程

7213935_1470619136mvy2

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

 

參考鏈接:

如何在軟件中實現多camera模組的兼容: http://blog.csdn.net/caizhonglong/article/details/78109347


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM