diff --git a/src/cam.cpp b/src/cam.cpp index cc5c0f2652c97a13242ae1741a48a558f1fd32da..b07e6a0a0623b4c87cb03704822fd57f93a94367 100644 --- a/src/cam.cpp +++ b/src/cam.cpp @@ -1,23 +1,20 @@ #include "cam.h" #include "iprinter.h" #include "utils.h" -#include "frameobserver.h" +#include "record.h" #include "VmbC/VmbCommonTypes.h" #include "VmbC/VmbCTypeDefinitions.h" #include "VmbCPP/SharedPointerDefines.h" -#include <chrono> #include <memory> //shared_ptr #include <string> #include <unistd.h> -#include <QTimer> #include <QDebug> using State = Cam::State; using namespace VmbCPP; -using namespace std::chrono; using utils::DELIM; Cam::Cam(QString name, QString ip) : IPrinter(), @@ -26,28 +23,15 @@ _name(name), _ip(ip), _id(""), _state(disconnected), -_frames(FramePtrVector(utils::threadsPerCam())), -// _frames(FramePtrVector(1)), -_payloadSize(0LL), -_pixelFormat(""), -_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())); -} +_rec(/*Dflt Ctor*/) +{} 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(other._timer), //? -_outDir(other._outDir) +_state(other._state) { //careful of changing member vars of a copy only! qDebug() << __LINE__ << "-" << __PRETTY_FUNCTION__ << "copy constructor"; @@ -111,161 +95,6 @@ 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(".") ) - { - error("could not create directory: " + _outDir); - return false; - } - - - info("writing frames to: " + _outDir); - return true; -} - -QString Cam::outDir() -{ - return _outDir; -} - - -/* Does: - get Payloadsize - get Pixelformat - eg RGB8 - Allocate memory for frame buffer - Register frame observer / callback for each frame - Announce frame to the API - Start the capture engine (API) - Put frame into the frame queue - Start the acquisition engine ( _curCam) - - 2d get frameID -*/ -void Cam::startRecording(seconds dur) -{ - if(_state != opened) - return error("cant start recording, when cam is " + stateToString(_state)); - - if(!checkOutDir()) - return; - - try - { - FeaturePtr pFeature; - - g( _cam->GetFeatureByName ("PayloadSize", pFeature )); //xxx adjust: set to 7062528 - g( pFeature->GetValue (_payloadSize)); - print("PayloadSize",_payloadSize); - - g( _cam->GetFeatureByName("PixelFormat", pFeature)); - g( pFeature->GetValue(_pixelFormat)); - print("PixelFormat",_pixelFormat); - - for( auto& frame : _frames ) - { - frame.reset(new Frame(_payloadSize)); - g( frame->RegisterObserver( IFrameObserverPtr( new FrameObserver(std::make_shared<Cam>(*this)) )),"register frame observer"); - g( _cam->AnnounceFrame(frame), "announce frame"); - } - - g( _cam->StartCapture(), "start capture"); - - for( auto& frame : _frames ) - g( _cam->QueueFrame(frame),"QueueFrame"); - - g( _cam->GetFeatureByName ("AcquisitionStart", pFeature ),"get AcquisitionStart"); - g( pFeature->RunCommand(),"run AcquisitionStart"); - - } - catch (const std::runtime_error& xx) - { - qDebug() << __FUNCTION__ << "Exception caught: " << xx.what(); - return; - } - - _state = recording; - - // Convert to milliseconds - // auto dur_ms = duration_cast<milliseconds>(dur); - _timer->start(dur); -} - -void Cam::startRecording(minutes dur) -{ - startRecording(duration_cast<seconds>(dur)); // Convert to seconds -} - -/* Does: - Stop the capture engine (API) + discard all pending callbacks - Flush the frame queue - Revoke all frames from the API - Unregister the frame observer / callback -*/ -void Cam::stopRecording() -{ - if(_state != recording) - return error("cant stop recording, when cam is " + stateToString(_state)); - - _timer->stop(); //stop timer or it will try to close an already closed cam - - FeaturePtr pFeature; - try - { - g(_cam->GetFeatureByName ("AcquisitionStop", pFeature ),"get AcquisitionStop"); - g(pFeature->RunCommand(),"run AcquisitionStop"); - g(_cam->EndCapture(),"end capture"); - g(_cam->FlushQueue(),"flush queue"); - g(_cam->RevokeAllFrames(),"revoke all frames"); - for( FramePtr frame : _frames ) - g(frame->UnregisterObserver(),"unregister observer"); - - _state = opened; - } - catch (const std::runtime_error& xx) - { - qDebug() << __FUNCTION__ << "Exception caught: " << xx.what(); - return; - } -} - - //hdd space used - // hdd space left - // time elapsed / progress - // fps? -void Cam::showRecordingStats() -{ - printFeatures("StatFrameDropped"); - printFeatures({ - // "StatFrameDropped", //unsigned int max 4294967295 - "StatFrameRate", //float send by cam - "StatLocalRate", //float rcvd by observer - "StatFrameRescued", - "StatFrameShoved", - "StatFrameUnderrun", - "StatPacketErrors", - "StatPacketMissed", - "StatPacketReceived", - "StatPacketRequested", - "StatPacketResent", - "StatTimeElapsed", //float - time elapsed since start of acquisition - "StatFrameDelivered" - }); - -} - -void Cam::showRecordingProgress() -{ - if( _state != recording ) - return; // error("cant show progress, when cam is " + stateToString(_state)); - - //TODO test - //fps? - progressBar(_timer); -} - void Cam::printFeatures( QString feature) { printFeatures(QStringList(feature)); @@ -334,7 +163,7 @@ void Cam::printFeatures( QStringList features) } // id,name,model,serial,interfaceID,state -QString Cam::printCamInfo() +QString Cam::camInfo() { QString camInfo = _name + DELIM + _ip + DELIM; if( state() == Cam::disconnected ) @@ -361,6 +190,9 @@ QString Cam::printCamInfo() camInfo += QString::fromStdString(str) + DELIM; camInfo += stateToString(_state); + if( _state == recording) + _rec->progressBar(); + } catch(const std::exception& e) { @@ -446,3 +278,10 @@ void Cam::loadSettings() else info("Loaded settings from " + settingsFile()); } + +//also inits RecordPtr with new CameraPtr +void Cam::setCameraPtr( CameraPtr pCamera ) +{ + _cam = pCamera; + _rec = std::make_shared<Record>( shared_from_this() ); +} diff --git a/src/cam.h b/src/cam.h index f98d6d7bd8e07e35cb60a450e33102516a916f06..dda6732d6e93a8b7dc16d3af745758f95ecf4a42 100644 --- a/src/cam.h +++ b/src/cam.h @@ -1,32 +1,9 @@ #pragma once #include "iprinter.h" +#include "typeDefinitions.h" -#include <QObject> -#include <QString> -#include <QDir> - -#include <chrono> -#include <vector> -#include <memory> //shared_ptr - -#include <VmbCPP/Camera.h> - -using VmbCPP::CameraPtr; -using VmbCPP::FramePtr; -using VmbCPP::FeaturePtr; -using VmbCPP::FramePtrVector; -using VmbCPP::UpdateTriggerType; - -using std::chrono::minutes; -using std::chrono::seconds; - -class Cam; // != Camera -using CamPtr = std::shared_ptr<Cam>; -using CamPtrVector = std::vector<CamPtr>; -class QTimer; - -class Cam : public IPrinter +class Cam : public IPrinter, public std::enable_shared_from_this<Cam> { Q_OBJECT @@ -47,50 +24,36 @@ public: QString id(); QString name() const; QString ip() const; + RecordPtr rec(); State state() const; void setState(const State&); - static QString stateToString(const State&); + QString stateToString(const State&); + void onChanged(UpdateTriggerType); void open(); void close(); - void startRecording(minutes); - void startRecording(seconds); //can use literals "1s, 1min" - QString printCamInfo(); - void showRecordingStats(); - void showRecordingProgress(); + QString camInfo(); void printFeatures(QStringList); void printFeatures(QString); - void saveSettings(); void loadSettings(); inline CameraPtr getCameraPtr() { return _cam; } - inline void setCameraPtr( CameraPtr pCamera ) { _cam = pCamera; } - QString outDir(); + void setCameraPtr( CameraPtr ); friend class FrameObserver; -public slots: - void stopRecording(); - private: - bool checkOutDir(); - CameraPtr _cam; QString _name; QString _ip; QString _id; State _state; - FramePtrVector _frames; - VmbInt64_t _payloadSize; - std::string _pixelFormat; - QTimer* _timer; - QString _outDir; - + RecordPtr _rec; }; diff --git a/src/core.cpp b/src/core.cpp index 09f341e83575921a46b375a954fff3f435d92e4f..062f83fbbff274d26f8cbefba10a0358a09e9be7 100644 --- a/src/core.cpp +++ b/src/core.cpp @@ -78,6 +78,7 @@ void Core::detectCams() if( VmbErrorSuccess == _sys.GetCameraByID( cam->ip().toStdString(), VmbAccessModeFull, pcam ) ) { cam->setCameraPtr(pcam); //triggers camobserver changed signal > set state + //create Vimba Camera and Record objects } } } @@ -103,7 +104,7 @@ void Core::listCams() camInfo += " * "; else camInfo += " "; - camInfo += camera->printCamInfo(); + camInfo += camera->camInfo(); allCamInfo << camInfo; } @@ -116,18 +117,14 @@ void Core::listCams() void Core::openCam() { - if( !cam() ) - return; - - cam()->open(); + if( cam() ) + cam()->open(); } void Core::closeCam() { - if( !cam() ) - return; - - cam()->close(); + if( cam() ) + cam()->close(); } /* @@ -157,20 +154,31 @@ CamPtr Core::cam(const unsigned long &idx) void Core::startRecording() { - if( cam() ) - cam()->startRecording( _recDuration ); + if( !cam() ) + return; + + //test this worx (booloperator record) XXX + if( ! cam()->rec() ) + return error(utils::errRecordInvalid); + + cam()->rec()->start( _recDuration ); } void Core::stopRecording() { - if( cam() ) - cam()->stopRecording(); + if( !cam() ) + return; + + if( cam()->state() != Cam::recording ) + return error("cant stop recording, when cam is " + cam()->stateToString(cam()->state())); + + cam()->rec()->stop(); } void Core::showRecordingStats() { if( cam() ) - cam()->showRecordingStats(); + cam()->rec()->showStats(); } void Core::setDuration(int dur) diff --git a/src/iprinter.cpp b/src/iprinter.cpp index b9de8a87b5eeb403214aedd84e0e4aabfa844b19..068f6d616e9d141cb6d432ae28d185e09f3b6ce1 100644 --- a/src/iprinter.cpp +++ b/src/iprinter.cpp @@ -106,18 +106,19 @@ void IPrinter::print(const char* name, const QString& val) emit info(QString::fromLocal8Bit(name) + ": " + val); } -void IPrinter::progressBar(QTimer* timer) +QString IPrinter::progressBar(QTimer* timer) { int total_ms = timer->interval(); int remaining_ms = timer->remainingTime(); auto elapsed_ms = total_ms - remaining_ms; int progressInPercent = (double) elapsed_ms / total_ms; //print in minutes and secs - print(QString::number(progressInPercent) + "% | " + formatTime(elapsed_ms) + " < " + formatTime(remaining_ms)); - progressBar(progressInPercent); + auto s1 = QString(QString::number(progressInPercent) + "% | " + formatTime(elapsed_ms) + " < " + formatTime(remaining_ms)); + auto s2 = QString(progressBar(progressInPercent)); + return s1 + s2; } -void IPrinter::progressBar(int percentage) +QString IPrinter::progressBar(int percentage) { int cols = 42; @@ -125,21 +126,13 @@ void IPrinter::progressBar(int percentage) { cols = atoi(env_p); } + cols -= 2; qDebug() << "#col: " << cols; - - // print without appending newline - QDebug deb = qDebug(); - deb << "["; int pos_progress = cols*(percentage/100.0); - for(int pos=1; pos<cols-1; pos++) - { - if( pos < pos_progress ) - deb << "="; - else - deb << " "; - } - deb << "]"; + QString left = QString("=").repeated(pos_progress); + QString right = QString(" ").repeated(cols-pos_progress); + return QString("[%1%2]").arg(left).arg(right); } diff --git a/src/iprinter.h b/src/iprinter.h index b66d470e5d87efb7798f376117b99903b6d38e8e..180bed5598e4c568c70d5a3cca68d4ddc2d518de 100644 --- a/src/iprinter.h +++ b/src/iprinter.h @@ -39,10 +39,10 @@ public: void print(const char*, const QString&); - void progressBar(QTimer*); + QString progressBar(QTimer*); + QString progressBar(int); private: - void progressBar(int); QString formatTime(const int&); diff --git a/src/record.cpp b/src/record.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1cc4ec206a116eeeda3979e0ed1ff6e27df22b61 --- /dev/null +++ b/src/record.cpp @@ -0,0 +1,237 @@ +#include "record.h" +#include "utils.h" +#include "cam.h" +#include "frameobserver.h" + +#include <QDebug> +#include <QTimer> +#include <QStorageInfo> + +using namespace VmbCPP; +using namespace std::chrono; + +Record::Record(CamPtr cam) : IPrinter(), +_cam(cam), +_timer(new QTimer(this)), +_updateTimer(new QTimer(this)), +_dir(utils::outDir() + QDir::separator() + cam->name() + QDir::separator()), //specific for cam +_payloadSize(0LL), +_pixelFormat(""), +_frames(FramePtrVector(utils::threadsPerCam())) +// _frames(FramePtrVector(1)), +{ + _timer->setSingleShot(true); + connect(_timer, SIGNAL(timeout()), this, SLOT(stop())); + + _updateTimer->setInterval(1000); + connect(_updateTimer, SIGNAL(timeout()), this, SLOT(showProgress())); + connect(_updateTimer, SIGNAL(timeout()), this, SLOT(showStats())); +} + +Record::Record() : IPrinter(), +_cam(nullptr), +_timer(nullptr), +_updateTimer(nullptr), +_dir(""), +_payloadSize(0LL), +_pixelFormat(""), +_frames() +{} + + +bool Record::checkDirExists() +{ + //check if dir exists and if it doesnt, create it + QDir dir(_dir); + if (!dir.exists() && !dir.mkpath(".") ) + { + error("could not create directory: " + _dir); + return false; + } + + checkDiskSpace(); + + info("writing frames to: " + _dir); + return true; +} + +void Record::checkDiskSpace() +{ + //TODO + //check disk space + + //calculate disk space needed + //check if enough space + //if not, stop recording +} + +/* Does: + get Payloadsize + get Pixelformat - eg RGB8 + Allocate memory for frame buffer + Register frame observer / callback for each frame + Announce frame to the API + Start the capture engine (API) + Put frame into the frame queue + Start the acquisition engine ( _curCam) + + 2d get frameID +*/ +void Record::start(seconds dur) +{ + if(!checkDirExists()) + return; + + if( _cam->state() != Cam::opened ) + return error("cant start recording, when cam is " + _cam->stateToString(_cam->state())); + + try + { + auto vcam = _cam->getCameraPtr(); + FeaturePtr pFeature; + + g( vcam->GetFeatureByName ("PayloadSize", pFeature )); //xxx adjust: set to 7062528 + g( pFeature->GetValue (_payloadSize)); + print("PayloadSize",_payloadSize); + + g( vcam->GetFeatureByName("PixelFormat", pFeature)); + g( pFeature->GetValue(_pixelFormat)); + print("PixelFormat",_pixelFormat); + + for( auto& frame : _frames ) + { + frame.reset(new Frame(_payloadSize)); + g( frame->RegisterObserver( IFrameObserverPtr( new FrameObserver(_cam) )),"register frame observer"); + + g( vcam->AnnounceFrame(frame), "announce frame"); + } + + g( vcam->StartCapture(), "start capture"); + + for( auto& frame : _frames ) + g( vcam->QueueFrame(frame),"QueueFrame"); + + g( vcam->GetFeatureByName ("AcquisitionStart", pFeature ),"get AcquisitionStart"); + g( pFeature->RunCommand(),"run AcquisitionStart"); + + } + catch (const std::runtime_error& xx) + { + qDebug() << __FUNCTION__ << "Exception caught: " << xx.what(); + return; + } + + _cam->setState(Cam::recording); + + // Convert to milliseconds + // auto dur_ms = duration_cast<milliseconds>(dur); + _timer->start(dur); +} + +void Record::start(minutes dur) +{ + start(duration_cast<seconds>(dur)); // Convert to seconds +} + +/* Does: + Stop the capture engine (API) + discard all pending callbacks + Flush the frame queue + Revoke all frames from the API + Unregister the frame observer / callback +*/ +void Record::stop() +{ + if(_timer->isActive()) + { + //user stop or error + info( progressBar(_timer) ); + _timer->stop(); + } + else + { + //normal stop + info( progressBar(100) ); + } + + try + { + FeaturePtr pFeature; + auto vcam = _cam->getCameraPtr(); + + g(vcam->GetFeatureByName ("AcquisitionStop", pFeature ),"get AcquisitionStop"); + g(pFeature->RunCommand(),"run AcquisitionStop"); + g(vcam->EndCapture(),"end capture"); + g(vcam->FlushQueue(),"flush queue"); + g(vcam->RevokeAllFrames(),"revoke all frames"); + for( FramePtr frame : _frames ) + g(frame->UnregisterObserver(),"unregister observer"); + + _cam->setState(Cam::opened); + } + catch (const std::runtime_error& xx) + { + qDebug() << __FUNCTION__ << "Exception caught: " << xx.what(); + return; + } + + showStats(); +} + + //hdd space used + // hdd space left + // time elapsed / progress + // fps? +void Record::showStats() +{ + _cam->printFeatures("StatFrameDropped"); + _cam->printFeatures({ + // "StatFrameDropped", //unsigned int max 4294967295 + "StatFrameRate", //float send by cam + "StatLocalRate", //float rcvd by observer + "StatFrameRescued", + "StatFrameShoved", + "StatFrameUnderrun", + "StatPacketErrors", + "StatPacketMissed", + "StatPacketReceived", + "StatPacketRequested", + "StatPacketResent", + "StatTimeElapsed", //float - time elapsed since start of acquisition + "StatFrameDelivered" + }); + + // showHDD(); 2D +} + +void Record::showProgress() +{ + //TODO test + //fps? + info( progressBar(_timer) ); +} + +void Record::checkDiskSpace(const QString &dir, seconds dur) +{ + QStorageInfo storageInfo(dir); + + //in bytes + qint64 available = storageInfo.bytesAvailable(); + qint64 total = storageInfo.bytesTotal(); + qint64 used = utils::calcDirSize(dir); + + int usedPercentage = (double(used) / total) * 100; + info( progressBar(usedPercentage) ); // << cuz of this line, the function is here not in utils... + + qint64 estimated = dur.count() * utils::fps() * utils::frameSize(); + + qDebug() << "Used Space:" << used / (1024 * 1024) << "MB"; + qDebug() << "Available Space:" << available / (1024 * 1024) << "MB"; + qDebug() << "Total Space:" << total / (1024 * 1024) << "MB"; + qDebug() << "Used Percentage:" << usedPercentage << "%"; + qDebug() << "Estimated Recording Space:" << estimated / (1024 * 1024) << "MB"; + + // Check if estimated recording space exceeds available space + if (estimated > available) { + qWarning() << "Warning: Estimated recording space exceeds available space!"; + } +} diff --git a/src/record.h b/src/record.h new file mode 100644 index 0000000000000000000000000000000000000000..9d9fd952e2df754e21c88c2d5ddb9fc126332da5 --- /dev/null +++ b/src/record.h @@ -0,0 +1,50 @@ +#pragma once + +#include "iprinter.h" +#include "typeDefinitions.h" + +#include <QDir> + + +class QTimer; + +class Record : public IPrinter +{ + Q_OBJECT + +public: + Record(CamPtr); + Record(); + // Record(const Record&); + // ~Record(); + + void start(minutes); + void start(seconds); //can use literals "1s, 1min" + + void showStats(); + void showProgress(); + + void checkDiskSpace(const QString &, seconds); + + operator bool() const { + return _cam != nullptr; + } + +public slots: + void stop(); + +private: + bool checkDirExists(); + + CamPtr _cam; + QTimer* _timer; + QTimer* _updateTimer; + + QString _dir; + VmbInt64_t _payloadSize; + std::string _pixelFormat; + FramePtrVector _frames; + + +}; + diff --git a/src/typeDefinitions.h b/src/typeDefinitions.h new file mode 100644 index 0000000000000000000000000000000000000000..cdd192e2dbfab8b07471e0384d66bd1c4ca9528b --- /dev/null +++ b/src/typeDefinitions.h @@ -0,0 +1,27 @@ +#pragma once + +/* most common includes + type definitions */ + +#include <vector> +#include <memory> //shared_ptr +#include <QObject> +#include <QString> + +#include <VmbCPP/Camera.h> + +using VmbCPP::CameraPtr; +using VmbCPP::FramePtr; +using VmbCPP::FeaturePtr; +using VmbCPP::FramePtrVector; +using VmbCPP::UpdateTriggerType; + +#include <chrono> +using std::chrono::minutes; +using std::chrono::seconds; + +class Cam; // != Camera, which is the vimba object! +using CamPtr = std::shared_ptr<Cam>; +using CamPtrVector = std::vector<CamPtr>; + +class Record; +using RecordPtr = std::shared_ptr<Record>; diff --git a/src/utils.cpp b/src/utils.cpp index f97cdc18a38ac8e41f5ded7c82b2b3d02f57298a..f97ab783e969e92e2c7ed9486b55af53e9b9147a 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -16,6 +16,8 @@ #include <QJsonDocument> #include <QJsonArray> #include <QJsonObject> +#include <QFileInfoList> + using namespace VmbCPP; @@ -47,6 +49,18 @@ int threadsPerCam() #endif } +int frameSize() +{ + //XXX make configurable + return 764000; +} + +int fps() +{ + //XXX make configurable + return 17; +} + const QString getVersion() { return QString("# Recorder: %1.%2.%3").arg(APP_VERSION_MAJOR).arg(APP_VERSION_MINOR).arg(APP_VERSION_PATCH); @@ -97,6 +111,7 @@ const QString errorCodeToMessage( VmbError_t err ) case errNoCams: msg += "no cameras found."; break; case errRegisterCamObserver: msg += "cant register camobserver."; break; case errLessCamsThanExpected: msg += "less cameras found, than expected"; break; + case errRecordInvalid: msg += "Record invalid"; break; // ... add more } @@ -226,6 +241,20 @@ QString settingsFile(QString filename) return _settingsFile.isEmpty() ? utils::getFirstFileInAppDirEndingWith("xml") : _settingsFile; } +qint64 calcDirSize(const QString &dirrr) { + QDir dir(dirrr); + qint64 size = 0; + + // Recursively calculate size of files in the directory + foreach(QFileInfo fileInfo, dir.entryInfoList(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot, QDir::DirsFirst)) + { + if (fileInfo.isDir()) + size += calcDirSize(fileInfo.absoluteFilePath()); + else + size += fileInfo.size(); + } + return size; +} } // namespace utils diff --git a/src/utils.h b/src/utils.h index 9f44df37ff7c6da3bfcc9145cbaec07b86929d04..b03252542660b8a120548bfee92919a20497a377 100644 --- a/src/utils.h +++ b/src/utils.h @@ -21,8 +21,12 @@ bool parseConfig(QList<QPair<QString,QString>>&, seconds&); QString configFile(QString filename=""); QString settingsFile(QString filename=""); QString outDir(QString dirname=""); -QString getFirstFileInAppDirEndingWith( QString const&); +int frameSize(); +int fps(); +qint64 calcDirSize(const QString &); + +QString getFirstFileInAppDirEndingWith( QString const&); const QStringList getVersions(); const QString getVersion(); @@ -40,6 +44,7 @@ typedef enum camtronErr errNoCams = 11, //!< no cameras found errRegisterCamObserver = 12, //!< cant register camobserver errLessCamsThanExpected = 13, //!< no cameras found + errRecordInvalid = 14, //!< record invalid } camtronErr; } //namespace utils