From 7b52a9bc643e27f386fda4938d970f3996c5245d Mon Sep 17 00:00:00 2001 From: am0ebe <am0ebe@gmx.de> Date: Thu, 23 May 2024 18:02:39 +0200 Subject: [PATCH] change conf.json to include outdir,recordduratiodefault and put cams in array, parse, add outdir func for each cam > construct dir if it doesnt exist, add cam ctor --- src/cam.cpp | 57 ++++++++++++++++++++++++++++----------- src/cam.h | 7 ++++- src/core.cpp | 4 +-- src/frameobserver.cpp | 7 ++--- src/frameobserver.h | 7 +++-- src/frameprocessor.cpp | 24 ++++++++++------- src/frameprocessor.h | 5 ++-- src/utils.cpp | 60 +++++++++++++++++++++++++++++++++++------- src/utils.h | 9 +++++-- 9 files changed, 132 insertions(+), 48 deletions(-) diff --git a/src/cam.cpp b/src/cam.cpp index d529391..899911f 100644 --- a/src/cam.cpp +++ b/src/cam.cpp @@ -15,6 +15,8 @@ #include <QTimer> #include <QDebug> + + using State = Cam::State; using namespace VmbCPP; using namespace std::chrono; @@ -30,13 +32,28 @@ _state(disconnected), _frames(FramePtrVector(utils::threadsPerCam())), _payloadSize(0LL), _pixelFormat(""), -_timer(new QTimer(this)) +_timer(new QTimer(this)), +_outDir(utils::outDir() + QDir::separator() + _name + QDir::separator()) //specific for cam { _timer->setSingleShot(true); connect(_timer, SIGNAL(timeout()), this, SLOT(stopRecording())); - // id(); } +// Copy constructor +Cam::Cam(const Cam& other) : IPrinter(), +_cam(other._cam), +_name(other._name), +_ip(other._ip), +_id(other._id), +_state(other._state), +_frames(other._frames), +_payloadSize(other._payloadSize), +_pixelFormat(other._pixelFormat), +_timer(new QTimer(this)), +_outDir(other._outDir) +{ + qDebug() << __LINE__ << "-" << __PRETTY_FUNCTION__ << "copy constructor"; +} //xxx add ip and name // Cam::Cam(CameraPtr pCamera) : IPrinter(), @@ -56,18 +73,6 @@ _timer(new QTimer(this)) // } -// // Copy constructor -// Cam::Cam(const Cam& other) : -// IPrinter(), -// _cam(other._cam), -// _id(other._id), -// _state(other._state), -// _frames(other._frames), -// _payloadSize(other._payloadSize), -// _pixelFormat(other._pixelFormat) -// { -// qDebug() << __LINE__ << "-" << __PRETTY_FUNCTION__ << "copy constructor"; -// } Cam::~Cam() { @@ -127,6 +132,22 @@ void Cam::close() //state change will be handled by CamObserver::CameraStateChanged > Core::onCameraChanged > Cam::onChanged } +bool Cam::checkOutDir() +{ + //check if dir exists and if it doesnt, create it + QDir dir(_outDir); + if (!dir.exists()) + dir.mkpath("."); + + return dir.exists(); +} + +QString Cam::outDir() +{ + return _outDir; +} + + /* Does: get Payloadsize get Pixelformat - eg RGB8 @@ -145,6 +166,11 @@ void Cam::startRecording(seconds dur) if(_state != opened) return error("cant start recording, when cam is " + stateToString(_state)); + if(!checkOutDir()) + return error("could not create directory: " + _outDir); + else + IPrinter::info("writing frames to: " + _outDir); + try { FeaturePtr pFeature; @@ -161,7 +187,7 @@ void Cam::startRecording(seconds dur) for( auto& frame : _frames ) { frame.reset(new Frame(_payloadSize)); - g( frame->RegisterObserver( IFrameObserverPtr( new FrameObserver(_cam) )),"register frame observer"); + g( frame->RegisterObserver( IFrameObserverPtr( new FrameObserver(std::make_shared<Cam>(*this)) )),"register frame observer"); g( _cam->AnnounceFrame(frame), "announce frame"); } @@ -302,7 +328,6 @@ void Cam::onChanged(UpdateTriggerType type) error("onChanged: unknown trigger type"); } } -#include <VmbC/VmbCommonTypes.h> //write out settings.xml for current open cam void Cam::saveSettings() { diff --git a/src/cam.h b/src/cam.h index 3103aaa..9e08782 100644 --- a/src/cam.h +++ b/src/cam.h @@ -4,6 +4,7 @@ #include <QObject> #include <QString> +#include <QDir> #include <chrono> #include <vector> @@ -39,8 +40,8 @@ public: // const QString& name, const int& nThreads Cam(QString name, QString ip); + Cam(const Cam&); // Cam(CameraPtr pCamera); - // Cam(const Cam&); ~Cam(); QString id(); @@ -64,11 +65,14 @@ public: inline CameraPtr getCameraPtr() { return _cam; } inline void setCameraPtr( CameraPtr pCamera ) { _cam = pCamera; } + QString outDir(); public slots: void stopRecording(); private: + bool checkOutDir(); + CameraPtr _cam; QString _name; QString _ip; @@ -78,5 +82,6 @@ private: VmbInt64_t _payloadSize; std::string _pixelFormat; QTimer* _timer; + QString _outDir; }; diff --git a/src/core.cpp b/src/core.cpp index 2147a87..03135c0 100644 --- a/src/core.cpp +++ b/src/core.cpp @@ -20,7 +20,6 @@ #include <QCoreApplication> using namespace VmbCPP; -using namespace std::chrono_literals; //ms, s, m, h Core::Core() : IPrinter(), _sys( VmbSystem::GetInstance() ), // create and get Vimba singleton @@ -44,14 +43,13 @@ void Core::init() //parse config file QList<QPair<QString, QString>> parsedCameras; - if( ! utils::parseConfig(parsedCameras) ) + if( ! utils::parseConfig(parsedCameras, _recDuration) ) { utils::running = false; qApp->quit(); return; } - //add to cam list for ( auto cam : parsedCameras ) { diff --git a/src/frameobserver.cpp b/src/frameobserver.cpp index 92177fb..720a5da 100644 --- a/src/frameobserver.cpp +++ b/src/frameobserver.cpp @@ -11,9 +11,9 @@ using namespace VmbCPP; -FrameObserver::FrameObserver( CameraPtr pCamera ) : IFrameObserver( pCamera ) +FrameObserver::FrameObserver( CamPtr cam ) : IFrameObserver( cam->getCameraPtr() ), +_cam(cam) { - } /* Frame callback notifies about incoming frames @@ -22,6 +22,7 @@ FrameObserver::FrameObserver( CameraPtr pCamera ) : IFrameObserver( pCamera ) Do not apply image processing within this callback ( performance ) -> create frame processor to handle frame processing asynchronously - when the frame has been processed , requeue it + - frameprocessing is done in a separate thread */ void FrameObserver::FrameReceived ( const FramePtr pframe ) { @@ -51,7 +52,7 @@ void FrameObserver::FrameReceived ( const FramePtr pframe ) break; } - FrameProcessor* processor = new FrameProcessor(pframe); + FrameProcessor* processor = new FrameProcessor(pframe,_cam->outDir()); QThread *thread = new QThread; processor->moveToThread(thread); diff --git a/src/frameobserver.h b/src/frameobserver.h index 6ab97f0..c87e7c1 100644 --- a/src/frameobserver.h +++ b/src/frameobserver.h @@ -1,9 +1,9 @@ #pragma once +#include "cam.h" #include <QObject> #include <VmbCPP/IFrameObserver.h> -using VmbCPP::CameraPtr; using VmbCPP::FramePtr; using VmbCPP::IFrameObserver; @@ -12,12 +12,15 @@ class FrameObserver : public QObject, public IFrameObserver Q_OBJECT public: + FrameObserver( CamPtr cam ); void FrameReceived( const FramePtr ); - FrameObserver( CameraPtr pCamera ); public slots: void queueFrame(FramePtr pframe); + private: + CamPtr _cam; + }; diff --git a/src/frameprocessor.cpp b/src/frameprocessor.cpp index 4db68ed..114413a 100644 --- a/src/frameprocessor.cpp +++ b/src/frameprocessor.cpp @@ -1,6 +1,6 @@ #include "frameprocessor.h" #include "frameobserver.h" -// #include "qobject.h" +#include "utils.h" #include <opencv2/imgcodecs.hpp> #include <opencv2/opencv.hpp> @@ -12,8 +12,13 @@ #include <QThread> #include <QObject> #include <QImage> +#include <QDir> -FrameProcessor::FrameProcessor(const FramePtr pframe) : m_pframe(pframe) {} +FrameProcessor::FrameProcessor(const FramePtr pframe, const QString& outDir) : +_pframe(pframe), +_outDir( outDir ) +{ +} FrameProcessor::~FrameProcessor() { @@ -33,11 +38,11 @@ void FrameProcessor::processFrame() VmbUint64_t timestamp = 0; VmbPixelFormatType pixelFormat; - m_pframe->GetWidth(width); - m_pframe->GetHeight(height); - m_pframe->GetBuffer(pdata); - m_pframe->GetTimestamp(timestamp); - m_pframe->GetPixelFormat(pixelFormat); + _pframe->GetWidth(width); + _pframe->GetHeight(height); + _pframe->GetBuffer(pdata); + _pframe->GetTimestamp(timestamp); + _pframe->GetPixelFormat(pixelFormat); QString pixelFormatStr = "RGB8"; if (pixelFormat != VmbPixelFormatRgb8) @@ -49,7 +54,8 @@ void FrameProcessor::processFrame() cv::Mat frameMat(height, width, CV_8UC3, pdata); std::vector<int> params = {cv::IMWRITE_JPEG_QUALITY, 99, cv::IMWRITE_JPEG_OPTIMIZE, 1, cv::IMWRITE_JPEG_RST_INTERVAL,4}; - QString filename = QString::number(timestamp) + "_frame.jpg"; + + QString filename = _outDir + QString::number(timestamp) + ".jpg"; cv::imwrite(filename.toStdString(), frameMat, params); qDebug() << "rcvd Frame #" << count << ": " << width << "x" << height << "px, format: " << pixelFormatStr << ", timestamp: " << timestamp << ", file: " << filename; @@ -60,5 +66,5 @@ void FrameProcessor::processFrame() #endif - emit frameProcessed(m_pframe); + emit frameProcessed(_pframe); } diff --git a/src/frameprocessor.h b/src/frameprocessor.h index ffd1aa4..10b9191 100644 --- a/src/frameprocessor.h +++ b/src/frameprocessor.h @@ -8,7 +8,7 @@ class FrameProcessor : public QObject Q_OBJECT public: - explicit FrameProcessor(const FramePtr); + explicit FrameProcessor(const FramePtr, const QString&); ~FrameProcessor(); @@ -20,6 +20,7 @@ signals: private: - FramePtr m_pframe; + FramePtr _pframe; + const QString _outDir; }; diff --git a/src/utils.cpp b/src/utils.cpp index e812374..ddbf4e3 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -6,12 +6,11 @@ #include <iostream> #include "VmbCPP/VmbCPP.h" -#include "qcoreapplication.h" +#include <VmbC/VmbCommonTypes.h> #include <QDebug> #include <QDir> #include <QThread> - #include <QCoreApplication> #include <QFile> #include <QJsonDocument> @@ -103,7 +102,7 @@ const QString errorCodeToMessage( VmbError_t err ) return msg; } -bool parseConfig(QList<QPair<QString,QString>>& parsedCameras) +bool parseConfig(QList<QPair<QString,QString>>& parsedCameras, seconds& recDuration) { qDebug() << "open " << configFile(); QFile file(configFile()); @@ -124,15 +123,43 @@ bool parseConfig(QList<QPair<QString,QString>>& parsedCameras) return false; } - if (!doc.isArray()) + if (!doc.isObject()) + { + qWarning() << "JSON content is not an object"; + return false; + } + + QJsonObject jsonObject = doc.object(); + + // Parse recordDurationInSeconds + if (!jsonObject.contains("recordDurationInSeconds") || !jsonObject["recordDurationInSeconds"].isDouble()) + { + qWarning() << "Missing or invalid recordDurationInSeconds"; + return false; + } + + recDuration = jsonObject["recordDurationInSeconds"].toInt() * 1s; //convert to s + qDebug() << "parsed recDuration:" << recDuration.count(); + + // Parse outDir + if (!jsonObject.contains("outDir") || !jsonObject["outDir"].isString()) { - qWarning() << "JSON content is not an array"; + qWarning() << "Missing or invalid outDir"; + return false; + } + outDir(jsonObject["outDir"].toString()); //set global + qDebug() << "parsed outDir:" << outDir(); + + // Parse cameras + if (!jsonObject.contains("cameras") || !jsonObject["cameras"].isArray()) + { + qWarning() << "Missing or invalid cameras array"; return false; } parsedCameras.clear(); - QJsonArray jsonArray = doc.array(); - for (const QJsonValue& value : jsonArray) + QJsonArray camerasArray = jsonObject["cameras"].toArray(); + for (const QJsonValue& value : camerasArray) { if (!value.isObject()) { @@ -147,11 +174,25 @@ bool parseConfig(QList<QPair<QString,QString>>& parsedCameras) parsedCameras.append(qMakePair(name, ip)); } - // for (const auto& cam : parsedCameras) - // qDebug() << "Camera Name:" << cam.first << ", IP:" << cam.second; return true; } +//general basedir +QString outDir(QString dirname) +{ + static QString _outDir; + if( _outDir.isEmpty() ) + { + if( dirname.isEmpty() ) + _outDir = QCoreApplication::applicationDirPath(); + else + _outDir = dirname; + } + + qDebug() << "outDir:" << _outDir; + return _outDir; +} + // needed to find cams via ip QString configFile(QString filename) { @@ -167,7 +208,6 @@ QString getFirstFileInAppDirEndingWith( QString const& suffix ) QDir dir(QCoreApplication::applicationDirPath()); QStringList files = dir.entryList(QStringList() << "*."+suffix, QDir::Files); // QStringList const folders = source.entryList(QDir::NoDot | QDir::NoDotDot | QDir::Dirs); - // auto file = QCoreApplication::applicationDirPath()+QDir::separator()+files.first(); auto file = files.first(); return files.isEmpty() || suffix.isEmpty() ? QString() : file; } diff --git a/src/utils.h b/src/utils.h index b5b1afc..996ca5e 100644 --- a/src/utils.h +++ b/src/utils.h @@ -2,20 +2,25 @@ #define UTILS_H #include "VmbC/VmbCommonTypes.h" //VmbError_t -> cant really fwd-decl typedef...?? + #include <atomic> +#include <chrono> #include <QString> #include <QList> #include <QPair> class QDir; +using std::chrono::seconds; +using namespace std::chrono_literals; namespace utils { -bool parseConfig(QList<QPair<QString,QString>>&); +bool parseConfig(QList<QPair<QString,QString>>&, seconds&); QString configFile(QString filename=""); QString settingsFile(QString filename=""); +QString outDir(QString dirname=""); QString getFirstFileInAppDirEndingWith( QString const&); @@ -23,7 +28,7 @@ const QStringList getVersions(); const QString getVersion(); const QString errorCodeToMessage( VmbError_t ); -extern std::atomic<bool> running; //global flag to sync threads and ensure proper exit +extern std::atomic<bool> running; //global flag to ensure proper exit of threads int threadsPerCam(); int ncam(); -- GitLab