From patchwork Fri Mar 24 14:29:04 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Daniel Semkowicz X-Patchwork-Id: 18449 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 A7F49C329E for ; Fri, 24 Mar 2023 14:29:36 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 020E762717; Fri, 24 Mar 2023 15:29:35 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1679668176; bh=lWQp7FDFUsf+brUcDAs21WmvGm8oBGyyT7hhIY12fkc=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc: From; b=qq4pWW0NhR3d4mVq3KPK6Fj1/T1LBxeBv/gMJ+y5L0ZTmMvXbH2gW326XbZn7X/Il 1oak6MEjdlpGAu5Y3PI8/czt39Vk3ufpkfgiGHdyL41sHWbnmfBMdGcocZpWzhckDp DhyG2V7w9xrPCQYlYozyEmlreRmhqkTSJ86PA7p5C4kpzVzL4HPAZmqpQaFlBRLMns ZUWCbbIlhrh8z94Kenl5P03ga5JrcLhXuXbwk3T/Klhi4sJlc9M4uRjkRbfqDT6MtS S3crarkIaZFWP2Oo/76zrxHWz2MxGjlgioGAXYPmuOGhuoBNRAwIBTz448voU6RNDf Oj5dMwzkC5qjg== Received: from mail-lj1-x230.google.com (mail-lj1-x230.google.com [IPv6:2a00:1450:4864:20::230]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 460A36270F for ; Fri, 24 Mar 2023 15:29:28 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=thaumatec-com.20210112.gappssmtp.com header.i=@thaumatec-com.20210112.gappssmtp.com header.b="q2AMk/Pi"; dkim-atps=neutral Received: by mail-lj1-x230.google.com with SMTP id t14so1917993ljd.5 for ; Fri, 24 Mar 2023 07:29:28 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=thaumatec-com.20210112.gappssmtp.com; s=20210112; t=1679668167; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=jYWPwpLuVPnMkUQZsWBwirOzn6cygNfvhONXpwEd+Tk=; b=q2AMk/PiBhmlS702p6xLBs+qohqhwWcVsdPBn+tR3YVQGVrdD5Myl72fnmmdc9/71I AHN6oKaODa+l6zfQj6jh8EeCMWzbpnslYxivBcxbe/ARUqkbkOUJNX9cJsRgtBkWHcxG ANfZif8GOhaIP+tVCDIUhcov1Zsrtd28mAWm3LQyKaECI5vbpt2BL3450TMZBmniQhh7 fYrAaqMBL9MJUu0XeP24yBG/Q3E5pPTGMECQLfiOfrVV9ixbFZDi0+i0UU3Vs1MNUCI/ Z7CqIwAsnQA0P9IDyQSzqjNnCDbNk5+pPgaU0ymqkzbeUgKehLiL8IxOO86jNMNAwNVO xw6w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1679668167; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=jYWPwpLuVPnMkUQZsWBwirOzn6cygNfvhONXpwEd+Tk=; b=cZ6jgDRCOZIV35yPmdrJHhIRbUaCiO5r5vMpsfhvywJwVuC+NG1fiYyUxaF9pq4s8U geqYw6UyjuupO9WlqTdG0hTWEpRKR7LQZnejdubeQzAVOgR3rNW/6sbANC+zxoxzJ3MT KIhszX6TIhkcMxVT9ca3fH8Uvl1dpbwOnEHysd3/Y5/E5+eQZYFivSoTJNrwm7BsrfHk OfCknWrOmxpAi57B/bJZG2WA1DiZ/s1LlGe8bPHNxWx1v17rZPu5VpdpK7VlK6UvXT6+ FJmi2Ehjj1+6CnokL7ppHIrFGpqxvbMEKMGjxkM4AI198fa9xeC1Yt5t04MbyQru5YjQ P1sw== X-Gm-Message-State: AAQBX9f+nT0/RTMfzRs/H5rylD7KQCkjggdoPDUNKcTSb69LCHFY1OCQ xI63kxE/Y9RvsjbGy9E+8pFG4SFXJfVNEgv4H5A= X-Google-Smtp-Source: AKy350a4gFQN4gDFxZhZPNkEPdHmS3tjxp6wMlLA/feCkrPaGp+uKyA2Pi/Ewo/1SN+r2pMUZ4/MUg== X-Received: by 2002:a2e:97c1:0:b0:29e:e7ad:c8e1 with SMTP id m1-20020a2e97c1000000b0029ee7adc8e1mr1026041ljj.28.1679668167380; Fri, 24 Mar 2023 07:29:27 -0700 (PDT) Received: from localhost.localdomain ([91.90.166.178]) by smtp.gmail.com with ESMTPSA id j21-20020a2e8515000000b002a10b2ea089sm981714lji.16.2023.03.24.07.29.26 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 24 Mar 2023 07:29:27 -0700 (PDT) To: libcamera-devel@lists.libcamera.org Date: Fri, 24 Mar 2023 15:29:04 +0100 Message-Id: <20230324142908.64224-7-dse@thaumatec.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20230324142908.64224-1-dse@thaumatec.com> References: <20230324142908.64224-1-dse@thaumatec.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v5 06/10] ipa: rkisp1: Add AF algorithm based on AfHillClimbing 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: Daniel Semkowicz via libcamera-devel From: Daniel Semkowicz Reply-To: Daniel Semkowicz Cc: jacopo.mondi@ideasonboard.com Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Add contrast based auto focus implementation for rkisp1 platform using the common AfHillClimbing algorithm. Rockchip ISP AF block allows calculation of sharpness and luminance in up to three user defined windows. If no windows are set, there are some default settings applied for the first window and exposed through the driver. For each frame, use the sharpness value calculated for this default window and feed the hill climbing algorithm with them. Then set the lens position to value calculated by the algorithm. Signed-off-by: Daniel Semkowicz Reviewed-by: Jacopo Mondi --- src/ipa/rkisp1/algorithms/af.cpp | 117 ++++++++++++++++++++++++++ src/ipa/rkisp1/algorithms/af.h | 43 ++++++++++ src/ipa/rkisp1/algorithms/meson.build | 1 + src/ipa/rkisp1/ipa_context.cpp | 13 +++ src/ipa/rkisp1/ipa_context.h | 5 ++ 5 files changed, 179 insertions(+) create mode 100644 src/ipa/rkisp1/algorithms/af.cpp create mode 100644 src/ipa/rkisp1/algorithms/af.h diff --git a/src/ipa/rkisp1/algorithms/af.cpp b/src/ipa/rkisp1/algorithms/af.cpp new file mode 100644 index 00000000..aca127d2 --- /dev/null +++ b/src/ipa/rkisp1/algorithms/af.cpp @@ -0,0 +1,117 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2023, Theobroma Systems + * + * af.cpp - RkISP1 AF hill climbing based control algorithm + */ + +#include "af.h" + +/** + * \file af.h + */ + +namespace libcamera { + +namespace ipa::rkisp1::algorithms { + +/** + * \class Af + * \brief AF contrast based hill climbing control algorithm for RkISP platforms + * + * Auto focus algorithm for RkISP platforms, based on the common hill climbing + * auto focus implementation + * (libcamera::ipa::algorithms::AfHillClimbing). + * + * This is the platform layer of the algorithm. + * + * Tuning file parameters: + * - **wait-frames-lens:** Number of frames that should be skipped when lens + * position is changed. Lens movement takes some time and statistics measured + * during the lens movement are unstable. Currently there is no way to know + * when lens movement finished and this is a workaround for this. Wait a fixed + * amount of time on each movement. This parameter should be set according + * to the worst case - the number of frames it takes to move lens between + * limit positions. + * . + * \sa libcamera::ipa::algorithms::AfHillClimbing for additional tuning + * parameters. + * + * \todo Model the lens delay as number of frames required for the lens position + * to stabilize in the CameraLens class. + */ + +LOG_DEFINE_CATEGORY(RkISP1Af) + +/** + * \copydoc libcamera::ipa::Algorithm::init + */ +int Af::init([[maybe_unused]] IPAContext &context, const YamlObject &tuningData) +{ + waitFramesLens_ = tuningData["wait-frames-lens"].get(1); + + LOG(RkISP1Af, Debug) << "waitFramesLens_: " << waitFramesLens_; + + return af.init(tuningData); +} + +/** + * \copydoc libcamera::ipa::Algorithm::configure + */ +int Af::configure(IPAContext &context, const IPACameraSensorInfo &configInfo) +{ + const auto &lensConfig = context.configuration.lens; + + af.configure(lensConfig.minFocusPosition, lensConfig.maxFocusPosition, + configInfo.outputSize); + + /* + * Lens position is unknown at the startup, so initialize + * the current position to something out of range. + */ + context.activeState.af.lensPosition = lensConfig.maxFocusPosition + 1; + + return 0; +} + +/** + * \copydoc libcamera::ipa::Algorithm::queueRequest + */ +void Af::queueRequest([[maybe_unused]] IPAContext &context, + [[maybe_unused]] const uint32_t frame, + [[maybe_unused]] IPAFrameContext &frameContext, + const ControlList &controls) +{ + af.queueRequest(controls); +} + +/** + * \copydoc libcamera::ipa::Algorithm::process + */ +void Af::process(IPAContext &context, [[maybe_unused]] const uint32_t frame, + [[maybe_unused]] IPAFrameContext &frameContext, + const rkisp1_stat_buffer *stats, + [[maybe_unused]] ControlList &metadata) +{ + uint32_t sharpness = stats->params.af.window[0].sum; + uint32_t luminance = stats->params.af.window[0].lum; + + LOG(RkISP1Af, Debug) + << "lensPosition: " << context.activeState.af.lensPosition + << ", Sharpness: " << sharpness + << ", Luminance: " << luminance; + + int32_t newLensPosition = af.process(sharpness); + + if (newLensPosition != context.activeState.af.lensPosition) { + context.activeState.af.lensPosition = newLensPosition; + context.activeState.af.applyLensCtrls = true; + af.setFramesToSkip(waitFramesLens_); + } +} + +REGISTER_IPA_ALGORITHM(Af, "Af") + +} /* namespace ipa::rkisp1::algorithms */ + +} /* namespace libcamera */ diff --git a/src/ipa/rkisp1/algorithms/af.h b/src/ipa/rkisp1/algorithms/af.h new file mode 100644 index 00000000..3ba66d38 --- /dev/null +++ b/src/ipa/rkisp1/algorithms/af.h @@ -0,0 +1,43 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2023, Theobroma Systems + * + * af.h - RkISP1 AF hill climbing based control algorithm + */ + +#pragma once + +#include + +#include "libipa/algorithms/af_hill_climbing.h" + +#include "algorithm.h" + +namespace libcamera { + +namespace ipa::rkisp1::algorithms { + +class Af : public Algorithm +{ +public: + int init(IPAContext &context, const YamlObject &tuningData) override; + int configure(IPAContext &context, + const IPACameraSensorInfo &configInfo) override; + void queueRequest(IPAContext &context, uint32_t frame, + IPAFrameContext &frameContext, + const ControlList &controls) override; + void process(IPAContext &context, uint32_t frame, + IPAFrameContext &frameContext, + const rkisp1_stat_buffer *stats, + ControlList &metadata) override; + +private: + ipa::algorithms::AfHillClimbing af; + + /* Wait number of frames after changing lens position */ + uint32_t waitFramesLens_ = 0; +}; + +} /* namespace ipa::rkisp1::algorithms */ + +} /* namespace libcamera */ diff --git a/src/ipa/rkisp1/algorithms/meson.build b/src/ipa/rkisp1/algorithms/meson.build index 93a48329..ab7e44f3 100644 --- a/src/ipa/rkisp1/algorithms/meson.build +++ b/src/ipa/rkisp1/algorithms/meson.build @@ -1,6 +1,7 @@ # SPDX-License-Identifier: CC0-1.0 rkisp1_ipa_algorithms = files([ + 'af.cpp', 'agc.cpp', 'awb.cpp', 'blc.cpp', diff --git a/src/ipa/rkisp1/ipa_context.cpp b/src/ipa/rkisp1/ipa_context.cpp index 401c098f..5c5f80c7 100644 --- a/src/ipa/rkisp1/ipa_context.cpp +++ b/src/ipa/rkisp1/ipa_context.cpp @@ -134,6 +134,19 @@ namespace libcamera::ipa::rkisp1 { * member may be read by any algorithm, but shall only be written by its owner. */ +/** + * \var IPAActiveState::af + * \brief State for the Automatic Focus Control algorithm + * + * \var IPAActiveState::af.lensPosition + * \brief Lens position calculated by the AF algorithm + * + * \var IPAActiveState::af.applyLensCtrls + * \brief Whether the lens position should be applied + * + * If true, IPA should send new controls to the PH to set new lens position. + */ + /** * \var IPAActiveState::agc * \brief State for the Automatic Gain Control algorithm diff --git a/src/ipa/rkisp1/ipa_context.h b/src/ipa/rkisp1/ipa_context.h index bfb6e1b7..2c2eec3b 100644 --- a/src/ipa/rkisp1/ipa_context.h +++ b/src/ipa/rkisp1/ipa_context.h @@ -58,6 +58,11 @@ struct IPASessionConfiguration { }; struct IPAActiveState { + struct { + int32_t lensPosition; + bool applyLensCtrls; + } af; + struct { struct { uint32_t exposure;