summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJacopo Mondi <jacopo@jmondi.org>2022-11-02 17:05:56 +0100
committerJacopo Mondi <jacopo@jmondi.org>2022-11-25 12:07:17 +0100
commitb35f04b3c19487de903b67340fcfb801557295d3 (patch)
treed84c2346112c9f3de7e9182589847632a912a573
parent87f5d12718b0ad83e2dd7fbbfe48e404ebaec092 (diff)
cam: capture_script: Support parsing array controls
Add support for parsing array controls to the cam capture script. Signed-off-by: Jacopo Mondi <jacopo@jmondi.org> Reviewed-by: Paul Elder <paul.elder@ideasonboard.com> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
-rw-r--r--src/apps/cam/capture_script.cpp158
-rw-r--r--src/apps/cam/capture_script.h5
2 files changed, 146 insertions, 17 deletions
diff --git a/src/apps/cam/capture_script.cpp b/src/apps/cam/capture_script.cpp
index 5a27361c..062a7258 100644
--- a/src/apps/cam/capture_script.cpp
+++ b/src/apps/cam/capture_script.cpp
@@ -454,24 +454,9 @@ void CaptureScript::unpackFailure(const ControlId *id, const std::string &repr)
<< typeName << " control " << id->name() << std::endl;
}
-ControlValue CaptureScript::unpackControl(const ControlId *id)
+ControlValue CaptureScript::parseScalarControl(const ControlId *id,
+ const std::string repr)
{
- /* Parse complex types. */
- switch (id->type()) {
- case ControlTypeRectangle:
- return parseRectangles();
- case ControlTypeSize:
- /* \todo Parse Sizes. */
- return {};
- default:
- break;
- }
-
- /* Parse basic types represented by a single scalar. */
- const std::string repr = parseScalar();
- if (repr.empty())
- return {};
-
ControlValue value{};
switch (id->type()) {
@@ -524,6 +509,145 @@ ControlValue CaptureScript::unpackControl(const ControlId *id)
return value;
}
+ControlValue CaptureScript::parseArrayControl(const ControlId *id,
+ const std::vector<std::string> &repr)
+{
+ ControlValue value{};
+
+ switch (id->type()) {
+ case ControlTypeNone:
+ break;
+ case ControlTypeBool: {
+ /*
+ * This is unpleasant, but we cannot use an std::vector<> as its
+ * boolean type overload does not allow to access the raw data,
+ * as boolean values are stored in a bitmask for efficiency.
+ *
+ * As we need a contiguous memory region to wrap in a Span<>,
+ * use an array instead but be strict about not overflowing it
+ * by limiting the number of controls we can store.
+ *
+ * Be loud but do not fail, as the issue would present at
+ * runtime and it's not fatal.
+ */
+ static constexpr unsigned int kMaxNumBooleanControls = 1024;
+ std::array<bool, kMaxNumBooleanControls> values;
+ unsigned int idx = 0;
+
+ for (const std::string &s : repr) {
+ bool val;
+
+ if (s == "true") {
+ val = true;
+ } else if (s == "false") {
+ val = false;
+ } else {
+ unpackFailure(id, s);
+ return value;
+ }
+
+ if (idx == kMaxNumBooleanControls) {
+ std::cerr << "Cannot parse more than "
+ << kMaxNumBooleanControls
+ << " boolean controls" << std::endl;
+ break;
+ }
+
+ values[idx++] = val;
+ }
+
+ value = Span<bool>(values.data(), idx);
+ break;
+ }
+ case ControlTypeByte: {
+ std::vector<uint8_t> values;
+ for (const std::string &s : repr) {
+ uint8_t val = strtoll(s.c_str(), NULL, 10);
+ values.push_back(val);
+ }
+
+ value = Span<const uint8_t>(values.data(), values.size());
+ break;
+ }
+ case ControlTypeInteger32: {
+ std::vector<int32_t> values;
+ for (const std::string &s : repr) {
+ int32_t val = strtoll(s.c_str(), NULL, 10);
+ values.push_back(val);
+ }
+
+ value = Span<const int32_t>(values.data(), values.size());
+ break;
+ }
+ case ControlTypeInteger64: {
+ std::vector<int64_t> values;
+ for (const std::string &s : repr) {
+ int64_t val = strtoll(s.c_str(), NULL, 10);
+ values.push_back(val);
+ }
+
+ value = Span<const int64_t>(values.data(), values.size());
+ break;
+ }
+ case ControlTypeFloat: {
+ std::vector<float> values;
+ for (const std::string &s : repr)
+ values.push_back(strtof(s.c_str(), NULL));
+
+ value = Span<const float>(values.data(), values.size());
+ break;
+ }
+ case ControlTypeString: {
+ value = Span<const std::string>(repr.data(), repr.size());
+ break;
+ }
+ default:
+ std::cerr << "Unsupported control type" << std::endl;
+ break;
+ }
+
+ return value;
+}
+
+ControlValue CaptureScript::unpackControl(const ControlId *id)
+{
+ /* Parse complex types. */
+ switch (id->type()) {
+ case ControlTypeRectangle:
+ return parseRectangles();
+ case ControlTypeSize:
+ /* \todo Parse Sizes. */
+ return {};
+ default:
+ break;
+ }
+
+ /* Check if the control has a single scalar value or is an array. */
+ EventPtr event = nextEvent();
+ if (!event)
+ return {};
+
+ switch (event->type) {
+ case YAML_SCALAR_EVENT: {
+ const std::string repr = eventScalarValue(event);
+ if (repr.empty())
+ return {};
+
+ return parseScalarControl(id, repr);
+ }
+ case YAML_SEQUENCE_START_EVENT: {
+ std::vector<std::string> array = parseSingleArray();
+ if (array.empty())
+ return {};
+
+ return parseArrayControl(id, array);
+ }
+ default:
+ std::cerr << "Unexpected event type: " << event->type << std::endl;
+ return {};
+ }
+}
+
libcamera::Rectangle CaptureScript::unpackRectangle(const std::vector<std::string> &strVec)
{
int x = strtol(strVec[0].c_str(), NULL, 10);
diff --git a/src/apps/cam/capture_script.h b/src/apps/cam/capture_script.h
index 7a0ddebb..40042c03 100644
--- a/src/apps/cam/capture_script.h
+++ b/src/apps/cam/capture_script.h
@@ -56,6 +56,11 @@ private:
int parseFrame(EventPtr event);
int parseControl(EventPtr event, libcamera::ControlList &controls);
+ libcamera::ControlValue parseScalarControl(const libcamera::ControlId *id,
+ const std::string repr);
+ libcamera::ControlValue parseArrayControl(const libcamera::ControlId *id,
+ const std::vector<std::string> &repr);
+
std::string parseScalar();
libcamera::ControlValue parseRectangles();
std::vector<std::vector<std::string>> parseArrays();