camera_manager.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577
  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 <errno.h>
  12. #include <pthread.h>
  13. #include <unistd.h>
  14. #define LOG_LEVEL 3
  15. #define LOG_PREFIX "camera_manager"
  16. #include <syslog.h>
  17. #include <camera_string.h>
  18. #include <csi_camera_platform_spec.h>
  19. #include "camera_manager.h"
  20. #include "camera_manager_utils.h"
  21. #include "platform_action.h"
  22. // ref: https://developer.android.google.cn/reference/android/hardware/camera2/CameraManager#inherited-methods
  23. #define _CHECK_SESSION_RETURN() \
  24. do { \
  25. if (session == NULL) { \
  26. LOG_E("session is NULL\n"); \
  27. return -EPERM; \
  28. } \
  29. } while (0)
  30. #define _CHECK_STATE_RETURN(expect) \
  31. do { \
  32. if ((session->state & expect) == 0) { \
  33. LOG_E("current state(%d) is not expected(%d)\n",\
  34. session->state, expect); \
  35. return -EPERM; \
  36. } \
  37. } while (0)
  38. static bool camera_thread_flag = true;
  39. static int _camera_session_reset(cams_t *session)
  40. {
  41. _CHECK_SESSION_RETURN();
  42. memset(session, 0, sizeof(*session));
  43. session->state = CAMERA_STATE_CLOSED;
  44. session->camera_handle = NULL;
  45. session->event_handle = NULL;
  46. for (int chn = 0; chn < CSI_CAMERA_CHANNEL_MAX_COUNT; chn++) {
  47. session->chn_cfg[chn].chn_id = -1;
  48. session->chn_cfg[chn].status = CSI_CAMERA_CHANNEL_INVALID;
  49. }
  50. session->camera_action_fun = NULL;
  51. session->channel_action_fun = NULL;
  52. return 0;
  53. }
  54. typedef enum _info_field {
  55. CAMERA_INFOS_READY = (1 << 0), // saved in: cams_t.camera_infos
  56. CAMERA_MODES_READY = (1 << 1), // saved in: cams_t.camera_modes
  57. CHANNEL_INIT_READY = (1 << 2), // saved in: cams_t.chn_cfg
  58. } _info_field_e;
  59. /* set: true means set field to be 1, false means clear the field */
  60. static inline void _set_info_status(cams_t *session, _info_field_e field,
  61. bool set)
  62. {
  63. if (set)
  64. session->info_status |= field;
  65. else
  66. session->info_status &= ~field;
  67. }
  68. /* set: true means set field to be 1, false means clear the field */
  69. static inline bool _get_info_status(cams_t *session, _info_field_e field)
  70. {
  71. return ((session->info_status & field) != 0);
  72. }
  73. int camera_create_session(cams_t **session)
  74. {
  75. if (session == NULL) {
  76. LOG_E("input param error\n");
  77. return -EPERM;
  78. }
  79. *session = malloc(sizeof(cams_t));
  80. if (*session == NULL) {
  81. LOG_E("Create manager failed, %s\n", strerror(errno));
  82. return -ENOMEM;
  83. }
  84. _camera_session_reset(*session);
  85. return 0;
  86. }
  87. int camera_destory_session(cams_t **session)
  88. {
  89. free(*session);
  90. *session = NULL;
  91. return 0;
  92. }
  93. int camera_query_list(cams_t *session)
  94. {
  95. if (_get_info_status(session, CAMERA_INFOS_READY)) {
  96. LOG_D("camera list has been got before\n");
  97. return 0;
  98. }
  99. int ret = csi_camera_query_list(&session->camera_infos);
  100. if (ret != 0) {
  101. LOG_E("csi_camera_query_list() failed\n");
  102. _set_info_status(session, CAMERA_INFOS_READY, false);
  103. }
  104. _set_info_status(session, CAMERA_INFOS_READY, true);
  105. return 0;
  106. }
  107. int camera_get_caps(cams_t *session)
  108. {
  109. int ret;
  110. _CHECK_SESSION_RETURN();
  111. return 0;
  112. }
  113. int camera_open(cams_t *session, const char *dev_name)
  114. {
  115. _CHECK_SESSION_RETURN();
  116. int ret;
  117. csi_camera_info_s camera_info;
  118. csi_cam_handle_t handle;
  119. if (!_get_info_status(session, CAMERA_INFOS_READY)) {
  120. LOG_E("Can't open %s\n", dev_name);
  121. return -1;
  122. }
  123. ret = csi_camera_open(&handle, dev_name);
  124. if (ret != 0) {
  125. LOG_E("Open camera(%s) failed\n", dev_name);
  126. return -1;
  127. }
  128. session->camera_handle = handle;
  129. session->state = CAMERA_STATE_OPENED;
  130. camera_event_action_union_t *event_action;
  131. const camera_spec_enums_s *enum_array;
  132. /* Camera Event/Action init */
  133. ret = csi_camera_create_event(&session->event_handle, session->camera_handle);
  134. if (ret != 0) {
  135. LOG_E("csi_camera_create_event failed, ret handle=%p\n", session->event_handle);
  136. return -1;
  137. }
  138. for (int i = 0; i < CSI_CAMERA_EVENT_MAX_COUNT; i++) {
  139. event_action = &(session->camera_event_action[i]);
  140. event_action->target = MANAGE_TARGET_CAMERA;
  141. event_action->camera.event = 1 << i;
  142. //LOG_W("i=%d, event_action->camera.event=0x%08x\n", i, event_action->camera.event);
  143. event_action->camera.supported = false;
  144. event_action->camera.subscribed = false;
  145. event_action->camera.action = CAMERA_ACTION_NONE;
  146. }
  147. enum_array = camera_spec_get_enum_array(CAMERA_SPEC_ENUM_CAMERA_EVENT_TYPES);
  148. for (int i = 0; (enum_array != NULL) && (i < enum_array->count); i++) {
  149. for (int j = 0; j < CSI_CAMERA_EVENT_MAX_COUNT; j++) {
  150. event_action = &(session->camera_event_action[j]);
  151. if (enum_array->enums[i] == event_action->camera.event) {
  152. event_action->camera.supported = true;
  153. //cam_mng_dump_event_action_union(event_action);
  154. }
  155. }
  156. }
  157. /* Camera Channel Event/Action init */
  158. for (int chn = 0; chn < CSI_CAMERA_CHANNEL_MAX_COUNT; chn++) {
  159. for (int i = 0; i < CSI_CAMERA_CHANNEL_EVENT_MAX_COUNT; i++) {
  160. event_action = &(session->channel_event_action[chn][i]);
  161. event_action->target = MANAGE_TARGET_CHANNEL;
  162. event_action->channel.event = 1 << i;
  163. event_action->channel.supported = false;
  164. event_action->channel.subscribed = false;
  165. event_action->channel.action = CAMERA_CHANNEL_ACTION_NONE;
  166. }
  167. }
  168. enum_array = camera_spec_get_enum_array(CAMERA_SPEC_ENUM_CHANNEL_EVENT_TYPES);
  169. for (int i = 0; (enum_array != NULL) && (i < enum_array->count); i++) {
  170. for (int j = 0; j < CSI_CAMERA_CHANNEL_MAX_COUNT; j++) {
  171. for (int k = 0; k < CSI_CAMERA_CHANNEL_MAX_COUNT; k++) {
  172. event_action = &(session->channel_event_action[j][k]);
  173. if (enum_array->enums[i] == event_action->camera.event) {
  174. event_action->camera.supported = true;
  175. //cam_mng_dump_event_action_union(event_action);
  176. }
  177. }
  178. }
  179. }
  180. session->event_action_thread_id = -1;
  181. return 0;
  182. }
  183. int camera_close(cams_t *session)
  184. {
  185. int ret;
  186. _CHECK_SESSION_RETURN();
  187. if (session->event_handle >= 0) {
  188. csi_camera_destory_event(session->event_handle);
  189. session->event_handle = NULL;
  190. }
  191. if (csi_camera_close(session->camera_handle) != 0) {
  192. LOG_E("Close camera() failed\n");
  193. return -1;
  194. }
  195. _camera_session_reset(session);
  196. session->state = CAMERA_STATE_CLOSED;
  197. return 0;
  198. }
  199. int camera_get_modes(cams_t *session)
  200. {
  201. int ret;
  202. _CHECK_SESSION_RETURN();
  203. _CHECK_STATE_RETURN(CAMERA_STATE_OPENED | CAMERA_STATE_MODE_SET);
  204. if (_get_info_status(session, CAMERA_MODES_READY))
  205. return 0;
  206. ret = csi_camera_get_modes(session->camera_handle, &(session->camera_modes));
  207. if (ret != 0) {
  208. LOG_E("csi_camera_get_modes() failed, ret=%d\n", ret);
  209. _set_info_status(session, CAMERA_MODES_READY, false);
  210. return ret;
  211. }
  212. _set_info_status(session, CAMERA_MODES_READY, true);
  213. return 0;
  214. }
  215. int camera_set_mode(cams_t *session, int mode_id)
  216. {
  217. int ret;
  218. _CHECK_SESSION_RETURN();
  219. _CHECK_STATE_RETURN(CAMERA_STATE_OPENED | CAMERA_STATE_MODE_SET);
  220. csi_camera_mode_cfg_s mode_cfg;
  221. mode_cfg.mode_id = mode_id;
  222. mode_cfg.calibriation = NULL; // TODO
  223. mode_cfg.lib3a = NULL; // TODO
  224. ret = csi_camera_set_mode(session->camera_handle, &mode_cfg);
  225. if (ret != 0) {
  226. LOG_E("csi_camera_set_mode() failed, ret=%d\n", ret);
  227. return ret;
  228. }
  229. session->state = CAMERA_STATE_MODE_SET;
  230. return 0;
  231. }
  232. int camera_query_property(cams_t *session,
  233. csi_camera_property_description_s *description)
  234. {
  235. _CHECK_SESSION_RETURN();
  236. _CHECK_STATE_RETURN(CAMERA_STATE_OPENED | CAMERA_STATE_MODE_SET);
  237. return csi_camera_query_property(session->camera_handle, description);
  238. }
  239. int camera_set_property(cams_t *session, csi_camera_properties_s *properties)
  240. {
  241. _CHECK_SESSION_RETURN();
  242. _CHECK_STATE_RETURN(CAMERA_STATE_OPENED|CAMERA_STATE_MODE_SET|CAMERA_STATE_RUNNING);
  243. return csi_camera_set_property(session->camera_handle, properties);
  244. }
  245. int camera_channel_query_list(cams_t *session)
  246. {
  247. int ret;
  248. _CHECK_SESSION_RETURN();
  249. _CHECK_STATE_RETURN(CAMERA_STATE_OPENED | CAMERA_STATE_MODE_SET |
  250. CAMERA_STATE_RUNNING);
  251. // Init channel's ID and Status
  252. if (! _get_info_status(session, CHANNEL_INIT_READY)) {
  253. for (int i = CSI_CAMERA_CHANNEL_0; i < CSI_CAMERA_CHANNEL_MAX_COUNT; i++) {
  254. session->chn_cfg[i].chn_id = i; // CSI_CAMERA_CHANNEL_x
  255. session->chn_cfg[i].status = CSI_CAMERA_CHANNEL_INVALID;
  256. }
  257. }
  258. for (int i = CSI_CAMERA_CHANNEL_0; i < CSI_CAMERA_CHANNEL_MAX_COUNT; i++) {
  259. if (_get_info_status(session, CHANNEL_INIT_READY)) {
  260. if (session->chn_cfg[i].status == CSI_CAMERA_CHANNEL_INVALID) {
  261. continue;
  262. }
  263. }
  264. ret = csi_camera_channel_query(session->camera_handle, &session->chn_cfg[i]);
  265. if (ret != 0) {
  266. LOG_E("Get %d channel configuration from camera[%s] failed\n",
  267. i, session->camera_infos.info->device_name);
  268. continue;
  269. } else {
  270. //LOG_D("channel[%d] status=%s\n", session->chn_cfg[i].chn_id,
  271. // camera_string_chn_status(session->chn_cfg[i].status));
  272. }
  273. }
  274. _set_info_status(session, CHANNEL_INIT_READY, true);
  275. return 0;
  276. }
  277. int camera_channel_open(cams_t *session, csi_camera_channel_cfg_s *chn_cfg)
  278. {
  279. int ret;
  280. _CHECK_SESSION_RETURN();
  281. _CHECK_STATE_RETURN(CAMERA_STATE_OPENED | CAMERA_STATE_MODE_SET |
  282. CAMERA_STATE_RUNNING);
  283. if (! _get_info_status(session, CHANNEL_INIT_READY)) {
  284. camera_channel_query_list(session);
  285. }
  286. int chn_id = chn_cfg->chn_id;
  287. csi_camera_channel_cfg_s *channel = &(session->chn_cfg[chn_id]);
  288. if (channel->status != CSI_CAMERA_CHANNEL_CLOSED) {
  289. LOG_E("Channel[%d] status(%d) is not CLOSED\n",
  290. chn_id, channel->status);
  291. return -1;
  292. }
  293. ret = csi_camera_channel_open(session->camera_handle, chn_cfg);
  294. if (ret != 0) {
  295. LOG_E("Open channel(%d) failed, ret=%d\n", chn_id, ret);
  296. return -1;
  297. }
  298. // Update session->chn_cfg
  299. csi_camera_channel_query(session->camera_handle,
  300. &(session->chn_cfg[chn_cfg->chn_id]));
  301. LOG_I("Open channel[%d] OK\n", chn_id);
  302. return 0;
  303. }
  304. int camera_channel_close(cams_t *session, csi_camera_channel_id_e chn_id)
  305. {
  306. int ret;
  307. _CHECK_SESSION_RETURN();
  308. _CHECK_STATE_RETURN(CAMERA_STATE_OPENED | CAMERA_STATE_MODE_SET |
  309. CAMERA_STATE_RUNNING);
  310. csi_camera_channel_cfg_s *channel = &(session->chn_cfg[chn_id]);
  311. if (channel->status != CSI_CAMERA_CHANNEL_OPENED) {
  312. LOG_E("Channel[%d] status(%d) is not CLOSED\n",
  313. chn_id, channel->status);
  314. return -1;
  315. }
  316. ret = csi_camera_channel_close(session->camera_handle, chn_id);
  317. if (ret != 0) {
  318. LOG_E("Close channel(%d) failed, ret=%d\n", chn_id, ret);
  319. return -1;
  320. }
  321. LOG_I("Close channel[%d] OK\n", chn_id);
  322. return 0;
  323. }
  324. int camera_subscribe_event(cams_t *session)
  325. {
  326. int ret;
  327. struct csi_camera_event_subscription subscribe;
  328. camera_event_action_union_t *event_action;
  329. _CHECK_SESSION_RETURN();
  330. _CHECK_STATE_RETURN(CAMERA_STATE_OPENED | CAMERA_STATE_MODE_SET);
  331. for (int i = 0; i < CSI_CAMERA_EVENT_MAX_COUNT; i++) {
  332. event_action = &session->camera_event_action[i];
  333. if (!event_action->camera.supported) {
  334. LOG_D("Camera event(%08x) is not supported\n",
  335. event_action->camera.event);
  336. continue;
  337. }
  338. LOG_D("Camera event(%08x) is supported\n", event_action->camera.event);
  339. subscribe.type = CSI_CAMERA_EVENT_TYPE_CAMERA;
  340. subscribe.id = event_action->camera.event;
  341. if (event_action->camera.subscribed) {
  342. ret = csi_camera_subscribe_event(session->event_handle, &subscribe);
  343. if (ret == 0)
  344. LOG_D("subscribe_event(type=CAMERA, id=0x%08x(%s)) OK\n",
  345. subscribe.id, camera_string_camera_event_type(subscribe.id));
  346. else
  347. LOG_E("subscribe_event(type=CAMERA, id=0x%08x(%s)) Failed\n",
  348. subscribe.id, camera_string_camera_event_type(subscribe.id));
  349. } else {
  350. ret = csi_camera_unsubscribe_event(session->event_handle, &subscribe);
  351. if (ret == 0)
  352. LOG_D("unsubscribe_event(type=CAMERA, id=0x%08x(%s)) OK\n",
  353. subscribe.id, camera_string_camera_event_type(subscribe.id));
  354. else
  355. LOG_E("unsubscribe_event(type=CAMERA, id=0x%08x(%s)) Failed\n",
  356. subscribe.id, camera_string_camera_event_type(subscribe.id));
  357. }
  358. }
  359. for (int chn = 0; chn < CSI_CAMERA_CHANNEL_MAX_COUNT; chn++) {
  360. if (session->chn_cfg[chn].status != CSI_CAMERA_CHANNEL_OPENED) {
  361. LOG_D("Camera[%s]:Channel[%d] is not OPENED\n", session->camera_infos.info->device_name, chn);
  362. continue;
  363. }
  364. for (int i = 0; i < CSI_CAMERA_CHANNEL_EVENT_MAX_COUNT; i++) {
  365. event_action = &session->channel_event_action[chn][i];
  366. if (!event_action->channel.supported) {
  367. LOG_D("channel(%d) event(%08x) is not supported\n",
  368. chn, event_action->channel.event);
  369. continue;
  370. }
  371. LOG_D("channel(%d) event(%08x) is supported\n",
  372. chn, event_action->channel.event);
  373. subscribe.type = CSI_CAMERA_EVENT_TYPE_CHANNEL0 + chn;
  374. subscribe.id = event_action->camera.event;
  375. if (event_action->camera.subscribed) { // FIXME: event_action->camera.subscribed in dialog
  376. ret = csi_camera_subscribe_event(session->event_handle, &subscribe);
  377. if (ret == 0)
  378. LOG_D("subscribe_event(type=CHANNEL%d, id=0x%08x(%s)) OK\n",
  379. chn, subscribe.id, camera_string_channel_event_type(subscribe.id));
  380. else
  381. LOG_E("subscribe_event(type=CHANNEL%d, id=0x%08x(%s)) Failed\n",
  382. chn, subscribe.id, camera_string_channel_event_type(subscribe.id));
  383. } else {
  384. ret = csi_camera_unsubscribe_event(session->event_handle, &subscribe);
  385. if (ret == 0)
  386. LOG_D("unsubscribe_event(type=CHANNEL%d, id=0x%08x(%s)) OK\n",
  387. chn, subscribe.id, camera_string_channel_event_type(subscribe.id));
  388. else
  389. LOG_E("unsubscribe_event(type=CHANNEL%d, id=0x%08x(%s)) Failed\n",
  390. chn, subscribe.id, camera_string_channel_event_type(subscribe.id));
  391. }
  392. }
  393. }
  394. return 0;
  395. }
  396. int camera_register_event_action(cams_t *session,
  397. camera_action_fun_t camera_action_fun,
  398. camera_action_fun_t channel_action_fun)
  399. {
  400. _CHECK_SESSION_RETURN();
  401. ENTER_VOID();
  402. session->camera_action_fun = camera_action_fun;
  403. session->channel_action_fun = channel_action_fun;
  404. return 0;
  405. }
  406. static void *camera_event_action_thread(void *arg)
  407. {
  408. int ret;
  409. cams_t *session = (cams_t *)arg;
  410. LOG_D("pthread start\n");
  411. if (session == NULL) {
  412. LOG_E("session is NULL\n");
  413. return NULL;
  414. }
  415. csi_camera_event_s event;
  416. int timeout = -1; // unit: ms, -1 means wait forever, or until error occurs
  417. int loop_count = 0;
  418. while (camera_thread_flag) {
  419. LOG_D("while(true)...loog_count=%d\n", ++loop_count);
  420. ret = csi_camera_get_event(session->event_handle, &event, timeout);
  421. if (ret != 0) {
  422. LOG_E("csi_camera_get_event() failed, ret=%d\n", ret);
  423. continue;
  424. }
  425. LOG_D("event{.type=%d, .id=%d}\n", event.type, event.id);
  426. if (event.type == CSI_CAMERA_EVENT_TYPE_CAMERA) {
  427. if (session->camera_action_fun != NULL) {
  428. session->camera_action_fun(session, &event);
  429. } else {
  430. LOG_D("session->camera_action_fun is NULL\n");
  431. }
  432. } else if (event.type >= CSI_CAMERA_EVENT_TYPE_CHANNEL0 &&
  433. event.type <= CSI_CAMERA_EVENT_TYPE_CHANNEL7) {
  434. if (session->channel_action_fun != NULL) {
  435. session->channel_action_fun(session, &event);
  436. } else {
  437. LOG_D("session->channel_action_fun is NULL\n");
  438. }
  439. } else {
  440. LOG_E("Unknown event type:%d\n", event.type);
  441. }
  442. }
  443. pthread_exit(NULL);
  444. }
  445. int camera_channel_start(cams_t *session, csi_camera_channel_id_e chn_id)
  446. {
  447. int ret;
  448. _CHECK_SESSION_RETURN();
  449. _CHECK_STATE_RETURN(CAMERA_STATE_OPENED | CAMERA_STATE_MODE_SET);
  450. LOG_D("camera_channel_start = %d\n",chn_id);
  451. ret = csi_camera_channel_start(session->camera_handle, chn_id);
  452. if (ret != 0) {
  453. LOG_E("csi_camera_channel_start() failed, ret=%d", ret);
  454. return -1;
  455. }
  456. // start event action thread
  457. camera_thread_flag = true;
  458. ret = pthread_create(&session->event_action_thread_id, NULL,
  459. (void *)camera_event_action_thread, session);
  460. if (ret != 0) {
  461. LOG_E("pthread_create() failed, ret=%d", ret);
  462. return -1;
  463. }
  464. session->state = CAMERA_STATE_RUNNING;
  465. LOG_D("camera_channel_start(chn_id=%d) OK\n", chn_id);
  466. return ret;
  467. }
  468. int camera_channel_stop(cams_t *session, csi_camera_channel_id_e chn_id)
  469. {
  470. int ret;
  471. _CHECK_SESSION_RETURN();
  472. _CHECK_STATE_RETURN(CAMERA_STATE_RUNNING);
  473. int i = 0;
  474. camera_thread_flag = false;
  475. if (pthread_join(session->event_action_thread_id, NULL)) {
  476. LOG_E("pthread_join() failed, %s\n", strerror(errno));
  477. return -2;
  478. }
  479. session->event_action_thread_id = -1;
  480. LOG_D("pthread canceled\n");
  481. ret = csi_camera_channel_stop(session->camera_handle, chn_id);
  482. if (ret != 0) {
  483. LOG_E("csi_camera_channel_stop() faild, ret=%d\n", ret);
  484. return -1;
  485. }
  486. LOG_D("camera_channel_stop ok\n");
  487. session->state = CAMERA_STATE_OPENED;
  488. return ret;
  489. }