Compare commits
No commits in common. "f4ea944f97ccbb6df75256785c66745c637972ec" and "19872b3ff59fc69d647320a397f1b6024731c992" have entirely different histories.
f4ea944f97
...
19872b3ff5
17
README.md
17
README.md
|
@ -60,26 +60,15 @@ img_thresh = 80000
|
||||||
# before it is considered motion. any video clips found with frames
|
# before it is considered motion. any video clips found with frames
|
||||||
# exceeding this value will be copied from live footage to event footage.
|
# exceeding this value will be copied from live footage to event footage.
|
||||||
#
|
#
|
||||||
frame_gap = 10
|
|
||||||
# this is the amount of frames in between the comparison frames to check
|
|
||||||
# for pixel differences. the higher the value, the lower the cpu over
|
|
||||||
# head, however it does lower motion detection accuracy.
|
|
||||||
#
|
|
||||||
max_events = 40
|
max_events = 40
|
||||||
# this indicates the maximum amount of motion event video clips to keep
|
# this indicates the maximum amount of motion event video clips to keep
|
||||||
# before deleting the oldest clip.
|
# before deleting the oldest clip.
|
||||||
#
|
#
|
||||||
max_event_secs = 10
|
sch_sec = 60
|
||||||
# this is the maximum amount of secs of video footage that can be
|
# this is the amount of seconds to wait in between running post_cmd.
|
||||||
# recorded in a motion event.
|
|
||||||
#
|
|
||||||
post_secs = 60
|
|
||||||
# this is the amount of seconds to wait before running the command
|
|
||||||
# defined in post_cmd. the command will not run if motion was detected
|
|
||||||
# in the space before post_secs elapsed.
|
|
||||||
#
|
#
|
||||||
post_cmd = move_the_ptz_camera.py
|
post_cmd = move_the_ptz_camera.py
|
||||||
# this an optional command to run with post_secs. one great use for this
|
# this an optional command to run with sch_sec. one great use for this
|
||||||
# is to move a ptz camera to the next position of it's patrol pattern.
|
# is to move a ptz camera to the next position of it's patrol pattern.
|
||||||
# note: the call to this command will be delayed if motion was detected.
|
# note: the call to this command will be delayed if motion was detected.
|
||||||
#
|
#
|
||||||
|
|
|
@ -175,11 +175,6 @@ string genDstFile(const string &dirOut, const char *fmt, const string &ext)
|
||||||
return cleanDir(dirOut) + string("/") + genTimeStr(fmt) + ext;
|
return cleanDir(dirOut) + string("/") + genTimeStr(fmt) + ext;
|
||||||
}
|
}
|
||||||
|
|
||||||
string genEventName(int score)
|
|
||||||
{
|
|
||||||
return genTimeStr(string("%Y-%j-%H-%M-%S--" + to_string(score)).c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
void rdLine(const string ¶m, const string &line, string *value)
|
void rdLine(const string ¶m, const string &line, string *value)
|
||||||
{
|
{
|
||||||
if (line.rfind(param.c_str(), 0) == 0)
|
if (line.rfind(param.c_str(), 0) == 0)
|
||||||
|
@ -222,12 +217,10 @@ bool rdConf(const string &filePath, shared_t *share)
|
||||||
rdLine("web_text = ", line, &share->webTxt);
|
rdLine("web_text = ", line, &share->webTxt);
|
||||||
rdLine("web_bg = ", line, &share->webBg);
|
rdLine("web_bg = ", line, &share->webBg);
|
||||||
rdLine("web_font = ", line, &share->webFont);
|
rdLine("web_font = ", line, &share->webFont);
|
||||||
rdLine("max_event_secs = ", line, &share->evMaxSecs);
|
rdLine("sch_sec = ", line, &share->schSec);
|
||||||
rdLine("post_secs = ", line, &share->postSecs);
|
|
||||||
rdLine("post_cmd = ", line, &share->postCmd);
|
rdLine("post_cmd = ", line, &share->postCmd);
|
||||||
rdLine("pix_thresh = ", line, &share->pixThresh);
|
rdLine("pix_thresh = ", line, &share->pixThresh);
|
||||||
rdLine("img_thresh = ", line, &share->imgThresh);
|
rdLine("img_thresh = ", line, &share->imgThresh);
|
||||||
rdLine("frame_gap = ", line, &share->frameGap);
|
|
||||||
rdLine("max_events = ", line, &share->maxEvents);
|
rdLine("max_events = ", line, &share->maxEvents);
|
||||||
rdLine("max_log_size = ", line, &share->maxLogSize);
|
rdLine("max_log_size = ", line, &share->maxLogSize);
|
||||||
}
|
}
|
||||||
|
@ -248,11 +241,9 @@ bool rdConf(shared_t *share)
|
||||||
share->pixThresh = 50;
|
share->pixThresh = 50;
|
||||||
share->imgThresh = 800;
|
share->imgThresh = 800;
|
||||||
share->maxEvents = 40;
|
share->maxEvents = 40;
|
||||||
share->maxLogSize = 100000;
|
share->maxLogSize = 50000;
|
||||||
share->skipCmd = false;
|
share->skipCmd = false;
|
||||||
share->postSecs = 60;
|
share->schSec = 60;
|
||||||
share->evMaxSecs = 10;
|
|
||||||
share->frameGap = 10;
|
|
||||||
share->webRoot = "/var/www/html";
|
share->webRoot = "/var/www/html";
|
||||||
share->webBg = "#485564";
|
share->webBg = "#485564";
|
||||||
share->webTxt = "#dee5ee";
|
share->webTxt = "#dee5ee";
|
||||||
|
@ -359,3 +350,8 @@ string genVidNameFromLive(const string &tsPath)
|
||||||
return string();
|
return string();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint64_t genEpoch()
|
||||||
|
{
|
||||||
|
return duration_cast<seconds>(system_clock::now().time_since_epoch()).count();
|
||||||
|
}
|
||||||
|
|
56
src/common.h
56
src/common.h
|
@ -34,54 +34,47 @@ using namespace std;
|
||||||
using namespace std::filesystem;
|
using namespace std::filesystem;
|
||||||
using namespace std::chrono;
|
using namespace std::chrono;
|
||||||
|
|
||||||
#define APP_VER "2.2"
|
#define APP_VER "2.0"
|
||||||
#define APP_NAME "Motion Watch"
|
#define APP_NAME "Motion Watch"
|
||||||
#define REC_LOG_NAME "rec_log_lines.html"
|
#define REC_LOG_NAME "rec_log_lines.html"
|
||||||
#define DET_LOG_NAME "det_log_lines.html"
|
#define DET_LOG_NAME "det_log_lines.html"
|
||||||
#define UPK_LOG_NAME "upk_log_lines.html"
|
#define UPK_LOG_NAME "upk_log_lines.html"
|
||||||
|
|
||||||
struct evt_t
|
struct pls_t
|
||||||
{
|
{
|
||||||
string evName;
|
string evName;
|
||||||
vector<string> srcPaths;
|
vector<string> srcPaths;
|
||||||
|
uint64_t createTime;
|
||||||
Mat thumbnail;
|
Mat thumbnail;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct shared_t
|
struct shared_t
|
||||||
{
|
{
|
||||||
vector<evt_t> recList;
|
map<string, pls_t> recList;
|
||||||
string conf;
|
string conf;
|
||||||
string recLog;
|
string recLog;
|
||||||
string detLog;
|
string detLog;
|
||||||
string upkLog;
|
string upkLog;
|
||||||
string recordUrl;
|
string recordUrl;
|
||||||
string outDir;
|
string outDir;
|
||||||
string postCmd;
|
string postCmd;
|
||||||
string camName;
|
string camName;
|
||||||
string webBg;
|
string webBg;
|
||||||
string webTxt;
|
string webTxt;
|
||||||
string webFont;
|
string webFont;
|
||||||
string webRoot;
|
string webRoot;
|
||||||
evt_t curEvent;
|
bool skipCmd;
|
||||||
bool skipCmd;
|
int procTime;
|
||||||
int frameGap;
|
int schSec;
|
||||||
int evMaxSecs;
|
int pixThresh;
|
||||||
int postSecs;
|
int imgThresh;
|
||||||
int maxScore;
|
int maxEvents;
|
||||||
int procCnt;
|
int maxLogSize;
|
||||||
int hlsCnt;
|
int retCode;
|
||||||
int pixThresh;
|
|
||||||
int imgThresh;
|
|
||||||
int maxEvents;
|
|
||||||
int maxLogSize;
|
|
||||||
int retCode;
|
|
||||||
int postInd;
|
|
||||||
int evInd;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
string genVidNameFromLive(const string &tsPath);
|
string genVidNameFromLive(const string &tsPath);
|
||||||
string genEventPath(const string &tsPath);
|
string genEventPath(const string &tsPath);
|
||||||
string genEventName(int score);
|
|
||||||
string genDstFile(const string &dirOut, const char *fmt, const string &ext);
|
string genDstFile(const string &dirOut, const char *fmt, const string &ext);
|
||||||
string genTimeStr(const char *fmt);
|
string genTimeStr(const char *fmt);
|
||||||
string cleanDir(const string &path);
|
string cleanDir(const string &path);
|
||||||
|
@ -97,5 +90,6 @@ void enforceMaxEvents(shared_t *share);
|
||||||
bool rdConf(shared_t *share);
|
bool rdConf(shared_t *share);
|
||||||
vector<string> lsFilesInDir(const string &path, const string &ext = string());
|
vector<string> lsFilesInDir(const string &path, const string &ext = string());
|
||||||
vector<string> lsDirsInDir(const string &path);
|
vector<string> lsDirsInDir(const string &path);
|
||||||
|
uint64_t genEpoch();
|
||||||
|
|
||||||
#endif // COMMON_H
|
#endif // COMMON_H
|
||||||
|
|
76
src/main.cpp
76
src/main.cpp
|
@ -14,17 +14,6 @@
|
||||||
#include "logger.h"
|
#include "logger.h"
|
||||||
#include "web.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)
|
void detectMo(shared_t *share)
|
||||||
{
|
{
|
||||||
while (share->retCode == 0)
|
while (share->retCode == 0)
|
||||||
|
@ -38,31 +27,40 @@ void eventLoop(shared_t *share)
|
||||||
{
|
{
|
||||||
while (share->retCode == 0)
|
while (share->retCode == 0)
|
||||||
{
|
{
|
||||||
if (!share->recList.empty())
|
while (!share->recList.empty())
|
||||||
{
|
{
|
||||||
auto event = share->recList[0];
|
auto it = share->recList.begin();
|
||||||
|
auto evName = it->first;
|
||||||
|
auto event = it->second;
|
||||||
|
auto timeDiff = genEpoch() - event.createTime;
|
||||||
|
|
||||||
try
|
// wait at least 62 seconds before processing the event in
|
||||||
|
// queue.
|
||||||
|
if ((timeDiff > 0) && (timeDiff > 62))
|
||||||
{
|
{
|
||||||
recLog("attempting write out of event: " + event.evName, share);
|
try
|
||||||
|
|
||||||
createDirTree("events");
|
|
||||||
|
|
||||||
if (wrOutVod(event, share))
|
|
||||||
{
|
{
|
||||||
genHTMLvod(event.evName);
|
createDirTree("events");
|
||||||
imwrite(string("events/" + event.evName + ".jpg").c_str(), event.thumbnail);
|
wrOutVod(event, share);
|
||||||
|
genHTMLvod(evName);
|
||||||
|
|
||||||
|
if (!exists("events/" + evName + ".jpg"))
|
||||||
|
{
|
||||||
|
imwrite(string("events/" + evName + ".jpg").c_str(), event.thumbnail);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
catch (filesystem_error &ex)
|
||||||
catch (filesystem_error &ex)
|
{
|
||||||
{
|
recLog(string("err: ") + ex.what(), share);
|
||||||
recLog(string("err: ") + ex.what(), share);
|
}
|
||||||
|
|
||||||
|
share->recList.erase(it);
|
||||||
}
|
}
|
||||||
|
|
||||||
share->recList.erase(share->recList.begin());
|
sleep(5);
|
||||||
}
|
}
|
||||||
|
|
||||||
sleep(10);
|
sleep(5);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -108,15 +106,7 @@ void upkeep(shared_t *share)
|
||||||
upkLog("skipping update of the webroot page, it is busy.", share);
|
upkLog("skipping update of the webroot page, it is busy.", share);
|
||||||
}
|
}
|
||||||
|
|
||||||
sleep(10);
|
sleep(60);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void rmLive()
|
|
||||||
{
|
|
||||||
if (exists("live"))
|
|
||||||
{
|
|
||||||
remove_all("live");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,6 +114,11 @@ void recLoop(shared_t *share)
|
||||||
{
|
{
|
||||||
while (share->retCode == 0)
|
while (share->retCode == 0)
|
||||||
{
|
{
|
||||||
|
if (exists("live"))
|
||||||
|
{
|
||||||
|
remove_all("live");
|
||||||
|
}
|
||||||
|
|
||||||
auto cmd = "ffmpeg -hide_banner -rtsp_transport tcp -timeout 3000000 -i " +
|
auto cmd = "ffmpeg -hide_banner -rtsp_transport tcp -timeout 3000000 -i " +
|
||||||
share->recordUrl +
|
share->recordUrl +
|
||||||
" -strftime 1" +
|
" -strftime 1" +
|
||||||
|
@ -131,11 +126,10 @@ void recLoop(shared_t *share)
|
||||||
" -hls_segment_filename 'live/%Y-%j-%H-%M-%S.ts'" +
|
" -hls_segment_filename 'live/%Y-%j-%H-%M-%S.ts'" +
|
||||||
" -hls_flags delete_segments" +
|
" -hls_flags delete_segments" +
|
||||||
" -y -vcodec copy" +
|
" -y -vcodec copy" +
|
||||||
" -f hls -hls_time 2 -hls_list_size 1000" +
|
" -f hls -hls_time 10 -hls_list_size 400" +
|
||||||
" stream.m3u8";
|
" stream.m3u8";
|
||||||
|
|
||||||
recLog("ffmpeg_run: " + cmd, share);
|
recLog("ffmpeg_run: " + cmd, share);
|
||||||
rmLive();
|
|
||||||
|
|
||||||
auto retCode = system(cmd.c_str());
|
auto retCode = system(cmd.c_str());
|
||||||
|
|
||||||
|
@ -175,9 +169,7 @@ int main(int argc, char** argv)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
sharedRes.retCode = 0;
|
sharedRes.retCode = 0;
|
||||||
sharedRes.maxScore = 0;
|
sharedRes.procTime = 0;
|
||||||
sharedRes.postInd = 0;
|
|
||||||
sharedRes.evInd = 0;
|
|
||||||
sharedRes.skipCmd = false;
|
sharedRes.skipCmd = false;
|
||||||
|
|
||||||
rdConf(&sharedRes);
|
rdConf(&sharedRes);
|
||||||
|
@ -186,13 +178,11 @@ int main(int argc, char** argv)
|
||||||
auto thr2 = thread(upkeep, &sharedRes);
|
auto thr2 = thread(upkeep, &sharedRes);
|
||||||
auto thr3 = thread(detectMo, &sharedRes);
|
auto thr3 = thread(detectMo, &sharedRes);
|
||||||
auto thr4 = thread(eventLoop, &sharedRes);
|
auto thr4 = thread(eventLoop, &sharedRes);
|
||||||
auto thr5 = thread(timer, &sharedRes);
|
|
||||||
|
|
||||||
thr1.join();
|
thr1.join();
|
||||||
thr2.join();
|
thr2.join();
|
||||||
thr3.join();
|
thr3.join();
|
||||||
thr4.join();
|
thr4.join();
|
||||||
thr5.join();
|
|
||||||
|
|
||||||
return sharedRes.retCode;
|
return sharedRes.retCode;
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,55 +14,25 @@
|
||||||
|
|
||||||
void detectMoInStream(const string &streamFile, shared_t *share)
|
void detectMoInStream(const string &streamFile, shared_t *share)
|
||||||
{
|
{
|
||||||
if (share->postInd >= share->postSecs)
|
if (share->procTime >= share->schSec)
|
||||||
{
|
{
|
||||||
if (!share->postCmd.empty())
|
if (!share->skipCmd)
|
||||||
{
|
{
|
||||||
detLog("---POST_BREAK---", share);
|
detLog("no motion detected, running post command: " + share->postCmd, share);
|
||||||
|
system(share->postCmd.c_str());
|
||||||
if (!share->skipCmd)
|
|
||||||
{
|
|
||||||
detLog("no motion detected, running post command: " + share->postCmd, share);
|
|
||||||
system(share->postCmd.c_str());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
share->skipCmd = false;
|
|
||||||
|
|
||||||
detLog("motion detected, skipping the post command.", share);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
share->postInd = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (share->evInd >= share->evMaxSecs)
|
|
||||||
{
|
|
||||||
detLog("---EVENT_BREAK---", share);
|
|
||||||
|
|
||||||
if (!share->curEvent.srcPaths.empty())
|
|
||||||
{
|
|
||||||
share->curEvent.evName = genEventName(share->maxScore);
|
|
||||||
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
|
else
|
||||||
{
|
{
|
||||||
detLog("no motion detected in all files. none queued for event generation.", share);
|
share->skipCmd = false;
|
||||||
|
share->procTime = 0;
|
||||||
|
|
||||||
|
detLog("motion detected, skipping the post command.", share);
|
||||||
}
|
}
|
||||||
|
|
||||||
share->curEvent.srcPaths.clear();
|
|
||||||
share->curEvent.evName.clear();
|
|
||||||
share->curEvent.thumbnail.release();
|
|
||||||
|
|
||||||
share->evInd = 0;
|
|
||||||
share->maxScore = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ifstream fileIn(streamFile);
|
ifstream fileIn(streamFile);
|
||||||
string tsPath;
|
string tsPath;
|
||||||
|
Mat thumbnail;
|
||||||
|
|
||||||
for (string line; getline(fileIn, line); )
|
for (string line; getline(fileIn, line); )
|
||||||
{
|
{
|
||||||
|
@ -74,12 +44,31 @@ void detectMoInStream(const string &streamFile, shared_t *share)
|
||||||
|
|
||||||
if (!tsPath.empty())
|
if (!tsPath.empty())
|
||||||
{
|
{
|
||||||
if (moDetect(tsPath, share))
|
if (moDetect(tsPath, thumbnail, share))
|
||||||
{
|
{
|
||||||
share->curEvent.srcPaths.push_back(tsPath);
|
auto eventName = genTimeStr("%Y-%j-%H-%M");
|
||||||
|
|
||||||
|
if (share->recList.find(eventName) != share->recList.end())
|
||||||
|
{
|
||||||
|
share->recList[eventName].srcPaths.push_back(tsPath);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pls_t event;
|
||||||
|
|
||||||
|
event.srcPaths.push_back(tsPath);
|
||||||
|
|
||||||
|
event.createTime = genEpoch();
|
||||||
|
event.thumbnail = thumbnail.clone();
|
||||||
|
event.evName = eventName;
|
||||||
|
|
||||||
|
share->recList.insert(pair{eventName, event});
|
||||||
|
}
|
||||||
|
|
||||||
share->skipCmd = true;
|
share->skipCmd = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
share->procTime += 10;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,43 +87,34 @@ bool imgDiff(const Mat &prev, const Mat &next, int &score, shared_t *share)
|
||||||
|
|
||||||
score = countNonZero(diff);
|
score = countNonZero(diff);
|
||||||
|
|
||||||
detLog("diff_score: " + to_string(score) + " thresh: " + to_string(share->imgThresh), share);
|
detLog("diff_score: " + to_string(score) + " tresh: " + to_string(share->imgThresh), share);
|
||||||
|
|
||||||
return score >= share->imgThresh;
|
return score >= share->imgThresh;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool moDetect(const string &buffFile, shared_t *share)
|
bool moDetect(const string &buffFile, Mat &vidThumb, shared_t *share)
|
||||||
{
|
{
|
||||||
auto score = 0;
|
auto maxScore = 0;
|
||||||
auto mod = false;
|
auto score = 0;
|
||||||
|
|
||||||
detLog("stream_clip: " + buffFile, share);
|
detLog("stream_clip: " + buffFile, share);
|
||||||
|
|
||||||
VideoCapture capture;
|
VideoCapture capture(buffFile.c_str(), CAP_FFMPEG);
|
||||||
|
|
||||||
if (!capture.open(buffFile.c_str(), CAP_FFMPEG))
|
|
||||||
{
|
|
||||||
usleep(500);
|
|
||||||
|
|
||||||
capture.open(buffFile.c_str(), CAP_FFMPEG);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (capture.isOpened())
|
if (capture.isOpened())
|
||||||
{
|
{
|
||||||
Mat prev;
|
Mat prev;
|
||||||
Mat next;
|
Mat next;
|
||||||
|
|
||||||
int fps = capture.get(cv::CAP_PROP_FPS);
|
detLog("capture open successful.", share);
|
||||||
|
|
||||||
for (auto gap = 0, frm = fps; capture.grab(); ++gap, ++frm)
|
while (capture.grab())
|
||||||
{
|
{
|
||||||
if (frm == fps) sleep(1); frm = 1;
|
|
||||||
|
|
||||||
if (prev.empty())
|
if (prev.empty())
|
||||||
{
|
{
|
||||||
capture.retrieve(prev);
|
capture.retrieve(prev);
|
||||||
}
|
}
|
||||||
else if (gap == (share->frameGap - 1))
|
else
|
||||||
{
|
{
|
||||||
capture.retrieve(next);
|
capture.retrieve(next);
|
||||||
|
|
||||||
|
@ -142,76 +122,45 @@ bool moDetect(const string &buffFile, shared_t *share)
|
||||||
{
|
{
|
||||||
if (imgDiff(prev, next, score, share))
|
if (imgDiff(prev, next, score, share))
|
||||||
{
|
{
|
||||||
mod = true;
|
if (score > maxScore)
|
||||||
|
|
||||||
if (share->maxScore <= score)
|
|
||||||
{
|
{
|
||||||
share->maxScore = score;
|
maxScore = score;
|
||||||
|
|
||||||
resize(next, share->curEvent.thumbnail, Size(720, 480), INTER_LINEAR);
|
resize(next, vidThumb, Size(720, 480), INTER_LINEAR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
prev = next.clone();
|
prev.release();
|
||||||
gap = 0;
|
|
||||||
|
|
||||||
next.release();
|
next.release();
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
sleep(1);
|
||||||
capture.grab();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
detLog("err: failed to open: " + buffFile + " after 500 msecs. giving up.", share);
|
detLog("capture open failure, check debug output.", share);
|
||||||
}
|
}
|
||||||
|
|
||||||
capture.release();
|
capture.release();
|
||||||
|
|
||||||
return mod;
|
return maxScore > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool wrOutVod(const evt_t &event, shared_t *share)
|
void wrOutVod(const pls_t &event, shared_t *share)
|
||||||
{
|
{
|
||||||
auto cnt = 0;
|
|
||||||
auto concat = event.evName + ".tmp";
|
auto concat = event.evName + ".tmp";
|
||||||
|
|
||||||
ofstream file(concat.c_str());
|
ofstream file(concat.c_str());
|
||||||
|
|
||||||
for (auto i = 0; i < event.srcPaths.size(); ++i)
|
for (auto i = 0; i < event.srcPaths.size(); ++i)
|
||||||
{
|
{
|
||||||
recLog("event_src: " + event.srcPaths[i], share);
|
file << "file '" << event.srcPaths[i] << "''" << endl;
|
||||||
|
|
||||||
if (exists(event.srcPaths[i]))
|
|
||||||
{
|
|
||||||
file << "file '" << event.srcPaths[i] << "''" << endl; cnt++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
file.close();
|
file.close();
|
||||||
|
|
||||||
if (cnt == 0)
|
system(string("ffmpeg -f concat -safe 0 -i " + concat + " -c copy events/" + event.evName + ".mp4").c_str());
|
||||||
{
|
remove(concat);
|
||||||
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"
|
#include "logger.h"
|
||||||
|
|
||||||
bool imgDiff(const Mat &prev, const Mat &next, int &score, shared_t *share);
|
bool imgDiff(const Mat &prev, const Mat &next, int &score, shared_t *share);
|
||||||
bool moDetect(const string &buffFile, shared_t *share);
|
bool moDetect(const string &buffFile, Mat &vidThumb, shared_t *share);
|
||||||
void detectMoInStream(const string &streamFile, shared_t *share);
|
void detectMoInStream(const string &streamFile, shared_t *share);
|
||||||
bool wrOutVod(const evt_t &pls, shared_t *share);
|
void wrOutVod(const pls_t &pls, shared_t *share);
|
||||||
|
|
||||||
#endif // MO_DETECT_H
|
#endif // MO_DETECT_H
|
||||||
|
|
Loading…
Reference in New Issue
Block a user