Browse Source

Linux_SDK_V1.0.2

thead_admin 1 year ago
parent
commit
c9c8f34f4e

+ 11 - 0
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 $@) $<

+ 10 - 2
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

+ 1561 - 0
examples/camera/cam_demo_dual_ir.c

@@ -0,0 +1,1561 @@
+/*
+ * Copyright (C) 2021 Alibaba Group Holding Limited
+ * Author: ShenWuYi <shenwuyi.swy@alibaba-inc.com>
+ *
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+#define LOG_LEVEL 5
+#define LOG_PREFIX "cam_demo_dual_ir"
+#include <syslog.h>
+
+#include <csi_frame.h>
+#include <csi_camera.h>
+#include <csi_camera_dev_api.h>
+#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,&params_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,&params_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(
+		&timestap, 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_ch<cam_ctx->channel_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_ch<cam_ctx->channel_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_ch<params->channel_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_ch<cam_ctx->channel_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_ch<cam_ctx->channel_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_ch<ctx->channel_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(&params[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;i<cam_num;i++)
+    {
+        if(ctx[i])
+            camera_close(ctx[i]);
+    }
+    dsp_process_destroy(dsp_hdl);
+    cam_sync_destroy(cam_sync_hdl);
+    exit(0);
+}
+
+static void dump_camera_meta(csi_frame_s *frame)
+{
+	int i;
+	//printf("%s\n", __func__);
+	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_I("meta_id=%d, meta_type=%d, meta_value=%d\n",
+			meta_unit.id, meta_unit.type, meta_unit.int_value);
+}
+
+

+ 41 - 15
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);
 }
 

+ 26 - 11
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;

+ 0 - 5
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);

+ 1 - 1
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",

+ 110 - 45
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;i<count;i++)
+                    {
+                        hdr = (PlinkMsg *)(pkt.list[i]);
+                        resp_id = hdr->msg;
+                        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, &params);
+        if (VMEM_allocate(vmem, &params) != 0) {
+			return -1;
+		}
         VMEM_mmap(vmem, &params);
         VMEM_export(vmem, &params);
         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__);

+ 353 - 0
examples/camera/list.h

@@ -0,0 +1,353 @@
+/*
+ * Copyright © 2010 Intel Corporation
+ * Copyright © 2010 Francisco Jerez <currojerez@riseup.net>
+ *
+ * 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 <bskeggs@redhat.com> 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

+ 1 - 1
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);

+ 8 - 15
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++) {