diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/libcamera/camera.cpp | 13 | ||||
-rw-r--r-- | src/libcamera/pipeline_handler.cpp | 93 |
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 |