From patchwork Fri Jun 21 16:13:53 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kieran Bingham X-Patchwork-Id: 1494 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id B89E160E4D for ; Fri, 21 Jun 2019 18:14:06 +0200 (CEST) Received: from localhost.localdomain (cpc89242-aztw30-2-0-cust488.18-1.cable.virginm.net [86.31.129.233]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 43E1D33C; Fri, 21 Jun 2019 18:14:06 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1561133646; bh=+5rebP32rbsRGWdoofnbvFIibREVMlWM+svdDmUePKQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=reKn0PQPRuZo9r5cT+PRJoRuYG1ZMy/p6mMed4BA/G4TTjGDGmOrUlLNmoWxz+vhw b7SPg1lwFUuE20EZibcX1+q2KVZu9XvqzriX10GCTZ+LUOr7ZMP5dwx7pFtblVR6Bg yvEjVFYWtDhUYIacpLUJ/Bc14hDPUC1JFz5Fa3TM= From: Kieran Bingham To: LibCamera Devel Date: Fri, 21 Jun 2019 17:13:53 +0100 Message-Id: <20190621161401.28337-2-kieran.bingham@ideasonboard.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190621161401.28337-1-kieran.bingham@ideasonboard.com> References: <20190621161401.28337-1-kieran.bingham@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [RFC PATCH v2 1/9] libcamera: Value: Provide abstract value class X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 21 Jun 2019 16:14:07 -0000 To facilitate passing typed data generically, implement a class which stores the type and value as efficiently as possible. Signed-off-by: Kieran Bingham --- include/libcamera/meson.build | 1 + include/libcamera/value.h | 63 ++++++++++ src/libcamera/meson.build | 1 + src/libcamera/value.cpp | 226 ++++++++++++++++++++++++++++++++++ 4 files changed, 291 insertions(+) create mode 100644 include/libcamera/value.h create mode 100644 src/libcamera/value.cpp diff --git a/include/libcamera/meson.build b/include/libcamera/meson.build index 201832105457..eb2211ae1fc3 100644 --- a/include/libcamera/meson.build +++ b/include/libcamera/meson.build @@ -12,6 +12,7 @@ libcamera_api = files([ 'signal.h', 'stream.h', 'timer.h', + 'value.h', 'version.h', ]) diff --git a/include/libcamera/value.h b/include/libcamera/value.h new file mode 100644 index 000000000000..00c5d53d5cc0 --- /dev/null +++ b/include/libcamera/value.h @@ -0,0 +1,63 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2019, Google Inc. + * + * value.h - Abstract value handling + */ + +#include + +#ifndef __LIBCAMERA_VALUE_H__ +#define __LIBCAMERA_VALUE_H__ + +namespace libcamera { + +enum ValueType : uint8_t { + ValueNull, + ValueBool, + ValueInteger, + ValueInteger64, + ValueString, +}; + +class Value +{ +public: + Value(); + Value(bool value); + Value(int value); + Value(const char *value); + Value(const std::string &value); + + ValueType type() const { return type_; }; + bool isNull() const { return type_ == ValueNull; }; + + void set(bool value); + void set(int value); + void set(int64_t value); + void set(const char *value); + void set(const std::string &value); + + bool getBool() const; + int getInt() const; + int getInt64() const; + std::string getString() const; + + std::string toString() const; + +private: + ValueType type_; + + union { + bool bool_; + int integer_; + int64_t integer64_; + }; + std::string string_; +}; + +std::ostream &operator<<(std::ostream &stream, const Value &value); + +} /* namespace libcamera */ + +#endif /* __LIBCAMERA_VALUE_H__ */ diff --git a/src/libcamera/meson.build b/src/libcamera/meson.build index 68c7ce14b5b4..8e68373118df 100644 --- a/src/libcamera/meson.build +++ b/src/libcamera/meson.build @@ -27,6 +27,7 @@ libcamera_sources = files([ 'v4l2_device.cpp', 'v4l2_subdevice.cpp', 'v4l2_videodevice.cpp', + 'value.cpp', 'version.cpp', ]) diff --git a/src/libcamera/value.cpp b/src/libcamera/value.cpp new file mode 100644 index 000000000000..f713907b38dd --- /dev/null +++ b/src/libcamera/value.cpp @@ -0,0 +1,226 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2019, Google Inc. + * + * value.cpp - Abstract value handling + */ + +#include +#include +#include + +#include + +#include "log.h" // For ASSERT() + +/** + * \file value.h + * \brief Handles variant value types as an abstract object + */ + +namespace libcamera { + +/** + * \enum ValueType + * Determines the type of value represented by a \a Value + * \var ValueNull + * Identifies an unset value + * \var ValueBool + * Identifies controls storing a boolean value + * \var ValueInteger + * Identifies controls storing an integer value + * \var ValueString + * Identifies controls storing a string value + */ + +/** + * \class Value + * \brief Abstract a value for a common data exchange + */ + +/** + * \brief Construct an empty Value. + * The Value must be \a set() before being used. + */ +Value::Value() + : type_(ValueNull) +{ +} + +/** + * \brief Construct a Boolean Value + * \param[in] value Boolean value to store + */ +Value::Value(bool value) + : type_(ValueBool), bool_(value) +{ +} + +/** + * \brief Construct an integer Value + * \param[in] value Integer value to store + */ +Value::Value(int value) + : type_(ValueInteger), integer_(value) +{ +} + +/** + * \brief Construct a string Value + * \param[in] value String representation to store + */ +Value::Value(const char *value) + : type_(ValueString), string_(value) +{ +} + +/** + * \brief Construct a string Value + * \param[in] value String representation to store + */ +Value::Value(const std::string &value) + : type_(ValueString), string_(value) +{ +} + +/** + * \fn Value::type + * \brief Return the type of value represented by the object + */ + +/** + * \fn Value::isNull + * \brief Determines if the Value is initialised + * \return true if the value type is ValueNull, false otherwise + */ + +/** + * \brief Set the value with a boolean + * \param[in] value Boolean value to store + */ +void Value::set(bool value) +{ + type_ = ValueBool; + bool_ = value; +} + +/** + * \brief Set the value with an integer + * \param[in] value Integer value to store + */ +void Value::set(int value) +{ + type_ = ValueInteger; + integer_ = value; +} + +/** + * \brief Set the value with a 64 bit integer + * \param[in] value Integer value to store + */ +void Value::set(int64_t value) +{ + type_ = ValueInteger64; + integer64_ = value; +} + +/** + * \brief Set the value with a string representation + * \param[in] value String value to store + */ +void Value::set(const char *value) +{ + type_ = ValueString; + string_ = value; +} + +/** + * \brief Set the value with a string representation + * \param[in] value String value to store + */ +void Value::set(const std::string &value) +{ + type_ = ValueString; + string_ = value; +} + +/** + * \brief Get the boolean value. + * + * The Value type must be Boolean. + */ +bool Value::getBool() const +{ + ASSERT(type_ == ValueBool); + + return bool_; +} + +/** + * \brief Get the integer value. + * + * The Value type must be Integer. + */ +int Value::getInt() const +{ + ASSERT(type_ == ValueInteger); + + return integer_; +} + +/** + * \brief Get the 64bit integer value. + * + * The Value type must be Integer64. + */ +int Value::getInt64() const +{ + ASSERT(type_ == ValueInteger64); + + return integer64_; +} + +/** + * \brief Get the string value. + * + * The Value type must be String. + */ +std::string Value::getString() const +{ + ASSERT(type_ == ValueString); + + return string_; +} + +/** + * \brief Prepare a string representation of the Value + */ +std::string Value::toString() const +{ + switch (type_) { + case ValueNull: + return ""; + case ValueBool: + return bool_ ? "True" : "False"; + case ValueInteger: + return std::to_string(integer_); + case ValueInteger64: + return std::to_string(integer64_); + case ValueString: + return string_; + } + + /* Unreachable */ + return ""; +} + +/** + * \brief Provide a string stream representation of the Value \a value to + * the \a stream. + */ +std::ostream &operator<<(std::ostream &stream, const Value &value) +{ + return stream << value.toString(); +} + +} /* namespace libcamera */ From patchwork Fri Jun 21 16:13:54 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kieran Bingham X-Patchwork-Id: 1495 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id DE7C2615BC for ; Fri, 21 Jun 2019 18:14:06 +0200 (CEST) Received: from localhost.localdomain (cpc89242-aztw30-2-0-cust488.18-1.cable.virginm.net [86.31.129.233]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 8CAD952A; Fri, 21 Jun 2019 18:14:06 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1561133646; bh=1I58ueIgZpJe4vC52rlGsh3C91qg8EGfNd9XndywWPw=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=gshrnjJQf50GTBzTwPsgAG21CHHqEbCzxuOo/Yxe/iuYjhDtX4s2icsEfa/IOrvfN 5hb7D/jLCegY5dDDfSp9RMQeXUze2qIh2NaXhzaO+URRg8bqzn1Qg7x0OdeCoyQrdt VeNltAh8vqpQ2sOJ8QXhXDnClSn0PK5EbQ58iTcM= From: Kieran Bingham To: LibCamera Devel Date: Fri, 21 Jun 2019 17:13:54 +0100 Message-Id: <20190621161401.28337-3-kieran.bingham@ideasonboard.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190621161401.28337-1-kieran.bingham@ideasonboard.com> References: <20190621161401.28337-1-kieran.bingham@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [RFC PATCH v2 2/9] libcamera: test: Add Value tests X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 21 Jun 2019 16:14:07 -0000 Add initial basic testing for the new Value APIs. Signed-off-by: Kieran Bingham --- test/meson.build | 1 + test/value.cpp | 82 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 83 insertions(+) create mode 100644 test/value.cpp diff --git a/test/meson.build b/test/meson.build index c36ac2479636..eff541ddc0a6 100644 --- a/test/meson.build +++ b/test/meson.build @@ -15,6 +15,7 @@ public_tests = [ ['list-cameras', 'list-cameras.cpp'], ['signal', 'signal.cpp'], ['timer', 'timer.cpp'], + ['value', 'value.cpp'], ] internal_tests = [ diff --git a/test/value.cpp b/test/value.cpp new file mode 100644 index 000000000000..fea8cd2396cd --- /dev/null +++ b/test/value.cpp @@ -0,0 +1,82 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2019, Google Inc. + * + * value.cpp - Value tests + */ + +#include + +#include + +#include "test.h" + +using namespace std; +using namespace libcamera; + +class Values : public Test +{ +protected: + int run() + { + Value integer(1234); + Value boolean(true); + Value string("test-string"); + + /* Just a string conversion output test... no validation */ + cout << "Int: " << integer.toString() + << " Bool: " << boolean.toString() + << " String: " << string.toString() + << endl; + + /* Just a string conversion output test. Using overloaded << */ + cout << "Int: " << integer + << " Bool: " << boolean + << " String: " << string + << endl; + + if (integer.getInt() != 1234) { + cerr << "Failed to get Integer" << endl; + return TestFail; + } + + if (boolean.getBool() != true) { + cerr << "Failed to get Boolean" << endl; + return TestFail; + } + + if (string.getString() != "test-string") { + cerr << "Failed to get string" << endl; + return TestFail; + } + + /* Test an uninitialised value, and updating it. */ + + Value value; + if (!value.isNull()) { + cerr << "Empty value is non-null" << endl; + return TestFail; + } + + value.set(true); + if (value.isNull()) { + cerr << "Failed to set an empty object" << endl; + return TestFail; + } + + if (value.getBool() != true) { + cerr << "Failed to get Booleans" << endl; + return TestFail; + } + + value.set(10); + if (value.getInt() != 10) { + cerr << "Failed to get Integer" << endl; + return TestFail; + } + + return TestPass; + } +}; + +TEST_REGISTER(Values) From patchwork Fri Jun 21 16:13:55 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kieran Bingham X-Patchwork-Id: 1496 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 339E5615BC for ; Fri, 21 Jun 2019 18:14:07 +0200 (CEST) Received: from localhost.localdomain (cpc89242-aztw30-2-0-cust488.18-1.cable.virginm.net [86.31.129.233]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id D1D34E04; Fri, 21 Jun 2019 18:14:06 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1561133647; bh=65KJEfpWcjVvfIS/Pk6jQPpsXi7LZ+0Rix04nCSgklo=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=A0N+/YWX4mwoLq/1zSrJyasBL7VVfjrRlkgEfi7l0zT+frqnEmzT5+gVzG16ZzF4h 7903Kbgbjo1s0AnBNhD68anC72WHzNlAwvaz+M5sZI8Na37KrbPAeOhlQU5m64elOM 6/GxmjkN9r5C/aJUtXqteuBOtt1eD/R6v5SIJXzM= From: Kieran Bingham To: LibCamera Devel Date: Fri, 21 Jun 2019 17:13:55 +0100 Message-Id: <20190621161401.28337-4-kieran.bingham@ideasonboard.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190621161401.28337-1-kieran.bingham@ideasonboard.com> References: <20190621161401.28337-1-kieran.bingham@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [RFC PATCH v2 3/9] libcamera: controls: Introduce Control structures X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 21 Jun 2019 16:14:07 -0000 ControlIdentifiers declare the types of a control, and map their names, and the ControlInfo class allows runtime state to be represented. Signed-off-by: Kieran Bingham --- include/libcamera/controls.h | 58 ++++++++++++ include/libcamera/meson.build | 1 + src/libcamera/controls.cpp | 160 ++++++++++++++++++++++++++++++++++ src/libcamera/meson.build | 1 + 4 files changed, 220 insertions(+) create mode 100644 include/libcamera/controls.h create mode 100644 src/libcamera/controls.cpp diff --git a/include/libcamera/controls.h b/include/libcamera/controls.h new file mode 100644 index 000000000000..95198d41c4cf --- /dev/null +++ b/include/libcamera/controls.h @@ -0,0 +1,58 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2019, Google Inc. + * + * controls.h - Control handling + */ +#ifndef __LIBCAMERA_CONTROLS_H__ +#define __LIBCAMERA_CONTROLS_H__ + +#include + +namespace libcamera { + +enum ControlId : uint32_t { + /* IPA Controls */ + IpaAwbEnable, + + /* Manual Controls */ + ManualBrightness, + ManualExposure, + ManualGain, +}; + +struct ControlIdentifier { + ControlId id; + const char *name; + ValueType type; +}; + +class ControlInfo +{ +public: + ControlInfo(ControlId id, Value min = 0, Value max = 0); + + ControlId id() const { return ident_->id; } + const char *name() const { return ident_->name; } + ValueType type() const { return ident_->type; } + + const Value &min() { return min_; } + const Value &max() { return min_; } + + std::string toString() const; + + bool operator==(const ControlInfo &rhs) const { return id() == rhs.id(); } + bool operator==(const ControlId rhs) const { return id() == rhs; } + +private: + struct ControlIdentifier const *ident_; + Value min_; + Value max_; + +}; + +std::ostream &operator<<(std::ostream &stream, const ControlInfo &value); + +} /* namespace libcamera */ + +#endif /* __LIBCAMERA_CONTROLS_H__ */ diff --git a/include/libcamera/meson.build b/include/libcamera/meson.build index eb2211ae1fc3..06e3feebd23d 100644 --- a/include/libcamera/meson.build +++ b/include/libcamera/meson.build @@ -1,5 +1,6 @@ libcamera_api = files([ 'buffer.h', + 'controls.h', 'camera.h', 'camera_manager.h', 'event_dispatcher.h', diff --git a/src/libcamera/controls.cpp b/src/libcamera/controls.cpp new file mode 100644 index 000000000000..b1be46ddb55e --- /dev/null +++ b/src/libcamera/controls.cpp @@ -0,0 +1,160 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2019, Google Inc. + * + * controls.cpp - Control handling + */ + +#include +#include +#include + +#include + +#include "log.h" +#include "utils.h" + +/** + * \file controls.h + * \brief Describes control framework and controls supported by a camera + */ + +namespace libcamera { + +LOG_DEFINE_CATEGORY(Controls) + +/** + * \enum ControlId + * Control Identifiers + * \var IpaAwbEnable + * bool: Enables or disables the AWB + * \var ManualExposure + * Manually control the exposure time in milli-seconds + * \var ManualGain + * Controls the value of the manual gain setting + */ + +/** + * \struct ControlIdentifier + * Defines a Control with a unique ID, a name, and a type. + * \var ControlIdentifier::id + * The unique ID for a control + * \var ControlIdentifier::name + * The string representation of the control + * \var ControlIdentifier::type + * The ValueType required to represent the control value + */ + +/* + * Two sets of tables are generated for the static control definitions. + * + * An enum to declare the ID (in controls.h), and a type to establish its + * representation. + * + * Todo: Automate the generation of both tables from a single input table. + * Todo: Consider if this should be a static std::map created at init instead. + */ +static const struct ControlIdentifier ControlTypes[] = { +#define CONTROL_TYPE(_id, _type) { _id, #_id, _type } + + CONTROL_TYPE(IpaAwbEnable, ValueBool), + CONTROL_TYPE(ManualBrightness, ValueInteger), + CONTROL_TYPE(ManualExposure, ValueInteger), + CONTROL_TYPE(ManualGain, ValueInteger), + +#undef CONTROL_TYPE +}; + +static struct ControlIdentifier const *FindControlType(ControlId id) +{ + struct ControlIdentifier const *ident; + + for (ident = ControlTypes; + ident != &ControlTypes[ARRAY_SIZE(ControlTypes)]; + ++ident) { + if (ident->id == id) + return ident; + } + + LOG(Controls, Fatal) << "Failed to find a ControlType."; + + /* Unreachable. */ + return nullptr; +} + +/** + * \class ControlInfo + * \brief Describes the information and capabilities of a Control + */ + +/** + * \brief Construct a ControlInfo with minimum and maximum range parameters. + */ +ControlInfo::ControlInfo(ControlId id, Value min, Value max) + : ident_(FindControlType(id)), min_(min), max_(max) +{ +} + +/** + * \fn ControlInfo::id() + * \brief Return the ID of the control information descriptor + * \return the ControlId + */ + +/** + * \fn ControlInfo::name() + * \brief Return the string name of the control information descriptor + * \return A string name for the Control + */ + +/** + * \fn ControlInfo::type() + * \brief Return the ValueType of the control information descriptor + * \return the ControlId + */ + +/** + * \fn ControlInfo::min() + * \brief Reports the minimum value of the control + * \return a Value with the minimum setting for the control + */ + +/** + * \fn ControlInfo::max() + * \brief Reports the maximum value of the control + * \return a Value with the maximum setting for the control + */ + +/** + * \brief Provide a string representation of the ControlInfo + */ +std::string ControlInfo::toString() const +{ + std::stringstream ss; + + ss << "Control: " << name() + << " : Min(" << min_ << ") Max(" << max_ << ")"; + + return ss.str(); +} + +/** + * \fn ControlInfo::operator==(const ControlInfo &rhs) const + * \brief Establish equivalence of ControlInfo. Only the IDs are considered. + */ + +/** + * \fn ControlInfo::operator==(const ControlId rhs) const + * \brief Establish equivalence of ControlInfo, against a ControlID. + */ + +/** + * \brief Provide a string stream representation of the ControlInfo \a info to + * the \a stream. + */ +std::ostream &operator<<(std::ostream &stream, const ControlInfo &info) +{ + return stream << info.toString(); +} + +} /* namespace libcamera */ diff --git a/src/libcamera/meson.build b/src/libcamera/meson.build index 8e68373118df..e2c07d79bfb5 100644 --- a/src/libcamera/meson.build +++ b/src/libcamera/meson.build @@ -3,6 +3,7 @@ libcamera_sources = files([ 'camera.cpp', 'camera_manager.cpp', 'camera_sensor.cpp', + 'controls.cpp', 'device_enumerator.cpp', 'device_enumerator_sysfs.cpp', 'event_dispatcher.cpp', From patchwork Fri Jun 21 16:13:56 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Kieran Bingham X-Patchwork-Id: 1497 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 70A01615BC for ; Fri, 21 Jun 2019 18:14:07 +0200 (CEST) Received: from localhost.localdomain (cpc89242-aztw30-2-0-cust488.18-1.cable.virginm.net [86.31.129.233]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 257C6E0C; Fri, 21 Jun 2019 18:14:07 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1561133647; bh=5UShzsoGre4Oq/mg2zHBbXwtxijEO5sZqG6gmeHMtZ0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=r46r1QKU165tayPaQNd22ozdjW+y68CEUUsFyD1AkxoCcNBZKcumSEBvwAWPMQCMt PhuFb7kZ5X3kkalWhi0rzeLox4wWLNx/DOwX7EwSBfKacLN3v+cSbFid+9dwlKeOC/ sn/St+mWSDWE33L4yzIQI8Uitj+qdiBg1g9PKMYI= From: Kieran Bingham To: LibCamera Devel Date: Fri, 21 Jun 2019 17:13:56 +0100 Message-Id: <20190621161401.28337-5-kieran.bingham@ideasonboard.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190621161401.28337-1-kieran.bingham@ideasonboard.com> References: <20190621161401.28337-1-kieran.bingham@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [RFC PATCH v2 4/9] libcamera: test: Add ControlInfo tests X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 21 Jun 2019 16:14:07 -0000 Provide an initial test coverage for the ControlInfo class. Signed-off-by: Kieran Bingham Reviewed-by: Niklas Söderlund --- test/controls.cpp | 40 ++++++++++++++++++++++++++++++++++++++++ test/meson.build | 1 + 2 files changed, 41 insertions(+) create mode 100644 test/controls.cpp diff --git a/test/controls.cpp b/test/controls.cpp new file mode 100644 index 000000000000..94e89f270108 --- /dev/null +++ b/test/controls.cpp @@ -0,0 +1,40 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2019, Google Inc. + * + * controls.cpp - Control tests + */ + +#include + +#include + +#include "test.h" + +using namespace std; +using namespace libcamera; + +class Controls : public Test +{ +protected: + int testControlInfo() + { + ControlInfo gainInfo(ManualGain); + cout << "Gain Info: " << gainInfo << endl; + + return TestPass; + } + + int run() + { + int ret; + + ret = testControlInfo(); + if (ret) + return ret; + + return TestPass; + } +}; + +TEST_REGISTER(Controls) diff --git a/test/meson.build b/test/meson.build index eff541ddc0a6..0b3e6c6813e6 100644 --- a/test/meson.build +++ b/test/meson.build @@ -9,6 +9,7 @@ subdir('v4l2_subdevice') subdir('v4l2_videodevice') public_tests = [ + ['controls', 'controls.cpp'], ['event', 'event.cpp'], ['event-dispatcher', 'event-dispatcher.cpp'], ['geometry', 'geometry.cpp'], From patchwork Fri Jun 21 16:13:57 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Kieran Bingham X-Patchwork-Id: 1498 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id C9D41615BC for ; Fri, 21 Jun 2019 18:14:07 +0200 (CEST) Received: from localhost.localdomain (cpc89242-aztw30-2-0-cust488.18-1.cable.virginm.net [86.31.129.233]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 6BB3AF81; Fri, 21 Jun 2019 18:14:07 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1561133647; bh=0Bt6+LQA9Hoznez1ludzlC5gnVMhR5h+d8cIS0UFoSE=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=YhTuT8EKbAlExdV440W74GYea345X+5G/S8hULdfLYGfu39iDzSIMPtc2Zl11Luao xVeU5J0XQbd6YVC8/adguRmaoW9mYKX5dvlp3+bJID0HiKJy1aMqrMBMPGfMhOweMj WAcgWiPa/NCmvTj5VBOWVShwmVH9qVRpkA7j+HVg= From: Kieran Bingham To: LibCamera Devel Date: Fri, 21 Jun 2019 17:13:57 +0100 Message-Id: <20190621161401.28337-6-kieran.bingham@ideasonboard.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190621161401.28337-1-kieran.bingham@ideasonboard.com> References: <20190621161401.28337-1-kieran.bingham@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [RFC PATCH v2 5/9] libcamera: Implement a ControlList X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 21 Jun 2019 16:14:08 -0000 Define a ControlList which wraps the STL std::unordered_map to contain a list of associative pairs of ControlInfo and Value items. A ControlInfo (or represented by its ControlId) together with a Value provide a control item which can be interpreted by the internal IPA and PipelineHandler components. To pass a set of controls around, a ControlList can be added to a Request or stored locally to establish a set of default values for later reuse. Signed-off-by: Kieran Bingham Reviewed-by: Niklas Söderlund --- include/libcamera/controls.h | 41 +++++++++++ src/libcamera/controls.cpp | 128 +++++++++++++++++++++++++++++++++++ 2 files changed, 169 insertions(+) diff --git a/include/libcamera/controls.h b/include/libcamera/controls.h index 95198d41c4cf..5835b840a31b 100644 --- a/include/libcamera/controls.h +++ b/include/libcamera/controls.h @@ -4,6 +4,9 @@ * * controls.h - Control handling */ + +#include + #ifndef __LIBCAMERA_CONTROLS_H__ #define __LIBCAMERA_CONTROLS_H__ @@ -53,6 +56,44 @@ private: std::ostream &operator<<(std::ostream &stream, const ControlInfo &value); +class ControlList +{ +private: + struct ControlInfoHasher { + std::size_t operator()(const ControlInfo &ci) const + { + return std::hash()(ci.id()); + } + }; + + typedef std::unordered_map ControlListMap; + +public: + ControlList(); + + using iterator = ControlListMap::iterator; + using const_iterator = ControlListMap::const_iterator; + + iterator begin() { return controls_.begin(); } + iterator end() { return controls_.end(); } + const_iterator begin() const { return controls_.begin(); } + const_iterator end() const { return controls_.end(); } + + bool contains(ControlId id) const { return controls_.count(id); }; + bool empty() const { return controls_.empty(); } + size_t size() const { return controls_.size(); } + void reset() { controls_.clear(); } + + Value &operator[](ControlId id) { return controls_[id]; } + + void update(const ControlList &list); + void update(enum ControlId id, const Value &value); + void update(const ControlInfo &info, const Value &value); + +private: + ControlListMap controls_; +}; + } /* namespace libcamera */ #endif /* __LIBCAMERA_CONTROLS_H__ */ diff --git a/src/libcamera/controls.cpp b/src/libcamera/controls.cpp index b1be46ddb55e..7c55afffe4ca 100644 --- a/src/libcamera/controls.cpp +++ b/src/libcamera/controls.cpp @@ -157,4 +157,132 @@ std::ostream &operator<<(std::ostream &stream, const ControlInfo &info) return stream << info.toString(); } +/** + * \class ControlList + * \brief Associates a list of ControlIds with their values. + * + * The ControlList stores a pair of ControlInfo and Value classes as an + * unordered map. Entries can be updated using array syntax such as + * myControlList[MyControlId] = myValue; + * or + * myNewValue = myControlList[MyControlId]; + */ + +/** + * \brief Construct a ControlList + */ +ControlList::ControlList() +{ +} + +/** + * \typedef ControlList::iterator + * \brief Iterator for the controls contained within the list. + */ + +/** + * \typedef ControlList::const_iterator + * \brief Const iterator for the controls contained within the list. + */ + +/** + * \fn iterator ControlList::begin() + * \brief Retrieve an iterator to the first Control in the list + * \return An iterator to the first Control in the list + */ + +/** + * \fn iterator ControlList::end() + * \brief Retrieve an iterator to the next element after the last controls in + * the instance. + * \return An iterator to the element following the last control in the instance + */ + +/** + * \fn const_iterator ControlList::begin() const + * \brief Retrieve a const_iterator to the first Control in the list + * \return A const_iterator to the first Control in the list + */ + +/** + * \fn const_iterator ControlList::end() const + * \brief Retrieve a constant iterator pointing to an empty element after the + * \return A const iterator to the element following the last control in the + * instance + */ + +/** + * \fn ControlList::contains() + * \brief Identify if the List contains a control with the specified ControlId + * \return True if the list contains a matching control, false otherwise + */ + +/** + * \fn ControlList::empty() + * \brief Identify if the list is empty + * \return True if the list does not contain any control, false otherwise + */ + +/** + * \fn ControlList::size() + * \brief Retrieve the number of controls in the list + * \return The number of Control entries stored in the list + */ + +/** + * \fn ControlList::reset() + * \brief Removes all controls from the list + */ + +/** + * \fn ControlList::operator[]() + * \brief Access the control with the given Id + * \param id The id of the control to access + * \return The Value of the control with a ControlId of \a Id + */ + +/** + * \brief Update all Control values with the value from the given \a list + * \param list The list of controls to update or append to this list + * + * Update all controls in the ControlList, by the values given by \a list + * If the list already contains a control of this ID then it will be overwritten + */ +void ControlList::update(const ControlList &list) +{ + for (auto it : list) { + const ControlInfo &info = it.first; + const Value &value = it.second; + + controls_[info] = value; + } +} + +/** + * \brief Update a control value in the list + * \param id The ControlId of the control to update + * \param value The new value for the updated control + * + * Set the Control value in the list to the appropriate value + * If the list already contains a control of this ID then it will be overwritten + */ +void ControlList::update(enum ControlId id, const Value &value) +{ + controls_[id] = value; +} + +/** + * \brief Update a control value in the list. + * \param info The ControlInfo of the control to update + * \param value The new value for the updated control + * + * Set the Control value in the list to the appropriate value. + * If the list already contains a control of the Id matching the ControlInfo + * then it will be overwritten. + */ +void ControlList::update(const ControlInfo &info, const Value &value) +{ + controls_[info] = value; +} + } /* namespace libcamera */ From patchwork Fri Jun 21 16:13:58 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Kieran Bingham X-Patchwork-Id: 1499 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 14664615AB for ; Fri, 21 Jun 2019 18:14:08 +0200 (CEST) Received: from localhost.localdomain (cpc89242-aztw30-2-0-cust488.18-1.cable.virginm.net [86.31.129.233]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id B236E67; Fri, 21 Jun 2019 18:14:07 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1561133647; bh=sMIEUyHP6455q7DFJ3S2G5zFuwEuRoYuAPlgKSKbygg=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Pdw1pv7FU8LYmakRJzxf+J6oC/qdNJ92LbOQmyjv4VQjLfKvqHPaW+wxUyPqn3W2D Tf9zkIAFjG/In7xSBlqhtMc5Sp5N3IS+LcHvQPOYg5AC4jIccnhfiXatrswnkaaOQ0 Dz0GPNdG3i9K3+BI1q5JH424uefqwV+fdWoFs5kI= From: Kieran Bingham To: LibCamera Devel Date: Fri, 21 Jun 2019 17:13:58 +0100 Message-Id: <20190621161401.28337-7-kieran.bingham@ideasonboard.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190621161401.28337-1-kieran.bingham@ideasonboard.com> References: <20190621161401.28337-1-kieran.bingham@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [RFC PATCH v2 6/9] libcamera: request: Add a ControlList X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 21 Jun 2019 16:14:08 -0000 Provide a ControlList on request objects to facilitate setting controls Signed-off-by: Kieran Bingham Reviewed-by: Niklas Söderlund --- include/libcamera/request.h | 3 +++ src/libcamera/request.cpp | 10 ++++++++++ 2 files changed, 13 insertions(+) diff --git a/include/libcamera/request.h b/include/libcamera/request.h index 58de6f00a554..8075270a9a12 100644 --- a/include/libcamera/request.h +++ b/include/libcamera/request.h @@ -11,6 +11,7 @@ #include #include +#include namespace libcamera { @@ -32,6 +33,7 @@ public: Request(const Request &) = delete; Request &operator=(const Request &) = delete; + ControlList &controls() { return controls_; } const std::map &buffers() const { return bufferMap_; } int setBuffers(const std::map &streamMap); Buffer *findBuffer(Stream *stream) const; @@ -50,6 +52,7 @@ private: bool completeBuffer(Buffer *buffer); Camera *camera_; + ControlList controls_; std::map bufferMap_; std::unordered_set pending_; diff --git a/src/libcamera/request.cpp b/src/libcamera/request.cpp index fa3ee46da440..9a0409b46017 100644 --- a/src/libcamera/request.cpp +++ b/src/libcamera/request.cpp @@ -52,6 +52,16 @@ Request::Request(Camera *camera) { } +/** + * \fn Request::controls() + * \brief Retrieve the request's ControlList + * + * Return a reference to the ControlList that stores all the controls relevant + * to this request. + * + * \return A reference to the ControlList in this request + */ + /** * \fn Request::buffers() * \brief Retrieve the request's streams to buffers map From patchwork Fri Jun 21 16:13:59 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Kieran Bingham X-Patchwork-Id: 1500 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 57DD3615FF for ; Fri, 21 Jun 2019 18:14:08 +0200 (CEST) Received: from localhost.localdomain (cpc89242-aztw30-2-0-cust488.18-1.cable.virginm.net [86.31.129.233]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 03DD633C; Fri, 21 Jun 2019 18:14:07 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1561133648; bh=FxHWjaUOq2Qab1TBN0eiVHm2pTJE3gPMBx0l/7AYuuk=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=RX6r0TGCUZwylRLnTmiINxZU9rI5tO528ep6/Lpl+LjsMoUEuELk4CCz+lkux98Yp gGf2J3/SsK81cI69x12UMGKv7j03wC/eonn4wI4NYCzwS3kFMXcBiMSH5u1c5d4Tei xnwc0AHwzCGBmxJHJLJlPYyJoZmSk2/WlJO3U51E= From: Kieran Bingham To: LibCamera Devel Date: Fri, 21 Jun 2019 17:13:59 +0100 Message-Id: <20190621161401.28337-8-kieran.bingham@ideasonboard.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190621161401.28337-1-kieran.bingham@ideasonboard.com> References: <20190621161401.28337-1-kieran.bingham@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [RFC PATCH v2 7/9] libcamera: test: Add ControlList tests X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 21 Jun 2019 16:14:08 -0000 Extend the Controls tests with specific testing of the ControlList infrastructure and public APIs. Signed-off-by: Kieran Bingham Reviewed-by: Niklas Söderlund --- test/controls.cpp | 99 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) diff --git a/test/controls.cpp b/test/controls.cpp index 94e89f270108..c4145b7a0543 100644 --- a/test/controls.cpp +++ b/test/controls.cpp @@ -25,6 +25,101 @@ protected: return TestPass; } + int testControlList() + { + ControlList list; + + if (list.contains(ManualGain)) { + cout << "Unexpected item in the bagging area" << endl; + return TestFail; + } + + if (list.size() != 0) { + cout << "List should contain zero elements" << endl; + return TestFail; + } + + if (!list.empty()) { + cout << "List expected to be empty" << endl; + return TestFail; + } + + /* Set a control */ + list[ManualBrightness] = 255; + + /* Contains should still not find a non set control */ + if (list.contains(ManualGain)) { + cout << "Unexpected item in the bagging area" << endl; + return TestFail; + } + + if (list.size() != 1) { + cout << "List should contain one element" << endl; + return TestFail; + } + + if (list.empty()) { + cout << "List not expected to be empty" << endl; + return TestFail; + } + + /* Finally lets find that Gain */ + list[ManualGain] = 128; + if (!list.contains(ManualGain)) { + cout << "Couldn't identify an in-list control" << endl; + return TestFail; + } + + /* Validate value retrieval */ + if (list[ManualGain].getInt() != 128 || + list[ManualBrightness].getInt() != 255) { + cout << "Failed to retrieve control value" << endl; + return TestFail; + } + + /* Update using ControlInfo */ + ControlInfo gainInfo(ManualGain); + list.update(gainInfo, 200); + if (list[ManualGain].getInt() != 200) { + cout << "Failed to update control value" << endl; + return TestFail; + } + + /* Create a new list from an existing one */ + ControlList newList; + + newList.update(list); + + /* + * Clear down the original list and assert items are still in + * the new list + */ + list.reset(); + + if (list.size() != 0) { + cout << "Old List should contain zero elements" << endl; + return TestFail; + } + + if (!list.empty()) { + cout << "Old List expected to be empty" << endl; + return TestFail; + } + + if (newList.size() != 2) { + cout << "New list with incorrect size" << endl; + return TestFail; + } + + if (!(newList.contains(ManualGain) && + newList.contains(ManualBrightness))) { + cout << "New list with incorrect items" << endl; + return TestFail; + } + + return TestPass; + } + int run() { int ret; @@ -33,6 +128,10 @@ protected: if (ret) return ret; + ret = testControlList(); + if (ret) + return ret; + return TestPass; } }; From patchwork Fri Jun 21 16:14:00 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kieran Bingham X-Patchwork-Id: 1501 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id A8E8F600F7 for ; Fri, 21 Jun 2019 18:14:08 +0200 (CEST) Received: from localhost.localdomain (cpc89242-aztw30-2-0-cust488.18-1.cable.virginm.net [86.31.129.233]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 4907D52A; Fri, 21 Jun 2019 18:14:08 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1561133648; bh=0wLOUMpJartSM/CFN0lzrHPCTIpwC5tvrXjd1gi13vY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=VD2cfcmsZqeFUOoplhHeX6GxE/n49nADOx/4N4uz4ONErpXKhM3rKhnzvuXeOHUzS xNRIFcF7XXFz/sl2UZ8bcMrlnNaE1Eko4ufZvkdXspWmc12RUw0krdqvNLf7eiKtH9 jehG03qnoTtmIUrRRtw/YjSyjvo3WE0p3/hMPpY4= From: Kieran Bingham To: LibCamera Devel Date: Fri, 21 Jun 2019 17:14:00 +0100 Message-Id: <20190621161401.28337-9-kieran.bingham@ideasonboard.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190621161401.28337-1-kieran.bingham@ideasonboard.com> References: <20190621161401.28337-1-kieran.bingham@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [RFC PATCH v2 8/9] [PoC] UVCPipelineHandler: Set Controls X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 21 Jun 2019 16:14:09 -0000 Provide an initial sketch of setting controls on the UVC Video Device making use of the V4L2Control API and interacting with Libcamera controls. This is not intended to be a full implementation, simply an initial demonstration of setting real-world controls from requests. Not-signed-off-by: Kieran Bingham --- src/libcamera/pipeline/uvcvideo.cpp | 43 ++++++++++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/src/libcamera/pipeline/uvcvideo.cpp b/src/libcamera/pipeline/uvcvideo.cpp index 2e22523d7cb1..14a2089ea654 100644 --- a/src/libcamera/pipeline/uvcvideo.cpp +++ b/src/libcamera/pipeline/uvcvideo.cpp @@ -8,6 +8,7 @@ #include #include +#include #include #include @@ -16,6 +17,7 @@ #include "media_device.h" #include "pipeline_handler.h" #include "utils.h" +#include "v4l2_controls.h" #include "v4l2_videodevice.h" namespace libcamera { @@ -71,6 +73,8 @@ public: bool match(DeviceEnumerator *enumerator) override; private: + int processControls(UVCCameraData *data, Request *request); + UVCCameraData *cameraData(const Camera *camera) { return static_cast( @@ -216,6 +220,39 @@ void PipelineHandlerUVC::stop(Camera *camera) PipelineHandler::stop(camera); } +int PipelineHandlerUVC::processControls(UVCCameraData *data, Request *request) +{ + V4L2Controls controls; + + for (auto it : request->controls()) { + const ControlInfo &ci = it.first; + Value &value = it.second; + + switch (ci.id()) { + case ManualBrightness: + LOG(UVC, Debug) << "Setting Brightness to : " << value; + controls.add(V4L2_CID_BRIGHTNESS, value.getInt()); + break; + case ManualExposure: + LOG(UVC, Debug) << "Setting Exposure to : " << value; + controls.add(V4L2_CID_EXPOSURE_AUTO, 1); + controls.add(V4L2_CID_EXPOSURE_ABSOLUTE, value.getInt()); + break; + case ManualGain: + default: + LOG(UVC, Debug) << "Unsupported control: " + << ci.name() << " : " << value; + break; + } + } + + int ret = data->video_->setControls(&controls); + if (ret) + LOG(UVC, Error) << "Failed to set controls"; + + return ret; +} + int PipelineHandlerUVC::queueRequest(Camera *camera, Request *request) { UVCCameraData *data = cameraData(camera); @@ -227,7 +264,11 @@ int PipelineHandlerUVC::queueRequest(Camera *camera, Request *request) return -ENOENT; } - int ret = data->video_->queueBuffer(buffer); + int ret = processControls(data, request); + if (ret < 0) + return ret; + + ret = data->video_->queueBuffer(buffer); if (ret < 0) return ret; From patchwork Fri Jun 21 16:14:01 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kieran Bingham X-Patchwork-Id: 1502 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 10367600F7 for ; Fri, 21 Jun 2019 18:14:09 +0200 (CEST) Received: from localhost.localdomain (cpc89242-aztw30-2-0-cust488.18-1.cable.virginm.net [86.31.129.233]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id A59B9E0C; Fri, 21 Jun 2019 18:14:08 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1561133648; bh=Wrhp2qftXZQNb0Emd9HGLPJnBdzpg7oEbuvLHCsDqaw=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=AwWoTgoAz9LHwFYHNdU62HcqR5Y9hZ6qrwFa+KIkPNBDEmcz1qifjuLVkgYNsWFrq QGlrDB1k9yO0ol3TMg9mZ4OlqO/LfBmVM/f7b0qBhEJUSxSueopPVwBUCT868GEO99 Ksqs1jYQpKi+ic1ajeZcVewCiYPHvTKLEYayD+GE= From: Kieran Bingham To: LibCamera Devel Date: Fri, 21 Jun 2019 17:14:01 +0100 Message-Id: <20190621161401.28337-10-kieran.bingham@ideasonboard.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190621161401.28337-1-kieran.bingham@ideasonboard.com> References: <20190621161401.28337-1-kieran.bingham@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [RFC PATCH v2 9/9] [PoC] QCam: Control demo: A SineWave Brightness X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 21 Jun 2019 16:14:09 -0000 As an example of how to add a control to each request, set the Brightness value with a changing value against the buffer time stamps. The Brightness will go up and down following a sine wave to visualise the control effect on the video stream. Signed-off-by: Kieran Bingham --- src/qcam/main_window.cpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/qcam/main_window.cpp b/src/qcam/main_window.cpp index 8c55941f137b..1449e020c815 100644 --- a/src/qcam/main_window.cpp +++ b/src/qcam/main_window.cpp @@ -5,6 +5,7 @@ * main_window.cpp - qcam - Main application window */ +#include #include #include #include @@ -219,6 +220,13 @@ void MainWindow::stopCapture() config_.reset(); } +int SineWaveValue(Buffer *buffer) +{ + unsigned int millisec = buffer->timestamp() / 1000000; + constexpr float rads = 2 * M_PI / 180; + return sin(0.036 * rads * millisec) * 100; +} + void MainWindow::requestComplete(Request *request, const std::map &buffers) { @@ -260,6 +268,14 @@ void MainWindow::requestComplete(Request *request, return; } + /* + * A demonstration control, which has a distinct visual effect. + * Scale the brightness up and down with a sine wave. + */ + /* How do we deal with max/min/defaults etc? */ + request->controls()[ManualBrightness] = SineWaveValue(buffer); + request->controls().update(ManualGain, SineWaveValue(buffer)); + request->setBuffers(buffers); camera_->queueRequest(request); }