From patchwork Fri Jul 9 11:28:14 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Elder X-Patchwork-Id: 12880 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 E1BF2C3224 for ; Fri, 9 Jul 2021 11:28:38 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 381286851B; Fri, 9 Jul 2021 13:28:38 +0200 (CEST) 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="f6G62OCp"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id C0FEF605AC for ; Fri, 9 Jul 2021 13:28:36 +0200 (CEST) Received: from pyrite.rasen.tech (unknown [IPv6:2400:4051:61:600:2c71:1b79:d06d:5032]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id C5990E7; Fri, 9 Jul 2021 13:28:34 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1625830116; bh=OMhVPC/24Cu6gjOCcFbc1tDprSFQoCdC7zGANkkjfk0=; h=From:To:Cc:Subject:Date:From; b=f6G62OCpDdA9lBSx5HHcyKUjSUwmc8TtFqQabDno8T7+1fkLLp1DWZ5vWDXNrkfmr BiIT4hAwhjJj7CGp3KKAydiUBC8RZlxuHAaFFRIxSf7V9jYVHSNrQSyyxeQG9aBz4E 1bU7I29brG1yZqbGFwUZQdsTDBk7gpuSgz7Fco14= From: Paul Elder To: libcamera-devel@lists.libcamera.org Date: Fri, 9 Jul 2021 20:28:14 +0900 Message-Id: <20210709112814.87917-1-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.27.0 MIME-Version: 1.0 Subject: [libcamera-devel] [RFC PATCH] wip: android: capabilities: Capability detection by population 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" Implement capability and hardware level detection based on the static metadata that has been set, instead of disabling them as requirements are not met. This results in cleaner code where the static metadata is set. Signed-off-by: Paul Elder --- This currently does not work as the ControlInfo constructor for Spans is broken. This is more of an RFC for Jacopo to check that this is the direction that he wants. Clearly this is not meant to be merged, as the actual capability requirements are not fully specified yet. Plus they belong in separate patches anyway. This patch does not apply either, as it depends on many unreleased patches. --- src/android/camera_capabilities.cpp | 219 ++++++++++++++++++++-------- 1 file changed, 157 insertions(+), 62 deletions(-) diff --git a/src/android/camera_capabilities.cpp b/src/android/camera_capabilities.cpp index 83c7f0d0..ceb5cfe8 100644 --- a/src/android/camera_capabilities.cpp +++ b/src/android/camera_capabilities.cpp @@ -262,6 +262,149 @@ std::vector setMetadata(CameraMetadata *metadata, uint32_t tag, return ret; } + +template +bool metadataContains(camera_metadata_ro_entry_t &entry, T value); + +template<> +bool metadataContains(camera_metadata_ro_entry_t &entry, uint8_t value) +{ + for (unsigned int i = 0; i < entry.count; i++) + if (entry.data.u8[i] == value) + return true; + + return false; +} + +bool validateManualSensorCapability(CameraMetadata *staticMetadata) +{ + camera_metadata_ro_entry_t entry; + bool found; + + found = staticMetadata->getEntry(ANDROID_CONTROL_AE_AVAILABLE_MODES, + &entry); + if (!found || !metadataContains(entry, ANDROID_CONTROL_AE_MODE_OFF)) { + LOG(HAL, Info) + << "Missing AE mode off: " + << (found ? "not supported" : "not found"); + return false; + } + + found = staticMetadata->getEntry(ANDROID_CONTROL_AE_LOCK_AVAILABLE, + &entry); + if (!found || !(*entry.data.u8 == ANDROID_CONTROL_AE_LOCK_AVAILABLE_TRUE)) { + LOG(HAL, Info) << "Missing AE lock"; + return false; + } + + found = staticMetadata->getEntry(ANDROID_EDGE_AVAILABLE_EDGE_MODES, + &entry); + if (!found) { + LOG(HAL, Info) << "Missing edge modes"; + return false; + } + + return true; +} + +bool validateManualPostProcessingCapability(CameraMetadata *staticMetadata) +{ + camera_metadata_ro_entry_t entry; + bool found; + + found = staticMetadata->getEntry(ANDROID_CONTROL_AWB_AVAILABLE_MODES, + &entry); + if (!found || !metadataContains(entry, ANDROID_CONTROL_AWB_MODE_OFF)) { + LOG(HAL, Info) << "Missing AWB mode off"; + return false; + } + + found = staticMetadata->getEntry(ANDROID_CONTROL_AWB_LOCK_AVAILABLE, + &entry); + if (!found || !(*entry.data.u8 == ANDROID_CONTROL_AWB_LOCK_AVAILABLE_TRUE)) { + LOG(HAL, Info) << "Missing AWB lock"; + return false; + } + + return true; +} + +bool validateBurstCaptureCapability(CameraMetadata *staticMetadata) +{ + camera_metadata_ro_entry_t entry; + bool found; + + found = staticMetadata->getEntry(ANDROID_CONTROL_AE_LOCK_AVAILABLE, + &entry); + if (!found || !(*entry.data.u8 == ANDROID_CONTROL_AE_LOCK_AVAILABLE_TRUE)) { + LOG(HAL, Info) << "Missing AE lock"; + return false; + } + + found = staticMetadata->getEntry(ANDROID_CONTROL_AWB_LOCK_AVAILABLE, + &entry); + if (!found || !(*entry.data.u8 == ANDROID_CONTROL_AWB_LOCK_AVAILABLE_TRUE)) { + LOG(HAL, Info) << "Missing AWB lock"; + return false; + } + + found = staticMetadata->getEntry(ANDROID_SYNC_MAX_LATENCY, &entry); + if (!found || *entry.data.i32 < 0 || 4 < *entry.data.i32) { + LOG(HAL, Info) + << "Max sync latency is " + << (found ? std::to_string(*entry.data.i32) : "not present"); + return false; + } + + return true; +} + +std::set +computeCapabilities(CameraMetadata *staticMetadata, + std::set &existingCaps) +{ + std::set + capabilities = existingCaps; + + capabilities.insert(ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE); + + if (validateManualSensorCapability(staticMetadata)) + capabilities.insert(ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR); + + if (validateManualPostProcessingCapability(staticMetadata)) + capabilities.insert(ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MANUAL_POST_PROCESSING); + + if (validateBurstCaptureCapability(staticMetadata)) + capabilities.insert(ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BURST_CAPTURE); + + return capabilities; +} + +camera_metadata_enum_android_info_supported_hardware_level +computeHwLevel(CameraMetadata *staticMetadata, + std::set capabilities) +{ + camera_metadata_ro_entry_t entry; + bool found; + camera_metadata_enum_android_info_supported_hardware_level + hwLevel = ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_FULL; + + if (!capabilities.count(ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR)) + hwLevel = ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED; + + if (!capabilities.count(ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MANUAL_POST_PROCESSING)) + hwLevel = ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED; + + if (!capabilities.count(ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BURST_CAPTURE)) + hwLevel = ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED; + + found = staticMetadata->getEntry(ANDROID_SYNC_MAX_LATENCY, &entry); + if (!found || *entry.data.i32 != 0) + hwLevel = ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED; + + return hwLevel; +} + } /* namespace */ int CameraCapabilities::initialize(std::shared_ptr camera, @@ -655,17 +798,7 @@ int CameraCapabilities::initializeStaticMetadata() }; std::set - capabilities = { - ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE, - ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR, - ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MANUAL_POST_PROCESSING, - ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BURST_CAPTURE, - }; - - std::set - hwLevels = { - ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_FULL, - }; + capabilities = {}; /* Color correction static metadata. */ { @@ -692,19 +825,12 @@ int CameraCapabilities::initializeStaticMetadata() staticMetadata_->addEntry(ANDROID_CONTROL_AE_AVAILABLE_ANTIBANDING_MODES, aeAvailableAntiBandingModes); - std::vector aeModes = setMetadata( + setMetadata( staticMetadata_.get(), ANDROID_CONTROL_AE_AVAILABLE_MODES, controlsInfo, &controls::AeEnable, { ANDROID_CONTROL_AE_MODE_ON }); - if (std::find(aeModes.begin(), aeModes.end(), - ANDROID_CONTROL_AE_MODE_OFF) == aeModes.end()) { - LOG(HAL, Info) << "AE cannot be turned off"; - hwLevels.erase(ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_FULL); - capabilities.erase(ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR); - } - int64_t minFrameDurationNsec = -1; int64_t maxFrameDurationNsec = -1; const auto frameDurationsInfo = controlsInfo.find(&controls::FrameDurationLimits); @@ -791,17 +917,11 @@ int CameraCapabilities::initializeStaticMetadata() staticMetadata_->addEntry(ANDROID_CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES, availableStabilizationModes); - std::vector awbModes = setMetadata( + setMetadata( staticMetadata_.get(), ANDROID_CONTROL_AWB_AVAILABLE_MODES, controlsInfo, &controls::AwbMode, { ANDROID_CONTROL_AWB_MODE_AUTO }); - if (std::find(awbModes.begin(), awbModes.end(), - ANDROID_CONTROL_AWB_MODE_OFF) == awbModes.end()) { - LOG(HAL, Info) << "AWB cannot be turned off"; - hwLevels.erase(ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_FULL); - capabilities.erase(ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MANUAL_POST_PROCESSING); - } std::vector availableMaxRegions = { 0, 0, 0, @@ -817,29 +937,19 @@ int CameraCapabilities::initializeStaticMetadata() staticMetadata_->addEntry(ANDROID_CONTROL_SCENE_MODE_OVERRIDES, sceneModesOverride); - uint8_t aeLockAvailable = setMetadata( + setMetadata( staticMetadata_.get(), ANDROID_CONTROL_AE_LOCK_AVAILABLE, controlsInfo, &controls::AeLock, ControlRange::Max, ANDROID_CONTROL_AE_LOCK_AVAILABLE_FALSE); - if (aeLockAvailable != ANDROID_CONTROL_AE_LOCK_AVAILABLE_TRUE) { - LOG(HAL, Info) << "AE lock is unavailable"; - capabilities.erase(ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BURST_CAPTURE); - capabilities.erase(ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR); - } - uint8_t awbLockAvailable = setMetadata( + setMetadata( staticMetadata_.get(), ANDROID_CONTROL_AWB_LOCK_AVAILABLE, controlsInfo, &controls::AwbLock, ControlRange::Max, ANDROID_CONTROL_AWB_LOCK_AVAILABLE_FALSE); - if (awbLockAvailable != ANDROID_CONTROL_AWB_LOCK_AVAILABLE_TRUE) { - LOG(HAL, Info) << "AWB lock is unavailable"; - capabilities.erase(ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BURST_CAPTURE); - capabilities.erase(ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MANUAL_POST_PROCESSING); - } char availableControlModes = ANDROID_CONTROL_MODE_AUTO; staticMetadata_->addEntry(ANDROID_CONTROL_AVAILABLE_MODES, @@ -859,10 +969,6 @@ int CameraCapabilities::initializeStaticMetadata() availableCharacteristicsKeys_.insert(ANDROID_EDGE_AVAILABLE_EDGE_MODES); availableRequestKeys_.insert(ANDROID_EDGE_MODE); availableResultKeys_.insert(ANDROID_EDGE_MODE); - } else { - LOG(HAL, Info) << "Edge mode unavailable"; - hwLevels.erase(ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_FULL); - capabilities.erase(ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR); } /* JPEG static metadata. */ @@ -1046,17 +1152,11 @@ int CameraCapabilities::initializeStaticMetadata() } /* Sync static metadata. */ - int32_t maxLatency = setMetadata( + setMetadata( staticMetadata_.get(), ANDROID_SYNC_MAX_LATENCY, controlsInfo, &controls::draft::MaxLatency, ControlRange::Def, ANDROID_SYNC_MAX_LATENCY_UNKNOWN); - LOG(HAL, Info) << "Max sync latency is " << maxLatency; - /* CTS allows a sync latency of up to 4 for burst capture capability */ - if (maxLatency < 0 || 4 < maxLatency) - capabilities.erase(ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BURST_CAPTURE); - if (maxLatency != 0) - hwLevels.erase(ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_FULL); /* Flash static metadata. */ char flashAvailable = ANDROID_FLASH_INFO_AVAILABLE_FALSE; @@ -1220,19 +1320,14 @@ int CameraCapabilities::initializeStaticMetadata() numOutStreams); /* Check capabilities */ - std::vector availableCapabilities(capabilities.begin(), - capabilities.end()); - staticMetadata_->addEntry(ANDROID_REQUEST_AVAILABLE_CAPABILITIES, - availableCapabilities); - - uint8_t hwLevel = ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED; - if (capabilities.count(ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR) && - capabilities.count(ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MANUAL_POST_PROCESSING) && - capabilities.count(ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BURST_CAPTURE) && - hwLevels.count(ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_FULL)) - hwLevel = ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_FULL; - staticMetadata_->addEntry(ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL, - hwLevel); + capabilities = computeCapabilities(staticMetadata_.get(), capabilities); + std::vector + capsVec = std::vector(capabilities.begin(), capabilities.end()); + staticMetadata_->addEntry(ANDROID_REQUEST_AVAILABLE_CAPABILITIES, capsVec); + + camera_metadata_enum_android_info_supported_hardware_level hwLevel = + computeHwLevel(staticMetadata_.get(), capabilities); + staticMetadata_->addEntry(ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL, hwLevel); LOG(HAL, Info) << "Hardware level: "