From patchwork Thu Feb 6 01:25:53 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 2777 Return-Path: Received: from relay10.mail.gandi.net (relay10.mail.gandi.net [217.70.178.230]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id CAAB960446 for ; Thu, 6 Feb 2020 02:23:33 +0100 (CET) Received: from uno.lan (93-34-114-233.ip49.fastwebnet.it [93.34.114.233]) (Authenticated sender: jacopo@jmondi.org) by relay10.mail.gandi.net (Postfix) with ESMTPSA id 9E99B240002 for ; Thu, 6 Feb 2020 01:23:33 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Thu, 6 Feb 2020 02:25:53 +0100 Message-Id: <20200206012601.153858-2-jacopo@jmondi.org> X-Mailer: git-send-email 2.24.1 In-Reply-To: <20200206012601.153858-1-jacopo@jmondi.org> References: <20200206012601.153858-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v5 1/9] [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: Thu, 06 Feb 2020 01:23:33 -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 Thu Feb 6 01:25:54 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 2778 Return-Path: Received: from relay10.mail.gandi.net (relay10.mail.gandi.net [217.70.178.230]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 21FC660446 for ; Thu, 6 Feb 2020 02:23:34 +0100 (CET) Received: from uno.lan (93-34-114-233.ip49.fastwebnet.it [93.34.114.233]) (Authenticated sender: jacopo@jmondi.org) by relay10.mail.gandi.net (Postfix) with ESMTPSA id E88E4240002 for ; Thu, 6 Feb 2020 01:23:33 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Thu, 6 Feb 2020 02:25:54 +0100 Message-Id: <20200206012601.153858-3-jacopo@jmondi.org> X-Mailer: git-send-email 2.24.1 In-Reply-To: <20200206012601.153858-1-jacopo@jmondi.org> References: <20200206012601.153858-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v5 2/9] 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: Thu, 06 Feb 2020 01:23:34 -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 | 50 +++++++++++++++++++++++++++++++---- 1 file changed, 45 insertions(+), 5 deletions(-) diff --git a/src/libcamera/gen-controls.py b/src/libcamera/gen-controls.py index 2e5ac5c81cca..b251e528d50b 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,31 @@ ${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 entry in enum: + entry_name, entry_info = entry.popitem() + value_info = { + 'name' : name, + 'value': entry_name, + 'description': format_description(entry_info['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 +79,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 +98,19 @@ def generate_h(controls): 'type': ctrl['type'], } + enum = ctrl.get('enum') + if enum: + ctrls.append(enum_template_start.substitute(info)) + + for entry in enum: + entry_name, entry_info = entry.popitem() + value_info = { + 'name': entry_name, + 'value': entry_info['value'], + } + ctrls.append(enum_value_template.substitute(value_info)) + ctrls.append("};") + ctrls.append(template.substitute(info)) id_value += 1 From patchwork Thu Feb 6 01:25:55 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 2779 Return-Path: Received: from relay10.mail.gandi.net (relay10.mail.gandi.net [217.70.178.230]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 72B6960446 for ; Thu, 6 Feb 2020 02:23:34 +0100 (CET) Received: from uno.lan (93-34-114-233.ip49.fastwebnet.it [93.34.114.233]) (Authenticated sender: jacopo@jmondi.org) by relay10.mail.gandi.net (Postfix) with ESMTPSA id 4457E240004 for ; Thu, 6 Feb 2020 01:23:34 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Thu, 6 Feb 2020 02:25:55 +0100 Message-Id: <20200206012601.153858-4-jacopo@jmondi.org> X-Mailer: git-send-email 2.24.1 In-Reply-To: <20200206012601.153858-1-jacopo@jmondi.org> References: <20200206012601.153858-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v5 3/9] 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: Thu, 06 Feb 2020 01:23:34 -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. Reviewed-by: Niklas Söderlund Signed-off-by: Laurent Pinchart Signed-off-by: Jacopo Mondi --- 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..f384e5205ef6 --- /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 Thu Feb 6 01:25:56 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 2780 Return-Path: Received: from relay10.mail.gandi.net (relay10.mail.gandi.net [217.70.178.230]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id C8BC260446 for ; Thu, 6 Feb 2020 02:23:34 +0100 (CET) Received: from uno.lan (93-34-114-233.ip49.fastwebnet.it [93.34.114.233]) (Authenticated sender: jacopo@jmondi.org) by relay10.mail.gandi.net (Postfix) with ESMTPSA id 92766240002 for ; Thu, 6 Feb 2020 01:23:34 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Thu, 6 Feb 2020 02:25:56 +0100 Message-Id: <20200206012601.153858-5-jacopo@jmondi.org> X-Mailer: git-send-email 2.24.1 In-Reply-To: <20200206012601.153858-1-jacopo@jmondi.org> References: <20200206012601.153858-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v5 4/9] 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: Thu, 06 Feb 2020 01:23:35 -0000 The rotation property describes the rotation of the camera sensor. Reviewed-by: Laurent Pinchart Reviewed-by: Niklas Söderlund Signed-off-by: Jacopo Mondi --- src/libcamera/property_ids.yaml | 329 ++++++++++++++++++++++++++++++++ 1 file changed, 329 insertions(+) diff --git a/src/libcamera/property_ids.yaml b/src/libcamera/property_ids.yaml index f384e5205ef6..c3070de9d9f8 100644 --- a/src/libcamera/property_ids.yaml +++ b/src/libcamera/property_ids.yaml @@ -25,4 +25,333 @@ 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 relative to 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 a 2-dimensional reference system 'Rc' defined by + its pixel array read-out order. The origin is set to the first pixel + being read out, the X-axis points along the column read-out direction + towards the last columns, and the Y-axis along the row read-out + direction towards the last row. + + A typical example for a sensor with a 2592x1944 pixel array matrix + observed from the front is + + 2591 X-axis 0 + <------------------------+ 0 + .......... ... ..........! + .......... ... ..........! Y-axis + ... ! + .......... ... ..........! + .......... ... ..........! 1943 + V + + + The external world scene reference system 'Rs' is a 2-dimensional + reference system on the focal plane of the camera module. The origin is + placed on the top-left corner of the visible scene, the X-axis points + towards the right, and the Y-axis points towards the bottom of the + scene. The top, bottom, left and right directions are intentionally not + defined and depend on the environment in which the camera is used. + + A typical example of a (very common) picture of a shark swimming from + left to right, as seen from the camera, is + + 0 X-axis + 0 +------------------------------------> + ! + ! + ! |\____)\___ + ! ) _____ __`< + ! |/ )/ + ! + V + Y-axis + + With the reference system 'Rs' placed on the camera focal plane. + + ! + / ! + / ! + / ! + _ / ! + +-/ \-+ / ! + | (o) | ! Camera focal plane + +-----+ \ ! + \ ! + \ ! + \ ! + \ ! + ! + + When projected on the sensor's pixel array, the image and the associated + reference system 'Rs' are typically (but not always) inverted, due to + the camera module's lens optical inversion effect. + + Assuming the above represented scene of the swimming shark, the lens + inversion projects the scene and its reference system onto the sensor + pixel array, seen from the front of the camera sensor, as follow + + Y-axis + ^ + ! + ! |\_____)\__ + ! ) ____ ___.< + ! |/ )/ + ! + ! + 0 +------------------------------------> + 0 X-axis + + Note the shark being upside-down. + + The resulting projected reference system is named 'Rp'. + + The camera rotation property is then defined as the angular difference + in the counterclockwise direction between the camera reference system + 'Rc' and the projected scene reference system 'Rp'. It is expressed in + degrees as a number in the range [0, 360[. + + 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 + + 0 + <-----------------------------------+ 0 + X-Rc ! + y-Rp ! + ^ ! + ! ! Y-Rc + ! ! + ! ! + ! V + ! + 0 +------------------------------------> + 0 X-Rp + + 270 degrees camera rotation + + 0 Y-Rc + 0 +-----------------------> + ! 0 + ! <-----------------------------------+ 0 + ! X-Rc ! + ! ! + ! ! + ! ! + ! ! + ! 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 upside-down 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 needs to be applied to the resulting + image once captured to memory buffers to correctly display it to users. + + +--------------------------+ + ! |\____)\___ ! + ! ) _____ __`< ! + ! |/ )/ ! + +--------------------------+ + + If the camera sensor is not mounted upside-down to compensate for the + lens optical inversion, the two reference systems will not be aligned, + with 'Rp' being rotated 180 degrees relatively to 'Rc'. + + + X-Rc 0 + <------------------------------------+ 0 + Y-Rp ! + ^ ! + ! ! Y-Rc + ! |\_____)\__ ! + ! ) ____ ___.< ! + ! |/ )/ ! + ! V + ! + 0 +-------------------------------------> + 0 X-Rp + + The image once captured to memory will then be rotated by 180 degrees + + +--------------------------------------+ + ! ! + ! __/(_____/| ! + ! >.___ ____ ( ! + ! \( \| ! + ! ! + +--------------------------------------+ + + 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 sensor is typically mounted with its pixel array longer side + aligned to the device longer side, upside-down mounted to compensate for + 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 rotated by 90 degrees in the counterclockwise direction + relatively to the 'Rc' reference system. + + The image once captured to memory 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 Thu Feb 6 01:25:57 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 2781 Return-Path: Received: from relay10.mail.gandi.net (relay10.mail.gandi.net [217.70.178.230]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 22B3C60446 for ; Thu, 6 Feb 2020 02:23:35 +0100 (CET) Received: from uno.lan (93-34-114-233.ip49.fastwebnet.it [93.34.114.233]) (Authenticated sender: jacopo@jmondi.org) by relay10.mail.gandi.net (Postfix) with ESMTPSA id E8233240002 for ; Thu, 6 Feb 2020 01:23:34 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Thu, 6 Feb 2020 02:25:57 +0100 Message-Id: <20200206012601.153858-6-jacopo@jmondi.org> X-Mailer: git-send-email 2.24.1 In-Reply-To: <20200206012601.153858-1-jacopo@jmondi.org> References: <20200206012601.153858-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v5 5/9] 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: Thu, 06 Feb 2020 01:23:35 -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 34a8c8dd9458..0031cd064da9 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 Thu Feb 6 01:25:58 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 2782 Return-Path: Received: from relay10.mail.gandi.net (relay10.mail.gandi.net [217.70.178.230]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 6E6D260446 for ; Thu, 6 Feb 2020 02:23:35 +0100 (CET) Received: from uno.lan (93-34-114-233.ip49.fastwebnet.it [93.34.114.233]) (Authenticated sender: jacopo@jmondi.org) by relay10.mail.gandi.net (Postfix) with ESMTPSA id 43099240002 for ; Thu, 6 Feb 2020 01:23:35 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Thu, 6 Feb 2020 02:25:58 +0100 Message-Id: <20200206012601.153858-7-jacopo@jmondi.org> X-Mailer: git-send-email 2.24.1 In-Reply-To: <20200206012601.153858-1-jacopo@jmondi.org> References: <20200206012601.153858-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v5 6/9] 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: Thu, 06 Feb 2020 01:23:36 -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 Thu Feb 6 01:25:59 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 2783 Return-Path: Received: from relay10.mail.gandi.net (relay10.mail.gandi.net [217.70.178.230]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id B93AB607E5 for ; Thu, 6 Feb 2020 02:23:35 +0100 (CET) Received: from uno.lan (93-34-114-233.ip49.fastwebnet.it [93.34.114.233]) (Authenticated sender: jacopo@jmondi.org) by relay10.mail.gandi.net (Postfix) with ESMTPSA id 8C847240002 for ; Thu, 6 Feb 2020 01:23:35 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Thu, 6 Feb 2020 02:25:59 +0100 Message-Id: <20200206012601.153858-8-jacopo@jmondi.org> X-Mailer: git-send-email 2.24.1 In-Reply-To: <20200206012601.153858-1-jacopo@jmondi.org> References: <20200206012601.153858-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v5 7/9] 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: Thu, 06 Feb 2020 01:23:37 -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 97157dd75c8a..923bd393d1a2 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 8e8e370922ad..387bb070b505 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 0b3dd9759387..68f16f03a81e 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 b1054d307ea2..5d3d12fef30b 100644 --- a/src/libcamera/pipeline/vimc.cpp +++ b/src/libcamera/pipeline/vimc.cpp @@ -452,6 +452,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 5476dbab74d5..e976393db3e0 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 Thu Feb 6 01:26:00 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 2784 Return-Path: Received: from relay10.mail.gandi.net (relay10.mail.gandi.net [217.70.178.230]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 13A50607C9 for ; Thu, 6 Feb 2020 02:23:36 +0100 (CET) Received: from uno.lan (93-34-114-233.ip49.fastwebnet.it [93.34.114.233]) (Authenticated sender: jacopo@jmondi.org) by relay10.mail.gandi.net (Postfix) with ESMTPSA id D68A9240002 for ; Thu, 6 Feb 2020 01:23:35 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Thu, 6 Feb 2020 02:26:00 +0100 Message-Id: <20200206012601.153858-9-jacopo@jmondi.org> X-Mailer: git-send-email 2.24.1 In-Reply-To: <20200206012601.153858-1-jacopo@jmondi.org> References: <20200206012601.153858-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v5 8/9] 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: Thu, 06 Feb 2020 01:23:37 -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 c37319eda2dc..c453b95228a7 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 802e7fd0d12f..ca09e297d32a 100644 --- a/src/libcamera/camera.cpp +++ b/src/libcamera/camera.cpp @@ -627,7 +627,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 */ @@ -636,6 +637,19 @@ const ControlInfoMap &Camera::controls() return p_->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 p_->pipe_->properties(this); +} + /** * \brief Retrieve all the camera's stream information * From patchwork Thu Feb 6 01:26:01 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 2785 Return-Path: Received: from relay10.mail.gandi.net (relay10.mail.gandi.net [217.70.178.230]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 5BEC5607E9 for ; Thu, 6 Feb 2020 02:23:36 +0100 (CET) Received: from uno.lan (93-34-114-233.ip49.fastwebnet.it [93.34.114.233]) (Authenticated sender: jacopo@jmondi.org) by relay10.mail.gandi.net (Postfix) with ESMTPSA id 30A8A240002 for ; Thu, 6 Feb 2020 01:23:36 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Thu, 6 Feb 2020 02:26:01 +0100 Message-Id: <20200206012601.153858-10-jacopo@jmondi.org> X-Mailer: git-send-email 2.24.1 In-Reply-To: <20200206012601.153858-1-jacopo@jmondi.org> References: <20200206012601.153858-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v5 9/9] 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: Thu, 06 Feb 2020 01:23:38 -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 67c1d47e67ed..96674698cece 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 = {