Message ID | 20201116164918.2055-3-david.plowman@raspberrypi.com |
---|---|
State | Accepted |
Headers | show |
Series |
|
Related | show |
Hi David, On Mon, 16 Nov 2020 at 16:49, David Plowman <david.plowman@raspberrypi.com> wrote: > On the libcamera/VC4 platform the AGC Prepare/Process methods, and any > changes to the AGC settings, run synchronously - so a number of > mutexes and copies are unnecessary and can be removed. > > Signed-off-by: David Plowman <david.plowman@raspberrypi.com> > --- > src/ipa/raspberrypi/controller/rpi/agc.cpp | 99 ++++++++-------------- > src/ipa/raspberrypi/controller/rpi/agc.hpp | 5 +- > 2 files changed, 37 insertions(+), 67 deletions(-) > > diff --git a/src/ipa/raspberrypi/controller/rpi/agc.cpp > b/src/ipa/raspberrypi/controller/rpi/agc.cpp > index 8079345b..c4379b99 100644 > --- a/src/ipa/raspberrypi/controller/rpi/agc.cpp > +++ b/src/ipa/raspberrypi/controller/rpi/agc.cpp > @@ -160,7 +160,6 @@ Agc::Agc(Controller *controller) > status_.total_exposure_value = 0.0; > status_.target_exposure_value = 0.0; > status_.locked = false; > - output_status_ = status_; > } > > char const *Agc::Name() const > @@ -185,43 +184,36 @@ void Agc::Read(boost::property_tree::ptree const > ¶ms) > > void Agc::SetEv(double ev) > { > - std::unique_lock<std::mutex> lock(settings_mutex_); > ev_ = ev; > } > > void Agc::SetFlickerPeriod(double flicker_period) > { > - std::unique_lock<std::mutex> lock(settings_mutex_); > flicker_period_ = flicker_period; > } > > void Agc::SetFixedShutter(double fixed_shutter) > { > - std::unique_lock<std::mutex> lock(settings_mutex_); > fixed_shutter_ = fixed_shutter; > } > > void Agc::SetFixedAnalogueGain(double fixed_analogue_gain) > { > - std::unique_lock<std::mutex> lock(settings_mutex_); > fixed_analogue_gain_ = fixed_analogue_gain; > } > > void Agc::SetMeteringMode(std::string const &metering_mode_name) > { > - std::unique_lock<std::mutex> lock(settings_mutex_); > metering_mode_name_ = metering_mode_name; > } > > void Agc::SetExposureMode(std::string const &exposure_mode_name) > { > - std::unique_lock<std::mutex> lock(settings_mutex_); > exposure_mode_name_ = exposure_mode_name; > } > > void Agc::SetConstraintMode(std::string const &constraint_mode_name) > { > - std::unique_lock<std::mutex> lock(settings_mutex_); > constraint_mode_name_ = constraint_mode_name; > } > > @@ -240,14 +232,9 @@ void Agc::SwitchMode([[maybe_unused]] CameraMode > const &camera_mode, > > void Agc::Prepare(Metadata *image_metadata) > { > - AgcStatus status; > - { > - std::unique_lock<std::mutex> lock(output_mutex_); > - status = output_status_; > - } > int lock_count = lock_count_; > lock_count_ = 0; > - status.digital_gain = 1.0; > + status_.digital_gain = 1.0; > if (status_.total_exposure_value) { > // Process has run, so we have meaningful values. > DeviceStatus device_status; > @@ -255,48 +242,46 @@ void Agc::Prepare(Metadata *image_metadata) > double actual_exposure = > device_status.shutter_speed * > > device_status.analogue_gain; > if (actual_exposure) { > - status.digital_gain = > + status_.digital_gain = > status_.total_exposure_value / > actual_exposure; > LOG(RPiAgc, Debug) << "Want total exposure > " << status_.total_exposure_value; > // Never ask for a gain < 1.0, and also > impose > // some upper limit. Make it customisable? > - status.digital_gain = std::max( > + status_.digital_gain = std::max( > 1.0, > - std::min(status.digital_gain, > 4.0)); > + std::min(status_.digital_gain, > 4.0)); > LOG(RPiAgc, Debug) << "Actual exposure " > << actual_exposure; > - LOG(RPiAgc, Debug) << "Use digital_gain " > << status.digital_gain; > - LOG(RPiAgc, Debug) << "Effective exposure > " << actual_exposure * status.digital_gain; > + LOG(RPiAgc, Debug) << "Use digital_gain " > << status_.digital_gain; > + LOG(RPiAgc, Debug) << "Effective exposure > " << actual_exposure * status_.digital_gain; > // Decide whether AEC/AGC has converged. > // Insist AGC is steady for MAX_LOCK_COUNT > // frames before we say we are "locked". > // (The hard-coded constants may need to > // become customisable.) > - if (status.target_exposure_value) { > + if (status_.target_exposure_value) { > #define MAX_LOCK_COUNT 3 > - double err = 0.10 * > status.target_exposure_value + 200; > + double err = 0.10 * > status_.target_exposure_value + 200; > if (actual_exposure < > - status.target_exposure_value + > err > - && actual_exposure > > - status.target_exposure_value - > err) > + > status_.target_exposure_value + err && > + actual_exposure > > + > status_.target_exposure_value - err) > lock_count_ = > > std::min(lock_count + 1, > - > MAX_LOCK_COUNT); > + > MAX_LOCK_COUNT); > else if (actual_exposure < > - > status.target_exposure_value > - + 1.5 * err && > + > status_.target_exposure_value + 1.5 * err && > actual_exposure > > - > status.target_exposure_value > - - 1.5 * err) > + > status_.target_exposure_value - 1.5 * err) > lock_count_ = lock_count; > LOG(RPiAgc, Debug) << "Lock count: > " << lock_count_; > } > } > } else > LOG(RPiAgc, Debug) << Name() << ": no device > metadata"; > - status.locked = lock_count_ >= MAX_LOCK_COUNT; > - //printf("%s\n", status.locked ? "+++++++++" : "-"); > - image_metadata->Set("agc.status", status); > + status_.locked = lock_count_ >= MAX_LOCK_COUNT; > + //printf("%s\n", status_.locked ? "+++++++++" : "-"); > Is it worth getting rid of this commented out printf, or perhaps changing to a trace log point? > + image_metadata->Set("agc.status", status_); > } > } > > @@ -335,55 +320,47 @@ static void copy_string(std::string const &s, char > *d, size_t size) > void Agc::housekeepConfig() > { > // First fetch all the up-to-date settings, so no one else has to > do it. > - std::string new_exposure_mode_name, new_constraint_mode_name, > - new_metering_mode_name; > - { > - std::unique_lock<std::mutex> lock(settings_mutex_); > - new_metering_mode_name = metering_mode_name_; > - new_exposure_mode_name = exposure_mode_name_; > - new_constraint_mode_name = constraint_mode_name_; > - status_.ev = ev_; > - status_.fixed_shutter = fixed_shutter_; > - status_.fixed_analogue_gain = fixed_analogue_gain_; > - status_.flicker_period = flicker_period_; > - } > + status_.ev = ev_; > + status_.fixed_shutter = fixed_shutter_; > + status_.fixed_analogue_gain = fixed_analogue_gain_; > + status_.flicker_period = flicker_period_; > LOG(RPiAgc, Debug) << "ev " << status_.ev << " fixed_shutter " > << status_.fixed_shutter << " > fixed_analogue_gain " > << status_.fixed_analogue_gain; > // Make sure the "mode" pointers point to the up-to-date things, if > // they've changed. > - if (strcmp(new_metering_mode_name.c_str(), status_.metering_mode)) > { > - auto it = > config_.metering_modes.find(new_metering_mode_name); > + if (strcmp(metering_mode_name_.c_str(), status_.metering_mode)) { > + auto it = config_.metering_modes.find(metering_mode_name_); > if (it == config_.metering_modes.end()) > throw std::runtime_error("Agc: no metering mode " + > - new_metering_mode_name); > + metering_mode_name_); > metering_mode_ = &it->second; > - copy_string(new_metering_mode_name, status_.metering_mode, > + copy_string(metering_mode_name_, status_.metering_mode, > sizeof(status_.metering_mode)); > } > - if (strcmp(new_exposure_mode_name.c_str(), status_.exposure_mode)) > { > - auto it = > config_.exposure_modes.find(new_exposure_mode_name); > + if (strcmp(exposure_mode_name_.c_str(), status_.exposure_mode)) { > + auto it = config_.exposure_modes.find(exposure_mode_name_); > if (it == config_.exposure_modes.end()) > throw std::runtime_error("Agc: no exposure profile > " + > - new_exposure_mode_name); > + exposure_mode_name_); > exposure_mode_ = &it->second; > - copy_string(new_exposure_mode_name, status_.exposure_mode, > + copy_string(exposure_mode_name_, status_.exposure_mode, > sizeof(status_.exposure_mode)); > } > - if (strcmp(new_constraint_mode_name.c_str(), > status_.constraint_mode)) { > + if (strcmp(constraint_mode_name_.c_str(), > status_.constraint_mode)) { > auto it = > - > config_.constraint_modes.find(new_constraint_mode_name); > + > config_.constraint_modes.find(constraint_mode_name_); > if (it == config_.constraint_modes.end()) > throw std::runtime_error("Agc: no constraint list > " + > - new_constraint_mode_name); > + constraint_mode_name_); > constraint_mode_ = &it->second; > - copy_string(new_constraint_mode_name, > status_.constraint_mode, > + copy_string(constraint_mode_name_, status_.constraint_mode, > sizeof(status_.constraint_mode)); > } > LOG(RPiAgc, Debug) << "exposure_mode " > - << new_exposure_mode_name << " constraint_mode " > - << new_constraint_mode_name << " metering_mode " > - << new_metering_mode_name; > + << exposure_mode_name_ << " constraint_mode " > + << constraint_mode_name_ << " metering_mode " > + << metering_mode_name_; > } > > void Agc::fetchCurrentExposure(Metadata *image_metadata) > @@ -638,10 +615,6 @@ void Agc::writeAndFinish(Metadata *image_metadata, > bool desaturate) > status_.target_exposure_value = desaturate ? 0 : > target_.total_exposure_no_dg; > status_.shutter_time = filtered_.shutter; > status_.analogue_gain = filtered_.analogue_gain; > - { > - std::unique_lock<std::mutex> lock(output_mutex_); > - output_status_ = status_; > - } > // Write to metadata as well, in case anyone wants to update the > camera > // immediately. > image_metadata->Set("agc.status", status_); > diff --git a/src/ipa/raspberrypi/controller/rpi/agc.hpp > b/src/ipa/raspberrypi/controller/rpi/agc.hpp > index ba7ae092..5a02df4e 100644 > --- a/src/ipa/raspberrypi/controller/rpi/agc.hpp > +++ b/src/ipa/raspberrypi/controller/rpi/agc.hpp > @@ -106,12 +106,9 @@ private: > ExposureValues current_; // values for the current frame > ExposureValues target_; // calculate the values we want here > ExposureValues filtered_; // these values are filtered towards > target > - AgcStatus status_; // to "latch" settings so they can't > change > - AgcStatus output_status_; // the status we will write out > - std::mutex output_mutex_; > + AgcStatus status_; > int lock_count_; > // Below here the "settings" that applications can change. > - std::mutex settings_mutex_; > std::string metering_mode_name_; > std::string exposure_mode_name_; > std::string constraint_mode_name_; > -- > 2.20.1 > Apart from the minor nit, Reviewed-by: Naushir Patuck <naush@raspberrypi.com> > > _______________________________________________ > libcamera-devel mailing list > libcamera-devel@lists.libcamera.org > https://lists.libcamera.org/listinfo/libcamera-devel >
diff --git a/src/ipa/raspberrypi/controller/rpi/agc.cpp b/src/ipa/raspberrypi/controller/rpi/agc.cpp index 8079345b..c4379b99 100644 --- a/src/ipa/raspberrypi/controller/rpi/agc.cpp +++ b/src/ipa/raspberrypi/controller/rpi/agc.cpp @@ -160,7 +160,6 @@ Agc::Agc(Controller *controller) status_.total_exposure_value = 0.0; status_.target_exposure_value = 0.0; status_.locked = false; - output_status_ = status_; } char const *Agc::Name() const @@ -185,43 +184,36 @@ void Agc::Read(boost::property_tree::ptree const ¶ms) void Agc::SetEv(double ev) { - std::unique_lock<std::mutex> lock(settings_mutex_); ev_ = ev; } void Agc::SetFlickerPeriod(double flicker_period) { - std::unique_lock<std::mutex> lock(settings_mutex_); flicker_period_ = flicker_period; } void Agc::SetFixedShutter(double fixed_shutter) { - std::unique_lock<std::mutex> lock(settings_mutex_); fixed_shutter_ = fixed_shutter; } void Agc::SetFixedAnalogueGain(double fixed_analogue_gain) { - std::unique_lock<std::mutex> lock(settings_mutex_); fixed_analogue_gain_ = fixed_analogue_gain; } void Agc::SetMeteringMode(std::string const &metering_mode_name) { - std::unique_lock<std::mutex> lock(settings_mutex_); metering_mode_name_ = metering_mode_name; } void Agc::SetExposureMode(std::string const &exposure_mode_name) { - std::unique_lock<std::mutex> lock(settings_mutex_); exposure_mode_name_ = exposure_mode_name; } void Agc::SetConstraintMode(std::string const &constraint_mode_name) { - std::unique_lock<std::mutex> lock(settings_mutex_); constraint_mode_name_ = constraint_mode_name; } @@ -240,14 +232,9 @@ void Agc::SwitchMode([[maybe_unused]] CameraMode const &camera_mode, void Agc::Prepare(Metadata *image_metadata) { - AgcStatus status; - { - std::unique_lock<std::mutex> lock(output_mutex_); - status = output_status_; - } int lock_count = lock_count_; lock_count_ = 0; - status.digital_gain = 1.0; + status_.digital_gain = 1.0; if (status_.total_exposure_value) { // Process has run, so we have meaningful values. DeviceStatus device_status; @@ -255,48 +242,46 @@ void Agc::Prepare(Metadata *image_metadata) double actual_exposure = device_status.shutter_speed * device_status.analogue_gain; if (actual_exposure) { - status.digital_gain = + status_.digital_gain = status_.total_exposure_value / actual_exposure; LOG(RPiAgc, Debug) << "Want total exposure " << status_.total_exposure_value; // Never ask for a gain < 1.0, and also impose // some upper limit. Make it customisable? - status.digital_gain = std::max( + status_.digital_gain = std::max( 1.0, - std::min(status.digital_gain, 4.0)); + std::min(status_.digital_gain, 4.0)); LOG(RPiAgc, Debug) << "Actual exposure " << actual_exposure; - LOG(RPiAgc, Debug) << "Use digital_gain " << status.digital_gain; - LOG(RPiAgc, Debug) << "Effective exposure " << actual_exposure * status.digital_gain; + LOG(RPiAgc, Debug) << "Use digital_gain " << status_.digital_gain; + LOG(RPiAgc, Debug) << "Effective exposure " << actual_exposure * status_.digital_gain; // Decide whether AEC/AGC has converged. // Insist AGC is steady for MAX_LOCK_COUNT // frames before we say we are "locked". // (The hard-coded constants may need to // become customisable.) - if (status.target_exposure_value) { + if (status_.target_exposure_value) { #define MAX_LOCK_COUNT 3 - double err = 0.10 * status.target_exposure_value + 200; + double err = 0.10 * status_.target_exposure_value + 200; if (actual_exposure < - status.target_exposure_value + err - && actual_exposure > - status.target_exposure_value - err) + status_.target_exposure_value + err && + actual_exposure > + status_.target_exposure_value - err) lock_count_ = std::min(lock_count + 1, - MAX_LOCK_COUNT); + MAX_LOCK_COUNT); else if (actual_exposure < - status.target_exposure_value - + 1.5 * err && + status_.target_exposure_value + 1.5 * err && actual_exposure > - status.target_exposure_value - - 1.5 * err) + status_.target_exposure_value - 1.5 * err) lock_count_ = lock_count; LOG(RPiAgc, Debug) << "Lock count: " << lock_count_; } } } else LOG(RPiAgc, Debug) << Name() << ": no device metadata"; - status.locked = lock_count_ >= MAX_LOCK_COUNT; - //printf("%s\n", status.locked ? "+++++++++" : "-"); - image_metadata->Set("agc.status", status); + status_.locked = lock_count_ >= MAX_LOCK_COUNT; + //printf("%s\n", status_.locked ? "+++++++++" : "-"); + image_metadata->Set("agc.status", status_); } } @@ -335,55 +320,47 @@ static void copy_string(std::string const &s, char *d, size_t size) void Agc::housekeepConfig() { // First fetch all the up-to-date settings, so no one else has to do it. - std::string new_exposure_mode_name, new_constraint_mode_name, - new_metering_mode_name; - { - std::unique_lock<std::mutex> lock(settings_mutex_); - new_metering_mode_name = metering_mode_name_; - new_exposure_mode_name = exposure_mode_name_; - new_constraint_mode_name = constraint_mode_name_; - status_.ev = ev_; - status_.fixed_shutter = fixed_shutter_; - status_.fixed_analogue_gain = fixed_analogue_gain_; - status_.flicker_period = flicker_period_; - } + status_.ev = ev_; + status_.fixed_shutter = fixed_shutter_; + status_.fixed_analogue_gain = fixed_analogue_gain_; + status_.flicker_period = flicker_period_; LOG(RPiAgc, Debug) << "ev " << status_.ev << " fixed_shutter " << status_.fixed_shutter << " fixed_analogue_gain " << status_.fixed_analogue_gain; // Make sure the "mode" pointers point to the up-to-date things, if // they've changed. - if (strcmp(new_metering_mode_name.c_str(), status_.metering_mode)) { - auto it = config_.metering_modes.find(new_metering_mode_name); + if (strcmp(metering_mode_name_.c_str(), status_.metering_mode)) { + auto it = config_.metering_modes.find(metering_mode_name_); if (it == config_.metering_modes.end()) throw std::runtime_error("Agc: no metering mode " + - new_metering_mode_name); + metering_mode_name_); metering_mode_ = &it->second; - copy_string(new_metering_mode_name, status_.metering_mode, + copy_string(metering_mode_name_, status_.metering_mode, sizeof(status_.metering_mode)); } - if (strcmp(new_exposure_mode_name.c_str(), status_.exposure_mode)) { - auto it = config_.exposure_modes.find(new_exposure_mode_name); + if (strcmp(exposure_mode_name_.c_str(), status_.exposure_mode)) { + auto it = config_.exposure_modes.find(exposure_mode_name_); if (it == config_.exposure_modes.end()) throw std::runtime_error("Agc: no exposure profile " + - new_exposure_mode_name); + exposure_mode_name_); exposure_mode_ = &it->second; - copy_string(new_exposure_mode_name, status_.exposure_mode, + copy_string(exposure_mode_name_, status_.exposure_mode, sizeof(status_.exposure_mode)); } - if (strcmp(new_constraint_mode_name.c_str(), status_.constraint_mode)) { + if (strcmp(constraint_mode_name_.c_str(), status_.constraint_mode)) { auto it = - config_.constraint_modes.find(new_constraint_mode_name); + config_.constraint_modes.find(constraint_mode_name_); if (it == config_.constraint_modes.end()) throw std::runtime_error("Agc: no constraint list " + - new_constraint_mode_name); + constraint_mode_name_); constraint_mode_ = &it->second; - copy_string(new_constraint_mode_name, status_.constraint_mode, + copy_string(constraint_mode_name_, status_.constraint_mode, sizeof(status_.constraint_mode)); } LOG(RPiAgc, Debug) << "exposure_mode " - << new_exposure_mode_name << " constraint_mode " - << new_constraint_mode_name << " metering_mode " - << new_metering_mode_name; + << exposure_mode_name_ << " constraint_mode " + << constraint_mode_name_ << " metering_mode " + << metering_mode_name_; } void Agc::fetchCurrentExposure(Metadata *image_metadata) @@ -638,10 +615,6 @@ void Agc::writeAndFinish(Metadata *image_metadata, bool desaturate) status_.target_exposure_value = desaturate ? 0 : target_.total_exposure_no_dg; status_.shutter_time = filtered_.shutter; status_.analogue_gain = filtered_.analogue_gain; - { - std::unique_lock<std::mutex> lock(output_mutex_); - output_status_ = status_; - } // Write to metadata as well, in case anyone wants to update the camera // immediately. image_metadata->Set("agc.status", status_); diff --git a/src/ipa/raspberrypi/controller/rpi/agc.hpp b/src/ipa/raspberrypi/controller/rpi/agc.hpp index ba7ae092..5a02df4e 100644 --- a/src/ipa/raspberrypi/controller/rpi/agc.hpp +++ b/src/ipa/raspberrypi/controller/rpi/agc.hpp @@ -106,12 +106,9 @@ private: ExposureValues current_; // values for the current frame ExposureValues target_; // calculate the values we want here ExposureValues filtered_; // these values are filtered towards target - AgcStatus status_; // to "latch" settings so they can't change - AgcStatus output_status_; // the status we will write out - std::mutex output_mutex_; + AgcStatus status_; int lock_count_; // Below here the "settings" that applications can change. - std::mutex settings_mutex_; std::string metering_mode_name_; std::string exposure_mode_name_; std::string constraint_mode_name_;
On the libcamera/VC4 platform the AGC Prepare/Process methods, and any changes to the AGC settings, run synchronously - so a number of mutexes and copies are unnecessary and can be removed. Signed-off-by: David Plowman <david.plowman@raspberrypi.com> --- src/ipa/raspberrypi/controller/rpi/agc.cpp | 99 ++++++++-------------- src/ipa/raspberrypi/controller/rpi/agc.hpp | 5 +- 2 files changed, 37 insertions(+), 67 deletions(-)