dgain: Introduce digital gain

This commit is contained in:
Pavel Machek
2024-08-31 22:06:03 +00:00
parent bbc077f528
commit 7c59259f27
5 changed files with 82 additions and 6 deletions

View File

@@ -103,6 +103,12 @@ update_process_pipeline()
.gain.max = state_io.gain.max, .gain.max = state_io.gain.max,
.gain.manual = state_io.gain.manual, .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.control = state_io.exposure.control,
.exposure.auto_control = state_io.exposure.auto_control, .exposure.auto_control = state_io.exposure.auto_control,
.exposure.value = state_io.exposure.value, .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 // the value seems to be 248 which creates a 5 frame burst
// for manual gain you can go up to 11 frames // 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.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; 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 = (int)fmax(sqrtf(gain_norm) * 10, 2) + 1;
state_io.burst_length = MAX(1, state_io.burst_length); state_io.burst_length = MAX(1, state_io.burst_length);
@@ -509,6 +516,24 @@ init_controls()
state_io.gain.auto_control.id = 0; 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; MPControl exposure_control;
if (mp_camera_query_control(state_io.camera->sensor_fd, if (mp_camera_query_control(state_io.camera->sensor_fd,
V4L2_CID_EXPOSURE, 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 = new_state->gain.manual;
state_io.gain.manual_req = new_state->gain.manual_req; 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 = new_state->exposure.value;
state_io.exposure.value_req = new_state->exposure.value_req; state_io.exposure.value_req = new_state->exposure.value_req;
state_io.exposure.manual = new_state->exposure.manual; state_io.exposure.manual = new_state->exposure.manual;

View File

@@ -128,6 +128,14 @@ update_io_pipeline()
.gain.manual = state.gain.manual, .gain.manual = state.gain.manual,
.gain.manual_req = state.gain.manual_req, .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.control = state.exposure.control,
.exposure.auto_control = state.exposure.auto_control, .exposure.auto_control = state.exposure.auto_control,
.exposure.value = state.exposure.value, .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.max = new_state->gain.max;
state.gain.manual = new_state->gain.manual; 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.control = new_state->exposure.control;
state.exposure.auto_control = new_state->exposure.auto_control; state.exposure.auto_control = new_state->exposure.auto_control;
state.exposure.value = new_state->exposure.value; state.exposure.value = new_state->exposure.value;

View File

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

View File

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

View File

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