From patchwork Tue Jun 29 10:44:59 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Naushir Patuck X-Patchwork-Id: 12744 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 0FDDCC3220 for ; Tue, 29 Jun 2021 10:45:15 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id AFCC1684F1; Tue, 29 Jun 2021 12:45:14 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=raspberrypi.com header.i=@raspberrypi.com header.b="ZTBPlv/L"; dkim-atps=neutral Received: from mail-wr1-x430.google.com (mail-wr1-x430.google.com [IPv6:2a00:1450:4864:20::430]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id B747C684CB for ; Tue, 29 Jun 2021 12:45:10 +0200 (CEST) Received: by mail-wr1-x430.google.com with SMTP id j1so25195855wrn.9 for ; Tue, 29 Jun 2021 03:45:10 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=raspberrypi.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=ByU0tPnr2bUEFQTfwUWtu++AJuNRXu6bhgu6LjppJcU=; b=ZTBPlv/LaRG8n6QhiMM0VgShSF83bJhDQGdHw0oY9nhLGp7Agp+gxfXBsTMnFJPPm0 7ln9bBw3L7CwZz+YiP/IpP/p926BEaPk/t9mj/dKax82VA8tRRM/o9C6+CoCSLICZ25c i8VaSBJ+FaIRdQ51umBzBnn0qrW1HSL25rbgDxQJFGYSOTUGnPsjx0rk5gN6I6zTCoRd 7aFz/JjxZ8B1ByirF8IPhDOvMoXb4IToZ0QNiR3aPO7celAfnNFPibvh6KXHc4H2HEs5 cFI/GAxtYZ1XTzgdC/dLHBvoKzBUg/djGM/S6gmQarWYHjmOCIflUFsL4E4wgykLNwVH MMiA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=ByU0tPnr2bUEFQTfwUWtu++AJuNRXu6bhgu6LjppJcU=; b=ZJcO1smbrwqWuQEVcQTFgpyTFCw9tUE5jxj7xsvRLEuEy5px0NnVb77pqhwHntfGzv BrVJGpbCRGwM3/77lsVMNmCTDBHObqDSkAAjWtAMyLhDskaPNnM8/b1oE9Gcky3skcKn 0SbBvaL1DWNQN+eIdWFTYpj0zFycoJ+HFmLIRW0tpFJSOgdtTUCH1WJkBMpb6zyqUY3E Ec811fq6Kajfc5wpM35+VuizMYuf+Li5HFaPkjBUWlul268jRyi96025VUZEfG1VFW9l ENgIivoFHC/2qpvFqInLMrDBkeHKm5nekGxXHzQ2cfZgduj7PV6pNJdrp0hR3k+ShuWO 8kNQ== X-Gm-Message-State: AOAM530S/U2hI19pavdNE2thtkbQCgf/3cJ1cA3dKhl1Y7LGCJHWWpLK MxlOclpb4BtR+pIasEaAoZuReWLJdSg3Vg== X-Google-Smtp-Source: ABdhPJyxE4eYd2jbB/0VFV6HBXc+FGd0ybMBhkZyXYXch2UEDhe4zsT9qTm/ZIfl59gbBmJmQmZ4Nw== X-Received: by 2002:adf:f907:: with SMTP id b7mr32715778wrr.357.1624963510283; Tue, 29 Jun 2021 03:45:10 -0700 (PDT) Received: from naush-laptop.pitowers.org ([2a00:1098:3142:14:d9cf:b3d0:bdee:72b2]) by smtp.gmail.com with ESMTPSA id l20sm16669930wmq.3.2021.06.29.03.45.09 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 29 Jun 2021 03:45:09 -0700 (PDT) From: Naushir Patuck To: libcamera-devel@lists.libcamera.org Date: Tue, 29 Jun 2021 11:44:59 +0100 Message-Id: <20210629104500.51672-2-naush@raspberrypi.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210629104500.51672-1-naush@raspberrypi.com> References: <20210629104500.51672-1-naush@raspberrypi.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 1/2] ipa: raspberrypi: Use a unique_ptr for the metadata parser X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" The derived CamHelper class now allocates a metadata parser object through a unique_ptr that is passed to the base class constructor. This automates the lifetime management of the parser object. Signed-off-by: Naushir Patuck Reviewed-by: David Plowman Reviewed-by: Kieran Bingham Reviewed-by: Laurent Pinchart --- src/ipa/raspberrypi/cam_helper.cpp | 5 ++--- src/ipa/raspberrypi/cam_helper.hpp | 5 +++-- src/ipa/raspberrypi/cam_helper_imx219.cpp | 4 ++-- src/ipa/raspberrypi/cam_helper_imx290.cpp | 2 +- src/ipa/raspberrypi/cam_helper_imx477.cpp | 2 +- src/ipa/raspberrypi/cam_helper_ov5647.cpp | 2 +- src/ipa/raspberrypi/cam_helper_ov9281.cpp | 2 +- 7 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/ipa/raspberrypi/cam_helper.cpp b/src/ipa/raspberrypi/cam_helper.cpp index 062e94c4fef3..90498c37af98 100644 --- a/src/ipa/raspberrypi/cam_helper.cpp +++ b/src/ipa/raspberrypi/cam_helper.cpp @@ -40,15 +40,14 @@ CamHelper *CamHelper::Create(std::string const &cam_name) return nullptr; } -CamHelper::CamHelper(MdParser *parser, unsigned int frameIntegrationDiff) - : parser_(parser), initialized_(false), +CamHelper::CamHelper(std::unique_ptr parser, unsigned int frameIntegrationDiff) + : parser_(std::move(parser)), initialized_(false), frameIntegrationDiff_(frameIntegrationDiff) { } CamHelper::~CamHelper() { - delete parser_; } void CamHelper::Prepare(Span buffer, diff --git a/src/ipa/raspberrypi/cam_helper.hpp b/src/ipa/raspberrypi/cam_helper.hpp index b19c95f67453..fc3139e22be0 100644 --- a/src/ipa/raspberrypi/cam_helper.hpp +++ b/src/ipa/raspberrypi/cam_helper.hpp @@ -6,6 +6,7 @@ */ #pragma once +#include #include #include @@ -67,7 +68,7 @@ class CamHelper { public: static CamHelper *Create(std::string const &cam_name); - CamHelper(MdParser *parser, unsigned int frameIntegrationDiff); + CamHelper(std::unique_ptr parser, unsigned int frameIntegrationDiff); virtual ~CamHelper(); void SetCameraMode(const CameraMode &mode); virtual void Prepare(libcamera::Span buffer, @@ -92,7 +93,7 @@ protected: void parseEmbeddedData(libcamera::Span buffer, Metadata &metadata); - MdParser *parser_; + std::unique_ptr parser_; CameraMode mode_; private: diff --git a/src/ipa/raspberrypi/cam_helper_imx219.cpp b/src/ipa/raspberrypi/cam_helper_imx219.cpp index ec218dce5456..c85044a5fa6d 100644 --- a/src/ipa/raspberrypi/cam_helper_imx219.cpp +++ b/src/ipa/raspberrypi/cam_helper_imx219.cpp @@ -58,9 +58,9 @@ private: CamHelperImx219::CamHelperImx219() #if ENABLE_EMBEDDED_DATA - : CamHelper(new MdParserImx219(), frameIntegrationDiff) + : CamHelper(std::make_unique(), frameIntegrationDiff) #else - : CamHelper(nullptr, frameIntegrationDiff) + : CamHelper({}, frameIntegrationDiff) #endif { } diff --git a/src/ipa/raspberrypi/cam_helper_imx290.cpp b/src/ipa/raspberrypi/cam_helper_imx290.cpp index 6f412e403f16..871c1f8eaec4 100644 --- a/src/ipa/raspberrypi/cam_helper_imx290.cpp +++ b/src/ipa/raspberrypi/cam_helper_imx290.cpp @@ -30,7 +30,7 @@ private: }; CamHelperImx290::CamHelperImx290() - : CamHelper(nullptr, frameIntegrationDiff) + : CamHelper({}, frameIntegrationDiff) { } diff --git a/src/ipa/raspberrypi/cam_helper_imx477.cpp b/src/ipa/raspberrypi/cam_helper_imx477.cpp index 25b36bce0dac..d72a9be0438e 100644 --- a/src/ipa/raspberrypi/cam_helper_imx477.cpp +++ b/src/ipa/raspberrypi/cam_helper_imx477.cpp @@ -50,7 +50,7 @@ private: }; CamHelperImx477::CamHelperImx477() - : CamHelper(new MdParserImx477(), frameIntegrationDiff) + : CamHelper(std::make_unique(), frameIntegrationDiff) { } diff --git a/src/ipa/raspberrypi/cam_helper_ov5647.cpp b/src/ipa/raspberrypi/cam_helper_ov5647.cpp index 12be6bf931a8..702c2d07f73a 100644 --- a/src/ipa/raspberrypi/cam_helper_ov5647.cpp +++ b/src/ipa/raspberrypi/cam_helper_ov5647.cpp @@ -38,7 +38,7 @@ private: */ CamHelperOv5647::CamHelperOv5647() - : CamHelper(nullptr, frameIntegrationDiff) + : CamHelper({}, frameIntegrationDiff) { } diff --git a/src/ipa/raspberrypi/cam_helper_ov9281.cpp b/src/ipa/raspberrypi/cam_helper_ov9281.cpp index 54091f835565..9de868c31dc0 100644 --- a/src/ipa/raspberrypi/cam_helper_ov9281.cpp +++ b/src/ipa/raspberrypi/cam_helper_ov9281.cpp @@ -34,7 +34,7 @@ private: */ CamHelperOv9281::CamHelperOv9281() - : CamHelper(nullptr, frameIntegrationDiff) + : CamHelper({}, frameIntegrationDiff) { } From patchwork Tue Jun 29 10:45:00 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Naushir Patuck X-Patchwork-Id: 12745 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 360B6C3220 for ; Tue, 29 Jun 2021 10:45:16 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 8BFF0684EB; Tue, 29 Jun 2021 12:45:15 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=raspberrypi.com header.i=@raspberrypi.com header.b="CcuEQkYX"; dkim-atps=neutral Received: from mail-wr1-x42b.google.com (mail-wr1-x42b.google.com [IPv6:2a00:1450:4864:20::42b]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 052D1684ED for ; Tue, 29 Jun 2021 12:45:11 +0200 (CEST) Received: by mail-wr1-x42b.google.com with SMTP id i8so2999788wrc.0 for ; Tue, 29 Jun 2021 03:45:11 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=raspberrypi.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=EH6+B9Ybzch2uo+Fet1PHYrGxOFnIwUE1GDbzuQF4P4=; b=CcuEQkYXmwXC6ELxAZ77PXivDW1u7HZv/5eUefVEGa/Zt18ScPJctQo4kmjmM5keCS SG1fFgD9CGLoWKG/YAFpqX9TJaxLIl6t0FhZenD3LSlYJ5PWBOOZuqI1FdIzEvpRjvvP gm+xLRu87NAQXnX8VqZfcRW1GRFUv0fBJCkspS4Y/D5jJ4usZlMvBwwPFgoUhy16dX0a Ha7otIsI6nY+hR2rZAjYCSXfXRYEugDujSeSBbsk6w/6gRi8QtfyYVk7glsE+JAVqDvt 40DoeSYuQ/IrRmTRjqWFlkhqCl74IGvArDHOhyQe4pHiQ0aqK4m4CEw4kS1pN+6FWcJa ZDNA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=EH6+B9Ybzch2uo+Fet1PHYrGxOFnIwUE1GDbzuQF4P4=; b=uZo/+gAJEWyVqMZPjh0F9QbfYu6s9kLqnpEcWPXenT36ZKRxM5QK4vG/comtCILol2 ytJpDXYPaC0+RA5NeDRXB+HS6AZ8IMoOSEF8kicDHWdJDY9iFeFm6Mh3GmuLQZ0ihFpX 38fJekeXIu02a9QQhoU3hDLMT3ZJFQJ4QBCakk/sim15H9t2VwaX+1W2dvBGX04FhorG uxFv2i8Zr7jlU7MRW/uNvwmAN8Q+7kc1LFUQk8mRA5IQskbdD69y4yyTsqmep+ow0PzY mgupyQS+LD793ArSyObBEGf2Bnc/qPlUpYn//zROgEZherM8RzPE7l30bwxexij03ZWn Nm6Q== X-Gm-Message-State: AOAM533mTubHkLBjErwm19uNsDjytGvvvt0X5S3jyHQU9OZ2fAVz3J5s 7XIR077mJ4AuW7ERBUFJe73UZCVW3VEodQ== X-Google-Smtp-Source: ABdhPJxGxyf0Itroiql0dKpLf4dDcwyE/c7Nq2QLCi+0eTJrMygczLPveWR6X0HPWh7EjPThtqzQ3Q== X-Received: by 2002:adf:fd46:: with SMTP id h6mr32813436wrs.420.1624963511105; Tue, 29 Jun 2021 03:45:11 -0700 (PDT) Received: from naush-laptop.pitowers.org ([2a00:1098:3142:14:d9cf:b3d0:bdee:72b2]) by smtp.gmail.com with ESMTPSA id l20sm16669930wmq.3.2021.06.29.03.45.10 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 29 Jun 2021 03:45:10 -0700 (PDT) From: Naushir Patuck To: libcamera-devel@lists.libcamera.org Date: Tue, 29 Jun 2021 11:45:00 +0100 Message-Id: <20210629104500.51672-3-naush@raspberrypi.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210629104500.51672-1-naush@raspberrypi.com> References: <20210629104500.51672-1-naush@raspberrypi.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 2/2] ipa: raspberrypi: Generalise the SMIA metadata parser X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Instead of having each CamHelper subclass the MdParserSmia, change the implementation of MdParserSmia to be more generic. The MdParserSmia now gets given a list of registers to search for and helper functions are used to compute exposure lines and gain codes from these registers. Update the imx219 and imx477 CamHelpers by using this new mechanism. Signed-off-by: Naushir Patuck Reviewed-by: Laurent Pinchart --- src/ipa/raspberrypi/cam_helper.cpp | 33 +++--- src/ipa/raspberrypi/cam_helper.hpp | 2 + src/ipa/raspberrypi/cam_helper_imx219.cpp | 114 ++++---------------- src/ipa/raspberrypi/cam_helper_imx477.cpp | 122 ++++------------------ src/ipa/raspberrypi/md_parser.hpp | 41 +++++--- src/ipa/raspberrypi/md_parser_smia.cpp | 66 ++++++++++-- 6 files changed, 144 insertions(+), 234 deletions(-) diff --git a/src/ipa/raspberrypi/cam_helper.cpp b/src/ipa/raspberrypi/cam_helper.cpp index 90498c37af98..e6d2258c66d7 100644 --- a/src/ipa/raspberrypi/cam_helper.cpp +++ b/src/ipa/raspberrypi/cam_helper.cpp @@ -159,32 +159,34 @@ unsigned int CamHelper::MistrustFramesModeSwitch() const void CamHelper::parseEmbeddedData(Span buffer, Metadata &metadata) { + MdParser::RegisterMap registers; + Metadata parsedMetadata; + if (buffer.empty()) return; - uint32_t exposureLines, gainCode; - - if (parser_->Parse(buffer) != MdParser::Status::OK || - parser_->GetExposureLines(exposureLines) != MdParser::Status::OK || - parser_->GetGainCode(gainCode) != MdParser::Status::OK) { + 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 DeviceStatus, as - * we know better. Fetch it first in case any other fields were - * set meaningfully. + * 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; - - if (metadata.Get("device.status", deviceStatus) != 0) { + DeviceStatus deviceStatus, parsedDeviceStatus; + if (metadata.Get("device.status", deviceStatus) || + parsedMetadata.Get("device.status", parsedDeviceStatus)) { LOG(IPARPI, Error) << "DeviceStatus not found"; return; } - deviceStatus.shutter_speed = Exposure(exposureLines); - deviceStatus.analogue_gain = Gain(gainCode); + deviceStatus.shutter_speed = parsedDeviceStatus.shutter_speed; + deviceStatus.analogue_gain = parsedDeviceStatus.analogue_gain; LOG(IPARPI, Debug) << "Metadata updated - Exposure : " << deviceStatus.shutter_speed @@ -194,6 +196,11 @@ void CamHelper::parseEmbeddedData(Span buffer, 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) { diff --git a/src/ipa/raspberrypi/cam_helper.hpp b/src/ipa/raspberrypi/cam_helper.hpp index fc3139e22be0..200cc83f3872 100644 --- a/src/ipa/raspberrypi/cam_helper.hpp +++ b/src/ipa/raspberrypi/cam_helper.hpp @@ -92,6 +92,8 @@ public: protected: void parseEmbeddedData(libcamera::Span buffer, Metadata &metadata); + virtual void PopulateMetadata(const MdParser::RegisterMap ®isters, + Metadata &metadata) const; std::unique_ptr parser_; CameraMode mode_; diff --git a/src/ipa/raspberrypi/cam_helper_imx219.cpp b/src/ipa/raspberrypi/cam_helper_imx219.cpp index c85044a5fa6d..4e4994188ff3 100644 --- a/src/ipa/raspberrypi/cam_helper_imx219.cpp +++ b/src/ipa/raspberrypi/cam_helper_imx219.cpp @@ -23,21 +23,14 @@ using namespace RPiController; -/* Metadata parser implementation specific to Sony IMX219 sensors. */ - -class MdParserImx219 : public MdParserSmia -{ -public: - MdParserImx219(); - Status Parse(libcamera::Span buffer) override; - Status GetExposureLines(unsigned int &lines) override; - Status GetGainCode(unsigned int &gain_code) override; -private: - /* Offset of the register's value in the metadata block. */ - int reg_offsets_[3]; - /* Value of the register, once read from the metadata block. */ - int reg_values_[3]; -}; +/* + * We care about one gain register and a pair of exposure registers. Their I2C + * addresses from the Sony IMX219 datasheet: + */ +constexpr uint32_t gainReg = 0x157; +constexpr uint32_t expHiReg = 0x15a; +constexpr uint32_t expLoReg = 0x15b; +constexpr std::initializer_list registerList = { expHiReg, expLoReg, gainReg }; class CamHelperImx219 : public CamHelper { @@ -54,11 +47,14 @@ private: * in units of lines. */ static constexpr int frameIntegrationDiff = 4; + + void PopulateMetadata(const MdParser::RegisterMap ®isters, + Metadata &metadata) const override; }; CamHelperImx219::CamHelperImx219() #if ENABLE_EMBEDDED_DATA - : CamHelper(std::make_unique(), frameIntegrationDiff) + : CamHelper(std::make_unique(registerList), frameIntegrationDiff) #else : CamHelper({}, frameIntegrationDiff) #endif @@ -90,88 +86,20 @@ bool CamHelperImx219::SensorEmbeddedDataPresent() const return ENABLE_EMBEDDED_DATA; } -static CamHelper *Create() +void CamHelperImx219::PopulateMetadata(const MdParser::RegisterMap ®isters, + Metadata &metadata) const { - return new CamHelperImx219(); -} + DeviceStatus deviceStatus; -static RegisterCamHelper reg("imx219", &Create); + deviceStatus.shutter_speed = Exposure(registers.at(expHiReg) * 256 + registers.at(expLoReg)); + deviceStatus.analogue_gain = Gain(registers.at(gainReg)); -/* - * We care about one gain register and a pair of exposure registers. Their I2C - * addresses from the Sony IMX219 datasheet: - */ -#define GAIN_REG 0x157 -#define EXPHI_REG 0x15A -#define EXPLO_REG 0x15B - -/* - * Index of each into the reg_offsets and reg_values arrays. Must be in - * register address order. - */ -#define GAIN_INDEX 0 -#define EXPHI_INDEX 1 -#define EXPLO_INDEX 2 - -MdParserImx219::MdParserImx219() -{ - reg_offsets_[0] = reg_offsets_[1] = reg_offsets_[2] = -1; + metadata.Set("device.status", deviceStatus); } -MdParser::Status MdParserImx219::Parse(libcamera::Span buffer) -{ - bool try_again = false; - - if (reset_) { - /* - * Search again through the metadata for the gain and exposure - * registers. - */ - assert(bits_per_pixel_); - /* Need to be ordered */ - uint32_t regs[3] = { GAIN_REG, EXPHI_REG, EXPLO_REG }; - reg_offsets_[0] = reg_offsets_[1] = reg_offsets_[2] = -1; - int ret = static_cast(findRegs(buffer, - regs, reg_offsets_, 3)); - /* - * > 0 means "worked partially but parse again next time", - * < 0 means "hard error". - */ - if (ret > 0) - try_again = true; - else if (ret < 0) - return ERROR; - } - - for (int i = 0; i < 3; i++) { - if (reg_offsets_[i] == -1) - continue; - - reg_values_[i] = buffer[reg_offsets_[i]]; - } - - /* Re-parse next time if we were unhappy in some way. */ - reset_ = try_again; - - return OK; -} - -MdParser::Status MdParserImx219::GetExposureLines(unsigned int &lines) +static CamHelper *Create() { - if (reg_offsets_[EXPHI_INDEX] == -1 || reg_offsets_[EXPLO_INDEX] == -1) - return NOTFOUND; - - lines = reg_values_[EXPHI_INDEX] * 256 + reg_values_[EXPLO_INDEX]; - - return OK; + return new CamHelperImx219(); } -MdParser::Status MdParserImx219::GetGainCode(unsigned int &gain_code) -{ - if (reg_offsets_[GAIN_INDEX] == -1) - return NOTFOUND; - - gain_code = reg_values_[GAIN_INDEX]; - - return OK; -} +static RegisterCamHelper reg("imx219", &Create); diff --git a/src/ipa/raspberrypi/cam_helper_imx477.cpp b/src/ipa/raspberrypi/cam_helper_imx477.cpp index d72a9be0438e..efd1a5893db8 100644 --- a/src/ipa/raspberrypi/cam_helper_imx477.cpp +++ b/src/ipa/raspberrypi/cam_helper_imx477.cpp @@ -15,21 +15,15 @@ using namespace RPiController; -/* Metadata parser implementation specific to Sony IMX477 sensors. */ - -class MdParserImx477 : public MdParserSmia -{ -public: - MdParserImx477(); - Status Parse(libcamera::Span buffer) override; - Status GetExposureLines(unsigned int &lines) override; - Status GetGainCode(unsigned int &gain_code) override; -private: - /* Offset of the register's value in the metadata block. */ - int reg_offsets_[4]; - /* Value of the register, once read from the metadata block. */ - int reg_values_[4]; -}; +/* + * We care about two gain registers and a pair of exposure registers. Their + * I2C addresses from the Sony IMX477 datasheet: + */ +constexpr uint32_t expHiReg = 0x0202; +constexpr uint32_t expLoReg = 0x0203; +constexpr uint32_t gainHiReg = 0x0204; +constexpr uint32_t gainLoReg = 0x0205; +constexpr std::initializer_list registerList = { expHiReg, expLoReg, gainHiReg, gainLoReg }; class CamHelperImx477 : public CamHelper { @@ -47,10 +41,13 @@ private: * in units of lines. */ static constexpr int frameIntegrationDiff = 22; + + void PopulateMetadata(const MdParser::RegisterMap ®isters, + Metadata &metadata) const override; }; CamHelperImx477::CamHelperImx477() - : CamHelper(std::make_unique(), frameIntegrationDiff) + : CamHelper(std::make_unique(registerList), frameIntegrationDiff) { } @@ -77,95 +74,20 @@ bool CamHelperImx477::SensorEmbeddedDataPresent() const return true; } -static CamHelper *Create() +void CamHelperImx477::PopulateMetadata(const MdParser::RegisterMap ®isters, + Metadata &metadata) const { - return new CamHelperImx477(); -} + DeviceStatus deviceStatus; -static RegisterCamHelper reg("imx477", &Create); + deviceStatus.shutter_speed = Exposure(registers.at(expHiReg) * 256 + registers.at(expLoReg)); + deviceStatus.analogue_gain = Gain(registers.at(gainHiReg) * 256 + registers.at(gainLoReg)); -/* - * We care about two gain registers and a pair of exposure registers. Their - * I2C addresses from the Sony IMX477 datasheet: - */ -#define EXPHI_REG 0x0202 -#define EXPLO_REG 0x0203 -#define GAINHI_REG 0x0204 -#define GAINLO_REG 0x0205 - -/* - * Index of each into the reg_offsets and reg_values arrays. Must be in register - * address order. - */ -#define EXPHI_INDEX 0 -#define EXPLO_INDEX 1 -#define GAINHI_INDEX 2 -#define GAINLO_INDEX 3 - -MdParserImx477::MdParserImx477() -{ - reg_offsets_[0] = reg_offsets_[1] = reg_offsets_[2] = reg_offsets_[3] = -1; + metadata.Set("device.status", deviceStatus); } -MdParser::Status MdParserImx477::Parse(libcamera::Span buffer) -{ - bool try_again = false; - - if (reset_) { - /* - * Search again through the metadata for the gain and exposure - * registers. - */ - assert(bits_per_pixel_); - /* Need to be ordered */ - uint32_t regs[4] = { - EXPHI_REG, - EXPLO_REG, - GAINHI_REG, - GAINLO_REG - }; - reg_offsets_[0] = reg_offsets_[1] = reg_offsets_[2] = reg_offsets_[3] = -1; - int ret = static_cast(findRegs(buffer, - regs, reg_offsets_, 4)); - /* - * > 0 means "worked partially but parse again next time", - * < 0 means "hard error". - */ - if (ret > 0) - try_again = true; - else if (ret < 0) - return ERROR; - } - - for (int i = 0; i < 4; i++) { - if (reg_offsets_[i] == -1) - continue; - - reg_values_[i] = buffer[reg_offsets_[i]]; - } - - /* Re-parse next time if we were unhappy in some way. */ - reset_ = try_again; - - return OK; -} - -MdParser::Status MdParserImx477::GetExposureLines(unsigned int &lines) +static CamHelper *Create() { - if (reg_offsets_[EXPHI_INDEX] == -1 || reg_offsets_[EXPLO_INDEX] == -1) - return NOTFOUND; - - lines = reg_values_[EXPHI_INDEX] * 256 + reg_values_[EXPLO_INDEX]; - - return OK; + return new CamHelperImx477(); } -MdParser::Status MdParserImx477::GetGainCode(unsigned int &gain_code) -{ - if (reg_offsets_[GAINHI_INDEX] == -1 || reg_offsets_[GAINLO_INDEX] == -1) - return NOTFOUND; - - gain_code = reg_values_[GAINHI_INDEX] * 256 + reg_values_[GAINLO_INDEX]; - - return OK; -} +static RegisterCamHelper reg("imx477", &Create); diff --git a/src/ipa/raspberrypi/md_parser.hpp b/src/ipa/raspberrypi/md_parser.hpp index 8497216f8db7..e3e2738537a8 100644 --- a/src/ipa/raspberrypi/md_parser.hpp +++ b/src/ipa/raspberrypi/md_parser.hpp @@ -6,6 +6,9 @@ */ #pragma once +#include +#include +#include #include #include @@ -19,7 +22,7 @@ * application code doesn't have to worry which kind to instantiate. But for * the sake of example let's suppose we're parsing imx219 metadata. * - * MdParser *parser = new MdParserImx219(); // for example + * MdParser *parser = new MdParserSmia({ expHiReg, expLoReg, gainReg }); * parser->SetBitsPerPixel(bpp); * parser->SetLineLengthBytes(pitch); * parser->SetNumLines(2); @@ -32,13 +35,11 @@ * * Then on every frame: * - * if (parser->Parse(buffer) != MdParser::OK) + * RegisterMap registers; + * if (parser->Parse(buffer, registers) != MdParser::OK) * much badness; - * unsigned int exposure_lines, gain_code - * if (parser->GetExposureLines(exposure_lines) != MdParser::OK) - * exposure was not found; - * if (parser->GetGainCode(parser, gain_code) != MdParser::OK) - * gain code was not found; + * Metadata metadata; + * CamHelper::PopulateMetadata(registers, metadata); * * (Note that the CamHelper class converts to/from exposure lines and time, * and gain_code / actual gain.) @@ -59,6 +60,8 @@ namespace RPiController { class MdParser { public: + using RegisterMap = std::map; + /* * Parser status codes: * OK - success @@ -98,9 +101,8 @@ public: line_length_bytes_ = num_bytes; } - virtual Status Parse(libcamera::Span buffer) = 0; - virtual Status GetExposureLines(unsigned int &lines) = 0; - virtual Status GetGainCode(unsigned int &gain_code) = 0; + virtual Status Parse(libcamera::Span buffer, + RegisterMap ®isters) = 0; protected: bool reset_; @@ -116,14 +118,18 @@ protected: * md_parser_imx219.cpp for an example). */ -class MdParserSmia : public MdParser +class MdParserSmia final : public MdParser { public: - MdParserSmia() : MdParser() - { - } + MdParserSmia(std::initializer_list registerList); + + MdParser::Status Parse(libcamera::Span buffer, + RegisterMap ®isters) override; + +private: + /* Maps register address to offset in the buffer. */ + using OffsetMap = std::map>; -protected: /* * Note that error codes > 0 are regarded as non-fatal; codes < 0 * indicate a bad data buffer. Status codes are: @@ -141,8 +147,9 @@ protected: BAD_PADDING = -5 }; - ParseStatus findRegs(libcamera::Span buffer, uint32_t regs[], - int offsets[], unsigned int num_regs); + ParseStatus findRegs(libcamera::Span buffer); + + OffsetMap offsets_; }; } // namespace RPi diff --git a/src/ipa/raspberrypi/md_parser_smia.cpp b/src/ipa/raspberrypi/md_parser_smia.cpp index 0a14875575a2..7f72fc03948f 100644 --- a/src/ipa/raspberrypi/md_parser_smia.cpp +++ b/src/ipa/raspberrypi/md_parser_smia.cpp @@ -6,9 +6,11 @@ */ #include +#include "libcamera/base/log.h" #include "md_parser.hpp" using namespace RPiController; +using namespace libcamera; /* * This function goes through the embedded data to find the offsets (not @@ -26,18 +28,61 @@ constexpr unsigned int REG_LOW_BITS = 0xa5; constexpr unsigned int REG_VALUE = 0x5a; constexpr unsigned int REG_SKIP = 0x55; -MdParserSmia::ParseStatus MdParserSmia::findRegs(libcamera::Span buffer, - uint32_t regs[], int offsets[], - unsigned int num_regs) +MdParserSmia::MdParserSmia(std::initializer_list registerList) { - assert(num_regs > 0); + for (auto r : registerList) + offsets_[r] = {}; +} + +MdParser::Status MdParserSmia::Parse(libcamera::Span buffer, + RegisterMap ®isters) +{ + if (reset_) { + /* + * Search again through the metadata for all the registers + * requested. + */ + ASSERT(bits_per_pixel_); + + for (const auto &[reg, offset] : offsets_) + offsets_[reg] = {}; + + ParseStatus ret = findRegs(buffer); + /* + * > 0 means "worked partially but parse again next time", + * < 0 means "hard error". + * + * In either case, we retry parsing on the next frame. + */ + if (ret != PARSE_OK) + return ERROR; + + reset_ = false; + } + + /* Populate the register values requested. */ + registers.clear(); + for (const auto &[reg, offset] : offsets_) { + if (!offset) { + reset_ = true; + return NOTFOUND; + } + registers[reg] = buffer[offset.value()]; + } + + return OK; +} + +MdParserSmia::ParseStatus MdParserSmia::findRegs(libcamera::Span buffer) +{ + ASSERT(offsets_.size()); if (buffer[0] != LINE_START) return NO_LINE_START; unsigned int current_offset = 1; /* after the LINE_START */ unsigned int current_line_start = 0, current_line = 0; - unsigned int reg_num = 0, first_reg = 0; + unsigned int reg_num = 0, regs_done = 0; while (1) { int tag = buffer[current_offset++]; @@ -89,13 +134,12 @@ MdParserSmia::ParseStatus MdParserSmia::findRegs(libcamera::Span else if (tag == REG_SKIP) reg_num++; else if (tag == REG_VALUE) { - while (reg_num >= - /* assumes registers are in order... */ - regs[first_reg]) { - if (reg_num == regs[first_reg]) - offsets[first_reg] = current_offset - 1; + auto reg = offsets_.find(reg_num); + + if (reg != offsets_.end()) { + offsets_[reg_num] = current_offset - 1; - if (++first_reg == num_regs) + if (++regs_done == offsets_.size()) return PARSE_OK; } reg_num++;