Android 上Camera分析

一.Camera构架分析

Android的Camera包含取景(preview)和拍摄照片(take picture)的功能。目前Android发布版的Camera程序的架构分成 客户端 和 服务器 两个部分,它们 建立在Android的进程间通讯Binder的结构上。Android中Camera模块同样遵循Andorid的框架,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中的功能,进程间通讯的部分对上层程序不可见。


Android的Camera子系统提供一个 拍照和录制视频 的框架。

libui.so它将Camera的上层应用 与 Application Framework 、用户库 串接起来,而正是这个 用户库来与Camera的硬件层通信,从而实现操作camera硬件。

image

Android Camera的代码结构:


Android的Camera代码主要在以下的目录中:
Camera的JAVA部分
packages/apps/Camera/src/com/android/camera/Camera.java
。其中Camera.java是主要实现的文件。这部分内容编译成为目标是Camera.apk
com.android.camera这个包,几个主要的类文件如下:
PhotoViewer:GalleryPicker.java(所有图片集)--->ImageGallery.java(某个Folder下图片列表)--->ViewImage.java(看某张具体图片)
VideoPlayer:GalleryPicker.java(所有视频集) --->MovieView.java(看某一个视频)
Camera:Camera.java(Camera取景及拍照)
VideoCamera:VideoCamera.java(VideoCamera取景及摄像)

Camera的framework供上层应用调用的部分

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

这部分目标framework.jar

Camera的JNI部分
frameworks/base/core/jni/android_hardware_Camera.cpp

这部分内容编译成为目标libandroid_runtime.so。

Camera UI库部分
frameworks/base/libs/ui/camera
这部分的内容被编译成库libui.so。

Camera服务部分
frameworks/base/camera/libcameraservice/
这部分内容被编译成库libcameraservice.so。

Camera HAL层部分
hardware/msm7k/libcamera

vendor/qcom/android-open/libcamera2
为了实现一个具体功能的Camera,在HAL层需要一个硬件相关的Camera库(例如通过调用video for linux驱动程序和Jpeg编码程序实现或者直接用各个chip厂商实现的私有库来实现,比如Qualcomm实现的libcamera.so和libqcamera.so),实现CameraHardwareInterface规定的接口,来调用相关的库,驱动相关的driver,实现对camera硬件的操作。这个库将被Camera的服务库libcameraservice.so调用


从框架结构上来看,源码中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定义如下:
复制到剪贴板  Java代码

    static JNINativeMethod camMethods[] = { { "native_setup", "(Ljava/lang/Object;)V", (void*)android_hardware_Camera_native_setup }, { "native_release", "()V", (void*)android_hardware_Camera_release }, { "setPreviewDisplay", "(Landroid/view/Surface;)V", (void *)android_hardware_Camera_setPreviewDisplay }, { "startPreview", "()V", (void *)android_hardware_Camera_startPreview }, { "stopPreview", "()V", (void *)android_hardware_Camera_stopPreview }, { "previewEnabled", "()Z", (void *)android_hardware_Camera_previewEnabled }, { "setHasPreviewCallback", "(ZZ)V", (void *)android_hardware_Camera_setHasPreviewCallback }, { "native_autoFocus", "()V", (void *)android_hardware_Camera_autoFocus }, { "native_takePicture", "()V", (void *)android_hardware_Camera_takePicture }, { "native_setParameters", "(Ljava/lang/String;)V", (void *)android_hardware_Camera_setParameters }, { "native_getParameters", "()Ljava/lang/String;", (void *)android_hardware_Camera_getParameters }, { "reconnect", "()V", (void*)android_hardware_Camera_reconnect }, { "lock", "()I", (void*)android_hardware_Camera_lock }, { "unlock", "()I", (void*)android_hardware_Camera_unlock }, };  

 JNINativeMethod的第一个成员是一个字符串,表示了JAVA本地调用方法的名称,这个名称是在JAVA程序中调用的名称;第二个成员也是一个字符串,表示JAVA本地调用方法的参数和返回值;第三个成员是JAVA本地调用方法对应的C语言函数。 ②.Mediaserver proces:进程注册了以下几个server: AudioFlinger、 MediaPlayerServer、CameraService.
复制到剪贴板  Java代码

    int main(int argc, char** argv) { sp proc(ProcessState::self()); sp sm = defaultServiceManager(); LOGI("ServiceManager: %p", sm.get()); AudioFlinger::instantiate(); MediaPlayerService::instantiate(); CameraService::instantiate(); ProcessState::self()->startThreadPool(); IPCThreadState::self()->joinThreadPool(); }  

 当向ServiceManager注册了CameraService服务后就可以响应client的请求了 2.client端向service发送请求 ①.在java应用层调用onCreate()函数得到一个上层的Camera对象
复制到剪贴板  Java代码

    public void onCreate(Bundle icicle) { super.onCreate(icicle); Thread openCameraThread = new Thread( new Runnable() { public void run() { mCameraDevice = android.hardware.Camera.open(); } } ); ……………………… }  

 ②.通过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库通过以下规则来构建
复制到剪贴板  Java代码

    LOCAL_PATH:= $(call my-dir) # # Set USE_CAMERA_STUB for non-emulator and non-simulator builds, if you want # the camera service to use the fake camera. For emulator or simulator builds, # we always use the fake camera. ifeq ($(USE_CAMERA_STUB),) USE_CAMERA_STUB:=false ifneq ($(filter sooner generic sim,$(TARGET_DEVICE)),) USE_CAMERA_STUB:=true endif #libcamerastub endif ifeq ($(USE_CAMERA_STUB),true) # # libcamerastub # include $(CLEAR_VARS) LOCAL_SRC_FILES:= \ CameraHardwareStub.cpp \ FakeCamera.cpp LOCAL_MODULE:= libcamerastub LOCAL_SHARED_LIBRARIES:= libui include $(BUILD_STATIC_LIBRARY) endif # USE_CAMERA_STUB # # libcameraservice # include $(CLEAR_VARS) LOCAL_SRC_FILES:= \ CameraService.cpp LOCAL_SHARED_LIBRARIES:= \ libui \ libutils \ libcutils \ libmedia LOCAL_MODULE:= libcameraservice LOCAL_CFLAGS+=-DLOG_TAG=\"CameraService\" ifeq ($(USE_CAMERA_STUB), true) LOCAL_STATIC_LIBRARIES += libcamerastub LOCAL_CFLAGS += -include CameraHardwareStub.h else LOCAL_SHARED_LIBRARIES += libcamera endif 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” ); class CameraHardwareInterface :
复制到剪贴板  Java代码

    public virtual RefBase { public: virtual ~CameraHardwareInterface() { } virtual sp getPreviewHeap() const; virtual sp getRawHeap() const; virtual status_t startPreview(preview_callback cb, void* user); virtual bool useOverlay() {return false;} virtual status_t setOverlay(const sp &overlay) {return BAD_VALUE;} virtual void stopPreview(); virtual bool previewEnabled(); virtual status_t startRecording(recording_callback cb, void* user); virtual void stopRecording(); virtual bool recordingEnabled(); virtual void releaseRecordingFrame(const sp& mem); virtual status_t autoFocus(autofocus_callback, void* user); virtual status_t takePicture(shutter_callback, raw_callback, jpeg_callback, void* user); virtual status_t cancelPicture(bool cancel_shutter, bool cancel_raw, bool cancel_jpeg); virtual status_t setParameters(const CameraParameters& params); virtual CameraParameters getParameters() const; virtual void release(); virtual status_t dump(int fd, const Vector& args) const ; };   

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

3. 仿照其他.mk文件编写Android.mk文件用于生成一个包含步骤2编写的源文件和其他相关文件的libcamera.so文件;例如
复制到剪贴板  Java代码

    LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := libcamera LOCAL_SHARED_LIBRARIES := \ libutils \ librpc \ liblog LOCAL_SRC_FILES += MyCameraHardware.cpp LOCAL_CFLAGS += LOCAL_C_INCLUDES += LOCAL_STATIC_LIBRARIES += \ libcamera-common \ libclock-rpc \ libcommondefs-rpc 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中很少代码即可。
  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值