End continuous events on alarm (#2644)

* Reference /run/zm instead of /var/run/zm because systemd-tmpfiles complains about it

* Spacing, google code style and tabs to spaces

* add update script to add MinSectionLength

* Add min_section_length to enforce a minimum event length when closing continuous events on alarm
This commit is contained in:
Isaac Connor 2019-06-24 11:29:00 -04:00 committed by GitHub
parent 299f994506
commit 6ed0074077
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 64 additions and 18 deletions

View File

@ -479,6 +479,7 @@ CREATE TABLE `Monitors` (
`StreamReplayBuffer` int(10) unsigned NOT NULL default '1000',
`AlarmFrameCount` smallint(5) unsigned NOT NULL default '1',
`SectionLength` int(10) unsigned NOT NULL default '600',
`MinSectionLength` int(10) unsigned NOT NULL default '10',
`FrameSkip` smallint(5) unsigned NOT NULL default '0',
`MotionFrameSkip` smallint(5) unsigned NOT NULL default '0',
`AnalysisFPSLimit` decimal(5,2) default NULL,

12
db/zm_update-1.33.10.sql Normal file
View File

@ -0,0 +1,12 @@
SET @s = (SELECT IF(
(SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE()
AND table_name = 'Monitors'
AND column_name = 'MinSectionLength'
) > 0,
"SELECT 'Column MinSectionLength already exists in Monitors'",
"ALTER TABLE Monitors ADD `MinSectionLength` int(10) unsigned NOT NULL default '10' AFTER SectionLength"
));
PREPARE stmt FROM @s;
EXECUTE stmt;

View File

@ -78,7 +78,7 @@ std::string load_monitor_sql =
"Brightness, Contrast, Hue, Colour, "
"EventPrefix, LabelFormat, LabelX, LabelY, LabelSize,"
"ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, "
"SectionLength, FrameSkip, MotionFrameSkip, "
"SectionLength, MinSectionLength, FrameSkip, MotionFrameSkip, "
"FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion, Exif, SignalCheckPoints, SignalCheckColour FROM Monitors";
std::string CameraType_Strings[] = {
@ -296,6 +296,7 @@ Monitor::Monitor(
int p_stream_replay_buffer,
int p_alarm_frame_count,
int p_section_length,
int p_min_section_length,
int p_frame_skip,
int p_motion_frame_skip,
double p_analysis_fps,
@ -333,6 +334,7 @@ Monitor::Monitor(
post_event_count( p_post_event_count ),
stream_replay_buffer( p_stream_replay_buffer ),
section_length( p_section_length ),
min_section_length( p_min_section_length ),
frame_skip( p_frame_skip ),
motion_frame_skip( p_motion_frame_skip ),
analysis_fps( p_analysis_fps ),
@ -1411,20 +1413,21 @@ bool Monitor::Analyse() {
shared_data->active = signal;
ref_image = *snap_image;
} else if ( signal && Active() && (function == MODECT || function == MOCORD) ) {
Event::StringSet zoneSet;
if ( (!motion_frame_skip) || !(image_count % (motion_frame_skip+1) ) ) {
// Get new score.
int new_motion_score = DetectMotion(*snap_image, zoneSet);
} else if ( signal ) {
if ( Active() && (function == MODECT || function == MOCORD) ) {
// All is good, so add motion detection score.
Event::StringSet zoneSet;
if ( (!motion_frame_skip) || !(image_count % (motion_frame_skip+1)) ) {
// Get new score.
int new_motion_score = DetectMotion(*snap_image, zoneSet);
Debug(3,
"After motion detection, last_motion_score(%d), new motion score(%d)",
last_motion_score, new_motion_score
);
last_motion_score = new_motion_score;
}
if ( last_motion_score ) {
if ( !event ) {
Debug(3,
"After motion detection, last_motion_score(%d), new motion score(%d)",
last_motion_score, new_motion_score
);
last_motion_score = new_motion_score;
}
if ( last_motion_score ) {
score += last_motion_score;
if ( cause.length() )
cause += ", ";
@ -1555,6 +1558,14 @@ bool Monitor::Analyse() {
if ( score ) {
if ( state == IDLE || state == TAPE || state == PREALARM ) {
if ( (!pre_event_count) || (Event::PreAlarmCount() >= alarm_frame_count) ) {
// If we should end then previous continuous event and start a new non-continuous event
if ( event && event->Frames() && !event->AlarmFrames()
&& ( ( timestamp->tv_sec - video_store_data->recording.tv_sec ) >= min_section_length )
) {
Info("%s: %03d - Closing event %" PRIu64 ", continuous end, alarm begins",
name, image_count, event->Id());
closeEvent();
}
shared_data->state = state = ALARM;
// lets construct alarm cause. It will contain cause + names of zones alarmed
std::string alarm_cause = "";
@ -1811,7 +1822,13 @@ void Monitor::Reload() {
static char sql[ZM_SQL_MED_BUFSIZ];
// This seems to have fallen out of date.
snprintf(sql, sizeof(sql), "select Function+0, Enabled, LinkedMonitors, EventPrefix, LabelFormat, LabelX, LabelY, LabelSize, WarmupCount, PreEventCount, PostEventCount, AlarmFrameCount, SectionLength, FrameSkip, MotionFrameSkip, AnalysisFPSLimit, AnalysisUpdateDelay, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion, SignalCheckColour from Monitors where Id = '%d'", id);
snprintf(sql, sizeof(sql),
"SELECT Function+0, Enabled, LinkedMonitors, EventPrefix, LabelFormat, "
"LabelX, LabelY, LabelSize, WarmupCount, PreEventCount, PostEventCount, "
"AlarmFrameCount, SectionLength, MinSectionLength, FrameSkip, "
"MotionFrameSkip, AnalysisFPSLimit, AnalysisUpdateDelay, MaxFPS, AlarmMaxFPS, "
"FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion, "
"SignalCheckColour FROM Monitors WHERE Id = '%d'", id);
zmDbRow *row = zmDbFetchOne(sql);
if ( !row ) {
@ -1842,6 +1859,7 @@ void Monitor::Reload() {
post_event_count = atoi(dbrow[index++]);
alarm_frame_count = atoi(dbrow[index++]);
section_length = atoi(dbrow[index++]);
min_section_length = atoi(dbrow[index++]);
frame_skip = atoi(dbrow[index++]);
motion_frame_skip = atoi(dbrow[index++]);
analysis_fps = dbrow[index] ? strtod(dbrow[index], NULL) : 0; index++;
@ -2057,7 +2075,7 @@ int Monitor::LoadFfmpegMonitors(const char *file, Monitor **&monitors, Purpose p
"Brightness, Contrast, Hue, Colour, "
"EventPrefix, LabelFormat, LabelX, LabelY, LabelSize,"
"ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, "
"SectionLength, FrameSkip, MotionFrameSkip, "
"SectionLength, MinSectionLength, FrameSkip, MotionFrameSkip, "
"FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion, Exif, SignalCheckColour FROM Monitors";
*/
@ -2138,6 +2156,7 @@ Monitor *Monitor::Load(MYSQL_ROW dbrow, bool load_zones, Purpose purpose) {
int stream_replay_buffer = atoi(dbrow[col]); col++;
int alarm_frame_count = atoi(dbrow[col]); col++;
int section_length = atoi(dbrow[col]); col++;
int min_section_length = atoi(dbrow[col]); col++;
int frame_skip = atoi(dbrow[col]); col++;
int motion_frame_skip = atoi(dbrow[col]); col++;
int fps_report_interval = atoi(dbrow[col]); col++;
@ -2338,6 +2357,7 @@ Monitor *Monitor::Load(MYSQL_ROW dbrow, bool load_zones, Purpose purpose) {
stream_replay_buffer,
alarm_frame_count,
section_length,
min_section_length,
frame_skip,
motion_frame_skip,
analysis_fps,
@ -2813,6 +2833,7 @@ bool Monitor::DumpSettings(char *output, bool verbose) {
sprintf(output+strlen(output), "Stream Replay Buffer : %d\n", stream_replay_buffer );
sprintf(output+strlen(output), "Alarm Frame Count : %d\n", alarm_frame_count );
sprintf(output+strlen(output), "Section Length : %d\n", section_length);
sprintf(output+strlen(output), "Min Section Length : %d\n", min_section_length);
sprintf(output+strlen(output), "Maximum FPS : %.2f\n", capture_delay?(double)DT_PREC_3/capture_delay:0.0);
sprintf(output+strlen(output), "Alarm Maximum FPS : %.2f\n", alarm_capture_delay?(double)DT_PREC_3/alarm_capture_delay:0.0);
sprintf(output+strlen(output), "Reference Blend %%ge : %d\n", ref_blend_perc);

View File

@ -273,6 +273,7 @@ protected:
int post_event_count; // How many unalarmed images must occur before the alarm state is reset
int stream_replay_buffer; // How many frames to store to support DVR functions, IGNORED from this object, passed directly into zms now
int section_length; // How long events should last in continuous modes
int min_section_length; // Minimum event length when using event_close_mode == ALARM
bool adaptive_skip; // Whether to use the newer adaptive algorithm for this monitor
int frame_skip; // How many frames to skip in continuous modes
int motion_frame_skip; // How many frames to skip in motion detection
@ -382,6 +383,7 @@ public:
int p_stream_replay_buffer,
int p_alarm_frame_count,
int p_section_length,
int p_min_section_length,
int p_frame_skip,
int p_motion_frame_skip,
double p_analysis_fps,

View File

@ -1 +1 @@
1.33.9
1.33.10

View File

@ -61,6 +61,7 @@ private $defaults = array(
'StreamReplayBuffer' => 0,
'AlarmFrameCount' => 1,
'SectionLength' => 600,
'MinSectionLength' => 10,
'FrameSkip' => 0,
'AnalysisFPSLimit' => null,
'AnalysisUpdateDelay' => 0,

View File

@ -103,6 +103,7 @@ if ( ! $monitor ) {
'ReturnLocation' => -1,
'ReturnDelay' => '',
'SectionLength' => 600,
'MinSectionLength' => 10,
'FrameSkip' => 0,
'MotionFrameSkip' => 0,
'EventPrefix' => 'Event-',
@ -657,6 +658,7 @@ if ( $tab != 'misc' ) {
?>
<input type="hidden" name="newMonitor[EventPrefix]" value="<?php echo validHtmlStr($monitor->EventPrefix()) ?>"/>
<input type="hidden" name="newMonitor[SectionLength]" value="<?php echo validHtmlStr($monitor->SectionLength()) ?>"/>
<input type="hidden" name="newMonitor[MinSectionLength]" value="<?php echo validHtmlStr($monitor->MinSectionLength()) ?>"/>
<input type="hidden" name="newMonitor[FrameSkip]" value="<?php echo validHtmlStr($monitor->FrameSkip()) ?>"/>
<input type="hidden" name="newMonitor[MotionFrameSkip]" value="<?php echo validHtmlStr($monitor->MotionFrameSkip()) ?>"/>
<input type="hidden" name="newMonitor[AnalysisUpdateDelay]" value="<?php echo validHtmlStr($monitor->AnalysisUpdateDelay()) ?>"/>
@ -1024,6 +1026,13 @@ if ( $monitor->Type() == 'Local' ) {
<?php echo translate('seconds')?>
</td>
</tr>
<tr>
<td><?php echo translate('MinSectionlength') ?></td>
<td>
<input type="number" name="newMonitor[MinSectionLength]" value="<?php echo validHtmlStr($monitor->MinSectionLength()) ?>"/>
<?php echo translate('seconds')?>
</td>
</tr>
<tr>
<td><?php echo translate('FrameSkip') ?></td>
<td>