EventStream: Finalize conversion of internals to std::chrono

This commit is contained in:
Peter Keresztes Schmidt 2021-06-12 21:35:06 +02:00
parent e1fe53338c
commit b2ee71c96e
2 changed files with 157 additions and 118 deletions

View File

@ -27,7 +27,6 @@
#include "zm_storage.h" #include "zm_storage.h"
#include <arpa/inet.h> #include <arpa/inet.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <unistd.h>
#ifdef __FreeBSD__ #ifdef __FreeBSD__
#include <netinet/in.h> #include <netinet/in.h>
@ -40,7 +39,9 @@ const std::string EventStream::StreamMode_Strings[4] = {
"Gapless" "Gapless"
}; };
bool EventStream::loadInitialEventData(int monitor_id, time_t event_time) { constexpr Milliseconds EventStream::STREAM_PAUSE_WAIT;
bool EventStream::loadInitialEventData(int monitor_id, SystemTimePoint event_time) {
std::string sql = stringtf("SELECT `Id` FROM `Events` WHERE " std::string sql = stringtf("SELECT `Id` FROM `Events` WHERE "
"`MonitorId` = %d AND unix_timestamp(`EndDateTime`) > %ld " "`MonitorId` = %d AND unix_timestamp(`EndDateTime`) > %ld "
"ORDER BY `Id` ASC LIMIT 1", monitor_id, event_time); "ORDER BY `Id` ASC LIMIT 1", monitor_id, event_time);
@ -62,23 +63,26 @@ bool EventStream::loadInitialEventData(int monitor_id, time_t event_time) {
loadEventData(init_event_id); loadEventData(init_event_id);
if ( event_time ) { if (event_time.time_since_epoch() == Seconds(0)) {
curr_stream_time = event_time; curr_stream_time = event_time;
curr_frame_id = 1; // curr_frame_id is 1-based curr_frame_id = 1; // curr_frame_id is 1-based
if ( event_time >= event_data->start_time ) { if (event_time >= event_data->start_time) {
Debug(2, "event time is after event start"); Debug(2, "event time is after event start");
for ( unsigned int i = 0; i < event_data->frame_count; i++ ) { for (unsigned int i = 0; i < event_data->frame_count; i++) {
//Info( "eft %d > et %d", event_data->frames[i].timestamp, event_time ); //Info( "eft %d > et %d", event_data->frames[i].timestamp, event_time );
if ( event_data->frames[i].timestamp >= event_time ) { if (event_data->frames[i].timestamp >= event_time) {
curr_frame_id = i+1; curr_frame_id = i + 1;
Debug(3, "Set curr_stream_time:%.2f, curr_frame_id:%ld", curr_stream_time, curr_frame_id); Debug(3, "Set curr_stream_time: %.2f, curr_frame_id: %ld",
FPSeconds(curr_stream_time.time_since_epoch()).count(),
curr_frame_id);
break; break;
} }
} // end foreach frame } // end foreach frame
Debug(3, "Skipping %ld frames", event_data->frame_count); Debug(3, "Skipping %ld frames", event_data->frame_count);
} else { } else {
Warning("Requested an event time less than the start of the event. event_time %" PRIi64 " < start_time %" PRIi64, Warning("Requested an event time less than the start of the event. event_time %" PRIi64 " < start_time %" PRIi64,
static_cast<int64>(event_time), static_cast<int64>(event_data->start_time)); static_cast<int64>(std::chrono::duration_cast<Seconds>(event_time.time_since_epoch()).count()),
static_cast<int64>(std::chrono::duration_cast<Seconds>(event_data->start_time.time_since_epoch()).count()));
} }
} // end if have a start time } // end if have a start time
return true; return true;
@ -136,11 +140,12 @@ bool EventStream::loadEventData(uint64_t event_id) {
event_data->monitor_id = atoi(dbrow[0]); event_data->monitor_id = atoi(dbrow[0]);
event_data->storage_id = dbrow[1] ? atoi(dbrow[1]) : 0; event_data->storage_id = dbrow[1] ? atoi(dbrow[1]) : 0;
event_data->frame_count = dbrow[2] == nullptr ? 0 : atoi(dbrow[2]); event_data->frame_count = dbrow[2] == nullptr ? 0 : atoi(dbrow[2]);
event_data->start_time = atoi(dbrow[3]); event_data->start_time = SystemTimePoint(Seconds(atoi(dbrow[3])));
event_data->end_time = dbrow[4] ? atoi(dbrow[4]) : 0; event_data->end_time = dbrow[4] ? SystemTimePoint(Seconds(atoi(dbrow[4]))) : SystemTimePoint();
event_data->duration = event_data->end_time - event_data->start_time; event_data->duration = std::chrono::duration_cast<Microseconds>(event_data->end_time - event_data->start_time);
event_data->frames_duration = dbrow[5] ? atof(dbrow[5]) : 0.0; event_data->frames_duration =
strncpy(event_data->video_file, dbrow[6], sizeof(event_data->video_file)-1); std::chrono::duration_cast<Microseconds>(dbrow[5] ? FPSeconds(atof(dbrow[5])) : FPSeconds(0.0));
strncpy(event_data->video_file, dbrow[6], sizeof(event_data->video_file) - 1);
std::string scheme_str = std::string(dbrow[7]); std::string scheme_str = std::string(dbrow[7]);
if ( scheme_str == "Deep" ) { if ( scheme_str == "Deep" ) {
event_data->scheme = Storage::DEEP; event_data->scheme = Storage::DEEP;
@ -172,7 +177,8 @@ bool EventStream::loadEventData(uint64_t event_id) {
if ( event_data->scheme == Storage::DEEP ) { if ( event_data->scheme == Storage::DEEP ) {
tm event_time = {}; tm event_time = {};
localtime_r(&event_data->start_time, &event_time); time_t start_time_t = std::chrono::system_clock::to_time_t(event_data->start_time);
localtime_r(&start_time_t, &event_time);
if ( storage_path[0] == '/' ) if ( storage_path[0] == '/' )
snprintf(event_data->path, sizeof(event_data->path), snprintf(event_data->path, sizeof(event_data->path),
@ -188,7 +194,9 @@ bool EventStream::loadEventData(uint64_t event_id) {
event_time.tm_hour, event_time.tm_min, event_time.tm_sec); event_time.tm_hour, event_time.tm_min, event_time.tm_sec);
} else if ( event_data->scheme == Storage::MEDIUM ) { } else if ( event_data->scheme == Storage::MEDIUM ) {
tm event_time = {}; tm event_time = {};
localtime_r(&event_data->start_time, &event_time); time_t start_time_t = std::chrono::system_clock::to_time_t(event_data->start_time);
localtime_r(&start_time_t, &event_time);
if ( storage_path[0] == '/' ) if ( storage_path[0] == '/' )
snprintf(event_data->path, sizeof(event_data->path), snprintf(event_data->path, sizeof(event_data->path),
"%s/%u/%04d-%02d-%02d/%" PRIu64, "%s/%u/%04d-%02d-%02d/%" PRIu64,
@ -212,7 +220,11 @@ bool EventStream::loadEventData(uint64_t event_id) {
event_data->event_id); event_data->event_id);
} }
updateFrameRate((event_data->frame_count and event_data->duration) ? (double)event_data->frame_count/event_data->duration : 1); double fps = 1.0;
if ((event_data->frame_count and event_data->duration != Seconds(0))) {
fps = static_cast<double>(event_data->frame_count) / FPSeconds(event_data->duration).count();
}
updateFrameRate(fps);
sql = stringtf("SELECT `FrameId`, unix_timestamp(`TimeStamp`), `Delta` " sql = stringtf("SELECT `FrameId`, unix_timestamp(`TimeStamp`), `Delta` "
"FROM `Frames` WHERE `EventId` = %" PRIu64 " ORDER BY `FrameId` ASC", event_id); "FROM `Frames` WHERE `EventId` = %" PRIu64 " ORDER BY `FrameId` ASC", event_id);
@ -226,46 +238,47 @@ bool EventStream::loadEventData(uint64_t event_id) {
event_data->frames = new FrameData[event_data->frame_count]; event_data->frames = new FrameData[event_data->frame_count];
int last_id = 0; int last_id = 0;
double last_timestamp = event_data->start_time; SystemTimePoint last_timestamp = event_data->start_time;
double last_delta = 0.0; Microseconds last_delta = Seconds(0);
while ( ( dbrow = mysql_fetch_row(result) ) ) { while ( ( dbrow = mysql_fetch_row(result) ) ) {
int id = atoi(dbrow[0]); int id = atoi(dbrow[0]);
//timestamp = atof(dbrow[1]); //timestamp = atof(dbrow[1]);
double delta = atof(dbrow[2]); Microseconds delta = std::chrono::duration_cast<Microseconds>(FPSeconds(atof(dbrow[2])));
int id_diff = id - last_id; int id_diff = id - last_id;
double frame_delta = id_diff ? (delta-last_delta)/id_diff : (delta-last_delta); Microseconds frame_delta =
std::chrono::duration_cast<Microseconds>(id_diff ? (delta - last_delta) / id_diff : (delta - last_delta));
// Fill in data between bulk frames // Fill in data between bulk frames
if ( id_diff > 1 ) { if (id_diff > 1) {
for ( int i = last_id+1; i < id; i++ ) { for (int i = last_id + 1; i < id; i++) {
// Delta is the time since last frame, no since beginning of Event // 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].delta = frame_delta;
event_data->frames[i-1].timestamp = last_timestamp + ((i-last_id)*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].offset =
event_data->frames[i-1].in_db = false; std::chrono::duration_cast<Microseconds>(event_data->frames[i - 1].timestamp - event_data->start_time);
Debug(3, "Frame %d timestamp:(%f), offset(%f) delta(%f), in_db(%d)", event_data->frames[i - 1].in_db = false;
i, Debug(3, "Frame %d timestamp (%f s), offset (%f s) delta (%f s), in_db (%d)",
event_data->frames[i-1].timestamp, i,
event_data->frames[i-1].offset, FPSeconds(event_data->frames[i - 1].timestamp.time_since_epoch()).count(),
event_data->frames[i-1].delta, FPSeconds(event_data->frames[i - 1].offset).count(),
event_data->frames[i-1].in_db FPSeconds(event_data->frames[i - 1].delta).count(),
); event_data->frames[i - 1].in_db);
} }
} }
event_data->frames[id-1].timestamp = event_data->start_time + delta; event_data->frames[id - 1].timestamp = event_data->start_time + delta;
event_data->frames[id-1].offset = delta; event_data->frames[id - 1].offset = delta;
event_data->frames[id-1].delta = frame_delta; event_data->frames[id - 1].delta = frame_delta;
event_data->frames[id-1].in_db = true; event_data->frames[id - 1].in_db = true;
last_id = id; last_id = id;
last_delta = delta; last_delta = delta;
last_timestamp = event_data->frames[id-1].timestamp; last_timestamp = event_data->frames[id-1].timestamp;
Debug(3, "Frame %d timestamp:(%f), offset(%f) delta(%f), in_db(%d)", Debug(3, "Frame %d timestamp (%f s), offset (%f s), delta(%f s), in_db(%d)",
id, id,
event_data->frames[id-1].timestamp, FPSeconds(event_data->frames[id - 1].timestamp.time_since_epoch()).count(),
event_data->frames[id-1].offset, FPSeconds(event_data->frames[id - 1].offset).count(),
event_data->frames[id-1].delta, FPSeconds(event_data->frames[id - 1].delta).count(),
event_data->frames[id-1].in_db event_data->frames[id - 1].in_db);
);
} }
// Incomplete events might not have any frame data // Incomplete events might not have any frame data
event_data->last_frame_id = last_id; event_data->last_frame_id = last_id;
@ -300,8 +313,12 @@ bool EventStream::loadEventData(uint64_t event_id) {
else else
curr_stream_time = event_data->frames[event_data->last_frame_id-1].timestamp; curr_stream_time = event_data->frames[event_data->last_frame_id-1].timestamp;
} }
Debug(2, "Event:%" PRIu64 ", Frames:%ld, Last Frame ID(%ld, Duration: %.2f Frames Duration: %.2f", Debug(2, "Event: %" PRIu64 ", Frames: %ld, Last Frame ID (%ld, Duration: %.2f s Frames Duration: %.2f s",
event_data->event_id, event_data->frame_count, event_data->last_frame_id, event_data->duration, event_data->frames_duration); event_data->event_id,
event_data->frame_count,
event_data->last_frame_id,
FPSeconds(event_data->duration).count(),
FPSeconds(event_data->frames_duration).count());
return true; return true;
} // bool EventStream::loadEventData( int event_id ) } // bool EventStream::loadEventData( int event_id )
@ -503,25 +520,25 @@ void EventStream::processCommand(const CmdMsg *msg) {
break; break;
case CMD_SEEK : case CMD_SEEK :
{ {
// offset is in seconds double int_part = ((unsigned char) msg->msg_data[1] << 24) | ((unsigned char) msg->msg_data[2] << 16)
| ((unsigned char) msg->msg_data[3] << 8) | (unsigned char) msg->msg_data[4];
double dec_part = ((unsigned char) msg->msg_data[5] << 24) | ((unsigned char) msg->msg_data[6] << 16)
| ((unsigned char) msg->msg_data[7] << 8) | (unsigned char) msg->msg_data[8];
int int_part = ((unsigned char)msg->msg_data[1]<<24)|((unsigned char)msg->msg_data[2]<<16)|((unsigned char)msg->msg_data[3]<<8)|(unsigned char)msg->msg_data[4]; FPSeconds offset = FPSeconds(int_part + dec_part / 1000000.0);
int dec_part = ((unsigned char)msg->msg_data[5]<<24)|((unsigned char)msg->msg_data[6]<<16)|((unsigned char)msg->msg_data[7]<<8)|(unsigned char)msg->msg_data[8]; if (offset < Seconds(0)) {
double offset = (double)int_part + (double)(dec_part / (double)1000000);
if ( offset < 0.0 ) {
Warning("Invalid offset, not seeking"); Warning("Invalid offset, not seeking");
break; break;
} }
// This should get us close, but not all frames will have the same duration // This should get us close, but not all frames will have the same duration
curr_frame_id = (int)(event_data->frame_count*offset/event_data->duration)+1; curr_frame_id = (int) (event_data->frame_count * offset / event_data->duration) + 1;
if ( event_data->frames[curr_frame_id-1].offset > offset ) { if (event_data->frames[curr_frame_id - 1].offset > offset) {
while ( (curr_frame_id --) && ( event_data->frames[curr_frame_id-1].offset > offset ) ) { while ((curr_frame_id--) && (event_data->frames[curr_frame_id - 1].offset > offset)) {}
} } else if (event_data->frames[curr_frame_id - 1].offset < offset) {
} else if ( event_data->frames[curr_frame_id-1].offset < offset ) { while ((curr_frame_id++) && (event_data->frames[curr_frame_id - 1].offset > offset)) {}
while ( (curr_frame_id ++) && ( event_data->frames[curr_frame_id-1].offset > offset ) ) {
}
} }
if ( curr_frame_id < 1 ) { if ( curr_frame_id < 1 ) {
curr_frame_id = 1; curr_frame_id = 1;
} else if ( (unsigned long)curr_frame_id > event_data->last_frame_id ) { } else if ( (unsigned long)curr_frame_id > event_data->last_frame_id ) {
@ -529,8 +546,10 @@ void EventStream::processCommand(const CmdMsg *msg) {
} }
curr_stream_time = event_data->frames[curr_frame_id-1].timestamp; curr_stream_time = event_data->frames[curr_frame_id-1].timestamp;
Debug(1, "Got SEEK command, to %f (new current frame id: %ld offset %f)", Debug(1, "Got SEEK command, to %f s (new current frame id: %ld offset %f s)",
offset, curr_frame_id, event_data->frames[curr_frame_id-1].offset); FPSeconds(offset).count(),
curr_frame_id,
FPSeconds(event_data->frames[curr_frame_id - 1].offset).count());
send_frame = true; send_frame = true;
break; break;
} }
@ -547,12 +566,12 @@ void EventStream::processCommand(const CmdMsg *msg) {
struct { struct {
uint64_t event_id; uint64_t event_id;
double duration; Microseconds duration;
double progress; Microseconds progress;
int rate; int rate;
int zoom; int zoom;
bool paused; bool paused;
} status_data; } status_data = {};
status_data.event_id = event_data->event_id; status_data.event_id = event_data->event_id;
status_data.duration = event_data->duration; status_data.duration = event_data->duration;
@ -561,13 +580,12 @@ void EventStream::processCommand(const CmdMsg *msg) {
status_data.zoom = zoom; status_data.zoom = zoom;
status_data.paused = paused; status_data.paused = paused;
Debug(2, "Event:%" PRIu64 ", Duration %f, Paused:%d, progress:%f Rate:%d, Zoom:%d", Debug(2, "Event:%" PRIu64 ", Duration %f, Paused:%d, progress:%f Rate:%d, Zoom:%d",
status_data.event_id, status_data.event_id,
status_data.duration, FPSeconds(status_data.duration).count(),
status_data.paused, status_data.paused,
status_data.progress, FPSeconds(status_data.progress).count(),
status_data.rate, status_data.rate,
status_data.zoom status_data.zoom);
);
DataMsg status_msg; DataMsg status_msg;
status_msg.msg_type = MSG_DATA_EVENT; status_msg.msg_type = MSG_DATA_EVENT;
@ -580,11 +598,17 @@ void EventStream::processCommand(const CmdMsg *msg) {
//exit(-1); //exit(-1);
} }
} }
// quit after sending a status, if this was a quit request
if ( (MsgCommand)msg->msg_data[0] == CMD_QUIT )
exit(0);
updateFrameRate((event_data->frame_count and event_data->duration) ? (double)event_data->frame_count/event_data->duration : 1); // quit after sending a status, if this was a quit request
if (static_cast<MsgCommand>(msg->msg_data[0]) == CMD_QUIT) {
exit(0);
}
double fps = 1.0;
if ((event_data->frame_count and event_data->duration != Seconds(0))) {
fps = static_cast<double>(event_data->frame_count) / FPSeconds(event_data->duration).count();
}
updateFrameRate(fps);
} // void EventStream::processCommand(const CmdMsg *msg) } // void EventStream::processCommand(const CmdMsg *msg)
bool EventStream::checkEventLoaded() { bool EventStream::checkEventLoaded() {
@ -595,7 +619,7 @@ bool EventStream::checkEventLoaded() {
"SELECT `Id` FROM `Events` WHERE `MonitorId` = %d AND `Id` < %" PRIu64 " ORDER BY `Id` DESC LIMIT 1", "SELECT `Id` FROM `Events` WHERE `MonitorId` = %d AND `Id` < %" PRIu64 " ORDER BY `Id` DESC LIMIT 1",
event_data->monitor_id, event_data->event_id); event_data->monitor_id, event_data->event_id);
} else if ( (unsigned int)curr_frame_id > event_data->last_frame_id ) { } else if ( (unsigned int)curr_frame_id > event_data->last_frame_id ) {
if ( !event_data->end_time ) { if (event_data->end_time.time_since_epoch() == Seconds(0)) {
// We are viewing an in-process event, so just reload it. // We are viewing an in-process event, so just reload it.
loadEventData(event_data->event_id); loadEventData(event_data->event_id);
if ( (unsigned int)curr_frame_id > event_data->last_frame_id ) if ( (unsigned int)curr_frame_id > event_data->last_frame_id )
@ -732,9 +756,8 @@ bool EventStream::sendFrame(Microseconds delta_us) {
} else if ( ffmpeg_input ) { } else if ( ffmpeg_input ) {
// Get the frame from the mp4 input // Get the frame from the mp4 input
FrameData *frame_data = &event_data->frames[curr_frame_id-1]; FrameData *frame_data = &event_data->frames[curr_frame_id-1];
AVFrame *frame = ffmpeg_input->get_frame( AVFrame *frame =
ffmpeg_input->get_video_stream_id(), ffmpeg_input->get_frame(ffmpeg_input->get_video_stream_id(), FPSeconds(frame_data->offset).count());
frame_data->offset);
if ( frame ) { if ( frame ) {
image = new Image(frame); image = new Image(frame);
//av_frame_free(&frame); //av_frame_free(&frame);
@ -826,12 +849,16 @@ void EventStream::runStream() {
exit(0); exit(0);
} }
updateFrameRate((event_data->frame_count and event_data->duration) ? (double)event_data->frame_count/event_data->duration : 1); double fps = 1.0;
if ((event_data->frame_count and event_data->duration != Seconds(0))) {
fps = static_cast<double>(event_data->frame_count) / FPSeconds(event_data->duration).count();
}
updateFrameRate(fps);
start = std::chrono::system_clock::now(); start = std::chrono::system_clock::now();
uint64_t last_frame_offset = 0; SystemTimePoint::duration last_frame_offset = Seconds(0);
SystemTimePoint::duration time_to_event = Seconds(0);
double time_to_event = 0;
while ( !zm_terminate ) { while ( !zm_terminate ) {
now = std::chrono::system_clock::now(); now = std::chrono::system_clock::now();
@ -880,31 +907,39 @@ void EventStream::runStream() {
} // end if streaming stepping or doing nothing } // end if streaming stepping or doing nothing
// time_to_event > 0 means that we are not in the event // time_to_event > 0 means that we are not in the event
if ( ( time_to_event > 0 ) and ( mode == MODE_ALL ) ) { if (time_to_event > Seconds(0) and mode == MODE_ALL) {
auto time_since_last_send = now - last_frame_sent; SystemTimePoint::duration time_since_last_send = now - last_frame_sent;
Debug(1, "Time since last send = %.2f s", FPSeconds(time_since_last_send).count()); Debug(1, "Time since last send = %.2f s", FPSeconds(time_since_last_send).count());
if (time_since_last_send > Seconds(1)) { if (time_since_last_send > Seconds(1)) {
char frame_text[64]; char frame_text[64];
snprintf(frame_text, sizeof(frame_text), "Time to %s event = %d seconds", snprintf(frame_text, sizeof(frame_text), "Time to %s event = %f s",
(replay_rate > 0 ? "next" : "previous" ), (int)time_to_event); (replay_rate > 0 ? "next" : "previous"),
if ( !sendTextFrame(frame_text) ) FPSeconds(time_to_event).count());
if (!sendTextFrame(frame_text)) {
zm_terminate = true; zm_terminate = true;
}
send_frame = false; // In case keepalive was set send_frame = false; // In case keepalive was set
} }
// FIXME ICON But we are not paused. We are somehow still in the event? // FIXME ICON But we are not paused. We are somehow still in the event?
double sleep_time = (replay_rate>0?1:-1) * ((1.0L * replay_rate * STREAM_PAUSE_WAIT)/(ZM_RATE_BASE * 1000000)); Milliseconds sleep_time = std::chrono::duration_cast<Milliseconds>(
(replay_rate > 0 ? 1 : -1) * ((1.0L * replay_rate * STREAM_PAUSE_WAIT) / ZM_RATE_BASE));
//double sleep_time = (replay_rate * STREAM_PAUSE_WAIT)/(ZM_RATE_BASE * 1000000); //double sleep_time = (replay_rate * STREAM_PAUSE_WAIT)/(ZM_RATE_BASE * 1000000);
//// ZM_RATE_BASE == 100, and 1x replay_rate is 100 //// ZM_RATE_BASE == 100, and 1x replay_rate is 100
//double sleep_time = ((replay_rate/ZM_RATE_BASE) * STREAM_PAUSE_WAIT)/1000000; //double sleep_time = ((replay_rate/ZM_RATE_BASE) * STREAM_PAUSE_WAIT)/1000000;
if ( !sleep_time ) { if (sleep_time == Seconds(0)) {
sleep_time += STREAM_PAUSE_WAIT/1000000; sleep_time += STREAM_PAUSE_WAIT;
} }
curr_stream_time += sleep_time; curr_stream_time += sleep_time;
time_to_event -= sleep_time; time_to_event -= sleep_time;
Debug(2, "Sleeping (%dus) because we are not at the next event yet, adding %f", STREAM_PAUSE_WAIT, sleep_time); Debug(2, "Sleeping (%" PRIi64 " ms) because we are not at the next event yet, adding %" PRIi64 " ms",
usleep(STREAM_PAUSE_WAIT); static_cast<int64>(Milliseconds(STREAM_PAUSE_WAIT).count()),
static_cast<int64>(Milliseconds(sleep_time).count()));
std::this_thread::sleep_for(STREAM_PAUSE_WAIT);
//curr_stream_time += (1.0L * replay_rate * STREAM_PAUSE_WAIT)/(ZM_RATE_BASE * 1000000); //curr_stream_time += (1.0L * replay_rate * STREAM_PAUSE_WAIT)/(ZM_RATE_BASE * 1000000);
//} //}
@ -922,7 +957,7 @@ void EventStream::runStream() {
if (!paused) { if (!paused) {
// delta is since the last frame // delta is since the last frame
delta = std::chrono::duration_cast<Microseconds>(FPSeconds(frame_data->delta)); delta = std::chrono::duration_cast<Microseconds>(frame_data->delta);
Debug(3, "frame delta %" PRIi64 "us ", Debug(3, "frame delta %" PRIi64 "us ",
static_cast<int64>(std::chrono::duration_cast<Microseconds>(delta).count())); static_cast<int64>(std::chrono::duration_cast<Microseconds>(delta).count()));
@ -967,19 +1002,19 @@ void EventStream::runStream() {
// you can calculate the relationship between now and the start // you can calculate the relationship between now and the start
// or calc the relationship from the last frame. I think from the start is better as it self-corrects // or calc the relationship from the last frame. I think from the start is better as it self-corrects
// //
if ( last_frame_offset ) { if (last_frame_offset != Seconds(0)) {
// We assume that we are going forward and the next frame is in the future. // We assume that we are going forward and the next frame is in the future.
delta = std::chrono::duration_cast<Microseconds>(FPSeconds(frame_data->offset) - (now - start)); delta = std::chrono::duration_cast<Microseconds>(frame_data->offset - (now - start));
Debug(2, "New delta: now - start = %" PRIu64 " us offset %f - elapsed = %" PRIu64 " us", Debug(2, "New delta: now - start = %" PRIu64 " us offset %" PRIi64 " us- elapsed = %" PRIu64 " us",
static_cast<int64>(std::chrono::duration_cast<Microseconds>(now - start).count()), static_cast<int64>(std::chrono::duration_cast<Microseconds>(now - start).count()),
frame_data->offset * 1000000, static_cast<int64>(std::chrono::duration_cast<Microseconds>(frame_data->offset).count()),
static_cast<int64>(std::chrono::duration_cast<Microseconds>(delta).count())); static_cast<int64>(std::chrono::duration_cast<Microseconds>(delta).count()));
} else { } else {
Debug(2, "No last frame_offset, no sleep"); Debug(2, "No last frame_offset, no sleep");
delta = Seconds(0); delta = Seconds(0);
} }
last_frame_offset = frame_data->offset * 1000000; last_frame_offset = frame_data->offset;
if (send_frame && type != STREAM_MPEG) { if (send_frame && type != STREAM_MPEG) {
if (delta != Seconds(0)) { if (delta != Seconds(0)) {
@ -1030,15 +1065,19 @@ void EventStream::runStream() {
if ( replay_rate > 0 ) { if ( replay_rate > 0 ) {
// This doesn't make sense unless we have hit the end of the event. // This doesn't make sense unless we have hit the end of the event.
time_to_event = event_data->frames[0].timestamp - curr_stream_time; time_to_event = event_data->frames[0].timestamp - curr_stream_time;
Debug(1, "replay rate(%d) time_to_event(%f)=frame timestamp:%f - curr_stream_time(%f)", Debug(1, "replay rate (%d) time_to_event (%f s) = frame timestamp (%f s) - curr_stream_time (%f s)",
replay_rate, time_to_event, replay_rate,
event_data->frames[0].timestamp, FPSeconds(time_to_event).count(),
curr_stream_time); FPSeconds(event_data->frames[0].timestamp.time_since_epoch()).count(),
FPSeconds(curr_stream_time.time_since_epoch()).count());
} else if ( replay_rate < 0 ) { } else if ( replay_rate < 0 ) {
time_to_event = curr_stream_time - event_data->frames[event_data->frame_count-1].timestamp; time_to_event = curr_stream_time - event_data->frames[event_data->frame_count-1].timestamp;
Debug(1, "replay rate(%d) time_to_event(%f)=curr_stream_time(%f)-frame timestamp:%f", Debug(1, "replay rate (%d), time_to_event(%f s) = curr_stream_time (%f s) - frame timestamp (%f s)",
replay_rate, time_to_event, curr_stream_time, event_data->frames[event_data->frame_count-1].timestamp); replay_rate,
FPSeconds(time_to_event).count(),
FPSeconds(curr_stream_time.time_since_epoch()).count(),
FPSeconds(event_data->frames[event_data->frame_count - 1].timestamp.time_since_epoch()).count());
} // end if forward or reverse } // end if forward or reverse
} // end if checkEventLoaded } // end if checkEventLoaded
} // end while ! zm_terminate } // end while ! zm_terminate

View File

@ -40,10 +40,10 @@ class EventStream : public StreamBase {
protected: protected:
struct FrameData { struct FrameData {
//unsigned long id; //unsigned long id;
double timestamp; SystemTimePoint timestamp;
double offset; Microseconds offset;
double delta; Microseconds delta;
bool in_db; bool in_db;
}; };
struct EventData { struct EventData {
@ -52,10 +52,10 @@ class EventStream : public StreamBase {
unsigned long storage_id; unsigned long storage_id;
unsigned long frame_count; // Value of Frames column in Event unsigned long frame_count; // Value of Frames column in Event
unsigned long last_frame_id; // Highest frame id known about. Can be < frame_count in incomplete events unsigned long last_frame_id; // Highest frame id known about. Can be < frame_count in incomplete events
time_t start_time; SystemTimePoint start_time;
time_t end_time; SystemTimePoint end_time;
double duration; Microseconds duration;
double frames_duration; Microseconds frames_duration;
char path[PATH_MAX]; char path[PATH_MAX];
int n_frames; // # of frame rows returned from database int n_frames; // # of frame rows returned from database
FrameData *frames; FrameData *frames;
@ -66,7 +66,7 @@ class EventStream : public StreamBase {
}; };
protected: protected:
static const int STREAM_PAUSE_WAIT = 250000; // Microseconds static constexpr Milliseconds STREAM_PAUSE_WAIT = Milliseconds(250);
static const StreamMode DEFAULT_MODE = MODE_SINGLE; static const StreamMode DEFAULT_MODE = MODE_SINGLE;
@ -74,7 +74,7 @@ class EventStream : public StreamBase {
bool forceEventChange; bool forceEventChange;
long curr_frame_id; long curr_frame_id;
double curr_stream_time; SystemTimePoint curr_stream_time;
bool send_frame; bool send_frame;
SystemTimePoint start; // clock time when started the event SystemTimePoint start; // clock time when started the event
@ -83,7 +83,7 @@ class EventStream : public StreamBase {
protected: protected:
bool loadEventData(uint64_t event_id); bool loadEventData(uint64_t event_id);
bool loadInitialEventData(uint64_t init_event_id, unsigned int init_frame_id); bool loadInitialEventData(uint64_t init_event_id, unsigned int init_frame_id);
bool loadInitialEventData(int monitor_id, time_t event_time); bool loadInitialEventData(int monitor_id, SystemTimePoint event_time);
bool checkEventLoaded(); bool checkEventLoaded();
void processCommand(const CmdMsg *msg) override; void processCommand(const CmdMsg *msg) override;
@ -94,12 +94,12 @@ class EventStream : public StreamBase {
mode(DEFAULT_MODE), mode(DEFAULT_MODE),
forceEventChange(false), forceEventChange(false),
curr_frame_id(0), curr_frame_id(0),
curr_stream_time(0.0),
send_frame(false), send_frame(false),
event_data(nullptr), event_data(nullptr),
storage(nullptr), storage(nullptr),
ffmpeg_input(nullptr) ffmpeg_input(nullptr)
{} {}
~EventStream() { ~EventStream() {
if ( event_data ) { if ( event_data ) {
if ( event_data->frames ) { if ( event_data->frames ) {