camera daemon进程

一、守护进程启动包含的路径文件
1) 确定daemon进程编译路径
代码路径:vendor/qcom/proprietary/mm-camera/Android.mk
概述:确定生成mm-qcamera-daemon的路径
1
BUILD_SERVER := false
2
BUILD_SERVER_BOARD_PLATFORM_LIST := msm7627a
3
#BUILD_SERVER_BOARD_PLATFORM_LIST += msm7630_surf
4
#BUILD_SERVER_BOARD_PLATFORM_LIST += msm7630_fusion
5
BUILD_SERVER_BOARD_PLATFORM_LIST += msm8660
6
#BUILD_SERVER_BOARD_PLATFORM_LIST += msm8960
7
#BUILD_SERVER_BOARD_PLATFORM_LIST += msm8974
8
#BUILD_SERVER_BOARD_PLATFORM_LIST += msm8226
9
#BUILD_SERVER_BOARD_PLATFORM_LIST += msm8610
10
ifeq ($(call is-board-platform-in-list,$(BUILD_SERVER_BOARD_PLATFORM_LIST)),true)
11
  BUILD_SERVER := true
12
  USE_SERVER_TREE := -D_V4L2_BASED_CAM_
13
endif
14
15
BUILD_MM_CAMERA2 := false
16
BUILD_MM_CAMERA2_BOARD_PLATFORM_LIST := msm8960
17
BUILD_MM_CAMERA2_BOARD_PLATFORM_LIST += msm8974
18
BUILD_MM_CAMERA2_BOARD_PLATFORM_LIST += msm8226
19
BUILD_MM_CAMERA2_BOARD_PLATFORM_LIST += msm8610
20
BUILD_MM_CAMERA2_BOARD_PLATFORM_LIST += msm8916
21
BUILD_MM_CAMERA2_BOARD_PLATFORM_LIST += msm8909
22
ifeq ($(call is-board-platform-in-list,$(BUILD_MM_CAMERA2_BOARD_PLATFORM_LIST)),true)
23
  BUILD_MM_CAMERA2 := true
24
endif
25
26
/***由此可以得知BUILD_SERVER=flase BUILD_MM_CAMERA2 =true ***/
27
28
  ifeq ($(BUILD_SERVER), true)
29
    include $(MY_PATH)/apps/Android.mk
30
    include $(MY_PATH)/server/Android.mk
31
  else ifeq ($(BUILD_MM_CAMERA2), true)
32
    include $(MY_PATH)/mm-camera2/Android.mk/***包含的路径是vendor/qcom/proprietary/mm-camera/mm-camera2/Android.mk***/
33
  else
34
    include $(MY_PATH)/apps/Android.mk
35
    include $(MY_PATH)/targets/Android.mk
36
  endif
代码路径:vendor/qcom/proprietary/mm-camera/mm-camera2/server-imaging/Android.mk
概述:确定生成 mm-qcamera-daemon的包含的文件
1
LOCAL_MODULE:= mm-qcamera-daemon    LOCAL_MODULE模块必须定义,以表示Android.mk中的每一个模块。名字必须唯一且不包含空格。
2
LOCAL_SRC_FILES:= server.c  server_process.c
3
4
LOCAL_C_INCLUDES:=$(LOCAL_PATH)/******可以知道守护进程处理的文件路径范围******/
5
LOCAL_C_INCLUDES+= $(LOCAL_PATH)/../includes/
6
LOCAL_C_INCLUDES+= $(LOCAL_PATH)/../media-controller/mct/bus/
7
LOCAL_C_INCLUDES+= $(LOCAL_PATH)/../media-controller/mct/controller/
8
LOCAL_C_INCLUDES+= $(LOCAL_PATH)/../media-controller/mct/object/
9
LOCAL_C_INCLUDES+= $(LOCAL_PATH)/../media-controller/includes/
10
LOCAL_C_INCLUDES+= $(LOCAL_PATH)/../media-controller/mct/tools/
11
LOCAL_C_INCLUDES+= $(LOCAL_PATH)/../media-controller/mct/event/
12
LOCAL_C_INCLUDES+= $(LOCAL_PATH)/../media-controller/mct/pipeline/
13
LOCAL_C_INCLUDES+= $(LOCAL_PATH)/../media-controller/mct/stream/
14
LOCAL_C_INCLUDES+= $(LOCAL_PATH)/../media-controller/mct/module/
15
LOCAL_C_INCLUDES+= $(LOCAL_PATH)/../media-controller/mct/port/
16
LOCAL_C_INCLUDES+= $(LOCAL_PATH)/../media-controller/mct/debug/
17
18
19
LOCAL_SHARED_LIBRARIES:= libcutils libdl liboemcamera \   /***库文件路径:out\target\product\msm8909\system\vendor\lib\libmmcamera2_stats_modules.so
20
                                   libmmcamera2_stats_modules \
21
                                   libmmcamera2_iface_modules \
22
                                   libmmcamera2_isp_modules \
23
                                   libmmcamera2_sensor_modules \
24
                                   libmmcamera2_pproc_modules \
25
                                   libmmcamera2_imglib_modules
代码路径:device/qcom/msm8909/init.target.rc
概述:启动mm-qcamera-daemon服务
1
#start camera server as daemon
2
service qcamerasvr /system/bin/mm-qcamera-daemon
3
    class late_start
4
    user camera
5
    group camera system inet input graphics
代码路径:device/qcom/common/rootdir/etc/init.qcom.rc
概述:为域套接字的通信创建文件
1
#Create folder for mm-qcamera-daemon
2
    mkdir /data/camera 0770 media camera
二、守护进程具体的内容
1) 初始化模块
1
int main(int argc, char *argv[])
2
{
3
  mct_list_t                *listen_fd_list = NULL;
4
  read_fd_info_t            *hal_fd = NULL, *hal_ds_fd = NULL, *mct_fds = NULL;
5
  server_select_fds_t       select_fds;
6
  struct v4l2_event         event;
7
  /* 1. find server node name and open the node */
8
  get_server_node_name(serv_hal_node_name;
9
  hal_fd->fd[0] = open(dev_name, O_RDWR | O_NONBLOCK);/****dev_name = dev/video0***/
10
  hal_fd->type = RD_FD_HAL;
11
  listen_fd_list = mct_list_append(listen_fd_list, hal_fd, NULL, NULL);/******/
12
  property_get("cameradaemon.SaveMemAtBoot", savemem, "0");
13
  enabled_savemem = atoi(savemem);
14
  /* 2. after open node, initialize modules */
15
  server_process_module_sensor_init();
16
  /***
17
  *server_process_module_sensor_init只是初始化了modules_list[0].init_mod(modules_list[0].name);即sensor
18
  ***/
19
  if (enabled_savemem != 1) {
20
    if (server_process_module_init() == FALSE);
21
     /***
22
     *for (i = 1; i < (int)(sizeof(modules_list)/sizeof(mct_module_init_name_t)); i++)
23
     *所以会初始化iface、isp、stats、pproc、imglib这五个模块
24
     ***/
25
    }
26
   /* Subcribe V4L2 event */
27
  subscribe.type = MSM_CAMERA_V4L2_EVENT_TYPE;
28
  ioctl(hal_fd->fd[0], VIDIOC_SUBSCRIBE_EVENT, &subscribe);/***函数分析1、2***/
29
  select_fds.select_fd = hal_fd->fd[0];
30
  CDBG("CAMERA_DAEMON:waiting for camera to open\n");
31
  do {
32
       FD_ZERO(&(select_fds.fds));
33
       mct_list_traverse(listen_fd_list, server_reset_select_fd, &select_fds); /***函数分析3***/
34
       ret = select(select_fds.select_fd + 1, &(select_fds.fds), NULL, NULL, NULL);  
35
       if (ret > 0)
36
        {
37
           mct_list_t     *find_list;
38
           read_fd_info_t *fd_info;
39
           find_list = mct_list_find_custom(listen_fd_list, &(select_fds.fds), server_check_listen_fd);
40
            /***通过select_fds.fds中被置1的fd找到对应的链表***/
41
           fd_info = (read_fd_info_t *)find_list->data;
42
           switch (fd_info->type) {
43
           case RD_FD_HAL: {
44
             if (ioctl(fd_info->fd[0], VIDIOC_DQEVENT, &event) < 0)
45
                continue;
46
           /* server process HAL event:
47
            *   1. if it returns success, it means the event message has been posted to MCT, don't need to send CMD ACK back to kernel
48
            *      immediately, because MCT will notify us after process;
49
            *
50
            *   2. if it returns failure, it means the event message was not posted to MCT successfully, hence we need to send CMD ACK back
51
            *      to kernel immediately so that HAL thread which sends this event can be blocked.
52
            */
53
              proc_ret = server_process_hal_event(&event);
54
            break;
55
          case RD_DS_FD_HAL:
56
          /* server process message sent by HAL through Domain Socket */
57
              proc_ret = server_process_hal_ds_packet(fd_info->fd[0],fd_info->session);
58
            break;
59
          case RD_PIPE_FD_MCT:
60
          /* server process message sent by media controller through pipe: */
61
            proc_ret = server_process_mct_msg(fd_info->fd[0],  fd_info->session);
62
            break;
63
          default:
64
             continue;
65
        } /* switch (fd_info->type) */    
66
    }while (1);
67
}
68
  

函数分析:
1) 代码路径:vendor/qcom/proprietary/mm-camera/mm-camera2/server-imaging/server_process.c
函数:server_process_module_init();
概述:对modules_list数组中的模块进行初始化
1
static mct_module_init_name_t modules_list[] = {
2
  {"sensor", module_sensor_init,   module_sensor_deinit, NULL},
3
  {"iface",  module_iface_init,   module_iface_deinit, NULL},
4
  {"isp",    module_isp_init,      module_isp_deinit, NULL},
5
  {"stats",  stats_module_init,    stats_module_deinit, NULL},
6
  {"pproc",  pproc_module_init,    pproc_module_deinit, NULL},
7
  {"imglib", module_imglib_init, module_imglib_deinit, NULL},
8
};
2) 代码路径:kernel/drivers/media/platform/msm/camera_v2/camera/camera.c
函数:int camera_init_v4l2(struct device *dev, unsigned int *session);
1
int camera_init_v4l2(struct device *dev, unsigned int *session)
2
{
3
    struct msm_video_device *pvdev;
4
    struct v4l2_device *v4l2_dev;
5
    pvdev->vdev->release  = video_device_release;
6
    pvdev->vdev->fops     = &camera_v4l2_fops;
7
    pvdev->vdev->ioctl_ops = &camera_v4l2_ioctl_ops;
8
    pvdev->vdev->minor     = -1;
9
    pvdev->vdev->vfl_type  = VFL_TYPE_GRABBER;
10
    rc = video_register_device(pvdev->vdev, VFL_TYPE_GRABBER, -1);
11
}
函数ioctl(hal_fd->fd[0], VIDIOC_SUBSCRIBE_EVENT, &subscribe);打开的文件是dev/video0,所以ioctl调用是这video_register_device注册的ioctl_ops。
这里主要关注的两个函是
函数:static unsigned int  camera_v4l2_poll(struct file *filep,   struct poll_table_struct *wait)
作用:select函数通过设备文件的poll函数来检查是否可读、可写。(用户空间的select系统调用对应内核中的poll函数)
参考文章: http://blog.csdn.net/waldmer/article/details/18735517  关于select的调用方法
                   http://blog.csdn.net/gtkknd/article/details/7229576   关于返回值的解析
1
static unsigned int camera_v4l2_poll(struct file *filep,   struct poll_table_struct *wait)
2
{
3
    int rc = 0;
4
    struct camera_v4l2_private *sp = fh_to_private(filep->private_data);
5
    if (sp->is_vb2_valid == 1)
6
        rc = vb2_poll(&sp->vb2_q, filep, wait);
7
8
    poll_wait(filep, &sp->fh.wait, wait);
9
    if (v4l2_event_pending(&sp->fh))
10
        rc |= POLLPRI;
11
    return rc;
12
}
13
在函数camera_v4l2_poll()中的v4l2_event_pending()函数返回的是fh->navailable;
1
int v4l2_event_pending(struct v4l2_fh *fh)
2
{
3
    return fh->navailable;
4
}
函数:static void __v4l2_event_queue_fh(struct v4l2_fh *fh, const struct v4l2_event *ev,  const struct timespec *ts)
作用: fh->sequence++;
函数:static int __v4l2_event_dequeue(struct v4l2_fh *fh, struct v4l2_event *event)
作用: fh->sequence--;
例如MSM_CAMERA_NEW_SESSION的过程
HAL层:调用int32_t mm_camera_open(mm_camera_obj_t *my_obj)打开camera
kernel层:static int camera_v4l2_open(struct file *filep)  ---->  camera_pack_event(filep, MSM_CAMERA_NEW_SESSION, 0, -1, &event);---->  
                  rc = msm_post_event(&event, MSM_POST_EVT_TIMEOUT);---->  v4l2_event_queue(vdev, event);----> __v4l2_event_queue_fh(fh, ev, &timestamp);
                  ----> fh->sequence++; ---> static unsigned int camera_v4l2_poll(struct file *filep,  struct poll_table_struct *wait) ---> rc |= POLLPRI; POLLPRI表示 可读
vendor层:ret = select(select_fds.select_fd + 1, &(select_fds.fds), NULL, NULL, NULL)---> ioctl(fd_info->fd[0], VIDIOC_DQEVENT, &event)---> fh->sequence--;
                   通过select系统调用获得kernel的fd的状态改变,从而进行事件的处理,同时调用 VIDIOC_DQEVENT使得fh->sequence--

3)代码路径:vendor/qcom/proprietary/mm-camera/mm-camera2/media-controller/mct/tools/mct_list.c
函数:boolean mct_list_traverse(mct_list_t *mct_list, mct_list_traverse_func traverse,  void *user_data);
函数:mct_list_traverse(listen_fd_list, server_reset_select_fd, &select_fds);
作用:Traverse whole list
1
boolean mct_list_traverse(mct_list_t *mct_list, mct_list_traverse_func traverse, void *user_data)
2
{
3
  mct_list_t *temp_list;
4
  uint32_t num;
5
6
  if (mct_list && traverse) {
7
    if (traverse(mct_list->data, user_data) == FALSE)
8
      return FALSE;
9
10
    num = mct_list->next_num;
11
    if (num > 0 && mct_list->next) {
12
      temp_list = mct_list->next[0];
13
      while (num--) {
14
        mct_list_traverse(temp_list, traverse, user_data);/***递归地遍历执行traverse(mct_list->data, user_data)函数***/
15
        temp_list++;
16
      }
17
    }
18
  }
19
20
  return TRUE;
21
}
函数:static boolean server_reset_select_fd(void *data, void *user_data)
作用:
1
static boolean server_reset_select_fd(void *data, void *user_data)
2
{
3
  read_fd_info_t      *fd_info  = (read_fd_info_t *)data;
4
  server_select_fds_t *selected = (server_select_fds_t *)user_data;
5
  FD_SET(fd_info->fd[0], &(selected->fds)); /***FD_SET(int fd, fd_set *fdset);  将fd加入set集合***/
6
  selected->select_fd = MTYPE_MAX(selected->select_fd, fd_info->fd[0]);/***FD_SET(int fd, fd_set *fdset);  将fd加入set集合***/
7
8
  return TRUE;
9
}
10
Camera daemon handles the following types of domain socket messages:
    域套接字
  消息类型:
   Buffer mapping –Handled via type RD_DS_FD_HAL 对应于  hal_ds_fd->fd[0]
   消息来源:     
      hal_ds_fd->session = proc_ret.new_session_info.session_idx;
      hal_ds_fd->fd[0] = proc_ret.new_session_info.hal_ds_fd;/***域套接字***/
      hal_ds_fd->type = RD_DS_FD_HAL;
   VIDIOC_SUBSCRIBE_EVENT
   消息类型:
       Video node updates from kernel –Handled via type RD_FD_HAL 对应于 hal_fd->fd[0]
   消息来源:
        hal_fd->fd[0] = open(dev_name, O_RDWR | O_NONBLOCK); /****dev_name = dev/video0***/
        hal_fd->type = RD_FD_HAL;
       ioctl(hal_fd->fd[0], VIDIOC_SUBSCRIBE_EVENT, &subscribe)
   管道
   消息类型:
      Updates from MCT (over Unix pipe) –Handled via type RD_PIPE_FD_MCT  对应于 mct_fds->fd[0]
   消息来源:
      mct_fds->session = proc_ret.new_session_info.session_idx;
      mct_fds->fd[0] = proc_ret.new_session_info.mct_msg_rd_fd;/***管道***/
      mct_fds->fd[1] = proc_ret.new_session_info.mct_msg_wt_fd;/***管道***/
      mct_fds->type = RD_PIPE_FD_MCT;
通过下面三个函数将三个不同类型的fd全部添加到 listen_fd_list这个链表中,最后通过mct_list_traverse(listen_fd_list, server_reset_select_fd, &select_fds);获取最大的 fd作为select函数的第一个参数。
listen_fd_list = mct_list_append(listen_fd_list,hal_ds_fd, NULL, NULL)
|---> mct_list_t* mct_list_append(mct_list_t *mct_list, void *data, void *appendto, mct_list_find_func list_find)
      |---> new_list = mct_list_new(data);

listen_fd_list = mct_list_append(listen_fd_list, mct_fds, NULL, NULL)
|---> mct_list_t* mct_list_append(mct_list_t *mct_list, void *data, void *appendto, mct_list_find_func list_find)
      |---> new_list = mct_list_new(data);

listen_fd_list = mct_list_append(listen_fd_list, hal_fd, NULL, NULL)
|---> mct_list_t* mct_list_append(mct_list_t *mct_list, void *data, void *appendto, mct_list_find_func list_find)
      |---> new_list = mct_list_new(data);
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值