/* * Copyright (C) 2021 Alibaba Group Holding Limited * Author: LuChongzhi * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ #include #include #include #include #include #include #define LOG_LEVEL 2 #define LOG_PREFIX "cam_demo_simple" #include #include #include #include "csi_camera_dev_api.h" // #include "vi_mem.h" #ifdef PLATFORM_SIMULATOR #include "apputilities.h" #endif static void dump_camera_meta(csi_frame_s *frame); static void dump_camera_frame(csi_frame_s *frame, csi_pixel_fmt_e fmt); #define TEST_DEVICE_NAME "/dev/video0" #define CSI_CAMERA_TRUE 1 #define CSI_CAMERA_FALSE 0 typedef struct frame_fps { uint64_t frameNumber; struct timeval initTick; float fps; } frame_fps_t; typedef struct cb_context{ int id; csi_cam_handle_t cam_handle; int dsp_id; int dsp_path; void *ref_buf; int buf_size; }cb_context_t; typedef struct cb_args{ char setting[16]; uint32_t frame_id; uint32_t timestap; }cb_args_t; cb_context_t cb_context[2]; void dsp_algo_result_cb(void*context,void*arg) { cb_context_t *ctx = (cb_context_t *)context; cb_args_t *cb_args= (cb_args_t*)arg; char update_setting[16]; uint32_t frame_id = cb_args->frame_id; uint32_t frame_timestap = cb_args->timestap; LOG_O("cb:%d,setting:%s,frame :%d,timestad:0x%x\n",ctx->id,cb_args->setting,frame_id,frame_timestap); sprintf(update_setting, "update_%d", frame_id); csi_camera_update_dsp_algo_setting(ctx->cam_handle,ctx->dsp_id,ctx->dsp_path,update_setting); if(frame_id%20) { void *replace_buf; csi_camera_update_dsp_algo_buf(ctx->cam_handle, ctx->dsp_id,ctx->dsp_path,ctx->ref_buf,&replace_buf); LOG_O("cb:%d,old buffer:0x%lx,new buffer:0x%lx\n",ctx->id,(uint64_t)ctx->ref_buf,(uint64_t)replace_buf); ctx->ref_buf = replace_buf; } } static void usage(void) { printf(" 1 : video id cases\n"); printf(" 2 : channel cases\n"); printf(" 3 : dump enable\n"); printf(" 4 : display enable\n"); printf(" 5 : width\n"); printf(" 6 : heithg\n"); printf(" 7 : fmt\n"); printf(" 8 : frame_num\n"); printf(" 9 : file_id\n"); } static void get_system_time(const char *func, int line_num) { struct timeval cur_time; memset(&cur_time, 0, sizeof(cur_time)); gettimeofday(&cur_time, 0); LOG_O("%s %s line_num = %d, cur_time.tv_sec = %ld, cur_time.tv_usec = %ld\n", __func__, func, line_num, cur_time.tv_sec, cur_time.tv_usec); } int file_id = 0; extern void *vi_plink_create(csi_camera_channel_cfg_s *chn_cfg); extern void vi_plink_release(void * plink); extern void display_camera_frame(void * plink, csi_frame_s *frame); int main(int argc, char *argv[]) { bool running = true; int channel_id = -1; int video_id = -1; int dump_enable = -1; int display_enable = -1; int width = 0, height = 0, fmt = -1; int ret = 0; uint64_t frame_num = 0; csi_camera_info_s camera_info; memset(&camera_info, 0, sizeof(camera_info)); int chn_id = CSI_CAMERA_CHANNEL_0; int env_type = CSI_CAMERA_EVENT_TYPE_CHANNEL0; frame_fps_t demo_fps; memset(&demo_fps, 0, sizeof(demo_fps)); struct timeval init_time, cur_time; memset(&init_time, 0, sizeof(init_time)); memset(&cur_time, 0, sizeof(cur_time)); get_system_time(__func__, __LINE__); char dev_name[128]; // 打印HAL接口版本号 csi_api_version_u version; csi_camera_get_version(&version); if (argc == 5) { video_id = atoi(argv[1]); channel_id = atoi(argv[2]); dump_enable = atoi(argv[3]); display_enable = atoi(argv[4]); width = 640; height = 480; fmt = 1; printf("%s, %s, %s, %s \n", argv[1],argv[2],argv[3],argv[4]); printf("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$, %d, display_enable is %d\n", __LINE__, display_enable ); } else if (argc == 8) { video_id = atoi(argv[1]); channel_id = atoi(argv[2]); dump_enable = atoi(argv[3]); display_enable = atoi(argv[4]); width = atoi(argv[5]); height = atoi(argv[6]); fmt = atoi(argv[7]); }else if (argc == 9) { video_id = atoi(argv[1]); channel_id = atoi(argv[2]); dump_enable = atoi(argv[3]); display_enable = atoi(argv[4]); width = atoi(argv[5]); height = atoi(argv[6]); fmt = atoi(argv[7]); frame_num = atoi(argv[8]); }else if (argc == 10) { video_id = atoi(argv[1]); channel_id = atoi(argv[2]); dump_enable = atoi(argv[3]); display_enable = atoi(argv[4]); width = atoi(argv[5]); height = atoi(argv[6]); fmt = atoi(argv[7]); frame_num = atoi(argv[8]); file_id = atoi(argv[9]); } else { usage(); video_id = 0; channel_id = 0; dump_enable = 0; display_enable = 0; width = 640; height = 480; fmt = 1; printf("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$, %d, display_enable is %d\n", __LINE__, display_enable ); } sprintf(dev_name, "/dev/video%d", video_id); LOG_O("Camera HAL version: %d.%d video_id = %d channel_id = %d size{%d, %d} fmt = %d\n", version.major, version.minor, video_id, channel_id, width, height, fmt); // 获取设备中,所有的Camera struct csi_camera_infos camera_infos; memset(&camera_infos, 0, sizeof(camera_infos)); csi_camera_query_list(&camera_infos); // 打印所有设备所支持的Camera for (int i = 0; i < camera_infos.count; i++) { camera_info = camera_infos.info[i]; printf("Camera[%d]: camera_name='%s', device_name='%s', bus_info='%s', capabilities=0x%08x\n", i, camera_info.camera_name, camera_info.device_name, camera_info.bus_info, camera_info.capabilities); printf("Camera[%d] caps are:\n", i); /* The caps are: Video capture, metadata capture */ for (int j = 1; j <= 0x08000000; j = j << 1) { switch (camera_info.capabilities & j) { case CSI_CAMERA_CAP_VIDEO_CAPTURE: printf("\t camera_infos.info[%d]:Video capture,\n", i); break; case CSI_CAMERA_CAP_META_CAPTURE: printf("\t camera_infos.info[%d] metadata capture,\n", i); break; default: if (camera_info.capabilities & j) { printf("\t camera_infos.info[%d] unknown capabilities(0x%08x)\n", i, camera_info.capabilities & j); } break; } } } /* Camera[0]: camera_name='RGB_Camera', device_name='/dev/video0', bus_info='CSI-MIPI', capabilities=0x00800001 * Camera[1]: camera_name:'Mono_Camera', device_name:'/dev/video8', bus_info='USB', capabilities=0x00000001 */ bool found_camera = false; for (int i = 0; i < camera_infos.count; i++) { if (strcmp(camera_infos.info[i].device_name, dev_name) == 0) { camera_info = camera_infos.info[i]; printf("found device_name:'%s'\n", camera_info.device_name); found_camera = true; break; } } if (!found_camera) { LOG_E("Can't find camera_name:'%s'\n", dev_name); exit(-1); } get_system_time(__func__, __LINE__); // 打开Camera设备获取句柄,作为后续操对象 csi_cam_handle_t cam_handle; csi_camera_open(&cam_handle, camera_info.device_name); get_system_time(__func__, __LINE__); // 获取Camera支持的工作模式 struct csi_camera_modes camera_modes; csi_camera_get_modes(cam_handle, &camera_modes); // 打印camera所支持的所有工作模式 printf("Camera:'%s' modes are:\n", dev_name); printf("{\n"); for (int i = 0; i < camera_modes.count; i++) { printf("\t mode_id=%d: description:'%s'\n", camera_modes.modes[i].mode_id, camera_modes.modes[i].description); } printf("}\n"); // 设置camera的工作模式及其配置 csi_camera_mode_cfg_s camera_cfg; camera_cfg.mode_id = 1; camera_cfg.calibriation = NULL; // 采用系统默认配置 camera_cfg.lib3a = NULL; // 采用系统默认配置 csi_camera_set_mode(cam_handle, &camera_cfg); // 获取单个可控单元的属性 csi_camera_property_description_s description; /* id=0x0098090x, type=2 default=0 value=1 */ /* Other example: * id=0x0098090y, type=3 min=0 max=255 step=1 default=127 value=116 * id=0x0098090z, type=4 min=0 max=3 default=0 value=2 * 0: IDLE * 1: BUSY * 2: REACHED * 3: FAILED */ // 轮询获取所有可控制的单元 printf("all properties are:\n"); description.id = CSI_CAMERA_PID_HFLIP; while (!csi_camera_query_property(cam_handle, &description)) { switch (description.type) { case (CSI_CAMERA_PROPERTY_TYPE_INTEGER): printf("id=0x%08x type=%d default=%d value=%d\n", description.id, description.type, description.default_value.int_value, description.value.int_value); break; case (CSI_CAMERA_PROPERTY_TYPE_BOOLEAN): printf("id=0x%08x type=%d default=%d value=%d\n", description.id, description.type, description.default_value.bool_value, description.value.bool_value); break; case (CSI_CAMERA_PROPERTY_TYPE_ENUM): printf("id=0x%08x type=%d default=%d value=%d\n", description.id, description.type, description.default_value.enum_value, description.value.enum_value); break; case (CSI_CAMERA_PROPERTY_TYPE_STRING): printf("id=0x%08x type=%d default=%s value=%s\n", description.id, description.type, description.default_value.str_value, description.value.str_value); break; case (CSI_CAMERA_PROPERTY_TYPE_BITMASK): printf("id=0x%08x type=%d default=%x value=%x\n", description.id, description.type, description.default_value.bitmask_value, description.value.bitmask_value); break; default: LOG_E("error type!\n"); break; } description.id |= CSI_CAMERA_FLAG_NEXT_CTRL; } // 同时配置多个参数 csi_camera_properties_s properties; csi_camera_property_s property[3]; property[0].id = CSI_CAMERA_PID_HFLIP; property[0].type = CSI_CAMERA_PROPERTY_TYPE_BOOLEAN; property[0].value.bool_value = false; property[1].id = CSI_CAMERA_PID_VFLIP; property[1].type = CSI_CAMERA_PROPERTY_TYPE_BOOLEAN; property[1].value.bool_value = false; property[2].id = CSI_CAMERA_PID_ROTATE; property[2].type = CSI_CAMERA_PROPERTY_TYPE_INTEGER; property[2].value.int_value = 0; properties.count = 3; properties.property = property; if (csi_camera_set_property(cam_handle, &properties) < 0) { LOG_O("set_property fail!\n"); } LOG_O("set_property ok!\n"); // extern int csi_camera_set_pp_path_param(csi_cam_handle_t cam_handle, uint16_t line_num,uint16_t buf_mode); // csi_camera_set_pp_path_param(cam_handle,80,0); // 查询输出channel switch (channel_id) { case 0: chn_id = CSI_CAMERA_CHANNEL_0; env_type = CSI_CAMERA_EVENT_TYPE_CHANNEL0; break; case 1: chn_id = CSI_CAMERA_CHANNEL_1; env_type = CSI_CAMERA_EVENT_TYPE_CHANNEL1; break; case 2: chn_id = CSI_CAMERA_CHANNEL_2; env_type = CSI_CAMERA_EVENT_TYPE_CHANNEL2; break; case 3: chn_id = CSI_CAMERA_CHANNEL_3; env_type = CSI_CAMERA_EVENT_TYPE_CHANNEL3; break; case 4: chn_id = CSI_CAMERA_CHANNEL_4; env_type = CSI_CAMERA_EVENT_TYPE_CHANNEL4; break; case 5: chn_id = CSI_CAMERA_CHANNEL_5; env_type = CSI_CAMERA_EVENT_TYPE_CHANNEL5; break; case 6: chn_id = CSI_CAMERA_CHANNEL_6; env_type = CSI_CAMERA_EVENT_TYPE_CHANNEL6; break; case 7: chn_id = CSI_CAMERA_CHANNEL_7; env_type = CSI_CAMERA_EVENT_TYPE_CHANNEL7; break; default: LOG_E("fail to check chn_id = %d unsupport\n", chn_id); exit(-1); } csi_camera_channel_cfg_s chn_cfg; chn_cfg.chn_id = chn_id; csi_camera_channel_query(cam_handle, &chn_cfg); if (chn_cfg.status != CSI_CAMERA_CHANNEL_CLOSED) { LOG_E("Can't open chn_id = %d\n", chn_id); exit(-1); } extern int csi_camera_set_pp_path_param(csi_cam_handle_t cam_handle, uint16_t line_num,uint16_t buf_mode); /*set PP line num to default and enable sram*/ csi_camera_set_pp_path_param(cam_handle,0,1); // 打开输出channel chn_cfg.chn_id = chn_id; chn_cfg.frm_cnt = 1; chn_cfg.img_fmt.width = width; chn_cfg.img_fmt.height = height; chn_cfg.img_fmt.pix_fmt = fmt; chn_cfg.img_type = CSI_IMG_TYPE_DMA_BUF; chn_cfg.meta_fields = CSI_CAMERA_META_DEFAULT_FIELDS; chn_cfg.capture_type = CSI_CAMERA_CHANNEL_CAPTURE_VIDEO | CSI_CAMERA_CHANNEL_CAPTURE_META; ret = csi_camera_channel_open(cam_handle, &chn_cfg); if (ret) { exit(-1); } get_system_time(__func__, __LINE__); /*init for vi->vo plink*/ void * display_plink = NULL; if (display_enable == 1) { chn_cfg.chn_id = chn_id; display_plink = vi_plink_create(&chn_cfg); if(display_plink==NULL) { LOG_E("plink create fail\n"); exit(-1); } } // 订阅Event csi_cam_event_handle_t event_handle; csi_camera_create_event(&event_handle, cam_handle); csi_camera_event_subscription_s subscribe; subscribe.type = CSI_CAMERA_EVENT_TYPE_CAMERA; // 订阅Camera的ERROR事件 subscribe.id = CSI_CAMERA_EVENT_WARNING | CSI_CAMERA_EVENT_ERROR; csi_camera_subscribe_event(event_handle, &subscribe); subscribe.type = env_type; // 订阅Channel0的FRAME_READY事件 subscribe.id = CSI_CAMERA_CHANNEL_EVENT_FRAME_READY | CSI_CAMERA_CHANNEL_EVENT_OVERFLOW; csi_camera_subscribe_event(event_handle, &subscribe); /* for dsp algo setting cb_context[0].id=0; cb_context[0].cam_handle = cam_handle; cb_context[0].dsp_id = 1; cb_context[0].dsp_path = 2; char test_set[16]="init"; cb_context[0].buf_size = 1920*1080; cb_context[0].ref_buf=NULL; csi_camera_dsp_algo_param_t algo_param_1={ .algo_name = "dsp1_dummy_algo_flo", .algo_cb.cb = dsp_algo_result_cb, .algo_cb.context = &cb_context[0], .algo_cb.arg_size = sizeof(cb_args_t), .sett_ptr = test_set, .sett_size =16, .extra_buf_num =1, .extra_buf_sizes = &cb_context[0].buf_size, .extra_bufs = &cb_context[0].ref_buf, }; if(csi_camera_set_dsp_algo_param(cam_handle,cb_context[0].dsp_id,cb_context[0].dsp_path, &algo_param_1)) { LOG_E("set DSP algo fail\n"); } */ // 开始从channel中取出准备好的frame csi_camera_channel_start(cam_handle, chn_id); get_system_time(__func__, __LINE__); // 处理订阅的Event csi_frame_s frame; struct csi_camera_event event; while (running) { if (frame_num != 0) { if (demo_fps.frameNumber > frame_num) { running = false; } } int timeout = -1; // unit: ms, -1 means wait forever, or until error occurs csi_camera_get_event(event_handle, &event, timeout); // printf("%s event.type = %d, event.id = %d\n", __func__, event.type, event.id); switch (event.type) { case CSI_CAMERA_EVENT_TYPE_CAMERA: switch (event.id) { case CSI_CAMERA_EVENT_ERROR: // do sth. LOG_O("get CAMERA EVENT CSI_CAMERA_EVENT_ERROR!\n"); break; case CSI_CAMERA_EVENT_WARNING: LOG_O("get CAMERA EVENT CSI_CAMERA_EVENT_WRN,RC: %s\n",event.bin); break; default: break; } break; case CSI_CAMERA_EVENT_TYPE_CHANNEL0: case CSI_CAMERA_EVENT_TYPE_CHANNEL1: case CSI_CAMERA_EVENT_TYPE_CHANNEL2: case CSI_CAMERA_EVENT_TYPE_CHANNEL3: case CSI_CAMERA_EVENT_TYPE_CHANNEL4: case CSI_CAMERA_EVENT_TYPE_CHANNEL5: case CSI_CAMERA_EVENT_TYPE_CHANNEL6: case CSI_CAMERA_EVENT_TYPE_CHANNEL7: switch (event.id) { case CSI_CAMERA_CHANNEL_EVENT_FRAME_READY: { get_system_time(__func__, __LINE__); int read_frame_count = csi_camera_get_frame_count(cam_handle, chn_id); unsigned long diff; if (init_time.tv_usec == 0) gettimeofday(&init_time,0);//osGetTick(); gettimeofday(&cur_time, 0); diff = 1000000 * (cur_time.tv_sec-init_time.tv_sec)+ cur_time.tv_usec-init_time.tv_usec; demo_fps.frameNumber++; if (diff != 0) demo_fps.fps = (float)demo_fps.frameNumber / diff * 1000000.0f; LOG_O("%s %d read_frame_count = %d, frame_count = %ld, fps = %.2f diff = %ld\n", __func__, __LINE__, read_frame_count, demo_fps.frameNumber, demo_fps.fps, diff); for (int i = 0; i < read_frame_count; i++) { csi_camera_get_frame(cam_handle, chn_id, &frame, timeout); #ifdef PLATFORM_SIMULATOR if (frame.img.type == CSI_IMG_TYPE_DMA_BUF) { void *phyaddr = vi_mem_import(frame.img.dmabuf[0].fds); void *p = vi_mem_map(phyaddr) + frame.img.dmabuf[0].offset; show_frame_image(p, frame.img.height, frame.img.width); vi_mem_release(phyaddr); } else { show_frame_image(frame.img.usr_addr[0], frame.img.height, frame.img.width); } #endif // printf("main 443 phyaddr=%p\n", vi_mem_import(frame.img.dmabuf[0].fds)); dump_camera_meta(&frame); chn_cfg.chn_id = chn_id; csi_camera_channel_query(cam_handle, &chn_cfg); frame.img.pix_format = chn_cfg.img_fmt.pix_fmt; if (dump_enable) { dump_camera_frame(&frame, chn_cfg.img_fmt.pix_fmt); } if (display_enable == 1) { display_camera_frame(display_plink, &frame); } // csi_camera_frame_unlock(cam_handle, &frame); csi_camera_put_frame(&frame); csi_frame_release(&frame); } break; } default: break; } break; default: break; } } csi_camera_channel_stop(cam_handle, chn_id); usleep (1000000); // 取消订阅某一个event, 也可以直接调用csi_camera_destory_event,结束所有的订阅 subscribe.type = env_type; subscribe.id = CSI_CAMERA_CHANNEL_EVENT_FRAME_READY; csi_camera_unsubscribe_event(event_handle, &subscribe); csi_camera_destory_event(event_handle); csi_camera_channel_close(cam_handle, chn_id); csi_camera_close(cam_handle); if(display_plink) { vi_plink_release(display_plink); } } static void dump_camera_meta(csi_frame_s *frame) { int i; if (frame->meta.type != CSI_META_TYPE_CAMERA) return; csi_camera_meta_s *meta_data = (csi_camera_meta_s *)frame->meta.data; int meta_count = meta_data->count; csi_camrea_meta_unit_s meta_unit; csi_camera_frame_get_meta_unit( &meta_unit, meta_data, CSI_CAMERA_META_ID_FRAME_ID); LOG_O("meta_id=%d, meta_type=%d, meta_value=%d\n", meta_unit.id, meta_unit.type, meta_unit.int_value); } static void dump_camera_frame(csi_frame_s *frame, csi_pixel_fmt_e fmt) { char file[128]; static int file_indx=0; int size; uint32_t indexd, j; void *buf[3]; int buf_size; csi_camera_meta_s *meta_data = (csi_camera_meta_s *)frame->meta.data; csi_camrea_meta_unit_s meta_unit; csi_camera_frame_get_meta_unit( &meta_unit, meta_data, CSI_CAMERA_META_ID_CAMERA_NAME); sprintf(file,"demo_save_img%s_%d_%d",meta_unit.str_value,file_id, file_indx++%10); int fd = open(file, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IROTH); if(fd == -1) { LOG_E("%s, %d, open file error!!!!!!!!!!!!!!!\n", __func__, __LINE__); return ; } if (frame->img.type == CSI_IMG_TYPE_DMA_BUF) { buf_size = frame->img.strides[0]*frame->img.height; switch(fmt) { case CSI_PIX_FMT_NV12: case CSI_PIX_FMT_YUV_SEMIPLANAR_420: if(frame->img.num_planes ==2) { buf_size+=frame->img.strides[1]*frame->img.height/2; } else{ LOG_E("img fomrat is not match with frame planes:%d\n",frame->img.num_planes); return; } break; case CSI_PIX_FMT_YUV_SEMIPLANAR_422: if(frame->img.num_planes ==2) { buf_size+=frame->img.strides[1]*frame->img.height; } else{ LOG_E("img fomrat is not match with frame planes:%d\n",frame->img.num_planes); return; } break; default: break; } buf[0]= mmap(0, buf_size, PROT_READ | PROT_WRITE, MAP_SHARED, frame->img.dmabuf[0].fds, frame->img.dmabuf[0].offset); // plane_size[1] = frame->img.strides[1]*frame->img.height; // printf("frame plane 1 stride:%d,offset:%d\n", frame->img.strides[1],(uint32_t)frame->img.dmabuf[1].offset); if(frame->img.num_planes ==2) { // buf[1] = mmap(0, plane_size[1]/2, PROT_READ | PROT_WRITE, // MAP_SHARED, frame->img.dmabuf[1].fds, frame->img.dmabuf[1].offset); buf[1] = buf[0]+frame->img.dmabuf[1].offset; } } else{ buf[0] = frame->img.usr_addr[0]; buf[1] = frame->img.usr_addr[1]; } LOG_O("%s,save img from : (%lx,%lx)size:%d to %s, fmt:%d width:%d stride:%d height:%d\n",__FUNCTION__, (uint64_t)buf[0],(uint64_t)buf[1],size, file, fmt, frame->img.width, frame->img.strides[0], frame->img.height); if (frame->img.strides[0] == 0) { frame->img.strides[0] = frame->img.width; } switch(fmt) { case CSI_PIX_FMT_NV12: case CSI_PIX_FMT_YUV_SEMIPLANAR_420: for (j = 0; j < frame->img.height; j++) { //Y indexd = j*frame->img.strides[0]; write(fd, buf[0] + indexd, frame->img.width); } for (j = 0; j < frame->img.height / 2; j++) { //UV indexd = j*frame->img.strides[0]; write(fd, buf[1] + indexd, frame->img.width); } break; case CSI_PIX_FMT_RGB_INTEVLEAVED_888: case CSI_PIX_FMT_YUV_TEVLEAVED_444: size = frame->img.width*3; for (j = 0; j < frame->img.height; j++) { indexd = j*frame->img.strides[0]; write(fd, buf[0] + indexd, size); } break; case CSI_PIX_FMT_BGR: case CSI_PIX_FMT_RGB_PLANAR_888: case CSI_PIX_FMT_YUV_PLANAR_444: size = frame->img.width * frame->img.height * 3; write(fd, buf[0], size); break; case CSI_PIX_FMT_RAW_8BIT: size = frame->img.width; for (j = 0; j < frame->img.height; j++) { indexd = j*frame->img.strides[0]; write(fd, buf[0] + indexd, size); } break; case CSI_PIX_FMT_YUV_TEVLEAVED_422: case CSI_PIX_FMT_RAW_10BIT: case CSI_PIX_FMT_RAW_12BIT: case CSI_PIX_FMT_RAW_14BIT: case CSI_PIX_FMT_RAW_16BIT: size = frame->img.width*2; for (j = 0; j < frame->img.height; j++) { indexd = j*frame->img.strides[0]; write(fd, buf[0] + indexd, size); } break; case CSI_PIX_FMT_YUV_SEMIPLANAR_422: if (frame->img.strides[0] == 0) { frame->img.strides[0] = frame->img.width; } for (j = 0; j < frame->img.height; j++) { //Y indexd = j*frame->img.strides[0]; write(fd,buf[0] + indexd, frame->img.width); } for (j = 0; j < frame->img.height; j++) { //UV indexd = j*frame->img.strides[0]; write(fd, buf[1]+ indexd, frame->img.width); } break; default: LOG_E("%s unsupported format to save\n", __func__); exit(-1); break; } close(fd); munmap(buf[0],buf_size); // munmap(buf[1],plane_size[1]); LOG_O("%s exit\n", __func__); }