cam: capture_script: Introduce 'loop' property

Add support to the capture script for properties that control the script
execution. Script properties are specified in the 'properties' section
before the actual list of controls specified in the 'frames' section.

Define a first 'loop' property that allows repeating the frame list
periodically. All the frame ids in the 'frames' section shall be smaller
than the loop control.

Modify the capture script example to show usage of the 'loop' property
and better document the frames list while at it.

Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>
Reviewed-by: Paul Elder <paul.elder@ideasonboard.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
This commit is contained in:
Jacopo Mondi 2022-09-02 16:54:43 +02:00
parent 74ab3f778c
commit cf5d0cbb34
3 changed files with 107 additions and 5 deletions

View file

@ -4,6 +4,19 @@
# #
# A capture script allows to associate a list of controls and their values # A capture script allows to associate a list of controls and their values
# to frame numbers. # to frame numbers.
#
# The script allows defining a list of frames associated with controls
# and an optional list of properties that can control the script behaviour.
# properties:
# # Repeat the controls every 'idx' frames.
# - loop: idx
#
# # List of frame number with associated a list of controls to be applied
# frames:
# - frame-number:
# Control1: value1
# Control2: value2
# \todo Formally define the capture script structure with a schema # \todo Formally define the capture script structure with a schema
@ -12,10 +25,16 @@
# libcamera::controls:: enumeration # libcamera::controls:: enumeration
# - Controls not supported by the camera currently operated are ignored # - Controls not supported by the camera currently operated are ignored
# - Frame numbers shall be monotonically incrementing, gaps are allowed # - Frame numbers shall be monotonically incrementing, gaps are allowed
# - If a loop limit is specified, frame numbers in the 'frames' list shall be
# less than the loop control
# Example: Turn brightness up and down every 460 frames
properties:
- loop: 460
# Example:
frames: frames:
- 1: - 0:
Brightness: 0.0 Brightness: 0.0
- 40: - 40:
@ -44,3 +63,9 @@ frames:
- 340: - 340:
Brightness: -0.8 Brightness: -0.8
- 380:
Brightness: -0.4
- 420:
Brightness: -0.2

View file

@ -15,7 +15,7 @@ using namespace libcamera;
CaptureScript::CaptureScript(std::shared_ptr<Camera> camera, CaptureScript::CaptureScript(std::shared_ptr<Camera> camera,
const std::string &fileName) const std::string &fileName)
: camera_(camera), valid_(false) : camera_(camera), loop_(0), valid_(false)
{ {
FILE *fh = fopen(fileName.c_str(), "r"); FILE *fh = fopen(fileName.c_str(), "r");
if (!fh) { if (!fh) {
@ -44,8 +44,13 @@ CaptureScript::CaptureScript(std::shared_ptr<Camera> camera,
const ControlList &CaptureScript::frameControls(unsigned int frame) const ControlList &CaptureScript::frameControls(unsigned int frame)
{ {
static ControlList controls{}; static ControlList controls{};
unsigned int idx = frame;
auto it = frameControls_.find(frame); /* If we loop, repeat the controls every 'loop_' frames. */
if (loop_)
idx = frame % loop_;
auto it = frameControls_.find(idx);
if (it == frameControls_.end()) if (it == frameControls_.end())
return controls; return controls;
@ -149,7 +154,11 @@ int CaptureScript::parseScript(FILE *script)
std::string section = eventScalarValue(event); std::string section = eventScalarValue(event);
if (section == "frames") { if (section == "properties") {
ret = parseProperties();
if (ret)
return ret;
} else if (section == "frames") {
ret = parseFrames(); ret = parseFrames();
if (ret) if (ret)
return ret; return ret;
@ -161,6 +170,65 @@ int CaptureScript::parseScript(FILE *script)
} }
} }
int CaptureScript::parseProperty()
{
EventPtr event = nextEvent(YAML_MAPPING_START_EVENT);
if (!event)
return -EINVAL;
std::string prop = parseScalar();
if (prop.empty())
return -EINVAL;
if (prop == "loop") {
event = nextEvent();
if (!event)
return -EINVAL;
std::string value = eventScalarValue(event);
if (value.empty())
return -EINVAL;
loop_ = atoi(value.c_str());
if (!loop_) {
std::cerr << "Invalid loop limit '" << loop_ << "'"
<< std::endl;
return -EINVAL;
}
} else {
std::cerr << "Unsupported property '" << prop << "'" << std::endl;
return -EINVAL;
}
event = nextEvent(YAML_MAPPING_END_EVENT);
if (!event)
return -EINVAL;
return 0;
}
int CaptureScript::parseProperties()
{
EventPtr event = nextEvent(YAML_SEQUENCE_START_EVENT);
if (!event)
return -EINVAL;
while (1) {
if (event->type == YAML_SEQUENCE_END_EVENT)
return 0;
int ret = parseProperty();
if (ret)
return ret;
event = nextEvent();
if (!event)
return -EINVAL;
}
return 0;
}
int CaptureScript::parseFrames() int CaptureScript::parseFrames()
{ {
EventPtr event = nextEvent(YAML_SEQUENCE_START_EVENT); EventPtr event = nextEvent(YAML_SEQUENCE_START_EVENT);
@ -191,6 +259,12 @@ int CaptureScript::parseFrame(EventPtr event)
return -EINVAL; return -EINVAL;
unsigned int frameId = atoi(key.c_str()); unsigned int frameId = atoi(key.c_str());
if (loop_ && frameId >= loop_) {
std::cerr
<< "Frame id (" << frameId << ") shall be smaller than"
<< "loop limit (" << loop_ << ")" << std::endl;
return -EINVAL;
}
event = nextEvent(YAML_MAPPING_START_EVENT); event = nextEvent(YAML_MAPPING_START_EVENT);
if (!event) if (!event)

View file

@ -40,6 +40,7 @@ private:
std::map<unsigned int, libcamera::ControlList> frameControls_; std::map<unsigned int, libcamera::ControlList> frameControls_;
std::shared_ptr<libcamera::Camera> camera_; std::shared_ptr<libcamera::Camera> camera_;
yaml_parser_t parser_; yaml_parser_t parser_;
unsigned int loop_;
bool valid_; bool valid_;
EventPtr nextEvent(yaml_event_type_t expectedType = YAML_NO_EVENT); EventPtr nextEvent(yaml_event_type_t expectedType = YAML_NO_EVENT);
@ -49,6 +50,8 @@ private:
int parseScript(FILE *script); int parseScript(FILE *script);
int parseProperties();
int parseProperty();
int parseFrames(); int parseFrames();
int parseFrame(EventPtr event); int parseFrame(EventPtr event);
int parseControl(EventPtr event, libcamera::ControlList &controls); int parseControl(EventPtr event, libcamera::ControlList &controls);