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 <selva.nair@gmail.com>
This commit is contained in:
Selva Nair 2019-11-01 17:30:57 -04:00
parent dd31279ca3
commit 5260563ec4
4 changed files with 47 additions and 0 deletions

View File

@ -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");

View File

@ -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 ) {

View File

@ -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)",

View File

@ -466,6 +466,8 @@ public:
const std::vector<EncoderParameter_t>* 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; };