camera_test1.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391
  1. /*
  2. * Copyright (C) 2021 Alibaba Group Holding Limited
  3. * Author: LuChongzhi <chongzhi.lcz@alibaba-inc.com>
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License version 2 as
  7. * published by the Free Software Foundation.
  8. */
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include <string.h>
  12. #define LOG_LEVEL 2
  13. #define LOG_PREFIX "camera_demo1"
  14. #include <syslog.h>
  15. #include <csi_frame.h>
  16. #include <csi_camera.h>
  17. #ifdef PLATFORM_SIMULATOR
  18. #include "apputilities.h"
  19. #endif
  20. static void dump_camera_meta(csi_frame_s *frame);
  21. static int save_camera_img(csi_frame_s *frame);
  22. static int save_camera_stream(csi_frame_s *frame);
  23. #define TEST_DEVICE_NAME "/dev/video0"
  24. #define CSI_CAMERA_TRUE 1
  25. #define CSI_CAMERA_FALSE 0
  26. char *prog_name;
  27. void usage()
  28. {
  29. fprintf (stderr,
  30. "usage: %s [options]\n"
  31. "Options:\n"
  32. "\t-D dev target video device like /dev/video0\n"
  33. "\t-R resolution format is like 640x480\n"
  34. "\t-F format like NV12\n"
  35. "\t-C channel_index channel index defined in dts, index from 0\n"
  36. "\t-M output mode 0: save as image; 1: save as stream file\n"
  37. "\t-N number for frames 0: record forever; others: the recorded frame numbers"
  38. , prog_name
  39. );
  40. }
  41. int main(int argc, char *argv[])
  42. {
  43. bool running = false;
  44. csi_camera_info_s camera_info;
  45. int opt;
  46. char device[CSI_CAMERA_NAME_MAX_LEN]; /* target video device like /dev/video0 */
  47. char *resolution; /* resolution information like 640x480 */
  48. int hres, vres; /* resolution information like 640x480 */
  49. char *resDelim = "xX";
  50. char *format; /* format information like NV12 */
  51. enum csi_pixel_fmt fenum;
  52. int channelIdx; /* channel information like 8 */
  53. int outMode = 0;
  54. int fNum = 0;
  55. prog_name = argv[0];
  56. while ((opt = getopt(argc, argv, "D:R:F:C:M:hN:")) != EOF) {
  57. switch(opt) {
  58. case 'D':
  59. //device = optarg;
  60. strcpy(device, optarg);
  61. continue;
  62. case 'R':
  63. resolution = optarg;
  64. hres = atoi(strtok(resolution, resDelim));
  65. vres = atoi(strtok(NULL, resDelim));
  66. continue;
  67. case 'M':
  68. outMode = atoi(optarg);
  69. continue;
  70. case 'N':
  71. fNum = atoi(optarg);
  72. continue;
  73. case 'F':
  74. format = optarg;
  75. if(strstr(format, "NV12")){
  76. fenum = CSI_PIX_FMT_NV12;
  77. }
  78. else if(strstr(format, "I420")){
  79. fenum = CSI_PIX_FMT_I420;
  80. }
  81. else{
  82. fenum = CSI_PIX_FMT_I420;
  83. }
  84. continue;
  85. case 'C':
  86. channelIdx = atoi(optarg);
  87. continue;
  88. case '?':
  89. case 'h':
  90. default:
  91. usage();
  92. return 1;
  93. }
  94. }
  95. const csi_camera_channel_id_e CAMERA_CHANNEL_ID = CSI_CAMERA_CHANNEL_0 + channelIdx;
  96. const csi_camera_event_type_e CAMERA_CHANNEL_EVENT_TYPE = CSI_CAMERA_EVENT_TYPE_CHANNEL0 + channelIdx;
  97. if (fNum == 0)
  98. running == true;
  99. // 打印HAL接口版本号
  100. csi_api_version_u version;
  101. csi_camera_get_version(&version);
  102. printf("Camera HAL version: %d.%d\n", version.major, version.minor);
  103. // 获取设备中,所有的Camera
  104. struct csi_camera_infos camera_infos;
  105. memset(&camera_infos, 0, sizeof(camera_infos));
  106. csi_camera_query_list(&camera_infos);
  107. // 打印所有设备所支持的Camera
  108. for (int i = 0; i < camera_infos.count; i++) {
  109. camera_info = camera_infos.info[i];
  110. printf("Camera[%d]: camera_name='%s', device_name='%s', bus_info='%s', capabilities=0x%08x\n",
  111. i,
  112. camera_info.camera_name, camera_info.device_name, camera_info.bus_info,
  113. camera_info.capabilities);
  114. printf("Camera[%d] caps are:\n",
  115. i); /* The caps are: Video capture, metadata capture */
  116. for (int j = 1; j <= 0x08000000; j = j << 1) {
  117. switch (camera_info.capabilities & j) {
  118. case CSI_CAMERA_CAP_VIDEO_CAPTURE:
  119. printf("\t camera_infos.info[%d]:Video capture,\n", i);
  120. break;
  121. case CSI_CAMERA_CAP_META_CAPTURE:
  122. printf("\t camera_infos.info[%d] metadata capture,\n", i);
  123. break;
  124. default:
  125. if (camera_info.capabilities & j) {
  126. printf("\t camera_infos.info[%d] unknown capabilities(0x%08x)\n", i,
  127. camera_info.capabilities & j);
  128. }
  129. break;
  130. }
  131. }
  132. }
  133. // 打开Camera设备获取句柄,作为后续操对象
  134. csi_cam_handle_t cam_handle;
  135. //csi_camera_open(&cam_handle, camera_info.device_name);
  136. strcpy(camera_info.device_name, device);
  137. //camera_info.device_name = device;
  138. csi_camera_open(&cam_handle, camera_info.device_name);
  139. //csi_camera_open(&cam_handle, device);
  140. // 获取Camera支持的工作模式
  141. struct csi_camera_modes camera_modes;
  142. csi_camera_get_modes(cam_handle, &camera_modes);
  143. // 打印camera所支持的所有工作模式
  144. printf("Camera:'%s' modes are:\n", device);
  145. printf("{\n");
  146. for (int i = 0; i < camera_modes.count; i++) {
  147. printf("\t mode_id=%d: description:'%s'\n",
  148. camera_modes.modes[i].mode_id, camera_modes.modes[i].description);
  149. }
  150. printf("}\n");
  151. // 设置camera的工作模式及其配置
  152. csi_camera_mode_cfg_s camera_cfg;
  153. camera_cfg.mode_id = 1;
  154. camera_cfg.calibriation = NULL; // 采用系统默认配置
  155. camera_cfg.lib3a = NULL; // 采用系统默认配置
  156. csi_camera_set_mode(cam_handle, &camera_cfg);
  157. // 获取单个可控单元的属性
  158. csi_camera_property_description_s description;
  159. /* id=0x0098090x, type=2 default=0 value=1 */
  160. /* Other example:
  161. * id=0x0098090y, type=3 min=0 max=255 step=1 default=127 value=116
  162. * id=0x0098090z, type=4 min=0 max=3 default=0 value=2
  163. * 0: IDLE
  164. * 1: BUSY
  165. * 2: REACHED
  166. * 3: FAILED
  167. */
  168. // 轮询获取所有可控制的单元
  169. printf("all properties are:\n");
  170. description.id = CSI_CAMERA_PID_HFLIP;
  171. while (!csi_camera_query_property(cam_handle, &description)) {
  172. switch (description.type) {
  173. case (CSI_CAMERA_PROPERTY_TYPE_INTEGER):
  174. printf("id=0x%08x type=%d default=%d value=%d\n",
  175. description.id, description.type,
  176. description.default_value.int_value, description.value.int_value);
  177. break;
  178. case (CSI_CAMERA_PROPERTY_TYPE_BOOLEAN):
  179. printf("id=0x%08x type=%d default=%d value=%d\n",
  180. description.id, description.type,
  181. description.default_value.bool_value, description.value.bool_value);
  182. break;
  183. case (CSI_CAMERA_PROPERTY_TYPE_ENUM):
  184. printf("id=0x%08x type=%d default=%d value=%d\n",
  185. description.id, description.type,
  186. description.default_value.enum_value, description.value.enum_value);
  187. break;
  188. case (CSI_CAMERA_PROPERTY_TYPE_STRING):
  189. printf("id=0x%08x type=%d default=%s value=%s\n",
  190. description.id, description.type,
  191. description.default_value.str_value, description.value.str_value);
  192. break;
  193. case (CSI_CAMERA_PROPERTY_TYPE_BITMASK):
  194. printf("id=0x%08x type=%d default=%x value=%x\n",
  195. description.id, description.type,
  196. description.default_value.bitmask_value, description.value.bitmask_value);
  197. break;
  198. default:
  199. LOG_E("error type!\n");
  200. break;
  201. }
  202. description.id |= CSI_CAMERA_FLAG_NEXT_CTRL;
  203. }
  204. // 同时配置多个参数
  205. csi_camera_properties_s properties;
  206. csi_camera_property_s property[3];
  207. property[0].id = CSI_CAMERA_PID_HFLIP;
  208. property[0].type = CSI_CAMERA_PROPERTY_TYPE_BOOLEAN;
  209. property[0].value.bool_value = false;
  210. property[1].id = CSI_CAMERA_PID_VFLIP;
  211. property[1].type = CSI_CAMERA_PROPERTY_TYPE_BOOLEAN;
  212. property[1].value.bool_value = false;
  213. property[2].id = CSI_CAMERA_PID_ROTATE;
  214. property[2].type = CSI_CAMERA_PROPERTY_TYPE_INTEGER;
  215. property[2].value.int_value = 0;
  216. properties.count = 3;
  217. properties.property = property;
  218. if (csi_camera_set_property(cam_handle, &properties) < 0) {
  219. LOG_O("set_property fail!\n");
  220. }
  221. LOG_O("set_property ok!\n");
  222. // 查询输出channel
  223. csi_camera_channel_cfg_s chn_cfg;
  224. chn_cfg.chn_id = CAMERA_CHANNEL_ID;
  225. csi_camera_channel_query(cam_handle, &chn_cfg);
  226. if (chn_cfg.status != CSI_CAMERA_CHANNEL_CLOSED) {
  227. printf("Can't open CSI_CAMERA_CHANNEL_0\n");
  228. exit(-1);
  229. }
  230. // 打开输出channel
  231. chn_cfg.chn_id = channelIdx;
  232. chn_cfg.frm_cnt = 4;
  233. chn_cfg.img_fmt.width = hres;
  234. chn_cfg.img_fmt.height = vres;
  235. chn_cfg.img_fmt.pix_fmt = fenum;
  236. chn_cfg.img_type = CSI_IMG_TYPE_DMA_BUF;
  237. chn_cfg.meta_fields = CSI_CAMERA_META_DEFAULT_FIELDS;
  238. chn_cfg.capture_type = CSI_CAMERA_CHANNEL_CAPTURE_VIDEO |
  239. CSI_CAMERA_CHANNEL_CAPTURE_META;
  240. csi_camera_channel_open(cam_handle, &chn_cfg);
  241. // 订阅Event
  242. csi_cam_event_handle_t event_handle;
  243. csi_camera_create_event(&event_handle, cam_handle);
  244. csi_camera_event_subscription_s subscribe;
  245. subscribe.type =
  246. CSI_CAMERA_EVENT_TYPE_CAMERA; // 订阅Camera的ERROR事件
  247. subscribe.id = CSI_CAMERA_EVENT_WARNING | CSI_CAMERA_EVENT_ERROR;
  248. csi_camera_subscribe_event(event_handle, &subscribe);
  249. subscribe.type =
  250. CAMERA_CHANNEL_EVENT_TYPE; // 订阅Channel0的FRAME_READY事件
  251. subscribe.id = CSI_CAMERA_CHANNEL_EVENT_FRAME_READY |
  252. CSI_CAMERA_CHANNEL_EVENT_OVERFLOW;
  253. csi_camera_subscribe_event(event_handle, &subscribe);
  254. // 开始从channel中取出准备好的frame
  255. csi_camera_channel_start(cam_handle, CAMERA_CHANNEL_ID);
  256. // 处理订阅的Event
  257. csi_frame_s frame;
  258. struct csi_camera_event event;
  259. while (running || fNum >= 0 ) {
  260. int timeout = -1; // unit: ms, -1 means wait forever, or until error occurs
  261. csi_camera_get_event(event_handle, &event, timeout);
  262. if(event.type == CSI_CAMERA_EVENT_TYPE_CAMERA){
  263. switch (event.id) {
  264. case CSI_CAMERA_EVENT_ERROR:
  265. // do sth.
  266. LOG_D("get CAMERA EVENT CSI_CAMERA_EVENT_ERROR!\n");
  267. break;
  268. default:
  269. break;
  270. }
  271. }
  272. if(event.type == CAMERA_CHANNEL_EVENT_TYPE){
  273. switch (event.id) {
  274. case CSI_CAMERA_CHANNEL_EVENT_FRAME_READY: {
  275. int read_frame_count = csi_camera_get_frame_count(cam_handle,
  276. CAMERA_CHANNEL_ID);
  277. for (int i = 0; i < read_frame_count; i++) {
  278. csi_camera_get_frame(cam_handle, CAMERA_CHANNEL_ID, &frame, timeout);
  279. fNum--;
  280. #ifdef PLATFORM_SIMULATOR
  281. show_frame_image(frame.img.usr_addr[0], frame.img.height, frame.img.width);
  282. #endif
  283. if (outMode == 0)
  284. save_camera_img(&frame);
  285. else
  286. save_camera_stream(&frame);
  287. csi_frame_release(&frame);
  288. }
  289. break;
  290. }
  291. default:
  292. break;
  293. }
  294. }
  295. }
  296. csi_camera_channel_stop(cam_handle, CAMERA_CHANNEL_ID);
  297. usleep (1000000);
  298. // 取消订阅某一个event, 也可以直接调用csi_camera_destory_event,结束所有的订阅
  299. subscribe.type = CAMERA_CHANNEL_EVENT_TYPE;
  300. subscribe.id = CSI_CAMERA_CHANNEL_EVENT_FRAME_READY;
  301. csi_camera_unsubscribe_event(event_handle, &subscribe);
  302. csi_camera_destory_event(event_handle);
  303. csi_camera_channel_close(cam_handle, CAMERA_CHANNEL_ID);
  304. csi_camera_close(cam_handle);
  305. }
  306. static void dump_camera_meta(csi_frame_s *frame)
  307. {
  308. int i;
  309. //printf("%s\n", __func__);
  310. if (frame->meta.type != CSI_META_TYPE_CAMERA)
  311. return;
  312. csi_camera_meta_s *meta_data = (csi_camera_meta_s *)frame->meta.data;
  313. int meta_count = meta_data->count;
  314. csi_camrea_meta_unit_s meta_unit;
  315. for (i = 0; i < meta_count; i++) {
  316. csi_camera_frame_get_meta_unit(
  317. &meta_unit, meta_data, CSI_CAMERA_META_ID_FRAME_ID);
  318. //printf("meta_id=%d, meta_type=%d, meta_value=%d",
  319. // meta_unit.id, meta_unit.type, meta_unit.int_value);
  320. }
  321. }
  322. static int save_camera_img(csi_frame_s *frame)
  323. {
  324. static int fcount = 0;
  325. char fname[20];
  326. FILE *fp;
  327. fcount = fcount%4;
  328. sprintf(fname, "%s%d%s", "hal_image", fcount, ".yuv");
  329. fcount++;
  330. if((fp = fopen(fname, "wb")) == NULL){
  331. printf("Error: Can't open file\n");
  332. return -1;
  333. }
  334. fwrite(frame->img.usr_addr[0], sizeof(char), frame->img.size, fp);
  335. fclose(fp);
  336. return 0;
  337. }
  338. static int save_camera_stream(csi_frame_s *frame)
  339. {
  340. FILE *fp;
  341. char *fname = "hal_stream.yuv";
  342. if((fp = fopen(fname, "ab+")) == NULL){
  343. printf("Error: Can't open file\n");
  344. return -1;
  345. }
  346. fwrite(frame->img.usr_addr[0], sizeof(char), frame->img.size, fp);
  347. fclose(fp);
  348. return 0;
  349. }