1. 程式人生 > >Qualcomm Android camera 架構簡析及如何debug

Qualcomm Android camera 架構簡析及如何debug

              Qualcomm Android camera 架構簡析及如何debug

一. Camera模組(CCM)介紹

CCM一般包含四大件: 鏡頭(lens)、感測器(sensor)、軟板(FPC)、影象處理晶片(DSP):

 

Camera的成像原理可以簡單概括如下

 

1、CCD/CMOS將被攝體的光訊號轉變為電訊號—電子影象(模擬訊號) 2、由模/數轉換器(ADC)晶片來將模擬訊號轉化為數字訊號 3、數字訊號形成後,由DSP或編碼庫對訊號進行壓縮並轉化為特定的影象檔案格式儲存

4. 送到cpu中處理並display。

 

二. 電路圖

 

1. 電源

--dvdd,iovdd,avdd。

2. I2c

由於I2C介面採用OpenDrain機制,器件本身只能輸出低電平,無法主動輸出高電平,只能通過外部上拉電阻RP將訊號線拉至高電平。因此I2C總線上必須有上拉電阻!

阻值:I2C的上拉電阻可以是1.5K,2.2K,4.7K, 電阻的大小對時序有一定影響,對訊號的上升時間和下降時間也有影響,一般接1.5K或2.2K。不能低於1k。高於10k。

過小的話灌入埠的電流變大,低電平變高。過大上升平緩。

通產情況下,SDA,SCL兩條線上的上拉電阻取值是一致的,並上拉到同一電源上。

在I2c匯流排可以串連300歐姆電阻RS可以用於防止SDA和SCL線的高電壓毛刺

.

3. Mipi

而DDR是一個時鐘週期內傳輸兩次次資料,它能夠在時鐘的上升期和下降期各傳輸一次資料,因此稱為雙倍速率同步動態隨機儲存器

MIPI的通道模式和線上電平。在正常的操作模式下,資料通道處於高速模式或者控制模式。在高速模式下,通道狀態是差分的0或者1,也就是線對內P比N高時,定義為1,P比N低時,定義為0,高低速分別200MV,1.2V.

控制模式:LP11,LP10,LP01,LP00四個狀態;MIPI協議規定控制模式4個不同狀態組成的不同時序代表著將要進入或者退出高速模式等;比如LP11-LP01-LP00序列後,進入高速模式。下圖為線上電平的圖示

MIN [ Settle count * T(Timer clock)] > T(HS_SETTLE)_MIN

MAX [ Settle count * T(Timer clock)] < T(HS-PREPARE)+T(HS_ZERO) - 4*T(Timer clock)

 

三.AndroidCamera框架簡析

 

Android框架看,分為四層:應用層、應用框架層、庫層、核心層。

庫層是Android與底層硬體通訊介面,它封裝底層硬體介面實現該模組的具體邏輯,並以服務的形式通過Binder通訊機制暴露給應用框架

1.camera應用層

2.Framework.Camera client/service

3.硬體抽象層HAL Hardware Abstraction Layer

 

 

1.1、camera應用層

Camera 的應用層在Android 上表現為直接呼叫SDK API 開發的一個Camera 應用APK 包。主要對 android.hardware.Camera(在Framework中) 類的呼叫,並且實現Camera 應用的業務邏輯和UI 顯示。

使用這個android.hardware.Camera類,需要在Manifest 檔案宣告Camera 的許可權,另外還 需要新增一些<uses-feature> 元素來宣告應用中的Camera 特性。

<uses-feature android:name = "android.hardware.camera" />

......

<uses-feature android:name = "android.hardware.camera.autofocus" />

1.2、Framework層

1.android.hardware.Camera封裝類

/frameworks/base/core/Java/android/hardware/Camera.java

這是Android 提供給app層呼叫的java介面。這個類用來連線或斷開一個Camera 服務,設定拍攝引數,預覽,拍照等。作為Android SDK Camera部分提供給上層應用,並通過JNI的方式呼叫本地C++程式碼。

Camera的Java native呼叫部分(JNI):/android/frameworks/base/core/jni/android_hardware_Camera.cpp。承接JAVA 程式碼到C++ 程式碼的橋樑。

1.3.Camera框架的client部分:

程式碼位置:/android/frameworks/av/camera/ICameraClient.cpp

這部分的內容編譯生成libcamera_client.so 。與另外一部分內容服務端libcameraservice.so 通過程序間通訊(即Binder 機制)的方式進行通訊

1.4.Camera框架的service部分

程式碼位置:/android/frameworks/av/camera/ICameraService.cpp

這部分內容被編譯成庫libcameraservice.so 。CameraService 是Camera 服務,Camera 框架的中間層,用於連結CameraHardwareInterface 和Client部分 ,它通過呼叫實際的Camera 硬體介面來實現功能,即下層HAL層。

1.5、硬體抽象層HAL

這層的程式碼在/android/hardware/qcom/camera, 直接和底層硬體驅動相關的。框架層對下在CameraHardwareInterface.h標頭檔案中定義了Camera硬體抽象層的介面,它是包含純虛擬函式的類,必須被實現類繼承才能使用。HAL層正好繼承CameraHardwareInterface介面,依據V4l2規範例項化底層硬體驅動,使用ioctl方式呼叫驅動.

程式碼流程:

1、Camera apk----java

2、camerajava interface,JNI-----(java—>C++)

3、camera client-----C++

4、camera services----C++

5、HAL----C++

6、camera drv

a. 點選Camera 應用後,進入CameraActivity.java,完成初始化,onCreate 呼叫setModuleFromIndex 方法,賦值  mCurrentModule = new PhotoModule();

mCameraDevice = CameraUtil.openCamera(                mActivity, mCameraId, mHandler,                mActivity.getCameraOpenErrorCallback())其中mCameraDevice是com.android.camera.CameraManager.CameraProxy;的例項。CameraUtil屬於公共的API,用於給不同模組提供對Camera的不同操作。在它openCamera 方法裡,執行:CameraHolder.instance().open(handler, cameraId, cb);其中CameraHolder.instance()單例模式。目的就是控制,相機開啟的只有能是一個。再次開啟前,要確認上次已經銷燬。

b 在CameraManager系統服務,獲得camera裝置物件為Camera裝置提供操作的方法。

    public CameraProxy cameraOpen(            Handler handler, int cameraId, CameraOpenErrorCallback callback);

CameraProxy AndroidCameraProxyImpl類這個介面就是將對Camera 接受和傳送的操作,送達到Camera裝置。

這個介面的實現類是AndroidCameraProxyImpl,這個類屬於AndroidCameraManagerImpl的內部類。在AndroidCameraManagerImpl.java 裡面還有一個內部類CameraHandler,這個類屬於Handler。在CameraHandler的handleMessage方法裡,就是根據不同的訊息引數來對android.hardware.Camera 進行控制。比如開啟,釋放,對焦,變焦等等

c. jni

應用裡通過CameraProxy物件傳送訊息給CameraHandler處理,CameraHandler通過android.hardware.Camera的介面去呼叫JNI層的方法,Camera JNI實現在android_hardware_Camera.cpp裡

d. Camerahal

     Camera HAL層的介面是通過CameraHardwareInterface類的各個方法給framework呼叫, CameraHardwareInterface物件在CameraClient裡實現,並且CameraClient封裝了Camera硬體的各個操作的介面.

Camera.cpp裡的每一個Camera的操作方法最後都呼叫ICamera接口裡定義的方法,這個介面被BpCamera繼承,BpCamera是binder機制的標準使用方法,他對應的呼叫類就是BnCamera.

e. 為了實現一個具體功能的Camera,在最底層還需要一個硬體相關的Camere 驅動庫(例如通過呼叫video for Linux 驅動程式和Jpeg 編碼程式實現)。這個庫將被Camera 的服務庫libcameraservice.so 呼叫。  

f.Camera核心code

Driver,csid,csiphy..

android啟動和camera probe

Probe:Server.c->main

四.Camera debug:

Sensor log:

adb shell setprop persist.camera.hal.debug.mask 536870919

HAL/mm-camera-interface/mm-jpeg-interface CDBG_HIGH() 和CDBG() log都會被列印. CDBG_ERROR() log總是被列印

0-27位決定列印模組(目前只有三個模組):

§Bit0: HAL (hardware/qcom/camera/QCamera2/HAL)

§Bit1: mm-camera-interface (hardware/qcom/camera/QCamera2/stack/mm-camera-interface)

§Bit2: mm-jpeg-interface (hardware/qcom/camera/QCamera2/stack/mm-jpeg-interface)

adb shell setprop persist.camera.sensor.debug 3

§   SERR(), SHIGH()和SLOW() log會被列印

adb shell setprop persist.camera.imglib.logs 4

§  IDBG_ERROR(), IDBG_HIGH() , IDBG_MED(), IDBG_LOW()都會被列印

adb shell setprop persist.camera.pproc.debug.mask 805306375

§805306375 = 0x30000007, 表示PPROC/C2D/CPP模組CDBG_HIGH(), CDBG(), CDBG_LOW() 都會被列印.

  Bit0: PPROC (mm-camera2/media-controller/modules/pproc-new)

§Bit1: C2D (mm-camera2/media-controller/modules/pproc-new/c2d)

§Bit2: CPP (mm-camera2/media-controller/modules/pproc-new/cpp)

adb shell setprop persist.camera.mct.debug.mask  536870913

§536870913 = 0x20000001, 表示MCT CDBG_HIGH(), CDBG() 都會被列印.

0-27位決定列印模組(目前只一個模組):

§Bit0: PPROC (mm-camera2/media-controller/mct)

adb shell setprop persist.camera.ISP.debug.mask 16777217

§16777217 = 0x1000001, 開啟ISP_MOD_COM. ISP_MOD_LINEARIZATIO log

Bit 0: ISP_MOD_LINEARIZATION

Bit 1: ISP_MOD_ROLLOFF

Bit 2: ISP_MOD_DEMUX

Bit 3: ISP_MOD_DEMOSAIC

Bit 4: ISP_MOD_BPC

Bit 5: ISP_MOD_ABF

Bit 6: ISP_MOD_ASF

Bit 7: ISP_MOD_COLOR_CONV

Bit 8: ISP_MOD_COLOR_CORRECT

Bit 9: ISP_MOD_CHROMA_SS

Bit 10: ISP_MOD_CHROMA_SUPPRESS

Bit 11: ISP_MOD_LA

Bit 12: ISP_MOD_MCE

Bit 13: ISP_MOD_SCE

Bit 14: ISP_MOD_CLF

Bit 15: ISP_MOD_WB

Bit 16: ISP_MOD_GAMMA

Bit 17: ISP_MOD_FOV

Bit 18: ISP_MOD_SCALER

Bit 19: ISP_MOD_BCC

Bit 20: ISP_MOD_CLAMP

Bit 21: ISP_MOD_FRAME_SKIP

Bit 22: ISP_MOD_STATS

Bit 23: ISP_MOD_COLOR_XFORM

Bit 24: ISP_MOD_COM

adb shell setprop persist.camera.stats.debug.mask 7

§7 = 0b111, 開啟AEC/AWB/AF log

Bit 0: STATS_DEBUG_MASK_AEC_LOG

Bit 1: STATS_DEBUG_MASK_AWB_LOG

Bit 2: STATS_DEBUG_MASK_AF_LOG

Bit 3: STATS_DEBUG_MASK_ASD_LOG

Bit 4: STATS_DEBUG_MASK_AFD_LOG

MSM8916 Android 5.0 Camera log -HAL

adb shell setprop persist.camera.hal.debug 2

§表示HAL/mm-camera-interface/mm-jpeg-interfaceCDBG_HIGH() 和CDBG() log都會被列印. CDBG_ERROR() log總是被列印

adb shell setprop persist.camera.sensor.debug 2

§表示sensor module (mm-camera2/media-controller/modules/sensors)SERR() , SHIGH() 和SLOW() log都會被列印.

CPP-log

沒有動態開關,需要修改mm-camera2/media-controller/modules/pproc-new/cpp/cpp_log.h裡面定義的CPP_LOG_VERBOSE後重新編譯

§CPP_LOG_VERBOSE = 0,只有CPP_ERR() log被列印

§CPP_LOG_VERBOSE = 1,CPP_ERR(), CPP_HIGH() log被列印

§CPP_LOG_VERBOSE = 2,CPP_ERR(), CPP_HIGH(), CPP_DBG() log被列印

§CPP_LOG_VERBOSE = 3,CPP_ERR(), CPP_HIGH(), CPP_DBG() , CPP_LOW() log都被列印

§預設CPP_LOG_VERBOSE = 1

adb shell setprop persist.camera.mct.debug 2

§表示MCT(mm-camera2/media-controller/mct)CDBG_ERROR(), CDBG_HIGH(), CDBG() 都會被列印

adb shell setprop persist.camera.stats.debug 2

§開啟AEC ERR/HIGH/LOW log, 即AEC_ERR()/AEC_HIGH()/AEC_LOW() log會被列印

Bit 0-1: STATS_DEBUG_MASK_AEC_LOG

§Bit 2-3: STATS_DEBUG_MASK_AWB_LOG

§Bit 4-5: STATS_DEBUG_MASK_AF_LOG

§Bit 6-7: STATS_DEBUG_MASK_ASD_LOG

§Bit 8-9: STATS_DEBUG_MASK_AFD_LOG

§Bit 10-11: STATS_DEBUG_MASK_Q3A_LOG

§Bit 12-13: STATS_DEBUG_MASK_STATS_LOG

§Bit 14-15: STATS_DEBUG_MASK_IS_LOG

adb shell setprop persist.camera.global.debug 2

§表示HAL/Sensor/MCT/3A 所有ERROR/HIGH/LOW log都會被列印

Kernel log:

Sensor bring up and 常見問題的分析:

如果有高通lisence的同學也可以看看下面文件

參考文件:

80-NU323-2SC_D_Multimedia_Driver_Development_and_Bringup_Guide_-_Camera_Simplified_Chinese.pdf

80-NL239-33SC_D_Linux_Camera_Debugging_Guide_Simplified_Chinese.pdf

80-ND717-2BX_MSM8X10-MSM8X12_SOFTWARE_INTERFACE_FOR_OEMS.pdf