diff options
Diffstat (limited to 'src/ipa/raspberrypi/cam_helper.cpp')
-rw-r--r-- | src/ipa/raspberrypi/cam_helper.cpp | 119 |
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 ®isters, + [[maybe_unused]] Metadata &metadata) const +{ +} + RegisterCamHelper::RegisterCamHelper(char const *cam_name, CamHelperCreateFunc create_func) { |