From b47091527634e0b71e322ba1ee5e9248282838f8 Mon Sep 17 00:00:00 2001 From: Maurice ONeal Date: Wed, 21 Dec 2022 20:30:37 -0500 Subject: [PATCH] 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. --- src/common.cpp | 11 ++++- src/common.h | 59 +++++++++++++-------------- src/main.cpp | 101 +++++++++++++++++----------------------------- src/mo_detect.cpp | 2 +- 4 files changed, 78 insertions(+), 95 deletions(-) diff --git a/src/common.cpp b/src/common.cpp index a555219..654e6ff 100644 --- a/src/common.cpp +++ b/src/common.cpp @@ -202,7 +202,6 @@ bool rdConf(shared_t *share) share->buffDir = "/tmp"; share->vidExt = "mp4"; share->vidCodec = "copy"; - share->recLoopWait = false; share->skipCmd = false; share->webBg = "#485564"; share->webTxt = "#dee5ee"; @@ -284,3 +283,13 @@ string parseForParam(const string &arg, int argc, char** argv, bool argOnly) return string(); } + +void waitForDetThreads(shared_t *share) +{ + for (auto &&thr : share->detThreads) + { + thr.join(); + } + + share->detThreads.clear(); +} diff --git a/src/common.h b/src/common.h index b347b3a..95f22c7 100644 --- a/src/common.h +++ b/src/common.h @@ -35,40 +35,38 @@ using namespace cv; using namespace std; using namespace std::filesystem; -#define APP_VER "1.5.t15" +#define APP_VER "1.5.t16" #define APP_NAME "Motion Watch" struct shared_t { - - ofstream recLogFile; - ofstream detLogFile; - string recLogPath; - string detLogPath; - string recordUrl; - string outDir; - string postCmd; - string conf; - string buffDir; - string vidExt; - string vidCodec; - string camName; - string webBg; - string webTxt; - string webFont; - string webRoot; - bool init; - bool recLoopWait; - bool logRun; - bool skipCmd; - int frameGap; - int pixThresh; - int imgThresh; - int secs; - int maxDays; - int maxClips; - int maxLogSize; - int retCode; + vector detThreads; + ofstream recLogFile; + ofstream detLogFile; + string recLogPath; + string detLogPath; + string recordUrl; + string outDir; + string postCmd; + string conf; + string buffDir; + string vidExt; + string vidCodec; + string camName; + string webBg; + string webTxt; + string webFont; + string webRoot; + bool init; + bool skipCmd; + int frameGap; + int pixThresh; + int imgThresh; + int secs; + int maxDays; + int maxClips; + int maxLogSize; + int retCode; }; 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, int *value); void statOut(shared_t *share); +void waitForDetThreads(shared_t *share); bool rdConf(shared_t *share); vector lsFilesInDir(const string &path, const string &ext = string()); vector lsDirsInDir(const string &path); diff --git a/src/main.cpp b/src/main.cpp index ea53f73..9cff0f6 100755 --- a/src/main.cpp +++ b/src/main.cpp @@ -13,57 +13,24 @@ #include "mo_detect.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 bufFiles; - auto waitingForFiles = 0; + Mat thumbNail; - 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 - // 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 - // then the last file is finally processed. - - 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; - } + wrOut(bufPath, thumbNail, share); + } + else if (exists(bufPath)) + { + remove(bufPath); } - while (!share->recLoopWait || !bufFiles.empty()); - detLog("detect_loop() -- finished", share); + detLog("detect_mo_in_file() -- finished", 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); - auto bufPath = cleanDir(share->buffDir) + "/%03d." + share->vidExt; - auto secs = to_string(share->secs); - auto limSecs = to_string(share->secs + 3); - 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; + for (auto i = 0; i < share->secs; i += 10) + { + auto bufPath = cleanDir(share->buffDir) + "/" + to_string(i) + "." + share->vidExt; + 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); - recLog("ffmpeg_run: " + cmd, share); + auto retCode = system(cmd.c_str()); - 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) { - recLog("motion not detected by the detection loop.", share); + recLog("no motion detected", share); if (share->postCmd.empty()) { @@ -135,7 +112,7 @@ void recLoop(shared_t *share) } 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); @@ -171,11 +148,9 @@ int main(int argc, char** argv) } else { - sharedRes.retCode = 0; - sharedRes.recLoopWait = false; - sharedRes.skipCmd = false; - sharedRes.init = true; - sharedRes.logRun = true; + sharedRes.retCode = 0; + sharedRes.skipCmd = false; + sharedRes.init = true; recLoop(&sharedRes); diff --git a/src/mo_detect.cpp b/src/mo_detect.cpp index 86b0b83..44201ee 100644 --- a/src/mo_detect.cpp +++ b/src/mo_detect.cpp @@ -123,7 +123,7 @@ bool moDetect(const string &buffFile, Mat &vidThumb, shared_t *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; }