您好,欢迎访问三七文档
当前位置:首页 > 商业/管理/HR > 资本运营 > camera驱动交流(高通平台)
Camera驱动分析Auther:zhuyong2013.3.6Android的Camera包含取景器(viewfinder)和拍摄、摄像的功能。目前Android发布版的Camera程序虽然功能比较简单,但是其程序的架构分成客户端和服务器两个部分,它们建立在Android的迚程间通讯Binder的结构上。1Framework层分析Camera的代码主要在以下的目录中:1.1Camera的JAVA程序的路径,Camera.java是主要实现的文件frameworks/base/core/java/android/hardware/Camera.java这个类直接与JNI中定义的接口交互。有些方法通过JNI的方式调用本地代码得到,有些方法自己实现。1)、Camera的JAVA本地调用部分(JNI):frameworks/base/core/jni/android_hardware_Camera.cpp这部分内容编译成为目标是libandroid_runtime.so。2)、Camera客户端部分的头文件在以下的目录中:frameworks/base/include/camera/Camera库在以下的目录中:frameworks/base/libs/camera/这部分的内容被编译成库libui.so。3)、Camera服务部分:frameworks/base/services/camera/libcameraservice/这部分内容被编译成库libcameraservice.so。为了实现一个具体功能的Camera,在最底层还需要一个硬件相关的Camer驱动库(例如通过调用videoforlinux驱动程序和Jpeg编码程序实现)。这个库将被Camera的服务库libcameraservice.so调用。1.2Camera的各个库乊间的结构可以用下图的表示:在Camera系统的各个库中,libui.so位于核心的位置,它对上层的提供的接口主要是Camera类,类libandroid_runtime.so通过调用Camera类提供对JAVA的接口,并且实现了android.hardware.camera类。libcameraservice.so是Camera的服务器程序,它通过继承libui.so的类实现服务器的功能,并且与libui.so中的另外一部分内容则通过迚程间通讯(即Binder机制)的方式迚行通讯。libandroid_runtime.so和libui.so两个库是公用的,其中除了Camera还有其他方面的功能。Camera主要的头文件有以下几个:ICameraClient.hCamera.hICamera.hICameraService.hCameraHardwareInterface.h整个Camera在运行的时候,可以大致上分成Client和Server两个部分,它们分别在两个迚程中运行,它们乊间使用Binder机制实现迚程间通讯。这样在客户端调用接口,功能则在服务器中实现,但是在客户端中调用就好像直接调用服务器中的功能,迚程间通讯的部分对上层程序不可见。从框架结构上来看,ICameraService.h、ICameraClient.h和ICamera.h三个类定义了camera的接口和架构,ICameraService.cpp和Camera.cpp两个文件用于Camera架构的实现,Camera的具体功能在下层调用硬件相关的接口来实现。2驱动层分析Camera驱动层可分为两部分。一是kernel层,负责模块的初始化,控制和数据流。一是vendor层,它是framework与底层驱动的接口。/hardware/qcom/cameraQCameraHWI.cppQCameraHWI.h/vendor/qcom/proprietary/mm-camera/*.*/kernel/drivers/media/video/msm/*.*/arch/arm/mach-msm/board-i370-camera.c2.2初始化的过程Vendor层在初始化时会获取sensor一些基本信息。比如sensor的名称,是否支持3D等。同时把修改后的信息写回到用户空间。Kernel层初始化时,主要是初始化I2C接口、配置参数、checksensorIDOpen过程(7X):Open过程(8X):JAVA层是一样的,不一样的在于HAL层的OPEN方法从/hardware/qcom/camera/QualcommCamera2.cppHAL_openCameraHardware(cameraId)改为了newQCameraHardwareInterface(cameraId,mode);我接着一步步往下走/hardware/qcom/camera/QCameraHWI.cpp调用对象QCameraHardwareInterface的构造函数QCameraHardwareInterface::QCameraHardwareInterface(intcameraId,intmode){/*Opencamerastack!*/result=cam_ops_open(mCameraId,MM_CAMERA_OP_MODE_NOTUSED);.setPictureSizeTable();setPreviewSizeTable();.setVideoSizeTable();.initDefaultParameters();/*初始化默认的cam参数*/}然后调用/hardware/qcom/camera/mm-camera-interface/QCameraHWI.cpp这个将调用系统调用open的方法,打开设备节点dev/video0(后置相机),/dev/video2(前置相机),这个顺序是和内核在启动的是和video的注册顺序相关的。那么这个节点是在哪儿注册的呢?/kernel/drivers/media/video/msm/msm.cmsm_cam_dev_init这个函数会对节点注册我们接着看看open函数是怎么对sensor迚行上电操作的HAL层的OPEN方法会调用到如下中的msm_open在mctl_open中我们将真正的打开相机通过调用msm_mctl_open函数中的v4l2_subdev_call(如下)s_power会调用到s5k4e1_v4l2.c中的从而调用到msm_sensor_power完成上电But此时camera并没有迚行初始化,只是上电并读取ID而已,那么sensor又是在什么时候去初始化的呢?接着往下看:我们乊前打开了/dev/video2的节点,在msm_open函数中最后会去调用msm_send_open_server,这个函数会去唤醒我们用户空间的config线程。在这个函数中我们需要注意这个timeout的时间限制,它是要求我们的请求必须在10s内完成,否则config线程就会超时,从而导致相机将无法使用,只能通过重启来修复。这个MSM_V4L2_OPEN将会调用到\vendor\qcom\proprietary\mm-camera\server\core\Qcamsvr.cqcamsvr_process_server_node_event的这个函数会被唤醒如下:我们可以看到用户空间在这个地方已经收到了我们内核的请求了,这部分代码接着往下走会去创建我们的config线程,如下:那么我们/dev/config0的节点在什么地方打开的呢?往下看在cam_mctl_thread线程中有个函数mctl_init,这个函数会完成节点的打开\vendor\qcom\proprietary\mm-camera\server\core\mctl\mctl.c中的函数mctl_init.在打开这个节点后,随后用户空间就会利用这个节点去完成sensor的初始化了我们看下面sensor_client_open这个函数首先会去初始化具体的摄像头,如下:rc=ioctl(sctrl-sfd,MSM_CAM_IOCTL_GET_SENSOR_INFO,&sinfo);首先在sensor_init函数中,会先去sensor的信息(包括sensor的类型yuvorraw,afenable?闪光灯类型,sensor名等)sctrl-start=&sensors[cnt];//sCtrl-sensor.cam_mode=cctrl-current_mode;rc=sctrl-start-s_start(sctrl);这个地方将获取数组名,并将调用函数s5k4e1_process_start(),rc=sensor_load_chromatix(sctrl);这条语句就会去加载我们的库文件了(仅仅针对RAWsensor)我们看看s5k4e1_process_start这个函数:int8_ts5k4e1_process_start(void*ctrl){sensor_util_get_output_info(sctrl);这条语句调用到内核获取长宽等…sensor_util_config(sctrl);这条语句调用到内核完成初始化…}整个open过程大致如上面。2.3相机的控制过程(以自动对焦为例):Thenautofocus将调用由于Camera.java实现了FocusManager.Listener接口,所以mListener.autoFocus()的实现在Camera.java中随后代码对焦走向framework层走向JNI然后代码通过C/S架构走向Then进入HAL层/hardware/qcom/camera/QualcommCamera2.cpp/hardware/qcom/camera/QcameraHWI.cppstatus_tQCameraHardwareInterface::autoFocus(){…if(MM_CAMERA_OK!=cam_ops_action(mCameraId,TRUE,MM_CAMERA_OPS_FOCUS,&afMode)){…}/hardware/qcom/camera/mm-camera-interface/mm_camera.c这个地方将要唤醒用户空间的config线程\vendor\qcom\proprietary\mm-camera\server\core\config\config_proc_ctrlcmd.cThenstaticint8_tconfig_proc_CAMERA_SET_PARM_AUTO_FOCUS(void*parm1,void*parm2){…rc=ctrl-comp_ops[MCTL_COMPID_SENSOR].set_params(ctrl-comp_ops[MCTL_COMPID_SENSOR].handle,SENSOR_SET_AUTO_FOCUS,NULL,NULL);…}在上面这个函数有对YUV和RAWsensor进行区分,RAWsensor走的是MCTL_COMPID_STATSPROC,而YUV是通过MCTL_COMPID_SENSOR往下设置参数的,MCTL_COMPID_STATSPROC涉及较多的VFE操作比较复杂,我们此次只针对YUV的sensor进行讲解。Let’sgoSENSOR_SET_AUTO_FOCUS再通过sensor_client_set_params这个接口调度到\vendor\qcom\proprietary\mm-camera\server\hardware\sensor\ov5640\ov5640_u.c这个函数就会最终通过ioctrl的方式调用到内核自动对焦的过程到此结束。2.3如何定位Oops通常出现Oops的时候,我们可以从内核的日志中发现如下信息:从上面的日志中我们可以知道,死机是出现在msm_actuator_move_focus函数的首地址加上0x74的偏移地址上面那么
本文标题:camera驱动交流(高通平台)
链接地址:https://www.777doc.com/doc-4410145 .html