[RFC PATCH 7/7] apps: cam: Add command line options for stream specific outputs
Milan Zamazal
mzamazal at redhat.com
Fri Mar 14 21:29:35 CET 2025
Now, when the support for multiple outputs is ready, let's add command
line options to actually use it.
To remain backward compatible and to keep the things simple for the
user, the original output related command line options work as before.
For example, simply running
cam -c1 -C -D
or
cam ... -s role=viewfinder,... -s role=raw,... -Fimage#
still works.
But the user can also specify a different output for each of the given
streams now, for example:
cam ... -s role=viewfinder,... --stream-display \
-s role=raw,... --stream-file=raw#
or
cam ... -s role=viewfinder,... --stream-file=processed#.ppm \
-s role=raw,... --stream-file=raw#
To not complicate the implementation more than necessary, it's not
allowed to combine the old and the new output options.
It is also checked that --stream-display is not used more than once (the
KMS output may be used only for a single stream) and that each stream
has at most one output assigned.
Signed-off-by: Milan Zamazal <mzamazal at redhat.com>
---
src/apps/cam/camera_session.cpp | 67 ++++++++++++++++++++++++++++++++-
src/apps/cam/main.cpp | 23 ++++++++---
src/apps/cam/main.h | 3 ++
3 files changed, 85 insertions(+), 8 deletions(-)
diff --git a/src/apps/cam/camera_session.cpp b/src/apps/cam/camera_session.cpp
index 5124029b..5ef0c2fe 100644
--- a/src/apps/cam/camera_session.cpp
+++ b/src/apps/cam/camera_session.cpp
@@ -7,13 +7,16 @@
#include "camera_session.h"
+#include <algorithm>
#include <iomanip>
#include <iostream>
#include <limits.h>
+#include <memory.h>
#include <sstream>
#include <libcamera/control_ids.h>
#include <libcamera/property_ids.h>
+#include <libcamera/stream.h>
#include "../common/event_loop.h"
#include "../common/stream_options.h"
@@ -292,10 +295,70 @@ int CameraSession::start()
defaultSink = std::move(sink);
}
+#ifdef HAVE_KMS
+ bool kmsSinkAssigned = false;
+#endif
+ auto &streamOptions = options_[OptStream];
for (unsigned int i = 0; i < config_->size(); i++) {
const StreamConfiguration &cfg = config_->at(i);
- if (defaultSink)
- defaultSink->addStream(cfg.stream());
+ if (streamOptions.empty()) {
+ if (defaultSink)
+ defaultSink->addStream(cfg.stream());
+ } else {
+ const OptionsParser::Options &suboptions = streamOptions.toArray()[i].children();
+ if (defaultSink) {
+ if (suboptions.isSet(OptStreamDisplay) ||
+ suboptions.isSet(OptStreamSDL) ||
+ suboptions.isSet(OptStreamFile)) {
+ std::cerr << "Combining default and stream specific outputs is unsupported" << std::endl;
+ return -EINVAL;
+ }
+
+ defaultSink->addStream(cfg.stream());
+ continue;
+ }
+
+ std::unique_ptr<FrameSink> sink;
+#ifdef HAVE_KMS
+ if (suboptions.isSet(OptStreamDisplay)) {
+ if (kmsSinkAssigned) {
+ std::cerr << "Display doesn't support multiple streams" << std::endl;
+ return -EINVAL;
+ }
+ kmsSinkAssigned = true;
+
+ sink = std::make_unique<KMSSink>(suboptions[OptStreamDisplay].toString());
+ }
+#endif
+#ifdef HAVE_SDL
+ if (suboptions.isSet(OptStreamSDL)) {
+ if (sink) {
+ std::cerr << "Single stream cannot have multiple outputs" << std::endl;
+ return -EINVAL;
+ }
+ sink = std::make_unique<SDLSink>();
+ }
+#endif
+ if (suboptions.isSet(OptStreamFile)) {
+ if (sink) {
+ std::cerr << "Single stream cannot have multiple outputs" << std::endl;
+ return -EINVAL;
+ }
+ std::unique_ptr<FileSink> fileSink =
+ std::make_unique<FileSink>(camera_.get(), streamNames_);
+ if (!suboptions[OptStreamFile].toString().empty()) {
+ ret = fileSink->setFilePattern(suboptions[OptStreamFile]);
+ if (ret)
+ return ret;
+ }
+ sink = std::move(fileSink);
+ }
+
+ if (sink) {
+ sink->addStream(cfg.stream());
+ sinks_.push_back(std::move(sink));
+ }
+ }
}
if (defaultSink)
diff --git a/src/apps/cam/main.cpp b/src/apps/cam/main.cpp
index 9d84ef8e..10b7a33a 100644
--- a/src/apps/cam/main.cpp
+++ b/src/apps/cam/main.cpp
@@ -138,14 +138,21 @@ int CamApp::parseOptions(int argc, char *argv[])
"Desired image orientation (rot0, rot180, mirror, flip)",
"orientation", ArgumentRequired, "orientation", false,
OptCamera);
+ parser.addOption(OptStream, &streamKeyValue,
+ "Set configuration of a camera stream", "stream", true,
+ OptCamera);
#ifdef HAVE_KMS
parser.addOption(OptDisplay, OptionString,
- "Display viewfinder through DRM/KMS on specified connector",
+ "Display viewfinder by default through DRM/KMS on specified connector",
"display", ArgumentOptional, "connector", false,
OptCamera);
+ parser.addOption(OptStreamDisplay, OptionString,
+ "Display viewfinder stream through DRM/KMS on specified connector",
+ "stream-display", ArgumentOptional, "connector", false,
+ OptStream);
#endif
parser.addOption(OptFile, OptionString,
- "Write captured frames to disk\n"
+ "Write captured frames by default to disk\n"
"If the file name ends with a '/', it sets the directory in which\n"
"to write files, using the default file name. Otherwise it sets the\n"
"full file path and name. The first '#' character in the file name\n"
@@ -159,13 +166,17 @@ int CamApp::parseOptions(int argc, char *argv[])
"The default file name is 'frame-#.bin'.",
"file", ArgumentOptional, "filename", false,
OptCamera);
+ parser.addOption(OptStreamFile, OptionString,
+ "Write frames captured from a stream to disk\n"
+ "The file name is of the same format as in --file.",
+ "stream-file", ArgumentOptional, "filename", false,
+ OptStream);
#ifdef HAVE_SDL
- parser.addOption(OptSDL, OptionNone, "Display viewfinder through SDL",
+ parser.addOption(OptSDL, OptionNone, "Display viewfinder by default through SDL",
"sdl", ArgumentNone, "", false, OptCamera);
+ parser.addOption(OptStreamSDL, OptionNone, "Display stream viewfinder through SDL",
+ "stream-sdl", ArgumentNone, "", false, OptStream);
#endif
- parser.addOption(OptStream, &streamKeyValue,
- "Set configuration of a camera stream", "stream", true,
- OptCamera);
parser.addOption(OptStrictFormats, OptionNone,
"Do not allow requested stream format(s) to be adjusted",
"strict-formats", ArgumentNone, nullptr, false,
diff --git a/src/apps/cam/main.h b/src/apps/cam/main.h
index 64e6a20e..2f630fbe 100644
--- a/src/apps/cam/main.h
+++ b/src/apps/cam/main.h
@@ -20,6 +20,9 @@ enum {
OptOrientation = 'o',
OptSDL = 'S',
OptStream = 's',
+ OptStreamDisplay = 'd',
+ OptStreamFile = 'f',
+ OptStreamSDL = 'w',
OptListControls = 256,
OptStrictFormats = 257,
OptMetadata = 258,
--
2.48.1
More information about the libcamera-devel
mailing list