af: Port focus code from millipixels.

This commit is contained in:
Pavel Machek
2024-09-02 21:07:34 +00:00
parent 88b9ca9e50
commit d87c6263ed

View File

@@ -374,6 +374,95 @@ clamp_control(controlstate *control)
} }
} }
static int focus;
static int focus_phase;
static void auto_focus_start(void)
{
focus_phase = 0;
focus = 0;
}
struct focus_stats {
unsigned long long sharp;
};
#define PH_SWEEP 5
#define PH_DONE 6
static void auto_focus_step(const struct focus_stats *stats)
{
static uint64_t best_sharp, best_focus;
static const bool debug = true;
if (debug) printf("Phase %d, sharp %d best %d ", focus_phase, (int)(stats->sharp / 10000), (int)(best_sharp/ 10000));
if (focus_phase >= PH_DONE) {
focus_phase++;
if (stats->sharp < (best_sharp * 6) / 10) {
if (debug) printf("Lost, restart.\n");
auto_focus_start();
return;
}
if (debug) printf("Idle @ %d.\n", focus);
return;
}
if (focus_phase < PH_SWEEP) {
best_sharp = 0;
focus = 200;
focus_phase ++;
best_focus = 0;
if (debug) printf("...prepare\n");
goto set;
}
if (stats->sharp > best_sharp) {
if (debug) printf("Still improving, focus %d\n", focus);
best_focus = focus;
best_sharp = stats->sharp;
focus += 10;
goto set;
}
if (stats->sharp < (best_sharp * 8) / 10) {
if (debug) printf("AF done?\n");
focus = best_focus - 10;
focus_phase = PH_DONE;
goto set;
}
if (focus > 1023) {
if (debug) printf("Finished range\n");
focus = best_focus - 10;
focus_phase = PH_DONE;
goto set;
}
if (debug) printf("Not improving\n");
focus += 10;
set:
state_proc.focus.value_req = focus;
clamp_control(&state_proc.focus);
mp_io_pipeline_set_control_int32(&state_proc.focus.control,
state_proc.focus.value_req);
state_proc.focus.value = state_proc.focus.value_req;
}
static void
focus_stats(struct focus_stats *stats, const unsigned int *frame, const int width,
const int height)
{
unsigned long long sharp = 0;
unsigned int last_y = 0;
for (ssize_t p = 0; p < width * height; p++) {
unsigned int r = (frame[p] >> 0) & 0xff;
unsigned int g = (frame[p] >> 8) & 0xff;
unsigned int b = (frame[p] >> 16) & 0xff;
unsigned int y = (r + g + b) / 3;
sharp += (y-last_y) * (y-last_y);
last_y = y;
}
stats->sharp = sharp;
}
static void static void
process_aaa() process_aaa()
{ {
@@ -400,6 +489,12 @@ process_aaa()
state_proc.blacklevel -= (float)state_proc.stats.blacklevel * 0.001f; state_proc.blacklevel -= (float)state_proc.stats.blacklevel * 0.001f;
state_proc.blacklevel = clamp_float(state_proc.blacklevel, 0.0f, 0.07f); state_proc.blacklevel = clamp_float(state_proc.blacklevel, 0.0f, 0.07f);
if (auto_focus) {
struct focus_stats stats;
focus_stats(&stats, center, width, height);
auto_focus_step(&stats);
}
if (auto_exposure) { if (auto_exposure) {
int direction = state_proc.stats.exposure; int direction = state_proc.stats.exposure;
int step = 0; int step = 0;