From 3c116f2307bee6a2c61a6b7faab072ee3ea6fc7a Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Mon, 20 Nov 2023 21:28:31 +0100 Subject: [PATCH] device: some v4l2 cameras do not accept parameters unless streaming This fixes 3DO camera not accepting `--camera-options=focus_absolute=100` and `--camera-options=focus_automatic_continuous=0`, and not properly configuring the sensor. The settings are applied twice (if failed) to ignore ordering problems related to auto-focus and focus-absolute value command line order. --- device/camera/camera.c | 10 +++++++++- device/device.c | 14 +++++++++++--- device/device.h | 2 +- 3 files changed, 21 insertions(+), 5 deletions(-) diff --git a/device/camera/camera.c b/device/camera/camera.c index 4c47982..e6bb1a6 100644 --- a/device/camera/camera.c +++ b/device/camera/camera.c @@ -99,7 +99,15 @@ void camera_capture_add_callbacks(camera_t *camera, buffer_list_t *capture, link int camera_set_params(camera_t *camera) { device_set_fps(camera->camera, camera->options.fps); - device_set_option_list(camera->camera, camera->options.options); + + // HACK: + // Some cameras require to be in streaming to apply settings + // This applies twice to avoid ordering issues (auto-focus vs focus value) + if (camera->camera->n_capture_list > 0) + buffer_list_set_stream(camera->camera->capture_lists[0], true); + if (device_set_option_list(camera->camera, camera->options.options) < 0) + device_set_option_list(camera->camera, camera->options.options); + device_set_option_list(camera->isp, camera->options.isp.options); if (camera->options.auto_focus) { diff --git a/device/device.c b/device/device.c index 30c1499..147a3a0 100644 --- a/device/device.c +++ b/device/device.c @@ -250,22 +250,26 @@ int device_set_option_string(device_t *dev, const char *key, const char *value) return -1; } -void device_set_option_list(device_t *dev, const char *option_list) +int device_set_option_list(device_t *dev, const char *option_list) { if (!dev || !option_list || !option_list[0]) { - return; + return 0; } char *start = strdup(option_list); char *string = start; char *option; + bool err = false; + int count = 0; while ((option = strsep(&string, OPTION_VALUE_LIST_SEP)) != NULL) { char *value = option; char *key = strsep(&value, "="); if (value) { - device_set_option_string(dev, key, value); + if (device_set_option_string(dev, key, value) < 0) { + err = true; + } } else { LOG_INFO(dev, "Missing 'key=value' for '%s'", option); continue; @@ -273,9 +277,13 @@ void device_set_option_list(device_t *dev, const char *option_list) // consume all separators while (strsep(&value, "=")); + + count++; } free(start); + + return err ? -count : count; } int device_output_enqueued(device_t *dev) diff --git a/device/device.h b/device/device.h index 992871a..ce22cae 100644 --- a/device/device.h +++ b/device/device.h @@ -112,7 +112,7 @@ int device_dump_options2(device_t *dev, device_option_fn fn, void *opaque); int device_set_fps(device_t *dev, int desired_fps); int device_set_rotation(device_t *dev, bool vflip, bool hflip); int device_set_option_string(device_t *dev, const char *option, const char *value); -void device_set_option_list(device_t *dev, const char *option_list); +int device_set_option_list(device_t *dev, const char *option_list); int device_output_enqueued(device_t *dev); int device_capture_enqueued(device_t *dev, int *max);