mm_camera_cmd_thread

  需求:一个新的线程,监听和分发处理一些命令。

     在实际的应用中,这种使用场景是非常多见的。

typedef void (*mm_camera_cmd_cb_t)(mm_camera_cmdcb_t * cmd_cb, void* user_data);

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 */ /* Command处理的Callback函数,由用户注册 */ void* user_data; /* user_data for cb */ char threadName[THREAD_NAME_SIZE]; } mm_camera_cmd_thread_t;

 1. 新建线程

int32_t mm_camera_cmd_thread_launch(mm_camera_cmd_thread_t * cmd_thread,
                                    mm_camera_cmd_cb_t cb,
                                    void* user_data)
{
    int32_t rc = 0;

    cam_sem_init(&cmd_thread->cmd_sem, 0);
    cam_sem_init(&cmd_thread->sync_sem, 0);
    cam_queue_init(&cmd_thread->cmd_queue);
    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);
    return rc;
}

 

  太简单了,无话可说。

2.  线程的其他控制函数

int32_t mm_camera_cmd_thread_name(const char* name)    // 设置线程名字
{
    int32_t rc = 0;
    /* name the thread */
    if (name && strlen(name))
        prctl(PR_SET_NAME, (unsigned long)name, 0, 0, 0);
    return rc;
}


int32_t mm_camera_cmd_thread_stop(mm_camera_cmd_thread_t * cmd_thread)  // 停止线程
{
    int32_t rc = 0;
    mm_camera_cmdcb_t* node = (mm_camera_cmdcb_t *)malloc(sizeof(mm_camera_cmdcb_t));
    if (NULL == node) {
        CDBG_ERROR("%s: No memory for mm_camera_cmdcb_t", __func__);
        return -1;
    }

    memset(node, 0, sizeof(mm_camera_cmdcb_t));
    node->cmd_type = MM_CAMERA_CMD_TYPE_EXIT;

    cam_queue_enq(&cmd_thread->cmd_queue, node);
    cam_sem_post(&cmd_thread->cmd_sem);

    /* wait until cmd thread exits */
    if (pthread_join(cmd_thread->cmd_pid, NULL) != 0) {  // 这里很重要,说明调用该函数是会给工作线程收尸
        CDBG("%s: pthread dead already\n", __func__);
    }
    return rc;
}

int32_t mm_camera_cmd_thread_destroy(mm_camera_cmd_thread_t * cmd_thread)
{
    int32_t rc = 0;
    cam_queue_deinit(&cmd_thread->cmd_queue);
    cam_sem_destroy(&cmd_thread->cmd_sem);
    cam_sem_destroy(&cmd_thread->sync_sem);
    memset(cmd_thread, 0, sizeof(mm_camera_cmd_thread_t));
    return rc;
}

int32_t mm_camera_cmd_thread_release(mm_camera_cmd_thread_t * cmd_thread)
{
    int32_t rc = 0;
    rc = mm_camera_cmd_thread_stop(cmd_thread);
    if (0 == rc) {
        rc = mm_camera_cmd_thread_destroy(cmd_thread);
    }
    return rc;
}

 

 3. 线程主体

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) {
                CDBG_ERROR("%s: cam_sem_wait error (%s)",
                           __func__, 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) {  // 这些用户定义的命令的处理使用用户指定的 Callback 函数
                    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;
}

 

 

typedef enum
{
    MM_CAMERA_CMD_TYPE_DATA_CB,    /* dataB CMD */
    MM_CAMERA_CMD_TYPE_EVT_CB,     /* evtCB CMD */
    MM_CAMERA_CMD_TYPE_EXIT,       /* EXIT */
    MM_CAMERA_CMD_TYPE_REQ_DATA_CB,/* request data */
    MM_CAMERA_CMD_TYPE_SUPER_BUF_DATA_CB,    /* superbuf dataB CMD */
    MM_CAMERA_CMD_TYPE_CONFIG_NOTIFY, /* configure notify mode */
    MM_CAMERA_CMD_TYPE_START_ZSL, /* start zsl snapshot for channel */
    MM_CAMERA_CMD_TYPE_STOP_ZSL, /* stop zsl snapshot for channel */
    MM_CAMERA_CMD_TYPE_FLUSH_QUEUE, /* flush queue */
    MM_CAMERA_CMD_TYPE_GENERAL,  /* general cmd */
    MM_CAMERA_CMD_TYPE_MAX
} mm_camera_cmdcb_type_t;

typedef struct {
    uint32_t stream_id;
    uint32_t frame_idx;
    uint32_t flags;
    mm_camera_buf_def_t *buf; /* ref to buf */
} mm_camera_buf_info_t;

typedef enum {
    MM_CAMERA_GENERIC_CMD_TYPE_AE_BRACKETING,
    MM_CAMERA_GENERIC_CMD_TYPE_AF_BRACKETING,
    MM_CAMERA_GENERIC_CMD_TYPE_FLASH_BRACKETING,
    MM_CAMERA_GENERIC_CMD_TYPE_ZOOM_1X,
    MM_CAMERA_GENERIC_CMD_TYPE_CAPTURE_SETTING,
} mm_camera_generic_cmd_type_t;

typedef struct {
    mm_camera_generic_cmd_type_t type;
    uint32_t payload[32];
    union {
        cam_capture_frame_config_t frame_config;
    };
} mm_camera_generic_cmd_t;

typedef struct {
    uint32_t frame_idx;
    cam_stream_type_t stream_type;
} mm_camera_flush_cmd_t;

typedef struct {
    mm_camera_cmdcb_type_t cmd_type;
    union {
        mm_camera_buf_info_t buf;    /* frame buf if dataCB */
        mm_camera_event_t evt;       /* evt if evtCB */
        mm_camera_super_buf_t superbuf; /* superbuf if superbuf dataCB*/
        mm_camera_req_buf_t req_buf; /* num of buf requested */
        mm_camera_flush_cmd_t flush_cmd; /* frame idx boundary for flush superbuf queue*/
        mm_camera_super_buf_notify_mode_t notify_mode; /* notification mode */
        mm_camera_generic_cmd_t gen_cmd;
    } u;
} mm_camera_cmdcb_t;

 

4. 线程目的

  该线程的主要目的是为了 监听  Kernel或者 Demon 中的事件。

static void mm_camera_event_notify(void* user_data)  // 回调。Kernel事件监听线程的回调。会有一个线程不断地 poll Kernel 的事件。具体实现,后期文章再细讲
{
    struct v4l2_event ev;
    struct msm_v4l2_event_data *msm_evt = NULL;
    int rc;
    mm_camera_event_t evt;
    memset(&evt, 0, sizeof(mm_camera_event_t));

    mm_camera_obj_t *my_obj = (mm_camera_obj_t*)user_data;
    if (NULL != my_obj) {
        /* read evt */
        memset(&ev, 0, sizeof(ev));
        rc = ioctl(my_obj->ctrl_fd, VIDIOC_DQEVENT, &ev); 

        if (rc >= 0 && ev.id == MSM_CAMERA_MSM_NOTIFY) {
            msm_evt = (struct msm_v4l2_event_data *)ev.u.data;
            switch (msm_evt->command) {
            case CAM_EVENT_TYPE_DAEMON_PULL_REQ:
                evt.server_event_type = CAM_EVENT_TYPE_DAEMON_PULL_REQ;
                mm_camera_enqueue_evt(my_obj, &evt);
                break;
            case CAM_EVENT_TYPE_MAP_UNMAP_DONE:    // 该事件是用来表示 发 Demon 消息时的返回结果
                pthread_mutex_lock(&my_obj->evt_lock);
                my_obj->evt_rcvd.server_event_type = msm_evt->command;
                my_obj->evt_rcvd.status = msm_evt->status;
                pthread_cond_signal(&my_obj->evt_cond);
                pthread_mutex_unlock(&my_obj->evt_lock);
                break;
            case CAM_EVENT_TYPE_INT_TAKE_JPEG:
            case CAM_EVENT_TYPE_INT_TAKE_RAW:
                {
                    evt.server_event_type = msm_evt->command;
                    mm_camera_enqueue_evt(my_obj, &evt);
                }
                break;
            case MSM_CAMERA_PRIV_SHUTDOWN:
                {
                    CDBG_ERROR("%s: Camera Event DAEMON DIED received", __func__);
                    evt.server_event_type = CAM_EVENT_TYPE_DAEMON_DIED;
                    mm_camera_enqueue_evt(my_obj, &evt);
                }
                break;
            case CAM_EVENT_TYPE_CAC_DONE:
                {
                    evt.server_event_type = CAM_EVENT_TYPE_CAC_DONE;
                    mm_camera_enqueue_evt(my_obj, &evt);
                }
                break;
            default:
                break;
            }
        }
    }
}

int32_t mm_camera_enqueue_evt(mm_camera_obj_t *my_obj,
                              mm_camera_event_t *event)
{
    int32_t rc = 0;
    mm_camera_cmdcb_t *node = NULL;

    node = (mm_camera_cmdcb_t *)malloc(sizeof(mm_camera_cmdcb_t));
    if (NULL != node) {
        memset(node, 0, sizeof(mm_camera_cmdcb_t));
        node->cmd_type = MM_CAMERA_CMD_TYPE_EVT_CB;  // MM_CAMERA_CMD_TYPE_EVT_CB
        node->u.evt = *event;

        /* enqueue to evt cmd thread */
        cam_queue_enq(&(my_obj->evt_thread.cmd_queue), node);       // evt_thread 的事件的唯一入口
        /* wake up evt cmd thread */
        cam_sem_post(&(my_obj->evt_thread.cmd_sem));
    } else {
        CDBG_ERROR("%s: No memory for mm_camera_node_t", __func__);
        rc = -1;
    }

    return rc;
}

 

转载于:https://www.cnblogs.com/ronny-blog/p/8253050.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值