解析高通vendor层mct框架
凡越底层的代码,更能体现代码的精髓所在 — 数据结构 + 算法模型,所以在研究其代码时,可以先重点关注其数据结构,能更好的帮助我们解析其背后的原理逻辑!今天来分析一下高通的camera vendor下与camera hal相关的部分,mct模块,mct算是其中一个基础模块,其他所有的sensor、isp、imagelib等都会使用mct,所以对它的理解至关重要,更能帮助我们理解其他模块
基础数据结构体
mct_module_t
mct_module_t是mct的重要模块,几乎其他所有结构体和代码都和它由关系;
_mct_module就是mct_module_t的底层实现
struct _mct_module {
mct_object_t object;
mct_list_t *type_list; //相对于stream的此module的类型列表
mct_list_t *srcports; //源端口,发出端口
unsigned short numsrcports; //端口数量
mct_list_t *sinkports; //汇入端口,接收数据
unsigned short numsinkports; //端口数量
void *module_private; //私有变量,每个module该类型不同,如sensor它为module_sensor_ctrl_r
pthread_mutex_t type_list_lock; //线程的互斥量
/* 虚函数,所有的模块都必须要实现这些虚函数 */
mct_module_process_event_func process_event;
mct_module_set_mod_func set_mod;
mct_module_query_mod_func query_mod;
mct_module_request_port_function request_new_port;
mct_module_start_session start_session;
mct_module_stop_session stop_session;
mct_module_set_session_data set_session_data;
mct_module_get_session_data get_session_data;
};
mct_module可以作为stream的子对象,相对于stream来说这个mct_module是什么类型,source、sink或者中间
typedef struct {
stream表示identity
unsigned int identity;
相对于stream,mct_module类型type
mct_module_type_t type;
} mct_module_type_identity_t;
mct_object_t
mct中很多结构体都会有父或者子对象,如何形成父子对象映射关系,就是通过mct_object_t来实现的;因为很多结构体都会拥有或者间接拥有一个mct_object_t成员,所以就可能通过内部引用找到自己的mct_object_t来设置父子关系
struct _mct_object {
一个object匹配一个pipeline,父子规则如下:
一个pipeline可能有多个子对象stream
一个stream可能有多个子对象modules
一个module可能有多个子Port
一个port可能有多个子stream或者session,port必须并且只有一个父Module
moudle可能有多个父stream
stream有且仅有一个父pipeline
mct_list_t *parent; 表示自己的父对象有哪些,是一个链表形式,说明可以有多个
unsigned int parentsnum;
mct_list_t *children; 标明自己的子对象有哪些,同上
unsigned int childrennum;
char *name; /* individual object's name */
/* invidual Object information */
int refcount; /* individual object's reference count */
/* Note: For future usage,
* object LOCK, should be initialized to PTHREAD_MUTEX_INITIALIZER */
pthread_mutex_t lock;
unsigned int flags;
void *priv;
};
/*
mct list的node节点,双向链表,其中data有可能有两种结构体:
相对于各个module模块来说,其类型为mct_module_t
相对一个session会话来说,是mct_controller_t类型
相对于bus总线上的消息,是mct_bus_msg_t
*/
struct _mct_list {
void *data;
mct_list_t *prev;
mct_list_t **next; /*理解为一个二维数组 */
uint32_t next_num; /* 二维数组中的第一纬度有多少个 */
};
mct_controller_t
也就是mct_controller_t结构体,开启session会拥有一个这个结构体
struct _mct_controller {
mct_queue_t *serv_cmd_q;
mct_queue_t *bus_cmd_q;
pthread_mutex_t serv_msg_q_lock;
pthread_mutex_t server_lock;
/* Server result Q and its lock */
mct_queue_t *serv_res_q;
pthread_mutex_t serv_res_q_lock;
/* signal variable and its lock */
pthread_cond_t serv_res_cond;
pthread_mutex_t serv_res_cond_lock;
pthread_cond_t mctl_thread_started_cond;
pthread_mutex_t mctl_thread_started_mutex;
/* 1. Server communicates with Media Controller through signal(servSignal);
* 2. Media Controller communicate with Server through Pipe(servFd) */
int serv_fd;
int config_fd;
pthread_t mct_tid; /* Thread ID of mct main thread */
pthread_t mct_bus_handle_tid; /* Thread ID of mct bus_handler thread */
pthread_cond_t mctl_cond;
pthread_mutex_t mctl_mutex;
pthread_cond_t mctl_bus_handle_cond;
pthread_mutex_t mctl_bus_handle_mutex;
mct_thread_state_type bus_thread_state;
pthread_mutex_t mctl_state_mutex;
pthread_cond_t mctl_state_cond;
serv_cmd_q的计数器
unsigned int serv_cmd_q_counter;
以下结构体也很复杂,在mct_pipline.h里面有定义
mct_pipeline_t *pipeline;
/* HAL callback */
void *event_cb;
};
上面serv_cmd_q变量的消息体,用在server线程中:
typedef struct _mct_serv_msg {
这个消息是HAL msg还是Domain Socketmsg
如果是socket 则为ds_msg
如果是hal,则是hal_msg
mct_serv_msg_type msg_type;
union {
mct_serv_ds_msg_bundle_t ds_msg;
struct v4l2_event hal_msg;
} u;
} mct_serv_msg_t;
port
port模块主要的结构体
struct _mct_port {
mct_object_t object;
mct_port_caps_t caps;
mct_port_direction_t direction;
相关的port,stream形成的链路,容一个我角色,如都为src
mct_port_t *peer;
相关的port,stream形成的链路,中间伙伴
mct_port_t *internal_peer[MAX_PORT_CONNECTIONS];
mct_inter_peer_entity_t inter_session_peer[MAX_PORT_CONNECTIONS];
void *port_private;
/* virtual functions to be defined by individual ports */
执行函数,用于数据流执行函数
mct_port_event_func event_func;
mct_port_intra_event_func intra_event_func;
中间连接函数
mct_port_int_link_func int_link;
mct_port_ext_link_func ext_link;
mct_port_intra_link_func intra_link;
mct_port_unlink_func un_link;
mct_port_intra_unlink_func intra_unlink;
mct_port_set_caps_func set_caps;
mct_port_check_caps_reserve_func check_caps_reserve;
mct_port_check_caps_unreserve_func check_caps_unreserve;
};
typedef struct {
uint32_t session_id;
uint16_t num_cid_ch; /* num CIDs from sensor */
sensor_src_port_cap_entry_t sensor_cid_ch[SENSOR_CID_CH_MAX];
uint8_t num_meta_ch; /* num of meta channels */
sensor_src_port_cap_entry_t meta_ch[MAX_META];
uint8_t is_stereo_config;
} sensor_src_port_cap_t;
pipeline
struct _mct_pipeline {
mct_module_t module;
mct_bus_t *bus;
mct_controller_t *controller; //管理pipeline的controller,controller内部有成员指向该pipeline
mct_list_t *modules; //全局链表的首节点
mct_queue_t *param_queue;
session交互的数据格式
mct_pipeline_session_data_t session_data;
stream交互的数据格式
mct_pipeline_session_stream_info_t session_stream;
该pipeline拥有的多少条正在执行stream郑,这个是计数器
int8_t stream_on_cnt;
省略部分
//函数指针 此pipe提供的方法
mct_pipeline_add_stream_func add_stream;
mct_pipeline_remove_stream_func remove_stream;
发送事件函数,一般都是将数据发送到stream上
mct_pipeline_event_func send_event;
mct_pipeline_set_bus_func set_bus;
mct_pipeline_get_bus_func get_bus;
mct_pipeline_map_buf_func map_buf;
mct_pipeline_unmap_buf_func unmap_buf;
mct_pipeline_map_parm_func map_parm;
mct_pipeline_unmap_parm_func unmap_parm;
处理server线程的函数指针
mct_pipeline_proc_msg_func process_serv_msg;
处理bus线程的函数指针
mct_pipeline_proc_msg_func process_bus_msg;
每个module下子设备的线程变量
mct_pipeline_thread_data_t thread_data;
}
typedef struct{
pthread_t pid;
mct_module_t *module;
unsigned int session_id;
pthread_cond_t cond_v;
mct_sync_data_t sync;
pthread_mutex_t mutex;
unsigned int started_num;
unsigned int started_num_success;
unsigned int modules_num;
}mct_pipeline_thread_data_t;
消息队列,存储消息
typedef struct _mct_queue {
消息头结点
mct_list_t *head;
消息尾结点
mct_list_t *tail;
一共有多少个节点
uint32_t length;
} mct_queue_t;
获取strea信息结构体:
typedef struct _mct_pipeline_get_stream_info {
mct_pipeline_check_stream_t check_type;
uint32_t stream_index;
cam_stream_type_t stream_type;
uint32_t session_index;
cam_feature_mask_t feature_mask;
} mct_pipeline_get_stream_info_t;
Stream
stream总结构体:
struct _mct_stream {
/* Stream's parent should be pipeline,
* Stream's children should be modules which is arranged from
* source module to sink module -
* Note: Only Stream's children list can grow into a TREE form */
mct_object_t object;
uint32_t streamid;
mct_stream_info_t streaminfo;
/*
* Everything is in one thread context, there is no need
* to stuck in State. We shall difinitely NOT consider
* asynchronous State transition, otherwise things could
* end up with much complexity.
*
* At stream layer, 3 States: LINKED STOP and RUNNING should be
* sufficient.
*/
mct_stream_state_t state;
uint32_t current_frame_id;
void *kernel_sof_ptr;
uint32_t hw_sleep_frame_id;
mct_stream_bufs_t buffers;
void *stream_private;
int buf_mgr_fd;
mct_stream_metadata_t metadata_stream; /*Could be added to stream private?*/
mct_list_t *frame_num_idx_list;
boolean valid_buffer;
/* virtual functions */
mct_stream_add_module_func add_module;
mct_stream_remove_module_func remove_module;
mct_stream_insert_module_func insert_module;
mct_stream_configure_func configure;
mct_stream_send_event_func send_event;
mct_stream_link_modules_func link;
mct_stream_unlink_modules_func unlink;
mct_stream_map_buf_func map_buf;
mct_stream_unmap_buf_func unmap_buf;
mct_stream_map_parm_func map_parm;
mct_stream_unmap_parm_func unmap_parm;
};
stream详细info结构体
typedef struct _mct_stream_info_t {
unsigned int identity;
/* stream type*/
cam_stream_type_t stream_type;
/* image format */ /* for sensor, */
cam_format_t fmt;
/* image dimension */ /* for sensor, */
cam_dimension_t dim;
/* buffer plane information, will be calc based on stream_type, fmt,
dim, and padding_info(from stream config). Info including:
offset_x, offset_y, stride, scanline, plane offset */
cam_stream_buf_plane_info_t buf_planes;
/* streaming type */
cam_streaming_mode_t streaming_mode;
/* burst number of snapshot */
int num_burst;
/*num of frames generated
* only valid when streaming mode = CAM_STREAMING_MODE_BATCH*/
cam_stream_user_buf_info_t user_buf_info;
/*DS mapped buffer information*/
mct_list_t *img_buffer_list;
/* Stream buffer parameters */
cam_stream_parm_buffer_t parm_buf;
cam_pp_feature_config_t pp_config;
cam_stream_reproc_config_t reprocess_config;
int num_bufs;
mct_stream_status_t status;
mct_stream_t *stream;
/* Buffer params during aspect ratio mismatch */
uint32_t resize;
cam_dimension_t original_dim;
boolean expect_divert;
/*TODO: Add more fileds based on requirements*/
/* Image Stabilization type */
cam_is_type_t is_type;
uint8_t dis_enable;
cam_stream_secure_t is_secure;
cam_perf_mode_t perf_mode;
} mct_stream_info_t;
typedef struct {
void *stream_info;
size_t stream_size;
int stream_fd;
mct_list_t *img_buf;
mct_list_t *container_buf;
pthread_mutex_t lock_img_buf;
} mct_stream_bufs_t;
bus
struct _mct_bus {
unsigned int session_id;
bus总线上存储的消息队列
mct_queue_t *bus_queue;
bus总线上存储的优先级的消息队列
mct_queue_t *priority_queue;
/* Mutex for bus_queue */
pthread_mutex_t bus_msg_q_lock;
/* Mutex for priority_queue */
pthread_mutex_t priority_q_lock;
/* Bus signalling constructs */
pthread_mutex_t *mct_mutex;
pthread_cond_t *mct_cond;
post_msg_to_bus_func post_msg_to_bus;
/* SOF-monitor thread signalling constructs */
pthread_mutex_t bus_sof_msg_lock;
pthread_cond_t bus_sof_msg_cond;
pthread_mutex_t bus_sof_init_lock;
pthread_cond_t bus_sof_init_cond;
pthread_t bus_sof_tid;
线程运行状态,1表示内部线程已启动,线程为mct_bus_sof_thread_run函数
int thread_run;
uint32_t prev_sof_id;
mct_bus_msg_type_t msg_to_send_metadata;
uint32_t thread_wait_time;
};
bus总线上发送的消息消息结构体
typedef struct _mct_bus_msg {
uint32_t sessionid;
mct_bus_msg_type_t type;
uint32_t size; 此大小是指后面msg指针指向对象大小
void *msg;
mct_bus_metadata_collection_type_t metadata_collection_type;
} mct_bus_msg_t;
处理bus总线上消息后的返回结构体:
typedef struct _mct_process_ret {
这个type表示处理的message是一个sever msg还是bus msg
如果是server msg,则SERV_RET_TO_HAL_CMDACK是控制指令,SERV_RET_TO_HAL_NOTIFY缓存映射
如果是bus msg则使用SERV_RET_TO_HAL_NOTIFY MCT_PROCESS_RET_BUS_MSG
mct_process_ret_type type;
union {
处理server message后的返回
mct_proc_serv_msg_ret serv_msg_ret;
处理bus总线message后的返回
mct_proc_bus_msg_ret bus_msg_ret;
} u;
} mct_process_ret_t;
typedef struct _mct_proc_serv_msg_ret {
boolean error;
mct_serv_msg_t msg;
} mct_proc_serv_msg_ret;
typedef struct _mct_proc_bus_msg_ret {
boolean error;
mct_bus_msg_type_t msg_type;
meta data的缓存buffer index
int metadata_buf_idx;
int sof_debug;
unsigned int session;
unsigned int stream;
} mct_proc_bus_msg_ret;
与sensor相关的结构体
typedef struct {
/* Sensor module information for each sensor */
mct_list_t *sensor_bundle; /* mct_list_t里面data是module_sensor_bundle_info_t,它存储了所有子设备subdev信息 * */
void *eebin_hdl; //eeprom驱动层的调用句柄
/* Number of sensor bundle information - one per sensor successfully probed */
uint8_t size;
mct_stream_info_t streaminfo;
int32_t session_count;
/* Two sessions are linked for dual cam support. */
boolean is_dual_cam;
/* STREAM_ON command is issued for both sessions. */
boolean is_dual_stream_on;
/* actual streaming for both sessions */
boolean is_dual_streaming;
pthread_mutex_t dual_cam_mutex;
} module_sensor_ctrl_t;
sensor下面子设备相关的函数结构体:
typedef struct module_sensor_bundle_info_t {
/* info common for module and sensor submodule */
sensor_submod_common_info_t sensor_common_info;
/* for intra port communication : initial value -1*/
uint32_t peer_identity;
/* Entity to store subdev name for all imager modules */
char sensor_sd_name[SUB_MODULE_MAX][MAX_SUBDEV_SIZE];
/* Entity to store information of all subdev interfaces */
sensor_submodule_info_t subdev_info[SUB_MODULE_MAX];
/* Entity to store sensor name and index of its sub modules */
struct msm_sensor_info_t *sensor_info;
/* Sensor library params */
sensor_lib_params_t *sensor_lib_params;
/* chromatix manager */
chromatix_manager_type chromatix_manager;
/* eeprom data */
format_data_t *formatted_data;
sensor module下所有子设备的控制函数指针,每个数组对应一个子设备param,其中存放了对驱动层子设备的open、process和close函数,可以与kernl驱动层交互
module_sensor_params_t *module_sensor_params[SUB_MODULE_MAX];
/* stream ref count */
uint16_t ref_count;
/* max width of all streams */
uint32_t max_width;
/* max height of all streams */
uint32_t max_height;
/* stream mask of all streams */
uint32_t stream_mask;
/* refcount for non bundle stream on / off */
int32_t stream_on_count;
uint32_t last_idx;
uint16_t num_skip;
/* 1 started, 2, done, 3 done no led */
sensor_aec_est_state_t state;
uint32_t regular_led_trigger;
int32_t regular_led_af;
cam_flash_mode_t last_flash_request;
uint32_t stream_thread_wait_time;
/* store chromatix pointers to post to bus */
mct_bus_msg_sensor_metadata_t chromatix_metadata;
/* store trigger update to post to bus */
mct_bus_msg_stats_aec_metadata_t aec_metadata;
sensor_eeprom_data_t *eeprom_data;
/* Store sensor_params to post to bus */
cam_sensor_params_t sensor_params;
uint32_t torch_on;
int32_t longshot;
cam_fps_range_t fps_info;
sensor_frame_ctrl_params_t frame_ctrl;
pthread_mutex_t mutex;
pthread_cond_t cond;
int32_t init_config_done;
int32_t open_done;
int32_t res_cfg_done;
int32_t actuator_cfg_done;
int32_t parm_pending;
/* To be set when set/get parm need to be blocked */
int32_t block_parm;
/* Store HAL version */
int32_t hal_version;
/* Store capture intent */
int32_t capture_intent;
sensor_hal_params_t hal_params;
sensor_flash_params_t flash_params;
/* Sensor Bracketing Feature Specific */
sensor_af_bracket_t af_bracket_params;
sensor_bracket_params_t flash_bracket_params;
sensor_capture_control_t cap_control;
/* counter for LED off in burst mode */
int16_t led_off_count;
float led_off_gain;
uint32_t led_off_linecount;
uint32_t burst_num;
uint32_t led_on_period;
uint32_t flash_rer_enable;
/**** Flash control info ****/
uint32_t main_flash_on_frame_skip;
uint32_t main_flash_off_frame_skip;
uint32_t torch_on_frame_skip;
uint32_t torch_off_frame_skip;
int8_t retry_frame_skip;
uint32_t capture_pipeline_delay;
uint8_t partial_flash_frame_skip;
int8_t batch_idx;
uint32_t delay_frame_idx;
pthread_mutex_t capture_control_mutex;
/**********************/
与驱动层的管道端口
int32_t pfd[2];
uint32_t isp_frameskip[CAM_STREAM_TYPE_MAX];
uint8_t is_bayer;
uint32_t identity[CAM_STREAM_TYPE_MAX];
/*This mask is used to execute OIS commands after OIS init is done*/
uint16_t ois_cmd_queue_mask;
/* During fast aec mode, mctl thread will block on this thread */
pthread_cond_t fast_aec_cond;
/* Mutex used for fast aec mode */
pthread_mutex_t fast_aec_mutex;
/* number of frames to skip for fast AEC use case */
uint16_t sensor_num_fast_aec_frame_skip;
uint16_t fast_aec_wait_count;
boolean fast_aec_is_running;
boolean fast_aec_required;
uint32_t ois_enabled;
int32_t ois_mode;
uint32_t max_isp_frame_skip;
void * external_library[SENSOR_EXTERNAL_LIB_MAX];
float actuator_sensitivity;
cam_stream_size_info_t stream_size_info;
cam_capture_frame_config_t hal_frame_batch; /*from HAL*/
int32_t live_connect_fd[2];
boolean live_connect_thread_started;
uint32_t is_valid_dualcalib;
cam_related_system_calibration_data_t dualcam_tune_data;
uint8_t subsequent_bundle_stream;
uint32_t delay_frame_cnt;
uint32_t ext_pipeline_delay;
uint32_t cur_scene_mode;
float digital_gain;
void *isp_cap;
camif_cap_t camif_data_fmt;
cam_led_calibration_mode_t led_calibration_mode;
uint16_t cur_logical_lens_pos;
boolean sensor_sleeping;
boolean is_stereo_configuration;
struct module_sensor_bundle_info_t* stereo_peer_s_bundle;
} module_sensor_bundle_info_t;
typedef struct {
module_sensor_bundle_info_t *s_bundle;
会话session id
uint32_t session_id;
uint32_t stream_id;
} sensor_bundle_info_t;
typedef struct {
void *sensor_lib_handle;
sensor_lib_t *sensor_lib_ptr;
sensor_custom_API_t sensor_custom_API;
} sensor_lib_params_t;
module_sensor_params_t结构体中的func_tbl函数指针,如下:
typedef struct {
/* Open func for sub module
1st param -> Address of function table to be filled by sub module
2nd param -> Subdev info
return status -> success / failure */
int32_t (*open)(void **, void *);
/* Set param for sub module
1st param -> module pointer
2nd param -> event type
3rd param -> private data
return status -> success / failure */
int32_t (*process)(void *, sensor_submodule_event_type_t, void *);
/* close func for sub module
1st param -> module pointer
return status -> success / failure */
int32_t (*close)(void *);
} sensor_func_tbl_t;
SENSOR_SUB_MODULE_PROCESS_EVENT宏定义,就会调用上面这个函数指针;
首先,sensor_bundle_info_t里面的类型为module_sensor_params_t,名称为module_sensor_params是一个数组,分别对应sensor下面的每个子设备;而module_sensor_params_t里面有一个函数结构体指针名字为func_tbl,而这个函数指针如何初始化,是依靠下面这个数组写好的,每个子设备的函数指针:
static int32_t (*sub_module_init[SUB_MODULE_MAX])(sensor_func_tbl_t *) = {
[SUB_MODULE_SENSOR] = sensor_sub_module_init,
[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
};
每个子设备的初始化函数,会返回func_tbl指针;
最后使用SENSOR_SUB_MODULE_PROCESS_EVENT宏定义可以快速调用这个指针;如:
调用s_bundle下面的SUB_MODULE_SENSOR子设备的func_tbl指针的process函数,
传递的参数为SENSOR_GET_SENSOR_FORMAT和output_format,rc是返回值
SENSOR_SUB_MODULE_PROCESS_EVENT(s_bundle, SUB_MODULE_SENSOR,
SENSOR_GET_SENSOR_FORMAT, &output_format, rc);
创建Sensor module的MCT模块
在mct中,每个module的初始化都写到了一个数组中去了,如下:
每条内容依次是module名字、初始化函数、析构函数以及最后一个模块module
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 的驱动模块 —— src模块;
iface — ISP interface模块 —— inter模块;
isp — 主要是ISP的处理,其内部又包含了众多的模块 —— inter模块 ,如本文档主要涉及的bpc、bcc和snr子模块;
stats — 一些统计算法模块,如3A,ASD,AFD,IS,GRRO等数据统计的处理 ¬—— sink模块;
pproc —— post process处理 —— inter模块;
imglib —— 主要是图片的一些后端处理,如HDR等 —— sink模块。
以上数组中每个item的结构体如下:
* typedef struct _mct_module_init_name
{
const char *name; 名称
mct_module_init init_mod; 初始化函数指针
mct_module_deinit deinit_mod; 析构函数指针
mct_module_t *module; 模块结构体,初始化成功后会返回
} mct_module_init_name_t;
由HAL层进入Vendor是通过shim进入的,在HAl中mm_camera_interface.c中会类似于一种反射的形式,通过字符串函数名称mct_shimlayer_process_module_init调用:
int mct_shimlayer_process_module_init(mm_camera_shim_ops_t
*shim_ops_tbl)
{
mct_module_t *temp = NULL;
int32_t enabled_savemem = 0;
char savemem[128];
char config_node_name[MAX_DEV_NAME_SIZE];
char dev_name[MAX_DEV_NAME_SIZE];
int rc = 0;
struct msm_v4l2_event_data event_data;
if (!shim_ops_tbl) {
CLOGE(CAM_SHIM_LAYER, "Ops table NULL");
return FALSE;
}
#if defined(LOG_DEBUG)
cam_debug_open();
#endif
pthread_mutex_init(&session_mutex, NULL);
//config_node_name 获取为video0 video1 ...
if (get_config_node_name(config_node_name) == FALSE) {
CLOGE(CAM_SHIM_LAYER, "Failed to get config node name");
}
snprintf(dev_name, sizeof(dev_name), "/dev/%s", config_node_name);
//非阻塞式打开这个虚拟设备
config_fd = open(dev_name, O_RDWR | O_NONBLOCK);
if (config_fd < 0) {
CLOGE(CAM_SHIM_LAYER, "Failed to open config node");
}
property_get("cameradaemon.SaveMemAtBoot", savemem, "0");
enabled_savemem = atoi(savemem);
初始化各个sensor
if (mct_shimlayer_module_sensor_init() == FALSE) {
CLOGE(CAM_SHIM_LAYER, "sensor module init failed");
return FALSE;
}
if (enabled_savemem != 1) {
初始化其他各个模块
if (mct_shimlayer_module_init() == FALSE) {
CLOGE(CAM_SHIM_LAYER, "Module init failed");
return FALSE;
}
}
/*Sending IOCTL to inform kernel that daemon is not present */
禁止DAEMON模式
rc = ioctl(config_fd, MSM_CAM_V4L2_IOCTL_DAEMON_DISABLED, &event_data);
if (rc < 0) {
CLOGE(CAM_SHIM_LAYER, "Failed to send Daemon disabled IOCTL to kernel");
}
//配置函数指针,返回给hal使用
shim_ops_tbl->mm_camera_shim_open_session = mct_shimlayer_start_session;
shim_ops_tbl->mm_camera_shim_close_session = mct_shimlayer_stop_session;
shim_ops_tbl->mm_camera_shim_send_cmd = mct_shimlayer_process_event;
return TRUE;
}
初始化sensor module
static boolean mct_shimlayer_module_sensor_init(void)
{
mct_module_t *temp = NULL;
CLOGH(CAM_SHIM_LAYER, "Sensor module init");
if( NULL == modules_list[0].init_mod)
return FALSE;
调用上面数组中配置的初始化函数,并返回module结构体
temp = modules_list[0].init_mod(modules_list[0].name);
if (temp) {
modules_list[0].module = temp;
把sensor module的结构体添加到全局节点modules链表中去
if ((modules = mct_list_append(modules, temp, NULL, NULL)) == NULL) {
创建失败,释放sensor模块相关结构体
if (modules) {
modules_list[0].deinit_mod(temp);
modules_list[0].module = NULL;
return FALSE;
}
}
}
CLOGH(CAM_SHIM_LAYER, "Sensor module init done");
return TRUE;
}
mct基础模块不能独立存在,一般都是其他模块用它来创建,比如camera sensor模块创建一个名为sensor的mct模块,那这个模块就是sensor模块;好的,就用这个为例:
----module_sensor.c
mct_module_t *module_sensor_init(const char *name)
{
....
mct_module_t s_module = mct_module_create("sensor");
module_ctrl = malloc(sizeof(module_sensor_ctrl_t));
s_module->module_private = (void *)module_ctrl;
/* sensor module doesn't have sink port */
module_sensor_ctrl_t* s_module->numsinkports = 0;
就是创建一个eebin_hdl,赋值给module_ctrl
rc = eebin_interface_init(&module_ctrl->eebin_hdl);
//查找驱动kernel的eeprom设备,返回其标识
rc = eebin_interface_control(module_ctrl->eebin_hdl, &bin_ctl);
/* module_sensor_probe_sensors */
ret = sensor_init_probe(module_ctrl);
/* 查找所有的子设备actuator, etc with sensor */
ret = module_sensor_find_other_subdev(module_ctrl);
以下mct_list_traverse会遍历sensor_bundle中所有的子设备,并以此调用module_sensors_subinit
方法来初始化所有子设备
ret = mct_list_traverse(module_ctrl->sensor_bundle, module_sensors_subinit,
NULL);
....
创建port基于CID信息,port_sensor_create是port_sensor.c的函数
ret = mct_list_traverse(module_ctrl->sensor_bundle, port_sensor_create,
s_module);
if (ret == FALSE) {
SERR("failed");
goto ERROR1;
}
return s_module;
}
----mct_module.c
mct_module_t* mct_module_create(const char *name)
{
mct_module_t *new_module;
new_module = malloc(sizeof(mct_module_t));
if (!new_module) {
/*print error code here strerror(errno)*/
return FALSE;
}
memset(new_module, 0, sizeof(mct_module_t));
初始化mct_obj的lock互斥量,暂不清楚使用
pthread_mutex_init(MCT_OBJECT_GET_LOCK(new_module), NULL);
初始化type_list_lock互斥量
pthread_mutex_init(&new_module->type_list_lock, NULL);
MCT_OBJECT_CAST就是强者把new_module转换为变量使用,将其object的name设置
mct_object_set_name(MCT_OBJECT_CAST(new_module), name);
设置其set_mod、query_mod、start_session和stop_session等虚函数
mct_module_set_set_mod_func(new_module, mct_module_set_mod_default);
mct_module_set_query_mod_func(new_module, mct_module_query_mod_default);
//mct_module_set_request_port_func(new_module,
// mct_module_request_port_default);
mct_module_set_start_session_func(new_module,
mct_module_start_session_default);
mct_module_set_stop_session_func(new_module,
mct_module_stop_session_default);
return new_module;
}
sensor创建port
在上面module_sensor_init函数最几句代码执行mct_list_traverse会遍历所有bundle信息,然后执行port_sensor_create函数:
boolean port_sensor_create(void *data, void *user_data)
{
boolean ret = TRUE;
int32_t rc = SENSOR_SUCCESS;
mct_port_t *s_port = NULL;
module_sensor_bundle_info_t *s_bundle = (module_sensor_bundle_info_t *)data;
sensor_lib_params_t *sensor_lib_params = NULL;
mct_module_t *s_module = (mct_module_t *)user_data;
module_sensor_ctrl_t *module_ctrl = NULL;
int32_t i = 0, j = 0;
char port_name[32];
module_sensor_params_t *module_sensor_params = NULL;
module_sensor_params_t *module_right_sensor_params = NULL;
sensor_stream_info_array_t *sensor_stream_info_array = NULL;
sensor_stream_info_array_t *right_sensor_stream_info_array = NULL;
sensor_src_port_cap_t *sensor_src_port_cap = NULL;
module_sensor_params_t *csid_module_params = NULL;
uint32_t csid_version = 0;
uint8_t num_meta_ch = 0;
uint32_t pix_fmt_fourcc = 0;
获取sensor下子设备的相关参数,返回参数有open、process和close
module_sensor_params = s_bundle->module_sensor_params[SUB_MODULE_SENSOR];
csid_module_params = s_bundle->module_sensor_params[SUB_MODULE_CSID];
调用csid的子设备的open函数,open 会打开/dev/下的子设备,将kernel返回的fd保存
在csid自己的结构体中,之后就可以通过这个fd与驱动层访问了
rc = csid_module_params->func_tbl.open(
&csid_module_params->sub_module_private,
&s_bundle->subdev_info[SUB_MODULE_CSID]);
if (rc < 0) {
SERR("failed");
return FALSE;
}
获取csid的版本号,根据命令码CSID_GET_VERSION
rc = csid_module_params->func_tbl.process(
csid_module_params->sub_module_private,
CSID_GET_VERSION, &csid_version);
ioctl传递关闭csid指令
csid_module_params->func_tbl.close(
csid_module_params->sub_module_private);
module_ctrl = (module_sensor_ctrl_t *)s_module->module_private;
sensor_lib_params = s_bundle->sensor_lib_params;
获取sensor下流stream信息,读取到sensor_stream_info_array数组中
rc = module_sensor_params->func_tbl.process(s_bundle->sensor_lib_params,
SENSOR_GET_SENSOR_PORT_INFO, &sensor_stream_info_array);
感觉像是另一个s_bundle,就是子设备都是成对的
if (NULL != s_bundle->stereo_peer_s_bundle) {
获取右边的sensor param
module_right_sensor_params =
s_bundle->stereo_peer_s_bundle->module_sensor_params[SUB_MODULE_SENSOR];
将右边的stream信息读取到right_sensor_stream_info_array数组
rc = module_right_sensor_params->func_tbl.process(
s_bundle->stereo_peer_s_bundle->sensor_lib_params,
SENSOR_GET_SENSOR_PORT_INFO, &right_sensor_stream_info_array);
遍历sensor下的stream信息
for (j = 0; j < sensor_stream_info_array->size; j++) {
如果第j条流stream的size大于最大值,错误
if (SENSOR_CID_CH_MAX <
sensor_stream_info_array->sensor_stream_info[j].vc_cfg_size) {
SERR("vc_cfg_size out of range (%d) ",
(int) sensor_stream_info_array->sensor_stream_info[j].vc_cfg_size);
goto ERROR1;
}
sensorX,X是index,作为port的名称
snprintf(port_name, sizeof(port_name), "%s%d",
s_bundle->sensor_info->sensor_name, j);
创建port
s_port = mct_port_create(port_name);
sensor_src_port_cap = malloc(sizeof(sensor_src_port_cap_t));
....省略为s_port赋值的过程.....
s_port->direction = MCT_PORT_SRC;
s_port->check_caps_reserve = port_sensor_caps_reserve;
s_port->check_caps_unreserve = port_sensor_caps_unreserve;
s_port->ext_link = port_sensor_ext_link_func;
s_port->un_link = port_sensor_unlink_func;
s_port->event_func = port_sensor_port_process_event;
s_port->intra_event_func = port_sensor_port_process_event;
.......
将s_port作为s_module的子对象,并且根据direction将port加入到
s_module的的srcports或sinkport链表中
ret = mct_module_add_port(s_module, s_port);
}
这样就把mct_module的port加入进去了,因为sensor module是src的,所以它只有source port
sensor module初始化总结
经过module_sensor_init函数会进入sensor module模块内部,
- 首先会创建mct_module_t结构体,再次创建sensor模块的module_sensor_ctrl_t结构体,前者是mct所有module的共性部分结构体,后者每个module不同的结构体,他们之间也有引用关系;
- 在sensor中首先会open其驱动层/dev/video,然后找到其下面的sub_dev如actuator、etc等等,并将他们的信息写入到module_sensor_ctrl_t结构体中
- 然后会使用mct_list_traverse函数多次遍历module_sensor_ctrl_t结构体中的子设备,执行其初始化、创建管理器等
- mct_module根据自己内部的子设备信息中的stream,创建port,然后加入到mct_module的srcport里面去
- 最后将mct_module_t结构体写入到链表modules中去,其类型为mct_list_t,链表中的data为mct_module_t类型
记住在,相对于各个module模块的全局链表类型为mct_list_t,名字为modules,链表中存储的数据类型为mct_module_t,这是一个全局的
上图是初始化的逻辑关系图,各个逻辑模块最终都会用数据结构体整合在一起;外层各个module会用mct_list组成list保存,每个module都是一个mct_module结构体,这个mct_module内部的module_private成员是具体模块的结构体,如sensor module就是一个module_sensor_ctrl_t类型,赋值在module_private成员上,而module_sensor_ctrl_t作为sensor module的类型,其下面会有许多子设备,这些子设备存储在sensor_bundle成员下面,而最终又会创建许多port模块,这些port模块作为src,赋值在module_sensor_ctrl_t的子对象里面
start_session业务
其他的module初始化暂部分性,我们进行下一步,创建好module后,还需要打通与其的连接,MCT通过session来访问,入口函数:
cam_status_t mct_shimlayer_start_session(int session,
mm_camera_shim_event_handler_func event_cb)
{
int32_t enabled_savemem;
char savemem[128];
cam_status_t ret = CAM_STATUS_FAILED;
.....
if (enabled_savemem == 1) {
//如果没有初始化 这里就要初始化
if (mct_shimlayer_module_init() == FALSE) {
pthread_mutex_unlock(&session_mutex);
return CAM_STATUS_FAILED;
}
}
session是打开dev/video后的session config_fd是打开dev/video后的文件描述符
modules是mct链表的首节点,每个node节点对应一个硬件模块,如sensor isp等
ret = mct_controller_new(modules, session, config_fd, event_cb);
....
}
上面直观重要的就是mct_controller_new函数,跟进去看看:
cam_status_t mct_controller_new(mct_list_t *mods,
unsigned int session_idx, int serv_fd, void *event_cb)
{
以下结构体结构体文章上面有,是_mct_controller类型
mct_controller_t *mct = NULL;
mct_controller_t就是_mct_controller类型,在此文件头文件里面定义
mct = (mct_controller_t *)malloc(sizeof(mct_controller_t));
创建pipeline,其内部还要创建mct_queue队列和mct_bus总线
mct->pipeline = mct_pipeline_new(session_idx, mct);
为pipeline的modules赋值mods,是全局的moduels链表
mct->pipeline->modules = mods;
启动会话
ret_type = mct_pipeline_start_session(mct->pipeline);
//mct_queue_new是一个宏定义,就是创建一个mct_queue_t结构体
mct->serv_cmd_q = mct_queue_new;
mct->serv_cmd_q_counter = 0;
记录来自hal的回调event事件
mct->event_cb = event_cb;
定义bus线程为idle状态
mct->bus_thread_state = MCT_THREAD_STATE_IDLE;
初始化mct_queue_t结构体,serv_cmd_q是一个mct_queue_t类型
mct_queue_init(mct->serv_cmd_q);
mct->serv_res_q = mct_queue_new;
mct_queue_init(mct->serv_res_q);
记录/dev/video的文件句柄
mct->config_fd = serv_fd;
创建mct_controller_thread_run线程 -- mct
if (pthread_create(&tid, NULL, mct_controller_thread_run, mct)) {
pthread_mutex_unlock(&mct->mctl_thread_started_mutex);
goto main_thread_error;
}
pthread_setname_np(tid, "CAM_MctServ");
等待上面线程正常执行后继续执行
pthread_cond_wait(&mct->mctl_thread_started_cond,
&mct->mctl_thread_started_mutex);
pthread_mutex_unlock(&mct->mctl_thread_started_mutex);
mct->mct_tid = tid;
创建mct_bus_handler_thread_run线程 -- bus
if (pthread_create(&bus_hdl_tid, NULL, mct_bus_handler_thread_run, mct)) {
pthread_mutex_unlock(&mct->mctl_bus_handle_mutex);
goto bus_handle_thread_error;
}
pthread_setname_np(bus_hdl_tid, "CAM_MctBus");
pthread_mutex_unlock(&mct->mctl_bus_handle_mutex);
mct->mct_bus_handle_tid = bus_hdl_tid;
mct->pipeline->bus->mct_mutex = &mct->mctl_bus_handle_mutex;
mct->pipeline->bus->mct_cond = &mct->mctl_bus_handle_cond;
mcts又是一个全局的变量,也是一个链表,将mct加入到这个链表中
if (!(mcts = mct_list_append(mcts, mct, NULL, NULL))) {
goto all_error;
}
return CAM_STATUS_SUCCESS;
}
小结
开启会话会创建多个结构体,其中以mct_controller_t为主以及pipeline和bus等,然后在pipeline启动会话session,再创建两个线程mct_controller_thread_run和mct_bus_handler_thread_run,最后,把此次会话创建的mct_controller_t结构体加入mcts链表中,它也是一个mct_list_t类型,只不过其中元素类型为mct_controller_t,记住目前为止,已经有两个全局链表了,一个是modules,一个是mcts,这里先分析创建的pipeline,在分析后面两个线程
pipeline模块
pipeline模块由 mct_pipeline_new 函数创建,如下:
mct_pipeline_t* mct_pipeline_new (unsigned int session_idx,
mct_controller_t *pController)
{
mct_pipeline_t *pipeline;
pipeline = malloc(sizeof(mct_pipeline_t));
pipeline->session = session_idx;
与外层的mct_controller_t相互引用
pipeline->controller = pController;
以下宏定义就是强制拿去pipeline内部的obj成员变量
mct_object_t *obj = MCT_OBJECT_CAST(pipeline);
obj->children = NULL;
obj->childrennum = 0;
创建mct_queue_t数据结构体
pipeline->super_param_queue = (mct_queue_t *)mct_queue_new;
初始化queue内部各成员变量
mct_queue_init(pipeline->super_param_queue);
创建bus结构体
pipeline->bus = mct_bus_create(session_idx);
pipeline->sleep_duration = MCT_PIPELINE_SLEEP_DURATION;
给pipeline内部函数指针变量赋值
pipeline->map_buf = mct_pipeline_map_buf;
pipeline->unmap_buf = mct_pipeline_unmap_buf;
pipeline->map_parm = mct_pipeline_map_parm;
pipeline->unmap_parm = mct_pipeline_unmap_parm;
/* For case SERV_MSG_SET,SERV_MSG_GET, SERV_MSG_STREAMON, SERV_MSG_STREAMOFF,
SERV_MSG_QUERY,SERV_MSG_CLOSE_SESSION */
pipeline->process_serv_msg= mct_pipeline_process_serv_msg;
pipeline->process_bus_msg = mct_pipeline_process_bus_msg;
pipeline->add_stream = mct_pipeline_add_stream;
pipeline->remove_stream = mct_pipeline_remove_stream;
pipeline->send_event = mct_pipeline_send_event;
pipeline->set_bus = mct_pipeline_set_bus;
pipeline->get_bus = mct_pipeline_get_bus;
pipeline->hal_version = CAM_HAL_V1;
return pipeline;
}
bus模块
上面这块代码很简单,主要是分配内存,然后赋值,里面相对比较关键的是又创建了一个bus结构体,文章前面有这个结构体类型展示,mct_bus_create:
mct_bus_t *mct_bus_create(unsigned int session)
{
mct_bus_t *new_bus;
new_bus = malloc(sizeof(mct_bus_t));
memset(new_bus, 0 , sizeof(mct_bus_t));
pthread_mutex_init(&new_bus->bus_msg_q_lock, NULL);
pthread_mutex_init(&new_bus->priority_q_lock, NULL);
pthread_mutex_init(&new_bus->bus_sof_init_lock, NULL);
pthread_cond_init(&new_bus->bus_sof_init_cond, NULL);
new_bus->bus_queue = mct_queue_new;
if (!new_bus->bus_queue) {
pthread_mutex_destroy(&new_bus->bus_msg_q_lock);
goto busmsgq_error;
}
mct_queue_init(new_bus->bus_queue);
new_bus->priority_queue = mct_queue_new;
if (!new_bus->priority_queue) {
pthread_mutex_destroy(&new_bus->priority_q_lock);
goto busmsgq_error;
}
mct_queue_init(new_bus->priority_queue);
赋值函数指针mct_bus_post_msg,其字面意思就是将消息推送到bus总线上去
new_bus->post_msg_to_bus = mct_bus_post_msg;
new_bus->session_id = session;
return new_bus;
}
消息推送到bus总线
这里,你可以把bus理解为总线,总线就是数据通信中的主要道路,所有的信息msg最终都会把消息传递到bus总线,再由总线发送到其他地方,以下代码相对长,但是比较简单;
static boolean mct_bus_post_msg(mct_bus_t *bus, mct_bus_msg_t *bus_msg)
{
mct_bus_msg_t *local_msg;
boolean post_msg = FALSE;
mct_bus_msg_isp_sof_t *isp_sof_bus_msg = NULL;
unsigned int payload_size;
if (!bus || !bus_msg) {
CLOGE(CAM_MCT_MODULE, "NULL ptr detected: bus = [%p], bus_msg = [%p]",
bus, bus_msg);
goto error_2;
}
//如果bus总线上存储消息队列长度超过1000个
if (bus->bus_queue->length > MAX_MCT_BUS_QUEUE_LENGTH) {
pthread_mutex_lock(&bus->bus_msg_q_lock);
//flush所有存储的消息
mct_bus_queue_flush(bus);
CLOGI(CAM_MCT_MODULE,
"Discarded the bus msgs that got stagnated in the queue");
pthread_mutex_unlock(&bus->bus_msg_q_lock);
return TRUE;
}
//消息msg的type无效
if (bus_msg->type >= MCT_BUS_MSG_MAX) {
CLOGI(CAM_MCT_MODULE, "bus_msg type %d is not valid", bus_msg->type);
goto error_2;
}
payload_size = bus_msg->size;
//到这儿,说明此次消息是一个有效的消息
switch (bus_msg->type) {
case MCT_BUS_MSG_ISP_SOF:
post_msg = TRUE;
if (bus->thread_run == 1) {
pthread_mutex_lock(&bus->bus_sof_msg_lock);
pthread_cond_signal(&bus->bus_sof_msg_cond);
pthread_mutex_unlock(&bus->bus_sof_msg_lock);
}
isp_sof_bus_msg = bus_msg->msg;
CLOGD(CAM_MCT_MODULE,
"Posting SOF for frame ID %d", isp_sof_bus_msg->frame_id);
break;
//error错误,清楚所有的消息
case MCT_BUS_MSG_SEND_HW_ERROR:
post_msg = TRUE;
pthread_mutex_lock(&bus->bus_msg_q_lock);
mct_bus_queue_flush(bus);
pthread_mutex_unlock(&bus->bus_msg_q_lock);
break;
//sensor正在启动重
case MCT_BUS_MSG_SENSOR_STARTING:
bus->thread_wait_time = *((uint32_t *)bus_msg->msg);
//启动check线程
start_sof_check_thread(bus);
return TRUE;
break;
//sensor停止中,结束check线程
case MCT_BUS_MSG_SENSOR_STOPPING:
stop_sof_check_thread(bus);
return TRUE;
break;
case MCT_BUS_MSG_ERROR_MESSAGE:
case MCT_BUS_MSG_NOTIFY_KERNEL:
case MCT_BUS_MSG_CONTROL_REQUEST_FRAME:
case MCT_BUS_MSG_EZTUNE_JPEG:
case MCT_BUS_MSG_EZTUNE_RAW:
case MCT_BUS_MSG_DELAY_SUPER_PARAM:
case MCT_BUS_MSG_FRAME_SKIP:
case MCT_BUS_MSG_CAC_STAGE_DONE:
case MCT_BUS_MSG_ISP_RD_DONE:
post_msg = TRUE;
break;
default:
break;
}
local_msg = malloc(sizeof(mct_bus_msg_t));
if (!local_msg) {
CLOGE(CAM_MCT_MODULE, "Can't allocate memory");
goto error_2;
}
//将传递进来的msg拷贝到本地消息
local_msg->sessionid = bus_msg->sessionid;
local_msg->type = bus_msg->type;
local_msg->size = bus_msg->size;
//payload_size指后面msg指针指向对象大小
if (payload_size) {
local_msg->msg = malloc(payload_size);
if (!local_msg->msg) {
CLOGE(CAM_MCT_MODULE, "Can't allocate memory");
goto error_1;
}
memcpy(local_msg->msg, bus_msg->msg, payload_size);
} else {
local_msg->msg = NULL;
}
post_msg为true,说明有消息,需要将消息加入到bus总线的queue中,这里加入到priority_queue成员中
if (post_msg) {
pthread_mutex_lock(&bus->priority_q_lock);
入队queue
mct_queue_push_tail(bus->priority_queue, local_msg);
pthread_mutex_unlock(&bus->priority_q_lock);
pthread_mutex_lock(bus->mct_mutex);
pthread_cond_signal(bus->mct_cond);
pthread_mutex_unlock(bus->mct_mutex);
}
else {
/*Store bus messages in bus_msg queue
and dequeue during next SOF. */
pthread_mutex_lock(&bus->bus_msg_q_lock);
mct_queue_push_tail(bus->bus_queue, local_msg);
pthread_mutex_unlock(&bus->bus_msg_q_lock);
}
return TRUE;
}
此函数的目的就是把mct_bus_msg_t添加到mct_bus_t的两个消息队列queue上,一个priority_queue和一个bus_queue;并且此函数在收到类型MCT_BUS_MSG_SENSOR_STARTING类型会启动一个check函数,看看这个check函数:
static void start_sof_check_thread(mct_bus_t *bus)
{
int rc = 0;
if (!bus) {
CLOGE(CAM_MCT_MODULE, "NULL bus ptr");
return;
}
if (bus->thread_run == 1)
return;
....
pthread_mutex_init(&bus->bus_sof_msg_lock, NULL);
pthread_cond_init(&bus->bus_sof_msg_cond, NULL);
pthread_mutex_lock(&bus->bus_sof_init_lock);
//开启mct_bus_sof_thread_run线程
rc = pthread_create(&bus->bus_sof_tid, NULL, mct_bus_sof_thread_run, bus);
if(!rc) {
pthread_setname_np(bus->bus_sof_tid, "CAM_sof_timer");
pthread_cond_wait(&bus->bus_sof_init_cond, &bus->bus_sof_init_lock);
}
pthread_mutex_unlock(&bus->bus_sof_init_lock);
}
就是启动一个新线程mct_bus_sof_thread_run:
static void* mct_bus_sof_thread_run(void *data)
{
mct_bus_t *bus = (mct_bus_t *)data;
设置一个超时时间
signed long long timeout =
(((signed long long)(bus->thread_wait_time)) * MCT_BUS_NANOSECOND_SCALER);
int ret;
线程启动标志
bus->thread_run = 1;
while(bus->thread_run) {
等待超时时间的二分之一
ret = mct_bus_timeout_wait(&bus->bus_sof_msg_cond,
&bus->bus_sof_msg_lock, timeout/2);
if(bus->thread_run) {
超时原因导致
if ((ret == ETIMEDOUT) && (debug_data == 0)) {
enable = 1;
debug_data = 1;
mct_bus_msg_t bus_msg;
bus_msg.type = MCT_BUS_MSG_NOTIFY_KERNEL;
bus_msg.size = sizeof(int);
bus_msg.msg = (void *)&enable;
bus_msg.sessionid = bus->session_id;
发送一个enable为1的消息到bus总线上,这个消息会发送到
bus->post_msg_to_bus(bus, &bus_msg);
} else if ((ret == ETIMEDOUT) && (debug_data == 1)) {
,.....
break;
} else if (debug_data == 1) {
enable = 0;
debug_data = 0;
CLOGE(CAM_MCT_MODULE, "Session %d: Hinting SOF freeze is recover.",
bus->session_id);
mct_bus_msg_t bus_msg;
bus_msg.type = MCT_BUS_MSG_NOTIFY_KERNEL;
bus_msg.size = sizeof(int);
bus_msg.msg = (void *)&enable;
bus_msg.sessionid = bus->session_id;
bus->post_msg_to_bus(bus, &bus_msg);
}
} else {
CLOGI(CAM_MCT_MODULE, "Closing SOF tracker thread");
break;
}
}
线程结束,会清除掉bus内queue的所有消息
if (bus->thread_run == 1) {
/*Things went wrong*/
mct_bus_msg_t bus_msg;
bus_msg.type = MCT_BUS_MSG_SEND_HW_ERROR;
bus_msg.size = 0;
bus_msg.sessionid = bus->session_id;
bus->post_msg_to_bus(bus, &bus_msg);
}
return NULL;
}
bus小结
首先,会创建mct_bus_t结构体,结构体中有两个队列mct_queue_t成员,其队列中存储的主要类型是mct_bus_msg_t
其次,bus模块有个关键函数mct_bus_post_msg,它会将外部的消息根据type类型push到mct_bus_t的bus_queue和priority_queue队列中
最后,在mct_bus_post_msg函数中,type为MCT_BUS_MSG_SENSOR_STARTING会启动一个check线程,这个线程主要设置一个超时时间,周期性的唤醒线程,然后发送MCT_BUS_MSG_NOTIFY_KERNEL类型消息,将消息post到priority_queue队列中
pipeline启动session
回到session启动函数中的mct_controller_new中,创建完pipeline后,会调用mct_pipeline_start_session启动session
cam_status_t mct_pipeline_start_session(mct_pipeline_t *pipeline)
{
boolean rc;
int ret;
struct timespec timeToWait;
.....
pipeline->thread_data.started_num = 0;
pipeline->thread_data.modules_num = 0;
pipeline->thread_data.started_num_success = 0;
modules是全局modules链表,里面存放了sensor、isp各个module,mct_list_traverse会遍历所有node然后执行mct_pipeline_get_module_num,计算一共有多少个module
rc = mct_list_traverse(pipeline->modules, mct_pipeline_get_module_num,
pipeline);
遍历每个module,并其执行mct_pipeline_modules_start,这个函数会开启一个线程,打通与kernel层交互,使用管道通信,发现sensor模块是这样的
rc &= mct_list_traverse(pipeline->modules, mct_pipeline_modules_start,
pipeline);
rc = mct_util_get_timeout(MCT_THREAD_TIMEOUT, &timeToWait);
........
同上,遍历module,执行mct_pipeline_get_session_data方法,第三个是传递的参数
rc &= mct_list_traverse(pipeline->modules, mct_pipeline_get_session_data,
pipeline);
........
pipeline->session_data.set_session_mask |= SESSION_DATA_SUPERSET;
同上
rc &= mct_list_traverse(pipeline->modules, mct_pipeline_set_session_data,
pipeline);
pipeline->session_data.set_session_mask = 0;
将pipeline的session状态设置为启动STARTING
pipeline->session_stream.state = MCT_ST_STATE_STARTING;
同时也为这个session活动添加一个stream流信息
mct_pipeline_start_stream_internal(pipeline);
if (TRUE == rc)
return CAM_STATUS_SUCCESS;
else
return CAM_STATUS_FAILED;
}
如上函数,mct_list_traverse是一个很重要的函数,他会遍历第一个参数中的所有节点node,然后将执行第二个参数,第二个参数是函数指针,最后一个是第二个函数指针需要的参数;所以上面函数重点就是几个mct_list_traverse传递的函数指针是啥意思:
最后,不要遗漏函数后面几行代码mct_pipeline_start_stream_internal,启动stream的函数,里面涉及了stream以及绑定逻辑
第一个mct_pipeline_get_module_num
static boolean mct_pipeline_get_module_num(void *data1 __unused, void *data2)
{
mct_pipeline_t *pipeline = (mct_pipeline_t *)data2;
pipeline->thread_data.modules_num++;
return TRUE;
}
它就是计算一共有多少个module,并记录在pipeline的thread_data成员中的modules_num去
第二个mct_pipeline_modules_start
看名字也就知道,会对各个module执行启动操作,至于启动做什么就要看看以下代码了
static boolean mct_pipeline_modules_start(void *data1, void *data2)
{
int rc = 0;
pthread_attr_t attr;
char thread_name[20];
mct_pipeline_t *pipeline = (mct_pipeline_t *)data2;
这个thread_data只有一个,但是data1会有多个,也就是有多个module赋值到一个thread_data
mct_pipeline_thread_data_t *thread_data = &(pipeline->thread_data);
thread_data->module = (mct_module_t *)data1;
thread_data->session_id = pipeline->session;
为每个module创建一个线程,线程主体执行函数是mct_pipeline_start_session_thread
rc = pthread_create(&pipeline->thread_data.pid, &attr,
&mct_pipeline_start_session_thread, (void *)thread_data);
snprintf(thread_name, sizeof(thread_name), "CAM_start%s",
MCT_MODULE_NAME(thread_data->module));
if(!rc) {
pthread_setname_np(pipeline->thread_data.pid,thread_name);
必须要等到子线程执行完成后才能进行下一个module的start
pthread_cond_wait(&thread_data->cond_v, &thread_data->mutex);
}
pthread_mutex_unlock(&thread_data->mutex);
return TRUE;
}
这里有一个疑问,thread_data作为pipeline的内部成员,只有一个,而mct_pipeline_modules_start函数因为遍历多个module所以会执行多次,所以thread_data就会被赋值多次,为啥要赋值多次呢?并且这个thread_data要传递到下个线程中去;重点看看mct_pipeline_start_session_thread函数:
static void* mct_pipeline_start_session_thread(void *data)
{
mct_pipeline_thread_data_t *thread_data = (mct_pipeline_thread_data_t*)data;
mct_module_t *module = thread_data->module;
unsigned int session_id = thread_data->session_id;
boolean rc = FALSE;
....
pthread_mutex_lock(&thread_data->mutex);
释放信号,上一个函数可以继续往下执行了,因为module和session都已经读取了
pthread_cond_signal(&thread_data->cond_v);
pthread_mutex_unlock(&thread_data->mutex);
如果module的start_session方法不为空
if (module->start_session) {
CLOGI(CAM_MCT_MODULE, "Calling start_session on Module %s",
MCT_MODULE_NAME(module));
执行start_session方法,启动会话
rc = module->start_session(module, session_id);
CLOGI(CAM_MCT_MODULE, "Module %s start_session rc = %d",
MCT_MODULE_NAME(module), rc);
}
pthread_mutex_lock(&thread_data->mutex);
成功启动,为线程成功启动的加1
thread_data->started_num++;
if (rc == TRUE)
thread_data->started_num_success++;
如果线程启动总数量等于总的module数量,那么释放notify信号
if(thread_data->started_num == thread_data->modules_num)
pthread_cond_signal(&thread_data->cond_v);
pthread_mutex_unlock(&thread_data->mutex);
ATRACE_END();
CLOGI(CAM_MCT_MODULE, "X %s" , MCT_MODULE_NAME(module));
return NULL;
}
这里也很简单,主要就是启动module的start_session方法;这里就解决了上面的疑惑了,当前线程执行前几行代码会马上读取module和session id,然后就释放cond_v信号量,通知上一个函数可以继续执行了,这样就算下一个module执行而来,就算对thread_data重新赋值也没有影响
真正的start_session
到这里,我们发现start_session经过一番折腾,又回到了自己的module模块下,执行器start_session方法,每个module的开启session都不一样,这里我们就只看sensor module了,sensor module在初始化的时候对start_session函数指针赋值为s_module->start_session = module_sensor_start_session,所以:
static boolean module_sensor_start_session(
mct_module_t *module, uint32_t sessionid)
{
module_sensor_ctrl_t *module_ctrl = NULL;
mct_list_t *s_list = NULL;
module_sensor_bundle_info_t *s_bundle = NULL;
boolean ret = TRUE;
SHIGH("sessionid %d", sessionid);
RETURN_ON_NULL(module);
module_ctrl = (module_sensor_ctrl_t *)module->module_private;
RETURN_ON_NULL(module_ctrl);
ATRACE_BEGIN(PROF_SENSOR_START_SESSION);
session id通过session找到kernel驱动层对应的虚拟设备信息
s_list = mct_list_find_custom(module_ctrl->sensor_bundle, &sessionid,
sensor_util_find_bundle);
RETURN_ON_NULL(s_list);
s_bundle = (module_sensor_bundle_info_t *)s_list->data;
RETURN_ON_NULL(s_bundle);
/* initialize the "torch on" flag to 0 */
s_bundle->torch_on = 0;
s_bundle->longshot = 0;
为这个虚拟设备创建一个线程,一直轮询通过管道读取里面的数据
ret = sensor_thread_create(s_bundle);
if (ret == FALSE) {
SERR("failed to create sensor thread");
goto ERROR;
}
以下双通道都关闭,默认单通道
module_ctrl->is_dual_cam = FALSE;
module_ctrl->is_dual_stream_on = FALSE;
module_ctrl->is_dual_streaming = FALSE;
初始化这个session、包括上电、配置sensor等
ret = module_sensor_init_session(s_bundle, module_ctrl->eebin_hdl);
if (ret == FALSE) {
SERR("failed");
goto ERROR;
}
如果是双通道模式就上电
if (TRUE == s_bundle->is_stereo_configuration &&
s_bundle->stereo_peer_s_bundle != NULL) {
SERR("Powering up peer stereo sensor. ");
ret = module_sensor_init_session(s_bundle->stereo_peer_s_bundle,
module_ctrl->eebin_hdl);
if (ret == FALSE) {
SERR("failed");
goto ERROR;
}
}
SHIGH("SUCCESS");
ATRACE_END();
return TRUE;
}
sensor_thread_create函数就不进去看了,他就是创建一个线程sensor_thread_func,直接查看这个进程函数是干什么的?
参数data是在sensor_thread_create函数中组装的变量,主要包含与驱动层的通信的管道端口
void* sensor_thread_func(void *data)
{
sensor_thread_t *thread = (sensor_thread_t*)data;
int32_t readfd, writefd;
pthread_mutex_lock(&thread->mutex);
设置为true,表示线程开始执行了
thread->is_thread_started = TRUE;
读取管道
readfd = thread->readfd;
writefd = thread->writefd;
pthread_cond_signal(&thread->cond);
pthread_mutex_unlock(&thread->mutex);
struct pollfd pollfds;
int32_t num_of_fds = 1;
boolean thread_exit = FALSE;
int32_t ready = 0;
设置管道信息以及感兴趣的时间
pollfds.fd = readfd;
pollfds.events = POLLIN | POLLPRI;
cancel_autofocus = FALSE;
这个轮询读取的数据来源于哪里?
猜测1:管道fd属于s_bundle下的成员,而bundle与自身相关,猜测来源于kernel驱动
猜测2:在sensor module下有很多源代码往这个管道写入了数据,如结束session、module_sensor_update_af_bracket_entry等
此类型的更多是type为offload类型,函数重载
while(!thread_exit){
轮询管道
ready = poll(&pollfds, (nfds_t)num_of_fds, -1);
if(ready > 0)
{
有事件正在发生
if(pollfds.revents & (POLLIN | POLLPRI)){
ssize_t nread = 0;
sensor_thread_msg_t msg;
读取管道消息
nread = read(pollfds.fd, &msg, sizeof(sensor_thread_msg_t));
if(nread < 0) {
SERR("Unable to read the message");
}
如果msg中有停止的信号,结束线程
if(msg.stop_thread) {
break;
}
sensor_process_thread_message(&msg);
}
}
else{
if (errno != EINTR) {
SERR("Unable to ple exiting the thread");
break;
}
}
}
close(readfd);
close(writefd);
return NULL;
}
void sensor_process_thread_message(sensor_thread_msg_t *msg)
{
mct_bus_msg_t bus_msg;
mct_bus_msg_af_status_t af_msg;
enum sensor_af_t status;
int32_t i = 0;
ssize_t ret = 0;
cam_focus_distances_info_t fdistance;
SLOW("Processing Pipe message %d", msg->msgtype);
long long start __attribute__((unused)) = sensor_current_timestamp();
switch(msg->msgtype){
消息类型为设置自动对焦
case SET_AUTOFOCUS: {
status = SENSOR_AF_NOT_FOCUSSED;
while (i < 20) {
获取sensor自动对焦状态,最多尝试20次
ret = ioctl(msg->fd, VIDIOC_MSM_SENSOR_GET_AF_STATUS, &status);
if (ret < 0) {
SERR("failed");
}
对焦成功,跳出循环
if(status == SENSOR_AF_FOCUSSED)
break;
if(cancel_autofocus) {
cancel_autofocus = FALSE;
break;
}
usleep(10000);
i++;
}
/* Send the AF call back */
switch (status) {
case SENSOR_AF_FOCUSSED:
af_msg.focus_state = CAM_AF_FOCUSED;
break;
default:
af_msg.focus_state = CAM_AF_NOT_FOCUSED;
break;
}
memset(&fdistance, 0, sizeof(fdistance));
af_msg.f_distance = fdistance;
memset(&bus_msg, 0, sizeof(mct_bus_msg_t));
bus_msg.type = MCT_BUS_MSG_SENSOR_AF_STATUS;
bus_msg.msg = (void *)&af_msg;
bus_msg.size = sizeof(mct_bus_msg_af_status_t);
bus_msg.sessionid = msg->sessionid;
对焦成功,把消息发送到bus总线上去,这里类型为MCT_BUS_MSG_SENSOR_AF_STATUS,
所以会发到bus_queue队列上去
mct_module_post_bus_msg(msg->module,&bus_msg);
cancel_autofocus = FALSE;
SLOW("Setting Auto Focus message received");
break;
}
case OFFLOAD_FUNC: {
if (msg->offload_func) {
msg->offload_func(msg->param1, msg->param2, msg->param3, msg->param4);
} else {
SERR("msg->offload_func is null");
}
}
break;
default:
break;
}
}
start_session小结
从pipeline中start_session最终都会走到各个module自己内部的session start,以sensor module为例:
- 根据传入的session id,查找到相关的sensor_bundle设备信息
- 创建一个线程,循环poll管道,读取来自kernel或者sensor module的消息
- 如果消息类型是自动对焦,则把消息发送到bus总线上去;如果是offload类型则会重载去执行一些函数
第三个 mct_pipeline_get_session_data
和start_session一样,不难得出,这个get_session最终也会调用module自己的get函数,如下:
boolean mct_pipeline_get_session_data(void *data, void *user_data)
{
mct_pipeline_t *pipeline = (mct_pipeline_t *)user_data;
mct_module_t *module = (mct_module_t *)data;
if (!pipeline || !module) {
return FALSE;
}
调用module自己的get_session
if (module->get_session_data) {
第二个参数是指针,说明是要把数据读到它里面
module->get_session_data(
module, &pipeline->session_data, pipeline->session);
}
return TRUE;
}
get_session_data数据结构指向的是module_sensor_get_session_data函数,这个函数主要就是读取其对应结构体里面的内容,如一些图像输出格式、相机位置以及3A信息等,然后将数据保存到此次pipeline的session_data里面去
第四个 mct_pipeline_set_session_data
set_session仍然是调用module的set session函数,反过来它是将上一个步骤得到的数据session_data又写回到module_sensor_ctrl_t结构体里面去
static boolean module_sensor_set_session_data(mct_module_t *module,
void *set_buf, uint32_t sessionid)
{
mct_pipeline_session_data_t *frame_ctrl_data = NULL;
module_sensor_ctrl_t *module_ctrl = NULL;
sensor_bundle_info_t bundle_info;
module_sensor_bundle_info_t *s_bundle = NULL;
uint32_t identity = 0;
RETURN_ON_NULL(module);
RETURN_ON_NULL(set_buf);
frame_ctrl_data = (mct_pipeline_session_data_t *)set_buf;
/* Extract module private */
module_ctrl = (module_sensor_ctrl_t *)module->module_private;
RETURN_ON_NULL(module_ctrl);
memset(&bundle_info, 0, sizeof(sensor_bundle_info_t));
identity = pack_identity(sessionid, 0);
查找sensor_bundle
RETURN_ON_FALSE(sensor_util_get_sbundle(module, identity, &bundle_info));
s_bundle = bundle_info.s_bundle;
RETURN_ON_NULL(s_bundle);
设置session_data内容
s_bundle->frame_ctrl.session_data = *frame_ctrl_data;
s_bundle->capture_pipeline_delay =
s_bundle->frame_ctrl.session_data.max_pipeline_frame_applying_delay;
s_bundle->retry_frame_skip =
s_bundle->frame_ctrl.session_data.min_isp_sw_frame_skip_retry;
SHIGH("max delay %d report delay %d retry skip %d",
frame_ctrl_data->max_pipeline_frame_applying_delay,
frame_ctrl_data->max_pipeline_meta_reporting_delay,
s_bundle->retry_frame_skip);
return TRUE;
}
start session之添加stream流信息
在mct_pipeline_start_session启动session函数最后一步里面有一个mct_pipeline_start_stream_internal函数,将会为此次session添加stream信息,如下所示:
static void* mct_pipeline_start_stream_internal(mct_pipeline_t *pipeline)
{
boolean rc = TRUE;
mct_stream_t *stream = NULL;
mct_pipeline_get_stream_info_t info;
struct v4l2_event msg;
struct msm_v4l2_event_data *data =
(struct msm_v4l2_event_data*)&msg.u.data[0];
cam_stream_info_t *stream_info;
/*create new session based stream */
data->session_id = pipeline->session;
//MCT_SESSION_STREAM_ID = 15
data->stream_id = MCT_SESSION_STREAM_ID;
if (pipeline->add_stream) {
CLOGI(CAM_MCT_MODULE,
"Adding session stream streamid= 0x%x for session=%d",
data->stream_id, pipeline->session);
添加流信息,add_stream里面会create一个stream
rc = pipeline->add_stream(pipeline, data->stream_id);
}
CLOGD(CAM_MCT_MODULE, "Allocating stream buffer");
pipeline->session_stream.session_stream_info =
malloc(sizeof(cam_stream_info_t));
if (!pipeline->session_stream.session_stream_info) {
CLOGE(CAM_MCT_MODULE, "session_stream_info allocation failed");
return NULL;
}
CLOGD(CAM_MCT_MODULE, "Mapping stream buffer");
映射,将上面创建的stream结构体内部的stream info信息映射到pipeline结构体中;
这样后面的配置stream info两边都修改了,也就是pipeline.session_stream.session_stream_info = stream.buffers.stream_info
if (pipeline->map_parm(pipeline) == FALSE) {
CLOGE(CAM_MCT_MODULE, "stream map_param failed");
return NULL;
}
配置stream的相关格式信息
stream_info =
(cam_stream_info_t *)pipeline->session_stream.session_stream_info;
memset(stream_info, 0, sizeof(cam_stream_info_t));
stream_info->stream_type = CAM_STREAM_TYPE_PARM;
stream_info->fmt = CAM_FORMAT_YUV_420_NV12;
stream_info->dim.width = 0;
stream_info->dim.height = 0;
stream_info->streaming_mode = CAM_STREAMING_MODE_CONTINUOUS;
stream_info->buf_planes.plane_info.num_planes= 0;
stream_info->num_bufs = 0;
data->session_id = pipeline->session;
data->stream_id = MCT_SESSION_STREAM_ID;
info.check_type = CHECK_INDEX;
info.stream_index = data->stream_id;
因为流stream作为child添加到pipeline的结构体中,这里检查是否已经被添加进去
stream = mct_pipeline_get_stream(pipeline, &info);
这句代码很关键,宏定义又是宏定义,高通很多关键代码都用宏定义来处理,MCT_STREAM_LINK
宏定义主要是检测stream结构体的link函数指针成员是否存在,如果存在就执行这个三行
表达式的第二个,也就是调用stream的link函数,传递参数为自己本身stream
(MCT_STREAM_LINK(stream)) ?
(rc = (MCT_STREAM_LINK(stream))(stream)) : (rc = FALSE);
....省略后面.....
}
static boolean mct_pipeline_add_stream(mct_pipeline_t *pipeline,
uint32_t stream_id)
{
mct_stream_t *stream = NULL;
if (!pipeline)
return FALSE;
创建一个mct_stream_t
stream = mct_stream_new(stream_id);
if (!stream)
goto stream_failed;
stream是子,pipeline是父,首先他们二者均有自己的mct_obj_t成员,
第一步将pipelin的mct_obj加入到pipeline的mct_obj的parent里面去
第二步将stream的mct_obj加入到pipeline的mct_obj的child里面去
if (!mct_object_set_parent(MCT_OBJECT_CAST(stream),
MCT_OBJECT_CAST(pipeline))) {
goto set_parent_failed;
}
return TRUE;
}
在mct_pipeline_start_stream_internal中,首先,创建mct_stream,把他加入到pipeline的子对象,使pipeline和stream之间建立好父子关系;然后,将stream中的info映射到pipeline的stream成员info中,并且配置这个stream info的具体信息,流type,图像格式fmt宽高等信息;最后,在调用stream自己的link函数,link内部很复杂,但是它主要的工作就是将stream与它需要的module进行绑定,并建立好module之间的数据流关系
stream之link
由pipeline如何调用link就不分析,我们直接进入link函数mct_stream_start_link:
static boolean mct_stream_start_link(mct_stream_t *stream)
{
uint32_t sessionid;
cam_stream_info_t *stream_info;
boolean ret = FALSE;
获取stream的buffers成员的stream_info成员,这个info就是上个mct_pipeline_start_stream_internal函数配置的info信息
mct_stream_map_buf_t *info = MCT_STREAM_STREAMINFO(stream);
内部MCT_OBJECT_PARENT最终拿到的是pipeline 外部MCT_PIPELINE_MODULES则是拿到pipeline的modules成员,它是全局所有module的首节点,包括sensor、isp、等
mct_list_t *modules =
MCT_PIPELINE_MODULES(MCT_OBJECT_PARENT(stream)->data);
mct_pipeline_t *pipeline =
MCT_PIPELINE_CAST((MCT_STREAM_PARENT(stream))->data);
char *(*link_mod)[MAX_STREAM_MODULES] = NULL;
stream->streaminfo.identity = pack_identity(sessionid, stream->streamid);
stream->streaminfo.stream_type = stream_info->stream_type;
stream->streaminfo.fmt = stream_info->fmt;
stream->streaminfo.dim = stream_info->dim;
stream->streaminfo.streaming_mode = stream_info->streaming_mode;
stream->streaminfo.num_burst = stream_info->num_of_burst;
stream->streaminfo.buf_planes = stream_info->buf_planes;
stream->streaminfo.pp_config = stream_info->pp_config;
stream->streaminfo.reprocess_config = stream_info->reprocess_config;
stream->streaminfo.num_bufs = stream_info->num_bufs;
stream->streaminfo.is_type = stream_info->is_type;
stream->streaminfo.dis_enable = stream_info->dis_enable;
stream->streaminfo.is_secure = stream_info->is_secure;
stream->streaminfo.perf_mode = stream_info->perf_mode;
stream->streaminfo.user_buf_info = stream_info->user_buf_info;
stream->streaminfo.stream = stream;
switch (stream->streaminfo.stream_type) {
case CAM_STREAM_TYPE_POSTVIEW:
case CAM_STREAM_TYPE_PREVIEW:
.....
session - stream链接,前面的函数配置为此类型
case CAM_STREAM_TYPE_PARM: {
CLOGI(CAM_MCT_MODULE, "Start linking Session-stream 0x%x",
stream->streaminfo.identity);
if (pipeline->session_data.sensor_format != FORMAT_YCBCR) {
link_mod = param_bayer_mod;
} else {
yuv参数所需要的module,param_yuv_mod为全局参数,见本函数后面
link_mod = param_yuv_mod;
}
}
break;
case CAM_STREAM_TYPE_CALLBACK:
case CAM_STREAM_TYPE_SNAPSHOT:
case CAM_STREAM_TYPE_VIDEO:
case CAM_STREAM_TYPE_RAW:
....有很多case.....
配置连接
ret = mct_stream_link_module_array(stream,link_mod);
}
char *param_yuv_mod[][MAX_STREAM_MODULES] = {
{"sensor","iface","pproc","imglib"},
{},
};
这个link函数就是配置stream所需要的子module,为了完成我们的stream目标为CAM_FORMAT_YUV_420_NV12和CAM_STREAM_TYPE_PARM,需要param_yuv_mod这几个module,但是这几个module如何连接依赖当前stream,还要看看mct_stream_link_module_array函数:
static boolean mct_stream_link_module_array(mct_stream_t *stream,
char *(*stream_type_mod)[MAX_STREAM_MODULES])
{
boolean ret = TRUE;
获取stream的父pipeline
mct_pipeline_t *pipeline =
MCT_PIPELINE_CAST((MCT_STREAM_PARENT(stream))->data);
获取所有的module
mct_list_t *modules =
MCT_PIPELINE_MODULES(MCT_OBJECT_PARENT(stream)->data);
mct_module_t *module[MAX_STREAM_MODULES];
int mod_type;
int mod_row=0;
int mod_col=0;
int num_mod=0;
如果传入的mod为空,返回
if (stream_type_mod[mod_row][mod_col] == NULL) {
return ret;
}
while(1) {
if (mod_col > MAX_STREAM_MODULES) {
CLOGE(CAM_MCT_MODULE, "array overflow");
return FALSE;
}
if (stream_type_mod[mod_row][mod_col]) {
找到此stream配置的module,并存放在module这个局部数组里面,最终这个数组里面存放的就是此stream所需的module
但是还没有完,还要建立module之间的连接关系
module[num_mod] = mct_stream_get_module(modules,stream_type_mod[mod_row][mod_col]);
if (module[num_mod] == NULL) {
CLOGE(CAM_MCT_MODULE, "Null: %p",module[num_mod]);
return FALSE;
}
mod_col++;
num_mod++;
} else {
遍历找到的module数组
for (num_mod=0; num_mod< mod_col;num_mod++) {
找到的第一个module,其类型为source
if (num_mod == 0 && mod_row ==0) {
mod_type = MCT_MODULE_FLAG_SOURCE;
找到最后一个module,它为一个sinkmode
} else if (num_mod == (mod_col-1)) {
mod_type = MCT_MODULE_FLAG_SINK;
中间的module则为Indexable
} else {
mod_type = MCT_MODULE_FLAG_INDEXABLE;
}
设置module的type_list里面的成员,主要是相对于stream,这个module是source、sink还是其他的
module[num_mod]->set_mod(module[num_mod],mod_type,stream->streaminfo.identity);
}
for (num_mod=0; num_mod< (mod_col-1);num_mod++) {
if (mod_row!=0) {
...这里不会执行,因为只有一行module配置....
} else {
主要就是将参数中两个module依次加入到stream的子children里面
ret = mct_stream_link_modules(stream,module[num_mod],module[num_mod+1], NULL);
if (ret == FALSE) {
CLOGE(CAM_MCT_MODULE, "Linking failed");
return FALSE;
}
}
}
mod_row++;
mod_col=0;
num_mod=0;
if (stream_type_mod[mod_row][mod_col] == NULL) {
break;
}
}
};
if (ret == FALSE) {
CLOGE(CAM_MCT_MODULE, "link failed");
return FALSE;
}
return ret;
}
就这样把stream相关的module都配置到其子children里面去了,link也总算完成了!总的来说,stream的link就是就是把相关的module设置到stream的子children对象里面去,并且children里面的排序分别是source/中间/sink模块,与此同时,这些模块通过port来连接,port内部则又有peer成员来确定他们之间的相互关系
再次小结start_session框架图
值得注意的是纵向创建stream时,首先配置stream目标,此次流是什么样的流?然后这个流需要哪些module支持,如sensor和isp这些等等,link好后,将相关module添加到stream的子对象中,最后建立这些module之间的关系;
最后,下面这两个线程就会使用这些建立好的关系!
start_session两个重要的线程
第一个线程mct_controller_thread_run
此线程主要是轮询mct_controller_t上的serv_cmd_q队列,取数据,然后执行操作的,
static void* mct_controller_thread_run(void *data)
{
mct_controller_t *mct_this;
mct_process_ret_t *mct_ret = NULL;
mct_process_ret_t proc_ret;
mct_serv_msg_t *msg;
timer_t mct_timerid;
int mct_t_ret = 0;
struct timespec timeToWait;
mct_this = (mct_controller_t *)data;
mct_this->mct_tid = pthread_self();
/* create a timer */
mct_t_ret = mct_util_create_timer(&mct_timerid);
.....
do {
pthread_mutex_lock(&mct_this->mctl_mutex);
serv_cmd计数器为0就等待命令
if (!mct_this->serv_cmd_q_counter) {
pthread_cond_wait(&mct_this->mctl_cond, &mct_this->mctl_mutex);
}
while (1) {
pthread_mutex_lock(&mct_this->serv_msg_q_lock);
取出serv_cmd_q中的消息
msg = (mct_serv_msg_t *)mct_queue_pop_head(mct_this->serv_cmd_q);
pthread_mutex_unlock(&mct_this->serv_msg_q_lock);
取出的消息为空,退出内存循环
if (!msg) {
break;
}
消息数量减一
mct_this->serv_cmd_q_counter--;
pthread_mutex_unlock(&mct_this->mctl_mutex);
mct_ret = (mct_process_ret_t *)malloc (sizeof(mct_process_ret_t));
if (!mct_ret) {
CLOGE(CAM_MCT_MODULE, "Out of Memory, Malloc failed");
goto close_mct;
}
处理消息,获取返回结果
*mct_ret = mct_controller_proc_serv_msg_internal(mct_this, msg);
free(msg);
msg = NULL;
如果处理结果为删除session会话,就结束当前线程
if (mct_ret->type == MCT_PROCESS_RET_SERVER_MSG &&
mct_ret->u.serv_msg_ret.msg.msg_type == SERV_MSG_HAL &&
mct_ret->u.serv_msg_ret.msg.u.hal_msg.id == MSM_CAMERA_DEL_SESSION) {
goto close_mct;
}
.......
}
} while(1);
......
}
到这一步,只能看出取出消息,然后调用mct_controller_proc_serv_msg_internal来处理消息,再继续往下看的同时,建议你先看看文章最上面的mct_serv_msg_t结构体内部结构,然后在看mct_controller_proc_serv_msg_internal函数:
static mct_process_ret_t mct_controller_proc_serv_msg_internal(
mct_controller_t *mct, mct_serv_msg_t *msg)
{
serv线程的返回值类型mct_process_ret_t
mct_process_ret_t ret;
mct_pipeline_t *pipeline;
初始化返回值
memset(&ret, 0x00, sizeof(mct_process_ret_t));
ret.type = MCT_PROCESS_RET_SERVER_MSG;
ret.u.serv_msg_ret.error = TRUE;
.......
ret.u.serv_msg_ret.msg = *msg;
pipeline = mct->pipeline;
switch (msg->msg_type) {
来自socket的消息,也就是vendor层另一边还有一个socket进程,此文还未提及
case SERV_MSG_DS: {
这部分主要会调用pipeline的map映射操作
if ((msg->u.ds_msg.operation == CAM_MAPPING_TYPE_FD_BUNDLED_MAPPING ||
msg->u.ds_msg.operation == CAM_MAPPING_TYPE_FD_MAPPING)
&& pipeline->map_buf) {
ret.u.serv_msg_ret.error = pipeline->map_buf(&msg->u.ds_msg, pipeline);
} else if (msg->u.ds_msg.operation == CAM_MAPPING_TYPE_FD_UNMAPPING &&
pipeline->unmap_buf) {
ret.u.serv_msg_ret.error = pipeline->unmap_buf(&msg->u.ds_msg, pipeline);
}
}
break;
case SERV_MSG_HAL:
来自hal的消息
if (pipeline->process_serv_msg)
pipeline处理
ret.u.serv_msg_ret.error = pipeline->process_serv_msg(&msg->u.hal_msg,
pipeline);
break;
default:
break;
}
return ret;
}
如上,处理hal的消息又进入到pipeline了,这个消息是从上往下传递的,hal–>vendor;而process_serv_msg是一个函数指针:
pipeline->process_serv_msg= mct_pipeline_process_serv_msg;
这种操作在mct内很常见,各个module的结构体内部都会有许多函数指针,而module之间调用就会通过这种指针调用;所以当你找不到函数时,去module的初始化里面去找,说不定它就是个函数指针:
static boolean mct_pipeline_process_serv_msg(void *message,
mct_pipeline_t *pipeline)
{
struct v4l2_event *msg = (struct v4l2_event *)message;
boolean ret = TRUE;
struct msm_v4l2_event_data *data =
(struct msm_v4l2_event_data *)(msg->u.data);
if (!message || !pipeline || data->session_id != pipeline->session)
return FALSE;
switch (msg->id) {
设置相机参数
case MSM_CAMERA_SET_PARM:
ret = mct_pipeline_process_set(data, pipeline);
break;
获取相机参数
case MSM_CAMERA_GET_PARM:
/* process config_w */
ret = mct_pipeline_process_get(data, pipeline);
break;
结束session
case MSM_CAMERA_DEL_SESSION: {
/* for session ending:
* a session has ONLY one child */
if (MCT_PIPELINE_CHILDREN(pipeline)) {
MCT_OBJECT_LOCK(pipeline);
/* Delete streams */
mct_list_free_all(MCT_PIPELINE_CHILDREN(pipeline),
mct_pipeline_delete_stream);
MCT_PIPELINE_CHILDREN(pipeline) = NULL;
MCT_PIPELINE_NUM_CHILDREN(pipeline) = 0;
MCT_OBJECT_UNLOCK(pipeline);
}
}
break;
default:
/* something wrong */
ret = FALSE;
break;
} /* switch (msg->msg_type) */
return ret;
}
这个函数也很简单,从上层传递下来的就是设置/获取相机参数,或者结束session会话;这里我们以set参数为例跟进去看看,
static boolean mct_pipeline_process_set(struct msm_v4l2_event_data *data,
mct_pipeline_t *pipeline)
{
boolean ret = TRUE;
mct_stream_t *stream = NULL;
mct_pipeline_get_stream_info_t info;
if (data->command != CAM_PRIV_PARM)
CLOGI(CAM_MCT_MODULE, "command=%x", data->command);
第一个switch会根据指令大范围摔选相关的stream流,并处理一些共性逻辑判断,如下
switch (data->command) {
case CAM_PRIV_STREAM_INFO_SYNC:
case MSM_CAMERA_PRIV_STREAM_ON:
case MSM_CAMERA_PRIV_STREAM_OFF:
case MSM_CAMERA_PRIV_DEL_STREAM:
case CAM_PRIV_STREAM_PARM: {
info.check_type = CHECK_INDEX;
info.stream_index = data->stream_id;
CLOGL(CAM_MCT_MODULE, "stream id: %x", data->stream_id);
stream = mct_pipeline_get_stream(pipeline, &info);
if (!stream) {
CLOGE(CAM_MCT_MODULE, "Couldn't find stream id: %x",
data->stream_id);
return FALSE;
}
如果是stream启动指令,并且stream已经启动了,就直接返回
if (MSM_CAMERA_PRIV_STREAM_ON == data->command &&
MCT_ST_STATE_RUNNING == stream->state) {
return TRUE;
}
如果是stream结束指令,并且stream已经结束了,就直接返回
else if (MSM_CAMERA_PRIV_STREAM_OFF == data->command &&
MCT_ST_STATE_IDLE == stream->state) {
return TRUE;
}
}
break;
case CAM_PRIV_PARM:
case CAM_PRIV_PREPARE_SNAPSHOT:
case CAM_PRIV_START_ZSL_SNAPSHOT:
case CAM_PRIV_STOP_ZSL_SNAPSHOT:
case CAM_PRIV_CANCEL_AUTO_FOCUS:
case CAM_PRIV_DO_AUTO_FOCUS:
case CAM_PRIV_SYNC_RELATED_SENSORS: {
info.check_type = CHECK_INDEX;
info.stream_index = MCT_SESSION_STREAM_ID;
stream = mct_pipeline_get_stream(pipeline, &info);
if (!stream) {
CLOGE(CAM_MCT_MODULE, "Couldn't find stream id: %x",
data->stream_id);
return FALSE;
}
}
break;
default:
break;
}
精准处理,根据不同的指令,不同的操作
switch (data->command) {
添加一条新的stream
case MSM_CAMERA_PRIV_NEW_STREAM: {
CLOGD(CAM_MCT_MODULE, "Adding new stream: id [0%x]", data->stream_id);
if (pipeline->add_stream) {
MCT_PROF_LOG_BEG(PROF_MCT_STREAMADD, "id:", data->stream_id);
增加stream
ret = pipeline->add_stream(pipeline, data->stream_id);
if(FALSE == ret)
MCT_PROF_LOG_END();
} else {
ret = FALSE;
}
}
break;
stream 同步,会导致stream和其相关的module连接起来,module作为stream的子对象
case CAM_PRIV_STREAM_INFO_SYNC: {
拿到此流的info配置信息,包括图像格式。宽高等信息
if (!MCT_STREAM_STREAMINFO(stream)) {
没有拿到,说明stream有问题,返回
ret = FALSE;
else 说明拿到stream的info信息
} else {
MCT_PROF_LOG_BEG(PROF_MCT_STREAM_LINK, "id", stream->streamid,
"type", stream->streaminfo.stream_type);
这句代码和pipeline启动session后,最后几行代码一样,属于link stream with module
(MCT_STREAM_LINK(stream)) ?
(ret = (MCT_STREAM_LINK(stream))(stream)) : (ret = FALSE);
if (FALSE == ret) {
stream->streaminfo.identity,
stream->streaminfo.stream_type);
} else {
。。.。
}
MCT_PROF_LOG_END();
}
启动 or 结束stream信息
case MSM_CAMERA_PRIV_STREAM_ON:
case MSM_CAMERA_PRIV_STREAM_OFF:{
mct_event_t cmd_event;
mct_event_control_t event_data;
char command[20];
boolean ret = TRUE;
if (data->command == MSM_CAMERA_PRIV_STREAM_ON) {
event_data.type = MCT_EVENT_CONTROL_STREAMON;
strlcpy (command, "STREAM-ON", sizeof(command));
} else {
event_data.type = MCT_EVENT_CONTROL_STREAMOFF;
strlcpy (command, "STREAM-OFF", sizeof(command));
}
如果在pipeline的子对象running状态的stream只有一条,并且当前是结束指令
if ( (1 == pipeline->stream_on_cnt) &&
(data->command == MSM_CAMERA_PRIV_STREAM_OFF) ) {
MCT_OBJECT_LOCK(pipeline);
暂不清楚这个frame_num_idx_list是什么,但是这里就是释放所有的frame_num_idx_list
mct_list_free_all(pipeline->frame_num_idx_list,
mct_stream_free_frame_num_list);
pipeline->frame_num_idx_list = NULL;
MCT_OBJECT_UNLOCK(pipeline);
if (!MCT_QUEUE_IS_EMPTY(pipeline->super_param_queue)) {
发送之前的指令
mct_pipeline_flush_super_param_queue(pipeline);
}
}
event_data.control_event_data = (void *)&stream->streaminfo;
CLOGI(CAM_MCT_MODULE, " %s on stream 0x%x stream type=%d",
command, stream->streaminfo.identity, stream->streaminfo.stream_type);
/打包指令,也就是将一种数据结构转换成另一种结构,把数据event_data和指令都会封装到cmd_event里面
ret = mct_pipeline_pack_event(MCT_EVENT_CONTROL_CMD,
(pack_identity(MCT_PIPELINE_SESSION(pipeline), data->stream_id)),
MCT_EVENT_DOWNSTREAM, &event_data, &cmd_event);
if (ret == FALSE) {
CLOGE(CAM_MCT_MODULE, "Error in packing event");
break;
}
继续发送指令
if (pipeline->send_event) {
发送指令,调用pipeline的send_event,其内部又是调用stream的send_event
ret = pipeline->send_event(pipeline, data->stream_id, &cmd_event);
if (TRUE == ret) {
启动加一
if (data->command == MSM_CAMERA_PRIV_STREAM_ON) {
stream->state = MCT_ST_STATE_RUNNING;
if ((stream->streaminfo.stream_type != CAM_STREAM_TYPE_METADATA) &&
(stream->streaminfo.stream_type != CAM_STREAM_TYPE_OFFLINE_PROC)) {
加一操作
pipeline->stream_on_cnt++;
}
结束减一
} else {
stream->state = MCT_ST_STATE_IDLE;
if ((stream->streaminfo.stream_type != CAM_STREAM_TYPE_METADATA) &&
(stream->streaminfo.stream_type != CAM_STREAM_TYPE_OFFLINE_PROC)) {
pipeline->stream_on_cnt--;
if (0 == pipeline->stream_on_cnt) {
if (pipeline->bus) {
pipeline->bus->prev_sof_id = 0; /* Reset SOF tracker */
}
}
}
}
} else {
.....
}
}
else {
CLOGE(CAM_MCT_MODULE, "send_event not registered");
ret = FALSE;
}
MCT_PROF_LOG_END();
}
break;
......
}
case......
后面还有很多case
此函数相对较长,主要是根据case命令,执行不同的操作,这里以这MSM_CAMERA_PRIV_STREAM_ON来跟踪分析,些命令都来自上层;上层应用都是根据session来回话的,而传入的参数data里面有session和streamid,这里会根据stream id找到pipeline下子对象的相同id的stream,然后对其发送事件;几乎所有的case条件,都会先打包封装参数,然后调用pipeline的sent_event事件去操作,不难猜出sent_event是一个函数指针,最终肯定走到stream里面去:
send_event == mct_pipeline_send_event
static boolean mct_pipeline_send_event(mct_pipeline_t *pipeline,
uint32_t stream_id, mct_event_t *event)
{
boolean ret = TRUE;
mct_stream_t *stream = NULL;
mct_pipeline_get_stream_info_t info;
if (!pipeline || !event)
return FALSE;
info.check_type = CHECK_INDEX;
info.stream_index = stream_id;
stream = mct_pipeline_get_stream(pipeline, &info);
if (!stream) {
CLOGE(CAM_MCT_MODULE, "Couldn't find stream");
return FALSE;
}
调用stream的send_even
ret = stream->send_event(stream, event);
return ret;
}
是这样吧!进入stream吧!
stream->send_event = mct_stream_send_event;
static boolean mct_stream_send_event(mct_stream_t *stream, mct_event_t *event)
{
mct_module_t *src_module = NULL;
boolean ret = FALSE;
mct_list_t *sinkports;
mct_port_t *port = NULL;
if (stream->streaminfo.stream_type == CAM_STREAM_TYPE_METADATA) {
.....
} else if ((stream->streaminfo.stream_type == CAM_STREAM_TYPE_OFFLINE_PROC)
&&
((stream->streaminfo.reprocess_config.\
pp_feature_config.feature_mask &
(CAM_QCOM_FEATURE_METADATA_PROCESSING | CAM_QCOM_FEATURE_METADATA_BYPASS)))) {
....
} else {
宏定义判断这个stream必须有子对象module才行
if (MCT_STREAM_CHILDREN(stream)) {
后面这个宏定义依次是取mct_stream=>mct_obj->children->data,有可能stream有多个module,而这里取出来的是第一个添加进去的module,也就是源module
src_module = (mct_module_t *)(MCT_STREAM_CHILDREN(stream)->data);
}
第一个子对象必须source,因为最终图像数据都从第一个module出来
if (!src_module)
return FALSE;
module根据标识identity是此流的source,并且这个module必须有process_event事件,就去执行
if ((mct_module_find_type(src_module, event->identity)
== MCT_MODULE_FLAG_SOURCE) && src_module->process_event) {
ret = src_module->process_event(src_module, event);
} else {
.......
}
}
return ret;
}
这么一看stream_on事件又会传递到其相关的module下面去,执行module的process_event函数指针,这样正常,启动stream肯定要去配置其子对象module能正常工作才行,stream子对象有哪些module呢? 这个和你一开始创建stream时配置有关系,在mct_stream.c源文件头部有很多配置,如下是部分展示:
本文前面在start_session部分有提及创建stream时会有一些配置,其中配置选择了param_yuv_mod,这里就以这个为讲解,上面代码的src_module->process_event就会执行sensor module的事件,process_event;我们跳转到sensor module里面去执行,sensor中此process_event也是一个函数指针,设置在这里
mct_module_set_process_event_func(module,module_sensor_module_process_event);
static boolean module_sensor_module_process_event(mct_module_t *module,
mct_event_t *event)
{
boolean ret = TRUE;
int32_t rc = SENSOR_SUCCESS;
module_sensor_ctrl_t *module_ctrl = NULL;
mct_event_control_t *event_ctrl = NULL;
sensor_bundle_info_t bundle_info;
struct timespec ts;
module_ctrl = (module_sensor_ctrl_t *)module->module_private;
RETURN_ON_NULL(module_ctrl);
event_ctrl = &event->u.ctrl_event;
准备抓图
if (event_ctrl->type == MCT_EVENT_CONTROL_PREPARE_SNAPSHOT) {
sensor_output_format_t output_format;
mct_bus_msg_t bus_msg;
memset(&bus_msg, 0, sizeof(mct_bus_msg_t));
module_sensor_params_t *module_sensor_params = NULL;
bundle_info.s_bundle->state = 0;
bundle_info.s_bundle->regular_led_trigger = 0;
SUB_MODULE_SENSOR是其module子设备
module_sensor_params =
bundle_info.s_bundle->module_sensor_params[SUB_MODULE_SENSOR];
向sensor子设备发送获取sensor格式指令
rc = module_sensor_params->func_tbl.process(
module_sensor_params->sub_module_private,
SENSOR_GET_SENSOR_FORMAT, &output_format);
SLOW("in Prepare snapshot, sensor type is %d\n", output_format);
if (output_format == SENSOR_YCBCR) {
bus_msg.sessionid = bundle_info.s_bundle->sensor_info->session_id;
bus_msg.type = MCT_BUS_MSG_PREPARE_HW_DONE;
cam_prep_snapshot_state_t state;
state = DO_NOT_NEED_FUTURE_FRAME;
bus_msg.msg = &state;
bus_msg.size = sizeof(cam_prep_snapshot_state_t);
向bus总线上post消息,说我已经准备好抓图,msg会推送到bus的bus_queue
if (mct_module_post_bus_msg(module,&bus_msg)!=TRUE)
SERR("Failure posting to the bus!");
return TRUE;
}
}
switch (event_ctrl->type) {
启动stream指令
case MCT_EVENT_CONTROL_STREAMON:
MCT_PROF_LOG_BEG(PROF_SENSOR_STREAM_ON, "stream type", module_ctrl->streaminfo.stream_type);
SLOW("ide %x MCT_EVENT_CONTROL_STREAMON",event->identity);
/* Set the sensor stream */
ret = module_sensor_set_sensor_stream(bundle_info.s_bundle);
BREAK_ON_FALSE(ret);
memcpy(&module_ctrl->streaminfo, event->u.ctrl_event.control_event_data,
sizeof(mct_stream_info_t));
向module下的port发送stream on指令
ret = port_sensor_handle_stream_on(module, event, &bundle_info);
BREAK_ON_FALSE(ret);
break;
case .....
}
此函数也相对较长,有很多case语句,这里就只看MCT_EVENT_CONTROL_STREAMON,sensor module又将事件发送到port上去,port才是最终的执行者;
boolean port_sensor_handle_stream_on(mct_module_t *module, mct_event_t *event,
sensor_bundle_info_t *bundle_info)
{
boolean ret = TRUE;
mct_port_t *port = NULL;
if (bundle_info->s_bundle->sensor_num_fast_aec_frame_skip &&
bundle_info->s_bundle->fast_aec_required)
ret = port_sensor_handle_stream_on_fastaec(module, event, bundle_info);
else
走正常逻辑
ret = port_sensor_handle_stream_on_normal(module, event, bundle_info);
RETURN_ON_FALSE(ret);
/* Set stream ON flag */
说明已经stream on了,设置stream中的状态标志
ret = sensor_util_set_stream_on(module, event->identity, TRUE);
RETURN_ON_FALSE(ret);
return ret;
}
static boolean port_sensor_handle_stream_on_normal(mct_module_t *module,
mct_event_t *event,
sensor_bundle_info_t *bundle_info)
{
boolean ret = TRUE;
调用module sensor中各个子设备,配置其信息,使stream on
ret = module_sensor_stream_on(module, event, bundle_info->s_bundle);
RETURN_ON_FALSE(ret);
return TRUE;
}
sensor module的stream on:
boolean module_sensor_stream_on(mct_module_t *module,
mct_event_t *event, module_sensor_bundle_info_t *s_bundle)
{
boolean ret = TRUE;
int32_t rc = SENSOR_SUCCESS;
int32_t i = 0;
module_sensor_params_t *module_sensor_params = NULL;
sensor_get_t sensor_get;
sensor_output_format_t output_format;
int32_t stream_on_count;
mct_stream_info_t* stream_info =
(mct_stream_info_t*) event->u.ctrl_event.control_event_data;
sensor_set_res_cfg_t stream_on_cfg;
int32_t bundle_id = -1;
boolean stream_on_flag = FALSE;
module_sensor_port_bundle_info_t *bundle_info = NULL;
int32_t delay_en = 1;
sensor_thread_msg_t msg;
int32_t nwrite = 0;
module_sensor_params_t *stereo_peer_module_sensor_params = NULL;
....
module_sensor_params = s_bundle->module_sensor_params[SUB_MODULE_SENSOR];
配置sensor子设备
rc = module_sensor_params->func_tbl.process(
module_sensor_params->sub_module_private,
SENSOR_SET_DELAY_CFG, (void*)&delay_en);
配置LED
module_sensor_params_t *led_module_params =
s_bundle->module_sensor_params[SUB_MODULE_LED_FLASH];
if (led_module_params->func_tbl.process != NULL) {
rc = led_module_params->func_tbl.process(
led_module_params->sub_module_private, LED_FLASH_SET_TORCH, NULL);
}
这块里面涉及到大量的底层交互
...
配置完成后
}
server thread 小结
到这里,终于把线程中大部分任务看完了;总的来说:
- 取mct_controller中server_cmd数据处理
- 分析参数数据,然后依次交给pipeline --> stream -> module -> port处理
- 设置相关的状态变量
如上图,事件最终在port模块会完结,最后在将成功或者失败的消息发送到mct_bus_t模块的数据队列上去;将由下一个线程将消息回调给上层应用
第二个线程mct_bus_handler_thread_run
这个线程相对简单,主要是将数据由底层传递给上层,一步一步分析:
static void* mct_bus_handler_thread_run(void *data)
{
mct_process_ret_t proc_ret;
mct_bus_msg_t *bus_msg;
mct_controller_t* mct_obj = (mct_controller_t *)data;
if(!mct_obj) {
CLOGE(CAM_MCT_MODULE, "Invalid pointer for mct object");
return NULL;
}
do {
pthread_mutex_lock(&mct_obj->mctl_bus_handle_mutex);
如果bus总线上的priority_queue队列长度为0,说明没有数据,wait等待数据
if(!mct_obj->pipeline->bus->priority_queue->length) {
pthread_cond_wait(&mct_obj->mctl_bus_handle_cond,
&mct_obj->mctl_bus_handle_mutex);
}
pthread_mutex_unlock(&mct_obj->mctl_bus_handle_mutex);
/* Received Signal from Pipeline Bus */
while (1) {
pthread_mutex_lock(&mct_obj->pipeline->bus->priority_q_lock);
从bus总线的priority_queue取数据
bus_msg = (mct_bus_msg_t *)mct_queue_pop_head
(mct_obj->pipeline->bus->priority_queue);
pthread_mutex_unlock(&mct_obj->pipeline->bus->priority_q_lock);
取出的消息为空,退出内层循环
if (!bus_msg) {
break;
}
消息类型为close camera,退出线程
if (bus_msg->type == MCT_BUS_MSG_CLOSE_CAM) {
goto thread_exit;
}
//处理消息msg
proc_ret = mct_controller_proc_bus_msg_internal(mct_obj, bus_msg);
}
} while(1);
....
}
return NULL;
}
轮询bus中的priority_queue任务队列,函数请看注释,接着看mct_controller_proc_bus_msg_internal,处理bus msg:
static mct_process_ret_t mct_controller_proc_bus_msg_internal(
mct_controller_t *mct, mct_bus_msg_t *bus_msg)
{
mct_process_ret_t ret;
mct_pipeline_t *pipeline;
ret.u.bus_msg_ret.error = TRUE;
ret.type = MCT_PROCESS_RET_BUS_MSG;
if (!mct || !bus_msg || !mct->pipeline) {
return ret;
}
//设置状态
mct_controller_set_thread_state(mct, MCT_THREAD_STATE_RUNNING);
ret.u.bus_msg_ret.error = FALSE;
ret.u.bus_msg_ret.msg_type = bus_msg->type;
ret.u.bus_msg_ret.session = bus_msg->sessionid;
pipeline = mct->pipeline;
....
请求frame
if (bus_msg->type == MCT_BUS_MSG_CONTROL_REQUEST_FRAME) {
ret.u.bus_msg_ret.error = FALSE;
if (!mct_pipeline_control_hw_state(pipeline, bus_msg->msg)) {
CLOGE(CAM_MCT_MODULE, "Failed to set HW module state");
return ret;
}
}
if (bus_msg->type == MCT_BUS_MSG_SEND_HW_ERROR ||
bus_msg->type == MCT_BUS_MSG_EZTUNE_JPEG ||
bus_msg->type == MCT_BUS_MSG_EZTUNE_RAW) {
向应用层发送回调
ret.u.bus_msg_ret.error = mct_controller_send_cb(pipeline, bus_msg->type);
.....
return ret;
}
......
if(MCT_BUS_MSG_ISP_RD_DONE == bus_msg->type) {
if(!mct_controller_handle_offline_meta_proc(pipeline, bus_msg)) {
......
}
}
if (bus_msg->type == MCT_BUS_MSG_CAC_STAGE_DONE) {
向应用层发送回调
ret.u.bus_msg_ret.error = mct_controller_send_cb(pipeline, bus_msg->type);
if (ret.u.bus_msg_ret.error == FALSE) {
CLOGE(CAM_MCT_MODULE, "Failed to send callback to HAL for type = %d",
bus_msg->type);
return ret;
}
}
设置状态
mct_controller_set_thread_state(mct, MCT_THREAD_STATE_IDLE);
return ret;
}
上面函数大多数都会执行mct_controller_send_cb发送回调事件,这个回调事件,然后又统一调用mct_controller_notify_hal_internal_event将事件通知给上层
static boolean mct_controller_notify_hal_internal_event(
mct_pipeline_t *pipeline, cam_event_type_t command)
{
mct_process_ret_t proc_ret;
struct v4l2_event *event;
cam_event_t cam_event;
int rc;
mct_controller_t *mct = NULL;
mm_camera_shim_event_handler_func evt_cb;
if (!pipeline) {
CLOGE(CAM_MCT_MODULE, "Pipeline ptr NULL");
return FALSE;
}
mct = pipeline->controller;
if (!mct) {
CLOGE(CAM_MCT_MODULE, "NULL mct_controller object.");
return FALSE;
}
cam_event.server_event_type = command;
cam_event.status = CAM_STATUS_SUCCESS;
回调,start_session调用vendor层时传递下来的回调
evt_cb = (mm_camera_shim_event_handler_func)mct->event_cb;
if (!evt_cb) {
CLOGE(CAM_MCT_MODULE, "Callback not registered");
return FALSE;
}
执行回调
rc = evt_cb(pipeline->session,&cam_event);
if (rc == FALSE) {
CLOGE(CAM_MCT_MODULE, "Failed to send callback cmd = %d", command);
return FALSE;
}
}
这里这个线程工作就完了,然后又会继续轮询数据,可能大家有个疑惑,轮询的源头,bus中的priority_queue中数据哪里来?当然是从kernel底层来了,当然也有可能是从vendor这里就有返回,比如启动session,完成后,就会直接往bus中post一个小小说完成了,进而发送到上层;这个数据会发送到hal层的evt thread线程,由这个线程发送到App上
bus thread小结
本文总结
为了更好的理解mct组成,首先要知道camera模块的硬件组成有哪些,camera许多硬件模块都对应了软件层的module;本文从两条线来阐述:
一条是初始化init过程,会依次初始化各个module模块
另一条是start session业务,会创建相关的通信结构体,controller、pipeline、bus、stream以及port和module等;
最后,start session会创建两个线程;
mct_controller_thread_run线程是数据从上到下的传递,它会贯通start session创建的相关结构体;
mct_bus_handler_thread_run则是数据从下到上的传递,是数据的回调过程
本文只是学习了mct整体架构的组成和运作逻辑部分,而关于camera更专业的地方,如图像调优、3A、turning则未深入查看了,鉴于本人水平有限,加之网上关于高通mct资料相对较少,只能摸索出这个名堂了!如有不对的,望指正!