io_pipeline.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632
  1. #include "io_pipeline.h"
  2. #include "camera.h"
  3. #include "flash.h"
  4. #include "main.h"
  5. #include "pipeline.h"
  6. #include "process_pipeline.h"
  7. #include "state.h"
  8. #include <assert.h>
  9. #include <errno.h>
  10. #include <fcntl.h>
  11. #include <glib.h>
  12. #include <math.h>
  13. #include <stdio.h>
  14. #include <string.h>
  15. #include <sys/ioctl.h>
  16. #include <sys/prctl.h>
  17. mp_state_io state_io;
  18. MPCamera *mpcamera = NULL;
  19. static MPPipeline *pipeline;
  20. static GSource *capture_source;
  21. static bool pipeline_changed = true;
  22. typedef struct invoke_set_control {
  23. MPControl *control;
  24. int32_t int_value;
  25. bool bool_value;
  26. } invoke_set_control;
  27. static void
  28. setup(MPPipeline *pipeline, const void *data)
  29. {
  30. prctl(PR_SET_NAME, "megapixels-io", NULL, NULL, NULL);
  31. }
  32. void
  33. mp_io_pipeline_start()
  34. {
  35. mp_process_pipeline_start();
  36. pipeline = mp_pipeline_new();
  37. mp_pipeline_invoke(pipeline, setup, NULL, 0);
  38. }
  39. void
  40. mp_io_pipeline_stop()
  41. {
  42. if (capture_source) {
  43. g_source_destroy(capture_source);
  44. }
  45. mp_pipeline_free(pipeline);
  46. mp_process_pipeline_stop();
  47. }
  48. /*
  49. * Update state from IO -> Process
  50. */
  51. static void
  52. update_process_pipeline()
  53. {
  54. if (!pipeline_changed) {
  55. return;
  56. }
  57. pipeline_changed = false;
  58. // Grab the latest control values
  59. if (!state_io.gain.manual && state_io.gain.control.id) {
  60. state_io.gain.value = mp_camera_control_get_int32(&state_io.gain.control);
  61. }
  62. if (!state_io.exposure.manual && state_io.exposure.control.id) {
  63. state_io.exposure.value = mp_camera_control_get_int32(&state_io.exposure.control);
  64. }
  65. float balance_red = 1.0f;
  66. float balance_blue = 1.0f;
  67. if (state_io.red.control.id && state_io.blue.control.id) {
  68. int red = mp_camera_control_get_int32(&state_io.red.control);
  69. int blue = mp_camera_control_get_int32(&state_io.blue.control);
  70. balance_red = (float)red / (float)state_io.red.max;
  71. balance_blue = (float)blue / (float)state_io.blue.max;
  72. }
  73. mp_state_proc new_state = {
  74. .camera = state_io.camera,
  75. .configuration = state_io.configuration,
  76. .burst_length = state_io.burst_length,
  77. .preview_width = state_io.preview_width,
  78. .preview_height = state_io.preview_height,
  79. .device_rotation = state_io.device_rotation,
  80. .gain.control = state_io.gain.control,
  81. .gain.auto_control = state_io.gain.auto_control,
  82. .gain.value = state_io.gain.value,
  83. .gain.max = state_io.gain.max,
  84. .gain.manual = state_io.gain.manual,
  85. .exposure.control = state_io.exposure.control,
  86. .exposure.auto_control = state_io.exposure.auto_control,
  87. .exposure.value = state_io.exposure.value,
  88. .exposure.max = state_io.exposure.max,
  89. .exposure.manual = state_io.exposure.manual,
  90. .focus.control = state_io.focus.control,
  91. .focus.auto_control = state_io.focus.auto_control,
  92. .focus.value = state_io.focus.value,
  93. .focus.max = state_io.focus.max,
  94. .focus.manual = state_io.focus.manual,
  95. .balance = { balance_red, 1.0f, balance_blue },
  96. .flash_enabled = state_io.flash_enabled,
  97. };
  98. mp_process_pipeline_update_state(&new_state);
  99. }
  100. static void
  101. focus(MPPipeline *pipeline, const void *data)
  102. {
  103. state_io.trigger_af = true;
  104. }
  105. void
  106. mp_io_pipeline_focus()
  107. {
  108. mp_pipeline_invoke(pipeline, focus, NULL, 0);
  109. }
  110. static void
  111. set_control_int32(MPPipeline *pipeline, const void *data)
  112. {
  113. const invoke_set_control *control_data = (const invoke_set_control *)data;
  114. mp_camera_control_set_int32(control_data->control, control_data->int_value);
  115. }
  116. void
  117. mp_io_pipeline_set_control_int32(MPControl *control, uint32_t value)
  118. {
  119. invoke_set_control data = { 0 };
  120. data.control = control;
  121. data.int_value = value;
  122. mp_pipeline_invoke(
  123. pipeline, set_control_int32, &data, sizeof(invoke_set_control));
  124. }
  125. static void
  126. capture(MPPipeline *pipeline, const void *data)
  127. {
  128. float gain_norm;
  129. // Disable the autogain/exposure while taking the burst
  130. mp_camera_control_set_int32(&state_io.gain.auto_control, 0);
  131. mp_camera_control_set_int32(&state_io.exposure.auto_control, V4L2_EXPOSURE_MANUAL);
  132. // Get current gain to calculate a burst length;
  133. // with low gain there's 3, with the max automatic gain of the ov5640
  134. // the value seems to be 248 which creates a 5 frame burst
  135. // for manual gain you can go up to 11 frames
  136. state_io.gain.value =
  137. mp_camera_control_get_int32(&state_io.gain.control);
  138. gain_norm = (float)state_io.gain.value / (float)state_io.gain.max;
  139. state_io.burst_length = (int)fmax(sqrtf(gain_norm) * 10, 2) + 1;
  140. state_io.burst_length = MAX(1, state_io.burst_length);
  141. state_io.captures_remaining = state_io.burst_length;
  142. // Change camera mode for capturing
  143. mp_process_pipeline_sync();
  144. mp_camera_stop_capture(mpcamera);
  145. struct v4l2_format format = { 0 };
  146. libmegapixels_select_mode(state_io.camera, state_io.mode_capture, &format);
  147. state_io.flush_pipeline = true;
  148. mp_camera_start_capture(mpcamera);
  149. // Enable flash
  150. if (state_io.flash_enabled) {
  151. mp_flash_enable(state_io.camera);
  152. }
  153. update_process_pipeline();
  154. mp_process_pipeline_capture();
  155. }
  156. void
  157. mp_io_pipeline_capture()
  158. {
  159. mp_pipeline_invoke(pipeline, capture, NULL, 0);
  160. }
  161. static void
  162. release_buffer(MPPipeline *pipeline, const uint32_t *buffer_index)
  163. {
  164. mp_camera_release_buffer(mpcamera, *buffer_index);
  165. }
  166. void
  167. mp_io_pipeline_release_buffer(uint32_t buffer_index)
  168. {
  169. mp_pipeline_invoke(pipeline,
  170. (MPPipelineCallback)release_buffer,
  171. &buffer_index,
  172. sizeof(uint32_t));
  173. }
  174. static pid_t focus_continuous_task = 0;
  175. static pid_t start_focus_task = 0;
  176. static void
  177. start_focus()
  178. {
  179. // only run 1 manual focus at once
  180. if (!mp_camera_check_task_complete(mpcamera, start_focus_task) ||
  181. !mp_camera_check_task_complete(mpcamera, focus_continuous_task))
  182. return;
  183. if (state_io.focus.control.id) {
  184. focus_continuous_task = mp_camera_control_set_bool_bg(
  185. mpcamera, &state_io.focus.control, 1);
  186. } else if (state_io.can_af_trigger) {
  187. // TODO improve
  188. MPControl auto_focus_start_control;
  189. auto_focus_start_control.id = V4L2_CID_AUTO_FOCUS_START;
  190. auto_focus_start_control.fd = state_io.camera->sensor_fd;
  191. start_focus_task = mp_camera_control_set_bool_bg(
  192. mpcamera, &auto_focus_start_control, 1);
  193. }
  194. }
  195. static void
  196. update_controls()
  197. {
  198. bool state_changed = false;
  199. // Don't update controls while capturing
  200. if (state_io.captures_remaining > 0) {
  201. return;
  202. }
  203. if (state_io.trigger_af) {
  204. state_io.trigger_af = false;
  205. start_focus();
  206. }
  207. if (state_io.gain.manual != state_io.gain.manual_req) {
  208. mp_camera_control_set_bool_bg(mpcamera,
  209. &state_io.gain.auto_control,
  210. !state_io.gain.manual_req);
  211. state_io.gain.manual = state_io.gain.manual_req;
  212. state_changed = true;
  213. }
  214. if ((state_io.gain.manual ||
  215. (!state_io.gain.manual && state_io.gain.auto_control.id == 0)) &&
  216. state_io.gain.value != state_io.gain.value_req) {
  217. mp_camera_control_set_int32_bg(mpcamera,
  218. &state_io.gain.control,
  219. state_io.gain.value_req);
  220. state_io.gain.value = state_io.gain.value_req;
  221. state_changed = true;
  222. }
  223. if (state_io.exposure.manual != state_io.exposure.manual_req) {
  224. mp_camera_control_set_bool_bg(mpcamera,
  225. &state_io.exposure.auto_control,
  226. state_io.exposure.manual_req ?
  227. V4L2_EXPOSURE_MANUAL :
  228. V4L2_EXPOSURE_AUTO);
  229. state_io.exposure.manual = state_io.exposure.manual_req;
  230. state_changed = true;
  231. }
  232. if (state_io.exposure.manual &&
  233. state_io.exposure.value != state_io.exposure.value_req) {
  234. mp_camera_control_set_int32_bg(mpcamera,
  235. &state_io.exposure.control,
  236. state_io.exposure.value_req);
  237. state_io.exposure.value = state_io.exposure.value_req;
  238. state_changed = true;
  239. }
  240. if (state_changed) {
  241. pipeline_changed = true;
  242. update_process_pipeline();
  243. }
  244. }
  245. static void
  246. do_aaa()
  247. {
  248. bool auto_exposure =
  249. !state_io.exposure.manual && state_io.exposure.auto_control.id == 0;
  250. if (auto_exposure) {
  251. int direction = state_io.stats.exposure;
  252. int step = 0;
  253. if (direction > 0) {
  254. // Preview is too dark
  255. // Try raising the exposure time first
  256. if (state_io.exposure.value < state_io.exposure.max) {
  257. step = state_io.exposure.value / 16;
  258. state_io.exposure.value_req =
  259. state_io.exposure.value + (step * direction);
  260. printf("Expose + %d\n", state_io.exposure.value_req);
  261. } else {
  262. // Raise sensor gain if exposure limit is hit
  263. step = state_io.gain.value / 16;
  264. state_io.gain.value_req =
  265. state_io.gain.value + (step * direction);
  266. printf("Gain + %d\n", state_io.gain.value_req);
  267. }
  268. } else if (direction < 0) {
  269. // Preview is too bright
  270. // Lower the sensor gain first to have less noise
  271. if (state_io.gain.value > 0) {
  272. step = state_io.gain.value / 16;
  273. state_io.gain.value_req =
  274. state_io.gain.value + (step * direction);
  275. printf("Gain - %d\n", state_io.gain.value_req);
  276. } else {
  277. // Shorten the exposure time to go even darker
  278. step = state_io.exposure.value / 16;
  279. state_io.exposure.value_req =
  280. state_io.exposure.value + (step * direction);
  281. printf("Expose - %d\n", state_io.exposure.value_req);
  282. }
  283. }
  284. }
  285. }
  286. static void
  287. on_frame(MPBuffer buffer, void *_data)
  288. {
  289. // Don't process frame when the window is not active, unless we're capturing an image,
  290. // in which case the flash window may be active instead of this window
  291. if (!check_window_active() && state_io.captures_remaining == 0) {
  292. return;
  293. }
  294. pipeline_changed = true;
  295. // Only update controls right after a frame was captured
  296. do_aaa();
  297. update_controls();
  298. // When the mode is switched while capturing we get a couple blank frames,
  299. // presumably from buffers made ready during the switch. Ignore these.
  300. if (state_io.flush_pipeline) {
  301. if (state_io.blank_frame_count < 20) {
  302. // Only check a 10x10 area
  303. size_t test_size =
  304. MIN(10, state_io.camera->current_mode->width) *
  305. MIN(10, state_io.camera->current_mode->height);
  306. bool image_is_blank = true;
  307. for (size_t i = 0; i < test_size; ++i) {
  308. if (buffer.data[i] != 0) {
  309. image_is_blank = false;
  310. }
  311. }
  312. if (image_is_blank) {
  313. ++state_io.blank_frame_count;
  314. return;
  315. }
  316. } else {
  317. printf("Blank image limit reached, resulting capture may be blank\n");
  318. }
  319. state_io.flush_pipeline = false;
  320. state_io.blank_frame_count = 0;
  321. }
  322. // Send the image off for processing
  323. mp_process_pipeline_process_image(buffer);
  324. if (state_io.captures_remaining > 0) {
  325. --state_io.captures_remaining;
  326. if (state_io.captures_remaining == 0) {
  327. // Restore the auto exposure and gain if needed
  328. if (!state_io.exposure.manual) {
  329. mp_camera_control_set_int32_bg(
  330. mpcamera,
  331. &state_io.exposure.auto_control,
  332. V4L2_EXPOSURE_AUTO);
  333. }
  334. if (!state_io.gain.manual) {
  335. mp_camera_control_set_bool_bg(
  336. mpcamera, &state_io.gain.auto_control, true);
  337. }
  338. // Go back to preview mode
  339. mp_process_pipeline_sync();
  340. mp_camera_stop_capture(mpcamera);
  341. struct v4l2_format format = { 0 };
  342. libmegapixels_select_mode(
  343. state_io.camera, state_io.mode_preview, &format);
  344. state_io.flush_pipeline = true;
  345. mp_camera_start_capture(mpcamera);
  346. // Disable flash
  347. if (state_io.flash_enabled) {
  348. mp_flash_disable(state_io.camera);
  349. }
  350. update_process_pipeline();
  351. }
  352. }
  353. }
  354. static void
  355. init_controls()
  356. {
  357. MPControl focus_control;
  358. if (mp_camera_query_control(
  359. state_io.camera->sensor_fd, V4L2_CID_FOCUS_ABSOLUTE, &focus_control)) {
  360. state_io.focus.control = focus_control;
  361. } else {
  362. state_io.focus.control.id = 0;
  363. }
  364. MPControl auto_focus_control;
  365. if (mp_camera_query_control(state_io.camera->sensor_fd, V4L2_CID_FOCUS_AUTO, &auto_focus_control)) {
  366. mp_camera_control_set_bool_bg(
  367. mpcamera, &auto_focus_control, true);
  368. state_io.focus.auto_control = auto_focus_control;
  369. } else {
  370. state_io.focus.auto_control.id = 0;
  371. }
  372. state_io.can_af_trigger = mp_camera_query_control(
  373. state_io.camera->sensor_fd, V4L2_CID_AUTO_FOCUS_START, NULL);
  374. MPControl gain_control;
  375. if (mp_camera_query_control(state_io.camera->sensor_fd, V4L2_CID_GAIN, &gain_control)) {
  376. state_io.gain.control = gain_control;
  377. state_io.gain.max = gain_control.max;
  378. } else if (mp_camera_query_control(
  379. state_io.camera->sensor_fd, V4L2_CID_ANALOGUE_GAIN, &gain_control)) {
  380. state_io.gain.control = gain_control;
  381. state_io.gain.max = gain_control.max;
  382. } else {
  383. state_io.gain.max = 0;
  384. state_io.gain.control.id = 0;
  385. }
  386. if (state_io.gain.control.id) {
  387. state_io.gain.value = mp_camera_control_get_int32(&state_io.gain.control);
  388. } else {
  389. state_io.gain.value = 0;
  390. }
  391. MPControl auto_gain_control;
  392. if (mp_camera_query_control(state_io.camera->sensor_fd, V4L2_CID_AUTOGAIN, &auto_gain_control)) {
  393. state_io.gain.auto_control = auto_gain_control;
  394. state_io.gain.manual =
  395. mp_camera_control_get_bool(&auto_gain_control) == 0;
  396. } else {
  397. state_io.gain.auto_control.id = 0;
  398. }
  399. MPControl exposure_control;
  400. if (mp_camera_query_control(state_io.camera->sensor_fd, V4L2_CID_EXPOSURE, &exposure_control)) {
  401. state_io.exposure.control = exposure_control;
  402. state_io.exposure.max = exposure_control.max;
  403. state_io.exposure.value = mp_camera_control_get_int32(&exposure_control);
  404. } else {
  405. state_io.exposure.control.id = 0;
  406. }
  407. MPControl auto_exposure_control;
  408. if (mp_camera_query_control(
  409. state_io.camera->sensor_fd, V4L2_CID_EXPOSURE_AUTO, &auto_exposure_control)) {
  410. state_io.exposure.auto_control = auto_exposure_control;
  411. state_io.exposure.manual =
  412. mp_camera_control_get_int32(&auto_exposure_control) == V4L2_EXPOSURE_MANUAL;
  413. } else {
  414. state_io.exposure.auto_control.id = 0;
  415. }
  416. MPControl red_control;
  417. if (mp_camera_query_control(
  418. state_io.camera->sensor_fd, V4L2_CID_RED_BALANCE, &red_control)) {
  419. state_io.red.control = red_control;
  420. state_io.red.max = red_control.max;
  421. } else {
  422. state_io.red.control.id = 0;
  423. }
  424. MPControl blue_control;
  425. if (mp_camera_query_control(
  426. state_io.camera->sensor_fd, V4L2_CID_BLUE_BALANCE, &blue_control)) {
  427. state_io.blue.control = blue_control;
  428. state_io.blue.max = blue_control.max;
  429. } else {
  430. state_io.blue.control.id = 0;
  431. }
  432. pipeline_changed = true;
  433. update_process_pipeline();
  434. }
  435. /*
  436. * State transfer from Main -> IO
  437. */
  438. static void
  439. update_state(MPPipeline *pipeline, const mp_state_io *new_state)
  440. {
  441. if (state_io.camera != new_state->camera) {
  442. if (state_io.camera != NULL) {
  443. mp_process_pipeline_sync();
  444. mp_camera_stop_capture(mpcamera);
  445. libmegapixels_close(state_io.camera);
  446. }
  447. if (capture_source) {
  448. g_source_destroy(capture_source);
  449. capture_source = NULL;
  450. }
  451. state_io.camera = new_state->camera;
  452. if (state_io.camera) {
  453. libmegapixels_open(state_io.camera);
  454. mpcamera = mp_camera_new(state_io.camera);
  455. state_io.mode_preview = NULL;
  456. state_io.mode_capture = NULL;
  457. float score = 0;
  458. int area_preview =
  459. state_io.preview_width * state_io.preview_height;
  460. if (area_preview == 0) {
  461. area_preview = 1280 * 720;
  462. }
  463. for (int m = 0; m < state_io.camera->num_modes; m++) {
  464. float mscore = 0;
  465. if (state_io.camera->modes[m]->rate > 29) {
  466. mscore += 1;
  467. }
  468. int mode_area = state_io.camera->modes[m]->width *
  469. state_io.camera->modes[m]->height;
  470. mscore += 1.0f -
  471. (float)(ABS(mode_area - area_preview) /
  472. area_preview);
  473. if (mscore > score) {
  474. state_io.mode_preview =
  475. state_io.camera->modes[m];
  476. score = mscore;
  477. }
  478. }
  479. long area = 0;
  480. for (int m = 0; m < state_io.camera->num_modes; m++) {
  481. long this_pixels = state_io.camera->modes[m]->width *
  482. state_io.camera->modes[m]->height;
  483. if (this_pixels > area) {
  484. area = this_pixels;
  485. state_io.mode_capture =
  486. state_io.camera->modes[m];
  487. }
  488. }
  489. if (state_io.mode_preview == NULL &&
  490. state_io.mode_capture != NULL) {
  491. // If no fast preview mode is available, make due
  492. // with slow modes.
  493. state_io.mode_preview = state_io.mode_capture;
  494. }
  495. if (state_io.mode_preview != NULL) {
  496. if (state_io.camera->video_fd == 0) {
  497. libmegapixels_open(state_io.camera);
  498. }
  499. struct v4l2_format format = { 0 };
  500. libmegapixels_select_mode(state_io.camera,
  501. state_io.mode_preview,
  502. &format);
  503. }
  504. mp_camera_start_capture(mpcamera);
  505. capture_source = mp_pipeline_add_capture_source(
  506. pipeline, mpcamera, on_frame, NULL);
  507. init_controls();
  508. }
  509. }
  510. state_io.configuration = new_state->configuration;
  511. state_io.burst_length = new_state->burst_length;
  512. state_io.preview_width = new_state->preview_width;
  513. state_io.preview_height = new_state->preview_height;
  514. state_io.device_rotation = new_state->device_rotation;
  515. if (state_io.camera) {
  516. state_io.gain.value = new_state->gain.value;
  517. state_io.gain.value_req = new_state->gain.value_req;
  518. state_io.gain.manual = new_state->gain.manual;
  519. state_io.gain.manual_req = new_state->gain.manual_req;
  520. state_io.exposure.value = new_state->exposure.value;
  521. state_io.exposure.value_req = new_state->exposure.value_req;
  522. state_io.exposure.manual = new_state->exposure.manual;
  523. state_io.exposure.manual_req = new_state->exposure.manual_req;
  524. state_io.focus.value = new_state->focus.value;
  525. state_io.focus.value_req = new_state->focus.value_req;
  526. state_io.focus.manual = new_state->focus.manual;
  527. state_io.focus.manual_req = new_state->focus.manual_req;
  528. state_io.flash_enabled = new_state->flash_enabled;
  529. state_io.stats.exposure = new_state->stats.exposure;
  530. state_io.stats.temp = new_state->stats.temp;
  531. state_io.stats.tint = new_state->stats.tint;
  532. state_io.stats.focus = new_state->stats.focus;
  533. }
  534. update_process_pipeline();
  535. }
  536. void
  537. mp_io_pipeline_update_state(const mp_state_io *state)
  538. {
  539. if (!pipeline) {
  540. printf("no pipeline\n");
  541. exit(1);
  542. }
  543. mp_pipeline_invoke(pipeline,
  544. (MPPipelineCallback)update_state,
  545. state,
  546. sizeof(mp_state_io));
  547. }