From patchwork Mon Jan 23 15:49:29 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Naushir Patuck X-Patchwork-Id: 18184 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 72824C3240 for ; Mon, 23 Jan 2023 15:50:00 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 2281662601; Mon, 23 Jan 2023 16:50:00 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1674489000; 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=qI8FKaV02xEtyCMS9pb+ulaBolQ0uD2LH4073sApV+T7v7YvICErplEqzXaE7kALF /LYTvQ/JztlRD2EcmM+uZMWSpgMwHB5qRY3DEiodAVg+MsbAHDzRdTCXCk6MljKzNv gpNR3FR7FH8GW400rXkddGJSrox7s+qeulC1HI1Un7Zolwxx82GUGz0DjdlmfLXeXu p1JHhEdOyOj8P/3aXo0tqIqmGjx9GdlLCrgRfSE0QVhiJwd3LNsi2azE0rEGD7kZQx Cz5+Qthsd0rpSfjuUbn/1ZYukx10BQ/QRGB8eSAneVlNsFOHFIUN63GeAYg35uPAj9 XAbIDeTjApArQ== Received: from mail-wm1-x331.google.com (mail-wm1-x331.google.com [IPv6:2a00:1450:4864:20::331]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id EF2D4625E7 for ; Mon, 23 Jan 2023 16:49:53 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=raspberrypi.com header.i=@raspberrypi.com header.b="RcuLwLea"; dkim-atps=neutral Received: by mail-wm1-x331.google.com with SMTP id q8so9356323wmo.5 for ; Mon, 23 Jan 2023 07:49:53 -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=RcuLwLea8VS0jYl9VX7cWP9Zb2pEovDe9YzgIFH+IBfCnlNmmL0ulQ2GcRSANafUI4 yuW+QQkjuoQ5+rnZkBvvT4a2QRO9agDYwnOw3Ln3Cn7rND1srUWft5782VL6AQzlC9vo hu6x7liEj7/zhZgmfL3GhzA6eHP+LN7jAh+sCHm6/vlt4r2SZ/M9OewsrfT2M6uJz7aS P6eMrjPQ6wpa1a59iE67+799qC3wnNbQ7n8Y40DLj5W8FUsYI0vtD/j1D4BuIXAWWfxN IZRQ36FttWGJ+lkA/Oqdke38BDPHWB7gm2FyZOcV7c6SfZbeat4Bcr6mqLu0K580GEXk sAwg== 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=HVH/gzFWuwMYQ0qyuudn6qy2WJVo+e1t706rdXmaYkQQLZ4xgFuLN5sAWgXwcTAaLA RDKyn6P31BXVOQ6LjM7pGLbcVnotyZONmiuA5ugomdlqK40+Pagrpbijm0kEPOINJc9e wHdzL2F7ZkmPz1ENhrqPsqRIRWWNaqXG9O119FrwFnWFYA7phqMh3WCFo244Vgd32Q/X q1YeoAbXs3WkoaJZTzLTNVM5sGCQZVxd6Zvghkd0udhDeNKZoBjlVXt70JiPPVCmoqPn LTbdmn2BhT8u+eiWwOkwlEz+SYd8gcLoFSktyPjL3G+niJk71lunTkdz5TcmZIGjcTCJ EPoA== X-Gm-Message-State: AFqh2koj0lo6qRh36NqzAEc9TzGEPQ9L96hHNNWABsUBaMyfVHi9Ey2H HSrFhux0AIgYZzU2CYkAXHmN92XQaLRBRgDEQ20= X-Google-Smtp-Source: AMrXdXumBryeoFKlx3q21kt+6w6tIvcRvh/+mmribhVVR1MNYe2tu/q+qVbtjU7pCYS3usJk2iPzvA== X-Received: by 2002:a05:600c:810:b0:3da:f0e:fe34 with SMTP id k16-20020a05600c081000b003da0f0efe34mr23332251wmp.32.1674488993194; Mon, 23 Jan 2023 07:49:53 -0800 (PST) Received: from localhost.localdomain ([93.93.133.154]) by smtp.gmail.com with ESMTPSA id n16-20020a05600c181000b003d1de805de5sm10339689wmp.16.2023.01.23.07.49.52 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 23 Jan 2023 07:49:52 -0800 (PST) To: libcamera-devel@lists.libcamera.org Date: Mon, 23 Jan 2023 15:49:29 +0000 Message-Id: <20230123154934.27803-10-naush@raspberrypi.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230123154934.27803-1-naush@raspberrypi.com> References: <20230123154934.27803-1-naush@raspberrypi.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 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()