From 042d4c3099c32180fcea3890c220cd5e850043e5 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Sun, 9 Sep 2018 18:32:00 -0400 Subject: [PATCH 01/12] Default to auditing all Storage Areas. Add a Server flag to audit only areas on a specific server. --- scripts/zmaudit.pl.in | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/scripts/zmaudit.pl.in b/scripts/zmaudit.pl.in index dbe480d28..f0f534a5b 100644 --- a/scripts/zmaudit.pl.in +++ b/scripts/zmaudit.pl.in @@ -67,6 +67,7 @@ my $level = 1; my $monitor_id = 0; my $version; my $force = 0; +my $server_id = undef; my $storage_id = undef; logInit(); @@ -78,6 +79,7 @@ GetOptions( level =>\$level, 'monitor_id=i' =>\$monitor_id, report =>\$report, + 'server_id=i' =>\$server_id, 'storage_id=i' =>\$storage_id, version =>\$version ) or pod2usage(-exitstatus => -1); @@ -181,13 +183,15 @@ MAIN: while( $loop ) { Term(); } Info("Auditing Storage Area $Storage_Areas[0]{Id} $Storage_Areas[0]{Name} at $Storage_Areas[0]{Path}"); - } elsif ( $Config{ZM_SERVER_ID} ) { - @Storage_Areas = ZoneMinder::Storage->find( ServerId => $Config{ZM_SERVER_ID} ); + } elsif ( $server_id ) { + @Storage_Areas = ZoneMinder::Storage->find( ServerId => $server_id ); if ( ! @Storage_Areas ) { - Error("No Storage Area found with ServerId =" . $Config{ZM_SERVER_ID}); + Error("No Storage Area found with ServerId =" . $server_id); Term(); } - Info("Auditing All Storage Areas on Server " . $Storage_Areas[0]->Server()->Name()); + foreach my $Storage ( @Storage_Areas ) { + Info('Auditing ' . $Storage->Name() . ' at ' . $Storage->Path() . ' on ' . $Storage->Server()->Name() ); + } } else { @Storage_Areas = ZoneMinder::Storage->find(); Info("Auditing All Storage Areas"); @@ -382,7 +386,7 @@ MAIN: while( $loop ) { } # if USE_DEEP_STORAGE Debug( 'Got '.int(keys(%$fs_events))." filesystem events for monitor $monitor_dir\n" ); - delete_empty_directories($monitor_dir); + delete_empty_directories($$Storage{Path}.'/'.$monitor_dir); } # end foreach monitor if ( $cleaned ) { From 0ee261fae3217cd9bd8a570046f1707452f395ce Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Mon, 10 Sep 2018 15:11:41 -0400 Subject: [PATCH 02/12] get rid of code that hid the close/back button on events if there was no history. --- web/skins/classic/views/js/event.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/web/skins/classic/views/js/event.js b/web/skins/classic/views/js/event.js index 86989cbf6..59dd5052a 100644 --- a/web/skins/classic/views/js/event.js +++ b/web/skins/classic/views/js/event.js @@ -1001,9 +1001,6 @@ function initPage() { nearEventsQuery(eventData.Id); initialAlarmCues(eventData.Id); //call ajax+renderAlarmCues if (scale == "auto") changeScale(); - if (window.history.length == 1) { - $j('#closeWindow').html(''); - } } // Kick everything off From 8608fc97bec048d6847d0710410a12fb3f79adac Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Mon, 10 Sep 2018 15:11:57 -0400 Subject: [PATCH 03/12] fix trms=>terms --- web/skins/classic/views/js/watch.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/web/skins/classic/views/js/watch.js b/web/skins/classic/views/js/watch.js index 7e8f868b3..a1d5b5f29 100644 --- a/web/skins/classic/views/js/watch.js +++ b/web/skins/classic/views/js/watch.js @@ -493,11 +493,11 @@ function getEventCmdResponse( respObj, respText ) { var cells = row.getElements( 'td' ); - var link = new Element( 'a', { 'href': '#', 'events': { 'click': createEventPopup.pass( [ event.Id, '&trms=1&attr1=MonitorId&op1=%3d&val1='+monitorId+'&page=1&popup=1', event.Width, event.Height ] ) } }); + var link = new Element( 'a', { 'href': '#', 'events': { 'click': createEventPopup.pass( [ event.Id, '&terms=1&attr1=MonitorId&op1=%3d&val1='+monitorId+'&page=1&popup=1', event.Width, event.Height ] ) } }); link.set( 'text', event.Id ); link.inject( row.getElement( 'td.colId' ) ); - link = new Element( 'a', { 'href': '#', 'events': { 'click': createEventPopup.pass( [ event.Id, '&trms=1&attr1=MonitorId&op1=%3d&val1='+monitorId+'&page=1&popup=1', event.Width, event.Height ] ) } }); + link = new Element( 'a', { 'href': '#', 'events': { 'click': createEventPopup.pass( [ event.Id, '&terms=1&attr1=MonitorId&op1=%3d&val1='+monitorId+'&page=1&popup=1', event.Width, event.Height ] ) } }); link.set( 'text', event.Name ); link.inject( row.getElement( 'td.colName' ) ); From bf1fbd169c963d76b135cd48e1256bc42bf59aa7 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Mon, 10 Sep 2018 15:12:19 -0400 Subject: [PATCH 04/12] return uninformative debug statement --- src/zm_videostore.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/zm_videostore.cpp b/src/zm_videostore.cpp index f36ecc72f..7db4906ca 100644 --- a/src/zm_videostore.cpp +++ b/src/zm_videostore.cpp @@ -178,7 +178,6 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in, } Monitor::Orientation orientation = monitor->getOrientation(); - Debug(3, "Have orientation"); if (orientation) { if (orientation == Monitor::ROTATE_0) { } else if (orientation == Monitor::ROTATE_90) { From c70fb2f195712cfee74ebbfffc6da0b3c9b3fdc2 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Mon, 10 Sep 2018 17:11:16 -0400 Subject: [PATCH 05/12] When signal loss occurs, trigger an event close so that the event stops because we are no longer writing to the mp4 --- src/zm_monitor.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/zm_monitor.cpp b/src/zm_monitor.cpp index 58292ef52..b6272f421 100644 --- a/src/zm_monitor.cpp +++ b/src/zm_monitor.cpp @@ -1735,6 +1735,7 @@ bool Monitor::Analyse() { } shared_data->state = state = IDLE; last_section_mod = 0; + trigger_data->trigger_state = TRIGGER_CANCEL; } // end if ( trigger_data->trigger_state != TRIGGER_OFF ) if ( (!signal_change && signal) && (function == MODECT || function == MOCORD) ) { @@ -2388,6 +2389,9 @@ int Monitor::Capture() { if ( captureResult < 0 ) { Warning("Return from Capture (%d), signal loss", captureResult); + // Tell zma to end the event. zma will reset TRIGGER + trigger_data->trigger_state = TRIGGER_OFF; + // Unable to capture image for temporary reason // Fake a signal loss image Rgb signalcolor; From b545528bb0d2151f28527575579a8ae4b04b4dd9 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 11 Sep 2018 08:49:42 -0400 Subject: [PATCH 06/12] If DefaultVideo is set, use the passthrough mp4 instead of generating and mp4 from jpegs --- scripts/zmfilter.pl.in | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/scripts/zmfilter.pl.in b/scripts/zmfilter.pl.in index cfea3bfe4..0d76cbd97 100644 --- a/scripts/zmfilter.pl.in +++ b/scripts/zmfilter.pl.in @@ -713,13 +713,17 @@ sub substituteTags { } } # end if $first_alarm_frame - if ( $attachments_ref && $Config{ZM_OPT_FFMPEG} ) { + if ( $attachments_ref ) { if ( $text =~ s/%EV%//g ) { - my ( $format, $path ) = generateVideo($filter, $Event); - if ( !$format ) { - return undef; + if ( $$Event{DefaultVideo} ) { + push @$attachments_ref, { type=>'video/mp4', path=>join('/',$Event->Path(), $Event->DefaultVideo()) }; + } elsif ( $Config{ZM_OPT_FFMPEG} ) { + my ( $format, $path ) = generateVideo($filter, $Event); + if ( !$format ) { + return undef; + } + push( @$attachments_ref, { type=>"video/$format", path=>$path } ); } - push( @$attachments_ref, { type=>"video/$format", path=>$path } ); } if ( $text =~ s/%EVM%//g ) { my ( $format, $path ) = generateVideo($filter, $Event, 1); From cc417cf3e757cee156bf9f6cae9f7cd1b7ed6884 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 11 Sep 2018 13:19:33 -0400 Subject: [PATCH 07/12] reverse order of tests to be more efficient --- src/zm_event.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/zm_event.cpp b/src/zm_event.cpp index 713b9728d..11fff6a76 100644 --- a/src/zm_event.cpp +++ b/src/zm_event.cpp @@ -540,7 +540,7 @@ Debug(3, "Writing video"); if ( score < 0 ) score = 0; - bool db_frame = ( frame_type != BULK ) || ((frames%config.bulk_frame_interval)==0) || !frames; + bool db_frame = ( frame_type != BULK ) || (!frames) || ((frames%config.bulk_frame_interval)==0) ; if ( db_frame ) { Debug( 1, "Adding frame %d of type \"%s\" to DB", frames, Event::frame_type_names[frame_type] ); From ec6317bd66623a1e0e8a5bae6b8ecbe197802f70 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 11 Sep 2018 13:20:41 -0400 Subject: [PATCH 08/12] change how frame data is stored to be more useful, pass frame time offset to getFrame to tell ffmpeg which frame to get --- src/zm_eventstream.cpp | 69 +++++++++++++++++++++++++++++++----------- src/zm_eventstream.h | 4 +-- 2 files changed, 53 insertions(+), 20 deletions(-) diff --git a/src/zm_eventstream.cpp b/src/zm_eventstream.cpp index 2578d91d4..d853d1404 100644 --- a/src/zm_eventstream.cpp +++ b/src/zm_eventstream.cpp @@ -109,7 +109,10 @@ bool EventStream::loadInitialEventData( uint64_t init_event_id, unsigned int ini bool EventStream::loadEventData(uint64_t event_id) { static char sql[ZM_SQL_MED_BUFSIZ]; - snprintf(sql, sizeof(sql), "SELECT MonitorId, StorageId, Frames, unix_timestamp( StartTime ) AS StartTimestamp, (SELECT max(Delta)-min(Delta) FROM Frames WHERE EventId=Events.Id) AS Duration, DefaultVideo, Scheme FROM Events WHERE Id = %" PRIu64, event_id); + snprintf(sql, sizeof(sql), "SELECT MonitorId, StorageId, Frames," + " unix_timestamp( StartTime ) AS StartTimestamp," + " (SELECT max(Delta)-min(Delta) FROM Frames WHERE EventId=Events.Id) AS Duration, DefaultVideo, Scheme" + " FROM Events WHERE Id = %" PRIu64, event_id); if ( mysql_query(&dbconn, sql) ) { Error("Can't run query: %s", mysql_error(&dbconn)); @@ -161,18 +164,25 @@ bool EventStream::loadEventData(uint64_t event_id) { if ( storage_path[0] == '/' ) snprintf( event_data->path, sizeof(event_data->path), "%s/%ld/%02d/%02d/%02d/%02d/%02d/%02d", - storage_path, event_data->monitor_id, event_time->tm_year-100, event_time->tm_mon+1, event_time->tm_mday, event_time->tm_hour, event_time->tm_min, event_time->tm_sec ); + storage_path, event_data->monitor_id, + event_time->tm_year-100, event_time->tm_mon+1, event_time->tm_mday, + event_time->tm_hour, event_time->tm_min, event_time->tm_sec ); else snprintf( event_data->path, sizeof(event_data->path), "%s/%s/%ld/%02d/%02d/%02d/%02d/%02d/%02d", - staticConfig.PATH_WEB.c_str(), storage_path, event_data->monitor_id, event_time->tm_year-100, event_time->tm_mon+1, event_time->tm_mday, event_time->tm_hour, event_time->tm_min, event_time->tm_sec ); + staticConfig.PATH_WEB.c_str(), storage_path, event_data->monitor_id, + event_time->tm_year-100, event_time->tm_mon+1, event_time->tm_mday, + event_time->tm_hour, event_time->tm_min, event_time->tm_sec ); } else if ( event_data->scheme == Storage::MEDIUM ) { struct tm *event_time = localtime( &event_data->start_time ); if ( storage_path[0] == '/' ) snprintf( event_data->path, sizeof(event_data->path), "%s/%ld/%04d-%02d-%02d/%" PRIu64, - storage_path, event_data->monitor_id, event_time->tm_year+1900, event_time->tm_mon+1, event_time->tm_mday, event_data->event_id ); + storage_path, event_data->monitor_id, + event_time->tm_year+1900, event_time->tm_mon+1, event_time->tm_mday, + event_data->event_id ); else snprintf( event_data->path, sizeof(event_data->path), "%s/%s/%ld/%04d-%02d-%02d/%" PRIu64, - staticConfig.PATH_WEB.c_str(), storage_path, event_data->monitor_id, event_time->tm_year+1900, event_time->tm_mon+1, event_time->tm_mday, + staticConfig.PATH_WEB.c_str(), storage_path, event_data->monitor_id, + event_time->tm_year+1900, event_time->tm_mon+1, event_time->tm_mday, event_data->event_id ); } else { @@ -186,8 +196,9 @@ bool EventStream::loadEventData(uint64_t event_id) { delete storage; storage = NULL; updateFrameRate( (double)event_data->frame_count/event_data->duration ); + Debug(3,"fps set by frame_count(%d)/duration(%f)", event_data->frame_count, event_data->duration); - snprintf(sql, sizeof(sql), "SELECT FrameId, unix_timestamp( `TimeStamp` ), Delta FROM Frames where EventId = %" PRIu64 " ORDER BY FrameId ASC", event_id); + snprintf(sql, sizeof(sql), "SELECT FrameId, unix_timestamp(`TimeStamp`), Delta FROM Frames WHERE EventId = %" PRIu64 " ORDER BY FrameId ASC", event_id); if ( mysql_query(&dbconn, sql) ) { Error("Can't run query: %s", mysql_error(&dbconn)); exit(mysql_errno(&dbconn)); @@ -203,29 +214,46 @@ bool EventStream::loadEventData(uint64_t event_id) { event_data->frames = new FrameData[event_data->frame_count]; int last_id = 0; - time_t timestamp, last_timestamp = event_data->start_time; + double last_timestamp = event_data->start_time; double last_delta = 0.0; + while ( ( dbrow = mysql_fetch_row( result ) ) ) { int id = atoi(dbrow[0]); - timestamp = atoi(dbrow[1]); + //timestamp = atof(dbrow[1]); double delta = atof(dbrow[2]); int id_diff = id - last_id; - double frame_delta = id_diff ? (delta-last_delta)/id_diff : 0; + double frame_delta = id_diff ? (delta-last_delta)/id_diff : (delta - last_delta); + // Fill in data between bulk frames if ( id_diff > 1 ) { for ( int i = last_id+1; i < id; i++ ) { - event_data->frames[i-1].timestamp = (time_t)(last_timestamp + ((i-last_id)*frame_delta)); - event_data->frames[i-1].offset = (time_t)(event_data->frames[i-1].timestamp-event_data->start_time); + // Delta is the time since last frame, no since beginning of Event event_data->frames[i-1].delta = frame_delta; + event_data->frames[i-1].timestamp = last_timestamp + ((i-last_id)*frame_delta); + event_data->frames[i-1].offset = event_data->frames[i-1].timestamp - event_data->start_time; event_data->frames[i-1].in_db = false; + Debug(4,"Frame %d timestamp:(%f), offset(%f) delta(%f), in_db(%d)", + i, + event_data->frames[i-1].timestamp, + event_data->frames[i-1].offset, + event_data->frames[i-1].delta, + event_data->frames[i-1].in_db + ); } } - event_data->frames[id-1].timestamp = timestamp; - event_data->frames[id-1].offset = (time_t)(event_data->frames[id-1].timestamp-event_data->start_time); - event_data->frames[id-1].delta = id>1?frame_delta:0.0; + event_data->frames[id-1].timestamp = event_data->start_time + delta; + event_data->frames[id-1].offset = delta; + event_data->frames[id-1].delta = frame_delta; event_data->frames[id-1].in_db = true; last_id = id; last_delta = delta; - last_timestamp = timestamp; + last_timestamp = event_data->frames[id-1].timestamp; + Debug(4,"Frame %d timestamp:(%f), offset(%f) delta(%f), in_db(%d)", + id, + event_data->frames[id-1].timestamp, + event_data->frames[id-1].offset, + event_data->frames[id-1].delta, + event_data->frames[id-1].in_db + ); } if ( mysql_errno( &dbconn ) ) { Error( "Can't fetch row: %s", mysql_error( &dbconn ) ); @@ -636,7 +664,8 @@ Debug(1, "Loading image"); } else if ( ffmpeg_input ) { // Get the frame from the mp4 input Debug(1,"Getting frame from ffmpeg"); - AVFrame *frame = ffmpeg_input->get_frame( ffmpeg_input->get_video_stream_id() ); + FrameData *frame_data = &event_data->frames[curr_frame_id-1]; + AVFrame *frame = ffmpeg_input->get_frame( ffmpeg_input->get_video_stream_id(), frame_data->offset ); if ( frame ) { image = new Image(frame); av_frame_free(&frame); @@ -797,12 +826,16 @@ void EventStream::runStream() { } // Figure out if we should send this frame - +Debug(3,"cur_frame_id (%d-1) mod frame_mod(%d)",curr_frame_id, frame_mod); // If we are streaming and this frame is due to be sent - if ( ((curr_frame_id-1)%frame_mod) == 0 ) { + // frame mod defaults to 1 and if we are going faster than max_fps will get multiplied by 2 + // so if it is 2, then we send every other frame, if is it 4 then every fourth frame, etc. + if ( (frame_mod == 1) || (((curr_frame_id-1)%frame_mod) == 0) ) { delta_us = (unsigned int)(frame_data->delta * 1000000); + Debug(3,"frame delta %u ", delta_us); // if effective > base we should speed up frame delivery delta_us = (unsigned int)((delta_us * base_fps)/effective_fps); + Debug(3,"delta %u = base_fps(%f)/effective fps(%f)", delta_us, base_fps, effective_fps); // but must not exceed maxfps delta_us = max(delta_us, 1000000 / maxfps); send_frame = true; diff --git a/src/zm_eventstream.h b/src/zm_eventstream.h index 067661937..b3a776b6c 100644 --- a/src/zm_eventstream.h +++ b/src/zm_eventstream.h @@ -47,8 +47,8 @@ class EventStream : public StreamBase { protected: struct FrameData { //unsigned long id; - time_t timestamp; - time_t offset; + double timestamp; + double offset; double delta; bool in_db; }; From 0efc45fa93e43dc3d0d1c624492b6539597542c2 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 11 Sep 2018 13:21:12 -0400 Subject: [PATCH 09/12] implement a getFrame function that takes a timestamp and will seek to the appropriate time in the mp4 before getting a frame --- src/zm_ffmpeg_input.cpp | 20 ++++++++++++++++++-- src/zm_ffmpeg_input.h | 1 + 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/src/zm_ffmpeg_input.cpp b/src/zm_ffmpeg_input.cpp index c7b60cd7b..2f719af2f 100644 --- a/src/zm_ffmpeg_input.cpp +++ b/src/zm_ffmpeg_input.cpp @@ -119,8 +119,9 @@ AVFrame *FFmpeg_Input::get_frame( int stream_id ) { Error( "Unable to read packet from stream %d: error %d \"%s\".", packet.stream_index, ret, errbuf ); return NULL; } + dumpPacket(&packet, "Received packet"); - if ( (stream_id < 0 ) || ( packet.stream_index == stream_id ) ) { + if ( (stream_id < 0) || (packet.stream_index == stream_id) ) { Debug(3,"Packet is for our stream (%d)", packet.stream_index ); AVCodecContext *context = streams[packet.stream_index].context; @@ -154,7 +155,7 @@ AVFrame *FFmpeg_Input::get_frame( int stream_id ) { } } else { #endif - Debug(1,"Getting a frame?"); + Debug(1,"Getting frame %d", streams[packet.stream_index].frame_count); ret = avcodec_receive_frame( context, frame ); if ( ret < 0 ) { av_strerror( ret, errbuf, AV_ERROR_MAX_STRING_SIZE ); @@ -185,3 +186,18 @@ AVFrame *FFmpeg_Input::get_frame( int stream_id ) { return frame; } // end AVFrame *FFmpeg_Input::get_frame + +AVFrame *FFmpeg_Input::get_frame( int stream_id, double at ) { + Debug(1, "Getting frame from stream %d at %f", stream_id, at); + + int64_t seek_target = (int64_t)at * AV_TIME_BASE; + seek_target = av_rescale_q(seek_target, AV_TIME_BASE_Q, input_format_context->streams[stream_id]->time_base); + + int ret; + if ( ( ret = av_seek_frame(input_format_context, stream_id, seek_target, 0/*FORWARDS*/) < 0 ) ) { + Error("Unable to seek in stream"); + return NULL; + } + return get_frame(stream_id); + +} // end AVFrame *FFmpeg_Input::get_frame( int stream_id, struct timeval at) diff --git a/src/zm_ffmpeg_input.h b/src/zm_ffmpeg_input.h index 727fc110a..ba03fad52 100644 --- a/src/zm_ffmpeg_input.h +++ b/src/zm_ffmpeg_input.h @@ -22,6 +22,7 @@ class FFmpeg_Input { int Open( const char *filename ); int Close(); AVFrame *get_frame( int stream_id=-1 ); + AVFrame *get_frame( int stream_id, double at ); int get_video_stream_id() { return video_stream_id; } From e98603885d662e2fccebbff808b6f927d0d5e4db Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 11 Sep 2018 13:21:42 -0400 Subject: [PATCH 10/12] Show # of frames, not the # of frames decoded already --- src/zm_ffmpeg.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/zm_ffmpeg.cpp b/src/zm_ffmpeg.cpp index ac841f27b..e498def2b 100644 --- a/src/zm_ffmpeg.cpp +++ b/src/zm_ffmpeg.cpp @@ -276,7 +276,7 @@ void zm_dump_stream_format(AVFormatContext *ic, int i, int index, int is_output) Debug(1, "[0x%x]", st->id); if (lang) Debug(1, "(%s)", lang->value); - Debug(1, ", frames:%d, timebase: %d/%d", st->codec_info_nb_frames, st->time_base.num, st->time_base.den); + Debug(1, ", frames:%d, timebase: %d/%d", st->nb_frames, st->time_base.num, st->time_base.den); avcodec_string(buf, sizeof(buf), st->codec, is_output); Debug(1, ": %s", buf); #if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0) From b3ef347fd59f69c54be8d033e1d357ab004ff252 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 11 Sep 2018 13:22:01 -0400 Subject: [PATCH 11/12] slight optimisations in frame skipping --- src/zm_monitor.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/zm_monitor.cpp b/src/zm_monitor.cpp index b6272f421..63fd58d3e 100644 --- a/src/zm_monitor.cpp +++ b/src/zm_monitor.cpp @@ -1395,7 +1395,7 @@ bool Monitor::Analyse() { } else if ( signal && Active() && (function == MODECT || function == MOCORD) ) { Event::StringSet zoneSet; int motion_score = last_motion_score; - if ( !(image_count % (motion_frame_skip+1) ) ) { + if ( (!motion_frame_skip) || !(image_count % (motion_frame_skip+1) ) ) { // Get new score. motion_score = DetectMotion(*snap_image, zoneSet); @@ -1718,7 +1718,7 @@ bool Monitor::Analyse() { //Warning("In state TAPE, //video_store_data->recording = event->StartTime(); //} - if ( !(image_count%(frame_skip+1)) ) { + if ( (!frame_skip) || !(image_count%(frame_skip+1)) ) { if ( config.bulk_frame_interval > 1 ) { event->AddFrame( snap_image, *timestamp, (event->Frames() Date: Tue, 11 Sep 2018 13:22:35 -0400 Subject: [PATCH 12/12] improve debug message --- src/zm_stream.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/zm_stream.cpp b/src/zm_stream.cpp index f911f2c78..3464d8aea 100644 --- a/src/zm_stream.cpp +++ b/src/zm_stream.cpp @@ -64,7 +64,7 @@ void StreamBase::updateFrameRate(double fps) { base_fps = fps; effective_fps = (base_fps*abs(replay_rate))/ZM_RATE_BASE; frame_mod = 1; - Debug(3, "FPS:%.2f, MXFPS:%.2f, BFPS:%.2f, EFPS:%.2f, FM:%d", fps, maxfps, base_fps, effective_fps, frame_mod); + Debug(3, "FPS:%.2f, MaxFPS:%.2f, BaseFPS:%.2f, EffectiveFPS:%.2f, FrameMod:%d", fps, maxfps, base_fps, effective_fps, frame_mod); // Min frame repeat? while( effective_fps > maxfps ) { effective_fps /= 2.0;