From e2a81cc2c5454192f5039757b809611131c6269d Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Sun, 2 Jan 2022 18:38:34 -0500 Subject: [PATCH 1/9] make max_score an int to get rid of the casts. Move assignment of it above the event UPDATE sql so that it is immediately accurate. --- src/zm_event.cpp | 15 ++++++++------- src/zm_event.h | 4 ++-- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/zm_event.cpp b/src/zm_event.cpp index 2d95ec23a..f927eac5c 100644 --- a/src/zm_event.cpp +++ b/src/zm_event.cpp @@ -55,7 +55,7 @@ Event::Event( alarm_frames(0), alarm_frame_written(false), tot_score(0), - max_score(0), + max_score(-1), //path(""), //snapshit_file(), //alarm_file(""), @@ -486,12 +486,12 @@ void Event::AddFrame(Image *image, Debug(1, "frames %d, score %d max_score %d", frames, score, max_score); // If this is the first frame, we should add a thumbnail to the event directory - if ((frames == 1) || (score > (int)max_score)) { + if ((frames == 1) || (score > max_score)) { write_to_db = true; // web ui might show this as thumbnail, so db needs to know about it. Debug(1, "Writing snapshot"); WriteFrameImage(image, timestamp, snapshot_file.c_str()); } else { - Debug(1, "Not Writing snapshot because score %d > max %d", score, max_score); + Debug(1, "Not Writing snapshot because frames %d score %d > max %d", frames, score, max_score); } // We are writing an Alarm frame @@ -523,11 +523,15 @@ void Event::AddFrame(Image *image, bool db_frame = ( frame_type == BULK ) or ( frame_type == ALARM ) or ( frames == 1 ) - or ( score > (int)max_score ) + or ( score > max_score ) or ( monitor_state == Monitor::ALERT ) or ( monitor_state == Monitor::ALARM ) or ( monitor_state == Monitor::PREALARM ); + if (score > max_score) { + max_score = score; + } + if (db_frame) { Microseconds delta_time = std::chrono::duration_cast(timestamp - start_time); Debug(1, "Frame delta is %.2f s - %.2f s = %.2f s, score %u zone_stats.size %zu", @@ -568,9 +572,6 @@ void Event::AddFrame(Image *image, } // end if frame_type == BULK } // end if db_frame - if (score > (int) max_score) { - max_score = score; - } end_time = timestamp; } diff --git a/src/zm_event.h b/src/zm_event.h index 611b2f716..a26c029b5 100644 --- a/src/zm_event.h +++ b/src/zm_event.h @@ -77,8 +77,8 @@ class Event { int frames; int alarm_frames; bool alarm_frame_written; - unsigned int tot_score; - unsigned int max_score; + int tot_score; + int max_score; std::string path; std::string snapshot_file; std::string alarm_file; From 205ff6c033507d697e5dab1dd509b36e4e774ded Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Sun, 2 Jan 2022 19:25:44 -0500 Subject: [PATCH 2/9] apply fix to RtspServer --- dep/RtspServer | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dep/RtspServer b/dep/RtspServer index cd7fd49be..1b40f1661 160000 --- a/dep/RtspServer +++ b/dep/RtspServer @@ -1 +1 @@ -Subproject commit cd7fd49becad6010a1b8466bfebbd93999a39878 +Subproject commit 1b40f1661f93f50fd5805f239d1e466a3bcf888f From 7215756fed4a428e0514e9173114a1703cbc6f68 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Mon, 3 Jan 2022 19:03:04 -0500 Subject: [PATCH 3/9] Introduce a method update the noteSetMap after event creation (addNote). --- src/zm_event.cpp | 4 ++++ src/zm_event.h | 25 +++++++++++++------------ 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/src/zm_event.cpp b/src/zm_event.cpp index f927eac5c..7db8f84f3 100644 --- a/src/zm_event.cpp +++ b/src/zm_event.cpp @@ -291,6 +291,10 @@ void Event::createNotes(std::string ¬es) { } } // void Event::createNotes(std::string ¬es) +void Event::addNote(const char *cause, const std::string ¬e) { + noteSetMap[cause].insert(note); +} + bool Event::WriteFrameImage(Image *image, SystemTimePoint timestamp, const char *event_file, bool alarm_frame) const { int thisquality = (alarm_frame && (config.jpeg_alarm_file_quality > config.jpeg_file_quality)) ? diff --git a/src/zm_event.h b/src/zm_event.h index a26c029b5..4fb5c7469 100644 --- a/src/zm_event.h +++ b/src/zm_event.h @@ -110,6 +110,7 @@ class Event { uint64_t Id() const { return id; } const std::string &Cause() const { return cause; } + void addNote(const char *cause, const std::string ¬e); int Frames() const { return frames; } int AlarmFrames() const { return alarm_frames; } @@ -123,7 +124,7 @@ class Event { void updateNotes(const StringSetMap &stringSetMap); - void AddFrame(Image *image, + void AddFrame(Image *image, SystemTimePoint timestamp, const std::vector &stats, int score = 0, @@ -134,17 +135,17 @@ class Event { bool SetPath(Storage *storage); public: - static std::string getSubPath(tm time) { - std::string subpath = stringtf("%02d/%02d/%02d/%02d/%02d/%02d", - time.tm_year - 100, time.tm_mon + 1, time.tm_mday, - time.tm_hour, time.tm_min, time.tm_sec); - return subpath; - } - static std::string getSubPath(time_t *time) { - tm time_tm = {}; - localtime_r(time, &time_tm); - return Event::getSubPath(time_tm); - } + static std::string getSubPath(tm time) { + std::string subpath = stringtf("%02d/%02d/%02d/%02d/%02d/%02d", + time.tm_year - 100, time.tm_mon + 1, time.tm_mday, + time.tm_hour, time.tm_min, time.tm_sec); + return subpath; + } + static std::string getSubPath(time_t *time) { + tm time_tm = {}; + localtime_r(time, &time_tm); + return Event::getSubPath(time_tm); + } const char* getEventFile() const { return video_file.c_str(); From b1353823cf8653fb3cab0983d61baab7156e44ac Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Mon, 3 Jan 2022 19:04:21 -0500 Subject: [PATCH 4/9] clean up signal change code a bit, using new event notesetmap update function. So now when we lose signal, the event will close but it will have signal change :Lost added to it's notes. A new event will only be created if in RECORD/MOCORD. --- src/zm_monitor.cpp | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/src/zm_monitor.cpp b/src/zm_monitor.cpp index ac2703b71..5fa6728f9 100644 --- a/src/zm_monitor.cpp +++ b/src/zm_monitor.cpp @@ -1769,29 +1769,25 @@ bool Monitor::Analyse() { // FIXME this snap might not be the one that caused the signal change. Need to store that in the packet. if (signal_change) { Debug(2, "Signal change, new signal is %d", signal); - const char *signalText = "Unknown"; if (!signal) { - signalText = "Lost"; if (event) { + event->addNote(SIGNAL_CAUSE, "Lost"); Info("%s: %03d - Closing event %" PRIu64 ", signal loss", name.c_str(), analysis_image_count, event->Id()); closeEvent(); last_section_mod = 0; } - } else { - signalText = "Reacquired"; - score += 100; + } else if (function == MOCORD or function == RECORD) { + if (!event) { + if (cause.length()) cause += ", "; + cause += SIGNAL_CAUSE + std::string(": Reacquired"); + } else { + event->addNote(SIGNAL_CAUSE, "Reacquired"); + } + if (snap->image) + ref_image.Assign(*(snap->image)); } - if (!event) { - if (cause.length()) cause += ", "; - cause += SIGNAL_CAUSE; - } - Event::StringSet noteSet; - noteSet.insert(signalText); - noteSetMap[SIGNAL_CAUSE] = noteSet; shared_data->state = state = IDLE; shared_data->active = signal; - if ((function == MODECT or function == MOCORD) and snap->image) - ref_image.Assign(*(snap->image)); } // end if signal change if (signal) { From a59e33d8b0634f33dac3c7e3d5f8a75de17116e3 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Mon, 3 Jan 2022 19:14:27 -0500 Subject: [PATCH 5/9] remove unused last_section_mod --- src/zm_monitor.cpp | 3 --- src/zm_monitor.h | 1 - 2 files changed, 4 deletions(-) diff --git a/src/zm_monitor.cpp b/src/zm_monitor.cpp index 5fa6728f9..52fca1218 100644 --- a/src/zm_monitor.cpp +++ b/src/zm_monitor.cpp @@ -375,7 +375,6 @@ Monitor::Monitor() first_alarm_count(0), last_alarm_count(0), last_signal(false), - last_section_mod(0), buffer_count(0), state(IDLE), last_motion_score(0), @@ -426,7 +425,6 @@ Monitor::Monitor() event_close_mode = CLOSE_IDLE; event = nullptr; - last_section_mod = 0; adaptive_skip = true; @@ -1774,7 +1772,6 @@ bool Monitor::Analyse() { event->addNote(SIGNAL_CAUSE, "Lost"); Info("%s: %03d - Closing event %" PRIu64 ", signal loss", name.c_str(), analysis_image_count, event->Id()); closeEvent(); - last_section_mod = 0; } } else if (function == MOCORD or function == RECORD) { if (!event) { diff --git a/src/zm_monitor.h b/src/zm_monitor.h index 8d6bbd95e..447ea3580 100644 --- a/src/zm_monitor.h +++ b/src/zm_monitor.h @@ -351,7 +351,6 @@ protected: int first_alarm_count; int last_alarm_count; bool last_signal; - int last_section_mod; int buffer_count; State state; SystemTimePoint start_time; From 198ee73d0e34ba5873bdb53cd2df0ea2f8699946 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 4 Jan 2022 17:38:25 -0500 Subject: [PATCH 6/9] Add alarm_cause to zm_packet. Clean up code dealing with decoding not being ready --- src/zm_monitor.cpp | 87 +++++++++++++++++++--------------------------- src/zm_packet.h | 1 + 2 files changed, 36 insertions(+), 52 deletions(-) diff --git a/src/zm_monitor.cpp b/src/zm_monitor.cpp index 52fca1218..36f735aa7 100644 --- a/src/zm_monitor.cpp +++ b/src/zm_monitor.cpp @@ -1828,27 +1828,14 @@ bool Monitor::Analyse() { /* try to stay behind the decoder. */ if (decoding_enabled) { - while (!snap->decoded and !zm_terminate and !analysis_thread->Stopped()) { + if (!snap->decoded and !zm_terminate and !analysis_thread->Stopped()) { // Need to wait for the decoder thread. Debug(1, "Waiting for decode"); packetqueue.unlock(packet_lock); // This will delete packet_lock and notify_all packetqueue.wait(); - - // Another thread may have moved our it. Unlikely but possible - packet_lock = packetqueue.get_packet(analysis_it); - if (!packet_lock) return false; - snap = packet_lock->packet_; - - if (!snap->image and snap->decoded) { - Debug(1, "No image but was decoded, giving up"); - delete packet_lock; - return false; - } - } // end while ! decoded - if (zm_terminate) { - delete packet_lock; + // Everything may have changed, just return and start again. This needs to be more RAII return false; - } + } // end while ! decoded } // end if decoding enabled SystemTimePoint timestamp = snap->timestamp; @@ -1864,46 +1851,43 @@ bool Monitor::Analyse() { motion_frame_skip, capture_fps, analysis_fps_limit); } - if (!(analysis_image_count % (motion_frame_skip+1))) { - if (snap->image) { - // decoder may not have been able to provide an image - if (!ref_image.Buffer()) { - Debug(1, "Assigning instead of Detecting"); - ref_image.Assign(*(snap->image)); - } else { - Debug(1, "Detecting motion on image %d, image %p", snap->image_index, snap->image); - // Get new score. - int motion_score = DetectMotion(*(snap->image), zoneSet); + if (snap->image) { + // decoder may not have been able to provide an image + if (!ref_image.Buffer()) { + Debug(1, "Assigning instead of Detecting"); + ref_image.Assign(*(snap->image)); + } else if (!(analysis_image_count % (motion_frame_skip+1))) { + Debug(1, "Detecting motion on image %d, image %p", snap->image_index, snap->image); + // Get new score. + int motion_score = DetectMotion(*(snap->image), zoneSet); - // lets construct alarm cause. It will contain cause + names of zones alarmed - std::string alarm_cause; - snap->zone_stats.reserve(zones.size()); - for (const Zone &zone : zones) { - const ZoneStats &stats = zone.GetStats(); - stats.DumpToLog("After detect motion"); - snap->zone_stats.push_back(stats); - if (zone.Alarmed()) { - if (!alarm_cause.empty()) alarm_cause += ","; - alarm_cause += std::string(zone.Label()); - } + // lets construct alarm cause. It will contain cause + names of zones alarmed + snap->zone_stats.reserve(zones.size()); + for (const Zone &zone : zones) { + const ZoneStats &stats = zone.GetStats(); + stats.DumpToLog("After detect motion"); + snap->zone_stats.push_back(stats); + if (zone.Alarmed()) { + if (!snap->alarm_cause.empty()) snap->alarm_cause += ","; + snap->alarm_cause += std::string(zone.Label()); } - Debug(3, "After motion detection, score:%d last_motion_score(%d), new motion score(%d)", - score, last_motion_score, motion_score); - motion_frame_count += 1; - last_motion_score = motion_score; - - if (motion_score) { - if (cause.length()) cause += ", "; - cause += MOTION_CAUSE+std::string(":")+alarm_cause; - noteSetMap[MOTION_CAUSE] = zoneSet; - } // end if motion_score } + Debug(3, "After motion detection, score:%d last_motion_score(%d), new motion score(%d)", + score, last_motion_score, motion_score); + motion_frame_count += 1; + last_motion_score = motion_score; + + if (motion_score) { + if (cause.length()) cause += ", "; + cause += MOTION_CAUSE+std::string(":")+snap->alarm_cause; + noteSetMap[MOTION_CAUSE] = zoneSet; + } // end if motion_score } else { - Debug(1, "no image so skipping motion detection"); - } // end if has image + Debug(1, "Skipped motion detection last motion score was %d", last_motion_score); + } } else { - Debug(1, "Skipped motion detection last motion score was %d", last_motion_score); - } + Debug(1, "no image so skipping motion detection"); + } // end if has image score += last_motion_score; } else { Debug(1, "Not Active(%d) enabled %d active %d doing motion detection: %d", @@ -1912,7 +1896,6 @@ bool Monitor::Analyse() { ); } // end if active and doing motion detection - if (function == RECORD or function == MOCORD) { // If doing record, check to see if we need to close the event or not. if (event) { diff --git a/src/zm_packet.h b/src/zm_packet.h index 9cce4dd03..8a6a31de5 100644 --- a/src/zm_packet.h +++ b/src/zm_packet.h @@ -57,6 +57,7 @@ class ZMPacket { int64_t pts; // pts in the packet can be in another time base. This MUST be in AV_TIME_BASE_Q bool decoded; std::vector zone_stats; + std::string alarm_cause; public: AVPacket *av_packet() { return &packet; } From cce24ea427c81af80aad39880b26a31f10ca34c7 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 5 Jan 2022 16:48:46 -0500 Subject: [PATCH 7/9] Add RTSPServer and Importance fields --- scripts/ZoneMinder/lib/ZoneMinder/Monitor.pm | 3 +++ 1 file changed, 3 insertions(+) diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Monitor.pm b/scripts/ZoneMinder/lib/ZoneMinder/Monitor.pm index d179534d4..25db048fc 100644 --- a/scripts/ZoneMinder/lib/ZoneMinder/Monitor.pm +++ b/scripts/ZoneMinder/lib/ZoneMinder/Monitor.pm @@ -133,6 +133,9 @@ $serial = $primary_key = 'Id'; DefaultCodec Latitude Longitude + RTSPServer + RTSPStreamName + Importance ); %defaults = ( From bfac696fb7177373abddf0ba531c04e80a038d44 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 5 Jan 2022 16:49:00 -0500 Subject: [PATCH 8/9] return logger from loginit so that we can use it --- scripts/ZoneMinder/lib/ZoneMinder/Logger.pm | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Logger.pm b/scripts/ZoneMinder/lib/ZoneMinder/Logger.pm index 43ae38e72..03bc84cd3 100644 --- a/scripts/ZoneMinder/lib/ZoneMinder/Logger.pm +++ b/scripts/ZoneMinder/lib/ZoneMinder/Logger.pm @@ -638,6 +638,7 @@ sub logInit( ;@ ) { $logger = ZoneMinder::Logger->new() if !$logger; $logger->initialise(%options); logSetSignal(); + return $logger; } sub logReinit { From bc67493f91ca7597d5c465b6a8b5c400d7a5544b Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 5 Jan 2022 16:49:20 -0500 Subject: [PATCH 9/9] Alter log level of restart events based on Importance setting --- scripts/zmwatch.pl.in | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/scripts/zmwatch.pl.in b/scripts/zmwatch.pl.in index 1b4790bce..dd5cfc252 100644 --- a/scripts/zmwatch.pl.in +++ b/scripts/zmwatch.pl.in @@ -67,7 +67,7 @@ $ENV{PATH} = '/bin:/usr/bin:/usr/local/bin'; $ENV{SHELL} = '/bin/sh' if exists $ENV{SHELL}; delete @ENV{qw(IFS CDPATH ENV BASH_ENV)}; -logInit(); +my $log = logInit(); logSetSignal(); my $zm_terminate = 0; sub TermHandler { @@ -114,7 +114,7 @@ while (!$zm_terminate) { # We can't get the last capture time so can't be sure it's died, it might just be starting up. my $startup_time = zmGetStartupTime($monitor); if (($now - $startup_time) > $Config{ZM_WATCH_MAX_DELAY}) { - Warning( + $log->logPrint(ZoneMinder::Logger::WARNING+$monitor->Importance(), "Restarting capture daemon for $$monitor{Name}, no image since startup. ". "Startup time was $startup_time - now $now > $Config{ZM_WATCH_MAX_DELAY}" ); @@ -133,8 +133,9 @@ while (!$zm_terminate) { my $image_delay = $now - $capture_time; Debug("Monitor $monitor->{Id} last captured $image_delay seconds ago, max is $max_image_delay"); if ($image_delay > $max_image_delay) { - Warning('Restarting capture daemon for '.$monitor->{Name}. - ", time since last capture $image_delay seconds ($now-$capture_time)"); + $log->logPrint(ZoneMinder::Logger::WARNING+$monitor->Importance(), + 'Restarting capture daemon for '.$monitor->{Name}. + ", time since last capture $image_delay seconds ($now-$capture_time)"); $monitor->control('restart'); next; } @@ -160,10 +161,11 @@ while (!$zm_terminate) { my $image_delay = $now-$image_time; Debug("Monitor $monitor->{Id} last analysed $image_delay seconds ago, max is $max_image_delay"); if ($image_delay > $max_image_delay) { - Warning("Analysis daemon for $$monitor{Id} $$monitor{Name} needs restarting," - ." time since last analysis $image_delay seconds ($now-$image_time)"); - $monitor->control('restart'); - next; + $log->logPrint(ZoneMinder::Logger::WARNING+$monitor->Importance(), + "daemon for $$monitor{Id} $$monitor{Name} needs restarting," + ." time since last analysis $image_delay seconds ($now-$image_time)"); + $monitor->control('restart'); + next; } }