• Android 上Camera分析


    http://blog.csdn.net/u010503912/article/details/52315721

    Android Camera 系统架构源码分析(1)---->Camera的初始化  http://blog.csdn.net/shell812/article/details/49424857

    //------------------------------------------------------------------------------------------------------------------------

    1.总体介绍
      Android Camera框架从整体上看是一个client/service架构。有两个进程,一个是client进程,可以看成AP端
    ,主要包括Java代码和一些native层的c/c++代码;另一个是service进程,属于服务端,是native c/c++代码,
    主要负责和linux kernel中的camera driver交互,搜集linux kernel中driver层传上来的数据,并交给显示系统(surface)显示。client 和 service 进程通过Binder机制进行通信,client端通过调用service端的接口实现各个具体的功能。
      对于preview数据不会通过Binder机制从service端copy 到client端,但会通过回调函数与消息机制将preview数据的buffer地址传到client端,最终可在Java ap中操作处理preview数据。

    2.调用层次划分

    Package -> Framework -> JNI ->Camera.cpp -- (binder) ->CameraService ->Camera HAL -> Qcom ->Camera Driver

    client端:
    Package 中的 camera.java 调用Framework中的 camera.java(framework/base/core/java/android/hardware).
    Framework中的 camera.java 调用 JNI层的native 函数。JNI层的调用实现在android_hardware_camera.cpp(framework/base/core/jni文件下的文件都被 编译进libandroid_runtime.so)文件中,android_hardware_camera.cpp文件中的 register_android_hardware_camera(JNIEnv *env)函数会将native函数注册到虚拟机中,以供framework层的JAVA代码调用,这些native函数通过调用 libcamera_client.so中的camera类实现具体功能。

      核心的libcamera_client.so动态库源代码位于:framework/base/core/av中,其中 Icamera,IcameraClient,IcameraService三个类按照Binder IPC通信要求的框架实现的,用来与service端通信。CameraParameters类接受framework层的 android.hardware.camera::Parameters类为参数。

    service端:
    service端的实现在动态库libcameraservice.so中,源代码位于:frameworks/av/services/camera。
    CameraService:Client类通过调用Camera HAL层来实现具体的功能。

    Camera Service 在系统启动时new了一个实例额,以“media.camera”注册到servicemanager中。在init.rc中启动多媒体服务进程。


    CameraHAL层:
    libcameraservice.so::CameraService::Client类调用camera HAL 的代码实现具体功能。
    JAVA Ap中的功能调用最终会调用到HAL层,HAL层通过startpreview 掉到hardware/qcom/camera中的start_preview.然后就是高通这一层对底层驱动上来的数据做一些处理。从linux kernel中的camera driver得到preview数据。然后交个surface显示或者保存到文件。

    //------------------------------------------------------------------------------------------------------------------------

    一.Camera构架分析
    Android 的Camera包含取景(preview)和拍摄照片(take picture)的功能。目前Android发布版的Camera程序虽然功能比较简单,但是其程序的架构分成客户端和服务器两个部分,它们建立在 Android的进程间通讯Binder的结构上。Android中Camera模块同样遵循Andorid的框架,如下图所示



    Camera Architecture
    Camera模块主要包含了libandroid_runtime.so、libui.so和libcameraservice.so等几个库文件,它们之间的调用关系如下所示:

    在Camera模块的各个库中,libui.so位于核心的位置,它对上层的提供的接口主要是Camera类。
        libcameraservice.so是Camera的server程序,它通过继承libui.so中的类实现server的功能,并且与libui.so中的另外一部分内容通过进程间通讯(即Binder机制)的方式进行通讯。

    libandroid_runtime.so 和libui.so两个库是公用的,其中除了Camera还有其他方面的功能。整个Camera在运行的时 候,可以大致上分成Client和Server两个部分,它们分别在两个进程中运行,它们之间使用Binder机制实现进程间通讯。这样在client调 用接口,功能则在server中实现,但是在client中调用就好像直接调用server中的功能,进程间通讯的部分对上层程序不可见。

    从 框架结构上来看,源码中ICameraService.h、ICameraClient.h和ICamera.h三个类定义了MeidaPlayer的 接口和 架构,ICameraService.cpp和Camera.cpp两个文件则用于Camera架构的实现,Camera的具体功能在下层调用硬件相关的 接 口来实现。 
    从Camera的整体结构上,类Camera是整个系统 核心,ICamera类提供了Camera主要功能的接口,在客户端方面调 用;CameraService是Camera服务,它通过调用实际的Camera硬件接口来实现功能。事实上,图中红色虚线框的部分都是Camera程 序的框架部分,它主要利用了Android的系统的Binder机制来完成通讯。蓝色虚线框的部分通过调用Camera硬件相关的接口完成具体的 Camera服 务功能,其它的部分是为上层的Java程序提供JNI接口。在整体结构上,左边可以视为一个客户端,右边是一个可以视为服务器,二者通过Android的 Bimder来实现进程间的通讯。

    二.Camera工作流程概述

    1.Camera Service的启动

    ①.App_main process: 进程通过AndroidRuntime调用register_jni_procs向JNI注册模块的native函数供JVM调用。

    AndroidRuntime::registerNativeMethods(env, "android/hardware/Camera",

    camMethods, NELEM(camMethods));

            其中camMethods定义如下: 

    1. static JNINativeMethod camMethods[] = { 
    2.  
    3.   { "native_setup", 
    4.  
    5.     "(Ljava/lang/Object;)V", 
    6.  
    7.     (void*)android_hardware_Camera_native_setup }, 
    8.  
    9.   { "native_release", 
    10.  
    11.     "()V", 
    12.  
    13.     (void*)android_hardware_Camera_release }, 
    14.  
    15.   { "setPreviewDisplay", 
    16.  
    17.     "(Landroid/view/Surface;)V", 
    18.  
    19.     (void *)android_hardware_Camera_setPreviewDisplay }, 
    20.  
    21.   { "startPreview", 
    22.  
    23.     "()V", 
    24.  
    25.     (void *)android_hardware_Camera_startPreview }, 
    26.  
    27.   { "stopPreview", 
    28.  
    29.     "()V", 
    30.  
    31.     (void *)android_hardware_Camera_stopPreview }, 
    32.  
    33.   { "previewEnabled", 
    34.  
    35.     "()Z", 
    36.  
    37.     (void *)android_hardware_Camera_previewEnabled }, 
    38.  
    39.   { "setHasPreviewCallback", 
    40.  
    41.     "(ZZ)V", 
    42.  
    43.     (void *)android_hardware_Camera_setHasPreviewCallback }, 
    44.  
    45.   { "native_autoFocus", 
    46.  
    47.     "()V", 
    48.  
    49.     (void *)android_hardware_Camera_autoFocus }, 
    50.  
    51.   { "native_takePicture", 
    52.  
    53.     "()V", 
    54.  
    55.     (void *)android_hardware_Camera_takePicture }, 
    56.  
    57.   { "native_setParameters", 
    58.  
    59.     "(Ljava/lang/String;)V", 
    60.  
    61.     (void *)android_hardware_Camera_setParameters }, 
    62.  
    63.   { "native_getParameters", 
    64.  
    65.     "()Ljava/lang/String;", 
    66.  
    67.     (void *)android_hardware_Camera_getParameters }, 
    68.  
    69.   { "reconnect", 
    70.  
    71.     "()V", 
    72.  
    73.     (void*)android_hardware_Camera_reconnect }, 
    74.  
    75.   { "lock", 
    76.  
    77.     "()I", 
    78.  
    79.     (void*)android_hardware_Camera_lock }, 
    80.  
    81.   { "unlock", 
    82.  
    83.     "()I", 
    84.  
    85.     (void*)android_hardware_Camera_unlock }, 
    86.  
    87. }; 

    JNINativeMethod的第一个成员是一个字符串,表示了JAVA本地调用方法的名称,这个名称是在JAVA程序中调用的名称;第二个成员也是一个字符串,表示JAVA本地调用方法的参数和返回值;第三个成员是JAVA本地调用方法对应的C语言函数。

    ②.Mediaserver proces:进程注册了以下几个server: AudioFlinger、 MediaPlayerServer、CameraService. 

    1. int main(int argc, char** argv) 
    2.  
    3.  
    4.     sp proc(ProcessState::self()); 
    5.  
    6.     sp sm = defaultServiceManager(); 
    7.  
    8.     LOGI("ServiceManager: %p", sm.get()); 
    9.  
    10.     AudioFlinger::instantiate(); 
    11.  
    12.     MediaPlayerService::instantiate(); 
    13.  
    14.     CameraService::instantiate(); 
    15.  
    16.     ProcessState::self()->startThreadPool(); 
    17.  
    18.     IPCThreadState::self()->joinThreadPool(); 
    19.  

     当向ServiceManager注册了CameraService服务后就可以响应client的请求了

    2.client端向service发送请求

    ①.在java应用层调用onCreate()函数得到一个上层的Camera对象 

    1. public void onCreate(Bundle icicle) { 
    2.  
    3. super.onCreate(icicle); 
    4.  
    5. Thread openCameraThread = new Thread( 
    6.  
    7. new Runnable() { 
    8.  
    9. public void run() { 
    10.  
    11.                 mCameraDevice = android.hardware.Camera.open(); 
    12.  
    13.  
    14.  
    15. ); 
    16.  
    17. ……………………… 
    18.  
    19. }     

    ②.通过Camera对象的调用成员函数,而这些成员函数会调用已向JNI注册过的native函数来调用ICamera接口的成员函数向Binder Kernel Driver发送服务请求。

    ③. Binder Kernel Driver接收到client的请求后,通过唤醒service的进程来处理client的请求,处理完后通过回调函数传回数据并通知上层处理已完成。

    三.Camera库文件分析

        上面已提到Camera模块主要包含libandroid_runtime.so、libui.so、libcameraservice.so和一个与 Camera硬件相关的底层库。其中libandroid_runtime.so、libui.so是与Android系统构架相关的不需要对其进行修 改, libcameraservice.so和Camera硬件相关的底层库则是和硬件设备相关联的,而Canera硬件相关的底层库实际上就是设备的 Linux驱动,所以Camera设备的系统集成主要通过移植Camera Linux驱动和修改libcameraservice.so库来完成。

        libcameraservice.so库通过以下规则来构建: 

    1. LOCAL_PATH:= $(call my-dir) 
    2.  
    3.  
    4. Set USE_CAMERA_STUB for non-emulator and non-simulator builds, if you want 
    5.  
    6. # the camera service to use the fake camera.  For emulator or simulator builds, 
    7.  
    8. # we always use the fake camera. 
    9.  
    10. ifeq ($(USE_CAMERA_STUB),) 
    11.  
    12. USE_CAMERA_STUB:=false 
    13.  
    14. ifneq ($(filter sooner generic sim,$(TARGET_DEVICE)),) 
    15.  
    16. USE_CAMERA_STUB:=true 
    17.  
    18. endif #libcamerastub 
    19.  
    20. endif ifeq ($(USE_CAMERA_STUB),true) 
    21.  
    22.  
    23. # libcamerastub 
    24.  
    25.  
    26. include $(CLEAR_VARS) 
    27.  
    28. LOCAL_SRC_FILES:=                
    29.  
    30.     CameraHardwareStub.cpp       
    31.  
    32.     FakeCamera.cpp 
    33.  
    34. LOCAL_MODULE:= libcamerastub 
    35.  
    36. LOCAL_SHARED_LIBRARIES:= libui 
    37.  
    38. include $(BUILD_STATIC_LIBRARY) 
    39.  
    40. endif # USE_CAMERA_STUB 
    41.  
    42.  
    43. # libcameraservice 
    44.  
    45.  
    46. include $(CLEAR_VARS) 
    47.  
    48. LOCAL_SRC_FILES:=                
    49.  
    50.     CameraService.cpp 
    51.  
    52. LOCAL_SHARED_LIBRARIES:=  
    53.  
    54.     libui  
    55.  
    56.     libutils  
    57.  
    58.     libcutils  
    59.  
    60.     libmedia 
    61.  
    62. LOCAL_MODULE:= libcameraservice 
    63.  
    64. LOCAL_CFLAGS+=-DLOG_TAG="CameraService" 
    65.  
    66. ifeq ($(USE_CAMERA_STUB), true) 
    67.  
    68. LOCAL_STATIC_LIBRARIES += libcamerastub 
    69.  
    70. LOCAL_CFLAGS += -include CameraHardwareStub.h 
    71.  
    72. else 
    73.  
    74. LOCAL_SHARED_LIBRARIES += libcamera 
    75.  
    76. endif 
    77.  
    78. include $(BUILD_SHARED_LIBRARY) 

         在上面的构建规则中可以看到使用了宏USE_CAMERA_STUB决定 是否使用真的Camera,如果宏为真,则使用 CameraHardwareStub.cpp和FakeCamera.cpp构造一个假的Camera,如果为假则使用 libcamera来构造一个实际上的Camera服务。

        在CameraHardwareStub.cpp中定义了CameraHardwareStub类,它继承并实现了抽象类 CameraHardwareInterface中定义的真正操作Camera设备的所有的纯虚函数。通过 openCameraHardware()将返回一个CameraHardwareInterface类的对象,但由于 CameraHardwareInterface类是抽象类所以它并不能创建对象,而它的派生类CameraHardwareStub完全实现了其父类的 纯虚函数所以openCameraHardware()返回一个指向派生类对象的基类指针用于底层设备的操作。由于CameraHardwareStub 类定义的函数是去操作一个假的Camera,故通过openCameraHardware返回的指针主要用于仿真环境对Camera的模拟操作,要想通过 openCameraHardware返回的指针操作真正的硬件设备则需完成以下步骤:

    1.    将CameraHardwareInterface类中的所有纯虚函数的声明改为虚函数的声明(即去掉虚函数声明后的“= 0” ); 

    1. class CameraHardwareInterface : public virtual RefBase { 
    2.  
    3. public: 
    4.  
    5.     virtual ~CameraHardwareInterface() { } 
    6.  
    7.     virtual sp         getPreviewHeap() const; 
    8.  
    9.     virtual sp         getRawHeap() const; 
    10.  
    11.     virtual status_t    startPreview(preview_callback cb, void* user); 
    12.  
    13.     virtual bool useOverlay() {return false;} 
    14.  
    15.     virtual status_t setOverlay(const sp &overlay) {return BAD_VALUE;} 
    16.  
    17.     virtual void        stopPreview(); 
    18.  
    19.     virtual bool        previewEnabled(); 
    20.  
    21.     virtual status_t    startRecording(recording_callback cb, void* user); 
    22.  
    23.     virtual void        stopRecording(); 
    24.  
    25.     virtual bool        recordingEnabled(); 
    26.  
    27.     virtual void        releaseRecordingFrame(const sp& mem); 
    28.  
    29.     virtual status_t    autoFocus(autofocus_callback, 
    30.  
    31.                                   void* user); 
    32.  
    33.   
    34.  
    35.     virtual status_t    takePicture(shutter_callback, 
    36.  
    37.                                     raw_callback, 
    38.  
    39.                                     jpeg_callback, 
    40.  
    41.                                     void* user); 
    42.  
    43.     virtual status_t    cancelPicture(bool cancel_shutter, 
    44.  
    45.                                       bool cancel_raw, 
    46.  
    47.                                       bool cancel_jpeg); 
    48.  
    49.     virtual status_t    setParameters(const CameraParameters& params); 
    50.  
    51.     virtual CameraParameters  getParameters() const; 
    52.  
    53.     virtual void release(); 
    54.  
    55.     virtual status_t dump(int fd, const Vector& args) const ; 
    56.  
    57. }; 

    2.    编写一个源文件去定义CameraHardwareInterface类中声明的所有虚函数,并实现openCameraHardware()函数让该函数返回一个CameraHardwareInterface类对象的指针;例如: 

    1. extern "C" sp openCameraHardware() 
    2.  
    3.  
    4.     CameraHardwareInterface realCamera; 
    5.  
    6.     return &realCamera; 
    7.  

    3.    仿照其他.mk文件编写Android.mk文件用于生成一个包含步骤2编写的源文件和其他相关文件的libcamera.so文件;例如 

    1. LOCAL_PATH := $(call my-dir) 
    2.  
    3. include $(CLEAR_VARS) 
    4.  
    5. LOCAL_MODULE := libcamera 
    6.  
    7. LOCAL_SHARED_LIBRARIES :=  
    8.  
    9.     libutils  
    10.  
    11.     librpc  
    12.  
    13.     liblog 
    14.  
    15. LOCAL_SRC_FILES += MyCameraHardware.cpp 
    16.  
    17. LOCAL_CFLAGS += 
    18.  
    19. LOCAL_C_INCLUDES += 
    20.  
    21. LOCAL_STATIC_LIBRARIES +=  
    22.  
    23.     libcamera-common  
    24.  
    25.     libclock-rpc  
    26.  
    27.     libcommondefs-rpc 
    28.  
    29. include $(BUILD_SHARED_LIBRARY) 

    4.    将宏USE_CAMERA_STUB改成false,这样生成libcameraservice.so时就会包含libcamera.so库。(注:如果 CameraHardwareInterface类的成员函数并没有直接操作硬件而是调用Camera的linux驱动来间接对硬件操作,那么包含这样的 CameraHardwareInterface类的libcamera.so库就相当于一个HAL)

          上面左图中libcamera.so库直接操作Camera设备,这样相对于右图来说就相当于libcamera.so库包含了Camera驱动,而右图 则将驱动从库中分离出来并形成一层HAL这样做的好处是:移植不同型号或不同厂商的同类设备时只需修改HAL中很少代码即可。

  • 相关阅读:
    Java 密钥库 证书 公钥 私钥
    Theos小例子
    armbian禁用zram
    常见JS混淆器和特征
    命令行工具收藏
    python中生成器的两段代码
    把mysql数据库从windows迁移到linux系统上的方法
    【转载】使用Flink低级处理函数ProcessFunction
    spark读取压缩文件
    SpringBoot系列——validation参数校验
  • 原文地址:https://www.cnblogs.com/jukan/p/6678222.html
Copyright © 2020-2023  润新知