af: Port focus code from millipixels.
This commit is contained in:
@@ -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
|
||||
process_aaa()
|
||||
{
|
||||
@@ -400,6 +489,12 @@ process_aaa()
|
||||
state_proc.blacklevel -= (float)state_proc.stats.blacklevel * 0.001f;
|
||||
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) {
|
||||
int direction = state_proc.stats.exposure;
|
||||
int step = 0;
|
||||
|
Reference in New Issue
Block a user