io_pipeline.c 23 KB

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