陳二微

隨著行業互聯網的持續發展,各行業對Camera數據的采集、應用提出了不同的需求。以Linux操作系統為基礎的V4L2子系統是一種較為通用的驅動架構。本文描述基于電子的硬件ISP在V4L2接口下的實現方法、Camera連接的拓撲結構、提出了一種3A獨立進程的圖像調試方式,及其靈活的、可拓展的應用形式。
Linux V412及ISP硬件
Video For Linux 2(V412),是Linux Kernel中專用于處理視頻、圖像的子系統框架,向Linux操作系統應用層提供了ISP及Camera硬件的標準接口,被廣泛應用于各芯片廠商的設備驅動。通過對數據流的詳細定義,使得應用程序的開發有統一的接口,LinuxTV組織即是這個子系統的維護者。
ISP在本文中指集成于SoC中的圖像處理核心,它能夠將Camera感光元件獲取的Raw Bayer原始數據進行去馬賽克(Demosaicing)處理,從而轉成一張YUV或RGB圖像;同時對圖像進行3A (Auto Focus,Auto Exposure,Auto White Balance)信息統計并調試校正出一張曝光及白平衡準確的圖像。ISP的硬件接口靈活,能夠接收不同分辨率、不同格式、MIPI或DVP協議傳輸的原始圖像數據,也可接收已經調試好的YUV或RGB圖像輸入;能夠對原圖進行裁剪、縮放,并可同時輸出兩路不同格式(YUV或RGB)、不同大小的圖像。
驅動的實現方法
一個完整的ISP傳輸Camera數據鏈路如圖1所示,它分為了Camera感光Sensor(可以包含一個或多個),MIPI DPHY 數據傳輸通路,ISP轉發數據,統計圖像信息,調試參數配置,雙路圖像輸出6個大模塊。各個模塊分別表示為一個Entity 節點,使用Link將兩個Entity連接起來,從而形成一條或2條的鏈路。
其中Camera攝像頭Entity可以支持1個或多個,在建立Link鏈接時,可以指定當前有效的攝像頭。2個的圖像輸出接口從上一級Entity處得到圖像后,可以分別自由地裁剪、縮放并輸出。3A的調試過程從統計輸出數據Entity獲取3A信息,調整后將修改數據由調試參數Entity傳入,直到統計值收斂。
各個Entity需要按功能實現回調函數。如攝像頭、ISP轉發數據、圖像輸出接口,都需要實現set_fmt、get_fmt用于設置圖像的大小與格式;s_power用于給模塊上下電;s_stream用于使能數據流的輸出。圖像輸出接口另外還需要實現與應用層的buffer輪轉,即QBUF、DQBUF、QBUF...這樣的循環操作,以及裁剪與縮放接口,即s_selection,g_selection。這里采用v412框架中集成的vb2(video buffer 2)管理buffer,同時實現ISP內嵌的iommu模塊,將不連續的物理內存映射成ISP可以訪問的虛擬的連接內存。
攝像頭模塊并不集成在SoC芯片中,與MIPI DPHY或ISP是物理上獨立的,驅動上它也是最大限度地獨立,并且通過異步加載的形式注冊成為子設備(Sub-Device)。
應用開發與3A獨立成一個進程
基于V4L2的驅動接口,應用程序開發獲取圖像幀數據,主要包括設置鏈路選擇攝像頭輸入、打開/dev/video設備、設置各個Entity的輸入與輸出大小格式、分配存儲Buffer、通過QBUF將Buffer配置到kernel、使能整個鏈路、等待一幀數據完成并DQBUF到應用層、Buffer處理(或顯示或保存等等)完畢后再通過QBUF配置到kernel,并循環DQBUF與QBUF的操作直到退出。
得益于驅動的標準化,例如v4l-utils、gstreamer、vlc等通用程序能直接獲取數據流并顯示出圖像、視頻。然而因公司的策略,3A調試部分是閉源且不在驅動中實現。在沒有3A調試時,應用程序獲取的圖像或偏亮或偏暗,或顏色與實際相差太大。雖然有提供動態鏈接庫供調用并使能3A,以完成圖像的調試,但需要修改v4l-utils、gstreamer、vlc等的源代碼,加入3A的初始化、使能與關閉。
本文提出了將3A與數據流分割開,獨立成一個進程。令3A進程通過v4l2-event 監聽isp驅動中start_stream與stop_ stream操作,在start_stream時在用戶空間完成3A的初始化,反之在stop_stream時關閉3A的操作。從而使得v4l-utils等工具能夠無縫地直接使用,也簡化了應用程序的開發。
Camera驅動開發
除了應用的開發,另一個大塊是Camera(Sensor)攝像頭的驅動如何移植。
基于該ISP的驅動結構,Camera作為一個sub-device,驅動的移植有簡潔統一的步驟。概括為6個部分:
照datasheet 編寫上電時序,主要包括vdd,reset,powerdown,clk等;
配置sensor的寄存器以輸出所需的分辨率、格式;
編寫struct v4l2_subdev_ops所需要的回調函數,一般包括set_fmt,get_fmt,s_power,s_stream,用于描述Camera所支持的格式與分辨率,上下電及輸出的開關;
增加v412controller用來設置女口fps,exposure,gain,test pattern,用于調整幀率,設置曝光及增益,輸出內嵌的測試圖片編寫.probe()函數,并添加media control 及v4l2sub device 初始化代碼,使得該設備可以作為一個sub-device添加到ISP的完整鏈路中;
Dts(Device Tree Source)中通過remote-endpoint建立與ISP的具體鏈接信息。
相對于舊的驅動,新的驅動主要的提升包含6個內容,
①是使接口標準化;
②是使得3A進程獨立運行,極簡了應用的開發;
③是雙路的圖像輸出可以同時獨立地進行;
④是采用了vb2的buffer管理,有效地復用了代碼;
⑤是使得Camera,MipiDphy,ISP驅動相互獨立,Camera異步注冊,從而解耦合了整體結構;
⑥是能復用ISP模塊支持多個Camera接入到同一個ISP。
該isp驅動已經形成了一套完整的Camera驅動、應用程序開發方法,于項目實踐中應用。