總體介紹 Android Camera 框架從整體上看是一個(gè) client/service 的架構(gòu),有兩個(gè)進(jìn)程:一個(gè)是 client 進(jìn) 程,可以看成是 AP 端,主要包括 JAVA 代碼與一些 native c/c++代碼;另一個(gè)是 service 進(jìn) 程,屬于服務(wù)端,是 native c/c++代碼,主要負(fù)責(zé)和 linux kernel 中的 camera driver 交互,搜 集 linux kernel 中 camera driver 傳上來的數(shù)據(jù),并交給顯示系統(tǒng)(surface)顯示,。client 進(jìn)程與 service 進(jìn)程通過 Binder 機(jī)制通信, client 端通過調(diào)用 service 端的接口實(shí)現(xiàn)各個(gè)具體的功能,。 需要注意的是真正的 preview 數(shù)據(jù)不會(huì)通過 Binder IPC 機(jī)制從 service 端復(fù)制到 client 端, 但 會(huì)通過回調(diào)函數(shù)與消息的機(jī)制將 preview 數(shù)據(jù) buffer 的地址傳到 client 端, 最終可在 JAVA AP 中操作處理這個(gè) preview 數(shù)據(jù),。 client 端 從 JAVA AP 的角度看 camera ap 就是調(diào)用 FrameWork 層的 android.hardware.camera 類來實(shí)現(xiàn) 具體的功能,。JAVA Ap 最終被打包成 APK,。 FrameWork 層主要提供了 android.hardware.camera 類給應(yīng)用層使用,這個(gè)類也是 JAVA 代碼 實(shí) 現(xiàn) ,。 Android.hardware.camera 類 通 過 JNI 調(diào) 用 native 代 碼 實(shí) 現(xiàn) 具 體 的 功 能 ,。 Android.hardware.camera 類中提供了如下的一個(gè)參數(shù)類給應(yīng)用層使用: public class Parameters { // Parameter keys to communicate with the camera driver。 private static final String KEY_PREVIEW_SIZE = "preview-size"; private static final String KEY_PREVIEW_FORMAT = "preview-format"; ...... } 參數(shù)會(huì)以字典(map)的方式組織存儲(chǔ)起來,關(guān)鍵字就是 Parameters 類中的這些靜態(tài)字符 串,。這些參數(shù)最終會(huì)以形如“preview-size=640X480;preview-format=yuv422sp;....”格式的 字符串傳到 service 端,。 源代碼位于:framework/base/core/java/android/hardware/camera.java 提供的接口示例: 獲得一個(gè) android.hardware.camera 類的實(shí)例 public static Camera open() {return new Camera(); } 接口直接調(diào)用 native 代碼(android_hardware_camera.cpp 中的代碼) public native final void startPreview(); public native final void stopPreview(); android.hardware.camera 類的 JNI 調(diào)用實(shí)現(xiàn)在 android_hardware_camera.cpp 文件中,源代碼 位置: framework/base/core/jni/android_hardware_camera.cpp (framework/base/core/jni/文件夾下的文件都被編譯進(jìn) libandroid_runtime.so 公共庫(kù)中 ) android_hardware_camera.cpp 文件中的 JNI 調(diào)用實(shí)現(xiàn)函數(shù)都如下圖: android_hardware_camera.cpp 文件中的 register_android_hardware_Camera(JNIEnv *env)函數(shù)會(huì)將上面的 native 函數(shù)注冊(cè)到虛擬機(jī)中,以供 FrameWork 層的 JAVA 代碼調(diào)用。這些 native 函數(shù)通過調(diào)用 libcamera_client.so 中的 Camera 類實(shí)現(xiàn)具體的功能,。 核心的 libcamera_client.so 動(dòng)態(tài)庫(kù)源代碼位于: frameworks/base/libs/camera/, 實(shí)現(xiàn)了如下幾 個(gè)類: Camera---->Camera.cpp/Camera.h CameraParameters--->CameraParameters.cpp/CameraParameters.h Icamera--->ICamera.cpp/ICamera.h IcameraClient--->ICameraClient.cpp/ICameraClient.h IcameraService--->ICameraService.cpp/ICameraService.h Icamera,、IcameraClient、IcameraService 三個(gè)類是按照 Binder IPC 通信要求的框架實(shí)現(xiàn)的,用 來與 service 端通信,。 類 CameraParameters 接收 FrameWork 層的 android.hardware.camera::Parameters 類為參數(shù), 解析與格式化所有的參數(shù)設(shè)置,。 Camera 是一個(gè)很重要的類, 它與 CameraService 端通過 Binder IPC 機(jī)制交互來實(shí)現(xiàn)具體功能。 Camera 繼承自 BnCameraClient,并最終繼承自 ICameraClient,。 Camera 類通過: sp sp sp 得到名字為“media.camera”的 CameraService,。通過調(diào)用 CameraService 的接口 connect()返 回得到 sp mClient。mClient 繼承自 BnCamera,并最終繼承自 ICamera,。 之 后 Camera 類 通 過 這 個(gè) sp CameraService::Client 類 mClient 的函數(shù),。CameraService::Client 類實(shí)現(xiàn)具體的功能。 service 端 實(shí)現(xiàn)在動(dòng)態(tài)庫(kù) libcameraservice.so 中, 源代碼位于: frameworks/base/camera/libcameraservice Libcameraservice.so 中主要有下面兩個(gè)類:Libcameraservice.so::CameraService 類 , 繼 承 自 BnCameraService , 并 最 終 繼 承 自 ICameraService Libcameraservice.so::CameraService::Client 類, 繼承自 BnCamera, 并最終繼承自 ICamera CameraService::Client 類通過調(diào)用 Camera HAL 層來實(shí)現(xiàn)具體的功能,。目前的 code 中只支持 一個(gè) CameraService::Client 實(shí)例,。 Camera Service 在 系 統(tǒng) 啟 動(dòng) 時(shí) new 了 一 個(gè) 實(shí) 例 , 以 “ media.camera ” 為 名 字 注 冊(cè) 到 ServiceManager 中。在 init.rc 中有如下代碼執(zhí)行可執(zhí)行文件/system/bin/mediaserver,啟動(dòng)多 媒體服務(wù)進(jìn)程,。 service media /system/bin/mediaserver Mediaserver 的 c 代碼如下: int main(int argc,char** argv) { sp sp LOGI("ServiceManager: %p",sm,。get()); AudioFlinger::instantiate(); MediaPlayerService::instantiate(); CameraService::instantiate(); AudioPolicyService::instantiate(); ProcessState::self()->startThreadPool(); IPCThreadState::self()->joinThreadPool(); } Camera HAL(硬件抽象層) Libcameraservice.so::CameraService::Client 類調(diào)用 camera HAL 的代碼實(shí)現(xiàn)具體功能,camera HAL 一般實(shí)現(xiàn)為一個(gè)動(dòng)態(tài)庫(kù) libcamera.so(動(dòng)態(tài)庫(kù)名字可以改,只需要與 Android.mk 一致即 可)。Android 只給了一個(gè)定義文件: /home/miracle/Work/android/android_src/froyo/frameworks/base/include/camera/CameraHard wareInterface.h class CameraHardwareInterface : public virtual RefBase { public: virtual ~CameraHardwareInterface() { } virtual sp virtual sp virtual void setCallbacks(notify_callback notify_cb,data_callback data_cb, data_callback_timestamp data_cb_timestamp,void* user) = 0; virtual void enableMsgType(int32_t msgType) = 0; virtual void disableMsgType(int32_t msgType) = 0; virtual bool msgTypeEnabled(int32_t msgType) = 0; virtual status_t startPreview() = 0; virtual bool useOverlay() {return false;} virtual status_t setOverlay(const sp virtual void stopPreview() = 0; virtual bool previewEnabled() = 0; virtual status_t startRecording() = 0; virtual bool recordingEnabled() = 0; virtual status_t autoFocus() = 0; virtual status_t cancelAutoFocus() = 0; virtual status_t takePicture() = 0; virtual status_t cancelPicture() = 0; virtual status_t setParameters(const CameraParameters& params) = 0; virtual CameraParameters getParameters() const = 0; virtual status_t sendCommand(int32_t cmd,int32_t arg1,int32_t arg2) = 0; virtual void release() = 0; virtual status_t dump(int fd,const Vector }; extern "C" sp }; // namespace android 可以看到在 JAVA Ap 中的功能調(diào)用最終會(huì)調(diào)用到 HAL 層這里,Camera HAL 層的實(shí)現(xiàn)是主要 的工作, 它一般通過 V4L2 command 從 linux kernel 中的 camera driver 得到 preview 數(shù)據(jù),。然 后交給 surface(overlay)顯示或者保存為文件,。在 HAL 層需要打開對(duì)應(yīng)的設(shè)備文件,并通過 ioctrl 訪問 camera driver。Android 通過這個(gè) HAL 層來保證底層硬件(驅(qū)動(dòng))改變,只需修改 對(duì)應(yīng)的 HAL 層代碼,FrameWork 層與 JAVA Ap 的都不用改變,。 Preview 數(shù)據(jù)流程 Android 框架中 preview 數(shù)據(jù)的顯示過程如下: 1,、 打開內(nèi)核設(shè)備文件,。CameraHardwareInterface.h 中定義的 openCameraHardware()打開 linux kernel 中的 camera driver 的設(shè)備文件(如/dev/video0) ,創(chuàng)建初始化一些相關(guān)的類 的實(shí)例。 2,、 設(shè)置攝像頭的工作參數(shù),。CameraHardwareInterface.h 中定義的 setParameters()函數(shù),在 這一步可以通過參數(shù)告訴 camera HAL 使用哪一個(gè)硬件攝像頭, 以及它工作的參數(shù) (size, format 等) ,并在 HAL 層分配存儲(chǔ) preview 數(shù)據(jù)的 buffers(如果 buffers 是在 linux kernel 中的 camera driver 中分配的,在這一步也會(huì)拿到這些 buffers mmap 后的地址指針) 。 3,、 設(shè)置顯示目標(biāo),。需在 JAVA APP 中創(chuàng)建一個(gè) surface 然后傳遞到 CameraService 中。會(huì)調(diào) 用到 libcameraservice.so 中的 setPreviewDisplay(const sp 這里分兩種情況考慮:一種是不使用 overlay;一種是使用 overlay 顯示,。如果不使用 overlay 那設(shè)置顯示目標(biāo)最后就在 libcameraservice.so 中,不會(huì)進(jìn) Camera HAL 動(dòng)態(tài)庫(kù)。 并將上一步拿到的 preview 數(shù)據(jù) buffers 地址注冊(cè)到 surface 中,。 如果使用 overlay 那在 libcameraservice.so 中會(huì)通過傳進(jìn)來的 Isurface 創(chuàng)建 Overlay 類的實(shí)例,然后調(diào)用 CameraHardwareInterface.h 中定義的 setOverlay()設(shè)置到 Camera HAL 動(dòng)態(tài)庫(kù)中,。 4、 開始 preview 工作,。最終調(diào)用到 CameraHardwareInterface.h 中定義的 startPreview()函數(shù),。 如果不使用 overlay,Camera HAL 得到 linux kernel 中的 preview 數(shù)據(jù)后回調(diào)通知到 libcameraservice.so 中。在 libcameraservice.so 中會(huì)使用上一步的 surface 進(jìn)行顯示,。如 果使用 overlay, Camera HAL 得到 linux kernel 中的 preview 數(shù)據(jù)后直接交給 Overlay 對(duì)象, 然后有 Overlay HAL 去顯示,。 模擬器中的虛擬 camera 如果沒有 camera 硬件,不實(shí)現(xiàn)真正的 Camera HAL 動(dòng)態(tài)庫(kù),可以使用虛擬 camera。源代碼 位于: frameworks/base/camera/libcameraservice/FakeCamera.cpp frameworks/base/camera/libcameraservice/CameraHardwareStub.cpp FakeCamera.cpp 文件提供虛擬的 preview 數(shù)據(jù),。CameraHardwareStub.cpp 文件中實(shí)現(xiàn)了 camera HAL(硬件抽象層)的功能,。當(dāng)宏 USE_CAMERA_STUB 為 true 時(shí)可以使用這個(gè)虛擬的 camera。 ifeq ($(USE_CAMERA_STUB),true) LOCAL_STATIC_LIBRARIES += libcamerastub //虛擬的 camera #if want show LOGV message,should use follow define,。 add 0929 #LOCAL_CFLAGS += -DLOG_NDEBUG=0 LOCAL_CFLAGS += -include CameraHardwareStub。h else LOCAL_SHARED_LIBRARIES += libcamera //真正的 camera HAL 庫(kù) endif 框架圖 Overlay 簡(jiǎn)單介紹overlay 一般用在 camera preview,視頻播放等需要高幀率的地方,還有可能 UI 界面設(shè)計(jì) 的需求, 如map 地圖查看軟件需兩層顯示信息,。 overlay 需要硬件與驅(qū)動(dòng)的支持,。 Overlay 沒 有 java 層的 code,也就沒有 JNI 調(diào)用。一般都在 native 中使用,。 Overlay 的使用方法 1. 頭文件 overlay object 對(duì)外的接口 #include 下面三個(gè)用于從 HAL 得到 overlay object #include #include #include 2. 相關(guān)動(dòng)態(tài)庫(kù)文件 libui.so libsurfaceflinger_client.so 3. 調(diào)用步驟 創(chuàng)建 surfaceflinger 的客戶端 sp 創(chuàng)建推模式 surface sp PIXEL_FORMAT_UNKNOWN,IsurfaceComposer::ePushBuffers); 獲得 surface 接口 sp 獲得 overlay 設(shè)備 sp 這里會(huì)通過調(diào)用 overlay hal 層的 createoverlay()打開對(duì)應(yīng)的設(shè)備文件。 創(chuàng)建 overlay 對(duì)象 sp 使用 overlay API overlay_buffer_t buffer; //typedef void* overlay_buffer_t; void* address = overlay->getBufferAddress(buffer); address 指針就是 mmap 后的 overlay buffer 指針, 只需將數(shù)據(jù)填充到這個(gè) address 指針就可 以看到畫面了,。 Android overlay 框架 overlay 本地框架代碼 源代碼位于:frameworks/base/libs/ui/ ,編譯到 libui.so 中,。 Overlay.cpp : 提 供 給 外 部 程 序 調(diào) 用 的 Overlay object 接 口 與 API 。 定 義 在 frameworks/base/include/ui/Overlay.h 中,。實(shí)現(xiàn)了兩個(gè)類:OverlayRef 與 Overlay,。外部 程序通過這個(gè) Overlay 對(duì)象來使用 overlay 的功能,。Overlay.cpp 內(nèi)部通過 binder 與 surfaceFlinger service 通信,最終調(diào)用到 Overlay HAL。 IOVerlay.cpp: 定義提供 binder 所需的類, 其中 LayerBuffer::OverlaySource::OverlayChannel 繼承自 BnOverlay,。 overlay 的服務(wù)部分代碼 源代碼位于:frameworks/base/libs/surfaceflinger/ overlay 系統(tǒng)被包在 Surface 系統(tǒng)中, 通過 surface 來控制 overlay 或者在不使用 overlay 的情 況下統(tǒng)一的來管理,。所以 overlay 的 service 部分也包含在 SurfaceFlinger service 中,主要的 類 LayerBuffer。 android 啟動(dòng)的時(shí)候會(huì)啟動(dòng) SurfaceFlinger service,SurfaceFlinger 啟動(dòng)時(shí)會(huì)實(shí)例化一個(gè) DisplayHardware: DisplayHardware* const hw = new DisplayHardware(this,dpy); DisplayHardware 構(gòu)造函數(shù)調(diào)用函數(shù) init: DisplayHardware::DisplayHardware(const sp uint32_t dpy) : DisplayHardwareBase(flinger,dpy) { init(dpy); } Init 函數(shù)中: if(hw_get_module(OVERLAY_HARDWARE_MODULE_ID,&module) == 0) { overlay_control_open(module,&mOverlayEngine); } 獲得 overlay 的 module 參數(shù), 調(diào)用 overlay_control_open 獲取控制設(shè)備結(jié)構(gòu) mOverlayEngine,。 擁有了控制設(shè)備結(jié)構(gòu)體就可以創(chuàng)建數(shù)據(jù)設(shè)備結(jié)構(gòu)體 ,并具體控制使用 overlay 了,。 overlay HAL 層 源代碼位于:hardware/libhardware/include/hardware/overlay.h android 只給出了接口的定義,需要我們自己實(shí)現(xiàn)具體的功能。 overlay hal 層生成的動(dòng)態(tài)庫(kù) 在 SurfaceFlinger 中顯式的加載,。Overlay HAL 層具體功能如何實(shí)現(xiàn)取決于硬件與驅(qū)動(dòng)程序,。 Android 提供了一個(gè) Overlay Hal 層實(shí)現(xiàn)的框架代碼, hardware/libhardware/modules/overlay/。 因?yàn)?overlay hal 層生成的動(dòng)態(tài)庫(kù)是顯式的動(dòng)態(tài)打開(hw_get_module -> dlopen),所以這個(gè)庫(kù) 文件必須放在文件系統(tǒng)的 system/lib/hw/下,。 多層 overlay 例如需要同時(shí)支持 overlay1 與 overlay2,。 1. overlay hal 的 overlay_control_device_t 中要添加 overlay1 與 overlay2 的結(jié)構(gòu): struct overlay_control_context_t { struct overlay_control_device_t device; /* our private state goes below here */ struct overlay_t* overlay_video1;//overlay1 struct overlay_t* overlay_video2;//overlay2 }; 每個(gè) overlay_t 代表一層 overlay,每層 ovelay 有自己的 handle。 在構(gòu)造 OverlayRef 之前需指明使用哪一層 overlay: sp 可以使用自定義參數(shù)調(diào)用 overlay_control_device_t::setParameter()來指定 Hal 層具體實(shí)現(xiàn),。 2,通過 Overlay object 來拿到 overlay1 與 overlay2 的 buffer 指針,。 |
|