From patchwork Mon Oct 14 09:59:36 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 21616 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 8D4D8C32F8 for ; Mon, 14 Oct 2024 10:00:10 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 4F6736538E; Mon, 14 Oct 2024 12:00:06 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="ob6HMijX"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 3ED316537B for ; Mon, 14 Oct 2024 12:00:00 +0200 (CEST) Received: from ideasonboard.com (unknown [5.77.95.224]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 849828BE; Mon, 14 Oct 2024 11:58:18 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1728899899; bh=oXrkN3on37pRu2/oNtO4qLlJzaW8X6MHVA/ZT7ap/KA=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=ob6HMijXxQ/xuQcQawIjayCr466GvGB5aCZhLimfLOMbSMnOr3LCI28koPfA0Iavr xSQteQfwgyXjVyUFhQzDWLGyIIddOZVA0sMmSfw9yZwds2o71F4k5tTMz2WGYnFxuO p8pT7qMbQkWqjNk/R+gwEAAw04M3udexZcjlCuf0= From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Cc: Jacopo Mondi Subject: [RFC 4/4] libcamera: pipeline_handler: Use YamlEmitter Date: Mon, 14 Oct 2024 11:59:36 +0200 Message-ID: <20241014095937.24924-5-jacopo.mondi@ideasonboard.com> X-Mailer: git-send-email 2.46.2 In-Reply-To: <20241014095937.24924-1-jacopo.mondi@ideasonboard.com> References: <20241014095937.24924-1-jacopo.mondi@ideasonboard.com> MIME-Version: 1.0 X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Signed-off-by: Jacopo Mondi --- include/libcamera/internal/pipeline_handler.h | 11 ++- src/libcamera/pipeline_handler.cpp | 94 +++++++++---------- 2 files changed, 54 insertions(+), 51 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 #include +#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 controlsEmitter_; + std::unique_ptr controlsDict_; + std::unique_ptr controlsList_; + + std::unique_ptr metadataEmitter_; + std::unique_ptr metadataDict_; + std::unique_ptr metadataList_; friend class PipelineHandlerFactoryBase; }; diff --git a/src/libcamera/pipeline_handler.cpp b/src/libcamera/pipeline_handler.cpp index 7002b4323bdd..82868a8122ce 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 media : mediaDevices_) media->release(); - - if (dumpCaptureScript_) - delete dumpCaptureScript_; - - if (dumpMetadata_) - delete dumpMetadata_; } /** @@ -788,65 +783,66 @@ void PipelineHandler::disconnect() void PipelineHandler::dumpConfiguration(const std::set &streams, const Orientation &orientation) { - if (!dumpCaptureScript_) - return; + auto configurationDict = controlsDict_->dict("configuration"); - std::stringstream ss; - ss << "configuration:" << std::endl; - ss << " orientation: " << orientation << std::endl; + (*configurationDict)["orientation"] = orientation; /* 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; + auto yamlStream = streamsList->dict(); + + (*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); + if (streamConfig.colorSpace) - ss << " colorSpace: " << streamConfig.colorSpace->toString() << std::endl; + (*yamlStream)["colorSpace"] = + streamConfig.colorSpace->toString(); } - dumpCaptureScript_->write(ss.str().c_str(), ss.str().size()); + streamsList->close(); + configurationDict->close(); - std::string str = "frames:\n"; - dumpCaptureScript_->write(str.c_str(), str.size()); - dumpCaptureScript_->flush(); + controlsList_ = controlsDict_->list("frames"); } 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()) + ControlList &controls = mode == DumpMode::Controls ? request->controls() + : request->metadata(); + if (controls.empty()) return; - std::stringstream ss; + std::unique_ptr yamlFrame; + if (mode == DumpMode::Controls) { + if (!controlsEmitter_) + return; + + 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(); } /**