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


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端最开始拿到帧数据的地方,所以其它算法的流程都基于从这里拿到的帧数据之后。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
这些文件是与音频处理相关的代码文件,属于Android系统中的音频相关模块。下面简单介绍一下每个文件的作用: - alsa_config_parameters.c:alsa驱动的配置参数管理。 - alsa_manager.c:alsa驱动的管理,包括打开、关闭、读写等操作。 - aml_audio_delay.c:音频延迟的处理。 - aml_audio_dev2mix_process.c:音频设备到混音器的音频数据处理。 - aml_audio_ease.c:音频的平滑处理。 - aml_audio_hal_avsync.c:音频硬件同步的处理。 - aml_audio_mixer.c、amlAudioMixer.c、sub_mixing_factory.c:音频混音的处理。 - aml_audio_ms12_bypass.c、aml_audio_ms12_render.c、aml_audio_ms12_sync.c:Dolby MS12音频的处理。 - aml_audio_nonms12_render.c:非Dolby MS12音频的处理。 - aml_audio_scaletempo.c:音频的变速变调处理。 - aml_audio_spdifout.c:SPDIF音频输出的处理。 - aml_audio_stream.c:音频流的处理。 - aml_audio_timer.c:音频定时器的处理。 - aml_avsync_tuning.c:音视频同步的调节。 - aml_config_data.c、aml_config_parser.c:音频相关配置数据的处理。 - aml_dtvsync.c:DTV同步的处理。 - aml_hfp.c:音频头戴式设备的处理。 - aml_mmap_audio.c:音频内存映射的处理。 - aml_vad_wakeup.c:语音唤醒的处理。 - audio_aec.c:音频回声消除的处理。 - audio_bt_sco.c:蓝牙SCO音频的处理。 - audio_dtv_utils.c:DTV音频的处理。 - audio_format_parse.c:音频格式解析的处理。 - audio_hdmi_util.c:HDMI音频的处理。 - audio_hw.c、audio_hw_dtv.c、audio_hw_ms12.c、audio_hw_ms12_common.c、audio_hw_ms12_v2.c、audio_hw_profile.c:音频硬件相关的处理。 - audio_hwsync.c、audio_hwsync_wrap.c:音频硬件同步的处理。 - audio_hw_utils.c:音频硬件工具类的处理。 - audio_kara.c:卡拉OK音频的处理。 - audio_mediasync_wrap.c:媒体同步的处理。 - audio_policy.c:音频策略的处理。 - audio_port.c:音频端口的管理。 - audio_post_process.c:音频后处理的处理。 - audio_tsync_wrap.c:时间同步的处理。 - audio_usb_hal.c:USB音频的处理。 - audio_virtual_buf.c:虚拟音频缓冲的处理。 - dolby_lib_api.c:Dolby音频库的API。 - earc_utils.c:EARC音频的处理。 - hw_avsync.c、hw_avsync_callbacks.c:硬件音视频同步的处理。 - karaoke_manager.c:卡拉OK管理的处理。 - spdif_encoder_api.c:SPDIF编码的API。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值