From patchwork Wed Jun 1 23:17:59 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christian Rauch X-Patchwork-Id: 16127 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 35771C3256 for ; Wed, 1 Jun 2022 23:18:20 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 0EEC165637; Thu, 2 Jun 2022 01:18:19 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1654125499; bh=dYd4SEO/wKUUSY9mxAYDnNUBt2P9MmuPdq+E3WZUQhc=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=fNjqzZhSXM/uzQRVco8/lbq1lDO8PSsuwwDrQziihg5YgDniK3VGg+1kEWHpBPE6f rMBzj/bdvK/MzCtA1cRW/eOSsBF31el1KOT08wo9SEluY4gdnx3b9bGlpJ8DKLfvY5 XyKXoXRHSoRTT1yhaas/CRwEa+jvxcpvWYDQeQoJK+qzJ6wIX88GQJZo7mS2KtDzyx e8ILF0c9HhnLnVD6RCWYNENYCSzKSdX/j5wgD7Oid1bJp9E10jIndQ03xCMvb9PqU+ dhbccKnUi8sXJJ7SBmJT/UQZuTxgf8wCZBixzCWf1TJJQ+sgQZum4Elfu1fyXt3AW2 BRck5R6JfnvPw== Received: from mout.gmx.net (mout.gmx.net [212.227.17.22]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id A81EC60414 for ; Thu, 2 Jun 2022 01:18:15 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=gmx.net header.i=@gmx.net header.b="PYSm5P3I"; dkim-atps=neutral DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=gmx.net; s=badeba3b8450; t=1654125495; bh=dYd4SEO/wKUUSY9mxAYDnNUBt2P9MmuPdq+E3WZUQhc=; h=X-UI-Sender-Class:From:To:Cc:Subject:Date:In-Reply-To:References; b=PYSm5P3IxbFCv7t23iJEsJCLK5TIqyQ0WhU9R1WRiex9EZRsKIGEp7BYToLf2Rgd+ nPN5f/GZCAlzrhH+6QCbiMWQU4Cxzqcjga2Cx+cGKXDDfjig2SRDqAZFw5pjY2UpTT GGz9Lo5wgp4DHs5o3K0MGM2kXO43ePWB1xAFH3Uw= X-UI-Sender-Class: 01bb95c1-4bf8-414a-932a-4f6e2808ef9c Received: from localhost.localdomain ([92.18.80.244]) by mail.gmx.net (mrgmx105 [212.227.17.168]) with ESMTPSA (Nemesis) id 1MnJlc-1nUsHT0mOK-00jFUa; Thu, 02 Jun 2022 01:18:15 +0200 To: libcamera-devel@lists.libcamera.org Date: Thu, 2 Jun 2022 00:17:59 +0100 Message-Id: <20220601231802.16735-2-Rauch.Christian@gmx.de> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220601231802.16735-1-Rauch.Christian@gmx.de> References: <20220601231802.16735-1-Rauch.Christian@gmx.de> MIME-Version: 1.0 X-Provags-ID: V03:K1:Op+qXHQQEKBCOheyQk/oTn6rNWtA5UwB5UlmUjMIYdkyMgHP7di GTqa8hPOhtizsErYUJc4d6FmDKg3uQLDpR/6RLDVKdM93tz5MndGZOmil4q2yfH0I1VeJUf HiktF/DUbp48Nx7fS7mxVgTUlJ83ZnHzxYcNokjzYttDxyQ0I2FRbnKn8lONWoRFIjhBf3o Hb1hBKo2LkULtcs5BOGFQ== X-Spam-Flag: NO X-UI-Out-Filterresults: notjunk:1; V03:K0:c+PSh9tbOF0=:2Z85xk1X2cmusSkETqZGmE iSGhRldlUkP0MunAj8EN/XDeISBEne9zx7xrqukBqV2sJo8eDez8Kat+z7bclfL0OmF8jpu+S YqffFRKI6FNiNqBPVjozSrFvnGKytR+gFIT2b1vKe28OcrQOOHgfM7yFiiCwNiOsIBKraZuPN 9yGxuwARLj5gBaRGQrY4BNtnP7jXzHIvvWcwEHZotV92hzpou8fYFBTDSjEStp38ccPL/zVFo y9f3MpDnCsUD9wqAKW4aF8gul0O/bEiQ8B02QyEBitYS+ppS0PzvxLaS231YXyAxQ7gKIw1Cx ZAYy2AnXgehCfW8707KfrAWF/zwrOABKGOBcf96B0010O5EfrOm9qyrv7QzkV1OR/1nktemU6 et8DbvCmtaLj4WYlCtrs9HluGrck9bqK/pGIoRWIxpdPO2fC7+NKtIhi5xF1FjxiiI4M+gbl5 GhrQyfqiZJtkg5L+dnbKP1bWaDBZhQncJTQ+ad4VK1Pd5m8cbLcmR98JmyEAE0pMwEu8HI0Ih 3AAECtmTMUdmrZPLbx3wAtYIquvMzAr/qyp5nijaPOpbDWzv0ANM9sXSwRuRCoDvETPuQ32pG a4nS2WgLGyCGNCB2i4aNGeh1EwAYbsRKFr22eTRyNrQKrCovcxtP/+H6TTfZkeFfz1ApZYdqf sCQQQglAIl+4VVVbpL/BUvhWYMmpWN3XZ5kVdwSruB4f+9PYfl6SJyZWy0+dJzKO1AgK+obDA /x5QbaNnj5uds6wCoG2US1Zhdje9JqGzmH4RdvINLXPo9I+9BUz7Wb9rO4ydYwyBmShcZQQsg 70/2SvGYusRa2BsQcz29wu9T78BIqdS0IcauyZ7BECC7P6GrUm9ltg3g2gBUI785Ba8rR1WLO QuG4uPBIhvSo2PSIBRMdTYGyQP8TVfQUMKVA824BdVAlWewh8KZiBMNXfPQCeiUSHQPd5F0Kc uAuNN1MIWKvDGpIktM7MijPFBd6W5egr+VtpezJwrHhaE3PMQ92hxRAVjP5JGyQLhfljCuH2q bz3zfQGzmGlCh8PQwXndqMiDvO241jpTEJiG//ugDQGoIVG2nlhfq6Z8qryS1+N0cGd+EZrcV vIHQpJRKJnJnY48NTJFJhOKLNb+88M6fG4boLxkJdf4kEVShlYpnoqpxg== Subject: [libcamera-devel] [PATCH v5 1/4] libcamera: controls: Use std::optional to handle invalid control values 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: , X-Patchwork-Original-From: Christian Rauch via libcamera-devel From: Christian Rauch Reply-To: Christian Rauch Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Previously, ControlList::get() would use default constructed objects to indicate that a ControlList does not have the requested Control. This has several disadvantages: 1) It requires types to be default constructible, 2) it does not differentiate between a default constructed object and an object that happens to have the same state as a default constructed object. std::optional additionally stores the information if the object is valid or not, and therefore is more expressive than a default constructed object. Signed-off-by: Christian Rauch --- include/libcamera/controls.h | 7 ++++--- src/cam/main.cpp | 4 ++-- src/ipa/raspberrypi/raspberrypi.cpp | 2 +- src/libcamera/pipeline/ipu3/ipu3.cpp | 9 ++++----- .../pipeline/raspberrypi/raspberrypi.cpp | 10 ++++++---- src/qcam/dng_writer.cpp | 15 +++++++++------ 6 files changed, 26 insertions(+), 21 deletions(-) -- 2.34.1 diff --git a/include/libcamera/controls.h b/include/libcamera/controls.h index 665bcac1..363e7809 100644 --- a/include/libcamera/controls.h +++ b/include/libcamera/controls.h @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -167,7 +168,7 @@ public: using V = typename T::value_type; const V *value = reinterpret_cast(data().data()); - return { value, numElements_ }; + return T{ value, numElements_ }; } #ifndef __DOXYGEN__ @@ -373,11 +374,11 @@ public: bool contains(unsigned int id) const; template - T get(const Control &ctrl) const + std::optional get(const Control &ctrl) const { const ControlValue *val = find(ctrl.id()); if (!val) - return T{}; + return std::nullopt; return val->get(); } diff --git a/src/cam/main.cpp b/src/cam/main.cpp index 79875ed7..9b773931 100644 --- a/src/cam/main.cpp +++ b/src/cam/main.cpp @@ -301,7 +301,7 @@ std::string CamApp::cameraName(const Camera *camera) * is only used if the location isn't present or is set to External. */ if (props.contains(properties::Location)) { - switch (props.get(properties::Location)) { + switch (props.get(properties::Location).value_or(int32_t{})) { case properties::CameraLocationFront: addModel = false; name = "Internal front camera "; @@ -321,7 +321,7 @@ std::string CamApp::cameraName(const Camera *camera) * If the camera location is not availble use the camera model * to build the camera name. */ - name = "'" + props.get(properties::Model) + "' "; + name = "'" + props.get(properties::Model).value_or(std::string{}) + "' "; } name += "(" + camera->id() + ")"; diff --git a/src/ipa/raspberrypi/raspberrypi.cpp b/src/ipa/raspberrypi/raspberrypi.cpp index 3b126bb5..00600a2e 100644 --- a/src/ipa/raspberrypi/raspberrypi.cpp +++ b/src/ipa/raspberrypi/raspberrypi.cpp @@ -939,7 +939,7 @@ void IPARPi::returnEmbeddedBuffer(unsigned int bufferId) void IPARPi::prepareISP(const ISPConfig &data) { - int64_t frameTimestamp = data.controls.get(controls::SensorTimestamp); + int64_t frameTimestamp = data.controls.get(controls::SensorTimestamp).value_or(int64_t{}); RPiController::Metadata lastMetadata; Span embeddedBuffer; diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp index fd989e61..1e9e5081 100644 --- a/src/libcamera/pipeline/ipu3/ipu3.cpp +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp @@ -1145,7 +1145,7 @@ int PipelineHandlerIPU3::registerCameras() /* Convert the sensor rotation to a transformation */ int32_t rotation = 0; if (data->properties_.contains(properties::Rotation)) - rotation = data->properties_.get(properties::Rotation); + rotation = data->properties_.get(properties::Rotation).value_or(int32_t{}); else LOG(IPU3, Warning) << "Rotation control not exposed by " << cio2->sensor()->id() @@ -1331,7 +1331,7 @@ void IPU3CameraData::imguOutputBufferReady(FrameBuffer *buffer) request->metadata().set(controls::draft::PipelineDepth, 3); /* \todo Actually apply the scaler crop region to the ImgU. */ if (request->controls().contains(controls::ScalerCrop)) - cropRegion_ = request->controls().get(controls::ScalerCrop); + cropRegion_ = request->controls().get(controls::ScalerCrop).value_or(Rectangle{}); request->metadata().set(controls::ScalerCrop, cropRegion_); if (frameInfos_.tryComplete(info)) @@ -1424,7 +1424,7 @@ void IPU3CameraData::statBufferReady(FrameBuffer *buffer) return; } - ipa_->processStatsBuffer(info->id, request->metadata().get(controls::SensorTimestamp), + ipa_->processStatsBuffer(info->id, request->metadata().get(controls::SensorTimestamp).value_or(int64_t{}), info->statBuffer->cookie(), info->effectiveSensorControls); } @@ -1458,8 +1458,7 @@ void IPU3CameraData::frameStart(uint32_t sequence) if (!request->controls().contains(controls::draft::TestPatternMode)) return; - const int32_t testPatternMode = request->controls().get( - controls::draft::TestPatternMode); + const int32_t testPatternMode = request->controls().get(controls::draft::TestPatternMode).value_or(int32_t{}); int ret = cio2_.sensor()->setTestPatternMode( static_cast(testPatternMode)); diff --git a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp index adc397e8..556af882 100644 --- a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp +++ b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp @@ -365,7 +365,7 @@ CameraConfiguration::Status RPiCameraConfiguration::validate() * error means the platform can never run. Let's just print a warning * and continue regardless; the rotation is effectively set to zero. */ - int32_t rotation = data_->sensor_->properties().get(properties::Rotation); + int32_t rotation = data_->sensor_->properties().get(properties::Rotation).value_or(int32_t{}); bool success; Transform rotationTransform = transformFromRotation(rotation, &success); if (!success) @@ -1706,7 +1706,9 @@ void RPiCameraData::statsMetadataComplete(uint32_t bufferId, const ControlList & * V4L2_CID_NOTIFY_GAINS control (which means notifyGainsUnity_ is set). */ if (notifyGainsUnity_ && controls.contains(libcamera::controls::ColourGains)) { - libcamera::Span colourGains = controls.get(libcamera::controls::ColourGains); + libcamera::Span colourGains = + controls.get(libcamera::controls::ColourGains).\ + value_or(libcamera::Span({ 0, 0 })); /* The control wants linear gains in the order B, Gb, Gr, R. */ ControlList ctrls(sensor_->controls()); std::array gains{ @@ -2041,7 +2043,7 @@ Rectangle RPiCameraData::scaleIspCrop(const Rectangle &ispCrop) const void RPiCameraData::applyScalerCrop(const ControlList &controls) { if (controls.contains(controls::ScalerCrop)) { - Rectangle nativeCrop = controls.get(controls::ScalerCrop); + Rectangle nativeCrop = controls.get(controls::ScalerCrop).value_or(Rectangle{}); if (!nativeCrop.width || !nativeCrop.height) nativeCrop = { 0, 0, 1, 1 }; @@ -2079,7 +2081,7 @@ void RPiCameraData::fillRequestMetadata(const ControlList &bufferControls, Request *request) { request->metadata().set(controls::SensorTimestamp, - bufferControls.get(controls::SensorTimestamp)); + bufferControls.get(controls::SensorTimestamp).value_or(int64_t{})); request->metadata().set(controls::ScalerCrop, scalerCrop_); } diff --git a/src/qcam/dng_writer.cpp b/src/qcam/dng_writer.cpp index 34c8df5a..e119ca52 100644 --- a/src/qcam/dng_writer.cpp +++ b/src/qcam/dng_writer.cpp @@ -392,7 +392,7 @@ int DNGWriter::write(const char *filename, const Camera *camera, TIFFSetField(tif, TIFFTAG_MAKE, "libcamera"); if (cameraProperties.contains(properties::Model)) { - std::string model = cameraProperties.get(properties::Model); + std::string model = cameraProperties.get(properties::Model).value_or(std::string{}); TIFFSetField(tif, TIFFTAG_MODEL, model.c_str()); /* \todo set TIFFTAG_UNIQUECAMERAMODEL. */ } @@ -438,7 +438,8 @@ int DNGWriter::write(const char *filename, const Camera *camera, const double eps = 1e-2; if (metadata.contains(controls::ColourGains)) { - Span const &colourGains = metadata.get(controls::ColourGains); + Span const &colourGains = + metadata.get(controls::ColourGains).value_or(libcamera::Span({ 0, 0 })); if (colourGains[0] > eps && colourGains[1] > eps) { wbGain = Matrix3d::diag(colourGains[0], 1, colourGains[1]); neutral[0] = 1.0 / colourGains[0]; /* red */ @@ -446,7 +447,8 @@ int DNGWriter::write(const char *filename, const Camera *camera, } } if (metadata.contains(controls::ColourCorrectionMatrix)) { - Span const &coeffs = metadata.get(controls::ColourCorrectionMatrix); + Span const &coeffs = + metadata.get(controls::ColourCorrectionMatrix).value_or(Span({ 0, 0, 0, 0, 0, 0, 0, 0, 0 })); Matrix3d ccmSupplied(coeffs); if (ccmSupplied.determinant() > eps) ccm = ccmSupplied; @@ -515,7 +517,8 @@ int DNGWriter::write(const char *filename, const Camera *camera, uint32_t whiteLevel = (1 << info->bitsPerSample) - 1; if (metadata.contains(controls::SensorBlackLevels)) { - Span levels = metadata.get(controls::SensorBlackLevels); + Span levels = + metadata.get(controls::SensorBlackLevels).value_or(Span({ 0, 0, 0, 0 })); /* * The black levels control is specified in R, Gr, Gb, B order. @@ -593,13 +596,13 @@ int DNGWriter::write(const char *filename, const Camera *camera, TIFFSetField(tif, EXIFTAG_DATETIMEDIGITIZED, strTime); if (metadata.contains(controls::AnalogueGain)) { - float gain = metadata.get(controls::AnalogueGain); + float gain = metadata.get(controls::AnalogueGain).value_or(float{}); uint16_t iso = std::min(std::max(gain * 100, 0.0f), 65535.0f); TIFFSetField(tif, EXIFTAG_ISOSPEEDRATINGS, 1, &iso); } if (metadata.contains(controls::ExposureTime)) { - float exposureTime = metadata.get(controls::ExposureTime) / 1e6; + float exposureTime = metadata.get(controls::ExposureTime).value_or(float{}) / 1e6; TIFFSetField(tif, EXIFTAG_EXPOSURETIME, exposureTime); }