|
@@ -1,6 +1,6 @@
|
|
|
/*
|
|
|
- * Copyright (C) 2021 Alibaba Group Holding Limited
|
|
|
- * Author: LuChongzhi <chongzhi.lcz@alibaba-inc.com>
|
|
|
+ * Copyright (C) 2021-2022 Alibaba Group Holding Limited
|
|
|
+ * Author: LuChongzhi <chongzhi.lcz@alibaba-inc.com>; Minxiong Tian <minxiong.tmx@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
|
|
@@ -10,27 +10,139 @@
|
|
|
#include <stdio.h>
|
|
|
#include <stdlib.h>
|
|
|
#include <string.h>
|
|
|
+#include <pthread.h>
|
|
|
+#include <unistd.h>
|
|
|
+#include <error.h>
|
|
|
+#include <errno.h>
|
|
|
+
|
|
|
+#include <sys/mman.h>
|
|
|
+#include <sys/ipc.h>
|
|
|
+#include <sys/shm.h>
|
|
|
+#include <sys/sem.h>
|
|
|
+
|
|
|
+#include "csi_camera_dev_api.h"
|
|
|
+
|
|
|
+/* macros for share memory and semaphore */
|
|
|
+#define SHMKEY (key_t)0x39126
|
|
|
+#define SEMKEY (key_t)0x49126
|
|
|
+#define IFLAGS (IPC_CREAT|IPC_EXCL)
|
|
|
|
|
|
#define LOG_LEVEL 2
|
|
|
#define LOG_PREFIX "camera_demo1"
|
|
|
#include <syslog.h>
|
|
|
|
|
|
-#include <csi_frame.h>
|
|
|
+#include <csi_frame_ex.h>
|
|
|
#include <csi_camera.h>
|
|
|
|
|
|
#ifdef PLATFORM_SIMULATOR
|
|
|
#include "apputilities.h"
|
|
|
#endif
|
|
|
|
|
|
-static void dump_camera_meta(csi_frame_s *frame);
|
|
|
-static int save_camera_img(csi_frame_s *frame);
|
|
|
-static int save_camera_stream(csi_frame_s *frame);
|
|
|
+#define PAGE_SIZE 1024
|
|
|
+#define PAGE_ALIGN(addr) (void *)(((int)(addr)+PAGE_SIZE-1)&~( PAGE_SIZE-1))
|
|
|
+
|
|
|
+/* data store in share-memory */
|
|
|
+struct databuf {
|
|
|
+ int d_buf[2];
|
|
|
+};
|
|
|
+
|
|
|
+static void dump_camera_meta(csi_frame_ex_s *frame, int idx);
|
|
|
+static void* save_camera_img(void *);
|
|
|
+static void* save_camera_stream(void *);
|
|
|
+static int set_properties(csi_cam_handle_t cam_handle, char *pArgs);
|
|
|
+static enum csi_pixel_fmt parse_format(char *fmt);
|
|
|
+// static void handle_dma_buf(csi_frame_s *framei, int cid);
|
|
|
+//extern int csi_camera_frame_unlock(csi_cam_handle_t cam_handle, csi_frame_s *frame);
|
|
|
+extern int csi_camera_put_frame(csi_frame_ex_s *frame);
|
|
|
+static void i_save(csi_frame_ex_s *framei, int cid, FILE *fp, int vmode);
|
|
|
+static void parse_fmt_res(int cindx);
|
|
|
+static void getseg(struct databuf* *pdata);
|
|
|
+static int getsem();
|
|
|
+static void remove_s();
|
|
|
+static void writer(struct databuf *buf, int index, int value);
|
|
|
+static void reader(struct databuf *buf, int index, int * rv);
|
|
|
+static int pr_error(char *mess);
|
|
|
+extern int csi_camera_set_pp_path_param(csi_cam_handle_t cam_handle, uint16_t line_num,uint16_t buf_mode);
|
|
|
+
|
|
|
+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_ex_s *frame);
|
|
|
|
|
|
#define TEST_DEVICE_NAME "/dev/video0"
|
|
|
#define CSI_CAMERA_TRUE 1
|
|
|
#define CSI_CAMERA_FALSE 0
|
|
|
+#define chnMAX 8
|
|
|
+#define fmtMAX 19
|
|
|
+
|
|
|
+csi_cam_handle_t cam_handle;
|
|
|
+char *prog_name;
|
|
|
+int Soff = 0;
|
|
|
+static char device[CSI_CAMERA_NAME_MAX_LEN]; /* target video device like /dev/video0 */
|
|
|
+static char path[128] = "./"; /* output path */
|
|
|
+static int channelIdx[chnMAX]; /* channel information like 8 */
|
|
|
+enum csi_pixel_fmt fenum[chnMAX];
|
|
|
+int fid[chnMAX] = {0};
|
|
|
+int tframes = 4;
|
|
|
+csi_camera_channel_id_e CAMERA_CHANNEL_ID[chnMAX];
|
|
|
+
|
|
|
+/* File local Global array to store information which will be used when storig images */
|
|
|
+static int PLANE[chnMAX] = {0};
|
|
|
+static int PBIT[chnMAX] = {0};
|
|
|
+static int PLNS[chnMAX][3] = {0};
|
|
|
+static int LNN[chnMAX][3] = {0};
|
|
|
+static int LSZ[chnMAX][3] = {0};
|
|
|
+static int LNNV[chnMAX][3] = {0}; /* for rotation 90/270 */
|
|
|
+static int LSZV[chnMAX][3] = {0}; /* for rotation 90/270 */
|
|
|
+static int NOSTRD[chnMAX] = {0};
|
|
|
+
|
|
|
+/* local global array for meta data verify */
|
|
|
+static int cur_metaint[chnMAX] = {-1, -1, -1, -1};
|
|
|
+static int pre_metaint[chnMAX] = {-1, -1, -1, -1};
|
|
|
+static int cur_metasec[chnMAX] = {-1, -1, -1, -1};
|
|
|
+static int pre_metasec[chnMAX] = {-1, -1, -1, -1};
|
|
|
+static int cur_metausec[chnMAX] = {-1, -1, -1, -1};
|
|
|
+static int pre_metausec[chnMAX] = {-1, -1, -1, -1};
|
|
|
+
|
|
|
+static int shmid, semid;
|
|
|
+struct sembuf p1 = {0, -1, 0}, v1 = {0, 1, 0};
|
|
|
|
|
|
-char *prog_name;
|
|
|
+int meta_mode = -1;
|
|
|
+int flashMode = 0;
|
|
|
+int fNumInc[chnMAX] = {0};
|
|
|
+int fCount = 1;
|
|
|
+int onoffMode = 0;
|
|
|
+int afterOnOff[chnMAX];
|
|
|
+int onoffDrop = 4;
|
|
|
+int onoffFrame = 0;
|
|
|
+int ooNum[chnMAX] = {0};
|
|
|
+int ofTop = 30;
|
|
|
+csi_frame_ex_s frame[chnMAX];
|
|
|
+pthread_t tid[chnMAX]={0};
|
|
|
+int hres[chnMAX], vres[chnMAX]; /* resolution information like 640x480 */
|
|
|
+int idxArray[chnMAX][10]={0};
|
|
|
+static char *dname;
|
|
|
+static int chNum = 0;
|
|
|
+char fmtArray[fmtMAX][50] = {
|
|
|
+ "CSI_PIX_FMT_I420",
|
|
|
+ "CSI_PIX_FMT_NV12",
|
|
|
+ "CSI_PIX_FMT_BGR",
|
|
|
+ "CSI_PIX_FMT_RAW_8BIT",
|
|
|
+ "CSI_PIX_FMT_RAW_10BIT",
|
|
|
+ "CSI_PIX_FMT_RAW_12BIT",
|
|
|
+ "CSI_PIX_FMT_RAW_14BIT",
|
|
|
+ "CSI_PIX_FMT_RAW_16BIT",
|
|
|
+ "CSI_PIX_FMT_RGB_PLANAR_888",
|
|
|
+ "CSI_PIX_FMT_RGB_INTEVLEAVED_888",
|
|
|
+ "CSI_PIX_FMT_YUV_PLANAR_422",
|
|
|
+ "CSI_PIX_FMT_YUV_PLANAR_420",
|
|
|
+ "CSI_PIX_FMT_YUV_PLANAR_444",
|
|
|
+ "CSI_PIX_FMT_YUV_SEMIPLANAR_422",
|
|
|
+ "CSI_PIX_FMT_YUV_SEMIPLANAR_420",
|
|
|
+ "CSI_PIX_FMT_YUV_SEMIPLANAR_444",
|
|
|
+ "CSI_PIX_FMT_YUV_TEVLEAVED_422",
|
|
|
+ "CSI_PIX_FMT_YUV_TEVLEAVED_420",
|
|
|
+ "CSI_PIX_FMT_YUV_TEVLEAVED_444"
|
|
|
+};
|
|
|
|
|
|
void usage()
|
|
|
{
|
|
@@ -38,64 +150,132 @@ void usage()
|
|
|
"usage: %s [options]\n"
|
|
|
"Options:\n"
|
|
|
"\t-D dev target video device like /dev/video0\n"
|
|
|
- "\t-R resolution format is like 640x480\n"
|
|
|
- "\t-F format like NV12\n"
|
|
|
- "\t-C channel_index channel index defined in dts, index from 0\n"
|
|
|
- "\t-M output mode 0: save as image; 1: save as stream file\n"
|
|
|
- "\t-N number for frames 0: record forever; others: the recorded frame numbers"
|
|
|
+ "\t-R resolution format is like 640x480, use 640x480/1092x1080 for multi channel output\n"
|
|
|
+ "\t-F format like NV12, use NV12/NV12 to support multi channel output\n"
|
|
|
+ "\t-C channel_index channel index defined in dts, index from 0, use 0/2 for multi channel output\n"
|
|
|
+ "\t-M test mode 0: save as image; 1: save as stream file; 2: output to plink; 3. performace test\n"
|
|
|
+ "\t-N number for frames 0: record forever; others: the recorded frame numbers, use 30/30 from multi channel output\n"
|
|
|
+ "\t-n number of frames to save if not given, 4 is used\n"
|
|
|
+ "\t-P Property id:type:value, use id:type:value/id:type:value for multi property setting\n"
|
|
|
+ "\t-p output path store output file in the give path\n"
|
|
|
+ "\t-S turn off stride mode if given, turn off stride mode\n"
|
|
|
+ "\t-t stream turn on/off test if will turn off stream after several streams then turn on\n"
|
|
|
+ "\t-s turn off sram mode if given, turn off sram mode between ISP/DSP and DSP/ISP-RY\n"
|
|
|
+ "\t-m disable DW DMA-BUF if given, turn off dma-buf mode\n"
|
|
|
+ "\t-f enable LED flash mode if given, enable LED flash mode for odd and even frame feature in lightA production board\n"
|
|
|
+ "\t-i nubmer of process which needs to do IPC, use for multi-video and mutli-process test scenarios\n"
|
|
|
+ "\t-y meta-data test 0 - meta dump all all elements; 1 - meta verify for CAMERA_NAME;\n"
|
|
|
+ " 2 - meta verify for CHANNEL_ID; 3 - meta verify for FRAME_ID;\n"
|
|
|
+ " 4 - meta verify for TIMESTAMP.\n"
|
|
|
+ " 200 - meta verify for all elements\n"
|
|
|
, prog_name
|
|
|
);
|
|
|
}
|
|
|
|
|
|
int main(int argc, char *argv[])
|
|
|
{
|
|
|
- bool running = false;
|
|
|
+ bool running = 0;
|
|
|
csi_camera_info_s camera_info;
|
|
|
|
|
|
int opt;
|
|
|
- char device[CSI_CAMERA_NAME_MAX_LEN]; /* target video device like /dev/video0 */
|
|
|
- char *resolution; /* resolution information like 640x480 */
|
|
|
- int hres, vres; /* resolution information like 640x480 */
|
|
|
- char *resDelim = "xX";
|
|
|
- char *format; /* format information like NV12 */
|
|
|
- enum csi_pixel_fmt fenum;
|
|
|
- int channelIdx; /* channel information like 8 */
|
|
|
+ char *resDelim = "xX/";
|
|
|
int outMode = 0;
|
|
|
- int fNum = 0;
|
|
|
+ int fNum[chnMAX] = {0};
|
|
|
+ char pArgs[500] = {'\0'}; /* store property args */
|
|
|
+ char *devDelim = "/";
|
|
|
+ char *sCur;
|
|
|
+ int idx = 0;
|
|
|
+ int ret = 0;
|
|
|
+ csi_camera_event_type_e CAMERA_CHANNEL_EVENT_TYPE[chnMAX];
|
|
|
+ struct timeval init_time, cur_time;
|
|
|
+ memset(&init_time, 0, sizeof(init_time));
|
|
|
+ memset(&cur_time, 0, sizeof(cur_time));
|
|
|
+ unsigned long video_open = 0;
|
|
|
+ unsigned long channel_open = 0;
|
|
|
+ unsigned long channel_start = 0;
|
|
|
+ unsigned long first_frame = 0;
|
|
|
+ unsigned long total_frame = 0;
|
|
|
+ float fps = 0.0;
|
|
|
+ int sramMode = 1;
|
|
|
+
|
|
|
+ /* data for share-memory */
|
|
|
+ struct databuf *buf;
|
|
|
+ int mi = 0;
|
|
|
+ int srv1 = 0, srv2 = 0;
|
|
|
|
|
|
prog_name = argv[0];
|
|
|
|
|
|
- while ((opt = getopt(argc, argv, "D:R:F:C:M:hN:")) != EOF) {
|
|
|
+ while ((opt = getopt(argc, argv, "t:D:R:F:C:M:hN:P:p:Smi:y:fsn:")) != EOF) {
|
|
|
switch(opt) {
|
|
|
case 'D':
|
|
|
- //device = optarg;
|
|
|
strcpy(device, optarg);
|
|
|
+ strtok(optarg, devDelim);
|
|
|
+ dname=strtok(NULL, devDelim);
|
|
|
+ continue;
|
|
|
+ case 'p':
|
|
|
+ strcpy(path, optarg);
|
|
|
+ continue;
|
|
|
+ case 'S':
|
|
|
+ Soff = 1;
|
|
|
+ continue;
|
|
|
+ case 't':
|
|
|
+ onoffMode = 1;
|
|
|
+ onoffFrame = atoi(optarg);
|
|
|
+ continue;
|
|
|
+ case 's':
|
|
|
+ sramMode = 0;
|
|
|
+ case 'f':
|
|
|
+ flashMode = 1;
|
|
|
+ continue;
|
|
|
+ case 'P':
|
|
|
+ strcpy(pArgs, optarg);
|
|
|
continue;
|
|
|
case 'R':
|
|
|
- resolution = optarg;
|
|
|
- hres = atoi(strtok(resolution, resDelim));
|
|
|
- vres = atoi(strtok(NULL, resDelim));
|
|
|
+ idx = 0;
|
|
|
+ sCur=strtok(optarg, resDelim);
|
|
|
+ while (sCur != NULL){
|
|
|
+ if (idx % 2 == 0)
|
|
|
+ hres[idx/2] = atoi(sCur);
|
|
|
+ if (idx % 2 == 1)
|
|
|
+ vres[idx/2] = atoi(sCur);
|
|
|
+ sCur=strtok(NULL, resDelim);
|
|
|
+ idx++;
|
|
|
+ }
|
|
|
continue;
|
|
|
case 'M':
|
|
|
outMode = atoi(optarg);
|
|
|
continue;
|
|
|
+ case 'i':
|
|
|
+ mi = atoi(optarg);
|
|
|
+ continue;
|
|
|
+ case 'y':
|
|
|
+ meta_mode = atoi(optarg);
|
|
|
+ continue;
|
|
|
case 'N':
|
|
|
- fNum = atoi(optarg);
|
|
|
+ for(int j=0; j<chnMAX; j++)
|
|
|
+ fNum[j] = atoi(optarg);
|
|
|
+ continue;
|
|
|
+ case 'n':
|
|
|
+ tframes = atoi(optarg);
|
|
|
continue;
|
|
|
case 'F':
|
|
|
- format = optarg;
|
|
|
- if(strstr(format, "NV12")){
|
|
|
- fenum = CSI_PIX_FMT_NV12;
|
|
|
- }
|
|
|
- else if(strstr(format, "I420")){
|
|
|
- fenum = CSI_PIX_FMT_I420;
|
|
|
- }
|
|
|
- else{
|
|
|
- fenum = CSI_PIX_FMT_I420;
|
|
|
- }
|
|
|
+ idx = 0;
|
|
|
+ sCur=strtok(optarg, devDelim);
|
|
|
+ while (sCur != NULL){
|
|
|
+ fenum[idx] = parse_format(sCur);
|
|
|
+ sCur=strtok(NULL, devDelim);
|
|
|
+ idx++;
|
|
|
+ }
|
|
|
continue;
|
|
|
case 'C':
|
|
|
- channelIdx = atoi(optarg);
|
|
|
+ idx = 0;
|
|
|
+ sCur=strtok(optarg, devDelim);
|
|
|
+ while (sCur != NULL){
|
|
|
+ channelIdx[idx] = atoi(sCur);
|
|
|
+ sCur=strtok(NULL, devDelim);
|
|
|
+ idx++;
|
|
|
+ }
|
|
|
+ chNum = idx;
|
|
|
continue;
|
|
|
case '?':
|
|
|
case 'h':
|
|
@@ -105,11 +285,23 @@ int main(int argc, char *argv[])
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- const csi_camera_channel_id_e CAMERA_CHANNEL_ID = CSI_CAMERA_CHANNEL_0 + channelIdx;
|
|
|
- const csi_camera_event_type_e CAMERA_CHANNEL_EVENT_TYPE = CSI_CAMERA_EVENT_TYPE_CHANNEL0 + channelIdx;
|
|
|
- if (fNum == 0)
|
|
|
- running == true;
|
|
|
+ /* get semaphore ID and share-memory ID if mi >=2 */
|
|
|
+ if(mi >= 2){
|
|
|
+ semid = getsem();
|
|
|
+ getseg(&buf);
|
|
|
+ printf("------IPC mode enable - finish-------\n");
|
|
|
+ }
|
|
|
|
|
|
+ /* init the target channel ID and channel event type array */
|
|
|
+ for (int j=0; j<chNum; j++){
|
|
|
+ CAMERA_CHANNEL_ID[j] = CSI_CAMERA_CHANNEL_0 + channelIdx[j];
|
|
|
+ CAMERA_CHANNEL_EVENT_TYPE[j] = CSI_CAMERA_EVENT_TYPE_CHANNEL0 + channelIdx[j];
|
|
|
+ }
|
|
|
+
|
|
|
+ if (fNum[0] == 0){
|
|
|
+ running = 1;
|
|
|
+ printf("------running = 1-------\n");
|
|
|
+ }
|
|
|
|
|
|
// 打印HAL接口版本号
|
|
|
csi_api_version_u version;
|
|
@@ -150,12 +342,11 @@ int main(int argc, char *argv[])
|
|
|
|
|
|
|
|
|
// 打开Camera设备获取句柄,作为后续操对象
|
|
|
- csi_cam_handle_t cam_handle;
|
|
|
- //csi_camera_open(&cam_handle, camera_info.device_name);
|
|
|
strcpy(camera_info.device_name, device);
|
|
|
- //camera_info.device_name = device;
|
|
|
+ gettimeofday(&init_time, 0);
|
|
|
csi_camera_open(&cam_handle, camera_info.device_name);
|
|
|
- //csi_camera_open(&cam_handle, device);
|
|
|
+ gettimeofday(&cur_time, 0);
|
|
|
+ video_open = 1000000 * (cur_time.tv_sec-init_time.tv_sec)+ cur_time.tv_usec-init_time.tv_usec;
|
|
|
// 获取Camera支持的工作模式
|
|
|
struct csi_camera_modes camera_modes;
|
|
|
csi_camera_get_modes(cam_handle, &camera_modes);
|
|
@@ -169,6 +360,7 @@ int main(int argc, char *argv[])
|
|
|
}
|
|
|
printf("}\n");
|
|
|
|
|
|
+
|
|
|
// 设置camera的工作模式及其配置
|
|
|
csi_camera_mode_cfg_s camera_cfg;
|
|
|
camera_cfg.mode_id = 1;
|
|
@@ -178,17 +370,9 @@ int main(int argc, char *argv[])
|
|
|
|
|
|
// 获取单个可控单元的属性
|
|
|
csi_camera_property_description_s description;
|
|
|
- /* id=0x0098090x, type=2 default=0 value=1 */
|
|
|
- /* Other example:
|
|
|
- * id=0x0098090y, type=3 min=0 max=255 step=1 default=127 value=116
|
|
|
- * id=0x0098090z, type=4 min=0 max=3 default=0 value=2
|
|
|
- * 0: IDLE
|
|
|
- * 1: BUSY
|
|
|
- * 2: REACHED
|
|
|
- * 3: FAILED
|
|
|
- */
|
|
|
|
|
|
// 轮询获取所有可控制的单元
|
|
|
+
|
|
|
printf("all properties are:\n");
|
|
|
description.id = CSI_CAMERA_PID_HFLIP;
|
|
|
while (!csi_camera_query_property(cam_handle, &description)) {
|
|
@@ -225,167 +409,868 @@ int main(int argc, char *argv[])
|
|
|
description.id |= CSI_CAMERA_FLAG_NEXT_CTRL;
|
|
|
}
|
|
|
|
|
|
- // 同时配置多个参数
|
|
|
- csi_camera_properties_s properties;
|
|
|
- csi_camera_property_s property[3];
|
|
|
- property[0].id = CSI_CAMERA_PID_HFLIP;
|
|
|
- property[0].type = CSI_CAMERA_PROPERTY_TYPE_BOOLEAN;
|
|
|
- property[0].value.bool_value = false;
|
|
|
- property[1].id = CSI_CAMERA_PID_VFLIP;
|
|
|
- property[1].type = CSI_CAMERA_PROPERTY_TYPE_BOOLEAN;
|
|
|
- property[1].value.bool_value = false;
|
|
|
- property[2].id = CSI_CAMERA_PID_ROTATE;
|
|
|
- property[2].type = CSI_CAMERA_PROPERTY_TYPE_INTEGER;
|
|
|
- property[2].value.int_value = 0;
|
|
|
- properties.count = 3;
|
|
|
- properties.property = property;
|
|
|
- if (csi_camera_set_property(cam_handle, &properties) < 0) {
|
|
|
- LOG_O("set_property fail!\n");
|
|
|
- }
|
|
|
- LOG_O("set_property ok!\n");
|
|
|
+ if (pArgs[0] != '\0'){
|
|
|
+ set_properties(cam_handle, pArgs);
|
|
|
+ }
|
|
|
|
|
|
// 查询输出channel
|
|
|
- csi_camera_channel_cfg_s chn_cfg;
|
|
|
- chn_cfg.chn_id = CAMERA_CHANNEL_ID;
|
|
|
- csi_camera_channel_query(cam_handle, &chn_cfg);
|
|
|
- if (chn_cfg.status != CSI_CAMERA_CHANNEL_CLOSED) {
|
|
|
- printf("Can't open CSI_CAMERA_CHANNEL_0\n");
|
|
|
- exit(-1);
|
|
|
- }
|
|
|
+ csi_camera_channel_cfg_s chn_cfg[chnMAX];
|
|
|
+ for (int j=0; j<chNum; j++){
|
|
|
+ chn_cfg[j].chn_id = CAMERA_CHANNEL_ID[j];
|
|
|
+ csi_camera_channel_query(cam_handle, &chn_cfg[j]);
|
|
|
+ if (chn_cfg[j].status != CSI_CAMERA_CHANNEL_CLOSED) {
|
|
|
+ printf("Can't open channel: %d\n", CAMERA_CHANNEL_ID[j]);
|
|
|
+ exit(-1);
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
// 打开输出channel
|
|
|
- chn_cfg.chn_id = channelIdx;
|
|
|
- chn_cfg.frm_cnt = 4;
|
|
|
- chn_cfg.img_fmt.width = hres;
|
|
|
- chn_cfg.img_fmt.height = vres;
|
|
|
- chn_cfg.img_fmt.pix_fmt = fenum;
|
|
|
- chn_cfg.img_type = CSI_IMG_TYPE_DMA_BUF;
|
|
|
- chn_cfg.meta_fields = CSI_CAMERA_META_DEFAULT_FIELDS;
|
|
|
- chn_cfg.capture_type = CSI_CAMERA_CHANNEL_CAPTURE_VIDEO |
|
|
|
- CSI_CAMERA_CHANNEL_CAPTURE_META;
|
|
|
- csi_camera_channel_open(cam_handle, &chn_cfg);
|
|
|
-
|
|
|
- // 订阅Event
|
|
|
+ if (sramMode == 1){
|
|
|
+ csi_camera_set_pp_path_param(cam_handle,0,1);
|
|
|
+ }
|
|
|
csi_cam_event_handle_t event_handle;
|
|
|
- csi_camera_create_event(&event_handle, cam_handle);
|
|
|
csi_camera_event_subscription_s subscribe;
|
|
|
- subscribe.type =
|
|
|
- CSI_CAMERA_EVENT_TYPE_CAMERA; // 订阅Camera的ERROR事件
|
|
|
- subscribe.id = CSI_CAMERA_EVENT_WARNING | CSI_CAMERA_EVENT_ERROR;
|
|
|
- csi_camera_subscribe_event(event_handle, &subscribe);
|
|
|
- subscribe.type =
|
|
|
- CAMERA_CHANNEL_EVENT_TYPE; // 订阅Channel0的FRAME_READY事件
|
|
|
- subscribe.id = CSI_CAMERA_CHANNEL_EVENT_FRAME_READY |
|
|
|
- CSI_CAMERA_CHANNEL_EVENT_OVERFLOW;
|
|
|
- csi_camera_subscribe_event(event_handle, &subscribe);
|
|
|
-
|
|
|
- // 开始从channel中取出准备好的frame
|
|
|
- csi_camera_channel_start(cam_handle, CAMERA_CHANNEL_ID);
|
|
|
+ for (int j=0; j<chNum; j++){
|
|
|
+ chn_cfg[j].chn_id = CAMERA_CHANNEL_ID[j];
|
|
|
+ chn_cfg[j].frm_cnt = fCount;
|
|
|
+ chn_cfg[j].img_fmt.width = hres[j];
|
|
|
+ chn_cfg[j].img_fmt.height = vres[j];
|
|
|
+ chn_cfg[j].img_fmt.pix_fmt = fenum[j];
|
|
|
+ chn_cfg[j].img_type = CSI_IMG_TYPE_DMA_BUF;
|
|
|
+ chn_cfg[j].meta_fields = CSI_CAMERA_META_DEFAULT_FIELDS;
|
|
|
+ chn_cfg[j].capture_type = CSI_CAMERA_CHANNEL_CAPTURE_VIDEO |
|
|
|
+ CSI_CAMERA_CHANNEL_CAPTURE_META;
|
|
|
+ parse_fmt_res(j);
|
|
|
+ gettimeofday(&init_time, 0);
|
|
|
+ ret = csi_camera_channel_open(cam_handle, &chn_cfg[j]);
|
|
|
+ if (ret) {
|
|
|
+ exit(-1);
|
|
|
+ }
|
|
|
+ gettimeofday(&cur_time, 0);
|
|
|
+ channel_open = 1000000 * (cur_time.tv_sec-init_time.tv_sec)+ cur_time.tv_usec-init_time.tv_usec;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 订阅Event
|
|
|
+ csi_camera_create_event(&event_handle, cam_handle);
|
|
|
+ for (int j=0; j<chNum; j++){
|
|
|
+ subscribe.type =
|
|
|
+ CSI_CAMERA_EVENT_TYPE_CAMERA; // 订阅Camera的ERROR事件
|
|
|
+ subscribe.id = CSI_CAMERA_EVENT_WARNING | CSI_CAMERA_EVENT_ERROR;
|
|
|
+ csi_camera_subscribe_event(event_handle, &subscribe);
|
|
|
+ subscribe.type =
|
|
|
+ CAMERA_CHANNEL_EVENT_TYPE[j]; // 订阅Channel0的FRAME_READY事件
|
|
|
+ subscribe.id = CSI_CAMERA_CHANNEL_EVENT_FRAME_READY |
|
|
|
+ CSI_CAMERA_CHANNEL_EVENT_OVERFLOW;
|
|
|
+ csi_camera_subscribe_event(event_handle, &subscribe);
|
|
|
+ }
|
|
|
+
|
|
|
+ if ( flashMode == 1){
|
|
|
+ csi_camera_floodlight_led_set_flash_bright(cam_handle, 500); //500ma
|
|
|
+ csi_camera_projection_led_set_flash_bright(cam_handle, 500); //500ma
|
|
|
+ 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);
|
|
|
+ }
|
|
|
+ // start all channels
|
|
|
+ for (int j=0; j<chNum; j++){
|
|
|
+ gettimeofday(&init_time, 0);
|
|
|
+ csi_camera_channel_start(cam_handle, CAMERA_CHANNEL_ID[j]);
|
|
|
+ gettimeofday(&cur_time, 0);
|
|
|
+ channel_start = 1000000 * (cur_time.tv_sec-init_time.tv_sec)+ cur_time.tv_usec-init_time.tv_usec;
|
|
|
+ }
|
|
|
+ gettimeofday(&init_time, 0);
|
|
|
|
|
|
// 处理订阅的Event
|
|
|
- csi_frame_s frame;
|
|
|
struct csi_camera_event event;
|
|
|
+ int fnumTotal = fNum[0] * chNum;
|
|
|
+ int frameTotal = fnumTotal;
|
|
|
|
|
|
- while (running || fNum >= 0 ) {
|
|
|
+ while (running || fnumTotal > 0 ) {
|
|
|
int timeout = -1; // unit: ms, -1 means wait forever, or until error occurs
|
|
|
csi_camera_get_event(event_handle, &event, timeout);
|
|
|
+ printf("%s event.type = %d, event.id = %d\n", __func__, event.type, event.id);
|
|
|
if(event.type == CSI_CAMERA_EVENT_TYPE_CAMERA){
|
|
|
switch (event.id) {
|
|
|
case CSI_CAMERA_EVENT_ERROR:
|
|
|
// do sth.
|
|
|
- LOG_D("get CAMERA EVENT CSI_CAMERA_EVENT_ERROR!\n");
|
|
|
+ printf("-------get CAMERA EVENT CSI_CAMERA_EVENT_ERROR!----------\n");
|
|
|
break;
|
|
|
+ case CSI_CAMERA_EVENT_WARNING:
|
|
|
+ printf("-------get CAMERA EVENT CSI_CAMERA_EVENT_WRN,RC: %s-------\n",event.bin);
|
|
|
+ break;
|
|
|
default:
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
- if(event.type == CAMERA_CHANNEL_EVENT_TYPE){
|
|
|
- switch (event.id) {
|
|
|
- case CSI_CAMERA_CHANNEL_EVENT_FRAME_READY: {
|
|
|
- int read_frame_count = csi_camera_get_frame_count(cam_handle,
|
|
|
- CAMERA_CHANNEL_ID);
|
|
|
- for (int i = 0; i < read_frame_count; i++) {
|
|
|
- csi_camera_get_frame(cam_handle, CAMERA_CHANNEL_ID, &frame, timeout);
|
|
|
- fNum--;
|
|
|
+ for (int j=0; j<chNum; j++){
|
|
|
+ if(event.type == CAMERA_CHANNEL_EVENT_TYPE[j]){
|
|
|
+ switch (event.id) {
|
|
|
+ case CSI_CAMERA_CHANNEL_EVENT_OVERFLOW:
|
|
|
+ printf("-------get channel EVENT CSI_CAMERA_CHANNEL_EVENT_OVERFLOW-------\n");
|
|
|
+ break;
|
|
|
+ case CSI_CAMERA_CHANNEL_EVENT_FRAME_READY: {
|
|
|
+ int read_frame_count = csi_camera_get_frame_count(cam_handle,
|
|
|
+ CAMERA_CHANNEL_ID[j]);
|
|
|
+ printf("-------read_frame_count=%d-------\n", read_frame_count);
|
|
|
+ for (int i = 0; i < fCount; i++) {
|
|
|
+ if (tid[j] != 0){
|
|
|
+ /* wait for previous image save thread end */
|
|
|
+ pthread_join(tid[j], NULL);
|
|
|
+ }
|
|
|
+ csi_camera_get_frame(cam_handle, CAMERA_CHANNEL_ID[j], &frame[j], timeout);
|
|
|
+ if (afterOnOff[j] != 0 ){
|
|
|
+ /* drop the first event after on/off operation */
|
|
|
+ afterOnOff[j]--;
|
|
|
+ csi_camera_put_frame(&frame[j]);
|
|
|
+ // csi_frame_release(&frame[j]);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ fNum[j]--;
|
|
|
+ fNumInc[j]++;
|
|
|
+ if (fNum[j] < 0 && running == 0 ){
|
|
|
+ //csi_camera_frame_unlock(cam_handle, &frame[j]);
|
|
|
+ csi_camera_put_frame(&frame[j]);
|
|
|
+ // csi_frame_release(&frame[j]);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
|
|
|
-#ifdef PLATFORM_SIMULATOR
|
|
|
- show_frame_image(frame.img.usr_addr[0], frame.img.height, frame.img.width);
|
|
|
-#endif
|
|
|
-
|
|
|
- if (outMode == 0)
|
|
|
- save_camera_img(&frame);
|
|
|
- else
|
|
|
- save_camera_stream(&frame);
|
|
|
-
|
|
|
- csi_frame_release(&frame);
|
|
|
- }
|
|
|
- break;
|
|
|
- }
|
|
|
- default:
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- csi_camera_channel_stop(cam_handle, CAMERA_CHANNEL_ID);
|
|
|
+ #ifdef PLATFORM_SIMULATOR
|
|
|
+ show_frame_image(frame[j].img.usr_addr[0], frame[j].img.height, frame.img.width);
|
|
|
+ #endif
|
|
|
+ fid[j]++;
|
|
|
+ fnumTotal--;
|
|
|
+ if (outMode == 0){
|
|
|
+ int * tIdx = malloc(sizeof(int));
|
|
|
+ *tIdx = j;
|
|
|
+ /* submit thread to save image for current channel then we can go to handle other channel */
|
|
|
+ pthread_create(&tid[j], NULL, save_camera_img, (void *)tIdx);
|
|
|
+ }
|
|
|
+ else if (outMode == 1){
|
|
|
+ int * tIdx = malloc(sizeof(int));
|
|
|
+ *tIdx = j;
|
|
|
+ pthread_create(&tid[j], NULL, save_camera_stream, (void *)tIdx);
|
|
|
+ }
|
|
|
+ else if(outMode == 3){
|
|
|
+ /* mode 3 only do performance test, no actual image saving */
|
|
|
+ gettimeofday(&cur_time, 0);
|
|
|
+ if (fid[j] == 1){
|
|
|
+ /* first frame */
|
|
|
+ first_frame = 1000000 * (cur_time.tv_sec-init_time.tv_sec)+ cur_time.tv_usec-init_time.tv_usec + video_open + channel_open + channel_start;
|
|
|
+ }
|
|
|
+ if (fnumTotal == 0){
|
|
|
+ /* last frame */
|
|
|
+ total_frame = 1000000 * (cur_time.tv_sec-init_time.tv_sec)+ cur_time.tv_usec-init_time.tv_usec;
|
|
|
+ fps = (float)frameTotal / total_frame * 1000000.0f;
|
|
|
+ printf("\n");
|
|
|
+ printf("\n");
|
|
|
+ printf("Performance data:\n");
|
|
|
+ printf("video_open:%lu ms\n", video_open/1000);
|
|
|
+ printf("channel_open:%lu ms\n", channel_open/1000);
|
|
|
+ printf("channel_start:%lu ms\n", channel_start/1000);
|
|
|
+ printf("first_frame:%lu ms\n", first_frame/1000);
|
|
|
+ printf("fps:%f fps\n", fps);
|
|
|
+ printf("\n");
|
|
|
+ printf("\n");
|
|
|
+ }
|
|
|
+ /* for mode 3, unlock in this branch, for mode 0,1 unlock in thread */
|
|
|
+ //csi_camera_frame_unlock(cam_handle, &frame[j]);
|
|
|
+ csi_camera_put_frame(&frame[j]);
|
|
|
+
|
|
|
+ }
|
|
|
+ else{
|
|
|
+ chn_cfg[j].chn_id = j;
|
|
|
+ csi_camera_channel_query(cam_handle, &chn_cfg[j]);
|
|
|
+ // display_camera_frame(cam_handle, &chn_cfg[j], &frame[j]);
|
|
|
+ //csi_camera_frame_unlock(cam_handle, &frame[j]);
|
|
|
+ csi_camera_put_frame(&frame[j]);
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ default:
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ /* for IPC, update finish status to share-memory */
|
|
|
+ if(mi >= 2){
|
|
|
+ writer(buf, 0, 1);
|
|
|
+ }
|
|
|
+ for (int j=0; j<chNum; j++){
|
|
|
+ /* for IPC only do stop when share memory value equals mi */
|
|
|
+ if(mi >= 2){
|
|
|
+ while (1){
|
|
|
+ reader(buf, 0, &srv1);
|
|
|
+ if (srv1 != mi){
|
|
|
+ sleep(2);
|
|
|
+ }
|
|
|
+ else{
|
|
|
+ /* update the second value in share-memory which is used to decide whether to remove share-memory */
|
|
|
+ writer(buf, 1, 1);
|
|
|
+ reader(buf, 1, &srv2);
|
|
|
+ if (srv2 == mi){
|
|
|
+ /* I am the last process to update the buf[1], remove the share-memory */
|
|
|
+ remove_s();
|
|
|
+ printf("------IPC mode: remove-------\n");
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ csi_camera_channel_stop(cam_handle, CAMERA_CHANNEL_ID[j]);
|
|
|
+ }
|
|
|
+ if ( flashMode == 1){
|
|
|
+ csi_camera_led_disable(cam_handle, LED_FLOODLIGHT_PROJECTION);
|
|
|
+ }
|
|
|
usleep (1000000);
|
|
|
// 取消订阅某一个event, 也可以直接调用csi_camera_destory_event,结束所有的订阅
|
|
|
- subscribe.type = CAMERA_CHANNEL_EVENT_TYPE;
|
|
|
- subscribe.id = CSI_CAMERA_CHANNEL_EVENT_FRAME_READY;
|
|
|
- csi_camera_unsubscribe_event(event_handle, &subscribe);
|
|
|
+ for (int j=0; j<chNum; j++){
|
|
|
+ subscribe.type = CAMERA_CHANNEL_EVENT_TYPE[j];
|
|
|
+ subscribe.id = CSI_CAMERA_CHANNEL_EVENT_FRAME_READY;
|
|
|
+ csi_camera_unsubscribe_event(event_handle, &subscribe);
|
|
|
+ }
|
|
|
|
|
|
csi_camera_destory_event(event_handle);
|
|
|
|
|
|
- csi_camera_channel_close(cam_handle, CAMERA_CHANNEL_ID);
|
|
|
+ for (int j=0; j<chNum; j++){
|
|
|
+ csi_camera_channel_close(cam_handle, CAMERA_CHANNEL_ID[j]);
|
|
|
+ }
|
|
|
csi_camera_close(cam_handle);
|
|
|
}
|
|
|
|
|
|
-static void dump_camera_meta(csi_frame_s *frame)
|
|
|
+int pr_error(char *mess){
|
|
|
+ perror(mess);
|
|
|
+ exit(1);
|
|
|
+}
|
|
|
+
|
|
|
+/* function: get or create share-memory*/
|
|
|
+void getseg(struct databuf* *pdata){
|
|
|
+ /* try to get share-memory */
|
|
|
+ if((shmid = shmget(SHMKEY, sizeof(struct databuf), 0600 | IFLAGS)) < 0){
|
|
|
+ if(errno == EEXIST){
|
|
|
+ /* exist, return its ID */
|
|
|
+ shmid = shmget(SHMKEY, sizeof(struct databuf), 0600 | IPC_CREAT);
|
|
|
+ if(shmid < 0){
|
|
|
+ pr_error("--------share-memory getting: error!!!!!---------");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ pr_error("--------share-memory getting: other error!!!!!---------");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if((*pdata = (struct databuf *)(shmat(shmid, 0, 0))) < 0 ){
|
|
|
+ /* mapping share-memory */
|
|
|
+ pr_error("--------share-memory mapping error!!!!!---------");
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/* function: get semaphore */
|
|
|
+int getsem(){
|
|
|
+ /* try to get or create semaphore */
|
|
|
+ if((semid = semget(SEMKEY, 1, 0600|IFLAGS)) < 0){
|
|
|
+ if(errno == EEXIST){
|
|
|
+ /* exist, reurn its ID */
|
|
|
+ semid = semget(SEMKEY, 1, 0600 | IPC_CREAT);
|
|
|
+ if(semid < 0){
|
|
|
+ pr_error("--------semaphore getting ID: error!!!!!---------");
|
|
|
+ }
|
|
|
+ else{
|
|
|
+ /* semaphore already exsit and return ID directly */
|
|
|
+ return semid;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else{
|
|
|
+ pr_error("--------semaphore getting: error!!!!!---------");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ /* do semaphore init to 1 once just after semaphore creating */
|
|
|
+ if(semctl(semid, 0, SETVAL, 1) < 0){
|
|
|
+ pr_error("-----------semctl-----------");
|
|
|
+ }
|
|
|
+ return semid;
|
|
|
+}
|
|
|
+
|
|
|
+/* function remove share-memory and semaphore */
|
|
|
+void remove_s(){
|
|
|
+ if(shmctl(shmid, IPC_RMID, NULL) < 0)
|
|
|
+ pr_error("-----------shmctl when removing-----------");
|
|
|
+ if(semctl(semid, 0, IPC_RMID) < 0)
|
|
|
+ pr_error("-----------semctl when removing-----------");
|
|
|
+}
|
|
|
+
|
|
|
+/* function writer to share-memory */
|
|
|
+void writer(struct databuf *buf, int index, int value){
|
|
|
+ /* get semaphore before update share-memory */
|
|
|
+ semop(semid, &p1, 1);
|
|
|
+ /* update share-memory */
|
|
|
+ buf->d_buf[index] += value;
|
|
|
+ /* release semaphore */
|
|
|
+ semop(semid, &v1, 1);
|
|
|
+}
|
|
|
+
|
|
|
+/* function read to share-memory */
|
|
|
+void reader(struct databuf *buf, int index, int *rv){
|
|
|
+ /* get semaphore before update share-memory */
|
|
|
+ semop(semid, &p1, 1);
|
|
|
+ /* get share-memory value */
|
|
|
+ *rv = buf->d_buf[index];
|
|
|
+ /* release semaphore */
|
|
|
+ semop(semid, &v1, 1);
|
|
|
+}
|
|
|
+
|
|
|
+static void dump_camera_meta(csi_frame_ex_s *frame, int idx)
|
|
|
{
|
|
|
int i;
|
|
|
//printf("%s\n", __func__);
|
|
|
- if (frame->meta.type != CSI_META_TYPE_CAMERA)
|
|
|
+ if (frame->frame_meta.type != CSI_META_TYPE_CAMERA)
|
|
|
return;
|
|
|
|
|
|
- csi_camera_meta_s *meta_data = (csi_camera_meta_s *)frame->meta.data;
|
|
|
+ csi_camera_meta_s *meta_data = (csi_camera_meta_s *)frame->frame_meta.data;
|
|
|
int meta_count = meta_data->count;
|
|
|
- csi_camrea_meta_unit_s meta_unit;
|
|
|
+ csi_camera_meta_unit_s meta_unit;
|
|
|
+ csi_camera_meta_id_e meta_id;
|
|
|
|
|
|
- for (i = 0; i < meta_count; i++) {
|
|
|
- csi_camera_frame_get_meta_unit(
|
|
|
- &meta_unit, meta_data, CSI_CAMERA_META_ID_FRAME_ID);
|
|
|
- //printf("meta_id=%d, meta_type=%d, meta_value=%d",
|
|
|
- // meta_unit.id, meta_unit.type, meta_unit.int_value);
|
|
|
- }
|
|
|
+ if(meta_mode > 0){
|
|
|
+ meta_id = (1<<(meta_mode - 1));
|
|
|
+ csi_camera_frame_get_meta_unit(
|
|
|
+ &meta_unit, meta_data, meta_id);
|
|
|
+ }
|
|
|
+ if(meta_mode == 1 || meta_mode == 2){
|
|
|
+ /* camera_name and channel_id - which should keep same during testing */
|
|
|
+ cur_metaint[idx] = meta_unit.int_value;
|
|
|
+ if(pre_metaint[idx] == -1){
|
|
|
+ pre_metaint[idx] = cur_metaint[idx];
|
|
|
+ }
|
|
|
+ else{
|
|
|
+ if(cur_metaint[idx] != pre_metaint[idx]){
|
|
|
+ pr_error("-----meta test fail: camera_id or channel_id changes during test--------");
|
|
|
+ }
|
|
|
+ pre_metaint[idx] = cur_metaint[idx];
|
|
|
+ printf("-----meta test camera_name or channel_id:%d--------\n", cur_metaint[idx]);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else if(meta_mode == 3){
|
|
|
+ /* frame id - which should increase from 0 */
|
|
|
+ if(cur_metaint[idx] == -1 && meta_unit.int_value != 1){
|
|
|
+ pr_error("-----meta test fail: first frame ID is not 1--------\n");
|
|
|
+ }
|
|
|
+ cur_metaint[idx] = meta_unit.int_value;
|
|
|
+ if(pre_metaint[idx] == -1){
|
|
|
+ pre_metaint[idx] = cur_metaint[idx];
|
|
|
+ }
|
|
|
+ else{
|
|
|
+ if(cur_metaint[idx] != (pre_metaint[idx]+1)){
|
|
|
+ pr_error("-----meta test fail: frame_id is not continuous--------\n");
|
|
|
+ }
|
|
|
+ printf("-----meta test: meta_id: %d, frame_id:%d, previous_id: %d--------\n", meta_unit.id, cur_metaint[idx], pre_metaint[idx]);
|
|
|
+ pre_metaint[idx] = cur_metaint[idx];
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else if(meta_mode == 4){
|
|
|
+ /* timestamps - which should be larger or equal to previous */
|
|
|
+ cur_metasec[idx] = meta_unit.time_value.tv_sec;
|
|
|
+ cur_metausec[idx] = meta_unit.time_value.tv_usec;
|
|
|
+ if(pre_metasec[idx] == -1){
|
|
|
+ pre_metasec[idx] = cur_metasec[idx];
|
|
|
+ pre_metausec[idx] = cur_metausec[idx];
|
|
|
+ }
|
|
|
+ else{
|
|
|
+ if(cur_metasec[idx] <= pre_metasec[idx] && cur_metausec[idx] <= pre_metausec[idx]){
|
|
|
+ pr_error("-----meta test fail: timestamp decrease--------");
|
|
|
+ }
|
|
|
+ printf("-----meta test time - second:%d--------\n", cur_metasec[idx]);
|
|
|
+ printf("-----meta test time - usecond:%d--------\n", cur_metausec[idx]);
|
|
|
+ pre_metasec[idx] = cur_metasec[idx];
|
|
|
+ pre_metausec[idx] = cur_metausec[idx];
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else{
|
|
|
+ /* means meta_mode = 0 */
|
|
|
+ for (i = 0; i < meta_count; i++) {
|
|
|
+ meta_id = (1<<i);
|
|
|
+ csi_camera_frame_get_meta_unit(
|
|
|
+ &meta_unit, meta_data, meta_id);
|
|
|
+ printf("meta_id=%d, meta_type=%d, meta_value=%d\n",
|
|
|
+ meta_unit.id, meta_unit.type, meta_unit.int_value);
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
-static int save_camera_img(csi_frame_s *frame)
|
|
|
+/*
|
|
|
+function: parse the format and resolution to generate the output information used to save img
|
|
|
+Input args: index of channel will be tested whose order is decided when running
|
|
|
+Below information should be included:
|
|
|
+1. how may planars which will be store in global int PLANE[] array
|
|
|
+2. the pix bit which will be store in global int PBIT[] array
|
|
|
+3. the bytes of each plane for the give channel to store in global int PLNS[][3] array
|
|
|
+4. the line numbers of each plane for the give channel to store in global int LNN[][3] array
|
|
|
+5. the bytes to store for each line size in each plane to store in global int LSZ[][3] array
|
|
|
+*/
|
|
|
+static void parse_fmt_res(int cindx){
|
|
|
+ /* fetch the format the resolution information */
|
|
|
+ enum csi_pixel_fmt fmt = fenum[cindx];
|
|
|
+ int iw = hres[cindx];
|
|
|
+ int ih = vres[cindx];
|
|
|
+ /* decide the pixel bit number */
|
|
|
+ switch(fmt) {
|
|
|
+ case CSI_PIX_FMT_RAW_10BIT:
|
|
|
+ PBIT[cindx] = 10;
|
|
|
+ break;
|
|
|
+ case CSI_PIX_FMT_RAW_12BIT:
|
|
|
+ PBIT[cindx] = 12;
|
|
|
+ break;
|
|
|
+ case CSI_PIX_FMT_RAW_14BIT:
|
|
|
+ PBIT[cindx] = 14;
|
|
|
+ break;
|
|
|
+ case CSI_PIX_FMT_RAW_16BIT:
|
|
|
+ PBIT[cindx] = 16;
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ PBIT[cindx] = 8;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ /* decide plane numbers, each plane size(byte) and line and line size*/
|
|
|
+ switch(fmt) {
|
|
|
+ case CSI_PIX_FMT_RAW_8BIT:
|
|
|
+ PLNS[cindx][0] = iw * ih;
|
|
|
+ LNN[cindx][0] = ih;
|
|
|
+ LSZ[cindx][0] = iw * 2 ;
|
|
|
+ LNNV[cindx][0] = iw;
|
|
|
+ LSZV[cindx][0] = ih * 2 ;
|
|
|
+ PLANE[cindx] = 1;
|
|
|
+ NOSTRD[cindx] = 0;
|
|
|
+ break;
|
|
|
+ case CSI_PIX_FMT_RAW_10BIT:
|
|
|
+ case CSI_PIX_FMT_RAW_12BIT:
|
|
|
+ case CSI_PIX_FMT_RAW_14BIT:
|
|
|
+ case CSI_PIX_FMT_RAW_16BIT:
|
|
|
+ PLNS[cindx][0] = iw * ih * 2;
|
|
|
+ LNN[cindx][0] = ih;
|
|
|
+ LSZ[cindx][0] = iw * 2 ;
|
|
|
+ LNNV[cindx][0] = iw;
|
|
|
+ LSZV[cindx][0] = ih * 2 ;
|
|
|
+ PLANE[cindx] = 1;
|
|
|
+ NOSTRD[cindx] = 0;
|
|
|
+ break;
|
|
|
+ case CSI_PIX_FMT_RGB_INTEVLEAVED_888:
|
|
|
+ case CSI_PIX_FMT_YUV_TEVLEAVED_444:
|
|
|
+ PLNS[cindx][0] = (iw * ih * PBIT[cindx] / 8) * 3;
|
|
|
+ LNN[cindx][0] = ih;
|
|
|
+ LSZ[cindx][0] = (iw * PBIT[cindx] / 8) * 3;
|
|
|
+ LNNV[cindx][0] = iw;
|
|
|
+ LSZV[cindx][0] = (ih * PBIT[cindx] / 8) * 3;
|
|
|
+ PLANE[cindx] = 1;
|
|
|
+ break;
|
|
|
+ case CSI_PIX_FMT_YUV_TEVLEAVED_422:
|
|
|
+ PLNS[cindx][0] = (iw * ih * PBIT[cindx] / 8) * 2;
|
|
|
+ LNN[cindx][0] = ih;
|
|
|
+ LSZ[cindx][0] = (iw * PBIT[cindx] / 8) * 2;
|
|
|
+ LNNV[cindx][0] = iw;
|
|
|
+ LSZV[cindx][0] = (ih * PBIT[cindx] / 8) * 2;
|
|
|
+ PLANE[cindx] = 1;
|
|
|
+ break;
|
|
|
+ case CSI_PIX_FMT_YUV_TEVLEAVED_420:
|
|
|
+ PLNS[cindx][0] = ((iw * ih * PBIT[cindx] / 8) * 3) / 2;
|
|
|
+ LNN[cindx][0] = ih;
|
|
|
+ LSZ[cindx][0] = ((iw * PBIT[cindx] / 8) * 3) / 2;
|
|
|
+ LNNV[cindx][0] = iw;
|
|
|
+ LSZV[cindx][0] = ((ih * PBIT[cindx] / 8) * 3) / 2;
|
|
|
+ PLANE[cindx] = 1;
|
|
|
+ break;
|
|
|
+ case CSI_PIX_FMT_BGR:
|
|
|
+ case CSI_PIX_FMT_RGB_PLANAR_888:
|
|
|
+ case CSI_PIX_FMT_YUV_PLANAR_444:
|
|
|
+ PLNS[cindx][0] = (iw * ih * PBIT[cindx] / 8);
|
|
|
+ PLNS[cindx][1] = (iw * ih * PBIT[cindx] / 8);
|
|
|
+ PLNS[cindx][2] = (iw * ih * PBIT[cindx] / 8);
|
|
|
+ LNN[cindx][0] = ih;
|
|
|
+ LNN[cindx][1] = ih;
|
|
|
+ LNN[cindx][2] = ih;
|
|
|
+ LSZ[cindx][0] = LSZ[cindx][1] = LSZ[cindx][2] = (iw * PBIT[cindx] / 8);
|
|
|
+ LNNV[cindx][0] = iw;
|
|
|
+ LNNV[cindx][1] = iw;
|
|
|
+ LNNV[cindx][2] = iw;
|
|
|
+ LSZV[cindx][0] = LSZV[cindx][1] = LSZV[cindx][2] = (ih * PBIT[cindx] / 8);
|
|
|
+ PLANE[cindx] = 3;
|
|
|
+ break;
|
|
|
+ case CSI_PIX_FMT_YUV_PLANAR_422:
|
|
|
+ PLNS[cindx][0] = (iw * ih * PBIT[cindx] / 8);
|
|
|
+ PLNS[cindx][1] = (iw * ih * PBIT[cindx] / 8) / 2;
|
|
|
+ PLNS[cindx][2] = (iw * ih * PBIT[cindx] / 8) / 2;
|
|
|
+ LNN[cindx][0] = ih;
|
|
|
+ LNN[cindx][1] = ih / 2;
|
|
|
+ LNN[cindx][2] = ih / 2;
|
|
|
+ LSZ[cindx][0] = (iw * PBIT[cindx] / 8);
|
|
|
+ LSZ[cindx][1] = LSZ[cindx][2] = (iw * PBIT[cindx] / 8) / 2;
|
|
|
+ LNNV[cindx][0] = iw;
|
|
|
+ LNNV[cindx][1] = iw /2;
|
|
|
+ LNNV[cindx][2] = iw /2;
|
|
|
+ LSZV[cindx][0] = (ih * PBIT[cindx] / 8);
|
|
|
+ LSZV[cindx][1] = LSZV[cindx][2] = (ih * PBIT[cindx] / 8) / 2;
|
|
|
+ PLANE[cindx] = 3;
|
|
|
+ break;
|
|
|
+ case CSI_PIX_FMT_YUV_PLANAR_420:
|
|
|
+ PLNS[cindx][0] = (iw * ih * PBIT[cindx] / 8);
|
|
|
+ PLNS[cindx][1] = PLNS[cindx][2] = (iw * ih * PBIT[cindx] / 8) / 4;
|
|
|
+ LNN[cindx][0] = ih;
|
|
|
+ LNN[cindx][1] = LNN[cindx][2] = ih / 4;
|
|
|
+ LSZ[cindx][0] = (iw * PBIT[cindx] / 8);
|
|
|
+ LSZ[cindx][1] = LSZ[cindx][2] = (iw * PBIT[cindx] / 8) / 4;
|
|
|
+ LNNV[cindx][0] = iw;
|
|
|
+ LNNV[cindx][1] = LNNV[cindx][2] = iw / 4;
|
|
|
+ LSZV[cindx][0] = (ih * PBIT[cindx] / 8);
|
|
|
+ LSZV[cindx][1] = LSZV[cindx][2] = (ih * PBIT[cindx] / 8) / 4;
|
|
|
+ PLANE[cindx] = 3;
|
|
|
+ break;
|
|
|
+ case CSI_PIX_FMT_I420:
|
|
|
+ case CSI_PIX_FMT_NV12:
|
|
|
+ case CSI_PIX_FMT_YUV_SEMIPLANAR_420:
|
|
|
+ PLNS[cindx][0] = (iw * ih * PBIT[cindx] / 8);
|
|
|
+ PLNS[cindx][1] = (iw * ih * PBIT[cindx] / 8) / 2;
|
|
|
+ LNN[cindx][0] = ih;
|
|
|
+ LNN[cindx][1] = ih / 2;
|
|
|
+ LSZ[cindx][0] = LSZ[cindx][1] = (iw * PBIT[cindx] / 8);
|
|
|
+ LNNV[cindx][0] = iw;
|
|
|
+ LNNV[cindx][1] = iw / 2;
|
|
|
+ LSZV[cindx][0] = LSZV[cindx][1] = (ih * PBIT[cindx] / 8);
|
|
|
+ PLANE[cindx] = 2;
|
|
|
+ break;
|
|
|
+ case CSI_PIX_FMT_YUV_SEMIPLANAR_422:
|
|
|
+ PLNS[cindx][0] = PLNS[cindx][1] = (iw * ih * PBIT[cindx] / 8);
|
|
|
+ LNN[cindx][0] = ih;
|
|
|
+ LNN[cindx][1] = ih;
|
|
|
+ LSZ[cindx][0] = LSZ[cindx][0] = (iw * PBIT[cindx] / 8);
|
|
|
+ LNNV[cindx][0] = iw;
|
|
|
+ LNNV[cindx][1] = iw;
|
|
|
+ LSZV[cindx][0] = LSZV[cindx][0] = (ih * PBIT[cindx] / 8);
|
|
|
+ PLANE[cindx] = 2;
|
|
|
+ break;
|
|
|
+ case CSI_PIX_FMT_YUV_SEMIPLANAR_444:
|
|
|
+ PLNS[cindx][0] = (iw * ih * PBIT[cindx] / 8);
|
|
|
+ PLNS[cindx][1] = (iw * ih * PBIT[cindx] / 8) * 2;
|
|
|
+ LNN[cindx][0] = ih;
|
|
|
+ LNN[cindx][1] = ih * 2;
|
|
|
+ LSZ[cindx][0] = (iw * PBIT[cindx] / 8);
|
|
|
+ LSZ[cindx][1] = (iw * PBIT[cindx] / 8);
|
|
|
+ LNNV[cindx][0] = iw;
|
|
|
+ LNNV[cindx][1] = iw * 2;
|
|
|
+ LSZV[cindx][0] = (ih * PBIT[cindx] / 8);
|
|
|
+ LSZV[cindx][1] = (ih * PBIT[cindx] / 8);
|
|
|
+ PLANE[cindx] = 2;
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ PLNS[cindx][0] = (iw * ih * PBIT[cindx] / 8);
|
|
|
+ PLNS[cindx][1] = (iw * ih * PBIT[cindx] / 8) / 2;
|
|
|
+ LNN[cindx][0] = ih;
|
|
|
+ LNN[cindx][1] = ih / 2;
|
|
|
+ LSZ[cindx][0] = LSZ[cindx][1] = (iw * PBIT[cindx] / 8);
|
|
|
+ LNNV[cindx][0] = iw;
|
|
|
+ LNNV[cindx][1] = iw / 2;
|
|
|
+ LSZV[cindx][0] = LSZV[cindx][1] = (ih * PBIT[cindx] / 8);
|
|
|
+ PLANE[cindx] = 2;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+function: store image of each frame
|
|
|
+input1: frame
|
|
|
+input2: channel index
|
|
|
+input3: target file point
|
|
|
+input4: reverse mdoe for rotating 90 and 270 degree
|
|
|
+*/
|
|
|
+static void i_save(csi_frame_ex_s *framei, int cid, FILE *fp, int vmode)
|
|
|
+{
|
|
|
+ int lindex = 0;
|
|
|
+ int smode = 0;
|
|
|
+ if( vmode == 0){
|
|
|
+ if(framei->frame_data.stride[0] != LSZ[cid][0] && NOSTRD[cid] == 0){
|
|
|
+ //if(NOSTRD[cid] == 0){
|
|
|
+ smode = 1;
|
|
|
+ printf("-------------In Stride mode, framei->img.strides[0]=%d---------------\n", framei->frame_data.stride[0]);
|
|
|
+ }
|
|
|
+ else{
|
|
|
+ printf("-------------No Stride, framei->img.strides[0]=%d---------------\n", framei->frame_data.stride[0]);
|
|
|
+ }
|
|
|
+ for (int p = 0; p < PLANE[cid]; p++){
|
|
|
+ /* loop for each planar */
|
|
|
+ //printf("-------------framei->img.usr_addr[%d]=0x%llx---------------\n", p, framei->img.usr_addr[p]);
|
|
|
+ lindex = 0;
|
|
|
+ //int size = 0;
|
|
|
+ if(smode == 0){
|
|
|
+ /* no stride, write plane by plane*/
|
|
|
+ printf("-------------No Stride, length is = %d---------------\n", PLNS[cid][p]);
|
|
|
+ //while(size < PLNS[cid][p]){
|
|
|
+ // size += fwrite(framei->img.usr_addr[p] + size, sizeof(char), PLNS[cid][p] - size, fp);
|
|
|
+ // }
|
|
|
+ fwrite(framei->frame_data.vir_addr[p], sizeof(char), PLNS[cid][p], fp);
|
|
|
+ }
|
|
|
+ else{
|
|
|
+ /* stride mode, write line by line */
|
|
|
+ for(int l = 0; l < LNN[cid][p]; l++){
|
|
|
+ if(framei->frame_data.stride[p] == 0){
|
|
|
+ printf("-------------Error: stride[%d] is 0---------------\n", p);
|
|
|
+ lindex = LSZ[cid][p] * l;
|
|
|
+ }
|
|
|
+ else{
|
|
|
+ /* for each plane, the strides[x] is the same */
|
|
|
+ lindex = framei->frame_data.stride[0] * l;
|
|
|
+ }
|
|
|
+ fwrite(framei->frame_data.vir_addr[p] + lindex, sizeof(char), LSZ[cid][p], fp);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else{
|
|
|
+ if(framei->frame_data.stride[0] != LSZV[cid][0] && NOSTRD[cid] == 0){
|
|
|
+ smode = 1;
|
|
|
+ printf("-------------In Stride mode, framei->img.strides[0]=%d---------------\n", framei->frame_data.stride[0]);
|
|
|
+ }
|
|
|
+ else{
|
|
|
+ printf("-------------No Stride, framei->img.strides[0]=%d---------------\n", framei->frame_data.stride[0]);
|
|
|
+ }
|
|
|
+ for (int p = 0; p < PLANE[cid]; p++){
|
|
|
+ /* loop for each planar */
|
|
|
+ //printf("-------------framei->img.usr_addr[%d]=0x%llx---------------\n", p, framei->img.usr_addr[p]);
|
|
|
+ lindex = 0;
|
|
|
+ int size = 0;
|
|
|
+ if(smode == 0){
|
|
|
+ /* no stride, write plane by plane*/
|
|
|
+ printf("-------------No Stride, length is = %d---------------\n", PLNS[cid][p]);
|
|
|
+ while(size < PLNS[cid][p]){
|
|
|
+ size += fwrite(framei->frame_data.vir_addr[p] + size, sizeof(char), PLNS[cid][p] - size, fp);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else{
|
|
|
+ /* stride mode, write line by line */
|
|
|
+ for(int l = 0; l < LNNV[cid][p]; l++){
|
|
|
+ if(framei->frame_data.stride[p] == 0){
|
|
|
+ printf("-------------Error: stride[%d] is 0---------------\n", p);
|
|
|
+ lindex = LSZV[cid][p] * l;
|
|
|
+ }
|
|
|
+ else{
|
|
|
+ /* for each plane, the strides[x] is the same */
|
|
|
+ lindex = framei->frame_data.stride[0] * l;
|
|
|
+ }
|
|
|
+ fwrite(framei->frame_data.vir_addr[p] + lindex, sizeof(char), LSZV[cid][p], fp);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+function: convert dma-buf file point to target address
|
|
|
+input1: framei
|
|
|
+input2: channel index
|
|
|
+*/
|
|
|
+// static void handle_dma_buf(csi_frame_ex_s *framei, int cid)
|
|
|
+// {
|
|
|
+// if (frame->img.type == CSI_IMG_TYPE_DMA_BUF) {
|
|
|
+// void *p[3] = {0};
|
|
|
+// /*
|
|
|
+// The first plane which exists always.
|
|
|
+// All data for packed; Y data for planar or semi-planar
|
|
|
+// */
|
|
|
+// void *phyaddr = vi_mem_import(framei->img.dmabuf[0].fds);
|
|
|
+// p[0] = vi_mem_map(phyaddr) + framei->img.dmabuf[0].offset;
|
|
|
+// framei->img.usr_addr[0] = p[0];
|
|
|
+// /*
|
|
|
+// For other planes, in our solution, we only have plane[1] for
|
|
|
+// planar or sp; or no other plane for packed.
|
|
|
+// */
|
|
|
+// for (int i=1; i<PLANE[cid]; i++){
|
|
|
+// if (framei->img.dmabuf[i].offset != NULL){
|
|
|
+// p[i] = framei->img.dmabuf[i].offset + p[0];
|
|
|
+// framei->img.usr_addr[i] = p[i];
|
|
|
+// }
|
|
|
+// else{
|
|
|
+// printf("-------------DMA ERROR, no usr_addr for plane=%d---------------\n", i);
|
|
|
+// }
|
|
|
+// }
|
|
|
+// vi_mem_release(phyaddr);
|
|
|
+// }
|
|
|
+// }
|
|
|
+
|
|
|
+/*
|
|
|
+function: save data as image
|
|
|
+input1: channel index
|
|
|
+*/
|
|
|
+static void* save_camera_img(void * idx)
|
|
|
{
|
|
|
- static int fcount = 0;
|
|
|
- char fname[20];
|
|
|
+ int index = *(int*)(idx);
|
|
|
+ free(idx);
|
|
|
+ char fname[512];
|
|
|
+ char fidname[256];
|
|
|
FILE *fp;
|
|
|
- fcount = fcount%4;
|
|
|
- sprintf(fname, "%s%d%s", "hal_image", fcount, ".yuv");
|
|
|
- fcount++;
|
|
|
+ char fidc[128];
|
|
|
+ int fcount;
|
|
|
+ int fidi = fid[index];
|
|
|
+ int cid = channelIdx[index];
|
|
|
+ int hresi = hres[index];
|
|
|
+ int vresi = vres[index];
|
|
|
+ enum csi_pixel_fmt fmt = fenum[index];
|
|
|
+ csi_frame_ex_s *framei = &frame[index];
|
|
|
+ int vmode = 0;
|
|
|
+
|
|
|
+ if(framei->frame_info.width == vresi && framei->frame_info.height == hresi && vresi != hresi){
|
|
|
+ vmode = 1;
|
|
|
+ vresi = framei->frame_info.height;
|
|
|
+ hresi = framei->frame_info.width;
|
|
|
+ }
|
|
|
|
|
|
+ /* generate the image name */
|
|
|
+ fcount = fidi%tframes;
|
|
|
+ sprintf(fname, "%s%s%s%s%d%s%d%s%d%s%d%s%d%s%s", path, "/img_", dname, "_", PLANE[index], "P_", cid, "_", hresi, "x", vresi, "_", fcount, ".", fmtArray[fmt]);
|
|
|
+ /* dma-buf to address */
|
|
|
+ // handle_dma_buf(framei, index);
|
|
|
if((fp = fopen(fname, "wb")) == NULL){
|
|
|
printf("Error: Can't open file\n");
|
|
|
- return -1;
|
|
|
+ return NULL;
|
|
|
}
|
|
|
- fwrite(frame->img.usr_addr[0], sizeof(char), frame->img.size, fp);
|
|
|
- fclose(fp);
|
|
|
- return 0;
|
|
|
+ /* data saving */
|
|
|
+ i_save(framei, index, fp, vmode);
|
|
|
+ fclose(fp);
|
|
|
+
|
|
|
+ /* frame ID saving */
|
|
|
+ sprintf(fidc, "%d\n", fidi);
|
|
|
+ sprintf(fidname, "%s%s%s%s%d%s", path, "/fid_", dname, "_chn_", cid, ".txt");
|
|
|
+ if((fp = fopen(fidname, "a+")) == NULL){
|
|
|
+ printf("Error: Can't open file\n");
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+ fwrite(fidc, sizeof(char), strlen(fidc), fp);
|
|
|
+ fclose(fp);
|
|
|
+ if(meta_mode >= 0){
|
|
|
+ dump_camera_meta(framei, index);
|
|
|
+ }
|
|
|
+ //csi_camera_frame_unlock(cam_handle, framei);
|
|
|
+ csi_camera_put_frame(framei);
|
|
|
+ // csi_frame_release(framei);
|
|
|
+ if (onoffMode == 1 && fNumInc[index] % onoffFrame == 0){
|
|
|
+ afterOnOff[index] = onoffDrop;
|
|
|
+ // stop stream, sleep, start stream
|
|
|
+ csi_camera_channel_stop(cam_handle, CAMERA_CHANNEL_ID[index]);
|
|
|
+ //sleep(1);
|
|
|
+ csi_camera_channel_start(cam_handle, CAMERA_CHANNEL_ID[index]);
|
|
|
+ }
|
|
|
+ return NULL;
|
|
|
}
|
|
|
|
|
|
-static int save_camera_stream(csi_frame_s *frame)
|
|
|
+/*
|
|
|
+function: save data as stream
|
|
|
+input1: channel index
|
|
|
+*/
|
|
|
+static void* save_camera_stream(void *idx)
|
|
|
{
|
|
|
- FILE *fp;
|
|
|
- char *fname = "hal_stream.yuv";
|
|
|
- if((fp = fopen(fname, "ab+")) == NULL){
|
|
|
- printf("Error: Can't open file\n");
|
|
|
- return -1;
|
|
|
- }
|
|
|
- fwrite(frame->img.usr_addr[0], sizeof(char), frame->img.size, fp);
|
|
|
- fclose(fp);
|
|
|
- return 0;
|
|
|
+ int index = *(int*)(idx);
|
|
|
+
|
|
|
+ free(idx);
|
|
|
+ FILE *fp;
|
|
|
+ char fname[256];
|
|
|
+ int cid = channelIdx[index];
|
|
|
+ int hresi = hres[index];
|
|
|
+ int vresi = vres[index];
|
|
|
+ enum csi_pixel_fmt fmt = fenum[index];
|
|
|
+ csi_frame_ex_s *framei = &frame[index];
|
|
|
+ int vmode = 0;
|
|
|
+
|
|
|
+ if(framei->frame_info.width == vresi && framei->frame_info.height == hresi && vresi != hresi){
|
|
|
+ vmode = 1;
|
|
|
+ vresi = framei->frame_info.height;
|
|
|
+ hresi = framei->frame_info.width;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* generate stream name - for each time it is the same name */
|
|
|
+ sprintf(fname, "%s%s%s%s%d%s%d%s%d%s%d%s%s", path, "/str_", dname, "_", PLANE[index], "P_", cid, "_", hresi, "x", vresi, ".", fmtArray[fmt]);
|
|
|
+ // handle_dma_buf(framei, index);
|
|
|
+ if((fp = fopen(fname, "ab+")) == NULL){
|
|
|
+ printf("Error: Can't open file\n");
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+ i_save(framei, index, fp, vmode);
|
|
|
+ fclose(fp);
|
|
|
+ if(meta_mode >= 0){
|
|
|
+ dump_camera_meta(framei, index);
|
|
|
+ }
|
|
|
+
|
|
|
+ //csi_camera_frame_unlock(cam_handle, framei);
|
|
|
+ csi_camera_put_frame(framei);
|
|
|
+ // csi_frame_release(framei);
|
|
|
+ if (onoffMode == 1 && fNumInc[index] % onoffFrame == 0){
|
|
|
+ afterOnOff[index] = onoffDrop;
|
|
|
+ // stop stream, sleep, start stream
|
|
|
+ csi_camera_channel_stop(cam_handle, CAMERA_CHANNEL_ID[index]);
|
|
|
+ //sleep(1);
|
|
|
+ csi_camera_channel_start(cam_handle, CAMERA_CHANNEL_ID[index]);
|
|
|
+ }
|
|
|
+ return NULL;
|
|
|
}
|
|
|
|
|
|
+// 同时配置多个参数
|
|
|
+static int set_properties(csi_cam_handle_t cam_handle, char *pArgs)
|
|
|
+{
|
|
|
+ csi_camera_properties_s properties;
|
|
|
+ csi_camera_property_s property[30];
|
|
|
+
|
|
|
+ char *pDelim=":/";
|
|
|
+ int pid;
|
|
|
+ int ptype;
|
|
|
+ int pvalueInt;
|
|
|
+ char *pvalueStr;
|
|
|
+ char *pFirst;
|
|
|
+ /*
|
|
|
+ parse multi-properties which delimited by : or /
|
|
|
+ 1. / is used to seprate multi properties
|
|
|
+ 2. : is used to sperate pid:type:value
|
|
|
+ for example: 1:2:1/2:2:1/3:1:90
|
|
|
+ */
|
|
|
+ pFirst = strtok(pArgs, pDelim);
|
|
|
+ int i = 0;
|
|
|
+ while(pFirst != NULL){
|
|
|
+ pid = atoi(pFirst);
|
|
|
+ property[i].id = pid + CSI_CAMERA_PID_BASE;
|
|
|
+ /*
|
|
|
+ property type difinition:
|
|
|
+ CSI_CAMERA_PROPERTY_TYPE_INTEGER = 1,
|
|
|
+ CSI_CAMERA_PROPERTY_TYPE_BOOLEAN = 2,
|
|
|
+ CSI_CAMERA_PROPERTY_TYPE_ENUM = 3,
|
|
|
+ CSI_CAMERA_PROPERTY_TYPE_STRING = 7,
|
|
|
+ CSI_CAMERA_PROPERTY_TYPE_BITMASK = 8,
|
|
|
+ */
|
|
|
+ ptype = atoi(strtok(NULL, pDelim));
|
|
|
+ property[i].type = ptype;
|
|
|
+ if (ptype == CSI_CAMERA_PROPERTY_TYPE_STRING) {
|
|
|
+ pvalueStr = strtok(NULL, pDelim);
|
|
|
+ strcpy(property[i].value.str_value, pvalueStr);
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ pvalueInt = atoi(strtok(NULL, pDelim));
|
|
|
+ property[i].value.int_value = pvalueInt;
|
|
|
+ }
|
|
|
+ i++;
|
|
|
+ pFirst = strtok(NULL, pDelim);
|
|
|
+ }
|
|
|
+
|
|
|
+ /* set multi-properties(here the property number is i) by calling API just one time */
|
|
|
+ properties.count = i;
|
|
|
+ properties.property = property;
|
|
|
+ if (csi_camera_set_property(cam_handle, &properties) < 0) {
|
|
|
+ printf("set_property fail!\n");
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+ printf("set_property ok!\n");
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static enum csi_pixel_fmt parse_format(char *fmt)
|
|
|
+{
|
|
|
+ for(int i=0; i<fmtMAX; i++){
|
|
|
+ if(strstr(fmtArray[i], fmt)){
|
|
|
+ return CSI_PIX_FMT_I420 + i;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return CSI_PIX_FMT_NV12;
|
|
|
+}
|