io_pipeline.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505
  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. struct control_state {
  56. bool gain_is_manual;
  57. int gain;
  58. bool exposure_is_manual;
  59. int exposure;
  60. };
  61. static struct control_state desired_controls = {};
  62. static struct control_state current_controls = {};
  63. static bool want_focus = false;
  64. static MPPipeline *pipeline;
  65. static GSource *capture_source;
  66. static void setup_camera(MPDeviceList **device_list, const struct mp_camera_config *config)
  67. {
  68. // Find device info
  69. size_t device_index = 0;
  70. for (; device_index < num_devices; ++device_index) {
  71. if (strcmp(config->media_dev_name, devices[device_index].media_dev_name) == 0) {
  72. break;
  73. }
  74. }
  75. if (device_index == num_devices)
  76. {
  77. device_index = num_devices;
  78. // Initialize new device
  79. struct device_info *info = &devices[device_index];
  80. info->media_dev_name = config->media_dev_name;
  81. info->device = mp_device_list_find_remove(device_list, info->media_dev_name);
  82. if (!info->device) {
  83. g_printerr("Could not find /dev/media* node matching '%s'\n", info->media_dev_name);
  84. exit(EXIT_FAILURE);
  85. }
  86. const struct media_v2_entity *entity = mp_device_find_entity(info->device, info->media_dev_name);
  87. if (!entity) {
  88. g_printerr("Count not find device video entity\n");
  89. exit(EXIT_FAILURE);
  90. }
  91. const struct media_v2_pad *pad = mp_device_get_pad_from_entity(info->device, entity->id);
  92. info->interface_pad_id = pad->id;
  93. const struct media_v2_interface *interface = mp_device_find_entity_interface(info->device, entity->id);
  94. char dev_name[260];
  95. if (!mp_find_device_path(interface->devnode, dev_name, 260)) {
  96. g_printerr("Count not find video path\n");
  97. exit(EXIT_FAILURE);
  98. }
  99. info->video_fd = open(dev_name, O_RDWR);
  100. if (info->video_fd == -1) {
  101. g_printerr("Could not open %s\n", dev_name);
  102. exit(EXIT_FAILURE);
  103. }
  104. ++num_devices;
  105. }
  106. {
  107. struct camera_info *info = &cameras[config->index];
  108. struct device_info *dev_info = &devices[device_index];
  109. info->device_index = device_index;
  110. const struct media_v2_entity *entity = mp_device_find_entity(dev_info->device, config->dev_name);
  111. if (!entity) {
  112. g_printerr("Count not find camera entity matching '%s'\n", config->dev_name);
  113. exit(EXIT_FAILURE);
  114. }
  115. const struct media_v2_pad *pad = mp_device_get_pad_from_entity(dev_info->device, entity->id);
  116. info->pad_id = pad->id;
  117. // Make sure the camera starts out as disabled
  118. mp_device_setup_link(
  119. dev_info->device,
  120. info->pad_id,
  121. dev_info->interface_pad_id,
  122. false);
  123. const struct media_v2_interface *interface = mp_device_find_entity_interface(dev_info->device, entity->id);
  124. if (!mp_find_device_path(interface->devnode, info->dev_fname, 260)) {
  125. g_printerr("Count not find camera device path\n");
  126. exit(EXIT_FAILURE);
  127. }
  128. info->fd = open(info->dev_fname, O_RDWR);
  129. if (info->fd == -1) {
  130. g_printerr("Could not open %s\n", info->dev_fname);
  131. exit(EXIT_FAILURE);
  132. }
  133. info->camera = mp_camera_new(dev_info->video_fd, info->fd);
  134. // Trigger continuous auto focus if the sensor supports it
  135. if (mp_camera_query_control(info->camera, V4L2_CID_FOCUS_AUTO, NULL)) {
  136. info->has_auto_focus_continuous = true;
  137. mp_camera_control_set_bool(info->camera, V4L2_CID_FOCUS_AUTO, true);
  138. }
  139. if (mp_camera_query_control(info->camera, V4L2_CID_AUTO_FOCUS_START, NULL)) {
  140. info->has_auto_focus_start = true;
  141. }
  142. MPControl control;
  143. if (mp_camera_query_control(info->camera, V4L2_CID_GAIN, &control)) {
  144. info->gain_ctrl = V4L2_CID_GAIN;
  145. info->gain_max = control.max;
  146. }
  147. else if (mp_camera_query_control(info->camera, V4L2_CID_ANALOGUE_GAIN, &control)) {
  148. info->gain_ctrl = V4L2_CID_ANALOGUE_GAIN;
  149. info->gain_max = control.max;
  150. }
  151. }
  152. }
  153. static void setup(MPPipeline *pipeline, const void *data)
  154. {
  155. MPDeviceList *device_list = mp_device_list_new();
  156. for (size_t i = 0; i < MP_MAX_CAMERAS; ++i) {
  157. const struct mp_camera_config *config = mp_get_camera_config(i);
  158. if (!config) {
  159. break;
  160. }
  161. setup_camera(&device_list, config);
  162. }
  163. mp_device_list_free(device_list);
  164. }
  165. void mp_io_pipeline_start()
  166. {
  167. mp_process_pipeline_start();
  168. pipeline = mp_pipeline_new();
  169. mp_pipeline_invoke(pipeline, setup, NULL, 0);
  170. }
  171. void mp_io_pipeline_stop()
  172. {
  173. if (capture_source) {
  174. g_source_destroy(capture_source);
  175. }
  176. mp_pipeline_free(pipeline);
  177. mp_process_pipeline_stop();
  178. }
  179. static void
  180. update_process_pipeline()
  181. {
  182. struct camera_info *info = &cameras[camera->index];
  183. // Grab the latest control values
  184. if (!current_controls.gain_is_manual) {
  185. current_controls.gain = mp_camera_control_get_int32(info->camera, info->gain_ctrl);
  186. }
  187. if (!current_controls.exposure_is_manual) {
  188. current_controls.exposure = mp_camera_control_get_int32(info->camera, V4L2_CID_EXPOSURE);
  189. }
  190. struct mp_process_pipeline_state pipeline_state = {
  191. .camera = camera,
  192. .mode = mode,
  193. .burst_length = burst_length,
  194. .preview_width = preview_width,
  195. .preview_height = preview_height,
  196. .gain_is_manual = current_controls.gain_is_manual,
  197. .gain = current_controls.gain,
  198. .gain_max = info->gain_max,
  199. .exposure_is_manual = current_controls.exposure_is_manual,
  200. .exposure = current_controls.exposure,
  201. .has_auto_focus_continuous = info->has_auto_focus_continuous,
  202. .has_auto_focus_start = info->has_auto_focus_start,
  203. };
  204. mp_process_pipeline_update_state(&pipeline_state);
  205. }
  206. static void
  207. focus(MPPipeline *pipeline, const void *data)
  208. {
  209. want_focus = true;
  210. }
  211. void mp_io_pipeline_focus()
  212. {
  213. mp_pipeline_invoke(pipeline, focus, NULL, 0);
  214. }
  215. static void
  216. capture(MPPipeline *pipeline, const void *data)
  217. {
  218. struct camera_info *info = &cameras[camera->index];
  219. captures_remaining = burst_length;
  220. // Disable the autogain/exposure while taking the burst
  221. mp_camera_control_set_int32(info->camera, V4L2_CID_AUTOGAIN, 0);
  222. mp_camera_control_set_int32(info->camera, V4L2_CID_EXPOSURE_AUTO, V4L2_EXPOSURE_MANUAL);
  223. // Change camera mode for capturing
  224. mp_camera_stop_capture(info->camera);
  225. mode = camera->capture_mode;
  226. mp_camera_set_mode(info->camera, &mode);
  227. just_switched_mode = true;
  228. mp_camera_start_capture(info->camera);
  229. update_process_pipeline();
  230. mp_process_pipeline_capture();
  231. }
  232. void mp_io_pipeline_capture()
  233. {
  234. mp_pipeline_invoke(pipeline, capture, NULL, 0);
  235. }
  236. static void
  237. update_controls()
  238. {
  239. // Don't update controls while capturing
  240. if (captures_remaining > 0) {
  241. return;
  242. }
  243. struct camera_info *info = &cameras[camera->index];
  244. if (want_focus) {
  245. if (info->has_auto_focus_continuous) {
  246. mp_camera_control_set_bool(info->camera, V4L2_CID_FOCUS_AUTO, 1);
  247. } else if (info->has_auto_focus_start) {
  248. mp_camera_control_set_bool(info->camera, V4L2_CID_AUTO_FOCUS_START, 1);
  249. }
  250. want_focus = false;
  251. }
  252. if (current_controls.gain_is_manual != desired_controls.gain_is_manual) {
  253. mp_camera_control_set_bool(info->camera, V4L2_CID_AUTOGAIN, !desired_controls.gain_is_manual);
  254. }
  255. if (desired_controls.gain_is_manual && current_controls.gain != desired_controls.gain) {
  256. mp_camera_control_set_int32(info->camera, info->gain_ctrl, desired_controls.gain);
  257. }
  258. if (current_controls.exposure_is_manual != desired_controls.exposure_is_manual) {
  259. mp_camera_control_set_int32(
  260. info->camera,
  261. V4L2_CID_EXPOSURE_AUTO,
  262. desired_controls.exposure_is_manual ? V4L2_EXPOSURE_MANUAL : V4L2_EXPOSURE_AUTO);
  263. }
  264. if (desired_controls.exposure_is_manual && current_controls.exposure != desired_controls.exposure) {
  265. mp_camera_control_set_int32(info->camera, V4L2_CID_EXPOSURE, desired_controls.exposure);
  266. }
  267. current_controls = desired_controls;
  268. }
  269. static void
  270. on_frame(MPImage image, void *data)
  271. {
  272. // Only update controls right after a frame was captured
  273. update_controls();
  274. // When the mode is switched while capturing we get a couple blank frames,
  275. // presumably from buffers made ready during the switch. Ignore these.
  276. if (just_switched_mode)
  277. {
  278. if (blank_frame_count < 20) {
  279. // Only check a 50x50 area
  280. size_t test_size = MIN(50, image.width) * MIN(50, image.height);
  281. bool image_is_blank = true;
  282. for (size_t i = 0; i < test_size; ++i) {
  283. if (image.data[i] != 0) {
  284. image_is_blank = false;
  285. }
  286. }
  287. if (image_is_blank) {
  288. ++blank_frame_count;
  289. return;
  290. }
  291. } else {
  292. printf("Blank image limit reached, resulting capture may be blank\n");
  293. }
  294. just_switched_mode = false;
  295. blank_frame_count = 0;
  296. }
  297. // Copy from the camera buffer
  298. size_t size = mp_pixel_format_width_to_bytes(image.pixel_format, image.width) * image.height;
  299. uint8_t *buffer = malloc(size);
  300. memcpy(buffer, image.data, size);
  301. image.data = buffer;
  302. // Send the image off for processing
  303. mp_process_pipeline_process_image(image);
  304. if (captures_remaining > 0) {
  305. --captures_remaining;
  306. if (captures_remaining == 0) {
  307. struct camera_info *info = &cameras[camera->index];
  308. // Restore the auto exposure and gain if needed
  309. if (!current_controls.exposure_is_manual) {
  310. mp_camera_control_set_int32(info->camera, V4L2_CID_EXPOSURE_AUTO, V4L2_EXPOSURE_AUTO);
  311. }
  312. if (!current_controls.gain_is_manual) {
  313. mp_camera_control_set_bool(info->camera, V4L2_CID_AUTOGAIN, true);
  314. }
  315. // Go back to preview mode
  316. mp_camera_stop_capture(info->camera);
  317. mode = camera->preview_mode;
  318. mp_camera_set_mode(info->camera, &mode);
  319. just_switched_mode = true;
  320. mp_camera_start_capture(info->camera);
  321. update_process_pipeline();
  322. }
  323. }
  324. }
  325. static void
  326. update_state(MPPipeline *pipeline, const struct mp_io_pipeline_state *state)
  327. {
  328. // Make sure the state isn't updated more than it needs to be by checking
  329. // whether this state change actually changes anything.
  330. bool has_changed = false;
  331. if (camera != state->camera) {
  332. has_changed = true;
  333. if (camera) {
  334. struct camera_info *info = &cameras[camera->index];
  335. struct device_info *dev_info = &devices[info->device_index];
  336. mp_camera_stop_capture(info->camera);
  337. mp_device_setup_link(
  338. dev_info->device,
  339. info->pad_id,
  340. dev_info->interface_pad_id,
  341. false);
  342. }
  343. if (capture_source) {
  344. g_source_destroy(capture_source);
  345. capture_source = NULL;
  346. }
  347. camera = state->camera;
  348. if (camera) {
  349. struct camera_info *info = &cameras[camera->index];
  350. struct device_info *dev_info = &devices[info->device_index];
  351. mp_device_setup_link(
  352. dev_info->device,
  353. info->pad_id,
  354. dev_info->interface_pad_id,
  355. true);
  356. mode = camera->preview_mode;
  357. mp_camera_set_mode(info->camera, &mode);
  358. mp_camera_start_capture(info->camera);
  359. capture_source = mp_pipeline_add_capture_source(pipeline, info->camera, on_frame, NULL);
  360. current_controls.gain_is_manual = mp_camera_control_get_int32(info->camera, V4L2_CID_EXPOSURE_AUTO) == V4L2_EXPOSURE_MANUAL;
  361. current_controls.gain = mp_camera_control_get_int32(info->camera, info->gain_ctrl);
  362. current_controls.exposure_is_manual = mp_camera_control_get_bool(info->camera, V4L2_CID_AUTOGAIN) == 0;
  363. current_controls.exposure = mp_camera_control_get_int32(info->camera, V4L2_CID_EXPOSURE);
  364. }
  365. }
  366. has_changed = has_changed
  367. || burst_length != state->burst_length
  368. || preview_width != state->preview_width
  369. || preview_height != state->preview_height;
  370. burst_length = state->burst_length;
  371. preview_width = state->preview_width;
  372. preview_height = state->preview_height;
  373. if (camera) {
  374. struct control_state previous_desired = desired_controls;
  375. desired_controls.gain_is_manual = state->gain_is_manual;
  376. desired_controls.gain = state->gain;
  377. desired_controls.exposure_is_manual = state->exposure_is_manual;
  378. desired_controls.exposure = state->exposure;
  379. has_changed = has_changed || memcmp(&previous_desired, &desired_controls, sizeof(struct control_state)) != 0;
  380. }
  381. assert(has_changed);
  382. update_process_pipeline();
  383. }
  384. void mp_io_pipeline_update_state(const struct mp_io_pipeline_state *state)
  385. {
  386. mp_pipeline_invoke(pipeline, (MPPipelineCallback)update_state, state, sizeof(struct mp_io_pipeline_state));
  387. }