io_pipeline.c 28 KB

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