From patchwork Tue Dec 21 05:33:03 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Elder X-Patchwork-Id: 15204 X-Patchwork-Delegate: paul.elder@ideasonboard.com 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 846A3BE080 for ; Tue, 21 Dec 2021 05:33:15 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id A104060901; Tue, 21 Dec 2021 06:33:14 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="WgZUsAjz"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 30CF0608EB for ; Tue, 21 Dec 2021 06:33:13 +0100 (CET) Received: from pyrite.mediacom.info (unknown [IPv6:2604:2d80:ad90:fb00:96fd:8874:873:6c16]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 62401FD2; Tue, 21 Dec 2021 06:33:12 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1640064792; bh=Gj3hqLPq6Vs1gN+PjmFsLy+0u9LQ00ZI2D5o3wqKPu0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=WgZUsAjzUieTxRG+O90mGCCUimNMtatzuFvKEs0wwr2XTpgbeHY6LJhnpFc5IvuLS a5JpZnWqsutRBHjop2+7Bl4l+yT5ofqHdclDVVSwypBlk3zafpB68KhoQvS3SDxUcV r9ZPkmlasBoZAyZ2jRdOioy+1Lcfj0r0sPcKb6hI= From: Paul Elder To: libcamera-devel@lists.libcamera.org Date: Mon, 20 Dec 2021 23:33:03 -0600 Message-Id: <20211221053304.2704780-2-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20211221053304.2704780-1-paul.elder@ideasonboard.com> References: <20211221053304.2704780-1-paul.elder@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 1/2] controls: Add HotPixelMode 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: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Add a control for setting and reporting the operating mode for hot pixel correction. Signed-off-by: Paul Elder --- src/libcamera/control_ids.yaml | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/libcamera/control_ids.yaml b/src/libcamera/control_ids.yaml index 411200a8..44f785e2 100644 --- a/src/libcamera/control_ids.yaml +++ b/src/libcamera/control_ids.yaml @@ -925,6 +925,34 @@ controls: value: 3 description: The AWB algorithm is locked. + - HotPixelMode: + type: int32_t + draft: true + description: | + Control to set and report the operation mode for hot pixel correction. + + Hot pixel correction interpolates out, or otherwise removes, pixels + that do not accurately measure the incoming light (i.e. pixels that are + stuck at an arbitrary value or are oversensitive). + + \todo Return the hot pixel map. + enum: + - name: HotPixelModeOff + value: 0 + description: | + No hot pixel correction is applied. The frame rate must not be + reduced relative to sensor raw output. + - name: HotPixelModeFast + value: 1 + description: | + Hot pixel correction is applied, without reducing frame rate + relative to sensor raw output. + - name: HotPixelModeHighQuality + value: 2 + description: | + Hot pixel correction is applied, at a cost of possibly reduced + frame rate relative to sensor raw output. + - SensorRollingShutterSkew: type: int64_t draft: true From patchwork Tue Dec 21 05:33:04 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Elder X-Patchwork-Id: 15206 X-Patchwork-Delegate: paul.elder@ideasonboard.com 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 86025C3258 for ; Tue, 21 Dec 2021 05:33:18 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 2B4D16090C; Tue, 21 Dec 2021 06:33:18 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="L4MbhkTp"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 6D5D6608EB for ; Tue, 21 Dec 2021 06:33:14 +0100 (CET) Received: from pyrite.mediacom.info (unknown [IPv6:2604:2d80:ad90:fb00:96fd:8874:873:6c16]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 4DD69FD2; Tue, 21 Dec 2021 06:33:13 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1640064794; bh=nzR+iTqrvmeL9h3+bzgU0m2kB+Qfx6YoTmjhB8G+zqg=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=L4MbhkTpvu8/0c7Kt4+Q4wgms1IlpsePGDaDbiylLMoDQUT6zHWGnfTEFIFX1MsbW LxtAnWs/RyAXa/+1V9wzyZJAlxpRb5fqPrxuHq98YQmllWyCAqZMK0VRz3Z305k0HE 7ebesK5QeZ+yAyDxK5rUFmdGVD44ZHnzeqqp+Bbw= From: Paul Elder To: libcamera-devel@lists.libcamera.org Date: Mon, 20 Dec 2021 23:33:04 -0600 Message-Id: <20211221053304.2704780-3-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20211221053304.2704780-1-paul.elder@ideasonboard.com> References: <20211221053304.2704780-1-paul.elder@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 2/2] android: Plumb hot pixel mode 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: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Plumb hot pixel mode: - add check for hardware level FULL - static metadata: report the available modes, enable the keys - request, result: convert between libcamera control and android control - add to templates Signed-off-by: Paul Elder --- src/android/camera_capabilities.cpp | 55 +++++++++++++++++++++++++++++ src/android/camera_device.cpp | 46 ++++++++++++++++++++++++ 2 files changed, 101 insertions(+) diff --git a/src/android/camera_capabilities.cpp b/src/android/camera_capabilities.cpp index 2ce465aa..c52b22be 100644 --- a/src/android/camera_capabilities.cpp +++ b/src/android/camera_capabilities.cpp @@ -492,6 +492,12 @@ void CameraCapabilities::computeHwLevel( hwLevel = ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED; } + found = availableResultKeys_.count(ANDROID_HOT_PIXEL_MODE); + if (!found) { + LOG(HAL, Info) << noFull << "missing hot pixel mode"; + hwLevel = ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED; + } + hwLevel_ = hwLevel; } @@ -1132,6 +1138,37 @@ int CameraCapabilities::initializeStaticMetadata() staticMetadata_->addEntry(ANDROID_CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES, availableStabilizationModes); + std::vector availableHotPixelModes; + const auto &hotPixelInfo = controlsInfo.find(&controls::draft::HotPixelMode); + if (hotPixelInfo != controlsInfo.end()) { + for (const auto &value : hotPixelInfo->second.values()) { + uint8_t mode; + switch (value.get()) { + case controls::draft::HotPixelModeOff: + mode = ANDROID_HOT_PIXEL_MODE_OFF; + break; + case controls::draft::HotPixelModeFast: + mode = ANDROID_HOT_PIXEL_MODE_FAST; + break; + case controls::draft::HotPixelModeHighQuality: + mode = ANDROID_HOT_PIXEL_MODE_HIGH_QUALITY; + break; + default: + LOG(HAL, Error) << "Unknown hot pixel mode"; + continue; + } + + availableHotPixelModes.push_back(mode); + } + + staticMetadata_->addEntry(ANDROID_HOT_PIXEL_AVAILABLE_HOT_PIXEL_MODES, + availableHotPixelModes); + + availableCharacteristicsKeys_.insert(ANDROID_HOT_PIXEL_AVAILABLE_HOT_PIXEL_MODES); + availableRequestKeys_.insert(ANDROID_HOT_PIXEL_MODE); + availableResultKeys_.insert(ANDROID_HOT_PIXEL_MODE); + } + /* * \todo Inspect the camera capabilities to report the available * AWB modes. Default to AUTO as CTS tests require it. @@ -1995,6 +2032,12 @@ std::unique_ptr CameraCapabilities::requestTemplatePreview() con requestTemplate->addEntry(ANDROID_TONEMAP_MODE, tonemapMode); } + if (staticMetadata_->entryContains(ANDROID_HOT_PIXEL_AVAILABLE_HOT_PIXEL_MODES, + ANDROID_HOT_PIXEL_MODE_FAST)) { + uint8_t hotPixelMode = ANDROID_HOT_PIXEL_MODE_FAST; + requestTemplate->addEntry(ANDROID_HOT_PIXEL_MODE, hotPixelMode); + } + return requestTemplate; } @@ -2029,6 +2072,12 @@ std::unique_ptr CameraCapabilities::requestTemplateStill() const stillTemplate->appendEntry(ANDROID_TONEMAP_MODE, tonemapMode); } + if (staticMetadata_->entryContains(ANDROID_HOT_PIXEL_AVAILABLE_HOT_PIXEL_MODES, + ANDROID_HOT_PIXEL_MODE_HIGH_QUALITY)) { + uint8_t hotPixelMode = ANDROID_HOT_PIXEL_MODE_HIGH_QUALITY; + stillTemplate->appendEntry(ANDROID_HOT_PIXEL_MODE, hotPixelMode); + } + return stillTemplate; } @@ -2058,6 +2107,12 @@ std::unique_ptr CameraCapabilities::requestTemplateVideo() const previewTemplate->appendEntry(ANDROID_TONEMAP_MODE, tonemapMode); } + if (staticMetadata_->entryContains(ANDROID_HOT_PIXEL_AVAILABLE_HOT_PIXEL_MODES, + ANDROID_HOT_PIXEL_MODE_FAST)) { + uint8_t hotPixelMode = ANDROID_HOT_PIXEL_MODE_FAST; + previewTemplate->appendEntry(ANDROID_HOT_PIXEL_MODE, hotPixelMode); + } + /* * Assume the AE_AVAILABLE_TARGET_FPS_RANGE static metadata * has been assembled as {{min, max} {max, max}}. diff --git a/src/android/camera_device.cpp b/src/android/camera_device.cpp index 7cffb4b1..7cab878c 100644 --- a/src/android/camera_device.cpp +++ b/src/android/camera_device.cpp @@ -973,6 +973,27 @@ int CameraDevice::processControls(Camera3RequestDescriptor *descriptor) } } + if (settings.getEntry(ANDROID_HOT_PIXEL_MODE, &entry)) { + const int32_t data = static_cast(*entry.data.u8); + int32_t hotPixelMode; + switch (data) { + case ANDROID_HOT_PIXEL_MODE_OFF: + hotPixelMode = controls::draft::HotPixelModeOff; + break; + case ANDROID_HOT_PIXEL_MODE_FAST: + hotPixelMode = controls::draft::HotPixelModeFast; + break; + case ANDROID_HOT_PIXEL_MODE_HIGH_QUALITY: + hotPixelMode = controls::draft::HotPixelModeHighQuality; + break; + default: + LOG(HAL, Error) << "Unknown hot pixel mode: " << data; + return -EINVAL; + } + + controls.set(controls::draft::HotPixelMode, hotPixelMode); + } + if (settings.getEntry(ANDROID_STATISTICS_LENS_SHADING_MAP_MODE, &entry)) { const int32_t data = static_cast(*entry.data.u8); int32_t statsLensShadingMode; @@ -1793,6 +1814,31 @@ CameraDevice::getResultMetadata(const Camera3RequestDescriptor &descriptor) cons resultMetadata->addEntry(ANDROID_EDGE_MODE, descriptor.edgeMode_); } + if (metadata.contains(controls::draft::HotPixelMode)) { + bool valid; + switch (metadata.get(controls::draft::HotPixelMode)) { + case controls::draft::HotPixelModeOff: + value = ANDROID_HOT_PIXEL_MODE_OFF; + valid = true; + break; + case controls::draft::HotPixelModeFast: + value = ANDROID_HOT_PIXEL_MODE_FAST; + valid = true; + break; + case controls::draft::HotPixelModeHighQuality: + value = ANDROID_HOT_PIXEL_MODE_HIGH_QUALITY; + valid = true; + break; + default: + LOG(HAL, Error) << "Invalid hot pixel mode"; + valid = false; + } + + /* Can be null on non-FULL */ + if (valid) + resultMetadata->addEntry(ANDROID_HOT_PIXEL_MODE, value); + } + if (metadata.contains(controls::ScalerCrop)) { Rectangle crop = metadata.get(controls::ScalerCrop); int32_t cropRect[] = {