From aafd120af3ffc70eb27ce1c9573a7cabae6adce1 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Wed, 22 Feb 2023 17:59:29 +0100 Subject: [PATCH] libcamera: support `Rectangle` and `Size` types Fixes: https://github.com/ayufan/camera-streamer/issues/28 Replaces: https://github.com/ayufan/camera-streamer/pull/30 --- cmd/camera-streamer/http.c | 54 ++++++++++++++++++++++---------------- device/device.c | 2 +- device/libcamera/device.cc | 40 ++++++++++++++++++++++++++-- 3 files changed, 70 insertions(+), 26 deletions(-) diff --git a/cmd/camera-streamer/http.c b/cmd/camera-streamer/http.c index ee5915d..7f06ad4 100644 --- a/cmd/camera-streamer/http.c +++ b/cmd/camera-streamer/http.c @@ -13,42 +13,48 @@ extern unsigned char html_webrtc_html[]; extern unsigned int html_webrtc_html_len; extern camera_t *camera; -void *camera_http_set_option(http_worker_t *worker, FILE *stream, const char *key, const char *value, void *headersp) +static void http_once(FILE *stream, void (*fn)(FILE *stream, const char *data), void *headersp) { bool *headers = headersp; + if (!*headers) { + fn(stream, ""); + *headers = true; + } +} + +void *camera_http_set_option(http_worker_t *worker, FILE *stream, const char *key, const char *value, void *headersp) +{ if (!camera) { - if (!*headers) { - http_500(stream, ""); - *headers = true; - } + http_once(stream, http_500, headersp); fprintf(stream, "No camera attached.\r\n"); return NULL; } - bool set = false; + bool found = false; for (int i = 0; i < MAX_DEVICES; i++) { - if (device_set_option_string(camera->devices[i], key, value) == 0) { - set = true; - break; + device_t *dev = camera->devices[i]; + if (!dev) { + continue; } + + int ret = device_set_option_string(dev, key, value); + if (ret > 0) { + http_once(stream, http_200, headersp); + fprintf(stream, "%s: The '%s' was set to '%s'.\r\n", dev->name, key, value); + } else if (ret < 0) { + http_once(stream, http_500, headersp); + fprintf(stream, "%s: Cannot set '%s' to '%s'.\r\n", dev->name, key, value); + } + found = true; } - if (set) { - if (!*headers) { - http_200(stream, ""); - *headers = true; - } - fprintf(stream, "The '%s' was set to '%s'.\r\n", key, value); - } else { - if (!*headers) { - http_500(stream, ""); - *headers = true; - } - fprintf(stream, "Cannot set '%s' to '%s'.\r\n", key, value); - } + if (found) + return NULL; + http_once(stream, http_404, headersp); + fprintf(stream, "The '%s' was set not found.\r\n", key); return NULL; } @@ -56,7 +62,9 @@ void camera_http_option(http_worker_t *worker, FILE *stream) { bool headers = false; http_enum_params(worker, stream, camera_http_set_option, &headers); - if (!headers) { + if (headers) { + fprintf(stream, "---\r\n"); + } else { http_404(stream, ""); fprintf(stream, "No options passed.\r\n"); } diff --git a/device/device.c b/device/device.c index 124fed0..3931ca7 100644 --- a/device/device.c +++ b/device/device.c @@ -258,7 +258,7 @@ int device_set_rotation(device_t *dev, bool vflip, bool hflip) int device_set_option_string(device_t *dev, const char *key, const char *value) { if (!dev) { - return -1; + return 0; } return dev->hw->device_set_option(dev, key, value); diff --git a/device/libcamera/device.cc b/device/libcamera/device.cc index 5ebe76e..b4169f1 100644 --- a/device/libcamera/device.cc +++ b/device/libcamera/device.cc @@ -173,9 +173,43 @@ int libcamera_device_set_option(device_t *dev, const char *keyp, const char *val control_value.set(atof(value)); break; - case libcamera::ControlTypeString: case libcamera::ControlTypeRectangle: + static const char *RECTANGLE_PATTERNS[] = { + "(%d,%d)/%ux%u", + "%d,%d,%u,%u", + NULL + }; + + for (int i = 0; RECTANGLE_PATTERNS[i]; i++) { + libcamera::Rectangle rectangle; + + if (4 == sscanf(value, RECTANGLE_PATTERNS[i], + &rectangle.x, &rectangle.y, + &rectangle.width, &rectangle.height)) { + control_value.set(rectangle); + break; + } + } + break; + case libcamera::ControlTypeSize: + static const char *SIZE_PATTERNS[] = { + "%ux%u", + "%u,%u", + NULL + }; + + for (int i = 0; SIZE_PATTERNS[i]; i++) { + libcamera::Size size; + + if (2 == sscanf(value, SIZE_PATTERNS[i], &size.width, &size.height)) { + control_value.set(size); + break; + } + } + break; + + case libcamera::ControlTypeString: break; } @@ -187,9 +221,11 @@ int libcamera_device_set_option(device_t *dev, const char *keyp, const char *val control_key.c_str(), control_id->id(), control_id->type(), control_value.toString().c_str()); dev->libcamera->controls.set(control_id->id(), control_value); - return 0; + return 1; } + return 0; + error: return -1; }