From patchwork Thu Jun 18 11:12:35 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Plowman X-Patchwork-Id: 4076 Return-Path: Received: from mail-wr1-x435.google.com (mail-wr1-x435.google.com [IPv6:2a00:1450:4864:20::435]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 6C2A5603C1 for ; Thu, 18 Jun 2020 13:12:56 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=raspberrypi.com header.i=@raspberrypi.com header.b="LlJiOYdC"; dkim-atps=neutral Received: by mail-wr1-x435.google.com with SMTP id t18so5621847wru.6 for ; Thu, 18 Jun 2020 04:12:56 -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=5qE8hU/GIenZXSbgyE45a/3aThYh0QnODP/DovYVTmA=; b=LlJiOYdCyp74Ynjm9v4CJKPxtGK6UqLcdmb426vWzRMuD2qgntWVojPGYbyPBmf5Lf FtTOXm79QOgrzoV9R2U2TjGzgVikipyluLVzKdUPxFs6zhLZV+dMBin9t+oTebZWxyYX EkJRR5qhEQDygVh3+/CSwiOpEHPgOaZFsQ7AcU+tUw3sx3+Uc4Cz6Cs85xZtQhkwrx+C SbXG7PgTXWL8/iiNcFdEXthkxmXjq+dj/4y2IQ12ZmNxdxorYw+yiMEPLB5HVtk3wAIS Zie0RnkilyP869Ax84kKc5wCCL6iuZ11N4cfiX4Pzi7kJPgTbS5T9XatyxvX6eBnVw9V 4VVw== 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=5qE8hU/GIenZXSbgyE45a/3aThYh0QnODP/DovYVTmA=; b=t9LLodHznAPuibTw7OBOr6WeNVpNvgcgOR67/Mztb+mz0Twa/Olw3jOFTj0HQUrHOr lxs+sJSiVJM9oRBH3yCP0bU1YVIrcOiuCWfMtWWdt2K3+Cgu7zbIDzJvJKiYzgEURLhd AfNA1nHyoVDLPAR/Cw7RezzEZPWQN/3ngU5Oc4y9QBK2/BIDUqp2e9JA2UmS40vONMAb jd6PE5dWlfFj7cp07kqnjESWHskAl8TLi/6TVhLxt0dFSLT5XfedMvp8Gp0YjIrPd0hg y7k3hOyRazPZtBUpXVqjy3BIN9fAJuj81s0prt5qml2C7CSfMUyvLt5+oCIvoy7cbplN qvWw== X-Gm-Message-State: AOAM533iRGZ0F/HoVfzBoFsHb8yTfSEHpNyn0vKSR5wMUkceqs0lqexS pPqRzdCvHMnAFg/gj5b3jxSVs07a2nc= X-Google-Smtp-Source: ABdhPJwOy2+jh1Kr6r05P74tP02ns6cltgWBYT3iG1Fp2Cgg4KvhfO390b4FuId9JCbHl18rcgVHBA== X-Received: by 2002:adf:e84e:: with SMTP id d14mr3943789wrn.31.1592478775129; Thu, 18 Jun 2020 04:12:55 -0700 (PDT) Received: from pi4-davidp.lan (plowpeople3.plus.com. [80.229.223.72]) by smtp.gmail.com with ESMTPSA id e10sm3103857wrn.11.2020.06.18.04.12.53 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 18 Jun 2020 04:12:54 -0700 (PDT) From: David Plowman To: libcamera-devel@lists.libcamera.org Date: Thu, 18 Jun 2020 12:12:35 +0100 Message-Id: <20200618111236.26897-2-david.plowman@raspberrypi.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200618111236.26897-1-david.plowman@raspberrypi.com> References: <20200618111236.26897-1-david.plowman@raspberrypi.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 1/2] libcamera: raspberrypi: allow SwitchMode method to return camera settings 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-List-Received-Date: Thu, 18 Jun 2020 11:12:56 -0000 This commit adds a Metadata parameter to the SwitchMode method enabling it to return camera and other settings to the caller (usually the configure method, just after the camera mode has been selected). In future this will allow the Raspberry Pi IPAs to take those settings (such as exposure and analogue gain) and program them directly into the camera or ISP before the camera is even started. Signed-off-by: David Plowman Reviewed-by: Laurent Pinchart --- src/ipa/raspberrypi/controller/algorithm.cpp | 3 ++- src/ipa/raspberrypi/controller/algorithm.hpp | 2 +- src/ipa/raspberrypi/controller/controller.cpp | 4 ++-- src/ipa/raspberrypi/controller/controller.hpp | 2 +- src/ipa/raspberrypi/controller/rpi/alsc.cpp | 4 +++- src/ipa/raspberrypi/controller/rpi/alsc.hpp | 2 +- src/ipa/raspberrypi/controller/rpi/noise.cpp | 4 +++- src/ipa/raspberrypi/controller/rpi/noise.hpp | 2 +- src/ipa/raspberrypi/controller/rpi/sharpen.cpp | 4 +++- src/ipa/raspberrypi/controller/rpi/sharpen.hpp | 2 +- src/ipa/raspberrypi/raspberrypi.cpp | 3 ++- 11 files changed, 20 insertions(+), 12 deletions(-) diff --git a/src/ipa/raspberrypi/controller/algorithm.cpp b/src/ipa/raspberrypi/controller/algorithm.cpp index 9bd3df8..55cb201 100644 --- a/src/ipa/raspberrypi/controller/algorithm.cpp +++ b/src/ipa/raspberrypi/controller/algorithm.cpp @@ -16,9 +16,10 @@ void Algorithm::Read(boost::property_tree::ptree const ¶ms) void Algorithm::Initialise() {} -void Algorithm::SwitchMode(CameraMode const &camera_mode) +void Algorithm::SwitchMode(CameraMode const &camera_mode, Metadata *metadata) { (void)camera_mode; + (void)metadata; } void Algorithm::Prepare(Metadata *image_metadata) diff --git a/src/ipa/raspberrypi/controller/algorithm.hpp b/src/ipa/raspberrypi/controller/algorithm.hpp index b82c184..187c50c 100644 --- a/src/ipa/raspberrypi/controller/algorithm.hpp +++ b/src/ipa/raspberrypi/controller/algorithm.hpp @@ -37,7 +37,7 @@ public: virtual void Resume() { paused_ = false; } virtual void Read(boost::property_tree::ptree const ¶ms); virtual void Initialise(); - virtual void SwitchMode(CameraMode const &camera_mode); + virtual void SwitchMode(CameraMode const &camera_mode, Metadata *metadata); virtual void Prepare(Metadata *image_metadata); virtual void Process(StatisticsPtr &stats, Metadata *image_metadata); Metadata &GetGlobalMetadata() const diff --git a/src/ipa/raspberrypi/controller/controller.cpp b/src/ipa/raspberrypi/controller/controller.cpp index 20dd4c7..7c4b04f 100644 --- a/src/ipa/raspberrypi/controller/controller.cpp +++ b/src/ipa/raspberrypi/controller/controller.cpp @@ -56,11 +56,11 @@ void Controller::Initialise() RPI_LOG("Controller finished"); } -void Controller::SwitchMode(CameraMode const &camera_mode) +void Controller::SwitchMode(CameraMode const &camera_mode, Metadata *metadata) { RPI_LOG("Controller starting"); for (auto &algo : algorithms_) - algo->SwitchMode(camera_mode); + algo->SwitchMode(camera_mode, metadata); switch_mode_called_ = true; RPI_LOG("Controller finished"); } diff --git a/src/ipa/raspberrypi/controller/controller.hpp b/src/ipa/raspberrypi/controller/controller.hpp index d685386..6ba9412 100644 --- a/src/ipa/raspberrypi/controller/controller.hpp +++ b/src/ipa/raspberrypi/controller/controller.hpp @@ -39,7 +39,7 @@ public: Algorithm *CreateAlgorithm(char const *name); void Read(char const *filename); void Initialise(); - void SwitchMode(CameraMode const &camera_mode); + void SwitchMode(CameraMode const &camera_mode, Metadata *metadata); void Prepare(Metadata *image_metadata); void Process(StatisticsPtr stats, Metadata *image_metadata); Metadata &GetGlobalMetadata(); diff --git a/src/ipa/raspberrypi/controller/rpi/alsc.cpp b/src/ipa/raspberrypi/controller/rpi/alsc.cpp index 821a0ca..76e2f04 100644 --- a/src/ipa/raspberrypi/controller/rpi/alsc.cpp +++ b/src/ipa/raspberrypi/controller/rpi/alsc.cpp @@ -173,8 +173,10 @@ void Alsc::Initialise() lambda_r_[i] = lambda_b_[i] = 1.0; } -void Alsc::SwitchMode(CameraMode const &camera_mode) +void Alsc::SwitchMode(CameraMode const &camera_mode, Metadata *metadata) { + (void)metadata; + // There's a bit of a question what we should do if the "crop" of the // camera mode has changed. Any calculation currently in flight would // not be useful to the new mode, so arguably we should abort it, and diff --git a/src/ipa/raspberrypi/controller/rpi/alsc.hpp b/src/ipa/raspberrypi/controller/rpi/alsc.hpp index c8ed3d2..3806257 100644 --- a/src/ipa/raspberrypi/controller/rpi/alsc.hpp +++ b/src/ipa/raspberrypi/controller/rpi/alsc.hpp @@ -50,7 +50,7 @@ public: ~Alsc(); char const *Name() const override; void Initialise() override; - void SwitchMode(CameraMode const &camera_mode) override; + void SwitchMode(CameraMode const &camera_mode, Metadata *metadata) override; void Read(boost::property_tree::ptree const ¶ms) override; void Prepare(Metadata *image_metadata) override; void Process(StatisticsPtr &stats, Metadata *image_metadata) override; diff --git a/src/ipa/raspberrypi/controller/rpi/noise.cpp b/src/ipa/raspberrypi/controller/rpi/noise.cpp index 2209d79..2cafde3 100644 --- a/src/ipa/raspberrypi/controller/rpi/noise.cpp +++ b/src/ipa/raspberrypi/controller/rpi/noise.cpp @@ -27,8 +27,10 @@ char const *Noise::Name() const return NAME; } -void Noise::SwitchMode(CameraMode const &camera_mode) +void Noise::SwitchMode(CameraMode const &camera_mode, Metadata *metadata) { + (void)metadata; + // For example, we would expect a 2x2 binned mode to have a "noise // factor" of sqrt(2x2) = 2. (can't be less than one, right?) mode_factor_ = std::max(1.0, camera_mode.noise_factor); diff --git a/src/ipa/raspberrypi/controller/rpi/noise.hpp b/src/ipa/raspberrypi/controller/rpi/noise.hpp index 51d46a3..25bf188 100644 --- a/src/ipa/raspberrypi/controller/rpi/noise.hpp +++ b/src/ipa/raspberrypi/controller/rpi/noise.hpp @@ -18,7 +18,7 @@ class Noise : public Algorithm public: Noise(Controller *controller); char const *Name() const override; - void SwitchMode(CameraMode const &camera_mode) override; + void SwitchMode(CameraMode const &camera_mode, Metadata *metadata) override; void Read(boost::property_tree::ptree const ¶ms) override; void Prepare(Metadata *image_metadata) override; diff --git a/src/ipa/raspberrypi/controller/rpi/sharpen.cpp b/src/ipa/raspberrypi/controller/rpi/sharpen.cpp index 1f07bb6..086952f 100644 --- a/src/ipa/raspberrypi/controller/rpi/sharpen.cpp +++ b/src/ipa/raspberrypi/controller/rpi/sharpen.cpp @@ -26,8 +26,10 @@ char const *Sharpen::Name() const return NAME; } -void Sharpen::SwitchMode(CameraMode const &camera_mode) +void Sharpen::SwitchMode(CameraMode const &camera_mode, Metadata *metadata) { + (void)metadata; + // can't be less than one, right? mode_factor_ = std::max(1.0, camera_mode.noise_factor); } diff --git a/src/ipa/raspberrypi/controller/rpi/sharpen.hpp b/src/ipa/raspberrypi/controller/rpi/sharpen.hpp index 3b0d680..f871aa6 100644 --- a/src/ipa/raspberrypi/controller/rpi/sharpen.hpp +++ b/src/ipa/raspberrypi/controller/rpi/sharpen.hpp @@ -18,7 +18,7 @@ class Sharpen : public Algorithm public: Sharpen(Controller *controller); char const *Name() const override; - void SwitchMode(CameraMode const &camera_mode) override; + void SwitchMode(CameraMode const &camera_mode, Metadata *metadata) override; void Read(boost::property_tree::ptree const ¶ms) override; void Prepare(Metadata *image_metadata) override; diff --git a/src/ipa/raspberrypi/raspberrypi.cpp b/src/ipa/raspberrypi/raspberrypi.cpp index 9669f21..d6fd3df 100644 --- a/src/ipa/raspberrypi/raspberrypi.cpp +++ b/src/ipa/raspberrypi/raspberrypi.cpp @@ -267,7 +267,8 @@ void IPARPi::configure(const CameraSensorInfo &sensorInfo, queueFrameAction.emit(0, op); } - controller_.SwitchMode(mode_); + RPi::Metadata metadata; + controller_.SwitchMode(mode_, &metadata); lastMode_ = mode_; } From patchwork Thu Jun 18 11:12:36 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Plowman X-Patchwork-Id: 4077 Return-Path: Received: from mail-wm1-x330.google.com (mail-wm1-x330.google.com [IPv6:2a00:1450:4864:20::330]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 79C23607DE for ; Thu, 18 Jun 2020 13:12:58 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=raspberrypi.com header.i=@raspberrypi.com header.b="a0N/zIlq"; dkim-atps=neutral Received: by mail-wm1-x330.google.com with SMTP id a6so1398857wmm.5 for ; Thu, 18 Jun 2020 04:12:58 -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=vfF7umJN63KhWa9zfa1zff+dqwZNZIkIJp+wbjDa9aQ=; b=a0N/zIlq8SU9F94epC1dSJlaZCO26PxB+SnFuuLvn5sMEzzt5XjxvtVbZbMs6LE1s7 ca7dctV9/Ef3mlIbqnbI15QoWbIYN+JxVNRbB/QQspGXqjiS+aGbKplEYF83CxxyQ3M4 OUspoFyHgVEA4h7Ngi3bwubcmRP9WJOvKfIC8hXMa9EUi6D5WdPXDIe8jCpfx9t4tLKE dAMvJpQKOTBtXMKS/dVr8hVrmLXuE3TnaoGP0G69JiFQUbIcFcptEV5ZkZ7XjtwBC90u VgGB/No6D5BqGwkiUIeQdRUzIzs9E3UWh4ASJN30NcL4r5yd4HScu/NzILTV/VRpEbze 3SOA== 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=vfF7umJN63KhWa9zfa1zff+dqwZNZIkIJp+wbjDa9aQ=; b=DgOibxUNrCOkzAesYnhX5zOscDvilVQjg5m0yxVcuQDQkokyZ6/03jjrToSB+a+wXf B5jpOBX++n05jJ0JoLPuSS5ksZzUHVz4CFtscWXrWSy0UEEhrcruN8+NPS5eTvsmJCIP uEwLcvrM5OTOYCrWdanoqP64m01yx/NePXTQvVEfATy8roBhX56KHHr2Aa7BlsdrE0Hr NGUZFCxE69fizuU2g2UM8d7UtH3DKxFHkNzd6baWnSHLOvyRH6BecVFkDZv1XXBg/wQS yjDRy9opo6NlYVd60ibgEUMXKcmNlpfjnJmiucfvWYBto/z5ne1gcT2J7nGYV6babnnP Ui8g== X-Gm-Message-State: AOAM533qZ73ucZdEu/swQvhIEr99sQNF44BEBJgdecLAjvWSaL9yiT42 JCmvqoOeqsnC7j5gNcJabYUxmHhIHww= X-Google-Smtp-Source: ABdhPJx5infg9dfKJ+Z0qgkgNjcJcDE+/68UupVCwBUeTDgWB5FJ0bp9q3mBlRWtOmjKMMJFWPyJFA== X-Received: by 2002:a1c:9687:: with SMTP id y129mr3495953wmd.30.1592478777423; Thu, 18 Jun 2020 04:12:57 -0700 (PDT) Received: from pi4-davidp.lan (plowpeople3.plus.com. [80.229.223.72]) by smtp.gmail.com with ESMTPSA id e10sm3103857wrn.11.2020.06.18.04.12.56 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 18 Jun 2020 04:12:56 -0700 (PDT) From: David Plowman To: libcamera-devel@lists.libcamera.org Date: Thu, 18 Jun 2020 12:12:36 +0100 Message-Id: <20200618111236.26897-3-david.plowman@raspberrypi.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200618111236.26897-1-david.plowman@raspberrypi.com> References: <20200618111236.26897-1-david.plowman@raspberrypi.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 2/2] libcamera: raspberrypi: recalculate camera exposure/gain when camera mode changes 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-List-Received-Date: Thu, 18 Jun 2020 11:12:58 -0000 This commit causes the AGC to recalculate its camera exposure/gain values when the camera mode changes. For example it's possible that the exposure profile could be changed by the application so the division between exposure time and analogue gain may be different. The other underlying reason (and which this commit accomplishes too) is that the sensor's line timing may change in a new mode, and because V4L2 drivers store a number of exposure _lines_, the resulting _time_ will "change under our feet". So we have to go through the process of recalculating the correct number of lines and writing this back to the sensor with every mode switch, regardless of anything else. Signed-off-by: David Plowman Reviewed-by: Laurent Pinchart --- src/ipa/raspberrypi/controller/rpi/agc.cpp | 12 +++++++++++ src/ipa/raspberrypi/controller/rpi/agc.hpp | 1 + src/ipa/raspberrypi/raspberrypi.cpp | 25 +++++++++++----------- 3 files changed, 26 insertions(+), 12 deletions(-) diff --git a/src/ipa/raspberrypi/controller/rpi/agc.cpp b/src/ipa/raspberrypi/controller/rpi/agc.cpp index a474287..c02b5ec 100644 --- a/src/ipa/raspberrypi/controller/rpi/agc.cpp +++ b/src/ipa/raspberrypi/controller/rpi/agc.cpp @@ -221,6 +221,18 @@ void Agc::SetConstraintMode(std::string const &constraint_mode_name) constraint_mode_name_ = constraint_mode_name; } +void Agc::SwitchMode(CameraMode const &camera_mode, Metadata *metadata) +{ + // On a mode switch, it's possible the exposure profile could change, + // so we run through the dividing up of exposure/gain again and + // write the results into the metadata we've been given. + if (status_.total_exposure_value) { + housekeepConfig(); + divvyupExposure(); + writeAndFinish(metadata, false); + } +} + void Agc::Prepare(Metadata *image_metadata) { AgcStatus status; diff --git a/src/ipa/raspberrypi/controller/rpi/agc.hpp b/src/ipa/raspberrypi/controller/rpi/agc.hpp index dbcefba..9a7e89c 100644 --- a/src/ipa/raspberrypi/controller/rpi/agc.hpp +++ b/src/ipa/raspberrypi/controller/rpi/agc.hpp @@ -75,6 +75,7 @@ public: void SetMeteringMode(std::string const &metering_mode_name) override; void SetExposureMode(std::string const &exposure_mode_name) override; void SetConstraintMode(std::string const &contraint_mode_name) override; + void SwitchMode(CameraMode const &camera_mode, Metadata *metadata) override; void Prepare(Metadata *image_metadata) override; void Process(StatisticsPtr &stats, Metadata *image_metadata) override; diff --git a/src/ipa/raspberrypi/raspberrypi.cpp b/src/ipa/raspberrypi/raspberrypi.cpp index d6fd3df..42c84b1 100644 --- a/src/ipa/raspberrypi/raspberrypi.cpp +++ b/src/ipa/raspberrypi/raspberrypi.cpp @@ -247,29 +247,30 @@ void IPARPi::configure(const CameraSensorInfo &sensorInfo, mistrust_count_ = helper_->MistrustFramesStartup(); } + struct AgcStatus agcStatus; + /* These zero values mean not program anything (unless overwritten). */ + agcStatus.shutter_time = 0.0; + agcStatus.analogue_gain = 0.0; + if (!controllerInit_) { /* Load the tuning file for this sensor. */ controller_.Read(tuningFile_.c_str()); controller_.Initialise(); controllerInit_ = true; - /* Calculate initial values for gain and exposure. */ - int32_t gain_code = helper_->GainCode(DEFAULT_ANALOGUE_GAIN); - int32_t exposure_lines = helper_->ExposureLines(DEFAULT_EXPOSURE_TIME); - - ControlList ctrls(unicam_ctrls_); - ctrls.set(V4L2_CID_ANALOGUE_GAIN, gain_code); - ctrls.set(V4L2_CID_EXPOSURE, exposure_lines); - - IPAOperationData op; - op.operation = RPI_IPA_ACTION_V4L2_SET_STAGGERED; - op.controls.push_back(ctrls); - queueFrameAction.emit(0, op); + /* Supply initial values for gain and exposure. */ + agcStatus.shutter_time = DEFAULT_EXPOSURE_TIME; + agcStatus.analogue_gain = DEFAULT_ANALOGUE_GAIN; } RPi::Metadata metadata; controller_.SwitchMode(mode_, &metadata); + /* SwitchMode may supply updated exposure/gain values to use. */ + metadata.Get("agc.status", agcStatus); + if (agcStatus.shutter_time != 0.0 && agcStatus.analogue_gain != 0.0) + applyAGC(&agcStatus); + lastMode_ = mode_; }