camera驱动交流(高通平台)
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
然后代码通过 C/S 架构走向
Then 进入HAL层 /hardware/qcom/camera/QualcommCamera2.cpp
/hardware/qcom/camera/QcameraHWI.cpp
status_t QCameraHardwareInterface::autoFocus() { …
Kernel 层初始化时,主要是初始化 I2C 接口、配置参数、check sensor ID
Open 过程(7X):
Open 过程(8X): JAVA层是一样的,不一样的在于HAL层的OPEN方法从 /hardware/qcom/camera/ QualcommCamera2.cpp HAL_openCameraHardware(cameraId) 改为了 new QCameraHardwareInterface(cameraId, mode);
我们乊前打开了/dev/video2 的节点,在 msm_open 函数中最后会去 调 用 msm_send_open_server,这 个函数 会 去唤 醒我 们用 户 空间 的 config 线程。
在这个函数中我们需要注意这个timeout的时间限制,它是要求我们 的请求必须在10s内完成,否则config线程就会超时,从而导致相机将 无法使用,只能通过重启来修复。 这个MSM_V4L2_OPEN将会调用到 \vendor\qcom\proprietary\mm-camera\server\core\Qcamsvr. c qcamsvr_process_server_node_event的这个函数会被唤醒 如下:
Then
static int8_t config_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和RAW sensor进行区分,RAW sensor走的是 MCTL_COMPID_STATSPROC,而YUV是通过MCTL_COMPID_SENSOR往
我们接着看看 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又是在什么时候去初始化的呢? 接着往下看:
/* Open camera stack! */ result=cam_ops_open(mCameraId, MM_CAMERA_OP_MODE_NOTUSED); . setPictureSizeTable(); setPreviewSizeTable(); . setVideoSizeTable(); . initDefaultParameters();/* 初始化默认的cam参数*/ }
Camera驱动分析 Auther:zhuyong 2013.3.6
Android 的 Camera 包含取景器(viewfinder)和拍摄、摄像的功 能。目前Android 发布版的Camera 程序虽然功能比较简单,但是其 程序的架构分成客户端和服务器两个部分,它们建立在Android 的迚 程间通讯Binder 的结构上。 1 Framework 层分析 Camera 的代码主要在以下的目录中: 1.1 Camera 的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 服务部分:
2.3 相机的控制过程(以自动对焦为例):
Then autofocus 将调用
由于 Camera.java 实现了 FocusManager.Listener 接口,所以 mListener.autoFocus()的实现在 Camera.java 中
随后代码对焦走向 framework 层 走向 JNI
frameworks/base/services/camera/libcameraservice/ 这部分内容被编译成库libcameraservice.so。 为了实现一个具体功能的Camera,在最底层还需要一个硬件相关的 Camer 驱动库(例如通过调用video for linux 驱动程序和Jpeg 编码 程序实现)。这个库将被Camera 的服务 库libcameraservice.so 调用。 1.2 Camera 的各个库乊间的结构可以用下图的表示:
在Camera 系统的各个库中,libui.so 位于核心的位置,它对上层的 提供的接口主要是 Camera 类,类libandroid_runtime.so 通过调用Camera 类提供对 JAVA 的接口,并且实现了android.hardware.camera 类。 libcameraservice.so 是Camera 的服务器程序,它通过继承libui.so
在打开这个节点后,随后用户空间就会利用这个节点去完成sensor的初始化了 我们看下面
sensor_client_open 这个函数首先会去初始化具体的摄像头,如下:
rc = ioctl(sctrl->sfd, MSM_CAM_IOCTL_GET_SENSOR_INFO, &sinfo); 首先在sensor_init函数中,会先去sensor的信息(包括sensor的类型yuv or raw, af enable ? 闪光灯类型,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);
的类实现服务 器的功能,并且与libui.so 中的另外一部分内容则通过迚程间通讯(即 Binder 机制)的方式迚行通讯。 libandroid_runtime.so 和libui.so 两个库是公用的,其中除了Camera 还有其他方面的功能。 Camera 主要的头文件有以下几个: ICameraClient.h Camera.h ICamera.h ICameraService.h CameraHardwareInterface.h 整个Camera 在运行的时候,可以大致上分成Client 和Server 两个 部分,它们分别在两个迚程中运行,它们乊间使用Binder 机制实现 迚程间通讯。这样在客户端调用接口,功能则在服务器中实现,但是 在客户端中调用就好像直接调用服务器中的功能,迚程间通讯的部分 对上层程序不可见。 从框架结构上来看,ICameraService.h、ICameraClient.h 和 ICamera.h 三个类定义了camera 的接口和架构, ICameraService.cpp 和Camera.cpp 两个文件用于Camera 架构的实现,Camera 的具体功能在下层调用硬件相关的接口来实现。 2 驱动层分析 Camera 驱动层可分为两部分。一是kernel 层,负责模块的初始化,
我接着一步步往下走 /hardware/qcom/camera/QCameraHWI.cpp 调用对象QCameraHardwareInterface的构造函数 QCameraHardwareInterface:: QCameraHardwareInterface(int cameraId, int mode) {
控制和数据流。一是vendor层,它是framework 与底层驱动的接口。 /hardware/qcom/camera QCameraHWI.cpp QCameraHWI.h /vendቤተ መጻሕፍቲ ባይዱr/qcom/proprietary/mm-camera/ *.* /kernel/drivers/media/video/msm/ *.* /arch/arm/mach-msm/board-i370-camera.c 2.2 初始化的过程 Vendor 层在初始化时会获取sensor 一些基本信息。比如sensor 的 名称,是否支持3D 等。 同时把修改后的信息写回到用户空间。
我们可以看到用户空间在这个地方已经收到了我们内核的请求了,这部分代码接着 往下走会去创建我们的 config 线程,如下:
那么我们/dev/config0的节点在什么地方打开的呢?往下看 在cam_mctl_thread线程中有个函数mctl_init,这个函数会完成节点的打开 \vendor\qcom\proprietary\mm-camera\server\core\mctl\mctl.c 中的函数 mctl_init.
下设置参数的,MCTL_COMPID_STATSPROC涉及较多的VFE操作比较复杂, 我们此次只针对YUV的sensor进行讲解。Let’s go SENSOR_SET_AUTO_FOCUS再通过sensor_client_set_params这个接口 调度到 \vendor\qcom\proprietary\mm-camera\server\hardware\sensor\o v5640\ ov5640_u.c
这条语句就会去加载我们的库文件了(仅仅针对RAW sensor) 我们看看s5k4e1_process_start这个函数: int8_t s5k4e1_process_start(void *ctrl) { sensor_util_get_output_info(sctrl);这条语句调用到内核获取长宽等 … sensor_util_config(sctrl);这条语句调用到内核完成初始化 … } 整个open过程大致如上面。
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_ctrlcm d.c
然后调用
/hardware/qcom/camera/mm-camera-interface/QCameraHWI.cpp
这个将调用系统调用open的方法,打开设备节点dev/video0(后置相 机),/dev/video2(前置相机),这个顺序是和内核在启动的是和 video的注册顺序相关的。 那么这个节点是在哪儿注册的呢? /kernel/drivers/media/video/msm/msm.c msm_cam_dev_init 这个函数会对节点注册
Then 进入HAL层 /hardware/qcom/camera/QualcommCamera2.cpp
/hardware/qcom/camera/QcameraHWI.cpp
status_t QCameraHardwareInterface::autoFocus() { …
Kernel 层初始化时,主要是初始化 I2C 接口、配置参数、check sensor ID
Open 过程(7X):
Open 过程(8X): JAVA层是一样的,不一样的在于HAL层的OPEN方法从 /hardware/qcom/camera/ QualcommCamera2.cpp HAL_openCameraHardware(cameraId) 改为了 new QCameraHardwareInterface(cameraId, mode);
我们乊前打开了/dev/video2 的节点,在 msm_open 函数中最后会去 调 用 msm_send_open_server,这 个函数 会 去唤 醒我 们用 户 空间 的 config 线程。
在这个函数中我们需要注意这个timeout的时间限制,它是要求我们 的请求必须在10s内完成,否则config线程就会超时,从而导致相机将 无法使用,只能通过重启来修复。 这个MSM_V4L2_OPEN将会调用到 \vendor\qcom\proprietary\mm-camera\server\core\Qcamsvr. c qcamsvr_process_server_node_event的这个函数会被唤醒 如下:
Then
static int8_t config_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和RAW sensor进行区分,RAW sensor走的是 MCTL_COMPID_STATSPROC,而YUV是通过MCTL_COMPID_SENSOR往
我们接着看看 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又是在什么时候去初始化的呢? 接着往下看:
/* Open camera stack! */ result=cam_ops_open(mCameraId, MM_CAMERA_OP_MODE_NOTUSED); . setPictureSizeTable(); setPreviewSizeTable(); . setVideoSizeTable(); . initDefaultParameters();/* 初始化默认的cam参数*/ }
Camera驱动分析 Auther:zhuyong 2013.3.6
Android 的 Camera 包含取景器(viewfinder)和拍摄、摄像的功 能。目前Android 发布版的Camera 程序虽然功能比较简单,但是其 程序的架构分成客户端和服务器两个部分,它们建立在Android 的迚 程间通讯Binder 的结构上。 1 Framework 层分析 Camera 的代码主要在以下的目录中: 1.1 Camera 的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 服务部分:
2.3 相机的控制过程(以自动对焦为例):
Then autofocus 将调用
由于 Camera.java 实现了 FocusManager.Listener 接口,所以 mListener.autoFocus()的实现在 Camera.java 中
随后代码对焦走向 framework 层 走向 JNI
frameworks/base/services/camera/libcameraservice/ 这部分内容被编译成库libcameraservice.so。 为了实现一个具体功能的Camera,在最底层还需要一个硬件相关的 Camer 驱动库(例如通过调用video for linux 驱动程序和Jpeg 编码 程序实现)。这个库将被Camera 的服务 库libcameraservice.so 调用。 1.2 Camera 的各个库乊间的结构可以用下图的表示:
在Camera 系统的各个库中,libui.so 位于核心的位置,它对上层的 提供的接口主要是 Camera 类,类libandroid_runtime.so 通过调用Camera 类提供对 JAVA 的接口,并且实现了android.hardware.camera 类。 libcameraservice.so 是Camera 的服务器程序,它通过继承libui.so
在打开这个节点后,随后用户空间就会利用这个节点去完成sensor的初始化了 我们看下面
sensor_client_open 这个函数首先会去初始化具体的摄像头,如下:
rc = ioctl(sctrl->sfd, MSM_CAM_IOCTL_GET_SENSOR_INFO, &sinfo); 首先在sensor_init函数中,会先去sensor的信息(包括sensor的类型yuv or raw, af enable ? 闪光灯类型,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);
的类实现服务 器的功能,并且与libui.so 中的另外一部分内容则通过迚程间通讯(即 Binder 机制)的方式迚行通讯。 libandroid_runtime.so 和libui.so 两个库是公用的,其中除了Camera 还有其他方面的功能。 Camera 主要的头文件有以下几个: ICameraClient.h Camera.h ICamera.h ICameraService.h CameraHardwareInterface.h 整个Camera 在运行的时候,可以大致上分成Client 和Server 两个 部分,它们分别在两个迚程中运行,它们乊间使用Binder 机制实现 迚程间通讯。这样在客户端调用接口,功能则在服务器中实现,但是 在客户端中调用就好像直接调用服务器中的功能,迚程间通讯的部分 对上层程序不可见。 从框架结构上来看,ICameraService.h、ICameraClient.h 和 ICamera.h 三个类定义了camera 的接口和架构, ICameraService.cpp 和Camera.cpp 两个文件用于Camera 架构的实现,Camera 的具体功能在下层调用硬件相关的接口来实现。 2 驱动层分析 Camera 驱动层可分为两部分。一是kernel 层,负责模块的初始化,
我接着一步步往下走 /hardware/qcom/camera/QCameraHWI.cpp 调用对象QCameraHardwareInterface的构造函数 QCameraHardwareInterface:: QCameraHardwareInterface(int cameraId, int mode) {
控制和数据流。一是vendor层,它是framework 与底层驱动的接口。 /hardware/qcom/camera QCameraHWI.cpp QCameraHWI.h /vendቤተ መጻሕፍቲ ባይዱr/qcom/proprietary/mm-camera/ *.* /kernel/drivers/media/video/msm/ *.* /arch/arm/mach-msm/board-i370-camera.c 2.2 初始化的过程 Vendor 层在初始化时会获取sensor 一些基本信息。比如sensor 的 名称,是否支持3D 等。 同时把修改后的信息写回到用户空间。
我们可以看到用户空间在这个地方已经收到了我们内核的请求了,这部分代码接着 往下走会去创建我们的 config 线程,如下:
那么我们/dev/config0的节点在什么地方打开的呢?往下看 在cam_mctl_thread线程中有个函数mctl_init,这个函数会完成节点的打开 \vendor\qcom\proprietary\mm-camera\server\core\mctl\mctl.c 中的函数 mctl_init.
下设置参数的,MCTL_COMPID_STATSPROC涉及较多的VFE操作比较复杂, 我们此次只针对YUV的sensor进行讲解。Let’s go SENSOR_SET_AUTO_FOCUS再通过sensor_client_set_params这个接口 调度到 \vendor\qcom\proprietary\mm-camera\server\hardware\sensor\o v5640\ ov5640_u.c
这条语句就会去加载我们的库文件了(仅仅针对RAW sensor) 我们看看s5k4e1_process_start这个函数: int8_t s5k4e1_process_start(void *ctrl) { sensor_util_get_output_info(sctrl);这条语句调用到内核获取长宽等 … sensor_util_config(sctrl);这条语句调用到内核完成初始化 … } 整个open过程大致如上面。
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_ctrlcm d.c
然后调用
/hardware/qcom/camera/mm-camera-interface/QCameraHWI.cpp
这个将调用系统调用open的方法,打开设备节点dev/video0(后置相 机),/dev/video2(前置相机),这个顺序是和内核在启动的是和 video的注册顺序相关的。 那么这个节点是在哪儿注册的呢? /kernel/drivers/media/video/msm/msm.c msm_cam_dev_init 这个函数会对节点注册