主要涉及三方面:
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,