Browse Source

Refactor controls more

Martijn Braam 1 year ago
parent
commit
f26f81e3f1
5 changed files with 154 additions and 112 deletions
  1. 51 23
      src/io_pipeline.c
  2. 2 21
      src/io_pipeline.h
  3. 64 36
      src/main.c
  4. 22 12
      src/process_pipeline.c
  5. 15 20
      src/state.h

+ 51 - 23
src/io_pipeline.c

@@ -83,21 +83,24 @@ update_process_pipeline()
                 .device_rotation = state_io.device_rotation,
 
                 .gain.control = state_io.gain.control,
+                .gain.auto_control = state_io.gain.auto_control,
                 .gain.value = state_io.gain.value,
                 .gain.max = state_io.gain.max,
                 .gain.manual = state_io.gain.manual,
 
                 .exposure.control = state_io.exposure.control,
+                .exposure.auto_control = state_io.exposure.auto_control,
                 .exposure.value = state_io.exposure.value,
                 .exposure.max = state_io.exposure.max,
                 .exposure.manual = state_io.exposure.manual,
 
                 .focus.control = state_io.focus.control,
+                .focus.auto_control = state_io.focus.auto_control,
                 .focus.value = state_io.focus.value,
                 .focus.max = state_io.focus.max,
                 .focus.manual = state_io.focus.manual,
 
-                .balance = {balance_red, 1.0f, balance_blue},
+                .balance = { balance_red, 1.0f, balance_blue },
         };
 
         struct mp_process_pipeline_state pipeline_state = {
@@ -359,6 +362,9 @@ init_controls()
         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.focus.auto_control = V4L2_CID_FOCUS_AUTO;
+        } else {
+                state_io.focus.auto_control = 0;
         }
 
         state_io.can_af_trigger = mp_camera_query_control(
@@ -383,8 +389,14 @@ init_controls()
                 state_io.gain.value = 0;
         }
 
-        state_io.gain.manual =
-                mp_camera_control_get_bool(state_io.camera, V4L2_CID_AUTOGAIN) == 0;
+        if (mp_camera_query_control(state_io.camera, V4L2_CID_AUTOGAIN, &control)) {
+                state_io.gain.auto_control = V4L2_CID_AUTOGAIN;
+                state_io.gain.manual =
+                        mp_camera_control_get_bool(state_io.camera,
+                                                   V4L2_CID_AUTOGAIN) == 0;
+        } else {
+                state_io.gain.auto_control = 0;
+        }
 
         if (mp_camera_query_control(state_io.camera, V4L2_CID_EXPOSURE, &control)) {
                 state_io.exposure.control = V4L2_CID_EXPOSURE;
@@ -396,10 +408,16 @@ init_controls()
                 state_io.exposure.control = 0;
         }
 
-        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_EXPOSURE_AUTO, &control)) {
+                state_io.exposure.auto_control = V4L2_CID_EXPOSURE_AUTO;
+                state_io.exposure.manual =
+                        mp_camera_control_get_int32(state_io.camera,
+                                                    V4L2_CID_EXPOSURE_AUTO) ==
+                        V4L2_EXPOSURE_MANUAL;
+        } else {
+                state_io.exposure.auto_control = 0;
+        }
 
         if (mp_camera_query_control(
                     state_io.camera, V4L2_CID_RED_BALANCE, &control)) {
@@ -422,9 +440,9 @@ init_controls()
  * State transfer from Main -> IO
  */
 static void
-update_state(MPPipeline *pipeline, const struct mp_io_pipeline_state *state)
+update_state(MPPipeline *pipeline, const mp_state_io *new_state)
 {
-        if (state_io.camera != state->camera) {
+        if (state_io.camera != new_state->camera) {
                 if (state_io.camera != NULL) {
                         mp_process_pipeline_sync();
                         mp_camera_stop_capture(mpcamera);
@@ -436,7 +454,7 @@ update_state(MPPipeline *pipeline, const struct mp_io_pipeline_state *state)
                         capture_source = NULL;
                 }
 
-                state_io.camera = state->camera;
+                state_io.camera = new_state->camera;
                 if (state_io.camera) {
                         libmegapixels_open(state_io.camera);
                         mpcamera = mp_camera_new(state_io.camera);
@@ -495,29 +513,39 @@ update_state(MPPipeline *pipeline, const struct mp_io_pipeline_state *state)
                         init_controls();
                 }
         }
-        state_io.configuration = state->configuration;
-        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;
+        state_io.configuration = new_state->configuration;
+        state_io.burst_length = new_state->burst_length;
+        state_io.preview_width = new_state->preview_width;
+        state_io.preview_height = new_state->preview_height;
+        state_io.device_rotation = new_state->device_rotation;
 
         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;
-
-                state_io.flash_enabled = state->flash_enabled;
+                state_io.gain.value = new_state->gain.value;
+                state_io.gain.value_req = new_state->gain.value_req;
+                state_io.gain.manual = new_state->gain.manual;
+                state_io.gain.manual_req = new_state->gain.manual_req;
+
+                state_io.exposure.value = new_state->exposure.value;
+                state_io.exposure.value_req = new_state->exposure.value_req;
+                state_io.exposure.manual = new_state->exposure.manual;
+                state_io.exposure.manual_req = new_state->exposure.manual_req;
+
+                state_io.focus.value = new_state->focus.value;
+                state_io.focus.value_req = new_state->focus.value_req;
+                state_io.focus.manual = new_state->focus.manual;
+                state_io.focus.manual_req = new_state->focus.manual_req;
+
+                state_io.flash_enabled = new_state->flash_enabled;
         }
 
         update_process_pipeline();
 }
 
 void
-mp_io_pipeline_update_state(const struct mp_io_pipeline_state *state)
+mp_io_pipeline_update_state(const mp_state_io *state)
 {
         mp_pipeline_invoke(pipeline,
                            (MPPipelineCallback)update_state,
                            state,
-                           sizeof(struct mp_io_pipeline_state));
+                           sizeof(mp_state_io));
 }

+ 2 - 21
src/io_pipeline.h

@@ -1,29 +1,10 @@
 #pragma once
 
+#include "state.h"
 #include <libmegapixels.h>
 #include <stdbool.h>
 #include <stdint.h>
 
-struct mp_io_pipeline_state {
-        libmegapixels_camera *camera;
-        libmegapixels_devconfig *configuration;
-
-        int burst_length;
-
-        int preview_width;
-        int preview_height;
-
-        int device_rotation;
-
-        bool gain_is_manual;
-        int gain;
-
-        bool exposure_is_manual;
-        int exposure;
-
-        bool flash_enabled;
-};
-
 void mp_io_pipeline_start();
 void mp_io_pipeline_stop();
 
@@ -32,4 +13,4 @@ void mp_io_pipeline_capture();
 
 void mp_io_pipeline_release_buffer(uint32_t buffer_index);
 
-void mp_io_pipeline_update_state(const struct mp_io_pipeline_state *state);
+void mp_io_pipeline_update_state(const mp_state_io *state);

+ 64 - 36
src/main.c

@@ -100,37 +100,70 @@ check_window_active()
 static void
 update_io_pipeline()
 {
-        struct mp_io_pipeline_state io_state = {
+        mp_state_io new_state = {
                 .camera = state.camera,
                 .configuration = state.configuration,
                 .burst_length = state.burst_length,
                 .preview_width = state.preview_width,
                 .preview_height = state.preview_height,
                 .device_rotation = state.device_rotation,
-                .gain_is_manual = state.gain_is_manual,
-                .gain = state.gain,
-                .exposure_is_manual = state.exposure_is_manual,
-                .exposure = state.exposure,
-                .flash_enabled = state.flash_enabled,
+
+                .gain.control = state.gain.control,
+                .gain.auto_control = state.gain.auto_control,
+                .gain.value = state.gain.value,
+                .gain.value_req = state.gain.value_req,
+                .gain.max = state.gain.max,
+                .gain.manual = state.gain.manual,
+                .gain.manual_req = state.gain.manual_req,
+
+                .exposure.control = state.exposure.control,
+                .exposure.auto_control = state.exposure.auto_control,
+                .exposure.value = state.exposure.value,
+                .exposure.value_req = state.exposure.value_req,
+                .exposure.max = state.exposure.max,
+                .exposure.manual = state.exposure.manual,
+                .exposure.manual_req = state.exposure.manual_req,
+
+                .focus.control = state.focus.control,
+                .focus.auto_control = state.focus.auto_control,
+                .focus.value = state.focus.value,
+                .focus.value_req = state.focus.value_req,
+                .focus.max = state.focus.max,
+                .focus.manual = state.focus.manual,
+                .focus.manual_req = state.focus.manual_req,
         };
-        mp_io_pipeline_update_state(&io_state);
+        mp_io_pipeline_update_state(&new_state);
 
         // Make the right settings available for the camera
         gtk_widget_set_visible(flash_button, state.control_flash);
-        gtk_widget_set_visible(iso_button, state.control_gain);
-        gtk_widget_set_visible(shutter_button, state.control_exposure);
+        gtk_widget_set_visible(iso_button, state.gain.control != 0);
+        gtk_widget_set_visible(shutter_button, state.exposure.control != 0);
 }
 
+/*
+ * State transfer from Process -> Main
+ */
 static bool
 update_state(const mp_state_main *new_state)
 {
         if (state.camera == new_state->camera) {
-                state.gain_is_manual = new_state->gain_is_manual;
-                state.gain = new_state->gain;
-                state.gain_max = new_state->gain_max;
-
-                state.exposure_is_manual = new_state->exposure_is_manual;
-                state.exposure = new_state->exposure;
+                state.gain.control = new_state->gain.control;
+                state.gain.auto_control = new_state->gain.auto_control;
+                state.gain.value = new_state->gain.value;
+                state.gain.max = new_state->gain.max;
+                state.gain.manual = new_state->gain.manual;
+
+                state.exposure.control = new_state->exposure.control;
+                state.exposure.auto_control = new_state->exposure.auto_control;
+                state.exposure.value = new_state->exposure.value;
+                state.exposure.max = new_state->exposure.max;
+                state.exposure.manual = new_state->exposure.manual;
+
+                state.focus.control = new_state->focus.control;
+                state.focus.auto_control = new_state->focus.auto_control;
+                state.focus.value = new_state->focus.value;
+                state.focus.max = new_state->focus.max;
+                state.focus.manual = new_state->focus.manual;
 
                 state.has_auto_focus_continuous =
                         new_state->has_auto_focus_continuous;
@@ -140,10 +173,6 @@ update_state(const mp_state_main *new_state)
         state.preview_buffer_width = new_state->preview_buffer_width;
         state.preview_buffer_height = new_state->preview_buffer_height;
 
-        state.control_gain = new_state->control_gain;
-        state.control_exposure = new_state->control_exposure;
-        state.control_focus = new_state->control_focus;
-        state.control_flash = new_state->control_flash;
         return false;
 }
 
@@ -785,8 +814,8 @@ open_controls(GtkWidget *parent,
 static void
 set_gain(double value)
 {
-        if (state.gain != (int)value) {
-                state.gain = (int)value;
+        if (state.gain.value != (int)value) {
+                state.gain.value_req = (int)value;
                 update_io_pipeline();
         }
 }
@@ -794,8 +823,8 @@ set_gain(double value)
 static void
 set_gain_auto(bool is_auto)
 {
-        if (state.gain_is_manual != !is_auto) {
-                state.gain_is_manual = !is_auto;
+        if (state.gain.manual != !is_auto) {
+                state.gain.manual_req = !is_auto;
                 update_io_pipeline();
         }
 }
@@ -806,9 +835,9 @@ open_iso_controls(GtkWidget *button, gpointer user_data)
         open_controls(button,
                       "ISO",
                       0,
-                      state.gain_max,
-                      state.gain,
-                      !state.gain_is_manual,
+                      state.gain.max,
+                      state.gain.value,
+                      !state.gain.manual,
                       set_gain,
                       set_gain_auto);
 }
@@ -816,21 +845,18 @@ open_iso_controls(GtkWidget *button, gpointer user_data)
 static void
 set_shutter(double value)
 {
-        // TODO: Implement shutter in libmegapixels
-        /*
-        int new_exposure = (int)(value / 360.0 * camera->capture_mode.height);
-        if (new_exposure != exposure) {
-                exposure = new_exposure;
+        int new_exposure = (int)(value / 360.0 * state.camera->current_mode->height);
+        if (new_exposure != state.exposure.value) {
+                state.exposure.value_req = new_exposure;
                 update_io_pipeline();
         }
-         */
 }
 
 static void
 set_shutter_auto(bool is_auto)
 {
-        if (state.exposure_is_manual != !is_auto) {
-                state.exposure_is_manual = !is_auto;
+        if (state.exposure.manual != !is_auto) {
+                state.exposure.manual_req = !is_auto;
                 update_io_pipeline();
         }
 }
@@ -838,12 +864,14 @@ set_shutter_auto(bool is_auto)
 static void
 open_shutter_controls(GtkWidget *button, gpointer user_data)
 {
+        float value =
+                ((float)state.exposure.value / (float)state.exposure.max) * 360.0f;
         open_controls(button,
                       "Shutter",
                       1.0,
                       360.0,
-                      state.exposure,
-                      !state.exposure_is_manual,
+                      value,
+                      !state.exposure.manual,
                       set_shutter,
                       set_shutter_auto);
 }

+ 22 - 12
src/process_pipeline.c

@@ -460,7 +460,7 @@ process_image_for_preview(const uint8_t *image)
         mp_process_pipeline_buffer_ref(output_buffer);
         mp_main_set_preview(output_buffer);
 
-        if (!state_proc.exposure.manual) {
+        if (!state_proc.exposure.manual && state_proc.exposure.auto_control == 0) {
                 int width = output_buffer_width / 3;
                 int height = output_buffer_height / 3;
                 uint32_t *center = g_malloc_n(width * height * sizeof(uint32_t), 1);
@@ -473,9 +473,6 @@ process_image_for_preview(const uint8_t *image)
                              center);
                 libmegapixels_aaa_software_statistics(
                         center, width, height, &state_proc.stats);
-                printf("STAT: %d %d\n",
-                       state_proc.stats.exposure,
-                       state_proc.stats.whitebalance);
         }
 
         // Create a thumbnail from the preview for the last capture
@@ -961,16 +958,19 @@ update_state(MPPipeline *pipeline, const mp_state_proc *new_state)
         state_proc.camera = new_state->camera;
 
         state_proc.gain.control = new_state->gain.control;
+        state_proc.gain.auto_control = new_state->gain.auto_control;
         state_proc.gain.value = new_state->gain.value;
         state_proc.gain.max = new_state->gain.max;
         state_proc.gain.manual = new_state->gain.manual;
 
         state_proc.exposure.control = new_state->exposure.control;
+        state_proc.exposure.auto_control = new_state->exposure.auto_control;
         state_proc.exposure.value = new_state->exposure.value;
         state_proc.exposure.max = new_state->exposure.max;
         state_proc.exposure.manual = new_state->exposure.manual;
 
         state_proc.focus.control = new_state->focus.control;
+        state_proc.focus.auto_control = new_state->focus.auto_control;
         state_proc.focus.value = new_state->focus.value;
         state_proc.focus.max = new_state->focus.max;
         state_proc.focus.manual = new_state->focus.manual;
@@ -1010,19 +1010,29 @@ update_state(MPPipeline *pipeline, const mp_state_proc *new_state)
 
         mp_state_main new_main = {
                 .camera = pr_camera,
-                .gain_is_manual = new_state->gain.manual,
-                .gain = state_proc.gain.value,
-                .gain_max = state_proc.gain.max,
-                .exposure_is_manual = state_proc.exposure.manual,
-                .exposure = state_proc.exposure.value,
                 .has_auto_focus_continuous = false,
                 .has_auto_focus_start = false,
                 .preview_buffer_width = output_buffer_width,
                 .preview_buffer_height = output_buffer_height,
-                .control_gain = new_state->gain.control != 0,
-                .control_exposure = state_proc.exposure.control != 0,
-                .control_focus = state_proc.focus.control != 0,
                 .control_flash = false,
+
+                .gain.control = state_proc.gain.control,
+                .gain.auto_control = state_proc.gain.auto_control,
+                .gain.value = state_proc.gain.value,
+                .gain.max = state_proc.gain.max,
+                .gain.manual = state_proc.gain.manual,
+
+                .exposure.control = state_proc.exposure.control,
+                .exposure.auto_control = state_proc.exposure.auto_control,
+                .exposure.value = state_proc.exposure.value,
+                .exposure.max = state_proc.exposure.max,
+                .exposure.manual = state_proc.exposure.manual,
+
+                .focus.control = state_proc.focus.control,
+                .focus.auto_control = state_proc.focus.auto_control,
+                .focus.value = state_proc.focus.value,
+                .focus.max = state_proc.focus.max,
+                .focus.manual = state_proc.focus.manual,
         };
         mp_main_update_state(&new_main);
 }

+ 15 - 20
src/state.h

@@ -2,9 +2,20 @@
 #include <libmegapixels.h>
 #include <stdbool.h>
 
+typedef struct cstate {
+        uint32_t control;
+        int32_t value;
+        int32_t value_req;
+        int32_t max;
+        bool manual;
+        bool manual_req;
+        uint32_t auto_control;
+} controlstate;
+
 typedef struct state_main {
         libmegapixels_devconfig *configuration;
         libmegapixels_camera *camera;
+        libmegapixels_aaa_stats stats;
 
         // Size of the preview widget
         int preview_width;
@@ -19,38 +30,22 @@ typedef struct state_main {
         int burst_length;
 
         // Control state
-        bool control_gain;
-        bool control_exposure;
         bool control_flash;
-        bool control_focus;
-
-        bool gain_is_manual;
-        int gain;
-        int gain_max;
-
-        bool exposure_is_manual;
-        int exposure;
-
         bool flash_enabled;
+        controlstate gain;
+        controlstate exposure;
+        controlstate focus;
 
         bool has_auto_focus_continuous;
         bool has_auto_focus_start;
 } mp_state_main;
 
-typedef struct cstate {
-        uint32_t control;
-        int32_t value;
-        int32_t value_req;
-        int32_t max;
-        bool manual;
-        bool manual_req;
-} controlstate;
-
 typedef struct state_io {
         libmegapixels_devconfig *configuration;
         libmegapixels_camera *camera;
         libmegapixels_mode *mode_capture;
         libmegapixels_mode *mode_preview;
+        libmegapixels_aaa_stats stats;
 
         int burst_length;
         int captures_remaining;