• Camera Hal OEM模块 ---- cmr_preview.c


    文章目录


    cmr_preview.c 是我目前全文追过最长的文件了 18000 行。。。
    最开始看到这么长的文件,确实很抵触,但是一遍看下来发现有很多有规律的内容,比如这里面管理了5个channel,channle0、channle1、channle2、channle3、channle4,他们的大部分内容是都相似的,alloc buf、configure、queue、dequeue等等,后面我们会详细说明。

    还是先来看下cmr_preview中定义的结构体
    最关键且最长的是 prev_context,内容太多了,这单个结构体的成员有将近250个,我们截取其中关键变量说明下

    关键结构体

    struct preview_param prev_param;//preview_param  后面会在列出这个结构体的内容
    
    //channel_id
    cmr_uint prev_channel_id;
    cmr_uint video_channel_id;
    cmr_uint cap_channel_id;
    
    //preivew 相关成员
    struct img_frm prev_frm[PREV_FRM_CNT];
    struct img_frm prev_reserved_frm;
    cmr_uint prev_phys_addr_array[PREV_FRM_CNT + PREV_ROT_FRM_CNT];
    cmr_uint prev_virt_addr_array[PREV_FRM_CNT + PREV_ROT_FRM_CNT];
    cmr_s32 prev_fd_array[PREV_FRM_CNT + PREV_ROT_FRM_CNT];
    cmr_uint prev_reserved_phys_addr;
    cmr_uint prev_reserved_virt_addr;
    cmr_s32 prev_reserved_fd;
    cmr_uint prev_phys_yuv_addr;
    cmr_uint prev_virt_yuv_addr;
    cmr_s32 prev_mfd_yuv;
    //rot 和 ultra_wide
    cmr_uint prev_rot_index;
    cmr_uint prev_rot_frm_is_lock[PREV_ROT_FRM_CNT];
    struct img_frm prev_rot_frm[PREV_ROT_FRM_CNT];
    cmr_uint prev_ultra_wide_index;
    cmr_uint prev_ultra_wide_frm_is_lock[PREV_ULTRA_WIDE_ALLOC_CNT];
    struct img_frm prev_ultra_wide_frm[PREV_ULTRA_WIDE_ALLOC_CNT];
    
    //video 的相关成员
    struct img_frm video_frm[PREV_FRM_CNT];
    cmr_uint video_phys_addr_array[PREV_FRM_CNT + PREV_ROT_FRM_CNT];
    cmr_uint video_virt_addr_array[PREV_FRM_CNT + PREV_ROT_FRM_CNT];
    cmr_s32 video_fd_array[PREV_FRM_CNT + PREV_ROT_FRM_CNT];
    cmr_uint video_reserved_phys_addr;
    cmr_uint video_reserved_virt_addr;
    cmr_s32 video_reserved_fd;
    // rot 和 ultra_wide
    cmr_uint video_rot_index;
    cmr_uint video_rot_frm_is_lock[PREV_ROT_FRM_CNT];
    struct img_frm video_rot_frm[PREV_ROT_FRM_CNT];
    cmr_uint video_ultra_wide_index;
    cmr_uint video_ultra_wide_frm_is_lock[VIDEO_ULTRA_WIDE_ALLOC_CNT];
    struct img_frm video_ultra_wide_frm[VIDEO_ULTRA_WIDE_ALLOC_CNT];
    
    // for channel0
    channel0_t channel0;
    cmr_uint channel0_work_mode;
    
    // for channel1
    channel1_t channel1;
    struct img_size channel1_actual_pic_size;
    cmr_uint channel1_work_mode;
    
    // for channel2
    channel2_t channel2;
    struct img_size channel2_actual_pic_size;
    int channel2_pending_request;
    cmr_uint channel2_work_mode;
    
    // for channel3
    channel3_t channel3;
    struct img_size channel3_actual_pic_size;
    cmr_uint channel3_work_mode;
    
    // for channel4
    channel4_t channel4;
    struct img_size channel4_actual_pic_size;
    cmr_uint channel4_work_mode;
    
    //capture相关的
    struct cmr_cap_mem cap_mem[CMR_CAPTURE_MEM_SUM];
    struct img_frm cap_frm[CMR_CAPTURE_MEM_SUM];
    cmr_uint cap_phys_addr_array[CMR_CAPTURE_MEM_SUM];
    cmr_uint cap_virt_addr_array[CMR_CAPTURE_MEM_SUM];
    cmr_s32 cap_fd_array[CMR_CAPTURE_MEM_SUM];
    cmr_uint cap_phys_addr_path_array[CMR_CAPTURE_MEM_SUM];
    cmr_uint cap_virt_addr_path_array[CMR_CAPTURE_MEM_SUM];
    cmr_s32 cap_fd_path_array[CMR_CAPTURE_MEM_SUM];
    //hdr相关的
    cmr_uint cap_hdr_phys_addr_path_array[HDR_CAP_NUM];
    cmr_uint cap_hdr_virt_addr_path_array[HDR_CAP_NUM];
    cmr_s32 cap_hdr_fd_path_array[HDR_CAP_NUM];	
    //3dnr 相关的
    cmr_uint cap_3dnr_phys_addr_path_array[CAP_3DNR_NUM];
    cmr_uint cap_3dnr_virt_addr_path_array[CAP_3DNR_NUM];
    cmr_s32 cap_3dnr_fd_path_array[CAP_3DNR_NUM];
    //zsl相关的
    cmr_uint cap_zsl_phys_addr_array[ZSL_FRM_CNT + ZSL_ROT_FRM_CNT];
    cmr_uint cap_zsl_virt_addr_array[ZSL_FRM_CNT + ZSL_ROT_FRM_CNT];
    cmr_s32 cap_zsl_fd_array[ZSL_FRM_CNT + ZSL_ROT_FRM_CNT];
    struct img_frm cap_zsl_frm[ZSL_FRM_CNT];
    struct img_frm cap_zsl_reserved_frm;	
    cmr_uint cap_zsl_reserved_phys_addr;
    cmr_uint cap_zsl_reserved_virt_addr;
    cmr_s32 cap_zsl_reserved_fd;
    //zsl下的rot和ultra_wide
    cmr_uint cap_zsl_rot_index;
    cmr_uint cap_zsl_rot_frm_is_lock[ZSL_ROT_FRM_CNT];
    struct img_frm cap_zsl_rot_frm[ZSL_ROT_FRM_CNT];
    cmr_uint cap_zsl_ultra_wide_index;
    cmr_uint cap_zsl_ultra_wide_frm_is_lock[ZSL_ULTRA_WIDE_ALLOC_CNT];
    struct img_frm cap_zsl_ultra_wide_frm[ZSL_ULTRA_WIDE_ALLOC_CNT];
    
    //4in1相关的
    cmr_uint cap_4in1_phys_addr_array[CAP_4IN1_NUM];
    cmr_uint cap_4in1_virt_addr_array[CAP_4IN1_NUM];
    cmr_s32 cap_4in1_fd_array[CAP_4IN1_NUM];
    cmr_uint cap_4in1_mem_size;
    cmr_uint cap_4in1_mem_num;
    cmr_int cap_4in1_mem_valid_num;
    
    //hdr相关的
    cmr_uint cap_rgb_phys_addr_array[FDR_FRM_ALLOC_CNT];
    cmr_uint cap_rgb_virt_addr_array[FDR_FRM_ALLOC_CNT];
    cmr_s32 cap_rgb_fd_array[FDR_FRM_ALLOC_CNT];
    cmr_uint cap_rgb_mem_size;
    cmr_u32 cap_rgb_mem_num;
    cmr_uint cap_fdr_phys_addr_array[FDR_FRM_ALLOC_CNT];
    cmr_uint cap_fdr_virt_addr_array[FDR_FRM_ALLOC_CNT];
    cmr_s32 cap_fdr_fd_array[FDR_FRM_ALLOC_CNT];
    cmr_uint cap_fdr_mem_size;
    cmr_u32 cap_fdr_mem_num;
    struct buffer_cfg cap_used_fdr_buf_cfg;
    //各个handle
    cmr_handle fd_handle;
    cmr_handle ultra_wide_handle;
    cmr_handle zsl_ultra_wide_handle;
    cmr_handle video_ultra_wide_handle;
    cmr_handle refocus_handle;
    cmr_handle prev_3dnr_handle;
    cmr_handle ai_scence_handle;
    cmr_handle auto_tracking_handle;
    
    
    //eis  auto_tracking 等一般项目不同,暂不关注
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134

    在来看下上面prev_context 中包括的 preview_param

    //preview_param管理8个模块:preview、video、snapshot、channel0、channel1、channel2、channel3、channel4
        cmr_u32 preview_eb;
        cmr_uint preview_fmt;
        cmr_uint prev_rot;
        struct img_size preview_size;
    
        cmr_u32 video_eb;
        struct img_size video_size;
        cmr_u32 video_fmt;
        
        cmr_u32 snapshot_eb;
        struct img_size picture_size;
        struct img_size raw_capture_size;
        struct img_size thumb_size;
        cmr_uint cap_fmt;
    	
    	    cmr_u32 channel0_eb;
        cmr_u32 channel0_fmt;
        struct img_size channel0_size;
    
        cmr_u32 channel1_eb;
        cmr_u32 channel1_fmt;
        cmr_u32 channel1_rot_angle;
        struct img_size channel1_size;
        cmr_u32 channel1_flip_on;
    
        cmr_u32 channel2_eb;
        cmr_u32 channel2_fmt;
        cmr_u32 channel2_rot_angle;
        struct img_size channel2_size;
        cmr_u32 channel2_flip_on;
    
        cmr_u32 channel3_eb;
        cmr_u32 channel3_fmt;
        cmr_u32 channel3_rot_angle;
        struct img_size channel3_size;
        cmr_u32 channel3_flip_on;
    
        cmr_u32 channel4_eb;
        cmr_u32 channel4_fmt;
        cmr_u32 channel4_rot_angle;
        struct img_size channel4_size;
        cmr_u32 channel4_flip_on;
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44

    还有prev_context 中包括的5个channel,这几个channel中,channel0 的内容略微最简单的,后面几个基本是一样的,我们把chaneel2贴出来看下

    typedef struct channel2 {
        cmr_u32 enable;
        struct img_size size;
        cmr_u32 buf_size;
        cmr_u32 buf_cnt;
        // valid_buf_cnt means how many buffers set to kernel driver
        cmr_u32 valid_buf_cnt;
        cmr_u32 shrink;
        cmr_u32 chn_id;
        cmr_u32 chn_status;
        cmr_u32 format;
        cmr_u32 skip_num;
        cmr_u32 skip_mode;
        unsigned long frm_cnt;
        struct img_data_end endian;
        struct img_frm frm[CHANNEL2_BUF_CNT];
        struct img_frm frm_reserved;
        cmr_u32 frm_valid;
    
        struct img_frm rot_frm[CHANNEL2_BUF_CNT_ROT];
        cmr_u32 rot_frm_lock_flag[CHANNEL2_BUF_CNT_ROT];
        cmr_u32 rot_index;
    
        cmr_s32 fd[CHANNEL2_BUF_CNT + CHANNEL2_BUF_CNT_ROT];
        unsigned long addr_phy[CHANNEL2_BUF_CNT + CHANNEL2_BUF_CNT_ROT];
        unsigned long addr_vir[CHANNEL2_BUF_CNT + CHANNEL2_BUF_CNT_ROT];
    } channel2_t;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    关于这几个chennel,补充一点,根据log看到,上层配置的previewDateCallabck是走的channel2,缩略图走的是channel3,其余几个channel还没有看到用的地方,可能是预留的。
    上层配流较多的情况就是4路:预览流、拍照流、预览回调流、缩略图流。

    最后在看一个结构体 preview_handle

    struct prev_handle {
        cmr_handle oem_handle;
        cmr_handle ipm_handle;
        cmr_uint sensor_bits; // multi-sensors need multi mem ? channel_cfg
        preview_cb_func oem_cb;
        struct preview_md_ops ops;
        void *private_data;
        struct prev_thread_cxt thread_cxt;
        struct prev_context prev_cxt[CAMERA_ID_MAX];
        cmr_uint frame_active;
        cmr_u32 zsl_ips_en;
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    前5个在后面会看到使用,各种对应的handle,其中oem_cb 是事件回调对象,会调用到cmr_oem.c 中

    关于cmr_preview.c的结构体就说到这里,下面我们进入正文。

    还是可以先看下函数声明

    函数声明

    1. 三个thread
    2. freme处理,分为4种
    3. 帧错误处理
    4. init 与deinit
    5. 开启和停止预览
    6. buf管理:alloc 与 free
    7. 构建帧数据
    8. setParam相关的
    9. channel0、channel1、channel2、channel3、channel4 的管理
    10. 功能的管理:fd、3dnr、ai_scene、ultra_wide、auto_tracking
    11. preview的buffer管理
    12. video的buffer管理
    13. zsl的buffer管理
    14. 最后一条,也是比较关键的 prev_receive_data

    1,三个thread

    static cmr_int prev_create_thread(struct prev_handle *handle);
    static cmr_int prev_destroy_thread(struct prev_handle *handle);
    static cmr_int prev_thread_proc(struct cmr_msg *message, void *p_data);
    
    static cmr_int prev_create_cb_thread(struct prev_handle *handle);
    static cmr_int prev_destroy_cb_thread(struct prev_handle *handle);
    static cmr_int prev_cb_thread_proc(struct cmr_msg *message, void *p_data);
    
    static cmr_int prev_assist_thread_proc(struct cmr_msg *message, void *p_data);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    2,freme处理,分为4种

    cmr_int prev_frame_handle(struct prev_handle *handle, cmr_u32 camera_id,struct frm_info *data);
    
    static cmr_int prev_preview_frame_handle(struct prev_handle *handle,cmr_u32 camera_id,struct frm_info *data);
    
    static cmr_int prev_video_frame_handle(struct prev_handle *handle,cmr_u32 camera_id,struct frm_info *data);
    
    static cmr_int prev_capture_frame_handle(struct prev_handle *handle,cmr_u32 camera_id,struct frm_info *data);
    
    static cmr_int prev_zsl_frame_handle(struct prev_handle *handle,cmr_u32 camera_id, struct frm_info *data);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    3,帧错误处理

    我们之前在遇到无法连接的问题时,就会看着这个函数被调用

    static cmr_int prev_error_handle(struct prev_handle *handle, cmr_u32 camera_id,cmr_uint evt_type);
    
    • 1

    4,init 与deinit

    static cmr_int prev_local_init(struct prev_handle *handle);
    static cmr_int prev_local_deinit(struct prev_handle *handle);
    
    • 1
    • 2

    5,开启和停止预览

    static cmr_int prev_start(struct prev_handle *handle, cmr_u32 camera_id,cmr_u32 is_restart, cmr_u32 is_sn_reopen);
    
    static cmr_int prev_stop(struct prev_handle *handle, cmr_u32 camera_id,cmr_u32 is_restart);
    
    • 1
    • 2
    • 3

    6,buf管理:alloc 与 free

    static cmr_int prev_alloc_prev_buf(struct prev_handle *handle,cmr_u32 camera_id, cmr_u32 is_restart,struct buffer_cfg *buffer);
    static cmr_int prev_free_prev_buf(struct prev_handle *handle, cmr_u32 camera_id,cmr_u32 is_restart);
    
    static cmr_int prev_alloc_video_buf(struct prev_handle *handle,cmr_u32 camera_id, cmr_u32 is_restart,struct buffer_cfg *buffer);
    static cmr_int prev_free_video_buf(struct prev_handle *handle,cmr_u32 camera_id, cmr_u32 is_restart);
    
    static cmr_int prev_alloc_cap_buf(struct prev_handle *handle, cmr_u32 camera_id,cmr_u32 is_restart,struct buffer_cfg *buffer);
    static cmr_int prev_free_cap_buf(struct prev_handle *handle, cmr_u32 camera_id,cmr_u32 is_restart);
    
    static cmr_int prev_alloc_zsl_buf(struct prev_handle *handle, cmr_u32 camera_id,cmr_u32 is_restart,struct buffer_cfg *buffer);
    static cmr_int prev_free_zsl_buf(struct prev_handle *handle, cmr_u32 camera_id,cmr_u32 is_restart);
    
    static cmr_int prev_free_zsl_raw_buf(struct prev_handle *handle, cmr_u32 camera_id,cmr_u32 is_restart);
    
    static cmr_int prev_alloc_4in1_buf(struct prev_handle *handle,cmr_u32 camera_id, cmr_u32 is_restart);
    static cmr_int prev_free_4in1_buf(struct prev_handle *handle, cmr_u32 camera_id,cmr_u32 is_restart);
    
    static prev_alloc_cap_reserve_buf(struct prev_handle *handle,cmr_u32 camera_id, cmr_u32 is_restart);
    static cmr_int prev_free_cap_reserve_buf(struct prev_handle *handle,cmr_u32 camera_id, cmr_u32 is_restart);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    7,构建帧数据

    static cmr_int prev_construct_frame(struct prev_handle *handle,cmr_u32 camera_id, struct frm_info *info,struct camera_frame_type *frame_type);
    
    static cmr_int prev_construct_video_frame(struct prev_handle *handle,cmr_u32 camera_id,struct frm_info *info,struct camera_frame_type *frame_type);
    
    static cmr_int prev_construct_zsl_frame(struct prev_handle *handle,cmr_u32 camera_id,struct frm_info *info,struct camera_frame_type *frame_type);
    
    • 1
    • 2
    • 3
    • 4
    • 5

    8,setParam相关的

    static cmr_int prev_set_prev_param(struct prev_handle *handle,cmr_u32 camera_id, cmr_u32 is_restart,struct preview_out_param *out_param_ptr);
    
    static cmr_int prev_set_video_param(struct prev_handle *handle,cmr_u32 camera_id, cmr_u32 is_restart,struct preview_out_param *out_param_ptr);
    
    static cmr_int prev_set_prev_param_lightly(struct prev_handle *handle,cmr_u32 camera_id);
    
    static cmr_int prev_set_cap_param(struct prev_handle *handle, cmr_u32 camera_id,cmr_u32 is_restart, cmr_u32 is_lightly,struct preview_out_param *out_param_ptr);
    
    static cmr_int prev_update_cap_param(struct prev_handle *handle,cmr_u32 camera_id, cmr_u32 encode_angle,struct snp_proc_param *out_param_ptr);
    
    static cmr_int prev_set_zsl_param_lightly(struct prev_handle *handle,cmr_u32 camera_id);
    
    static cmr_int prev_set_cap_param_raw(struct prev_handle *handle,cmr_u32 camera_id, cmr_u32 is_restart,struct preview_out_param *out_param_ptr);
                                           
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    9,channel0、channel1、channel2、channel3、channel4 的管理

    基本都是相同的:configure、alloc_bufs、free_bufs、queue_buffer、dequeue_buffer

    cmr_int channel0_configure(struct prev_handle *handle, cmr_u32 camera_id,cmr_u32 is_restart,struct preview_out_param *out_param_ptr);
    cmr_int channel0_alloc_bufs(struct prev_handle *handle, cmr_u32 camera_id,cmr_u32 is_restart, struct buffer_cfg *buffer);
    cmr_int channel0_free_bufs(struct prev_handle *handle, cmr_u32 camera_id,cmr_u32 is_restart);
    cmr_s32 channel0_queue_buffer(struct prev_handle *handle, cmr_u32 camera_id,cam_buffer_info_t *buffer);
    int channel0_dequeue_buffer(struct prev_handle *handle, cmr_u32 camera_id,struct frm_info *info);
    
    cmr_int channel1_configure(struct prev_handle *handle, cmr_u32 camera_id,cmr_u32 is_restart,struct preview_out_param *out_param_ptr);
    cmr_int channel1_alloc_bufs(struct prev_handle *handle, cmr_u32 camera_id,cmr_u32 is_restart, struct buffer_cfg *buffer);
    cmr_int channel1_free_bufs(struct prev_handle *handle, cmr_u32 camera_id,cmr_u32 is_restart);
    cmr_s32 channel1_queue_buffer(struct prev_handle *handle, cmr_u32 camera_id,cam_buffer_info_t *buffer);
    int channel1_dequeue_buffer(struct prev_handle *handle, cmr_u32 camera_id,struct frm_info *info);
    cmr_int channel1_update_params(struct prev_handle *handle, cmr_u32 camera_id);
    cmr_s32 channel1_find_free_rot_buffer(struct prev_context *prev_cxt,cmr_u32 *index);
    
    cmr_int channel2_configure(struct prev_handle *handle, cmr_u32 camera_id,cmr_u32 is_restart,struct preview_out_param *out_param_ptr);
    cmr_int channel2_alloc_bufs(struct prev_handle *handle, cmr_u32 camera_id,cmr_u32 is_restart, struct buffer_cfg *buffer);
    cmr_int channel2_free_bufs(struct prev_handle *handle, cmr_u32 camera_id,cmr_u32 is_restart);
    cmr_s32 channel2_add_cbsream_pending_request(struct prev_handle *handle, cmr_u32 camera_id);
    cmr_uint channel2_reduce_pending_request(struct prev_handle *handle, cmr_u32 camera_id);
    cmr_s32 channel2_queue_buffer(struct prev_handle *handle, cmr_u32 camera_id,cam_buffer_info_t *buffer);
    int channel2_dequeue_buffer(struct prev_handle *handle, cmr_u32 camera_id,struct frm_info *info);
    cmr_int channel2_update_params(struct prev_handle *handle, cmr_u32 camera_id);
    cmr_s32 channel2_find_free_rot_buffer(struct prev_context *prev_cxt,cmr_u32 *index);
    
    cmr_int channel3_configure(struct prev_handle *handle, cmr_u32 camera_id,cmr_u32 is_restart,struct preview_out_param *out_param_ptr);
    cmr_int channel3_alloc_bufs(struct prev_handle *handle, cmr_u32 camera_id,cmr_u32 is_restart, struct buffer_cfg *buffer);
    cmr_int channel3_free_bufs(struct prev_handle *handle, cmr_u32 camera_id,cmr_u32 is_restart);
    cmr_s32 channel3_queue_buffer(struct prev_handle *handle, cmr_u32 camera_id,cam_buffer_info_t *buffer);
    int channel3_dequeue_buffer(struct prev_handle *handle, cmr_u32 camera_id,struct frm_info *info);
    cmr_int channel3_update_params(struct prev_handle *handle, cmr_u32 camera_id);
    cmr_s32 channel3_find_free_rot_buffer(struct prev_context *prev_cxt,cmr_u32 *index);
    
    cmr_int channel4_configure(struct prev_handle *handle, cmr_u32 camera_id,cmr_u32 is_restart,struct preview_out_param *out_param_ptr);
    cmr_int channel4_alloc_bufs(struct prev_handle *handle, cmr_u32 camera_id,cmr_u32 is_restart, struct buffer_cfg *buffer);
    cmr_int channel4_free_bufs(struct prev_handle *handle, cmr_u32 camera_id,cmr_u32 is_restart);
    cmr_s32 channel4_queue_buffer(struct prev_handle *handle, cmr_u32 camera_id,cam_buffer_info_t *buffer);
    int channel4_dequeue_buffer(struct prev_handle *handle, cmr_u32 camera_id,struct frm_info *info);
    cmr_int channel4_update_params(struct prev_handle *handle, cmr_u32 camera_id);
    cmr_s32 channel4_find_free_rot_buffer(struct prev_context *prev_cxt,cmr_u32 *index);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39

    10,功能的管理:fd、3dnr、ai_scene、ultra_wide、auto_tracking

    由于 ultra_wide、auto_tracking 我们项目一般不支持,先略过

    static cmr_int prev_fd_open(struct prev_handle *handle, cmr_u32 camera_id);
    static cmr_int prev_fd_close(struct prev_handle *handle, cmr_u32 camera_id);
    static cmr_int prev_fd_send_data(struct prev_handle *handle, cmr_u32 camera_id,struct img_frm *frm);
    static cmr_int prev_fd_cb(cmr_u32 class_type, struct ipm_frame_out *cb_param);
    static cmr_int prev_fd_ctrl(struct prev_handle *handle, cmr_u32 camera_id,cmr_u32 on_off);
    
    static cmr_int prev_3dnr_open(struct prev_handle *handle, cmr_u32 camera_id);
    static cmr_int prev_3dnr_close(struct prev_handle *handle, cmr_u32 camera_id);
    static cmr_int prev_3dnr_send_data(struct prev_handle *handle,cmr_u32 camera_id, struct frm_info *frm_info,struct camera_frame_type *frame_type,struct img_frm *frm,struct img_frm *video_frm);
    
    static cmr_int prev_ai_scene_send_data(struct prev_handle *handle,cmr_u32 camera_id, struct img_frm *frm,struct frm_info *frm_info);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    11,preview的buffer管理

    static cmr_int prev_set_preview_buffer(struct prev_handle *handle,cmr_u32 camera_id,cam_buffer_info_t *buffer);
    static cmr_int prev_pop_preview_buffer(struct prev_handle *handle,cmr_u32 camera_id, struct frm_info *data,cmr_u32 is_to_hal);
    static cmr_int prev_clear_preview_buffers(struct prev_handle *handle,cmr_u32 camera_id);
    
    • 1
    • 2
    • 3

    12,video的buffer管理

    static cmr_int prev_set_video_buffer(struct prev_handle *handle,cmr_u32 camera_id,cam_buffer_info_t *buffer);
    static cmr_int prev_pop_video_buffer_sw_3dnr(struct prev_handle *handle,cmr_u32 camera_id,struct frm_info *data,cmr_u32 is_to_hal);
    static cmr_int prev_pop_video_buffer(struct prev_handle *handle,cmr_u32 camera_id, struct frm_info *data,cmr_u32 is_to_hal);
    
    • 1
    • 2
    • 3

    13,zsl的buffer管理

    static cmr_int prev_set_zsl_buffer(struct prev_handle *handle,cmr_u32 camera_id, cmr_uint src_phy_addr,cmr_uint src_vir_addr, cmr_s32 fd);
    static cmr_int prev_pop_zsl_buffer(struct prev_handle *handle,cmr_u32 camera_id, struct frm_info *data,cmr_u32 is_to_hal);
    
    • 1
    • 2

    14,最后一条,也是比较关键的 prev_receive_data

    接收帧数据,我们在前一篇介绍cmr_grab的文章中看到,cmr_grab是oem端最开始拿到帧数据的地方,grab拿到帧数据后,会回调到cmr_preview这里来处理。

    static cmr_int prev_receive_data(struct prev_handle *handle, cmr_u32 camera_id,
                                     cmr_uint evt, struct frm_info *data);
    
    • 1
    • 2

    关于preview、video、zsl的buffer的管理,也有比较明显的共同之处,set 与 pop 是相反的操作,set是向帧数组中添加一个buffer,pop是去出一个buffer帧数据。与channel中的queue 与 dequeue,是一样的原理:

    set 、queque ===> 入队 ===> 入到数组的最后一个位置 ===> channel_buf_cfg

    pop、dequeue ===> 出队 ===> 取出数组中的第一个位置的数据 ===> 数组从2到lenght -1的位置前移,数组最后一个位置置null ===> callback 取出的第一个位置数据

    函数头的关键内容基本就是这些了,下面就来看下这些函数的具体实现,老规矩,函数内容我都是只截取关键部分。
    实现的逻辑我按照文件中的顺序来,与上面介绍的函数声明的顺序不往前匹配,但是关键内容就这这些函数头声明的函数。

    补充一个规律,cmr_preview.c中有很多以 cmr_preview_ 开头的函数,其内容是发送一个message,在message接收的地方在去做实际的逻辑。message的处理就是我们在函数声明的第一步介绍的几个thread,其中主要处理逻辑在prev_thread_proc 和prev_assist_thread_proc。prev_cb_thread_proc主要是处理帧数据回调到cmr_oem的

    实现详解

    1. init 与deinit
    2. 帧数据处理 :prev_frame_handle
    3. prev_preview_frame_handle
    4. 帧异常处理 prev_error_handle
    5. prev_start 开启预览
    6. 停止预览 prev_stop
    7. 申请 buffer :prev_alloc_prev_buf
    8. 释放buffer:prev_free_prev_buf
    9. channelX系列 — channel2_alloc_bufs
    10. channelX系列 — channel2_free_bufs
    11. channelX系列 — channel2_queue_buffer
    12. channelX系列 — channel2_dequeue_buffer
    13. channelX系列 — channel2_configure
    14. prev_alloc_prev_buf
    15. prev_freee_prev_buf
    16. 设置预览参数:prev_set_prev_param
    17. prev_set_param_internal

    1,init 与deinit

    cmr_preview_init 与 cmr_preview_deinit 主要式操作thread的创建与销毁

    cmr_int cmr_preview_init(struct preview_init_param *init_param_ptr,
                             cmr_handle *preview_handle_ptr) {
    	//接受handle参数
    	handle->oem_handle = init_param_ptr->oem_handle;
        handle->ipm_handle = init_param_ptr->ipm_handle;
        handle->sensor_bits = init_param_ptr->sensor_bits;
        handle->oem_cb = init_param_ptr->oem_cb;
        handle->ops = init_param_ptr->ops;
        handle->private_data = init_param_ptr->private_data;
    	
    	ret = prev_create_thread(handle);
    	ret = prev_create_cb_thread(handle);
    }
    
    cmr_int cmr_preview_deinit(cmr_handle preview_handle) {
       if (PREVIEWING == handle->prev_cxt[i].prev_status) {
                /*prev_stop(handle, i, 0);*/
                cmr_preview_stop(preview_handle, i);
        }
        ret = prev_destroy_thread(handle);
    
        ret = prev_destroy_cb_thread(handle);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    2,帧数据处理 :prev_frame_handle

    关键参数 struct frm_info *data

    cmr_int prev_frame_handle(struct prev_handle *handle, cmr_u32 camera_id,struct frm_info *data) 
    
        prev_cxt = &handle->prev_cxt[camera_id];
        preview_enable = prev_cxt->prev_param.preview_eb;
        snapshot_enable = prev_cxt->prev_param.snapshot_eb;
        video_enable = prev_cxt->prev_param.video_eb;
        channel0_eb = prev_cxt->prev_param.channel0_eb;
        channel1_eb = prev_cxt->prev_param.channel1_eb;
        channel2_eb = prev_cxt->prev_param.channel2_eb;
        channel3_eb = prev_cxt->prev_param.channel3_eb;
        channel4_eb = prev_cxt->prev_param.channel4_eb;
    //以普通预览为例(只配置了 预览和拍照 流)
    //preview_enable = 1 ,snapshot_enable  = 1, 其余channel全都是 0
    
        if (preview_enable && (data->channel_id == prev_cxt->prev_channel_id)) {
            if (prev_cxt->recovery_status != PREV_RECOVERY_IDLE &&
                data->fd != prev_cxt->prev_frm[0].fd) {
                CMR_LOGD("recoverying");
                return ret;
            }
            ret = prev_preview_frame_handle(handle, camera_id, data);
        }
    
        if (video_enable && (data->channel_id == prev_cxt->video_channel_id)) {
            ret = prev_video_frame_handle(handle, camera_id, data);
        }
    
        if (channel0_eb && (data->channel_id == prev_cxt->channel0.chn_id)) {
            CMR_LOGD("channel0_dequeue_buffer");
            ret = channel0_dequeue_buffer(handle, camera_id, data);
        }
    
        if (channel1_eb && (data->channel_id == prev_cxt->channel1.chn_id)) {
            CMR_LOGD("channel1_dequeue_buffer");
            ret = channel1_dequeue_buffer(handle, camera_id, data);
        }
    
        if (channel2_eb && (data->channel_id == prev_cxt->channel2.chn_id)) {
            CMR_LOGD("channel2_dequeue_buffer");
            ret = channel2_dequeue_buffer(handle, camera_id, data);
        }
    
        if (channel3_eb && (data->channel_id == prev_cxt->channel3.chn_id)) {
            CMR_LOGD("channel3_dequeue_buffer");
            ret = channel3_dequeue_buffer(handle, camera_id, data);
        }
    
        if (channel4_eb && (data->channel_id == prev_cxt->channel4.chn_id)) {
            CMR_LOGD("channel4_dequeue_buffer");
            ret = channel4_dequeue_buffer(handle, camera_id, data);
        }
    
        if (snapshot_enable && (data->channel_id == prev_cxt->cap_channel_id)) {
            if (prev_cxt->is_zsl_frm) {
                ret = prev_zsl_frame_handle(handle, camera_id, data);
            } else {
                ret = prev_capture_frame_handle(handle, camera_id, data);
            }
        }
        //上面的流程便只走 prev_preview_frame_handle 和 prev_zsl_frame_handle
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61

    下面我们分别来看 prev_preview_frame_handle 和 prev_zsl_frame_handle

    3,prev_preview_frame_handle

    prev_preview_frame_handle 一开始会做很所判断,是否是 ultra_wide、是否有 prev_cxt->prev_param.prev_rot,我们只关注一般情况下的分支流程,如下:

     else if (IMG_ANGLE_0 == prev_cxt->prev_param.prev_rot) {
            ret = prev_construct_frame(handle, camera_id, data, &frame_type);
            if (ret) {
                CMR_LOGE("construct frm err");
                goto exit;
            }
    
            if (prev_cxt->prev_param.sprd_3dnr_type != CAMERA_3DNR_TYPE_PREV_SW_VIDEO_SW &&
                prev_cxt->prev_param.sprd_3dnr_type != CAMERA_3DNR_TYPE_PREV_SW_CAP_SW)
            {
                prev_cxt->prev_buf_id = frame_type.buf_id;
                ret = prev_pop_preview_buffer(handle, camera_id, data, 0);
                if (ret) {
                    CMR_LOGE("pop frm 0x%x err", data->channel_id);
                    goto exit;
                    }
                /*notify frame via callback*/
                cb_data_info.cb_type = PREVIEW_EVT_CB_FRAME;
                cb_data_info.func_type = PREVIEW_FUNC_START_PREVIEW;
                cb_data_info.frame_data = &frame_type;
                prev_cb_start(handle, &cb_data_info);
             }
    
        } 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    这里有分为两步:prev_construct_frame 和 prev_pop_preview_buffer

    3.1 prev_construct_frame
    cmr_int prev_construct_frame(struct prev_handle *handle, cmr_u32 camera_id,struct frm_info *info,struct camera_frame_type *frame_type)
    
    • 1

    注意参数 struct frm_info *info 包含了帧数据
    1,根据 info 去调用 prev_get_frm_index 获取 frm_id (此info在预览帧数组的位置)

    frm_id = prev_get_frm_index(prev_cxt->prev_frm, info);
    
    • 1

    2,使用prev_cxt->prev_frm[frm_id] 填充 frame_type 对象

    		frm_ptr = &prev_cxt->prev_frm[frm_id];
            frame_type->buf_id = frm_id;
            frame_type->order_buf_id = frm_id;
            frame_type->y_vir_addr = prev_cxt->prev_frm[frm_id].addr_vir.addr_y;
            frame_type->y_phy_addr = prev_cxt->prev_frm[frm_id].addr_phy.addr_y;
            frame_type->fd = prev_cxt->prev_frm[frm_id].fd;
    
            frame_type->width = prev_cxt->prev_param.preview_size.width;
            frame_type->height = prev_cxt->prev_param.preview_size.height;
            frame_type->frame_num = info->frame_real_id;
            frame_type->timestamp = info->sec * 1000000000LL + info->usec * 1000LL;
            frame_type->monoboottime = info->monoboottime;
            frame_type->zoom_ratio =
                prev_cxt->prev_param.zoom_setting.zoom_info.zoom_ratio;
            frame_type->ae_time = ae_time;
            frame_type->vcm_step = (cmr_u32)prev_cxt->vcm_step;
            frame_type->type = PREVIEW_FRAME;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    3,如果打开了人脸检测

    prev_fd_send_data(handle, camera_id, frm_ptr);
    
    • 1

    4,符合 3dnr 的条件

    if (prev_cxt->prev_param.sprd_3dnr_type == CAMERA_3DNR_TYPE_PREV_SW_VIDEO_SW ||
                prev_cxt->prev_param.sprd_3dnr_type == CAMERA_3DNR_TYPE_PREV_SW_CAP_SW)
            {
                struct frm_info data;
                if (((void *)(frm_ptr->addr_vir.addr_y) != NULL) &&
                    (prev_cxt->prev_param.sprd_3dnr_type == CAMERA_3DNR_TYPE_PREV_SW_VIDEO_SW||
                    prev_cxt->prev_param.sprd_3dnr_type == CAMERA_3DNR_TYPE_PREV_SW_CAP_SW)) {
                    video_frm_id = frm_id;
                    video_frm_ptr = &prev_cxt->video_frm[frm_id];
                }
                ret = prev_3dnr_send_data(handle, camera_id, info,
                        frame_type, frm_ptr, video_frm_ptr);
            }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    5,打开了 ai_scene

    if (cxt->ipm_cxt.ai_scene_inited && cxt->ai_scene_enable == 1 && cxt->ref_camera_id == camera_id) {
                prev_ai_scene_send_data(handle, camera_id, frm_ptr, info);
            }
    
    • 1
    • 2
    • 3

    6,auto_tracking(暂不关注)

    总结下:prev_construct_frame 主要是根据入参 struct frm_info *info 来填充 入参frame_type,然后在将帧数据发送到各个需要从预览帧数据中跑算法的逻辑中。

    3.2 prev_pop_preview_buffer
    cmr_int prev_pop_preview_buffer(struct prev_handle *handle, cmr_u32 camera_id,struct frm_info *data, cmr_u32 is_to_hal)
    
    • 1

    我们在前面介绍过 pop 的主要流程:取出第一个位置的帧数据

    如下 if 也做了这个判断 ,本函数后面所有流程都在这个 if 成立的条件之下

    if ((prev_cxt->prev_frm[0].fd == (cmr_s32)data->fd) && valid_num > 0) {
        } 
    
    • 1
    • 2

    1,用第一个位置的帧数据填充 frame_type

     frame_type.y_phy_addr = prev_cxt->prev_frm[0].addr_phy.addr_y;
     frame_type.y_vir_addr = prev_cxt->prev_frm[0].addr_vir.addr_y;
     frame_type.fd = prev_cxt->prev_frm[0].fd;
     frame_type.frame_num = data->frame_real_id;
     frame_type.type = PREVIEW_CANCELED_FRAME;
    
    • 1
    • 2
    • 3
    • 4
    • 5

    2,预览帧数组左移

    for (i = 0; i < (cmr_u32)(valid_num - 1); i++) {
        prev_cxt->prev_phys_addr_array[i] =
             prev_cxt->prev_phys_addr_array[i + 1];
         prev_cxt->prev_virt_addr_array[i] =
             prev_cxt->prev_virt_addr_array[i + 1];
         prev_cxt->prev_fd_array[i] = prev_cxt->prev_fd_array[i + 1];
         memcpy(&prev_cxt->prev_frm[i], &prev_cxt->prev_frm[i + 1],
                sizeof(struct img_frm));
     }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    3,清空预览帧数组最后一个位置的内容

    prev_cxt->prev_phys_addr_array[valid_num - 1] = 0;
    prev_cxt->prev_virt_addr_array[valid_num - 1] = 0;
    prev_cxt->prev_fd_array[valid_num - 1] = 0;
    cmr_bzero(&prev_cxt->prev_frm[valid_num - 1], sizeof(struct img_frm));
    prev_cxt->prev_mem_valid_num--;
    
    • 1
    • 2
    • 3
    • 4
    • 5

    4,如果 is_to_hal ,回调刚刚 frame_type 保存的第一个位置的帧数据

    if (is_to_hal) {
        frame_type.timestamp = data->sec * 1000000000LL + data->usec * 1000LL;
        frame_type.monoboottime = data->monoboottime;
        cb_data_info.cb_type = PREVIEW_EVT_CB_FRAME;
        cb_data_info.func_type = PREVIEW_FUNC_START_PREVIEW;
        cb_data_info.frame_data = &frame_type;
        prev_cb_start(handle, &cb_data_info);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    到这里 prev_preview_frame_handle 的流程基本走完了,在它的最后有调用了一次 callback,参数就是我们在 prev_construct_frame 中填充的。(prev_pop_preview_buffer中调用回调有 is_to_hal 的条件限制)

    cb_data_info.cb_type = PREVIEW_EVT_CB_FRAME;
    cb_data_info.func_type = PREVIEW_FUNC_START_PREVIEW;
    cb_data_info.frame_data = &frame_type;
    prev_cb_start(handle, &cb_data_info);
    
    • 1
    • 2
    • 3
    • 4

    prev_preview_frame_handle 主要内容如下:
    通过prev_construct_frame 构建一个 frame_type,并将帧数据传给各个算法模块(fd、3dnr、ai_scene、auto_tracking)
    然后在通过prev_pop_preview_buffer 将帧数据的数组prev_cxt->prev_frm[] 整理下(去除第一个,后面的前移)
    最后在通过 prev_cb_start 将数据的第一个位置的帧数据回调上去。

    这是预览帧的处理,其它的比如video的帧处理函数 prev_video_frame_handle 、zsl的帧处理函数 prev_zsl_frame_handle 都是类似的流程。

    prev_construct_video_frame
    prev_pop_video_buffer
    
    prev_construct_zsl_frame
    prev_pop_zsl_buffer
    
    • 1
    • 2
    • 3
    • 4
    • 5

    4,帧异常处理 prev_error_handle

    参数 evt_type 指示了错误类型

    cmr_int prev_error_handle(struct prev_handle *handle, cmr_u32 camera_id,cmr_uint evt_type)
    
    • 1

    根据代码逻辑,大致分为两类

        case CMR_GRAB_TX_ERROR:
        case CMR_GRAB_CSI2_ERR:
    
        case CMR_SENSOR_ERROR:
        case CMR_GRAB_TIME_OUT:
    
    • 1
    • 2
    • 3
    • 4
    • 5

    我们常见的是 CMR_GRAB_TIME_OUT,超时为未出帧(5s)

        switch (evt_type) {
        case CMR_GRAB_TX_ERROR:
        case CMR_GRAB_CSI2_ERR:
            if (PREV_RECOVERING == prev_cxt->recovery_status) {
                prev_cxt->recovery_cnt--;
                CMR_LOGD("recovery_cnt, %ld", prev_cxt->recovery_cnt);
                if (prev_cxt->recovery_cnt) {
                    /* try once more */
                    mode = RECOVERY_MIDDLE;
                } else {
                    /* tried three times, it hasn't recovered yet, restart */
                    mode = RECOVERY_HEAVY;
                    prev_cxt->recovery_status = PREV_RECOVERY_DONE;
                }
            } else {
                /* now in recovering, start to recover three times */
                mode = RECOVERY_MIDDLE;
                prev_cxt->recovery_status = PREV_RECOVERING;
                prev_cxt->recovery_cnt = PREV_RECOVERY_CNT;
                CMR_LOGD("need recover, recovery_cnt=%ld", prev_cxt->recovery_cnt);
            }
            break;
    
        case CMR_SENSOR_ERROR:
        case CMR_GRAB_TIME_OUT:
            mode = RECOVERY_HEAVY;
            prev_cxt->recovery_status = PREV_RECOVERY_DONE;
            CMR_LOGD("sensor error, restart preview");
            break;
    
        default:
            CMR_LOGE("invalid evt_type");
            break;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    5,prev_start 开启预览

    1. 计算 channel_bits
    2. 开启预览
    3. 启动相应的功能 (与预览帧处理中的逻辑类似)
    5.1 计算 channel_bits

    根据计算逻辑看到,channel_bits 是各个配流channel的总和

        if (preview_enable)
            channel_bits |= 1 << prev_cxt->prev_channel_id;
        if (video_enable)
            channel_bits |= 1 << prev_cxt->video_channel_id;
        if (snapshot_enable)
            channel_bits |= 1 << prev_cxt->cap_channel_id;
        if (prev_cxt->prev_param.channel0_eb)
            channel_bits |= 1 << prev_cxt->channel0.chn_id;
        if (prev_cxt->prev_param.channel1_eb)
            channel_bits |= 1 << prev_cxt->channel1.chn_id;
        if (prev_cxt->prev_param.channel2_eb)
            channel_bits |= 1 << prev_cxt->channel2.chn_id;
        if (prev_cxt->prev_param.channel3_eb)
            channel_bits |= 1 << prev_cxt->channel3.chn_id;
        if (prev_cxt->prev_param.channel4_eb)
            channel_bits |= 1 << prev_cxt->channel4.chn_id;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    5.2 开启预览

    传入了上一步中的 channel_bits,表达的应该是同步开启channel_bit 中的流

    ret = handle->ops.channel_start(handle->oem_handle, channel_bits, skip_num);
    
    • 1
    5.3 启动相应的功能 (与预览帧处理中的逻辑类似)

    fd、ultra_wide、3ndr、auto_tracking

    if (prev_cxt->prev_param.is_support_fd) {
                prev_fd_open(handle, camera_id);
            }
            /*init ultra_wide*/
            if (prev_cxt->prev_param.is_ultra_wide) {
                prev_ultra_wide_open(handle, camera_id);
            }
            /*init 3dnr*/
           if (prev_cxt->prev_param.sprd_3dnr_type == CAMERA_3DNR_TYPE_PREV_SW_VIDEO_SW ||
                prev_cxt->prev_param.sprd_3dnr_type == CAMERA_3DNR_TYPE_PREV_SW_CAP_SW) {
                prev_3dnr_open(handle, camera_id);
            }
            /*init at, dual pd sensor default open 4d auto tracking */
            if (property_get_bool("persist.vendor.cam.auto.tracking.enable", 0) || pdaf_type == DUAL_PD) {
                if (!prev_cxt->auto_tracking_inited) {
                    prev_auto_tracking_open(handle, camera_id);
                    prev_cxt->auto_tracking_inited = 1;
                }
            }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    6,停止预览 prev_stop

    1. 计算channel_bit
    2. 停止预览
    3. 停止相应的功能
    4. 释放buffer
    6.1 计算channel_bit
    channel_bits
    
    • 1
    6.2 停止预览

    同上 传入 channel_bits,表达的应该是同步停止channel_bit 中的流

    ret = handle->ops.channel_stop(handle->oem_handle, channel_bits);
    
    • 1
    6.3 停止相应的功能

    fd、ultra_wide、3dnr、auto_tracking

        if (preview_enable) {
            if (is_restart && PREV_RECOVERY_IDLE != prev_cxt->recovery_status) {
                prev_cxt->prev_status = RECOVERING_IDLE;
            } else {
                prev_cxt->prev_status = IDLE;
            }
    
            /*deinit fd*/
            if (prev_cxt->prev_param.is_support_fd) {
                prev_fd_close(handle, camera_id);
            }
            /*deinit ultra wide*/
            if (prev_cxt->prev_param.is_ultra_wide) {
                prev_ultra_wide_close(handle, camera_id);
            }
    
            /*deinit 3dnr_preview*/
            if (prev_cxt->prev_param.sprd_3dnr_type == CAMERA_3DNR_TYPE_PREV_HW_CAP_SW ||
                      prev_cxt->prev_param.sprd_3dnr_type == CAMERA_3DNR_TYPE_PREV_SW_CAP_SW ||
                      prev_cxt->prev_param.sprd_3dnr_type == CAMERA_3DNR_TYPE_PREV_SW_VIDEO_SW) {
                prev_3dnr_close(handle, camera_id);
            }
            /*stop auto tracking*/
            if (prev_cxt->auto_tracking_inited) {
                prev_auto_tracking_close(handle, camera_id);
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    6.4 释放buffer
    1. 释放预览buffer,并回调通知
    2. 释放 video buffer
    3. 释放各个channel buffer
    4. 释放拍照相关的buffer
    //释放预览buffer,并回调通知
    if (preview_enable) {
         prev_post_set(handle, camera_id);
         prev_free_prev_buf(handle, camera_id, is_restart);
         
         if (!is_restart) {
             /*stop response*/
             cb_data_info.cb_type = PREVIEW_RSP_CB_SUCCESS;
             cb_data_info.func_type = PREVIEW_FUNC_STOP_PREVIEW;
             cb_data_info.frame_data = NULL;
             prev_cb_start(handle, &cb_data_info);
         }
         //释放 video buffer
        if (video_enable) {
            prev_free_video_buf(handle, camera_id, is_restart);
            valid_num = prev_cxt->video_mem_valid_num;
        }
    	
    	//释放各个channel buffer
    	    if (prev_cxt->prev_param.channel1_eb) {
            channel1_free_bufs(handle, camera_id, 0);
        }
    
        if (prev_cxt->prev_param.channel2_eb) {
            channel2_free_bufs(handle, camera_id, 0);
        }
    
        if (prev_cxt->prev_param.channel3_eb) {
            channel3_free_bufs(handle, camera_id, 0);
        }
    
        if (prev_cxt->prev_param.channel4_eb) {
            channel4_free_bufs(handle, camera_id, 0);
        }
    
    	//释放拍照相关的buffer
        if (snapshot_enable) {
            ret = handle->ops.capture_post_proc(handle->oem_handle, camera_id);
            prev_free_cap_buf(handle, camera_id, is_restart);
        }
        prev_free_cap_reserve_buf(handle, camera_id, is_restart);
        prev_free_zsl_buf(handle, camera_id, is_restart);
        prev_free_zsl_raw_buf(handle, camera_id, is_restart);
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45

    7,申请 buffer :prev_alloc_prev_buf

    1. 计算需要申请的mem_size
    2. 申请 CAMERA_PREVIEW
    3. 申请 CAMERA_PREVIEW_ULTRA_WIDE
    4. 计算 prev_cxt->prev_mem_valid_num 的值
    5. 申请 CAMERA_PREVIEW_RESERVED
    6. 填充 prev_cxt->prev_frm[] 和 入参 buffer_cfg *buffer
    7. 填充 prev_cxt->prev_reserved_frm
    8. 填充 prev_cxt->prev_rot_frm 和 prev_cxt->prev_ultra_wide_frm
    cmr_int prev_alloc_prev_buf(struct prev_handle *handle, cmr_u32 camera_id,cmr_u32 is_restart, struct buffer_cfg *buffer)
    
    • 1
    7.1 计算需要申请的mem_size
        if (CAM_IMG_FMT_YUV420_NV21 == prev_cxt->prev_param.preview_fmt ||
            CAM_IMG_FMT_YUV420_NV12 == prev_cxt->prev_param.preview_fmt ||
            CAM_IMG_FMT_BAYER_MIPI_RAW == prev_cxt->prev_param.preview_fmt) {
            prev_cxt->prev_mem_size = (width * height * 3) >> 1;
        } else if (CAM_IMG_FMT_YUV422P == prev_cxt->prev_param.preview_fmt) {
            prev_cxt->prev_mem_size = (width * height) << 1;
        } else if (CAM_IMG_FMT_YUV420_YV12 == prev_cxt->prev_param.preview_fmt) {
            if (IMG_ANGLE_90 == prev_cxt->prev_param.prev_rot ||
                IMG_ANGLE_270 == prev_cxt->prev_param.prev_rot) {
                prev_cxt->prev_mem_size =
                    (height + camera_get_aligned_size(aligned_type, height / 2)) *
                    width;
            } else {
                prev_cxt->prev_mem_size =
                    (width + camera_get_aligned_size(aligned_type, width / 2)) *
                    height;
            }
            prev_cxt->prev_param.preview_fmt = CAM_IMG_FMT_YUV420_NV21;
        } else {
            CMR_LOGE("unsupprot fmt %ld", prev_cxt->prev_param.preview_fmt);
            return CMR_CAMERA_INVALID_PARAM;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    7.2 申请 CAMERA_PREVIEW
    mem_ops->alloc_mem(
         CAMERA_PREVIEW, handle->oem_handle,
         (cmr_u32 *)&prev_cxt->prev_mem_size,
         (cmr_u32 *)&prev_cxt->prev_mem_num, prev_cxt->prev_phys_addr_array,
         prev_cxt->prev_virt_addr_array, prev_cxt->prev_fd_array);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    7.3 申请 CAMERA_PREVIEW_ULTRA_WIDE

    如果满足 prev_cxt->prev_param.is_ultra_wide 条件

    if (prev_cxt->prev_param.is_ultra_wide) {
      cmr_u32 prev_mem_size = prev_cxt->prev_mem_size;
      ultra_wide_mem_num = PREV_ULTRA_WIDE_ALLOC_CNT;
      CMR_LOGD("ultra wide gpu alloc 0x%lx, mem_num %ld",
               prev_cxt->prev_mem_size, ultra_wide_mem_num);
      mem_ops->gpu_alloc_mem(
          CAMERA_PREVIEW_ULTRA_WIDE, handle->oem_handle,
          (cmr_u32 *)&prev_mem_size, &ultra_wide_mem_num,
          prev_cxt->prev_phys_addr_array + prev_mem_num,
          prev_cxt->prev_virt_addr_array + prev_mem_num,
          prev_cxt->prev_fd_array + prev_mem_num,
          prev_cxt->prev_ultra_wide_handle_array, &real_width,
          &real_height);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    7.4 计算 prev_cxt->prev_mem_valid_num 的值
     for (i = 0; i < (prev_mem_num + ultra_wide_mem_num); i++) {
         if ((0 == prev_cxt->prev_virt_addr_array[i]) ||
             (0 == prev_cxt->prev_fd_array[i])) {
             if (i >= PREV_FRM_ALLOC_CNT) {
                 CMR_LOGE("memory is invalid");
                 return CMR_CAMERA_NO_MEM;
             }
         } else {
             if (i < PREV_FRM_ALLOC_CNT) {
                 prev_cxt->prev_mem_valid_num++;
             }
         }
     }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    7.5 申请 CAMERA_PREVIEW_RESERVED
    mem_ops->alloc_mem(
        CAMERA_PREVIEW_RESERVED, handle->oem_handle,
        (cmr_u32 *)&prev_cxt->prev_mem_size, (cmr_u32 *)&reserved_count,
        &prev_cxt->prev_reserved_phys_addr,
        &prev_cxt->prev_reserved_virt_addr, &prev_cxt->prev_reserved_fd);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    7.6 填充 prev_cxt->prev_frm[] 和 入参 buffer_cfg *buffer

    使用前面调用 mem_ops->alloc_mem时传入的
    prev_cxt->prev_virt_addr_array 和
    prev_cxt->prev_phys_addr_array
    来赋值 prev_cxt->prev_frm 和 buffer_cfg

    for (i = 0; i < (cmr_uint)prev_cxt->prev_mem_valid_num; i++) {
        prev_cxt->prev_frm[i].buf_size = frame_size;
        prev_cxt->prev_frm[i].addr_vir.addr_y = prev_cxt->prev_virt_addr_array[i];
        prev_cxt->prev_frm[i].addr_vir.addr_u = prev_cxt->prev_frm[i].addr_vir.addr_y + buffer_size;
        prev_cxt->prev_frm[i].addr_phy.addr_y = prev_cxt->prev_phys_addr_array[i];
        prev_cxt->prev_frm[i].addr_phy.addr_u = prev_cxt->prev_frm[i].addr_phy.addr_y + buffer_size;
        prev_cxt->prev_frm[i].fd = prev_cxt->prev_fd_array[i];
        prev_cxt->prev_frm[i].fmt = prev_cxt->prev_param.preview_fmt;
        prev_cxt->prev_frm[i].size.width = prev_cxt->actual_prev_size.width;
        prev_cxt->prev_frm[i].size.height = prev_cxt->actual_prev_size.height;
    
        buffer->addr[i].addr_y = prev_cxt->prev_frm[i].addr_phy.addr_y;
        buffer->addr[i].addr_u = prev_cxt->prev_frm[i].addr_phy.addr_u;
        buffer->addr_vir[i].addr_y = prev_cxt->prev_frm[i].addr_vir.addr_y;
        buffer->addr_vir[i].addr_u = prev_cxt->prev_frm[i].addr_vir.addr_u;
        buffer->fd[i] = prev_cxt->prev_frm[i].fd;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    7.7 填充 prev_cxt->prev_reserved_frm
    prev_cxt->prev_reserved_frm.buf_size = frame_size;
    prev_cxt->prev_reserved_frm.addr_vir.addr_y = prev_cxt->prev_reserved_virt_addr;
    prev_cxt->prev_reserved_frm.addr_vir.addr_u = prev_cxt->prev_reserved_frm.addr_vir.addr_y + buffer_size;
    prev_cxt->prev_reserved_frm.addr_phy.addr_y = prev_cxt->prev_reserved_phys_addr;
    prev_cxt->prev_reserved_frm.addr_phy.addr_u = prev_cxt->prev_reserved_frm.addr_phy.addr_y + buffer_size;
    prev_cxt->prev_reserved_frm.fd = prev_cxt->prev_reserved_fd;
    
    prev_cxt->prev_reserved_frm.fmt = prev_cxt->prev_param.preview_fmt;
    prev_cxt->prev_reserved_frm.size.width = prev_cxt->actual_prev_size.width;
    prev_cxt->prev_reserved_frm.size.height = prev_cxt->actual_prev_size.height;
    
    prev_cxt->prev_frm[i].addr_phy.addr_v = 0;
    prev_cxt->prev_reserved_frm.addr_phy.addr_v = 0;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    7.8 填充 prev_cxt->prev_rot_frm 和 prev_cxt->prev_ultra_wide_frm

    如果满足相应条件(一般项目都是false)

    if (prev_cxt->prev_param.prev_rot) {
       for (i = 0; i < PREV_ROT_FRM_ALLOC_CNT; i++) {
           prev_cxt->prev_rot_frm[i].buf_size = frame_size;
           prev_cxt->prev_rot_frm[i].addr_vir.addr_y = prev_cxt->prev_virt_addr_array[prev_num + i];
           prev_cxt->prev_rot_frm[i].addr_vir.addr_u = prev_cxt->prev_rot_frm[i].addr_vir.addr_y + buffer_size;
           prev_cxt->prev_rot_frm[i].addr_phy.addr_y = prev_cxt->prev_phys_addr_array[prev_num + i];
           prev_cxt->prev_rot_frm[i].addr_phy.addr_u = prev_cxt->prev_rot_frm[i].addr_phy.addr_y + buffer_size;
           prev_cxt->prev_rot_frm[i].addr_phy.addr_v = 0;
           prev_cxt->prev_rot_frm[i].fd = prev_cxt->prev_fd_array[prev_num + i];
           prev_cxt->prev_rot_frm[i].fmt = prev_cxt->prev_param.preview_fmt;
           prev_cxt->prev_rot_frm[i].size.width = prev_cxt->actual_prev_size.width;
           prev_cxt->prev_rot_frm[i].size.height = prev_cxt->actual_prev_size.height;
       }
    }
    if (prev_cxt->prev_param.is_ultra_wide) {
       for (i = 0; i < PREV_ULTRA_WIDE_ALLOC_CNT; i++) {
           prev_cxt->prev_ultra_wide_frm[i].buf_size = frame_size;
           prev_cxt->prev_ultra_wide_frm[i].addr_vir.addr_y = prev_cxt->prev_virt_addr_array[prev_num + i];
           prev_cxt->prev_ultra_wide_frm[i].addr_vir.addr_u = prev_cxt->prev_ultra_wide_frm[i].addr_vir.addr_y + buffer_size;
           prev_cxt->prev_ultra_wide_frm[i].addr_phy.addr_y = prev_cxt->prev_phys_addr_array[prev_num + i];
           prev_cxt->prev_ultra_wide_frm[i].addr_phy.addr_u = prev_cxt->prev_ultra_wide_frm[i].addr_phy.addr_y + buffer_size;
           prev_cxt->prev_ultra_wide_frm[i].addr_phy.addr_v = 0;
           prev_cxt->prev_ultra_wide_frm[i].fd = prev_cxt->prev_fd_array[prev_num + i];
           prev_cxt->prev_ultra_wide_frm[i].fmt = prev_cxt->prev_param.preview_fmt;
           prev_cxt->prev_ultra_wide_frm[i].size.width = prev_cxt->actual_prev_size.width;
           prev_cxt->prev_ultra_wide_frm[i].size.height = prev_cxt->actual_prev_size.height;
       }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    8,释放buffer:prev_free_prev_buf

    释放的操作与申请的操作是相对的,申请了什么,就要释放什么

    1. 释放 CAMERA_PREVIEW
    2. 释放 CAMERA_PREVIEW_ULTRA_WIDE
    3. 释放 CAMERA_PREVIEW_RESERVED
    mem_ops->free_mem(CAMERA_PREVIEW, handle->oem_handle,
                      prev_cxt->prev_phys_addr_array,
                      prev_cxt->prev_virt_addr_array,
                      prev_cxt->prev_fd_array, prev_cxt->prev_mem_num);
                      
    if (prev_cxt->prev_param.is_ultra_wide) {
        mem_ops->free_mem(CAMERA_PREVIEW_ULTRA_WIDE, handle->oem_handle,
                          prev_cxt->prev_phys_addr_array + prev_mem_num,
                          prev_cxt->prev_virt_addr_array + prev_mem_num,
                          prev_cxt->prev_fd_array + prev_mem_num,
                          ultra_wide_mem_num);
        cmr_bzero(prev_cxt->prev_ultra_wide_handle_array,
                  (ultra_wide_mem_num) * sizeof(void *));
    }
    
    mem_ops->free_mem(CAMERA_PREVIEW_RESERVED, handle->oem_handle,
                      (cmr_uint *)prev_cxt->prev_reserved_phys_addr,
                      (cmr_uint *)prev_cxt->prev_reserved_virt_addr,
                      &prev_cxt->prev_reserved_fd, (cmr_u32)1);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • video buffer 的申请与释放
      prev_alloc_video_buf、prev_free_video_buf

    • cap buffer 的的申请与释放
      prev_alloc_cap_buf、prev_free_cap_buf

    • cap_reserve buffer 的的申请与释放
      prev_alloc_cap_reserve_buf、prev_free_cap_reserve_buf

    • zsl buffer 的的申请与释放
      prev_alloc_zsl_buf、prev_free_zsl_buf

    • prev_free_zsl_raw_buf

    • 4in1 的的申请与释放
      prev_alloc_4in1_buf、prev_free_4in1_buf

    都是与preview的alloc 与 free 是类似的

    9,channelX系列 — channel2_alloc_bufs

    alloc_buffer 流程基本是与上面介绍preview alloc_buffer是类似的,我们以 channel2 为例在看下

    1. 计算需要申请的 buf_size
    2. 申请 CAMERA_CHANNEL_2 (如果满足条件)
    3. 申请 CAMERA_CHANNEL_2_RESERVED
    4. 给 prev_cxt->channel2.frm[] 和 入参 buffer_cfg *buffer 赋值
    5. 给 prev_cxt->channel2.frm_reserved 赋值
    6. 给 channel2.rot_frm 赋值
    9.1 计算需要申请的 buf_size

    log打印这个format一般都是 CAM_IMG_FMT_YUV420_NV21

     if (CAM_IMG_FMT_YUV420_NV21 == prev_cxt->prev_param.channel2_fmt ||
         CAM_IMG_FMT_YUV420_NV12 == prev_cxt->prev_param.channel2_fmt) {
         prev_cxt->channel2.buf_size = (width * height * 3) >> 1;
     } else if (CAM_IMG_FMT_YUV422P == prev_cxt->prev_param.channel2_fmt) {
         prev_cxt->channel2.buf_size = (width * height) << 1;
     } else if (CAM_IMG_FMT_YUV420_YV12 == prev_cxt->prev_param.channel2_fmt) {
         prev_cxt->channel2.buf_size = (width * height * 3) >> 1;
         prev_cxt->prev_param.channel2_fmt = CAM_IMG_FMT_YUV420_NV21;
     } else if (CAM_IMG_FMT_BAYER_MIPI_RAW ==
                prev_cxt->prev_param.channel2_fmt) {
         prev_cxt->channel2.buf_size = (width * height) << 1;
     } else {
         CMR_LOGE("unsupprot fmt %d", prev_cxt->prev_param.channel2_fmt);
         return CMR_CAMERA_INVALID_PARAM;
     }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    9.2 申请 CAMERA_CHANNEL_2 (如果满足条件)
        if (prev_cxt->prev_param.channel2_rot_angle) {
            CMR_LOGD("rotation need more buffer");
            prev_cxt->channel2.buf_cnt += CHANNEL2_BUF_CNT_ROT;
            if (!is_restart) {
                mem_ops->alloc_mem(CAMERA_CHANNEL_2, handle->oem_handle,
                                   &prev_cxt->channel2.buf_size,
                                   &prev_cxt->channel2.buf_cnt,
                                   &prev_cxt->channel2.addr_phy[CHANNEL2_BUF_CNT],
                                   &prev_cxt->channel2.addr_vir[CHANNEL2_BUF_CNT],
                                   &prev_cxt->channel2.fd[CHANNEL2_BUF_CNT]);
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    9.3 申请 CAMERA_CHANNEL_2_RESERVED
    if (!is_restart) {
        prev_cxt->channel2.valid_buf_cnt = 0;
        rot_frm_start_num = CHANNEL2_BUF_CNT;
        mem_ops->alloc_mem(CAMERA_CHANNEL_2_RESERVED, handle->oem_handle,
                           &prev_cxt->channel2.buf_size, &reserved_count,
                           &prev_cxt->channel2.frm_reserved.addr_phy.addr_y,
                           &prev_cxt->channel2.frm_reserved.addr_vir.addr_y,
                           &prev_cxt->channel2.frm_reserved.fd);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    9.4 给 prev_cxt->channel2.frm[] 和 入参 buffer_cfg *buffer 赋值

    注意:这里我还有点疑问,这里是用 prev_cxt->channel2.addr_vir 去赋值的,但是上面alloc_mem的时候,一般 channel2_rot_angle 条件是false的,prev_cxt->channel2.addr_vir 是没有申请到地址的,但这里仍然是吧 prev_cxt->channel2.addr_vir 赋值给prev_cxt->channel2.frm[] 和 入参 buffer_cfg *buffer。

    for (i = 0; i < (cmr_uint)prev_cxt->channel2.valid_buf_cnt; i++) {
        prev_cxt->channel2.frm[i].fmt = prev_cxt->prev_param.channel2_fmt;
        prev_cxt->channel2.frm[i].buf_size = prev_cxt->channel2.buf_size;
        prev_cxt->channel2.frm[i].size.width = prev_cxt->channel2.size.width;
        prev_cxt->channel2.frm[i].size.height = prev_cxt->channel2.size.height;
    
        prev_cxt->channel2.frm[i].addr_vir.addr_y = prev_cxt->channel2.addr_vir[i];
        prev_cxt->channel2.frm[i].addr_vir.addr_u = prev_cxt->channel2.frm[i].addr_vir.addr_y + width * height;
    
        prev_cxt->channel2.frm[i].addr_phy.addr_y = prev_cxt->channel2.addr_phy[i];
        prev_cxt->channel2.frm[i].addr_phy.addr_u = prev_cxt->channel2.frm[i].addr_phy.addr_y + width * height;
        prev_cxt->channel2.frm[i].fd = prev_cxt->channel2.fd[i];
    
        buffer->addr[i].addr_y = prev_cxt->channel2.frm[i].addr_phy.addr_y;
        buffer->addr[i].addr_u = prev_cxt->channel2.frm[i].addr_phy.addr_u;
        buffer->addr_vir[i].addr_y = prev_cxt->channel2.frm[i].addr_vir.addr_y;
        buffer->addr_vir[i].addr_u = prev_cxt->channel2.frm[i].addr_vir.addr_u;
        buffer->fd[i] = prev_cxt->channel2.frm[i].fd;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    9.5 给 prev_cxt->channel2.frm_reserved 赋值

    注意:这里的 addr_vir.addr_y 和 addr_phy.addr_y 都被注释掉了。

    prev_cxt->channel2.frm_reserved.fmt = prev_cxt->prev_param.channel2_fmt;
    prev_cxt->channel2.frm_reserved.buf_size = prev_cxt->channel2.buf_size;
    prev_cxt->channel2.frm_reserved.size.width = width;
    prev_cxt->channel2.frm_reserved.size.height = height;
    //prev_cxt->channel2.frm_reserved.addr_vir.addr_y =
        //prev_cxt->channel2.frm_reserved.addr_vir.addr_y;
    prev_cxt->channel2.frm_reserved.addr_vir.addr_u =
        prev_cxt->channel2.frm_reserved.addr_vir.addr_y + width * height;
    //prev_cxt->channel2.frm_reserved.addr_phy.addr_y =
        //prev_cxt->channel2.frm_reserved.addr_phy.addr_y;
    prev_cxt->channel2.frm_reserved.addr_phy.addr_u =
        prev_cxt->channel2.frm_reserved.addr_phy.addr_y + width * height;
    //prev_cxt->channel2.frm_reserved.fd = prev_cxt->channel2.frm_reserved.fd;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    9.6 给 channel2.rot_frm 赋值
    if (prev_cxt->prev_param.channel2_rot_angle) {
    	for (i = 0; i < CHANNEL2_BUF_CNT_ROT; i++) {
    	    prev_cxt->channel2.rot_frm[i].fmt = prev_cxt->prev_param.channel2_fmt;
    	    prev_cxt->channel2.rot_frm[i].buf_size = prev_cxt->channel2.buf_size;
    	    prev_cxt->channel2.rot_frm[i].size.width = prev_cxt->channel2.size.width;
    	    prev_cxt->channel2.rot_frm[i].size.height = prev_cxt->channel2.size.height;
    	    prev_cxt->channel2.rot_frm[i].addr_vir.addr_y = prev_cxt->channel2.addr_vir[rot_frm_start_num + i];
    	    prev_cxt->channel2.rot_frm[i].addr_vir.addr_u = prev_cxt->channel2.rot_frm[i].addr_vir.addr_y + width * height;
    	    prev_cxt->channel2.rot_frm[i].addr_phy.addr_y = prev_cxt->channel2.addr_phy[rot_frm_start_num + i];
    	    prev_cxt->channel2.rot_frm[i].addr_phy.addr_u = prev_cxt->channel2.rot_frm[i].addr_phy.addr_y + width * height;
    	    prev_cxt->channel2.rot_frm[i].fd = prev_cxt->channel2.fd[rot_frm_start_num + i];
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    10,channelX系列 — channel2_free_bufs

    free_mem :CAMERA_CHANNEL_2 和 CAMERA_CHANNEL_2_RESERVED

        if (!is_restart) {
            mem_ops->free_mem(CAMERA_CHANNEL_2, handle->oem_handle,
                              prev_cxt->channel2.addr_phy,
                              prev_cxt->channel2.addr_vir, prev_cxt->channel2.fd,
                              prev_cxt->channel2.buf_cnt);
            cmr_bzero(prev_cxt->channel2.addr_phy,
                      (CHANNEL2_BUF_CNT + CHANNEL2_BUF_CNT_ROT) *
                          sizeof(unsigned long));
            cmr_bzero(prev_cxt->channel2.addr_vir,
                      (CHANNEL2_BUF_CNT + CHANNEL2_BUF_CNT_ROT) *
                          sizeof(unsigned long));
            cmr_bzero(prev_cxt->channel2.fd,
                      (CHANNEL2_BUF_CNT + CHANNEL2_BUF_CNT_ROT) * sizeof(cmr_s32));
            mem_ops->free_mem(
                CAMERA_CHANNEL_2_RESERVED, handle->oem_handle,
                (cmr_uint *)prev_cxt->channel2.frm_reserved.addr_phy.addr_y,
                (cmr_uint *)prev_cxt->channel2.frm_reserved.addr_vir.addr_y,
                &prev_cxt->channel2.frm_reserved.fd, 1);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    11,channelX系列 — channel2_queue_buffer

    1. 将入参 cam_buffer_info_t *buffer 赋值给 prev_cxt->channel2 的最后一位
    2. 将 prev_cxt->channel2 的 地址赋值给 prev_cxt->channel2.frm[] 的最后一位
    3. 赋值 buffer_cfg buf_cfg
    4. 调用 channel_buff_cfg
    11.1 将入参 cam_buffer_info_t *buffer 赋值给 prev_cxt->channel2 的最后一位
    prev_cxt->channel2.fd[valid_num] = buffer->fd;
    prev_cxt->channel2.addr_phy[valid_num] = (unsigned long)buffer->addr_phy;
    prev_cxt->channel2.addr_vir[valid_num] = (unsigned long)buffer->addr_vir;
    
    • 1
    • 2
    • 3
    11.2 将 prev_cxt->channel2 的 地址赋值给 prev_cxt->channel2.frm[] 的最后一位
    prev_cxt->channel2.frm[valid_num].fmt = prev_cxt->prev_param.channel2_fmt;
    prev_cxt->channel2.frm[valid_num].buf_size = prev_cxt->channel2.buf_size;
    prev_cxt->channel2.frm[valid_num].size.width = width;
    prev_cxt->channel2.frm[valid_num].size.height = height;
    prev_cxt->channel2.frm[valid_num].fd = prev_cxt->channel2.fd[valid_num];
    prev_cxt->channel2.frm[valid_num].addr_phy.addr_y = prev_cxt->channel2.addr_phy[valid_num];
    prev_cxt->channel2.frm[valid_num].addr_phy.addr_u = prev_cxt->channel2.frm[valid_num].addr_phy.addr_y + width * height;
    prev_cxt->channel2.frm[valid_num].addr_vir.addr_y = prev_cxt->channel2.addr_vir[valid_num];
    prev_cxt->channel2.frm[valid_num].addr_vir.addr_u = prev_cxt->channel2.frm[valid_num].addr_vir.addr_y + width * height;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    11.3 赋值 buffer_cfg buf_cfg
    buf_cfg.addr[0].addr_y = prev_cxt->channel2.frm[valid_num].addr_phy.addr_y;
    buf_cfg.addr[0].addr_u = prev_cxt->channel2.frm[valid_num].addr_phy.addr_u;
    buf_cfg.addr_vir[0].addr_y = prev_cxt->channel2.frm[valid_num].addr_vir.addr_y;
    buf_cfg.addr_vir[0].addr_u = prev_cxt->channel2.frm[valid_num].addr_vir.addr_u;
    buf_cfg.fd[0] = prev_cxt->channel2.frm[valid_num].fd;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    11.4 调用 channel_buff_cfg
    ret = handle->ops.channel_buff_cfg(handle->oem_handle, &buf_cfg);
    
    • 1

    12,channelX系列 — channel2_dequeue_buffer

    1. 使用 prev_cxt->channel2.frm[0]的信息给 camera_frame_type frame_type 赋值
    2. 左移 prev_cxt->channel2 和 prev_cxt->channel2.frm
    3. 将 prev_cxt->channel2 和 prev_cxt->channel2.frm 的最后一位赋值为0
    4. 将步骤1中构建的 frame_type 回调上去
    12.1 使用 prev_cxt->channel2.frm[0]的信息给 camera_frame_type frame_type 赋值
    frame_type.buf_id = 0;
    frame_type.order_buf_id = 0;
    frame_type.y_vir_addr = prev_cxt->channel2.frm[0].addr_vir.addr_y;
    frame_type.uv_vir_addr = prev_cxt->channel2.frm[0].addr_vir.addr_u;
    frame_type.fd = prev_cxt->channel2.frm[0].fd;
    frame_type.y_phy_addr = prev_cxt->channel2.frm[0].addr_phy.addr_y;
    frame_type.uv_phy_addr = prev_cxt->channel2.frm[0].addr_phy.addr_u;
    frame_type.width = prev_cxt->channel2.size.width;
    frame_type.height = prev_cxt->channel2.size.height;
    frame_type.timestamp = info->sec * 1000000000LL + info->usec * 1000LL;
    frame_type.monoboottime = info->monoboottime;
    frame_type.type = CHANNEL2_FRAME;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    12.2 左移 prev_cxt->channel2 和 prev_cxt->channel2.frm
    valid_buf_cnt = prev_cxt->channel2.valid_buf_cnt;
     for (i = 0; i < (int)valid_buf_cnt - 1; i++) {
         prev_cxt->channel2.fd[i] = prev_cxt->channel2.fd[i + 1];
         prev_cxt->channel2.addr_phy[i] = prev_cxt->channel2.addr_phy[i + i];
         prev_cxt->channel2.addr_vir[i] = prev_cxt->channel2.addr_vir[i + 1];
         prev_cxt->channel2.frm[i] = prev_cxt->channel2.frm[i + 1];
     }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    12.3 将 prev_cxt->channel2 和 prev_cxt->channel2.frm 的最后一位置为null
     prev_cxt->channel2.fd[valid_buf_cnt - 1] = 0;
     prev_cxt->channel2.addr_phy[valid_buf_cnt - 1] = 0;
     prev_cxt->channel2.addr_vir[valid_buf_cnt - 1] = 0;
     cmr_bzero(&prev_cxt->channel2.frm[valid_buf_cnt - 1],sizeof(struct img_frm));
    
    • 1
    • 2
    • 3
    • 4
    12.4 将步骤1中构建的 frame_type 回调上去
    cb_data_info.cb_type = PREVIEW_EVT_CB_FRAME;
    cb_data_info.func_type = PREVIEW_FUNC_START_PREVIEW;
    cb_data_info.frame_data = &frame_type;
    prev_cb_start(handle, &cb_data_info);
    
    • 1
    • 2
    • 3
    • 4

    13,channelX系列 — channel2_configure

    confiugre的关键流程大概就是如下3个步骤,搞清楚了前面的流程,configure就很好理解了。

    1. channel2_alloc_bufs
    2. channel_cfg
    3. channel_buff_cfg

    14,prev_alloc_prev_buf

    preview的 buffer 操作与 channel系列非常相似,但是preview太重要了,我们还是尽量简单的一下

    1. 根据 preview_fmt 计算需要申请的 prev_mem_size
    2. 申请 CAMERA_PREVIEW
    3. 申请 CAMERA_PREVIEW_ULTRA_WIDE (有条件)
    4. 计算 prev_cxt->prev_mem_valid_num
    5. 申请 CAMERA_PREVIEW_RESERVED
    6. 给 prev_cxt->prev_frm[] 和 入参 buffer_cfg *buffer 赋值
    7. 给 prev_cxt->prev_reserved_frm 赋值
    8. 给 prev_cxt->prev_ultra_wide_frm[] 赋值(有条件)

    15,prev_free_prev_buf

    1. 释放 CAMERA_PREVIEW
    2. 释放 CAMERA_PREVIEW_ULTRA_WIDE (有条件)
    3. 释放 CAMERA_PREVIEW_RESERVED

    16,设置预览参数:prev_set_prev_param

    1. 构建 struct channel_start_param chn_param;
    2. 调用 prev_get_sn_inf
    3. prev_alloc_prev_buf(handle, camera_id, is_restart, &chn_param.buffer);
    4. handle->ops.channel_cfg(handle->oem_handle, handle, camera_id,&chn_param, &channel_id, &endian);
    5. handle->ops.channel_buff_cfg(handle->oem_handle, &chn_param.buffer); ===》prev_cxt->prev_frm[]
    6. handle->ops.channel_buff_cfg(handle->oem_handle, &buf_cfg); == 》prev_cxt->prev_reserved_frm

    17,prev_set_param_internal

    根据当前各个流配置的 enable 情况,调用set_XXX_param.

    1. prev_set_prev_param
    2. prev_set_video_param
    3. channel0_configure
    4. channel1_configure
    5. channel2_configure
    6. channel3_configure
    7. channel4_configure
    8. prev_set_cap_param
        if (handle->prev_cxt[camera_id].prev_param.preview_eb) {
            ret =prev_set_prev_param(handle, camera_id, is_restart, out_param_ptr);
            if (ret) {
                CMR_LOGE("set prev param failed");
                goto exit;
            }
        }
    
        if (handle->prev_cxt[camera_id].prev_param.video_eb) {
            ret = prev_set_video_param(handle, camera_id, is_restart, out_param_ptr);
            if (ret) {
                CMR_LOGE("set video param failed");
                goto exit;
            }
        }
    
        if (handle->prev_cxt[camera_id].prev_param.channel0_eb) {
            ret = channel0_configure(handle, camera_id, is_restart, out_param_ptr);
            if (ret) {
                CMR_LOGE("channel0_configure failed");
                goto exit;
            }
        }
    
        if (handle->prev_cxt[camera_id].prev_param.channel1_eb) {
            ret = channel1_configure(handle, camera_id, is_restart, out_param_ptr);
            if (ret) {
                CMR_LOGE("channel1_configure failed");
                goto exit;
            }
        }
    
        if (handle->prev_cxt[camera_id].prev_param.channel2_eb) {
            ret = channel2_configure(handle, camera_id, is_restart, out_param_ptr);
            if (ret) {
                CMR_LOGE("channel2_configure failed");
                goto exit;
            }
        }
    
        setting_param.camera_id = cxt->camera_id;
        ret = cmr_setting_ioctl(setting_cxt->setting_handle,
                             SETTING_GET_APPMODE, &setting_param);
        app_mode = setting_param.cmd_type_value;
        CMR_LOGD("app mode =%d",app_mode);
        property_get("persist.vendor.cam.fast.automode", value, "null");//persist.vendor.cam.fast.automode = true
        config_thumb = (cxt->is_multi_mode != MODE_MULTI_CAMERA && app_mode == 0 && !strcmp(value,"true"));
        if(!config_thumb) {
            if (handle->prev_cxt[camera_id].prev_param.channel3_eb) {
                ret = channel3_configure(handle, camera_id, is_restart, out_param_ptr);
                if (ret) {
                    CMR_LOGE("channel3_configure failed");
                    goto exit;
                }
            }
        }
    
        if (handle->prev_cxt[camera_id].prev_param.channel4_eb) {
            ret = channel4_configure(handle, camera_id, is_restart, out_param_ptr);
            if (ret) {
                CMR_LOGE("channel4_configure failed");
                goto exit;
            }
        }
    	if (handle->prev_cxt[camera_id].prev_param.snapshot_eb) {
    		ret = prev_set_cap_param(handle, camera_id, is_restart, 0,out_param_ptr);
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67

    关于cmr_preivew.c的介绍据就基本结束了,我看看到,这个文件虽然叫cmr_preview,但是其内容却包含了preivew、caprure、video、channel系列的管理配置。导致这个文件内容特别长,我们本篇的介绍也很长。希望大家能耐心的读下来。

  • 相关阅读:
    封装window10-21H1踩的坑,无法分析或处理pass[specialize]应答文件
    第四天:gec6818开发板串口蓝牙模块的使用与配置
    DaVinci:套底流程
    Matlab图像分割与特征提取的实践指南
    使用Java实现一个简单的贪吃蛇小游戏
    武田公司2022财年第一季度业绩强劲;正稳步实现全年的管理层指引目标
    软件架构师必需要了解的 saas 架构设计?
    Azure Data Factory(九)基础知识回顾
    离散数学 一阶逻辑基本概念 习题
    Java_递归
  • 原文地址:https://blog.csdn.net/u010869159/article/details/126016040