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