[{"id":18474,"web_url":"https://patchwork.libcamera.org/comment/18474/","msgid":"<YQdIDkAYf7tri3TF@pendragon.ideasonboard.com>","date":"2021-08-02T01:19:10","subject":"Re: [libcamera-devel] [PATCH v7 5/9] android: Add infrastructure\n\tfor determining capabilities and hardware level","submitter":{"id":2,"url":"https://patchwork.libcamera.org/api/people/2/","name":"Laurent Pinchart","email":"laurent.pinchart@ideasonboard.com"},"content":"Hi Paul,\n\nThank you for the patch.\n\nOn Fri, Jul 30, 2021 at 07:35:32PM +0900, Paul Elder wrote:\n> Add the infrastructure for checking and reporting capabilities. Use\n> these capabilities to determine the hardware level as well.\n> \n> Bug: https://bugs.libcamera.org/show_bug.cgi?id=55\n> Signed-off-by: Paul Elder <paul.elder@ideasonboard.com>\n> \n> ---\n> Changes in v7:\n> - use entryContains for the single-presence checks\n> - go back to set\n> - use the staticMetadata_ member variable instead of passing it\n> - return false in the capaibilities detector, with a todo item\n> \n> Changes in v6:\n> - make all args const\n> - convert the caps list from set to vector\n> \n> Changes in v5:\n> - change the whole thing to turn on capabilities after they are all\n>   confirmed, instead of disabling them as conditions are not met\n> \n> Changes in v4:\n> - rebase on camera capabilities refactoring\n> - switch to std::set from std::map\n> - make hwlevel similar to capabilities\n> \n> Changes in v3:\n> - fix some compiler errors\n> - go ahead and initialize the capabilities to true, update the commit\n>   message accordingly\n> \n> Changes in v2:\n> - add a flag for FULL, since there are a few requirements that are not\n>   obtained from capabilities alone\n> - add burst capture capability, since that is required for FULL as well\n> ---\n>  src/android/camera_capabilities.cpp | 202 +++++++++++++++++++++++++---\n>  src/android/camera_capabilities.h   |  11 ++\n>  2 files changed, 198 insertions(+), 15 deletions(-)\n> \n> diff --git a/src/android/camera_capabilities.cpp b/src/android/camera_capabilities.cpp\n> index 3596b136..b59a854f 100644\n> --- a/src/android/camera_capabilities.cpp\n> +++ b/src/android/camera_capabilities.cpp\n> @@ -7,8 +7,10 @@\n>  \n>  #include \"camera_capabilities.h\"\n>  \n> +#include <algorithm>\n>  #include <array>\n>  #include <cmath>\n> +#include <map>\n>  \n>  #include <hardware/camera3.h>\n>  \n> @@ -114,8 +116,180 @@ const std::map<int, const Camera3Format> camera3FormatsMap = {\n>  \t},\n>  };\n>  \n> +const std::map<camera_metadata_enum_android_info_supported_hardware_level, std::string>\n> +hwLevelStrings = {\n> +\t{ ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED,  \"LIMITED\" },\n> +\t{ ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_FULL,     \"FULL\" },\n> +\t{ ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY,   \"LEGACY\" },\n> +\t{ ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_3,        \"LEVEL_3\" },\n> +\t{ ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_EXTERNAL, \"EXTERNAL\" },\n> +};\n> +\n>  } /* namespace */\n>  \n> +bool CameraCapabilities::validateManualSensorCapability()\n> +{\n> +\tconst char *noMode = \"Manual sensor capability unavailable: \";\n> +\n> +\tif (!staticMetadata_->entryContains<uint8_t>(ANDROID_CONTROL_AE_AVAILABLE_MODES,\n> +\t\t\t\t\t\t     ANDROID_CONTROL_AE_MODE_OFF)) {\n> +\t\tLOG(HAL, Info) << noMode << \"missing AE mode off\";\n> +\t\treturn false;\n> +\t}\n> +\n> +\tif (!staticMetadata_->entryContains<uint8_t>(ANDROID_CONTROL_AE_LOCK_AVAILABLE,\n> +\t\t\t\t\t\t     ANDROID_CONTROL_AE_LOCK_AVAILABLE_TRUE)) {\n> +\t\tLOG(HAL, Info) << noMode << \"missing AE lock\";\n> +\t\treturn false;\n> +\t}\n> +\n> +\t/*\n> +\t * \\todo Return true here after we satisfy all the requirements:\n> +\t * https://developer.android.com/reference/android/hardware/camera2/CameraMetadata#REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR\n> +\t * Manual frame duration control\n> +\t *     android.sensor.frameDuration\n> +\t *     android.sensor.info.maxFrameDuration\n> +\t * Manual exposure control\n> +\t *     android.sensor.exposureTime\n> +\t *     android.sensor.info.exposureTimeRange\n> +\t * Manual sensitivity control\n> +\t *     android.sensor.sensitivity\n> +\t *     android.sensor.info.sensitivityRange\n> +\t * Manual lens control (if the lens is adjustable)\n> +\t *     android.lens.*\n> +\t * Manual flash control (if a flash unit is present)\n> +\t *     android.flash.*\n> +\t * Manual black level locking\n> +\t *     android.blackLevel.lock\n> +\t * Auto exposure lock\n> +\t *     android.control.aeLock\n> +\t */\n> +\treturn false;\n> +}\n> +\n> +bool CameraCapabilities::validateManualPostProcessingCapability()\n> +{\n> +\tconst char *noMode = \"Manual post processing capability unavailable: \";\n> +\n> +\tif (!staticMetadata_->entryContains<uint8_t>(ANDROID_CONTROL_AWB_AVAILABLE_MODES,\n> +\t\t\t\t\t\t     ANDROID_CONTROL_AWB_MODE_OFF)) {\n> +\t\tLOG(HAL, Info) << noMode << \"missing AWB mode off\";\n> +\t\treturn false;\n> +\t}\n> +\n> +\tif (!staticMetadata_->entryContains<uint8_t>(ANDROID_CONTROL_AWB_LOCK_AVAILABLE,\n> +\t\t\t\t\t\t     ANDROID_CONTROL_AWB_LOCK_AVAILABLE_TRUE)) {\n> +\t\tLOG(HAL, Info) << noMode << \"missing AWB lock\";\n> +\t\treturn false;\n> +\t}\n> +\n> +\t/*\n> +\t * \\todo return true here after we satisfy all the requirements:\n> +\t * https://developer.android.com/reference/android/hardware/camera2/CameraMetadata#REQUEST_AVAILABLE_CAPABILITIES_MANUAL_POST_PROCESSING\n> +\t * Manual tonemap control\n> +\t *     android.tonemap.curve\n> +\t *     android.tonemap.mode\n> +\t *     android.tonemap.maxCurvePoints\n> +\t *     android.tonemap.gamma\n> +\t *     android.tonemap.presetCurve\n> +\t * Manual white balance control\n> +\t *     android.colorCorrection.transform\n> +\t *     android.colorCorrection.gains\n> +\t * Manual lens shading map control\n> +\t *     android.shading.mode\n> +\t *     android.statistics.lensShadingMapMode\n> +\t *     android.statistics.lensShadingMap\n> +\t *     android.lens.info.shadingMapSize\n> +\t * Manual aberration correction control (if aberration correction is supported)\n> +\t *     android.colorCorrection.aberrationMode\n> +\t *     android.colorCorrection.availableAberrationModes\n> +\t * Auto white balance lock\n> +\t *     android.control.awbLock\n> +\t */\n> +\treturn false;\n> +}\n> +\n> +bool CameraCapabilities::validateBurstCaptureCapability()\n> +{\n> +\tcamera_metadata_ro_entry_t entry;\n> +\tbool found;\n> +\n> +\tconst char *noMode = \"Burst capture capability unavailable: \";\n> +\n> +\tif (!staticMetadata_->entryContains<uint8_t>(ANDROID_CONTROL_AE_LOCK_AVAILABLE,\n> +\t\t\t\t\t\t     ANDROID_CONTROL_AE_LOCK_AVAILABLE_TRUE)) {\n> +\t\tLOG(HAL, Info) << noMode << \"missing AE lock\";\n> +\t\treturn false;\n> +\t}\n> +\n> +\tif (!staticMetadata_->entryContains<uint8_t>(ANDROID_CONTROL_AWB_LOCK_AVAILABLE,\n> +\t\t\t\t\t\t     ANDROID_CONTROL_AWB_LOCK_AVAILABLE_TRUE)) {\n> +\t\tLOG(HAL, Info) << noMode << \"missing AWB lock\";\n> +\t\treturn false;\n> +\t}\n> +\n> +\tfound = staticMetadata_->getEntry(ANDROID_SYNC_MAX_LATENCY, &entry);\n> +\tif (!found || *entry.data.i32 < 0 || 4 < *entry.data.i32) {\n\nNot sure if you've seen my last e-mail about this in v5 :-)\n\n> +\t\tLOG(HAL, Info)\n> +\t\t\t<< noMode << \"max sync latency is \"\n> +\t\t\t<< (found ? std::to_string(*entry.data.i32) : \"not present\");\n> +\t\treturn false;\n> +\t}\n> +\n> +\t/*\n> +\t * \\todo return true here after we satisfy all the requirements\n> +\t * https://developer.android.com/reference/android/hardware/camera2/CameraMetadata#REQUEST_AVAILABLE_CAPABILITIES_BURST_CAPTURE\n> +\t */\n> +\treturn false;\n> +}\n> +\n> +std::set<camera_metadata_enum_android_request_available_capabilities>\n> +CameraCapabilities::computeCapabilities()\n> +{\n> +\tstd::set<camera_metadata_enum_android_request_available_capabilities>\n> +\t\tcapabilities;\n> +\n> +\tcapabilities.insert(ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE);\n> +\n> +\tif (validateManualSensorCapability())\n> +\t\tcapabilities.insert(ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR);\n> +\n> +\tif (validateManualPostProcessingCapability())\n> +\t\tcapabilities.insert(ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MANUAL_POST_PROCESSING);\n> +\n> +\tif (validateBurstCaptureCapability())\n> +\t\tcapabilities.insert(ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BURST_CAPTURE);\n> +\n> +\tif (rawStreamAvailable_)\n> +\t\tcapabilities.insert(ANDROID_REQUEST_AVAILABLE_CAPABILITIES_RAW);\n> +\n> +\treturn capabilities;\n> +}\n> +\n> +void CameraCapabilities::computeHwLevel(\n> +\tconst std::set<camera_metadata_enum_android_request_available_capabilities> &caps)\n> +{\n> +\tcamera_metadata_ro_entry_t entry;\n> +\tbool found;\n> +\tcamera_metadata_enum_android_info_supported_hardware_level\n> +\t\thwLevel = ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_FULL;\n> +\n> +\tif (!caps.count(ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR))\n> +\t\thwLevel = ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED;\n> +\n> +\tif (!caps.count(ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MANUAL_POST_PROCESSING))\n> +\t\thwLevel = ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED;\n> +\n> +\tif (!caps.count(ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BURST_CAPTURE))\n> +\t\thwLevel = ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED;\n> +\n> +\tfound = staticMetadata_->getEntry(ANDROID_SYNC_MAX_LATENCY, &entry);\n> +\tif (!found || *entry.data.i32 != 0)\n> +\t\thwLevel = ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED;\n> +\n> +\thwLevel_ = hwLevel;\n\nYou could use hwLevel_ through the function and drop the local variable,\nup to you.\n\n> +}\n> +\n>  int CameraCapabilities::initialize(std::shared_ptr<libcamera::Camera> camera,\n>  \t\t\t\t   int orientation, int facing)\n>  {\n> @@ -851,11 +1025,6 @@ int CameraCapabilities::initializeStaticMetadata()\n>  \tuint8_t croppingType = ANDROID_SCALER_CROPPING_TYPE_CENTER_ONLY;\n>  \tstaticMetadata_->addEntry(ANDROID_SCALER_CROPPING_TYPE, croppingType);\n>  \n> -\t/* Info static metadata. */\n> -\tuint8_t supportedHWLevel = ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED;\n> -\tstaticMetadata_->addEntry(ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL,\n> -\t\t\t\t  supportedHWLevel);\n> -\n>  \t/* Request static metadata. */\n>  \tint32_t partialResultCount = 1;\n>  \tstaticMetadata_->addEntry(ANDROID_REQUEST_PARTIAL_RESULT_COUNT,\n> @@ -876,21 +1045,24 @@ int CameraCapabilities::initializeStaticMetadata()\n>  \tstaticMetadata_->addEntry(ANDROID_REQUEST_MAX_NUM_INPUT_STREAMS,\n>  \t\t\t\t  maxNumInputStreams);\n>  \n> -\tstd::vector<uint8_t> availableCapabilities = {\n> -\t\tANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE,\n> -\t};\n> -\n> -\t/* Report if camera supports RAW. */\n> -\tif (rawStreamAvailable_)\n> -\t\tavailableCapabilities.push_back(ANDROID_REQUEST_AVAILABLE_CAPABILITIES_RAW);\n> -\n>  \t/* Number of { RAW, YUV, JPEG } supported output streams */\n>  \tint32_t numOutStreams[] = { rawStreamAvailable_, 2, 1 };\n>  \tstaticMetadata_->addEntry(ANDROID_REQUEST_MAX_NUM_OUTPUT_STREAMS,\n>  \t\t\t\t  numOutStreams);\n>  \n> -\tstaticMetadata_->addEntry(ANDROID_REQUEST_AVAILABLE_CAPABILITIES,\n> -\t\t\t\t  availableCapabilities);\n> +\t/* Check capabilities */\n> +\tstd::set<camera_metadata_enum_android_request_available_capabilities>\n> +\t\tcapabilities = computeCapabilities();\n> +\tstd::vector<camera_metadata_enum_android_request_available_capabilities>\n> +\t\tcapsVec(capabilities.begin(), capabilities.end());\n> +\tstaticMetadata_->addEntry(ANDROID_REQUEST_AVAILABLE_CAPABILITIES, capsVec);\n> +\n> +\tcomputeHwLevel(capabilities);\n> +\tstaticMetadata_->addEntry(ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL, hwLevel_);\n> +\n> +\tLOG(HAL, Info)\n> +\t\t<< \"Hardware level: \"\n> +\t\t<< hwLevelStrings.find(hwLevel_)->second;\n\nThe last two lines hold on a single line.\n\nWith these comments addressed or not,\n\nReviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n\n>  \n>  \tstd::vector<int32_t> availableCharacteristicsKeys = {\n>  \t\tANDROID_COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES,\n> diff --git a/src/android/camera_capabilities.h b/src/android/camera_capabilities.h\n> index 42a976d3..c7a966ce 100644\n> --- a/src/android/camera_capabilities.h\n> +++ b/src/android/camera_capabilities.h\n> @@ -42,6 +42,16 @@ private:\n>  \t\tint androidFormat;\n>  \t};\n>  \n> +\tbool validateManualSensorCapability();\n> +\tbool validateManualPostProcessingCapability();\n> +\tbool validateBurstCaptureCapability();\n> +\n> +\tstd::set<camera_metadata_enum_android_request_available_capabilities>\n> +\t\tcomputeCapabilities();\n> +\n> +\tvoid computeHwLevel(\n> +\t\tconst std::set<camera_metadata_enum_android_request_available_capabilities> &caps);\n> +\n>  \tstd::vector<libcamera::Size>\n>  \tinitializeYUVResolutions(const libcamera::PixelFormat &pixelFormat,\n>  \t\t\t\t const std::vector<libcamera::Size> &resolutions);\n> @@ -56,6 +66,7 @@ private:\n>  \tint facing_;\n>  \tint orientation_;\n>  \tbool rawStreamAvailable_;\n> +\tcamera_metadata_enum_android_info_supported_hardware_level hwLevel_;\n>  \n>  \tstd::vector<Camera3StreamConfiguration> streamConfigurations_;\n>  \tstd::map<int, libcamera::PixelFormat> formatsMap_;","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id 2AA09C3232\n\tfor <parsemail@patchwork.libcamera.org>;\n\tMon,  2 Aug 2021 01:19:22 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 8E627687C3;\n\tMon,  2 Aug 2021 03:19:21 +0200 (CEST)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id B4A1D687B6\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon,  2 Aug 2021 03:19:20 +0200 (CEST)","from pendragon.ideasonboard.com (62-78-145-57.bb.dnainternet.fi\n\t[62.78.145.57])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 34F3087C;\n\tMon,  2 Aug 2021 03:19:20 +0200 (CEST)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"iyqQWGLO\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1627867160;\n\tbh=iVWr/Uj4gdUVOBnJYaCNwpgzEBaDqKbAdC3OMmR/NsU=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=iyqQWGLOkor/3gGPPjxMGCrsNWC/ax/Zy4zPVc66U6wgGY2i53VYBVhsCcVP+wJcR\n\tQd5M+5ygQ6J4TSzc2zM4I5NzjMXLzgGcsfK/aEClFmIxXJvM49rsr4lr06hH5irzy+\n\tMbLGJEMnYPivUoTV1UU4BIIZBp8dHmeC662alxWo=","Date":"Mon, 2 Aug 2021 04:19:10 +0300","From":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","To":"Paul Elder <paul.elder@ideasonboard.com>","Message-ID":"<YQdIDkAYf7tri3TF@pendragon.ideasonboard.com>","References":"<20210730103536.81117-1-paul.elder@ideasonboard.com>\n\t<20210730103536.81117-6-paul.elder@ideasonboard.com>","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Disposition":"inline","In-Reply-To":"<20210730103536.81117-6-paul.elder@ideasonboard.com>","Subject":"Re: [libcamera-devel] [PATCH v7 5/9] android: Add infrastructure\n\tfor determining capabilities and hardware level","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Cc":"libcamera-devel@lists.libcamera.org","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}}]