io_pipeline.c 14 KB

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