Qualcomm Camera基礎

高通將android的camera模塊從新修改了一下,與原生的方式存在一些差別。這裏將前段時間學習的一些零散知識進行一下總結,便於之後查閱。linux

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

2.在Qualcomm執行初始化時就會調用到mm_camera_exec()函數來創建config線程 launch_cam_conf_thread();閱讀此線程函數體會發現裏面使用了select機制來檢測配置指令並進行分發(調用不一樣的分支函 數)。後面就是一連串的function call了。 關於select機制還有很多疑點須要進一步學習:指令的來源?如何對文件進行控制的?git

好比下面這一段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
......shell

看過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的像素就越少,以拍照3M2048×1536sensor輸出的原始照片爲3M)的照片爲例,若是作2Xzoom,那麼須要從原始照片中crop1024×768的畫面,而後再插值放大成2048×1536;若是是4Xzoom,那麼須要從原始照片中crop512×384的畫面,而後再插值放大成2048×1536,以此類推。倍數是指寬和高的倍數,而非面積。

下面結合圖片來講明一下數碼變焦的原理:

       1、當用戶須要拍照畫面的尺寸和sensor輸出畫面的尺寸一致


原始照片,紅色部分爲zoom後須要crop的部分


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

能夠發現,zoom先後照片大小是一致的,但照片的範圍變小了,感受是鏡頭拉近了,其實就是經過crop後再插值放大來完成,zoom的倍數越高,須要插值的像素就越多,zoom後的照片就會越模糊。

Note:這裏的插值放大是指軟件算法,和圖像處理軟件中那種線性放大是不一樣的,關於算法的實現這裏很少介紹了。

 

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

下圖是sensor輸出的原始照片,1600×1200。須要拍照的分辨率爲800×600,便可以做2Xdigitalzoom


在這種情況下是不須要插值放大的,圖片的質量並無下降;但若是zoom的等級比較大,好比要4xzoom,那麼光靠crop是不行的,仍是得再經過插值放大來完成。一般說來,若是拍照的分辨率比較小,zoom大均可以只經過crop的方式來完成。在上章節中介紹了digitalzoom的效果以及基本的實現原理,本章將着重介紹高通平臺上實現digitalzoom所涉及的相關模塊架構,由於digitalzoomcamera中的一個feature,分別須要在previewsnapshot中完成,


所涉及的相關模塊也都是和
camera相關的,以下所示:

上圖是preview的時候,digitalzoom所涉及的相關模塊,各個模塊的用途以下(這裏主要介紹sensorVFEMDP):

一、 Sensor

       雖然自己也有zoom的功能,但在這裏並未使用。Preview時若是作digitalzoom,只是正常的輸出frame而已,好比輸出30fpsVGA數據(YUV)。

二、 VFE

DSP的一部分,功能主要都是和圖像處理相關,在zoom的時候,它的用途主要就是Crop(剪裁),它會把sensor輸出的VGA數據croppreview時所須要大小的數據,如CIF352×288),這樣的話至關於已經作了一部分zoom640/352,大概是1.8X,若是不夠,剩餘的zoom將由後面的MDP來完成。

NoteVFE只有crop的功能,沒有upscale(放大)的能力,因此VFE最多隻能完成有限的zoom

三、 MDP

這是一個專門處理顯示數據的處理器,功能比較齊全,在zoom的時候主要的用處就是cropupscale。由於VFEzoom能力有限,因此當VFE不能知足要求的時候,MDP則繼續完成剩餘的zoom,好比:若是要求preview畫面的大小爲QVGA,如今要作4Xzoom,那麼VFE會從原始的VGA數據中cropQVGA大小的數據,至關於已經作了2Xzoom,那麼剩下的2Xzoom怎麼作呢?MDP會從VFE輸出的QVGA320×240)數據中crop160×120大小的數據(從中間截取),而後再upscaleQVGA大小的數據送到LCD顯示,這樣至關於又作了2Xzoom,因此加起來一共作了4Xzoom

NoteMDP最大能夠進行4Xupscale

 

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

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

 

一、             Sensor

輸出拍照須要的原始數據。在當前應用中,無論設置的拍照分辨率是多少,咱們要求sensor輸出的拍照數據是固定的,即最大3M(2048*1536,ICE爲例)

二、             VFE

功能和preview時候是一致的,只不過在拍照的時候,VFE會根據zoom的等級以及須要拍照的分辨率來自動crop出合適大小的數據。

例如選擇拍照的分辨率爲2048×1536zoomlevel4X,那麼VFE將從原始的2048×1536的數據中crop512×384大小的數據,後面的zoomVideocore中的jpegencoder完成。

還有一種情況,若是拍照的分辨率較小,那麼有可能只經過VFEcrop就能夠完成zoom功能,好比拍照的分辨率爲1024×768,這個時候若是作2Xzoom,那麼VFE只須要從原始的2048×1536的數據中間直接crop1024×768的數據便可,後面就不須要再用jpegencoderzoom了。但若是zoom的等級比較高,後面的2Xzoom仍是要經過jpegencoder來作了。

三、             Video core

               負責把VFE輸出的數據encoderjpeg文件,這裏的jpegencoder還有一個比較重要的功能,那就是upscale,經過這個功能,再搭配以前VFEcrop功能,zoom就能夠完成了。

       NoteJpeg encoderupscale功能是有限的,最大能夠進行4X的放大,目前能夠知足ICE上的需求。

               能夠看出,從HW架構來講,previewsnapshot只是在後面的upscale部分有所區別,前者是經過MDP來完成,後者則是經過jpegencoderDSP)來完成。

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

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

Note:目前以Androiddonut版本爲例,高通在androidéclair版本上尚未導入

先來看一下Preview的流程:
一、VFEdriver會把從sensor傳送來的frame數據crop成上層須要的大小(具體若是crop要根據zoom的level),而後連同crop信息一塊兒把數據傳送到HAL。
二、HAL層不會對preview數據作任何處理,它會這些數據原封不動的callback到camera service,一樣包含cropinfo(下章節會詳細介紹crop info)。
三、Camera service在一開始的時候會在surfaceflinger中建立一個surface。當cameraservice收到preview數據的時候,2個主要接口會被調用:
1)     zoomUpScale_callback
經過調用mSurface->updateCropRect接口把crop相關信息通知給surfaceflinger
2)     previewCallback
經過調用mSurface->postBuffer接口把preview的數據傳遞給surfaceflinger。
四、Surfaceflinger收到數據和crop信息後會調用copybit的接口來驅動MDP去作相關的動做(crop&upscale),而後就去畫屏了。

再來看一下snapshot時的流程:
一、VFEdriver把從sensor傳遞來的原始拍照數據(最大分辨率:2048×1536)crop成zoom須要大小的數據,連同crop信息一塊兒傳遞給HAL。
二、HAL層收到snapshot的數據後會先去檢查crop info,判斷是否須要jpegencoder去作upscale的動做。若是不須要就直接encode成jpeg數據;若是須要,填好upscale的參數再作encode。
三、Jpeg encoder後的數據會從HAL callback到camera service,cameraservice會在通知上層去把數據寫成文件。
因而可知,在snapshot的時候,整個zoom在HAL就能夠完成了,而不像preview的時候,須要在surfaceflinger中配置MDP協助完成。具體的原理在第二章節中有詳細的敘述,這裏就不重複了。

 

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

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

Note:基於高通5110 releasecode

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

#define MAX_ZOOM_LEVEL5//對於user來講能夠zoom的等級

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

另外須要說明高通VFEzoom的最大值爲60(和分辨率無關)。所在在ICE上咱們應該讓MAX_ZOOM_LEVEL×ZOOM_STEP60。要麼增大MAX_ZOOM_LEVEL,要麼增大ZOOM_STEP

下面再來看一下zoom等級的對應關係(高通能夠作到最大的就是zoom4X,這個是HWMDPjpegencoder)的限制):


 

下面看一下HALzoom的接口

HAL層的接口比較簡單,就是setZoom,上層傳遞一個zoomlevel便可,執行時會判斷參數,若是沒有超出則通知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_offcbcr_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進行的.

相關文章
相關標籤/搜索