summaryrefslogtreecommitdiff
path: root/src/ipa/raspberrypi/controller/controller.cpp
blob: d3433ad2e7e8266a3c1623a60c7cfe9f4e45e82d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
/* SPDX-License-Identifier: BSD-2-Clause */
/*
 * Copyright (C) 2019, Raspberry Pi (Trading) Limited
 *
 * controller.cpp - ISP controller
 */

#include <libcamera/base/log.h>

#include "algorithm.hpp"
#include "controller.hpp"

#include <boost/property_tree/json_parser.hpp>
#include <boost/property_tree/ptree.hpp>

using namespace RPiController;
using namespace libcamera;

LOG_DEFINE_CATEGORY(RPiController)

Controller::Controller()
	: switch_mode_called_(false) {}

Controller::Controller(char const *json_filename)
	: switch_mode_called_(false)
{
	Read(json_filename);
	Initialise();
}

Controller::~Controller() {}

void Controller::Read(char const *filename)
{
	boost::property_tree::ptree root;
	boost::property_tree::read_json(filename, root);
	for (auto const &key_and_value : root) {
		Algorithm *algo = CreateAlgorithm(key_and_value.first.c_str());
		if (algo) {
			algo->Read(key_and_value.second);
			algorithms_.push_back(AlgorithmPtr(algo));
		} else
			LOG(RPiController, Warning)
				<< "No algorithm found for \"" << key_and_value.first << "\"";
	}
}

Algorithm *Controller::CreateAlgorithm(char const *name)
{
	auto it = GetAlgorithms().find(std::string(name));
	return it != GetAlgorithms().end() ? (*it->second)(this) : nullptr;
}

void Controller::Initialise()
{
	for (auto &algo : algorithms_)
		algo->Initialise();
}

void Controller::SwitchMode(CameraMode const &camera_mode, Metadata *metadata)
{
	for (auto &algo : algorithms_)
		algo->SwitchMode(camera_mode, metadata);
	switch_mode_called_ = true;
}

void Controller::Prepare(Metadata *image_metadata)
{
	assert(switch_mode_called_);
	for (auto &algo : algorithms_)
		if (!algo->IsPaused())
			algo->Prepare(image_metadata);
}

void Controller::Process(StatisticsPtr stats, Metadata *image_metadata)
{
	assert(switch_mode_called_);
	for (auto &algo : algorithms_)
		if (!algo->IsPaused())
			algo->Process(stats, image_metadata);
}

Metadata &Controller::GetGlobalMetadata()
{
	return global_metadata_;
}

Algorithm *Controller::GetAlgorithm(std::string const &name) const
{
	// The passed name must be the entire algorithm name, or must match the
	// last part of it with a period (.) just before.
	size_t name_len = name.length();
	for (auto &algo : algorithms_) {
		char const *algo_name = algo->Name();
		size_t algo_name_len = strlen(algo_name);
		if (algo_name_len >= name_len &&
		    strcasecmp(name.c_str(),
			       algo_name + algo_name_len - name_len) == 0 &&
		    (name_len == algo_name_len ||
		     algo_name[algo_name_len - name_len - 1] == '.'))
			return algo.get();
	}
	return nullptr;
}
class="hl opt">, }; namespace details { template<typename T> struct control_type { }; template<> struct control_type<void> { static constexpr ControlType value = ControlTypeNone; }; template<> struct control_type<bool> { static constexpr ControlType value = ControlTypeBool; }; template<> struct control_type<uint8_t> { static constexpr ControlType value = ControlTypeByte; }; template<> struct control_type<int32_t> { static constexpr ControlType value = ControlTypeInteger32; }; template<> struct control_type<int64_t> { static constexpr ControlType value = ControlTypeInteger64; }; template<> struct control_type<float> { static constexpr ControlType value = ControlTypeFloat; }; template<> struct control_type<std::string> { static constexpr ControlType value = ControlTypeString; }; template<> struct control_type<Rectangle> { static constexpr ControlType value = ControlTypeRectangle; }; template<> struct control_type<Size> { static constexpr ControlType value = ControlTypeSize; }; template<typename T, std::size_t N> struct control_type<Span<T, N>> : public control_type<std::remove_cv_t<T>> { }; } /* namespace details */ class ControlValue { public: ControlValue(); #ifndef __DOXYGEN__ template<typename T, typename std::enable_if_t<!details::is_span<T>::value && details::control_type<T>::value && !std::is_same<std::string, std::remove_cv_t<T>>::value, std::nullptr_t> = nullptr> ControlValue(const T &value) : type_(ControlTypeNone), numElements_(0) { set(details::control_type<std::remove_cv_t<T>>::value, false, &value, 1, sizeof(T)); } template<typename T, typename std::enable_if_t<details::is_span<T>::value || std::is_same<std::string, std::remove_cv_t<T>>::value, std::nullptr_t> = nullptr> #else template<typename T> #endif ControlValue(const T &value) : type_(ControlTypeNone), numElements_(0) { set(details::control_type<std::remove_cv_t<T>>::value, true, value.data(), value.size(), sizeof(typename T::value_type)); } ~ControlValue(); ControlValue(const ControlValue &other); ControlValue &operator=(const ControlValue &other); ControlType type() const { return type_; } bool isNone() const { return type_ == ControlTypeNone; } bool isArray() const { return isArray_; } std::size_t numElements() const { return numElements_; } Span<const uint8_t> data() const; Span<uint8_t> data(); std::string toString() const; bool operator==(const ControlValue &other) const; bool operator!=(const ControlValue &other) const { return !(*this == other); } #ifndef __DOXYGEN__ template<typename T, typename std::enable_if_t<!details::is_span<T>::value && !std::is_same<std::string, std::remove_cv_t<T>>::value, std::nullptr_t> = nullptr> T get() const { assert(type_ == details::control_type<std::remove_cv_t<T>>::value); assert(!isArray_); return *reinterpret_cast<const T *>(data().data()); } template<typename T, typename std::enable_if_t<details::is_span<T>::value || std::is_same<std::string, std::remove_cv_t<T>>::value, std::nullptr_t> = nullptr> #else template<typename T> #endif T get() const { assert(type_ == details::control_type<std::remove_cv_t<T>>::value); assert(isArray_); using V = typename T::value_type; const V *value = reinterpret_cast<const V *>(data().data()); return { value, numElements_ }; } #ifndef __DOXYGEN__ template<typename T, typename std::enable_if_t<!details::is_span<T>::value && !std::is_same<std::string, std::remove_cv_t<T>>::value, std::nullptr_t> = nullptr> void set(const T &value) { set(details::control_type<std::remove_cv_t<T>>::value, false, reinterpret_cast<const void *>(&value), 1, sizeof(T)); } template<typename T, typename std::enable_if_t<details::is_span<T>::value || std::is_same<std::string, std::remove_cv_t<T>>::value, std::nullptr_t> = nullptr> #else template<typename T> #endif void set(const T &value) { set(details::control_type<std::remove_cv_t<T>>::value, true, value.data(), value.size(), sizeof(typename T::value_type)); } void reserve(ControlType type, bool isArray = false, std::size_t numElements = 1); private: ControlType type_ : 8; bool isArray_; std::size_t numElements_ : 32; union { uint64_t value_; void *storage_; }; void release(); void set(ControlType type, bool isArray, const void *data, std::size_t numElements, std::size_t elementSize); }; class ControlId { public: ControlId(unsigned int id, const std::string &name, ControlType type) : id_(id), name_(name), type_(type) { } unsigned int id() const { return id_; } const std::string &name() const { return name_; } ControlType type() const { return type_; } private: LIBCAMERA_DISABLE_COPY_AND_MOVE(ControlId) unsigned int id_; std::string name_; ControlType type_; }; static inline bool operator==(unsigned int lhs, const ControlId &rhs) { return lhs == rhs.id(); } static inline bool operator!=(unsigned int lhs, const ControlId &rhs) { return !(lhs == rhs); } static inline bool operator==(const ControlId &lhs, unsigned int rhs) { return lhs.id() == rhs; } static inline bool operator!=(const ControlId &lhs, unsigned int rhs) { return !(lhs == rhs); } template<typename T> class Control : public ControlId { public: using type = T; Control(unsigned int id, const char *name) : ControlId(id, name, details::control_type<std::remove_cv_t<T>>::value) { } private: LIBCAMERA_DISABLE_COPY_AND_MOVE(Control) }; class ControlInfo { public: explicit ControlInfo(const ControlValue &min = 0, const ControlValue &max = 0, const ControlValue &def = 0); explicit ControlInfo(Span<const ControlValue> values, const ControlValue &def = {}); const ControlValue &min() const { return min_; } const ControlValue &max() const { return max_; } const ControlValue &def() const { return def_; } const std::vector<ControlValue> &values() const { return values_; } std::string toString() const; bool operator==(const ControlInfo &other) const { return min_ == other.min_ && max_ == other.max_; } bool operator!=(const ControlInfo &other) const { return !(*this == other); } private: ControlValue min_; ControlValue max_; ControlValue def_; std::vector<ControlValue> values_; }; using ControlIdMap = std::unordered_map<unsigned int, const ControlId *>; class ControlInfoMap : private std::unordered_map<const ControlId *, ControlInfo> { public: using Map = std::unordered_map<const ControlId *, ControlInfo>; ControlInfoMap() = default; ControlInfoMap(const ControlInfoMap &other) = default; ControlInfoMap(std::initializer_list<Map::value_type> init); ControlInfoMap(Map &&info); ControlInfoMap &operator=(const ControlInfoMap &other) = default; ControlInfoMap &operator=(std::initializer_list<Map::value_type> init); ControlInfoMap &operator=(Map &&info); using Map::key_type; using Map::mapped_type; using Map::value_type; using Map::size_type; using Map::iterator; using Map::const_iterator; using Map::begin; using Map::cbegin; using Map::end; using Map::cend; using Map::at; using Map::empty; using Map::size; using Map::count; using Map::find; mapped_type &at(unsigned int key); const mapped_type &at(unsigned int key) const; size_type count(unsigned int key) const; iterator find(unsigned int key); const_iterator find(unsigned int key) const; const ControlIdMap &idmap() const { return idmap_; } private: void generateIdmap(); ControlIdMap idmap_; }; class ControlList { private: using ControlListMap = std::unordered_map<unsigned int, ControlValue>; public: ControlList(); ControlList(const ControlIdMap &idmap, ControlValidator *validator = nullptr); ControlList(const ControlInfoMap &infoMap, ControlValidator *validator = nullptr); 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 empty() const { return controls_.empty(); } std::size_t size() const { return controls_.size(); } void clear() { controls_.clear(); } void merge(const ControlList &source); bool contains(const ControlId &id) const; bool contains(unsigned int id) const; template<typename T> T get(const Control<T> &ctrl) const { const ControlValue *val = find(ctrl.id()); if (!val) return T{}; return val->get<T>(); } template<typename T, typename V> void set(const Control<T> &ctrl, const V &value) { ControlValue *val = find(ctrl.id()); if (!val) return; val->set<T>(value); } template<typename T, typename V> void set(const Control<T> &ctrl, const std::initializer_list<V> &value) { ControlValue *val = find(ctrl.id()); if (!val) return; val->set<T>(Span<const typename std::remove_cv_t<V>>{ value.begin(), value.size() }); } const ControlValue &get(unsigned int id) const; void set(unsigned int id, const ControlValue &value); const ControlInfoMap *infoMap() const { return infoMap_; } private: const ControlValue *find(unsigned int id) const; ControlValue *find(unsigned int id); ControlValidator *validator_; const ControlIdMap *idmap_; const ControlInfoMap *infoMap_; ControlListMap controls_; }; } /* namespace libcamera */ #endif /* __LIBCAMERA_CONTROLS_H__ */