summaryrefslogtreecommitdiff
path: root/src/ipa/raspberrypi/cam_helper.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/ipa/raspberrypi/cam_helper.cpp')
-rw-r--r--src/ipa/raspberrypi/cam_helper.cpp119
1 files changed, 106 insertions, 13 deletions
diff --git a/src/ipa/raspberrypi/cam_helper.cpp b/src/ipa/raspberrypi/cam_helper.cpp
index c8ac3232..3c6afce7 100644
--- a/src/ipa/raspberrypi/cam_helper.cpp
+++ b/src/ipa/raspberrypi/cam_helper.cpp
@@ -17,6 +17,12 @@
#include "md_parser.hpp"
using namespace RPiController;
+using namespace libcamera;
+using libcamera::utils::Duration;
+
+namespace libcamera {
+LOG_DECLARE_CATEGORY(IPARPI)
+}
static std::map<std::string, CamHelperCreateFunc> cam_helpers;
@@ -34,37 +40,80 @@ CamHelper *CamHelper::Create(std::string const &cam_name)
return nullptr;
}
-CamHelper::CamHelper(MdParser *parser)
- : parser_(parser), initialized_(false)
+CamHelper::CamHelper(std::unique_ptr<MdParser> parser, unsigned int frameIntegrationDiff)
+ : parser_(std::move(parser)), initialized_(false),
+ frameIntegrationDiff_(frameIntegrationDiff)
{
}
CamHelper::~CamHelper()
{
- delete parser_;
}
-uint32_t CamHelper::ExposureLines(double exposure_us) const
+void CamHelper::Prepare(Span<const uint8_t> buffer,
+ Metadata &metadata)
+{
+ parseEmbeddedData(buffer, metadata);
+}
+
+void CamHelper::Process([[maybe_unused]] StatisticsPtr &stats,
+ [[maybe_unused]] Metadata &metadata)
+{
+}
+
+uint32_t CamHelper::ExposureLines(const Duration exposure) const
+{
+ assert(initialized_);
+ return exposure / mode_.line_length;
+}
+
+Duration CamHelper::Exposure(uint32_t exposure_lines) const
{
assert(initialized_);
- return exposure_us * 1000.0 / mode_.line_length;
+ return exposure_lines * mode_.line_length;
}
-double CamHelper::Exposure(uint32_t exposure_lines) const
+uint32_t CamHelper::GetVBlanking(Duration &exposure,
+ Duration minFrameDuration,
+ Duration maxFrameDuration) const
{
+ uint32_t frameLengthMin, frameLengthMax, vblank;
+ uint32_t exposureLines = ExposureLines(exposure);
+
assert(initialized_);
- return exposure_lines * mode_.line_length / 1000.0;
+
+ /*
+ * minFrameDuration and maxFrameDuration are clamped by the caller
+ * based on the limits for the active sensor mode.
+ */
+ frameLengthMin = minFrameDuration / mode_.line_length;
+ frameLengthMax = maxFrameDuration / mode_.line_length;
+
+ /*
+ * Limit the exposure to the maximum frame duration requested, and
+ * re-calculate if it has been clipped.
+ */
+ exposureLines = std::min(frameLengthMax - frameIntegrationDiff_, exposureLines);
+ exposure = Exposure(exposureLines);
+
+ /* Limit the vblank to the range allowed by the frame length limits. */
+ vblank = std::clamp(exposureLines + frameIntegrationDiff_,
+ frameLengthMin, frameLengthMax) - mode_.height;
+ return vblank;
}
void CamHelper::SetCameraMode(const CameraMode &mode)
{
mode_ = mode;
- parser_->SetBitsPerPixel(mode.bitdepth);
- parser_->SetLineLengthBytes(0); /* We use SetBufferSize. */
+ if (parser_) {
+ parser_->SetBitsPerPixel(mode.bitdepth);
+ parser_->SetLineLengthBytes(0); /* We use SetBufferSize. */
+ }
initialized_ = true;
}
-void CamHelper::GetDelays(int &exposure_delay, int &gain_delay) const
+void CamHelper::GetDelays(int &exposure_delay, int &gain_delay,
+ int &vblank_delay) const
{
/*
* These values are correct for many sensors. Other sensors will
@@ -72,6 +121,7 @@ void CamHelper::GetDelays(int &exposure_delay, int &gain_delay) const
*/
exposure_delay = 2;
gain_delay = 1;
+ vblank_delay = 2;
}
bool CamHelper::SensorEmbeddedDataPresent() const
@@ -82,10 +132,10 @@ bool CamHelper::SensorEmbeddedDataPresent() const
unsigned int CamHelper::HideFramesStartup() const
{
/*
- * By default, hide 6 frames completely at start-up while AGC etc. sort
- * themselves out (converge).
+ * The number of frames when a camera first starts that shouldn't be
+ * displayed as they are invalid in some way.
*/
- return 6;
+ return 0;
}
unsigned int CamHelper::HideFramesModeSwitch() const
@@ -106,6 +156,49 @@ unsigned int CamHelper::MistrustFramesModeSwitch() const
return 0;
}
+void CamHelper::parseEmbeddedData(Span<const uint8_t> buffer,
+ Metadata &metadata)
+{
+ MdParser::RegisterMap registers;
+ Metadata parsedMetadata;
+
+ if (buffer.empty())
+ return;
+
+ if (parser_->Parse(buffer, registers) != MdParser::Status::OK) {
+ LOG(IPARPI, Error) << "Embedded data buffer parsing failed";
+ return;
+ }
+
+ PopulateMetadata(registers, parsedMetadata);
+ metadata.Merge(parsedMetadata);
+
+ /*
+ * Overwrite the exposure/gain values in the existing DeviceStatus with
+ * values from the parsed embedded buffer. Fetch it first in case any
+ * other fields were set meaningfully.
+ */
+ DeviceStatus deviceStatus, parsedDeviceStatus;
+ if (metadata.Get("device.status", deviceStatus) ||
+ parsedMetadata.Get("device.status", parsedDeviceStatus)) {
+ LOG(IPARPI, Error) << "DeviceStatus not found";
+ return;
+ }
+
+ deviceStatus.shutter_speed = parsedDeviceStatus.shutter_speed;
+ deviceStatus.analogue_gain = parsedDeviceStatus.analogue_gain;
+ deviceStatus.frame_length = parsedDeviceStatus.frame_length;
+
+ LOG(IPARPI, Debug) << "Metadata updated - " << deviceStatus;
+
+ metadata.Set("device.status", deviceStatus);
+}
+
+void CamHelper::PopulateMetadata([[maybe_unused]] const MdParser::RegisterMap &registers,
+ [[maybe_unused]] Metadata &metadata) const
+{
+}
+
RegisterCamHelper::RegisterCamHelper(char const *cam_name,
CamHelperCreateFunc create_func)
{