2022-09-22 20:57:46 -04:00
|
|
|
// This file is part of Motion Watch.
|
2022-04-14 09:45:54 -04:00
|
|
|
|
2022-09-22 20:57:46 -04:00
|
|
|
// Motion Watch is free software: you can redistribute it and/or modify
|
|
|
|
// it under the terms of the GNU General Public License as published by
|
|
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
|
|
// (at your option) any later version.
|
2022-04-14 09:45:54 -04:00
|
|
|
|
2022-09-22 20:57:46 -04:00
|
|
|
// Motion Watch is distributed in the hope that it will be useful,
|
|
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
// GNU General Public License for more details.
|
2022-04-14 09:45:54 -04:00
|
|
|
|
2022-09-22 20:57:46 -04:00
|
|
|
#include "mo_detect.h"
|
2022-12-11 10:25:22 -05:00
|
|
|
#include "logger.h"
|
2023-03-05 16:07:07 -05:00
|
|
|
#include "web.h"
|
2022-08-12 21:46:36 -04:00
|
|
|
|
2023-03-05 16:07:07 -05:00
|
|
|
void detectMo(shared_t *share)
|
2022-04-14 09:45:54 -04:00
|
|
|
{
|
2023-03-05 16:07:07 -05:00
|
|
|
while (share->retCode == 0)
|
|
|
|
{
|
|
|
|
sleep(2);
|
|
|
|
detectMoInStream("stream.m3u8", share);
|
|
|
|
}
|
|
|
|
}
|
2022-12-11 10:25:22 -05:00
|
|
|
|
2023-03-05 16:07:07 -05:00
|
|
|
void eventLoop(shared_t *share)
|
|
|
|
{
|
|
|
|
while (share->retCode == 0)
|
2023-02-18 21:20:24 -05:00
|
|
|
{
|
2023-04-15 08:23:49 -04:00
|
|
|
while (share->recList.size() > 1)
|
2023-03-05 16:07:07 -05:00
|
|
|
{
|
2023-04-15 08:23:49 -04:00
|
|
|
auto it = share->recList.begin();
|
|
|
|
auto evName = it->first;
|
|
|
|
auto event = it->second;
|
|
|
|
|
|
|
|
try
|
2023-03-05 16:07:07 -05:00
|
|
|
{
|
2023-04-15 08:23:49 -04:00
|
|
|
createDirTree("events");
|
|
|
|
wrOutVod(event, share);
|
|
|
|
genHTMLvod(evName);
|
|
|
|
|
|
|
|
if (!exists("events/" + evName + ".jpg"))
|
2023-03-12 13:22:10 -04:00
|
|
|
{
|
2023-04-15 08:23:49 -04:00
|
|
|
imwrite(string("events/" + evName + ".jpg").c_str(), event.thumbnail);
|
2023-03-05 16:07:07 -05:00
|
|
|
}
|
2023-03-12 13:22:10 -04:00
|
|
|
}
|
2023-04-15 08:23:49 -04:00
|
|
|
catch (filesystem_error &ex)
|
|
|
|
{
|
|
|
|
recLog(string("err: ") + ex.what(), share);
|
|
|
|
}
|
2023-03-05 16:07:07 -05:00
|
|
|
}
|
|
|
|
|
2023-04-15 08:23:49 -04:00
|
|
|
sleep(10);
|
2023-02-07 23:19:41 -05:00
|
|
|
}
|
2023-03-05 16:07:07 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void upkeep(shared_t *share)
|
2022-08-12 21:46:36 -04:00
|
|
|
{
|
2023-03-05 16:07:07 -05:00
|
|
|
while (share->retCode == 0)
|
2022-08-12 21:46:36 -04:00
|
|
|
{
|
2023-03-26 10:32:56 -04:00
|
|
|
createDirTree("live");
|
|
|
|
createDirTree("events");
|
|
|
|
createDirTree("logs");
|
|
|
|
|
|
|
|
enforceMaxLogSize(string("logs/") + REC_LOG_NAME, share);
|
|
|
|
enforceMaxLogSize(string("logs/") + DET_LOG_NAME, share);
|
|
|
|
enforceMaxLogSize(string("logs/") + UPK_LOG_NAME, share);
|
2022-12-13 20:27:32 -05:00
|
|
|
|
2023-03-26 10:32:56 -04:00
|
|
|
dumpLogs(string("logs/") + REC_LOG_NAME, share->recLog);
|
|
|
|
dumpLogs(string("logs/") + DET_LOG_NAME, share->detLog);
|
|
|
|
dumpLogs(string("logs/") + UPK_LOG_NAME, share->upkLog);
|
2023-03-10 19:05:54 -05:00
|
|
|
|
|
|
|
share->recLog.clear();
|
|
|
|
share->detLog.clear();
|
|
|
|
share->upkLog.clear();
|
2022-12-13 20:27:32 -05:00
|
|
|
|
|
|
|
initLogFrontPages(share);
|
2023-03-05 16:07:07 -05:00
|
|
|
enforceMaxEvents(share);
|
|
|
|
|
|
|
|
genHTMLul(".", share->camName, share);
|
|
|
|
|
|
|
|
upkLog("camera specific webroot page updated: " + share->outDir + "/index.html", share);
|
2022-12-13 20:27:32 -05:00
|
|
|
|
2023-02-18 21:20:24 -05:00
|
|
|
if (!exists("/tmp/mow-lock"))
|
2022-12-04 15:13:39 -05:00
|
|
|
{
|
|
|
|
system("touch /tmp/mow-lock");
|
2022-12-13 20:27:32 -05:00
|
|
|
|
2022-12-11 10:25:22 -05:00
|
|
|
genCSS(share);
|
|
|
|
genHTMLul(share->webRoot, string(APP_NAME) + " " + string(APP_VER), share);
|
2022-12-13 20:27:32 -05:00
|
|
|
|
|
|
|
remove("/tmp/mow-lock");
|
2023-03-05 16:07:07 -05:00
|
|
|
upkLog("webroot page updated: " + cleanDir(share->webRoot) + "/index.html", share);
|
2023-02-18 21:20:24 -05:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2023-03-05 16:07:07 -05:00
|
|
|
upkLog("skipping update of the webroot page, it is busy.", share);
|
2022-12-11 10:25:22 -05:00
|
|
|
}
|
2022-09-23 21:50:06 -04:00
|
|
|
|
2023-03-05 16:07:07 -05:00
|
|
|
sleep(60);
|
|
|
|
}
|
|
|
|
}
|
2023-02-07 23:19:41 -05:00
|
|
|
|
2023-03-05 16:07:07 -05:00
|
|
|
void recLoop(shared_t *share)
|
|
|
|
{
|
|
|
|
while (share->retCode == 0)
|
|
|
|
{
|
2023-03-26 10:32:56 -04:00
|
|
|
if (exists("live"))
|
|
|
|
{
|
|
|
|
remove_all("live");
|
|
|
|
}
|
|
|
|
|
|
|
|
auto cmd = "ffmpeg -hide_banner -rtsp_transport tcp -timeout 3000000 -i " +
|
2023-03-05 16:07:07 -05:00
|
|
|
share->recordUrl +
|
|
|
|
" -strftime 1" +
|
|
|
|
" -strftime_mkdir 1" +
|
2023-03-26 10:32:56 -04:00
|
|
|
" -hls_segment_filename 'live/%Y-%j-%H-%M-%S.ts'" +
|
|
|
|
" -hls_flags delete_segments" +
|
2023-03-10 19:05:54 -05:00
|
|
|
" -y -vcodec copy" +
|
2023-04-15 08:23:49 -04:00
|
|
|
" -f hls -hls_time 2 -hls_list_size 1000" +
|
2023-03-05 16:07:07 -05:00
|
|
|
" stream.m3u8";
|
2023-02-18 17:43:10 -05:00
|
|
|
|
2023-03-05 16:07:07 -05:00
|
|
|
recLog("ffmpeg_run: " + cmd, share);
|
2022-07-28 10:30:07 -04:00
|
|
|
|
2023-03-05 16:07:07 -05:00
|
|
|
auto retCode = system(cmd.c_str());
|
2023-02-14 19:29:02 -05:00
|
|
|
|
2023-03-05 16:07:07 -05:00
|
|
|
recLog("ffmpeg_retcode: " + to_string(retCode), share);
|
2022-12-13 20:27:32 -05:00
|
|
|
|
2023-03-05 16:07:07 -05:00
|
|
|
if (retCode != 0)
|
2022-12-11 10:25:22 -05:00
|
|
|
{
|
2023-03-05 16:07:07 -05:00
|
|
|
recLog("err: ffmpeg returned non zero, indicating failure. please check stderr output.", share);
|
2022-12-11 10:25:22 -05:00
|
|
|
}
|
|
|
|
|
2023-03-26 10:32:56 -04:00
|
|
|
sleep(10);
|
2022-12-13 20:27:32 -05:00
|
|
|
}
|
2022-07-08 15:24:45 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
int main(int argc, char** argv)
|
|
|
|
{
|
2022-09-22 20:57:46 -04:00
|
|
|
struct shared_t sharedRes;
|
|
|
|
|
2023-03-05 16:07:07 -05:00
|
|
|
sharedRes.conf = parseForParam("-c", argc, argv, false);
|
2022-07-08 15:24:45 -04:00
|
|
|
|
|
|
|
if (parseForParam("-h", argc, argv, true) == "true")
|
2022-04-14 09:45:54 -04:00
|
|
|
{
|
2022-09-23 21:50:06 -04:00
|
|
|
cout << "Motion Watch " << APP_VER << endl << endl;
|
2022-09-22 20:57:46 -04:00
|
|
|
cout << "Usage: mow <argument>" << endl << endl;
|
|
|
|
cout << "-h : display usage information about this application." << endl;
|
2023-03-05 16:07:07 -05:00
|
|
|
cout << "-c : path to the config file." << endl;
|
2022-12-24 13:48:51 -05:00
|
|
|
cout << "-v : display the current version." << endl << endl;
|
2022-09-23 21:50:06 -04:00
|
|
|
}
|
2022-12-04 15:13:39 -05:00
|
|
|
else if (parseForParam("-v", argc, argv, true) == "true")
|
2022-09-23 21:50:06 -04:00
|
|
|
{
|
|
|
|
cout << APP_VER << endl;
|
2022-04-14 09:45:54 -04:00
|
|
|
}
|
2022-07-08 15:24:45 -04:00
|
|
|
else if (sharedRes.conf.empty())
|
2022-04-14 09:45:54 -04:00
|
|
|
{
|
2023-02-18 21:20:24 -05:00
|
|
|
cerr << "err: no config file(s) were given in -c" << endl;
|
2022-04-14 09:45:54 -04:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2023-03-26 10:32:56 -04:00
|
|
|
sharedRes.retCode = 0;
|
|
|
|
sharedRes.procTime = 0;
|
2023-04-15 08:23:49 -04:00
|
|
|
sharedRes.maxScore = 0;
|
2023-03-26 10:32:56 -04:00
|
|
|
sharedRes.skipCmd = false;
|
2023-03-05 16:07:07 -05:00
|
|
|
|
|
|
|
rdConf(&sharedRes);
|
|
|
|
|
|
|
|
auto thr1 = thread(recLoop, &sharedRes);
|
|
|
|
auto thr2 = thread(upkeep, &sharedRes);
|
2023-03-26 10:32:56 -04:00
|
|
|
auto thr3 = thread(detectMo, &sharedRes);
|
|
|
|
auto thr4 = thread(eventLoop, &sharedRes);
|
2023-03-05 16:07:07 -05:00
|
|
|
|
|
|
|
thr1.join();
|
|
|
|
thr2.join();
|
2023-03-26 10:32:56 -04:00
|
|
|
thr3.join();
|
|
|
|
thr4.join();
|
2022-04-14 09:45:54 -04:00
|
|
|
|
2022-07-08 15:24:45 -04:00
|
|
|
return sharedRes.retCode;
|
2022-04-14 09:45:54 -04:00
|
|
|
}
|
|
|
|
|
2022-07-08 15:24:45 -04:00
|
|
|
return EINVAL;
|
2022-04-14 09:45:54 -04:00
|
|
|
}
|