From patchwork Mon Jan 13 16:42:23 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 2616 Return-Path: Received: from relay11.mail.gandi.net (relay11.mail.gandi.net [217.70.178.231]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id AD58F60607 for ; Mon, 13 Jan 2020 17:40:24 +0100 (CET) Received: from uno.lan (2-224-242-101.ip172.fastwebnet.it [2.224.242.101]) (Authenticated sender: jacopo@jmondi.org) by relay11.mail.gandi.net (Postfix) with ESMTPSA id 4A9C610000A; Mon, 13 Jan 2020 16:40:24 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Mon, 13 Jan 2020 17:42:23 +0100 Message-Id: <20200113164245.52535-2-jacopo@jmondi.org> X-Mailer: git-send-email 2.24.0 In-Reply-To: <20200113164245.52535-1-jacopo@jmondi.org> References: <20200113164245.52535-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 01/23] [TEMP] include: linux: Update v4l2-controls.h 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: , X-List-Received-Date: Mon, 13 Jan 2020 16:40:24 -0000 Import a temporary version of the v4l2-controls.h with the newly added definition of V4L2_CID_CAMERA_SENSOR_LOCATION control. This patch should be temporary applied waiting for the newly added control to land in the mainline kernel version. Signed-off-by: Jacopo Mondi --- include/linux/v4l2-controls.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/include/linux/v4l2-controls.h b/include/linux/v4l2-controls.h index ef2ee5b796b4..d18a7749d3f1 100644 --- a/include/linux/v4l2-controls.h +++ b/include/linux/v4l2-controls.h @@ -910,6 +910,13 @@ enum v4l2_auto_focus_range { #define V4L2_CID_PAN_SPEED (V4L2_CID_CAMERA_CLASS_BASE+32) #define V4L2_CID_TILT_SPEED (V4L2_CID_CAMERA_CLASS_BASE+33) +#define V4L2_CID_CAMERA_SENSOR_LOCATION (V4L2_CID_CAMERA_CLASS_BASE+34) +#define V4L2_LOCATION_FRONT 0 +#define V4L2_LOCATION_BACK 1 +#define V4L2_LOCATION_EXTERNAL 2 + +#define V4L2_CID_CAMERA_SENSOR_ROTATION (V4L2_CID_CAMERA_CLASS_BASE+35) + /* FM Modulator class control IDs */ #define V4L2_CID_FM_TX_CLASS_BASE (V4L2_CTRL_CLASS_FM_TX | 0x900) From patchwork Mon Jan 13 16:42:24 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 2617 Return-Path: Received: from relay11.mail.gandi.net (relay11.mail.gandi.net [217.70.178.231]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 9C5B6606EA for ; Mon, 13 Jan 2020 17:40:25 +0100 (CET) Received: from uno.lan (2-224-242-101.ip172.fastwebnet.it [2.224.242.101]) (Authenticated sender: jacopo@jmondi.org) by relay11.mail.gandi.net (Postfix) with ESMTPSA id D24CD100004; Mon, 13 Jan 2020 16:40:24 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Mon, 13 Jan 2020 17:42:24 +0100 Message-Id: <20200113164245.52535-3-jacopo@jmondi.org> X-Mailer: git-send-email 2.24.0 In-Reply-To: <20200113164245.52535-1-jacopo@jmondi.org> References: <20200113164245.52535-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 02/23] libcamera: controls: Parse 'enum' in gen-controls.py 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: , X-List-Received-Date: Mon, 13 Jan 2020 16:40:25 -0000 In preparation to add libcamera Camera properties definitions by re-using the control generation framework, augment the gen_controls.py script to support parsing the 'enum' yaml tag and generate documentation and definition of possible values associated with a Control or a Property and defined through an enumeration of supported values. Reviewed-by: Niklas Söderlund Signed-off-by: Laurent Pinchart Signed-off-by: Jacopo Mondi --- src/libcamera/gen-controls.py | 48 +++++++++++++++++++++++++++++++---- 1 file changed, 43 insertions(+), 5 deletions(-) diff --git a/src/libcamera/gen-controls.py b/src/libcamera/gen-controls.py index 940386cc68c8..7369ab4b0fdb 100755 --- a/src/libcamera/gen-controls.py +++ b/src/libcamera/gen-controls.py @@ -16,7 +16,18 @@ def snake_case(s): return ''.join([c.isupper() and ('_' + c) or c for c in s]).strip('_') +def format_description(description): + description = description.strip('\n').split('\n') + description[0] = '\\brief ' + description[0] + return '\n'.join([(line and ' * ' or ' *') + line for line in description]) + + def generate_cpp(controls): + enum_doc_start_template = string.Template('''/** + * \\enum ${name}Values + * \\brief Supported ${name} values''') + enum_doc_value_template = string.Template(''' * \\var ${name}Values::${value} +${description}''') doc_template = string.Template('''/** * \\var extern const Control<${type}> ${name} ${description} @@ -31,17 +42,30 @@ ${description} name, ctrl = ctrl.popitem() id_name = snake_case(name).upper() - description = ctrl['description'].strip('\n').split('\n') - description[0] = '\\brief ' + description[0] - description = '\n'.join([(line and ' * ' or ' *') + line for line in description]) - info = { 'name': name, 'type': ctrl['type'], - 'description': description, + 'description': format_description(ctrl['description']), 'id_name': id_name, } + enum = ctrl.get('enum') + if enum: + enum_doc = [] + enum_doc.append(enum_doc_start_template.substitute(info)) + + for value in enum: + value_info = { + 'name' : name, + 'value': list(value.keys())[0], + 'description': format_description(value['description']), + } + enum_doc.append(enum_doc_value_template.substitute(value_info)) + + enum_doc = '\n *\n'.join(enum_doc) + enum_doc += '\n */' + ctrls_doc.append(enum_doc) + ctrls_doc.append(doc_template.substitute(info)) ctrls_def.append(def_template.substitute(info)) ctrls_map.append('\t{ ' + id_name + ', &' + name + ' },') @@ -54,6 +78,8 @@ ${description} def generate_h(controls): + enum_template_start = string.Template('''enum ${name}Values {''') + enum_value_template = string.Template('''\t${name} = ${value},''') template = string.Template('''extern const Control<${type}> ${name};''') ctrls = [] @@ -71,6 +97,18 @@ def generate_h(controls): 'type': ctrl['type'], } + enum = ctrl.get('enum') + if enum: + ctrls.append(enum_template_start.substitute(info)) + + for value in enum: + value_info = { + 'name': list(value.keys())[0], + 'value': value['value'], + } + ctrls.append(enum_value_template.substitute(value_info)) + ctrls.append("};") + ctrls.append(template.substitute(info)) id_value += 1 From patchwork Mon Jan 13 16:42:25 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 2618 Return-Path: Received: from relay11.mail.gandi.net (relay11.mail.gandi.net [217.70.178.231]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 7378D606F7 for ; Mon, 13 Jan 2020 17:40:26 +0100 (CET) Received: from uno.lan (2-224-242-101.ip172.fastwebnet.it [2.224.242.101]) (Authenticated sender: jacopo@jmondi.org) by relay11.mail.gandi.net (Postfix) with ESMTPSA id CEB4510000B; Mon, 13 Jan 2020 16:40:25 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Mon, 13 Jan 2020 17:42:25 +0100 Message-Id: <20200113164245.52535-4-jacopo@jmondi.org> X-Mailer: git-send-email 2.24.0 In-Reply-To: <20200113164245.52535-1-jacopo@jmondi.org> References: <20200113164245.52535-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 03/23] libcamera: properties: Add location property 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: , X-List-Received-Date: Mon, 13 Jan 2020 16:40:27 -0000 Re-use the Control generation infrastructure to generate libcamera properties and define the first 'Location' property. Introduce three additional files: - include/libcamera/property_ids.h Defines the properties ids - src/libcamera/property_ids.cpp Defines the properties Control<> instances - src/libcamera/property_ids.yaml Provide the first 'Location' property definition. Signed-off-by: Laurent Pinchart Signed-off-by: Jacopo Mondi Reviewed-by: Niklas Söderlund --- include/libcamera/meson.build | 26 +++++++++++------ include/libcamera/property_ids.h.in | 33 ++++++++++++++++++++++ src/libcamera/meson.build | 21 ++++++++------ src/libcamera/property_ids.cpp.in | 43 +++++++++++++++++++++++++++++ src/libcamera/property_ids.yaml | 28 +++++++++++++++++++ 5 files changed, 134 insertions(+), 17 deletions(-) create mode 100644 include/libcamera/property_ids.h.in create mode 100644 src/libcamera/property_ids.cpp.in create mode 100644 src/libcamera/property_ids.yaml diff --git a/include/libcamera/meson.build b/include/libcamera/meson.build index 8db217bb782c..f58c02d2cf35 100644 --- a/include/libcamera/meson.build +++ b/include/libcamera/meson.build @@ -25,15 +25,23 @@ install_headers(libcamera_api, gen_controls = files('../../src/libcamera/gen-controls.py') -control_ids_h = custom_target('control_ids_h', - input : files('../../src/libcamera/control_ids.yaml', 'control_ids.h.in'), - output : 'control_ids.h', - depend_files : gen_controls, - command : [gen_controls, '-o', '@OUTPUT@', '@INPUT@'], - install : true, - install_dir : join_paths('include', include_dir)) - -libcamera_api += control_ids_h +control_source_files = [ + 'control_ids', + 'property_ids', +] + +control_headers = [] + +foreach header : control_source_files + input_files = files('../../src/libcamera/' + header +'.yaml', header + '.h.in') + control_headers += custom_target(header + '_h', + input : input_files, + output : header + '.h', + depend_files : gen_controls, + command : [gen_controls, '-o', '@OUTPUT@', '@INPUT@'], + install : true, + install_dir : join_paths('include', include_dir)) +endforeach gen_header = files('gen-header.sh') diff --git a/include/libcamera/property_ids.h.in b/include/libcamera/property_ids.h.in new file mode 100644 index 000000000000..62799b3e8c54 --- /dev/null +++ b/include/libcamera/property_ids.h.in @@ -0,0 +1,33 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2019, Google Inc. + * + * property_ids.h : Property ID list + * + * This file is auto-generated. Do not edit. + */ + +#ifndef __LIBCAMERA_PROPERTY_IDS_H__ +#define __LIBCAMERA_PROPERTY_IDS_H__ + +#include + +#include + +namespace libcamera { + +namespace properties { + +enum { +${ids} +}; + +${controls} + +extern const ControlIdMap properties; + +} /* namespace propertiess */ + +} /* namespace libcamera */ + +#endif // __LIBCAMERA_PROPERTY_IDS_H__ diff --git a/src/libcamera/meson.build b/src/libcamera/meson.build index 68d89559b290..1e5b54b34078 100644 --- a/src/libcamera/meson.build +++ b/src/libcamera/meson.build @@ -69,14 +69,19 @@ endif gen_controls = files('gen-controls.py') -control_ids_cpp = custom_target('control_ids_cpp', - input : files('control_ids.yaml', 'control_ids.cpp.in'), - output : 'control_ids.cpp', - depend_files : gen_controls, - command : [gen_controls, '-o', '@OUTPUT@', '@INPUT@']) - -libcamera_sources += control_ids_cpp -libcamera_sources += control_ids_h +control_sources = [] + +foreach source : control_source_files + input_files = files(source +'.yaml', source + '.cpp.in') + control_sources += custom_target(source + '_cpp', + input : input_files, + output : source + '.cpp', + depend_files : gen_controls, + command : [gen_controls, '-o', '@OUTPUT@', '@INPUT@']) +endforeach + +libcamera_sources += control_headers +libcamera_sources += control_sources gen_version = join_paths(meson.source_root(), 'utils', 'gen-version.sh') diff --git a/src/libcamera/property_ids.cpp.in b/src/libcamera/property_ids.cpp.in new file mode 100644 index 000000000000..bfdd823f63b0 --- /dev/null +++ b/src/libcamera/property_ids.cpp.in @@ -0,0 +1,43 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2019, Google Inc. + * + * property_ids.cpp : Property ID list + * + * This file is auto-generated. Do not edit. + */ + +#include + +/** + * \file property_ids.h + * \brief Camera property identifiers + */ + +namespace libcamera { + +/** + * \brief Namespace for libcamera properties + */ +namespace properties { + +${controls_doc} + +#ifndef __DOXYGEN__ +/* + * Keep the properties definitions hidden from doxygen as it incorrectly parses + * them as functions. + */ +${controls_def} +#endif + +/** + * \brief List of all supported libcamera properties + */ +extern const ControlIdMap properties { +${controls_map} +}; + +} /* namespace properties */ + +} /* namespace libcamera */ diff --git a/src/libcamera/property_ids.yaml b/src/libcamera/property_ids.yaml new file mode 100644 index 000000000000..aaadcbd3e52b --- /dev/null +++ b/src/libcamera/property_ids.yaml @@ -0,0 +1,28 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later +# +# Copyright (C) 2019, Google Inc. +# +%YAML 1.2 +--- +controls: + - Location: + type: int32_t + description: | + Camera mounting location + enum: + - CameraLocationFront: + value: 0 + description: | + The camera is mounted on the front side of the device, facing the + user + - CameraLocationBack: + value: 1 + description: | + The camera is mounted on the back side of the device, facing away + from the user + - CameraLocationExternal: + value: 2 + description: | + The camera is attached to the device in a way that allows it to + be moved freely +... From patchwork Mon Jan 13 16:42:26 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 2619 Return-Path: Received: from relay11.mail.gandi.net (relay11.mail.gandi.net [217.70.178.231]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 0782160700 for ; Mon, 13 Jan 2020 17:40:27 +0100 (CET) Received: from uno.lan (2-224-242-101.ip172.fastwebnet.it [2.224.242.101]) (Authenticated sender: jacopo@jmondi.org) by relay11.mail.gandi.net (Postfix) with ESMTPSA id 96382100003; Mon, 13 Jan 2020 16:40:26 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Mon, 13 Jan 2020 17:42:26 +0100 Message-Id: <20200113164245.52535-5-jacopo@jmondi.org> X-Mailer: git-send-email 2.24.0 In-Reply-To: <20200113164245.52535-1-jacopo@jmondi.org> References: <20200113164245.52535-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 04/23] libcamera: properties: Add rotation property 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: , X-List-Received-Date: Mon, 13 Jan 2020 16:40:27 -0000 The rotation property describes the rotation of the camera sensor. Signed-off-by: Jacopo Mondi Reviewed-by: Niklas Söderlund Reviewed-by: Laurent Pinchart --- src/libcamera/property_ids.yaml | 309 ++++++++++++++++++++++++++++++++ 1 file changed, 309 insertions(+) diff --git a/src/libcamera/property_ids.yaml b/src/libcamera/property_ids.yaml index aaadcbd3e52b..243af7bd0a03 100644 --- a/src/libcamera/property_ids.yaml +++ b/src/libcamera/property_ids.yaml @@ -25,4 +25,313 @@ controls: description: | The camera is attached to the device in a way that allows it to be moved freely + + - Rotation: + type: int32_t + description: | + The camera rotation is expressed as the angular difference in degrees + between two reference systems, one implicitly defined by the camera + module intrinsics characteristics, and one artificially defined on the + external world scene to be captured when projected on the image sensor + pixel array. + + A camera sensor has an implicitly defined 2-dimensional reference + system 'Rc' defined by its pixel array scan-out order, with its origin + posed at pixel address (0,0), the x-axis progressing from there towards + the last scanned out column of the pixel array and the y-axis + progressing towards the last scanned out line. + + A typical example for a sensor with a (2592x1944) pixel array matrix + observed from the front is + + (2592) x-axis 0 + <------------------------+ 0 + .......... ... ..........! + .......... ... ..........! y-axis + ... ! + .......... ... ..........! + .......... ... ..........! (1944) + V + + The external world scene reference system scene 'Rs' is defined as a + 2-dimensional reference system on the parallel plane posed in front + of the camera module's focal plane, with its origin placed on the + visible top-left corner, the x-axis progressing towards the right from + there and the y-axis progressing towards the bottom of the visible + scene. + + A typical example of a (very common) picture of a shark swimming from + left to right is + + x-axis + (0,0)----------------------> + ! + ! + ! |\____)\___ + ! ) _____ __`< + ! |/ )/ + ! + V + y-axis + + With the reference plane posed in front of the camera module and + parallel to its focal plane + + ! + / ! + / ! + / ! + _ / ! + +-/ \-+ / ! + | (o) | ! 'Rs' reference plane + +-----+ \ ! + \ ! + \ ! + \ ! + \ ! + ! + + When projected on the sensor's pixel array, the image and the associated + reference system 'Rs' are typically inverted, due to the camera module's + lens optical inversion effect. + + Assuming the above represented scene of the swimming shark, the lens + inversion projects on the sensor pixel array the reference plane 'Rp' + + y-axis + ^ + ! + ! |\_____)\__ + ! ) ____ ___.< + ! |/ )/ + ! + ! + (0,0)----------------------> + x-axis + + The camera rotation property is then defined as the angular difference + in counterclockwise direction between the origin of the camera reference + system 'Rc', defined by the camera sensor scan-out direction and its + mounting position, and the origin of the projected scene reference + system 'Rp', result of the optical projection of the scene reference + system 'Rs' on the sensor pixel array. + + Examples + + 0 degrees camera rotation + + y-Rp + y-Rc ^ + ^ ! + ! ! + ! ! + ! ! + ! ! + ! ! + ! (0,0)----------------------> + ! x-Rp + 0 +-------------------------------------> + 0 x-Rc + + + x-Rc 0 + <------------------------+ 0 + x-Rp ! + <-----------------------(0,0) ! + ! ! + ! ! + ! ! + ! V + ! y-Rc + V + y-Rp + + 90 degrees camera rotation + + 0 y-Rc + 0 +-----------------------> + ! + ! y-Rp + ! ^ + ! ! + ! ! + ! ! + ! ! + ! ! + ! ! + ! (0,0)----------------------> + ! x-Rp + ! + V + x-Rc + + 180 degrees camera rotation + + x-Cr 0 + <------------------------+ 0 + y-Rp ! + ^ ! + ! ! y-Cr + ! ! + ! ! + ! V + ! + ! + (0,0)---------------------> + x-Rp + + 270 degrees camera rotation + + 0 y-Rc + 0 +-----------------------> + ! x-Rp + ! <-----------------------(0,0 + ! ! + ! ! + ! ! + ! ! + ! ! + ! V + ! y-Rp + ! + ! + V + x-Rc + + + + Example one - Webcam + + A camera module installed on the user facing part of a laptop screen + casing used for video calls. The captured images are meant to be + displayed in landscape mode (width > height) on the laptop screen. + + The camera is typically mounted 180 degrees rotated to compensate the + lens optical inversion effect. + + y-Rp + y-Rc ^ + ^ ! + ! ! |\_____)\__ + ! ! ) ____ ___.< + ! ! |/ )/ + ! ! + ! ! + ! (0,0)----------------------> + ! x-Rp + 0 +-------------------------------------> + 0 x-Rc + + The two reference systems are aligned, the resulting camera rotation is + 0 degrees, no rotation correction should be applied to the resulting + image once captured to memory buffers to correctly display it to users. + + +--------------------------+ + ! |\____)\___ ! + ! ) _____ __`< ! + ! |/ )/ ! + +--------------------------+ + + If the camera module is not mounted 180 degrees rotated to compensate + the lens optical inversion, the two reference system will result not + aligned, with 'Rp' plane 180 degrees rotated in respect to the 'Rc' + plane. + + x-Rc 0 + <------------------------+ 0 + y-Rp ! + ^ ! + ! ! y-Rc + ! |\_____)\__ ! + ! ) ____ ___.< ! + ! |/ )/ V + ! + ! + (0,0)---------------------> + x-Rp + + The image once captured to memory will then be 180 degrees rotated + + +--------------------------+ + ! __/(_____/| ! + ! >.___ ____ ( ! + ! \( \| ! + +--------------------------+ + + A software rotation correction of 180 degrees should be applied to + correctly display the image. + + +--------------------------+ + ! |\____)\___ ! + ! ) _____ __`< ! + ! |/ )/ ! + +--------------------------+ + + Example two - Phone camera + + A camera installed on the back-side of a mobile device facing away from + the user. The captured images are meant to be displayed in portrait mode + (height > width) to match the device screen orientation and the device + usage orientation used when taking the picture. + + The camera is typically mounted with its pixel array longer side aligned + to the device longer side, 180 degrees rotated to compensate the lens + optical inversion effect. + + 0 y-Rc + 0 +-----------------------> + ! + ! y-Rp + ! ^ + ! ! + ! ! |\_____)\__ + ! ! ) ____ ___.< + ! ! |/ )/ + ! ! + ! ! + ! (0,0)----------------------> + ! x-Rp + ! + ! + V + x-Rc + + The two reference systems are not aligned and the 'Rp' reference + system is 90 degrees rotated in counterclockwise direction in respect + to the 'Rc' reference system. + + The image, when captured to memory buffer will be rotated. + + +---------------------------------------+ + | _ _ | + | \ / | + | | | | + | | | | + | | > | + | < | | + | | | | + | . | + | V | + +---------------------------------------+ + + A correction of 90 degrees in counterclockwise direction has to be + applied to correctly display the image in portrait mode on the device + screen. + + +-----------------+ + | | + | | + | | + | | + | | + | | + | |\____)\___ | + | ) _____ __`< | + | |/ )/ | + | | + | | + | | + | | + | | + +-----------------+ ... From patchwork Mon Jan 13 16:42:27 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 2620 Return-Path: Received: from relay11.mail.gandi.net (relay11.mail.gandi.net [217.70.178.231]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id F30AC606F6 for ; Mon, 13 Jan 2020 17:40:27 +0100 (CET) Received: from uno.lan (2-224-242-101.ip172.fastwebnet.it [2.224.242.101]) (Authenticated sender: jacopo@jmondi.org) by relay11.mail.gandi.net (Postfix) with ESMTPSA id 34CAC100003; Mon, 13 Jan 2020 16:40:27 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Mon, 13 Jan 2020 17:42:27 +0100 Message-Id: <20200113164245.52535-6-jacopo@jmondi.org> X-Mailer: git-send-email 2.24.0 In-Reply-To: <20200113164245.52535-1-jacopo@jmondi.org> References: <20200113164245.52535-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 05/23] libcamera: controls: Add default to ControlRange 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: , X-List-Received-Date: Mon, 13 Jan 2020 16:40:28 -0000 Augment the the ControlRange class to store the control default value. This is particularly relevant for v4l2 controls used to create Camera properties, which are constructed using immutable video device properties, whose value won't change at runtime. Reviewed-by: Laurent Pinchart Reviewed-by: Niklas Söderlund Signed-off-by: Jacopo Mondi --- include/libcamera/controls.h | 5 ++++- src/libcamera/controls.cpp | 12 ++++++++++-- src/libcamera/v4l2_controls.cpp | 9 ++++++--- 3 files changed, 20 insertions(+), 6 deletions(-) diff --git a/include/libcamera/controls.h b/include/libcamera/controls.h index b1b73367e874..458b84e8fa8c 100644 --- a/include/libcamera/controls.h +++ b/include/libcamera/controls.h @@ -114,10 +114,12 @@ class ControlRange { public: explicit ControlRange(const ControlValue &min = 0, - const ControlValue &max = 0); + const ControlValue &max = 0, + const ControlValue &def = 0); const ControlValue &min() const { return min_; } const ControlValue &max() const { return max_; } + const ControlValue &def() const { return def_; } std::string toString() const; @@ -134,6 +136,7 @@ public: private: ControlValue min_; ControlValue max_; + ControlValue def_; }; using ControlIdMap = std::unordered_map; diff --git a/src/libcamera/controls.cpp b/src/libcamera/controls.cpp index 7d8a0e97ee3a..123a6f19974a 100644 --- a/src/libcamera/controls.cpp +++ b/src/libcamera/controls.cpp @@ -357,10 +357,12 @@ Control::Control(unsigned int id, const char *name) * \brief Construct a ControlRange with minimum and maximum range parameters * \param[in] min The control minimum value * \param[in] max The control maximum value + * \param[in] def The control default value */ ControlRange::ControlRange(const ControlValue &min, - const ControlValue &max) - : min_(min), max_(max) + const ControlValue &max, + const ControlValue &def) + : min_(min), max_(max), def_(def) { } @@ -376,6 +378,12 @@ ControlRange::ControlRange(const ControlValue &min, * \return A ControlValue with the maximum value for the control */ +/** + * \fn ControlRange::def() + * \brief Retrieve the default value of the control + * \return A ControlValue with the default value for the control + */ + /** * \brief Provide a string representation of the ControlRange */ diff --git a/src/libcamera/v4l2_controls.cpp b/src/libcamera/v4l2_controls.cpp index b6547a7c627c..7446c3880330 100644 --- a/src/libcamera/v4l2_controls.cpp +++ b/src/libcamera/v4l2_controls.cpp @@ -121,17 +121,20 @@ V4L2ControlRange::V4L2ControlRange(const struct v4l2_query_ext_ctrl &ctrl) switch (ctrl.type) { case V4L2_CTRL_TYPE_BOOLEAN: ControlRange::operator=(ControlRange(static_cast(ctrl.minimum), - static_cast(ctrl.maximum))); + static_cast(ctrl.maximum), + static_cast(ctrl.default_value))); break; case V4L2_CTRL_TYPE_INTEGER64: ControlRange::operator=(ControlRange(static_cast(ctrl.minimum), - static_cast(ctrl.maximum))); + static_cast(ctrl.maximum), + static_cast(ctrl.default_value))); break; default: ControlRange::operator=(ControlRange(static_cast(ctrl.minimum), - static_cast(ctrl.maximum))); + static_cast(ctrl.maximum), + static_cast(ctrl.default_value))); break; } } From patchwork Mon Jan 13 16:42:28 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 2621 Return-Path: Received: from relay11.mail.gandi.net (relay11.mail.gandi.net [217.70.178.231]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id E02C560702 for ; Mon, 13 Jan 2020 17:40:28 +0100 (CET) Received: from uno.lan (2-224-242-101.ip172.fastwebnet.it [2.224.242.101]) (Authenticated sender: jacopo@jmondi.org) by relay11.mail.gandi.net (Postfix) with ESMTPSA id 2309410000A; Mon, 13 Jan 2020 16:40:27 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Mon, 13 Jan 2020 17:42:28 +0100 Message-Id: <20200113164245.52535-7-jacopo@jmondi.org> X-Mailer: git-send-email 2.24.0 In-Reply-To: <20200113164245.52535-1-jacopo@jmondi.org> References: <20200113164245.52535-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 06/23] libcamera: camera_sensor: Parse camera properties 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: , X-List-Received-Date: Mon, 13 Jan 2020 16:40:29 -0000 Parse and collect camera sensor properties by inspecting the associated v4l2 controls. Augment the CameraSensor class with an operation to retrieve the collected properties. Reviewed-by: Laurent Pinchart Reviewed-by: Niklas Söderlund Signed-off-by: Jacopo Mondi --- src/libcamera/camera_sensor.cpp | 49 ++++++++++++++++++++++++++- src/libcamera/include/camera_sensor.h | 7 ++-- 2 files changed, 53 insertions(+), 3 deletions(-) diff --git a/src/libcamera/camera_sensor.cpp b/src/libcamera/camera_sensor.cpp index 86f0c772861b..2219a4307436 100644 --- a/src/libcamera/camera_sensor.cpp +++ b/src/libcamera/camera_sensor.cpp @@ -13,6 +13,8 @@ #include #include +#include + #include "formats.h" #include "utils.h" #include "v4l2_subdevice.h" @@ -47,7 +49,7 @@ LOG_DEFINE_CATEGORY(CameraSensor); * Once constructed the instance must be initialized with init(). */ CameraSensor::CameraSensor(const MediaEntity *entity) - : entity_(entity) + : entity_(entity), properties_(properties::properties) { subdev_ = new V4L2Subdevice(entity); } @@ -89,6 +91,45 @@ int CameraSensor::init() if (ret < 0) return ret; + /* Retrieve and store the camera sensor properties. */ + const ControlInfoMap &controls = subdev_->controls(); + int32_t propertyValue; + + /* Camera Location: default is front location. */ + const auto &locationControl = controls.find(V4L2_CID_CAMERA_SENSOR_LOCATION); + if (locationControl != controls.end()) { + int32_t v4l2Location = + locationControl->second.def().get(); + + switch (v4l2Location) { + default: + LOG(CameraSensor, Warning) + << "Unsupported camera location " + << v4l2Location << ", setting to Front"; + /* Fall-through */ + case V4L2_LOCATION_FRONT: + propertyValue = properties::CameraLocationFront; + break; + case V4L2_LOCATION_BACK: + propertyValue = properties::CameraLocationBack; + break; + case V4L2_LOCATION_EXTERNAL: + propertyValue = properties::CameraLocationExternal; + break; + } + } else { + propertyValue = properties::CameraLocationFront; + } + properties_.set(properties::Location, propertyValue); + + /* Camera Rotation: default is 0 degrees. */ + const auto &rotationControl = controls.find(V4L2_CID_CAMERA_SENSOR_ROTATION); + if (rotationControl != controls.end()) + propertyValue = rotationControl->second.def().get(); + else + propertyValue = 0; + properties_.set(properties::Rotation, propertyValue); + /* Enumerate and cache media bus codes and sizes. */ const ImageFormats formats = subdev_->formats(0); if (formats.isEmpty()) { @@ -284,6 +325,12 @@ int CameraSensor::getControls(ControlList *ctrls) return subdev_->getControls(ctrls); } +/** + * \fn CameraSensor::properties() + * \brief Retrieve the camera sensor properties + * \return The list of camera sensor properties + */ + /** * \brief Write controls to the sensor * \param[in] ctrls The list of controls to write diff --git a/src/libcamera/include/camera_sensor.h b/src/libcamera/include/camera_sensor.h index 1fb36a4f4951..99cff98128dc 100644 --- a/src/libcamera/include/camera_sensor.h +++ b/src/libcamera/include/camera_sensor.h @@ -10,14 +10,13 @@ #include #include +#include #include #include "log.h" namespace libcamera { -class ControlInfoMap; -class ControlList; class MediaEntity; class V4L2Subdevice; @@ -47,6 +46,8 @@ public: int getControls(ControlList *ctrls); int setControls(ControlList *ctrls); + const ControlList &properties() const { return properties_; } + protected: std::string logPrefix() const; @@ -56,6 +57,8 @@ private: std::vector mbusCodes_; std::vector sizes_; + + ControlList properties_; }; } /* namespace libcamera */ From patchwork Mon Jan 13 16:42:29 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 2622 Return-Path: Received: from relay11.mail.gandi.net (relay11.mail.gandi.net [217.70.178.231]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id CC1B0606BD for ; Mon, 13 Jan 2020 17:40:29 +0100 (CET) Received: from uno.lan (2-224-242-101.ip172.fastwebnet.it [2.224.242.101]) (Authenticated sender: jacopo@jmondi.org) by relay11.mail.gandi.net (Postfix) with ESMTPSA id 0FABF10000B; Mon, 13 Jan 2020 16:40:28 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Mon, 13 Jan 2020 17:42:29 +0100 Message-Id: <20200113164245.52535-8-jacopo@jmondi.org> X-Mailer: git-send-email 2.24.0 In-Reply-To: <20200113164245.52535-1-jacopo@jmondi.org> References: <20200113164245.52535-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 07/23] libcamera: pipeline_handler: Add Camera properties 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: , X-List-Received-Date: Mon, 13 Jan 2020 16:40:30 -0000 Associate to each Camera a ControlList which contains the Camera properties as created by pipeline handlers in the pipeline handler's CameraData and provide an operation to retrieve them. Collect properties from the camera sensor in all pipeline handlers that support one (IPU3, RKISP1 and VIMC). Reviewed-by: Laurent Pinchart Reviewed-by: Niklas Söderlund Signed-off-by: Jacopo Mondi --- src/libcamera/include/pipeline_handler.h | 2 ++ src/libcamera/pipeline/ipu3/ipu3.cpp | 3 +++ src/libcamera/pipeline/rkisp1/rkisp1.cpp | 3 +++ src/libcamera/pipeline/vimc.cpp | 4 ++++ src/libcamera/pipeline_handler.cpp | 19 +++++++++++++++++++ 5 files changed, 31 insertions(+) diff --git a/src/libcamera/include/pipeline_handler.h b/src/libcamera/include/pipeline_handler.h index a6c1e1fbae38..789c5f928e6a 100644 --- a/src/libcamera/include/pipeline_handler.h +++ b/src/libcamera/include/pipeline_handler.h @@ -44,6 +44,7 @@ public: PipelineHandler *pipe_; std::list queuedRequests_; ControlInfoMap controlInfo_; + ControlList properties_; std::unique_ptr ipa_; private: @@ -65,6 +66,7 @@ public: void unlock(); const ControlInfoMap &controls(Camera *camera); + const ControlList &properties(Camera *camera); virtual CameraConfiguration *generateConfiguration(Camera *camera, const StreamRoles &roles) = 0; diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp index 7894084a025e..13a3a2369f42 100644 --- a/src/libcamera/pipeline/ipu3/ipu3.cpp +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp @@ -887,6 +887,9 @@ int PipelineHandlerIPU3::registerCameras() if (ret) continue; + /* Initialize the camera properties. */ + data->properties_ = cio2->sensor_->properties(); + /** * \todo Dynamically assign ImgU and output devices to each * stream and camera; as of now, limit support to two cameras diff --git a/src/libcamera/pipeline/rkisp1/rkisp1.cpp b/src/libcamera/pipeline/rkisp1/rkisp1.cpp index 389a99cf52bd..19b9c44208ec 100644 --- a/src/libcamera/pipeline/rkisp1/rkisp1.cpp +++ b/src/libcamera/pipeline/rkisp1/rkisp1.cpp @@ -906,6 +906,9 @@ int PipelineHandlerRkISP1::createCamera(MediaEntity *sensor) if (ret) return ret; + /* Initialize the camera properties. */ + data->properties_ = data->sensor_->properties(); + ret = data->loadIPA(); if (ret) return ret; diff --git a/src/libcamera/pipeline/vimc.cpp b/src/libcamera/pipeline/vimc.cpp index 1700ac967299..2df5447177fa 100644 --- a/src/libcamera/pipeline/vimc.cpp +++ b/src/libcamera/pipeline/vimc.cpp @@ -454,6 +454,10 @@ int VimcCameraData::init(MediaDevice *media) } controlInfo_ = std::move(ctrls); + + /* Initialize the camera properties. */ + properties_ = sensor_->properties(); + return 0; } diff --git a/src/libcamera/pipeline_handler.cpp b/src/libcamera/pipeline_handler.cpp index 669097f609ab..d93ee89c3855 100644 --- a/src/libcamera/pipeline_handler.cpp +++ b/src/libcamera/pipeline_handler.cpp @@ -98,6 +98,14 @@ LOG_DEFINE_CATEGORY(Pipeline) * creating the camera, and shall not be modified afterwards. */ +/** + * \var CameraData::properties_ + * \brief The list of properties supported by the camera + * + * The list of camera properties shall be initialised by the pipeline handler + * when creating the camera, and shall not be modified afterwards. + */ + /** * \var CameraData::ipa_ * \brief The IPA module used by the camera @@ -246,6 +254,17 @@ const ControlInfoMap &PipelineHandler::controls(Camera *camera) return data->controlInfo_; } +/** + * \brief Retrieve the list of properties for a camera + * \param[in] camera The camera + * \return A ControlList of properties supported by \a camera + */ +const ControlList &PipelineHandler::properties(Camera *camera) +{ + CameraData *data = cameraData(camera); + return data->properties_; +} + /** * \fn PipelineHandler::generateConfiguration() * \brief Generate a camera configuration for a specified camera From patchwork Mon Jan 13 16:42:30 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 2623 Return-Path: Received: from relay11.mail.gandi.net (relay11.mail.gandi.net [217.70.178.231]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id CA685606BD for ; Mon, 13 Jan 2020 17:40:30 +0100 (CET) Received: from uno.lan (2-224-242-101.ip172.fastwebnet.it [2.224.242.101]) (Authenticated sender: jacopo@jmondi.org) by relay11.mail.gandi.net (Postfix) with ESMTPSA id F3D3510000A; Mon, 13 Jan 2020 16:40:29 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Mon, 13 Jan 2020 17:42:30 +0100 Message-Id: <20200113164245.52535-9-jacopo@jmondi.org> X-Mailer: git-send-email 2.24.0 In-Reply-To: <20200113164245.52535-1-jacopo@jmondi.org> References: <20200113164245.52535-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 08/23] libcamera: camera: Add Camera properties 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: , X-List-Received-Date: Mon, 13 Jan 2020 16:40:31 -0000 Add a method to the Camera class to retrieve the Camera properties registered by the pipeline handler. While at it, reword the Camera::controls() operation documentation to specify that the camera control information are constant during the camera lifetime not their value, while the camera properties value are the actually static information. Reviewed-by: Laurent Pinchart Reviewed-by: Niklas Söderlund Signed-off-by: Jacopo Mondi --- include/libcamera/camera.h | 1 + src/libcamera/camera.cpp | 16 +++++++++++++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/include/libcamera/camera.h b/include/libcamera/camera.h index 6597ade83288..ad9ddaa5231a 100644 --- a/include/libcamera/camera.h +++ b/include/libcamera/camera.h @@ -86,6 +86,7 @@ public: int release(); const ControlInfoMap &controls(); + const ControlList &properties(); const std::set &streams() const; std::unique_ptr generateConfiguration(const StreamRoles &roles); diff --git a/src/libcamera/camera.cpp b/src/libcamera/camera.cpp index 79a5f994f9bb..cd4e8f7ce855 100644 --- a/src/libcamera/camera.cpp +++ b/src/libcamera/camera.cpp @@ -547,7 +547,8 @@ int Camera::release() /** * \brief Retrieve the list of controls supported by the camera * - * Camera controls remain constant through the lifetime of the camera. + * The list of controls supported by the camera and their associated + * constraints remain constant through the lifetime of the Camera object. * * \return A ControlInfoMap listing the controls supported by the camera */ @@ -556,6 +557,19 @@ const ControlInfoMap &Camera::controls() return pipe_->controls(this); } +/** + * \brief Retrieve the list of properties of the camera + * + * Camera properties are static information that describe the capabilities of + * the camera. They remain constant through the lifetime of the Camera object. + * + * \return A ControlList of properties supported by the camera + */ +const ControlList &Camera::properties() +{ + return pipe_->properties(this); +} + /** * \brief Retrieve all the camera's stream information * From patchwork Mon Jan 13 16:42:31 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 2624 Return-Path: Received: from relay11.mail.gandi.net (relay11.mail.gandi.net [217.70.178.231]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id DEB97606BD for ; Mon, 13 Jan 2020 17:40:31 +0100 (CET) Received: from uno.lan (2-224-242-101.ip172.fastwebnet.it [2.224.242.101]) (Authenticated sender: jacopo@jmondi.org) by relay11.mail.gandi.net (Postfix) with ESMTPSA id 06C6F100004; Mon, 13 Jan 2020 16:40:30 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Mon, 13 Jan 2020 17:42:31 +0100 Message-Id: <20200113164245.52535-10-jacopo@jmondi.org> X-Mailer: git-send-email 2.24.0 In-Reply-To: <20200113164245.52535-1-jacopo@jmondi.org> References: <20200113164245.52535-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 09/23] android: camera_device: Use Camera properties for static Metadata 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: , X-List-Received-Date: Mon, 13 Jan 2020 16:40:32 -0000 Construct two example static metadata to be reported to the Android framework using the properties reported by the Camera. Reviewed-by: Niklas Söderlund Signed-off-by: Laurent Pinchart Signed-off-by: Jacopo Mondi --- src/android/camera_device.cpp | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/src/android/camera_device.cpp b/src/android/camera_device.cpp index a98fd744f534..ea35dd685d3d 100644 --- a/src/android/camera_device.cpp +++ b/src/android/camera_device.cpp @@ -7,6 +7,9 @@ #include "camera_device.h" +#include +#include + #include "log.h" #include "utils.h" @@ -95,6 +98,8 @@ camera_metadata_t *CameraDevice::getStaticMetadata() if (staticMetadata_) return staticMetadata_->get(); + const ControlList &properties = camera_->properties(); + /* * The here reported metadata are enough to implement a basic capture * example application, but a real camera implementation will require @@ -259,9 +264,15 @@ camera_metadata_t *CameraDevice::getStaticMetadata() staticMetadata_->addEntry(ANDROID_SENSOR_INFO_EXPOSURE_TIME_RANGE, &exposureTimeRange, 2); + /* + * The Android orientation metadata and libcamera rotation property are + * defined differently but have identical numerical values for Android + * devices such as phones and tablets. + */ int32_t orientation = 0; - staticMetadata_->addEntry(ANDROID_SENSOR_ORIENTATION, - &orientation, 1); + if (properties.contains(properties::Rotation)) + orientation = properties.get(properties::Rotation); + staticMetadata_->addEntry(ANDROID_SENSOR_ORIENTATION, &orientation, 1); std::vector testPatterModes = { ANDROID_SENSOR_TEST_PATTERN_MODE_OFF, @@ -308,6 +319,20 @@ camera_metadata_t *CameraDevice::getStaticMetadata() lensApertures.size()); uint8_t lensFacing = ANDROID_LENS_FACING_FRONT; + if (properties.contains(properties::Location)) { + int32_t location = properties.get(properties::Location); + switch (location) { + case properties::CameraLocationFront: + lensFacing = ANDROID_LENS_FACING_FRONT; + break; + case properties::CameraLocationBack: + lensFacing = ANDROID_LENS_FACING_BACK; + break; + case properties::CameraLocationExternal: + lensFacing = ANDROID_LENS_FACING_EXTERNAL; + break; + } + } staticMetadata_->addEntry(ANDROID_LENS_FACING, &lensFacing, 1); std::vector lensFocalLenghts = { From patchwork Mon Jan 13 16:42:32 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 2625 Return-Path: Received: from relay11.mail.gandi.net (relay11.mail.gandi.net [217.70.178.231]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id F07DB606BD for ; Mon, 13 Jan 2020 17:40:32 +0100 (CET) Received: from uno.lan (2-224-242-101.ip172.fastwebnet.it [2.224.242.101]) (Authenticated sender: jacopo@jmondi.org) by relay11.mail.gandi.net (Postfix) with ESMTPSA id 1310A100003; Mon, 13 Jan 2020 16:40:31 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Mon, 13 Jan 2020 17:42:32 +0100 Message-Id: <20200113164245.52535-11-jacopo@jmondi.org> X-Mailer: git-send-email 2.24.0 In-Reply-To: <20200113164245.52535-1-jacopo@jmondi.org> References: <20200113164245.52535-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 10/23] cam: Add option to list camera properties 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: , X-List-Received-Date: Mon, 13 Jan 2020 16:40:33 -0000 Add the '-p'|'--list-properties' option to the cam application to list the properties of a camera. Reviewed-by: Niklas Söderlund Signed-off-by: Laurent Pinchart Signed-off-by: Jacopo Mondi --- src/cam/main.cpp | 50 ++++++++++++++++++++++++++++++++++++++++++++++++ src/cam/main.h | 1 + 2 files changed, 51 insertions(+) diff --git a/src/cam/main.cpp b/src/cam/main.cpp index a38cca959aca..41aedea3ab17 100644 --- a/src/cam/main.cpp +++ b/src/cam/main.cpp @@ -11,6 +11,7 @@ #include #include +#include #include "capture.h" #include "event_loop.h" @@ -36,6 +37,7 @@ public: private: int parseOptions(int argc, char *argv[]); int prepareConfig(); + int listProperties(); int infoConfiguration(); int run(); @@ -180,6 +182,7 @@ int CamApp::parseOptions(int argc, char *argv[]) parser.addOption(OptInfo, OptionNone, "Display information about stream(s)", "info"); parser.addOption(OptList, OptionNone, "List all cameras", "list"); + parser.addOption(OptProps, OptionNone, "List cameras properties", "list-properties"); options_ = parser.parse(argc, argv); if (!options_.valid()) @@ -268,6 +271,47 @@ int CamApp::prepareConfig() return 0; } +int CamApp::listProperties() +{ + if (!camera_) { + std::cout << "Cannot list properties without a camera" + << std::endl; + return -EINVAL; + } + + const ControlList &properties = camera_->properties(); + for (const auto &prop : properties) { + unsigned int id = prop.first; + const auto &ctrlId = properties::properties.find(id); + const ControlId *ctrl = ctrlId->second; + const ControlValue &value = prop.second; + + std::cout << "Property: " << ctrl->name() << " = "; + + switch (ctrl->type()) { + case ControlTypeBool: { + bool val = value.get(); + std::cout << (val ? "True" : "False") << std::endl; + break; + } + case ControlTypeInteger32: { + int32_t val = value.get(); + std::cout << val << std::endl; + break; + } + case ControlTypeInteger64: { + int64_t val = value.get(); + std::cout << val << std::endl; + break; + } + default: + break; + } + } + + return 0; +} + int CamApp::infoConfiguration() { if (!config_) { @@ -312,6 +356,12 @@ int CamApp::run() } } + if (options_.isSet(OptProps)) { + ret = listProperties(); + if (ret) + return ret; + } + if (options_.isSet(OptInfo)) { ret = infoConfiguration(); if (ret) diff --git a/src/cam/main.h b/src/cam/main.h index 0997476bb335..afcad4353b7d 100644 --- a/src/cam/main.h +++ b/src/cam/main.h @@ -14,6 +14,7 @@ enum { OptHelp = 'h', OptInfo = 'I', OptList = 'l', + OptProps = 'p', OptStream = 's', }; From patchwork Mon Jan 13 16:42:33 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 2626 Return-Path: Received: from relay11.mail.gandi.net (relay11.mail.gandi.net [217.70.178.231]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 8440C606EA for ; Mon, 13 Jan 2020 17:40:33 +0100 (CET) Received: from uno.lan (2-224-242-101.ip172.fastwebnet.it [2.224.242.101]) (Authenticated sender: jacopo@jmondi.org) by relay11.mail.gandi.net (Postfix) with ESMTPSA id 224C110000E; Mon, 13 Jan 2020 16:40:32 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Mon, 13 Jan 2020 17:42:33 +0100 Message-Id: <20200113164245.52535-12-jacopo@jmondi.org> X-Mailer: git-send-email 2.24.0 In-Reply-To: <20200113164245.52535-1-jacopo@jmondi.org> References: <20200113164245.52535-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 11/23] libcamera: controls: Add support for float controls 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: , X-List-Received-Date: Mon, 13 Jan 2020 16:40:33 -0000 Add support for float values in Control<> and ControlValue classes. Signed-off-by: Jacopo Mondi Reviewed-by: Niklas Söderlund --- include/libcamera/controls.h | 3 +++ src/libcamera/control_serializer.cpp | 13 ++++++++++ src/libcamera/controls.cpp | 36 ++++++++++++++++++++++++++++ 3 files changed, 52 insertions(+) diff --git a/include/libcamera/controls.h b/include/libcamera/controls.h index 458b84e8fa8c..8fa33d93b088 100644 --- a/include/libcamera/controls.h +++ b/include/libcamera/controls.h @@ -20,6 +20,7 @@ enum ControlType { ControlTypeBool, ControlTypeInteger32, ControlTypeInteger64, + ControlTypeFloat, }; class ControlValue @@ -29,6 +30,7 @@ public: ControlValue(bool value); ControlValue(int32_t value); ControlValue(int64_t value); + ControlValue(float value); ControlType type() const { return type_; } bool isNone() const { return type_ == ControlTypeNone; } @@ -53,6 +55,7 @@ private: bool bool_; int32_t integer32_; int64_t integer64_; + float float_; }; }; diff --git a/src/libcamera/control_serializer.cpp b/src/libcamera/control_serializer.cpp index a5d6d875c76f..fd91baf15156 100644 --- a/src/libcamera/control_serializer.cpp +++ b/src/libcamera/control_serializer.cpp @@ -34,6 +34,7 @@ static constexpr size_t ControlValueSize[] = { [ControlTypeBool] = sizeof(bool), [ControlTypeInteger32] = sizeof(int32_t), [ControlTypeInteger64] = sizeof(int64_t), + [ControlTypeFloat] = sizeof(float), }; } /* namespace */ @@ -176,6 +177,12 @@ void ControlSerializer::store(const ControlValue &value, break; } + case ControlTypeFloat: { + float data = value.get(); + buffer.write(&data); + break; + } + default: break; } @@ -348,6 +355,12 @@ ControlValue ControlSerializer::load(ControlType type, return ControlValue(value); } + case ControlTypeFloat: { + float value; + b.read(&value); + return ControlValue(value); + } + default: return ControlValue(); } diff --git a/src/libcamera/controls.cpp b/src/libcamera/controls.cpp index 123a6f19974a..74ce5d0ba4f1 100644 --- a/src/libcamera/controls.cpp +++ b/src/libcamera/controls.cpp @@ -58,6 +58,8 @@ LOG_DEFINE_CATEGORY(Controls) * The control stores a 32-bit integer value * \var ControlTypeInteger64 * The control stores a 64-bit integer value + * \var ControlTypeFloat + * The control stores a 32-bit floating point value */ /** @@ -100,6 +102,15 @@ ControlValue::ControlValue(int64_t value) { } +/** + * \brief Construct a float ControlValue + * \param[in] value Float value to store + */ +ControlValue::ControlValue(float value) + : type_(ControlTypeFloat), float_(value) +{ +} + /** * \fn ControlValue::type() * \brief Retrieve the data type of the value @@ -153,6 +164,14 @@ const int64_t &ControlValue::get() const return integer64_; } +template<> +const float &ControlValue::get() const +{ + ASSERT(type_ == ControlTypeFloat); + + return float_; +} + template<> void ControlValue::set(const bool &value) { @@ -173,6 +192,13 @@ void ControlValue::set(const int64_t &value) type_ = ControlTypeInteger64; integer64_ = value; } + +template<> +void ControlValue::set(const float &value) +{ + type_ = ControlTypeFloat; + float_ = value; +} #endif /* __DOXYGEN__ */ /** @@ -190,6 +216,8 @@ std::string ControlValue::toString() const return std::to_string(integer32_); case ControlTypeInteger64: return std::to_string(integer64_); + case ControlTypeFloat: + return std::to_string(float_); } return ""; @@ -211,6 +239,8 @@ bool ControlValue::operator==(const ControlValue &other) const return integer32_ == other.integer32_; case ControlTypeInteger64: return integer64_ == other.integer64_; + case ControlTypeFloat: + return float_ == other.float_; default: return false; } @@ -341,6 +371,12 @@ Control::Control(unsigned int id, const char *name) : ControlId(id, name, ControlTypeInteger64) { } + +template<> +Control::Control(unsigned int id, const char *name) + : ControlId(id, name, ControlTypeFloat) +{ +} #endif /* __DOXYGEN__ */ /** From patchwork Mon Jan 13 16:42:34 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 2627 X-Patchwork-Delegate: jacopo@jmondi.org Return-Path: Received: from relay11.mail.gandi.net (relay11.mail.gandi.net [217.70.178.231]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 1D258606EA for ; Mon, 13 Jan 2020 17:40:34 +0100 (CET) Received: from uno.lan (2-224-242-101.ip172.fastwebnet.it [2.224.242.101]) (Authenticated sender: jacopo@jmondi.org) by relay11.mail.gandi.net (Postfix) with ESMTPSA id ABA0B100009; Mon, 13 Jan 2020 16:40:33 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Mon, 13 Jan 2020 17:42:34 +0100 Message-Id: <20200113164245.52535-13-jacopo@jmondi.org> X-Mailer: git-send-email 2.24.0 In-Reply-To: <20200113164245.52535-1-jacopo@jmondi.org> References: <20200113164245.52535-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 12/23] libcamera: Add C++20 std::span<> implementation 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: , X-List-Received-Date: Mon, 13 Jan 2020 16:40:34 -0000 Add a simplified implementation of C++20 std::span<> class. Signed-off-by: Jacopo Mondi --- Documentation/Doxyfile.in | 4 +- include/libcamera/meson.build | 1 + include/libcamera/span.h | 89 +++++++++++++++++++++++ src/libcamera/meson.build | 1 + src/libcamera/span.cpp | 128 ++++++++++++++++++++++++++++++++++ 5 files changed, 222 insertions(+), 1 deletion(-) create mode 100644 include/libcamera/span.h create mode 100644 src/libcamera/span.cpp diff --git a/Documentation/Doxyfile.in b/Documentation/Doxyfile.in index 8e6fbdbb92b6..6b08960a921f 100644 --- a/Documentation/Doxyfile.in +++ b/Documentation/Doxyfile.in @@ -838,8 +838,10 @@ RECURSIVE = YES # Note that relative paths are relative to the directory from which doxygen is # run. -EXCLUDE = @TOP_SRCDIR@/src/libcamera/device_enumerator_sysfs.cpp \ +EXCLUDE = @TOP_SRCDIR@/include/libcamera/span.h \ + @TOP_SRCDIR@/src/libcamera/device_enumerator_sysfs.cpp \ @TOP_SRCDIR@/src/libcamera/device_enumerator_udev.cpp \ + @TOP_SRCDIR@/src/libcamera/span.cpp \ @TOP_SRCDIR@/src/libcamera/include/device_enumerator_sysfs.h \ @TOP_SRCDIR@/src/libcamera/include/device_enumerator_udev.h \ @TOP_SRCDIR@/src/libcamera/pipeline/ \ diff --git a/include/libcamera/meson.build b/include/libcamera/meson.build index f58c02d2cf35..f47c583cbbc0 100644 --- a/include/libcamera/meson.build +++ b/include/libcamera/meson.build @@ -14,6 +14,7 @@ libcamera_api = files([ 'pixelformats.h', 'request.h', 'signal.h', + 'span.h', 'stream.h', 'timer.h', ]) diff --git a/include/libcamera/span.h b/include/libcamera/span.h new file mode 100644 index 000000000000..3e63603f60ed --- /dev/null +++ b/include/libcamera/span.h @@ -0,0 +1,89 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2020, Google Inc. + * + * span.h - C++20 std::span<> implementation for C++11 + */ + +#ifndef __LIBCAMERA_SPAN_H__ +#define __LIBCAMERA_SPAN_H__ + +#include +#include + +namespace libcamera { + +template +class Span +{ +private: + using iterator = T *; + using const_iterator = const T *; + + class Storage + { + public: + Storage(T *ptr, size_t size) + : ptr_(ptr), size_(size) + { + } + + T *ptr() const { return ptr_; } + size_t size() const { return size_; } + + private: + T *ptr_; + size_t size_; + }; + +public: + Span(T &v) + : storage_(&v, 1) + { + } + + Span(const T &v) + : storage_(const_cast(&v), 1) + { + } + + Span(T *v, size_t s) + : storage_(v, s) + { + } + + Span(const T *v, size_t s) + : storage_(const_cast(v), s) + { + } + + Span(std::initializer_list list) + : storage_(const_cast(list.begin()), list.size()) + { + } + + Span(const Span &other) = default; + Span &operator=(const Span &other) = default; + + T *data() const { return storage_.ptr(); } + size_t size() const { return storage_.size(); } + + T &operator[](unsigned int index) const + { + if (index >= size()) + return *(end() - 1); + return *(data() + index); + } + + constexpr iterator begin() const { return data(); } + constexpr iterator cbegin() const { return begin(); } + constexpr iterator end() const { return data() + size(); } + constexpr iterator cend() const { return end(); } + +private: + Storage storage_; +}; + +}; /* namespace libcamera */ + +#endif /* __LIBCAMERA_SPAN_H__ */ diff --git a/src/libcamera/meson.build b/src/libcamera/meson.build index 1e5b54b34078..ecc5b5fe4023 100644 --- a/src/libcamera/meson.build +++ b/src/libcamera/meson.build @@ -36,6 +36,7 @@ libcamera_sources = files([ 'request.cpp', 'semaphore.cpp', 'signal.cpp', + 'span.cpp', 'stream.cpp', 'thread.cpp', 'timer.cpp', diff --git a/src/libcamera/span.cpp b/src/libcamera/span.cpp new file mode 100644 index 000000000000..72ffdf7481c4 --- /dev/null +++ b/src/libcamera/span.cpp @@ -0,0 +1,128 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2020, Google Inc. + * + * span.h - C++20 std::span<> implementation for C++11 + */ + +#include + +/** + * \file span.h + * \brief libcamera implementation of C++20 std::span<> + */ + +namespace libcamera { + +/** + * \class Span + * \brief Representation of a sequence of contiguous objects of type T + * + * This class represents a sequence of fixed size of contiguous objects of + * template type T with the first object residing in position 0. + * + * A Span internally consists of a pointer to raw memory and an associated + * number of elements there located. It does not enforce any ownership on the + * memory it represents, but it only provides a convenient, lightweight and + * easily transportable view on such memory area. + * + * A Span can be constructed from a single element as well as from raw memory + * by providing an associated size. It can be accessed by index and iterated + * as a regular standard library container. As Span does not enforce any memory + * ownership, destroying a Span instance does not invalidate the memory it + * represents. + * + * The libcamera implementation of Span it's a simplified implementation of + * C++20 the std::span<> class and it is no 1-to-1 compatible with it. Care + * should be taken in not mixing usage of the two classes. + */ + +/** + * \fn Span::Span(T &v) + * \brief Contruct a Span of size 1 representing element \a v + * \param[in] v The element represented by the Span + */ + +/** + * \fn Span::Span(const T &v) + * \brief Contruct a Span of size 1 representing the constant element \a v + * \param[in] v The constant element represented by the Span + */ + +/** + * \fn Span::Span(T *v, size_t s) + * \brief Contruct a Span of size \a s representing elements in memory \a v + * \param[in] v The memory area represeted by the Span + * \param[in] s The number of elements in memory area \a v + */ + +/** + * \fn Span::Span(const T *v, size_t s) + * \brief Contruct a Span of size \a s representing elements in constant memory \a v + * \param[in] v The constant memory area represeted by the Span + * \param[in] s The number of elements in memory area \a v + */ + +/** + * \fn Span::Span(std::initializer_list list) + * \brief Contruct a Span with an initialier list of elements + * \param[in] list The initializer list + */ + +/** + * \fn Span::Span(const Span &other) + * \brief Contruct a Span with the content of \a other + * \param[in] other The other Span + */ + +/** + * \fn Span::operator=(const Span &other) + * \brief Replace the content of the Span with the one from \a other + * \param[in] other The other Span + */ + +/** + * \fn Span::data() + * \brief Retrieve a pointer to the beginning of the memory area represented by + * the Span + * \return A pointer to the raw memory area + */ + +/** + * \fn Span::size() + * \brief Retrieve the number of elements in the Span + * \return The number of elements in the Span + */ + +/** + * \fn Span::operator[](unsigned int index) + * \brief Retrieve element in position \a index + * \param[in] index + * + * If \a index is larger than the number of elements in the Span, the last + * element is returned. + * + * \return The element at position \a index + */ + +/** + * \fn iterator Span::begin() + * \brief Retrieve an iterator to the first element in the Span + */ + +/** + * \fn const_iterator Span::cbegin() + * \brief Retrieve a constant iterator to the first element in the Span + */ + +/** + * \fn iterator Span::end() + * \brief Retrieve an iterator pointing to the past-the-end element in the Span + */ + +/** + * \fn const_iterator Span::cend() + * \brief Retrieve a constant iterator pointing to the past-the-end element in the Span + */ + +} /* namespace libcamera */ From patchwork Mon Jan 13 16:42:35 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 2628 X-Patchwork-Delegate: jacopo@jmondi.org Return-Path: Received: from relay11.mail.gandi.net (relay11.mail.gandi.net [217.70.178.231]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id BC5D3606EA for ; Mon, 13 Jan 2020 17:40:34 +0100 (CET) Received: from uno.lan (2-224-242-101.ip172.fastwebnet.it [2.224.242.101]) (Authenticated sender: jacopo@jmondi.org) by relay11.mail.gandi.net (Postfix) with ESMTPSA id 43B0D100012; Mon, 13 Jan 2020 16:40:34 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Mon, 13 Jan 2020 17:42:35 +0100 Message-Id: <20200113164245.52535-14-jacopo@jmondi.org> X-Mailer: git-send-email 2.24.0 In-Reply-To: <20200113164245.52535-1-jacopo@jmondi.org> References: <20200113164245.52535-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 13/23] libcamera: span: Add support for STL containers 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: , X-List-Received-Date: Mon, 13 Jan 2020 16:40:34 -0000 From: Laurent Pinchart Add support for STL containers to the Span class implementation and make it fully C++20-compliant. Signed-off-by: Laurent Pinchart --- include/libcamera/span.h | 187 +++++++++++++++++++++++++++++++-------- src/libcamera/span.cpp | 115 ------------------------ 2 files changed, 152 insertions(+), 150 deletions(-) diff --git a/include/libcamera/span.h b/include/libcamera/span.h index 3e63603f60ed..0fffad3a99db 100644 --- a/include/libcamera/span.h +++ b/include/libcamera/span.h @@ -9,79 +9,196 @@ #define __LIBCAMERA_SPAN_H__ #include +#include +#include #include +#include namespace libcamera { +static constexpr std::size_t dynamic_extent = std::numeric_limits::max(); + +template +class Span; + template -class Span +class Span { private: + template + struct is_array : public std::false_type { + }; + + template + struct is_array> : public std::true_type { + }; + + template + struct is_span : public std::false_type { + }; + + template + struct is_span> : public std::true_type { + }; + + template + using enable_if_t = typename std::enable_if::type; + + template + using remove_pointer_t = typename std::remove_pointer::type; + +public: + using element_type = T; + using value_type = typename std::remove_cv::type; + using size_type = std::size_t; + using different_type = std::ptrdiff_t; + using pointer = T *; + using const_pointer = const T *; + using reference = T &; + using const_reference = const T &; using iterator = T *; using const_iterator = const T *; + using reverse_iterator = std::reverse_iterator; + using const_reverse_iterator = std::reverse_iterator; - class Storage + static constexpr std::size_t extent = dynamic_extent; + + constexpr Span() noexcept + : data_(nullptr), size_(0) { - public: - Storage(T *ptr, size_t size) - : ptr_(ptr), size_(size) - { - } + } - T *ptr() const { return ptr_; } - size_t size() const { return size_; } + constexpr Span(pointer ptr, size_type count) + : data_(ptr), size_(count) + { + } - private: - T *ptr_; - size_t size_; - }; + constexpr Span(pointer first, pointer last) + : data_(first), size_(last - first) + { + } -public: - Span(T &v) - : storage_(&v, 1) + template + constexpr Span(element_type (&arr)[N], + enable_if_t (*)[], + element_type (*)[]>::value, + std::nullptr_t> = nullptr) noexcept + : data_(arr), size_(N) { } - Span(const T &v) - : storage_(const_cast(&v), 1) + template + constexpr Span(std::array &arr, + enable_if_t (*)[], + element_type (*)[]>::value, + std::nullptr_t> = nullptr) noexcept + : data_(arr.data()), size_(N) { } - Span(T *v, size_t s) - : storage_(v, s) + template + constexpr Span(const std::array &arr) noexcept + : data_(arr.data()), size_(N) { } - Span(const T *v, size_t s) - : storage_(const_cast(v), s) + template + constexpr Span(Container &cont, + enable_if_t::value && + !is_array::value && + !std::is_array::value && + std::is_convertible (*)[], + element_type (*)[]>::value, + std::nullptr_t> = nullptr) + : data_(cont.data()), size_(cont.size()) { } - Span(std::initializer_list list) - : storage_(const_cast(list.begin()), list.size()) + template + constexpr Span(const Container &cont, + enable_if_t::value && + !is_array::value && + !std::is_array::value && + std::is_convertible (*)[], + element_type (*)[]>::value, + std::nullptr_t> = nullptr) + : data_(cont.data()), size_(cont.size()) { } - Span(const Span &other) = default; - Span &operator=(const Span &other) = default; + template + constexpr Span(const Span &s, + enable_if_t::value, + std::nullptr_t> = nullptr) noexcept + : data_(s.data()), size_(s.size()) + { + } - T *data() const { return storage_.ptr(); } - size_t size() const { return storage_.size(); } + constexpr Span(const Span &other) noexcept = default; - T &operator[](unsigned int index) const +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wconstexpr-not-const" + constexpr Span &operator=(const Span &other) noexcept { - if (index >= size()) - return *(end() - 1); - return *(data() + index); + return *this, data_ = other.data_, size_ = other.size_; } +#pragma GCC diagnostic pop constexpr iterator begin() const { return data(); } - constexpr iterator cbegin() const { return begin(); } + constexpr const_iterator cbegin() const { return begin(); } constexpr iterator end() const { return data() + size(); } - constexpr iterator cend() const { return end(); } + constexpr const_iterator cend() const { return end(); } + constexpr reverse_iterator rbegin() const { return data() + size() - 1; } + constexpr const_reverse_iterator crbegin() const { return rbegin(); } + constexpr reverse_iterator rend() const { return data() - 1; } + constexpr const_reverse_iterator crend() const { return rend(); } + + constexpr reference front() const { return *data(); } + constexpr reference back() const { return *(data() + size() - 1); } + constexpr reference operator[](size_type idx) const { return data()[idx]; } + constexpr pointer data() const noexcept { return data_; } + + constexpr size_type size() const noexcept { return size_; } + constexpr size_type size_bytes() const noexcept { return size_ * sizeof(element_type); } + constexpr bool empty() const noexcept { return size_ == 0; } + + template + constexpr Span first() const + { + return { data(), Count }; + } + + constexpr Span first(std::size_t Count) const + { + return { data(), Count }; + } + + template + constexpr Span last() const + { + return { data() + size() - Count, Count }; + } + + constexpr Span last(std::size_t Count) const + { + return { data() + size() - Count, Count }; + } + + template + constexpr Span subspan() const + { + return { data() + Offset, Count == dynamic_extent ? size() - Offset : Count }; + } + + constexpr Span + subspan(std::size_t Offset, std::size_t Count = dynamic_extent) const + { + return { data() + Offset, Count == dynamic_extent ? size() - Offset : Count }; + } private: - Storage storage_; + pointer data_; + size_type size_; }; }; /* namespace libcamera */ diff --git a/src/libcamera/span.cpp b/src/libcamera/span.cpp index 72ffdf7481c4..43391b29ec85 100644 --- a/src/libcamera/span.cpp +++ b/src/libcamera/span.cpp @@ -7,122 +7,7 @@ #include -/** - * \file span.h - * \brief libcamera implementation of C++20 std::span<> - */ - namespace libcamera { -/** - * \class Span - * \brief Representation of a sequence of contiguous objects of type T - * - * This class represents a sequence of fixed size of contiguous objects of - * template type T with the first object residing in position 0. - * - * A Span internally consists of a pointer to raw memory and an associated - * number of elements there located. It does not enforce any ownership on the - * memory it represents, but it only provides a convenient, lightweight and - * easily transportable view on such memory area. - * - * A Span can be constructed from a single element as well as from raw memory - * by providing an associated size. It can be accessed by index and iterated - * as a regular standard library container. As Span does not enforce any memory - * ownership, destroying a Span instance does not invalidate the memory it - * represents. - * - * The libcamera implementation of Span it's a simplified implementation of - * C++20 the std::span<> class and it is no 1-to-1 compatible with it. Care - * should be taken in not mixing usage of the two classes. - */ - -/** - * \fn Span::Span(T &v) - * \brief Contruct a Span of size 1 representing element \a v - * \param[in] v The element represented by the Span - */ - -/** - * \fn Span::Span(const T &v) - * \brief Contruct a Span of size 1 representing the constant element \a v - * \param[in] v The constant element represented by the Span - */ - -/** - * \fn Span::Span(T *v, size_t s) - * \brief Contruct a Span of size \a s representing elements in memory \a v - * \param[in] v The memory area represeted by the Span - * \param[in] s The number of elements in memory area \a v - */ - -/** - * \fn Span::Span(const T *v, size_t s) - * \brief Contruct a Span of size \a s representing elements in constant memory \a v - * \param[in] v The constant memory area represeted by the Span - * \param[in] s The number of elements in memory area \a v - */ - -/** - * \fn Span::Span(std::initializer_list list) - * \brief Contruct a Span with an initialier list of elements - * \param[in] list The initializer list - */ - -/** - * \fn Span::Span(const Span &other) - * \brief Contruct a Span with the content of \a other - * \param[in] other The other Span - */ - -/** - * \fn Span::operator=(const Span &other) - * \brief Replace the content of the Span with the one from \a other - * \param[in] other The other Span - */ - -/** - * \fn Span::data() - * \brief Retrieve a pointer to the beginning of the memory area represented by - * the Span - * \return A pointer to the raw memory area - */ - -/** - * \fn Span::size() - * \brief Retrieve the number of elements in the Span - * \return The number of elements in the Span - */ - -/** - * \fn Span::operator[](unsigned int index) - * \brief Retrieve element in position \a index - * \param[in] index - * - * If \a index is larger than the number of elements in the Span, the last - * element is returned. - * - * \return The element at position \a index - */ - -/** - * \fn iterator Span::begin() - * \brief Retrieve an iterator to the first element in the Span - */ - -/** - * \fn const_iterator Span::cbegin() - * \brief Retrieve a constant iterator to the first element in the Span - */ - -/** - * \fn iterator Span::end() - * \brief Retrieve an iterator pointing to the past-the-end element in the Span - */ - -/** - * \fn const_iterator Span::cend() - * \brief Retrieve a constant iterator pointing to the past-the-end element in the Span - */ } /* namespace libcamera */ From patchwork Mon Jan 13 16:42:36 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 2629 X-Patchwork-Delegate: jacopo@jmondi.org Return-Path: Received: from relay11.mail.gandi.net (relay11.mail.gandi.net [217.70.178.231]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 4BC58606EA for ; Mon, 13 Jan 2020 17:40:35 +0100 (CET) Received: from uno.lan (2-224-242-101.ip172.fastwebnet.it [2.224.242.101]) (Authenticated sender: jacopo@jmondi.org) by relay11.mail.gandi.net (Postfix) with ESMTPSA id E1A08100009; Mon, 13 Jan 2020 16:40:34 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Mon, 13 Jan 2020 17:42:36 +0100 Message-Id: <20200113164245.52535-15-jacopo@jmondi.org> X-Mailer: git-send-email 2.24.0 In-Reply-To: <20200113164245.52535-1-jacopo@jmondi.org> References: <20200113164245.52535-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 14/23] libcamera: controls: Parse 'compound' yaml property 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: , X-List-Received-Date: Mon, 13 Jan 2020 16:40:35 -0000 Parse the 'compound' yaml property and create Control<> instances with the opportune type accordingly. Controls defined in the yaml source file as 'compound' will be instantiated with 'Span' type, while non-compound controls retain the 'T' type. Example controls_ids.yaml: - CompoundControl: type: int32_t description: A fictional compound control compound: true Will be parsed by gen-control.py to generate a Control> instance. Signed-off-by: Jacopo Mondi --- src/libcamera/gen-controls.py | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/libcamera/gen-controls.py b/src/libcamera/gen-controls.py index 7369ab4b0fdb..53ac66483bf6 100755 --- a/src/libcamera/gen-controls.py +++ b/src/libcamera/gen-controls.py @@ -42,9 +42,14 @@ ${description} name, ctrl = ctrl.popitem() id_name = snake_case(name).upper() + if ctrl.get('compound'): + ctrl_type = 'Span<%s>' % ctrl['type'] + else: + ctrl_type = ctrl['type'] + info = { 'name': name, - 'type': ctrl['type'], + 'type': ctrl_type, 'description': format_description(ctrl['description']), 'id_name': id_name, } @@ -92,9 +97,14 @@ def generate_h(controls): ids.append('\t' + id_name + ' = ' + str(id_value) + ',') + if ctrl.get('compound'): + ctrl_type = 'Span<%s>' % ctrl['type'] + else: + ctrl_type = ctrl['type'] + info = { 'name': name, - 'type': ctrl['type'], + 'type': ctrl_type, } enum = ctrl.get('enum') From patchwork Mon Jan 13 16:42:37 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 2630 X-Patchwork-Delegate: jacopo@jmondi.org Return-Path: Received: from relay11.mail.gandi.net (relay11.mail.gandi.net [217.70.178.231]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id EA66A60728 for ; Mon, 13 Jan 2020 17:40:35 +0100 (CET) Received: from uno.lan (2-224-242-101.ip172.fastwebnet.it [2.224.242.101]) (Authenticated sender: jacopo@jmondi.org) by relay11.mail.gandi.net (Postfix) with ESMTPSA id 757CB100005; Mon, 13 Jan 2020 16:40:35 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Mon, 13 Jan 2020 17:42:37 +0100 Message-Id: <20200113164245.52535-16-jacopo@jmondi.org> X-Mailer: git-send-email 2.24.0 In-Reply-To: <20200113164245.52535-1-jacopo@jmondi.org> References: <20200113164245.52535-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 15/23] libcamera: controls: Support compound controls in ControlValue 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: , X-List-Received-Date: Mon, 13 Jan 2020 16:40:37 -0000 Add compound controls support to the ControlValue class. The polymorphic class can now store more than a single element and supports access and creation through the use of Span<>. Signed-off-by: Jacopo Mondi --- include/libcamera/controls.h | 37 +++- src/libcamera/controls.cpp | 329 ++++++++++++++++++++++++++++++++--- 2 files changed, 333 insertions(+), 33 deletions(-) diff --git a/include/libcamera/controls.h b/include/libcamera/controls.h index 8fa33d93b088..bdbdb213528d 100644 --- a/include/libcamera/controls.h +++ b/include/libcamera/controls.h @@ -11,6 +11,8 @@ #include #include +#include + namespace libcamera { class ControlValidator; @@ -21,6 +23,10 @@ enum ControlType { ControlTypeInteger32, ControlTypeInteger64, ControlTypeFloat, + ControlTypeCompoundBool, + ControlTypeCompoundInt32, + ControlTypeCompoundInt64, + ControlTypeCompoundFloat, }; class ControlValue @@ -31,12 +37,18 @@ public: ControlValue(int32_t value); ControlValue(int64_t value); ControlValue(float value); + ControlValue(Span &values); + ControlValue(Span &values); + ControlValue(Span &values); + ControlValue(Span &values); + ~ControlValue(); ControlType type() const { return type_; } bool isNone() const { return type_ == ControlTypeNone; } + std::size_t numElements() const { return numElements_; } template - const T &get() const; + T get() const; template void set(const T &value); @@ -57,6 +69,21 @@ private: int64_t integer64_; float float_; }; + + union { + void *pvoid_; + bool *pbool_; + int32_t *p32_; + int64_t *p64_; + float *pfloat_; + }; + + std::size_t numElements_; + + void release(); + bool compareElement(const ControlValue &other) const; + bool compareElement(const ControlValue &other, unsigned int i) const; + std::string elemToString(unsigned int i) const; }; class ControlId @@ -215,13 +242,11 @@ public: bool contains(unsigned int id) const; template - const T &get(const Control &ctrl) const + const T get(const Control &ctrl) const { const ControlValue *val = find(ctrl.id()); - if (!val) { - static T t(0); - return t; - } + if (!val) + return T{}; return val->get(); } diff --git a/src/libcamera/controls.cpp b/src/libcamera/controls.cpp index 74ce5d0ba4f1..7718a53911e6 100644 --- a/src/libcamera/controls.cpp +++ b/src/libcamera/controls.cpp @@ -9,7 +9,9 @@ #include #include -#include +#include + +#include #include "control_validator.h" #include "log.h" @@ -60,6 +62,14 @@ LOG_DEFINE_CATEGORY(Controls) * The control stores a 64-bit integer value * \var ControlTypeFloat * The control stores a 32-bit floating point value + * \var ControlTypeCompoundBool + * The control stores an array of boolean values + * \var ControlTypeCompoundInt32 + * The control stores an array of 32-bit integer values + * \var ControlTypeCompoundInt64 + * The control stores an array of 64-bit integer values + * \var ControlTypeCompoundFloat + * The control stores an array of 32-bit floating values */ /** @@ -71,7 +81,7 @@ LOG_DEFINE_CATEGORY(Controls) * \brief Construct an empty ControlValue. */ ControlValue::ControlValue() - : type_(ControlTypeNone) + : type_(ControlTypeNone), pvoid_(nullptr), numElements_(0) { } @@ -80,7 +90,8 @@ ControlValue::ControlValue() * \param[in] value Boolean value to store */ ControlValue::ControlValue(bool value) - : type_(ControlTypeBool), bool_(value) + : type_(ControlTypeBool), bool_(value), pvoid_(nullptr), + numElements_(1) { } @@ -89,7 +100,8 @@ ControlValue::ControlValue(bool value) * \param[in] value Integer value to store */ ControlValue::ControlValue(int32_t value) - : type_(ControlTypeInteger32), integer32_(value) + : type_(ControlTypeInteger32), integer32_(value), pvoid_(nullptr), + numElements_(1) { } @@ -98,7 +110,8 @@ ControlValue::ControlValue(int32_t value) * \param[in] value Integer value to store */ ControlValue::ControlValue(int64_t value) - : type_(ControlTypeInteger64), integer64_(value) + : type_(ControlTypeInteger64), integer64_(value), pvoid_(nullptr), + numElements_(1) { } @@ -107,8 +120,73 @@ ControlValue::ControlValue(int64_t value) * \param[in] value Float value to store */ ControlValue::ControlValue(float value) - : type_(ControlTypeFloat), float_(value) + : type_(ControlTypeFloat), float_(value), pvoid_(nullptr), + numElements_(1) +{ +} + +/** + * \brief Construct a ControlValue with a Span of boolean elements + * \param[in] values Span of boolean values to store + */ +ControlValue::ControlValue(Span &values) + : type_(ControlTypeCompoundBool), numElements_(values.size()) { + pbool_ = new bool[numElements_]; + memcpy(pbool_, values.data(), sizeof(bool) * numElements_); +} + +/** + * \brief Construct a ControlValue with a Span of 32 bit integers elements + * \param[in] values Span of 32 bit integer values to store + */ +ControlValue::ControlValue(Span &values) + : type_(ControlTypeCompoundInt32), numElements_(values.size()) +{ + p32_ = new int32_t[numElements_]; + memcpy(p32_, values.data(), sizeof(int32_t) * numElements_); +} + +/** + * \brief Construct a ControlValue with a Span of 64 bit integers elements + * \param[in] values Span of 64 bit integer values to store + */ +ControlValue::ControlValue(Span &values) + : type_(ControlTypeCompoundInt64), numElements_(values.size()) +{ + p64_ = new int64_t[numElements_]; + memcpy(p64_, values.data(), sizeof(int64_t) * numElements_); +} + +/** + * \brief Construct a ControlValue with a Span of float elements + * \param[in] values Span of float values to store + */ +ControlValue::ControlValue(Span &values) + : type_(ControlTypeCompoundFloat), numElements_(values.size()) +{ + pfloat_ = new float[numElements_]; + memcpy(pfloat_, values.data(), sizeof(float) * numElements_); +} + +void ControlValue::release() +{ + switch (type_) { + case ControlTypeCompoundBool: + case ControlTypeCompoundInt32: + case ControlTypeCompoundInt64: + case ControlTypeCompoundFloat: + delete[] pbool_; + pbool_ = nullptr; + /* fall-through. */ + default: + return; + } +} + +ControlValue::~ControlValue() +{ + release(); } /** @@ -124,24 +202,38 @@ ControlValue::ControlValue(float value) */ /** - * \fn template const T &ControlValue::get() const - * \brief Get the control value + * \fn ControlValue::numElements() + * \brief Retrieve the number of elements stored in the ControlValue + * \return The number of elements stored in the ControlValue + */ + +/** + * \fn template const T ControlValue::get() const + * \brief Get the control values * * The control value type shall match the type T, otherwise the behaviour is * undefined. * - * \return The control value + * This function applies to ControlValue instances which store a single or + * multiple values. The ControlValue's elements are returned in a Span in the + * former case. + * + * \return The control value or a Span of values */ /** - * \fn template void ControlValue::set(const T &value) - * \brief Set the control value to \a value - * \param[in] value The control value + * \fn template void ControlValue::set(const T &values) + * \brief Set the control values to \a values + * \param[in] values The control values + * + * This function can be used to set the ControlValue to a single value, or + * to store multiple values by providing a Span<> of elements to the + * function. */ #ifndef __DOXYGEN__ template<> -const bool &ControlValue::get() const +bool ControlValue::get() const { ASSERT(type_ == ControlTypeBool); @@ -149,7 +241,19 @@ const bool &ControlValue::get() const } template<> -const int32_t &ControlValue::get() const +Span ControlValue::get>() const +{ + ASSERT(type_ == ControlTypeCompoundBool); + + /* + * Explicitly create a Span instance, otherwise the compiler + * tries to match with the Span class initializer_list constructor. + */ + return Span(pbool_, static_cast(numElements_)); +} + +template<> +int32_t ControlValue::get() const { ASSERT(type_ == ControlTypeInteger32 || type_ == ControlTypeInteger64); @@ -157,7 +261,16 @@ const int32_t &ControlValue::get() const } template<> -const int64_t &ControlValue::get() const +Span ControlValue::get>() const +{ + ASSERT(type_ == ControlTypeCompoundInt32 || + type_ == ControlTypeCompoundInt64); + + return { p32_, numElements_ }; +} + +template<> +int64_t ControlValue::get() const { ASSERT(type_ == ControlTypeInteger32 || type_ == ControlTypeInteger64); @@ -165,62 +278,190 @@ const int64_t &ControlValue::get() const } template<> -const float &ControlValue::get() const +Span ControlValue::get>() const +{ + ASSERT(type_ == ControlTypeCompoundInt32 || + type_ == ControlTypeCompoundInt64); + + return { p64_, numElements_ }; +} + +template<> +float ControlValue::get() const { ASSERT(type_ == ControlTypeFloat); return float_; } +template<> +Span ControlValue::get>() const +{ + ASSERT(type_ == ControlTypeCompoundFloat); + + return { pfloat_, numElements_ }; +} + template<> void ControlValue::set(const bool &value) { + release(); + type_ = ControlTypeBool; bool_ = value; + numElements_ = 1; +} + +template<> +void ControlValue::set>(const Span &values) +{ + release(); + + type_ = ControlTypeCompoundBool; + numElements_ = values.size(); + + pbool_ = new bool[numElements_]; + memcpy(pbool_, values.data(), sizeof(bool) * numElements_); } template<> void ControlValue::set(const int32_t &value) { + release(); + type_ = ControlTypeInteger32; integer32_ = value; + numElements_ = 1; +} + +template<> +void ControlValue::set>(const Span &values) +{ + release(); + + type_ = ControlTypeCompoundInt32; + numElements_ = values.size(); + + p32_ = new int32_t[numElements_]; + memcpy(p32_, values.data(), sizeof(int32_t) * numElements_); } template<> void ControlValue::set(const int64_t &value) { + release(); + type_ = ControlTypeInteger64; integer64_ = value; + numElements_ = 1; +} + +template<> +void ControlValue::set>(const Span &values) +{ + release(); + + type_ = ControlTypeCompoundInt64; + numElements_ = values.size(); + + p64_ = new int64_t[numElements_]; + memcpy(p64_, values.data(), sizeof(int64_t) * numElements_); } template<> void ControlValue::set(const float &value) { + release(); + type_ = ControlTypeFloat; float_ = value; + numElements_ = 1; } + +template<> +void ControlValue::set>(const Span &values) +{ + release(); + + type_ = ControlTypeCompoundFloat; + numElements_ = values.size(); + + pfloat_ = new float[numElements_]; + memcpy(pfloat_, values.data(), sizeof(float) * numElements_); +} + #endif /* __DOXYGEN__ */ +std::string ControlValue::elemToString(unsigned int i) const +{ + switch (type_) { + case ControlTypeBool: + return bool_ ? "True " : "False "; + case ControlTypeInteger32: + return std::to_string(integer32_); + case ControlTypeInteger64: + return std::to_string(integer64_); + case ControlTypeFloat: + return std::to_string(float_); + case ControlTypeCompoundBool: + return pbool_[i] ? "True " : "False "; + case ControlTypeCompoundInt32: + return std::to_string(p32_[i]) + " "; + case ControlTypeCompoundInt64: + return std::to_string(p64_[i]) + " "; + case ControlTypeCompoundFloat: + return std::to_string(pfloat_[i]) + " "; + default: + return ""; + } +} + /** * \brief Assemble and return a string describing the value * \return A string describing the ControlValue */ std::string ControlValue::toString() const +{ + if (ControlTypeNone) + return ""; + + std::string str; + for (unsigned int i = 0; i < numElements_; ++i) + str += elemToString(i); + + return str; +} + +bool ControlValue::compareElement(const ControlValue &other) const { switch (type_) { - case ControlTypeNone: - return ""; case ControlTypeBool: - return bool_ ? "True" : "False"; + return bool_ == other.bool_; case ControlTypeInteger32: - return std::to_string(integer32_); + return integer32_ == other.integer32_; case ControlTypeInteger64: - return std::to_string(integer64_); + return integer64_ == other.integer64_; case ControlTypeFloat: - return std::to_string(float_); + return float_ == other.float_; + default: + return false; } +} - return ""; +bool ControlValue::compareElement(const ControlValue &other, unsigned int i) const +{ + switch (type_) { + case ControlTypeCompoundBool: + return pbool_[i] == other.pbool_[i]; + case ControlTypeCompoundInt32: + return p32_[i] == other.p32_[i]; + case ControlTypeCompoundInt64: + return p64_[i] == other.p64_[i]; + case ControlTypeCompoundFloat: + return pfloat_[i] == other.pfloat_[i]; + default: + return false; + } } /** @@ -232,15 +473,25 @@ bool ControlValue::operator==(const ControlValue &other) const if (type_ != other.type_) return false; + if (numElements_ != other.numElements()) + return false; + switch (type_) { case ControlTypeBool: - return bool_ == other.bool_; case ControlTypeInteger32: - return integer32_ == other.integer32_; case ControlTypeInteger64: - return integer64_ == other.integer64_; case ControlTypeFloat: - return float_ == other.float_; + return compareElement(other); + case ControlTypeCompoundBool: + case ControlTypeCompoundInt32: + case ControlTypeCompoundInt64: + case ControlTypeCompoundFloat: + for (unsigned int i = 0; i < numElements_; ++i) { + if (!compareElement(other, i)) + return false; + } + + return true; default: return false; } @@ -360,23 +611,47 @@ Control::Control(unsigned int id, const char *name) { } +template<> +Control>::Control(unsigned int id, const char *name) + : ControlId(id, name, ControlTypeCompoundBool) +{ +} + template<> Control::Control(unsigned int id, const char *name) : ControlId(id, name, ControlTypeInteger32) { } +template<> +Control>::Control(unsigned int id, const char *name) + : ControlId(id, name, ControlTypeCompoundInt32) +{ +} + template<> Control::Control(unsigned int id, const char *name) : ControlId(id, name, ControlTypeInteger64) { } +template<> +Control>::Control(unsigned int id, const char *name) + : ControlId(id, name, ControlTypeCompoundInt64) +{ +} + template<> Control::Control(unsigned int id, const char *name) : ControlId(id, name, ControlTypeFloat) { } + +template<> +Control>::Control(unsigned int id, const char *name) + : ControlId(id, name, ControlTypeCompoundFloat) +{ +} #endif /* __DOXYGEN__ */ /** From patchwork Mon Jan 13 16:42:38 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 2631 Return-Path: Received: from relay11.mail.gandi.net (relay11.mail.gandi.net [217.70.178.231]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id CE5A060703 for ; Mon, 13 Jan 2020 17:40:36 +0100 (CET) Received: from uno.lan (2-224-242-101.ip172.fastwebnet.it [2.224.242.101]) (Authenticated sender: jacopo@jmondi.org) by relay11.mail.gandi.net (Postfix) with ESMTPSA id 247AA100005; Mon, 13 Jan 2020 16:40:35 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Mon, 13 Jan 2020 17:42:38 +0100 Message-Id: <20200113164245.52535-17-jacopo@jmondi.org> X-Mailer: git-send-email 2.24.0 In-Reply-To: <20200113164245.52535-1-jacopo@jmondi.org> References: <20200113164245.52535-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 16/23] libcamera: controls: Don't convert 32-bit and 64-bit implicitly 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: , X-List-Received-Date: Mon, 13 Jan 2020 16:40:37 -0000 From: Laurent Pinchart The ControlValue::get() method verifies that the T type corresponds to the ControlValue type. It however accepts int32_t as a return type for 64-bit integer controls, and int64_t as a return type for 32-bit integer controls. There's no reason to do so anymore, make the type check stricter. Reviewed-by: Jacopo Mondi Signed-off-by: Laurent Pinchart --- src/libcamera/controls.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libcamera/controls.cpp b/src/libcamera/controls.cpp index 7718a53911e6..c311ab1d6af1 100644 --- a/src/libcamera/controls.cpp +++ b/src/libcamera/controls.cpp @@ -255,7 +255,7 @@ Span ControlValue::get>() const template<> int32_t ControlValue::get() const { - ASSERT(type_ == ControlTypeInteger32 || type_ == ControlTypeInteger64); + ASSERT(type_ == ControlTypeInteger32); return integer32_; } @@ -272,7 +272,7 @@ Span ControlValue::get>() const template<> int64_t ControlValue::get() const { - ASSERT(type_ == ControlTypeInteger32 || type_ == ControlTypeInteger64); + ASSERT(type_ == ControlTypeInteger64); return integer64_; } From patchwork Mon Jan 13 16:42:39 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 2632 X-Patchwork-Delegate: jacopo@jmondi.org Return-Path: Received: from relay11.mail.gandi.net (relay11.mail.gandi.net [217.70.178.231]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 66A9F60703 for ; Mon, 13 Jan 2020 17:40:37 +0100 (CET) Received: from uno.lan (2-224-242-101.ip172.fastwebnet.it [2.224.242.101]) (Authenticated sender: jacopo@jmondi.org) by relay11.mail.gandi.net (Postfix) with ESMTPSA id 0428710000E; Mon, 13 Jan 2020 16:40:36 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Mon, 13 Jan 2020 17:42:39 +0100 Message-Id: <20200113164245.52535-18-jacopo@jmondi.org> X-Mailer: git-send-email 2.24.0 In-Reply-To: <20200113164245.52535-1-jacopo@jmondi.org> References: <20200113164245.52535-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 17/23] libcamera: control: Deep-copy control values 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: , X-List-Received-Date: Mon, 13 Jan 2020 16:40:37 -0000 Implement operator=() and copy constructor for the ControlValue class, deep-copying the content of the 'other' ControlValue by using ControlValue::set() operation which, in case of compound ControlValue, guarantees proper memory allocation and data copy. Signed-off-by: Jacopo Mondi --- include/libcamera/controls.h | 5 +++ src/libcamera/controls.cpp | 62 ++++++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+) diff --git a/include/libcamera/controls.h b/include/libcamera/controls.h index bdbdb213528d..d13144b69198 100644 --- a/include/libcamera/controls.h +++ b/include/libcamera/controls.h @@ -43,6 +43,9 @@ public: ControlValue(Span &values); ~ControlValue(); + ControlValue(const ControlValue &other); + ControlValue &operator=(const ControlValue &other); + ControlType type() const { return type_; } bool isNone() const { return type_ == ControlTypeNone; } std::size_t numElements() const { return numElements_; } @@ -81,6 +84,8 @@ private: std::size_t numElements_; void release(); + template + void copyValue(const ControlValue &source); bool compareElement(const ControlValue &other) const; bool compareElement(const ControlValue &other, unsigned int i) const; std::string elemToString(unsigned int i) const; diff --git a/src/libcamera/controls.cpp b/src/libcamera/controls.cpp index c311ab1d6af1..fd04d2311db3 100644 --- a/src/libcamera/controls.cpp +++ b/src/libcamera/controls.cpp @@ -189,6 +189,68 @@ ControlValue::~ControlValue() release(); } +template +void ControlValue::copyValue(const ControlValue &other) +{ + set(other.get()); +} + +/** + * \brief Contruct a ControlValue with the content of \a other + * \param[in] other The ControlValue to copy content from + */ +ControlValue::ControlValue(const ControlValue &other) +{ + *this = other; +} + +/** + * \brief Replace the content of the ControlValue with the one of \a other + * \param[in] other The ControlValue to copy content from + * + * Deep-copy the content of \a other into the ControlValue by reserving memory + * and copy data there in case \a other transports arrays of values in one of + * its pointer data members. + * + * \return The ControlValue with its content replaced with the one of \a other + */ +ControlValue &ControlValue::operator=(const ControlValue &other) +{ + switch (other.type_) { + case ControlTypeBool: + copyValue(other); + break; + case ControlTypeInteger32: + copyValue(other); + break; + case ControlTypeInteger64: + copyValue(other); + break; + case ControlTypeFloat: + copyValue(other); + break; + case ControlTypeCompoundBool: + copyValue>(other); + break; + case ControlTypeCompoundInt32: + copyValue>(other); + break; + case ControlTypeCompoundInt64: + copyValue>(other); + break; + case ControlTypeCompoundFloat: + copyValue>(other); + break; + default: + break; + } + + type_ = other.type_; + numElements_ = other.numElements_; + + return *this; +} + /** * \fn ControlValue::type() * \brief Retrieve the data type of the value From patchwork Mon Jan 13 16:42:40 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 2633 X-Patchwork-Delegate: jacopo@jmondi.org Return-Path: Received: from relay11.mail.gandi.net (relay11.mail.gandi.net [217.70.178.231]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id EF23260703 for ; Mon, 13 Jan 2020 17:40:37 +0100 (CET) Received: from uno.lan (2-224-242-101.ip172.fastwebnet.it [2.224.242.101]) (Authenticated sender: jacopo@jmondi.org) by relay11.mail.gandi.net (Postfix) with ESMTPSA id 8CA03100005; Mon, 13 Jan 2020 16:40:37 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Mon, 13 Jan 2020 17:42:40 +0100 Message-Id: <20200113164245.52535-19-jacopo@jmondi.org> X-Mailer: git-send-email 2.24.0 In-Reply-To: <20200113164245.52535-1-jacopo@jmondi.org> References: <20200113164245.52535-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 18/23] libcamera: controls: Re-oder ControlValue methods 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: , X-List-Received-Date: Mon, 13 Jan 2020 16:40:38 -0000 Re-order operation in ControlValue class to group const methods together. Cosmetic change only. Signed-off-by: Jacopo Mondi --- include/libcamera/controls.h | 10 +- src/libcamera/controls.cpp | 222 +++++++++++++++++------------------ 2 files changed, 116 insertions(+), 116 deletions(-) diff --git a/include/libcamera/controls.h b/include/libcamera/controls.h index d13144b69198..9343a947764b 100644 --- a/include/libcamera/controls.h +++ b/include/libcamera/controls.h @@ -50,11 +50,6 @@ public: bool isNone() const { return type_ == ControlTypeNone; } std::size_t numElements() const { return numElements_; } - template - T get() const; - template - void set(const T &value); - std::string toString() const; bool operator==(const ControlValue &other) const; @@ -63,6 +58,11 @@ public: return !(*this == other); } + template + T get() const; + template + void set(const T &value); + private: ControlType type_; diff --git a/src/libcamera/controls.cpp b/src/libcamera/controls.cpp index fd04d2311db3..750c36bd011e 100644 --- a/src/libcamera/controls.cpp +++ b/src/libcamera/controls.cpp @@ -269,6 +269,117 @@ ControlValue &ControlValue::operator=(const ControlValue &other) * \return The number of elements stored in the ControlValue */ +std::string ControlValue::elemToString(unsigned int i) const +{ + switch (type_) { + case ControlTypeBool: + return bool_ ? "True " : "False "; + case ControlTypeInteger32: + return std::to_string(integer32_); + case ControlTypeInteger64: + return std::to_string(integer64_); + case ControlTypeFloat: + return std::to_string(float_); + case ControlTypeCompoundBool: + return pbool_[i] ? "True " : "False "; + case ControlTypeCompoundInt32: + return std::to_string(p32_[i]) + " "; + case ControlTypeCompoundInt64: + return std::to_string(p64_[i]) + " "; + case ControlTypeCompoundFloat: + return std::to_string(pfloat_[i]) + " "; + default: + return ""; + } +} + +/** + * \brief Assemble and return a string describing the value + * \return A string describing the ControlValue + */ +std::string ControlValue::toString() const +{ + if (ControlTypeNone) + return ""; + + std::string str; + for (unsigned int i = 0; i < numElements_; ++i) + str += elemToString(i); + + return str; +} + +bool ControlValue::compareElement(const ControlValue &other) const +{ + switch (type_) { + case ControlTypeBool: + return bool_ == other.bool_; + case ControlTypeInteger32: + return integer32_ == other.integer32_; + case ControlTypeInteger64: + return integer64_ == other.integer64_; + case ControlTypeFloat: + return float_ == other.float_; + default: + return false; + } +} + +bool ControlValue::compareElement(const ControlValue &other, unsigned int i) const +{ + switch (type_) { + case ControlTypeCompoundBool: + return pbool_[i] == other.pbool_[i]; + case ControlTypeCompoundInt32: + return p32_[i] == other.p32_[i]; + case ControlTypeCompoundInt64: + return p64_[i] == other.p64_[i]; + case ControlTypeCompoundFloat: + return pfloat_[i] == other.pfloat_[i]; + default: + return false; + } +} + +/** + * \brief Compare ControlValue instances for equality + * \return True if the values have identical types and values, false otherwise + */ +bool ControlValue::operator==(const ControlValue &other) const +{ + if (type_ != other.type_) + return false; + + if (numElements_ != other.numElements()) + return false; + + switch (type_) { + case ControlTypeBool: + case ControlTypeInteger32: + case ControlTypeInteger64: + case ControlTypeFloat: + return compareElement(other); + case ControlTypeCompoundBool: + case ControlTypeCompoundInt32: + case ControlTypeCompoundInt64: + case ControlTypeCompoundFloat: + for (unsigned int i = 0; i < numElements_; ++i) { + if (!compareElement(other, i)) + return false; + } + + return true; + default: + return false; + } +} + +/** + * \fn bool ControlValue::operator!=() + * \brief Compare ControlValue instances for non equality + * \return False if the values have identical types and values, true otherwise + */ + /** * \fn template const T ControlValue::get() const * \brief Get the control values @@ -454,117 +565,6 @@ void ControlValue::set>(const Span &values) #endif /* __DOXYGEN__ */ -std::string ControlValue::elemToString(unsigned int i) const -{ - switch (type_) { - case ControlTypeBool: - return bool_ ? "True " : "False "; - case ControlTypeInteger32: - return std::to_string(integer32_); - case ControlTypeInteger64: - return std::to_string(integer64_); - case ControlTypeFloat: - return std::to_string(float_); - case ControlTypeCompoundBool: - return pbool_[i] ? "True " : "False "; - case ControlTypeCompoundInt32: - return std::to_string(p32_[i]) + " "; - case ControlTypeCompoundInt64: - return std::to_string(p64_[i]) + " "; - case ControlTypeCompoundFloat: - return std::to_string(pfloat_[i]) + " "; - default: - return ""; - } -} - -/** - * \brief Assemble and return a string describing the value - * \return A string describing the ControlValue - */ -std::string ControlValue::toString() const -{ - if (ControlTypeNone) - return ""; - - std::string str; - for (unsigned int i = 0; i < numElements_; ++i) - str += elemToString(i); - - return str; -} - -bool ControlValue::compareElement(const ControlValue &other) const -{ - switch (type_) { - case ControlTypeBool: - return bool_ == other.bool_; - case ControlTypeInteger32: - return integer32_ == other.integer32_; - case ControlTypeInteger64: - return integer64_ == other.integer64_; - case ControlTypeFloat: - return float_ == other.float_; - default: - return false; - } -} - -bool ControlValue::compareElement(const ControlValue &other, unsigned int i) const -{ - switch (type_) { - case ControlTypeCompoundBool: - return pbool_[i] == other.pbool_[i]; - case ControlTypeCompoundInt32: - return p32_[i] == other.p32_[i]; - case ControlTypeCompoundInt64: - return p64_[i] == other.p64_[i]; - case ControlTypeCompoundFloat: - return pfloat_[i] == other.pfloat_[i]; - default: - return false; - } -} - -/** - * \brief Compare ControlValue instances for equality - * \return True if the values have identical types and values, false otherwise - */ -bool ControlValue::operator==(const ControlValue &other) const -{ - if (type_ != other.type_) - return false; - - if (numElements_ != other.numElements()) - return false; - - switch (type_) { - case ControlTypeBool: - case ControlTypeInteger32: - case ControlTypeInteger64: - case ControlTypeFloat: - return compareElement(other); - case ControlTypeCompoundBool: - case ControlTypeCompoundInt32: - case ControlTypeCompoundInt64: - case ControlTypeCompoundFloat: - for (unsigned int i = 0; i < numElements_; ++i) { - if (!compareElement(other, i)) - return false; - } - - return true; - default: - return false; - } -} - -/** - * \fn bool ControlValue::operator!=() - * \brief Compare ControlValue instances for non equality - * \return False if the values have identical types and values, true otherwise - */ - /** * \class ControlId * \brief Control static metadata From patchwork Mon Jan 13 16:42:41 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 2634 X-Patchwork-Delegate: jacopo@jmondi.org Return-Path: Received: from relay11.mail.gandi.net (relay11.mail.gandi.net [217.70.178.231]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 88C93606FE for ; Mon, 13 Jan 2020 17:40:38 +0100 (CET) Received: from uno.lan (2-224-242-101.ip172.fastwebnet.it [2.224.242.101]) (Authenticated sender: jacopo@jmondi.org) by relay11.mail.gandi.net (Postfix) with ESMTPSA id 259E4100005; Mon, 13 Jan 2020 16:40:37 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Mon, 13 Jan 2020 17:42:41 +0100 Message-Id: <20200113164245.52535-20-jacopo@jmondi.org> X-Mailer: git-send-email 2.24.0 In-Reply-To: <20200113164245.52535-1-jacopo@jmondi.org> References: <20200113164245.52535-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 19/23] libcamera: controls: Validate compound controls range 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: , X-List-Received-Date: Mon, 13 Jan 2020 16:40:38 -0000 The type of a ControlRnge associated with a Control<> is different from the type of the Control<> itself if the control is a compound. Add a function to help validation of the two types during ControlInfoMap idmap generation. Signed-off-by: Jacopo Mondi --- include/libcamera/controls.h | 1 + src/libcamera/controls.cpp | 32 +++++++++++++++++++++++++++++++- 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/include/libcamera/controls.h b/include/libcamera/controls.h index 9343a947764b..a3ac2b8c5447 100644 --- a/include/libcamera/controls.h +++ b/include/libcamera/controls.h @@ -217,6 +217,7 @@ public: private: void generateIdmap(); + bool validateRange(const ControlId *control, const ControlRange range); ControlIdMap idmap_; }; diff --git a/src/libcamera/controls.cpp b/src/libcamera/controls.cpp index 750c36bd011e..71075ade4577 100644 --- a/src/libcamera/controls.cpp +++ b/src/libcamera/controls.cpp @@ -940,6 +940,36 @@ ControlInfoMap::const_iterator ControlInfoMap::find(unsigned int id) const return find(iter->second); } +bool ControlInfoMap::validateRange(const ControlId *control, + const ControlRange range) +{ + ControlType controlType = control->type(); + ControlType rangeType = range.min().type(); + + /* + * Validate the control type against its associated range type, + * regardless it being a compound control or not. + */ + switch (controlType) { + case ControlTypeBool: + case ControlTypeCompoundBool: + return rangeType == ControlTypeBool; + case ControlTypeInteger32: + case ControlTypeCompoundInt32: + return (rangeType == ControlTypeInteger32 || + rangeType == ControlTypeInteger64); + case ControlTypeInteger64: + case ControlTypeCompoundInt64: + return (rangeType == ControlTypeInteger64 || + rangeType == ControlTypeInteger32); + case ControlTypeFloat: + case ControlTypeCompoundFloat: + return rangeType == ControlTypeFloat; + default: + return false; + } +} + /** * \fn const ControlIdMap &ControlInfoMap::idmap() const * \brief Retrieve the ControlId map @@ -956,7 +986,7 @@ void ControlInfoMap::generateIdmap() idmap_.clear(); for (const auto &ctrl : *this) { - if (ctrl.first->type() != ctrl.second.min().type()) { + if (!validateRange(ctrl.first, ctrl.second)) { LOG(Controls, Error) << "Control " << utils::hex(ctrl.first->id()) << " type and range type mismatch"; From patchwork Mon Jan 13 16:42:42 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 2635 X-Patchwork-Delegate: jacopo@jmondi.org Return-Path: Received: from relay11.mail.gandi.net (relay11.mail.gandi.net [217.70.178.231]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 69CC66073E for ; Mon, 13 Jan 2020 17:40:39 +0100 (CET) Received: from uno.lan (2-224-242-101.ip172.fastwebnet.it [2.224.242.101]) (Authenticated sender: jacopo@jmondi.org) by relay11.mail.gandi.net (Postfix) with ESMTPSA id C508A100011; Mon, 13 Jan 2020 16:40:38 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Mon, 13 Jan 2020 17:42:42 +0100 Message-Id: <20200113164245.52535-21-jacopo@jmondi.org> X-Mailer: git-send-email 2.24.0 In-Reply-To: <20200113164245.52535-1-jacopo@jmondi.org> References: <20200113164245.52535-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 20/23] DNI: test compound controls 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: , X-List-Received-Date: Mon, 13 Jan 2020 16:40:41 -0000 Define a fictional compound control and register it in the VIMC pipeline handler. Add a test to exercize it. Do not include, just a proof of concept. The test could be included once we'll have real compound controls defined. Signed-off-by: Laurent Pinchart Signed-off-by: Jacopo Mondi --- src/libcamera/control_ids.yaml | 5 ++ src/libcamera/pipeline/vimc.cpp | 5 ++ test/controls/compound_controls.cpp | 71 +++++++++++++++++++++++++++++ test/controls/meson.build | 1 + 4 files changed, 82 insertions(+) create mode 100644 test/controls/compound_controls.cpp diff --git a/src/libcamera/control_ids.yaml b/src/libcamera/control_ids.yaml index 4befec746a59..1bdece651638 100644 --- a/src/libcamera/control_ids.yaml +++ b/src/libcamera/control_ids.yaml @@ -50,4 +50,9 @@ controls: type: int32_t description: Specify a fixed gain parameter + - CompoundControl: + type: int32_t + description: A fictional compound control + compound: true + ... diff --git a/src/libcamera/pipeline/vimc.cpp b/src/libcamera/pipeline/vimc.cpp index 2df5447177fa..2bcb9f2248e6 100644 --- a/src/libcamera/pipeline/vimc.cpp +++ b/src/libcamera/pipeline/vimc.cpp @@ -453,6 +453,11 @@ int VimcCameraData::init(MediaDevice *media) std::forward_as_tuple(range)); } + /* Register a compound control. */ + ctrls.emplace(std::piecewise_construct, + std::forward_as_tuple(&controls::CompoundControl), + std::forward_as_tuple(0, 100)); + controlInfo_ = std::move(ctrls); /* Initialize the camera properties. */ diff --git a/test/controls/compound_controls.cpp b/test/controls/compound_controls.cpp new file mode 100644 index 000000000000..96d3d9204c74 --- /dev/null +++ b/test/controls/compound_controls.cpp @@ -0,0 +1,71 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2019, Google Inc. + * + * compound_controls.cpp - CompoundControls test + */ + +#include +#include + +#include +#include +#include +#include +#include + +#include "camera_controls.h" + +#include "camera_test.h" +#include "test.h" + +using namespace std; +using namespace libcamera; + +class CompoundControlsTest : public CameraTest, public Test +{ +public: + CompoundControlsTest() + : CameraTest("VIMC Sensor B") + { + } + +protected: + int init() override + { + return status_; + } + + int run() override + { + CameraControlValidator validator(camera_.get()); + ControlList list(controls::controls, &validator); + + /* + * Span + * + * A Span can be initialized with an initializer list + * and sequentially or random accessed + */ + std::array array = { 1, 2, 3 }; + Span span{ array }; + for (uint32_t i : span) + cout << i << endl; + cout << span[0] << endl; + + /* + * Compound Controls: can be set with a span of values + */ + std::vector values = { 0, 125, 253 }; + list.set(controls::CompoundControl, Span{ values }); + Span iSpan = list.get(controls::CompoundControl); + + cout << iSpan.size() << endl; + for (uint32_t i : iSpan) + cout << i << endl; + + return TestPass; + } +}; + +TEST_REGISTER(CompoundControlsTest) diff --git a/test/controls/meson.build b/test/controls/meson.build index f0850df28c8a..f4752dcff33b 100644 --- a/test/controls/meson.build +++ b/test/controls/meson.build @@ -3,6 +3,7 @@ control_tests = [ [ 'control_list', 'control_list.cpp' ], [ 'control_range', 'control_range.cpp' ], [ 'control_value', 'control_value.cpp' ], + [ 'compound_controls', 'compound_controls.cpp'], ] foreach t : control_tests From patchwork Mon Jan 13 16:42:43 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 2637 X-Patchwork-Delegate: jacopo@jmondi.org Return-Path: Received: from relay11.mail.gandi.net (relay11.mail.gandi.net [217.70.178.231]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 0C0F36074A for ; Mon, 13 Jan 2020 17:40:40 +0100 (CET) Received: from uno.lan (2-224-242-101.ip172.fastwebnet.it [2.224.242.101]) (Authenticated sender: jacopo@jmondi.org) by relay11.mail.gandi.net (Postfix) with ESMTPSA id 92526100005; Mon, 13 Jan 2020 16:40:39 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Mon, 13 Jan 2020 17:42:43 +0100 Message-Id: <20200113164245.52535-22-jacopo@jmondi.org> X-Mailer: git-send-email 2.24.0 In-Reply-To: <20200113164245.52535-1-jacopo@jmondi.org> References: <20200113164245.52535-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 21/23] libcamera: byte_stream_buffer: Support span<> 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: , X-List-Received-Date: Mon, 13 Jan 2020 16:40:42 -0000 Add support to write and read span<> of data to the ByteStreamBuffer class. Signed-off-by: Jacopo Mondi --- src/libcamera/byte_stream_buffer.cpp | 31 ++++++++++++++++++++-- src/libcamera/include/byte_stream_buffer.h | 14 ++++++++++ 2 files changed, 43 insertions(+), 2 deletions(-) diff --git a/src/libcamera/byte_stream_buffer.cpp b/src/libcamera/byte_stream_buffer.cpp index 23d624dd0a06..9fb14508722f 100644 --- a/src/libcamera/byte_stream_buffer.cpp +++ b/src/libcamera/byte_stream_buffer.cpp @@ -225,22 +225,49 @@ int ByteStreamBuffer::skip(size_t size) /** * \fn template int ByteStreamBuffer::read(T *t) - * \brief Read \a size \a data from the managed memory buffer + * \brief Read data from the managed memory buffer into \a t * \param[out] t Pointer to the memory containing the read data * \return 0 on success, a negative error code otherwise * \retval -EACCES attempting to read from a write buffer * \retval -ENOSPC no more space is available in the managed memory buffer */ +/** + * \fn template int ByteStreamBuffer::read(Span *t) + * \brief Read a sequence of data from the managed memory buffer into span \a t + * \param[out] t Pointer to an intialized span where to read data + * + * This function reads data from managed memory and writes it to an initialized + * memory location represented by the span \a t. + * + * The provided span \a t should be initialized with a memory area large + * enough to contain the read data. This function does not perform any + * memory allocation or initialization in the span \a t. It is responsibility of + * the caller to do so. + * + * \return 0 on success, a negative error code otherwise + * \retval -EACCES attempting to read from a write buffer + * \retval -ENOSPC no more space is available in the managed memory buffer + */ + /** * \fn template int ByteStreamBuffer::write(const T *t) - * \brief Write \a data of \a size to the managed memory buffer + * \brief Write \a t to the managed memory buffer * \param[in] t The data to write to memory * \return 0 on success, a negative error code otherwise * \retval -EACCES attempting to write to a read buffer * \retval -ENOSPC no more space is available in the managed memory buffer */ +/** + * \fn template int ByteStreamBuffer::write(const Span &t) + * \brief Write a span of data \a t to the managed memory buffer + * \param[in] t The span of data to write to memory + * \return 0 on success, a negative error code otherwise + * \retval -EACCES attempting to write to a read buffer + * \retval -ENOSPC no more space is available in the managed memory buffer + */ + int ByteStreamBuffer::read(uint8_t *data, size_t size) { if (!read_) diff --git a/src/libcamera/include/byte_stream_buffer.h b/src/libcamera/include/byte_stream_buffer.h index b5274c62b85e..2d5267ac06c0 100644 --- a/src/libcamera/include/byte_stream_buffer.h +++ b/src/libcamera/include/byte_stream_buffer.h @@ -10,6 +10,8 @@ #include #include +#include + namespace libcamera { class ByteStreamBuffer @@ -34,10 +36,22 @@ public: return read(reinterpret_cast(t), sizeof(*t)); } template + int read(Span *t) + { + return read(reinterpret_cast(t->data()), + sizeof(t->data()[0]) * t->size()); + } + template int write(const T *t) { return write(reinterpret_cast(t), sizeof(*t)); } + template + int write(const Span &t) + { + return write(reinterpret_cast(t.data()), + sizeof(t.data()[0]) * t.size()); + } private: ByteStreamBuffer(const ByteStreamBuffer &other) = delete; From patchwork Mon Jan 13 16:42:44 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 2636 X-Patchwork-Delegate: jacopo@jmondi.org Return-Path: Received: from relay11.mail.gandi.net (relay11.mail.gandi.net [217.70.178.231]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 9662D60700 for ; Mon, 13 Jan 2020 17:40:40 +0100 (CET) Received: from uno.lan (2-224-242-101.ip172.fastwebnet.it [2.224.242.101]) (Authenticated sender: jacopo@jmondi.org) by relay11.mail.gandi.net (Postfix) with ESMTPSA id 30D90100003; Mon, 13 Jan 2020 16:40:40 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Mon, 13 Jan 2020 17:42:44 +0100 Message-Id: <20200113164245.52535-23-jacopo@jmondi.org> X-Mailer: git-send-email 2.24.0 In-Reply-To: <20200113164245.52535-1-jacopo@jmondi.org> References: <20200113164245.52535-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 22/23] libcamera: control_serializer: Add support for compound controls 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: , X-List-Received-Date: Mon, 13 Jan 2020 16:40:42 -0000 Add support for serializing and deserializing control values which transport compound values. Signed-off-by: Jacopo Mondi --- src/libcamera/control_serializer.cpp | 123 ++++++++++++++++++--- src/libcamera/include/control_serializer.h | 10 +- 2 files changed, 117 insertions(+), 16 deletions(-) diff --git a/src/libcamera/control_serializer.cpp b/src/libcamera/control_serializer.cpp index fd91baf15156..75e8ebc3d9d3 100644 --- a/src/libcamera/control_serializer.cpp +++ b/src/libcamera/control_serializer.cpp @@ -14,6 +14,7 @@ #include #include #include +#include #include "byte_stream_buffer.h" #include "log.h" @@ -30,11 +31,15 @@ LOG_DEFINE_CATEGORY(Serializer) namespace { static constexpr size_t ControlValueSize[] = { - [ControlTypeNone] = 1, - [ControlTypeBool] = sizeof(bool), - [ControlTypeInteger32] = sizeof(int32_t), - [ControlTypeInteger64] = sizeof(int64_t), - [ControlTypeFloat] = sizeof(float), + [ControlTypeNone] = 1, + [ControlTypeBool] = sizeof(bool), + [ControlTypeInteger32] = sizeof(int32_t), + [ControlTypeInteger64] = sizeof(int64_t), + [ControlTypeFloat] = sizeof(float), + [ControlTypeCompoundBool] = sizeof(bool), + [ControlTypeCompoundInt32] = sizeof(int32_t), + [ControlTypeCompoundInt64] = sizeof(int64_t), + [ControlTypeCompoundFloat] = sizeof(float), }; } /* namespace */ @@ -107,7 +112,7 @@ void ControlSerializer::reset() size_t ControlSerializer::binarySize(const ControlValue &value) { - return ControlValueSize[value.type()]; + return ControlValueSize[value.type()] * value.numElements(); } size_t ControlSerializer::binarySize(const ControlRange &range) @@ -183,6 +188,30 @@ void ControlSerializer::store(const ControlValue &value, break; } + case ControlTypeCompoundBool: { + Span data = value.get>(); + buffer.write(&data); + break; + } + + case ControlTypeCompoundInt32: { + Span data = value.get>(); + buffer.write(data); + break; + } + + case ControlTypeCompoundInt64: { + Span data = value.get>(); + buffer.write(data); + break; + } + + case ControlTypeCompoundFloat: { + Span data = value.get>(); + buffer.write(data); + break; + } + default: break; } @@ -318,7 +347,7 @@ int ControlSerializer::serialize(const ControlList &list, struct ipa_control_value_entry entry; entry.id = id; - entry.count = 1; + entry.count = value.numElements(); entry.type = value.type(); entry.offset = values.offset(); entries.write(&entry); @@ -332,35 +361,74 @@ int ControlSerializer::serialize(const ControlList &list, return 0; } +template +void ControlSerializer::loadData(ByteStreamBuffer &buffer, unsigned int count, + ControlValue *value) +{ + Span data(new T[count], count); + buffer.read(&data); + + /* + * Use of ControlValue::set() guarantees the memory content + * is copied into the ControlValue. + */ + value->set(data); +} + template<> ControlValue ControlSerializer::load(ControlType type, - ByteStreamBuffer &b) + ByteStreamBuffer &buffer, + unsigned int count) { switch (type) { case ControlTypeBool: { bool value; - b.read(&value); + buffer.read(&value); return ControlValue(value); } case ControlTypeInteger32: { int32_t value; - b.read(&value); + buffer.read(&value); return ControlValue(value); } case ControlTypeInteger64: { int64_t value; - b.read(&value); + buffer.read(&value); return ControlValue(value); } case ControlTypeFloat: { float value; - b.read(&value); + buffer.read(&value); return ControlValue(value); } + case ControlTypeCompoundBool: { + ControlValue value; + loadData(buffer, count, &value); + return value; + } + + case ControlTypeCompoundInt32: { + ControlValue value; + loadData(buffer, count, &value); + return value; + } + + case ControlTypeCompoundInt64: { + ControlValue value; + loadData(buffer, count, &value); + return value; + } + + case ControlTypeCompoundFloat: { + ControlValue value; + loadData(buffer, count, &value); + return value; + } + default: return ControlValue(); } @@ -370,8 +438,32 @@ template<> ControlRange ControlSerializer::load(ControlType type, ByteStreamBuffer &b) { - ControlValue min = load(type, b); - ControlValue max = load(type, b); + /* + * The 'type' parameter represents the type of the Control + * the ControlRange refers to. Even if the Control is a compound, + * its range elements are not: adjust the type opportunely. + */ + ControlType rangeType; + switch (type) { + case ControlTypeCompoundBool: + rangeType = ControlTypeBool; + break; + case ControlTypeCompoundInt32: + rangeType = ControlTypeInteger32; + break; + case ControlTypeCompoundInt64: + rangeType = ControlTypeInteger64; + break; + case ControlTypeCompoundFloat: + rangeType = ControlTypeFloat; + break; + default: + rangeType = type; + break; + } + + ControlValue min = load(rangeType, b); + ControlValue max = load(rangeType, b); return ControlRange(min, max); } @@ -519,7 +611,8 @@ ControlList ControlSerializer::deserialize(ByteStreamBuffer &buffer } ControlType type = static_cast(entry.type); - ctrls.set(entry.id, load(type, values)); + ctrls.set(entry.id, + load(type, values, entry.count)); } return ctrls; diff --git a/src/libcamera/include/control_serializer.h b/src/libcamera/include/control_serializer.h index 55259913a2ca..2d76ffe7ed84 100644 --- a/src/libcamera/include/control_serializer.h +++ b/src/libcamera/include/control_serializer.h @@ -10,6 +10,7 @@ #include #include #include +#include #include @@ -40,8 +41,15 @@ private: static void store(const ControlValue &value, ByteStreamBuffer &buffer); static void store(const ControlRange &range, ByteStreamBuffer &buffer); + template::value>::type * = nullptr> + T load(ControlType type, ByteStreamBuffer &buffer, unsigned int count = 1); + template::value>::type * = nullptr> + T load(ControlType type, ByteStreamBuffer &buffer); template - T load(ControlType type, ByteStreamBuffer &b); + void loadData(ByteStreamBuffer &buffer, unsigned int count, + ControlValue *value); unsigned int serial_; std::vector> controlIds_; From patchwork Mon Jan 13 16:42:45 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 2638 X-Patchwork-Delegate: jacopo@jmondi.org Return-Path: Received: from relay11.mail.gandi.net (relay11.mail.gandi.net [217.70.178.231]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 3B3B960706 for ; Mon, 13 Jan 2020 17:40:41 +0100 (CET) Received: from uno.lan (2-224-242-101.ip172.fastwebnet.it [2.224.242.101]) (Authenticated sender: jacopo@jmondi.org) by relay11.mail.gandi.net (Postfix) with ESMTPSA id CF9C2100008; Mon, 13 Jan 2020 16:40:40 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Mon, 13 Jan 2020 17:42:45 +0100 Message-Id: <20200113164245.52535-24-jacopo@jmondi.org> X-Mailer: git-send-email 2.24.0 In-Reply-To: <20200113164245.52535-1-jacopo@jmondi.org> References: <20200113164245.52535-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 23/23] DNI: test: serialization: Serialize compound controls 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: , X-List-Received-Date: Mon, 13 Jan 2020 16:40:42 -0000 Depends on the fictional compound control definition. Not for inclusion. Signed-off-by: Jacopo Mondi --- test/serialization/control_serialization.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/serialization/control_serialization.cpp b/test/serialization/control_serialization.cpp index 2989b52774fb..e50ea9ffb60e 100644 --- a/test/serialization/control_serialization.cpp +++ b/test/serialization/control_serialization.cpp @@ -45,6 +45,8 @@ protected: list.set(controls::Brightness, 255); list.set(controls::Contrast, 128); list.set(controls::Saturation, 50); + std::vector values = { 0, 125, 253 }; + list.set(controls::CompoundControl, Span{ values }); /* * Serialize the control list, this should fail as the control