status: extend to provide all camera options and properties in JSON payload
- control: add `device_option_is_equal` - libcamera: provide human readable configurable options - v4l2: include camera control values - libcamera: store all applied controls - libcamera: use `device_option_is_equal`
This commit is contained in:
@ -85,7 +85,7 @@ int libcamera_buffer_enqueue(buffer_t *buf, const char *who)
|
||||
if (camera->queueRequest(buf->libcamera->request.get()) < 0) {
|
||||
LOG_ERROR(buf, "Can't queue buffer.");
|
||||
}
|
||||
buf->buf_list->dev->libcamera->controls.clear();
|
||||
libcamera_device_apply_controls(buf->buf_list->dev);
|
||||
return 0;
|
||||
|
||||
error:
|
||||
|
@ -170,7 +170,7 @@ int libcamera_buffer_list_set_stream(buffer_list_t *buf_list, bool do_on)
|
||||
LOG_ERROR(buf_list, "Failed to start camera.");
|
||||
}
|
||||
|
||||
buf_list->dev->libcamera->controls.clear();
|
||||
libcamera_device_apply_controls(buf_list->dev);
|
||||
} else {
|
||||
buf_list->dev->libcamera->camera->requestCompleted.disconnect(
|
||||
buf_list->libcamera, &buffer_list_libcamera_t::libcamera_buffer_list_dequeued);
|
||||
|
@ -1,63 +1,6 @@
|
||||
#ifdef USE_LIBCAMERA
|
||||
#include "libcamera.hh"
|
||||
|
||||
std::string libcamera_device_option_normalize(std::string key)
|
||||
{
|
||||
key.resize(device_option_normalize_name(key.data(), key.data()));
|
||||
return key;
|
||||
}
|
||||
|
||||
libcamera::ControlInfoMap::Map libcamera_control_list(device_t *dev)
|
||||
{
|
||||
libcamera::ControlInfoMap::Map controls_map;
|
||||
for (auto const &control : dev->libcamera->camera->controls()) {
|
||||
controls_map[control.first] = control.second;
|
||||
}
|
||||
return controls_map;
|
||||
}
|
||||
|
||||
void libcamera_device_dump_options(device_t *dev, FILE *stream)
|
||||
{
|
||||
auto &properties = dev->libcamera->camera->properties();
|
||||
auto idMap = properties.idMap();
|
||||
|
||||
fprintf(stream, "%s Properties:\n", dev->name);
|
||||
|
||||
for (auto const &control : properties) {
|
||||
if (!control.first)
|
||||
continue;
|
||||
|
||||
auto control_id = control.first;
|
||||
auto control_value = control.second;
|
||||
std::string control_id_name = "";
|
||||
|
||||
if (auto control_id_info = idMap ? idMap->at(control_id) : NULL) {
|
||||
control_id_name = control_id_info->name();
|
||||
}
|
||||
|
||||
fprintf(stream, "- property: %s (%08x, type=%d): %s\n",
|
||||
control_id_name.c_str(), control_id, control_value.type(),
|
||||
control_value.toString().c_str());
|
||||
}
|
||||
|
||||
fprintf(stream, "\n");
|
||||
fprintf(stream, "%s Options:\n", dev->name);
|
||||
|
||||
for (auto const &control : libcamera_control_list(dev)) {
|
||||
if (!control.first)
|
||||
continue;
|
||||
|
||||
auto control_id = control.first;
|
||||
auto control_key = libcamera_device_option_normalize(control_id->name());
|
||||
auto control_info = control.second;
|
||||
|
||||
fprintf(stream, "- available option: %s (%08x, type=%d): %s\n",
|
||||
control_id->name().c_str(), control_id->id(), control_id->type(),
|
||||
control_info.toString().c_str());
|
||||
}
|
||||
fprintf(stream, "\n");
|
||||
}
|
||||
|
||||
void libcamera_print_cameras(device_t *dev)
|
||||
{
|
||||
if (dev->libcamera->camera_manager->cameras().size()) {
|
||||
@ -153,99 +96,15 @@ int libcamera_device_set_rotation(device_t *dev, bool vflip, bool hflip)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int libcamera_device_set_option(device_t *dev, const char *keyp, const char *value)
|
||||
void libcamera_device_apply_controls(device_t *dev)
|
||||
{
|
||||
auto key = libcamera_device_option_normalize(keyp);
|
||||
auto &controls = dev->libcamera->controls;
|
||||
auto &applied_controls = dev->libcamera->applied_controls;
|
||||
|
||||
for (auto const &control : libcamera_control_list(dev)) {
|
||||
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::ControlTypeNone:
|
||||
break;
|
||||
|
||||
case libcamera::ControlTypeBool:
|
||||
control_value.set<bool>(atoi(value));
|
||||
break;
|
||||
|
||||
case libcamera::ControlTypeByte:
|
||||
control_value.set<unsigned char>(atoi(value));
|
||||
break;
|
||||
|
||||
case libcamera::ControlTypeInteger32:
|
||||
control_value.set<int32_t>(atoi(value));
|
||||
break;
|
||||
|
||||
case libcamera::ControlTypeInteger64:
|
||||
control_value.set<int64_t>(atoi(value));
|
||||
break;
|
||||
|
||||
case libcamera::ControlTypeFloat:
|
||||
control_value.set<float>(atof(value));
|
||||
break;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
if (control_value.isNone()) {
|
||||
LOG_ERROR(dev, "The `%s` type `%d` is not supported.", control_key.c_str(), control_id->type());
|
||||
}
|
||||
|
||||
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 1;
|
||||
for (auto &control : controls) {
|
||||
applied_controls.set(control.first, control.second);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
return -1;
|
||||
controls.clear();
|
||||
}
|
||||
#endif // USE_LIBCAMERA
|
||||
|
@ -5,6 +5,7 @@ device_hw_t libcamera_device_hw = {
|
||||
.device_open = libcamera_device_open,
|
||||
.device_close = libcamera_device_close,
|
||||
.device_dump_options = libcamera_device_dump_options,
|
||||
.device_dump_options2 = libcamera_device_dump_options2,
|
||||
.device_set_fps = libcamera_device_set_fps,
|
||||
.device_set_rotation = libcamera_device_set_rotation,
|
||||
.device_set_option = libcamera_device_set_option,
|
||||
|
@ -42,6 +42,7 @@ typedef struct device_libcamera_s {
|
||||
std::shared_ptr<libcamera::CameraConfiguration> configuration;
|
||||
std::shared_ptr<libcamera::FrameBufferAllocator> allocator;
|
||||
libcamera::ControlList controls;
|
||||
libcamera::ControlList applied_controls;
|
||||
bool vflip, hflip;
|
||||
} device_libcamera_t;
|
||||
|
||||
@ -59,9 +60,11 @@ typedef struct buffer_libcamera_s {
|
||||
int libcamera_device_open(device_t *dev);
|
||||
void libcamera_device_close(device_t *dev);
|
||||
void libcamera_device_dump_options(device_t *dev, FILE *stream);
|
||||
int libcamera_device_dump_options2(device_t *dev, device_option_fn fn, void *opaque);
|
||||
int libcamera_device_set_fps(device_t *dev, int desired_fps);
|
||||
int libcamera_device_set_rotation(device_t *dev, bool vflip, bool hflip);
|
||||
int libcamera_device_set_option(device_t *dev, const char *key, const char *value);
|
||||
void libcamera_device_apply_controls(device_t *dev);
|
||||
|
||||
int libcamera_buffer_open(buffer_t *buf);
|
||||
void libcamera_buffer_close(buffer_t *buf);
|
||||
|
446
device/libcamera/options.cc
Normal file
446
device/libcamera/options.cc
Normal file
@ -0,0 +1,446 @@
|
||||
#ifdef USE_LIBCAMERA
|
||||
#include "libcamera.hh"
|
||||
#include "third_party/magic_enum/include/magic_enum.hpp"
|
||||
|
||||
static std::string libcamera_device_option_normalize(std::string key)
|
||||
{
|
||||
key.resize(device_option_normalize_name(key.data(), key.data()));
|
||||
return key;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static std::map<unsigned, std::string> control_enum_values(const char *prefix)
|
||||
{
|
||||
std::map<unsigned, std::string> ret;
|
||||
|
||||
for (auto e : magic_enum::enum_entries<T>()) {
|
||||
auto value = std::string(e.second);
|
||||
if (prefix && value.find(prefix) == 0) {
|
||||
value = value.substr(strlen(prefix));
|
||||
}
|
||||
ret[e.first] = value;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct libcamera_control_id_t
|
||||
{
|
||||
const libcamera::ControlId *control_id;
|
||||
std::map<unsigned, std::string> enum_values;
|
||||
};
|
||||
|
||||
#define LIBCAMERA_CONTROL_RAW(Name, Strip) \
|
||||
{ Name.id(), { .control_id = &Name, .enum_values = control_enum_values<Name##Enum>(Strip), } }
|
||||
|
||||
#define LIBCAMERA_CONTROL(Name, Strip) \
|
||||
LIBCAMERA_CONTROL_RAW(libcamera::controls::Name, Strip ? Strip : #Name)
|
||||
|
||||
#define LIBCAMERA_DRAFT_CONTROL(Name) \
|
||||
LIBCAMERA_CONTROL_RAW(libcamera::controls::draft::Name, #Name)
|
||||
|
||||
static std::map<unsigned, libcamera_control_id_t> libcamera_control_ids =
|
||||
{
|
||||
LIBCAMERA_CONTROL(AeMeteringMode, "Metering"),
|
||||
LIBCAMERA_CONTROL(AeConstraintMode, "Constraint"),
|
||||
LIBCAMERA_CONTROL(AeExposureMode, "Exposure"),
|
||||
LIBCAMERA_CONTROL(AwbMode, "Awb"),
|
||||
LIBCAMERA_CONTROL(AfMode, "AfMode"),
|
||||
LIBCAMERA_CONTROL(AfRange, "AfRange"),
|
||||
LIBCAMERA_CONTROL(AfSpeed, "AfSpeed"),
|
||||
LIBCAMERA_CONTROL(AfTrigger, "AfTrigger"),
|
||||
LIBCAMERA_CONTROL(AfState, "AfState"),
|
||||
LIBCAMERA_DRAFT_CONTROL(AePrecaptureTrigger),
|
||||
LIBCAMERA_DRAFT_CONTROL(NoiseReductionMode),
|
||||
LIBCAMERA_DRAFT_CONTROL(ColorCorrectionAberrationMode),
|
||||
LIBCAMERA_DRAFT_CONTROL(AeState),
|
||||
LIBCAMERA_DRAFT_CONTROL(AwbState),
|
||||
LIBCAMERA_DRAFT_CONTROL(LensShadingMapMode),
|
||||
LIBCAMERA_DRAFT_CONTROL(SceneFlicker),
|
||||
LIBCAMERA_DRAFT_CONTROL(TestPatternMode)
|
||||
};
|
||||
|
||||
static auto control_type_values = control_enum_values<libcamera::ControlType>("ControlType");
|
||||
|
||||
static const std::map<unsigned, std::string> *libcamera_find_control_ids(unsigned control_id)
|
||||
{
|
||||
auto iter = libcamera_control_ids.find(control_id);
|
||||
if (iter == libcamera_control_ids.end())
|
||||
return NULL;
|
||||
|
||||
return &iter->second.enum_values;
|
||||
}
|
||||
|
||||
static long long libcamera_find_control_id_named_value(unsigned control_id, const char *name)
|
||||
{
|
||||
auto named_values = libcamera_find_control_ids(control_id);
|
||||
if (named_values) {
|
||||
for (const auto & named_value : *named_values) {
|
||||
if (device_option_is_equal(named_value.second.c_str(), name))
|
||||
return named_value.first;
|
||||
}
|
||||
}
|
||||
|
||||
return strtoll(name, NULL, 10);
|
||||
}
|
||||
|
||||
static libcamera::ControlInfoMap::Map libcamera_control_list(device_t *dev)
|
||||
{
|
||||
libcamera::ControlInfoMap::Map controls_map;
|
||||
for (auto const &control : dev->libcamera->camera->controls()) {
|
||||
controls_map[control.first] = control.second;
|
||||
}
|
||||
return controls_map;
|
||||
}
|
||||
|
||||
void libcamera_device_dump_options(device_t *dev, FILE *stream)
|
||||
{
|
||||
auto &properties = dev->libcamera->camera->properties();
|
||||
auto idMap = properties.idMap();
|
||||
|
||||
fprintf(stream, "%s Properties:\n", dev->name);
|
||||
|
||||
for (auto const &control : properties) {
|
||||
if (!control.first)
|
||||
continue;
|
||||
|
||||
auto control_id = control.first;
|
||||
auto control_value = control.second;
|
||||
std::string control_id_name = "";
|
||||
|
||||
if (auto control_id_info = idMap ? idMap->at(control_id) : NULL) {
|
||||
control_id_name = control_id_info->name();
|
||||
}
|
||||
|
||||
fprintf(stream, "- property: %s (%08x, type=%s) = %s\n",
|
||||
control_id_name.c_str(), control_id,
|
||||
control_type_values[control_value.type()].c_str(),
|
||||
control_value.toString().c_str());
|
||||
}
|
||||
|
||||
fprintf(stream, "\n");
|
||||
fprintf(stream, "%s Options:\n", dev->name);
|
||||
|
||||
for (auto const &control : libcamera_control_list(dev)) {
|
||||
if (!control.first)
|
||||
continue;
|
||||
|
||||
auto control_id = control.first;
|
||||
auto control_key = libcamera_device_option_normalize(control_id->name());
|
||||
auto control_info = control.second;
|
||||
|
||||
fprintf(stream, "- available option: %s (%08x, type=%s): %s\n",
|
||||
control_id->name().c_str(), control_id->id(),
|
||||
control_type_values[control_id->type()].c_str(),
|
||||
control_info.toString().c_str());
|
||||
|
||||
auto named_values = libcamera_find_control_ids(control_id->id());
|
||||
|
||||
if (named_values != NULL) {
|
||||
for (const auto & named_value : *named_values) {
|
||||
fprintf(stream, "\t\t%d: %s\n", named_value.first, named_value.second.c_str());
|
||||
}
|
||||
} else {
|
||||
for (size_t i = 0; i < control_info.values().size(); i++) {
|
||||
fprintf(stream, "\t\t%s\n", control_info.values()[i].toString().c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
fprintf(stream, "\n");
|
||||
}
|
||||
|
||||
static int libcamera_device_dump_control_option(device_option_fn fn, void *opaque, const libcamera::ControlId &control_id, const libcamera::ControlInfo *control_info, const libcamera::ControlValue *control_value, bool read_only)
|
||||
{
|
||||
device_option_t opt = {
|
||||
.control_id = control_id.id()
|
||||
};
|
||||
opt.flags.read_only = read_only;
|
||||
strcpy(opt.name, control_id.name().c_str());
|
||||
|
||||
if (control_info) {
|
||||
strcpy(opt.description, control_info->toString().c_str());
|
||||
}
|
||||
|
||||
if (control_value) {
|
||||
if (!control_value->isNone()) {
|
||||
strcpy(opt.value, control_value->toString().c_str());
|
||||
} else {
|
||||
control_value = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
switch (control_id.type()) {
|
||||
case libcamera::ControlTypeNone:
|
||||
break;
|
||||
|
||||
case libcamera::ControlTypeBool:
|
||||
opt.type = device_option_type_bool;
|
||||
break;
|
||||
|
||||
case libcamera::ControlTypeByte:
|
||||
opt.type = device_option_type_u8;
|
||||
break;
|
||||
|
||||
case libcamera::ControlTypeInteger32:
|
||||
opt.type = device_option_type_integer;
|
||||
break;
|
||||
|
||||
case libcamera::ControlTypeInteger64:
|
||||
opt.type = device_option_type_integer64;
|
||||
break;
|
||||
|
||||
case libcamera::ControlTypeFloat:
|
||||
opt.type = device_option_type_float;
|
||||
break;
|
||||
|
||||
case libcamera::ControlTypeRectangle:
|
||||
opt.type = device_option_type_float;
|
||||
opt.elems = 4;
|
||||
break;
|
||||
|
||||
case libcamera::ControlTypeSize:
|
||||
opt.type = device_option_type_float;
|
||||
opt.elems = 2;
|
||||
break;
|
||||
|
||||
case libcamera::ControlTypeString:
|
||||
opt.type = device_option_type_string;
|
||||
break;
|
||||
}
|
||||
|
||||
auto named_values = libcamera_find_control_ids(control_id.id());
|
||||
|
||||
if (named_values != NULL) {
|
||||
for (const auto & named_value : *named_values) {
|
||||
if (opt.menu_items >= MAX_DEVICE_OPTION_MENU) {
|
||||
opt.flags.invalid = true;
|
||||
break;
|
||||
}
|
||||
|
||||
device_option_menu_t *opt_menu = &opt.menu[opt.menu_items++];
|
||||
opt_menu->id = named_value.first;
|
||||
strcpy(opt_menu->name, named_value.second.c_str());
|
||||
if (control_value && atoi(control_value->toString().c_str()) == opt_menu->id) {
|
||||
strcpy(opt.value, opt_menu->name);
|
||||
}
|
||||
}
|
||||
} else if (control_info) {
|
||||
for (size_t i = 0; i < control_info->values().size(); i++) {
|
||||
if (opt.menu_items >= MAX_DEVICE_OPTION_MENU) {
|
||||
opt.flags.invalid = true;
|
||||
break;
|
||||
}
|
||||
|
||||
device_option_menu_t *opt_menu = &opt.menu[opt.menu_items++];
|
||||
opt_menu->id = atoi(control_info->values()[i].toString().c_str());
|
||||
strcpy(opt_menu->name, control_info->values()[i].toString().c_str());
|
||||
if (control_value && atoi(control_value->toString().c_str()) == opt_menu->id) {
|
||||
strcpy(opt.value, opt_menu->name);
|
||||
}
|
||||
}
|
||||
} else if (control_value && control_value->numElements() > 0) {
|
||||
opt.elems = control_value->numElements();
|
||||
}
|
||||
|
||||
if (opt.type) {
|
||||
int ret = fn(&opt, opaque);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int libcamera_device_dump_options2(device_t *dev, device_option_fn fn, void *opaque)
|
||||
{
|
||||
auto &properties = dev->libcamera->camera->properties();
|
||||
auto idMap = properties.idMap();
|
||||
|
||||
int n = 0;
|
||||
|
||||
for (auto const &control : properties) {
|
||||
if (!control.first)
|
||||
continue;
|
||||
|
||||
auto control_id = control.first;
|
||||
auto control_value = control.second;
|
||||
std::string control_id_name = "";
|
||||
|
||||
if (auto control_id_info = idMap ? idMap->at(control_id) : NULL) {
|
||||
int ret = libcamera_device_dump_control_option(fn, opaque, *control_id_info, NULL, &control_value, true);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
n++;
|
||||
}
|
||||
}
|
||||
|
||||
for (auto const &control : libcamera_control_list(dev)) {
|
||||
if (!control.first)
|
||||
continue;
|
||||
|
||||
auto control_id = control.first;
|
||||
auto control_info = control.second;
|
||||
|
||||
auto control_value = dev->libcamera->applied_controls.contains(control_id->id())
|
||||
? &dev->libcamera->applied_controls.get(control_id->id())
|
||||
: nullptr;
|
||||
|
||||
int ret = libcamera_device_dump_control_option(fn, opaque,
|
||||
*control_id, &control_info, control_value, false);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
n++;
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
static libcamera::Rectangle libcamera_parse_rectangle(const char *value)
|
||||
{
|
||||
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)) {
|
||||
return rectangle;
|
||||
}
|
||||
}
|
||||
|
||||
return libcamera::Rectangle();
|
||||
}
|
||||
|
||||
static libcamera::Size libcamera_parse_size(const char *value)
|
||||
{
|
||||
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)) {
|
||||
return size;
|
||||
}
|
||||
}
|
||||
|
||||
return libcamera::Size();
|
||||
}
|
||||
|
||||
template<typename T, typename F>
|
||||
static bool libcamera_parse_control_value(libcamera::ControlValue &control_value, const char *value, const F &fn)
|
||||
{
|
||||
std::vector<T> parsed;
|
||||
|
||||
while (value && *value) {
|
||||
std::string current_value;
|
||||
|
||||
if (const char *next = strchr(value, ',')) {
|
||||
current_value.assign(value, next);
|
||||
value = &next[1];
|
||||
} else {
|
||||
current_value.assign(value);
|
||||
value = NULL;
|
||||
}
|
||||
|
||||
if (current_value.empty())
|
||||
continue;
|
||||
|
||||
parsed.push_back(fn(current_value.c_str()));
|
||||
}
|
||||
|
||||
if (parsed.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (parsed.size() > 1) {
|
||||
control_value.set<libcamera::Span<T> >(parsed);
|
||||
} else {
|
||||
control_value.set<T>(parsed[0]);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int libcamera_device_set_option(device_t *dev, const char *keyp, const char *value)
|
||||
{
|
||||
for (auto const &control : libcamera_control_list(dev)) {
|
||||
if (!control.first)
|
||||
continue;
|
||||
|
||||
auto control_id = control.first;
|
||||
auto control_key = control_id->name();
|
||||
if (!device_option_is_equal(keyp, control_key.c_str()))
|
||||
continue;
|
||||
|
||||
libcamera::ControlValue control_value;
|
||||
|
||||
switch (control_id->type()) {
|
||||
case libcamera::ControlTypeNone:
|
||||
break;
|
||||
|
||||
case libcamera::ControlTypeBool:
|
||||
control_value.set<bool>(atoi(value));
|
||||
break;
|
||||
|
||||
case libcamera::ControlTypeByte:
|
||||
libcamera_parse_control_value<unsigned char>(control_value, value,
|
||||
[control_id](const char *value) { return libcamera_find_control_id_named_value(control_id->id(), value); });
|
||||
break;
|
||||
|
||||
case libcamera::ControlTypeInteger32:
|
||||
libcamera_parse_control_value<int32_t>(control_value, value,
|
||||
[control_id](const char *value) { return libcamera_find_control_id_named_value(control_id->id(), value); });
|
||||
break;
|
||||
|
||||
case libcamera::ControlTypeInteger64:
|
||||
libcamera_parse_control_value<int64_t>(control_value, value,
|
||||
[control_id](const char *value) { return libcamera_find_control_id_named_value(control_id->id(), value); });
|
||||
break;
|
||||
|
||||
case libcamera::ControlTypeFloat:
|
||||
libcamera_parse_control_value<float>(control_value, value, atof);
|
||||
break;
|
||||
|
||||
case libcamera::ControlTypeRectangle:
|
||||
libcamera_parse_control_value<libcamera::Rectangle>(
|
||||
control_value, value, libcamera_parse_rectangle);
|
||||
break;
|
||||
|
||||
case libcamera::ControlTypeSize:
|
||||
libcamera_parse_control_value<libcamera::Size>(
|
||||
control_value, value, libcamera_parse_size);
|
||||
break;
|
||||
|
||||
case libcamera::ControlTypeString:
|
||||
break;
|
||||
}
|
||||
|
||||
if (control_value.isNone()) {
|
||||
LOG_ERROR(dev, "The `%s` type `%d` is not supported.", control_key.c_str(), control_id->type());
|
||||
}
|
||||
|
||||
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 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
return -1;
|
||||
}
|
||||
#endif // USE_LIBCAMERA
|
Reference in New Issue
Block a user