From patchwork Tue Jun 15 14:42:09 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Naushir Patuck X-Patchwork-Id: 12604 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 15D3CC3218 for ; Tue, 15 Jun 2021 14:42:19 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 551506894C; Tue, 15 Jun 2021 16:42:17 +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="gxKVQPIt"; dkim-atps=neutral Received: from mail-wr1-x42e.google.com (mail-wr1-x42e.google.com [IPv6:2a00:1450:4864:20::42e]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 6B5596029D for ; Tue, 15 Jun 2021 16:42:15 +0200 (CEST) Received: by mail-wr1-x42e.google.com with SMTP id q5so18664249wrm.1 for ; Tue, 15 Jun 2021 07:42:15 -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=Mx3ZUrPxq8qf2W8C1qUdwxUjpRrwA0SfOt3vj/8i03E=; b=gxKVQPItvlmPvLnNeE/hg4VHmzDYV7nCMXmcc8jWoVeQ0QHA1vEEUXN7xCcOo/cnQh t0m2Bt6ptCyq5jXWGRf9/6oAjzdskqq4z16kCu+6B0mlrPZHzDzJYDhFc+TMpQbSDOQ1 X/VcHec7XAZ5AWGZrSLXrHLVDORc5/IRKG3XBejnJsdigyA+7JnjH0YsWbd8s+E3WZWZ nghSHZiWSI5v7iSkHbA/3RsuqSxhO98RXAC3SlN4Fw/b7hQxn5aAOCXXeSEJgTtXqvTd HlCBgcJzL3ho2M2ZTZ0E/LqgphEmWcHYYdefrDNXlpuXXRPS43UBokb5Gwn6oVYUZD6L ie7A== 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=Mx3ZUrPxq8qf2W8C1qUdwxUjpRrwA0SfOt3vj/8i03E=; b=aclFIZ7MR0m6nza/L5aNOvjhoVyp2xftfB6LJH1cp2l8c3xrnRPpSNpS0rfwd1MjnJ +8QDxZ6dy0EbV87jOu251gUPzRtZY0xts5sl0BvzWfZwhnNVT8wbLooQKvl9x5OI61rX /efIWKp/uaquewNb0DQOjDch10C8obGBGcc29gV2tpaUWcTtHu4vbfQFg1dV0/2bxjy/ UWQFrzellEwJziOyRX3xCDgXkdoYM3zPjhQ2XABXhW8BQg4N5Ak4IQ/Fk0ZqjSI0pzT4 ydsokvkeSW+Gcw53FPMNERq5GtLpNe8UvPajA0omDCaHmgNazLjU+MrGgrMmwxasCclp eiTA== X-Gm-Message-State: AOAM533BjXa9mN1rqF7MAEtaVlo+O20/nqGh63mYe/dAxcVgKoAQjpiq k9KERt5wy60hhWNAWR+6MhZnOSKikRVW3A== X-Google-Smtp-Source: ABdhPJwhJY+uwun6jh4DGnOJMeClLNziatgx2KeG8ebstrh3qyjZN7uYruBQB2JrlgM0/2KvMErAZw== X-Received: by 2002:a5d:6d8c:: with SMTP id l12mr26371380wrs.189.1623768134887; Tue, 15 Jun 2021 07:42:14 -0700 (PDT) Received: from naush-laptop.pitowers.org ([2a00:1098:3142:14:5904:b958:1fd:d555]) by smtp.gmail.com with ESMTPSA id k12sm2441142wmr.2.2021.06.15.07.42.14 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 15 Jun 2021 07:42:14 -0700 (PDT) From: Naushir Patuck To: libcamera-devel@lists.libcamera.org Date: Tue, 15 Jun 2021 15:42:09 +0100 Message-Id: <20210615144211.173047-2-naush@raspberrypi.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210615144211.173047-1-naush@raspberrypi.com> References: <20210615144211.173047-1-naush@raspberrypi.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 1/3] ipa: raspberrypi: Embed the metadata parser in the sensor CamHelper classes 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" This avoids the need for any dynamic allocations and lifetime management. The base CamHelper class still accesses the parser through a pointer that is setup by the derived class constructor. Signed-off-by: Naushir Patuck Reviewed-by: Kieran Bingham Reviewed-by: David Plowman Reviewed-by: Laurent Pinchart --- src/ipa/raspberrypi/cam_helper.cpp | 1 - src/ipa/raspberrypi/cam_helper_imx219.cpp | 4 +++- src/ipa/raspberrypi/cam_helper_imx477.cpp | 4 +++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/ipa/raspberrypi/cam_helper.cpp b/src/ipa/raspberrypi/cam_helper.cpp index 062e94c4fef3..1474464c9257 100644 --- a/src/ipa/raspberrypi/cam_helper.cpp +++ b/src/ipa/raspberrypi/cam_helper.cpp @@ -48,7 +48,6 @@ CamHelper::CamHelper(MdParser *parser, unsigned int frameIntegrationDiff) CamHelper::~CamHelper() { - delete parser_; } void CamHelper::Prepare(Span buffer, diff --git a/src/ipa/raspberrypi/cam_helper_imx219.cpp b/src/ipa/raspberrypi/cam_helper_imx219.cpp index ec218dce5456..d951cd552a21 100644 --- a/src/ipa/raspberrypi/cam_helper_imx219.cpp +++ b/src/ipa/raspberrypi/cam_helper_imx219.cpp @@ -54,11 +54,13 @@ private: * in units of lines. */ static constexpr int frameIntegrationDiff = 4; + + MdParserImx219 imx219_parser; }; CamHelperImx219::CamHelperImx219() #if ENABLE_EMBEDDED_DATA - : CamHelper(new MdParserImx219(), frameIntegrationDiff) + : CamHelper(&imx219_parser, frameIntegrationDiff) #else : CamHelper(nullptr, frameIntegrationDiff) #endif diff --git a/src/ipa/raspberrypi/cam_helper_imx477.cpp b/src/ipa/raspberrypi/cam_helper_imx477.cpp index 25b36bce0dac..44f030ed7da9 100644 --- a/src/ipa/raspberrypi/cam_helper_imx477.cpp +++ b/src/ipa/raspberrypi/cam_helper_imx477.cpp @@ -47,10 +47,12 @@ private: * in units of lines. */ static constexpr int frameIntegrationDiff = 22; + + MdParserImx477 imx477_parser; }; CamHelperImx477::CamHelperImx477() - : CamHelper(new MdParserImx477(), frameIntegrationDiff) + : CamHelper(&imx477_parser, frameIntegrationDiff) { } From patchwork Tue Jun 15 14:42:10 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Naushir Patuck X-Patchwork-Id: 12605 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 06286C3218 for ; Tue, 15 Jun 2021 14:42:20 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id C8AC268946; Tue, 15 Jun 2021 16:42:17 +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="R224ZhPu"; dkim-atps=neutral Received: from mail-wr1-x436.google.com (mail-wr1-x436.google.com [IPv6:2a00:1450:4864:20::436]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 2FF0C6029D for ; Tue, 15 Jun 2021 16:42:16 +0200 (CEST) Received: by mail-wr1-x436.google.com with SMTP id v9so2348162wrx.6 for ; Tue, 15 Jun 2021 07:42:16 -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=qZ5x/QJR9ar257IFq88wn4YlpH7vJmdUmMNASJJkMdM=; b=R224ZhPuqIf9XDpp9StkQwjEywP0quQ1Jema/tfdPAaZHJKY3JWJ3p327/Z+wIEbiT 2cq0rebJ/FeB2ksqGoslP9/U+5+PzN3oALVQl6QFbot1cIqIxqSwdjurlmeztKkPkfuC cFJf9eQzwEyCFqWkg3yfDrVy5Rp854EwyGZIv94PF6NmkJ4/kLoaM6QvwxzclSz9Zjn2 h2iscb6SxPynJCCGwdsBHeMEauVHIh5V2y2wGLva1eY7r7zGPOgXQROR72uGhhAGnS4X Qv+eFtAFFgxfBuoozlxUOb94TNX0LVEysyYJFrYg4TU8G0tQ3v2N0LF9O3owUBk9/M8J rI6A== 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=qZ5x/QJR9ar257IFq88wn4YlpH7vJmdUmMNASJJkMdM=; b=K41diAXro+oCpHnYp7MvI5v4il5hIo1JeBIece2JJVHSJBp3FJ3xwJvjUc3AU9qNQY JyBbh/ALLgoP8qJIyYarNdIKprckm7DNOFzU8xys2NMuNK++LlX4DNE7D8GXEFrktypS J0rM7vb4RmW0ke4XOm+m1E4uM5BhyQr4nWH6ZkJLmA3rskfFpwEMTgQwkRucPK7L5gHq GMb3gmYj1pOA5Y60rK3AL4sErmWH+9Lzn+VNDBQWo4yzihQs+IIKivWr815IY9E3874O PcBknZk8+ajNs8jbd4N4/VIR/vV8NKXMIMPkIgZSkdR5uDvVbn2owzfxmu8/a/O62ZaI Y22Q== X-Gm-Message-State: AOAM533N25v/ZSahLBStceNjOdfPDcMfNVkNp07q1L+7jmwgVCvQ0b3c vZbCT7MYn6yUGLFj2WQT2jTzWVYmf5auDA== X-Google-Smtp-Source: ABdhPJwAOR/bgBH0GN7n2kNH35HBEF/FHvzA6MDGVV7pOggsPgUGrwsGTQW/sTqeROObZGXCGhhNiw== X-Received: by 2002:a5d:6082:: with SMTP id w2mr25666620wrt.209.1623768135660; Tue, 15 Jun 2021 07:42:15 -0700 (PDT) Received: from naush-laptop.pitowers.org ([2a00:1098:3142:14:5904:b958:1fd:d555]) by smtp.gmail.com with ESMTPSA id k12sm2441142wmr.2.2021.06.15.07.42.14 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 15 Jun 2021 07:42:15 -0700 (PDT) From: Naushir Patuck To: libcamera-devel@lists.libcamera.org Date: Tue, 15 Jun 2021 15:42:10 +0100 Message-Id: <20210615144211.173047-3-naush@raspberrypi.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210615144211.173047-1-naush@raspberrypi.com> References: <20210615144211.173047-1-naush@raspberrypi.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 2/3] ipa: raspberrypi: Fix possible buffer overrun in metadata parsing 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 SMIA metadata parser could possibly read one byte past the end of the buffer as the buffer size test ran after the read operation. Fix this. Signed-off-by: Naushir Patuck Reviewed-by: Kieran Bingham Reviewed-by: David Plowman Reviewed-by: Laurent Pinchart --- src/ipa/raspberrypi/md_parser_smia.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ipa/raspberrypi/md_parser_smia.cpp b/src/ipa/raspberrypi/md_parser_smia.cpp index 5c413f1b55cc..0a14875575a2 100644 --- a/src/ipa/raspberrypi/md_parser_smia.cpp +++ b/src/ipa/raspberrypi/md_parser_smia.cpp @@ -71,8 +71,8 @@ MdParserSmia::ParseStatus MdParserSmia::findRegs(libcamera::Span return NO_LINE_START; } else { /* allow a zero line length to mean "hunt for the next line" */ - while (buffer[current_offset] != LINE_START && - current_offset < buffer.size()) + while (current_offset < buffer.size() && + buffer[current_offset] != LINE_START) current_offset++; if (current_offset == buffer.size()) From patchwork Tue Jun 15 14:42:11 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Naushir Patuck X-Patchwork-Id: 12606 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 3ED38C3218 for ; Tue, 15 Jun 2021 14:42:21 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id ED39668947; Tue, 15 Jun 2021 16:42:20 +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="GYJX8Of2"; dkim-atps=neutral Received: from mail-wm1-x329.google.com (mail-wm1-x329.google.com [IPv6:2a00:1450:4864:20::329]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 5308A6894B for ; Tue, 15 Jun 2021 16:42:17 +0200 (CEST) Received: by mail-wm1-x329.google.com with SMTP id l7-20020a05600c1d07b02901b0e2ebd6deso2177245wms.1 for ; Tue, 15 Jun 2021 07:42:17 -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=UqBAMU+hGzhajQp+YHiicwMjOgX7sKUTm5LvzwB97SE=; b=GYJX8Of2Mk+3iQypf1QuidmfF1kSZr0Aj/8ueMA1V9xaXBhIkrLs79RMUxGG8f5h+N KCVONSOMClKglO1MfaYoC68UVXxNoIIJ3KzeMR9DNERNYA8F6NWy7/SIRHp3HLaNS72L lVA6VwVMiE+AznSx58B1AKMInldnyMzYnzMmwJKCexh+d9OfajcXvLUASqw6BryVcygD zYCrOGnYDwMnKyGd4nNgOGgYCgxAmpI9zUBmZ5oCVptdFIfIAPGscR7/2r6n8qHt/vmX f8iT/mk81XLKJDpyJWCBPiCfpv6goaA42Tay7lfAyk3xWXmLlFjFMFkBY7p+coWC/epr ixIw== 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=UqBAMU+hGzhajQp+YHiicwMjOgX7sKUTm5LvzwB97SE=; b=JB+hzCBGkH1ZHlc80YdPwWwaAX5xnYMffn5JZ4/SITyosLaCvM6OZpRPsBplzYpe3b b6K8N+OGd++lXAx70F9EGu0j9mCjxuEIEuQ7w5LsGKHDU/75UeByz9nMCRWihH02I37F xtzr07ZZuvgJVSwNIOmSa/8Nb9Q5i4hk8TkyHF7hY75Auv9eGDCLjRCmUS2Pz1vqGVK8 doydF7OgBQ7rGCR/LGfd54GQbMiE+zpPcEZJOa4PYLqfNOwBiA8Cfmoe9lVTLj/AA7nc bZfb8/nZnHmyV47pPs5FdHWECscSB9NIOUGRaMceUFq6yZHn+k91Ez8pkamGw2eIxUvV 9wbA== X-Gm-Message-State: AOAM533YOMVltnpEYNBB5v1/gdt+wbbkwiySwUMNdGQfMKm2khvH1u7q uxIx0MoQWI2p5clEFx5F41oWQOuenhVujQ== X-Google-Smtp-Source: ABdhPJzDHTe8uh0PvBxwUw3UIugWPr7jEPl0c/TweYI/dYrLsKnyeyaswCeuv5EeCflgYaBc1sgVIw== X-Received: by 2002:a7b:ce13:: with SMTP id m19mr23816595wmc.159.1623768136512; Tue, 15 Jun 2021 07:42:16 -0700 (PDT) Received: from naush-laptop.pitowers.org ([2a00:1098:3142:14:5904:b958:1fd:d555]) by smtp.gmail.com with ESMTPSA id k12sm2441142wmr.2.2021.06.15.07.42.15 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 15 Jun 2021 07:42:15 -0700 (PDT) From: Naushir Patuck To: libcamera-devel@lists.libcamera.org Date: Tue, 15 Jun 2021 15:42:11 +0100 Message-Id: <20210615144211.173047-4-naush@raspberrypi.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210615144211.173047-1-naush@raspberrypi.com> References: <20210615144211.173047-1-naush@raspberrypi.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 3/3] 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 --- src/ipa/raspberrypi/cam_helper.cpp | 35 +++--- src/ipa/raspberrypi/cam_helper.hpp | 2 + src/ipa/raspberrypi/cam_helper_imx219.cpp | 118 ++++---------------- src/ipa/raspberrypi/cam_helper_imx477.cpp | 124 ++++------------------ src/ipa/raspberrypi/md_parser.hpp | 42 +++++--- src/ipa/raspberrypi/md_parser_smia.cpp | 66 ++++++++++-- 6 files changed, 148 insertions(+), 239 deletions(-) diff --git a/src/ipa/raspberrypi/cam_helper.cpp b/src/ipa/raspberrypi/cam_helper.cpp index 1474464c9257..41e292ecbb61 100644 --- a/src/ipa/raspberrypi/cam_helper.cpp +++ b/src/ipa/raspberrypi/cam_helper.cpp @@ -159,32 +159,32 @@ unsigned int CamHelper::MistrustFramesModeSwitch() const void CamHelper::parseEmbeddedData(Span buffer, Metadata &metadata) { + MdParser::RegisterMap map; + 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, map) != MdParser::Status::OK) { LOG(IPARPI, Error) << "Embedded data buffer parsing failed"; return; } + PopulateMetadata(map, 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) { - LOG(IPARPI, Error) << "DeviceStatus not found"; + DeviceStatus deviceStatus, parsedDeviceStatus; + if (metadata.Get("device.status", deviceStatus) || + parsedMetadata.Get("device.status", parsedDeviceStatus)) 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 +194,11 @@ void CamHelper::parseEmbeddedData(Span buffer, metadata.Set("device.status", deviceStatus); } +void CamHelper::PopulateMetadata([[maybe_unused]] const MdParser::RegisterMap &map, + [[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 f53f5c39b01c..30879e60b861 100644 --- a/src/ipa/raspberrypi/cam_helper.hpp +++ b/src/ipa/raspberrypi/cam_helper.hpp @@ -91,6 +91,8 @@ public: protected: void parseEmbeddedData(libcamera::Span buffer, Metadata &metadata); + virtual void PopulateMetadata([[maybe_unused]] const MdParser::RegisterMap &map, + [[maybe_unused]] Metadata &metadata) const; MdParser *parser_; CameraMode mode_; diff --git a/src/ipa/raspberrypi/cam_helper_imx219.cpp b/src/ipa/raspberrypi/cam_helper_imx219.cpp index d951cd552a21..24818e9ec4de 100644 --- a/src/ipa/raspberrypi/cam_helper_imx219.cpp +++ b/src/ipa/raspberrypi/cam_helper_imx219.cpp @@ -23,21 +23,13 @@ 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; class CamHelperImx219 : public CamHelper { @@ -55,15 +47,19 @@ private: */ static constexpr int frameIntegrationDiff = 4; - MdParserImx219 imx219_parser; + MdParserSmia imx219_parser; + + void PopulateMetadata(const MdParser::RegisterMap &map, + Metadata &metadata) const override; }; CamHelperImx219::CamHelperImx219() #if ENABLE_EMBEDDED_DATA - : CamHelper(&imx219_parser, frameIntegrationDiff) + : CamHelper(&imx219_parser, frameIntegrationDiff), #else - : CamHelper(nullptr, frameIntegrationDiff) + : CamHelper(nullptr, frameIntegrationDiff), #endif + imx219_parser({ gainReg, expHiReg, expLoReg }) { } @@ -92,88 +88,20 @@ bool CamHelperImx219::SensorEmbeddedDataPresent() const return ENABLE_EMBEDDED_DATA; } -static CamHelper *Create() +void CamHelperImx219::PopulateMetadata(const MdParser::RegisterMap &map, + Metadata &metadata) const { - return new CamHelperImx219(); -} + DeviceStatus deviceStatus; -static RegisterCamHelper reg("imx219", &Create); + deviceStatus.shutter_speed = Exposure(map.at(expHiReg) * 256 + map.at(expLoReg)); + deviceStatus.analogue_gain = Gain(map.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 44f030ed7da9..7586e5f897d5 100644 --- a/src/ipa/raspberrypi/cam_helper_imx477.cpp +++ b/src/ipa/raspberrypi/cam_helper_imx477.cpp @@ -15,21 +15,14 @@ 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; class CamHelperImx477 : public CamHelper { @@ -48,11 +41,15 @@ private: */ static constexpr int frameIntegrationDiff = 22; - MdParserImx477 imx477_parser; + MdParserSmia imx477_parser; + + void PopulateMetadata(const MdParser::RegisterMap &map, + Metadata &metadata) const override; }; CamHelperImx477::CamHelperImx477() - : CamHelper(&imx477_parser, frameIntegrationDiff) + : CamHelper(&imx477_parser, frameIntegrationDiff), + imx477_parser({ expHiReg, expLoReg, gainHiReg, gainLoReg }) { } @@ -79,95 +76,20 @@ bool CamHelperImx477::SensorEmbeddedDataPresent() const return true; } -static CamHelper *Create() +void CamHelperImx477::PopulateMetadata(const MdParser::RegisterMap &map, + Metadata &metadata) const { - return new CamHelperImx477(); -} + DeviceStatus deviceStatus; -static RegisterCamHelper reg("imx477", &Create); + deviceStatus.shutter_speed = Exposure(map.at(expHiReg) * 256 + map.at(expLoReg)); + deviceStatus.analogue_gain = Gain(map.at(gainHiReg) * 256 + map.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 65aab02d51b6..64f9bbb12845 100644 --- a/src/ipa/raspberrypi/md_parser.hpp +++ b/src/ipa/raspberrypi/md_parser.hpp @@ -8,6 +8,10 @@ #include +#include +#include +#include + #include /* @@ -19,7 +23,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 +36,11 @@ * * Then on every frame: * - * if (parser->Parse(buffer) != MdParser::OK) + * RegisterMap map; + * if (parser->Parse(buffer, map) != 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(map, metadata); * * (Note that the CamHelper class converts to/from exposure lines and time, * and gain_code / actual gain.) @@ -59,6 +61,8 @@ namespace RPiController { class MdParser { public: + using RegisterMap = std::map; + /* * Parser status codes: * OK - success @@ -98,9 +102,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 &map) = 0; protected: bool reset_; @@ -116,14 +119,18 @@ protected: * md_parser_imx219.cpp for an example). */ -class MdParserSmia : public MdParser +class MdParserSmia final : public MdParser { public: - MdParserSmia() : MdParser() - { - } + MdParserSmia(const std::vector ®s); + + MdParser::Status Parse(libcamera::Span buffer, + RegisterMap &map) 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 +148,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..9920699dfe25 100644 --- a/src/ipa/raspberrypi/md_parser_smia.cpp +++ b/src/ipa/raspberrypi/md_parser_smia.cpp @@ -6,9 +6,11 @@ */ #include +#include "libcamera/internal/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(const std::vector ®isters) { - assert(num_regs > 0); + for (auto r : registers) + offsets_[r] = {}; +} + +MdParser::Status MdParserSmia::Parse(libcamera::Span buffer, + RegisterMap &map) +{ + if (reset_) { + /* + * Search again through the metadata for the gain and exposure + * registers. + */ + ASSERT(bits_per_pixel_); + + for (auto &kv : offsets_) + offsets_[kv.first] = {}; + + 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. */ + map.clear(); + for (auto &kv : offsets_) { + if (!kv.second) { + reset_ = true; + return NOTFOUND; + } + map[kv.first] = buffer[kv.second.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++;