当前位置: 首页 > 工具软件 > grab > 使用案例 >

Camera Hal OEM模块 ---- cmr_grab.c

蔚承天
2023-12-01


cmr_grab.c是oem端拿到帧数据最底层的地方,直接操作节点
CMR_GRAB_DEV_NAME “/dev/sprd_image”
我们在hal端拿到的预览和拍照的数据都来自这个文件。这里是原始的数据,hal和oem在从cmr_grab中拿到数据后在跑各种算法。
cmr_grab还有大量的 ioctl 操作。

下面我们来看下cmr_grab的重要内容

1,cmr_grab_init

cmr_int cmr_grab_init(struct grab_init_param *init_param_ptr,cmr_handle *grab_handle)

1.1,open 节点

p_grab->fd = open(CMR_GRAB_DEV_NAME, O_RDWR, 0);

1.2,维护mutex

ret = pthread_mutex_init(&p_grab->cb_mutex, NULL);
ret = pthread_mutex_init(&p_grab->dcam_mutex, NULL);
ret = pthread_mutex_init(&p_grab->status_mutex, NULL);
ret = pthread_mutex_init(&p_grab->path_mutex[channel_id], NULL);

1.3, SPRD_IMG_IO_GET_DCAM_RES

ret = ioctl(p_grab->fd, SPRD_IMG_IO_GET_DCAM_RES, &res);

1.4,创建thread

ret = cmr_grab_create_thread((cmr_handle)p_grab);

2,cmr_grab_deinit

cmr_int cmr_grab_deinit(cmr_handle grab_handle)

2.1 kill thread ,指令 SPRD_IMG_STOP_DCAM

ret = cmr_grab_kill_thread(grab_handle);

op.cmd = SPRD_IMG_STOP_DCAM;
op.sensor_id = p_grab->init_param.sensor_id;
cnt = write(p_grab->fd, &op, sizeof(struct sprd_img_write_op));

2.2 指令 SPRD_IMG_IO_PUT_DCAM_RES

ret = ioctl(p_grab->fd, SPRD_IMG_IO_PUT_DCAM_RES, &res);

2.3 mutex destory

pthread_mutex_destroy(&p_grab->cb_mutex);
pthread_mutex_destroy(&p_grab->dcam_mutex);
pthread_mutex_destroy(&p_grab->status_mutex);
pthread_mutex_destroy(&p_grab->path_mutex[channel_id]);

老规矩,init 与 deinit 的操作基本是相对的,创建了什么就要销毁什么

3,一些指令

SPRD_IMG_IO_GET_IOMMU_STATUS
SPRD_IMG_IO_SET_CAM_SECURITY
SPRD_IMG_IO_SET_CAP_ZSL_INFO
SPRD_ISP_IO_SET_PULSE_LINE
SPRD_ISP_IO_SET_VCM_LOG
SPRD_ISP_IO_SET_NEXT_VCM_POS

4,帧数据回调

cmr_grab_evt_reg 是在拿到帧数据之后向上回调的,我们后面在接收帧数据的时候会在看到这个函数

void cmr_grab_evt_reg(cmr_handle grab_handle, cmr_evt_cb grab_event_cb) {
    struct cmr_grab *p_grab;

    p_grab = (struct cmr_grab *)grab_handle;
    if (!p_grab)
        return;

    pthread_mutex_lock(&p_grab->cb_mutex);
    p_grab->grab_evt_cb = grab_event_cb;
    pthread_mutex_unlock(&p_grab->cb_mutex);
    return;
}

5,一些 cfg

cmr_int cmr_grab_if_cfg(cmr_handle grab_handle, struct sensor_if *sn_if)
cmr_int cmr_grab_sw_3dnr_cfg(cmr_handle grab_handle,struct sprd_img_3dnr_param *threednr_info)
cmr_int cmr_grab_sn_cfg(cmr_handle grab_handle, struct sn_cfg *config)
static cmr_int cmr_grab_cap_cfg_common(cmr_handle grab_handle,struct cap_cfg *config,cmr_u32 channel_id,struct img_data_end *endian)
cmr_int cmr_grab_cap_cfg(cmr_handle grab_handle, struct cap_cfg *config,cmr_u32 *channel_id, struct img_data_end *endian)
cmr_int cmr_grab_3dnr_cfg(cmr_handle grab_handle, cmr_u32 channel_id,cmr_u32 need_3dnr)
cmr_int cmr_grab_longexp_cfg(cmr_handle grab_handle, cmr_u32 need_longexp)
cmr_int cmr_grab_auto_3dnr_cfg(cmr_handle grab_handle,cmr_u32 auto_3dnr_enable)
cmr_int cmr_grab_cap_cfg_lightly(cmr_handle grab_handle, struct cap_cfg *config,cmr_u32 channel_id)
cmr_int cmr_grab_buff_cfg(cmr_handle grab_handle, struct buffer_cfg *buf_cfg) 

6,cmr_grab_cap_start 和 cmr_grab_cap_stop

ret = ioctl(p_grab->fd, SPRD_IMG_IO_STREAM_ON, &stream_on); //start
ret = ioctl(p_grab->fd, SPRD_IMG_IO_STREAM_OFF, &stream_on);//stop

他们分别在打开cameraApp 和 退出 CameraApp 的时候被调用的,从如下log时序中可以很清楚的看到。

Line 89953: 07-23 19:57:53.826  8634  8634 I CAM_CameraActivity Drea: onStartTasks start!
Line 92901: 07-23 19:57:55.832   531  8731 D cmr_grab: 1232, cmr_grab_cap_start: ret = 0
Line 102592: 07-23 19:57:59.978  8634  8634 I CAM_CameraActivity Drea: onPauseTasks start!
Line 103137: 07-23 19:58:00.146   531  8731 D cmr_grab: 1274, cmr_grab_cap_stop: ret = 0

7,pause 和 resume

ret = ioctl(p_grab->fd, SPRD_IMG_IO_STREAM_PAUSE, &temp);//pause
ret = ioctl(p_grab->fd, SPRD_IMG_IO_STREAM_RESUME, &temp);//resume

8,cmr_grab_start_capture 和 cmr_grab_stop_capture

根据log,这两个函数是在开启拍照 和 需要的拍照帧数据都拿到后分别调用的

ret = ioctl(p_grab->fd, SPRD_IMG_IO_START_CAPTURE, &capture_param);
ret = ioctl(p_grab->fd, SPRD_IMG_IO_STOP_CAPTURE, &stop);

注:cmr_grab_stop_capture 在退出camera的时候也会被调用一次

9,cmr_grab_cap_resume 和 cmr_grab_cap_pause

常规拍照流程暂未看到这两个函数的调用

10,关键函数:cmr_grab_thread_proc

cmr_grab_thread_proc 就是接受帧数据的函数

static void *cmr_grab_thread_proc(void *data)

10.1 irq_type 含义

CAMERA_IRQ_IMG  //1
CAMERA_IRQ_FDRL //9
CAMERA_IRQ_FDRH //10
CAMERA_IRQ_4IN1_DONE //6
CAMERA_IRQ_STATIS //2
CAMERA_IRQ_DONE //3

其中预览和拍照的帧数据都是 CAMERA_IRQ_IMG ,log打印看到也有 2、3这两种类型,但是并没有走后续处理流程,我们目前只关注 CAMERA_IRQ_IMG 类型。

10.2 channel_id 的概念

从参数 data中使用指令 SPRD_IMG_GET_FRM_BUFFER 读数据 到 op 对象中

struct cmr_grab *p_grab;
p_grab = (struct cmr_grab *)data;
cnt = sizeof(struct sprd_img_read_op);
op.cmd = SPRD_IMG_GET_FRM_BUFFER;
op.sensor_id = p_grab->init_param.sensor_id;
if (cnt != read(p_grab->fd, &op, sizeof(struct sprd_img_read_op))) {
    CMR_LOGE("read failed");
    break;
}

然后从op对象中可以拿到channel_id的值

op.parm.frame.channel_id
log中看到各类型的channel_id值
preview ---> 1
snapshot ---> 3
callback ---> 2
yuv2 ---> 5

10.3 封装帧数据的值

struct frm_info frame;
frame.height = op.parm.frame.height;
frame.frame_id = op.parm.frame.index;
frame.frame_real_id = op.parm.frame.real_index;
frame.sec = op.parm.frame.sec;
frame.usec = op.parm.frame.usec;
frame.monoboottime = op.parm.frame.monoboottime;
frame.length = op.parm.frame.length;
frame.base = op.parm.frame.frm_base_id;
frame.fmt = cmr_grab_get_img_type(op.parm.frame.img_fmt);
frame.yaddr = op.parm.frame.yaddr;
frame.uaddr = op.parm.frame.uaddr;
frame.vaddr = op.parm.frame.vaddr;
frame.yaddr_vir = op.parm.frame.yaddr_vir;
frame.uaddr_vir = op.parm.frame.uaddr_vir;
frame.vaddr_vir = op.parm.frame.vaddr_vir;
frame.fd = op.parm.frame.mfd;
frame.frame_num = op.parm.frame.frame_id;
frame.zoom_ratio = op.parm.frame.zoom_ratio;

10.4 回调

这里是指针函数 grab_evt_cb,我们在全面说过 cmr_grab_evt_reg 函数,就是给 grab_evt_cb 赋值的。

if (p_grab->grab_evt_cb) {
    (*p_grab->grab_evt_cb)(
        evt_id, &frame,
        (void *)p_grab->init_param.oem_handle);
}

cmr_grab_evt_reg 是在 cmr_oem.c 中调用的,所以cmr_grab在拿到帧数据后会回调到 cmr_oem 中 的 camera_grab_evt_cb 函数。
后面就涉及到 预览帧 和 拍照帧的处理了,分别在 cmr_preview.c 和 cmr_snapshot.c 中,他们的内容都比较多,本篇的重点是cmr_grab.c , 我们会在分别单独写文章介绍cmr_preview.c 和 cmr_snapshot.c。

到这里 cmr_grab.c 就介绍得差不多了,大家只要记住,cmr_grab是oem端最开始拿到帧数据的地方,所以其它算法的流程都基于从这里拿到的帧数据之后。

 类似资料: