From patchwork Thu Jan 19 10:45:39 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Naushir Patuck X-Patchwork-Id: 18158 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 F1CF7BD87C for ; Thu, 19 Jan 2023 10:46:06 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 933E46260C; Thu, 19 Jan 2023 11:46:06 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1674125166; bh=FwWs23/yLeIYaKR2QHxyiUmReWahysMWlCP0J/P5NkU=; 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=JRiZzGwXWv2qAbyc0tdeU5AFfQJLl1jTvJJzoDUz4y33mUu5SdxfQMQHxk1MIvnvu GQrSQifwM/JwJ30GsyuQiSOLAil0XAxQGce3MhKtQuLbj8KB6Rh/GX5P5B6gWpHVha tB3PbI4IsdbSKvdY99p57Cz6mxkhdN9sveMZHhll8lHihrDCoFUE8mDwIhsV0C1rs0 gHiyISunKLoxeuYUhiRBruZPrROkHFEnQIOZ/862SWLcZLbvTtGCzujwyca88C9hI+ qO2fNZmvr/NuH4883rKK+4fsEevWOH94V1ds1EOxTIDVJIH3Yq0VF8g5BYm6WhxKMk /McvCMzYAZzbw== Received: from mail-wm1-x32b.google.com (mail-wm1-x32b.google.com [IPv6:2a00:1450:4864:20::32b]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id D6F5A625E7 for ; Thu, 19 Jan 2023 11:45:58 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=raspberrypi.com header.i=@raspberrypi.com header.b="EEk9IlBz"; dkim-atps=neutral Received: by mail-wm1-x32b.google.com with SMTP id g10so1170170wmo.1 for ; Thu, 19 Jan 2023 02:45:58 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=raspberrypi.com; s=google; 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=4UYvcAZ8aQ9iDqO1x3vQcdFJHQPnJdXnBpdMdVUYWW4=; b=EEk9IlBzSrAUuynjqdmXZStL/VN1S9bS7jo05JFuvIPSJ28xZAH/ebq97EZZ7z1vtD 4lPy5EAhk5hj5bHFwjO4cybu4RcNG34hEQi7024Or3PqajRKaXAkGY80lu78Yuq4FVdk H5Aad89YRxj4Kg6Ga5JIQchsZnRNt4vfgfI+ckyUkIpLDqeBMZI7aauU+56M02ZLR6Ad Wm7ZSk12Gh2hcfMzy0ZHE/LMDEqrgNXxunZbBohMdCxORhD80q/7sdFBP9AdJdvfo9aa 6gZtcgKT1mPhUEfQh8Ibf66h3mVRsRj2cEqJTQPaTcpBFa5CNOv72J1cX/rnYPMyXQ2s 25Sw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; 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=4UYvcAZ8aQ9iDqO1x3vQcdFJHQPnJdXnBpdMdVUYWW4=; b=Lu4sJB0U0+9Dlxrn9f8YL2L94Gr9lnNCGyr5vFQ93kNFqHpCjjDgCu6j22fZCI8aLb u+KVp/sCj/0fzEI8x+YJGvdBReYbwwNjcLPTfYPx2RZ/xCC4r/nsYEMjGlLRqXP8SD49 ClDa8TvK6cUPL4PPHJdgUZTwmNvHeIDeVfxnVm71DsPPR8OQVIzkRO6D5d6AMd+XjbpE fYCre32Cov8Wj8bhzScUXDnEflzWPw2SRlwRyBt0bfeZK8+BfE0A424wmqfuIH8uBKN8 uf5nxlEvUu/3dJousL1KI5bmADd1wU1FV3NfmbIs+tYTDQP0mf2gVINY+wGda0MRFv2D 4vzA== X-Gm-Message-State: AFqh2koKKVihyP9DA0iTlbkUX+MaVu6p4eRqYoOUlJoni0ghSzs+pgdr IjRDRKC67dhAo4LOb74VCtam0mAospbM7rt6kyI= X-Google-Smtp-Source: AMrXdXs0IKF4BOO+aT3L9MXS0PXVEHNlFc2wI3oca5vX6vARKdwWnCrP7W+xJS/9THA9ou6yn9RVXA== X-Received: by 2002:a05:600c:539a:b0:3d9:ef72:190d with SMTP id hg26-20020a05600c539a00b003d9ef72190dmr9705986wmb.19.1674125158292; Thu, 19 Jan 2023 02:45:58 -0800 (PST) Received: from localhost.localdomain ([93.93.133.154]) by smtp.gmail.com with ESMTPSA id be12-20020a05600c1e8c00b003db06224953sm5332029wmb.41.2023.01.19.02.45.57 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 19 Jan 2023 02:45:57 -0800 (PST) To: libcamera-devel@lists.libcamera.org Date: Thu, 19 Jan 2023 10:45:39 +0000 Message-Id: <20230119104544.9456-10-naush@raspberrypi.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230119104544.9456-1-naush@raspberrypi.com> References: <20230119104544.9456-1-naush@raspberrypi.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v1 09/14] ipa: raspberrypi: Handle autofocus controls 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: Naushir Patuck via libcamera-devel From: Naushir Patuck Reply-To: Naushir Patuck Cc: Nick Hollinghurst Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" From: Nick Hollinghurst Add handlers for all autofocus related libcamera controls. Translate these controls to the RPiController autofocus algorithm API. Signed-off-by: Nick Hollinghurst Signed-off-by: Naushir Patuck Reviewed-by: Naushir Patuck Reviewed-by: David Plowman --- src/ipa/raspberrypi/raspberrypi.cpp | 144 ++++++++++++++++++++++++++++ 1 file changed, 144 insertions(+) diff --git a/src/ipa/raspberrypi/raspberrypi.cpp b/src/ipa/raspberrypi/raspberrypi.cpp index 745c16f354ce..0eb55ed605b6 100644 --- a/src/ipa/raspberrypi/raspberrypi.cpp +++ b/src/ipa/raspberrypi/raspberrypi.cpp @@ -31,6 +31,7 @@ #include "libcamera/internal/mapped_framebuffer.h" +#include "af_algorithm.h" #include "agc_algorithm.h" #include "agc_status.h" #include "alsc_status.h" @@ -732,11 +733,49 @@ static const std::map DenoiseModeTable = { { controls::draft::NoiseReductionModeZSL, RPiController::DenoiseMode::ColourHighQuality }, }; +static const std::map AfModeTable = { + { controls::AfModeManual, RPiController::AfAlgorithm::AfModeManual }, + { controls::AfModeAuto, RPiController::AfAlgorithm::AfModeAuto }, + { controls::AfModeContinuous, RPiController::AfAlgorithm::AfModeContinuous }, +}; + +static const std::map AfRangeTable = { + { controls::AfRangeNormal, RPiController::AfAlgorithm::AfRangeNormal }, + { controls::AfRangeMacro, RPiController::AfAlgorithm::AfRangeMacro }, + { controls::AfRangeFull, RPiController::AfAlgorithm::AfRangeFull }, +}; + +static const std::map AfPauseTable = { + { controls::AfPauseImmediate, RPiController::AfAlgorithm::AfPauseImmediate }, + { controls::AfPauseDeferred, RPiController::AfAlgorithm::AfPauseDeferred }, + { controls::AfPauseResume, RPiController::AfAlgorithm::AfPauseResume }, +}; + void IPARPi::queueRequest(const ControlList &controls) { + using RPiController::AfAlgorithm; + /* Clear the return metadata buffer. */ libcameraMetadata_.clear(); + /* Because some AF controls are mode-specific, handle AF mode change first. */ + if (controls.contains(controls::AF_MODE)) { + AfAlgorithm *af = dynamic_cast(controller_.getAlgorithm("af")); + if (!af) { + LOG(IPARPI, Warning) + << "Could not set AF_MODE - no AF algorithm"; + } + + int32_t idx = controls.get(controls::AF_MODE).get(); + auto mode = AfModeTable.find(idx); + if (mode == AfModeTable.end()) { + LOG(IPARPI, Error) << "AF mode " << idx + << " not recognised"; + } else + af->setMode(mode->second); + } + + /* Iterate over controls */ for (auto const &ctrl : controls) { LOG(IPARPI, Debug) << "Request ctrl: " << controls::controls.at(ctrl.first)->name() @@ -1028,6 +1067,111 @@ void IPARPi::queueRequest(const ControlList &controls) break; } + case controls::AF_MODE: + break; /* We already handled this one above */ + + case controls::AF_RANGE: { + AfAlgorithm *af = dynamic_cast(controller_.getAlgorithm("af")); + if (!af) { + LOG(IPARPI, Warning) + << "Could not set AF_RANGE - no focus algorithm"; + break; + } + + auto range = AfRangeTable.find(ctrl.second.get()); + if (range == AfRangeTable.end()) { + LOG(IPARPI, Error) << "AF range " << ctrl.second.get() + << " not recognised"; + break; + } + af->setRange(range->second); + break; + } + + case controls::AF_SPEED: { + AfAlgorithm *af = dynamic_cast(controller_.getAlgorithm("af")); + if (!af) { + LOG(IPARPI, Warning) + << "Could not set AF_SPEED - no focus algorithm"; + break; + } + + AfAlgorithm::AfSpeed speed = ctrl.second.get() == controls::AfSpeedFast ? + AfAlgorithm::AfSpeedFast : AfAlgorithm::AfSpeedNormal; + af->setSpeed(speed); + break; + } + + case controls::AF_METERING: { + AfAlgorithm *af = dynamic_cast(controller_.getAlgorithm("af")); + if (!af) { + LOG(IPARPI, Warning) + << "Could not set AF_METERING - no AF algorithm"; + break; + } + af->setMetering(ctrl.second.get() == controls::AfMeteringWindows); + break; + } + + case controls::AF_WINDOWS: { + AfAlgorithm *af = dynamic_cast(controller_.getAlgorithm("af")); + if (!af) { + LOG(IPARPI, Warning) + << "Could not set AF_WINDOWS - no AF algorithm"; + break; + } + af->setWindows(ctrl.second.get>()); + break; + } + + case controls::AF_PAUSE: { + AfAlgorithm *af = dynamic_cast(controller_.getAlgorithm("af")); + if (!af || af->getMode() != AfAlgorithm::AfModeContinuous) { + LOG(IPARPI, Warning) + << "Could not set AF_PAUSE - no AF algorithm or not Continuous"; + break; + } + auto pause = AfPauseTable.find(ctrl.second.get()); + if (pause == AfPauseTable.end()) { + LOG(IPARPI, Error) << "AF pause " << ctrl.second.get() + << " not recognised"; + break; + } + af->pause(pause->second); + break; + } + + case controls::AF_TRIGGER: { + AfAlgorithm *af = dynamic_cast(controller_.getAlgorithm("af")); + if (!af || af->getMode() != AfAlgorithm::AfModeAuto) { + LOG(IPARPI, Warning) + << "Could not set AF_TRIGGER - no AF algorithm or not Auto"; + break; + } else { + if (ctrl.second.get() == controls::AfTriggerStart) + af->triggerScan(); + else + af->cancelScan(); + } + break; + } + + case controls::LENS_POSITION: { + AfAlgorithm *af = dynamic_cast(controller_.getAlgorithm("af")); + if (af) { + int32_t hwpos; + if (af->setLensPosition(ctrl.second.get(), &hwpos)) { + ControlList lensCtrls(lensCtrls_); + lensCtrls.set(V4L2_CID_FOCUS_ABSOLUTE, hwpos); + setLensControls.emit(lensCtrls); + } + } else { + LOG(IPARPI, Warning) + << "Could not set LENS_POSITION - no AF algorithm"; + } + break; + } + default: LOG(IPARPI, Warning) << "Ctrl " << controls::controls.at(ctrl.first)->name()