Skip to content

Commit

Permalink
core: Reduce the camera manager init calls if possible.
Browse files Browse the repository at this point in the history
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 <[email protected]>
  • Loading branch information
naushir committed Oct 25, 2023
1 parent a32dd5a commit 59e3ed1
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 52 deletions.
18 changes: 14 additions & 4 deletions core/libcamera_app.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,8 @@ LibcameraApp::LibcameraApp(std::unique_ptr<Options> opts)
if (!options_)
options_ = std::make_unique<Options>();

options_->SetApp(this);

set_pipeline_configuration(platform);
}

Expand All @@ -151,6 +153,15 @@ LibcameraApp::~LibcameraApp()
CloseCamera();
}

void LibcameraApp::initCameraManager()
{
camera_manager_.reset();
camera_manager_ = std::make_unique<CameraManager>();
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();
Expand All @@ -170,14 +181,13 @@ void LibcameraApp::OpenCamera()

LOG(2, "Opening camera...");

camera_manager_ = std::make_unique<CameraManager>();
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<std::shared_ptr<libcamera::Camera>> 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");

Expand Down
3 changes: 3 additions & 0 deletions core/libcamera_app.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,7 @@ class LibcameraApp

friend class BufferWriteSync;
friend class BufferReadSync;
friend class Options;

protected:
std::unique_ptr<Options> options_;
Expand Down Expand Up @@ -229,6 +230,7 @@ class LibcameraApp
Stream *stream;
};

void initCameraManager();
void setupCapture();
void makeRequests();
void queueRequest(CompletedRequest *completed_request);
Expand All @@ -241,6 +243,7 @@ class LibcameraApp
Mode selectMode(const Mode &mode) const;

std::unique_ptr<CameraManager> camera_manager_;
std::vector<std::shared_ptr<libcamera::Camera>> cameras_;
std::shared_ptr<Camera> camera_;
bool camera_acquired_ = false;
std::unique_ptr<CameraConfiguration> configuration_;
Expand Down
98 changes: 51 additions & 47 deletions core/options.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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++)
Expand All @@ -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[])
Expand Down Expand Up @@ -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<CameraManager> cm = std::make_unique<CameraManager>();
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<std::shared_ptr<libcamera::Camera>> cameras = LibcameraApp::GetCameras(cm.get());
std::vector<std::shared_ptr<libcamera::Camera>> 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<CameraManager> cm = std::make_unique<CameraManager>();
int ret = cm->start();
if (ret)
throw std::runtime_error("camera manager failed to start, code " + std::to_string(-ret));

std::vector<std::shared_ptr<libcamera::Camera>> cameras = LibcameraApp::GetCameras(cm.get());
if (cameras.size() != 0)
{
unsigned int idx = 0;
Expand Down Expand Up @@ -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

Expand Down
6 changes: 5 additions & 1 deletion core/options.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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_;

Expand All @@ -302,4 +305,5 @@ struct Options
std::string timeout_;
std::string shutter_;
std::string flicker_period_;
LibcameraApp *app_;
};

0 comments on commit 59e3ed1

Please sign in to comment.