From patchwork Mon Nov 25 15:30:00 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Elder X-Patchwork-Id: 22077 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 D5E86C32A3 for ; Mon, 25 Nov 2024 15:30:19 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 533E366030; Mon, 25 Nov 2024 16:30:18 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="GNj0a2gM"; 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 95D7D65F6B for ; Mon, 25 Nov 2024 16:30:15 +0100 (CET) Received: from neptunite.flets-east.jp (unknown [IPv6:2404:7a81:160:2100:9d06:dcbb:7303:4be6]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 0D55C6B5; Mon, 25 Nov 2024 16:29:52 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1732548594; bh=HdaC5RTSGQkQQtvuOETAKDkk2V7quRdGa1vNc+DFB/E=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=GNj0a2gMYfKf/4apoUZaHdmaMZnNzhkQhPQf7+uJv0f3zY8Jv2XXZHMgaPO6S/FAU 4EVCHlPNgPb4hB+VUnfpg1IOj+xpurjy3upSgO7zrIVygrBfSUv1jTtVLXBH8YacCm lypjEbPbLJCvLSuv/Sax2mz8xUQRXGGGvImclgqk= From: Paul Elder To: libcamera-devel@lists.libcamera.org Cc: Paul Elder Subject: [PATCH 1/4] libcamera: controls: Populate direction field in control definitions Date: Tue, 26 Nov 2024 00:30:00 +0900 Message-Id: <20241125153003.3309066-2-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20241125153003.3309066-1-paul.elder@ideasonboard.com> References: <20241125153003.3309066-1-paul.elder@ideasonboard.com> MIME-Version: 1.0 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" In preparation for adding support for querying direction information from controls, populate the corresponding field in the control ID defintions. Signed-off-by: Paul Elder --- src/libcamera/control_ids_core.yaml | 12 ++++++++++++ src/libcamera/control_ids_draft.yaml | 7 +++++++ 2 files changed, 19 insertions(+) diff --git a/src/libcamera/control_ids_core.yaml b/src/libcamera/control_ids_core.yaml index d34a2d068b60..c0e91d1852cd 100644 --- a/src/libcamera/control_ids_core.yaml +++ b/src/libcamera/control_ids_core.yaml @@ -17,6 +17,7 @@ controls: - AeLocked: type: bool + direction: out description: | Report the lock status of a running AE algorithm. @@ -236,6 +237,7 @@ controls: - AeFlickerDetected: type: int32_t + direction: out description: | Flicker period detected in microseconds. @@ -274,6 +276,7 @@ controls: - Lux: type: float + direction: out description: | Report an estimate of the current illuminance level in lux. @@ -324,6 +327,7 @@ controls: - AwbLocked: type: bool + direction: out description: | Report the lock status of a running AWB algorithm. @@ -361,6 +365,7 @@ controls: - SensorBlackLevels: type: int32_t + direction: out description: | Reports the sensor black levels used for processing a frame. @@ -385,6 +390,7 @@ controls: - FocusFoM: type: int32_t + direction: out description: | Reports a Figure of Merit (FoM) to indicate how in-focus the frame is. @@ -442,6 +448,7 @@ controls: - FrameDuration: type: int64_t + direction: out description: | The instantaneous frame duration from start of frame exposure to start of next exposure, expressed in microseconds. @@ -450,6 +457,7 @@ controls: - FrameDurationLimits: type: int64_t + direction: in description: | The minimum and maximum (in that order) frame duration, expressed in microseconds. @@ -487,6 +495,7 @@ controls: - SensorTemperature: type: float + direction: out description: | Temperature measure from the camera sensor in Celsius. @@ -499,6 +508,7 @@ controls: - SensorTimestamp: type: int64_t + direction: out description: | The time when the first row of the image sensor active array is exposed. @@ -667,6 +677,7 @@ controls: - AfTrigger: type: int32_t + direction: in description: | Start an autofocus scan. @@ -692,6 +703,7 @@ controls: - AfPause: type: int32_t + direction: in description: | Pause lens movements when in continuous autofocus mode. diff --git a/src/libcamera/control_ids_draft.yaml b/src/libcamera/control_ids_draft.yaml index 1b284257f601..59aa6141c25c 100644 --- a/src/libcamera/control_ids_draft.yaml +++ b/src/libcamera/control_ids_draft.yaml @@ -79,6 +79,7 @@ controls: - AeState: type: int32_t + direction: out description: | Control to report the current AE algorithm state. Currently identical to ANDROID_CONTROL_AE_STATE. @@ -108,6 +109,7 @@ controls: - AwbState: type: int32_t + direction: out description: | Control to report the current AWB algorithm state. Currently identical to ANDROID_CONTROL_AWB_STATE. @@ -129,6 +131,7 @@ controls: - SensorRollingShutterSkew: type: int64_t + direction: out description: | Control to report the time between the start of exposure of the first row and the start of exposure of the last row. Currently identical to @@ -262,6 +265,7 @@ controls: - FaceDetectFaceRectangles: type: Rectangle + direction: out description: | Boundary rectangles of the detected faces. The number of values is the number of detected faces. @@ -273,6 +277,7 @@ controls: - FaceDetectFaceScores: type: uint8_t + direction: out description: | Confidence score of each of the detected faces. The range of score is [0, 100]. The number of values should be the number of faces reported @@ -285,6 +290,7 @@ controls: - FaceDetectFaceLandmarks: type: Point + direction: out description: | Array of human face landmark coordinates in format [..., left_eye_i, right_eye_i, mouth_i, left_eye_i+1, ...], with i = index of face. The @@ -298,6 +304,7 @@ controls: - FaceDetectFaceIds: type: int32_t + direction: out description: | Each detected face is given a unique ID that is valid for as long as the face is visible to the camera device. A face that leaves the field of From patchwork Mon Nov 25 15:30:01 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Elder X-Patchwork-Id: 22078 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 AFA82C32A3 for ; Mon, 25 Nov 2024 15:30:21 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id B3DFD66034; Mon, 25 Nov 2024 16:30:19 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="Dn72Mo/d"; 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 33C8065F6B for ; Mon, 25 Nov 2024 16:30:17 +0100 (CET) Received: from neptunite.flets-east.jp (unknown [IPv6:2404:7a81:160:2100:9d06:dcbb:7303:4be6]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 8F71F6B5; Mon, 25 Nov 2024 16:29:54 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1732548595; bh=mX5StPOhw3lNpFAxIQJVyz+ZcGk92qAi9J2FXoJF/mI=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Dn72Mo/dIBG2jFESslevwmTHyZIFFDqZqvewPR6R5lfF1lgOZjoU3aZ/cJ3xMo1R4 QfcvAtfwZ/TlHTabjkz0A8oqUv4by/k29+8ooVPX08Owu1/KVNIRO5/y26BG0uO1HE VaJKDnv25FAL4QvIORRZ7De1xG6G6MN2J0B4kmZ0= From: Paul Elder To: libcamera-devel@lists.libcamera.org Cc: Paul Elder Subject: [PATCH 2/4] utils: codegen: controls.py: Parse direction information Date: Tue, 26 Nov 2024 00:30:01 +0900 Message-Id: <20241125153003.3309066-3-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20241125153003.3309066-1-paul.elder@ideasonboard.com> References: <20241125153003.3309066-1-paul.elder@ideasonboard.com> MIME-Version: 1.0 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" In preparation for adding support for querying direction information from controls, parse the direction information from control ID definitions. This can later be plugged in directly to the IPA code generators simply by using ctrl.direction. Signed-off-by: Paul Elder Reviewed-by: Laurent Pinchart --- utils/codegen/controls.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/utils/codegen/controls.py b/utils/codegen/controls.py index 03c77cc64abe..bc1c655f1b9b 100644 --- a/utils/codegen/controls.py +++ b/utils/codegen/controls.py @@ -60,6 +60,15 @@ class Control(object): self.__size = num_elems + direction = self.__data.get('direction') + if direction is not None: + valid_values = ['in', 'out', 'inout'] + if direction not in valid_values: + raise RuntimeError(f'Control `{self.__name}` direction `{direction}` is invalid; must be one of `in`, `out`, or `inout`') + self.__direction = direction + else: + self.__direction = 'inout' + @property def description(self): """The control description""" @@ -111,6 +120,18 @@ class Control(object): else: return f"Span" + @property + def direction(self): + in_flag = 'static_cast(ControlId::Direction::In)' + out_flag = 'static_cast(ControlId::Direction::Out)' + + if self.__direction == 'inout': + return f'{in_flag} | {out_flag}' + if self.__direction == 'in': + return in_flag + if self.__direction == 'out': + return out_flag + @property def element_type(self): return self.__data.get('type') From patchwork Mon Nov 25 15:30:02 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Elder X-Patchwork-Id: 22079 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 0FB6DC32A3 for ; Mon, 25 Nov 2024 15:30:24 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id B59CE65F73; Mon, 25 Nov 2024 16:30:23 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="WwnU7YZH"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id EC68365F7F for ; Mon, 25 Nov 2024 16:30:18 +0100 (CET) Received: from neptunite.flets-east.jp (unknown [IPv6:2404:7a81:160:2100:9d06:dcbb:7303:4be6]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 1DEF66B5; Mon, 25 Nov 2024 16:29:55 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1732548597; bh=rAdDTPZva8Km2A/oF3v15Pi4d9Ow6Kp9wLi+0UlRADc=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=WwnU7YZHuerViwBeIRMKuFZOKHsUrzK5CYBzE0RcKzNdS1HG2kKsLY+bkxS55t/av kRaXPIqw9Rj4DqcImRpgNka3q/faly0MQ2OPUHfo5tVioDIvd9qjGSrcRTRsPYwiHs +yPI2MvXEEhedlEtpQQJ6XdbDQHYAKGRVZ1ij25k= From: Paul Elder To: libcamera-devel@lists.libcamera.org Cc: Paul Elder Subject: [PATCH 3/4] libcamera: controls: Add support for querying direction information Date: Tue, 26 Nov 2024 00:30:02 +0900 Message-Id: <20241125153003.3309066-4-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20241125153003.3309066-1-paul.elder@ideasonboard.com> References: <20241125153003.3309066-1-paul.elder@ideasonboard.com> MIME-Version: 1.0 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 support to ControlId for querying direction information. This allows applications to query whether a ControlId is meant for being set in controls or to be returned in metadata or both. This also has a side effect of properly encoding this information, as previously it was only mentioned losely and inconsistently in the control id definition. Signed-off-by: Paul Elder --- include/libcamera/controls.h | 27 +++++++++++++++++++- src/libcamera/control_ids.cpp.in | 4 +-- src/libcamera/controls.cpp | 42 ++++++++++++++++++++++++++++++-- 3 files changed, 68 insertions(+), 5 deletions(-) diff --git a/include/libcamera/controls.h b/include/libcamera/controls.h index 3cfe2de5973c..cd338ac0d653 100644 --- a/include/libcamera/controls.h +++ b/include/libcamera/controls.h @@ -17,6 +17,7 @@ #include #include +#include #include #include @@ -235,8 +236,18 @@ private: class ControlId { public: + enum class Direction { + In = (1 << 0), + Out = (1 << 1), + }; + + using DirectionFlags = Flags; + ControlId(unsigned int id, const std::string &name, const std::string &vendor, ControlType type, std::size_t size = 0, + const DirectionFlags &direction = + static_cast(Direction::In) | + static_cast(Direction::Out), const std::map &enumStrMap = {}); unsigned int id() const { return id_; } @@ -245,6 +256,16 @@ public: ControlType type() const { return type_; } bool isArray() const { return size_ > 0; } std::size_t size() const { return size_; } + bool isInput() const + { + return static_cast( + direction_ & static_cast(Direction::In)); + } + bool isOutput() const + { + return static_cast( + direction_ & static_cast(Direction::Out)); + } const std::map &enumerators() const { return reverseMap_; } private: @@ -255,6 +276,7 @@ private: std::string vendor_; ControlType type_; std::size_t size_; + DirectionFlags direction_; std::map enumStrMap_; std::map reverseMap_; }; @@ -286,9 +308,12 @@ public: using type = T; Control(unsigned int id, const char *name, const char *vendor, + const ControlId::DirectionFlags &direction = + static_cast(ControlId::Direction::In) | + static_cast(ControlId::Direction::Out), const std::map &enumStrMap = {}) : ControlId(id, name, vendor, details::control_type>::value, - details::control_type>::size, enumStrMap) + details::control_type>::size, direction, enumStrMap) { } diff --git a/src/libcamera/control_ids.cpp.in b/src/libcamera/control_ids.cpp.in index afe9e2c96610..65668d486dbc 100644 --- a/src/libcamera/control_ids.cpp.in +++ b/src/libcamera/control_ids.cpp.in @@ -89,9 +89,9 @@ extern const std::map {{ctrl.name}}NameValueMap = { { "{{enum.name}}", {{enum.name}} }, {%- endfor %} }; -extern const Control<{{ctrl.type}}> {{ctrl.name}}({{ctrl.name|snake_case|upper}}, "{{ctrl.name}}", "{{vendor}}", {{ctrl.name}}NameValueMap); +extern const Control<{{ctrl.type}}> {{ctrl.name}}({{ctrl.name|snake_case|upper}}, "{{ctrl.name}}", "{{vendor}}", {{ctrl.direction}}, {{ctrl.name}}NameValueMap); {% else -%} -extern const Control<{{ctrl.type}}> {{ctrl.name}}({{ctrl.name|snake_case|upper}}, "{{ctrl.name}}", "{{vendor}}"); +extern const Control<{{ctrl.type}}> {{ctrl.name}}({{ctrl.name|snake_case|upper}}, "{{ctrl.name}}", "{{vendor}}", {{ctrl.direction}}); {% endif -%} {%- endfor %} diff --git a/src/libcamera/controls.cpp b/src/libcamera/controls.cpp index 2efecf0fc52b..30eb17e7f064 100644 --- a/src/libcamera/controls.cpp +++ b/src/libcamera/controls.cpp @@ -397,14 +397,15 @@ void ControlValue::reserve(ControlType type, bool isArray, std::size_t numElemen * \param[in] vendor The vendor name * \param[in] type The control data type * \param[in] size The size of the array control, or 0 if scalar control + * \param[in] direction The direction of the control, if it can be used in Controls or Metadata * \param[in] enumStrMap The map from enum names to values (optional) */ ControlId::ControlId(unsigned int id, const std::string &name, const std::string &vendor, ControlType type, - std::size_t size, + std::size_t size, const DirectionFlags &direction, const std::map &enumStrMap) : id_(id), name_(name), vendor_(vendor), type_(type), size_(size), - enumStrMap_(enumStrMap) + direction_(direction), enumStrMap_(enumStrMap) { for (const auto &pair : enumStrMap_) reverseMap_[pair.second] = pair.first; @@ -440,6 +441,26 @@ ControlId::ControlId(unsigned int id, const std::string &name, * \return True if the control is an array control, false otherwise */ +/** + * \fn bool ControlId::isInput() const + * \brief Determine if the control is available to be used as an input control + * + * Controls can be used either as input as a control, or as output in metadata. + * This function checks if the control is allowed to be used as the former. + * + * \return True if the control can be used as an input control, false otherwise + */ + +/** + * \fn bool ControlId::isOutput() const + * \brief Determine if the control is available to be used in output metadata + * + * Controls can be used either as input as a control, or as output in metadata. + * This function checks if the control is allowed to be used as the latter. + * + * \return True if the control can be returned in output metadata, false otherwise + */ + /** * \fn std::size_t ControlId::size() const * \brief Retrieve the size of the control if it is an array control @@ -471,6 +492,22 @@ ControlId::ControlId(unsigned int id, const std::string &name, * \return True if \a lhs.id() is equal to \a rhs, false otherwise */ +/** + * \enum ControlId::Direction + * \brief The direction that a control of the ControlId is capable of being passed from/to + * + * \var ControlId::Direction::In + * \brief The control can be passed in controls as input + * + * \var ControlId::Direction::Out + * \brief The control can be returned in output as metadata + */ + +/** + * \typedef ControlId::DirectionFlags + * \brief A wrapper for ControlId::Direction so that it can be used as flags + */ + /** * \class Control * \brief Describe a control and its intrinsic properties @@ -504,6 +541,7 @@ ControlId::ControlId(unsigned int id, const std::string &name, * \param[in] id The control numerical ID * \param[in] name The control name * \param[in] vendor The vendor name + * \param[in] direction The direction of the control, if it can be used in Controls or Metadata * \param[in] enumStrMap The map from enum names to values (optional) * * The control data type is automatically deduced from the template type T. From patchwork Mon Nov 25 15:30:03 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Elder X-Patchwork-Id: 22080 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 5E93BC32A3 for ; Mon, 25 Nov 2024 15:30:25 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id F01A666040; Mon, 25 Nov 2024 16:30:24 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="meH5007X"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 36DCD6603D for ; Mon, 25 Nov 2024 16:30:20 +0100 (CET) Received: from neptunite.flets-east.jp (unknown [IPv6:2404:7a81:160:2100:9d06:dcbb:7303:4be6]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id A0B4912E9; Mon, 25 Nov 2024 16:29:57 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1732548598; bh=Mv19DzoGdexe9gDai8YxU1/+ZgP8sxyLMS2T2pqJB2U=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=meH5007XPkv0UM6RZGhUfGSfRc/RmHyKhzeHNBVSi9ATKOiMsj8gFsVFrkNHRozYq 4il4s8hdBQ7l7j6z42MHvGlvTZ2ew3dVX5iaoJ+jIO9W1yHQlf5/gUPhGy+gsgXVpq Wn/qrrf5GYCyUjWe4icVJGliOOL1qyZRASMyjrew= From: Paul Elder To: libcamera-devel@lists.libcamera.org Cc: Paul Elder Subject: [PATCH 4/4] apps: cam: Print control direction information Date: Tue, 26 Nov 2024 00:30:03 +0900 Message-Id: <20241125153003.3309066-5-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20241125153003.3309066-1-paul.elder@ideasonboard.com> References: <20241125153003.3309066-1-paul.elder@ideasonboard.com> MIME-Version: 1.0 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" Now that there is support for retrieving the allowed directions of a control, print this information when listing controls. Sample output: $ cam --list-controls -c 2 Using camera Virtual0 as cam0 Control: [io] draft::FaceDetectMode: - FaceDetectModeOff (0) Control: [i ] libcamera::FrameDurationLimits: [16666..33333] Size: 2 Signed-off-by: Paul Elder --- src/apps/cam/camera_session.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/apps/cam/camera_session.cpp b/src/apps/cam/camera_session.cpp index 6e9890ccfda1..1baf36fcfd3c 100644 --- a/src/apps/cam/camera_session.cpp +++ b/src/apps/cam/camera_session.cpp @@ -159,12 +159,18 @@ CameraSession::~CameraSession() void CameraSession::listControls() const { for (const auto &[id, info] : camera_->controls()) { + std::stringstream io; + io << "[" + << (id->isInput() ? "i" : " ") + << (id->isOutput() ? "o" : " ") + << "] "; + if (info.values().empty()) { - std::cout << "Control: " + std::cout << "Control: " << io.str() << id->vendor() << "::" << id->name() << ": " << info.toString() << std::endl; } else { - std::cout << "Control: " + std::cout << "Control: " << io.str() << id->vendor() << "::" << id->name() << ":" << std::endl; for (const auto &value : info.values()) {