BaseStream: Convert internals to std::chrono

This commit is contained in:
Peter Keresztes Schmidt 2021-06-12 09:50:36 +02:00
parent 8dae46bc75
commit e1fe53338c
10 changed files with 181 additions and 168 deletions

View File

@ -578,17 +578,16 @@ void Event::AddFrame(
SystemTimePoint timestamp_us = SystemTimePoint(zm::chrono::duration_cast<Microseconds>(timestamp));
if (db_frame) {
FPSeconds delta_time = timestamp_us - start_time;
Debug(1, "Frame delta is %.2f - %.2f = %.2f, score %u zone_stats.size %zu",
std::chrono::duration_cast<FPSeconds>(timestamp_us.time_since_epoch()).count(),
std::chrono::duration_cast<FPSeconds>(start_time.time_since_epoch()).count(),
delta_time.count(),
Microseconds delta_time = std::chrono::duration_cast<Microseconds>(timestamp_us - start_time);
Debug(1, "Frame delta is %.2f s - %.2f s = %.2f s, score %u zone_stats.size %zu",
FPSeconds(timestamp_us.time_since_epoch()).count(),
FPSeconds(start_time.time_since_epoch()).count(),
FPSeconds(delta_time).count(),
score,
zone_stats.size());
Milliseconds delta_time_ms = std::chrono::duration_cast<Milliseconds>(delta_time);
// The idea is to write out 1/sec
frame_data.push(new Frame(id, frames, frame_type, timestamp, delta_time_ms, score, zone_stats));
frame_data.push(new Frame(id, frames, frame_type, timestamp, delta_time, score, zone_stats));
double fps = monitor->get_capture_fps();
if (write_to_db
or
@ -604,7 +603,7 @@ void Event::AddFrame(
std::string sql = stringtf(
"UPDATE Events SET Length = %.2f, Frames = %d, AlarmFrames = %d, TotScore = %d, AvgScore = %d, MaxScore = %d WHERE Id = %" PRIu64,
delta_time.count(),
FPSeconds(delta_time).count(),
frames,
alarm_frames,
tot_score,

View File

@ -316,7 +316,7 @@ void EventStream::processCommand(const CmdMsg *msg) {
// Set paused flag
paused = true;
replay_rate = ZM_RATE_BASE;
last_frame_sent = TV_2_FLOAT(now);
last_frame_sent = now;
break;
case CMD_PLAY :
Debug(1, "Got PLAY command");
@ -674,7 +674,7 @@ Image * EventStream::getImage( ) {
return image;
}
bool EventStream::sendFrame(int delta_us) {
bool EventStream::sendFrame(Microseconds delta_us) {
Debug(2, "Sending frame %ld", curr_frame_id);
static char filepath[PATH_MAX];
@ -710,7 +710,10 @@ bool EventStream::sendFrame(int delta_us) {
fprintf(stdout, "Content-type: %s\r\n\r\n", vid_stream->MimeType());
vid_stream->OpenStream();
}
/* double pts = */ vid_stream->EncodeFrame(send_image->Buffer(), send_image->Size(), config.mpeg_timed_frames, delta_us*1000);
vid_stream->EncodeFrame(send_image->Buffer(),
send_image->Size(),
config.mpeg_timed_frames,
delta_us.count() * 1000);
} else {
bool send_raw = (type == STREAM_JPEG) && ((scale>=ZM_SCALE_BASE)&&(zoom==ZM_SCALE_BASE)) && filepath[0];
@ -806,7 +809,7 @@ bool EventStream::sendFrame(int delta_us) {
fputs("\r\n", stdout);
fflush(stdout);
last_frame_sent = TV_2_FLOAT(now);
last_frame_sent = now;
return true;
} // bool EventStream::sendFrame( int delta_us )
@ -824,16 +827,16 @@ void EventStream::runStream() {
}
updateFrameRate((event_data->frame_count and event_data->duration) ? (double)event_data->frame_count/event_data->duration : 1);
gettimeofday(&start, nullptr);
uint64_t start_usec = start.tv_sec * 1000000 + start.tv_usec;
start = std::chrono::system_clock::now();
uint64_t last_frame_offset = 0;
double time_to_event = 0;
while ( !zm_terminate ) {
gettimeofday(&now, nullptr);
now = std::chrono::system_clock::now();
int delta_us = 0;
Microseconds delta = Microseconds(0);
send_frame = false;
if ( connkey ) {
@ -843,7 +846,7 @@ void EventStream::runStream() {
}
// Update modified time of the socket .lock file so that we can tell which ones are stale.
if ( now.tv_sec - last_comm_update.tv_sec > 3600 ) {
if (now - last_comm_update > Hours(1)) {
touch(sock_path_lock);
last_comm_update = now;
}
@ -869,8 +872,7 @@ void EventStream::runStream() {
send_frame = true;
} else if ( !send_frame ) {
// We are paused, not stepping and doing nothing, meaning that comms didn't set send_frame to true
double time_since_last_send = TV_2_FLOAT(now) - last_frame_sent;
if ( time_since_last_send > MAX_STREAM_DELAY ) {
if (now - last_frame_sent > MAX_STREAM_DELAY) {
// Send keepalive
Debug(2, "Sending keepalive frame");
send_frame = true;
@ -879,10 +881,10 @@ void EventStream::runStream() {
// time_to_event > 0 means that we are not in the event
if ( ( time_to_event > 0 ) and ( mode == MODE_ALL ) ) {
double time_since_last_send = TV_2_FLOAT(now) - last_frame_sent;
Debug(1, "Time since last send = %f = %f - %f", time_since_last_send, TV_2_FLOAT(now), last_frame_sent);
if ( time_since_last_send > 1 /* second */ ) {
static char frame_text[64];
auto time_since_last_send = now - last_frame_sent;
Debug(1, "Time since last send = %.2f s", FPSeconds(time_since_last_send).count());
if (time_since_last_send > Seconds(1)) {
char frame_text[64];
snprintf(frame_text, sizeof(frame_text), "Time to %s event = %d seconds",
(replay_rate > 0 ? "next" : "previous" ), (int)time_to_event);
@ -909,8 +911,8 @@ void EventStream::runStream() {
continue;
} // end if !in_event
if ( send_frame ) {
if ( !sendFrame(delta_us) ) {
if (send_frame) {
if (!sendFrame(delta)) {
zm_terminate = true;
break;
}
@ -918,23 +920,30 @@ void EventStream::runStream() {
curr_stream_time = frame_data->timestamp;
if ( !paused ) {
if (!paused) {
// delta is since the last frame
delta_us = (unsigned int)(frame_data->delta * 1000000);
Debug(3, "frame delta %uus ", delta_us);
delta = std::chrono::duration_cast<Microseconds>(FPSeconds(frame_data->delta));
Debug(3, "frame delta %" PRIi64 "us ",
static_cast<int64>(std::chrono::duration_cast<Microseconds>(delta).count()));
// 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);
delta = std::chrono::duration_cast<Microseconds>((delta * base_fps) / effective_fps);
Debug(3, "delta %" PRIi64 " us = base_fps (%f) / effective_fps (%f)",
static_cast<int64>(std::chrono::duration_cast<Microseconds>(delta).count()),
base_fps,
effective_fps);
// but must not exceed maxfps
delta_us = std::max(delta_us, int(1000000/maxfps));
Debug(3, "delta %u = base_fps(%f)/effective fps(%f) from 30fps", delta_us, base_fps, effective_fps);
delta = std::max(delta, Microseconds(lround(Microseconds::period::den / maxfps)));
Debug(3, "delta %" PRIi64 " us = base_fps (%f) /effective_fps (%f) from 30fps",
static_cast<int64>(std::chrono::duration_cast<Microseconds>(delta).count()),
base_fps,
effective_fps);
// +/- 1? What if we are skipping frames?
curr_frame_id += (replay_rate>0) ? frame_mod : -1*frame_mod;
// sending the frame may have taken some time, so reload now
gettimeofday(&now, nullptr);
uint64_t now_usec = (now.tv_sec * 1000000 + now.tv_usec);
now = std::chrono::system_clock::now();
// we incremented by replay_rate, so might have jumped past frame_count
if ( (mode == MODE_SINGLE) && (
@ -945,8 +954,8 @@ void EventStream::runStream() {
) {
Debug(2, "Have mode==MODE_SINGLE and at end of event, looping back to start");
curr_frame_id = 1;
// Have to reset start_usec to now when replaying
start_usec = now_usec;
// Have to reset start to now when replaying
start = now;
}
frame_data = &event_data->frames[curr_frame_id-1];
@ -960,41 +969,51 @@ void EventStream::runStream() {
//
if ( last_frame_offset ) {
// We assume that we are going forward and the next frame is in the future.
delta_us = frame_data->offset * 1000000 - (now_usec-start_usec);
// - (now_usec - start_usec);
Debug(2, "New delta_us now %" PRIu64 " - start %" PRIu64 " = %" PRIu64 " offset %f - elapsed = %dusec",
now_usec, start_usec, static_cast<uint64>(now_usec - start_usec), frame_data->offset * 1000000, delta_us);
delta = std::chrono::duration_cast<Microseconds>(FPSeconds(frame_data->offset) - (now - start));
Debug(2, "New delta: now - start = %" PRIu64 " us offset %f - elapsed = %" PRIu64 " us",
static_cast<int64>(std::chrono::duration_cast<Microseconds>(now - start).count()),
frame_data->offset * 1000000,
static_cast<int64>(std::chrono::duration_cast<Microseconds>(delta).count()));
} else {
Debug(2, "No last frame_offset, no sleep");
delta_us = 0;
delta = Seconds(0);
}
last_frame_offset = frame_data->offset * 1000000;
if ( send_frame && (type != STREAM_MPEG) ) {
if ( delta_us > 0 ) {
if ( delta_us > MAX_SLEEP_USEC ) {
Debug(1, "Limiting sleep to %d because calculated sleep is too long %d", MAX_SLEEP_USEC, delta_us);
delta_us = MAX_SLEEP_USEC;
if (send_frame && type != STREAM_MPEG) {
if (delta != Seconds(0)) {
if (delta > MAX_SLEEP) {
Debug(1, "Limiting sleep to %" PRIi64 " ms because calculated sleep is too long: %" PRIi64" us",
static_cast<int64>(std::chrono::duration_cast<Milliseconds>(MAX_SLEEP).count()),
static_cast<int64>(std::chrono::duration_cast<Microseconds>(delta).count()));
delta = MAX_SLEEP;
}
usleep(delta_us);
Debug(3, "Done sleeping: %d usec", delta_us);
std::this_thread::sleep_for(delta);
Debug(3, "Done sleeping: %" PRIi64 " us",
static_cast<int64>(std::chrono::duration_cast<Microseconds>(delta).count()));
}
}
} else {
delta_us = ((1000000 * ZM_RATE_BASE)/((base_fps?base_fps:1)*(replay_rate?abs(replay_rate*2):2)));
delta = std::chrono::duration_cast<Microseconds>(FPSeconds(
ZM_RATE_BASE / ((base_fps ? base_fps : 1) * (replay_rate ? abs(replay_rate * 2) : 2))));
Debug(2, "Sleeping %d because 1000000 * ZM_RATE_BASE(%d) / ( base_fps (%f), replay_rate(%d)",
delta_us,
ZM_RATE_BASE,
(base_fps ? base_fps : 1),
(replay_rate ? abs(replay_rate*2) : 0)
);
if ( delta_us > 0 ) {
if ( delta_us > MAX_SLEEP_USEC ) {
Debug(1, "Limiting sleep to %d because calculated sleep is too long %d", MAX_SLEEP_USEC, delta_us);
delta_us = MAX_SLEEP_USEC;
Debug(2, "Sleeping %" PRIi64 " us because ZM_RATE_BASE (%d) / ( base_fps (%f) * replay_rate (%d)",
static_cast<int64>(std::chrono::duration_cast<Microseconds>(delta).count()),
ZM_RATE_BASE,
(base_fps ? base_fps : 1),
(replay_rate ? abs(replay_rate * 2) : 0));
if (delta != Seconds(0)) {
if (delta > MAX_SLEEP) {
Debug(1, "Limiting sleep to %" PRIi64 " ms because calculated sleep is too long %" PRIi64,
static_cast<int64>(std::chrono::duration_cast<Milliseconds>(MAX_SLEEP).count()),
static_cast<int64>(std::chrono::duration_cast<Microseconds>(delta).count()));
delta = MAX_SLEEP;
}
usleep(delta_us);
std::this_thread::sleep_for(delta);
}
// We are paused, so might be stepping
//if ( step != 0 )// Adding 0 is cheaper than an if 0
@ -1036,7 +1055,7 @@ bool EventStream::send_file(const char *filepath) {
int img_buffer_size = 0;
uint8_t *img_buffer = temp_img_buffer;
FILE *fdj = NULL;
FILE *fdj = nullptr;
fdj = fopen(filepath, "rb");
if ( !fdj ) {
Error("Can't open %s: %s", filepath, strerror(errno));

View File

@ -76,7 +76,7 @@ class EventStream : public StreamBase {
long curr_frame_id;
double curr_stream_time;
bool send_frame;
struct timeval start; // clock time when started the event
SystemTimePoint start; // clock time when started the event
EventData *event_data;
@ -87,7 +87,7 @@ class EventStream : public StreamBase {
bool checkEventLoaded();
void processCommand(const CmdMsg *msg) override;
bool sendFrame(int delta_us);
bool sendFrame(Microseconds delta);
public:
EventStream() :

View File

@ -92,7 +92,7 @@ bool FifoStream::sendMJEGFrames() {
}
fprintf(stdout, "\r\n\r\n");
fflush(stdout);
last_frame_sent = TV_2_FLOAT(now);
last_frame_sent = now;
frame_count++;
return true;
}
@ -156,8 +156,9 @@ void FifoStream::runStream() {
}
while ( !zm_terminate ) {
gettimeofday(&now, nullptr);
now = std::chrono::system_clock::now();
checkCommandQueue();
if ( stream_type == MJPEG ) {
if ( !sendMJEGFrames() )
zm_terminate = true;

View File

@ -4,7 +4,7 @@ Frame::Frame(event_id_t p_event_id,
int p_frame_id,
FrameType p_type,
struct timeval p_timestamp,
Milliseconds p_delta,
Microseconds p_delta,
int p_score,
std::vector<ZoneStats> p_stats)
: event_id(p_event_id),

View File

@ -42,7 +42,7 @@ class Frame {
int p_frame_id,
FrameType p_type,
struct timeval p_timestamp,
Milliseconds p_delta,
Microseconds p_delta,
int p_score,
std::vector<ZoneStats> p_stats
);
@ -51,7 +51,7 @@ class Frame {
int frame_id;
FrameType type;
struct timeval timestamp;
Milliseconds delta;
Microseconds delta;
int score;
std::vector<ZoneStats> zone_stats;
};

View File

@ -85,7 +85,7 @@ void MonitorStream::processCommand(const CmdMsg *msg) {
Debug(1, "Got PAUSE command");
paused = true;
delayed = true;
last_frame_sent = TV_2_FLOAT(now);
last_frame_sent = now;
break;
case CMD_PLAY :
Debug(1, "Got PLAY command");
@ -280,7 +280,7 @@ void MonitorStream::processCommand(const CmdMsg *msg) {
status_data.delayed = delayed;
status_data.paused = paused;
status_data.rate = replay_rate;
status_data.delay = TV_2_FLOAT(now) - TV_2_FLOAT(last_frame_timestamp);
status_data.delay = FPSeconds(now - last_frame_timestamp).count();
status_data.zoom = zoom;
Debug(2, "fps: %.2f capture_fps: %.2f analysis_fps: %.2f Buffer Level:%d, Delayed:%d, Paused:%d, Rate:%d, delay:%.3f, Zoom:%d, Enabled:%d Forced:%d",
status_data.fps,
@ -320,7 +320,7 @@ void MonitorStream::processCommand(const CmdMsg *msg) {
//updateFrameRate(monitor->GetFPS());
} // end void MonitorStream::processCommand(const CmdMsg *msg)
bool MonitorStream::sendFrame(const char *filepath, const timeval &timestamp) {
bool MonitorStream::sendFrame(const char *filepath, SystemTimePoint timestamp) {
bool send_raw = ((scale>=ZM_SCALE_BASE)&&(zoom==ZM_SCALE_BASE));
if (
@ -350,8 +350,8 @@ bool MonitorStream::sendFrame(const char *filepath, const timeval &timestamp) {
TimePoint send_start_time = std::chrono::steady_clock::now();
if (
(0 > fprintf(stdout, "Content-Length: %d\r\nX-Timestamp: %d.%06d\r\n\r\n",
img_buffer_size, (int)timestamp.tv_sec, (int)timestamp.tv_usec))
(0 > fprintf(stdout, "Content-Length: %d\r\nX-Timestamp: %.6f\r\n\r\n",
img_buffer_size, std::chrono::duration_cast<FPSeconds>(timestamp.time_since_epoch()).count()))
||
(fwrite(img_buffer, img_buffer_size, 1, stdout) != 1)
) {
@ -363,26 +363,27 @@ bool MonitorStream::sendFrame(const char *filepath, const timeval &timestamp) {
fflush(stdout);
TimePoint send_end_time = std::chrono::steady_clock::now();
Milliseconds frame_send_time = std::chrono::duration_cast<Milliseconds>(send_end_time - send_start_time);
TimePoint::duration frame_send_time = send_end_time - send_start_time;
if (frame_send_time > Milliseconds(lround(Milliseconds::period::den / maxfps))) {
maxfps /= 2;
Info("Frame send time %" PRIi64 " msec too slow, throttling maxfps to %.2f",
static_cast<int64>(frame_send_time.count()),
Info("Frame send time %" PRIi64 " ms too slow, throttling maxfps to %.2f",
static_cast<int64>(std::chrono::duration_cast<Milliseconds>(frame_send_time).count()),
maxfps);
}
last_frame_sent = TV_2_FLOAT(now);
last_frame_sent = now;
return true;
}
return false;
} // end bool MonitorStream::sendFrame(const char *filepath, struct timeval *timestamp)
bool MonitorStream::sendFrame(Image *image, const timeval &timestamp) {
bool MonitorStream::sendFrame(Image *image, SystemTimePoint timestamp) {
Image *send_image = prepareImage(image);
if (!config.timestamp_on_capture)
monitor->TimestampImage(send_image, timestamp);
if (!config.timestamp_on_capture) {
monitor->TimestampImage(send_image, zm::chrono::duration_cast<timeval>(timestamp.time_since_epoch()));
}
fputs("--" BOUNDARY "\r\n", stdout);
if ( type == STREAM_MPEG ) {
@ -392,13 +393,11 @@ bool MonitorStream::sendFrame(Image *image, const timeval &timestamp) {
vid_stream->OpenStream();
}
static struct timeval base_time;
Milliseconds delta_time =
zm::chrono::duration_cast<Milliseconds>(timestamp) - zm::chrono::duration_cast<Milliseconds>(base_time);
static SystemTimePoint base_time;
if (!frame_count) {
base_time = timestamp;
}
SystemTimePoint::duration delta_time = timestamp - base_time;
/* double pts = */ vid_stream->EncodeFrame(send_image->Buffer(), send_image->Size(), config.mpeg_timed_frames, delta_time.count());
} else {
@ -436,8 +435,8 @@ bool MonitorStream::sendFrame(Image *image, const timeval &timestamp) {
return false;
}
if (
( 0 > fprintf(stdout, "Content-Length: %d\r\nX-Timestamp: %d.%06d\r\n\r\n",
img_buffer_size, (int)timestamp.tv_sec, (int)timestamp.tv_usec) )
(0 > fprintf(stdout, "Content-Length: %d\r\nX-Timestamp: %.6f\r\n\r\n",
img_buffer_size, std::chrono::duration_cast<FPSeconds>(timestamp.time_since_epoch()).count()))
||
(fwrite(img_buffer, img_buffer_size, 1, stdout) != 1)
) {
@ -451,16 +450,16 @@ bool MonitorStream::sendFrame(Image *image, const timeval &timestamp) {
fflush(stdout);
TimePoint send_end_time = std::chrono::steady_clock::now();
Milliseconds frame_send_time = std::chrono::duration_cast<Milliseconds>(send_end_time - send_start_time);
TimePoint::duration frame_send_time = send_end_time - send_start_time;
if (frame_send_time > Milliseconds(lround(Milliseconds::period::den / maxfps))) {
maxfps /= 1.5;
Warning("Frame send time %" PRIi64 " msec too slow, throttling maxfps to %.2f",
static_cast<int64>(frame_send_time.count()),
static_cast<int64>(std::chrono::duration_cast<Milliseconds>(frame_send_time).count()),
maxfps);
}
} // Not mpeg
last_frame_sent = TV_2_FLOAT(now);
last_frame_sent = now;
return true;
} // end bool MonitorStream::sendFrame( Image *image, const timeval &timestamp )
@ -503,8 +502,7 @@ void MonitorStream::runStream() {
// point to end which is theoretically not a valid value because all indexes are % image_buffer_count
int32_t last_read_index = monitor->image_buffer_count;
time_t stream_start_time;
time(&stream_start_time);
SystemTimePoint stream_start_time = std::chrono::system_clock::now();
frame_count = 0;
@ -518,7 +516,7 @@ void MonitorStream::runStream() {
// Last image and timestamp when paused, will be resent occasionally to prevent timeout
Image *paused_image = nullptr;
struct timeval paused_timestamp;
SystemTimePoint paused_timestamp;
if ( connkey && ( playback_buffer > 0 ) ) {
// 15 is the max length for the swap path suffix, /zmswap-whatever, assuming max 6 digits for monitor id
@ -554,7 +552,6 @@ void MonitorStream::runStream() {
} else {
Debug(2, "Assigning temporary buffer");
temp_image_buffer = new SwapImage[temp_image_buffer_count];
memset(temp_image_buffer, 0, sizeof(*temp_image_buffer)*temp_image_buffer_count);
Debug(2, "Assigned temporary buffer");
}
}
@ -575,7 +572,7 @@ void MonitorStream::runStream() {
break;
}
gettimeofday(&now, nullptr);
now = std::chrono::system_clock::now();
bool was_paused = paused;
if ( connkey ) {
@ -585,7 +582,7 @@ void MonitorStream::runStream() {
got_command = true;
}
// Update modified time of the socket .lock file so that we can tell which ones are stale.
if ( now.tv_sec - last_comm_update.tv_sec > 3600 ) {
if (now - last_comm_update > Hours(1)) {
touch(sock_path_lock);
last_comm_update = now;
}
@ -596,7 +593,7 @@ void MonitorStream::runStream() {
int index = monitor->shared_data->last_write_index % monitor->image_buffer_count;
Debug(1, "Saving paused image from index %d",index);
paused_image = new Image(*monitor->image_buffer[index]);
paused_timestamp = monitor->shared_timestamps[index];
paused_timestamp = SystemTimePoint(zm::chrono::duration_cast<Microseconds>(monitor->shared_timestamps[index]));
}
} else if ( paused_image ) {
Debug(1, "Clearing paused_image");
@ -624,55 +621,46 @@ void MonitorStream::runStream() {
delayed = true;
temp_read_index = MOD_ADD(temp_read_index, (replay_rate>=0?-1:1), temp_image_buffer_count);
} else {
// Debug( 3, "siT: %f, lfT: %f", TV_2_FLOAT( swap_image->timestamp ), TV_2_FLOAT( last_frame_timestamp ) );
double expected_delta_time = ((TV_2_FLOAT(swap_image->timestamp) - TV_2_FLOAT(last_frame_timestamp)) * ZM_RATE_BASE)/replay_rate;
double actual_delta_time = TV_2_FLOAT(now) - last_frame_sent;
FPSeconds expected_delta_time = ((FPSeconds(swap_image->timestamp - last_frame_timestamp)) * ZM_RATE_BASE) / replay_rate;
SystemTimePoint::duration actual_delta_time = now - last_frame_sent;
// Debug( 3, "eDT: %.3lf, aDT: %.3f, lFS:%.3f, NOW:%.3f", expected_delta_time, actual_delta_time, last_frame_sent, TV_2_FLOAT( now ) );
// If the next frame is due
if ( actual_delta_time > expected_delta_time ) {
if (actual_delta_time > expected_delta_time) {
// Debug( 2, "eDT: %.3lf, aDT: %.3f", expected_delta_time, actual_delta_time );
if ( temp_index%frame_mod == 0 ) {
if (temp_index % frame_mod == 0) {
Debug(2, "Sending delayed frame %d", temp_index);
// Send the next frame
if (!sendFrame(temp_image_buffer[temp_index].file_name, temp_image_buffer[temp_index].timestamp)) {
zm_terminate = true;
}
memcpy(&last_frame_timestamp, &(swap_image->timestamp), sizeof(last_frame_timestamp));
last_frame_timestamp = swap_image->timestamp;
// frame_sent = true;
}
temp_read_index = MOD_ADD(temp_read_index, (replay_rate>0?1:-1), temp_image_buffer_count);
temp_read_index = MOD_ADD(temp_read_index, (replay_rate > 0 ? 1 : -1), temp_image_buffer_count);
}
}
} else if ( step != 0 ) {
} else if (step != 0) {
temp_read_index = MOD_ADD(temp_read_index, (step>0?1:-1), temp_image_buffer_count);
SwapImage *swap_image = &temp_image_buffer[temp_read_index];
// Send the next frame
if ( !sendFrame(
temp_image_buffer[temp_read_index].file_name,
temp_image_buffer[temp_read_index].timestamp
) ) {
if (!sendFrame(temp_image_buffer[temp_read_index].file_name, temp_image_buffer[temp_read_index].timestamp)) {
zm_terminate = true;
}
memcpy(
&last_frame_timestamp,
&(swap_image->timestamp),
sizeof(last_frame_timestamp)
);
last_frame_timestamp = swap_image->timestamp;
// frame_sent = true;
step = 0;
} else {
//paused?
int temp_index = MOD_ADD(temp_read_index, 0, temp_image_buffer_count);
double actual_delta_time = TV_2_FLOAT(now) - last_frame_sent;
if ( got_command || (actual_delta_time > 5) ) {
if (got_command || (now - last_frame_sent > Seconds(5))) {
// Send keepalive
Debug(2, "Sending keepalive frame %d", temp_index);
// Send the next frame
if ( !sendFrame(temp_image_buffer[temp_index].file_name, temp_image_buffer[temp_index].timestamp) ) {
if (!sendFrame(temp_image_buffer[temp_index].file_name, temp_image_buffer[temp_index].timestamp)) {
zm_terminate = true;
}
// frame_sent = true;
@ -702,20 +690,21 @@ void MonitorStream::runStream() {
// Send the next frame
//
// Perhaps we should use NOW instead.
last_frame_timestamp = monitor->shared_timestamps[index];
last_frame_timestamp =
SystemTimePoint(zm::chrono::duration_cast<Microseconds>(monitor->shared_timestamps[index]));
Image *image = monitor->image_buffer[index];
if ( !sendFrame(image, last_frame_timestamp) ) {
if (!sendFrame(image, last_frame_timestamp)) {
Debug(2, "sendFrame failed, quiting.");
zm_terminate = true;
break;
}
//frame_sent = true;
//
if ( frame_count == 0 ) {
if (frame_count == 0) {
// Chrome will not display the first frame until it receives another.
// Firefox is fine. So just send the first frame twice.
if ( !sendFrame(image, last_frame_timestamp) ) {
if (!sendFrame(image, last_frame_timestamp)) {
Debug(2, "sendFrame failed, quiting.");
zm_terminate = true;
break;
@ -735,12 +724,12 @@ void MonitorStream::runStream() {
if (!sendFrame(paused_image, paused_timestamp))
zm_terminate = true;
} else {
double actual_delta_time = TV_2_FLOAT(now) - last_frame_sent;
if ( actual_delta_time > 5 ) {
if ( paused_image ) {
SystemTimePoint::duration actual_delta_time = now - last_frame_sent;
if (actual_delta_time > Seconds(5)) {
if (paused_image) {
// Send keepalive
Debug(2, "Sending keepalive frame because delta time %.2f > 5",
actual_delta_time);
Debug(2, "Sending keepalive frame because delta time %.2f s > 5 s",
FPSeconds(actual_delta_time).count());
// Send the next frame
if (!sendFrame(paused_image, paused_timestamp))
zm_terminate = true;
@ -766,7 +755,9 @@ void MonitorStream::runStream() {
temp_index);
temp_image_buffer[temp_index].valid = true;
}
temp_image_buffer[temp_index].timestamp = monitor->shared_timestamps[index];
temp_image_buffer[temp_index].timestamp =
SystemTimePoint(zm::chrono::duration_cast<Microseconds>(monitor->shared_timestamps[index]));
monitor->image_buffer[index]->WriteJpeg(
temp_image_buffer[temp_index].file_name,
config.jpeg_file_quality
@ -791,27 +782,29 @@ void MonitorStream::runStream() {
Debug(3, "Waiting for capture last_write_index=%u", monitor->shared_data->last_write_index);
} // end if ( (unsigned int)last_read_index != monitor->shared_data->last_write_index )
unsigned long sleep_time = (unsigned long)((1000000 * ZM_RATE_BASE)/((base_fps?base_fps:1)*abs(replay_rate*2)));
if ( sleep_time > MonitorStream::MAX_SLEEP_USEC ) {
FPSeconds sleep_time =
FPSeconds(ZM_RATE_BASE / ((base_fps ? base_fps : 1) * (replay_rate ? abs(replay_rate * 2) : 2)));
if (sleep_time > MonitorStream::MAX_SLEEP) {
// Shouldn't sleep for long because we need to check command queue, etc.
sleep_time = MonitorStream::MAX_SLEEP_USEC;
Debug(3, "Sleeping for MAX_SLEEP_USEC %luus", sleep_time);
sleep_time = MonitorStream::MAX_SLEEP;
Debug(3, "Sleeping for MAX_SLEEP_USEC %" PRIi64 " us",
static_cast<int64>(std::chrono::duration_cast<Microseconds>(sleep_time).count()));
} else {
Debug(3, "Sleeping for %luus", sleep_time);
Debug(3, "Sleeping for %" PRIi64 " us",
static_cast<int64>(std::chrono::duration_cast<Microseconds>(sleep_time).count()));
}
usleep(sleep_time);
if ( ttl ) {
if ( (now.tv_sec - stream_start_time) > ttl ) {
Debug(2, "now(%" PRIi64 ") - start(%" PRIi64 " ) > ttl(%" PRIi64 ") break",
static_cast<int64>(now.tv_sec),
static_cast<int64>(stream_start_time),
static_cast<int64>(ttl));
break;
}
std::this_thread::sleep_for(sleep_time);
if (ttl > Seconds(0) && (now - stream_start_time) > ttl) {
Debug(2, "now - start > ttl (%" PRIi64 " us). break",
static_cast<int64>(std::chrono::duration_cast<Microseconds>(ttl).count()));
break;
}
if ( !last_frame_sent ) {
if (last_frame_sent.time_since_epoch() == Seconds(0)) {
// If we didn't capture above, because frame_mod was bad? Then last_frame_sent will not have a value.
last_frame_sent = now.tv_sec;
last_frame_sent = now;
Warning("no last_frame_sent. Shouldn't happen. frame_mod was (%d) frame_count (%d)",
frame_mod, frame_count);
}

View File

@ -25,11 +25,11 @@
class MonitorStream : public StreamBase {
protected:
typedef struct SwapImage {
bool valid;
struct timeval timestamp;
char file_name[PATH_MAX];
} SwapImage;
struct SwapImage {
bool valid = false;
SystemTimePoint timestamp;
char file_name[PATH_MAX] = "";
};
private:
SwapImage *temp_image_buffer;
@ -38,15 +38,15 @@ class MonitorStream : public StreamBase {
int temp_write_index;
protected:
time_t ttl;
Microseconds ttl;
int playback_buffer;
bool delayed;
int frame_count;
protected:
bool checkSwapPath(const char *path, bool create_path);
bool sendFrame(const char *filepath, const timeval &timestamp);
bool sendFrame(Image *image, const timeval &timestamp);
bool sendFrame(const char *filepath, SystemTimePoint timestamp);
bool sendFrame(Image *image, SystemTimePoint timestamp);
void processCommand(const CmdMsg *msg) override;
void SingleImage(int scale=100);
void SingleImageRaw(int scale=100);
@ -55,7 +55,7 @@ class MonitorStream : public StreamBase {
#endif
public:
MonitorStream() :
MonitorStream() :
temp_image_buffer(nullptr),
temp_image_buffer_count(0),
temp_read_index(0),
@ -63,13 +63,13 @@ class MonitorStream : public StreamBase {
ttl(0),
playback_buffer(0),
delayed(false),
frame_count(0) {
}
frame_count(0) {}
void setStreamBuffer(int p_playback_buffer) {
playback_buffer = p_playback_buffer;
}
void setStreamTTL(time_t p_ttl) {
ttl = p_ttl;
ttl = Seconds(p_ttl);
}
bool setStreamStart(int monitor_id) {
return loadMonitor(monitor_id);

View File

@ -27,6 +27,9 @@
#include <sys/stat.h>
#include <unistd.h>
constexpr Seconds StreamBase::MAX_STREAM_DELAY;
constexpr Milliseconds StreamBase::MAX_SLEEP;
StreamBase::~StreamBase() {
if (vid_stream) {
delete vid_stream;
@ -283,7 +286,7 @@ bool StreamBase::sendTextFrame(const char *frame_text) {
fputs("\r\n\r\n", stdout);
fflush(stdout);
}
last_frame_sent = TV_2_FLOAT(now);
last_frame_sent = now;
return true;
}
@ -368,7 +371,7 @@ void StreamBase::openComms() {
strncpy(rem_addr.sun_path, rem_sock_path, sizeof(rem_addr.sun_path));
rem_addr.sun_family = AF_UNIX;
gettimeofday(&last_comm_update, nullptr);
last_comm_update = std::chrono::system_clock::now();
} // end if connKey > 0
Debug(3, "comms open at %s", loc_sock_path);
} // end void StreamBase::openComms()

View File

@ -22,13 +22,13 @@
#include "zm_logger.h"
#include "zm_mpeg.h"
#include "zm_time.h"
#include <memory>
#include <sys/un.h>
class Image;
class Monitor;
#define TV_2_FLOAT( tv ) ( double((tv).tv_sec) + (double((tv).tv_usec) / 1000000.0) )
#define BOUNDARY "ZoneMinderFrame"
class StreamBase {
@ -42,8 +42,8 @@ public:
} StreamType;
protected:
static const int MAX_STREAM_DELAY = 5; // Seconds
static const int MAX_SLEEP_USEC = 500000; // .5 Seconds
static constexpr Seconds MAX_STREAM_DELAY = Seconds(5);
static constexpr Milliseconds MAX_SLEEP = Milliseconds(500);
static const StreamType DEFAULT_TYPE = STREAM_JPEG;
enum { DEFAULT_RATE=ZM_RATE_BASE };
@ -119,15 +119,15 @@ protected:
bool paused;
int step;
struct timeval now;
struct timeval last_comm_update;
SystemTimePoint now;
SystemTimePoint last_comm_update;
double base_fps;
double effective_fps;
int frame_mod;
double last_frame_sent;
struct timeval last_frame_timestamp;
SystemTimePoint last_frame_sent;
SystemTimePoint last_frame_timestamp;
VideoStream *vid_stream;
@ -176,9 +176,7 @@ public:
effective_fps = 0.0;
frame_mod = 1;
vid_stream = 0;
last_frame_sent = 0.0;
last_frame_timestamp = {};
vid_stream = nullptr;
msg = { 0, { 0 } };
}
virtual ~StreamBase();