mm-camera 概述
1. 流程
高通将camera的所有功能划分为不同的模块,让模块自己来决定自己的事情(高内聚,低耦合),模块需要有统一的接口和格式。模块中有端口,通过端口把模块连接起来,又把模块挂在总线上。每一个端口的连接就是一个流,把这些流用pipeline来管理。
每次启动一个camera就创建一个sesion,由这个session来管理此camera的一切事物。对于每一个seeion,模块是共享的,它可以是camera的硬件资源也可以是其它资源(如一些软件算法等资源)
2.那么如何来定义这个模块的结构呢?
1.端口——端口属于模块,如果这个模块只有source端口,那么它就是一个src模块;如果只有sink端口就是sink模块,如果都有就是中间模块。没有端口的模块是不能连接到流中的,但他可以完成一些其他的功能,比如接收引擎的设置,报告事件到bus等。连接到流中的端口,也就是说流事件(set/get)主要通过端口来处理。而来自于引擎的(set/get)通过模块来处理,当然端口也可以把事件交给模块来处理。模块内部的端口可以通过模块来建立关系,也可以建立内部的连接,端口有关get/set process。
2.模块线程——每个模块可以有一个线程来处理模块的事情。一个线程对应一个队列,线程就是从队列中取出数据处理,然后应答回去。
3.总线回调——挡一个模块向总线注册时,总线向其提供一个回调函数,当模块有事件发生时,调用这个函数向bus发消息,然后总线把这个消息提交给管道,管道把这个消息顺着流发下去。
4.模块的get、set以及process。
3. 框架
pipeline 有两端,一端用于读,一端用于写.
camera 引擎对管道监控.
session 管理camera 引擎
media-controller
|- mct——应该就是camera的引擎 里面包含了引擎、pipiline、bus、module、stream及event等定义及封装。
|- modules —— 这里面就是划分好的一些模块代码,各模块大致功能如下 :
|- sensor —— sensor 的驱动模块(src模块)
|- iface —— ISP interface模块(inter模块)
|- isp —— 主要是ISP的处理,其内部又包含了众多的模块(inter模块)
|- stats —— 一些统计算法模块,如3A,ASD,AFD,IS,GRRO等数据统计的处理(sink模块)
|- pproc —— post process处理(inter模块)
|- imglib —— 主要是图片的一些后端处理,如HDR等(sink模块)
4.架构
mm-camera架构有2个版本 (1)最老的版本是有一个守护进程mm-qcamera-daemon的, 如msm8909平台,后来新版的架构改过,移除了这个守护进程,如msm8937(sdm429)平台。 (2) Android O 中,系统启动时,就会启动 CameraProvider 服务。它将 Camera HAL 从 cameraserver 进程中分离出来,做为一个独立进程 android.hardware.camera.provider@2.4-service 来控制 HAL。这两个进程之间经过 HIDL 机制进行通讯
4.1 media controller线程
MCT线程是camera新架构的引擎部分,负责对管道的监控,由此来完成一个camera设备的控制运转。
-
旧版本 运行在daemon进程空间,由MSM_CAMERA_NEW_SESSION事件来开启,具体开启函数为server_process_hal_event—>mct_controller_new()。 server_process_hal_event() -> mct_controller_new() //“vendor/qcom/proprietary/mm-camera/mm-camera2/server-imaging/server.c” -
新版本 mm_camera_module_open_session() //“hardware/qcom/camera/QCamera2/stack/mm-camera-interface/src/mm_camera_interface.c” shim_ops_tbl->mm_camera_shim_open_session = mct_shimlayer_start_session; //“vendor/qcom/proprietary/mm-camera/mm-camera2/media-controller/mct_shim_layer/mct_shim_layer.c” mct_shimlayer_start_session -> mct_controller_new()
mct_controller_new()
1.mct_pipeline_new()
---->创建一个Pipeline及其bus,并完成pipeline函数的映射。
2.mct_pipeline_start_session()
---->开启camera的所有模块并查询其能力
3.pthread_create(..., mct_controller_thread_run, ...)
---->创建mct线程并开始执行
4.pthread_create(..., mct_bus_handler_thread_run, ...)
---->创建bus处理线程
MCT整个引擎部分主要处理server及bus两类事情,对应前面提到的MCT及bus两个线程。MCT线程主要用来处理来自image server的消息,先pop MCT queue,查看是否有消息,如果有则执行mct_controller_proc_serv_msg_internal()函数来处理。
mct_controller_proc_serv_msg_internal函数用来处理来自image server的消息,并返回类型MCT_PROCESS_RET_SERVER_MSG。这里处理的消息类型主要有SERV_MSG_DS与SERV_MSG_HAL两种,分别在pipline中给出了相应的处理函数
参考: https://blog.csdn.net/u012839187/article/details/87306144
4.2 旧版本mm-qcamera-daemon
mm-qcamera-daemo进程是hal和kernel沟通的桥梁。 mm-qcamera-daemon处于hal与kernel之间,进行hal与kernel的通信, 例如: 应用在发出操作camera的执行命令之后,通过framwork、hal,之后通过ioctl调用到kernel中,kernel则发送消息到daemon中,daemon接到消息之后再发送消息到各个module中,各个module操作实际硬件完成相应操作。
code:“vendor/qcom/proprietary/mm-camera/mm-camera2/server-imaging/server.c”
1 、在Server.c中从mian()函数进入
(1) find server node name and open the node,找到server节点并且打开节点
(2) after open node, initialize modules,打开节点后初始化模块
2、在初始化模块中
(1) 调用server_process_module_sensor_init() 进入server_process.c中的boolean server_process_module_sensor_init(void)函数
(2) 根据modules_list[0]初始化list数组中的模块,初始化模块包含sensor,iface,isp,stats,pproc和imglib
static mct_module_init_name_t modules_list[] = {
{"sensor", module_sensor_init, module_sensor_deinit, NULL},
{"iface", module_iface_init, module_iface_deinit, NULL},
{"isp", module_isp_init, module_isp_deinit, NULL},
{"stats", stats_module_init, stats_module_deinit, NULL},
{"pproc", pproc_module_init, pproc_module_deinit, NULL},
{"imglib", module_imglib_init, module_imglib_deinit, NULL},
};
3、Sensor模块初始化过程
(1) 调用module_sensor_init函数进入module_sensor.c中的mct_module_t *module_sensor_init(const char *name)函数
(2) Create MCT module for sensor,为sensor创建MCT Module
(3) Fill function table in MCT module,填充功能表
(4) Create sensor module control structure that consists of bundle information,创建sensor module control结构体:module_ctrl = malloc(sizeof(module_sensor_ctrl_t))
(5) module_sensor_probe_sensors,sensor识过程,在server_init.c中调用sensor_init_probe函数
1 > 打开设备节点"/dev/video0"
2 > Open sensor_init subdev,找到subdev并且打开
3 > sensor识别过程
(6) module_sensor_find_other_subdev(module_ctrl),找到sensor外的其他子设备,为每一个自设备创建sensor_bundle,并填充设备信息到sensor_bundle
(7) Create ports based on CID info,为sensor_bundle创建端口
(8) intiialize the eeprom,初始化eeprom,module_sensor_init_eeprom
4、iface、isp、stats、pproc和imglib相继进行初始化操作
5、进入主循环来处理来自HAL及MCT的事件及消息,处理完之后的结果反馈给kernel
mm-qcamera-daemon守护进程具体参考:https://blog.csdn.net/huifeidedabian/article/details/77949419
4.3 新版本 android.hardware.camera.provider@2.4-service
在 Android O 中,系统启动时,就会启动 CameraProvider 服务。它将 Camera HAL 从 cameraserver 进程中分离出来,作为一个独立进程 android.hardware.camera.provider@2.4-service 来控制 HAL。 这两个进程之间通过 HIDL 机制进行通信。
这样的改动源自于 Android O 版本加入的 Treble 机制,它的主要功能(如下图所示)是将 service 与 HAL 隔离,以方便 HAL 部分进行独立升级。这其实和 APP 与 Framework 之间的 Binder 机制类似,通过引入一个进程间通信机制而针对不同层级进行解耦(从 Local call 变成了 Remote call)。
- camera provide 启动
hardware/interfaces/camera/provider/2.4/default/android.hardware.camera.provider@2.4-service.rca
service vendor.camera-provider-2-4 /vendor/bin/hw/android.hardware.camera.provider@2.4-service
interface android.hardware.camera.provider@2.4::ICameraProvider legacy/0
class hal
user cameraserver
group audio camera input drmrpc
ioprio rt 4
capabilities SYS_NICE
task_profiles CameraServiceCapacity HighPerformance
________________________________________
service <name> <pathname> [ <argument> ]*
<option>
<option>
...
<option>服务的修饰符。它们影响init运行服务的方式和时间。
class hal:
该服务属于类hal,在init启动hal类服务的时候,该服务也会被启动,hal类的启动点则在init.rc文件中
user&&group:
以system的用户和组的身份来运行该服务。
hardware/interfaces/camera/provider/2.4/default/service.cpp
int main()
{
ALOGI("Camera provider Service is starting.");
// The camera HAL may communicate to other vendor components via
// /dev/vndbinder
android::ProcessState::initWithDriver("/dev/vndbinder");
return defaultPassthroughServiceImplementation<ICameraProvider>("legacy/0", /*maxThreads*/ 6);
}
* android::ProcessState::initWithDriver :camera HAL 经过 /dev/vndbinder 驱动可与其余模块的HAL进行通讯;
* defaultPassthroughServiceImplementation :建立默认为直通模式(passthrough)的 CameraProvider 服务;
具体参考:https://blog.csdn.net/qq_16775897/article/details/81240600 没有完全理解调用
5.vendor code 流程
hal 层掉用的mm-camera 的接口
*(void **)&mm_camera_shim_module_init =
dlsym(qdaemon_lib, "mct_shimlayer_process_module_init"); //"hardware/qcom/camera/QCamera2/stack/mm-camera-interface/src/mm_camera_interface.c"
mct_shimlayer_process_module_init() //"vendor/qcom/proprietary/mm-camera/mm-camera2/media-controller/mct_shim_layer/mct_shim_layer.c"
现分析mm-camera 入口函数
mm-camera 代码结构,库 libmmcamera2_mct_shimlayer.so 入口函数 mct_shimlayer_process_module_init
mct_shimlayer_process_module_init() //"vendor/qcom/proprietary/mm-camera/mm-camera2/media-controller/mct_shim_layer/mct_shim_layer.c"
mct_util_init_imager_session() //"vendor/qcom/proprietary/mm-camera/mm-camera2/media-controller/mct/tools/mct_util.c"
open(/dev/mediaX) --匹配到 msm_config 为止
MEDIA_IOC_ENUM_ENTITIES //获取实列 entity
open(/dev/v4l2-subdevX)
VIDIOC_MSM_SENSOR_CFG //cfg.cfg.sensor_info.session_id =4 n680x imager_session_id =4
get_config_node_name() //得到video device 的node_name
mct_shimlayer_module_sensor_init() //会找到module_list 中的init_mod
static mct_module_init_name_t modules_list[] = {
{"sensor", module_sensor_init, module_sensor_deinit, NULL},
{"iface", module_iface_init, module_iface_deinit, NULL},
{"isp", module_isp_init, module_isp_deinit, NULL},
{"stats", stats_module_init, stats_module_deinit, NULL},
{"pproc", pproc_module_init, pproc_module_deinit, NULL},
{"imglib", module_imglib_init, module_imglib_deinit, NULL},
};
调用开始后会初始化各个模块,其中就包括sensor模块,sensor初始化入口函数即为module_sensor_init(...)。这个函数将创建sensor模块并返回其指针,另外将创建它的端口,填充一些功能函数等。
module_sensor_init() //"vendor/qcom/proprietary/mm-camera/mm-camera2/media-controller/modules/sensors/module/module_sensor.c"
mct_module_create() //创建MCT module for sensor 之后填充set mode、query mode、start session、stop session及set session data五个接口函数。
struct mct_module_t // 填充mct_module_t 的结构体.
struct module_sensor_ctrl_t //此结构体包含bundle信息,用来构建前面提到的模块树(方便添加、遍历等操作)
s_module->numsinkports = 0; sensor模块是source模块,所以其numsinkports应该设置为0。
eebin_interface_init()
eebin_interface_control()
eebin_get_bin_data()
eebin_read() //读不到
sensor_init_probe() \\"vendor/qcom/proprietary/mm-camera/mm-camera2/media-controller/modules/sensors/module/sensor_init.c"
open(/dev/v4l-subdevX)
sensor_init_eebin_probe() //没有实质意义
eebin_interface_control()
sensor_init_xml_probe()
/vendor/etc/camera/hon660-CT60-XXX
sensor_probe()
sensor_load_library() //加载libmmcamera_X.so
sensor_open_lib()函数指针调用到驱动的参数 ,信息存放在sensor_lib_params_t *sensor_lib_params;
translate_sensor_slave_info //填充struct msm_camera_sensor_slave_info (xml里的配置信息xmlConfig->configPtr,, driver.h 中的电源设置sensor_lib_params)
VIDIOC_MSM_SENSOR_INIT_CFG -> msm_sensor_driver_cmd() //"kernel/msm-4.19/drivers/media/platform/msm/camera_v2/sensor/msm_sensor_init.c"
msm_sensor_driver_probe() //将slave_info传递给kernel "kernel/msm-4.19/drivers/media/platform/msm/camera_v2/sensor/msm_sensor_init.c"
msm_sensor_get_power_settings() //上下电信息
msm_sensor_fill_eeprom_subdevid_by_name // 设置 eeprom_subdev_id 值等于 cell-index
msm_sensor_fill_actuator_subdevid_by_name // actuator_subdev_id
msm_sensor_power_up() //"kernel/msm-4.19/drivers/media/platform/msm/camera_v2/sensor/msm_sensor.c"
msm_camera_power_up() //供电
msm_camera_pinctrl_init() //从链表中找出 "cam_default" 和 "cam_suspend"
//pinctrl-names = "cam_default", "cam_suspend";默认就这么配置,前面代表clk,后面代表reset脚和standby脚,唤醒作用。
msm_camera_request_gpio_table()
gpio_request_one() //设置gpio 对应名称goio_label , 设置输入输出 flag
msm_sensor_check_id() //检查id
msm_sensor_match_id() //匹配i2c 读取的id 与驱动中的匹配
msm_sensor_driver_create_v4l_subdev() //
camera_init_v4l2()
media_device_init() //初始化media_device 的链表
media_device_register() //
media_devnode_register() /**
* 1. 找到设备号 2.初始化media_devnode_fops 3. 添加一个媒体设备,在系统中生成/dev/mediaX节点
* 4.表明已注册 */
device_create_file(&devnode->dev, &dev_attr_model); //./platform/soc/ca00000.qcom,msm-cam/media0/model
media_entity_pads_init() //建立media_entity与media_pad之间的链接:
v4l2_device_register() //
strlcpy(pvdev->vdev->name, "msm-sensor", sizeof(pvdev->vdev->name)); //
/**
/sys/class/video4linux/video3 # cat name
msm-sensor
*/
video_register_device() //
__vilde_register_device()
device_register()
video_register_media_controller()
media_device_register_entity(vdev->v4l2_dev->mdev, &vdev->entity);
v4l2_subdev_init()
media_entity_pads_init()
msm_sd_register()
__msm_sd_register_subdev()
v4l2_device_register_subdev()
media_device_register_entity()
__video_register_device()
module_sensor_find_other_subdev()
LOG_IOCTL(dev_fd, MEDIA_IOC_DEVICE_INFO, &mdev_info, "dev_info"); //kernel/msm-4.4/drivers/media/media-device.c 查看media 子系统https://blog.csdn.net/h_8410435/article/details/125256578?spm=1001.2014.3001.5501
module_sensors_subinit() // 初始化senosr modules , 注意struct sensor_func_tbl_t
static int32_t (*sub_module_init[SUB_MODULE_MAX])(sensor_func_tbl_t *) = {
[SUB_MODULE_SENSOR] = sensor_sub_module_init, //vendor/qcom/proprietary/mm-camera/mm-camera2/media-controller/modules/sensors/module/module_sensor.c {sensor_open,sensor_process}
[SUB_MODULE_CHROMATIX] = chromatix_sub_module_init, //
[SUB_MODULE_ACTUATOR] = actuator_sub_module_init,
[SUB_MODULE_EEPROM] = eeprom_sub_module_init,
[SUB_MODULE_LED_FLASH] = led_flash_sub_module_init,
[SUB_MODULE_CSIPHY] = csiphy_sub_module_init,
[SUB_MODULE_CSIPHY_3D] = csiphy_sub_module_init,
[SUB_MODULE_CSID] = csid_sub_module_init,
[SUB_MODULE_CSID_3D] = csid_sub_module_init,
[SUB_MODULE_OIS] = ois_sub_module_init,
[SUB_MODULE_EXT] = external_sub_module_init,
[SUB_MODULE_IR_LED] = ir_led_sub_module_init,
[SUB_MODULE_IR_CUT] = ir_cut_sub_module_init,
[SUB_MODULE_LASER_LED] = laser_led_sub_module_init
};
port_sensor_create() //创建port基于CID信息,port_sensor_create是port_sensor.c的函数
module_sensor_init_eeprom() // 初始化eeprom
module_sensor_init_chromatix() // 创建chromatix manger
|