diff --git a/device/libcamera/device.cc b/device/libcamera/device.cc index e2bbc8a..aa57f41 100644 --- a/device/libcamera/device.cc +++ b/device/libcamera/device.cc @@ -38,7 +38,6 @@ void libcamera_device_close(device_t *dev) { if (dev->libcamera) { if (dev->libcamera->camera) { - dev->libcamera->camera->stop(); dev->libcamera->camera->release(); } @@ -47,23 +46,73 @@ void libcamera_device_close(device_t *dev) } } -int libcamera_device_set_decoder_start(device_t *dev, bool do_on) -{ - return -1; -} - -int libcamera_device_video_force_key(device_t *dev) -{ - return -1; -} - int libcamera_device_set_fps(device_t *dev, int desired_fps) { + int64_t frame_time = 1000000 / desired_fps; + dev->libcamera->controls.set(libcamera::controls::FrameDurationLimits, { frame_time, frame_time }); return -1; } -int libcamera_device_set_option(device_t *dev, const char *key, const char *value) +std::string libcamera_device_option_normalize(std::string key) { + key.resize(device_option_normalize_name(key.data(), key.data())); + return key; +} + +int libcamera_device_set_option(device_t *dev, const char *keyp, const char *value) +{ + auto key = libcamera_device_option_normalize(keyp); + + for (auto const &control : dev->libcamera->camera->controls()) { + if (!control.first) + continue; + + auto control_id = control.first; + auto control_key = libcamera_device_option_normalize(control_id->name()); + if (key != control_key) + continue; + + libcamera::ControlValue control_value; + + switch (control_id->type()) { + case libcamera::ControlTypeBool: + control_value.set(atoi(value)); + break; + + case libcamera::ControlTypeByte: + control_value.set(atoi(value)); + break; + + case libcamera::ControlTypeInteger32: + control_value.set(atoi(value)); + break; + + case libcamera::ControlTypeInteger64: + control_value.set(atoi(value)); + break; + + case libcamera::ControlTypeFloat: + control_value.set(atof(value)); + break; + + case libcamera::ControlTypeString: + case libcamera::ControlTypeRectangle: + case libcamera::ControlTypeSize: + break; + } + + if (control_value.isNone()) { + E_LOG_ERROR(dev, "The `%s` type `%d` is not supported.", control_key.c_str(), control_id->type()); + } + + E_LOG_INFO(dev, "Configuring option %s (%08x, type=%d) = %s", + 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; + } + +error: return -1; } #endif // USE_LIBCAMERA diff --git a/device/libcamera/libcamera.cc b/device/libcamera/libcamera.cc index e82cf42..cd24f3c 100644 --- a/device/libcamera/libcamera.cc +++ b/device/libcamera/libcamera.cc @@ -4,8 +4,6 @@ device_hw_t libcamera_device_hw = { .device_open = libcamera_device_open, .device_close = libcamera_device_close, - .device_set_decoder_start = libcamera_device_set_decoder_start, - .device_video_force_key = libcamera_device_video_force_key, .device_set_fps = libcamera_device_set_fps, .device_set_option = libcamera_device_set_option, diff --git a/device/libcamera/libcamera.hh b/device/libcamera/libcamera.hh index 75e3ddf..ca42547 100644 --- a/device/libcamera/libcamera.hh +++ b/device/libcamera/libcamera.hh @@ -12,6 +12,7 @@ extern "C" { #include "device/buffer.h" #include "opts/log.h" #include "opts/fourcc.h" +#include "opts/control.h" }; #ifdef USE_LIBCAMERA @@ -38,6 +39,7 @@ struct pollfd; typedef struct device_libcamera_s { std::shared_ptr camera_manager; std::shared_ptr camera; + libcamera::ControlList controls; } device_libcamera_t; typedef struct buffer_list_libcamera_s { @@ -55,8 +57,6 @@ typedef struct buffer_libcamera_s { int libcamera_device_open(device_t *dev); void libcamera_device_close(device_t *dev); -int libcamera_device_set_decoder_start(device_t *dev, bool do_on); -int libcamera_device_video_force_key(device_t *dev); int libcamera_device_set_fps(device_t *dev, int desired_fps); int libcamera_device_set_option(device_t *dev, const char *key, const char *value); diff --git a/device/v4l2/device_options.c b/device/v4l2/device_options.c index b29b3fd..3481ab7 100644 --- a/device/v4l2/device_options.c +++ b/device/v4l2/device_options.c @@ -1,8 +1,7 @@ #include "v4l2.h" #include "device/device.h" #include "opts/log.h" - -#include +#include "opts/control.h" int v4l2_device_set_option_by_id(device_t *dev, const char *name, uint32_t id, int32_t value) { @@ -21,24 +20,6 @@ error: return -1; } -void v4l2_device_option_normalize_name(char *in) -{ - char *out = in; - - while (*in) { - if (isalnum(*in)) { - *out++ = tolower(*in++); - } else if (isprint(*in)) { - *out++ = '_'; - while (*++in && isprint(*in) && !isalnum(*in)); - } else { - in++; - } - } - - *out++ = 0; -} - static int v4l2_device_set_option_string_fd_iter_id(device_t *dev, int fd, uint32_t *id, char *name, char *value) { struct v4l2_query_ext_ctrl qctrl = { .id = *id }; @@ -50,7 +31,7 @@ static int v4l2_device_set_option_string_fd_iter_id(device_t *dev, int fd, uint3 } *id = qctrl.id; - v4l2_device_option_normalize_name(qctrl.name); + device_option_normalize_name(qctrl.name, qctrl.name); if (strcmp(qctrl.name, name) != 0) return 0; @@ -150,7 +131,7 @@ int v4l2_device_set_option(device_t *dev, const char *key, const char *value) int ret = 0; - v4l2_device_option_normalize_name(keyp); + device_option_normalize_name(keyp, keyp); if (dev->v4l2->subdev_fd >= 0) ret = v4l2_device_set_option_string_fd(dev, dev->v4l2->subdev_fd, keyp, valuep); diff --git a/opts/control.c b/opts/control.c new file mode 100644 index 0000000..6e5a733 --- /dev/null +++ b/opts/control.c @@ -0,0 +1,34 @@ +#include "control.h" + +#include +#include + +int device_option_normalize_name(const char *in, char *outp) +{ + // The output is always shorter, so `outp=in` + // colour_correction_matrix => ColourCorrectionMatrix + // Colour Correction Matrix => ColourCorrectionMatrix + // ColourCorrectionMatrix => ColourCorrectionMatrix + + char *out = outp; + bool upper = true; + + while (*in) { + if (isalnum(*in)) { + if (upper) { + *out++ = toupper(*in++); + upper = false; + } else { + *out++ = *in++; + } + } else if (isprint(*in)) { + upper = true; + while (*++in && isprint(*in) && !isalnum(*in)); + } else { + in++; + } + } + + *out++ = 0; + return out - outp; +} diff --git a/opts/control.h b/opts/control.h new file mode 100644 index 0000000..fd4da10 --- /dev/null +++ b/opts/control.h @@ -0,0 +1 @@ +int device_option_normalize_name(const char *in, char *out);