qual_camera_video

来源:互联网 发布:java面试基础知识 编辑:程序博客网 时间:2024/05/29 08:29
/*******************************************
**********   qual_camera_stats CODE  WALK THROUTH  ************
*************************************************
********************************************/


//main函数在qcom\proprietary\mm-camera\mm-camera2\server-imaging\Server.c
int main(int argc, char *argv[])---->server_process_module_init会调用到下边的init数组

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},
};

我们这里关注stats_module_init函数

stats_module_init
    mct_module_create("stats");
    for{stats_mods_list[i].init_mod} //这里会call到sub module的init函数,如下sub module表
            ---->q3a_module_init
                                  mct_module_create("q3a");
                                  aec_module_init("aec"); //这三个是q3a的三个sub module
                                  awb_module_init("awb");
                                  af_module_init("af");



stats module 下有好多sub module,如下
static mct_module_init_name_t stats_mods_list[] = {
  { "q3a",  q3a_module_init,  q3a_module_deinit },
  { "afd",  afd_module_init,  afd_module_deinit },
  { "asd",  asd_module_init,  asd_module_deinit },
  { "is",   is_module_init,   is_module_deinit},
};





camera launch的时候stats_module_start_session会被调用到*****        //Stats_module.c (qcom\proprietary\mm-camera\mm-camera2\media-controller\modules\stats)
下边解释stats_module_start_session为什么会被call到
mm_camera_open    //Mm_camera.c (hardware\qcom\camera\qcamera2\stack\mm-camera-interface\src)
    open(dev_name, O_RDWR | O_NONBLOCK);导致camera_v4l2_open(struct file *filep)被调用  //Camera.c (drivers\media\platform\msm\camera_v2\camera)
camera_v4l2_open
    camera_pack_event(filep, MSM_CAMERA_NEW_SESSION, 0, -1, &event); //发送event,会调用到下边的函数
server_process_hal_event  函数中case MSM_CAMERA_NEW_SESSION:  mct_controller_new(modules, data->session_id, pipe_fd[1])
mct_controller_new(modules, data->session_id, pipe_fd[1])会调用到mct_pipeline_start_session--->mct_pipeline_modules_start--->mct_pipeline_start_session_thread----
---->module->start_session(为每一个module调用start_session动作,即调用/********stats_module_start_session*******/)




stats_module_start_session的调用过程
    /* Now need to create a new sink port */
    port = mct_port_create("stats_sink");  //这里只create了一个port ,因为这里stats只有一个入口,
    stats_module_sub_mod_start_session
    module->start_session     //这里的start_session可以是q3a_module.c的start_session----
------>q3a_module_start_session  //创建一个port,和三个子module的start_session
        mct_port_create("q3a_sink");
        private->aec_module->start_session(private->aec_module, sessionid);
        private->awb_module->start_session(private->awb_module, sessionid);
        private->af_module->start_session(private->af_module, sessionid);
        aec_port = aec_module_get_port(private->aec_module, sessionid);
        awb_port = awb_module_get_port(private->awb_module, sessionid);
        af_port  = af_module_get_port(private->af_module, sessionid);
        q3a_port_init(port, aec_port, awb_port, af_port,    //对这些port做init动作
    sub.sub_ports = NULL; //存放后边所有的port  
    stats_port_init(port, sessionid , sub.sub_ports)
        port->direction      = MCT_PORT_SINK; //port的方向
        caps.port_caps_type  = MCT_PORT_CAPS_STATS;
          mct_port_set_event_func(port, stats_port_event);     //这个function会用来做port跟port之间event的deliever跟receive
          mct_port_set_set_caps_func(port, stats_port_set_caps);
          mct_port_set_ext_link_func(port, stats_port_ext_link);  //port跟port做link的时候会用到
          mct_port_set_unlink_func(port, stats_port_unlink);
          mct_port_set_check_caps_reserve_func(port, stats_port_check_caps_reserve);
          mct_port_set_check_caps_unreserve_func(port, stats_port_check_caps_unreserve);


再看q3a的sub module 的start_session
aec_module_start_session
     mct_port_create("aec_sink");
     mct_module_add_port(module, port)



//如何get到这些port可以参考如下函数,最终结果是所有的port存在sub.sub_ports中
stats_module_get_sub_ports





message 的handle    (upstream跟downstream)
port跟port之间event的都会调用到stats_port_event,上边有说到,在stats_port.c中
stats_port_event  //有两个方向的event,MCT_EVENT_UPSTREAM和MCT_EVENT_DOWNSTREAM
    case MCT_EVENT_UPSTREAM
    case MCT_EVENT_DOWNSTREAM:
        这里继续根据event的type和ctrl的type来进行不同的处理
        最终会调用到这,把event进一步发送到sub module的port_event(),如q3a_port_event(),会送到所有的port,如果不合适可以不处理
        mct_list_traverse((mct_list_t *)private->sub_ports, stats_port_send_event_downstream, &port_event);
        
        
q3a_port_event()
    case MCT_EVENT_UPSTREAM
    case MCT_EVENT_DOWNSTREAM:    
        q3a_port_send_event_downstream(port, event)
            MCT_PORT_EVENT_FUNC(private->aec_port)(private->aec_port, event);   //调用到aec的port的event(aec_port_event)
            MCT_PORT_EVENT_FUNC(private->awb_port)(private->awb_port, event);
            MCT_PORT_EVENT_FUNC(private->af_port)(private->af_port, event);


aec_port_event
    case MCT_EVENT_UPSTREAM
    case MCT_EVENT_DOWNSTREAM:
        aec_port_proc_downstream_event(port, event);

af_port_event
    af_port_handle_module_event(port, mod_evt);
        q3a_af_thread_en_q_msg(af_port->thread_data, af_msg);  会调用到q3a_thread如下
af_thread_handler  //Q3a_thread.c (qcom\proprietary\mm-camera\mm-camera2\media-controller\modules\stats\q3a)
    case MSG_BF_STATS:af->af_obj->af_ops.process(msg->u.stats, &(af->af_obj->output),
            af->af_cb(& (af->af_obj->output), af->af_port);  ----->af_port_callback(每个port都会有自己的callback函数)
af_port_callback
    event.direction = MCT_EVENT_UPSTREAM;    改变传送方向后,它会向down的所有port传送此event
    event.type = MCT_EVENT_MODULE_EVENT;
    event.u.module_event.type = MCT_EVENT_MODULE_STATS_AF_UPDATE;



stats_port_ext_link      //port跟port做link的时候会用到   即  调用mct_stream_link_modules(stream, sensor, iface, isp, pproc, imglib,)link这些module的时候;



event.direction = MCT_EVENT_UPSTREAM;   //event传送的方向   改变传送方向后,它会向up的所有port传送此event
event.type = MCT_EVENT_MODULE_EVENT;     //event的类型
event.u.module_event.type = MCT_EVENT_MODULE_STATS_AF_UPDATE; //event的模块

q3a_port_event
    case MCT_EVENT_UPSTREAM:   q3a_port_proc_upstream_mod_event(port,event);
                    mct_port_event_to_peer(); //送到upstream的下一个port,从框图可以看到下一个port是stats——port,所以调用stats_port_event()
                        






AF Region of Internet(Rol)  Handing example
从hal传过来,类型为downstream     set_param(为ctrl event)
从port过来,所以看stats_port_event()函数看起
stats_port_event
    case MCT_EVENT_DOWNSTREAM:
        if (event->type == MCT_EVENT_CONTROL_CMD &&event->u.ctrl_event.type == MCT_EVENT_CONTROL_SET_PARM)
            stats_port_proc_downstream_set_parm(port, event, &sent);
                case CAM_INTF_PARM_AF_ROI:处理完成后,继续送到 q3a_port.c中的event处理
总体downstream处理流程,stats_port_event  ---->   q3a_port_event  ----> af_port_event --->process  --->q3a_af_thread_en_q_msg ---->af_port_event----->  q3a_port_event


所有的q_msg都会有一个thread 来hand它
比如:afd_thread_handler,这些thread在asd_port_ext_link(连接两个port)的时候被create    "asd_port_start_threads()"


isp相关的event
isp_port.c
port_isp_event_func--->port_isp_module_event






源码相关目录
mm_camera/mm-camera2/media-controller/modules/stats/



















/******************************************************************
**********   VIDEO QCAMERA SERVER AND MCTL CODE WALK THROUGH  ************
************************************************************
*****************************************************************/
MCTL:media controller



open:
main       //Server.c (qcom\proprietary\mm-camera\mm-camera2\server-imaging)
    open(dev_name, O_RDWR | O_NONBLOCK);
    server_process_module_init()
        modules_list[i].init_mod
    server_process_hal_event(&event);
        case MSM_CAMERA_NEW_SESSION
            mct_controller_new(modules, data->session_id, pipe_fd[1])
                mct_pipeline_start_session(mct->pipeline)
                pthread_create(&tid, NULL, mct_controller_thread_run, mct)
                do {...}while(1);




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},
}




query_cap:
mct_controller_proc_serv_msg_internal
    case SERV_MSG_HAL:
        pipeline->process_serv_msg(&msg->u.hal_msg,pipeline);//这里的process_serv_msg被赋值为mct_pipeline_process_serv_msg

mct_pipeline_process_serv_msg:
    case MSM_CAMERA_GET_PARM:
        mct_pipeline_process_get(data, pipeline);
            case MSM_CAMERA_PRIV_QUERY_CAP:
                mct_pipeline_populate_query_cap_buffer(pipeline); //fill up HAL's query buffer




close:
server_process_hal_event
    case MSM_CAMERA_DEL_SESSION:
        mct_controller_destroy(data->session_id)
            mct_pipeline_stop_session(mct->pipeline);
            mct_pipeline_destroy(mct->pipeline);


set_format:
mct_pipeline_process_serv_msg
    case MSM_CAMERA_SET_PARM:
        mct_pipeline_process_set(data, pipeline);
            case CAM_PRIV_STREAM_INFO_SYNC:
                MCT_STREAM_LINK(stream)----->mct_stream_start_link---->mct_stream_link_modules(stream, sensor, iface, isp);------>mct_module_link----->



stream_on:
mct_pipeline_process_set
    case MSM_CAMERA_PRIV_STREAM_ON:
        mct_pipeline_pack_event(MCT_EVENT_CONTROL_CMD,
        pipeline->send_event(pipeline, data->stream_id, &cmd_event);
            mct_stream_send_event
                src_module->process_event(src_module, event);


















typedef boolean (*mct_port_event_func)(mct_port_t *port, mct_event_t *event);

typedef mct_list_t *(*mct_port_int_link_func)(unsigned int identity,
  mct_port_t *port);

typedef boolean (*mct_port_ext_link_func)(unsigned int identity,
 mct_port_t* port, mct_port_t *peer);

typedef void (*mct_port_unlink_func)(unsigned int identity,
 mct_port_t *port, mct_port_t *peer);

typedef boolean (*mct_port_set_caps_func)(mct_port_t *port,
  mct_port_caps_t *caps);

typedef boolean (*mct_port_check_caps_reserve_func)
  (mct_port_t *port, void *peer_caps, void *stream_info);

typedef boolean (*mct_port_check_caps_unreserve_func)
(mct_port_t *port, unsigned int identity);


module中的函数
struct _mct_module {
  mct_object_t      object;
  mct_list_t        *type_list;
  mct_list_t        *srcports;
  unsigned short    numsrcports;
  mct_list_t        *sinkports;
  unsigned short    numsinkports;
  void              *module_private;

  /* virtual functions - MUST be implemented by each module */
  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;
};

#define mct_module_set_process_event_func(mod,f)  \
  MCT_MODULE_CAST(mod)->process_event = f

#define mct_module_set_set_mod_func(mod,f)  \
  MCT_MODULE_CAST(mod)->set_mod = f

#define mct_module_set_query_mod_func(mod,f)  \
  MCT_MODULE_CAST(mod)->query_mod = f

#define mct_module_set_request_new_port_func(mod,f)  \
  MCT_MODULE_CAST(mod)->request_new_port = f

#define mct_module_set_start_session_func(mod,f)  \
  MCT_MODULE_CAST(mod)->start_session = f

#define mct_module_set_stop_session_func(mod,f)  \
  MCT_MODULE_CAST(mod)->stop_session = f







polling and types messages handled    //以下在server.c的main函数中
    RD_DS_FD_HAL用来处理mapping buffer的socket messages
    RD_FD_HAL  用来处理kernel的node update
    RD_PIPE_FD_MCT 用来处理mct的update


buffer manager:
buffer type: matedata 和frame buffers
main  //Server.c (qcom\proprietary\mm-camera\mm-camera2\server-imaging)
    case RD_DS_FD_HAL:
        server_process_hal_ds_packet
            mct_controller_proc_serv_msg
                case SERV_MSG_DS:
                    session = serv_msg->u.ds_msg.session;
            同时mct_controller_proc_serv_msg_internal会被调用
                case SERV_MSG_DS:   pipeline->map_buf(&msg->u.ds_msg, pipeline); //这里会调用到mct_pipeline_map_buf()


mct_pipeline_map_buf()
    stream->map_buf(msg, stream);//这里会调用 mct_stream_map_buf---->mmap();



message passing
post 一个消息到bus  通过函数mct_module_post_bus_msg




msg_bus_post_msg
    case MCT_BUS_MSG_ISP_SOF:
        
mct_stream_metadata_bus_msg//mct_stream.c中
    if (MCT_BUS_MSG_ISP_SOF == bus_msg->type)
        ioctl(stream->metadata_stream.buf_mgr_dev_fd,VIDIOC_MSM_BUF_MNGR_BUF_DONE
        ioctl(stream->metadata_stream.buf_mgr_dev_fd,VIDIOC_MSM_BUF_MNGR_GET_BUF


debug point:
mct_pipeline_process_set()//traceing stream information  or    tracking command
mct_pipeline.c  mct_pipeline_process_set--->CDBG_HIGH("%s: stream_type = %d\n", __func__, stream->streaminfo.stream_type);
mct_pipeline.c  mct_pipeline_process_set--->CDBG_HIGH("%s:command=%x", __func__, data->command);   //what message is goingon















/*******************************************************
          MCTL POSTPROC CODE WALKTHROUGH
***********************************************************/
vi server/core/config/config_v2.c
/STREAM_ON
搜到函数config_MSM_V4L2_STREAM_ON
config_MSM_V4L2_STREAM_ON
     config_v2_pp_topology
          config_pp_acquire_mctl_node  //preparing mctl pp node    config_pp.c
               mctl_pp_node_open
               mctl_pp_node_prepare    //mctl_pp_node.c
                    mctl_pp_node_alloc_buf
                    mctl_pp_node_reg_buf
                    mctl_pp_node_streamon
                    
               
          config_update_stream_info    //updating mctl inst
          config_pp_setup_pp_topology  //set video mode to mctl_pp
                       cmd.src_cfg.parms.image_mode =
                         ctrl->curr_output_info.output[SECONDARY].stream_type;
                       cmd.src_cfg.parms.path =
                         ctrl->curr_output_info.output[SECONDARY].path;
                       cmd.src_cfg.parms.format =
                         ctrl->curr_output_info.output[SECONDARY].format;
                       cmd.src_cfg.parms.image_width =
                         ctrl->curr_output_info.output[SECONDARY].image_width +
                         ctrl->curr_output_info.output[SECONDARY].extra_pad_width;
                       cmd.src_cfg.parms.image_height =
                         ctrl->curr_output_info.output[SECONDARY].image_height +
                         ctrl->curr_output_info.output[SECONDARY].extra_pad_height;
                       cmd.src_cfg.parms.plane[0] =
                         ctrl->curr_output_info.output[SECONDARY].plane[0];
                       cmd.src_cfg.parms.plane[1] =
                         ctrl->curr_output_info.output[SECONDARY].plane[1];
                       cmd.cmd_type = QCAM_MCTL_CMD_CONFIG_SRC;   //重点
                       mctl_pp_cmd(&ctrl->mctl_pp_ctrl[pipeline_idx], &cmd);---->mctl_pp_proc_config_src
                       cmd.cmd_type = QCAM_MCTL_CMD_CONFIG_DEST;   //重点
                       mctl_pp_cmd(&ctrl->mctl_pp_ctrl[pipeline_idx], &cmd);
          config_pp_acquire_hw         //acquiring hardware,下边会分析
          config_pp_send_stream_on     //Sending START CMD to VFE







     cmd.cmd_type = QCAM_MCTL_CMD_CONFIG_SRC;
     mctl_pp_cmd(&ctrl->mctl_pp_ctrl[pipeline_idx], &cmd);
<----->
mctl_pp_proc_config_src     //Mctl_pp.c (qcom\proprietary\mm-camera\server\core\mctl)
     pp_ctrl->src[src_cfg->src_idx].ops->config_src(poll_cb, src_cfg);
             .config_src = mctl_pp_src_config, //mctl_pp_src.c


     cmd.cmd_type = QCAM_MCTL_CMD_CONFIG_DEST;
     mctl_pp_cmd(&ctrl->mctl_pp_ctrl[pipeline_idx], &cmd);
<----->
mctl_pp_proc_config_dest   //Mctl_pp.c (qcom\proprietary\mm-camera\server\core\mctl)
     pp_ctrl->src[dest_cfg->src_idx].ops->config_dest(poll_cb, dest_cfg);
          .config_dest = mctl_pp_src_config_dest,
                dest->ops->config_dest(poll_cb, dest_cfg);
                     .config_dest = mctl_pp_dest_config, //Mctl_pp_dest.c (qcom\proprietary\mm-camera\server\core\mctl)






acquire_hw调用过程:
config_pp_acquire_hw //Config_pp.c (qcom\proprietary\mm-camera\server\core\config)
     mctl_pp_cmd(&ctrl->mctl_pp_ctrl[pipeline_idx], &pp_cmd);//Mctl_pp.c mm-camera\server\core\mctl
          pp_ctrl->src[i].ops->acquire_hw((void *)poll_cb, i, j);
               mctl_pp_src_acquire_hw
               mctl_pp_dest_acquire_hw
                    mctl_pp_acquire_vpe(poll_cb, dest);   //Mctl_pp_vpe_cmd.c (qcom\proprietary\mm-camera\server\core\mctl)
                    mctl_pp_acquire_c2d(poll_cb, dest);   //Mctl_pp_c2d_cmd.c (qcom\proprietary\mm-camera\server\core\mctl)
                         c2d_interface_create(c2d_mod_ops)
                         pipe(fds);
                         c2d_mod_ops->init(c2d_mod_ops->handle, &mctl_ops, fds)
                         mctl_pp_add_poll_fd(poll_cb, &poll_fd, src->my_idx, dest->my_idx);
                         
                         
                         





streamon调用过程:
mctl_pp_stream_on_off_notify
     pp_ctrl->src[i].ops->streamon((void *)poll_cb, i, j);
          mctl_pp_src_streamon
               mctl_pp_src_enable(poll_cb, 1, src->data.path);
          mctl_pp_dest_streamon
               case MCTL_PP_C2D_CROP_2D:hw_ops->process(hw_ops->handle, C2D_EVENT_START, &init_data);
                    ---->c2d_event_start
                            c2d_get_frame_format(init_data->src_format);
                            c2d_create_default_yuv_surface(ctrl, &ctrl->persist_params.dst.surfaceDef,    //
                            cam_list_init(&(ctrl->g_list.list));
                            ctrl->state = C2D_STATE_START;
                            CDBG("%s: ctrl->state = %d", __func__, ctrl->state);
    
0 0
原创粉丝点击