mirror of
https://github.com/ZoneMinder/zoneminder.git
synced 2026-10-27 16:58:31 -04:00
Merge branch 'master' into fmt
This commit is contained in:
507 files changed
+52739
-20996
No files matched your search
+75
-133
@@ -54,10 +54,10 @@ possible, this should run at more or less constant speed.
|
||||
*/
|
||||
|
||||
#include "zm.h"
|
||||
#include "zm_analysis_thread.h"
|
||||
#include "zm_camera.h"
|
||||
#include "zm_db.h"
|
||||
#include "zm_define.h"
|
||||
#include "zm_fifo.h"
|
||||
#include "zm_monitor.h"
|
||||
#include "zm_rtsp_server_thread.h"
|
||||
#include "zm_signal.h"
|
||||
@@ -65,19 +65,18 @@ possible, this should run at more or less constant speed.
|
||||
#include "zm_utils.h"
|
||||
#include <fmt/format.h>
|
||||
#include <getopt.h>
|
||||
#include <iostream>
|
||||
|
||||
void Usage() {
|
||||
fprintf(stderr, "zmc -d <device_path> or -r <proto> -H <host> -P <port> -p <path> or -f <file_path> or -m <monitor_id>\n");
|
||||
|
||||
fprintf(stderr, "Options:\n");
|
||||
#if defined(BSD)
|
||||
fprintf(stderr, " -d, --device <device_path> : For local cameras, device to access. E.g /dev/bktr0 etc\n");
|
||||
fprintf(stderr, " -d, --device <device_path> : For local cameras, device to access. E.g /dev/bktr0 etc\n");
|
||||
#else
|
||||
fprintf(stderr, " -d, --device <device_path> : For local cameras, device to access. E.g /dev/video0 etc\n");
|
||||
fprintf(stderr, " -d, --device <device_path> : For local cameras, device to access. E.g /dev/video0 etc\n");
|
||||
#endif
|
||||
fprintf(stderr, " -f, --file <file_path> : For local images, jpg file to access.\n");
|
||||
fprintf(stderr, " -m, --monitor <monitor_id> : For sources associated with a single monitor\n");
|
||||
fprintf(stderr, " -f, --file <file_path> : For local images, jpg file to access.\n");
|
||||
fprintf(stderr, " -m, --monitor <monitor_id> : For sources associated with a single monitor\n");
|
||||
fprintf(stderr, " -h, --help : This screen\n");
|
||||
fprintf(stderr, " -v, --version : Report the installed version of ZoneMinder\n");
|
||||
exit(0);
|
||||
@@ -189,14 +188,14 @@ int main(int argc, char *argv[]) {
|
||||
zmLoadDBConfig();
|
||||
logInit(logId);
|
||||
|
||||
hwcaps_detect();
|
||||
HwCapsDetect();
|
||||
|
||||
std::vector<std::shared_ptr<Monitor>> monitors;
|
||||
#if ZM_HAS_V4L
|
||||
#if ZM_HAS_V4L2
|
||||
if ( device[0] ) {
|
||||
monitors = Monitor::LoadLocalMonitors(device, Monitor::CAPTURE);
|
||||
} else
|
||||
#endif // ZM_HAS_V4L
|
||||
#endif // ZM_HAS_V4L2
|
||||
if ( host[0] ) {
|
||||
if ( !port )
|
||||
port = "80";
|
||||
@@ -214,7 +213,7 @@ int main(int argc, char *argv[]) {
|
||||
Error("No monitors found");
|
||||
exit(-1);
|
||||
} else {
|
||||
Debug(2, "%d monitors loaded", monitors.size());
|
||||
Debug(2, "%zu monitors loaded", monitors.size());
|
||||
}
|
||||
|
||||
Info("Starting Capture version %s", ZM_VERSION);
|
||||
@@ -234,7 +233,6 @@ int main(int argc, char *argv[]) {
|
||||
|
||||
while (!zm_terminate) {
|
||||
result = 0;
|
||||
static char sql[ZM_SQL_SML_BUFSIZ];
|
||||
|
||||
for (const std::shared_ptr<Monitor> &monitor : monitors) {
|
||||
monitor->LoadCamera();
|
||||
@@ -242,74 +240,51 @@ int main(int argc, char *argv[]) {
|
||||
if (!monitor->connect()) {
|
||||
Warning("Couldn't connect to monitor %d", monitor->Id());
|
||||
}
|
||||
time_t now = (time_t)time(nullptr);
|
||||
monitor->setStartupTime(now);
|
||||
SystemTimePoint now = std::chrono::system_clock::now();
|
||||
monitor->SetStartupTime(now);
|
||||
monitor->SetHeartbeatTime(now);
|
||||
|
||||
snprintf(sql, sizeof(sql),
|
||||
std::string sql = stringtf(
|
||||
"INSERT INTO Monitor_Status (MonitorId,Status,CaptureFPS,AnalysisFPS)"
|
||||
" VALUES (%d, 'Running',0,0) ON DUPLICATE KEY UPDATE Status='Running',CaptureFPS=0,AnalysisFPS=0",
|
||||
" VALUES (%u, 'Running',0,0) ON DUPLICATE KEY UPDATE Status='Running',CaptureFPS=0,AnalysisFPS=0",
|
||||
monitor->Id());
|
||||
zmDbDo(sql);
|
||||
|
||||
Seconds sleep_time = Seconds(0);
|
||||
while (monitor->PrimeCapture() <= 0) {
|
||||
if (prime_capture_log_count % 60) {
|
||||
Error("Failed to prime capture of initial monitor");
|
||||
logPrintf(Logger::ERROR + monitor->Importance(),
|
||||
"Failed to prime capture of initial monitor");
|
||||
} else {
|
||||
Debug(1, "Failed to prime capture of initial monitor");
|
||||
}
|
||||
prime_capture_log_count ++;
|
||||
if (zm_terminate) break;
|
||||
sleep(1);
|
||||
}
|
||||
if (zm_terminate) break;
|
||||
|
||||
snprintf(sql, sizeof(sql),
|
||||
"INSERT INTO Monitor_Status (MonitorId,Status) VALUES (%d, 'Connected') ON DUPLICATE KEY UPDATE Status='Connected'",
|
||||
monitor->Id());
|
||||
prime_capture_log_count++;
|
||||
if (zm_terminate) {
|
||||
break;
|
||||
}
|
||||
if (sleep_time < Seconds(60)) {
|
||||
sleep_time++;
|
||||
}
|
||||
|
||||
std::this_thread::sleep_for(sleep_time);
|
||||
}
|
||||
if (zm_terminate) {
|
||||
break;
|
||||
}
|
||||
|
||||
sql = stringtf(
|
||||
"INSERT INTO Monitor_Status (MonitorId,Status) VALUES (%u, 'Connected') ON DUPLICATE KEY UPDATE Status='Connected'",
|
||||
monitor->Id());
|
||||
zmDbDo(sql);
|
||||
} // end foreach monitor
|
||||
if (zm_terminate) break;
|
||||
|
||||
#if HAVE_RTSP_SERVER
|
||||
RTSPServerThread ** rtsp_server_threads = nullptr;
|
||||
if (config.min_rtsp_port and monitors[0]->RTSPServer()) {
|
||||
rtsp_server_threads = new RTSPServerThread *[monitors.size()];
|
||||
Debug(1, "Starting RTSP server because min_rtsp_port is set");
|
||||
} else {
|
||||
Debug(1, "Not starting RTSP server because min_rtsp_port not set");
|
||||
}
|
||||
#endif
|
||||
|
||||
std::vector<std::unique_ptr<AnalysisThread>> analysis_threads = std::vector<std::unique_ptr<AnalysisThread>>();
|
||||
|
||||
int *capture_delays = new int[monitors.size()];
|
||||
int *alarm_capture_delays = new int[monitors.size()];
|
||||
struct timeval * last_capture_times = new struct timeval[monitors.size()];
|
||||
|
||||
for (size_t i = 0; i < monitors.size(); i++) {
|
||||
last_capture_times[i].tv_sec = last_capture_times[i].tv_usec = 0;
|
||||
capture_delays[i] = monitors[i]->GetCaptureDelay();
|
||||
alarm_capture_delays[i] = monitors[i]->GetAlarmCaptureDelay();
|
||||
Debug(2, "capture delay(%u mSecs 1000/capture_fps) alarm delay(%u)",
|
||||
capture_delays[i], alarm_capture_delays[i]);
|
||||
|
||||
Monitor::Function function = monitors[0]->GetFunction();
|
||||
if (function != Monitor::MONITOR) {
|
||||
Debug(1, "Starting an analysis thread for monitor (%d)", monitors[i]->Id());
|
||||
analysis_threads.emplace_back(ZM::make_unique<AnalysisThread>(monitors[i]));
|
||||
}
|
||||
#if HAVE_RTSP_SERVER
|
||||
if (rtsp_server_threads) {
|
||||
rtsp_server_threads[i] = new RTSPServerThread(monitors[i]);
|
||||
rtsp_server_threads[i]->addStream(monitors[i]->GetVideoStream(), monitors[i]->GetAudioStream());
|
||||
rtsp_server_threads[i]->start();
|
||||
}
|
||||
#endif
|
||||
if (zm_terminate){
|
||||
break;
|
||||
}
|
||||
|
||||
struct timeval now;
|
||||
struct DeltaTimeval delta_time;
|
||||
int sleep_time = 0;
|
||||
std::vector<SystemTimePoint> last_capture_times = std::vector<SystemTimePoint>(monitors.size());
|
||||
Microseconds sleep_time = Microseconds(0);
|
||||
|
||||
while (!zm_terminate) {
|
||||
//sigprocmask(SIG_BLOCK, &block_set, 0);
|
||||
@@ -317,47 +292,50 @@ int main(int argc, char *argv[]) {
|
||||
monitors[i]->CheckAction();
|
||||
|
||||
if (monitors[i]->PreCapture() < 0) {
|
||||
Error("Failed to pre-capture monitor %d %d (%d/" SZFMTD ")",
|
||||
monitors[i]->Id(), monitors[i]->Name(), i+1, monitors.size());
|
||||
Error("Failed to pre-capture monitor %d %s (%zu/%zu)",
|
||||
monitors[i]->Id(), monitors[i]->Name(), i + 1, monitors.size());
|
||||
result = -1;
|
||||
break;
|
||||
}
|
||||
if (monitors[i]->Capture() < 0) {
|
||||
Error("Failed to capture image from monitor %d %s (%d/" SZFMTD ")",
|
||||
monitors[i]->Id(), monitors[i]->Name(), i+1, monitors.size());
|
||||
Error("Failed to capture image from monitor %d %s (%zu/%zu)",
|
||||
monitors[i]->Id(), monitors[i]->Name(), i + 1, monitors.size());
|
||||
result = -1;
|
||||
break;
|
||||
}
|
||||
if (monitors[i]->PostCapture() < 0) {
|
||||
Error("Failed to post-capture monitor %d %s (%d/" SZFMTD ")",
|
||||
monitors[i]->Id(), monitors[i]->Name(), i+1, monitors.size());
|
||||
Error("Failed to post-capture monitor %d %s (%zu/%zu)",
|
||||
monitors[i]->Id(), monitors[i]->Name(), i + 1, monitors.size());
|
||||
result = -1;
|
||||
break;
|
||||
}
|
||||
monitors[i]->UpdateFPS();
|
||||
|
||||
gettimeofday(&now, nullptr);
|
||||
// capture_delay is the amount of time we should sleep in useconds to achieve the desired framerate.
|
||||
int delay = (monitors[i]->GetState() == Monitor::ALARM) ? alarm_capture_delays[i] : capture_delays[i];
|
||||
if (delay && last_capture_times[i].tv_sec) {
|
||||
// DT_PREC_3 means that the value will be in thousands of a second
|
||||
DELTA_TIMEVAL(delta_time, now, last_capture_times[i], DT_PREC_6);
|
||||
Microseconds delay = (monitors[i]->GetState() == Monitor::ALARM) ? monitors[i]->GetAlarmCaptureDelay()
|
||||
: monitors[i]->GetCaptureDelay();
|
||||
if (delay != Seconds(0)) {
|
||||
SystemTimePoint now = std::chrono::system_clock::now();
|
||||
if (last_capture_times[i].time_since_epoch() != Seconds(0)) {
|
||||
Microseconds delta_time = std::chrono::duration_cast<Microseconds>(now - last_capture_times[i]);
|
||||
|
||||
// You have to add back in the previous sleep time
|
||||
sleep_time = delay - (delta_time.delta - sleep_time);
|
||||
Debug(4, "Sleep time is %d from now:%d.%d last:%d.%d delta %d delay: %d",
|
||||
sleep_time,
|
||||
now.tv_sec, now.tv_usec,
|
||||
last_capture_times[i].tv_sec, last_capture_times[i].tv_usec,
|
||||
delta_time.delta,
|
||||
delay
|
||||
);
|
||||
|
||||
if (sleep_time > 0) {
|
||||
Debug(4, "usleeping (%d)", sleep_time);
|
||||
usleep(sleep_time);
|
||||
}
|
||||
} // end if has a last_capture time
|
||||
last_capture_times[i] = now;
|
||||
// You have to add back in the previous sleep time
|
||||
sleep_time = delay - (delta_time - sleep_time);
|
||||
Debug(4,
|
||||
"Sleep time is %" PRIi64 " from now: %.2f s last: %.2f s delta % " PRIi64 " us delay: %" PRIi64 " us",
|
||||
static_cast<int64>(Microseconds(sleep_time).count()),
|
||||
FPSeconds(now.time_since_epoch()).count(),
|
||||
FPSeconds(last_capture_times[i].time_since_epoch()).count(),
|
||||
static_cast<int64>(delta_time.count()),
|
||||
static_cast<int64>(Microseconds(delay).count()));
|
||||
|
||||
if (sleep_time > Seconds(0)) {
|
||||
std::this_thread::sleep_for(sleep_time);
|
||||
}
|
||||
} // end if has a last_capture time
|
||||
|
||||
last_capture_times[i] = now;
|
||||
} // end if delay
|
||||
} // end foreach n_monitors
|
||||
|
||||
if ((result < 0) or zm_reload) {
|
||||
@@ -366,45 +344,11 @@ int main(int argc, char *argv[]) {
|
||||
}
|
||||
} // end while ! zm_terminate and connected
|
||||
|
||||
for (std::unique_ptr<AnalysisThread> &analysis_thread: analysis_threads)
|
||||
analysis_thread->Stop();
|
||||
|
||||
for (size_t i = 0; i < monitors.size(); i++) {
|
||||
#if HAVE_RTSP_SERVER
|
||||
if (rtsp_server_threads) {
|
||||
rtsp_server_threads[i]->stop();
|
||||
}
|
||||
#endif
|
||||
|
||||
monitors[i]->Close();
|
||||
|
||||
#if HAVE_RTSP_SERVER
|
||||
if (rtsp_server_threads) {
|
||||
rtsp_server_threads[i]->join();
|
||||
delete rtsp_server_threads[i];
|
||||
rtsp_server_threads[i] = nullptr;
|
||||
}
|
||||
#endif
|
||||
for (std::shared_ptr<Monitor> & monitor : monitors) {
|
||||
monitor->Close();
|
||||
monitor->disconnect();
|
||||
}
|
||||
|
||||
// Killoff the analysis threads. Don't need them spinning while we try to reconnect
|
||||
analysis_threads.clear();
|
||||
|
||||
#if HAVE_RTSP_SERVER
|
||||
if (rtsp_server_threads) {
|
||||
delete[] rtsp_server_threads;
|
||||
rtsp_server_threads = nullptr;
|
||||
}
|
||||
#endif
|
||||
delete [] alarm_capture_delays;
|
||||
delete [] capture_delays;
|
||||
delete [] last_capture_times;
|
||||
|
||||
if (result < 0 and !zm_terminate) {
|
||||
// Failure, try reconnecting
|
||||
Debug(1, "Sleeping for 5");
|
||||
sleep(5);
|
||||
}
|
||||
if (zm_reload) {
|
||||
for (std::shared_ptr<Monitor> &monitor : monitors) {
|
||||
monitor->Reload();
|
||||
@@ -415,12 +359,9 @@ int main(int argc, char *argv[]) {
|
||||
} // end if zm_reload
|
||||
} // end while ! zm_terminate outer connection loop
|
||||
|
||||
Debug(1,"Updating Monitor status");
|
||||
|
||||
for (std::shared_ptr<Monitor> &monitor : monitors) {
|
||||
static char sql[ZM_SQL_SML_BUFSIZ];
|
||||
snprintf(sql, sizeof(sql),
|
||||
"INSERT INTO Monitor_Status (MonitorId,Status) VALUES (%d, 'Connected') ON DUPLICATE KEY UPDATE Status='NotRunning'",
|
||||
std::string sql = stringtf(
|
||||
"INSERT INTO Monitor_Status (MonitorId,Status) VALUES (%u, 'NotRunning') ON DUPLICATE KEY UPDATE Status='NotRunning'",
|
||||
monitor->Id());
|
||||
zmDbDo(sql);
|
||||
}
|
||||
@@ -428,7 +369,8 @@ int main(int argc, char *argv[]) {
|
||||
Image::Deinitialise();
|
||||
Debug(1, "terminating");
|
||||
logTerm();
|
||||
dbQueue.stop();
|
||||
zmDbClose();
|
||||
|
||||
return zm_terminate ? 0 : result;
|
||||
return zm_terminate ? 0 : result;
|
||||
}
|
||||
Reference in new issue
Block a user