diff --git a/db/zm_create.sql.in b/db/zm_create.sql.in index 510a65082..ac4f2fbed 100644 --- a/db/zm_create.sql.in +++ b/db/zm_create.sql.in @@ -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, diff --git a/db/zm_update-1.33.10.sql b/db/zm_update-1.33.10.sql new file mode 100644 index 000000000..8eb8fc548 --- /dev/null +++ b/db/zm_update-1.33.10.sql @@ -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; diff --git a/src/zm_monitor.cpp b/src/zm_monitor.cpp index a33ed81e3..2e875e885 100644 --- a/src/zm_monitor.cpp +++ b/src/zm_monitor.cpp @@ -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 += ", "; @@ -1475,7 +1478,7 @@ bool Monitor::Analyse() { ) { Info("%s: %03d - Closing event %" PRIu64 ", section end forced %d - %d = %d >= %d", name, image_count, event->Id(), - timestamp->tv_sec, video_store_data->recording.tv_sec, + timestamp->tv_sec, video_store_data->recording.tv_sec, timestamp->tv_sec - video_store_data->recording.tv_sec, section_length ); @@ -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); diff --git a/src/zm_monitor.h b/src/zm_monitor.h index f3927144c..c7e406f89 100644 --- a/src/zm_monitor.h +++ b/src/zm_monitor.h @@ -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, diff --git a/version b/version index c64ec5337..b47971c3e 100644 --- a/version +++ b/version @@ -1 +1 @@ -1.33.9 +1.33.10 diff --git a/web/includes/Monitor.php b/web/includes/Monitor.php index cdac2bcca..6e685508c 100644 --- a/web/includes/Monitor.php +++ b/web/includes/Monitor.php @@ -61,6 +61,7 @@ private $defaults = array( 'StreamReplayBuffer' => 0, 'AlarmFrameCount' => 1, 'SectionLength' => 600, + 'MinSectionLength' => 10, 'FrameSkip' => 0, 'AnalysisFPSLimit' => null, 'AnalysisUpdateDelay' => 0, diff --git a/web/skins/classic/views/monitor.php b/web/skins/classic/views/monitor.php index 1430b93bf..1cedd8071 100644 --- a/web/skins/classic/views/monitor.php +++ b/web/skins/classic/views/monitor.php @@ -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' ) { ?> + @@ -1024,6 +1026,13 @@ if ( $monitor->Type() == 'Local' ) { +