From 5260563ec47dea417b4f69dca50e9eeeeebf43be Mon Sep 17 00:00:00 2001 From: Selva Nair Date: Fri, 1 Nov 2019 17:30:57 -0400 Subject: [PATCH] Update frame deltas in the database to be relative to the video start time Currenltly the frames written to database have delta time measured from the event start time. As these deltas are also used to generate any frame on the fly from the recorded video, these should be relative to the video start time. Adjust by subtracting the offset of the video start from event start. Done when the event is closed. If video is not stored, this has no effect. Signed-off-by: Selva Nair --- src/zm_event.cpp | 35 +++++++++++++++++++++++++++++++++++ src/zm_event.h | 1 + src/zm_ffmpeg_camera.cpp | 9 +++++++++ src/zm_monitor.h | 2 ++ 4 files changed, 47 insertions(+) diff --git a/src/zm_event.cpp b/src/zm_event.cpp index 109df5dd3..e564479f3 100644 --- a/src/zm_event.cpp +++ b/src/zm_event.cpp @@ -256,6 +256,20 @@ Event::~Event() { if ( frame_data.size() ) WriteDbFrames(); + // update frame deltas to refer to video start time which may be a few frames before event start + struct timeval video_offset = {0}; + struct timeval video_start_time = monitor->GetVideoWriterStartTime(); + if (video_start_time.tv_sec > 0) { + timersub(&video_start_time, &start_time, &video_offset); + Debug(1, "Updating frames delta by %d sec %d usec", + video_offset.tv_sec, video_offset.tv_usec); + UpdateFramesDelta(video_offset.tv_sec + video_offset.tv_usec*1e-6); + } + else { + Debug(3, "Video start_time %d sec %d usec not valid -- frame deltas not updated", + video_start_time.tv_sec, video_start_time.tv_usec); + } + // Should not be static because we might be multi-threaded char sql[ZM_SQL_LGE_BUFSIZ]; snprintf(sql, sizeof(sql), @@ -554,6 +568,27 @@ void Event::WriteDbFrames() { db_mutex.unlock(); } // end void Event::WriteDbFrames() +// Subtract an offset time from frames deltas to match with video start time +void Event::UpdateFramesDelta(double offset) { + char sql[ZM_SQL_MED_BUFSIZ]; + + if (offset == 0.0) return; + // the table is set to auto update timestamp so we force it to keep current value + snprintf(sql, sizeof(sql), + "UPDATE Frames SET timestamp = timestamp, Delta = Delta - (%.4f) WHERE EventId = %" PRIu64, + offset, id); + + db_mutex.lock(); + if (mysql_query(&dbconn, sql)) { + db_mutex.unlock(); + Error("Can't update frames: %s, sql was %s", mysql_error(&dbconn), sql); + return; + } + db_mutex.unlock(); + Info("Updating frames delta by %0.2f sec to match video file", offset); +} + + 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"); diff --git a/src/zm_event.h b/src/zm_event.h index 2035b6af6..77199509c 100644 --- a/src/zm_event.h +++ b/src/zm_event.h @@ -132,6 +132,7 @@ class Event { private: void AddFramesInternal( int n_frames, int start_frame, Image **images, struct timeval **timestamps ); void WriteDbFrames(); + void UpdateFramesDelta(double offset); public: static const char *getSubPath( struct tm *time ) { diff --git a/src/zm_ffmpeg_camera.cpp b/src/zm_ffmpeg_camera.cpp index 029a2de0d..ef4dfc057 100644 --- a/src/zm_ffmpeg_camera.cpp +++ b/src/zm_ffmpeg_camera.cpp @@ -872,6 +872,7 @@ int FfmpegCamera::CaptureAndRecord( // since the last keyframe. unsigned int packet_count = 0; ZMPacket *queued_packet; + struct timeval video_offset = {0}; // Clear all packets that predate the moment when the recording began packetqueue->clear_unwanted_packets( @@ -880,6 +881,14 @@ int FfmpegCamera::CaptureAndRecord( while ( (queued_packet = packetqueue->popPacket()) ) { AVPacket *avp = queued_packet->av_packet(); + // compute time offset between event start and first frame in video + if (packet_count == 0){ + monitor->SetVideoWriterStartTime(queued_packet->timestamp); + timersub(&queued_packet->timestamp, &recording, &video_offset); + Info("Event video offset is %.3f sec (<0 means video starts early)", + video_offset.tv_sec + video_offset.tv_usec*1e-6); + } + packet_count += 1; // Write the packet to our video store Debug(2, "Writing queued packet stream: %d KEY %d, remaining (%d)", diff --git a/src/zm_monitor.h b/src/zm_monitor.h index 97f173845..9109c9c72 100644 --- a/src/zm_monitor.h +++ b/src/zm_monitor.h @@ -466,6 +466,8 @@ public: const std::vector* GetOptEncoderParams() const { return &encoderparamsvec; } uint64_t GetVideoWriterEventId() const { return video_store_data->current_event; } void SetVideoWriterEventId( unsigned long long p_event_id ) { video_store_data->current_event = p_event_id; } + struct timeval GetVideoWriterStartTime() const { return video_store_data->recording; } + void SetVideoWriterStartTime(struct timeval &t) { video_store_data->recording = t; } unsigned int GetPreEventCount() const { return pre_event_count; }; struct timeval GetVideoBufferDuration() const { return video_buffer_duration; };