v3.3.t5
-again reformed the detectloop class to use filesystem monitoring instead of timers to pull clips from the live stream. -removed the loop class after reforming detectloop.
This commit is contained in:
parent
60a24c9d67
commit
4f0c37b92b
246
src/camera.cpp
246
src/camera.cpp
|
@ -31,22 +31,22 @@ int Camera::start(const QStringList &args)
|
||||||
return shared.retCode;
|
return shared.retCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
Loop::Loop(shared_t *sharedRes, QThread *thr, QObject *parent) : QObject(parent)
|
EventLoop::EventLoop(shared_t *sharedRes, QThread *thr, QObject *parent) : QObject(parent)
|
||||||
{
|
{
|
||||||
shared = sharedRes;
|
shared = sharedRes;
|
||||||
heartBeat = 10;
|
heartBeat = 2;
|
||||||
loopTimer = 0;
|
loopTimer = 0;
|
||||||
|
|
||||||
connect(thr, &QThread::started, this, &Loop::init);
|
connect(thr, &QThread::started, this, &EventLoop::init);
|
||||||
|
|
||||||
moveToThread(thr);
|
moveToThread(thr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Loop::init()
|
void EventLoop::init()
|
||||||
{
|
{
|
||||||
loopTimer = new QTimer(this);
|
loopTimer = new QTimer(this);
|
||||||
|
|
||||||
connect(loopTimer, &QTimer::timeout, this, &Loop::loopSlot);
|
connect(loopTimer, &QTimer::timeout, this, &EventLoop::loopSlot);
|
||||||
|
|
||||||
loopTimer->setSingleShot(false);
|
loopTimer->setSingleShot(false);
|
||||||
loopTimer->start(heartBeat * 1000);
|
loopTimer->start(heartBeat * 1000);
|
||||||
|
@ -54,7 +54,7 @@ void Loop::init()
|
||||||
loopSlot();
|
loopSlot();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Loop::loopSlot()
|
void EventLoop::loopSlot()
|
||||||
{
|
{
|
||||||
if (!exec())
|
if (!exec())
|
||||||
{
|
{
|
||||||
|
@ -62,21 +62,6 @@ void Loop::loopSlot()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Loop::exec()
|
|
||||||
{
|
|
||||||
if (loopTimer->interval() != heartBeat * 1000)
|
|
||||||
{
|
|
||||||
loopTimer->start(heartBeat * 1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
return shared->retCode == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
EventLoop::EventLoop(shared_t *sharedRes, QThread *thr, QObject *parent) : Loop(sharedRes, thr, parent)
|
|
||||||
{
|
|
||||||
heartBeat = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool EventLoop::wrOutVod(const evt_t &event)
|
bool EventLoop::wrOutVod(const evt_t &event)
|
||||||
{
|
{
|
||||||
auto ret = false;
|
auto ret = false;
|
||||||
|
@ -155,33 +140,74 @@ bool EventLoop::exec()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Loop::exec();
|
return shared->retCode == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
DetectLoop::DetectLoop(shared_t *sharedRes, QThread *thr, QObject *parent) : Loop(sharedRes, thr, parent)
|
DetectLoop::DetectLoop(shared_t *sharedRes, QThread *thr, QObject *parent) : QFileSystemWatcher(parent)
|
||||||
{
|
{
|
||||||
pcTimer = 0;
|
pcTimer = 0;
|
||||||
heartBeat = 2;
|
shared = sharedRes;
|
||||||
|
|
||||||
|
connect(thr, &QThread::started, this, &DetectLoop::init);
|
||||||
|
|
||||||
|
moveToThread(thr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DetectLoop::init()
|
void DetectLoop::init()
|
||||||
{
|
{
|
||||||
pcTimer = new QTimer(this);
|
pcTimer = new QTimer(this);
|
||||||
|
|
||||||
eventQue.queAge = 0;
|
|
||||||
eventQue.score = 0;
|
|
||||||
eventQue.inQue = false;
|
|
||||||
|
|
||||||
connect(pcTimer, &QTimer::timeout, this, &DetectLoop::pcBreak);
|
connect(pcTimer, &QTimer::timeout, this, &DetectLoop::pcBreak);
|
||||||
|
connect(this, &QFileSystemWatcher::directoryChanged, this, &DetectLoop::updated);
|
||||||
|
|
||||||
resetTimers();
|
addPath(shared->buffPath + "/live");
|
||||||
|
|
||||||
Loop::init();
|
pcTimer->start(shared->postSecs * 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DetectLoop::resetTimers()
|
void DetectLoop::reset()
|
||||||
{
|
{
|
||||||
pcTimer->start(shared->postSecs * 1000);
|
vidAPath.clear();
|
||||||
|
vidBPath.clear();
|
||||||
|
|
||||||
|
eventQue.inQue = false;
|
||||||
|
eventQue.score = 0;
|
||||||
|
eventQue.queAge = 0;
|
||||||
|
|
||||||
|
eventQue.imgPath.clear();
|
||||||
|
eventQue.vidList.clear();
|
||||||
|
eventQue.timeStamp.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DetectLoop::updated(const QString &path)
|
||||||
|
{
|
||||||
|
auto clips = lsFilesInDir(path, shared->streamExt);
|
||||||
|
|
||||||
|
if (clips.isEmpty())
|
||||||
|
{
|
||||||
|
thread()->sleep(5); reset();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
auto latestPath = path + "/" + clips.last();
|
||||||
|
|
||||||
|
if (vidAPath.isEmpty())
|
||||||
|
{
|
||||||
|
vidAPath = latestPath;
|
||||||
|
}
|
||||||
|
else if (latestPath == vidAPath)
|
||||||
|
{
|
||||||
|
thread()->usleep(500);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
vidBPath = latestPath;
|
||||||
|
|
||||||
|
thread()->sleep(1);
|
||||||
|
|
||||||
|
exec();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DetectLoop::pcBreak()
|
void DetectLoop::pcBreak()
|
||||||
|
@ -259,6 +285,8 @@ QStringList DetectLoop::buildSnapArgs(const QString &vidSrc, const QString &imgP
|
||||||
QStringList ret;
|
QStringList ret;
|
||||||
|
|
||||||
ret.append("-hide_banner");
|
ret.append("-hide_banner");
|
||||||
|
ret.append("-loglevel");
|
||||||
|
ret.append("panic");
|
||||||
ret.append("-y");
|
ret.append("-y");
|
||||||
ret.append("-i");
|
ret.append("-i");
|
||||||
ret.append(vidSrc);
|
ret.append(vidSrc);
|
||||||
|
@ -269,101 +297,87 @@ QStringList DetectLoop::buildSnapArgs(const QString &vidSrc, const QString &imgP
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DetectLoop::exec()
|
void DetectLoop::exec()
|
||||||
{
|
{
|
||||||
if (eventQue.inQue)
|
auto imgAPath = shared->buffPath + "/img/" + QFileInfo(vidAPath).baseName() + ".bmp";
|
||||||
{
|
auto imgBPath = shared->buffPath + "/img/" + QFileInfo(vidBPath).baseName() + ".bmp";
|
||||||
eventQue.queAge += heartBeat;
|
auto snapArgsA = buildSnapArgs(vidAPath, imgAPath);
|
||||||
}
|
auto snapArgsB = buildSnapArgs(vidBPath, imgBPath);
|
||||||
|
auto compArgs = buildArgs(imgAPath, imgBPath);
|
||||||
|
|
||||||
auto clips = lsFilesInDir(shared->buffPath + "/live", shared->streamExt);
|
if (compArgs.isEmpty())
|
||||||
|
|
||||||
if (clips.size() < 2)
|
|
||||||
{
|
{
|
||||||
QTextStream(stdout) << "warning: didn't pick up enough clips files from the video stream. number of files: " << QString::number(clips.size()) << Qt::endl;
|
QTextStream(stderr) << "err: could not parse a executable name from img_comp_cmd: " << shared->compCmd << Qt::endl;
|
||||||
QTextStream(stdout) << " will try again on the next loop." << Qt::endl;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
auto vidAPath = shared->buffPath + "/live/" + clips[clips.size() - 2];
|
QProcess::execute("ffmpeg", snapArgsA);
|
||||||
auto vidBPath = shared->buffPath + "/live/" + clips[clips.size() - 1];
|
QProcess::execute("ffmpeg", snapArgsB);
|
||||||
auto imgAPath = shared->buffPath + "/img/" + QFileInfo(vidAPath).baseName() + ".bmp";
|
|
||||||
auto imgBPath = shared->buffPath + "/img/" + QFileInfo(vidBPath).baseName() + ".bmp";
|
|
||||||
auto snapArgsA = buildSnapArgs(vidAPath, imgAPath);
|
|
||||||
auto snapArgsB = buildSnapArgs(vidBPath, imgBPath);
|
|
||||||
auto compArgs = buildArgs(imgAPath, imgBPath);
|
|
||||||
|
|
||||||
if (compArgs.isEmpty())
|
if (QFile::exists(imgAPath) && QFile::exists(imgBPath))
|
||||||
{
|
{
|
||||||
QTextStream(stderr) << "err: could not parse a executable name from img_comp_cmd: " << shared->compCmd << Qt::endl;
|
QProcess extComp;
|
||||||
|
|
||||||
|
extComp.start(compArgs[0], compArgs.mid(1));
|
||||||
|
extComp.waitForFinished();
|
||||||
|
|
||||||
|
float score = 0;
|
||||||
|
|
||||||
|
if (shared->outputType == "stdout")
|
||||||
|
{
|
||||||
|
score = getFloatFromExe(extComp.readAllStandardOutput());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
score = getFloatFromExe(extComp.readAllStandardError());
|
||||||
|
}
|
||||||
|
|
||||||
|
QTextStream(stdout) << compArgs.join(" ") << " --result: " << QString::number(score) << Qt::endl;
|
||||||
|
|
||||||
|
if (eventQue.inQue)
|
||||||
|
{
|
||||||
|
eventQue.queAge += 4;
|
||||||
|
|
||||||
|
if (eventQue.score < score)
|
||||||
|
{
|
||||||
|
eventQue.score = score;
|
||||||
|
eventQue.imgPath = imgBPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
eventQue.vidList.append(vidAPath);
|
||||||
|
eventQue.vidList.append(vidBPath);
|
||||||
|
|
||||||
|
if (eventQue.queAge >= shared->evMaxSecs)
|
||||||
|
{
|
||||||
|
eventQue.inQue = false;
|
||||||
|
|
||||||
|
shared->recList.append(eventQue);
|
||||||
|
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (score >= shared->imgThresh)
|
||||||
|
{
|
||||||
|
QTextStream(stdout) << "--threshold_meet: " << QString::number(shared->imgThresh) << Qt::endl;
|
||||||
|
|
||||||
|
eventQue.score = score;
|
||||||
|
eventQue.imgPath = imgBPath;
|
||||||
|
eventQue.inQue = true;
|
||||||
|
eventQue.queAge = 0;
|
||||||
|
eventQue.timeStamp = QDateTime::currentDateTime().toString(DATETIME_FMT);
|
||||||
|
|
||||||
|
eventQue.vidList.append(vidAPath);
|
||||||
|
eventQue.vidList.append(vidBPath);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
QProcess::execute("ffmpeg", snapArgsA);
|
QTextStream(stdout) << "why?" << Qt::endl;
|
||||||
QProcess::execute("ffmpeg", snapArgsB);
|
QTextStream(stdout) << "imgAPath: " << imgAPath << Qt::endl;
|
||||||
|
QTextStream(stdout) << "imgBPath: " << imgBPath << Qt::endl;
|
||||||
if (QFile::exists(imgAPath) && QFile::exists(imgBPath))
|
|
||||||
{
|
|
||||||
QProcess extComp;
|
|
||||||
|
|
||||||
extComp.start(compArgs[0], compArgs.mid(1));
|
|
||||||
extComp.waitForFinished();
|
|
||||||
|
|
||||||
float score = 0;
|
|
||||||
|
|
||||||
if (shared->outputType == "stdout")
|
|
||||||
{
|
|
||||||
score = getFloatFromExe(extComp.readAllStandardOutput());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
score = getFloatFromExe(extComp.readAllStandardError());
|
|
||||||
}
|
|
||||||
|
|
||||||
QTextStream(stdout) << compArgs.join(" ") << " --result: " << QString::number(score) << Qt::endl;
|
|
||||||
|
|
||||||
if (eventQue.inQue)
|
|
||||||
{
|
|
||||||
if (eventQue.score < score)
|
|
||||||
{
|
|
||||||
eventQue.score = score;
|
|
||||||
eventQue.imgPath = imgBPath;
|
|
||||||
}
|
|
||||||
|
|
||||||
eventQue.vidList.append(vidAPath);
|
|
||||||
eventQue.vidList.append(vidBPath);
|
|
||||||
|
|
||||||
if (eventQue.queAge >= shared->evMaxSecs)
|
|
||||||
{
|
|
||||||
eventQue.inQue = false;
|
|
||||||
|
|
||||||
shared->recList.append(eventQue);
|
|
||||||
|
|
||||||
eventQue.imgPath.clear();
|
|
||||||
eventQue.vidList.clear();
|
|
||||||
eventQue.timeStamp.clear();
|
|
||||||
|
|
||||||
eventQue.score = 0;
|
|
||||||
eventQue.queAge = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (score >= shared->imgThresh)
|
|
||||||
{
|
|
||||||
QTextStream(stdout) << "--threshold_breached: " << QString::number(shared->imgThresh) << Qt::endl;
|
|
||||||
|
|
||||||
eventQue.score = score;
|
|
||||||
eventQue.imgPath = imgBPath;
|
|
||||||
eventQue.inQue = true;
|
|
||||||
eventQue.queAge = 0;
|
|
||||||
eventQue.timeStamp = QDateTime::currentDateTime().toString(DATETIME_FMT);
|
|
||||||
|
|
||||||
eventQue.vidList.clear();
|
|
||||||
eventQue.vidList.append(vidAPath);
|
|
||||||
eventQue.vidList.append(vidBPath);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Loop::exec();
|
vidAPath.clear();
|
||||||
|
vidBPath.clear();
|
||||||
}
|
}
|
||||||
|
|
44
src/camera.h
44
src/camera.h
|
@ -30,37 +30,21 @@ public:
|
||||||
int start(const QStringList &args);
|
int start(const QStringList &args);
|
||||||
};
|
};
|
||||||
|
|
||||||
class Loop : public QObject
|
class EventLoop : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
protected:
|
private slots:
|
||||||
|
|
||||||
|
void init();
|
||||||
|
void loopSlot();
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
shared_t *shared;
|
shared_t *shared;
|
||||||
QTimer *loopTimer;
|
QTimer *loopTimer;
|
||||||
int heartBeat;
|
int heartBeat;
|
||||||
|
|
||||||
protected slots:
|
|
||||||
|
|
||||||
virtual void init();
|
|
||||||
|
|
||||||
private slots:
|
|
||||||
|
|
||||||
void loopSlot();
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
explicit Loop(shared_t *shared, QThread *thr, QObject *parent = nullptr);
|
|
||||||
|
|
||||||
virtual bool exec();
|
|
||||||
};
|
|
||||||
|
|
||||||
class EventLoop : public Loop
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
bool wrOutVod(const evt_t &event);
|
bool wrOutVod(const evt_t &event);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -70,16 +54,18 @@ public:
|
||||||
bool exec();
|
bool exec();
|
||||||
};
|
};
|
||||||
|
|
||||||
class DetectLoop : public Loop
|
class DetectLoop : public QFileSystemWatcher
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
QTimer *pcTimer;
|
QString vidAPath;
|
||||||
evt_t eventQue;
|
QString vidBPath;
|
||||||
|
QTimer *pcTimer;
|
||||||
|
evt_t eventQue;
|
||||||
|
shared_t *shared;
|
||||||
|
|
||||||
void resetTimers();
|
|
||||||
float getFloatFromExe(const QByteArray &line);
|
float getFloatFromExe(const QByteArray &line);
|
||||||
QStringList buildArgs(const QString &prev, const QString &next);
|
QStringList buildArgs(const QString &prev, const QString &next);
|
||||||
QStringList buildSnapArgs(const QString &vidSrc, const QString &imgPath);
|
QStringList buildSnapArgs(const QString &vidSrc, const QString &imgPath);
|
||||||
|
@ -87,13 +73,15 @@ private:
|
||||||
private slots:
|
private slots:
|
||||||
|
|
||||||
void init();
|
void init();
|
||||||
|
void reset();
|
||||||
void pcBreak();
|
void pcBreak();
|
||||||
|
void updated(const QString &path);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
explicit DetectLoop(shared_t *shared, QThread *thr, QObject *parent = nullptr);
|
explicit DetectLoop(shared_t *shared, QThread *thr, QObject *parent = nullptr);
|
||||||
|
|
||||||
bool exec();
|
void exec();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // CAMERA_H
|
#endif // CAMERA_H
|
||||||
|
|
|
@ -25,11 +25,12 @@
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
#include <QMutex>
|
#include <QMutex>
|
||||||
#include <QRegularExpression>
|
#include <QRegularExpression>
|
||||||
|
#include <QFileSystemWatcher>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
#define APP_VER "3.3.t4"
|
#define APP_VER "3.3.t5"
|
||||||
#define APP_NAME "Motion Watch"
|
#define APP_NAME "Motion Watch"
|
||||||
#define APP_BIN "mow"
|
#define APP_BIN "mow"
|
||||||
#define DATETIME_FMT "yyyyMMddhhmmss"
|
#define DATETIME_FMT "yyyyMMddhhmmss"
|
||||||
|
|
Loading…
Reference in New Issue
Block a user