io_pipeline.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635
  1. #include "io_pipeline.h"
  2. #include "camera.h"
  3. #include "device.h"
  4. #include "flash.h"
  5. #include "pipeline.h"
  6. #include "process_pipeline.h"
  7. #include <assert.h>
  8. #include <errno.h>
  9. #include <fcntl.h>
  10. #include <glib.h>
  11. #include <stdio.h>
  12. #include <string.h>
  13. #include <sys/ioctl.h>
  14. struct media_link_info {
  15. unsigned int source_entity_id;
  16. unsigned int target_entity_id;
  17. char source_fname[260];
  18. char target_fname[260];
  19. };
  20. struct camera_info {
  21. size_t device_index;
  22. unsigned int pad_id;
  23. char dev_fname[260];
  24. int fd;
  25. MPCamera *camera;
  26. MPFlash *flash;
  27. int gain_ctrl;
  28. int gain_max;
  29. bool has_auto_focus_continuous;
  30. bool has_auto_focus_start;
  31. // unsigned int entity_id;
  32. // enum v4l2_buf_type type;
  33. // char media_dev_fname[260];
  34. // char video_dev_fname[260];
  35. // int media_fd;
  36. // struct mp_media_link media_links[MP_MAX_LINKS];
  37. // int num_media_links;
  38. // int gain_ctrl;
  39. };
  40. struct device_info {
  41. const char *media_dev_name; // owned by camera config
  42. MPDevice *device;
  43. unsigned int interface_pad_id;
  44. int video_fd;
  45. };
  46. static struct camera_info cameras[MP_MAX_CAMERAS];
  47. static struct device_info devices[MP_MAX_CAMERAS];
  48. static size_t num_devices = 0;
  49. static const struct mp_camera_config *camera = NULL;
  50. static MPCameraMode mode;
  51. static bool just_switched_mode = false;
  52. static int blank_frame_count = 0;
  53. static int burst_length;
  54. static int captures_remaining = 0;
  55. static int preview_width;
  56. static int preview_height;
  57. static int device_rotation;
  58. static bool save_dng;
  59. struct control_state {
  60. bool gain_is_manual;
  61. int gain;
  62. bool exposure_is_manual;
  63. int exposure;
  64. };
  65. static struct control_state desired_controls = {};
  66. static struct control_state current_controls = {};
  67. static bool flash_enabled = false;
  68. static bool want_focus = false;
  69. static MPPipeline *pipeline;
  70. static GSource *capture_source;
  71. static void
  72. setup_camera(MPDeviceList **device_list, const struct mp_camera_config *config)
  73. {
  74. // Find device info
  75. size_t device_index = 0;
  76. for (; device_index < num_devices; ++device_index) {
  77. if (strcmp(config->media_dev_name,
  78. devices[device_index].media_dev_name) == 0) {
  79. break;
  80. }
  81. }
  82. if (device_index == num_devices) {
  83. device_index = num_devices;
  84. // Initialize new device
  85. struct device_info *info = &devices[device_index];
  86. info->media_dev_name = config->media_dev_name;
  87. info->device = mp_device_list_find_remove(device_list,
  88. info->media_dev_name);
  89. if (!info->device) {
  90. g_printerr("Could not find /dev/media* node matching '%s'\n",
  91. info->media_dev_name);
  92. exit(EXIT_FAILURE);
  93. }
  94. const struct media_v2_entity *entity =
  95. mp_device_find_entity_type(info->device, MEDIA_ENT_F_IO_V4L);
  96. if (!entity) {
  97. g_printerr("Could not find device video entity\n");
  98. exit(EXIT_FAILURE);
  99. }
  100. const struct media_v2_pad *pad =
  101. mp_device_get_pad_from_entity(info->device, entity->id);
  102. info->interface_pad_id = pad->id;
  103. const struct media_v2_interface *interface =
  104. mp_device_find_entity_interface(info->device, entity->id);
  105. char dev_name[260];
  106. if (!mp_find_device_path(interface->devnode, dev_name, 260)) {
  107. g_printerr("Could not find video path\n");
  108. exit(EXIT_FAILURE);
  109. }
  110. info->video_fd = open(dev_name, O_RDWR);
  111. if (info->video_fd == -1) {
  112. g_printerr("Could not open %s: %s\n",
  113. dev_name,
  114. strerror(errno));
  115. exit(EXIT_FAILURE);
  116. }
  117. ++num_devices;
  118. }
  119. {
  120. struct camera_info *info = &cameras[config->index];
  121. struct device_info *dev_info = &devices[device_index];
  122. info->device_index = device_index;
  123. const struct media_v2_entity *entity =
  124. mp_device_find_entity(dev_info->device, config->dev_name);
  125. if (!entity) {
  126. g_printerr("Could not find camera entity matching '%s'\n",
  127. config->dev_name);
  128. exit(EXIT_FAILURE);
  129. }
  130. const struct media_v2_pad *pad =
  131. mp_device_get_pad_from_entity(dev_info->device, entity->id);
  132. info->pad_id = pad->id;
  133. // Make sure the camera starts out as disabled
  134. mp_device_setup_link(dev_info->device,
  135. info->pad_id,
  136. dev_info->interface_pad_id,
  137. false);
  138. const struct media_v2_interface *interface =
  139. mp_device_find_entity_interface(dev_info->device,
  140. entity->id);
  141. if (!mp_find_device_path(interface->devnode, info->dev_fname, 260)) {
  142. g_printerr("Could not find camera device path\n");
  143. exit(EXIT_FAILURE);
  144. }
  145. info->fd = open(info->dev_fname, O_RDWR);
  146. if (info->fd == -1) {
  147. g_printerr("Could not open %s: %s\n",
  148. info->dev_fname,
  149. strerror(errno));
  150. exit(EXIT_FAILURE);
  151. }
  152. info->camera = mp_camera_new(dev_info->video_fd, info->fd);
  153. // Start with the capture format, this works around a bug with
  154. // the ov5640 driver where it won't allow setting the preview
  155. // format initially.
  156. MPCameraMode mode = config->capture_mode;
  157. mp_camera_set_mode(info->camera, &mode);
  158. // Trigger continuous auto focus if the sensor supports it
  159. if (mp_camera_query_control(
  160. info->camera, V4L2_CID_FOCUS_AUTO, NULL)) {
  161. info->has_auto_focus_continuous = true;
  162. mp_camera_control_set_bool_bg(
  163. info->camera, V4L2_CID_FOCUS_AUTO, true);
  164. }
  165. if (mp_camera_query_control(
  166. info->camera, V4L2_CID_AUTO_FOCUS_START, NULL)) {
  167. info->has_auto_focus_start = true;
  168. }
  169. MPControl control;
  170. if (mp_camera_query_control(info->camera, V4L2_CID_GAIN, &control)) {
  171. info->gain_ctrl = V4L2_CID_GAIN;
  172. info->gain_max = control.max;
  173. } else if (mp_camera_query_control(
  174. info->camera, V4L2_CID_ANALOGUE_GAIN, &control)) {
  175. info->gain_ctrl = V4L2_CID_ANALOGUE_GAIN;
  176. info->gain_max = control.max;
  177. }
  178. // Setup flash
  179. if (config->flash_path[0]) {
  180. info->flash = mp_led_flash_from_path(config->flash_path);
  181. } else if (config->flash_display) {
  182. info->flash = mp_create_display_flash();
  183. } else {
  184. info->flash = NULL;
  185. }
  186. }
  187. }
  188. static void
  189. setup(MPPipeline *pipeline, const void *data)
  190. {
  191. MPDeviceList *device_list = mp_device_list_new();
  192. for (size_t i = 0; i < MP_MAX_CAMERAS; ++i) {
  193. const struct mp_camera_config *config = mp_get_camera_config(i);
  194. if (!config) {
  195. break;
  196. }
  197. setup_camera(&device_list, config);
  198. }
  199. mp_device_list_free(device_list);
  200. }
  201. static void
  202. clean_cameras()
  203. {
  204. for (size_t i = 0; i < MP_MAX_CAMERAS; ++i) {
  205. struct camera_info *info = &cameras[i];
  206. if (info->camera) {
  207. mp_camera_free(info->camera);
  208. info->camera = NULL;
  209. }
  210. }
  211. }
  212. void
  213. mp_io_pipeline_start()
  214. {
  215. mp_process_pipeline_start();
  216. pipeline = mp_pipeline_new();
  217. mp_pipeline_invoke(pipeline, setup, NULL, 0);
  218. }
  219. void
  220. mp_io_pipeline_stop()
  221. {
  222. if (capture_source) {
  223. g_source_destroy(capture_source);
  224. }
  225. clean_cameras();
  226. mp_pipeline_free(pipeline);
  227. mp_process_pipeline_stop();
  228. }
  229. static void
  230. update_process_pipeline()
  231. {
  232. struct camera_info *info = &cameras[camera->index];
  233. // Grab the latest control values
  234. if (!current_controls.gain_is_manual) {
  235. current_controls.gain =
  236. mp_camera_control_get_int32(info->camera, info->gain_ctrl);
  237. }
  238. if (!current_controls.exposure_is_manual) {
  239. current_controls.exposure =
  240. mp_camera_control_get_int32(info->camera, V4L2_CID_EXPOSURE);
  241. }
  242. struct mp_process_pipeline_state pipeline_state = {
  243. .camera = camera,
  244. .mode = mode,
  245. .burst_length = burst_length,
  246. .save_dng = save_dng,
  247. .preview_width = preview_width,
  248. .preview_height = preview_height,
  249. .device_rotation = device_rotation,
  250. .gain_is_manual = current_controls.gain_is_manual,
  251. .gain = current_controls.gain,
  252. .gain_max = info->gain_max,
  253. .exposure_is_manual = current_controls.exposure_is_manual,
  254. .exposure = current_controls.exposure,
  255. .has_auto_focus_continuous = info->has_auto_focus_continuous,
  256. .has_auto_focus_start = info->has_auto_focus_start,
  257. };
  258. mp_process_pipeline_update_state(&pipeline_state);
  259. }
  260. static void
  261. focus(MPPipeline *pipeline, const void *data)
  262. {
  263. want_focus = true;
  264. }
  265. void
  266. mp_io_pipeline_focus()
  267. {
  268. mp_pipeline_invoke(pipeline, focus, NULL, 0);
  269. }
  270. static void
  271. capture(MPPipeline *pipeline, const void *data)
  272. {
  273. struct camera_info *info = &cameras[camera->index];
  274. captures_remaining = burst_length;
  275. // Disable the autogain/exposure while taking the burst
  276. mp_camera_control_set_int32(info->camera, V4L2_CID_AUTOGAIN, 0);
  277. mp_camera_control_set_int32(
  278. info->camera, V4L2_CID_EXPOSURE_AUTO, V4L2_EXPOSURE_MANUAL);
  279. // Change camera mode for capturing
  280. mp_process_pipeline_sync();
  281. mp_camera_stop_capture(info->camera);
  282. mode = camera->capture_mode;
  283. mp_camera_set_mode(info->camera, &mode);
  284. just_switched_mode = true;
  285. mp_camera_start_capture(info->camera);
  286. // Enable flash
  287. if (info->flash && flash_enabled) {
  288. mp_flash_enable(info->flash);
  289. }
  290. update_process_pipeline();
  291. mp_process_pipeline_capture();
  292. }
  293. void
  294. mp_io_pipeline_capture()
  295. {
  296. mp_pipeline_invoke(pipeline, capture, NULL, 0);
  297. }
  298. static void
  299. release_buffer(MPPipeline *pipeline, const uint32_t *buffer_index)
  300. {
  301. struct camera_info *info = &cameras[camera->index];
  302. mp_camera_release_buffer(info->camera, *buffer_index);
  303. }
  304. void
  305. mp_io_pipeline_release_buffer(uint32_t buffer_index)
  306. {
  307. mp_pipeline_invoke(pipeline,
  308. (MPPipelineCallback)release_buffer,
  309. &buffer_index,
  310. sizeof(uint32_t));
  311. }
  312. static pid_t focus_continuous_task = 0;
  313. static pid_t start_focus_task = 0;
  314. static void
  315. start_focus(struct camera_info *info)
  316. {
  317. // only run 1 manual focus at once
  318. if (!mp_camera_check_task_complete(info->camera, start_focus_task) ||
  319. !mp_camera_check_task_complete(info->camera, focus_continuous_task))
  320. return;
  321. if (info->has_auto_focus_continuous) {
  322. focus_continuous_task = mp_camera_control_set_bool_bg(
  323. info->camera, V4L2_CID_FOCUS_AUTO, 1);
  324. } else if (info->has_auto_focus_start) {
  325. start_focus_task = mp_camera_control_set_bool_bg(
  326. info->camera, V4L2_CID_AUTO_FOCUS_START, 1);
  327. }
  328. }
  329. static void
  330. update_controls()
  331. {
  332. // Don't update controls while capturing
  333. if (captures_remaining > 0) {
  334. return;
  335. }
  336. struct camera_info *info = &cameras[camera->index];
  337. if (want_focus) {
  338. start_focus(info);
  339. want_focus = false;
  340. }
  341. if (current_controls.gain_is_manual != desired_controls.gain_is_manual) {
  342. mp_camera_control_set_bool_bg(info->camera,
  343. V4L2_CID_AUTOGAIN,
  344. !desired_controls.gain_is_manual);
  345. }
  346. if (desired_controls.gain_is_manual &&
  347. current_controls.gain != desired_controls.gain) {
  348. mp_camera_control_set_int32_bg(
  349. info->camera, info->gain_ctrl, desired_controls.gain);
  350. }
  351. if (current_controls.exposure_is_manual !=
  352. desired_controls.exposure_is_manual) {
  353. mp_camera_control_set_int32_bg(info->camera,
  354. V4L2_CID_EXPOSURE_AUTO,
  355. desired_controls.exposure_is_manual ?
  356. V4L2_EXPOSURE_MANUAL :
  357. V4L2_EXPOSURE_AUTO);
  358. }
  359. if (desired_controls.exposure_is_manual &&
  360. current_controls.exposure != desired_controls.exposure) {
  361. mp_camera_control_set_int32_bg(
  362. info->camera, V4L2_CID_EXPOSURE, desired_controls.exposure);
  363. }
  364. current_controls = desired_controls;
  365. }
  366. static void
  367. on_frame(MPBuffer buffer, void *_data)
  368. {
  369. // Only update controls right after a frame was captured
  370. update_controls();
  371. // When the mode is switched while capturing we get a couple blank frames,
  372. // presumably from buffers made ready during the switch. Ignore these.
  373. if (just_switched_mode) {
  374. if (blank_frame_count < 20) {
  375. // Only check a 10x10 area
  376. size_t test_size =
  377. MIN(10, mode.width) * MIN(10, mode.height);
  378. bool image_is_blank = true;
  379. for (size_t i = 0; i < test_size; ++i) {
  380. if (buffer.data[i] != 0) {
  381. image_is_blank = false;
  382. }
  383. }
  384. if (image_is_blank) {
  385. ++blank_frame_count;
  386. return;
  387. }
  388. } else {
  389. printf("Blank image limit reached, resulting capture may be blank\n");
  390. }
  391. just_switched_mode = false;
  392. blank_frame_count = 0;
  393. }
  394. // Send the image off for processing
  395. mp_process_pipeline_process_image(buffer);
  396. if (captures_remaining > 0) {
  397. --captures_remaining;
  398. if (captures_remaining == 0) {
  399. struct camera_info *info = &cameras[camera->index];
  400. // Restore the auto exposure and gain if needed
  401. if (!current_controls.exposure_is_manual) {
  402. mp_camera_control_set_int32_bg(
  403. info->camera,
  404. V4L2_CID_EXPOSURE_AUTO,
  405. V4L2_EXPOSURE_AUTO);
  406. }
  407. if (!current_controls.gain_is_manual) {
  408. mp_camera_control_set_bool_bg(
  409. info->camera, V4L2_CID_AUTOGAIN, true);
  410. }
  411. // Go back to preview mode
  412. mp_process_pipeline_sync();
  413. mp_camera_stop_capture(info->camera);
  414. mode = camera->preview_mode;
  415. mp_camera_set_mode(info->camera, &mode);
  416. just_switched_mode = true;
  417. mp_camera_start_capture(info->camera);
  418. // Disable flash
  419. if (info->flash) {
  420. mp_flash_disable(info->flash);
  421. }
  422. update_process_pipeline();
  423. }
  424. }
  425. }
  426. static void
  427. update_state(MPPipeline *pipeline, const struct mp_io_pipeline_state *state)
  428. {
  429. // Make sure the state isn't updated more than it needs to be by checking
  430. // whether this state change actually changes anything.
  431. bool has_changed = false;
  432. if (camera != state->camera) {
  433. has_changed = true;
  434. if (camera) {
  435. struct camera_info *info = &cameras[camera->index];
  436. struct device_info *dev_info = &devices[info->device_index];
  437. mp_process_pipeline_sync();
  438. mp_camera_stop_capture(info->camera);
  439. mp_device_setup_link(dev_info->device,
  440. info->pad_id,
  441. dev_info->interface_pad_id,
  442. false);
  443. }
  444. if (capture_source) {
  445. g_source_destroy(capture_source);
  446. capture_source = NULL;
  447. }
  448. camera = state->camera;
  449. if (camera) {
  450. struct camera_info *info = &cameras[camera->index];
  451. struct device_info *dev_info = &devices[info->device_index];
  452. mp_device_setup_link(dev_info->device,
  453. info->pad_id,
  454. dev_info->interface_pad_id,
  455. true);
  456. mode = camera->preview_mode;
  457. mp_camera_set_mode(info->camera, &mode);
  458. mp_camera_start_capture(info->camera);
  459. capture_source = mp_pipeline_add_capture_source(
  460. pipeline, info->camera, on_frame, NULL);
  461. current_controls.gain_is_manual =
  462. mp_camera_control_get_bool(info->camera,
  463. V4L2_CID_AUTOGAIN) == 0;
  464. current_controls.gain = mp_camera_control_get_int32(
  465. info->camera, info->gain_ctrl);
  466. current_controls.exposure_is_manual =
  467. mp_camera_control_get_int32(
  468. info->camera, V4L2_CID_EXPOSURE_AUTO) ==
  469. V4L2_EXPOSURE_MANUAL;
  470. current_controls.exposure = mp_camera_control_get_int32(
  471. info->camera, V4L2_CID_EXPOSURE);
  472. }
  473. }
  474. has_changed = has_changed || burst_length != state->burst_length ||
  475. preview_width != state->preview_width ||
  476. preview_height != state->preview_height ||
  477. device_rotation != state->device_rotation;
  478. burst_length = state->burst_length;
  479. preview_width = state->preview_width;
  480. preview_height = state->preview_height;
  481. device_rotation = state->device_rotation;
  482. save_dng = state->save_dng;
  483. if (camera) {
  484. struct control_state previous_desired = desired_controls;
  485. desired_controls.gain_is_manual = state->gain_is_manual;
  486. desired_controls.gain = state->gain;
  487. desired_controls.exposure_is_manual = state->exposure_is_manual;
  488. desired_controls.exposure = state->exposure;
  489. has_changed = has_changed ||
  490. memcmp(&previous_desired,
  491. &desired_controls,
  492. sizeof(struct control_state)) != 0 ||
  493. flash_enabled != state->flash_enabled;
  494. flash_enabled = state->flash_enabled;
  495. }
  496. assert(has_changed);
  497. update_process_pipeline();
  498. }
  499. void
  500. mp_io_pipeline_update_state(const struct mp_io_pipeline_state *state)
  501. {
  502. mp_pipeline_invoke(pipeline,
  503. (MPPipelineCallback)update_state,
  504. state,
  505. sizeof(struct mp_io_pipeline_state));
  506. }