天天看點

Qualcomm Camera基礎1. Digital zoom原理介紹3.高通 Android平台軟體架構分析(digitalzoom相關)4.Zoom相關接口及參數介紹

高通将android的camera子產品重新修改了一下,與原生的方式存在一些差異。這裡将前段時間學習的一些零散知識進行一下總結,便于以後查閱。

1.整個子產品主要巡行三個主線程:control、config及frame,control用來執行總的控制,是上層控制接口(這個線程還未去了解)?config主要進行一些配置,這個線程裡面主要進行3A的工作,另外還有一些跟效果有關的設定;至于frame線程好像主要用來做預覽吧。目前還隻是大緻了解config線程。

2.在Qualcomm執行初始化時就會調用到mm_camera_exec()函數來建立config線程launch_cam_conf_thread();閱讀此線程函數體會發現裡面使用了select機制來檢測配置指令并進行分發(調用不同的分支函數)。後面就是一連串的function call了。 關于select機制還有不少疑點需要進一步學習:指令的來源?如何對檔案進行控制的?

比如下面這一段LOG就可以看到對AE、AWB及HIS設定的過程(隻貼了部分):

E/CAM_FD  (  194): ...... entering config duty loop ......

E/CAM_FD  (  194): cam_conf: MSM_CAM_IOCTL_GET_STATS: resptype=1 ctrl_cmd.type=4

E/mm-camera(  194): +++++++++++++ config_proc_vfe_event_message type 0                 // event類型

E/mm-camera(  194): camconfig_proc_vfe_event_message received msgId = 9               

E/mm-camera(  194): vfe_process_msg_evt msg_id = 9

E/mm-camera(  194): vfe_process_VFE_ID_COMMON, vfe common message = 0x4a000           // AE、AWB、IHIS

E/mm-camera(  194): received AEC stats: buf = 0x40821000, fd = 52

E/mm-camera(  194): VFE_ID_STATS_AE numReg 256, opt_mode 4

E/mm-camera(  194): vfe_util_do_aec: numReg = 256, num_pixels_per_region_aec = 30856

E/CAM_FD  (  194): isp3a_execute stats_type: 0                              // 執行AEC

E/mm-camera(  194): vfe_util_do_aec: no pendingPrepSnapCtrlCmd

......

看過Qualcomm攝像頭部分代碼的都知道,裡面充斥了一些全局及靜态變量,在未完全理清楚前看起來很費勁,比如我現在就處于這種狀态。下面就将一些已發現的變量總結一下寫在這裡,友善以後查閱。在海量代碼中查閱一些資料結構真是一件令人頭痛的事情。

1.config線程相關:

        config線程主要負責攝像頭的配置工作,由它完成子產品的大部分工作,調試的重點也在這部分。

        首先定義了一個全局的變量config_ctrl_t cfgctrl,所有的config相關的資料都跟這個變量相關,比如調試過程中常用到的isp3a_ctrl_t及sensor_ctrl_t等,都挂在這裡。從這個結構體層層往下找就能慢慢理清Qualcomm中的資料結構。在config線程裡面發生的ctrl command和vfe event message都将傳入cfgctrl位址及需要重新整理的值,進行後續的操作并保持一些狀态到cfgctrl中。是以如果需要了解某個狀态,隻要讀取cfgctrl中的相關字段即可。ctrl command主要是一些菜單的設定,而vfe event message主要是vfe一些event的回報處理。

        Qualcomm提供了一些接口來設定,但擷取狀态的接口基本沒有,隻能自己編寫。

2.AWB相關(Bayer格式):

        在AWB的處理過程中,除了上面提到的isp3a_ctrl_t結構體用于對外互動外,AWB子產品内部還定義了一個靜态變量awb_algo_ctrl_t*awbCtrl用于儲存AWB相關的資料及狀态。這裡面最重要的一個結構體awb_advanced_grey_world_t就是為增強的灰階世界法算法服務的。

Android高通平台調試Camera驅動全紀錄

項目比較緊,3周内把一個帶有外置ISP,MIPI資料通信,800萬像素的camera從無驅動到實作客戶全部需求。

1日 搭平台,建環境,編譯核心,燒寫代碼。

我是一直在Window下搭個虛拟機登伺服器搞開發的,對Linux系統環境實在無愛,每每一到項目剛開始要搭環境了,内心總有點排斥,過程就比較糾結,看來以後還是要搞個linux真機玩玩。

2日 編寫camera驅動大緻架構,配置GPIO,I2C,MIPI,電壓,時鐘等。

很少能碰到FAE隻給硬體手冊,沒有Linux和Android驅動的。因為是camerasensor外接ISP晶片,杯具就發生了。整個系統是這樣,高通平台的開發闆,自己寫驅動來控制ISP晶片,ISP晶片與camerasensor封裝在一起,ISP控制sensor,實質就是sensor寫寄存器。

 開始寫驅動了,說好聽的那是站在巨人的肩膀上借鑒别的驅動,說難聽的就是照葫蘆畫瓢,反正再改下Kconfig,Makefile,這驅動架構就算是有了。

  對驅動開發而言,前期的主要工作應該就是配置GPIO口和晶片上電時序了。

每個特定平台在操作GPIO,電壓,時鐘上都會有自己的一套核心API封裝實作,隻要能看懂會用這些API即可。配置完後,須在驅動初始化函數裡,正确設定晶片的上電時序,確定晶片硬體上能正常工作起來。

3日 編寫I2C通信的封裝函數,調試CPU與ISP間的I2C通信

對于一些成熟方案,上面的工作完成順利的話,驅動就差不多了。。很可惜,這塊ISP晶片在提升800萬camera性能的同時,并沒有給我帶來足夠多的技術支援,隻能說,成也ISP,敗也ISP,解決方案全都自己來吧。萬裡長征第一道坎便是I2C。

I2C通信本身要注意兩點,

1) SDA第9位ACK位為低時說明從裝置有響應。

2) Slave address

晶片手冊對這個從裝置位址沒有統一的寫法,有的給出8位位址,有的給出7位位址,一開始容易混淆。如果給出的是8位位址,那第8位是指Write-0或者Read-1,實際的I2C晶片位址是7位的。Linux源碼裡structi2c_board_info的闆基資訊應填寫7位I2C位址,另外,I2C晶片位址可以通過開發闆shell環境下$ ls/sys/bus/i2c/devices/ 檢視。舉個例子,

static struct i2c_board_info msm_camera_boardinfo[] __initdata ={

 {

  I2C_BOARD_INFO("ov8820", 0x78>> 1),

 },

4日 FAE現場支援

FAE過來了,就确認了一件事,沒有現成驅動了,我徹底死心了。後來還發現一個規律,隻要FAE來現場那就意味着啥都搞不出來了。。幾個人彙聚思想還不如一個人靜下心來研究。不過他們此行至少留下一份重要的資料-ISP晶片指令序列,camera所有功能的實作就靠它了。

5日 調通I2C

I2C的調通具有裡程碑式的意義,它不僅标志着硬體性能正常開啟,更為後來璀璨絢爛的camera世界奠定了堅實的基礎。。

有段時間卡在I2C 通信上,給ISP晶片0x3c寫入開啟晶片指令0xf0成功,但是再發送其他指令全部失敗。

分析現象,I2C總線已經可以通信了,問題隻能是在ISP晶片上,于是,查電路圖,抄家夥起來把電路闆上的電和時鐘全部再量一遍。。

結果發現,有一路來自自動對焦馬達的電壓隻有1.7V,沒有達到要求,驅動裡沒有把它的GPIO拉高,導緻晶片無法正常開啟工作。

6日 編寫預覽驅動,測量MIPI資料

根據葵花寶典裡的ISP指令序列,在Linux驅動裡和Android高通抽象層裡填寫相關代碼,便可實作預覽功能。不過很不幸,光靠那兩下子預覽還是出不來的。開啟預覽程式時,用示波器量MIPI總線上的圖像資料,能夠得到理想的MIPI波形,說明底層驅動的預覽功能OK,問題在于高通平台的CAMIFVFE上,于是,翻閱高通的技術資料,學習添加VFE的一些配置。

7日 配置VFE,點亮預覽

預覽的成功具有劃時代的意義,它不僅标志着camera子產品在整個Android系統架構中的成型,更為後來的拍照,錄像,圖像效果等功能奠定了堅實的基礎。預覽的出現,意味着我不用再回答那些類似像“camera亮沒”之類的隻注重表面現象的問題,從那一刻起,我仿佛站上了另一個高度,有種夢回漢唐的感覺。。      

8日 健壯代碼,編寫拍照功能,對焦功能

至此,整個camera子產品從上層應用到底層驅動已全部打通,接下來就可以見神殺神,見佛殺佛了。。

9日 編寫白平衡,色彩效果,場景模式,ISO,防震,閃光燈等功能

這年頭碼農傷不起啊!就按葵花寶典上的ISP指令序列往裡使勁填充。

10日 登陸伺服器送出代碼

高通Android平台

最近負責一個項目(手機)上camera的功能,其中有要求做zoom這個功能(項目上要求對所有的分辨率都可以支援4X的zoom),是以把這個部分比較全面的學習了一下,本文對高通在android平台上zoom的實作原理做一個深入的分析,包括的部分主要有zoom功能所涉及高通HW子產品的原理架構、高通在android軟體中digitalzoom的實作流程以及具體的相關接口參數介紹,旨在讓讀者能夠對高通android平台下digitalzoom的實作原理及架構有一個清楚的了解。

1. Digital zoom原理介紹

這裡提到的digitalzoom,即數位變焦,是相機變焦的一種;另外一種為光學變焦,主要是在數位相機中有所應用,它通過相機鏡頭的移動來放大與縮小需要拍攝的景物,光學變焦倍數越大,能拍攝的景物就越遠,而且不會影響畫質。本章節重點介紹數位變焦部分,這種變焦在手機中應該較為廣泛。

手機上的數位變焦是通過手機内的處理器,把圖檔内的每個象素面積增大,進而達到放大目的。這種手法如同用圖像處理軟體把圖檔的面積改大,不過程式在手機内進行,把原來sensor上的一部份像素使用"插值"處理手段做放大,将sensor上的像素用插值算法将畫面放大到整個畫面。通過數位變焦,拍攝的景物放大了,但它的清晰度會有一定程度的下降,是以數位變焦并沒有太大的實際意義。

下圖是數位變焦和光學變焦的效果對比,一目了然。

數位變焦一般分為分為2個步驟,crop和插值放大。另外,數位變焦有2種狀況:一種是使用者需要拍照畫面的尺寸和sensor輸出畫面的尺寸是一緻的;另一種則是使用者需要拍照畫面的尺寸×zoom等級後比sensor輸出畫面的尺寸小。在第二種情況下隻需要crop就可以了(具體要根據zoom等級計算)

       關于zoom的等級,倍數越高,crop的像素就越少,以拍照3M(2048×1536,sensor輸出的原始照片為3M)的照片為例,如果做2X的zoom,那麼需要從原始照片中crop出1024×768的畫面,然後再插值放大成2048×1536;如果是4X的zoom,那麼需要從原始照片中crop出512×384的畫面,然後再插值放大成2048×1536,以此類推。倍數是指寬和高的倍數,而非面積。

下面結合圖檔來說明一下數位變焦的原理:

       1、當使用者需要拍照畫面的尺寸和sensor輸出畫面的尺寸一緻

原始照片,紅色部分為zoom後需要crop的部分

Zoom後的照片,crop後并插值放大

可以發現,zoom前後照片大小是一緻的,但照片的範圍變小了,感覺是鏡頭拉近了,其實就是通過crop後再插值放大來完成,zoom的倍數越高,需要插值的像素就越多,zoom後的照片就會越模糊。

Note:這裡的插值放大是指軟體算法,和圖像處理軟體中那種線性放大是不同的,關于算法的實作這裡不多介紹了。

2、使用者需要拍照畫面的尺寸×zoom等級後比sensor輸出畫面的尺寸小

下圖是sensor輸出的原始照片,1600×1200。需要拍照的分辨率為800×600,即可以作2X的digitalzoom

在這種狀況下是不需要插值放大的,圖檔的品質并沒有降低;但如果zoom的等級比較大,比如要4x的zoom,那麼光靠crop是不行的,還是得再通過插值放大來完成。通常說來,如果拍照的分辨率比較小,zoom大都可以隻通過crop的方式來完成。在上章節中介紹了digitalzoom的效果以及基本的實作原理,本章将着重介紹高通平台上實作digitalzoom所涉及的相關子產品架構,因為digitalzoom是camera中的一個feature,分别需要在preview和snapshot中完成,

所涉及的相關子產品也都是和camera相關的,如下所示:

上圖是preview的時候,digitalzoom所涉及的相關子產品,各個子產品的用途如下(這裡主要介紹sensor、VFE和MDP):

1、 Sensor

       雖然本身也有zoom的功能,但在這裡并未使用。Preview時如果做digitalzoom,隻是正常的輸出frame而已,比如輸出30fps的VGA資料(YUV)。

2、 VFE

DSP的一部分,功能主要都是和圖像處理相關,在zoom的時候,它的用途主要就是Crop(剪裁),它會把sensor輸出的VGA資料crop成preview時所需要大小的資料,如CIF(352×288),這樣的話相當于已經做了一部分zoom(640/352),大概是1.8X,如果不夠,剩餘的zoom将由後面的MDP來完成。

Note:VFE隻有crop的功能,沒有upscale(放大)的能力,是以VFE最多隻能完成有限的zoom。

3、 MDP

這是一個專門處理顯示資料的處理器,功能比較齊全,在zoom的時候主要的用處就是crop+upscale。因為VFE的zoom能力有限,是以當VFE不能滿足要求的時候,MDP則繼續完成剩餘的zoom,比如:如果要求preview畫面的大小為QVGA,現在要做4X的zoom,那麼VFE會從原始的VGA資料中crop出QVGA大小的資料,相當于已經做了2X的zoom,那麼剩下的2Xzoom怎麼做呢?MDP會從VFE輸出的QVGA(320×240)資料中crop出160×120大小的資料(從中間截取),然後再upscale成QVGA大小的資料送到LCD顯示,這樣相當于又做了2X的zoom,是以加起來一共做了4X的zoom。

Note:MDP最大可以進行4X的upscale。

      上面介紹了preview時zoom的實作,下面來看一下拍照時zoom是如何實作的?

Note:為了滿足所拍為所看,即拍下來照片的景物範圍和preview時所看到的景物範圍要保持一緻,preview時和snapshot時的zoomlevel必須保持一緻。

1、             Sensor

輸出拍照需要的原始資料。在目前應用中,不管設定的拍照分辨率是多少,我們要求sensor輸出的拍照資料是固定的,即最大3M(2048*1536,以ICE為例)。

2、             VFE

功能和preview時候是一緻的,隻不過在拍照的時候,VFE會根據zoom的等級以及需要拍照的分辨率來自動crop出合适大小的資料。

例如選擇拍照的分辨率為2048×1536,zoom的level為4X,那麼VFE将從原始的2048×1536的資料中crop出512×384大小的資料,後面的zoom由Videocore中的jpegencoder完成。

還有一種狀況,如果拍照的分辨率較小,那麼有可能隻通過VFE的crop就可以完成zoom功能,比如拍照的分辨率為1024×768,這個時候如果做2X的zoom,那麼VFE隻需要從原始的2048×1536的資料中間直接crop出1024×768的資料即可,後面就不需要再用jpegencoder來zoom了。但如果zoom的等級比較高,後面的2Xzoom還是要通過jpegencoder來做了。

3、             Video core

               負責把VFE輸出的資料encoder成jpeg檔案,這裡的jpegencoder還有一個比較重要的功能,那就是upscale,通過這個功能,再搭配之前VFE的crop功能,zoom就可以完成了。

       Note:Jpeg encoder的upscale功能是有限的,最大可以進行4X的放大,目前可以滿足ICE上的需求。

               可以看出,從HW架構來說,preview和snapshot隻是在後面的upscale部分有所差別,前者是通過MDP來完成,後者則是通過jpegencoder(DSP)來完成。

3.高通 Android平台軟體架構分析(digitalzoom相關)

本章将從軟體角度來分析一下高通Android平台下digitalzoom的架構以及實作流程,下面先來看一下Android中camera部分的軟體架構。

Note:目前以Androiddonut版本為例,高通在androidéclair版本上還沒有導入

先來看一下Preview的流程:

1、VFEdriver會把從sensor傳送來的frame資料crop成上層需要的大小(具體如果crop要根據zoom的level),然後連同crop資訊一起把資料傳送到HAL。

2、HAL層不會對preview資料做任何處理,它會這些資料原封不動的callback到camera service,同樣包含cropinfo(下章節會詳細介紹crop info)。

3、Camera service在一開始的時候會在surfaceflinger中建立一個surface。當cameraservice收到preview資料的時候,2個主要接口會被調用:

1)     zoomUpScale_callback

通過調用mSurface->updateCropRect接口把crop相關資訊通知給surfaceflinger

2)     previewCallback

通過調用mSurface->postBuffer接口把preview的資料傳遞給surfaceflinger。

4、Surfaceflinger收到資料和crop資訊後會調用copybit的接口來驅動MDP去做相關的動作(crop&upscale),然後就去畫屏了。

再來看一下snapshot時的流程:

1、VFEdriver把從sensor傳遞來的原始拍照資料(最大分辨率:2048×1536)crop成zoom需要大小的資料,連同crop資訊一起傳遞給HAL。

2、HAL層收到snapshot的資料後會先去檢查crop info,判斷是否需要jpegencoder去做upscale的動作。如果不需要就直接encode成jpeg資料;如果需要,填好upscale的參數再做encode。

3、Jpeg encoder後的資料會從HAL callback到camera service,cameraservice會在通知上層去把資料寫成檔案。

由此可見,在snapshot的時候,整個zoom在HAL就可以完成了,而不像preview的時候,需要在surfaceflinger中配置MDP協助完成。具體的原理在第二章節中有詳細的叙述,這裡就不重複了。

4.Zoom相關接口及參數介紹

本章将從代碼的層次來分析一下zoom的實作原理及流程。

Note:基于高通5110 release的code

首先來看一些配置參數(基于HAL):

#define MAX_ZOOM_LEVEL5//對于user來說可以zoom的等級

static const int ZOOM_STEP =6;//每次zoom時的幅度,可以修改

另外需要說明高通VFE中zoom的最大值為60(和分辨率無關)。所在在ICE上我們應該讓MAX_ZOOM_LEVEL×ZOOM_STEP=60。要麼增大MAX_ZOOM_LEVEL,要麼增大ZOOM_STEP。

下面再來看一下zoom等級的對應關系(高通可以做到最大的就是zoom4X,這個是HW(MDP和jpegencoder)的限制):

下面看一下HAL層zoom的接口

HAL層的接口比較簡單,就是setZoom,上層傳遞一個zoom的level即可,執行時會判斷參數,如果沒有超出則通知VFE進行crop,如下:

       是以surfaceflinger在更新畫面的時候就會根據這些參數來配置MDP,完成後續的操作了。

       拍照的時候同樣也是這樣的原理,差别在于crop中的資訊不需要傳遞給上層,而是直接傳遞給jpegencoder即可(寫到mDimension這個結構體中),如下(HAL中的receiveRawPicture函數):

Jpegencoder完成後,HAL隻需要把zoom好的jpegdata callback給上層就OK了,是以拍照部分的zoom不需要上層額外的處理。

下面看看Camera service裡面是怎麼處理的?

       Cameraservice收到callback後會把crop相關資訊及标志更新到preview所申請的surface中.

下面看一下VFE輸出資料的格式:

在Preview的時候,通過MSM_CAM_IOCTL_GETFRAME系統指令從底層得到preview的資料,格式如下:

  buffer為資料位址,y_off和cbcr_off分辨為Y的偏移和CBCR的偏移,通過y_off=0,cbcr_off=w*h,這裡和zoom相關的是cropinfo,比較重要,如下:

      可以看出有2個buffer的參數,其中1是preview的,2是snapshot的。如果沒有開啟zoom功能,這些參數都是空的;如果zoom的level比較低,VFE足以處理,那麼這些參數也是空的。

隻有當VFE不足以處理所需要的zoom level時,這些參數的值才有意義。具體含義如下:

out的值代表上層需要資料的寬和高,比如說上層設定的preview大小為480×320,那麼out1_w=480;out1_h=320;而in的值則代表後端的MDP或是jpegencoder需要crop的大小,舉例來說明:

      Sensor輸出VGApreview畫面,MMI設定HVGApreview大小,如果要做2X的zoom,VFE能力有限,隻能做640/480=1.3X,這個時候VFE輸出資料是crop後的HVGA資料,crop資訊中的in1_w=320;out1_w=216,意思是後面的MDP需要從HVGA的資料中crop出320×216大小的資料,然後在scale成HVGA,這樣整體算起來就是zoom2X了。

      是以HAL隻需要将preview資料以及crop info傳遞給上層即可,這裡是通過callback進行的.

繼續閱讀