我是靠谱客的博主 高挑康乃馨,最近开发中收集的这篇文章主要介绍解析高通vendor层mct框架解析高通vendor层mct框架,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

解析高通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模块内部,

  1. 首先会创建mct_module_t结构体,再次创建sensor模块的module_sensor_ctrl_t结构体,前者是mct所有module的共性部分结构体,后者每个module不同的结构体,他们之间也有引用关系;
  2. 在sensor中首先会open其驱动层/dev/video,然后找到其下面的sub_dev如actuator、etc等等,并将他们的信息写入到module_sensor_ctrl_t结构体中
  3. 然后会使用mct_list_traverse函数多次遍历module_sensor_ctrl_t结构体中的子设备,执行其初始化、创建管理器等
  4. mct_module根据自己内部的子设备信息中的stream,创建port,然后加入到mct_module的srcport里面去
  5. 最后将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为例:

  1. 根据传入的session id,查找到相关的sensor_bundle设备信息
  2. 创建一个线程,循环poll管道,读取来自kernel或者sensor module的消息
  3. 如果消息类型是自动对焦,则把消息发送到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 %dn", 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 小结

到这里,终于把线程中大部分任务看完了;总的来说:

  1. 取mct_controller中server_cmd数据处理
  2. 分析参数数据,然后依次交给pipeline --> stream -> module -> port处理
  3. 设置相关的状态变量
    在这里插入图片描述
    如上图,事件最终在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资料相对较少,只能摸索出这个名堂了!如有不对的,望指正!

最后

以上就是高挑康乃馨为你收集整理的解析高通vendor层mct框架解析高通vendor层mct框架的全部内容,希望文章能够帮你解决解析高通vendor层mct框架解析高通vendor层mct框架所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(51)

评论列表共有 0 条评论

立即
投稿
返回
顶部