Browse Source

af: Port focus code from millipixels.

Pavel Machek 6 months ago
parent
commit
d87c6263ed
1 changed files with 95 additions and 0 deletions
  1. 95 0
      src/process_pipeline.c

+ 95 - 0
src/process_pipeline.c

@@ -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;