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
|
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;
|
||||||
|
Reference in New Issue
Block a user