From ffa888a5750694b146299d09f49cadde27ea4445 Mon Sep 17 00:00:00 2001
From: Jakob Bornecrantz <jakob@collabora.com>
Date: Wed, 2 Sep 2020 11:57:47 +0100
Subject: [PATCH] d/v4l2: Use different tweaks depending on capture type

---
 src/xrt/drivers/v4l2/v4l2_driver.c | 90 +++++++++++++++++++++---------
 1 file changed, 63 insertions(+), 27 deletions(-)

diff --git a/src/xrt/drivers/v4l2/v4l2_driver.c b/src/xrt/drivers/v4l2/v4l2_driver.c
index 60c3b2693..6cf7f96c0 100644
--- a/src/xrt/drivers/v4l2/v4l2_driver.c
+++ b/src/xrt/drivers/v4l2/v4l2_driver.c
@@ -126,15 +126,24 @@ struct v4l2_frame
 	struct v4l2_buffer v_buf;
 };
 
+struct v4l2_state_want
+{
+	bool active;
+	int value;
+};
+
 /*!
  * @ingroup drv_v4l2
  */
 struct v4l2_control_state
 {
-	int force;
 	int id;
-	int want;
+	int force;
+
+	struct v4l2_state_want want[2];
+
 	int value;
+
 	const char *name;
 };
 
@@ -158,7 +167,7 @@ struct v4l2_fs
 		bool timeperframe;
 	} has;
 
-
+	enum xrt_fs_capture_type capture_type;
 	struct v4l2_control_state states[256];
 	size_t num_states;
 
@@ -278,14 +287,18 @@ v4l2_control_set(struct v4l2_fs *vid, uint32_t id, int value)
 }
 
 static void
-v4l2_add_control_state(
-    struct v4l2_fs *vid, int control, int want, int force, const char *name)
+v4l2_add_control_state(struct v4l2_fs *vid,
+                       int control,
+                       struct v4l2_state_want want[2],
+                       int force,
+                       const char *name)
 {
 	struct v4l2_control_state *state = &vid->states[vid->num_states++];
 
 	state->id = control;
 	state->name = name;
-	state->want = want;
+	state->want[0] = want[0];
+	state->want[1] = want[1];
 	state->force = force;
 }
 
@@ -354,31 +367,48 @@ v4l2_query_cap_and_validate(struct v4l2_fs *vid)
 	vid->quirks.ps4_cam =
 	    strcmp(card, "USB Camera-OV580: USB Camera-OV") == 0;
 
+#define ADD(CONTROL, WANT1, WANT2, WANT3, WANT4, NAME)                         \
+	do {                                                                   \
+		struct v4l2_state_want want[2] = {{WANT1, WANT2},              \
+		                                  {WANT3, WANT4}};             \
+		v4l2_add_control_state(vid, V4L2_CID_##CONTROL, want, 2,       \
+		                       NAME);                                  \
+	} while (false)
+
 	if (vid->quirks.ps4_cam) {
 		// The experimented best controls to best track things.
-		v4l2_add_control_state(vid, V4L2_CID_GAIN, 0, 2, "gain");
-		v4l2_add_control_state(vid, V4L2_CID_AUTO_WHITE_BALANCE, 0, 2,
-		                       "auto_white_balance");
-		v4l2_add_control_state(vid, V4L2_CID_WHITE_BALANCE_TEMPERATURE,
-		                       3900, 2, "white_balance_temperature");
-		v4l2_add_control_state(vid, V4L2_CID_EXPOSURE_AUTO, 2, 2,
-		                       "exposure_auto");
-		v4l2_add_control_state(
-		    vid, V4L2_CID_EXPOSURE_ABSOLUTE,
-		    debug_get_num_option_v4l2_exposure_absolute(), 2,
+		ADD(GAIN,              //
+		    true, 0, false, 0, //
+		    "gain");
+		ADD(AUTO_WHITE_BALANCE, //
+		    true, 0, true, 1,   //
+		    "auto_white_balance");
+		ADD(WHITE_BALANCE_TEMPERATURE, //
+		    true, 3900, false, 0,      //
+		    "white_balance_temperature");
+		ADD(EXPOSURE_AUTO,    //
+		    true, 2, true, 0, //
+		    "exposure_auto");
+		long num = debug_get_num_option_v4l2_exposure_absolute();
+		ADD(EXPOSURE_ABSOLUTE,   //
+		    true, num, false, 0, //
 		    "exposure_absolute");
 	}
 
 	if (strcmp(card, "3D USB Camera: 3D USB Camera") == 0) {
 		// The experimented best controls to best track things.
-		v4l2_add_control_state(vid, V4L2_CID_AUTO_WHITE_BALANCE, 0, 2,
-		                       "auto_white_balance");
-		v4l2_add_control_state(vid, V4L2_CID_WHITE_BALANCE_TEMPERATURE,
-		                       6500, 2, "white_balance_temperature");
-		v4l2_add_control_state(vid, V4L2_CID_EXPOSURE_AUTO, 1, 2,
-		                       "exposure_auto");
-		v4l2_add_control_state(vid, V4L2_CID_EXPOSURE_ABSOLUTE, 10, 2,
-		                       "exposure_absolute");
+		ADD(AUTO_WHITE_BALANCE, //
+		    true, 0, true, 1,   //
+		    "auto_white_balance");
+		ADD(WHITE_BALANCE_TEMPERATURE, //
+		    true, 6500, false, 0,      //
+		    "white_balance_temperature");
+		ADD(EXPOSURE_AUTO,    //
+		    true, 1, true, 3, //
+		    "exposure_auto");
+		ADD(EXPOSURE_ABSOLUTE,  //
+		    true, 10, false, 0, //
+		    "exposure_absolute");
 	}
 
 	// Done
@@ -594,12 +624,17 @@ v4l2_set_control_if_diff(struct v4l2_fs *vid, struct v4l2_control_state *state)
 	int value = 0;
 	int ret = 0;
 
+	struct v4l2_state_want *want = &state->want[vid->capture_type];
+	if (!want->active) {
+		return;
+	}
+
 	ret = v4l2_control_get(vid, state->id, &value);
 	if (ret != 0) {
 		return;
 	}
 
-	if (value == state->want && state->force <= 0) {
+	if (value == want->value && state->force <= 0) {
 		return;
 	}
 
@@ -610,7 +645,7 @@ v4l2_set_control_if_diff(struct v4l2_fs *vid, struct v4l2_control_state *state)
 	        state->want, value, state->force);
 #endif
 
-	ret = v4l2_control_set(vid, state->id, state->want);
+	ret = v4l2_control_set(vid, state->id, want->value);
 	if (ret != 0) {
 		fprintf(stderr, "Failed to set ");
 		dump_contron_name(state->id);
@@ -690,6 +725,7 @@ v4l2_fs_stream_start(struct xrt_fs *xfs,
 
 	vid->sink = xs;
 	vid->is_running = true;
+	vid->capture_type = capture_type;
 	if (pthread_create(&vid->stream_thread, NULL, v4l2_fs_stream_run,
 	                   xfs)) {
 		vid->is_running = false;
@@ -813,7 +849,7 @@ v4l2_fs_create(struct xrt_frame_context *xfctx, const char *path)
 	u_var_add_bool(vid, &vid->print_debug, "Debug");
 	u_var_add_bool(vid, &vid->print_spew, "Spew");
 	for (size_t i = 0; i < vid->num_states; i++) {
-		u_var_add_i32(vid, &vid->states[i].want, vid->states[i].name);
+		u_var_add_i32(vid, &vid->states[i].want[0].value, vid->states[0].name);
 	}
 	// clang-format on