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定义如下:
- 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.
- 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对象
- 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库通过以下规则来构建:
- 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 : 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文件;例如
- 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中很少代码即可。
Android 上Camera分析的更多相关文章
- Android上的SQLLite性能分析
也许有人还不知道,Android 是有一些内建的 类库支持 SQL Lite 数据库的操作.他提供了一个很好的方式在 Android 上组织少量的数据.不管怎样,在使用这些类库的时候有一些陷阱是需要注 ...
- Android 的Camera架构介绍
http://java-admin.iteye.com/blog/452464 第一部分 Camera概述Android的Camera包含取景器(viewfinder)和拍摄照片的功能.目前And ...
- Android学习十二---在android上实现图像匹配
一.效果图及功能描述 效果图 点击ShowImg后 点击match,然后点击showmatch,可以不断点击showmatch. 主要功能描述:显示在SD卡上已经存在的图片test.jpg,根据图片在 ...
- 编译可在Android上运行的qemu user mode
前言 本文在Ubuntu 64位系统上对qemu项目进行交叉编译,并且只编译与qemu user mode有关的代码. 下文中的”NDK”若无特殊说明均指”Android NDK”. 下文中”$NDK ...
- Android APP性能分析方法及工具
近期读到<Speed up your app>一文.这是一篇关于Android APP性能分析.优化的文章.在这篇文章中,作者介绍他的APP分析优化规则.使用的工具和方法.我觉得值得大家借 ...
- 【Android】Camera 使用浅析
Camera的简单使用浅析 由于最近工作上用到android.hardware.Camera这个类,于是简单的学习了一些基本用法. 首先注意:Camera这个类在API21以后就不推荐使用了,官方提供 ...
- android上的图片占用内存问题
近日正在把ios程序移植到android上,以前没做过android的程序,于是,想当然地把ios的图片资源放到了android工程的drawable文件夹下,这些图片都是png. 程序界面也很正常. ...
- Android源码分析-全面理解Context
前言 Context在android中的作用不言而喻,当我们访问当前应用的资源,启动一个新的activity的时候都需要提供Context,而这个Context到底是什么呢,这个问题好像很好回答又好像 ...
- Android动画原理分析
最近在Android上做了一些动画效果,网上查了一些资料,有各种各样的使用方式,于是乘热打铁,想具体分析一下动画是如何实现的,Animation, Animator都有哪些区别等等. 首先说Anima ...
随机推荐
- go的sync.Map
sync.Map这个数据结构是线程安全的(基本类型Map结构体在并发读写时会panic严重错误),它填补了Map线程不安全的缺陷,不过最好只在需要的情况下使用.它一般用于并发模型中对同一类map结构体 ...
- Java基础11 对象引用(转载)
对象引用 我们沿用之前定义的Human类,并有一个Test类: public class Test{ public static void main(String[] args){ ...
- AI for AI
1.Li, Ke, and Jitendra Malik. "Learning to optimize." arXiv preprint arXiv:1606.01885 (201 ...
- Xcode中授权普通成员
问题: 在普通用户账户下使用系统的Xcode在编译通过时候会提示” Developer Tools Access“需控制另一进程,需要输入“Developer Tools”组用户名密码才能继续调试 解 ...
- solr-in-action-ch4-Configuring Solr
Solr基本的三个XML配置文件: solr.xml: solr 日志.shard.solrcould等配置 solrconfig.xml: 某个solr core的配置 schema.xml:某个s ...
- What is /dev/null 2>&1?
>> /dev/null redirects standard output (stdout) to /dev/null, which discards it. (The >> ...
- Linq源代码阅读
在 System.Core dotnet451\source\ndp\fx\src\core\system\linq\enumerable.cs Where 和 Select 内 ,把数组和List分 ...
- SlidingMenu官方实例分析2——BaseActivity
本文从BaseActivity说起,因为其他功能页面都继承了这个类. 这里继承了Sliding中的SlidingFragmentActivity,其实也可以继承SlidingActivity, 但是现 ...
- HDU1087 Super Jumping! Jumping! Jumping! 最大连续递增子段
Super Jumping! Jumping! Jumping! Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 ...
- 1、aritcMS-环境搭建-设置布局-布局测试
在开始项目之前,准备开发工具等请参考easyUI章节. 首先.在获取broPHP框架的时候(可以在网上下载).在brophp文件夹同级目录下新建admin.php,以及index.php admin. ...