From 9b8ca69203f9407c5dd13d17212074c9ff3cfa7b Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Thu, 13 Jan 2022 10:21:32 -0500 Subject: [PATCH 1/7] default interactive to whether we have stdio. So now when running from console it will default to interactive and when running from zmdc.pl will be non-interactive. Do check regardless of ZM_UPDATE_CHECK setting. --- scripts/zmupdate.pl.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/zmupdate.pl.in b/scripts/zmupdate.pl.in index 9ad5a1a02..d096c70b5 100644 --- a/scripts/zmupdate.pl.in +++ b/scripts/zmupdate.pl.in @@ -96,7 +96,7 @@ my $use_log = (($> == 0) || ($> == $web_uid)); logInit( toFile=>$use_log?DEBUG:NOLOG ); logSetSignal(); -my $interactive = 1; +my $interactive = -t STDERR; # interactive if we have IO my $check = 0; my $freshen = 0; my $rename = 0; @@ -144,7 +144,7 @@ if ( ($check + $freshen + $rename + $zoneFix + $migrateEvents + ($version?1:0)) pod2usage(-exitstatus => -1); } -if ($check and ($Config{ZM_CHECK_FOR_UPDATES} or $interactive) ) { +if ($check) { if (!$interactive) { Info('Update agent starting at '.strftime('%y/%m/%d %H:%M:%S', localtime() )."\n"); } From 7c1ba721aa66b91cfff19193b6b62b81075b9480 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Thu, 13 Jan 2022 22:14:14 -0500 Subject: [PATCH 2/7] Preface Debug with ZM --- web/includes/csrf/csrf-magic.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/includes/csrf/csrf-magic.php b/web/includes/csrf/csrf-magic.php index b102c565a..10d200240 100644 --- a/web/includes/csrf/csrf-magic.php +++ b/web/includes/csrf/csrf-magic.php @@ -348,7 +348,7 @@ return false; return $value === csrf_hash($_COOKIE[$n], $time); case 'key': if (!$GLOBALS['csrf']['key']) { - Debug("Checking key: no key set" ); + ZM\Debug("Checking key: no key set" ); return false; } #Debug("Checking sid: $value === " . csrf_hash($GLOBALS['csrf']['key'], $time) ); From 9240a93ef501658fb1869433437bdfb4730629fb Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 14 Jan 2022 14:09:18 -0500 Subject: [PATCH 3/7] Revert my idea of having ONVIF and TRIGGER code start/end events. Move code to tst for Ready() up above ONVIF and TRIGGER code. When waiting for decode, junk the idea of locking in the packetqueue. Since waiting releases the lock, we should be ok waiting and notifying in the packet. (I know there was a time when I felt this was necessary and I think it had to do with the deinterlacing case, but I've simplified that code too). --- src/zm_monitor.cpp | 128 ++++++++++++++++++++++++--------------------- 1 file changed, 67 insertions(+), 61 deletions(-) diff --git a/src/zm_monitor.cpp b/src/zm_monitor.cpp index d5865a842..bc7ee0484 100644 --- a/src/zm_monitor.cpp +++ b/src/zm_monitor.cpp @@ -1839,6 +1839,12 @@ bool Monitor::Analyse() { packetqueue.increment_it(analysis_it); return false; } + // Ready means that we have captured the warmup # of frames + if (!Ready()) { + Debug(3, "Not ready?"); + delete packet_lock; + return false; + } // signal is set by capture bool signal = shared_data->signal; @@ -1853,54 +1859,36 @@ bool Monitor::Analyse() { // if we have been told to be OFF, then we are off and don't do any processing. if (trigger_data->trigger_state != TriggerState::TRIGGER_OFF) { Debug(4, "Trigger not OFF state is (%d)", int(trigger_data->trigger_state)); - // Ready means that we have captured the warmup # of frames - if (!Ready()) { - Debug(3, "Not ready?"); - delete packet_lock; - return false; - } int score = 0; std::string cause; Event::StringSetMap noteSetMap; #ifdef WITH_GSOAP - if (ONVIF_Trigger_State) { - score += 9; - Debug(1, "Triggered on ONVIF"); - if (!event) { + if (onvif_event_listener && ONVIF_Healthy) { + if (ONVIF_Trigger_State) { + score += 9; + Debug(1, "Triggered on ONVIF"); Event::StringSet noteSet; noteSet.insert("ONVIF2"); noteSetMap[MOTION_CAUSE] = noteSet; - - event = openEvent(snap, "ONVIF", noteSetMap); cause += "ONVIF"; - } else { - event->addNote(MOTION_CAUSE, "ONVIF2"); -// Add to cause - } - // Regardless of previous state, we go to ALARM - shared_data->state = state = ALARM; - //If the camera isn't going to send an event close, we need to close it here, but only after it has actually triggered an alarm. - if (!ONVIF_Closes_Event && state == ALARM) - ONVIF_Trigger_State = FALSE; - } // end ONVIF_Trigger + //If the camera isn't going to send an event close, we need to close it here, but only after it has actually triggered an alarm. + if (!ONVIF_Closes_Event && state == ALARM) + ONVIF_Trigger_State = FALSE; + } // end ONVIF_Trigger + } // end if (onvif_event_listener && ONVIF_Healthy) #endif - // Specifically told to be on. Setting the score here will trigger the alarm. + // Specifically told to be on. Setting the score here is not enough to trigger the alarm. Must jump directly to ALARM if (trigger_data->trigger_state == TriggerState::TRIGGER_ON) { score += trigger_data->trigger_score; Debug(1, "Triggered on score += %d => %d", trigger_data->trigger_score, score); - if (!event) { - Event::StringSet noteSet; - noteSet.insert(trigger_data->trigger_text); - noteSetMap[trigger_data->trigger_cause] = noteSet; - event = openEvent(snap, trigger_data->trigger_cause, noteSetMap); - Info("%s: %03d - Opening new event %" PRIu64 ", alarm start", name.c_str(), analysis_image_count, event->Id()); - } else { - event->addNote(trigger_data->trigger_cause, trigger_data->trigger_text); - // Need to know if we should end the previous and start a new one, or just add the data - } + if (!cause.empty()) cause += ", "; + cause += trigger_data->trigger_cause; + Event::StringSet noteSet; + noteSet.insert(trigger_data->trigger_text); + noteSetMap[trigger_data->trigger_cause] = noteSet; shared_data->state = state = ALARM; } // end if trigger_on @@ -1968,14 +1956,21 @@ bool Monitor::Analyse() { /* try to stay behind the decoder. */ if (decoding_enabled) { - if (!snap->decoded and !zm_terminate and !analysis_thread->Stopped()) { + while (!snap->decoded and !zm_terminate and !analysis_thread->Stopped()) { // Need to wait for the decoder thread. + // decoder thread might be waiting on the lock for this packet. + // So we need to relinquish the lock and wait. Waiting automatically relinquishes the lock + // So... Debug(1, "Waiting for decode"); - packetqueue.unlock(packet_lock); // This will delete packet_lock and notify_all - packetqueue.wait(); - // Everything may have changed, just return and start again. This needs to be more RAII - return true; + packet_lock->wait(); + //packetqueue.unlock(packet_lock); // This will delete packet_lock and notify_all + //packetqueue.wait(); + ////packet_lock->lock(); } // end while ! decoded + if (zm_terminate or analysis_thread->Stopped()) { + delete packet_lock; + return false; + } } // end if decoding enabled if (Active() and (function == MODECT or function == MOCORD)) { @@ -1990,7 +1985,6 @@ bool Monitor::Analyse() { } if (snap->image) { - // decoder may not have been able to provide an image if (!ref_image.Buffer()) { Debug(1, "Assigning instead of Detecting"); @@ -2024,8 +2018,9 @@ bool Monitor::Analyse() { if (snap->score) { if (cause.length()) cause += ", "; - cause += MOTION_CAUSE+std::string(":")+snap->alarm_cause; + cause += MOTION_CAUSE + std::string(":") + snap->alarm_cause; noteSetMap[MOTION_CAUSE] = zoneSet; + score += snap->score; } // end if motion_score } else { Debug(1, "Skipped motion detection last motion score was %d", last_motion_score); @@ -2069,13 +2064,15 @@ bool Monitor::Analyse() { Info("%s: %03d - Opened new event %" PRIu64 ", continuous section start", name.c_str(), analysis_image_count, event->Id()); /* To prevent cancelling out an existing alert\prealarm\alarm state */ + // This ignores current score status. This should all come after the state machine calculations if (state == IDLE) { shared_data->state = state = TAPE; } } // end if ! event } // end if RECORDING - if ((snap->score > 0) and (function != MONITOR)) { + // If motion detecting, score will be > 0 on motion, but if skipping frames, might not be. So also test snap->score + if ((score > 0) or ((snap->score > 0) and (function != MONITOR))) { if ((state == IDLE) || (state == TAPE) || (state == PREALARM)) { // If we should end then previous continuous event and start a new non-continuous event if (event && event->Frames() @@ -2133,8 +2130,8 @@ bool Monitor::Analyse() { if (state == ALARM) { last_alarm_count = analysis_image_count; } // This is needed so post_event_count counts after last alarmed frames while in ALARM not single alarmed frames while ALERT - } else if (!score and snap->score == 0) { // snap->score means -1 which means didn't do motion detection so don't do state transition - Debug(1, "!score"); + } else if (!score and (snap->score == 0)) { // snap->score means -1 which means didn't do motion detection so don't do state transition + Debug(1, "!score %s", State_Strings[state].c_str()); alert_to_alarm_frame_count = alarm_frame_count; // load same value configured for alarm_frame_count if (state == ALARM) { @@ -2238,17 +2235,17 @@ bool Monitor::Analyse() { // In the case where people have pre-alarm frames, the web ui will generate the frame images // from the mp4. So no one will notice anyways. if (snap->image and (videowriter == PASSTHROUGH)) { - if (!savejpegs) { - Debug(1, "Deleting image data for %d", snap->image_index); - // Don't need raw images anymore - delete snap->image; - snap->image = nullptr; - } - if (snap->analysis_image and !(savejpegs & 2)) { - Debug(1, "Deleting analysis image data for %d", snap->image_index); - delete snap->analysis_image; - snap->analysis_image = nullptr; - } + if (!savejpegs) { + Debug(1, "Deleting image data for %d", snap->image_index); + // Don't need raw images anymore + delete snap->image; + snap->image = nullptr; + } + if (snap->analysis_image and !(savejpegs & 2)) { + Debug(1, "Deleting analysis image data for %d", snap->image_index); + delete snap->analysis_image; + snap->analysis_image = nullptr; + } } packetqueue.clearPackets(snap); @@ -2571,7 +2568,8 @@ bool Monitor::Decode() { std::shared_ptr packet = packet_lock->packet_; if (packet->codec_type != AVMEDIA_TYPE_VIDEO) { Debug(4, "Not video"); - packetqueue.unlock(packet_lock); + //packetqueue.unlock(packet_lock); + delete packet_lock; return true; // Don't need decode } @@ -2677,24 +2675,31 @@ bool Monitor::Decode() { capture_image->Deinterlace_Blend(); } else if (deinterlacing_value == 4) { while (!zm_terminate) { + // ICON FIXME SHould we not clone decoder_it? ZMLockedPacket *deinterlace_packet_lock = packetqueue.get_packet(decoder_it); if (!deinterlace_packet_lock) { - packetqueue.unlock(packet_lock); + delete packet_lock; + //packetqueue.unlock(packet_lock); return false; } if (deinterlace_packet_lock->packet_->codec_type == packet->codec_type) { capture_image->Deinterlace_4Field(deinterlace_packet_lock->packet_->image, (deinterlacing>>8)&0xff); - packetqueue.unlock(deinterlace_packet_lock); + delete deinterlace_packet_lock; + //packetqueue.unlock(deinterlace_packet_lock); break; } - packetqueue.unlock(deinterlace_packet_lock); + delete deinterlace_packet_lock; + //packetqueue.unlock(deinterlace_packet_lock); packetqueue.increment_it(decoder_it); } - if (zm_terminate) return false; + if (zm_terminate) { + delete packet_lock; + return false; + } } else if (deinterlacing_value == 5) { capture_image->Deinterlace_Blend_CustomRatio((deinterlacing>>8)&0xff); } - } + } // end if deinterlacing_value if (orientation != ROTATE_0) { Debug(3, "Doing rotation"); @@ -2731,7 +2736,8 @@ bool Monitor::Decode() { shared_data->signal = (capture_image and signal_check_points) ? CheckSignal(capture_image) : true; shared_data->last_write_index = index; shared_data->last_write_time = std::chrono::system_clock::to_time_t(packet->timestamp); - packetqueue.unlock(packet_lock); + delete packet_lock; + //packetqueue.unlock(packet_lock); return true; } // end bool Monitor::Decode() From 8b99b15b41b56e56d66ad37f48fc8616d64d3c77 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 14 Jan 2022 14:17:07 -0500 Subject: [PATCH 4/7] Use a scope to shorten the lock on event_lock --- src/zm_monitor.cpp | 702 +++++++++++++++++++++++---------------------- 1 file changed, 352 insertions(+), 350 deletions(-) diff --git a/src/zm_monitor.cpp b/src/zm_monitor.cpp index bc7ee0484..e8b1bb1c0 100644 --- a/src/zm_monitor.cpp +++ b/src/zm_monitor.cpp @@ -1853,384 +1853,386 @@ bool Monitor::Analyse() { Debug(3, "Motion detection is enabled signal(%d) signal_change(%d) trigger state(%s) image index %d", signal, signal_change, TriggerState_Strings[trigger_data->trigger_state].c_str(), snap->image_index); - // Need to guard around event creation/deletion from Reload() - std::lock_guard lck(event_mutex); + { // scope for event lock + // Need to guard around event creation/deletion from Reload() + std::lock_guard lck(event_mutex); - // if we have been told to be OFF, then we are off and don't do any processing. - if (trigger_data->trigger_state != TriggerState::TRIGGER_OFF) { - Debug(4, "Trigger not OFF state is (%d)", int(trigger_data->trigger_state)); + // if we have been told to be OFF, then we are off and don't do any processing. + if (trigger_data->trigger_state != TriggerState::TRIGGER_OFF) { + Debug(4, "Trigger not OFF state is (%d)", int(trigger_data->trigger_state)); - int score = 0; - std::string cause; - Event::StringSetMap noteSetMap; + int score = 0; + std::string cause; + Event::StringSetMap noteSetMap; #ifdef WITH_GSOAP - if (onvif_event_listener && ONVIF_Healthy) { - if (ONVIF_Trigger_State) { - score += 9; - Debug(1, "Triggered on ONVIF"); - Event::StringSet noteSet; - noteSet.insert("ONVIF2"); - noteSetMap[MOTION_CAUSE] = noteSet; - cause += "ONVIF"; - //If the camera isn't going to send an event close, we need to close it here, but only after it has actually triggered an alarm. - if (!ONVIF_Closes_Event && state == ALARM) - ONVIF_Trigger_State = FALSE; - } // end ONVIF_Trigger - } // end if (onvif_event_listener && ONVIF_Healthy) + if (onvif_event_listener && ONVIF_Healthy) { + if (ONVIF_Trigger_State) { + score += 9; + Debug(1, "Triggered on ONVIF"); + Event::StringSet noteSet; + noteSet.insert("ONVIF2"); + noteSetMap[MOTION_CAUSE] = noteSet; + cause += "ONVIF"; + //If the camera isn't going to send an event close, we need to close it here, but only after it has actually triggered an alarm. + if (!ONVIF_Closes_Event && state == ALARM) + ONVIF_Trigger_State = FALSE; + } // end ONVIF_Trigger + } // end if (onvif_event_listener && ONVIF_Healthy) #endif - // Specifically told to be on. Setting the score here is not enough to trigger the alarm. Must jump directly to ALARM - if (trigger_data->trigger_state == TriggerState::TRIGGER_ON) { - score += trigger_data->trigger_score; - Debug(1, "Triggered on score += %d => %d", trigger_data->trigger_score, score); - if (!cause.empty()) cause += ", "; - cause += trigger_data->trigger_cause; - Event::StringSet noteSet; - noteSet.insert(trigger_data->trigger_text); - noteSetMap[trigger_data->trigger_cause] = noteSet; - shared_data->state = state = ALARM; - } // end if trigger_on + // Specifically told to be on. Setting the score here is not enough to trigger the alarm. Must jump directly to ALARM + if (trigger_data->trigger_state == TriggerState::TRIGGER_ON) { + score += trigger_data->trigger_score; + Debug(1, "Triggered on score += %d => %d", trigger_data->trigger_score, score); + if (!cause.empty()) cause += ", "; + cause += trigger_data->trigger_cause; + Event::StringSet noteSet; + noteSet.insert(trigger_data->trigger_text); + noteSetMap[trigger_data->trigger_cause] = noteSet; + shared_data->state = state = ALARM; + } // end if trigger_on - // 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); - if (!signal) { - if (event) { - event->addNote(SIGNAL_CAUSE, "Lost"); - Info("%s: %03d - Closing event %" PRIu64 ", signal loss", name.c_str(), analysis_image_count, event->Id()); - closeEvent(); + // 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); + if (!signal) { + if (event) { + event->addNote(SIGNAL_CAUSE, "Lost"); + Info("%s: %03d - Closing event %" PRIu64 ", signal loss", name.c_str(), analysis_image_count, event->Id()); + closeEvent(); + } + } else if (function == MOCORD or function == RECORD) { + if (!event) { + if (!cause.empty()) cause += ", "; + cause += SIGNAL_CAUSE + std::string(": Reacquired"); + } else { + event->addNote(SIGNAL_CAUSE, "Reacquired"); + } + if (snap->image) + ref_image.Assign(*(snap->image)); } - } else if (function == MOCORD or function == RECORD) { - if (!event) { - if (!cause.empty()) cause += ", "; - cause += SIGNAL_CAUSE + std::string(": Reacquired"); - } else { - event->addNote(SIGNAL_CAUSE, "Reacquired"); - } - if (snap->image) - ref_image.Assign(*(snap->image)); - } - shared_data->state = state = IDLE; - shared_data->active = signal; - } // end if signal change + shared_data->state = state = IDLE; + shared_data->active = signal; + } // end if signal change - if (signal) { - if (snap->codec_type == AVMEDIA_TYPE_VIDEO) { - // Check to see if linked monitors are triggering. - if (n_linked_monitors > 0) { - Debug(1, "Checking linked monitors"); - // FIXME improve logic here - bool first_link = true; - Event::StringSet noteSet; - for (int i = 0; i < n_linked_monitors; i++) { - // TODO: Shouldn't we try to connect? - if (linked_monitors[i]->isConnected()) { - Debug(1, "Linked monitor %d %s is connected", - linked_monitors[i]->Id(), linked_monitors[i]->Name()); - if (linked_monitors[i]->hasAlarmed()) { - Debug(1, "Linked monitor %d %s is alarmed", + if (signal) { + if (snap->codec_type == AVMEDIA_TYPE_VIDEO) { + // Check to see if linked monitors are triggering. + if (n_linked_monitors > 0) { + Debug(1, "Checking linked monitors"); + // FIXME improve logic here + bool first_link = true; + Event::StringSet noteSet; + for (int i = 0; i < n_linked_monitors; i++) { + // TODO: Shouldn't we try to connect? + if (linked_monitors[i]->isConnected()) { + Debug(1, "Linked monitor %d %s is connected", linked_monitors[i]->Id(), linked_monitors[i]->Name()); - if (!event) { - if (first_link) { - if (cause.length()) - cause += ", "; - cause += LINKED_CAUSE; - first_link = false; + if (linked_monitors[i]->hasAlarmed()) { + Debug(1, "Linked monitor %d %s is alarmed", + linked_monitors[i]->Id(), linked_monitors[i]->Name()); + if (!event) { + if (first_link) { + if (cause.length()) + cause += ", "; + cause += LINKED_CAUSE; + first_link = false; + } + } + noteSet.insert(linked_monitors[i]->Name()); + score += linked_monitors[i]->lastFrameScore(); // 50; + } else { + Debug(1, "Linked monitor %d %s is not alarmed", + linked_monitors[i]->Id(), linked_monitors[i]->Name()); + } + } else { + Debug(1, "Linked monitor %d %d is not connected. Connecting.", i, linked_monitors[i]->Id()); + linked_monitors[i]->connect(); + } + } // end foreach linked_monitor + if (noteSet.size() > 0) + noteSetMap[LINKED_CAUSE] = noteSet; + } // end if linked_monitors + + /* try to stay behind the decoder. */ + if (decoding_enabled) { + while (!snap->decoded and !zm_terminate and !analysis_thread->Stopped()) { + // Need to wait for the decoder thread. + // decoder thread might be waiting on the lock for this packet. + // So we need to relinquish the lock and wait. Waiting automatically relinquishes the lock + // So... + Debug(1, "Waiting for decode"); + packet_lock->wait(); + //packetqueue.unlock(packet_lock); // This will delete packet_lock and notify_all + //packetqueue.wait(); + ////packet_lock->lock(); + } // end while ! decoded + if (zm_terminate or analysis_thread->Stopped()) { + delete packet_lock; + return false; + } + } // end if decoding enabled + + if (Active() and (function == MODECT or function == MOCORD)) { + Debug(3, "signal and active and modect"); + Event::StringSet zoneSet; + + if (analysis_fps_limit) { + double capture_fps = get_capture_fps(); + motion_frame_skip = capture_fps / analysis_fps_limit; + Debug(1, "Recalculating motion_frame_skip (%d) = capture_fps(%f) / analysis_fps(%f)", + motion_frame_skip, capture_fps, analysis_fps_limit); + } + + 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)); + alarm_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. + snap->score = DetectMotion(*(snap->image), zoneSet); + + if (!snap->analysis_image) + snap->analysis_image = new Image(*(snap->image)); + // 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()); + if (zone.AlarmImage()) + snap->analysis_image->Overlay(*(zone.AlarmImage())); } } - noteSet.insert(linked_monitors[i]->Name()); - score += linked_monitors[i]->lastFrameScore(); // 50; + alarm_image.Assign(*(snap->analysis_image)); + Debug(3, "After motion detection, score:%d last_motion_score(%d), new motion score(%d)", + score, last_motion_score, snap->score); + motion_frame_count += 1; + last_motion_score = snap->score; + + if (snap->score) { + if (cause.length()) cause += ", "; + cause += MOTION_CAUSE + std::string(":") + snap->alarm_cause; + noteSetMap[MOTION_CAUSE] = zoneSet; + score += snap->score; + } // end if motion_score } else { - Debug(1, "Linked monitor %d %s is not alarmed", - linked_monitors[i]->Id(), linked_monitors[i]->Name()); + Debug(1, "Skipped motion detection last motion score was %d", last_motion_score); + alarm_image.Assign(*(snap->image)); } } else { - Debug(1, "Linked monitor %d %d is not connected. Connecting.", i, linked_monitors[i]->Id()); - linked_monitors[i]->connect(); - } - } // end foreach linked_monitor - if (noteSet.size() > 0) - noteSetMap[LINKED_CAUSE] = noteSet; - } // end if linked_monitors - - /* try to stay behind the decoder. */ - if (decoding_enabled) { - while (!snap->decoded and !zm_terminate and !analysis_thread->Stopped()) { - // Need to wait for the decoder thread. - // decoder thread might be waiting on the lock for this packet. - // So we need to relinquish the lock and wait. Waiting automatically relinquishes the lock - // So... - Debug(1, "Waiting for decode"); - packet_lock->wait(); - //packetqueue.unlock(packet_lock); // This will delete packet_lock and notify_all - //packetqueue.wait(); - ////packet_lock->lock(); - } // end while ! decoded - if (zm_terminate or analysis_thread->Stopped()) { - delete packet_lock; - return false; - } - } // end if decoding enabled - - if (Active() and (function == MODECT or function == MOCORD)) { - Debug(3, "signal and active and modect"); - Event::StringSet zoneSet; - - if (analysis_fps_limit) { - double capture_fps = get_capture_fps(); - motion_frame_skip = capture_fps / analysis_fps_limit; - Debug(1, "Recalculating motion_frame_skip (%d) = capture_fps(%f) / analysis_fps(%f)", - motion_frame_skip, capture_fps, analysis_fps_limit); - } - - 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)); - alarm_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. - snap->score = DetectMotion(*(snap->image), zoneSet); - - if (!snap->analysis_image) - snap->analysis_image = new Image(*(snap->image)); - // 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()); - if (zone.AlarmImage()) - snap->analysis_image->Overlay(*(zone.AlarmImage())); - } - } - alarm_image.Assign(*(snap->analysis_image)); - Debug(3, "After motion detection, score:%d last_motion_score(%d), new motion score(%d)", - score, last_motion_score, snap->score); - motion_frame_count += 1; - last_motion_score = snap->score; - - if (snap->score) { - if (cause.length()) cause += ", "; - cause += MOTION_CAUSE + std::string(":") + snap->alarm_cause; - noteSetMap[MOTION_CAUSE] = zoneSet; - score += snap->score; - } // end if motion_score - } else { - Debug(1, "Skipped motion detection last motion score was %d", last_motion_score); - alarm_image.Assign(*(snap->image)); - } + Debug(1, "no image so skipping motion detection"); + } // end if has image + //score += last_motion_score; } else { - Debug(1, "no image so skipping motion detection"); - } // end if has image -//score += last_motion_score; - } else { - Debug(1, "Not Active(%d) enabled %d shared->active %d doing motion detection: %d", - Active(), enabled, shared_data->active, - (function == MODECT or function == MOCORD) - ); - } // end if active and doing motion detection + Debug(1, "Not Active(%d) enabled %d shared->active %d doing motion detection: %d", + Active(), enabled, shared_data->active, + (function == MODECT or function == MOCORD) + ); + } // 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) { - Debug(2, "Have event %" PRIu64 " in record", event->Id()); + if (function == RECORD or function == MOCORD) { + // If doing record, check to see if we need to close the event or not. + if (event) { + Debug(2, "Have event %" PRIu64 " in record", event->Id()); - if (section_length != Seconds(0) && (snap->timestamp - event->StartTime() >= section_length) - && ((function == MOCORD && event_close_mode != CLOSE_TIME) - || (function == RECORD && event_close_mode == CLOSE_TIME) - || std::chrono::duration_cast(snap->timestamp.time_since_epoch()) % section_length == Seconds(0))) { - Info("%s: %03d - Closing event %" PRIu64 ", section end forced %" PRIi64 " - %" PRIi64 " = %" PRIi64 " >= %" PRIi64 , - name.c_str(), - image_count, - event->Id(), - static_cast(std::chrono::duration_cast(snap->timestamp.time_since_epoch()).count()), - static_cast(std::chrono::duration_cast(event->StartTime().time_since_epoch()).count()), - static_cast(std::chrono::duration_cast(snap->timestamp - event->StartTime()).count()), - static_cast(Seconds(section_length).count())); - closeEvent(); - } // end if section_length - } // end if event - - if (!event) { - event = openEvent(snap, cause.empty() ? "Continuous" : cause, noteSetMap); - - Info("%s: %03d - Opened new event %" PRIu64 ", continuous section start", - name.c_str(), analysis_image_count, event->Id()); - /* To prevent cancelling out an existing alert\prealarm\alarm state */ - // This ignores current score status. This should all come after the state machine calculations - if (state == IDLE) { - shared_data->state = state = TAPE; - } - } // end if ! event - } // end if RECORDING - - // If motion detecting, score will be > 0 on motion, but if skipping frames, might not be. So also test snap->score - if ((score > 0) or ((snap->score > 0) and (function != MONITOR))) { - if ((state == IDLE) || (state == TAPE) || (state == PREALARM)) { - // If we should end then previous continuous event and start a new non-continuous event - if (event && event->Frames() - && !event->AlarmFrames() - && (event_close_mode == CLOSE_ALARM) - // FIXME since we won't be including this snap in the event if we close it, we should be looking at event->duration() instead - && ((snap->timestamp - event->StartTime()) >= min_section_length) - && ((!pre_event_count) || (Event::PreAlarmCount() >= alarm_frame_count - 1))) { - Info("%s: %03d - Closing event %" PRIu64 ", continuous end, alarm begins", - name.c_str(), image_count, event->Id()); - closeEvent(); - } else if (event) { - // This is so if we need more than 1 alarm frame before going into alarm, so it is basically if we have enough alarm frames - Debug(3, - "pre_alarm_count in event %d of %d, event frames %d, alarm frames %d event length %" PRIi64 " >=? %" PRIi64 " min close mode is ALARM? %d", - Event::PreAlarmCount(), pre_event_count, - event->Frames(), - event->AlarmFrames(), - static_cast(std::chrono::duration_cast(snap->timestamp - event->StartTime()).count()), - static_cast(Seconds(min_section_length).count()), - (event_close_mode == CLOSE_ALARM)); - } - if ((!pre_event_count) || (Event::PreAlarmCount() >= alarm_frame_count-1)) { - Info("%s: %03d - Gone into alarm state PreAlarmCount: %u > AlarmFrameCount:%u Cause:%s", - name.c_str(), image_count, Event::PreAlarmCount(), alarm_frame_count, cause.c_str()); - - if (!event) { - event = openEvent(snap, cause, noteSetMap); - Info("%s: %03d - Opening new event %" PRIu64 ", alarm start", name.c_str(), analysis_image_count, event->Id()); - } // end if no event, so start it - shared_data->state = state = ALARM; - if (alarm_frame_count) { - Debug(1, "alarm frame count so SavePreAlarmFrames"); - event->SavePreAlarmFrames(); - } - } else if (state != PREALARM) { - Info("%s: %03d - Gone into prealarm state", name.c_str(), analysis_image_count); - shared_data->state = state = PREALARM; - } - } else if (state == ALERT) { - alert_to_alarm_frame_count--; - Info("%s: %03d - Alarmed frame while in alert state. Consecutive alarmed frames left to return to alarm state: %03d", - name.c_str(), analysis_image_count, alert_to_alarm_frame_count); - if (alert_to_alarm_frame_count == 0) { - Info("%s: %03d - Gone back into alarm state", name.c_str(), analysis_image_count); - shared_data->state = state = ALARM; - } - } else if (state == TAPE) { - // Already recording, but IDLE so switch to ALARM - shared_data->state = state = ALARM; - Debug(1, "Was in TAPE, going into ALARM"); - } else { - Debug(1, "Staying in %s", State_Strings[state].c_str()); - } - if (state == ALARM) { - last_alarm_count = analysis_image_count; - } // This is needed so post_event_count counts after last alarmed frames while in ALARM not single alarmed frames while ALERT - } else if (!score and (snap->score == 0)) { // snap->score means -1 which means didn't do motion detection so don't do state transition - Debug(1, "!score %s", State_Strings[state].c_str()); - alert_to_alarm_frame_count = alarm_frame_count; // load same value configured for alarm_frame_count - - if (state == ALARM) { - Info("%s: %03d - Gone into alert state", name.c_str(), analysis_image_count); - shared_data->state = state = ALERT; - } else if (state == ALERT) { - if ( - ((analysis_image_count - last_alarm_count) > post_event_count) - && - ((snap->timestamp - event->StartTime()) >= min_section_length)) { - Info("%s: %03d - Left alarm state (%" PRIu64 ") - %d(%d) images", - name.c_str(), analysis_image_count, event->Id(), event->Frames(), event->AlarmFrames()); - if ( - (function != RECORD && function != MOCORD) - || - (event_close_mode == CLOSE_ALARM || event_close_mode==CLOSE_IDLE) - ) { - shared_data->state = state = IDLE; - Info("%s: %03d - Closing event %" PRIu64 ", alarm end%s", - name.c_str(), analysis_image_count, event->Id(), (function==MOCORD)?", section truncated":"" ); + if (section_length != Seconds(0) && (snap->timestamp - event->StartTime() >= section_length) + && ((function == MOCORD && event_close_mode != CLOSE_TIME) + || (function == RECORD && event_close_mode == CLOSE_TIME) + || std::chrono::duration_cast(snap->timestamp.time_since_epoch()) % section_length == Seconds(0))) { + Info("%s: %03d - Closing event %" PRIu64 ", section end forced %" PRIi64 " - %" PRIi64 " = %" PRIi64 " >= %" PRIi64 , + name.c_str(), + image_count, + event->Id(), + static_cast(std::chrono::duration_cast(snap->timestamp.time_since_epoch()).count()), + static_cast(std::chrono::duration_cast(event->StartTime().time_since_epoch()).count()), + static_cast(std::chrono::duration_cast(snap->timestamp - event->StartTime()).count()), + static_cast(Seconds(section_length).count())); closeEvent(); - } else { + } // end if section_length + } // end if event + + if (!event) { + event = openEvent(snap, cause.empty() ? "Continuous" : cause, noteSetMap); + + Info("%s: %03d - Opened new event %" PRIu64 ", continuous section start", + name.c_str(), analysis_image_count, event->Id()); + /* To prevent cancelling out an existing alert\prealarm\alarm state */ + // This ignores current score status. This should all come after the state machine calculations + if (state == IDLE) { shared_data->state = state = TAPE; } + } // end if ! event + } // end if RECORDING + + // If motion detecting, score will be > 0 on motion, but if skipping frames, might not be. So also test snap->score + if ((score > 0) or ((snap->score > 0) and (function != MONITOR))) { + if ((state == IDLE) || (state == TAPE) || (state == PREALARM)) { + // If we should end then previous continuous event and start a new non-continuous event + if (event && event->Frames() + && !event->AlarmFrames() + && (event_close_mode == CLOSE_ALARM) + // FIXME since we won't be including this snap in the event if we close it, we should be looking at event->duration() instead + && ((snap->timestamp - event->StartTime()) >= min_section_length) + && ((!pre_event_count) || (Event::PreAlarmCount() >= alarm_frame_count - 1))) { + Info("%s: %03d - Closing event %" PRIu64 ", continuous end, alarm begins", + name.c_str(), image_count, event->Id()); + closeEvent(); + } else if (event) { + // This is so if we need more than 1 alarm frame before going into alarm, so it is basically if we have enough alarm frames + Debug(3, + "pre_alarm_count in event %d of %d, event frames %d, alarm frames %d event length %" PRIi64 " >=? %" PRIi64 " min close mode is ALARM? %d", + Event::PreAlarmCount(), pre_event_count, + event->Frames(), + event->AlarmFrames(), + static_cast(std::chrono::duration_cast(snap->timestamp - event->StartTime()).count()), + static_cast(Seconds(min_section_length).count()), + (event_close_mode == CLOSE_ALARM)); + } + if ((!pre_event_count) || (Event::PreAlarmCount() >= alarm_frame_count-1)) { + Info("%s: %03d - Gone into alarm state PreAlarmCount: %u > AlarmFrameCount:%u Cause:%s", + name.c_str(), image_count, Event::PreAlarmCount(), alarm_frame_count, cause.c_str()); + + if (!event) { + event = openEvent(snap, cause, noteSetMap); + Info("%s: %03d - Opening new event %" PRIu64 ", alarm start", name.c_str(), analysis_image_count, event->Id()); + } // end if no event, so start it + shared_data->state = state = ALARM; + if (alarm_frame_count) { + Debug(1, "alarm frame count so SavePreAlarmFrames"); + event->SavePreAlarmFrames(); + } + } else if (state != PREALARM) { + Info("%s: %03d - Gone into prealarm state", name.c_str(), analysis_image_count); + shared_data->state = state = PREALARM; + } + } else if (state == ALERT) { + alert_to_alarm_frame_count--; + Info("%s: %03d - Alarmed frame while in alert state. Consecutive alarmed frames left to return to alarm state: %03d", + name.c_str(), analysis_image_count, alert_to_alarm_frame_count); + if (alert_to_alarm_frame_count == 0) { + Info("%s: %03d - Gone back into alarm state", name.c_str(), analysis_image_count); + shared_data->state = state = ALARM; + } + } else if (state == TAPE) { + // Already recording, but IDLE so switch to ALARM + shared_data->state = state = ALARM; + Debug(1, "Was in TAPE, going into ALARM"); + } else { + Debug(1, "Staying in %s", State_Strings[state].c_str()); } - } else if (state == PREALARM) { - // Back to IDLE - shared_data->state = state = ((function != MOCORD) ? IDLE : TAPE); - } else { - Debug(1, - "State %d %s because analysis_image_count(%d)-last_alarm_count(%d) > post_event_count(%d) and timestamp.tv_sec(%" PRIi64 ") - recording.tv_src(%" PRIi64 ") >= min_section_length(%" PRIi64 ")", - state, - State_Strings[state].c_str(), - analysis_image_count, - last_alarm_count, - post_event_count, - static_cast(std::chrono::duration_cast(snap->timestamp.time_since_epoch()).count()), - static_cast(std::chrono::duration_cast(GetVideoWriterStartTime().time_since_epoch()).count()), - static_cast(Seconds(min_section_length).count())); - } - if (Event::PreAlarmCount()) - Event::EmptyPreAlarmFrames(); - } // end if score or not + if (state == ALARM) { + last_alarm_count = analysis_image_count; + } // This is needed so post_event_count counts after last alarmed frames while in ALARM not single alarmed frames while ALERT + } else if (!score and (snap->score == 0)) { // snap->score means -1 which means didn't do motion detection so don't do state transition + Debug(1, "!score %s", State_Strings[state].c_str()); + alert_to_alarm_frame_count = alarm_frame_count; // load same value configured for alarm_frame_count - if (score > snap->score) - snap->score = score; + if (state == ALARM) { + Info("%s: %03d - Gone into alert state", name.c_str(), analysis_image_count); + shared_data->state = state = ALERT; + } else if (state == ALERT) { + if ( + ((analysis_image_count - last_alarm_count) > post_event_count) + && + ((snap->timestamp - event->StartTime()) >= min_section_length)) { + Info("%s: %03d - Left alarm state (%" PRIu64 ") - %d(%d) images", + name.c_str(), analysis_image_count, event->Id(), event->Frames(), event->AlarmFrames()); + if ( + (function != RECORD && function != MOCORD) + || + (event_close_mode == CLOSE_ALARM || event_close_mode==CLOSE_IDLE) + ) { + shared_data->state = state = IDLE; + Info("%s: %03d - Closing event %" PRIu64 ", alarm end%s", + name.c_str(), analysis_image_count, event->Id(), (function==MOCORD)?", section truncated":"" ); + closeEvent(); + } else { + shared_data->state = state = TAPE; + } + } + } else if (state == PREALARM) { + // Back to IDLE + shared_data->state = state = ((function != MOCORD) ? IDLE : TAPE); + } else { + Debug(1, + "State %d %s because analysis_image_count(%d)-last_alarm_count(%d) > post_event_count(%d) and timestamp.tv_sec(%" PRIi64 ") - recording.tv_src(%" PRIi64 ") >= min_section_length(%" PRIi64 ")", + state, + State_Strings[state].c_str(), + analysis_image_count, + last_alarm_count, + post_event_count, + static_cast(std::chrono::duration_cast(snap->timestamp.time_since_epoch()).count()), + static_cast(std::chrono::duration_cast(GetVideoWriterStartTime().time_since_epoch()).count()), + static_cast(Seconds(min_section_length).count())); + } + if (Event::PreAlarmCount()) + Event::EmptyPreAlarmFrames(); + } // end if score or not - if (state == PREALARM) { - // incremement pre alarm image count - Event::AddPreAlarmFrame(snap->image, snap->timestamp, score, nullptr); - } else if (state == ALARM) { - if (event) { - if (noteSetMap.size() > 0) + if (score > snap->score) + snap->score = score; + + if (state == PREALARM) { + // incremement pre alarm image count + Event::AddPreAlarmFrame(snap->image, snap->timestamp, score, nullptr); + } else if (state == ALARM) { + if (event) { + if (noteSetMap.size() > 0) + event->updateNotes(noteSetMap); + if (section_length != Seconds(0) && (snap->timestamp - event->StartTime() >= section_length)) { + Warning("%s: %03d - event %" PRIu64 ", has exceeded desired section length. %" PRIi64 " - %" PRIi64 " = %" PRIi64 " >= %" PRIi64, + name.c_str(), analysis_image_count, event->Id(), + static_cast(std::chrono::duration_cast(snap->timestamp.time_since_epoch()).count()), + static_cast(std::chrono::duration_cast(GetVideoWriterStartTime().time_since_epoch()).count()), + static_cast(std::chrono::duration_cast(snap->timestamp - GetVideoWriterStartTime()).count()), + static_cast(Seconds(section_length).count())); + closeEvent(); + event = openEvent(snap, cause, noteSetMap); + } + } else { + Error("ALARM but no event"); + } + } else if (state == ALERT) { + // Alert means this frame has no motion, but we were alarmed and are still recording. + if ((noteSetMap.size() > 0) and event) event->updateNotes(noteSetMap); - if (section_length != Seconds(0) && (snap->timestamp - event->StartTime() >= section_length)) { - Warning("%s: %03d - event %" PRIu64 ", has exceeded desired section length. %" PRIi64 " - %" PRIi64 " = %" PRIi64 " >= %" PRIi64, - name.c_str(), analysis_image_count, event->Id(), - static_cast(std::chrono::duration_cast(snap->timestamp.time_since_epoch()).count()), - static_cast(std::chrono::duration_cast(GetVideoWriterStartTime().time_since_epoch()).count()), - static_cast(std::chrono::duration_cast(snap->timestamp - GetVideoWriterStartTime()).count()), - static_cast(Seconds(section_length).count())); - closeEvent(); - event = openEvent(snap, cause, noteSetMap); + } else if (state == TAPE) { + // bulk frame code moved to event. + } // end if state machine + + if ((function == MODECT or function == MOCORD) and snap->image) { + if (!ref_image.Buffer()) { + Debug(1, "Assigning"); + ref_image.Assign(*(snap->image)); + } else { + Debug(1, "Blending"); + ref_image.Blend(*(snap->image), ( state==ALARM ? alarm_ref_blend_perc : ref_blend_perc )); + Debug(1, "Done Blending"); } - } else { - Error("ALARM but no event"); } - } else if (state == ALERT) { - // Alert means this frame has no motion, but we were alarmed and are still recording. - if ((noteSetMap.size() > 0) and event) - event->updateNotes(noteSetMap); - } else if (state == TAPE) { - // bulk frame code moved to event. - } // end if state machine + last_signal = signal; + } // end if videostream + } // end if signal + shared_data->last_frame_score = score; + } else { + Debug(3, "trigger == off"); + if (event) { + Info("%s: %03d - Closing event %" PRIu64 ", trigger off", name.c_str(), analysis_image_count, event->Id()); + closeEvent(); + } + shared_data->state = state = IDLE; + } // end if ( trigger_data->trigger_state != TRIGGER_OFF ) - if ((function == MODECT or function == MOCORD) and snap->image) { - if (!ref_image.Buffer()) { - Debug(1, "Assigning"); - ref_image.Assign(*(snap->image)); - } else { - Debug(1, "Blending"); - ref_image.Blend(*(snap->image), ( state==ALARM ? alarm_ref_blend_perc : ref_blend_perc )); - Debug(1, "Done Blending"); - } - } - last_signal = signal; - } // end if videostream - } // end if signal - shared_data->last_frame_score = score; - } else { - Debug(3, "trigger == off"); - if (event) { - Info("%s: %03d - Closing event %" PRIu64 ", trigger off", name.c_str(), analysis_image_count, event->Id()); - closeEvent(); - } - shared_data->state = state = IDLE; - } // end if ( trigger_data->trigger_state != TRIGGER_OFF ) - - if (event) event->AddPacket(snap); + if (event) event->AddPacket(snap); + } // end scope for event_lock // In the case where people have pre-alarm frames, the web ui will generate the frame images // from the mp4. So no one will notice anyways. From eb59b4de7f920236520724598afd26e8eb503415 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 14 Jan 2022 14:20:17 -0500 Subject: [PATCH 5/7] Clear out dead code --- src/zm_event.h | 30 ------------------------------ 1 file changed, 30 deletions(-) diff --git a/src/zm_event.h b/src/zm_event.h index be6d922de..74955d23f 100644 --- a/src/zm_event.h +++ b/src/zm_event.h @@ -178,18 +178,6 @@ class Event { return pre_alarm_count; } static void EmptyPreAlarmFrames() { -#if 0 - while ( pre_alarm_count > 0 ) { - int i = pre_alarm_count - 1; - delete pre_alarm_data[i].image; - pre_alarm_data[i].image = nullptr; - if ( pre_alarm_data[i].alarm_frame ) { - delete pre_alarm_data[i].alarm_frame; - pre_alarm_data[i].alarm_frame = nullptr; - } - pre_alarm_count--; - } -#endif pre_alarm_count = 0; } static void AddPreAlarmFrame( @@ -198,28 +186,10 @@ class Event { int score=0, Image *alarm_frame=nullptr ) { -#if 0 - pre_alarm_data[pre_alarm_count].image = new Image(*image); - pre_alarm_data[pre_alarm_count].timestamp = timestamp; - pre_alarm_data[pre_alarm_count].score = score; - if ( alarm_frame ) { - pre_alarm_data[pre_alarm_count].alarm_frame = new Image(*alarm_frame); - } -#endif pre_alarm_count++; } void SavePreAlarmFrames() { -#if 0 - for ( int i = 0; i < pre_alarm_count; i++ ) { - AddFrame( - pre_alarm_data[i].image, - pre_alarm_data[i].timestamp, - pre_alarm_data[i].score, - pre_alarm_data[i].alarm_frame); - } -#endif EmptyPreAlarmFrames(); } }; - #endif // ZM_EVENT_H From 1fe4bbedc0e2e810ec5d036e73d00e9766975636 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 14 Jan 2022 14:35:16 -0500 Subject: [PATCH 6/7] use min_section_length instead of 0 when testing minimumm section length. Use event->Duration instead of snap-event->StartTime because this snap will not be included in the event. This results in events of 29.59 seconds instead of 30 seconds. --- src/zm_monitor.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/zm_monitor.cpp b/src/zm_monitor.cpp index e8b1bb1c0..4a707889f 100644 --- a/src/zm_monitor.cpp +++ b/src/zm_monitor.cpp @@ -2043,7 +2043,7 @@ bool Monitor::Analyse() { if (event) { Debug(2, "Have event %" PRIu64 " in record", event->Id()); - if (section_length != Seconds(0) && (snap->timestamp - event->StartTime() >= section_length) + if (section_length != Seconds(min_section_length) && (event->Duration() >= section_length) && ((function == MOCORD && event_close_mode != CLOSE_TIME) || (function == RECORD && event_close_mode == CLOSE_TIME) || std::chrono::duration_cast(snap->timestamp.time_since_epoch()) % section_length == Seconds(0))) { @@ -2080,7 +2080,7 @@ bool Monitor::Analyse() { && !event->AlarmFrames() && (event_close_mode == CLOSE_ALARM) // FIXME since we won't be including this snap in the event if we close it, we should be looking at event->duration() instead - && ((snap->timestamp - event->StartTime()) >= min_section_length) + && (event->Duration() >= min_section_length) && ((!pre_event_count) || (Event::PreAlarmCount() >= alarm_frame_count - 1))) { Info("%s: %03d - Closing event %" PRIu64 ", continuous end, alarm begins", name.c_str(), image_count, event->Id()); @@ -2092,7 +2092,7 @@ bool Monitor::Analyse() { Event::PreAlarmCount(), pre_event_count, event->Frames(), event->AlarmFrames(), - static_cast(std::chrono::duration_cast(snap->timestamp - event->StartTime()).count()), + static_cast(std::chrono::duration_cast(event->Duration()).count()), static_cast(Seconds(min_section_length).count()), (event_close_mode == CLOSE_ALARM)); } @@ -2142,7 +2142,7 @@ bool Monitor::Analyse() { if ( ((analysis_image_count - last_alarm_count) > post_event_count) && - ((snap->timestamp - event->StartTime()) >= min_section_length)) { + (event->Duration() >= min_section_length)) { Info("%s: %03d - Left alarm state (%" PRIu64 ") - %d(%d) images", name.c_str(), analysis_image_count, event->Id(), event->Frames(), event->AlarmFrames()); if ( @@ -2187,12 +2187,12 @@ bool Monitor::Analyse() { if (event) { if (noteSetMap.size() > 0) event->updateNotes(noteSetMap); - if (section_length != Seconds(0) && (snap->timestamp - event->StartTime() >= section_length)) { + if (section_length != Seconds(min_section_length) && (event->Duration() >= section_length)) { Warning("%s: %03d - event %" PRIu64 ", has exceeded desired section length. %" PRIi64 " - %" PRIi64 " = %" PRIi64 " >= %" PRIi64, name.c_str(), analysis_image_count, event->Id(), static_cast(std::chrono::duration_cast(snap->timestamp.time_since_epoch()).count()), - static_cast(std::chrono::duration_cast(GetVideoWriterStartTime().time_since_epoch()).count()), - static_cast(std::chrono::duration_cast(snap->timestamp - GetVideoWriterStartTime()).count()), + static_cast(std::chrono::duration_cast(event->StartTime().time_since_epoch()).count()), + static_cast(std::chrono::duration_cast(event->Duration()).count()), static_cast(Seconds(section_length).count())); closeEvent(); event = openEvent(snap, cause, noteSetMap); From a4b0aa442a655337c808bde8d0dcabcc0b82851f Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 14 Jan 2022 14:35:26 -0500 Subject: [PATCH 7/7] Introduce event->Duration() --- src/zm_event.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/zm_event.h b/src/zm_event.h index 74955d23f..31a23fad4 100644 --- a/src/zm_event.h +++ b/src/zm_event.h @@ -132,6 +132,7 @@ class Event { SystemTimePoint StartTime() const { return start_time; } SystemTimePoint EndTime() const { return end_time; } + TimePoint::duration Duration() const { return end_time - start_time; }; void AddPacket(const std::shared_ptr &p); void AddPacket_(const std::shared_ptr &p);