@@ -292,6 +292,12 @@ int CameraSession::start()
defaultSink = std::move(sink);
}
+ for (unsigned int i = 0; i < config_->size(); i++) {
+ const StreamConfiguration &cfg = config_->at(i);
+ if (defaultSink)
+ defaultSink->addStream(cfg.stream());
+ }
+
if (defaultSink)
sinks_.push_back(std::move(defaultSink));
@@ -374,7 +380,8 @@ int CameraSession::startCapture()
}
for (auto &sink : sinks_)
- sink->mapBuffer(buffer.get());
+ if (sink->assignedStream(stream))
+ sink->mapBuffer(buffer.get());
}
requests_.push_back(std::move(request));
@@ -96,7 +96,8 @@ void FileSink::mapBuffer(FrameBuffer *buffer)
bool FileSink::processRequest(Request *request)
{
for (auto [stream, buffer] : request->buffers())
- writeBuffer(stream, buffer, request->metadata());
+ if (assignedStream(stream))
+ writeBuffer(stream, buffer, request->metadata());
return true;
}
@@ -7,6 +7,8 @@
#include "frame_sink.h"
+#include <iostream>
+
/**
* \class FrameSink
* \brief Abstract class to model a consumer of frames
@@ -65,3 +67,15 @@ int FrameSink::stop()
* \return True if the request has been processed synchronously, false if
* processing has been queued
*/
+
+const libcamera::StreamConfiguration &FrameSink::findConfiguration(
+ const libcamera::CameraConfiguration &config)
+{
+ for (unsigned int i = 0; i < config.size(); i++)
+ if (assignedStream(config.at(i).stream()))
+ return config.at(i);
+
+ /* This should never happen. */
+ std::cerr << "No camera configuration for frame sink" << std::endl;
+ return config.at(0);
+}
@@ -7,8 +7,13 @@
#pragma once
+#include <vector>
+
#include <libcamera/base/signal.h>
+#include <libcamera/camera.h>
+#include <libcamera/stream.h>
+
namespace libcamera {
class CameraConfiguration;
class FrameBuffer;
@@ -27,6 +32,27 @@ public:
virtual int start();
virtual int stop();
+ void addStream(libcamera::Stream *const stream)
+ {
+ streams_.push_back(stream);
+ }
+
+ bool assignedStream(const libcamera::Stream *const stream)
+ {
+ return std::find(streams_.begin(), streams_.end(), stream) != streams_.end();
+ }
+
+ bool empty()
+ {
+ return streams_.empty();
+ }
+
virtual bool processRequest(libcamera::Request *request) = 0;
libcamera::Signal<libcamera::Request *> requestProcessed;
+
+protected:
+ const libcamera::StreamConfiguration &findConfiguration(
+ const libcamera::CameraConfiguration &config);
+
+ std::vector<libcamera::Stream *> streams_;
};
@@ -110,7 +110,7 @@ int KMSSink::configure(const libcamera::CameraConfiguration &config)
plane_ = nullptr;
mode_ = nullptr;
- const libcamera::StreamConfiguration &cfg = config.at(0);
+ const libcamera::StreamConfiguration &cfg = findConfiguration(config);
/* Find the best mode for the stream size. */
const std::vector<DRM::Mode> &modes = connector_->modes();
@@ -456,6 +456,12 @@ bool KMSSink::processRequest(libcamera::Request *camRequest)
return true;
libcamera::FrameBuffer *buffer = camRequest->buffers().begin()->second;
+ for (auto [stream, buf] : camRequest->buffers()) {
+ if (assignedStream(stream)) {
+ buffer = buf;
+ break;
+ }
+ }
auto iter = buffers_.find(buffer);
if (iter == buffers_.end())
return true;
@@ -44,18 +44,17 @@ int SDLSink::configure(const libcamera::CameraConfiguration &config)
if (ret < 0)
return ret;
- if (config.size() > 1) {
+ if (streams_.size() > 1) {
std::cerr
- << "SDL sink only supports one camera stream at present, streaming first camera stream"
+ << "SDL sink only supports one camera stream at present, streaming first stream"
<< std::endl;
- } else if (config.empty()) {
+ } else if (streams_.empty()) {
std::cerr << "Require at least one camera stream to process"
<< std::endl;
return -EINVAL;
}
- const libcamera::StreamConfiguration &cfg = config.at(0);
- rect_.w = cfg.size.width;
+ const libcamera::StreamConfiguration &cfg = findConfiguration(config);
rect_.h = cfg.size.height;
switch (cfg.pixelFormat) {
@@ -163,8 +162,10 @@ void SDLSink::mapBuffer(FrameBuffer *buffer)
bool SDLSink::processRequest(Request *request)
{
for (auto [stream, buffer] : request->buffers()) {
- renderBuffer(buffer);
- break; /* to be expanded to launch SDL window per buffer */
+ if (assignedStream(stream)) {
+ renderBuffer(buffer);
+ break; /* to be expanded to launch SDL window per buffer */
+ }
}
return true;
In order to support different sinks for different streams, we must track the relationship between sinks and streams. Let's track the corresponding streams in FrameSink. Different kinds of sinks use different approaches to multiple streams; keeping the sinks to handle that this way is the simplest. Let's add FrameSink class member and some utility methods for the purpose. We still create only one, the default, sink, so all the streams are added to the default sink unconditionally. This will be changed in a followup patch. Operations on each given sink are applied only for streams the sink contains. Signed-off-by: Milan Zamazal <mzamazal@redhat.com> --- src/apps/cam/camera_session.cpp | 9 ++++++++- src/apps/cam/file_sink.cpp | 3 ++- src/apps/cam/frame_sink.cpp | 14 ++++++++++++++ src/apps/cam/frame_sink.h | 26 ++++++++++++++++++++++++++ src/apps/cam/kms_sink.cpp | 8 +++++++- src/apps/cam/sdl_sink.cpp | 15 ++++++++------- 6 files changed, 65 insertions(+), 10 deletions(-)