[RFC v2 4/4] libcamera: pipeline_handler: Use YamlEmitter
Kieran Bingham
kieran.bingham at ideasonboard.com
Sun Oct 20 00:35:05 CEST 2024
Quoting Jacopo Mondi (2024-10-17 13:52:19)
> Replace raw output usage with YamlEmitter.
>
> Signed-off-by: Jacopo Mondi <jacopo.mondi at ideasonboard.com>
> ---
> include/libcamera/internal/pipeline_handler.h | 11 +-
> src/libcamera/pipeline_handler.cpp | 102 +++++++++---------
> 2 files changed, 61 insertions(+), 52 deletions(-)
>
> diff --git a/include/libcamera/internal/pipeline_handler.h b/include/libcamera/internal/pipeline_handler.h
> index fb3914185a01..a10d7b1fab8c 100644
> --- a/include/libcamera/internal/pipeline_handler.h
> +++ b/include/libcamera/internal/pipeline_handler.h
> @@ -19,6 +19,8 @@
> #include <libcamera/controls.h>
> #include <libcamera/stream.h>
>
> +#include "libcamera/internal/yaml_emitter.h"
> +
> namespace libcamera {
>
> enum class Orientation;
> @@ -110,8 +112,13 @@ private:
> const char *name_;
> unsigned int useCount_;
>
> - std::ostream *dumpCaptureScript_;
> - std::ostream *dumpMetadata_;
> + std::unique_ptr<YamlRoot> controlsEmitter_;
> + std::unique_ptr<YamlDict> controlsDict_;
> + std::unique_ptr<YamlList> controlsList_;
> +
> + std::unique_ptr<YamlRoot> metadataEmitter_;
> + std::unique_ptr<YamlDict> metadataDict_;
> + std::unique_ptr<YamlList> metadataList_;
Will 'all' users of a YamlEmitter instance need each of a root/dict/list
- or is this just specific to this usage?
I don't think this series has taken on comments from Pauls' series,
where I saw a lot of duplication between different 'output streams'
which should be factored out.
I can't tell if they should be factored out to a 'YamlEmitter' class
each - or if ther eshould be some extra use-case specific class specific
to the metadata here ...
>
> friend class PipelineHandlerFactoryBase;
> };
> diff --git a/src/libcamera/pipeline_handler.cpp b/src/libcamera/pipeline_handler.cpp
> index 7002b4323bdd..533d0f8fc132 100644
> --- a/src/libcamera/pipeline_handler.cpp
> +++ b/src/libcamera/pipeline_handler.cpp
> @@ -69,36 +69,31 @@ LOG_DEFINE_CATEGORY(Pipeline)
> * through the PipelineHandlerFactoryBase::create() function.
> */
> PipelineHandler::PipelineHandler(CameraManager *manager)
> - : manager_(manager), useCount_(0),
> - dumpCaptureScript_(nullptr), dumpMetadata_(nullptr)
> + : manager_(manager), useCount_(0)
> {
> /* 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);
> + std::string filePath(file);
> + controlsEmitter_ = YamlEmitter::root(filePath);
> + controlsDict_ = controlsEmitter_->dict();
>
> /*
> * 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();
> + std::string metadataFilePath = filePath + ".metadata";
> + metadataEmitter_ = YamlEmitter::root(metadataFilePath);
> + metadataDict_ = metadataEmitter_->dict();
> + metadataList_ = metadataDict_->list("frames");
> }
>
> PipelineHandler::~PipelineHandler()
> {
> for (std::shared_ptr<MediaDevice> media : mediaDevices_)
> media->release();
> -
> - if (dumpCaptureScript_)
> - delete dumpCaptureScript_;
> -
> - if (dumpMetadata_)
> - delete dumpMetadata_;
> }
>
> /**
> @@ -788,65 +783,72 @@ void PipelineHandler::disconnect()
> void PipelineHandler::dumpConfiguration(const std::set<const Stream *> &streams,
> const Orientation &orientation)
> {
> - if (!dumpCaptureScript_)
> + if (!controlsEmitter_)
> return;
>
> - std::stringstream ss;
> - ss << "configuration:" << std::endl;
> - ss << " orientation: " << orientation << std::endl;
> + auto configurationDict = controlsDict_->dict("configuration");
> +
> + std::stringstream o;
> + o << orientation;
> + (*configurationDict)["orientation"] = o.str();
>
> /* TODO Dump Sensor configuration */
>
> - ss << " streams:" << std::endl;
> + auto streamsList = configurationDict->list("streams");
> +
> 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;
> - }
> + auto yamlStream = streamsList->dict();
>
> - dumpCaptureScript_->write(ss.str().c_str(), ss.str().size());
> + (*yamlStream)["pixelformat"] = streamConfig.pixelFormat.toString();
> + (*yamlStream)["size"] = streamConfig.size.toString();
> + (*yamlStream)["stride"] = std::to_string(streamConfig.stride);
> + (*yamlStream)["frameSize"] = std::to_string(streamConfig.frameSize);
> + (*yamlStream)["bufferCount"] = std::to_string(streamConfig.bufferCount);
>
> - std::string str = "frames:\n";
> - dumpCaptureScript_->write(str.c_str(), str.size());
> - dumpCaptureScript_->flush();
> + if (streamConfig.colorSpace)
> + (*yamlStream)["colorSpace"] =
> + streamConfig.colorSpace->toString();
> + }
> }
>
> 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())
> + if (!controlsEmitter_)
> return;
>
> - std::stringstream ss;
> + ControlList &controls = mode == DumpMode::Controls ? request->controls()
> + : request->metadata();
> + if (controls.empty())
> + return;
> +
> + std::unique_ptr<YamlDict> yamlFrame;
> + if (mode == DumpMode::Controls) {
> + if (!controlsEmitter_)
> + return;
> +
> + if (!controlsList_)
> + controlsList_ = controlsDict_->list("frames");
> +
> + yamlFrame = controlsList_->dict();
> + } else {
> + if (!metadataEmitter_)
> + return;
> +
> + yamlFrame = metadataList_->dict();
> + }
> +
> + auto yamlCtrls = yamlFrame->dict(std::to_string(request->sequence()));
> +
> /* 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;
> + (*yamlCtrls)[ctrlId->name()] = pair.second.toString();
> }
> -
> - /*
> - * 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();
> }
>
> /**
> --
> 2.47.0
>
More information about the libcamera-devel
mailing list