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>
This commit is contained in:
Jacopo Mondi 2022-11-02 17:05:56 +01:00
parent 87f5d12718
commit b35f04b3c1
2 changed files with 146 additions and 17 deletions

View file

@ -454,24 +454,9 @@ void CaptureScript::unpackFailure(const ControlId *id, const std::string &repr)
<< typeName << " control " << id->name() << std::endl; << 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{}; ControlValue value{};
switch (id->type()) { switch (id->type()) {
@ -524,6 +509,145 @@ ControlValue CaptureScript::unpackControl(const ControlId *id)
return value; 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) libcamera::Rectangle CaptureScript::unpackRectangle(const std::vector<std::string> &strVec)
{ {
int x = strtol(strVec[0].c_str(), NULL, 10); int x = strtol(strVec[0].c_str(), NULL, 10);

View file

@ -56,6 +56,11 @@ private:
int parseFrame(EventPtr event); int parseFrame(EventPtr event);
int parseControl(EventPtr event, libcamera::ControlList &controls); 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(); std::string parseScalar();
libcamera::ControlValue parseRectangles(); libcamera::ControlValue parseRectangles();
std::vector<std::vector<std::string>> parseArrays(); std::vector<std::vector<std::string>> parseArrays();