From c9c8f34f4e643d0c397d3ab5542f44d924d948e6 Mon Sep 17 00:00:00 2001 From: thead_admin Date: Tue, 22 Nov 2022 15:44:55 +0800 Subject: [PATCH] Linux_SDK_V1.0.2 --- common_target.mk | 11 + examples/camera/Makefile | 12 +- examples/camera/cam_demo_dual_ir.c | 1561 +++++++++++++++++ examples/camera/cam_demo_ir.c | 56 +- examples/camera/cam_demo_simple.c | 37 +- examples/camera/camera_demo2.c | 5 - .../camera_demo3_srcs/dialog_camera_open.c | 2 +- examples/camera/camera_frame_display.c | 155 +- examples/camera/list.h | 353 ++++ include/lib_camera/camera_manager.h | 2 +- src/lib_camera/camera_manager.c | 23 +- 11 files changed, 2122 insertions(+), 95 deletions(-) create mode 100644 examples/camera/cam_demo_dual_ir.c create mode 100755 examples/camera/list.h diff --git a/common_target.mk b/common_target.mk index cdcbee7..906167e 100644 --- a/common_target.mk +++ b/common_target.mk @@ -105,3 +105,14 @@ $(OBJS_8): %.o:%.c @echo ">>> Compiling" $< "..." $(CC) $(CFLAGS) $(INCLUDE) -c -o .obj/$(notdir $@) $< +OBJS_9 = $(SRCS_9:.c=.o) +$(TARGET_9): $(OBJS_9) $(PREPARE) + @mkdir -p $(OUTPUT_DIR) + @echo ">>> Linking" $@ "..." + $(CC) $(LFLAGS) -o $@ $(addprefix .obj/,$(notdir $(OBJS_9))) -Wl,--start-group $(LIBS) $(LIBS_8) -Wl,--end-group + cp $@ $(OUTPUT_DIR) + +$(OBJS_9): %.o:%.c + @mkdir -p .obj + @echo ">>> Compiling" $< "..." + $(CC) $(CFLAGS) $(INCLUDE) -c -o .obj/$(notdir $@) $< \ No newline at end of file diff --git a/examples/camera/Makefile b/examples/camera/Makefile index aa94d16..e94e53c 100644 --- a/examples/camera/Makefile +++ b/examples/camera/Makefile @@ -17,8 +17,9 @@ PREPARE := lib_camera ifeq ($(PLATFORM),light) CFLAGS += -I$(VISYS_SYM_PATH)/usr/include/plink/ CFLAGS += -I$(VISYS_SYM_PATH)/usr/include/vidmem/ + CFLAGS += -I$(VISYS_SYM_PATH)/usr/include/dsp/lib/inc/ LIBS += -lstdc++ -lpthread - LIBS += -lvmem -lplink + LIBS += -lvmem -lplink -ldsp endif @@ -53,10 +54,13 @@ SRCS_7 = cam_demo_ir.c camera_frame_display.c TARGET_8 := cam_demo_multi SRCS_8 = cam_demo_multi.c camera_frame_display.c +TARGET_9 := cam_demo_dual_ir +SRCS_9 = cam_demo_dual_ir.c + ifeq ($(PLATFORM),simulator) TARGET_ALL := $(TARGET_1) $(TARGET_2) $(TARGET_3) $(TARGET_4) else -TARGET_ALL := $(TARGET_1) $(TARGET_2) $(TARGET_3) $(TARGET_5) $(TARGET_6) $(TARGET_7) $(TARGET_8) +TARGET_ALL := $(TARGET_1) $(TARGET_2) $(TARGET_3) $(TARGET_5) $(TARGET_6) $(TARGET_7) $(TARGET_8) $(TARGET_9) endif all: $(TARGET_ALL) @@ -78,6 +82,10 @@ clean: rm -f $(TARGET_3) $(OUTPUT_DIR)/camera_demo3.conf rm -f $(TARGET_4) $(OUTPUT_DIR)/$(TARGET_4) rm -f $(TARGET_5) $(OUTPUT_DIR)/$(TARGET_5) + rm -f $(TARGET_6) $(OUTPUT_DIR)/$(TARGET_6) + rm -f $(TARGET_7) $(OUTPUT_DIR)/$(TARGET_7) + rm -f $(TARGET_8) $(OUTPUT_DIR)/$(TARGET_8) + rm -f $(TARGET_9) $(OUTPUT_DIR)/$(TARGET_9) make -C ./opencv clean include $(DIR_TO_ROOT)/common_target.mk diff --git a/examples/camera/cam_demo_dual_ir.c b/examples/camera/cam_demo_dual_ir.c new file mode 100644 index 0000000..b3a6d57 --- /dev/null +++ b/examples/camera/cam_demo_dual_ir.c @@ -0,0 +1,1561 @@ +/* + * Copyright (C) 2021 Alibaba Group Holding Limited + * Author: ShenWuYi + * + * 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 +#define LOG_LEVEL 5 +#define LOG_PREFIX "cam_demo_dual_ir" +#include + +#include +#include +#include +#include "list.h" +#include "video_mem.h" +#include "csi_dsp_api.h" +#include "csi_dsp_task_defs.h" +#include "csi_dsp_post_process_defs.h" +#ifdef PLATFORM_SIMULATOR +#include "apputilities.h" +#endif +#define MAX_CAM_NUM 3 +#define MAX_CHANNEL_NUM 3 + +#define TEST_DEVICE_NAME "/dev/video0" +#define CSI_CAMERA_TRUE 1 +#define CSI_CAMERA_FALSE 0 + +/*************************************common data struct************************************************************************/ +typedef struct msg_queue_item{ + void* payload; + struct msg_queue_item *next; +}msg_queue_item_t; +typedef struct msg_queue{ + msg_queue_item_t *head; + msg_queue_item_t *tail; + int exit; + pthread_mutex_t mutex; + pthread_cond_t cond; +}msg_queue_ctx_t; + + +typedef struct cam_dsp_info{ + int master_fd; + int slave_fd; + /**add AE ctrl info********/ +}cam_dsp_info_t; + + +/*************************************camera data struct*************************************************************/ +typedef enum{ + CAM_SYNC_MSG_MAIN_FRAME, + CAM_SYNC_MSG_SLAVE_FRAME, + CAM_SYNC_MSG_AI_INFO, + CAM_SYNC_MSG_DSP_INFO, +}cam_sync_message_type_e; + +typedef struct{ + +}cam_ai_info_t; + + +typedef struct camera_sync_msg{ + cam_sync_message_type_e type; + union{ + csi_frame_s frame; + cam_ai_info_t ai_info; + cam_dsp_info_t dsp_info; + }; +}camera_sync_msg_t; + + +typedef enum _cam_type{ + CAM_TYEP_MASTER =0, + CAM_TYEP_SLAVE, + CAM_TYEP_INVALID, +}cam_type_e; + +typedef enum _frame_mode{ + FRAME_NONE =0, + FRAME_SAVE_IMG =1, + FRAME_SAVE_STREAM =2, + FRAME_SAVE_DISPLAY, + FRAME_INVALID, +}frame_mode_t; +typedef struct _camera_param{ + int video_id; + int channel_num; + struct { + int width; + int height; + csi_pixel_fmt_e fmt; + + }out_pic[MAX_CHANNEL_NUM]; + + cam_type_e type; + int frames_to_stop; +}camera_param_t; + +typedef struct event_queue_item{ + struct csi_camera_event evet; + struct event_queue_item *next; +}event_queue_item_t; + +typedef struct _camera_ctx{ + + int cam_id; + // pthread_t cam_thread; + int exit; + msg_queue_ctx_t *cam_sync_queue; + csi_cam_handle_t cam_handle; + int channel_num; + csi_cam_event_handle_t event_handle; + csi_camera_event_subscription_s event_subscribe; + csi_camera_channel_cfg_s chn_cfg[MAX_CHANNEL_NUM]; + int frame_num; + struct timeval init_time; + float fps; + // frame_mode_t frame_mode[MAX_CHANNEL_NUM]; +}camera_ctx_t; + +/********************************dsp data struct*********************************************************/ +#define MAX_DSP_DEVICE 2 + + +typedef struct algo_pic_out_setting{ + enum{ + ALGO_PIC_MODE_FULL_COPY, + ALGO_PIC_MODE_FULL_COPY_WITH_PARAM, + ALGO_PIC_MODE_FULL_COPY_NONE, + }mode; + int buf_id; + int h_offset; + int height; + uint32_t frame_id; + uint64_t timestap; + uint32_t temp_projector; //投射器温度 +}algo_pic_out_setting_t; + +typedef struct algo_result{ + char lib_name[16]; + uint64_t timestap; +}algo_result_t; + +typedef struct dsp_dual_ir_frame_msg{ + size_t size; + uint32_t width; + uint32_t height; + uint32_t master_stride; + uint32_t slave_stride; + csi_pixel_fmt_e pix_format; + int master_fd; + int slave_fd; + uint32_t frame_id; + uint64_t timestap; + uint32_t temp_projector; //投射器温度 + +}dsp_dual_ir_frame_msg_t; + +typedef struct dsp_ctx{ + int dsp_id; + void * instance; + void* dsp_task; + char* algo_name; +}dsp_ctx_t; + +typedef struct dual_dsp_handle{ + dsp_ctx_t dsp_ctx[MAX_DSP_DEVICE]; + msg_queue_ctx_t dsp_prcoess_queue; + msg_queue_ctx_t *cam_sync_queue; + void *mem_allocor; + pthread_t thread_dsp_process; + frame_mode_t frame_mode; +}dual_dsp_handle_t; + + +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); + +static void *cam_frame_sync_process(void *ctx); +static void* dsp_dual_ir_porcess(void *arg); +/*******************************common func***********************************************************************/ +static void usage(void) +{ + printf(" 1 : IR 1 Camera id \n"); + printf(" 2 : IR 2 Camera id \n"); + printf(" 3 : runing Camera frame num :0 not stop ,else frame num to stop \n"); + printf(" 4 : DSP frame mode :0 none ,1 dump enable,2 display \n"); + +} + +void printUsage(char *name) +{ + printf("usage: %s [options]\n" + "\n" + " Available options:\n" + " -m master camera id \n" + " -s slave camera device id)\n" + " -w width (default: 800))\n" + " -h height (default: 1280))\n" + " -n runing Camera frame num :0 not stop ,else frame num to stop )\n" + " -M DSP frame mode :0 none ,1 dump enable,2 display)\n" + + "\n", name); +} + +static int parseParams(int argc, char **argv, camera_param_t *params,frame_mode_t *mode) +{ + int index =0; + int i = 1; + params[index].video_id = 0; + params[index].type = CAM_TYEP_MASTER; + + params[index].channel_num =1; + params[index].out_pic[0].width = 1920; + params[index].out_pic[0].height = 1088; + params[index].out_pic[0].fmt = CSI_PIX_FMT_RAW_10BIT; + + params[index].frames_to_stop = 30; + index++; + + params[index].video_id = 15; + params[index].type = CAM_TYEP_SLAVE; + + params[index].channel_num = 1; + params[index].out_pic[0].width = 1920; + params[index].out_pic[0].height = 1088; + params[index].out_pic[0].fmt =CSI_PIX_FMT_RAW_10BIT; + + params[index].frames_to_stop = 30; + index++; + *mode = FRAME_NONE; + while (i < argc) + { + if (argv[i][0] != '-' || strlen(argv[i]) < 2) + { + i++; + continue; + } + + if (argv[i][1] == 'm') + { + if (++i < argc) + params[0].video_id = atoi(argv[i++]); + } + else if (argv[i][1] == 's') + { + if (++i < argc) + params[1].video_id = atoi(argv[i++]); + } + else if (argv[i][1] == 'w') + { + if (++i < argc) + params[0].out_pic[0].width = atoi(argv[i++]); + params[1].out_pic[0].width = params[0].out_pic[0].width; + } + else if (argv[i][1] == 'h') + { + if (++i < argc) + params[0].out_pic[0].height = atoi(argv[i++]); + params[1].out_pic[0].height = params[0].out_pic[0].height; + } + else if (argv[i][1] == 'n') + { + if (++i < argc) + params[0].frames_to_stop = atoi(argv[i++]); + params[1].frames_to_stop = params[0].frames_to_stop; + } + else if (argv[i][1] == 'M') + { + if (++i < argc) + *mode = atoi(argv[i++]); + } + else if (strcmp(argv[i], "--help") == 0) + { + printUsage(argv[0]); + return -1; + } + } + printf("[DUAL IR] master camera : %d\n", params[0].video_id); + printf("[DUAL IR] master camera : %d\n",params[1].video_id); + printf("[DUAL IR] Resolution : %dx%d\n", params[0].out_pic[0].width,params[0].out_pic[0].height); + printf("[DUAL IR] run frame : %d\n", params[0].frames_to_stop); + printf("[DUAL IR] frame mode : %d\n", *mode); + + + return index; +} + +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_D("%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); +} + +static msg_queue_item_t *dequeue_msg(msg_queue_ctx_t *ctx) +{ + msg_queue_item_t *ev = ctx->head; + pthread_mutex_lock(&ctx->mutex); + if(!ev) + { + pthread_mutex_unlock(&ctx->mutex); + return NULL; + } + + if(ev == ctx->tail) + ctx->tail = NULL; + ctx->head = ev->next; + pthread_mutex_unlock(&ctx->mutex); + return ev; +} + +static int enqueue_msg(msg_queue_ctx_t *ctx,msg_queue_item_t * item) +{ + + if(!item || !ctx) + return -1; + item->next = NULL; + LOG_D("%s enter \n", __func__); + pthread_mutex_lock(&ctx->mutex); + if (ctx->tail) { + ctx->tail->next = item; + } else { + ctx->head = item; + // pthread_cond_broadcast(&ctx->cond); + } + ctx->tail = item; + pthread_mutex_unlock(&ctx->mutex); + return 0; +} + +/***********************DSP Dual-IR process *******************************/ +static void dsp_dump_frame(void *frame_buf, csi_pixel_fmt_e fmt, int width,int height,int stride) +{ + char file[128]; + static int file_indx=0; + int size; + uint32_t indexd, j; + + sprintf(file,"demo_save_img_%d",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; + } + + + LOG_O("save img from to %s, fmt:%d width:%d stride:%d height:%d \n",file, fmt, width, stride,height); + + switch(fmt) { + default: + size = width*2; + for (j = 0; j < height; j++) { + indexd = j*stride; + write(fd, frame_buf + indexd, size); + } + + } + close(fd); +} + + +static void* req_DmaBuffer(void*mem_allocor,VmemParams *params) +{ + + int pgsize = getpagesize(); + params->size = ((params->size+pgsize-1)/pgsize)*pgsize; + if(VMEM_allocate(mem_allocor, params)) + { + return NULL; + } + + LOG_O("alloct dma buf @ phy:0x%x\n",params->phy_address); + if(VMEM_export(mem_allocor,params)) + { + return NULL; + } + LOG_D("export dma buf @fd:%x\n",params->fd); + if(VMEM_mmap(mem_allocor,params)) + { + return NULL; + } + memset(params->vir_address,0xff,params->size); + return params->vir_address; + +} + + static int release_DmaBuffer(void*mem_allocor,VmemParams *params) + { + VMEM_free(mem_allocor, params); + } + +static int dsp_construct_task(dsp_ctx_t *ctx) +{ + if(ctx== NULL || ctx->dsp_id >= MAX_DSP_DEVICE || ctx->dsp_id <0 || ctx->algo_name == NULL) + { + LOG_E("prama check fail\n"); + goto one_err; + } + + ctx->instance = csi_dsp_create_instance(ctx->dsp_id); + if (ctx->instance==NULL) { + LOG_E("dsp create fail\n"); + goto one_err; + } + + ctx->dsp_task = csi_dsp_create_task(ctx->instance, CSI_DSP_TASK_SW_TO_SW); + if (ctx->dsp_task==NULL) { + LOG_E("dsp task create fail.\n"); + goto two_err; + } + + if(csi_dsp_task_acquire_algo(ctx->dsp_task,ctx->algo_name)) + { + LOG_E("dsp task create fail.\n"); + goto three_err; + } + return 0; +three_err: + csi_dsp_destroy_task(ctx->dsp_task); +two_err: + csi_dsp_delete_instance(ctx->instance); +one_err: + return -1; + +} + + +static int dsp_release_task(dsp_ctx_t *ctx) +{ + if(ctx==NULL || ctx->instance || ctx->dsp_task) + { + return -1; + } + csi_dsp_destroy_task(ctx->instance); + csi_dsp_delete_instance(ctx->instance); + + +} + +static int dsp_send_info_to_cam(msg_queue_ctx_t* cam_msg_queue,int master_fd,int slave_fd) +{ + camera_sync_msg_t * msg_payload; + msg_queue_item_t * msg; + if(cam_msg_queue==NULL|| master_fd<=0|| slave_fd<=0) + { + LOG_E("param check fail\n"); + return -1; + } + msg_payload = malloc(sizeof(camera_sync_msg_t)); + if(msg_payload == NULL) + { + LOG_E("malloc fail\n"); + return -1; + } + msg = malloc(sizeof(msg_queue_item_t)); + if(msg==NULL) + { + LOG_E("malloc fail\n"); + free(msg_payload); + return -1; + } + msg_payload->type = CAM_SYNC_MSG_DSP_INFO; + msg_payload->dsp_info.master_fd = master_fd; + msg_payload->dsp_info.slave_fd = slave_fd; + msg->payload = msg_payload; + + if(enqueue_msg(cam_msg_queue,msg)) + { + free(msg_payload); + free(msg); + return -1; + } + LOG_D("send dsp resp to cam sync for fd(%d,%d)\n",master_fd,slave_fd); + return 0; +} + +static dual_dsp_handle_t* dsp_process_create(frame_mode_t mode) +{ + dual_dsp_handle_t *dsp_hdl=NULL; + dsp_hdl = malloc(sizeof(dual_dsp_handle_t)); + if(dsp_hdl==NULL) + { + return NULL; + } + dsp_hdl->dsp_ctx[0].dsp_id = 0; + dsp_hdl->dsp_ctx[1].dsp_id = 1; + dsp_hdl->dsp_ctx[0].algo_name = "dummy_ir_algo_flo_0"; + dsp_hdl->dsp_ctx[1].algo_name = "dummy_ir_algo_flo_1"; + dsp_hdl->dsp_prcoess_queue.head=NULL; + dsp_hdl->dsp_prcoess_queue.tail=NULL; + dsp_hdl->dsp_prcoess_queue.exit = 0; + dsp_hdl->frame_mode = mode; + pthread_mutex_init(&dsp_hdl->dsp_prcoess_queue.mutex,NULL); + + if(dsp_construct_task(&dsp_hdl->dsp_ctx[0])) + { + free(dsp_hdl); + return NULL; + } + if(dsp_construct_task(&dsp_hdl->dsp_ctx[1])) + { + dsp_release_task(&dsp_hdl->dsp_ctx[0]); + free(dsp_hdl); + return NULL; + } + if( VMEM_create(&dsp_hdl->mem_allocor) <0) + { + dsp_release_task(&dsp_hdl->dsp_ctx[0]); + dsp_release_task(&dsp_hdl->dsp_ctx[1]); + free(dsp_hdl); + return NULL; + } + if(pthread_create(&dsp_hdl->thread_dsp_process,NULL,dsp_dual_ir_porcess,dsp_hdl)) + { + dsp_release_task(&dsp_hdl->dsp_ctx[0]); + dsp_release_task(&dsp_hdl->dsp_ctx[1]); + VMEM_destroy(dsp_hdl->mem_allocor); + free(dsp_hdl); + return NULL; + } + LOG_D("dsp process crated\n"); + return dsp_hdl; +} + +void dsp_process_destroy(dual_dsp_handle_t* dsp_hdl) +{ + if(dsp_hdl==NULL) + { + LOG_E("NULL Ptr\n"); + return; + } + + dsp_hdl->dsp_prcoess_queue.exit=1; + pthread_join(dsp_hdl->thread_dsp_process,NULL); + + dsp_release_task(&dsp_hdl->dsp_ctx[0]); + dsp_release_task(&dsp_hdl->dsp_ctx[1]); + VMEM_destroy(dsp_hdl->mem_allocor); + free(dsp_hdl); + return; +} + +static void* dsp_dual_ir_porcess(void *arg) +{ + msg_queue_item_t * msg=NULL; + dsp_dual_ir_frame_msg_t *dual_ir_frame; + VmemParams params_out; + void* out_buf=NULL; + algo_pic_out_setting_t setting; + algo_result_t *dsp0_result; + algo_result_t *dsp1_result; + dual_dsp_handle_t *dsp_hdl =(dual_dsp_handle_t *) arg; + if(dsp_hdl==NULL) + { + pthread_exit(0); + } + // alloc DSP out put buf from video memory ,which is dma buf + params_out.size = 1920*1088*2; + params_out.flags = VMEM_FLAG_CONTIGUOUS; + out_buf = req_DmaBuffer(dsp_hdl->mem_allocor,¶ms_out); + if(out_buf == NULL) + { + LOG_E("req dma Buf fail\n"); + pthread_exit(0); + } + + LOG_O("Runing ...\n"); + while(dsp_hdl->dsp_prcoess_queue.exit!=1) + { + if(msg!=NULL) + { + free(msg); + } + msg = dequeue_msg(&dsp_hdl->dsp_prcoess_queue); + if(msg == NULL) + { + usleep(1000); + continue; + } + LOG_D("get msg\n"); + dual_ir_frame = (dsp_dual_ir_frame_msg_t *)msg->payload; + + struct csi_sw_task_req* req1 = NULL; + struct csi_sw_task_req* req2 = NULL; + req1 = csi_dsp_task_create_request(dsp_hdl->dsp_ctx[0].dsp_task); + if (req1 == NULL) { + LOG_W("req create fail.\n"); + dsp_send_info_to_cam(dsp_hdl->cam_sync_queue, dual_ir_frame->master_fd,dual_ir_frame->slave_fd); + continue; + } + req2 = csi_dsp_task_create_request(dsp_hdl->dsp_ctx[1].dsp_task); + if (req2 == NULL) { + LOG_W("req create fail.\n"); + csi_dsp_task_release_request(req1); + dsp_send_info_to_cam(dsp_hdl->cam_sync_queue, dual_ir_frame->master_fd,dual_ir_frame->slave_fd); + continue; + } + + + struct csi_dsp_buffer buf1; + struct csi_dsp_buffer buf2; + struct csi_dsp_buffer buf3; + struct csi_dsp_buffer buf4; + // import main camera frame + buf1.buf_id = 0; + buf1.dir = CSI_DSP_BUFFER_IN; + buf1.type = CSI_DSP_BUF_TYPE_DMA_BUF_IMPORT; + buf1.plane_count = 1; + buf1.width = dual_ir_frame->width; + buf1.height = dual_ir_frame->height; + buf1.format = 2; + buf1.planes[0].stride = dual_ir_frame->master_stride; + buf1.planes[0].size = dual_ir_frame->size; + buf1.planes[0].fd = dual_ir_frame->master_fd; + // import slave cmaera frame + buf2.buf_id = 1; + buf2.dir = CSI_DSP_BUFFER_IN; + buf2.type = CSI_DSP_BUF_TYPE_DMA_BUF_IMPORT; + buf2.plane_count = 1; + buf2.width = dual_ir_frame->width; + buf2.height = dual_ir_frame->height; + buf2.format=2; + buf2.planes[0].stride = dual_ir_frame->slave_stride; + buf2.planes[0].size = dual_ir_frame->size; + buf2.planes[0].fd = dual_ir_frame->slave_fd; + // import output frame buf + buf3.buf_id = 2; + buf3.dir = CSI_DSP_BUFFER_OUT; + buf3.type = CSI_DSP_BUF_TYPE_DMA_BUF_IMPORT; + buf3.plane_count = 1; + buf3.width = dual_ir_frame->width; + buf3.height = dual_ir_frame->height; + buf3.format=2; + buf3.planes[0].stride = dual_ir_frame->width*2; + buf3.planes[0].size = params_out.size; + buf3.planes[0].fd = params_out.fd; + // malloc algo result buf + buf4.buf_id = 3; + buf4.dir = CSI_DSP_BUFFER_OUT; + buf4.type = CSI_DSP_BUF_ALLOC_DRV; + buf4.plane_count = 1; + buf4.planes[0].size = sizeof(algo_result_t); + /**********************add buf for dsp0 req*****************************************/ + /* buf0:master frame; buf1:output buf; buf2: slave frame,buf3:algo result buf********/ + if(csi_dsp_request_add_buffer(req1,&buf1)) + { + + csi_dsp_task_release_request(req1); + csi_dsp_task_release_request(req2); + dsp_send_info_to_cam(dsp_hdl->cam_sync_queue, dual_ir_frame->master_fd,dual_ir_frame->slave_fd); + LOG_W("req create fail.\n"); + continue; + } + if(csi_dsp_request_add_buffer(req1,&buf3)) + { + + csi_dsp_task_release_request(req1); + csi_dsp_task_release_request(req2); + dsp_send_info_to_cam(dsp_hdl->cam_sync_queue, dual_ir_frame->master_fd,dual_ir_frame->slave_fd); + LOG_W("req create fail.\n"); + continue; + } + + + if(csi_dsp_request_add_buffer(req1,&buf2)) + { + + csi_dsp_task_release_request(req1); + csi_dsp_task_release_request(req2); + dsp_send_info_to_cam(dsp_hdl->cam_sync_queue, dual_ir_frame->master_fd,dual_ir_frame->slave_fd); + LOG_W("req create fail.\n"); + continue; + } + + if(csi_dsp_request_add_buffer(req1,&buf4)) + { + + csi_dsp_task_release_request(req1); + csi_dsp_task_release_request(req2); + dsp_send_info_to_cam(dsp_hdl->cam_sync_queue, dual_ir_frame->master_fd,dual_ir_frame->slave_fd); + LOG_W("req create fail.\n"); + continue; + } + dsp0_result = (algo_result_t *)buf4.planes[0].buf_vir; + /**********************add buf for dsp1 req*****************************************/ + /* buf0:salve frame; buf1:output buf; buf2: master frame,buf3:algo result buf********/ + if(csi_dsp_request_add_buffer(req2,&buf2)) + { + + csi_dsp_task_release_request(req1); + csi_dsp_task_release_request(req2); + dsp_send_info_to_cam(dsp_hdl->cam_sync_queue, dual_ir_frame->master_fd,dual_ir_frame->slave_fd); + LOG_W("req create fail.\n"); + continue; + } + + if(csi_dsp_request_add_buffer(req2,&buf3)) + { + + csi_dsp_task_release_request(req1); + csi_dsp_task_release_request(req2); + dsp_send_info_to_cam(dsp_hdl->cam_sync_queue, dual_ir_frame->master_fd,dual_ir_frame->slave_fd); + LOG_W("req create fail.\n"); + continue; + } + + if(csi_dsp_request_add_buffer(req2,&buf1)) + { + + csi_dsp_task_release_request(req1); + csi_dsp_task_release_request(req2); + dsp_send_info_to_cam(dsp_hdl->cam_sync_queue, dual_ir_frame->master_fd,dual_ir_frame->slave_fd); + LOG_W("req create fail.\n"); + continue; + } + if(csi_dsp_request_add_buffer(req2,&buf4)) + { + + csi_dsp_task_release_request(req1); + csi_dsp_task_release_request(req2); + dsp_send_info_to_cam(dsp_hdl->cam_sync_queue, dual_ir_frame->master_fd,dual_ir_frame->slave_fd); + LOG_W("req create fail.\n"); + continue; + } + dsp1_result = (algo_result_t *)buf4.planes[0].buf_vir; + setting.mode = ALGO_PIC_MODE_FULL_COPY_WITH_PARAM; + setting.buf_id=0; + setting.h_offset = dual_ir_frame->height/2; + setting.height =dual_ir_frame->height/2; + setting.timestap = dual_ir_frame->timestap; + if(csi_dsp_request_set_property(req1,&setting,sizeof(setting))) + { + csi_dsp_task_release_request(req1); + csi_dsp_task_release_request(req2); + dsp_send_info_to_cam(dsp_hdl->cam_sync_queue, dual_ir_frame->master_fd,dual_ir_frame->slave_fd); + LOG_W("req create fail.\n"); + continue; + } + + setting.mode = ALGO_PIC_MODE_FULL_COPY_WITH_PARAM; + setting.buf_id=0; + setting.h_offset = 0; + setting.height =dual_ir_frame->height/2; + setting.timestap = dual_ir_frame->timestap; + if(csi_dsp_request_set_property(req2,&setting,sizeof(setting))) + { + csi_dsp_task_release_request(req1); + csi_dsp_task_release_request(req2); + dsp_send_info_to_cam(dsp_hdl->cam_sync_queue, dual_ir_frame->master_fd,dual_ir_frame->slave_fd); + LOG_W("req create fail.\n"); + continue; + } + + + if(csi_dsp_request_enqueue(req1)) + { + csi_dsp_task_release_request(req1); + csi_dsp_task_release_request(req2); + dsp_send_info_to_cam(dsp_hdl->cam_sync_queue, dual_ir_frame->master_fd,dual_ir_frame->slave_fd); + LOG_W("req create fail.\n"); + continue; + } + + if(csi_dsp_request_enqueue(req2)) + { + req1 = csi_dsp_request_dequeue(dsp_hdl->dsp_ctx[0].dsp_task); + csi_dsp_task_release_request(req1); + csi_dsp_task_release_request(req2); + dsp_send_info_to_cam(dsp_hdl->cam_sync_queue, dual_ir_frame->master_fd,dual_ir_frame->slave_fd); + LOG_W("req create fail.\n"); + continue; + } + req1 = csi_dsp_request_dequeue(dsp_hdl->dsp_ctx[0].dsp_task); + if(req1 == NULL) + { + LOG_W("dequeue fail.\n"); + + } + req2 =csi_dsp_request_dequeue(dsp_hdl->dsp_ctx[1].dsp_task); + if(req2 == NULL) + { + LOG_W("dequeue fail.\n"); + } + LOG_D("dsp0 lib:%s timestap:%lx,dsp1 lib:%s,timestap:%lx\n",dsp0_result->lib_name,dsp0_result->timestap, + dsp1_result->lib_name,dsp1_result->timestap); + + dsp_send_info_to_cam(dsp_hdl->cam_sync_queue, dual_ir_frame->master_fd,dual_ir_frame->slave_fd); + + switch(dsp_hdl->frame_mode) + { + case FRAME_NONE: + break; + case FRAME_SAVE_IMG: + dsp_dump_frame((void *)buf3.planes[0].buf_vir,0,buf3.width,buf3.height,buf3.planes[0].stride); + break; + default: + LOG_W("unsupport frame mode %d\n",dsp_hdl->frame_mode); + } + csi_dsp_task_release_request(req1); + csi_dsp_task_release_request(req2); + + } + release_DmaBuffer(dsp_hdl->mem_allocor,¶ms_out); + LOG_O("exit\n"); + pthread_exit(0); +} + +/************************************Camera sync process***************************/ +#define MAX_FIFO_FACE_INFO_NUM 2 +#define MAX_FIFO_FRAME_NUM 2 + + +typedef struct { + struct list_head head; + void* item; +}frame_item_t; + +typedef struct cam_sync_process_ctx{ + msg_queue_ctx_t cam_sync_queue; + msg_queue_ctx_t *dsp_prcoess_queue; //DSP 消息queue + csi_cam_handle_t master_cam_handle; + csi_cam_handle_t slave_cam_handle; + struct list_head cam_master_frame_list; // 缓存master camera 的frame + struct list_head cam_slave_frame_list; // slave camera 的frame + struct list_head cam_busy_frame_list; //缓存发送给DSP的frame + struct list_head ai_info_list; + pthread_t thread_cam_sync; + uint32_t paried_frame_num; +}cam_sync_process_ctx_t; + +static cam_sync_process_ctx_t *cam_sync_create() +{ + cam_sync_process_ctx_t * ctx; + ctx = malloc(sizeof(cam_sync_process_ctx_t)); + if(ctx == NULL) + { + return NULL; + } + ctx->cam_sync_queue.head=NULL; + ctx->cam_sync_queue.tail = NULL; + ctx->cam_sync_queue.exit =0; + ctx->paried_frame_num = 0; + pthread_mutex_init(&ctx->cam_sync_queue.mutex,NULL); + INIT_LIST_HEAD(&ctx->cam_master_frame_list); + INIT_LIST_HEAD(&ctx->ai_info_list); + INIT_LIST_HEAD(&ctx->cam_busy_frame_list); + INIT_LIST_HEAD(&ctx->cam_slave_frame_list); + + if(pthread_create(&ctx->thread_cam_sync,NULL,cam_frame_sync_process,ctx)) + { + LOG_E("cam sync thread create fail\n"); + free(ctx); + return NULL; + } + return ctx; +} + + +static void cam_sync_destroy(void *arg) +{ + cam_sync_process_ctx_t *ctx= (cam_sync_process_ctx_t *)arg; + if(ctx==NULL) + { + return ; + } + ctx->cam_sync_queue.exit =1; + pthread_join(ctx->thread_cam_sync,NULL); + free(ctx); + LOG_O("cam sync destroy\n"); +} +static int push_new_frame(struct list_head *frame_list, csi_frame_s * new_frame) +{ + int entry_num =0; + frame_item_t *frame_item = NULL; + frame_item_t * new_item = NULL; + if(frame_list == NULL || new_frame==NULL) + { + return -1; + } + + list_for_each_entry(frame_item,frame_list,head){ + entry_num++; + } + if((entry_num+1)>MAX_FIFO_FRAME_NUM) + { + frame_item = list_first_entry(frame_list,frame_item_t,head); + LOG_D("release frame fd:%d\n",((csi_frame_s *)frame_item->item)->img.fds[0]); + csi_camera_put_frame((csi_frame_s *)frame_item->item); + free(frame_item->item); + list_del(&frame_item->head); + free(frame_item); + } + new_item = malloc(sizeof(frame_item_t)); + new_item->item = new_frame; + list_add_tail(&new_item->head,frame_list); + return 0; +} + +static csi_frame_s * pop_matched_frame_with_fd(struct list_head *frame_list,int fd) +{ + csi_frame_s * frame = NULL; + frame_item_t *frame_item = NULL; + frame_item_t * temp; + if(frame_list==NULL) + { + return NULL; + } + list_for_each_entry_safe(frame_item,temp,frame_list,head){ + frame = (csi_frame_s *)frame_item->item; + if(frame->img.fds[0]==fd) + { + list_del(&frame_item->head); + free(frame_item); + LOG_D("get frame fd:%d\n",frame->img.fds[0]); + return frame; + } + } + return NULL; +} + + +static csi_frame_s * pop_matched_frame_with_ts(struct list_head *frame_list, csi_frame_s * target_frame,uint32_t rang_us,bool clear_early) +{ + csi_camera_meta_s *meta_data = (csi_camera_meta_s *)target_frame->meta.data; + csi_camrea_meta_unit_s target_ts,loop_ts; + csi_frame_s * frame; + frame_item_t *frame_item = NULL; + frame_item_t * tmp; + struct timeval time_value; + long long target_us,loop_us,deta_us; + if(target_frame == NULL || frame_list==NULL) + { + return NULL; + } + if(list_empty(frame_list)) + { + return NULL; + } + csi_camera_frame_get_meta_unit( + &target_ts, meta_data, CSI_CAMERA_META_ID_TIMESTAMP); + + target_us = target_ts.time_value.tv_sec*1000000 + target_ts.time_value.tv_usec; + + list_for_each_entry_safe(frame_item,tmp,frame_list,head){ + frame = ( csi_frame_s *)frame_item->item; + meta_data = (csi_camera_meta_s *)frame->meta.data; + csi_camera_frame_get_meta_unit( + &loop_ts, meta_data, CSI_CAMERA_META_ID_TIMESTAMP); + loop_us = loop_ts.time_value.tv_sec*1000000 + loop_ts.time_value.tv_usec; + deta_us = (target_us-loop_us); + if(deta_us <=rang_us || deta_us>=(-rang_us)) + { + list_del(&frame_item->head); + free(frame_item); + return frame; + } + if(clear_early && deta_us < 0) + { + csi_camera_put_frame(frame); + list_del(&frame_item->head); + free(frame_item); + } + frame_item=NULL; + } + return NULL; + +} + +static int send_paired_frame_to_dsp(msg_queue_ctx_t *queue,csi_frame_s *master_frame,csi_frame_s *slave_frame,struct list_head *send_frames) +{ + dsp_dual_ir_frame_msg_t *dsp_msg_payload; + msg_queue_item_t *dsp_msg; + frame_item_t *main_item,*slave_item; + csi_camera_meta_s *meta_data; + csi_camrea_meta_unit_s timestap; + if(queue==NULL || master_frame==NULL || slave_frame==NULL) + { + return -1; + } + + if(master_frame->img.width!=slave_frame->img.width|| + master_frame->img.height!=slave_frame->img.height) + { + LOG_E("paird frame not the same picture param\n"); + return -1; + } + dsp_msg=malloc(sizeof(msg_queue_item_t)); + if(dsp_msg==NULL){ + return -1; + } + dsp_msg_payload = malloc(sizeof(dsp_dual_ir_frame_msg_t)); + if(dsp_msg_payload==NULL) + { + free(dsp_msg); + return -1; + } + meta_data = (csi_camera_meta_s *)master_frame->meta.data; + csi_camera_frame_get_meta_unit( + ×tap, meta_data, CSI_CAMERA_META_ID_TIMESTAMP); + + dsp_msg->payload = dsp_msg_payload; + + dsp_msg_payload->size = master_frame->img.height*master_frame->img.strides[0]; + dsp_msg_payload->width = master_frame->img.width; + dsp_msg_payload->height = master_frame->img.height; + dsp_msg_payload->pix_format = master_frame->img.pix_format; + dsp_msg_payload->master_stride = master_frame->img.strides[0]; + dsp_msg_payload->master_fd = master_frame->img.fds[0]; + dsp_msg_payload->slave_fd = slave_frame->img.fds[0]; + dsp_msg_payload->slave_stride = slave_frame->img.strides[0]; + dsp_msg_payload->timestap = timestap.time_value.tv_sec*1000000+timestap.time_value.tv_usec; + enqueue_msg(queue,dsp_msg); + main_item = malloc(sizeof(frame_item_t)); + main_item->item = master_frame; + slave_item = malloc(sizeof(frame_item_t)); + slave_item->item = slave_frame; + list_add_tail(&main_item->head,send_frames); + list_add_tail(&slave_item->head,send_frames); + LOG_D("send paired fd (%d,%d)\n",dsp_msg_payload->master_fd,dsp_msg_payload->slave_fd); + return 0; +} + +static int cam_dual_frame_process(struct list_head * pair_frame_list,struct list_head * free_frame_list, struct list_head *busy_frame_list,csi_frame_s *frame, msg_queue_ctx_t *dsp_prcoess_queue,cam_sync_message_type_e type) +{ + csi_frame_s *new_frame = NULL; + csi_frame_s *pair_frame = NULL; + csi_frame_s *master_frame = NULL; + csi_frame_s *slave_frame = NULL; + + if(pair_frame_list == NULL ||free_frame_list==NULL ||busy_frame_list ==NULL || + frame == NULL || dsp_prcoess_queue == NULL || type >CAM_SYNC_MSG_SLAVE_FRAME) + { + LOG_E("param check fail \n"); + return -1; + } + + new_frame = malloc(sizeof(csi_frame_s)); + if(new_frame==NULL) + { + LOG_E("malloc fail\n"); + csi_camera_put_frame(frame); + return -1; + } + memcpy(new_frame,frame,sizeof(csi_frame_s)); + pair_frame = pop_matched_frame_with_ts(pair_frame_list,frame,0,true); + if(pair_frame == NULL) + { + if(push_new_frame(free_frame_list,new_frame)) + { + csi_camera_put_frame(new_frame); + free(new_frame); + LOG_E("save new frame fail\n"); + return -1; + } + }else + { + if(type == CAM_SYNC_MSG_MAIN_FRAME) + { + master_frame = new_frame; + slave_frame = pair_frame; + }else + { + master_frame = pair_frame; + slave_frame = new_frame; + } + if(send_paired_frame_to_dsp(dsp_prcoess_queue,master_frame,slave_frame,busy_frame_list)) + { + LOG_E("fail to send paired frame fd (%d,%d) to dsp\n",new_frame->img.fds[0],pair_frame->img.fds[0]); + csi_camera_put_frame(master_frame); + free(master_frame); + csi_camera_put_frame(slave_frame); + free(slave_frame); + return -1; + } + } + return 0; +} + +static void *cam_frame_sync_process(void *arg) +{ + camera_sync_msg_t *msg; + csi_frame_s * master_frame=NULL; + csi_frame_s * slave_frame=NULL; + struct list_head *matched_list=NULL; + msg_queue_item_t * item; + cam_sync_process_ctx_t *ctx =(cam_sync_process_ctx_t *)arg; + LOG_O("frame sync process running....\n"); + while(ctx->cam_sync_queue.exit!=1) + { + item = dequeue_msg(&ctx->cam_sync_queue); + if(item == NULL) + { + usleep(1000); + continue; + } + msg = (camera_sync_msg_t *)item->payload; + free(item); + LOG_D("get msg:%d\n",msg->type); + switch(msg->type) + { + case CAM_SYNC_MSG_MAIN_FRAME: + cam_dual_frame_process(&ctx->cam_slave_frame_list,&ctx->cam_master_frame_list,&ctx->cam_busy_frame_list,&msg->frame,ctx->dsp_prcoess_queue,CAM_SYNC_MSG_MAIN_FRAME); + break; + case CAM_SYNC_MSG_SLAVE_FRAME: + cam_dual_frame_process(&ctx->cam_master_frame_list,&ctx->cam_slave_frame_list,&ctx->cam_busy_frame_list,&msg->frame,ctx->dsp_prcoess_queue,CAM_SYNC_MSG_SLAVE_FRAME); + break; + case CAM_SYNC_MSG_AI_INFO: + break; + case CAM_SYNC_MSG_DSP_INFO: + master_frame = pop_matched_frame_with_fd(&ctx->cam_busy_frame_list,msg->dsp_info.master_fd); + if(master_frame == NULL) + { + LOG_E("fail to find sending fd\n"); + }else + { + csi_camera_put_frame(master_frame); + free(master_frame); + } + slave_frame =pop_matched_frame_with_fd(&ctx->cam_busy_frame_list,msg->dsp_info.slave_fd); + if(slave_frame == NULL) + { + LOG_E("fail to find sending fd\n"); + }else + { + csi_camera_put_frame(slave_frame); + free(slave_frame); + } + ctx->paried_frame_num++; + /***********done some thing for*********/ + break; + default: + LOG_W("invalid msg type:%d\n",msg->type); + break; + } + free(msg); + } + LOG_O("frame sync process exit....\n"); + pthread_exit(0); +} + + +/********************************Main prcoess *******************************************************************/ +static int camera_get_chl_id(int env_type, int *chl_id) +{ + if (chl_id == NULL) { + LOG_E("fail to check param chl_id = %p\n", chl_id); + return -1; + } + switch (env_type) { + case CSI_CAMERA_EVENT_TYPE_CHANNEL0: + *chl_id = CSI_CAMERA_CHANNEL_0; + break; + case CSI_CAMERA_EVENT_TYPE_CHANNEL1: + *chl_id = CSI_CAMERA_CHANNEL_1; + break; + case CSI_CAMERA_EVENT_TYPE_CHANNEL2: + *chl_id = CSI_CAMERA_CHANNEL_2; + break; + default: + LOG_D("fail to check env_type = %d unsupport\n", env_type); + break; + } + return 0; +} +static int cam_send_frame_to_sync_process(msg_queue_ctx_t *queue,csi_frame_s *frame, cam_sync_message_type_e type) +{ + camera_sync_msg_t *msg_palyload = malloc(sizeof(camera_sync_msg_t)); + msg_queue_item_t * item=NULL; + if(msg_palyload==NULL) + { + return -1; + } + item = malloc(sizeof(msg_queue_item_t)); + if(item==NULL) + { + free(msg_palyload); + return -1; + } + msg_palyload->type= type; + memcpy(&msg_palyload->frame,frame,sizeof(csi_frame_s)); + item->payload = msg_palyload; + return enqueue_msg(queue,item); + +} +static int camera_event_process(void *arg) +{ + int ret = 0; + if (arg == NULL) { + LOG_E("NULL Ptr\n"); + return -1; + } + camera_ctx_t* ctx = (camera_ctx_t*)arg; + csi_cam_event_handle_t ev_handle = ctx->event_handle; + csi_camera_channel_cfg_s *ch_cfg=NULL; + cam_sync_message_type_e type; + type = ctx->cam_id==0?CAM_SYNC_MSG_MAIN_FRAME:CAM_SYNC_MSG_SLAVE_FRAME; + struct timeval cur_time; + struct csi_camera_event event; + csi_frame_s frame; + + if (ev_handle == NULL) { + LOG_E("fail to get ev_handle ev_handle\n"); + return -1; + } + + if(ctx->exit!=0) + { + return 1; + } + + int timeout =0; // unit: ms, -1 means wait forever, or until error occurs + ret = csi_camera_get_event(ev_handle, &event, timeout); + if(ret) + { + return -1; + } + LOG_D("Camera_%d event.type = %d, event.id = %d\n",ctx->cam_id ,event.type, event.id); + switch (event.type) { + case CSI_CAMERA_EVENT_TYPE_CAMERA: + switch (event.id) { + case CSI_CAMERA_EVENT_ERROR: + // do sth. + LOG_E("get CAMERA EVENT CSI_CAMERA_EVENT_ERROR!\n"); + break; + case CSI_CAMERA_EVENT_WARNING: + LOG_W("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: + switch (event.id) { + case CSI_CAMERA_CHANNEL_EVENT_FRAME_READY: { + int chn_id = 0; + ret = camera_get_chl_id(event.type, &chn_id); + if (ret) { + LOG_E("fail to get chl_id = %d\n", chn_id); + return -1; + } + ch_cfg = &ctx->chn_cfg[chn_id]; + get_system_time(__func__, __LINE__); + int read_frame_count = csi_camera_get_frame_count(ctx->cam_handle, + chn_id); + + for (int i = 0; i < read_frame_count; i++) { + csi_camera_get_frame(ctx->cam_handle, chn_id, &frame, timeout); + ctx->frame_num++; + if(cam_send_frame_to_sync_process(ctx->cam_sync_queue,&frame,type)) + { + csi_camera_put_frame(&frame); + } + } + + unsigned long diff; + if (ctx->init_time.tv_usec == 0) + gettimeofday(&ctx->init_time,0);//osGetTick(); + gettimeofday(&cur_time, 0); + diff = 1000000 * (cur_time.tv_sec-ctx->init_time.tv_sec)+ cur_time.tv_usec-ctx->init_time.tv_usec; + if (diff != 0) + ctx->fps = (float) ctx->frame_num / diff * 1000000.0f; + LOG_O("cam:%d,read_frame_count = %d, frame_count = %d, fps = %.2f\n", ctx->cam_id,read_frame_count, ctx->frame_num,ctx->fps); + + break; + } + default: + break; + } + break; + default: + break; + } + + return 0; +} + + +static void camera_start_all(camera_ctx_t * ctx) +{ + camera_ctx_t * cam_ctx = ctx; + int loop_ch; + for(loop_ch=0;loop_chchannel_num;loop_ch++) + { + csi_camera_channel_start(cam_ctx->cam_handle, cam_ctx->chn_cfg[loop_ch].chn_id); + } +} + +static void camera_stop_all(camera_ctx_t * ctx) +{ + camera_ctx_t * cam_ctx = ctx; + int loop_ch; + for(loop_ch=0;loop_chchannel_num;loop_ch++) + { + csi_camera_channel_stop(cam_ctx->cam_handle, cam_ctx->chn_cfg[loop_ch].chn_id); + LOG_I("Stop CAM:%d,channel:%d\n",cam_ctx->cam_id,loop_ch); + } +} +static camera_ctx_t * camera_open(camera_param_t *params) +{ + int ret = 0; + char dev_name[128]; + camera_ctx_t * cam_ctx = NULL; + int loop_ch; + LOG_O("Open Camera %d\n",params->video_id); + if(params==NULL || params->video_id <0) + { + LOG_E("param err\n"); + return NULL; + } + if(params->channel_num> MAX_CHANNEL_NUM) + { + LOG_E("unsupoort channle num:%d \n",params->channel_num); + return NULL; + } + + + cam_ctx = malloc(sizeof(camera_ctx_t)); + if(!cam_ctx) + { + return NULL; + } + memset(cam_ctx,0x0,sizeof(camera_ctx_t)); + + // 打开Camera设备获取句柄,作为后续操对象 + sprintf(dev_name, "/dev/video%d", params->video_id); + if(csi_camera_open(&cam_ctx->cam_handle, dev_name)) + { + LOG_E("Fail to open cam :%s\n",dev_name); + goto ONE_ERR; + } + + for(loop_ch= CSI_CAMERA_CHANNEL_0;loop_chchannel_num;loop_ch++) + { + cam_ctx->chn_cfg[loop_ch].chn_id = loop_ch; + cam_ctx->chn_cfg[loop_ch].img_fmt.pix_fmt = params->out_pic[loop_ch].fmt; + cam_ctx->chn_cfg[loop_ch].img_fmt.width= params->out_pic[loop_ch].width; + cam_ctx->chn_cfg[loop_ch].img_fmt.height = params->out_pic[loop_ch].height; + cam_ctx->chn_cfg[loop_ch].img_type = CSI_IMG_TYPE_DMA_BUF; + cam_ctx->chn_cfg[loop_ch].meta_fields = CSI_CAMERA_META_DEFAULT_FIELDS; + if(csi_camera_channel_open(cam_ctx->cam_handle,&cam_ctx->chn_cfg[loop_ch])) + { + LOG_E("Fail to open cam %s,channel :%d\n",dev_name,loop_ch); + goto TWO_ERR; + } + + cam_ctx->channel_num++; + } + + if(csi_camera_create_event(&cam_ctx->event_handle,cam_ctx->cam_handle)) + { + LOG_E("Fail to create event handler for cam %s\n",dev_name); + goto TWO_ERR; + } + + cam_ctx->event_subscribe.type = CSI_CAMERA_EVENT_TYPE_CAMERA; + cam_ctx->event_subscribe.id = CSI_CAMERA_EVENT_WARNING | CSI_CAMERA_EVENT_ERROR; + if(csi_camera_subscribe_event(cam_ctx->event_handle,&cam_ctx->event_subscribe)) + { + LOG_E("Fail to subscribe eventfor cam %s\n",dev_name); + goto TWO_ERR; + } + + + for(loop_ch=0;loop_chchannel_num;loop_ch++) + { + cam_ctx->event_subscribe.type = CSI_CAMERA_EVENT_TYPE_CHANNEL0+loop_ch; + cam_ctx->event_subscribe.id = CSI_CAMERA_CHANNEL_EVENT_FRAME_READY; + if(csi_camera_subscribe_event(cam_ctx->event_handle,&cam_ctx->event_subscribe)) + { + LOG_E("Fail to subscribe eventfor cam %s\n",dev_name); + goto TWO_ERR; + } + } + + LOG_O("%s open successfully\n",dev_name); + + // if(params->type == CAM_TYEP_MASTER) + // { + // csi_camera_floodlight_led_set_flash_bright(cam_ctx->cam_handle, 500); //500ma + // csi_camera_projection_led_set_flash_bright(cam_ctx->cam_handle, 500); //500ma + // csi_camera_projection_led_set_mode(cam_ctx->cam_handle, LED_IR_ENABLE); + // csi_camera_floodlight_led_set_mode(cam_ctx->cam_handle, LED_IR_ENABLE); + // csi_camera_led_enable(cam_ctx->cam_handle, LED_FLOODLIGHT_PROJECTION); + // } + + get_system_time(__func__, __LINE__); + + + return cam_ctx; + + +TWO_ERR: + for(loop_ch=0;loop_chchannel_num;loop_ch++) + { + csi_camera_channel_close(cam_ctx->cam_handle, cam_ctx->chn_cfg[loop_ch].chn_id); + } + csi_camera_close(cam_ctx->cam_handle); +ONE_ERR: + free(cam_ctx); + return NULL; +} + +static void camera_close(camera_ctx_t *ctx) +{ + int loop_ch; + if(ctx->cam_handle==NULL ) + { + return; + } + + csi_camera_unsubscribe_event(ctx->event_handle, &ctx->event_subscribe); + + csi_camera_destory_event(ctx->event_handle); + + for(loop_ch=0;loop_chchannel_num;loop_ch++) + { + csi_camera_channel_close(ctx->cam_handle, ctx->chn_cfg[loop_ch].chn_id); + } + csi_camera_close(ctx->cam_handle); + free(ctx); +} + +cam_sync_process_ctx_t *cam_sync_hdl; +dual_dsp_handle_t *dsp_hdl; + +int main(int argc, char *argv[]) +{ + + char dev_name[128]; + int camera_id = 0; + // 打印HAL接口版本号 + csi_api_version_u version; + csi_camera_get_version(&version); + camera_param_t params[MAX_CAM_NUM]; + camera_ctx_t * ctx[MAX_CAM_NUM]={NULL}; + frame_mode_t frame_mode ; + int cam_num=0; + bool running = false; + cam_num =parseParams(argc,argv,params,&frame_mode); + if(cam_num <=0 || cam_num>MAX_CAM_NUM) + { + LOG_E("not camera is active\n"); + exit(0); + } + + dsp_hdl =dsp_process_create(frame_mode); + if(dsp_hdl==NULL) + { + LOG_E("dsp create faile\n"); + exit(0); + } + cam_sync_hdl =cam_sync_create(); + if(cam_sync_hdl==NULL) + { + LOG_E("cam sync create fail\n"); + dsp_process_destroy(dsp_hdl); + exit(0); + } + + dsp_hdl->cam_sync_queue = &cam_sync_hdl->cam_sync_queue; + cam_sync_hdl->dsp_prcoess_queue = &dsp_hdl->dsp_prcoess_queue; + + for(int i =cam_num-1;i>=0;i--) + { + ctx[i]=camera_open(¶ms[i]); + if(ctx[i]==NULL) + { + LOG_E("camera %d open %dfail\n",i,params[i].type); + goto ONR_ERR; + } + ctx[i]->cam_id = i; + ctx[i]->frame_num =0; + ctx[i]->cam_sync_queue = &cam_sync_hdl->cam_sync_queue; + if(params[i].type ==CAM_TYEP_MASTER ) + { + cam_sync_hdl->master_cam_handle=ctx[i]->cam_handle; + } + else if(params[i].type ==CAM_TYEP_SLAVE) + { + cam_sync_hdl->slave_cam_handle = ctx[i]->cam_handle; + } + camera_start_all(ctx[i]); + running = true; + } + + int all_exit=1; + do{ + usleep(1000); + all_exit=1; + for(int i =cam_num-1;i>=0;i--) + { + + camera_event_process(ctx[i]); + if(ctx[i]&& + ctx[i]->exit==0 && + params[i].frames_to_stop>0 && + cam_sync_hdl->paried_frame_num >=params[i].frames_to_stop) + { + camera_stop_all(ctx[i]); + ctx[i]->exit=1; + } + if(ctx[i]) + all_exit &= ctx[i]->exit; + } + if(all_exit ==1) + { + LOG_O("All camera are stop\n"); + running = false; + } + + }while(running); + +ONR_ERR: + for(int i =0;imeta.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_I("meta_id=%d, meta_type=%d, meta_value=%d\n", + meta_unit.id, meta_unit.type, meta_unit.int_value); +} + + diff --git a/examples/camera/cam_demo_ir.c b/examples/camera/cam_demo_ir.c index 046d872..b99718e 100644 --- a/examples/camera/cam_demo_ir.c +++ b/examples/camera/cam_demo_ir.c @@ -58,6 +58,7 @@ static event_queue_item_t *dequeue_event(channel_handle_ctx_t *ctx) if(!ev) { pthread_mutex_unlock(&ctx->event_queue.mutex); + usleep(1000); return NULL; } @@ -223,7 +224,8 @@ int main(int argc, char *argv[]) int frame_num = 0; algo_2 = "dsp1_dummy_algo_flo"; algo_1 = "dsp1_dummy_algo_flo_1"; - switch(argc) + int ret = 0; + switch(argc) { case 0: case 1: @@ -303,8 +305,12 @@ int main(int argc, char *argv[]) /* The caps are: Video capture, metadata capture */ // 打开Camera设备获取句柄,作为后续操对象 csi_cam_handle_t cam_handle; - csi_camera_open(&cam_handle, camera_info.device_name); - LOG_O("csi_camera_open() OK\n"); + ret = csi_camera_open(&cam_handle, camera_info.device_name); + if (ret) { + LOG_E("Failed to csi_camera_open %s\n", camera_info.device_name); + exit(-1); + } + LOG_O("csi_camera_open() OK\n"); // 获取Camera支持的工作模式 struct csi_camera_modes camera_modes; @@ -332,7 +338,10 @@ int main(int argc, char *argv[]) chn_cfg.meta_fields = CSI_CAMERA_META_DEFAULT_FIELDS; chn_cfg.capture_type = CSI_CAMERA_CHANNEL_CAPTURE_VIDEO | CSI_CAMERA_CHANNEL_CAPTURE_META; - csi_camera_channel_open(cam_handle, &chn_cfg); + ret = csi_camera_channel_open(cam_handle, &chn_cfg); + if (ret) { + exit(-1); + } LOG_O("CSI_CAMERA_CHANNEL_0: csi_camera_channel_open() OK\n"); @@ -346,7 +355,10 @@ int main(int argc, char *argv[]) chn_cfg.meta_fields = CSI_CAMERA_META_DEFAULT_FIELDS; chn_cfg.capture_type = CSI_CAMERA_CHANNEL_CAPTURE_VIDEO | CSI_CAMERA_CHANNEL_CAPTURE_META; - csi_camera_channel_open(cam_handle, &chn_cfg); + ret = csi_camera_channel_open(cam_handle, &chn_cfg); + if (ret) { + exit(-1); + } LOG_O("CSI_CAMERA_CHANNEL_1: csi_camera_channel_open() OK\n"); // 订阅Event @@ -402,8 +414,7 @@ int main(int argc, char *argv[]) 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"); - + LOG_E("set DSP algo fail\n"); } @@ -436,11 +447,18 @@ int main(int argc, char *argv[]) csi_camera_projection_led_set_mode(cam_handle, LED_IR_ENABLE); csi_camera_floodlight_led_set_mode(cam_handle, LED_IR_ENABLE); csi_camera_led_enable(cam_handle, LED_FLOODLIGHT_PROJECTION); - + csi_camera_led_set_switch_mode(cam_handle, SWITCH_MODE_PROJECTION_EVEN_FLOODLIGHT_ODD); + // 开始从channel中取出准备好的frame - csi_camera_channel_start(cam_handle, CSI_CAMERA_CHANNEL_0); - csi_camera_channel_start(cam_handle, CSI_CAMERA_CHANNEL_1); - LOG_O("Channel start OK\n"); + ret = csi_camera_channel_start(cam_handle, CSI_CAMERA_CHANNEL_0); + if (ret) { + exit(-1); + } + ret = csi_camera_channel_start(cam_handle, CSI_CAMERA_CHANNEL_1); + if (ret) { + exit(-1); + } + LOG_O("Channel start OK\n"); // 处理订阅的Event csi_frame_s frame; @@ -450,14 +468,21 @@ int main(int argc, char *argv[]) while (running) { int timeout = -1; // unit: ms, -1 means wait forever, or until error occurs event_item = malloc(sizeof( event_queue_item_t)); - csi_camera_get_event(event_handle, &event_item->evet, timeout); - LOG_O("event.type = %d, event.id = %d\n",event_item->evet.type, event_item->evet.id); - + if(csi_camera_get_event(event_handle, &event_item->evet, timeout)) + { + LOG_E("get event timeout\n"); + free(event_item); + continue; + } + LOG_O("event.type = %d, event.id = %d\n",event_item->evet.type, event_item->evet.id); switch (event_item->evet.type) { case CSI_CAMERA_EVENT_TYPE_CAMERA: switch (event_item->evet.id) { case CSI_CAMERA_EVENT_ERROR: - // do sth. + LOG_E("CSI_CAMERA_EVENT_ERROR reprot\n"); + break; + case CSI_CAMERA_EVENT_WARNING: + LOG_W("CSI_CAMERA_EVENT_ERROR reprot\n"); break; default: break; @@ -521,6 +546,7 @@ int main(int argc, char *argv[]) csi_camera_destory_event(event_handle); csi_camera_channel_close(cam_handle, CSI_CAMERA_CHANNEL_0); + csi_camera_channel_close(cam_handle, CSI_CAMERA_CHANNEL_1); csi_camera_close(cam_handle); } diff --git a/examples/camera/cam_demo_simple.c b/examples/camera/cam_demo_simple.c index 04a03e4..021d6fc 100644 --- a/examples/camera/cam_demo_simple.c +++ b/examples/camera/cam_demo_simple.c @@ -229,7 +229,11 @@ int main(int argc, char *argv[]) get_system_time(__func__, __LINE__); // 打开Camera设备获取句柄,作为后续操对象 csi_cam_handle_t cam_handle; - csi_camera_open(&cam_handle, camera_info.device_name); + ret = csi_camera_open(&cam_handle, camera_info.device_name); + if (ret) { + LOG_E("Failed to csi_camera_open %s\n", camera_info.device_name); + exit(-1); + } get_system_time(__func__, __LINE__); // 获取Camera支持的工作模式 struct csi_camera_modes camera_modes; @@ -317,9 +321,10 @@ int main(int argc, char *argv[]) if (csi_camera_set_property(cam_handle, &properties) < 0) { LOG_O("set_property fail!\n"); } - LOG_O("set_property ok!\n"); - - + else + { + 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); @@ -440,8 +445,12 @@ int main(int argc, char *argv[]) } */ // 开始从channel中取出准备好的frame - csi_camera_channel_start(cam_handle, chn_id); - get_system_time(__func__, __LINE__); + ret = csi_camera_channel_start(cam_handle, chn_id); + if (ret) { + LOG_E("Failed to csi_camera_channel_start ch%d\n", chn_id); + exit(-1); + } + get_system_time(__func__, __LINE__); // 处理订阅的Event csi_frame_s frame; struct csi_camera_event event; @@ -453,7 +462,11 @@ int main(int argc, char *argv[]) } } int timeout = -1; // unit: ms, -1 means wait forever, or until error occurs - csi_camera_get_event(event_handle, &event, timeout); + if(csi_camera_get_event(event_handle, &event, timeout)) + { + LOG_E("Failed to get event \n"); + continue; + } // printf("%s event.type = %d, event.id = %d\n", __func__, event.type, event.id); switch (event.type) { case CSI_CAMERA_EVENT_TYPE_CAMERA: @@ -493,7 +506,11 @@ int main(int argc, char *argv[]) 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); + if(csi_camera_get_frame(cam_handle, chn_id, &frame, timeout)) + { + LOG_W("get frame fail\n"); + continue; + } #ifdef PLATFORM_SIMULATOR if (frame.img.type == CSI_IMG_TYPE_DMA_BUF) { void *phyaddr = vi_mem_import(frame.img.dmabuf[0].fds); @@ -504,7 +521,6 @@ int main(int argc, char *argv[]) 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); @@ -515,10 +531,9 @@ int main(int argc, char *argv[]) } if (display_enable == 1) { display_camera_frame(display_plink, &frame); + continue; } - // csi_camera_frame_unlock(cam_handle, &frame); csi_camera_put_frame(&frame); - csi_frame_release(&frame); } break; diff --git a/examples/camera/camera_demo2.c b/examples/camera/camera_demo2.c index 15b641a..1fc63b3 100644 --- a/examples/camera/camera_demo2.c +++ b/examples/camera/camera_demo2.c @@ -265,11 +265,6 @@ int main(int argc, char *argv[]) CSI_CAMERA_CHANNEL_0); csi_camera_get_frame(cam_handle,CSI_CAMERA_CHANNEL_0, &frame, timeout); - // frame.image: {.width, .height, .pix_fmt, .dma-buf} - //show_frame_image(frame.image); // 伪代码 - // frame.meta: {.count, - // .meta_data[]={meta_id, type, - // union{int_value, str_value, ...}}} #ifdef PLATFORM_SIMULATOR camera_action_image_display(&frame); diff --git a/examples/camera/camera_demo3_srcs/dialog_camera_open.c b/examples/camera/camera_demo3_srcs/dialog_camera_open.c index f7f70de..91ef5de 100644 --- a/examples/camera/camera_demo3_srcs/dialog_camera_open.c +++ b/examples/camera/camera_demo3_srcs/dialog_camera_open.c @@ -103,7 +103,7 @@ again: /* Show operation result */ cam_id = item_activate_selected_pos(); //char str_buf[256]; - bool opened = (camera_open(cam_session, cam_id) == 0); + bool opened = (camera_open(cam_session, "/dev/video0") == 0); snprintf(str_buf, sizeof(str_buf), "Open the below camera %s:\n" "\t id=%d \n\t name='%s' \n\t device='%s' \n\t bus='%s'\n", diff --git a/examples/camera/camera_frame_display.c b/examples/camera/camera_frame_display.c index b7b4461..e96d0f5 100644 --- a/examples/camera/camera_frame_display.c +++ b/examples/camera/camera_frame_display.c @@ -38,11 +38,14 @@ typedef struct _CsiPlinkContext int useplink; int exitplink; CsiPictureBuffer sendbuffer[NUM_OF_BUFFERS]; + csi_frame_s frame_buf[NUM_OF_BUFFERS]; int sendid; int available_bufs; void *vmem; PlinkHandle plink; PlinkChannelID chnid; + pthread_t buf_release_thread; + pthread_mutex_t mutex; } CsiPlinkContext; static int get_buffer_count(PlinkPacket *pkt) { @@ -65,7 +68,64 @@ static int get_buffer_count(PlinkPacket *pkt) return ret; } -static void allocate_sendbuffers(CsiPictureBuffer picbuffers[NUM_OF_BUFFERS], unsigned int size, void *vmem) +static void* camera_buf_release_process(CsiPlinkContext * plink_ctx) +{ + PlinkPacket pkt = {0}; + if(plink_ctx == NULL) + { + return NULL; + } + LOG_O("Process is runing.....\n"); + while(!plink_ctx->exitplink) + { + if (plink_ctx->plink != NULL) { + if (PLINK_wait(plink_ctx->plink, plink_ctx->chnid, 1000) == PLINK_STATUS_OK) + { + if (PLINK_recv(plink_ctx->plink, plink_ctx->chnid, &pkt) != PLINK_STATUS_OK) { + plink_ctx->exitplink = 1; + break; + } + int count = get_buffer_count(&pkt); + if (count >= 0) + { + PlinkMsg *hdr; + int resp_id; + for(int i=0;imsg; + if((resp_id>=NUM_OF_BUFFERS)) + { + LOG_W("invalid resp_id:%d\n",resp_id); + continue; + } + if(plink_ctx->frame_buf[resp_id].img.dmabuf[0].fds!= 0) + { + csi_camera_put_frame(&plink_ctx->frame_buf[resp_id]); + LOG_D("release resp_id:%d, fd:%d\n",resp_id,plink_ctx->frame_buf[resp_id].img.dmabuf[0].fds); + plink_ctx->frame_buf[resp_id].img.dmabuf[0].fds = 0; + } + + } + pthread_mutex_lock(&plink_ctx->mutex); + plink_ctx->available_bufs += count; + pthread_mutex_unlock(&plink_ctx->mutex); + } + else { + fprintf(stderr, "[SERVER] Exit!\n"); + plink_ctx->exitplink = 1; + break; + } + }else + { + LOG_W("Plink Resp timeout\n"); + } + } + } + LOG_O("Process is exit .....\n"); + return NULL; +} +static int allocate_sendbuffers(CsiPictureBuffer picbuffers[NUM_OF_BUFFERS], unsigned int size, void *vmem) { unsigned int buffer_size = (size + 0xFFF) & ~0xFFF; VmemParams params; @@ -73,7 +133,9 @@ static void allocate_sendbuffers(CsiPictureBuffer picbuffers[NUM_OF_BUFFERS], un params.flags = VMEM_FLAG_CONTIGUOUS | VMEM_FLAG_4GB_ADDR; for (int i = 0; i < NUM_OF_BUFFERS; i++) { - VMEM_allocate(vmem, ¶ms); + if (VMEM_allocate(vmem, ¶ms) != 0) { + return -1; + } VMEM_mmap(vmem, ¶ms); VMEM_export(vmem, ¶ms); LOG_O("[SERVER] mmap %p from %x with size %d, dma-buf fd %d\n", @@ -146,7 +208,9 @@ void *vi_plink_create(csi_camera_channel_cfg_s *chn_cfg) case CSI_PIX_FMT_BGR: { framesize = stride * 304 * 3; //stride * chn_cfg->img_fmt.height * 3; - allocate_sendbuffers(plink_ctx->sendbuffer, framesize, plink_ctx->vmem); + if (allocate_sendbuffers(plink_ctx->sendbuffer, framesize, plink_ctx->vmem) != 0) { + return NULL; + } // reset to black picture uint32_t lumasize = stride * chn_cfg->img_fmt.height; for (int i = 0; i < NUM_OF_BUFFERS; i++) @@ -158,7 +222,9 @@ void *vi_plink_create(csi_camera_channel_cfg_s *chn_cfg) default: { framesize = stride * chn_cfg->img_fmt.height * 3 / 2; - allocate_sendbuffers(plink_ctx->sendbuffer, framesize, plink_ctx->vmem); + if (allocate_sendbuffers(plink_ctx->sendbuffer, framesize, plink_ctx->vmem) != 0) { + return NULL; + } // reset to black picture uint32_t lumasize = stride * chn_cfg->img_fmt.height; for (int i = 0; i < NUM_OF_BUFFERS; i++) { @@ -178,6 +244,10 @@ void *vi_plink_create(csi_camera_channel_cfg_s *chn_cfg) plink_ctx->sendid = 0; plink_ctx->available_bufs = NUM_OF_BUFFERS; + memset(plink_ctx->frame_buf,0x0,sizeof(plink_ctx->frame_buf)); + pthread_mutex_init(&plink_ctx->mutex,NULL); + pthread_create(&plink_ctx->buf_release_thread,NULL,(void *)camera_buf_release_process,plink_ctx); + return plink_ctx; } @@ -187,6 +257,9 @@ void vi_plink_release(void * plink) CsiPlinkContext * plink_ctx = (CsiPlinkContext *)plink; if(plink_ctx) { + plink_ctx->exitplink=1; + pthread_join(plink_ctx->buf_release_thread,NULL); + PLINK_close(plink_ctx->plink,plink_ctx->chnid); VMEM_destroy(plink_ctx->vmem); } @@ -203,40 +276,12 @@ void display_camera_frame(void *plink, csi_frame_s *frame) } - LOG_O("%sfmt=%d img.strides[0] = %d\n", __func__,frame->img.pix_format, frame->img.strides[0]); + LOG_O("fmt=%d img.strides[0] = %d\n",frame->img.pix_format, frame->img.strides[0]); if (!plink_ctx->exitplink) { struct timeval tv_start, tv_end, tv_duration; gettimeofday(&tv_start, 0); - // retrieve buffers PlinkPacket pkt = {0}; - if (plink_ctx->plink != NULL) { - while (PLINK_wait(plink_ctx->plink, plink_ctx->chnid, 0) == PLINK_STATUS_OK) - { - if (PLINK_recv(plink_ctx->plink, plink_ctx->chnid, &pkt) != PLINK_STATUS_OK) { - plink_ctx->exitplink = 1; - break; - } - int count = get_buffer_count(&pkt); - if (count >= 0) - plink_ctx->available_bufs += count; - else { - fprintf(stderr, "[SERVER] Exit!\n"); - plink_ctx->exitplink = 1; - break; - } - } - } - - /* - void *phy_address = NULL; - int dmabuf_fd = -1; - if (vi_mem_dmabuf_isenable()) { - phy_address = vi_mem_unmap(frame->img.usr_addr[0]); - dmabuf_fd = vi_mem_export(phy_address); - } - */ - // send one buffer if there is available slot if (frame->img.type == CSI_IMG_TYPE_DMA_BUF && !plink_ctx->exitplink && plink_ctx->available_bufs > 0 && plink_ctx->plink != NULL && ((frame->img.pix_format == CSI_PIX_FMT_RAW_8BIT)|| (frame->img.pix_format == CSI_PIX_FMT_RAW_12BIT))) { @@ -245,15 +290,12 @@ void display_camera_frame(void *plink, csi_frame_s *frame) uint32_t dstw = frame->img.width;//800; uint32_t dsth = frame->img.height;//1280; uint32_t dsts = frame->img.strides[0];//896; - i++; - sprintf(str, "echo frame is %d > ~/frame", i); - system(str); PlinkRawInfo info = {0}; info.header.type = PLINK_TYPE_2D_RAW; info.header.size = DATA_SIZE(info); - info.header.id = plink_ctx->sendid + 1; + info.header.id = plink_ctx->sendid; info.format = PLINK_COLOR_FormatRawBayer10bit; // info.bus_address = vi_mem_import(frame->img.dmabuf[0].fds) + frame->img.dmabuf[0].offset; @@ -266,12 +308,20 @@ void display_camera_frame(void *plink, csi_frame_s *frame) pkt.list[0] = &info; pkt.num = 1; pkt.fd = frame->img.dmabuf[0].fds; + if(plink_ctx->frame_buf[plink_ctx->sendid].img.dmabuf[0].fds!=0) + { + LOG_W("previous sendid :%d,fd %d not release,release it now\n",plink_ctx->sendid,plink_ctx->frame_buf[plink_ctx->sendid].img.dmabuf[0].fds); + csi_camera_put_frame(&plink_ctx->frame_buf[plink_ctx->sendid]); + } + memcpy(&plink_ctx->frame_buf[plink_ctx->sendid],frame,sizeof(csi_frame_s)); + plink_ctx->sendid = (plink_ctx->sendid + 1) % NUM_OF_BUFFERS; if (PLINK_send(plink_ctx->plink, plink_ctx->chnid, &pkt) != PLINK_STATUS_OK) plink_ctx->exitplink = 1; gettimeofday(&tv_end, 0); timersub(&tv_end, &tv_start, &tv_duration); - plink_ctx->sendid = (plink_ctx->sendid + 1) % NUM_OF_BUFFERS; + pthread_mutex_lock(&plink_ctx->mutex); plink_ctx->available_bufs -= 1; + pthread_mutex_unlock(&plink_ctx->mutex); } else if (frame->img.type == CSI_IMG_TYPE_DMA_BUF && !plink_ctx->exitplink && plink_ctx->available_bufs > 0 && plink_ctx->plink != NULL && ((frame->img.pix_format == CSI_PIX_FMT_YUV_SEMIPLANAR_420)|| (frame->img.pix_format == CSI_PIX_FMT_NV12))) { @@ -280,15 +330,13 @@ void display_camera_frame(void *plink, csi_frame_s *frame) uint32_t dstw = frame->img.width;//800; uint32_t dsth = frame->img.height;//1280; uint32_t dsts = frame->img.strides[0];//896; - i++; - sprintf(str, "echo frame is %d > ~/frame", i); - system(str); + PlinkYuvInfo info = {0}; info.header.type = PLINK_TYPE_2D_YUV; info.header.size = DATA_SIZE(info); - info.header.id = plink_ctx->sendid + 1; + info.header.id = plink_ctx->sendid; info.format = PLINK_COLOR_FormatYUV420SemiPlanar; // info.bus_address_y = vi_mem_import(frame->img.dmabuf[0].fds) + frame->img.dmabuf[0].offset; @@ -306,16 +354,32 @@ void display_camera_frame(void *plink, csi_frame_s *frame) pkt.list[0] = &info; pkt.num = 1; pkt.fd = frame->img.dmabuf[0].fds; + + if(plink_ctx->frame_buf[plink_ctx->sendid].img.dmabuf[0].fds!=0) + { + LOG_W("previous sendid :%d,fd %d not release,release it now\n",plink_ctx->sendid,plink_ctx->frame_buf[plink_ctx->sendid].img.dmabuf[0].fds); + csi_camera_put_frame(&plink_ctx->frame_buf[plink_ctx->sendid]); + } + memcpy(&plink_ctx->frame_buf[plink_ctx->sendid],frame,sizeof(csi_frame_s)); + plink_ctx->sendid = (plink_ctx->sendid + 1) % NUM_OF_BUFFERS; if (PLINK_send(plink_ctx->plink, plink_ctx->chnid, &pkt) != PLINK_STATUS_OK) plink_ctx->exitplink = 1; gettimeofday(&tv_end, 0); timersub(&tv_end, &tv_start, &tv_duration); - plink_ctx->sendid = (plink_ctx->sendid + 1) % NUM_OF_BUFFERS; + pthread_mutex_lock(&plink_ctx->mutex); plink_ctx->available_bufs -= 1; + pthread_mutex_unlock(&plink_ctx->mutex); } else if (!plink_ctx->exitplink && plink_ctx->available_bufs > 0 && plink_ctx->plink != NULL && (frame->img.pix_format == CSI_PIX_FMT_BGR)) { CsiPictureBuffer *buf = &plink_ctx->sendbuffer[plink_ctx->sendid]; int y = 0; - + // if (1) { + // void *pbuf[3]; + // void *phyaddr = vi_mem_import(frame->img.dmabuf[0].fds); + // pbuf[0] = vi_mem_map(phyaddr) + frame->img.dmabuf[0].offset; + // pbuf[1] = pbuf[0] + frame->img.dmabuf[1].offset; + // vi_mem_release(phyaddr); + // frame->img.usr_addr[0] = pbuf[0]; + // } uint8_t *src = frame->img.usr_addr[0]; uint8_t *dst = buf->virtual_address; uint32_t srcw = frame->img.width; @@ -429,9 +493,10 @@ void display_camera_frame(void *plink, csi_frame_s *frame) gettimeofday(&tv_end, 0); timersub(&tv_end, &tv_start, &tv_duration); - + pthread_mutex_lock(&plink_ctx->mutex); plink_ctx->sendid = (plink_ctx->sendid + 1) % NUM_OF_BUFFERS; plink_ctx->available_bufs -= 1; + pthread_mutex_unlock(&plink_ctx->mutex); } } LOG_O("%s exit \n", __func__); diff --git a/examples/camera/list.h b/examples/camera/list.h new file mode 100755 index 0000000..efe0696 --- /dev/null +++ b/examples/camera/list.h @@ -0,0 +1,353 @@ +/* + * Copyright © 2010 Intel Corporation + * Copyright © 2010 Francisco Jerez + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + */ + +/* Modified by Ben Skeggs to match kernel list APIs */ + +#ifndef _XORG_LIST_H_ +#define _XORG_LIST_H_ + +/** + * @file Classic doubly-link circular list implementation. + * For real usage examples of the linked list, see the file test/list.c + * + * Example: + * We need to keep a list of struct foo in the parent struct bar, i.e. what + * we want is something like this. + * + * struct bar { + * ... + * struct foo *list_of_foos; -----> struct foo {}, struct foo {}, struct foo{} + * ... + * } + * + * We need one list head in bar and a list element in all list_of_foos (both are of + * data type 'struct list_head'). + * + * struct bar { + * ... + * struct list_head list_of_foos; + * ... + * } + * + * struct foo { + * ... + * struct list_head entry; + * ... + * } + * + * Now we initialize the list head: + * + * struct bar bar; + * ... + * INIT_LIST_HEAD(&bar.list_of_foos); + * + * Then we create the first element and add it to this list: + * + * struct foo *foo = malloc(...); + * .... + * list_add(&foo->entry, &bar.list_of_foos); + * + * Repeat the above for each element you want to add to the list. Deleting + * works with the element itself. + * list_del(&foo->entry); + * free(foo); + * + * Note: calling list_del(&bar.list_of_foos) will set bar.list_of_foos to an empty + * list again. + * + * Looping through the list requires a 'struct foo' as iterator and the + * name of the field the subnodes use. + * + * struct foo *iterator; + * list_for_each_entry(iterator, &bar.list_of_foos, entry) { + * if (iterator->something == ...) + * ... + * } + * + * Note: You must not call list_del() on the iterator if you continue the + * loop. You need to run the safe for-each loop instead: + * + * struct foo *iterator, *next; + * list_for_each_entry_safe(iterator, next, &bar.list_of_foos, entry) { + * if (...) + * list_del(&iterator->entry); + * } + * + */ + +/** + * The linkage struct for list nodes. This struct must be part of your + * to-be-linked struct. struct list_head is required for both the head of the + * list and for each list node. + * + * Position and name of the struct list_head field is irrelevant. + * There are no requirements that elements of a list are of the same type. + * There are no requirements for a list head, any struct list_head can be a list + * head. + */ +struct list_head { + struct list_head *next, *prev; +}; + +/** + * Initialize the list as an empty list. + * + * Example: + * INIT_LIST_HEAD(&bar->list_of_foos); + * + * @param The list to initialized. + */ +#define LIST_HEAD_INIT(name) { &(name), &(name) } + +#define LIST_HEAD(name) \ + struct list_head name = LIST_HEAD_INIT(name) + +static inline void +INIT_LIST_HEAD(struct list_head *list) +{ + list->next = list->prev = list; +} + +static inline void +__list_add(struct list_head *entry, + struct list_head *prev, struct list_head *next) +{ + next->prev = entry; + entry->next = next; + entry->prev = prev; + prev->next = entry; +} + +/** + * Insert a new element after the given list head. The new element does not + * need to be initialised as empty list. + * The list changes from: + * head → some element → ... + * to + * head → new element → older element → ... + * + * Example: + * struct foo *newfoo = malloc(...); + * list_add(&newfoo->entry, &bar->list_of_foos); + * + * @param entry The new element to prepend to the list. + * @param head The existing list. + */ +static inline void +list_add(struct list_head *entry, struct list_head *head) +{ + __list_add(entry, head, head->next); +} + +/** + * Append a new element to the end of the list given with this list head. + * + * The list changes from: + * head → some element → ... → lastelement + * to + * head → some element → ... → lastelement → new element + * + * Example: + * struct foo *newfoo = malloc(...); + * list_add_tail(&newfoo->entry, &bar->list_of_foos); + * + * @param entry The new element to prepend to the list. + * @param head The existing list. + */ +static inline void +list_add_tail(struct list_head *entry, struct list_head *head) +{ + __list_add(entry, head->prev, head); +} + +static inline void +__list_del(struct list_head *prev, struct list_head *next) +{ + next->prev = prev; + prev->next = next; +} + +/** + * Remove the element from the list it is in. Using this function will reset + * the pointers to/from this element so it is removed from the list. It does + * NOT free the element itself or manipulate it otherwise. + * + * Using list_del on a pure list head (like in the example at the top of + * this file) will NOT remove the first element from + * the list but rather reset the list as empty list. + * + * Example: + * list_del(&foo->entry); + * + * @param entry The element to remove. + */ +static inline void +list_del(struct list_head *entry) +{ + __list_del(entry->prev, entry->next); +} + +static inline void +list_del_init(struct list_head *entry) +{ + __list_del(entry->prev, entry->next); + INIT_LIST_HEAD(entry); +} + +static inline void list_move_tail(struct list_head *list, + struct list_head *head) +{ + __list_del(list->prev, list->next); + list_add_tail(list, head); +} + +/** + * Check if the list is empty. + * + * Example: + * list_empty(&bar->list_of_foos); + * + * @return True if the list contains one or more elements or False otherwise. + */ +static inline int +list_empty(struct list_head *head) +{ + return head->next == head; +} + +/** + * Returns a pointer to the container of this list element. + * + * Example: + * struct foo* f; + * f = container_of(&foo->entry, struct foo, entry); + * assert(f == foo); + * + * @param ptr Pointer to the struct list_head. + * @param type Data type of the list element. + * @param member Member name of the struct list_head field in the list element. + * @return A pointer to the data struct containing the list head. + */ +#ifndef container_of +#define container_of(ptr, type, member) \ + (type *)((char *)(ptr) - (char *) &((type *)0)->member) +#endif + +/** + * Alias of container_of + */ +#define list_entry(ptr, type, member) \ + container_of(ptr, type, member) + +/** + * Retrieve the first list entry for the given list pointer. + * + * Example: + * struct foo *first; + * first = list_first_entry(&bar->list_of_foos, struct foo, list_of_foos); + * + * @param ptr The list head + * @param type Data type of the list element to retrieve + * @param member Member name of the struct list_head field in the list element. + * @return A pointer to the first list element. + */ +#define list_first_entry(ptr, type, member) \ + list_entry((ptr)->next, type, member) + +/** + * Retrieve the last list entry for the given listpointer. + * + * Example: + * struct foo *first; + * first = list_last_entry(&bar->list_of_foos, struct foo, list_of_foos); + * + * @param ptr The list head + * @param type Data type of the list element to retrieve + * @param member Member name of the struct list_head field in the list element. + * @return A pointer to the last list element. + */ +#define list_last_entry(ptr, type, member) \ + list_entry((ptr)->prev, type, member) + +#define __container_of(ptr, sample, member) \ + (void *)container_of((ptr), typeof(*(sample)), member) + +/** + * Loop through the list given by head and set pos to struct in the list. + * + * Example: + * struct foo *iterator; + * list_for_each_entry(iterator, &bar->list_of_foos, entry) { + * [modify iterator] + * } + * + * This macro is not safe for node deletion. Use list_for_each_entry_safe + * instead. + * + * @param pos Iterator variable of the type of the list elements. + * @param head List head + * @param member Member name of the struct list_head in the list elements. + * + */ +#define list_for_each_entry(pos, head, member) \ + for (pos = __container_of((head)->next, pos, member); \ + &pos->member != (head); \ + pos = __container_of(pos->member.next, pos, member)) + +/** + * Loop through the list, keeping a backup pointer to the element. This + * macro allows for the deletion of a list element while looping through the + * list. + * + * See list_for_each_entry for more details. + */ +#define list_for_each_entry_safe(pos, tmp, head, member) \ + for (pos = __container_of((head)->next, pos, member), \ + tmp = __container_of(pos->member.next, pos, member); \ + &pos->member != (head); \ + pos = tmp, tmp = __container_of(pos->member.next, tmp, member)) + + +#define list_for_each_entry_reverse(pos, head, member) \ + for (pos = __container_of((head)->prev, pos, member); \ + &pos->member != (head); \ + pos = __container_of(pos->member.prev, pos, member)) + +#define list_for_each_entry_continue(pos, head, member) \ + for (pos = __container_of(pos->member.next, pos, member); \ + &pos->member != (head); \ + pos = __container_of(pos->member.next, pos, member)) + +#define list_for_each_entry_continue_reverse(pos, head, member) \ + for (pos = __container_of(pos->member.prev, pos, member); \ + &pos->member != (head); \ + pos = __container_of(pos->member.prev, pos, member)) + +#define list_for_each_entry_from(pos, head, member) \ + for (; \ + &pos->member != (head); \ + pos = __container_of(pos->member.next, pos, member)) + +#endif diff --git a/include/lib_camera/camera_manager.h b/include/lib_camera/camera_manager.h index 4ff87ff..418b8e9 100644 --- a/include/lib_camera/camera_manager.h +++ b/include/lib_camera/camera_manager.h @@ -102,7 +102,7 @@ int camera_destory_session(cams_t **session); int camera_query_list(cams_t *session); int camera_get_caps(cams_t *session); -int camera_open(cams_t *session, int cam_id); +int camera_open(cams_t *session, const char *dev_name); int camera_close(cams_t *session); int camera_get_modes(cams_t *session); diff --git a/src/lib_camera/camera_manager.c b/src/lib_camera/camera_manager.c index 68879c7..16f7b8b 100644 --- a/src/lib_camera/camera_manager.c +++ b/src/lib_camera/camera_manager.c @@ -48,7 +48,6 @@ static int _camera_session_reset(cams_t *session) memset(session, 0, sizeof(*session)); session->state = CAMERA_STATE_CLOSED; - session->camera_id = -1; session->camera_handle = NULL; session->event_handle = NULL; @@ -133,26 +132,24 @@ int camera_get_caps(cams_t *session) return 0; } -int camera_open(cams_t *session, int cam_id) +int camera_open(cams_t *session, const char *dev_name) { _CHECK_SESSION_RETURN(); int ret; + csi_camera_info_s camera_info; + csi_cam_handle_t handle; - if (!_get_info_status(session, CAMERA_INFOS_READY) || - session->camera_infos.count <= cam_id) { - LOG_E("Can't open cam_id=%d\n", cam_id); + if (!_get_info_status(session, CAMERA_INFOS_READY)) { + LOG_E("Can't open %s\n", dev_name); return -1; } - char *dev_name = session->camera_infos.info[cam_id].device_name; - csi_cam_handle_t handle; ret = csi_camera_open(&handle, dev_name); if (ret != 0) { LOG_E("Open camera(%s) failed\n", dev_name); return -1; } - session->camera_id = cam_id; session->camera_handle = handle; session->state = CAMERA_STATE_OPENED; @@ -170,8 +167,6 @@ int camera_open(cams_t *session, int cam_id) event_action = &(session->camera_event_action[i]); event_action->target = MANAGE_TARGET_CAMERA; - event_action->camera_id = cam_id; - event_action->channel_id = -1; event_action->camera.event = 1 << i; //LOG_W("i=%d, event_action->camera.event=0x%08x\n", i, event_action->camera.event); event_action->camera.supported = false; @@ -196,8 +191,6 @@ int camera_open(cams_t *session, int cam_id) event_action = &(session->channel_event_action[chn][i]); event_action->target = MANAGE_TARGET_CHANNEL; - event_action->camera_id = cam_id; - event_action->channel_id = chn; event_action->channel.event = 1 << i; event_action->channel.supported = false; event_action->channel.subscribed = false; @@ -323,8 +316,8 @@ int camera_channel_query_list(cams_t *session) } ret = csi_camera_channel_query(session->camera_handle, &session->chn_cfg[i]); if (ret != 0) { - LOG_E("Get %d channel configuration from camera[%d] failed\n", - i, session->camera_id); + LOG_E("Get %d channel configuration from camera[%s] failed\n", + i, session->camera_infos.info->device_name); continue; } else { //LOG_D("channel[%d] status=%s\n", session->chn_cfg[i].chn_id, @@ -436,7 +429,7 @@ int camera_subscribe_event(cams_t *session) for (int chn = 0; chn < CSI_CAMERA_CHANNEL_MAX_COUNT; chn++) { if (session->chn_cfg[chn].status != CSI_CAMERA_CHANNEL_OPENED) { - LOG_D("Camera[%d]:Channel[%d] is not OPENED\n", session->camera_id, chn); + LOG_D("Camera[%s]:Channel[%d] is not OPENED\n", session->camera_infos.info->device_name, chn); continue; } for (int i = 0; i < CSI_CAMERA_CHANNEL_EVENT_MAX_COUNT; i++) {