Android 上Camera分析

农村四月闲人少,勤学苦攻把名扬。这篇文章主要讲述Android 上Camera分析相关的知识,希望能为你提供帮助。
http://blog.csdn.net/u010503912/article/details/52315721
一.Camera构架分析
android 的Camera包含取景(preview)和拍摄照片(take picture)的功能。目前Android发布版的Camera程序虽然功能比较简单,但是其程序的架构分成客户端和服务器两个部分,它们建立在 Android的进程间通讯Binder的结构上。Android中Camera模块同样遵循Andorid的框架,如下图所示

Android 上Camera分析

文章图片


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

文章图片


在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));
【Android 上Camera分析】              其中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中很少代码即可。









    推荐阅读