Browse Source

dgain: Introduce digital gain

Pavel Machek 6 months ago
parent
commit
7c59259f27
5 changed files with 82 additions and 6 deletions
  1. 30 0
      src/io_pipeline.c
  2. 14 0
      src/main.c
  3. 2 0
      src/main.h
  4. 32 5
      src/process_pipeline.c
  5. 4 1
      src/state.h

+ 30 - 0
src/io_pipeline.c

@@ -103,6 +103,12 @@ update_process_pipeline()
                 .gain.max = state_io.gain.max,
                 .gain.manual = state_io.gain.manual,
 
+                .dgain.control = state_io.dgain.control,
+                .dgain.auto_control = state_io.dgain.auto_control,
+                .dgain.value = state_io.dgain.value,
+                .dgain.max = state_io.dgain.max,
+                .dgain.manual = state_io.dgain.manual,
+
                 .exposure.control = state_io.exposure.control,
                 .exposure.auto_control = state_io.exposure.auto_control,
                 .exposure.value = state_io.exposure.value,
@@ -168,6 +174,7 @@ capture(MPPipeline *pipeline, const void *data)
         // the value seems to be 248 which creates a 5 frame burst
         // for manual gain you can go up to 11 frames
         state_io.gain.value = mp_camera_control_get_int32(&state_io.gain.control);
+        state_io.dgain.value = mp_camera_control_get_int32(&state_io.dgain.control);
         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 = MAX(1, state_io.burst_length);
@@ -509,6 +516,24 @@ init_controls()
                 state_io.gain.auto_control.id = 0;
         }
 
+        MPControl dgain_control;
+        if (mp_camera_query_control(
+                    state_io.camera->sensor_fd, V4L2_CID_DIGITAL_GAIN, &dgain_control)) {
+                state_io.dgain.control = dgain_control;
+                state_io.dgain.max = dgain_control.max;
+		printf("Have d/gain, max: %d\n", dgain_control.max);
+        } else {
+                state_io.dgain.max = 0;
+                state_io.dgain.control.id = 0;
+        }
+	mp_camera_control_set_int32(&state_io.gain.control, 768);
+        if (state_io.dgain.control.id) {
+                state_io.dgain.value =
+                        mp_camera_control_get_int32(&state_io.dgain.control);
+        } else {
+                state_io.dgain.value = 0;
+        }
+
         MPControl exposure_control;
         if (mp_camera_query_control(state_io.camera->sensor_fd,
                                     V4L2_CID_EXPOSURE,
@@ -648,6 +673,11 @@ update_state(MPPipeline *pipeline, const mp_state_io *new_state)
                 state_io.gain.manual = new_state->gain.manual;
                 state_io.gain.manual_req = new_state->gain.manual_req;
 
+                state_io.dgain.value = new_state->dgain.value;
+                state_io.dgain.value_req = new_state->dgain.value_req;
+                state_io.dgain.manual = new_state->dgain.manual;
+                state_io.dgain.manual_req = new_state->dgain.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;

+ 14 - 0
src/main.c

@@ -128,6 +128,14 @@ update_io_pipeline()
                 .gain.manual = state.gain.manual,
                 .gain.manual_req = state.gain.manual_req,
 
+                .dgain.control = state.dgain.control,
+                .dgain.auto_control = state.dgain.auto_control,
+                .dgain.value = state.dgain.value,
+                .dgain.value_req = state.dgain.value_req,
+                .dgain.max = state.dgain.max,
+                .dgain.manual = state.dgain.manual,
+                .dgain.manual_req = state.dgain.manual_req,
+
                 .exposure.control = state.exposure.control,
                 .exposure.auto_control = state.exposure.auto_control,
                 .exposure.value = state.exposure.value,
@@ -186,6 +194,12 @@ update_state(const mp_state_main *new_state)
         state.gain.max = new_state->gain.max;
         state.gain.manual = new_state->gain.manual;
 
+        state.dgain.control = new_state->dgain.control;
+        state.dgain.auto_control = new_state->dgain.auto_control;
+        state.dgain.value = new_state->dgain.value;
+        state.dgain.max = new_state->dgain.max;
+        state.dgain.manual = new_state->dgain.manual;
+
         state.exposure.control = new_state->exposure.control;
         state.exposure.auto_control = new_state->exposure.auto_control;
         state.exposure.value = new_state->exposure.value;

+ 2 - 0
src/main.h

@@ -14,6 +14,8 @@ struct mp_main_state {
         bool gain_is_manual;
         int gain;
         int gain_max;
+        int dgain;
+        int dgain_max;
 
         bool exposure_is_manual;
         int exposure;

+ 32 - 5
src/process_pipeline.c

@@ -505,7 +505,6 @@ process_aaa()
                 int step = 0;
                 if (direction > 0) {
                         // Preview is too dark
-
                         // Try raising the exposure time first
                         if (state_proc.exposure.value < state_proc.exposure.max) {
                                 step = state_proc.exposure.value / 4;
@@ -515,19 +514,30 @@ process_aaa()
                                         (step * direction);
                                 printf("Expose + %d\n",
                                        state_proc.exposure.value_req);
-                        } else {
+                        } else if (state_proc.gain.value < state_proc.gain.max) {
                                 // Raise sensor gain if exposure limit is hit
                                 step = state_proc.gain.value / 4;
                                 step = step < 4 ? 4 : step;
                                 state_proc.gain.value_req =
                                         state_proc.gain.value + (step * direction);
                                 printf("Gain + %d\n", state_proc.gain.value_req);
-                        }
+                        } else {
+                                // Raise sensor gain if exposure limit is hit
+                                step = state_proc.dgain.value / 4;
+                                step = step < 4 ? 4 : step;
+                                state_proc.dgain.value_req =
+				        state_proc.dgain.value + (step * direction);
+                                printf("D/Gain + %d\n", state_proc.dgain.value_req);
+			}
                 } else if (direction < 0) {
                         // Preview is too bright
-
                         // Lower the sensor gain first to have less noise
-                        if (state_proc.gain.value > 0) {
+                        if (state_proc.dgain.value > 256 /* state_proc.dgain.min FIXME */) {
+                                step = state_proc.dgain.value / 4;
+                                state_proc.dgain.value_req =
+                                        state_proc.dgain.value + (step * direction);
+                                printf("D/Gain - %d\n", state_proc.gain.value_req);
+			} else if (state_proc.gain.value > 0) {
                                 step = state_proc.gain.value / 4;
                                 state_proc.gain.value_req =
                                         state_proc.gain.value + (step * direction);
@@ -544,12 +554,16 @@ process_aaa()
                 }
 
                 clamp_control(&state_proc.gain);
+                clamp_control(&state_proc.dgain);
                 clamp_control(&state_proc.exposure);
                 mp_io_pipeline_set_control_int32(&state_proc.gain.control,
                                                  state_proc.gain.value_req);
+                mp_io_pipeline_set_control_int32(&state_proc.dgain.control,
+                                                 state_proc.dgain.value_req);
                 mp_io_pipeline_set_control_int32(&state_proc.exposure.control,
                                                  state_proc.exposure.value_req);
                 state_proc.gain.value = state_proc.gain.value_req;
+                state_proc.dgain.value = state_proc.dgain.value_req;
                 state_proc.exposure.value = state_proc.exposure.value_req;
         }
 
@@ -1378,6 +1392,12 @@ update_state(MPPipeline *pipeline, const mp_state_proc *new_state)
         state_proc.gain.max = new_state->gain.max;
         state_proc.gain.manual = new_state->gain.manual;
 
+        state_proc.dgain.control = new_state->dgain.control;
+        state_proc.dgain.auto_control = new_state->dgain.auto_control;
+        state_proc.dgain.value = new_state->dgain.value;
+        state_proc.dgain.max = new_state->dgain.max;
+        state_proc.dgain.manual = new_state->dgain.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;
@@ -1453,6 +1473,13 @@ update_state(MPPipeline *pipeline, const mp_state_proc *new_state)
                 .gain.max = state_proc.gain.max,
                 .gain.manual = state_proc.gain.manual,
 
+                .dgain.control = state_proc.dgain.control,
+                .dgain.auto_control = state_proc.dgain.auto_control,
+                .dgain.value = state_proc.dgain.value,
+                .dgain.value_req = state_proc.dgain.value_req,
+                .dgain.max = state_proc.dgain.max,
+                .dgain.manual = state_proc.dgain.manual,
+
                 .exposure.control = state_proc.exposure.control,
                 .exposure.auto_control = state_proc.exposure.auto_control,
                 .exposure.value = state_proc.exposure.value,

+ 4 - 1
src/state.h

@@ -34,6 +34,7 @@ typedef struct state_main {
         // Control state
         bool flash_enabled;
         controlstate gain;
+        controlstate dgain;
         controlstate exposure;
         controlstate focus;
 
@@ -55,6 +56,7 @@ typedef struct state_io {
 
         // Control state
         controlstate gain;
+        controlstate dgain;
         controlstate exposure;
         controlstate focus;
         controlstate red;
@@ -97,6 +99,7 @@ typedef struct state_proc {
 
         float balance[3];
         controlstate gain;
+        controlstate dgain;
         controlstate exposure;
         controlstate focus;
 
@@ -111,4 +114,4 @@ typedef struct state_proc {
         int mode_focus;
 
         bool flash_enabled;
-} mp_state_proc;
+} mp_state_proc;