The open source OpenXR runtime

d/wmr: Adjust exposure and gain individually for each camera

+89 -38
+1 -1
src/xrt/auxiliary/util/u_autoexpgain.c
··· 42 42 #define INITIAL_BRIGHTNESS 0.5 43 43 #define INITIAL_MAX_BRIGHTNESS_STEP 0.1 44 44 #define INITIAL_THRESHOLD 0.1 45 - #define GRID_COLS 40 //!< Amount of columns for the histogram sample grid 45 + #define GRID_COLS 32 //!< Amount of columns for the histogram sample grid 46 46 47 47 //! AEG State machine states 48 48 enum u_aeg_state
+85 -35
src/xrt/drivers/wmr/wmr_camera.c
··· 24 24 #include "util/u_frame.h" 25 25 #include "util/u_trace_marker.h" 26 26 27 + #include "wmr_config.h" 27 28 #include "wmr_protocol.h" 28 29 #include "wmr_camera.h" 29 30 30 31 //! Specifies whether the user wants to enable autoexposure from the start. 31 32 DEBUG_GET_ONCE_BOOL_OPTION(wmr_autoexposure, "WMR_AUTOEXPOSURE", true) 32 33 34 + //! Specifies whether the user wants to use the same exp/gain values for all cameras 35 + DEBUG_GET_ONCE_BOOL_OPTION(wmr_unify_expgain, "WMR_UNIFY_EXPGAIN", false) 36 + 33 37 static int 34 - update_expgain(struct wmr_camera *cam, struct xrt_frame *xf); 38 + update_expgain(struct wmr_camera *cam, struct xrt_frame **frames); 35 39 36 40 /* 37 41 * ··· 97 101 98 102 struct libusb_transfer *xfers[NUM_XFERS]; 99 103 100 - bool manual_control; //!< Whether to control exp/gain manually or with aeg 101 - uint16_t last_exposure, exposure; 102 - uint8_t last_gain, gain; 103 - struct u_var_draggable_u16 exposure_ui; //! Widget to control `exposure` value 104 - struct u_autoexpgain *aeg; 104 + struct wmr_camera_expgain 105 + { 106 + bool manual_control; //!< Whether to control exp/gain manually or with aeg 107 + uint16_t last_exposure, exposure; 108 + uint8_t last_gain, gain; 109 + struct u_var_draggable_u16 exposure_ui; //! Widget to control `exposure` value 110 + struct u_autoexpgain *aeg; 111 + } ceg[WMR_MAX_CAMERAS]; //!< Camera exposure-gain control 112 + bool unify_expgains; //!< Whether to use the same exposure/gain values for all cameras 105 113 106 114 struct u_sink_debug debug_sinks[2]; 107 115 ··· 370 378 u_frame_create_roi(xf, cam->configs[0].roi, &xf_left); 371 379 u_frame_create_roi(xf, cam->configs[1].roi, &xf_right); 372 380 373 - update_expgain(cam, xf_left); 381 + struct xrt_frame *frames[WMR_MAX_CAMERAS] = {xf_left, xf_right, NULL, NULL}; 382 + update_expgain(cam, frames); 374 383 375 384 if (cam->left_sink != NULL) { 376 385 xrt_sink_push_frame(cam->left_sink, xf_left); ··· 401 410 wmr_camera_open(struct xrt_prober_device *dev_holo, 402 411 struct xrt_frame_sink *left_sink, 403 412 struct xrt_frame_sink *right_sink, 413 + int camera_count, 404 414 enum u_logging_level log_level) 405 415 { 406 416 DRV_TRACE_MARKER(); ··· 410 420 int i; 411 421 412 422 cam->log_level = log_level; 413 - cam->exposure = DEFAULT_EXPOSURE; 414 - cam->gain = DEFAULT_GAIN; 415 423 416 424 if (os_thread_helper_init(&cam->usb_thread) != 0) { 417 425 WMR_CAM_ERROR(cam, "Failed to initialise threading"); ··· 450 458 451 459 bool enable_aeg = debug_get_bool_option_wmr_autoexposure(); 452 460 int frame_delay = 3; // WMR takes about three frames until the cmd changes the image 453 - cam->aeg = u_autoexpgain_create(U_AEG_STRATEGY_TRACKING, enable_aeg, frame_delay); 461 + cam->unify_expgains = debug_get_bool_option_wmr_unify_expgain(); 454 462 455 - cam->exposure_ui.val = &cam->exposure; 456 - cam->exposure_ui.max = WMR_MAX_EXPOSURE; 457 - cam->exposure_ui.min = WMR_MIN_EXPOSURE; 458 - cam->exposure_ui.step = 25; 463 + for (int i = 0; i < camera_count; i++) { 464 + struct wmr_camera_expgain *ceg = &cam->ceg[i]; 465 + ceg->manual_control = false; 466 + ceg->last_exposure = DEFAULT_EXPOSURE; 467 + ceg->exposure = DEFAULT_EXPOSURE; 468 + ceg->last_gain = DEFAULT_GAIN; 469 + ceg->gain = DEFAULT_GAIN; 470 + ceg->exposure_ui.val = &ceg->exposure; 471 + ceg->exposure_ui.max = WMR_MAX_EXPOSURE; 472 + ceg->exposure_ui.min = WMR_MIN_EXPOSURE; 473 + ceg->exposure_ui.step = 25; 474 + ceg->aeg = u_autoexpgain_create(U_AEG_STRATEGY_TRACKING, enable_aeg, frame_delay); 475 + } 459 476 460 477 u_sink_debug_init(&cam->debug_sinks[0]); 461 478 u_sink_debug_init(&cam->debug_sinks[1]); 462 479 u_var_add_root(cam, "WMR Camera", true); 463 480 u_var_add_log_level(cam, &cam->log_level, "Log level"); 464 - u_var_add_bool(cam, &cam->manual_control, "Manual exposure and gain control"); 465 - u_var_add_draggable_u16(cam, &cam->exposure_ui, "Exposure (usec)"); 466 - u_var_add_u8(cam, &cam->gain, "Gain"); 467 - u_autoexpgain_add_vars(cam->aeg, cam, ""); 468 - u_var_add_gui_header(cam, NULL, "Camera Streams"); 481 + 482 + u_var_add_gui_header_begin(cam, NULL, "Camera Streams"); 469 483 u_var_add_sink_debug(cam, &cam->debug_sinks[0], "Tracking Streams"); 470 484 u_var_add_sink_debug(cam, &cam->debug_sinks[1], "Controller Streams"); 485 + u_var_add_gui_header_end(cam, NULL, NULL); 486 + 487 + u_var_add_gui_header_begin(cam, NULL, "Exposure and gain control"); 488 + u_var_add_bool(cam, &cam->unify_expgains, "Use same values"); 489 + 490 + for (int i = 0; i < camera_count; i++) { 491 + struct wmr_camera_expgain *ceg = &cam->ceg[i]; 492 + char label[256] = {0}; 493 + 494 + (void)snprintf(label, sizeof(label), "Control for camera %d", i); 495 + u_var_add_gui_header_begin(cam, NULL, label); 496 + 497 + (void)snprintf(label, sizeof(label), "[%d] Manual exposure and gain control", i); 498 + u_var_add_bool(cam, &ceg->manual_control, label); 499 + 500 + (void)snprintf(label, sizeof(label), "[%d] Exposure (usec)", i); 501 + u_var_add_draggable_u16(cam, &ceg->exposure_ui, label); 502 + 503 + (void)snprintf(label, sizeof(label), "[%d] Gain", i); 504 + u_var_add_u8(cam, &ceg->gain, label); 505 + 506 + (void)snprintf(label, sizeof(label), "[%d] ", i); 507 + u_autoexpgain_add_vars(ceg->aeg, cam, label); 508 + 509 + u_var_add_gui_header_end(cam, NULL, NULL); 510 + } 511 + 512 + u_var_add_gui_header_end(cam, NULL, "Auto exposure and gain control END"); 471 513 472 514 cam->left_sink = left_sink; 473 515 cam->right_sink = right_sink; ··· 614 656 } 615 657 616 658 static int 617 - update_expgain(struct wmr_camera *cam, struct xrt_frame *xf) 659 + update_expgain(struct wmr_camera *cam, struct xrt_frame **frames) 618 660 { 619 - if (!cam->manual_control && xf != NULL) { 620 - u_autoexpgain_update(cam->aeg, xf); 621 - cam->exposure = u_autoexpgain_get_exposure(cam->aeg); 622 - cam->gain = u_autoexpgain_get_gain(cam->aeg); 623 - } 624 - 625 - if (cam->last_exposure == cam->exposure && cam->last_gain == cam->gain) { 626 - return 0; 627 - } 628 - cam->last_exposure = cam->exposure; 629 - cam->last_gain = cam->gain; 630 - 631 661 int res = 0; 632 662 for (int i = 0; i < cam->config_count; i++) { 633 663 const struct wmr_camera_config *config = &cam->configs[i]; 634 664 if (config->purpose != WMR_CAMERA_PURPOSE_HEAD_TRACKING) { 635 665 continue; 636 666 } 637 - res = wmr_camera_set_exposure_gain(cam, config->location, cam->exposure, cam->gain); 638 - if (res != 0) { 667 + 668 + struct wmr_camera_expgain *ceg = &cam->ceg[i]; 669 + 670 + if (!ceg->manual_control && frames != NULL && frames[i] != NULL) { 671 + if (!cam->unify_expgains || i == 0) { 672 + u_autoexpgain_update(ceg->aeg, frames[i]); 673 + ceg->exposure = (uint16_t)u_autoexpgain_get_exposure(ceg->aeg); 674 + ceg->gain = (uint8_t)u_autoexpgain_get_gain(ceg->aeg); 675 + } else { 676 + ceg->exposure = cam->ceg[0].exposure; 677 + ceg->gain = cam->ceg[0].gain; 678 + } 679 + } 680 + 681 + if (ceg->last_exposure == ceg->exposure && ceg->last_gain == ceg->gain) { 682 + continue; 683 + } 684 + ceg->last_exposure = ceg->exposure; 685 + ceg->last_gain = ceg->gain; 686 + 687 + bool status = wmr_camera_set_exposure_gain(cam, config->location, ceg->exposure, ceg->gain); 688 + if (status != 0) { 639 689 WMR_CAM_ERROR(cam, "Failed to set exposure and gain for camera %d", i); 640 - return res; 641 690 } 691 + res |= status; 642 692 } 643 693 return res; 644 694 }
+2 -1
src/xrt/drivers/wmr/wmr_camera.h
··· 27 27 wmr_camera_open(struct xrt_prober_device *dev_holo, 28 28 struct xrt_frame_sink *left_sink, 29 29 struct xrt_frame_sink *right_sink, 30 + int camera_count, 30 31 enum u_logging_level log_level); 31 32 void 32 33 wmr_camera_free(struct wmr_camera *cam); ··· 55 56 #else 56 57 57 58 /* Stubs to disable camera functions without libusb */ 58 - #define wmr_camera_open(dev_holo, left_sink, right_sink, log_level) NULL 59 + #define wmr_camera_open(dev_holo, left_sink, right_sink, camera_count, log_level) NULL 59 60 #define wmr_camera_free(cam) 60 61 #define wmr_camera_start(cam, cam_configs, n_configs) false 61 62 #define wmr_camera_stop(cam) false
+1 -1
src/xrt/drivers/wmr/wmr_source.c
··· 305 305 ws->in_sinks.left = &ws->left_sink; 306 306 ws->in_sinks.right = &ws->right_sink; 307 307 ws->in_sinks.imu = &ws->imu_sink; 308 - ws->camera = wmr_camera_open(dev_holo, ws->in_sinks.left, ws->in_sinks.right, ws->log_level); 308 + ws->camera = wmr_camera_open(dev_holo, ws->in_sinks.left, ws->in_sinks.right, cfg.n_cameras, ws->log_level); 309 309 ws->config = cfg; 310 310 311 311 // Setup UI