summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPaul Elder <paul.elder@ideasonboard.com>2024-10-01 02:09:06 +0900
committerJacopo Mondi <jacopo.mondi@ideasonboard.com>2024-10-02 08:00:40 +0200
commit18f72aa4e662b831fc2137b3affddd247f0b878e (patch)
treee878344629f516d4ee11941361946924ec5b6699 /src
parent3088e14e814eb3bb25103de8f5402ef6b0211689 (diff)
pipeline: Add support for dumping capture script and metadata
Add support for dumping capture scripts and metadata. The capture scripts can then be fed into the cam application and a capture can thus be "replayed". Metadata can also be dumped. Camera configuration is also dumped to the capture script. The cam application currently does not support loading configuration from the capture script, but support for that will be added in a subsequent patch. These can be enabled by a new environment variable. Signed-off-by: Paul Elder <paul.elder@ideasonboard.com>
Diffstat (limited to 'src')
-rw-r--r--src/libcamera/camera.cpp13
-rw-r--r--src/libcamera/pipeline_handler.cpp93
2 files changed, 105 insertions, 1 deletions
diff --git a/src/libcamera/camera.cpp b/src/libcamera/camera.cpp
index a86f552a..1282f99d 100644
--- a/src/libcamera/camera.cpp
+++ b/src/libcamera/camera.cpp
@@ -1215,6 +1215,9 @@ int Camera::configure(CameraConfiguration *config)
d->activeStreams_.insert(stream);
}
+ /* TODO Save sensor configuration for dumping it to capture script */
+ d->orientation_ = config->orientation;
+
d->setState(Private::CameraConfigured);
return 0;
@@ -1356,6 +1359,16 @@ int Camera::start(const ControlList *controls)
ASSERT(d->requestSequence_ == 0);
+ /*
+ * Invoke method in blocking mode to avoid the risk of writing after
+ * streaming has started.
+ * This needs to be here as PipelineHandler::start is a virtual function
+ * so it is impractical to add the dumping there.
+ * TODO Pass the sensor configuration, once it is supported
+ */
+ d->pipe_->invokeMethod(&PipelineHandler::dumpConfiguration,
+ ConnectionTypeBlocking, d->activeStreams_, d->orientation_);
+
ret = d->pipe_->invokeMethod(&PipelineHandler::start,
ConnectionTypeBlocking, this, controls);
if (ret)
diff --git a/src/libcamera/pipeline_handler.cpp b/src/libcamera/pipeline_handler.cpp
index e5940469..7002b432 100644
--- a/src/libcamera/pipeline_handler.cpp
+++ b/src/libcamera/pipeline_handler.cpp
@@ -8,6 +8,7 @@
#include "libcamera/internal/pipeline_handler.h"
#include <chrono>
+#include <fstream>
#include <sys/stat.h>
#include <sys/sysmacros.h>
@@ -68,14 +69,36 @@ LOG_DEFINE_CATEGORY(Pipeline)
* through the PipelineHandlerFactoryBase::create() function.
*/
PipelineHandler::PipelineHandler(CameraManager *manager)
- : manager_(manager), useCount_(0)
+ : manager_(manager), useCount_(0),
+ dumpCaptureScript_(nullptr), dumpMetadata_(nullptr)
{
+ /* TODO Print notification that we're dumping capture script */
+ const char *file = utils::secure_getenv("LIBCAMERA_DUMP_CAPTURE_SCRIPT");
+ if (!file)
+ return;
+
+ dumpCaptureScript_ = new std::ofstream(file);
+
+ /*
+ * Metadata needs to go into a separate file because otherwise it'll
+ * flood the capture script
+ */
+ dumpMetadata_ = new std::ofstream(std::string(file) + ".metadata");
+ std::string str = "frames:\n";
+ dumpMetadata_->write(str.c_str(), str.size());
+ dumpMetadata_->flush();
}
PipelineHandler::~PipelineHandler()
{
for (std::shared_ptr<MediaDevice> media : mediaDevices_)
media->release();
+
+ if (dumpCaptureScript_)
+ delete dumpCaptureScript_;
+
+ if (dumpMetadata_)
+ delete dumpMetadata_;
}
/**
@@ -464,6 +487,8 @@ void PipelineHandler::doQueueRequest(Request *request)
request->_d()->sequence_ = data->requestSequence_++;
+ dumpRequest(request, DumpMode::Controls);
+
if (request->_d()->cancelled_) {
completeRequest(request);
return;
@@ -555,6 +580,8 @@ void PipelineHandler::completeRequest(Request *request)
request->_d()->complete();
+ dumpRequest(request, DumpMode::Metadata);
+
Camera::Private *data = camera->_d();
while (!data->queuedRequests_.empty()) {
@@ -758,6 +785,70 @@ void PipelineHandler::disconnect()
* \return The CameraManager for this pipeline handler
*/
+void PipelineHandler::dumpConfiguration(const std::set<const Stream *> &streams,
+ const Orientation &orientation)
+{
+ if (!dumpCaptureScript_)
+ return;
+
+ std::stringstream ss;
+ ss << "configuration:" << std::endl;
+ ss << " orientation: " << orientation << std::endl;
+
+ /* TODO Dump Sensor configuration */
+
+ ss << " streams:" << std::endl;
+ for (const auto &stream : streams) {
+ const StreamConfiguration &streamConfig = stream->configuration();
+ ss << " - pixelFormat: " << streamConfig.pixelFormat << std::endl;
+ ss << " size: " << streamConfig.size << std::endl;
+ ss << " stride: " << streamConfig.stride << std::endl;
+ ss << " frameSize: " << streamConfig.frameSize << std::endl;
+ ss << " bufferCount: " << streamConfig.bufferCount << std::endl;
+ if (streamConfig.colorSpace)
+ ss << " colorSpace: " << streamConfig.colorSpace->toString() << std::endl;
+ }
+
+ dumpCaptureScript_->write(ss.str().c_str(), ss.str().size());
+
+ std::string str = "frames:\n";
+ dumpCaptureScript_->write(str.c_str(), str.size());
+ dumpCaptureScript_->flush();
+}
+
+void PipelineHandler::dumpRequest(Request *request, DumpMode mode)
+{
+ ControlList &controls =
+ mode == DumpMode::Controls ? request->controls()
+ : request->metadata();
+ std::ostream *output =
+ mode == DumpMode::Controls ? dumpCaptureScript_
+ : dumpMetadata_;
+
+ if (!output || controls.empty())
+ return;
+
+ std::stringstream ss;
+ /* TODO Figure out PFC */
+ ss << " - " << request->sequence() << ":" << std::endl;
+
+ const ControlIdMap *idMap = controls.idMap();
+ for (const auto &pair : controls) {
+ const ControlId *ctrlId = idMap->at(pair.first);
+ /* TODO Prettify enums (probably by upgrading ControlValue::toString()) */
+ ss << " " << ctrlId->name() << ": " << pair.second.toString() << std::endl;
+ }
+
+ /*
+ * TODO Investigate the overhead of flushing this frequently
+ * Controls aren't going to be queued too frequently so it should be
+ * fine to dump controls every frame. Metadata on the other hand needs
+ * to be investigated.
+ */
+ output->write(ss.str().c_str(), ss.str().size());
+ output->flush();
+}
+
/**
* \class PipelineHandlerFactoryBase
* \brief Base class for pipeline handler factories