v2.1.t2
the delay on the motion detection loop slowed it down too much to the point that it falls too far behind live. I removed the delay and re-introduced the frame gap so all frames in the video files need to be decoded. post command and event timers are now seperate but still tied to a single thread so they can still be synced. fixed an issued that cuased several thmubnails to not generate. added more log lines the aid with debugging.
This commit is contained in:
parent
bafd2bf727
commit
b4ca30b0e1
|
@ -175,6 +175,11 @@ string genDstFile(const string &dirOut, const char *fmt, const string &ext)
|
|||
return cleanDir(dirOut) + string("/") + genTimeStr(fmt) + ext;
|
||||
}
|
||||
|
||||
string genEventName()
|
||||
{
|
||||
return genTimeStr("%Y-%j-%H-%M");
|
||||
}
|
||||
|
||||
void rdLine(const string ¶m, const string &line, string *value)
|
||||
{
|
||||
if (line.rfind(param.c_str(), 0) == 0)
|
||||
|
@ -217,10 +222,12 @@ bool rdConf(const string &filePath, shared_t *share)
|
|||
rdLine("web_text = ", line, &share->webTxt);
|
||||
rdLine("web_bg = ", line, &share->webBg);
|
||||
rdLine("web_font = ", line, &share->webFont);
|
||||
rdLine("sch_sec = ", line, &share->schSec);
|
||||
rdLine("max_event_secs = ", line, &share->evMaxSecs);
|
||||
rdLine("post_secs = ", line, &share->postSecs);
|
||||
rdLine("post_cmd = ", line, &share->postCmd);
|
||||
rdLine("pix_thresh = ", line, &share->pixThresh);
|
||||
rdLine("img_thresh = ", line, &share->imgThresh);
|
||||
rdLine("frame_gap = ", line, &share->frameGap);
|
||||
rdLine("max_events = ", line, &share->maxEvents);
|
||||
rdLine("max_log_size = ", line, &share->maxLogSize);
|
||||
}
|
||||
|
@ -241,9 +248,11 @@ bool rdConf(shared_t *share)
|
|||
share->pixThresh = 50;
|
||||
share->imgThresh = 800;
|
||||
share->maxEvents = 40;
|
||||
share->maxLogSize = 50000;
|
||||
share->maxLogSize = 100000;
|
||||
share->skipCmd = false;
|
||||
share->schSec = 60;
|
||||
share->postSecs = 60;
|
||||
share->evMaxSecs = 10;
|
||||
share->frameGap = 5;
|
||||
share->webRoot = "/var/www/html";
|
||||
share->webBg = "#485564";
|
||||
share->webTxt = "#dee5ee";
|
||||
|
|
18
src/common.h
18
src/common.h
|
@ -34,13 +34,13 @@ using namespace std;
|
|||
using namespace std::filesystem;
|
||||
using namespace std::chrono;
|
||||
|
||||
#define APP_VER "2.1.t1"
|
||||
#define APP_VER "2.1.t2"
|
||||
#define APP_NAME "Motion Watch"
|
||||
#define REC_LOG_NAME "rec_log_lines.html"
|
||||
#define DET_LOG_NAME "det_log_lines.html"
|
||||
#define UPK_LOG_NAME "upk_log_lines.html"
|
||||
|
||||
struct pls_t
|
||||
struct evt_t
|
||||
{
|
||||
string evName;
|
||||
vector<string> srcPaths;
|
||||
|
@ -49,8 +49,7 @@ struct pls_t
|
|||
|
||||
struct shared_t
|
||||
{
|
||||
map<string, pls_t> recList;
|
||||
string curEventName;
|
||||
vector<evt_t> recList;
|
||||
string conf;
|
||||
string recLog;
|
||||
string detLog;
|
||||
|
@ -63,19 +62,26 @@ struct shared_t
|
|||
string webTxt;
|
||||
string webFont;
|
||||
string webRoot;
|
||||
evt_t curEvent;
|
||||
bool skipCmd;
|
||||
int frameGap;
|
||||
int evMaxSecs;
|
||||
int postSecs;
|
||||
int maxScore;
|
||||
int procTime;
|
||||
int schSec;
|
||||
int procCnt;
|
||||
int hlsCnt;
|
||||
int pixThresh;
|
||||
int imgThresh;
|
||||
int maxEvents;
|
||||
int maxLogSize;
|
||||
int retCode;
|
||||
int postInd;
|
||||
int evInd;
|
||||
};
|
||||
|
||||
string genVidNameFromLive(const string &tsPath);
|
||||
string genEventPath(const string &tsPath);
|
||||
string genEventName();
|
||||
string genDstFile(const string &dirOut, const char *fmt, const string &ext);
|
||||
string genTimeStr(const char *fmt);
|
||||
string cleanDir(const string &path);
|
||||
|
|
41
src/main.cpp
41
src/main.cpp
|
@ -14,6 +14,17 @@
|
|||
#include "logger.h"
|
||||
#include "web.h"
|
||||
|
||||
void timer(shared_t *share)
|
||||
{
|
||||
while (share->retCode == 0)
|
||||
{
|
||||
sleep(1);
|
||||
|
||||
share->postInd += 1;
|
||||
share->evInd += 1;
|
||||
}
|
||||
}
|
||||
|
||||
void detectMo(shared_t *share)
|
||||
{
|
||||
while (share->retCode == 0)
|
||||
|
@ -27,27 +38,32 @@ void eventLoop(shared_t *share)
|
|||
{
|
||||
while (share->retCode == 0)
|
||||
{
|
||||
while (share->recList.size() > 1)
|
||||
if (!share->recList.empty())
|
||||
{
|
||||
auto it = share->recList.begin();
|
||||
auto evName = it->first;
|
||||
auto event = it->second;
|
||||
auto event = share->recList[0];
|
||||
|
||||
try
|
||||
{
|
||||
createDirTree("events");
|
||||
wrOutVod(event, share);
|
||||
genHTMLvod(evName);
|
||||
recLog("attempting write out of event: " + event.evName, share);
|
||||
|
||||
if (!exists("events/" + evName + ".jpg"))
|
||||
createDirTree("events");
|
||||
|
||||
if (wrOutVod(event, share))
|
||||
{
|
||||
imwrite(string("events/" + evName + ".jpg").c_str(), event.thumbnail);
|
||||
genHTMLvod(event.evName);
|
||||
|
||||
if (exists("events"))
|
||||
{
|
||||
imwrite(string("events/" + event.evName + ".jpg").c_str(), event.thumbnail);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (filesystem_error &ex)
|
||||
{
|
||||
recLog(string("err: ") + ex.what(), share);
|
||||
}
|
||||
|
||||
share->recList.erase(share->recList.begin());
|
||||
}
|
||||
|
||||
sleep(10);
|
||||
|
@ -96,7 +112,7 @@ void upkeep(shared_t *share)
|
|||
upkLog("skipping update of the webroot page, it is busy.", share);
|
||||
}
|
||||
|
||||
sleep(60);
|
||||
sleep(10);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -159,8 +175,9 @@ int main(int argc, char** argv)
|
|||
else
|
||||
{
|
||||
sharedRes.retCode = 0;
|
||||
sharedRes.procTime = 0;
|
||||
sharedRes.maxScore = 0;
|
||||
sharedRes.postInd = 0;
|
||||
sharedRes.evInd = 0;
|
||||
sharedRes.skipCmd = false;
|
||||
|
||||
rdConf(&sharedRes);
|
||||
|
@ -169,11 +186,13 @@ int main(int argc, char** argv)
|
|||
auto thr2 = thread(upkeep, &sharedRes);
|
||||
auto thr3 = thread(detectMo, &sharedRes);
|
||||
auto thr4 = thread(eventLoop, &sharedRes);
|
||||
auto thr5 = thread(timer, &sharedRes);
|
||||
|
||||
thr1.join();
|
||||
thr2.join();
|
||||
thr3.join();
|
||||
thr4.join();
|
||||
thr5.join();
|
||||
|
||||
return sharedRes.retCode;
|
||||
}
|
||||
|
|
|
@ -14,12 +14,11 @@
|
|||
|
||||
void detectMoInStream(const string &streamFile, shared_t *share)
|
||||
{
|
||||
if (share->procTime >= share->schSec)
|
||||
if (share->postInd >= share->postSecs)
|
||||
{
|
||||
share->curEventName.clear();
|
||||
|
||||
share->procTime = 0;
|
||||
share->maxScore = 0;
|
||||
if (!share->postCmd.empty())
|
||||
{
|
||||
detLog("---POST_BREAK---", share);
|
||||
|
||||
if (!share->skipCmd)
|
||||
{
|
||||
|
@ -34,9 +33,36 @@ void detectMoInStream(const string &streamFile, shared_t *share)
|
|||
}
|
||||
}
|
||||
|
||||
share->postInd = 0;
|
||||
}
|
||||
|
||||
if (share->evInd >= share->evMaxSecs)
|
||||
{
|
||||
detLog("---EVENT_BREAK---", share);
|
||||
|
||||
if (!share->curEvent.srcPaths.empty())
|
||||
{
|
||||
share->curEvent.evName = genEventName();
|
||||
share->recList.push_back(share->curEvent);
|
||||
|
||||
detLog("motion detected in " + to_string(share->curEvent.srcPaths.size()) + " file(s) in " + to_string(share->evMaxSecs) + " secs", share);
|
||||
detLog("all video clips queued for event generation under event name: " + share->curEvent.evName, share);
|
||||
}
|
||||
else
|
||||
{
|
||||
detLog("no motion detected in all files. none queued for event generation.", share);
|
||||
}
|
||||
|
||||
share->curEvent.srcPaths.clear();
|
||||
share->curEvent.evName.clear();
|
||||
share->curEvent.thumbnail.release();
|
||||
|
||||
share->evInd = 0;
|
||||
share->maxScore = 0;
|
||||
}
|
||||
|
||||
ifstream fileIn(streamFile);
|
||||
string tsPath;
|
||||
Mat thumbnail;
|
||||
|
||||
for (string line; getline(fileIn, line); )
|
||||
{
|
||||
|
@ -46,40 +72,14 @@ void detectMoInStream(const string &streamFile, shared_t *share)
|
|||
}
|
||||
}
|
||||
|
||||
if (share->curEventName.empty())
|
||||
{
|
||||
share->curEventName = genTimeStr("%Y-%j-%H-%M");
|
||||
}
|
||||
|
||||
if (!tsPath.empty())
|
||||
{
|
||||
if (moDetect(tsPath, thumbnail, share))
|
||||
if (moDetect(tsPath, share))
|
||||
{
|
||||
if (share->recList.find(share->curEventName) != share->recList.end())
|
||||
{
|
||||
share->recList[share->curEventName].srcPaths.push_back(tsPath);
|
||||
|
||||
if (!thumbnail.empty())
|
||||
{
|
||||
share->recList[share->curEventName].thumbnail = thumbnail.clone();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pls_t event;
|
||||
|
||||
event.srcPaths.push_back(tsPath);
|
||||
|
||||
event.thumbnail = thumbnail.clone();
|
||||
event.evName = share->curEventName;
|
||||
|
||||
share->recList.insert(pair{event.evName, event});
|
||||
}
|
||||
share->curEvent.srcPaths.push_back(tsPath);
|
||||
|
||||
share->skipCmd = true;
|
||||
}
|
||||
|
||||
share->procTime += 2;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -103,28 +103,34 @@ bool imgDiff(const Mat &prev, const Mat &next, int &score, shared_t *share)
|
|||
return score >= share->imgThresh;
|
||||
}
|
||||
|
||||
bool moDetect(const string &buffFile, Mat &vidThumb, shared_t *share)
|
||||
bool moDetect(const string &buffFile, shared_t *share)
|
||||
{
|
||||
auto score = 0;
|
||||
auto mod = false;
|
||||
|
||||
detLog("stream_clip: " + buffFile, share);
|
||||
|
||||
VideoCapture capture(buffFile.c_str(), CAP_FFMPEG);
|
||||
VideoCapture capture;
|
||||
|
||||
if (!capture.open(buffFile.c_str(), CAP_FFMPEG))
|
||||
{
|
||||
usleep(500);
|
||||
|
||||
capture.open(buffFile.c_str(), CAP_FFMPEG);
|
||||
}
|
||||
|
||||
if (capture.isOpened())
|
||||
{
|
||||
Mat prev;
|
||||
Mat next;
|
||||
|
||||
detLog("capture open successful.", share);
|
||||
|
||||
while (capture.grab())
|
||||
for (auto gap = 0; capture.grab(); ++gap)
|
||||
{
|
||||
if (prev.empty())
|
||||
{
|
||||
capture.retrieve(prev);
|
||||
}
|
||||
else
|
||||
else if (gap == (share->frameGap - 1))
|
||||
{
|
||||
capture.retrieve(next);
|
||||
|
||||
|
@ -132,45 +138,76 @@ bool moDetect(const string &buffFile, Mat &vidThumb, shared_t *share)
|
|||
{
|
||||
if (imgDiff(prev, next, score, share))
|
||||
{
|
||||
if (score > share->maxScore)
|
||||
mod = true;
|
||||
|
||||
if (share->maxScore <= score)
|
||||
{
|
||||
share->maxScore = score;
|
||||
|
||||
resize(next, vidThumb, Size(720, 480), INTER_LINEAR);
|
||||
resize(next, share->curEvent.thumbnail, Size(720, 480), INTER_LINEAR);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
prev.release();
|
||||
prev = next.clone();
|
||||
gap = 0;
|
||||
|
||||
next.release();
|
||||
}
|
||||
|
||||
sleep(1);
|
||||
else
|
||||
{
|
||||
capture.grab();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
detLog("capture open failure, check debug output.", share);
|
||||
detLog("err: failed to open: " + buffFile + " after 500 msecs. giving up.", share);
|
||||
}
|
||||
|
||||
capture.release();
|
||||
|
||||
return score > 0;
|
||||
return mod;
|
||||
}
|
||||
|
||||
void wrOutVod(const pls_t &event, shared_t *share)
|
||||
bool wrOutVod(const evt_t &event, shared_t *share)
|
||||
{
|
||||
auto cnt = 0;
|
||||
auto concat = event.evName + ".tmp";
|
||||
|
||||
ofstream file(concat.c_str());
|
||||
|
||||
for (auto i = 0; i < event.srcPaths.size(); ++i)
|
||||
{
|
||||
file << "file '" << event.srcPaths[i] << "''" << endl;
|
||||
recLog("event_src: " + event.srcPaths[i], share);
|
||||
|
||||
if (exists(event.srcPaths[i]))
|
||||
{
|
||||
file << "file '" << event.srcPaths[i] << "''" << endl; cnt++;
|
||||
}
|
||||
}
|
||||
|
||||
file.close();
|
||||
|
||||
system(string("ffmpeg -f concat -safe 0 -i " + concat + " -c copy events/" + event.evName + ".mp4").c_str());
|
||||
remove(concat);
|
||||
if (cnt == 0)
|
||||
{
|
||||
recLog("err: none of the event hls clips exists, canceling write out.", share);
|
||||
|
||||
if (exists(concat)) remove(concat);
|
||||
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto ret = system(string("ffmpeg -f concat -safe 0 -i " + concat + " -c copy events/" + event.evName + ".mp4").c_str());
|
||||
|
||||
if (ret != 0)
|
||||
{
|
||||
recLog("err: ffmpeg concat failure, canceling write out.", share);
|
||||
}
|
||||
|
||||
if (exists(concat)) remove(concat);
|
||||
|
||||
return ret == 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,8 +17,8 @@
|
|||
#include "logger.h"
|
||||
|
||||
bool imgDiff(const Mat &prev, const Mat &next, int &score, shared_t *share);
|
||||
bool moDetect(const string &buffFile, Mat &vidThumb, shared_t *share);
|
||||
bool moDetect(const string &buffFile, shared_t *share);
|
||||
void detectMoInStream(const string &streamFile, shared_t *share);
|
||||
void wrOutVod(const pls_t &pls, shared_t *share);
|
||||
bool wrOutVod(const evt_t &pls, shared_t *share);
|
||||
|
||||
#endif // MO_DETECT_H
|
||||
|
|
Loading…
Reference in New Issue
Block a user