diff --git a/README.md b/README.md index 3e5da20..5af4b67 100644 --- a/README.md +++ b/README.md @@ -40,7 +40,7 @@ detection_stream = rtsp://1.2.3.4:554/h264cif output_dir = /path/to/footage/directory # this is the output directory that will be used to store recorded footage # from the camera. the file naming convention uses date codes. it creates -# a subfolder for the date if it needs to and then stores the video file +# a sub-folder for the date if it needs to and then stores the video file # using the time. # diff_threshold = 210 @@ -68,14 +68,12 @@ pixel_size = 3 # this is the pixel size of the detected object or movement. this can # prevent false positives due small moves in grass/plants or insects. # -frames_post_motion = 60 -# this is the amount frames to capture after motion was detected. +secs_post_motion = 3 +# this is the minimum amount of seconds to capture after motion was +# detected. # -minimum_recording_frames = 90 -# this is the minimum amount of frames needed before video footage is -# recorded to storage. this prevents video files that are too small to -# be of any use and reduces clutter. warning: setting this value too -# high could cause the application to use too much memory. +recording_fps = 25 +# recording fps to use when recording footage to storage. # section_size = 100 # detection frames are read in y axis sections and then runs gray level diff --git a/src/main.cpp b/src/main.cpp index c248ba6..db619bf 100755 --- a/src/main.cpp +++ b/src/main.cpp @@ -27,13 +27,13 @@ struct shared_t string conf; bool wrRunning; bool ffRunning; - int motion; + bool motion; + int fps; int secs; int thrWithMotion; int thresh; int pixSize; int postMoIncr; - int minRecFrames; int sectionSize; int retCode; @@ -81,7 +81,7 @@ bool createDirTree(const string &full_path) void vidCap(shared_t *share) { - if (share->buff.size() >= share->minRecFrames) + if (!share->buff.empty()) { share->wrRunning = true; @@ -104,7 +104,7 @@ void vidCap(shared_t *share) VideoWriter writer; - writer.open(dstPath, codec, 30.0, share->buff[0].size(), true); + writer.open(dstPath, codec, (double) share->fps, share->buff[0].size(), true); if (!writer.isOpened()) { @@ -205,11 +205,11 @@ bool grayDiff(Mat imgA, Mat imgB, shared_t *share) return share->thrWithMotion != 0; } -void timer(shared_t *share) +void loopTimer(shared_t *share) { sleep(share->secs); - if (share->motion == 0) + if (!share->motion) { share->ffRunning = false; } @@ -220,6 +220,13 @@ void timer(shared_t *share) } } +void motionTimer(shared_t *share) +{ + sleep(share->postMoIncr); + + share->motion = false; +} + Mat toGray(const Mat &src) { Mat ret; @@ -238,11 +245,11 @@ void moDetect(shared_t *share) while (share->ffRunning) { - if (share->motion == 0) dCap >> dFrame; + if (!share->motion) dCap >> dFrame; rCap >> rFrame; - if (dFrame.empty() && (share->motion == 0)) + if (dFrame.empty() && (!share->motion)) { // broken frames returned from the cameras i've tested this with would cause // the entire capture connection to drop, hence why this bit of code is here @@ -254,11 +261,9 @@ void moDetect(shared_t *share) { rCap.open(share->recordUrl, CAP_FFMPEG); } - else if (share->motion > 0) + else if (share->motion) { share->buff.push_back(rFrame.clone()); - - share->motion -= 1; } else if (dPrev.empty() || rPrev.empty()) { @@ -270,7 +275,9 @@ void moDetect(shared_t *share) share->buff.push_back(rPrev); share->buff.push_back(rFrame.clone()); - share->motion += share->postMoIncr; + share->motion = true; + + thread(motionTimer, share); rPrev.release(); dPrev.release(); @@ -303,7 +310,7 @@ string parseForParam(const string &arg, int argc, char** argv, bool argOnly) } else { - return string("true") + return string("true"); } } } @@ -311,19 +318,28 @@ string parseForParam(const string &arg, int argc, char** argv, bool argOnly) return string(); } +void rdLine(const string ¶m, const string &line, string *value) +{ + if (line.rfind(param.c_str(), 0) == 0) + { + *value = line.substr(param.size()); + + cout << param << *value << endl; + } +} + +void rdLine(const string ¶m, const string &line, int *value) +{ + if (line.rfind(param.c_str(), 0) == 0) + { + *value = strtol(line.substr(param.size()).c_str(), NULL, 10); + + cout << param << *value << endl; + } +} + bool rdConf(shared_t *share) { - // recording_stream - // detection_stream - // output_dir - // diff_threshold - // post_cmd - // duration - // pixel_size - // frames_post_motion - // minimum_recording_frames - // section_size - auto ret = false; share->retCode = ENOENT; @@ -344,66 +360,16 @@ bool rdConf(shared_t *share) if (line.rfind("#", 0) != 0) { - if (line.rfind("recording_stream = ", 0) == 0) - { - share->recordUrl = line.substr(19); - - cout << "recording_stream = " << share->recordUrl << endl; - } - else if (line.rfind("detection_stream = ", 0) == 0) - { - share->detectUrl = line.substr(19); - - cout << "detection_stream = " << share->detectUrl << endl; - } - else if (line.rfind("output_dir = ", 0) == 0) - { - share->outDir = line.substr(13); - - cout << "output_dir = " << share->outDir << endl; - } - else if (line.rfind("post_cmd = ", 0) == 0) - { - share->postCmd = line.substr(11); - - cout << "post_cmd = " << share->postCmd << endl; - } - else if (line.rfind("diff_threshold = ", 0) == 0) - { - share->thresh = strtol(line.substr(17).c_str(), NULL, 10); - - cout << "diff_threshold = " << share->thresh << endl; - } - else if (line.rfind("duration = ", 0) == 0) - { - share->secs = strtol(line.substr(11).c_str(), NULL, 10); - - cout << "duration = " << share->secs << endl; - } - else if (line.rfind("pixel_size = ", 0) == 0) - { - share->pixSize = strtol(line.substr(13).c_str(), NULL, 10); - - cout << "pixel_size = " << share->pixSize << endl; - } - else if (line.rfind("frames_post_motion = ", 0) == 0) - { - share->postMoIncr = strtol(line.substr(21).c_str(), NULL, 10); - - cout << "frames_post_motion = " << share->postMoIncr << endl; - } - else if (line.rfind("minimum_recording_frames = ", 0) == 0) - { - share->minRecFrames = strtol(line.substr(27).c_str(), NULL, 10); - - cout << "minimum_recording_frames = " << share->minRecFrames << endl; - } - else if (line.rfind("section_size = ", 0) == 0) - { - share->sectionSize = strtol(line.substr(15).c_str(), NULL, 10); - - cout << "section_size = " << share->sectionSize << endl; - } + rdLine("recording_stream = ", line, &share->recordUrl); + rdLine("detection_stream = ", line, &share->detectUrl); + rdLine("output_dir = ", line, &share->outDir); + rdLine("post_cmd = ", line, &share->postCmd); + rdLine("diff_threshold = ", line, &share->thresh); + rdLine("duration = ", line, &share->secs); + rdLine("pixel_size = ", line, &share->pixSize); + rdLine("secs_post_motion = ", line, &share->postMoIncr); + rdLine("section_size = ", line, &share->sectionSize); + rdLine("recording_fps = ", line, &share->fps); } } while(!line.empty()); @@ -441,14 +407,14 @@ int main(int argc, char** argv) else { sharedRes.retCode = 0; - sharedRes.motion = 0; + sharedRes.motion = false; sharedRes.wrRunning = false; while (rdConf(&sharedRes)) { sharedRes.ffRunning = true; - thread th1(timer, &sharedRes); + thread th1(loopTimer, &sharedRes); thread th2(moDetect, &sharedRes); // Wait for the threads to finish