From 59e3ed1769e33121a88e710faaf60d9433fbb425 Mon Sep 17 00:00:00 2001 From: Naushir Patuck Date: Wed, 25 Oct 2023 13:59:05 +0100 Subject: [PATCH] core: Reduce the camera manager init calls if possible. The camera manager may be initialised multiple times depending on the current and wanted state of the sensor HDR control. Avoid this by having the camera manager accessable from the Options class and only re-initialising it if the state of the sensor HDR control has changed. Do this carefully enough, and there ought to be no change in behaviour perceived by a application or the user. Signed-off-by: Naushir Patuck --- core/libcamera_app.cpp | 18 ++++++-- core/libcamera_app.hpp | 3 ++ core/options.cpp | 98 ++++++++++++++++++++++-------------------- core/options.hpp | 6 ++- 4 files changed, 73 insertions(+), 52 deletions(-) diff --git a/core/libcamera_app.cpp b/core/libcamera_app.cpp index 3d3c181a..86a6d705 100644 --- a/core/libcamera_app.cpp +++ b/core/libcamera_app.cpp @@ -137,6 +137,8 @@ LibcameraApp::LibcameraApp(std::unique_ptr opts) if (!options_) options_ = std::make_unique(); + options_->SetApp(this); + set_pipeline_configuration(platform); } @@ -151,6 +153,15 @@ LibcameraApp::~LibcameraApp() CloseCamera(); } +void LibcameraApp::initCameraManager() +{ + camera_manager_.reset(); + camera_manager_ = std::make_unique(); + int ret = camera_manager_->start(); + if (ret) + throw std::runtime_error("camera manager failed to start, code " + std::to_string(-ret)); +} + std::string const &LibcameraApp::CameraId() const { return camera_->id(); @@ -170,14 +181,13 @@ void LibcameraApp::OpenCamera() LOG(2, "Opening camera..."); - camera_manager_ = std::make_unique(); - int ret = camera_manager_->start(); - if (ret) - throw std::runtime_error("camera manager failed to start, code " + std::to_string(-ret)); + if (!camera_manager_) + initCameraManager(); std::vector> cameras = GetCameras(); if (cameras.size() == 0) throw std::runtime_error("no cameras available"); + if (options_->camera >= cameras.size()) throw std::runtime_error("selected camera is not available"); diff --git a/core/libcamera_app.hpp b/core/libcamera_app.hpp index 1bdd2de1..76e1b1db 100644 --- a/core/libcamera_app.hpp +++ b/core/libcamera_app.hpp @@ -179,6 +179,7 @@ class LibcameraApp friend class BufferWriteSync; friend class BufferReadSync; + friend class Options; protected: std::unique_ptr options_; @@ -229,6 +230,7 @@ class LibcameraApp Stream *stream; }; + void initCameraManager(); void setupCapture(); void makeRequests(); void queueRequest(CompletedRequest *completed_request); @@ -241,6 +243,7 @@ class LibcameraApp Mode selectMode(const Mode &mode) const; std::unique_ptr camera_manager_; + std::vector> cameras_; std::shared_ptr camera_; bool camera_acquired_ = false; std::unique_ptr configuration_; diff --git a/core/options.cpp b/core/options.cpp index 52587a84..73790b5b 100644 --- a/core/options.cpp +++ b/core/options.cpp @@ -104,8 +104,9 @@ static int xioctl(int fd, unsigned long ctl, void *arg) return ret; } -static void set_subdev_hdr_ctrl(int en) +static bool set_subdev_hdr_ctrl(int en) { + bool changed = false; // Currently this does not exist in libcamera, so go directly to V4L2 // XXX it's not obvious which v4l2-subdev to use for which camera! for (int i = 0; i < 8; i++) @@ -117,9 +118,17 @@ static void set_subdev_hdr_ctrl(int en) continue; v4l2_control ctrl { V4L2_CID_WIDE_DYNAMIC_RANGE, en }; - xioctl(fd, VIDIOC_S_CTRL, &ctrl); + xioctl(fd, VIDIOC_G_CTRL, &ctrl); + if (ctrl.value != en) + { + ctrl.value = en; + xioctl(fd, VIDIOC_S_CTRL, &ctrl); + changed = true; + } close(fd); } + + return changed; } bool Options::Parse(int argc, char *argv[]) @@ -164,70 +173,55 @@ bool Options::Parse(int argc, char *argv[]) shutter.set(shutter_); flicker_period.set(flicker_period_); + if (help) + { + std::cout << options_; + return false; + } + + if (version) + { + std::cout << "libcamera-apps build: " << LibcameraAppsVersion() << std::endl; + std::cout << "libcamera build: " << libcamera::CameraManager::version() << std::endl; + return false; + } + if (hdr != "off" && hdr != "single-exp" && hdr != "sensor" && hdr != "auto") throw std::runtime_error("Invalid HDR option provided: " + hdr); - logSetTarget(LoggingTargetNone); + if (!verbose || list_cameras) + libcamera::logSetTarget(libcamera::LoggingTargetNone); // HDR control. Set the sensor control before opening or listing any cameras. - // Start by disabling HDR unconditionally. + // Start by disabling HDR unconditionally. Reset the camera manager if we have + // actually switched the value of the control. set_subdev_hdr_ctrl(0); + app_->initCameraManager(); - std::unique_ptr cm = std::make_unique(); - int ret = cm->start(); - if (ret) - throw std::runtime_error("camera manager failed to start, code " + std::to_string(-ret)); + // Unconditionally disable libcamera logging for a bit. + libcamera::logSetTarget(libcamera::LoggingTargetNone); - std::vector> cameras = LibcameraApp::GetCameras(cm.get()); + std::vector> cameras = app_->GetCameras(); std::string const &cam_id = *cameras[camera]->properties().get(libcamera::properties::Model); - cameras.clear(); - cm->stop(); - cm.reset(); if ((hdr == "sensor" || hdr == "auto") && cam_id == "imx708") { - set_subdev_hdr_ctrl(1); + // Turn on sensor HDR. Reset the camera manager if we have switched the value of the control. + if (set_subdev_hdr_ctrl(1)) + { + cameras.clear(); + app_->initCameraManager(); + cameras = app_->GetCameras(); + } hdr = "sensor"; } - logSetTarget(LoggingTargetStream); - - // We have to pass the tuning file name through an environment variable. - // Note that we only overwrite the variable if the option was given. - if (tuning_file != "-") - setenv("LIBCAMERA_RPI_TUNING_FILE", tuning_file.c_str(), 1); - - // Set the verbosity - LibcameraApp::verbosity = verbose; - - if (verbose == 0) - libcamera::logSetTarget(libcamera::LoggingTargetNone); - - if (help) - { - std::cout << options_; - return false; - } - - if (version) - { - std::cout << "libcamera-apps build: " << LibcameraAppsVersion() << std::endl; - std::cout << "libcamera build: " << libcamera::CameraManager::version() << std::endl; - return false; - } - if (list_cameras) { // Disable any libcamera logging for this bit. logSetTarget(LoggingTargetNone); LibcameraApp::verbosity = 1; - std::unique_ptr cm = std::make_unique(); - int ret = cm->start(); - if (ret) - throw std::runtime_error("camera manager failed to start, code " + std::to_string(-ret)); - - std::vector> cameras = LibcameraApp::GetCameras(cm.get()); if (cameras.size() != 0) { unsigned int idx = 0; @@ -341,11 +335,21 @@ bool Options::Parse(int argc, char *argv[]) std::cout << "No cameras available!" << std::endl; verbose = 1; - cameras.clear(); - cm->stop(); return false; } + // Reset verbosity to the user request. + if (verbose) + libcamera::logSetTarget(libcamera::LoggingTargetStream); + + // Set the verbosity + LibcameraApp::verbosity = verbose; + + // We have to pass the tuning file name through an environment variable. + // Note that we only overwrite the variable if the option was given. + if (tuning_file != "-") + setenv("LIBCAMERA_RPI_TUNING_FILE", tuning_file.c_str(), 1); + if (sscanf(preview.c_str(), "%u,%u,%u,%u", &preview_x, &preview_y, &preview_width, &preview_height) != 4) preview_x = preview_y = preview_width = preview_height = 0; // use default window diff --git a/core/options.hpp b/core/options.hpp index b0daff39..4869055a 100644 --- a/core/options.hpp +++ b/core/options.hpp @@ -94,7 +94,8 @@ struct TimeVal struct Options { - Options() : set_default_lens_position(false), af_on_capture(false), options_("Valid options are", 120, 80) + Options() + : set_default_lens_position(false), af_on_capture(false), options_("Valid options are", 120, 80), app_(nullptr) { using namespace boost::program_options; // clang-format off @@ -290,6 +291,8 @@ struct Options virtual bool Parse(int argc, char *argv[]); virtual void Print() const; + void SetApp(LibcameraApp *app) { app_ = app; } + protected: boost::program_options::options_description options_; @@ -302,4 +305,5 @@ struct Options std::string timeout_; std::string shutter_; std::string flicker_period_; + LibcameraApp *app_; };