高通capability获取流程以及预览拍照如何判断走驱动的哪个res设置
一capacity的获取流程:
Qcamera2HWI.cpp
int QCamera2HardwareInterface::openCamera()
{
if(NO_ERROR != initCapabilities(mCameraId,mCameraHandle)) {
LOGE("initCapabilities failed.");
rc = UNKNOWN_ERROR;
goto error_exit3;
}
}
int QCamera2HardwareInterface::initCapabilities(uint32_t cameraId,
mm_camera_vtbl_t *cameraHandle)
{
cameraHandle->ops->map_bufs(cameraHandle->camera_handle,
&bufMapList);
cameraHandle->ops->query_capability(cameraHandle->camera_handle);
}
cameraHandle是Mm_camera_interface.c中的g_cam_ctrl.cam_obj[camera_idx]->vtbl; cam_obj->vtbl.ops = &mm_camera_ops;
所以会调用static int32_t mm_camera_intf_query_capability(uint32_t camera_handle)
{
rc = mm_camera_query_capability(my_obj);
}
Mm_camera.c中的int32_t mm_camera_query_capability(mm_camera_obj_t *my_obj)
{
ioctl(my_obj->ctrl_fd, VIDIOC_QUERYCAP, &cap);
}
通过一些复杂的调用,会跑到mct_pipeline.c中的
static boolean mct_pipeline_process_get(struct msm_v4l2_event_data *data,
mct_pipeline_t *pipeline)
{
case MSM_CAMERA_PRIV_QUERY_CAP: {
/* for queryBuf */
ret &= mct_list_traverse(pipeline->modules, mct_pipeline_query_modules,
pipeline);//各个module去获取capability
if (!pipeline->query_buf || !pipeline->modules) {
CLOGE(CAM_MCT_MODULE,
"NULL ptr detected! query_buf = [%p] module list = [%p]",
pipeline->query_buf, pipeline->modules);
ret = FALSE;
} else {
/* fill up HAL's query buffer with query_data
extracted during start_session */
ret = mct_pipeline_populate_query_cap_buffer(pipeline);//填充capability
}
}
}
static boolean mct_pipeline_query_modules(void *data, void *user_data)
{
boolean ret = TRUE;
mct_pipeline_t *pipeline = (mct_pipeline_t *)user_data;
mct_module_t *module = (mct_module_t *)data;
if (!pipeline || !module)
return FALSE;
if (module->query_mod) {
ret = module->query_mod(module, &pipeline->query_data, pipeline->session);
if(FALSE == ret)
CLOGE(CAM_MCT_MODULE, "Query mod failed on %s",
MCT_MODULE_NAME(module));
}
return ret;
}
调用各个module的query_mod来查询capacity,具体在sensor这块,是调用
static boolean module_sensor_query_mod(mct_module_t *module,
void *buf, uint32_t sessionid)
二预览拍照如何判断走驱动的哪个res设置:
Sensor_pick_res.c中的int32_t sensor_pick_resolution(void *sctrl,
sensor_set_res_cfg_t *res_cfg, int32_t *pick_res)函数,res_cfg上层需要的尺寸,会从sensor驱动提供的最小的分辨率开始做各种检测,找到合适的res配置。
for(i = 0; i<SEN_COND_MAX; i++){
((*sensor_pick->pick)[i][sensor_pick->usecase])
}
const check_func_t check_v1 = {
[SEN_COND_FPS] = sensor_pick_check_fps,
[SEN_COND_BOUNDED_FPS] = sensor_pick_check_bounded_fps,
[SEN_COND_ASPR] = sensor_pick_check_aspect_ratio,
[SEN_COND_W] = sensor_pick_check_width,
[SEN_COND_H] = sensor_pick_check_height,
[SEN_COND_CLK] = sensor_pick_check_pixclk,
[SEN_COND_MODE_QUADRA] = sensor_pick_check_mode,
[SEN_COND_MODE_HFR] = sensor_pick_check_mode,
[SEN_COND_MODE_DEF] = sensor_pick_check_mode,
[SEN_COND_MODE_IHDR] = sensor_pick_check_mode,
[SEN_COND_MODE_RHDR] = sensor_pick_check_mode,
[SEN_COND_MODE_MPIX] = sensor_pick_check_mpix,
[SEN_COND_MODE_BEST_RES] = sensor_pick_check_best_res
};
其中res_cfg是需要输出的分辨率,这个分辨率是从哪里来的呢?从hardware层开始描述:
Qcamera2HWI.CPP中streamInfo->dim这个记录了一个stream需要的分辨率,这个分辨率是apk通过setpreviewsize/setpicutresize等设置下来的。
Port_sensor.c中的函数static boolean port_sensor_caps_reserve(mct_port_t *port,
void __attribute__((unused))*peer_caps, void *info)
{
if (stream_info->pp_config.rotation == ROTATE_90 ||
stream_info->pp_config.rotation == ROTATE_270) {
if (bundle_info.s_bundle->max_width< (uint32_t)stream_info->dim.height)
bundle_info.s_bundle->max_width =
(uint32_t)stream_info->dim.height;
if (bundle_info.s_bundle->max_height< (uint32_t)stream_info->dim.width)
bundle_info.s_bundle->max_height =
(uint32_t)stream_info->dim.width;
} else {
if (bundle_info.s_bundle->max_width < (uint32_t)stream_info->dim.width)
bundle_info.s_bundle->max_width =
(uint32_t)stream_info->dim.width;
if (bundle_info.s_bundle->max_height < (uint32_t)stream_info->dim.height)
bundle_info.s_bundle->max_height =
(uint32_t)stream_info->dim.height;
}
}
这个函数非常关键,根据stream传下来的width和height,如果大于bundle的设置,则赋值给bundle。Bundle指向的就是某一颗sensor,可以通过s_bundle->sensor_info->session_id标记。也就是说这个port或者说sensor上有多少个stream(一般拍照预览有CAM_STREAM_TYPE_PREVIEW、CAM_STREAM_TYPE_SNAPSHOT、CAM_STREAM_TYPE_ANALYSIS三个stream),这颗sensor使用的max_width就是这三个stream的最大值
Module_sensor.c
static boolean module_sensor_is_ready_for_stream_on(mct_port_t *port,
mct_event_t *event, sensor_set_res_cfg_t *res_cfg,
module_sensor_bundle_info_t *s_bundle, int32_t bundle_id)
{
res_cfg->width = s_bundle->max_width;
res_cfg->height = s_bundle->max_height;
res_cfg->stream_mask = s_bundle->stream_mask;
}//需要设置的分辨率获取,在下面的函数中使用
boolean module_sensor_stream_on(mct_module_t *module,
mct_event_t *event, module_sensor_bundle_info_t *s_bundle)
{
stream_on_flag = module_sensor_is_ready_for_stream_on(port, event,
&stream_on_cfg, s_bundle, bundle_id);
ret = module_sensor_set_new_resolution_stream_on(module, event, s_bundle,
module_sensor_params, &stream_on_cfg, stream_info);
}
boolean module_sensor_set_new_resolution_stream_on(mct_module_t *module,
mct_event_t *event, module_sensor_bundle_info_t *s_bundle,
module_sensor_params_t* module_sensor_params,
sensor_set_res_cfg_t *stream_on_cfg, mct_stream_info_t* stream_info)
{
retVal = modules_sensor_set_new_resolution(module, event, s_bundle,
module_sensor_params, stream_on_cfg, &is_retry, stream_info);
}
boolean modules_sensor_set_new_resolution(mct_module_t *module,
mct_event_t *event,
module_sensor_bundle_info_t *s_bundle,
module_sensor_params_t *module_sensor_params,
sensor_set_res_cfg_t *stream_on_cfg,
boolean *is_retry,
mct_stream_info_t *stream_info)
{
rc = module_sensor_get_pick_data(s_bundle, &s_bundle->stream_size_info,
stream_on_cfg);//这边更新stream_on_cfg的其他设置
rc = module_sensor_params->func_tbl.process(
module_sensor_params->sub_module_private,
SENSOR_SET_RESOLUTION, &set_res);
}
static int32_t sensor_set_resolution(void *sctrl, void *data)
{
rc = sensor_pick_resolution(sctrl, res_cfg, &res);
}//这个位置就是去获取sensor驱动提供的哪一组res配置
另外preview size会在获取capacity的时候做lcd显示尺寸的限制。
四fps_ranges_tbl获取:
typedef struct {
float min_fps;
float max_fps;
float video_min_fps;
float video_max_fps;
} cam_fps_range_t;