Compare commits

...

4 Commits

Author SHA1 Message Date
Zii
25528617d5 v3.1
Current version is stable, realeasing to master.
2023-07-23 09:35:36 -04:00
Zii
ad733f8317 v3.1.t2
added a buffer directory so the actual work of image frame capture
and live video recording can be moved off of main storage.

also removed installation of the apache2 http server from
install.sh to make this app more agnostic and leave it up to the
end user to install what ever web server they want.
2023-07-18 18:47:14 -04:00
Zii
c17f74bea9 v3.1.t1
-Fixed the compile error for older versions of QT.
2023-06-20 18:02:35 -04:00
Zii
5f9c4be6b2 v3.1.t1
-added event age to evt_t as a way to track the age of the event
 in EventLoop so now only events approching and exceeding
 evMaxSecs will have the video range added for writing.
2023-06-20 17:49:52 -04:00
5 changed files with 85 additions and 41 deletions

View File

@ -40,6 +40,11 @@ web_root = /var/www/html
# warning: this will overwrite any existing index.html files so be sure # warning: this will overwrite any existing index.html files so be sure
# to choose a directory that doesn't have an existing website. # to choose a directory that doesn't have an existing website.
# #
buffer_path = /tmp
# this is the work directory the app will use to store live footage and
# image frames. it's recommended to use a ram disk for this since there
# will be large amounts of io occuring here.
#
cam_name = cam-1 cam_name = cam-1
# this is the optional camera name parameter to identify the camera. this # this is the optional camera name parameter to identify the camera. this
# name will also be used to as the base directory in web_root. if not # name will also be used to as the base directory in web_root. if not

View File

@ -1,12 +1,9 @@
#!/bin/sh #!/bin/sh
apt install apache2
if [ ! -d "/opt/mow" ]; then if [ ! -d "/opt/mow" ]; then
mkdir /opt/mow mkdir /opt/mow
fi fi
cp ./.build-mow/mow /opt/mow/bin cp ./.build-mow/mow /opt/mow/bin
printf "#!/bin/sh\n" > /opt/mow/run printf "#!/bin/sh\n" > /opt/mow/run
printf "export OPENCV_LOG_LEVEL=DEBUG\n" >> /opt/mow/run
printf "export OPENCV_VIDEOIO_DEBUG=1\n" >> /opt/mow/run
printf "/opt/mow/bin \$1 \$2 \$3\n" >> /opt/mow/run printf "/opt/mow/bin \$1 \$2 \$3\n" >> /opt/mow/run
chmod +x /opt/mow/run chmod +x /opt/mow/run
chmod +x /opt/mow/bin chmod +x /opt/mow/bin

View File

@ -25,6 +25,7 @@ Camera::Camera(QObject *parent) : QObject(parent)
shared.skipCmd = false; shared.skipCmd = false;
shared.postSecs = 60; shared.postSecs = 60;
shared.evMaxSecs = 30; shared.evMaxSecs = 30;
shared.buffPath = QDir::tempPath();
shared.webRoot = "/var/www/html"; shared.webRoot = "/var/www/html";
shared.webBg = "#485564"; shared.webBg = "#485564";
shared.webTxt = "#dee5ee"; shared.webTxt = "#dee5ee";
@ -37,14 +38,6 @@ int Camera::start(const QStringList &args)
if (rdConf(&shared)) if (rdConf(&shared))
{ {
QDir("live").removeRecursively();
QDir("img").removeRecursively();
QDir().mkdir("live");
QDir().mkdir("events");
QDir().mkdir("logs");
QDir().mkdir("img");
auto thr1 = new QThread(nullptr); auto thr1 = new QThread(nullptr);
auto thr2 = new QThread(nullptr); auto thr2 = new QThread(nullptr);
auto thr3 = new QThread(nullptr); auto thr3 = new QThread(nullptr);
@ -215,11 +208,6 @@ Upkeep::Upkeep(shared_t *sharedRes, QThread *thr, QObject *parent) : Loop(shared
bool Upkeep::exec() bool Upkeep::exec()
{ {
QDir().mkdir("live");
QDir().mkdir("events");
QDir().mkdir("logs");
QDir().mkdir("img");
enforceMaxLogSize(QString("logs/") + REC_LOG_NAME, shared); enforceMaxLogSize(QString("logs/") + REC_LOG_NAME, shared);
enforceMaxLogSize(QString("logs/") + DET_LOG_NAME, shared); enforceMaxLogSize(QString("logs/") + DET_LOG_NAME, shared);
@ -253,7 +241,7 @@ EventLoop::EventLoop(shared_t *sharedRes, QThread *thr, QObject *parent) : Loop(
bool EventLoop::exec() bool EventLoop::exec()
{ {
if (cycles * 2 >= shared->evMaxSecs) if (!vidList.isEmpty())
{ {
vidList.removeDuplicates(); vidList.removeDuplicates();
@ -282,31 +270,45 @@ bool EventLoop::exec()
vidList.clear(); vidList.clear();
} }
else
{
cycles += 1;
shared->recMutex.lock(); shared->recMutex.lock();
for (auto &&event : shared->recList) QList<int> rmIndx;
{
auto maxFiles = shared->evMaxSecs / 2;
// there's 2 secs in each hls segment
if (highScore < event.score) for (auto i = 0; i < shared->recList.size(); ++i)
{ {
name = event.timeStamp.toString(DATETIME_FMT); auto event = &shared->recList[i];
imgPath = event.imgPath;
highScore = event.score; if (highScore < event->score)
{
name = event->timeStamp.toString(DATETIME_FMT);
imgPath = event->imgPath;
highScore = event->score;
} }
vidList.append(backwardFacingFiles("live", ".ts", event.timeStamp, maxFiles / 2)); if (event->queAge >= (shared->evMaxSecs / heartBeat))
vidList.append(forwardFacingFiles("live", ".ts", event.timeStamp, maxFiles / 2)); {
auto maxSecs = shared->evMaxSecs / 2;
// half the maxsecs value to get front-back half secs
auto backFiles = backwardFacingFiles("live", ".ts", event->timeStamp, maxSecs);
auto frontFiles = forwardFacingFiles("live", ".ts", event->timeStamp, maxSecs);
vidList.append(backFiles + frontFiles);
rmIndx.append(i);
}
else
{
event->queAge += heartBeat;
}
}
for (auto i : rmIndx)
{
shared->recList.removeAt(i);
} }
shared->recList.clear();
shared->recMutex.unlock(); shared->recMutex.unlock();
}
return Loop::exec(); return Loop::exec();
} }
@ -377,9 +379,9 @@ DetectLoop::DetectLoop(shared_t *sharedRes, QThread *thr, QObject *parent) : Loo
{ {
pcTimer = 0; pcTimer = 0;
heartBeat = 2; heartBeat = 2;
delayCycles = 8; // this will be used to delay the delayCycles = 12; // this will be used to delay the
// actual start of DetectLoop by // actual start of DetectLoop by
// 16secs. // 24secs.
} }
void DetectLoop::init() void DetectLoop::init()
@ -473,6 +475,7 @@ bool DetectLoop::exec()
event.timeStamp = curDT; event.timeStamp = curDT;
event.score = score; event.score = score;
event.imgPath = images[pos]; event.imgPath = images[pos];
event.queAge = 0;
shared->recMutex.lock(); shared->recMutex.lock();
shared->recList.append(event); mod = true; shared->recList.append(event); mod = true;

View File

@ -167,6 +167,21 @@ void rdLine(const QString &param, const QString &line, int *value)
} }
} }
void touch(const QString &path)
{
if (!QFile::exists(path))
{
QFile file(path);
if (file.open(QFile::WriteOnly))
{
file.write("");
}
file.close();
}
}
bool rdConf(const QString &filePath, shared_t *share) bool rdConf(const QString &filePath, shared_t *share)
{ {
QFile varFile(filePath); QFile varFile(filePath);
@ -189,6 +204,7 @@ bool rdConf(const QString &filePath, shared_t *share)
{ {
rdLine("cam_name = ", line, &share->camName); rdLine("cam_name = ", line, &share->camName);
rdLine("recording_stream = ", line, &share->recordUrl); rdLine("recording_stream = ", line, &share->recordUrl);
rdLine("buffer_path = ", line, &share->buffPath);
rdLine("web_root = ", line, &share->webRoot); rdLine("web_root = ", line, &share->webRoot);
rdLine("web_text = ", line, &share->webTxt); rdLine("web_text = ", line, &share->webTxt);
rdLine("web_bg = ", line, &share->webBg); rdLine("web_bg = ", line, &share->webBg);
@ -217,10 +233,29 @@ bool rdConf(shared_t *share)
} }
share->outDir = QDir().cleanPath(share->webRoot) + "/" + share->camName; share->outDir = QDir().cleanPath(share->webRoot) + "/" + share->camName;
share->tmpDir = share->buffPath + "/" + APP_BIN + "/" + share->camName;
QDir().mkpath(share->outDir); QDir().mkpath(share->outDir);
QDir().mkpath(share->tmpDir);
if (!QDir::setCurrent(share->outDir)) QDir().mkpath(share->outDir + "/events");
QDir().mkpath(share->tmpDir + "/live");
QDir().mkpath(share->tmpDir + "/logs");
QDir().mkpath(share->tmpDir + "/img");
touch(share->tmpDir + "/index.html");
touch(share->tmpDir + "/stream.html");
touch(share->tmpDir + "/stream.m3u8");
QFile::link(share->tmpDir + "/live", share->outDir + "/live");
QFile::link(share->tmpDir + "/logs", share->outDir + "/logs");
QFile::link(share->tmpDir + "/img", share->outDir + "/img");
QFile::link(share->tmpDir + "/index.html", share->outDir + "/index.html");
QFile::link(share->tmpDir + "/stream.html", share->outDir + "/stream.html");
QFile::link(share->tmpDir + "/stream.m3u8", share->outDir + "/stream.m3u8");
QFile::link(share->outDir + "/events", share->tmpDir + "/events");
if (!QDir::setCurrent(share->tmpDir))
{ {
QTextStream(stderr) << "err: failed to change/create the current working directory to camera folder: '" << share->outDir << "' does it exists?" << Qt::endl; QTextStream(stderr) << "err: failed to change/create the current working directory to camera folder: '" << share->outDir << "' does it exists?" << Qt::endl;

View File

@ -29,7 +29,7 @@
using namespace std; using namespace std;
#define APP_VER "3.0.0" #define APP_VER "3.1"
#define APP_NAME "Motion Watch" #define APP_NAME "Motion Watch"
#define APP_BIN "mow" #define APP_BIN "mow"
#define REC_LOG_NAME "rec_log_lines.html" #define REC_LOG_NAME "rec_log_lines.html"
@ -45,6 +45,7 @@ struct evt_t
QDateTime timeStamp; QDateTime timeStamp;
QString imgPath; QString imgPath;
float score; float score;
uint queAge;
}; };
struct shared_t struct shared_t
@ -57,6 +58,8 @@ struct shared_t
QString detLog; QString detLog;
QString recordUrl; QString recordUrl;
QString outDir; QString outDir;
QString tmpDir;
QString buffPath;
QString postCmd; QString postCmd;
QString camName; QString camName;
QString webBg; QString webBg;
@ -80,6 +83,7 @@ QStringList backwardFacingFiles(const QString &path, const QString &ext, const Q
QStringList forwardFacingFiles(const QString &path, const QString &ext, const QDateTime &stamp, int secs); QStringList forwardFacingFiles(const QString &path, const QString &ext, const QDateTime &stamp, int secs);
bool rdConf(const QString &filePath, shared_t *share); bool rdConf(const QString &filePath, shared_t *share);
bool rdConf(shared_t *share); bool rdConf(shared_t *share);
void touch(const QString &path);
void rdLine(const QString &param, const QString &line, QString *value); void rdLine(const QString &param, const QString &line, QString *value);
void rdLine(const QString &param, const QString &line, int *value); void rdLine(const QString &param, const QString &line, int *value);
void enforceMaxEvents(shared_t *share); void enforceMaxEvents(shared_t *share);