diff options
Diffstat (limited to 'src/cam')
-rw-r--r-- | src/cam/main.cpp | 75 |
1 files changed, 64 insertions, 11 deletions
diff --git a/src/cam/main.cpp b/src/cam/main.cpp index 3dd4b24d..ac4c7e78 100644 --- a/src/cam/main.cpp +++ b/src/cam/main.cpp @@ -5,8 +5,10 @@ * main.cpp - cam - The libcamera swiss army knife */ +#include <algorithm> #include <iomanip> #include <iostream> +#include <limits.h> #include <map> #include <signal.h> #include <string.h> @@ -42,6 +44,9 @@ void signalHandler(int signal) static int parseOptions(int argc, char *argv[]) { KeyValueParser streamKeyValue; + streamKeyValue.addOption("role", OptionString, + "Role for the stream (viewfinder, video, still)", + ArgumentRequired); streamKeyValue.addOption("width", OptionInteger, "Width in pixels", ArgumentRequired); streamKeyValue.addOption("height", OptionInteger, "Height in pixels", @@ -61,7 +66,7 @@ static int parseOptions(int argc, char *argv[]) "The default file name is 'frame-#.bin'.", "file", ArgumentOptional, "filename"); parser.addOption(OptStream, &streamKeyValue, - "Set configuration of a camera stream", "stream"); + "Set configuration of a camera stream", "stream", true); parser.addOption(OptHelp, OptionNone, "Display this help message", "help"); parser.addOption(OptList, OptionNone, "List all cameras", "list"); @@ -80,11 +85,51 @@ static int parseOptions(int argc, char *argv[]) static int prepareCameraConfig(CameraConfiguration *config) { - *config = camera->streamConfiguration({ Stream::VideoRecording() }); - Stream *stream = config->front(); + std::vector<StreamUsage> roles; + + /* If no configuration is provided assume a single video stream. */ + if (!options.isSet(OptStream)) { + *config = camera->streamConfiguration({ Stream::VideoRecording() }); + return 0; + } + + const std::vector<OptionValue> &streamOptions = + options[OptStream].toArray(); + + /* Use roles and get a default configuration. */ + for (auto const &value : streamOptions) { + KeyValueParser::Options conf = value.toKeyValues(); + + if (!conf.isSet("role")) { + roles.push_back(Stream::VideoRecording()); + } else if (conf["role"].toString() == "viewfinder") { + roles.push_back(Stream::Viewfinder(conf["width"], + conf["height"])); + } else if (conf["role"].toString() == "video") { + roles.push_back(Stream::VideoRecording()); + } else if (conf["role"].toString() == "still") { + roles.push_back(Stream::StillCapture()); + } else { + std::cerr << "Unknown stream role " + << conf["role"].toString() << std::endl; + return -EINVAL; + } + } + + *config = camera->streamConfiguration(roles); + + if (!config->isValid()) { + std::cerr << "Failed to get default stream configuration" + << std::endl; + return -EINVAL; + } - if (options.isSet(OptStream)) { - KeyValueParser::Options conf = options[OptStream]; + /* Apply configuration explicitly requested. */ + CameraConfiguration::iterator it = config->begin(); + for (auto const &value : streamOptions) { + KeyValueParser::Options conf = value.toKeyValues(); + Stream *stream = *it; + it++; if (conf.isSet("width")) (*config)[stream].width = conf["width"]; @@ -136,7 +181,6 @@ static void requestComplete(Request *request, const std::map<Stream *, Buffer *> static int capture() { CameraConfiguration config; - std::vector<Request *> requests; int ret; ret = prepareCameraConfig(&config); @@ -151,8 +195,6 @@ static int capture() return ret; } - Stream *stream = config.front(); - ret = camera->allocateBuffers(); if (ret) { std::cerr << "Failed to allocate buffers" @@ -162,9 +204,18 @@ static int capture() camera->requestCompleted.connect(requestComplete); - BufferPool &pool = stream->bufferPool(); + /* Identify the stream with the least number of buffers. */ + unsigned int nbuffers = UINT_MAX; + for (Stream *stream : config) + nbuffers = std::min(nbuffers, stream->bufferPool().count()); + + /* + * TODO: make cam tool smarter to support still capture by for + * example pushing a button. For now run all streams all the time. + */ - for (Buffer &buffer : pool.buffers()) { + std::vector<Request *> requests; + for (unsigned int i = 0; i < nbuffers; i++) { Request *request = camera->createRequest(); if (!request) { std::cerr << "Can't create request" << std::endl; @@ -173,7 +224,9 @@ static int capture() } std::map<Stream *, Buffer *> map; - map[stream] = &buffer; + for (Stream *stream : config) + map[stream] = &stream->bufferPool().buffers()[i]; + ret = request->setBuffers(map); if (ret < 0) { std::cerr << "Can't set buffers for request" << std::endl; |