From patchwork Tue Dec 21 05:25:07 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Elder X-Patchwork-Id: 15200 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 BA806BF415 for ; Tue, 21 Dec 2021 05:25:25 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 67C1460908; Tue, 21 Dec 2021 06:25:25 +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="ozn9cw+7"; 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 59D1E608E9 for ; Tue, 21 Dec 2021 06:25:22 +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 8B44A881; Tue, 21 Dec 2021 06:25:21 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1640064322; bh=yJW/wid7/A114WdKfol9TMMhMSZuLQYtpEGAkAYgpKA=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=ozn9cw+7TqGtpejOqx/dRNJK3V07n5puxrEjToIsNtHca+cb0gvmWkpdtq2FBlLtE 9cxeMu8rgJWuRAYPV41Y5lHQMtQDFhXGcg0R14c84eZK0cxkQASiNeannkXy0Mj3pF WFWEIlqaE1kLQ16nZ+sQye9Ttcss1XGbqBPTZcLY= From: Paul Elder To: libcamera-devel@lists.libcamera.org Date: Mon, 20 Dec 2021 23:25:07 -0600 Message-Id: <20211221052507.2678322-3-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20211221052507.2678322-1-paul.elder@ideasonboard.com> References: <20211221052507.2678322-1-paul.elder@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 2/2] android: Plumb lens shading 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 the controls related to lens shading: - request the lens shading map to be reported (and report the current mode) - report the lens shading map (size + map) - request and report enabling/disabling of lens shading - corresponding static metadata to report available modes Also add a check for the RAW capability, as being able to report the lens shading map is a requirement for it. Signed-off-by: Paul Elder --- src/android/camera_capabilities.cpp | 102 +++++++++++++++++++++++++++- src/android/camera_device.cpp | 100 +++++++++++++++++++++++++-- 2 files changed, 196 insertions(+), 6 deletions(-) diff --git a/src/android/camera_capabilities.cpp b/src/android/camera_capabilities.cpp index 742c6a6a..cb5ea5e9 100644 --- a/src/android/camera_capabilities.cpp +++ b/src/android/camera_capabilities.cpp @@ -295,6 +295,18 @@ bool CameraCapabilities::validateManualPostProcessingCapability() return false; } + /* From docs */ + if (!staticMetadata_->entryContains(ANDROID_SHADING_AVAILABLE_MODES, + ANDROID_SHADING_MODE_OFF) || + !staticMetadata_->entryContains(ANDROID_SHADING_AVAILABLE_MODES, + ANDROID_SHADING_MODE_FAST) || + /* From CTS */ + !staticMetadata_->entryContains(ANDROID_SHADING_AVAILABLE_MODES, + ANDROID_SHADING_MODE_HIGH_QUALITY)) { + LOG(HAL, Info) << noMode << "missing shading modes off or fast or HQ"; + return false; + } + /* * \todo return true here after we satisfy all the requirements: * https://developer.android.com/reference/android/hardware/camera2/CameraMetadata#REQUEST_AVAILABLE_CAPABILITIES_MANUAL_POST_PROCESSING @@ -375,8 +387,12 @@ CameraCapabilities::computeCapabilities() if (validateBurstCaptureCapability()) capabilities.insert(ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BURST_CAPTURE); - if (rawStreamAvailable_) + if (rawStreamAvailable_ && + staticMetadata_->entryContains( + ANDROID_STATISTICS_INFO_AVAILABLE_LENS_SHADING_MAP_MODES, + ANDROID_STATISTICS_LENS_SHADING_MAP_MODE_ON)) { capabilities.insert(ANDROID_REQUEST_AVAILABLE_CAPABILITIES_RAW); + } return capabilities; } @@ -437,6 +453,21 @@ void CameraCapabilities::computeHwLevel( hwLevel = ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED; } + /* + * Shading mode and lens shading map mode are always available and + * don't need to be checked. We only need to check we support reporting + * the lens shading map. + * + * The lens shading map may have a null map with a zero size. It is + * valid, but will give android a null correction map. + * \todo Confirm that this is fine + */ + found = availableResultKeys_.count(ANDROID_LENS_INFO_SHADING_MAP_SIZE); + if (!found) { + LOG(HAL, Info) << noFull << "missing reportable lens shading map"; + hwLevel = ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED; + } + hwLevel_ = hwLevel; } @@ -871,7 +902,9 @@ int CameraCapabilities::initializeStaticMetadata() ANDROID_SENSOR_INFO_PIXEL_ARRAY_SIZE, ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE, ANDROID_SENSOR_ORIENTATION, + ANDROID_SHADING_AVAILABLE_MODES, ANDROID_STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES, + ANDROID_STATISTICS_INFO_AVAILABLE_LENS_SHADING_MAP_MODES, ANDROID_STATISTICS_INFO_MAX_FACE_COUNT, ANDROID_SYNC_MAX_LATENCY, }; @@ -903,7 +936,9 @@ int CameraCapabilities::initializeStaticMetadata() ANDROID_LENS_OPTICAL_STABILIZATION_MODE, ANDROID_NOISE_REDUCTION_MODE, ANDROID_SCALER_CROP_REGION, - ANDROID_STATISTICS_FACE_DETECT_MODE + ANDROID_SHADING_MODE, + ANDROID_STATISTICS_FACE_DETECT_MODE, + ANDROID_STATISTICS_LENS_SHADING_MAP_MODE, }; availableResultKeys_ = { @@ -949,6 +984,7 @@ int CameraCapabilities::initializeStaticMetadata() ANDROID_SENSOR_ROLLING_SHUTTER_SKEW, ANDROID_SENSOR_TEST_PATTERN_MODE, ANDROID_SENSOR_TIMESTAMP, + ANDROID_SHADING_MODE, ANDROID_STATISTICS_FACE_DETECT_MODE, ANDROID_STATISTICS_LENS_SHADING_MAP_MODE, ANDROID_STATISTICS_HOT_PIXEL_MAP_MODE, @@ -1361,7 +1397,25 @@ int CameraCapabilities::initializeStaticMetadata() staticMetadata_->addEntry(ANDROID_STATISTICS_INFO_MAX_FACE_COUNT, maxFaceCount); + /* Lens shading */ { + /* + * Controls for requesting and reporting the lens shading map: + * static: + * - ANDROID_STATISTICS_INFO_AVAILABLE_LENS_SHADING_MAP_MODES + * - availability of requesting the lens shading map, always + * available + * request: + * - ANDROID_STATISTICS_LENS_SHADING_MAP_MODE + * - request reporting of the lens shading map, always available + * result: + * - ANDROID_STATISTICS_LENS_SHADING_MAP_MODE + * - result version of the above control + * - ANDROID_LENS_INFO_SHADING_MAP_SIZE + * - size of the lens shading map + * - ANDROID_STATISTICS_LENS_SHADING_MAP + * - the actual lens shading map + */ std::vector data; data.reserve(2); const auto &infoMap = controlsInfo.find(&controls::StatsLensShadingMapMode); @@ -1373,6 +1427,34 @@ int CameraCapabilities::initializeStaticMetadata() } staticMetadata_->addEntry(ANDROID_STATISTICS_INFO_AVAILABLE_LENS_SHADING_MAP_MODES, data); + + const auto &mapSizeInfoMap = controlsInfo.find(&controls::StatsLensShadingMapSize); + if (mapSizeInfoMap != controlsInfo.end()) + availableResultKeys_.insert(ANDROID_LENS_INFO_SHADING_MAP_SIZE); + + const auto &mapInfoMap = controlsInfo.find(&controls::StatsLensShadingMap); + if (mapInfoMap != controlsInfo.end()) + availableResultKeys_.insert(ANDROID_STATISTICS_LENS_SHADING_MAP); + + /* + * Controls for enabling/disabling lens shading: + * static: + * - ANDROID_SHADING_AVAILABLE_MODES + * - list of available lens shading modes, always available + * request and result: + * - ANDROID_SHADING_MODE + * - set/report the shading mode (off, fast, hq) + */ + data.clear(); + data.reserve(3); + const auto &shadingInfoMap = controlsInfo.find(&controls::LensShadingMode); + if (shadingInfoMap != controlsInfo.end()) { + for (const auto &value : shadingInfoMap->second.values()) + data.push_back(value.get()); + } else { + data.push_back(ANDROID_SHADING_MODE_OFF); + } + staticMetadata_->addEntry(ANDROID_SHADING_AVAILABLE_MODES, data); } /* Sync static metadata. */ @@ -1802,6 +1884,16 @@ std::unique_ptr CameraCapabilities::requestTemplatePreview() con requestTemplate->addEntry(ANDROID_CONTROL_CAPTURE_INTENT, captureIntent); + uint8_t shadingMapMode = ANDROID_STATISTICS_LENS_SHADING_MAP_MODE_OFF; + requestTemplate->addEntry(ANDROID_STATISTICS_LENS_SHADING_MAP_MODE, + shadingMapMode); + + if (staticMetadata_->entryContains(ANDROID_SHADING_AVAILABLE_MODES, + ANDROID_SHADING_MODE_FAST)) { + uint8_t shadingMode = ANDROID_SHADING_MODE_FAST; + requestTemplate->addEntry(ANDROID_SHADING_MODE, shadingMode); + } + return requestTemplate; } @@ -1817,6 +1909,12 @@ std::unique_ptr CameraCapabilities::requestTemplateStill() const stillTemplate->appendEntry(ANDROID_EDGE_MODE, edgeMode); } + if (staticMetadata_->entryContains(ANDROID_SHADING_AVAILABLE_MODES, + ANDROID_SHADING_MODE_HIGH_QUALITY)) { + uint8_t shadingMode = ANDROID_SHADING_MODE_HIGH_QUALITY; + stillTemplate->appendEntry(ANDROID_SHADING_MODE, shadingMode); + } + if (staticMetadata_->entryContains( ANDROID_NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES, ANDROID_NOISE_REDUCTION_MODE_HIGH_QUALITY)) { diff --git a/src/android/camera_device.cpp b/src/android/camera_device.cpp index 883a5dc1..7be0ce45 100644 --- a/src/android/camera_device.cpp +++ b/src/android/camera_device.cpp @@ -973,6 +973,47 @@ int CameraDevice::processControls(Camera3RequestDescriptor *descriptor) } } + if (settings.getEntry(ANDROID_STATISTICS_LENS_SHADING_MAP_MODE, &entry)) { + const int32_t data = static_cast(*entry.data.u8); + int32_t statsLensShadingMode; + switch (data) { + case ANDROID_STATISTICS_LENS_SHADING_MAP_MODE_ON: + statsLensShadingMode = controls::StatsLensShadingMapModeOn; + break; + case ANDROID_STATISTICS_LENS_SHADING_MAP_MODE_OFF: + statsLensShadingMode = controls::StatsLensShadingMapModeOff; + break; + default: + LOG(HAL, Error) + << "Unknown lens shading map mode: " << data; + return -EINVAL; + } + + controls.set(controls::StatsLensShadingMapMode, statsLensShadingMode); + } + + if (settings.getEntry(ANDROID_SHADING_MODE, &entry)) { + const int32_t data = static_cast(*entry.data.u8); + int32_t shadingMode; + switch (data) { + case ANDROID_SHADING_MODE_OFF: + shadingMode = controls::LensShadingModeOff; + break; + case ANDROID_SHADING_MODE_FAST: + shadingMode = controls::LensShadingModeFast; + break; + case ANDROID_SHADING_MODE_HIGH_QUALITY: + shadingMode = controls::LensShadingModeHighQuality; + break; + default: + LOG(HAL, Error) + << "Unknown shading mode: " << data; + return -EINVAL; + } + + controls.set(controls::LensShadingMode, shadingMode); + } + return 0; } @@ -1613,10 +1654,6 @@ CameraDevice::getResultMetadata(const Camera3RequestDescriptor &descriptor) cons value = ANDROID_STATISTICS_FACE_DETECT_MODE_OFF; resultMetadata->addEntry(ANDROID_STATISTICS_FACE_DETECT_MODE, value); - value = ANDROID_STATISTICS_LENS_SHADING_MAP_MODE_OFF; - resultMetadata->addEntry(ANDROID_STATISTICS_LENS_SHADING_MAP_MODE, - value); - value = ANDROID_STATISTICS_HOT_PIXEL_MAP_MODE_OFF; resultMetadata->addEntry(ANDROID_STATISTICS_HOT_PIXEL_MAP_MODE, value); @@ -1720,6 +1757,61 @@ CameraDevice::getResultMetadata(const Camera3RequestDescriptor &descriptor) cons std::vector focusRange = { 0.0f, 0.0f }; resultMetadata->addEntry(ANDROID_LENS_FOCUS_RANGE, focusRange); + value = ANDROID_STATISTICS_LENS_SHADING_MAP_MODE_OFF; + if (metadata.contains(controls::StatsLensShadingMapMode)) { + switch (metadata.get(controls::StatsLensShadingMapMode)) { + case controls::StatsLensShadingMapModeOn: + value = ANDROID_STATISTICS_LENS_SHADING_MAP_MODE_ON; + break; + case controls::StatsLensShadingMapModeOff: + value = ANDROID_STATISTICS_LENS_SHADING_MAP_MODE_OFF; + break; + default: + LOG(HAL, Error) << "Invalid StatsLensShadingMapMode"; + } + } + resultMetadata->addEntry(ANDROID_STATISTICS_LENS_SHADING_MAP_MODE, value); + + if (metadata.contains(controls::LensShadingMode)) { + bool valid; + switch (metadata.get(controls::LensShadingMode)) { + case controls::LensShadingModeOff: + value = ANDROID_SHADING_MODE_OFF; + valid = true; + break; + case controls::LensShadingModeFast: + value = ANDROID_SHADING_MODE_FAST; + valid = true; + break; + case controls::LensShadingModeHighQuality: + value = ANDROID_SHADING_MODE_HIGH_QUALITY; + valid = true; + break; + default: + LOG(HAL, Error) << "Invalid LensShadingMode"; + valid = false; + } + + /* Can be null on non-FULL */ + if (valid) + resultMetadata->addEntry(ANDROID_SHADING_MODE, value); + } + + if (metadata.contains(controls::StatsLensShadingMapSize)) { + Size size = metadata.get(controls::StatsLensShadingMapSize); + std::array mapSize = { size.width, size.height }; + resultMetadata->addEntry(ANDROID_LENS_INFO_SHADING_MAP_SIZE, mapSize); + + /* valid size and null map is fine, but not vice versa */ + if (metadata.contains(controls::StatsLensShadingMap)) { + const Span map = + metadata.get(controls::StatsLensShadingMap); + std::vector shadingMap(map.begin(), map.end()); + resultMetadata->addEntry(ANDROID_STATISTICS_LENS_SHADING_MAP, + shadingMap); + } + } + /* * Return the result metadata pack even is not valid: get() will return * nullptr.