v1.5.t16
The app is still failing with intermittent moov atom failures on trying to open the video clips with opencv VideoCapture. I suspect it is trying to open the files while ffmpeg is not done finalizing them. Reformed the detection loop to spawn dedicated motion detection threads for each video clip and only when ffmpeg confirmed finished.
This commit is contained in:
parent
ad4a6357b4
commit
b470915276
|
@ -202,7 +202,6 @@ bool rdConf(shared_t *share)
|
||||||
share->buffDir = "/tmp";
|
share->buffDir = "/tmp";
|
||||||
share->vidExt = "mp4";
|
share->vidExt = "mp4";
|
||||||
share->vidCodec = "copy";
|
share->vidCodec = "copy";
|
||||||
share->recLoopWait = false;
|
|
||||||
share->skipCmd = false;
|
share->skipCmd = false;
|
||||||
share->webBg = "#485564";
|
share->webBg = "#485564";
|
||||||
share->webTxt = "#dee5ee";
|
share->webTxt = "#dee5ee";
|
||||||
|
@ -284,3 +283,13 @@ string parseForParam(const string &arg, int argc, char** argv, bool argOnly)
|
||||||
|
|
||||||
return string();
|
return string();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void waitForDetThreads(shared_t *share)
|
||||||
|
{
|
||||||
|
for (auto &&thr : share->detThreads)
|
||||||
|
{
|
||||||
|
thr.join();
|
||||||
|
}
|
||||||
|
|
||||||
|
share->detThreads.clear();
|
||||||
|
}
|
||||||
|
|
59
src/common.h
59
src/common.h
|
@ -35,40 +35,38 @@ using namespace cv;
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace std::filesystem;
|
using namespace std::filesystem;
|
||||||
|
|
||||||
#define APP_VER "1.5.t15"
|
#define APP_VER "1.5.t16"
|
||||||
#define APP_NAME "Motion Watch"
|
#define APP_NAME "Motion Watch"
|
||||||
|
|
||||||
struct shared_t
|
struct shared_t
|
||||||
{
|
{
|
||||||
|
vector<thread> detThreads;
|
||||||
ofstream recLogFile;
|
ofstream recLogFile;
|
||||||
ofstream detLogFile;
|
ofstream detLogFile;
|
||||||
string recLogPath;
|
string recLogPath;
|
||||||
string detLogPath;
|
string detLogPath;
|
||||||
string recordUrl;
|
string recordUrl;
|
||||||
string outDir;
|
string outDir;
|
||||||
string postCmd;
|
string postCmd;
|
||||||
string conf;
|
string conf;
|
||||||
string buffDir;
|
string buffDir;
|
||||||
string vidExt;
|
string vidExt;
|
||||||
string vidCodec;
|
string vidCodec;
|
||||||
string camName;
|
string camName;
|
||||||
string webBg;
|
string webBg;
|
||||||
string webTxt;
|
string webTxt;
|
||||||
string webFont;
|
string webFont;
|
||||||
string webRoot;
|
string webRoot;
|
||||||
bool init;
|
bool init;
|
||||||
bool recLoopWait;
|
bool skipCmd;
|
||||||
bool logRun;
|
int frameGap;
|
||||||
bool skipCmd;
|
int pixThresh;
|
||||||
int frameGap;
|
int imgThresh;
|
||||||
int pixThresh;
|
int secs;
|
||||||
int imgThresh;
|
int maxDays;
|
||||||
int secs;
|
int maxClips;
|
||||||
int maxDays;
|
int maxLogSize;
|
||||||
int maxClips;
|
int retCode;
|
||||||
int maxLogSize;
|
|
||||||
int retCode;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
string genDstFile(const string &dirOut, const char *fmt, const string &ext);
|
string genDstFile(const string &dirOut, const char *fmt, const string &ext);
|
||||||
|
@ -82,6 +80,7 @@ void enforceMaxClips(const string &dirPath, shared_t *share);
|
||||||
void rdLine(const string ¶m, const string &line, string *value);
|
void rdLine(const string ¶m, const string &line, string *value);
|
||||||
void rdLine(const string ¶m, const string &line, int *value);
|
void rdLine(const string ¶m, const string &line, int *value);
|
||||||
void statOut(shared_t *share);
|
void statOut(shared_t *share);
|
||||||
|
void waitForDetThreads(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);
|
||||||
|
|
101
src/main.cpp
101
src/main.cpp
|
@ -13,57 +13,24 @@
|
||||||
#include "mo_detect.h"
|
#include "mo_detect.h"
|
||||||
#include "logger.h"
|
#include "logger.h"
|
||||||
|
|
||||||
void detectLoop(shared_t *share)
|
void detectMoInFile(const string &bufPath, shared_t *share)
|
||||||
{
|
{
|
||||||
detLog("detect_loop() -- start", share);
|
detLog("detect_mo_in_file() -- start", share);
|
||||||
|
|
||||||
vector<string> bufFiles;
|
Mat thumbNail;
|
||||||
auto waitingForFiles = 0;
|
|
||||||
|
|
||||||
do
|
if (moDetect(bufPath, thumbNail, share))
|
||||||
{
|
{
|
||||||
bufFiles = lsFilesInDir(share->buffDir, "." + share->vidExt);
|
share->skipCmd = true;
|
||||||
|
|
||||||
// this loop will not process the last buffile while recLoop is still actively
|
wrOut(bufPath, thumbNail, share);
|
||||||
// pulling footage from ffmpeg. it is assumed the last file is not finished.
|
}
|
||||||
// share->recLoopWait is used to detect if the recloop is still pulling. if not
|
else if (exists(bufPath))
|
||||||
// then the last file is finally processed.
|
{
|
||||||
|
remove(bufPath);
|
||||||
if ((bufFiles.size() >= 2) || (share->recLoopWait && !bufFiles.empty()))
|
|
||||||
{
|
|
||||||
auto fullPath = cleanDir(share->buffDir) + "/" + bufFiles[0];
|
|
||||||
Mat thumbNail;
|
|
||||||
|
|
||||||
if (moDetect(fullPath, thumbNail, share))
|
|
||||||
{
|
|
||||||
share->skipCmd = true;
|
|
||||||
|
|
||||||
wrOut(fullPath, thumbNail, share);
|
|
||||||
}
|
|
||||||
else if (exists(fullPath))
|
|
||||||
{
|
|
||||||
remove(fullPath);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (waitingForFiles >= share->secs)
|
|
||||||
{
|
|
||||||
detLog("timed out waiting for buff files from ffmpeg, did it fail?", share);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
detLog(to_string(bufFiles.size()) + " buff file(s) found, waiting for more.", share);
|
|
||||||
}
|
|
||||||
|
|
||||||
sleep(5); waitingForFiles += 5;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
while (!share->recLoopWait || !bufFiles.empty());
|
|
||||||
|
|
||||||
detLog("detect_loop() -- finished", share);
|
detLog("detect_mo_in_file() -- finished", share);
|
||||||
}
|
}
|
||||||
|
|
||||||
void recLoop(shared_t *share)
|
void recLoop(shared_t *share)
|
||||||
|
@ -99,29 +66,39 @@ void recLoop(shared_t *share)
|
||||||
|
|
||||||
recLog("camera specific webroot page updated: " + share->outDir + "/index.html", share);
|
recLog("camera specific webroot page updated: " + share->outDir + "/index.html", share);
|
||||||
|
|
||||||
auto bufPath = cleanDir(share->buffDir) + "/%03d." + share->vidExt;
|
for (auto i = 0; i < share->secs; i += 10)
|
||||||
auto secs = to_string(share->secs);
|
{
|
||||||
auto limSecs = to_string(share->secs + 3);
|
auto bufPath = cleanDir(share->buffDir) + "/" + to_string(i) + "." + share->vidExt;
|
||||||
auto cmd = "timeout -k 1 " + limSecs + " ffmpeg -hide_banner -i " + share->recordUrl + " -y -vcodec " + share->vidCodec + " -movflags faststart -map 0 -segment_time 00:00:10 -f segment -t " + secs + " " + bufPath;
|
auto cmd = "ffmpeg -hide_banner -i " + share->recordUrl + " -y vcodec " + share->vidCodec + " -movflags faststart -t 10 " + bufPath;
|
||||||
|
|
||||||
thread th2(detectLoop, share);
|
recLog("ffmpeg_run: " + cmd, share);
|
||||||
|
|
||||||
recLog("detect_loop() -- started in a seperate thread.", share);
|
auto retCode = system(cmd.c_str());
|
||||||
recLog("ffmpeg_run: " + cmd, share);
|
|
||||||
|
|
||||||
auto retCode = system(cmd.c_str());
|
recLog("ffmpeg_retcode: " + to_string(retCode), share);
|
||||||
|
|
||||||
recLog("ffmpeg_retcode: " + to_string(retCode), share);
|
if (retCode == 0)
|
||||||
|
{
|
||||||
|
recLog("detect_mo_in_file() -- started in a seperate thread.", share);
|
||||||
|
|
||||||
share->recLoopWait = true;
|
share->detThreads.push_back(thread(detectMoInFile, bufPath, share));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
recLog("ffmpeg returned non zero, indicating failure. please check stderr output.", share);
|
||||||
|
|
||||||
th2.join();
|
if (exists(bufPath))
|
||||||
|
{
|
||||||
|
remove(bufPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
recLog("detect_loop() -- thread finished.", share);
|
waitForDetThreads(share);
|
||||||
|
|
||||||
if (!share->skipCmd)
|
if (!share->skipCmd)
|
||||||
{
|
{
|
||||||
recLog("motion not detected by the detection loop.", share);
|
recLog("no motion detected", share);
|
||||||
|
|
||||||
if (share->postCmd.empty())
|
if (share->postCmd.empty())
|
||||||
{
|
{
|
||||||
|
@ -135,7 +112,7 @@ void recLoop(shared_t *share)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
recLog("motion detected by the detection loop, skipping the post command.", share);
|
recLog("motion detected, skipping the post command.", share);
|
||||||
}
|
}
|
||||||
|
|
||||||
recLog("rec_loop() -- finished", share);
|
recLog("rec_loop() -- finished", share);
|
||||||
|
@ -171,11 +148,9 @@ int main(int argc, char** argv)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
sharedRes.retCode = 0;
|
sharedRes.retCode = 0;
|
||||||
sharedRes.recLoopWait = false;
|
sharedRes.skipCmd = false;
|
||||||
sharedRes.skipCmd = false;
|
sharedRes.init = true;
|
||||||
sharedRes.init = true;
|
|
||||||
sharedRes.logRun = true;
|
|
||||||
|
|
||||||
recLoop(&sharedRes);
|
recLoop(&sharedRes);
|
||||||
|
|
||||||
|
|
|
@ -123,7 +123,7 @@ bool moDetect(const string &buffFile, Mat &vidThumb, shared_t *share)
|
||||||
|
|
||||||
if (imgDiff(prev, next, share))
|
if (imgDiff(prev, next, share))
|
||||||
{
|
{
|
||||||
resize(next, vidThumb, Size(1280, 720), INTER_LINEAR);
|
resize(next, vidThumb, Size(720, 480), INTER_LINEAR);
|
||||||
|
|
||||||
mod = true; break;
|
mod = true; break;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user