Camera安卓源码-高通mm_camera架构剖析

主要涉及三方面:
1. Camera open
2. Camera preview
3. Camera capture

1. Camera Open

mm_camera&mm_camera_open()

首先,mm_camera层用一个结构体去表示从底层获取的camera对象,这个结构体叫做mm_camera_obj
如下结构体所示,mm_camera对象包含了两个线程:
1. mm_camera_poll_thread_t
2. mm_camera_cmd_thread_t
还包含了一个用于存储自身所拥有的Channel的数组:
mm_channel_t ch[MM_CAMERA_CHANNEL_MAX]

typedef struct mm_camera_obj {
    uint32_t my_hdl;
    int ref_count;
    int32_t ctrl_fd;
    int32_t ds_fd; /* domain socket fd */
    pthread_mutex_t cam_lock;
    pthread_mutex_t cb_lock; /* lock for evt cb */
    mm_channel_t ch[MM_CAMERA_CHANNEL_MAX];
    mm_camera_evt_obj_t evt;
    mm_camera_poll_thread_t evt_poll_thread; /* evt poll thread */
    mm_camera_cmd_thread_t evt_thread;       /* thread for evt CB */
    mm_camera_vtbl_t vtbl;

    pthread_mutex_t evt_lock;
    pthread_cond_t evt_cond;
    mm_camera_event_t evt_rcvd;

    pthread_mutex_t msg_lock; /* lock for sending msg through socket */
    uint32_t sessionid; /* Camera server session id */
} mm_camera_obj_t;

而在camer open的过程中,kernel层以上最终会调用到mm_camera_open(mm_camera_obj_t *my_obj)方法。该方法是在mm_camera_interface中被调用的。

int32_t camera_open(uint8_t camera_idx, mm_camera_vtbl_t **camera_vtbl)
{
    ......
    mm_camera_obj_t *cam_obj = NULL;

    cam_obj = (mm_camera_obj_t *)malloc(sizeof(mm_camera_obj_t));
    if(NULL == cam_obj) {
        pthread_mutex_unlock(&g_intf_lock);
        LOGE("no mem");
        return -EINVAL;
    }

    /* initialize camera obj */
    memset(cam_obj, 0, sizeof(mm_camera_obj_t));
    cam_obj->ctrl_fd = -1;
    cam_obj->ds_fd = -1;
    cam_obj->ref_count++;
    cam_obj->my_hdl = mm_camera_util_generate_handler(camera_idx);
    cam_obj->vtbl.camera_handle = cam_obj->my_hdl; /* set handler */
    cam_obj->vtbl.ops = &mm_camera_ops;
    pthread_mutex_init(&cam_obj->cam_lock, NULL);
    /* unlock global interface lock, if not, in dual camera use case,
      * current open will block operation of another opened camera obj*/
    pthread_mutex_lock(&cam_obj->cam_lock);
    pthread_mutex_unlock(&g_intf_lock);

    rc = mm_camera_open(cam_obj);
    ......
}

也就是通过mm_camera_open方法去填充这个mm_camera_obj的结构体,再供上层使用。

接下来进入mm_camera_open方法体:

    LOGD("Launch evt Thread in Cam Open");
    snprintf(my_obj->evt_thread.threadName, THREAD_NAME_SIZE, "CAM_Dispatch");
    mm_camera_cmd_thread_launch(&my_obj->evt_thread,
                                mm_camera_dispatch_app_event,
                                (void *)my_obj);

    /* launch event poll thread
     * we will add evt fd into event poll thread upon user first register for evt */
    LOGD("Launch evt Poll Thread in Cam Open");
    snprintf(my_obj->evt_poll_thread.threadName, THREAD_NAME_SIZE, "CAM_evntPoll");
    mm_camera_poll_thread_launch(&my_obj->evt_poll_thread,
                                 MM_CAMERA_POLL_TYPE_EVT);
    mm_camera_evt_sub(my_obj, TRUE);

会开启两个线程。

1.1 线程1:mm_camera_cmd_thread

其中第一个mm_camera_cmd_thread_launch方法在mm_camera_thread中定义:

int32_t mm_camera_cmd_thread_launch(mm_camera_cmd_thread_t * cmd_thread,
                                    mm_camera_cmd_cb_t cb,
                                    void* user_data){

    cmd_thread->cb = cb;
    cmd_thread->user_data = user_data;
    cmd_thread->is_active = TRUE;

    /* launch the thread */
    pthread_create(&cmd_thread->cmd_pid,
                   NULL,
                   mm_camera_cmd_thread,
                   (void *)cmd_thread);
}
typedef struct {
    uint8_t is_active;     /*indicates whether thread is active or not */
    cam_queue_t cmd_queue; /* cmd queue (queuing dataCB, asyncCB, or exitCMD) */
    pthread_t cmd_pid;           /* cmd thread ID */
    cam_semaphore_t cmd_sem;     /* semaphore for cmd thread */
    cam_semaphore_t sync_sem;     /* semaphore for synchronization with cmd thread */
    mm_camera_cmd_cb_t cb;       /* cb for cmd */
    void* user_data;             /* user_data for cb */
    char threadName[THREAD_NAME_SIZE];
} mm_camera_cmd_thread_t;

也就是先给mm_camera_obj中的mm_camera_cmd_thread_t的cb赋值,然后启动该线程的方法体mm_camera_cmd_thread

static void *mm_camera_cmd_thread(void *data)
{
    int running = 1;
    int ret;
    mm_camera_cmd_thread_t *cmd_thread =
                (mm_camera_cmd_thread_t *)data;
    mm_camera_cmdcb_t* node = NULL;

    mm_camera_cmd_thread_name(cmd_thread->threadName);
    do {
        do {
            ret = cam_sem_wait(&cmd_thread->cmd_sem);
            if (ret != 0 && errno != EINVAL) {
                LOGE("cam_sem_wait error (%s)",
                            strerror(errno));
                return NULL;
            }
        } while (ret != 0);

        /* we got notified about new cmd avail in cmd queue */
        node = (mm_camera_cmdcb_t*)cam_queue_deq(&cmd_thread->cmd_queue);
        while (node != NULL) {
            switch (node->cmd_type) {
            case MM_CAMERA_CMD_TYPE_EVT_CB:
            case MM_CAMERA_CMD_TYPE_DATA_CB:
            case MM_CAMERA_CMD_TYPE_REQ_DATA_CB:
            case MM_CAMERA_CMD_TYPE_SUPER_BUF_DATA_CB:
            case MM_CAMERA_CMD_TYPE_CONFIG_NOTIFY:
            case MM_CAMERA_CMD_TYPE_START_ZSL:
            case MM_CAMERA_CMD_TYPE_STOP_ZSL:
            case MM_CAMERA_CMD_TYPE_GENERAL:
            case MM_CAMERA_CMD_TYPE_FLUSH_QUEUE:
                if (NULL != cmd_thread->cb) {
                    cmd_thread->cb(node, cmd_thread->user_data);
                }
                break;
            case MM_CAMERA_CMD_TYPE_EXIT:
            default:
                running = 0;
                break;
            }
            free(node);
            node = (mm_camera_cmdcb_t*)cam_queue_deq(&cmd_thread->cmd_queue);
        } /* (node != NULL) */
    } while (running);
    return NULL;
}

该线程体中会不断循环的从线程队列中取出cmd,并执行cb,这里的cb是之前通过mm_camera_cmd_thread_launch传进来的,在源码中是方法:

static void mm_camera_dispatch_app_event(mm_camera_cmdcb_t *cmd_cb,
                                         void* user_data)
{
    int i;
    mm_camera_event_t *event = &cmd_cb->u.evt;
    mm_camera_obj_t * my_obj = (mm_camera_obj_t *)user_data;
    if (NULL != my_obj) {
        mm_camera_cmd_thread_name(my_obj->evt_thread.threadName);
        pthread_mutex_lock(&my_obj->cb_lock);
        for(i = 0; i < MM_CAMERA_EVT_ENTRY_MAX; i++) {
            if(my_obj->evt.evt[i].evt_cb) {
                my_obj->evt.evt[i].evt_cb(
                    my_obj->my_hdl,
               
  • 11
    点赞
  • 49
    收藏
    觉得还不错? 一键收藏
  • 9
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值