From ab9081e1bf71ea224b8ad6683a0dcb797a718afd Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 5 Dec 2018 13:18:21 -0500 Subject: [PATCH] create a simple Frame class. Add a queue of Frames to the Event. When we get 10 of them write them out to the db. --- src/CMakeLists.txt | 2 +- src/zm_event.cpp | 62 +++++++++++++++++++++++++++++++++------------- src/zm_event.h | 7 +++++- src/zm_frame.cpp | 18 ++++++++++++++ src/zm_frame.h | 54 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 124 insertions(+), 19 deletions(-) create mode 100644 src/zm_frame.cpp create mode 100644 src/zm_frame.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index a87abe955..61dfb024a 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -4,7 +4,7 @@ configure_file(zm_config.h.in "${CMAKE_CURRENT_BINARY_DIR}/zm_config.h" @ONLY) # Group together all the source files that are used by all the binaries (zmc, zma, zmu, zms etc) -set(ZM_BIN_SRC_FILES zm_box.cpp zm_buffer.cpp zm_camera.cpp zm_comms.cpp zm_config.cpp zm_coord.cpp zm_curl_camera.cpp zm.cpp zm_db.cpp zm_logger.cpp zm_event.cpp zm_eventstream.cpp zm_exception.cpp zm_file_camera.cpp zm_ffmpeg_input.cpp zm_ffmpeg_camera.cpp zm_group.cpp zm_image.cpp zm_jpeg.cpp zm_libvlc_camera.cpp zm_local_camera.cpp zm_monitor.cpp zm_monitorstream.cpp zm_ffmpeg.cpp zm_mpeg.cpp zm_packet.cpp zm_packetqueue.cpp zm_poly.cpp zm_regexp.cpp zm_remote_camera.cpp zm_remote_camera_http.cpp zm_remote_camera_nvsocket.cpp zm_remote_camera_rtsp.cpp zm_rtp.cpp zm_rtp_ctrl.cpp zm_rtp_data.cpp zm_rtp_source.cpp zm_rtsp.cpp zm_rtsp_auth.cpp zm_sdp.cpp zm_signal.cpp zm_stream.cpp zm_swscale.cpp zm_thread.cpp zm_time.cpp zm_timer.cpp zm_user.cpp zm_utils.cpp zm_video.cpp zm_videostore.cpp zm_zone.cpp zm_storage.cpp) +set(ZM_BIN_SRC_FILES zm_box.cpp zm_buffer.cpp zm_camera.cpp zm_comms.cpp zm_config.cpp zm_coord.cpp zm_curl_camera.cpp zm.cpp zm_db.cpp zm_logger.cpp zm_event.cpp zm_frame.cpp zm_eventstream.cpp zm_exception.cpp zm_file_camera.cpp zm_ffmpeg_input.cpp zm_ffmpeg_camera.cpp zm_group.cpp zm_image.cpp zm_jpeg.cpp zm_libvlc_camera.cpp zm_local_camera.cpp zm_monitor.cpp zm_monitorstream.cpp zm_ffmpeg.cpp zm_mpeg.cpp zm_packet.cpp zm_packetqueue.cpp zm_poly.cpp zm_regexp.cpp zm_remote_camera.cpp zm_remote_camera_http.cpp zm_remote_camera_nvsocket.cpp zm_remote_camera_rtsp.cpp zm_rtp.cpp zm_rtp_ctrl.cpp zm_rtp_data.cpp zm_rtp_source.cpp zm_rtsp.cpp zm_rtsp_auth.cpp zm_sdp.cpp zm_signal.cpp zm_stream.cpp zm_swscale.cpp zm_thread.cpp zm_time.cpp zm_timer.cpp zm_user.cpp zm_utils.cpp zm_video.cpp zm_videostore.cpp zm_zone.cpp zm_storage.cpp) # A fix for cmake recompiling the source files for every target. add_library(zm STATIC ${ZM_BIN_SRC_FILES}) diff --git a/src/zm_event.cpp b/src/zm_event.cpp index fbf5cf848..6da57c29e 100644 --- a/src/zm_event.cpp +++ b/src/zm_event.cpp @@ -238,6 +238,9 @@ Event::~Event() { videowriter = NULL; } + if ( frame_data.size() ) + WriteDbFrames(); + // Should not be static because we are multi-threaded char sql[ZM_SQL_MED_BUFSIZ]; struct DeltaTimeval delta_time; @@ -260,7 +263,11 @@ Event::~Event() { snprintf(sql, sizeof(sql), "UPDATE Events SET Name='%s %" PRIu64 "', EndTime = from_unixtime( %ld ), Length = %s%ld.%02ld, Frames = %d, AlarmFrames = %d, TotScore = %d, AvgScore = %d, MaxScore = %d, DefaultVideo = '%s' WHERE Id = %" PRIu64, - monitor->EventPrefix(), id, end_time.tv_sec, delta_time.positive?"":"-", delta_time.sec, delta_time.fsec, frames, alarm_frames, tot_score, (int)(alarm_frames?(tot_score/alarm_frames):0), max_score, video_name, id ); + monitor->EventPrefix(), id, end_time.tv_sec, + delta_time.positive?"":"-", delta_time.sec, delta_time.fsec, + frames, alarm_frames, + tot_score, (int)(alarm_frames?(tot_score/alarm_frames):0), max_score, + video_name, id ); db_mutex.lock(); while ( mysql_query(&dbconn, sql) && !zm_terminate ) { Error("Can't update event: %s reason: %s", sql, mysql_error(&dbconn)); @@ -376,7 +383,7 @@ void Event::updateNotes( const StringSetMap &newNoteSetMap ) { createNotes( notes ); Debug( 2, "Updating notes for event %d, '%s'", id, notes.c_str() ); - static char sql[ZM_SQL_MED_BUFSIZ]; + static char sql[ZM_SQL_LGE_BUFSIZ]; #if USE_PREPARED_SQL static MYSQL_STMT *stmt = 0; @@ -504,6 +511,35 @@ void Event::AddFramesInternal( int n_frames, int start_frame, Image **images, st } } +void Event::WriteDbFrames() { + static char sql[ZM_SQL_LGE_BUFSIZ]; + char * sql_ptr = (char *)&sql; + sql_ptr += snprintf(sql, sizeof(sql), + "INSERT INTO Frames ( EventId, FrameId, Type, TimeStamp, Delta, Score ) VALUES " + ); + while ( frame_data.size() ) { + Frame *frame = frame_data.front(); + frame_data.pop(); + sql_ptr += snprintf(sql_ptr, sizeof(sql)-(sql_ptr-(char *)&sql), "( %" PRIu64 ", %d, '%s', from_unixtime( %ld ), %s%ld.%02ld, %d ), ", + id, frame->frame_id, frame_type_names[frame->type], + frame->timestamp.tv_sec, + frame->delta.positive?"":"-", + frame->delta.sec, + frame->delta.fsec, + frame->score); + delete frame; + } + *(sql_ptr-2) = '\0'; + db_mutex.lock(); + if ( mysql_query(&dbconn, sql) ) { + Error("Can't insert frames: %s", mysql_error(&dbconn)); + Error("SQL was %s", sql); + db_mutex.unlock(); + return; + } + db_mutex.unlock(); +} + void Event::AddFrame(Image *image, struct timeval timestamp, int score, Image *alarm_image) { if ( !timestamp.tv_sec ) { Debug(1, "Not adding new frame, zero timestamp"); @@ -543,22 +579,14 @@ Debug(3, "Writing video"); 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] ); static char sql[ZM_SQL_MED_BUFSIZ]; - snprintf(sql, sizeof(sql), - "INSERT INTO Frames ( EventId, FrameId, Type, TimeStamp, Delta, Score )" - " VALUES ( %" PRIu64 ", %d, '%s', from_unixtime( %ld ), %s%ld.%02ld, %d )", - id, frames, frame_type_names[frame_type], timestamp.tv_sec, delta_time.positive?"":"-", delta_time.sec, delta_time.fsec, score); - db_mutex.lock(); - if ( mysql_query(&dbconn, sql) ) { - Error("Can't insert frame: %s", mysql_error(&dbconn)); - Error("SQL was %s", sql); - db_mutex.unlock(); - return; + + frame_data.push( new Frame(id, frames, frame_type, timestamp, delta_time, score ) ); + if ( frame_data.size() > 10 ) { + WriteDbFrames(); + Debug(1, "Adding 10 frames to DB"); + last_db_frame = frames; } - db_mutex.unlock(); - last_db_frame = frames; // We are writing a Bulk frame if ( frame_type == BULK ) { @@ -581,7 +609,7 @@ Debug(3, "Writing video"); db_mutex.lock(); } db_mutex.unlock(); - } + } // end if frame_type == BULK } // end if db_frame end_time = timestamp; diff --git a/src/zm_event.h b/src/zm_event.h index 1e55ae593..39319e6c7 100644 --- a/src/zm_event.h +++ b/src/zm_event.h @@ -33,6 +33,7 @@ #include #include +#include #include "zm.h" #include "zm_image.h" @@ -45,7 +46,10 @@ class Monitor; class EventStream; #define MAX_PRE_ALARM_FRAMES 16 // Maximum number of prealarm frames that can be stored +typedef uint64_t event_id_t; + typedef enum { NORMAL=0, BULK, ALARM } FrameType; +#include "zm_frame.h" // // Class describing events, i.e. captured periods of activity. // @@ -60,7 +64,6 @@ class Event { typedef std::map StringSetMap; protected: - typedef enum { NORMAL=0, BULK, ALARM } FrameType; static const char * frame_type_names[3]; struct PreAlarmData { @@ -69,6 +72,7 @@ class Event { unsigned int score; Image *alarm_frame; }; + std::queue frame_data; static int pre_alarm_count; static PreAlarmData pre_alarm_data[MAX_PRE_ALARM_FRAMES]; @@ -124,6 +128,7 @@ class Event { private: void AddFramesInternal( int n_frames, int start_frame, Image **images, struct timeval **timestamps ); + void WriteDbFrames(); public: static const char *getSubPath( struct tm *time ) { diff --git a/src/zm_frame.cpp b/src/zm_frame.cpp new file mode 100644 index 000000000..bf47bdbf5 --- /dev/null +++ b/src/zm_frame.cpp @@ -0,0 +1,18 @@ +#include "zm_frame.h" + +Frame::Frame( + event_id_t p_event_id, + int p_frame_id, + FrameType p_type, + struct timeval p_timestamp, + struct DeltaTimeval p_delta, + int p_score + ) : + event_id(p_event_id), + frame_id(p_frame_id), + type(p_type), + timestamp(p_timestamp), + delta(p_delta), + score(p_score) +{ +} diff --git a/src/zm_frame.h b/src/zm_frame.h new file mode 100644 index 000000000..84190e779 --- /dev/null +++ b/src/zm_frame.h @@ -0,0 +1,54 @@ +// +// ZoneMinder Frame Class Interfaces, $Date$, $Revision$ +// Copyright (C) 2001-2008 Philip Coombes +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// + +#ifndef ZM_FRAME_H +#define ZM_FRAME_H + +#include +#include +class Frame; + +#include "zm_event.h" +#include "zm_time.h" + +// +// This describes a frame record +// +class Frame { + +public: + Frame( + event_id_t p_event_id, + int p_frame_id, + FrameType p_type, + struct timeval p_timestamp, + struct DeltaTimeval p_delta, + int p_score + ); + + event_id_t event_id; + int frame_id; + FrameType type; + struct timeval timestamp; + struct DeltaTimeval delta; + int score; + +}; + +#endif // ZM_FRAME_H