|
@@ -4,6 +4,7 @@
|
|
|
#include "flash.h"
|
|
|
#include "pipeline.h"
|
|
|
#include "process_pipeline.h"
|
|
|
+#include "state.h"
|
|
|
#include <assert.h>
|
|
|
#include <errno.h>
|
|
|
#include <fcntl.h>
|
|
@@ -13,36 +14,10 @@
|
|
|
#include <string.h>
|
|
|
#include <sys/ioctl.h>
|
|
|
|
|
|
-libmegapixels_camera *io_camera = NULL;
|
|
|
-libmegapixels_mode *mode_capture = NULL;
|
|
|
-libmegapixels_mode *mode_preview = NULL;
|
|
|
-MPCamera *mpcamera = NULL;
|
|
|
-
|
|
|
-static bool just_switched_mode = false;
|
|
|
-static int blank_frame_count = 0;
|
|
|
-
|
|
|
-static int burst_length;
|
|
|
-static int captures_remaining = 0;
|
|
|
-
|
|
|
-static int preview_width;
|
|
|
-static int preview_height;
|
|
|
-
|
|
|
-static int device_rotation;
|
|
|
-
|
|
|
-struct control_state {
|
|
|
- bool gain_is_manual;
|
|
|
- int gain;
|
|
|
+mp_state_io state_io;
|
|
|
|
|
|
- bool exposure_is_manual;
|
|
|
- int exposure;
|
|
|
-};
|
|
|
-
|
|
|
-static struct control_state desired_controls = {};
|
|
|
-static struct control_state current_controls = {};
|
|
|
-
|
|
|
-static bool flash_enabled = false;
|
|
|
+MPCamera *mpcamera = NULL;
|
|
|
|
|
|
-static bool want_focus = false;
|
|
|
|
|
|
static MPPipeline *pipeline;
|
|
|
static GSource *capture_source;
|
|
@@ -57,9 +32,7 @@ void
|
|
|
mp_io_pipeline_start()
|
|
|
{
|
|
|
mp_process_pipeline_start();
|
|
|
-
|
|
|
pipeline = mp_pipeline_new();
|
|
|
-
|
|
|
mp_pipeline_invoke(pipeline, setup, NULL, 0);
|
|
|
}
|
|
|
|
|
@@ -69,57 +42,59 @@ mp_io_pipeline_stop()
|
|
|
if (capture_source) {
|
|
|
g_source_destroy(capture_source);
|
|
|
}
|
|
|
-
|
|
|
mp_pipeline_free(pipeline);
|
|
|
-
|
|
|
mp_process_pipeline_stop();
|
|
|
}
|
|
|
|
|
|
+/*
|
|
|
+ * Update state from IO -> Process
|
|
|
+ */
|
|
|
static void
|
|
|
update_process_pipeline()
|
|
|
{
|
|
|
// Grab the latest control values
|
|
|
- if (!current_controls.gain_is_manual) {
|
|
|
- // current_controls.gain =
|
|
|
- // mp_camera_control_get_int32(info->camera,
|
|
|
- // info->gain_ctrl);
|
|
|
+ if (!state_io.gain.manual && state_io.gain.control) {
|
|
|
+ state_io.gain.value = mp_camera_control_get_int32(
|
|
|
+ state_io.camera, state_io.gain.control);
|
|
|
}
|
|
|
- if (!current_controls.exposure_is_manual) {
|
|
|
- // current_controls.exposure =
|
|
|
- // mp_camera_control_get_int32(info->camera,
|
|
|
- // V4L2_CID_EXPOSURE);
|
|
|
+
|
|
|
+ if (!state_io.exposure.manual && state_io.exposure.control) {
|
|
|
+ state_io.exposure.value = mp_camera_control_get_int32(
|
|
|
+ state_io.camera, state_io.exposure.control);
|
|
|
}
|
|
|
|
|
|
MPControl control;
|
|
|
float balance_red = 1.0f;
|
|
|
float balance_blue = 1.0f;
|
|
|
- /*
|
|
|
- if (mp_camera_query_control(info->camera, V4L2_CID_RED_BALANCE, &control)) {
|
|
|
- int red = mp_camera_control_get_int32(info->camera,
|
|
|
- V4L2_CID_RED_BALANCE);
|
|
|
- int blue = mp_camera_control_get_int32(info->camera,
|
|
|
- V4L2_CID_BLUE_BALANCE);
|
|
|
- balance_red = (float)red / (float)control.max;
|
|
|
- balance_blue = (float)blue / (float)control.max;
|
|
|
+ if (state_io.red.control && state_io.blue.control) {
|
|
|
+ int red = mp_camera_control_get_int32(state_io.camera,
|
|
|
+ state_io.red.control);
|
|
|
+ int blue = mp_camera_control_get_int32(state_io.camera,
|
|
|
+ state_io.blue.control);
|
|
|
+ balance_red = (float)red / (float)state_io.red.max;
|
|
|
+ balance_blue = (float)blue / (float)state_io.blue.max;
|
|
|
}
|
|
|
- */
|
|
|
|
|
|
struct mp_process_pipeline_state pipeline_state = {
|
|
|
- .camera = io_camera,
|
|
|
- .burst_length = burst_length,
|
|
|
- .preview_width = preview_width,
|
|
|
- .preview_height = preview_height,
|
|
|
- .device_rotation = device_rotation,
|
|
|
- .gain_is_manual = current_controls.gain_is_manual,
|
|
|
- .gain = current_controls.gain,
|
|
|
- .gain_max = 1, // TODO: Fix
|
|
|
+ .camera = state_io.camera,
|
|
|
+ .burst_length = state_io.burst_length,
|
|
|
+ .preview_width = state_io.preview_width,
|
|
|
+ .preview_height = state_io.preview_height,
|
|
|
+ .device_rotation = state_io.device_rotation,
|
|
|
+ .gain_is_manual = state_io.gain.manual,
|
|
|
+ .gain = state_io.gain.value,
|
|
|
+ .gain_max = state_io.gain.max,
|
|
|
.balance_red = balance_red,
|
|
|
.balance_blue = balance_blue,
|
|
|
- .exposure_is_manual = current_controls.exposure_is_manual,
|
|
|
- .exposure = current_controls.exposure,
|
|
|
- .has_auto_focus_continuous = false, // TODO: fix
|
|
|
- .has_auto_focus_start = false, // TODO: fix
|
|
|
- .flash_enabled = flash_enabled,
|
|
|
+ .exposure_is_manual = state_io.exposure.manual,
|
|
|
+ .exposure = state_io.exposure.value,
|
|
|
+ .has_auto_focus_continuous = state_io.focus.control != 0,
|
|
|
+ .has_auto_focus_start = state_io.can_af_trigger,
|
|
|
+ .flash_enabled = state_io.flash_enabled,
|
|
|
+ .control_gain = state_io.gain.control != 0,
|
|
|
+ .control_exposure = state_io.exposure.control != 0,
|
|
|
+ .control_focus = state_io.focus.control != 0,
|
|
|
+ .control_flash = true,
|
|
|
};
|
|
|
mp_process_pipeline_update_state(&pipeline_state);
|
|
|
}
|
|
@@ -127,7 +102,7 @@ update_process_pipeline()
|
|
|
static void
|
|
|
focus(MPPipeline *pipeline, const void *data)
|
|
|
{
|
|
|
- want_focus = true;
|
|
|
+ state_io.trigger_af = true;
|
|
|
}
|
|
|
|
|
|
void
|
|
@@ -139,32 +114,30 @@ mp_io_pipeline_focus()
|
|
|
static void
|
|
|
capture(MPPipeline *pipeline, const void *data)
|
|
|
{
|
|
|
- uint32_t gain;
|
|
|
float gain_norm;
|
|
|
|
|
|
// Disable the autogain/exposure while taking the burst
|
|
|
- /* TODO: Fix
|
|
|
- mp_camera_control_set_int32(info->camera, V4L2_CID_AUTOGAIN, 0);
|
|
|
+ mp_camera_control_set_int32(state_io.camera, V4L2_CID_AUTOGAIN, 0);
|
|
|
mp_camera_control_set_int32(
|
|
|
- info->camera, V4L2_CID_EXPOSURE_AUTO, V4L2_EXPOSURE_MANUAL);
|
|
|
- */
|
|
|
+ state_io.camera, V4L2_CID_EXPOSURE_AUTO, V4L2_EXPOSURE_MANUAL);
|
|
|
|
|
|
// Get current gain to calculate a burst length;
|
|
|
// with low gain there's 3, with the max automatic gain of the ov5640
|
|
|
// the value seems to be 248 which creates a 5 frame burst
|
|
|
// for manual gain you can go up to 11 frames
|
|
|
- gain = mp_camera_control_get_int32(io_camera, V4L2_CID_GAIN);
|
|
|
- // gain_norm = (float)gain / (float)mpcamera.gain_max;
|
|
|
- // burst_length = (int)fmax(sqrt(gain_norm) * 10, 2) + 1;
|
|
|
- burst_length = MIN(1, burst_length);
|
|
|
- captures_remaining = burst_length;
|
|
|
+ state_io.gain.value =
|
|
|
+ mp_camera_control_get_int32(state_io.camera, V4L2_CID_GAIN);
|
|
|
+ gain_norm = (float)state_io.gain.value / (float)state_io.gain.max;
|
|
|
+ state_io.burst_length = (int)fmax(sqrtf(gain_norm) * 10, 2) + 1;
|
|
|
+ state_io.burst_length = MIN(1, state_io.burst_length);
|
|
|
+ state_io.captures_remaining = state_io.burst_length;
|
|
|
|
|
|
// Change camera mode for capturing
|
|
|
mp_process_pipeline_sync();
|
|
|
mp_camera_stop_capture(mpcamera);
|
|
|
- struct v4l2_format format = {0};
|
|
|
- libmegapixels_select_mode(io_camera, mode_capture, &format);
|
|
|
- just_switched_mode = true;
|
|
|
+ struct v4l2_format format = { 0 };
|
|
|
+ libmegapixels_select_mode(state_io.camera, state_io.mode_capture, &format);
|
|
|
+ state_io.flush_pipeline = true;
|
|
|
|
|
|
mp_camera_start_capture(mpcamera);
|
|
|
|
|
@@ -211,59 +184,58 @@ start_focus()
|
|
|
!mp_camera_check_task_complete(mpcamera, focus_continuous_task))
|
|
|
return;
|
|
|
|
|
|
- /* TODO: implement
|
|
|
- if (mpcamera.has_auto_focus_continuous) {
|
|
|
+ if (state_io.focus.control) {
|
|
|
focus_continuous_task = mp_camera_control_set_bool_bg(
|
|
|
- info->camera, V4L2_CID_FOCUS_AUTO, 1);
|
|
|
- } else if (info->has_auto_focus_start) {
|
|
|
+ state_io.camera, state_io.focus.control, 1);
|
|
|
+ } else if (state_io.can_af_trigger) {
|
|
|
start_focus_task = mp_camera_control_set_bool_bg(
|
|
|
- info->camera, V4L2_CID_AUTO_FOCUS_START, 1);
|
|
|
+ state_io.camera, V4L2_CID_AUTO_FOCUS_START, 1);
|
|
|
}
|
|
|
- */
|
|
|
}
|
|
|
|
|
|
static void
|
|
|
update_controls()
|
|
|
{
|
|
|
// Don't update controls while capturing
|
|
|
- if (captures_remaining > 0) {
|
|
|
+ if (state_io.captures_remaining > 0) {
|
|
|
return;
|
|
|
}
|
|
|
- /* TODO: implement
|
|
|
- if (want_focus) {
|
|
|
- start_focus(mpcamera);
|
|
|
- want_focus = false;
|
|
|
+
|
|
|
+ if (state_io.trigger_af) {
|
|
|
+ state_io.trigger_af = false;
|
|
|
+ start_focus();
|
|
|
}
|
|
|
|
|
|
- if (current_controls.gain_is_manual != desired_controls.gain_is_manual) {
|
|
|
- mp_camera_control_set_bool_bg(info->camera,
|
|
|
+ if (state_io.gain.manual != state_io.gain.manual_req) {
|
|
|
+ mp_camera_control_set_bool_bg(state_io.camera,
|
|
|
V4L2_CID_AUTOGAIN,
|
|
|
- !desired_controls.gain_is_manual);
|
|
|
+ !state_io.gain.manual_req);
|
|
|
+ state_io.gain.manual = state_io.gain.manual_req;
|
|
|
}
|
|
|
|
|
|
- if (desired_controls.gain_is_manual &&
|
|
|
- current_controls.gain != desired_controls.gain) {
|
|
|
- mp_camera_control_set_int32_bg(
|
|
|
- info->camera, info->gain_ctrl, desired_controls.gain);
|
|
|
+ if (state_io.gain.manual && state_io.gain.value != state_io.gain.value_req) {
|
|
|
+ mp_camera_control_set_int32_bg(state_io.camera,
|
|
|
+ state_io.gain.control,
|
|
|
+ state_io.gain.value_req);
|
|
|
+ state_io.gain.value = state_io.gain.value_req;
|
|
|
}
|
|
|
|
|
|
- if (current_controls.exposure_is_manual !=
|
|
|
- desired_controls.exposure_is_manual) {
|
|
|
- mp_camera_control_set_int32_bg(info->camera,
|
|
|
- V4L2_CID_EXPOSURE_AUTO,
|
|
|
- desired_controls.exposure_is_manual ?
|
|
|
- V4L2_EXPOSURE_MANUAL :
|
|
|
- V4L2_EXPOSURE_AUTO);
|
|
|
+ if (state_io.exposure.manual != state_io.exposure.manual_req) {
|
|
|
+ mp_camera_control_set_bool_bg(state_io.camera,
|
|
|
+ V4L2_CID_EXPOSURE_AUTO,
|
|
|
+ state_io.exposure.manual_req ?
|
|
|
+ V4L2_EXPOSURE_MANUAL :
|
|
|
+ V4L2_EXPOSURE_AUTO);
|
|
|
+ state_io.exposure.manual = state_io.exposure.manual_req;
|
|
|
}
|
|
|
|
|
|
- if (desired_controls.exposure_is_manual &&
|
|
|
- current_controls.exposure != desired_controls.exposure) {
|
|
|
- mp_camera_control_set_int32_bg(
|
|
|
- info->camera, V4L2_CID_EXPOSURE, desired_controls.exposure);
|
|
|
+ if (state_io.exposure.manual &&
|
|
|
+ state_io.exposure.value != state_io.exposure.value_req) {
|
|
|
+ mp_camera_control_set_int32_bg(state_io.camera,
|
|
|
+ state_io.exposure.control,
|
|
|
+ state_io.exposure.value_req);
|
|
|
+ state_io.exposure.value = state_io.exposure.value_req;
|
|
|
}
|
|
|
-
|
|
|
- current_controls = desired_controls;
|
|
|
- */
|
|
|
}
|
|
|
|
|
|
static void
|
|
@@ -274,11 +246,12 @@ on_frame(MPBuffer buffer, void *_data)
|
|
|
|
|
|
// When the mode is switched while capturing we get a couple blank frames,
|
|
|
// presumably from buffers made ready during the switch. Ignore these.
|
|
|
- if (just_switched_mode) {
|
|
|
- if (blank_frame_count < 20) {
|
|
|
+ if (state_io.flush_pipeline) {
|
|
|
+ if (state_io.blank_frame_count < 20) {
|
|
|
// Only check a 10x10 area
|
|
|
- size_t test_size = MIN(10, io_camera->current_mode->width) *
|
|
|
- MIN(10, io_camera->current_mode->height);
|
|
|
+ size_t test_size =
|
|
|
+ MIN(10, state_io.camera->current_mode->width) *
|
|
|
+ MIN(10, state_io.camera->current_mode->height);
|
|
|
|
|
|
bool image_is_blank = true;
|
|
|
for (size_t i = 0; i < test_size; ++i) {
|
|
@@ -288,45 +261,44 @@ on_frame(MPBuffer buffer, void *_data)
|
|
|
}
|
|
|
|
|
|
if (image_is_blank) {
|
|
|
- ++blank_frame_count;
|
|
|
+ ++state_io.blank_frame_count;
|
|
|
return;
|
|
|
}
|
|
|
} else {
|
|
|
printf("Blank image limit reached, resulting capture may be blank\n");
|
|
|
}
|
|
|
|
|
|
- just_switched_mode = false;
|
|
|
- blank_frame_count = 0;
|
|
|
+ state_io.flush_pipeline = false;
|
|
|
+ state_io.blank_frame_count = 0;
|
|
|
}
|
|
|
|
|
|
// Send the image off for processing
|
|
|
mp_process_pipeline_process_image(buffer);
|
|
|
|
|
|
- if (captures_remaining > 0) {
|
|
|
- --captures_remaining;
|
|
|
+ if (state_io.captures_remaining > 0) {
|
|
|
+ --state_io.captures_remaining;
|
|
|
|
|
|
- if (captures_remaining == 0) {
|
|
|
+ if (state_io.captures_remaining == 0) {
|
|
|
// Restore the auto exposure and gain if needed
|
|
|
- if (!current_controls.exposure_is_manual) {
|
|
|
+ if (!state_io.exposure.manual) {
|
|
|
mp_camera_control_set_int32_bg(
|
|
|
- io_camera,
|
|
|
+ state_io.camera,
|
|
|
V4L2_CID_EXPOSURE_AUTO,
|
|
|
V4L2_EXPOSURE_AUTO);
|
|
|
}
|
|
|
|
|
|
- /* TODO: implement
|
|
|
- if (!current_controls.gain_is_manual) {
|
|
|
+ if (!state_io.gain.manual) {
|
|
|
mp_camera_control_set_bool_bg(
|
|
|
- info->camera, V4L2_CID_AUTOGAIN, true);
|
|
|
+ state_io.camera, V4L2_CID_AUTOGAIN, true);
|
|
|
}
|
|
|
- */
|
|
|
|
|
|
// Go back to preview mode
|
|
|
mp_process_pipeline_sync();
|
|
|
mp_camera_stop_capture(mpcamera);
|
|
|
- struct v4l2_format format = {0};
|
|
|
- libmegapixels_select_mode(io_camera, mode_preview, &format);
|
|
|
- just_switched_mode = true;
|
|
|
+ struct v4l2_format format = { 0 };
|
|
|
+ libmegapixels_select_mode(
|
|
|
+ state_io.camera, state_io.mode_preview, &format);
|
|
|
+ state_io.flush_pipeline = true;
|
|
|
|
|
|
mp_camera_start_capture(mpcamera);
|
|
|
|
|
@@ -343,19 +315,81 @@ on_frame(MPBuffer buffer, void *_data)
|
|
|
}
|
|
|
|
|
|
static void
|
|
|
-update_state(MPPipeline *pipeline, const struct mp_io_pipeline_state *state)
|
|
|
+init_controls()
|
|
|
{
|
|
|
- // Make sure the state isn't updated more than it needs to be by checking
|
|
|
- // whether this state change actually changes anything.
|
|
|
- bool has_changed = false;
|
|
|
+ if (mp_camera_query_control(
|
|
|
+ state_io.camera, V4L2_CID_FOCUS_ABSOLUTE, NULL)) {
|
|
|
+ // TODO: Set focus state
|
|
|
+ state_io.focus.control = V4L2_CID_FOCUS_ABSOLUTE;
|
|
|
+ } else {
|
|
|
+ state_io.focus.control = 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (mp_camera_query_control(state_io.camera, V4L2_CID_FOCUS_AUTO, NULL)) {
|
|
|
+ mp_camera_control_set_bool_bg(
|
|
|
+ state_io.camera, V4L2_CID_FOCUS_AUTO, true);
|
|
|
+ }
|
|
|
+
|
|
|
+ state_io.can_af_trigger = mp_camera_query_control(
|
|
|
+ state_io.camera, V4L2_CID_AUTO_FOCUS_START, NULL);
|
|
|
|
|
|
- if (io_camera != state->camera) {
|
|
|
- has_changed = true;
|
|
|
+ MPControl control;
|
|
|
+ if (mp_camera_query_control(state_io.camera, V4L2_CID_GAIN, &control)) {
|
|
|
+ state_io.gain.control = V4L2_CID_GAIN;
|
|
|
+ state_io.gain.max = control.max;
|
|
|
+ } else if (mp_camera_query_control(
|
|
|
+ state_io.camera, V4L2_CID_ANALOGUE_GAIN, &control)) {
|
|
|
+ state_io.gain.control = V4L2_CID_ANALOGUE_GAIN;
|
|
|
+ state_io.gain.max = control.max;
|
|
|
+ } else {
|
|
|
+ state_io.gain.max = 0;
|
|
|
+ state_io.gain.control = 0;
|
|
|
+ }
|
|
|
+ if (state_io.gain.control) {
|
|
|
+ state_io.gain.value = mp_camera_control_get_int32(
|
|
|
+ state_io.camera, state_io.gain.control);
|
|
|
+ } else {
|
|
|
+ state_io.gain.value = 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ state_io.gain.manual =
|
|
|
+ mp_camera_control_get_bool(state_io.camera, V4L2_CID_AUTOGAIN) == 0;
|
|
|
+
|
|
|
+ state_io.exposure.value =
|
|
|
+ mp_camera_control_get_int32(state_io.camera, V4L2_CID_EXPOSURE);
|
|
|
+ state_io.exposure.manual =
|
|
|
+ mp_camera_control_get_int32(state_io.camera,
|
|
|
+ V4L2_CID_EXPOSURE_AUTO) ==
|
|
|
+ V4L2_EXPOSURE_MANUAL;
|
|
|
+
|
|
|
+ if (mp_camera_query_control(
|
|
|
+ state_io.camera, V4L2_CID_RED_BALANCE, &control)) {
|
|
|
+ state_io.red.control = V4L2_CID_RED_BALANCE;
|
|
|
+ state_io.red.max = control.max;
|
|
|
+ } else {
|
|
|
+ state_io.red.control = 0;
|
|
|
+ }
|
|
|
|
|
|
- if (io_camera != NULL) {
|
|
|
+ if (mp_camera_query_control(
|
|
|
+ state_io.camera, V4L2_CID_BLUE_BALANCE, &control)) {
|
|
|
+ state_io.blue.control = V4L2_CID_BLUE_BALANCE;
|
|
|
+ state_io.blue.max = control.max;
|
|
|
+ } else {
|
|
|
+ state_io.blue.control = 0;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+ * State transfer from Main -> IO
|
|
|
+ */
|
|
|
+static void
|
|
|
+update_state(MPPipeline *pipeline, const struct mp_io_pipeline_state *state)
|
|
|
+{
|
|
|
+ if (state_io.camera != state->camera) {
|
|
|
+ if (state_io.camera != NULL) {
|
|
|
mp_process_pipeline_sync();
|
|
|
mp_camera_stop_capture(mpcamera);
|
|
|
- libmegapixels_close(io_camera);
|
|
|
+ libmegapixels_close(state_io.camera);
|
|
|
}
|
|
|
|
|
|
if (capture_source) {
|
|
@@ -363,90 +397,68 @@ update_state(MPPipeline *pipeline, const struct mp_io_pipeline_state *state)
|
|
|
capture_source = NULL;
|
|
|
}
|
|
|
|
|
|
- io_camera = state->camera;
|
|
|
- if (io_camera) {
|
|
|
- libmegapixels_open(io_camera);
|
|
|
- mpcamera = mp_camera_new(io_camera);
|
|
|
- mode_preview = NULL;
|
|
|
- mode_capture = NULL;
|
|
|
- for (int m = 0; m < io_camera->num_modes; m++) {
|
|
|
- if (io_camera->modes[m]->rate > 29) {
|
|
|
- mode_preview = io_camera->modes[m];
|
|
|
+ state_io.camera = state->camera;
|
|
|
+ if (state_io.camera) {
|
|
|
+ libmegapixels_open(state_io.camera);
|
|
|
+ mpcamera = mp_camera_new(state_io.camera);
|
|
|
+ state_io.mode_preview = NULL;
|
|
|
+ state_io.mode_capture = NULL;
|
|
|
+ for (int m = 0; m < state_io.camera->num_modes; m++) {
|
|
|
+ if (state_io.camera->modes[m]->rate > 29) {
|
|
|
+ state_io.mode_preview =
|
|
|
+ state_io.camera->modes[m];
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
long area = 0;
|
|
|
- for (int m = 0; m < io_camera->num_modes; m++) {
|
|
|
- long this_pixels = io_camera->modes[m]->width *
|
|
|
- io_camera->modes[m]->height;
|
|
|
+ for (int m = 0; m < state_io.camera->num_modes; m++) {
|
|
|
+ long this_pixels = state_io.camera->modes[m]->width *
|
|
|
+ state_io.camera->modes[m]->height;
|
|
|
|
|
|
if (this_pixels > area) {
|
|
|
area = this_pixels;
|
|
|
- mode_capture = io_camera->modes[m];
|
|
|
+ state_io.mode_capture =
|
|
|
+ state_io.camera->modes[m];
|
|
|
}
|
|
|
}
|
|
|
- if (mode_preview == NULL && mode_capture != NULL) {
|
|
|
- // If no fast preview mode is available, make do with
|
|
|
- // slow modes.
|
|
|
- mode_preview = mode_capture;
|
|
|
+ if (state_io.mode_preview == NULL &&
|
|
|
+ state_io.mode_capture != NULL) {
|
|
|
+ // If no fast preview mode is available, make due
|
|
|
+ // with slow modes.
|
|
|
+ state_io.mode_preview = state_io.mode_capture;
|
|
|
}
|
|
|
- if (mode_preview != NULL) {
|
|
|
- if (io_camera->video_fd == 0) {
|
|
|
- libmegapixels_open(io_camera);
|
|
|
+ if (state_io.mode_preview != NULL) {
|
|
|
+ if (state_io.camera->video_fd == 0) {
|
|
|
+ libmegapixels_open(state_io.camera);
|
|
|
}
|
|
|
- struct v4l2_format format = {0};
|
|
|
- libmegapixels_select_mode(io_camera, mode_preview, &format);
|
|
|
+ struct v4l2_format format = { 0 };
|
|
|
+ libmegapixels_select_mode(state_io.camera,
|
|
|
+ state_io.mode_preview,
|
|
|
+ &format);
|
|
|
}
|
|
|
|
|
|
mp_camera_start_capture(mpcamera);
|
|
|
capture_source = mp_pipeline_add_capture_source(
|
|
|
pipeline, mpcamera, on_frame, NULL);
|
|
|
|
|
|
- current_controls.gain_is_manual =
|
|
|
- mp_camera_control_get_bool(io_camera,
|
|
|
- V4L2_CID_AUTOGAIN) == 0;
|
|
|
- // current_controls.gain =
|
|
|
- // mp_camera_control_get_int32(camera,
|
|
|
- // info->gain_ctrl);
|
|
|
-
|
|
|
- // current_controls.exposure_is_manual =
|
|
|
- // mp_camera_control_get_int32(
|
|
|
- // info->camera, V4L2_CID_EXPOSURE_AUTO) ==
|
|
|
- // V4L2_EXPOSURE_MANUAL;
|
|
|
- // current_controls.exposure = mp_camera_control_get_int32(
|
|
|
- // info->camera, V4L2_CID_EXPOSURE);
|
|
|
+ init_controls();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- has_changed = has_changed || burst_length != state->burst_length ||
|
|
|
- preview_width != state->preview_width ||
|
|
|
- preview_height != state->preview_height ||
|
|
|
- device_rotation != state->device_rotation;
|
|
|
-
|
|
|
- burst_length = state->burst_length;
|
|
|
- preview_width = state->preview_width;
|
|
|
- preview_height = state->preview_height;
|
|
|
- device_rotation = state->device_rotation;
|
|
|
-
|
|
|
- if (io_camera) {
|
|
|
- struct control_state previous_desired = desired_controls;
|
|
|
+ state_io.burst_length = state->burst_length;
|
|
|
+ state_io.preview_width = state->preview_width;
|
|
|
+ state_io.preview_height = state->preview_height;
|
|
|
+ state_io.device_rotation = state->device_rotation;
|
|
|
|
|
|
- desired_controls.gain_is_manual = state->gain_is_manual;
|
|
|
- desired_controls.gain = state->gain;
|
|
|
- desired_controls.exposure_is_manual = state->exposure_is_manual;
|
|
|
- desired_controls.exposure = state->exposure;
|
|
|
+ if (state_io.camera) {
|
|
|
+ state_io.gain.manual_req = state->gain_is_manual;
|
|
|
+ state_io.gain.value_req = state->gain;
|
|
|
+ state_io.exposure.manual_req = state->exposure_is_manual;
|
|
|
+ state_io.exposure.value_req = state->exposure;
|
|
|
|
|
|
- has_changed = has_changed ||
|
|
|
- memcmp(&previous_desired,
|
|
|
- &desired_controls,
|
|
|
- sizeof(struct control_state)) != 0 ||
|
|
|
- flash_enabled != state->flash_enabled;
|
|
|
-
|
|
|
- flash_enabled = state->flash_enabled;
|
|
|
+ state_io.flash_enabled = state->flash_enabled;
|
|
|
}
|
|
|
|
|
|
- assert(has_changed);
|
|
|
-
|
|
|
update_process_pipeline();
|
|
|
}
|
|
|
|