[libcamera-devel] [PATCH 1/3] cam: Add helper class to parse stream configuration

Niklas Söderlund niklas.soderlund at ragnatech.se
Fri Apr 24 03:16:54 CEST 2020


Create a new helper class StreamOptionsParser to parse command line
options describing stream configurations. The goal is to share this new
class between cam and qcam.

The parser inherits from OptionsParser which it aims to replace and
allows for a common command line argument syntax to be inserted anywhere
in the argument list with addStreamOptions(), still allowing for any
short and long option name.

The Options data carrier returned inherits from OptionsParser::Options
and extends it with new functions; roles() and applyCameraParameters().
The new functions makes it easy to generate and override the default
values of a camera configuration.

Signed-off-by: Niklas Söderlund <niklas.soderlund at ragnatech.se>
---
 src/cam/meson.build        |   1 +
 src/cam/stream_options.cpp | 116 +++++++++++++++++++++++++++++++++++++
 src/cam/stream_options.h   |  63 ++++++++++++++++++++
 3 files changed, 180 insertions(+)
 create mode 100644 src/cam/stream_options.cpp
 create mode 100644 src/cam/stream_options.h

diff --git a/src/cam/meson.build b/src/cam/meson.build
index 2419d648bc17e02b..162d6333f94e4851 100644
--- a/src/cam/meson.build
+++ b/src/cam/meson.build
@@ -4,6 +4,7 @@ cam_sources = files([
     'event_loop.cpp',
     'main.cpp',
     'options.cpp',
+    'stream_options.cpp',
 ])
 
 cam  = executable('cam', cam_sources,
diff --git a/src/cam/stream_options.cpp b/src/cam/stream_options.cpp
new file mode 100644
index 0000000000000000..22bf61f2c13d10c1
--- /dev/null
+++ b/src/cam/stream_options.cpp
@@ -0,0 +1,116 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (C) 2020, Raspberry Pi (Trading) Ltd.
+ *
+ * stream_options.cpp - Helper to parse options for stremas
+ */
+#include "stream_options.h"
+
+#include <iostream>
+
+using namespace libcamera;
+
+int StreamOptionsParser::Options::applyCameraParameters(CameraConfiguration *config) const
+{
+	if (!config) {
+		std::cerr << "No configuration provided" << std::endl;
+		return -EINVAL;
+	}
+
+	if (config->size() != streamParameters_.size()) {
+		std::cerr
+			<< "Number of streams in configuration "
+			<< config->size()
+			<< " does not match number of streams parsed "
+			<< streamParameters_.size()
+			<< std::endl;
+		return -EINVAL;
+	}
+
+	unsigned int i = 0;
+	for (auto const &param : streamParameters_) {
+		StreamConfiguration &cfg = config->at(i++);
+
+		if (param.size.width && param.size.height)
+			cfg.size = param.size;
+
+		if (param.pixelFormat.isValid())
+			cfg.pixelFormat = param.pixelFormat;
+	}
+
+	return 0;
+}
+
+int StreamOptionsParser::addStreamOptions(int opt, const char *name)
+{
+	if (opt_)
+		return -EINVAL;
+
+	opt_ = opt;
+
+	streamKeyValue_.addOption("role", OptionString,
+				  "Role for the stream (viewfinder, video, still, stillraw)",
+				  ArgumentRequired);
+	streamKeyValue_.addOption("width", OptionInteger, "Width in pixels",
+				  ArgumentRequired);
+	streamKeyValue_.addOption("height", OptionInteger, "Height in pixels",
+				  ArgumentRequired);
+	streamKeyValue_.addOption("pixelformat", OptionInteger, "Pixel format",
+				  ArgumentRequired);
+
+	return addOption(opt_, &streamKeyValue_,
+			 "Set configuration of a camera stream", name, true);
+}
+
+StreamOptionsParser::Options StreamOptionsParser::parse(int argc, char *argv[])
+{
+	OptionsParser::Options options = OptionsParser::parse(argc, argv);
+
+	if (!opt_ || !options.isSet(opt_))
+		return Options(options, {StreamRole::Viewfinder});
+
+	StreamRoles roles;
+	std::vector<Options::Parameters> parameters;
+
+	for (auto const &value : options[opt_].toArray()) {
+		KeyValueParser::Options opts = value.toKeyValues();
+		Options::Parameters param;
+
+		if (opts.isSet("width") && opts.isSet("height")) {
+			param.size.width = opts["width"];
+			param.size.height = opts["height"];
+		}
+
+		/* TODO: Translate 4CC string to ID. */
+		if (opts.isSet("pixelformat"))
+			param.pixelFormat = PixelFormat(opts["pixelformat"]);
+
+		roles.push_back(parseRole(opts));
+		parameters.push_back(param);
+	}
+
+	return Options(options, roles, parameters);
+}
+
+StreamRole StreamOptionsParser::parseRole(KeyValueParser::Options opts)
+{
+	if (!opts.isSet("role"))
+		return StreamRole::Viewfinder;
+
+	std::string role = opts["role"].toString();
+
+	if (role == "viewfinder")
+		return StreamRole::Viewfinder;
+	if (role == "video")
+		return StreamRole::VideoRecording;
+	if (role == "still")
+		return StreamRole::StillCapture;
+	if (role == "stillraw")
+		return StreamRole::StillCaptureRaw;
+
+	/* No stream role found, warn and default to viewfinder. */
+	std::cerr << "Unknown stream role " << role
+		  << ", adjusted to viewfinder" << std::endl;
+
+	return StreamRole::Viewfinder;
+}
diff --git a/src/cam/stream_options.h b/src/cam/stream_options.h
new file mode 100644
index 0000000000000000..a0f8a456b44fe275
--- /dev/null
+++ b/src/cam/stream_options.h
@@ -0,0 +1,63 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (C) 2020, Raspberry Pi (Trading) Ltd.
+ *
+ * stream_options.h - Helper to parse options for stremas
+ */
+#ifndef __CAM_STREAM_OPTIONS_H__
+#define __CAM_STREAM_OPTIONS_H__
+
+#include <libcamera/camera.h>
+#include <libcamera/stream.h>
+
+#include "options.h"
+
+using namespace libcamera;
+
+class StreamOptionsParser : public OptionsParser
+{
+public:
+	class Options : public OptionsParser::Options
+	{
+	public:
+		struct Parameters {
+			PixelFormat pixelFormat;
+			Size size;
+		};
+
+		Options()
+			: OptionsParser::Options()
+		{
+		}
+
+		Options(OptionsParser::Options options, StreamRoles roles = {},
+			std::vector<Parameters> parameters = {})
+			: OptionsParser::Options(options), roles_(roles),
+			  streamParameters_(parameters)
+		{
+		}
+
+		const StreamRoles &roles() const { return roles_; }
+		int applyCameraParameters(CameraConfiguration *config) const;
+
+	private:
+		StreamRoles roles_;
+		std::vector<Parameters> streamParameters_;
+	};
+
+	StreamOptionsParser()
+		: opt_(0)
+	{
+	}
+
+	int addStreamOptions(int opt, const char *name = nullptr);
+	Options parse(int argc, char *argv[]);
+
+private:
+	StreamRole parseRole(KeyValueParser::Options opts);
+
+	int opt_;
+	KeyValueParser streamKeyValue_;
+};
+
+#endif /* __CAM_STREAM_OPTIONS_H__ */
-- 
2.26.0



More information about the libcamera-devel mailing list