[libcamera-devel,RFC,2/2] cam: make the --format option take arguments

Message ID 20190125212154.26950-3-niklas.soderlund@ragnatech.se
State Superseded
Delegated to: Niklas Söderlund
Headers show
Series
  • cam: make the --format option take arguments
Related show

Commit Message

Niklas Söderlund Jan. 25, 2019, 9:21 p.m. UTC
Instead of configuring a static frame dimension of 640x480 make the
format option take a list of arguments and parse the width, height and
pixel format from that list.

The pixel format is still specified as a integer which should correspond
to the kernels FOURCC identifiers. Going forward this should be turned
into a string representation and the cam parser should translate between
the two.

Signed-off-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>
---
 src/cam/main.cpp | 71 ++++++++++++++++++++++++++++++++++++++++++------
 1 file changed, 63 insertions(+), 8 deletions(-)

Patch

diff --git a/src/cam/main.cpp b/src/cam/main.cpp
index b8c05d9079be3cb3..9fee77d6ddec31bc 100644
--- a/src/cam/main.cpp
+++ b/src/cam/main.cpp
@@ -41,7 +41,15 @@  static int parseOptions(int argc, char *argv[])
 	parser.addOption(OptCamera, "Specify which camera to operate on",
 			 "camera", OptionsParser::ArgumentRequired,
 			 "camera");
-	parser.addOption(OptFormat, "Configure the first stream to 640x480", "format");
+	parser.addOption(OptFormat,
+			 "Set format of the cameras first stream\n"
+			 "\tformatdesc is a string of key=value pairs joined by a commas\n\n"
+			 "\twidth=<w>             Specify the width (int)\n"
+			 "\theight=<w>            Specify the height (int)\n"
+			 "\tpixelformat=<pf>      Specify the pixelformat (int)\n"
+			 "\n\tAny combination of options are valid, example: --format width=800,height=600",
+			 "format", OptionsParser::ArgumentRequired,
+			 "formatdesc");
 	parser.addOption(OptHelp, "Display this help message", "help");
 	parser.addOption(OptList, "List all cameras", "list");
 
@@ -57,6 +65,57 @@  static int parseOptions(int argc, char *argv[])
 	return 0;
 }
 
+int str2uint(std::string str, unsigned int *dest)
+{
+	unsigned long tmp = stoul(str);
+	*dest = tmp;
+	if (*dest != tmp)
+		return -EINVAL;;
+	return 0;
+}
+
+bool configureStreams(Camera *camera, const std::string &arg)
+{
+	SubOptionsParser parser;
+	parser.addToken("width");
+	parser.addToken("height");
+	parser.addToken("pixelformat");
+	SubOptionsParser::Options format = parser.parse(arg.c_str());
+
+	if (!format.valid())
+		return false;
+
+	std::vector<Stream> streams = camera->streams();
+	StreamConfiguration config = StreamConfiguration(streams.front());
+
+	if (format.isSet("width") && format.isSet("height")) {
+		unsigned int width, height;
+
+		if (str2uint(format["width"], &width) || str2uint(format["height"], &height))
+			return false;
+
+		config.setDimension(width, height);
+	}
+
+	if (format.isSet("pixelformat")) {
+		unsigned int pixelformat;
+
+		/* TODO: Translate 4CC string to ID. */
+		if (str2uint(format["pixelformat"], &pixelformat))
+			return false;
+
+		config.setPixelFormat(pixelformat);
+	}
+
+	std::vector<StreamConfiguration *> configs;
+	configs.push_back(&config);
+
+	if (camera->configure(configs))
+		return false;
+
+	return true;
+}
+
 int main(int argc, char **argv)
 {
 	int ret;
@@ -117,14 +176,10 @@  int main(int argc, char **argv)
 			goto out_camera;
 		}
 
-		StreamConfiguration config = StreamConfiguration(streams.front());
-		config.setDimension(640, 480);
-
-		std::vector<StreamConfiguration *> configs;
-		configs.push_back(&config);
-
-		if (camera->configure(configs))
+		if (!configureStreams(camera.get(), options[OptFormat])) {
 			std::cout << "Failed to configure camera" << std::endl;
+			goto out_camera;
+		}
 	}
 
 	ret = loop->exec();